Try to use flock call (this doesn't work because we don't always have an
authorEric Allman <eric@ucbvax.Berkeley.EDU>
Thu, 6 Dec 1984 15:16:18 +0000 (07:16 -0800)
committerEric Allman <eric@ucbvax.Berkeley.EDU>
Thu, 6 Dec 1984 15:16:18 +0000 (07:16 -0800)
open fd); security and performance fixes from Kirk Smith at Purdue; "a"
option is now the number of minutes to wait for "@:@" alias; fix bug in
$[ $] using -t; random cleanup

SCCS-vsn: usr.sbin/sendmail/src/queue.c 4.3
SCCS-vsn: usr.sbin/sendmail/src/conf.c 4.6
SCCS-vsn: usr.sbin/sendmail/src/main.c 4.15
SCCS-vsn: usr.sbin/sendmail/src/alias.c 4.7
SCCS-vsn: usr.sbin/sendmail/src/clock.c 4.3
SCCS-vsn: usr.sbin/sendmail/src/envelope.c 4.8
SCCS-vsn: usr.sbin/sendmail/src/parseaddr.c 4.14
SCCS-vsn: usr.sbin/sendmail/src/readcf.c 4.9
SCCS-vsn: usr.sbin/sendmail/src/version.c 4.43

usr/src/usr.sbin/sendmail/src/alias.c
usr/src/usr.sbin/sendmail/src/clock.c
usr/src/usr.sbin/sendmail/src/conf.c
usr/src/usr.sbin/sendmail/src/envelope.c
usr/src/usr.sbin/sendmail/src/main.c
usr/src/usr.sbin/sendmail/src/parseaddr.c
usr/src/usr.sbin/sendmail/src/queue.c
usr/src/usr.sbin/sendmail/src/readcf.c
usr/src/usr.sbin/sendmail/src/version.c

index 11a26cf..1626e23 100644 (file)
@@ -5,9 +5,9 @@
 # include "sendmail.h"
 
 # ifdef DBM
 # include "sendmail.h"
 
 # ifdef DBM
