[comp.sources.bugs] Deliver 1.00 patch #7

chip@ateng.ateng.com (Chip Salzenberg) (02/11/89)

This is an offical patch for deliver 1.00.  Please apply it.

Patch number:   7
Date:           10 Feb 1989
Priority:       REQUIRED for V7, LOW otherwise
Changes:
        Deliver was originally written without concern for portability to
        Unix Classic (V7).  However, a particularly dedicated V7 user, Pete
        Alleman <digitran!pja>, ported deliver to V7.  Loathe to throw away
        the results of his labor, I have taken his ideas and incorporated
	them into the offical deliver sources.  Thanks, Pete.

	BTW, Berkeley sites should be able to compile without BSD defined,
	since V7 is a subset of BSD.


Index: patchlevel.h
Prereq: 6
***************
*** 1 ****
! #define PATCHLEVEL 6
--- 1 ----
! #define PATCHLEVEL 7

Index: config.h
***************
*** 1,8 ****
! /* $Header: config.h,v 1.6 88/11/26 13:19:37 network Exp $
   *
   * Deliver configuration.
   *
   * $Log:	config.h,v $
   * Revision 1.6  88/11/26  13:19:37  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
--- 1,14 ----
! /* $Header: config.h,v 1.8 89/02/10 18:08:24 network Exp $
   *
   * Deliver configuration.
   *
   * $Log:	config.h,v $
+  * Revision 1.8  89/02/10  18:08:24  network
+  * Fix location of mailboxes.
+  * 
+  * Revision 1.7  89/02/10  15:45:51  network
+  * V7 support.
+  * 
   * Revision 1.6  88/11/26  13:19:37  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
***************
*** 33,38 ****
--- 39,54 ----
   */
  
  /*----------------------------------------------------------------------
+  * SCO Xenix System V compilers define M_SYSV, which implies USG.
+  */
+ 
+ #ifdef M_SYSV
+ #ifndef USG
+ #define USG
+ #endif
+ #endif
+ 
+ /*----------------------------------------------------------------------
   * Trusted users.
   * Deliver permits "trusted" users to specify delivery filenames
   * without renouncing setuid privileges.  Essentially, these users
***************
*** 97,106 ****
--- 113,124 ----
  
  /*----------------------------------------------------------------------
   * How to get the host name.
+  * Define one.
   *
   * HOSTFILE             file containing name    (Xenix)
   * UNAME                uname()                 (System V)
   * GETHOSTNAME          gethostname()           (BSD)
+  * HOSTNAME             host name string        (V7)
   */
  
  #ifdef M_XENIX
***************
*** 111,125 ****
  #else
  #ifdef BSD
  #define GETHOSTNAME
  #endif
  #endif
  #endif
  
  /*----------------------------------------------------------------------
   * Are vprintf() and friends available?
   */
  
! #ifndef BSD
  #define HAS_VPRINTF
  #endif
  
--- 129,161 ----
  #else
  #ifdef BSD
  #define GETHOSTNAME
+ #else
+ #define HOSTNAME   "cleese"
  #endif
  #endif
  #endif
  
  /*----------------------------------------------------------------------
+  * Is <varargs.h> or <stdarg.h> available?
+  */
+ 
+ #ifdef __STDC__
+ #define HAS_STDARG
+ #else
+ #ifdef USG
+ #define HAS_VARARGS
+ #else
+ #ifdef BSD
+ #define HAS_VARARGS
+ #endif
+ #endif
+ #endif
+ 
+ /*----------------------------------------------------------------------
   * Are vprintf() and friends available?
   */
  
! #ifdef USG
  #define HAS_VPRINTF
  #endif
  
***************
*** 127,133 ****
   * Is putenv() available?
   */
  
! #ifndef BSD
  #define HAS_PUTENV
  #endif
  
--- 163,169 ----
   * Is putenv() available?
   */
  
! #ifdef USG
  #define HAS_PUTENV
  #endif
  
***************
*** 135,141 ****
   * Is getopt() available?
   */
  
! #ifndef BSD
  #define HAS_GETOPT
  #endif
  
--- 171,177 ----
   * Is getopt() available?
   */
  
! #ifdef USG
  #define HAS_GETOPT
  #endif
  
***************
*** 163,191 ****
  /*----------------------------------------------------------------------
   * Standard mailbox location.
   *
!  * Define either MAILBOX_NAME or MAILBOX_DIR.
!  * If MAILBOX_NAME is defined, then the default mailbox is a file with
   * that name in the user's home directory.
!  * If MAILBOX_DIR is defined, then the default mailbox is a file in that
   * directory with the same name as the user.
   *
!  * Define MAILBOX_GROUP if all mailboxes must be owned by a specific group.
!  * (System V requires this feature.)  If MAILBOX_GROUP is not defined,
   * mailboxes will have their groups set to the recipients' default group.
   *
!  * Define MAILBOX_MODE to the file access modes for new mailboxes.
   * (System V requires group write permissions, i.e. 0020.)
   */
  
! #ifdef USG
! /* #define MAILBOX_NAME   "mbox" */
! #define MAILBOX_DIR     "/usr/mail"
! #define MAILBOX_MODE    0660
! #define MAILBOX_GROUP   "mail"
  #else
! /* #define MAILBOX_NAME   "mbox" */
! #define MAILBOX_DIR     "/usr/spool/mail"
! #define MAILBOX_MODE    0600
  #endif
  
  /*----------------------------------------------------------------------
--- 199,227 ----
  /*----------------------------------------------------------------------
   * Standard mailbox location.
   *
!  * Define either MBX_NAME or MBOX_DIR.
!  * If MBX_NAME is defined, then the default mailbox is a file with
   * that name in the user's home directory.
!  * If MBX_DIR is defined, then the default mailbox is a file in that
   * directory with the same name as the user.
   *
!  * Define MBX_GROUP if all mailboxes must be owned by a specific group.
!  * (System V requires this feature.)  If MBX_GROUP is not defined,
   * mailboxes will have their groups set to the recipients' default group.
   *
!  * Define MBX_MODE to the file access modes for new mailboxes.
   * (System V requires group write permissions, i.e. 0020.)
   */
  
! #if defined(USG) && !defined(M_XENIX)
! /* #define MBX_NAME   "mbox" */
! #define MBX_DIR     "/usr/mail"
! #define MBX_MODE    0660
! #define MBX_GROUP   "mail"
  #else
! /* #define MBX_NAME   "mbox" */
! #define MBX_DIR     "/usr/spool/mail"
! #define MBX_MODE    0600
  #endif
  
  /*----------------------------------------------------------------------

Index: context.c
***************
*** 1,4 ****
! /* $Header: context.c,v 1.3 88/09/14 19:41:40 network Exp $
   *
   * User context manager.
   * This module exists for efficiency reasons; I could just call getpwnam()
--- 1,4 ----
! /* $Header: context.c,v 1.4 89/02/10 15:46:09 network Exp $
   *
   * User context manager.
   * This module exists for efficiency reasons; I could just call getpwnam()
***************
*** 5,10 ****
--- 5,13 ----
   * every time I need context info.
   *
   * $Log:	context.c,v $
+  * Revision 1.4  89/02/10  15:46:09  network
+  * V7 support.
+  * 
   * Revision 1.3  88/09/14  19:41:40  network
   * Portability to System V and BSD.
   * General fixup.
***************
*** 49,57 ****
  	struct passwd *pw;
  	CONTEXT *ct;
  
! 	for (ct = ctlist; ct; ct = ct->next)
  	{
! 		if (strcmp(ct->name, name) == 0)
  			return ct;
  	}
  
--- 52,60 ----
  	struct passwd *pw;
  	CONTEXT *ct;
  
! 	for (ct = ctlist; ct; ct = ct->ct_next)
  	{
! 		if (strcmp(ct->ct_name, name) == 0)
  			return ct;
  	}
  
***************
*** 72,80 ****
  	struct passwd *pw;
  	CONTEXT *ct;
  
! 	for (ct = ctlist; ct; ct = ct->next)
  	{
! 		if (ct->uid == uid)
  			return ct;
  	}
  
--- 75,83 ----
  	struct passwd *pw;
  	CONTEXT *ct;
  
! 	for (ct = ctlist; ct; ct = ct->ct_next)
  	{
! 		if (ct->ct_uid == uid)
  			return ct;
  	}
  
***************
*** 96,107 ****
  	CONTEXT *ct;
  
  	ct = (CONTEXT *) zalloc(sizeof(CONTEXT));
! 	ct->uid = pw->pw_uid;
! 	ct->gid = pw->pw_gid;
! 	ct->name = copystr(pw->pw_name);
! 	ct->home = copystr(pw->pw_dir);
  
! 	ct->next = ctlist;
  	ctlist = ct;
  
  	return ct;
--- 99,110 ----
  	CONTEXT *ct;
  
  	ct = (CONTEXT *) zalloc(sizeof(CONTEXT));
! 	ct->ct_uid = pw->pw_uid;
! 	ct->ct_gid = pw->pw_gid;
! 	ct->ct_name = copystr(pw->pw_name);
! 	ct->ct_home = copystr(pw->pw_dir);
  
! 	ct->ct_next = ctlist;
  	ctlist = ct;
  
  	return ct;
***************
*** 119,125 ****
  		return FALSE;
  
  	if (eff_uid == 0
! 	 || ((real_uid == ct->uid) && (real_gid == ct->gid)))
  		return TRUE;
  	else
  		return FALSE;
--- 122,128 ----
  		return FALSE;
  
  	if (eff_uid == 0
! 	 || ((real_uid == ct->ct_uid) && (real_gid == ct->ct_gid)))
  		return TRUE;
  	else
  		return FALSE;
***************
*** 129,135 ****
   * Look up a group ID by name.
   */
  
