--- Makefile.orig	Wed Jan 28 22:57:33 1998
+++ Makefile	Sat Jan 31 01:00:53 1998
@@ -25,16 +25,6 @@
 	echo LD=\'`head -1 conf-ld`\' \
 	) > auto-ccld.sh
 
-auto-gid: \
-load auto-gid.o substdio.a error.a str.a fs.a
-	./load auto-gid substdio.a error.a str.a fs.a 
-
-auto-gid.o: \
-compile auto-gid.c auto-gid.c auto-gid.c subfd.h substdio.h subfd.h \
-auto-gid.c substdio.h substdio.h auto-gid.c readwrite.h auto-gid.c \
-exit.h auto-gid.c scan.h auto-gid.c fmt.h auto-gid.c
-	./compile auto-gid.c
-
 auto-int: \
 load auto-int.o substdio.a error.a str.a fs.a
 	./load auto-int substdio.a error.a str.a fs.a 
@@ -62,16 +52,6 @@
 exit.h auto-str.c
 	./compile auto-str.c
 
-auto-uid: \
-load auto-uid.o substdio.a error.a str.a fs.a
-	./load auto-uid substdio.a error.a str.a fs.a 
-
-auto-uid.o: \
-compile auto-uid.c auto-uid.c auto-uid.c subfd.h substdio.h subfd.h \
-auto-uid.c substdio.h substdio.h auto-uid.c readwrite.h auto-uid.c \
-exit.h auto-uid.c scan.h auto-uid.c fmt.h auto-uid.c
-	./compile auto-uid.c
-
 auto_break.c: \
 auto-str conf-break
 	./auto-str auto_break \
@@ -113,22 +93,17 @@
 compile auto_split.c
 	./compile auto_split.c
 
-auto_uids.c: \
-auto-uid auto-gid conf-users conf-groups
-	( ./auto-uid auto_uida `head -1 conf-users` \
-	&&./auto-uid auto_uidd `head -2 conf-users | tail -1` \
-	&&./auto-uid auto_uidl `head -3 conf-users | tail -1` \
-	&&./auto-uid auto_uido `head -4 conf-users | tail -1` \
-	&&./auto-uid auto_uidp `head -5 conf-users | tail -1` \
-	&&./auto-uid auto_uidq `head -6 conf-users | tail -1` \
-	&&./auto-uid auto_uidr `head -7 conf-users | tail -1` \
-	&&./auto-uid auto_uids `head -8 conf-users | tail -1` \
-	&&./auto-gid auto_gidq `head -1 conf-groups` \
-	&&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \
-	) > auto_uids.c
+make-owners: \
+make-owners.head conf-users conf-groups
+	cat make-owners.head >make-owners
+	for num in a d l o p q r s; do read name; \
+		echo checkuid $$num $$name; done <conf-users >>make-owners
+	for num in q n; do read name; \
+		echo checkgid $$num $$name; done <conf-groups >>make-owners
+	chmod +x make-owners
 
 auto_uids.o: \
-compile auto_uids.c
+compile auto_uids.c auto_uids.h exit.h substdio.h subfd.h
 	./compile auto_uids.c
 
 auto_usera.c: \
@@ -721,7 +696,7 @@
 qmail-popup qmail-qmtpd qmail-smtpd sendmail tcp-env dnscname dnsptr \
 dnsip dnsmxip dnsfq hostname ipmeprint qlist qlist2 qreceipt qsmhook \
 qbiff forward preline condredirect maildirmake maildir2mbox \
-maildirwatch qail elq pinq qmail-hier install instcheck
+maildirwatch qail elq pinq qmail-hier install instcheck make-owners
 
 load: \
 make-load warn-auto.sh systype
@@ -969,7 +944,7 @@
 	./compile prioq.c
 
 prot.o: \
-compile prot.c hasshsgr.h prot.c prot.h prot.c
+compile prot.c hasshsgr.h prot.c prot.h prot.c auto_uids.h
 	./compile prot.c
 
 qail: \
@@ -1111,9 +1086,9 @@
 
 qmail-hier: \
 load qmail-hier.o substdio.a error.a str.a fs.a auto_split.o \
-auto_uids.o
-	./load qmail-hier substdio.a error.a str.a fs.a \
-	auto_split.o auto_uids.o 
+auto_uids.o auto_qmail.o open.a stralloc.a
+	./load qmail-hier auto_split.o auto_uids.o fs.a \
+	substdio.a str.a error.a open.a
 
 qmail-hier.o: \
 compile qmail-hier.c subfd.h substdio.h subfd.h qmail-hier.c \
