예제 #1
0
파일: amq.c 프로젝트: nugins99/amq
amqd_t amq_open(const char *name, int oflags, aemode_t mode, struct amq_attr * attr) {
    struct impl_t * q;
    q = find_queue(name);

    // create new queue if not found 
    if (q == NULL) {
        if (oflags & O_CREAT) { 
            q = (struct impl_t*) malloc(sizeof(struct impl_t));
            if (q == NULL) {
                return -1;
            }
            q->name = (char*) malloc(strlen(name) +1); 
            strcpy(q->name, name);
            q->next = NULL;
            q->prev = NULL;
            q->use_count = 1; 
            /* allocate mem for temp buffer */
            q->tmp= (struct data_t*)  malloc(attr->mq_msgsize + sizeof(size_t)); 
            pthread_mutex_init(&q->mutex, 0);
            pthread_cond_init(&q->cond,0);

            cb_init(&q->cb,attr->mq_maxmsg, attr->mq_msgsize + sizeof(size_t) );
            // insert new queue at front 
            q->next = queues; 
            queues = q; 
        } else {
            errno = ENOENT; 
            return -1; 
        }
    } else {
        q->use_count++; 
    }
    return (amqd_t) q; 
}
예제 #2
0
파일: amq.c 프로젝트: nugins99/amq
amqd_t amq_unlink(const char * name) {
    amqd_t q = find_queue(name);
    if (q) {
        return amq_close(q);
    } else {
        errno =  ENOENT; 
        return -1; 
    }
}
예제 #3
0
파일: amq.c 프로젝트: nugins99/amq
/** Open a message queue with a name  */
amqd_t amqd_open(const char *name, int oflag) {
    struct impl_t * q;
    q = find_queue(name);
    if (q == NULL) {
        return -1; 
    } else {
        q->use_count++; 
        return (amqd_t) q; 
    }
}
예제 #4
0
파일: em_menu.c 프로젝트: Exim/exim
static void editsenderAction(Widget w, XtPointer client_data,
  XtPointer call_data)
{
queue_item *q;
uschar *sender;
w = w;      /* Keep picky compilers happy */
call_data = call_data;
Ustrncpy(actioned_message, client_data, 24);
actioned_message[23] = '\0';
q = find_queue(actioned_message, queue_noop, 0);
sender = !q ? US"" : q->sender[0] == 0 ? US"<>" : q->sender;
action_required = US"-Mes";
dialog_ref_widget = menushell;
create_dialog(US"New sender address?", sender);
}
예제 #5
0
/**
 * runs the current request through the queues
 * \param	forced_pipe	is >= 0 if a specific pipe should be used, < 0 otherwise
 * \return -1 if drop needed, 1 if allowed
 */
static int rl_check(struct sip_msg * msg, int forced_pipe)
{
	int que_id, pipe_id, ret;
	str method = msg->first_line.u.request.method;

	LOCK_GET(rl_lock);
	if (forced_pipe < 0) {
		if (find_queue(msg, &que_id)) {
			pipe_id = que_id = 0;
			ret = 1;
			goto out_release;
		}
		pipe_id = *queues[que_id].pipe;
	} else {
		que_id = 0; 
		pipe_id = forced_pipe;
	}

	ret = pipe_push(msg, pipe_id);
out_release:
	LOCK_RELEASE(rl_lock);

	/* no locks here because it's only read and pipes[pipe_id] is always alloc'ed */
	LOG(L_DBG,
			"meth=%.*s queue=%d pipe=%d algo=%d limit=%d pkg_load=%d counter=%d "
			"load=%2.1lf => %s\n",
			method.len,
			method.s, 
			que_id, 
			pipe_id,
			*pipes[pipe_id].algo,
			*pipes[pipe_id].limit,
			*pipes[pipe_id].load,
			*pipes[pipe_id].counter, 
			*load_value,
			(ret == 1) ? "ACCEPT" : "DROP");
	
	return ret;
}
예제 #6
0
파일: ratelimit.c 프로젝트: mtulio/mtulio
/**     
 * runs the current request through the queues
 * \param       forced_pipe     is >= 0 if a specific pipe should be used, < 0 otherwise
 * \return	-1 if drop needed, 1 if allowed
 */