! #ifdef MAILBOX_GROUP
  
  int
  group_id(name)
--- 132,138 ----
   * Look up a group ID by name.
   */
  
! #ifdef MBX_GROUP
  
  int
  group_id(name)
***************
*** 143,146 ****
  	return grp->gr_gid;
  }
  
! #endif /* MAILBOX_GROUP */
--- 146,149 ----
  	return grp->gr_gid;
  }
  
! #endif /* MBX_GROUP */

Index: context.h
***************
*** 1,8 ****
! /* $Header: context.h,v 1.1 88/06/06 09:37:40 chip Exp $
   *
   * User context, as found in /etc/passwd.
   *
   * $Log:	context.h,v $
   * Revision 1.1  88/06/06  09:37:40  chip
   * Initial revision
   * 
--- 1,11 ----
! /* $Header: context.h,v 1.2 89/02/10 15:46:13 network Exp $
   *
   * User context, as found in /etc/passwd.
   *
   * $Log:	context.h,v $
+  * Revision 1.2  89/02/10  15:46:13  network
+  * V7 support.
+  * 
   * Revision 1.1  88/06/06  09:37:40  chip
   * Initial revision
   * 
***************
*** 14,22 ****
  
  #define CONTEXT struct context
  CONTEXT {
! 	CONTEXT *next;
! 	int     uid;
! 	int     gid;
! 	char    *name;
! 	char    *home;
  };
--- 17,25 ----
  
  #define CONTEXT struct context
  CONTEXT {
! 	CONTEXT *ct_next;
! 	int     ct_uid;
! 	int     ct_gid;
! 	char    *ct_name;
! 	char    *ct_home;
  };

Index: copymsg.c
***************
*** 1,9 ****
! /* $Header: copymsg.c,v 1.3 88/11/28 18:07:46 network Exp $
   *
   * Take the message from standard input and write it to two temp files,
   * one for the header (including the empty line) and one for the body.
   *
   * $Log:	copymsg.c,v $
   * Revision 1.3  88/11/28  18:07:46  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
--- 1,12 ----
! /* $Header: copymsg.c,v 1.4 89/02/10 15:46:17 network Exp $
   *
   * Take the message from standard input and write it to two temp files,
   * one for the header (including the empty line) and one for the body.
   *
   * $Log:	copymsg.c,v $
+  * Revision 1.4  89/02/10  15:46:17  network
+  * V7 support.
+  * 
   * Revision 1.3  88/11/28  18:07:46  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
***************
*** 145,151 ****
  
  	/* else use our real ID */
  	else
! 		sender = real_ct->name;
  
  	/* debugging message */
  
--- 148,154 ----
  
  	/* else use our real ID */
  	else
! 		sender = real_ct->ct_name;
  
  	/* debugging message */
  
***************
*** 398,408 ****
  {
  	int     fd;
  
! 	if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0)) == -1)
  	{
  		syserr("can't create %s", name);
  		return -1;
  	}
  
  	return fd;
  }
--- 401,425 ----
  {
  	int     fd;
  
! #ifdef O_CREAT
! 	fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0);
! #else
! 	fd = creat(name, 0);
! #endif
! 	if (fd == -1)
  	{
  		syserr("can't create %s", name);
  		return -1;
  	}
+ 
+ #ifndef O_CREAT
+ 	(void) close(fd);
+ 	if ((fd = open(name, 2)) == -1)
+ 	{
+ 		syserr("can't re-open %s", name);
+ 		return -1;
+ 	}
+ #endif
  
  	return fd;
  }

Index: debug.c
***************
*** 1,8 ****
! /* $Header: debug.c,v 1.2 88/11/26 13:20:38 network Exp $
   *
   * Debugging output.
   *
   * $Log:	debug.c,v $
   * Revision 1.2  88/11/26  13:20:38  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
--- 1,11 ----
! /* $Header: debug.c,v 1.3 89/02/10 15:46:24 network Exp $
   *
   * Debugging output.
   *
   * $Log:	debug.c,v $
+  * Revision 1.3  89/02/10  15:46:24  network
+  * V7 support.
+  * 
   * Revision 1.2  88/11/26  13:20:38  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
***************
*** 28,42 ****
  	message("Destinations %s:\n", when);
  	for (d = first_dest(); d; d = next_dest(d))
  	{
! 		message("\t%s", d->name);
  
! 		switch (d->class)
  		{
  		case CL_USER:
  			/* it's understood */
  			break;
  		case CL_MBOX:
! 			message(", mailbox='%s'", d->mailbox);
  			break;
  		case CL_UUCP:
  			message(" (UUCP)");
--- 31,45 ----
  	message("Destinations %s:\n", when);
  	for (d = first_dest(); d; d = next_dest(d))
  	{
! 		message("\t%s", d->d_name);
  
! 		switch (d->d_class)
  		{
  		case CL_USER:
  			/* it's understood */
  			break;
  		case CL_MBOX:
! 			message(", mailbox='%s'", d->d_mailbox);
  			break;
  		case CL_UUCP:
  			message(" (UUCP)");
***************
*** 43,49 ****
  			break;
  		}
  		message("; ");
! 		switch (d->state)
  		{
  		case ST_WORKING:
  			message("Working");
--- 46,52 ----
  			break;
  		}
  		message("; ");
! 		switch (d->d_state)
  		{
  		case ST_WORKING:
  			message("Working");
***************
*** 55,61 ****
  			message("Done");
  			break;
  		case ST_ERROR:
! 			message("Error (%s)", d->error);
  			break;
  		}
  		message("\n");
--- 58,64 ----
  			message("Done");
  			break;
  		case ST_ERROR:
! 			message("Error (%s)", derrmsg(d->d_error));
  			break;
  		}
  		message("\n");

Index: deliver.h
***************
*** 1,8 ****
! /* $Header: deliver.h,v 1.6 88/11/28 18:07:53 network Exp $
   *
   * General pull-it-together include file.
   *
   * $Log:	deliver.h,v $
   * Revision 1.6  88/11/28  18:07:53  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
--- 1,11 ----
! /* $Header: deliver.h,v 1.7 89/02/10 15:46:27 network Exp $
   *
   * General pull-it-together include file.
   *
   * $Log:	deliver.h,v $
+  * Revision 1.7  89/02/10  15:46:27  network
+  * V7 support.
+  * 
   * Revision 1.6  88/11/28  18:07:53  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
***************
*** 28,34 ****
   */
  
  #include <stdio.h>
- #include <fcntl.h>
  #include <ctype.h>
  
  #include "config.h"
--- 31,36 ----
***************
*** 87,92 ****
--- 89,95 ----
  char    *basename();
  char    *gethost();
  char    *copystr();
+ char    *derrmsg();
  char    *zalloc();
  char    *srealloc();
  

Index: dest.c
***************
*** 1,8 ****
! /* $Header: dest.c,v 1.3 88/11/26 13:20:42 network Exp $
   *
   * Operations on the list of mail destinations.
   *
   * $Log:	dest.c,v $
   * Revision 1.3  88/11/26  13:20:42  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
--- 1,11 ----
! /* $Header: dest.c,v 1.4 89/02/10 15:46:31 network Exp $
   *
   * Operations on the list of mail destinations.
   *
   * $Log:	dest.c,v $
+  * Revision 1.4  89/02/10  15:46:31  network
+  * V7 support.
+  * 
   * Revision 1.3  88/11/26  13:20:42  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
***************
*** 46,57 ****
  	else
  		class = CL_USER;
  
! 	for (d = HEADPTR->next; d != HEADPTR; d = d->next)
  	{
! 		if (d->class != class)
  			continue;
  
! 		if (strcmp(d->name, name) != 0)
  			continue;
  
  		/*
--- 49,60 ----
  	else
  		class = CL_USER;
  
! 	for (d = HEADPTR->d_next; d != HEADPTR; d = d->d_next)
  	{
! 		if (d->d_class != class)
  			continue;
  
! 		if (strcmp(d->d_name, name) != 0)
  			continue;
  
  		/*
***************
*** 60,66 ****
  		 */
  
  		if (class == CL_MBOX
! 		 && strcmp(d->mailbox, mailbox) != 0)
  			continue;
  
  		/*
--- 63,69 ----
  		 */
  
  		if (class == CL_MBOX
! 		 && strcmp(d->d_mailbox, mailbox) != 0)
  			continue;
  
  		/*
***************
*** 75,85 ****
  	 */
  
  	d = (DEST *) zalloc(sizeof(DEST));
