Exemple #1
0
static void out_cb(void *context, int rec_type, const char *buf,
		           ssize_t len, off_t offset)
{
    const HBC_TEST_CONTEXT *dp = (HBC_TEST_CONTEXT *) context;

    vstream_fwrite(dp->fp, buf, len);
    VSTREAM_PUTC('\n', dp->fp);
    vstream_fflush(dp->fp);
}
Exemple #2
0
void    netstring_put(VSTREAM *stream, const char *data, ssize_t len)
{
    const char *myname = "netstring_put";

    if (msg_verbose > 1)
	msg_info("%s: write netstring len %ld data %.*s",
		 myname, (long) len, (int) (len < 30 ? len : 30), data);
    vstream_fprintf(stream, "%ld:", (long) len);
    vstream_fwrite(stream, data, len);
    VSTREAM_PUTC(',', stream);
}
Exemple #3
0
int     main(int unused_argc, char **unused_argv)
{
    VSTRING *in = vstring_alloc(10);
    VSTRING *out = vstring_alloc(10);

    while (vstring_fgets_nonl(in, VSTREAM_IN)) {
	unescape(out, vstring_str(in));
	vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
    }
    vstream_fflush(VSTREAM_OUT);
    exit(0);
}
int     main(void)
{
    VSTRING *buf = vstring_alloc(1);

    while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
        vstream_printf("%c", (LEN(buf) && !valid_utf8_string(STR(buf), LEN(buf))) ?
                       '!' : ' ');
        vstream_fwrite(VSTREAM_OUT, STR(buf), LEN(buf));
        vstream_printf("\n");
    }
    vstream_fflush(VSTREAM_OUT);
    vstring_free(buf);
    exit(0);
}
Exemple #5
0
int     main(int argc, char **argv)
{
	VSTRING *in = vstring_alloc(10);
	VSTRING *out = vstring_alloc(10);
	int     un_escape = 1;

	if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0)
		msg_fatal("usage: %s [-e (escape)]", argv[0]);

	if (un_escape) {
		while (vstring_fgets_nonl(in, VSTREAM_IN)) {
			unescape(out, vstring_str(in));
			vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
		}
	} else {
		while (vstring_fgets(in, VSTREAM_IN)) {
			escape(out, vstring_str(in), VSTRING_LEN(in));
			vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
		}
	}
	vstream_fflush(VSTREAM_OUT);
	exit(0);
}
Exemple #6
0
int     memcache_fwrite(VSTREAM *stream, const char *cp, ssize_t todo)
{

    /*
     * Sanity check.
     */
    if (todo < 0)
	msg_panic("memcache_fwrite: negative todo %ld", (long) todo);

    /*
     * Do the I/O.
     */
    if (msg_verbose)
	msg_info("%s write: %.*s", VSTREAM_PATH(stream), (int) todo, cp);
    if (vstream_fwrite(stream, cp, todo) != todo
	|| vstream_fputs("\r\n", stream) == VSTREAM_EOF)
	return (-1);
    else
	return (0);
}
Exemple #7
0
main(int unused_argc, char **unused_argv)
{
    VSTRING *raw = vstring_alloc(BUFLEN);
    VSTRING *hex = vstring_alloc(100);
    int     len;

    while ((len = read_buf(VSTREAM_IN, raw)) > 0) {
	hex_quote(hex, STR(raw));
	if (hex_unquote(raw, STR(hex)) == 0)
	    msg_fatal("bad input: %.100s", STR(hex));
	if (LEN(raw) != len)
	    msg_fatal("len %d != raw len %d", len, LEN(raw));
	if (vstream_fwrite(VSTREAM_OUT, STR(raw), LEN(raw)) != LEN(raw))
	    msg_fatal("write error: %m");
    }
    vstream_fflush(VSTREAM_OUT);
    vstring_free(raw);
    vstring_free(hex);
    return (0);
}
Exemple #8
0
int     main(int unused_argc, char **unused_argv)
{
    VSTRING *unquoted = vstring_alloc(BUFLEN);
    VSTRING *quoted = vstring_alloc(100);
    ssize_t len;

    while ((len = read_buf(VSTREAM_IN, unquoted)) > 0) {
	xtext_quote(quoted, STR(unquoted), "+=");
	if (xtext_unquote(unquoted, STR(quoted)) == 0)
	    msg_fatal("bad input: %.100s", STR(quoted));
	if (LEN(unquoted) != len)
	    msg_fatal("len %ld != unquoted len %ld",
		      (long) len, (long) LEN(unquoted));
	if (vstream_fwrite(VSTREAM_OUT, STR(unquoted), LEN(unquoted)) != LEN(unquoted))
	    msg_fatal("write error: %m");
    }
    vstream_fflush(VSTREAM_OUT);
    vstring_free(unquoted);
    vstring_free(quoted);
    return (0);
}
Exemple #9
0
void    smtp_fwrite(const char *cp, int todo, VSTREAM *stream)
{
    unsigned err;

    if (todo < 0)
	msg_panic("smtp_fwrite: negative todo %d", todo);

    /*
     * Do the I/O, protected against timeout.
     */
    smtp_timeout_reset(stream);
    err = (vstream_fwrite(stream, cp, todo) != todo);
    smtp_timeout_detect(stream);

    /*
     * See if there was a problem.
     */
    if (err != 0) {
	if (msg_verbose)
	    msg_info("smtp_fwrite: EOF");
	vstream_longjmp(stream, SMTP_ERR_EOF);
    }
}
Exemple #10
0
static void show_queue(void)
{
    const char *errstr;
    char    buf[VSTREAM_BUFSIZE];
    VSTREAM *showq;
    int     n;
    uid_t   uid = getuid();

    if (uid != 0 && uid != var_owner_uid
	&& (errstr = check_user_acl_byuid(VAR_SHOWQ_ACL, var_showq_acl,
					  uid)) != 0)
	msg_fatal_status(EX_NOPERM,
		       "User %s(%ld) is not allowed to view the mail queue",
			 errstr, (long) uid);

    /*
     * Connect to the show queue service. Terminate silently when piping into
     * a program that terminates early.
     */
    if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
	while ((n = vstream_fread(showq, buf, sizeof(buf))) > 0) {
	    if (vstream_fwrite(VSTREAM_OUT, buf, n) != n
		|| vstream_fflush(VSTREAM_OUT) != 0) {
		if (errno == EPIPE)
		    break;
		msg_fatal("write error: %m");
	    }
	}
	if (vstream_fclose(showq) && errno != EPIPE)
	    msg_warn("close: %m");
    }

    /*
     * Don't assume that the mail system is down when the user has
     * insufficient permission to access the showq socket.
     */
    else if (errno == EACCES) {
	msg_fatal_status(EX_SOFTWARE,
			 "Connect to the %s %s service: %m",
			 var_mail_name, var_showq_service);
    }

    /*
     * When the mail system is down, the superuser can still access the queue
     * directly. Just run the showq program in stand-alone mode.
     */
    else if (geteuid() == 0) {
	ARGV   *argv;
	int     stat;

	msg_warn("Mail system is down -- accessing queue directly");
	argv = argv_alloc(6);
	argv_add(argv, var_showq_service, "-u", "-S", (char *) 0);
	for (n = 0; n < msg_verbose; n++)
	    argv_add(argv, "-v", (char *) 0);
	argv_terminate(argv);
	stat = mail_run_foreground(var_daemon_dir, argv->argv);
	argv_free(argv);
	if (stat != 0)
	    msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
			     "Error running %s/%s",
			     var_daemon_dir, argv->argv[0]);
    }

    /*
     * When the mail system is down, unprivileged users are stuck, because by
     * design the mail system contains no set_uid programs. The only way for
     * an unprivileged user to cross protection boundaries is to talk to the
     * showq daemon.
     */
    else {
	msg_fatal_status(EX_UNAVAILABLE,
			 "Queue report unavailable - mail system is down");
    }
}
Exemple #11
0
static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
{
    int     prev_type = 0;
    int     rec_type;
    struct timeval tv;
    time_t  time;
    int     ch;
    off_t   offset;
    const char *error_text;
    char   *attr_name;
    char   *attr_value;
    int     rec_flags = (msg_verbose ? REC_FLAG_NONE : REC_FLAG_DEFAULT);
    int     state;			/* state machine, input type */
    int     do_print;			/* state machine, output control */
    long    data_offset;		/* state machine, read optimization */
    long    data_size;			/* state machine, read optimization */

#define TEXT_RECORD(rec_type) \
	    (rec_type == REC_TYPE_CONT || rec_type == REC_TYPE_NORM)

    /*
     * See if this is a plausible file.
     */
    if ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
	if (!strchr(REC_TYPE_ENVELOPE, ch)) {
	    msg_warn("%s: input is not a valid queue file", VSTREAM_PATH(fp));
	    return;
	}
	vstream_ungetc(fp, ch);
    }

    /*
     * Other preliminaries.
     */
    if (flags & PC_FLAG_PRINT_ENV)
	vstream_printf("*** ENVELOPE RECORDS %s ***\n",
		       VSTREAM_PATH(fp));
    state = PC_STATE_ENV;
    do_print = (flags & PC_FLAG_PRINT_ENV);
    data_offset = data_size = -1;

    /*
     * Now look at the rest.
     */
    for (;;) {
	if (flags & PC_FLAG_PRINT_OFFSET)
	    offset = vstream_ftell(fp);
	rec_type = rec_get_raw(fp, buffer, 0, rec_flags);
	if (rec_type == REC_TYPE_ERROR)
	    msg_fatal("record read error");
	if (rec_type == REC_TYPE_EOF)
	    break;

	/*
	 * First inspect records that have side effects on the (envelope,
	 * header, body) state machine or on the record reading order.
	 * 
	 * XXX Comments marked "Optimization:" identify subtle code that will
	 * likely need to be revised when the queue file organization is
	 * changed.
	 */
#define PRINT_MARKER(flags, fp, offset, type, text) do { \
    if ((flags) & PC_FLAG_PRINT_OFFSET) \
	vstream_printf("%9lu ", (unsigned long) (offset)); \
    if (flags & PC_FLAG_PRINT_RTYPE_DEC) \
	vstream_printf("%3d ", (type)); \
    vstream_printf("*** %s %s ***\n", (text), VSTREAM_PATH(fp)); \
    vstream_fflush(VSTREAM_OUT); \
} while (0)