-SCCSID(@(#)alias.c     4.6             %G%     (with DBM));
+SCCSID(@(#)alias.c     4.7             %G%     (with DBM));
 # else DBM
 # else DBM
-SCCSID(@(#)alias.c     4.6             %G%     (without DBM));
+SCCSID(@(#)alias.c     4.7             %G%     (without DBM));
 # endif DBM
 
 /*
 # endif DBM
 
 /*
@@ -176,9 +176,14 @@ initaliases(aliasfile, init)
        */
 
        dbminit(aliasfile);
        */
 
        dbminit(aliasfile);
-       atcnt = 10;
-       while (SafeAlias && !init && atcnt-- >= 0 && aliaslookup("@") == NULL)
-               sleep(30);
+       atcnt = SafeAlias * 2;
+       if (atcnt > 0)
+       {
+               while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL)
+                       sleep(30);
+       }
+       else
+               atcnt = 1;
 
        /*
        **  See if the DBM version of the file is out of date with
 
        /*
        **  See if the DBM version of the file is out of date with
index 45bc4fa..efbdbca 100644 (file)
@@ -1,7 +1,7 @@
 # include "sendmail.h"
 # include <signal.h>
 
 # include "sendmail.h"
 # include <signal.h>
 
-SCCSID(@(#)clock.c     4.2             %G%);
+SCCSID(@(#)clock.c     4.3             %G%);
 
 /*
 **  SETEVENT -- set an event to happen at a specific time.
 
 /*
 **  SETEVENT -- set an event to happen at a specific time.
@@ -129,6 +129,7 @@ tick()
 {
        register time_t now;
        register EVENT *ev;
 {
        register time_t now;
        register EVENT *ev;
+       int pid = getpid();
 
        (void) signal(SIGALRM, SIG_IGN);
        (void) alarm(0);
 
        (void) signal(SIGALRM, SIG_IGN);
        (void) alarm(0);
@@ -140,7 +141,7 @@ tick()
 # endif DEBUG
 
        while ((ev = EventQueue) != NULL &&
 # endif DEBUG
 
        while ((ev = EventQueue) != NULL &&
-              (ev->ev_time <= now || ev->ev_pid != getpid()))
+              (ev->ev_time <= now || ev->ev_pid != pid))
        {
                int (*f)();
                int arg;
        {
                int (*f)();
                int arg;
index ef3890e..2cdbef7 100644 (file)
@@ -34,7 +34,7 @@
 
 
 
 
 
 
-SCCSID(@(#)conf.c      4.5             %G%);
+SCCSID(@(#)conf.c      4.6             %G%);
 \f/*
 **  Header info table
 **     Final (null) entry contains the flags used for any other field.
 \f/*
 **  Header info table
 **     Final (null) entry contains the flags used for any other field.
@@ -310,9 +310,30 @@ getrgid()
 char *
 username()
 {
 char *
 username()
 {
+       static char *myname = NULL;
        extern char *getlogin();
 
        extern char *getlogin();
 
-       return (getlogin());
+       /* cache the result */
+       if (myname == NULL)
+       {
+               myname = getlogin();
+               if (myname == NULL || myname[0] == '\0')
+               {
+                       register struct passwd *pw;
+                       extern struct passwd *getpwuid();
+
+                       pw = getpwuid(getruid());
+                       if (pw != NULL)
+                               myname = pw->pw_name;
+               }
+               if (myname == NULL || myname[0] == '\0')
+               {
+                       syserr("Who are you?");
+                       myname = "postmaster";
+               }
+       }
+
+       return (myname);
 }
 \f/*
 **  TTYPATH -- Get the path of the user's tty
 }
 \f/*
 **  TTYPATH -- Get the path of the user's tty
@@ -507,3 +528,27 @@ getla()
 }
 
 #endif VMUNIX
 }
 
 #endif VMUNIX
+\f/*
+**  DBMCLOSE -- close the DBM file
+**
+**     This depends on the implementation of the DBM library.  It
+**     seems to work for all versions that I have come across.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Closes the current DBM file; dbminit must be
+**             called again to continue using the DBM routines.
+*/
+
+dbmclose()
+{
+       extern int pagf, dirf;  /* defined in the DBM package */
+
+       (void) close(pagf);
+       (void) close(dirf);
+}
index d70413d..c24c756 100644 (file)
@@ -3,7 +3,7 @@
 #include "sendmail.h"
 #include <sys/stat.h>
 
 #include "sendmail.h"
 #include <sys/stat.h>
 
-SCCSID(@(#)envelope.c  4.7             %G%);
+SCCSID(@(#)envelope.c  4.8             %G%);
 
 /*
 **  NEWENVELOPE -- allocate a new envelope
 
 /*
 **  NEWENVELOPE -- allocate a new envelope
@@ -185,37 +185,6 @@ clearenvelope(e)
        e->e_flags = 0;
 }
 \f/*
        e->e_flags = 0;
 }
 \f/*
-**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
-**
-**     Parameters:
-**             e -- the envelope to unlock.
-**
-**     Returns:
-**             none
-**
-**     Side Effects:
-**             unlocks the queue for `e'.
-*/
-
-unlockqueue(e)
-       ENVELOPE *e;
-{
-       /* remove the transcript */
-#ifdef DEBUG
-# ifdef LOG
-       if (LogLevel > 19)
-               syslog(LOG_DEBUG, "%s: unlock", e->e_id);
-# endif LOG
-       if (!tTd(51, 4))
-#endif DEBUG
-               xunlink(queuename(e, 'x'));
-
-# ifdef QUEUE
-       /* last but not least, remove the lock */
-       xunlink(queuename(e, 'l'));
-# endif QUEUE
-}
-\f/*
 **  INITSYS -- initialize instantiation of system
 **
 **     In Daemon mode, this is done in the child.
 **  INITSYS -- initialize instantiation of system
 **
 **     In Daemon mode, this is done in the child.
@@ -275,6 +244,7 @@ initsys()
        /* time as integer, unix time, arpa time */
        settime();
 
        /* time as integer, unix time, arpa time */
        settime();
 
+#ifdef TTYNAME
        /* tty name */
        if (macvalue('y', CurEnv) == NULL)
        {
        /* tty name */
        if (macvalue('y', CurEnv) == NULL)
        {
@@ -287,6 +257,7 @@ initsys()
                        define('y', ybuf, CurEnv);
                }
        }
                        define('y', ybuf, CurEnv);
                }
        }
+#endif TTYNAME
 }
 \f/*
 **  SETTIME -- set the current time.
 }
 \f/*
 **  SETTIME -- set the current time.
@@ -327,125 +298,6 @@ settime()
        define('b', p, CurEnv);
 }
 \f/*
        define('b', p, CurEnv);
 }
 \f/*
-**  QUEUENAME -- build a file name in the queue directory for this envelope.
-**
-**     Assigns an id code if one does not already exist.
-**     This code is very careful to avoid trashing existing files
-**     under any circumstances.
-**             We first create an nf file that is only used when
-**             assigning an id.  This file is always empty, so that
-**             we can never accidently truncate an lf file.
-**
-**     Parameters:
-**             e -- envelope to build it in/from.
-**             type -- the file type, used as the first character
-**                     of the file name.
-**
-**     Returns:
-**             a pointer to the new file name (in a static buffer).
-**
-**     Side Effects:
-**             Will create the lf and qf files if no id code is
-**             already assigned.  This will cause the envelope
-**             to be modified.
-*/
-
-char *
-queuename(e, type)
-       register ENVELOPE *e;
-       char type;
-{
-       static char buf[MAXNAME];
-       static int pid = -1;
-       char c1 = 'A';
-       char c2 = 'A';
-
-       if (e->e_id == NULL)
-       {
-               char qf[20];
-               char lf[20];
-               char nf[20];
-
-               /* find a unique id */
-               if (pid != getpid())
-               {
-                       /* new process -- start back at "AA" */
-                       pid = getpid();
-                       c1 = 'A';
-                       c2 = 'A' - 1;
-               }
-               (void) sprintf(qf, "qfAA%05d", pid);
-               strcpy(lf, qf);
-               lf[0] = 'l';
-               strcpy(nf, qf);
-               nf[0] = 'n';
-
-               while (c1 < '~' || c2 < 'Z')
-               {
-                       int i;
-
-                       if (c2 >= 'Z')
-                       {
-                               c1++;
-                               c2 = 'A' - 1;
-                       }
-                       qf[2] = lf[2] = nf[2] = c1;
-                       qf[3] = lf[3] = nf[3] = ++c2;
-# ifdef DEBUG
-                       if (tTd(7, 20))
-                               printf("queuename: trying \"%s\"\n", nf);
-# endif DEBUG
-# ifdef QUEUE
-                       if (access(lf, 0) >= 0 || access(qf, 0) >= 0)
-                               continue;
-                       errno = 0;
-                       i = creat(nf, FileMode);
-                       if (i < 0)
-                       {
-                               (void) unlink(nf);      /* kernel bug */
-                               continue;
-                       }
-                       (void) close(i);
-                       i = link(nf, lf);
-                       (void) unlink(nf);
-                       if (i < 0)
-                               continue;
-                       if (link(lf, qf) >= 0)
-                               break;
-                       (void) unlink(lf);
-# else QUEUE
-                       if (close(creat(qf, FileMode)) < 0)
-                               continue;
-# endif QUEUE
-               }
-               if (c1 >= '~' && c2 >= 'Z')
-               {
-                       syserr("queuename: Cannot create \"%s\" in \"%s\"",
-                               lf, QueueDir);
-                       exit(EX_OSERR);
-               }
-               e->e_id = newstr(&qf[2]);
-               define('i', e->e_id, e);
-# ifdef DEBUG
-               if (tTd(7, 1))
-                       printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
-# ifdef LOG
-               if (LogLevel > 16)
-                       syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
-# endif LOG
-# endif DEBUG
-       }
-
-       if (type == '\0')
-               return (NULL);
-       (void) sprintf(buf, "%cf%s", type, e->e_id);
-# ifdef DEBUG
-       if (tTd(7, 2))
-               printf("queuename: %s\n", buf);
-# endif DEBUG
-       return (buf);
-}
-\f/*
 **  OPENXSCRIPT -- Open transcript file
 **
 **     Creates a transcript file for possible eventual mailing or
 **  OPENXSCRIPT -- Open transcript file
 **
 **     Creates a transcript file for possible eventual mailing or
@@ -536,7 +388,6 @@ setsender(from)
        char *from;
 {
        register char **pvp;
        char *from;
 {
        register char **pvp;
-       register struct passwd *pw = NULL;
        char *realname = NULL;
        char buf[MAXNAME];
        char pvpbuf[PSBUFSIZE];
        char *realname = NULL;
        char buf[MAXNAME];
        char pvpbuf[PSBUFSIZE];
@@ -562,20 +413,6 @@ setsender(from)
                extern char *username();
 
                realname = username();
                extern char *username();
 
                realname = username();
-               errno = 0;
-       }
-       if (realname == NULL || realname[0] == '\0')
-       {
-               extern struct passwd *getpwuid();
-
-               pw = getpwuid(getruid());
-               if (pw != NULL)
-                       realname = pw->pw_name;
-       }
-       if (realname == NULL || realname[0] == '\0')
-       {
-               syserr("Who are you?");
-               realname = "root";
        }
 
        /*
        }
 
        /*
@@ -596,8 +433,6 @@ setsender(from)
                        /* syserr("%s, you cannot use the -f flag", realname); */
                        from = NULL;
                }
                        /* syserr("%s, you cannot use the -f flag", realname); */
                        from = NULL;
                }
-               else if (strcmp(from, realname) != 0)
-                       pw = NULL;
        }
 
        SuprErrs = TRUE;
        }
 
        SuprErrs = TRUE;
@@ -612,19 +447,17 @@ setsender(from)
        loweraddr(&CurEnv->e_from);
        SuprErrs = FALSE;
 
        loweraddr(&CurEnv->e_from);
        SuprErrs = FALSE;
 
-       if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer)
+       if (CurEnv->e_from.q_mailer == LocalMailer)
        {
        {
+               register struct passwd *pw;
                extern struct passwd *getpwnam();
 
                extern struct passwd *getpwnam();
 
-               pw = getpwnam(CurEnv->e_from.q_user);
-       }
+               /*
+               **  Process passwd file entry.
+               */
 
 
-       /*
-       **  Process passwd file entry.
-       */
+               pw = getpwnam(CurEnv->e_from.q_user);
 
 
-       if (pw != NULL)
-       {
                /* extract home directory */
                CurEnv->e_from.q_home = newstr(pw->pw_dir);
                define('z', CurEnv->e_from.q_home, CurEnv);
                /* extract home directory */
                CurEnv->e_from.q_home = newstr(pw->pw_dir);
                define('z', CurEnv->e_from.q_home, CurEnv);
index 9cb30d6..d17c2ff 100644 (file)
@@ -3,7 +3,7 @@
 # include <sgtty.h>
 # include "sendmail.h"
 
 # include <sgtty.h>
 # include "sendmail.h"
 
-SCCSID(@(#)main.c      4.14            %G%);
+SCCSID(@(#)main.c      4.15            %G%);
 
 /*
 **  SENDMAIL -- Post mail to a set of destinations.
 
 /*
 **  SENDMAIL -- Post mail to a set of destinations.
@@ -103,7 +103,7 @@ main(argc, argv, envp)
        **  Be sure we have enough file descriptors.
        */
 
        **  Be sure we have enough file descriptors.
        */
 
-       for (i = 3; i < 20; i++)
+       for (i = 3; i < 50; i++)
                (void) close(i);
        errno = 0;
 
                (void) close(i);
        errno = 0;
 
@@ -117,12 +117,23 @@ main(argc, argv, envp)
 
        argv[argc] = NULL;
        av = argv;
 
        argv[argc] = NULL;
        av = argv;
-       while (*++av != NULL)
+       while ((p = *++av) != NULL)
        {
        {
-               if (strncmp(*av, "-C", 2) == 0 || strncmp(*av, "-bz", 3) == 0)
+               if (strncmp(p, "-C", 2) == 0)
+               {
+                       ConfFile = &p[2];
+                       if (ConfFile[0] == '\0')
+                               ConfFile = "sendmail.cf";
+                       readconfig = safecf = FALSE;
+                       setuid(getruid());
+                       setgid(getrgid());
+                       readcf(ConfFile, FALSE);
+                       break;
+               }
+               else if (strncmp(p, "-bz", 3) == 0)
                        break;
        }
                        break;
        }
-       if (*av == NULL)
+       if (p == NULL)
                readconfig = !thaw(FreezeFile);
 
        /* reset the environment after the thaw */
                readconfig = !thaw(FreezeFile);
 
        /* reset the environment after the thaw */
@@ -153,10 +164,6 @@ main(argc, argv, envp)
        BlankEnvelope.e_xfp = NULL;
        CurEnv = &BlankEnvelope;
 
        BlankEnvelope.e_xfp = NULL;
        CurEnv = &BlankEnvelope;
 
-       /* make sure we have a clean slate */
-       for (i = 3; i < 50; i++)
-               (void) close(i);
-
 # ifdef LOG
        openlog("sendmail", LOG_PID);
 # endif LOG
 # ifdef LOG
        openlog("sendmail", LOG_PID);
 # endif LOG
@@ -233,11 +240,7 @@ main(argc, argv, envp)
                        }
                        break;
 
                        }
                        break;
 
-                 case 'C':     /* select configuration file */
-                       ConfFile = &p[2];
-                       if (ConfFile[0] == '\0')
-                               ConfFile = "sendmail.cf";
-                       safecf = FALSE;
+                 case 'C':     /* select configuration file (already done) */
                        break;
 
 # ifdef DEBUG
                        break;
 
 # ifdef DEBUG
@@ -341,11 +344,6 @@ main(argc, argv, envp)
        **      Extract special fields for local use.
        */
 
        **      Extract special fields for local use.
        */
 
-       if (!safecf)
-       {
-               setgid(getrgid());
-               setuid(getruid());
-       }
        if (!safecf || OpMode == MD_FREEZE || readconfig)
                readcf(ConfFile, safecf);
 
        if (!safecf || OpMode == MD_FREEZE || readconfig)
                readcf(ConfFile, safecf);
 
@@ -956,6 +954,7 @@ disconnect(fulldrop)
                        (void) ioctl(fd, TIOCNOTTY, 0);
                        (void) close(fd);
                }
                        (void) ioctl(fd, TIOCNOTTY, 0);
                        (void) close(fd);
                }
+               setpgrp(0);
                errno = 0;
        }
 #endif TIOCNOTTY
                errno = 0;
        }
 #endif TIOCNOTTY
index 8707e68..2a2d362 100644 (file)
@@ -1,6 +1,6 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)parseaddr.c 4.13            %G%);
+SCCSID(@(#)parseaddr.c 4.14            %G%);
 
 /*
 **  PARSEADDR -- Parse an address
 
 /*
 **  PARSEADDR -- Parse an address
@@ -736,9 +736,11 @@ rewrite(pvp, ruleset)
                        char **xpvp;
                        int trsize;
                        int i;
                        char **xpvp;
                        int trsize;
                        int i;
+                       char *olddelimchar;
                        char buf[MAXNAME + 1];
                        char *pvpb1[MAXATOM + 1];
                        char pvpbuf[PSBUFSIZE];
                        char buf[MAXNAME + 1];
                        char *pvpb1[MAXATOM + 1];
                        char pvpbuf[PSBUFSIZE];
+                       extern char *DelimChar;
 
                        if (**rvp != HOSTBEGIN)
                                continue;
 
                        if (**rvp != HOSTBEGIN)
                                continue;
@@ -766,7 +768,9 @@ rewrite(pvp, ruleset)
                        maphostname(buf, sizeof buf);
 
                        /* scan the new host name */
                        maphostname(buf, sizeof buf);
 
                        /* scan the new host name */
+                       olddelimchar = DelimChar;
                        xpvp = prescan(buf, '\0', pvpbuf);
                        xpvp = prescan(buf, '\0', pvpbuf);
+                       DelimChar = olddelimchar;
                        if (xpvp == NULL)
                        {
                                syserr("rewrite: cannot prescan canonical hostname: %s", buf);
                        if (xpvp == NULL)
                        {
                                syserr("rewrite: cannot prescan canonical hostname: %s", buf);
index 818cf0a..bd9bdac 100644 (file)
@@ -3,12 +3,15 @@
 # include <sys/dir.h>
 # include <signal.h>
 # include <errno.h>
 # include <sys/dir.h>
 # include <signal.h>
 # include <errno.h>
+# ifdef FLOCK
+# include <sys/file.h>
+# endif FLOCK
 
 # ifndef QUEUE
 
 # ifndef QUEUE
-SCCSID(@(#)queue.c     4.2             %G%     (no queueing));
+SCCSID(@(#)queue.c     4.3             %G%     (no queueing));
 # else QUEUE
 
 # else QUEUE
 
-SCCSID(@(#)queue.c     4.2             %G%);
+SCCSID(@(#)queue.c     4.3             %G%);
 
 /*
 **  Work queue.
 
 /*
 **  Work queue.
@@ -54,21 +57,27 @@ queueup(e, queueall, announce)
        MAILER nullmailer;
 
        /*
        MAILER nullmailer;
 
        /*
-       **  Create control file.
+       **  Create control file if necessary.
        */
 
        */
 
-       tf = newstr(queuename(e, 't'));
-       tfp = fopen(tf, "w");
+       tfp = e->e_qfp;
        if (tfp == NULL)
        {
        if (tfp == NULL)
        {
-               syserr("queueup: cannot create temp file %s", tf);
-               return;
+               tf = newstr(queuename(e, 't'));
+               tfp = fopen(tf, "w");
+               if (tfp == NULL)
+               {
+                       syserr("queueup: cannot create temp file %s", tf);
+                       return;
+               }
+               (void) chmod(tf, FileMode);
        }
        }
-       (void) chmod(tf, FileMode);
+       else
+               tf = NULL;
 
 # ifdef DEBUG
        if (tTd(40, 1))
 
 # ifdef DEBUG
        if (tTd(40, 1))
-               printf("queueing in %s\n", tf);
+               printf("queueing %s\n", e->e_id);
 # endif DEBUG
 
        /*
 # endif DEBUG
 
        /*
@@ -201,15 +210,25 @@ queueup(e, queueall, announce)
        **  Clean up.
        */
 
        **  Clean up.
        */
 
-       (void) fclose(tfp);
        qf = queuename(e, 'q');
        qf = queuename(e, 'q');
-       holdsigs();
-       (void) unlink(qf);
-       if (link(tf, qf) < 0)
-               syserr("cannot link(%s, %s), df=%s", tf, qf, e->e_df);
-       else
-               (void) unlink(tf);
-       rlsesigs();
+       if (tf != NULL)
+       {
+# ifdef FLOCK
+               (void) flock(fileno(tfp), LOCK_EX|LOCK_NB);
+               if (rename(tf, qf) < 0)
+                       syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df);
+# else FLOCK
+               holdsigs();
+               (void) unlink(qf);
+               if (link(tf, qf) < 0)
+                       syserr("cannot link(%s, %s), df=%s", tf, qf, e->e_df);
+               else
+                       (void) unlink(tf);
+               rlsesigs();
+# endif FLOCK
+       }
+       (void) fclose(tfp);
+       e->e_qfp = NULL;
 
 # ifdef LOG
        /* save log info */
 
 # ifdef LOG
        /* save log info */
@@ -494,6 +513,8 @@ dowork(w)
 
        if (i == 0)
        {
 
        if (i == 0)
        {
+               FILE *qfp;
+
                /*
                **  CHILD
                **      Lock the control file to avoid duplicate deliveries.
                /*
                **  CHILD
                **      Lock the control file to avoid duplicate deliveries.
@@ -518,8 +539,17 @@ dowork(w)
                /* don't use the headers from sendmail.cf... */
                CurEnv->e_header = NULL;
 
                /* don't use the headers from sendmail.cf... */
                CurEnv->e_header = NULL;
 
-               /* create the link to the control file during processing */
+               FileName = queuename(CurEnv, 'q');
+               qfp = fopen(FileName, "r");
+               if (qfp == NULL)
+                       exit(EX_OK);
+
+               /* lock the control file during processing */
+# ifdef FLOCK
+               if (flock(fileno(qfp), LOCK_EX|LOCK_NB) < 0)
+# else FLOCK
                if (link(w->w_name, queuename(CurEnv, 'l')) < 0)
                if (link(w->w_name, queuename(CurEnv, 'l')) < 0)
+# endif FLOCK
                {
                        /* being processed by another queuer */
 # ifdef LOG
                {
                        /* being processed by another queuer */
 # ifdef LOG
@@ -533,7 +563,8 @@ dowork(w)
                initsys();
 
                /* read the queue control file */
                initsys();
 
                /* read the queue control file */
-               readqf(CurEnv, TRUE);
+               readqf(qfp, CurEnv, TRUE);
+               (void) fclose(qfp);
                CurEnv->e_flags |= EF_INQUEUE;
                eatheader(CurEnv);
 
                CurEnv->e_flags |= EF_INQUEUE;
                eatheader(CurEnv);
 
@@ -556,6 +587,7 @@ dowork(w)
 **  READQF -- read queue file and set up environment.
 **
 **     Parameters:
 **  READQF -- read queue file and set up environment.
 **
 **     Parameters:
+**             qfp -- the file pointer for the qf file.
 **             e -- the envelope of the job to run.
 **             full -- if set, read in all information.  Otherwise just
 **                     read in info needed for a queue print.
 **             e -- the envelope of the job to run.
 **             full -- if set, read in all information.  Otherwise just
 **                     read in info needed for a queue print.
@@ -568,37 +600,23 @@ dowork(w)
 **             we had been invoked by argument.
 */
 
 **             we had been invoked by argument.
 */
 
-readqf(e, full)
+readqf(qfp, e, full)
+       register FILE *qfp;
        register ENVELOPE *e;
        bool full;
 {
        register ENVELOPE *e;
        bool full;
 {
-       register FILE *f;
        char buf[MAXFIELD];
        extern char *fgetfolded();
        char buf[MAXFIELD];
        extern char *fgetfolded();
-       register char *p;
        extern ADDRESS *sendto();
 
        extern ADDRESS *sendto();
 
-       /*
-       **  Open the file created by queueup.
-       */
-
-       p = queuename(e, 'q');
-       f = fopen(p, "r");
-       if (f == NULL)
-       {
-               syserr("readqf: no control file %s", p);
-               return;
-       }
-       FileName = p;
-       LineNumber = 0;
-
        /*
        **  Read and process the file.
        */
 
        /*
        **  Read and process the file.
        */
 
+       LineNumber = 0;
        if (Verbose && full)
                printf("\nRunning %s\n", e->e_id);
        if (Verbose && full)
                printf("\nRunning %s\n", e->e_id);
-       while (fgetfolded(buf, sizeof buf, f) != NULL)
+       while (fgetfolded(buf, sizeof buf, qfp) != NULL)
        {
                switch (buf[0])
                {
        {
                switch (buf[0])
                {
@@ -693,24 +711,41 @@ printqueue()
                struct stat st;
                auto time_t submittime = 0;
                long dfsize = -1;
                struct stat st;
                auto time_t submittime = 0;
                long dfsize = -1;
+               int fd;
+# ifndef FLOCK
                char lf[20];
                char lf[20];
+# endif FLOCK
                char message[MAXLINE];
 
                char message[MAXLINE];
 
+               f = fopen(w->w_name, "r");
+               if (f == NULL)
+               {
+                       errno = 0;
+                       continue;
+               }
                printf("%7s", w->w_name + 2);
                printf("%7s", w->w_name + 2);
+# ifdef FLOCK
+               fd = fileno(f);
+
+               if (flock(fd, LOCK_EX|LOCK_NB) < 0)
+               {
+                       printf("*");
+               }
+               else
+               {
+                       flock(fd, LOCK_UN);
+                       printf(" ");
+               }
+# else FLOCK
                strcpy(lf, w->w_name);
                lf[0] = 'l';
                if (stat(lf, &st) >= 0)
                        printf("*");
                else
                        printf(" ");
                strcpy(lf, w->w_name);
                lf[0] = 'l';
                if (stat(lf, &st) >= 0)
                        printf("*");
                else
                        printf(" ");
+# endif FLOCK
                errno = 0;
                errno = 0;
-               f = fopen(w->w_name, "r");
-               if (f == NULL)
-               {
-                       printf(" (finished)\n");
-                       errno = 0;
-                       continue;
-               }
+
                message[0] = '\0';
                while (fgets(buf, sizeof buf, f) != NULL)
                {
                message[0] = '\0';
                while (fgets(buf, sizeof buf, f) != NULL)
                {
@@ -750,3 +785,181 @@ printqueue()
 }
 
 # endif QUEUE
 }
 
 # endif QUEUE
+\f/*
+**  QUEUENAME -- build a file name in the queue directory for this envelope.
+**
+**     Assigns an id code if one does not already exist.
+**     This code is very careful to avoid trashing existing files
+**     under any circumstances.
+**             We first create an nf file that is only used when
+**             assigning an id.  This file is always empty, so that
+**             we can never accidently truncate an lf file.
+**
+**     Parameters:
+**             e -- envelope to build it in/from.
+**             type -- the file type, used as the first character
+**                     of the file name.
+**
+**     Returns:
+**             a pointer to the new file name (in a static buffer).
+**
+**     Side Effects:
+**             Will create the lf and qf files if no id code is
+**             already assigned.  This will cause the envelope
+**             to be modified.
+*/
+
+char *
+queuename(e, type)
+       register ENVELOPE *e;
+       char type;
+{
+       static char buf[MAXNAME];
+       static int pid = -1;
+       char c1 = 'A';
+       char c2 = 'A';
+
+       if (e->e_id == NULL)
+       {
+               char qf[20];
+               char nf[20];
+# ifndef FLOCK
+               char lf[20];
+# endif FLOCK
+
+               /* find a unique id */
+               if (pid != getpid())
+               {
+                       /* new process -- start back at "AA" */
+                       pid = getpid();
+                       c1 = 'A';
+                       c2 = 'A' - 1;
+               }
+               (void) sprintf(qf, "qfAA%05d", pid);
+# ifndef FLOCK
+               strcpy(lf, qf);
+               lf[0] = 'l';
+# endif FLOCK
+               strcpy(nf, qf);
+               nf[0] = 'n';
+
+               while (c1 < '~' || c2 < 'Z')
+               {
+                       int i;
+
+                       if (c2 >= 'Z')
+                       {
+                               c1++;
+                               c2 = 'A' - 1;
+                       }
+                       nf[2] = qf[2] = c1;
+                       nf[3] = qf[3] = ++c2;
+# ifndef FLOCK
+                       lf[2] = c1;
+                       lf[3] = c2;
+# endif FLOCK
+# ifdef DEBUG
+                       if (tTd(7, 20))
+                               printf("queuename: trying \"%s\"\n", nf);
+# endif DEBUG
+
+# ifdef FLOCK
+                       i = open(nf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
+                       if (i >= 0)
+                       {
+                               (void) flock(i, LOCK_EX|LOCK_NB);
+                               if (link(nf, qf) < 0)
+                               {
+                                       (void) close(i);
+                                       (void) unlink(nf);
+                                       continue;
+                               }
+                               e->e_qfp = fdopen(i, "w");
+                               (void) unlink(nf);
+                               break;
+                       }
+# else FLOCK
+# ifdef QUEUE
+                       if (access(lf, 0) >= 0 || access(qf, 0) >= 0)
+                               continue;
+                       errno = 0;
+                       i = creat(nf, FileMode);
+                       if (i < 0)
+                       {
+                               (void) unlink(nf);      /* kernel bug */
+                               continue;
+                       }
+                       (void) close(i);
+                       i = link(nf, lf);
+                       (void) unlink(nf);
+                       if (i < 0)
+                               continue;
+                       if (link(lf, qf) >= 0)
+                               break;
+                       (void) unlink(lf);
+# else QUEUE
+                       if (close(creat(qf, FileMode)) < 0)
+                               continue;
+# endif QUEUE
+# endif FLOCK
+               }
+               if (c1 >= '~' && c2 >= 'Z')
+               {
+                       syserr("queuename: Cannot create \"%s\" in \"%s\"",
+                               qf, QueueDir);
+                       exit(EX_OSERR);
+               }
+               e->e_id = newstr(&qf[2]);
+               define('i', e->e_id, e);
+# ifdef DEBUG
+               if (tTd(7, 1))
+                       printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
+# ifdef LOG
+               if (LogLevel > 16)
+                       syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
+# endif LOG
+# endif DEBUG
+       }
+
+       if (type == '\0')
+               return (NULL);
+       (void) sprintf(buf, "%cf%s", type, e->e_id);
+# ifdef DEBUG
+       if (tTd(7, 2))
+               printf("queuename: %s\n", buf);
+# endif DEBUG
+       return (buf);
+}
+\f/*
+**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
+**
+**     Parameters:
+**             e -- the envelope to unlock.
+**
+**     Returns:
+**             none
+**
+**     Side Effects:
+**             unlocks the queue for `e'.
+*/
+
+unlockqueue(e)
+       ENVELOPE *e;
+{
+       /* remove the transcript */
+#ifdef DEBUG
+# ifdef LOG
+       if (LogLevel > 19)
+               syslog(LOG_DEBUG, "%s: unlock", e->e_id);
+# endif LOG
+       if (!tTd(51, 4))
+#endif DEBUG
+               xunlink(queuename(e, 'x'));
+
+# ifdef QUEUE
+# ifndef FLOCK
+       /* last but not least, remove the lock */
+       xunlink(queuename(e, 'l'));
+# endif FLOCK
+# endif QUEUE
+}
index bc612c3..4aacb7f 100644 (file)
@@ -1,6 +1,6 @@
 # include "sendmail.h"
 
 # include "sendmail.h"
 
-SCCSID(@(#)readcf.c    4.8             %G%);
+SCCSID(@(#)readcf.c    4.9             %G%);
 
 /*
 **  READCF -- read control file.
 
 /*
 **  READCF -- read control file.
@@ -619,6 +619,8 @@ setoption(opt, val, safe, sticky)
        extern time_t convtime();
        extern int QueueLA;
        extern int RefuseLA;
        extern time_t convtime();
        extern int QueueLA;
        extern int RefuseLA;
+       extern bool trusteduser();
+       extern char *username();
 
 # ifdef DEBUG
        if (tTd(37, 1))
 
 # ifdef DEBUG
        if (tTd(37, 1))
@@ -642,8 +644,14 @@ setoption(opt, val, safe, sticky)
                printf("\n");
 #endif DEBUG
 
                printf("\n");
 #endif DEBUG
 
-       if (getruid() == 0)
+       /*
+       **  Check to see if this option can be specified by this user.
+       */
+
+       if (!safe && (getruid() == 0 || trusteduser(username())))
                safe = TRUE;
                safe = TRUE;
+       if (!safe && index("deiLmorsv", opt) == NULL)
+               return;
 
        switch (opt)
        {
 
        switch (opt)
        {
@@ -654,16 +662,19 @@ setoption(opt, val, safe, sticky)
                        AliasFile = newstr(val);
                break;
 
                        AliasFile = newstr(val);
                break;
 
+         case 'a':             /* look N minutes for "@:@" in alias file */
+               if (val[0] == '\0')
+                       SafeAlias = 5;
+               else
+                       SafeAlias = atoi(val);
+               break;
+
          case 'B':             /* substitution for blank character */
                SpaceSub = val[0];
                if (SpaceSub == '\0')
                        SpaceSub = ' ';
                break;
 
          case 'B':             /* substitution for blank character */
                SpaceSub = val[0];
                if (SpaceSub == '\0')
                        SpaceSub = ' ';
                break;
 
-         case 'a':             /* look for "@:@" in alias file */
-               SafeAlias = atobool(val);
-               break;
-
          case 'c':             /* don't connect to "expensive" mailers */
                NoConnect = atobool(val);
                break;
          case 'c':             /* don't connect to "expensive" mailers */
                NoConnect = atobool(val);
                break;
@@ -721,8 +732,7 @@ setoption(opt, val, safe, sticky)
                break;
 
          case 'g':             /* default gid */
                break;
 
          case 'g':             /* default gid */
-               if (safe)
-                       DefGid = atoi(val);
+               DefGid = atoi(val);
                break;
 
          case 'H':             /* help file */
                break;
 
          case 'H':             /* help file */
@@ -800,8 +810,7 @@ setoption(opt, val, safe, sticky)
                break;
 
          case 'u':             /* set default uid */
                break;
 
          case 'u':             /* set default uid */
-               if (safe)
-                       DefUid = atoi(val);
+               DefUid = atoi(val);
                break;
 
          case 'v':             /* run in verbose mode */
                break;
 
          case 'v':             /* run in verbose mode */
@@ -810,8 +819,7 @@ setoption(opt, val, safe, sticky)
 
 # ifdef DEBUG
          case 'W':             /* set the wizards password */
 
 # ifdef DEBUG
          case 'W':             /* set the wizards password */
-               if (safe)
-                       WizWord = newstr(val);
+               WizWord = newstr(val);
                break;
 # endif DEBUG
 
                break;
 # endif DEBUG
 
index 15bdf54..bdfb916 100644 (file)
@@ -1,5 +1,5 @@
 # ifndef lint
 # ifndef lint
-static char    SccsId[] = "@(#)SendMail version 4.42 of %G%";
+static char    SccsId[] = "@(#)SendMail version 4.43 of %G%";
 # endif lint
 
 # endif lint
 
-char   Version[] = "4.42";
+char   Version[] = "4.43";