int memcache_get(VSTREAM *stream, VSTRING *vp, ssize_t bound) { int last_char; int next_char; last_char = (bound == 0 ? vstring_get(vp, stream) : vstring_get_bound(vp, stream, bound)); switch (last_char) { /* * Do some repair in the rare case that we stopped reading in the * middle of the CRLF record terminator. */ case '\r': if ((next_char = VSTREAM_GETC(stream)) == '\n') { VSTRING_ADDCH(vp, '\n'); /* FALLTRHOUGH */ } else { if (next_char != VSTREAM_EOF) vstream_ungetc(stream, next_char); /* * Input too long, or EOF */ default: if (msg_verbose) msg_info("%s got %s", VSTREAM_PATH(stream), LEN(vp) < bound ? "EOF" : "input too long"); return (-1); } /* * Strip off the record terminator: either CRLF or just bare LF. */ case '\n': vstring_truncate(vp, VSTRING_LEN(vp) - 1); if (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r') vstring_truncate(vp, VSTRING_LEN(vp) - 1); VSTRING_TERMINATE(vp); if (msg_verbose) msg_info("%s got: %s", VSTREAM_PATH(stream), STR(vp)); return (0); } }
int smtp_get(VSTRING *vp, VSTREAM *stream, int bound) { int last_char; int next_char; /* * It's painful to do I/O with records that may span multiple buffers. * Allow for partial long lines (we will read the remainder later) and * allow for lines ending in bare LF. The idea is to be liberal in what * we accept, strict in what we send. * * XXX 2821: Section 4.1.1.4 says that an SMTP server must not recognize * bare LF as record terminator. */ smtp_timeout_reset(stream); last_char = (bound == 0 ? vstring_get(vp, stream) : vstring_get_bound(vp, stream, bound)); switch (last_char) { /* * Do some repair in the rare case that we stopped reading in the * middle of the CRLF record terminator. */ case '\r': if ((next_char = VSTREAM_GETC(stream)) == '\n') { VSTRING_ADDCH(vp, '\n'); last_char = '\n'; /* FALLTRHOUGH */ } else { if (next_char != VSTREAM_EOF) vstream_ungetc(stream, next_char); break; } /* * Strip off the record terminator: either CRLF or just bare LF. * * XXX RFC 2821 disallows sending bare CR everywhere. We remove bare CR * if received before CRLF, and leave it alone otherwise. */ case '\n': vstring_truncate(vp, VSTRING_LEN(vp) - 1); while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r') vstring_truncate(vp, VSTRING_LEN(vp) - 1); VSTRING_TERMINATE(vp); /* * Partial line: just read the remainder later. If we ran into EOF, * the next test will deal with it. */ default: break; } smtp_timeout_detect(stream); /* * EOF is bad, whether or not it happens in the middle of a record. Don't * allow data that was truncated because of EOF. */ if (vstream_feof(stream) || vstream_ferror(stream)) { if (msg_verbose) msg_info("smtp_get: EOF"); vstream_longjmp(stream, SMTP_ERR_EOF); } return (last_char); }