Esempio n. 1
0
static const char *tok822_comment(TOK822 *tp, const char *str)
{
    int     level = 1;
    int     ch;

    /*
     * XXX We cheat by storing comments in their external form. Otherwise it
     * would be a royal pain to preserve \ before (. That would require a
     * recursive parser; the easy to implement stack-based recursion would be
     * too expensive.
     */
    VSTRING_ADDCH(tp->vstr, '(');

    while ((ch = *(unsigned char *) str) != 0) {
	VSTRING_ADDCH(tp->vstr, ch);
	str++;
	if (ch == '(') {			/* comments can nest! */
	    level++;
	} else if (ch == ')') {
	    if (--level == 0)
		break;
	} else if (ch == '\\') {
	    if ((ch = *(unsigned char *) str) == 0)
		break;
	    VSTRING_ADDCH(tp->vstr, ch);
	    str++;
	}
    }
    VSTRING_TERMINATE(tp->vstr);
    return (str);
}
Esempio n. 2
0
VSTRING *format_tv(VSTRING *buf, int sec, int usec,
		           int sig_dig, int max_dig)
{
    static int pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000};
    int     n;
    int     rem;
    int     wid;
    int     ures;

    /*
     * Sanity check.
     */
    if (max_dig < 0 || max_dig > 6)
	msg_panic("format_tv: bad maximum decimal count %d", max_dig);
    if (sec < 0 || usec < 0 || usec > MILLION)
	msg_panic("format_tv: bad time %ds %dus", sec, usec);
    if (sig_dig < 1 || sig_dig > 6)
	msg_panic("format_tv: bad significant decimal count %d", sig_dig);
    ures = MILLION / pow10[max_dig];
    wid = pow10[sig_dig];

    /*
     * Adjust the resolution to suppress irrelevant digits.
     */
    if (ures < MILLION) {
	if (sec > 0) {
	    for (n = 1; sec >= n && n <= wid / 10; n *= 10)
		 /* void */ ;
	    ures = (MILLION / wid) * n;
	} else {
	    while (usec >= wid * ures)
		ures *= 10;
	}
    }

    /*
     * Round up the number if necessary. Leave thrash below the resolution.
     */
    if (ures > 1) {
	usec += ures / 2;
	if (usec >= MILLION) {
	    sec += 1;
	    usec -= MILLION;
	}
    }

    /*
     * Format the number. Truncate trailing null and thrash below resolution.
     */
    vstring_sprintf_append(buf, "%d", sec);
    if (usec >= ures) {
	VSTRING_ADDCH(buf, '.');
	for (rem = usec, n = MILLION / 10; rem >= ures && n > 0; n /= 10) {
	    VSTRING_ADDCH(buf, "0123456789"[rem / n]);
	    rem %= n;
	}
    }
    VSTRING_TERMINATE(buf);
    return (buf);
}
Esempio n. 3
0
static VSTRING *flush_site_to_path(VSTRING *path, const char *site)
{
    const char *ptr;
    int     ch;

    /*
     * Allocate buffer on the fly; caller still needs to clean up.
     */
    if (path == 0)
	path = vstring_alloc(10);

    /*
     * Mask characters that could upset the name-to-queue-file mapping code.
     */
    for (ptr = site; (ch = *(unsigned const char *) ptr) != 0; ptr++)
	if (ISALNUM(ch))
	    VSTRING_ADDCH(path, ch);
	else
	    VSTRING_ADDCH(path, '_');
    VSTRING_TERMINATE(path);

    if (msg_verbose)
	msg_info("site %s to path %s", site, STR(path));

    return (path);
}
Esempio n. 4
0
static VSTRING *flush_site_to_path(VSTRING *path, const char *site)
{
    const char *ptr;
    int     ch;

    /*
     * Convert the name to ASCII, so that we don't to end up with non-ASCII
     * names in the file system. The IDNA library functions fold case.
     */
#ifndef NO_EAI
    if ((site = midna_domain_to_ascii(site)) == 0)
	return (0);
#endif

    /*
     * Allocate buffer on the fly; caller still needs to clean up.
     */
    if (path == 0)
	path = vstring_alloc(10);

    /*
     * Mask characters that could upset the name-to-queue-file mapping code.
     */
    for (ptr = site; (ch = *(unsigned const char *) ptr) != 0; ptr++)
	if (ISALNUM(ch))
	    VSTRING_ADDCH(path, tolower(ch));
	else
	    VSTRING_ADDCH(path, '_');
    VSTRING_TERMINATE(path);

    if (msg_verbose)
	msg_info("site %s to path %s", site, STR(path));

    return (path);
}
Esempio n. 5
0
char   *safe_ultostr(VSTRING *buf, unsigned long ulval, int base,
		             int padlen, int padchar)
{
    const char *myname = "safe_ultostr";
    char   *start;
    char   *last;
    int     i;

    /*
     * Sanity check.
     */
    if (base < SAFE_MIN_BASE || base > SAFE_MAX_BASE)
	msg_panic("%s: bad base: %d", myname, base);

    /*
     * First accumulate the result, backwards.
     */
    VSTRING_RESET(buf);
    while (ulval != 0) {
	VSTRING_ADDCH(buf, safe_chars[ulval % base]);
	ulval /= base;
    }
    while (VSTRING_LEN(buf) < padlen)
	VSTRING_ADDCH(buf, padchar);
    VSTRING_TERMINATE(buf);

    /*
     * Then, reverse the result.
     */
    start = STR(buf);
    last = END(buf) - 1;
    for (i = 0; i < VSTRING_LEN(buf) / 2; i++)
	SWAP(int, start[i], last[-i]);
    return (STR(buf));
}
Esempio n. 6
0
static void tok822_copy_quoted(VSTRING *vp, char *str, char *quote_set)
{
    int     ch;

    while ((ch = *(unsigned char *) str++) != 0) {
	if (strchr(quote_set, ch))
	    VSTRING_ADDCH(vp, '\\');
	VSTRING_ADDCH(vp, ch);
    }
}
Esempio n. 7
0
static void mime_state_downgrade(MIME_STATE *state, int rec_type,
				         const char *text, int len)
{
    static char hexchars[] = "0123456789ABCDEF";
    const unsigned char *cp;
    int     ch;

#define QP_ENCODE(buffer, ch) { \
	VSTRING_ADDCH(buffer, '='); \
	VSTRING_ADDCH(buffer, hexchars[(ch >> 4) & 0xff]); \
	VSTRING_ADDCH(buffer, hexchars[ch & 0xf]); \
    }

    /*
     * Insert a soft line break when the output reaches a critical length
     * before we reach a hard line break.
     */
    for (cp = CU_CHAR_PTR(text); cp < CU_CHAR_PTR(text + len); cp++) {
	/* Critical length before hard line break. */
	if (LEN(state->output_buffer) > 72) {
	    VSTRING_ADDCH(state->output_buffer, '=');
	    VSTRING_TERMINATE(state->output_buffer);
	    BODY_OUT(state, REC_TYPE_NORM,
		     STR(state->output_buffer),
		     LEN(state->output_buffer));
	    VSTRING_RESET(state->output_buffer);
	}
	/* Append the next character. */
	ch = *cp;
	if ((ch < 32 && ch != '\t') || ch == '=' || ch > 126) {
	    QP_ENCODE(state->output_buffer, ch);
	} else {
	    VSTRING_ADDCH(state->output_buffer, ch);
	}
    }

    /*
     * Flush output after a hard line break (i.e. the end of a REC_TYPE_NORM
     * record). Fix trailing whitespace as per the RFC: in the worst case,
     * the output length will grow from 73 characters to 75 characters.
     */
    if (rec_type == REC_TYPE_NORM) {
	if (LEN(state->output_buffer) > 0
	    && ((ch = END(state->output_buffer)[-1]) == ' ' || ch == '\t')) {
	    vstring_truncate(state->output_buffer,
			     LEN(state->output_buffer) - 1);
	    QP_ENCODE(state->output_buffer, ch);
	}
	VSTRING_TERMINATE(state->output_buffer);
	BODY_OUT(state, REC_TYPE_NORM,
		 STR(state->output_buffer),
		 LEN(state->output_buffer));
	VSTRING_RESET(state->output_buffer);
    }
}
Esempio n. 8
0
static void encode_utf8(VSTRING *buffer, int codepoint)
{
    const char myname[] = "encode_utf8";

    VSTRING_RESET(buffer);
    if (codepoint < 0x80) {
	VSTRING_ADDCH(buffer, codepoint);
    } else if (codepoint < 0x800) {
	VSTRING_ADDCH(buffer, 0xc0 | (codepoint >> 6));
	VSTRING_ADDCH(buffer, 0x80 | (codepoint & 0x3f));
    } else if (codepoint < 0x10000) {
Esempio n. 9
0
char   *dir_forest(VSTRING *buf, const char *path, int depth)
{
    const char *myname = "dir_forest";
    static VSTRING *private_buf = 0;
    int     n;
    const char *cp;
    int     ch;

    /*
     * Sanity checks.
     */
    if (*path == 0)
	msg_panic("%s: empty path", myname);
    if (depth < 1)
	msg_panic("%s: depth %d", myname, depth);

    /*
     * Your buffer or mine?
     */
    if (buf == 0) {
	if (private_buf == 0)
	    private_buf = vstring_alloc(1);
	buf = private_buf;
    }

    /*
     * Generate one or more subdirectory levels, depending on the pathname
     * contents. When the pathname is short, use underscores instead.
     * Disallow non-printable characters or characters that are special to
     * the file system.
     */
    VSTRING_RESET(buf);
    for (cp = path, n = 0; n < depth; n++) {
	if ((ch = *cp) == 0) {
	    ch = '_';
	} else {
	    if (!ISPRINT(ch) || ch == '.' || ch == '/')
		msg_panic("%s: invalid pathname: %s", myname, path);
	    cp++;
	}
	VSTRING_ADDCH(buf, ch);
	VSTRING_ADDCH(buf, '/');
    }
    VSTRING_TERMINATE(buf);

    if (msg_verbose > 1)
	msg_info("%s: %s -> %s", myname, path, vstring_str(buf));
    return (vstring_str(buf));
}
Esempio n. 10
0
static char *xsasl_dovecot_server_mech_filter(ARGV *mechanism_argv,
				           XSASL_DCSRV_MECH *mechanism_list,
					            unsigned int conf_props)
{
    const char *myname = "xsasl_dovecot_server_mech_filter";
    unsigned int pos_conf_props = (conf_props & SEC_PROPS_POS_MASK);
    unsigned int neg_conf_props = (conf_props & SEC_PROPS_NEG_MASK);
    VSTRING *mechanisms_str = vstring_alloc(10);
    XSASL_DCSRV_MECH *mp;

    /*
     * Match Postfix properties against Dovecot server properties.
     */
    for (mp = mechanism_list; mp != 0; mp = mp->next) {
	if ((mp->sec_props & pos_conf_props) == pos_conf_props
	    && (mp->sec_props & neg_conf_props) == 0) {
	    if (VSTRING_LEN(mechanisms_str) > 0)
		VSTRING_ADDCH(mechanisms_str, ' ');
	    vstring_strcat(mechanisms_str, mp->mech_name);
	    argv_add(mechanism_argv, mp->mech_name, (char *) 0);
	    if (msg_verbose)
		msg_info("%s: keep mechanism: %s", myname, mp->mech_name);
	} else {
	    if (msg_verbose)
		msg_info("%s: skip mechanism: %s", myname, mp->mech_name);
	}
    }
    return (vstring_export(mechanisms_str));
}
Esempio n. 11
0
VSTRING *off_cvt_number(VSTRING *buf, off_t offset)
{
    static char digs[] = "0123456789";
    char   *start;
    char   *last;
    int     i;

    /*
     * Sanity checks
     */
    if (offset < 0)
        msg_panic("off_cvt_number: negative offset -%s",
                  STR(off_cvt_number(buf, -offset)));

    /*
     * First accumulate the result, backwards.
     */
    VSTRING_RESET(buf);
    while (offset != 0) {
        VSTRING_ADDCH(buf, digs[offset % 10]);
        offset /= 10;
    }
    VSTRING_TERMINATE(buf);

    /*
     * Then, reverse the result.
     */
    start = STR(buf);
    last = END(buf) - 1;
    for (i = 0; i < VSTRING_LEN(buf) / 2; i++)
        SWAP(int, start[i], last[-i]);
    return (buf);
}
Esempio n. 12
0
static int attr_scan_plain_string(VSTREAM *fp, VSTRING *plain_buf,
				        int terminator, const char *context)
{
#if 0
    extern int var_line_limit;		/* XXX */
    int     limit = var_line_limit * 4;

#endif
    int     ch;

    VSTRING_RESET(plain_buf);
    while ((ch = VSTREAM_GETC(fp)) != '\n'
	   && (terminator == 0 || ch != terminator)) {
	if (ch == VSTREAM_EOF) {
	    msg_warn("%s on %s while reading %s",
		vstream_ftimeout(fp) ? "timeout" : "premature end-of-input",
		     VSTREAM_PATH(fp), context);
	    return (-1);
	}
	VSTRING_ADDCH(plain_buf, ch);
#if 0
	if (LEN(plain_buf) > limit) {
	    msg_warn("string length > %d characters from %s while reading %s",
		     limit, VSTREAM_PATH(fp), context);
	    return (-1);
	}
#endif
    }
    VSTRING_TERMINATE(plain_buf);

    if (msg_verbose)
	msg_info("%s: %s", context, *STR(plain_buf) ? STR(plain_buf) : "(end)");
    return (ch);
}
Esempio n. 13
0
static void qmqpd_reply(QMQPD_STATE *state, int log_message,
			        int status_code, const char *fmt,...)
{
    va_list ap;

    /*
     * Optionally change hard errors into retryable ones. Send the reply and
     * optionally log it. Always insert a delay before reporting a problem.
     * This slows down software run-away conditions.
     */
    if (status_code == QMQPD_STAT_HARD && var_soft_bounce)
	status_code = QMQPD_STAT_RETRY;
    VSTRING_RESET(state->buf);
    VSTRING_ADDCH(state->buf, status_code);
    va_start(ap, fmt);
    vstring_vsprintf_append(state->buf, fmt, ap);
    va_end(ap);
    NETSTRING_PUT_BUF(state->client, state->buf);
    if (log_message)
	(status_code == QMQPD_STAT_OK ? msg_info : msg_warn) ("%s: %s: %s",
		      state->queue_id, state->namaddr, STR(state->buf) + 1);
    if (status_code != QMQPD_STAT_OK)
	sleep(var_qmqpd_err_sleep);
    netstring_fflush(state->client);
}
Esempio n. 14
0
File: xtext.c Progetto: aosm/postfix
VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted)
{
    const char *cp;
    int     ch;

    for (cp = quoted; (ch = *cp) != 0; cp++) {
	if (ch == '+') {
	    if (ISDIGIT(cp[1]))
		ch = (cp[1] - '0') << 4;
	    else if (cp[1] >= 'a' && cp[1] <= 'f')
		ch = (cp[1] - 'a' + 10) << 4;
	    else if (cp[1] >= 'A' && cp[1] <= 'F')
		ch = (cp[1] - 'A' + 10) << 4;
	    else
		return (0);
	    if (ISDIGIT(cp[2]))
		ch |= (cp[2] - '0');
	    else if (cp[2] >= 'a' && cp[2] <= 'f')
		ch |= (cp[2] - 'a' + 10);
	    else if (cp[2] >= 'A' && cp[2] <= 'F')
		ch |= (cp[2] - 'A' + 10);
	    else
		return (0);
	    cp += 2;
	}
	VSTRING_ADDCH(unquoted, ch);
    }
    VSTRING_TERMINATE(unquoted);
    return (unquoted);
}
Esempio n. 15
0
VSTRING *unquote_822_local(VSTRING *dst, const char *mbox)
{
    const char *start;			/* first byte of localpart */
    const char *end;			/* first byte after localpart */
    const char *colon;
    const char *cp;

    if (mbox[0] == '@' && (colon = strchr(mbox, ':')) != 0) {
	start = colon + 1;
	vstring_strncpy(dst, mbox, start - mbox);
    } else {
	start = mbox;
	VSTRING_RESET(dst);
    }
    if ((end = strrchr(start, '@')) == 0)
	end = start + strlen(start);
    for (cp = start; cp < end; cp++) {
	if (*cp == '"')
	    continue;
	if (*cp == '\\') {
	    if (cp[1] == 0)
		continue;
	    cp++;
	}
	VSTRING_ADDCH(dst, *cp);
    }
    if (*end)
	vstring_strcat(dst, end);
    else
	VSTRING_TERMINATE(dst);
    return (dst);
}
Esempio n. 16
0
VSTRING *hex_decode(VSTRING *result, const char *in, ssize_t len)
{
    const unsigned char *cp;
    ssize_t count;
    unsigned int hex;
    unsigned int bin;

    VSTRING_RESET(result);
    for (cp = UCHAR_PTR(in), count = len; count > 0; cp += 2, count -= 2) {
	if (count < 2)
	    return (0);
	hex = cp[0];
	if (hex >= '0' && hex <= '9')
	    bin = (hex - '0') << 4;
	else if (hex >= 'A' && hex <= 'F')
	    bin = (hex - 'A' + 10) << 4;
	else if (hex >= 'a' && hex <= 'f')
	    bin = (hex - 'a' + 10) << 4;
	else
	    return (0);
	hex = cp[1];
	if (hex >= '0' && hex <= '9')
	    bin |= (hex - '0');
	else if (hex >= 'A' && hex <= 'F')
	    bin |= (hex - 'A' + 10);
	else if (hex >= 'a' && hex <= 'f')
	    bin |= (hex - 'a' + 10);
	else
	    return (0);
	VSTRING_ADDCH(result, bin);
    }
    VSTRING_TERMINATE(result);
    return (result);
}
Esempio n. 17
0
static const char *dict_union_lookup(DICT *dict, const char *query)
{
    static const char myname[] = "dict_union_lookup";
    DICT_UNION *dict_union = (DICT_UNION *) dict;
    DICT   *map;
    char  **cpp;
    char   *dict_type_name;
    const char *result = 0;

    /*
     * After Roel van Meer, postfix-users mailing list, Sept 2014.
     */
    VSTRING_RESET(dict_union->re_buf);
    for (cpp = dict_union->map_union->argv; (dict_type_name = *cpp) != 0; cpp++) {
	if ((map = dict_handle(dict_type_name)) == 0)
	    msg_panic("%s: dictionary \"%s\" not found", myname, dict_type_name);
	if ((result = dict_get(map, query)) == 0)
	    continue;
	if (VSTRING_LEN(dict_union->re_buf) > 0)
	    VSTRING_ADDCH(dict_union->re_buf, ',');
	vstring_strcat(dict_union->re_buf, result);
    }
    DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE,
			VSTRING_LEN(dict_union->re_buf) > 0 ?
			STR(dict_union->re_buf) : 0);
}
Esempio n. 18
0
VSTRING *hex_unquote(VSTRING *raw, const char *hex)
{
    const char *cp;
    int     ch;

    VSTRING_RESET(raw);
    for (cp = hex; (ch = *cp) != 0; cp++) {
	if (ch == '%') {
	    if (ISDIGIT(cp[1]))
		ch = (cp[1] - '0') << 4;
	    else if (cp[1] >= 'a' && cp[1] <= 'f')
		ch = (cp[1] - 'a' + 10) << 4;
	    else if (cp[1] >= 'A' && cp[1] <= 'F')
		ch = (cp[1] - 'A' + 10) << 4;
	    else
		return (0);
	    if (ISDIGIT(cp[2]))
		ch |= (cp[2] - '0');
	    else if (cp[2] >= 'a' && cp[2] <= 'f')
		ch |= (cp[2] - 'a' + 10);
	    else if (cp[2] >= 'A' && cp[2] <= 'F')
		ch |= (cp[2] - 'A' + 10);
	    else
		return (0);
	    cp += 2;
	}
	VSTRING_ADDCH(raw, ch);
    }
    VSTRING_TERMINATE(raw);
    return (raw);
}
Esempio n. 19
0
const char *fullname(void)
{
    static VSTRING *result;
    char   *cp;
    int     ch;
    uid_t   uid;
    struct passwd *pwd;

    if (result == 0)
	result = vstring_alloc(10);

    /*
     * Try the environment.
     */
    if ((cp = safe_getenv("NAME")) != 0)
	return (vstring_str(vstring_strcpy(result, cp)));

    /*
     * Try the password file database.
     */
    uid = getuid();
    if ((pwd = getpwuid(uid)) == 0)
	return (0);

    /*
     * Replace all `&' characters by the login name of this user, first
     * letter capitalized. Although the full name comes from the protected
     * password file, the actual data is specified by the user so we should
     * not trust its sanity.
     */
    VSTRING_RESET(result);
    for (cp = pwd->pw_gecos; (ch = *(unsigned char *) cp) != 0; cp++) {
	if (ch == ',' || ch == ';' || ch == '%')
	    break;
	if (ch == '&') {
	    if (pwd->pw_name[0]) {
		VSTRING_ADDCH(result, TOUPPER(pwd->pw_name[0]));
		vstring_strcat(result, pwd->pw_name + 1);
	    }
	} else {
	    VSTRING_ADDCH(result, ch);
	}
    }
    VSTRING_TERMINATE(result);
    return (vstring_str(result));
}
Esempio n. 20
0
static char *pop3_next_token(char *cp, POP3D_TOKEN *arg)
{
    int     c;

    VSTRING_RESET(arg->vstrval);
    arg->tokval = POP3D_TOK_OTHER;

#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
#define STREQ(x,y,l) (strncasecmp((x), (y), (l)) == 0)

    for (;;) {
	if ((c = *cp) == 0)			/* end of input */
	    break;
	cp++;
	if (ISSPACE(c)) {			/* whitespace, skip */
	    while (*cp && ISSPACE(*cp))
		cp++;
	    if (LEN(arg->vstrval) > 0)		/* end of token */
		break;
	} else if (c == '<') {			/* <stuff> */
	    cp = pop3_quoted(cp, arg, c, '>');
	} else if (c == '"') {			/* "stuff" */
	    cp = pop3_quoted(cp, arg, c, c);
	} else if (c == ':') {			/* this is gross, but... */
	    VSTRING_ADDCH(arg->vstrval, c);
	    if (STREQ(STR(arg->vstrval), "to:", LEN(arg->vstrval))
		|| STREQ(STR(arg->vstrval), "from:", LEN(arg->vstrval)))
		break;
	} else {				/* other */
	    if (c == '\\') {
		VSTRING_ADDCH(arg->vstrval, c);
		if ((c = *cp) == 0)
		    break;
		cp++;
	    }
	    VSTRING_ADDCH(arg->vstrval, c);
	}
    }
    if (LEN(arg->vstrval) <= 0)			/* no token found */
	return (0);
    VSTRING_TERMINATE(arg->vstrval);
    arg->strval = vstring_str(arg->vstrval);
    return (cp);
}
Esempio n. 21
0
VSTRING *vstring_strncat(VSTRING *vp, const char *src, ssize_t len)
{
    while (len-- > 0 && *src) {
	VSTRING_ADDCH(vp, *src);
	src++;
    }
    VSTRING_TERMINATE(vp);
    return (vp);
}
Esempio n. 22
0
VSTRING *vstring_strcat(VSTRING *vp, const char *src)
{
    while (*src) {
	VSTRING_ADDCH(vp, *src);
	src++;
    }
    VSTRING_TERMINATE(vp);
    return (vp);
}
Esempio n. 23
0
static char *pop3_quoted(char *cp, POP3D_TOKEN *arg, int start, int last)
{
    static VSTRING *stack;
    int     wanted;
    int     c;

    /*
     * Parser stack. `ch' is always the most-recently entered character.
     */
#define ENTER_CHAR(buf, ch) VSTRING_ADDCH(buf, ch);
#define LEAVE_CHAR(buf, ch) { \
	vstring_truncate(buf, VSTRING_LEN(buf) - 1); \
	ch = vstring_end(buf)[-1]; \
    }

    if (stack == 0)
	stack = vstring_alloc(1);
    VSTRING_RESET(stack);
    ENTER_CHAR(stack, wanted = last);

    VSTRING_ADDCH(arg->vstrval, start);
    for (;;) {
	if ((c = *cp) == 0)
	    break;
	cp++;
	VSTRING_ADDCH(arg->vstrval, c);
	if (c == '\\') {			/* parse escape sequence */
	    if ((c = *cp) == 0)
		break;
	    cp++;
	    VSTRING_ADDCH(arg->vstrval, c);
	} else if (c == wanted) {		/* closing quote etc. */
	    if (VSTRING_LEN(stack) == 1)
		return (cp);
	    LEAVE_CHAR(stack, wanted);
	} else if (c == '"') {
	    ENTER_CHAR(stack, wanted = '"');	/* highest precedence */
	} else if (c == '<' && wanted == '>') {
	    ENTER_CHAR(stack, wanted = '>');	/* lowest precedence */
	}
    }
    arg->tokval = POP3D_TOK_ERROR;		/* missing end */
    return (cp);
}
Esempio n. 24
0
int     vstring_get_null(VSTRING *vp, VSTREAM *fp)
{
    int     c;

    VSTRING_RESET(vp);
    while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
	VSTRING_ADDCH(vp, c);
    VSTRING_TERMINATE(vp);
    return (c == 0 ? c : VSTRING_GET_RESULT(vp));
}
Esempio n. 25
0
VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
{
    int     ch;
    int     next;
    int     start;
    char   *cp;

    VSTRING_RESET(buf);

    /*
     * Ignore comment lines, all whitespace lines, and empty lines. Terminate
     * at EOF or at the beginning of the next logical line.
     */
    for (;;) {
	/* Read one line, possibly not newline terminated. */
	start = LEN(buf);
	while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
	    VSTRING_ADDCH(buf, ch);
	if (ch == '\n' && lineno != 0)
	    *lineno += 1;
	/* Ignore comment line, all whitespace line, or empty line. */
	for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++)
	     /* void */ ;
	if (cp == END(buf) || *cp == '#')
	    vstring_truncate(buf, start);
	/* Terminate at EOF or at the beginning of the next logical line. */
	if (ch == VSTREAM_EOF)
	    break;
	if (LEN(buf) > 0) {
	    if ((next = VSTREAM_GETC(fp)) != VSTREAM_EOF)
		vstream_ungetc(fp, next);
	    if (next != '#' && !ISSPACE(next))
		break;
	}
    }
    VSTRING_TERMINATE(buf);

    /*
     * Invalid input: continuing text without preceding text. Allowing this
     * would complicate "postconf -e", which implements its own multi-line
     * parsing routine. Do not abort, just warn, so that critical programs
     * like postmap do not leave behind a truncated table.
     */
    if (LEN(buf) > 0 && ISSPACE(*STR(buf))) {
	msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"",
		 VSTREAM_PATH(fp), STR(buf),
		 LEN(buf) > 30 ? "..." : "");
	return (readlline(buf, fp, lineno));
    }

    /*
     * Done.
     */
    return (LEN(buf) > 0 ? buf : 0);
}
Esempio n. 26
0
static void strip_address(VSTRING *vp, int start, TOK822 *addr)
{
    VSTRING *tmp;

    /*
     * Emit plain <address>. Discard any comments or phrases.
     */
    msg_warn("stripping too many comments from address: %.100s...",
	     printable(vstring_str(vp) + start, '?'));
    vstring_truncate(vp, start);
    VSTRING_ADDCH(vp, '<');
    if (addr) {
	tmp = vstring_alloc(100);
	tok822_internalize(tmp, addr, TOK822_STR_TERM);
	quote_822_local_flags(vp, vstring_str(tmp),
			      QUOTE_FLAG_8BITCLEAN | QUOTE_FLAG_APPEND);
	vstring_free(tmp);
    }
    VSTRING_ADDCH(vp, '>');
}
Esempio n. 27
0
static VSTRING *make_822_quoted_string(VSTRING *dst, const char *local_part,
				               const char *end, int flags)
{
    const char *cp;
    int     ch;

    /*
     * Put quotes around the result, and prepend a backslash to characters
     * that need quoting when they occur in a quoted-string.
     */
    VSTRING_ADDCH(dst, '"');
    for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
	if ((ch > 127 && !(flags & QUOTE_FLAG_8BITCLEAN))
	    || ch == '"' || ch == '\\' || ch == '\r')
	    VSTRING_ADDCH(dst, '\\');
	VSTRING_ADDCH(dst, ch);
    }
    VSTRING_ADDCH(dst, '"');
    return (dst);
}
Esempio n. 28
0
static void smtp_key_append_str(VSTRING *buffer, const char *str,
				        const char *delim_na)
{
    if (str == 0 || str[0] == 0) {
	smtp_key_append_na(buffer, delim_na);
    } else if (str[strcspn(str, delim_na)] != 0) {
	base64_encode_opt(buffer, str, strlen(str), BASE64_FLAG_APPEND);
	VSTRING_ADDCH(buffer, delim_na[0]);
    } else {
	vstring_sprintf_append(buffer, "%s%c", str, delim_na[0]);
    }
}
Esempio n. 29
0
int     vstring_get(VSTRING *vp, VSTREAM *fp)
{
    int     c;

    VSTRING_RESET(vp);
    while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
	VSTRING_ADDCH(vp, c);
	if (c == '\n')
	    break;
    }
    VSTRING_TERMINATE(vp);
    return (VSTRING_GET_RESULT(vp));
}
Esempio n. 30
0
int     vstring_get_null_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound)
{
    int     c;

    if (bound <= 0)
	msg_panic("vstring_get_nonl_bound: invalid bound %ld", (long) bound);

    VSTRING_RESET(vp);
    while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
	VSTRING_ADDCH(vp, c);
    VSTRING_TERMINATE(vp);
    return (c == 0 ? c : VSTRING_GET_RESULT(vp));
}