! 	d->class = class;
! 	d->state = ST_WORKING;
! 	d->name = copystr(name);
  	if (class == CL_MBOX)
! 		d->mailbox = copystr(mailbox);
  
  	/*
  	 * Check address for validity.
--- 78,88 ----
  	 */
  
  	d = (DEST *) zalloc(sizeof(DEST));
! 	d->d_class = class;
! 	d->d_state = ST_WORKING;
! 	d->d_name = copystr(name);
  	if (class == CL_MBOX)
! 		d->d_mailbox = copystr(mailbox);
  
  	/*
  	 * Check address for validity.
***************
*** 86,101 ****
  	 */
  
  	if (!valid_address(name))
! 	{
! 		d->state = ST_ERROR;
! 		d->error = "Invalid address string";
! 	}
! 	else if (class != CL_UUCP
! 	 && name_context(name) == NULL)
! 	{
! 		d->state = ST_ERROR;
! 		d->error = "No such user";
! 	}
  
  	/*
  	 * Put new address at the end of of the chain.
--- 89,97 ----
  	 */
  
  	if (!valid_address(name))
! 		dest_err(d, E_IVADDR);
! 	else if (class != CL_UUCP && name_context(name) == NULL)
! 		dest_err(d, E_NSUSER);
  
  	/*
  	 * Put new address at the end of of the chain.
***************
*** 102,111 ****
  	 * (This is important!  Other code depends on it.)
  	 */
  
! 	d->prev = HEADPTR->prev;
! 	d->next = HEADPTR;
! 	d->prev->next = d;
! 	d->next->prev = d;
  
  	return d;
  }
--- 98,107 ----
  	 * (This is important!  Other code depends on it.)
  	 */
  
! 	d->d_prev = HEADPTR->d_prev;
! 	d->d_next = HEADPTR;
! 	d->d_prev->d_next = d;
! 	d->d_next->d_prev = d;
  
  	return d;
  }
***************
*** 117,124 ****
  DEST *
  first_dest()
  {
! 	if (HEADPTR->next != HEADPTR)
! 		return HEADPTR->next;
  
  	return NULL;
  }
--- 113,120 ----
  DEST *
  first_dest()
  {
! 	if (HEADPTR->d_next != HEADPTR)
! 		return HEADPTR->d_next;
  
  	return NULL;
  }
***************
*** 131,138 ****
  next_dest(d)
  DEST    *d;
  {
! 	if (d && (d = d->next) != HEADPTR)
  		return d;
  
  	return NULL;
  }
--- 127,166 ----
  next_dest(d)
  DEST    *d;
  {
! 	if (d && (d = d->d_next) != HEADPTR)
  		return d;
  
  	return NULL;
+ }
+ 
+ /*----------------------------------------------------------------------
+  * Return an error message given a DERROR.
+  */
+ 
+ char *
+ derrmsg(e)
+ DERROR  e;
+ {
+ 	static  char    unknown_buf[40];
+ 
+ 	switch (e)
+ 	{
+ 	case E_IVADDR:
+ 		return "Invalid address string";
+ 	case E_NSUSER:
+ 		return "No such user";
+ 	case E_NSHOST:
+ 		return "No such host (UUCP addresses)";
+ 	case E_CTPERM:
+ 		return "No permissions for that context";
+ 	case E_CTLOST:
+ 		return "Context lost (should never happen)";
+ 	case E_MBOX:
+ 		return "Can't write to mailbox";
+ 	case E_UUX:
+ 		return "Can't pipe to uux";
+ 	}
+ 
+ 	(void) sprintf(unknown_buf, "Unknown error %d", e);
+ 	return unknown_buf;
  }

Index: dest.h
***************
*** 1,8 ****
! /* $Header: dest.h,v 1.1 88/06/06 09:37:48 chip Exp $
   *
   * Description of a mail destination and its state.
   *
   * $Log:	dest.h,v $
   * Revision 1.1  88/06/06  09:37:48  chip
   * Initial revision
   * 
--- 1,11 ----
! /* $Header: dest.h,v 1.2 89/02/10 15:46:38 network Exp $
   *
   * Description of a mail destination and its state.
   *
   * $Log:	dest.h,v $
+  * Revision 1.2  89/02/10  15:46:38  network
+  * V7 support.
+  * 
   * Revision 1.1  88/06/06  09:37:48  chip
   * Initial revision
   * 
***************
*** 30,47 ****
  } DSTATE;
  
  /*----------------------------------------------------------------------
   * Structure describing a mail destination.
   */
  
  #define DEST    struct dest
  DEST {
! 	DEST    *next;          /* next destination in the chain        */
! 	DEST    *prev;          /* previous destination in the chain    */
! 	DCLASS  class;          /* destination class                    */
! 	DSTATE  state;          /* destination state                    */
! 	int     dfdone;         /* boolean -- delivery file was run     */
! 	char    *name;          /* context for delivery                 */
! 	char    *mailbox;       /* mailbox name or NULL for default     */
! 	char    *error;         /* error message (if state is ERROR)    */
  };
  
--- 33,69 ----
  } DSTATE;
  
  /*----------------------------------------------------------------------
+  * Types of destination errors.
+  */
+ 
+ typedef enum {
+ 	E_IVADDR,               /* invalid address string               */
+ 	E_NSUSER,               /* no such user                         */
+ 	E_NSHOST,               /* no such host (UUCP addresses)        */
+ 	E_CTPERM,               /* no permissions for that context      */
+ 	E_CTLOST,               /* context lost (should never happen)   */
+ 	E_MBOX,                 /* can't write to mailbox               */
+ 	E_UUX                   /* can't pipe to uux                    */
+ } DERROR;
+ 
+ /*----------------------------------------------------------------------
   * Structure describing a mail destination.
   */
  
  #define DEST    struct dest
  DEST {
! 	DEST    *d_next;        /* next destination in the chain        */
! 	DEST    *d_prev;        /* previous destination in the chain    */
! 	DCLASS  d_class;        /* destination class                    */
! 	DSTATE  d_state;        /* destination state                    */
! 	DERROR  d_error;        /* error message (if state is ERROR)    */
! 	int     d_dfdone;       /* boolean -- delivery file was run     */
! 	char    *d_name;        /* context for delivery                 */
! 	char    *d_mailbox;     /* mailbox name or NULL for default     */
  };
  
+ /*----------------------------------------------------------------------
+  * Action macros.
+  */
+ 
+ #define dest_err(d,m)   ((d)->d_state = ST_ERROR, (d)->d_error = (m))

Index: dfile.c
***************
*** 1,8 ****
! /* $Header: dfile.c,v 1.6 88/11/28 18:07:57 network Exp $
   *
   * Filter destination(s) through delivery file(s).
   *
   * $Log:	dfile.c,v $
   * Revision 1.6  88/11/28  18:07:57  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
--- 1,11 ----
! /* $Header: dfile.c,v 1.7 89/02/10 15:46:42 network Exp $
   *
   * Filter destination(s) through delivery file(s).
   *
   * $Log:	dfile.c,v $
+  * Revision 1.7  89/02/10  15:46:42  network
+  * V7 support.
+  * 
   * Revision 1.6  88/11/28  18:07:57  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
***************
*** 148,159 ****
  		nfound = 0;
  		for (d = first_dest(); d; d = next_dest(d))
  		{
! 			if (d->class == CL_USER
! 			 && d->state == ST_WORKING
! 			 && !d->dfdone)
  			{
  				one_dfile(d);
! 				d->dfdone = TRUE;
  			}
  		}
  	} while (nfound > 0);
--- 151,162 ----
  		nfound = 0;
  		for (d = first_dest(); d; d = next_dest(d))
  		{
! 			if (d->d_class == CL_USER
! 			 && d->d_state == ST_WORKING
! 			 && !d->d_dfdone)
  			{
  				one_dfile(d);
! 				d->d_dfdone = TRUE;
  			}
  		}
  	} while (nfound > 0);
***************
*** 173,182 ****
  	char    udel_path[100];
  	struct stat st;
  
! 	if ((ct = name_context(d->name)) == NULL)
  	{
! 		d->state = ST_ERROR;
! 		d->error = "Missing context in user_dfile_one()";
  		return;
  	}
  
--- 176,184 ----
  	char    udel_path[100];
  	struct stat st;
  
! 	if ((ct = name_context(d->d_name)) == NULL)
  	{
! 		dest_err(d, E_CTLOST);
  		return;
  	}
  
***************
*** 187,198 ****
  	 * Thanks to Jon Zeeff for this hint...
  	 */
  
! 	if (stat(ct->home, &st) == -1
  	 || (st.st_mode & S_IFMT) != S_IFDIR)
  	{
  		if (verbose)
  			message("user %s: home directory %s is missing!\n",
! 				ct->name, ct->home);
  		return;
  	}
  
--- 189,200 ----
  	 * Thanks to Jon Zeeff for this hint...
  	 */
  
! 	if (stat(ct->ct_home, &st) == -1
  	 || (st.st_mode & S_IFMT) != S_IFDIR)
  	{
  		if (verbose)
  			message("user %s: home directory %s is missing!\n",
! 				ct->ct_name, ct->ct_home);
  		return;
  	}
  