static int rl_check(struct sip_msg * msg, int forced_pipe)
{
	int que_id, pipe_id, ret;
	str method = msg->first_line.u.request.method;

	if (forced_pipe >=0 && (forced_pipe>=MAX_PIPES || *pipes[forced_pipe].algo==PIPE_ALGO_NOP)) {
		LM_ERR("forced pipe %d out of range or not defined "
			" => defaulting to method type checking\n", forced_pipe);
		forced_pipe = -1;
	}

	LOCK_GET(rl_lock);
	if (forced_pipe < 0) { 
		if (find_queue(msg, &que_id)) {
			pipe_id = que_id = 0;
			ret = 1;
			goto out_release;
		}
		pipe_id = *queues[que_id].pipe;
	} else {
		que_id = 0;
		pipe_id = forced_pipe;
	}

	ret = pipe_push(msg, pipe_id);
out_release:
	LOCK_RELEASE(rl_lock);

	/* no locks here because it's only read and pipes[pipe_id] is always alloc'ed */
	LM_DBG("meth=%.*s queue=%d pipe=%d algo=%d limit=%d pkg_load=%d counter=%d "
		"load=%2.1lf network_load=%d => %s\n",
		method.len, method.s, que_id, pipe_id,
		*pipes[pipe_id].algo, *pipes[pipe_id].limit,
		*pipes[pipe_id].load, *pipes[pipe_id].counter,
		*load_value, *network_load_value, (ret == 1) ? "ACCEPT" : "DROP");

	return ret;
}
예제 #7
0
파일: em_log.c 프로젝트: fanf2/exim
void read_log(void)
{
struct stat statdata;
uschar buffer[log_buffer_len];

/* If log is not yet open, skip all of this. */

if (LOG != NULL)
  {
  fseek(LOG, log_position, SEEK_SET);

  while (Ufgets(buffer, log_buffer_len, LOG) != NULL)
    {
    uschar *id;
    uschar *p = buffer;
    void *reset_point;
    int length = Ustrlen(buffer);
    int i;

    /* Skip totally blank lines (paranoia: there shouldn't be any) */

    while (*p == ' ' || *p == '\t') p++;
    if (*p == '\n') continue;

    /* We should now have a complete log entry in the buffer; check
    it for various regular expression matches and take appropriate
    action. Get the current store point so we can reset to it. */

    reset_point = store_get(0);

    /* First, update any stripchart data values, noting that the zeroth
    stripchart is the queue length, which is handled elsewhere, and the
    1st may the a size monitor. */

    for (i = stripchart_varstart; i < stripchart_number; i++)
      {
      if (pcre_exec(stripchart_regex[i], NULL, CS buffer, length, 0, PCRE_EOPT,
            NULL, 0) >= 0)
        stripchart_total[i]++;
      }

    /* Munge the log entry and display shortened form on one line.
    We omit the date and show only the time. Remove any time zone offset.
    Take note of the presence of [pid]. */

    if (pcre_exec(yyyymmdd_regex,NULL,CS buffer,length,0,PCRE_EOPT,NULL,0) >= 0)
      {
      int pidlength = 0;
      if ((buffer[20] == '+' || buffer[20] == '-') &&
          isdigit(buffer[21]) && buffer[25] == ' ')
        memmove(buffer + 20, buffer + 26, Ustrlen(buffer + 26) + 1);
      if (buffer[20] == '[')
        {
        while (Ustrchr("[]0123456789", buffer[20+pidlength++]) != NULL);
        }
      id = string_copyn(buffer + 20 + pidlength, MESSAGE_ID_LENGTH);
      show_log("%s", buffer+11);
      }
    else
      {
      id = US"";
      show_log("%s", buffer);
      }

    /* Deal with frozen and unfrozen messages */

    if (strstric(buffer, US"frozen", FALSE) != NULL)
      {
      queue_item *qq = find_queue(id, queue_noop, 0);
      if (qq != NULL)
        {
        if (strstric(buffer, US"unfrozen", FALSE) != NULL)
          qq->frozen = FALSE;
        else qq->frozen = TRUE;
        }
      }

    /* Notice defer messages, and add the destination if it
    isn't already on the list for this message, with a pointer
    to the parent if we can. */

    if ((p = Ustrstr(buffer, "==")) != NULL)
      {
      queue_item *qq = find_queue(id, queue_noop, 0);
      if (qq != NULL)
        {
        dest_item *d;
        uschar *q, *r;
        p += 2;
        while (isspace(*p)) p++;
        q = p;
        while (*p != 0 && !isspace(*p))
          {
          if (*p++ != '\"') continue;
          while (*p != 0)
            {
            if (*p == '\\') p += 2;
              else if (*p++ == '\"') break;
            }
          }
        *p++ = 0;
        if ((r = strstric(q, qualify_domain, FALSE)) != NULL &&
          *(--r) == '@') *r = 0;

        /* If we already have this destination, as tested case-insensitively,
        do not add it to the destinations list. */

        d = find_dest(qq, q, dest_add, TRUE);

        if (d->parent == NULL)
          {
          while (isspace(*p)) p++;
          if (*p == '<')
            {
            dest_item *dd;
            q = ++p;
            while (*p != 0 && *p != '>') p++;
            *p = 0;
            if ((p = strstric(q, qualify_domain, FALSE)) != NULL &&
              *(--p) == '@') *p = 0;
            dd = find_dest(qq, q, dest_noop, FALSE);
            if (dd != NULL && dd != d) d->parent = dd;
            }
          }
        }
      }

    store_reset(reset_point);
    }
  }


/* We have to detect when the log file is changed, and switch to the new file.
In practice, for non-datestamped files, this means that some deliveries might
go unrecorded, since they'll be written to the old file, but this usually
happens in the middle of the night, and I don't think the hassle of keeping
track of two log files is worth it.

First we check the datestamped name of the log file if necessary; if it is
different to the file we currently have open, go for the new file. As happens
in Exim itself, we leave in the following inode check, even when datestamping
because it does no harm and will cope should a file actually be renamed for
some reason.

The test for a changed log file is to look up the inode of the file by name and
compare it with the saved inode of the file we currently are processing. This
accords with the usual interpretation of POSIX and other Unix specs that imply
"one file, one inode". However, it appears that on some Digital systems, if an
open file is unlinked, a new file may be created with the same inode while the
old file remains in existence. This can happen if the old log file is renamed,
processed in some way, and then deleted. To work round this, also test for a
link count of zero on the currently open file. */

if (log_datestamping)
  {
  uschar log_file_wanted[256];
  string_format(log_file_wanted, sizeof(log_file_wanted), CS log_file);
  if (Ustrcmp(log_file_wanted, log_file_open) != 0)
    {
    if (LOG != NULL)
      {
      fclose(LOG);
      LOG = NULL;
      }
    Ustrcpy(log_file_open, log_file_wanted);
    }
  }

if (LOG == NULL ||
    (fstat(fileno(LOG), &statdata) == 0 && statdata.st_nlink == 0) ||
    (Ustat(log_file, &statdata) == 0 && log_inode != statdata.st_ino))
  {
  FILE *TEST;

  /* Experiment shows that sometimes you can't immediately open
  the new log file - presumably immediately after the old one
  is renamed and before the new one exists. Therefore do a
  trial open first to be sure. */

  if ((TEST = fopen(CS log_file_open, "r")) != NULL)
    {
    if (LOG != NULL) fclose(LOG);
    LOG = TEST;
    fstat(fileno(LOG), &statdata);
    log_inode = statdata.st_ino;
    }
  }

/* Save the position we have got to in the log. */

if (LOG != NULL) log_position = ftell(LOG);
}
예제 #8
0
파일: em_menu.c 프로젝트: Exim/exim
static void ActOnMessage(uschar *id, uschar *action, uschar *address_arg)
{
int pid;
int pipe_fd[2];
int delivery = Ustrcmp(action + Ustrlen(action) - 2, "-M") == 0;
uschar *quote = US"";
uschar *at = US"";
uschar *qualify = US"";
uschar buffer[256];
queue_item *qq;
Widget text = NULL;

/* If the address arg is not empty and does not contain @ and there is a
qualify domain, qualify it. (But don't qualify '<>'.)*/

if (address_arg[0] != 0)
  {
  quote = US"\'";
  if (Ustrchr(address_arg, '@') == NULL &&
      Ustrcmp(address_arg, "<>") != 0 &&
      qualify_domain != NULL &&
      qualify_domain[0] != 0)
    {
    at = US"@";
    qualify = qualify_domain;
    }
  }
sprintf(CS buffer, "%s %s %s %s %s %s%s%s%s%s", exim_path,
  (alternate_config == NULL)? US"" : US"-C",
  (alternate_config == NULL)? US"" : alternate_config,
  action, id, quote, address_arg, at, qualify, quote);

/* If we know we are going to need the window, create it now. */

if (action_output || delivery)
  {
  text = text_create(id, text_depth);
  text_showf(text, "%s\n", buffer);
  }

/* Create the pipe for output. Remember, on most systems pipe[0] is
for reading and pipe[1] is for writing! Solaris, with its two-way
pipes is a trap! */

if (pipe(pipe_fd) != 0)
  {
  if (text == NULL)
    {
    text = text_create(id, text_depth);
    text_showf(text, "%s\n", buffer);
    }
  text_show(text, US"*** Failed to create pipe ***\n");
  return;
  }

if (  fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK)
   || fcntl(pipe_fd[1], F_SETFL, O_NONBLOCK))
  {
  perror("set nonblocking on pipe");
  exit(1);
  }

