summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sup
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1995-12-26 04:54:48 +0000
committerpeter <peter@FreeBSD.org>1995-12-26 04:54:48 +0000
commit6cfdf3a92be66bd2aad749ab1816ca6b7e60aaec (patch)
tree8e0bf13003906a5f44544e14538e6b5064fc0110 /usr.sbin/sup
downloadFreeBSD-src-6cfdf3a92be66bd2aad749ab1816ca6b7e60aaec.zip
FreeBSD-src-6cfdf3a92be66bd2aad749ab1816ca6b7e60aaec.tar.gz
Import the unmodified version of the sup that we are using.
The heritage of this version is not clear. It appears to be NetBSD derived from some time ago.
Diffstat (limited to 'usr.sbin/sup')
-rw-r--r--usr.sbin/sup/Makefile143
-rw-r--r--usr.sbin/sup/README.FreeBSD4
-rw-r--r--usr.sbin/sup/lib/atoo.c54
-rw-r--r--usr.sbin/sup/lib/c.h79
-rw-r--r--usr.sbin/sup/lib/ci.c847
-rw-r--r--usr.sbin/sup/lib/errmsg.c63
-rw-r--r--usr.sbin/sup/lib/expand.c366
-rw-r--r--usr.sbin/sup/lib/ffilecopy.c85
-rw-r--r--usr.sbin/sup/lib/filecopy.c65
-rw-r--r--usr.sbin/sup/lib/libc.h294
-rw-r--r--usr.sbin/sup/lib/log.c169
-rw-r--r--usr.sbin/sup/lib/netcryptvoid.c95
-rw-r--r--usr.sbin/sup/lib/nxtarg.c77
-rw-r--r--usr.sbin/sup/lib/path.c96
-rw-r--r--usr.sbin/sup/lib/quit.c67
-rw-r--r--usr.sbin/sup/lib/run.c181
-rw-r--r--usr.sbin/sup/lib/salloc.c48
-rw-r--r--usr.sbin/sup/lib/scan.c969
-rw-r--r--usr.sbin/sup/lib/scm.c596
-rw-r--r--usr.sbin/sup/lib/scmio.c744
-rw-r--r--usr.sbin/sup/lib/skipto.c78
-rw-r--r--usr.sbin/sup/lib/stree.c357
-rw-r--r--usr.sbin/sup/lib/sup.h257
-rw-r--r--usr.sbin/sup/lib/supmsg.c622
-rw-r--r--usr.sbin/sup/lib/supmsg.h191
-rw-r--r--usr.sbin/sup/lib/sys/viceioctl.h75
-rw-r--r--usr.sbin/sup/lib/sysent.h150
-rw-r--r--usr.sbin/sup/lib/time.h94
-rw-r--r--usr.sbin/sup/lib/vprintf.c131
-rw-r--r--usr.sbin/sup/sup/sup.1886
-rw-r--r--usr.sbin/sup/sup/supcdefs.h155
-rw-r--r--usr.sbin/sup/sup/supcmain.c736
-rw-r--r--usr.sbin/sup/sup/supcmeat.c1483
-rw-r--r--usr.sbin/sup/sup/supcmisc.c345
-rw-r--r--usr.sbin/sup/sup/supcname.c115
-rw-r--r--usr.sbin/sup/sup/supcparse.c244
-rw-r--r--usr.sbin/sup/sup/supcvers.c80
-rw-r--r--usr.sbin/sup/supfilesrv/supfilesrv.c1769
-rw-r--r--usr.sbin/sup/supfilesrv/supservers.8241
-rw-r--r--usr.sbin/sup/supscan/supscan.c428
40 files changed, 13479 insertions, 0 deletions
diff --git a/usr.sbin/sup/Makefile b/usr.sbin/sup/Makefile
new file mode 100644
index 0000000..fce18cf
--- /dev/null
+++ b/usr.sbin/sup/Makefile
@@ -0,0 +1,143 @@
+# 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
+AFS_DEFINES = -DAFS -I/usr/afsws/include
+OSF_DEFINES = -UMACH -DOSF -D_BSD -noshrlib -g -DNEED_VSNPRINTF -DVAR_TMP
+CMUCS_DEFINES = -DMACH -DDOPRINT_VA -DNEED_VPRINTF
+NON_MACH_DEFINES = -UMACH
+#DEFS = -UCMUCS -UCMU ${${SITE}_DEFINES}
+DEFS = -UCMUCS -UCMU ${NETBSD_DEFINES}
+
+#INSTALLATION PARAMETERS
+NETBSD_BINDIR = /usr/local/bin
+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
+
+.if defined(USE_CRYPT)
+NETBSD_LIBS = -lcrypt -lutil
+.else
+NETBSD_LIBS = -lutil
+.endif
+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:
+ rm -f ${PROGRAMS} libextra.a netcrypt.c *.o core a.out
+
+install:
+ 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}
+
+package: install
+ pkg_create -c pkg/+ONELINE -d pkg/+DESC -f pkg/+PLIST sup_bin
+
+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.sbin/sup/README.FreeBSD b/usr.sbin/sup/README.FreeBSD
new file mode 100644
index 0000000..37bb37d
--- /dev/null
+++ b/usr.sbin/sup/README.FreeBSD
@@ -0,0 +1,4 @@
+This is the current CMU sup, modified to support on-the-fly compression.
+It is the same sup used with NetBSD, and thus we've converged on the
+configuration parameters (in other words, don't be alarmed - it works
+fine with FreeBSD!).
diff --git a/usr.sbin/sup/lib/atoo.c b/usr.sbin/sup/lib/atoo.c
new file mode 100644
index 0000000..eac0764
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/c.h b/usr.sbin/sup/lib/c.h
new file mode 100644
index 0000000..801331d
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/ci.c b/usr.sbin/sup/lib/ci.c
new file mode 100644
index 0000000..8960eb5
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/errmsg.c b/usr.sbin/sup/lib/errmsg.c
new file mode 100644
index 0000000..0ca7c9d
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/expand.c b/usr.sbin/sup/lib/expand.c
new file mode 100644
index 0000000..ff4b094
--- /dev/null
+++ b/usr.sbin/sup/lib/expand.c
@@ -0,0 +1,366 @@
+/*
+ * 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>
+#include <sys/dir.h>
+#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 */
+
+#if __STDC__
+static addone __P((register char *, register char *));
+static addpath __P((char));
+static amatch __P((char *, char *));
+static execbrc __P((char *, char *));
+static gethdir __P((char *));
+static glob __P((char *));
+static matchdir __P((char *));
+static match __P((char *, char *));
+#endif
+
+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 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 matchdir(pattern)
+ char *pattern;
+{
+ register struct direct *dp;
+ DIR *dirp;
+
+ dirp = opendir(path);
+ if (dirp == NULL)
+ return;
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_ino == 0) continue;
+ if (match(dp->d_name, pattern))
+ addone(path, dp->d_name);
+ }
+ closedir(dirp);
+ return;
+}
+
+static 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 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 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 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 addpath(c)
+ char c;
+{
+ if (pathp >= lastpathp)
+ return(1);
+ *pathp++ = c;
+ *pathp = 0;
+ return(0);
+}
+
+static 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.sbin/sup/lib/ffilecopy.c b/usr.sbin/sup/lib/ffilecopy.c
new file mode 100644
index 0000000..4cb4262
--- /dev/null
+++ b/usr.sbin/sup/lib/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);
+
+#ifdef __386BSD__
+ 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);
+
+#ifdef __386BSD__
+ (here->_flags) |= __SEOF; /* indicate EOF */
+#else
+ (here->_flag) |= _IOEOF; /* indicate EOF */
+#endif
+ return (0);
+}
diff --git a/usr.sbin/sup/lib/filecopy.c b/usr.sbin/sup/lib/filecopy.c
new file mode 100644
index 0000000..553becb
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/libc.h b/usr.sbin/sup/lib/libc.h
new file mode 100644
index 0000000..108f701
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/log.c b/usr.sbin/sup/lib/log.c
new file mode 100644
index 0000000..4879cf7
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/netcryptvoid.c b/usr.sbin/sup/lib/netcryptvoid.c
new file mode 100644
index 0000000..9dd3c78
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/nxtarg.c b/usr.sbin/sup/lib/nxtarg.c
new file mode 100644
index 0000000..9e93c28
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/path.c b/usr.sbin/sup/lib/path.c
new file mode 100644
index 0000000..f982268
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/quit.c b/usr.sbin/sup/lib/quit.c
new file mode 100644
index 0000000..23b4cb7
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/run.c b/usr.sbin/sup/lib/run.c
new file mode 100644
index 0000000..9072ebe
--- /dev/null
+++ b/usr.sbin/sup/lib/run.c
@@ -0,0 +1,181 @@
+/*
+ * 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);
+ *
+ * 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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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 <sys/wait.h>
+#include <varargs.h>
+
+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);
+}
diff --git a/usr.sbin/sup/lib/salloc.c b/usr.sbin/sup/lib/salloc.c
new file mode 100644
index 0000000..bd0e804
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/scan.c b/usr.sbin/sup/lib/scan.c
new file mode 100644
index 0000000..e68bcdd
--- /dev/null
+++ b/usr.sbin/sup/lib/scan.c
@@ -0,0 +1,969 @@
+/*
+ * 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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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 <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#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 */
+
+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,STRINGLENGTH,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,STRINGLENGTH,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;
+{
+ 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],*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,STRINGLENGTH,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;
+ 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;
+{
+ struct direct *dentry;
+ 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];
+ 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,STRINGLENGTH,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,STRINGLENGTH,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);
+ if (ts.Tctime > lasttime)
+ ts.Tflags |= FNEW;
+ else if (newonly) {
+ for (tl = listTL; tl != NULL; tl = tl->TLnext)
+ if (tmp = Tsearch (tl->TLtree,q))
+ tmp->Tflags &= ~FNEW;
+ notwanted = TRUE;
+ continue;
+ }
+ if (Tlookup (refuseT,q)) {
+ notwanted = TRUE;
+ continue;
+ }
+ t = Tinsert (&listT,q,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 ();
+
+ if (t->Tflags&FBACKUP) fprintf (*scanF,"B");
+ if (t->Tflags&FNOACCT) fprintf (*scanF,"N");
+ fprintf (*scanF,"%o %d %d %s\n",
+ t->Tmode,t->Tctime,t->Tmtime,t->Tname);
+ (void) Tprocess (t->Texec,recordexec,*scanF);
+ return (SCMOK);
+}
+
+static
+recordexec (t,scanF)
+TREE *t;
+FILE **scanF;
+{
+ fprintf(*scanF,"X%s\n",t->Tname);
+ 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.sbin/sup/lib/scm.c b/usr.sbin/sup/lib/scm.c
new file mode 100644
index 0000000..5d71bcc
--- /dev/null
+++ b/usr.sbin/sup/lib/scm.c
@@ -0,0 +1,596 @@
+/*
+ * 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.2 1994/06/20 06:04:04 rgrimes
+ * Humm.. they did a lot of #if __STDC__ but failed to properly prototype
+ * the code. Also fixed one bad argument to a wait3 call.
+ *
+ * It won't compile -Wall, but atleast it compiles standard without warnings
+ * now.
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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";
+
+/*
+ * PROTOTYPES
+ */
+#if __STDC__
+int scmerr __P((int, char *,...));
+#endif
+/*************************
+ *** 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? */
+
+/***************************************************
+ *** 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.sbin/sup/lib/scmio.c b/usr.sbin/sup/lib/scmio.c
new file mode 100644
index 0000000..cde2c9f
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:33 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/skipto.c b/usr.sbin/sup/lib/skipto.c
new file mode 100644
index 0000000..2fa5a4f
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/stree.c b/usr.sbin/sup/lib/stree.c
new file mode 100644
index 0000000..0170b3b
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/sup.h b/usr.sbin/sup/lib/sup.h
new file mode 100644
index 0000000..0b5f07e
--- /dev/null
+++ b/usr.sbin/sup/lib/sup.h
@@ -0,0 +1,257 @@
+/*
+ * 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.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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();
diff --git a/usr.sbin/sup/lib/supmsg.c b/usr.sbin/sup/lib/supmsg.c
new file mode 100644
index 0000000..3894910
--- /dev/null
+++ b/usr.sbin/sup/lib/supmsg.c
@@ -0,0 +1,622 @@
+/*
+ * 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.1.1 1993/08/21 00:46:35 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/supmsg.h b/usr.sbin/sup/lib/supmsg.h
new file mode 100644
index 0000000..b30ea9a
--- /dev/null
+++ b/usr.sbin/sup/lib/supmsg.h
@@ -0,0 +1,191 @@
+/*
+ * 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.1.1 1993/08/21 00:46:35 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/sys/viceioctl.h b/usr.sbin/sup/lib/sys/viceioctl.h
new file mode 100644
index 0000000..0731b52
--- /dev/null
+++ b/usr.sbin/sup/lib/sys/viceioctl.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1989 Carnegie-Mellon University
+ * Copyright (c) 1988 Carnegie-Mellon University
+ * Copyright (c) 1987 Carnegie-Mellon University
+ * All rights reserved. The CMU software License Agreement specifies
+ * the terms and conditions for use and redistribution.
+ */
+/*
+ * Revision 2.4 90/08/30 11:51:12 bohman
+ */
+/*
+ * ITC Remote file system - vice ioctl interface module
+ */
+
+/*
+ * TODO: Find /usr/local/include/viceioctl.h.
+ */
+
+#ifndef _SYS_VICEIOCTL_H_
+#define _SYS_VICEIOCTL_H_
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+struct ViceIoctl {
+ caddr_t in, out; /* Data to be transferred in, or out */
+ short in_size; /* Size of input buffer <= 2K */
+ short out_size; /* Maximum size of output buffer, <= 2K */
+};
+
+/* The 2K limits above are a consequence of the size of the kernel buffer
+ used to buffer requests from the user to venus--2*MAXPATHLEN.
+ The buffer pointers may be null, or the counts may be 0 if there
+ are no input or output parameters
+ */
+
+#ifdef __STDC__
+#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
+#else
+#define _VICEIOCTL(id) ((unsigned int ) _IOW(V, id, struct ViceIoctl))
+#endif
+/* Use this macro to define up to 256 vice ioctl's. These ioctl's
+ all potentially have in/out parameters--this depends upon the
+ values in the ViceIoctl structure. This structure is itself passed
+ into the kernel by the normal ioctl parameter passing mechanism.
+ */
+
+#define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && com <= _VICEIOCTL(255))
+
+#endif _SYS_VICEIOCTL_H_
diff --git a/usr.sbin/sup/lib/sysent.h b/usr.sbin/sup/lib/sysent.h
new file mode 100644
index 0000000..b5839da
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:35 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/lib/time.h b/usr.sbin/sup/lib/time.h
new file mode 100644
index 0000000..0b4ea54
--- /dev/null
+++ b/usr.sbin/sup/lib/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.sbin/sup/lib/vprintf.c b/usr.sbin/sup/lib/vprintf.c
new file mode 100644
index 0000000..235a5f1
--- /dev/null
+++ b/usr.sbin/sup/lib/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.1.1 1993/08/21 00:46:35 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/sup/sup.1 b/usr.sbin/sup/sup/sup.1
new file mode 100644
index 0000000..fa35f5d
--- /dev/null
+++ b/usr.sbin/sup/sup/sup.1
@@ -0,0 +1,886 @@
+.\" 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.2 1994/08/11 02:46:19 rich
+.\" Added extensions written by David Dawes. From the man page:
+.\"
+.\" The -u flag, or the noupdate supfile option prevent updates from
+.\" occurring for regular files where the modification time and mode
+.\" hasn't changed.
+.\"
+.\" Now, how do we feed these patches back to CMU for consideration?
+.\"
+.\" Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+.\" Current sup with compression support.
+.\"
+.\" 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 -u
+The
+.B -u
+flag, or the
+.B noupdate
+supfile option prevent updates from occurring for regular files where
+the modification time and mode hasn't changed.
+.TP
+.B -U
+The
+.B -U
+flag overrides and disables the
+.B -u
+flag and the
+.B noupdate
+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 noupdate
+As described above under the
+.B -u
+flag.
+.TP
+.B compress
+As described above under the
+.B -z
+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/cs/lib/supfiles/coll.list
+supfile used for -s flag
+.TP
+.B /usr/cs/lib/supservers/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/cs/lib/supservers/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.sbin/sup/sup/supcdefs.h b/usr.sbin/sup/sup/supcdefs.h
new file mode 100644
index 0000000..c348fd2
--- /dev/null
+++ b/usr.sbin/sup/sup/supcdefs.h
@@ -0,0 +1,155 @@
+/*
+ * 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.3 1994/08/11 02:46:21 rich
+ * Added extensions written by David Dawes. From the man page:
+ *
+ * The -u flag, or the noupdate supfile option prevent updates from
+ * occurring for regular files where the modification time and mode
+ * hasn't changed.
+ *
+ * Now, how do we feed these patches back to CMU for consideration?
+ *
+ * Revision 1.2 1994/06/20 06:04:06 rgrimes
+ * Humm.. they did a lot of #if __STDC__ but failed to properly prototype
+ * the code. Also fixed one bad argument to a wait3 call.
+ *
+ * It won't compile -Wall, but atleast it compiles standard without warnings
+ * now.
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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
+#define CFNOUPDATE 010000
+
+/*************************
+ *** M A C R O S ***
+ *************************/
+
+#define vnotify if (thisC->Cflags&CFVERBOSE) notify
+/*
+ * C prototypes
+ */
+#if __STDC__
+void done __P((int value,char *fmt,...));
+void goaway __P((char *fmt,...));
+void notify __P((char *fmt,...));
+#endif
diff --git a/usr.sbin/sup/sup/supcmain.c b/usr.sbin/sup/sup/supcmain.c
new file mode 100644
index 0000000..0b25af1
--- /dev/null
+++ b/usr.sbin/sup/sup/supcmain.c
@@ -0,0 +1,736 @@
+/*
+ * 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.2 1994/08/11 02:46:22 rich
+ * Added extensions written by David Dawes. From the man page:
+ *
+ * The -u flag, or the noupdate supfile option prevent updates from
+ * occurring for regular files where the modification time and mode
+ * hasn't changed.
+ *
+ * Now, how do we feed these patches back to CMU for consideration?
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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
+
+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 'u':
+ oflags |= CFNOUPDATE;
+ aflags &= ~CFNOUPDATE;
+ break;
+ case 'U':
+ oflags &= ~CFNOUPDATE;
+ aflags |= CFNOUPDATE;
+ break;
+ case 'v':
+ oflags |= CFVERBOSE;
+ break;
+ case 'z':
+ oflags |= CFCOMPRESS;
+ aflags &= ~CFCOMPRESS;
+ break;
+ case 'Z':
+ oflags &= ~CFCOMPRESS;
+ aflags |= 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.sbin/sup/sup/supcmeat.c b/usr.sbin/sup/sup/supcmeat.c
new file mode 100644
index 0000000..1011074
--- /dev/null
+++ b/usr.sbin/sup/sup/supcmeat.c
@@ -0,0 +1,1483 @@
+/*
+ * 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.4 1994/08/11 02:46:23 rich
+ * Added extensions written by David Dawes. From the man page:
+ *
+ * The -u flag, or the noupdate supfile option prevent updates from
+ * occurring for regular files where the modification time and mode
+ * hasn't changed.
+ *
+ * Now, how do we feed these patches back to CMU for consideration?
+ *
+ * Revision 1.3 1994/06/20 06:04:09 rgrimes
+ * Humm.. they did a lot of #if __STDC__ but failed to properly prototype
+ * the code. Also fixed one bad argument to a wait3 call.
+ *
+ * It won't compile -Wall, but atleast it compiles standard without warnings
+ * now.
+ *
+ * Revision 1.2 1994/05/25 17:58:38 nate
+ * From Gene Stark
+ *
+ * system() returns non-zero status for errors, so check for non-zero
+ * status instead of < 0 which causes gzip/gunzip failures not to be noticed.
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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 */
+
+/*************************************************
+ *** 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;
+ notify ("SUP Fileserver supports compression.\n");
+ }
+ return (FALSE);
+}
+
+/*** Tell file server what to connect to ***/
+
+setup (t)
+register TREE *t;
+{
+ char buf[STRINGLENGTH];
+ 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';
+ (void) sprintf (buf,FILEWHEN,collname,relsufix);
+ f = open (buf,O_RDONLY,0);
+ if (f >= 0) {
+ if (read(f,(char *)&lasttime,sizeof(long)) != sizeof(long))
+ lasttime = 0;
+ (void) close (f);
+ } else
+ lasttime = 0;
+ /* 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. */
+ if (!fetch && t->Tmode == sbuf.st_mode &&
+ (t->Tmode&S_IFMT) == S_IFREG && (thisC->Cflags&CFNOUPDATE)) {
+ vnotify ("SUP update avoided for %s\n", t->Tname);
+ return (SCMOK);
+ }
+ newt = Tinsert (&needT,t->Tname,TRUE);
+ if (!fetch && (t->Tmode&S_IFMT) == S_IFREG)
+ newt->Tflags |= FUPDATE;
+ return (SCMOK);
+}
+
+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];
+ char sys_com[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) {
+ /* make sure file permissions don't cause a problem */
+ (void) unlink (to);
+ sprintf(sys_com, "gunzip < %s > %s\n", tname, to);
+ /* Uncompress it onto the destination */
+ if (system(sys_com) != 0) {
+ notify ("SUP: Error in uncompressing file %s\n",
+ to);
+ (void) unlink (tname);
+ 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;
+ }
+ f = open (fname,(O_WRONLY|O_CREAT|O_TRUNC),0644);
+ if (f < 0) {
+ 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;
+ }
+ (void) write (f,(char *)&scantime,sizeof(int));
+ (void) close (f);
+ 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__
+void
+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__
+void
+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.sbin/sup/sup/supcmisc.c b/usr.sbin/sup/sup/supcmisc.c
new file mode 100644
index 0000000..4894349
--- /dev/null
+++ b/usr.sbin/sup/sup/supcmisc.c
@@ -0,0 +1,345 @@
+/*
+ * 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.2 1994/06/20 06:04:11 rgrimes
+ * Humm.. they did a lot of #if __STDC__ but failed to properly prototype
+ * the code. Also fixed one bad argument to a wait3 call.
+ *
+ * It won't compile -Wall, but atleast it compiles standard without warnings
+ * now.
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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 */
+
+/*************************************************
+ *** 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);
+ (void) sprintf (buf,FILEWHEN,thisC->Cname,relsufix);
+ f = open (buf,O_RDONLY,0);
+ if (f >= 0) {
+ if (read(f,(char *)&twhen,sizeof(long)) != sizeof(long))
+ twhen = 0;
+ (void) close (f);
+ } else
+ twhen = 0;
+ (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__
+void
+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.sbin/sup/sup/supcname.c b/usr.sbin/sup/sup/supcname.c
new file mode 100644
index 0000000..6e645ba
--- /dev/null
+++ b/usr.sbin/sup/sup/supcname.c
@@ -0,0 +1,115 @@
+/*
+ * 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.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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.
+ */
+
+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.sbin/sup/sup/supcparse.c b/usr.sbin/sup/sup/supcparse.c
new file mode 100644
index 0000000..1b55f1e
--- /dev/null
+++ b/usr.sbin/sup/sup/supcparse.c
@@ -0,0 +1,244 @@
+/*
+ * 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.2 1994/08/11 02:46:25 rich
+ * Added extensions written by David Dawes. From the man page:
+ *
+ * The -u flag, or the noupdate supfile option prevent updates from
+ * occurring for regular files where the modification time and mode
+ * hasn't changed.
+ *
+ * Now, how do we feed these patches back to CMU for consideration?
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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, ONOUPDATE
+} 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,
+ "noupdate", ONOUPDATE
+};
+
+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 ONOUPDATE:
+ c->Cflags |= CFNOUPDATE;
+ break;
+ case OTIMEOUT:
+ passdelim (&args,'=');
+ arg = nxtarg (&args," \t");
+ c->Ctimeout = atoi (arg);
+ break;
+ }
+ }
+ return(0);
+}
diff --git a/usr.sbin/sup/sup/supcvers.c b/usr.sbin/sup/sup/supcvers.c
new file mode 100644
index 0000000..5e47f4a
--- /dev/null
+++ b/usr.sbin/sup/sup/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.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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.sbin/sup/supfilesrv/supfilesrv.c b/usr.sbin/sup/supfilesrv/supfilesrv.c
new file mode 100644
index 0000000..dd4dbff
--- /dev/null
+++ b/usr.sbin/sup/supfilesrv/supfilesrv.c
@@ -0,0 +1,1769 @@
+/*
+ * 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]
+ * -l "live" -- don't fork daemon
+ * -P "debug ports" -- use debugging network ports
+ * -N "debug network" -- print debugging messages for network i/o
+ *
+ **********************************************************************
+ * 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.4 1994/08/11 02:46:26 rich
+ * Added extensions written by David Dawes. From the man page:
+ *
+ * The -u flag, or the noupdate supfile option prevent updates from
+ * occurring for regular files where the modification time and mode
+ * hasn't changed.
+ *
+ * Now, how do we feed these patches back to CMU for consideration?
+ *
+ * Revision 1.3 1994/06/20 06:04:13 rgrimes
+ * Humm.. they did a lot of #if __STDC__ but failed to properly prototype
+ * the code. Also fixed one bad argument to a wait3 call.
+ *
+ * It won't compile -Wall, but atleast it compiles standard without warnings
+ * now.
+ *
+ * Revision 1.2 1994/05/25 17:58:40 nate
+ * From Gene Stark
+ *
+ * system() returns non-zero status for errors, so check for non-zero
+ * status instead of < 0 which causes gzip/gunzip failures not to be noticed.
+ *
+ * Revision 1.1.1.1 1993/08/21 00:46:34 jkh
+ * Current sup with compression support.
+ *
+ * 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;
+
+char *clienthost; /* host name of client */
+int nchildren; /* number of children that exist */
+char *prefix; /* collection pathname prefix */
+char *release; /* collection release name */
+char *cryptkey; /* encryption key if non-null */
+int lockfd; /* descriptor of lock file */
+
+/* global variables for scan functions */
+int trace = FALSE; /* directory scan trace */
+int cancompress=FALSE; /* Can we compress files */
+int docompress=FALSE; /* Do we compress files */
+
+HASH *uidH[HASHSIZE]; /* for uid and gid lookup */
+HASH *gidH[HASHSIZE];
+HASH *inodeH[HASHSIZE]; /* for inode lookup for linked file check */
+
+char *fmttime (); /* time format routine */
+
+/*
+ * PROTOTYPES
+ */
+#if __STDC__
+void goaway __P((char *,...));
+#endif
+
+#ifdef LOG_PID_PATHNAME
+static void log_pid(pathname)
+char *pathname;
+{
+ FILE *fp = fopen(pathname,"w");
+ if (!fp) {
+ logerr ("Unable to create pid to file %s",pathname);
+ return;
+ }
+ fprintf (fp, "%d\n", getpid());
+ fclose (fp);
+}
+#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
+
+#ifdef LOG_PID_PATHNAME
+ log_pid(LOG_PID_PATHNAME);
+#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()
+{
+ int w;
+
+ while (wait3(&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;
+
+ 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;
+ 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;
+ 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);
+ execv (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 (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;
+ }
+ 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);
+ (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 sys_com[STRINGLENGTH], temp_file[STRINGLENGTH];
+ char *uconvert(),*gconvert();
+ int sendfile ();
+
+ 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) {
+ if (docompress) {
+ tmpnam(temp_file);
+ sprintf(sys_com, "gzip -c < %s > %s\n", t->Tname, temp_file);
+ if (system(sys_com) < 0) {
+ /* Just in case */
+ unlink(temp_file);
+ goaway ("We died trying to compress");
+ t->Tmode = 0;
+ }
+ fd = open (temp_file,O_RDONLY,0);
+ }
+ else
+ fd = open (t->Tname,O_RDONLY,0);
+ if (fd < 0) t->Tmode = 0;
+ }
+ if (t->Tmode) {
+ t->Tuser = salloc (uconvert (t->Tuid));
+ t->Tgroup = salloc (gconvert (t->Tgid));
+ }
+ }
+ x = msgrecv (sendfile,fd);
+ if (docompress)
+ unlink(temp_file);
+ 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__
+void
+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.sbin/sup/supfilesrv/supservers.8 b/usr.sbin/sup/supfilesrv/supservers.8
new file mode 100644
index 0000000..b39e1fc
--- /dev/null
+++ b/usr.sbin/sup/supfilesrv/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.1.1 1993/08/21 00:46:35 jkh
+.\" Current sup with compression support.
+.\"
+.\" 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.sbin/sup/supscan/supscan.c b/usr.sbin/sup/supscan/supscan.c
new file mode 100644
index 0000000..f43623d
--- /dev/null
+++ b/usr.sbin/sup/supscan/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.1.1 1993/08/21 00:46:35 jkh
+ * Current sup with compression support.
+ *
+ * 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);
+}
OpenPOWER on IntegriCloud