***************
*** 200,206 ****
  	{
  		if (verbose)
  			message("user %s: home directory is writable to the world!\n",
! 				ct->name);
  		return;
  	}
  
--- 202,208 ----
  	{
  		if (verbose)
  			message("user %s: home directory is writable to the world!\n",
! 				ct->ct_name);
  		return;
  	}
  
***************
*** 208,218 ****
  	 * If there is no delivery file to execute, just return.
  	 */
  
! 	(void) sprintf(udel_path, "%s/%s", ct->home, user_deliver);
  	if (stat(udel_path, &st) == -1)
  	{
  		if (verbose)
! 			message("%s has no delivery file\n", d->name);
  		return;
  	}
  
--- 210,220 ----
  	 * If there is no delivery file to execute, just return.
  	 */
  
! 	(void) sprintf(udel_path, "%s/%s", ct->ct_home, user_deliver);
  	if (stat(udel_path, &st) == -1)
  	{
  		if (verbose)
! 			message("%s has no delivery file\n", d->d_name);
  		return;
  	}
  
***************
*** 222,232 ****
  	 * the delivery file names it.
  	 */
  
! 	d->state = ST_HOLD;
  
  	fav[0] = shell;
  	fav[1] = udel_path;
! 	fav[2] = d->name;
  	fav[3] = NULL;
  	(void) do_dfile(ct, fav, d);
  }
--- 224,234 ----
  	 * the delivery file names it.
  	 */
  
! 	d->d_state = ST_HOLD;
  
  	fav[0] = shell;
  	fav[1] = udel_path;
! 	fav[2] = d->d_name;
  	fav[3] = NULL;
  	(void) do_dfile(ct, fav, d);
  }
***************
*** 250,261 ****
  	if (! ok_context(ct))
  	{
  		if (d)
! 		{
! 			d->state = ST_ERROR;
! 			d->error = "No permissions for that context";
! 		}
  		else
! 			message("No permissions to run as %s\n", ct);
  
  		return -1;
  	}
--- 252,260 ----
  	if (! ok_context(ct))
  	{
  		if (d)
! 			dest_err(d, E_CTPERM);
  		else
! 			message("No permissions to run as %s\n", ct->ct_name);
  
  		return -1;
  	}
***************
*** 273,283 ****
  	/* Here we go! */
  
  	if (verbose)
! 		message("Processing delivery file as %s\n", ct->name);
  
  	if ((fp = ct_popenv(ct, shell, av, "r")) == NULL)
  	{
! 		error("can't execute delivery file as %s\n", ct->name);
  		leave(1);
  	}
  
--- 272,282 ----
  	/* Here we go! */
  
  	if (verbose)
! 		message("Processing delivery file as %s\n", ct->ct_name);
  
  	if ((fp = ct_popenv(ct, shell, av, "r")) == NULL)
  	{
! 		error("can't execute delivery file as %s\n", ct->ct_name);
  		leave(1);
  	}
  
***************
*** 290,297 ****
  		DEST    *nd;
  
  		nd = dest(name, mailbox);
! 		if (nd->state == ST_HOLD)
! 			nd->state = ST_WORKING;
  
  		/*
  		 * If the delivery file specified a mailbox, verify
--- 289,296 ----
  		DEST    *nd;
  
  		nd = dest(name, mailbox);
! 		if (nd->d_state == ST_HOLD)
! 			nd->d_state = ST_WORKING;
  
  		/*
  		 * If the delivery file specified a mailbox, verify
***************
*** 299,318 ****
  		 * permissions for the requested context.
  		 */
  
! 		if ((nd->state == ST_WORKING) && (mailbox != NULL))
  		{
  			CONTEXT *nct;
  
  			if ((nct = name_context(name)) == NULL)
! 			{
! 				nd->state = ST_ERROR;
! 				nd->error = "Lost context in do_dfile()";
! 			}
  			else if (! ok_context(nct))
! 			{
! 				nd->state = ST_ERROR;
! 				nd->error = "No permissions for that context";
! 			}
  		}
  	}
  
--- 298,311 ----
  		 * permissions for the requested context.
  		 */
  
! 		if ((nd->d_state == ST_WORKING) && (mailbox != NULL))
  		{
  			CONTEXT *nct;
  
  			if ((nct = name_context(name)) == NULL)
! 				dest_err(nd, E_CTLOST);
  			else if (! ok_context(nct))
! 				dest_err(nd, E_CTPERM);
  		}
  	}
  
***************
*** 403,412 ****
  			syserr("can't chmod %s", tfile[t]);
  			++err;
  		}
! 		if (chown(tfile[t], ct->uid, ct->gid) == -1)
  		{
  			syserr("can't chown %s to %d/%d",
! 				tfile[t], ct->uid, ct->gid);
  			++err;
  		}
  	}
--- 396,405 ----
  			syserr("can't chmod %s", tfile[t]);
  			++err;
  		}
! 		if (chown(tfile[t], ct->ct_uid, ct->ct_gid) == -1)
  		{
  			syserr("can't chown %s to %d/%d",
! 				tfile[t], ct->ct_uid, ct->ct_gid);
  			++err;
  		}
  	}

Index: getopt.c
***************
*** 1,15 ****
! /* $Header: getopt.c,v 1.2 88/11/30 16:24:50 network Exp $
   *
   * A version of the public-domain getopt() function, as found
   * in the SVID and fine Unix manuals everywhere.
   *
   * $Log:	getopt.c,v $
   * Revision 1.2  88/11/30  16:24:50  network
   * patch6:  Separate getopt() into its own module.
   * 
   */
  
  #include "config.h"
  
  /*----------------------------------------------------------------------
   * Get command line options.
--- 1,20 ----
! /* $Header: getopt.c,v 1.3 89/02/10 15:46:49 network Exp $
   *
   * A version of the public-domain getopt() function, as found
   * in the SVID and fine Unix manuals everywhere.
   *
   * $Log:	getopt.c,v $
+  * Revision 1.3  89/02/10  15:46:49  network
+  * V7 support.
+  * 
   * Revision 1.2  88/11/30  16:24:50  network
   * patch6:  Separate getopt() into its own module.
   * 
   */
  
+ #include <stdio.h>
  #include "config.h"
+ #include "misc.h"
  
  /*----------------------------------------------------------------------
   * Get command line options.

Index: lock.c
***************
*** 1,9 ****
! /* $Header: lock.c,v 1.2 88/08/30 16:13:14 network Exp $
   *
   * Mailbox locking.
   * Local hacks for mailbox access should be grafted here.
   *
   * $Log:	lock.c,v $
   * Revision 1.2  88/08/30  16:13:14  network
   * Portability fixes from Ronald Karr <tron@uts.amdahl.com>.
   * 
--- 1,15 ----
! /* $Header: lock.c,v 1.4 89/02/10 17:59:46 network Exp $
   *
   * Mailbox locking.
   * Local hacks for mailbox access should be grafted here.
   *
   * $Log:	lock.c,v $
+  * Revision 1.4  89/02/10  17:59:46  network
+  * Fix typo.
+  * 
+  * Revision 1.3  89/02/10  15:46:52  network
+  * V7 support.
+  * 
   * Revision 1.2  88/08/30  16:13:14  network
   * Portability fixes from Ronald Karr <tron@uts.amdahl.com>.
   * 
***************
*** 65,71 ****
   */
  
  int
