summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-12-16 11:47:08 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-12-16 11:47:08 +0000
commit8c538e676fee82f4be45abefea6360bb9ee417b3 (patch)
tree5586f089a9bba22b362414c8e772bc09e63450d0 /usr.bin
parentc06c806f45c8bf1ce55fb3e5ea1bf864cb85d146 (diff)
add sup to the tree
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/Makefile4
-rw-r--r--usr.bin/sup/Makefile5
-rw-r--r--usr.bin/sup/Makefile.inc2
-rw-r--r--usr.bin/sup/src/Makefile.save136
-rw-r--r--usr.bin/sup/src/atoo.c54
-rw-r--r--usr.bin/sup/src/c.h79
-rw-r--r--usr.bin/sup/src/ci.c847
-rw-r--r--usr.bin/sup/src/crypt.diffs87
-rw-r--r--usr.bin/sup/src/crypt.info15
-rw-r--r--usr.bin/sup/src/cvt.c56
-rw-r--r--usr.bin/sup/src/errmsg.c63
-rw-r--r--usr.bin/sup/src/expand.c376
-rw-r--r--usr.bin/sup/src/ffilecopy.c85
-rw-r--r--usr.bin/sup/src/filecopy.c65
-rw-r--r--usr.bin/sup/src/libc.h294
-rw-r--r--usr.bin/sup/src/log.c169
-rw-r--r--usr.bin/sup/src/netcryptvoid.c95
-rw-r--r--usr.bin/sup/src/nxtarg.c77
-rw-r--r--usr.bin/sup/src/path.c96
-rw-r--r--usr.bin/sup/src/quit.c67
-rw-r--r--usr.bin/sup/src/run.c252
-rw-r--r--usr.bin/sup/src/salloc.c48
-rw-r--r--usr.bin/sup/src/scan.c1024
-rw-r--r--usr.bin/sup/src/scm.c593
-rw-r--r--usr.bin/sup/src/scmio.c744
-rw-r--r--usr.bin/sup/src/skipto.c78
-rw-r--r--usr.bin/sup/src/stree.c357
-rw-r--r--usr.bin/sup/src/sup.1862
-rw-r--r--usr.bin/sup/src/sup.h268
-rw-r--r--usr.bin/sup/src/supcdefs.h133
-rw-r--r--usr.bin/sup/src/supcmain.c723
-rw-r--r--usr.bin/sup/src/supcmeat.c1468
-rw-r--r--usr.bin/sup/src/supcmisc.c339
-rw-r--r--usr.bin/sup/src/supcname.c118
-rw-r--r--usr.bin/sup/src/supcparse.c281
-rw-r--r--usr.bin/sup/src/supcvers.c80
-rw-r--r--usr.bin/sup/src/supfilesrv.c1870
-rw-r--r--usr.bin/sup/src/supmsg.c625
-rw-r--r--usr.bin/sup/src/supmsg.h194
-rw-r--r--usr.bin/sup/src/supscan.c428
-rw-r--r--usr.bin/sup/src/supservers.8241
-rw-r--r--usr.bin/sup/src/sysent.h150
-rw-r--r--usr.bin/sup/src/time.h94
-rw-r--r--usr.bin/sup/src/vprintf.c131
-rw-r--r--usr.bin/sup/sup/Makefile19
-rw-r--r--usr.bin/sup/supfilesrv/Makefile18
-rw-r--r--usr.bin/sup/supscan/Makefile18
47 files changed, 13826 insertions, 2 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile
index 79e1e996f58..055304a7212 100644
--- a/usr.bin/Makefile
+++ b/usr.bin/Makefile
@@ -1,5 +1,5 @@
# from: @(#)Makefile 5.8.1.1 (Berkeley) 5/8/91
-# $Id: Makefile,v 1.2 1995/11/06 21:42:19 deraadt Exp $
+# $Id: Makefile,v 1.3 1995/12/16 11:46:37 deraadt Exp $
SUBDIR= apply apropos asa at banner basename bdes biff cal calendar cap_mkdb \
checknr chflags chpass cksum cmp col colcrt colrm column comm \
@@ -13,7 +13,7 @@ SUBDIR= apply apropos asa at banner basename bdes biff cal calendar cap_mkdb \
rdist renice rev rlogin rpcgen rpcinfo rs \
rsh rup ruptime rusers rwall rwho \
script sed shar showmount skey skeyinit soelim split strings \
- su systat tail talk tcopy tee telnet tftp time \
+ su sup systat tail talk tcopy tee telnet tftp time \
tip tn3270 touch tput tr true tset tsort tty ul uname unexpand \
unifdef uniq units unvis users uudecode uuencode \
vacation vgrind vi vis vmstat w wall wc what whatis whereis \
diff --git a/usr.bin/sup/Makefile b/usr.bin/sup/Makefile
new file mode 100644
index 00000000000..b6045b6b869
--- /dev/null
+++ b/usr.bin/sup/Makefile
@@ -0,0 +1,5 @@
+# $Id: Makefile,v 1.1 1995/12/16 11:46:39 deraadt Exp $
+
+SUBDIR= sup supscan supfilesrv
+
+.include <bsd.subdir.mk>
diff --git a/usr.bin/sup/Makefile.inc b/usr.bin/sup/Makefile.inc
new file mode 100644
index 00000000000..b8c97c5eed8
--- /dev/null
+++ b/usr.bin/sup/Makefile.inc
@@ -0,0 +1,2 @@
+
+CFLAGS+=-UCMUCS -UCMU -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR
diff --git a/usr.bin/sup/src/Makefile.save b/usr.bin/sup/src/Makefile.save
new file mode 100644
index 00000000000..0aad1c0f1bf
--- /dev/null
+++ b/usr.bin/sup/src/Makefile.save
@@ -0,0 +1,136 @@
+# 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
+NETBSD_DEFINES = -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR
+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/sbin
+NETBSD_MAN1 = /usr/local/man/man1
+NETBSD_MAN8 = /usr/local/man/man8
+
+CFLAGS = ${DEFS} -O -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
+
+
+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
+
+.if exists(/usr/lib/libcrypt.a) && exists(${.CURDIR}/crypt/crypt.c) && !defined(EXPORTABLE_SYSTEM)
+USE_CRYPT = yes
+.endif
+
+NETBSD_LIBS = -lcrypt -lutil
+CMUCS_LIBS = -lsys
+OSF_LIBS = -lbsd
+LIBS = libextra.a
+sup_OFILES = ${SUPCL} ${SUPS}
+supfilesrv_OFILES = supfilesrv.o scan.o ${SUPS}
+supfilesrv_LIBS = libextra.a
+supscan_OFILES = supscan.o stree.o scan.o
+
+
+all: ${PROGRAMS}
+.if defined(USE_CRYPT)
+ @echo "WARNING: You have built a NON-exportable version of sup because it uses crypt()!"
+ @echo " To build a crypt-clean version define EXPORTABLE_SYSTEM=true and make."
+.endif
+
+sup: ${sup_OFILES} ${LIBS}
+ ${CC} ${CFLAGS} -o sup ${sup_OFILES} ${LIBS} ${NETBSD_LIBS}
+
+supfilesrv: ${supfilesrv_OFILES} ${supfilesrv_LIBS}
+ ${CC} ${CFLAGS} -o supfilesrv ${supfilesrv_OFILES} ${supfilesrv_LIBS} ${NETBSD_LIBS}
+
+supscan: ${supscan_OFILES} ${LIBS}
+ ${CC} ${CFLAGS} -o supscan ${supscan_OFILES} ${LIBS} ${NETBSD_LIBS}
+
+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 -cs -m 555 -o bin -g bin ${PROGRAMS} ${NETBSD_BINDIR}
+ install -c -m 444 -o bin -g bin ${MAN1} ${NETBSD_MAN1}
+ install -c -m 444 -o bin -g bin ${MAN8} ${NETBSD_MAN8}
+
+netcrypt.c: crypt.diffs
+.if defined(USE_CRYPT)
+ ed - crypt/crypt.c < crypt.diffs
+.else
+ @echo "[ Using netcryptvoid.c ]"
+ cp netcryptvoid.c netcrypt.c
+.endif
+
+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
diff --git a/usr.bin/sup/src/atoo.c b/usr.bin/sup/src/atoo.c
new file mode 100644
index 00000000000..eac0764e31c
--- /dev/null
+++ b/usr.bin/sup/src/atoo.c
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+/* atoo -- convert ascii to octal
+ *
+ * Usge: i = atoo (string);
+ * unsigned int i;
+ * char *string;
+ *
+ * Atoo converts the value contained in "string" into an
+ * unsigned integer, assuming that the value represents
+ * an octal number.
+ *
+ * HISTORY
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Rewritten for VAX.
+ *
+ */
+
+unsigned int atoo(ap)
+char *ap;
+{
+ register unsigned int n;
+ register char *p;
+
+ p = ap;
+ n = 0;
+ while(*p == ' ' || *p == ' ')
+ p++;
+ while(*p >= '0' && *p <= '7')
+ n = n * 8 + *p++ - '0';
+ return(n);
+}
diff --git a/usr.bin/sup/src/c.h b/usr.bin/sup/src/c.h
new file mode 100644
index 00000000000..801331d098e
--- /dev/null
+++ b/usr.bin/sup/src/c.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+/*
+ * Standard C macros
+ *
+ **********************************************************************
+ * HISTORY
+ * 02-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added check to allow multiple or recursive inclusion of this
+ * file. Added bool enum from machine/types.h for regular users
+ * that want a real boolean type.
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Also change spacing of MAX and MIN to coincide with that of
+ * sys/param.h.
+ *
+ * 19-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed the number of tabs between TRUE, FALSE and their
+ * respective values to match those in sys/types.h.
+ *
+ * 17-Dec-84 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Only define TRUE and FALSE if not defined. Added caseE macro
+ * for using enumerated types in switch statements.
+ *
+ * 23-Apr-81 Mike Accetta (mja) at Carnegie-Mellon University
+ * Added "sizeofS" and "sizeofA" macros which expand to the size
+ * of a string constant and array respectively.
+ *
+ **********************************************************************
+ */
+
+#ifndef _C_INCLUDE_
+#define _C_INCLUDE_
+
+#define ABS(x) ((x)>=0?(x):-(x))
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+#ifndef FALSE
+#define FALSE 0
+#endif FALSE
+#ifndef TRUE
+#define TRUE 1
+#endif TRUE
+
+#define CERROR (-1)
+
+#ifndef bool
+typedef enum { false = 0, true = 1 } bool;
+#endif bool
+
+#define sizeofS(string) (sizeof(string) - 1)
+#define sizeofA(array) (sizeof(array)/sizeof(array[0]))
+
+#define caseE(enum_type) case (int)(enum_type)
+
+#endif _C_INCLUDE_
diff --git a/usr.bin/sup/src/ci.c b/usr.bin/sup/src/ci.c
new file mode 100644
index 00000000000..8960eb50cee
--- /dev/null
+++ b/usr.bin/sup/src/ci.c
@@ -0,0 +1,847 @@
+/*
+ * 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.
+ */
+/* ci -- command interpreter
+ *
+ * Usage (etc.)
+ *
+ * HISTORY
+ * 22-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed checks for VIRTUE window manager. If they don't like
+ * it then they can fix the more program.
+ *
+ * 08-May-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Increased MAXENTRIES and MAXHELPS from 200 to 400.
+ *
+ * 30-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Adapted for 4.2 UNIX. Added calls to check for
+ * using window manager of VIRTUE.
+ *
+ * 29-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added two small bug fixes (courtesy of Richard Cohn).
+ *
+ * 14-Aug-84 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added fflush(stdout) after printing prompt, before asking for input line.
+ *
+ * 01-Jul-83 Steven Shafer (sas) at Carnegie-Mellon University
+ * Bug fix: whitespace now required before ">filename" and not permitted
+ * within or after filename.
+ *
+ * 06-Jun-83 Steven Shafer (sas) at Carnegie-Mellon University
+ * Bug fix: added line to initialize "redirected" to 0.
+ *
+ * 20-May-83 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added quiet bits CINOSEM, CINOFILE, CIFIRSTEQUAL to allow user to
+ * have special characters ; > = treated as normal data (except =
+ * after first argument, which still means "variable assignment").
+ * Also added output redirection via >filename on input line.
+ *
+ * 07-Mar-83 Dave McKeown (dmm) at Carnegie-Mellon University
+ * (Slight alterations by Steve Shafer.)
+ * Made cidepth a global, used for recursive and nested calls to
+ * ci(), and accessable to the user. Added '@x' command, similar
+ * to '^x' except that the previous command interpreter name is
+ * remembered and after 'x' is executed, the previous command
+ * interpreter is reinvoked. Users who plan to use this feature
+ * must save the name of the previous ci in global variable
+ * 'ciprev' after exit from the ci(). ie.
+ * ci(.........);
+ * strcpy(ciprev,"ci-name");
+ * Added ci state CICMDNOINDENT to allow for no indentation of the
+ * command line prompt based on cidepth.
+ * Reduced amount of indentation on source code.
+ * Bug: the "depth" argument is now a no-op, retained for backward
+ * compatibility. Cidepth is initialized to zero, and incremented
+ * upon invocation of a ci(). If cidepth is <1 then you are not
+ * in a ci() instantiation.
+ *
+ * 21-Feb-83 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added up-arrow (^) command (and variable cinext). ^x is used when
+ * you have a ci program in which one command invokes ci with a
+ * new set of commands (i.e. a subsystem of the program). Inside the
+ * subsystem, ^x will exit the subsystem, and cause the main level
+ * to execute the command line "x" before reading more input lines.
+ * The cinext variable is used to implement this. Cinext can also be
+ * used by any user code which desires to force ci to execute a
+ * specific command before reading more input from the current file.
+ *
+ * 16-Jul-82 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added extra code in _ci_help to eliminate duplicate help file
+ * names. This way, if several directories are specified and there
+ * is are files with the same name in more than one directory, only
+ * the first of each file will be included in the help list.
+ *
+ * It would have been nice to do this after the qsort instead of
+ * before (in ci_help). However, qsort does not ensure that
+ * "equivalent" entries are kept in the same relative
+ * order; thus there would be no way to ensure that the
+ * file being used was the first such file found.
+ *
+ * 07-Jul-82 William Chiles (wpc) at Carnegie-Mellon University
+ * Modified so that "!" invokes shell commands from the type of
+ * shell specified by the environment variable SHELL. If SHELL
+ * is not defined the standard shell is used.
+ *
+ * 21-Sep-81 Steven Shafer (sas) at Carnegie-Mellon University
+ * Increased LINELENGTH (input buffer length) to 1100 to satisfy
+ * voracious requirements of a certain user whose name I won't mention
+ * but whose initials are "faa".
+ *
+ * 08-Oct-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added class variables: ci_tclass cases in ci_show and ci_set.
+ * Also added CICMDFPEEK in addition to existing CISETPEEK.
+ *
+ * 22-May-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Ci now sorts help topics into alphabetical order. Some interrupt
+ * handling has been added, but there are bugs, for example, when
+ * you interrupt "*" (the listing of command names). The right thing
+ * happens, but bogus messages are printed.
+ *
+ * 16-Apr-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Ci now prints lists of names with prstab(). This uses multiple
+ * columns when appropriate.
+ *
+ * 12-Mar-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added code to skip over leading blanks and tabs in the argument list
+ * when executing commands, and setting and displaying variables.
+ * Also fixed meta-help, which mysteriously disappeared.
+ *
+ * 19-Feb-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added "if (0) del();" to force del() routine to be loaded. This is
+ * the safest way I know of to define the external int "_del_". If you
+ * don't believe it, think again about separately compiled files.
+ *
+ * 28-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created. Patterned (somewhat) after ci() on PDP-11.
+ *
+ */
+
+
+#include <strings.h>
+#include <libc.h>
+#include <ci.h>
+#include <del.h>
+
+char *index(),*getenv(),*rindex();
+extern char _argbreak;
+long atol();
+double atof();
+static int ci_help(), ci_show();
+static int _ci_sho(), _ci_set(), ci_set();
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+#define LINELENGTH 1100 /* max length of input line */
+#define MAXENTRIES 400 /* max entries in entry list */
+#define MAXHELPS 400 /* max help files available */
+#define METAHELP "/usr/lib/ci.help" /* standard help file */
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+int ciquiet = 0; /* init globals */
+int ciexit = 0;
+int cidepth = 0;
+int ciback = 0; /* for use in '@' command */
+FILE *ciinput;
+
+char cinext[LINELENGTH] = "";
+char ciprev[LINELENGTH] = "";
+
+static char *delchoice[] = { /* breakpoint choices */
+ "abort abort command file",
+ "breakpoint break to tty, then resume command file",
+ 0};
+
+/*************************************
+ *** M A I N R O U T I N E ***
+ *************************************/
+
+ci (prompt,fil,depth,list,helppath,cmdfpath)
+char *prompt; /* prompt message */
+FILE *fil; /* input file */
+int depth; /* recursion depth */
+CIENTRY *list; /* entry list */
+char *helppath; /* search list for help files */
+char *cmdfpath; /* search list for command files */
+
+{
+
+ FILE *savfile; /* input file for calling instance of ci */
+ int savquiet, savexit; /* globals for calling instance of ci */
+ char *p,*q,*cmd,*arg; /* temps for parsing input */
+ int i; /* temp */
+ char line[LINELENGTH]; /* input line buffer */
+ int firststmt; /* temp */
+ char *equals,*star; /* index of = and * in input line */
+ char cfnam[200]; /* name of command file */
+ char *name[MAXENTRIES]; /* name list for entries */
+ char *vname[MAXENTRIES]; /* name list for just variables */
+ int vnum[MAXENTRIES]; /* correspondence list for variables */
+ int nv; /* number of variables */
+ int helpcmd; /* "help" command index */
+ FILE *newfile; /* command file just opened */
+ char bprompt[100]; /* breakpoint prompt */
+ char *tname[MAXENTRIES]; /* temp name list */
+ int tnum; /* # entries in tname */
+ char *Shell; /* holds SHELL value from .login */
+ int redirected; /* 1 iff currently redirected output */
+ FILE savestdout; /* place to save normal std. output */
+ FILE *outfile; /* current output file */
+ char *outname; /* output file name */
+
+
+ /* force del() routine to be declared */
+ if (0) del();
+ /* save globals on stack */
+ cidepth++; /* bump the global depth, first CI() is 1 */
+ savquiet = ciquiet;
+ savexit = ciexit;
+ savfile = ciinput;
+ ciexit = 0; /* don't exit until this is set */
+ ciinput = (fil ? fil : stdin); /* new input file */
+
+ /* construct name lists for stablk */
+
+ nv = 0;
+ for (i=0; list[i].ci_etyp != ci_tend; i++) {
+ name[i] = list[i].ci_enam;
+ if (list[i].ci_etyp != ci_tcmd) { /* is variable */
+ vname[nv] = name[i];
+ vnum[nv] = i;
+ nv++;
+ }
+ }
+ helpcmd = i++; /* force-feed "help" onto list */
+ name[helpcmd] = "help";
+ name[i] = 0;
+ vname[nv] = 0;
+
+ /* loop for input lines */
+
+ redirected = 0;
+ while (!ciexit) {
+
+ if (*cinext) { /* get line from ^ command */
+ if (ciback) {
+ sprintf(line,"%s;%s",cinext,ciprev);
+ ciback = 0;
+ }
+ else {
+ strcpy (line,cinext);
+ }
+ strcpy (cinext,"");
+ p = line;
+ }
+ else { /* else read file */
+ if ((ciinput == stderr) || (ciinput == stdin) || (!(ciquiet&CICMDFPROMPT))) {
+ if (!(ciquiet &CICMDNOINDENT)) {
+ for (i=1; i<cidepth; i++) {
+ printf (" ");
+ }
+ }
+ printf ("%s ",prompt);
+ if ((ciinput == stderr) || (ciinput == stdin)) fflush (stdout);
+ }
+ p = fgets (line,LINELENGTH,ciinput); /* read input line */
+ if (p == 0) { /* EOF */
+ if (_del_) {
+ DELCLEAR;
+ strcpy (line,"");
+ p = line;
+ }
+ else {
+ ciexit = 1;
+ if ((ciinput==stdin) || (ciinput==stderr) ||
+ (!(ciquiet&CICMDFECHO))) printf ("\n");
+ }
+ }
+ else {
+ if ((ciinput != stderr) && (ciinput != stdin) &&
+ (!(ciquiet&CICMDFECHO))) printf ("%s",line);
+
+ for (p=line; (*p) && (*p != '\n'); p++) ;
+ *p = 0; /* kill trailing newline */
+ p = line; /* points to start of line */
+ }
+ }
+
+ /* check for redirection of output */
+
+ if (!ciexit) {
+ outname = rindex (p,'>');
+ if (outname) {
+ if (outname == p || *(outname+1) == 0
+ || ((*(outname-1) != ' ') && (*(outname-1) != '\t'))) {
+ outname = 0;
+ }
+ else {
+ for (q=outname+1; *q && (*q != ' ') && (*q != '\t'); q++) ;
+ if (*q) outname = 0;
+ }
+ }
+ if (outname && !(ciquiet&CINOFILE)) {
+ *outname++ = 0;
+ outfile = fopen (outname,"w");
+ if (outfile == 0) {
+ printf ("ci: Can't create output file %s\n",outname);
+ p = "";
+ }
+ else {
+ fflush (stdout);
+ savestdout = *stdout;
+ *stdout = *outfile;
+ redirected = 1;
+ }
+ }
+ }
+
+ /* loop for each command */
+
+ firststmt = 1; /* first time through loop */
+ while ((!ciexit) && (((ciquiet&CINOSEM) && firststmt) || *(cmd=nxtarg(&p,";")) || _argbreak)) {
+
+ if (ciquiet & CINOSEM) {
+ cmd = p;
+ firststmt = 0;
+ }
+
+ switch (*cmd) { /* what kind of line? */
+
+ case ':': /* : comment */
+ case 0: /* null line */
+ break;
+
+ case '!': /* ! shell command */
+ cmd = skipover (cmd+1," ");
+ if ((Shell = getenv("SHELL")) == 0) Shell = "sh";
+ if (*cmd) runp (Shell, Shell, "-c", cmd, 0);
+ else runp (Shell, Shell, 0);
+ if (!(ciquiet&CISHEXIT)) printf ("Back to %s\n",prompt);
+ break;
+
+ case '?': /* ? help */
+ cmd = skipover (cmd+1," ");
+ ci_help (cmd,helppath);
+ break;
+
+ case '<': /* < command file */
+ arg = cmd + 1;
+ cmd = nxtarg (&arg,0); /* parse name */
+ if (*cmd == 0) printf ("ci: missing filename\n");
+ else {
+ if (cmdfpath) newfile = fopenp (cmdfpath,cmd,cfnam,"r");
+ else newfile = fopen (cmd,"r");
+
+ if (newfile == 0)
+ printf ("ci: can't open command file %s\n",cmd);
+ else {
+ if (!(ciquiet&CICMDFECHO)) printf ("\n");
+ ci (prompt,newfile,cidepth,list,helppath,cmdfpath);
+ fclose (newfile);
+ if (!(ciquiet&CICMDFEXIT)) printf ("End of file\n\n");
+ }
+ }
+ break;
+
+ case '^': /* exit and do command */
+ case '@':
+ if (cidepth > 1) {
+ if (*cmd == '@') ciback = 1;
+ if (_argbreak == ';') *(cmd+strlen(cmd)) = ';';
+ ciexit = 1;
+ cmd = skipover(cmd+1," ");
+ strcpy (cinext,cmd);
+ }
+ else printf ("ci: ^ not allowed at top level of ci\n");
+ break;
+
+ default: /* list cmds, etc. */
+ equals = index (cmd,'=');
+ if (equals == cmd) cmd++;
+
+ if (equals) {
+ if (*(equals+1) == 0) *equals = 0;
+ else *equals = ' ';
+ }
+
+ arg = cmd; /* parse first word */
+ cmd = nxtarg (&arg,0);
+ if ((ciquiet&CIFIRSTEQUAL) && equals && equals>arg) {
+ *equals = '='; /* if user doesn't want extra =, kill */
+ equals = 0;
+ }
+ star = index (cmd,'*');
+ if (star) *star = 0;
+ if (star && equals) { /* list vars */
+ printf ("\n");
+ for (i=0; vname[i]; i++) {
+ if (stlmatch (vname[i],cmd)) {
+ ci_show (list[vnum[i]],arg,CIPEEK);
+ }
+ DELBREAK;
+ }
+ printf ("\n");
+ }
+ else if (star) { /* list cmds */
+ printf ("\n");
+ tnum = 0;
+ for (i=0;name[i]; i++) {
+ if ((i==helpcmd || list[i].ci_etyp == ci_tcmd) &&
+ stlmatch (name[i],cmd)) {
+ tname[tnum++] = name[i];
+ }
+ }
+ tname[tnum] = 0;
+ prstab (tname);
+ if (_del_) {_DELNOTE_}
+ printf ("\n");
+ }
+ else if (equals) { /* set var */
+ i = stablk (cmd,vname,0);
+ if (i >= 0) ci_set (list[vnum[i]],skipover(arg," \t"));
+ }
+ else {
+ i = stablk (cmd,name,0);
+
+ if (i == helpcmd) ci_help (arg,helppath);
+ else if (i >= 0) {
+ if (list[i].ci_etyp == ci_tcmd) {
+ (* (int(*)()) (list[i].ci_eptr)) (skipover(arg," \t"));
+ }
+ else ci_show (list[i],skipover(arg," \t"),CISHOW);
+ }
+ }
+ }
+
+ /* end of command */
+
+ /* DEL trapping */
+
+ if (_del_) {
+ if (ciinput == stdin) {
+ DELCLEAR; /* already at tty level */
+ }
+ else {
+ _del_ = 0;
+ i = getstab ("INTERRUPT: abort or breakpoint?",delchoice,"abort");
+ if (i == 0) ciexit = 1; /* abort */
+ else { /* breakpoint */
+ sprintf (bprompt,"Breakpoint for %s",prompt);
+ ci (bprompt,0,cidepth,list,helppath,cmdfpath);
+ }
+ }
+ }
+
+ /* end of loop for commands */
+
+ }
+
+ /* end of loop for lines of input file */
+
+ if (redirected) {
+ fflush (stdout);
+ fclose (stdout);
+ *stdout = savestdout;
+ redirected = 0;
+ }
+
+ }
+
+ /* restore globals */
+ cidepth --; /* update current depth */
+ ciinput = savfile;
+ ciquiet = savquiet;
+ ciexit = savexit;
+}
+
+/********************************************
+ *** P R I N T H E L P F I L E ***
+ ********************************************/
+
+static int _h_found; /* how many matching names? */
+static char **_h_list; /* list of matching names */
+static char (*_h_nlist)[20]; /* list of filename part of names */
+
+static int _ci_help (filspec)
+/* called by searchp to expand filspec, adding names to _h_list */
+char *filspec;
+{
+ register int i,j,result;
+ char dir[200];
+
+ result = expand (filspec, _h_list + _h_found, MAXHELPS - _h_found);
+ if (result > 0) {
+ for (i=0; i<result; ) { /* elim duplicates */
+ path (_h_list[i+_h_found],dir,_h_nlist[i+_h_found]);
+ for (j=0;
+ j<_h_found && strcmp(_h_nlist[j],_h_nlist[i+_h_found]) != 0;
+ j++) ;
+ if (j < _h_found) { /* is duplicate */
+ --result;
+ strcpy (_h_list[i+_h_found],_h_list[result+_h_found]);
+ }
+ else i++; /* isn't duplicate */
+ }
+
+ _h_found += result;
+ }
+
+ return (1); /* keep searching */
+}
+
+/* for use in sorting help file names */
+static ci_hcomp (p,q)
+char **p,**q;
+{
+ char dir[200],file1[20],file2[20];
+ path ((*p),dir,file1);
+ path ((*q),dir,file2);
+ return (strcmp(file1,file2));
+}
+
+static ci_help (topic,helppath)
+char *topic,*helppath;
+{
+ char *fnames[MAXHELPS]; /* names of matching files */
+ char names[MAXHELPS][20]; /* stripped filenames */
+ char *nptr[MAXHELPS+1]; /* list of ptrs for stablk */
+ char dir[200]; /* temp */
+ char shstr[300]; /* shell string for system */
+ int i;
+ char *star;
+ FILE *f;
+
+ if (*topic == 0) { /* wants meta-help */
+ f = fopen (METAHELP,"r");
+ if (f == 0) {
+ printf ("Yikes!! Can't open standard help file!\n");
+ }
+ else {
+ printf ("\n");
+ runp("more","more",METAHELP,0);
+ if (_del_) {_DELNOTE_}
+ printf ("\n");
+ fclose (f);
+ }
+ if (helppath && (*helppath) && (!getbool("Do you want a list of help topics?",1))) {
+ return;
+ }
+ }
+ else { /* chop at * */
+ star = index (topic,'*');
+ if (star) *star = 0;
+ }
+
+ if (helppath == 0) { /* no help at all */
+ printf ("Sorry, no specific help is available for this program.\n");
+ }
+ else {
+ _h_found = 0;
+ _h_list = fnames;
+ _h_nlist = names;
+ searchp (helppath,"*",dir,_ci_help); /* find file names */
+ qsort (fnames,_h_found,sizeof(char *),ci_hcomp);
+
+ for (i=0; i<_h_found; i++) { /* strip pathnames */
+ path (fnames[i],dir,names[i]);
+ nptr[i] = names[i];
+ }
+ nptr[i] = 0;
+
+ if (*topic) { /* request some topic */
+ if (_h_found == 0) {
+ printf ("No help for %s. Type '?*' for list of help messages.\n",topic);
+ }
+ else {
+ i = stablk (topic,nptr,1);
+ if (i < 0) i = stabsearch (topic,nptr,0);
+ if (i >= 0) {
+ f = fopen (fnames[i],"r");
+ if (f == 0)
+ printf ("Yikes! Can't open help file %s\n",fnames[i]);
+ else {
+ printf ("\n");
+ runp("more","more",fnames[i],0);
+ if (_del_) {_DELNOTE_}
+ printf ("\n");
+ fclose (f);
+ }
+ }
+ }
+ }
+ else { /* request topic list */
+ printf ("\nHelp is available for these topics:\n");
+ prstab (nptr);
+ if (_del_) {_DELNOTE_}
+ printf ("\n");
+ }
+
+ for (i=0; i<_h_found; i++) free (fnames[i]);
+
+ }
+}
+
+/*********************************************************
+ *** S H O W V A L U E O F V A R I A B L E ***
+ *********************************************************/
+
+static ci_show (entry,arg,mode)
+CIENTRY entry; /* entry to display */
+char *arg; /* arg for variable procedures */
+CIMODE mode; /* mode (CIPEEK or CISHOW) */
+{
+ if (entry.ci_etyp == ci_tproc) { /* procedure */
+ (* (int(*)()) (entry.ci_eptr)) (mode,arg);
+ }
+ else if (entry.ci_etyp == ci_tclass) { /* class variable */
+ (* (int(*)()) (entry.ci_eptr)) (mode,arg,entry.ci_evar,entry.ci_enam);
+ }
+ else {
+ printf ("%-14s \t",entry.ci_enam);
+ _ci_sho (entry.ci_etyp, entry.ci_eptr);
+ printf ("\n");
+ }
+}
+
+static _ci_sho (etype,eptr)
+ci_type etype;
+ci_union *eptr;
+{
+ int i;
+ unsigned int u;
+
+ switch (etype) {
+
+ case ci_tint:
+ printf ("%d",eptr->ci_uint);
+ break;
+ case ci_tshort:
+ printf ("%d",eptr->ci_ushort);
+ break;
+ case ci_tlong:
+ printf ("%D",eptr->ci_ulong);
+ break;
+ case ci_toct:
+ if (eptr->ci_uoct) printf ("0");
+ printf ("%o",eptr->ci_uoct);
+ break;
+ case ci_thex:
+ if (eptr->ci_uhex) printf ("0x");
+ printf ("%x",eptr->ci_uhex);
+ break;
+ case ci_tdouble:
+ printf ("%g",eptr->ci_udouble);
+ break;
+ case ci_tfloat:
+ printf ("%g",eptr->ci_ufloat);
+ break;
+ case ci_tbool:
+ if (eptr->ci_ubool) printf ("yes");
+ else printf ("no");
+ break;
+ case ci_tstring:
+ printf ("%s",(char *)eptr);
+ break;
+ case ci_tcint:
+ printf ("%d",*(eptr->ci_ucint.ci_ival));
+ break;
+ case ci_tcshort:
+ printf ("%d",*(eptr->ci_ucshort.ci_sval));
+ break;
+ case ci_tclong:
+ printf ("%D",*(eptr->ci_uclong.ci_lval));
+ break;
+ case ci_tcoct:
+ u = *(eptr->ci_ucoct.ci_uval);
+ if (u) printf ("0");
+ printf ("%o",u);
+ break;
+ case ci_tchex:
+ u = *(eptr->ci_uchex.ci_uval);
+ if (u) printf ("0x");
+ printf ("%x",u);
+ break;
+ case ci_tcdouble:
+ printf ("%g",*(eptr->ci_ucdouble.ci_dval));
+ break;
+ case ci_tcfloat:
+ printf ("%g",*(eptr->ci_ucfloat.ci_fval));
+ break;
+ case ci_tcbool:
+ i = *(eptr->ci_ucbool.ci_bval);
+ if (i) printf ("yes");
+ else printf ("no");
+ break;
+ case ci_tcchr:
+ i = *(eptr->ci_ucchr.ci_cval);
+ printf ("%c",eptr->ci_ucchr.ci_cleg[i]);
+ break;
+ case ci_tcstring:
+ printf ("%s",eptr->ci_ucstring.ci_pval);
+ break;
+ case ci_tctab:
+ i = *(eptr->ci_ucstab.ci_tval);
+ printf ("%s",eptr->ci_ucstab.ci_ttab[i]);
+ break;
+ case ci_tcsearch:
+ i = *(eptr->ci_ucsearch.ci_tval);
+ printf ("%s",eptr->ci_ucsearch.ci_ttab[i]);
+ break;
+ default:
+ printf ("Yeek! Illegal cientry type %d!\n",(int) etype);
+ }
+}
+
+/*************************************************************
+ *** A S S I G N V A L U E T O V A R I A B L E ***
+ *************************************************************/
+
+static ci_set (entry,arg)
+CIENTRY entry;
+char *arg;
+{
+ if (entry.ci_etyp == ci_tproc) { /* variable procedure */
+ (* (int(*)()) (entry.ci_eptr)) (CISET,arg);
+ }
+ else if (entry.ci_etyp == ci_tclass) { /* class variable */
+ (* (int(*)()) (entry.ci_eptr)) (CISET,arg,entry.ci_evar,entry.ci_enam);
+ }
+ else {
+ _ci_set (entry.ci_etyp, entry.ci_eptr, arg);
+ if (!(ciquiet & (((ciinput==stdin)||(ciinput==stderr)) ? CISETPEEK : CICMDFPEEK)))
+ ci_show (entry,arg,CIPEEK);
+ }
+}
+
+static _ci_set (etype,eptr,arg)
+ci_type etype;
+ci_union *eptr;
+char *arg;
+{
+ int i;
+ unsigned int u;
+ char *p;
+
+ if (etype == ci_tstring) {
+ strcpy ((char *)eptr,arg);
+ return;
+ }
+ if (etype == ci_tcstring) {
+ strarg (&arg, ";", eptr->ci_ucstring.ci_pmsg,
+ eptr->ci_ucstring.ci_pval,eptr->ci_ucstring.ci_pval);
+ return;
+ }
+
+ p = arg; /* parse first word */
+ arg = nxtarg (&p,0);
+
+ switch (etype) {
+
+ case ci_tint:
+ eptr->ci_uint = atoi (arg);
+ break;
+ case ci_tshort:
+ eptr->ci_ushort = atoi (arg);
+ break;
+ case ci_tlong:
+ eptr->ci_ulong = atol (arg);
+ break;
+ case ci_toct:
+ eptr->ci_uoct = atoo (arg);
+ break;
+ case ci_thex:
+ if (stlmatch(arg,"0x") || stlmatch(arg,"0X")) arg += 2;
+ eptr->ci_uhex = atoh (arg);
+ break;
+ case ci_tdouble:
+ eptr->ci_udouble = atof (arg);
+ break;
+ case ci_tfloat:
+ eptr->ci_ufloat = atof (arg);
+ break;
+ case ci_tbool:
+ eptr->ci_ubool = (index("yYtT",*arg) != 0);
+ break;
+ case ci_tcint:
+ *(eptr->ci_ucint.ci_ival) =
+ intarg (&arg,0,eptr->ci_ucint.ci_imsg,eptr->ci_ucint.ci_imin,
+ eptr->ci_ucint.ci_imax,*(eptr->ci_ucint.ci_ival));
+ break;
+ case ci_tcshort:
+ *(eptr->ci_ucshort.ci_sval) =
+ shortarg (&arg,0,eptr->ci_ucshort.ci_smsg,eptr->ci_ucshort.ci_smin,
+ eptr->ci_ucshort.ci_smax,*(eptr->ci_ucshort.ci_sval));
+ break;
+ case ci_tclong:
+ *(eptr->ci_uclong.ci_lval) =
+ longarg (&arg,0,eptr->ci_uclong.ci_lmsg,eptr->ci_uclong.ci_lmin,
+ eptr->ci_uclong.ci_lmax,*(eptr->ci_uclong.ci_lval));
+ break;
+ case ci_tcoct:
+ *(eptr->ci_ucoct.ci_uval) =
+ octarg (&arg,0,eptr->ci_ucoct.ci_umsg,eptr->ci_ucoct.ci_umin,
+ eptr->ci_ucoct.ci_umax,*(eptr->ci_ucoct.ci_uval));
+ break;
+ case ci_tchex:
+ *(eptr->ci_uchex.ci_uval) =
+ hexarg (&arg,0,eptr->ci_uchex.ci_umsg,eptr->ci_uchex.ci_umin,
+ eptr->ci_uchex.ci_umax,*(eptr->ci_uchex.ci_uval));
+ break;
+ case ci_tcdouble:
+ *(eptr->ci_ucdouble.ci_dval) =
+ doublearg (&arg,0,eptr->ci_ucdouble.ci_dmsg,eptr->ci_ucdouble.ci_dmin,
+ eptr->ci_ucdouble.ci_dmax,*(eptr->ci_ucdouble.ci_dval));
+ break;
+ case ci_tcfloat:
+ *(eptr->ci_ucfloat.ci_fval) =
+ floatarg (&arg,0,eptr->ci_ucfloat.ci_fmsg,eptr->ci_ucfloat.ci_fmin,
+ eptr->ci_ucfloat.ci_fmax,*(eptr->ci_ucfloat.ci_fval));
+ break;
+ case ci_tcbool:
+ *(eptr->ci_ucbool.ci_bval) =
+ boolarg (&arg,0,eptr->ci_ucbool.ci_bmsg,*(eptr->ci_ucbool.ci_bval));
+ break;
+ case ci_tcchr:
+ *(eptr->ci_ucchr.ci_cval) =
+ chrarg (&arg,0,eptr->ci_ucchr.ci_cmsg,eptr->ci_ucchr.ci_cleg,
+ eptr->ci_ucchr.ci_cleg[*(eptr->ci_ucchr.ci_cval)]);
+ break;
+ case ci_tctab:
+ *(eptr->ci_ucstab.ci_tval) =
+ stabarg (&arg,0,eptr->ci_ucstab.ci_tmsg,eptr->ci_ucstab.ci_ttab,
+ eptr->ci_ucstab.ci_ttab[*(eptr->ci_ucstab.ci_tval)]);
+ break;
+ case ci_tcsearch:
+ *(eptr->ci_ucsearch.ci_tval) =
+ searcharg (&arg,0,eptr->ci_ucsearch.ci_tmsg,
+ eptr->ci_ucsearch.ci_ttab,
+ eptr->ci_ucsearch.ci_ttab[*(eptr->ci_ucsearch.ci_tval)]);
+ break;
+ default:;
+ }
+}
diff --git a/usr.bin/sup/src/crypt.diffs b/usr.bin/sup/src/crypt.diffs
new file mode 100644
index 00000000000..c1201ceccd3
--- /dev/null
+++ b/usr.bin/sup/src/crypt.diffs
@@ -0,0 +1,87 @@
+118,$c
+void encode (in,out,count)
+char *in,*out;
+int count;
+{
+ decode (in,out,count);
+}
+.
+109,113c
+ nr2 = n2;
+.
+103c
+ *outp++ = i;
+.
+95,101c
+ while(count -- > 0) {
+ i = *inp++;
+ nr1 = n1;
+.
+93a
+ inp = in;
+ outp = out;
+.
+86,90c
+ return (SCMOK);
+}
+
+void decode (in,out,count)
+char *in,*out;
+register int count;
+{
+ register i, n1, n2, nr1, nr2;
+ char *inp, *outp;
+.
+81,84c
+ if (cryptflag == 0) {
+ if (cryptsize > 0) free (cryptbuf);
+ cryptsize = 0;
+ } else if (x > cryptsize) {
+ if (cryptsize > 0) free (cryptbuf);
+ cryptbuf = malloc ((unsigned)x+1);
+ if (cryptbuf == NULL)
+ return (scmerr (-1,"Can't allocate encryption buffer"));
+ cryptsize = x;
+.
+78,79c
+ static int cryptsize = 0; /* size of current cryptbuf */
+.
+75,76c
+int getcryptbuf (x)
+int x;
+.
+72a
+ return (SCMOK);
+.
+54d
+42,48c
+ cryptflag = 1;
+ for (i=0; i<ROTORSZ; i++) t1[i] = t2[i] = t3[i] = 0;
+ (void) strncpy(buf, pw, 8);
+ (void) strncpy(buf, crypt(buf, buf), 13);
+.
+27,40c
+ if (pw == NULL) {
+ cryptflag = 0;
+ (void) getcryptbuf (0);
+ return (SCMOK);
+.
+23d
+19c
+netcrypt(pw)
+.
+12,17c
+static char t1[ROTORSZ];
+static char t2[ROTORSZ];
+static char t3[ROTORSZ];
+static char buf[13];
+int cryptflag = 0; /* whether to encrypt/decrypt data */
+char *cryptbuf; /* buffer for data encryption/decryption */
+.
+9a
+#include "sup.h"
+
+extern char *malloc();
+
+.
+w netcrypt.c
diff --git a/usr.bin/sup/src/crypt.info b/usr.bin/sup/src/crypt.info
new file mode 100644
index 00000000000..badffccf328
--- /dev/null
+++ b/usr.bin/sup/src/crypt.info
@@ -0,0 +1,15 @@
+The sup programs can be built with or without crypting functionality.
+If the file netcryptvoid.c is used no crypting code will be used.
+If the file netcrypt.c is used, an engima engine crypting scheme
+taken from the BSD 4.3 (1/25/85) file /usr/bin/crypt.c will be used. Since,
+this code is both licensed and under U.S. foreign trade restrictions,
+we cannot make this code available for anonymous FTP.
+
+If you want to build a sup client which can encrypt data and you
+are a domestic site who has a 4.3 BSD license, we can mail you
+a copy of then netcrypt.c file. Just send mail to mach@cs.cmu.edu
+requesting the file.
+
+If you have a crypt.c file available, copy it to the directory
+./crypt and the makefile file apply the diff in crypt.diffs to
+generate the netcrypt.c file.
diff --git a/usr.bin/sup/src/cvt.c b/usr.bin/sup/src/cvt.c
new file mode 100644
index 00000000000..0551a266948
--- /dev/null
+++ b/usr.bin/sup/src/cvt.c
@@ -0,0 +1,56 @@
+/*
+ * Quick hack to convert old binary sup when.collection files into
+ * the new ascii format.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ long b;
+ FILE *fp;
+ int fd;
+
+ if (argc != 2) {
+ (void) fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+
+ if ((fd = open(argv[1], O_RDWR)) == -1) {
+ perror("open");
+ return 1;
+ }
+
+ if (read(fd, &b, sizeof(b)) != sizeof(b)) {
+ perror("read");
+ return 1;
+ }
+
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ perror("lseek");
+ return 1;
+ }
+
+ (void) close(fd);
+
+ if ((fp = fopen(argv[1], "w")) == NULL) {
+ perror("fopen");
+ return 1;
+ }
+
+ if (fprintf(fp, "%ld\n", b) < 0) {
+ perror("fprintf");
+ return 1;
+ }
+ if (fclose(fp) != 0) {
+ perror("fclose");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/usr.bin/sup/src/errmsg.c b/usr.bin/sup/src/errmsg.c
new file mode 100644
index 00000000000..0ca7c9d04f4
--- /dev/null
+++ b/usr.bin/sup/src/errmsg.c
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+/*****************************************************************
+ * HISTORY
+ * 04-Mar-85 Rudy Nedved (ern) at Carnegie-Mellon University
+ * Create a CMU version of the BBN errmsg routine from scratch. It
+ * differs from the BBN errmsg routine in the fact that it uses a
+ * negative value to indicate using the current errno value...the
+ * BBN uses a negative OR zero value.
+ */
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+static char *itoa(p,n)
+char *p;
+unsigned n;
+{
+ if (n >= 10)
+ p =itoa(p,n/10);
+ *p++ = (n%10)+'0';
+ return(p);
+}
+
+char *errmsg(cod)
+int cod;
+{
+ static char unkmsg[] = "Unknown error ";
+ static char unk[sizeof(unkmsg)+11]; /* trust us */
+
+ if (cod < 0) cod = errno;
+
+ if((cod >= 0) && (cod < sys_nerr))
+ return(sys_errlist[cod]);
+
+ strcpy(unk,unkmsg);
+ *itoa(&unk[sizeof(unkmsg)-1],cod) = '\0';
+
+ return(unk);
+}
diff --git a/usr.bin/sup/src/expand.c b/usr.bin/sup/src/expand.c
new file mode 100644
index 00000000000..0014ebba911
--- /dev/null
+++ b/usr.bin/sup/src/expand.c
@@ -0,0 +1,376 @@
+/*
+ * 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.
+ */
+/*
+ * expand - expand wildcard filename specifications
+ *
+ * Usage:
+ * int expand(spec, buffer, bufsize);
+ * char *spec, **buffer;
+ * int bufsize;
+ *
+ * Expand takes a file specification, and expands it into filenames
+ * by resolving the characters '*', '?', '[', ']', '{', '}' and '~'
+ * in the same manner as the shell. You provide "buffer", which is
+ * an array of char *'s, and you tell how big it is in bufsize.
+ * Expand will compute the corresponding filenames, and will fill up
+ * the entries of buffer with pointers to malloc'd strings.
+ *
+ * The value returned by expand is the number of filenames found. If
+ * this value is -1, then malloc failed to allocate a string. If the
+ * value is bufsize + 1, then too many names were found and you can try
+ * again with a bigger buffer.
+ *
+ * This routine was basically created from the csh sh.glob.c file with
+ * the following intended differences:
+ *
+ * Filenames are not sorted.
+ * All expanded filenames returned exist.
+ *
+ **********************************************************************
+ * HISTORY
+ * 13-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Replaced a stat() with lstat() and changed glob() to only call
+ * matchdir() for directories.
+ *
+ * 20-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created from csh glob() function and 4.1 expand() function.
+ *
+ **********************************************************************
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#ifdef HAS_POSIX_DIR
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#endif
+#include <pwd.h>
+#include <ctype.h>
+#include <libc.h>
+#include <setjmp.h>
+
+static jmp_buf sjbuf;
+
+static char pathbuf[MAXPATHLEN];
+static char *path, *pathp, *lastpathp;
+
+static char *globchars = "{[*?"; /* meta characters */
+static char *entp; /* current dir entry pointer */
+
+static char **BUFFER; /* pointer to the buffer */
+static int BUFSIZE; /* maximum number in buffer */
+static int bufcnt; /* current number in buffer */
+
+static void glob();
+static void matchdir();
+static int execbrc();
+static int match();
+static int amatch();
+static void addone();
+static int addpath();
+static int gethdir();
+
+int expand(spec, buffer, bufsize)
+ register char *spec;
+ char **buffer;
+ int bufsize;
+{
+ pathp = path = pathbuf;
+ *pathp = 0;
+ lastpathp = &path[MAXPATHLEN - 2];
+ BUFFER = buffer;
+ BUFSIZE = bufsize;
+ bufcnt = 0;
+ if (setjmp(sjbuf) == 0)
+ glob(spec);
+ return(bufcnt);
+}
+
+static void glob(as)
+ char *as;
+{
+ register char *cs;
+ register char *spathp, *oldcs;
+ struct stat stb;
+
+ spathp = pathp;
+ cs = as;
+ if (*cs == '~' && pathp == path) {
+ if (addpath('~')) goto endit;
+ for (cs++; isalnum(*cs) || *cs == '_' || *cs == '-';)
+ if (addpath(*cs++)) goto endit;
+ if (!*cs || *cs == '/') {
+ if (pathp != path + 1) {
+ *pathp = 0;
+ if (gethdir(path + 1)) goto endit;
+ strcpy(path, path + 1);
+ } else
+ strcpy(path, (char *)getenv("HOME"));
+ pathp = path;
+ while (*pathp) pathp++;
+ }
+ }
+ while (*cs == 0 || index(globchars, *cs) == 0) {
+ if (*cs == 0) {
+ if (lstat(path, &stb) >= 0) addone(path, "");
+ goto endit;
+ }
+ if (addpath(*cs++)) goto endit;
+ }
+ oldcs = cs;
+ while (cs > as && *cs != '/')
+ cs--, pathp--;
+ if (*cs == '/')
+ cs++, pathp++;
+ *pathp = 0;
+ if (*oldcs == '{') {
+ execbrc(cs, NULL);
+ return;
+ }
+ /* this should not be an lstat */
+ if (stat(path, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR)
+ matchdir(cs);
+endit:
+ pathp = spathp;
+ *pathp = 0;
+ return;
+}
+
+static void matchdir(pattern)
+ char *pattern;
+{
+#ifdef HAS_POSIX_DIR
+ register struct dirent *dp;
+#else
+ register struct direct *dp;
+#endif
+ DIR *dirp;
+
+ dirp = opendir(path);
+ if (dirp == NULL)
+ return;
+ while ((dp = readdir(dirp)) != NULL) {
+#ifdef HAS_POSIX_DIR
+ if (dp->d_fileno == 0) continue;
+#else
+ if (dp->d_ino == 0) continue;
+#endif
+ if (match(dp->d_name, pattern))
+ addone(path, dp->d_name);
+ }
+ closedir(dirp);
+ return;
+}
+
+static int execbrc(p, s)
+ char *p, *s;
+{
+ char restbuf[MAXPATHLEN + 1];
+ register char *pe, *pm, *pl;
+ int brclev = 0;
+ char *lm, savec, *spathp;
+
+ for (lm = restbuf; *p != '{'; *lm++ = *p++)
+ continue;
+ for (pe = ++p; *pe; pe++)
+ switch (*pe) {
+ case '{':
+ brclev++;
+ continue;
+ case '}':
+ if (brclev == 0) goto pend;
+ brclev--;
+ continue;
+ case '[':
+ for (pe++; *pe && *pe != ']'; pe++)
+ continue;
+ if (!*pe) break;
+ continue;
+ }
+pend:
+ if (brclev || !*pe) return (0);
+ for (pl = pm = p; pm <= pe; pm++)
+ switch (*pm & 0177) {
+ case '{':
+ brclev++;
+ continue;
+ case '}':
+ if (brclev) {
+ brclev--;
+ continue;
+ }
+ goto doit;
+ case ',':
+ if (brclev) continue;
+doit:
+ savec = *pm;
+ *pm = 0;
+ strcpy(lm, pl);
+ strcat(restbuf, pe + 1);
+ *pm = savec;
+ if (s == 0) {
+ spathp = pathp;
+ glob(restbuf);
+ pathp = spathp;
+ *pathp = 0;
+ } else if (amatch(s, restbuf))
+ return (1);
+ pl = pm + 1;
+ continue;
+
+ case '[':
+ for (pm++; *pm && *pm != ']'; pm++)
+ continue;
+ if (!*pm) break;
+ continue;
+ }
+ return (0);
+}
+
+static int match(s, p)
+ char *s, *p;
+{
+ register int c;
+ register char *sentp;
+
+ if (*s == '.' && *p != '.') return(0);
+ sentp = entp;
+ entp = s;
+ c = amatch(s, p);
+ entp = sentp;
+ return (c);
+}
+
+static int amatch(s, p)
+ register char *s, *p;
+{
+ register int scc;
+ int ok, lc;
+ char *spathp;
+ struct stat stb;
+ int c, cc;
+
+ for (;;) {
+ scc = *s++ & 0177;
+ switch (c = *p++) {
+ case '{':
+ return (execbrc(p - 1, s - 1));
+ case '[':
+ ok = 0;
+ lc = 077777;
+ while (cc = *p++) {
+ if (cc == ']') {
+ if (ok) break;
+ return (0);
+ }
+ if (cc == '-') {
+ if (lc <= scc && scc <= *p++)
+ ok++;
+ } else
+ if (scc == (lc = cc))
+ ok++;
+ }
+ if (cc == 0) return (0);
+ continue;
+ case '*':
+ if (!*p) return (1);
+ if (*p == '/') {
+ p++;
+ goto slash;
+ }
+ for (s--; *s; s++)
+ if (amatch(s, p))
+ return (1);
+ return (0);
+ case 0:
+ return (scc == 0);
+ default:
+ if (c != scc) return (0);
+ continue;
+ case '?':
+ if (scc == 0) return (0);
+ continue;
+ case '/':
+ if (scc) return (0);
+slash:
+ s = entp;
+ spathp = pathp;
+ while (*s)
+ if (addpath(*s++)) goto pathovfl;
+ if (addpath('/')) goto pathovfl;
+ if (stat(path, &stb) >= 0 &&
+ (stb.st_mode&S_IFMT) == S_IFDIR)
+ if (*p == 0)
+ addone(path, "");
+ else
+ glob(p);
+pathovfl:
+ pathp = spathp;
+ *pathp = 0;
+ return (0);
+ }
+ }
+}
+
+static void addone(s1, s2)
+ register char *s1, *s2;
+{
+ register char *ep;
+
+ if (bufcnt >= BUFSIZE) {
+ bufcnt = BUFSIZE + 1;
+ longjmp(sjbuf, 1);
+ }
+ ep = (char *)malloc(strlen(s1) + strlen(s2) + 1);
+ if (ep == 0) {
+ bufcnt = -1;
+ longjmp(sjbuf, 1);
+ }
+ BUFFER[bufcnt++] = ep;
+ while (*s1) *ep++ = *s1++;
+ while (*ep++ = *s2++);
+}
+
+static int addpath(c)
+ char c;
+{
+ if (pathp >= lastpathp)
+ return(1);
+ *pathp++ = c;
+ *pathp = 0;
+ return(0);
+}
+
+static int gethdir(home)
+ char *home;
+{
+ struct passwd *getpwnam();
+ register struct passwd *pp = getpwnam(home);
+
+ if (pp == 0)
+ return(1);
+ strcpy(home, pp->pw_dir);
+ return(0);
+}
diff --git a/usr.bin/sup/src/ffilecopy.c b/usr.bin/sup/src/ffilecopy.c
new file mode 100644
index 00000000000..e6834239f5c
--- /dev/null
+++ b/usr.bin/sup/src/ffilecopy.c
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+/* ffilecopy -- very fast buffered file copy
+ *
+ * Usage: i = ffilecopy (here,there)
+ * int i;
+ * FILE *here, *there;
+ *
+ * Ffilecopy is a very fast routine to copy the rest of a buffered
+ * input file to a buffered output file. Here and there are open
+ * buffers for reading and writing (respectively); ffilecopy
+ * performs a file-copy faster than you should expect to do it
+ * yourself. Ffilecopy returns 0 if everything was OK; EOF if
+ * there was any error. Normally, the input file will be left in
+ * EOF state (feof(here) will return TRUE), and the output file will be
+ * flushed (i.e. all data on the file rather in the core buffer).
+ * It is not necessary to flush the output file before ffilecopy.
+ *
+ * HISTORY
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for VAX.
+ *
+ */
+
+#include <stdio.h>
+int filecopy();
+
+int ffilecopy (here,there)
+FILE *here, *there;
+{
+ register int i, herefile, therefile;
+
+ herefile = fileno(here);
+ therefile = fileno(there);
+
+ if (fflush (there) == EOF) /* flush pending output */
+ return (EOF);
+
+#if defined(__386BSD__) || defined(__NetBSD__)
+ if ((here->_r) > 0) { /* flush buffered input */
+ i = write (therefile, here->_p, here->_r);
+ if (i != here->_r) return (EOF);
+ here->_p = here->_bf._base;
+ here->_r = 0;
+ }
+#else
+ if ((here->_cnt) > 0) { /* flush buffered input */
+ i = write (therefile, here->_ptr, here->_cnt);
+ if (i != here->_cnt) return (EOF);
+ here->_ptr = here->_base;
+ here->_cnt = 0;
+ }
+#endif
+ i = filecopy (herefile, therefile); /* fast file copy */
+ if (i < 0) return (EOF);
+
+#if defined(__386BSD__) || defined(__NetBSD__)
+ (here->_flags) |= __SEOF; /* indicate EOF */
+#else
+ (here->_flag) |= _IOEOF; /* indicate EOF */
+#endif
+ return (0);
+}
diff --git a/usr.bin/sup/src/filecopy.c b/usr.bin/sup/src/filecopy.c
new file mode 100644
index 00000000000..553becb34cc
--- /dev/null
+++ b/usr.bin/sup/src/filecopy.c
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+/* filecopy -- copy a file from here to there
+ *
+ * Usage: i = filecopy (here,there);
+ * int i, here, there;
+ *
+ * Filecopy performs a fast copy of the file "here" to the
+ * file "there". Here and there are both file descriptors of
+ * open files; here is open for input, and there for output.
+ * Filecopy returns 0 if all is OK; -1 on error.
+ *
+ * I have performed some tests for possible improvements to filecopy.
+ * Using a buffer size of 10240 provides about a 1.5 times speedup
+ * over 512 for a file of about 200,000 bytes. Of course, other
+ * buffer sized should also work; this is a rather arbitrary choice.
+ * I have also tried inserting special startup code to attempt
+ * to align either the input or the output file to lie on a
+ * physical (512-byte) block boundary prior to the big loop,
+ * but this presents only a small (about 5% speedup, so I've
+ * canned that code. The simple thing seems to be good enough.
+ *
+ * HISTORY
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Rewritten for VAX; same as "filcopy" on PDP-11. Bigger buffer
+ * size (20 physical blocks) seems to be a big win; aligning things
+ * on block boundaries seems to be a negligible improvement at
+ * considerable cost in complexity.
+ *
+ */
+
+#define BUFFERSIZE 10240
+
+int filecopy (here,there)
+int here,there;
+{
+ register int kount;
+ char buffer[BUFFERSIZE];
+ kount = 0;
+ while (kount == 0 && (kount=read(here,buffer,BUFFERSIZE)) > 0)
+ kount -= write (there,buffer,kount);
+ return (kount ? -1 : 0);
+}
diff --git a/usr.bin/sup/src/libc.h b/usr.bin/sup/src/libc.h
new file mode 100644
index 00000000000..bac8444ec15
--- /dev/null
+++ b/usr.bin/sup/src/libc.h
@@ -0,0 +1,294 @@
+/*
+ * 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.
+ */
+/*
+ **********************************************************************
+ * HISTORY
+ * $Log: libc.h,v $
+ * Revision 1.1 1995/12/16 11:46:46 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.7 89/04/03 11:10:45 vanryzin
+ * Changed definition of qsort for c++ to indicate the procedure
+ * passed to qsort has parameters. Since we were unsure if ANSI C
+ * could handle the syntax I placed the new definition within #if
+ * defined(c_plusplus) conditionals. This may not be necessary
+ * and perhaps should be fixed at a later time.
+ * [89/04/03 vanryzin]
+ *
+ * Revision 1.6 89/02/05 15:55:57 gm0w
+ * Added extern char *errmsg().
+ * [89/02/04 gm0w]
+ *
+ * Revision 1.5 89/01/20 15:34:40 gm0w
+ * Moved all of the STDC changes to other existing include files
+ * back into this one. Added non-STDC extern declarations for
+ * all functions without int return values to match those defined
+ * by STDC. Added include of sysent.h. Removed obsolete cdate
+ * extern declaration.
+ * [88/12/17 gm0w]
+ *
+ * Revision 1.4 88/12/22 16:58:56 mja
+ * Correct __STDC__ parameter type for getenv().
+ * [88/12/20 dld]
+ *
+ * Revision 1.3 88/12/14 23:31:42 mja
+ * Made file reentrant. Added declarations for __STDC__.
+ * [88/01/06 jjk]
+ *
+ * 30-Apr-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added pathof() extern.
+ *
+ * 01-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added getname() extern.
+ *
+ * 29-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added lseek() extern.
+ *
+ * 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added salloc() extern.
+ *
+ * 14-Aug-81 Mike Accetta (mja) at Carnegie-Mellon University
+ * Created.
+ *
+ **********************************************************************
+ */
+
+#ifndef _LIBC_H_
+#define _LIBC_H_ 1
+
+#ifndef _TYPES_
+#include <sys/types.h>
+#endif /* _TYPES_ */
+
+#ifndef _SYSENT_H_
+#include <sysent.h>
+#endif /* _SYSENT_H_ */
+
+#ifndef FILE
+#include <stdio.h>
+#endif /* FILE */
+
+#ifndef _STRINGS_H_
+#include <strings.h>
+#endif /* _STRINGS_H_ */
+
+#ifndef _TIME_H_
+#include <time.h>
+#endif /* _TIME_H_ */
+
+/* CMU stdio additions */
+#if defined(__STDC__)
+extern FILE *fopenp(const char*, const char*, char*, char*);
+extern FILE *fwantread(const char*, const char*, const char*, const char*);
+extern FILE *fwantwrite(const char*, const char*, const char*, const char*,
+ int);
+#else /* __STDC__ */
+extern FILE *fopenp();
+extern FILE *fwantread();
+extern FILE *fwantwrite();
+#endif /* __STDC__ */
+
+/* CMU string routines */
+#if defined(__STDC__)
+extern char* foldup(char*, const char*);
+extern char* folddown(char*, const char*);
+extern char* sindex(const char*, const char*);
+extern char* skipto(const char*, const char*);
+extern char* skipover(const char*, const char*);
+extern char* nxtarg(char**, const char*);
+extern char _argbreak;
+extern char* getstr(const char*, char*, char*);
+extern int getstab(const char*, const char**, const char*);
+extern int getsearch(const char*, const char**, const char*);
+extern char* strarg(const char**, const char*, const char*, char*, char*);
+extern int stabarg(const char**, const char*, const char*, const char**,
+ const char*);
+extern int searcharg(const char**, const char*, const char*, const char**,
+ const char*);
+extern int getint(const char*, int, int, int);
+extern int intarg(const char**, const char*, const char*, int, int, int);
+extern long getlong(const char*, long, long, long);
+extern long longarg(const char**, const char*, const char*, long, long, long);
+extern short getshort(const char*, short, short, short);
+extern short shortarg(const char**, const char*, const char*,
+ short, short, short);
+extern float getfloat(const char*, float, float, float);
+extern float floatarg(const char**, const char*, const char*,
+ float, float, float);
+extern double getdouble(const char*, double, double, double);
+extern double doublearg(const char**, const char*, const char*,
+ double, double, double);
+extern unsigned int getoct(const char*, unsigned int, unsigned int,
+ unsigned int);
+extern unsigned int octarg(const char**, const char*, const char*,
+ unsigned int, unsigned int, unsigned int);
+extern unsigned int gethex(const char*, unsigned int, unsigned int,
+ unsigned int);
+extern unsigned int hexarg(const char**, const char*, const char*,
+ unsigned int, unsigned int, unsigned int);
+extern unsigned int atoo(const char*);
+extern unsigned int atoh(const char*);
+extern char *salloc(const char*);
+extern char *concat(const char*, int, ...);
+#else /* __STDC__ */
+extern char *foldup(), *folddown();
+extern char *sindex(), *skipto(), *skipover(), *nxtarg();
+extern char *getstr(), *strarg();
+extern long getlong(), longarg();
+extern short getshort(), shortarg();
+extern float getfloat(), floatarg();
+extern double getdouble(), doublearg();
+extern unsigned int getoct(), octarg(), gethex(), hexarg();
+extern unsigned int atoo(), atoh();
+extern char *salloc();
+extern char *concat();
+#endif /* __STDC__ */
+
+/* CMU library routines */
+#if defined(__STDC__)
+extern char *getname(int);
+extern char *pathof(char *);
+extern char *errmsg(int);
+#else /* __STDC__ */
+extern char *getname();
+extern char *pathof();
+extern char *errmsg();
+#endif /* __STDC__ */
+
+/* CMU time additions */
+#if defined(__STDC__)
+extern long gtime(const struct tm*);
+extern long atot(const char*);
+#else /* __STDC__ */
+extern long gtime();
+extern long atot();
+#endif /* __STDC__ */
+
+/* 4.3 BSD standard library routines; taken from man(3) */
+#if defined(__STDC__)
+typedef int (*PFI)();
+#if defined(c_plusplus)
+typedef int (*PFI2)(...);
+#endif /* c_plusplus */
+#if 0
+extern void abort(void);
+extern int abs(int);
+extern double atof(const char *);
+extern int atoi(const char *);
+extern long atol(const char *);
+extern void bcopy(const void *, void *, int);
+extern int bcmp(const void *, const void *, int);
+extern void bzero(void *, int);
+extern int ffs(int);
+extern char *crypt(const char *, const char *);
+extern void setkey(char *);
+extern void encrypt(char *, int);
+extern char *ecvt(double, int, int *, int *);
+extern char *fcvt(double, int, int *, int *);
+extern char *gcvt(double, int, char *);
+extern int execl(const char *, ...);
+extern int execv(const char *, const char **);
+extern int execle(const char *, ...);
+extern int exect(const char *, const char **, const char **);
+extern void exit(int);
+extern char *getenv(const char *);
+extern char *getlogin(void);
+extern int getopt(int, const char **, const char *);
+extern char *getpass(const char *);
+extern char *getusershell(void);
+extern void setusershell(void);
+extern void endusershell(void);
+extern char *getwd(char *);
+extern int initgroups(const char *, gid_t);
+extern void *malloc(unsigned);
+extern void free(void *);
+extern void *realloc(void *, unsigned);
+extern void *calloc(unsigned, unsigned);
+extern void *alloca(int);
+extern char *mktemp(char *);
+extern int mkstemp(char *);
+extern void monitor(PFI, PFI, short *, int, int);
+extern void monstartup(PFI, PFI);
+extern void moncontrol(int);
+extern int pause(void);
+#if defined(c_plusplus)
+extern void qsort(void *, int, int, PFI2);
+#else /* c_plusplus */
+extern void qsort(void *, int, int, PFI);
+#endif /* c_plusplus */
+extern long random(void);
+extern int srandom(int);
+extern void *initstate(unsigned, void *, int);
+extern void *setstate(void *);
+extern int rcmd(char **, int, const char *, const char *, const char *, int);
+extern int rresvport(int *);
+extern int ruserok(char *, int, const char *, const char *);
+extern char *re_comp(char *);
+extern int re_exec(char *);
+extern int rexec(char **, int, const char *, const char *, const char *,
+ int *);
+extern int setuid(uid_t);
+extern int seteuid(uid_t);
+extern int setruid(uid_t);
+extern int setgid(gid_t);
+extern int setegid(gid_t);
+extern int setrgid(gid_t);
+extern void sleep(unsigned);
+extern void swab(void *, void *, int);
+extern int system(const char *);
+extern char *ttyname(int);
+extern int isatty(int);
+extern int ttyslot(void);
+extern unsigned ualarm(unsigned, unsigned);
+extern void usleep(unsigned);
+#endif
+#else /* __STDC__ */
+extern double atof();
+extern long atol();
+extern char *crypt();
+extern char *ecvt();
+extern char *fcvt();
+extern char *gcvt();
+extern char *getenv();
+extern char *getlogin();
+extern char *getpass();
+extern char *getusershell();
+extern char *getwd();
+extern char *malloc();
+extern char *realloc();
+extern char *calloc();
+extern char *alloca();
+extern char *mktemp();
+extern long random();
+extern char *initstate();
+extern char *setstate();
+extern char *re_comp();
+extern char *ttyname();
+extern unsigned ualarm();
+#endif /* __STDC__ */
+#endif /* not _LIBC_H_ */
diff --git a/usr.bin/sup/src/log.c b/usr.bin/sup/src/log.c
new file mode 100644
index 00000000000..4a0ab60b8fa
--- /dev/null
+++ b/usr.bin/sup/src/log.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Logging support for SUP
+ **********************************************************************
+ * HISTORY
+ * $Log: log.c,v $
+ * Revision 1.1 1995/12/16 11:46:47 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.5 92/08/11 12:03:43 mrt
+ * Brad's delinting and variable argument list usage
+ * changes. Added copyright.
+ *
+ * Revision 1.3 89/08/15 15:30:37 bww
+ * Updated to use v*printf() in place of _doprnt().
+ * From "[89/04/19 mja]" at CMU.
+ * [89/08/15 bww]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added check to allow logopen() to be called multiple times.
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created.
+ *
+ **********************************************************************
+ */
+
+#include <stdio.h>
+#include <sys/syslog.h>
+#include <c.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "sup.h"
+
+#ifdef lint
+/*VARARGS1*//*ARGSUSED*/
+static void quit(status) {};
+#endif /* lint */
+
+static int opened = 0;
+
+logopen(program)
+char *program;
+{
+ if (opened) return;
+ openlog(program,LOG_PID,LOG_DAEMON);
+ opened++;
+}
+
+#if __STDC__
+logquit(int retval,char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+logquit(va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ int retval;
+ char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ va_list ap;
+
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ retval = va_arg(ap,int);
+ fmt = va_arg(ap,char *);
+#endif
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ if (opened) {
+ syslog (LOG_ERR,buf);
+ closelog ();
+ exit (retval);
+ }
+ quit (retval,"SUP: %s\n",buf);
+}
+
+#if __STDC__
+logerr(char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+logerr(va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ va_list ap;
+
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ fmt = va_arg(ap,char *);
+#endif
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ if (opened) {
+ syslog (LOG_ERR,buf);
+ return;
+ }
+ fprintf (stderr,"SUP: %s\n",buf);
+ (void) fflush (stderr);
+}
+
+#if __STDC__
+loginfo(char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+loginfo(va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ va_list ap;
+
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ fmt = va_arg(ap,char *);
+#endif
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ if (opened) {
+ syslog (LOG_INFO,buf);
+ return;
+ }
+ printf ("%s\n",buf);
+ (void) fflush (stdout);
+}
diff --git a/usr.bin/sup/src/netcryptvoid.c b/usr.bin/sup/src/netcryptvoid.c
new file mode 100644
index 00000000000..4676df945c5
--- /dev/null
+++ b/usr.bin/sup/src/netcryptvoid.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/**********************************************************************
+ * HISTORY
+ * $Log: netcryptvoid.c,v $
+ * Revision 1.1 1995/12/16 11:46:47 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 2.2 92/09/09 22:04:34 mrt
+ * Created.
+ * [92/09/09 mrt]
+ *
+ */
+/*
+ * DATA ENCRYPTION
+ * netcrypt (key) turn on/off encryption of strings and files
+ * char *key; encryption key
+ *
+ */
+
+/*
+ * Replacement for subroutine version of "crypt" program
+ * for foreign and non-BSD-licensed sites. With this code
+ * you can only run unencrypted sups
+ */
+
+#include <libc.h>
+#include "sup.h"
+#include "supmsg.h"
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+int cryptflag = 0; /* whether to encrypt/decrypt data */
+char *cryptbuf; /* buffer for data encryption/decryption */
+
+int netcrypt (pword)
+char *pword;
+{
+ if (pword == NULL || (strcmp(pword,PSWDCRYPT) == 0)) {
+ cryptflag = 0;
+ (void) getcryptbuf (0);
+ return (SCMOK);
+ }
+ return (SCMERR);
+}
+int getcryptbuf (x)
+int x;
+{
+ static int cryptsize = 0; /* size of current cryptbuf */
+
+ if (cryptflag == 0) {
+ return(SCMOK);
+ } else
+ return (SCMERR);
+}
+
+void decode (in,out,count)
+char *in,*out;
+int count;
+{
+}
+
+
+void encode (in,out,count)
+char *in,*out;
+int count;
+{
+}
diff --git a/usr.bin/sup/src/nxtarg.c b/usr.bin/sup/src/nxtarg.c
new file mode 100644
index 00000000000..9e93c2840ee
--- /dev/null
+++ b/usr.bin/sup/src/nxtarg.c
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+/*
+ * nxtarg -- strip off arguments from a string
+ *
+ * Usage: p = nxtarg (&q,brk);
+ * char *p,*q,*brk;
+ * extern char _argbreak;
+ *
+ * q is pointer to next argument in string
+ * after call, p points to string containing argument,
+ * q points to remainder of string
+ *
+ * Leading blanks and tabs are skipped; the argument ends at the
+ * first occurence of one of the characters in the string "brk".
+ * When such a character is found, it is put into the external
+ * variable "_argbreak", and replaced by a null character; if the
+ * arg string ends before that, then the null character is
+ * placed into _argbreak;
+ * If "brk" is 0, then " " is substituted.
+ *
+ * HISTORY
+ * 01-Jul-83 Steven Shafer (sas) at Carnegie-Mellon University
+ * Bug fix: added check for "back >= front" in loop to chop trailing
+ * white space.
+ *
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Rewritten for VAX. By popular demand, a table of break characters
+ * has been added (implemented as a string passed into nxtarg).
+ *
+ * Originally from klg (Ken Greer); IUS/SUS UNIX.
+ */
+
+char _argbreak;
+char *skipto();
+
+char *nxtarg (q,brk)
+char **q,*brk;
+{
+ register char *front,*back;
+ front = *q; /* start of string */
+ /* leading blanks and tabs */
+ while (*front && (*front == ' ' || *front == '\t')) front++;
+ /* find break character at end */
+ if (brk == 0) brk = " ";
+ back = skipto (front,brk);
+ _argbreak = *back;
+ *q = (*back ? back+1 : back); /* next arg start loc */
+ /* elim trailing blanks and tabs */
+ back -= 1;
+ while ((back >= front) && (*back == ' ' || *back == '\t')) back--;
+ back++;
+ if (*back) *back = '\0';
+ return (front);
+}
diff --git a/usr.bin/sup/src/path.c b/usr.bin/sup/src/path.c
new file mode 100644
index 00000000000..f9822689dc8
--- /dev/null
+++ b/usr.bin/sup/src/path.c
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+/* path -- break filename into directory and file
+ *
+ * path (filename,direc,file);
+ * char *filename,*direc,*file;
+ * filename is input; direc and file are output (user-supplied).
+ * file will not have any trailing /; direc might.
+ *
+ * Note these rules:
+ * 1. trailing / are ignored (except as first character)
+ * 2. x/y is x;y where y contains no / (x may contain /)
+ * 3. /y is /;y where y contains no /
+ * 4. y is .;y where y contains no /
+ * 5. is .;. (null filename)
+ * 6. / is /;. (the root directory)
+ *
+ * Algorithm is this:
+ * 1. delete trailing / except in first position
+ * 2. if any /, find last one; change to null; y++
+ * else y = x; (x is direc; y is file)
+ * 3. if y is null, y = .
+ * 4. if x equals y, x = .
+ * else if x is null, x = /
+ *
+ * HISTORY
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Copied verbatim from PDP-11. Still as messy as ever.
+ * Some people have asked for a modification (I think that's a better
+ * idea than a new routine) which will change the directory name
+ * into an absolute pathname if it isn't one already. The change
+ * involves doing a getwd() and prepending that if appropriate, with
+ * a "/" in between that and the directory part of the path.
+ * If you want to be cute, you can also resolve ".."s at that time.
+ *
+ */
+
+path (original,direc,file)
+char *original,*direc,*file;
+{
+ register char *y;
+ /* x is direc */
+ register char *p;
+
+ /* copy and note the end */
+ p = original;
+ y = direc;
+ while (*y++ = *p++) ; /* copy string */
+ /* y now points to first char after null */
+ --y; /* y now points to null */
+ --y; /* y now points to last char of string before null */
+
+ /* chop off trailing / except as first character */
+ while (y>direc && *y == '/') --y; /* backpedal past / */
+ /* y now points to char before first trailing / or null */
+ *(++y) = 0; /* chop off end of string */
+ /* y now points to null */
+
+ /* find last /, if any. If found, change to null and bump y */
+ while (y>direc && *y != '/') --y;
+ /* y now points to / or direc. Note *direc may be / */
+ if (*y == '/') {
+ *y++ = 0;
+ }
+
+ /* find file name part */
+ if (*y) strcpy (file,y);
+ else strcpy (file,".");
+
+ /* find directory part */
+ if (direc == y) strcpy (direc,".");
+ else if (*direc == 0) strcpy (direc,"/");
+ /* else direc already has proper value */
+}
diff --git a/usr.bin/sup/src/quit.c b/usr.bin/sup/src/quit.c
new file mode 100644
index 00000000000..e867c8b2d6a
--- /dev/null
+++ b/usr.bin/sup/src/quit.c
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+/*
+ * quit -- print message and exit
+ *
+ * Usage: quit (status,format [,arg]...);
+ * int status;
+ * (... format and arg[s] make up a printf-arglist)
+ *
+ * Quit is a way to easily print an arbitrary message and exit.
+ * It is most useful for error exits from a program:
+ * if (open (...) < 0) then quit (1,"Can't open...",file);
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: quit.c,v $
+ * Revision 1.1 1995/12/16 11:46:49 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.2 88/12/13 13:52:41 gm0w
+ * Rewritten to use varargs.
+ * [88/12/13 gm0w]
+ *
+ **********************************************************************
+ */
+
+#include <stdio.h>
+#include <varargs.h>
+
+quit (status, fmt, va_alist)
+int status;
+char *fmt;
+va_dcl
+{
+ va_list args;
+
+ fflush(stdout);
+ va_start(args);
+ (void) vfprintf(stderr, fmt, args);
+ va_end(args);
+ exit(status);
+}
diff --git a/usr.bin/sup/src/run.c b/usr.bin/sup/src/run.c
new file mode 100644
index 00000000000..7f625c1d27c
--- /dev/null
+++ b/usr.bin/sup/src/run.c
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+/* run, runv, runp, runvp -- execute process and wait for it to exit
+ *
+ * Usage:
+ * i = run (file, arg1, arg2, ..., argn, 0);
+ * i = runv (file, arglist);
+ * i = runp (file, arg1, arg2, ..., argn, 0);
+ * i = runvp (file, arglist);
+ * i = runio (argv, in, out, err);
+ *
+ * Run, runv, runp and runvp have argument lists exactly like the
+ * corresponding routines, execl, execv, execlp, execvp. The run
+ * routines perform a fork, then:
+ * IN THE NEW PROCESS, an execl[p] or execv[p] is performed with the
+ * specified arguments. The process returns with a -1 code if the
+ * exec was not successful.
+ * IN THE PARENT PROCESS, the signals SIGQUIT and SIGINT are disabled,
+ * the process waits until the newly forked process exits, the
+ * signals are restored to their original status, and the return
+ * status of the process is analyzed.
+ * All run routines return: -1 if the exec failed or if the child was
+ * terminated abnormally; otherwise, the exit code of the child is
+ * returned.
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: run.c,v $
+ * Revision 1.1 1995/12/16 11:46:49 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1995/06/24 16:21:33 christos
+ * - Don't use system(3) to fork processes. It is a big security hole.
+ * - Encode the filenames in the scan files using strvis(3), so filenames
+ * that contain newlines or other weird characters don't break the scanner.
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.1 89/10/14 19:53:39 rvb
+ * Initial revision
+ *
+ * Revision 1.2 89/08/03 14:36:46 mja
+ * Update run() and runp() to use <varargs.h>.
+ * [89/04/19 mja]
+ *
+ * 23-Sep-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Merged old runv and runvp modules.
+ *
+ * 22-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added check and kill if child process was stopped.
+ *
+ * 30-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Adapted for 4.2 BSD UNIX: Conforms to new signals and wait.
+ *
+ * 15-July-82 Mike Accetta (mja) and Neal Friedman (naf)
+ * at Carnegie-Mellon University
+ * Added a return(-1) if vfork fails. This should only happen
+ * if there are no more processes available.
+ *
+ * 28-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Added setuid and setgid for system programs' use.
+ *
+ * 21-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University
+ * Changed fork to vfork.
+ *
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for VAX. The proper way to fork-and-execute a system
+ * program is now by "runvp" or "runp", with the program name
+ * (rather than an absolute pathname) as the first argument;
+ * that way, the "PATH" variable in the environment does the right
+ * thing. Too bad execvp and execlp (hence runvp and runp) don't
+ * accept a pathlist as an explicit argument.
+ *
+ **********************************************************************
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <varargs.h>
+
+#ifndef __STDC__
+#ifndef const
+#define const
+#endif
+#endif
+
+static int dorun();
+
+int run (name,va_alist)
+char *name;
+va_dcl
+{
+ int val;
+ va_list ap;
+
+ va_start(ap);
+ val = runv (name,ap);
+ va_end(ap);
+ return(val);
+}
+
+int runv (name,argv)
+char *name,**argv;
+{
+ return (dorun (name, argv, 0));
+}
+
+int runp (name,va_alist)
+char *name;
+va_dcl
+{
+ int val;
+ va_list ap;
+
+ va_start(ap);
+ val = runvp (name,ap);
+ va_end(ap);
+ return (val);
+}
+
+int runvp (name,argv)
+char *name,**argv;
+{
+ return (dorun (name, argv, 1));
+}
+
+static
+int dorun (name,argv,usepath)
+char *name,**argv;
+int usepath;
+{
+ int wpid;
+ register int pid;
+ struct sigvec ignoresig,intsig,quitsig;
+ union wait status;
+ int execvp(), execv();
+ int (*execrtn)() = usepath ? execvp : execv;
+
+ if ((pid = vfork()) == -1)
+ return(-1); /* no more process's, so exit with error */
+
+ if (pid == 0) { /* child process */
+ setgid (getgid());
+ setuid (getuid());
+ (*execrtn) (name,argv);
+ fprintf (stderr,"run: can't exec %s\n",name);
+ _exit (0377);
+ }
+
+ ignoresig.sv_handler = SIG_IGN; /* ignore INT and QUIT signals */
+ ignoresig.sv_mask = 0;
+ ignoresig.sv_onstack = 0;
+ sigvec (SIGINT,&ignoresig,&intsig);
+ sigvec (SIGQUIT,&ignoresig,&quitsig);
+ do {
+ wpid = wait3 (&status.w_status, WUNTRACED, 0);
+ if (WIFSTOPPED (status)) {
+ kill (0,SIGTSTP);
+ wpid = 0;
+ }
+ } while (wpid != pid && wpid != -1);
+ sigvec (SIGINT,&intsig,0); /* restore signals */
+ sigvec (SIGQUIT,&quitsig,0);
+
+ if (WIFSIGNALED (status) || status.w_retcode == 0377)
+ return (-1);
+
+ return (status.w_retcode);
+}
+
+/*
+ * Like system(3), but with an argument list and explicit redirections
+ * that does not use the shell
+ */
+int
+runio(argv, infile, outfile, errfile)
+ char *const argv[];
+ const char *infile;
+ const char *outfile;
+ const char *errfile;
+{
+ int fd;
+ pid_t pid;
+ int status;
+
+ switch ((pid = fork())) {
+ case -1:
+ return -1;
+
+ case 0:
+ if (infile) {
+ (void) close(0);
+ if ((fd = open(infile, O_RDONLY)) == -1)
+ exit(1);
+ if (fd != 0)
+ (void) dup2(fd, 0);
+ }
+
+ if (outfile) {
+ (void) close(1);
+ if ((fd = open(outfile, O_RDWR|O_CREAT|O_TRUNC,
+ 0666)) == -1)
+ exit(1);
+ if (fd != 1)
+ (void) dup2(fd, 1);
+ }
+
+ if (errfile) {
+ (void) close(2);
+ if ((fd = open(errfile, O_RDWR|O_CREAT|O_TRUNC,
+ 0666)) == -1)
+ exit(1);
+ if (fd != 2)
+ (void) dup2(fd, 2);
+ }
+
+ execvp(argv[0], argv);
+ exit(1);
+ /*NOTREACHED*/
+ return 0;
+
+ default:
+ if (waitpid(pid, &status, 0) == -1)
+ return -1;
+ return status;
+ }
+}
diff --git a/usr.bin/sup/src/salloc.c b/usr.bin/sup/src/salloc.c
new file mode 100644
index 00000000000..bd0e804251f
--- /dev/null
+++ b/usr.bin/sup/src/salloc.c
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+/*
+ **********************************************************************
+ * HISTORY
+ * 09-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed to save length and use bcopy instead of strcpy.
+ *
+ * 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created from routine by same name in Steve Shafer's sup program.
+ *
+ **********************************************************************
+ */
+char *malloc();
+
+char *salloc(p)
+char *p;
+{
+ register char *q;
+ register int l;
+
+ q = malloc(l = strlen(p) + 1);
+ if (q != 0)
+ bcopy(p, q, l);
+ return(q);
+}
diff --git a/usr.bin/sup/src/scan.c b/usr.bin/sup/src/scan.c
new file mode 100644
index 00000000000..8e634e291bd
--- /dev/null
+++ b/usr.bin/sup/src/scan.c
@@ -0,0 +1,1024 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * scan.c - sup list file scanner
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: scan.c,v $
+ * Revision 1.1 1995/12/16 11:46:50 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.4 1995/10/29 23:54:45 christos
+ * - runio fails when result != 0 not only < 0
+ * - print vis-encoded file in the scanner.
+ *
+ * Revision 1.3 1995/06/24 16:21:42 christos
+ * - Don't use system(3) to fork processes. It is a big security hole.
+ * - Encode the filenames in the scan files using strvis(3), so filenames
+ * that contain newlines or other weird characters don't break the scanner.
+ *
+ * Revision 1.2 1994/01/03 14:47:25 brezak
+ * Change <sys/dir.h> to <dirent.h>
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.8 92/08/11 12:04:28 mrt
+ * Brad's changes: delinted, added forward declarations of static
+ * functions.Added Copyright.
+ * [92/07/24 mrt]
+ *
+ * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added host=<hostfile> support to releases file.
+ *
+ * 11-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added "rsymlink" recursive symbolic link quoting directive.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support.
+ *
+ * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Lets see if we'll be able to write the scan file BEFORE
+ * we collect the data for it. Include sys/file.h and use
+ * new definitions for access check codes.
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added type casting information for lint.
+ *
+ * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added check for newonly upgrade when lasttime is the same as
+ * scantime. This will save us the trouble of parsing the scanfile
+ * when the client has successfully received everything in the
+ * scanfile already.
+ *
+ * 16-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Clear Texec pointers in execT so that Tfree of execT will not
+ * free command trees associated with files in listT.
+ *
+ * 06-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to omit scanned files from list if we want new files
+ * only and they are old.
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Major rewrite for protocol version 4. Added version numbers to
+ * scan file. Also added mode of file in addition to flags.
+ * Execute commands are now immediately after file information.
+ *
+ * 13-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added comments to list file format.
+ *
+ * 08-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to implement omitany. Currently doesn't know about
+ * {a,b,c} patterns.
+ *
+ * 07-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#include <c.h>
+#include <vis.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#ifdef HAS_POSIX_DIR
+#include <dirent.h>
+#else
+#include <sys/dir.h>
+#endif
+#include <sys/file.h>
+#include "sup.h"
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+#define SPECNUMBER 1000
+ /* number of filenames produced by a single spec in the list file */
+
+/*******************************************
+ *** D A T A S T R U C T U R E S ***
+ *******************************************/
+
+typedef enum { /* release options */
+ ONEXT, OPREFIX, OLIST, OSCAN,
+ OHOST
+} OPTION;
+
+static char *options[] = {
+ "next", "prefix", "list", "scan",
+ "host",
+ 0
+};
+
+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
+};
+
+#define FALWAYS FUPDATE
+
+/* list file lines */
+static TREE *upgT; /* files to upgrade */
+static TREE *flagsT; /* special flags: BACKUP NOACCT */
+static TREE *omitT; /* recursize file omition list */
+static TREE *omanyT; /* non-recursize file omition list */
+static TREE *symT; /* symbolic links to quote */
+static TREE *rsymT; /* recursive symbolic links to quote */
+static TREE *execT; /* execute command list */
+
+/*************************
+ *** E X T E R N ***
+ *************************/
+
+#ifdef lint
+static char _argbreak;
+#else
+extern char _argbreak; /* break character from nxtarg */
+#endif
+
+extern TREELIST *listTL; /* list of trees for scanning */
+extern TREE *listT; /* final list of files in collection */
+extern TREE *refuseT; /* files refused by client */
+
+extern char *collname; /* collection name */
+extern char *basedir; /* base directory name */
+extern char *prefix; /* collection pathname prefix */
+extern long lasttime; /* time of last upgrade */
+extern long scantime; /* time of this scan */
+extern int trace; /* trace directories */
+extern int newonly; /* new files only */
+
+#ifdef RCSSTAT
+extern char *rcs_branch;
+extern int candorcs;
+#endif
+
+extern long time();
+
+/*************************************************
+ *** STATIC R O U T I N E S ***
+ *************************************************/
+
+static makescan();
+static getscan();
+static doscan();
+static readlistfile();
+static expTinsert();
+static listone();
+static listentry();
+static listname();
+static listdir();
+static omitanyone();
+static anyglob();
+static int getscanfile();
+static chkscanfile();
+static makescanfile();
+static recordone();
+static recordexec();
+
+/*************************************************
+ *** L I S T S C A N R O U T I N E S ***
+ *************************************************/
+
+static
+passdelim (ptr,delim) /* skip over delimiter */
+char **ptr,delim;
+{
+ *ptr = skipover (*ptr, " \t");
+ if (_argbreak != delim && **ptr == delim) {
+ (*ptr)++;
+ *ptr = skipover (*ptr, " \t");
+ }
+}
+
+static
+char *parserelease(tlp,relname,args)
+TREELIST **tlp;
+char *relname,*args;
+{
+ register TREELIST *tl;
+ register char *arg;
+ register OPTION option;
+ int opno;
+ char *nextrel;
+
+ tl = (TREELIST *) malloc (sizeof(TREELIST));
+ if ((*tlp = tl) == NULL)
+ goaway ("Couldn't allocate TREELIST");
+ tl->TLnext = NULL;
+ tl->TLname = salloc (relname);
+ tl->TLprefix = NULL;
+ tl->TLlist = NULL;
+ tl->TLscan = NULL;
+ tl->TLhost = NULL;
+ nextrel = NULL;
+ args = skipover (args," \t");
+ while (*(arg=nxtarg(&args," \t="))) {
+ for (opno = 0; options[opno] != NULL; opno++)
+ if (strcmp (arg,options[opno]) == 0)
+ break;
+ if (options[opno] == NULL)
+ goaway ("Invalid release option %s for release %s",
+ arg,relname);
+ option = (OPTION) opno;
+ switch (option) {
+ case ONEXT:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ nextrel = salloc (arg);
+ break;
+ case OPREFIX:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ tl->TLprefix = salloc (arg);
+ break;
+ case OLIST:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ tl->TLlist = salloc (arg);
+ break;
+ case OSCAN:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ tl->TLscan = salloc (arg);
+ break;
+ case OHOST:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ tl->TLhost = salloc (arg);
+ break;
+ }
+ }
+ return (nextrel);
+}
+
+getrelease (release)
+char *release;
+{
+ TREELIST *tl;
+ char buf[STRINGLENGTH];
+ char *p,*q;
+ int rewound;
+ FILE *f;
+
+ if (release == NULL)
+ release = salloc (DEFRELEASE);
+ listTL = NULL;
+
+ (void) sprintf (buf,FILERELEASES,collname);
+ f = fopen (buf,"r");
+ if (f != NULL) {
+ rewound = TRUE;
+ for (;;) {
+ p = fgets (buf,sizeof(buf),f);
+ if (p == NULL) {
+ if (rewound)
+ break;
+ rewind (f);
+ rewound = TRUE;
+ continue;
+ }
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t");
+ if (strcmp (q,release) != 0)
+ continue;
+ release = parserelease (&tl,release,p);
+ if (tl->TLprefix == NULL)
+ tl->TLprefix = prefix;
+ else if (chdir (tl->TLprefix) < 0)
+ return (FALSE);
+ else
+ (void) chdir (basedir);
+ tl->TLnext = listTL;
+ listTL = tl;
+ if (release == NULL)
+ break;
+ rewound = FALSE;
+ }
+ (void) fclose (f);
+ }
+ if (release == NULL)
+ return (TRUE);
+ if (strcmp (release,DEFRELEASE) != 0)
+ return (FALSE);
+ (void) parserelease (&tl,release,"");
+ tl->TLprefix = prefix;
+ tl->TLnext = listTL;
+ listTL = tl;
+ return (TRUE);
+}
+
+makescanlists ()
+{
+ TREELIST *tl;
+ char buf[STRINGLENGTH];
+ char *p,*q;
+ FILE *f;
+ char *saveprefix = prefix;
+ int count = 0;
+
+ (void) sprintf (buf,FILERELEASES,collname);
+ f = fopen (buf,"r");
+ if (f != NULL) {
+ while (p = fgets (buf,sizeof(buf),f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t");
+ (void) parserelease (&tl,q,p);
+ if ((prefix = tl->TLprefix) == NULL)
+ prefix = saveprefix;
+ if (prefix != NULL) {
+ if (chdir (prefix) < 0)
+ goaway ("Can't chdir to %s",prefix);
+ (void) chdir (basedir);
+ }
+ makescan (tl->TLlist,tl->TLscan);
+ free ((char *)tl);
+ count++;
+ }
+ (void) fclose (f);
+ }
+ if (count == 0)
+ makescan ((char *)NULL,(char *)NULL);
+}
+
+static
+scanone (t)
+register TREE *t;
+{
+ register TREE *newt;
+
+ 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;
+ return (SCMOK);
+}
+
+getscanlists ()
+{
+ TREELIST *tl,*stl;
+
+ stl = listTL;
+ listTL = NULL;
+ while ((tl = stl) != NULL) {
+ prefix = tl->TLprefix;
+ getscan (tl->TLlist,tl->TLscan);
+ tl->TLtree = listT;
+ stl = tl->TLnext;
+ tl->TLnext = listTL;
+ listTL = tl;
+ }
+ listT = NULL;
+ for (tl = listTL; tl != NULL; tl = tl->TLnext)
+ (void) Tprocess (tl->TLtree,scanone);
+}
+
+static
+makescan (listfile,scanfile)
+char *listfile,*scanfile;
+{
+ listT = NULL;
+ chkscanfile (scanfile); /* can we can write a scan file? */
+ doscan (listfile); /* read list file and scan disk */
+ makescanfile (scanfile); /* record names in scan file */
+ Tfree (&listT); /* free file list tree */
+}
+
+static
+getscan (listfile,scanfile)
+char *listfile,*scanfile;
+{
+ struct tm *utc_time;
+
+ listT = NULL;
+ if (!getscanfile(scanfile)) { /* check for pre-scanned file list */
+ scantime = time ((long *)NULL);
+ doscan (listfile); /* read list file and scan disk */
+ }
+}
+
+static
+doscan (listfile)
+ char *listfile;
+{
+ char buf[STRINGLENGTH];
+ int listone ();
+
+ upgT = NULL;
+ flagsT = NULL;
+ omitT = NULL;
+ omanyT = NULL;
+ execT = NULL;
+ symT = NULL;
+ rsymT = NULL;
+ if (listfile == NULL)
+ listfile = FILELISTDEF;
+ (void) sprintf (buf,FILELIST,collname,listfile);
+ readlistfile (buf); /* get contents of list file */
+ (void) Tprocess (upgT,listone); /* build list of files specified */
+ cdprefix ((char *)NULL);
+ Tfree (&upgT);
+ Tfree (&flagsT);
+ Tfree (&omitT);
+ Tfree (&omanyT);
+ Tfree (&execT);
+ Tfree (&symT);
+ Tfree (&rsymT);
+}
+
+static
+readlistfile (fname)
+char *fname;
+{
+ char buf[STRINGLENGTH+MAXPATHLEN*4+1],*p;
+ register char *q,*r;
+ register FILE *f;
+ register int ltn,n,i,flags;
+ register TREE **t;
+ register LISTTYPE lt;
+ char *speclist[SPECNUMBER];
+
+ f = fopen (fname,"r");
+ if (f == NULL) goaway ("Can't read list file %s",fname);
+ cdprefix (prefix);
+ while (p = fgets (buf,sizeof(buf),f)) {
+ if (q = index (p,'\n')) *q = '\0';
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t");
+ if (*q == '\0') continue;
+ for (ltn = 0; ltname[ltn] && strcmp(q,ltname[ltn]) != 0; ltn++);
+ if (ltname[ltn] == NULL)
+ goaway ("Invalid list file keyword %s",q);
+ lt = (LISTTYPE) ltn;
+ flags = 0;
+ switch (lt) {
+ case LUPGRADE:
+ t = &upgT;
+ break;
+ case LBACKUP:
+ t = &flagsT;
+ flags = FBACKUP;
+ break;
+ case LNOACCT:
+ t = &flagsT;
+ flags = FNOACCT;
+ break;
+ case LSYMLINK:
+ t = &symT;
+ break;
+ case LRSYMLINK:
+ t = &rsymT;
+ break;
+ case LOMIT:
+ t = &omitT;
+ break;
+ case LOMITANY:
+ t = &omanyT;
+ break;
+ case LALWAYS:
+ t = &upgT;
+ flags = FALWAYS;
+ break;
+ case LINCLUDE:
+ while (*(q=nxtarg(&p," \t"))) {
+ cdprefix ((char *)NULL);
+ n = expand (q,speclist,SPECNUMBER);
+ for (i = 0; i < n && i < SPECNUMBER; i++) {
+ readlistfile (speclist[i]);
+ cdprefix ((char *)NULL);
+ free (speclist[i]);
+ }
+ cdprefix (prefix);
+ }
+ continue;
+ case LEXECUTE:
+ r = p = q = skipover (p," \t");
+ do {
+ q = p = skipto (p," \t(");
+ p = skipover (p," \t");
+ } while (*p != '(' && *p != '\0');
+ if (*p++ == '(') {
+ *q = '\0';
+ do {
+ q = nxtarg (&p," \t)");
+ if (*q == 0)
+ _argbreak = ')';
+ else
+ expTinsert (q,&execT,0,r);
+ } while (_argbreak != ')');
+ continue;
+ }
+ /* fall through */
+ default:
+ goaway ("Error in handling list file keyword %d",ltn);
+ }
+ 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];
+
+ n = expand (p,speclist,SPECNUMBER);
+ for (i = 0; i < n && i < SPECNUMBER; i++) {
+ 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);
+}
+
+static
+listentry(name,fullname,updir,always)
+register char *name, *fullname, *updir;
+int always;
+{
+ struct stat statbuf;
+ int link = 0;
+ int omitanyone ();
+
+ if (Tlookup (refuseT,fullname)) return;
+ if (!always) {
+ if (Tsearch (omitT,fullname)) return;
+ if (Tprocess (omanyT,omitanyone,fullname) != SCMOK)
+ return;
+ }
+ if (lstat(name,&statbuf) < 0)
+ return;
+ if ((statbuf.st_mode&S_IFMT) == S_IFLNK) {
+ if (Tsearch (symT,fullname)) {
+ listname (fullname,&statbuf);
+ return;
+ }
+ if (Tlookup (rsymT,fullname)) {
+ listname (fullname,&statbuf);
+ return;
+ }
+ if (updir) link++;
+ if (stat(name,&statbuf) < 0) return;
+ }
+ if ((statbuf.st_mode&S_IFMT) == S_IFDIR) {
+ if (access(name,R_OK|X_OK) < 0) return;
+ if (chdir(name) < 0) return;
+ listname (fullname,&statbuf);
+ if (trace) {
+ printf ("Scanning directory %s\n",fullname);
+ (void) fflush (stdout);
+ }
+ listdir (fullname,always);
+ if (updir == 0 || link) {
+ (void) chdir (basedir);
+ if (prefix) (void) chdir (prefix);
+ if (updir && *updir) (void) chdir (updir);
+ } else
+ (void) chdir ("..");
+ return;
+ }
+ if (access(name,R_OK) < 0) return;
+#ifdef RCSSTAT
+ if (candorcs) {
+ char rcs_release[STRINGLENGTH];
+ int status;
+ 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, name, rcs_file);
+#else
+ status = runp("rcsstat", "rcsstat", "-q", rcs_release, name, 0);
+#endif
+ if (status != 0) return;
+ }
+#endif
+ listname (fullname,&statbuf);
+}
+
+static
+listname (name,st)
+register char *name;
+register struct stat *st;
+{
+ register TREE *t,*ts;
+ register int new;
+ register TREELIST *tl;
+
+ new = st->st_ctime > lasttime;
+ if (newonly && !new) {
+ for (tl = listTL; tl != NULL; tl = tl->TLnext)
+ if (ts = Tsearch (tl->TLtree,name))
+ ts->Tflags &= ~FNEW;
+ return;
+ }
+ t = Tinsert (&listT,name,FALSE);
+ if (t == NULL) return;
+ t->Tmode = st->st_mode;
+ 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;
+ }
+}
+
+static
+listdir (name,always) /* expand directory */
+char *name;
+int always;
+{
+#ifdef HAS_POSIX_DIR
+ struct dirent *dentry;
+#else
+ struct direct *dentry;
+#endif
+ register DIR *dirp;
+ char ename[STRINGLENGTH],newname[STRINGLENGTH],filename[STRINGLENGTH];
+ register char *p,*newp;
+ register int i;
+
+ dirp = opendir (".");
+ if (dirp == 0) return; /* unreadable: probably protected */
+
+ p = name; /* punt leading ./ and trailing / */
+ newp = newname;
+ if (p[0] == '.' && p[1] == '/') {
+ p += 2;
+ while (*p == '/') p++;
+ }
+ while (*newp++ = *p++) ; /* copy string */
+ --newp; /* trailing null */
+ while (newp > newname && newp[-1] == '/') --newp; /* trailing / */
+ *newp = 0;
+ if (strcmp (newname,".") == 0) newname[0] = 0; /* "." ==> "" */
+
+ while (dentry=readdir(dirp)) {
+ if (dentry->d_ino == 0) continue;
+ if (strcmp(dentry->d_name,".") == 0) continue;
+ if (strcmp(dentry->d_name,"..") == 0) continue;
+ for (i=0; i<=MAXNAMLEN && dentry->d_name[i]; i++)
+ ename[i] = dentry->d_name[i];
+ ename[i] = 0;
+ if (*newname)
+ (void) sprintf (filename,"%s/%s",newname,ename);
+ else
+ (void) strcpy (filename,ename);
+ listentry(ename,filename,newname,always);
+ }
+ closedir (dirp);
+}
+
+static
+omitanyone (t,filename)
+TREE *t;
+char **filename;
+{
+ if (anyglob (t->Tname,*filename))
+ return (SCMERR);
+ return (SCMOK);
+}
+
+static
+anyglob (pattern,match)
+char *pattern,*match;
+{
+ register char *p,*m;
+ register char *pb,*pe;
+
+ p = pattern;
+ m = match;
+ while (*m && *p == *m ) {
+ p++;
+ m++;
+ }
+ if (*p == '\0' && *m == '\0')
+ return (TRUE);
+ switch (*p++) {
+ case '*':
+ for (;;) {
+ if (*p == '\0')
+ return (TRUE);
+ if (*m == '\0')
+ return (*p == '\0');
+ if (anyglob (p,++m))
+ return (TRUE);
+ }
+ case '?':
+ return (anyglob (p,++m));
+ case '[':
+ pb = p;
+ while (*(++p) != ']')
+ if (*p == '\0')
+ return (FALSE);
+ pe = p;
+ for (p = pb + 1; p != pe; p++) {
+ switch (*p) {
+ case '-':
+ if (p == pb && *m == '-') {
+ p = pe + 1;
+ return (anyglob (p,++m));
+ }
+ if (p == pb)
+ continue;
+ if ((p + 1) == pe)
+ return (FALSE);
+ if (*m > *(p - 1) &&
+ *m <= *(p + 1)) {
+ p = pe + 1;
+ return (anyglob (p,++m));
+ }
+ continue;
+ default:
+ if (*m == *p) {
+ p = pe + 1;
+ return (anyglob (p,++m));
+ }
+ }
+ }
+ return (FALSE);
+ default:
+ return (FALSE);
+ }
+}
+
+/*****************************************
+ *** R E A D S C A N F I L E ***
+ *****************************************/
+
+static
+int getscanfile (scanfile)
+char *scanfile;
+{
+ char buf[STRINGLENGTH];
+ char fname[MAXPATHLEN];
+ struct stat sbuf;
+ register FILE *f;
+ TREE ts;
+ register char *p,*q;
+ register TREE *tmp, *t = NULL;
+ register notwanted;
+ register TREELIST *tl;
+
+ if (scanfile == NULL)
+ scanfile = FILESCANDEF;
+ (void) sprintf (buf,FILESCAN,collname,scanfile);
+ if (stat(buf,&sbuf) < 0)
+ return (FALSE);
+ if ((f = fopen (buf,"r")) == NULL)
+ return (FALSE);
+ if ((p = fgets (buf,sizeof(buf),f)) == NULL) {
+ (void) fclose (f);
+ return (FALSE);
+ }
+ if (q = index (p,'\n')) *q = '\0';
+ if (*p++ != 'V') {
+ (void) fclose (f);
+ return (FALSE);
+ }
+ if (atoi (p) != SCANVERSION) {
+ (void) fclose (f);
+ return (FALSE);
+ }
+ scantime = sbuf.st_mtime; /* upgrade time is time of supscan,
+ * i.e. time of creation of scanfile */
+ if (newonly && scantime == lasttime) {
+ (void) fclose (f);
+ return (TRUE);
+ }
+ notwanted = FALSE;
+ while (p = fgets (buf,sizeof(buf),f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ ts.Tflags = 0;
+ if (*p == 'X') {
+ if (notwanted) continue;
+ if (t == NULL)
+ goaway ("scanfile format inconsistant");
+ (void) Tinsert (&t->Texec,++p,FALSE);
+ continue;
+ }
+ notwanted = FALSE;
+ if (*p == 'B') {
+ p++;
+ ts.Tflags |= FBACKUP;
+ }
+ if (*p == 'N') {
+ p++;
+ ts.Tflags |= FNOACCT;
+ }
+ if ((q = index (p,' ')) == NULL)
+ goaway ("scanfile format inconsistant");
+ *q++ = '\0';
+ ts.Tmode = atoo (p);
+ p = q;
+ if ((q = index (p,' ')) == NULL)
+ goaway ("scanfile format inconsistant");
+ *q++ = '\0';
+ ts.Tctime = atoi (p);
+ p = q;
+ if ((q = index (p,' ')) == NULL)
+ goaway ("scanfile format inconsistant");
+ *q++ = 0;
+ ts.Tmtime = atoi (p);
+ (void) strunvis(fname, q);
+ if (ts.Tctime > lasttime)
+ ts.Tflags |= FNEW;
+ else if (newonly) {
+ for (tl = listTL; tl != NULL; tl = tl->TLnext)
+ if (tmp = Tsearch (tl->TLtree,fname))
+ tmp->Tflags &= ~FNEW;
+ notwanted = TRUE;
+ continue;
+ }
+ if (Tlookup (refuseT,fname)) {
+ notwanted = TRUE;
+ continue;
+ }
+ t = Tinsert (&listT,fname,TRUE);
+ t->Tmode = ts.Tmode;
+ t->Tflags = ts.Tflags;
+ t->Tctime = ts.Tctime;
+ t->Tmtime = ts.Tmtime;
+ }
+ (void) fclose (f);
+ return (TRUE);
+}
+
+/*******************************************
+ *** W R I T E S C A N F I L E ***
+ *******************************************/
+
+static chkscanfile (scanfile)
+char *scanfile;
+{
+ char tname[STRINGLENGTH], fname[STRINGLENGTH];
+ FILE *f;
+
+ if (scanfile == NULL)
+ scanfile = FILESCANDEF;
+ (void) sprintf (fname,FILESCAN,collname,scanfile);
+ (void) sprintf (tname,"%s.temp",fname);
+ if (NULL == (f = fopen (tname, "w")))
+ goaway ("Can't test scan file temp %s for %s",tname,collname);
+ else {
+ (void) unlink (tname);
+ (void) fclose (f);
+ }
+}
+
+static makescanfile (scanfile)
+char *scanfile;
+{
+ char tname[STRINGLENGTH],fname[STRINGLENGTH];
+ struct timeval tbuf[2];
+ FILE *scanF; /* output file for scanned file list */
+ int recordone ();
+
+ if (scanfile == NULL)
+ scanfile = FILESCANDEF;
+ (void) sprintf (fname,FILESCAN,collname,scanfile);
+ (void) sprintf (tname,"%s.temp",fname);
+ scanF = fopen (tname,"w");
+ if (scanF == NULL)
+ goaway ("Can't write scan file temp %s for %s",tname,collname);
+ fprintf (scanF,"V%d\n",SCANVERSION);
+ (void) Tprocess (listT,recordone,scanF);
+ (void) fclose (scanF);
+ if (rename (tname,fname) < 0)
+ goaway ("Can't change %s to %s",tname,fname);
+ (void) unlink (tname);
+ tbuf[0].tv_sec = time((long *)NULL); tbuf[0].tv_usec = 0;
+ tbuf[1].tv_sec = scantime; tbuf[1].tv_usec = 0;
+ (void) utimes (fname,tbuf);
+}
+
+static
+recordone (t,scanF)
+TREE *t;
+FILE **scanF;
+{
+ int recordexec ();
+ char fname[MAXPATHLEN*4+1];
+
+ if (t->Tflags&FBACKUP) fprintf (*scanF,"B");
+ if (t->Tflags&FNOACCT) fprintf (*scanF,"N");
+ strvis(fname, t->Tname, VIS_WHITE);
+ fprintf (*scanF,"%o %d %d %s\n",
+ t->Tmode,t->Tctime,t->Tmtime,fname);
+ (void) Tprocess (t->Texec,recordexec,*scanF);
+ return (SCMOK);
+}
+
+static
+recordexec (t,scanF)
+TREE *t;
+FILE **scanF;
+{
+ char fname[MAXPATHLEN*4+1];
+ strvis(fname, t->Tname, VIS_WHITE);
+ fprintf(*scanF,"X%s\n",fname);
+ return (SCMOK);
+}
+
+cdprefix (prefix)
+char *prefix;
+{
+ static char *curprefix = NULL;
+
+ if (curprefix == NULL) {
+ if (prefix == NULL)
+ return;
+ (void) chdir (prefix);
+ curprefix = prefix;
+ return;
+ }
+ if (prefix == NULL) {
+ (void) chdir (basedir);
+ curprefix = NULL;
+ return;
+ }
+ if (prefix == curprefix)
+ return;
+ if (strcmp (prefix, curprefix) == 0) {
+ curprefix = prefix;
+ return;
+ }
+ (void) chdir (basedir);
+ (void) chdir (prefix);
+ curprefix = prefix;
+}
diff --git a/usr.bin/sup/src/scm.c b/usr.bin/sup/src/scm.c
new file mode 100644
index 00000000000..59be450716d
--- /dev/null
+++ b/usr.bin/sup/src/scm.c
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * SUP Communication Module for 4.3 BSD
+ *
+ * SUP COMMUNICATION MODULE SPECIFICATIONS:
+ *
+ * IN THIS MODULE:
+ *
+ * CONNECTION ROUTINES
+ *
+ * FOR SERVER
+ * servicesetup (port) establish TCP port connection
+ * char *port; name of service
+ * service () accept TCP port connection
+ * servicekill () close TCP port in use by another process
+ * serviceprep () close temp ports used to make connection
+ * serviceend () close TCP port
+ *
+ * FOR CLIENT
+ * request (port,hostname,retry) establish TCP port connection
+ * char *port,*hostname; name of service and host
+ * int retry; true if retries should be used
+ * requestend () close TCP port
+ *
+ * HOST NAME CHECKING
+ * p = remotehost () remote host name (if known)
+ * char *p;
+ * i = samehost () whether remote host is also this host
+ * int i;
+ * i = matchhost (name) whether remote host is same as name
+ * int i;
+ * char *name;
+ *
+ * RETURN CODES
+ * All procedures return values as indicated above. Other routines
+ * normally return SCMOK on success, SCMERR on error.
+ *
+ * COMMUNICATION PROTOCOL
+ *
+ * Described in scmio.c.
+ *
+ **********************************************************************
+ * HISTORY
+ * 2-Oct-92 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Added conditional declarations of INADDR_NONE and INADDR_LOOPBACK
+ * since Tahoe version of <netinet/in.h> does not define them.
+ *
+ * $Log: scm.c,v $
+ * Revision 1.1 1995/12/16 11:46:51 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1995/06/03 21:21:51 christos
+ * Changes to write ascii timestamps in the when files.
+ * Looked into making it 64 bit clean, but it is hopeless.
+ * Added little program to convert from the old timestamp files
+ * into the new ones.
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.13 92/08/11 12:05:35 mrt
+ * Added changes from stump:
+ * Allow for multiple interfaces, and for numeric addresses.
+ * Changed to use builtin port for the "supfiledbg"
+ * service when getservbyname() cannot find it.
+ * Added forward static declatations, delinted.
+ * Updated variable argument usage.
+ * [92/08/08 mrt]
+ *
+ * Revision 1.12 92/02/08 19:01:11 mja
+ * Add (struct sockaddr *) casts for HC 2.1.
+ * [92/02/08 18:59:09 mja]
+ *
+ * Revision 1.11 89/08/03 19:49:03 mja
+ * Updated to use v*printf() in place of _doprnt().
+ * [89/04/19 mja]
+ *
+ * 11-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Moved sleep into computeBackoff, renamed to dobackoff.
+ *
+ * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added timeout to backoff.
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed nameserver support.
+ *
+ * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fixed to depend less upon having name of remote host.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon Universtiy
+ * Extracted backoff/sleeptime computation from "request" and
+ * created "computeBackoff" so that I could use it in sup.c when
+ * trying to get to nameservers as a group.
+ *
+ * 21-May-87 Chriss Stephens (chriss) at Carnegie Mellon University
+ * Merged divergent CS and EE versions.
+ *
+ * 02-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added some bullet-proofing code around hostname calls.
+ *
+ * 31-Mar-87 Dan Nydick (dan) at Carnegie-Mellon University
+ * Fixed for 4.3.
+ *
+ * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to use known values for well-known ports if they are
+ * not found in the host table.
+ *
+ * 19-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed setsockopt SO_REUSEADDR to be non-fatal. Added fourth
+ * parameter as described in 4.3 manual entry.
+ *
+ * 15-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added call of readflush() to requestend() routine.
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Major rewrite for protocol version 4. All read/write and crypt
+ * routines are now in scmio.c.
+ *
+ * 14-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added setsockopt SO_REUSEADDR call.
+ *
+ * 01-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed code to "gracefully" handle unexpected messages. This
+ * seems reasonable since it didn't work anyway, and should be
+ * handled at a higher level anyway by adhering to protocol version
+ * number conventions.
+ *
+ * 26-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fixed scm.c to free space for remote host name when connection
+ * is closed.
+ *
+ * 07-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fixed 4.2 retry code to reload sin values before retry.
+ *
+ * 22-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to retry initial connection open request.
+ *
+ * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Merged 4.1 and 4.2 versions together.
+ *
+ * 21-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Add close() calls after pipe() call.
+ *
+ * 12-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Converted for 4.2 sockets; added serviceprep() routine.
+ *
+ * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for 4.2 BSD.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netdb.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "sup.h"
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff /* -1 return */
+#endif
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (u_long)0x7f000001 /* 127.0.0.1 */
+#endif
+
+extern int errno;
+static char *myhost ();
+
+char scmversion[] = "4.3 BSD";
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+/* networking parameters */
+#define NCONNECTS 5
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+extern char program[]; /* name of program we are running */
+extern int progpid; /* process id to display */
+
+int netfile = -1; /* network file descriptor */
+
+static int sock = -1; /* socket used to make connection */
+static struct in_addr remoteaddr; /* remote host address */
+static char *remotename = NULL; /* remote host name */
+static int swapmode; /* byte-swapping needed on server? */
+
+#if __STDC__
+int scmerr(int,char *,...);
+#endif
+
+/***************************************************
+ *** C O N N E C T I O N R O U T I N E S ***
+ *** F O R S E R V E R ***
+ ***************************************************/
+
+servicesetup (server) /* listen for clients */
+char *server;
+{
+ struct sockaddr_in sin;
+ struct servent *sp;
+ short port;
+ 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);
+}
+
+service ()
+{
+ struct sockaddr_in from;
+ int x,len;
+
+ remotename = NULL;
+ len = sizeof (from);
+ do {
+ 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);
+}
+
+serviceprep () /* kill temp socket in daemon */
+{
+ if (sock >= 0) {
+ (void) close (sock);
+ sock = -1;
+ }
+ return (SCMOK);
+}
+
+servicekill () /* kill net file in daemon's parent */
+{
+ if (netfile >= 0) {
+ (void) close (netfile);
+ netfile = -1;
+ }
+ if (remotename) {
+ free (remotename);
+ remotename = NULL;
+ }
+ return (SCMOK);
+}
+
+serviceend () /* kill net file after use in daemon */
+{
+ if (netfile >= 0) {
+ (void) close (netfile);
+ netfile = -1;
+ }
+ if (remotename) {
+ free (remotename);
+ remotename = NULL;
+ }
+ return (SCMOK);
+}
+
+/***************************************************
+ *** C O N N E C T I O N R O U T I N E S ***
+ *** F O R C L I E N T ***
+ ***************************************************/
+
+dobackoff (t,b)
+int *t,*b;
+{
+ struct timeval tt;
+ unsigned s;
+
+ if (*t == 0)
+ return (0);
+ s = *b * 30;
+ if (gettimeofday (&tt,(struct timezone *)NULL) >= 0)
+ s += (tt.tv_usec >> 8) % s;
+ if (*b < 32) *b <<= 1;
+ if (*t != -1) {
+ if (s > *t)
+ s = *t;
+ *t -= s;
+ }
+ (void) scmerr (-1,"Will retry in %d seconds",s);
+ sleep (s);
+ return (1);
+}
+
+request (server,hostname,retry) /* connect to server */
+char *server;
+char *hostname;
+int *retry;
+{
+ int x, backoff;
+ struct hostent *h;
+ struct servent *sp;
+ struct sockaddr_in sin, tin;
+ short port;
+
+ 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;
+ (void) bzero ((char *)&sin,sizeof(sin));
+ sin.sin_family = AF_INET;
+ 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);
+ }
+ sin.sin_port = port;
+ backoff = 1;
+ 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);
+ }
+ remoteaddr = sin.sin_addr;
+ remotename = salloc(hostname);
+ x = 0x01020304;
+ (void) write (netfile,(char *)&x,sizeof(int));
+ swapmode = 0; /* swap only on server, not client */
+ return (SCMOK);
+}
+
+requestend () /* end connection to server */
+{
+ (void) readflush ();
+ if (netfile >= 0) {
+ (void) close (netfile);
+ netfile = -1;
+ }
+ if (remotename) {
+ free (remotename);
+ remotename = NULL;
+ }
+ return (SCMOK);
+}
+
+/*************************************************
+ *** H O S T N A M E C H E C K I N G ***
+ *************************************************/
+
+static
+char *myhost () /* find my host name */
+{
+ struct hostent *h;
+ static char name[MAXHOSTNAMELEN];
+
+
+ if (name[0] == '\0') {
+ if (gethostname (name,MAXHOSTNAMELEN) < 0)
+ return (NULL);
+ if ((h = gethostbyname (name)) == NULL)
+ return (NULL);
+ (void) strcpy (name,h->h_name);
+ }
+ return (name);
+}
+
+char *remotehost () /* remote host name (if known) */
+{
+ register struct hostent *h;
+
+ if (remotename == NULL) {
+ h = gethostbyaddr ((char *)&remoteaddr,sizeof(remoteaddr),
+ AF_INET);
+ remotename = salloc (h ? h->h_name : inet_ntoa(remoteaddr));
+ if (remotename == NULL)
+ return("UNKNOWN");
+ }
+ return (remotename);
+}
+
+int thishost (host)
+register char *host;
+{
+ register struct hostent *h;
+ char *name;
+
+ if ((name = myhost ()) == NULL)
+ logquit (1,"Can't find my host entry");
+ h = gethostbyname (host);
+ if (h == NULL) return (0);
+ return (strcasecmp (name,h->h_name) == 0);
+}
+
+int samehost () /* is remote host same as local host? */
+{
+ static struct in_addr *intp;
+ static int nint = 0;
+ struct in_addr *ifp;
+ int n;
+
+ if (nint <= 0) {
+ int s;
+ char buf[BUFSIZ];
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ struct sockaddr_in sin;
+
+ if ((s = socket (AF_INET,SOCK_DGRAM,0)) < 0)
+ logquit (1,"Can't create socket for SIOCGIFCONF");
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl (s,SIOCGIFCONF,(char *)&ifc) < 0)
+ logquit (1,"SIOCGIFCONF failed");
+ (void) close(s);
+ if ((nint = ifc.ifc_len/sizeof(struct ifreq)) <= 0)
+ return (0);
+ intp = (struct in_addr *)
+ malloc ((unsigned) nint*sizeof(struct in_addr));
+ if ((ifp = intp) == 0)
+ logquit (1,"no space for interfaces");
+ for (ifr = ifc.ifc_req, n = nint; n > 0; --n, ifr++) {
+ (void) bcopy ((char *)&ifr->ifr_addr,(char *)&sin,sizeof(sin));
+ *ifp++ = sin.sin_addr;
+ }
+ }
+ if (remoteaddr.s_addr == htonl(INADDR_LOOPBACK))
+ return (1);
+ for (ifp = intp, n = nint; n > 0; --n, ifp++)
+ if (remoteaddr.s_addr == ifp->s_addr)
+ return (1);
+ return (0);
+}
+
+int matchhost (name) /* is this name of remote host? */
+char *name;
+{
+ struct hostent *h;
+ struct in_addr addr;
+ char **ap;
+ if ((addr.s_addr = inet_addr(name)) != (u_long) INADDR_NONE)
+ return (addr.s_addr == remoteaddr.s_addr);
+ if ((h = gethostbyname (name)) == 0)
+ return (0);
+ if (h->h_addrtype != AF_INET || h->h_length != sizeof(struct in_addr))
+ return (0);
+ for (ap = h->h_addr_list; *ap; ap++)
+ if (bcmp ((char *)&remoteaddr,*ap,h->h_length) == 0)
+ return (1);
+ return (0);
+}
+
+#if __STDC__
+int scmerr (int errno,char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+int scmerr (va_alist)
+va_dcl
+#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);
+ return (SCMERR);
+}
+
+/*******************************************************
+ *** I N T E G E R B Y T E - S W A P P I N G ***
+ *******************************************************/
+
+union intchar {
+ int ui;
+ char uc[sizeof(int)];
+};
+
+int byteswap (in)
+int in;
+{
+ union intchar x,y;
+ register int ix,iy;
+
+ if (swapmode == 0) return (in);
+ x.ui = in;
+ iy = sizeof(int);
+ for (ix=0; ix<sizeof(int); ix++) {
+ --iy;
+ y.uc[iy] = x.uc[ix];
+ }
+ return (y.ui);
+}
diff --git a/usr.bin/sup/src/scmio.c b/usr.bin/sup/src/scmio.c
new file mode 100644
index 00000000000..b0852e2d9de
--- /dev/null
+++ b/usr.bin/sup/src/scmio.c
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * SUP Communication Module for 4.3 BSD
+ *
+ * SUP COMMUNICATION MODULE SPECIFICATIONS:
+ *
+ * IN THIS MODULE:
+ *
+ * OUTPUT TO NETWORK
+ *
+ * MESSAGE START/END
+ * writemsg (msg) start message
+ * int msg; message type
+ * writemend () end message and flush data to network
+ *
+ * MESSAGE DATA
+ * writeint (i) write int
+ * int i; integer to write
+ * writestring (p) write string
+ * char *p; string pointer
+ * writefile (f) write open file
+ * int f; open file descriptor
+ *
+ * COMPLETE MESSAGE (start, one data block, end)
+ * writemnull (msg) write message with no data
+ * int msg; message type
+ * writemint (msg,i) write int message
+ * int msg; message type
+ * int i; integer to write
+ * writemstr (msg,p) write string message
+ * int msg; message type
+ * char *p; string pointer
+ *
+ * INPUT FROM NETWORK
+ * MESSAGE START/END
+ * readflush () flush any unread data (close)
+ * readmsg (msg) read specified message type
+ * int msg; message type
+ * readmend () read message end
+ *
+ * MESSAGE DATA
+ * readskip () skip over one input data block
+ * readint (i) read int
+ * int *i; pointer to integer
+ * readstring (p) read string
+ * char **p; pointer to string pointer
+ * readfile (f) read into open file
+ * int f; open file descriptor
+ *
+ * COMPLETE MESSAGE (start, one data block, end)
+ * readmnull (msg) read message with no data
+ * int msg; message type
+ * readmint (msg,i) read int message
+ * int msg; message type
+ * int *i; pointer to integer
+ * readmstr (msg,p) read string message
+ * int msg; message type
+ * char **p; pointer to string pointer
+ *
+ * RETURN CODES
+ * All routines normally return SCMOK. SCMERR may be returned
+ * by any routine on abnormal (usually fatal) errors. An
+ * unexpected MSGGOAWAY will result in SCMEOF being returned.
+ *
+ * COMMUNICATION PROTOCOL
+ * Messages always alternate, with the first message after
+ * connecting being sent by the client process.
+ *
+ * At the end of the conversation, the client process will
+ * send a message to the server telling it to go away. Then,
+ * both processes will close the network connection.
+ *
+ * Any time a process receives a message it does not expect,
+ * the "readmsg" routine will send a MSGGOAWAY message and
+ * return SCMEOF.
+ *
+ * Each message has this format:
+ * ---------- ------------ ------------ ----------
+ * |msg type| |count|data| |count|data| ... |ENDCOUNT|
+ * ---------- ------------ ------------ ----------
+ * size: int int var. int var. int
+ *
+ * All ints are assumed to be 32-bit quantities. A message
+ * with no data simply has a message type followed by ENDCOUNT.
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: scmio.c,v $
+ * Revision 1.1 1995/12/16 11:46:52 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1993/05/24 17:57:26 brezak
+ * Remove netcrypt.c. Remove unneeded files. Cleanup make.
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.7 92/09/09 22:04:41 mrt
+ * Removed the data encryption routines from here to netcrypt.c
+ * [92/09/09 mrt]
+ *
+ * Revision 1.6 92/08/11 12:05:57 mrt
+ * Brad's changes: Delinted,Added forward declarations of
+ * static functions. Added copyright.
+ * [92/07/24 mrt]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Found error in debuging code for readint().
+ *
+ * 01-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to readdata to "push" data back into the data buffer.
+ * Added prereadcount() to return the message count size after
+ * reading it and then pushing it back into the buffer. Clear
+ * any encryption when a GOAWAY message is detected before reading
+ * the reason string. [V5.19]
+ *
+ * 02-Oct-86 Rudy Nedved (ern) at Carnegie-Mellon University
+ * Put a timeout on reading from the network.
+ *
+ * 25-May-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University
+ * Renamed "howmany" parameter to routines "encode" and "decode" from
+ * to "count" to avoid conflict with 4.3BSD macro.
+ *
+ * 15-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added readflush() to flush any unread data from the input
+ * buffer. Called by requestend() in scm.c module.
+ *
+ * 19-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added register variables to decode() for speedup. Added I/O
+ * buffering to reduce the number or read/write system calls.
+ * Removed readmfil/writemfil routines which were not used and were
+ * not compatable with the other similarly defined routines anyway.
+ *
+ * 19-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created from scm.c I/O and crypt routines.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include "sup.h"
+#include "supmsg.h"
+
+extern int errno;
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+/* end of message */
+#define ENDCOUNT (-1) /* end of message marker */
+#define NULLCOUNT (-2) /* used for sending NULL pointer */
+
+#define RETRIES 15 /* # of times to retry io */
+#define FILEXFER 2048 /* block transfer size */
+#define XFERSIZE(count) ((count > FILEXFER) ? FILEXFER : count)
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+extern int scmerr (); /* error printing routine */
+extern int netfile; /* network file descriptor */
+
+int scmdebug; /* scm debug flag */
+
+int cryptflag; /* whether to encrypt/decrypt data */
+char *cryptbuf; /* buffer for data encryption/decryption */
+
+extern char *goawayreason; /* reason for goaway message */
+
+struct buf {
+ char b_data[FILEXFER]; /* buffered data */
+ char *b_ptr; /* pointer to end of buffer */
+ int b_cnt; /* number of bytes in buffer */
+} buffers[2];
+struct buf *bufptr; /* buffer pointer */
+
+
+/***********************************************
+ *** O U T P U T T O N E T W O R K ***
+ ***********************************************/
+
+static
+writedata (count,data) /* write raw data to network */
+int count;
+char *data;
+{
+ register int x,tries;
+ register struct buf *bp;
+
+ if (bufptr) {
+ if (bufptr->b_cnt + count <= FILEXFER) {
+ bcopy (data,bufptr->b_ptr,count);
+ bufptr->b_cnt += count;
+ bufptr->b_ptr += count;
+ return (SCMOK);
+ }
+ bp = (bufptr == buffers) ? &buffers[1] : buffers;
+ bcopy (data,bp->b_data,count);
+ bp->b_cnt = count;
+ bp->b_ptr = bp->b_data + count;
+ data = bufptr->b_data;
+ count = bufptr->b_cnt;
+ bufptr->b_cnt = 0;
+ bufptr->b_ptr = bufptr->b_data;
+ bufptr = bp;
+ }
+ tries = 0;
+ for (;;) {
+ errno = 0;
+ x = write (netfile,data,count);
+ if (x > 0) break;
+ if (errno) break;
+ if (++tries > RETRIES) break;
+ if (scmdebug > 0)
+ logerr ("SCM Retrying failed network write");
+ }
+ 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);
+}
+
+static
+writeblock (count,data) /* write data block */
+int count;
+char *data;
+{
+ register int x;
+ int y = byteswap(count);
+
+ x = writedata (sizeof(int),(char *)&y);
+ if (x == SCMOK) x = writedata (count,data);
+ return (x);
+}
+
+writemsg (msg) /* write start of message */
+int msg;
+{
+ int x;
+
+ 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;
+ x = byteswap (msg);
+ return (writedata(sizeof(int),(char *)&x));
+}
+
+writemend () /* write end of message */
+{
+ register int count;
+ register char *data;
+ int x;
+
+ x = byteswap (ENDCOUNT);
+ 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);
+ }
+ data = bufptr->b_data;
+ count = bufptr->b_cnt;
+ bufptr = NULL;
+ return (writedata (count, data));
+}
+
+writeint (i) /* write int as data block */
+int i;
+{
+ int x;
+ if (scmdebug > 2)
+ loginfo ("SCM Writing integer %d",i);
+ x = byteswap(i);
+ return (writeblock(sizeof(int),(char *)&x));
+}
+
+writestring (p) /* write string as data block */
+char *p;
+{
+ register int len,x;
+ if (p == NULL) {
+ int y = byteswap(NULLCOUNT);
+ if (scmdebug > 2)
+ loginfo ("SCM Writing string NULL");
+ return (writedata (sizeof(int),(char *)&y));
+ }
+ if (scmdebug > 2)
+ loginfo ("SCM Writing string %s",p);
+ len = strlen (p);
+ if (cryptflag) {
+ x = getcryptbuf (len+1);
+ if (x != SCMOK)
+ return (x);
+ encode (p,cryptbuf,len);
+ p = cryptbuf;
+ }
+ return (writeblock(len,p));
+}
+
+writefile (f) /* write open file as a data block */
+int f;
+{
+ char buf[FILEXFER];
+ register int number,sum,filesize,x;
+ int y;
+ 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);
+
+ if (cryptflag) x = getcryptbuf (FILEXFER);
+
+ if (x == SCMOK) {
+ sum = 0;
+ do {
+ number = read (f,buf,FILEXFER);
+ if (number > 0) {
+ if (cryptflag) {
+ encode (buf,cryptbuf,number);
+ x = writedata (number,cryptbuf);
+ }
+ else {
+ x = writedata (number,buf);
+ }
+ sum += number;
+ }
+ } 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);
+}
+
+writemnull (msg) /* write message with no data */
+int msg;
+{
+ register int x;
+ x = writemsg (msg);
+ if (x == SCMOK) x = writemend ();
+ return (x);
+}
+
+writemint (msg,i) /* write message of one int */
+int msg,i;
+{
+ register int x;
+ x = writemsg (msg);
+ if (x == SCMOK) x = writeint (i);
+ if (x == SCMOK) x = writemend ();
+ return (x);
+}
+
+writemstr (msg,p) /* write message of one string */
+int msg;
+char *p;
+{
+ register int x;
+ x = writemsg (msg);
+ if (x == SCMOK) x = writestring (p);
+ if (x == SCMOK) x = writemend ();
+ return (x);
+}
+
+/*************************************************
+ *** I N P U T F R O M N E T W O R K ***
+ *************************************************/
+
+static
+readdata (count,data) /* read raw data from network */
+int count;
+char *data;
+{
+ register char *p;
+ register int n,m,x;
+ int tries;
+ static int bufcnt = 0;
+ static char *bufptr;
+ static char buffer[FILEXFER];
+ static int imask;
+ static struct timeval timout;
+
+ if (count < 0) {
+ if (bufptr + count < buffer)
+ return (scmerr (-1,"No space in buffer %d",count));
+ bufptr += count;
+ bufcnt -= count;
+ bcopy (data,bufptr,-count);
+ return (SCMOK);
+ }
+ if (count == 0 && data == NULL) {
+ bufcnt = 0;
+ return (SCMOK);
+ }
+ if (count <= bufcnt) {
+ bcopy (bufptr,data,count);
+ bufptr += count;
+ bufcnt -= count;
+ return (SCMOK);
+ }
+ if (bufcnt > 0) {
+ bcopy (bufptr,data,bufcnt);
+ data += bufcnt;
+ count -= bufcnt;
+ }
+ bufptr = buffer;
+ bufcnt = 0;
+ timout.tv_usec = 0;
+ timout.tv_sec = 2*60*60;
+ p = buffer;
+ n = FILEXFER;
+ m = count;
+ while (m > 0) {
+ 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)
+ loginfo ("SCM Retrying failed network read");
+ }
+ if (x < 0) {
+ if (errno)
+ return (scmerr (errno,"Read error on network"));
+ return (scmerr (-1,"Read retries failed"));
+ }
+ p += x;
+ n -= x;
+ m -= x;
+ bufcnt += x;
+ }
+ bcopy (bufptr,data,count);
+ bufptr += count;
+ bufcnt -= count;
+ return (SCMOK);
+}
+
+static
+int readcount (count) /* read count of data block */
+int *count;
+{
+ register int x;
+ int y;
+ x = readdata (sizeof(int),(char *)&y);
+ if (x != SCMOK) return (x);
+ *count = byteswap(y);
+ return (SCMOK);
+}
+
+int prereadcount (count) /* preread count of data block */
+int *count;
+{
+ register int x;
+ int y;
+ x = readdata (sizeof(int),(char *)&y);
+ if (x != SCMOK) return (x);
+ x = readdata (-sizeof(int),(char *)&y);
+ if (x != SCMOK) return (x);
+ *count = byteswap(y);
+ return (SCMOK);
+}
+
+readflush ()
+{
+ return (readdata (0, (char *)NULL));
+}
+
+readmsg (msg) /* read header for expected message */
+int msg; /* if message is unexpected, send back SCMHUH */
+{
+ register int x;
+ int m;
+ if (scmdebug > 1)
+ loginfo ("SCM Reading message %d",msg);
+ x = readdata (sizeof(int),(char *)&m); /* msg type */
+ if (x != SCMOK) return (x);
+ m = byteswap(m);
+ if (m == msg) return (x);
+
+ /* 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 ();
+ if (goawayreason == NULL)
+ return (SCMEOF);
+ logerr ("SCM GOAWAY %s",goawayreason);
+ return (SCMEOF);
+}
+
+readmend ()
+{
+ register int x;
+ int y;
+ x = readdata (sizeof(int),(char *)&y);
+ y = byteswap(y);
+ if (x == SCMOK && y != ENDCOUNT)
+ return (scmerr (-1,"Error reading end of message"));
+ return (x);
+}
+
+readskip () /* skip over one input block */
+{
+ register int x;
+ int n;
+ char buf[FILEXFER];
+ 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);
+ }
+ return (x);
+}
+
+int readint (buf) /* read int data block */
+int *buf;
+{
+ register int x;
+ int y;
+ 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)
+ loginfo ("SCM Reading integer %d",*buf);
+ return (x);
+}
+
+int readstring (buf) /* read string data block */
+register char **buf;
+{
+ register int x;
+ int count;
+ register char *p;
+
+ x = readcount (&count);
+ if (x != SCMOK) return (x);
+ if (count == NULLCOUNT) {
+ if (scmdebug > 2)
+ loginfo ("SCM Reading string NULL");
+ *buf = NULL;
+ 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);
+ if (x != SCMOK) return (x);
+ if (scmdebug > 3)
+ printf ("SCM Reading encrypted string %s\n",cryptbuf);
+ decode (cryptbuf,p,count);
+ }
+ else {
+ x = readdata (count,p);
+ if (x != SCMOK) return (x);
+ }
+ p[count] = 0; /* NULL at end of string */
+ *buf = p;
+ if (scmdebug > 2)
+ loginfo ("SCM Reading string %s",*buf);
+ return (SCMOK);
+}
+
+readfile (f) /* read data block into open file */
+int f;
+{
+ register int x;
+ int count;
+ char buf[FILEXFER];
+
+ if (cryptflag) {
+ x = getcryptbuf (FILEXFER);
+ if (x != SCMOK) return (x);
+ }
+ 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);
+ if (x == SCMOK) decode (cryptbuf,buf,XFERSIZE(count));
+ }
+ else
+ x = readdata (XFERSIZE(count),buf);
+ if (x == SCMOK) {
+ (void) write (f,buf,XFERSIZE(count));
+ count -= XFERSIZE(count);
+ }
+ }
+ return (x);
+}
+
+readmnull (msg) /* read null message */
+int msg;
+{
+ register int x;
+ x = readmsg (msg);
+ if (x == SCMOK) x = readmend ();
+ return (x);
+}
+
+readmint (msg,buf) /* read int message */
+int msg,*buf;
+{
+ register int x;
+ x = readmsg (msg);
+ if (x == SCMOK) x = readint (buf);
+ if (x == SCMOK) x = readmend ();
+ return (x);
+}
+
+int readmstr (msg,buf) /* read string message */
+int msg;
+char **buf;
+{
+ register int x;
+ x = readmsg (msg);
+ if (x == SCMOK) x = readstring (buf);
+ if (x == SCMOK) x = readmend ();
+ return (x);
+}
+
+/**********************************
+ *** C R O S S P A T C H ***
+ **********************************/
+
+crosspatch ()
+{
+ fd_set ibits, obits, xbits;
+ register int c;
+ char buf[STRINGLENGTH];
+
+ for (;;) {
+ FD_ZERO (&ibits);
+ FD_ZERO (&obits);
+ FD_ZERO (&xbits);
+ FD_SET (0,&ibits);
+ FD_SET (netfile,&ibits);
+ if ((c = select(16, &ibits, &obits, &xbits,
+ (struct timeval *)NULL)) < 1) {
+ if (c == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ }
+ sleep (5);
+ continue;
+ }
+ if (FD_ISSET (netfile,&ibits)) {
+ c = read (netfile,buf,sizeof (buf));
+ if (c < 0 && errno == EWOULDBLOCK)
+ c = 0;
+ else {
+ if (c <= 0) {
+ break;
+ }
+ (void) write (1,buf,c);
+ }
+ }
+ if (FD_ISSET(0, &ibits)) {
+ c = read (0,buf,sizeof (buf));
+ if (c < 0 && errno == EWOULDBLOCK)
+ c = 0;
+ else {
+ if (c <= 0)
+ break;
+ (void) write (netfile,buf,c);
+ }
+ }
+ }
+}
diff --git a/usr.bin/sup/src/skipto.c b/usr.bin/sup/src/skipto.c
new file mode 100644
index 00000000000..2fa5a4f4022
--- /dev/null
+++ b/usr.bin/sup/src/skipto.c
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+/************************************************************************
+ * skipover and skipto -- skip over characters in string
+ *
+ * Usage: p = skipto (string,charset);
+ * p = skipover (string,charset);
+ *
+ * char *p,*charset,*string;
+ *
+ * Skipto returns a pointer to the first character in string which
+ * is in the string charset; it "skips until" a character in charset.
+ * Skipover returns a pointer to the first character in string which
+ * is not in the string charset; it "skips over" characters in charset.
+ ************************************************************************
+ * HISTORY
+ * 26-Jun-81 David Smith (drs) at Carnegie-Mellon University
+ * Skipover, skipto rewritten to avoid inner loop at expense of space.
+ *
+ * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
+ * Skipover, skipto adapted for VAX from skip() and skipx() on the PDP-11
+ * (from Ken Greer). The names are more mnemonic.
+ *
+ * Sindex adapted for VAX from indexs() on the PDP-11 (thanx to Ralph
+ * Guggenheim). The name has changed to be more like the index()
+ * and rindex() functions from Bell Labs; the return value (pointer
+ * rather than integer) has changed partly for the same reason,
+ * and partly due to popular usage of this function.
+ */
+
+static unsigned char tab[256] = {
+ 0};
+
+char *skipto (string,charset)
+unsigned char *string, *charset;
+{
+ register unsigned char *setp,*strp;
+
+ tab[0] = 1; /* Stop on a null, too. */
+ for (setp=charset; *setp; setp++) tab[*setp]=1;
+ for (strp=string; tab[*strp]==0; strp++) ;
+ for (setp=charset; *setp; setp++) tab[*setp]=0;
+ return ((char *)strp);
+}
+
+char *skipover (string,charset)
+unsigned char *string, *charset;
+{
+ register unsigned char *setp,*strp;
+
+ tab[0] = 0; /* Do not skip over nulls. */
+ for (setp=charset; *setp; setp++) tab[*setp]=1;
+ for (strp=string; tab[*strp]; strp++) ;
+ for (setp=charset; *setp; setp++) tab[*setp]=0;
+ return ((char *)strp);
+}
diff --git a/usr.bin/sup/src/stree.c b/usr.bin/sup/src/stree.c
new file mode 100644
index 00000000000..125c37e50e9
--- /dev/null
+++ b/usr.bin/sup/src/stree.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * stree.c -- SUP Tree Routines
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: stree.c,v $
+ * Revision 1.1 1995/12/16 11:46:53 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:17 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.4 92/08/11 12:06:32 mrt
+ * Added copyright. Delinted
+ * [92/08/10 mrt]
+ *
+ *
+ * Revision 1.3 89/08/15 15:30:57 bww
+ * Changed code in Tlookup to Tsearch for each subpart of path.
+ * Added indent formatting code to Tprint.
+ * From "[89/06/24 gm0w]" at CMU.
+ * [89/08/15 bww]
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to please lint.
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to initialize new fields. Added Tfree routine.
+ *
+ * 27-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#include <c.h>
+#include <sys/param.h>
+#include "sup.h"
+
+#define Static /* static /* comment for debugging */
+
+/*************************************************************
+ *** T R E E P R O C E S S I N G R O U T I N E S ***
+ *************************************************************/
+
+Tfree (t)
+register TREE **t;
+{
+ if (*t == NULL) return;
+ Tfree (&((*t)->Tlink));
+ Tfree (&((*t)->Texec));
+ Tfree (&((*t)->Tlo));
+ Tfree (&((*t)->Thi));
+ if ((*t)->Tname) free ((*t)->Tname);
+ if ((*t)->Tuser) free ((*t)->Tuser);
+ if ((*t)->Tgroup) free ((*t)->Tgroup);
+ free (*(char **)t);
+ *t = NULL;
+}
+
+Static
+TREE *Tmake (p)
+char *p;
+{
+ register TREE *t;
+ t = (TREE *) malloc (sizeof (TREE));
+ t->Tname = (p == NULL) ? NULL : salloc (p);
+ t->Tflags = 0;
+ t->Tuid = 0;
+ t->Tgid = 0;
+ t->Tuser = NULL;
+ t->Tgroup = NULL;
+ t->Tmode = 0;
+ t->Tctime = 0;
+ t->Tmtime = 0;
+ t->Tlink = NULL;
+ t->Texec = NULL;
+ t->Tbf = 0;
+ t->Tlo = NULL;
+ t->Thi = NULL;
+ return (t);
+}
+
+Static
+TREE *Trotll (tp,tl)
+register TREE *tp,*tl;
+{
+ tp->Tlo = tl->Thi;
+ tl->Thi = tp;
+ tp->Tbf = tl->Tbf = 0;
+ return(tl);
+}
+
+Static
+TREE *Trotlh (tp,tl)
+register TREE *tp,*tl;
+{
+ register TREE *th;
+
+ th = tl->Thi;
+ tp->Tlo = th->Thi;
+ tl->Thi = th->Tlo;
+ th->Thi = tp;
+ th->Tlo = tl;
+ tp->Tbf = tl->Tbf = 0;
+ if (th->Tbf == 1)
+ tp->Tbf = -1;
+ else if (th->Tbf == -1)
+ tl->Tbf = 1;
+ th->Tbf = 0;
+ return(th);
+}
+
+Static
+TREE *Trothl (tp,th)
+register TREE *tp,*th;
+{
+ register TREE *tl;
+
+ tl = th->Tlo;
+ tp->Thi = tl->Tlo;
+ th->Tlo = tl->Thi;
+ tl->Tlo = tp;
+ tl->Thi = th;
+ tp->Tbf = th->Tbf = 0;
+ if (tl->Tbf == -1)
+ tp->Tbf = 1;
+ else if (tl->Tbf == 1)
+ th->Tbf = -1;
+ tl->Tbf = 0;
+ return(tl);
+}
+
+Static
+TREE *Trothh (tp,th)
+register TREE *tp,*th;
+{
+ tp->Thi = th->Tlo;
+ th->Tlo = tp;
+ tp->Tbf = th->Tbf = 0;
+ return(th);
+}
+
+Static
+Tbalance (t)
+TREE **t;
+{
+ if ((*t)->Tbf < 2 && (*t)->Tbf > -2)
+ return;
+ if ((*t)->Tbf > 0) {
+ if ((*t)->Tlo->Tbf > 0)
+ *t = Trotll(*t, (*t)->Tlo);
+ else
+ *t = Trotlh(*t, (*t)->Tlo);
+ } else {
+ if ((*t)->Thi->Tbf > 0)
+ *t = Trothl(*t, (*t)->Thi);
+ else
+ *t = Trothh(*t, (*t)->Thi);
+ }
+}
+
+Static
+TREE *Tinsertavl (t,p,find,dh)
+TREE **t;
+char *p;
+int find;
+int *dh;
+{
+ register TREE *newt;
+ register int cmp;
+ int deltah;
+
+ if (*t == NULL) {
+ *t = Tmake (p);
+ *dh = 1;
+ return (*t);
+ }
+ if ((cmp = strcmp(p, (*t)->Tname)) == 0) {
+ if (!find) return (NULL); /* node already exists */
+ *dh = 0;
+ return (*t);
+ } else if (cmp < 0) {
+ if ((newt = Tinsertavl (&((*t)->Tlo),p,find,&deltah)) == NULL)
+ return (NULL);
+ (*t)->Tbf += deltah;
+ } else {
+ if ((newt = Tinsertavl (&((*t)->Thi),p,find,&deltah)) == NULL)
+ return (NULL);
+ (*t)->Tbf -= deltah;
+ }
+ Tbalance(t);
+ if ((*t)->Tbf == 0) deltah = 0;
+ *dh = deltah;
+ return (newt);
+}
+
+TREE *Tinsert (t,p,find)
+TREE **t;
+register char *p;
+int find;
+{
+ int deltah;
+
+ if (p != NULL && p[0] == '.' && p[1] == '/') {
+ p += 2;
+ while (*p == '/') p++;
+ if (*p == 0) p = ".";
+ }
+ return (Tinsertavl (t,p,find,&deltah));
+}
+
+TREE *Tsearch (t,p)
+TREE *t;
+char *p;
+{
+ register TREE *x;
+ register int cmp;
+
+ x = t;
+ while (x) {
+ cmp = strcmp (p,x->Tname);
+ if (cmp == 0) return (x);
+ if (cmp < 0) x = x->Tlo;
+ else x = x->Thi;
+ }
+ return (NULL);
+}
+
+TREE *Tlookup (t,p)
+TREE *t;
+char *p;
+{
+ register TREE *x;
+ char buf[MAXPATHLEN+1];
+
+ if (p == NULL)
+ return (NULL);
+ if (p[0] == '.' && p[1] == '/') {
+ p += 2;
+ while (*p == '/') p++;
+ if (*p == 0) p = ".";
+ }
+ if ((x = Tsearch (t,p)) != NULL)
+ return (x);
+ if (*p != '/' && (x = Tsearch (t,".")) != NULL)
+ return (x);
+ (void) strncpy(buf, p, sizeof(buf)-1);
+ buf[MAXPATHLEN] = '\0';
+ while ((p = rindex(buf, '/')) != NULL) {
+ while (p >= buf && *(p-1) == '/')
+ p--;
+ if (p == buf)
+ *(p+1) = '\0';
+ else
+ *p = '\0';
+ if ((x = Tsearch (t,buf)) != NULL)
+ return (x);
+ if (p == buf)
+ break;
+ }
+ return (NULL);
+}
+
+Static int process_level;
+
+Static
+int Tsubprocess (t,reverse,f,argp)
+TREE *t;
+int reverse;
+int (*f)();
+int *argp;
+{
+ register int x = SCMOK;
+ process_level++;
+ if (reverse?t->Thi:t->Tlo)
+ x = Tsubprocess (reverse?t->Thi:t->Tlo,
+ reverse,f,argp);
+ if (x == SCMOK) {
+ x = (*f) (t,argp);
+ if (x == SCMOK) {
+ if (reverse?t->Tlo:t->Thi)
+ x = Tsubprocess (reverse?t->Tlo:t->Thi,
+ reverse,f,argp);
+ }
+ }
+ process_level--;
+ return (x);
+}
+
+/* VARARGS2 */
+int Trprocess (t,f,args)
+TREE *t;
+int (*f)();
+int args;
+{
+ if (t == NULL) return (SCMOK);
+ process_level = 0;
+ return (Tsubprocess (t,TRUE,f,&args));
+}
+
+/* VARARGS2 */
+int Tprocess (t,f,args)
+TREE *t;
+int (*f)();
+int args;
+{
+ if (t == NULL) return (SCMOK);
+ process_level = 0;
+ return (Tsubprocess (t,FALSE,f,&args));
+}
+
+Static
+int Tprintone (t)
+TREE *t;
+{
+ int i;
+ for (i = 0; i < (process_level*2); i++)
+ (void) putchar(' ');
+ printf ("Node at %X name '%s' flags %o hi %X lo %X\n",t,t->Tname,t->Tflags,t->Thi,t->Tlo);
+ return (SCMOK);
+}
+
+Tprint (t,p) /* print tree -- for debugging */
+TREE *t;
+char *p;
+{
+ printf ("%s\n",p);
+ (void) Tprocess (t,Tprintone);
+ printf ("End of tree\n");
+ (void) fflush (stdout);
+}
diff --git a/usr.bin/sup/src/sup.1 b/usr.bin/sup/src/sup.1
new file mode 100644
index 00000000000..f3999e024d6
--- /dev/null
+++ b/usr.bin/sup/src/sup.1
@@ -0,0 +1,862 @@
+.\" Copyright (c) 1992 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 Mellon
+.\" the rights to redistribute these changes.
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.\" HISTORY
+.\" $Log: sup.1,v $
+.\" Revision 1.1 1995/12/16 11:46:54 deraadt
+.\" add sup to the tree
+.\"
+.\" Revision 1.3 1995/06/03 21:21:53 christos
+.\" Changes to write ascii timestamps in the when files.
+.\" Looked into making it 64 bit clean, but it is hopeless.
+.\" Added little program to convert from the old timestamp files
+.\" into the new ones.
+.\"
+.\" Revision 1.2 1993/08/04 17:46:14 brezak
+.\" Changes from nate for gzip'ed sup
+.\"
+.\" Revision 1.1.1.1 1993/05/21 14:52:16 cgd
+.\" initial import of CMU's SUP to NetBSD
+.\"
+.\" Revision 1.4 92/08/11 12:08:40 mrt
+.\" .TP
+.\" Add description of releases and use-rel-suffix
+.\" [92/07/31 mrt]
+.\"
+.\" Revision 1.3 92/02/08 18:24:31 mja
+.\" Added description of -k and -K switches and "keep" option.
+.\" [92/01/17 vdelvecc]
+.\"
+.\" 10-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+.\" Replaced reference to /usr/cmu with /usr/cs.
+.\"
+.\" 29-Mar-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+.\" Updated manual entry to version 5.14 of sup.
+.\"
+.\" 14-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+.\" Updated manual entry to version 5.7 of sup.
+.\"
+.\" 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
+.SH "SYNOPSIS"
+\fBsup\fR [ \fIflags\fR ] [ \fIsupfile\fR ] [ \fIcollection\fR ...]
+.SH "DESCRIPTION"
+.I Sup
+is a program used for upgrading collections of files from other machines
+to your machine. You execute
+.IR sup ,
+the
+.I client
+program, which talks over the network using IP/TCP to a
+.I file server
+process.
+The file server process cooperates with
+.I sup
+to determine which files of the collection need to be upgraded on
+your machine.
+
+Sup collections can have multiple releases. One use for such releases is
+to provide different versions of the same files. At CMU, for example,
+system binaries have alpha, beta and default release corresponding to
+different staging levels of the software. We also use release names
+default and minimal to provide complete releases or subset releases.
+In both of these cases, it only makes sense to sup one release of the
+collections. Releases have also been used in private or external sups to
+provide subsets of collections where it makes sense to pick up several
+of the releases. For example the Mach 3.0 kernel sources has a default
+release of machine independent sources and separate releases of
+machine dependent sources for each supported platform.
+
+In performing an upgrade, the file server constructs a list of
+files included in the specified release of the collection. The list is sent to your machine,
+which determines which files are needed. Those files are then sent
+from the file server.
+It will be most useful to run
+.I sup
+as a daemon each night so you will continually have the latest version of the
+files in the needed collections.
+
+The only required argument to
+.I sup
+is the name of a supfile. It must either be given explicitly on the command
+line, or the
+.B -s
+flag must be specified. If the
+.B -s
+flag is given, the system supfile will be used and a supfile command argument
+should not be specified. The list of collections is optional and if specified
+will be the only collections upgraded. The following flags affect all
+collections specified:
+.TP
+.B -s
+As described above.
+.TP
+.B -t
+When this flag is given,
+.I sup
+will print the time
+that each collection was last upgraded, rather than
+performing actual upgrades.
+.TP
+.B -N
+.I Sup
+will trace network messages sent and received that implement the
+.I sup
+network protocol.
+.TP
+.B -P
+Sup will use a set of non-privileged network
+ports reserved for debugging purposes.
+.i0
+.DT
+.PP
+
+The remaining flags affect all collections unless an explicit list
+of collections are given with the flags. Multiple flags may be
+specified together that affect the same collections. For the sake
+of convience, any flags that always affect all collections can be
+specified with flags that affect only some collections. For
+example,
+.B sup -sde=coll1,coll2
+would perform a system upgrade,
+and the first two collections would allow both file deletions and
+command executions. Note that this is not the same command as
+.B sup -sde=coll1 coll2,
+which would perform a system upgrade of
+just the coll2 collection and would ignore the flags given for the
+coll1 collection.
+.TP
+.B -a
+All files in the collection will be copied from
+the repository, regardless of their status on the
+current machine. Because of this, it is a very
+expensive operation and should only be done for
+small collections if data corruption is suspected
+and been confirmed. In most cases, the
+.B -o
+flag should be sufficient.
+.TP
+.B -b
+If the
+.B -b
+flag if given, or the
+.B backup
+supfile
+option is specified, the contents of regular files
+on the local system will be saved before they are
+overwritten with new data. The file collection maintainer
+can designate specific files to be
+worthy of backing up whenever they are upgraded.
+However, such
+backup will only take place if you specify this flag or the
+.B backup
+option to allow
+backups for a file collection on your machine.
+The backup mechanism
+will create a copy of the current version of a file immediately
+before a new copy is received from the file server; the copy is
+given the same name as the original file but is put into a directory
+called
+.B
+BACKUP
+within the directory containing the original file.
+For example,
+.B
+/usr/sas/src/foo.c
+would have a backup copy called
+.B
+/usr/sas/src/BACKUP/foo.c.
+There is no provision for automatically maintaining multiple old
+versions of files; you would have to do this yourself.
+.TP
+.B -B
+The
+.B -B
+flag overrides and disables the
+.B -b
+flag and the
+.B backup
+supfile option.
+.TP
+.B -d
+Files that are no longer in the collection on the
+repository will be deleted if present on the local
+machine and were put there by a previous sup.
+This may also be specified in a supfile with the
+.B delete
+option.
+.TP
+.B -D
+The
+.B -D
+flag overrides and disables the
+.B -d
+flag and the
+.B delete
+supfile option.
+.TP
+.B -e
+Sup will execute commands sent from the repository
+that should be run when a file is upgraded. If
+the
+.B -e
+flag is omitted, Sup will print a message
+that specifies the command to execute. This may
+also be specified in a supfile with the
+.B execute
+option.
+.TP
+.B -E
+The
+.B -E
+flag overrides and disables the
+.B -e
+flag and the
+.B execute
+supfile option.
+.TP
+.B -f
+A
+.I list-only
+upgrade will be performed. Messages
+will be printed that indicate what would happen if
+an actual upgrade were done.
+.TP
+.B -k
+.I Sup
+will check the modification times of
+files on the local disk before updating them. Only files which are
+newer on the repository than on the local disk will be updated;
+files that are newer on the local disk will be kept as they are.
+This may also be specified in a supfile with the
+.B keep
+option.
+.TP
+.B -K
+The
+.B -K
+flag overrides and disables the
+.B -k
+flag and the
+.B keep
+supfile option.
+.TP
+.B -l
+Normally,
+.I sup
+will not upgrade a collection if the
+repository is on the same machine. This allows
+users to run upgrades on all machines without
+having to make special checks for the repository
+machine. If the
+.B -l
+flag is specified, collections
+will be upgraded even if the repository is local.
+.TP
+.B -m
+Normally,
+.I sup
+used standard output for messages.
+If the
+.B -m
+flag if given,
+.I sup
+will send mail to the user running
+.IR sup ,
+or a user specified with the
+.B notify
+supfile option, that contains messages
+printed by
+.IR sup .
+.TP
+.B -o
+.I Sup
+will normally only upgrade files that have
+changed on the repository since the last time an
+upgrade was performed. That is, if the file in the
+repository is newer than the date stored in the
+.I when
+file on the client. The
+.B -o
+flag, or the
+.B old
+supfile option, will cause
+.I sup
+to check all files
+in the collection for changes instead of just the
+new ones.
+.TP
+.B -O
+The
+.B -O
+flag overrides and disables the
+.B -o
+flag and the
+.B old
+supfile option.
+.TP
+.B -z
+Normally sup transfers files directly without any
+other processing, but with the
+.B -z
+flag, or the
+.B compress
+supfile option, sup will compress the file
+before sending it across the network and
+uncompress it and restore all the correct
+file attributes at the recieving end.
+.TP
+.B -Z
+The
+.B -Z
+flag overrides and disables the
+.B -z
+flag and the
+.B compress
+supfile option.
+.TP
+.B -v
+Normally,
+.I sup
+will only print messages if there
+are problems. This flag causes
+.I sup
+to also print
+messages during normal progress showing what
+.I sup
+is doing.
+.i0
+.DT
+.PP
+.SH "SETTING UP UPGRADES"
+Each file collection to be upgraded must have a
+.I base directory
+which contains a subdirectory called
+.B sup
+that will be used by the
+.I sup
+program; it will be created automatically if you do not create it.
+.I Sup
+will put subdirectories and files into this directory as needed.
+
+.I Sup
+will look for a subdirectory with the same name as the
+collection within the
+.B sup
+subdirectory of the
+.I base directory.
+If it exists it may contain any of the following files:
+.TP
+.B when.<rel-suffix>
+This file is automatically updated by
+.I sup
+when a collection is successfully upgraded and contains the
+time that the file server, or possibly
+.IR supscan ,
+created the list of files in the upgrade list.
+.I Sup
+will send this time to the file server for generating the list
+of files that have been changed on the repository machine.
+.TP
+.B refuse
+This file contains a list of files and directories, one per line, that
+the client is not interested in that should not be upgraded.
+.TP
+.B lock
+This file is used by
+.I sup
+to lock a collection while it is being upgraded.
+.I Sup
+will get exclusive access to the lock file using
+.IR flock (2),
+preventing more than one
+.I sup
+from upgrading the same collection at the same time.
+.TP
+.B last.<rel-suffix>
+This file contains a list of files and directories, one per line, that
+have been upgraded by
+.I sup
+in the past. This information is used when the
+.B delete
+option, or the
+.B -d
+flag is used to locate files previously upgraded that are no longer
+in the collection that should be deleted.
+.i0
+.DT
+.PP
+
+Each file collection must also be described in one or more supfiles.
+When
+.I sup
+is executed, it reads the specified supfile to determine what file
+collections and releases to upgrade.
+Each collection-release set is described by a single
+line of text in the supfile; this line must contain the name of the
+collection, and possibly one or more options separated by spaces.
+The options are:
+.TP
+.BI release= releasename
+If a collection contains multiple releases, you need to specify which
+release you want. You can only specify one release per line, so
+if you want multiple releases from the same collections, you will need
+to specify the collection more than once. In this case, you should use
+the
+.I use-rel-suffix
+ption in the supfile
+to keep the last and when files for the two releases separate.
+.TP
+.BI base= directory
+The usual default name of the base directory for a collection is
+described below (see FILES); if you want to specify another
+directory name, use this option specifying the desired
+directory.
+.TP
+.BI prefix= directory
+Each collection may also have an associated
+.I prefix directory
+which is used instead of the base directory to specify in what
+directory files within the collection will be placed.
+.TP
+.BI host= hostname
+.br
+.ns
+.TP
+.BI hostbase= directory
+.br
+.I System
+collections are supported by the system maintainers, and
+.I sup
+will automatically find out the name of the host machine and
+base directory on that machine.
+However, you can also upgrade
+.I private
+collections; you simply specify with these options
+the
+.I hostname
+of the machine containing the files and the
+.I directory
+used as a base directory for the file server on that machine.
+Details of setting up a file collection are given in the section
+below.
+.TP
+.BI login= accountid
+.br
+.ns
+.TP
+.BI password= password
+.br
+.br
+.ns
+.TP
+.BI crypt= key
+.br
+Files on the file server may be protected, and network transmissions
+may be encrypted.
+This prevents unauthorized access to files via
+.IR sup .
+When files are not accessible to the default account (e.g.
+the
+.B anon
+anonymous account), you can specify an alternative
+.I accountid
+and
+.I password
+for the file server to use on the repository host.
+Network
+transmission of the password will be always be encrypted.
+You can
+also have the actual file data encrypted by specifying a
+.IR key ;
+the file collection on the repository must specify the same key
+or else
+.I sup
+will not be able to upgrade files from that collection.
+In this case, the default account used by the file server on the
+repository machine will be the owner of the encryption key
+file (see FILES) rather than the
+.B anon
+anonymous account.
+.TP
+.BI notify= address
+If you use the
+.B
+-m
+option to receive log messages by mail, you can have the mail
+sent to different user, possibly on another host, than the user
+running the sup program.
+Messages will be sent to the specified
+.IR address ,
+which can be any legal netmail address.
+In particular, a
+project maintainer can be designated to receive mail for that
+project's file collection from all users running
+.I sup
+to upgrade that collection.
+.TP
+.B backup
+As described above under the
+.B -b
+flag.
+.TP
+.B delete
+As described above under the
+.B -d
+flag.
+.TP
+.B execute
+As described above under the
+.B -e
+flag.
+.TP
+.B keep
+As described above under the
+.B -k
+flag.
+.TP
+.B old
+As described above under the
+.B -o
+flag.
+.TP
+.B use-rel-suffix
+Causes the release name to be used as a suffix to the
+.I last
+and
+.I when
+files. This is necessary whenever you are supping more than one
+release in the same collection.
+.i0
+.DT
+.PP
+.SH "PREPARING A FILE COLLECTION REPOSITORY"
+A set of files residing on a repository must be prepared before
+.I sup
+client processes can upgrade those files.
+The collection must
+be given a
+.I name
+and a
+.I base directory.
+If it is a private collection, client users
+must be told the name of the collection, repository host, and
+base directory;
+these will be specified in the supfile via the
+.B host
+and
+.B hostbase
+options.
+For a system-maintained file collection, entries must be
+placed into the host list file and directory list file as described
+in
+.IR supservers (8).
+
+Within the base directory, a subdirectory must be created called
+.B sup .
+Within this directory there must be a subdirectory for each
+collection using that base directory, whose name is the name of the
+collection; within each of these directories will be a
+list file and possibly a prefix file, a host file, an encryption key
+file, a log file and
+a scan file.
+The filenames are listed under FILES below.
+.TP
+.B prefix
+Normally, all files in the collection are relative to the base directory.
+This file contains a single line which is the name of a directory to be
+used in place of the base directory for file references.
+.TP
+.B host
+Normally,
+all remote host machines are allowed access to a file collection.
+If you wish to restrict access to specific remote hosts for this
+collection,
+put each allowed hostname on a
+separate line of text in this file.
+If a host has more than one name, only one of its names needs to be
+listed.
+The name
+.B LOCAL
+can be used to grant access to all hosts on the local
+network. The host name may be a numeric network adddress
+or a network name. If a crypt appears on the same line as
+the host name, that crypt will be used for that host. Otherwise,
+the crypt appearing in the
+.I crypt
+file, if any will be used.
+.TP
+.B crypt
+If you wish to use the
+.I sup
+data encryption mechanism, create an encryption file containing,
+on a single line of text, the desired encryption key.
+Client
+processes must then specify the same key with the
+.B crypt
+option in the supfile or they will be denied access to the files.
+In addition, actual network transmission of file contents and
+filenames will be encrypted.
+.TP
+.B list
+This file describes the actual list of files to be included in this
+file collection, in a format described below.
+.TP
+.B releases
+This file describes any releases that the collection may have. Each
+line starts with the release name and then may specify any of the following
+files:
+.I prefix=<dirname>
+to use a different parent directory for the files in this release.
+.I list=<listname>
+to specify the list of files in the release.
+.I scan=<scanfile>
+must be used in multi-release collections that are scanned to keep
+the scan files for the different releases separate.
+.I host=<hostfile>
+to allow different host restrictions for this release.
+.I next=<release>
+used to chain releases together. This has the effect of making one release
+be a combination of serveral other releases. If the same file appears in
+more than one chained release, the first one found will be used.
+If these files are not specified for a release the default names:
+prefix,list,scan and host will be used.
+.TP
+.B scan
+This file, created by
+.IR supscan ,
+is the list of filenames that correspond to the instructions in the
+list file. The scan file is only used for frequently-updated file
+collections; it makes the file server run much faster. See
+.IR supservers (8)
+for more information.
+.TP
+.B lock
+As previously mentioned, this file is used to indicate that the
+collection should be locked while upgrades are in progress. All
+file servers will try to get shared access to the lock file with
+.IR flock (2).
+.TP
+.B logfile
+If a log file exists in the collection directory, the file server
+will append the last time an upgrade was successfully completed,
+the time the last upgrade started and finished, and the name of
+the host requesting the upgrade.
+.i0
+.DT
+.PP
+It should be noted that
+.I sup
+allows several different named collections to use the same base
+directory. Separate encryption, remote host access, and file lists
+are used for each collection, since these files reside in subdirectorie
+.I <basedir>/sup/<coll.name>.
+
+The list file is a text file with one command on each line.
+Each command
+contains a keyword and a number of operands separated by spaces.
+All filenames in the list file are evaluated on the repository machine
+relative to the host's base directory, or prefix directory if one is
+specified, and on your machine with respect
+to the base, or prefix, directory for the client.
+The
+.I filenames
+below (except \fIexec-command\fR)
+may all include wild-cards and meta-characters as used by
+.IR csh (1)
+including *, ?, [...], and {...}. The commands are:
+.TP
+\fBupgrade\fR \fIfilename\fR ...
+The specified file(s) (or directories) will be included in the list
+of files to be upgraded.
+If a directory name is given, it recursively
+includes all subdirectories and files within that directory.
+.TP
+\fBalways\fR \fIfilename\fR ...
+The always command is identical to upgrade, except that omit and
+omitany commands do not affect filenames specified with the always
+command.
+.TP
+\fBomit\fR \fIfilename\fR ...
+The specified file(s) (or directories) will be excluded from the
+list of files to be upgraded.
+For example, by specifying
+.B upgrade /usr/vision
+and
+.B omit /usr/vision/exp,
+the generated list
+of files would include all subdirectories and files of /usr/vision
+except /usr/vision/exp (and its subdirectories and files).
+.TP
+\fBomitany\fR \fIpattern\fR ...
+The specified patterns are compared against the files in the upgrade
+list. If a pattern matches, the file is omitted. The omitany command
+currently supports all wild-card patterns except {...}. Also, the
+pattern must match the entire filename, so a leading */, or a trailing /*,
+may be necessary in the pattern.
+.TP
+\fBbackup\fR \fIfilename\fR ...
+The specified file(s) are marked for backup; if they are upgraded
+and the client has specified the
+.B backup
+option in the corresponding
+line of the supfile, then backup copies will be created as described
+above.
+Directories may not be specified, and no recursive filename
+construction is performed; you must specify the names of the specific
+files to be backed up before upgrading.
+.TP
+\fBnoaccount\fR \fIfilename\fR ...
+The accounting information of the specified file(s) will not be
+preserved by
+.IR sup .
+Accounting information consists of the owner,
+group, mode and modified time of a file.
+.TP
+\fBsymlink\fR \fIfilename\fR ...
+The specified file(s) are to be treated as symbolic links
+and will be transfered as such and not followed. By default,
+.I sup
+will follow symbolic links.
+.TP
+\fBrsymlink\fR \fIdirname\fR ...
+All symbolic links in the specified directory and its
+subdirectories are to be treated as symbolic links. That
+is the links will be transferred and not the files to which
+they point.
+.TP
+\fBexecute\fR \fIexec-command\fR (\fIfilename\fR ...)
+The
+.I exec-command
+you specified will be executed on the client process
+whenever any of the files listed in parentheses are upgraded.
+A special token,
+.B %s,
+may be specified in the
+.I exec-command
+and will be replaced by the name of the file that was upgraded.
+For example, if you say
+\fBexecute ranlib %s (libc.a)\fR,
+then whenever libc.a is upgraded, the client machine will execute
+.B
+ranlib libc.a.
+As described above, the client must invoke
+.I sup
+with the
+.B -e
+flag to allow the automatic execution of command files.
+.TP
+\fBinclude\fR \fIlistfile\fR ...
+The specified
+.I listfiles
+will be read at this point. This is useful
+when one collection subsumes other collections; the larger collection
+can simply specify the listfiles for the smaller collections contained
+within it.
+.i0
+.DT
+.PP
+The order in which the command lines appear in the list file does not
+matter. Blank lines may appear freely in the list file.
+.SH "FILES"
+Files on the client machine for
+.IR sup :
+.TP
+.B /usr/lib/supfiles/coll.list
+supfile used for -s flag
+.TP
+.B /usr/lib/supfiles/coll.what
+supfile used for -s flag when -t flag is also specified
+.TP
+.B /usr/lib/supfiles/coll.host
+host name list for system collections
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/last\fR<\fI.release\fR>
+recorded list of files in collection as of last upgrade
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/lock
+file used to lock collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/refuse
+list of files to refuse in collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/when\fR<\fI.release\fR>
+recorded time of last upgrade
+.TP
+\fB/usr/sup/\fR<\fIcollection\fR>
+default base directory for file collection
+.i0
+.DT
+.PP
+
+Files needed on each repository machine for the file server:
+.TP
+.B /usr/lib/supfiles/coll.dir
+base directory list for system
+collections
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/crypt
+data encryption key for a
+collection. the owner of this file is the
+default account used when data encryption is specified
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/host
+list of remote hosts allowed to
+upgrade a collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/list
+list file for a collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/lock
+lock file for a collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/logfile
+log file for a collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/prefix
+file containing the name of the prefix directory
+for a collection
+.TP
+<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/scan
+scan file for a collection
+.TP
+\fB/usr/\fR<\fIcollection\fR>
+default base directory for a file collection
+.i0
+.DT
+.PP
+.SH "SEE ALSO"
+.IR supservers (8)
+.br
+\fIThe SUP Software Upgrade Protocol\fR, S. A. Shafer,
+CMU Computer Science Department, 1985.
+.SH "EXAMPLE"
+<example>
+.SH "BUGS"
+The encryption mechanism should be strengthened, although it's
+not trivial.
diff --git a/usr.bin/sup/src/sup.h b/usr.bin/sup/src/sup.h
new file mode 100644
index 00000000000..eee3b860107
--- /dev/null
+++ b/usr.bin/sup/src/sup.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/* sup.h -- declarations for sup, supnamesrv, supfilesrv
+ *
+ * VERSION NUMBER for any program is given by: a.b (c)
+ * where a = PROTOVERSION is the protocol version #
+ * b = PGMVERSION is program # within protocol
+ * c = scmversion is communication module version
+ * (i.e. operating system for which scm is configured)
+ **********************************************************************
+ * HISTORY
+ * 13-Sep-92 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed name of DEFDIR from /usr/cs to /usr.
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: sup.h,v $
+ * Revision 1.1 1995/12/16 11:46:55 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.3 1995/06/03 21:21:54 christos
+ * Changes to write ascii timestamps in the when files.
+ * Looked into making it 64 bit clean, but it is hopeless.
+ * Added little program to convert from the old timestamp files
+ * into the new ones.
+ *
+ * Revision 1.2 1993/08/04 17:46:15 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.10 92/08/11 12:06:42 mrt
+ * Added definition for DEBUGFPORTNUM, the debugging port number.
+ * Changed so that last and when file names could include
+ * the relase name if any.
+ * [92/07/23 mrt]
+ *
+ * Revision 1.9 91/04/29 14:39:03 mja
+ * Reduce MAXCHILDREN from 8 to 3.
+ *
+ * Revision 1.8 89/08/23 14:55:30 gm0w
+ * Moved coll.dir from supservers to supfiles.
+ * [89/08/23 gm0w]
+ *
+ * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added host=<hostfile> support to releases file.
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support. Removed nameserver support.
+ *
+ * 27-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added TREELIST and other changes for "release" support.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Version 6 of the network protocol, better support to reflect errors
+ * back to server logfile.
+ *
+ * 21-May-87 Chriss Stephens (chriss) at Carnegie Mellon University
+ * Merged divergent CS and EE versions.
+ *
+ * 19-Sep-86 Mike Accetta (mja) at Carnegie-Mellon University
+ * Added FILESUPTDEFAULT definition.
+ *
+ * 07-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed FILESRVBUSYWAIT. Now uses exponential backoff.
+ *
+ * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added numeric port numbers to use when port names are not in the
+ * host table.
+ *
+ * 04-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Update protocol version to 5 for name server protocol change to
+ * allow multiple repositories per collection. Added FILESRVBUSYWAIT
+ * of 5 minutes. Added FILELOCK file to indicate collections that
+ * should be exclusively locked when upgraded.
+ *
+ * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Merged 4.1 and 4.2 versions together.
+ *
+ * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for 4.2 BSD.
+ *
+ **********************************************************************
+ */
+
+/* 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"
+#define FILEPORTNUM 871
+#define DEBUGFPORT "supfiledbg"
+#define DEBUGFPORTNUM 1127
+
+/* Data files used in scan.c */
+#define FILELIST "sup/%s/%s"
+#define FILESCAN "sup/%s/%s"
+#define FILEHOST "sup/%s/%s"
+#define FILELISTDEF "list"
+#define FILESCANDEF "scan"
+#define FILEHOSTDEF "host"
+#define DEFRELEASE "default"
+
+/* Data files used in sup.c */
+#define FILEBASEDEFAULT "/usr/%s" /* also supfilesrv and supscan */
+#ifdef EE_XXX
+#define FILESUPDEFAULT "%s/supfiles/coll.list"
+#define FILESUPTDEFAULT "%s/supfiles/coll.what"
+#define FILEHOSTS "%s/supfiles/coll.host"
+#else EE_XXX
+#define FILESUPDEFAULT "%s/lib/supfiles/coll.list"
+#define FILESUPTDEFAULT "%s/lib/supfiles/coll.what"
+#define FILEHOSTS "%s/lib/supfiles/coll.host"
+#endif EE_XXX
+#define FILEBKDIR "%s/BACKUP"
+#define FILEBACKUP "%s/BACKUP/%s"
+#define FILELAST "sup/%s/last%s"
+#define FILELASTTEMP "sup/%s/last.temp"
+#define FILELOCK "sup/%s/lock" /* also supfilesrv */
+#define FILEREFUSE "sup/%s/refuse"
+#define FILEWHEN "sup/%s/when%s"
+
+/* Data files used in supfilesrv.c */
+#define FILEXPATCH "%s/sup/xpatch.host"
+#ifdef EE_XXX
+#define FILEDIRS "%s/supfiles/coll.dir" /* also supscan */
+#else EE_XXX
+#define FILEDIRS "%s/lib/supfiles/coll.dir" /* also supscan */
+#endif EE_XXX
+#define FILECRYPT "sup/%s/crypt"
+#define FILELOGFILE "sup/%s/logfile"
+#define FILEPREFIX "sup/%s/prefix" /* also supscan */
+#define FILERELEASES "sup/%s/releases" /* also supscan */
+
+/* String length */
+#define STRINGLENGTH 2000
+
+/* Password transmission encryption key */
+#define PSWDCRYPT "SuperMan"
+/* Test string for encryption */
+#define CRYPTTEST "Hello there, Sailor Boy!"
+
+/* Default directory for system sup information */
+#ifndef DEFDIR
+#ifdef EE_XXX
+#define DEFDIR "/etc"
+#else EE_XXX
+#define DEFDIR "/usr"
+#endif EE_XXX
+#endif DEFDIR
+
+/* Default login account for file server */
+#ifndef DEFUSER
+#define DEFUSER "anon"
+#endif DEFUSER
+
+/* subroutine return codes */
+#define SCMOK (1) /* routine performed correctly */
+#define SCMEOF (0) /* read EOF on network connection */
+#define SCMERR (-1) /* error occurred during routine */
+
+/* data structure for describing a file being upgraded */
+
+struct treestruct {
+/* fields for file information */
+ char *Tname; /* path component name */
+ int Tflags; /* flags of file */
+ int Tmode; /* st_mode of file */
+ char *Tuser; /* owner of file */
+ int Tuid; /* owner id of file */
+ char *Tgroup; /* group of file */
+ int Tgid; /* group id of file */
+ int Tctime; /* inode modification time */
+ int Tmtime; /* data modification time */
+ struct treestruct *Tlink; /* tree of link names */
+ struct treestruct *Texec; /* tree of execute commands */
+/* fields for sibling AVL tree */
+ int Tbf; /* balance factor */
+ struct treestruct *Tlo,*Thi; /* ordered sibling tree */
+};
+typedef struct treestruct TREE;
+
+/* data structure to represent a list of trees to upgrade */
+
+struct tliststruct {
+ struct tliststruct *TLnext; /* next entry in tree list */
+/* fields for tree information */
+ char *TLname; /* release name for tree */
+ char *TLprefix; /* prefix of tree */
+ char *TLlist; /* name of list file */
+ char *TLscan; /* name of scan file */
+ char *TLhost; /* name of host file */
+ TREE *TLtree; /* tree of files to upgrade */
+};
+typedef struct tliststruct TREELIST;
+
+/* bitfield not defined in stat.h */
+#define S_IMODE 07777 /* part of st_mode that chmod sets */
+
+/* flag bits for files */
+#define FNEW 01 /* ctime of file has changed */
+#define FBACKUP 02 /* backup of file is allowed */
+#define FNOACCT 04 /* don't set file information */
+#define FUPDATE 010 /* only set file information */
+#define FNEEDED 0100000 /* file needed for upgrade */
+
+/* version 3 compatability */
+#define FCOMPAT 0010000 /* Added to detect execute commands to send */
+
+/* message types now obsolete */
+#define MSGFEXECQ (115)
+#define MSGFEXECNAMES (116)
+
+/* flag bits for files in list of all files */
+#define ALLNEW 01
+#define ALLBACKUP 02
+#define ALLEND 04
+#define ALLDIR 010
+#define ALLNOACCT 020
+#define ALLSLINK 0100
+
+/* flag bits for file mode word */
+#define MODELINK 010000
+#define MODEDIR 040000
+#define MODESYM 0100000
+#define MODENOACCT 0200000
+#define MODEUPDATE 01000000
+
+/* blocking factor for filenames in list of all file names */
+#define BLOCKALL 32
+
+/* end version 3 compatability */
+
+#define MAXCHILDREN 3 /* maximum number of children allowed
+ to sup at the same time */
+
+/* scm and stree external declarations */
+char *remotehost();
+TREE *Tinsert(),*Tsearch(),*Tlookup();
+long getwhen();
+int putwhen();
diff --git a/usr.bin/sup/src/supcdefs.h b/usr.bin/sup/src/supcdefs.h
new file mode 100644
index 00000000000..12261403e34
--- /dev/null
+++ b/usr.bin/sup/src/supcdefs.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * supcdefs.h -- Declarations shared by the collection of files
+ * that build the sup client.
+ *
+ **********************************************************************
+ * HISTORY
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supcdefs.h,v $
+ * Revision 1.1 1995/12/16 11:46:55 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1993/08/04 17:46:16 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.6 92/08/11 12:06:52 mrt
+ * Added CFURELSUF - use-release-suffix flag
+ * Made rpause code conditional on MACH rather than CMUCS
+ * [92/07/26 mrt]
+ *
+ * Revision 1.5 92/02/08 18:23:57 mja
+ * Added CFKEEP flag.
+ * [92/01/17 vdelvecc]
+ *
+ * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added timeout for backoff.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added Crelease for "release" support.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Created.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#include <netdb.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+#if MACH /* used by resource pausing code only */
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#endif /* MACH */
+#include <c.h>
+#include "sup.h"
+#include "supmsg.h"
+
+extern int errno;
+extern uid_t getuid();
+extern gid_t getgid();
+extern long time();
+
+extern int PGMVERSION;
+
+/*******************************************
+ *** D A T A S T R U C T U R E S ***
+ *******************************************/
+
+struct collstruct { /* one per collection to be upgraded */
+ char *Cname; /* collection name */
+ TREE *Chost; /* attempted host for collection */
+ TREE *Chtree; /* possible hosts for collection */
+ char *Cbase; /* local base directory */
+ char *Chbase; /* remote base directory */
+ char *Cprefix; /* local collection pathname prefix */
+ char *Crelease; /* release name */
+ char *Cnotify; /* user to notify of status */
+ char *Clogin; /* remote login name */
+ char *Cpswd; /* remote password */
+ char *Ccrypt; /* data encryption key */
+ int Ctimeout; /* timeout for backoff */
+ int Cflags; /* collection flags */
+ int Cnogood; /* upgrade no good, "when" unchanged */
+ int Clockfd; /* >= 0 if collection is locked */
+ struct collstruct *Cnext; /* next collection */
+};
+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
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+#define vnotify if (thisC->Cflags&CFVERBOSE) notify
diff --git a/usr.bin/sup/src/supcmain.c b/usr.bin/sup/src/supcmain.c
new file mode 100644
index 00000000000..5568acb91a8
--- /dev/null
+++ b/usr.bin/sup/src/supcmain.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * sup -- Software Upgrade Protocol client process
+ *
+ * Usage: sup [ flags ] [ supfile ] [ collection ... ]
+ *
+ * The only required argument to sup is the name of a supfile. It
+ * must either be given explicitly on the command line, or the -s
+ * flag must be specified. If the -s flag is given, the system
+ * supfile will be used and a supfile command argument should not be
+ * specified. The list of collections is optional and if specified
+ * will be the only collections upgraded. The following flags affect
+ * all collections specified.
+ *
+ * -s "system upgrade" flag
+ * As described above.
+ *
+ * -t "upgrade time" flag
+ * When this flag is given, Sup will print the time
+ * that each collection was last upgraded, rather than
+ * performing actual upgrades.
+ *
+ * -R "resource pause" flag
+ * Sup will not disable resource pausing and will not
+ * make filesystem space checks.
+ *
+ * -N "debug network" flag
+ * Sup will trace messages sent and received that
+ * implement the Sup network protocol.
+ *
+ * -P "debug ports" flag
+ * Sup will use a set of non-privileged network
+ * ports reserved for debugging purposes.
+ *
+ * -X "crosspatch" flag
+ * Sup is being run remotely with a crosspatch.
+ * Need to be carefull as we may be running as root
+ * instead of collection owner.
+ *
+ * The remaining flags affect all collections unless an explicit list
+ * of collections are given with the flags. Multiple flags may be
+ * specified together that affect the same collections. For the sake
+ * of convience, any flags that always affect all collections can be
+ * specified with flags that affect only some collections. For
+ * example, "sup -sde=coll1,coll2" would perform a system upgrade,
+ * and the first two collections would allow both file deletions and
+ * command executions. Note that this is not the same command as
+ * "sup -sde=coll1 coll2", which would perform a system upgrade of
+ * just the coll2 collection and would ignore the flags given for the
+ * coll1 collection.
+ *
+ * -a "all files" flag
+ * All files in the collection will be copied from
+ * the repository, regardless of their status on the
+ * current machine. Because of this, it is a very
+ * expensive operation and should only be done for
+ * small collections if data corruption is suspected
+ * and been confirmed. In most cases, the -o flag
+ * should be sufficient.
+ *
+ * -b "backup files" flag
+ * If the -b flag if given, or the "backup" supfile
+ * option is specified, the contents of regular files
+ * on the local system will be saved before they are
+ * overwritten with new data. The data will be saved
+ * in a subdirectory called "BACKUP" in the directory
+ * containing the original version of the file, in a
+ * file with the same non-directory part of the file
+ * name. The files to backup are specified by the
+ * list file on the repository.
+ *
+ * -B "don't backup files" flag
+ * The -B flag overrides and disables the -b flag and
+ * the "backup" supfile option.
+ *
+ * -d "delete files" flag
+ * Files that are no longer in the collection on the
+ * repository will be deleted if present on the local
+ * machine. This may also be specified in a supfile
+ * with the "delete" option.
+ *
+ * -D "don't delete files" flag
+ * The -D flag overrides and disables the -d flag and
+ * the "delete" supfile option.
+ *
+ * -e "execute files" flag
+ * Sup will execute commands sent from the repository
+ * that should be run when a file is upgraded. If
+ * the -e flag is omitted, Sup will print a message
+ * that specifies the command to execute. This may
+ * also be specified in a supfile with the "execute"
+ * option.
+ *
+ * -E "don't execute files" flag
+ * The -E flag overrides and disables the -e flag and
+ * the "execute" supfile option.
+ *
+ * -f "file listing" flag
+ * A "list-only" upgrade will be performed. Messages
+ * will be printed that indicate what would happen if
+ * an actual upgrade were done.
+ *
+ * -k "keep newer files" flag
+ * The -k flag, or "keep" supfile option, will cause
+ * Sup to check to see whether there is a newer file on
+ * the local disk before updating files. Only files
+ * which are newer on the repository will be updated.
+ *
+ * -K "don't keep newer files" flag
+ * The -K flag overrides and disables the -k flag and
+ * the "keep" supfile option.
+ *
+ * -l "local upgrade" flag
+ * Normally, Sup will not upgrade a collection if the
+ * repository is on the same machine. This allows
+ * users to run upgrades on all machines without
+ * having to make special checks for the repository
+ * machine. If the -l flag is specified, collections
+ * will be upgraded even if the repository is local.
+ *
+ * -m "mail" flag
+ * Normally, Sup used standard output for messages.
+ * If the -m flag if given, Sup will send mail to the
+ * user running Sup, or a user specified with the
+ * "notify" supfile option, that contains messages
+ * printed by Sup.
+ *
+ * -o "old files" flag
+ * Sup will normally only upgrade files that have
+ * changed on the repository since the last time an
+ * upgrade was performed. The -o flag, or the "old"
+ * supfile option, will cause Sup to check all files
+ * in the collection for changes instead of just the
+ * new ones.
+ *
+ * -O "not old files" flag
+ * The -O flag overrides and disables the -o flag and
+ * the "old" supfile option.
+ *
+ * -v "verbose" flag
+ * Normally, Sup will only print messages if there
+ * are problems. This flag causes Sup to also print
+ * messages during normal progress showing what Sup
+ * is doing.
+ *
+ **********************************************************************
+ * HISTORY
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supcmain.c,v $
+ * Revision 1.1 1995/12/16 11:46:56 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.4 1995/09/16 19:01:25 glass
+ * if the function returns nothing, declare it void
+ *
+ * Revision 1.3 1993/08/04 17:46:17 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.2 1993/05/24 17:57:28 brezak
+ * Remove netcrypt.c. Remove unneeded files. Cleanup make.
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.6 92/08/11 12:06:59 mrt
+ * Merged in Brad's changes. Made resource pausing code conditional
+ * on MACH, rather than CMUCS. Fixed some calls to sprintf to
+ * return void.
+ * [92/08/09 mrt]
+ *
+ * Revision 1.5 92/02/08 19:01:18 mja
+ * Correct oldsigsys type when ANSI C.
+ * [92/02/08 18:59:47 mja]
+ *
+ * Revision 1.4 92/02/08 18:24:01 mja
+ * Added -k and -K switches.
+ * [92/01/17 vdelvecc]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support (is currently ignored).
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Split into several files. This is the main program and
+ * command line processing and old history log. [V5.21]
+ *
+ * 21-May-87 Chriss Stephens (chriss) at Carnegie Mellon University
+ * Merged divergent CS and ECE versions. ifdeffed out the resource
+ * pausing code - only compiled in if CMUCS defined. [V5.21a]
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed support for version 3 of SUP protocol. Added changes
+ * to make lint happy. Added calls to new logging routines. [V5.20]
+ *
+ * 01-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added -R switch to reenable resource pausing, which is currently
+ * disabled by default. Added code to check for free disk space
+ * available on the target filesystem so that sup shouldn't run the
+ * system out of disk space as frequently. [V5.19]
+ *
+ * 19-Sep-86 Mike Accetta (mja) at Carnegie-Mellon University
+ * Changed default supfile name for system collections when -t
+ * is specified to use FILESUPTDEFAULT; added missing new-line
+ * in retry message. [V5.18]
+ *
+ * 21-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Missed a caller to a routine which had an extra argument added
+ * to it last edit. [V5.17]
+ *
+ * 07-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed getcoll() so that fatal errors are checked immediately
+ * instead of after sleeping for a little while. Changed all
+ * rm -rf commands to rmdir since the Mach folks keep deleting
+ * their root and /usr directory trees. Reversed the order of
+ * delete commands to that directories will possibly empty so
+ * that the rmdir's work. [V5.16]
+ *
+ * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed temporary file names to #n.sup format. [V5.15]
+ *
+ * 19-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Moved PGMVERSION to supvers.c module. [V5.14]
+ *
+ * 06-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added check for file type before unlink when receiving a
+ * symbolic link. Now runs "rm -rf" if the file type is a
+ * directory. [V5.13]
+ *
+ * 03-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fixed small bug in signon that didn't retry connections if an
+ * error occured on the first attempt to connect. [V5.12]
+ *
+ * 26-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * New command interface. Added -bBDEO flags and "delete",
+ * "execute" and "old" supfile options. Changed -d to work
+ * correctly without implying -o. [V5.11]
+ *
+ * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fix incorrect check for supfile changing. Flush output buffers
+ * before restart. [V5.10]
+ *
+ * 17-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Add call to requestend() after connection errors are retried to
+ * free file descriptors. [V5.9]
+ *
+ * 15-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fix SERIOUS merge error from previous edit. Added notify
+ * when execute command fails. [V5.8]
+ *
+ * 11-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed ugconvert to clear setuid/setgid bits if it doesn't use
+ * the user and group specified by the remote system. Changed
+ * execute code to invalidate collection if execute command returns
+ * with a non-zero exit status. Added support for execv() of
+ * original arguments of supfile is upgraded sucessfully. Changed
+ * copyfile to always use a temp file if possible. [V5.7]
+ *
+ * 04-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added support for fileserver busy messages and new nameserver
+ * protocol to support multiple repositories per collection.
+ * Added code to lock collections with lock files. [V5.6]
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Major rewrite for protocol version 4. [V4.5]
+ *
+ * 12-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed to check for DIFFERENT mtime (again). [V3.4]
+ *
+ * 08-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Replaced [ug]convert routines with ugconvert routine so that an
+ * appropriate group will be used if the default user is used.
+ * Changed switch parsing to allow multiple switches to be specified
+ * at the same time. [V3.3]
+ *
+ * 04-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added test to request a new copy of an old file that already
+ * exists if the mtime is different. [V3.2]
+ *
+ * 24-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added -l switch to enable upgrades from local repositories.
+ *
+ * 03-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Minor change in order -t prints so that columns line up.
+ *
+ * 22-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to implement retry flag and pass this on to request().
+ *
+ * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Merged 4.1 and 4.2 versions together.
+ *
+ * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for 4.2 BSD.
+ *
+ **********************************************************************
+ */
+
+#define MSGFILE
+#include "supcdefs.h"
+#if MACH
+#include <sys/syscall.h>
+#ifndef SYS_rpause
+#define SYS_rpause (-5)
+#endif
+#endif
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+char program[] = "SUP"; /* program name for SCM messages */
+int progpid = -1; /* and process id */
+
+COLLECTION *firstC,*thisC; /* collection list pointer */
+
+extern int dontjump; /* disable longjmp */
+extern int scmdebug; /* SCM debugging flag */
+
+int sysflag; /* system upgrade flag */
+int timeflag; /* print times flag */
+#if MACH
+int rpauseflag; /* don't disable resource pausing */
+#endif /* MACH */
+int xpatchflag; /* crosspatched with remote system */
+int portdebug; /* network debugging ports */
+
+/*************************************
+ *** M A I N R O U T I N E ***
+ *************************************/
+
+main (argc,argv)
+int argc;
+char **argv;
+{
+ char *init ();
+ char *progname,*supfname;
+ int restart,sfdev,sfino,sfmtime;
+ struct stat sbuf;
+ struct sigvec ignvec,oldvec;
+
+ /* initialize global variables */
+ pgmversion = PGMVERSION; /* export version number */
+ server = FALSE; /* export that we're not a server */
+ collname = NULL; /* no current collection yet */
+ dontjump = TRUE; /* clear setjmp buffer */
+ progname = salloc (argv[0]);
+
+ supfname = init (argc,argv);
+ restart = -1; /* don't make restart checks */
+ if (*progname == '/' && *supfname == '/') {
+ if (stat (supfname,&sbuf) < 0)
+ logerr ("Can't stat supfile %s",supfname);
+ else {
+ sfdev = sbuf.st_dev;
+ sfino = sbuf.st_ino;
+ sfmtime = sbuf.st_mtime;
+ restart = 0;
+ }
+ }
+ if (timeflag) {
+ for (thisC = firstC; thisC; thisC = thisC->Cnext)
+ prtime ();
+ } else {
+ /* ignore network pipe signals */
+ ignvec.sv_handler = SIG_IGN;
+ ignvec.sv_onstack = 0;
+ ignvec.sv_mask = 0;
+ (void) sigvec (SIGPIPE,&ignvec,&oldvec);
+ getnams (); /* find unknown repositories */
+ for (thisC = firstC; thisC; thisC = thisC->Cnext) {
+ getcoll (); /* upgrade each collection */
+ if (restart == 0) {
+ if (stat (supfname,&sbuf) < 0)
+ logerr ("Can't stat supfile %s",
+ supfname);
+ else if (sfmtime != sbuf.st_mtime ||
+ sfino != sbuf.st_ino ||
+ sfdev != sbuf.st_dev) {
+ restart = 1;
+ break;
+ }
+ }
+ }
+ endpwent (); /* close /etc/passwd */
+ (void) endgrent (); /* close /etc/group */
+ if (restart == 1) {
+ int fd;
+ loginfo ("SUP Restarting %s with new supfile %s",
+ progname,supfname);
+ for (fd = getdtablesize (); fd > 3; fd--)
+ (void) close (fd);
+ execv (progname,argv);
+ logquit (1,"Restart failed");
+ }
+ }
+ while (thisC = firstC) {
+ firstC = firstC->Cnext;
+ free (thisC->Cname);
+ Tfree (&thisC->Chtree);
+ free (thisC->Cbase);
+ if (thisC->Chbase) free (thisC->Chbase);
+ if (thisC->Cprefix) free (thisC->Cprefix);
+ if (thisC->Crelease) free (thisC->Crelease);
+ if (thisC->Cnotify) free (thisC->Cnotify);
+ if (thisC->Clogin) free (thisC->Clogin);
+ if (thisC->Cpswd) free (thisC->Cpswd);
+ if (thisC->Ccrypt) free (thisC->Ccrypt);
+ free ((char *)thisC);
+ }
+ exit (0);
+}
+
+/*****************************************
+ *** I N I T I A L I Z A T I O N ***
+ *****************************************/
+/* Set up collection list from supfile. Check all fields except
+ * hostname to be sure they make sense.
+ */
+
+#define Toflags Tflags
+#define Taflags Tmode
+#define Twant Tuid
+#define Tcount Tgid
+
+void doswitch (argp,collTp,oflagsp,aflagsp)
+char *argp;
+register TREE **collTp;
+int *oflagsp,*aflagsp;
+{
+ register TREE *t;
+ register char *coll;
+ register int oflags,aflags;
+
+ oflags = aflags = 0;
+ for (;;) {
+ switch (*argp) {
+ default:
+ logerr ("Invalid flag '%c' ignored",*argp);
+ break;
+ case '\0':
+ case '=':
+ if (*argp++ == '\0' || *argp == '\0') {
+ *oflagsp |= oflags;
+ *oflagsp &= ~aflags;
+ *aflagsp |= aflags;
+ *aflagsp &= ~oflags;
+ return;
+ }
+ do {
+ coll = nxtarg (&argp,", \t");
+ t = Tinsert (collTp,coll,TRUE);
+ t->Toflags |= oflags;
+ t->Toflags &= ~aflags;
+ t->Taflags |= aflags;
+ t->Taflags &= ~oflags;
+ argp = skipover (argp,", \t");
+ } while (*argp);
+ return;
+ case 'N':
+ scmdebug++;
+ break;
+ case 'P':
+ portdebug = TRUE;
+ break;
+ case 'R':
+#if MACH
+ rpauseflag = TRUE;
+#endif /* MACH */
+ break;
+ case 'X':
+ xpatchflag = TRUE;
+ break;
+ case 's':
+ sysflag = TRUE;
+ break;
+ case 't':
+ timeflag = TRUE;
+ break;
+ case 'a':
+ oflags |= CFALL;
+ break;
+ case 'b':
+ oflags |= CFBACKUP;
+ aflags &= ~CFBACKUP;
+ break;
+ case 'B':
+ oflags &= ~CFBACKUP;
+ aflags |= CFBACKUP;
+ break;
+ case 'd':
+ oflags |= CFDELETE;
+ aflags &= ~CFDELETE;
+ break;
+ case 'D':
+ oflags &= ~CFDELETE;
+ aflags |= CFDELETE;
+ break;
+ case 'e':
+ oflags |= CFEXECUTE;
+ aflags &= ~CFEXECUTE;
+ break;
+ case 'E':
+ oflags &= ~CFEXECUTE;
+ aflags |= CFEXECUTE;
+ break;
+ case 'f':
+ oflags |= CFLIST;
+ break;
+ case 'k':
+ oflags |= CFKEEP;
+ aflags &= ~CFKEEP;
+ break;
+ case 'K':
+ oflags &= ~CFKEEP;
+ aflags |= CFKEEP;
+ break;
+ case 'l':
+ oflags |= CFLOCAL;
+ break;
+ case 'm':
+ oflags |= CFMAIL;
+ break;
+ case 'o':
+ oflags |= CFOLD;
+ aflags &= ~CFOLD;
+ break;
+ case 'O':
+ oflags &= ~CFOLD;
+ aflags |= CFOLD;
+ break;
+ case 'v':
+ oflags |= CFVERBOSE;
+ break;
+ case 'z':
+ oflags |= CFCOMPRESS;
+ break;
+ case 'Z':
+ oflags &= ~CFCOMPRESS;
+ break;
+ }
+ argp++;
+ }
+}
+
+char *init (argc,argv)
+int argc;
+char **argv;
+{
+ char buf[STRINGLENGTH],*p;
+ char username[STRINGLENGTH];
+ register char *supfname,*q,*arg;
+ register COLLECTION *c,*lastC;
+ register FILE *f;
+ register int bogus;
+ register struct passwd *pw;
+ register TREE *t;
+ TREE *collT; /* collections we are interested in */
+ long timenow; /* startup time */
+ int checkcoll ();
+ int oflags,aflags;
+ int cwant;
+#ifdef MACH
+#ifdef __STDC__
+ void (*oldsigsys)();
+#else
+ int (*oldsigsys)();
+#endif
+#endif /* MACH */
+ char *fmttime();
+
+ sysflag = FALSE; /* not system upgrade */
+ timeflag = FALSE; /* don't print times */
+#if MACH
+ rpauseflag = FALSE; /* don't disable resource pausing */
+#endif /* MACH */
+ xpatchflag = FALSE; /* not normally crosspatched */
+ scmdebug = 0; /* level zero, no SCM debugging */
+ portdebug = FALSE; /* no debugging ports */
+
+ collT = NULL;
+ oflags = aflags = 0;
+ while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
+ doswitch (&argv[1][1],&collT,&oflags,&aflags);
+ --argc;
+ argv++;
+ }
+ if (argc == 1 && !sysflag)
+ logquit (1,"Need either -s or supfile");
+#if MACH
+ oldsigsys = signal (SIGSYS,SIG_IGN);
+ if (rpauseflag != TRUE)
+ if (syscall (SYS_rpause,ENOSPC,RPAUSE_ALL,RPAUSE_DISABLE) < 0)
+ rpauseflag = TRUE;
+ (void) signal (SIGSYS,oldsigsys);
+#endif /* MACH */
+ if (sysflag)
+ (void) sprintf (supfname = buf,
+ timeflag?FILESUPTDEFAULT:FILESUPDEFAULT,
+ DEFDIR);
+ else {
+ supfname = argv[1];
+ if (strcmp (supfname,"-") == 0)
+ supfname = "";
+ --argc;
+ argv++;
+ }
+ cwant = argc > 1;
+ while (argc > 1) {
+ t = Tinsert (&collT,argv[1],TRUE);
+ t->Twant = TRUE;
+ --argc;
+ argv++;
+ }
+ if ((p = (char *)getlogin()) ||
+ ((pw = getpwuid ((int)getuid())) && (p = pw->pw_name)))
+ (void) strcpy (username,p);
+ else
+ *username = '\0';
+ if (*supfname) {
+ f = fopen (supfname,"r");
+ if (f == NULL)
+ logquit (1,"Can't open supfile %s",supfname);
+ } else
+ f = stdin;
+ firstC = NULL;
+ lastC = NULL;
+ bogus = FALSE;
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = '\0';
+ if (index ("#;:",*p)) continue;
+ arg = nxtarg (&p," \t");
+ if (*arg == '\0') {
+ logerr ("Missing collection name in supfile");
+ bogus = TRUE;
+ continue;
+ }
+ if (cwant) {
+ register TREE *t;
+ if ((t = Tsearch (collT,arg)) == NULL)
+ continue;
+ t->Tcount++;
+ }
+ c = (COLLECTION *) malloc (sizeof(COLLECTION));
+ if (firstC == NULL) firstC = c;
+ if (lastC != NULL) lastC->Cnext = c;
+ lastC = c;
+ if (parsecoll(c,arg,p) < 0) {
+ bogus = TRUE;
+ continue;
+ }
+ c->Cflags |= oflags;
+ c->Cflags &= ~aflags;
+ if (t = Tsearch (collT,c->Cname)) {
+ c->Cflags |= t->Toflags;
+ c->Cflags &= ~t->Taflags;
+ }
+ if ((c->Cflags&CFMAIL) && c->Cnotify == NULL) {
+ if (*username == '\0')
+ logerr ("User unknown, notification disabled");
+ else
+ c->Cnotify = salloc (username);
+ }
+ if (c->Cbase == NULL) {
+ (void) sprintf (buf,FILEBASEDEFAULT,c->Cname);
+ c->Cbase = salloc (buf);
+ }
+ }
+ if (bogus) logquit (1,"Aborted due to supfile errors");
+ if (f != stdin) (void) fclose (f);
+ if (cwant) (void) Tprocess (collT,checkcoll);
+ Tfree (&collT);
+ if (firstC == NULL) logquit (1,"No collections to upgrade");
+ timenow = time ((long *)NULL);
+ if (*supfname == '\0')
+ p = "standard input";
+ else if (sysflag)
+ p = "system software";
+ else
+ (void) sprintf (p = buf,"file %s",supfname);
+ loginfo ("SUP %d.%d (%s) for %s at %s",PROTOVERSION,PGMVERSION,
+ scmversion,p,fmttime (timenow));
+ return (salloc (supfname));
+}
+
+checkcoll (t)
+register TREE *t;
+{
+ if (!t->Twant) return (SCMOK);
+ if (t->Tcount == 0)
+ logerr ("Collection %s not found",t->Tname);
+ if (t->Tcount > 1)
+ logerr ("Collection %s found more than once",t->Tname);
+ return (SCMOK);
+}
diff --git a/usr.bin/sup/src/supcmeat.c b/usr.bin/sup/src/supcmeat.c
new file mode 100644
index 00000000000..daf07be7e2a
--- /dev/null
+++ b/usr.bin/sup/src/supcmeat.c
@@ -0,0 +1,1468 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * sup "meat" routines
+ **********************************************************************
+ * HISTORY
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supcmeat.c,v $
+ * Revision 1.1 1995/12/16 11:46:56 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.6 1995/10/29 23:54:47 christos
+ * - runio fails when result != 0 not only < 0
+ * - print vis-encoded file in the scanner.
+ *
+ * Revision 1.5 1995/06/24 16:21:48 christos
+ * - Don't use system(3) to fork processes. It is a big security hole.
+ * - Encode the filenames in the scan files using strvis(3), so filenames
+ * that contain newlines or other weird characters don't break the scanner.
+ *
+ * Revision 1.4 1995/06/03 21:21:56 christos
+ * Changes to write ascii timestamps in the when files.
+ * Looked into making it 64 bit clean, but it is hopeless.
+ * Added little program to convert from the old timestamp files
+ * into the new ones.
+ *
+ * Revision 1.3 1993/08/04 17:46:18 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.2 1993/05/24 18:57:50 brezak
+ * Use /var/tmp for NetBSD
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.16 92/09/09 22:04:51 mrt
+ * Really added bww's recvone changes this time.
+ * Added code to support non-crypting version of sup.
+ * [92/09/01 mrt]
+ *
+ * Revision 1.15 92/08/11 12:07:09 mrt
+ * Added support to add release to FILEWHEN name.
+ * Updated variable arguemnt list usage - bww
+ * Updated recvone() to take a va_list - bww
+ * Changed conditional for rpausing code from CMUCS to MACH
+ * [92/07/24 mrt]
+ *
+ * Revision 1.14 92/02/08 18:24:12 mja
+ * Only apply "keep" mode when local file is strictly newer
+ * otherwise allow update as before if necessary.
+ * [92/02/08 18:09:00 mja]
+ *
+ * Added support for -k (keep) option to needone(). Rewrote and
+ * commented other parts of needone().
+ * [92/01/17 vdelvecc]
+ *
+ * Revision 1.13 91/05/16 14:49:41 ern
+ * Add timestap to fileserver.
+ * Drop day of the week from 5 messages.
+ * [91/05/16 14:47:53 ern]
+ *
+ * Revision 1.12 89/08/23 14:55:44 gm0w
+ * Changed msgf routines to msg routines.
+ * [89/08/23 gm0w]
+ *
+ * Revision 1.11 89/08/03 19:49:10 mja
+ * Updated to use v*printf() in place of _doprnt().
+ * [89/04/19 mja]
+ *
+ * Revision 1.10 89/06/18 14:41:27 gm0w
+ * Fixed up some notify messages of errors to use "SUP:" prefix.
+ * [89/06/18 gm0w]
+ *
+ * Revision 1.9 89/06/10 15:12:17 gm0w
+ * Changed to always use rename to install targets. This breaks hard
+ * links and recreates those known to sup, other links will be orphaned.
+ * [89/06/10 gm0w]
+ *
+ * Revision 1.8 89/05/24 15:04:23 gm0w
+ * Added code to check for EINVAL from FSPARAM ioctl for disk
+ * space check failures when the ioctl is not implemented.
+ * [89/05/24 gm0w]
+ *
+ * Revision 1.7 89/01/16 18:22:28 gm0w
+ * Changed needone() to check that mode of files match before
+ * setting update if times also match.
+ * [89/01/16 gm0w]
+ *
+ * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added timeout to backoff.
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support.
+ *
+ * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to be less verbose when updating files that have
+ * already been successfully upgraded.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support.
+ *
+ * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Converted to end connection with more information.
+ * Added done routine. Modified goaway routine to free old
+ * goawayreason.
+ *
+ * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Use computeBackoff from scm instead of doing it ourselves.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Split off from sup.c and reindented goaway calls.
+ *
+ **********************************************************************
+ */
+
+#include "supcdefs.h"
+#include <sys/wait.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+TREE *lastT; /* last filenames in collection */
+jmp_buf sjbuf; /* jump location for network errors */
+int dontjump; /* flag to void sjbuf */
+int cancompress=FALSE; /* Can we do compression? */
+int docompress=FALSE; /* Do we do compression? */
+
+extern COLLECTION *thisC; /* collection list pointer */
+extern int rpauseflag; /* don't disable resource pausing */
+extern int portdebug; /* network debugging ports */
+
+#if __STDC__
+int done(int,char *,...);
+int goaway(char *,...);
+#endif
+
+/*************************************************
+ *** U P G R A D E C O L L E C T I O N ***
+ *************************************************/
+
+/* The next two routines define the fsm to support multiple fileservers
+ * per collection.
+ */
+getonehost (t,state)
+register TREE *t;
+int *state;
+{
+ if (t->Tflags != *state)
+ return (SCMOK);
+ if (*state != 0 && t->Tmode == SCMEOF) {
+ t->Tflags = 0;
+ return (SCMOK);
+ }
+ if (*state == 2)
+ t->Tflags--;
+ else
+ t->Tflags++;
+ thisC->Chost = t;
+ return (SCMEOF);
+}
+
+TREE *getcollhost (tout,backoff,state,nhostsp)
+int *tout,*backoff,*state,*nhostsp;
+{
+ static int laststate = 0;
+ static int nhosts = 0;
+
+ if (*state != laststate) {
+ *nhostsp = nhosts;
+ laststate = *state;
+ nhosts = 0;
+ }
+ if (Tprocess (thisC->Chtree,getonehost,*state) == SCMEOF) {
+ if (*state != 0 && nhosts == 0 && !dobackoff (tout,backoff))
+ return (NULL);
+ nhosts++;
+ return (thisC->Chost);
+ }
+ if (nhosts == 0)
+ return (NULL);
+ if (*state == 2)
+ (*state)--;
+ else
+ (*state)++;
+ return (getcollhost (tout,backoff,state,nhostsp));
+}
+
+/* Upgrade a collection from the file server on the appropriate
+ * host machine.
+ */
+
+getcoll ()
+{
+ register TREE *t;
+ register int x;
+ int tout,backoff,state,nhosts;
+
+ collname = thisC->Cname;
+ tout = thisC->Ctimeout;
+ lastT = NULL;
+ backoff = 2;
+ state = 0;
+ nhosts = 0;
+ for (;;) {
+ t = getcollhost (&tout,&backoff,&state,&nhosts);
+ if (t == NULL) {
+ finishup (SCMEOF);
+ notify ((char *)NULL);
+ return;
+ }
+ t->Tmode = SCMEOF;
+ dontjump = FALSE;
+ if (!setjmp (sjbuf) && !signon (t,nhosts,&tout) && !setup (t))
+ break;
+ (void) requestend ();
+ }
+ dontjump = FALSE;
+ if (setjmp (sjbuf))
+ x = SCMERR;
+ else {
+ login ();
+ listfiles ();
+ recvfiles ();
+ x = SCMOK;
+ }
+ if (thisC->Clockfd >= 0) {
+ (void) close (thisC->Clockfd);
+ thisC->Clockfd = -1;
+ }
+ finishup (x);
+ notify ((char *)NULL);
+}
+
+/*** Sign on to file server ***/
+
+int signon (t,nhosts,tout)
+register TREE *t;
+int nhosts;
+int *tout;
+{
+ register int x;
+ int timeout;
+ long tloc;
+
+ if ((thisC->Cflags&CFLOCAL) == 0 && thishost (thisC->Chost->Tname)) {
+ vnotify ("SUP: Skipping local collection %s\n",collname);
+ t->Tmode = SCMEOF;
+ return (TRUE);
+ }
+ if (nhosts == 1)
+ timeout = *tout;
+ else
+ timeout = 0;
+ x = request (portdebug?DEBUGFPORT:FILEPORT,
+ thisC->Chost->Tname,&timeout);
+ if (nhosts == 1)
+ *tout = timeout;
+ if (x != SCMOK) {
+ if (nhosts) {
+ notify ("SUP: Can't connect to host %s\n",
+ thisC->Chost->Tname);
+ t->Tmode = SCMEOF;
+ } else
+ t->Tmode = SCMOK;
+ return (TRUE);
+ }
+ xpatch = FALSE;
+ x = msgsignon (); /* signon to fileserver */
+ if (x != SCMOK)
+ goaway ("Error sending signon request to fileserver");
+ x = msgsignonack (); /* receive signon ack from fileserver */
+ if (x != SCMOK)
+ goaway ("Error reading signon reply from fileserver");
+ tloc = time ((long *)NULL);
+ vnotify ("SUP Fileserver %d.%d (%s) %d on %s at %.8s\n",
+ protver,pgmver,scmver,fspid,remotehost(),ctime (&tloc) + 11);
+ free (scmver);
+ scmver = NULL;
+ if (protver < 4) {
+ dontjump = TRUE;
+ goaway ("Fileserver sup protocol version is obsolete.");
+ notify ("SUP: This version of sup can only communicate with a fileserver using at least\n");
+ notify ("SUP: version 4 of the sup network protocol. You should either run a newer\n");
+ notify ("SUP: version of the sup fileserver or find an older version of sup.\n");
+ t->Tmode = SCMEOF;
+ return (TRUE);
+ }
+ /* If protocol is > 7 then try compression */
+ if (protver > 7) {
+ cancompress = TRUE;
+ }
+ return (FALSE);
+}
+
+/*** Tell file server what to connect to ***/
+
+setup (t)
+register TREE *t;
+{
+ char relsufix[STRINGLENGTH];
+ register int f,x;
+ struct stat sbuf;
+
+ if (chdir (thisC->Cbase) < 0)
+ goaway ("Can't change to base directory %s",thisC->Cbase);
+ if (stat ("sup",&sbuf) < 0) {
+ (void) mkdir ("sup",0755);
+ if (stat("sup",&sbuf) < 0)
+ goaway ("Can't create directory %s/sup",thisC->Cbase);
+ vnotify ("SUP Created directory %s/sup\n",thisC->Cbase);
+ }
+ if (thisC->Cprefix && chdir (thisC->Cprefix) < 0)
+ goaway ("Can't change to %s from base directory %s",
+ thisC->Cprefix,thisC->Cbase);
+ if (stat (".",&sbuf) < 0)
+ goaway ("Can't stat %s directory %s",
+ thisC->Cprefix?"prefix":"base",
+ thisC->Cprefix?thisC->Cprefix:thisC->Cbase);
+ if (thisC->Cprefix) (void) chdir (thisC->Cbase);
+ /* read time of last upgrade from when file */
+
+ if ((thisC->Cflags&CFURELSUF) && thisC->Crelease)
+ (void) sprintf (relsufix,".%s",thisC->Crelease);
+ else
+ relsufix[0] = '\0';
+ lasttime = getwhen(collname,relsufix);
+ /* setup for msgsetup */
+ basedir = thisC->Chbase;
+ basedev = sbuf.st_dev;
+ baseino = sbuf.st_ino;
+ listonly = (thisC->Cflags&CFLIST);
+ newonly = ((thisC->Cflags&(CFALL|CFDELETE|CFOLD)) == 0);
+ release = thisC->Crelease;
+ x = msgsetup ();
+ if (x != SCMOK)
+ goaway ("Error sending setup request to file server");
+ x = msgsetupack ();
+ if (x != SCMOK)
+ goaway ("Error reading setup reply from file server");
+ if (setupack == FSETUPOK) {
+ /* Test encryption */
+ if (netcrypt (thisC->Ccrypt) != SCMOK)
+ goaway ("Running non-crypting sup");
+ crypttest = CRYPTTEST;
+ x = msgcrypt ();
+ if (x != SCMOK)
+ goaway ("Error sending encryption test request");
+ x = msgcryptok ();
+ if (x == SCMEOF)
+ goaway ("Data encryption test failed");
+ if (x != SCMOK)
+ goaway ("Error reading encryption test reply");
+ return (FALSE);
+ }
+ switch (setupack) {
+ case FSETUPSAME:
+ notify ("SUP: Attempt to upgrade from same host to same directory\n");
+ done (FDONESRVERROR,"Overwrite error");
+ case FSETUPHOST:
+ notify ("SUP: This host has no permission to access %s\n",
+ collname);
+ done (FDONESRVERROR,"Permission denied");
+ case FSETUPOLD:
+ notify ("SUP: This version of SUP is too old for the fileserver\n");
+ done (FDONESRVERROR,"Obsolete client");
+ case FSETUPRELEASE:
+ notify ("SUP: Invalid release %s for collection %s\n",
+ release == NULL ? DEFRELEASE : release,collname);
+ done (FDONESRVERROR,"Invalid release");
+ case FSETUPBUSY:
+ vnotify ("SUP Fileserver is currently busy\n");
+ t->Tmode = SCMOK;
+ doneack = FDONESRVERROR;
+ donereason = "Fileserver is busy";
+ (void) netcrypt ((char *)NULL);
+ (void) msgdone ();
+ return (TRUE);
+ default:
+ goaway ("Unrecognized file server setup status %d",setupack);
+ }
+ /* NOTREACHED */
+}
+
+/*** Tell file server what account to use ***/
+
+int login ()
+{
+ char buf[STRINGLENGTH];
+ register int f,x;
+
+ /* lock collection if desired */
+ (void) sprintf (buf,FILELOCK,collname);
+ f = open (buf,O_RDONLY,0);
+ if (f >= 0) {
+ if (flock (f,(LOCK_EX|LOCK_NB)) < 0) {
+ if (errno != EWOULDBLOCK)
+ goaway ("Can't lock collection %s",collname);
+ if (flock (f,(LOCK_SH|LOCK_NB)) < 0) {
+ (void) close (f);
+ if (errno == EWOULDBLOCK)
+ goaway ("Collection %s is locked by another sup",collname);
+ goaway ("Can't lock collection %s",collname);
+ }
+ vnotify ("SUP Waiting for exclusive access lock\n");
+ if (flock (f,LOCK_EX) < 0) {
+ (void) close (f);
+ goaway ("Can't lock collection %s",collname);
+ }
+ }
+ thisC->Clockfd = f;
+ vnotify ("SUP Locked collection %s for exclusive access\n",collname);
+ }
+ logcrypt = (char *) NULL;
+ loguser = thisC->Clogin;
+ logpswd = thisC->Cpswd;
+
+#ifndef CRYPTING /* Define CRYPTING for backwards compatibility with old supfileservers */
+ if (thisC->Clogin != (char *) NULL) /* othewise we only encrypt if there is a login id */
+#endif /* CRYPTING */
+ {
+ logcrypt = CRYPTTEST;
+ (void) netcrypt (PSWDCRYPT); /* encrypt password data */
+ }
+ x = msglogin ();
+#ifndef CRYPTING
+ if (thisC->Clogin != (char *) NULL)
+#endif
+ (void) netcrypt ((char *)NULL); /* turn off encryption */
+ if (x != SCMOK)
+ goaway ("Error sending login request to file server");
+ x = msglogack ();
+ if (x != SCMOK)
+ goaway ("Error reading login reply from file server");
+ if (logack == FLOGNG) {
+ notify ("SUP: %s\n",logerror);
+ free (logerror);
+ logerror = NULL;
+ notify ("SUP: Improper login to %s account",
+ thisC->Clogin ? thisC->Clogin : "default");
+ done (FDONESRVERROR,"Improper login");
+ }
+ if (netcrypt (thisC->Ccrypt) != SCMOK) /* restore encryption */
+ goaway("Running non-crypting sup");
+}
+
+/*
+ * send list of files that we are not interested in. receive list of
+ * files that are on the repository that could be upgraded. Find the
+ * ones that we need. Receive the list of files that the server could
+ * not access. Delete any files that have been upgraded in the past
+ * which are no longer on the repository.
+ */
+
+int listfiles ()
+{
+ int needone(), denyone(), deleteone();
+ char buf[STRINGLENGTH];
+ char relsufix[STRINGLENGTH];
+ register char *p,*q;
+ register FILE *f;
+ register int x;
+
+
+ if ((thisC->Cflags&CFURELSUF) && release)
+ (void) sprintf (relsufix,".%s",release);
+ else
+ relsufix[0] = '\0';
+ (void) sprintf (buf,FILELAST,collname,relsufix);
+ f = fopen (buf,"r");
+ 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);
+ }
+ refuseT = NULL;
+ (void) sprintf (buf,FILEREFUSE,collname);
+ f = fopen (buf,"r");
+ if (f) {
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ if (q = index (p,'\n')) *q = '\0';
+ if (index ("#;:",*p)) continue;
+ (void) Tinsert (&refuseT,p,FALSE);
+ }
+ (void) fclose (f);
+ }
+ vnotify ("SUP Requesting changes since %s",ctime (&lasttime) + 4);
+ x = msgrefuse ();
+ if (x != SCMOK)
+ goaway ("Error sending refuse list to file server");
+ listT = NULL;
+ x = msglist ();
+ if (x != SCMOK)
+ goaway ("Error reading file list from file server");
+ if (thisC->Cprefix) (void) chdir (thisC->Cprefix);
+ needT = NULL;
+ (void) Tprocess (listT,needone);
+ Tfree (&listT);
+ x = msgneed ();
+ if (x != SCMOK)
+ goaway ("Error sending needed files list to file server");
+ Tfree (&needT);
+ denyT = NULL;
+ x = msgdeny ();
+ if (x != SCMOK)
+ goaway ("Error reading denied files list from file server");
+ if (thisC->Cflags&CFVERBOSE)
+ (void) Tprocess (denyT,denyone);
+ Tfree (&denyT);
+ if (thisC->Cflags&(CFALL|CFDELETE|CFOLD))
+ (void) Trprocess (lastT,deleteone);
+ Tfree (&refuseT);
+}
+
+needone (t)
+register TREE *t;
+{
+ 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
+ rely solely on the server: if the file changed, we do an
+ update; otherwise nothing. If the file is a normal file,
+ we check timestamps. If we are in "keep" mode, we fetch if
+ the file on the server is newer, and do nothing otherwise.
+ Otherwise, we fetch if the timestamp is wrong; if the file
+ changed on the server but the timestamp is right, we do an
+ update. (Update refers to updating stat information, i.e.
+ timestamp, owner, mode bits, etc.) */
+ if (exists && (sbuf.st_mode&S_IFMT) == (t->Tmode&S_IFMT))
+ if ((t->Tmode&S_IFMT) != S_IFREG)
+ if (t->Tflags&FNEW)
+ fetch = FALSE;
+ else return (SCMOK);
+ else if ((thisC->Cflags&CFKEEP) &&
+ sbuf.st_mtime > t->Tmtime)
+ return (SCMOK);
+ else if (sbuf.st_mtime == t->Tmtime)
+ if (t->Tflags&FNEW)
+ fetch = FALSE;
+ 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&S_IFMT) == S_IFREG)
+ newt->Tflags |= FUPDATE;
+ return (SCMOK);
+}
+
+denyone (t)
+register TREE *t;
+{
+ vnotify ("SUP: Access denied to %s\n",t->Tname);
+ return (SCMOK);
+}
+
+deleteone (t)
+TREE *t;
+{
+ 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)) {
+ vnotify ("SUP Would not delete symbolic link %s\n",
+ name);
+ return (SCMOK);
+ }
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would delete symbolic link %s\n",name);
+ return (SCMOK);
+ }
+ if ((thisC->Cflags&CFDELETE) == 0) {
+ notify ("SUP Please delete symbolic link %s\n",name);
+ t->Tflags |= FUPDATE;
+ return (SCMOK);
+ }
+ x = unlink (name);
+ if (x < 0) {
+ notify ("SUP: Unable to delete symbolic link %s\n",
+ name);
+ t->Tflags |= FUPDATE;
+ return (SCMOK);
+ }
+ vnotify ("SUP Deleted symbolic link %s\n",name);
+ return (SCMOK);
+ }
+ /* is it a directory ? */
+ if ((sbuf.st_mode & S_IFMT) == S_IFDIR) {
+ if (Tlookup (refuseT,name)) {
+ vnotify ("SUP Would not delete directory %s\n",name);
+ return (SCMOK);
+ }
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would delete directory %s\n",name);
+ return (SCMOK);
+ }
+ if ((thisC->Cflags&CFDELETE) == 0) {
+ notify ("SUP Please delete directory %s\n",name);
+ t->Tflags |= FUPDATE;
+ return (SCMOK);
+ }
+ (void) rmdir (name);
+ if (lstat(name,&sbuf) == 0) {
+ notify ("SUP: Unable to delete directory %s\n",name);
+ t->Tflags |= FUPDATE;
+ return (SCMOK);
+ }
+ vnotify ("SUP Deleted directory %s\n",name);
+ return (SCMOK);
+ }
+ /* it is a file */
+ if (Tlookup (refuseT,name)) {
+ vnotify ("SUP Would not delete file %s\n",name);
+ return (SCMOK);
+ }
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would delete file %s\n",name);
+ return (SCMOK);
+ }
+ if ((thisC->Cflags&CFDELETE) == 0) {
+ notify ("SUP Please delete file %s\n",name);
+ t->Tflags |= FUPDATE;
+ return (SCMOK);
+ }
+ x = unlink (name);
+ if (x < 0) {
+ notify ("SUP: Unable to delete file %s\n",name);
+ t->Tflags |= FUPDATE;
+ return (SCMOK);
+ }
+ vnotify ("SUP Deleted file %s\n",name);
+ return (SCMOK);
+}
+
+/***************************************
+ *** R E C E I V E F I L E S ***
+ ***************************************/
+
+/* Note for these routines, return code SCMOK generally means
+ * NETWORK communication is OK; it does not mean that the current
+ * file was correctly received and stored. If a file gets messed
+ * up, too bad, just print a message and go on to the next one;
+ * but if the network gets messed up, the whole sup program loses
+ * badly and best just stop the program as soon as possible.
+ */
+
+recvfiles ()
+{
+ register int x;
+ int recvone ();
+ int recvmore;
+
+ /* Does the protocol support compression */
+ if (cancompress) {
+ /* Check for compression on sending files */
+ docompress = (thisC->Cflags&CFCOMPRESS);
+ x = msgcompress();
+ if ( x != SCMOK)
+ goaway ("Error sending compression check to server");
+ if (docompress)
+ vnotify("SUP Using compressed file transfer\n");
+ }
+ recvmore = TRUE;
+ upgradeT = NULL;
+ do {
+ x = msgsend ();
+ if (x != SCMOK)
+ goaway ("Error sending receive file request to file server");
+ (void) Tinsert (&upgradeT,(char *)NULL,FALSE);
+ x = msgrecv (recvone,&recvmore);
+ if (x != SCMOK)
+ goaway ("Error receiving file from file server");
+ Tfree (&upgradeT);
+ } while (recvmore);
+}
+
+/* prepare the target, if necessary */
+prepare (name,mode,newp,statp)
+char *name;
+int mode,*newp;
+struct stat *statp;
+{
+ register char *type;
+
+ if (mode == S_IFLNK)
+ *newp = (lstat (name,statp) < 0);
+ else
+ *newp = (stat (name,statp) < 0);
+ if (*newp) {
+ if (thisC->Cflags&CFLIST)
+ return (FALSE);
+ if (establishdir (name))
+ return (TRUE);
+ return (FALSE);
+ }
+ if (mode == (statp->st_mode&S_IFMT))
+ return (FALSE);
+ *newp = TRUE;
+ switch (statp->st_mode&S_IFMT) {
+ case S_IFDIR:
+ type = "directory";
+ break;
+ case S_IFLNK:
+ type = "symbolic link";
+ break;
+ case S_IFREG:
+ type = "regular file";
+ break;
+ default:
+ type = "unknown file";
+ break;
+ }
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would remove %s %s\n",type,name);
+ return (FALSE);
+ }
+ 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) {
+ vnotify ("SUP Removed %s %s\n",type,name);
+ return (FALSE);
+ }
+ notify ("SUP: Couldn't remove %s %s\n",type,name);
+ return (TRUE);
+}
+
+recvone (t,ap)
+register TREE *t;
+va_list ap;
+{
+ register int x;
+ int new;
+ struct stat sbuf;
+ int linkone (),execone ();
+ int *recvmore = va_arg(ap,int *);
+
+ /* check for end of file list */
+ if (t == NULL) {
+ *recvmore = FALSE;
+ return (SCMOK);
+ }
+ /* check for failed access at fileserver */
+ if (t->Tmode == 0) {
+ notify ("SUP: File server unable to transfer file %s\n",
+ t->Tname);
+ 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)
+ goaway ("Can't skip file transfer");
+ }
+ thisC->Cnogood = TRUE;
+ return (SCMOK);
+ }
+ /* make file mode specific changes */
+ switch (t->Tmode&S_IFMT) {
+ case S_IFDIR:
+ x = recvdir (t,new,&sbuf);
+ break;
+ case S_IFLNK:
+ x = recvsym (t,new,&sbuf);
+ break;
+ case S_IFREG:
+ x = recvreg (t,new,&sbuf);
+ break;
+ default:
+ goaway ("Unknown file type %o\n",t->Tmode&S_IFMT);
+ }
+ if (x) {
+ thisC->Cnogood = TRUE;
+ return (SCMOK);
+ }
+ if ((t->Tmode&S_IFMT) == S_IFREG)
+ (void) Tprocess (t->Tlink,linkone,t->Tname);
+ (void) Tprocess (t->Texec,execone);
+ return (SCMOK);
+}
+
+int recvdir (t,new,statp) /* receive directory from network */
+register TREE *t;
+register int new;
+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);
+ }
+ }
+ if ((t->Tflags&FNOACCT) == 0) {
+ /* convert user and group names to local ids */
+ ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode);
+ }
+ if (!new && (t->Tflags&FNEW) == 0 && statp->st_mtime == t->Tmtime) {
+ if (t->Tflags&FNOACCT)
+ return (FALSE);
+ if (statp->st_uid == t->Tuid && statp->st_gid == t->Tgid)
+ 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);
+}
+
+int recvsym (t,new,statp) /* receive symbolic link */
+register TREE *t;
+register int new;
+register struct stat *statp;
+{
+ 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);
+}
+
+int recvreg (t,new,statp) /* receive file from network */
+register TREE *t;
+register int new;
+register struct stat *statp;
+{
+ register FILE *fin,*fout;
+ char dirpart[STRINGLENGTH],filepart[STRINGLENGTH];
+ char filename[STRINGLENGTH],buf[STRINGLENGTH];
+ struct timeval tbuf[2];
+ register int x;
+ register char *p;
+
+ if (t->Tflags&FUPDATE) {
+ if ((t->Tflags&FNOACCT) == 0) {
+ /* convert user and group names to local ids */
+ ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,
+ &t->Tmode);
+ }
+ if (!new && (t->Tflags&FNEW) == 0 &&
+ statp->st_mtime == t->Tmtime) {
+ if (t->Tflags&FNOACCT)
+ return (FALSE);
+ if (statp->st_uid == t->Tuid &&
+ statp->st_gid == t->Tgid)
+ 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) {
+ if (new)
+ p = "create";
+ else if (statp->st_mtime < t->Tmtime)
+ p = "receive new";
+ else if (statp->st_mtime > t->Tmtime)
+ 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) {
+ (void) sprintf (buf,FILEBKDIR,dirpart);
+ (void) mkdir (buf,0755);
+ fout = fopen (filename,"w");
+ }
+ if (fout == NULL) {
+ x = readskip (); /* skip over file */
+ if (x != SCMOK)
+ goaway ("Can't skip file transfer");
+ notify ("SUP: Can't create %s for backup\n",filename);
+ (void) fclose (fin);
+ return (TRUE);
+ }
+ 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);
+}
+
+linkone (t,fname) /* link to file already received */
+register TREE *t;
+register char **fname;
+{
+ struct stat fbuf,sbuf;
+ register char *name = t->Tname;
+ int new,x;
+ char *type;
+
+ if (stat(*fname,&fbuf) < 0) { /* source file */
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would link %s to %s\n",name,*fname);
+ return (SCMOK);
+ }
+ notify ("SUP: Can't link %s to missing file %s\n",name,*fname);
+ thisC->Cnogood = TRUE;
+ return (SCMOK);
+ }
+ if (prepare (name,S_IFREG,&new,&sbuf)) {
+ notify ("SUP: Can't prepare path for link %s\n",name);
+ thisC->Cnogood = TRUE;
+ return (SCMOK);
+ }
+ if (!new && (t->Tflags&FNEW) == 0 &&
+ fbuf.st_dev == sbuf.st_dev && fbuf.st_ino == sbuf.st_ino)
+ return (SCMOK);
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would link %s to %s\n",name,*fname);
+ return (SCMOK);
+ }
+ (void) unlink (name);
+ type = "";
+ if ((x = link (*fname,name)) < 0) {
+ type = "symbolic ";
+ x = symlink (*fname,name);
+ }
+ if (x < 0 || lstat(name,&sbuf) < 0) {
+ notify ("SUP: Unable to create %slink %s\n",type,name);
+ return (TRUE);
+ }
+ vnotify ("SUP Created %slink %s to %s\n",type,name,*fname);
+ return (SCMOK);
+}
+
+execone (t) /* execute command for file */
+register TREE *t;
+{
+ union wait w;
+
+ if (thisC->Cflags&CFLIST) {
+ vnotify ("SUP Would execute %s\n",t->Tname);
+ return (SCMOK);
+ }
+ if ((thisC->Cflags&CFEXECUTE) == 0) {
+ notify ("SUP Please execute %s\n",t->Tname);
+ return (SCMOK);
+ }
+ vnotify ("SUP Executing %s\n",t->Tname);
+
+ w.w_status = system (t->Tname);
+ if (WIFEXITED(w) && w.w_retcode != 0) {
+ notify ("SUP: Execute command returned failure status %#o\n",
+ w.w_retcode);
+ thisC->Cnogood = TRUE;
+ } else if (WIFSIGNALED(w)) {
+ notify ("SUP: Execute command killed by signal %d\n",
+ w.w_termsig);
+ thisC->Cnogood = TRUE;
+ } else if (WIFSTOPPED(w)) {
+ notify ("SUP: Execute command stopped by signal %d\n",
+ w.w_stopsig);
+ thisC->Cnogood = TRUE;
+ }
+ return (SCMOK);
+}
+
+int copyfile (to,from)
+char *to;
+char *from; /* 0 if reading from network */
+{
+ register int fromf,tof,istemp,x;
+ char dpart[STRINGLENGTH],fpart[STRINGLENGTH];
+ char tname[STRINGLENGTH];
+ struct stat sbuf;
+
+ static int thispid = 0; /* process id # */
+
+ if (from) { /* reading file */
+ fromf = open (from,O_RDONLY,0);
+ if (fromf < 0) {
+ notify ("SUP: Can't open %s to copy to %s: %s\n",
+ from,to,errmsg (-1));
+ return (TRUE);
+ }
+ } else /* reading network */
+ fromf = -1;
+ istemp = TRUE; /* try to create temp file */
+ lockout (TRUE); /* block interrupts */
+ if (thispid == 0) thispid = getpid ();
+ /* Now try hard to find a temp file name. Try VERY hard. */
+ for (;;) {
+ /* try destination directory */
+ path (to,dpart,fpart);
+ (void) sprintf (tname,"%s/#%d.sup",dpart,thispid);
+ tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof >= 0) break;
+ /* try sup directory */
+ if (thisC->Cprefix) (void) chdir (thisC->Cbase);
+ (void) sprintf (tname,"sup/#%d.sup",thispid);
+ tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof >= 0) {
+ if (thisC->Cprefix) (void) chdir (thisC->Cprefix);
+ break;
+ }
+ /* try base directory */
+ (void) sprintf (tname,"#%d.sup",thispid);
+ tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (thisC->Cprefix) (void) chdir (thisC->Cprefix);
+ if (tof >= 0) break;
+#ifdef VAR_TMP
+ /* try /var/tmp */
+ (void) sprintf (tname,"/var/tmp/#%d.sup",thispid);
+ tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof >= 0) break;
+#else
+ /* try /usr/tmp */
+ (void) sprintf (tname,"/usr/tmp/#%d.sup",thispid);
+ tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof >= 0) break;
+#endif
+ /* try /tmp */
+ (void) sprintf (tname,"/tmp/#%d.sup",thispid);
+ tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof >= 0) break;
+ istemp = FALSE;
+ /* give up: try to create output file */
+ if (!docompress)
+ tof = open (to,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof >= 0) break;
+ /* no luck */
+ notify ("SUP: Can't create %s or temp file for it\n",to);
+ lockout (FALSE);
+ if (fromf >= 0)
+ (void) close (fromf);
+ else {
+ x = readskip ();
+ if (x != SCMOK)
+ goaway ("Can't skip file transfer");
+ }
+ return (TRUE);
+ }
+ if (fromf >= 0) { /* read file */
+ x = filecopy (fromf,tof);
+ (void) close (fromf);
+ (void) close (tof);
+ if (x < 0) {
+ notify ("SUP: Error in copying %s to %s\n",from,to);
+ if (istemp) (void) unlink (tname);
+ lockout (FALSE);
+ return (TRUE);
+ }
+ } else { /* read network */
+#if MACH
+ if (!rpauseflag) {
+ int fsize;
+ struct fsparam fsp;
+
+ x = prereadcount (&fsize);
+ if (x != SCMOK) {
+ if (istemp) (void) unlink (tname);
+ lockout (FALSE);
+ x = readskip ();
+ if (x != SCMOK)
+ goaway ("Can't skip file transfer");
+ goaway ("Error in server space check");
+ logquit (1,"Error in server space check");
+ }
+ errno = 0;
+ if (ioctl (tof,FIOCFSPARAM,(char *)&fsp) < 0 &&
+ errno != EINVAL) {
+ if (istemp) (void) unlink (tname);
+ lockout (FALSE);
+ x = readskip ();
+ if (x != SCMOK)
+ goaway ("Can't skip file transfer");
+ goaway ("Error in disk space check");
+ logquit (1,"Error in disk space check");
+ }
+ if (errno == 0) {
+ fsize = (fsize + 1023) / 1024;
+ x = fsp.fsp_size * MAX (fsp.fsp_minfree,1) / 100;
+ fsp.fsp_free -= x;
+ if (fsize > MAX (fsp.fsp_free,0)) {
+ if (istemp) (void) unlink (tname);
+ lockout (FALSE);
+ x = readskip ();
+ if (x != SCMOK)
+ goaway ("Can't skip file transfer");
+ goaway ("No disk space for file %s", to);
+ logquit (1,"No disk space for file %s",to);
+ }
+ }
+ }
+#endif /* MACH */
+ x = readfile (tof);
+ (void) close (tof);
+ if (x != SCMOK) {
+ if (istemp) (void) unlink (tname);
+ lockout (FALSE);
+ goaway ("Error in receiving %s\n",to);
+ }
+ }
+ if (!istemp) { /* no temp file used */
+ lockout (FALSE);
+ return (FALSE);
+ }
+ /* uncompress it first */
+ if (docompress) {
+ char *av[4];
+ int ac = 0;
+ av[ac++] = "gzip";
+ av[ac++] = "-d";
+ av[ac++] = NULL;
+ if (runio(av, tname, to, NULL) != 0) {
+ /* Uncompress it onto the destination */
+ notify ("SUP: Error in uncompressing file %s\n",
+ to);
+ (void) unlink (tname);
+ /* Just in case */
+ (void) unlink (to);
+ lockout (FALSE);
+ return (TRUE);
+ }
+ (void) unlink (tname);
+ lockout (FALSE);
+ return (FALSE);
+ }
+ /* move to destination */
+ if (rename (tname,to) == 0) {
+ (void) unlink (tname);
+ lockout (FALSE);
+ return (FALSE);
+ }
+ fromf = open (tname,O_RDONLY,0);
+ if (fromf < 0) {
+ notify ("SUP: Error in moving temp file to %s: %s\n",
+ to,errmsg (-1));
+ (void) unlink (tname);
+ lockout (FALSE);
+ return (TRUE);
+ }
+ tof = open (to,(O_WRONLY|O_CREAT|O_TRUNC),0600);
+ if (tof < 0) {
+ (void) close (fromf);
+ notify ("SUP: Can't create %s from temp file: %s\n",
+ to,errmsg (-1));
+ (void) unlink (tname);
+ lockout (FALSE);
+ return (TRUE);
+ }
+ x = filecopy (fromf,tof);
+ (void) close (fromf);
+ (void) close (tof);
+ (void) unlink (tname);
+ lockout (FALSE);
+ if (x < 0) {
+ notify ("SUP: Error in storing data in %s\n",to);
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*** Finish connection with file server ***/
+
+finishup (x)
+int x;
+{
+ char tname[STRINGLENGTH],fname[STRINGLENGTH];
+ char relsufix[STRINGLENGTH];
+ char collrelname[STRINGLENGTH];
+ long tloc;
+ FILE *finishfile; /* record of all filenames */
+ int f,finishone();
+
+ if ((thisC->Cflags&CFURELSUF) && release) {
+ (void) sprintf (relsufix,".%s",release);
+ (void) sprintf (collrelname,"%s-%s",collname,release);
+ } else {
+ relsufix[0] = '\0';
+ (void) strcpy (collrelname,collname);
+ }
+ dontjump = TRUE; /* once here, no more longjmp */
+ (void) netcrypt ((char *)NULL);
+ if (protver < 6) {
+ /* done with server */
+ if (x == SCMOK)
+ goaway ((char *)NULL);
+ (void) requestend ();
+ }
+ tloc = time ((long *)NULL);
+ if (x != SCMOK) {
+ notify ("SUP: Upgrade of %s aborted at %s",
+ collrelname,ctime (&tloc) + 4);
+ Tfree (&lastT);
+ if (protver < 6) return;
+ /* if we've not been blown off, make sure he is! */
+ if (x != SCMEOF)
+ goaway ("Aborted");
+ (void) requestend ();
+ return;
+ }
+ if (thisC->Cnogood) {
+ notify ("SUP: Upgrade of %s completed with errors at %s",
+ collrelname,ctime (&tloc) + 4);
+ notify ("SUP: Upgrade time will not be updated\n");
+ Tfree (&lastT);
+ if (protver < 6) return;
+ done (FDONEUSRERROR,"Completed with errors");
+ (void) requestend ();
+ return;
+ }
+ if (thisC->Cprefix) (void) chdir (thisC->Cbase);
+ vnotify ("SUP Upgrade of %s completed at %s",
+ collrelname,ctime (&tloc) + 4);
+ if (thisC->Cflags&CFLIST) {
+ Tfree (&lastT);
+ if (protver < 6) return;
+ done (FDONEDONTLOG,"List only");
+ (void) requestend ();
+ return;
+ }
+ (void) sprintf (fname,FILEWHEN,collname,relsufix);
+ if (establishdir (fname)) {
+ notify ("SUP: Can't create directory for upgrade timestamp\n");
+ Tfree (&lastT);
+ if (protver < 6) return;
+ done (FDONEUSRERROR,"Couldn't timestamp");
+ (void) requestend ();
+ return;
+ }
+ if (!putwhen(fname, scantime)) {
+ notify ("SUP: Can't record current time in %s: %s\n",
+ fname,errmsg (-1));
+ Tfree (&lastT);
+ if (protver < 6) return;
+ done (FDONEUSRERROR,"Couldn't timestamp");
+ (void) requestend ();
+ return;
+ }
+ if (protver >= 6) {
+ /* At this point we have let the server go */
+ /* "I'm sorry, we've had to let you go" */
+ done (FDONESUCCESS,"Success");
+ (void) requestend ();
+ }
+ (void) sprintf (tname,FILELASTTEMP,collname);
+ finishfile = fopen (tname,"w");
+ if (finishfile == NULL) {
+ notify ("SUP: Can't record list of all files in %s\n",tname);
+ Tfree (&lastT);
+ return;
+ }
+ (void) Tprocess (lastT,finishone,finishfile);
+ (void) fclose (finishfile);
+ (void) sprintf (fname,FILELAST,collname,relsufix);
+ if (rename (tname,fname) < 0)
+ notify ("SUP: Can't change %s to %s\n",tname,fname);
+ (void) unlink (tname);
+ Tfree (&lastT);
+}
+
+finishone (t,finishfile)
+TREE *t;
+FILE **finishfile;
+{
+ if ((thisC->Cflags&CFDELETE) == 0 || (t->Tflags&FUPDATE))
+ fprintf (*finishfile,"%s\n",t->Tname);
+ return (SCMOK);
+}
+
+#if __STDC__
+done (int value,char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+done (va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ int value;
+ char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ va_list ap;
+
+ (void) netcrypt ((char *)NULL);
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ value = va_arg(ap,int);
+ fmt = va_arg(ap,char *);
+#endif
+ if (fmt)
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ if (protver < 6) {
+ if (goawayreason)
+ free (goawayreason);
+ goawayreason = (fmt) ? salloc (buf) : (char *)NULL;
+ (void) msggoaway ();
+ }
+ else {
+ doneack = value;
+ donereason = (fmt) ? buf : (char *)NULL;
+ (void) msgdone ();
+ }
+ if (!dontjump)
+ longjmp (sjbuf,TRUE);
+}
+#if __STDC__
+goaway (char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+goaway (va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ register char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ va_list ap;
+
+ (void) netcrypt ((char *)NULL);
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ fmt = va_arg(ap,char *);
+#endif
+ if (fmt) {
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ goawayreason = buf;
+ } else
+ goawayreason = NULL;
+ va_end(ap);
+ (void) msggoaway ();
+ if (fmt)
+ if (thisC)
+ notify ("SUP: %s\n",buf);
+ else
+ printf ("SUP: %s\n",buf);
+ if (!dontjump)
+ longjmp (sjbuf,TRUE);
+}
diff --git a/usr.bin/sup/src/supcmisc.c b/usr.bin/sup/src/supcmisc.c
new file mode 100644
index 00000000000..54bade3eb10
--- /dev/null
+++ b/usr.bin/sup/src/supcmisc.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * sup misc. routines, include list processing.
+ **********************************************************************
+ * HISTORY
+ * $Log: supcmisc.c,v $
+ * Revision 1.1 1995/12/16 11:46:57 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1995/06/03 21:21:57 christos
+ * Changes to write ascii timestamps in the when files.
+ * Looked into making it 64 bit clean, but it is hopeless.
+ * Added little program to convert from the old timestamp files
+ * into the new ones.
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.5 92/08/11 12:07:22 mrt
+ * Added release to FILEWHEN name.
+ * Brad's changes: delinted and updated variable arguement usage.
+ * [92/07/26 mrt]
+ *
+ * Revision 1.3 89/08/15 15:31:28 bww
+ * Updated to use v*printf() in place of _doprnt().
+ * From "[89/04/19 mja]" at CMU.
+ * [89/08/15 bww]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fixed bug in ugconvert() which left pw uninitialized.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Split off from sup.c and changed goaway to use printf
+ * instead of notify if thisC is NULL.
+ *
+ **********************************************************************
+ */
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "supcdefs.h"
+
+struct liststruct { /* uid and gid lists */
+ char *Lname; /* name */
+ int Lnumber; /* uid or gid */
+ struct liststruct *Lnext;
+};
+typedef struct liststruct LIST;
+
+#define HASHBITS 4
+#define HASHSIZE (1<<HASHBITS)
+#define HASHMASK (HASHSIZE-1)
+#define LISTSIZE (HASHSIZE*HASHSIZE)
+
+static LIST *uidL[LISTSIZE]; /* uid and gid lists */
+static LIST *gidL[LISTSIZE];
+
+extern COLLECTION *thisC; /* collection list pointer */
+#if __STDC__
+int notify (char *, ...);
+#endif
+
+/*************************************************
+ *** P R I N T U P D A T E T I M E S ***
+ *************************************************/
+
+prtime ()
+{
+ char buf[STRINGLENGTH];
+ char relsufix[STRINGLENGTH];
+ long twhen;
+ int f;
+
+ if ((thisC->Cflags&CFURELSUF) && thisC->Crelease)
+ (void) sprintf (relsufix,".%s",thisC->Crelease);
+ else
+ relsufix[0] = '\0';
+ if (chdir (thisC->Cbase) < 0)
+ logerr ("Can't change to base directory %s for collection %s",
+ thisC->Cbase,thisC->Cname);
+ twhen = getwhen(thisC->Cname,relsufix);
+ (void) strcpy (buf,ctime (&twhen));
+ buf[strlen(buf)-1] = '\0';
+ loginfo ("Last update occurred at %s for collection %s",
+ buf,thisC->Cname);
+}
+
+int establishdir (fname)
+char *fname;
+{
+ char dpart[STRINGLENGTH],fpart[STRINGLENGTH];
+ path (fname,dpart,fpart);
+ return (estabd (fname,dpart));
+}
+
+int estabd (fname,dname)
+char *fname,*dname;
+{
+ char dpart[STRINGLENGTH],fpart[STRINGLENGTH];
+ struct stat sbuf;
+ register int x;
+
+ if (stat (dname,&sbuf) >= 0) return (FALSE); /* exists */
+ path (dname,dpart,fpart);
+ if (strcmp (fpart,".") == 0) { /* dname is / or . */
+ notify ("SUP: Can't create directory %s for %s\n",dname,fname);
+ return (TRUE);
+ }
+ x = estabd (fname,dpart);
+ if (x) return (TRUE);
+ (void) mkdir (dname,0755);
+ if (stat (dname,&sbuf) < 0) { /* didn't work */
+ notify ("SUP: Can't create directory %s for %s\n",dname,fname);
+ return (TRUE);
+ }
+ vnotify ("SUP Created directory %s for %s\n",dname,fname);
+ return (FALSE);
+}
+
+/***************************************
+ *** L I S T R O U T I N E S ***
+ ***************************************/
+
+static
+int Lhash (name)
+char *name;
+{
+ /* Hash function is: HASHSIZE * (strlen mod HASHSIZE)
+ * + (char mod HASHSIZE)
+ * where "char" is last character of name (if name is non-null).
+ */
+
+ register int len;
+ register char c;
+
+ len = strlen (name);
+ if (len > 0) c = name[len-1];
+ else c = 0;
+ return (((len&HASHMASK)<<HASHBITS)|(((int)c)&HASHMASK));
+}
+
+static
+Linsert (table,name,number)
+LIST **table;
+char *name;
+int number;
+{
+ register LIST *l;
+ register int lno;
+ lno = Lhash (name);
+ l = (LIST *) malloc (sizeof(LIST));
+ l->Lname = name;
+ l->Lnumber = number;
+ l->Lnext = table[lno];
+ table[lno] = l;
+}
+
+static
+LIST *Llookup (table,name)
+LIST **table;
+char *name;
+{
+ register int lno;
+ register LIST *l;
+ lno = Lhash (name);
+ for (l = table[lno]; l && strcmp(l->Lname,name) != 0; l = l->Lnext);
+ return (l);
+}
+
+ugconvert (uname,gname,uid,gid,mode)
+char *uname,*gname;
+int *uid,*gid,*mode;
+{
+ register LIST *u,*g;
+ register struct passwd *pw;
+ register struct group *gr;
+ struct stat sbuf;
+ static int defuid = -1;
+ static int defgid;
+ static int first = TRUE;
+
+ if (first) {
+ bzero ((char *)uidL, sizeof (uidL));
+ bzero ((char *)gidL, sizeof (gidL));
+ first = FALSE;
+ }
+ pw = NULL;
+ if (u = Llookup (uidL,uname))
+ *uid = u->Lnumber;
+ else if (pw = getpwnam (uname)) {
+ Linsert (uidL,salloc(uname),pw->pw_uid);
+ *uid = pw->pw_uid;
+ }
+ if (u || pw) {
+ if (g = Llookup (gidL,gname)) {
+ *gid = g->Lnumber;
+ return;
+ }
+ if (gr = getgrnam (gname)) {
+ Linsert (gidL,salloc(gname),gr->gr_gid);
+ *gid = gr->gr_gid;
+ return;
+ }
+ if (pw == NULL)
+ pw = getpwnam (uname);
+ *mode &= ~S_ISGID;
+ *gid = pw->pw_gid;
+ return;
+ }
+ *mode &= ~(S_ISUID|S_ISGID);
+ if (defuid >= 0) {
+ *uid = defuid;
+ *gid = defgid;
+ return;
+ }
+ if (stat (".",&sbuf) < 0) {
+ *uid = defuid = getuid ();
+ *gid = defgid = getgid ();
+ return;
+ }
+ *uid = defuid = sbuf.st_uid;
+ *gid = defgid = sbuf.st_gid;
+}
+
+
+/*********************************************
+ *** U T I L I T Y R O U T I N E S ***
+ *********************************************/
+
+#if __STDC__
+notify (char *fmt,...) /* record error message */
+#else
+/*VARARGS*//*ARGSUSED*/
+notify (va_alist) /* record error message */
+va_dcl
+#endif
+{
+#if !__STDC__
+ char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ char collrelname[STRINGLENGTH];
+ long tloc;
+ static FILE *noteF = NULL; /* mail program on pipe */
+ va_list ap;
+
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ fmt = va_arg(ap,char *);
+#endif
+ if (fmt == NULL) {
+ if (noteF && noteF != stdout)
+ (void) pclose (noteF);
+ noteF = NULL;
+ return;
+ }
+ if ((thisC->Cflags&CFURELSUF) && thisC->Crelease)
+ (void) sprintf (collrelname,"%s-%s",collname,thisC->Crelease);
+ else
+ (void) strcpy (collrelname,collname);
+
+ if (noteF == NULL) {
+ if ((thisC->Cflags&CFMAIL) && thisC->Cnotify) {
+ (void) sprintf (buf,"mail -s \"SUP Upgrade of %s\" %s >/dev/null",
+ collrelname,thisC->Cnotify);
+ noteF = popen (buf,"w");
+ if (noteF == NULL) {
+ logerr ("Can't send mail to %s for %s",
+ thisC->Cnotify,collrelname);
+ noteF = stdout;
+ }
+ } else
+ noteF = stdout;
+ tloc = time ((long *)NULL);
+ fprintf (noteF,"SUP Upgrade of %s at %s",
+ collrelname,ctime (&tloc));
+ (void) fflush (noteF);
+ }
+ vfprintf(noteF,fmt,ap);
+ va_end(ap);
+ (void) fflush (noteF);
+}
+
+lockout (on) /* lock out interrupts */
+int on;
+{
+ register int x;
+ static int lockmask;
+
+ if (on) {
+ x = sigmask (SIGHUP) | sigmask (SIGINT) |
+ sigmask (SIGQUIT) | sigmask (SIGTERM);
+ lockmask = sigblock (x);
+ }
+ else {
+ (void) sigsetmask (lockmask);
+ }
+}
+
+char *fmttime (time)
+long time;
+{
+ static char buf[STRINGLENGTH];
+ int len;
+
+ (void) strcpy (buf,ctime (&time));
+ len = strlen(buf+4)-6;
+ (void) strncpy (buf,buf+4,len);
+ buf[len] = '\0';
+ return (buf);
+}
diff --git a/usr.bin/sup/src/supcname.c b/usr.bin/sup/src/supcname.c
new file mode 100644
index 00000000000..fbad5e3e325
--- /dev/null
+++ b/usr.bin/sup/src/supcname.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * sup client name server interface
+ **********************************************************************
+ * HISTORY
+ * $Log: supcname.c,v $
+ * Revision 1.1 1995/12/16 11:46:58 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1995/09/16 19:12:14 glass
+ * if the function returns nothing, declare it void
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.4 92/08/11 12:07:32 mrt
+ * Added copyright.
+ * [92/08/10 mrt]
+ *
+ * 21-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed to no longer use a name server.
+ *
+ * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Changed getnams and added several new routines to change the
+ * way that sup finds nameservers. It now builds a tree of
+ * servers to check. It walks over the tree. At each node, it
+ * tries to contact the name server and get as many names
+ * resolved as it can. It stops after either all collections
+ * have host names, or if some collections don't have host names
+ * but either everyone doesn't know what they are, or after too
+ * many tries, none could be reached.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Split off from sup.c
+ *
+ **********************************************************************
+ */
+
+#include "supcdefs.h"
+
+extern COLLECTION *firstC; /* collection list pointer */
+
+/*****************************************
+ *** G E T H O S T N A M E S ***
+ *****************************************/
+
+/*
+ * For each collection that doesn't have a host name specified, read
+ * the file server list for the name of the host for that collection.
+ * It's a fatal error if a collection has no file server.
+ */
+
+void getnams ()
+{
+ register COLLECTION *c;
+ char buf[STRINGLENGTH];
+ register FILE *f;
+ char *p,*q;
+
+ for (c = firstC; c && c->Chtree != NULL; c = c->Cnext);
+ if (c == NULL) return;
+ (void) sprintf (buf,FILEHOSTS,DEFDIR);
+ f = fopen (buf,"r");
+ if (f == NULL) logquit (1,"Can't open %s",buf);
+ while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) {
+ if (q = index (p,'\n')) *q = '\0';
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p,"= \t");
+ p = skipover (p," \t");
+ if (*p == '=') p++;
+ p = skipover (p," \t");
+ if (*p == '\0') goaway ("error in collection/host file");
+ do {
+ if (strcmp (c->Cname, q) == 0) {
+ do {
+ q = nxtarg (&p,", \t");
+ p = skipover (p," \t");
+ if (*p == ',') p++;
+ p = skipover (p," \t");
+ (void) Tinsert (&c->Chtree,q,FALSE);
+ } while (*p != '\0');
+ }
+ while ((c = c->Cnext) != NULL && c->Chtree != NULL);
+ } while (c != NULL);
+ for (c = firstC; c && c->Chtree != NULL; c = c->Cnext);
+ if (c == NULL) break;
+ }
+ (void) fclose (f);
+ if (c == NULL) return;
+ do {
+ logerr ("Host for collection %s not found",c->Cname);
+ while ((c = c->Cnext) != NULL && c->Chtree != NULL);
+ } while (c);
+ logquit (1,"Hosts not found for all collections");
+}
diff --git a/usr.bin/sup/src/supcparse.c b/usr.bin/sup/src/supcparse.c
new file mode 100644
index 00000000000..ea3eb6e6eb4
--- /dev/null
+++ b/usr.bin/sup/src/supcparse.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * sup collection parsing routines
+ **********************************************************************
+ * HISTORY
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supcparse.c,v $
+ * Revision 1.1 1995/12/16 11:46:58 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.4 1995/06/09 04:33:34 christos
+ * fixed bug related to the ascii `when' files previous fix, where the -t
+ * option would fail to read the timestamp files.
+ *
+ * Revision 1.2 1993/08/04 17:46:20 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:18 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.6 92/08/11 12:07:38 mrt
+ * Added use-rel-suffix option corresponding to -u switch.
+ * [92/07/26 mrt]
+ *
+ * Revision 1.5 92/02/08 18:24:19 mja
+ * Added "keep" supfile option, corresponding to -k switch.
+ * [92/01/17 vdelvecc]
+ *
+ * Revision 1.4 91/05/16 14:49:50 ern
+ * Change default timeout from none to 3 hours so we don't accumalute
+ * processes running sups to dead hosts especially for users.
+ * [91/05/16 14:49:21 ern]
+ *
+ *
+ * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added timeout to backoff.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support. Removed obsolete options.
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Split off from sup.c
+ *
+ **********************************************************************
+ */
+
+#include "supcdefs.h"
+
+
+#ifdef lint
+static char _argbreak;
+#else
+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
+} OPTION;
+
+struct option {
+ char *op_name;
+ OPTION op_enum;
+} options[] = {
+ "host", OHOST,
+ "base", OBASE,
+ "hostbase", OHOSTBASE,
+ "prefix", OPREFIX,
+ "release", ORELEASE,
+ "notify", ONOTIFY,
+ "login", OLOGIN,
+ "password", OPASSWORD,
+ "crypt", OCRYPT,
+ "backup", OBACKUP,
+ "delete", ODELETE,
+ "execute", OEXECUTE,
+ "old", OOLD,
+ "timeout", OTIMEOUT,
+ "keep", OKEEP,
+ "use-rel-suffix", OURELSUF,
+ "compress", OCOMPRESS
+};
+
+passdelim (ptr,delim) /* skip over delimiter */
+char **ptr,delim;
+{
+ *ptr = skipover (*ptr, " \t");
+ if (_argbreak != delim && **ptr == delim) {
+ (*ptr)++;
+ *ptr = skipover (*ptr, " \t");
+ }
+}
+
+parsecoll(c,collname,args)
+COLLECTION *c;
+char *collname,*args;
+{
+ register char *arg,*p;
+ register OPTION option;
+ int opno;
+
+ c->Cnext = NULL;
+ c->Cname = salloc (collname);
+ c->Chost = NULL;
+ c->Chtree = NULL;
+ c->Cbase = NULL;
+ c->Chbase = NULL;
+ c->Cprefix = NULL;
+ c->Crelease = NULL;
+ c->Cnotify = NULL;
+ c->Clogin = NULL;
+ c->Cpswd = NULL;
+ c->Ccrypt = NULL;
+ c->Ctimeout = 3*60*60; /* default to 3 hours instead of no timeout */
+ c->Cflags = 0;
+ c->Cnogood = FALSE;
+ c->Clockfd = -1;
+ args = skipover (args," \t");
+ while (*(arg=nxtarg(&args," \t="))) {
+ for (opno = 0; opno < sizeofA(options); opno++)
+ if (strcmp (arg,options[opno].op_name) == 0)
+ break;
+ if (opno == sizeofA(options)) {
+ logerr ("Invalid supfile option %s for collection %s",
+ arg,c->Cname);
+ return(-1);
+ }
+ option = options[opno].op_enum;
+ switch (option) {
+ case OHOST:
+ passdelim (&args,'=');
+ do {
+ arg = nxtarg (&args,", \t");
+ (void) Tinsert (&c->Chtree,arg,FALSE);
+ arg = args;
+ p = skipover (args," \t");
+ if (*p++ == ',') args = p;
+ } while (arg != args);
+ break;
+ case OBASE:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Cbase = salloc (arg);
+ break;
+ case OHOSTBASE:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Chbase = salloc (arg);
+ break;
+ case OPREFIX:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Cprefix = salloc (arg);
+ break;
+ case ORELEASE:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Crelease = salloc (arg);
+ break;
+ case ONOTIFY:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Cnotify = salloc (arg);
+ break;
+ case OLOGIN:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Clogin = salloc (arg);
+ break;
+ case OPASSWORD:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Cpswd = salloc (arg);
+ break;
+ case OCRYPT:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Ccrypt = salloc (arg);
+ break;
+ case OBACKUP:
+ c->Cflags |= CFBACKUP;
+ break;
+ case ODELETE:
+ c->Cflags |= CFDELETE;
+ break;
+ case OEXECUTE:
+ c->Cflags |= CFEXECUTE;
+ break;
+ case OOLD:
+ c->Cflags |= CFOLD;
+ break;
+ case OKEEP:
+ c->Cflags |= CFKEEP;
+ break;
+ case OURELSUF:
+ c->Cflags |= CFURELSUF;
+ break;
+ case OCOMPRESS:
+ c->Cflags |= CFCOMPRESS;
+ break;
+ case OTIMEOUT:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Ctimeout = atoi (arg);
+ break;
+ }
+ }
+ return(0);
+}
+
+
+long
+getwhen(collection, relsuffix)
+ char *collection, *relsuffix;
+{
+ char buf[STRINGLENGTH];
+ char *ep;
+ FILE *fp;
+ long tstamp;
+
+ (void) sprintf (buf,FILEWHEN,collection,relsuffix);
+
+ if ((fp = fopen(buf, "r")) == NULL)
+ return 0;
+
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ (void) fclose(fp);
+ return 0;
+ }
+
+ (void) fclose(fp);
+
+ if ((tstamp = strtol(buf, &ep, 0)) == -1 || *ep != '\n')
+ return 0;
+
+ return tstamp;
+}
+
+int
+putwhen(fname, tstamp)
+ char *fname;
+ long tstamp;
+{
+ FILE *fp;
+ if ((fp = fopen(fname, "w")) == NULL)
+ return 0;
+ if (fprintf(fp, "%ld\n", tstamp) < 0)
+ return 0;
+ if (fclose(fp) != 0)
+ return 0;
+ return 1;
+}
diff --git a/usr.bin/sup/src/supcvers.c b/usr.bin/sup/src/supcvers.c
new file mode 100644
index 00000000000..e325fe97c1d
--- /dev/null
+++ b/usr.bin/sup/src/supcvers.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ **********************************************************************
+ * HISTORY
+ * $Log: supcvers.c,v $
+ * Revision 1.1 1995/12/16 11:46:59 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:19 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.8 92/08/11 12:07:51 mrt
+ * Added use-rel-suffix option. Picked up STUMP changes.
+ * [V7.26]
+ *
+ * Revision 1.7 92/02/08 18:24:23 mja
+ * Support for -k/-K and "keep" option. [V7.25]
+ * [92/01/17 vdelvecc]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support. Removed nameserver support. [V7.24]
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support. [V6.23]
+ *
+ * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Changes for Version 6, better supoort to reflect errors to
+ * logfile. [V6.22]
+ *
+ * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Split sup.c into subparts. [V5.21]
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changes to many files to make lint happy. [V5.20]
+ *
+ * 01-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changes to sup.c and scmio.c. [V5.19]
+ *
+ * 19-Sep-86 Mike Accetta (mja) at Carnegie-Mellon University
+ * Changes to sup.c. [V5.18]
+ *
+ * 21-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Minor bug fix to previous edit in sup.c. [V5.17]
+ *
+ * 07-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changes to sup.c and sup.h. [V5.16]
+ *
+ * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added changes to sup.c, sup.h, scm.c, scmio.h. [V5.15]
+ *
+ * 19-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created. [V5.14]
+ *
+ **********************************************************************
+ */
+
+int PGMVERSION = 26; /* program version of sup */
diff --git a/usr.bin/sup/src/supfilesrv.c b/usr.bin/sup/src/supfilesrv.c
new file mode 100644
index 00000000000..12e2ce20e16
--- /dev/null
+++ b/usr.bin/sup/src/supfilesrv.c
@@ -0,0 +1,1870 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ *
+/*
+ * 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
+ * 13-Sep-92 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Changed name of sup program in xpatch from /usr/cs/bin/sup to
+ * /usr/bin/sup for exported version of sup.
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supfilesrv.c,v $
+ * Revision 1.1 1995/12/16 11:46:59 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.8 1995/10/29 23:54:49 christos
+ * - runio fails when result != 0 not only < 0
+ * - print vis-encoded file in the scanner.
+ *
+ * Revision 1.7 1995/06/24 16:21:55 christos
+ * - Don't use system(3) to fork processes. It is a big security hole.
+ * - Encode the filenames in the scan files using strvis(3), so filenames
+ * that contain newlines or other weird characters don't break the scanner.
+ *
+ * Revision 1.6 1995/06/03 21:22:00 christos
+ * Changes to write ascii timestamps in the when files.
+ * Looked into making it 64 bit clean, but it is hopeless.
+ * Added little program to convert from the old timestamp files
+ * into the new ones.
+ *
+ * Revision 1.5 1993/08/04 17:46:21 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.3 1993/06/05 21:32:17 cgd
+ * use daemon() to put supfilesrv into daemon mode...
+ *
+ * Revision 1.2 1993/05/24 17:57:31 brezak
+ * Remove netcrypt.c. Remove unneeded files. Cleanup make.
+ *
+ * Revision 1.20 92/09/09 22:05:00 mrt
+ * Added Brad's change to make sendfile take a va_list.
+ * Added support in login to accept an non-encrypted login
+ * message if no user or password is being sent. This supports
+ * a non-crypting version of sup. Also fixed to skip leading
+ * white space from crypts in host files.
+ * [92/09/01 mrt]
+ *
+ * Revision 1.19 92/08/11 12:07:59 mrt
+ * Made maxchildren a patchable variable, which can be set by the
+ * command line switch -C or else defaults to the MAXCHILDREN
+ * defined in sup.h. Added most of Brad's STUMP changes.
+ * Increased PGMVERSION to 12 to reflect substantial changes.
+ * [92/07/28 mrt]
+ *
+ * Revision 1.18 90/12/25 15:15:39 ern
+ * Yet another rewrite of the logging code. Make up the text we will write
+ * and then get in, write it and get out.
+ * Also set error on write-to-full-disk if the logging is for recording
+ * server is busy.
+ * [90/12/25 15:15:15 ern]
+ *
+ * Revision 1.17 90/05/07 09:31:13 dlc
+ * Sigh, some more fixes to the new "crypt" file handling code. First,
+ * just because the "crypt" file is in a local file system does not mean
+ * it can be trusted. We have to check for hard links to root owned
+ * files whose contents could be interpretted as a crypt key. For
+ * checking this fact, the new routine stat_info_ok() was added. This
+ * routine also makes other sanity checks, such as owner only permission,
+ * the file is a regular file, etc. Also, even if the uid/gid of th
+ * "crypt" file is not going to be used, still use its contents in order
+ * to cause fewer surprises to people supping out of a shared file system
+ * such as AFS.
+ * [90/05/07 dlc]
+ *
+ * Revision 1.16 90/04/29 04:21:08 dlc
+ * Fixed logic bug in docrypt() which would not get the stat information
+ * from the crypt file if the crypt key had already been set from a
+ * "host" file.
+ * [90/04/29 dlc]
+ *
+ * Revision 1.15 90/04/18 19:51:27 dlc
+ * Added the new routines local_file(), link_nofollow() for use in
+ * dectecting whether a file is located in a local file system. These
+ * routines probably should have been in another module, but only
+ * supfilesrv needs to do the check and none of its other modules seemed
+ * appropriate. Note, the implementation should be changed once we have
+ * direct kernel support, for example the fstatfs(2) system call, for
+ * detecting the type of file system a file resides. Also, I changed
+ * the routines which read the crosspatch crypt file or collection crypt
+ * file to save the uid and gid from the stat information obtained via
+ * the local_file() call (when the file is local) at the same time the
+ * crypt key is read. This change disallows non-local files for the
+ * crypt key to plug a security hole involving the usage of the uid/gid
+ * of the crypt file to define who the the file server should run as. If
+ * the saved uid/gid are both valid, then the server will set its uid/gid
+ * to these values.
+ * [90/04/18 dlc]
+ *
+ * Revision 1.14 89/08/23 14:56:15 gm0w
+ * Changed msgf routines to msg routines.
+ * [89/08/23 gm0w]
+ *
+ * Revision 1.13 89/08/03 19:57:33 mja
+ * Remove setaid() call.
+ *
+ * Revision 1.12 89/08/03 19:49:24 mja
+ * Updated to use v*printf() in place of _doprnt().
+ * [89/04/19 mja]
+ *
+ * 11-Sep-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to record release name in logfile.
+ *
+ * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added host=<hostfile> support to releases file. [V7.12]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support. Created docrypt() routine for crypt
+ * test message.
+ *
+ * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed common information logging code, the quiet switch, and
+ * moved samehost() check to after device/inode check.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support. [V5.11]
+ *
+ * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Added code to record final status of client in logfile. [V5.10]
+ *
+ * 22-May-87 Chriss Stephens (chriss) at Carnegie Mellon University
+ * Mergered divergent CS and ECE versions. [V5.9a]
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed support for version 3 of SUP protocol. Added changes
+ * to make lint happy. Added calls to new logging routines. [V5.9]
+ *
+ * 31-Mar-87 Dan Nydick (dan) at Carnegie-Mellon University
+ * Fixed so no password check is done when crypts are used.
+ *
+ * 25-Nov-86 Rudy Nedved (ern) at Carnegie-Mellon University
+ * Set F_APPEND fcntl in logging to increase the chance
+ * that the log entry from this incarnation of the file
+ * server will not be lost by another incarnation. [V5.8]
+ *
+ * 20-Oct-86 Dan Nydick (dan) at Carnegie-Mellon University
+ * Changed not to call okmumbles when not compiled with CMUCS.
+ *
+ * 04-Aug-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to increment scmdebug as more -N flags are
+ * added. [V5.7]
+ *
+ * 25-May-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University
+ * Renamed local variable in main program from "sigmask" to
+ * "signalmask" to avoid name conflict with 4.3BSD identifier.
+ * Conditionally compile in calls to CMU routines, "setaid" and
+ * "logaccess". [V5.6]
+ *
+ * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed supfilesrv to use the crypt file owner and group for
+ * access purposes, rather than the directory containing the crypt
+ * file. [V5.5]
+ *
+ * 07-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to keep logfiles in repository collection directory.
+ * Added code for locking collections. [V5.4]
+ *
+ * 05-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to support new FSETUPBUSY return. Now accepts all
+ * connections and tells any clients after the 8th that the
+ * fileserver is busy. New clients will retry again later. [V5.3]
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Major rewrite for protocol version 4. [V4.2]
+ *
+ * 12-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Fixed close of crypt file to use file pointer as argument
+ * instead of string pointer.
+ *
+ * 24-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Allow "!hostname" lines and comments in collection "host" file.
+ *
+ * 13-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Don't use access() on symbolic links since they may not point to
+ * an existing file.
+ *
+ * 22-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code to restrict file server availability to when it has
+ * less than or equal to eight children.
+ *
+ * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Merged 4.1 and 4.2 versions together.
+ *
+ * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for 4.2 BSD.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#ifdef AFS
+#include <afs/param.h>
+#undef MAXNAMLEN
+#endif
+#include <sys/param.h>
+#include <c.h>
+#include <signal.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <pwd.h>
+#include <grp.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/dir.h>
+#if MACH
+#include <sys/ioctl.h>
+#endif
+#if CMUCS
+#include <acc.h>
+#include <sys/ttyloc.h>
+#include <access.h>
+#include <sys/viceioctl.h>
+#else CMUCS
+#define ACCESS_CODE_OK 0
+#define ACCESS_CODE_BADPASSWORD (-2)
+#endif CMUCS
+#include "sup.h"
+#define MSGFILE
+#include "supmsg.h"
+
+#ifdef lint
+/*VARARGS1*//*ARGSUSED*/
+static void quit(status) {};
+#endif /* lint */
+
+extern int errno;
+long time ();
+uid_t getuid ();
+
+int maxchildren;
+
+/*
+ * These are used to save the stat information from the crosspatch crypt
+ * file or collection crypt file at the time it is opened for the crypt
+ * key and it is verified to be a local file.
+ */
+int runas_uid = -1;
+int runas_gid = -1;
+
+#define PGMVERSION 13
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+#define HASHBITS 8
+#define HASHSIZE (1<<HASHBITS)
+#define HASHMASK (HASHSIZE-1)
+#define HASHFUNC(x,y) ((x)&HASHMASK)
+
+/*******************************************
+ *** D A T A S T R U C T U R E S ***
+ *******************************************/
+
+struct hashstruct { /* hash table for number lists */
+ int Hnum1; /* numeric keys */
+ int Hnum2;
+ char *Hname; /* string value */
+ TREE *Htree; /* TREE value */
+ struct hashstruct *Hnext;
+};
+typedef struct hashstruct HASH;
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+char program[] = "supfilesrv"; /* program name for SCM messages */
+int progpid = -1; /* and process id */
+
+jmp_buf sjbuf; /* jump location for network errors */
+TREELIST *listTL; /* list of trees to upgrade */
+
+int live; /* -l flag */
+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 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];
+HASH *inodeH[HASHSIZE]; /* for inode lookup for linked file check */
+
+char *fmttime (); /* time format routine */
+#if __STDC__
+int goaway(char *fmt,...);
+#endif
+
+/*************************************
+ *** M A I N R O U T I N E ***
+ *************************************/
+
+main (argc,argv)
+int argc;
+char **argv;
+{
+ register int x,pid,signalmask;
+ struct sigvec chldvec,ignvec,oldvec;
+ void chldsig();
+ long tloc;
+
+ /* initialize global variables */
+ pgmversion = PGMVERSION; /* export version number */
+ server = TRUE; /* export that we're not a server */
+ collname = NULL; /* no current collection yet */
+ maxchildren = MAXCHILDREN; /* defined in sup.h */
+
+ init (argc,argv); /* process arguments */
+
+#ifdef HAS_DAEMON
+ if (!live) /* if not debugging, turn into daemon */
+ daemon(0, 0);
+#endif
+
+ logopen ("supfile");
+ tloc = time ((long *)NULL);
+ loginfo ("SUP File Server Version %d.%d (%s) starting at %s",
+ PROTOVERSION,PGMVERSION,scmversion,fmttime (tloc));
+ if (live) {
+ x = service ();
+ if (x != SCMOK)
+ logquit (1,"Can't connect to network");
+ answer ();
+ (void) serviceend ();
+ exit (0);
+ }
+ ignvec.sv_handler = SIG_IGN;
+ ignvec.sv_onstack = 0;
+ ignvec.sv_mask = 0;
+ (void) sigvec (SIGHUP,&ignvec,&oldvec);
+ (void) sigvec (SIGINT,&ignvec,&oldvec);
+ (void) sigvec (SIGPIPE,&ignvec,&oldvec);
+ chldvec.sv_handler = chldsig;
+ chldvec.sv_mask = 0;
+ chldvec.sv_onstack = 0;
+ (void) sigvec (SIGCHLD,&chldvec,&oldvec);
+ nchildren = 0;
+ for (;;) {
+ x = service ();
+ if (x != SCMOK) {
+ logerr ("Error in establishing network connection");
+ (void) servicekill ();
+ continue;
+ }
+ signalmask = sigblock(sigmask(SIGCHLD));
+ if ((pid = fork()) == 0) { /* server process */
+ (void) serviceprep ();
+ answer ();
+ (void) serviceend ();
+ exit (0);
+ }
+ (void) servicekill (); /* parent */
+ if (pid > 0) nchildren++;
+ (void) sigsetmask(signalmask);
+ }
+}
+
+/*
+ * Child status signal handler
+ */
+
+void
+chldsig(snum)
+ int snum;
+{
+ union wait w;
+
+ while (wait3((int *) &w, WNOHANG, (struct rusage *)0) > 0) {
+ if (nchildren) nchildren--;
+ }
+}
+
+/*****************************************
+ *** I N I T I A L I Z A T I O N ***
+ *****************************************/
+
+usage ()
+{
+ quit (1,"Usage: supfilesrv [ -l | -P | -N | -C <max children> | -H <host> <user> <cryptfile> <supargs> ]\n");
+}
+
+init (argc,argv)
+int argc;
+char **argv;
+{
+ register int i;
+ register int x;
+ char *clienthost,*clientuser;
+ char *p,*q;
+ char buf[STRINGLENGTH];
+ int maxsleep;
+ register FILE *f;
+
+#ifdef RCS
+ candorcs = FALSE;
+#endif
+ live = FALSE;
+ dbgportsq = FALSE;
+ scmdebug = 0;
+ clienthost = NULL;
+ clientuser = NULL;
+ maxsleep = 5;
+ if (--argc < 0)
+ usage ();
+ argv++;
+ while (clienthost == NULL && argc > 0 && argv[0][0] == '-') {
+ switch (argv[0][1]) {
+ case 'l':
+ live = TRUE;
+ break;
+ case 'P':
+ dbgportsq = TRUE;
+ break;
+ case 'N':
+ scmdebug++;
+ break;
+ case 'C':
+ if (--argc < 1)
+ quit (1,"Missing arg to -C\n");
+ argv++;
+ maxchildren = atoi(argv[0]);
+ break;
+ case 'H':
+ if (--argc < 3)
+ quit (1,"Missing args to -H\n");
+ argv++;
+ clienthost = argv[0];
+ clientuser = argv[1];
+ cryptkey = argv[2];
+ argc -= 2;
+ argv += 2;
+ break;
+#ifdef RCS
+ case 'R':
+ candorcs = TRUE;
+ break;
+#endif
+ default:
+ fprintf (stderr,"Unknown flag %s ignored\n",argv[0]);
+ break;
+ }
+ --argc;
+ argv++;
+ }
+ if (clienthost == NULL) {
+ if (argc != 0)
+ usage ();
+ x = servicesetup (dbgportsq ? DEBUGFPORT : FILEPORT);
+ if (x != SCMOK)
+ quit (1,"Error in network setup");
+ for (i = 0; i < HASHSIZE; i++)
+ uidH[i] = gidH[i] = inodeH[i] = NULL;
+ return;
+ }
+ server = FALSE;
+ if (argc < 1)
+ usage ();
+ f = fopen (cryptkey,"r");
+ if (f == NULL)
+ quit (1,"Unable to open cryptfile %s\n",cryptkey);
+ if (p = fgets (buf,STRINGLENGTH,f)) {
+ if (q = index (p,'\n')) *q = '\0';
+ if (*p == '\0')
+ quit (1,"No cryptkey found in %s\n",cryptkey);
+ cryptkey = salloc (buf);
+ }
+ (void) fclose (f);
+ x = request (dbgportsq ? DEBUGFPORT : FILEPORT,clienthost,&maxsleep);
+ if (x != SCMOK)
+ quit (1,"Unable to connect to host %s\n",clienthost);
+ x = msgsignon ();
+ if (x != SCMOK)
+ quit (1,"Error sending signon request to fileserver\n");
+ x = msgsignonack ();
+ if (x != SCMOK)
+ quit (1,"Error reading signon reply from fileserver\n");
+ printf ("SUP Fileserver %d.%d (%s) %d on %s\n",
+ protver,pgmver,scmver,fspid,remotehost());
+ free (scmver);
+ scmver = NULL;
+ if (protver < 7)
+ quit (1,"Remote fileserver does not implement reverse sup\n");
+ xpatch = TRUE;
+ xuser = clientuser;
+ x = msgsetup ();
+ if (x != SCMOK)
+ quit (1,"Error sending setup request to fileserver\n");
+ x = msgsetupack ();
+ if (x != SCMOK)
+ quit (1,"Error reading setup reply from fileserver\n");
+ switch (setupack) {
+ case FSETUPOK:
+ break;
+ case FSETUPSAME:
+ quit (1,"User %s not found on remote client\n",xuser);
+ case FSETUPHOST:
+ quit (1,"This host has no permission to reverse sup\n");
+ default:
+ quit (1,"Unrecognized file server setup status %d\n",setupack);
+ }
+ if (netcrypt (cryptkey) != SCMOK )
+ quit (1,"Running non-crypting fileserver\n");
+ crypttest = CRYPTTEST;
+ x = msgcrypt ();
+ if (x != SCMOK)
+ quit (1,"Error sending encryption test request\n");
+ x = msgcryptok ();
+ if (x == SCMEOF)
+ quit (1,"Data encryption test failed\n");
+ if (x != SCMOK)
+ quit (1,"Error reading encryption test reply\n");
+ logcrypt = CRYPTTEST;
+ loguser = NULL;
+ logpswd = NULL;
+ if (netcrypt (PSWDCRYPT) != SCMOK) /* encrypt password data */
+ quit (1,"Running non-crypting fileserver\n");
+ x = msglogin ();
+ (void) netcrypt ((char *)NULL); /* turn off encryption */
+ if (x != SCMOK)
+ quit (1,"Error sending login request to file server\n");
+ x = msglogack ();
+ if (x != SCMOK)
+ quit (1,"Error reading login reply from file server\n");
+ if (logack == FLOGNG)
+ quit (1,"%s\nImproper login to %s account\n",logerror,xuser);
+ xargc = argc;
+ xargv = argv;
+ x = msgxpatch ();
+ if (x != SCMOK)
+ quit (1,"Error sending crosspatch request\n");
+ crosspatch ();
+ exit (0);
+}
+
+/*****************************************
+ *** A N S W E R R E Q U E S T ***
+ *****************************************/
+
+answer ()
+{
+ long starttime;
+ register int x;
+
+ progpid = fspid = getpid ();
+ collname = NULL;
+ basedir = NULL;
+ prefix = NULL;
+ release = NULL;
+ rcs_branch = NULL;
+#ifdef CVS
+ cvs_root = NULL;
+#endif
+ goawayreason = NULL;
+ donereason = NULL;
+ lockfd = -1;
+ starttime = time ((long *)NULL);
+ if (!setjmp (sjbuf)) {
+ signon ();
+ setup ();
+ docrypt ();
+ login ();
+ if (xpatch) {
+ int fd;
+
+ x = msgxpatch ();
+ if (x != SCMOK)
+ exit (0);
+ xargv[0] = "sup";
+ xargv[1] = "-X";
+ xargv[xargc] = (char *)NULL;
+ (void) dup2 (netfile,0);
+ (void) dup2 (netfile,1);
+ (void) dup2 (netfile,2);
+ fd = getdtablesize ();
+ while (--fd > 2)
+ (void) close (fd);
+ execvp (xargv[0],xargv);
+ exit (0);
+ }
+ listfiles ();
+ sendfiles ();
+ }
+ finishup (starttime);
+ if (collname) free (collname);
+ 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;
+ free (goawayreason);
+ }
+ if (donereason) free (donereason);
+ if (lockfd >= 0) (void) close (lockfd);
+ endpwent ();
+ (void) endgrent ();
+#if CMUCS
+ endacent ();
+#endif /* CMUCS */
+ Hfree (uidH);
+ Hfree (gidH);
+ Hfree (inodeH);
+}
+
+/*****************************************
+ *** S I G N O N C L I E N T ***
+ *****************************************/
+
+signon ()
+{
+ register int x;
+
+ xpatch = FALSE;
+ x = msgsignon ();
+ if (x != SCMOK) goaway ("Error reading signon request from client");
+ x = msgsignonack ();
+ if (x != SCMOK) goaway ("Error sending signon reply to client");
+ free (scmver);
+ scmver = NULL;
+}
+
+/*****************************************************************
+ *** E X C H A N G E S E T U P I N F O R M A T I O N ***
+ *****************************************************************/
+
+setup ()
+{
+ register int x;
+ char *p,*q;
+ char buf[STRINGLENGTH];
+ register FILE *f;
+ struct stat sbuf;
+ register TREELIST *tl;
+
+ if (protver > 7) {
+ cancompress = TRUE;
+ }
+ x = msgsetup ();
+ if (x != SCMOK) goaway ("Error reading setup request from client");
+ if (protver < 4) {
+ setupack = FSETUPOLD;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Sup client using obsolete version of protocol");
+ }
+ if (xpatch) {
+ register struct passwd *pw;
+ extern int link_nofollow(), local_file();
+
+ if ((pw = getpwnam (xuser)) == NULL) {
+ setupack = FSETUPSAME;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("User not found");
+ }
+ (void) free (xuser);
+ xuser = salloc (pw->pw_dir);
+
+ /* check crosspatch host access file */
+ cryptkey = NULL;
+ (void) sprintf (buf,FILEXPATCH,xuser);
+
+ /* Turn off link following */
+ if (link_nofollow(1) != -1) {
+ int hostok = FALSE;
+ /* get stat info before open */
+ if (stat(buf, &sbuf) == -1)
+ (void) bzero((char *)&sbuf, sizeof(sbuf));
+
+ if ((f = fopen (buf,"r")) != NULL) {
+ struct stat fsbuf;
+
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t");
+ if (*p == '\0') continue;
+ if (!matchhost(q)) continue;
+
+ cryptkey = salloc (p);
+ hostok = TRUE;
+ if (local_file(fileno(f), &fsbuf) > 0
+ && stat_info_ok(&sbuf, &fsbuf)) {
+ runas_uid = sbuf.st_uid;
+ runas_gid = sbuf.st_gid;
+ }
+ break;
+ }
+ (void) fclose (f);
+ }
+
+ /* Restore link following */
+ if (link_nofollow(0) == -1)
+ goaway ("Restore link following");
+
+ if (!hostok) {
+ setupack = FSETUPHOST;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Host not on access list");
+ }
+ }
+ setupack = FSETUPOK;
+ x = msgsetupack ();
+ if (x != SCMOK)
+ 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') {
+ basedir = NULL;
+ (void) sprintf (buf,FILEDIRS,DEFDIR);
+ f = fopen (buf,"r");
+ if (f) {
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t=");
+ if (strcmp(q,collname) == 0) {
+ basedir = skipover(p," \t=");
+ basedir = salloc (basedir);
+ break;
+ }
+ }
+ (void) fclose (f);
+ }
+ if (basedir == NULL) {
+ (void) sprintf (buf,FILEBASEDEFAULT,collname);
+ basedir = salloc(buf);
+ }
+ }
+ if (chdir (basedir) < 0)
+ goaway ("Can't chdir to base directory %s",basedir);
+ (void) sprintf (buf,FILEPREFIX,collname);
+ f = fopen (buf,"r");
+ if (f) {
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ prefix = salloc(p);
+ if (chdir (prefix) < 0)
+ goaway ("Can't chdir to %s from base directory %s",
+ prefix,basedir);
+ break;
+ }
+ (void) fclose (f);
+ }
+ x = stat (".",&sbuf);
+ 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);
+ goaway ("Sup client told to try again later");
+ }
+ if (sbuf.st_dev == basedev && sbuf.st_ino == baseino && samehost()) {
+ setupack = FSETUPSAME;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Attempt to upgrade to same directory on same host");
+ }
+ /* obtain release information */
+ if (!getrelease (release)) {
+ setupack = FSETUPRELEASE;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Invalid release information");
+ }
+ /* check host access file */
+ cryptkey = NULL;
+ for (tl = listTL; tl != NULL; tl = tl->TLnext) {
+ char *h;
+ if ((h = tl->TLhost) == NULL)
+ h = FILEHOSTDEF;
+ (void) sprintf (buf,FILEHOST,collname,h);
+ f = fopen (buf,"r");
+ if (f) {
+ int hostok = FALSE;
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ int not;
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ 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);
+ break;
+ }
+ }
+ (void) fclose (f);
+ if (!hostok) {
+ setupack = FSETUPHOST;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Host not on access list for %s",
+ collname);
+ }
+ }
+ }
+ /* try to lock collection */
+ (void) sprintf (buf,FILELOCK,collname);
+ x = open (buf,O_RDONLY,0);
+ if (x >= 0) {
+ if (flock (x,(LOCK_SH|LOCK_NB)) < 0) {
+ (void) close (x);
+ if (errno != EWOULDBLOCK)
+ goaway ("Can't lock collection %s",collname);
+ setupack = FSETUPBUSY;
+ (void) msgsetupack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Sup client told to wait for lock");
+ }
+ lockfd = x;
+ }
+ setupack = FSETUPOK;
+ x = msgsetupack ();
+ if (x != SCMOK) goaway ("Error sending setup reply to client");
+}
+
+/** Test data encryption **/
+docrypt ()
+{
+ register int x;
+ char *p,*q;
+ char buf[STRINGLENGTH];
+ register FILE *f;
+ struct stat sbuf;
+ extern int link_nofollow(), local_file();
+
+ if (!xpatch) {
+ (void) sprintf (buf,FILECRYPT,collname);
+
+ /* Turn off link following */
+ if (link_nofollow(1) != -1) {
+ /* get stat info before open */
+ if (stat(buf, &sbuf) == -1)
+ (void) bzero((char *)&sbuf, sizeof(sbuf));
+
+ if ((f = fopen (buf,"r")) != NULL) {
+ struct stat fsbuf;
+
+ if (cryptkey == NULL &&
+ (p = fgets (buf,STRINGLENGTH,f))) {
+ if (q = index (p,'\n')) *q = '\0';
+ if (*p) cryptkey = salloc (buf);
+ }
+ if (local_file(fileno(f), &fsbuf) > 0
+ && stat_info_ok(&sbuf, &fsbuf)) {
+ runas_uid = sbuf.st_uid;
+ runas_gid = sbuf.st_gid;
+ }
+ (void) fclose (f);
+ }
+ /* Restore link following */
+ if (link_nofollow(0) == -1)
+ goaway ("Restore link following");
+ }
+ }
+ if ( netcrypt (cryptkey) != SCMOK )
+ goaway ("Runing non-crypting supfilesrv");
+ x = msgcrypt ();
+ if (x != SCMOK)
+ goaway ("Error reading encryption test request from client");
+ (void) netcrypt ((char *)NULL);
+ if (strcmp(crypttest,CRYPTTEST) != 0)
+ goaway ("Client not encrypting data properly");
+ free (crypttest);
+ crypttest = NULL;
+ x = msgcryptok ();
+ if (x != SCMOK)
+ goaway ("Error sending encryption test reply to client");
+}
+
+/***************************************************************
+ *** C O N N E C T T O P R O P E R A C C O U N T ***
+ ***************************************************************/
+
+login ()
+{
+ char *changeuid ();
+ register int x,fileuid,filegid;
+
+ (void) netcrypt (PSWDCRYPT); /* encrypt acct name and password */
+ x = msglogin ();
+ (void) netcrypt ((char *)NULL); /* turn off encryption */
+ if (x != SCMOK) goaway ("Error reading login request from client");
+ if ( logcrypt ) {
+ if (strcmp(logcrypt,CRYPTTEST) != 0) {
+ logack = FLOGNG;
+ logerror = "Improper login encryption";
+ (void) msglogack ();
+ goaway ("Client not encrypting login information properly");
+ }
+ free (logcrypt);
+ logcrypt = NULL;
+ }
+ if (loguser == NULL) {
+ if (cryptkey) {
+ if (runas_uid >= 0 && runas_gid >= 0) {
+ fileuid = runas_uid;
+ filegid = runas_gid;
+ loguser = NULL;
+ } else
+ loguser = salloc (DEFUSER);
+ } else
+ loguser = salloc (DEFUSER);
+ }
+ if ((logerror = changeuid (loguser,logpswd,fileuid,filegid)) != NULL) {
+ logack = FLOGNG;
+ (void) msglogack ();
+ if (protver >= 6) longjmp (sjbuf,TRUE);
+ goaway ("Client denied login access");
+ }
+ if (loguser) free (loguser);
+ if (logpswd) free (logpswd);
+ logack = FLOGOK;
+ x = msglogack ();
+ if (x != SCMOK) goaway ("Error sending login reply to client");
+ if (!xpatch) /* restore desired encryption */
+ if (netcrypt (cryptkey) != SCMOK)
+ goaway("Running non-crypting supfilesrv");
+ free (cryptkey);
+ cryptkey = NULL;
+}
+
+/*****************************************
+ *** M A K E N A M E L I S T ***
+ *****************************************/
+
+listfiles ()
+{
+ int denyone();
+ register int x;
+
+ refuseT = NULL;
+ x = msgrefuse ();
+ if (x != SCMOK) goaway ("Error reading refuse list from client");
+ getscanlists ();
+ Tfree (&refuseT);
+ x = msglist ();
+ if (x != SCMOK) goaway ("Error sending file list to client");
+ Tfree (&listT);
+ listT = NULL;
+ needT = NULL;
+ x = msgneed ();
+ if (x != SCMOK)
+ goaway ("Error reading needed files list from client");
+ denyT = NULL;
+ (void) Tprocess (needT,denyone);
+ Tfree (&needT);
+ x = msgdeny ();
+ if (x != SCMOK) goaway ("Error sending denied files list to client");
+ Tfree (&denyT);
+}
+
+denyone (t)
+register TREE *t;
+{
+ register TREELIST *tl;
+ register char *name = t->Tname;
+ register int update = (t->Tflags&FUPDATE) != 0;
+ struct stat sbuf;
+ register TREE *tlink;
+ TREE *linkcheck ();
+ char slinkname[STRINGLENGTH];
+ register int x;
+
+ for (tl = listTL; tl != NULL; tl = tl->TLnext)
+ if ((t = Tsearch (tl->TLtree,name)) != NULL)
+ break;
+ if (t == NULL) {
+ (void) Tinsert (&denyT,name,FALSE);
+ return (SCMOK);
+ }
+ cdprefix (tl->TLprefix);
+ if ((t->Tmode&S_IFMT) == S_IFLNK)
+ x = lstat(name,&sbuf);
+ else
+ x = stat(name,&sbuf);
+ if (x < 0 || (sbuf.st_mode&S_IFMT) != (t->Tmode&S_IFMT)) {
+ (void) Tinsert (&denyT,name,FALSE);
+ return (SCMOK);
+ }
+ switch (t->Tmode&S_IFMT) {
+ case S_IFLNK:
+ if ((x = readlink (name,slinkname,STRINGLENGTH)) <= 0) {
+ (void) Tinsert (&denyT,name,FALSE);
+ return (SCMOK);
+ }
+ slinkname[x] = '\0';
+ (void) Tinsert (&t->Tlink,slinkname,FALSE);
+ break;
+ case S_IFREG:
+ if (sbuf.st_nlink > 1 &&
+ (tlink = linkcheck (t,(int)sbuf.st_dev,(int)sbuf.st_ino)))
+ {
+ (void) Tinsert (&tlink->Tlink,name,FALSE);
+ return (SCMOK);
+ }
+ if (update) t->Tflags |= FUPDATE;
+ case S_IFDIR:
+ t->Tuid = sbuf.st_uid;
+ t->Tgid = sbuf.st_gid;
+ break;
+ default:
+ (void) Tinsert (&denyT,name,FALSE);
+ return (SCMOK);
+ }
+ t->Tflags |= FNEEDED;
+ return (SCMOK);
+}
+
+/*********************************
+ *** S E N D F I L E S ***
+ *********************************/
+
+sendfiles ()
+{
+ int sendone(),senddir(),sendfile();
+ register TREELIST *tl;
+ register int x;
+
+ /* Does the protocol support compression */
+ if (cancompress) {
+ /* Check for compression on sending files */
+ x = msgcompress();
+ if ( x != SCMOK)
+ goaway ("Error sending compression check to server");
+ }
+ /* 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 */
+ for (tl = listTL; tl != NULL; tl = tl->TLnext) {
+ cdprefix (tl->TLprefix);
+ (void) Trprocess (tl->TLtree,senddir);
+ }
+ x = msgsend ();
+ if (x != SCMOK)
+ goaway ("Error reading receive file request from client");
+ upgradeT = NULL;
+ x = msgrecv (sendfile,0);
+ if (x != SCMOK)
+ goaway ("Error sending file to client");
+}
+
+sendone (t)
+TREE *t;
+{
+ register int x,fd;
+ register int fdtmp;
+ char temp_file[STRINGLENGTH], rcs_file[STRINGLENGTH];
+ union wait status;
+ char *uconvert(),*gconvert();
+ int sendfile ();
+ int ac;
+ char *av[50]; /* More than enough */
+
+ if ((t->Tflags&FNEEDED) == 0) /* only send needed files */
+ return (SCMOK);
+ if ((t->Tmode&S_IFMT) == S_IFDIR) /* send no directories this pass */
+ return (SCMOK);
+ x = msgsend ();
+ if (x != SCMOK) goaway ("Error reading receive file request from client");
+ upgradeT = t; /* upgrade file pointer */
+ 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';
+ ac = 0;
+#ifdef CVS
+ av[ac++] = "cvs";
+ av[ac++] = "-d";
+ av[ac++] = cvs_root;
+ av[ac++] = "-r";
+ av[ac++] = "-l";
+ av[ac++] = "-Q";
+ av[ac++] = "co";
+ av[ac++] = "-p";
+ if (rcs_branch != NULL) {
+ av[ac++] = "-r";
+ av[ac++] = rcs_branch;
+ }
+#else
+ av[ac++] = "co";
+ av[ac++] = "-q";
+ av[ac++] = "-p";
+ if (rcs_branch != NULL) {
+ sprintf(rcs_release, "-r%s",
+ rcs_branch);
+ av[ac++] = rcs_release;
+ }
+#endif
+ av[ac++] = t->Tname;
+ av[ac++] = NULL;
+ status.w_status = runio(av,
+ NULL,
+ rcs_file,
+ "/dev/null");
+ /*loginfo("using rcs mode \n");*/
+ if (status.w_status < 0 || status.w_retcode) {
+ /* Just in case */
+ unlink(rcs_file);
+ if (status.w_status < 0) {
+ goaway ("We died trying to run cvs or rcs");
+ t->Tmode = 0;
+ }
+ else {
+ /*logerr("rcs command failed = %d\n",
+ status.w_retcode);*/
+ t->Tflags |= FUPDATE;
+ }
+ }
+ else if (docompress) {
+ tmpnam(temp_file);
+ av[0] = "gzip";
+ av[1] = "-c";
+ av[2] = NULL;
+ if (runio(av, rcs_file, temp_file, NULL) != 0) {
+ /* Just in case */
+ unlink(temp_file);
+ unlink(rcs_file);
+ goaway ("We died trying to gzip a file");
+ 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);
+ av[0] = "gzip";
+ av[1] = "-c";
+ av[2] = NULL;
+ if (runio(av, t->Tname, temp_file, NULL) != 0) {
+ /* Just in case */
+ unlink(temp_file);
+ goaway ("We died trying to run gzip");
+ 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));
+ t->Tgroup = salloc (gconvert (t->Tgid));
+ }
+ }
+ 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);
+}
+
+senddir (t)
+TREE *t;
+{
+ register int x;
+ char *uconvert(),*gconvert();
+ int sendfile ();
+
+ if ((t->Tflags&FNEEDED) == 0) /* only send needed files */
+ return (SCMOK);
+ if ((t->Tmode&S_IFMT) != S_IFDIR) /* send only directories this pass */
+ return (SCMOK);
+ x = msgsend ();
+ if (x != SCMOK) goaway ("Error reading receive file request from client");
+ upgradeT = t; /* upgrade file pointer */
+ t->Tuser = salloc (uconvert (t->Tuid));
+ t->Tgroup = salloc (gconvert (t->Tgid));
+ x = msgrecv (sendfile,0);
+ if (x != SCMOK) goaway ("Error sending file to client");
+ return (SCMOK);
+}
+
+sendfile (t,ap)
+register TREE *t;
+va_list ap;
+{
+ register int x;
+ int fd = va_arg(ap,int);
+ if ((t->Tmode&S_IFMT) != S_IFREG || listonly || (t->Tflags&FUPDATE))
+ return (SCMOK);
+ x = writefile (fd);
+ if (x != SCMOK) goaway ("Error sending file to client");
+ (void) close (fd);
+ return (SCMOK);
+}
+
+/*****************************************
+ *** E N D C O N N E C T I O N ***
+ *****************************************/
+
+finishup (starttime)
+long starttime;
+{
+ register int x = SCMOK;
+ char tmpbuf[BUFSIZ], *p, lognam[STRINGLENGTH];
+ int logfd;
+ struct stat sbuf;
+ long finishtime;
+ char *releasename;
+
+ (void) netcrypt ((char *)NULL);
+ if (protver < 6) {
+ if (goawayreason != NULL)
+ free (goawayreason);
+ goawayreason = (char *)NULL;
+ x = msggoaway();
+ doneack = FDONESUCCESS;
+ donereason = salloc ("Unknown");
+ } else if (goawayreason == (char *)NULL)
+ x = msgdone ();
+ else {
+ doneack = FDONEGOAWAY;
+ donereason = goawayreason;
+ }
+ if (x == SCMEOF || x == SCMERR) {
+ doneack = FDONEUSRERROR;
+ donereason = salloc ("Premature EOF on network");
+ } else if (x != SCMOK) {
+ doneack = FDONESRVERROR;
+ donereason = salloc ("Unknown SCM code");
+ }
+ if (doneack == FDONEDONTLOG)
+ return;
+ if (donereason == NULL)
+ donereason = salloc ("No reason");
+ if (doneack == FDONESRVERROR || doneack == FDONEUSRERROR)
+ logerr ("%s", donereason);
+ else if (doneack == FDONEGOAWAY)
+ logerr ("GOAWAY: %s",donereason);
+ else if (doneack != FDONESUCCESS)
+ logerr ("Reason %d: %s",doneack,donereason);
+ goawayreason = donereason;
+ cdprefix ((char *)NULL);
+ (void) sprintf (lognam,FILELOGFILE,collname);
+ if ((logfd = open(lognam,O_APPEND|O_WRONLY,0644)) < 0)
+ return; /* can not open file up...error */
+ finishtime = time ((long *)NULL);
+ p = tmpbuf;
+ (void) sprintf (p,"%s ",fmttime (lasttime));
+ p += strlen(p);
+ (void) sprintf (p,"%s ",fmttime (starttime));
+ p += strlen(p);
+ (void) sprintf (p,"%s ",fmttime (finishtime));
+ p += strlen(p);
+ if ((releasename = release) == NULL)
+ releasename = "UNKNOWN";
+ (void) sprintf (p,"%s %s %d %s\n",remotehost(),releasename,
+ FDONESUCCESS-doneack,donereason);
+ p += strlen(p);
+#if MACH
+ /* if we are busy dont get stuck updating the disk if full */
+ if(setupack == FSETUPBUSY) {
+ long l = FIOCNOSPC_ERROR;
+ ioctl(logfd, FIOCNOSPC, &l);
+ }
+#endif /* MACH */
+ (void) write(logfd,tmpbuf,(p - tmpbuf));
+ (void) close(logfd);
+}
+
+/***************************************************
+ *** H A S H T A B L E R O U T I N E S ***
+ ***************************************************/
+
+Hfree (table)
+HASH **table;
+{
+ register HASH *h;
+ register int i;
+ for (i = 0; i < HASHSIZE; i++)
+ while (h = table[i]) {
+ table[i] = h->Hnext;
+ if (h->Hname) free (h->Hname);
+ free ((char *)h);
+ }
+}
+
+HASH *Hlookup (table,num1,num2)
+HASH **table;
+int num1,num2;
+{
+ register HASH *h;
+ register int hno;
+ hno = HASHFUNC(num1,num2);
+ for (h = table[hno]; h && (h->Hnum1 != num1 || h->Hnum2 != num2); h = h->Hnext);
+ return (h);
+}
+
+Hinsert (table,num1,num2,name,tree)
+HASH **table;
+int num1,num2;
+char *name;
+TREE *tree;
+{
+ register HASH *h;
+ register int hno;
+ hno = HASHFUNC(num1,num2);
+ h = (HASH *) malloc (sizeof(HASH));
+ h->Hnum1 = num1;
+ h->Hnum2 = num2;
+ h->Hname = name;
+ h->Htree = tree;
+ h->Hnext = table[hno];
+ table[hno] = h;
+}
+
+/*********************************************
+ *** U T I L I T Y R O U T I N E S ***
+ *********************************************/
+
+TREE *linkcheck (t,d,i)
+TREE *t;
+int d,i; /* inode # and device # */
+{
+ register HASH *h;
+ h = Hlookup (inodeH,i,d);
+ if (h) return (h->Htree);
+ Hinsert (inodeH,i,d,(char *)NULL,t);
+ return ((TREE *)NULL);
+}
+
+char *uconvert (uid)
+int uid;
+{
+ register struct passwd *pw;
+ register char *p;
+ register HASH *u;
+ u = Hlookup (uidH,uid,0);
+ if (u) return (u->Hname);
+ pw = getpwuid (uid);
+ if (pw == NULL) return ("");
+ p = salloc (pw->pw_name);
+ Hinsert (uidH,uid,0,p,(TREE*)NULL);
+ return (p);
+}
+
+char *gconvert (gid)
+int gid;
+{
+ register struct group *gr;
+ register char *p;
+ register HASH *g;
+ g = Hlookup (gidH,gid,0);
+ if (g) return (g->Hname);
+ gr = getgrgid (gid);
+ if (gr == NULL) return ("");
+ p = salloc (gr->gr_name);
+ Hinsert (gidH,gid,0,p,(TREE *)NULL);
+ return (p);
+}
+
+char *changeuid (namep,passwordp,fileuid,filegid)
+char *namep,*passwordp;
+int fileuid,filegid;
+{
+ char *okpassword ();
+ char *group,*account,*pswdp;
+ struct passwd *pwd;
+ struct group *grp;
+#if CMUCS
+ struct account *acc;
+ struct ttyloc tlc;
+#endif /* CMUCS */
+ register int status = ACCESS_CODE_OK;
+ char nbuf[STRINGLENGTH];
+ static char errbuf[STRINGLENGTH];
+#if CMUCS
+ int *grps;
+#endif /* CMUCS */
+ char *p;
+
+ if (namep == NULL) {
+ pwd = getpwuid (fileuid);
+ if (pwd == NULL) {
+ (void) sprintf (errbuf,"Reason: Unknown user id %d",
+ fileuid);
+ return (errbuf);
+ }
+ grp = getgrgid (filegid);
+ if (grp) group = strcpy (nbuf,grp->gr_name);
+ else group = NULL;
+ account = NULL;
+ pswdp = NULL;
+ } else {
+ (void) strcpy (nbuf,namep);
+ account = group = index (nbuf,',');
+ if (group != NULL) {
+ *group++ = '\0';
+ account = index (group,',');
+ if (account != NULL) {
+ *account++ = '\0';
+ if (*account == '\0') account = NULL;
+ }
+ if (*group == '\0') group = NULL;
+ }
+ pwd = getpwnam (nbuf);
+ if (pwd == NULL) {
+ (void) sprintf (errbuf,"Reason: Unknown user %s",
+ nbuf);
+ return (errbuf);
+ }
+ if (strcmp (nbuf,DEFUSER) == 0)
+ pswdp = NULL;
+ else
+ pswdp = passwordp ? passwordp : "";
+#ifdef AFS
+ if (strcmp (nbuf,DEFUSER) != 0) {
+ char *reason;
+ setpag(); /* set a pag */
+ if (ka_UserAuthenticate(pwd->pw_name, "", 0,
+ pswdp, 1, &reason)) {
+ (void) sprintf (errbuf,"AFS authentication failed, %s",
+ reason);
+ logerr ("Attempt by %s; %s",
+ nbuf, errbuf);
+ return (errbuf);
+ }
+ }
+#endif
+ }
+ if (getuid () != 0) {
+ if (getuid () == pwd->pw_uid)
+ return (NULL);
+ if (strcmp (pwd->pw_name,DEFUSER) == 0)
+ return (NULL);
+ logerr ("Fileserver not superuser");
+ return ("Reason: fileserver is not running privileged");
+ }
+#if CMUCS
+ tlc.tlc_hostid = TLC_UNKHOST;
+ tlc.tlc_ttyid = TLC_UNKTTY;
+ if (okaccess(pwd->pw_name,ACCESS_TYPE_SU,0,-1,tlc) != 1)
+ status = ACCESS_CODE_DENIED;
+ else {
+ grp = NULL;
+ acc = NULL;
+ status = oklogin(pwd->pw_name,group,&account,pswdp,&pwd,&grp,&acc,&grps);
+ if (status == ACCESS_CODE_OK) {
+ if ((p = okpassword(pswdp,pwd->pw_name,pwd->pw_gecos)) != NULL)
+ status = ACCESS_CODE_INSECUREPWD;
+ }
+ }
+#else /* CMUCS */
+ status = ACCESS_CODE_OK;
+ if (namep && strcmp(pwd->pw_name, DEFUSER) != 0)
+ if (strcmp(pwd->pw_passwd,(char *)crypt(pswdp,pwd->pw_passwd)))
+ status = ACCESS_CODE_BADPASSWORD;
+#endif /* CMUCS */
+ switch (status) {
+ case ACCESS_CODE_OK:
+ break;
+ case ACCESS_CODE_BADPASSWORD:
+ p = "Reason: Invalid password";
+ break;
+#if CMUCS
+ case ACCESS_CODE_INSECUREPWD:
+ (void) sprintf (errbuf,"Reason: %s",p);
+ p = errbuf;
+ break;
+ case ACCESS_CODE_DENIED:
+ p = "Reason: Access denied";
+ break;
+ case ACCESS_CODE_NOUSER:
+ p = errbuf;
+ break;
+ case ACCESS_CODE_ACCEXPIRED:
+ p = "Reason: Account expired";
+ break;
+ case ACCESS_CODE_GRPEXPIRED:
+ p = "Reason: Group expired";
+ break;
+ case ACCESS_CODE_ACCNOTVALID:
+ p = "Reason: Invalid account";
+ break;
+ case ACCESS_CODE_MANYDEFACC:
+ p = "Reason: User has more than one default account";
+ break;
+ case ACCESS_CODE_NOACCFORGRP:
+ p = "Reason: No account for group";
+ break;
+ case ACCESS_CODE_NOGRPFORACC:
+ p = "Reason: No group for account";
+ break;
+ case ACCESS_CODE_NOGRPDEFACC:
+ p = "Reason: No group for default account";
+ break;
+ case ACCESS_CODE_NOTGRPMEMB:
+ p = "Reason: Not member of group";
+ break;
+ case ACCESS_CODE_NOTDEFMEMB:
+ p = "Reason: Not member of default group";
+ break;
+ case ACCESS_CODE_OOPS:
+ p = "Reason: Internal error";
+ break;
+#endif /* CMUCS */
+ default:
+ (void) sprintf (p = errbuf,"Reason: Status %d",status);
+ break;
+ }
+ if (pwd == NULL)
+ return (p);
+ if (status != ACCESS_CODE_OK) {
+ logerr ("Login failure for %s",pwd->pw_name);
+ logerr ("%s",p);
+#if CMUCS
+ logaccess (pwd->pw_name,ACCESS_TYPE_SUP,status,0,-1,tlc);
+#endif /* CMUCS */
+ return (p);
+ }
+#if CMUCS
+ if (setgroups (grps[0], &grps[1]) < 0)
+ logerr ("setgroups: %%m");
+ if (setgid ((gid_t)grp->gr_gid) < 0)
+ logerr ("setgid: %%m");
+ if (setuid ((uid_t)pwd->pw_uid) < 0)
+ logerr ("setuid: %%m");
+#else /* CMUCS */
+ if (initgroups (pwd->pw_name,pwd->pw_gid) < 0)
+ return("Error setting group list");
+ if (setgid (pwd->pw_gid) < 0)
+ logerr ("setgid: %%m");
+ if (setuid (pwd->pw_uid) < 0)
+ logerr ("setuid: %%m");
+#endif /* CMUCS */
+ return (NULL);
+}
+
+#if __STDC__
+goaway (char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+goaway (va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ register char *fmt;
+#endif
+ char buf[STRINGLENGTH];
+ va_list ap;
+
+ (void) netcrypt ((char *)NULL);
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ fmt = va_arg(ap,char *);
+#endif
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ goawayreason = salloc (buf);
+ (void) msggoaway ();
+ logerr ("%s",buf);
+ longjmp (sjbuf,TRUE);
+}
+
+char *fmttime (time)
+long time;
+{
+ static char buf[STRINGLENGTH];
+ int len;
+
+ (void) strcpy (buf,ctime (&time));
+ len = strlen(buf+4)-6;
+ (void) strncpy (buf,buf+4,len);
+ buf[len] = '\0';
+ return (buf);
+}
+
+/*
+ * Determine whether the file referenced by the file descriptor 'handle' can
+ * be trusted, namely is it a file resident in the local file system.
+ *
+ * The main method of operation is to perform operations on the file
+ * descriptor so that an attempt to spoof the checks should fail, for
+ * example renamimg the file from underneath us and/or changing where the
+ * file lives from underneath us.
+ *
+ * returns: -1 for error, indicating that we can not tell
+ * 0 for file is definately not local, or it is an RFS link
+ * 1 for file is local and can be trusted
+ *
+ * Side effect: copies the stat information into the supplied buffer,
+ * regardless of the type of file system the file resides.
+ *
+ * Currently, the cases that we try to distinguish are RFS, AFS, NFS and
+ * UFS, where the latter is considered a trusted file. We assume that the
+ * caller has disabled link following and will detect an attempt to access
+ * a file through an RFS link, except in the case the the last component is
+ * an RFS link. With link following disabled, the last component itself is
+ * interpreted as a regular file if it is really an RFS link, so we
+ * disallow the RFS link identified by group "symlink" and mode "IEXEC by
+ * owner only". An AFS file is
+ * detected by trying the VIOCIGETCELL ioctl, which is one of the few AFS
+ * ioctls which operate on a file descriptor. Note, this AFS ioctl is
+ * implemented in the cache manager, so the decision does not involve a
+ * query with the AFS file server. An NFS file is detected by looking at
+ * the major device number and seeing if it matches the known values for
+ * MACH NSF/Sun OS 3.x or Sun OS 4.x.
+ *
+ * Having the fstatfs() system call would make this routine easier and
+ * more reliable.
+ *
+ * Note, in order to make the checks simpler, the file referenced by the
+ * file descriptor can not be a BSD style symlink. Even with symlink
+ * following of the last path component disabled, the attempt to open a
+ * file which is a symlink will succeed, so we check for the BSD symlink
+ * file type here. Also, the link following on/off and RFS file types
+ * are only relevant in a MACH environment.
+ */
+#ifdef AFS
+#include <sys/viceioctl.h>
+#endif
+
+#define SYMLINK_GRP 64
+
+int local_file(handle, sinfo)
+int handle;
+struct stat *sinfo;
+{
+ struct stat sb;
+#ifdef VIOCIGETCELL
+ /*
+ * dummies for the AFS ioctl
+ */
+ struct ViceIoctl vdata;
+ char cellname[512];
+#endif /* VIOCIGETCELL */
+
+ if (fstat(handle, &sb) < 0)
+ return(-1);
+ if (sinfo != NULL)
+ *sinfo = sb;
+
+#if CMUCS
+ /*
+ * If the following test succeeds, then the file referenced by
+ * 'handle' is actually an RFS link, so we will not trust it.
+ * See <sys/inode.h>.
+ */
+ if (sb.st_gid == SYMLINK_GRP
+ && (sb.st_mode & (S_IFMT|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)))
+ == (S_IFREG|S_IEXEC))
+ return(0);
+#endif /* CMUCS */
+
+ /*
+ * Do not trust BSD style symlinks either.
+ */
+ if ((sb.st_mode & S_IFMT) == S_IFLNK)
+ return(0);
+
+#ifdef VIOCIGETCELL
+ /*
+ * This is the VIOCIGETCELL ioctl, which takes an fd, not
+ * a path name. If it succeeds, then the file is in AFS.
+ *
+ * On failure, ENOTTY indicates that the file was not in
+ * AFS; all other errors are pessimistically assumed to be
+ * a temporary AFS error.
+ */
+ vdata.in_size = 0;
+ vdata.out_size = sizeof(cellname);
+ vdata.out = cellname;
+ if (ioctl(handle, VIOCIGETCELL, (char *)&vdata) != -1)
+ return(0);
+ if (errno != ENOTTY)
+ return(-1);
+#endif /* VIOCIGETCELL */
+
+ /*
+ * Verify the file is not in NFS.
+ *
+ * Our current implementation and Sun OS 3.x use major device
+ * 255 for NFS files; Sun OS 4.x seems to use 130 (I have only
+ * determined this empirically -- DLC). Without a fstatfs()
+ * system call, this will have to do for now.
+ */
+ if (major(sb.st_dev) == 255 || major(sb.st_dev) == 130)
+ return(0);
+
+ return(1);
+}
+
+/*
+ * Companion routine for ensuring that a local file can be trusted. Compare
+ * various pieces of the stat information to make sure that the file can be
+ * trusted. Returns true for stat information which meets the criteria
+ * for being trustworthy. The main paranoia is to prevent a hard link to
+ * a root owned file. Since the link could be removed after the file is
+ * opened, a simply fstat() can not be relied upon. The two stat buffers
+ * for comparison should come from a stat() on the file name and a following
+ * fstat() on the open file. Some of the following checks are also an
+ * additional level of paranoia. Also, this test will fail (correctly) if
+ * either or both of the stat structures have all fields zeroed; typically
+ * due to a stat() failure.
+ */
+
+
+int stat_info_ok(sb1, sb2)
+struct stat *sb1, *sb2;
+{
+ return (sb1->st_ino == sb2->st_ino && /* Still the same file */
+ sb1->st_dev == sb2->st_dev && /* On the same device */
+ sb1->st_mode == sb2->st_mode && /* Perms (and type) same */
+ (sb1->st_mode & S_IFMT) == S_IFREG && /* Only allow reg files */
+ (sb1->st_mode & 077) == 0 && /* Owner only perms */
+ sb1->st_nlink == sb2->st_nlink && /* # hard links same... */
+ sb1->st_nlink == 1 && /* and only 1 */
+ sb1->st_uid == sb2->st_uid && /* owner and ... */
+ sb1->st_gid == sb2->st_gid && /* group unchanged */
+ sb1->st_mtime == sb2->st_mtime && /* Unmodified between stats */
+ sb1->st_ctime == sb2->st_ctime); /* Inode unchanged. Hopefully
+ a catch-all paranoid test */
+}
+
+#if MACH
+/*
+ * Twiddle symbolic/RFS link following on/off. This is a no-op in a non
+ * CMUCS/MACH environment. Also, the setmodes/getmodes interface is used
+ * mainly because it is simpler than using table(2) directly.
+ */
+#include <sys/table.h>
+
+int link_nofollow(on)
+int on;
+{
+ static int modes = -1;
+
+ if (modes == -1 && (modes = getmodes()) == -1)
+ return(-1);
+ if (on)
+ return(setmodes(modes | UMODE_NOFOLLOW));
+ return(setmodes(modes));
+}
+#else /* MACH */
+/*ARGSUSED*/
+int link_nofollow(on)
+int on;
+{
+ return(0);
+}
+#endif /* MACH */
diff --git a/usr.bin/sup/src/supmsg.c b/usr.bin/sup/src/supmsg.c
new file mode 100644
index 00000000000..21b49916f6a
--- /dev/null
+++ b/usr.bin/sup/src/supmsg.c
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ **********************************************************************
+ * HISTORY
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supmsg.c,v $
+ * Revision 1.1 1995/12/16 11:47:00 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1993/08/04 17:46:23 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:19 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 2.4 92/09/09 22:05:17 mrt
+ * Moved PFI definition under __STDC__ conditional since it
+ * is already defined in libc.h in this case.
+ * [92/09/01 mrt]
+ *
+ * Revision 2.3 92/08/11 12:08:12 mrt
+ * Added copyright
+ * [92/08/10 mrt]
+ * Brad's changes: Delinted, Incorporated updated variable
+ * argument list usage from old msgxfer.c
+ * [92/07/24 mrt]
+ *
+ * Revision 2.2 89/08/23 15:02:56 gm0w
+ * Created from separate message modules.
+ * [89/08/14 gm0w]
+ *
+ **********************************************************************
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <libc.h>
+#include <c.h>
+#include "sup.h"
+#define MSGSUBR
+#define MSGFILE
+#include "supmsg.h"
+
+/*
+ * signon message
+ */
+extern int pgmver; /* program version of partner */
+extern int pgmversion; /* my program version */
+extern char *scmver; /* scm version of partner */
+extern int fspid; /* process id of fileserver */
+
+int msgsignon ()
+{
+ register int x;
+
+ if (server) {
+ x = readmsg (MSGSIGNON);
+ if (x == SCMOK) x = readint (&protver);
+ if (x == SCMOK) x = readint (&pgmver);
+ if (x == SCMOK) x = readstring (&scmver);
+ if (x == SCMOK) x = readmend ();
+ } else {
+ x = writemsg (MSGSIGNON);
+ if (x == SCMOK) x = writeint (PROTOVERSION);
+ if (x == SCMOK) x = writeint (pgmversion);
+ if (x == SCMOK) x = writestring (scmversion);
+ if (x == SCMOK) x = writemend ();
+ }
+ return (x);
+}
+
+int msgsignonack ()
+{
+ register int x;
+
+ if (server) {
+ x = writemsg (MSGSIGNONACK);
+ if (x == SCMOK) x = writeint (PROTOVERSION);
+ if (x == SCMOK) x = writeint (pgmversion);
+ if (x == SCMOK) x = writestring (scmversion);
+ if (x == SCMOK) x = writeint (fspid);
+ if (x == SCMOK) x = writemend ();
+ } else {
+ x = readmsg (MSGSIGNONACK);
+ if (x == SCMOK) x = readint (&protver);
+ if (x == SCMOK) x = readint (&pgmver);
+ if (x == SCMOK) x = readstring (&scmver);
+ if (x == SCMOK) x = readint (&fspid);
+ if (x == SCMOK) x = readmend ();
+ }
+ return (x);
+}
+
+/*
+ * setup message
+ */
+extern int xpatch; /* setup crosspatch to a new client */
+extern char *xuser; /* user,group,acct for crosspatch */
+extern char *collname; /* base directory */
+extern char *basedir; /* base directory */
+extern int basedev; /* base directory device */
+extern int baseino; /* base directory inode */
+extern long lasttime; /* time of last upgrade */
+extern int listonly; /* only listing files, no data xfer */
+extern int newonly; /* only send new files */
+extern char *release; /* release name */
+extern int setupack; /* ack return value for setup */
+
+int msgsetup ()
+{
+ register int x;
+
+ if (server) {
+ x = readmsg (MSGSETUP);
+ if (x != SCMOK) return (x);
+ if (protver >= 7) {
+ x = readint (&xpatch);
+ if (x != SCMOK) return (x);
+ } else
+ xpatch = FALSE;
+ if (xpatch) {
+ x = readstring (&xuser);
+ if (x != SCMOK) return (x);
+ return (readmend ());
+ }
+ x = readstring (&collname);
+ if (x == SCMOK) x = readint ((int *)&lasttime);
+ if (x == SCMOK) x = readstring (&basedir);
+ if (x == SCMOK) x = readint (&basedev);
+ if (x == SCMOK) x = readint (&baseino);
+ if (x == SCMOK) x = readint (&listonly);
+ if (x == SCMOK) x = readint (&newonly);
+ if (x == SCMOK)
+ if (protver < 6)
+ release = (char *)NULL;
+ else
+ x = readstring (&release);
+ if (x == SCMOK) x = readmend ();
+ } else {
+ x = writemsg (MSGSETUP);
+ if (x != SCMOK) return (x);
+ if (protver >= 7) {
+ x = writeint (xpatch);
+ if (x != SCMOK) return (x);
+ }
+ if (xpatch) {
+ x = writestring (xuser);
+ if (x != SCMOK) return (x);
+ return (writemend ());
+ }
+ if (x == SCMOK) x = writestring (collname);
+ if (x == SCMOK) x = writeint ((int)lasttime);
+ if (x == SCMOK) x = writestring (basedir);
+ if (x == SCMOK) x = writeint (basedev);
+ if (x == SCMOK) x = writeint (baseino);
+ if (x == SCMOK) x = writeint (listonly);
+ if (x == SCMOK) x = writeint (newonly);
+ if (x == SCMOK && protver >= 6) x = writestring (release);
+ if (x == SCMOK) x = writemend ();
+ }
+ return (x);
+}
+
+int msgsetupack ()
+{
+ if (server)
+ return (writemint (MSGSETUPACK,setupack));
+ return (readmint (MSGSETUPACK,&setupack));
+}
+
+/*
+ * crypt test message
+ */
+extern char *crypttest; /* encryption test string */
+
+int msgcrypt ()
+{
+ if (server)
+ return (readmstr (MSGCRYPT,&crypttest));
+ return (writemstr (MSGCRYPT,crypttest));
+}
+
+int msgcryptok ()
+{
+ if (server)
+ return (writemnull (MSGCRYPTOK));
+ return (readmnull (MSGCRYPTOK));
+}
+
+/*
+ * login message
+ */
+extern char *logcrypt; /* login encryption test */
+extern char *loguser; /* login username */
+extern char *logpswd; /* password for login */
+extern int logack; /* login ack status */
+extern char *logerror; /* error from login */
+
+int msglogin ()
+{
+ register int x;
+ if (server) {
+ x = readmsg (MSGLOGIN);
+ if (x == SCMOK) x = readstring (&logcrypt);
+ if (x == SCMOK) x = readstring (&loguser);
+ if (x == SCMOK) x = readstring (&logpswd);
+ if (x == SCMOK) x = readmend ();
+ } else {
+ x = writemsg (MSGLOGIN);
+ if (x == SCMOK) x = writestring (logcrypt);
+ if (x == SCMOK) x = writestring (loguser);
+ if (x == SCMOK) x = writestring (logpswd);
+ if (x == SCMOK) x = writemend ();
+ }
+ return (x);
+}
+
+int msglogack ()
+{
+ register int x;
+ if (server) {
+ x = writemsg (MSGLOGACK);
+ if (x == SCMOK) x = writeint (logack);
+ if (x == SCMOK) x = writestring (logerror);
+ if (x == SCMOK) x = writemend ();
+ } else {
+ x = readmsg (MSGLOGACK);
+ if (x == SCMOK) x = readint (&logack);
+ if (x == SCMOK) x = readstring (&logerror);
+ if (x == SCMOK) x = readmend ();
+ }
+ return (x);
+}
+
+/*
+ * refuse list message
+ */
+extern TREE *refuseT; /* tree of files to refuse */
+
+static int refuseone (t)
+register TREE *t;
+{
+ return (writestring (t->Tname));
+}
+
+int msgrefuse ()
+{
+ register int x;
+ if (server) {
+ char *name;
+ x = readmsg (MSGREFUSE);
+ if (x == SCMOK) x = readstring (&name);
+ while (x == SCMOK) {
+ if (name == NULL) break;
+ (void) Tinsert (&refuseT,name,FALSE);
+ free (name);
+ x = readstring (&name);
+ }
+ if (x == SCMOK) x = readmend ();
+ } else {
+ x = writemsg (MSGREFUSE);
+ if (x == SCMOK) x = Tprocess (refuseT,refuseone);
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ if (x == SCMOK) x = writemend ();
+ }
+ return (x);
+}
+
+/*
+ * list files message
+ */
+extern TREE *listT; /* tree of files to list */
+extern long scantime; /* time that collection was scanned */
+
+static int listone (t)
+register TREE *t;
+{
+ register int x;
+
+ x = writestring (t->Tname);
+ if (x == SCMOK) x = writeint ((int)t->Tmode);
+ if (x == SCMOK) x = writeint ((int)t->Tflags);
+ if (x == SCMOK) x = writeint (t->Tmtime);
+ return (x);
+}
+
+int msglist ()
+{
+ register int x;
+ if (server) {
+ x = writemsg (MSGLIST);
+ if (x == SCMOK) x = Tprocess (listT,listone);
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ 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;
+ x = readstring (&name);
+ }
+ if (x == SCMOK) x = readint ((int *)&scantime);
+ if (x == SCMOK) x = readmend ();
+ }
+ return (x);
+}
+
+/*
+ * files needed message
+ */
+extern TREE *needT; /* tree of files to need */
+
+static int needone (t)
+register TREE *t;
+{
+ register int x;
+ x = writestring (t->Tname);
+ if (x == SCMOK) x = writeint ((t->Tflags&FUPDATE) != 0);
+ return (x);
+}
+
+int msgneed ()
+{
+ register int x;
+ if (server) {
+ char *name;
+ int update;
+ register TREE *t;
+ x = readmsg (MSGNEED);
+ if (x == SCMOK) x = readstring (&name);
+ while (x == SCMOK) {
+ if (name == NULL) break;
+ x = readint (&update);
+ if (x != SCMOK) break;
+ t = Tinsert (&needT,name,TRUE);
+ free (name);
+ if (update) t->Tflags |= FUPDATE;
+ x = readstring (&name);
+ }
+ if (x == SCMOK) x = readmend ();
+ } else {
+ x = writemsg (MSGNEED);
+ if (x == SCMOK) x = Tprocess (needT,needone);
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ if (x == SCMOK) x = writemend ();
+ }
+ return (x);
+}
+
+/*
+ * files denied message
+ */
+extern TREE *denyT; /* tree of files to deny */
+
+static int denyone (t)
+register TREE *t;
+{
+ return (writestring (t->Tname));
+}
+
+int msgdeny ()
+{
+ register int x;
+ if (server) {
+ x = writemsg (MSGDENY);
+ if (x == SCMOK) x = Tprocess (denyT,denyone);
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ if (x == SCMOK) x = writemend ();
+ } else {
+ char *name;
+ x = readmsg (MSGDENY);
+ if (x == SCMOK) x = readstring (&name);
+ while (x == SCMOK) {
+ if (name == NULL) break;
+ (void) Tinsert (&denyT,name,FALSE);
+ free (name);
+ x = readstring (&name);
+ }
+ if (x == SCMOK) x = readmend ();
+ }
+ return (x);
+}
+
+/*
+ * send file message
+ */
+int msgsend ()
+{
+ if (server)
+ return (readmnull (MSGSEND));
+ return (writemnull (MSGSEND));
+}
+
+/*
+ * receive file message
+ */
+extern TREE *upgradeT; /* pointer to file being upgraded */
+
+static int writeone (t)
+register TREE *t;
+{
+ return (writestring (t->Tname));
+}
+
+
+#if __STDC__
+int msgrecv (PFI xferfile,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+int msgrecv (va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ typedef int (*PFI)();
+ PFI xferfile;
+#endif
+ va_list args;
+ register int x;
+ register TREE *t = upgradeT;
+#if __STDC__
+ va_start(args,xferfile);
+#else
+ va_start(args);
+ xferfile = va_arg(args, PFI);
+#endif
+ if (server) {
+ x = writemsg (MSGRECV);
+ if (t == NULL) {
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ if (x == SCMOK) x = writemend ();
+ return (x);
+ }
+ if (x == SCMOK) x = writestring (t->Tname);
+ if (x == SCMOK) x = writeint (t->Tmode);
+ if (t->Tmode == 0) {
+ if (x == SCMOK) x = writemend ();
+ return (x);
+ }
+ if (x == SCMOK) x = writeint (t->Tflags);
+ if (x == SCMOK) x = writestring (t->Tuser);
+ if (x == SCMOK) x = writestring (t->Tgroup);
+ if (x == SCMOK) x = writeint (t->Tmtime);
+ if (x == SCMOK) x = Tprocess (t->Tlink,writeone);
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ if (x == SCMOK) x = Tprocess (t->Texec,writeone);
+ if (x == SCMOK) x = writestring ((char *)NULL);
+ if (x == SCMOK) x = (*xferfile) (t,args);
+ if (x == SCMOK) x = writemend ();
+ } else {
+ char *linkname,*execcmd;
+ if (t == NULL) return (SCMERR);
+ x = readmsg (MSGRECV);
+ if (x == SCMOK) x = readstring (&t->Tname);
+ if (x == SCMOK && t->Tname == NULL) {
+ x = readmend ();
+ if (x == SCMOK) x = (*xferfile) (NULL,args);
+ return (x);
+ }
+ if (x == SCMOK) x = readint (&t->Tmode);
+ if (t->Tmode == 0) {
+ x = readmend ();
+ if (x == SCMOK) x = (*xferfile) (t,args);
+ return (x);
+ }
+ if (x == SCMOK) x = readint (&t->Tflags);
+ if (x == SCMOK) x = readstring (&t->Tuser);
+ if (x == SCMOK) x = readstring (&t->Tgroup);
+ if (x == SCMOK) x = readint (&t->Tmtime);
+ t->Tlink = NULL;
+ if (x == SCMOK) x = readstring (&linkname);
+ while (x == SCMOK) {
+ if (linkname == NULL) break;
+ (void) Tinsert (&t->Tlink,linkname,FALSE);
+ free (linkname);
+ x = readstring (&linkname);
+ }
+ t->Texec = NULL;
+ if (x == SCMOK) x = readstring (&execcmd);
+ while (x == SCMOK) {
+ if (execcmd == NULL) break;
+ (void) Tinsert (&t->Texec,execcmd,FALSE);
+ free (execcmd);
+ x = readstring (&execcmd);
+ }
+ if (x == SCMOK) x = (*xferfile) (t,args);
+ if (x == SCMOK) x = readmend ();
+ }
+ va_end(args);
+ return (x);
+}
+
+/*
+ * protocol done message
+ */
+extern int doneack;
+extern char *donereason;
+
+int msgdone ()
+{
+ register int x;
+
+ if (protver < 6) {
+ printf ("Error, msgdone should not have been called.");
+ return (SCMERR);
+ }
+ if (server) {
+ x = readmsg (MSGDONE);
+ if (x == SCMOK) x = readint (&doneack);
+ if (x == SCMOK) x = readstring (&donereason);
+ if (x == SCMOK) x = readmend ();
+ } else {
+ x = writemsg (MSGDONE);
+ if (x == SCMOK) x = writeint (doneack);
+ if (x == SCMOK) x = writestring (donereason);
+ if (x == SCMOK) x = writemend ();
+ }
+ return (x);
+}
+
+/*
+ * go away message
+ */
+extern char *goawayreason; /* reason for goaway */
+
+int msggoaway ()
+{
+ return (writemstr (MSGGOAWAY,goawayreason));
+}
+
+/*
+ * cross-patch protocol message
+ */
+extern int xargc; /* arg count for crosspatch */
+extern char **xargv; /* arg array for crosspatch */
+
+int msgxpatch ()
+{
+ register int x;
+ register int i;
+
+ if (server) {
+ x = readmsg (MSGXPATCH);
+ if (x != SCMOK) return (x);
+ x = readint (&xargc);
+ if (x != SCMOK) return (x);
+ xargc += 2;
+ xargv = (char **)calloc (sizeof (char *),(unsigned)xargc+1);
+ if (xargv == NULL)
+ return (SCMERR);
+ for (i = 2; i < xargc; i++) {
+ x = readstring (&xargv[i]);
+ if (x != SCMOK) return (x);
+ }
+ x = readmend ();
+ } else {
+ x = writemsg (MSGXPATCH);
+ if (x != SCMOK) return (x);
+ x = writeint (xargc);
+ if (x != SCMOK) return (x);
+ for (i = 0; i < xargc; i++) {
+ x = writestring (xargv[i]);
+ if (x != SCMOK) return (x);
+ }
+ x = writemend ();
+ }
+ return (x);
+}
+
+/*
+ * Compression check protocol message
+ */
+extern int docompress; /* Compress file before sending? */
+
+int msgcompress ()
+{
+ if (server)
+ return (readmint (MSGCOMPRESS,&docompress));
+ return (writemint (MSGCOMPRESS, docompress));
+}
diff --git a/usr.bin/sup/src/supmsg.h b/usr.bin/sup/src/supmsg.h
new file mode 100644
index 00000000000..d4da8531d36
--- /dev/null
+++ b/usr.bin/sup/src/supmsg.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * supmsg.h - global definitions/variables used in msg routines.
+ *
+ **********************************************************************
+ * HISTORY
+ *
+ * 7-July-93 Nate Williams at Montana State University
+ * Modified SUP to use gzip based compression when sending files
+ * across the network to save BandWidth
+ *
+ * $Log: supmsg.h,v $
+ * Revision 1.1 1995/12/16 11:47:01 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.2 1993/08/04 17:46:24 brezak
+ * Changes from nate for gzip'ed sup
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:19 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.7 92/08/11 12:08:20 mrt
+ * Added copyright.
+ * [92/08/10 mrt]
+ *
+ * Revision 1.6 89/08/23 14:56:42 gm0w
+ * Changed MSGF to MSG constants.
+ * [89/08/23 gm0w]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added crosspatch support. Removed nameserver support.
+ *
+ * 29-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added "release" support.
+ *
+ * 27-May-87 Doug Philips (dwp) at Carnegie-Mellon University
+ * Added MSGFDONE and subvalues, added doneack and donereason.
+ *
+ * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added changes to make lint happy.
+ *
+ * 04-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed hostname to hostT to support multiple repositories per
+ * collection. Added FSETUPBUSY to tell clients that server is
+ * currently busy.
+ *
+ * 19-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Created.
+ *
+ **********************************************************************
+ */
+
+/* Special messages reserved for SCM */
+#define MSGGOAWAY (-1) /* see scm.c */
+
+/* Message types -- see supmsg.c */
+#define MSGSIGNON (101)
+#define MSGSIGNONACK (102)
+#define MSGSETUP (103)
+#define MSGSETUPACK (104)
+#define MSGLOGIN (105)
+#define MSGLOGACK (106)
+#define MSGCRYPT (107)
+#define MSGCRYPTOK (108)
+#define MSGREFUSE (109)
+#define MSGLIST (110)
+#define MSGNEED (111)
+#define MSGDENY (112)
+#define MSGSEND (113)
+#define MSGRECV (114)
+#define MSGDONE (115)
+#define MSGXPATCH (117)
+#define MSGCOMPRESS (118)
+
+/* MSGSETUPACK data codes - setupack */
+#define FSETUPOK (999)
+#define FSETUPHOST (998)
+#define FSETUPSAME (997)
+#define FSETUPOLD (996)
+#define FSETUPBUSY (995)
+#define FSETUPRELEASE (994)
+
+/* MSGLOGACK data codes - loginack */
+#define FLOGOK (989)
+#define FLOGNG (988)
+
+/* MSGDONE data codes - doneack */
+#define FDONESUCCESS (979)
+#define FDONEDONTLOG (978)
+#define FDONESRVERROR (977)
+#define FDONEUSRERROR (976)
+#define FDONEGOAWAY (975)
+
+#ifdef MSGSUBR
+
+/* used in all msg routines */
+extern int server; /* true if we are the server */
+extern int protver; /* protocol version of partner */
+
+#else MSGSUBR
+
+#ifdef MSGFILE
+#define EXTERN
+#else MSGFILE
+#define EXTERN extern
+#endif MSGFILE
+
+/* used in all msg routines */
+EXTERN int server; /* true if we are the server */
+
+/* msggoaway */
+EXTERN char *goawayreason; /* reason for goaway */
+
+/* msgsignon */
+EXTERN int pgmversion; /* version of this program */
+EXTERN int protver; /* protocol version of partner */
+EXTERN int pgmver; /* program version of partner */
+EXTERN char *scmver; /* scm version of partner */
+EXTERN int fspid; /* process id of fileserver */
+
+/* msgsetup */
+EXTERN int xpatch; /* setup crosspatch to a new client */
+EXTERN char *xuser; /* user for crosspatch */
+EXTERN char *collname; /* collection name */
+EXTERN char *basedir; /* base directory */
+EXTERN int basedev; /* base directory device */
+EXTERN int baseino; /* base directory inode */
+EXTERN long lasttime; /* time of last upgrade */
+EXTERN int listonly; /* only listing files, no data xfer */
+EXTERN int newonly; /* only send new files */
+EXTERN char *release; /* release name */
+EXTERN int setupack; /* ack return value for setup */
+
+/* msgcrypt */
+EXTERN char *crypttest; /* encryption test string */
+
+/* msglogin */
+EXTERN char *logcrypt; /* login encryption test */
+EXTERN char *loguser; /* login username */
+EXTERN char *logpswd; /* password for login */
+EXTERN int logack; /* login ack status */
+EXTERN char *logerror; /* error string from oklogin */
+
+/* msgxpatch */
+EXTERN int xargc; /* arg count for crosspatch */
+EXTERN char **xargv; /* arg array for crosspatch */
+
+/* msgrefuse */
+EXTERN TREE *refuseT; /* tree of files to refuse */
+
+/* msglist */
+EXTERN TREE *listT; /* tree of files to list */
+EXTERN long scantime; /* time that collection was scanned */
+
+/* msgneed */
+EXTERN TREE *needT; /* tree of files to need */
+
+/* msgdeny */
+EXTERN TREE *denyT; /* tree of files to deny */
+
+/* msgrecv */
+/* msgsend */
+EXTERN TREE *upgradeT; /* pointer to file being upgraded */
+
+/* msgdone */
+EXTERN int doneack; /* done ack status */
+EXTERN char *donereason; /* set if indicated by doneack */
+
+#undef EXTERN
+
+#endif MSGSUBR
diff --git a/usr.bin/sup/src/supscan.c b/usr.bin/sup/src/supscan.c
new file mode 100644
index 00000000000..1e6e8088373
--- /dev/null
+++ b/usr.bin/sup/src/supscan.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 1992 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 Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * supscan -- SUP Scan File Builder
+ *
+ * Usage: supscan [ -v ] collection [ basedir ]
+ * supscan [ -v ] -f dirfile
+ * supscan [ -v ] -s
+ * -f "file" -- use dirfile instead of system coll.dir
+ * -s "system" -- perform scan for system supfile
+ * -v "verbose" -- print messages as you go
+ * collection -- name of the desired collection if not -s
+ * basedir -- name of the base directory, if not
+ * the default or recorded in coll.dir
+ * dirfile -- name of replacement for system coll.dir.
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: supscan.c,v $
+ * Revision 1.1 1995/12/16 11:47:01 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:19 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 1.14 92/08/11 12:08:30 mrt
+ * Picked up Brad's deliniting and variable argument changes
+ * [92/08/10 mrt]
+ *
+ * Revision 1.13 92/02/08 18:04:44 dlc
+ * Once again revised localhost(). Do not use gethostbyname() at
+ * all, but assume that the host names in the coll.host file are at
+ * least a prefix of the fully qualified name. Modcoll (and related
+ * scripts) will maintain this fact.
+ * [92/02/08 dlc]
+ *
+ * Revision 1.12 91/08/17 23:35:31 dlc
+ * Changes to localhost() function:
+ * - Use host name in kernel for local host name; assume it is
+ * fully qualified.
+ * - If gethostbyname() of host to see if we are the repository
+ * fails, with TRY_AGAIN or NO_RECOVERY, then use the "host"
+ * parameter. Print a diagnostic in this case.
+ * [91/08/17 dlc]
+ *
+ * Revision 1.11 90/04/04 10:53:01 dlc
+ * Changed localhost to retry getting the local host name 4 times with
+ * 30 second sleep intervals before aborting; after 4 tries, things are
+ * probably too messed up for the supscan to do anything useful
+ * [90/04/04 dlc]
+ *
+ * Revision 1.10 89/08/03 19:49:33 mja
+ * Updated to use v*printf() in place of _doprnt().
+ * [89/04/19 mja]
+ *
+ * Revision 1.9 89/06/18 14:41:37 gm0w
+ * Fixed up some notify messages of errors to use "SUP:" prefix.
+ * [89/06/18 gm0w]
+ *
+ * 13-May-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed goaway to longjmp back to top-level to scan next
+ * collection. [V7.6]
+ *
+ * 19-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added -f <filename> switch to scan all (or part) of the
+ * collections in a file of collection/base-directory pairs.
+ * [V7.5]
+ *
+ * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Removed nameserver support (which means to use a new
+ * datafile).
+ *
+ * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Use case-insensitive hostname comparison.
+ *
+ * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added code for "release" support. [V6.4]
+ *
+ * 05-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Changed collection setup errors to be non-fatal. [V5.3]
+ *
+ * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Moved most of the scanning code to scan.c. [V4.2]
+ *
+ * 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Added "-s" option.
+ *
+ * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
+ * Merged 4.1 and 4.2 versions together.
+ *
+ * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University
+ * Created for 4.2 BSD.
+ *
+ **********************************************************************
+ */
+
+#include <libc.h>
+#include <c.h>
+#include <netdb.h>
+#include <setjmp.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <sys/time.h>
+#include <sys/types.h>
+#include "sup.h"
+
+#ifdef lint
+/*VARARGS1*//*ARGSUSED*/
+static void quit(status) {};
+#endif /* lint */
+
+#define PGMVERSION 6
+
+/*******************************************
+ *** D A T A S T R U C T U R E S ***
+ *******************************************/
+
+struct collstruct { /* one per collection to be upgraded */
+ char *Cname; /* collection name */
+ char *Cbase; /* local base directory */
+ char *Cprefix; /* local collection pathname prefix */
+ struct collstruct *Cnext; /* next collection */
+};
+typedef struct collstruct COLLECTION;
+
+/*********************************************
+ *** G L O B A L V A R I A B L E S ***
+ *********************************************/
+
+int trace; /* -v flag */
+
+COLLECTION *firstC; /* collection list pointer */
+char *collname; /* collection name */
+char *basedir; /* base directory name */
+char *prefix; /* collection pathname prefix */
+long lasttime = 0; /* time of last upgrade */
+long scantime; /* time of this scan */
+int newonly = FALSE; /* new files only */
+jmp_buf sjbuf; /* jump location for errors */
+
+TREELIST *listTL; /* list of all files specified by <coll>.list */
+TREE *listT; /* final list of files in collection */
+TREE *refuseT = NULL; /* list of all files specified by <coll>.list */
+
+long time ();
+
+/*************************************
+ *** M A I N R O U T I N E ***
+ *************************************/
+
+main (argc,argv)
+int argc;
+char **argv;
+{
+ register COLLECTION *c;
+
+ init (argc,argv); /* process arguments */
+ for (c = firstC; c; c = c->Cnext) {
+ collname = c->Cname;
+ basedir = c->Cbase;
+ prefix = c->Cprefix;
+ (void) chdir (basedir);
+ scantime = time ((long *)NULL);
+ printf ("SUP Scan for %s starting at %s",collname,
+ ctime (&scantime));
+ (void) fflush (stdout);
+ if (!setjmp (sjbuf)) {
+ makescanlists (); /* record names in scan files */
+ scantime = time ((long *)NULL);
+ printf ("SUP Scan for %s completed at %s",collname,
+ ctime (&scantime));
+ } else
+ printf ("SUP: Scan for %s aborted at %s",collname,
+ ctime (&scantime));
+ (void) fflush (stdout);
+ }
+ while (c = firstC) {
+ firstC = firstC->Cnext;
+ free (c->Cname);
+ free (c->Cbase);
+ if (c->Cprefix) free (c->Cprefix);
+ free ((char *)c);
+ }
+ exit (0);
+}
+
+/*****************************************
+ *** I N I T I A L I Z A T I O N ***
+ *****************************************/
+
+usage ()
+{
+ fprintf (stderr,"Usage: supscan [ -v ] collection [ basedir ]\n");
+ fprintf (stderr," supscan [ -v ] -f dirfile\n");
+ fprintf (stderr," supscan [ -v ] -s\n");
+ exit (1);
+}
+
+init (argc,argv)
+int argc;
+char **argv;
+{
+ char buf[STRINGLENGTH],fbuf[STRINGLENGTH],*p,*q;
+ FILE *f;
+ COLLECTION **c, *getcoll();
+ int fflag,sflag;
+ char *filename;
+
+ trace = FALSE;
+ fflag = FALSE;
+ sflag = FALSE;
+ while (argc > 1 && argv[1][0] == '-') {
+ switch (argv[1][1]) {
+ case 'f':
+ fflag = TRUE;
+ if (argc == 2)
+ usage ();
+ --argc;
+ argv++;
+ filename = argv[1];
+ break;
+ case 'v':
+ trace = TRUE;
+ break;
+ case 's':
+ sflag = TRUE;
+ break;
+ default:
+ fprintf (stderr,"supscan: Invalid flag %s ignored\n",argv[1]);
+ (void) fflush (stderr);
+ }
+ --argc;
+ argv++;
+ }
+ if (!fflag) {
+ (void) sprintf (fbuf,FILEDIRS,DEFDIR);
+ filename = fbuf;
+ }
+ if (sflag) {
+ if (argc != 1)
+ usage ();
+ firstC = NULL;
+ c = &firstC;
+ (void) sprintf (buf,FILEHOSTS,DEFDIR);
+ if ((f = fopen (buf,"r")) == NULL)
+ quit (1,"supscan: Unable to open %s\n",buf);
+ while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ collname = nxtarg (&p," \t=");
+ p = skipover (p," \t=");
+ if (!localhost (p)) continue;
+ *c = getcoll(filename,salloc (collname),
+ (char *)NULL);
+ if (*c) c = &((*c)->Cnext);
+ }
+ (void) fclose (f);
+ return;
+ }
+ if (argc < 2 && fflag) {
+ firstC = NULL;
+ c = &firstC;
+ if ((f = fopen (filename,"r")) == NULL)
+ quit (1,"supscan: Unable to open %s\n",filename);
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t=");
+ p = skipover (p," \t=");
+ *c = getcoll(filename,salloc (q),salloc (p));
+ if (*c) c = &((*c)->Cnext);
+ }
+ (void) fclose (f);
+ return;
+ }
+ if (argc < 2 || argc > 3)
+ usage ();
+ firstC = getcoll(filename,salloc (argv[1]),
+ argc > 2 ? salloc (argv[2]) : (char *)NULL);
+}
+
+COLLECTION *
+getcoll(filename, collname, basedir)
+register char *filename,*collname,*basedir;
+{
+ char buf[STRINGLENGTH],*p,*q;
+ FILE *f;
+ COLLECTION *c;
+
+ if (basedir == NULL) {
+ if (f = fopen (filename,"r")) {
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ q = nxtarg (&p," \t=");
+ if (strcmp (q,collname) == 0) {
+ p = skipover (p," \t=");
+ basedir = salloc (p);
+ break;
+ }
+ }
+ (void) fclose (f);
+ }
+ if (basedir == NULL) {
+ (void) sprintf (buf,FILEBASEDEFAULT,collname);
+ basedir = salloc (buf);
+ }
+ }
+ if (chdir(basedir) < 0) {
+ fprintf (stderr,"supscan: Can't chdir to base directory %s for %s\n",
+ basedir,collname);
+ return (NULL);
+ }
+ prefix = NULL;
+ (void) sprintf (buf,FILEPREFIX,collname);
+ if (f = fopen (buf,"r")) {
+ while (p = fgets (buf,STRINGLENGTH,f)) {
+ q = index (p,'\n');
+ if (q) *q = 0;
+ if (index ("#;:",*p)) continue;
+ prefix = salloc (p);
+ if (chdir(prefix) < 0) {
+ fprintf (stderr,"supscan: can't chdir to %s from base directory %s for %s\n",
+ prefix,basedir,collname);
+ return (NULL);
+ }
+ break;
+ }
+ (void) fclose (f);
+ }
+ if ((c = (COLLECTION *) malloc (sizeof(COLLECTION))) == NULL)
+ quit (1,"supscan: can't malloc collection structure\n");
+ c->Cname = collname;
+ c->Cbase = basedir;
+ c->Cprefix = prefix;
+ c->Cnext = NULL;
+ return (c);
+}
+#if __STDC__
+goaway (char *fmt,...)
+#else
+/*VARARGS*//*ARGSUSED*/
+goaway (va_alist)
+va_dcl
+#endif
+{
+#if !__STDC__
+ char *fmt;
+#endif
+ va_list ap;
+
+#if __STDC__
+ va_start(ap,fmt);
+#else
+ va_start(ap);
+ fmt = va_arg(ap,char *);
+#endif
+
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void) putc ('\n',stderr);
+ (void) fflush (stderr);
+ longjmp (sjbuf,TRUE);
+}
+
+int localhost (host)
+register char *host;
+{
+ static char myhost[STRINGLENGTH];
+ static int myhostlen;
+ register int hostlen;
+
+ if (*myhost == '\0') {
+ /*
+ * We assume that the host name in the kernel is the
+ * fully qualified form.
+ */
+ if (gethostname (myhost,sizeof (myhost)) < 0) {
+ quit (1,"supscan: can't get kernel host name\n");
+ }
+ myhostlen = strlen(myhost);
+ }
+
+ /*
+ * Here, we assume that the 'host' parameter from the
+ * coll.host file is at least a prefix of the fully qualified
+ * host name of some machine. This will be true when modcoll(8)
+ * (and related scripts) maintain the relevant files, but if
+ * a person makes a manual change, problems could result. In
+ * particular, if a nicname, such as "Y" for "GANDALF.CS.CMU.EDU"
+ * is present in the coll.host file, things will not work as
+ * expected.
+ */
+
+ hostlen = strlen(host);
+
+ return(strncasecmp (myhost,
+ host,
+ hostlen < myhostlen ? hostlen : myhostlen) == 0);
+}
diff --git a/usr.bin/sup/src/supservers.8 b/usr.bin/sup/src/supservers.8
new file mode 100644
index 00000000000..53d2e9f8a85
--- /dev/null
+++ b/usr.bin/sup/src/supservers.8
@@ -0,0 +1,241 @@
+.\" Copyright (c) 1992 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 Mellon
+.\" the rights to redistribute these changes.
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.\" HISTORY
+.\" $Log: supservers.8,v $
+.\" Revision 1.1 1995/12/16 11:47:02 deraadt
+.\" add sup to the tree
+.\"
+.\" Revision 1.1.1.1 1993/05/21 14:52:16 cgd
+.\" initial import of CMU's SUP to NetBSD
+.\"
+.\" Revision 1.3 92/08/11 12:08:50 mrt
+.\" Documented -C switch
+.\" [92/08/11 mrt]
+.\"
+.TH SUPSERVERS 8 1/16/86
+.CM 1
+.SH "NAME"
+supfilesrv, supscan \- sup server processes
+.SH "SYNOPSIS"
+supfilesrv
+[
+.I
+-l
+] [
+.I
+-q
+] [
+.I
+-N
+] [
+.I
+-P
+] [
+.I -C MaxChildren
+]
+.br
+supscan [
+.I
+-v
+] [
+.I
+-s
+] [
+.I
+collection
+] [
+.I
+basedir
+]
+.SH "DESCRIPTION"
+.I
+Supfilesrv
+is the server processes used to interact with
+.I
+sup
+client processes via the IP/TCP network protocol.
+This server
+normally is expected to be running on server machines at all times.
+Each machine with files of interest to users on other machines is
+expected to be a file server and should run
+.I
+supfilesrv.
+
+A file server machine will service requests for both "private" and
+"system" file collections.
+No special action is necessary to support
+private collections, as the client user is expected to supply all
+necessary information.
+For system collections, if the base directory
+is not the default (see FILES below), an entry must be put into
+the directory list file; this entry is a single text line containing
+the name of the collection, one or more spaces, and the name of the
+base directory for that collection.
+
+Each collection should have
+an entry in the host list file; this entry is a single text line
+containing the name of the collection, one or more spaces, and
+the name of the host machine acting as file server for that collection.
+
+Details of setting up a file collection for the file server are
+described in the manual entry for
+.I
+sup(1).
+
+.I
+Supfilesrv
+generally runs as a network server process that listens for connections,
+and for each connection (double-)forks a process to handle the interaction
+with the client.
+However, with the -l flag, no forking will take place:
+the server will listen for a network connection, handle it, and exit.
+This is useful for debugging the servers in "live" mode rather than as
+daemons.
+
+For debugging purposes, the -P "debugging ports" flag can be used.
+It will cause the selection of an alternate, non-privileged set of
+TCP ports instead of the usual ports, which are reserved for the
+active server processes. The -N "network debugging" flag can be used
+to produce voluminous messages describing the network communication
+progress and status. The more -N switches that you use the more output
+you get. Use 3 (separated by spaces: -N -N -N) to get a complete record
+of all network messages. Log messages are printed by
+.I syslog
+on
+.I daemon.log .
+To suppress
+log messages, the -q "quiet" flag can be used.
+
+
+Normally the
+.I supfilesrv
+will only respond to 3 requests simultaneously, forking a child
+process for each client. If it gets additional requests it will respond
+with the error FSSETUPBUSY. The -C MaxChildren switch can be used
+to increase (or decrease) this number.
+
+.SH "SUPSCAN"
+It is possible to pre-compile a list of the files in a collection
+to make
+.I
+supfilesrv
+service that collection much faster. This can be done by running
+.I
+supscan
+on the desired collection on the repository machine. This produces a
+list of all the files in the collection at the time of the
+.I
+supscan;
+subsequent upgrades will be based on this list of files rather than
+actually scanning the disk at the time of the upgrade. Of course,
+the upgrade will consequently bring the client machine up to the status
+of the repository machine as of the time of the
+.I
+supscan
+rather than as of the time of the upgrade; hence, if
+.I
+supscan
+is used, it should be run periodically on the
+collection.
+This facility is useful for extremely large file collections
+that are upgraded many times per day, such as the CMU UNIX system
+software. The "verbose" flag
+.I
+-v
+will cause
+.I
+supscan
+to produce output messages as it scans the files in the collection.
+The "system" flag
+.I
+-s
+will cause
+.I
+supscan
+to scan all system collections residing on the current host.
+The
+.I
+basedir
+parameter must be specified if the collection is a private
+collection whose base directory is not the default.
+.SH "FILES"
+.TP
+/usr
+default base directory for a collection
+.TP
+/usr/cs/lib/supfiles/coll.dir
+directory list file for file server
+.TP
+/usr/cs/lib/supfiles/coll.host
+host list file for system sups.
+.TP
+<base-directory>/sup/<collection>/*
+files used by file server (see
+.I
+sup(1))
+.TP
+<base-directory>/sup/<collection>/list
+list file used by
+.I
+supscan
+to create file list
+.TP
+<base-directory>/sup/<collection>/scan
+file list created by
+.I
+supscan
+from list file
+.i0
+.DT
+.PP
+.SH "SEE ALSO"
+sup(1)
+.br
+.I
+The SUP Software Upgrade Protocol,
+S.
+A.
+Shafer, CMU Computer Science Dept., 1985.
+.SH "DIAGNOSTICS"
+The file server places log messages on the
+standard and diagnostic output files.
+The process name and process
+id number generally accompany each message for diagnostic purposes.
+.SH "HISTORY"
+.TP
+31-July-92 Mary Thompson (mrt) at Carnegie Mellon University
+Removed references to supnameserver which has not existed for
+a long time. Update a few file names. Added -C switch.
+.TP
+21-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
+Updated documentation for 4.3; changed /usr/cmu to /usr/cs.
+.TP
+15-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University
+Updated documentation; -s switch to supscan.
+.TP
+23-May-85 Steven Shafer (sas) at Carnegie-Mellon University
+Supscan created and documented; also -N flag.
+.TP
+04-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University
+Created.
diff --git a/usr.bin/sup/src/sysent.h b/usr.bin/sup/src/sysent.h
new file mode 100644
index 00000000000..d513ea6c2f9
--- /dev/null
+++ b/usr.bin/sup/src/sysent.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+/*
+ **********************************************************************
+ * HISTORY
+ * $Log: sysent.h,v $
+ * Revision 1.1 1995/12/16 11:47:02 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:19 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 2.4 89/12/05 16:02:00 mrt
+ * Removed include of sys/features.h as it is no longer
+ * exported or needed.
+ * [89/12/05 mrt]
+ *
+ * Revision 2.3 89/01/20 15:44:24 gm0w
+ * Added externs to the non-STDC case for functions that do not
+ * have int return values.
+ * [88/12/17 gm0w]
+ *
+ * Revision 2.2 88/12/14 23:35:52 mja
+ * Created.
+ * [88/01/06 jjk]
+ *
+ **********************************************************************
+ */
+
+#ifndef _SYSENT_H_
+#define _SYSENT_H_ 1
+
+#if defined(__STDC__)
+#if 0
+#include <sys/types.h>
+#include <sys/time.h>
+extern int access(const char *, int);
+extern int acct(const char *);
+extern int brk(void *);
+extern int sbrk(int);
+extern int chdir(const char *);
+extern int chmod(const char *, int);
+extern int fchmod(int, int);
+extern int chown(const char *, int, int);
+extern int fchown(int, int, int);
+extern int chroot(const char *);
+extern int close(int);
+extern int creat(const char *, int);
+extern int dup(int);
+extern int dup2(int, int);
+extern int execve(const char *, const char **, const char **);
+extern void _exit(int);
+extern int fcntl(int, int, int);
+extern int flock(int, int);
+extern int fork(void);
+extern int fsync(int);
+extern int getdtablesize(void);
+extern gid_t getgid(void);
+extern gid_t getegid(void);
+extern int getgroups(int, int *);
+extern long gethostid(void);
+extern int sethostid(long);
+extern int gethostname(char *, int);
+extern int sethostname(const char *, int);
+extern int getpagesize(void);
+extern int getpgrp(int);
+extern int getpid(void);
+extern int getppid(void);
+extern uid_t getuid(void);
+extern uid_t geteuid(void);
+extern int ioctl(int, unsigned long, void *);
+extern int kill(int, int);
+extern int killpg(int, int);
+extern int link(const char *, const char *);
+extern off_t lseek(int, off_t, int);
+extern int mkdir(const char *, int);
+extern int mknod(const char *, int, int);
+extern int mount(const char *, const char *, int);
+extern int umount(const char *);
+extern int open(const char *, int, int);
+extern int pipe(int *);
+extern int profil(void *, int, int, int);
+extern int ptrace(int, int, int *, int);
+extern int quota(int, int, int, void *);
+extern int read(int, void *, int);
+extern int readlink(const char *, void *, int);
+extern int reboot(int);
+extern int rename(const char *, const char *);
+extern int rmdir(const char *);
+extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+extern int setgroups(int, int *);
+extern int setpgrp(int, int);
+extern int setquota(const char *, const char *);
+extern int setregid(gid_t, gid_t);
+extern int setreuid(uid_t, uid_t);
+extern int swapon(const char *);
+extern int symlink(const char *, const char *);
+extern void sync(void);
+extern int syscall(int, ...);
+extern int truncate(const char *, off_t);
+extern int ftruncate(int, off_t);
+extern int umask(int);
+extern int unlink(const char *);
+extern int vfork(void);
+extern void vhangup(void);
+extern int write(int, void *, int);
+
+#ifndef _VICEIOCTL
+#include <sys/viceioctl.h>
+#endif /* not _VICEIOCTL */
+extern int icreate(int, int, int, int, int, int);
+extern int iinc(int, int, long);
+extern int idec(int, int, long);
+extern int iopen(int, int, int);
+extern int iread(int, int, int, int, void *, int);
+extern int iwrite(int, int, int, int, void *, int);
+extern int pioctl(const char *, unsigned long, struct ViceIoctl *, int);
+extern int setpag(void);
+#endif
+#else defined(__STDC__)
+extern gid_t getgid();
+extern gid_t getegid();
+extern long gethostid();
+extern uid_t getuid();
+extern uid_t geteuid();
+extern off_t lseek();
+#endif /* __STDC__ */
+#endif /* not _SYSENT_H_ */
diff --git a/usr.bin/sup/src/time.h b/usr.bin/sup/src/time.h
new file mode 100644
index 00000000000..0b4ea542613
--- /dev/null
+++ b/usr.bin/sup/src/time.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement: ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)time.h 5.6 (Berkeley) 6/23/90
+ */
+/*
+ * HISTORY
+ * 20-Sep-90 Mary Thompson (mrt) at Carnegie-Mellon University
+ * Taken from 4.3-reno-source to get the new copyright, but
+ * removed the features that Mach is not supporting yet.
+ *
+ */
+
+#ifndef _TIME_H_
+#define _TIME_H_ 1
+
+struct tm {
+ int tm_sec; /* seconds after the minute [0-60] */
+ int tm_min; /* minutes after the hour [0-59] */
+ int tm_hour; /* hours since midnight [0-23] */
+ int tm_mday; /* day of the month [1-31] */
+ int tm_mon; /* months since January [0-11] */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* days since Sunday [0-6] */
+ int tm_yday; /* days since January 1 [0-365] */
+ int tm_isdst; /* Daylight Savings Time flag */
+ long tm_gmtoff; /* offset from CUT in seconds */
+ char *tm_zone; /* timezone abbreviation */
+};
+
+#if __STDC__ || c_plusplus
+extern struct tm *gmtime(const time_t *);
+extern struct tm *localtime(const time_t *);
+extern time_t mktime(const struct tm *);
+extern time_t time(time_t *);
+extern double difftime(const time_t, const time_t);
+extern char *asctime(const struct tm *);
+extern char *ctime(const time_t *);
+extern char *timezone(int , int);
+extern void tzset(void);
+extern void tzsetwall(void);
+#else
+extern struct tm *gmtime();
+extern struct tm *localtime();
+extern time_t mktime();
+extern time_t time();
+extern double difftime();
+extern char *asctime();
+extern char *ctime();
+extern char *timezone();
+extern void tzset();
+extern void tzsetwall();
+#endif
+
+#endif /* _TIME_H */
diff --git a/usr.bin/sup/src/vprintf.c b/usr.bin/sup/src/vprintf.c
new file mode 100644
index 00000000000..01280c21e94
--- /dev/null
+++ b/usr.bin/sup/src/vprintf.c
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+/*
+ * varargs versions of printf routines
+ *
+ **********************************************************************
+ * HISTORY
+ * $Log: vprintf.c,v $
+ * Revision 1.1 1995/12/16 11:47:03 deraadt
+ * add sup to the tree
+ *
+ * Revision 1.1.1.1 1993/05/21 14:52:19 cgd
+ * initial import of CMU's SUP to NetBSD
+ *
+ * Revision 2.5 89/09/08 18:15:55 mbj
+ * Use _doprnt() for the Multimax (an "old" architecture).
+ * [89/09/08 mbj]
+ *
+ * Revision 2.4 89/08/03 14:40:10 mja
+ * Add vsnprintf() routine.
+ * [89/07/12 mja]
+ *
+ * Terminate vsprintf() string with null byte.
+ * [89/04/21 mja]
+ *
+ * Change to use new hidden name for _doprnt on MIPS.
+ * [89/04/18 mja]
+ *
+ * Revision 2.3 89/06/10 14:13:43 gm0w
+ * Added putc of NULL byte to vsprintf.
+ * [89/06/10 gm0w]
+ *
+ * Revision 2.2 88/12/13 13:53:17 gm0w
+ * From Brad White.
+ * [88/12/13 gm0w]
+ ************************************************************
+ */
+
+#include <stdio.h>
+#include <varargs.h>
+
+#ifdef DOPRINT_VA
+/*
+ * system provides _doprnt_va routine
+ */
+#define _doprnt _doprnt_va
+#else
+/*
+ * system provides _doprnt routine
+ */
+#define _doprnt_va _doprnt
+#endif
+
+
+#ifdef NEED_VPRINTF
+int
+vprintf(fmt, args)
+ char *fmt;
+ va_list args;
+{
+ _doprnt(fmt, args, stdout);
+ return (ferror(stdout) ? EOF : 0);
+}
+
+int
+vfprintf(f, fmt, args)
+ FILE *f;
+ char *fmt;
+ va_list args;
+{
+ _doprnt(fmt, args, f);
+ return (ferror(f) ? EOF : 0);
+}
+
+int
+vsprintf(s, fmt, args)
+ char *s, *fmt;
+ va_list args;
+{
+ FILE fakebuf;
+
+ fakebuf._flag = _IOSTRG+_IOWRT; /* no _IOWRT: avoid stdio bug */
+ fakebuf._ptr = s;
+ fakebuf._cnt = 32767;
+ _doprnt(fmt, args, &fakebuf);
+ putc('\0', &fakebuf);
+ return (strlen(s));
+}
+#endif /* NEED_VPRINTF */
+
+#if defined(NEED_VSNPRINTF) || defined(NEED_VPRINTF)
+int
+vsnprintf(s, n, fmt, args)
+ char *s, *fmt;
+ va_list args;
+{
+ FILE fakebuf;
+
+ fakebuf._flag = _IOSTRG+_IOWRT; /* no _IOWRT: avoid stdio bug */
+ fakebuf._ptr = s;
+ fakebuf._cnt = n-1;
+ _doprnt(fmt, args, &fakebuf);
+ fakebuf._cnt++;
+ putc('\0', &fakebuf);
+ if (fakebuf._cnt<0)
+ fakebuf._cnt = 0;
+ return (n-fakebuf._cnt-1);
+}
+#endif /* NEED_VPRINTF || NEED_VSNPRINTF */
diff --git a/usr.bin/sup/sup/Makefile b/usr.bin/sup/sup/Makefile
new file mode 100644
index 00000000000..e200b5be8c3
--- /dev/null
+++ b/usr.bin/sup/sup/Makefile
@@ -0,0 +1,19 @@
+# $Id: Makefile,v 1.1 1995/12/16 11:47:05 deraadt Exp $
+
+.PATH: ${.CURDIR}/../src
+
+PROG= sup
+MAN= sup.1
+SRCS= supcmain.o supcvers.o supcparse.o supcname.o supcmisc.o supcmeat.o \
+ scm.o scmio.o stree.o log.o supmsg.o \
+ atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \
+ path.o quit.o run.o salloc.o skipto.o vprintf.o netcryptvoid.c
+LDADDR+=-lutil
+DPADD+= ${LIBUTIL}
+BINOWN= root
+BINGRP= daemon
+BINMODE=555
+BINDIR= /usr/bin
+CFLAGS+=-I${.CURDIR}/../src
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sup/supfilesrv/Makefile b/usr.bin/sup/supfilesrv/Makefile
new file mode 100644
index 00000000000..787b17daba5
--- /dev/null
+++ b/usr.bin/sup/supfilesrv/Makefile
@@ -0,0 +1,18 @@
+# $Id: Makefile,v 1.1 1995/12/16 11:47:06 deraadt Exp $
+
+.PATH: ${.CURDIR}/../src
+
+PROG= supfilesrv
+MAN= supservers.8
+SRCS= supfilesrv.o scan.o scm.o scmio.o stree.o log.o supmsg.o \
+ atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \
+ path.o quit.o run.o salloc.o skipto.o vprintf.o netcryptvoid.c
+LDADD+= -lutil -lcrypt
+DPADD+= ${LIBUTIL}
+BINOWN= root
+BINGRP= daemon
+BINMODE=555
+BINDIR= /usr/bin
+CFLAGS+=-I${.CURDIR}/../src
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sup/supscan/Makefile b/usr.bin/sup/supscan/Makefile
new file mode 100644
index 00000000000..c4fcff11332
--- /dev/null
+++ b/usr.bin/sup/supscan/Makefile
@@ -0,0 +1,18 @@
+# $Id: Makefile,v 1.1 1995/12/16 11:47:07 deraadt Exp $
+
+.PATH: ${.CURDIR}/../src
+
+PROG= supscan
+NOMAN=
+SRCS= supscan.o stree.o scan.o \
+ atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \
+ path.o quit.o run.o salloc.o skipto.o vprintf.o netcryptvoid.c
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
+BINOWN= root
+BINGRP= daemon
+BINMODE=555
+BINDIR= /usr/bin
+CFLAGS+=-I${.CURDIR}/../src
+
+.include <bsd.prog.mk>