@@ -1202,10 +1177,9 @@
 load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \
 case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \
 fs.a auto_qmail.o auto_uids.o auto_spawn.o
-	./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \
+	./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o auto_uids.o \
 	sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \
-	substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
-	auto_spawn.o 
+	substdio.a error.a str.a fs.a auto_qmail.o auto_spawn.o
 
 qmail-lspawn.0: \
 qmail-lspawn.8
@@ -1386,10 +1360,10 @@
 load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
 datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
 str.a fs.a auto_qmail.o auto_split.o auto_uids.o
-	./load qmail-queue triggerpull.o fmtqfn.o now.o \
+	./load qmail-queue triggerpull.o fmtqfn.o now.o auto_uids.o \
 	date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-	auto_split.o auto_uids.o 
+	auto_split.o
 
 qmail-queue.0: \
 qmail-queue.8
@@ -1442,10 +1416,9 @@
 load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
 seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \
 auto_qmail.o auto_uids.o auto_spawn.o
-	./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \
+	./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o auto_uids.o \
 	sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \
-	substdio.a error.a str.a auto_qmail.o auto_uids.o \
-	auto_spawn.o 
+	substdio.a error.a str.a auto_qmail.o auto_spawn.o
 
 qmail-rspawn.0: \
 qmail-rspawn.8
@@ -1547,8 +1520,10 @@
 	./compile qmail-smtpd.c
 
 qmail-start: \
-load qmail-start.o prot.o fd.a auto_uids.o
-	./load qmail-start prot.o fd.a auto_uids.o 
+load qmail-start.o prot.o fd.a auto_uids.o auto_qmail.o \
+open_read.o substdio.a error.a
+	./load qmail-start prot.o auto_uids.o fd.a \
+	auto_qmail.o open_read.o substdio.a str.a error.a
 
 qmail-start.0: \
 qmail-start.8
@@ -1564,7 +1539,7 @@
 
 qmail-start.o: \
 compile qmail-start.c fd.h qmail-start.c prot.h qmail-start.c exit.h \
-qmail-start.c fork.h qmail-start.c auto_uids.h qmail-start.c
+qmail-start.c fork.h qmail-start.c
 	./compile qmail-start.c
 
 qmail-tcpto: \
@@ -1765,7 +1740,7 @@
 RFCNETSTR RFCNRUDT RFCQMTP RFCQSBMF RFCVERP SECURITY INTERNALS FILES \
 VERSION SYSDEPS TARGETS Makefile conf-break auto_break.h conf-spawn \
 auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn \
-auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h \
+auto_patrn.h conf-users conf-groups auto_usera.h extra.h \
 addresses.5 condredirect.1 dot-qmail.9 envelopes.5 forgeries.7 \
 forward.1 maildir2mbox.1 maildirmake.1 maildirwatch.1 mailsubj.1 \
 mbox.5 preline.1 qbiff.1 qlist.1 qmail-clean.8 qmail-command.8 \
@@ -1791,7 +1766,7 @@
 tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c \
 trynpbg1.c trysyslog.c conf-cc conf-ld find-systype.sh \
 make-compile.sh make-load.sh make-makelib.sh trycpp.c warn-auto.sh \
-auto-str.c auto-int.c auto-int8.c auto-gid.c auto-uid.c install.c \
+auto-str.c auto-int.c auto-int8.c install.c \
 instcheck.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \
 case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \
 cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \
@@ -1897,7 +1872,7 @@
 substdio.h spawn.c byte.h spawn.c str.h spawn.c stralloc.h \
 gen_alloc.h stralloc.h spawn.c select.h select.h select.h select.h \
 spawn.c exit.h spawn.c coe.h spawn.c open.h spawn.c error.h spawn.c \
-auto_qmail.h spawn.c auto_uids.h spawn.c auto_spawn.h spawn.c
+auto_qmail.h spawn.c auto_uids.h spawn.c auto_spawn.h spawn.c \
 	./chkspawn
 	./compile spawn.c
 
--- TARGETS.orig	Thu Jan 29 13:25:45 1998
+++ TARGETS	Sat Jan 31 01:01:09 1998
@@ -130,11 +130,6 @@
 qmail-local
 uint32.h
 qmail-lspawn.o
-auto-uid.o
-auto-uid
-auto-gid.o
-auto-gid
-auto_uids.c
 auto_uids.o
 auto-int.o
 auto-int
@@ -351,3 +346,4 @@
 envelopes.0
 forgeries.0
 man
