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 + -
显示快捷键?