! lock_name(name)
  char    *name;
  {
  #ifdef ML_DOTLOCK
--- 71,77 ----
   */
  
  int
! name_lock(name)
  char    *name;
  {
  #ifdef ML_DOTLOCK
***************
*** 100,106 ****
   */
  
  int
! unlock_name(name)
  char    *name;
  {
  	int     ret = 0;
--- 106,112 ----
   */
  
  int
! name_unlock(name)
  char    *name;
  {
  	int     ret = 0;
***************
*** 132,138 ****
   */
  
  int
! lock_fd(fd)
  int     fd;
  {
  #ifdef ML_FCNTL
--- 138,144 ----
   */
  
  int
! fd_lock(fd)
  int     fd;
  {
  #ifdef ML_FCNTL
***************
*** 185,191 ****
   */
  
  int
! unlock_fd(fd)
  int     fd;
  {
  #ifdef ML_FCNTL
--- 191,197 ----
   */
  
  int
! fd_unlock(fd)
  int     fd;
  {
  #ifdef ML_FCNTL
***************
*** 312,324 ****
  create_lockfile(name)
  char    *name;
  {
! 	int     tries, fd;
  
  	for (tries = 0; tries < 10; ++tries)
  	{
  		if (tries)
  			snooze(3);
  
  		if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0)) >= 0)
  		{
  			(void) close(fd);
--- 318,349 ----
  create_lockfile(name)
  char    *name;
  {
! #ifndef O_CREAT
! 	char    *othername, *p;
! #endif
! 	int     fd, tries;
  
+ #ifndef O_CREAT
+ 	othername = zalloc(strlen(name) + 20);  /* fudge (???) */
+ 	(void) strcpy(othername, name);
+ 	(void) sprintf(basename(othername), ".dl.%d", getpid());
+ 	if ((fd = creat(othername, 0)) == -1)
+ 	{
+ 		syserr("can't create %s", othername);
+ 		return -1;
+ 	}
+ 	(void) close(fd);
+ 	if (verbose)
+ 		message("created pre-lockfile %s\n", name);
+ #endif
+ 
  	for (tries = 0; tries < 10; ++tries)
  	{
  		if (tries)
  			snooze(3);
  
+ #ifdef O_CREAT
+ 
  		if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0)) >= 0)
  		{
  			(void) close(fd);
***************
*** 327,337 ****
  			return 0;
  		}
  
! 		if (verbose && (tries == 0))
  		{
! 			message("Waiting to create %s (try #%d)\n",
! 				name, tries + 1);
  		}
  	}
  
  	syserr("can't create lockfile %s", name);
--- 352,373 ----
  			return 0;
  		}
  
! #else /* not O_CREAT */
! 
! 		if (link(othername, name) == 0)
  		{
! 			if (unlink(othername) == -1)
! 				syserr("can't remove %s", othername);
! 			free(othername);
! 			if (verbose)
! 				message("created lockfile %s\n", name);
! 			return 0;
  		}
+ 
+ #endif /* not O_CREAT */
+ 
+ 		if (verbose && (tries == 0))
+ 			message("Waiting to create %s\n", name);
  	}
  
  	syserr("can't create lockfile %s", name);

Index: main.c
***************
*** 1,8 ****
! /* $Header: main.c,v 1.9 88/11/28 18:08:03 network Exp $
   *
   * A program to deliver local mail with some flexibility.
   *
   * $Log:	main.c,v $
   * Revision 1.9  88/11/28  18:08:03  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
--- 1,11 ----
! /* $Header: main.c,v 1.10 89/02/10 15:46:59 network Exp $
   *
   * A program to deliver local mail with some flexibility.
   *
   * $Log:	main.c,v $
+  * Revision 1.10  89/02/10  15:46:59  network
+  * V7 support.
+  * 
   * Revision 1.9  88/11/28  18:08:03  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
***************
*** 59,66 ****
   * Local data
   */
  
! static  char    sys_default[] = SYS_DELIVER;
! static  char    user_default[] = USER_DELIVER;
  
  /*
   * Global data
--- 62,69 ----
   * Local data
   */
  
! static  char    sys_dfl[] = SYS_DELIVER;
! static  char    user_dfl[] = USER_DELIVER;
  
  /*
   * Global data
***************
*** 77,84 ****
  char    version[32]     = "1.0";
  char    *shell          = SHELL;
  
! char    *sys_deliver    = sys_default;
! char    *user_deliver   = user_default;
  char    *sender         = NULL;
  char    *hostname       = NULL;
  
--- 80,87 ----
  char    version[32]     = "1.0";
  char    *shell          = SHELL;
  
! char    *sys_deliver    = sys_dfl;
! char    *user_deliver   = user_dfl;
  char    *sender         = NULL;
  char    *hostname       = NULL;
  
***************
*** 120,127 ****
  
  	/* Make sure that stdout and stderr are interleaved correctly */
  
! 	(void) Linebuf(stdout);
! 	(void) Linebuf(stderr);
  
  	/* Figure out the name used to invoke this program. */
  
--- 123,130 ----
  
  	/* Make sure that stdout and stderr are interleaved correctly */
  
! 	Linebuf(stdout);
! 	Linebuf(stderr);
  
  	/* Figure out the name used to invoke this program. */
  
***************
*** 261,268 ****
  
  	/* Do we trust our delivery files? */
  
! 	if (strcmp(sys_default, sys_deliver) == 0
! 	 && strcmp(user_default, user_deliver) == 0)
  		trust_delfiles = TRUE;
  
  	/* Renounce special privileges if something insecure was requested. */
--- 264,271 ----
  
  	/* Do we trust our delivery files? */
  
! 	if (strcmp(sys_dfl, sys_deliver) == 0
! 	 && strcmp(user_dfl, user_deliver) == 0)
  		trust_delfiles = TRUE;
  
  	/* Renounce special privileges if something insecure was requested. */
***************
*** 291,298 ****
  	if (verbose)
  	{
  		message("effective uid = %s (%d/%d); real uid = %s (%d/%d)\n",
! 			eff_ct->name, eff_ct->uid, eff_ct->gid,
! 			real_ct->name, real_ct->uid, real_ct->gid);
  	}
  
  	/* Let's be sane about the file creation mask. */
--- 294,301 ----
  	if (verbose)
  	{
  		message("effective uid = %s (%d/%d); real uid = %s (%d/%d)\n",
! 			eff_ct->ct_name, eff_ct->ct_uid, eff_ct->ct_gid,
! 			real_ct->ct_name, real_ct->ct_uid, real_ct->ct_gid);
  	}
  
  	/* Let's be sane about the file creation mask. */
***************
*** 361,367 ****
  		int     a;
  
  		if (verbose)
! 			message("mailbox delivery as %s\n", real_ct->name);
  
  		/*
  		 * Consider all arguments as mailbox filenames.
--- 364,370 ----
  		int     a;
  
  		if (verbose)
! 			message("mailbox delivery as %s\n", real_ct->ct_name);
  
  		/*
  		 * Consider all arguments as mailbox filenames.
***************
*** 368,374 ****
  		 */
  
  		for (a = optind; a < argc; ++a)
! 			(void) dest(real_ct->name, argv[a]);
  
  		if (verbose)
  			dumpdests("(should all be mailboxes)");
--- 371,377 ----
  		 */
  
  		for (a = optind; a < argc; ++a)
! 			(void) dest(real_ct->ct_name, argv[a]);
  
  		if (verbose)
  			dumpdests("(should all be mailboxes)");
***************
*** 550,556 ****
  
  	for (d = first_dest(); d; d = next_dest(d))
  	{
! 		if (d->state != ST_ERROR)
  			continue;
  
  		if (++count == 1)
--- 553,559 ----
  
  	for (d = first_dest(); d; d = next_dest(d))
  	{
! 		if (d->d_state != ST_ERROR)
  			continue;
  
  		if (++count == 1)
***************
*** 560,569 ****
  				hostname);
  		}
  
! 		message("\t\"%s\"", d->name);
! 		if (d->class == CL_MBOX)
! 			message(", mailbox \"%s\"", d->mailbox);
! 		message(": %s\n", d->error);
  	}
  
  	return count;
--- 563,572 ----
  				hostname);
  		}
  
! 		message("\t\"%s\"", d->d_name);
! 		if (d->d_class == CL_MBOX)
! 			message(", mailbox \"%s\"", d->d_mailbox);
! 		message(": %s\n", derrmsg(d->d_error));
  	}
  
  	return count;
***************
*** 583,589 ****
  
  	for (n = t; *n; ++n)
  	{
! 		if ((ct = name_context(*n)) != NULL && uid == ct->uid)
  			return TRUE;
  	}
  
--- 586,592 ----
  
  	for (n = t; *n; ++n)
  	{
! 		if ((ct = name_context(*n)) != NULL && uid == ct->ct_uid)
  			return TRUE;
  	}
  

Index: mbox.c
***************
*** 1,8 ****
! /* $Header: mbox.c,v 1.3 88/11/28 18:08:13 network Exp $
   *
   * Finally!  Put the message in the specified mailbox(es).
   *
   * $Log:	mbox.c,v $
   * Revision 1.3  88/11/28  18:08:13  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
--- 1,11 ----
! /* $Header: mbox.c,v 1.4 89/02/10 15:47:10 network Exp $
   *
   * Finally!  Put the message in the specified mailbox(es).
   *
   * $Log:	mbox.c,v $
+  * Revision 1.4  89/02/10  15:47:10  network
+  * V7 support.
+  * 
   * Revision 1.3  88/11/28  18:08:13  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
***************
*** 31,37 ****
   * Local functions.
   */
  
! static          mbox_dest();
  static  int     mbox_write();
  
  /*----------------------------------------------------------------------
--- 34,40 ----
   * Local functions.
   */
  
! static          mbox_one();
  static  int     mbox_write();
  
  /*----------------------------------------------------------------------
***************
*** 44,55 ****
  
  	for (d = first_dest(); d; d = next_dest(d))
  	{
! 		switch (d->class)
  		{
  		case CL_USER:
  		case CL_MBOX:
! 			if (d->state == ST_WORKING)
! 				mbox_dest(d);
  			break;
  		}
  	}
--- 47,58 ----
  
  	for (d = first_dest(); d; d = next_dest(d))
  	{
! 		switch (d->d_class)
  		{
  		case CL_USER:
  		case CL_MBOX:
! 			if (d->d_state == ST_WORKING)
! 				mbox_one(d);
  			break;
  		}
  	}
***************
*** 60,66 ****
   */
  
  static