+make-owners
--- auto_uids.c.orig	Fri Jan 30 16:02:19 1998
+++ auto_uids.c	Sat Jan 31 01:02:01 1998
@@ -0,0 +1,108 @@
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "exit.h"
+#include "subfd.h"
+#include "substdio.h"
+#include "auto_qmail.h"
+#include "auto_uids.h"
+
+/* These are offsets from the end of either uid_files or gid_files */
+
+int auto_uida = -8;
+int auto_uidd = -7;
+int auto_uidl = -6;
+int auto_uido = -5;
+int auto_uidp = -4;
+int auto_uidq = -3;
+int auto_uidr = -2;
+int auto_uids = -1;
+
+int auto_gidn = -2;
+int auto_gidq = -1;
+
+#define uid_table_size 8
+#define gid_table_size 2
+
+struct file_ref { const char *name; int *var; };
+
+static struct file_ref uid_files[uid_table_size] = {
+	{ "uida", &auto_uida },
+	{ "uidd", &auto_uidd },
+	{ "uidl", &auto_uidl },
+	{ "uido", &auto_uido },
+	{ "uidp", &auto_uidp },
+	{ "uidq", &auto_uidq },
+	{ "uidr", &auto_uidr },
+	{ "uids", &auto_uids }
+};
+
+static struct file_ref gid_files[gid_table_size] = {
+	{ "gidn", &auto_gidn },
+	{ "gidq", &auto_gidq }
+};
+
+static int stat_control_file(name, buf) char* name; struct stat* buf;
+{
+  int result;
+  char* file = malloc(strlen(auto_qmail) + strlen(name) + 10);
+  if(file == 0)
+   {
+    substdio_putsflush(subfderr,"fatal: unable to allocate memory\n");
+    _exit(111);
+   }
+  strcpy(file, auto_qmail);
+  strcat(file, "/owners/");
+  strcat(file, name);
+  result = stat(file, buf);
+  free(file);
+  return result;
+}
+
+static int stat_uid_file(ref) struct file_ref* ref;
+{
+  struct stat statbuf;
+  if(stat_control_file(ref->name, &statbuf) == -1)
+   {
+    substdio_puts(subfderr,"fatal: unable to stat uid control file '");
+    substdio_puts(subfderr,ref->name);
+    substdio_puts(subfderr,"'\n");
+    substdio_flush(subfderr);
+    _exit(111);
+   }
+  return *(ref->var) = statbuf.st_uid;
+}
+
+static int stat_gid_file(ref) struct file_ref* ref;
+{
+  struct stat statbuf;
+  if(stat_control_file(ref->name, &statbuf) == -1)
+   {
+    substdio_puts(subfderr,"fatal: unable to stat gid control file '");
+    substdio_puts(subfderr,ref->name);
+    substdio_puts(subfderr,"'\n");
+    substdio_flush(subfderr);
+    _exit(111);
+   }
+  return *(ref->var) = statbuf.st_gid;
+}
+
+int get_uid(id) int id;
+{
+  if(id >= 0)
+    return id;
+  else if(id < -uid_table_size)
+    return -1;
+  else
+    return stat_uid_file(&uid_files[uid_table_size+id]);
+}
+
+int get_gid(id) int id;
+{
+  if(id >= 0)
+    return id;
+  else if(id < -gid_table_size)
+    return -1;
+  else
+    return stat_gid_file(&gid_files[gid_table_size+id]);
+}
+
--- auto_uids.h.orig	Wed Jan 28 22:51:43 1998
+++ auto_uids.h	Fri Jan 30 16:46:41 1998
@@ -13,4 +13,7 @@
 extern int auto_gidn;
 extern int auto_gidq;
 
+extern int get_uid();
+extern int get_gid();
+
 #endif
--- make-owners.head.orig	Fri Jan 30 15:41:00 1998
+++ make-owners.head	Sat Jan 31 00:57:19 1998
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+set -e
+dir=$1
+if ! [ -d $dir ]
+then
+	echo "usage: make-owners directory"
+	exit 1
+fi
+dir=$dir/owners
+if ! [ -d $dir ]
+then
+	echo "make-owners: directory '$dir' does not exist, creating."
+	mkdir $dir
+fi
+
+checkuid() {
+  file=$dir/uid$1
+  if ! [ -e $file ]; then
+    echo "make-owners: UID file '$file' does not exist, creating."
+    touch $file
+  fi
+  chown $2 $file
+}
+
+checkgid() {
+  file=$dir/gid$1
+  if ! [ -e $file ]; then
+    echo "make-owners: GID file '$file' does not exist, creating."
+    touch $file
+  fi
+  chgrp $2 $file
+}
+
--- prot.c.orig	Wed Jan 28 22:26:16 1998
+++ prot.c	Fri Jan 30 16:54:45 1998
@@ -1,10 +1,12 @@
 #include "hasshsgr.h"
 #include "prot.h"