/* Delivering a message can take some time, and we want to show the
output as it goes along. This requires subprocesses and is coded below. For
other commands, we can assume an immediate response, and so need not waste
resources with subprocesses. If action_output is FALSE, don't show the
output at all. */

if (!delivery)
  {
  int count, rc;
  int save_stdout = dup(1);
  int save_stderr = dup(2);

  close(1);
  close(2);

  dup2(pipe_fd[1], 1);
  dup2(pipe_fd[1], 2);
  close(pipe_fd[1]);

  rc = system(CS buffer);

  close(1);
  close(2);

  if (action_output || rc != 0)
    {
    if (text == NULL)
      {
      text = text_create(id, text_depth);
      text_showf(text, "%s\n", buffer);
      }
    while ((count = read(pipe_fd[0], buffer, 254)) > 0)
      {
      buffer[count] = 0;
      text_show(text, buffer);
      }
    }

  close(pipe_fd[0]);

  dup2(save_stdout, 1);
  dup2(save_stderr, 2);
  close(save_stdout);
  close(save_stderr);

  /* If action was to change the sender, and it succeeded, we have to
  update the in-store data. */

  if (rc == 0 && Ustrcmp(action + Ustrlen(action) - 4, "-Mes") == 0)
    {
    queue_item *q = find_queue(id, queue_noop, 0);
    if (q)
      {
      if (q->sender) store_free(q->sender);
      q->sender = store_malloc(Ustrlen(address_arg) + 1);
      Ustrcpy(q->sender, address_arg);
      }
    }

  /* If configured, cause a display update and return */

  if (action_queue_update) tick_queue_accumulator = 999999;
  return;
  }