! mbox_dest(d)
  DEST    *d;
  {
  	CONTEXT *ct;
--- 63,69 ----
   */
  
  static
! mbox_one(d)
  DEST    *d;
  {
  	CONTEXT *ct;
***************
*** 68,106 ****
  
  	if (printaddrs)
  	{
! 		(void) printf("%s", d->name);
! 		if (d->class == CL_MBOX)
! 			(void) printf(":%s", d->mailbox);
  		(void) printf("\n");
  	}
  
  	if (dryrun)
  	{
! 		d->state = ST_DONE;
  		return;
  	}
  
! 	if ((ct = name_context(d->name)) == NULL)
  	{
! 		d->state = ST_ERROR;
! 		d->error = "Lost context in mbox_dest()";
  		return;
  	}
  
  	if (! ok_context(ct))
  	{
! 		d->state = ST_ERROR;
! 		d->error = "No permissions for that context";
  		return;
  	}
  
! 	if (d->class == CL_MBOX)
  	{
  		if (sfork() == 0)
  		{
  			if (become(ct, !boxdelivery) < 0)
  				exit(1);
! 			if (mbox_write(d->mailbox, ct, FALSE) < 0)
  				exit(1);
  			exit(0);
  		}
--- 71,107 ----
  
  	if (printaddrs)
  	{
! 		(void) printf("%s", d->d_name);
! 		if (d->d_class == CL_MBOX)
! 			(void) printf(":%s", d->d_mailbox);
  		(void) printf("\n");
  	}
  
  	if (dryrun)
  	{
! 		d->d_state = ST_DONE;
  		return;
  	}
  
! 	if ((ct = name_context(d->d_name)) == NULL)
  	{
! 		dest_err(d, E_CTLOST);
  		return;
  	}
  
  	if (! ok_context(ct))
  	{
! 		dest_err(d, E_CTPERM);
  		return;
  	}
  
! 	if (d->d_class == CL_MBOX)
  	{
  		if (sfork() == 0)
  		{
  			if (become(ct, !boxdelivery) < 0)
  				exit(1);
! 			if (mbox_write(d->d_mailbox, ct, FALSE) < 0)
  				exit(1);
  			exit(0);
  		}
***************
*** 113,122 ****
  		char    mailbox[100];
  
  		(void) sprintf(mailbox, "%s/%s",
! #ifdef MAILBOX_DIR
! 			MAILBOX_DIR, d->name
  #else
! 			d->home, MAILBOX_NAME
  #endif
  			);
  
--- 114,123 ----
  		char    mailbox[100];
  
  		(void) sprintf(mailbox, "%s/%s",
! #ifdef MBX_DIR
! 			MBX_DIR, d->d_name
  #else
! 			d->d_home, MBX_NAME
  #endif
  			);
  
***************
*** 125,136 ****
  	}
  
  	if (ret >= 0)
! 		d->state = ST_DONE;
  	else
! 	{
! 		d->state = ST_ERROR;
! 		d->error = "Error writing to mailbox";
! 	}
  }
  
  /*----------------------------------------------------------------------
--- 126,134 ----
  	}
  
  	if (ret >= 0)
! 		d->d_state = ST_DONE;
  	else
! 		dest_err(d, E_MBOX);
  }
  
  /*----------------------------------------------------------------------
***************
*** 145,163 ****
  CONTEXT *ct;
  int     is_sys;
  {
! 	int     fd, t;
  	int     ret = 0;
  
  	if (verbose)
  	{
  		message("As %s, delivering to %s mailbox %s\n",
! 			ct->name, (is_sys ? "system" : "user"), mailbox);
  	}
  
! 	if (lock_name(mailbox) < 0)
  		return -1;
  
! 	while ((fd = open(mailbox, O_RDWR)) == -1)
  	{
  		if (errno != ENOENT)
  		{
--- 143,162 ----
  CONTEXT *ct;
  int     is_sys;
  {
! 	struct stat st;
! 	int     fd, t, mbox_uid, mbox_gid;
  	int     ret = 0;
  
  	if (verbose)
  	{
  		message("As %s, delivering to %s mailbox %s\n",
! 			ct->ct_name, (is_sys ? "system" : "user"), mailbox);
  	}
  
! 	if (name_lock(mailbox) < 0)
  		return -1;
  
! 	while ((fd = open(mailbox, O_WRONLY)) == -1)
  	{
  		if (errno != ENOENT)
  		{
***************
*** 165,218 ****
  			break;
  		}
  
! 		if ((fd = open(mailbox, O_RDWR|O_CREAT|O_EXCL,
! 				MAILBOX_MODE)) != -1)
  		{
! 			/* Make sure the mailbox receives the correct modes */
  
! 			int mbox_gid = ct->gid;
  
! #ifdef MAILBOX_GROUP
! 			if (is_sys)
! 			{
! 				static int mbox_gid_sv = -2;
  
! 				if (mbox_gid_sv == -2)
! 					mbox_gid_sv = group_id(MAILBOX_GROUP);
  
! 				if (mbox_gid_sv < 0)
! 					message("%s: no such group\n", MAILBOX_GROUP);
! 				else
! 					mbox_gid = mbox_gid_sv;
! 			}
! #endif /* MAILBOX_GROUP */
  
! 			if (chown(mailbox, ct->uid, mbox_gid) == -1)
! 			{
! 				/* print a message, but that's all. (???) */
! 				syserr("can't chown %s to %d,%d",
! 					mailbox, ct->uid, mbox_gid);
! 			}
! 			break;
  		}
  
! 		if (errno != EEXIST)
  		{
! 			syserr("can't create %s", mailbox);
  			break;
  		}
  	}
  
  	if (fd == -1)
  	{
! 		(void) unlock_name(mailbox);
  		return -1;
  	}
  
! 	if (lock_fd(fd) < 0)
  	{
  		(void) close(fd);
! 		(void) unlock_name(mailbox);
  		return -1;
  	}
  
--- 164,237 ----
  			break;
  		}
  
! #ifdef O_CREAT
! 		fd = open(mailbox, O_WRONLY|O_CREAT|O_EXCL, MBX_MODE);
! 
! 		/* If it exists now, try open() again. */
! 		if (fd == -1 && errno == EEXIST)
! 			continue;
! #else
! 		fd = creat(mailbox, MBX_MODE);
! #endif
! 		if (fd == -1)
  		{
! 			syserr("can't create %s", mailbox);
! 			break;
! 		}
  
! 		/* Make sure the mailbox receives the correct modes */
  
! 		mbox_uid = ct->ct_uid;
! 		mbox_gid = ct->ct_gid;
  
! #ifdef MBX_GROUP
! 		if (is_sys)
! 		{
! 			static int mbox_sv_gid = -2;
  
! 			if (mbox_sv_gid == -2)
! 				mbox_sv_gid = group_id(MBX_GROUP);
  
! 			if (mbox_sv_gid < 0)
! 				message("%s: no such group\n", MBX_GROUP);
! 			else
! 				mbox_gid = mbox_sv_gid;
  		}
+ #endif /* MBX_GROUP */
  
! 		if (fstat(fd, &st) == -1)
  		{
! 			syserr("can't fstat open mailbox?!");
! 			(void) close(fd);
! 			fd = -1;
  			break;
  		}
+ 
+ 		/* Change mailbox ownership if it's not already correct. */
+ 
+ 		if ((st.st_uid != mbox_uid || st.st_gid != mbox_gid)
+ 		 && chown(mailbox, mbox_uid, mbox_gid) == -1)
+ 		{
+ 			/* print a message, but that's all. (???) */
+ 			syserr("can't chown %s to %d,%d",
+ 				mailbox, mbox_uid, mbox_gid);
+ 		}
+ 
+ 		/* It's open now, so we can stop looping now. */
+ 
+ 		break;
  	}
  
  	if (fd == -1)
  	{
! 		(void) name_unlock(mailbox);
  		return -1;
  	}
  
! 	if (fd_lock(fd) < 0)
  	{
  		(void) close(fd);
! 		(void) name_unlock(mailbox);
  		return -1;
  	}
  
***************
*** 240,249 ****
  			message("wrote message to %s\n", mailbox);
  	}
  
! 	if (unlock_fd(fd) < 0)
  		ret = -1;
  	(void) close(fd);
! 	if (unlock_name(mailbox) < 0)
  		ret = -1;
  
  	return ret;
--- 259,268 ----
  			message("wrote message to %s\n", mailbox);
  	}
  
! 	if (fd_unlock(fd) < 0)
  		ret = -1;
  	(void) close(fd);
! 	if (name_unlock(mailbox) < 0)
  		ret = -1;
  
  	return ret;

Index: misc.h
***************
*** 1,8 ****
! /* $Header: misc.h,v 1.4 88/11/26 13:21:01 network Exp $
   *
   * Miscellaneous definitions.
   *
   * $Log:	misc.h,v $
   * Revision 1.4  88/11/26  13:21:01  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
--- 1,11 ----
! /* $Header: misc.h,v 1.5 89/02/10 15:47:15 network Exp $
   *
   * Miscellaneous definitions.
   *
   * $Log:	misc.h,v $
+  * Revision 1.5  89/02/10  15:47:15  network
+  * V7 support.
+  * 
   * Revision 1.4  88/11/26  13:21:01  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
***************
*** 27,39 ****
   * Non-portable include files
   */
  
! #ifdef BSD
! #include <strings.h>
! #else
  #include <string.h>
  #include <memory.h>
  #endif
  
  /*
   * Constants
   */
