--from implementation from <lha@stacken.kth.se>

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@5187 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Assar Westerlund
1998-11-07 14:50:12 +00:00
parent fe95a0b657
commit 4997b65eed

View File

@@ -54,6 +54,8 @@ static int do_fork;
static int do_leave; static int do_leave;
static int do_version; static int do_version;
static int do_help; static int do_help;
static int do_from;
static char *header_str;
struct getargs args[] = { struct getargs args[] = {
#ifdef KRB4 #ifdef KRB4
@@ -72,6 +74,9 @@ struct getargs args[] = {
NULL }, NULL },
{ "port", 'p', arg_string, &port_str, "Use this port", { "port", 'p', arg_string, &port_str, "Use this port",
"number-or-service" }, "number-or-service" },
{ "from", 0, arg_flag, &do_from, "Behave like from",
NULL },
{ "header", 0, arg_string, &header_str, "Header string to print", NULL },
{ "version", 0, arg_flag, &do_version, "Print version", { "version", 0, arg_flag, &do_version, "Print version",
NULL }, NULL },
{ "help", 0, arg_flag, &do_help, NULL, { "help", 0, arg_flag, &do_help, NULL,
@@ -128,7 +133,8 @@ do_connect (char *host, int port, int nodelay)
} }
} }
typedef enum { INIT = 0, GREAT, USER, PASS, STAT, RETR, DELE, QUIT } pop_state; typedef enum { INIT = 0, GREAT, USER, PASS, STAT, RETR, TOP,
DELE, QUIT } pop_state;
#define PUSH_BUFSIZ 65536 #define PUSH_BUFSIZ 65536
@@ -198,6 +204,7 @@ doit(int s,
char *host, char *host,
char *user, char *user,
char *outfilename, char *outfilename,
char *header_str,
int leavep, int leavep,
int verbose, int verbose,
int forkp) int forkp)
@@ -205,7 +212,6 @@ doit(int s,
int ret; int ret;
char out_buf[PUSH_BUFSIZ]; char out_buf[PUSH_BUFSIZ];
size_t out_len = 0; size_t out_len = 0;
char *out_ptr = out_buf;
char in_buf[PUSH_BUFSIZ + 1]; /* sentinel */ char in_buf[PUSH_BUFSIZ + 1]; /* sentinel */
size_t in_len = 0; size_t in_len = 0;
char *in_ptr = in_buf; char *in_ptr = in_buf;
@@ -218,12 +224,17 @@ doit(int s,
time_t now; time_t now;
struct write_state write_state; struct write_state write_state;
out_fd = open(outfilename, O_WRONLY | O_APPEND | O_CREAT, 0666); if (do_from) {
if (out_fd < 0) out_fd = -1;
err (1, "open %s", outfilename); if (verbose)
fprintf (stderr, "%s@%s\n", user, host);
if (verbose) } else {
fprintf (stderr, "%s@%s -> %s\n", user, host, outfilename); out_fd = open(outfilename, O_WRONLY | O_APPEND | O_CREAT, 0666);
if (out_fd < 0)
err (1, "open %s", outfilename);
if (verbose)
fprintf (stderr, "%s@%s -> %s\n", user, host, outfilename);
}
now = time(NULL); now = time(NULL);
from_line_length = snprintf (from_line, sizeof(from_line), from_line_length = snprintf (from_line, sizeof(from_line),
@@ -237,7 +248,8 @@ doit(int s,
if (verbose > 1) if (verbose > 1)
write (STDERR_FILENO, out_buf, out_len); write (STDERR_FILENO, out_buf, out_len);
write_state_init (&write_state, out_fd); if (!do_from)
write_state_init (&write_state, out_fd);
while(state != QUIT) { while(state != QUIT) {
fd_set readset, writeset; fd_set readset, writeset;
@@ -245,15 +257,17 @@ doit(int s,
FD_ZERO(&readset); FD_ZERO(&readset);
FD_ZERO(&writeset); FD_ZERO(&writeset);
FD_SET(s,&readset); FD_SET(s,&readset);
if ((state == STAT || state == RETR) && asked_for < count if (((state == STAT || state == RETR || state == TOP)
&& asked_for < count)
|| (state == DELE && asked_deleted < count)) || (state == DELE && asked_deleted < count))
FD_SET(s,&writeset); FD_SET(s,&writeset);
ret = select (s + 1, &readset, &writeset, NULL, NULL); ret = select (s + 1, &readset, &writeset, NULL, NULL);
if (ret < 0) if (ret < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
continue; continue;
else else
err (1, "select"); err (1, "select");
}
if (FD_ISSET(s, &readset)) { if (FD_ISSET(s, &readset)) {
char *beg, *p; char *beg, *p;
@@ -274,9 +288,27 @@ doit(int s,
rem = in_len; rem = in_len;
while(rem > 1 while(rem > 1
&& (p = strstr(beg, "\r\n")) != NULL) { && (p = strstr(beg, "\r\n")) != NULL) {
if (state == RETR) { if (state == TOP) {
char *copy = beg; char *copy = beg;
if (strncmp(copy,
header_str,
min(p - copy + 1, strlen(header_str))) == 0) {
fprintf (stdout, "%.*s\n", p - copy, copy);
}
if (beg[0] == '.' && beg[1] == '\r' && beg[2] == '\n') {
state = STAT;
if (++retrieved == count) {
state = QUIT;
net_write (s, "QUIT\r\n", 6);
if (verbose > 1)
net_write (STDERR_FILENO, "QUIT\r\n", 6);
}
}
rem -= p - beg + 2;
beg = p + 2;
} else if (state == RETR) {
char *copy = beg;
if (beg[0] == '.') { if (beg[0] == '.') {
if (beg[1] == '\r' && beg[2] == '\n') { if (beg[1] == '\r' && beg[2] == '\n') {
if(!blank_line) if(!blank_line)
@@ -328,10 +360,14 @@ doit(int s,
beg = p + 2; beg = p + 2;
} else if (rem >= 3 && strncmp (beg, "+OK", 3) == 0) { } else if (rem >= 3 && strncmp (beg, "+OK", 3) == 0) {
if (state == STAT) { if (state == STAT) {
write_state_add(&write_state, if (!do_from)
from_line, from_line_length); write_state_add(&write_state,
from_line, from_line_length);
blank_line = 0; blank_line = 0;
state = RETR; if (do_from)
state = TOP;
else
state = RETR;
} else if (state == DELE) { } else if (state == DELE) {
if (++deleted == count) { if (++deleted == count) {
state = QUIT; state = QUIT;
@@ -361,16 +397,20 @@ doit(int s,
} else } else
errx (1, "Bad response: %.*s", p - beg, beg); errx (1, "Bad response: %.*s", p - beg, beg);
} }
write_state_flush (&write_state); if (!do_from)
write_state_flush (&write_state);
memmove (in_buf, beg, rem); memmove (in_buf, beg, rem);
in_len = rem; in_len = rem;
in_ptr = in_buf + rem; in_ptr = in_buf + rem;
} }
if (FD_ISSET(s, &writeset)) { if (FD_ISSET(s, &writeset)) {
if (state == STAT || state == RETR) if ((state == STAT && !do_from) || state == RETR)
out_len = snprintf (out_buf, sizeof(out_buf), out_len = snprintf (out_buf, sizeof(out_buf),
"RETR %u\r\n", ++asked_for); "RETR %u\r\n", ++asked_for);
else if ((state == STAT && do_from) || state == TOP)
out_len = snprintf (out_buf, sizeof(out_buf),
"TOP %u 0\r\n", ++asked_for);
else if(state == DELE) else if(state == DELE)
out_len = snprintf (out_buf, sizeof(out_buf), out_len = snprintf (out_buf, sizeof(out_buf),
"DELE %u\r\n", ++asked_deleted); "DELE %u\r\n", ++asked_deleted);
@@ -382,7 +422,8 @@ doit(int s,
} }
if (verbose) if (verbose)
fprintf (stderr, "Done\n"); fprintf (stderr, "Done\n");
write_state_destroy (&write_state); if (!do_from)
write_state_destroy (&write_state);
return 0; return 0;
} }
@@ -392,6 +433,7 @@ do_v5 (char *host,
int port, int port,
char *user, char *user,
char *filename, char *filename,
char *header_str,
int leavep, int leavep,
int verbose, int verbose,
int forkp) int forkp)
@@ -442,7 +484,7 @@ do_v5 (char *host,
krb5_get_err_text (context, ret)); krb5_get_err_text (context, ret));
return 1; return 1;
} }
return doit (s, host, user, filename, leavep, verbose, forkp); return doit (s, host, user, filename, header_str, leavep, verbose, forkp);
} }
#endif #endif
@@ -452,6 +494,7 @@ do_v4 (char *host,
int port, int port,
char *user, char *user,
char *filename, char *filename,
char *header_str,
int leavep, int leavep,
int verbose, int verbose,
int forkp) int forkp)
@@ -483,7 +526,7 @@ do_v4 (char *host,
warnx("krb_sendauth: %s", krb_get_err_text(ret)); warnx("krb_sendauth: %s", krb_get_err_text(ret));
return 1; return 1;
} }
return doit (s, host, user, filename, leavep, verbose, forkp); return doit (s, host, user, filename, header_str, leavep, verbose, forkp);
} }
#endif /* KRB4 */ #endif /* KRB4 */
@@ -509,7 +552,7 @@ parse_pobox (char *a0, char *a1,
*u++ = '\0'; *u++ = '\0';
else else
u = a0; u = a0;
if(h == u) if(h == u) {
/* some inconsistent compatibility with various mailers */ /* some inconsistent compatibility with various mailers */
if(po) { if(po) {
h = getenv("MAILHOST"); h = getenv("MAILHOST");
@@ -521,6 +564,7 @@ parse_pobox (char *a0, char *a1,
errx (1, "Who are you?"); errx (1, "Who are you?");
u = strdup(pwd->pw_name); u = strdup(pwd->pw_name);
} }
}
*host = h; *host = h;
*user = u; *user = u;
*filename = f; *filename = f;
@@ -566,9 +610,14 @@ main(int argc, char **argv)
return 0; return 0;
} }
if (argc != 2) if (argc != 2 && (do_from && argc != 1))
usage (1); usage (1);
if (do_from && header_str == NULL)
header_str = "From:";
else if (header_str != NULL)
do_from = 1;
if (port_str) { if (port_str) {
struct servent *s = roken_getservbyname (port_str, "tcp"); struct servent *s = roken_getservbyname (port_str, "tcp");
@@ -597,14 +646,14 @@ main(int argc, char **argv)
#ifdef KRB5 #ifdef KRB5
if (ret && use_v5) { if (ret && use_v5) {
ret = do_v5 (host, port, user, filename, ret = do_v5 (host, port, user, filename, header_str,
do_leave, do_verbose, do_fork); do_leave, do_verbose, do_fork);
} }
#endif #endif
#ifdef KRB4 #ifdef KRB4
if (ret && use_v4) { if (ret && use_v4) {
ret = do_v4 (host, port, user, filename, ret = do_v4 (host, port, user, filename, header_str,
do_leave, do_verbose, do_fork); do_leave, do_verbose, do_fork);
} }
#endif /* KRB4 */ #endif /* KRB4 */