コード例 #1
0
static void qmqpd_copy_sender(QMQPD_STATE *state)
{
    char   *end_prefix;
    char   *end_origin;
    int     verp_requested;
    static char verp_delims[] = "-=";

    /*
     * If the sender address looks like prefix@origin-@[], then request
     * variable envelope return path delivery, with an envelope sender
     * address of prefi@origin, and with VERP delimiters of x and =. This
     * way, the recipients will see envelope sender addresses that look like:
     * prefixuser=domain@origin.
     */
    state->where = "receiving sender address";
    netstring_get(state->client, state->buf, var_line_limit);
    VSTRING_TERMINATE(state->buf);
    verp_requested =
	((end_origin = vstring_end(state->buf) - 4) > STR(state->buf)
	 && strcmp(end_origin, "-@[]") == 0
	 && (end_prefix = strchr(STR(state->buf), '@')) != 0	/* XXX */
	 && --end_prefix < end_origin - 2	/* non-null origin */
	 && end_prefix > STR(state->buf));	/* non-null prefix */
    if (verp_requested) {
	verp_delims[0] = end_prefix[0];
	if (verp_delims_verify(verp_delims) != 0) {
	    state->err |= CLEANUP_STAT_CONT;	/* XXX */
	    vstring_sprintf(state->why_rejected, "Invalid VERP delimiters: \"%s\". Need two characters from \"%s\"",
			    verp_delims, var_verp_filter);
	}
	memmove(end_prefix, end_prefix + 1, end_origin - end_prefix - 1);
	vstring_truncate(state->buf, end_origin - STR(state->buf) - 1);
    }
    if (state->err == CLEANUP_STAT_OK
	&& REC_PUT_BUF(state->cleanup, REC_TYPE_FROM, state->buf) < 0)
	state->err = CLEANUP_STAT_WRITE;
    if (verp_requested)
	if (state->err == CLEANUP_STAT_OK
	    && rec_put(state->cleanup, REC_TYPE_VERP, verp_delims, 2) < 0)
	    state->err = CLEANUP_STAT_WRITE;
    state->sender = mystrndup(STR(state->buf), LEN(state->buf));
}
コード例 #2
0
static void receive_reply(int unused_event, char *context)
{
    SESSION *session = (SESSION *) context;
    int     except;

    /*
     * Prepare for disaster.
     */
    if ((except = vstream_setjmp(session->stream)) != 0)
	msg_fatal("%s while receiving server reply", exception_text(except));

    /*
     * Receive and process the server reply.
     */
    netstring_get(session->stream, buffer, var_line_limit);
    if (msg_verbose)
	vstream_printf("<< %.*s\n", (int) LEN(buffer), STR(buffer));
    if (STR(buffer)[0] != QMQP_STAT_OK)
	msg_fatal("%s error: %.*s",
		  STR(buffer)[0] == QMQP_STAT_RETRY ? "recoverable" :
		  STR(buffer)[0] == QMQP_STAT_HARD ? "unrecoverable" :
		  "unknown", (int) LEN(buffer) - 1, STR(buffer) + 1);

    /*
     * Update the optional running counter.
     */
    if (count) {
	counter++;
	vstream_printf("%d\r", counter);
	vstream_fflush(VSTREAM_OUT);
    }

    /*
     * Finish this session. QMQP sends only one message per session.
     */
    event_disable_readwrite(vstream_fileno(session->stream));
    vstream_fclose(session->stream);
    session->stream = 0;
    start_another(session);
}
コード例 #3
0
static void qmqpd_copy_recipients(QMQPD_STATE *state)
{
    int     ch;

    /*
     * Remember the first recipient. We are done when we read the over-all
     * netstring terminator.
     * 
     * XXX This approach violates abstractions, but it is a heck of a lot more
     * convenient than counting the over-all byte count down to zero, like
     * qmail does.
     */
    state->where = "receiving recipient address";
    while ((ch = VSTREAM_GETC(state->client)) != ',') {
	vstream_ungetc(state->client, ch);
	netstring_get(state->client, state->buf, var_line_limit);
	if (state->err == CLEANUP_STAT_OK
	    && REC_PUT_BUF(state->cleanup, REC_TYPE_RCPT, state->buf) < 0)
	    state->err = CLEANUP_STAT_WRITE;
	state->rcpt_count++;
	if (state->recipient == 0)
	    state->recipient = mystrndup(STR(state->buf), LEN(state->buf));
    }
}
コード例 #4
0
static void qmqpd_read_content(QMQPD_STATE *state)
{
    state->where = "receiving message content";
    netstring_get(state->client, state->message, var_message_limit);
}
コード例 #5
0
ファイル: dict_sockmap.c プロジェクト: aosm/postfix
static const char *dict_sockmap_lookup(DICT *dict, const char *key)
{
    const char *myname = "dict_sockmap_lookup";
    DICT_SOCKMAP *dp = (DICT_SOCKMAP *) dict;
    AUTO_CLNT *sockmap_clnt = DICT_SOCKMAP_RH_HANDLE(dp->client_info);
    VSTREAM *fp;
    int     netstring_err;
    char   *reply_payload;
    int     except_count;
    const char *error_class;

    if (msg_verbose)
	msg_info("%s: key %s", myname, key);

    /*
     * Optionally fold the key.
     */
    if (dict->flags & DICT_FLAG_FOLD_MUL) {
	if (dict->fold_buf == 0)
	    dict->fold_buf = vstring_alloc(100);
	vstring_strcpy(dict->fold_buf, key);
	key = lowercase(STR(dict->fold_buf));
    }

    /*
     * We retry connection-level errors once, to make server restarts
     * transparent.
     */
    for (except_count = 0; /* see below */ ; except_count++) {

	/*
	 * Look up the stream.
	 */
	if ((fp = auto_clnt_access(sockmap_clnt)) == 0) {
	    msg_warn("table %s:%s lookup error: %m", dict->type, dict->name);
	    dict->error = DICT_ERR_RETRY;
	    return (0);
	}

	/*
	 * Set up an exception handler.
	 */
	netstring_setup(fp, dict_sockmap_timeout);
	if ((netstring_err = vstream_setjmp(fp)) == 0) {

	    /*
	     * Send the query. This may raise an exception.
	     */
	    vstring_sprintf(dp->rdwr_buf, "%s %s", dp->sockmap_name, key);
	    NETSTRING_PUT_BUF(fp, dp->rdwr_buf);

	    /*
	     * Receive the response. This may raise an exception.
	     */
	    netstring_get(fp, dp->rdwr_buf, dict_sockmap_max_reply);

	    /*
	     * If we got here, then no exception was raised.
	     */
	    break;
	}

	/*
	 * Handle exceptions.
	 */
	else {

	    /*
	     * We retry a broken connection only once.
	     */
	    if (except_count == 0 && netstring_err == NETSTRING_ERR_EOF
		&& errno != ETIMEDOUT) {
		auto_clnt_recover(sockmap_clnt);
		continue;
	    }

	    /*
	     * We do not retry other errors.
	     */
	    else {
		msg_warn("table %s:%s lookup error: %s",
			 dict->type, dict->name,
			 netstring_strerror(netstring_err));
		dict->error = DICT_ERR_RETRY;
		return (0);
	    }
	}
    }

    /*
     * Parse the reply.
     */
    VSTRING_TERMINATE(dp->rdwr_buf);
    reply_payload = split_at(STR(dp->rdwr_buf), ' ');
    if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_OK) == 0) {
	dict->error = 0;
	return (reply_payload);
    } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_NOTFOUND) == 0) {
	dict->error = 0;
	return (0);
    }
    /* We got no definitive reply. */
    if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_TEMP) == 0) {
	error_class = "temporary";
	dict->error = DICT_ERR_RETRY;
    } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_TIMEOUT) == 0) {
	error_class = "timeout";
	dict->error = DICT_ERR_RETRY;
    } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_PERM) == 0) {
	error_class = "permanent";
	dict->error = DICT_ERR_CONFIG;
    } else {
	error_class = "unknown";
	dict->error = DICT_ERR_RETRY;
    }
    while (reply_payload && ISSPACE(*reply_payload))
	reply_payload++;
    msg_warn("%s:%s socketmap server %s error%s%.200s",
	     dict->type, dict->name, error_class,
	     reply_payload && *reply_payload ? ": " : "",
	     reply_payload && *reply_payload ?
	     printable(reply_payload, '?') : "");
    return (0);
}
コード例 #6
0
int main (void)
{
  stralloc indata = STRALLOC_ZERO ;
  unsigned int instate = 0 ;
  PROG = "s6-ftrigrd" ;

  if (ndelay_on(0) < 0) strerr_diefu2sys(111, "ndelay_on ", "0") ;
  if (ndelay_on(1) < 0) strerr_diefu2sys(111, "ndelay_on ", "1") ;
  if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ;

  {
    struct taia deadline, stamp ;
    taia_now(&stamp) ;
    taia_addsec(&deadline, &stamp, 2) ;
    if (!skaserver2_sync(&asyncout, FTRIGR_BANNER1, FTRIGR_BANNER1_LEN, FTRIGR_BANNER2, FTRIGR_BANNER2_LEN, &deadline, &stamp))
      strerr_diefu1sys(111, "sync with client") ;
  }

  for (;;)
  {
    register unsigned int n = genalloc_len(ftrigio_t, &a) ;
    iopause_fd x[3 + n] ;
    unsigned int i = 0 ;
    int r ;

    x[0].fd = 0 ; x[0].events = IOPAUSE_EXCEPT | IOPAUSE_READ ;
    x[1].fd = 1 ; x[1].events = IOPAUSE_EXCEPT | (bufalloc_len(bufalloc_1) ? IOPAUSE_WRITE : 0) ;
    x[2].fd = bufalloc_fd(&asyncout) ; x[2].events = IOPAUSE_EXCEPT | (bufalloc_len(&asyncout) ? IOPAUSE_WRITE : 0) ;
    for (; i < n ; i++)
    {
      register ftrigio_t_ref p = genalloc_s(ftrigio_t, &a) + i ;
      p->xindex = 3 + i ;
      x[3+i].fd = p->trig.fd ;
      x[3+i].events = IOPAUSE_READ ;
    }

    r = iopause(x, 3 + n, 0, 0) ;
    if (r < 0)
    {
      cleanup() ;
      strerr_diefu1sys(111, "iopause") ;
    }

   /* client closed => exit */
    if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) break ;

   /* client reading => flush pending data */
    if (x[1].revents & IOPAUSE_WRITE)
      if ((bufalloc_flush(bufalloc_1) == -1) && !error_isagain(errno))
      {
        cleanup() ;
        strerr_diefu1sys(111, "flush stdout") ;
      }
    if (x[2].revents & IOPAUSE_WRITE)
      if ((bufalloc_flush(&asyncout) == -1) && !error_isagain(errno))
      {
        cleanup() ;
        strerr_diefu1sys(111, "flush asyncout") ;
      }

   /* scan listening ftrigs */
    for (i = 0 ; i < genalloc_len(ftrigio_t, &a) ; i++)
    {
      register ftrigio_t_ref p = genalloc_s(ftrigio_t, &a) + i ;
      if (x[p->xindex].revents & IOPAUSE_READ)
      {
        char c ;
        register int r = sanitize_read(fd_read(p->trig.fd, &c, 1)) ;
        if (!r) continue ;
        if (r < 0)
        {
          trig(p->id, 'd', errno) ;
          remove(i--) ;
        }
        else if (!sredfa_feed(p->re, &p->dfastate, c))
        {
          trig(p->id, 'd', ENOEXEC) ;
          remove(i--) ;
        }
        else if (p->dfastate & SREDFA_ACCEPT)
        {
          trig(p->id, '!', c) ;
          if (p->options & FTRIGR_REPEAT)
            p->dfastate = SREDFA_START ;
          else remove(i--) ;
        }
      }
    }

   /* client writing => get data and parse it */
    if (buffer_len(buffer_0small) || x[0].revents & IOPAUSE_READ)
    {
      int r ;
      for (;;)
      {
        uint16 id ;
        r = sanitize_read(netstring_get(buffer_0small, &indata, &instate)) ;
        if (r <= 0) break ;
        if (indata.len < 3)
        {
          cleanup() ;
          strerr_dief1x(100, "invalid client request") ;
        }
        uint16_unpack_big(indata.s, &id) ;
        switch (indata.s[2])  /* protocol parsing */
        {
          case 'U' : /* unsubscribe */
          {
            register unsigned int i = genalloc_len(ftrigio_t, &a) ;
            for (; i ; i--) if (genalloc_s(ftrigio_t, &a)[i-1].id == id) break ;
            if (i) remove(i-1) ;
            answer(0) ;
            break ;
          }
          case 'L' : /* subscribe to path and match re */
          {
            ftrigio_t f = FTRIGIO_ZERO ;
            uint32 pathlen, relen ;
            if (indata.len < 18)
            {
              answer(EPROTO) ;
              break ;
            }
            uint32_unpack_big(indata.s + 3, &f.options) ;
            uint32_unpack_big(indata.s + 7, &pathlen) ;
            uint32_unpack_big(indata.s + 11, &relen) ;
            if (((pathlen + relen + 16) != indata.len) || indata.s[15 + pathlen])
            {
              answer(EPROTO) ;
              break ;
            }
            f.id = id ;
            if (!stralloc_0(&indata))
            {
              answer(errno) ;
              break ;
            }
            f.re = sredfa_new() ;
            if (!f.re)
            {
              answer(errno) ;
              break ;
            }
            if (!sredfa_from_regexp(f.re, indata.s + 16 + pathlen)
             || !ftrig1_make(&f.trig, indata.s + 15))
            {
              sredfa_delete(f.re) ;
              answer(errno) ;
              break ;
            }
            if (!genalloc_append(ftrigio_t, &a, &f))
            {
              ftrigio_deepfree(&f) ;
              answer(errno) ;
              break ;
            }
            answer(0) ;
            break ;
          }
          default :
          {
            cleanup() ;
            strerr_dief1x(100, "invalid client request") ;
          }
        }
        indata.len = 0 ;
      } /* end loop: parse input from client */

      if (r < 0)
      {
        if (errno == EPIPE) break ; /* client closed */
        else
        {
          cleanup() ;
          strerr_diefu1sys(111, "read a netstring") ;
        }
      } 
    } /* end if: stuff to read on stdin */
  } /* end loop: main iopause */

  cleanup() ;
  return 0 ;
}