--- 30,46 ----
   * Non-portable include files
   */
  
! #ifdef USG
! #include <fcntl.h>
  #include <string.h>
  #include <memory.h>
  #endif
  
+ #ifdef BSD
+ #include <strings.h>
+ #include <sys/file.h>
+ #endif
+ 
  /*
   * Constants
   */
***************
*** 46,51 ****
--- 53,64 ----
  #define FALSE   0
  #define TRUE    1
  
+ #ifndef O_RDONLY
+ #define O_RDONLY   0
+ #define O_WRONLY   1
+ #define O_RDWR     2
+ #endif
+ 
  /*
   * Macros.
   */
***************
*** 55,67 ****
  #define GETSIZE(buf)    (int) (sizeof(buf) - 1)
  
  /*
!  * Public data
   */
  
  extern  char    **environ;
  
  /*
!  * Library functions
   */
  
  extern  char    *ctime();
--- 68,80 ----
  #define GETSIZE(buf)    (int) (sizeof(buf) - 1)
  
  /*
!  * Public data.
   */
  
  extern  char    **environ;
  
  /*
!  * Common library functions.
   */
  
  extern  char    *ctime();
***************
*** 76,104 ****
  extern  SIGTYPE (*signal())();
  
  /*
!  * Library differences
   */
  
! #ifdef BSD
  
! extern  int     setlinebuf();
  
  #define strchr          index
  #define strrchr         rindex
! #define memcpy(d,s,n)   bcopy(s,d,n)
  #define Zero(d,n)       bzero(d,n)
! #define Linebuf(f)      setlinebuf(f)
  
! #else   /* not BSD */
  
  extern  int     setvbuf();
  
- #define Zero(d,n)       memset(d,0,(int)(n))
- 
  #ifdef XENIX_SETVBUF
! #define Linebuf(f)      setvbuf(f, _IOLBF, (char *)NULL, BUFSIZ)
  #else
! #define Linebuf(f)      setvbuf(f, (char *)NULL, _IOLBF, BUFSIZ)
  #endif
  
! #endif  /* not BSD */
--- 89,149 ----
  extern  SIGTYPE (*signal())();
  
  /*
!  * String search functions.
   */
  
! #ifndef USG
  
! #ifndef BSD
! extern  char    *index();
! extern  char    *rindex();
! #endif /* not BSD */
  
  #define strchr          index
  #define strrchr         rindex
! 
! #endif
! 
! /*
!  * Memory copy and zero.
!  */
! 
! #ifdef USG
! #define Copy(d,s,n)     (void) memcpy(d,s,n)
! #define Zero(d,n)       (void) memset(d,0,(int)(n))
! #else /* not USG */
! #ifdef BSD
! #define Copy(d,s,n)     bcopy(s,d,n)
  #define Zero(d,n)       bzero(d,n)
! #else /* not BSD */
! #define MEMFUNCS        /* define Copy() and Zero() in sysdep.c */
! #endif /* not BSD */
! #endif /* not USG */
  
! /*
!  * Line-buffering on stdio files.
!  */
  
+ #ifdef USG
+ 
  extern  int     setvbuf();
  
  #ifdef XENIX_SETVBUF
! #define Linebuf(f)      (void) setvbuf(f, _IOLBF, (char *)NULL, BUFSIZ)
  #else
! #define Linebuf(f)      (void) setvbuf(f, (char *)NULL, _IOLBF, BUFSIZ)
  #endif
  
! #else /* not USG */
! #ifdef BSD
! 
! extern  int     setlinebuf();
! 
! #define Linebuf(f)      (void) setlinebuf(f)
! 
! #else /* not BSD */
! 
! #define Linebuf(f)      /* can't do it */
! 
! #endif /* not BSD */
! #endif /* not USG */

Index: procs.c
***************
*** 1,8 ****
! /* $Header: procs.c,v 1.3 88/11/26 13:21:07 network Exp $
   *
   * Process management and misc support.
   *
   * $Log:	procs.c,v $
   * Revision 1.3  88/11/26  13:21:07  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
--- 1,11 ----
! /* $Header: procs.c,v 1.4 89/02/10 15:47:31 network Exp $
   *
   * Process management and misc support.
   *
   * $Log:	procs.c,v $
+  * Revision 1.4  89/02/10  15:47:31  network
+  * V7 support.
+  * 
   * Revision 1.3  88/11/26  13:21:07  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
***************
*** 73,79 ****
  
  	if (! ok_context(ct))
  	{
! 		error("in ct_popen: no permissions to become %s\n", ct->name);
  		return NULL;
  	}
  
--- 76,83 ----
  
  	if (! ok_context(ct))
  	{
! 		error("in ct_popen: no permissions to become %s\n",
! 		      ct->ct_name);
  		return NULL;
  	}
  
***************
*** 186,204 ****
  	 * Note the importance of doing the setgid() before the setuid().
  	 */
  
! 	if (setgid(ct->gid) == -1)
  	{
! 		syserr("can't setgid to %d", ct->gid);
  		return -1;
  	}
! 	if (setuid(ct->uid) == -1)
  	{
! 		syserr("can't setgid to %u", ct->uid);
  		return -1;
  	}
! 	if (chd && chdir(ct->home) == -1)
  	{
! 		syserr("can't chdir to %s", ct->home);
  		return -1;
  	}
  
--- 190,208 ----
  	 * Note the importance of doing the setgid() before the setuid().
  	 */
  
! 	if (setgid(ct->ct_gid) == -1)
  	{
! 		syserr("can't setgid to %d", ct->ct_gid);
  		return -1;
  	}
! 	if (setuid(ct->ct_uid) == -1)
  	{
! 		syserr("can't setgid to %u", ct->ct_uid);
  		return -1;
  	}
! 	if (chd && chdir(ct->ct_home) == -1)
  	{
! 		syserr("can't chdir to %s", ct->ct_home);
  		return -1;
  	}
  
***************
*** 205,212 ****
  	/* Set up the environment */
  
  	(void) sprintf(env_path, "%s:/bin:/usr/bin",
! 			((ct->uid == 0) ? "/etc" : "."));
! 	alloc_env("HOME", ct->home);
  	alloc_env("PATH", env_path);
  
  	/* I guess it worked. */
--- 209,216 ----
  	/* Set up the environment */
  
  	(void) sprintf(env_path, "%s:/bin:/usr/bin",
! 			((ct->ct_uid == 0) ? "/etc" : "."));
! 	alloc_env("HOME", ct->ct_home);
  	alloc_env("PATH", env_path);
  
  	/* I guess it worked. */

Index: subs.c
***************
*** 1,8 ****
! /* $Header: subs.c,v 1.5 88/11/26 13:21:11 network Exp $
   *
   * Miscellaneous subroutines.
   *
   * $Log:	subs.c,v $
   * Revision 1.5  88/11/26  13:21:11  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
--- 1,11 ----
! /* $Header: subs.c,v 1.6 89/02/10 15:47:40 network Exp $
   *
   * Miscellaneous subroutines.
   *
   * $Log:	subs.c,v $
+  * Revision 1.6  89/02/10  15:47:40  network
+  * V7 support.
+  * 
   * Revision 1.5  88/11/26  13:21:11  network
   * patch4: Add return type of signal handlers to config.h.
   * patch4: Provide a version of getopt() for systems that lack it.
***************
*** 56,62 ****
  	if ((p = malloc(size)) == NULL)
  		nomem();
  
! 	(void) Zero(p, size);
  	return p;
  }
  
--- 59,65 ----
  	if ((p = malloc(size)) == NULL)
  		nomem();
  
! 	Zero(p, size);
  	return p;
  }
  

Index: sysdep.c
***************
*** 1,4 ****
! /* $Header: sysdep.c,v 1.6 88/11/30 16:24:56 network Exp $
   *
   * Routines which are (or might well be) system-dependant.
   * I've put the message routines here since you may need to use
--- 1,4 ----
! /* $Header: sysdep.c,v 1.7 89/02/10 15:47:44 network Exp $
   *
   * Routines which are (or might well be) system-dependant.
   * I've put the message routines here since you may need to use
***************
*** 5,10 ****
--- 5,13 ----
   * the ANSI <stdarg.h> instead of <varargs.h>.
   *
   * $Log:	sysdep.c,v $
+  * Revision 1.7  89/02/10  15:47:44  network
+  * V7 support.
+  * 
   * Revision 1.6  88/11/30  16:24:56  network
   * patch6:  Separate getopt() into its own module.
   * 
***************
*** 31,37 ****
--- 34,57 ----
  
  #include "deliver.h"
  #include <errno.h>
+ #ifdef HAS_STDARG
+ #include <stdarg.h>
+ #else
+ #ifdef HAS_VARARGS
  #include <varargs.h>
+ #else
+ /*
+  * Non-portable home-grown varargs.  Use at your own risk.
+  * Especially note that if sizeof(int) > sizeof(short), then
+  * "va_arg(..,short)" is broken.
+  */
+ typedef char *va_list;
+ #define va_dcl          int va_alist;
+ #define va_start(ap)    ap = (char *) &va_alist
+ #define va_arg(ap,type) *(type *)(ap += sizeof(type), ap - sizeof(type))
+ #define va_end(ap)      /* nothing */
+ #endif
+ #endif
  
  #ifdef UNAME
  #include <sys/utsname.h>
