diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-12-16 11:47:08 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-12-16 11:47:08 +0000 |
commit | 8c538e676fee82f4be45abefea6360bb9ee417b3 (patch) | |
tree | 5586f089a9bba22b362414c8e772bc09e63450d0 /usr.bin | |
parent | c06c806f45c8bf1ce55fb3e5ea1bf864cb85d146 (diff) |
add sup to the tree
Diffstat (limited to 'usr.bin')
47 files changed, 13826 insertions, 2 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 79e1e996f58..055304a7212 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -1,5 +1,5 @@ # from: @(#)Makefile 5.8.1.1 (Berkeley) 5/8/91 -# $Id: Makefile,v 1.2 1995/11/06 21:42:19 deraadt Exp $ +# $Id: Makefile,v 1.3 1995/12/16 11:46:37 deraadt Exp $ SUBDIR= apply apropos asa at banner basename bdes biff cal calendar cap_mkdb \ checknr chflags chpass cksum cmp col colcrt colrm column comm \ @@ -13,7 +13,7 @@ SUBDIR= apply apropos asa at banner basename bdes biff cal calendar cap_mkdb \ rdist renice rev rlogin rpcgen rpcinfo rs \ rsh rup ruptime rusers rwall rwho \ script sed shar showmount skey skeyinit soelim split strings \ - su systat tail talk tcopy tee telnet tftp time \ + su sup systat tail talk tcopy tee telnet tftp time \ tip tn3270 touch tput tr true tset tsort tty ul uname unexpand \ unifdef uniq units unvis users uudecode uuencode \ vacation vgrind vi vis vmstat w wall wc what whatis whereis \ diff --git a/usr.bin/sup/Makefile b/usr.bin/sup/Makefile new file mode 100644 index 00000000000..b6045b6b869 --- /dev/null +++ b/usr.bin/sup/Makefile @@ -0,0 +1,5 @@ +# $Id: Makefile,v 1.1 1995/12/16 11:46:39 deraadt Exp $ + +SUBDIR= sup supscan supfilesrv + +.include <bsd.subdir.mk> diff --git a/usr.bin/sup/Makefile.inc b/usr.bin/sup/Makefile.inc new file mode 100644 index 00000000000..b8c97c5eed8 --- /dev/null +++ b/usr.bin/sup/Makefile.inc @@ -0,0 +1,2 @@ + +CFLAGS+=-UCMUCS -UCMU -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR diff --git a/usr.bin/sup/src/Makefile.save b/usr.bin/sup/src/Makefile.save new file mode 100644 index 00000000000..0aad1c0f1bf --- /dev/null +++ b/usr.bin/sup/src/Makefile.save @@ -0,0 +1,136 @@ +# Copyright (c) 1992,1991 Carnegie Mellon University +# All Rights Reserved. +# +# Permission to use, copy, modify and distribute this software and its +# documentation is hereby granted, provided that both the copyright +# notice and this permission notice appear in all copies of the +# software, derivative works or modified versions, and any portions +# thereof, and that both notices appear in supporting documentation. +# +# CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +# CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +# ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +# +# Carnegie Mellon requests users of this software to return to +# +# Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU +# School of Computer Science +# Carnegie Mellon University +# Pittsburgh PA 15213-3890 +# +# any improvements or extensions that they make and grant Carnegie the rights +# to redistribute these changes. +###################################################################### +# Makefile to build sup (the client side), supfilesrv (the repository +# side, and supscan (used by the repository. If you only want to sup +# files from CMU, just build sup. +# The header files: c.h, libc.h and sysent.h are only +# necessary if you are compiling on a non-Mach system. Likewise the +# files in libextra.a are normally found in libcs.a on a Mach system. +# DOPRINT_VA is used by vprintf.c and should be defined if your version +# of libc/doprnt.c defines the routine _doprnt_va. If it defines _doprnt +# instead, leave DORPINT_VA undefined. +###################################################################### +# +# If you need to build a sup for export outside of North America use +# "make EXPORTABLE_SYSTEM=true" +# this will remove (not use) any vestiges of crypt code that is present +# on the system. +# +# If you have crypt/crypt.c and /usr/lib/libcrypt.a, you will be building +# a system that uses the SUP crypt mechanism by default. +# +SITE = NETBSD +#SITE = CMUCS +NETBSD_DEFINES = -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR +AFS_DEFINES = -DAFS -I/usr/afsws/include +OSF_DEFINES = -UMACH -DOSF -D_BSD -noshrlib -g -DNEED_VSNPRINTF -DVAR_TMP +CMUCS_DEFINES = -DMACH -DDOPRINT_VA -DNEED_VPRINTF +NON_MACH_DEFINES = -UMACH +#DEFS = -UCMUCS -UCMU ${${SITE}_DEFINES} +DEFS = -UCMUCS -UCMU ${NETBSD_DEFINES} + +#INSTALLATION PARAMETERS +NETBSD_BINDIR = /usr/local/sbin +NETBSD_MAN1 = /usr/local/man/man1 +NETBSD_MAN8 = /usr/local/man/man8 + +CFLAGS = ${DEFS} -O -I. + +SUPCL = supcmain.o supcvers.o supcparse.o supcname.o \ + supcmisc.o supcmeat.o +SUPS = scm.o scmio.o stree.o log.o supmsg.o netcrypt.o +EXTRA = atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \ + path.o quit.o run.o salloc.o skipto.o vprintf.o + + +PROGRAMS = sup supscan supfilesrv +MAN1 = sup.1 +MAN8 = supservers.8 + +AFS_LIBPATH = /usr/afs/lib +AFS_LIBS = -L${AFS_LIBPATH}/afs -lkauth -lprot -L${AFS_LIBPATH} -lubik -lauth -lrxkad -lsys -ldes -lrx -llwp -lcmd -lcom_err -lc ${AFS_LIBPATH}/afs/util.a + +.if exists(/usr/lib/libcrypt.a) && exists(${.CURDIR}/crypt/crypt.c) && !defined(EXPORTABLE_SYSTEM) +USE_CRYPT = yes +.endif + +NETBSD_LIBS = -lcrypt -lutil +CMUCS_LIBS = -lsys +OSF_LIBS = -lbsd +LIBS = libextra.a +sup_OFILES = ${SUPCL} ${SUPS} +supfilesrv_OFILES = supfilesrv.o scan.o ${SUPS} +supfilesrv_LIBS = libextra.a +supscan_OFILES = supscan.o stree.o scan.o + + +all: ${PROGRAMS} +.if defined(USE_CRYPT) + @echo "WARNING: You have built a NON-exportable version of sup because it uses crypt()!" + @echo " To build a crypt-clean version define EXPORTABLE_SYSTEM=true and make." +.endif + +sup: ${sup_OFILES} ${LIBS} + ${CC} ${CFLAGS} -o sup ${sup_OFILES} ${LIBS} ${NETBSD_LIBS} + +supfilesrv: ${supfilesrv_OFILES} ${supfilesrv_LIBS} + ${CC} ${CFLAGS} -o supfilesrv ${supfilesrv_OFILES} ${supfilesrv_LIBS} ${NETBSD_LIBS} + +supscan: ${supscan_OFILES} ${LIBS} + ${CC} ${CFLAGS} -o supscan ${supscan_OFILES} ${LIBS} ${NETBSD_LIBS} + +libextra.a: ${EXTRA} + ar r libextra.a $? + ranlib libextra.a + +clean cleandir: + rm -f ${PROGRAMS} libextra.a netcrypt.c *.o core a.out + +install: ${PROGRAMS} + install -cs -m 555 -o bin -g bin ${PROGRAMS} ${NETBSD_BINDIR} + install -c -m 444 -o bin -g bin ${MAN1} ${NETBSD_MAN1} + install -c -m 444 -o bin -g bin ${MAN8} ${NETBSD_MAN8} + +netcrypt.c: crypt.diffs +.if defined(USE_CRYPT) + ed - crypt/crypt.c < crypt.diffs +.else + @echo "[ Using netcryptvoid.c ]" + cp netcryptvoid.c netcrypt.c +.endif + +scan.o: sup.h +scm.o: sup.h +scmio.o: sup.h supmsg.h +stree.o: sup.h +supcmain.o: sup.h supmsg.h supcdefs.h +supcmeat.o: sup.h supmsg.h supcdefs.h +supcmisc.o: sup.h supmsg.h supcdefs.h +supcname.o: sup.h supmsg.h supcdefs.h +supcparse.o: sup.h supmsg.h supcdefs.h +supfilesrv.o: sup.h supmsg.h +supmsg.o: sup.h supmsg.h +supscan.o: sup.h +netcryptvoid.o: sup.h supmsg.h +netcrypt.o: sup.h supmsg.h diff --git a/usr.bin/sup/src/atoo.c b/usr.bin/sup/src/atoo.c new file mode 100644 index 00000000000..eac0764e31c --- /dev/null +++ b/usr.bin/sup/src/atoo.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* atoo -- convert ascii to octal + * + * Usge: i = atoo (string); + * unsigned int i; + * char *string; + * + * Atoo converts the value contained in "string" into an + * unsigned integer, assuming that the value represents + * an octal number. + * + * HISTORY + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Rewritten for VAX. + * + */ + +unsigned int atoo(ap) +char *ap; +{ + register unsigned int n; + register char *p; + + p = ap; + n = 0; + while(*p == ' ' || *p == ' ') + p++; + while(*p >= '0' && *p <= '7') + n = n * 8 + *p++ - '0'; + return(n); +} diff --git a/usr.bin/sup/src/c.h b/usr.bin/sup/src/c.h new file mode 100644 index 00000000000..801331d098e --- /dev/null +++ b/usr.bin/sup/src/c.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + * Standard C macros + * + ********************************************************************** + * HISTORY + * 02-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added check to allow multiple or recursive inclusion of this + * file. Added bool enum from machine/types.h for regular users + * that want a real boolean type. + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Also change spacing of MAX and MIN to coincide with that of + * sys/param.h. + * + * 19-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed the number of tabs between TRUE, FALSE and their + * respective values to match those in sys/types.h. + * + * 17-Dec-84 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Only define TRUE and FALSE if not defined. Added caseE macro + * for using enumerated types in switch statements. + * + * 23-Apr-81 Mike Accetta (mja) at Carnegie-Mellon University + * Added "sizeofS" and "sizeofA" macros which expand to the size + * of a string constant and array respectively. + * + ********************************************************************** + */ + +#ifndef _C_INCLUDE_ +#define _C_INCLUDE_ + +#define ABS(x) ((x)>=0?(x):-(x)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +#ifndef FALSE +#define FALSE 0 +#endif FALSE +#ifndef TRUE +#define TRUE 1 +#endif TRUE + +#define CERROR (-1) + +#ifndef bool +typedef enum { false = 0, true = 1 } bool; +#endif bool + +#define sizeofS(string) (sizeof(string) - 1) +#define sizeofA(array) (sizeof(array)/sizeof(array[0])) + +#define caseE(enum_type) case (int)(enum_type) + +#endif _C_INCLUDE_ diff --git a/usr.bin/sup/src/ci.c b/usr.bin/sup/src/ci.c new file mode 100644 index 00000000000..8960eb50cee --- /dev/null +++ b/usr.bin/sup/src/ci.c @@ -0,0 +1,847 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* ci -- command interpreter + * + * Usage (etc.) + * + * HISTORY + * 22-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed checks for VIRTUE window manager. If they don't like + * it then they can fix the more program. + * + * 08-May-85 Steven Shafer (sas) at Carnegie-Mellon University + * Increased MAXENTRIES and MAXHELPS from 200 to 400. + * + * 30-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University + * Adapted for 4.2 UNIX. Added calls to check for + * using window manager of VIRTUE. + * + * 29-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University + * Added two small bug fixes (courtesy of Richard Cohn). + * + * 14-Aug-84 Steven Shafer (sas) at Carnegie-Mellon University + * Added fflush(stdout) after printing prompt, before asking for input line. + * + * 01-Jul-83 Steven Shafer (sas) at Carnegie-Mellon University + * Bug fix: whitespace now required before ">filename" and not permitted + * within or after filename. + * + * 06-Jun-83 Steven Shafer (sas) at Carnegie-Mellon University + * Bug fix: added line to initialize "redirected" to 0. + * + * 20-May-83 Steven Shafer (sas) at Carnegie-Mellon University + * Added quiet bits CINOSEM, CINOFILE, CIFIRSTEQUAL to allow user to + * have special characters ; > = treated as normal data (except = + * after first argument, which still means "variable assignment"). + * Also added output redirection via >filename on input line. + * + * 07-Mar-83 Dave McKeown (dmm) at Carnegie-Mellon University + * (Slight alterations by Steve Shafer.) + * Made cidepth a global, used for recursive and nested calls to + * ci(), and accessable to the user. Added '@x' command, similar + * to '^x' except that the previous command interpreter name is + * remembered and after 'x' is executed, the previous command + * interpreter is reinvoked. Users who plan to use this feature + * must save the name of the previous ci in global variable + * 'ciprev' after exit from the ci(). ie. + * ci(.........); + * strcpy(ciprev,"ci-name"); + * Added ci state CICMDNOINDENT to allow for no indentation of the + * command line prompt based on cidepth. + * Reduced amount of indentation on source code. + * Bug: the "depth" argument is now a no-op, retained for backward + * compatibility. Cidepth is initialized to zero, and incremented + * upon invocation of a ci(). If cidepth is <1 then you are not + * in a ci() instantiation. + * + * 21-Feb-83 Steven Shafer (sas) at Carnegie-Mellon University + * Added up-arrow (^) command (and variable cinext). ^x is used when + * you have a ci program in which one command invokes ci with a + * new set of commands (i.e. a subsystem of the program). Inside the + * subsystem, ^x will exit the subsystem, and cause the main level + * to execute the command line "x" before reading more input lines. + * The cinext variable is used to implement this. Cinext can also be + * used by any user code which desires to force ci to execute a + * specific command before reading more input from the current file. + * + * 16-Jul-82 Steven Shafer (sas) at Carnegie-Mellon University + * Added extra code in _ci_help to eliminate duplicate help file + * names. This way, if several directories are specified and there + * is are files with the same name in more than one directory, only + * the first of each file will be included in the help list. + * + * It would have been nice to do this after the qsort instead of + * before (in ci_help). However, qsort does not ensure that + * "equivalent" entries are kept in the same relative + * order; thus there would be no way to ensure that the + * file being used was the first such file found. + * + * 07-Jul-82 William Chiles (wpc) at Carnegie-Mellon University + * Modified so that "!" invokes shell commands from the type of + * shell specified by the environment variable SHELL. If SHELL + * is not defined the standard shell is used. + * + * 21-Sep-81 Steven Shafer (sas) at Carnegie-Mellon University + * Increased LINELENGTH (input buffer length) to 1100 to satisfy + * voracious requirements of a certain user whose name I won't mention + * but whose initials are "faa". + * + * 08-Oct-80 Steven Shafer (sas) at Carnegie-Mellon University + * Added class variables: ci_tclass cases in ci_show and ci_set. + * Also added CICMDFPEEK in addition to existing CISETPEEK. + * + * 22-May-80 Steven Shafer (sas) at Carnegie-Mellon University + * Ci now sorts help topics into alphabetical order. Some interrupt + * handling has been added, but there are bugs, for example, when + * you interrupt "*" (the listing of command names). The right thing + * happens, but bogus messages are printed. + * + * 16-Apr-80 Steven Shafer (sas) at Carnegie-Mellon University + * Ci now prints lists of names with prstab(). This uses multiple + * columns when appropriate. + * + * 12-Mar-80 Steven Shafer (sas) at Carnegie-Mellon University + * Added code to skip over leading blanks and tabs in the argument list + * when executing commands, and setting and displaying variables. + * Also fixed meta-help, which mysteriously disappeared. + * + * 19-Feb-80 Steven Shafer (sas) at Carnegie-Mellon University + * Added "if (0) del();" to force del() routine to be loaded. This is + * the safest way I know of to define the external int "_del_". If you + * don't believe it, think again about separately compiled files. + * + * 28-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University + * Created. Patterned (somewhat) after ci() on PDP-11. + * + */ + + +#include <strings.h> +#include <libc.h> +#include <ci.h> +#include <del.h> + +char *index(),*getenv(),*rindex(); +extern char _argbreak; +long atol(); +double atof(); +static int ci_help(), ci_show(); +static int _ci_sho(), _ci_set(), ci_set(); + +/************************* + *** M A C R O S *** + *************************/ + +#define LINELENGTH 1100 /* max length of input line */ +#define MAXENTRIES 400 /* max entries in entry list */ +#define MAXHELPS 400 /* max help files available */ +#define METAHELP "/usr/lib/ci.help" /* standard help file */ + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +int ciquiet = 0; /* init globals */ +int ciexit = 0; +int cidepth = 0; +int ciback = 0; /* for use in '@' command */ +FILE *ciinput; + +char cinext[LINELENGTH] = ""; +char ciprev[LINELENGTH] = ""; + +static char *delchoice[] = { /* breakpoint choices */ + "abort abort command file", + "breakpoint break to tty, then resume command file", + 0}; + +/************************************* + *** M A I N R O U T I N E *** + *************************************/ + +ci (prompt,fil,depth,list,helppath,cmdfpath) +char *prompt; /* prompt message */ +FILE *fil; /* input file */ +int depth; /* recursion depth */ +CIENTRY *list; /* entry list */ +char *helppath; /* search list for help files */ +char *cmdfpath; /* search list for command files */ + +{ + + FILE *savfile; /* input file for calling instance of ci */ + int savquiet, savexit; /* globals for calling instance of ci */ + char *p,*q,*cmd,*arg; /* temps for parsing input */ + int i; /* temp */ + char line[LINELENGTH]; /* input line buffer */ + int firststmt; /* temp */ + char *equals,*star; /* index of = and * in input line */ + char cfnam[200]; /* name of command file */ + char *name[MAXENTRIES]; /* name list for entries */ + char *vname[MAXENTRIES]; /* name list for just variables */ + int vnum[MAXENTRIES]; /* correspondence list for variables */ + int nv; /* number of variables */ + int helpcmd; /* "help" command index */ + FILE *newfile; /* command file just opened */ + char bprompt[100]; /* breakpoint prompt */ + char *tname[MAXENTRIES]; /* temp name list */ + int tnum; /* # entries in tname */ + char *Shell; /* holds SHELL value from .login */ + int redirected; /* 1 iff currently redirected output */ + FILE savestdout; /* place to save normal std. output */ + FILE *outfile; /* current output file */ + char *outname; /* output file name */ + + + /* force del() routine to be declared */ + if (0) del(); + /* save globals on stack */ + cidepth++; /* bump the global depth, first CI() is 1 */ + savquiet = ciquiet; + savexit = ciexit; + savfile = ciinput; + ciexit = 0; /* don't exit until this is set */ + ciinput = (fil ? fil : stdin); /* new input file */ + + /* construct name lists for stablk */ + + nv = 0; + for (i=0; list[i].ci_etyp != ci_tend; i++) { + name[i] = list[i].ci_enam; + if (list[i].ci_etyp != ci_tcmd) { /* is variable */ + vname[nv] = name[i]; + vnum[nv] = i; + nv++; + } + } + helpcmd = i++; /* force-feed "help" onto list */ + name[helpcmd] = "help"; + name[i] = 0; + vname[nv] = 0; + + /* loop for input lines */ + + redirected = 0; + while (!ciexit) { + + if (*cinext) { /* get line from ^ command */ + if (ciback) { + sprintf(line,"%s;%s",cinext,ciprev); + ciback = 0; + } + else { + strcpy (line,cinext); + } + strcpy (cinext,""); + p = line; + } + else { /* else read file */ + if ((ciinput == stderr) || (ciinput == stdin) || (!(ciquiet&CICMDFPROMPT))) { + if (!(ciquiet &CICMDNOINDENT)) { + for (i=1; i<cidepth; i++) { + printf (" "); + } + } + printf ("%s ",prompt); + if ((ciinput == stderr) || (ciinput == stdin)) fflush (stdout); + } + p = fgets (line,LINELENGTH,ciinput); /* read input line */ + if (p == 0) { /* EOF */ + if (_del_) { + DELCLEAR; + strcpy (line,""); + p = line; + } + else { + ciexit = 1; + if ((ciinput==stdin) || (ciinput==stderr) || + (!(ciquiet&CICMDFECHO))) printf ("\n"); + } + } + else { + if ((ciinput != stderr) && (ciinput != stdin) && + (!(ciquiet&CICMDFECHO))) printf ("%s",line); + + for (p=line; (*p) && (*p != '\n'); p++) ; + *p = 0; /* kill trailing newline */ + p = line; /* points to start of line */ + } + } + + /* check for redirection of output */ + + if (!ciexit) { + outname = rindex (p,'>'); + if (outname) { + if (outname == p || *(outname+1) == 0 + || ((*(outname-1) != ' ') && (*(outname-1) != '\t'))) { + outname = 0; + } + else { + for (q=outname+1; *q && (*q != ' ') && (*q != '\t'); q++) ; + if (*q) outname = 0; + } + } + if (outname && !(ciquiet&CINOFILE)) { + *outname++ = 0; + outfile = fopen (outname,"w"); + if (outfile == 0) { + printf ("ci: Can't create output file %s\n",outname); + p = ""; + } + else { + fflush (stdout); + savestdout = *stdout; + *stdout = *outfile; + redirected = 1; + } + } + } + + /* loop for each command */ + + firststmt = 1; /* first time through loop */ + while ((!ciexit) && (((ciquiet&CINOSEM) && firststmt) || *(cmd=nxtarg(&p,";")) || _argbreak)) { + + if (ciquiet & CINOSEM) { + cmd = p; + firststmt = 0; + } + + switch (*cmd) { /* what kind of line? */ + + case ':': /* : comment */ + case 0: /* null line */ + break; + + case '!': /* ! shell command */ + cmd = skipover (cmd+1," "); + if ((Shell = getenv("SHELL")) == 0) Shell = "sh"; + if (*cmd) runp (Shell, Shell, "-c", cmd, 0); + else runp (Shell, Shell, 0); + if (!(ciquiet&CISHEXIT)) printf ("Back to %s\n",prompt); + break; + + case '?': /* ? help */ + cmd = skipover (cmd+1," "); + ci_help (cmd,helppath); + break; + + case '<': /* < command file */ + arg = cmd + 1; + cmd = nxtarg (&arg,0); /* parse name */ + if (*cmd == 0) printf ("ci: missing filename\n"); + else { + if (cmdfpath) newfile = fopenp (cmdfpath,cmd,cfnam,"r"); + else newfile = fopen (cmd,"r"); + + if (newfile == 0) + printf ("ci: can't open command file %s\n",cmd); + else { + if (!(ciquiet&CICMDFECHO)) printf ("\n"); + ci (prompt,newfile,cidepth,list,helppath,cmdfpath); + fclose (newfile); + if (!(ciquiet&CICMDFEXIT)) printf ("End of file\n\n"); + } + } + break; + + case '^': /* exit and do command */ + case '@': + if (cidepth > 1) { + if (*cmd == '@') ciback = 1; + if (_argbreak == ';') *(cmd+strlen(cmd)) = ';'; + ciexit = 1; + cmd = skipover(cmd+1," "); + strcpy (cinext,cmd); + } + else printf ("ci: ^ not allowed at top level of ci\n"); + break; + + default: /* list cmds, etc. */ + equals = index (cmd,'='); + if (equals == cmd) cmd++; + + if (equals) { + if (*(equals+1) == 0) *equals = 0; + else *equals = ' '; + } + + arg = cmd; /* parse first word */ + cmd = nxtarg (&arg,0); + if ((ciquiet&CIFIRSTEQUAL) && equals && equals>arg) { + *equals = '='; /* if user doesn't want extra =, kill */ + equals = 0; + } + star = index (cmd,'*'); + if (star) *star = 0; + if (star && equals) { /* list vars */ + printf ("\n"); + for (i=0; vname[i]; i++) { + if (stlmatch (vname[i],cmd)) { + ci_show (list[vnum[i]],arg,CIPEEK); + } + DELBREAK; + } + printf ("\n"); + } + else if (star) { /* list cmds */ + printf ("\n"); + tnum = 0; + for (i=0;name[i]; i++) { + if ((i==helpcmd || list[i].ci_etyp == ci_tcmd) && + stlmatch (name[i],cmd)) { + tname[tnum++] = name[i]; + } + } + tname[tnum] = 0; + prstab (tname); + if (_del_) {_DELNOTE_} + printf ("\n"); + } + else if (equals) { /* set var */ + i = stablk (cmd,vname,0); + if (i >= 0) ci_set (list[vnum[i]],skipover(arg," \t")); + } + else { + i = stablk (cmd,name,0); + + if (i == helpcmd) ci_help (arg,helppath); + else if (i >= 0) { + if (list[i].ci_etyp == ci_tcmd) { + (* (int(*)()) (list[i].ci_eptr)) (skipover(arg," \t")); + } + else ci_show (list[i],skipover(arg," \t"),CISHOW); + } + } + } + + /* end of command */ + + /* DEL trapping */ + + if (_del_) { + if (ciinput == stdin) { + DELCLEAR; /* already at tty level */ + } + else { + _del_ = 0; + i = getstab ("INTERRUPT: abort or breakpoint?",delchoice,"abort"); + if (i == 0) ciexit = 1; /* abort */ + else { /* breakpoint */ + sprintf (bprompt,"Breakpoint for %s",prompt); + ci (bprompt,0,cidepth,list,helppath,cmdfpath); + } + } + } + + /* end of loop for commands */ + + } + + /* end of loop for lines of input file */ + + if (redirected) { + fflush (stdout); + fclose (stdout); + *stdout = savestdout; + redirected = 0; + } + + } + + /* restore globals */ + cidepth --; /* update current depth */ + ciinput = savfile; + ciquiet = savquiet; + ciexit = savexit; +} + +/******************************************** + *** P R I N T H E L P F I L E *** + ********************************************/ + +static int _h_found; /* how many matching names? */ +static char **_h_list; /* list of matching names */ +static char (*_h_nlist)[20]; /* list of filename part of names */ + +static int _ci_help (filspec) +/* called by searchp to expand filspec, adding names to _h_list */ +char *filspec; +{ + register int i,j,result; + char dir[200]; + + result = expand (filspec, _h_list + _h_found, MAXHELPS - _h_found); + if (result > 0) { + for (i=0; i<result; ) { /* elim duplicates */ + path (_h_list[i+_h_found],dir,_h_nlist[i+_h_found]); + for (j=0; + j<_h_found && strcmp(_h_nlist[j],_h_nlist[i+_h_found]) != 0; + j++) ; + if (j < _h_found) { /* is duplicate */ + --result; + strcpy (_h_list[i+_h_found],_h_list[result+_h_found]); + } + else i++; /* isn't duplicate */ + } + + _h_found += result; + } + + return (1); /* keep searching */ +} + +/* for use in sorting help file names */ +static ci_hcomp (p,q) +char **p,**q; +{ + char dir[200],file1[20],file2[20]; + path ((*p),dir,file1); + path ((*q),dir,file2); + return (strcmp(file1,file2)); +} + +static ci_help (topic,helppath) +char *topic,*helppath; +{ + char *fnames[MAXHELPS]; /* names of matching files */ + char names[MAXHELPS][20]; /* stripped filenames */ + char *nptr[MAXHELPS+1]; /* list of ptrs for stablk */ + char dir[200]; /* temp */ + char shstr[300]; /* shell string for system */ + int i; + char *star; + FILE *f; + + if (*topic == 0) { /* wants meta-help */ + f = fopen (METAHELP,"r"); + if (f == 0) { + printf ("Yikes!! Can't open standard help file!\n"); + } + else { + printf ("\n"); + runp("more","more",METAHELP,0); + if (_del_) {_DELNOTE_} + printf ("\n"); + fclose (f); + } + if (helppath && (*helppath) && (!getbool("Do you want a list of help topics?",1))) { + return; + } + } + else { /* chop at * */ + star = index (topic,'*'); + if (star) *star = 0; + } + + if (helppath == 0) { /* no help at all */ + printf ("Sorry, no specific help is available for this program.\n"); + } + else { + _h_found = 0; + _h_list = fnames; + _h_nlist = names; + searchp (helppath,"*",dir,_ci_help); /* find file names */ + qsort (fnames,_h_found,sizeof(char *),ci_hcomp); + + for (i=0; i<_h_found; i++) { /* strip pathnames */ + path (fnames[i],dir,names[i]); + nptr[i] = names[i]; + } + nptr[i] = 0; + + if (*topic) { /* request some topic */ + if (_h_found == 0) { + printf ("No help for %s. Type '?*' for list of help messages.\n",topic); + } + else { + i = stablk (topic,nptr,1); + if (i < 0) i = stabsearch (topic,nptr,0); + if (i >= 0) { + f = fopen (fnames[i],"r"); + if (f == 0) + printf ("Yikes! Can't open help file %s\n",fnames[i]); + else { + printf ("\n"); + runp("more","more",fnames[i],0); + if (_del_) {_DELNOTE_} + printf ("\n"); + fclose (f); + } + } + } + } + else { /* request topic list */ + printf ("\nHelp is available for these topics:\n"); + prstab (nptr); + if (_del_) {_DELNOTE_} + printf ("\n"); + } + + for (i=0; i<_h_found; i++) free (fnames[i]); + + } +} + +/********************************************************* + *** S H O W V A L U E O F V A R I A B L E *** + *********************************************************/ + +static ci_show (entry,arg,mode) +CIENTRY entry; /* entry to display */ +char *arg; /* arg for variable procedures */ +CIMODE mode; /* mode (CIPEEK or CISHOW) */ +{ + if (entry.ci_etyp == ci_tproc) { /* procedure */ + (* (int(*)()) (entry.ci_eptr)) (mode,arg); + } + else if (entry.ci_etyp == ci_tclass) { /* class variable */ + (* (int(*)()) (entry.ci_eptr)) (mode,arg,entry.ci_evar,entry.ci_enam); + } + else { + printf ("%-14s \t",entry.ci_enam); + _ci_sho (entry.ci_etyp, entry.ci_eptr); + printf ("\n"); + } +} + +static _ci_sho (etype,eptr) +ci_type etype; +ci_union *eptr; +{ + int i; + unsigned int u; + + switch (etype) { + + case ci_tint: + printf ("%d",eptr->ci_uint); + break; + case ci_tshort: + printf ("%d",eptr->ci_ushort); + break; + case ci_tlong: + printf ("%D",eptr->ci_ulong); + break; + case ci_toct: + if (eptr->ci_uoct) printf ("0"); + printf ("%o",eptr->ci_uoct); + break; + case ci_thex: + if (eptr->ci_uhex) printf ("0x"); + printf ("%x",eptr->ci_uhex); + break; + case ci_tdouble: + printf ("%g",eptr->ci_udouble); + break; + case ci_tfloat: + printf ("%g",eptr->ci_ufloat); + break; + case ci_tbool: + if (eptr->ci_ubool) printf ("yes"); + else printf ("no"); + break; + case ci_tstring: + printf ("%s",(char *)eptr); + break; + case ci_tcint: + printf ("%d",*(eptr->ci_ucint.ci_ival)); + break; + case ci_tcshort: + printf ("%d",*(eptr->ci_ucshort.ci_sval)); + break; + case ci_tclong: + printf ("%D",*(eptr->ci_uclong.ci_lval)); + break; + case ci_tcoct: + u = *(eptr->ci_ucoct.ci_uval); + if (u) printf ("0"); + printf ("%o",u); + break; + case ci_tchex: + u = *(eptr->ci_uchex.ci_uval); + if (u) printf ("0x"); + printf ("%x",u); + break; + case ci_tcdouble: + printf ("%g",*(eptr->ci_ucdouble.ci_dval)); + break; + case ci_tcfloat: + printf ("%g",*(eptr->ci_ucfloat.ci_fval)); + break; + case ci_tcbool: + i = *(eptr->ci_ucbool.ci_bval); + if (i) printf ("yes"); + else printf ("no"); + break; + case ci_tcchr: + i = *(eptr->ci_ucchr.ci_cval); + printf ("%c",eptr->ci_ucchr.ci_cleg[i]); + break; + case ci_tcstring: + printf ("%s",eptr->ci_ucstring.ci_pval); + break; + case ci_tctab: + i = *(eptr->ci_ucstab.ci_tval); + printf ("%s",eptr->ci_ucstab.ci_ttab[i]); + break; + case ci_tcsearch: + i = *(eptr->ci_ucsearch.ci_tval); + printf ("%s",eptr->ci_ucsearch.ci_ttab[i]); + break; + default: + printf ("Yeek! Illegal cientry type %d!\n",(int) etype); + } +} + +/************************************************************* + *** A S S I G N V A L U E T O V A R I A B L E *** + *************************************************************/ + +static ci_set (entry,arg) +CIENTRY entry; +char *arg; +{ + if (entry.ci_etyp == ci_tproc) { /* variable procedure */ + (* (int(*)()) (entry.ci_eptr)) (CISET,arg); + } + else if (entry.ci_etyp == ci_tclass) { /* class variable */ + (* (int(*)()) (entry.ci_eptr)) (CISET,arg,entry.ci_evar,entry.ci_enam); + } + else { + _ci_set (entry.ci_etyp, entry.ci_eptr, arg); + if (!(ciquiet & (((ciinput==stdin)||(ciinput==stderr)) ? CISETPEEK : CICMDFPEEK))) + ci_show (entry,arg,CIPEEK); + } +} + +static _ci_set (etype,eptr,arg) +ci_type etype; +ci_union *eptr; +char *arg; +{ + int i; + unsigned int u; + char *p; + + if (etype == ci_tstring) { + strcpy ((char *)eptr,arg); + return; + } + if (etype == ci_tcstring) { + strarg (&arg, ";", eptr->ci_ucstring.ci_pmsg, + eptr->ci_ucstring.ci_pval,eptr->ci_ucstring.ci_pval); + return; + } + + p = arg; /* parse first word */ + arg = nxtarg (&p,0); + + switch (etype) { + + case ci_tint: + eptr->ci_uint = atoi (arg); + break; + case ci_tshort: + eptr->ci_ushort = atoi (arg); + break; + case ci_tlong: + eptr->ci_ulong = atol (arg); + break; + case ci_toct: + eptr->ci_uoct = atoo (arg); + break; + case ci_thex: + if (stlmatch(arg,"0x") || stlmatch(arg,"0X")) arg += 2; + eptr->ci_uhex = atoh (arg); + break; + case ci_tdouble: + eptr->ci_udouble = atof (arg); + break; + case ci_tfloat: + eptr->ci_ufloat = atof (arg); + break; + case ci_tbool: + eptr->ci_ubool = (index("yYtT",*arg) != 0); + break; + case ci_tcint: + *(eptr->ci_ucint.ci_ival) = + intarg (&arg,0,eptr->ci_ucint.ci_imsg,eptr->ci_ucint.ci_imin, + eptr->ci_ucint.ci_imax,*(eptr->ci_ucint.ci_ival)); + break; + case ci_tcshort: + *(eptr->ci_ucshort.ci_sval) = + shortarg (&arg,0,eptr->ci_ucshort.ci_smsg,eptr->ci_ucshort.ci_smin, + eptr->ci_ucshort.ci_smax,*(eptr->ci_ucshort.ci_sval)); + break; + case ci_tclong: + *(eptr->ci_uclong.ci_lval) = + longarg (&arg,0,eptr->ci_uclong.ci_lmsg,eptr->ci_uclong.ci_lmin, + eptr->ci_uclong.ci_lmax,*(eptr->ci_uclong.ci_lval)); + break; + case ci_tcoct: + *(eptr->ci_ucoct.ci_uval) = + octarg (&arg,0,eptr->ci_ucoct.ci_umsg,eptr->ci_ucoct.ci_umin, + eptr->ci_ucoct.ci_umax,*(eptr->ci_ucoct.ci_uval)); + break; + case ci_tchex: + *(eptr->ci_uchex.ci_uval) = + hexarg (&arg,0,eptr->ci_uchex.ci_umsg,eptr->ci_uchex.ci_umin, + eptr->ci_uchex.ci_umax,*(eptr->ci_uchex.ci_uval)); + break; + case ci_tcdouble: + *(eptr->ci_ucdouble.ci_dval) = + doublearg (&arg,0,eptr->ci_ucdouble.ci_dmsg,eptr->ci_ucdouble.ci_dmin, + eptr->ci_ucdouble.ci_dmax,*(eptr->ci_ucdouble.ci_dval)); + break; + case ci_tcfloat: + *(eptr->ci_ucfloat.ci_fval) = + floatarg (&arg,0,eptr->ci_ucfloat.ci_fmsg,eptr->ci_ucfloat.ci_fmin, + eptr->ci_ucfloat.ci_fmax,*(eptr->ci_ucfloat.ci_fval)); + break; + case ci_tcbool: + *(eptr->ci_ucbool.ci_bval) = + boolarg (&arg,0,eptr->ci_ucbool.ci_bmsg,*(eptr->ci_ucbool.ci_bval)); + break; + case ci_tcchr: + *(eptr->ci_ucchr.ci_cval) = + chrarg (&arg,0,eptr->ci_ucchr.ci_cmsg,eptr->ci_ucchr.ci_cleg, + eptr->ci_ucchr.ci_cleg[*(eptr->ci_ucchr.ci_cval)]); + break; + case ci_tctab: + *(eptr->ci_ucstab.ci_tval) = + stabarg (&arg,0,eptr->ci_ucstab.ci_tmsg,eptr->ci_ucstab.ci_ttab, + eptr->ci_ucstab.ci_ttab[*(eptr->ci_ucstab.ci_tval)]); + break; + case ci_tcsearch: + *(eptr->ci_ucsearch.ci_tval) = + searcharg (&arg,0,eptr->ci_ucsearch.ci_tmsg, + eptr->ci_ucsearch.ci_ttab, + eptr->ci_ucsearch.ci_ttab[*(eptr->ci_ucsearch.ci_tval)]); + break; + default:; + } +} diff --git a/usr.bin/sup/src/crypt.diffs b/usr.bin/sup/src/crypt.diffs new file mode 100644 index 00000000000..c1201ceccd3 --- /dev/null +++ b/usr.bin/sup/src/crypt.diffs @@ -0,0 +1,87 @@ +118,$c +void encode (in,out,count) +char *in,*out; +int count; +{ + decode (in,out,count); +} +. +109,113c + nr2 = n2; +. +103c + *outp++ = i; +. +95,101c + while(count -- > 0) { + i = *inp++; + nr1 = n1; +. +93a + inp = in; + outp = out; +. +86,90c + return (SCMOK); +} + +void decode (in,out,count) +char *in,*out; +register int count; +{ + register i, n1, n2, nr1, nr2; + char *inp, *outp; +. +81,84c + if (cryptflag == 0) { + if (cryptsize > 0) free (cryptbuf); + cryptsize = 0; + } else if (x > cryptsize) { + if (cryptsize > 0) free (cryptbuf); + cryptbuf = malloc ((unsigned)x+1); + if (cryptbuf == NULL) + return (scmerr (-1,"Can't allocate encryption buffer")); + cryptsize = x; +. +78,79c + static int cryptsize = 0; /* size of current cryptbuf */ +. +75,76c +int getcryptbuf (x) +int x; +. +72a + return (SCMOK); +. +54d +42,48c + cryptflag = 1; + for (i=0; i<ROTORSZ; i++) t1[i] = t2[i] = t3[i] = 0; + (void) strncpy(buf, pw, 8); + (void) strncpy(buf, crypt(buf, buf), 13); +. +27,40c + if (pw == NULL) { + cryptflag = 0; + (void) getcryptbuf (0); + return (SCMOK); +. +23d +19c +netcrypt(pw) +. +12,17c +static char t1[ROTORSZ]; +static char t2[ROTORSZ]; +static char t3[ROTORSZ]; +static char buf[13]; +int cryptflag = 0; /* whether to encrypt/decrypt data */ +char *cryptbuf; /* buffer for data encryption/decryption */ +. +9a +#include "sup.h" + +extern char *malloc(); + +. +w netcrypt.c diff --git a/usr.bin/sup/src/crypt.info b/usr.bin/sup/src/crypt.info new file mode 100644 index 00000000000..badffccf328 --- /dev/null +++ b/usr.bin/sup/src/crypt.info @@ -0,0 +1,15 @@ +The sup programs can be built with or without crypting functionality. +If the file netcryptvoid.c is used no crypting code will be used. +If the file netcrypt.c is used, an engima engine crypting scheme +taken from the BSD 4.3 (1/25/85) file /usr/bin/crypt.c will be used. Since, +this code is both licensed and under U.S. foreign trade restrictions, +we cannot make this code available for anonymous FTP. + +If you want to build a sup client which can encrypt data and you +are a domestic site who has a 4.3 BSD license, we can mail you +a copy of then netcrypt.c file. Just send mail to mach@cs.cmu.edu +requesting the file. + +If you have a crypt.c file available, copy it to the directory +./crypt and the makefile file apply the diff in crypt.diffs to +generate the netcrypt.c file. diff --git a/usr.bin/sup/src/cvt.c b/usr.bin/sup/src/cvt.c new file mode 100644 index 00000000000..0551a266948 --- /dev/null +++ b/usr.bin/sup/src/cvt.c @@ -0,0 +1,56 @@ +/* + * Quick hack to convert old binary sup when.collection files into + * the new ascii format. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> + +int +main(argc, argv) + int argc; + char *argv[]; +{ + long b; + FILE *fp; + int fd; + + if (argc != 2) { + (void) fprintf(stderr, "Usage: %s <filename>\n", argv[0]); + return 1; + } + + if ((fd = open(argv[1], O_RDWR)) == -1) { + perror("open"); + return 1; + } + + if (read(fd, &b, sizeof(b)) != sizeof(b)) { + perror("read"); + return 1; + } + + if (lseek(fd, 0, SEEK_SET) == -1) { + perror("lseek"); + return 1; + } + + (void) close(fd); + + if ((fp = fopen(argv[1], "w")) == NULL) { + perror("fopen"); + return 1; + } + + if (fprintf(fp, "%ld\n", b) < 0) { + perror("fprintf"); + return 1; + } + if (fclose(fp) != 0) { + perror("fclose"); + return 1; + } + + return 0; +} diff --git a/usr.bin/sup/src/errmsg.c b/usr.bin/sup/src/errmsg.c new file mode 100644 index 00000000000..0ca7c9d04f4 --- /dev/null +++ b/usr.bin/sup/src/errmsg.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/***************************************************************** + * HISTORY + * 04-Mar-85 Rudy Nedved (ern) at Carnegie-Mellon University + * Create a CMU version of the BBN errmsg routine from scratch. It + * differs from the BBN errmsg routine in the fact that it uses a + * negative value to indicate using the current errno value...the + * BBN uses a negative OR zero value. + */ + +extern int errno; +extern int sys_nerr; +extern char *sys_errlist[]; + +static char *itoa(p,n) +char *p; +unsigned n; +{ + if (n >= 10) + p =itoa(p,n/10); + *p++ = (n%10)+'0'; + return(p); +} + +char *errmsg(cod) +int cod; +{ + static char unkmsg[] = "Unknown error "; + static char unk[sizeof(unkmsg)+11]; /* trust us */ + + if (cod < 0) cod = errno; + + if((cod >= 0) && (cod < sys_nerr)) + return(sys_errlist[cod]); + + strcpy(unk,unkmsg); + *itoa(&unk[sizeof(unkmsg)-1],cod) = '\0'; + + return(unk); +} diff --git a/usr.bin/sup/src/expand.c b/usr.bin/sup/src/expand.c new file mode 100644 index 00000000000..0014ebba911 --- /dev/null +++ b/usr.bin/sup/src/expand.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + * expand - expand wildcard filename specifications + * + * Usage: + * int expand(spec, buffer, bufsize); + * char *spec, **buffer; + * int bufsize; + * + * Expand takes a file specification, and expands it into filenames + * by resolving the characters '*', '?', '[', ']', '{', '}' and '~' + * in the same manner as the shell. You provide "buffer", which is + * an array of char *'s, and you tell how big it is in bufsize. + * Expand will compute the corresponding filenames, and will fill up + * the entries of buffer with pointers to malloc'd strings. + * + * The value returned by expand is the number of filenames found. If + * this value is -1, then malloc failed to allocate a string. If the + * value is bufsize + 1, then too many names were found and you can try + * again with a bigger buffer. + * + * This routine was basically created from the csh sh.glob.c file with + * the following intended differences: + * + * Filenames are not sorted. + * All expanded filenames returned exist. + * + ********************************************************************** + * HISTORY + * 13-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Replaced a stat() with lstat() and changed glob() to only call + * matchdir() for directories. + * + * 20-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created from csh glob() function and 4.1 expand() function. + * + ********************************************************************** + */ +#include <sys/param.h> +#include <sys/stat.h> +#ifdef HAS_POSIX_DIR +#include <dirent.h> +#else +#include <sys/dir.h> +#endif +#include <pwd.h> +#include <ctype.h> +#include <libc.h> +#include <setjmp.h> + +static jmp_buf sjbuf; + +static char pathbuf[MAXPATHLEN]; +static char *path, *pathp, *lastpathp; + +static char *globchars = "{[*?"; /* meta characters */ +static char *entp; /* current dir entry pointer */ + +static char **BUFFER; /* pointer to the buffer */ +static int BUFSIZE; /* maximum number in buffer */ +static int bufcnt; /* current number in buffer */ + +static void glob(); +static void matchdir(); +static int execbrc(); +static int match(); +static int amatch(); +static void addone(); +static int addpath(); +static int gethdir(); + +int expand(spec, buffer, bufsize) + register char *spec; + char **buffer; + int bufsize; +{ + pathp = path = pathbuf; + *pathp = 0; + lastpathp = &path[MAXPATHLEN - 2]; + BUFFER = buffer; + BUFSIZE = bufsize; + bufcnt = 0; + if (setjmp(sjbuf) == 0) + glob(spec); + return(bufcnt); +} + +static void glob(as) + char *as; +{ + register char *cs; + register char *spathp, *oldcs; + struct stat stb; + + spathp = pathp; + cs = as; + if (*cs == '~' && pathp == path) { + if (addpath('~')) goto endit; + for (cs++; isalnum(*cs) || *cs == '_' || *cs == '-';) + if (addpath(*cs++)) goto endit; + if (!*cs || *cs == '/') { + if (pathp != path + 1) { + *pathp = 0; + if (gethdir(path + 1)) goto endit; + strcpy(path, path + 1); + } else + strcpy(path, (char *)getenv("HOME")); + pathp = path; + while (*pathp) pathp++; + } + } + while (*cs == 0 || index(globchars, *cs) == 0) { + if (*cs == 0) { + if (lstat(path, &stb) >= 0) addone(path, ""); + goto endit; + } + if (addpath(*cs++)) goto endit; + } + oldcs = cs; + while (cs > as && *cs != '/') + cs--, pathp--; + if (*cs == '/') + cs++, pathp++; + *pathp = 0; + if (*oldcs == '{') { + execbrc(cs, NULL); + return; + } + /* this should not be an lstat */ + if (stat(path, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) + matchdir(cs); +endit: + pathp = spathp; + *pathp = 0; + return; +} + +static void matchdir(pattern) + char *pattern; +{ +#ifdef HAS_POSIX_DIR + register struct dirent *dp; +#else + register struct direct *dp; +#endif + DIR *dirp; + + dirp = opendir(path); + if (dirp == NULL) + return; + while ((dp = readdir(dirp)) != NULL) { +#ifdef HAS_POSIX_DIR + if (dp->d_fileno == 0) continue; +#else + if (dp->d_ino == 0) continue; +#endif + if (match(dp->d_name, pattern)) + addone(path, dp->d_name); + } + closedir(dirp); + return; +} + +static int execbrc(p, s) + char *p, *s; +{ + char restbuf[MAXPATHLEN + 1]; + register char *pe, *pm, *pl; + int brclev = 0; + char *lm, savec, *spathp; + + for (lm = restbuf; *p != '{'; *lm++ = *p++) + continue; + for (pe = ++p; *pe; pe++) + switch (*pe) { + case '{': + brclev++; + continue; + case '}': + if (brclev == 0) goto pend; + brclev--; + continue; + case '[': + for (pe++; *pe && *pe != ']'; pe++) + continue; + if (!*pe) break; + continue; + } +pend: + if (brclev || !*pe) return (0); + for (pl = pm = p; pm <= pe; pm++) + switch (*pm & 0177) { + case '{': + brclev++; + continue; + case '}': + if (brclev) { + brclev--; + continue; + } + goto doit; + case ',': + if (brclev) continue; +doit: + savec = *pm; + *pm = 0; + strcpy(lm, pl); + strcat(restbuf, pe + 1); + *pm = savec; + if (s == 0) { + spathp = pathp; + glob(restbuf); + pathp = spathp; + *pathp = 0; + } else if (amatch(s, restbuf)) + return (1); + pl = pm + 1; + continue; + + case '[': + for (pm++; *pm && *pm != ']'; pm++) + continue; + if (!*pm) break; + continue; + } + return (0); +} + +static int match(s, p) + char *s, *p; +{ + register int c; + register char *sentp; + + if (*s == '.' && *p != '.') return(0); + sentp = entp; + entp = s; + c = amatch(s, p); + entp = sentp; + return (c); +} + +static int amatch(s, p) + register char *s, *p; +{ + register int scc; + int ok, lc; + char *spathp; + struct stat stb; + int c, cc; + + for (;;) { + scc = *s++ & 0177; + switch (c = *p++) { + case '{': + return (execbrc(p - 1, s - 1)); + case '[': + ok = 0; + lc = 077777; + while (cc = *p++) { + if (cc == ']') { + if (ok) break; + return (0); + } + if (cc == '-') { + if (lc <= scc && scc <= *p++) + ok++; + } else + if (scc == (lc = cc)) + ok++; + } + if (cc == 0) return (0); + continue; + case '*': + if (!*p) return (1); + if (*p == '/') { + p++; + goto slash; + } + for (s--; *s; s++) + if (amatch(s, p)) + return (1); + return (0); + case 0: + return (scc == 0); + default: + if (c != scc) return (0); + continue; + case '?': + if (scc == 0) return (0); + continue; + case '/': + if (scc) return (0); +slash: + s = entp; + spathp = pathp; + while (*s) + if (addpath(*s++)) goto pathovfl; + if (addpath('/')) goto pathovfl; + if (stat(path, &stb) >= 0 && + (stb.st_mode&S_IFMT) == S_IFDIR) + if (*p == 0) + addone(path, ""); + else + glob(p); +pathovfl: + pathp = spathp; + *pathp = 0; + return (0); + } + } +} + +static void addone(s1, s2) + register char *s1, *s2; +{ + register char *ep; + + if (bufcnt >= BUFSIZE) { + bufcnt = BUFSIZE + 1; + longjmp(sjbuf, 1); + } + ep = (char *)malloc(strlen(s1) + strlen(s2) + 1); + if (ep == 0) { + bufcnt = -1; + longjmp(sjbuf, 1); + } + BUFFER[bufcnt++] = ep; + while (*s1) *ep++ = *s1++; + while (*ep++ = *s2++); +} + +static int addpath(c) + char c; +{ + if (pathp >= lastpathp) + return(1); + *pathp++ = c; + *pathp = 0; + return(0); +} + +static int gethdir(home) + char *home; +{ + struct passwd *getpwnam(); + register struct passwd *pp = getpwnam(home); + + if (pp == 0) + return(1); + strcpy(home, pp->pw_dir); + return(0); +} diff --git a/usr.bin/sup/src/ffilecopy.c b/usr.bin/sup/src/ffilecopy.c new file mode 100644 index 00000000000..e6834239f5c --- /dev/null +++ b/usr.bin/sup/src/ffilecopy.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* ffilecopy -- very fast buffered file copy + * + * Usage: i = ffilecopy (here,there) + * int i; + * FILE *here, *there; + * + * Ffilecopy is a very fast routine to copy the rest of a buffered + * input file to a buffered output file. Here and there are open + * buffers for reading and writing (respectively); ffilecopy + * performs a file-copy faster than you should expect to do it + * yourself. Ffilecopy returns 0 if everything was OK; EOF if + * there was any error. Normally, the input file will be left in + * EOF state (feof(here) will return TRUE), and the output file will be + * flushed (i.e. all data on the file rather in the core buffer). + * It is not necessary to flush the output file before ffilecopy. + * + * HISTORY + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Created for VAX. + * + */ + +#include <stdio.h> +int filecopy(); + +int ffilecopy (here,there) +FILE *here, *there; +{ + register int i, herefile, therefile; + + herefile = fileno(here); + therefile = fileno(there); + + if (fflush (there) == EOF) /* flush pending output */ + return (EOF); + +#if defined(__386BSD__) || defined(__NetBSD__) + if ((here->_r) > 0) { /* flush buffered input */ + i = write (therefile, here->_p, here->_r); + if (i != here->_r) return (EOF); + here->_p = here->_bf._base; + here->_r = 0; + } +#else + if ((here->_cnt) > 0) { /* flush buffered input */ + i = write (therefile, here->_ptr, here->_cnt); + if (i != here->_cnt) return (EOF); + here->_ptr = here->_base; + here->_cnt = 0; + } +#endif + i = filecopy (herefile, therefile); /* fast file copy */ + if (i < 0) return (EOF); + +#if defined(__386BSD__) || defined(__NetBSD__) + (here->_flags) |= __SEOF; /* indicate EOF */ +#else + (here->_flag) |= _IOEOF; /* indicate EOF */ +#endif + return (0); +} diff --git a/usr.bin/sup/src/filecopy.c b/usr.bin/sup/src/filecopy.c new file mode 100644 index 00000000000..553becb34cc --- /dev/null +++ b/usr.bin/sup/src/filecopy.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* filecopy -- copy a file from here to there + * + * Usage: i = filecopy (here,there); + * int i, here, there; + * + * Filecopy performs a fast copy of the file "here" to the + * file "there". Here and there are both file descriptors of + * open files; here is open for input, and there for output. + * Filecopy returns 0 if all is OK; -1 on error. + * + * I have performed some tests for possible improvements to filecopy. + * Using a buffer size of 10240 provides about a 1.5 times speedup + * over 512 for a file of about 200,000 bytes. Of course, other + * buffer sized should also work; this is a rather arbitrary choice. + * I have also tried inserting special startup code to attempt + * to align either the input or the output file to lie on a + * physical (512-byte) block boundary prior to the big loop, + * but this presents only a small (about 5% speedup, so I've + * canned that code. The simple thing seems to be good enough. + * + * HISTORY + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Rewritten for VAX; same as "filcopy" on PDP-11. Bigger buffer + * size (20 physical blocks) seems to be a big win; aligning things + * on block boundaries seems to be a negligible improvement at + * considerable cost in complexity. + * + */ + +#define BUFFERSIZE 10240 + +int filecopy (here,there) +int here,there; +{ + register int kount; + char buffer[BUFFERSIZE]; + kount = 0; + while (kount == 0 && (kount=read(here,buffer,BUFFERSIZE)) > 0) + kount -= write (there,buffer,kount); + return (kount ? -1 : 0); +} diff --git a/usr.bin/sup/src/libc.h b/usr.bin/sup/src/libc.h new file mode 100644 index 00000000000..bac8444ec15 --- /dev/null +++ b/usr.bin/sup/src/libc.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + ********************************************************************** + * HISTORY + * $Log: libc.h,v $ + * Revision 1.1 1995/12/16 11:46:46 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.7 89/04/03 11:10:45 vanryzin + * Changed definition of qsort for c++ to indicate the procedure + * passed to qsort has parameters. Since we were unsure if ANSI C + * could handle the syntax I placed the new definition within #if + * defined(c_plusplus) conditionals. This may not be necessary + * and perhaps should be fixed at a later time. + * [89/04/03 vanryzin] + * + * Revision 1.6 89/02/05 15:55:57 gm0w + * Added extern char *errmsg(). + * [89/02/04 gm0w] + * + * Revision 1.5 89/01/20 15:34:40 gm0w + * Moved all of the STDC changes to other existing include files + * back into this one. Added non-STDC extern declarations for + * all functions without int return values to match those defined + * by STDC. Added include of sysent.h. Removed obsolete cdate + * extern declaration. + * [88/12/17 gm0w] + * + * Revision 1.4 88/12/22 16:58:56 mja + * Correct __STDC__ parameter type for getenv(). + * [88/12/20 dld] + * + * Revision 1.3 88/12/14 23:31:42 mja + * Made file reentrant. Added declarations for __STDC__. + * [88/01/06 jjk] + * + * 30-Apr-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added pathof() extern. + * + * 01-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added getname() extern. + * + * 29-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added lseek() extern. + * + * 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added salloc() extern. + * + * 14-Aug-81 Mike Accetta (mja) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +#ifndef _LIBC_H_ +#define _LIBC_H_ 1 + +#ifndef _TYPES_ +#include <sys/types.h> +#endif /* _TYPES_ */ + +#ifndef _SYSENT_H_ +#include <sysent.h> +#endif /* _SYSENT_H_ */ + +#ifndef FILE +#include <stdio.h> +#endif /* FILE */ + +#ifndef _STRINGS_H_ +#include <strings.h> +#endif /* _STRINGS_H_ */ + +#ifndef _TIME_H_ +#include <time.h> +#endif /* _TIME_H_ */ + +/* CMU stdio additions */ +#if defined(__STDC__) +extern FILE *fopenp(const char*, const char*, char*, char*); +extern FILE *fwantread(const char*, const char*, const char*, const char*); +extern FILE *fwantwrite(const char*, const char*, const char*, const char*, + int); +#else /* __STDC__ */ +extern FILE *fopenp(); +extern FILE *fwantread(); +extern FILE *fwantwrite(); +#endif /* __STDC__ */ + +/* CMU string routines */ +#if defined(__STDC__) +extern char* foldup(char*, const char*); +extern char* folddown(char*, const char*); +extern char* sindex(const char*, const char*); +extern char* skipto(const char*, const char*); +extern char* skipover(const char*, const char*); +extern char* nxtarg(char**, const char*); +extern char _argbreak; +extern char* getstr(const char*, char*, char*); +extern int getstab(const char*, const char**, const char*); +extern int getsearch(const char*, const char**, const char*); +extern char* strarg(const char**, const char*, const char*, char*, char*); +extern int stabarg(const char**, const char*, const char*, const char**, + const char*); +extern int searcharg(const char**, const char*, const char*, const char**, + const char*); +extern int getint(const char*, int, int, int); +extern int intarg(const char**, const char*, const char*, int, int, int); +extern long getlong(const char*, long, long, long); +extern long longarg(const char**, const char*, const char*, long, long, long); +extern short getshort(const char*, short, short, short); +extern short shortarg(const char**, const char*, const char*, + short, short, short); +extern float getfloat(const char*, float, float, float); +extern float floatarg(const char**, const char*, const char*, + float, float, float); +extern double getdouble(const char*, double, double, double); +extern double doublearg(const char**, const char*, const char*, + double, double, double); +extern unsigned int getoct(const char*, unsigned int, unsigned int, + unsigned int); +extern unsigned int octarg(const char**, const char*, const char*, + unsigned int, unsigned int, unsigned int); +extern unsigned int gethex(const char*, unsigned int, unsigned int, + unsigned int); +extern unsigned int hexarg(const char**, const char*, const char*, + unsigned int, unsigned int, unsigned int); +extern unsigned int atoo(const char*); +extern unsigned int atoh(const char*); +extern char *salloc(const char*); +extern char *concat(const char*, int, ...); +#else /* __STDC__ */ +extern char *foldup(), *folddown(); +extern char *sindex(), *skipto(), *skipover(), *nxtarg(); +extern char *getstr(), *strarg(); +extern long getlong(), longarg(); +extern short getshort(), shortarg(); +extern float getfloat(), floatarg(); +extern double getdouble(), doublearg(); +extern unsigned int getoct(), octarg(), gethex(), hexarg(); +extern unsigned int atoo(), atoh(); +extern char *salloc(); +extern char *concat(); +#endif /* __STDC__ */ + +/* CMU library routines */ +#if defined(__STDC__) +extern char *getname(int); +extern char *pathof(char *); +extern char *errmsg(int); +#else /* __STDC__ */ +extern char *getname(); +extern char *pathof(); +extern char *errmsg(); +#endif /* __STDC__ */ + +/* CMU time additions */ +#if defined(__STDC__) +extern long gtime(const struct tm*); +extern long atot(const char*); +#else /* __STDC__ */ +extern long gtime(); +extern long atot(); +#endif /* __STDC__ */ + +/* 4.3 BSD standard library routines; taken from man(3) */ +#if defined(__STDC__) +typedef int (*PFI)(); +#if defined(c_plusplus) +typedef int (*PFI2)(...); +#endif /* c_plusplus */ +#if 0 +extern void abort(void); +extern int abs(int); +extern double atof(const char *); +extern int atoi(const char *); +extern long atol(const char *); +extern void bcopy(const void *, void *, int); +extern int bcmp(const void *, const void *, int); +extern void bzero(void *, int); +extern int ffs(int); +extern char *crypt(const char *, const char *); +extern void setkey(char *); +extern void encrypt(char *, int); +extern char *ecvt(double, int, int *, int *); +extern char *fcvt(double, int, int *, int *); +extern char *gcvt(double, int, char *); +extern int execl(const char *, ...); +extern int execv(const char *, const char **); +extern int execle(const char *, ...); +extern int exect(const char *, const char **, const char **); +extern void exit(int); +extern char *getenv(const char *); +extern char *getlogin(void); +extern int getopt(int, const char **, const char *); +extern char *getpass(const char *); +extern char *getusershell(void); +extern void setusershell(void); +extern void endusershell(void); +extern char *getwd(char *); +extern int initgroups(const char *, gid_t); +extern void *malloc(unsigned); +extern void free(void *); +extern void *realloc(void *, unsigned); +extern void *calloc(unsigned, unsigned); +extern void *alloca(int); +extern char *mktemp(char *); +extern int mkstemp(char *); +extern void monitor(PFI, PFI, short *, int, int); +extern void monstartup(PFI, PFI); +extern void moncontrol(int); +extern int pause(void); +#if defined(c_plusplus) +extern void qsort(void *, int, int, PFI2); +#else /* c_plusplus */ +extern void qsort(void *, int, int, PFI); +#endif /* c_plusplus */ +extern long random(void); +extern int srandom(int); +extern void *initstate(unsigned, void *, int); +extern void *setstate(void *); +extern int rcmd(char **, int, const char *, const char *, const char *, int); +extern int rresvport(int *); +extern int ruserok(char *, int, const char *, const char *); +extern char *re_comp(char *); +extern int re_exec(char *); +extern int rexec(char **, int, const char *, const char *, const char *, + int *); +extern int setuid(uid_t); +extern int seteuid(uid_t); +extern int setruid(uid_t); +extern int setgid(gid_t); +extern int setegid(gid_t); +extern int setrgid(gid_t); +extern void sleep(unsigned); +extern void swab(void *, void *, int); +extern int system(const char *); +extern char *ttyname(int); +extern int isatty(int); +extern int ttyslot(void); +extern unsigned ualarm(unsigned, unsigned); +extern void usleep(unsigned); +#endif +#else /* __STDC__ */ +extern double atof(); +extern long atol(); +extern char *crypt(); +extern char *ecvt(); +extern char *fcvt(); +extern char *gcvt(); +extern char *getenv(); +extern char *getlogin(); +extern char *getpass(); +extern char *getusershell(); +extern char *getwd(); +extern char *malloc(); +extern char *realloc(); +extern char *calloc(); +extern char *alloca(); +extern char *mktemp(); +extern long random(); +extern char *initstate(); +extern char *setstate(); +extern char *re_comp(); +extern char *ttyname(); +extern unsigned ualarm(); +#endif /* __STDC__ */ +#endif /* not _LIBC_H_ */ diff --git a/usr.bin/sup/src/log.c b/usr.bin/sup/src/log.c new file mode 100644 index 00000000000..4a0ab60b8fa --- /dev/null +++ b/usr.bin/sup/src/log.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * Logging support for SUP + ********************************************************************** + * HISTORY + * $Log: log.c,v $ + * Revision 1.1 1995/12/16 11:46:47 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.5 92/08/11 12:03:43 mrt + * Brad's delinting and variable argument list usage + * changes. Added copyright. + * + * Revision 1.3 89/08/15 15:30:37 bww + * Updated to use v*printf() in place of _doprnt(). + * From "[89/04/19 mja]" at CMU. + * [89/08/15 bww] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added check to allow logopen() to be called multiple times. + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +#include <stdio.h> +#include <sys/syslog.h> +#include <c.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "sup.h" + +#ifdef lint +/*VARARGS1*//*ARGSUSED*/ +static void quit(status) {}; +#endif /* lint */ + +static int opened = 0; + +logopen(program) +char *program; +{ + if (opened) return; + openlog(program,LOG_PID,LOG_DAEMON); + opened++; +} + +#if __STDC__ +logquit(int retval,char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +logquit(va_alist) +va_dcl +#endif +{ +#if !__STDC__ + int retval; + char *fmt; +#endif + char buf[STRINGLENGTH]; + va_list ap; + +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + retval = va_arg(ap,int); + fmt = va_arg(ap,char *); +#endif + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (opened) { + syslog (LOG_ERR,buf); + closelog (); + exit (retval); + } + quit (retval,"SUP: %s\n",buf); +} + +#if __STDC__ +logerr(char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +logerr(va_alist) +va_dcl +#endif +{ +#if !__STDC__ + char *fmt; +#endif + char buf[STRINGLENGTH]; + va_list ap; + +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + fmt = va_arg(ap,char *); +#endif + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (opened) { + syslog (LOG_ERR,buf); + return; + } + fprintf (stderr,"SUP: %s\n",buf); + (void) fflush (stderr); +} + +#if __STDC__ +loginfo(char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +loginfo(va_alist) +va_dcl +#endif +{ +#if !__STDC__ + char *fmt; +#endif + char buf[STRINGLENGTH]; + va_list ap; + +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + fmt = va_arg(ap,char *); +#endif + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (opened) { + syslog (LOG_INFO,buf); + return; + } + printf ("%s\n",buf); + (void) fflush (stdout); +} diff --git a/usr.bin/sup/src/netcryptvoid.c b/usr.bin/sup/src/netcryptvoid.c new file mode 100644 index 00000000000..4676df945c5 --- /dev/null +++ b/usr.bin/sup/src/netcryptvoid.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/********************************************************************** + * HISTORY + * $Log: netcryptvoid.c,v $ + * Revision 1.1 1995/12/16 11:46:47 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 2.2 92/09/09 22:04:34 mrt + * Created. + * [92/09/09 mrt] + * + */ +/* + * DATA ENCRYPTION + * netcrypt (key) turn on/off encryption of strings and files + * char *key; encryption key + * + */ + +/* + * Replacement for subroutine version of "crypt" program + * for foreign and non-BSD-licensed sites. With this code + * you can only run unencrypted sups + */ + +#include <libc.h> +#include "sup.h" +#include "supmsg.h" + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +int cryptflag = 0; /* whether to encrypt/decrypt data */ +char *cryptbuf; /* buffer for data encryption/decryption */ + +int netcrypt (pword) +char *pword; +{ + if (pword == NULL || (strcmp(pword,PSWDCRYPT) == 0)) { + cryptflag = 0; + (void) getcryptbuf (0); + return (SCMOK); + } + return (SCMERR); +} +int getcryptbuf (x) +int x; +{ + static int cryptsize = 0; /* size of current cryptbuf */ + + if (cryptflag == 0) { + return(SCMOK); + } else + return (SCMERR); +} + +void decode (in,out,count) +char *in,*out; +int count; +{ +} + + +void encode (in,out,count) +char *in,*out; +int count; +{ +} diff --git a/usr.bin/sup/src/nxtarg.c b/usr.bin/sup/src/nxtarg.c new file mode 100644 index 00000000000..9e93c2840ee --- /dev/null +++ b/usr.bin/sup/src/nxtarg.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + * nxtarg -- strip off arguments from a string + * + * Usage: p = nxtarg (&q,brk); + * char *p,*q,*brk; + * extern char _argbreak; + * + * q is pointer to next argument in string + * after call, p points to string containing argument, + * q points to remainder of string + * + * Leading blanks and tabs are skipped; the argument ends at the + * first occurence of one of the characters in the string "brk". + * When such a character is found, it is put into the external + * variable "_argbreak", and replaced by a null character; if the + * arg string ends before that, then the null character is + * placed into _argbreak; + * If "brk" is 0, then " " is substituted. + * + * HISTORY + * 01-Jul-83 Steven Shafer (sas) at Carnegie-Mellon University + * Bug fix: added check for "back >= front" in loop to chop trailing + * white space. + * + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Rewritten for VAX. By popular demand, a table of break characters + * has been added (implemented as a string passed into nxtarg). + * + * Originally from klg (Ken Greer); IUS/SUS UNIX. + */ + +char _argbreak; +char *skipto(); + +char *nxtarg (q,brk) +char **q,*brk; +{ + register char *front,*back; + front = *q; /* start of string */ + /* leading blanks and tabs */ + while (*front && (*front == ' ' || *front == '\t')) front++; + /* find break character at end */ + if (brk == 0) brk = " "; + back = skipto (front,brk); + _argbreak = *back; + *q = (*back ? back+1 : back); /* next arg start loc */ + /* elim trailing blanks and tabs */ + back -= 1; + while ((back >= front) && (*back == ' ' || *back == '\t')) back--; + back++; + if (*back) *back = '\0'; + return (front); +} diff --git a/usr.bin/sup/src/path.c b/usr.bin/sup/src/path.c new file mode 100644 index 00000000000..f9822689dc8 --- /dev/null +++ b/usr.bin/sup/src/path.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* path -- break filename into directory and file + * + * path (filename,direc,file); + * char *filename,*direc,*file; + * filename is input; direc and file are output (user-supplied). + * file will not have any trailing /; direc might. + * + * Note these rules: + * 1. trailing / are ignored (except as first character) + * 2. x/y is x;y where y contains no / (x may contain /) + * 3. /y is /;y where y contains no / + * 4. y is .;y where y contains no / + * 5. is .;. (null filename) + * 6. / is /;. (the root directory) + * + * Algorithm is this: + * 1. delete trailing / except in first position + * 2. if any /, find last one; change to null; y++ + * else y = x; (x is direc; y is file) + * 3. if y is null, y = . + * 4. if x equals y, x = . + * else if x is null, x = / + * + * HISTORY + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Copied verbatim from PDP-11. Still as messy as ever. + * Some people have asked for a modification (I think that's a better + * idea than a new routine) which will change the directory name + * into an absolute pathname if it isn't one already. The change + * involves doing a getwd() and prepending that if appropriate, with + * a "/" in between that and the directory part of the path. + * If you want to be cute, you can also resolve ".."s at that time. + * + */ + +path (original,direc,file) +char *original,*direc,*file; +{ + register char *y; + /* x is direc */ + register char *p; + + /* copy and note the end */ + p = original; + y = direc; + while (*y++ = *p++) ; /* copy string */ + /* y now points to first char after null */ + --y; /* y now points to null */ + --y; /* y now points to last char of string before null */ + + /* chop off trailing / except as first character */ + while (y>direc && *y == '/') --y; /* backpedal past / */ + /* y now points to char before first trailing / or null */ + *(++y) = 0; /* chop off end of string */ + /* y now points to null */ + + /* find last /, if any. If found, change to null and bump y */ + while (y>direc && *y != '/') --y; + /* y now points to / or direc. Note *direc may be / */ + if (*y == '/') { + *y++ = 0; + } + + /* find file name part */ + if (*y) strcpy (file,y); + else strcpy (file,"."); + + /* find directory part */ + if (direc == y) strcpy (direc,"."); + else if (*direc == 0) strcpy (direc,"/"); + /* else direc already has proper value */ +} diff --git a/usr.bin/sup/src/quit.c b/usr.bin/sup/src/quit.c new file mode 100644 index 00000000000..e867c8b2d6a --- /dev/null +++ b/usr.bin/sup/src/quit.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + * quit -- print message and exit + * + * Usage: quit (status,format [,arg]...); + * int status; + * (... format and arg[s] make up a printf-arglist) + * + * Quit is a way to easily print an arbitrary message and exit. + * It is most useful for error exits from a program: + * if (open (...) < 0) then quit (1,"Can't open...",file); + * + ********************************************************************** + * HISTORY + * $Log: quit.c,v $ + * Revision 1.1 1995/12/16 11:46:49 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.2 88/12/13 13:52:41 gm0w + * Rewritten to use varargs. + * [88/12/13 gm0w] + * + ********************************************************************** + */ + +#include <stdio.h> +#include <varargs.h> + +quit (status, fmt, va_alist) +int status; +char *fmt; +va_dcl +{ + va_list args; + + fflush(stdout); + va_start(args); + (void) vfprintf(stderr, fmt, args); + va_end(args); + exit(status); +} diff --git a/usr.bin/sup/src/run.c b/usr.bin/sup/src/run.c new file mode 100644 index 00000000000..7f625c1d27c --- /dev/null +++ b/usr.bin/sup/src/run.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* run, runv, runp, runvp -- execute process and wait for it to exit + * + * Usage: + * i = run (file, arg1, arg2, ..., argn, 0); + * i = runv (file, arglist); + * i = runp (file, arg1, arg2, ..., argn, 0); + * i = runvp (file, arglist); + * i = runio (argv, in, out, err); + * + * Run, runv, runp and runvp have argument lists exactly like the + * corresponding routines, execl, execv, execlp, execvp. The run + * routines perform a fork, then: + * IN THE NEW PROCESS, an execl[p] or execv[p] is performed with the + * specified arguments. The process returns with a -1 code if the + * exec was not successful. + * IN THE PARENT PROCESS, the signals SIGQUIT and SIGINT are disabled, + * the process waits until the newly forked process exits, the + * signals are restored to their original status, and the return + * status of the process is analyzed. + * All run routines return: -1 if the exec failed or if the child was + * terminated abnormally; otherwise, the exit code of the child is + * returned. + * + ********************************************************************** + * HISTORY + * $Log: run.c,v $ + * Revision 1.1 1995/12/16 11:46:49 deraadt + * add sup to the tree + * + * Revision 1.2 1995/06/24 16:21:33 christos + * - Don't use system(3) to fork processes. It is a big security hole. + * - Encode the filenames in the scan files using strvis(3), so filenames + * that contain newlines or other weird characters don't break the scanner. + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.1 89/10/14 19:53:39 rvb + * Initial revision + * + * Revision 1.2 89/08/03 14:36:46 mja + * Update run() and runp() to use <varargs.h>. + * [89/04/19 mja] + * + * 23-Sep-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Merged old runv and runvp modules. + * + * 22-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added check and kill if child process was stopped. + * + * 30-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University + * Adapted for 4.2 BSD UNIX: Conforms to new signals and wait. + * + * 15-July-82 Mike Accetta (mja) and Neal Friedman (naf) + * at Carnegie-Mellon University + * Added a return(-1) if vfork fails. This should only happen + * if there are no more processes available. + * + * 28-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University + * Added setuid and setgid for system programs' use. + * + * 21-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University + * Changed fork to vfork. + * + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Created for VAX. The proper way to fork-and-execute a system + * program is now by "runvp" or "runp", with the program name + * (rather than an absolute pathname) as the first argument; + * that way, the "PATH" variable in the environment does the right + * thing. Too bad execvp and execlp (hence runvp and runp) don't + * accept a pathlist as an explicit argument. + * + ********************************************************************** + */ + +#include <stdio.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/wait.h> +#include <varargs.h> + +#ifndef __STDC__ +#ifndef const +#define const +#endif +#endif + +static int dorun(); + +int run (name,va_alist) +char *name; +va_dcl +{ + int val; + va_list ap; + + va_start(ap); + val = runv (name,ap); + va_end(ap); + return(val); +} + +int runv (name,argv) +char *name,**argv; +{ + return (dorun (name, argv, 0)); +} + +int runp (name,va_alist) +char *name; +va_dcl +{ + int val; + va_list ap; + + va_start(ap); + val = runvp (name,ap); + va_end(ap); + return (val); +} + +int runvp (name,argv) +char *name,**argv; +{ + return (dorun (name, argv, 1)); +} + +static +int dorun (name,argv,usepath) +char *name,**argv; +int usepath; +{ + int wpid; + register int pid; + struct sigvec ignoresig,intsig,quitsig; + union wait status; + int execvp(), execv(); + int (*execrtn)() = usepath ? execvp : execv; + + if ((pid = vfork()) == -1) + return(-1); /* no more process's, so exit with error */ + + if (pid == 0) { /* child process */ + setgid (getgid()); + setuid (getuid()); + (*execrtn) (name,argv); + fprintf (stderr,"run: can't exec %s\n",name); + _exit (0377); + } + + ignoresig.sv_handler = SIG_IGN; /* ignore INT and QUIT signals */ + ignoresig.sv_mask = 0; + ignoresig.sv_onstack = 0; + sigvec (SIGINT,&ignoresig,&intsig); + sigvec (SIGQUIT,&ignoresig,&quitsig); + do { + wpid = wait3 (&status.w_status, WUNTRACED, 0); + if (WIFSTOPPED (status)) { + kill (0,SIGTSTP); + wpid = 0; + } + } while (wpid != pid && wpid != -1); + sigvec (SIGINT,&intsig,0); /* restore signals */ + sigvec (SIGQUIT,&quitsig,0); + + if (WIFSIGNALED (status) || status.w_retcode == 0377) + return (-1); + + return (status.w_retcode); +} + +/* + * Like system(3), but with an argument list and explicit redirections + * that does not use the shell + */ +int +runio(argv, infile, outfile, errfile) + char *const argv[]; + const char *infile; + const char *outfile; + const char *errfile; +{ + int fd; + pid_t pid; + int status; + + switch ((pid = fork())) { + case -1: + return -1; + + case 0: + if (infile) { + (void) close(0); + if ((fd = open(infile, O_RDONLY)) == -1) + exit(1); + if (fd != 0) + (void) dup2(fd, 0); + } + + if (outfile) { + (void) close(1); + if ((fd = open(outfile, O_RDWR|O_CREAT|O_TRUNC, + 0666)) == -1) + exit(1); + if (fd != 1) + (void) dup2(fd, 1); + } + + if (errfile) { + (void) close(2); + if ((fd = open(errfile, O_RDWR|O_CREAT|O_TRUNC, + 0666)) == -1) + exit(1); + if (fd != 2) + (void) dup2(fd, 2); + } + + execvp(argv[0], argv); + exit(1); + /*NOTREACHED*/ + return 0; + + default: + if (waitpid(pid, &status, 0) == -1) + return -1; + return status; + } +} diff --git a/usr.bin/sup/src/salloc.c b/usr.bin/sup/src/salloc.c new file mode 100644 index 00000000000..bd0e804251f --- /dev/null +++ b/usr.bin/sup/src/salloc.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + ********************************************************************** + * HISTORY + * 09-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed to save length and use bcopy instead of strcpy. + * + * 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created from routine by same name in Steve Shafer's sup program. + * + ********************************************************************** + */ +char *malloc(); + +char *salloc(p) +char *p; +{ + register char *q; + register int l; + + q = malloc(l = strlen(p) + 1); + if (q != 0) + bcopy(p, q, l); + return(q); +} diff --git a/usr.bin/sup/src/scan.c b/usr.bin/sup/src/scan.c new file mode 100644 index 00000000000..8e634e291bd --- /dev/null +++ b/usr.bin/sup/src/scan.c @@ -0,0 +1,1024 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * scan.c - sup list file scanner + * + ********************************************************************** + * HISTORY + * $Log: scan.c,v $ + * Revision 1.1 1995/12/16 11:46:50 deraadt + * add sup to the tree + * + * Revision 1.4 1995/10/29 23:54:45 christos + * - runio fails when result != 0 not only < 0 + * - print vis-encoded file in the scanner. + * + * Revision 1.3 1995/06/24 16:21:42 christos + * - Don't use system(3) to fork processes. It is a big security hole. + * - Encode the filenames in the scan files using strvis(3), so filenames + * that contain newlines or other weird characters don't break the scanner. + * + * Revision 1.2 1994/01/03 14:47:25 brezak + * Change <sys/dir.h> to <dirent.h> + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.8 92/08/11 12:04:28 mrt + * Brad's changes: delinted, added forward declarations of static + * functions.Added Copyright. + * [92/07/24 mrt] + * + * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added host=<hostfile> support to releases file. + * + * 11-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added "rsymlink" recursive symbolic link quoting directive. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Lets see if we'll be able to write the scan file BEFORE + * we collect the data for it. Include sys/file.h and use + * new definitions for access check codes. + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added type casting information for lint. + * + * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added check for newonly upgrade when lasttime is the same as + * scantime. This will save us the trouble of parsing the scanfile + * when the client has successfully received everything in the + * scanfile already. + * + * 16-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Clear Texec pointers in execT so that Tfree of execT will not + * free command trees associated with files in listT. + * + * 06-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to omit scanned files from list if we want new files + * only and they are old. + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Major rewrite for protocol version 4. Added version numbers to + * scan file. Also added mode of file in addition to flags. + * Execute commands are now immediately after file information. + * + * 13-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added comments to list file format. + * + * 08-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to implement omitany. Currently doesn't know about + * {a,b,c} patterns. + * + * 07-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +#include <libc.h> +#include <c.h> +#include <vis.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/stat.h> +#ifdef HAS_POSIX_DIR +#include <dirent.h> +#else +#include <sys/dir.h> +#endif +#include <sys/file.h> +#include "sup.h" + +/************************* + *** M A C R O S *** + *************************/ + +#define SPECNUMBER 1000 + /* number of filenames produced by a single spec in the list file */ + +/******************************************* + *** D A T A S T R U C T U R E S *** + *******************************************/ + +typedef enum { /* release options */ + ONEXT, OPREFIX, OLIST, OSCAN, + OHOST +} OPTION; + +static char *options[] = { + "next", "prefix", "list", "scan", + "host", + 0 +}; + +typedef enum { /* <collection>/list file lines */ + LUPGRADE, LOMIT, LBACKUP, LEXECUTE, + LINCLUDE, LNOACCT, LOMITANY, LALWAYS, + LSYMLINK, LRSYMLINK +} LISTTYPE; + +static char *ltname[] = { + "upgrade", "omit", "backup", "execute", + "include", "noaccount", "omitany", "always", + "symlink", "rsymlink", + 0 +}; + +#define FALWAYS FUPDATE + +/* list file lines */ +static TREE *upgT; /* files to upgrade */ +static TREE *flagsT; /* special flags: BACKUP NOACCT */ +static TREE *omitT; /* recursize file omition list */ +static TREE *omanyT; /* non-recursize file omition list */ +static TREE *symT; /* symbolic links to quote */ +static TREE *rsymT; /* recursive symbolic links to quote */ +static TREE *execT; /* execute command list */ + +/************************* + *** E X T E R N *** + *************************/ + +#ifdef lint +static char _argbreak; +#else +extern char _argbreak; /* break character from nxtarg */ +#endif + +extern TREELIST *listTL; /* list of trees for scanning */ +extern TREE *listT; /* final list of files in collection */ +extern TREE *refuseT; /* files refused by client */ + +extern char *collname; /* collection name */ +extern char *basedir; /* base directory name */ +extern char *prefix; /* collection pathname prefix */ +extern long lasttime; /* time of last upgrade */ +extern long scantime; /* time of this scan */ +extern int trace; /* trace directories */ +extern int newonly; /* new files only */ + +#ifdef RCSSTAT +extern char *rcs_branch; +extern int candorcs; +#endif + +extern long time(); + +/************************************************* + *** STATIC R O U T I N E S *** + *************************************************/ + +static makescan(); +static getscan(); +static doscan(); +static readlistfile(); +static expTinsert(); +static listone(); +static listentry(); +static listname(); +static listdir(); +static omitanyone(); +static anyglob(); +static int getscanfile(); +static chkscanfile(); +static makescanfile(); +static recordone(); +static recordexec(); + +/************************************************* + *** L I S T S C A N R O U T I N E S *** + *************************************************/ + +static +passdelim (ptr,delim) /* skip over delimiter */ +char **ptr,delim; +{ + *ptr = skipover (*ptr, " \t"); + if (_argbreak != delim && **ptr == delim) { + (*ptr)++; + *ptr = skipover (*ptr, " \t"); + } +} + +static +char *parserelease(tlp,relname,args) +TREELIST **tlp; +char *relname,*args; +{ + register TREELIST *tl; + register char *arg; + register OPTION option; + int opno; + char *nextrel; + + tl = (TREELIST *) malloc (sizeof(TREELIST)); + if ((*tlp = tl) == NULL) + goaway ("Couldn't allocate TREELIST"); + tl->TLnext = NULL; + tl->TLname = salloc (relname); + tl->TLprefix = NULL; + tl->TLlist = NULL; + tl->TLscan = NULL; + tl->TLhost = NULL; + nextrel = NULL; + args = skipover (args," \t"); + while (*(arg=nxtarg(&args," \t="))) { + for (opno = 0; options[opno] != NULL; opno++) + if (strcmp (arg,options[opno]) == 0) + break; + if (options[opno] == NULL) + goaway ("Invalid release option %s for release %s", + arg,relname); + option = (OPTION) opno; + switch (option) { + case ONEXT: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + nextrel = salloc (arg); + break; + case OPREFIX: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLprefix = salloc (arg); + break; + case OLIST: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLlist = salloc (arg); + break; + case OSCAN: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLscan = salloc (arg); + break; + case OHOST: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLhost = salloc (arg); + break; + } + } + return (nextrel); +} + +getrelease (release) +char *release; +{ + TREELIST *tl; + char buf[STRINGLENGTH]; + char *p,*q; + int rewound; + FILE *f; + + if (release == NULL) + release = salloc (DEFRELEASE); + listTL = NULL; + + (void) sprintf (buf,FILERELEASES,collname); + f = fopen (buf,"r"); + if (f != NULL) { + rewound = TRUE; + for (;;) { + p = fgets (buf,sizeof(buf),f); + if (p == NULL) { + if (rewound) + break; + rewind (f); + rewound = TRUE; + continue; + } + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + if (strcmp (q,release) != 0) + continue; + release = parserelease (&tl,release,p); + if (tl->TLprefix == NULL) + tl->TLprefix = prefix; + else if (chdir (tl->TLprefix) < 0) + return (FALSE); + else + (void) chdir (basedir); + tl->TLnext = listTL; + listTL = tl; + if (release == NULL) + break; + rewound = FALSE; + } + (void) fclose (f); + } + if (release == NULL) + return (TRUE); + if (strcmp (release,DEFRELEASE) != 0) + return (FALSE); + (void) parserelease (&tl,release,""); + tl->TLprefix = prefix; + tl->TLnext = listTL; + listTL = tl; + return (TRUE); +} + +makescanlists () +{ + TREELIST *tl; + char buf[STRINGLENGTH]; + char *p,*q; + FILE *f; + char *saveprefix = prefix; + int count = 0; + + (void) sprintf (buf,FILERELEASES,collname); + f = fopen (buf,"r"); + if (f != NULL) { + while (p = fgets (buf,sizeof(buf),f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + (void) parserelease (&tl,q,p); + if ((prefix = tl->TLprefix) == NULL) + prefix = saveprefix; + if (prefix != NULL) { + if (chdir (prefix) < 0) + goaway ("Can't chdir to %s",prefix); + (void) chdir (basedir); + } + makescan (tl->TLlist,tl->TLscan); + free ((char *)tl); + count++; + } + (void) fclose (f); + } + if (count == 0) + makescan ((char *)NULL,(char *)NULL); +} + +static +scanone (t) +register TREE *t; +{ + register TREE *newt; + + if (newonly && (t->Tflags&FNEW) == 0) + return (SCMOK); + newt = Tinsert (&listT,t->Tname,FALSE); + if (newt == NULL) + return (SCMOK); + newt->Tmode = t->Tmode; + newt->Tflags = t->Tflags; + newt->Tmtime = t->Tmtime; + return (SCMOK); +} + +getscanlists () +{ + TREELIST *tl,*stl; + + stl = listTL; + listTL = NULL; + while ((tl = stl) != NULL) { + prefix = tl->TLprefix; + getscan (tl->TLlist,tl->TLscan); + tl->TLtree = listT; + stl = tl->TLnext; + tl->TLnext = listTL; + listTL = tl; + } + listT = NULL; + for (tl = listTL; tl != NULL; tl = tl->TLnext) + (void) Tprocess (tl->TLtree,scanone); +} + +static +makescan (listfile,scanfile) +char *listfile,*scanfile; +{ + listT = NULL; + chkscanfile (scanfile); /* can we can write a scan file? */ + doscan (listfile); /* read list file and scan disk */ + makescanfile (scanfile); /* record names in scan file */ + Tfree (&listT); /* free file list tree */ +} + +static +getscan (listfile,scanfile) +char *listfile,*scanfile; +{ + struct tm *utc_time; + + listT = NULL; + if (!getscanfile(scanfile)) { /* check for pre-scanned file list */ + scantime = time ((long *)NULL); + doscan (listfile); /* read list file and scan disk */ + } +} + +static +doscan (listfile) + char *listfile; +{ + char buf[STRINGLENGTH]; + int listone (); + + upgT = NULL; + flagsT = NULL; + omitT = NULL; + omanyT = NULL; + execT = NULL; + symT = NULL; + rsymT = NULL; + if (listfile == NULL) + listfile = FILELISTDEF; + (void) sprintf (buf,FILELIST,collname,listfile); + readlistfile (buf); /* get contents of list file */ + (void) Tprocess (upgT,listone); /* build list of files specified */ + cdprefix ((char *)NULL); + Tfree (&upgT); + Tfree (&flagsT); + Tfree (&omitT); + Tfree (&omanyT); + Tfree (&execT); + Tfree (&symT); + Tfree (&rsymT); +} + +static +readlistfile (fname) +char *fname; +{ + char buf[STRINGLENGTH+MAXPATHLEN*4+1],*p; + register char *q,*r; + register FILE *f; + register int ltn,n,i,flags; + register TREE **t; + register LISTTYPE lt; + char *speclist[SPECNUMBER]; + + f = fopen (fname,"r"); + if (f == NULL) goaway ("Can't read list file %s",fname); + cdprefix (prefix); + while (p = fgets (buf,sizeof(buf),f)) { + if (q = index (p,'\n')) *q = '\0'; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + if (*q == '\0') continue; + for (ltn = 0; ltname[ltn] && strcmp(q,ltname[ltn]) != 0; ltn++); + if (ltname[ltn] == NULL) + goaway ("Invalid list file keyword %s",q); + lt = (LISTTYPE) ltn; + flags = 0; + switch (lt) { + case LUPGRADE: + t = &upgT; + break; + case LBACKUP: + t = &flagsT; + flags = FBACKUP; + break; + case LNOACCT: + t = &flagsT; + flags = FNOACCT; + break; + case LSYMLINK: + t = &symT; + break; + case LRSYMLINK: + t = &rsymT; + break; + case LOMIT: + t = &omitT; + break; + case LOMITANY: + t = &omanyT; + break; + case LALWAYS: + t = &upgT; + flags = FALWAYS; + break; + case LINCLUDE: + while (*(q=nxtarg(&p," \t"))) { + cdprefix ((char *)NULL); + n = expand (q,speclist,SPECNUMBER); + for (i = 0; i < n && i < SPECNUMBER; i++) { + readlistfile (speclist[i]); + cdprefix ((char *)NULL); + free (speclist[i]); + } + cdprefix (prefix); + } + continue; + case LEXECUTE: + r = p = q = skipover (p," \t"); + do { + q = p = skipto (p," \t("); + p = skipover (p," \t"); + } while (*p != '(' && *p != '\0'); + if (*p++ == '(') { + *q = '\0'; + do { + q = nxtarg (&p," \t)"); + if (*q == 0) + _argbreak = ')'; + else + expTinsert (q,&execT,0,r); + } while (_argbreak != ')'); + continue; + } + /* fall through */ + default: + goaway ("Error in handling list file keyword %d",ltn); + } + while (*(q=nxtarg(&p," \t"))) { + if (lt == LOMITANY) + (void) Tinsert (t,q,FALSE); + else + expTinsert (q,t,flags,(char *)NULL); + } + } + (void) fclose (f); +} + +static +expTinsert (p,t,flags,exec) +char *p; +TREE **t; +int flags; +char *exec; +{ + register int n, i; + register TREE *newt; + char *speclist[SPECNUMBER]; + char buf[STRINGLENGTH]; + + n = expand (p,speclist,SPECNUMBER); + for (i = 0; i < n && i < SPECNUMBER; i++) { + newt = Tinsert (t,speclist[i],TRUE); + newt->Tflags |= flags; + if (exec) { + (void) sprintf (buf,exec,speclist[i]); + (void) Tinsert (&newt->Texec,buf,FALSE); + } + free (speclist[i]); + } +} + +static +listone (t) /* expand and add one name from upgrade list */ +TREE *t; +{ + listentry(t->Tname,t->Tname,(char *)NULL,(t->Tflags&FALWAYS) != 0); + return (SCMOK); +} + +static +listentry(name,fullname,updir,always) +register char *name, *fullname, *updir; +int always; +{ + struct stat statbuf; + int link = 0; + int omitanyone (); + + if (Tlookup (refuseT,fullname)) return; + if (!always) { + if (Tsearch (omitT,fullname)) return; + if (Tprocess (omanyT,omitanyone,fullname) != SCMOK) + return; + } + if (lstat(name,&statbuf) < 0) + return; + if ((statbuf.st_mode&S_IFMT) == S_IFLNK) { + if (Tsearch (symT,fullname)) { + listname (fullname,&statbuf); + return; + } + if (Tlookup (rsymT,fullname)) { + listname (fullname,&statbuf); + return; + } + if (updir) link++; + if (stat(name,&statbuf) < 0) return; + } + if ((statbuf.st_mode&S_IFMT) == S_IFDIR) { + if (access(name,R_OK|X_OK) < 0) return; + if (chdir(name) < 0) return; + listname (fullname,&statbuf); + if (trace) { + printf ("Scanning directory %s\n",fullname); + (void) fflush (stdout); + } + listdir (fullname,always); + if (updir == 0 || link) { + (void) chdir (basedir); + if (prefix) (void) chdir (prefix); + if (updir && *updir) (void) chdir (updir); + } else + (void) chdir (".."); + return; + } + if (access(name,R_OK) < 0) return; +#ifdef RCSSTAT + if (candorcs) { + char rcs_release[STRINGLENGTH]; + int status; + if (rcs_branch != NULL) +#ifdef CVS + sprintf(rcs_release, "-r %s", rcs_branch); +#else + sprintf(rcs_release, "-r%s", rcs_branch); +#endif + else + rcs_release[0] = '\0'; +#ifdef CVS + sprintf(sys_com, "cvs -d %s -r -l -Q co -p %s %s > %s\n", cvs_root, rcs_release, name, rcs_file); +#else + status = runp("rcsstat", "rcsstat", "-q", rcs_release, name, 0); +#endif + if (status != 0) return; + } +#endif + listname (fullname,&statbuf); +} + +static +listname (name,st) +register char *name; +register struct stat *st; +{ + register TREE *t,*ts; + register int new; + register TREELIST *tl; + + new = st->st_ctime > lasttime; + if (newonly && !new) { + for (tl = listTL; tl != NULL; tl = tl->TLnext) + if (ts = Tsearch (tl->TLtree,name)) + ts->Tflags &= ~FNEW; + return; + } + t = Tinsert (&listT,name,FALSE); + if (t == NULL) return; + t->Tmode = st->st_mode; + t->Tctime = st->st_ctime; + t->Tmtime = st->st_mtime; + if (new) t->Tflags |= FNEW; + if (ts = Tsearch (flagsT,name)) + t->Tflags |= ts->Tflags; + if (ts = Tsearch (execT,name)) { + t->Texec = ts->Texec; + ts->Texec = NULL; + } +} + +static +listdir (name,always) /* expand directory */ +char *name; +int always; +{ +#ifdef HAS_POSIX_DIR + struct dirent *dentry; +#else + struct direct *dentry; +#endif + register DIR *dirp; + char ename[STRINGLENGTH],newname[STRINGLENGTH],filename[STRINGLENGTH]; + register char *p,*newp; + register int i; + + dirp = opendir ("."); + if (dirp == 0) return; /* unreadable: probably protected */ + + p = name; /* punt leading ./ and trailing / */ + newp = newname; + if (p[0] == '.' && p[1] == '/') { + p += 2; + while (*p == '/') p++; + } + while (*newp++ = *p++) ; /* copy string */ + --newp; /* trailing null */ + while (newp > newname && newp[-1] == '/') --newp; /* trailing / */ + *newp = 0; + if (strcmp (newname,".") == 0) newname[0] = 0; /* "." ==> "" */ + + while (dentry=readdir(dirp)) { + if (dentry->d_ino == 0) continue; + if (strcmp(dentry->d_name,".") == 0) continue; + if (strcmp(dentry->d_name,"..") == 0) continue; + for (i=0; i<=MAXNAMLEN && dentry->d_name[i]; i++) + ename[i] = dentry->d_name[i]; + ename[i] = 0; + if (*newname) + (void) sprintf (filename,"%s/%s",newname,ename); + else + (void) strcpy (filename,ename); + listentry(ename,filename,newname,always); + } + closedir (dirp); +} + +static +omitanyone (t,filename) +TREE *t; +char **filename; +{ + if (anyglob (t->Tname,*filename)) + return (SCMERR); + return (SCMOK); +} + +static +anyglob (pattern,match) +char *pattern,*match; +{ + register char *p,*m; + register char *pb,*pe; + + p = pattern; + m = match; + while (*m && *p == *m ) { + p++; + m++; + } + if (*p == '\0' && *m == '\0') + return (TRUE); + switch (*p++) { + case '*': + for (;;) { + if (*p == '\0') + return (TRUE); + if (*m == '\0') + return (*p == '\0'); + if (anyglob (p,++m)) + return (TRUE); + } + case '?': + return (anyglob (p,++m)); + case '[': + pb = p; + while (*(++p) != ']') + if (*p == '\0') + return (FALSE); + pe = p; + for (p = pb + 1; p != pe; p++) { + switch (*p) { + case '-': + if (p == pb && *m == '-') { + p = pe + 1; + return (anyglob (p,++m)); + } + if (p == pb) + continue; + if ((p + 1) == pe) + return (FALSE); + if (*m > *(p - 1) && + *m <= *(p + 1)) { + p = pe + 1; + return (anyglob (p,++m)); + } + continue; + default: + if (*m == *p) { + p = pe + 1; + return (anyglob (p,++m)); + } + } + } + return (FALSE); + default: + return (FALSE); + } +} + +/***************************************** + *** R E A D S C A N F I L E *** + *****************************************/ + +static +int getscanfile (scanfile) +char *scanfile; +{ + char buf[STRINGLENGTH]; + char fname[MAXPATHLEN]; + struct stat sbuf; + register FILE *f; + TREE ts; + register char *p,*q; + register TREE *tmp, *t = NULL; + register notwanted; + register TREELIST *tl; + + if (scanfile == NULL) + scanfile = FILESCANDEF; + (void) sprintf (buf,FILESCAN,collname,scanfile); + if (stat(buf,&sbuf) < 0) + return (FALSE); + if ((f = fopen (buf,"r")) == NULL) + return (FALSE); + if ((p = fgets (buf,sizeof(buf),f)) == NULL) { + (void) fclose (f); + return (FALSE); + } + if (q = index (p,'\n')) *q = '\0'; + if (*p++ != 'V') { + (void) fclose (f); + return (FALSE); + } + if (atoi (p) != SCANVERSION) { + (void) fclose (f); + return (FALSE); + } + scantime = sbuf.st_mtime; /* upgrade time is time of supscan, + * i.e. time of creation of scanfile */ + if (newonly && scantime == lasttime) { + (void) fclose (f); + return (TRUE); + } + notwanted = FALSE; + while (p = fgets (buf,sizeof(buf),f)) { + q = index (p,'\n'); + if (q) *q = 0; + ts.Tflags = 0; + if (*p == 'X') { + if (notwanted) continue; + if (t == NULL) + goaway ("scanfile format inconsistant"); + (void) Tinsert (&t->Texec,++p,FALSE); + continue; + } + notwanted = FALSE; + if (*p == 'B') { + p++; + ts.Tflags |= FBACKUP; + } + if (*p == 'N') { + p++; + ts.Tflags |= FNOACCT; + } + if ((q = index (p,' ')) == NULL) + goaway ("scanfile format inconsistant"); + *q++ = '\0'; + ts.Tmode = atoo (p); + p = q; + if ((q = index (p,' ')) == NULL) + goaway ("scanfile format inconsistant"); + *q++ = '\0'; + ts.Tctime = atoi (p); + p = q; + if ((q = index (p,' ')) == NULL) + goaway ("scanfile format inconsistant"); + *q++ = 0; + ts.Tmtime = atoi (p); + (void) strunvis(fname, q); + if (ts.Tctime > lasttime) + ts.Tflags |= FNEW; + else if (newonly) { + for (tl = listTL; tl != NULL; tl = tl->TLnext) + if (tmp = Tsearch (tl->TLtree,fname)) + tmp->Tflags &= ~FNEW; + notwanted = TRUE; + continue; + } + if (Tlookup (refuseT,fname)) { + notwanted = TRUE; + continue; + } + t = Tinsert (&listT,fname,TRUE); + t->Tmode = ts.Tmode; + t->Tflags = ts.Tflags; + t->Tctime = ts.Tctime; + t->Tmtime = ts.Tmtime; + } + (void) fclose (f); + return (TRUE); +} + +/******************************************* + *** W R I T E S C A N F I L E *** + *******************************************/ + +static chkscanfile (scanfile) +char *scanfile; +{ + char tname[STRINGLENGTH], fname[STRINGLENGTH]; + FILE *f; + + if (scanfile == NULL) + scanfile = FILESCANDEF; + (void) sprintf (fname,FILESCAN,collname,scanfile); + (void) sprintf (tname,"%s.temp",fname); + if (NULL == (f = fopen (tname, "w"))) + goaway ("Can't test scan file temp %s for %s",tname,collname); + else { + (void) unlink (tname); + (void) fclose (f); + } +} + +static makescanfile (scanfile) +char *scanfile; +{ + char tname[STRINGLENGTH],fname[STRINGLENGTH]; + struct timeval tbuf[2]; + FILE *scanF; /* output file for scanned file list */ + int recordone (); + + if (scanfile == NULL) + scanfile = FILESCANDEF; + (void) sprintf (fname,FILESCAN,collname,scanfile); + (void) sprintf (tname,"%s.temp",fname); + scanF = fopen (tname,"w"); + if (scanF == NULL) + goaway ("Can't write scan file temp %s for %s",tname,collname); + fprintf (scanF,"V%d\n",SCANVERSION); + (void) Tprocess (listT,recordone,scanF); + (void) fclose (scanF); + if (rename (tname,fname) < 0) + goaway ("Can't change %s to %s",tname,fname); + (void) unlink (tname); + tbuf[0].tv_sec = time((long *)NULL); tbuf[0].tv_usec = 0; + tbuf[1].tv_sec = scantime; tbuf[1].tv_usec = 0; + (void) utimes (fname,tbuf); +} + +static +recordone (t,scanF) +TREE *t; +FILE **scanF; +{ + int recordexec (); + char fname[MAXPATHLEN*4+1]; + + if (t->Tflags&FBACKUP) fprintf (*scanF,"B"); + if (t->Tflags&FNOACCT) fprintf (*scanF,"N"); + strvis(fname, t->Tname, VIS_WHITE); + fprintf (*scanF,"%o %d %d %s\n", + t->Tmode,t->Tctime,t->Tmtime,fname); + (void) Tprocess (t->Texec,recordexec,*scanF); + return (SCMOK); +} + +static +recordexec (t,scanF) +TREE *t; +FILE **scanF; +{ + char fname[MAXPATHLEN*4+1]; + strvis(fname, t->Tname, VIS_WHITE); + fprintf(*scanF,"X%s\n",fname); + return (SCMOK); +} + +cdprefix (prefix) +char *prefix; +{ + static char *curprefix = NULL; + + if (curprefix == NULL) { + if (prefix == NULL) + return; + (void) chdir (prefix); + curprefix = prefix; + return; + } + if (prefix == NULL) { + (void) chdir (basedir); + curprefix = NULL; + return; + } + if (prefix == curprefix) + return; + if (strcmp (prefix, curprefix) == 0) { + curprefix = prefix; + return; + } + (void) chdir (basedir); + (void) chdir (prefix); + curprefix = prefix; +} diff --git a/usr.bin/sup/src/scm.c b/usr.bin/sup/src/scm.c new file mode 100644 index 00000000000..59be450716d --- /dev/null +++ b/usr.bin/sup/src/scm.c @@ -0,0 +1,593 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * SUP Communication Module for 4.3 BSD + * + * SUP COMMUNICATION MODULE SPECIFICATIONS: + * + * IN THIS MODULE: + * + * CONNECTION ROUTINES + * + * FOR SERVER + * servicesetup (port) establish TCP port connection + * char *port; name of service + * service () accept TCP port connection + * servicekill () close TCP port in use by another process + * serviceprep () close temp ports used to make connection + * serviceend () close TCP port + * + * FOR CLIENT + * request (port,hostname,retry) establish TCP port connection + * char *port,*hostname; name of service and host + * int retry; true if retries should be used + * requestend () close TCP port + * + * HOST NAME CHECKING + * p = remotehost () remote host name (if known) + * char *p; + * i = samehost () whether remote host is also this host + * int i; + * i = matchhost (name) whether remote host is same as name + * int i; + * char *name; + * + * RETURN CODES + * All procedures return values as indicated above. Other routines + * normally return SCMOK on success, SCMERR on error. + * + * COMMUNICATION PROTOCOL + * + * Described in scmio.c. + * + ********************************************************************** + * HISTORY + * 2-Oct-92 Mary Thompson (mrt) at Carnegie-Mellon University + * Added conditional declarations of INADDR_NONE and INADDR_LOOPBACK + * since Tahoe version of <netinet/in.h> does not define them. + * + * $Log: scm.c,v $ + * Revision 1.1 1995/12/16 11:46:51 deraadt + * add sup to the tree + * + * Revision 1.2 1995/06/03 21:21:51 christos + * Changes to write ascii timestamps in the when files. + * Looked into making it 64 bit clean, but it is hopeless. + * Added little program to convert from the old timestamp files + * into the new ones. + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.13 92/08/11 12:05:35 mrt + * Added changes from stump: + * Allow for multiple interfaces, and for numeric addresses. + * Changed to use builtin port for the "supfiledbg" + * service when getservbyname() cannot find it. + * Added forward static declatations, delinted. + * Updated variable argument usage. + * [92/08/08 mrt] + * + * Revision 1.12 92/02/08 19:01:11 mja + * Add (struct sockaddr *) casts for HC 2.1. + * [92/02/08 18:59:09 mja] + * + * Revision 1.11 89/08/03 19:49:03 mja + * Updated to use v*printf() in place of _doprnt(). + * [89/04/19 mja] + * + * 11-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Moved sleep into computeBackoff, renamed to dobackoff. + * + * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added timeout to backoff. + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed nameserver support. + * + * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fixed to depend less upon having name of remote host. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon Universtiy + * Extracted backoff/sleeptime computation from "request" and + * created "computeBackoff" so that I could use it in sup.c when + * trying to get to nameservers as a group. + * + * 21-May-87 Chriss Stephens (chriss) at Carnegie Mellon University + * Merged divergent CS and EE versions. + * + * 02-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added some bullet-proofing code around hostname calls. + * + * 31-Mar-87 Dan Nydick (dan) at Carnegie-Mellon University + * Fixed for 4.3. + * + * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to use known values for well-known ports if they are + * not found in the host table. + * + * 19-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed setsockopt SO_REUSEADDR to be non-fatal. Added fourth + * parameter as described in 4.3 manual entry. + * + * 15-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added call of readflush() to requestend() routine. + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Major rewrite for protocol version 4. All read/write and crypt + * routines are now in scmio.c. + * + * 14-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added setsockopt SO_REUSEADDR call. + * + * 01-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed code to "gracefully" handle unexpected messages. This + * seems reasonable since it didn't work anyway, and should be + * handled at a higher level anyway by adhering to protocol version + * number conventions. + * + * 26-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fixed scm.c to free space for remote host name when connection + * is closed. + * + * 07-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fixed 4.2 retry code to reload sin values before retry. + * + * 22-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to retry initial connection open request. + * + * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Merged 4.1 and 4.2 versions together. + * + * 21-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Add close() calls after pipe() call. + * + * 12-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University + * Converted for 4.2 sockets; added serviceprep() routine. + * + * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University + * Created for 4.2 BSD. + * + ********************************************************************** + */ + +#include <libc.h> +#include <errno.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <netdb.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "sup.h" + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff /* -1 return */ +#endif +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7f000001 /* 127.0.0.1 */ +#endif + +extern int errno; +static char *myhost (); + +char scmversion[] = "4.3 BSD"; + +/************************* + *** M A C R O S *** + *************************/ + +/* networking parameters */ +#define NCONNECTS 5 + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +extern char program[]; /* name of program we are running */ +extern int progpid; /* process id to display */ + +int netfile = -1; /* network file descriptor */ + +static int sock = -1; /* socket used to make connection */ +static struct in_addr remoteaddr; /* remote host address */ +static char *remotename = NULL; /* remote host name */ +static int swapmode; /* byte-swapping needed on server? */ + +#if __STDC__ +int scmerr(int,char *,...); +#endif + +/*************************************************** + *** C O N N E C T I O N R O U T I N E S *** + *** F O R S E R V E R *** + ***************************************************/ + +servicesetup (server) /* listen for clients */ +char *server; +{ + struct sockaddr_in sin; + struct servent *sp; + short port; + int one = 1; + + if (myhost () == NULL) + return (scmerr (-1,"Local hostname not known")); + if ((sp = getservbyname(server,"tcp")) == 0) { + if (strcmp(server, FILEPORT) == 0) + port = htons((u_short)FILEPORTNUM); + else if (strcmp(server, DEBUGFPORT) == 0) + port = htons((u_short)DEBUGFPORTNUM); + else + return (scmerr (-1,"Can't find %s server description",server)); + (void) scmerr (-1,"%s/tcp: unknown service: using port %d", + server,port); + } else + port = sp->s_port; + endservent (); + sock = socket (AF_INET,SOCK_STREAM,0); + if (sock < 0) + return (scmerr (errno,"Can't create socket for connections")); + if (setsockopt (sock,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) + (void) scmerr (errno,"Can't set SO_REUSEADDR socket option"); + (void) bzero ((char *)&sin,sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = port; + if (bind (sock,(struct sockaddr *)&sin,sizeof(sin)) < 0) + return (scmerr (errno,"Can't bind socket for connections")); + if (listen (sock,NCONNECTS) < 0) + return (scmerr (errno,"Can't listen on socket")); + return (SCMOK); +} + +service () +{ + struct sockaddr_in from; + int x,len; + + remotename = NULL; + len = sizeof (from); + do { + netfile = accept (sock,(struct sockaddr *)&from,&len); + } while (netfile < 0 && errno == EINTR); + if (netfile < 0) + return (scmerr (errno,"Can't accept connections")); + remoteaddr = from.sin_addr; + if (read(netfile,(char *)&x,sizeof(int)) != sizeof(int)) + return (scmerr (errno,"Can't transmit data on connection")); + if (x == 0x01020304) + swapmode = 0; + else if (x == 0x04030201) + swapmode = 1; + else + return (scmerr (-1,"Unexpected byteswap mode %x",x)); + return (SCMOK); +} + +serviceprep () /* kill temp socket in daemon */ +{ + if (sock >= 0) { + (void) close (sock); + sock = -1; + } + return (SCMOK); +} + +servicekill () /* kill net file in daemon's parent */ +{ + if (netfile >= 0) { + (void) close (netfile); + netfile = -1; + } + if (remotename) { + free (remotename); + remotename = NULL; + } + return (SCMOK); +} + +serviceend () /* kill net file after use in daemon */ +{ + if (netfile >= 0) { + (void) close (netfile); + netfile = -1; + } + if (remotename) { + free (remotename); + remotename = NULL; + } + return (SCMOK); +} + +/*************************************************** + *** C O N N E C T I O N R O U T I N E S *** + *** F O R C L I E N T *** + ***************************************************/ + +dobackoff (t,b) +int *t,*b; +{ + struct timeval tt; + unsigned s; + + if (*t == 0) + return (0); + s = *b * 30; + if (gettimeofday (&tt,(struct timezone *)NULL) >= 0) + s += (tt.tv_usec >> 8) % s; + if (*b < 32) *b <<= 1; + if (*t != -1) { + if (s > *t) + s = *t; + *t -= s; + } + (void) scmerr (-1,"Will retry in %d seconds",s); + sleep (s); + return (1); +} + +request (server,hostname,retry) /* connect to server */ +char *server; +char *hostname; +int *retry; +{ + int x, backoff; + struct hostent *h; + struct servent *sp; + struct sockaddr_in sin, tin; + short port; + + if ((sp = getservbyname(server,"tcp")) == 0) { + if (strcmp(server, FILEPORT) == 0) + port = htons((u_short)FILEPORTNUM); + else if (strcmp(server, DEBUGFPORT) == 0) + port = htons((u_short)DEBUGFPORTNUM); + else + return (scmerr (-1,"Can't find %s server description", + server)); + (void) scmerr (-1,"%s/tcp: unknown service: using port %d", + server,port); + } else + port = sp->s_port; + (void) bzero ((char *)&sin,sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr (hostname); + if (sin.sin_addr.s_addr == (u_long) INADDR_NONE) { + if ((h = gethostbyname (hostname)) == NULL) + return (scmerr (-1,"Can't find host entry for %s", + hostname)); + hostname = h->h_name; + (void) bcopy (h->h_addr,(char *)&sin.sin_addr,h->h_length); + } + sin.sin_port = port; + backoff = 1; + for (;;) { + netfile = socket (AF_INET,SOCK_STREAM,0); + if (netfile < 0) + return (scmerr (errno,"Can't create socket")); + tin = sin; + if (connect(netfile,(struct sockaddr *)&tin,sizeof(tin)) >= 0) + break; + (void) scmerr (errno,"Can't connect to server for %s",server); + (void) close(netfile); + if (!dobackoff (retry,&backoff)) + return (SCMERR); + } + remoteaddr = sin.sin_addr; + remotename = salloc(hostname); + x = 0x01020304; + (void) write (netfile,(char *)&x,sizeof(int)); + swapmode = 0; /* swap only on server, not client */ + return (SCMOK); +} + +requestend () /* end connection to server */ +{ + (void) readflush (); + if (netfile >= 0) { + (void) close (netfile); + netfile = -1; + } + if (remotename) { + free (remotename); + remotename = NULL; + } + return (SCMOK); +} + +/************************************************* + *** H O S T N A M E C H E C K I N G *** + *************************************************/ + +static +char *myhost () /* find my host name */ +{ + struct hostent *h; + static char name[MAXHOSTNAMELEN]; + + + if (name[0] == '\0') { + if (gethostname (name,MAXHOSTNAMELEN) < 0) + return (NULL); + if ((h = gethostbyname (name)) == NULL) + return (NULL); + (void) strcpy (name,h->h_name); + } + return (name); +} + +char *remotehost () /* remote host name (if known) */ +{ + register struct hostent *h; + + if (remotename == NULL) { + h = gethostbyaddr ((char *)&remoteaddr,sizeof(remoteaddr), + AF_INET); + remotename = salloc (h ? h->h_name : inet_ntoa(remoteaddr)); + if (remotename == NULL) + return("UNKNOWN"); + } + return (remotename); +} + +int thishost (host) +register char *host; +{ + register struct hostent *h; + char *name; + + if ((name = myhost ()) == NULL) + logquit (1,"Can't find my host entry"); + h = gethostbyname (host); + if (h == NULL) return (0); + return (strcasecmp (name,h->h_name) == 0); +} + +int samehost () /* is remote host same as local host? */ +{ + static struct in_addr *intp; + static int nint = 0; + struct in_addr *ifp; + int n; + + if (nint <= 0) { + int s; + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq *ifr; + struct sockaddr_in sin; + + if ((s = socket (AF_INET,SOCK_DGRAM,0)) < 0) + logquit (1,"Can't create socket for SIOCGIFCONF"); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl (s,SIOCGIFCONF,(char *)&ifc) < 0) + logquit (1,"SIOCGIFCONF failed"); + (void) close(s); + if ((nint = ifc.ifc_len/sizeof(struct ifreq)) <= 0) + return (0); + intp = (struct in_addr *) + malloc ((unsigned) nint*sizeof(struct in_addr)); + if ((ifp = intp) == 0) + logquit (1,"no space for interfaces"); + for (ifr = ifc.ifc_req, n = nint; n > 0; --n, ifr++) { + (void) bcopy ((char *)&ifr->ifr_addr,(char *)&sin,sizeof(sin)); + *ifp++ = sin.sin_addr; + } + } + if (remoteaddr.s_addr == htonl(INADDR_LOOPBACK)) + return (1); + for (ifp = intp, n = nint; n > 0; --n, ifp++) + if (remoteaddr.s_addr == ifp->s_addr) + return (1); + return (0); +} + +int matchhost (name) /* is this name of remote host? */ +char *name; +{ + struct hostent *h; + struct in_addr addr; + char **ap; + if ((addr.s_addr = inet_addr(name)) != (u_long) INADDR_NONE) + return (addr.s_addr == remoteaddr.s_addr); + if ((h = gethostbyname (name)) == 0) + return (0); + if (h->h_addrtype != AF_INET || h->h_length != sizeof(struct in_addr)) + return (0); + for (ap = h->h_addr_list; *ap; ap++) + if (bcmp ((char *)&remoteaddr,*ap,h->h_length) == 0) + return (1); + return (0); +} + +#if __STDC__ +int scmerr (int errno,char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +int scmerr (va_alist) +va_dcl +#endif +{ +#if !__STDC__ + int errno; + char *fmt; +#endif + va_list ap; + + (void) fflush (stdout); + if (progpid > 0) + fprintf (stderr,"%s %d: ",program,progpid); + else + fprintf (stderr,"%s: ",program); +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + errno = va_arg(ap,int); + fmt = va_arg(ap,char *); +#endif + vfprintf(stderr, fmt, ap); + va_end(ap); + if (errno >= 0) + fprintf (stderr,": %s\n",errmsg(errno)); + else + fprintf (stderr,"\n"); + (void) fflush (stderr); + return (SCMERR); +} + +/******************************************************* + *** I N T E G E R B Y T E - S W A P P I N G *** + *******************************************************/ + +union intchar { + int ui; + char uc[sizeof(int)]; +}; + +int byteswap (in) +int in; +{ + union intchar x,y; + register int ix,iy; + + if (swapmode == 0) return (in); + x.ui = in; + iy = sizeof(int); + for (ix=0; ix<sizeof(int); ix++) { + --iy; + y.uc[iy] = x.uc[ix]; + } + return (y.ui); +} diff --git a/usr.bin/sup/src/scmio.c b/usr.bin/sup/src/scmio.c new file mode 100644 index 00000000000..b0852e2d9de --- /dev/null +++ b/usr.bin/sup/src/scmio.c @@ -0,0 +1,744 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * SUP Communication Module for 4.3 BSD + * + * SUP COMMUNICATION MODULE SPECIFICATIONS: + * + * IN THIS MODULE: + * + * OUTPUT TO NETWORK + * + * MESSAGE START/END + * writemsg (msg) start message + * int msg; message type + * writemend () end message and flush data to network + * + * MESSAGE DATA + * writeint (i) write int + * int i; integer to write + * writestring (p) write string + * char *p; string pointer + * writefile (f) write open file + * int f; open file descriptor + * + * COMPLETE MESSAGE (start, one data block, end) + * writemnull (msg) write message with no data + * int msg; message type + * writemint (msg,i) write int message + * int msg; message type + * int i; integer to write + * writemstr (msg,p) write string message + * int msg; message type + * char *p; string pointer + * + * INPUT FROM NETWORK + * MESSAGE START/END + * readflush () flush any unread data (close) + * readmsg (msg) read specified message type + * int msg; message type + * readmend () read message end + * + * MESSAGE DATA + * readskip () skip over one input data block + * readint (i) read int + * int *i; pointer to integer + * readstring (p) read string + * char **p; pointer to string pointer + * readfile (f) read into open file + * int f; open file descriptor + * + * COMPLETE MESSAGE (start, one data block, end) + * readmnull (msg) read message with no data + * int msg; message type + * readmint (msg,i) read int message + * int msg; message type + * int *i; pointer to integer + * readmstr (msg,p) read string message + * int msg; message type + * char **p; pointer to string pointer + * + * RETURN CODES + * All routines normally return SCMOK. SCMERR may be returned + * by any routine on abnormal (usually fatal) errors. An + * unexpected MSGGOAWAY will result in SCMEOF being returned. + * + * COMMUNICATION PROTOCOL + * Messages always alternate, with the first message after + * connecting being sent by the client process. + * + * At the end of the conversation, the client process will + * send a message to the server telling it to go away. Then, + * both processes will close the network connection. + * + * Any time a process receives a message it does not expect, + * the "readmsg" routine will send a MSGGOAWAY message and + * return SCMEOF. + * + * Each message has this format: + * ---------- ------------ ------------ ---------- + * |msg type| |count|data| |count|data| ... |ENDCOUNT| + * ---------- ------------ ------------ ---------- + * size: int int var. int var. int + * + * All ints are assumed to be 32-bit quantities. A message + * with no data simply has a message type followed by ENDCOUNT. + * + ********************************************************************** + * HISTORY + * $Log: scmio.c,v $ + * Revision 1.1 1995/12/16 11:46:52 deraadt + * add sup to the tree + * + * Revision 1.2 1993/05/24 17:57:26 brezak + * Remove netcrypt.c. Remove unneeded files. Cleanup make. + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.7 92/09/09 22:04:41 mrt + * Removed the data encryption routines from here to netcrypt.c + * [92/09/09 mrt] + * + * Revision 1.6 92/08/11 12:05:57 mrt + * Brad's changes: Delinted,Added forward declarations of + * static functions. Added copyright. + * [92/07/24 mrt] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Found error in debuging code for readint(). + * + * 01-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to readdata to "push" data back into the data buffer. + * Added prereadcount() to return the message count size after + * reading it and then pushing it back into the buffer. Clear + * any encryption when a GOAWAY message is detected before reading + * the reason string. [V5.19] + * + * 02-Oct-86 Rudy Nedved (ern) at Carnegie-Mellon University + * Put a timeout on reading from the network. + * + * 25-May-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University + * Renamed "howmany" parameter to routines "encode" and "decode" from + * to "count" to avoid conflict with 4.3BSD macro. + * + * 15-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added readflush() to flush any unread data from the input + * buffer. Called by requestend() in scm.c module. + * + * 19-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added register variables to decode() for speedup. Added I/O + * buffering to reduce the number or read/write system calls. + * Removed readmfil/writemfil routines which were not used and were + * not compatable with the other similarly defined routines anyway. + * + * 19-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created from scm.c I/O and crypt routines. + * + ********************************************************************** + */ + +#include <libc.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/time.h> +#include "sup.h" +#include "supmsg.h" + +extern int errno; + +/************************* + *** M A C R O S *** + *************************/ + +/* end of message */ +#define ENDCOUNT (-1) /* end of message marker */ +#define NULLCOUNT (-2) /* used for sending NULL pointer */ + +#define RETRIES 15 /* # of times to retry io */ +#define FILEXFER 2048 /* block transfer size */ +#define XFERSIZE(count) ((count > FILEXFER) ? FILEXFER : count) + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +extern int scmerr (); /* error printing routine */ +extern int netfile; /* network file descriptor */ + +int scmdebug; /* scm debug flag */ + +int cryptflag; /* whether to encrypt/decrypt data */ +char *cryptbuf; /* buffer for data encryption/decryption */ + +extern char *goawayreason; /* reason for goaway message */ + +struct buf { + char b_data[FILEXFER]; /* buffered data */ + char *b_ptr; /* pointer to end of buffer */ + int b_cnt; /* number of bytes in buffer */ +} buffers[2]; +struct buf *bufptr; /* buffer pointer */ + + +/*********************************************** + *** O U T P U T T O N E T W O R K *** + ***********************************************/ + +static +writedata (count,data) /* write raw data to network */ +int count; +char *data; +{ + register int x,tries; + register struct buf *bp; + + if (bufptr) { + if (bufptr->b_cnt + count <= FILEXFER) { + bcopy (data,bufptr->b_ptr,count); + bufptr->b_cnt += count; + bufptr->b_ptr += count; + return (SCMOK); + } + bp = (bufptr == buffers) ? &buffers[1] : buffers; + bcopy (data,bp->b_data,count); + bp->b_cnt = count; + bp->b_ptr = bp->b_data + count; + data = bufptr->b_data; + count = bufptr->b_cnt; + bufptr->b_cnt = 0; + bufptr->b_ptr = bufptr->b_data; + bufptr = bp; + } + tries = 0; + for (;;) { + errno = 0; + x = write (netfile,data,count); + if (x > 0) break; + if (errno) break; + if (++tries > RETRIES) break; + if (scmdebug > 0) + logerr ("SCM Retrying failed network write"); + } + if (x <= 0) { + if (errno == EPIPE) + return (scmerr (-1,"Network write timed out")); + if (errno) + return (scmerr (errno,"Write error on network")); + return (scmerr (-1,"Write retries failed")); + } + if (x != count) + return (scmerr (-1,"Write error on network returned %d on write of %d",x,count)); + return (SCMOK); +} + +static +writeblock (count,data) /* write data block */ +int count; +char *data; +{ + register int x; + int y = byteswap(count); + + x = writedata (sizeof(int),(char *)&y); + if (x == SCMOK) x = writedata (count,data); + return (x); +} + +writemsg (msg) /* write start of message */ +int msg; +{ + int x; + + if (scmdebug > 1) + loginfo ("SCM Writing message %d",msg); + if (bufptr) + return (scmerr (-1,"Buffering already enabled")); + bufptr = buffers; + bufptr->b_ptr = bufptr->b_data; + bufptr->b_cnt = 0; + x = byteswap (msg); + return (writedata(sizeof(int),(char *)&x)); +} + +writemend () /* write end of message */ +{ + register int count; + register char *data; + int x; + + x = byteswap (ENDCOUNT); + x = writedata (sizeof(int),(char *)&x); + if (x != SCMOK) return (x); + if (bufptr == NULL) + return (scmerr (-1,"Buffering already disabled")); + if (bufptr->b_cnt == 0) { + bufptr = NULL; + return (SCMOK); + } + data = bufptr->b_data; + count = bufptr->b_cnt; + bufptr = NULL; + return (writedata (count, data)); +} + +writeint (i) /* write int as data block */ +int i; +{ + int x; + if (scmdebug > 2) + loginfo ("SCM Writing integer %d",i); + x = byteswap(i); + return (writeblock(sizeof(int),(char *)&x)); +} + +writestring (p) /* write string as data block */ +char *p; +{ + register int len,x; + if (p == NULL) { + int y = byteswap(NULLCOUNT); + if (scmdebug > 2) + loginfo ("SCM Writing string NULL"); + return (writedata (sizeof(int),(char *)&y)); + } + if (scmdebug > 2) + loginfo ("SCM Writing string %s",p); + len = strlen (p); + if (cryptflag) { + x = getcryptbuf (len+1); + if (x != SCMOK) + return (x); + encode (p,cryptbuf,len); + p = cryptbuf; + } + return (writeblock(len,p)); +} + +writefile (f) /* write open file as a data block */ +int f; +{ + char buf[FILEXFER]; + register int number,sum,filesize,x; + int y; + struct stat statbuf; + + if (fstat(f,&statbuf) < 0) + return (scmerr (errno,"Can't access open file for message")); + filesize = statbuf.st_size; + y = byteswap(filesize); + x = writedata (sizeof(int),(char *)&y); + + if (cryptflag) x = getcryptbuf (FILEXFER); + + if (x == SCMOK) { + sum = 0; + do { + number = read (f,buf,FILEXFER); + if (number > 0) { + if (cryptflag) { + encode (buf,cryptbuf,number); + x = writedata (number,cryptbuf); + } + else { + x = writedata (number,buf); + } + sum += number; + } + } while (x == SCMOK && number > 0); + } + if (sum != filesize) + return (scmerr (-1,"File size error on output message")); + if (number < 0) + return (scmerr (errno,"Read error on file output message")); + return (x); +} + +writemnull (msg) /* write message with no data */ +int msg; +{ + register int x; + x = writemsg (msg); + if (x == SCMOK) x = writemend (); + return (x); +} + +writemint (msg,i) /* write message of one int */ +int msg,i; +{ + register int x; + x = writemsg (msg); + if (x == SCMOK) x = writeint (i); + if (x == SCMOK) x = writemend (); + return (x); +} + +writemstr (msg,p) /* write message of one string */ +int msg; +char *p; +{ + register int x; + x = writemsg (msg); + if (x == SCMOK) x = writestring (p); + if (x == SCMOK) x = writemend (); + return (x); +} + +/************************************************* + *** I N P U T F R O M N E T W O R K *** + *************************************************/ + +static +readdata (count,data) /* read raw data from network */ +int count; +char *data; +{ + register char *p; + register int n,m,x; + int tries; + static int bufcnt = 0; + static char *bufptr; + static char buffer[FILEXFER]; + static int imask; + static struct timeval timout; + + if (count < 0) { + if (bufptr + count < buffer) + return (scmerr (-1,"No space in buffer %d",count)); + bufptr += count; + bufcnt -= count; + bcopy (data,bufptr,-count); + return (SCMOK); + } + if (count == 0 && data == NULL) { + bufcnt = 0; + return (SCMOK); + } + if (count <= bufcnt) { + bcopy (bufptr,data,count); + bufptr += count; + bufcnt -= count; + return (SCMOK); + } + if (bufcnt > 0) { + bcopy (bufptr,data,bufcnt); + data += bufcnt; + count -= bufcnt; + } + bufptr = buffer; + bufcnt = 0; + timout.tv_usec = 0; + timout.tv_sec = 2*60*60; + p = buffer; + n = FILEXFER; + m = count; + while (m > 0) { + tries = 0; + for (;;) { + imask = 1 << netfile; + if (select(32,(fd_set *)&imask,(fd_set *)0,(fd_set *)0,&timout) < 0) + imask = 1; + errno = 0; + if (imask) + x = read (netfile,p,n); + else + return (scmerr (-1,"Timeout on network input")); + if (x > 0) break; + if (x == 0) + return (scmerr (-1,"Premature EOF on network input")); + if (errno) break; + if (++tries > RETRIES) break; + if (scmdebug > 0) + loginfo ("SCM Retrying failed network read"); + } + if (x < 0) { + if (errno) + return (scmerr (errno,"Read error on network")); + return (scmerr (-1,"Read retries failed")); + } + p += x; + n -= x; + m -= x; + bufcnt += x; + } + bcopy (bufptr,data,count); + bufptr += count; + bufcnt -= count; + return (SCMOK); +} + +static +int readcount (count) /* read count of data block */ +int *count; +{ + register int x; + int y; + x = readdata (sizeof(int),(char *)&y); + if (x != SCMOK) return (x); + *count = byteswap(y); + return (SCMOK); +} + +int prereadcount (count) /* preread count of data block */ +int *count; +{ + register int x; + int y; + x = readdata (sizeof(int),(char *)&y); + if (x != SCMOK) return (x); + x = readdata (-sizeof(int),(char *)&y); + if (x != SCMOK) return (x); + *count = byteswap(y); + return (SCMOK); +} + +readflush () +{ + return (readdata (0, (char *)NULL)); +} + +readmsg (msg) /* read header for expected message */ +int msg; /* if message is unexpected, send back SCMHUH */ +{ + register int x; + int m; + if (scmdebug > 1) + loginfo ("SCM Reading message %d",msg); + x = readdata (sizeof(int),(char *)&m); /* msg type */ + if (x != SCMOK) return (x); + m = byteswap(m); + if (m == msg) return (x); + + /* check for MSGGOAWAY in case he noticed problems first */ + if (m != MSGGOAWAY) + return (scmerr (-1,"Received unexpected message %d",m)); + (void) netcrypt ((char *)NULL); + (void) readstring (&goawayreason); + (void) readmend (); + if (goawayreason == NULL) + return (SCMEOF); + logerr ("SCM GOAWAY %s",goawayreason); + return (SCMEOF); +} + +readmend () +{ + register int x; + int y; + x = readdata (sizeof(int),(char *)&y); + y = byteswap(y); + if (x == SCMOK && y != ENDCOUNT) + return (scmerr (-1,"Error reading end of message")); + return (x); +} + +readskip () /* skip over one input block */ +{ + register int x; + int n; + char buf[FILEXFER]; + x = readcount (&n); + if (x != SCMOK) return (x); + if (n < 0) + return (scmerr (-1,"Invalid message count %d",n)); + while (x == SCMOK && n > 0) { + x = readdata (XFERSIZE(n),buf); + n -= XFERSIZE(n); + } + return (x); +} + +int readint (buf) /* read int data block */ +int *buf; +{ + register int x; + int y; + x = readcount (&y); + if (x != SCMOK) return (x); + if (y < 0) + return (scmerr (-1,"Invalid message count %d",y)); + if (y != sizeof(int)) + return (scmerr (-1,"Size error for int message is %d",y)); + x = readdata (sizeof(int),(char *)&y); + (*buf) = byteswap(y); + if (scmdebug > 2) + loginfo ("SCM Reading integer %d",*buf); + return (x); +} + +int readstring (buf) /* read string data block */ +register char **buf; +{ + register int x; + int count; + register char *p; + + x = readcount (&count); + if (x != SCMOK) return (x); + if (count == NULLCOUNT) { + if (scmdebug > 2) + loginfo ("SCM Reading string NULL"); + *buf = NULL; + return (SCMOK); + } + if (count < 0) + return (scmerr (-1,"Invalid message count %d",count)); + if (scmdebug > 3) + loginfo ("SCM Reading string count %d",count); + if ((p = (char *)malloc ((unsigned)count+1)) == NULL) + return (scmerr (-1,"Can't malloc %d bytes for string",count)); + if (cryptflag) { + x = getcryptbuf (count+1); + if (x == SCMOK) x = readdata (count,cryptbuf); + if (x != SCMOK) return (x); + if (scmdebug > 3) + printf ("SCM Reading encrypted string %s\n",cryptbuf); + decode (cryptbuf,p,count); + } + else { + x = readdata (count,p); + if (x != SCMOK) return (x); + } + p[count] = 0; /* NULL at end of string */ + *buf = p; + if (scmdebug > 2) + loginfo ("SCM Reading string %s",*buf); + return (SCMOK); +} + +readfile (f) /* read data block into open file */ +int f; +{ + register int x; + int count; + char buf[FILEXFER]; + + if (cryptflag) { + x = getcryptbuf (FILEXFER); + if (x != SCMOK) return (x); + } + x = readcount (&count); + if (x != SCMOK) return (x); + if (count < 0) + return (scmerr (-1,"Invalid message count %d",count)); + while (x == SCMOK && count > 0) { + if (cryptflag) { + x = readdata (XFERSIZE(count),cryptbuf); + if (x == SCMOK) decode (cryptbuf,buf,XFERSIZE(count)); + } + else + x = readdata (XFERSIZE(count),buf); + if (x == SCMOK) { + (void) write (f,buf,XFERSIZE(count)); + count -= XFERSIZE(count); + } + } + return (x); +} + +readmnull (msg) /* read null message */ +int msg; +{ + register int x; + x = readmsg (msg); + if (x == SCMOK) x = readmend (); + return (x); +} + +readmint (msg,buf) /* read int message */ +int msg,*buf; +{ + register int x; + x = readmsg (msg); + if (x == SCMOK) x = readint (buf); + if (x == SCMOK) x = readmend (); + return (x); +} + +int readmstr (msg,buf) /* read string message */ +int msg; +char **buf; +{ + register int x; + x = readmsg (msg); + if (x == SCMOK) x = readstring (buf); + if (x == SCMOK) x = readmend (); + return (x); +} + +/********************************** + *** C R O S S P A T C H *** + **********************************/ + +crosspatch () +{ + fd_set ibits, obits, xbits; + register int c; + char buf[STRINGLENGTH]; + + for (;;) { + FD_ZERO (&ibits); + FD_ZERO (&obits); + FD_ZERO (&xbits); + FD_SET (0,&ibits); + FD_SET (netfile,&ibits); + if ((c = select(16, &ibits, &obits, &xbits, + (struct timeval *)NULL)) < 1) { + if (c == -1) { + if (errno == EINTR) { + continue; + } + } + sleep (5); + continue; + } + if (FD_ISSET (netfile,&ibits)) { + c = read (netfile,buf,sizeof (buf)); + if (c < 0 && errno == EWOULDBLOCK) + c = 0; + else { + if (c <= 0) { + break; + } + (void) write (1,buf,c); + } + } + if (FD_ISSET(0, &ibits)) { + c = read (0,buf,sizeof (buf)); + if (c < 0 && errno == EWOULDBLOCK) + c = 0; + else { + if (c <= 0) + break; + (void) write (netfile,buf,c); + } + } + } +} diff --git a/usr.bin/sup/src/skipto.c b/usr.bin/sup/src/skipto.c new file mode 100644 index 00000000000..2fa5a4f4022 --- /dev/null +++ b/usr.bin/sup/src/skipto.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/************************************************************************ + * skipover and skipto -- skip over characters in string + * + * Usage: p = skipto (string,charset); + * p = skipover (string,charset); + * + * char *p,*charset,*string; + * + * Skipto returns a pointer to the first character in string which + * is in the string charset; it "skips until" a character in charset. + * Skipover returns a pointer to the first character in string which + * is not in the string charset; it "skips over" characters in charset. + ************************************************************************ + * HISTORY + * 26-Jun-81 David Smith (drs) at Carnegie-Mellon University + * Skipover, skipto rewritten to avoid inner loop at expense of space. + * + * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University + * Skipover, skipto adapted for VAX from skip() and skipx() on the PDP-11 + * (from Ken Greer). The names are more mnemonic. + * + * Sindex adapted for VAX from indexs() on the PDP-11 (thanx to Ralph + * Guggenheim). The name has changed to be more like the index() + * and rindex() functions from Bell Labs; the return value (pointer + * rather than integer) has changed partly for the same reason, + * and partly due to popular usage of this function. + */ + +static unsigned char tab[256] = { + 0}; + +char *skipto (string,charset) +unsigned char *string, *charset; +{ + register unsigned char *setp,*strp; + + tab[0] = 1; /* Stop on a null, too. */ + for (setp=charset; *setp; setp++) tab[*setp]=1; + for (strp=string; tab[*strp]==0; strp++) ; + for (setp=charset; *setp; setp++) tab[*setp]=0; + return ((char *)strp); +} + +char *skipover (string,charset) +unsigned char *string, *charset; +{ + register unsigned char *setp,*strp; + + tab[0] = 0; /* Do not skip over nulls. */ + for (setp=charset; *setp; setp++) tab[*setp]=1; + for (strp=string; tab[*strp]; strp++) ; + for (setp=charset; *setp; setp++) tab[*setp]=0; + return ((char *)strp); +} diff --git a/usr.bin/sup/src/stree.c b/usr.bin/sup/src/stree.c new file mode 100644 index 00000000000..125c37e50e9 --- /dev/null +++ b/usr.bin/sup/src/stree.c @@ -0,0 +1,357 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * stree.c -- SUP Tree Routines + * + ********************************************************************** + * HISTORY + * $Log: stree.c,v $ + * Revision 1.1 1995/12/16 11:46:53 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.4 92/08/11 12:06:32 mrt + * Added copyright. Delinted + * [92/08/10 mrt] + * + * + * Revision 1.3 89/08/15 15:30:57 bww + * Changed code in Tlookup to Tsearch for each subpart of path. + * Added indent formatting code to Tprint. + * From "[89/06/24 gm0w]" at CMU. + * [89/08/15 bww] + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to please lint. + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to initialize new fields. Added Tfree routine. + * + * 27-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +#include <libc.h> +#include <c.h> +#include <sys/param.h> +#include "sup.h" + +#define Static /* static /* comment for debugging */ + +/************************************************************* + *** T R E E P R O C E S S I N G R O U T I N E S *** + *************************************************************/ + +Tfree (t) +register TREE **t; +{ + if (*t == NULL) return; + Tfree (&((*t)->Tlink)); + Tfree (&((*t)->Texec)); + Tfree (&((*t)->Tlo)); + Tfree (&((*t)->Thi)); + if ((*t)->Tname) free ((*t)->Tname); + if ((*t)->Tuser) free ((*t)->Tuser); + if ((*t)->Tgroup) free ((*t)->Tgroup); + free (*(char **)t); + *t = NULL; +} + +Static +TREE *Tmake (p) +char *p; +{ + register TREE *t; + t = (TREE *) malloc (sizeof (TREE)); + t->Tname = (p == NULL) ? NULL : salloc (p); + t->Tflags = 0; + t->Tuid = 0; + t->Tgid = 0; + t->Tuser = NULL; + t->Tgroup = NULL; + t->Tmode = 0; + t->Tctime = 0; + t->Tmtime = 0; + t->Tlink = NULL; + t->Texec = NULL; + t->Tbf = 0; + t->Tlo = NULL; + t->Thi = NULL; + return (t); +} + +Static +TREE *Trotll (tp,tl) +register TREE *tp,*tl; +{ + tp->Tlo = tl->Thi; + tl->Thi = tp; + tp->Tbf = tl->Tbf = 0; + return(tl); +} + +Static +TREE *Trotlh (tp,tl) +register TREE *tp,*tl; +{ + register TREE *th; + + th = tl->Thi; + tp->Tlo = th->Thi; + tl->Thi = th->Tlo; + th->Thi = tp; + th->Tlo = tl; + tp->Tbf = tl->Tbf = 0; + if (th->Tbf == 1) + tp->Tbf = -1; + else if (th->Tbf == -1) + tl->Tbf = 1; + th->Tbf = 0; + return(th); +} + +Static +TREE *Trothl (tp,th) +register TREE *tp,*th; +{ + register TREE *tl; + + tl = th->Tlo; + tp->Thi = tl->Tlo; + th->Tlo = tl->Thi; + tl->Tlo = tp; + tl->Thi = th; + tp->Tbf = th->Tbf = 0; + if (tl->Tbf == -1) + tp->Tbf = 1; + else if (tl->Tbf == 1) + th->Tbf = -1; + tl->Tbf = 0; + return(tl); +} + +Static +TREE *Trothh (tp,th) +register TREE *tp,*th; +{ + tp->Thi = th->Tlo; + th->Tlo = tp; + tp->Tbf = th->Tbf = 0; + return(th); +} + +Static +Tbalance (t) +TREE **t; +{ + if ((*t)->Tbf < 2 && (*t)->Tbf > -2) + return; + if ((*t)->Tbf > 0) { + if ((*t)->Tlo->Tbf > 0) + *t = Trotll(*t, (*t)->Tlo); + else + *t = Trotlh(*t, (*t)->Tlo); + } else { + if ((*t)->Thi->Tbf > 0) + *t = Trothl(*t, (*t)->Thi); + else + *t = Trothh(*t, (*t)->Thi); + } +} + +Static +TREE *Tinsertavl (t,p,find,dh) +TREE **t; +char *p; +int find; +int *dh; +{ + register TREE *newt; + register int cmp; + int deltah; + + if (*t == NULL) { + *t = Tmake (p); + *dh = 1; + return (*t); + } + if ((cmp = strcmp(p, (*t)->Tname)) == 0) { + if (!find) return (NULL); /* node already exists */ + *dh = 0; + return (*t); + } else if (cmp < 0) { + if ((newt = Tinsertavl (&((*t)->Tlo),p,find,&deltah)) == NULL) + return (NULL); + (*t)->Tbf += deltah; + } else { + if ((newt = Tinsertavl (&((*t)->Thi),p,find,&deltah)) == NULL) + return (NULL); + (*t)->Tbf -= deltah; + } + Tbalance(t); + if ((*t)->Tbf == 0) deltah = 0; + *dh = deltah; + return (newt); +} + +TREE *Tinsert (t,p,find) +TREE **t; +register char *p; +int find; +{ + int deltah; + + if (p != NULL && p[0] == '.' && p[1] == '/') { + p += 2; + while (*p == '/') p++; + if (*p == 0) p = "."; + } + return (Tinsertavl (t,p,find,&deltah)); +} + +TREE *Tsearch (t,p) +TREE *t; +char *p; +{ + register TREE *x; + register int cmp; + + x = t; + while (x) { + cmp = strcmp (p,x->Tname); + if (cmp == 0) return (x); + if (cmp < 0) x = x->Tlo; + else x = x->Thi; + } + return (NULL); +} + +TREE *Tlookup (t,p) +TREE *t; +char *p; +{ + register TREE *x; + char buf[MAXPATHLEN+1]; + + if (p == NULL) + return (NULL); + if (p[0] == '.' && p[1] == '/') { + p += 2; + while (*p == '/') p++; + if (*p == 0) p = "."; + } + if ((x = Tsearch (t,p)) != NULL) + return (x); + if (*p != '/' && (x = Tsearch (t,".")) != NULL) + return (x); + (void) strncpy(buf, p, sizeof(buf)-1); + buf[MAXPATHLEN] = '\0'; + while ((p = rindex(buf, '/')) != NULL) { + while (p >= buf && *(p-1) == '/') + p--; + if (p == buf) + *(p+1) = '\0'; + else + *p = '\0'; + if ((x = Tsearch (t,buf)) != NULL) + return (x); + if (p == buf) + break; + } + return (NULL); +} + +Static int process_level; + +Static +int Tsubprocess (t,reverse,f,argp) +TREE *t; +int reverse; +int (*f)(); +int *argp; +{ + register int x = SCMOK; + process_level++; + if (reverse?t->Thi:t->Tlo) + x = Tsubprocess (reverse?t->Thi:t->Tlo, + reverse,f,argp); + if (x == SCMOK) { + x = (*f) (t,argp); + if (x == SCMOK) { + if (reverse?t->Tlo:t->Thi) + x = Tsubprocess (reverse?t->Tlo:t->Thi, + reverse,f,argp); + } + } + process_level--; + return (x); +} + +/* VARARGS2 */ +int Trprocess (t,f,args) +TREE *t; +int (*f)(); +int args; +{ + if (t == NULL) return (SCMOK); + process_level = 0; + return (Tsubprocess (t,TRUE,f,&args)); +} + +/* VARARGS2 */ +int Tprocess (t,f,args) +TREE *t; +int (*f)(); +int args; +{ + if (t == NULL) return (SCMOK); + process_level = 0; + return (Tsubprocess (t,FALSE,f,&args)); +} + +Static +int Tprintone (t) +TREE *t; +{ + int i; + for (i = 0; i < (process_level*2); i++) + (void) putchar(' '); + printf ("Node at %X name '%s' flags %o hi %X lo %X\n",t,t->Tname,t->Tflags,t->Thi,t->Tlo); + return (SCMOK); +} + +Tprint (t,p) /* print tree -- for debugging */ +TREE *t; +char *p; +{ + printf ("%s\n",p); + (void) Tprocess (t,Tprintone); + printf ("End of tree\n"); + (void) fflush (stdout); +} diff --git a/usr.bin/sup/src/sup.1 b/usr.bin/sup/src/sup.1 new file mode 100644 index 00000000000..f3999e024d6 --- /dev/null +++ b/usr.bin/sup/src/sup.1 @@ -0,0 +1,862 @@ +.\" Copyright (c) 1992 Carnegie Mellon University +.\" All Rights Reserved. +.\" +.\" Permission to use, copy, modify and distribute this software and its +.\" documentation is hereby granted, provided that both the copyright +.\" notice and this permission notice appear in all copies of the +.\" software, derivative works or modified versions, and any portions +.\" thereof, and that both notices appear in supporting documentation. +.\" +.\" CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +.\" CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +.\" ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +.\" +.\" Carnegie Mellon requests users of this software to return to +.\" +.\" Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU +.\" School of Computer Science +.\" Carnegie Mellon University +.\" Pittsburgh PA 15213-3890 +.\" +.\" any improvements or extensions that they make and grant Carnegie Mellon +.\" the rights to redistribute these changes. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.\" HISTORY +.\" $Log: sup.1,v $ +.\" Revision 1.1 1995/12/16 11:46:54 deraadt +.\" add sup to the tree +.\" +.\" Revision 1.3 1995/06/03 21:21:53 christos +.\" Changes to write ascii timestamps in the when files. +.\" Looked into making it 64 bit clean, but it is hopeless. +.\" Added little program to convert from the old timestamp files +.\" into the new ones. +.\" +.\" Revision 1.2 1993/08/04 17:46:14 brezak +.\" Changes from nate for gzip'ed sup +.\" +.\" Revision 1.1.1.1 1993/05/21 14:52:16 cgd +.\" initial import of CMU's SUP to NetBSD +.\" +.\" Revision 1.4 92/08/11 12:08:40 mrt +.\" .TP +.\" Add description of releases and use-rel-suffix +.\" [92/07/31 mrt] +.\" +.\" Revision 1.3 92/02/08 18:24:31 mja +.\" Added description of -k and -K switches and "keep" option. +.\" [92/01/17 vdelvecc] +.\" +.\" 10-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University +.\" Replaced reference to /usr/cmu with /usr/cs. +.\" +.\" 29-Mar-86 Glenn Marcy (gm0w) at Carnegie-Mellon University +.\" Updated manual entry to version 5.14 of sup. +.\" +.\" 14-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University +.\" Updated manual entry to version 5.7 of sup. +.\" +.\" 04-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University +.\" Created. +.\" +.TH SUP 1 02/08/92 +.CM 4 +.SH "NAME" +sup \- software upgrade protocol +.SH "SYNOPSIS" +\fBsup\fR [ \fIflags\fR ] [ \fIsupfile\fR ] [ \fIcollection\fR ...] +.SH "DESCRIPTION" +.I Sup +is a program used for upgrading collections of files from other machines +to your machine. You execute +.IR sup , +the +.I client +program, which talks over the network using IP/TCP to a +.I file server +process. +The file server process cooperates with +.I sup +to determine which files of the collection need to be upgraded on +your machine. + +Sup collections can have multiple releases. One use for such releases is +to provide different versions of the same files. At CMU, for example, +system binaries have alpha, beta and default release corresponding to +different staging levels of the software. We also use release names +default and minimal to provide complete releases or subset releases. +In both of these cases, it only makes sense to sup one release of the +collections. Releases have also been used in private or external sups to +provide subsets of collections where it makes sense to pick up several +of the releases. For example the Mach 3.0 kernel sources has a default +release of machine independent sources and separate releases of +machine dependent sources for each supported platform. + +In performing an upgrade, the file server constructs a list of +files included in the specified release of the collection. The list is sent to your machine, +which determines which files are needed. Those files are then sent +from the file server. +It will be most useful to run +.I sup +as a daemon each night so you will continually have the latest version of the +files in the needed collections. + +The only required argument to +.I sup +is the name of a supfile. It must either be given explicitly on the command +line, or the +.B -s +flag must be specified. If the +.B -s +flag is given, the system supfile will be used and a supfile command argument +should not be specified. The list of collections is optional and if specified +will be the only collections upgraded. The following flags affect all +collections specified: +.TP +.B -s +As described above. +.TP +.B -t +When this flag is given, +.I sup +will print the time +that each collection was last upgraded, rather than +performing actual upgrades. +.TP +.B -N +.I Sup +will trace network messages sent and received that implement the +.I sup +network protocol. +.TP +.B -P +Sup will use a set of non-privileged network +ports reserved for debugging purposes. +.i0 +.DT +.PP + +The remaining flags affect all collections unless an explicit list +of collections are given with the flags. Multiple flags may be +specified together that affect the same collections. For the sake +of convience, any flags that always affect all collections can be +specified with flags that affect only some collections. For +example, +.B sup -sde=coll1,coll2 +would perform a system upgrade, +and the first two collections would allow both file deletions and +command executions. Note that this is not the same command as +.B sup -sde=coll1 coll2, +which would perform a system upgrade of +just the coll2 collection and would ignore the flags given for the +coll1 collection. +.TP +.B -a +All files in the collection will be copied from +the repository, regardless of their status on the +current machine. Because of this, it is a very +expensive operation and should only be done for +small collections if data corruption is suspected +and been confirmed. In most cases, the +.B -o +flag should be sufficient. +.TP +.B -b +If the +.B -b +flag if given, or the +.B backup +supfile +option is specified, the contents of regular files +on the local system will be saved before they are +overwritten with new data. The file collection maintainer +can designate specific files to be +worthy of backing up whenever they are upgraded. +However, such +backup will only take place if you specify this flag or the +.B backup +option to allow +backups for a file collection on your machine. +The backup mechanism +will create a copy of the current version of a file immediately +before a new copy is received from the file server; the copy is +given the same name as the original file but is put into a directory +called +.B +BACKUP +within the directory containing the original file. +For example, +.B +/usr/sas/src/foo.c +would have a backup copy called +.B +/usr/sas/src/BACKUP/foo.c. +There is no provision for automatically maintaining multiple old +versions of files; you would have to do this yourself. +.TP +.B -B +The +.B -B +flag overrides and disables the +.B -b +flag and the +.B backup +supfile option. +.TP +.B -d +Files that are no longer in the collection on the +repository will be deleted if present on the local +machine and were put there by a previous sup. +This may also be specified in a supfile with the +.B delete +option. +.TP +.B -D +The +.B -D +flag overrides and disables the +.B -d +flag and the +.B delete +supfile option. +.TP +.B -e +Sup will execute commands sent from the repository +that should be run when a file is upgraded. If +the +.B -e +flag is omitted, Sup will print a message +that specifies the command to execute. This may +also be specified in a supfile with the +.B execute +option. +.TP +.B -E +The +.B -E +flag overrides and disables the +.B -e +flag and the +.B execute +supfile option. +.TP +.B -f +A +.I list-only +upgrade will be performed. Messages +will be printed that indicate what would happen if +an actual upgrade were done. +.TP +.B -k +.I Sup +will check the modification times of +files on the local disk before updating them. Only files which are +newer on the repository than on the local disk will be updated; +files that are newer on the local disk will be kept as they are. +This may also be specified in a supfile with the +.B keep +option. +.TP +.B -K +The +.B -K +flag overrides and disables the +.B -k +flag and the +.B keep +supfile option. +.TP +.B -l +Normally, +.I sup +will not upgrade a collection if the +repository is on the same machine. This allows +users to run upgrades on all machines without +having to make special checks for the repository +machine. If the +.B -l +flag is specified, collections +will be upgraded even if the repository is local. +.TP +.B -m +Normally, +.I sup +used standard output for messages. +If the +.B -m +flag if given, +.I sup +will send mail to the user running +.IR sup , +or a user specified with the +.B notify +supfile option, that contains messages +printed by +.IR sup . +.TP +.B -o +.I Sup +will normally only upgrade files that have +changed on the repository since the last time an +upgrade was performed. That is, if the file in the +repository is newer than the date stored in the +.I when +file on the client. The +.B -o +flag, or the +.B old +supfile option, will cause +.I sup +to check all files +in the collection for changes instead of just the +new ones. +.TP +.B -O +The +.B -O +flag overrides and disables the +.B -o +flag and the +.B old +supfile option. +.TP +.B -z +Normally sup transfers files directly without any +other processing, but with the +.B -z +flag, or the +.B compress +supfile option, sup will compress the file +before sending it across the network and +uncompress it and restore all the correct +file attributes at the recieving end. +.TP +.B -Z +The +.B -Z +flag overrides and disables the +.B -z +flag and the +.B compress +supfile option. +.TP +.B -v +Normally, +.I sup +will only print messages if there +are problems. This flag causes +.I sup +to also print +messages during normal progress showing what +.I sup +is doing. +.i0 +.DT +.PP +.SH "SETTING UP UPGRADES" +Each file collection to be upgraded must have a +.I base directory +which contains a subdirectory called +.B sup +that will be used by the +.I sup +program; it will be created automatically if you do not create it. +.I Sup +will put subdirectories and files into this directory as needed. + +.I Sup +will look for a subdirectory with the same name as the +collection within the +.B sup +subdirectory of the +.I base directory. +If it exists it may contain any of the following files: +.TP +.B when.<rel-suffix> +This file is automatically updated by +.I sup +when a collection is successfully upgraded and contains the +time that the file server, or possibly +.IR supscan , +created the list of files in the upgrade list. +.I Sup +will send this time to the file server for generating the list +of files that have been changed on the repository machine. +.TP +.B refuse +This file contains a list of files and directories, one per line, that +the client is not interested in that should not be upgraded. +.TP +.B lock +This file is used by +.I sup +to lock a collection while it is being upgraded. +.I Sup +will get exclusive access to the lock file using +.IR flock (2), +preventing more than one +.I sup +from upgrading the same collection at the same time. +.TP +.B last.<rel-suffix> +This file contains a list of files and directories, one per line, that +have been upgraded by +.I sup +in the past. This information is used when the +.B delete +option, or the +.B -d +flag is used to locate files previously upgraded that are no longer +in the collection that should be deleted. +.i0 +.DT +.PP + +Each file collection must also be described in one or more supfiles. +When +.I sup +is executed, it reads the specified supfile to determine what file +collections and releases to upgrade. +Each collection-release set is described by a single +line of text in the supfile; this line must contain the name of the +collection, and possibly one or more options separated by spaces. +The options are: +.TP +.BI release= releasename +If a collection contains multiple releases, you need to specify which +release you want. You can only specify one release per line, so +if you want multiple releases from the same collections, you will need +to specify the collection more than once. In this case, you should use +the +.I use-rel-suffix +ption in the supfile +to keep the last and when files for the two releases separate. +.TP +.BI base= directory +The usual default name of the base directory for a collection is +described below (see FILES); if you want to specify another +directory name, use this option specifying the desired +directory. +.TP +.BI prefix= directory +Each collection may also have an associated +.I prefix directory +which is used instead of the base directory to specify in what +directory files within the collection will be placed. +.TP +.BI host= hostname +.br +.ns +.TP +.BI hostbase= directory +.br +.I System +collections are supported by the system maintainers, and +.I sup +will automatically find out the name of the host machine and +base directory on that machine. +However, you can also upgrade +.I private +collections; you simply specify with these options +the +.I hostname +of the machine containing the files and the +.I directory +used as a base directory for the file server on that machine. +Details of setting up a file collection are given in the section +below. +.TP +.BI login= accountid +.br +.ns +.TP +.BI password= password +.br +.br +.ns +.TP +.BI crypt= key +.br +Files on the file server may be protected, and network transmissions +may be encrypted. +This prevents unauthorized access to files via +.IR sup . +When files are not accessible to the default account (e.g. +the +.B anon +anonymous account), you can specify an alternative +.I accountid +and +.I password +for the file server to use on the repository host. +Network +transmission of the password will be always be encrypted. +You can +also have the actual file data encrypted by specifying a +.IR key ; +the file collection on the repository must specify the same key +or else +.I sup +will not be able to upgrade files from that collection. +In this case, the default account used by the file server on the +repository machine will be the owner of the encryption key +file (see FILES) rather than the +.B anon +anonymous account. +.TP +.BI notify= address +If you use the +.B +-m +option to receive log messages by mail, you can have the mail +sent to different user, possibly on another host, than the user +running the sup program. +Messages will be sent to the specified +.IR address , +which can be any legal netmail address. +In particular, a +project maintainer can be designated to receive mail for that +project's file collection from all users running +.I sup +to upgrade that collection. +.TP +.B backup +As described above under the +.B -b +flag. +.TP +.B delete +As described above under the +.B -d +flag. +.TP +.B execute +As described above under the +.B -e +flag. +.TP +.B keep +As described above under the +.B -k +flag. +.TP +.B old +As described above under the +.B -o +flag. +.TP +.B use-rel-suffix +Causes the release name to be used as a suffix to the +.I last +and +.I when +files. This is necessary whenever you are supping more than one +release in the same collection. +.i0 +.DT +.PP +.SH "PREPARING A FILE COLLECTION REPOSITORY" +A set of files residing on a repository must be prepared before +.I sup +client processes can upgrade those files. +The collection must +be given a +.I name +and a +.I base directory. +If it is a private collection, client users +must be told the name of the collection, repository host, and +base directory; +these will be specified in the supfile via the +.B host +and +.B hostbase +options. +For a system-maintained file collection, entries must be +placed into the host list file and directory list file as described +in +.IR supservers (8). + +Within the base directory, a subdirectory must be created called +.B sup . +Within this directory there must be a subdirectory for each +collection using that base directory, whose name is the name of the +collection; within each of these directories will be a +list file and possibly a prefix file, a host file, an encryption key +file, a log file and +a scan file. +The filenames are listed under FILES below. +.TP +.B prefix +Normally, all files in the collection are relative to the base directory. +This file contains a single line which is the name of a directory to be +used in place of the base directory for file references. +.TP +.B host +Normally, +all remote host machines are allowed access to a file collection. +If you wish to restrict access to specific remote hosts for this +collection, +put each allowed hostname on a +separate line of text in this file. +If a host has more than one name, only one of its names needs to be +listed. +The name +.B LOCAL +can be used to grant access to all hosts on the local +network. The host name may be a numeric network adddress +or a network name. If a crypt appears on the same line as +the host name, that crypt will be used for that host. Otherwise, +the crypt appearing in the +.I crypt +file, if any will be used. +.TP +.B crypt +If you wish to use the +.I sup +data encryption mechanism, create an encryption file containing, +on a single line of text, the desired encryption key. +Client +processes must then specify the same key with the +.B crypt +option in the supfile or they will be denied access to the files. +In addition, actual network transmission of file contents and +filenames will be encrypted. +.TP +.B list +This file describes the actual list of files to be included in this +file collection, in a format described below. +.TP +.B releases +This file describes any releases that the collection may have. Each +line starts with the release name and then may specify any of the following +files: +.I prefix=<dirname> +to use a different parent directory for the files in this release. +.I list=<listname> +to specify the list of files in the release. +.I scan=<scanfile> +must be used in multi-release collections that are scanned to keep +the scan files for the different releases separate. +.I host=<hostfile> +to allow different host restrictions for this release. +.I next=<release> +used to chain releases together. This has the effect of making one release +be a combination of serveral other releases. If the same file appears in +more than one chained release, the first one found will be used. +If these files are not specified for a release the default names: +prefix,list,scan and host will be used. +.TP +.B scan +This file, created by +.IR supscan , +is the list of filenames that correspond to the instructions in the +list file. The scan file is only used for frequently-updated file +collections; it makes the file server run much faster. See +.IR supservers (8) +for more information. +.TP +.B lock +As previously mentioned, this file is used to indicate that the +collection should be locked while upgrades are in progress. All +file servers will try to get shared access to the lock file with +.IR flock (2). +.TP +.B logfile +If a log file exists in the collection directory, the file server +will append the last time an upgrade was successfully completed, +the time the last upgrade started and finished, and the name of +the host requesting the upgrade. +.i0 +.DT +.PP +It should be noted that +.I sup +allows several different named collections to use the same base +directory. Separate encryption, remote host access, and file lists +are used for each collection, since these files reside in subdirectorie +.I <basedir>/sup/<coll.name>. + +The list file is a text file with one command on each line. +Each command +contains a keyword and a number of operands separated by spaces. +All filenames in the list file are evaluated on the repository machine +relative to the host's base directory, or prefix directory if one is +specified, and on your machine with respect +to the base, or prefix, directory for the client. +The +.I filenames +below (except \fIexec-command\fR) +may all include wild-cards and meta-characters as used by +.IR csh (1) +including *, ?, [...], and {...}. The commands are: +.TP +\fBupgrade\fR \fIfilename\fR ... +The specified file(s) (or directories) will be included in the list +of files to be upgraded. +If a directory name is given, it recursively +includes all subdirectories and files within that directory. +.TP +\fBalways\fR \fIfilename\fR ... +The always command is identical to upgrade, except that omit and +omitany commands do not affect filenames specified with the always +command. +.TP +\fBomit\fR \fIfilename\fR ... +The specified file(s) (or directories) will be excluded from the +list of files to be upgraded. +For example, by specifying +.B upgrade /usr/vision +and +.B omit /usr/vision/exp, +the generated list +of files would include all subdirectories and files of /usr/vision +except /usr/vision/exp (and its subdirectories and files). +.TP +\fBomitany\fR \fIpattern\fR ... +The specified patterns are compared against the files in the upgrade +list. If a pattern matches, the file is omitted. The omitany command +currently supports all wild-card patterns except {...}. Also, the +pattern must match the entire filename, so a leading */, or a trailing /*, +may be necessary in the pattern. +.TP +\fBbackup\fR \fIfilename\fR ... +The specified file(s) are marked for backup; if they are upgraded +and the client has specified the +.B backup +option in the corresponding +line of the supfile, then backup copies will be created as described +above. +Directories may not be specified, and no recursive filename +construction is performed; you must specify the names of the specific +files to be backed up before upgrading. +.TP +\fBnoaccount\fR \fIfilename\fR ... +The accounting information of the specified file(s) will not be +preserved by +.IR sup . +Accounting information consists of the owner, +group, mode and modified time of a file. +.TP +\fBsymlink\fR \fIfilename\fR ... +The specified file(s) are to be treated as symbolic links +and will be transfered as such and not followed. By default, +.I sup +will follow symbolic links. +.TP +\fBrsymlink\fR \fIdirname\fR ... +All symbolic links in the specified directory and its +subdirectories are to be treated as symbolic links. That +is the links will be transferred and not the files to which +they point. +.TP +\fBexecute\fR \fIexec-command\fR (\fIfilename\fR ...) +The +.I exec-command +you specified will be executed on the client process +whenever any of the files listed in parentheses are upgraded. +A special token, +.B %s, +may be specified in the +.I exec-command +and will be replaced by the name of the file that was upgraded. +For example, if you say +\fBexecute ranlib %s (libc.a)\fR, +then whenever libc.a is upgraded, the client machine will execute +.B +ranlib libc.a. +As described above, the client must invoke +.I sup +with the +.B -e +flag to allow the automatic execution of command files. +.TP +\fBinclude\fR \fIlistfile\fR ... +The specified +.I listfiles +will be read at this point. This is useful +when one collection subsumes other collections; the larger collection +can simply specify the listfiles for the smaller collections contained +within it. +.i0 +.DT +.PP +The order in which the command lines appear in the list file does not +matter. Blank lines may appear freely in the list file. +.SH "FILES" +Files on the client machine for +.IR sup : +.TP +.B /usr/lib/supfiles/coll.list +supfile used for -s flag +.TP +.B /usr/lib/supfiles/coll.what +supfile used for -s flag when -t flag is also specified +.TP +.B /usr/lib/supfiles/coll.host +host name list for system collections +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/last\fR<\fI.release\fR> +recorded list of files in collection as of last upgrade +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/lock +file used to lock collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/refuse +list of files to refuse in collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/when\fR<\fI.release\fR> +recorded time of last upgrade +.TP +\fB/usr/sup/\fR<\fIcollection\fR> +default base directory for file collection +.i0 +.DT +.PP + +Files needed on each repository machine for the file server: +.TP +.B /usr/lib/supfiles/coll.dir +base directory list for system +collections +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/crypt +data encryption key for a +collection. the owner of this file is the +default account used when data encryption is specified +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/host +list of remote hosts allowed to +upgrade a collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/list +list file for a collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/lock +lock file for a collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/logfile +log file for a collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/prefix +file containing the name of the prefix directory +for a collection +.TP +<\fIbase-directory\fR>\fB/sup/\fR<\fIcollection\fR>\fB/scan +scan file for a collection +.TP +\fB/usr/\fR<\fIcollection\fR> +default base directory for a file collection +.i0 +.DT +.PP +.SH "SEE ALSO" +.IR supservers (8) +.br +\fIThe SUP Software Upgrade Protocol\fR, S. A. Shafer, +CMU Computer Science Department, 1985. +.SH "EXAMPLE" +<example> +.SH "BUGS" +The encryption mechanism should be strengthened, although it's +not trivial. diff --git a/usr.bin/sup/src/sup.h b/usr.bin/sup/src/sup.h new file mode 100644 index 00000000000..eee3b860107 --- /dev/null +++ b/usr.bin/sup/src/sup.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* sup.h -- declarations for sup, supnamesrv, supfilesrv + * + * VERSION NUMBER for any program is given by: a.b (c) + * where a = PROTOVERSION is the protocol version # + * b = PGMVERSION is program # within protocol + * c = scmversion is communication module version + * (i.e. operating system for which scm is configured) + ********************************************************************** + * HISTORY + * 13-Sep-92 Mary Thompson (mrt) at Carnegie-Mellon University + * Changed name of DEFDIR from /usr/cs to /usr. + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: sup.h,v $ + * Revision 1.1 1995/12/16 11:46:55 deraadt + * add sup to the tree + * + * Revision 1.3 1995/06/03 21:21:54 christos + * Changes to write ascii timestamps in the when files. + * Looked into making it 64 bit clean, but it is hopeless. + * Added little program to convert from the old timestamp files + * into the new ones. + * + * Revision 1.2 1993/08/04 17:46:15 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.10 92/08/11 12:06:42 mrt + * Added definition for DEBUGFPORTNUM, the debugging port number. + * Changed so that last and when file names could include + * the relase name if any. + * [92/07/23 mrt] + * + * Revision 1.9 91/04/29 14:39:03 mja + * Reduce MAXCHILDREN from 8 to 3. + * + * Revision 1.8 89/08/23 14:55:30 gm0w + * Moved coll.dir from supservers to supfiles. + * [89/08/23 gm0w] + * + * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added host=<hostfile> support to releases file. + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support. Removed nameserver support. + * + * 27-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added TREELIST and other changes for "release" support. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Version 6 of the network protocol, better support to reflect errors + * back to server logfile. + * + * 21-May-87 Chriss Stephens (chriss) at Carnegie Mellon University + * Merged divergent CS and EE versions. + * + * 19-Sep-86 Mike Accetta (mja) at Carnegie-Mellon University + * Added FILESUPTDEFAULT definition. + * + * 07-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed FILESRVBUSYWAIT. Now uses exponential backoff. + * + * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added numeric port numbers to use when port names are not in the + * host table. + * + * 04-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Update protocol version to 5 for name server protocol change to + * allow multiple repositories per collection. Added FILESRVBUSYWAIT + * of 5 minutes. Added FILELOCK file to indicate collections that + * should be exclusively locked when upgraded. + * + * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Merged 4.1 and 4.2 versions together. + * + * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University + * Created for 4.2 BSD. + * + ********************************************************************** + */ + +/* PGMVERSION is defined separately in each program */ +extern char scmversion[]; /* string version of scm */ +#define PROTOVERSION 8 /* version of network protocol */ +#define SCANVERSION 2 /* version of scan file format */ + +/* TCP servers for name server and file server */ +#define FILEPORT "supfilesrv" +#define FILEPORTNUM 871 +#define DEBUGFPORT "supfiledbg" +#define DEBUGFPORTNUM 1127 + +/* Data files used in scan.c */ +#define FILELIST "sup/%s/%s" +#define FILESCAN "sup/%s/%s" +#define FILEHOST "sup/%s/%s" +#define FILELISTDEF "list" +#define FILESCANDEF "scan" +#define FILEHOSTDEF "host" +#define DEFRELEASE "default" + +/* Data files used in sup.c */ +#define FILEBASEDEFAULT "/usr/%s" /* also supfilesrv and supscan */ +#ifdef EE_XXX +#define FILESUPDEFAULT "%s/supfiles/coll.list" +#define FILESUPTDEFAULT "%s/supfiles/coll.what" +#define FILEHOSTS "%s/supfiles/coll.host" +#else EE_XXX +#define FILESUPDEFAULT "%s/lib/supfiles/coll.list" +#define FILESUPTDEFAULT "%s/lib/supfiles/coll.what" +#define FILEHOSTS "%s/lib/supfiles/coll.host" +#endif EE_XXX +#define FILEBKDIR "%s/BACKUP" +#define FILEBACKUP "%s/BACKUP/%s" +#define FILELAST "sup/%s/last%s" +#define FILELASTTEMP "sup/%s/last.temp" +#define FILELOCK "sup/%s/lock" /* also supfilesrv */ +#define FILEREFUSE "sup/%s/refuse" +#define FILEWHEN "sup/%s/when%s" + +/* Data files used in supfilesrv.c */ +#define FILEXPATCH "%s/sup/xpatch.host" +#ifdef EE_XXX +#define FILEDIRS "%s/supfiles/coll.dir" /* also supscan */ +#else EE_XXX +#define FILEDIRS "%s/lib/supfiles/coll.dir" /* also supscan */ +#endif EE_XXX +#define FILECRYPT "sup/%s/crypt" +#define FILELOGFILE "sup/%s/logfile" +#define FILEPREFIX "sup/%s/prefix" /* also supscan */ +#define FILERELEASES "sup/%s/releases" /* also supscan */ + +/* String length */ +#define STRINGLENGTH 2000 + +/* Password transmission encryption key */ +#define PSWDCRYPT "SuperMan" +/* Test string for encryption */ +#define CRYPTTEST "Hello there, Sailor Boy!" + +/* Default directory for system sup information */ +#ifndef DEFDIR +#ifdef EE_XXX +#define DEFDIR "/etc" +#else EE_XXX +#define DEFDIR "/usr" +#endif EE_XXX +#endif DEFDIR + +/* Default login account for file server */ +#ifndef DEFUSER +#define DEFUSER "anon" +#endif DEFUSER + +/* subroutine return codes */ +#define SCMOK (1) /* routine performed correctly */ +#define SCMEOF (0) /* read EOF on network connection */ +#define SCMERR (-1) /* error occurred during routine */ + +/* data structure for describing a file being upgraded */ + +struct treestruct { +/* fields for file information */ + char *Tname; /* path component name */ + int Tflags; /* flags of file */ + int Tmode; /* st_mode of file */ + char *Tuser; /* owner of file */ + int Tuid; /* owner id of file */ + char *Tgroup; /* group of file */ + int Tgid; /* group id of file */ + int Tctime; /* inode modification time */ + int Tmtime; /* data modification time */ + struct treestruct *Tlink; /* tree of link names */ + struct treestruct *Texec; /* tree of execute commands */ +/* fields for sibling AVL tree */ + int Tbf; /* balance factor */ + struct treestruct *Tlo,*Thi; /* ordered sibling tree */ +}; +typedef struct treestruct TREE; + +/* data structure to represent a list of trees to upgrade */ + +struct tliststruct { + struct tliststruct *TLnext; /* next entry in tree list */ +/* fields for tree information */ + char *TLname; /* release name for tree */ + char *TLprefix; /* prefix of tree */ + char *TLlist; /* name of list file */ + char *TLscan; /* name of scan file */ + char *TLhost; /* name of host file */ + TREE *TLtree; /* tree of files to upgrade */ +}; +typedef struct tliststruct TREELIST; + +/* bitfield not defined in stat.h */ +#define S_IMODE 07777 /* part of st_mode that chmod sets */ + +/* flag bits for files */ +#define FNEW 01 /* ctime of file has changed */ +#define FBACKUP 02 /* backup of file is allowed */ +#define FNOACCT 04 /* don't set file information */ +#define FUPDATE 010 /* only set file information */ +#define FNEEDED 0100000 /* file needed for upgrade */ + +/* version 3 compatability */ +#define FCOMPAT 0010000 /* Added to detect execute commands to send */ + +/* message types now obsolete */ +#define MSGFEXECQ (115) +#define MSGFEXECNAMES (116) + +/* flag bits for files in list of all files */ +#define ALLNEW 01 +#define ALLBACKUP 02 +#define ALLEND 04 +#define ALLDIR 010 +#define ALLNOACCT 020 +#define ALLSLINK 0100 + +/* flag bits for file mode word */ +#define MODELINK 010000 +#define MODEDIR 040000 +#define MODESYM 0100000 +#define MODENOACCT 0200000 +#define MODEUPDATE 01000000 + +/* blocking factor for filenames in list of all file names */ +#define BLOCKALL 32 + +/* end version 3 compatability */ + +#define MAXCHILDREN 3 /* maximum number of children allowed + to sup at the same time */ + +/* scm and stree external declarations */ +char *remotehost(); +TREE *Tinsert(),*Tsearch(),*Tlookup(); +long getwhen(); +int putwhen(); diff --git a/usr.bin/sup/src/supcdefs.h b/usr.bin/sup/src/supcdefs.h new file mode 100644 index 00000000000..12261403e34 --- /dev/null +++ b/usr.bin/sup/src/supcdefs.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * supcdefs.h -- Declarations shared by the collection of files + * that build the sup client. + * + ********************************************************************** + * HISTORY + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supcdefs.h,v $ + * Revision 1.1 1995/12/16 11:46:55 deraadt + * add sup to the tree + * + * Revision 1.2 1993/08/04 17:46:16 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.6 92/08/11 12:06:52 mrt + * Added CFURELSUF - use-release-suffix flag + * Made rpause code conditional on MACH rather than CMUCS + * [92/07/26 mrt] + * + * Revision 1.5 92/02/08 18:23:57 mja + * Added CFKEEP flag. + * [92/01/17 vdelvecc] + * + * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added timeout for backoff. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added Crelease for "release" support. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +#include <libc.h> +#include <netdb.h> +#include <signal.h> +#include <setjmp.h> +#include <pwd.h> +#include <grp.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/file.h> +#include <sys/errno.h> +#if MACH /* used by resource pausing code only */ +#include <sys/ioctl.h> +#include <sys/resource.h> +#endif /* MACH */ +#include <c.h> +#include "sup.h" +#include "supmsg.h" + +extern int errno; +extern uid_t getuid(); +extern gid_t getgid(); +extern long time(); + +extern int PGMVERSION; + +/******************************************* + *** D A T A S T R U C T U R E S *** + *******************************************/ + +struct collstruct { /* one per collection to be upgraded */ + char *Cname; /* collection name */ + TREE *Chost; /* attempted host for collection */ + TREE *Chtree; /* possible hosts for collection */ + char *Cbase; /* local base directory */ + char *Chbase; /* remote base directory */ + char *Cprefix; /* local collection pathname prefix */ + char *Crelease; /* release name */ + char *Cnotify; /* user to notify of status */ + char *Clogin; /* remote login name */ + char *Cpswd; /* remote password */ + char *Ccrypt; /* data encryption key */ + int Ctimeout; /* timeout for backoff */ + int Cflags; /* collection flags */ + int Cnogood; /* upgrade no good, "when" unchanged */ + int Clockfd; /* >= 0 if collection is locked */ + struct collstruct *Cnext; /* next collection */ +}; +typedef struct collstruct COLLECTION; + +#define CFALL 00001 +#define CFBACKUP 00002 +#define CFDELETE 00004 +#define CFEXECUTE 00010 +#define CFLIST 00020 +#define CFLOCAL 00040 +#define CFMAIL 00100 +#define CFOLD 00200 +#define CFVERBOSE 00400 +#define CFKEEP 01000 +#define CFURELSUF 02000 +#define CFCOMPRESS 04000 + +/************************* + *** M A C R O S *** + *************************/ + +#define vnotify if (thisC->Cflags&CFVERBOSE) notify diff --git a/usr.bin/sup/src/supcmain.c b/usr.bin/sup/src/supcmain.c new file mode 100644 index 00000000000..5568acb91a8 --- /dev/null +++ b/usr.bin/sup/src/supcmain.c @@ -0,0 +1,723 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * sup -- Software Upgrade Protocol client process + * + * Usage: sup [ flags ] [ supfile ] [ collection ... ] + * + * The only required argument to sup is the name of a supfile. It + * must either be given explicitly on the command line, or the -s + * flag must be specified. If the -s flag is given, the system + * supfile will be used and a supfile command argument should not be + * specified. The list of collections is optional and if specified + * will be the only collections upgraded. The following flags affect + * all collections specified. + * + * -s "system upgrade" flag + * As described above. + * + * -t "upgrade time" flag + * When this flag is given, Sup will print the time + * that each collection was last upgraded, rather than + * performing actual upgrades. + * + * -R "resource pause" flag + * Sup will not disable resource pausing and will not + * make filesystem space checks. + * + * -N "debug network" flag + * Sup will trace messages sent and received that + * implement the Sup network protocol. + * + * -P "debug ports" flag + * Sup will use a set of non-privileged network + * ports reserved for debugging purposes. + * + * -X "crosspatch" flag + * Sup is being run remotely with a crosspatch. + * Need to be carefull as we may be running as root + * instead of collection owner. + * + * The remaining flags affect all collections unless an explicit list + * of collections are given with the flags. Multiple flags may be + * specified together that affect the same collections. For the sake + * of convience, any flags that always affect all collections can be + * specified with flags that affect only some collections. For + * example, "sup -sde=coll1,coll2" would perform a system upgrade, + * and the first two collections would allow both file deletions and + * command executions. Note that this is not the same command as + * "sup -sde=coll1 coll2", which would perform a system upgrade of + * just the coll2 collection and would ignore the flags given for the + * coll1 collection. + * + * -a "all files" flag + * All files in the collection will be copied from + * the repository, regardless of their status on the + * current machine. Because of this, it is a very + * expensive operation and should only be done for + * small collections if data corruption is suspected + * and been confirmed. In most cases, the -o flag + * should be sufficient. + * + * -b "backup files" flag + * If the -b flag if given, or the "backup" supfile + * option is specified, the contents of regular files + * on the local system will be saved before they are + * overwritten with new data. The data will be saved + * in a subdirectory called "BACKUP" in the directory + * containing the original version of the file, in a + * file with the same non-directory part of the file + * name. The files to backup are specified by the + * list file on the repository. + * + * -B "don't backup files" flag + * The -B flag overrides and disables the -b flag and + * the "backup" supfile option. + * + * -d "delete files" flag + * Files that are no longer in the collection on the + * repository will be deleted if present on the local + * machine. This may also be specified in a supfile + * with the "delete" option. + * + * -D "don't delete files" flag + * The -D flag overrides and disables the -d flag and + * the "delete" supfile option. + * + * -e "execute files" flag + * Sup will execute commands sent from the repository + * that should be run when a file is upgraded. If + * the -e flag is omitted, Sup will print a message + * that specifies the command to execute. This may + * also be specified in a supfile with the "execute" + * option. + * + * -E "don't execute files" flag + * The -E flag overrides and disables the -e flag and + * the "execute" supfile option. + * + * -f "file listing" flag + * A "list-only" upgrade will be performed. Messages + * will be printed that indicate what would happen if + * an actual upgrade were done. + * + * -k "keep newer files" flag + * The -k flag, or "keep" supfile option, will cause + * Sup to check to see whether there is a newer file on + * the local disk before updating files. Only files + * which are newer on the repository will be updated. + * + * -K "don't keep newer files" flag + * The -K flag overrides and disables the -k flag and + * the "keep" supfile option. + * + * -l "local upgrade" flag + * Normally, Sup will not upgrade a collection if the + * repository is on the same machine. This allows + * users to run upgrades on all machines without + * having to make special checks for the repository + * machine. If the -l flag is specified, collections + * will be upgraded even if the repository is local. + * + * -m "mail" flag + * Normally, Sup used standard output for messages. + * If the -m flag if given, Sup will send mail to the + * user running Sup, or a user specified with the + * "notify" supfile option, that contains messages + * printed by Sup. + * + * -o "old files" flag + * Sup will normally only upgrade files that have + * changed on the repository since the last time an + * upgrade was performed. The -o flag, or the "old" + * supfile option, will cause Sup to check all files + * in the collection for changes instead of just the + * new ones. + * + * -O "not old files" flag + * The -O flag overrides and disables the -o flag and + * the "old" supfile option. + * + * -v "verbose" flag + * Normally, Sup will only print messages if there + * are problems. This flag causes Sup to also print + * messages during normal progress showing what Sup + * is doing. + * + ********************************************************************** + * HISTORY + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supcmain.c,v $ + * Revision 1.1 1995/12/16 11:46:56 deraadt + * add sup to the tree + * + * Revision 1.4 1995/09/16 19:01:25 glass + * if the function returns nothing, declare it void + * + * Revision 1.3 1993/08/04 17:46:17 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.2 1993/05/24 17:57:28 brezak + * Remove netcrypt.c. Remove unneeded files. Cleanup make. + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.6 92/08/11 12:06:59 mrt + * Merged in Brad's changes. Made resource pausing code conditional + * on MACH, rather than CMUCS. Fixed some calls to sprintf to + * return void. + * [92/08/09 mrt] + * + * Revision 1.5 92/02/08 19:01:18 mja + * Correct oldsigsys type when ANSI C. + * [92/02/08 18:59:47 mja] + * + * Revision 1.4 92/02/08 18:24:01 mja + * Added -k and -K switches. + * [92/01/17 vdelvecc] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support (is currently ignored). + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Split into several files. This is the main program and + * command line processing and old history log. [V5.21] + * + * 21-May-87 Chriss Stephens (chriss) at Carnegie Mellon University + * Merged divergent CS and ECE versions. ifdeffed out the resource + * pausing code - only compiled in if CMUCS defined. [V5.21a] + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed support for version 3 of SUP protocol. Added changes + * to make lint happy. Added calls to new logging routines. [V5.20] + * + * 01-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added -R switch to reenable resource pausing, which is currently + * disabled by default. Added code to check for free disk space + * available on the target filesystem so that sup shouldn't run the + * system out of disk space as frequently. [V5.19] + * + * 19-Sep-86 Mike Accetta (mja) at Carnegie-Mellon University + * Changed default supfile name for system collections when -t + * is specified to use FILESUPTDEFAULT; added missing new-line + * in retry message. [V5.18] + * + * 21-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Missed a caller to a routine which had an extra argument added + * to it last edit. [V5.17] + * + * 07-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed getcoll() so that fatal errors are checked immediately + * instead of after sleeping for a little while. Changed all + * rm -rf commands to rmdir since the Mach folks keep deleting + * their root and /usr directory trees. Reversed the order of + * delete commands to that directories will possibly empty so + * that the rmdir's work. [V5.16] + * + * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed temporary file names to #n.sup format. [V5.15] + * + * 19-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Moved PGMVERSION to supvers.c module. [V5.14] + * + * 06-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added check for file type before unlink when receiving a + * symbolic link. Now runs "rm -rf" if the file type is a + * directory. [V5.13] + * + * 03-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fixed small bug in signon that didn't retry connections if an + * error occured on the first attempt to connect. [V5.12] + * + * 26-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * New command interface. Added -bBDEO flags and "delete", + * "execute" and "old" supfile options. Changed -d to work + * correctly without implying -o. [V5.11] + * + * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fix incorrect check for supfile changing. Flush output buffers + * before restart. [V5.10] + * + * 17-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Add call to requestend() after connection errors are retried to + * free file descriptors. [V5.9] + * + * 15-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fix SERIOUS merge error from previous edit. Added notify + * when execute command fails. [V5.8] + * + * 11-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed ugconvert to clear setuid/setgid bits if it doesn't use + * the user and group specified by the remote system. Changed + * execute code to invalidate collection if execute command returns + * with a non-zero exit status. Added support for execv() of + * original arguments of supfile is upgraded sucessfully. Changed + * copyfile to always use a temp file if possible. [V5.7] + * + * 04-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added support for fileserver busy messages and new nameserver + * protocol to support multiple repositories per collection. + * Added code to lock collections with lock files. [V5.6] + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Major rewrite for protocol version 4. [V4.5] + * + * 12-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed to check for DIFFERENT mtime (again). [V3.4] + * + * 08-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Replaced [ug]convert routines with ugconvert routine so that an + * appropriate group will be used if the default user is used. + * Changed switch parsing to allow multiple switches to be specified + * at the same time. [V3.3] + * + * 04-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added test to request a new copy of an old file that already + * exists if the mtime is different. [V3.2] + * + * 24-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added -l switch to enable upgrades from local repositories. + * + * 03-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Minor change in order -t prints so that columns line up. + * + * 22-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to implement retry flag and pass this on to request(). + * + * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Merged 4.1 and 4.2 versions together. + * + * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University + * Created for 4.2 BSD. + * + ********************************************************************** + */ + +#define MSGFILE +#include "supcdefs.h" +#if MACH +#include <sys/syscall.h> +#ifndef SYS_rpause +#define SYS_rpause (-5) +#endif +#endif + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +char program[] = "SUP"; /* program name for SCM messages */ +int progpid = -1; /* and process id */ + +COLLECTION *firstC,*thisC; /* collection list pointer */ + +extern int dontjump; /* disable longjmp */ +extern int scmdebug; /* SCM debugging flag */ + +int sysflag; /* system upgrade flag */ +int timeflag; /* print times flag */ +#if MACH +int rpauseflag; /* don't disable resource pausing */ +#endif /* MACH */ +int xpatchflag; /* crosspatched with remote system */ +int portdebug; /* network debugging ports */ + +/************************************* + *** M A I N R O U T I N E *** + *************************************/ + +main (argc,argv) +int argc; +char **argv; +{ + char *init (); + char *progname,*supfname; + int restart,sfdev,sfino,sfmtime; + struct stat sbuf; + struct sigvec ignvec,oldvec; + + /* initialize global variables */ + pgmversion = PGMVERSION; /* export version number */ + server = FALSE; /* export that we're not a server */ + collname = NULL; /* no current collection yet */ + dontjump = TRUE; /* clear setjmp buffer */ + progname = salloc (argv[0]); + + supfname = init (argc,argv); + restart = -1; /* don't make restart checks */ + if (*progname == '/' && *supfname == '/') { + if (stat (supfname,&sbuf) < 0) + logerr ("Can't stat supfile %s",supfname); + else { + sfdev = sbuf.st_dev; + sfino = sbuf.st_ino; + sfmtime = sbuf.st_mtime; + restart = 0; + } + } + if (timeflag) { + for (thisC = firstC; thisC; thisC = thisC->Cnext) + prtime (); + } else { + /* ignore network pipe signals */ + ignvec.sv_handler = SIG_IGN; + ignvec.sv_onstack = 0; + ignvec.sv_mask = 0; + (void) sigvec (SIGPIPE,&ignvec,&oldvec); + getnams (); /* find unknown repositories */ + for (thisC = firstC; thisC; thisC = thisC->Cnext) { + getcoll (); /* upgrade each collection */ + if (restart == 0) { + if (stat (supfname,&sbuf) < 0) + logerr ("Can't stat supfile %s", + supfname); + else if (sfmtime != sbuf.st_mtime || + sfino != sbuf.st_ino || + sfdev != sbuf.st_dev) { + restart = 1; + break; + } + } + } + endpwent (); /* close /etc/passwd */ + (void) endgrent (); /* close /etc/group */ + if (restart == 1) { + int fd; + loginfo ("SUP Restarting %s with new supfile %s", + progname,supfname); + for (fd = getdtablesize (); fd > 3; fd--) + (void) close (fd); + execv (progname,argv); + logquit (1,"Restart failed"); + } + } + while (thisC = firstC) { + firstC = firstC->Cnext; + free (thisC->Cname); + Tfree (&thisC->Chtree); + free (thisC->Cbase); + if (thisC->Chbase) free (thisC->Chbase); + if (thisC->Cprefix) free (thisC->Cprefix); + if (thisC->Crelease) free (thisC->Crelease); + if (thisC->Cnotify) free (thisC->Cnotify); + if (thisC->Clogin) free (thisC->Clogin); + if (thisC->Cpswd) free (thisC->Cpswd); + if (thisC->Ccrypt) free (thisC->Ccrypt); + free ((char *)thisC); + } + exit (0); +} + +/***************************************** + *** I N I T I A L I Z A T I O N *** + *****************************************/ +/* Set up collection list from supfile. Check all fields except + * hostname to be sure they make sense. + */ + +#define Toflags Tflags +#define Taflags Tmode +#define Twant Tuid +#define Tcount Tgid + +void doswitch (argp,collTp,oflagsp,aflagsp) +char *argp; +register TREE **collTp; +int *oflagsp,*aflagsp; +{ + register TREE *t; + register char *coll; + register int oflags,aflags; + + oflags = aflags = 0; + for (;;) { + switch (*argp) { + default: + logerr ("Invalid flag '%c' ignored",*argp); + break; + case '\0': + case '=': + if (*argp++ == '\0' || *argp == '\0') { + *oflagsp |= oflags; + *oflagsp &= ~aflags; + *aflagsp |= aflags; + *aflagsp &= ~oflags; + return; + } + do { + coll = nxtarg (&argp,", \t"); + t = Tinsert (collTp,coll,TRUE); + t->Toflags |= oflags; + t->Toflags &= ~aflags; + t->Taflags |= aflags; + t->Taflags &= ~oflags; + argp = skipover (argp,", \t"); + } while (*argp); + return; + case 'N': + scmdebug++; + break; + case 'P': + portdebug = TRUE; + break; + case 'R': +#if MACH + rpauseflag = TRUE; +#endif /* MACH */ + break; + case 'X': + xpatchflag = TRUE; + break; + case 's': + sysflag = TRUE; + break; + case 't': + timeflag = TRUE; + break; + case 'a': + oflags |= CFALL; + break; + case 'b': + oflags |= CFBACKUP; + aflags &= ~CFBACKUP; + break; + case 'B': + oflags &= ~CFBACKUP; + aflags |= CFBACKUP; + break; + case 'd': + oflags |= CFDELETE; + aflags &= ~CFDELETE; + break; + case 'D': + oflags &= ~CFDELETE; + aflags |= CFDELETE; + break; + case 'e': + oflags |= CFEXECUTE; + aflags &= ~CFEXECUTE; + break; + case 'E': + oflags &= ~CFEXECUTE; + aflags |= CFEXECUTE; + break; + case 'f': + oflags |= CFLIST; + break; + case 'k': + oflags |= CFKEEP; + aflags &= ~CFKEEP; + break; + case 'K': + oflags &= ~CFKEEP; + aflags |= CFKEEP; + break; + case 'l': + oflags |= CFLOCAL; + break; + case 'm': + oflags |= CFMAIL; + break; + case 'o': + oflags |= CFOLD; + aflags &= ~CFOLD; + break; + case 'O': + oflags &= ~CFOLD; + aflags |= CFOLD; + break; + case 'v': + oflags |= CFVERBOSE; + break; + case 'z': + oflags |= CFCOMPRESS; + break; + case 'Z': + oflags &= ~CFCOMPRESS; + break; + } + argp++; + } +} + +char *init (argc,argv) +int argc; +char **argv; +{ + char buf[STRINGLENGTH],*p; + char username[STRINGLENGTH]; + register char *supfname,*q,*arg; + register COLLECTION *c,*lastC; + register FILE *f; + register int bogus; + register struct passwd *pw; + register TREE *t; + TREE *collT; /* collections we are interested in */ + long timenow; /* startup time */ + int checkcoll (); + int oflags,aflags; + int cwant; +#ifdef MACH +#ifdef __STDC__ + void (*oldsigsys)(); +#else + int (*oldsigsys)(); +#endif +#endif /* MACH */ + char *fmttime(); + + sysflag = FALSE; /* not system upgrade */ + timeflag = FALSE; /* don't print times */ +#if MACH + rpauseflag = FALSE; /* don't disable resource pausing */ +#endif /* MACH */ + xpatchflag = FALSE; /* not normally crosspatched */ + scmdebug = 0; /* level zero, no SCM debugging */ + portdebug = FALSE; /* no debugging ports */ + + collT = NULL; + oflags = aflags = 0; + while (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') { + doswitch (&argv[1][1],&collT,&oflags,&aflags); + --argc; + argv++; + } + if (argc == 1 && !sysflag) + logquit (1,"Need either -s or supfile"); +#if MACH + oldsigsys = signal (SIGSYS,SIG_IGN); + if (rpauseflag != TRUE) + if (syscall (SYS_rpause,ENOSPC,RPAUSE_ALL,RPAUSE_DISABLE) < 0) + rpauseflag = TRUE; + (void) signal (SIGSYS,oldsigsys); +#endif /* MACH */ + if (sysflag) + (void) sprintf (supfname = buf, + timeflag?FILESUPTDEFAULT:FILESUPDEFAULT, + DEFDIR); + else { + supfname = argv[1]; + if (strcmp (supfname,"-") == 0) + supfname = ""; + --argc; + argv++; + } + cwant = argc > 1; + while (argc > 1) { + t = Tinsert (&collT,argv[1],TRUE); + t->Twant = TRUE; + --argc; + argv++; + } + if ((p = (char *)getlogin()) || + ((pw = getpwuid ((int)getuid())) && (p = pw->pw_name))) + (void) strcpy (username,p); + else + *username = '\0'; + if (*supfname) { + f = fopen (supfname,"r"); + if (f == NULL) + logquit (1,"Can't open supfile %s",supfname); + } else + f = stdin; + firstC = NULL; + lastC = NULL; + bogus = FALSE; + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = '\0'; + if (index ("#;:",*p)) continue; + arg = nxtarg (&p," \t"); + if (*arg == '\0') { + logerr ("Missing collection name in supfile"); + bogus = TRUE; + continue; + } + if (cwant) { + register TREE *t; + if ((t = Tsearch (collT,arg)) == NULL) + continue; + t->Tcount++; + } + c = (COLLECTION *) malloc (sizeof(COLLECTION)); + if (firstC == NULL) firstC = c; + if (lastC != NULL) lastC->Cnext = c; + lastC = c; + if (parsecoll(c,arg,p) < 0) { + bogus = TRUE; + continue; + } + c->Cflags |= oflags; + c->Cflags &= ~aflags; + if (t = Tsearch (collT,c->Cname)) { + c->Cflags |= t->Toflags; + c->Cflags &= ~t->Taflags; + } + if ((c->Cflags&CFMAIL) && c->Cnotify == NULL) { + if (*username == '\0') + logerr ("User unknown, notification disabled"); + else + c->Cnotify = salloc (username); + } + if (c->Cbase == NULL) { + (void) sprintf (buf,FILEBASEDEFAULT,c->Cname); + c->Cbase = salloc (buf); + } + } + if (bogus) logquit (1,"Aborted due to supfile errors"); + if (f != stdin) (void) fclose (f); + if (cwant) (void) Tprocess (collT,checkcoll); + Tfree (&collT); + if (firstC == NULL) logquit (1,"No collections to upgrade"); + timenow = time ((long *)NULL); + if (*supfname == '\0') + p = "standard input"; + else if (sysflag) + p = "system software"; + else + (void) sprintf (p = buf,"file %s",supfname); + loginfo ("SUP %d.%d (%s) for %s at %s",PROTOVERSION,PGMVERSION, + scmversion,p,fmttime (timenow)); + return (salloc (supfname)); +} + +checkcoll (t) +register TREE *t; +{ + if (!t->Twant) return (SCMOK); + if (t->Tcount == 0) + logerr ("Collection %s not found",t->Tname); + if (t->Tcount > 1) + logerr ("Collection %s found more than once",t->Tname); + return (SCMOK); +} diff --git a/usr.bin/sup/src/supcmeat.c b/usr.bin/sup/src/supcmeat.c new file mode 100644 index 00000000000..daf07be7e2a --- /dev/null +++ b/usr.bin/sup/src/supcmeat.c @@ -0,0 +1,1468 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * sup "meat" routines + ********************************************************************** + * HISTORY + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supcmeat.c,v $ + * Revision 1.1 1995/12/16 11:46:56 deraadt + * add sup to the tree + * + * Revision 1.6 1995/10/29 23:54:47 christos + * - runio fails when result != 0 not only < 0 + * - print vis-encoded file in the scanner. + * + * Revision 1.5 1995/06/24 16:21:48 christos + * - Don't use system(3) to fork processes. It is a big security hole. + * - Encode the filenames in the scan files using strvis(3), so filenames + * that contain newlines or other weird characters don't break the scanner. + * + * Revision 1.4 1995/06/03 21:21:56 christos + * Changes to write ascii timestamps in the when files. + * Looked into making it 64 bit clean, but it is hopeless. + * Added little program to convert from the old timestamp files + * into the new ones. + * + * Revision 1.3 1993/08/04 17:46:18 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.2 1993/05/24 18:57:50 brezak + * Use /var/tmp for NetBSD + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.16 92/09/09 22:04:51 mrt + * Really added bww's recvone changes this time. + * Added code to support non-crypting version of sup. + * [92/09/01 mrt] + * + * Revision 1.15 92/08/11 12:07:09 mrt + * Added support to add release to FILEWHEN name. + * Updated variable arguemnt list usage - bww + * Updated recvone() to take a va_list - bww + * Changed conditional for rpausing code from CMUCS to MACH + * [92/07/24 mrt] + * + * Revision 1.14 92/02/08 18:24:12 mja + * Only apply "keep" mode when local file is strictly newer + * otherwise allow update as before if necessary. + * [92/02/08 18:09:00 mja] + * + * Added support for -k (keep) option to needone(). Rewrote and + * commented other parts of needone(). + * [92/01/17 vdelvecc] + * + * Revision 1.13 91/05/16 14:49:41 ern + * Add timestap to fileserver. + * Drop day of the week from 5 messages. + * [91/05/16 14:47:53 ern] + * + * Revision 1.12 89/08/23 14:55:44 gm0w + * Changed msgf routines to msg routines. + * [89/08/23 gm0w] + * + * Revision 1.11 89/08/03 19:49:10 mja + * Updated to use v*printf() in place of _doprnt(). + * [89/04/19 mja] + * + * Revision 1.10 89/06/18 14:41:27 gm0w + * Fixed up some notify messages of errors to use "SUP:" prefix. + * [89/06/18 gm0w] + * + * Revision 1.9 89/06/10 15:12:17 gm0w + * Changed to always use rename to install targets. This breaks hard + * links and recreates those known to sup, other links will be orphaned. + * [89/06/10 gm0w] + * + * Revision 1.8 89/05/24 15:04:23 gm0w + * Added code to check for EINVAL from FSPARAM ioctl for disk + * space check failures when the ioctl is not implemented. + * [89/05/24 gm0w] + * + * Revision 1.7 89/01/16 18:22:28 gm0w + * Changed needone() to check that mode of files match before + * setting update if times also match. + * [89/01/16 gm0w] + * + * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added timeout to backoff. + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support. + * + * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to be less verbose when updating files that have + * already been successfully upgraded. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Converted to end connection with more information. + * Added done routine. Modified goaway routine to free old + * goawayreason. + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Use computeBackoff from scm instead of doing it ourselves. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Split off from sup.c and reindented goaway calls. + * + ********************************************************************** + */ + +#include "supcdefs.h" +#include <sys/wait.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +TREE *lastT; /* last filenames in collection */ +jmp_buf sjbuf; /* jump location for network errors */ +int dontjump; /* flag to void sjbuf */ +int cancompress=FALSE; /* Can we do compression? */ +int docompress=FALSE; /* Do we do compression? */ + +extern COLLECTION *thisC; /* collection list pointer */ +extern int rpauseflag; /* don't disable resource pausing */ +extern int portdebug; /* network debugging ports */ + +#if __STDC__ +int done(int,char *,...); +int goaway(char *,...); +#endif + +/************************************************* + *** U P G R A D E C O L L E C T I O N *** + *************************************************/ + +/* The next two routines define the fsm to support multiple fileservers + * per collection. + */ +getonehost (t,state) +register TREE *t; +int *state; +{ + if (t->Tflags != *state) + return (SCMOK); + if (*state != 0 && t->Tmode == SCMEOF) { + t->Tflags = 0; + return (SCMOK); + } + if (*state == 2) + t->Tflags--; + else + t->Tflags++; + thisC->Chost = t; + return (SCMEOF); +} + +TREE *getcollhost (tout,backoff,state,nhostsp) +int *tout,*backoff,*state,*nhostsp; +{ + static int laststate = 0; + static int nhosts = 0; + + if (*state != laststate) { + *nhostsp = nhosts; + laststate = *state; + nhosts = 0; + } + if (Tprocess (thisC->Chtree,getonehost,*state) == SCMEOF) { + if (*state != 0 && nhosts == 0 && !dobackoff (tout,backoff)) + return (NULL); + nhosts++; + return (thisC->Chost); + } + if (nhosts == 0) + return (NULL); + if (*state == 2) + (*state)--; + else + (*state)++; + return (getcollhost (tout,backoff,state,nhostsp)); +} + +/* Upgrade a collection from the file server on the appropriate + * host machine. + */ + +getcoll () +{ + register TREE *t; + register int x; + int tout,backoff,state,nhosts; + + collname = thisC->Cname; + tout = thisC->Ctimeout; + lastT = NULL; + backoff = 2; + state = 0; + nhosts = 0; + for (;;) { + t = getcollhost (&tout,&backoff,&state,&nhosts); + if (t == NULL) { + finishup (SCMEOF); + notify ((char *)NULL); + return; + } + t->Tmode = SCMEOF; + dontjump = FALSE; + if (!setjmp (sjbuf) && !signon (t,nhosts,&tout) && !setup (t)) + break; + (void) requestend (); + } + dontjump = FALSE; + if (setjmp (sjbuf)) + x = SCMERR; + else { + login (); + listfiles (); + recvfiles (); + x = SCMOK; + } + if (thisC->Clockfd >= 0) { + (void) close (thisC->Clockfd); + thisC->Clockfd = -1; + } + finishup (x); + notify ((char *)NULL); +} + +/*** Sign on to file server ***/ + +int signon (t,nhosts,tout) +register TREE *t; +int nhosts; +int *tout; +{ + register int x; + int timeout; + long tloc; + + if ((thisC->Cflags&CFLOCAL) == 0 && thishost (thisC->Chost->Tname)) { + vnotify ("SUP: Skipping local collection %s\n",collname); + t->Tmode = SCMEOF; + return (TRUE); + } + if (nhosts == 1) + timeout = *tout; + else + timeout = 0; + x = request (portdebug?DEBUGFPORT:FILEPORT, + thisC->Chost->Tname,&timeout); + if (nhosts == 1) + *tout = timeout; + if (x != SCMOK) { + if (nhosts) { + notify ("SUP: Can't connect to host %s\n", + thisC->Chost->Tname); + t->Tmode = SCMEOF; + } else + t->Tmode = SCMOK; + return (TRUE); + } + xpatch = FALSE; + x = msgsignon (); /* signon to fileserver */ + if (x != SCMOK) + goaway ("Error sending signon request to fileserver"); + x = msgsignonack (); /* receive signon ack from fileserver */ + if (x != SCMOK) + goaway ("Error reading signon reply from fileserver"); + tloc = time ((long *)NULL); + vnotify ("SUP Fileserver %d.%d (%s) %d on %s at %.8s\n", + protver,pgmver,scmver,fspid,remotehost(),ctime (&tloc) + 11); + free (scmver); + scmver = NULL; + if (protver < 4) { + dontjump = TRUE; + goaway ("Fileserver sup protocol version is obsolete."); + notify ("SUP: This version of sup can only communicate with a fileserver using at least\n"); + notify ("SUP: version 4 of the sup network protocol. You should either run a newer\n"); + notify ("SUP: version of the sup fileserver or find an older version of sup.\n"); + t->Tmode = SCMEOF; + return (TRUE); + } + /* If protocol is > 7 then try compression */ + if (protver > 7) { + cancompress = TRUE; + } + return (FALSE); +} + +/*** Tell file server what to connect to ***/ + +setup (t) +register TREE *t; +{ + char relsufix[STRINGLENGTH]; + register int f,x; + struct stat sbuf; + + if (chdir (thisC->Cbase) < 0) + goaway ("Can't change to base directory %s",thisC->Cbase); + if (stat ("sup",&sbuf) < 0) { + (void) mkdir ("sup",0755); + if (stat("sup",&sbuf) < 0) + goaway ("Can't create directory %s/sup",thisC->Cbase); + vnotify ("SUP Created directory %s/sup\n",thisC->Cbase); + } + if (thisC->Cprefix && chdir (thisC->Cprefix) < 0) + goaway ("Can't change to %s from base directory %s", + thisC->Cprefix,thisC->Cbase); + if (stat (".",&sbuf) < 0) + goaway ("Can't stat %s directory %s", + thisC->Cprefix?"prefix":"base", + thisC->Cprefix?thisC->Cprefix:thisC->Cbase); + if (thisC->Cprefix) (void) chdir (thisC->Cbase); + /* read time of last upgrade from when file */ + + if ((thisC->Cflags&CFURELSUF) && thisC->Crelease) + (void) sprintf (relsufix,".%s",thisC->Crelease); + else + relsufix[0] = '\0'; + lasttime = getwhen(collname,relsufix); + /* setup for msgsetup */ + basedir = thisC->Chbase; + basedev = sbuf.st_dev; + baseino = sbuf.st_ino; + listonly = (thisC->Cflags&CFLIST); + newonly = ((thisC->Cflags&(CFALL|CFDELETE|CFOLD)) == 0); + release = thisC->Crelease; + x = msgsetup (); + if (x != SCMOK) + goaway ("Error sending setup request to file server"); + x = msgsetupack (); + if (x != SCMOK) + goaway ("Error reading setup reply from file server"); + if (setupack == FSETUPOK) { + /* Test encryption */ + if (netcrypt (thisC->Ccrypt) != SCMOK) + goaway ("Running non-crypting sup"); + crypttest = CRYPTTEST; + x = msgcrypt (); + if (x != SCMOK) + goaway ("Error sending encryption test request"); + x = msgcryptok (); + if (x == SCMEOF) + goaway ("Data encryption test failed"); + if (x != SCMOK) + goaway ("Error reading encryption test reply"); + return (FALSE); + } + switch (setupack) { + case FSETUPSAME: + notify ("SUP: Attempt to upgrade from same host to same directory\n"); + done (FDONESRVERROR,"Overwrite error"); + case FSETUPHOST: + notify ("SUP: This host has no permission to access %s\n", + collname); + done (FDONESRVERROR,"Permission denied"); + case FSETUPOLD: + notify ("SUP: This version of SUP is too old for the fileserver\n"); + done (FDONESRVERROR,"Obsolete client"); + case FSETUPRELEASE: + notify ("SUP: Invalid release %s for collection %s\n", + release == NULL ? DEFRELEASE : release,collname); + done (FDONESRVERROR,"Invalid release"); + case FSETUPBUSY: + vnotify ("SUP Fileserver is currently busy\n"); + t->Tmode = SCMOK; + doneack = FDONESRVERROR; + donereason = "Fileserver is busy"; + (void) netcrypt ((char *)NULL); + (void) msgdone (); + return (TRUE); + default: + goaway ("Unrecognized file server setup status %d",setupack); + } + /* NOTREACHED */ +} + +/*** Tell file server what account to use ***/ + +int login () +{ + char buf[STRINGLENGTH]; + register int f,x; + + /* lock collection if desired */ + (void) sprintf (buf,FILELOCK,collname); + f = open (buf,O_RDONLY,0); + if (f >= 0) { + if (flock (f,(LOCK_EX|LOCK_NB)) < 0) { + if (errno != EWOULDBLOCK) + goaway ("Can't lock collection %s",collname); + if (flock (f,(LOCK_SH|LOCK_NB)) < 0) { + (void) close (f); + if (errno == EWOULDBLOCK) + goaway ("Collection %s is locked by another sup",collname); + goaway ("Can't lock collection %s",collname); + } + vnotify ("SUP Waiting for exclusive access lock\n"); + if (flock (f,LOCK_EX) < 0) { + (void) close (f); + goaway ("Can't lock collection %s",collname); + } + } + thisC->Clockfd = f; + vnotify ("SUP Locked collection %s for exclusive access\n",collname); + } + logcrypt = (char *) NULL; + loguser = thisC->Clogin; + logpswd = thisC->Cpswd; + +#ifndef CRYPTING /* Define CRYPTING for backwards compatibility with old supfileservers */ + if (thisC->Clogin != (char *) NULL) /* othewise we only encrypt if there is a login id */ +#endif /* CRYPTING */ + { + logcrypt = CRYPTTEST; + (void) netcrypt (PSWDCRYPT); /* encrypt password data */ + } + x = msglogin (); +#ifndef CRYPTING + if (thisC->Clogin != (char *) NULL) +#endif + (void) netcrypt ((char *)NULL); /* turn off encryption */ + if (x != SCMOK) + goaway ("Error sending login request to file server"); + x = msglogack (); + if (x != SCMOK) + goaway ("Error reading login reply from file server"); + if (logack == FLOGNG) { + notify ("SUP: %s\n",logerror); + free (logerror); + logerror = NULL; + notify ("SUP: Improper login to %s account", + thisC->Clogin ? thisC->Clogin : "default"); + done (FDONESRVERROR,"Improper login"); + } + if (netcrypt (thisC->Ccrypt) != SCMOK) /* restore encryption */ + goaway("Running non-crypting sup"); +} + +/* + * send list of files that we are not interested in. receive list of + * files that are on the repository that could be upgraded. Find the + * ones that we need. Receive the list of files that the server could + * not access. Delete any files that have been upgraded in the past + * which are no longer on the repository. + */ + +int listfiles () +{ + int needone(), denyone(), deleteone(); + char buf[STRINGLENGTH]; + char relsufix[STRINGLENGTH]; + register char *p,*q; + register FILE *f; + register int x; + + + if ((thisC->Cflags&CFURELSUF) && release) + (void) sprintf (relsufix,".%s",release); + else + relsufix[0] = '\0'; + (void) sprintf (buf,FILELAST,collname,relsufix); + f = fopen (buf,"r"); + if (f) { + while (p = fgets (buf,STRINGLENGTH,f)) { + if (q = index (p,'\n')) *q = '\0'; + if (index ("#;:",*p)) continue; + (void) Tinsert (&lastT,p,FALSE); + } + (void) fclose (f); + } + refuseT = NULL; + (void) sprintf (buf,FILEREFUSE,collname); + f = fopen (buf,"r"); + if (f) { + while (p = fgets (buf,STRINGLENGTH,f)) { + if (q = index (p,'\n')) *q = '\0'; + if (index ("#;:",*p)) continue; + (void) Tinsert (&refuseT,p,FALSE); + } + (void) fclose (f); + } + vnotify ("SUP Requesting changes since %s",ctime (&lasttime) + 4); + x = msgrefuse (); + if (x != SCMOK) + goaway ("Error sending refuse list to file server"); + listT = NULL; + x = msglist (); + if (x != SCMOK) + goaway ("Error reading file list from file server"); + if (thisC->Cprefix) (void) chdir (thisC->Cprefix); + needT = NULL; + (void) Tprocess (listT,needone); + Tfree (&listT); + x = msgneed (); + if (x != SCMOK) + goaway ("Error sending needed files list to file server"); + Tfree (&needT); + denyT = NULL; + x = msgdeny (); + if (x != SCMOK) + goaway ("Error reading denied files list from file server"); + if (thisC->Cflags&CFVERBOSE) + (void) Tprocess (denyT,denyone); + Tfree (&denyT); + if (thisC->Cflags&(CFALL|CFDELETE|CFOLD)) + (void) Trprocess (lastT,deleteone); + Tfree (&refuseT); +} + +needone (t) +register TREE *t; +{ + register TREE *newt; + register int exists, fetch; + struct stat sbuf; + + newt = Tinsert (&lastT,t->Tname,TRUE); + newt->Tflags |= FUPDATE; + fetch = TRUE; + if ((thisC->Cflags&CFALL) == 0) { + if ((t->Tflags&FNEW) == 0 && (thisC->Cflags&CFOLD) == 0) + return (SCMOK); + if ((t->Tmode&S_IFMT) == S_IFLNK) + exists = (lstat (t->Tname,&sbuf) == 0); + else + exists = (stat (t->Tname,&sbuf) == 0); + /* This is moderately complicated: + If the file is the wrong type or doesn't exist, we need to + fetch the whole file. If the file is a special file, we + rely solely on the server: if the file changed, we do an + update; otherwise nothing. If the file is a normal file, + we check timestamps. If we are in "keep" mode, we fetch if + the file on the server is newer, and do nothing otherwise. + Otherwise, we fetch if the timestamp is wrong; if the file + changed on the server but the timestamp is right, we do an + update. (Update refers to updating stat information, i.e. + timestamp, owner, mode bits, etc.) */ + if (exists && (sbuf.st_mode&S_IFMT) == (t->Tmode&S_IFMT)) + if ((t->Tmode&S_IFMT) != S_IFREG) + if (t->Tflags&FNEW) + fetch = FALSE; + else return (SCMOK); + else if ((thisC->Cflags&CFKEEP) && + sbuf.st_mtime > t->Tmtime) + return (SCMOK); + else if (sbuf.st_mtime == t->Tmtime) + if (t->Tflags&FNEW) + fetch = FALSE; + else return (SCMOK); + } + /* If we get this far, we're either doing an update or a full fetch. */ + newt = Tinsert (&needT,t->Tname,TRUE); + if (!fetch && (t->Tmode&S_IFMT) == S_IFREG) + newt->Tflags |= FUPDATE; + return (SCMOK); +} + +denyone (t) +register TREE *t; +{ + vnotify ("SUP: Access denied to %s\n",t->Tname); + return (SCMOK); +} + +deleteone (t) +TREE *t; +{ + struct stat sbuf; + register int x; + register char *name = t->Tname; + + if (t->Tflags&FUPDATE) /* in current upgrade list */ + return (SCMOK); + if (lstat(name,&sbuf) < 0) /* doesn't exist */ + return (SCMOK); + /* is it a symbolic link ? */ + if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { + if (Tlookup (refuseT,name)) { + vnotify ("SUP Would not delete symbolic link %s\n", + name); + return (SCMOK); + } + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would delete symbolic link %s\n",name); + return (SCMOK); + } + if ((thisC->Cflags&CFDELETE) == 0) { + notify ("SUP Please delete symbolic link %s\n",name); + t->Tflags |= FUPDATE; + return (SCMOK); + } + x = unlink (name); + if (x < 0) { + notify ("SUP: Unable to delete symbolic link %s\n", + name); + t->Tflags |= FUPDATE; + return (SCMOK); + } + vnotify ("SUP Deleted symbolic link %s\n",name); + return (SCMOK); + } + /* is it a directory ? */ + if ((sbuf.st_mode & S_IFMT) == S_IFDIR) { + if (Tlookup (refuseT,name)) { + vnotify ("SUP Would not delete directory %s\n",name); + return (SCMOK); + } + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would delete directory %s\n",name); + return (SCMOK); + } + if ((thisC->Cflags&CFDELETE) == 0) { + notify ("SUP Please delete directory %s\n",name); + t->Tflags |= FUPDATE; + return (SCMOK); + } + (void) rmdir (name); + if (lstat(name,&sbuf) == 0) { + notify ("SUP: Unable to delete directory %s\n",name); + t->Tflags |= FUPDATE; + return (SCMOK); + } + vnotify ("SUP Deleted directory %s\n",name); + return (SCMOK); + } + /* it is a file */ + if (Tlookup (refuseT,name)) { + vnotify ("SUP Would not delete file %s\n",name); + return (SCMOK); + } + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would delete file %s\n",name); + return (SCMOK); + } + if ((thisC->Cflags&CFDELETE) == 0) { + notify ("SUP Please delete file %s\n",name); + t->Tflags |= FUPDATE; + return (SCMOK); + } + x = unlink (name); + if (x < 0) { + notify ("SUP: Unable to delete file %s\n",name); + t->Tflags |= FUPDATE; + return (SCMOK); + } + vnotify ("SUP Deleted file %s\n",name); + return (SCMOK); +} + +/*************************************** + *** R E C E I V E F I L E S *** + ***************************************/ + +/* Note for these routines, return code SCMOK generally means + * NETWORK communication is OK; it does not mean that the current + * file was correctly received and stored. If a file gets messed + * up, too bad, just print a message and go on to the next one; + * but if the network gets messed up, the whole sup program loses + * badly and best just stop the program as soon as possible. + */ + +recvfiles () +{ + register int x; + int recvone (); + int recvmore; + + /* Does the protocol support compression */ + if (cancompress) { + /* Check for compression on sending files */ + docompress = (thisC->Cflags&CFCOMPRESS); + x = msgcompress(); + if ( x != SCMOK) + goaway ("Error sending compression check to server"); + if (docompress) + vnotify("SUP Using compressed file transfer\n"); + } + recvmore = TRUE; + upgradeT = NULL; + do { + x = msgsend (); + if (x != SCMOK) + goaway ("Error sending receive file request to file server"); + (void) Tinsert (&upgradeT,(char *)NULL,FALSE); + x = msgrecv (recvone,&recvmore); + if (x != SCMOK) + goaway ("Error receiving file from file server"); + Tfree (&upgradeT); + } while (recvmore); +} + +/* prepare the target, if necessary */ +prepare (name,mode,newp,statp) +char *name; +int mode,*newp; +struct stat *statp; +{ + register char *type; + + if (mode == S_IFLNK) + *newp = (lstat (name,statp) < 0); + else + *newp = (stat (name,statp) < 0); + if (*newp) { + if (thisC->Cflags&CFLIST) + return (FALSE); + if (establishdir (name)) + return (TRUE); + return (FALSE); + } + if (mode == (statp->st_mode&S_IFMT)) + return (FALSE); + *newp = TRUE; + switch (statp->st_mode&S_IFMT) { + case S_IFDIR: + type = "directory"; + break; + case S_IFLNK: + type = "symbolic link"; + break; + case S_IFREG: + type = "regular file"; + break; + default: + type = "unknown file"; + break; + } + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would remove %s %s\n",type,name); + return (FALSE); + } + if ((statp->st_mode&S_IFMT) == S_IFDIR) { + if (rmdir (name) < 0) + runp ("rm","rm","-rf",name,0); + } else + (void) unlink (name); + if (stat (name,statp) < 0) { + vnotify ("SUP Removed %s %s\n",type,name); + return (FALSE); + } + notify ("SUP: Couldn't remove %s %s\n",type,name); + return (TRUE); +} + +recvone (t,ap) +register TREE *t; +va_list ap; +{ + register int x; + int new; + struct stat sbuf; + int linkone (),execone (); + int *recvmore = va_arg(ap,int *); + + /* check for end of file list */ + if (t == NULL) { + *recvmore = FALSE; + return (SCMOK); + } + /* check for failed access at fileserver */ + if (t->Tmode == 0) { + notify ("SUP: File server unable to transfer file %s\n", + t->Tname); + thisC->Cnogood = TRUE; + return (SCMOK); + } + if (prepare (t->Tname,t->Tmode&S_IFMT,&new,&sbuf)) { + notify ("SUP: Can't prepare path for %s\n",t->Tname); + if ((t->Tmode&S_IFMT) == S_IFREG) { + x = readskip (); /* skip over file */ + if (x != SCMOK) + goaway ("Can't skip file transfer"); + } + thisC->Cnogood = TRUE; + return (SCMOK); + } + /* make file mode specific changes */ + switch (t->Tmode&S_IFMT) { + case S_IFDIR: + x = recvdir (t,new,&sbuf); + break; + case S_IFLNK: + x = recvsym (t,new,&sbuf); + break; + case S_IFREG: + x = recvreg (t,new,&sbuf); + break; + default: + goaway ("Unknown file type %o\n",t->Tmode&S_IFMT); + } + if (x) { + thisC->Cnogood = TRUE; + return (SCMOK); + } + if ((t->Tmode&S_IFMT) == S_IFREG) + (void) Tprocess (t->Tlink,linkone,t->Tname); + (void) Tprocess (t->Texec,execone); + return (SCMOK); +} + +int recvdir (t,new,statp) /* receive directory from network */ +register TREE *t; +register int new; +register struct stat *statp; +{ + struct timeval tbuf[2]; + + if (new) { + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would create directory %s\n",t->Tname); + return (FALSE); + } + (void) mkdir (t->Tname,0755); + if (stat (t->Tname,statp) < 0) { + notify ("SUP: Can't create directory %s\n",t->Tname); + return (TRUE); + } + } + if ((t->Tflags&FNOACCT) == 0) { + /* convert user and group names to local ids */ + ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode); + } + if (!new && (t->Tflags&FNEW) == 0 && statp->st_mtime == t->Tmtime) { + if (t->Tflags&FNOACCT) + return (FALSE); + if (statp->st_uid == t->Tuid && statp->st_gid == t->Tgid) + return (FALSE); + } + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would update directory %s\n",t->Tname); + return (FALSE); + } + if ((t->Tflags&FNOACCT) == 0) { + (void) chown (t->Tname,t->Tuid,t->Tgid); + (void) chmod (t->Tname,t->Tmode&S_IMODE); + } + tbuf[0].tv_sec = time((long *)NULL); tbuf[0].tv_usec = 0; + tbuf[1].tv_sec = t->Tmtime; tbuf[1].tv_usec = 0; + (void) utimes (t->Tname,tbuf); + vnotify ("SUP %s directory %s\n",new?"Created":"Updated",t->Tname); + return (FALSE); +} + +int recvsym (t,new,statp) /* receive symbolic link */ +register TREE *t; +register int new; +register struct stat *statp; +{ + char buf[STRINGLENGTH]; + int n; + register char *linkname; + + if (t->Tlink == NULL || t->Tlink->Tname == NULL) { + notify ("SUP: Missing linkname for symbolic link %s\n", + t->Tname); + return (TRUE); + } + linkname = t->Tlink->Tname; + if (!new && (t->Tflags&FNEW) == 0 && + (n = readlink (t->Tname,buf,sizeof(buf))) >= 0 && + (n == strlen (linkname)) && (strncmp (linkname,buf,n) == 0)) + return (FALSE); + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would %s symbolic link %s to %s\n", + new?"create":"update",t->Tname,linkname); + return (FALSE); + } + if (!new) + (void) unlink (t->Tname); + if (symlink (linkname,t->Tname) < 0 || lstat(t->Tname,statp) < 0) { + notify ("SUP: Unable to create symbolic link %s\n",t->Tname); + return (TRUE); + } + vnotify ("SUP Created symbolic link %s to %s\n",t->Tname,linkname); + return (FALSE); +} + +int recvreg (t,new,statp) /* receive file from network */ +register TREE *t; +register int new; +register struct stat *statp; +{ + register FILE *fin,*fout; + char dirpart[STRINGLENGTH],filepart[STRINGLENGTH]; + char filename[STRINGLENGTH],buf[STRINGLENGTH]; + struct timeval tbuf[2]; + register int x; + register char *p; + + if (t->Tflags&FUPDATE) { + if ((t->Tflags&FNOACCT) == 0) { + /* convert user and group names to local ids */ + ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid, + &t->Tmode); + } + if (!new && (t->Tflags&FNEW) == 0 && + statp->st_mtime == t->Tmtime) { + if (t->Tflags&FNOACCT) + return (FALSE); + if (statp->st_uid == t->Tuid && + statp->st_gid == t->Tgid) + return (FALSE); + } + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would update file %s\n",t->Tname); + return (FALSE); + } + vnotify ("SUP Updating file %s\n",t->Tname); + if ((t->Tflags&FNOACCT) == 0) { + (void) chown (t->Tname,t->Tuid,t->Tgid); + (void) chmod (t->Tname,t->Tmode&S_IMODE); + } + tbuf[0].tv_sec = time((long *)NULL); tbuf[0].tv_usec = 0; + tbuf[1].tv_sec = t->Tmtime; tbuf[1].tv_usec = 0; + (void) utimes (t->Tname,tbuf); + return (FALSE); + } + if (thisC->Cflags&CFLIST) { + if (new) + p = "create"; + else if (statp->st_mtime < t->Tmtime) + p = "receive new"; + else if (statp->st_mtime > t->Tmtime) + p = "receive old"; + else + p = "receive"; + vnotify ("SUP Would %s file %s\n",p,t->Tname); + return (FALSE); + } + vnotify ("SUP Receiving file %s\n",t->Tname); + if (!new && (t->Tmode&S_IFMT) == S_IFREG && + (t->Tflags&FBACKUP) && (thisC->Cflags&CFBACKUP)) { + fin = fopen (t->Tname,"r"); /* create backup */ + if (fin == NULL) { + x = readskip (); /* skip over file */ + if (x != SCMOK) + goaway ("Can't skip file transfer"); + notify ("SUP: Can't open %s to create backup\n", + t->Tname); + return (TRUE); /* mark upgrade as nogood */ + } + path (t->Tname,dirpart,filepart); + (void) sprintf (filename,FILEBACKUP,dirpart,filepart); + fout = fopen (filename,"w"); + if (fout == NULL) { + (void) sprintf (buf,FILEBKDIR,dirpart); + (void) mkdir (buf,0755); + fout = fopen (filename,"w"); + } + if (fout == NULL) { + x = readskip (); /* skip over file */ + if (x != SCMOK) + goaway ("Can't skip file transfer"); + notify ("SUP: Can't create %s for backup\n",filename); + (void) fclose (fin); + return (TRUE); + } + ffilecopy (fin,fout); + (void) fclose (fin); + (void) fclose (fout); + vnotify ("SUP Backup of %s created\n", t->Tname); + } + x = copyfile (t->Tname,(char *)NULL); + if (x) + return (TRUE); + if ((t->Tflags&FNOACCT) == 0) { + /* convert user and group names to local ids */ + ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode); + (void) chown (t->Tname,t->Tuid,t->Tgid); + (void) chmod (t->Tname,t->Tmode&S_IMODE); + } + tbuf[0].tv_sec = time((long *)NULL); tbuf[0].tv_usec = 0; + tbuf[1].tv_sec = t->Tmtime; tbuf[1].tv_usec = 0; + (void) utimes (t->Tname,tbuf); + return (FALSE); +} + +linkone (t,fname) /* link to file already received */ +register TREE *t; +register char **fname; +{ + struct stat fbuf,sbuf; + register char *name = t->Tname; + int new,x; + char *type; + + if (stat(*fname,&fbuf) < 0) { /* source file */ + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would link %s to %s\n",name,*fname); + return (SCMOK); + } + notify ("SUP: Can't link %s to missing file %s\n",name,*fname); + thisC->Cnogood = TRUE; + return (SCMOK); + } + if (prepare (name,S_IFREG,&new,&sbuf)) { + notify ("SUP: Can't prepare path for link %s\n",name); + thisC->Cnogood = TRUE; + return (SCMOK); + } + if (!new && (t->Tflags&FNEW) == 0 && + fbuf.st_dev == sbuf.st_dev && fbuf.st_ino == sbuf.st_ino) + return (SCMOK); + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would link %s to %s\n",name,*fname); + return (SCMOK); + } + (void) unlink (name); + type = ""; + if ((x = link (*fname,name)) < 0) { + type = "symbolic "; + x = symlink (*fname,name); + } + if (x < 0 || lstat(name,&sbuf) < 0) { + notify ("SUP: Unable to create %slink %s\n",type,name); + return (TRUE); + } + vnotify ("SUP Created %slink %s to %s\n",type,name,*fname); + return (SCMOK); +} + +execone (t) /* execute command for file */ +register TREE *t; +{ + union wait w; + + if (thisC->Cflags&CFLIST) { + vnotify ("SUP Would execute %s\n",t->Tname); + return (SCMOK); + } + if ((thisC->Cflags&CFEXECUTE) == 0) { + notify ("SUP Please execute %s\n",t->Tname); + return (SCMOK); + } + vnotify ("SUP Executing %s\n",t->Tname); + + w.w_status = system (t->Tname); + if (WIFEXITED(w) && w.w_retcode != 0) { + notify ("SUP: Execute command returned failure status %#o\n", + w.w_retcode); + thisC->Cnogood = TRUE; + } else if (WIFSIGNALED(w)) { + notify ("SUP: Execute command killed by signal %d\n", + w.w_termsig); + thisC->Cnogood = TRUE; + } else if (WIFSTOPPED(w)) { + notify ("SUP: Execute command stopped by signal %d\n", + w.w_stopsig); + thisC->Cnogood = TRUE; + } + return (SCMOK); +} + +int copyfile (to,from) +char *to; +char *from; /* 0 if reading from network */ +{ + register int fromf,tof,istemp,x; + char dpart[STRINGLENGTH],fpart[STRINGLENGTH]; + char tname[STRINGLENGTH]; + struct stat sbuf; + + static int thispid = 0; /* process id # */ + + if (from) { /* reading file */ + fromf = open (from,O_RDONLY,0); + if (fromf < 0) { + notify ("SUP: Can't open %s to copy to %s: %s\n", + from,to,errmsg (-1)); + return (TRUE); + } + } else /* reading network */ + fromf = -1; + istemp = TRUE; /* try to create temp file */ + lockout (TRUE); /* block interrupts */ + if (thispid == 0) thispid = getpid (); + /* Now try hard to find a temp file name. Try VERY hard. */ + for (;;) { + /* try destination directory */ + path (to,dpart,fpart); + (void) sprintf (tname,"%s/#%d.sup",dpart,thispid); + tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof >= 0) break; + /* try sup directory */ + if (thisC->Cprefix) (void) chdir (thisC->Cbase); + (void) sprintf (tname,"sup/#%d.sup",thispid); + tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof >= 0) { + if (thisC->Cprefix) (void) chdir (thisC->Cprefix); + break; + } + /* try base directory */ + (void) sprintf (tname,"#%d.sup",thispid); + tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (thisC->Cprefix) (void) chdir (thisC->Cprefix); + if (tof >= 0) break; +#ifdef VAR_TMP + /* try /var/tmp */ + (void) sprintf (tname,"/var/tmp/#%d.sup",thispid); + tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof >= 0) break; +#else + /* try /usr/tmp */ + (void) sprintf (tname,"/usr/tmp/#%d.sup",thispid); + tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof >= 0) break; +#endif + /* try /tmp */ + (void) sprintf (tname,"/tmp/#%d.sup",thispid); + tof = open (tname,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof >= 0) break; + istemp = FALSE; + /* give up: try to create output file */ + if (!docompress) + tof = open (to,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof >= 0) break; + /* no luck */ + notify ("SUP: Can't create %s or temp file for it\n",to); + lockout (FALSE); + if (fromf >= 0) + (void) close (fromf); + else { + x = readskip (); + if (x != SCMOK) + goaway ("Can't skip file transfer"); + } + return (TRUE); + } + if (fromf >= 0) { /* read file */ + x = filecopy (fromf,tof); + (void) close (fromf); + (void) close (tof); + if (x < 0) { + notify ("SUP: Error in copying %s to %s\n",from,to); + if (istemp) (void) unlink (tname); + lockout (FALSE); + return (TRUE); + } + } else { /* read network */ +#if MACH + if (!rpauseflag) { + int fsize; + struct fsparam fsp; + + x = prereadcount (&fsize); + if (x != SCMOK) { + if (istemp) (void) unlink (tname); + lockout (FALSE); + x = readskip (); + if (x != SCMOK) + goaway ("Can't skip file transfer"); + goaway ("Error in server space check"); + logquit (1,"Error in server space check"); + } + errno = 0; + if (ioctl (tof,FIOCFSPARAM,(char *)&fsp) < 0 && + errno != EINVAL) { + if (istemp) (void) unlink (tname); + lockout (FALSE); + x = readskip (); + if (x != SCMOK) + goaway ("Can't skip file transfer"); + goaway ("Error in disk space check"); + logquit (1,"Error in disk space check"); + } + if (errno == 0) { + fsize = (fsize + 1023) / 1024; + x = fsp.fsp_size * MAX (fsp.fsp_minfree,1) / 100; + fsp.fsp_free -= x; + if (fsize > MAX (fsp.fsp_free,0)) { + if (istemp) (void) unlink (tname); + lockout (FALSE); + x = readskip (); + if (x != SCMOK) + goaway ("Can't skip file transfer"); + goaway ("No disk space for file %s", to); + logquit (1,"No disk space for file %s",to); + } + } + } +#endif /* MACH */ + x = readfile (tof); + (void) close (tof); + if (x != SCMOK) { + if (istemp) (void) unlink (tname); + lockout (FALSE); + goaway ("Error in receiving %s\n",to); + } + } + if (!istemp) { /* no temp file used */ + lockout (FALSE); + return (FALSE); + } + /* uncompress it first */ + if (docompress) { + char *av[4]; + int ac = 0; + av[ac++] = "gzip"; + av[ac++] = "-d"; + av[ac++] = NULL; + if (runio(av, tname, to, NULL) != 0) { + /* Uncompress it onto the destination */ + notify ("SUP: Error in uncompressing file %s\n", + to); + (void) unlink (tname); + /* Just in case */ + (void) unlink (to); + lockout (FALSE); + return (TRUE); + } + (void) unlink (tname); + lockout (FALSE); + return (FALSE); + } + /* move to destination */ + if (rename (tname,to) == 0) { + (void) unlink (tname); + lockout (FALSE); + return (FALSE); + } + fromf = open (tname,O_RDONLY,0); + if (fromf < 0) { + notify ("SUP: Error in moving temp file to %s: %s\n", + to,errmsg (-1)); + (void) unlink (tname); + lockout (FALSE); + return (TRUE); + } + tof = open (to,(O_WRONLY|O_CREAT|O_TRUNC),0600); + if (tof < 0) { + (void) close (fromf); + notify ("SUP: Can't create %s from temp file: %s\n", + to,errmsg (-1)); + (void) unlink (tname); + lockout (FALSE); + return (TRUE); + } + x = filecopy (fromf,tof); + (void) close (fromf); + (void) close (tof); + (void) unlink (tname); + lockout (FALSE); + if (x < 0) { + notify ("SUP: Error in storing data in %s\n",to); + return (TRUE); + } + return (FALSE); +} + +/*** Finish connection with file server ***/ + +finishup (x) +int x; +{ + char tname[STRINGLENGTH],fname[STRINGLENGTH]; + char relsufix[STRINGLENGTH]; + char collrelname[STRINGLENGTH]; + long tloc; + FILE *finishfile; /* record of all filenames */ + int f,finishone(); + + if ((thisC->Cflags&CFURELSUF) && release) { + (void) sprintf (relsufix,".%s",release); + (void) sprintf (collrelname,"%s-%s",collname,release); + } else { + relsufix[0] = '\0'; + (void) strcpy (collrelname,collname); + } + dontjump = TRUE; /* once here, no more longjmp */ + (void) netcrypt ((char *)NULL); + if (protver < 6) { + /* done with server */ + if (x == SCMOK) + goaway ((char *)NULL); + (void) requestend (); + } + tloc = time ((long *)NULL); + if (x != SCMOK) { + notify ("SUP: Upgrade of %s aborted at %s", + collrelname,ctime (&tloc) + 4); + Tfree (&lastT); + if (protver < 6) return; + /* if we've not been blown off, make sure he is! */ + if (x != SCMEOF) + goaway ("Aborted"); + (void) requestend (); + return; + } + if (thisC->Cnogood) { + notify ("SUP: Upgrade of %s completed with errors at %s", + collrelname,ctime (&tloc) + 4); + notify ("SUP: Upgrade time will not be updated\n"); + Tfree (&lastT); + if (protver < 6) return; + done (FDONEUSRERROR,"Completed with errors"); + (void) requestend (); + return; + } + if (thisC->Cprefix) (void) chdir (thisC->Cbase); + vnotify ("SUP Upgrade of %s completed at %s", + collrelname,ctime (&tloc) + 4); + if (thisC->Cflags&CFLIST) { + Tfree (&lastT); + if (protver < 6) return; + done (FDONEDONTLOG,"List only"); + (void) requestend (); + return; + } + (void) sprintf (fname,FILEWHEN,collname,relsufix); + if (establishdir (fname)) { + notify ("SUP: Can't create directory for upgrade timestamp\n"); + Tfree (&lastT); + if (protver < 6) return; + done (FDONEUSRERROR,"Couldn't timestamp"); + (void) requestend (); + return; + } + if (!putwhen(fname, scantime)) { + notify ("SUP: Can't record current time in %s: %s\n", + fname,errmsg (-1)); + Tfree (&lastT); + if (protver < 6) return; + done (FDONEUSRERROR,"Couldn't timestamp"); + (void) requestend (); + return; + } + if (protver >= 6) { + /* At this point we have let the server go */ + /* "I'm sorry, we've had to let you go" */ + done (FDONESUCCESS,"Success"); + (void) requestend (); + } + (void) sprintf (tname,FILELASTTEMP,collname); + finishfile = fopen (tname,"w"); + if (finishfile == NULL) { + notify ("SUP: Can't record list of all files in %s\n",tname); + Tfree (&lastT); + return; + } + (void) Tprocess (lastT,finishone,finishfile); + (void) fclose (finishfile); + (void) sprintf (fname,FILELAST,collname,relsufix); + if (rename (tname,fname) < 0) + notify ("SUP: Can't change %s to %s\n",tname,fname); + (void) unlink (tname); + Tfree (&lastT); +} + +finishone (t,finishfile) +TREE *t; +FILE **finishfile; +{ + if ((thisC->Cflags&CFDELETE) == 0 || (t->Tflags&FUPDATE)) + fprintf (*finishfile,"%s\n",t->Tname); + return (SCMOK); +} + +#if __STDC__ +done (int value,char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +done (va_alist) +va_dcl +#endif +{ +#if !__STDC__ + int value; + char *fmt; +#endif + char buf[STRINGLENGTH]; + va_list ap; + + (void) netcrypt ((char *)NULL); +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + value = va_arg(ap,int); + fmt = va_arg(ap,char *); +#endif + if (fmt) + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (protver < 6) { + if (goawayreason) + free (goawayreason); + goawayreason = (fmt) ? salloc (buf) : (char *)NULL; + (void) msggoaway (); + } + else { + doneack = value; + donereason = (fmt) ? buf : (char *)NULL; + (void) msgdone (); + } + if (!dontjump) + longjmp (sjbuf,TRUE); +} +#if __STDC__ +goaway (char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +goaway (va_alist) +va_dcl +#endif +{ +#if !__STDC__ + register char *fmt; +#endif + char buf[STRINGLENGTH]; + va_list ap; + + (void) netcrypt ((char *)NULL); +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + fmt = va_arg(ap,char *); +#endif + if (fmt) { + vsnprintf(buf, sizeof(buf), fmt, ap); + goawayreason = buf; + } else + goawayreason = NULL; + va_end(ap); + (void) msggoaway (); + if (fmt) + if (thisC) + notify ("SUP: %s\n",buf); + else + printf ("SUP: %s\n",buf); + if (!dontjump) + longjmp (sjbuf,TRUE); +} diff --git a/usr.bin/sup/src/supcmisc.c b/usr.bin/sup/src/supcmisc.c new file mode 100644 index 00000000000..54bade3eb10 --- /dev/null +++ b/usr.bin/sup/src/supcmisc.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * sup misc. routines, include list processing. + ********************************************************************** + * HISTORY + * $Log: supcmisc.c,v $ + * Revision 1.1 1995/12/16 11:46:57 deraadt + * add sup to the tree + * + * Revision 1.2 1995/06/03 21:21:57 christos + * Changes to write ascii timestamps in the when files. + * Looked into making it 64 bit clean, but it is hopeless. + * Added little program to convert from the old timestamp files + * into the new ones. + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.5 92/08/11 12:07:22 mrt + * Added release to FILEWHEN name. + * Brad's changes: delinted and updated variable arguement usage. + * [92/07/26 mrt] + * + * Revision 1.3 89/08/15 15:31:28 bww + * Updated to use v*printf() in place of _doprnt(). + * From "[89/04/19 mja]" at CMU. + * [89/08/15 bww] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fixed bug in ugconvert() which left pw uninitialized. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Split off from sup.c and changed goaway to use printf + * instead of notify if thisC is NULL. + * + ********************************************************************** + */ + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "supcdefs.h" + +struct liststruct { /* uid and gid lists */ + char *Lname; /* name */ + int Lnumber; /* uid or gid */ + struct liststruct *Lnext; +}; +typedef struct liststruct LIST; + +#define HASHBITS 4 +#define HASHSIZE (1<<HASHBITS) +#define HASHMASK (HASHSIZE-1) +#define LISTSIZE (HASHSIZE*HASHSIZE) + +static LIST *uidL[LISTSIZE]; /* uid and gid lists */ +static LIST *gidL[LISTSIZE]; + +extern COLLECTION *thisC; /* collection list pointer */ +#if __STDC__ +int notify (char *, ...); +#endif + +/************************************************* + *** P R I N T U P D A T E T I M E S *** + *************************************************/ + +prtime () +{ + char buf[STRINGLENGTH]; + char relsufix[STRINGLENGTH]; + long twhen; + int f; + + if ((thisC->Cflags&CFURELSUF) && thisC->Crelease) + (void) sprintf (relsufix,".%s",thisC->Crelease); + else + relsufix[0] = '\0'; + if (chdir (thisC->Cbase) < 0) + logerr ("Can't change to base directory %s for collection %s", + thisC->Cbase,thisC->Cname); + twhen = getwhen(thisC->Cname,relsufix); + (void) strcpy (buf,ctime (&twhen)); + buf[strlen(buf)-1] = '\0'; + loginfo ("Last update occurred at %s for collection %s", + buf,thisC->Cname); +} + +int establishdir (fname) +char *fname; +{ + char dpart[STRINGLENGTH],fpart[STRINGLENGTH]; + path (fname,dpart,fpart); + return (estabd (fname,dpart)); +} + +int estabd (fname,dname) +char *fname,*dname; +{ + char dpart[STRINGLENGTH],fpart[STRINGLENGTH]; + struct stat sbuf; + register int x; + + if (stat (dname,&sbuf) >= 0) return (FALSE); /* exists */ + path (dname,dpart,fpart); + if (strcmp (fpart,".") == 0) { /* dname is / or . */ + notify ("SUP: Can't create directory %s for %s\n",dname,fname); + return (TRUE); + } + x = estabd (fname,dpart); + if (x) return (TRUE); + (void) mkdir (dname,0755); + if (stat (dname,&sbuf) < 0) { /* didn't work */ + notify ("SUP: Can't create directory %s for %s\n",dname,fname); + return (TRUE); + } + vnotify ("SUP Created directory %s for %s\n",dname,fname); + return (FALSE); +} + +/*************************************** + *** L I S T R O U T I N E S *** + ***************************************/ + +static +int Lhash (name) +char *name; +{ + /* Hash function is: HASHSIZE * (strlen mod HASHSIZE) + * + (char mod HASHSIZE) + * where "char" is last character of name (if name is non-null). + */ + + register int len; + register char c; + + len = strlen (name); + if (len > 0) c = name[len-1]; + else c = 0; + return (((len&HASHMASK)<<HASHBITS)|(((int)c)&HASHMASK)); +} + +static +Linsert (table,name,number) +LIST **table; +char *name; +int number; +{ + register LIST *l; + register int lno; + lno = Lhash (name); + l = (LIST *) malloc (sizeof(LIST)); + l->Lname = name; + l->Lnumber = number; + l->Lnext = table[lno]; + table[lno] = l; +} + +static +LIST *Llookup (table,name) +LIST **table; +char *name; +{ + register int lno; + register LIST *l; + lno = Lhash (name); + for (l = table[lno]; l && strcmp(l->Lname,name) != 0; l = l->Lnext); + return (l); +} + +ugconvert (uname,gname,uid,gid,mode) +char *uname,*gname; +int *uid,*gid,*mode; +{ + register LIST *u,*g; + register struct passwd *pw; + register struct group *gr; + struct stat sbuf; + static int defuid = -1; + static int defgid; + static int first = TRUE; + + if (first) { + bzero ((char *)uidL, sizeof (uidL)); + bzero ((char *)gidL, sizeof (gidL)); + first = FALSE; + } + pw = NULL; + if (u = Llookup (uidL,uname)) + *uid = u->Lnumber; + else if (pw = getpwnam (uname)) { + Linsert (uidL,salloc(uname),pw->pw_uid); + *uid = pw->pw_uid; + } + if (u || pw) { + if (g = Llookup (gidL,gname)) { + *gid = g->Lnumber; + return; + } + if (gr = getgrnam (gname)) { + Linsert (gidL,salloc(gname),gr->gr_gid); + *gid = gr->gr_gid; + return; + } + if (pw == NULL) + pw = getpwnam (uname); + *mode &= ~S_ISGID; + *gid = pw->pw_gid; + return; + } + *mode &= ~(S_ISUID|S_ISGID); + if (defuid >= 0) { + *uid = defuid; + *gid = defgid; + return; + } + if (stat (".",&sbuf) < 0) { + *uid = defuid = getuid (); + *gid = defgid = getgid (); + return; + } + *uid = defuid = sbuf.st_uid; + *gid = defgid = sbuf.st_gid; +} + + +/********************************************* + *** U T I L I T Y R O U T I N E S *** + *********************************************/ + +#if __STDC__ +notify (char *fmt,...) /* record error message */ +#else +/*VARARGS*//*ARGSUSED*/ +notify (va_alist) /* record error message */ +va_dcl +#endif +{ +#if !__STDC__ + char *fmt; +#endif + char buf[STRINGLENGTH]; + char collrelname[STRINGLENGTH]; + long tloc; + static FILE *noteF = NULL; /* mail program on pipe */ + va_list ap; + +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + fmt = va_arg(ap,char *); +#endif + if (fmt == NULL) { + if (noteF && noteF != stdout) + (void) pclose (noteF); + noteF = NULL; + return; + } + if ((thisC->Cflags&CFURELSUF) && thisC->Crelease) + (void) sprintf (collrelname,"%s-%s",collname,thisC->Crelease); + else + (void) strcpy (collrelname,collname); + + if (noteF == NULL) { + if ((thisC->Cflags&CFMAIL) && thisC->Cnotify) { + (void) sprintf (buf,"mail -s \"SUP Upgrade of %s\" %s >/dev/null", + collrelname,thisC->Cnotify); + noteF = popen (buf,"w"); + if (noteF == NULL) { + logerr ("Can't send mail to %s for %s", + thisC->Cnotify,collrelname); + noteF = stdout; + } + } else + noteF = stdout; + tloc = time ((long *)NULL); + fprintf (noteF,"SUP Upgrade of %s at %s", + collrelname,ctime (&tloc)); + (void) fflush (noteF); + } + vfprintf(noteF,fmt,ap); + va_end(ap); + (void) fflush (noteF); +} + +lockout (on) /* lock out interrupts */ +int on; +{ + register int x; + static int lockmask; + + if (on) { + x = sigmask (SIGHUP) | sigmask (SIGINT) | + sigmask (SIGQUIT) | sigmask (SIGTERM); + lockmask = sigblock (x); + } + else { + (void) sigsetmask (lockmask); + } +} + +char *fmttime (time) +long time; +{ + static char buf[STRINGLENGTH]; + int len; + + (void) strcpy (buf,ctime (&time)); + len = strlen(buf+4)-6; + (void) strncpy (buf,buf+4,len); + buf[len] = '\0'; + return (buf); +} diff --git a/usr.bin/sup/src/supcname.c b/usr.bin/sup/src/supcname.c new file mode 100644 index 00000000000..fbad5e3e325 --- /dev/null +++ b/usr.bin/sup/src/supcname.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * sup client name server interface + ********************************************************************** + * HISTORY + * $Log: supcname.c,v $ + * Revision 1.1 1995/12/16 11:46:58 deraadt + * add sup to the tree + * + * Revision 1.2 1995/09/16 19:12:14 glass + * if the function returns nothing, declare it void + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.4 92/08/11 12:07:32 mrt + * Added copyright. + * [92/08/10 mrt] + * + * 21-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed to no longer use a name server. + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Changed getnams and added several new routines to change the + * way that sup finds nameservers. It now builds a tree of + * servers to check. It walks over the tree. At each node, it + * tries to contact the name server and get as many names + * resolved as it can. It stops after either all collections + * have host names, or if some collections don't have host names + * but either everyone doesn't know what they are, or after too + * many tries, none could be reached. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Split off from sup.c + * + ********************************************************************** + */ + +#include "supcdefs.h" + +extern COLLECTION *firstC; /* collection list pointer */ + +/***************************************** + *** G E T H O S T N A M E S *** + *****************************************/ + +/* + * For each collection that doesn't have a host name specified, read + * the file server list for the name of the host for that collection. + * It's a fatal error if a collection has no file server. + */ + +void getnams () +{ + register COLLECTION *c; + char buf[STRINGLENGTH]; + register FILE *f; + char *p,*q; + + for (c = firstC; c && c->Chtree != NULL; c = c->Cnext); + if (c == NULL) return; + (void) sprintf (buf,FILEHOSTS,DEFDIR); + f = fopen (buf,"r"); + if (f == NULL) logquit (1,"Can't open %s",buf); + while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) { + if (q = index (p,'\n')) *q = '\0'; + if (index ("#;:",*p)) continue; + q = nxtarg (&p,"= \t"); + p = skipover (p," \t"); + if (*p == '=') p++; + p = skipover (p," \t"); + if (*p == '\0') goaway ("error in collection/host file"); + do { + if (strcmp (c->Cname, q) == 0) { + do { + q = nxtarg (&p,", \t"); + p = skipover (p," \t"); + if (*p == ',') p++; + p = skipover (p," \t"); + (void) Tinsert (&c->Chtree,q,FALSE); + } while (*p != '\0'); + } + while ((c = c->Cnext) != NULL && c->Chtree != NULL); + } while (c != NULL); + for (c = firstC; c && c->Chtree != NULL; c = c->Cnext); + if (c == NULL) break; + } + (void) fclose (f); + if (c == NULL) return; + do { + logerr ("Host for collection %s not found",c->Cname); + while ((c = c->Cnext) != NULL && c->Chtree != NULL); + } while (c); + logquit (1,"Hosts not found for all collections"); +} diff --git a/usr.bin/sup/src/supcparse.c b/usr.bin/sup/src/supcparse.c new file mode 100644 index 00000000000..ea3eb6e6eb4 --- /dev/null +++ b/usr.bin/sup/src/supcparse.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * sup collection parsing routines + ********************************************************************** + * HISTORY + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supcparse.c,v $ + * Revision 1.1 1995/12/16 11:46:58 deraadt + * add sup to the tree + * + * Revision 1.4 1995/06/09 04:33:34 christos + * fixed bug related to the ascii `when' files previous fix, where the -t + * option would fail to read the timestamp files. + * + * Revision 1.2 1993/08/04 17:46:20 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.1.1.1 1993/05/21 14:52:18 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.6 92/08/11 12:07:38 mrt + * Added use-rel-suffix option corresponding to -u switch. + * [92/07/26 mrt] + * + * Revision 1.5 92/02/08 18:24:19 mja + * Added "keep" supfile option, corresponding to -k switch. + * [92/01/17 vdelvecc] + * + * Revision 1.4 91/05/16 14:49:50 ern + * Change default timeout from none to 3 hours so we don't accumalute + * processes running sups to dead hosts especially for users. + * [91/05/16 14:49:21 ern] + * + * + * 10-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added timeout to backoff. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. Removed obsolete options. + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Split off from sup.c + * + ********************************************************************** + */ + +#include "supcdefs.h" + + +#ifdef lint +static char _argbreak; +#else +extern char _argbreak; /* break character from nxtarg */ +#endif + +typedef enum { /* supfile options */ + OHOST, OBASE, OHOSTBASE, OPREFIX, ORELEASE, + ONOTIFY, OLOGIN, OPASSWORD, OCRYPT, + OBACKUP, ODELETE, OEXECUTE, OOLD, OTIMEOUT, OKEEP, OURELSUF, + OCOMPRESS +} OPTION; + +struct option { + char *op_name; + OPTION op_enum; +} options[] = { + "host", OHOST, + "base", OBASE, + "hostbase", OHOSTBASE, + "prefix", OPREFIX, + "release", ORELEASE, + "notify", ONOTIFY, + "login", OLOGIN, + "password", OPASSWORD, + "crypt", OCRYPT, + "backup", OBACKUP, + "delete", ODELETE, + "execute", OEXECUTE, + "old", OOLD, + "timeout", OTIMEOUT, + "keep", OKEEP, + "use-rel-suffix", OURELSUF, + "compress", OCOMPRESS +}; + +passdelim (ptr,delim) /* skip over delimiter */ +char **ptr,delim; +{ + *ptr = skipover (*ptr, " \t"); + if (_argbreak != delim && **ptr == delim) { + (*ptr)++; + *ptr = skipover (*ptr, " \t"); + } +} + +parsecoll(c,collname,args) +COLLECTION *c; +char *collname,*args; +{ + register char *arg,*p; + register OPTION option; + int opno; + + c->Cnext = NULL; + c->Cname = salloc (collname); + c->Chost = NULL; + c->Chtree = NULL; + c->Cbase = NULL; + c->Chbase = NULL; + c->Cprefix = NULL; + c->Crelease = NULL; + c->Cnotify = NULL; + c->Clogin = NULL; + c->Cpswd = NULL; + c->Ccrypt = NULL; + c->Ctimeout = 3*60*60; /* default to 3 hours instead of no timeout */ + c->Cflags = 0; + c->Cnogood = FALSE; + c->Clockfd = -1; + args = skipover (args," \t"); + while (*(arg=nxtarg(&args," \t="))) { + for (opno = 0; opno < sizeofA(options); opno++) + if (strcmp (arg,options[opno].op_name) == 0) + break; + if (opno == sizeofA(options)) { + logerr ("Invalid supfile option %s for collection %s", + arg,c->Cname); + return(-1); + } + option = options[opno].op_enum; + switch (option) { + case OHOST: + passdelim (&args,'='); + do { + arg = nxtarg (&args,", \t"); + (void) Tinsert (&c->Chtree,arg,FALSE); + arg = args; + p = skipover (args," \t"); + if (*p++ == ',') args = p; + } while (arg != args); + break; + case OBASE: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Cbase = salloc (arg); + break; + case OHOSTBASE: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Chbase = salloc (arg); + break; + case OPREFIX: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Cprefix = salloc (arg); + break; + case ORELEASE: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Crelease = salloc (arg); + break; + case ONOTIFY: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Cnotify = salloc (arg); + break; + case OLOGIN: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Clogin = salloc (arg); + break; + case OPASSWORD: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Cpswd = salloc (arg); + break; + case OCRYPT: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Ccrypt = salloc (arg); + break; + case OBACKUP: + c->Cflags |= CFBACKUP; + break; + case ODELETE: + c->Cflags |= CFDELETE; + break; + case OEXECUTE: + c->Cflags |= CFEXECUTE; + break; + case OOLD: + c->Cflags |= CFOLD; + break; + case OKEEP: + c->Cflags |= CFKEEP; + break; + case OURELSUF: + c->Cflags |= CFURELSUF; + break; + case OCOMPRESS: + c->Cflags |= CFCOMPRESS; + break; + case OTIMEOUT: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + c->Ctimeout = atoi (arg); + break; + } + } + return(0); +} + + +long +getwhen(collection, relsuffix) + char *collection, *relsuffix; +{ + char buf[STRINGLENGTH]; + char *ep; + FILE *fp; + long tstamp; + + (void) sprintf (buf,FILEWHEN,collection,relsuffix); + + if ((fp = fopen(buf, "r")) == NULL) + return 0; + + if (fgets(buf, sizeof(buf), fp) == NULL) { + (void) fclose(fp); + return 0; + } + + (void) fclose(fp); + + if ((tstamp = strtol(buf, &ep, 0)) == -1 || *ep != '\n') + return 0; + + return tstamp; +} + +int +putwhen(fname, tstamp) + char *fname; + long tstamp; +{ + FILE *fp; + if ((fp = fopen(fname, "w")) == NULL) + return 0; + if (fprintf(fp, "%ld\n", tstamp) < 0) + return 0; + if (fclose(fp) != 0) + return 0; + return 1; +} diff --git a/usr.bin/sup/src/supcvers.c b/usr.bin/sup/src/supcvers.c new file mode 100644 index 00000000000..e325fe97c1d --- /dev/null +++ b/usr.bin/sup/src/supcvers.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + ********************************************************************** + * HISTORY + * $Log: supcvers.c,v $ + * Revision 1.1 1995/12/16 11:46:59 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:19 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.8 92/08/11 12:07:51 mrt + * Added use-rel-suffix option. Picked up STUMP changes. + * [V7.26] + * + * Revision 1.7 92/02/08 18:24:23 mja + * Support for -k/-K and "keep" option. [V7.25] + * [92/01/17 vdelvecc] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support. Removed nameserver support. [V7.24] + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. [V6.23] + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Changes for Version 6, better supoort to reflect errors to + * logfile. [V6.22] + * + * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Split sup.c into subparts. [V5.21] + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changes to many files to make lint happy. [V5.20] + * + * 01-Apr-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changes to sup.c and scmio.c. [V5.19] + * + * 19-Sep-86 Mike Accetta (mja) at Carnegie-Mellon University + * Changes to sup.c. [V5.18] + * + * 21-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Minor bug fix to previous edit in sup.c. [V5.17] + * + * 07-Jun-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changes to sup.c and sup.h. [V5.16] + * + * 30-May-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added changes to sup.c, sup.h, scm.c, scmio.h. [V5.15] + * + * 19-Feb-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created. [V5.14] + * + ********************************************************************** + */ + +int PGMVERSION = 26; /* program version of sup */ diff --git a/usr.bin/sup/src/supfilesrv.c b/usr.bin/sup/src/supfilesrv.c new file mode 100644 index 00000000000..12e2ce20e16 --- /dev/null +++ b/usr.bin/sup/src/supfilesrv.c @@ -0,0 +1,1870 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * +/* + * supfilesrv -- SUP File Server + * + * Usage: supfilesrv [-l] [-P] [-N] [-R] + * -l "live" -- don't fork daemon + * -P "debug ports" -- use debugging network ports + * -N "debug network" -- print debugging messages for network i/o + * -R "RCS mode" -- if file is an rcs file, use co to get contents + * + ********************************************************************** + * HISTORY + * 13-Sep-92 Mary Thompson (mrt) at Carnegie-Mellon University + * Changed name of sup program in xpatch from /usr/cs/bin/sup to + * /usr/bin/sup for exported version of sup. + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supfilesrv.c,v $ + * Revision 1.1 1995/12/16 11:46:59 deraadt + * add sup to the tree + * + * Revision 1.8 1995/10/29 23:54:49 christos + * - runio fails when result != 0 not only < 0 + * - print vis-encoded file in the scanner. + * + * Revision 1.7 1995/06/24 16:21:55 christos + * - Don't use system(3) to fork processes. It is a big security hole. + * - Encode the filenames in the scan files using strvis(3), so filenames + * that contain newlines or other weird characters don't break the scanner. + * + * Revision 1.6 1995/06/03 21:22:00 christos + * Changes to write ascii timestamps in the when files. + * Looked into making it 64 bit clean, but it is hopeless. + * Added little program to convert from the old timestamp files + * into the new ones. + * + * Revision 1.5 1993/08/04 17:46:21 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.3 1993/06/05 21:32:17 cgd + * use daemon() to put supfilesrv into daemon mode... + * + * Revision 1.2 1993/05/24 17:57:31 brezak + * Remove netcrypt.c. Remove unneeded files. Cleanup make. + * + * Revision 1.20 92/09/09 22:05:00 mrt + * Added Brad's change to make sendfile take a va_list. + * Added support in login to accept an non-encrypted login + * message if no user or password is being sent. This supports + * a non-crypting version of sup. Also fixed to skip leading + * white space from crypts in host files. + * [92/09/01 mrt] + * + * Revision 1.19 92/08/11 12:07:59 mrt + * Made maxchildren a patchable variable, which can be set by the + * command line switch -C or else defaults to the MAXCHILDREN + * defined in sup.h. Added most of Brad's STUMP changes. + * Increased PGMVERSION to 12 to reflect substantial changes. + * [92/07/28 mrt] + * + * Revision 1.18 90/12/25 15:15:39 ern + * Yet another rewrite of the logging code. Make up the text we will write + * and then get in, write it and get out. + * Also set error on write-to-full-disk if the logging is for recording + * server is busy. + * [90/12/25 15:15:15 ern] + * + * Revision 1.17 90/05/07 09:31:13 dlc + * Sigh, some more fixes to the new "crypt" file handling code. First, + * just because the "crypt" file is in a local file system does not mean + * it can be trusted. We have to check for hard links to root owned + * files whose contents could be interpretted as a crypt key. For + * checking this fact, the new routine stat_info_ok() was added. This + * routine also makes other sanity checks, such as owner only permission, + * the file is a regular file, etc. Also, even if the uid/gid of th + * "crypt" file is not going to be used, still use its contents in order + * to cause fewer surprises to people supping out of a shared file system + * such as AFS. + * [90/05/07 dlc] + * + * Revision 1.16 90/04/29 04:21:08 dlc + * Fixed logic bug in docrypt() which would not get the stat information + * from the crypt file if the crypt key had already been set from a + * "host" file. + * [90/04/29 dlc] + * + * Revision 1.15 90/04/18 19:51:27 dlc + * Added the new routines local_file(), link_nofollow() for use in + * dectecting whether a file is located in a local file system. These + * routines probably should have been in another module, but only + * supfilesrv needs to do the check and none of its other modules seemed + * appropriate. Note, the implementation should be changed once we have + * direct kernel support, for example the fstatfs(2) system call, for + * detecting the type of file system a file resides. Also, I changed + * the routines which read the crosspatch crypt file or collection crypt + * file to save the uid and gid from the stat information obtained via + * the local_file() call (when the file is local) at the same time the + * crypt key is read. This change disallows non-local files for the + * crypt key to plug a security hole involving the usage of the uid/gid + * of the crypt file to define who the the file server should run as. If + * the saved uid/gid are both valid, then the server will set its uid/gid + * to these values. + * [90/04/18 dlc] + * + * Revision 1.14 89/08/23 14:56:15 gm0w + * Changed msgf routines to msg routines. + * [89/08/23 gm0w] + * + * Revision 1.13 89/08/03 19:57:33 mja + * Remove setaid() call. + * + * Revision 1.12 89/08/03 19:49:24 mja + * Updated to use v*printf() in place of _doprnt(). + * [89/04/19 mja] + * + * 11-Sep-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to record release name in logfile. + * + * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added host=<hostfile> support to releases file. [V7.12] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support. Created docrypt() routine for crypt + * test message. + * + * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed common information logging code, the quiet switch, and + * moved samehost() check to after device/inode check. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. [V5.11] + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Added code to record final status of client in logfile. [V5.10] + * + * 22-May-87 Chriss Stephens (chriss) at Carnegie Mellon University + * Mergered divergent CS and ECE versions. [V5.9a] + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed support for version 3 of SUP protocol. Added changes + * to make lint happy. Added calls to new logging routines. [V5.9] + * + * 31-Mar-87 Dan Nydick (dan) at Carnegie-Mellon University + * Fixed so no password check is done when crypts are used. + * + * 25-Nov-86 Rudy Nedved (ern) at Carnegie-Mellon University + * Set F_APPEND fcntl in logging to increase the chance + * that the log entry from this incarnation of the file + * server will not be lost by another incarnation. [V5.8] + * + * 20-Oct-86 Dan Nydick (dan) at Carnegie-Mellon University + * Changed not to call okmumbles when not compiled with CMUCS. + * + * 04-Aug-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to increment scmdebug as more -N flags are + * added. [V5.7] + * + * 25-May-86 Jonathan J. Chew (jjc) at Carnegie-Mellon University + * Renamed local variable in main program from "sigmask" to + * "signalmask" to avoid name conflict with 4.3BSD identifier. + * Conditionally compile in calls to CMU routines, "setaid" and + * "logaccess". [V5.6] + * + * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed supfilesrv to use the crypt file owner and group for + * access purposes, rather than the directory containing the crypt + * file. [V5.5] + * + * 07-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to keep logfiles in repository collection directory. + * Added code for locking collections. [V5.4] + * + * 05-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to support new FSETUPBUSY return. Now accepts all + * connections and tells any clients after the 8th that the + * fileserver is busy. New clients will retry again later. [V5.3] + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Major rewrite for protocol version 4. [V4.2] + * + * 12-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Fixed close of crypt file to use file pointer as argument + * instead of string pointer. + * + * 24-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Allow "!hostname" lines and comments in collection "host" file. + * + * 13-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Don't use access() on symbolic links since they may not point to + * an existing file. + * + * 22-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to restrict file server availability to when it has + * less than or equal to eight children. + * + * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Merged 4.1 and 4.2 versions together. + * + * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University + * Created for 4.2 BSD. + * + ********************************************************************** + */ + +#include <libc.h> +#ifdef AFS +#include <afs/param.h> +#undef MAXNAMLEN +#endif +#include <sys/param.h> +#include <c.h> +#include <signal.h> +#include <errno.h> +#include <setjmp.h> +#include <pwd.h> +#include <grp.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <sys/dir.h> +#if MACH +#include <sys/ioctl.h> +#endif +#if CMUCS +#include <acc.h> +#include <sys/ttyloc.h> +#include <access.h> +#include <sys/viceioctl.h> +#else CMUCS +#define ACCESS_CODE_OK 0 +#define ACCESS_CODE_BADPASSWORD (-2) +#endif CMUCS +#include "sup.h" +#define MSGFILE +#include "supmsg.h" + +#ifdef lint +/*VARARGS1*//*ARGSUSED*/ +static void quit(status) {}; +#endif /* lint */ + +extern int errno; +long time (); +uid_t getuid (); + +int maxchildren; + +/* + * These are used to save the stat information from the crosspatch crypt + * file or collection crypt file at the time it is opened for the crypt + * key and it is verified to be a local file. + */ +int runas_uid = -1; +int runas_gid = -1; + +#define PGMVERSION 13 + +/************************* + *** M A C R O S *** + *************************/ + +#define HASHBITS 8 +#define HASHSIZE (1<<HASHBITS) +#define HASHMASK (HASHSIZE-1) +#define HASHFUNC(x,y) ((x)&HASHMASK) + +/******************************************* + *** D A T A S T R U C T U R E S *** + *******************************************/ + +struct hashstruct { /* hash table for number lists */ + int Hnum1; /* numeric keys */ + int Hnum2; + char *Hname; /* string value */ + TREE *Htree; /* TREE value */ + struct hashstruct *Hnext; +}; +typedef struct hashstruct HASH; + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +char program[] = "supfilesrv"; /* program name for SCM messages */ +int progpid = -1; /* and process id */ + +jmp_buf sjbuf; /* jump location for network errors */ +TREELIST *listTL; /* list of trees to upgrade */ + +int live; /* -l flag */ +int dbgportsq; /* -P flag */ +extern int scmdebug; /* -N flag */ +extern int netfile; +#ifdef RCS +int candorcs; /* -R flag */ +int dorcs = FALSE; +#endif + +char *clienthost; /* host name of client */ +int nchildren; /* number of children that exist */ +char *prefix; /* collection pathname prefix */ +char *release; /* collection release name */ +char *cryptkey; /* encryption key if non-null */ +#ifdef CVS +char *cvs_root; /* RCS root */ +#endif +char *rcs_branch; /* RCS branch name */ +int lockfd; /* descriptor of lock file */ + +/* global variables for scan functions */ +int trace = FALSE; /* directory scan trace */ +int cancompress = FALSE; /* Can we compress files */ +int docompress = FALSE; /* Do we compress files */ + +HASH *uidH[HASHSIZE]; /* for uid and gid lookup */ +HASH *gidH[HASHSIZE]; +HASH *inodeH[HASHSIZE]; /* for inode lookup for linked file check */ + +char *fmttime (); /* time format routine */ +#if __STDC__ +int goaway(char *fmt,...); +#endif + +/************************************* + *** M A I N R O U T I N E *** + *************************************/ + +main (argc,argv) +int argc; +char **argv; +{ + register int x,pid,signalmask; + struct sigvec chldvec,ignvec,oldvec; + void chldsig(); + long tloc; + + /* initialize global variables */ + pgmversion = PGMVERSION; /* export version number */ + server = TRUE; /* export that we're not a server */ + collname = NULL; /* no current collection yet */ + maxchildren = MAXCHILDREN; /* defined in sup.h */ + + init (argc,argv); /* process arguments */ + +#ifdef HAS_DAEMON + if (!live) /* if not debugging, turn into daemon */ + daemon(0, 0); +#endif + + logopen ("supfile"); + tloc = time ((long *)NULL); + loginfo ("SUP File Server Version %d.%d (%s) starting at %s", + PROTOVERSION,PGMVERSION,scmversion,fmttime (tloc)); + if (live) { + x = service (); + if (x != SCMOK) + logquit (1,"Can't connect to network"); + answer (); + (void) serviceend (); + exit (0); + } + ignvec.sv_handler = SIG_IGN; + ignvec.sv_onstack = 0; + ignvec.sv_mask = 0; + (void) sigvec (SIGHUP,&ignvec,&oldvec); + (void) sigvec (SIGINT,&ignvec,&oldvec); + (void) sigvec (SIGPIPE,&ignvec,&oldvec); + chldvec.sv_handler = chldsig; + chldvec.sv_mask = 0; + chldvec.sv_onstack = 0; + (void) sigvec (SIGCHLD,&chldvec,&oldvec); + nchildren = 0; + for (;;) { + x = service (); + if (x != SCMOK) { + logerr ("Error in establishing network connection"); + (void) servicekill (); + continue; + } + signalmask = sigblock(sigmask(SIGCHLD)); + if ((pid = fork()) == 0) { /* server process */ + (void) serviceprep (); + answer (); + (void) serviceend (); + exit (0); + } + (void) servicekill (); /* parent */ + if (pid > 0) nchildren++; + (void) sigsetmask(signalmask); + } +} + +/* + * Child status signal handler + */ + +void +chldsig(snum) + int snum; +{ + union wait w; + + while (wait3((int *) &w, WNOHANG, (struct rusage *)0) > 0) { + if (nchildren) nchildren--; + } +} + +/***************************************** + *** I N I T I A L I Z A T I O N *** + *****************************************/ + +usage () +{ + quit (1,"Usage: supfilesrv [ -l | -P | -N | -C <max children> | -H <host> <user> <cryptfile> <supargs> ]\n"); +} + +init (argc,argv) +int argc; +char **argv; +{ + register int i; + register int x; + char *clienthost,*clientuser; + char *p,*q; + char buf[STRINGLENGTH]; + int maxsleep; + register FILE *f; + +#ifdef RCS + candorcs = FALSE; +#endif + live = FALSE; + dbgportsq = FALSE; + scmdebug = 0; + clienthost = NULL; + clientuser = NULL; + maxsleep = 5; + if (--argc < 0) + usage (); + argv++; + while (clienthost == NULL && argc > 0 && argv[0][0] == '-') { + switch (argv[0][1]) { + case 'l': + live = TRUE; + break; + case 'P': + dbgportsq = TRUE; + break; + case 'N': + scmdebug++; + break; + case 'C': + if (--argc < 1) + quit (1,"Missing arg to -C\n"); + argv++; + maxchildren = atoi(argv[0]); + break; + case 'H': + if (--argc < 3) + quit (1,"Missing args to -H\n"); + argv++; + clienthost = argv[0]; + clientuser = argv[1]; + cryptkey = argv[2]; + argc -= 2; + argv += 2; + break; +#ifdef RCS + case 'R': + candorcs = TRUE; + break; +#endif + default: + fprintf (stderr,"Unknown flag %s ignored\n",argv[0]); + break; + } + --argc; + argv++; + } + if (clienthost == NULL) { + if (argc != 0) + usage (); + x = servicesetup (dbgportsq ? DEBUGFPORT : FILEPORT); + if (x != SCMOK) + quit (1,"Error in network setup"); + for (i = 0; i < HASHSIZE; i++) + uidH[i] = gidH[i] = inodeH[i] = NULL; + return; + } + server = FALSE; + if (argc < 1) + usage (); + f = fopen (cryptkey,"r"); + if (f == NULL) + quit (1,"Unable to open cryptfile %s\n",cryptkey); + if (p = fgets (buf,STRINGLENGTH,f)) { + if (q = index (p,'\n')) *q = '\0'; + if (*p == '\0') + quit (1,"No cryptkey found in %s\n",cryptkey); + cryptkey = salloc (buf); + } + (void) fclose (f); + x = request (dbgportsq ? DEBUGFPORT : FILEPORT,clienthost,&maxsleep); + if (x != SCMOK) + quit (1,"Unable to connect to host %s\n",clienthost); + x = msgsignon (); + if (x != SCMOK) + quit (1,"Error sending signon request to fileserver\n"); + x = msgsignonack (); + if (x != SCMOK) + quit (1,"Error reading signon reply from fileserver\n"); + printf ("SUP Fileserver %d.%d (%s) %d on %s\n", + protver,pgmver,scmver,fspid,remotehost()); + free (scmver); + scmver = NULL; + if (protver < 7) + quit (1,"Remote fileserver does not implement reverse sup\n"); + xpatch = TRUE; + xuser = clientuser; + x = msgsetup (); + if (x != SCMOK) + quit (1,"Error sending setup request to fileserver\n"); + x = msgsetupack (); + if (x != SCMOK) + quit (1,"Error reading setup reply from fileserver\n"); + switch (setupack) { + case FSETUPOK: + break; + case FSETUPSAME: + quit (1,"User %s not found on remote client\n",xuser); + case FSETUPHOST: + quit (1,"This host has no permission to reverse sup\n"); + default: + quit (1,"Unrecognized file server setup status %d\n",setupack); + } + if (netcrypt (cryptkey) != SCMOK ) + quit (1,"Running non-crypting fileserver\n"); + crypttest = CRYPTTEST; + x = msgcrypt (); + if (x != SCMOK) + quit (1,"Error sending encryption test request\n"); + x = msgcryptok (); + if (x == SCMEOF) + quit (1,"Data encryption test failed\n"); + if (x != SCMOK) + quit (1,"Error reading encryption test reply\n"); + logcrypt = CRYPTTEST; + loguser = NULL; + logpswd = NULL; + if (netcrypt (PSWDCRYPT) != SCMOK) /* encrypt password data */ + quit (1,"Running non-crypting fileserver\n"); + x = msglogin (); + (void) netcrypt ((char *)NULL); /* turn off encryption */ + if (x != SCMOK) + quit (1,"Error sending login request to file server\n"); + x = msglogack (); + if (x != SCMOK) + quit (1,"Error reading login reply from file server\n"); + if (logack == FLOGNG) + quit (1,"%s\nImproper login to %s account\n",logerror,xuser); + xargc = argc; + xargv = argv; + x = msgxpatch (); + if (x != SCMOK) + quit (1,"Error sending crosspatch request\n"); + crosspatch (); + exit (0); +} + +/***************************************** + *** A N S W E R R E Q U E S T *** + *****************************************/ + +answer () +{ + long starttime; + register int x; + + progpid = fspid = getpid (); + collname = NULL; + basedir = NULL; + prefix = NULL; + release = NULL; + rcs_branch = NULL; +#ifdef CVS + cvs_root = NULL; +#endif + goawayreason = NULL; + donereason = NULL; + lockfd = -1; + starttime = time ((long *)NULL); + if (!setjmp (sjbuf)) { + signon (); + setup (); + docrypt (); + login (); + if (xpatch) { + int fd; + + x = msgxpatch (); + if (x != SCMOK) + exit (0); + xargv[0] = "sup"; + xargv[1] = "-X"; + xargv[xargc] = (char *)NULL; + (void) dup2 (netfile,0); + (void) dup2 (netfile,1); + (void) dup2 (netfile,2); + fd = getdtablesize (); + while (--fd > 2) + (void) close (fd); + execvp (xargv[0],xargv); + exit (0); + } + listfiles (); + sendfiles (); + } + finishup (starttime); + if (collname) free (collname); + if (basedir) free (basedir); + if (prefix) free (prefix); + if (release) free (release); + if (rcs_branch) free (rcs_branch); +#ifdef CVS + if (cvs_root) free (cvs_root); +#endif + if (goawayreason) { + if (donereason == goawayreason) + donereason = NULL; + free (goawayreason); + } + if (donereason) free (donereason); + if (lockfd >= 0) (void) close (lockfd); + endpwent (); + (void) endgrent (); +#if CMUCS + endacent (); +#endif /* CMUCS */ + Hfree (uidH); + Hfree (gidH); + Hfree (inodeH); +} + +/***************************************** + *** S I G N O N C L I E N T *** + *****************************************/ + +signon () +{ + register int x; + + xpatch = FALSE; + x = msgsignon (); + if (x != SCMOK) goaway ("Error reading signon request from client"); + x = msgsignonack (); + if (x != SCMOK) goaway ("Error sending signon reply to client"); + free (scmver); + scmver = NULL; +} + +/***************************************************************** + *** E X C H A N G E S E T U P I N F O R M A T I O N *** + *****************************************************************/ + +setup () +{ + register int x; + char *p,*q; + char buf[STRINGLENGTH]; + register FILE *f; + struct stat sbuf; + register TREELIST *tl; + + if (protver > 7) { + cancompress = TRUE; + } + x = msgsetup (); + if (x != SCMOK) goaway ("Error reading setup request from client"); + if (protver < 4) { + setupack = FSETUPOLD; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Sup client using obsolete version of protocol"); + } + if (xpatch) { + register struct passwd *pw; + extern int link_nofollow(), local_file(); + + if ((pw = getpwnam (xuser)) == NULL) { + setupack = FSETUPSAME; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("User not found"); + } + (void) free (xuser); + xuser = salloc (pw->pw_dir); + + /* check crosspatch host access file */ + cryptkey = NULL; + (void) sprintf (buf,FILEXPATCH,xuser); + + /* Turn off link following */ + if (link_nofollow(1) != -1) { + int hostok = FALSE; + /* get stat info before open */ + if (stat(buf, &sbuf) == -1) + (void) bzero((char *)&sbuf, sizeof(sbuf)); + + if ((f = fopen (buf,"r")) != NULL) { + struct stat fsbuf; + + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + if (*p == '\0') continue; + if (!matchhost(q)) continue; + + cryptkey = salloc (p); + hostok = TRUE; + if (local_file(fileno(f), &fsbuf) > 0 + && stat_info_ok(&sbuf, &fsbuf)) { + runas_uid = sbuf.st_uid; + runas_gid = sbuf.st_gid; + } + break; + } + (void) fclose (f); + } + + /* Restore link following */ + if (link_nofollow(0) == -1) + goaway ("Restore link following"); + + if (!hostok) { + setupack = FSETUPHOST; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Host not on access list"); + } + } + setupack = FSETUPOK; + x = msgsetupack (); + if (x != SCMOK) + goaway ("Error sending setup reply to client"); + return; + } +#ifdef RCS + if (candorcs && release != NULL && + (strncmp(release, "RCS.", 4) == 0)) { + rcs_branch = salloc(&release[4]); + free(release); + release = salloc("RCS"); + dorcs = TRUE; + } +#endif + if (release == NULL) + release = salloc (DEFRELEASE); + if (basedir == NULL || *basedir == '\0') { + basedir = NULL; + (void) sprintf (buf,FILEDIRS,DEFDIR); + f = fopen (buf,"r"); + if (f) { + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t="); + if (strcmp(q,collname) == 0) { + basedir = skipover(p," \t="); + basedir = salloc (basedir); + break; + } + } + (void) fclose (f); + } + if (basedir == NULL) { + (void) sprintf (buf,FILEBASEDEFAULT,collname); + basedir = salloc(buf); + } + } + if (chdir (basedir) < 0) + goaway ("Can't chdir to base directory %s",basedir); + (void) sprintf (buf,FILEPREFIX,collname); + f = fopen (buf,"r"); + if (f) { + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + prefix = salloc(p); + if (chdir (prefix) < 0) + goaway ("Can't chdir to %s from base directory %s", + prefix,basedir); + break; + } + (void) fclose (f); + } + x = stat (".",&sbuf); + if (prefix) (void) chdir (basedir); + if (x < 0) + goaway ("Can't stat base/prefix directory"); + if (nchildren >= maxchildren) { + setupack = FSETUPBUSY; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Sup client told to try again later"); + } + if (sbuf.st_dev == basedev && sbuf.st_ino == baseino && samehost()) { + setupack = FSETUPSAME; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Attempt to upgrade to same directory on same host"); + } + /* obtain release information */ + if (!getrelease (release)) { + setupack = FSETUPRELEASE; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Invalid release information"); + } + /* check host access file */ + cryptkey = NULL; + for (tl = listTL; tl != NULL; tl = tl->TLnext) { + char *h; + if ((h = tl->TLhost) == NULL) + h = FILEHOSTDEF; + (void) sprintf (buf,FILEHOST,collname,h); + f = fopen (buf,"r"); + if (f) { + int hostok = FALSE; + while (p = fgets (buf,STRINGLENGTH,f)) { + int not; + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + if ((not = (*q == '!')) && *++q == '\0') + q = nxtarg (&p," \t"); + hostok = (not == (matchhost(q) == 0)); + if (hostok) { + while ((*p == ' ') || (*p == '\t')) p++; + if (*p) cryptkey = salloc (p); + break; + } + } + (void) fclose (f); + if (!hostok) { + setupack = FSETUPHOST; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Host not on access list for %s", + collname); + } + } + } + /* try to lock collection */ + (void) sprintf (buf,FILELOCK,collname); + x = open (buf,O_RDONLY,0); + if (x >= 0) { + if (flock (x,(LOCK_SH|LOCK_NB)) < 0) { + (void) close (x); + if (errno != EWOULDBLOCK) + goaway ("Can't lock collection %s",collname); + setupack = FSETUPBUSY; + (void) msgsetupack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Sup client told to wait for lock"); + } + lockfd = x; + } + setupack = FSETUPOK; + x = msgsetupack (); + if (x != SCMOK) goaway ("Error sending setup reply to client"); +} + +/** Test data encryption **/ +docrypt () +{ + register int x; + char *p,*q; + char buf[STRINGLENGTH]; + register FILE *f; + struct stat sbuf; + extern int link_nofollow(), local_file(); + + if (!xpatch) { + (void) sprintf (buf,FILECRYPT,collname); + + /* Turn off link following */ + if (link_nofollow(1) != -1) { + /* get stat info before open */ + if (stat(buf, &sbuf) == -1) + (void) bzero((char *)&sbuf, sizeof(sbuf)); + + if ((f = fopen (buf,"r")) != NULL) { + struct stat fsbuf; + + if (cryptkey == NULL && + (p = fgets (buf,STRINGLENGTH,f))) { + if (q = index (p,'\n')) *q = '\0'; + if (*p) cryptkey = salloc (buf); + } + if (local_file(fileno(f), &fsbuf) > 0 + && stat_info_ok(&sbuf, &fsbuf)) { + runas_uid = sbuf.st_uid; + runas_gid = sbuf.st_gid; + } + (void) fclose (f); + } + /* Restore link following */ + if (link_nofollow(0) == -1) + goaway ("Restore link following"); + } + } + if ( netcrypt (cryptkey) != SCMOK ) + goaway ("Runing non-crypting supfilesrv"); + x = msgcrypt (); + if (x != SCMOK) + goaway ("Error reading encryption test request from client"); + (void) netcrypt ((char *)NULL); + if (strcmp(crypttest,CRYPTTEST) != 0) + goaway ("Client not encrypting data properly"); + free (crypttest); + crypttest = NULL; + x = msgcryptok (); + if (x != SCMOK) + goaway ("Error sending encryption test reply to client"); +} + +/*************************************************************** + *** C O N N E C T T O P R O P E R A C C O U N T *** + ***************************************************************/ + +login () +{ + char *changeuid (); + register int x,fileuid,filegid; + + (void) netcrypt (PSWDCRYPT); /* encrypt acct name and password */ + x = msglogin (); + (void) netcrypt ((char *)NULL); /* turn off encryption */ + if (x != SCMOK) goaway ("Error reading login request from client"); + if ( logcrypt ) { + if (strcmp(logcrypt,CRYPTTEST) != 0) { + logack = FLOGNG; + logerror = "Improper login encryption"; + (void) msglogack (); + goaway ("Client not encrypting login information properly"); + } + free (logcrypt); + logcrypt = NULL; + } + if (loguser == NULL) { + if (cryptkey) { + if (runas_uid >= 0 && runas_gid >= 0) { + fileuid = runas_uid; + filegid = runas_gid; + loguser = NULL; + } else + loguser = salloc (DEFUSER); + } else + loguser = salloc (DEFUSER); + } + if ((logerror = changeuid (loguser,logpswd,fileuid,filegid)) != NULL) { + logack = FLOGNG; + (void) msglogack (); + if (protver >= 6) longjmp (sjbuf,TRUE); + goaway ("Client denied login access"); + } + if (loguser) free (loguser); + if (logpswd) free (logpswd); + logack = FLOGOK; + x = msglogack (); + if (x != SCMOK) goaway ("Error sending login reply to client"); + if (!xpatch) /* restore desired encryption */ + if (netcrypt (cryptkey) != SCMOK) + goaway("Running non-crypting supfilesrv"); + free (cryptkey); + cryptkey = NULL; +} + +/***************************************** + *** M A K E N A M E L I S T *** + *****************************************/ + +listfiles () +{ + int denyone(); + register int x; + + refuseT = NULL; + x = msgrefuse (); + if (x != SCMOK) goaway ("Error reading refuse list from client"); + getscanlists (); + Tfree (&refuseT); + x = msglist (); + if (x != SCMOK) goaway ("Error sending file list to client"); + Tfree (&listT); + listT = NULL; + needT = NULL; + x = msgneed (); + if (x != SCMOK) + goaway ("Error reading needed files list from client"); + denyT = NULL; + (void) Tprocess (needT,denyone); + Tfree (&needT); + x = msgdeny (); + if (x != SCMOK) goaway ("Error sending denied files list to client"); + Tfree (&denyT); +} + +denyone (t) +register TREE *t; +{ + register TREELIST *tl; + register char *name = t->Tname; + register int update = (t->Tflags&FUPDATE) != 0; + struct stat sbuf; + register TREE *tlink; + TREE *linkcheck (); + char slinkname[STRINGLENGTH]; + register int x; + + for (tl = listTL; tl != NULL; tl = tl->TLnext) + if ((t = Tsearch (tl->TLtree,name)) != NULL) + break; + if (t == NULL) { + (void) Tinsert (&denyT,name,FALSE); + return (SCMOK); + } + cdprefix (tl->TLprefix); + if ((t->Tmode&S_IFMT) == S_IFLNK) + x = lstat(name,&sbuf); + else + x = stat(name,&sbuf); + if (x < 0 || (sbuf.st_mode&S_IFMT) != (t->Tmode&S_IFMT)) { + (void) Tinsert (&denyT,name,FALSE); + return (SCMOK); + } + switch (t->Tmode&S_IFMT) { + case S_IFLNK: + if ((x = readlink (name,slinkname,STRINGLENGTH)) <= 0) { + (void) Tinsert (&denyT,name,FALSE); + return (SCMOK); + } + slinkname[x] = '\0'; + (void) Tinsert (&t->Tlink,slinkname,FALSE); + break; + case S_IFREG: + if (sbuf.st_nlink > 1 && + (tlink = linkcheck (t,(int)sbuf.st_dev,(int)sbuf.st_ino))) + { + (void) Tinsert (&tlink->Tlink,name,FALSE); + return (SCMOK); + } + if (update) t->Tflags |= FUPDATE; + case S_IFDIR: + t->Tuid = sbuf.st_uid; + t->Tgid = sbuf.st_gid; + break; + default: + (void) Tinsert (&denyT,name,FALSE); + return (SCMOK); + } + t->Tflags |= FNEEDED; + return (SCMOK); +} + +/********************************* + *** S E N D F I L E S *** + *********************************/ + +sendfiles () +{ + int sendone(),senddir(),sendfile(); + register TREELIST *tl; + register int x; + + /* Does the protocol support compression */ + if (cancompress) { + /* Check for compression on sending files */ + x = msgcompress(); + if ( x != SCMOK) + goaway ("Error sending compression check to server"); + } + /* send all files */ + for (tl = listTL; tl != NULL; tl = tl->TLnext) { + cdprefix (tl->TLprefix); +#ifdef CVS + if (candorcs) { + cvs_root = getcwd(NULL, 256); + if (access("CVSROOT", F_OK) < 0) + dorcs = FALSE; + else { + loginfo("is a CVSROOT \"%s\"\n", cvs_root); + dorcs = TRUE; + } + } +#endif + (void) Tprocess (tl->TLtree,sendone); + } + /* send directories in reverse order */ + for (tl = listTL; tl != NULL; tl = tl->TLnext) { + cdprefix (tl->TLprefix); + (void) Trprocess (tl->TLtree,senddir); + } + x = msgsend (); + if (x != SCMOK) + goaway ("Error reading receive file request from client"); + upgradeT = NULL; + x = msgrecv (sendfile,0); + if (x != SCMOK) + goaway ("Error sending file to client"); +} + +sendone (t) +TREE *t; +{ + register int x,fd; + register int fdtmp; + char temp_file[STRINGLENGTH], rcs_file[STRINGLENGTH]; + union wait status; + char *uconvert(),*gconvert(); + int sendfile (); + int ac; + char *av[50]; /* More than enough */ + + if ((t->Tflags&FNEEDED) == 0) /* only send needed files */ + return (SCMOK); + if ((t->Tmode&S_IFMT) == S_IFDIR) /* send no directories this pass */ + return (SCMOK); + x = msgsend (); + if (x != SCMOK) goaway ("Error reading receive file request from client"); + upgradeT = t; /* upgrade file pointer */ + fd = -1; /* no open file */ + if ((t->Tmode&S_IFMT) == S_IFREG) { + if (!listonly && (t->Tflags&FUPDATE) == 0) { +#ifdef RCS + if (dorcs) { + char rcs_release[STRINGLENGTH]; + + tmpnam(rcs_file); + if (strcmp(&t->Tname[strlen(t->Tname)-2], ",v") == 0) { + t->Tname[strlen(t->Tname)-2] = '\0'; + ac = 0; +#ifdef CVS + av[ac++] = "cvs"; + av[ac++] = "-d"; + av[ac++] = cvs_root; + av[ac++] = "-r"; + av[ac++] = "-l"; + av[ac++] = "-Q"; + av[ac++] = "co"; + av[ac++] = "-p"; + if (rcs_branch != NULL) { + av[ac++] = "-r"; + av[ac++] = rcs_branch; + } +#else + av[ac++] = "co"; + av[ac++] = "-q"; + av[ac++] = "-p"; + if (rcs_branch != NULL) { + sprintf(rcs_release, "-r%s", + rcs_branch); + av[ac++] = rcs_release; + } +#endif + av[ac++] = t->Tname; + av[ac++] = NULL; + status.w_status = runio(av, + NULL, + rcs_file, + "/dev/null"); + /*loginfo("using rcs mode \n");*/ + if (status.w_status < 0 || status.w_retcode) { + /* Just in case */ + unlink(rcs_file); + if (status.w_status < 0) { + goaway ("We died trying to run cvs or rcs"); + t->Tmode = 0; + } + else { + /*logerr("rcs command failed = %d\n", + status.w_retcode);*/ + t->Tflags |= FUPDATE; + } + } + else if (docompress) { + tmpnam(temp_file); + av[0] = "gzip"; + av[1] = "-c"; + av[2] = NULL; + if (runio(av, rcs_file, temp_file, NULL) != 0) { + /* Just in case */ + unlink(temp_file); + unlink(rcs_file); + goaway ("We died trying to gzip a file"); + t->Tmode = 0; + } + fd = open (temp_file,O_RDONLY,0); + } + else + fd = open (rcs_file,O_RDONLY,0); + } + } +#endif + if (fd == -1) { + if (docompress) { + tmpnam(temp_file); + av[0] = "gzip"; + av[1] = "-c"; + av[2] = NULL; + if (runio(av, t->Tname, temp_file, NULL) != 0) { + /* Just in case */ + unlink(temp_file); + goaway ("We died trying to run gzip"); + t->Tmode = 0; + } + fd = open (temp_file,O_RDONLY,0); + } + else + fd = open (t->Tname,O_RDONLY,0); + } + if (fd < 0 && (t->Tflags&FUPDATE) == 0) t->Tmode = 0; + } + if (t->Tmode) { + t->Tuser = salloc (uconvert (t->Tuid)); + t->Tgroup = salloc (gconvert (t->Tgid)); + } + } + x = msgrecv (sendfile,fd); + if (docompress) + unlink(temp_file); +#ifdef RCS + if (dorcs) + unlink(rcs_file); +#endif + if (x != SCMOK) goaway ("Error sending file to client"); + return (SCMOK); +} + +senddir (t) +TREE *t; +{ + register int x; + char *uconvert(),*gconvert(); + int sendfile (); + + if ((t->Tflags&FNEEDED) == 0) /* only send needed files */ + return (SCMOK); + if ((t->Tmode&S_IFMT) != S_IFDIR) /* send only directories this pass */ + return (SCMOK); + x = msgsend (); + if (x != SCMOK) goaway ("Error reading receive file request from client"); + upgradeT = t; /* upgrade file pointer */ + t->Tuser = salloc (uconvert (t->Tuid)); + t->Tgroup = salloc (gconvert (t->Tgid)); + x = msgrecv (sendfile,0); + if (x != SCMOK) goaway ("Error sending file to client"); + return (SCMOK); +} + +sendfile (t,ap) +register TREE *t; +va_list ap; +{ + register int x; + int fd = va_arg(ap,int); + if ((t->Tmode&S_IFMT) != S_IFREG || listonly || (t->Tflags&FUPDATE)) + return (SCMOK); + x = writefile (fd); + if (x != SCMOK) goaway ("Error sending file to client"); + (void) close (fd); + return (SCMOK); +} + +/***************************************** + *** E N D C O N N E C T I O N *** + *****************************************/ + +finishup (starttime) +long starttime; +{ + register int x = SCMOK; + char tmpbuf[BUFSIZ], *p, lognam[STRINGLENGTH]; + int logfd; + struct stat sbuf; + long finishtime; + char *releasename; + + (void) netcrypt ((char *)NULL); + if (protver < 6) { + if (goawayreason != NULL) + free (goawayreason); + goawayreason = (char *)NULL; + x = msggoaway(); + doneack = FDONESUCCESS; + donereason = salloc ("Unknown"); + } else if (goawayreason == (char *)NULL) + x = msgdone (); + else { + doneack = FDONEGOAWAY; + donereason = goawayreason; + } + if (x == SCMEOF || x == SCMERR) { + doneack = FDONEUSRERROR; + donereason = salloc ("Premature EOF on network"); + } else if (x != SCMOK) { + doneack = FDONESRVERROR; + donereason = salloc ("Unknown SCM code"); + } + if (doneack == FDONEDONTLOG) + return; + if (donereason == NULL) + donereason = salloc ("No reason"); + if (doneack == FDONESRVERROR || doneack == FDONEUSRERROR) + logerr ("%s", donereason); + else if (doneack == FDONEGOAWAY) + logerr ("GOAWAY: %s",donereason); + else if (doneack != FDONESUCCESS) + logerr ("Reason %d: %s",doneack,donereason); + goawayreason = donereason; + cdprefix ((char *)NULL); + (void) sprintf (lognam,FILELOGFILE,collname); + if ((logfd = open(lognam,O_APPEND|O_WRONLY,0644)) < 0) + return; /* can not open file up...error */ + finishtime = time ((long *)NULL); + p = tmpbuf; + (void) sprintf (p,"%s ",fmttime (lasttime)); + p += strlen(p); + (void) sprintf (p,"%s ",fmttime (starttime)); + p += strlen(p); + (void) sprintf (p,"%s ",fmttime (finishtime)); + p += strlen(p); + if ((releasename = release) == NULL) + releasename = "UNKNOWN"; + (void) sprintf (p,"%s %s %d %s\n",remotehost(),releasename, + FDONESUCCESS-doneack,donereason); + p += strlen(p); +#if MACH + /* if we are busy dont get stuck updating the disk if full */ + if(setupack == FSETUPBUSY) { + long l = FIOCNOSPC_ERROR; + ioctl(logfd, FIOCNOSPC, &l); + } +#endif /* MACH */ + (void) write(logfd,tmpbuf,(p - tmpbuf)); + (void) close(logfd); +} + +/*************************************************** + *** H A S H T A B L E R O U T I N E S *** + ***************************************************/ + +Hfree (table) +HASH **table; +{ + register HASH *h; + register int i; + for (i = 0; i < HASHSIZE; i++) + while (h = table[i]) { + table[i] = h->Hnext; + if (h->Hname) free (h->Hname); + free ((char *)h); + } +} + +HASH *Hlookup (table,num1,num2) +HASH **table; +int num1,num2; +{ + register HASH *h; + register int hno; + hno = HASHFUNC(num1,num2); + for (h = table[hno]; h && (h->Hnum1 != num1 || h->Hnum2 != num2); h = h->Hnext); + return (h); +} + +Hinsert (table,num1,num2,name,tree) +HASH **table; +int num1,num2; +char *name; +TREE *tree; +{ + register HASH *h; + register int hno; + hno = HASHFUNC(num1,num2); + h = (HASH *) malloc (sizeof(HASH)); + h->Hnum1 = num1; + h->Hnum2 = num2; + h->Hname = name; + h->Htree = tree; + h->Hnext = table[hno]; + table[hno] = h; +} + +/********************************************* + *** U T I L I T Y R O U T I N E S *** + *********************************************/ + +TREE *linkcheck (t,d,i) +TREE *t; +int d,i; /* inode # and device # */ +{ + register HASH *h; + h = Hlookup (inodeH,i,d); + if (h) return (h->Htree); + Hinsert (inodeH,i,d,(char *)NULL,t); + return ((TREE *)NULL); +} + +char *uconvert (uid) +int uid; +{ + register struct passwd *pw; + register char *p; + register HASH *u; + u = Hlookup (uidH,uid,0); + if (u) return (u->Hname); + pw = getpwuid (uid); + if (pw == NULL) return (""); + p = salloc (pw->pw_name); + Hinsert (uidH,uid,0,p,(TREE*)NULL); + return (p); +} + +char *gconvert (gid) +int gid; +{ + register struct group *gr; + register char *p; + register HASH *g; + g = Hlookup (gidH,gid,0); + if (g) return (g->Hname); + gr = getgrgid (gid); + if (gr == NULL) return (""); + p = salloc (gr->gr_name); + Hinsert (gidH,gid,0,p,(TREE *)NULL); + return (p); +} + +char *changeuid (namep,passwordp,fileuid,filegid) +char *namep,*passwordp; +int fileuid,filegid; +{ + char *okpassword (); + char *group,*account,*pswdp; + struct passwd *pwd; + struct group *grp; +#if CMUCS + struct account *acc; + struct ttyloc tlc; +#endif /* CMUCS */ + register int status = ACCESS_CODE_OK; + char nbuf[STRINGLENGTH]; + static char errbuf[STRINGLENGTH]; +#if CMUCS + int *grps; +#endif /* CMUCS */ + char *p; + + if (namep == NULL) { + pwd = getpwuid (fileuid); + if (pwd == NULL) { + (void) sprintf (errbuf,"Reason: Unknown user id %d", + fileuid); + return (errbuf); + } + grp = getgrgid (filegid); + if (grp) group = strcpy (nbuf,grp->gr_name); + else group = NULL; + account = NULL; + pswdp = NULL; + } else { + (void) strcpy (nbuf,namep); + account = group = index (nbuf,','); + if (group != NULL) { + *group++ = '\0'; + account = index (group,','); + if (account != NULL) { + *account++ = '\0'; + if (*account == '\0') account = NULL; + } + if (*group == '\0') group = NULL; + } + pwd = getpwnam (nbuf); + if (pwd == NULL) { + (void) sprintf (errbuf,"Reason: Unknown user %s", + nbuf); + return (errbuf); + } + if (strcmp (nbuf,DEFUSER) == 0) + pswdp = NULL; + else + pswdp = passwordp ? passwordp : ""; +#ifdef AFS + if (strcmp (nbuf,DEFUSER) != 0) { + char *reason; + setpag(); /* set a pag */ + if (ka_UserAuthenticate(pwd->pw_name, "", 0, + pswdp, 1, &reason)) { + (void) sprintf (errbuf,"AFS authentication failed, %s", + reason); + logerr ("Attempt by %s; %s", + nbuf, errbuf); + return (errbuf); + } + } +#endif + } + if (getuid () != 0) { + if (getuid () == pwd->pw_uid) + return (NULL); + if (strcmp (pwd->pw_name,DEFUSER) == 0) + return (NULL); + logerr ("Fileserver not superuser"); + return ("Reason: fileserver is not running privileged"); + } +#if CMUCS + tlc.tlc_hostid = TLC_UNKHOST; + tlc.tlc_ttyid = TLC_UNKTTY; + if (okaccess(pwd->pw_name,ACCESS_TYPE_SU,0,-1,tlc) != 1) + status = ACCESS_CODE_DENIED; + else { + grp = NULL; + acc = NULL; + status = oklogin(pwd->pw_name,group,&account,pswdp,&pwd,&grp,&acc,&grps); + if (status == ACCESS_CODE_OK) { + if ((p = okpassword(pswdp,pwd->pw_name,pwd->pw_gecos)) != NULL) + status = ACCESS_CODE_INSECUREPWD; + } + } +#else /* CMUCS */ + status = ACCESS_CODE_OK; + if (namep && strcmp(pwd->pw_name, DEFUSER) != 0) + if (strcmp(pwd->pw_passwd,(char *)crypt(pswdp,pwd->pw_passwd))) + status = ACCESS_CODE_BADPASSWORD; +#endif /* CMUCS */ + switch (status) { + case ACCESS_CODE_OK: + break; + case ACCESS_CODE_BADPASSWORD: + p = "Reason: Invalid password"; + break; +#if CMUCS + case ACCESS_CODE_INSECUREPWD: + (void) sprintf (errbuf,"Reason: %s",p); + p = errbuf; + break; + case ACCESS_CODE_DENIED: + p = "Reason: Access denied"; + break; + case ACCESS_CODE_NOUSER: + p = errbuf; + break; + case ACCESS_CODE_ACCEXPIRED: + p = "Reason: Account expired"; + break; + case ACCESS_CODE_GRPEXPIRED: + p = "Reason: Group expired"; + break; + case ACCESS_CODE_ACCNOTVALID: + p = "Reason: Invalid account"; + break; + case ACCESS_CODE_MANYDEFACC: + p = "Reason: User has more than one default account"; + break; + case ACCESS_CODE_NOACCFORGRP: + p = "Reason: No account for group"; + break; + case ACCESS_CODE_NOGRPFORACC: + p = "Reason: No group for account"; + break; + case ACCESS_CODE_NOGRPDEFACC: + p = "Reason: No group for default account"; + break; + case ACCESS_CODE_NOTGRPMEMB: + p = "Reason: Not member of group"; + break; + case ACCESS_CODE_NOTDEFMEMB: + p = "Reason: Not member of default group"; + break; + case ACCESS_CODE_OOPS: + p = "Reason: Internal error"; + break; +#endif /* CMUCS */ + default: + (void) sprintf (p = errbuf,"Reason: Status %d",status); + break; + } + if (pwd == NULL) + return (p); + if (status != ACCESS_CODE_OK) { + logerr ("Login failure for %s",pwd->pw_name); + logerr ("%s",p); +#if CMUCS + logaccess (pwd->pw_name,ACCESS_TYPE_SUP,status,0,-1,tlc); +#endif /* CMUCS */ + return (p); + } +#if CMUCS + if (setgroups (grps[0], &grps[1]) < 0) + logerr ("setgroups: %%m"); + if (setgid ((gid_t)grp->gr_gid) < 0) + logerr ("setgid: %%m"); + if (setuid ((uid_t)pwd->pw_uid) < 0) + logerr ("setuid: %%m"); +#else /* CMUCS */ + if (initgroups (pwd->pw_name,pwd->pw_gid) < 0) + return("Error setting group list"); + if (setgid (pwd->pw_gid) < 0) + logerr ("setgid: %%m"); + if (setuid (pwd->pw_uid) < 0) + logerr ("setuid: %%m"); +#endif /* CMUCS */ + return (NULL); +} + +#if __STDC__ +goaway (char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +goaway (va_alist) +va_dcl +#endif +{ +#if !__STDC__ + register char *fmt; +#endif + char buf[STRINGLENGTH]; + va_list ap; + + (void) netcrypt ((char *)NULL); +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + fmt = va_arg(ap,char *); +#endif + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + goawayreason = salloc (buf); + (void) msggoaway (); + logerr ("%s",buf); + longjmp (sjbuf,TRUE); +} + +char *fmttime (time) +long time; +{ + static char buf[STRINGLENGTH]; + int len; + + (void) strcpy (buf,ctime (&time)); + len = strlen(buf+4)-6; + (void) strncpy (buf,buf+4,len); + buf[len] = '\0'; + return (buf); +} + +/* + * Determine whether the file referenced by the file descriptor 'handle' can + * be trusted, namely is it a file resident in the local file system. + * + * The main method of operation is to perform operations on the file + * descriptor so that an attempt to spoof the checks should fail, for + * example renamimg the file from underneath us and/or changing where the + * file lives from underneath us. + * + * returns: -1 for error, indicating that we can not tell + * 0 for file is definately not local, or it is an RFS link + * 1 for file is local and can be trusted + * + * Side effect: copies the stat information into the supplied buffer, + * regardless of the type of file system the file resides. + * + * Currently, the cases that we try to distinguish are RFS, AFS, NFS and + * UFS, where the latter is considered a trusted file. We assume that the + * caller has disabled link following and will detect an attempt to access + * a file through an RFS link, except in the case the the last component is + * an RFS link. With link following disabled, the last component itself is + * interpreted as a regular file if it is really an RFS link, so we + * disallow the RFS link identified by group "symlink" and mode "IEXEC by + * owner only". An AFS file is + * detected by trying the VIOCIGETCELL ioctl, which is one of the few AFS + * ioctls which operate on a file descriptor. Note, this AFS ioctl is + * implemented in the cache manager, so the decision does not involve a + * query with the AFS file server. An NFS file is detected by looking at + * the major device number and seeing if it matches the known values for + * MACH NSF/Sun OS 3.x or Sun OS 4.x. + * + * Having the fstatfs() system call would make this routine easier and + * more reliable. + * + * Note, in order to make the checks simpler, the file referenced by the + * file descriptor can not be a BSD style symlink. Even with symlink + * following of the last path component disabled, the attempt to open a + * file which is a symlink will succeed, so we check for the BSD symlink + * file type here. Also, the link following on/off and RFS file types + * are only relevant in a MACH environment. + */ +#ifdef AFS +#include <sys/viceioctl.h> +#endif + +#define SYMLINK_GRP 64 + +int local_file(handle, sinfo) +int handle; +struct stat *sinfo; +{ + struct stat sb; +#ifdef VIOCIGETCELL + /* + * dummies for the AFS ioctl + */ + struct ViceIoctl vdata; + char cellname[512]; +#endif /* VIOCIGETCELL */ + + if (fstat(handle, &sb) < 0) + return(-1); + if (sinfo != NULL) + *sinfo = sb; + +#if CMUCS + /* + * If the following test succeeds, then the file referenced by + * 'handle' is actually an RFS link, so we will not trust it. + * See <sys/inode.h>. + */ + if (sb.st_gid == SYMLINK_GRP + && (sb.st_mode & (S_IFMT|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))) + == (S_IFREG|S_IEXEC)) + return(0); +#endif /* CMUCS */ + + /* + * Do not trust BSD style symlinks either. + */ + if ((sb.st_mode & S_IFMT) == S_IFLNK) + return(0); + +#ifdef VIOCIGETCELL + /* + * This is the VIOCIGETCELL ioctl, which takes an fd, not + * a path name. If it succeeds, then the file is in AFS. + * + * On failure, ENOTTY indicates that the file was not in + * AFS; all other errors are pessimistically assumed to be + * a temporary AFS error. + */ + vdata.in_size = 0; + vdata.out_size = sizeof(cellname); + vdata.out = cellname; + if (ioctl(handle, VIOCIGETCELL, (char *)&vdata) != -1) + return(0); + if (errno != ENOTTY) + return(-1); +#endif /* VIOCIGETCELL */ + + /* + * Verify the file is not in NFS. + * + * Our current implementation and Sun OS 3.x use major device + * 255 for NFS files; Sun OS 4.x seems to use 130 (I have only + * determined this empirically -- DLC). Without a fstatfs() + * system call, this will have to do for now. + */ + if (major(sb.st_dev) == 255 || major(sb.st_dev) == 130) + return(0); + + return(1); +} + +/* + * Companion routine for ensuring that a local file can be trusted. Compare + * various pieces of the stat information to make sure that the file can be + * trusted. Returns true for stat information which meets the criteria + * for being trustworthy. The main paranoia is to prevent a hard link to + * a root owned file. Since the link could be removed after the file is + * opened, a simply fstat() can not be relied upon. The two stat buffers + * for comparison should come from a stat() on the file name and a following + * fstat() on the open file. Some of the following checks are also an + * additional level of paranoia. Also, this test will fail (correctly) if + * either or both of the stat structures have all fields zeroed; typically + * due to a stat() failure. + */ + + +int stat_info_ok(sb1, sb2) +struct stat *sb1, *sb2; +{ + return (sb1->st_ino == sb2->st_ino && /* Still the same file */ + sb1->st_dev == sb2->st_dev && /* On the same device */ + sb1->st_mode == sb2->st_mode && /* Perms (and type) same */ + (sb1->st_mode & S_IFMT) == S_IFREG && /* Only allow reg files */ + (sb1->st_mode & 077) == 0 && /* Owner only perms */ + sb1->st_nlink == sb2->st_nlink && /* # hard links same... */ + sb1->st_nlink == 1 && /* and only 1 */ + sb1->st_uid == sb2->st_uid && /* owner and ... */ + sb1->st_gid == sb2->st_gid && /* group unchanged */ + sb1->st_mtime == sb2->st_mtime && /* Unmodified between stats */ + sb1->st_ctime == sb2->st_ctime); /* Inode unchanged. Hopefully + a catch-all paranoid test */ +} + +#if MACH +/* + * Twiddle symbolic/RFS link following on/off. This is a no-op in a non + * CMUCS/MACH environment. Also, the setmodes/getmodes interface is used + * mainly because it is simpler than using table(2) directly. + */ +#include <sys/table.h> + +int link_nofollow(on) +int on; +{ + static int modes = -1; + + if (modes == -1 && (modes = getmodes()) == -1) + return(-1); + if (on) + return(setmodes(modes | UMODE_NOFOLLOW)); + return(setmodes(modes)); +} +#else /* MACH */ +/*ARGSUSED*/ +int link_nofollow(on) +int on; +{ + return(0); +} +#endif /* MACH */ diff --git a/usr.bin/sup/src/supmsg.c b/usr.bin/sup/src/supmsg.c new file mode 100644 index 00000000000..21b49916f6a --- /dev/null +++ b/usr.bin/sup/src/supmsg.c @@ -0,0 +1,625 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + ********************************************************************** + * HISTORY + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supmsg.c,v $ + * Revision 1.1 1995/12/16 11:47:00 deraadt + * add sup to the tree + * + * Revision 1.2 1993/08/04 17:46:23 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.1.1.1 1993/05/21 14:52:19 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 2.4 92/09/09 22:05:17 mrt + * Moved PFI definition under __STDC__ conditional since it + * is already defined in libc.h in this case. + * [92/09/01 mrt] + * + * Revision 2.3 92/08/11 12:08:12 mrt + * Added copyright + * [92/08/10 mrt] + * Brad's changes: Delinted, Incorporated updated variable + * argument list usage from old msgxfer.c + * [92/07/24 mrt] + * + * Revision 2.2 89/08/23 15:02:56 gm0w + * Created from separate message modules. + * [89/08/14 gm0w] + * + ********************************************************************** + */ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <libc.h> +#include <c.h> +#include "sup.h" +#define MSGSUBR +#define MSGFILE +#include "supmsg.h" + +/* + * signon message + */ +extern int pgmver; /* program version of partner */ +extern int pgmversion; /* my program version */ +extern char *scmver; /* scm version of partner */ +extern int fspid; /* process id of fileserver */ + +int msgsignon () +{ + register int x; + + if (server) { + x = readmsg (MSGSIGNON); + if (x == SCMOK) x = readint (&protver); + if (x == SCMOK) x = readint (&pgmver); + if (x == SCMOK) x = readstring (&scmver); + if (x == SCMOK) x = readmend (); + } else { + x = writemsg (MSGSIGNON); + if (x == SCMOK) x = writeint (PROTOVERSION); + if (x == SCMOK) x = writeint (pgmversion); + if (x == SCMOK) x = writestring (scmversion); + if (x == SCMOK) x = writemend (); + } + return (x); +} + +int msgsignonack () +{ + register int x; + + if (server) { + x = writemsg (MSGSIGNONACK); + if (x == SCMOK) x = writeint (PROTOVERSION); + if (x == SCMOK) x = writeint (pgmversion); + if (x == SCMOK) x = writestring (scmversion); + if (x == SCMOK) x = writeint (fspid); + if (x == SCMOK) x = writemend (); + } else { + x = readmsg (MSGSIGNONACK); + if (x == SCMOK) x = readint (&protver); + if (x == SCMOK) x = readint (&pgmver); + if (x == SCMOK) x = readstring (&scmver); + if (x == SCMOK) x = readint (&fspid); + if (x == SCMOK) x = readmend (); + } + return (x); +} + +/* + * setup message + */ +extern int xpatch; /* setup crosspatch to a new client */ +extern char *xuser; /* user,group,acct for crosspatch */ +extern char *collname; /* base directory */ +extern char *basedir; /* base directory */ +extern int basedev; /* base directory device */ +extern int baseino; /* base directory inode */ +extern long lasttime; /* time of last upgrade */ +extern int listonly; /* only listing files, no data xfer */ +extern int newonly; /* only send new files */ +extern char *release; /* release name */ +extern int setupack; /* ack return value for setup */ + +int msgsetup () +{ + register int x; + + if (server) { + x = readmsg (MSGSETUP); + if (x != SCMOK) return (x); + if (protver >= 7) { + x = readint (&xpatch); + if (x != SCMOK) return (x); + } else + xpatch = FALSE; + if (xpatch) { + x = readstring (&xuser); + if (x != SCMOK) return (x); + return (readmend ()); + } + x = readstring (&collname); + if (x == SCMOK) x = readint ((int *)&lasttime); + if (x == SCMOK) x = readstring (&basedir); + if (x == SCMOK) x = readint (&basedev); + if (x == SCMOK) x = readint (&baseino); + if (x == SCMOK) x = readint (&listonly); + if (x == SCMOK) x = readint (&newonly); + if (x == SCMOK) + if (protver < 6) + release = (char *)NULL; + else + x = readstring (&release); + if (x == SCMOK) x = readmend (); + } else { + x = writemsg (MSGSETUP); + if (x != SCMOK) return (x); + if (protver >= 7) { + x = writeint (xpatch); + if (x != SCMOK) return (x); + } + if (xpatch) { + x = writestring (xuser); + if (x != SCMOK) return (x); + return (writemend ()); + } + if (x == SCMOK) x = writestring (collname); + if (x == SCMOK) x = writeint ((int)lasttime); + if (x == SCMOK) x = writestring (basedir); + if (x == SCMOK) x = writeint (basedev); + if (x == SCMOK) x = writeint (baseino); + if (x == SCMOK) x = writeint (listonly); + if (x == SCMOK) x = writeint (newonly); + if (x == SCMOK && protver >= 6) x = writestring (release); + if (x == SCMOK) x = writemend (); + } + return (x); +} + +int msgsetupack () +{ + if (server) + return (writemint (MSGSETUPACK,setupack)); + return (readmint (MSGSETUPACK,&setupack)); +} + +/* + * crypt test message + */ +extern char *crypttest; /* encryption test string */ + +int msgcrypt () +{ + if (server) + return (readmstr (MSGCRYPT,&crypttest)); + return (writemstr (MSGCRYPT,crypttest)); +} + +int msgcryptok () +{ + if (server) + return (writemnull (MSGCRYPTOK)); + return (readmnull (MSGCRYPTOK)); +} + +/* + * login message + */ +extern char *logcrypt; /* login encryption test */ +extern char *loguser; /* login username */ +extern char *logpswd; /* password for login */ +extern int logack; /* login ack status */ +extern char *logerror; /* error from login */ + +int msglogin () +{ + register int x; + if (server) { + x = readmsg (MSGLOGIN); + if (x == SCMOK) x = readstring (&logcrypt); + if (x == SCMOK) x = readstring (&loguser); + if (x == SCMOK) x = readstring (&logpswd); + if (x == SCMOK) x = readmend (); + } else { + x = writemsg (MSGLOGIN); + if (x == SCMOK) x = writestring (logcrypt); + if (x == SCMOK) x = writestring (loguser); + if (x == SCMOK) x = writestring (logpswd); + if (x == SCMOK) x = writemend (); + } + return (x); +} + +int msglogack () +{ + register int x; + if (server) { + x = writemsg (MSGLOGACK); + if (x == SCMOK) x = writeint (logack); + if (x == SCMOK) x = writestring (logerror); + if (x == SCMOK) x = writemend (); + } else { + x = readmsg (MSGLOGACK); + if (x == SCMOK) x = readint (&logack); + if (x == SCMOK) x = readstring (&logerror); + if (x == SCMOK) x = readmend (); + } + return (x); +} + +/* + * refuse list message + */ +extern TREE *refuseT; /* tree of files to refuse */ + +static int refuseone (t) +register TREE *t; +{ + return (writestring (t->Tname)); +} + +int msgrefuse () +{ + register int x; + if (server) { + char *name; + x = readmsg (MSGREFUSE); + if (x == SCMOK) x = readstring (&name); + while (x == SCMOK) { + if (name == NULL) break; + (void) Tinsert (&refuseT,name,FALSE); + free (name); + x = readstring (&name); + } + if (x == SCMOK) x = readmend (); + } else { + x = writemsg (MSGREFUSE); + if (x == SCMOK) x = Tprocess (refuseT,refuseone); + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = writemend (); + } + return (x); +} + +/* + * list files message + */ +extern TREE *listT; /* tree of files to list */ +extern long scantime; /* time that collection was scanned */ + +static int listone (t) +register TREE *t; +{ + register int x; + + x = writestring (t->Tname); + if (x == SCMOK) x = writeint ((int)t->Tmode); + if (x == SCMOK) x = writeint ((int)t->Tflags); + if (x == SCMOK) x = writeint (t->Tmtime); + return (x); +} + +int msglist () +{ + register int x; + if (server) { + x = writemsg (MSGLIST); + if (x == SCMOK) x = Tprocess (listT,listone); + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = writeint ((int)scantime); + if (x == SCMOK) x = writemend (); + } else { + char *name; + int mode,flags,mtime; + register TREE *t; + x = readmsg (MSGLIST); + if (x == SCMOK) x = readstring (&name); + while (x == SCMOK) { + if (name == NULL) break; + x = readint (&mode); + if (x == SCMOK) x = readint (&flags); + if (x == SCMOK) x = readint (&mtime); + if (x != SCMOK) break; + t = Tinsert (&listT,name,TRUE); + free (name); + t->Tmode = mode; + t->Tflags = flags; + t->Tmtime = mtime; + x = readstring (&name); + } + if (x == SCMOK) x = readint ((int *)&scantime); + if (x == SCMOK) x = readmend (); + } + return (x); +} + +/* + * files needed message + */ +extern TREE *needT; /* tree of files to need */ + +static int needone (t) +register TREE *t; +{ + register int x; + x = writestring (t->Tname); + if (x == SCMOK) x = writeint ((t->Tflags&FUPDATE) != 0); + return (x); +} + +int msgneed () +{ + register int x; + if (server) { + char *name; + int update; + register TREE *t; + x = readmsg (MSGNEED); + if (x == SCMOK) x = readstring (&name); + while (x == SCMOK) { + if (name == NULL) break; + x = readint (&update); + if (x != SCMOK) break; + t = Tinsert (&needT,name,TRUE); + free (name); + if (update) t->Tflags |= FUPDATE; + x = readstring (&name); + } + if (x == SCMOK) x = readmend (); + } else { + x = writemsg (MSGNEED); + if (x == SCMOK) x = Tprocess (needT,needone); + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = writemend (); + } + return (x); +} + +/* + * files denied message + */ +extern TREE *denyT; /* tree of files to deny */ + +static int denyone (t) +register TREE *t; +{ + return (writestring (t->Tname)); +} + +int msgdeny () +{ + register int x; + if (server) { + x = writemsg (MSGDENY); + if (x == SCMOK) x = Tprocess (denyT,denyone); + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = writemend (); + } else { + char *name; + x = readmsg (MSGDENY); + if (x == SCMOK) x = readstring (&name); + while (x == SCMOK) { + if (name == NULL) break; + (void) Tinsert (&denyT,name,FALSE); + free (name); + x = readstring (&name); + } + if (x == SCMOK) x = readmend (); + } + return (x); +} + +/* + * send file message + */ +int msgsend () +{ + if (server) + return (readmnull (MSGSEND)); + return (writemnull (MSGSEND)); +} + +/* + * receive file message + */ +extern TREE *upgradeT; /* pointer to file being upgraded */ + +static int writeone (t) +register TREE *t; +{ + return (writestring (t->Tname)); +} + + +#if __STDC__ +int msgrecv (PFI xferfile,...) +#else +/*VARARGS*//*ARGSUSED*/ +int msgrecv (va_alist) +va_dcl +#endif +{ +#if !__STDC__ + typedef int (*PFI)(); + PFI xferfile; +#endif + va_list args; + register int x; + register TREE *t = upgradeT; +#if __STDC__ + va_start(args,xferfile); +#else + va_start(args); + xferfile = va_arg(args, PFI); +#endif + if (server) { + x = writemsg (MSGRECV); + if (t == NULL) { + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = writemend (); + return (x); + } + if (x == SCMOK) x = writestring (t->Tname); + if (x == SCMOK) x = writeint (t->Tmode); + if (t->Tmode == 0) { + if (x == SCMOK) x = writemend (); + return (x); + } + if (x == SCMOK) x = writeint (t->Tflags); + if (x == SCMOK) x = writestring (t->Tuser); + if (x == SCMOK) x = writestring (t->Tgroup); + if (x == SCMOK) x = writeint (t->Tmtime); + if (x == SCMOK) x = Tprocess (t->Tlink,writeone); + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = Tprocess (t->Texec,writeone); + if (x == SCMOK) x = writestring ((char *)NULL); + if (x == SCMOK) x = (*xferfile) (t,args); + if (x == SCMOK) x = writemend (); + } else { + char *linkname,*execcmd; + if (t == NULL) return (SCMERR); + x = readmsg (MSGRECV); + if (x == SCMOK) x = readstring (&t->Tname); + if (x == SCMOK && t->Tname == NULL) { + x = readmend (); + if (x == SCMOK) x = (*xferfile) (NULL,args); + return (x); + } + if (x == SCMOK) x = readint (&t->Tmode); + if (t->Tmode == 0) { + x = readmend (); + if (x == SCMOK) x = (*xferfile) (t,args); + return (x); + } + if (x == SCMOK) x = readint (&t->Tflags); + if (x == SCMOK) x = readstring (&t->Tuser); + if (x == SCMOK) x = readstring (&t->Tgroup); + if (x == SCMOK) x = readint (&t->Tmtime); + t->Tlink = NULL; + if (x == SCMOK) x = readstring (&linkname); + while (x == SCMOK) { + if (linkname == NULL) break; + (void) Tinsert (&t->Tlink,linkname,FALSE); + free (linkname); + x = readstring (&linkname); + } + t->Texec = NULL; + if (x == SCMOK) x = readstring (&execcmd); + while (x == SCMOK) { + if (execcmd == NULL) break; + (void) Tinsert (&t->Texec,execcmd,FALSE); + free (execcmd); + x = readstring (&execcmd); + } + if (x == SCMOK) x = (*xferfile) (t,args); + if (x == SCMOK) x = readmend (); + } + va_end(args); + return (x); +} + +/* + * protocol done message + */ +extern int doneack; +extern char *donereason; + +int msgdone () +{ + register int x; + + if (protver < 6) { + printf ("Error, msgdone should not have been called."); + return (SCMERR); + } + if (server) { + x = readmsg (MSGDONE); + if (x == SCMOK) x = readint (&doneack); + if (x == SCMOK) x = readstring (&donereason); + if (x == SCMOK) x = readmend (); + } else { + x = writemsg (MSGDONE); + if (x == SCMOK) x = writeint (doneack); + if (x == SCMOK) x = writestring (donereason); + if (x == SCMOK) x = writemend (); + } + return (x); +} + +/* + * go away message + */ +extern char *goawayreason; /* reason for goaway */ + +int msggoaway () +{ + return (writemstr (MSGGOAWAY,goawayreason)); +} + +/* + * cross-patch protocol message + */ +extern int xargc; /* arg count for crosspatch */ +extern char **xargv; /* arg array for crosspatch */ + +int msgxpatch () +{ + register int x; + register int i; + + if (server) { + x = readmsg (MSGXPATCH); + if (x != SCMOK) return (x); + x = readint (&xargc); + if (x != SCMOK) return (x); + xargc += 2; + xargv = (char **)calloc (sizeof (char *),(unsigned)xargc+1); + if (xargv == NULL) + return (SCMERR); + for (i = 2; i < xargc; i++) { + x = readstring (&xargv[i]); + if (x != SCMOK) return (x); + } + x = readmend (); + } else { + x = writemsg (MSGXPATCH); + if (x != SCMOK) return (x); + x = writeint (xargc); + if (x != SCMOK) return (x); + for (i = 0; i < xargc; i++) { + x = writestring (xargv[i]); + if (x != SCMOK) return (x); + } + x = writemend (); + } + return (x); +} + +/* + * Compression check protocol message + */ +extern int docompress; /* Compress file before sending? */ + +int msgcompress () +{ + if (server) + return (readmint (MSGCOMPRESS,&docompress)); + return (writemint (MSGCOMPRESS, docompress)); +} diff --git a/usr.bin/sup/src/supmsg.h b/usr.bin/sup/src/supmsg.h new file mode 100644 index 00000000000..d4da8531d36 --- /dev/null +++ b/usr.bin/sup/src/supmsg.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * supmsg.h - global definitions/variables used in msg routines. + * + ********************************************************************** + * HISTORY + * + * 7-July-93 Nate Williams at Montana State University + * Modified SUP to use gzip based compression when sending files + * across the network to save BandWidth + * + * $Log: supmsg.h,v $ + * Revision 1.1 1995/12/16 11:47:01 deraadt + * add sup to the tree + * + * Revision 1.2 1993/08/04 17:46:24 brezak + * Changes from nate for gzip'ed sup + * + * Revision 1.1.1.1 1993/05/21 14:52:19 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.7 92/08/11 12:08:20 mrt + * Added copyright. + * [92/08/10 mrt] + * + * Revision 1.6 89/08/23 14:56:42 gm0w + * Changed MSGF to MSG constants. + * [89/08/23 gm0w] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added crosspatch support. Removed nameserver support. + * + * 29-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added "release" support. + * + * 27-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Added MSGFDONE and subvalues, added doneack and donereason. + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added changes to make lint happy. + * + * 04-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed hostname to hostT to support multiple repositories per + * collection. Added FSETUPBUSY to tell clients that server is + * currently busy. + * + * 19-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +/* Special messages reserved for SCM */ +#define MSGGOAWAY (-1) /* see scm.c */ + +/* Message types -- see supmsg.c */ +#define MSGSIGNON (101) +#define MSGSIGNONACK (102) +#define MSGSETUP (103) +#define MSGSETUPACK (104) +#define MSGLOGIN (105) +#define MSGLOGACK (106) +#define MSGCRYPT (107) +#define MSGCRYPTOK (108) +#define MSGREFUSE (109) +#define MSGLIST (110) +#define MSGNEED (111) +#define MSGDENY (112) +#define MSGSEND (113) +#define MSGRECV (114) +#define MSGDONE (115) +#define MSGXPATCH (117) +#define MSGCOMPRESS (118) + +/* MSGSETUPACK data codes - setupack */ +#define FSETUPOK (999) +#define FSETUPHOST (998) +#define FSETUPSAME (997) +#define FSETUPOLD (996) +#define FSETUPBUSY (995) +#define FSETUPRELEASE (994) + +/* MSGLOGACK data codes - loginack */ +#define FLOGOK (989) +#define FLOGNG (988) + +/* MSGDONE data codes - doneack */ +#define FDONESUCCESS (979) +#define FDONEDONTLOG (978) +#define FDONESRVERROR (977) +#define FDONEUSRERROR (976) +#define FDONEGOAWAY (975) + +#ifdef MSGSUBR + +/* used in all msg routines */ +extern int server; /* true if we are the server */ +extern int protver; /* protocol version of partner */ + +#else MSGSUBR + +#ifdef MSGFILE +#define EXTERN +#else MSGFILE +#define EXTERN extern +#endif MSGFILE + +/* used in all msg routines */ +EXTERN int server; /* true if we are the server */ + +/* msggoaway */ +EXTERN char *goawayreason; /* reason for goaway */ + +/* msgsignon */ +EXTERN int pgmversion; /* version of this program */ +EXTERN int protver; /* protocol version of partner */ +EXTERN int pgmver; /* program version of partner */ +EXTERN char *scmver; /* scm version of partner */ +EXTERN int fspid; /* process id of fileserver */ + +/* msgsetup */ +EXTERN int xpatch; /* setup crosspatch to a new client */ +EXTERN char *xuser; /* user for crosspatch */ +EXTERN char *collname; /* collection name */ +EXTERN char *basedir; /* base directory */ +EXTERN int basedev; /* base directory device */ +EXTERN int baseino; /* base directory inode */ +EXTERN long lasttime; /* time of last upgrade */ +EXTERN int listonly; /* only listing files, no data xfer */ +EXTERN int newonly; /* only send new files */ +EXTERN char *release; /* release name */ +EXTERN int setupack; /* ack return value for setup */ + +/* msgcrypt */ +EXTERN char *crypttest; /* encryption test string */ + +/* msglogin */ +EXTERN char *logcrypt; /* login encryption test */ +EXTERN char *loguser; /* login username */ +EXTERN char *logpswd; /* password for login */ +EXTERN int logack; /* login ack status */ +EXTERN char *logerror; /* error string from oklogin */ + +/* msgxpatch */ +EXTERN int xargc; /* arg count for crosspatch */ +EXTERN char **xargv; /* arg array for crosspatch */ + +/* msgrefuse */ +EXTERN TREE *refuseT; /* tree of files to refuse */ + +/* msglist */ +EXTERN TREE *listT; /* tree of files to list */ +EXTERN long scantime; /* time that collection was scanned */ + +/* msgneed */ +EXTERN TREE *needT; /* tree of files to need */ + +/* msgdeny */ +EXTERN TREE *denyT; /* tree of files to deny */ + +/* msgrecv */ +/* msgsend */ +EXTERN TREE *upgradeT; /* pointer to file being upgraded */ + +/* msgdone */ +EXTERN int doneack; /* done ack status */ +EXTERN char *donereason; /* set if indicated by doneack */ + +#undef EXTERN + +#endif MSGSUBR diff --git a/usr.bin/sup/src/supscan.c b/usr.bin/sup/src/supscan.c new file mode 100644 index 00000000000..1e6e8088373 --- /dev/null +++ b/usr.bin/sup/src/supscan.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * supscan -- SUP Scan File Builder + * + * Usage: supscan [ -v ] collection [ basedir ] + * supscan [ -v ] -f dirfile + * supscan [ -v ] -s + * -f "file" -- use dirfile instead of system coll.dir + * -s "system" -- perform scan for system supfile + * -v "verbose" -- print messages as you go + * collection -- name of the desired collection if not -s + * basedir -- name of the base directory, if not + * the default or recorded in coll.dir + * dirfile -- name of replacement for system coll.dir. + * + ********************************************************************** + * HISTORY + * $Log: supscan.c,v $ + * Revision 1.1 1995/12/16 11:47:01 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:19 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.14 92/08/11 12:08:30 mrt + * Picked up Brad's deliniting and variable argument changes + * [92/08/10 mrt] + * + * Revision 1.13 92/02/08 18:04:44 dlc + * Once again revised localhost(). Do not use gethostbyname() at + * all, but assume that the host names in the coll.host file are at + * least a prefix of the fully qualified name. Modcoll (and related + * scripts) will maintain this fact. + * [92/02/08 dlc] + * + * Revision 1.12 91/08/17 23:35:31 dlc + * Changes to localhost() function: + * - Use host name in kernel for local host name; assume it is + * fully qualified. + * - If gethostbyname() of host to see if we are the repository + * fails, with TRY_AGAIN or NO_RECOVERY, then use the "host" + * parameter. Print a diagnostic in this case. + * [91/08/17 dlc] + * + * Revision 1.11 90/04/04 10:53:01 dlc + * Changed localhost to retry getting the local host name 4 times with + * 30 second sleep intervals before aborting; after 4 tries, things are + * probably too messed up for the supscan to do anything useful + * [90/04/04 dlc] + * + * Revision 1.10 89/08/03 19:49:33 mja + * Updated to use v*printf() in place of _doprnt(). + * [89/04/19 mja] + * + * Revision 1.9 89/06/18 14:41:37 gm0w + * Fixed up some notify messages of errors to use "SUP:" prefix. + * [89/06/18 gm0w] + * + * 13-May-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed goaway to longjmp back to top-level to scan next + * collection. [V7.6] + * + * 19-Feb-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added -f <filename> switch to scan all (or part) of the + * collections in a file of collection/base-directory pairs. + * [V7.5] + * + * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Removed nameserver support (which means to use a new + * datafile). + * + * 09-Sep-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Use case-insensitive hostname comparison. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. [V6.4] + * + * 05-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Changed collection setup errors to be non-fatal. [V5.3] + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Moved most of the scanning code to scan.c. [V4.2] + * + * 02-Nov-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added "-s" option. + * + * 22-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Merged 4.1 and 4.2 versions together. + * + * 04-Jun-85 Steven Shafer (sas) at Carnegie-Mellon University + * Created for 4.2 BSD. + * + ********************************************************************** + */ + +#include <libc.h> +#include <c.h> +#include <netdb.h> +#include <setjmp.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <sys/time.h> +#include <sys/types.h> +#include "sup.h" + +#ifdef lint +/*VARARGS1*//*ARGSUSED*/ +static void quit(status) {}; +#endif /* lint */ + +#define PGMVERSION 6 + +/******************************************* + *** D A T A S T R U C T U R E S *** + *******************************************/ + +struct collstruct { /* one per collection to be upgraded */ + char *Cname; /* collection name */ + char *Cbase; /* local base directory */ + char *Cprefix; /* local collection pathname prefix */ + struct collstruct *Cnext; /* next collection */ +}; +typedef struct collstruct COLLECTION; + +/********************************************* + *** G L O B A L V A R I A B L E S *** + *********************************************/ + +int trace; /* -v flag */ + +COLLECTION *firstC; /* collection list pointer */ +char *collname; /* collection name */ +char *basedir; /* base directory name */ +char *prefix; /* collection pathname prefix */ +long lasttime = 0; /* time of last upgrade */ +long scantime; /* time of this scan */ +int newonly = FALSE; /* new files only */ +jmp_buf sjbuf; /* jump location for errors */ + +TREELIST *listTL; /* list of all files specified by <coll>.list */ +TREE *listT; /* final list of files in collection */ +TREE *refuseT = NULL; /* list of all files specified by <coll>.list */ + +long time (); + +/************************************* + *** M A I N R O U T I N E *** + *************************************/ + +main (argc,argv) +int argc; +char **argv; +{ + register COLLECTION *c; + + init (argc,argv); /* process arguments */ + for (c = firstC; c; c = c->Cnext) { + collname = c->Cname; + basedir = c->Cbase; + prefix = c->Cprefix; + (void) chdir (basedir); + scantime = time ((long *)NULL); + printf ("SUP Scan for %s starting at %s",collname, + ctime (&scantime)); + (void) fflush (stdout); + if (!setjmp (sjbuf)) { + makescanlists (); /* record names in scan files */ + scantime = time ((long *)NULL); + printf ("SUP Scan for %s completed at %s",collname, + ctime (&scantime)); + } else + printf ("SUP: Scan for %s aborted at %s",collname, + ctime (&scantime)); + (void) fflush (stdout); + } + while (c = firstC) { + firstC = firstC->Cnext; + free (c->Cname); + free (c->Cbase); + if (c->Cprefix) free (c->Cprefix); + free ((char *)c); + } + exit (0); +} + +/***************************************** + *** I N I T I A L I Z A T I O N *** + *****************************************/ + +usage () +{ + fprintf (stderr,"Usage: supscan [ -v ] collection [ basedir ]\n"); + fprintf (stderr," supscan [ -v ] -f dirfile\n"); + fprintf (stderr," supscan [ -v ] -s\n"); + exit (1); +} + +init (argc,argv) +int argc; +char **argv; +{ + char buf[STRINGLENGTH],fbuf[STRINGLENGTH],*p,*q; + FILE *f; + COLLECTION **c, *getcoll(); + int fflag,sflag; + char *filename; + + trace = FALSE; + fflag = FALSE; + sflag = FALSE; + while (argc > 1 && argv[1][0] == '-') { + switch (argv[1][1]) { + case 'f': + fflag = TRUE; + if (argc == 2) + usage (); + --argc; + argv++; + filename = argv[1]; + break; + case 'v': + trace = TRUE; + break; + case 's': + sflag = TRUE; + break; + default: + fprintf (stderr,"supscan: Invalid flag %s ignored\n",argv[1]); + (void) fflush (stderr); + } + --argc; + argv++; + } + if (!fflag) { + (void) sprintf (fbuf,FILEDIRS,DEFDIR); + filename = fbuf; + } + if (sflag) { + if (argc != 1) + usage (); + firstC = NULL; + c = &firstC; + (void) sprintf (buf,FILEHOSTS,DEFDIR); + if ((f = fopen (buf,"r")) == NULL) + quit (1,"supscan: Unable to open %s\n",buf); + while ((p = fgets (buf,STRINGLENGTH,f)) != NULL) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + collname = nxtarg (&p," \t="); + p = skipover (p," \t="); + if (!localhost (p)) continue; + *c = getcoll(filename,salloc (collname), + (char *)NULL); + if (*c) c = &((*c)->Cnext); + } + (void) fclose (f); + return; + } + if (argc < 2 && fflag) { + firstC = NULL; + c = &firstC; + if ((f = fopen (filename,"r")) == NULL) + quit (1,"supscan: Unable to open %s\n",filename); + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t="); + p = skipover (p," \t="); + *c = getcoll(filename,salloc (q),salloc (p)); + if (*c) c = &((*c)->Cnext); + } + (void) fclose (f); + return; + } + if (argc < 2 || argc > 3) + usage (); + firstC = getcoll(filename,salloc (argv[1]), + argc > 2 ? salloc (argv[2]) : (char *)NULL); +} + +COLLECTION * +getcoll(filename, collname, basedir) +register char *filename,*collname,*basedir; +{ + char buf[STRINGLENGTH],*p,*q; + FILE *f; + COLLECTION *c; + + if (basedir == NULL) { + if (f = fopen (filename,"r")) { + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t="); + if (strcmp (q,collname) == 0) { + p = skipover (p," \t="); + basedir = salloc (p); + break; + } + } + (void) fclose (f); + } + if (basedir == NULL) { + (void) sprintf (buf,FILEBASEDEFAULT,collname); + basedir = salloc (buf); + } + } + if (chdir(basedir) < 0) { + fprintf (stderr,"supscan: Can't chdir to base directory %s for %s\n", + basedir,collname); + return (NULL); + } + prefix = NULL; + (void) sprintf (buf,FILEPREFIX,collname); + if (f = fopen (buf,"r")) { + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + prefix = salloc (p); + if (chdir(prefix) < 0) { + fprintf (stderr,"supscan: can't chdir to %s from base directory %s for %s\n", + prefix,basedir,collname); + return (NULL); + } + break; + } + (void) fclose (f); + } + if ((c = (COLLECTION *) malloc (sizeof(COLLECTION))) == NULL) + quit (1,"supscan: can't malloc collection structure\n"); + c->Cname = collname; + c->Cbase = basedir; + c->Cprefix = prefix; + c->Cnext = NULL; + return (c); +} +#if __STDC__ +goaway (char *fmt,...) +#else +/*VARARGS*//*ARGSUSED*/ +goaway (va_alist) +va_dcl +#endif +{ +#if !__STDC__ + char *fmt; +#endif + va_list ap; + +#if __STDC__ + va_start(ap,fmt); +#else + va_start(ap); + fmt = va_arg(ap,char *); +#endif + + vfprintf(stderr, fmt, ap); + va_end(ap); + (void) putc ('\n',stderr); + (void) fflush (stderr); + longjmp (sjbuf,TRUE); +} + +int localhost (host) +register char *host; +{ + static char myhost[STRINGLENGTH]; + static int myhostlen; + register int hostlen; + + if (*myhost == '\0') { + /* + * We assume that the host name in the kernel is the + * fully qualified form. + */ + if (gethostname (myhost,sizeof (myhost)) < 0) { + quit (1,"supscan: can't get kernel host name\n"); + } + myhostlen = strlen(myhost); + } + + /* + * Here, we assume that the 'host' parameter from the + * coll.host file is at least a prefix of the fully qualified + * host name of some machine. This will be true when modcoll(8) + * (and related scripts) maintain the relevant files, but if + * a person makes a manual change, problems could result. In + * particular, if a nicname, such as "Y" for "GANDALF.CS.CMU.EDU" + * is present in the coll.host file, things will not work as + * expected. + */ + + hostlen = strlen(host); + + return(strncasecmp (myhost, + host, + hostlen < myhostlen ? hostlen : myhostlen) == 0); +} diff --git a/usr.bin/sup/src/supservers.8 b/usr.bin/sup/src/supservers.8 new file mode 100644 index 00000000000..53d2e9f8a85 --- /dev/null +++ b/usr.bin/sup/src/supservers.8 @@ -0,0 +1,241 @@ +.\" Copyright (c) 1992 Carnegie Mellon University +.\" All Rights Reserved. +.\" +.\" Permission to use, copy, modify and distribute this software and its +.\" documentation is hereby granted, provided that both the copyright +.\" notice and this permission notice appear in all copies of the +.\" software, derivative works or modified versions, and any portions +.\" thereof, and that both notices appear in supporting documentation. +.\" +.\" CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +.\" CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +.\" ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +.\" +.\" Carnegie Mellon requests users of this software to return to +.\" +.\" Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU +.\" School of Computer Science +.\" Carnegie Mellon University +.\" Pittsburgh PA 15213-3890 +.\" +.\" any improvements or extensions that they make and grant Carnegie Mellon +.\" the rights to redistribute these changes. +.\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +.\" HISTORY +.\" $Log: supservers.8,v $ +.\" Revision 1.1 1995/12/16 11:47:02 deraadt +.\" add sup to the tree +.\" +.\" Revision 1.1.1.1 1993/05/21 14:52:16 cgd +.\" initial import of CMU's SUP to NetBSD +.\" +.\" Revision 1.3 92/08/11 12:08:50 mrt +.\" Documented -C switch +.\" [92/08/11 mrt] +.\" +.TH SUPSERVERS 8 1/16/86 +.CM 1 +.SH "NAME" +supfilesrv, supscan \- sup server processes +.SH "SYNOPSIS" +supfilesrv +[ +.I +-l +] [ +.I +-q +] [ +.I +-N +] [ +.I +-P +] [ +.I -C MaxChildren +] +.br +supscan [ +.I +-v +] [ +.I +-s +] [ +.I +collection +] [ +.I +basedir +] +.SH "DESCRIPTION" +.I +Supfilesrv +is the server processes used to interact with +.I +sup +client processes via the IP/TCP network protocol. +This server +normally is expected to be running on server machines at all times. +Each machine with files of interest to users on other machines is +expected to be a file server and should run +.I +supfilesrv. + +A file server machine will service requests for both "private" and +"system" file collections. +No special action is necessary to support +private collections, as the client user is expected to supply all +necessary information. +For system collections, if the base directory +is not the default (see FILES below), an entry must be put into +the directory list file; this entry is a single text line containing +the name of the collection, one or more spaces, and the name of the +base directory for that collection. + +Each collection should have +an entry in the host list file; this entry is a single text line +containing the name of the collection, one or more spaces, and +the name of the host machine acting as file server for that collection. + +Details of setting up a file collection for the file server are +described in the manual entry for +.I +sup(1). + +.I +Supfilesrv +generally runs as a network server process that listens for connections, +and for each connection (double-)forks a process to handle the interaction +with the client. +However, with the -l flag, no forking will take place: +the server will listen for a network connection, handle it, and exit. +This is useful for debugging the servers in "live" mode rather than as +daemons. + +For debugging purposes, the -P "debugging ports" flag can be used. +It will cause the selection of an alternate, non-privileged set of +TCP ports instead of the usual ports, which are reserved for the +active server processes. The -N "network debugging" flag can be used +to produce voluminous messages describing the network communication +progress and status. The more -N switches that you use the more output +you get. Use 3 (separated by spaces: -N -N -N) to get a complete record +of all network messages. Log messages are printed by +.I syslog +on +.I daemon.log . +To suppress +log messages, the -q "quiet" flag can be used. + + +Normally the +.I supfilesrv +will only respond to 3 requests simultaneously, forking a child +process for each client. If it gets additional requests it will respond +with the error FSSETUPBUSY. The -C MaxChildren switch can be used +to increase (or decrease) this number. + +.SH "SUPSCAN" +It is possible to pre-compile a list of the files in a collection +to make +.I +supfilesrv +service that collection much faster. This can be done by running +.I +supscan +on the desired collection on the repository machine. This produces a +list of all the files in the collection at the time of the +.I +supscan; +subsequent upgrades will be based on this list of files rather than +actually scanning the disk at the time of the upgrade. Of course, +the upgrade will consequently bring the client machine up to the status +of the repository machine as of the time of the +.I +supscan +rather than as of the time of the upgrade; hence, if +.I +supscan +is used, it should be run periodically on the +collection. +This facility is useful for extremely large file collections +that are upgraded many times per day, such as the CMU UNIX system +software. The "verbose" flag +.I +-v +will cause +.I +supscan +to produce output messages as it scans the files in the collection. +The "system" flag +.I +-s +will cause +.I +supscan +to scan all system collections residing on the current host. +The +.I +basedir +parameter must be specified if the collection is a private +collection whose base directory is not the default. +.SH "FILES" +.TP +/usr +default base directory for a collection +.TP +/usr/cs/lib/supfiles/coll.dir +directory list file for file server +.TP +/usr/cs/lib/supfiles/coll.host +host list file for system sups. +.TP +<base-directory>/sup/<collection>/* +files used by file server (see +.I +sup(1)) +.TP +<base-directory>/sup/<collection>/list +list file used by +.I +supscan +to create file list +.TP +<base-directory>/sup/<collection>/scan +file list created by +.I +supscan +from list file +.i0 +.DT +.PP +.SH "SEE ALSO" +sup(1) +.br +.I +The SUP Software Upgrade Protocol, +S. +A. +Shafer, CMU Computer Science Dept., 1985. +.SH "DIAGNOSTICS" +The file server places log messages on the +standard and diagnostic output files. +The process name and process +id number generally accompany each message for diagnostic purposes. +.SH "HISTORY" +.TP +31-July-92 Mary Thompson (mrt) at Carnegie Mellon University +Removed references to supnameserver which has not existed for +a long time. Update a few file names. Added -C switch. +.TP +21-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University +Updated documentation for 4.3; changed /usr/cmu to /usr/cs. +.TP +15-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University +Updated documentation; -s switch to supscan. +.TP +23-May-85 Steven Shafer (sas) at Carnegie-Mellon University +Supscan created and documented; also -N flag. +.TP +04-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University +Created. diff --git a/usr.bin/sup/src/sysent.h b/usr.bin/sup/src/sysent.h new file mode 100644 index 00000000000..d513ea6c2f9 --- /dev/null +++ b/usr.bin/sup/src/sysent.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + ********************************************************************** + * HISTORY + * $Log: sysent.h,v $ + * Revision 1.1 1995/12/16 11:47:02 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:19 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 2.4 89/12/05 16:02:00 mrt + * Removed include of sys/features.h as it is no longer + * exported or needed. + * [89/12/05 mrt] + * + * Revision 2.3 89/01/20 15:44:24 gm0w + * Added externs to the non-STDC case for functions that do not + * have int return values. + * [88/12/17 gm0w] + * + * Revision 2.2 88/12/14 23:35:52 mja + * Created. + * [88/01/06 jjk] + * + ********************************************************************** + */ + +#ifndef _SYSENT_H_ +#define _SYSENT_H_ 1 + +#if defined(__STDC__) +#if 0 +#include <sys/types.h> +#include <sys/time.h> +extern int access(const char *, int); +extern int acct(const char *); +extern int brk(void *); +extern int sbrk(int); +extern int chdir(const char *); +extern int chmod(const char *, int); +extern int fchmod(int, int); +extern int chown(const char *, int, int); +extern int fchown(int, int, int); +extern int chroot(const char *); +extern int close(int); +extern int creat(const char *, int); +extern int dup(int); +extern int dup2(int, int); +extern int execve(const char *, const char **, const char **); +extern void _exit(int); +extern int fcntl(int, int, int); +extern int flock(int, int); +extern int fork(void); +extern int fsync(int); +extern int getdtablesize(void); +extern gid_t getgid(void); +extern gid_t getegid(void); +extern int getgroups(int, int *); +extern long gethostid(void); +extern int sethostid(long); +extern int gethostname(char *, int); +extern int sethostname(const char *, int); +extern int getpagesize(void); +extern int getpgrp(int); +extern int getpid(void); +extern int getppid(void); +extern uid_t getuid(void); +extern uid_t geteuid(void); +extern int ioctl(int, unsigned long, void *); +extern int kill(int, int); +extern int killpg(int, int); +extern int link(const char *, const char *); +extern off_t lseek(int, off_t, int); +extern int mkdir(const char *, int); +extern int mknod(const char *, int, int); +extern int mount(const char *, const char *, int); +extern int umount(const char *); +extern int open(const char *, int, int); +extern int pipe(int *); +extern int profil(void *, int, int, int); +extern int ptrace(int, int, int *, int); +extern int quota(int, int, int, void *); +extern int read(int, void *, int); +extern int readlink(const char *, void *, int); +extern int reboot(int); +extern int rename(const char *, const char *); +extern int rmdir(const char *); +extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +extern int setgroups(int, int *); +extern int setpgrp(int, int); +extern int setquota(const char *, const char *); +extern int setregid(gid_t, gid_t); +extern int setreuid(uid_t, uid_t); +extern int swapon(const char *); +extern int symlink(const char *, const char *); +extern void sync(void); +extern int syscall(int, ...); +extern int truncate(const char *, off_t); +extern int ftruncate(int, off_t); +extern int umask(int); +extern int unlink(const char *); +extern int vfork(void); +extern void vhangup(void); +extern int write(int, void *, int); + +#ifndef _VICEIOCTL +#include <sys/viceioctl.h> +#endif /* not _VICEIOCTL */ +extern int icreate(int, int, int, int, int, int); +extern int iinc(int, int, long); +extern int idec(int, int, long); +extern int iopen(int, int, int); +extern int iread(int, int, int, int, void *, int); +extern int iwrite(int, int, int, int, void *, int); +extern int pioctl(const char *, unsigned long, struct ViceIoctl *, int); +extern int setpag(void); +#endif +#else defined(__STDC__) +extern gid_t getgid(); +extern gid_t getegid(); +extern long gethostid(); +extern uid_t getuid(); +extern uid_t geteuid(); +extern off_t lseek(); +#endif /* __STDC__ */ +#endif /* not _SYSENT_H_ */ diff --git a/usr.bin/sup/src/time.h b/usr.bin/sup/src/time.h new file mode 100644 index 00000000000..0b4ea542613 --- /dev/null +++ b/usr.bin/sup/src/time.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)time.h 5.6 (Berkeley) 6/23/90 + */ +/* + * HISTORY + * 20-Sep-90 Mary Thompson (mrt) at Carnegie-Mellon University + * Taken from 4.3-reno-source to get the new copyright, but + * removed the features that Mach is not supporting yet. + * + */ + +#ifndef _TIME_H_ +#define _TIME_H_ 1 + +struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Savings Time flag */ + long tm_gmtoff; /* offset from CUT in seconds */ + char *tm_zone; /* timezone abbreviation */ +}; + +#if __STDC__ || c_plusplus +extern struct tm *gmtime(const time_t *); +extern struct tm *localtime(const time_t *); +extern time_t mktime(const struct tm *); +extern time_t time(time_t *); +extern double difftime(const time_t, const time_t); +extern char *asctime(const struct tm *); +extern char *ctime(const time_t *); +extern char *timezone(int , int); +extern void tzset(void); +extern void tzsetwall(void); +#else +extern struct tm *gmtime(); +extern struct tm *localtime(); +extern time_t mktime(); +extern time_t time(); +extern double difftime(); +extern char *asctime(); +extern char *ctime(); +extern char *timezone(); +extern void tzset(); +extern void tzsetwall(); +#endif + +#endif /* _TIME_H */ diff --git a/usr.bin/sup/src/vprintf.c b/usr.bin/sup/src/vprintf.c new file mode 100644 index 00000000000..01280c21e94 --- /dev/null +++ b/usr.bin/sup/src/vprintf.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the rights + * to redistribute these changes. + */ +/* + * varargs versions of printf routines + * + ********************************************************************** + * HISTORY + * $Log: vprintf.c,v $ + * Revision 1.1 1995/12/16 11:47:03 deraadt + * add sup to the tree + * + * Revision 1.1.1.1 1993/05/21 14:52:19 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 2.5 89/09/08 18:15:55 mbj + * Use _doprnt() for the Multimax (an "old" architecture). + * [89/09/08 mbj] + * + * Revision 2.4 89/08/03 14:40:10 mja + * Add vsnprintf() routine. + * [89/07/12 mja] + * + * Terminate vsprintf() string with null byte. + * [89/04/21 mja] + * + * Change to use new hidden name for _doprnt on MIPS. + * [89/04/18 mja] + * + * Revision 2.3 89/06/10 14:13:43 gm0w + * Added putc of NULL byte to vsprintf. + * [89/06/10 gm0w] + * + * Revision 2.2 88/12/13 13:53:17 gm0w + * From Brad White. + * [88/12/13 gm0w] + ************************************************************ + */ + +#include <stdio.h> +#include <varargs.h> + +#ifdef DOPRINT_VA +/* + * system provides _doprnt_va routine + */ +#define _doprnt _doprnt_va +#else +/* + * system provides _doprnt routine + */ +#define _doprnt_va _doprnt +#endif + + +#ifdef NEED_VPRINTF +int +vprintf(fmt, args) + char *fmt; + va_list args; +{ + _doprnt(fmt, args, stdout); + return (ferror(stdout) ? EOF : 0); +} + +int +vfprintf(f, fmt, args) + FILE *f; + char *fmt; + va_list args; +{ + _doprnt(fmt, args, f); + return (ferror(f) ? EOF : 0); +} + +int +vsprintf(s, fmt, args) + char *s, *fmt; + va_list args; +{ + FILE fakebuf; + + fakebuf._flag = _IOSTRG+_IOWRT; /* no _IOWRT: avoid stdio bug */ + fakebuf._ptr = s; + fakebuf._cnt = 32767; + _doprnt(fmt, args, &fakebuf); + putc('\0', &fakebuf); + return (strlen(s)); +} +#endif /* NEED_VPRINTF */ + +#if defined(NEED_VSNPRINTF) || defined(NEED_VPRINTF) +int +vsnprintf(s, n, fmt, args) + char *s, *fmt; + va_list args; +{ + FILE fakebuf; + + fakebuf._flag = _IOSTRG+_IOWRT; /* no _IOWRT: avoid stdio bug */ + fakebuf._ptr = s; + fakebuf._cnt = n-1; + _doprnt(fmt, args, &fakebuf); + fakebuf._cnt++; + putc('\0', &fakebuf); + if (fakebuf._cnt<0) + fakebuf._cnt = 0; + return (n-fakebuf._cnt-1); +} +#endif /* NEED_VPRINTF || NEED_VSNPRINTF */ diff --git a/usr.bin/sup/sup/Makefile b/usr.bin/sup/sup/Makefile new file mode 100644 index 00000000000..e200b5be8c3 --- /dev/null +++ b/usr.bin/sup/sup/Makefile @@ -0,0 +1,19 @@ +# $Id: Makefile,v 1.1 1995/12/16 11:47:05 deraadt Exp $ + +.PATH: ${.CURDIR}/../src + +PROG= sup +MAN= sup.1 +SRCS= supcmain.o supcvers.o supcparse.o supcname.o supcmisc.o supcmeat.o \ + scm.o scmio.o stree.o log.o supmsg.o \ + atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \ + path.o quit.o run.o salloc.o skipto.o vprintf.o netcryptvoid.c +LDADDR+=-lutil +DPADD+= ${LIBUTIL} +BINOWN= root +BINGRP= daemon +BINMODE=555 +BINDIR= /usr/bin +CFLAGS+=-I${.CURDIR}/../src + +.include <bsd.prog.mk> diff --git a/usr.bin/sup/supfilesrv/Makefile b/usr.bin/sup/supfilesrv/Makefile new file mode 100644 index 00000000000..787b17daba5 --- /dev/null +++ b/usr.bin/sup/supfilesrv/Makefile @@ -0,0 +1,18 @@ +# $Id: Makefile,v 1.1 1995/12/16 11:47:06 deraadt Exp $ + +.PATH: ${.CURDIR}/../src + +PROG= supfilesrv +MAN= supservers.8 +SRCS= supfilesrv.o scan.o scm.o scmio.o stree.o log.o supmsg.o \ + atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \ + path.o quit.o run.o salloc.o skipto.o vprintf.o netcryptvoid.c +LDADD+= -lutil -lcrypt +DPADD+= ${LIBUTIL} +BINOWN= root +BINGRP= daemon +BINMODE=555 +BINDIR= /usr/bin +CFLAGS+=-I${.CURDIR}/../src + +.include <bsd.prog.mk> diff --git a/usr.bin/sup/supscan/Makefile b/usr.bin/sup/supscan/Makefile new file mode 100644 index 00000000000..c4fcff11332 --- /dev/null +++ b/usr.bin/sup/supscan/Makefile @@ -0,0 +1,18 @@ +# $Id: Makefile,v 1.1 1995/12/16 11:47:07 deraadt Exp $ + +.PATH: ${.CURDIR}/../src + +PROG= supscan +NOMAN= +SRCS= supscan.o stree.o scan.o \ + atoo.o errmsg.o expand.o ffilecopy.o filecopy.o nxtarg.o \ + path.o quit.o run.o salloc.o skipto.o vprintf.o netcryptvoid.c +LDADD+= -lutil +DPADD+= ${LIBUTIL} +BINOWN= root +BINGRP= daemon +BINMODE=555 +BINDIR= /usr/bin +CFLAGS+=-I${.CURDIR}/../src + +.include <bsd.prog.mk> |