/* Message is to be delivered. Ensure that it is marked unfrozen,
because nothing will get written to the log to show that this has
happened. (Other freezing/unfreezings get logged and picked up from
there.) */

qq = find_queue(id, queue_noop, 0);
if (qq != NULL) qq->frozen = FALSE;

/* New, asynchronous code runs in a subprocess for commands that
will take some time. The main process does not wait. There is a
SIGCHLD handler in the main program that cleans up any terminating
sub processes. */

if ((pid = fork()) == 0)
  {
  close(1);
  close(2);

  dup2(pipe_fd[1], 1);
  dup2(pipe_fd[1], 2);
  close(pipe_fd[1]);

  system(CS buffer);

  close(1);
  close(2);
  close(pipe_fd[0]);
  _exit(0);
  }

/* Main process - set up an item for the main ticker to watch. */

if (pid < 0) text_showf(text, "Failed to fork: %s\n", strerror(errno)); else
  {
  pipe_item *p = (pipe_item *)store_malloc(sizeof(pipe_item));

  if (p == NULL)
    {
    text_show(text, US"Run out of store\n");
    return;
    }

  p->widget = text;
  p->fd = pipe_fd[0];

  p->next = pipe_chain;
  pipe_chain = p;

  close(pipe_fd[1]);
  }
}