⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slocal.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* slocal.c - MH style mailer to write to a local user's mailbox */#ifndef	lintstatic char ident[] = "@(#)$Id: slocal.c,v 1.24 1993/08/25 17:28:16 jromine Exp $";#endif	/* lint *//* This program implements mail delivery in the MH/MMDF style.   Under SendMail, users should add the line	"| /usr/local/lib/mh/slocal"   to their $HOME/.forward file.   Under MMDF-I, users should (symbolically) link /usr/local/lib/mh/slocal   to $HOME/bin/rcvmail.   Under stand-alone MH, post will automatically run this during local   delivery.   This program should be used ONLY if you have "mts sendmail" or "mts mh"   or "mts mmdf1" set in your MH configuration. *//*  */#include "../h/mh.h"#include "../h/dropsbr.h"#include "../h/rcvmail.h"#include "../zotnet/tws.h"#include "../zotnet/mts.h"#include <pwd.h>#include <signal.h>#ifndef	V7#ifndef	NOIOCTLH#include <sys/ioctl.h>#endif	/* NOIOCTLH */#endif	/* not V7 */#include <sys/stat.h>#include <utmp.h>#ifdef LOCALE#include	<locale.h>#endif#ifdef	MSGID#undef	DBM		/* used by ndbm.h */#include <ndbm.h>#include <stdio.h>#include <sys/types.h>#include <sys/file.h>#ifdef	SYS5#include <fcntl.h>#endif#ifdef UNISTD#include <unistd.h>#endif#if defined(LOCKF) && !defined(F_ULOCK)#include <sys/fcntl.h>#endif  /* LOCKF */#endif#define	NVEC	100/*  */static struct swit switches[] = {#define	ADDRSW	0    "addr address", 0,#define	USERSW	1    "user name", 0,#define	FILESW	2    "file file", 0,#define	SENDSW	3    "sender address", 0,#define	MBOXSW	4    "mailbox file", 0,#define	HOMESW	5    "home directory", -4,#define	INFOSW	6    "info data", 0,#define	MAILSW	7    "maildelivery file", 0,#define	VERBSW	8    "verbose", 0,#define	NVERBSW	9    "noverbose", 0,#define	DEBUGSW	10    "debug", 0,#define	HELPSW	11    "help", 4,    NULL, 0};/*  */static int  debug = 0;static int  globbed = 0;static int  parsed = 0;static int  utmped = 0;static int  verbose = 0;static char *addr = NULLCP;static char *user = NULLCP;static char *info = NULLCP;static char *file = NULLCP;static char *sender = NULLCP;static char *unixfrom = NULLCP;static char *mbox = NULLCP;static char *home = NULLCP;static struct passwd *pw;static char ddate[BUFSIZ];struct tws *now;static jmp_buf myctx;/*  */struct pair {    char   *p_name;    char   *p_value;    char    p_flags;#define	P_NIL	0x00#define	P_ADR	0x01#define	P_HID	0x02#define	P_CHK	0x04};static struct pair *lookup ();static struct pair  hdrs[NVEC + 1] = {    "source", NULL, P_HID,    "addr", NULL, P_HID,    "Return-Path", NULL, P_ADR,    "Reply-To", NULL, P_ADR,    "From", NULL, P_ADR,    "Sender", NULL, P_ADR,    "To", NULL, P_ADR,    "cc", NULL, P_ADR,    "Resent-Reply-To", NULL, P_ADR,    "Resent-From", NULL, P_ADR,    "Resent-Sender", NULL, P_ADR,    "Resent-To", NULL, P_ADR,    "Resent-cc", NULL, P_ADR,    NULL};static struct pair  vars[] = {    "sender", NULL, P_NIL,    "address", NULL, P_NIL,    "size", NULL, P_NIL,    "reply-to", NULL, P_CHK,    "info", NULL, P_NIL,    NULL};/*  */extern char **environ;static void	adorn ();static TYPESIG	alrmser ();off_t    lseek ();#ifndef	__STDC__#ifdef	SYS5struct passwd *getpwnam ();#endif	/* SYS5 */#endifstatic int	localmail(), usr_delivery(), split(), parse(), logged_in();static int	timely(), usr_file(), usr_pipe(), copyfile();static expand(), glob(), copyinfo();/*  *//* ARGSUSED */main (argc, argv, envp)int     argc;char  **argv,      **envp;{    int     fd;    FILE   *fp    = stdin;    char   *cp,	   *mdlvr = NULL,            buf[100],            from[BUFSIZ],            mailbox[BUFSIZ],            tmpfil[BUFSIZ],          **argp = argv + 1;#ifdef LOCALE	setlocale(LC_ALL, "");#endif    invo_name = r1bindex (*argv, '/');    m_foil (NULLCP);    mts_init (invo_name);/*  */    while (cp = *argp++) {	if (*cp == '-')	    switch (smatch (++cp, switches)) {		case AMBIGSW: 		    ambigsw (cp, switches);		    done (1);		case UNKWNSW: 		    adios (NULLCP, "-%s unknown", cp);		case HELPSW: 		    (void) sprintf (buf, "%s [switches] [address info sender]",			    invo_name);		    help (buf, switches);		    done (1);		case ADDRSW: 		    if (!(addr = *argp++))/* allow -xyz arguments */			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case INFOSW: 		    if (!(info = *argp++))/* allow -xyz arguments */			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case USERSW: 		    if (!(user = *argp++))/* allow -xyz arguments */			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case FILESW: 		    if (!(file = *argp++) || *file == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case SENDSW: 		    if (!(sender = *argp++))/* allow -xyz arguments */			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case MBOXSW: 		    if (!(mbox = *argp++) || *mbox == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case HOMESW: 		    if (!(home = *argp++) || *home == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    continue;		case MAILSW: 		    if (!(cp = *argp++) || *cp == '-')			adios (NULLCP, "missing argument to %s", argp[-2]);		    if (mdlvr)			adios (NULLCP, "only one maildelivery file at a time!");		    mdlvr = cp;		    continue;		case VERBSW: 		    verbose++;		    continue;		case NVERBSW: 		    verbose = 0;		    continue;		case DEBUGSW: 		    debug++;		    continue;	    }	switch (argp - (argv + 1)) {	    case 1: 		addr = cp;		break;	    case 2: 		info = cp;		break;	    case 3: 		sender = cp;		break;	}    }/*  */    if (addr == NULL)	addr = getusr ();    if (user == NULL)	user = (cp = index (addr, '.')) ? ++cp : addr;    if ((pw = getpwnam (user)) == NULL)	adios (NULLCP, "no such local user as %s", user);    if (chdir (pw -> pw_dir) == NOTOK)	(void) chdir ("/");    (void) umask (0077);    if (geteuid () == 0) {#ifdef	BSD41A	(void) inigrp (pw -> pw_name, pw -> pw_gid);#endif	/* BSD41A */	(void) setgid (pw -> pw_gid);#ifdef	BSD42	(void) initgroups (pw -> pw_name, pw -> pw_gid);#endif	/* BSD42 */	(void) setuid (pw -> pw_uid);    }        if (info == NULL)	info = "";    setbuf (stdin, NULLCP);    if (file == NULL) {	if ((fd = copyfile (fileno (stdin), file = tmpfil, 1)) == NOTOK)	    adios (NULLCP, "unable to create temporary file");	if (debug)	    fprintf (stderr, "temporary file \"%s\" selected\n", tmpfil);	else	    (void) unlink (tmpfil);   	if ((fp = fdopen (fd, "r+")) == NULL)	    adios (NULLCP, "unable to access temporary file");    }    else	fd = fileno (stdin);    from[0] = 0;    if (sender == NULL)	copyinfo (fp, from);    if (mbox == NULL) {	(void) sprintf (mailbox, "%s/%s",		mmdfldir[0] ? mmdfldir : pw -> pw_dir,		mmdflfil[0] ? mmdflfil : pw -> pw_name);	mbox = mailbox;    }    if (home == NULL)	home = pw -> pw_dir;    if ((now = dtwstime ()) == NULL)	adios (NULLCP, "unable to ascertain local time");    (void) sprintf (ddate, "Delivery-Date: %s\n", dtimenow ());    if (debug) {	fprintf (stderr, "addr=\"%s\" user=\"%s\" info=\"%s\" file=\"%s\"\n",		addr, user, info, file);	fprintf (stderr, "sender=\"%s\" mbox=\"%s\" home=\"%s\" from=\"%s\"\n",		sender, mbox, home, from);	fprintf (stderr, "ddate=\"%s\" now=%02d:%02d\n",		ddate, now -> tw_hour, now -> tw_min);    }    done (localmail (fd, from, mdlvr) != NOTOK ? RCV_MOK : RCV_MBX);}/*  */static int  localmail (fd, from, mdlvr)int     fd;char   *from,       *mdlvr;{#ifdef	MSGID    struct stat st;    if (stat (".maildelivery.pag", &st) != NOTOK	    && check_msgid (fd, ".maildelivery") == DONE)	return OK;#endif    if (usr_delivery (fd, mdlvr ? mdlvr : ".maildelivery", 0, from) != NOTOK)	return OK;    if (usr_delivery (fd, maildelivery, 1, from) != NOTOK)	return OK;#ifdef	notdef    if (verbose)	printf ("(invoking hook)\n");    if (usr_hook (fd, mbox) != NOTOK)	return OK;#endif	/* notdef */    if (verbose)	printf ("(trying normal delivery)\n");    return usr_file (fd, mbox, from);}/*  */#define	matches(a,b)	(stringdex (b, a) >= 0)static int  usr_delivery (fd, delivery, su, from)int     fd,	su;char   *delivery,       *from;{    int     i,	    accept,            status,            won,	    vecp,            next;    register char  *cp,                   *action,                   *field,                   *pattern,		   *string;    char    buffer[BUFSIZ],	    tmpbuf[BUFSIZ],           *vec[NVEC];    struct stat st;    register struct pair   *p;    register FILE  *fp;    if ((fp = fopen (delivery, "r")) == NULL)	return NOTOK;    if (fstat (fileno (fp), &st) == NOTOK	    || (st.st_uid != 0 && (su || st.st_uid != pw -> pw_uid))	    || st.st_mode & 0022) {	if (verbose) {	    printf ("%s: ownership/modes bad (%d, %d,%d,0%o)\n",		    delivery, su, pw -> pw_uid, st.st_uid, st.st_mode);	    (void) fflush (stdout);	}	return NOTOK;    }    won = 0;    next = 1;    while (fgets (buffer, sizeof buffer, fp) != NULL) {	if (*buffer == '#')	    continue;	if (cp = index (buffer, '\n'))	    *cp = 0;	if ((vecp = split (buffer, vec)) < 5)	    continue;	if (debug)	    for (i = 0; vec[i]; i++)		fprintf (stderr, "vec[%d]: \"%s\"\n", i, vec[i]);	field = vec[0];	pattern = vec[1];	action = vec[2];	switch (vec[3][0]) {	    case 'N':	    case 'n': 		if (! next)			continue;  /* if previous condition failed, don't				      do this - else fall through */	    case '?': 		if (won)		    continue;	/* else fall */	    case 'A': 	    case 'a': 		accept = 1;		break;	    case 'R': 	    case 'r': 	    default: 		accept = 0;		break;	}	string = vec[4];	if (vecp > 5) {	    if (uleq (vec[5], "select")) {		if (logged_in () != NOTOK)		    continue;		if (vecp > 7 && timely (vec[6], vec[7]) == NOTOK)		    continue;	    }	}	switch (*field) {	    case '*': 		break;	    case 'd': 		if (uleq (field, "default")) {		    if (won)			continue;		    break;		}		/* else fall */	    default: 		if (!parsed && parse (fd) == NOTOK) {		    (void) fclose (fp);		    return NOTOK;		}		if ((p = lookup (hdrs, field)) == NULL			|| (p->p_value == NULL)			/* XXX */			|| !matches (p -> p_value, pattern)) {			next = 0;			continue;		}		else		    next = 1;		break;	}	switch (*action) {	    case 'q':		if (!uleq (action, "qpipe"))		    continue;	/* else fall */	    case '^':		expand (tmpbuf, string, fd);		if (split (tmpbuf, vec) < 1)		    continue;		status = usr_pipe (fd, tmpbuf, vec[0], vec);		break;	    case 'p': 		if (!uleq (action, "pipe"))		    continue;	/* else fall */	    case '|': 		vec[2] = "sh";		vec[3] = "-c";		expand (tmpbuf, string, fd);		vec[4] = tmpbuf;		vec[5] = NULL;		status = usr_pipe (fd, tmpbuf, "/bin/sh", vec + 2);		break;	    case 'f': 		if (!uleq (action, "file"))		    continue;	/* else fall */	    case '>': #ifdef	RPATHS		status = usr_file (fd, string,  from);	/* UUCP format? */#else		status = usr_file (fd, string,  NULLCP);#endif		break;	    case 'm':		if (!uleq (action, "mbox"))		    continue;		status = usr_file (fd, string,  NULLCP);		break;	    case 'd': 		if (!uleq (action, "destroy"))		    continue;		status = OK;		break;	}	if (accept && status == OK)	    won++;    }    (void) fclose (fp);    return (won ? OK : NOTOK);}/*  */#define	QUOTE	'\\'static int  split (cp, vec)char   *cp,      **vec;{    register int    i;    register char  *s;    for (i = 0, s = cp; i <= NVEC;) {	vec[i] = NULL;	while (isspace (*s) || *s == ',')	    *s++ = 0;	if (*s == 0)	    break;	if (*s == '"') {	    for (vec[i++] = ++s; *s != 0 && *s != '"'; s++)		if (*s == QUOTE) {		    if (*++s == '"')			(void) strcpy (s - 1, s);		    s--;		}	    if (*s == '"')		*s++ = 0;	    continue;	}	if (*s == QUOTE && *++s != '"')	    s--;	vec[i++] = s++;	while (*s != 0 && !isspace (*s) && *s != ',')	    s++;    }    vec[i] = NULL;    return i;}/*  */static int  parse (fd)register int    fd;{    register int    i,                    state;    int     fd1;    register char  *cp,                   *dp,                   *lp;    char    name[NAMESZ],            field[BUFSIZ];    register struct pair   *p,			   *q;    register FILE  *in;    if (parsed++)	return OK;    if ((fd1 = dup (fd)) == NOTOK)	return NOTOK;    if ((in = fdopen (fd1, "r")) == NULL) {	(void) close (fd1);	return NOTOK;    }    rewind (in);    if (p = lookup (hdrs, "source"))	p -> p_value = getcpy (sender);    if (p = lookup (hdrs, "addr"))	p -> p_value = getcpy (addr);    for (i = 0, state = FLD;;) {	switch (state = m_getfld (state, name, field, sizeof field, in)) {	    case FLD: 	    case FLDEOF: 	    case FLDPLUS: 		lp = add (field, NULLCP);		while (state == FLDPLUS) {		    state = m_getfld (state, name, field, sizeof field, in);		    lp = add (field, lp);		}		for (p = hdrs; p -> p_name; p++)		    if (uleq (p -> p_name, name)) {			if (!(p -> p_flags & P_HID)) {			    if (cp = p -> p_value)				if (p -> p_flags & P_ADR) {				    dp = cp + strlen (cp) - 1;				    if (*dp == '\n')					*dp = 0;				    cp = add (",\n\t", cp);				}				else				    cp = add ("\t", cp);			    p -> p_value = add (lp, cp);			}			free (lp);			break;		    }		if (p -> p_name == NULL && i < NVEC) {		    p -> p_name = getcpy (name);		    p -> p_value = lp;		    p -> p_flags = P_NIL;		    p++, i++;		    p -> p_name = NULL;		}		if (state != FLDEOF)		    continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -