diff -c /var/tmp/sup/Makefile sup/Makefile
*** Makefile	Mon Apr 11 08:02:04 1994
--- sup/Makefile	Sun Aug 13 19:40:26 1995
***************
*** 42,54 ****
  #
  SITE			= NETBSD
  #SITE			= CMUCS
  NETBSD_DEFINES		= -UMACH -DVAR_TMP -DHAS_DAEMON
  AFS_DEFINES		= -DAFS -I/usr/afsws/include
  OSF_DEFINES		= -UMACH -DOSF -D_BSD -noshrlib -g -DNEED_VSNPRINTF -DVAR_TMP
  CMUCS_DEFINES		= -DMACH -DDOPRINT_VA -DNEED_VPRINTF
  NON_MACH_DEFINES	= -UMACH
  #DEFS			= -UCMUCS -UCMU  ${${SITE}_DEFINES}
! DEFS			= -UCMUCS -UCMU  ${NETBSD_DEFINES}
  
  #INSTALLATION PARAMETERS
  NETBSD_BINDIR		= /usr/local/bin
--- 42,55 ----
  #
  SITE			= NETBSD
  #SITE			= CMUCS
+ RENAMELOG		= \"/usr/local/etc/sup.moved\"
  NETBSD_DEFINES		= -UMACH -DVAR_TMP -DHAS_DAEMON
  AFS_DEFINES		= -DAFS -I/usr/afsws/include
  OSF_DEFINES		= -UMACH -DOSF -D_BSD -noshrlib -g -DNEED_VSNPRINTF -DVAR_TMP
  CMUCS_DEFINES		= -DMACH -DDOPRINT_VA -DNEED_VPRINTF
  NON_MACH_DEFINES	= -UMACH
  #DEFS			= -UCMUCS -UCMU  ${${SITE}_DEFINES}
! DEFS			= -UCMUCS -UCMU  ${NETBSD_DEFINES} -DRENAMELOG=${RENAMELOG}
  
  #INSTALLATION PARAMETERS
  NETBSD_BINDIR		= /usr/local/bin
***************
*** 60,67 ****
  SUPCL			= supcmain.o supcvers.o supcparse.o supcname.o \
  			  supcmisc.o supcmeat.o
  SUPS			= scm.o scmio.o stree.o log.o supmsg.o netcrypt.o
! EXTRA			= atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o  \
! 			  path.o quit.o run.o salloc.o skipto.o  vprintf.o
  
  
  PROGRAMS		= sup supscan supfilesrv
--- 61,69 ----
  SUPCL			= supcmain.o supcvers.o supcparse.o supcname.o \
  			  supcmisc.o supcmeat.o
  SUPS			= scm.o scmio.o stree.o log.o supmsg.o netcrypt.o
! EXTRA			= atoo.o errmsg.o expand.o ffilecopy.o filecopy.o \
! 			  nxtarg.o path.o quit.o run.o salloc.o skipto.o  \
! 			  vprintf.o
  
  
  PROGRAMS		= sup supscan supfilesrv
***************
*** 76,84 ****
  .endif
  
  .if defined(USE_CRYPT)
! NETBSD_LIBS		= -lcrypt -lutil
  .else
! NETBSD_LIBS		= -lutil
  .endif
  CMUCS_LIBS		= -lsys
  OSF_LIBS		= -lbsd
--- 78,86 ----
  .endif
  
  .if defined(USE_CRYPT)
! NETBSD_LIBS		= -lcipher -lcrypt -lutil
  .else
! NETBSD_LIBS		= -lcrypt -lutil
  .endif
  CMUCS_LIBS		= -lsys
  OSF_LIBS		= -lbsd
diff -c /var/tmp/sup/ffilecopy.c sup/ffilecopy.c
*** ffilecopy.c	Fri Aug 20 17:46:33 1993
--- sup/ffilecopy.c	Wed Apr  5 11:46:38 1995
***************
*** 58,64 ****
  	if (fflush (there) == EOF)		/* flush pending output */
  		return (EOF);
  
! #ifdef __386BSD__
  	if ((here->_r) > 0) {			/* flush buffered input */
  		i = write (therefile, here->_p, here->_r);
  		if (i != here->_r)  return (EOF);
--- 58,64 ----
  	if (fflush (there) == EOF)		/* flush pending output */
  		return (EOF);
  
! #ifdef __FreeBSD__
  	if ((here->_r) > 0) {			/* flush buffered input */
  		i = write (therefile, here->_p, here->_r);
  		if (i != here->_r)  return (EOF);
***************
*** 76,82 ****
  	i = filecopy (herefile, therefile);	/* fast file copy */
  	if (i < 0)  return (EOF);
  
! #ifdef __386BSD__
  	(here->_flags) |= __SEOF;		/* indicate EOF */
  #else
  	(here->_flag) |= _IOEOF;		/* indicate EOF */
--- 76,82 ----
  	i = filecopy (herefile, therefile);	/* fast file copy */
  	if (i < 0)  return (EOF);
  
! #ifdef __FreeBSD__
  	(here->_flags) |= __SEOF;		/* indicate EOF */
  #else
  	(here->_flag) |= _IOEOF;		/* indicate EOF */
diff -c /var/tmp/sup/libc.h sup/libc.h
*** libc.h	Fri Aug 20 17:46:33 1993
--- sup/libc.h	Sun Aug 13 19:03:32 1995
***************
*** 81,86 ****
--- 81,90 ----
  #ifndef	_LIBC_H_
  #define	_LIBC_H_ 1
  
+ #if defined(__hpux)
+ #define __P(x) x
+ #endif
+ 
  #ifndef _TYPES_
  #include <sys/types.h>
  #endif	/* _TYPES_ */
***************
*** 195,200 ****
--- 199,224 ----
  #if defined(c_plusplus)
  typedef int (*PFI2)(...);
  #endif /* c_plusplus */
+ 
+ #if defined(__hpux)
+ extern int utimes(char *, struct timeval *);
+ 
+ #ifndef LOCK_SH
+ #define LOCK_SH 1
+ #endif
+ #ifndef LOCK_EX
+ #define LOCK_EX 2
+ #endif
+ #ifndef LOCK_NB
+ #define LOCK_NB 4
+ #endif
+ #ifndef LOCK_UN
+ #define LOCK_UN 8
+ #endif
+ 
+ extern int flock(int, int);
+ #endif /* __hpux */
+ 
  #if 0
  extern void abort(void);
  extern int abs(int);
diff -c /var/tmp/sup/log.c sup/log.c
*** log.c	Fri Aug 20 17:46:33 1993
--- sup/log.c	Sun Aug 13 19:43:12 1995
***************
*** 52,59 ****
--- 52,64 ----
   */
  
  #include <stdio.h>
+ #ifdef __hpux
+ #include <syslog.h>
+ #include <stdlib.h>
+ #else
  #include <sys/syslog.h>
  #include <c.h>
+ #endif
  #if __STDC__
  #include <stdarg.h>
  #else
***************
*** 72,78 ****
  char *program;
  {
  	if (opened)  return;
! 	openlog(program,LOG_PID,LOG_DAEMON);
  	opened++;
  }
  
--- 77,83 ----
  char *program;
  {
  	if (opened)  return;
! 	openlog(program,LOG_PID,LOG_LOCAL1);
  	opened++;
  }
  
diff -c /var/tmp/sup/scan.c sup/scan.c
*** scan.c	Fri Aug 20 17:46:33 1993
--- sup/scan.c	Sun Aug 13 18:44:51 1995
***************
*** 122,134 ****
  typedef enum {			/* <collection>/list file lines */
  	LUPGRADE,	LOMIT,		LBACKUP,	LEXECUTE,
  	LINCLUDE,	LNOACCT,	LOMITANY,	LALWAYS,
! 	LSYMLINK,	LRSYMLINK
  } LISTTYPE;
  
  static char *ltname[] = {
  	"upgrade",	"omit",		"backup",	"execute",
  	"include",	"noaccount",	"omitany",	"always",
! 	"symlink",	"rsymlink",
  	0
  };
  
--- 122,134 ----
  typedef enum {			/* <collection>/list file lines */
  	LUPGRADE,	LOMIT,		LBACKUP,	LEXECUTE,
  	LINCLUDE,	LNOACCT,	LOMITANY,	LALWAYS,
! 	LSYMLINK,	LRSYMLINK,	LRENAME
  } LISTTYPE;
  
  static char *ltname[] = {
  	"upgrade",	"omit",		"backup",	"execute",
  	"include",	"noaccount",	"omitany",	"always",
! 	"symlink",	"rsymlink",	"rename",
  	0
  };
  
***************
*** 365,373 ****
  
  	if (newonly && (t->Tflags&FNEW) == 0)
  		return (SCMOK);
! 	newt = Tinsert (&listT,t->Tname,FALSE);
  	if (newt == NULL)
  		return (SCMOK);
  	newt->Tmode = t->Tmode;
  	newt->Tflags = t->Tflags;
  	newt->Tmtime = t->Tmtime;
--- 365,375 ----
  
  	if (newonly && (t->Tflags&FNEW) == 0)
  		return (SCMOK);
! 	newt = Tinsert (&listT,t->Tname,t->Tflags&FRENAME ? TRUE : FALSE);
  	if (newt == NULL)
  		return (SCMOK);
+ 	if(t->Tnewname)
+ 	  newt->Tnewname = salloc(t->Tnewname);
  	newt->Tmode = t->Tmode;
  	newt->Tflags = t->Tflags;
  	newt->Tmtime = t->Tmtime;
***************
*** 473,478 ****
--- 475,484 ----
  		case LUPGRADE:
  			t = &upgT;
  			break;
+ 		case LRENAME:
+ 			t = &flagsT;
+ 			flags = FRENAME;
+ 			break;
  		case LBACKUP:
  			t = &flagsT;
  			flags = FBACKUP;
***************
*** 522,528 ****
  					if (*q == 0)
  						_argbreak = ')';
  					else
! 						expTinsert (q,&execT,0,r);
  				} while (_argbreak != ')');
  				continue;
  			}
--- 528,534 ----
  					if (*q == 0)
  						_argbreak = ')';
  					else
! 						expTinsert (q,&execT,0,r,NULL);
  				} while (_argbreak != ')');
  				continue;
  			}
***************
*** 533,554 ****
  		while (*(q=nxtarg(&p," \t"))) {
  			if (lt == LOMITANY)
  				(void) Tinsert (t,q,FALSE);
  			else
! 				expTinsert (q,t,flags,(char *)NULL);
  		}
  	}
  	(void) fclose (f);
  }
  
  static
! expTinsert (p,t,flags,exec)
  char *p;
  TREE **t;
  int flags;
  char *exec;
  {
  	register int n, i;
! 	register TREE *newt;
  	char *speclist[SPECNUMBER];
  	char buf[STRINGLENGTH];
  
--- 539,575 ----
  		while (*(q=nxtarg(&p," \t"))) {
  			if (lt == LOMITANY)
  				(void) Tinsert (t,q,FALSE);
+ 			else if( lt == LRENAME )
+ 				if(*(r=nxtarg(&p," \t")))
+ 				{
+ 					expTinsert (q,t,flags,(char *)NULL,r);
+ 					/*
+ 					 * Omit the file it is being
+ 					 * renamed to, to avoid confusion
+ 					 */
+ 					expTinsert (r,&omitT,0,
+ 						   (char *)NULL, (char *)NULL);
+ 				}
+ 				else
+ 					printf("Rename %s without destination "
+ 					       "file.  Skipping...\n", q);
  			else
! 				expTinsert (q,t,flags,(char *)NULL,(char *)NULL);
  		}
  	}
  	(void) fclose (f);
  }
  
  static
! expTinsert (p,t,flags,exec, q)
  char *p;
+ char *q;
  TREE **t;
  int flags;
  char *exec;
  {
  	register int n, i;
! 	register TREE *newt, *ts;
  	char *speclist[SPECNUMBER];
  	char buf[STRINGLENGTH];
  
***************
*** 557,574 ****
  		newt = Tinsert (t,speclist[i],TRUE);
  		newt->Tflags |= flags;
  		if (exec) {
! 			(void) sprintf (buf,exec,speclist[i]);
  			(void) Tinsert (&newt->Texec,buf,FALSE);
  		}
  		free (speclist[i]);
  	}
  }
  
  static
! listone (t)		/* expand and add one name from upgrade list */
  TREE *t;
  {
! 	listentry(t->Tname,t->Tname,(char *)NULL,(t->Tflags&FALWAYS) != 0);
  	return (SCMOK);
  }
  
--- 578,602 ----
  		newt = Tinsert (t,speclist[i],TRUE);
  		newt->Tflags |= flags;
  		if (exec) {
! 			if((ts = Tsearch(flagsT, speclist[i])) 
! 			   && ts->Tflags&FRENAME)
! 				(void) sprintf (buf,exec,ts->Tnewname);
! 			else
! 				(void) sprintf (buf,exec,speclist[i]);
  			(void) Tinsert (&newt->Texec,buf,FALSE);
  		}
+ 		if (q)
+ 			newt->Tnewname = salloc(q);
  		free (speclist[i]);
  	}
  }
  
  static
! listone(t)		/* expand and add one name from upgrade list */
  TREE *t;
  {
! 	listentry(t->Tname,t->Tname,(char *)NULL,
! 		  (t->Tflags&FALWAYS) != 0);
  	return (SCMOK);
  }
  
***************
*** 644,651 ****
  	t->Tctime = st->st_ctime;
  	t->Tmtime = st->st_mtime;
  	if (new)  t->Tflags |= FNEW;
