sup-20100519/0000755000000000000000000000000011375014734011267 5ustar rootrootsup-20100519/sys/0000755000000000000000000000000011375014734012105 5ustar rootrootsup-20100519/sys/viceioctl.h0000644000000000000000000000474607513101313014237 0ustar rootroot/* $NetBSD: viceioctl.h,v 1.4 2002/07/10 18:54:03 wiz Exp $ */ /* * Copyright (c) 1991 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the rights * to redistribute these changes. */ /* * Mach Operating System * Copyright (c) 1989 Carnegie-Mellon University * Copyright (c) 1988 Carnegie-Mellon University * Copyright (c) 1987 Carnegie-Mellon University * All rights reserved. The CMU software License Agreement specifies * the terms and conditions for use and redistribution. */ /* * Revision 2.4 90/08/30 11:51:12 bohman */ /* * ITC Remote file system - vice ioctl interface module */ /* * TODO: Find /usr/local/include/viceioctl.h. */ #ifndef _SYS_VICEIOCTL_H_ #define _SYS_VICEIOCTL_H_ #include #include struct ViceIoctl { caddr_t in, out; /* Data to be transferred in, or out */ short in_size; /* Size of input buffer <= 2K */ short out_size; /* Maximum size of output buffer, <= 2K */ }; /* The 2K limits above are a consequence of the size of the kernel buffer used to buffer requests from the user to venus--2*MAXPATHLEN. The buffer pointers may be null, or the counts may be 0 if there are no input or output parameters */ #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl)) /* Use this macro to define up to 256 vice ioctl's. These ioctl's all potentially have in/out parameters--this depends upon the values in the ViceIoctl structure. This structure is itself passed into the kernel by the normal ioctl parameter passing mechanism. */ #define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && com <= _VICEIOCTL(255)) #endif /* _SYS_VICEIOCTL_H_ */ sup-20100519/Makefile0000644000000000000000000001326111133656336012734 0ustar rootroot# $NetBSD: Makefile,v 1.32 2009/01/15 15:57:18 christos Exp $ # 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 and libc.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. # # If building on non 4.4BSD systems, you'll need the vis(3) and the daemon(3) # functions from libc and libutil #SITE = SUNOS #SITE = SOLARIS #SITE = NETBSD #SITE = FREEBSD #SITE = CMUCS SITE1 != uname -s | tr '[a-z]' '[A-Z]' \ | sed -e s/_.*//g SITE2 = $(shell uname -s | tr '[a-z]' '[A-Z]' \ | sed -e s/_.*//g) SITE = ${SITE1}${SITE2} TARDIR = sup-0.3 LINUX_DEFINES = -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR \ -DNEED_SETPROCTITLE NETBSD_DEFINES = -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR \ -DHAS_FPARSELN -DHAS_FGETLN -DHAS_VIS FREEBSD_DEFINES = -UMACH -DVAR_TMP -DHAS_DAEMON -DHAS_POSIX_DIR \ -DHAS_FPARSELN -DHAS_FGETLN -DHAS_VIS SOLARIS_DEFINES = -UMACH -DVAR_TMP -DHAS_POSIX_DIR -DNEED_VSNPRINTF AFS_DEFINES = -DAFS -I/usr/afsws/include OSF_DEFINES = -UMACH -DOSF -D_BSD -noshrlib -g -DNEED_VSNPRINTF \ -DVAR_TMP SUNOS_DEFINES = -UMACH -D_BSD -DNEED_VSNPRINTF -DVAR_TMP \ -DHAS_POSIX_DIR -DHAS_DAEMON -DNEED_DAEMON CYGWIN_DEFINES = -UMACH -DVAR_TMP -DHAS_POSIX_DIR CMUCS_DEFINES = -DMACH -DDOPRINT_VA -DNEED_VPRINTF NON_MACH_DEFINES = -UMACH #INSTALLATION PARAMETERS PREFIX ?= /usr/pkg/ NETBSD_BINDIR = ${PREFIX}/sbin NETBSD_MAN1 = ${PREFIX}/man/man1 NETBSD_MAN8 = ${PREFIX}/man/man8 CFLAGS = ${DEFS} -O -I. -g 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 expand.o ffilecopy.o filecopy.o \ nxtarg.o path.o quit.o read_line.o run.o estrdup.o \ skipto.o vprintf.o setproctitle.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 NETBSD_LIBS = -lcrypt FREEBSD_LIBS = -lcrypt DRAGONFLY_LIBS = -lcrypt LINUX_LIBS = -lcrypt CYGWIN_LIBS = -lcrypt CMUCS_LIBS = -lsys OSF_LIBS = -lbsd EXTRALIBS = 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 SOLARIS_LIBS = -lsocket -lnsl SUNOS_LIBS = DEFS = -UCMUCS -UCMU ${${SITE}_DEFINES} #DEFS += -DDEFDIR=\"${PREFIX}/libdata/sup\" #DEFS += -DEE_XXX -DDEFSCAN=\"/var/\" -DDEFUSER=\"nobody\" LIBS = ${EXTRALIBS} all: ${PROGRAMS} sup: ${sup_OFILES} ${LIBS} ${CC} ${CFLAGS} -o sup ${sup_OFILES} ${LIBS} ${${SITE}_LIBS} supfilesrv: ${supfilesrv_OFILES} ${supfilesrv_LIBS} ${CC} ${CFLAGS} -o supfilesrv ${supfilesrv_OFILES} ${supfilesrv_LIBS} ${LIBS} ${${SITE}_LIBS} supscan: ${supscan_OFILES} ${LIBS} ${CC} ${CFLAGS} -o supscan ${supscan_OFILES} ${LIBS} ${${SITE}_LIBS} libextra.a: ${EXTRA} ar r libextra.a $? ranlib libextra.a clean cleandir distclean: 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: @echo "[ Using netcryptvoid.c ]" cp netcryptvoid.c netcrypt.c tar: mkdir ${TARDIR} ${TARDIR}/sys cp -p *.[ch18] Makefile ${TARDIR} cp -p sys/*.h ${TARDIR}/sys tar -czf ${TARDIR}.tar.gz ${TARDIR} rm -fr ${TARDIR} read_line.o: supextern.h 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 sup-20100519/atoo.c0000644000000000000000000000314607513123662012401 0ustar rootroot/* $NetBSD: atoo.c,v 1.5 2002/07/10 21:31:30 wiz Exp $ */ /* * 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 * * Usage: 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. * */ #include "supcdefs.h" #include "supextern.h" unsigned int atoo(char *ap) { unsigned int n; char *p; p = ap; n = 0; while (*p == ' ' || *p == ' ') p++; while (*p >= '0' && *p <= '7') n = n * 8 + *p++ - '0'; return (n); } sup-20100519/c.h0000644000000000000000000000515511217213135011657 0ustar rootroot/* $NetBSD: c.h,v 1.7 2009/06/20 17:03:25 christos Exp $ */ /* * 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_ #include #include #ifndef FALSE #define FALSE 0 #endif /* FALSE */ #ifndef TRUE #define TRUE 1 #endif /* TRUE */ #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif #ifdef __arraycount #define sizeofA(array) __arraycount(array) #else #define sizeofA(array) (sizeof(array)/sizeof(array[0])) #endif #ifndef __unused #ifndef __GNUC__ #define __unused #else #define __unused __attribute__((__unused__)) #endif #endif #endif /* _C_INCLUDE_ */ sup-20100519/cvt.c0000644000000000000000000000154307513101305012220 0ustar rootroot/* $NetBSD: cvt.c,v 1.3 2002/07/10 18:53:57 wiz Exp $ */ /* * Quick hack to convert old binary sup when.collection files into * the new ascii format. */ #include #include #include #include int main(int argc, char **argv) { long b; FILE *fp; int fd; if (argc != 2) { (void) fprintf(stderr, "Usage: %s \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; } sup-20100519/estrdup.c0000644000000000000000000000315710413625544013126 0ustar rootroot/* $NetBSD: estrdup.c,v 1.1 2006/04/02 01:39:48 christos Exp $ */ /* * 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. * ********************************************************************** */ #include "supcdefs.h" #include "supextern.h" char * estrdup(const char *p) { char *q; if ((q = strdup(p)) == NULL) goaway("Cannot allocate memory"); return q; } sup-20100519/expand.c0000644000000000000000000002041611266442205012712 0ustar rootroot/* $NetBSD: expand.c,v 1.18 2009/10/17 22:26:13 christos Exp $ */ /* * 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 #include #ifdef HAS_POSIX_DIR #include #else #include #endif #include #include #include "libc.h" #include #include #include static jmp_buf sjbuf; static char pathbuf[MAXPATHLEN]; static char *path, *pathp, *lastpathp; static const 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 */ #define fixit(a) (a[0] ? a : ".") int expand(char *, char **, int); static void glob(char *); static void matchdir(char *); static int execbrc(char *, char *); static int match(char *, char *); static int amatch(char *, char *); static void addone(char *, const char *); static int addpath(char); static int gethdir(char *, size_t); int expand(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(char *as) { char *cs; char *spathp, *oldcs; struct stat stb; spathp = pathp; cs = as; if (*cs == '~' && pathp == path) { if (addpath('~')) goto endit; for (cs++; isalnum((unsigned char)*cs) || *cs == '_' || *cs == '-';) if (addpath(*cs++)) goto endit; if (!*cs || *cs == '/') { if (pathp != path + 1) { *pathp = 0; if (gethdir(path + 1, sizeof path - 1)) goto endit; strncpy(path, path + 1, sizeof path - 1); } else strncpy(path, (char *) getenv("HOME"), sizeof path - 1); path[sizeof path - 1] = '\0'; pathp = path + strlen(path); } } while (*cs == 0 || strchr(globchars, *cs) == 0) { if (*cs == 0) { if (lstat(fixit(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(fixit(path), &stb) >= 0 && S_ISDIR(stb.st_mode)) matchdir(cs); endit: pathp = spathp; *pathp = 0; return; } static void matchdir(char *pattern) { #ifdef HAS_POSIX_DIR struct dirent *dp; #else struct direct *dp; #endif DIR *dirp; dirp = opendir(fixit(path)); if (dirp == NULL) return; while ((dp = readdir(dirp)) != NULL) { #if defined(HAS_POSIX_DIR) && !defined(__SVR4) && !defined(__CYGWIN__) 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(char *p, char *s) { char restbuf[MAXPATHLEN + 1]; 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; snprintf(lm, sizeof(restbuf) - (lm - restbuf), "%s%s", pl, 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(char *s, char *p) { int c; char *sentp; if (*s == '.' && *p != '.') return (0); sentp = entp; entp = s; c = amatch(s, p); entp = sentp; return (c); } static int amatch(char *s, char *p) { 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++) != 0) { 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(fixit(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(char *s1, const char *s2) { char *ep; if (bufcnt >= BUFSIZE) { bufcnt = BUFSIZE + 1; longjmp(sjbuf, 1); } ep = malloc(strlen(s1) + strlen(s2) + 1); if (ep == 0) { bufcnt = -1; longjmp(sjbuf, 1); } BUFFER[bufcnt++] = ep; while (*s1) *ep++ = *s1++; while ((*ep++ = *s2++) != '\0') continue; } static int addpath(char c) { if (pathp >= lastpathp) return (1); *pathp++ = c; *pathp = 0; return (0); } static int gethdir(char *home, size_t homelen) { struct passwd *pp = getpwnam(home); if (pp == 0) return (1); strncpy(home, pp->pw_dir, homelen - 1); home[homelen - 1] = '\0'; return (0); } sup-20100519/ffilecopy.c0000644000000000000000000000664111266631412013417 0ustar rootroot/* $NetBSD: ffilecopy.c,v 1.11 2009/10/18 15:23:54 christos Exp $ */ /* * Copyright (c) 1991 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the rights * to redistribute these changes. */ #include #include "supcdefs.h" #include "supextern.h" /* * Define two macros for fast file copying * * FBUF_HACK: this will copy data directly between the * underlying OSs FILE buffers * * FFLAG_HACK: this will set necessary OS FILE flags * after we've hacked the buffers up */ #if defined(__SEOF) # define FBUF_HACK(here,there) \ do { \ if ((here)->_r > 0) { \ i = write(therefile, (here)->_p, (size_t)(here)->_r); \ if (i != (here)->_r) \ return EOF; \ (here)->_p = (here)->_bf._base; \ (here)->_r = 0; \ } \ } while (/*CONSTCOND*/0) # define FFLAG_HACK(file) (file)->_flags |= __SEOF #elif defined(_IOEOF) # define FBUF_HACK(here, there) \ do { \ if ((here)->_cnt > 0) { \ i = write(therefile, (here)->_ptr, (here)->_cnt ); \ if (i != (here)->_cnt) \ return EOF; \ (here)->_ptr = (here)->_base; \ (here)->_cnt = 0; \ } \ } while (/*CONSTCOND*/0) # define FFLAG_HACK(file) (file)->_flag |= _IOEOF; #else # define FBUF_HACK(here, there) /* Nada */ # define FFLAG_HACK(here) (void)fseeko(here, (off_t)0, SEEK_END); #endif /* 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. * */ ssize_t ffilecopy(FILE * here, FILE * there) { int i, herefile, therefile; herefile = fileno(here); therefile = fileno(there); if (fflush(there) == EOF) /* flush pending output */ return EOF; /* if we know any buffer tricks, do them now */ FBUF_HACK(here,there); /* copy the rest of the file directly (avoiding FILE buffers) */ i = filecopy(herefile, therefile); /* fast file copy */ if (i < 0) return EOF; /* ensure we are at the end of the file */ FFLAG_HACK(here); return 0; } sup-20100519/filecopy.c0000644000000000000000000000511111266442205013240 0ustar rootroot/* $NetBSD: filecopy.c,v 1.5 2009/10/17 22:26:13 christos Exp $ */ /* * 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 #include "supcdefs.h" #include "supextern.h" ssize_t filecopy(int here, int there) { ssize_t kount; char buffer[BUFFERSIZE]; kount = 0; while (kount == 0 && (kount = read(here, buffer, BUFFERSIZE)) > 0) kount -= write(there, buffer, (size_t)kount); return (kount ? -1 : 0); } sup-20100519/libc.h0000644000000000000000000001264111133656462012357 0ustar rootroot/* $NetBSD: libc.h,v 1.8 2009/01/15 15:58:42 christos Exp $ */ /* * 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 * 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 estrdup() extern. * * 14-Aug-81 Mike Accetta (mja) at Carnegie-Mellon University * Created. * ********************************************************************** */ #ifndef _LIBC_H_ #define _LIBC_H_ 1 #ifndef _TYPES_ #include #endif /* _TYPES_ */ #ifndef FILE #include #endif /* FILE */ #ifndef _STRINGS_H_ #include #endif /* _STRINGS_H_ */ #ifndef _STRING_H_ #include #endif /* _STRINGS_H_ */ #ifndef _TIME_H_ #include #endif /* _TIME_H_ */ /* CMU stdio additions */ 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); /* CMU string routines */ extern char* foldup(char*, const char*); extern char* folddown(char*, const char*); extern char* sindex(const 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 atoh(const char*); extern char *concat(const char*, int, ...); /* CMU library routines */ extern char *getname(int); extern char *pathof(char *); /* CMU time additions */ extern long gtime(const struct tm*); extern long atot(const char*); /* 4.3 BSD standard library routines; taken from man(3) */ #if defined(c_plusplus) typedef int (*PFI2)(...); #endif /* c_plusplus */ #endif /* not _LIBC_H_ */ sup-20100519/log.c0000644000000000000000000000735211266065001012213 0ustar rootroot/* $NetBSD: log.c,v 1.10 2009/10/16 12:41:37 christos Exp $ */ /* * 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 * 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 #include #include "supcdefs.h" #include "supextern.h" #include "c.h" static int opened = 0; void logopen(char *program) { if (opened) return; openlog(program, LOG_PID, LOG_DAEMON); opened++; } void logquit(int retval, const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (opened) { syslog(LOG_ERR, "%s", buf); closelog(); exit(retval); } quit(retval, "SUP: %s\n", buf); } void logerr(const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (opened) { syslog(LOG_ERR, "%s", buf); return; } fprintf(stderr, "SUP: %s\n", buf); (void) fflush(stderr); } void loginfo(const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (opened) { syslog(LOG_INFO, "%s", buf); return; } printf("%s\n", buf); (void) fflush(stdout); } #ifdef LIBWRAP #include #ifndef LIBWRAP_ALLOW_FACILITY #define LIBWRAP_ALLOW_FACILITY LOG_AUTH #endif #ifndef LIBWRAP_ALLOW_SEVERITY #define LIBWRAP_ALLOW_SEVERITY LOG_INFO #endif #ifndef LIBWRAP_DENY_FACILITY #define LIBWRAP_DENY_FACILITY LOG_AUTH #endif #ifndef LIBWRAP_DENY_SEVERITY #define LIBWRAP_DENY_SEVERITY LOG_WARNING #endif int allow_severity = LIBWRAP_ALLOW_FACILITY | LIBWRAP_ALLOW_SEVERITY; int deny_severity = LIBWRAP_DENY_FACILITY | LIBWRAP_DENY_SEVERITY; void logdeny(const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (opened) { syslog(deny_severity, "%s", buf); return; } printf("%s\n", buf); (void) fflush(stdout); } void logallow(const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (opened) { syslog(allow_severity, "%s", buf); return; } printf("%s\n", buf); (void) fflush(stdout); } #endif /* LIBWRAP */ sup-20100519/netcryptvoid.c0000644000000000000000000000445111266442205014166 0ustar rootroot/* $NetBSD: netcryptvoid.c,v 1.10 2009/10/17 22:26:13 christos Exp $ */ /* * 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 * 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 "supcdefs.h" #include "supextern.h" #include "supmsg.h" /********************************************* *** G L O B A L V A R I A B L E S *** *********************************************/ int cryptflag; /* whether to encrypt/decrypt data */ char *cryptbuf; /* buffer for data encryption/decryption */ int netcrypt(char *pword) { if (pword == NULL || (strcmp(pword, PSWDCRYPT) == 0)) { cryptflag = 0; (void) getcryptbuf(0); return (SCMOK); } return (SCMERR); } int /*ARGSUSED*/ getcryptbuf(int x __unused) { if (cryptflag == 0) { return (SCMOK); } else return (SCMERR); } void /*ARGSUSED*/ decode(char *in __unused, char *out __unused, int count __unused) { } void /*ARGSUSED*/ encode(char *in __unused, char *out __unused, int count __unused) { } sup-20100519/nxtarg.c0000644000000000000000000000527411266065001012736 0ustar rootroot/* $NetBSD: nxtarg.c,v 1.6 2009/10/16 12:41:37 christos Exp $ */ /* * 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,sep); * char *p,*q,*sep; * 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 "sep". * 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 "sep" 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. */ #include "supcdefs.h" #include "supextern.h" char _argbreak; char * nxtarg(char **q, const char *sep) { char *front, *back; front = *q; /* start of string */ /* leading blanks and tabs */ while (*front && (*front == ' ' || *front == '\t')) front++; /* find break character at end */ if (sep == 0) sep = " "; back = skipto(front, sep); _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); } sup-20100519/path.c0000644000000000000000000000661607513113335012374 0ustar rootroot/* $NetBSD: path.c,v 1.4 2002/07/10 20:19:41 wiz Exp $ */ /* * 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. * */ #include "supcdefs.h" #include "supextern.h" void path(char *original, char *direc, char *file) { char *y; /* x is direc */ char *p; /* copy and note the end */ p = original; y = direc; while ((*y++ = *p++) != '\0'); /* 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 */ } sup-20100519/quit.c0000644000000000000000000000354611266065001012415 0ustar rootroot/* $NetBSD: quit.c,v 1.6 2009/10/16 12:41:37 christos Exp $ */ /* * 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 * Revision 1.2 88/12/13 13:52:41 gm0w * Rewritten to use varargs. * [88/12/13 gm0w] * ********************************************************************** */ #include #include "supcdefs.h" #include "supextern.h" void quit(int status, const char *fmt, ...) { va_list args; va_start(args, fmt); fflush(stdout); (void) vfprintf(stderr, fmt, args); va_end(args); exit(status); } sup-20100519/read_line.c0000644000000000000000000000657511267447565013406 0ustar rootroot/* $NetBSD: read_line.c,v 1.9 2009/10/21 00:01:57 snj Exp $ */ /* * Copyright (c) 1994 Mats O Jansson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #if defined(lint) && defined(__RCSID) __RCSID("$NetBSD: read_line.c,v 1.9 2009/10/21 00:01:57 snj Exp $"); #endif #include #include #include #include #include #include "supcdefs.h" #include "supextern.h" /* read_line(): * Read a line from a file, parsing continuations ending in \ * and eliminating trailing newlines. * Returns a pointer to an internal buffer that is reused upon * next invocation. * * NOTE: if HAS_FPARSELN is not defined, delim and flags are currently unused. */ char * read_line(FILE * fp, size_t * size, size_t * lineno, const char *delim, int flags) { static char *buf; #ifdef HAS_FPARSELN if (buf != NULL) free(buf); return (buf = fparseln(fp, size, lineno, delim, flags)); #else char *n; #ifndef HAS_FGETLN char sbuf[1024]; #endif static int buflen; size_t s, len; char *ptr; int cnt; len = 0; cnt = 1; while (cnt) { if (lineno != NULL) (*lineno)++; #ifdef HAS_FGETLN if ((ptr = fgetln(fp, &s)) == NULL) { if (size != NULL) *size = len; if (len == 0) return NULL; else return buf; } #else if ((ptr = fgets(sbuf, sizeof(sbuf) - 1, fp)) == NULL) { if (len == 0) return NULL; else return buf; } else { char *l; if ((l = strchr(sbuf, '\n')) == NULL) { if (sbuf[sizeof(sbuf) - 3] != '\\') { s = sizeof(sbuf); sbuf[sizeof(sbuf) - 2] = '\\'; sbuf[sizeof(sbuf) - 1] = '\0'; } else s = sizeof(sbuf) - 1; } else { s = l - sbuf; } } #endif if (ptr[s - 1] == '\n') /* the newline may be missing at EOF */ s--; /* forget newline */ if (!s) cnt = 0; else { if ((cnt = (ptr[s - 1] == '\\')) != 0) s--; /* forget \\ */ } if (len + s + 1 > buflen) { n = realloc(buf, len + s + 1); if (n == NULL) err(1, "can't realloc"); buf = n; buflen = len + s + 1; } memcpy(buf + len, ptr, s); len += s; buf[len] = '\0'; } if (size != NULL) *size = len; return buf; #endif /* HAS_FPARSELN */ } sup-20100519/run.c0000644000000000000000000001607211153543326012243 0ustar rootroot/* $NetBSD: run.c,v 1.14 2009/03/04 18:22:14 christos Exp $ */ /* * 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 * 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 . * [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 #include #include #include #include "supcdefs.h" #include "supextern.h" static int dorun(char *, char **, int); static char **makearglist(va_list); static char ** makearglist(va_list ap) { static size_t ns = 0; static char **np = NULL; char **nnp; size_t i = 0; do { if (i >= ns) { nnp = realloc(np, (ns + 20) * sizeof(*np)); if (nnp == NULL) { free(np); return NULL; } np = nnp; ns += 20; } np[i] = va_arg(ap, char *); } while (np[i++] != NULL); return np; } int run(char *name, ...) { int val; va_list ap; char **argv; va_start(ap, name); if ((argv = makearglist(ap)) == NULL) { va_end(ap); return -1; } val = runv(name, argv); va_end(ap); return (val); } int runv(char *name, char **argv) { return (dorun(name, argv, 0)); } int runp(char *name, ...) { int val; va_list ap; char **argv; va_start(ap, name); if ((argv = makearglist(ap)) == NULL) { va_end(ap); return -1; } val = runvp(name, argv); va_end(ap); return (val); } int runvp(char *name, char **argv) { return (dorun(name, argv, 1)); } static int dorun(char *name, char **argv, int usepath) { int wpid; int pid; struct sigaction ignoresig, intsig, quitsig; int status; if ((pid = vfork()) == -1) return (-1); /* no more processes, so exit with error */ if (pid == 0) { /* child process */ setgid(getgid()); setuid(getuid()); if (usepath) execvp(name, argv); else execv(name, argv); fprintf(stderr, "run: can't exec %s (%s)\n", name, strerror(errno)); _exit(0377); } ignoresig.sa_handler = SIG_IGN; /* ignore INT and QUIT signals */ sigemptyset(&ignoresig.sa_mask); ignoresig.sa_flags = 0; sigaction(SIGINT, &ignoresig, &intsig); sigaction(SIGQUIT, &ignoresig, &quitsig); do { wpid = wait3(&status, WUNTRACED, 0); if (WIFSTOPPED(status)) { kill(0, SIGTSTP); wpid = 0; } } while (wpid != pid && wpid != -1); sigaction(SIGINT, &intsig, 0); /* restore signals */ sigaction(SIGQUIT, &quitsig, 0); if (WIFSIGNALED(status) || WEXITSTATUS(status) == 0377) return (-1); return (WEXITSTATUS(status)); } /* * Like system(3), but with an argument list and explicit redirections * that does not use the shell */ int runio(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; } } /* * Like runio, but works with filedescriptors instead of filenames */ int runiofd(char *const * argv, const int infile, const int outfile, const int errfile) { pid_t pid; int status; switch ((pid = fork())) { case -1: return -1; case 0: if (infile != 0) dup2(infile, 0); if (outfile != 1) dup2(outfile, 1); if (errfile != 2) dup2(errfile, 2); execvp(argv[0], argv); exit(1); /* NOTREACHED */ return 0; default: if (waitpid(pid, &status, 0) == -1) return -1; return status; } } sup-20100519/scan.c0000644000000000000000000005732411266426413012372 0ustar rootroot/* $NetBSD: scan.c,v 1.27 2009/10/17 20:46:03 christos Exp $ */ /* * 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 * 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= 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. * ********************************************************************** */ #ifdef HAS_VIS #include #endif #include #include #include #include #ifdef HAS_POSIX_DIR #include #else #include #endif #include #include #include #include "supcdefs.h" #include "supextern.h" #include "libc.h" #include "c.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 { /* /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 *** *************************/ extern char _argbreak; /* break character from nxtarg */ 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 time_t lasttime; /* time of last upgrade */ extern time_t 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 /************************************************* *** STATIC R O U T I N E S *** *************************************************/ static void passdelim(char **, char); static char *parserelease(TREELIST **, char *, char *); static int scanone(TREE *, void *); static void makescan(char *, char *); static void getscan(char *, char *); static void doscan(char *); static void readlistfile(char *); static void expTinsert(char *, TREE **, int, char *); static int listone(TREE *, void *); static void listentry(char *, char *, char *, int); static void listname(char *, struct stat *); static void listdir(char *, int); static int omitanyone(TREE *, void *); static int anyglob(char *, char *); static int getscanfile(char *); static void chkscanfile(char *); static void makescanfile(char *); static int recordone(TREE *, void *); static int recordexec(TREE *, void *); /************************************************* *** L I S T S C A N R O U T I N E S *** *************************************************/ static void passdelim(char **ptr, char delim) { /* skip over delimiter */ *ptr = skipover(*ptr, " \t"); if (_argbreak != delim && **ptr == delim) { (*ptr)++; *ptr = skipover(*ptr, " \t"); } } static char * parserelease(TREELIST ** tlp, char *relname, char *args) { TREELIST *tl; char *arg; 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 = estrdup(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"); if (nextrel) free(nextrel); nextrel = estrdup(arg); break; case OPREFIX: passdelim(&args, '='); arg = nxtarg(&args, " \t"); tl->TLprefix = estrdup(arg); break; case OLIST: passdelim(&args, '='); arg = nxtarg(&args, " \t"); tl->TLlist = estrdup(arg); break; case OSCAN: passdelim(&args, '='); arg = nxtarg(&args, " \t"); tl->TLscan = estrdup(arg); break; case OHOST: passdelim(&args, '='); arg = nxtarg(&args, " \t"); tl->TLhost = estrdup(arg); break; } } return (nextrel); } int getrelease(char *release) { TREELIST *tl; char buf[STRINGLENGTH]; char *p, *q; int rewound; char *frelease = NULL; FILE *f; if (release == NULL) frelease = release = estrdup(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 = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *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) { free(tl); fclose(f); if (frelease) free(frelease); return (FALSE); } else (void) chdir(basedir); tl->TLnext = listTL; listTL = tl; if (release == NULL) break; rewound = FALSE; } (void) fclose(f); } if (release == NULL) { if (frelease) free(frelease); return (TRUE); } if (strcmp(release, DEFRELEASE) != 0) { if (frelease) free(frelease); return (FALSE); } (void) parserelease(&tl, release, ""); tl->TLprefix = prefix; tl->TLnext = listTL; listTL = tl; if (frelease) free(frelease); return (TRUE); } void makescanlists(void) { 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)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *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(tl); count++; } (void) fclose(f); } if (count == 0) makescan((char *) NULL, (char *) NULL); } static int scanone(TREE * t, void *v __unused) { 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); } void getscanlists(void) { 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, NULL); } static void makescan(char *listfile, char *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 void getscan(char *listfile, char *scanfile) { listT = NULL; if (!getscanfile(scanfile)) { /* check for pre-scanned file list */ scantime = time((time_t *) NULL); doscan(listfile); /* read list file and scan disk */ } } static void doscan(char *listfile) { char buf[STRINGLENGTH]; 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, NULL); /* build list of files * specified */ cdprefix((char *) NULL); Tfree(&upgT); Tfree(&flagsT); Tfree(&omitT); Tfree(&omanyT); Tfree(&execT); Tfree(&symT); Tfree(&rsymT); } static void readlistfile(char *fname) { char buf[STRINGLENGTH + MAXPATHLEN * 4 + 1], *p; char *q, *r; FILE *f; int ltn, n, i, flags; TREE **t = NULL; 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)) != NULL) { if ((q = strchr(p, '\n')) != NULL) *q = '\0'; if (strchr("#;:", *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; } /* FALLTHROUGH */ 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 void expTinsert(char *p, TREE ** t, int flags, char *exec) { int n, i; 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 int listone(TREE * t, void *v __unused) { /* expand and add one name from upgrade list */ listentry(t->Tname, t->Tname, (char *) NULL, (t->Tflags & FALWAYS) != 0); return (SCMOK); } static void listentry(char *name, char *fullname, char *updir, int always) { struct stat statbuf; int linkcount = 0; 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 (S_ISLNK(statbuf.st_mode)) { if (Tsearch(symT, fullname)) { listname(fullname, &statbuf); return; } if (Tlookup(rsymT, fullname)) { listname(fullname, &statbuf); return; } if (updir) linkcount++; if (stat(name, &statbuf) < 0) return; } if (S_ISDIR(statbuf.st_mode)) { 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 || linkcount) { (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 void listname(char *name, struct stat * st) { TREE *t, *ts; int new; TREELIST *tl; new = st->st_ctime > lasttime; if (newonly && !new) { for (tl = listTL; tl != NULL; tl = tl->TLnext) if ((ts = Tsearch(tl->TLtree, name)) != NULL) 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)) != NULL) t->Tflags |= ts->Tflags; if ((ts = Tsearch(execT, name)) != NULL) { t->Texec = ts->Texec; ts->Texec = NULL; } } static void listdir(char *name, int always) { /* expand directory */ #ifdef HAS_POSIX_DIR struct dirent *dentry; #else struct direct *dentry; #endif DIR *dirp; char newname[STRINGLENGTH], filename[STRINGLENGTH]; char *p, *newp; 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++) != '\0'); /* 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)) != NULL) { if (dentry->d_ino == 0) continue; if (strcmp(dentry->d_name, ".") == 0) continue; if (strcmp(dentry->d_name, "..") == 0) continue; if (*newname) { (void)snprintf(filename, sizeof(filename), "%s/%s", newname, dentry->d_name); } else { (void)strncpy(filename, dentry->d_name, sizeof(filename) - 1); filename[sizeof(filename) - 1] = '\0'; } listentry(dentry->d_name, filename, newname, always); } closedir(dirp); } static int omitanyone(TREE * t, void *fv) { char *filename = fv; if (anyglob(t->Tname, filename)) return (SCMERR); return (SCMOK); } static int anyglob(char *pattern, char *match) { char *p, *m; 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(char *scanfile) { char buf[STRINGLENGTH]; #ifdef HAS_VIS char fname[MAXPATHLEN]; #else char *fname; #endif struct stat sbuf; FILE *f; TREE ts; char *p, *q; TREE *tmp, *t = NULL; int notwanted; 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 = strchr(p, '\n')) != NULL) *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)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; ts.Tflags = 0; if (*p == 'X') { if (notwanted) continue; if (t == NULL) goaway("scanfile format inconsistent"); (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 = strchr(p, ' ')) == NULL) goaway("scanfile format inconsistent"); *q++ = '\0'; ts.Tmode = atoo(p); p = q; if ((q = strchr(p, ' ')) == NULL) goaway("scanfile format inconsistent"); *q++ = '\0'; ts.Tctime = atoi(p); p = q; if ((q = strchr(p, ' ')) == NULL) goaway("scanfile format inconsistent"); *q++ = 0; ts.Tmtime = atoi(p); #ifdef HAS_VIS (void) strunvis(fname, q); #else fname = q; #endif if (ts.Tctime > lasttime) ts.Tflags |= FNEW; else if (newonly) { for (tl = listTL; tl != NULL; tl = tl->TLnext) if ((tmp = Tsearch(tl->TLtree, fname)) != NULL) 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 void chkscanfile(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 void makescanfile(char *scanfile) { char tname[STRINGLENGTH], fname[STRINGLENGTH]; struct timeval tbuf[2]; FILE *scanF; /* output file for scanned file list */ if (scanfile == NULL) scanfile = FILESCANDEF; (void) sprintf(fname, FILESCAN, collname, scanfile); (void) sprintf(tname, "%s.temp", fname); scanF = fopen(tname, "w"); if (scanF == NULL) goto out; if (fprintf(scanF, "V%d\n", SCANVERSION) < 0) goto out; if (Tprocess(listT, recordone, scanF) != SCMOK) goto out; if (fclose(scanF) != 0) goto out; if (rename(tname, fname) < 0) { (void)unlink(tname); goaway("Can't change %s to %s", tname, fname); } tbuf[0].tv_sec = time((time_t *) NULL); tbuf[0].tv_usec = 0; tbuf[1].tv_sec = scantime; tbuf[1].tv_usec = 0; (void) utimes(fname, tbuf); return; out: goaway("Can't write scan file temp %s for %s", tname, collname); } static int recordone(TREE * t, void *v) { FILE *scanF = v; #ifdef HAS_VIS char fname[MAXPATHLEN * 4 + 1]; strvis(fname, t->Tname, VIS_WHITE); #else char *fname = t->Tname; #endif if (t->Tflags & FBACKUP) if (fprintf(scanF, "B") < 0) return SCMERR; if (t->Tflags & FNOACCT) if (fprintf(scanF, "N") < 0) return SCMERR; if (fprintf(scanF, "%o %d %d %s\n", t->Tmode, t->Tctime, t->Tmtime, fname) < 0) return SCMERR; return Tprocess(t->Texec, recordexec, scanF); } static int recordexec(TREE * t, void *v) { FILE *scanF = v; #ifdef HAS_VIS char fname[MAXPATHLEN * 4 + 1]; strvis(fname, t->Tname, VIS_WHITE); #else char *fname = t->Tname; #endif if (fprintf(scanF, "X%s\n", fname) < 0) return SCMERR; return (SCMOK); } void cdprefix(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; } sup-20100519/scm.c0000644000000000000000000004215111266442205012215 0ustar rootroot/* $NetBSD: scm.c,v 1.28 2009/10/17 22:26:13 christos Exp $ */ /* * 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 does not define them. * * 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 #include #include #include #include #include #include #include #include #include #if !defined(__linux__) #if !defined(__CYGWIN__) #include #else #include "ifaddrs.h" #endif #else #include #endif #ifdef __CYGWIN__ #include "getaddrinfo.h" #endif #include "supcdefs.h" #include "supextern.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 char scmversion[] = "4.3 BSD"; extern int silent; /************************* *** 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 sockaddr_storage remoteaddr; /* remote host address */ static char *remotename = NULL; /* remote host name */ static int swapmode; /* byte-swapping needed on server? */ static char *myhost(void); /*************************************************** *** 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 *** ***************************************************/ int servicesetup(char *server, int af) { /* listen for clients */ struct addrinfo hints, *res0, *res; char port[NI_MAXSERV]; int error; const char *cause = "unknown"; int one = 1; memset(&hints, 0, sizeof(hints)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, server, &hints, &res0); if (error) { /* retry with precompiled knowledge */ if (strcmp(server, FILEPORT) == 0) snprintf(port, sizeof(port), "%u", FILEPORTNUM); else if (strcmp(server, DEBUGFPORT) == 0) snprintf(port, sizeof(port), "%u", DEBUGFPORTNUM); else port[0] = '\0'; if (port[0]) error = getaddrinfo(NULL, port, &hints, &res0); if (error) return (scmerr(-1, "%s: %s", server, gai_strerror(error))); } for (res = res0; res; res = res->ai_next) { sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) { cause = "socket"; continue; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0) { cause = "setsockopt(SO_REUSEADDR)"; close(sock); continue; } if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { cause = "bind"; close(sock); continue; } if (listen(sock, NCONNECTS) < 0) { cause = "listen"; close(sock); continue; } freeaddrinfo(res0); return SCMOK; } freeaddrinfo(res0); return (scmerr(errno, "%s", cause)); } int service(void) { struct sockaddr_storage from; int x; socklen_t len; remotename = NULL; len = sizeof(from); do { netfile = accept(sock, (struct sockaddr *)(void *)&from, &len); } while (netfile < 0 && errno == EINTR); if (netfile < 0) return (scmerr(errno, "Can't accept connections")); if (len > sizeof(remoteaddr)) { close(netfile); return (scmerr(errno, "Can't accept connections")); } memcpy(&remoteaddr, &from, len); if (read(netfile, &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)); setproctitle("Serving %s", remotehost()); return (SCMOK); } int serviceprep(void) { /* kill temp socket in daemon */ if (sock >= 0) { (void) close(sock); sock = -1; } return (SCMOK); } int servicekill(void) { /* kill net file in daemon's parent */ if (netfile >= 0) { (void) close(netfile); netfile = -1; } if (remotename) { free(remotename); remotename = NULL; } return (SCMOK); } int serviceend(void) { /* 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 *** ***************************************************/ int dobackoff(int *t, int *b) { struct timeval tt; unsigned s; if (*t == 0) return (0); s = *b * 30; if (gettimeofday(&tt, (struct timezone *) NULL) >= 0) s += ((uint32_t)tt.tv_usec >> 8) % s; if (*b < 32) *b <<= 1; if (*t != -1) { if (s > (unsigned) *t) s = *t; *t -= s; } if (!silent) (void) scmerr(-1, "Will retry in %d seconds", s); sleep(s); return (1); } int request(char *server, char *hostname, int *retry) { /* connect to server */ struct addrinfo hints, *res, *res0; int error; char port[NI_MAXSERV]; int backoff; int x; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(hostname, server, &hints, &res0); if (error) { /* retry with precompiled knowledge */ if (strcmp(server, FILEPORT) == 0) snprintf(port, sizeof(port), "%u", FILEPORTNUM); else if (strcmp(server, DEBUGFPORT) == 0) snprintf(port, sizeof(port), "%u", DEBUGFPORTNUM); else port[0] = '\0'; if (port[0]) error = getaddrinfo(hostname, port, &hints, &res0); if (error) return (scmerr(-1, "%s: %s", server, gai_strerror(error))); } backoff = 1; for (;;) { netfile = -1; for (res = res0; res; res = res->ai_next) { if (res->ai_addrlen > sizeof(remoteaddr)) continue; netfile = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (netfile < 0) continue; if (connect(netfile, res->ai_addr, res->ai_addrlen) < 0) { close(netfile); netfile = -1; continue; } break; } if (netfile < 0) { if (!dobackoff(retry, &backoff)) { freeaddrinfo(res0); return (SCMERR); } continue; } else break; } if (res == NULL) { freeaddrinfo(res0); return (SCMERR); } memcpy(&remoteaddr, res->ai_addr, res->ai_addrlen); remotename = estrdup(hostname); x = 0x01020304; (void) write(netfile, &x, sizeof(int)); swapmode = 0; /* swap only on server, not client */ freeaddrinfo(res0); return (SCMOK); } int requestend(void) { /* 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(void) { /* find my host name */ struct hostent *h; static char name[MAXHOSTNAMELEN + 1]; if (name[0] == '\0') { if (gethostname(name, sizeof name) < 0) return (NULL); name[sizeof(name) - 1] = '\0'; if ((h = gethostbyname(name)) == NULL) return (NULL); (void) strcpy(name, h->h_name); } return (name); } const char * remotehost(void) { /* remote host name (if known) */ char h1[NI_MAXHOST]; if (remotename == NULL) { if (getnameinfo((struct sockaddr *)(void *)&remoteaddr, #ifdef BSD4_4 (socklen_t)remoteaddr.ss_len, #else sizeof(struct sockaddr), #endif h1, sizeof(h1), NULL, 0, 0)) return ("UNKNOWN"); remotename = estrdup(h1); if (remotename == NULL) return ("UNKNOWN"); } return (remotename); } int thishost(char *host) { struct hostent *h; char *name; if ((name = myhost()) == NULL) logquit(1, "Can't find my host entry '%s'", myhost()); h = gethostbyname(host); if (h == NULL) return (0); return (strcasecmp(name, h->h_name) == 0); } #ifdef __linux__ /* Nice and sleazy does it... */ struct ifaddrs { struct ifaddrs *ifa_next; struct sockaddr *ifa_addr; struct sockaddr ifa_addrspace; }; static int getifaddrs(struct ifaddrs **ifap) { struct ifaddrs *ifa; int nint; int n; char buf[10 * 1024]; struct ifconf ifc; struct ifreq *ifr; int s; if ((s = socket (AF_INET, SOCK_DGRAM, 0)) == -1) return -1; ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, &ifc) == -1) { (void)close(s); return -1; } (void)close(s); if ((nint = ifc.ifc_len / sizeof(struct ifreq)) <= 0) return 0; if ((ifa = malloc((unsigned)nint * sizeof(struct ifaddrs))) == NULL) return -1; for (ifr = ifc.ifc_req, n = 0; n < nint; n++, ifr++) { ifa[n].ifa_next = &ifa[n + 1]; ifa[n].ifa_addr = &ifa[n].ifa_addrspace; (void)memcpy(ifa[n].ifa_addr, &ifr->ifr_addr, sizeof(*ifa[n].ifa_addr)); } ifa[nint - 1].ifa_next = NULL; *ifap = ifa; return nint; } static void freeifaddrs(struct ifaddrs *ifa) { free(ifa); } #endif int samehost(void) { /* is remote host same as local host? */ struct ifaddrs *ifap, *ifa; char h1[NI_MAXHOST], h2[NI_MAXHOST]; const int niflags = NI_NUMERICHOST; if (getnameinfo((struct sockaddr *)(void *)&remoteaddr, #ifdef BSD4_4 (socklen_t)remoteaddr.ss_len, #else sizeof(struct sockaddr), #endif h1, sizeof(h1), NULL, 0, niflags)) return (0); if (getifaddrs(&ifap) < 0) return (0); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (remoteaddr.ss_family != ifa->ifa_addr->sa_family) continue; if (getnameinfo(ifa->ifa_addr, #ifdef BSD4_4 (socklen_t)ifa->ifa_addr->sa_len, #else sizeof(struct sockaddr), #endif h2, sizeof(h2), NULL, 0, niflags)) continue; if (strcmp(h1, h2) == 0) { freeifaddrs(ifap); return (1); } } freeifaddrs(ifap); return (0); } int matchhost(char *name) { /* is this name of remote host? */ char h1[NI_MAXHOST], h2[NI_MAXHOST]; const int niflags = NI_NUMERICHOST; struct addrinfo hints, *res0, *res; if (getnameinfo((struct sockaddr *)(void *)&remoteaddr, #ifdef BSD4_4 (socklen_t)remoteaddr.ss_len, #else sizeof(struct sockaddr), #endif h1, sizeof(h1), NULL, 0, niflags)) return (0); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; /* dummy */ if (getaddrinfo(name, "0", &hints, &res0) != 0) return (0); for (res = res0; res; res = res->ai_next) { if (remoteaddr.ss_family != res->ai_family) continue; if (getnameinfo(res->ai_addr, res->ai_addrlen, h2, sizeof(h2), NULL, 0, niflags)) continue; if (strcmp(h1, h2) == 0) { freeaddrinfo(res0); return (1); } } freeaddrinfo(res0); return (0); } int scmerr(int error, const char *fmt, ...) { va_list ap; va_start(ap, fmt); (void) fflush(stdout); if (progpid > 0) fprintf(stderr, "%s %d: ", program, progpid); else fprintf(stderr, "%s: ", program); vfprintf(stderr, fmt, ap); va_end(ap); if (error >= 0) fprintf(stderr, " (%s)\n", strerror(error)); 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(int in) { union intchar x, y; int ix, iy; if (swapmode == 0) return (in); x.ui = in; iy = sizeof(int); for (ix = 0; ix < (int) sizeof(int); ix++) { --iy; y.uc[iy] = x.uc[ix]; } return (y.ui); } sup-20100519/scmio.c0000644000000000000000000004344111266631412012550 0ustar rootroot/* $NetBSD: scmio.c,v 1.19 2009/10/18 15:23:54 christos Exp $ */ /* * 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 * 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 debugging 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 compatible 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 #include #include #include #include #include #include #include "supcdefs.h" #include "supextern.h" #include "supmsg.h" #ifndef INFTIM #define INFTIM -1 #endif /************************* *** 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 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 *gblbufptr; /* buffer pointer */ static int writedata(size_t, void *); static int writeblock(size_t, void *); static int readdata(size_t, void *, bool); static int readcount(int *); /*********************************************** *** O U T P U T T O N E T W O R K *** ***********************************************/ static int writedata(size_t count, void *data) { /* write raw data to network */ int x, tries; struct buf *bp; if (gblbufptr) { if (gblbufptr->b_cnt + count <= FILEXFER) { memcpy(gblbufptr->b_ptr, data, count); gblbufptr->b_cnt += count; gblbufptr->b_ptr += count; return (SCMOK); } bp = (gblbufptr == buffers) ? &buffers[1] : buffers; memcpy(bp->b_data, data, count); bp->b_cnt = count; bp->b_ptr = bp->b_data + count; data = gblbufptr->b_data; count = gblbufptr->b_cnt; gblbufptr->b_cnt = 0; gblbufptr->b_ptr = gblbufptr->b_data; gblbufptr = 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 %zu", x, count)); return (SCMOK); } static int writeblock(size_t count, void *data) { /* write data block */ int x; int y = byteswap((int)count); x = writedata(sizeof(int), &y); if (x == SCMOK) x = writedata(count, data); return (x); } int writemsg(int msg) { /* write start of message */ int x; if (scmdebug > 1) loginfo("SCM Writing message %d", msg); if (gblbufptr) return (scmerr(-1, "Buffering already enabled")); gblbufptr = buffers; gblbufptr->b_ptr = gblbufptr->b_data; gblbufptr->b_cnt = 0; x = byteswap(msg); return (writedata(sizeof(int), &x)); } int writemend(void) { /* write end of message */ size_t count; char *data; int x; x = byteswap(ENDCOUNT); x = writedata(sizeof(int), &x); if (x != SCMOK) return (x); if (gblbufptr == NULL) return (scmerr(-1, "Buffering already disabled")); if (gblbufptr->b_cnt == 0) { gblbufptr = NULL; return (SCMOK); } data = gblbufptr->b_data; count = gblbufptr->b_cnt; gblbufptr = NULL; return (writedata(count, data)); } int writeint(int i) { /* write int as data block */ int x; if (scmdebug > 2) loginfo("SCM Writing integer %d", i); x = byteswap(i); return (writeblock(sizeof(int), &x)); } int writestring(char *p) { /* write string as data block */ int len; int x; if (p == NULL) { int y = byteswap(NULLCOUNT); if (scmdebug > 2) loginfo("SCM Writing string NULL"); return (writedata(sizeof(int), &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((size_t)len, p)); } int writefile(int f) { /* write open file as a data block */ char buf[FILEXFER]; int number = 0, sum = 0, filesize, x; int y; struct stat statbuf; if (fstat(f, &statbuf) < 0) return (scmerr(errno, "Can't access open file for message")); filesize = (int)statbuf.st_size; y = byteswap(filesize); x = writedata(sizeof(int), &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((size_t)number, cryptbuf); } else { x = writedata((size_t)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); } int writemnull(int msg) { /* write message with no data */ int x; x = writemsg(msg); if (x == SCMOK) x = writemend(); return (x); } int writemint(int msg, int i) { /* write message of one int */ int x; x = writemsg(msg); if (x == SCMOK) x = writeint(i); if (x == SCMOK) x = writemend(); return (x); } int writemstr(int msg, char *p) { /* write message of one string */ 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 int readdata(size_t count, void *vdata, bool push) { /* read raw data from network */ char *p; int c, n, m, x; static int bufcnt = 0; static char *bufptr; static char buffer[FILEXFER]; struct pollfd set[1]; char *data = vdata; if (push) { if (bufptr + count < buffer) return (scmerr(-1, "No space in buffer %zu", count)); bufptr -= count; bufcnt += count; memcpy(bufptr, data, -count); return (SCMOK); } if (count == 0 && data == NULL) { bufcnt = 0; return (SCMOK); } if (count <= bufcnt) { memcpy(data, bufptr, count); bufptr += count; bufcnt -= count; return (SCMOK); } if (bufcnt > 0) { memcpy(data, bufptr, (size_t)bufcnt); data += bufcnt; count -= bufcnt; } bufptr = buffer; bufcnt = 0; set[0].fd = netfile; set[0].events = POLLIN; p = buffer; n = FILEXFER; m = count; while (m > 0) { while ((c = poll(set, 1, 2 * 60 * 60 * 1000)) < 1) { if (c == 0) return (scmerr(-1, "Timeout on network input")); if (errno != EINTR) sleep(5); } x = read(netfile, p, (size_t)n); if (x == 0) return (scmerr(-1, "Premature EOF on network input")); if (x < 0) return (scmerr(errno, "Read error on network")); p += x; n -= x; m -= x; bufcnt += x; } memcpy(data, bufptr, (size_t)count); bufptr += count; bufcnt -= count; return (SCMOK); } static int readcount(int *count) { /* read count of data block */ int x; int y; x = readdata(sizeof(int), &y, false); if (x != SCMOK) return (x); *count = byteswap(y); return (SCMOK); } int prereadcount(int *count) { /* preread count of data block */ int x; int y; x = readdata(sizeof(int), &y, false); if (x != SCMOK) return (x); x = readdata(sizeof(int), &y, true); if (x != SCMOK) return (x); *count = byteswap(y); return (SCMOK); } int readflush(void) { return readdata(0, NULL, false); } int readmsg(int msg) { /* read header for expected message */ /* if message is unexpected, send back SCMHUH */ int x; int m; if (scmdebug > 1) loginfo("SCM Reading message %d", msg); x = readdata(sizeof(int), &m, false); /* 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); } int readmend(void) { int x; int y; x = readdata(sizeof(int), &y, false); y = byteswap(y); if (x == SCMOK && y != ENDCOUNT) return (scmerr(-1, "Error reading end of message")); return (x); } int readskip(void) { /* skip over one input block */ 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((size_t)XFERSIZE(n), buf, false); n -= XFERSIZE(n); } return (x); } int readint(int *buf) { /* read int data block */ 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), &y, false); (*buf) = byteswap(y); if (scmdebug > 2) loginfo("SCM Reading integer %d", *buf); return (x); } int readstring(char **buf) { /* read string data block */ int x; int count; 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((size_t)count, cryptbuf, false); if (x != SCMOK) { free(p); return (x); } if (scmdebug > 3) printf("SCM Reading encrypted string %s\n", cryptbuf); decode(cryptbuf, p, count); } else { x = readdata((size_t)count, p, false); if (x != SCMOK) { free(p); return (x); } } p[count] = 0; /* NULL at end of string */ *buf = p; if (scmdebug > 2) loginfo("SCM Reading string %s", *buf); return (SCMOK); } int readfile(int f) { /* read data block into open file */ 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((size_t)XFERSIZE(count), cryptbuf, false); if (x == SCMOK) decode(cryptbuf, buf, XFERSIZE(count)); } else x = readdata((size_t)XFERSIZE(count), buf, false); if (x == SCMOK) { (void) write(f, buf, (size_t)XFERSIZE(count)); count -= XFERSIZE(count); } } return (x); } int readmnull(int msg) { /* read null message */ int x; x = readmsg(msg); if (x == SCMOK) x = readmend(); return (x); } int readmint(int msg, int *buf) { /* read int message */ int x; x = readmsg(msg); if (x == SCMOK) x = readint(buf); if (x == SCMOK) x = readmend(); return (x); } int readmstr(int msg, char **buf) { /* read string message */ 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 *** **********************************/ void crosspatch(void) { struct pollfd set[2]; int c; char buf[STRINGLENGTH]; set[0].fd = STDIN_FILENO; set[0].events = POLLIN; set[1].fd = netfile; set[1].events = POLLIN; for (;;) { if ((c = poll(set, 2, INFTIM)) < 1) { if (c == -1) { if (errno == EINTR) { continue; } } sleep(5); continue; } if (set[1].revents & POLLIN) { c = read(netfile, buf, sizeof(buf)); if (c < 0 && errno == EWOULDBLOCK) c = 0; else { if (c <= 0) { break; } (void) write(1, buf, (size_t)c); } } if (set[0].revents & POLLIN) { c = read(0, buf, sizeof(buf)); if (c < 0 && errno == EWOULDBLOCK) c = 0; else { if (c <= 0) break; (void) write(netfile, buf, (size_t)c); } } } } sup-20100519/setproctitle.c0000644000000000000000000000476111005431161014147 0ustar rootroot/*- * Copyright (c) 2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #ifdef NEED_SETPROCTITLE extern char **__environ; void setproctitle(const char *fmt, ...) { va_list ap; char buf[1024]; int len; char *pname, *p; char **args = __environ - 2; /* * Keep going while it looks like a pointer. We'll stop at argc, * Assume that we have < 10K args. */ while (*args > (char *)10240) args--; pname = *++args; *(int *)((int *)pname - 1) = 1; /* *argc = 1; */ /* Just the last component of the name */ if ((p = strrchr(pname, '/')) != NULL) pname = p + 1; /* In case we get called again */ if ((p = strrchr(pname, ':')) != NULL) *p = '\0'; va_start(ap, fmt); if (fmt != NULL) { len = snprintf(buf, sizeof(buf), "%s: ", pname); if (len >= 0) (void)vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); } else (void)snprintf(buf, sizeof(buf), "%s", pname); va_end(ap); (void)strcpy(pname, buf); } #endif #ifdef TEST int main(int argc, char **argv) { setproctitle("foo"); sleep(1000); return 0; } #endif sup-20100519/skipto.c0000644000000000000000000000610211266065001012733 0ustar rootroot/* $NetBSD: skipto.c,v 1.6 2009/10/16 12:41:37 christos Exp $ */ /* * 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. */ #include "supcdefs.h" #include "supextern.h" static char tab[256] = { 0 }; char * skipto(const char *string, const char *charset) { const char *setp, *strp; tab[0] = 1; /* Stop on a null, too. */ for (setp = charset; *setp; setp++) tab[(unsigned char) *setp] = 1; for (strp = string; tab[(unsigned char) *strp] == 0; strp++) continue; for (setp = charset; *setp; setp++) tab[(unsigned char) *setp] = 0; return __UNCONST(strp); } char * skipover(const char *string, const char *charset) { const char *setp, *strp; tab[0] = 0; /* Do not skip over nulls. */ for (setp = charset; *setp; setp++) tab[(unsigned char) *setp] = 1; for (strp = string; tab[(unsigned char) *strp]; strp++) continue; for (setp = charset; *setp; setp++) tab[(unsigned char) *setp] = 0; return __UNCONST(strp); } sup-20100519/stree.c0000644000000000000000000001632311266442205012557 0ustar rootroot/* $NetBSD: stree.c,v 1.15 2009/10/17 22:26:13 christos Exp $ */ /* * 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 * 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 #include #include "supcdefs.h" #include "supextern.h" #include "libc.h" #include "c.h" static TREE *Tmake(const char *); static TREE *Trotll(TREE *, TREE *); static TREE *Trotlh(TREE *, TREE *); static TREE *Trothl(TREE *, TREE *); static TREE *Trothh(TREE *, TREE *); static void Tbalance(TREE **); static TREE *Tinsertavl(TREE **, const char *, int, int *); static int Tsubprocess(TREE *, int, int (*f) (TREE *, void *), void *); static int Tprintone(TREE *, void *); /************************************************************* *** T R E E P R O C E S S I N G R O U T I N E S *** *************************************************************/ void Tfree(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(const char *p) { TREE *t; t = (TREE *) malloc(sizeof(TREE)); if (t == NULL) goaway("Cannot allocate memory"); t->Tname = (p == NULL) ? NULL : estrdup(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(TREE * tp, TREE * tl) { tp->Tlo = tl->Thi; tl->Thi = tp; tp->Tbf = tl->Tbf = 0; return (tl); } static TREE * Trotlh(TREE * tp, TREE * tl) { 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(TREE * tp, TREE * th) { 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(TREE * tp, TREE * th) { tp->Thi = th->Tlo; th->Tlo = tp; tp->Tbf = th->Tbf = 0; return (th); } static void Tbalance(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(TREE ** t, const char *p, int find, int *dh) { TREE *newt; 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(TREE ** t, const 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(TREE * t, const char *p) { TREE *x; 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(TREE * t, const char *p) { TREE *x; char buf[MAXPATHLEN + 1]; char *q; 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 ((q = strrchr(buf, '/')) != NULL) { while (q >= buf && *(q - 1) == '/') q--; if (q == buf) *(q + 1) = '\0'; else *q = '\0'; if ((x = Tsearch(t, buf)) != NULL) return (x); if (q == buf) break; } return (NULL); } static int process_level; static int Tsubprocess(TREE * t, int reverse, int (*f) (TREE *, void *), void *argp) { 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(TREE * t, int (*f) (TREE *, void *), void *args) { if (t == NULL) return (SCMOK); process_level = 0; return (Tsubprocess(t, TRUE, f, args)); } /* VARARGS2 */ int Tprocess(TREE * t, int (*f) (TREE *, void *), void *args) { if (t == NULL) return (SCMOK); process_level = 0; return (Tsubprocess(t, FALSE, f, args)); } static int /*ARGSUSED*/ Tprintone(TREE * t, void *v __unused) { int i; for (i = 0; i < (process_level * 2); i++) (void) putchar(' '); printf("Node at %p name '%s' flags %o hi %p lo %p\n", t, t->Tname, t->Tflags, t->Thi, t->Tlo); return (SCMOK); } void Tprint(TREE * t, char *p) { /* print tree -- for debugging */ printf("%s\n", p); (void) Tprocess(t, Tprintone, NULL); printf("End of tree\n"); (void) fflush(stdout); } sup-20100519/sup.10000644000000000000000000006161311273423720012163 0ustar rootroot.\" $NetBSD: sup.1,v 1.18 2009/11/02 00:29:04 joerg Exp $ .\" .\" 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 .\" 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 10/01/08 .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 -u When this flag is given, .I sup will not try to restore the user access and modified times of files in the collections from the server. .TP .B -S Operate silently printing messages only on errors. .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. .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 convenience, 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 -M like .B -m but send mail to the specified user. .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 receiving 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. .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.\*[Lt]rel-suffix\*[Gt] 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.\*[Lt]rel-suffix\*[Gt] 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. .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 option 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. .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 address 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=\*[Lt]dirname\*[Gt] to use a different parent directory for the files in this release. .I list=\*[Lt]listname\*[Gt] to specify the list of files in the release. .I scan=\*[Lt]scanfile\*[Gt] must be used in multi-release collections that are scanned to keep the scan files for the different releases separate. .I host=\*[Lt]hostfile\*[Gt] to allow different host restrictions for this release. .I next=\*[Lt]release\*[Gt] used to chain releases together. This has the effect of making one release be a combination of several 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. .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 subdirectories .I \*[Lt]basedir\*[Gt]/sup/\*[Lt]coll.name\*[Gt]. 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 transferred 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. .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 /etc/supfiles/coll.list supfile used for -s flag .TP .B /etc/supfiles/coll.what supfile used for -s flag when -t flag is also specified .TP .B /etc/supfiles/coll.host host name list for system collections .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/last\fR\*[Lt]\fI.release\fR\*[Gt] recorded list of files in collection as of last upgrade .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/lock file used to lock collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/refuse list of files to refuse in collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/when\fR\*[Lt]\fI.release\fR\*[Gt] recorded time of last upgrade .TP \fB/usr/sup/\fR\*[Lt]\fIcollection\fR\*[Gt] default base directory for file collection .DT .PP Files needed on each repository machine for the file server: .TP .B /etc/supfiles/coll.dir base directory list for system collections .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/crypt data encryption key for a collection. the owner of this file is the default account used when data encryption is specified .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/host list of remote hosts allowed to upgrade a collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/list list file for a collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/lock lock file for a collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/logfile log file for a collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/prefix file containing the name of the prefix directory for a collection .TP \*[Lt]\fIbase-directory\fR\*[Gt]\fB/sup/\fR\*[Lt]\fIcollection\fR\*[Gt]\fB/scan scan file for a collection .TP \fB/usr/\fR\*[Lt]\fIcollection\fR\*[Gt] default base directory for a file collection .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" \*[Lt]example\*[Gt] .SH "BUGS" The encryption mechanism should be strengthened, although it's not trivial. .PP .I sup can delete files it should not with the delete option. This is because in the delete pass, it tries to delete all files in the old list that don't exist in the new list. This is a problem when a directory becomes a symlink to a hierarchy that contains the same names. Then sup will cross the symlink and start deleting files and directories from the destination. This is not easily fixed. Don't use sup with symlink/rsymlink and the delete option at the same time or *be careful*! sup-20100519/sup.h0000644000000000000000000002163710732546440012260 0ustar rootroot/* $NetBSD: sup.h,v 1.11 2007/12/20 20:14:24 christos Exp $ */ /* * 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 * * 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= 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 /* 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 */ #ifndef DEFSCAN #define DEFSCAN "" #endif /* Data files used in scan.c */ #ifdef EE_XXX #define FILELIST DEFSCAN "supscan/%s/%s" #define FILESCAN DEFSCAN "supscan/%s/%s" #define FILEHOST DEFSCAN "supscan/%s/%s" #else #define FILELIST DEFSCAN "sup/%s/%s" #define FILESCAN DEFSCAN "sup/%s/%s" #define FILEHOST DEFSCAN "sup/%s/%s" #endif #define FILELISTDEF "list" #define FILESCANDEF "scan" #define FILEHOSTDEF "host" #define DEFRELEASE "default" /* Data files used in sup.c */ #define FILEBASEDEFAULT DEFDIR "/%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 DEFSCAN "sup/%s/last%s" #define FILELASTTEMP DEFSCAN "sup/%s/last%s.temp" #define FILELOCK DEFSCAN "sup/%s/lock" /* also supfilesrv */ #define FILEREFUSE DEFSCAN "sup/%s/refuse" #define FILEWHEN DEFSCAN "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 DEFSCAN "sup/%s/crypt" #define FILELOGFILE DEFSCAN "sup/%s/logfile" #ifdef EE_XXX #define FILEPREFIX DEFSCAN "supscan/%s/prefix" /* also supscan */ #define FILERELEASES DEFSCAN "supscan/%s/releases" /* also supscan */ #else #define FILEPREFIX DEFSCAN "sup/%s/prefix" /* also supscan */ #define FILERELEASES DEFSCAN "sup/%s/releases" /* also supscan */ #endif /* String length */ #define STRINGLENGTH 2000 /* Password transmission encryption key */ #define PSWDCRYPT "SuperMan" /* Test string for encryption */ #define CRYPTTEST "Hello there, Sailor Boy!" /* 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 compatibility */ #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 compatibility */ #define MAXCHILDREN 3 /* maximum number of children allowed to sup at the same time */ #include sup-20100519/supcdefs.h0000644000000000000000000000753607572026102013263 0ustar rootroot/* $NetBSD: supcdefs.h,v 1.13 2002/11/30 03:10:58 lukem Exp $ */ /* * 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 * * 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 #include "libc.h" #include #include #include #include #include #include #include #include #include #include #include #include #if MACH /* used by resource pausing code only */ #include #include #endif /* MACH */ #include "c.h" #include "sup.h" #include "supmsg.h" extern int PGMVERSION; /******************************************* *** D A T A S T R U C T U R E S *** *******************************************/ struct collstruct { /* one per collection to be upgraded */ char *Cname; /* collection name */ TREE *Chost; /* attempted host for collection */ TREE *Chtree; /* possible hosts for collection */ char *Cbase; /* local base directory */ char *Chbase; /* remote base directory */ char *Cprefix; /* local collection pathname prefix */ char *Crelease; /* release name */ char *Cnotify; /* user to notify of status */ char *Clogin; /* remote login name */ char *Cpswd; /* remote password */ char *Ccrypt; /* data encryption key */ int Ctimeout; /* timeout for backoff */ int Cflags; /* collection flags */ int Cnogood; /* upgrade no good, "when" unchanged */ int Clockfd; /* >= 0 if collection is locked */ struct collstruct *Cnext; /* next collection */ }; typedef struct collstruct COLLECTION; #define CFALL 00001 #define CFBACKUP 00002 #define CFDELETE 00004 #define CFEXECUTE 00010 #define CFLIST 00020 #define CFLOCAL 00040 #define CFMAIL 00100 #define CFOLD 00200 #define CFVERBOSE 00400 #define CFKEEP 01000 #define CFURELSUF 02000 #define CFCOMPRESS 04000 #define CFSILENT 10000 /************************* *** M A C R O S *** *************************/ #define vnotify if (thisC->Cflags&CFVERBOSE) notify sup-20100519/supcmain.c0000644000000000000000000005450211266426413013260 0ustar rootroot/* $NetBSD: supcmain.c,v 1.30 2009/10/17 20:46:03 christos Exp $ */ /* * 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. * * -u "utimes" flag * When this flags is given sup will not attempt to * restore access and modification files on the collection * files from the server. * * -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. * * -M "mailto" flag * Like -m, but send mail to the specified user. * -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 * * 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 occurred 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 successfully. 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 #ifndef SYS_rpause #define SYS_rpause (-5) #endif #endif #include "supextern.h" /********************************************* *** 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 silent; /* Silent run, print only errors */ int sysflag; /* system upgrade flag */ int timeflag; /* print times flag */ int noutime; /* Don't preserve utimes */ #if MACH int rpauseflag; /* don't disable resource pausing */ #endif /* MACH */ int xpatchflag; /* crosspatched with remote system */ int portdebug; /* network debugging ports */ int main(int, char **); static int checkcoll(TREE *, void *); static void doswitch(int *, char ***, TREE **, int *, int *, char *, size_t); static char *init(int, char **); /************************************* *** M A I N R O U T I N E *** *************************************/ int main(int argc, char **argv) { char *progname, *supfname; int restart; dev_t sfdev = 0; ino_t sfino = 0; time_t sfmtime = 0; struct stat sbuf; struct sigaction ign; /* initialize global variables */ pgmversion = PGMVERSION;/* export version number */ isserver = FALSE; /* export that we're not a server */ collname = NULL; /* no current collection yet */ dontjump = TRUE; /* clear setjmp buffer */ progname = estrdup(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 */ ign.sa_handler = SIG_IGN; ign.sa_flags = 0; sigemptyset(&ign.sa_mask); (void) sigaction(SIGPIPE, &ign, NULL); 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 || #ifndef __CYGWIN__ /* Cygwin's inodes are not constant */ sfino != sbuf.st_ino || #endif sfdev != sbuf.st_dev) { restart = 1; break; } } } endpwent(); /* close /etc/passwd */ (void) endgrent(); /* close /etc/group */ if (restart == 1) { int fd; if (!silent) 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) != NULL) { 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(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 static void doswitch(int *argc, char ***argv, TREE ** collTp, int *oflagsp, int *aflagsp, char *username, size_t ulen) { TREE *t; char *coll, *argp; int oflags, aflags; int c; #define SUPOPTIONS "abBdDeEfkKlmM:NoOPRsStuvXzZ=:" oflags = aflags = 0; while ((c = getopt(*argc, *argv, SUPOPTIONS)) != -1) switch (c) { default: logerr("Invalid flag '%c' ignored", c); break; case '\0': case '=': argp = optarg; 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); 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 'M': oflags |= CFMAIL; strncpy(username, optarg, ulen); username[ulen - 1] = '\0'; break; case 'N': scmdebug++; break; case 'o': oflags |= CFOLD; aflags &= ~CFOLD; break; case 'O': oflags &= ~CFOLD; aflags |= CFOLD; break; case 'P': portdebug = TRUE; break; case 'R': #if MACH rpauseflag = TRUE; #endif /* MACH */ break; case 's': sysflag = TRUE; break; case 'S': silent = TRUE; break; case 't': timeflag = TRUE; break; case 'u': noutime = TRUE; break; case 'v': oflags |= CFVERBOSE; break; case 'X': xpatchflag = TRUE; break; case 'z': oflags |= CFCOMPRESS; break; case 'Z': oflags &= ~CFCOMPRESS; break; } *oflagsp |= oflags; *oflagsp &= ~aflags; *aflagsp |= aflags; *aflagsp &= ~oflags; *argc -= optind; *argv += optind; } static char * init(int argc, char **argv) { char buf[STRINGLENGTH], *p; const char *u; char username[STRINGLENGTH]; char *supfname, *arg; COLLECTION *c, *lastC; FILE *f; int bogus; struct passwd *pw; TREE *t; TREE *collT; /* collections we are interested in */ time_t timenow; /* startup time */ int oflags, aflags; int cwant; #ifdef MACH void (*oldsigsys) (); #endif /* MACH */ username[0] = '\0'; 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; doswitch(&argc, &argv, &collT, &oflags, &aflags, username, sizeof(username)); if (argc == 0 && !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) snprintf(supfname = buf, sizeof(buf), timeflag ? FILESUPTDEFAULT : FILESUPDEFAULT, DEFDIR); else { supfname = *argv; if (strcmp(supfname, "-") == 0) supfname = ""; --argc; argv++; } cwant = argc > 0; while (argc > 0) { t = Tinsert(&collT, *argv, TRUE); t->Twant = TRUE; --argc; argv++; } if (*username == '\0' && ((u = getlogin()) || ((pw = getpwuid((int) getuid())) && (u = pw->pw_name)))) { (void)strncpy(username, u, sizeof(username)); username[sizeof(username) - 1] = '\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 = read_line(f, NULL, NULL, NULL, 0)) != NULL) { if (strchr("#;:", *p)) continue; arg = nxtarg(&p, " \t"); if (*arg == '\0') { logerr("Missing collection name in supfile"); bogus = TRUE; continue; } if (cwant) { TREE *mytree; if ((mytree = Tsearch(collT, arg)) == NULL) continue; mytree->Tcount++; } c = (COLLECTION *) malloc(sizeof(COLLECTION)); if (c == NULL) { logerr("Cannot allocate memory"); exit(1); } 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)) != NULL) { 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 = estrdup(username); } if (c->Cbase == NULL) { (void) sprintf(buf, FILEBASEDEFAULT, c->Cname); c->Cbase = estrdup(buf); } } if (bogus) logquit(1, "Aborted due to supfile errors"); if (f != stdin) (void) fclose(f); if (cwant) (void) Tprocess(collT, checkcoll, NULL); Tfree(&collT); if (firstC == NULL) logquit(1, "No collections to upgrade"); timenow = time((time_t *) NULL); if (*supfname == '\0') p = "standard input"; else if (sysflag) p = "system software"; else (void) sprintf(p = buf, "file %s", supfname); if (!silent) loginfo("SUP %d.%d (%s) for %s at %s", PROTOVERSION, PGMVERSION, scmversion, p, fmttime(timenow)); return (estrdup(supfname)); } static int checkcoll(TREE * t, void *dummy __unused) { 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); } sup-20100519/supcmeat.c0000644000000000000000000011722011266426413013257 0ustar rootroot/* $NetBSD: supcmeat.c,v 1.37 2009/10/17 20:46:03 christos Exp $ */ /* * 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 * * 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 "supextern.h" #include #include 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 */ extern int noutime; /* don't set utimes */ /************************************************* *** U P G R A D E C O L L E C T I O N *** *************************************************/ static int needone(TREE *, void *); static int recvone(TREE *, va_list); static int denyone(TREE *, void *); static int deleteone(TREE *, void *); static int linkone(TREE *, void *); static int execone(TREE *, void *); static int finishone(TREE *, void *); /* The next two routines define the fsm to support multiple fileservers * per collection. */ int getonehost(TREE * t, void *v) { long *state = v; 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(int *tout, int *backoff, long int *state, int *nhostsp) { static long 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. */ void getcoll(void) { TREE *t; int x; int tout, backoff, nhosts; long state; 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 { suplogin(); 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(TREE * t, int nhosts, int *tout) { int x; int timeout; time_t 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((time_t *) 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 ***/ int setup(TREE * t) { char relsufix[STRINGLENGTH]; int 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 */ return FALSE; } /*** Tell file server what account to use ***/ void suplogin(void) { char buf[STRINGLENGTH]; int f, x; /* lock collection if desired */ (void) sprintf(buf, FILELOCK, collname); f = open(buf, O_RDONLY, 0); if (f >= 0) { #if defined(LOCK_EX) #define TESTLOCK(f) flock(f, LOCK_EX|LOCK_NB) #define SHARELOCK(f) flock(f, LOCK_SH|LOCK_NB) #define WAITLOCK(f) flock(f, LOCK_EX) #elif defined(F_LOCK) #define TESTLOCK(f) lockf(f, F_TLOCK, 0) #define SHARELOCK(f) 1 #define WAITLOCK(f) lockf(f, F_LOCK, 0) #else #define TESTLOCK(f) (close(f), f = -1, 1) #define SHARELOCK(f) 1 #define WAITLOCK(f) 1 #endif if (TESTLOCK(f) < 0) { if (errno != EWOULDBLOCK && errno != EAGAIN) { (void) close(f); goaway("Can't lock collection %s", collname); } if (SHARELOCK(f) < 0) { (void) close(f); if (errno == EWOULDBLOCK && errno != EAGAIN) 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 (WAITLOCK(f) < 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. */ void listfiles(void) { char buf[STRINGLENGTH]; char relsufix[STRINGLENGTH]; char *p, *q; FILE *f; 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 = strchr(p, '\n'))) *q = '\0'; if (strchr("#;:", *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 = strchr(p, '\n'))) *q = '\0'; if (strchr("#;:", *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, NULL); 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, NULL); Tfree(&denyT); if (thisC->Cflags & (CFALL | CFDELETE | CFOLD)) (void) Trprocess(lastT, deleteone, NULL); Tfree(&refuseT); } static int needone(TREE * t, void *dummy __unused) { TREE *newt; 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 (S_ISLNK(t->Tmode)) 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 (!S_ISREG(t->Tmode)) 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 && S_ISREG(t->Tmode)) newt->Tflags |= FUPDATE; return (SCMOK); } static int denyone(TREE * t, void *v __unused) { vnotify("SUP: Access denied to %s\n", t->Tname); return (SCMOK); } static int deleteone(TREE * t, void *v __unused) { struct stat sbuf, pbuf; int x; char *name = t->Tname; char pname[MAXPATHLEN]; 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 (S_ISLNK(sbuf.st_mode)) { 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 (%s)\n", name, strerror(errno)); t->Tflags |= FUPDATE; return (SCMOK); } vnotify("SUP Deleted symbolic link %s\n", name); return (SCMOK); } /* is it a directory ? */ if (S_ISDIR(sbuf.st_mode)) { 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); } if (rmdir(name) < 0) { (void) chmod(name, sbuf.st_mode | S_IRWXU); if (strlen(name) < MAXPATHLEN - 3) { sprintf(pname, "%s/..", name); if (stat(pname, &pbuf) == 0) (void) chmod(pname, pbuf.st_mode | S_IRWXU); } runp("rm", "rm", "-rf", name, 0); } if (rmdir(name) < 0 && errno != ENOENT) { notify("SUP: Unable to delete directory %s (%s)\n", name, strerror(errno)); 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 (%s)\n", name, strerror(errno)); 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. */ void recvfiles(void) { int x; 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 */ int prepare(char *name, int mode, int *newp, struct stat * statp) { char *type; char pname[MAXPATHLEN]; struct stat pbuf; int er = 0; 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 (S_ISDIR(statp->st_mode)) { if (rmdir(name) < 0) { (void) chmod(name, statp->st_mode | S_IRWXU); if (strlen(name) < MAXPATHLEN - 3) { sprintf(pname, "%s/..", name); if (stat(pname, &pbuf) == 0) (void) chmod(pname, pbuf.st_mode | S_IRWXU); } runp("rm", "rm", "-rf", name, 0); } if (rmdir(name) < 0) er = errno; } else { if (unlink(name) < 0) er = errno; } if (stat(name, statp) < 0) { vnotify("SUP Removed %s %s\n", type, name); return (FALSE); } notify("SUP: Couldn't remove %s %s (%s)\n", type, name, strerror(er)); return (TRUE); } static int recvone(TREE * t, va_list ap) { int x = 0; int new; struct stat sbuf; int *recvmore; 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 (%s)\n", t->Tname, strerror(errno)); if (S_ISREG(t->Tmode)) { 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 (S_ISREG(t->Tmode)) (void) Tprocess(t->Tlink, linkone, t->Tname); (void) Tprocess(t->Texec, execone, NULL); return (SCMOK); } int recvdir(TREE * t, int new, struct stat * statp) { /* receive directory from network */ struct timeval tbuf[2]; if (new) { if (thisC->Cflags & CFLIST) { vnotify("SUP Would create directory %s\n", t->Tname); return (FALSE); } if (makedir(t->Tname, 0755, statp) == -1) { notify("SUP: Can't create directory %s (%s)\n", t->Tname, strerror(errno)); 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((time_t *) NULL); tbuf[0].tv_usec = 0; tbuf[1].tv_sec = t->Tmtime; tbuf[1].tv_usec = 0; if (!noutime) (void) utimes(t->Tname, tbuf); vnotify("SUP %s directory %s\n", new ? "Created" : "Updated", t->Tname); return (FALSE); } int recvsym(TREE * t, int new, struct stat * statp) { /* receive symbolic link */ char buf[STRINGLENGTH]; int n; 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; n = -1; if (!new && (t->Tflags & FNEW) == 0 && (n = readlink(t->Tname, buf, sizeof(buf) - 1)) >= 0 && (n == strlen(linkname)) && (strncmp(linkname, buf, n) == 0)) return (FALSE); if (n >= 0) t->Tname[n] = '\0'; 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 (%s)\n", t->Tname, strerror(errno)); return (TRUE); } vnotify("SUP Created symbolic link %s to %s\n", t->Tname, linkname); return (FALSE); } int recvreg(TREE * t, int new, struct stat * statp) { /* receive file from network */ FILE *fin, *fout; char dirpart[STRINGLENGTH], filepart[STRINGLENGTH]; char filename[STRINGLENGTH], buf[STRINGLENGTH]; struct timeval tbuf[2]; int x; 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((time_t *) NULL); tbuf[0].tv_usec = 0; tbuf[1].tv_sec = t->Tmtime; tbuf[1].tv_usec = 0; if (!noutime) (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 && S_ISREG(t->Tmode) && (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((time_t *) NULL); tbuf[0].tv_usec = 0; tbuf[1].tv_sec = t->Tmtime; tbuf[1].tv_usec = 0; if (!noutime) (void) utimes(t->Tname, tbuf); return (FALSE); } static int linkone(TREE * t, void *fv) { /* link to file already received */ char *fname = fv; struct stat fbuf, sbuf; char *name = t->Tname; int new, x; char *type; if (lstat(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_IFLNK, &new, &sbuf)) { 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 (S_ISDIR(fbuf.st_mode) || (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 (%s)\n", type, name, strerror(x)); return (TRUE); } vnotify("SUP Created %slink %s to %s\n", type, name, fname); return (SCMOK); } static int execone(TREE * t, void *v __unused) { /* execute command for file */ int 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 = system(t->Tname); if (WIFEXITED(w) && WEXITSTATUS(w) != 0) { notify("SUP: Execute command returned failure status %#o\n", WEXITSTATUS(w)); thisC->Cnogood = TRUE; } else if (WIFSIGNALED(w)) { notify("SUP: Execute command killed by signal %d\n", WTERMSIG(w)); thisC->Cnogood = TRUE; } else if (WIFSTOPPED(w)) { notify("SUP: Execute command stopped by signal %d\n", WSTOPSIG(w)); thisC->Cnogood = TRUE; } return (SCMOK); } /* from will be 0 if reading from network */ int copyfile(char *to, char *from) { int fromf, tof, istemp, x; char dpart[STRINGLENGTH], fpart[STRINGLENGTH]; char tname[STRINGLENGTH]; static int returntrue = 1; 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, strerror(errno)); 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 | O_EXCL), 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 | O_EXCL), 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 | O_EXCL), 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 | O_EXCL), 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 | O_EXCL), 0600); if (tof >= 0) break; #endif /* try /tmp */ (void) sprintf(tname, "/tmp/#%d.sup", thispid); tof = open(tname, (O_WRONLY | O_CREAT | O_TRUNC | O_EXCL), 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 | O_EXCL), 0600); if (tof >= 0) break; /* no luck */ notify("SUP: Can't create %s or temp file for it (%s)\n", to, strerror(errno)); lockout(FALSE); if (fromf >= 0) (void) close(fromf); else { x = readskip(); if (x != SCMOK) goaway("Can't skip file transfer"); } if (returntrue) 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); } /* ** If the file is compressed, uncompress it in place. We open the ** temp file for reading, unlink the file, and then open the same ** file again for writing. Then we pipe through gzip. When ** finished the temp file contains the uncompressed version and we ** can continue as before. ** ** Since sup prefers to write close to the original file the ** benefits of atomic updates probably outweigh the cost of the ** extra filecopy which occurs when the temp file is on a different ** filesystem from the original. */ if (docompress) { char *av[4]; int ac = 0; int infd = -1; int outfd = -1; av[ac++] = "gzip"; av[ac++] = "-d"; av[ac++] = NULL; if ((infd = open(tname, O_RDONLY, 0)) == -1 || unlink(tname) == -1 || (outfd = open(tname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) == -1 || runiofd(av, infd, outfd, 2) != 0) { notify("SUP: Error in uncompressing file %s (%s)\n", to, tname); (void) unlink(tname); if (infd != -1) (void) close(infd); if (outfd != -1) (void) close(outfd); lockout(FALSE); return (TRUE); } (void) close(infd); (void) close(outfd); } /* 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, strerror(errno)); (void) unlink(tname); lockout(FALSE); return (TRUE); } tof = open(to, (O_WRONLY | O_CREAT | O_TRUNC | O_EXCL), 0600); if (tof < 0) { (void) close(fromf); notify("SUP: Can't create %s from temp file (%s)\n", to, strerror(errno)); (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 ***/ void finishup(int x) { char tname[STRINGLENGTH], fname[STRINGLENGTH]; char relsufix[STRINGLENGTH]; char collrelname[STRINGLENGTH]; time_t tloc; FILE *finishfile; /* record of all filenames */ 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((time_t *) 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)) { 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, strerror(errno)); 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, relsufix); 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 (%s)\n", tname, fname, strerror(errno)); (void) unlink(tname); Tfree(&lastT); } int finishone(TREE * t, void *fv) { FILE *finishfile = fv; if ((thisC->Cflags & CFDELETE) == 0 || (t->Tflags & FUPDATE)) fprintf(finishfile, "%s\n", t->Tname); return (SCMOK); } void done(int value, const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); (void) netcrypt((char *) NULL); if (fmt) vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (protver < 6) { if (goawayreason) free(goawayreason); goawayreason = (fmt) ? estrdup(buf) : (char *) NULL; (void) msggoaway(); } else { doneack = value; donereason = (fmt) ? buf : (char *) NULL; (void) msgdone(); } if (!dontjump) longjmp(sjbuf, TRUE); } void goaway(const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); (void) netcrypt((char *) NULL); 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); } sup-20100519/supcmisc.c0000644000000000000000000002136211266065001013255 0ustar rootroot/* $NetBSD: supcmisc.c,v 1.20 2009/10/16 12:41:37 christos Exp $ */ /* * 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 * Revision 1.5 92/08/11 12:07:22 mrt * Added release to FILEWHEN name. * Brad's changes: delinted and updated variable argument 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. * ********************************************************************** */ #include "supcdefs.h" #include "supextern.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<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%s", buf, thisC->Cname, relsufix); } int establishdir(char *fname) { char dpart[STRINGLENGTH], fpart[STRINGLENGTH]; path(fname, dpart, fpart); return (estabd(fname, dpart)); } int makedir(char *fname, unsigned int mode, struct stat * statp) { int en, rv; if (lstat(fname, statp) != -1 && !S_ISDIR(statp->st_mode)) { if (unlink(fname) == -1) { notify("SUP: Can't delete %s (%s)\n", fname, strerror(errno)); return -1; } } if (mkdir(fname, mode) == -1) en = errno; else en = -1; rv = stat(fname, statp); if (en != -1) errno = en; return rv; } int estabd(char *fname, char *dname) { char dpart[STRINGLENGTH], fpart[STRINGLENGTH]; struct stat sbuf; 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 (Invalid name)\n", dname, fname); return (TRUE); } x = estabd(fname, dpart); if (x) return (TRUE); if (makedir(dname, 0755, &sbuf) < 0) { notify("SUP: Can't create directory %s for %s (%s)\n", dname, fname, strerror(errno)); 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(char *name) { /* Hash function is: HASHSIZE * (strlen mod HASHSIZE) + * (char mod HASHSIZE) where "char" is last character of name (if * name is non-null). */ int len; char c; len = strlen(name); if (len > 0) c = name[len - 1]; else c = 0; return (((len & HASHMASK) << HASHBITS) | (((int) c) & HASHMASK)); } static void Linsert(LIST ** table, char *name, int number) { LIST *l; int lno; lno = Lhash(name); l = (LIST *) malloc(sizeof(LIST)); if (l == NULL) goaway("Cannot allocate memory"); l->Lname = name; l->Lnumber = number; l->Lnext = table[lno]; table[lno] = l; } static LIST * Llookup(LIST ** table, char *name) { int lno; LIST *l; lno = Lhash(name); for (l = table[lno]; l && strcmp(l->Lname, name) != 0; l = l->Lnext); return (l); } void ugconvert(char *uname, char *gname, int *uid, int *gid, int *mode) { LIST *u, *g; struct passwd *pw; struct group *gr; struct stat sbuf; static int defuid = -1; static int defgid; static int first = TRUE; if (first) { bzero(uidL, sizeof(uidL)); bzero(gidL, sizeof(gidL)); first = FALSE; } pw = NULL; if ((u = Llookup(uidL, uname)) != NULL) *uid = u->Lnumber; else if ((pw = getpwnam(uname)) != NULL) { Linsert(uidL, estrdup(uname), pw->pw_uid); *uid = pw->pw_uid; } if (u || pw) { if ((g = Llookup(gidL, gname)) != NULL) { *gid = g->Lnumber; return; } if ((gr = getgrnam(gname)) != NULL) { Linsert(gidL, estrdup(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 *** *********************************************/ void notify(const char *fmt, ...) { /* record error message */ char buf[STRINGLENGTH]; char collrelname[STRINGLENGTH]; char hostname[STRINGLENGTH]; time_t tloc; static FILE *noteF = NULL; /* mail program on pipe */ va_list ap; int shouldMail = (thisC->Cflags & CFMAIL) && thisC->Cnotify; int needFile = shouldMail || silent; va_start(ap, fmt); if ((thisC->Cflags & CFURELSUF) && thisC->Crelease) (void) sprintf(collrelname, "%s-%s", collname, thisC->Crelease); else (void) strcpy(collrelname, collname); if (fmt == NULL) { if (noteF && noteF != stdout && (!silent || thisC->Cnogood)) { int nr; FILE *outF; if (shouldMail) { (void)gethostname(hostname, sizeof(hostname)); (void) snprintf(buf, sizeof(buf), "mail -s \"SUP Upgrade of %s on %s\" %s >" " /dev/null", collrelname, hostname, thisC->Cnotify); outF = popen(buf, "w"); if (outF == NULL) { logerr("Can't send mail to %s for %s", thisC->Cnotify, collrelname); outF = stdout; } } else outF = stdout; (void)rewind(noteF); while ((nr = fread(buf, 1, sizeof(buf), noteF)) > 0) (void)fwrite(buf, 1, nr, outF); (void)fflush(outF); if (outF != stdout) (void)pclose(outF); (void)fclose(noteF); } noteF = NULL; va_end(ap); return; } if (noteF == NULL) { if (needFile) { char template[] = "/tmp/sup.XXXXXX"; int fd = mkstemp(template); if (fd == -1 || (noteF = fdopen(fd, "r+")) == NULL) { logerr("Can't open temporary file for %s", collrelname); silent = 0; noteF = stdout; } (void)unlink(template); } else noteF = stdout; tloc = time((time_t *) 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); } void lockout(int on) { /* lock out interrupts */ static sigset_t oset; sigset_t nset; if (on) { sigemptyset(&nset); sigaddset(&nset, SIGHUP); sigaddset(&nset, SIGINT); sigaddset(&nset, SIGTERM); sigaddset(&nset, SIGQUIT); (void) sigprocmask(SIG_BLOCK, &nset, &oset); } else { (void) sigprocmask(SIG_SETMASK, &oset, NULL); } } char * fmttime(time_t time) { static char buf[STRINGLENGTH]; unsigned int len; (void) strcpy(buf, ctime(&time)); len = strlen(buf + 4) - 6; buf[len] = '\0'; return buf + 4; } sup-20100519/supcname.c0000644000000000000000000000727311266426413013257 0ustar rootroot/* $NetBSD: supcname.c,v 1.7 2009/10/17 20:46:03 christos Exp $ */ /* * 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 * 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" #include "supextern.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(void) { COLLECTION *c; char buf[STRINGLENGTH]; 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 = strchr(p, '\n')) != NULL) *q = '\0'; if (strchr("#;:", *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"); } sup-20100519/supcparse.c0000644000000000000000000001442210413625544013442 0ustar rootroot/* $NetBSD: supcparse.c,v 1.14 2006/04/02 01:39:48 christos Exp $ */ /* * 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 * * 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" #include "supextern.h" extern char _argbreak; /* break character from nxtarg */ 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 } }; static void passdelim(char **, char); static void passdelim(char **ptr, char delim) { /* skip over delimiter */ *ptr = skipover(*ptr, " \t"); if (_argbreak != delim && **ptr == delim) { (*ptr)++; *ptr = skipover(*ptr, " \t"); } } int parsecoll(COLLECTION * c, char *collname, char *args) { char *arg, *p; OPTION option; int opno; c->Cnext = NULL; c->Cname = estrdup(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 = estrdup(arg); break; case OHOSTBASE: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Chbase = estrdup(arg); break; case OPREFIX: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Cprefix = estrdup(arg); break; case ORELEASE: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Crelease = estrdup(arg); break; case ONOTIFY: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Cnotify = estrdup(arg); break; case OLOGIN: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Clogin = estrdup(arg); break; case OPASSWORD: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Cpswd = estrdup(arg); break; case OCRYPT: passdelim(&args, '='); arg = nxtarg(&args, " \t"); c->Ccrypt = estrdup(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); } time_t getwhen(char *collection, char *relsuffix) { char buf[STRINGLENGTH]; char *ep; FILE *fp; time_t 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(char *fname, time_t tstamp) { FILE *fp; if ((fp = fopen(fname, "w")) == NULL) return 0; if (fprintf(fp, "%lu\n", (u_long) tstamp) < 0) { (void) fclose(fp); return 0; } if (fclose(fp) != 0) return 0; return 1; } sup-20100519/supcvers.c0000644000000000000000000000531407513113342013302 0ustar rootroot/* $NetBSD: supcvers.c,v 1.5 2002/07/10 20:19:46 wiz Exp $ */ /* * 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 * 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 */ sup-20100519/supextern.h0000644000000000000000000001103711266442205013474 0ustar rootroot/* $NetBSD: supextern.h,v 1.22 2009/10/17 22:26:13 christos Exp $ */ struct stat; /* atoo.c */ unsigned int atoo(char *); /* expand.c */ int expand(char *, char **, int); /* ffilecopy.c */ ssize_t ffilecopy(FILE *, FILE *); /* filecopy.c */ ssize_t filecopy(int, int ); /* log.c */ void logopen(char *); void logquit(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); void logerr(const char *, ...) __attribute__((__format__(__printf__, 1, 2))) ; void loginfo(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); #ifdef LIBWRAP void logdeny(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); void logallow(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); #endif /* netcryptvoid.c */ int netcrypt(char *); int getcryptbuf(int); void decode(char *, char *, int); void encode(char *, char *, int); /* nxtarg.c */ char *nxtarg(char **, const char *); /* path.c */ void path(char *, char *, char *); /* quit.c */ void quit(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); /* read_line.c */ char *read_line(FILE *, size_t *, size_t *, const char[3], int); /* run.c */ int run(char *, ...); int runv(char *, char **); int runp(char *, ...); int runvp(char *, char **); int runio(char *const[], const char *, const char *, const char *); int runiofd(char *const[], const int, const int, const int); /* estrdup.c */ char *estrdup(const char *); /* scan.c */ int getrelease(char *); void makescanlists(void); void getscanlists(void); void cdprefix(char *); /* scm.c */ int servicesetup(char *, int); int service(void); int serviceprep(void); int servicekill(void); int serviceend(void); int dobackoff(int *, int *); int request(char *, char *, int *); int requestend(void); const char *remotehost(void); int thishost(char *); int samehost(void); int matchhost(char *); int scmerr(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); int byteswap(int); /* scmio.c */ int writemsg(int); int writemend(void); int writeint(int); int writestring(char *); int writefile(int); int writemnull(int); int writemint(int, int ); int writemstr(int, char *); int prereadcount(int *); int readflush(void); int readmsg(int); int readmend(void); int readskip(void); int readint(int *); int readstring(char **); int readfile(int); int readmnull(int); int readmint(int, int *); int readmstr(int, char **); void crosspatch(void); /* skipto.c */ char *skipto(const char *, const char *); char *skipover(const char *, const char *); /* stree.c */ void Tfree(TREE **); TREE *Tinsert(TREE **, const char *, int); TREE *Tsearch(TREE *, const char *); TREE *Tlookup(TREE *, const char *); int Trprocess(TREE *, int (*)(TREE *, void *), void *); int Tprocess(TREE *, int (*)(TREE *, void *), void *); void Tprint(TREE *, char *); /* supcmeat.c */ int getonehost(TREE *, void *); TREE *getcollhost(int *, int *, long *, int *); void getcoll(void); int signon(TREE *, int, int *); int setup(TREE *); void suplogin(void); void listfiles(void); void recvfiles(void); int prepare(char *, int, int *, struct stat *); int recvdir(TREE *, int, struct stat *); int recvsym(TREE *, int, struct stat *); int recvreg(TREE *, int, struct stat *); int copyfile(char *, char *); void finishup(int); void done(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); void goaway(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); /* supcmisc.c */ void prtime(void); int establishdir(char *); int makedir(char *, unsigned int, struct stat *); int estabd(char *, char *); void ugconvert(char *, char *, int *, int *, int *); void notify(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); void lockout(int); char *fmttime(time_t); /* supcname.c */ void getnams(void); /* supcparse.c */ int parsecoll(COLLECTION *, char *, char *); time_t getwhen(char *, char *); int putwhen(char *, time_t); /* supmsg.c */ int msgsignon(void); int msgsignonack(void); int msgsetup(void); int msgsetupack(void); int msgcrypt(void); int msgcryptok(void); int msglogin(void); int msglogack(void); int msgrefuse(void); int msglist(void); int msgneed(void); int msgdeny(void); int msgsend(void); int msgrecv(int (*)(TREE *, va_list), ...); int msgdone(void); int msggoaway(void); int msgxpatch(void); int msgcompress(void); /* vprintf.c */ /* XXX already in system headers included already - but with different argument declarations! */ #if 0 int vprintf(const char *, va_list); int vfprintf(FILE *, const char *, va_list); int vsprintf(char *, const char *, va_list); int vsnprintf(char *, size_t, const char *, va_list); #endif sup-20100519/supfilesrv.c0000644000000000000000000014664411266426413013654 0ustar rootroot/* $NetBSD: supfilesrv.c,v 1.43 2009/10/17 20:46:03 christos Exp $ */ /* * 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 [-d] [-l] [-P] [-N] [-R] [-S] * -d "debug" -- don't fork daemon * -l "log" -- print successull connects (when compiled with libwrap) * -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 * -S "Operate silently" -- Only print error messages * ********************************************************************** * HISTORY * 2-Aug-99 Manuel Bouyer at LIP6 * Added libwrap support * * 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 * * Revision 1.20 92/09/09 22:05:00 mrt * Added Brad's change to make send_file 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 fstatvfs(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 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= 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. * ********************************************************************** */ #ifdef AFS #include #undef MAXNAMLEN #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef HAS_POSIX_DIR #include #else #include #endif #if MACH #include #endif #if CMUCS #include #include #include #include #else /* CMUCS */ #define ACCESS_CODE_OK 0 #define ACCESS_CODE_BADPASSWORD (-2) #endif /* CMUCS */ #ifdef __SVR4 #include #include #endif #ifdef LIBWRAP #include #endif #include "supcdefs.h" #include "supextern.h" #define MSGFILE #include "supmsg.h" #include "libc.h" #include "c.h" extern char *crypt(const char *, const char *); 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< 0) nchildren++; (void) sigprocmask(SIG_SETMASK, &oset, NULL); } } /* * Child status signal handler */ void chldsig(int snum __unused) { int 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 *** *****************************************/ void usage(void) { #ifdef LIBWRAP quit(1, "Usage: supfilesrv [ -4 | -6 | -l | -d | -P | -N | -C | -H ]\n"); #else quit(1, "Usage: supfilesrv [ -4 | -6 | -d | -P | -N | -C | -H ]\n"); #endif } void init(int argc, char **argv) { int i; int x; char *clienthost, *clientuser; char *p, *q; char buf[STRINGLENGTH]; int maxsleep; FILE *f; int af = AF_INET; #ifdef RCS candorcs = FALSE; #endif live = FALSE; #ifdef LIBWRAP sup_clog = FALSE; #endif 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 'S': silent = TRUE; break; #ifdef LIBWRAP case 'l': sup_clog = TRUE; break; #endif case 'd': 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 case '4': af = AF_INET; break; #ifdef AF_INET6 case '6': af = AF_INET6; 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, af); if (x != SCMOK) quit(1, "Error in network setup"); for (i = 0; i < HASHSIZE; i++) uidH[i] = gidH[i] = inodeH[i] = NULL; return; } isserver = 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)) != NULL) { if ((q = strchr(p, '\n')) != NULL) *q = '\0'; if (*p == '\0') quit(1, "No cryptkey found in %s\n", cryptkey); cryptkey = estrdup(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 *** *****************************************/ void answer(void) { time_t starttime; 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((time_t *) NULL); if (!setjmp(sjbuf)) { srvsignon(); srvsetup(); docrypt(); srvlogin(); 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(); send_files(); } srvfinishup(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 *** *****************************************/ void srvsignon(void) { 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 *** *****************************************************************/ void srvsetup(void) { int x; char *p, *q; char buf[STRINGLENGTH]; FILE *f; struct stat sbuf; 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) { struct passwd *pw; if ((pw = getpwnam(xuser)) == NULL) { setupack = FSETUPSAME; (void) msgsetupack(); if (protver >= 6) longjmp(sjbuf, TRUE); goaway("User `%s' not found", xuser); } (void) free(xuser); xuser = estrdup(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(&sbuf, sizeof(sbuf)); if ((f = fopen(buf, "r")) != NULL) { struct stat fsbuf; while ((p = fgets(buf, STRINGLENGTH, f)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; q = nxtarg(&p, " \t"); if (*p == '\0') continue; if (!matchhost(q)) continue; cryptkey = estrdup(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 = estrdup(&release[4]); free(release); release = estrdup("RCS"); dorcs = TRUE; } #endif if (release == NULL) release = estrdup(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)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; q = nxtarg(&p, " \t="); if (strcmp(q, collname) == 0) { basedir = skipover(p, " \t="); basedir = estrdup(basedir); break; } } (void) fclose(f); } if (basedir == NULL) { (void) sprintf(buf, FILEBASEDEFAULT, collname); basedir = estrdup(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)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; prefix = estrdup(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)) != NULL) { int not; q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *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 = estrdup(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); #ifdef LOCK_SH 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; } #endif setupack = FSETUPOK; x = msgsetupack(); if (x != SCMOK) goaway("Error sending setup reply to client"); } void /** Test data encryption **/ docrypt(void) { int x; char *p, *q; char buf[STRINGLENGTH]; FILE *f; struct stat sbuf; 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(&sbuf, sizeof(sbuf)); if ((f = fopen(buf, "r")) != NULL) { struct stat fsbuf; if (cryptkey == NULL && (p = fgets(buf, STRINGLENGTH, f))) { if ((q = strchr(p, '\n')) != NULL) *q = '\0'; if (*p) cryptkey = estrdup(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 *** ***************************************************************/ void srvlogin(void) { int x, fileuid = -1, filegid = -1; (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 = estrdup(DEFUSER); } else loguser = estrdup(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 *** *****************************************/ void listfiles(void) { 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, NULL); Tfree(&needT); x = msgdeny(); if (x != SCMOK) goaway("Error sending denied files list to client"); Tfree(&denyT); } int denyone(TREE * t, void *v __unused) { TREELIST *tl; char *name = t->Tname; int update = (t->Tflags & FUPDATE) != 0; struct stat sbuf; TREE *tlink; char slinkname[STRINGLENGTH]; 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 (S_ISLNK(t->Tmode)) 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 - 1)) <= 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 *** *********************************/ void send_files(void) { TREELIST *tl; 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, send_one, NULL); } /* send directories in reverse order */ for (tl = listTL; tl != NULL; tl = tl->TLnext) { cdprefix(tl->TLprefix); (void) Trprocess(tl->TLtree, send_dir, NULL); } x = msgsend(); if (x != SCMOK) goaway("Error reading receive file request from client"); upgradeT = NULL; x = msgrecv(send_file, 0); if (x != SCMOK) goaway("Error sending file to client"); } int send_one(TREE * t, void *v __unused) { int x, fd; char temp_file[STRINGLENGTH]; char *av[50]; /* More than enough */ if ((t->Tflags & FNEEDED) == 0) /* only send needed files */ return (SCMOK); if (S_ISDIR(t->Tmode)) /* 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 (S_ISREG(t->Tmode)) { if (!listonly && (t->Tflags & FUPDATE) == 0) { #ifdef RCS if (dorcs) { char rcs_release[STRINGLENGTH]; tmpnam(rcs_file); fd = open(rcs_file, (O_WRONLY | O_CREAT | O_TRUNC | O_EXCL), 0600); if (fd < 0) goaway("We died trying to create temp file"); close(fd); fd = -1; 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 = runio(av, NULL, rcs_file, "/dev/null"); /* loginfo("using rcs mode \n"); */ if (status < 0 || WEXITSTATUS(status)) { /* Just in case */ unlink(rcs_file); if (status < 0) { goaway("We died trying to run cvs or rcs on %s", rcs_file); t->Tmode = 0; } else { #if 0 logerr("rcs command failed = %d\n", WEXITSTATUS(status)); #endif t->Tflags |= FUPDATE; } } else if (docompress) { tmpnam(temp_file); av[0] = "gzip"; av[1] = "-cf"; 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 %s", rcs_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) { snprintf(temp_file, sizeof(temp_file), "%s/supfilesrv.XXXXXX", P_tmpdir); fd = mkstemp(temp_file); if (fd < 0) goaway("We died trying to create temp file"); close(fd); fd = -1; av[0] = "gzip"; av[1] = "-cf"; av[2] = NULL; if (runio(av, t->Tname, temp_file, NULL) != 0) { /* Just in case */ unlink(temp_file); goaway("We died trying to gzip %s", t->Tname); 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 = estrdup(uconvert(t->Tuid)); t->Tgroup = estrdup(gconvert(t->Tgid)); } } x = msgrecv(send_file, fd); if (docompress) unlink(temp_file); #ifdef RCS if (dorcs) unlink(rcs_file); #endif if (x != SCMOK) goaway("Error sending file %s to client", t->Tname); return (SCMOK); } int send_dir(TREE * t, void *v __unused) { int x; if ((t->Tflags & FNEEDED) == 0) /* only send needed files */ return (SCMOK); if (!S_ISDIR(t->Tmode)) /* 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 = estrdup(uconvert(t->Tuid)); t->Tgroup = estrdup(gconvert(t->Tgid)); x = msgrecv(send_file, 0); if (x != SCMOK) goaway("Error sending file %s to client", t->Tname); return (SCMOK); } int send_file(TREE * t, va_list ap) { int x, fd; fd = va_arg(ap, int); if (!S_ISREG(t->Tmode) || listonly || (t->Tflags & FUPDATE)) return (SCMOK); x = writefile(fd); if (x != SCMOK) goaway("Error sending file %s to client", t->Tname); (void) close(fd); return (SCMOK); } /***************************************** *** E N D C O N N E C T I O N *** *****************************************/ void srvfinishup(time_t starttime) { int x = SCMOK; char tmpbuf[BUFSIZ], *p, lognam[STRINGLENGTH]; int logfd; time_t finishtime; char *releasename; (void) netcrypt((char *) NULL); if (protver < 6) { if (goawayreason != NULL) free(goawayreason); goawayreason = (char *) NULL; x = msggoaway(); doneack = FDONESUCCESS; donereason = estrdup("Unknown"); } else if (goawayreason == (char *) NULL) x = msgdone(); else { doneack = FDONEGOAWAY; donereason = goawayreason; } if (x == SCMEOF || x == SCMERR) { doneack = FDONEUSRERROR; donereason = estrdup("Premature EOF on network"); } else if (x != SCMOK) { doneack = FDONESRVERROR; donereason = estrdup("Unknown SCM code"); } if (doneack == FDONEDONTLOG) return; if (donereason == NULL) donereason = estrdup("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); if (collname == NULL) { logerr("NULL collection in svrfinishup"); return; } (void) sprintf(lognam, FILELOGFILE, collname); if ((logfd = open(lognam, O_APPEND | O_WRONLY, 0644)) < 0) return; /* can not open file up...error */ finishtime = time((time_t *) 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 *** ***************************************************/ void Hfree(HASH ** table) { HASH *h; int i; for (i = 0; i < HASHSIZE; i++) while ((h = table[i]) != NULL) { table[i] = h->Hnext; if (h->Hname) free(h->Hname); free(h); } } HASH * Hlookup(HASH ** table, int num1, int num2) { HASH *h; int hno; hno = HASHFUNC(num1, num2); for (h = table[hno]; h && (h->Hnum1 != num1 || h->Hnum2 != num2); h = h->Hnext); return (h); } void Hinsert(HASH ** table, int num1, int num2, char *name, TREE * tree) { HASH *h; int hno; hno = HASHFUNC(num1, num2); h = (HASH *) malloc(sizeof(HASH)); if (h == NULL) goaway("Cannot allocate memory"); 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(TREE * t, int d, int i) /* inode # and device # */ { HASH *h; h = Hlookup(inodeH, i, d); if (h) return (h->Htree); Hinsert(inodeH, i, d, (char *) NULL, t); return ((TREE *) NULL); } char * uconvert(int uid) { struct passwd *pw; char *p; HASH *u; u = Hlookup(uidH, uid, 0); if (u) return (u->Hname); pw = getpwuid(uid); if (pw == NULL) return (""); p = estrdup(pw->pw_name); Hinsert(uidH, uid, 0, p, (TREE *) NULL); return (p); } char * gconvert(int gid) { struct group *gr; char *p; HASH *g; g = Hlookup(gidH, gid, 0); if (g) return (g->Hname); gr = getgrgid(gid); if (gr == NULL) return (""); p = estrdup(gr->gr_name); Hinsert(gidH, gid, 0, p, (TREE *) NULL); return (p); } char * changeuid(char *namep, char *passwordp, int fileuid, int filegid) { char *group, *account, *pswdp; struct passwd *pwd; struct group *grp; #if CMUCS struct account *acc; struct ttyloc tlc; #endif /* CMUCS */ int status = ACCESS_CODE_OK; char nbuf[STRINGLENGTH]; static char errbuf[STRINGLENGTH]; #if CMUCS int *grps; #endif /* CMUCS */ char *p = NULL; 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 = strchr(nbuf, ','); if (group != NULL) { *group++ = '\0'; account = strchr(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 (pswdp == NULL || strcmp(pwd->pw_passwd, 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 (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); } void goaway(const char *fmt, ...) { char buf[STRINGLENGTH]; va_list ap; va_start(ap, fmt); (void) netcrypt((char *) NULL); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); goawayreason = estrdup(buf); (void) msggoaway(); logerr("%s", buf); longjmp(sjbuf, TRUE); } char * fmttime(time_t time) { static char buf[STRINGLENGTH]; unsigned 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 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 fstatvfs() 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 #endif #define SYMLINK_GRP 64 int local_file(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 . */ 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 (S_ISLNK(sb.st_mode)) 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 fstatvfs() * system call, this will have to do for now. */ #if defined(__SVR4) || __NetBSD_Version__ > 299000900 { struct statvfs sf; if (fstatvfs(handle, &sf) == -1) return (-1); #ifdef __SVR4 return strncmp(sf.f_basetype, "nfs", 3) != 0; #else return strncmp(sf.f_fstypename, "nfs", 3) != 0; #endif } #elif defined(__NetBSD__) { struct statfs sf; if (fstatfs(handle, &sf) == -1) return (-1); return strncmp(sf.f_fstypename, "nfs", 3) != 0; } #else if (major(sb.st_dev) == 255 || major(sb.st_dev) == 130) return (0); else return (1); #endif } /* * 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(struct stat * sb1, struct stat * 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 */ S_ISREG(sb1->st_mode) && /* 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 int link_nofollow(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(int on __unused) { return (0); } #endif /* MACH */ sup-20100519/supmsg.c0000644000000000000000000003551411266442205012756 0ustar rootroot/* $NetBSD: supmsg.c,v 1.17 2009/10/17 22:26:13 christos Exp $ */ /* * 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 * * 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 #include #include #include "libc.h" #include "c.h" #include "supcdefs.h" #include "supextern.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 */ static int refuseone(TREE *, void *); static int listone(TREE *, void *); static int needone(TREE *, void *); static int denyone(TREE *, void *); static int writeone(TREE *, void *); int msgsignon(void) { int x; if (isserver) { 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(void) { int x; if (isserver) { 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 time_t 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(void) { int x; if (isserver) { 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((void *) &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(void) { if (isserver) return (writemint(MSGSETUPACK, setupack)); return (readmint(MSGSETUPACK, &setupack)); } /* * crypt test message */ extern char *crypttest; /* encryption test string */ int msgcrypt(void) { if (isserver) return (readmstr(MSGCRYPT, &crypttest)); return (writemstr(MSGCRYPT, crypttest)); } int msgcryptok(void) { if (isserver) 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(void) { int x; if (isserver) { 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(void) { int x; if (isserver) { 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 /*ARGSUSED*/ refuseone(TREE * t, void *v __unused) { return (writestring(t->Tname)); } int msgrefuse(void) { int x; if (isserver) { 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); name = NULL; x = readstring(&name); } if (x == SCMOK) x = readmend(); } else { x = writemsg(MSGREFUSE); if (x == SCMOK) x = Tprocess(refuseT, refuseone, NULL); 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 time_t scantime; /* time that collection was scanned */ static int /*ARGSUSED*/ listone(TREE * t, void *v __unused) { 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(void) { int x; if (isserver) { x = writemsg(MSGLIST); if (x == SCMOK) x = Tprocess(listT, listone, NULL); 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; 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((void *) &scantime); if (x == SCMOK) x = readmend(); } return (x); } /* * files needed message */ extern TREE *needT; /* tree of files to need */ static int /*ARGSUSED*/ needone(TREE * t, void *v __unused) { int x; x = writestring(t->Tname); if (x == SCMOK) x = writeint((t->Tflags & FUPDATE) != 0); return (x); } int msgneed(void) { int x; if (isserver) { char *name; int update; 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, NULL); 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 /*ARGSUSED*/ denyone(TREE * t, void *v __unused) { return (writestring(t->Tname)); } int msgdeny(void) { int x; if (isserver) { x = writemsg(MSGDENY); if (x == SCMOK) x = Tprocess(denyT, denyone, NULL); 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); name = NULL; x = readstring(&name); } if (x == SCMOK) x = readmend(); } return (x); } /* * send file message */ int msgsend(void) { if (isserver) return (readmnull(MSGSEND)); return (writemnull(MSGSEND)); } /* * receive file message */ extern TREE *upgradeT; /* pointer to file being upgraded */ static int /*ARGSUSED*/ writeone(TREE * t, void *v __unused) { return (writestring(t->Tname)); } int msgrecv(int (*xferfile)(TREE *, va_list), ...) { va_list args; int x; TREE *t = upgradeT; va_start(args, xferfile); if (isserver) { x = writemsg(MSGRECV); if (t == NULL) { if (x == SCMOK) x = writestring((char *) NULL); if (x == SCMOK) x = writemend(); va_end(args); 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(); va_end(args); 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, NULL); if (x == SCMOK) x = writestring((char *) NULL); if (x == SCMOK) x = Tprocess(t->Texec, writeone, NULL); 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) { va_end(args); 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); va_end(args); return (x); } if (x == SCMOK) x = readint(&t->Tmode); if (t->Tmode == 0) { x = readmend(); if (x == SCMOK) x = (*xferfile) (t, args); va_end(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); linkname = NULL; 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); execcmd = NULL; 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(void) { int x; if (protver < 6) { printf("Error, msgdone should not have been called."); return (SCMERR); } if (isserver) { 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(void) { return (writemstr(MSGGOAWAY, goawayreason)); } /* * cross-patch protocol message */ extern int xargc; /* arg count for crosspatch */ extern char **xargv; /* arg array for crosspatch */ int msgxpatch(void) { int x; int i; if (isserver) { 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(void) { if (isserver) return (readmint(MSGCOMPRESS, &docompress)); return (writemint(MSGCOMPRESS, docompress)); } sup-20100519/supmsg.h0000644000000000000000000001306511266065001012753 0ustar rootroot/* $NetBSD: supmsg.h,v 1.7 2009/10/16 12:41:37 christos Exp $ */ /* * 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 * * 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 isserver; /* 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 isserver; /* 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 time_t 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 time_t 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 */ sup-20100519/supscan.c0000644000000000000000000003007411266426413013113 0ustar rootroot/* $NetBSD: supscan.c,v 1.18 2009/10/17 20:46:03 christos Exp $ */ /* * 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 * 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 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 #include #include #include #include #include #include "supcdefs.h" #include "supextern.h" #include "libc.h" #include "c.h" #define PGMVERSION 6 /******************************************* *** D A T A S T R U C T U R E S *** *******************************************/ struct scan_collstruct { /* one per collection to be upgraded */ char *Cname; /* collection name */ char *Cbase; /* local base directory */ char *Cprefix; /* local collection pathname prefix */ struct scan_collstruct *Cnext; /* next collection */ }; typedef struct scan_collstruct SCAN_COLLECTION; /********************************************* *** G L O B A L V A R I A B L E S *** *********************************************/ int trace; /* -v flag */ int quiet; /* -q flag */ SCAN_COLLECTION *firstC; /* collection list pointer */ char *collname; /* collection name */ char *basedir; /* base directory name */ char *prefix; /* collection pathname prefix */ time_t lasttime = 0; /* time of last upgrade */ time_t 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 .list */ TREE *listT; /* final list of files in collection */ TREE *refuseT = NULL; /* list of all files specified by .list */ void usage(void); void init(int, char **); static SCAN_COLLECTION *getscancoll(char *, char *, char *); int localhost(char *); int main(int, char **); /************************************* *** M A I N R O U T I N E *** *************************************/ int main(int argc, char **argv) { SCAN_COLLECTION * volatile c; /* Avoid longjmp clobbering */ #ifdef RLIMIT_DATA struct rlimit dlim; if (getrlimit(RLIMIT_DATA, &dlim) == -1) goaway("Error getting resource limit (%s)", strerror(errno)); if (dlim.rlim_cur != dlim.rlim_max) { dlim.rlim_cur = dlim.rlim_max; if (setrlimit(RLIMIT_DATA, &dlim) == -1) goaway("Error setting resource limit (%s)", strerror(errno)); } #endif 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((time_t *) NULL); if (!quiet) 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((time_t *) NULL); if (!quiet) printf("SUP Scan for %s completed at %s", collname, ctime(&scantime)); } else fprintf(stderr, "SUP: Scan for %s aborted at %s", collname, ctime(&scantime)); if (!quiet) (void) fflush(stdout); } while ((c = firstC) != NULL) { firstC = firstC->Cnext; free(c->Cname); free(c->Cbase); if (c->Cprefix) free(c->Cprefix); free(c); } exit(0); } /***************************************** *** I N I T I A L I Z A T I O N *** *****************************************/ void usage(void) { fprintf(stderr, "Usage: supscan [ -vq ] collection [ basedir ]\n"); fprintf(stderr, " supscan [ -vq ] -f dirfile\n"); fprintf(stderr, " supscan [ -vq ] -s\n"); exit(1); } void init(int argc, char **argv) { char buf[STRINGLENGTH], fbuf[STRINGLENGTH], *p, *q; FILE *f; SCAN_COLLECTION **c; int fflag, sflag; char *filename = NULL; quiet = FALSE; 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 'q': quiet = TRUE; 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 = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; collname = nxtarg(&p, " \t="); p = skipover(p, " \t="); if (!localhost(p)) continue; *c = getscancoll(filename, estrdup(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)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; q = nxtarg(&p, " \t="); p = skipover(p, " \t="); *c = getscancoll(filename, estrdup(q), estrdup(p)); if (*c) c = &((*c)->Cnext); } (void) fclose(f); return; } if (argc < 2 || argc > 3) usage(); firstC = getscancoll(filename, estrdup(argv[1]), argc > 2 ? estrdup(argv[2]) : (char *) NULL); } static SCAN_COLLECTION * getscancoll(char *filename, char *collname, char *basedir) { char buf[STRINGLENGTH], *p, *q; FILE *f; SCAN_COLLECTION *c; if (basedir == NULL) { if ((f = fopen(filename, "r")) != NULL) { while ((p = fgets(buf, STRINGLENGTH, f)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; q = nxtarg(&p, " \t="); if (strcmp(q, collname) == 0) { p = skipover(p, " \t="); basedir = estrdup(p); break; } } (void) fclose(f); } if (basedir == NULL) { (void) sprintf(buf, FILEBASEDEFAULT, collname); basedir = estrdup(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")) != NULL) { while ((p = fgets(buf, STRINGLENGTH, f)) != NULL) { q = strchr(p, '\n'); if (q) *q = 0; if (strchr("#;:", *p)) continue; prefix = estrdup(p); if (chdir(prefix) < 0) { fprintf(stderr, "supscan: can't chdir to %s from base directory %s for %s\n", prefix, basedir, collname); fclose(f); free(prefix); return (NULL); } break; } (void) fclose(f); } if ((c = (SCAN_COLLECTION *) malloc(sizeof(SCAN_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); } void goaway(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); (void) putc('\n', stderr); (void) fflush(stderr); longjmp(sjbuf, TRUE); } int localhost(char *host) { static char myhost[MAXHOSTNAMELEN + 1]; static unsigned int myhostlen; unsigned 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"); } myhost[sizeof(myhost) - 1] = '\0'; 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); } sup-20100519/supservers.80000644000000000000000000001567511273424336013617 0ustar rootroot.\" $NetBSD: supservers.8,v 1.10 2009/11/02 00:33:34 joerg Exp $ .\" .\" 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 .\" Revision 1.3 92/08/11 12:08:50 mrt .\" Documented -C switch .\" [92/08/11 mrt] .\" .TH SUPSERVERS 8 1/16/86 .SH "NAME" supfilesrv, supscan \- sup server processes .SH "SYNOPSIS" supfilesrv [ .I -4 ] [ .I -6 ] [ .I -d ] [ .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 -d 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. .I supfilesrv uses libwrap style access control (the /etc/hosts.allow and /etc/hosts.deny files) with service name "supfilesrv". The -l "log" flag turn on loggin of accepted connections (denied connections are always logged). 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. .I supfilesrv listens to IPv4 listening socket by default. With the -6 flag, it will listen to IPv6 listening socket. For dual stack support you will want to run two instances of .I supfilesrv. .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 /etc/supfiles/coll.dir base directory list for system collections .TP /etc/supfiles/coll.host host name list for system collections .TP \*[Lt]base-directory\*[Gt]/sup/\*[Lt]collection\*[Gt]/* files used by file server (see .I sup(1)) .TP \*[Lt]base-directory\*[Gt]/sup/\*[Lt]collection\*[Gt]/list list file used by .I supscan to create file list .TP \*[Lt]base-directory\*[Gt]/sup/\*[Lt]collection\*[Gt]/scan file list created by .I supscan from list file .DT .PP .SH "SEE ALSO" sup(1) hosts_access(5) hosts_options(5) .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. sup-20100519/vprintf.c0000644000000000000000000000625210405600156013120 0ustar rootroot/* $NetBSD: vprintf.c,v 1.9 2006/03/14 17:42:06 christos Exp $ */ /* * 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 * 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 #include #ifdef _IOSTRG #define STRFLAG (_IOSTRG|_IOWRT)/* no _IOWRT: avoid stdio bug */ #else #define STRFLAG (_IOREAD) /* XXX: Assume svr4 stdio */ #endif #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 = STRFLAG; fakebuf._base = (void *) s; fakebuf._ptr = (void *) 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 = STRFLAG; fakebuf._base = (void *) s; fakebuf._ptr = (void *) s; fakebuf._cnt = n - 1; fakebuf._file = -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 */