+\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.
+**
+** 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 qf file 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];
+
+ /* 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);
+
+ while (c1 < '~' || c2 < 'Z')
+ {
+ int i;
+
+ if (c2 >= 'Z')
+ {
+ c1++;
+ c2 = 'A' - 1;
+ }
+ qf[2] = c1;
+ qf[3] = ++c2;
+ if (tTd(7, 20))
+ printf("queuename: trying \"%s\"\n", qf);
+
+ i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
+ if (i < 0) {
+ if (errno != EEXIST) {
+ syserr("queuename: Cannot create \"%s\" in \"%s\"",
+ qf, QueueDir);
+ exit(EX_UNAVAILABLE);
+ }
+ } else {
+ (void) close(i);
+ break;
+ }
+ }
+ 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);
+ 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
+ }
+
+ if (type == '\0')
+ return (NULL);
+ (void) sprintf(buf, "%cf%s", type, e->e_id);
+ if (tTd(7, 2))
+ printf("queuename: %s\n", buf);
+ 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 LOG
+ if (LogLevel > 19)
+ syslog(LOG_DEBUG, "%s: unlock", e->e_id);
+# endif LOG
+ if (!tTd(51, 4))
+ xunlink(queuename(e, 'x'));
+
+}
+\f/*
+** GETCTLUSER -- return controlling user if mailing to prog or file
+**
+** Check for a "|" or "/" at the beginning of the address. If
+** found, return a controlling username.
+**
+** Parameters:
+** a - the address to check out
+**
+** Returns:
+** Either NULL, if we werent mailing to a program or file,
+** or a controlling user name (possibly in getpwuid's
+** static buffer).
+**
+** Side Effects:
+** none.
+*/
+
+char *
+getctluser(a)
+ ADDRESS *a;
+{
+ extern ADDRESS *getctladdr();
+ struct passwd *pw;
+ char *retstr;
+
+ /*
+ ** Get unquoted user for file, program or user.name check.
+ ** N.B. remove this code block to always emit controlling
+ ** addresses (at the expense of backward compatibility).
+ */
+
+ {
+ char buf[MAXNAME];
+ (void) strncpy(buf, a->q_paddr, MAXNAME);
+ buf[MAXNAME-1] = '\0';
+ stripquotes(buf, TRUE);
+
+ if (buf[0] != '|' && buf[0] != '/')
+ return((char *)NULL);
+ }
+
+ a = getctladdr(a); /* find controlling address */
+
+ if (a != NULL && a->q_uid != 0 && (pw = getpwuid(a->q_uid)) != NULL)
+ retstr = pw->pw_name;
+ else /* use default user */
+ retstr = DefUser;
+
+ if (tTd(40, 5))
+ printf("Set controlling user for `%s' to `%s'\n",
+ (a == NULL)? "<null>": a->q_paddr, retstr);
+
+ return(retstr);
+}
+\f/*
+** SETCTLUSER - sets `CtlUser' to controlling user
+** CLRCTLUSER - clears controlling user (no params, nothing returned)
+**
+** These routines manipulate `CtlUser'.
+**
+** Parameters:
+** str - controlling user as passed to setctluser()
+**
+** Returns:
+** None.
+**
+** Side Effects:
+** `CtlUser' is changed.
+*/
+
+static char CtlUser[MAXNAME];
+
+setctluser(str)
+register char *str;
+{
+ (void) strncpy(CtlUser, str, MAXNAME);
+ CtlUser[MAXNAME-1] = '\0';
+}
+
+clrctluser()
+{
+ CtlUser[0] = '\0';
+}
+
+\f/*
+** SETCTLADDR -- create a controlling address
+**
+** If global variable `CtlUser' is set and we are given a valid
+** address, make that address a controlling address; change the
+** `q_uid', `q_gid', and `q_ruser' fields and set QGOODUID.
+**
+** Parameters:
+** a - address for which control uid/gid info may apply
+**
+** Returns:
+** None.
+**
+** Side Effects:
+** Fills in uid/gid fields in address and sets QGOODUID
+** flag if appropriate.
+*/
+
+setctladdr(a)
+ ADDRESS *a;
+{
+ struct passwd *pw;
+
+ /*
+ ** If there is no current controlling user, or we were passed a
+ ** NULL addr ptr or we already have a controlling user, return.
+ */
+
+ if (CtlUser[0] == '\0' || a == NULL || a->q_ruser)
+ return;
+
+ /*
+ ** Set up addr fields for controlling user. If `CtlUser' is no
+ ** longer valid, use the default user/group.
+ */
+
+ if ((pw = getpwnam(CtlUser)) != NULL)
+ {
+ if (a->q_home)
+ free(a->q_home);
+ a->q_home = newstr(pw->pw_dir);
+ a->q_uid = pw->pw_uid;
+ a->q_gid = pw->pw_gid;
+ a->q_ruser = newstr(CtlUser);
+ }
+ else
+ {
+ a->q_uid = DefUid;
+ a->q_gid = DefGid;
+ a->q_ruser = newstr(DefUser);
+ }
+
+ a->q_flags |= QGOODUID; /* flag as a "ctladdr" */
+
+ if (tTd(40, 5))
+ printf("Restored controlling user for `%s' to `%s'\n",
+ a->q_paddr, a->q_ruser);
+}