! 	if (ts = Tsearch (flagsT,name))
  		t->Tflags |= ts->Tflags;
  	if (ts = Tsearch (execT,name)) {
  		t->Texec = ts->Texec;
  		ts->Texec = NULL;
--- 672,682 ----
  	t->Tctime = st->st_ctime;
  	t->Tmtime = st->st_mtime;
  	if (new)  t->Tflags |= FNEW;
! 	if (ts = Tsearch (flagsT,name)){
  		t->Tflags |= ts->Tflags;
+ 		if(t->Tflags&FRENAME)
+ 			t->Tnewname = salloc(ts->Tnewname);
+ 	}
  	if (ts = Tsearch (execT,name)) {
  		t->Texec = ts->Texec;
  		ts->Texec = NULL;
***************
*** 831,836 ****
--- 862,871 ----
  			p++;
  			ts.Tflags |= FNOACCT;
  		}
+ 		if (*p == 'R') {
+ 			p++;
+ 			ts.Tflags |= FRENAME;
+ 		}
  		if ((q = index (p,' ')) == NULL)
  			goaway ("scanfile format inconsistant");
  		*q++ = '\0';
***************
*** 845,850 ****
--- 880,894 ----
  			goaway ("scanfile format inconsistant");
  		*q++ = 0;
  		ts.Tmtime = atoi (p);
+ 		p = q;
+ 		ts.Tnewname = NULL;
+ 		if (ts.Tflags & FRENAME){
+ 			if ((q = index (p,' ')) == NULL)
+ 				goaway ("scanfile format inconsistant");
+ 			*q++ = '\0';
+ 			ts.Tnewname = salloc(q);
+ 			q = p;
+ 		}
  		if (ts.Tctime > lasttime)
  			ts.Tflags |= FNEW;
  		else if (newonly) {
***************
*** 863,868 ****
--- 907,913 ----
  		t->Tflags = ts.Tflags;
  		t->Tctime = ts.Tctime;
  		t->Tmtime = ts.Tmtime;
+ 		t->Tnewname = ts.Tnewname;
  	}
  	(void) fclose (f);
  	return (TRUE);
***************
*** 925,932 ****
  
  	if (t->Tflags&FBACKUP)  fprintf (*scanF,"B");
  	if (t->Tflags&FNOACCT)  fprintf (*scanF,"N");
! 	fprintf (*scanF,"%o %d %d %s\n",
  		t->Tmode,t->Tctime,t->Tmtime,t->Tname);
  	(void) Tprocess (t->Texec,recordexec,*scanF);
  	return (SCMOK);
  }
--- 970,983 ----
  
  	if (t->Tflags&FBACKUP)  fprintf (*scanF,"B");
  	if (t->Tflags&FNOACCT)  fprintf (*scanF,"N");
! 	if (t->Tflags&FRENAME)  fprintf (*scanF,"R");
! 
! 	fprintf (*scanF,"%o %d %d",
  		t->Tmode,t->Tctime,t->Tmtime,t->Tname);
+ 	if ( t->Tflags&FRENAME)
+ 		fprintf (*scanF," %s %s\n",t->Tname, t->Tnewname);
+ 	else
+ 		fprintf (*scanF," %s\n", t->Tname);
  	(void) Tprocess (t->Texec,recordexec,*scanF);
  	return (SCMOK);
  }
diff -c /var/tmp/sup/scm.c sup/scm.c
*** scm.c	Sun Jun 19 23:04:04 1994
--- sup/scm.c	Thu Apr  6 13:53:57 1995
***************
*** 208,214 ****
   * PROTOTYPES
   */
  #if __STDC__
! int	scmerr	__P((int, char *,...));
  #endif
  /*************************
   ***    M A C R O S    ***
--- 208,214 ----
   * PROTOTYPES
   */
  #if __STDC__
! int   scmerr  __P((int, FILE *, char *,...));
  #endif
  /*************************
   ***    M A C R O S    ***
***************
*** 245,275 ****
  	int one = 1;
  
  	if (myhost () == NULL)
! 		return (scmerr (-1,"Local hostname not known"));
  	if ((sp = getservbyname(server,"tcp")) == 0) {
  		if (strcmp(server, FILEPORT) == 0)
  			port = htons((u_short)FILEPORTNUM);
  		else if (strcmp(server, DEBUGFPORT) == 0)
  			port = htons((u_short)DEBUGFPORTNUM);
  		else
! 			return (scmerr (-1,"Can't find %s server description",server));
! 		(void) scmerr (-1,"%s/tcp: unknown service: using port %d",
  					server,port);
  	} else
  		port = sp->s_port;
  	endservent ();
  	sock = socket (AF_INET,SOCK_STREAM,0);
  	if (sock < 0)
! 		return (scmerr (errno,"Can't create socket for connections"));
  	if (setsockopt (sock,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0)
! 		(void) scmerr (errno,"Can't set SO_REUSEADDR socket option");
  	(void) bzero ((char *)&sin,sizeof(sin));
  	sin.sin_family = AF_INET;
  	sin.sin_port = port;
  	if (bind (sock,(struct sockaddr *)&sin,sizeof(sin)) < 0)
! 		return (scmerr (errno,"Can't bind socket for connections"));
  	if (listen (sock,NCONNECTS) < 0)
! 		return (scmerr (errno,"Can't listen on socket"));
  	return (SCMOK);
  }
  
--- 245,275 ----
  	int one = 1;
  
  	if (myhost () == NULL)
! 		return (scmerr (-1, stderr, "Local hostname not known"));
  	if ((sp = getservbyname(server,"tcp")) == 0) {
  		if (strcmp(server, FILEPORT) == 0)
  			port = htons((u_short)FILEPORTNUM);
  		else if (strcmp(server, DEBUGFPORT) == 0)
  			port = htons((u_short)DEBUGFPORTNUM);
  		else
! 			return (scmerr (-1, stderr, "Can't find %s server description",server));
! 		(void) scmerr (-1, stderr, "%s/tcp: unknown service: using port %d",
  					server,port);
  	} else
  		port = sp->s_port;
  	endservent ();
  	sock = socket (AF_INET,SOCK_STREAM,0);
  	if (sock < 0)
! 		return (scmerr (errno, stderr, "Can't create socket for connections"));
  	if (setsockopt (sock,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0)
! 		(void) scmerr (errno, stderr, "Can't set SO_REUSEADDR socket option");
  	(void) bzero ((char *)&sin,sizeof(sin));
  	sin.sin_family = AF_INET;
  	sin.sin_port = port;
  	if (bind (sock,(struct sockaddr *)&sin,sizeof(sin)) < 0)
! 		return (scmerr (errno, stderr, "Can't bind socket for connections"));
  	if (listen (sock,NCONNECTS) < 0)
! 		return (scmerr (errno, stderr, "Can't listen on socket"));
  	return (SCMOK);
  }
  
***************
*** 284,299 ****
  		netfile = accept (sock,(struct sockaddr *)&from,&len);
  	} while (netfile < 0 && errno == EINTR);
  	if (netfile < 0)
! 		return (scmerr (errno,"Can't accept connections"));
  	remoteaddr = from.sin_addr;
  	if (read(netfile,(char *)&x,sizeof(int)) != sizeof(int))
! 		return (scmerr (errno,"Can't transmit data on connection"));
  	if (x == 0x01020304)
  		swapmode = 0;
  	else if (x == 0x04030201)
  		swapmode = 1;
  	else
! 		return (scmerr (-1,"Unexpected byteswap mode %x",x));
  	return (SCMOK);
  }
  
--- 284,299 ----
  		netfile = accept (sock,(struct sockaddr *)&from,&len);
  	} while (netfile < 0 && errno == EINTR);
  	if (netfile < 0)
! 		return (scmerr (errno, stderr, "Can't accept connections"));
  	remoteaddr = from.sin_addr;
  	if (read(netfile,(char *)&x,sizeof(int)) != sizeof(int))
! 		return (scmerr (errno, stderr, "Can't transmit data on connection"));
  	if (x == 0x01020304)
  		swapmode = 0;
  	else if (x == 0x04030201)
  		swapmode = 1;
  	else
! 		return (scmerr (-1, stderr, "Unexpected byteswap mode %x",x));
  	return (SCMOK);
  }
  
***************
*** 354,360 ****
  			s = *t;
  		*t -= s;
  	}
! 	(void) scmerr (-1,"Will retry in %d seconds",s);
  	sleep (s);
  	return (1);
  }
--- 354,360 ----
  			s = *t;
  		*t -= s;
  	}
! 	(void) scmerr (-1, stdout, "Will retry in %d seconds",s);
  	sleep (s);
  	return (1);
  }
***************
*** 376,384 ****
  		else if (strcmp(server, DEBUGFPORT) == 0)
  			port = htons((u_short)DEBUGFPORTNUM);
  		else
! 			return (scmerr (-1,"Can't find %s server description",
  					server));
! 		(void) scmerr (-1,"%s/tcp: unknown service: using port %d",
  					server,port);
  	} else
  		port = sp->s_port;
--- 376,384 ----
  		else if (strcmp(server, DEBUGFPORT) == 0)
  			port = htons((u_short)DEBUGFPORTNUM);
  		else
! 			return (scmerr (-1, stderr, "Can't find %s server description",
  					server));
! 		(void) scmerr (-1, stderr, "%s/tcp: unknown service: using port %d",
  					server,port);
  	} else
  		port = sp->s_port;
***************
*** 387,393 ****
  	sin.sin_addr.s_addr = inet_addr (hostname);
  	if (sin.sin_addr.s_addr == (u_long) INADDR_NONE) {
  		if ((h = gethostbyname (hostname)) == NULL)
! 			return (scmerr (-1,"Can't find host entry for %s",
  					hostname));
  		hostname = h->h_name;
  		(void) bcopy (h->h_addr,(char *)&sin.sin_addr,h->h_length);
--- 387,393 ----
  	sin.sin_addr.s_addr = inet_addr (hostname);
  	if (sin.sin_addr.s_addr == (u_long) INADDR_NONE) {
  		if ((h = gethostbyname (hostname)) == NULL)
! 			return (scmerr (-1, stderr, "Can't find host entry for %s",
  					hostname));
  		hostname = h->h_name;
  		(void) bcopy (h->h_addr,(char *)&sin.sin_addr,h->h_length);
***************
*** 397,407 ****
  	for (;;) {
  		netfile = socket (AF_INET,SOCK_STREAM,0);
  		if (netfile < 0)
! 			return (scmerr (errno,"Can't create socket"));
  		tin = sin;
  		if (connect(netfile,(struct sockaddr *)&tin,sizeof(tin)) >= 0)
  			break;
! 		(void) scmerr (errno,"Can't connect to server for %s",server);
  		(void) close(netfile);
  		if (!dobackoff (retry,&backoff))
  			return (SCMERR);
--- 397,407 ----
  	for (;;) {
  		netfile = socket (AF_INET,SOCK_STREAM,0);
  		if (netfile < 0)
! 			return (scmerr (errno, stderr, "Can't create socket"));
  		tin = sin;
  		if (connect(netfile,(struct sockaddr *)&tin,sizeof(tin)) >= 0)
  			break;
! 		(void) scmerr (errno, stderr, "Can't connect to server for %s",server);
  		(void) close(netfile);
  		if (!dobackoff (retry,&backoff))
  			return (SCMERR);
***************
*** 522,527 ****
--- 522,529 ----
  	struct hostent *h;
  	struct in_addr addr;
  	char **ap;
+ 	if(!strcmp(name,"*"))
+ 		return (1);
  	if ((addr.s_addr = inet_addr(name)) != (u_long) INADDR_NONE)
  		return (addr.s_addr == remoteaddr.s_addr);
  	if ((h = gethostbyname (name)) == 0)
***************
*** 535,541 ****
  }
  
  #if __STDC__
! int scmerr (int errno,char *fmt,...)
  #else
  /*VARARGS*//*ARGSUSED*/
  int scmerr (va_alist)
--- 537,543 ----
  }
  
  #if __STDC__
! int scmerr (int eno,FILE *filedes,char *fmt,...)
  #else
  /*VARARGS*//*ARGSUSED*/
  int scmerr (va_alist)
***************
*** 543,569 ****
  #endif
  {
  #if !__STDC__
! 	int errno;
  	char *fmt;
  #endif
  	va_list ap;
  
! 	(void) fflush (stdout);
  	if (progpid > 0)
! 		fprintf (stderr,"%s %d: ",program,progpid);
  	else
! 		fprintf (stderr,"%s: ",program);
  #if __STDC__
  	va_start(ap,fmt);
  #else
  	va_start(ap);
! 	errno = va_arg(ap,int);
  	fmt = va_arg(ap,char *);
  #endif
  	vfprintf(stderr, fmt, ap);
  	va_end(ap);
! 	if (errno >= 0)
! 		fprintf (stderr,": %s\n",errmsg(errno));
  	else
  		fprintf (stderr,"\n");
  	(void) fflush (stderr);
--- 545,572 ----
  #endif
  {
  #if !__STDC__
! 	int eno;
! 	FILE *filedes;
  	char *fmt;
  #endif
  	va_list ap;
  
! 	(void) fflush (filedes);
  	if (progpid > 0)
! 		fprintf (filedes,"%s %d: ",program,progpid);
  	else
! 		fprintf (filedes,"%s: ",program);
  #if __STDC__
  	va_start(ap,fmt);
  #else
  	va_start(ap);
! 	eno = va_arg(ap,int);
  	fmt = va_arg(ap,char *);
  #endif
  	vfprintf(stderr, fmt, ap);
  	va_end(ap);
! 	if (eno >= 0)
! 		fprintf (stderr,": %s\n",errmsg(eno));
  	else
  		fprintf (stderr,"\n");
  	(void) fflush (stderr);
diff -c /var/tmp/sup/scmio.c sup/scmio.c
*** scmio.c	Fri Aug 20 17:46:33 1993
--- sup/scmio.c	Sun Aug 13 19:12:45 1995
***************
*** 249,261 ****
  	}
  	if (x <= 0) {
  		if (errno == EPIPE)
! 			return (scmerr (-1,"Network write timed out"));
  		if (errno)
! 			return (scmerr (errno,"Write error on network"));
! 		return (scmerr (-1,"Write retries failed"));
  	}
  	if (x != count)
! 		return (scmerr (-1,"Write error on network returned %d on write of %d",x,count));
  	return (SCMOK);
  }
  
--- 249,261 ----
  	}
  	if (x <= 0) {
  		if (errno == EPIPE)
! 			return (scmerr (-1,stderr,"Network write timed out"));
  		if (errno)
! 			return (scmerr (errno,stderr,"Write error on network"));
! 		return (scmerr (-1,stderr,"Write retries failed"));
  	}
  	if (x != count)
! 		return (scmerr (-1,stderr,"Write error on network returned %d on write of %d",x,count));
  	return (SCMOK);
  }
  
***************
*** 280,286 ****
  	if (scmdebug > 1)
  		loginfo ("SCM Writing message %d",msg);
  	if (bufptr)
! 		return (scmerr (-1,"Buffering already enabled"));
  	bufptr = buffers;
  	bufptr->b_ptr = bufptr->b_data;
  	bufptr->b_cnt = 0;
--- 280,286 ----
  	if (scmdebug > 1)
  		loginfo ("SCM Writing message %d",msg);
  	if (bufptr)
! 		return (scmerr (-1,stderr,"Buffering already enabled"));
  	bufptr = buffers;
  	bufptr->b_ptr = bufptr->b_data;
  	bufptr->b_cnt = 0;
***************
*** 298,304 ****
  	x = writedata (sizeof(int),(char *)&x);
  	if (x != SCMOK)  return (x);
  	if (bufptr == NULL)
! 		return (scmerr (-1,"Buffering already disabled"));
  	if (bufptr->b_cnt == 0) {
  		bufptr = NULL;
  		return (SCMOK);
--- 298,304 ----
  	x = writedata (sizeof(int),(char *)&x);
  	if (x != SCMOK)  return (x);
  	if (bufptr == NULL)
! 		return (scmerr (-1,stderr,"Buffering already disabled"));
  	if (bufptr->b_cnt == 0) {
  		bufptr = NULL;
  		return (SCMOK);
***************
*** 351,357 ****
  	struct stat statbuf;
  
  	if (fstat(f,&statbuf) < 0)
! 		return (scmerr (errno,"Can't access open file for message"));
  	filesize = statbuf.st_size;
  	y = byteswap(filesize);
  	x = writedata (sizeof(int),(char *)&y);
--- 351,357 ----
  	struct stat statbuf;
  
  	if (fstat(f,&statbuf) < 0)
! 		return (scmerr (errno,stderr,"Can't access open file for message"));
  	filesize = statbuf.st_size;
  	y = byteswap(filesize);
  	x = writedata (sizeof(int),(char *)&y);
***************
*** 375,383 ****
  		} while (x == SCMOK && number > 0);
  	}
  	if (sum != filesize)
! 		return (scmerr (-1,"File size error on output message"));
  	if (number < 0)
! 		return (scmerr (errno,"Read error on file output message"));
  	return (x);
  }
  
--- 375,383 ----
  		} while (x == SCMOK && number > 0);
  	}
  	if (sum != filesize)
! 		return (scmerr (-1,stderr,"File size error on output message"));
  	if (number < 0)
! 		return (scmerr (errno,stderr,"Read error on file output message"));
  	return (x);
  }
  
***************
*** 431,437 ****
  
  	if (count < 0) {
  		if (bufptr + count < buffer)
! 			return (scmerr (-1,"No space in buffer %d",count));
  		bufptr += count;
  		bufcnt -= count;
  		bcopy (data,bufptr,-count);
--- 431,437 ----
  
  	if (count < 0) {
  		if (bufptr + count < buffer)
! 			return (scmerr (-1,stderr,"No space in buffer %d",count));
  		bufptr += count;
  		bufcnt -= count;
  		bcopy (data,bufptr,-count);
***************
*** 463,478 ****
  		tries = 0;
  		for (;;) {
  			imask = 1 << netfile;
  			if (select(32,(fd_set *)&imask,(fd_set *)0,(fd_set *)0,&timout) < 0)
  				imask = 1;
  			errno = 0;
  			if (imask)
  				x = read (netfile,p,n);
  			else
! 				return (scmerr (-1,"Timeout on network input"));
  			if (x > 0)  break;
  			if (x == 0)
! 				return (scmerr (-1,"Premature EOF on network input"));
  			if (errno)  break;
  			if (++tries > RETRIES)  break;
  			if (scmdebug > 0)
--- 463,483 ----
  		tries = 0;
  		for (;;) {
  			imask = 1 << netfile;
+ #if defined(__hpux)
+ 			if (select(32,&imask,(int *)0,(int *)0,&timout) < 0)
+ #else
  			if (select(32,(fd_set *)&imask,(fd_set *)0,(fd_set *)0,&timout) < 0)
+ #endif
  				imask = 1;
  			errno = 0;
  			if (imask)
  				x = read (netfile,p,n);
  			else
! 				return (scmerr (-1,stderr,"Timeout on network input"));
  			if (x > 0)  break;
  			if (x == 0)
! 				return (scmerr (-1,stderr,"Premature EOF on network "
! 						"input"));
  			if (errno)  break;
  			if (++tries > RETRIES)  break;
  			if (scmdebug > 0)
***************
*** 480,487 ****
  		}
  		if (x < 0) {
  			if (errno)
! 				return (scmerr (errno,"Read error on network"));
! 			return (scmerr (-1,"Read retries failed"));
  		}
  		p += x;
  		n -= x;
--- 485,492 ----
  		}
  		if (x < 0) {
  			if (errno)
! 				return (scmerr (errno,stderr,"Read error on network"));
! 			return (scmerr (-1,stderr,"Read retries failed"));
  		}
  		p += x;
  		n -= x;
***************
*** 538,544 ****
  
  	/* check for MSGGOAWAY in case he noticed problems first */
  	if (m != MSGGOAWAY)
! 		return (scmerr (-1,"Received unexpected message %d",m));
  	(void) netcrypt ((char *)NULL);
  	(void) readstring (&goawayreason);
  	(void) readmend ();
--- 543,549 ----
  
  	/* check for MSGGOAWAY in case he noticed problems first */
  	if (m != MSGGOAWAY)
! 		return (scmerr (-1,stderr,"Received unexpected message %d",m));
  	(void) netcrypt ((char *)NULL);
  	(void) readstring (&goawayreason);
  	(void) readmend ();
***************
*** 555,561 ****
  	x = readdata (sizeof(int),(char *)&y);
  	y = byteswap(y);
  	if (x == SCMOK && y != ENDCOUNT)
! 		return (scmerr (-1,"Error reading end of message"));
  	return (x);
  }
  
--- 560,566 ----
  	x = readdata (sizeof(int),(char *)&y);
  	y = byteswap(y);
  	if (x == SCMOK && y != ENDCOUNT)
! 		return (scmerr (-1,stderr,"Error reading end of message"));
  	return (x);
  }
  
***************
*** 567,573 ****
  	x = readcount (&n);
  	if (x != SCMOK)  return (x);
  	if (n < 0)
! 		return (scmerr (-1,"Invalid message count %d",n));
  	while (x == SCMOK && n > 0) {
  		x = readdata (XFERSIZE(n),buf);
  		n -= XFERSIZE(n);
--- 572,578 ----
  	x = readcount (&n);
  	if (x != SCMOK)  return (x);
  	if (n < 0)
! 		return (scmerr (-1,stderr,"Invalid message count %d",n));
  	while (x == SCMOK && n > 0) {
  		x = readdata (XFERSIZE(n),buf);
  		n -= XFERSIZE(n);
***************
*** 583,591 ****
  	x = readcount (&y);
  	if (x != SCMOK)  return (x);
  	if (y < 0)
! 		return (scmerr (-1,"Invalid message count %d",y));
  	if (y != sizeof(int))
! 		return (scmerr (-1,"Size error for int message is %d",y));
  	x = readdata (sizeof(int),(char *)&y);
  	(*buf) = byteswap(y);
  	if (scmdebug > 2)
--- 588,596 ----
  	x = readcount (&y);
  	if (x != SCMOK)  return (x);
  	if (y < 0)
! 		return (scmerr (-1,stderr,"Invalid message count %d",y));
  	if (y != sizeof(int))
! 		return (scmerr (-1,stderr,"Size error for int message is %d",y));
  	x = readdata (sizeof(int),(char *)&y);
  	(*buf) = byteswap(y);
  	if (scmdebug > 2)
***************
*** 609,619 ****
  		return (SCMOK);
  	}
  	if (count < 0)
! 		return (scmerr (-1,"Invalid message count %d",count));
  	if (scmdebug > 3)
  		loginfo ("SCM Reading string count %d",count);
  	if ((p = (char *)malloc ((unsigned)count+1)) == NULL)
! 		return (scmerr (-1,"Can't malloc %d bytes for string",count));
  	if (cryptflag) {
  		x = getcryptbuf (count+1);
  		if (x == SCMOK)  x = readdata (count,cryptbuf);
--- 614,624 ----
  		return (SCMOK);
  	}
  	if (count < 0)
! 		return (scmerr (-1,stderr,"Invalid message count %d",count));
  	if (scmdebug > 3)
  		loginfo ("SCM Reading string count %d",count);
  	if ((p = (char *)malloc ((unsigned)count+1)) == NULL)
! 		return (scmerr (-1,stderr,"Can't malloc %d bytes for string",count));
  	if (cryptflag) {
  		x = getcryptbuf (count+1);
  		if (x == SCMOK)  x = readdata (count,cryptbuf);
***************
*** 647,653 ****
  	x = readcount (&count);
  	if (x != SCMOK)  return (x);
  	if (count < 0)
! 		return (scmerr (-1,"Invalid message count %d",count));
  	while (x == SCMOK && count > 0) {
  		if (cryptflag) {
  			x = readdata (XFERSIZE(count),cryptbuf);
--- 652,658 ----
  	x = readcount (&count);
  	if (x != SCMOK)  return (x);
  	if (count < 0)
! 		return (scmerr (-1,stderr,"Invalid message count %d",count));
  	while (x == SCMOK && count > 0) {
  		if (cryptflag) {
  			x = readdata (XFERSIZE(count),cryptbuf);
***************
*** 709,715 ****
--- 714,724 ----
  		FD_ZERO (&xbits);
  		FD_SET (0,&ibits);
  		FD_SET (netfile,&ibits);
+ #if defined(__hpux)
+ 		if ((c = select(16, (int *)&ibits, (int *)&obits, (int *)&xbits,
+ #else
  		if ((c = select(16, &ibits, &obits, &xbits,
+ #endif
  				(struct timeval *)NULL)) < 1) {
  			if (c == -1) {
  				if (errno == EINTR) {
diff -c /var/tmp/sup/stree.c sup/stree.c
*** stree.c	Fri Aug 20 17:46:34 1993
--- sup/stree.c	Wed Apr  5 12:36:58 1995
***************
*** 77,82 ****
--- 77,83 ----
  	Tfree (&((*t)->Tlo));
  	Tfree (&((*t)->Thi));
  	if ((*t)->Tname)  free ((*t)->Tname);
+ 	if ((*t)->Tnewname)  free ((*t)->Tnewname);
  	if ((*t)->Tuser)  free ((*t)->Tuser);
  	if ((*t)->Tgroup)  free ((*t)->Tgroup);
  	free (*(char **)t);
***************
*** 90,95 ****
--- 91,97 ----
  	register TREE *t;
  	t = (TREE *) malloc (sizeof (TREE));
  	t->Tname = (p == NULL) ? NULL : salloc (p);
+ 	t->Tnewname = NULL;
  	t->Tflags = 0;
  	t->Tuid = 0;
  	t->Tgid = 0;
diff -c /var/tmp/sup/sup.1 sup/sup.1
*** sup.1	Thu Aug 11 06:24:44 1994
--- sup/sup.1	Wed Apr 12 00:22:06 1995
***************
*** 59,65 ****
  .\" 04-Apr-85  Steven Shafer (sas) at Carnegie-Mellon University
  .\" 	Created.
  .\" 
! .TH SUP 1 02/08/92
  .CM 4
  .SH "NAME"
  sup \- software upgrade protocol
--- 59,65 ----
  .\" 04-Apr-85  Steven Shafer (sas) at Carnegie-Mellon University
  .\" 	Created.
  .\" 
! .TH SUP 1 03/15/95
  .CM 4
  .SH "NAME"
  sup \- software upgrade protocol
***************
*** 247,252 ****
--- 247,287 ----
  will be printed that indicate what would happen if
  an actual upgrade were done.
  .TP
+ .B -i
+ Normally, 
+ .I sup 
+ will fail to upgrade any files that are \fBETXTBSY\fR.
+ The
+ .B -i
+ flag, or the
+ .B unlinkbusy
+ supfile option, will cause
+ .I sup
+ to try to upgrade a busy file by unlinking it before the 
+ replacement file is installed.  The option is intended for
+ environments where upgrades to possibly running binaries or 
+ libraries will take place.  Some operating systems \fB(HPUX)\fR 
+ do not allow the unlink system call to succeed on ETXTBSY files.
+ If the unlink does not succeed, an attempt is made to rename the 
+ file to filename.sup#sup-pid.moved.  The new name is logged in either 
+ the system default rename log file, \fB/usr/local/etc/sup.moved\fR, 
+ or in a logfile as set by the \fBrenamelog\fR supfile option.  The 
+ logfile allows for easy deletion of ETXTBSY files once they are no 
+ longer in use.  A typical time to perform the deletions is at system 
+ boot time with something similar to:
+ .TP
+ .ce 1
+ cat /usr/local/etc/sup.moved | xargs rm -rf
+ .TP
+ .B -I
+ The
+ .B -I
+ flag overrides and disables the
+ .B -i
+ flag and the
+ .B unlinkbusy
+ supfile option.
+ .TP
  .B -k
  .I Sup
  will check the modification times of
***************
*** 537,542 ****
--- 572,590 ----
  .I sup
  to upgrade that collection.
  .TP
+ .BI renamelog= filename
+ When the 
+ .B
+ unlinkbusy
+ or
+ .B
+ -i
+ option is enabled, but the system cannot unlink a busy file, it
+ will rename it instead and log the new filename.  Logging will 
+ occur to the system default rename log file or to the specified
+ .IR filename
+ in the renamelog entry of a supfile.
+ .TP
  .B backup
  As described above under the
  .B -b
***************
*** 562,567 ****
--- 610,620 ----
  .B -o
  flag.
  .TP
+ .B unlinkbusy
+ As described above under the
+ .B -i
+ flag.
+ .TP
  .B noupdate
  As described above under the
  .B -u
***************
*** 729,734 ****
--- 782,793 ----
  omitany commands do not affect filenames specified with the always
  command.
  .TP
+ \fBrename\fR \fIfilename\fR \fIdest-filename\fR...
+ The rename command allows for a file on the server to be placed on the
+ client under a different name.  To prevent confusion and ease its use,
+ the rename option implicitly omits any files on the server that have 
+ the same name as \fIdest-filename\fR.
+ .TP
  \fBomit\fR \fIfilename\fR ...
  The specified file(s) (or directories) will be excluded from the
  list of files to be upgraded.
***************
*** 796,802 ****
  .I sup
  with the
  .B -e
! flag to allow the automatic execution of command files.
  .TP
  \fBinclude\fR \fIlistfile\fR ...
  The specified
--- 855,863 ----
  .I sup
  with the
  .B -e
! flag to allow the automatic execution of command files.  The timestamp
! of the upgraded file is maintained even if the executed command might
! change it so as to prevent an upgrade with every \fIsup\fR.
  .TP
  \fBinclude\fR \fIlistfile\fR ...
  The specified
***************
*** 861,866 ****
--- 922,930 ----
  .TP
  <\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/logfile
  log file for a collection
+ .TP
+ \fB/usr/local/etc/sup.moved\fR 
+ log file for files renamed by the \fBunlinkbusy\fR option
  .TP
  <\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/prefix
  file containing the name of the prefix directory
diff -c /var/tmp/sup/sup.h sup/sup.h
*** sup.h	Fri Aug 20 17:46:34 1993
--- sup/sup.h	Thu Apr  6 14:08:06 1995
***************
*** 101,108 ****
  
  /* PGMVERSION is defined separately in each program */
  extern char scmversion[];		/* string version of scm */
! #define PROTOVERSION 8			/* version of network protocol */
! #define SCANVERSION  2			/* version of scan file format */
  
  /* TCP servers for name server and file server */
  #define FILEPORT	"supfilesrv"
--- 101,108 ----
  
  /* PGMVERSION is defined separately in each program */
  extern char scmversion[];		/* string version of scm */
! #define PROTOVERSION 9			/* version of network protocol */
! #define SCANVERSION  3			/* version of scan file format */
  
  /* TCP servers for name server and file server */
  #define FILEPORT	"supfilesrv"
***************
*** 182,187 ****
--- 182,188 ----
  struct treestruct {
  /* fields for file information */
  	char *Tname;			/* path component name */
+ 	char *Tnewname;			/* Used for renameing files */
  	int Tflags;			/* flags of file */
  	int Tmode;			/* st_mode of file */
  	char *Tuser;			/* owner of file */
***************
*** 220,225 ****
--- 221,227 ----
  #define FBACKUP		     02		/* backup of file is allowed */
  #define FNOACCT		     04		/* don't set file information */
  #define FUPDATE		    010		/* only set file information */
+ #define FRENAME		    020		/* Rename this file while updating */
  #define FNEEDED		0100000		/* file needed for upgrade */
  
  /* version 3 compatability */
diff -c /var/tmp/sup/supcdefs.h sup/supcdefs.h
*** supcdefs.h	Thu Aug 11 06:24:45 1994
--- supcdefs.h	Sun May 30 22:13:40 1999
***************
*** 98,104 ****
  extern int errno;
  extern uid_t getuid();
  extern gid_t getgid();
- extern long time();
  
  extern int PGMVERSION;
  
--- 98,103 ----
***************
*** 118,123 ****
--- 117,123 ----
  	char *Clogin;			/* remote login name */
  	char *Cpswd;			/* remote password */
  	char *Ccrypt;			/* data encryption key */
+ 	char *Crenamelog;		/* Where to log files moved when busy */
  	int Ctimeout;			/* timeout for backoff */
  	int Cflags;			/* collection flags */
  	int Cnogood;			/* upgrade no good, "when" unchanged */
***************
*** 126,144 ****
  };
  typedef struct collstruct COLLECTION;
  
! #define CFALL		00001
! #define CFBACKUP	00002
! #define CFDELETE	00004
! #define CFEXECUTE	00010
! #define CFLIST		00020
! #define CFLOCAL		00040
! #define CFMAIL		00100
! #define CFOLD		00200
! #define CFVERBOSE	00400
! #define CFKEEP		01000
! #define CFURELSUF	02000
! #define CFCOMPRESS	04000
! #define CFNOUPDATE     010000
  
  /*************************
   ***	M A C R O S    ***
--- 126,145 ----
  };
  typedef struct collstruct COLLECTION;
  
! #define CFALL		0x0001
! #define CFBACKUP	0x0002
! #define CFDELETE	0x0004
! #define CFEXECUTE	0x0008
! #define CFLIST		0x0010
! #define CFLOCAL		0x0020
! #define CFMAIL		0x0040
! #define CFOLD		0x0080
! #define CFVERBOSE	0x0100
! #define CFKEEP		0x0200
! #define CFURELSUF	0x0400
! #define CFCOMPRESS	0x0800
! #define CFNOUPDATE	0x1000
! #define CFUNLINKBUSY	0x2000
  
  /*************************
   ***	M A C R O S    ***
***************
*** 149,155 ****
   * C prototypes
   */
  #if __STDC__
! void	done	__P((int value,char *fmt,...));
! void	goaway	__P((char *fmt,...));
! void	notify	__P((char *fmt,...));
  #endif
--- 150,156 ----
   * C prototypes
   */
  #if __STDC__
! void  done    __P((int value,char *fmt,...));
! void  goaway  __P((char *fmt,...));
! void  notify  __P((char *fmt,...));
  #endif
diff -c /var/tmp/sup/supcmain.c sup/supcmain.c
*** supcmain.c	Thu Aug 11 06:24:45 1994
--- sup/supcmain.c	Thu Apr  6 15:43:18 1995
***************
*** 418,424 ****
--- 418,428 ----
  			int fd;
  			loginfo ("SUP Restarting %s with new supfile %s",
  				progname,supfname);
+ #ifdef __hpux
+ 			for (fd = 256; fd > 3; fd--)
+ #else
  			for (fd = getdtablesize (); fd > 3; fd--)
+ #endif
  				(void) close (fd);
  			execv (progname,argv);
  			logquit (1,"Restart failed");
***************
*** 550,555 ****
--- 554,567 ----
  			break;
  		case 'm':
  			oflags |= CFMAIL;
+ 			break;
+ 		case 'i':
+ 			oflags |= CFUNLINKBUSY;
+ 			aflags &= ~CFUNLINKBUSY;
+ 			break;
+ 		case 'I':
+ 			oflags &= ~CFUNLINKBUSY;
+ 			aflags |= CFUNLINKBUSY;
  			break;
  		case 'o':
  			oflags |= CFOLD;
diff -c /var/tmp/sup/supcmeat.c sup/supcmeat.c
*** supcmeat.c	Thu Aug 11 06:24:45 1994
--- sup/supcmeat.c	Sun Aug 13 18:44:26 1995
***************
*** 156,161 ****
--- 156,163 ----
  int dontjump;				/* flag to void sjbuf */
  int cancompress=FALSE;			/* Can we do compression? */
  int docompress=FALSE;			/* Do we do compression? */
+ int dounlinkbusy=FALSE;			/* Should we try to unlink busy files?*/
+ FILE *renamelog=NULL;			/* Where we log renamed files */
  
  extern COLLECTION *thisC;		/* collection list pointer */
  extern int rpauseflag;			/* don't disable resource pausing */
***************
*** 492,498 ****
  	int needone(), denyone(), deleteone();
  	char buf[STRINGLENGTH];
  	char relsufix[STRINGLENGTH];
! 	register char *p,*q;
  	register FILE *f;
  	register int x;
  
--- 494,501 ----
  	int needone(), denyone(), deleteone();
  	char buf[STRINGLENGTH];
  	char relsufix[STRINGLENGTH];
! 	TREE *t;
! 	register char *p,*q,*r;
  	register FILE *f;
  	register int x;
  
***************
*** 506,513 ****
  	if (f) {
  		while (p = fgets (buf,STRINGLENGTH,f)) {
  			if (q = index (p,'\n'))  *q = '\0';
  			if (index ("#;:",*p))  continue;
! 			(void) Tinsert (&lastT,p,FALSE);
  		}
  		(void) fclose (f);
  	}
--- 509,522 ----
  	if (f) {
  		while (p = fgets (buf,STRINGLENGTH,f)) {
  			if (q = index (p,'\n'))  *q = '\0';
+ 			if (r = index (p,' '))  *r++ = '\0';
  			if (index ("#;:",*p))  continue;
! 			t = Tinsert (&lastT,p,FALSE);
! 			if(t && r)
! 			{
! 				t->Tnewname = salloc(r);
! 				t->Tflags = FRENAME;
! 			}
  		}
  		(void) fclose (f);
  	}
***************
*** 532,537 ****
--- 541,547 ----
  		goaway ("Error reading file list from file server");
  	if (thisC->Cprefix)  (void) chdir (thisC->Cprefix);
  	needT = NULL;
+ 	renameT = NULL;
  	(void) Tprocess (listT,needone);
  	Tfree (&listT);
  	x = msgneed ();
***************
*** 548,553 ****
--- 558,565 ----
  	if (thisC->Cflags&(CFALL|CFDELETE|CFOLD))
  		(void) Trprocess (lastT,deleteone);
  	Tfree (&refuseT);
+ 	Tfree (&renameT);
+ 	renameT = NULL;
  }
  
  needone (t)
***************
*** 556,572 ****
  	register TREE *newt;
  	register int exists, fetch;
  	struct stat sbuf;
  
  	newt = Tinsert (&lastT,t->Tname,TRUE);
  	newt->Tflags |= FUPDATE;
  	fetch = TRUE;
  	if ((thisC->Cflags&CFALL) == 0) {
  		if ((t->Tflags&FNEW) == 0 && (thisC->Cflags&CFOLD) == 0)
  			return (SCMOK);
  		if ((t->Tmode&S_IFMT) == S_IFLNK)
! 			exists = (lstat (t->Tname,&sbuf) == 0);
  		else
! 			exists = (stat (t->Tname,&sbuf) == 0);
  		/* This is moderately complicated:
  		   If the file is the wrong type or doesn't exist, we need to
  		   fetch the whole file.  If the file is a special file, we
--- 568,593 ----
  	register TREE *newt;
  	register int exists, fetch;
  	struct stat sbuf;
+ 	char *name;
  
  	newt = Tinsert (&lastT,t->Tname,TRUE);
  	newt->Tflags |= FUPDATE;
+ 	if(t->Tflags&FRENAME) {
+ 	  newt->Tflags |= FRENAME;
+ 	  newt->Tnewname = salloc(t->Tnewname);
+ 	  name = t->Tnewname; 
+ 	  Tinsert(&renameT,t->Tnewname);
+ 	}
+ 	else
+ 	  name = t->Tname;
  	fetch = TRUE;
  	if ((thisC->Cflags&CFALL) == 0) {
  		if ((t->Tflags&FNEW) == 0 && (thisC->Cflags&CFOLD) == 0)
  			return (SCMOK);
  		if ((t->Tmode&S_IFMT) == S_IFLNK)
! 			exists = (lstat (name,&sbuf) == 0);
  		else
! 			exists = (stat (name,&sbuf) == 0);
  		/* This is moderately complicated:
  		   If the file is the wrong type or doesn't exist, we need to
  		   fetch the whole file.  If the file is a special file, we
***************
*** 592,603 ****
  				else return (SCMOK);
  	}
  	/* If we get this far, we're either doing an update or a full fetch. */
  	if (!fetch && t->Tmode == sbuf.st_mode &&
  	    (t->Tmode&S_IFMT) == S_IFREG && (thisC->Cflags&CFNOUPDATE)) {
  		vnotify ("SUP update avoided for %s\n", t->Tname);
! 		return (SCMOK);
  	}
- 	newt = Tinsert (&needT,t->Tname,TRUE);
  	if (!fetch && (t->Tmode&S_IFMT) == S_IFREG)
  		newt->Tflags |= FUPDATE;
  	return (SCMOK);
--- 613,624 ----
  				else return (SCMOK);
  	}
  	/* If we get this far, we're either doing an update or a full fetch. */
+ 	newt = Tinsert (&needT,t->Tname,TRUE);
  	if (!fetch && t->Tmode == sbuf.st_mode &&
  	    (t->Tmode&S_IFMT) == S_IFREG && (thisC->Cflags&CFNOUPDATE)) {
  		vnotify ("SUP update avoided for %s\n", t->Tname);
! 		 return (SCMOK);
  	}
  	if (!fetch && (t->Tmode&S_IFMT) == S_IFREG)
  		newt->Tflags |= FUPDATE;
  	return (SCMOK);
***************
*** 615,626 ****
  {
  	struct stat sbuf;
  	register int x;
! 	register char *name = t->Tname;
  
  	if (t->Tflags&FUPDATE)		/* in current upgrade list */
  		return (SCMOK);
  	if (lstat(name,&sbuf) < 0)	/* doesn't exist */
  		return (SCMOK);
  	/* is it a symbolic link ? */
  	if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
  		if (Tlookup (refuseT,name)) {
--- 636,650 ----
  {
  	struct stat sbuf;
  	register int x;
! 	register char *name = t->Tflags & FRENAME ? t->Tnewname : t->Tname;
  
  	if (t->Tflags&FUPDATE)		/* in current upgrade list */
  		return (SCMOK);
  	if (lstat(name,&sbuf) < 0)	/* doesn't exist */
  		return (SCMOK);
+ 	if (Tlookup (renameT, name))    /* it is a file we're going to replace
+ 	        return (SCMOK);          * by renaming another target.
+ 		                         */
  	/* is it a symbolic link ? */
  	if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
  		if (Tlookup (refuseT,name)) {
***************
*** 723,728 ****
--- 747,756 ----
  		if (docompress)
  			vnotify("SUP Using compressed file transfer\n");
  	}
+ 	/* Should we attempt to unlink files that are busy? */
+ 	dounlinkbusy = (thisC->Cflags & CFUNLINKBUSY);
+ 	if(dounlinkbusy)
+ 		vnotify("SUP Will attempt to unlink busy files\n");
  	recvmore = TRUE;
  	upgradeT = NULL;
  	do {
***************
*** 735,740 ****
--- 763,770 ----
  			goaway ("Error receiving file from file server");
  		Tfree (&upgradeT);
  	} while (recvmore);
+ 	if( renamelog )
+ 	   fclose( renamelog );
  }
  
  /* prepare the target, if necessary */
***************
*** 779,785 ****
  	}
  	if ((statp->st_mode&S_IFMT) == S_IFDIR) {
  		if (rmdir (name) < 0)
! 			runp ("rm","rm","-rf",name,0);
  	} else
  		(void) unlink (name);
  	if (stat (name,statp) < 0) {
--- 809,815 ----
  	}
  	if ((statp->st_mode&S_IFMT) == S_IFDIR) {
  		if (rmdir (name) < 0)
! 			runp ("rm","rm","-rf",name,(char *)0);
  	} else
  		(void) unlink (name);
  	if (stat (name,statp) < 0) {
***************
*** 799,805 ****
  	struct stat sbuf;
  	int linkone (),execone ();
  	int *recvmore = va_arg(ap,int *);
! 
  	/* check for end of file list */
  	if (t == NULL) {
  		*recvmore = FALSE;
--- 829,835 ----
  	struct stat sbuf;
  	int linkone (),execone ();
  	int *recvmore = va_arg(ap,int *);
! 	char *name;
  	/* check for end of file list */
  	if (t == NULL) {
  		*recvmore = FALSE;
***************
*** 812,819 ****
  		thisC->Cnogood = TRUE;
  		return (SCMOK);
  	}
! 	if (prepare (t->Tname,t->Tmode&S_IFMT,&new,&sbuf)) {
! 		notify ("SUP: Can't prepare path for %s\n",t->Tname);
  		if ((t->Tmode&S_IFMT) == S_IFREG) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
--- 842,850 ----
  		thisC->Cnogood = TRUE;
  		return (SCMOK);
  	}
! 	name = t->Tflags & FRENAME ? t->Tnewname : t->Tname; 
! 	if (prepare (name,t->Tmode&S_IFMT,&new,&sbuf)) {
! 		notify ("SUP: Can't prepare path for %s\n",name);
  		if ((t->Tmode&S_IFMT) == S_IFREG) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
***************
*** 841,848 ****
  		return (SCMOK);
  	}
  	if ((t->Tmode&S_IFMT) == S_IFREG)
! 		(void) Tprocess (t->Tlink,linkone,t->Tname);
! 	(void) Tprocess (t->Texec,execone);
  	return (SCMOK);
  }
  
--- 872,879 ----
  		return (SCMOK);
  	}
  	if ((t->Tmode&S_IFMT) == S_IFREG)
! 		(void) Tprocess (t->Tlink,linkone,name);
! 	(void) Tprocess (t->Texec,execone,name);
  	return (SCMOK);
  }
  
***************
*** 852,866 ****
  register struct stat *statp;
  {
  	struct timeval tbuf[2];
  
  	if (new) {
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would create directory %s\n",t->Tname);
  			return (FALSE);
  		}
! 		(void) mkdir (t->Tname,0755);
! 		if (stat (t->Tname,statp) < 0) {
! 			notify ("SUP: Can't create directory %s\n",t->Tname);
  			return (TRUE);
  		}
  	}
--- 883,898 ----
  register struct stat *statp;
  {
  	struct timeval tbuf[2];
+ 	char *name = t->Tflags & FRENAME ? t->Tnewname : t->Tname;
  
  	if (new) {
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would create directory %s\n",name);
  			return (FALSE);
  		}
! 		(void) mkdir (name,0755);
! 		if (stat (name,statp) < 0) {
! 			notify ("SUP: Can't create directory %s\n",name);
  			return (TRUE);
  		}
  	}
***************
*** 875,891 ****
  			return (FALSE);
  	}
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would update directory %s\n",t->Tname);
  		return (FALSE);
  	}
  	if ((t->Tflags&FNOACCT) == 0) {
! 		(void) chown (t->Tname,t->Tuid,t->Tgid);
! 		(void) chmod (t->Tname,t->Tmode&S_IMODE);
  	}
  	tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  	tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 	(void) utimes (t->Tname,tbuf);
! 	vnotify ("SUP %s directory %s\n",new?"Created":"Updated",t->Tname);
  	return (FALSE);
  }
  
--- 907,923 ----
  			return (FALSE);
  	}
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would update directory %s\n",name);
  		return (FALSE);
  	}
  	if ((t->Tflags&FNOACCT) == 0) {
! 		(void) chown (name,t->Tuid,t->Tgid);
! 		(void) chmod (name,t->Tmode&S_IMODE);
  	}
  	tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  	tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 	(void) utimes (name,tbuf);
! 	vnotify ("SUP %s directory %s\n",new?"Created":"Updated",name);
  	return (FALSE);
  }
  
***************
*** 897,925 ****
  	char buf[STRINGLENGTH];
  	int n;
  	register char *linkname;
  
! 	if (t->Tlink == NULL || t->Tlink->Tname == NULL) {
  		notify ("SUP: Missing linkname for symbolic link %s\n",
  			t->Tname);
  		return (TRUE);
  	}
  	linkname = t->Tlink->Tname;
  	if (!new && (t->Tflags&FNEW) == 0 &&
! 	    (n = readlink (t->Tname,buf,sizeof(buf))) >= 0 &&
  	    (n == strlen (linkname)) && (strncmp (linkname,buf,n) == 0))
  		return (FALSE);
  	if (thisC->Cflags&CFLIST) {
  		vnotify ("SUP Would %s symbolic link %s to %s\n",
! 			new?"create":"update",t->Tname,linkname);
  		return (FALSE);
  	}
  	if (!new)
! 		(void) unlink (t->Tname);
! 	if (symlink (linkname,t->Tname) < 0 || lstat(t->Tname,statp) < 0) {
! 		notify ("SUP: Unable to create symbolic link %s\n",t->Tname);
  		return (TRUE);
  	}
! 	vnotify ("SUP Created symbolic link %s to %s\n",t->Tname,linkname);
  	return (FALSE);
  }
  
--- 929,958 ----
  	char buf[STRINGLENGTH];
  	int n;
  	register char *linkname;
+ 	char *name = t->Tflags & FRENAME ? t->Tnewname : t->Tname;
  
! 	if (t->Tlink == NULL || name == NULL) {
  		notify ("SUP: Missing linkname for symbolic link %s\n",
  			t->Tname);
  		return (TRUE);
  	}
  	linkname = t->Tlink->Tname;
  	if (!new && (t->Tflags&FNEW) == 0 &&
! 	    (n = readlink (name,buf,sizeof(buf))) >= 0 &&
  	    (n == strlen (linkname)) && (strncmp (linkname,buf,n) == 0))
  		return (FALSE);
  	if (thisC->Cflags&CFLIST) {
  		vnotify ("SUP Would %s symbolic link %s to %s\n",
! 			new?"create":"update",name,linkname);
  		return (FALSE);
  	}
  	if (!new)
! 		(void) unlink (name);
! 	if (symlink (linkname,name) < 0 || lstat(name,statp) < 0) {
! 		notify ("SUP: Unable to create symbolic link %s\n",name);
  		return (TRUE);
  	}
! 	vnotify ("SUP Created symbolic link %s to %s\n",name,linkname);
  	return (FALSE);
  }
  
***************
*** 934,939 ****
--- 967,973 ----
  	struct timeval tbuf[2];
  	register int x;
  	register char *p;
+ 	char *name = t->Tflags & FRENAME ? t->Tnewname : t->Tname;
  
  	if (t->Tflags&FUPDATE) {
  		if ((t->Tflags&FNOACCT) == 0) {
***************
*** 950,966 ****
  				return (FALSE);
  		}
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would update file %s\n",t->Tname);
  			return (FALSE);
  		}
! 		vnotify ("SUP Updating file %s\n",t->Tname);
  		if ((t->Tflags&FNOACCT) == 0) {
! 			(void) chown (t->Tname,t->Tuid,t->Tgid);
! 			(void) chmod (t->Tname,t->Tmode&S_IMODE);
  		}
  		tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  		tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 		(void) utimes (t->Tname,tbuf);
  		return (FALSE);
  	}
  	if (thisC->Cflags&CFLIST) {
--- 984,1000 ----
  				return (FALSE);
  		}
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would update file %s\n",name);
  			return (FALSE);
  		}
! 		vnotify ("SUP Updating file %s\n",name);
  		if ((t->Tflags&FNOACCT) == 0) {
! 			(void) chown (name,t->Tuid,t->Tgid);
! 			(void) chmod (name,t->Tmode&S_IMODE);
  		}
  		tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  		tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 		(void) utimes (name,tbuf);
  		return (FALSE);
  	}
  	if (thisC->Cflags&CFLIST) {
***************
*** 972,993 ****
  			p = "receive old";
  		else
  			p = "receive";
! 		vnotify ("SUP Would %s file %s\n",p,t->Tname);
  		return (FALSE);
  	}
! 	vnotify ("SUP Receiving file %s\n",t->Tname);
  	if (!new && (t->Tmode&S_IFMT) == S_IFREG &&
  	    (t->Tflags&FBACKUP) && (thisC->Cflags&CFBACKUP)) {
! 		fin = fopen (t->Tname,"r");	/* create backup */
  		if (fin == NULL) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
  				goaway ("Can't skip file transfer");
  			notify ("SUP: Can't open %s to create backup\n",
! 				t->Tname);
  			return (TRUE);		/* mark upgrade as nogood */
  		}
! 		path (t->Tname,dirpart,filepart);
  		(void) sprintf (filename,FILEBACKUP,dirpart,filepart);
  		fout = fopen (filename,"w");
  		if (fout == NULL) {
--- 1006,1027 ----
  			p = "receive old";
  		else
  			p = "receive";
! 		vnotify ("SUP Would %s file %s\n",p,name);
  		return (FALSE);
  	}
! 	vnotify ("SUP Receiving file %s\n",name);
  	if (!new && (t->Tmode&S_IFMT) == S_IFREG &&
  	    (t->Tflags&FBACKUP) && (thisC->Cflags&CFBACKUP)) {
! 		fin = fopen (name,"r");	/* create backup */
  		if (fin == NULL) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
  				goaway ("Can't skip file transfer");
  			notify ("SUP: Can't open %s to create backup\n",
! 				name);
  			return (TRUE);		/* mark upgrade as nogood */
  		}
! 		path (name,dirpart,filepart);
  		(void) sprintf (filename,FILEBACKUP,dirpart,filepart);
  		fout = fopen (filename,"w");
  		if (fout == NULL) {
***************
*** 1006,1025 ****
  		ffilecopy (fin,fout);
  		(void) fclose (fin);
  		(void) fclose (fout);
! 		vnotify ("SUP Backup of %s created\n", t->Tname);
  	}
! 	x = copyfile (t->Tname,(char *)NULL);
  	if (x)
  		return (TRUE);
  	if ((t->Tflags&FNOACCT) == 0) {
  		/* convert user and group names to local ids */
  		ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode);
! 		(void) chown (t->Tname,t->Tuid,t->Tgid);
! 		(void) chmod (t->Tname,t->Tmode&S_IMODE);
  	}
  	tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  	tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 	(void) utimes (t->Tname,tbuf);
  	return (FALSE);
  }
  
--- 1040,1059 ----
  		ffilecopy (fin,fout);
  		(void) fclose (fin);
  		(void) fclose (fout);
! 		vnotify ("SUP Backup of %s created\n", name);
  	}
! 	x = copyfile (name,(char *)NULL);
  	if (x)
  		return (TRUE);
  	if ((t->Tflags&FNOACCT) == 0) {
  		/* convert user and group names to local ids */
  		ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode);
! 		(void) chown (name,t->Tuid,t->Tgid);
! 		(void) chmod (name,t->Tmode&S_IMODE);
  	}
  	tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  	tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 	(void) utimes (name,tbuf);
  	return (FALSE);
  }
  
***************
*** 1067,1075 ****
  	return (SCMOK);
  }
  
! execone (t)			/* execute command for file */
  register TREE *t;
  {
  	union wait w;
  
  	if (thisC->Cflags&CFLIST) {
--- 1101,1112 ----
  	return (SCMOK);
  }
  
! execone (t,name)			/* execute command for file */
  register TREE *t;
+ register char **name;
  {
+ 	struct stat sbuf;
+ 	struct timeval tbuf[2];
  	union wait w;
  
  	if (thisC->Cflags&CFLIST) {
***************
*** 1082,1087 ****
--- 1119,1128 ----
  	}
  	vnotify ("SUP Executing %s\n",t->Tname);
  
+ 	if (lstat(*name,&sbuf)){
+ 		notify ("SUP Unable to stat file %s\n", *name);
+ 		sbuf.st_ino = 0;
+ 	}
  	w.w_status = system (t->Tname);
  	if (WIFEXITED(w) && w.w_retcode != 0) {
  		notify ("SUP: Execute command returned failure status %#o\n",
***************
*** 1096,1101 ****
--- 1137,1150 ----
  			w.w_stopsig);
  		thisC->Cnogood = TRUE;
  	}
+ 	if ((sbuf.st_ino != 0) && (sbuf.st_mode&S_IFMT) != S_IFLNK){
+ 		(void) chown (*name,sbuf.st_uid,sbuf.st_gid);
+ 		(void) chmod (*name,(sbuf.st_mode)&0x1ff);
+ 		tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
+ 		tbuf[1].tv_sec = sbuf.st_mtime;  tbuf[1].tv_usec = 0;
+ 		(void) utimes (*name,tbuf);
+ 	}
+ 
  	return (SCMOK);
  }
  
***************
*** 1108,1113 ****
--- 1157,1163 ----
  	char tname[STRINGLENGTH];
  	char sys_com[STRINGLENGTH];
  	struct stat sbuf;
+ 	int retried = 0;
  
  	static int thispid = 0;		/* process id # */
  
***************
*** 1241,1246 ****
--- 1291,1297 ----
  		return (FALSE);
  	}
  	/* uncompress it first */
