+\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
+}