+#include "auto_uids.h"
 
 /* XXX: there are more portability problems here waiting to leap out at me */
 
 int prot_gid(gid) int gid;
 {
+  gid = get_gid(gid);
 #ifdef HASSHORTSETGROUPS
   short x[2];
   x[0] = gid; x[1] = 73; /* catch errors */
@@ -17,5 +19,6 @@
 
 int prot_uid(uid) int uid;
 {
+  uid = get_uid(uid);
   return setuid(uid);
 }
--- qmail-hier.c.orig	Wed Jan 28 23:36:34 1998
+++ qmail-hier.c	Sat Jan 31 01:04:36 1998
@@ -4,14 +4,21 @@
 #include "auto_uids.h"
 #include "fmt.h"
 
+/* Fool auto_uids.o into pulling the uid/gid files from the subdirectory
+ * "owners" in the current directory.  This requires that the command
+ * "./make-owners ." be executed in the source directory before running
+ * qmail-hier.
+ */
+char auto_qmail[] = ".";
+
 char strnum[FMT_ULONG];
 
 void uidgid(uid)
 int uid;
 {
-  substdio_put(subfdout,strnum,fmt_ulong(strnum,(unsigned long) uid));
+  substdio_put(subfdout,strnum,fmt_ulong(strnum,(unsigned long) get_uid(uid)));
   substdio_puts(subfdout,":");
-  substdio_put(subfdout,strnum,fmt_ulong(strnum,(unsigned long) auto_gidq));
+  substdio_put(subfdout,strnum,fmt_ulong(strnum,(unsigned long) get_gid(auto_gidq)));
   substdio_puts(subfdout,":");
 }
 
@@ -67,6 +74,7 @@
 {
   dir(auto_uido,"755","");
   dir(auto_uido,"755","/control");
+  dir(auto_uido,"755","/owners");
   dir(auto_uido,"755","/users");
   dir(auto_uido,"755","/bin");
   dir(auto_uido,"755","/man");
@@ -144,6 +152,7 @@
   copy(auto_uido,"755","/bin/","qail");
   copy(auto_uido,"755","/bin/","elq");
   copy(auto_uido,"755","/bin/","pinq");
+  copy(auto_uido,"755","/bin/","make-owners");
 
   copy(auto_uido,"644","/man/man5/","addresses.5");
   copy(auto_uido,"644","/man/cat5/","addresses.0");
--- qmail-queue.c.orig	Fri Jan 30 16:43:43 1998
+++ qmail-queue.c	Fri Jan 30 16:55:17 1998
@@ -73,11 +73,11 @@
  i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i;
  i = fmt_ulong(s,mypid); len += i; if (s) s += i;
  i = fmt_str(s," invoked "); len += i; if (s) s += i;
- if (uid == auto_uida)
+ if (uid == get_uid(auto_uida))
   { i = fmt_str(s,"by alias"); len += i; if (s) s += i; }
- else if (uid == auto_uidd)
+ else if (uid == get_uid(auto_uidd))
   { i = fmt_str(s,"from network"); len += i; if (s) s += i; }
- else if (uid == auto_uids)
+ else if (uid == get_uid(auto_uids))
   { i = fmt_str(s,"for bounce"); len += i; if (s) s += i; }
  else
   {
--- spawn.c.orig	Thu Jan 29 13:57:22 1998
+++ spawn.c	Fri Jan 30 16:58:03 1998
@@ -110,7 +110,7 @@
   { close(fdmess); err("Zqmail-spawn unable to fstat message. (#4.3.0)\n"); return; }
  if ((st.st_mode & S_IFMT) != S_IFREG)
   { close(fdmess); err("ZSorry, message has wrong type. (#4.3.5)\n"); return; }
- if (st.st_uid != auto_uidq) /* aaack! qmailq has to be trusted! */
+ if (st.st_uid != get_uid(auto_uidq)) /* aaack! qmailq has to be trusted! */
   /* your security is already toast at this point. damage control... */
   { close(fdmess); err("ZSorry, message has wrong owner. (#4.3.5)\n"); return; }
 

