Example #1
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);
}
Example #2
0
static const char *dict_tcp_lookup(DICT *dict, const char *key)
{
    DICT_TCP *dict_tcp = (DICT_TCP *) dict;
    const char *myname = "dict_tcp_lookup";
    int     tries;
    char   *start;
    int     last_ch;

#define RETURN(errval, result) { dict_errno = errval; return (result); }

    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(10);
	vstring_strcpy(dict->fold_buf, key);
	key = lowercase(vstring_str(dict->fold_buf));
    }
    for (tries = 0; /* see below */ ; /* see below */ ) {

	/*
	 * Connect to the server, or use an existing connection.
	 */
	if (dict_tcp->fp != 0 || dict_tcp_connect(dict_tcp) == 0) {

	    /*
	     * Send request and receive response. Both are %XX quoted and
	     * both are terminated by newline. This encoding is convenient
	     * for data that is mostly text.
	     */
	    hex_quote(dict_tcp->hex_buf, key);
	    vstream_fprintf(dict_tcp->fp, "get %s\n", STR(dict_tcp->hex_buf));
	    if (msg_verbose)
		msg_info("%s: send: get %s", myname, STR(dict_tcp->hex_buf));
	    last_ch = vstring_get_nonl_bound(dict_tcp->hex_buf, dict_tcp->fp,
					     DICT_TCP_MAXLEN);
	    if (last_ch == '\n')
		break;

	    /*
	     * Disconnect from the server if it can't talk to us.
	     */
	    if (last_ch < 0)
		msg_warn("read TCP map reply from %s: unexpected EOF (%m)",
			 dict_tcp->dict.name);
	    else
		msg_warn("read TCP map reply from %s: text longer than %d",
			 dict_tcp->dict.name, DICT_TCP_MAXLEN);
	    dict_tcp_disconnect(dict_tcp);
	}

	/*
	 * Try to connect a limited number of times before giving up.
	 */
	if (++tries >= DICT_TCP_MAXTRY)
	    RETURN(DICT_ERR_RETRY, 0);

	/*
	 * Sleep between attempts, instead of hammering the server.
	 */
	sleep(1);
    }
    if (msg_verbose)
	msg_info("%s: recv: %s", myname, STR(dict_tcp->hex_buf));

    /*
     * Check the general reply syntax. If the reply is malformed, disconnect
     * and try again later.
     */
    if (start = STR(dict_tcp->hex_buf),
	!ISDIGIT(start[0]) || !ISDIGIT(start[1])
	|| !ISDIGIT(start[2]) || !ISSPACE(start[3])
	|| !hex_unquote(dict_tcp->raw_buf, start + 4)) {
	msg_warn("read TCP map reply from %s: malformed reply: %.100s",
	       dict_tcp->dict.name, printable(STR(dict_tcp->hex_buf), '_'));
	dict_tcp_disconnect(dict_tcp);
	RETURN(DICT_ERR_RETRY, 0);
    }

    /*
     * Examine the reply status code. If the reply is malformed, disconnect
     * and try again later.
     */
    switch (start[0]) {
    default:
	msg_warn("read TCP map reply from %s: bad status code: %.100s",
	       dict_tcp->dict.name, printable(STR(dict_tcp->hex_buf), '_'));
	dict_tcp_disconnect(dict_tcp);
	RETURN(DICT_ERR_RETRY, 0);
    case '4':
	if (msg_verbose)
	    msg_info("%s: soft error: %s",
		     myname, printable(STR(dict_tcp->hex_buf), '_'));
	dict_tcp_disconnect(dict_tcp);
	RETURN(DICT_ERR_RETRY, 0);
    case '5':
	if (msg_verbose)
	    msg_info("%s: not found: %s",
		     myname, printable(STR(dict_tcp->hex_buf), '_'));
	RETURN(DICT_ERR_NONE, 0);
    case '2':
	if (msg_verbose)
	    msg_info("%s: found: %s",
		     myname, printable(STR(dict_tcp->raw_buf), '_'));
	RETURN(DICT_ERR_NONE, STR(dict_tcp->raw_buf));
    }
}