+ retry:
  	if (docompress) {
  		/* make sure file permissions don't cause a problem */
  		(void) unlink (to);
***************
*** 1274,1279 ****
--- 1325,1372 ----
  	tof = open (to,(O_WRONLY|O_CREAT|O_TRUNC),0600);
  	if (tof < 0) {
  		(void) close (fromf);
+ 		/* Here we can tell if it is ETXTBSY and try this loop
+ 		   again */
+ 		if( dounlinkbusy && errno == ETXTBSY && !retried ) {
+ 		     /* Try to unlink the destination */
+ 		     if( unlink(to) == 0 ){
+ 			vnotify ("SUP: Removed busy file %s\n", to);
+ 			retried = 1;
+ 			goto retry;
+ 		     }
+ 		     /* 
+ 		      * Some OSs (ie. HP-UX), return ETXTBUSY on unlinking
+ 		      * a busy file.  We try to rename it instead and log
+ 		      * the filename so it can be removed later.
+ 		      */
+ 		      else if( errno == ETXTBSY ) {
+ 			char mname[STRINGLENGTH];
+ 
+ 			sprintf(mname, "%s.sup.#%d.moved", to, thispid);
+ 
+ 			if( rename(to, mname) == 0) {
+ 			   vnotify ("SUP: Moved busy file %s to %s\n", to,
+ 				    mname);
+ 			   if(renamelog == NULL) {
+ 			      renamelog = fopen(thisC->Crenamelog, "a");
+ 			      if( renamelog == NULL ) {
+ 				 notify ("SUP: Cannot open rename log file %s: "
+ 					 "%s\n",thisC->Crenamelog,errmsg (-1));
+ 			      }
+ 			      else {
+ 			   	fprintf(renamelog, "%s\n", mname);
+ 				fflush(renamelog);
+ 			      }
+ 			   }
+ 			   else {
+ 			   	fprintf(renamelog, "%s\n", mname);
+ 				fflush(renamelog);
+ 			   }
+ 			   retried = 1;
+ 			   goto retry;
+ 			}
+ 		      }
+ 		}
  		notify ("SUP: Can't create %s from temp file: %s\n",
  			to,errmsg (-1));
  		(void) unlink (tname);
***************
*** 1399,1405 ****
  FILE **finishfile;
  {
  	if ((thisC->Cflags&CFDELETE) == 0 || (t->Tflags&FUPDATE))
! 		fprintf (*finishfile,"%s\n",t->Tname);
  	return (SCMOK);
  }
  
--- 1492,1501 ----
  FILE **finishfile;
  {
  	if ((thisC->Cflags&CFDELETE) == 0 || (t->Tflags&FUPDATE))
! 		if(t->Tflags&FRENAME)
! 			fprintf(*finishfile,"%s %s\n",t->Tname,t->Tnewname);
! 		else
! 			fprintf (*finishfile,"%s\n",t->Tname);
  	return (SCMOK);
  }
  
diff -c /var/tmp/sup/supcparse.c sup/supcparse.c
*** supcparse.c	Thu Aug 11 06:24:46 1994
--- sup/supcparse.c	Tue Apr 11 15:18:57 1995
***************
*** 82,92 ****
  extern char _argbreak;			/* break character from nxtarg */
  #endif
  
  typedef enum {				/* supfile options */
  	OHOST, OBASE, OHOSTBASE, OPREFIX, ORELEASE,
! 	ONOTIFY, OLOGIN, OPASSWORD, OCRYPT,
  	OBACKUP, ODELETE, OEXECUTE, OOLD, OTIMEOUT, OKEEP, OURELSUF,
! 	OCOMPRESS, ONOUPDATE
  } OPTION;
  
  struct option {
--- 82,94 ----
  extern char _argbreak;			/* break character from nxtarg */
  #endif
  
+ char default_renamelog[] = RENAMELOG;
+ 
  typedef enum {				/* supfile options */
  	OHOST, OBASE, OHOSTBASE, OPREFIX, ORELEASE,
! 	ONOTIFY, OLOGIN, OPASSWORD, OCRYPT, ORENAMELOG,
  	OBACKUP, ODELETE, OEXECUTE, OOLD, OTIMEOUT, OKEEP, OURELSUF,
! 	OCOMPRESS, ONOUPDATE, OUNLINKBUSY
  } OPTION;
  
  struct option {
***************
*** 102,107 ****
--- 104,110 ----
  	"login",	OLOGIN,
  	"password",	OPASSWORD,
  	"crypt",	OCRYPT,
+ 	"renamelog",	ORENAMELOG,
  	"backup",	OBACKUP,
  	"delete",	ODELETE,
  	"execute",	OEXECUTE,
***************
*** 110,116 ****
  	"keep",		OKEEP,
  	"use-rel-suffix", OURELSUF,
   	"compress", 	OCOMPRESS,
! 	"noupdate",	ONOUPDATE
  };
  
  passdelim (ptr,delim)		/* skip over delimiter */
--- 113,120 ----
  	"keep",		OKEEP,
  	"use-rel-suffix", OURELSUF,
   	"compress", 	OCOMPRESS,
! 	"noupdate",	ONOUPDATE,
! 	"unlinkbusy",	OUNLINKBUSY,
  };
  
  passdelim (ptr,delim)		/* skip over delimiter */
***************
*** 143,148 ****
--- 147,153 ----
  	c->Clogin = NULL;
  	c->Cpswd = NULL;
  	c->Ccrypt = NULL;
+ 	c->Crenamelog = default_renamelog;
  	c->Ctimeout = 3*60*60;	/* default to 3 hours instead of no timeout */
  	c->Cflags = 0;
  	c->Cnogood = FALSE;
***************
*** 209,214 ****
--- 214,224 ----
  			arg = nxtarg (&args," \t");
  			c->Ccrypt = salloc (arg);
  			break;
+ 		case ORENAMELOG:
+ 			passdelim (&args,'=');
+ 			arg = nxtarg (&args," \t");
+ 			c->Crenamelog= salloc (arg);
+ 			break;
  		case OBACKUP:
  			c->Cflags |= CFBACKUP;
  			break;
***************
*** 232,237 ****
--- 242,250 ----
  			break;
  		case ONOUPDATE:
  			c->Cflags |= CFNOUPDATE;
+ 			break;
+ 		case OUNLINKBUSY:
+ 			c->Cflags |= CFUNLINKBUSY;
  			break;
  		case OTIMEOUT:
  			passdelim (&args,'=');
diff -c /var/tmp/sup/supfilesrv.c sup/supfilesrv.c
*** supfilesrv.c	Thu Aug 11 06:24:46 1994
--- sup/supfilesrv.c	Sun Aug 13 18:44:09 1995
***************
*** 25,34 ****
  /*
   * supfilesrv -- SUP File Server
   *
!  * Usage:  supfilesrv [-l] [-P] [-N]
   *	-l	"live" -- don't fork daemon
   *	-P	"debug ports" -- use debugging network ports
   *	-N	"debug network" -- print debugging messages for network i/o
   *
   **********************************************************************
   * HISTORY
--- 25,35 ----
  /*
   * supfilesrv -- SUP File Server
   *
!  * Usage:  supfilesrv [-l] [-P] [-N] [-R]
   *	-l	"live" -- don't fork daemon
   *	-P	"debug ports" -- use debugging network ports
   *	-N	"debug network" -- print debugging messages for network i/o
+  *	-R	"RCS mode" -- if file is an rcs file, use co to get contents
   *
   **********************************************************************
   * HISTORY
***************
*** 280,285 ****
--- 281,287 ----
  uid_t getuid ();
  
  int maxchildren;
+ int maxfriends = -1;
  
  /*
   * These are used to save the stat information from the crosspatch crypt
***************
*** 327,344 ****
  int dbgportsq;				/* -P flag */
  extern int scmdebug;			/* -N flag */
  extern int netfile;
  
  char *clienthost;			/* host name of client */
  int nchildren;				/* number of children that exist */
  char *prefix;				/* collection pathname prefix */
  char *release;				/* collection release name */
  char *cryptkey;				/* encryption key if non-null */
  int lockfd;				/* descriptor of lock file */
  
  /* global variables for scan functions */
  int trace = FALSE;			/* directory scan trace */
! int cancompress=FALSE;			/* Can we compress files */
! int docompress=FALSE;			/* Do we compress files */
  
  HASH *uidH[HASHSIZE];			/* for uid and gid lookup */
  HASH *gidH[HASHSIZE];
--- 329,355 ----
  int dbgportsq;				/* -P flag */
  extern int scmdebug;			/* -N flag */
  extern int netfile;
+ #ifdef RCS
+ int candorcs;				/* -R flag */
+ int dorcs = FALSE;
+ #endif
  
  char *clienthost;			/* host name of client */
+ int friend;				/* The client is a friend of us */
  int nchildren;				/* number of children that exist */
  char *prefix;				/* collection pathname prefix */
  char *release;				/* collection release name */
  char *cryptkey;				/* encryption key if non-null */
+ #ifdef CVS
+ char *cvs_root;				/* RCS root */
+ #endif
+ char *rcs_branch;			/* RCS branch name */
  int lockfd;				/* descriptor of lock file */
  
  /* global variables for scan functions */
  int trace = FALSE;			/* directory scan trace */
! int cancompress = FALSE;		/* Can we compress files */
! int docompress = FALSE;			/* Do we compress files */
  
  HASH *uidH[HASHSIZE];			/* for uid and gid lookup */
  HASH *gidH[HASHSIZE];
***************
*** 350,356 ****
   * PROTOTYPES
   */
  #if __STDC__
! void	goaway	__P((char *,...));
  #endif
  
  #ifdef LOG_PID_PATHNAME
--- 361,367 ----
   * PROTOTYPES
   */
  #if __STDC__
! void  goaway  __P((char *,...));
  #endif
  
  #ifdef LOG_PID_PATHNAME
***************
*** 442,454 ****
  /*
   * Child status signal handler
   */
- 
  void
  chldsig()
  {
  	int w;
  
  	while (wait3(&w, WNOHANG, (struct rusage *)0) > 0) {
  		if (nchildren) nchildren--;
  	}
  }
--- 453,472 ----
  /*
   * Child status signal handler
   */
  void
  chldsig()
  {
+ #if defined(__hpux) || defined(__FreeBSD__)
  	int w;
+ #else
+ 	union wait w;
+ #endif
  
+ #ifdef __hpux
+ 	while (wait3(&w, WNOHANG, (int *)0) > 0) {
+ #else
  	while (wait3(&w, WNOHANG, (struct rusage *)0) > 0) {
+ #endif
  		if (nchildren) nchildren--;
  	}
  }
***************
*** 474,479 ****
--- 492,500 ----
  	int maxsleep;
  	register FILE *f;
  
+ #ifdef RCS
+         candorcs = FALSE;
+ #endif
  	live = FALSE;
  	dbgportsq = FALSE;
  	scmdebug = 0;
***************
*** 500,505 ****
--- 521,532 ----
  			argv++;
  			maxchildren = atoi(argv[0]);
  			break;
+ 		case 'F':
+ 			if (--argc < 1)
+ 				quit (1,"Missing arg to -F\n");
+ 			argv++;
+ 			maxfriends = atoi(argv[0]);
+ 			break;
  		case 'H':
  			if (--argc < 3)
  				quit (1,"Missing args to -H\n");
***************
*** 510,515 ****
--- 537,547 ----
  			argc -= 2;
  			argv += 2;
  			break;
+ #ifdef RCS
+                 case 'R':
+                         candorcs = TRUE;
+                         break;
+ #endif
  		default:
  			fprintf (stderr,"Unknown flag %s ignored\n",argv[0]);
  			break;
***************
*** 517,522 ****
--- 549,559 ----
  		--argc;
  		argv++;
  	}
+ 	if (maxfriends == -1)
+ 		maxfriends = 2*maxchildren;
+ 	else
+ 		maxfriends += maxchildren; /* due to the way we check */
+ 
  	if (clienthost == NULL) {
  		if (argc != 0)
  			usage ();
***************
*** 621,626 ****
--- 658,667 ----
  	basedir = NULL;
  	prefix = NULL;
  	release = NULL;
+         rcs_branch = NULL;
+ #ifdef CVS
+         cvs_root = NULL;
+ #endif
  	goawayreason = NULL;
  	donereason = NULL;
  	lockfd = -1;
***************
*** 642,648 ****
--- 683,693 ----
  			(void) dup2 (netfile,0);
  			(void) dup2 (netfile,1);
  			(void) dup2 (netfile,2);
+ #ifdef __hpux
+ 			fd = 256;
+ #else
  			fd = getdtablesize ();
+ #endif
  			while (--fd > 2)
  				(void) close (fd);
  			execv (xargv[0],xargv);
***************
*** 656,661 ****
--- 701,710 ----
  	if (basedir)  free (basedir);
  	if (prefix)  free (prefix);
  	if (release)  free (release);
+ 	if (rcs_branch)  free (rcs_branch);
+ #ifdef CVS
+ 	if (cvs_root)  free (cvs_root);
+ #endif
  	if (goawayreason) {
  		if (donereason == goawayreason)
  			donereason = NULL;
***************
*** 778,783 ****
--- 827,841 ----
  			goaway ("Error sending setup reply to client");
  		return;
  	}
+ #ifdef RCS
+         if (candorcs && release != NULL &&
+             (strncmp(release, "RCS.", 4) == 0)) {
+                 rcs_branch = salloc(&release[4]);
+                 free(release);
+                 release = salloc("RCS");
+                 dorcs = TRUE;
+         }
+ #endif
  	if (release == NULL)
  		release = salloc (DEFRELEASE);
  	if (basedir == NULL || *basedir == '\0') {
***************
*** 824,830 ****
  	if (prefix)  (void) chdir (basedir);
  	if (x < 0)
  		goaway ("Can't stat base/prefix directory");
! 	if (nchildren >= maxchildren) {
  		setupack = FSETUPBUSY;
  		(void) msgsetupack ();
  		if (protver >= 6)  longjmp (sjbuf,TRUE);
--- 882,888 ----
  	if (prefix)  (void) chdir (basedir);
  	if (x < 0)
  		goaway ("Can't stat base/prefix directory");
! 	if (nchildren >=  maxfriends) {
  		setupack = FSETUPBUSY;
  		(void) msgsetupack ();
  		if (protver >= 6)  longjmp (sjbuf,TRUE);
***************
*** 861,867 ****
  				q = nxtarg (&p," \t");
  				if ((not = (*q == '!')) && *++q == '\0')
  					q = nxtarg (&p," \t");
! 				hostok = (not == (matchhost(q) == 0));
  				if (hostok) {
  					while ((*p == ' ') || (*p == '\t')) p++;
  					if (*p)  cryptkey = salloc (p);
--- 919,934 ----
  				q = nxtarg (&p," \t");
  				if ((not = (*q == '!')) && *++q == '\0')
  					q = nxtarg (&p," \t");
! 				if ((friend = (*q == '+')) && *++q == '\0')
! 					q = nxtarg (&p," \t");
! 				hostok = matchhost(q);
! 				if (hostok && not) {
! 					setupack = FSETUPHOST;
! 					(void) msgsetupack ();
! 					if (protver >= 6)  longjmp (sjbuf,TRUE);
! 					goaway ("Host blacklisted for %s",
! 						collname);
! 				}
  				if (hostok) {
  					while ((*p == ' ') || (*p == '\t')) p++;
  					if (*p)  cryptkey = salloc (p);
***************
*** 878,883 ****
--- 945,956 ----
  			}
  		}
  	}
+ 	if (!friend && nchildren >= maxchildren) {
+ 		setupack = FSETUPBUSY;
+ 		(void) msgsetupack ();
+ 		if (protver >= 6)  longjmp (sjbuf,TRUE);
+ 		goaway ("Sup client told to try again later");
+ 	}
  	/* try to lock collection */
  	(void) sprintf (buf,FILELOCK,collname);
  	x = open (buf,O_RDONLY,0);
***************
*** 1111,1116 ****
--- 1184,1200 ----
  	/* send all files */
  	for (tl = listTL; tl != NULL; tl = tl->TLnext) {
  		cdprefix (tl->TLprefix);
+ #ifdef CVS
+                 if (candorcs) {
+                         cvs_root = getcwd(NULL, 256);
+                         if (access("CVSROOT", F_OK) < 0)
+                                 dorcs = FALSE;
+                         else {
+                                 loginfo("is a CVSROOT \"%s\"\n", cvs_root);
+                                 dorcs = TRUE;
+                         }
+                 }
+ #endif
  		(void) Tprocess (tl->TLtree,sendone);
  	}
  	/* send directories in reverse order */
***************
*** 1132,1138 ****
  {
  	register int x,fd;
  	register int fdtmp;
! 	char sys_com[STRINGLENGTH], temp_file[STRINGLENGTH];
  	char *uconvert(),*gconvert();
  	int sendfile ();
  
--- 1216,1223 ----
  {
  	register int x,fd;
  	register int fdtmp;
! 	char sys_com[STRINGLENGTH], temp_file[STRINGLENGTH], rcs_file[STRINGLENGTH];
!         union wait status;
  	char *uconvert(),*gconvert();
  	int sendfile ();
  
***************
*** 1146,1165 ****
  	fd = -1;			/* no open file */
  	if ((t->Tmode&S_IFMT) == S_IFREG) {
  		if (!listonly && (t->Tflags&FUPDATE) == 0) {
! 			if (docompress) {
! 				tmpnam(temp_file);
! 				sprintf(sys_com, "gzip -c < %s > %s\n", t->Tname, temp_file);
! 				if (system(sys_com) < 0) {
! 					/* Just in case */
! 					unlink(temp_file);
! 					goaway ("We died trying to compress");
! 					t->Tmode = 0;
! 				}
! 				fd = open (temp_file,O_RDONLY,0);
! 			}
! 			else
! 				fd = open (t->Tname,O_RDONLY,0);
! 			if (fd < 0)  t->Tmode = 0;
  		}
  		if (t->Tmode) {
  			t->Tuser = salloc (uconvert (t->Tuid));
--- 1231,1304 ----
  	fd = -1;			/* no open file */
  	if ((t->Tmode&S_IFMT) == S_IFREG) {
  		if (!listonly && (t->Tflags&FUPDATE) == 0) {
! #ifdef RCS
!                         if (dorcs) {
!                                 char rcs_release[STRINGLENGTH];
! 
! 				tmpnam(rcs_file);
!                                 if (strcmp(&t->Tname[strlen(t->Tname)-2], ",v") == 0) {
!                                         t->Tname[strlen(t->Tname)-2] = '\0';
!                                         if (rcs_branch != NULL)
! #ifdef CVS
!                                                 sprintf(rcs_release, "-r %s", rcs_branch);
! #else
!                                                 sprintf(rcs_release, "-r%s", rcs_branch);
! #endif
!                                         else
!                                                 rcs_release[0] = '\0';
! #ifdef CVS
!                                         sprintf(sys_com, "cvs -d %s -r -l -Q co -p %s %s > %s\n", cvs_root, rcs_release, t->Tname, rcs_file);
! #else
!                                         sprintf(sys_com, "co -q -p %s %s > %s 2> /dev/null\n", rcs_release, t->Tname, rcs_file);
! #endif
!                                         /*loginfo("using rcs mode \"%s\"\n", sys_com);*/
!                                         status.w_status = system(sys_com);
!                                         if (status.w_status < 0 || status.w_retcode) {
!                                                 /* Just in case */
!                                                 unlink(rcs_file);
!                                                 if (status.w_status < 0) {
!                                                         goaway ("We died trying to \"%s\"", sys_com);
!                                                         t->Tmode = 0;
!                                                 }
!                                                 else {
!                                                         /*logerr("rcs command failed \"%s\" = %d\n",
!                                                                sys_com, status.w_retcode);*/
!                                                         t->Tflags |= FUPDATE;
!                                                 }
!                                         }
!                                         else if (docompress) {
!                                                 tmpnam(temp_file);
!                                                 sprintf(sys_com, "/usr/local/bin/gzip -c < %s > %s\n", rcs_file, temp_file);
!                                                 if (system(sys_com) < 0) {
!                                                         /* Just in case */
!                                                         unlink(temp_file);
!                                                         unlink(rcs_file);
!                                                         goaway ("We died trying to \"%s\"", sys_com);
!                                                         t->Tmode = 0;
!                                                 }
!                                                 fd = open (temp_file,O_RDONLY,0);
!                                         }
!                                         else
!                                                 fd = open (rcs_file,O_RDONLY,0);
!                                 }
!                         }
! #endif
!                         if (fd == -1) {
!                                 if (docompress) {
!                                         tmpnam(temp_file);
!                                         sprintf(sys_com, "gzip -c < %s > %s\n", t->Tname, temp_file);
!                                         if (system(sys_com) != 0) {
!                                                 /* Just in case */
!                                                 unlink(temp_file);
!                                                 goaway ("We died trying to \"%s\"", sys_com);
!                                                 t->Tmode = 0;
!                                         }
!                                         fd = open (temp_file,O_RDONLY,0);
!                                 }
!                                 else
!                                         fd = open (t->Tname,O_RDONLY,0);
!                         }
! 			if (fd < 0 && (t->Tflags&FUPDATE) == 0)  t->Tmode = 0;
  		}
  		if (t->Tmode) {
  			t->Tuser = salloc (uconvert (t->Tuid));
***************
*** 1169,1174 ****
--- 1308,1317 ----
  	x = msgrecv (sendfile,fd);
  	if (docompress)
  		unlink(temp_file);
+ #ifdef RCS
+ 	if (dorcs)
+ 		unlink(rcs_file);
+ #endif
  	if (x != SCMOK)  goaway ("Error sending file to client");
  	return (SCMOK);
  }
diff -c /var/tmp/sup/supmsg.c sup/supmsg.c
*** supmsg.c	Fri Aug 20 17:46:35 1993
--- sup/supmsg.c	Thu Apr  6 15:17:07 1995
***************
*** 299,304 ****
--- 299,305 ----
   * list files message
   */
  extern TREE	*listT;			/* tree of files to list */
+ extern TREE     *renameT;               /* tree of rename target files */
  extern long	scantime;		/* time that collection was scanned */
  
  static int listone (t)
***************
*** 307,312 ****
--- 308,315 ----
  	register int x;
  
  	x = writestring (t->Tname);
+ 	if ( protver > 8 )
+ 		if (x == SCMOK)  x = writestring (t->Tnewname);
  	if (x == SCMOK)  x = writeint ((int)t->Tmode);
  	if (x == SCMOK)  x = writeint ((int)t->Tflags);
  	if (x == SCMOK)  x = writeint (t->Tmtime);
***************
*** 323,341 ****
  		if (x == SCMOK)  x = writeint ((int)scantime);
  		if (x == SCMOK)  x = writemend ();
  	} else {
! 		char *name;
  		int mode,flags,mtime;
  		register TREE *t;
  		x = readmsg (MSGLIST);
  		if (x == SCMOK)  x = readstring (&name);
  		while (x == SCMOK) {
  			if (name == NULL)  break;
! 			x = readint (&mode);
  			if (x == SCMOK)  x = readint (&flags);
  			if (x == SCMOK)  x = readint (&mtime);
  			if (x != SCMOK)  break;
  			t = Tinsert (&listT,name,TRUE);
  			free (name);
  			t->Tmode = mode;
  			t->Tflags = flags;
  			t->Tmtime = mtime;
--- 326,350 ----
  		if (x == SCMOK)  x = writeint ((int)scantime);
  		if (x == SCMOK)  x = writemend ();
  	} else {
! 		char *name, *newname = NULL;
  		int mode,flags,mtime;
  		register TREE *t;
  		x = readmsg (MSGLIST);
  		if (x == SCMOK)  x = readstring (&name);
  		while (x == SCMOK) {
  			if (name == NULL)  break;
! 			if (protver > 8){
! 				x = readstring (&newname);
! 				if (x == SCMOK)  x = readint (&mode);
! 			}
! 			else
! 				x = readint (&mode);
  			if (x == SCMOK)  x = readint (&flags);
  			if (x == SCMOK)  x = readint (&mtime);
  			if (x != SCMOK)  break;
  			t = Tinsert (&listT,name,TRUE);
  			free (name);
+ 			t->Tnewname = newname;
  			t->Tmode = mode;
  			t->Tflags = flags;
  			t->Tmtime = mtime;
***************
*** 474,479 ****
--- 483,490 ----
  			return (x);
  		}
  		if (x == SCMOK)  x = writestring (t->Tname);
+ 		if (protver > 8)
+ 			if (x == SCMOK)  x = writestring (t->Tnewname);
  		if (x == SCMOK)  x = writeint (t->Tmode);
  		if (t->Tmode == 0) {
  			if (x == SCMOK)  x = writemend ();
***************
*** 499,504 ****
--- 510,517 ----
  			if (x == SCMOK)  x = (*xferfile) (NULL,args);
  			return (x);
  		}
+ 		if (protver > 8)
+ 			if (x == SCMOK)  x = readstring (&t->Tnewname);
  		if (x == SCMOK)  x = readint (&t->Tmode);
  		if (t->Tmode == 0) {
  			x = readmend ();
diff -c /var/tmp/sup/supmsg.h sup/supmsg.h
*** supmsg.h	Fri Aug 20 17:46:35 1993
--- sup/supmsg.h	Thu Apr  6 15:18:04 1995
***************
*** 170,175 ****
--- 170,176 ----
  
  /* msglist */
  EXTERN	TREE	*listT;			/* tree of files to list */
+ EXTERN	TREE	*renameT;		/* tree of file rename targets */
  EXTERN	long	scantime;		/* time that collection was scanned */
  
  /* msgneed */
diff -c /var/tmp/sup/vprintf.c sup/vprintf.c
*** vprintf.c	Fri Aug 20 17:46:35 1993
--- sup/vprintf.c	Thu Apr  6 15:26:03 1995
***************
*** 118,126 ****
--- 118,133 ----
  {
  	FILE fakebuf;
  
+ #ifdef __hpux
+ 	fakebuf._flag = _IODUMMY+_IOWRT;/* no _IOWRT: avoid stdio bug */
+ 	fakebuf._base = fakebuf._ptr = s;
+ 	fakebuf._cnt = n-1;
+ 	fakebuf.__fileL = fakebuf.__fileH = 0xff;
+ #else
  	fakebuf._flag = _IOSTRG+_IOWRT;	/* no _IOWRT: avoid stdio bug */
  	fakebuf._ptr = s;
  	fakebuf._cnt = n-1;
+ #endif
  	_doprnt(fmt, args, &fakebuf);
  	fakebuf._cnt++;
  	putc('\0', &fakebuf);
*** /dev/null	Sun Aug 13 11:14:38 1995
--- daemon.c	Sun Aug 13 19:59:10 1995
***************
*** 0 ****
--- 1,68 ----
+ /*-
+  * Copyright (c) 1990 The Regents of the University of California.
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  * 3. All advertising materials mentioning features or use of this software
+  *    must display the following acknowledgement:
+  *	This product includes software developed by the University of
+  *	California, Berkeley and its contributors.
+  * 4. Neither the name of the University nor the names of its contributors
+  *    may be used to endorse or promote products derived from this software
+  *    without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  *	from: "@(#)daemon.c	5.3 (Berkeley) 12/28/90
+  *	$Id: patch-aa,v 1.3 1998/09/23 05:13:55 imp Exp $
+  */
+ 
+ #if defined(LIBC_SCCS) && !defined(lint)
+ static char sccsid[] = "@(#)daemon.c	5.3 (Berkeley) 12/28/90";
+ #endif /* LIBC_SCCS and not lint */
+ 
+ #include <sys/fcntl.h>
+ #include <unistd.h>
+ 
+ daemon(nochdir, noclose)
+ 	int nochdir, noclose;
+ {
+ 	int cpid;
+ 
+ 	if ((cpid = fork()) == -1)
+ 		return (-1);
+ 	if (cpid)
+ 		exit(0);
+ 	(void) setsid();
+ 	if (!nochdir)
+ 		(void) chdir("/");
+ 	if (!noclose) {
+ 		int devnull = open("/dev/null", O_RDWR, 0);
+ 
+ 		if (devnull != -1) {
+ 			(void) dup2(devnull, STDIN_FILENO);
+ 			(void) dup2(devnull, STDOUT_FILENO);
+ 			(void) dup2(devnull, STDERR_FILENO);
+ 			if (devnull > 2)
+ 				(void) close(devnull);
+ 		}
+ 	}
+ 	return 0;
+ }
*** /dev/null	Sun Aug 13 11:14:38 1995
--- flock.c	Sun Aug 13 19:58:50 1995
***************
*** 0 ****
--- 1,112 ----
+ /*
+  * Copyright (c) 1991 Carnegie Mellon University
+  * All Rights Reserved.
+  * 
+  * Permission to use, copy, modify and distribute this software and its
+  * documentation is hereby granted, provided that both the copyright
+  * notice and this permission notice appear in all copies of the
+  * software, derivative works or modified versions, and any portions
+  * thereof, and that both notices appear in supporting documentation.
+  *
+  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+  *
+  * Carnegie Mellon requests users of this software to return to
+  *
+  *  Software Distribution Coordinator   or   Software.Distribution@CS.CMU.EDU
+  *  School of Computer Science
+  *  Carnegie Mellon University
+  *  Pittsburgh PA 15213-3890
+  *
+  * any improvements or extensions that they make and grant Carnegie the rights
+  * to redistribute these changes.
+  */
+ /*
+  * flock (fd, operation)
+  *
+  * This routine performs some file locking like the BSD 'flock'
+  * on the object described by the int file descriptor 'fd',
+  * which must already be open.
+  *
+  * The operations that are available are:
+  *
+  * LOCK_SH  -  get a shared lock.
+  * LOCK_EX  -  get an exclusive lock.
+  * LOCK_NB  -  don't block (must be ORed with LOCK_SH or LOCK_EX).
+  * LOCK_UN  -  release a lock.
+  *
+  * Return value: 0 if lock successful, -1 if failed.
+  *
+  * Note that whether the locks are enforced or advisory is
+  * controlled by the presence or absence of the SETGID bit on
+  * the executable.
+  *
+  * Note that there is no difference between shared and exclusive
+  * locks, since the 'lockf' system call in SYSV doesn't make any
+  * distinction.
+  *
+  * The file "<sys/file.h>" should be modified to contain the definitions
+  * of the available operations, which must be added manually (see below
+  * for the values).
+  */
+ 
+ #include <unistd.h>
+ #include <sys/file.h>
+ #include <errno.h>
+ 
+ #ifndef LOCK_SH
+ #define LOCK_SH 1
+ #endif
+ #ifndef LOCK_EX
+ #define LOCK_EX 2
+ #endif
+ #ifndef LOCK_NB
+ #define LOCK_NB 4
+ #endif
+ #ifndef LOCK_UN
+ #define LOCK_UN 8
+ #endif
+ 
+ /*extern int errno;*/
+ 
+ int
+ flock (fd, operation)
+      int fd, operation;
+ {
+ 	int i;
+ 
+ 	switch (operation) {
+ 
+ 	/* LOCK_SH - get a shared lock */
+ 	case LOCK_SH:
+ 	/* LOCK_EX - get an exclusive lock */
+ 	case LOCK_EX:
+ 		i = lockf (fd, F_LOCK, 0);
+ 		break;
+ 
+ 	/* LOCK_SH|LOCK_NB - get a non-blocking shared lock */
+ 	case LOCK_SH|LOCK_NB:
+ 	/* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */
+ 	case LOCK_EX|LOCK_NB:
+ 		i = lockf (fd, F_TLOCK, 0);
+ 		if (i == -1)
+ 			if ((errno == EAGAIN) || (errno == EACCES))
+ 				errno = EWOULDBLOCK;
+ 		break;
+ 
+ 	/* LOCK_UN - unlock */
+ 	case LOCK_UN:
+ 		i = lockf (fd, F_ULOCK, 0);
+ 		break;
+ 
+ 	/* Default - can't decipher operation */
+ 	default:
+ 		i = -1;
+ 		errno = EINVAL;
+ 		break;
+ 	}
+ 
+ 	return (i);
+ }
+ 
*** /dev/null	Sun Aug 13 11:14:38 1995
--- utimes.c	Sun Aug 13 19:58:43 1995
***************
*** 0 ****
--- 1,43 ----
+ /*
+  * Copyright (c) 1991 Carnegie Mellon University
+  * All Rights Reserved.
+  * 
+  * Permission to use, copy, modify and distribute this software and its
+  * documentation is hereby granted, provided that both the copyright
+  * notice and this permission notice appear in all copies of the
+  * software, derivative works or modified versions, and any portions
+  * thereof, and that both notices appear in supporting documentation.
+  *
+  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+  *
+  * Carnegie Mellon requests users of this software to return to
+  *
+  *  Software Distribution Coordinator   or   Software.Distribution@CS.CMU.EDU
+  *  School of Computer Science
+  *  Carnegie Mellon University
+  *  Pittsburgh PA 15213-3890
+  *
+  * any improvements or extensions that they make and grant Carnegie the rights
+  * to redistribute these changes.
+  */
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <utime.h>
+ 
+ int utimes(file,tvp) char *file; struct timeval *tvp;
+ {
+         struct utimbuf ut;
+         time_t now;
+ 
+         now = time((time_t *)NULL);
+         if (tvp == (struct timeval *)NULL) {
+                 ut.actime = now;
+                 ut.modtime = now;
+         } else {
+                 ut.actime = tvp++->tv_sec;
+                 ut.modtime = tvp->tv_sec;
+         }
+         return(utime(file,&ut));
+ }
*** /dev/null	Sun Aug 13 11:14:38 1995
--- Makefile.HP	Sun Aug 13 19:59:02 1995
***************
*** 0 ****
--- 1,127 ----
+ # Copyright (c) 1992,1991 Carnegie Mellon University
+ # All Rights Reserved.
+ # 
+ # Permission to use, copy, modify and distribute this software and its
+ # documentation is hereby granted, provided that both the copyright
+ # notice and this permission notice appear in all copies of the
+ # software, derivative works or modified versions, and any portions
+ # thereof, and that both notices appear in supporting documentation.
+ #
+ # CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ # CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ # ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ #
+ # Carnegie Mellon requests users of this software to return to
+ #
+ #  Software Distribution Coordinator   or   Software.Distribution@CS.CMU.EDU
+ #  School of Computer Science
+ #  Carnegie Mellon University
+ #  Pittsburgh PA 15213-3890
+ #
+ # any improvements or extensions that they make and grant Carnegie the rights
+ # to redistribute these changes.
+ ######################################################################
+ # Makefile to build sup (the client side), supfilesrv (the repository
+ # side, and supscan (used by the repository. If you only want to sup
+ # files from CMU, just build sup.
+ # The header files: c.h, libc.h and sysent.h are only
+ # necessary if you are compiling on a non-Mach system. Likewise the
+ # files in libextra.a are normally found in libcs.a on a Mach system.
+ # DOPRINT_VA is used by vprintf.c and should be defined if your version
+ # of libc/doprnt.c defines the routine _doprnt_va. If it defines _doprnt
+ # instead, leave DORPINT_VA undefined.
+ ######################################################################
+ #
+ # If you need to build a sup for export outside of North America use
+ # 	"make EXPORTABLE_SYSTEM=true"
+ # this will remove (not use) any vestiges of crypt code that is present
+ # on the system.
+ #
+ # If you have crypt/crypt.c and /usr/lib/libcrypt.a, you will be building
+ # a system that uses the SUP crypt mechanism by default.
+ #
+ SITE			= NETBSD
+ #SITE			= CMUCS
+ RENAMELOG		= \"/usr/local/etc/sup.moved\"
+ NETBSD_DEFINES		= -UMACH -DHAS_DAEMON -DNEED_VSNPRINTF
+ AFS_DEFINES		= -DAFS -I/usr/afsws/include
+ OSF_DEFINES		= -UMACH -DOSF -D_BSD -noshrlib -g -DNEED_VSNPRINTF -DVAR_TMP
+ CMUCS_DEFINES		= -DMACH -DDOPRINT_VA -DNEED_VPRINTF
+ NON_MACH_DEFINES	= -UMACH
+ #DEFS			= -UCMUCS -UCMU  ${${SITE}_DEFINES}
+ DEFS			= -UCMUCS -UCMU  ${NETBSD_DEFINES} -DRENAMELOG=${RENAMELOG} -D_BSD
+ 
+ #INSTALLATION PARAMETERS
+ NETBSD_BINDIR		= /usr/local/etc
+ NETBSD_MAN1		= /usr/local/man/man1
+ NETBSD_MAN8		= /usr/local/man/man8
+ EXPORTABLE_SYSTEM	= true
+ CC			= gcc
+ CFLAGS			= ${DEFS} -I. 
+ 
+ SUPCL			= supcmain.o supcvers.o supcparse.o supcname.o \
+ 			  supcmisc.o supcmeat.o
+ SUPS			= scm.o scmio.o stree.o log.o supmsg.o netcrypt.o
+ EXTRA			= atoo.o errmsg.o expand.o ffilecopy.o filecopy.o \
+ 			  nxtarg.o path.o quit.o run.o salloc.o skipto.o  \
+ 			  vprintf.o flock.o utimes.o
+ 
+ PROGRAMS		= sup supscan supfilesrv
+ MAN1			= sup.1
+ MAN8			= supservers.8
+ 
+ AFS_LIBPATH		= /usr/afs/lib
+ AFS_LIBS		= -L${AFS_LIBPATH}/afs -lkauth -lprot -L${AFS_LIBPATH} -lubik -lauth -lrxkad -lsys -ldes -lrx -llwp -lcmd -lcom_err -lc ${AFS_LIBPATH}/afs/util.a
+ 
+ USE_CRYPT		= no
+ 
+ LIBS			= libextra.a
+ sup_OFILES		= ${SUPCL} ${SUPS}
+ supfilesrv_OFILES	= supfilesrv.o scan.o daemon.o ${SUPS}
+ supfilesrv_LIBS		= libextra.a 
+ supscan_OFILES		= supscan.o stree.o scan.o
+ 
+ 
+ all: ${PROGRAMS}
+ 
+ sup: ${sup_OFILES} ${LIBS}
+ 	${CC} ${CFLAGS} -o sup ${sup_OFILES} ${LIBS} ${NETBSD_LIBS} -lBSD
+ 
+ supfilesrv: ${supfilesrv_OFILES} ${supfilesrv_LIBS}
+ 	${CC} ${CFLAGS} -o supfilesrv ${supfilesrv_OFILES} ${supfilesrv_LIBS} ${NETBSD_LIBS} -lBSD
+ 
+ supscan:  ${supscan_OFILES} ${LIBS}
+ 	${CC} ${CFLAGS} -o supscan ${supscan_OFILES} ${LIBS} ${NETBSD_LIBS} -lBSD
+ 
+ libextra.a: ${EXTRA}
+ 	ar r libextra.a $?
+ 	ranlib libextra.a
+ 
+ clean cleandir:
+ 	rm -f ${PROGRAMS} libextra.a netcrypt.c *.o core a.out
+ 
+ install: ${PROGRAMS}
+ 	install -m 500 -u bin -g bin -f ${NETBSD_BINDIR} supscan 
+ 	install -m 500 -u bin -g bin -f ${NETBSD_BINDIR} sup 
+ 	install -m 500 -u bin -g bin -f ${NETBSD_BINDIR} supfilesrv
+ 	install -m 444 -u bin -g bin -f ${NETBSD_MAN1} ${MAN1} 
+ 	install -m 444 -u bin -g bin -f ${NETBSD_MAN8} ${MAN8} 
+ 
+ #netcrypt.c: crypt.diffs
+ netcrypt.c:	netcryptvoid.c
+ 	cp netcryptvoid.c netcrypt.c
+ 
+ scan.o:	sup.h
+ scm.o:	sup.h
+ scmio.o: sup.h supmsg.h
+ stree.o: sup.h
+ supcmain.o: sup.h supmsg.h supcdefs.h
+ supcmeat.o: sup.h supmsg.h supcdefs.h
+ supcmisc.o: sup.h supmsg.h supcdefs.h
+ supcname.o: sup.h supmsg.h supcdefs.h
+ supcparse.o: sup.h supmsg.h supcdefs.h
+ supfilesrv.o: sup.h supmsg.h
+ supmsg.o: sup.h supmsg.h
+ supscan.o: sup.h
+ netcryptvoid.o: sup.h supmsg.h
+ netcrypt.o: sup.h supmsg.h