#define PRINT_RECORD(flags, offset, type, value) do { \
    if ((flags) & PC_FLAG_PRINT_OFFSET) \
	vstream_printf("%9lu ", (unsigned long) (offset)); \
    if (flags & PC_FLAG_PRINT_RTYPE_DEC) \
	vstream_printf("%3d ", (type)); \
    vstream_printf("%s: %s\n", rec_type_name(rec_type), (value)); \
    vstream_fflush(VSTREAM_OUT); \
} while (0)

	if (TEXT_RECORD(rec_type)) {
	    /* This is wrong when the message starts with whitespace. */
	    if (state == PC_STATE_HEADER && (flags & (PC_MASK_PRINT_TEXT))
		&& prev_type != REC_TYPE_CONT && TEXT_RECORD(rec_type)
	     && !(is_header(STR(buffer)) || IS_SPACE_TAB(STR(buffer)[0]))) {
		/* Update the state machine. */
		state = PC_STATE_BODY;
		do_print = (flags & PC_FLAG_PRINT_BODY);
		/* Optimization: terminate if nothing left to print. */
		if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV) == 0)
		    break;
		/* Optimization: skip to extracted segment marker. */
		if (do_print == 0 && (flags & PC_FLAG_PRINT_ENV)
		    && data_offset >= 0 && data_size >= 0
		    && vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
		    msg_fatal("seek error: %m");
	    }
	    /* Optional output happens further down below. */
	} else if (rec_type == REC_TYPE_MESG) {
	    /* Sanity check. */
	    if (state != PC_STATE_ENV)
		msg_warn("%s: out-of-order message content marker",
			 VSTREAM_PATH(fp));
	    /* Optional output. */
	    if (flags & PC_FLAG_PRINT_ENV)
		PRINT_MARKER(flags, fp, offset, rec_type, "MESSAGE CONTENTS");
	    /* Optimization: skip to extracted segment marker. */
	    if ((flags & PC_MASK_PRINT_TEXT) == 0
		&& data_offset >= 0 && data_size >= 0
		&& vstream_fseek(fp, data_offset + data_size, SEEK_SET) < 0)
		msg_fatal("seek error: %m");
	    /* Update the state machine, even when skipping. */
	    state = PC_STATE_HEADER;
	    do_print = (flags & PC_FLAG_PRINT_HEADER);
	    continue;
	} else if (rec_type == REC_TYPE_XTRA) {
	    /* Sanity check. */
	    if (state != PC_STATE_HEADER && state != PC_STATE_BODY)
		msg_warn("%s: out-of-order extracted segment marker",
			 VSTREAM_PATH(fp));
	    /* Optional output (terminate preceding header/body line). */
	    if (do_print && prev_type == REC_TYPE_CONT)
		VSTREAM_PUTCHAR('\n');
	    if (flags & PC_FLAG_PRINT_ENV)
		PRINT_MARKER(flags, fp, offset, rec_type, "HEADER EXTRACTED");
	    /* Update the state machine. */
	    state = PC_STATE_ENV;
	    do_print = (flags & PC_FLAG_PRINT_ENV);
	    /* Optimization: terminate if nothing left to print. */
	    if (do_print == 0)
		break;
	    continue;
	} else if (rec_type == REC_TYPE_END) {
	    /* Sanity check. */
	    if (state != PC_STATE_ENV)
		msg_warn("%s: out-of-order message end marker",
			 VSTREAM_PATH(fp));
	    /* Optional output. */
	    if (flags & PC_FLAG_PRINT_ENV)
		PRINT_MARKER(flags, fp, offset, rec_type, "MESSAGE FILE END");
	    /* Terminate the state machine. */
	    break;
	} else if (rec_type == REC_TYPE_PTR) {
	    /* Optional output. */
	    /* This record type is exposed only with '-v'. */
	    if (do_print)
		PRINT_RECORD(flags, offset, rec_type, STR(buffer));
	    /* Skip to the pointer's target record. */
	    if (rec_goto(fp, STR(buffer)) == REC_TYPE_ERROR)
		msg_fatal("bad pointer record, or input is not seekable");
	    continue;
	} else if (rec_type == REC_TYPE_SIZE) {
	    /* Optional output (here before we update the state machine). */
	    if (do_print)
		PRINT_RECORD(flags, offset, rec_type, STR(buffer));
	    /* Read the message size/offset for the state machine optimizer. */
	    if (data_size >= 0 || data_offset >= 0) {
		msg_warn("file contains multiple size records");
	    } else {
		if (sscanf(STR(buffer), "%ld %ld", &data_size, &data_offset) != 2
		    || data_offset <= 0 || data_size <= 0)
		    msg_fatal("invalid size record: %.100s", STR(buffer));
		/* Optimization: skip to the message header. */
		if ((flags & PC_FLAG_PRINT_ENV) == 0) {
		    if (vstream_fseek(fp, data_offset, SEEK_SET) < 0)
			msg_fatal("seek error: %m");
		    /* Update the state machine. */
		    state = PC_STATE_HEADER;
		    do_print = (flags & PC_FLAG_PRINT_HEADER);
		}
	    }
	    continue;
	}

	/*
	 * Don't inspect side-effect-free records that aren't printed.
	 */
	if (do_print == 0)
	    continue;
	if (flags & PC_FLAG_PRINT_OFFSET)
	    vstream_printf("%9lu ", (unsigned long) offset);
	if (flags & PC_FLAG_PRINT_RTYPE_DEC)
	    vstream_printf("%3d ", rec_type);
	switch (rec_type) {
	case REC_TYPE_TIME:
	    REC_TYPE_TIME_SCAN(STR(buffer), tv);
	    time = tv.tv_sec;
	    vstream_printf("%s: %s", rec_type_name(rec_type),
			   asctime(localtime(&time)));
	    break;
	case REC_TYPE_WARN:
	    REC_TYPE_WARN_SCAN(STR(buffer), time);
	    vstream_printf("%s: %s", rec_type_name(rec_type),
			   asctime(localtime(&time)));
	    break;
	case REC_TYPE_CONT:			/* REC_TYPE_FILT collision */
	    if (state == PC_STATE_ENV)
		vstream_printf("%s: ", rec_type_name(rec_type));
	    else if (msg_verbose)
		vstream_printf("unterminated_text: ");
	    vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
	    if (state == PC_STATE_ENV || msg_verbose
		|| (flags & PC_FLAG_PRINT_OFFSET) != 0) {
		rec_type = 0;
		VSTREAM_PUTCHAR('\n');
	    }
	    break;
	case REC_TYPE_NORM:
	    if (msg_verbose)
		vstream_printf("%s: ", rec_type_name(rec_type));
	    vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
	    VSTREAM_PUTCHAR('\n');
	    break;
	case REC_TYPE_DTXT:
	    /* This record type is exposed only with '-v'. */
	    vstream_printf("%s: ", rec_type_name(rec_type));
	    vstream_fwrite(VSTREAM_OUT, STR(buffer), LEN(buffer));
	    VSTREAM_PUTCHAR('\n');
	    break;
	case REC_TYPE_ATTR:
	    error_text = split_nameval(STR(buffer), &attr_name, &attr_value);
	    if (error_text != 0) {
		msg_warn("%s: malformed attribute: %s: %.100s",
			 VSTREAM_PATH(fp), error_text, STR(buffer));
		break;
	    }
	    if (strcmp(attr_name, MAIL_ATTR_CREATE_TIME) == 0) {
		time = atol(attr_value);
		vstream_printf("%s: %s", MAIL_ATTR_CREATE_TIME,
			       asctime(localtime(&time)));
	    } else {
		vstream_printf("%s: %s=%s\n", rec_type_name(rec_type),
			       attr_name, attr_value);
	    }
	    break;
	default:
	    vstream_printf("%s: %s\n", rec_type_name(rec_type), STR(buffer));
	    break;
	}
	prev_type = rec_type;

	/*
	 * In case the next record is broken.
	 */
	vstream_fflush(VSTREAM_OUT);
    }
}
Exemple #12
0
int     attr_vprint0(VSTREAM *fp, int flags, va_list ap)
{
    const char *myname = "attr_print0";
    int     attr_type;
    char   *attr_name;
    unsigned int_val;
    unsigned long long_val;
    char   *str_val;
    HTABLE_INFO **ht_info_list;
    HTABLE_INFO **ht;
    ssize_t len_val;
    static VSTRING *base64_buf;
    ATTR_PRINT_SLAVE_FN print_fn;
    void   *print_arg;

    /*
     * Sanity check.
     */
    if (flags & ~ATTR_FLAG_ALL)
	msg_panic("%s: bad flags: 0x%x", myname, flags);

    /*
     * Iterate over all (type, name, value) triples, and produce output on
     * the fly.
     */
    while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) {
	switch (attr_type) {
	case ATTR_TYPE_INT:
	    attr_name = va_arg(ap, char *);
	    vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
	    int_val = va_arg(ap, int);
	    vstream_fprintf(fp, "%u", (unsigned) int_val);
	    VSTREAM_PUTC('\0', fp);
	    if (msg_verbose)
		msg_info("send attr %s = %u", attr_name, int_val);
	    break;
	case ATTR_TYPE_LONG:
	    attr_name = va_arg(ap, char *);
	    vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
	    long_val = va_arg(ap, unsigned long);
	    vstream_fprintf(fp, "%lu", (unsigned long) long_val);
	    VSTREAM_PUTC('\0', fp);
	    if (msg_verbose)
		msg_info("send attr %s = %lu", attr_name, long_val);
	    break;
	case ATTR_TYPE_STR:
	    attr_name = va_arg(ap, char *);
	    vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
	    str_val = va_arg(ap, char *);
	    vstream_fwrite(fp, str_val, strlen(str_val) + 1);
	    if (msg_verbose)
		msg_info("send attr %s = %s", attr_name, str_val);
	    break;
	case ATTR_TYPE_DATA:
	    attr_name = va_arg(ap, char *);
	    vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
	    len_val = va_arg(ap, ssize_t);
	    str_val = va_arg(ap, char *);
	    if (base64_buf == 0)
		base64_buf = vstring_alloc(10);
	    base64_encode(base64_buf, str_val, len_val);
	    vstream_fwrite(fp, STR(base64_buf), LEN(base64_buf) + 1);
	    if (msg_verbose)
		msg_info("send attr %s = [data %ld bytes]",
			 attr_name, (long) len_val);
	    break;
	case ATTR_TYPE_FUNC:
	    print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN);
	    print_arg = va_arg(ap, void *);
	    print_fn(attr_print0, fp, flags | ATTR_FLAG_MORE, print_arg);
	    break;
	case ATTR_TYPE_HASH:
	    ht_info_list = htable_list(va_arg(ap, HTABLE *));
	    for (ht = ht_info_list; *ht; ht++) {
		vstream_fwrite(fp, ht[0]->key, strlen(ht[0]->key) + 1);
		vstream_fwrite(fp, ht[0]->value, strlen(ht[0]->value) + 1);
		if (msg_verbose)
		    msg_info("send attr name %s value %s",
			     ht[0]->key, (char *) ht[0]->value);
	    }
	    myfree((void *) ht_info_list);
	    break;
	default:
	    msg_panic("%s: unknown type code: %d", myname, attr_type);
	}
    }
    if ((flags & ATTR_FLAG_MORE) == 0)
	VSTREAM_PUTC('\0', fp);
    return (vstream_ferror(fp));
}