***************
*** 59,75 ****
   * Print a message.
   */
  
! /* VARARGS1 */
! message(fmt, va_alist)
! char    *fmt;
! va_dcl
  {
! 	va_list args;
! 	va_start(args);
  
! 	(void) vfprintf(stderr, fmt, args);
  
! 	va_end(args);
  }
  
  /*----------------------------------------------------------------------
--- 79,104 ----
   * Print a message.
   */
  
! /* VARARGS */
! #ifdef HAS_STDARG
! message(char *fmt, ...)
! #else
! message(va_alist) va_dcl
! #endif
  {
! 	va_list ap;
  
! #ifdef HAS_STDARG
! 	va_start(ap, fmt);
! #else
! 	char    *fmt;
! 	va_start(ap);
! 	fmt = va_arg(ap, char *);
! #endif
  
! 	(void) vfprintf(stderr, fmt, ap);
! 
! 	va_end(ap);
  }
  
  /*----------------------------------------------------------------------
***************
*** 76,93 ****
   * Print an error message.
   */
  
! /* VARARGS1 */
! error(fmt, va_alist)
! char    *fmt;
! va_dcl
  {
! 	va_list args;
! 	va_start(args);
  
  	(void) fprintf(stderr, "%s: ", progname);
! 	(void) vfprintf(stderr, fmt, args);
  
! 	va_end(args);
  }
  
  /*----------------------------------------------------------------------
--- 105,131 ----
   * Print an error message.
   */
  
! /* VARARGS */
! #ifdef HAS_STDARG
! error(char *fmt, ...)
! #else
! error(va_alist) va_dcl
! #endif
  {
! 	va_list ap;
  
+ #ifdef HAS_STDARG
+ 	va_start(ap, fmt);
+ #else
+ 	char    *fmt;
+ 	va_start(ap);
+ 	fmt = va_arg(ap, char *);
+ #endif
+ 
  	(void) fprintf(stderr, "%s: ", progname);
! 	(void) vfprintf(stderr, fmt, ap);
  
! 	va_end(ap);
  }
  
  /*----------------------------------------------------------------------
***************
*** 94,116 ****
   * Report an error returned from a system call.
   */
  
! /* VARARGS1 */
! syserr(fmt, va_alist)
! char    *fmt;
! va_dcl
  {
  	int     e = errno;
! 	va_list args;
! 	va_start(args);
  
  	(void) fprintf(stderr, "%s: ", progname);
! 	(void) vfprintf(stderr, fmt, args);
  	if (e <= sys_nerr)
  		(void) fprintf(stderr, ": %s\n", sys_errlist[e]);
  	else
  		(void) fprintf(stderr, ": unknown system error %d\n", e);
  
! 	va_end(args);
  }
  
  /*----------------------------------------------------------------------
--- 132,163 ----
   * Report an error returned from a system call.
   */
  
! /* VARARGS */
! #ifdef HAS_STDARG
! syserr(char *fmt, ...)
! #else
! syserr(va_alist) va_dcl
! #endif
  {
  	int     e = errno;
! 	va_list ap;
  
+ #ifdef HAS_STDARG
+ 	va_start(ap, fmt);
+ #else
+ 	char    *fmt;
+ 	va_start(ap);
+ 	fmt = va_arg(ap, char *);
+ #endif
+ 
  	(void) fprintf(stderr, "%s: ", progname);
! 	(void) vfprintf(stderr, fmt, ap);
  	if (e <= sys_nerr)
  		(void) fprintf(stderr, ": %s\n", sys_errlist[e]);
  	else
  		(void) fprintf(stderr, ": unknown system error %d\n", e);
  
! 	va_end(ap);
  }
  
  /*----------------------------------------------------------------------
***************
*** 193,198 ****
--- 240,259 ----
  #endif /* GETHOSTNAME */
  
  /*----------------------------------------------------------------------
+  * Return a pre-defined HOSTNAME.
+  */
+ 
+ #ifdef HOSTNAME
+ 
+ char *
+ gethost()
+ {
+ 	return HOSTNAME;
+ }
+ 
+ #endif /* HOSTNAME */
+ 
+ /*----------------------------------------------------------------------
   * Variable-argument-list output, System V style.
   */
  
***************
*** 277,284 ****
  			{}
  		env_size = i + 10;      /* arbitrary */
  		env_array = (char **) zalloc(env_size * sizeof(char *));
! 		(void) memcpy((char *)env_array, (char *)environ,
! 				(int) ((i + 1) * sizeof(char *)));
  		environ = env_array;
  	}
  	else if (environ != env_array)
--- 338,345 ----
  			{}
  		env_size = i + 10;      /* arbitrary */
  		env_array = (char **) zalloc(env_size * sizeof(char *));
! 		Copy((char *)env_array, (char *)environ,
! 		     (int) ((i + 1) * sizeof(char *)));
  		environ = env_array;
  	}
  	else if (environ != env_array)
***************
*** 311,313 ****
--- 372,407 ----
  }
  
  #endif  /* !HAS_PUTENV */
+ 
+ /*----------------------------------------------------------------------
+  * Memory copy.
+  */
+ 
+ #ifdef MEMFUNCS
+ 
+ Copy(dest, src, len)
+ char    *dest;
+ char    *src;
+ int     len;
+ {
+ 	while (len-- > 0)
+ 		*dest++ = *src++;
+ }
+ 
+ #endif
+ 
+ /*----------------------------------------------------------------------
+  * Memory clear.
+  */
+ 
+ #ifdef MEMFUNCS
+ 
+ Zero(dest, len)
+ char    *dest;
+ int     len;
+ {
+ 	while (len-- > 0)
+ 		*dest++ = 0;
+ }
+ 
+ #endif

Index: uucp.c
***************
*** 1,4 ****
! /* $Header: uucp.c,v 1.2 88/11/28 18:08:23 network Exp $
   *
   * Handle mail destined for other hosts via UUCP.
   * Deliver is intended as a very low-level program, so we don't
--- 1,4 ----
! /* $Header: uucp.c,v 1.3 89/02/10 15:47:51 network Exp $
   *
   * Handle mail destined for other hosts via UUCP.
   * Deliver is intended as a very low-level program, so we don't
***************
*** 5,10 ****
--- 5,13 ----
   * do anything fancy here.  We just hand the message to uux.
   *
   * $Log:	uucp.c,v $
+  * Revision 1.3  89/02/10  15:47:51  network
+  * V7 support.
+  * 
   * Revision 1.2  88/11/28  18:08:23  network
   * patch5: Copy temp files before handing them to delivery files.
   * patch5: Introduce "uid" program.
***************
*** 55,75 ****
  		char    rmail[40];
  		char    who[BUFSIZ];
  
! 		if (d->class != CL_UUCP || d->state != ST_WORKING)
  			continue;
  
  		if (printaddrs)
! 			(void) printf("%s\n", d->name);
  
  		if (dryrun)
  		{
! 			d->state = ST_DONE;
  			continue;
  		}
  
! 		bang = strchr(d->name, '!');
  		*bang = 0;
! 		(void) sprintf(rmail, "%s!rmail", d->name);
  		*bang++ = '!';
  		(void) sprintf(who, "(%s)", bang);
  
--- 58,78 ----
  		char    rmail[40];
  		char    who[BUFSIZ];
  
! 		if (d->d_class != CL_UUCP || d->d_state != ST_WORKING)
  			continue;
  
  		if (printaddrs)
! 			(void) printf("%s\n", d->d_name);
  
  		if (dryrun)
  		{
! 			d->d_state = ST_DONE;
  			continue;
  		}
  
! 		bang = strchr(d->d_name, '!');
  		*bang = 0;
! 		(void) sprintf(rmail, "%s!rmail", d->d_name);
  		*bang++ = '!';
  		(void) sprintf(who, "(%s)", bang);
  
***************
*** 82,101 ****
  			continue;
  
  		if (uucp_copy(uux_fp) < 0)
! 		{
! 			d->state = ST_ERROR;
! 			d->error = "Error piping to uux";
! 		}
  
  		if (ct_pclose(uux_fp))
  		{
! 			/* Overrides any problems with uucp_copy() */
! 
! 			d->state = ST_ERROR;
! 			d->error = "UUCP not available to that host";
  		}
  		else
! 			d->state = ST_DONE;
  	}
  }
  
--- 85,99 ----
  			continue;
  
  		if (uucp_copy(uux_fp) < 0)
! 			dest_err(d, E_UUX);
  
  		if (ct_pclose(uux_fp))
  		{
! 			/* "No such host" overrides piping problems. */
! 			dest_err(d, E_NSHOST);
  		}
  		else
! 			d->d_state = ST_DONE;
  	}
  }
  
-- 
Chip Salzenberg             <chip@ateng.com> or <uunet!ateng!chip>
A T Engineering             Me?  Speak for my company?  Surely you jest!
	  "It's no good.  They're tapping the lines."