popser.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,045 行 · 第 1/3 页
C
2,045 行
/* popser.c - the POP service */#ifndef lintstatic char ident[]="@(#)$Id: popser.c,v 1.1 90/07/20 11:26:30 sharpe Exp Locker: sharpe $";#endif#include "../h/mh.h"#include "../h/dropsbr.h"#include "../zotnet/bboards.h"#include <stdio.h>#include "../zotnet/mts.h"#include <ctype.h>#include <errno.h>#include <pwd.h>#include <signal.h>#include "syslog.h"#include <sys/types.h>#include <sys/stat.h>#ifdef SYS5#include <fcntl.h>#endif SYS5#ifdef SHADOW#include <shadow.h>#endif SHADOW#define TRUE 1#define FALSE 0#define NVEC 4#ifndef POPSERVICE#define POPSERVICE "pop"#endif/* */extern int errno;extern int debug;extern char myhost[];extern char *myname;#ifndef POP2static enum state { auth1, auth2, trans, update, halt, error} mystate;#elsestatic enum state { auth1, auth2, trans, mbox, item, ack, update, halt, error} mystate;#endifstatic int user (), pass ();#ifdef BPOPstatic isguest(), getbbmax();static int xtnd1(), xtnd2();#endif BPOP#ifdef RPOPstatic int rpop ();#endif RPOPstatic int status (), list (), retrieve (), delete (), reset ();static int top (), last ();#ifdef BPOPint xtnd ();#endif BPOPstatic int quit ();#ifdef POP2static int helo (), rdp2 (), acks (), ack2 (), fold (), nack ();#endif POP2static struct vector { char *v_cmd; int v_min, v_max; int (*v_vec) (); enum state v_valid; enum state v_win, v_lose;} vectors[] = { "user", 1, 1, user, auth1, auth2, auth1, "pass", 1, 1, pass, auth2, trans, auth1,#ifdef RPOP "rpop", 1, 1, rpop, auth2, trans, auth1,#endif RPOP "quit", 0, 0, NULL, auth1, halt, halt, "quit", 0, 0, NULL, auth2, halt, halt, "stat", 0, 0, status, trans, trans, trans, "list", 0, 1, list, trans, trans, trans, "retr", 1, 1, retrieve, trans, trans, trans, "dele", 1, 1, delete, trans, trans, trans, "noop", 0, 0, NULL, trans, trans, trans, "rset", 0, 0, reset, trans, trans, trans, "top", 2, 2, top, trans, trans, trans, "last", 0, 0, last, trans, trans, trans,#ifdef BPOP "xtnd", 1, 2, xtnd, trans, trans, trans,#endif BPOP "quit", 0, 0, quit, trans, halt, halt,#ifdef POP2 "helo", 2, 2, helo, auth1, mbox, auth1, "fold", 1, 1, fold, mbox, mbox, mbox, "quit", 0, 0, quit, mbox, halt, halt, "read", 0, 1, rdp2, mbox, item, error, "fold", 1, 1, fold, item, mbox, mbox, "read", 0, 1, rdp2, item, item, error, "quit", 0, 0, quit, item, halt, halt, "retr", 0, 0, retrieve, item, ack, error, "acks", 0, 0, ack2, ack, item, error, "ackd", 0, 0, ack2, ack, item, error, "nack", 0, 0, rdp2, ack, item, error, "quit", 0, 0, NULL, ack, halt, halt,#endif POP2 NULL};static struct vector *getvector ();/* */#ifdef POP2static int pop2 = NOTOK; /* current pop2 msg, or NOTOK if pop3 */#endif POP2#ifdef DPOPstatic int pop_uid;static int pop_gid;#endif DPOPstatic int rproto;static char *hostname;static char server[BUFSIZ];static char username[BUFSIZ];static char maildrop[BUFSIZ];static int mode;static time_t mtime;static FILE *dp;static long lastseen;static int rmsgs;#ifdef BPOPstatic int xtnded;static int guest_uid;static int guest_gid;static struct bboard *BBhead = NULL;static struct bboard *BBtail = NULL;static long BBtime = 0L;struct bboard *getbbaux ();#endif BPOPstruct Msg { /* Msgs[0] contains info for entire maildrop */ struct drop m_drop;#define m_id m_drop.d_id#define m_size m_drop.d_size#define m_last m_drop.d_start /* Msgs[i = 0] */#define m_start m_drop.d_start /* Msgs[i > 0] */#define m_stop m_drop.d_stop unsigned m_flags;#define MNULL 0x00#define MDELE 0x01#define MREAD 0x02};static int nMsgs = 0;static struct Msg *Msgs = NULL;static int nmsgs;static int dmsgs;#define TRM "."#define TRMLEN (sizeof TRM - 1)#define IAC 255static int pipeser ();FILE *input;FILE *output;void padvise (), padios ();long lseek ();char *crypt ();#ifdef POPUUMBOX#define MBX_READ pmbx_readstatic int pmbx_read ();static char *p_copy(), *p_copyin(), *p_nextword();static p_cmatch(), p_isdate(), p_ishead(), p_parse(), any();#else#define MBX_READ mbx_readextern int mbx_read ();#endifstatic int setup(), setupaux(), read_map(), read_file(), pmbx_size();static int quitaux(), quitfile(), respond(), getline();static m_gMsgs(), multiline(), multiend(), putline();/* */popinit () {#ifdef BPOP padvise (NULLCP, LOG_INFO, "initialize list of BBoards"); BBhead = BBtail = NULL; while (getbbaux (NULLCP)) continue;#endif BPOP}popassert () {#ifdef BPOP register char **p; register struct bboard *bb, *bp; if (BBtime == getbbtime ()) return; padvise (NULLCP, LOG_INFO, "list of BBoards has changed"); for (bb = BBhead; bb; bb = bp) { bp = bb -> bb_next; if (bb -> bb_name) free (bb -> bb_name); if (bb -> bb_file) free (bb -> bb_file); if (bb -> bb_archive) free (bb -> bb_archive); if (bb -> bb_info) free (bb -> bb_info); if (bb -> bb_map) free (bb -> bb_map); if (bb -> bb_passwd) free (bb -> bb_passwd); if (bb -> bb_date) free (bb -> bb_date); if (bb -> bb_addr) free (bb -> bb_addr); if (bb -> bb_request) free (bb -> bb_request); if (bb -> bb_relay) free (bb -> bb_relay); for (p = bb -> bb_aka; *p; p++) free (*p); free ((char *) bb -> bb_aka); for (p = bb -> bb_leader; *p; p++) free (*p); free ((char *) bb -> bb_leader); for (p = bb -> bb_dist; *p; p++) free (*p); free ((char *) bb -> bb_dist); free ((char *) bb); } BBhead = BBtail = NULL; while (getbbaux (NULLCP)) continue;#endif BPOP}/* */pop (in, out, priv, rhost)int in, out, priv;char *rhost;{ char buffer[BUFSIZ], *vec[NVEC + 1];#if defined (DPOP) || defined (BPOP) register struct passwd *pw;#endif defined (DPOP) || defined (BPOP) register struct vector *v; m_foil (NULLCP); mts_init (myname); rproto = priv; hostname = rhost; (void) sprintf (server, "%s %s server", myhost, priv ? "RPOP" : "POP"); if ((input = fdopen (in, "r")) == NULL || (output = fdopen (out, "w")) == NULL) {/* you lose big */ (void) respond (NOTOK, "%s loses on initialization", server); return; } (void) signal (SIGPIPE, pipeser);#ifdef DPOP if ((pw = getpwnam (POPUID)) == NULL || !setpwinfo (pw, POPDB, 1)) { (void) respond (NOTOK, "%s loses on DB initialization -- %s", server, pw ? getbberr () : "POP user-id unknown"); return; } pop_uid = pw -> pw_uid; pop_gid = pw -> pw_gid;#endif DPOP#ifdef BPOP if ((pw = getpwnam (popbbuser)) && pw -> pw_uid) { guest_uid = pw -> pw_uid; guest_gid = pw -> pw_gid; } else guest_uid = guest_gid = 0;#endif BPOP (void) respond (OK, "%s ready (Comments to: PostMaster@%s)", server, myhost); for (mystate = auth1; mystate != halt && mystate != error;) switch (getline (buffer, sizeof buffer, input)) { case OK: if ((v = getvector (buffer, vec)) == NULL) continue; mystate = (v -> v_vec ? (v -> v_vec) (vec) : respond (OK, NULLCP)) == OK ? v -> v_win : v -> v_lose; break; case NOTOK: case DONE: mystate = error; (void) respond (NOTOK, "%s signing off", server); break; }}/* */#ifdef POP2static int helo (vec) /* sort of "user" and "pass" */register char **vec;{ pop2 = 0; /* now we're talkin' pop2! */ make_lower (username, vec[1]); /* helo user pass */ return pass (++vec); /* user pass */}#endifstatic int user (vec)register char **vec;{ make_lower (username, vec[1]); return respond (OK, "password required for '%s'", username);}/* */static int pass (vec)register char **vec;{ int guest = 0;#ifndef DPOP register struct passwd *pw;#ifdef SHADOW register struct spwd *shpw;#endif SHADOW#else DPOP register struct bboard *pw;#endif DPOP#ifndef DPOP#ifdef BPOP if (isguest ()) {#ifdef TRUSTED static passwd gw; gw.pw_name = popbbuser; gw.pw_uid = guest_uid; pw = &gw;#endif TRUSTED guest = 1; goto anonymous; }#endif BPOP if ((pw = getpwnam (username)) == NULL#ifndef SHADOW || *pw -> pw_passwd == NULL || strcmp (crypt (vec[1], pw -> pw_passwd), pw -> pw_passwd)) {#else SHADOW || (shpw = getspnam (username)) == NULL || *shpw -> sp_pwdp == NULL || strcmp (crypt (vec[1], shpw -> sp_pwdp), shpw -> sp_pwdp)) {#endif SHADOW#ifdef TRUSTED trusted (0, hostname, NULLCP, 0, pw ? pw -> pw_name : username, pw && pw -> pw_uid == 0, POPSERVICE, "tcp", NULL);#endif TRUSTED return respond (NOTOK, "login incorrect"); }#else DPOP#ifdef BPOP if (isguest ()) { static struct bboard gw; gw.bb_name = popbbuser; pw = &gw; guest = 1; goto anonymous; }#endif BPOP if (((pw = getbbnam (username)) == NULL && (pw = getbbaka (username)) == NULL) || *pw -> bb_passwd == NULL || strcmp (crypt (vec[1], pw -> bb_passwd), pw -> bb_passwd)) {#ifdef TRUSTED trusted (0, hostname, NULLCP, 0, pw ? pw -> bb_name : username, 0, POPSERVICE, "tcp", NULL);#endif TRUSTED return respond (NOTOK, "login incorrect"); }#endif DPOP#ifdef BPOPanonymous: ;#endif BPOP#ifdef TRUSTED if (trusted (1, hostname, NULLCP, 0, myhost,#ifndef DPOP pw -> pw_name, pw -> pw_uid == 0,#else DPOP pw -> bb_name, 0,#endif DPOP POPSERVICE, "tcp", NULL) == 0) return respond (NOTOK, "permission denied");#endif TRUSTED return setup (pw, guest);}/* */#ifdef BPOPstatic isguest () { int i; register char *cp; char buffer[BUFSIZ]; register FILE *fp; if (strcmp (username, popbbuser) || !guest_uid) return FALSE; if (popbblist == NULL || (fp = fopen (popbblist, "r")) == NULL) return TRUE; i = FALSE; if (hostname) while (fgets (buffer, sizeof buffer, fp)) { if (cp = index (buffer, '\n')) *cp = NULL; if (strcmp (buffer, hostname) == 0) { i = TRUE; break; } } (void) fclose (fp); return i;}#endif BPOP/* */#ifdef RPOPstatic int rpop (vec)register char **vec;{#ifndef DPOP register struct passwd *pw;#else DPOP register int hostok = 0; register char *bp, *cp; char buffer[BUFSIZ]; register struct bboard *pw;#endif DPOP#ifndef DPOP if (!rproto || (pw = getpwnam (username)) == NULL) {#ifdef TRUSTED trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp", NULL);#endif TRUSTED return respond (NOTOK, "login incorrect"); } if (chdir (pw -> pw_dir) == NOTOK && chdir ("/") == NOTOK) return respond (NOTOK, "no remote directory"); if (ruserok (hostname, pw -> pw_uid == 0, vec[1], username) == NOTOK) {#ifdef TRUSTED trusted (0, hostname, vec[1], 0, pw -> pw_name, pw -> pw_uid == 0, "rpop", "tcp", NULL);#endif TRUSTED return respond (NOTOK, "permission denied"); }#else DPOP if (!rproto || ((pw = getbbnam (username)) == NULL && (pw = getbbaka (username)) == NULL)) {#ifdef TRUSTED trusted (0, hostname, vec[1], 0, username, 0, "rpop", "tcp", NULL);#endif TRUSTED return respond (NOTOK, "login incorrect"); }/* * hacked by Dave Cohrs Tue Feb 4 14:12:15 CST 1986 * to allow the hostname to be a list: user@host1,user@host2 * NOTE: the separator must be a comma -- no spaces are allowed */ (void) sprintf (buffer, "%s@%s", vec[1], hostname); for (bp = pw -> bb_addr; bp; bp = cp) { if ((cp = index (bp, ','))) *cp = NULL; hostok = uleq (bp, buffer); if (cp) *cp++ = ','; if (hostok) break; } if (!hostok) {#ifdef TRUSTED trusted (0, hostname, vec[1], 0, pw -> bb_name, 0, "rpop", "tcp", NULL);#endif TRUSTED return respond (NOTOK, "permission denied"); }#endif DPOP#ifdef TRUSTED if (trusted (1, hostname, vec[1], 0, username,#ifndef DPOP pw -> pw_uid == 0,#else DPOP 0,#endif DPOP "rpop", "tcp", NULL) == 0) return respond (NOTOK, "permission denied");#endif TRUSTED return setup (pw, FALSE);}#endif RPOP/* */static int setup (pw, guest)#ifndef DPOPregister struct passwd *pw;#else DPOPregister struct bboard *pw;#endif DPOPint guest;{#ifdef BPOP if (guest) { (void) setgid (guest_gid);#ifndef SYS5 (void) initgroups (popbbuser, guest_gid);#endif SYS5 (void) setuid (guest_uid); } else {#endif BPOP#ifndef DPOP (void) setgid (pw -> pw_gid);#ifndef SYS5 (void) initgroups (pw -> pw_name, pw -> pw_gid);#endif SYS5 (void) setuid (pw -> pw_uid);#else DPOP (void) setgid (pop_gid);#ifndef SYS5 (void) initgroups (POPUID, pop_gid);#endif SYS5 (void) setuid (pop_uid);#endif DPOP#ifdef BPOP }#endif BPOP#ifndef DPOP (void) sprintf (maildrop, "%s/%s", mmdfldir && *mmdfldir ? mmdfldir : pw -> pw_dir, mmdflfil && *mmdflfil ? mmdflfil : pw -> pw_name);#else DPOP (void) strcpy (maildrop, pw -> bb_file);#endif DPOP if (setupaux (guest) == NOTOK) return NOTOK;#ifdef POP2 if (pop2 != NOTOK) { /* in response to pop2 "helo" */ pop2 = nmsgs > 0 ? 1 : 0; return respond ('#', "%d message%s (%d octets)", nmsgs, nmsgs != 1 ? "s" : "", Msgs[0].m_size); } else#endif POP2 return respond (OK, nmsgs ? "maildrop has %d message%s (%d octets)" : "maildrop empty", nmsgs, nmsgs != 1 ? "s" : "", Msgs[0].m_size);}/* */static int setupaux (readonly)int readonly;{ register int i, msgp; struct stat st;#ifdef BPOP xtnded = 0;#endif BPOP if ((dp = readonly ? fopen (maildrop, "r") : lkfopen (maildrop, "r")) == NULL) switch (errno) { case ENOENT: m_gMsgs (msgp = 0); goto no_mail; default: nmsgs = dmsgs = 0; return respond (NOTOK, "unable to %s maildrop: \"%s\"", readonly ? "read" : "lock", maildrop); } if (fstat (fileno (dp), &st) != NOTOK) { mode = (int) (st.st_mode & 0777), mtime = st.st_mtime; msgp = read_map (maildrop, (long) st.st_size); } else { mode = 0600, mtime = 0; msgp = 0; } if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1) m_gMsgs (0);no_mail: ; lastseen = Msgs[0].m_last;if(debug)padvise(NULLCP,LOG_DEBUG,"XXX: lastseen=%d",lastseen); dmsgs = rmsgs = 0; nmsgs = msgp; Msgs[0].m_flags = readonly ? MREAD : MNULL; Msgs[0].m_size = 0; for (i = 1; i <= nmsgs; i++) { if (Msgs[i].m_size == 0) Msgs[i].m_size = pmbx_size (i); Msgs[0].m_size += Msgs[i].m_size; Msgs[i].m_flags = MNULL; } return OK;}/* */static int read_map (file, pos)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?