File:  [Research Unix] / researchv10no / cmd / odist / src.tar
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

TODO   644   3513      4         417  5032703557   4565 finish new setuid scheme
write document
add security configuration file support
(idea: receive reads this file, which looks like:
local-user remote-system	remote-user	remote-file	actions...)
set up two-pass install/remove scheme
make a backup package before installation
  ������ape/   755   3513      4           0  5032703607   4567 ape/Future/   755   3513      4           0  5031447510   6036 ape/Future/conf.c   644   3513      4        4652  5016334717   7232 #include <ctype.h>
#include <regexp.h>	/* FIXME: use Posix interface. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "conf.h"
#include "dist.h"

static char *
gettok(char *tok, char *src)
{
	while (!isspace(*src)) {
		if (!*src)
			break;
		*tok++ = *src++;
	}
	while (isspace(*src))
		++src;
	return src;
}

/* return the next line of the config file matching the given args.
   and argument can be NULL and will be assumed to match.  the return
   value is in a static data area.  */
struct conf *
confread(FILE *fp, char *host, char *user, char *file)
{
	static char confline[MAXLINE];
	static char confhost[MAXLINE], confuser[MAXLINE], conffile[MAXLINE];
	char *next;
	static struct conf conf = { confhost, confuser, conffile };
	int len, flag;
	regexp *re;
	regsubexp match[1];

	for (;;) {
		if (!fgets(confline, MAXLINE, fp))
			return NULL;
		if (confline[0] == '#')
			continue;
		len = strlen(confline);
		if (confline[len - 1] != '\n') {
			if (feof(fp))
				eprintf("readconf: incomplete last line!");
			else
				eprintf("readconf: line too long or embedded NUL!");
			exit(1);
		}
		next = gettok(confhost, confline);
		next = gettok(confuser, next);
		conf.cmds = gettok(conffile, next);
		if (host) {
			re = regcomp(confhost);
			flag = regexec(re, host, match, 1);
			free(re);
			if (!flag || match[0].ep - match[0].sp != strlen(host))
				continue;
		}
		if (user) {
			re = regcomp(confuser);
			flag = regexec(re, user, match, 1);
			free(re);
			if (!flag || match[0].ep - match[0].sp != strlen(user))
				continue;
		}
		if (file) {
			re = regcomp(conffile);
			flag = regexec(re, file, match, 1);
			free(re);
			if (!flag || match[0].ep - match[0].sp != strlen(file))
				continue;
		}
		return &conf;
	}
}

/* call functions associated with the commands in the given string
   return the total of the return values */
int
confexec(char *cmdstr, struct confcmds cmdtab[])
{
	char cmd[MAXLINE], arg[MAXLINE];
	int i, np, ret;

	ret = 0;
	while (*cmdstr) {
		for (i = 0; isalnum(*cmdstr); ++cmdstr)
			cmd[i++] = *cmdstr;
		cmd[i] = 0;
		if (*cmdstr == '(')
			for (i = 0, np = 1, ++cmdstr; *cmdstr && np; ++cmdstr) {
				if (*cmdstr == '(')
					++np;
				if (*cmdstr == ')' && !--np)
					continue;
				arg[i++] = *cmdstr;
			}
		for (i = 0; cmdtab[i].name; ++i)
			if (!strcmp(cmd, cmdtab[i].name)) {
				ret += (*cmdtab[i].func)(arg);
				break;
			}
		while (*cmdstr && !isalnum(*cmdstr))
			++cmdstr;
	}
	return ret;
}
t i, np, ret;

	ret = 0;
	while (*cmdstr) {
		for (i = 0; isalnum(*cmdstr); ++cmdstr)
ape/Future/conf.h   644   3513      4         676  5016334663   7221 /* structure corresponding to line of the config file */
struct conf {
	char *host;	/* regexp */
	char *user;	/* regexp */
	char *file;	/* regexp */
	char *cmds;	/* cmd+cmd+cmd... */
};

extern struct conf *confread(FILE *fp, char *host, char *user, char *file);

/* configuration command name and associated function to call */
struct confcmds {
	char *name;
	int (*func)(char *);
};

extern int confexec(char *cmdstr, struct confcmds *cmdtab);
= 0;
	while (*cmdstr) {
		for (i = 0; isalnum(*cmdstr); ++cmdstr)
ape/dist.sh   644   3513      4        4306  5032703266   6157 #! /bin/sh -

umask 022

LDIR=%LDIR%
SDIR=%SDIR%
QPREFIX=Q.

PATH=$LDIR:/bin:/usr/bin:/usr/ucb:/usr/bsd
export PATH

DEST=$LDIR/destinations

showq=0
recv=0
notify=0
systems=
usage='usage: dist [-q|-r] [system|-[Ff] file] [-n] [files...]'

while [ $# -gt 0 ]
do
	case "$1" in
	-q)
		showq=1
		;;
	-r)
		recv=1
		;;
	-n)
		notify=1
		;;
	-[Ff])
		if [ $# -lt 2 ]
		then
			echo "$usage" 1>&2
			exit 1
		fi
		if [ x$1 = x-f -a -r "$2" ]
		then
			systems=`cat "$2" 2>/dev/null`
		elif [ -r $DEST/"$2" ]
		then
			systems=`cat $DEST/"$2" 2>/dev/null`
		else
			echo "dist: can't open '$2'" 1>&2
			exit 1
		fi
		shift
		;;
	*)
		if [ "x$systems" != x ]
		then
			break
		fi
		systems="$1"
		;;
	esac
	shift
done

if [ $recv = 1 ]
then
	if [ x"$systems" = x ]
	then
		echo dist: no systems specified 1>&2
		exit 1
	else
		for sys in $systems
		do
			echo $sys:
			connect $sys transmit io receive || exit 1
		done
		exit 0
	fi
fi

if [ $showq = 1 ]
then
	if [ x"$systems" = x ]
	then
		showq
		exit 0
	else
		for sys in $systems
		do
			echo $sys:
			connect $sys showq i /bin/cat
		done
		exit 0
	fi
fi

if [ $# = 0 ]
then
	echo "$usage" 1>&2
	exit 1
fi

# construct spool directory
for d in `echo $$ | awk '{for (i = 0; i < 1000; ++i) printf "%3d%d\n", i, $1}'`
do
	if [ ! -f $SDIR/$QPREFIX$d ]
	then
		dir=$QPREFIX$d
		mkdir $SDIR/$dir && break
		echo "dist: can't make spool directory" 1>&2
		exit 1
	fi
done

data=$SDIR/$dir/data
ctl=$SDIR/$dir/tempctl
files=$SDIR/$dir/files

# use canonical system names.
canon $systems | awk '{for (i = 1; i <= NF; ++i) printf "%d %s\n", ++n, $i}' > $ctl

mkpkg "$@" > $data

pwd=`pwd`
for f in "$@"
do
	case "$f" in
	-*)	# flag to mkpkg
		;;
	/*)
		echo "$f"
		;;
	*)
		echo "$pwd/$f"
		;;
	esac
done | sort > $files

# rename the ctl file to its real name; at this point the package
# is now available for shipment.
mv $ctl $SDIR/$dir/ctl

# supersede old jobs containing the same files
cd $SDIR
for d in $QPREFIX*
do
	test $d = $dir && continue
	test -w $d || continue
	if [ `comm -23 $d/files $dir/files | wc -c` = 0 ]
	then
		sort +1 $d/ctl $dir/ctl | uniq -d -2 |
		while read num sys
		do
			echo superseded by $dir > $d/$num.done
		done
	fi
done

# clean up any jobs we completely superseded.
cleanq

done | sort > $files

# rename the ctl file to its real name; at this point the package
# is now available for shipment.
mv $ctl $SDIR/$dir/ctl

# supersede old jobs containing the same files
cd $SDIR
for d in $QPREFIX*
do
	test $d = $dir && continue
	test -w $d || continue
	if [ `comm -23 $d/files $dir/files | ape/mkfile   644   3513      4        2060  5031455043   6041 <../mkconf.$SYS
<../mkrules.$SYS

CFLAGS=-g
BPROG=dist
LPROG=receive transmit showq cleanq genmail nightly
LSUID=transmit cleanq

LIBOBJ=chat.$O chkperm.$O crc.$O eprintf.$O path.$O scanq.$O tryperm.$O

%.$O: %.c
	$CC -DLDIR='"'$LDIR'"' -DSDIR='"'$SDIR'"' -c $stem.c

%: %.$SH
	sed -e s@%LDIR%@$LDIR@ -e s@%SDIR%@$SDIR@ $stem.$SH > $target || rm -f $target
	chmod +x $target

compile:V: $BPROG $LPROG

install:V: compile
	test -d $LDIR || mkdir $LDIR
	test -d $SDIR || mkdir $SDIR && chmod 777 $SDIR
	cp $BPROG $BDIR
	cp $LPROG $LDIR
	(cd $LDIR; chown root $LSUID; chmod 4755 $LSUID)

receive: receive.$O lib.a ../$SYS/lib.a
	$CC -o receive receive.$O lib.a ../$SYS/lib.a $CCLIB

transmit: transmit.$O lib.a ../$SYS/lib.a
	$CC -o transmit transmit.$O lib.a ../$SYS/lib.a $CCLIB

showq: showq.$O lib.a ../$SYS/lib.a
	$CC -o showq showq.$O lib.a ../$SYS/lib.a $CCLIB

cleanq: cleanq.$O lib.a ../$SYS/lib.a
	$CC -o cleanq cleanq.$O lib.a ../$SYS/lib.a $CCLIB

lib.a: ${LIBOBJ:%=lib.a(%)}
	$RL lib.a

lib.a(%): %
	ar r lib.a $stem

clean:V:
	rm -f $BPROG $LPROG *.[$OS] lib.a
UID; chmod 4755 $LSUID)

receive: receive.$O lib.a ../$SYS/lib.a
	$CC -o receive receive.$O lib.a ../$SYS/lib.a $CCLIB

transmit: transmit.$O lib.a ../$SYS/lib.a
	$CC -o transmit transmit.$O lib.a ../$SYS/lib.a $CCLIB

showq: showq.$O lib.a ../$SYS/lib.a
	$CC -o showq showq.$O lib.a ../$SYS/lib.a $CCLIB

cleanq: cleanq.$O lib.a ../$SYS/lib.a
	$CC -o cleanq cleanq.$O lib.a ../$SYS/lib.a $CCLIB

lib.a: ${LIBOBJ:%=lib.a(%)}
	$RL lib.a

lib.a(%): %
	ar r lib.a $stape/scanq.c   644   3513      4        3466  5032142073   6130 #include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "dist.h"

static char *
copy(char *s)
{
	char *r;

	r = malloc(strlen(s) + 1);
	if (r)
		strcpy(r, s);
	return r;
}

static void
removeq(char *name)
{
	DIR *dp;
	struct dirent *d;
	char file[2 * MAXNAME + 1];

	name = copy(name);	/* readdir bug?!? */
	if (fork() == 0) {
		setuid(getuid());
		execl(LDIR "/genmail", "genmail", "-f", name, (char *) 0);
		exit(0);
	} else
		wait(0);
	if (!(dp = opendir(name)))
		return;
	while (d = readdir(dp)) {
		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
			continue;
		sprintf(file, "%s/%.*s", name, MAXNAME, d->d_name);
		remove(file);
	}
	closedir(dp);
	rmdir(name);
	free(name);
}

void
scanq(char *remsys, void (*func)(char *, int, char *))
{
	DIR *dp;
	struct dirent *d;
	FILE *fp;
	char sys[MAXLINE], cansys[MAXLINE], file[MAXNAME];
	int num, zapq;

	if (remsys)
		canon(remsys, cansys);

	if (chdir(SDIR) < 0) {
		eprintf("can't chdir %s", SDIR);
		exit(1);
	}

	if (!(dp = opendir("."))) {
		eprintf("can't read spool directory!");
		exit(1);
	}

	while (d = readdir(dp))
		if (strncmp(d->d_name, QPREFIX, strlen(QPREFIX)) == 0) {
			zapq = 1;
			if (chdir(d->d_name) < 0) {
				eprintf("can't chdir %s/%s", SDIR, d->d_name);
				continue;
			}
			if (fp = fopen(CTL, "r")) {
				while (fscanf(fp, "%d%s", &num, sys) == 2) {
					sprintf(file, "%d.%s", num, DONE);
					if (access(file, F_OK) == 0)
						continue;
					if (remsys && strcmp(sys, cansys) != 0) {
						zapq = 0;
						continue;
					}
					if (func)
						(*func)(d->d_name, num, sys);
					if (access(file, F_OK) != 0)
						zapq = 0;
				}
				fclose(fp);
			} else
				eprintf("can't read %s/%s", d->d_name, CTL);
			chdir("..");
			if (zapq)
				removeq(d->d_name);
		}

	closedir(dp);
}
		if (fp = fopen(CTL, "r")) {
				while (fscanf(fp, "%d%s", &num, sys) == 2) {
					sprintf(file, "%d.%s", num, DONE);
					if (access(file, F_OK) == 0)
						continue;
					if (remsys && strcmp(sys, caape/eprintf.c   644   3513      4        1030  5020312715   6452 #include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "dist.h"

char *prog;

void
eprintf(char *fmt, ...)
{
	time_t now;
	char mesg[MAXLINE];
	va_list ap;
	static int fd = -1;

	time(&now);
	sprintf(mesg, "%s[%d %.24s]: ", prog, getpid(), ctime(&now));
	va_start(ap, fmt);
	vsprintf(mesg + strlen(mesg), fmt, ap);
	strcat(mesg, "\n");
	write(2, mesg, strlen(mesg));
	if (fd < 0)
		fd = open(SDIR "/log", 1);
	lseek(fd, 0L, 2);	/* we really want O_APPEND mode, but... */
	write(fd, mesg, strlen(mesg));
}
lude <stdio.h>
#include <time.h>
#include <unistd.h>
#include "dist.h"

char *prog;

void
eprintf(char *fmt, ...)
{
	time_t now;
	char mesg[MAXLINE];
	va_list ap;
	static int fd = -1;

	time(&now);
	sprintf(mesg, "%s[%d %.24s]: ", prog, getpid(), ctime(&now));
	va_start(ap, fmt);
	vsprintf(mesg + strlen(mesg), fmt, ap);
	strcat(mesg, "\n");
	write(2, mesg, strlen(mesg));
	if (fd < 0)
		fd = open(SDIR "/log", 1);
	lseek(fd, 0L, 2);	/* we really want O_APPEND mode, but... */
	write(fd,ape/receive.c   644   3513      4        3406  5032661703   6445 #include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "dist.h"

void
recvjob(void)
{
	char data[MAXNAME], errs[MAXNAME], mesg[MAXLINE];
	int dfd, efd, attempt, status;

	if (!getline(mesg))
		exit(0);

	if (sscanf(mesg, "begin job %s", data) != 1) {
		eprintf("job header munged: mesg = %s", mesg);
		exit(1);
	}

	sprintf(data, "data.%d", getpid());
	remove(data);
	dfd = creat(data, 0600); /* ape deficiency */
	close(dfd);
	dfd = open(data, O_RDWR);
	if (dfd < 0) {
		eprintf("can't create data file %s", data);
		exit(1);
	}

	if (!recvfile(dfd)) {
		remove(data);
		eprintf("recvfile failed");
		exit(1);
	}

	/* see if file system permissions will likely allow inspkg to succeed */
	lseek(dfd, 0L, 0);
	attempt = tryperm(dfd);
	sprintf(mesg, "client attempt=%d\n", attempt);
	write(1, mesg, strlen(mesg));

	if (attempt) {
		sprintf(errs, "errs.%d", getpid());
		efd = creat(errs, 0600);	/* more ape bogosity */
		close(efd);
		efd = open(errs, O_RDWR);
		if (efd < 0) {
			eprintf("can't create errs file %s", errs);
			exit(1);
		}

		if (fork()) {
			status = 0xFF; /* evilly catch wait failures */
			wait(&status);
			if (status & 0xFF) {
				sprintf(mesg, "inspkg: exit %d\n", status & 0xFF);
				write(efd, mesg, strlen(mesg));
			}
		} else {
			lseek(dfd, 0L, 0);
			dup2(dfd, 0);
			dup2(efd, 1);
			dup2(efd, 2);
			close(dfd);
			close(efd);
			execl(LDIR "/inspkg", "inspkg", 0);
			eprintf("can't exec inspkg");
			exit(1);
		}

		lseek(efd, 0L, 0);
		if (!sendfile(efd)) {
			remove(data);
			remove(errs);
			eprintf("can't send error log");
			exit(1);
		}
	}

	close(dfd);
	remove(data);
	close(efd);
	remove(errs);
}

int
main(int argc, char *argv[])
{
	prog = argv[0];
	for (;;)
		recvjob();
}
	write(efd, mesg, strlen(mesg));
			}
		} else {
			lseek(dfd, 0L, 0);
			dup2(dfd, 0);
			dup2(efd, 1);
			dup2(efd, 2);
			close(dfd);
			close(efd);
			execl(LDIR "/inspkg", "inspkg", 0);
			eprintf("can't exec inspkg");
			exit(1);
		}

		lseek(eape/tryperm.c   644   3513      4        6311  5027736536   6536 #include <ctype.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "../pkg/ar.h"
#include "dist.h"

/* determine if we can create the given pathname.  not a generally useful
   function since it destroys the pathname in the process... */
static int
cancreate(char *path, int recurse)
{
	char *slash;

	for (;;) {
		slash = strrchr(path, '/');
		if (! slash)
			return 0;	/* supposed to be absolute */
		*slash = '\0';
		if (!*path)
			break;
		if (access(path, W_OK) == 0)
			return 1;
		if (!recurse)		/* for remove we check only one directory */
			return 0;
		if (access(path, F_OK) == 0)
			return 0;
	}
	return access("/", W_OK) == 0;
}
		
/*
 * try the instructions of the package on the given fd against the
 * permissions currently in the file system.  return 1 if we think we
 * ought to go ahead and try inspkg.
 */
int
tryperm(int fd)
{
	char armag[SARMAG];
	struct ar_hdr arhdr;
	long size;
	char temp[L_tmpnam];
	int tfd;
	FILE *tfp;
	int cmd, c, nf, retval;
	char *path;

	/* return 1 so inspkg will be called and barf for us */
	if (read(fd, armag, sizeof armag) != SARMAG || strncmp(armag, ARMAG, SARMAG))
		return 1;
	if (read(fd, (char *) &arhdr, sizeof arhdr) != sizeof arhdr)
		return 1;
	size = strtol(arhdr.ar_size, 0, 10);
	tmpnam(temp);
	close(creat(temp, 0600));	/* ape deficiency */
	tfd = open(temp, O_RDWR);
	if (tfd < 0) {
		eprintf("can't create temp file %s for tryperm", temp);
		remove(temp);		/* just in case something's *real* weird */
		exit(1);
	}
	if (fdcopy(tfd, fd, size, 0) != size) {
		close(tfd);
		remove(temp);
		eprintf("can't extract Instructions in tryperm");
		return 1;		/* inspkg will (presumably) barf for us */
	}
	lseek(tfd, 0L, 0);
	tfp = fdopen(tfd, "r");

	/* now that we have the instructions file, do the real meat.  */
	retval = 1;
	while ((cmd = getc(tfp)) != EOF) {
		switch (cmd) {
		case 'b':	/* b <mode> <dmaj> <dmin> <uid> <gid> <path> */
		case 'c':	/* c <mode> <dmaj> <dmin> <uid> <gid> <path> */
			nf = 6;
			break;
		case 'd':	/* d <mode> <uid> <gid> <path> */
		case 'f':	/* f <component> <uid> <gid> <path> */
			nf = 4;
			break;
		case 'l':	/* l <path1> <path2> */
		case 's':	/* s <path1> <path2> */
			nf = 2;
			break;
		case 'r':	/* r <path> */
		case 'x':	/* x <command> */
		case 'X':	/* X <path> */
			nf = 1;
			break;
		default:
			goto reterr;
		}

		/* get the last field of the line */
		while (nf--) {
			while ((c = getc(tfp)) != EOF)
				if (!isspace(c))
					break;
			if (c == EOF)
				goto reterr;
			ungetc(c, tfp);
			path = getpath(tfp);
		}

		/* eat the newline */
		if (getc(tfp) != '\n')
			goto reterr;

		switch (cmd) {
		case 'X':
		case 'x':
			break;

		case 'r':
			if (access(path, F_OK) != 0)
				break;
			if (cancreate(path, 0))
				break;
			retval = 0;
			goto out;

		default:
			if (cancreate(path, 1))
				break;
			retval = 0;
			goto out;
		}
	}

 out:
	fclose(tfp);
	remove(temp);
	return retval;

 reterr:
	/* there was some kind of bug in the format of the package.  return 1
	   and later on inspkg will generate an appropriate error message to
	   be returned to the remote system */
	fclose(tfp);	
	remove(temp);
	return 1;
}
ase 'x':
			break;

		case 'r':
			if (access(path, F_OK) != 0)
				break;
			if (cancreate(path, 0))
				break;
			retval = 0;
			goto out;

		default:
			if (cancreate(path, 1))
				break;
			retval = 0;
			goto out;
		}
	}

 out:
	fclose(tfp);
	remove(temp);
	return retval;

 reterr:
	/* there was some kindape/dist.h   644   3513      4        1530  5030707254   5767 #define QPREFIX "Q."
#define CTL "ctl"
#define DATA "data"
#define BUSY "busy"
#define DONE "done"
#define FILES "files"

#define MAXLINE 256
#define MAXNAME 20

/* system dependent */
extern void canon(char *sys, char cansys[]);
extern int lcreat(char *name, int mode);

/* chat.c */
extern int getline(char line[]);
extern long fdcopy(int dfd, int sfd, long size, unsigned long *crc);
extern int recvfile(int fd);
extern int sendfile(int fd);

/* chkperm.c */
extern int chkperm(int fd);

/* crc.c */
extern void crcinit(int *aux);
extern unsigned long crcincr(unsigned char *, size_t, unsigned long, int *);

/* eprintf.c */
extern char *prog;
extern void eprintf(char *fmt, ...);

/* path.c */
extern char *getpath(FILE *);

/* scanq.c */
extern void scanq(char *remsys, void (*func)(char *, int, char *));

/* tryperm.c */
extern int tryperm(int fd);
, int sfd, long size, unsigned long *crc);
extern int recvfile(int fd);
extern int sendfile(int fd);

/* chkperm.c */
extern int chkperm(int fd);

/* crc.c */
extern voape/chat.c   644   3513      4        3611  5027732160   5740 #include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include "dist.h"

#define MIN(A, B) ((A) < (B) ? (A) : (B))

int
getline(char line[])
{
	int i;

	i = 0;
	do
		if (read(0, line + i, 1) != 1)
			return 0;
	while (line[i++] != '\n' && i < MAXLINE - 1);
	if (line[i - 1] != '\n')
		return 0;
	line[i] = 0;
	return 1;
}

long
fdcopy(int dst, int src, long size, unsigned long *crc)
{
	char buf[4096];
	long cc, total;
	int aux;

	total = 0;
	if (crc) {
		crcinit(&aux);
		*crc = 0;
	}
	while (total < size) {
		if ((cc = read(src, buf, MIN(sizeof buf, size - total))) <= 0)
			break;
		if (crc)
			*crc = crcincr((unsigned char *) buf, cc, *crc, &aux);
		if (write(dst, buf, cc) != cc)
			break;
		total += cc;
	}
	return total;
}

int
sendfile(int fd)
{
	long len;
	char mesg[MAXLINE];
	unsigned long crc;

	/* size header */
	len = lseek(fd, 0L, 2);
	lseek(fd, 0L, 0);
	sprintf(mesg, "file length=%ld\n", len);
	write(1, mesg, strlen(mesg));

	/* body */
	if (fdcopy(1, fd, len, &crc) != len) {
		eprintf("sendfile fdcopy failure");
		return 0;
	}

	/* crc footer */
	sprintf(mesg, "file crc=%lu\n", crc);
	write(1, mesg, strlen(mesg));

	/* acknowledge */
	if (!getline(mesg) || strcmp(mesg, "ok\n") != 0) {
		eprintf("sendfile acknowledgement failure");
		return 0;
	}

	return 1;
}

int
recvfile(int fd)
{
	long len;
	char mesg[MAXLINE];
	unsigned long crc, trycrc;

	/* size header */
	if (!getline(mesg) || sscanf(mesg, "file length=%ld\n", &len) != 1) {
		eprintf("recvfile header munged");
		return 0;
	}

	/* body */
	if (fdcopy(fd, 0, len, &crc) != len) {
		eprintf("recvfile fdcopy failure");
		return 0;
	}

	/* crc footer */
	if (!getline(mesg) || sscanf(mesg, "file crc=%lu\n", &trycrc) != 1) {
		eprintf("recvfile footer munged");
		return 0;
	}
	if (crc != trycrc) {
		eprintf("recvfile crc failure");
		return 0;
	}

	/* acknowledge */
	sprintf(mesg, "ok\n");
	write(1, mesg, strlen(mesg));
	return 1;
}
 || sscanf(mesg, "file length=%ld\n", &len) != 1) {
		eprintf("recvfile header munged");
		return 0;
	}

	/* body */
	iape/chkperm.c   644   3513      4         135  5030710456   6426 #include <stddef.h>
#include <stdio.h>
#include "dist.h"

int
chkperm(int fd)
{
	return 1;
}
/* crc footer */
	if (!getline(mesg) || sscanf(mesg, "file crc=%lu\n", &trycrc) != 1) {
		eprintf("recvfile footer munged");
		return 0;
	}
	if (crc != trycrc) {
		eprintf("recvfile crc failure");
		return 0;
	}

	/* acknowledge */
	sprintf(mesg, "ok\n");
	write(1, mesg, strlen(mesg));
	return 1;
}
 || sscanf(mesg, "file length=%ld\n", &len) != 1) {
		eprintf("recvfile header munged");
		return 0;
	}

	/* body */
	iape/transmit.c   644   3513      4        2347  5025030057   6661 #include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "dist.h"

static void
sendjob(char *job, int num, char *sys)
{
	char busy[MAXNAME], done[MAXNAME], mesg[MAXLINE];
	int fd, attempt;

	sprintf(busy, "%d.%s", num, BUSY);
	sprintf(done, "%d.%s", num, DONE);

	fd = lcreat(busy, 0600);
	if (fd < 0)
		return;
	dup2(fd, 2);
	close(fd);

	/* avoid race condition */
	if (access(done, F_OK) == 0)
		goto out;

	fd = open(DATA, O_RDONLY);
	if (fd < 0)
		goto out;

	if (!chkperm(fd)) {
		close(fd);
		goto out;
	}

	sprintf(mesg, "begin job %s\n", job);
	write(1, mesg, strlen(mesg));

	if (!sendfile(fd))
		goto err;

	if (!getline(mesg) || sscanf(mesg, "client attempt=%d\n", &attempt) != 1)
		goto err;
	if (!attempt)
		goto out;

	if (!recvfile(2))
		goto err;

	rename(busy, done);

	fd = open("/dev/null", O_WRONLY);
	dup2(fd, 2);
	close(fd);
	return;

 out:
	/* continue with the next job */
	remove(busy);
	return;

 err:
	/* failure that's too hard to resynchronize */
	eprintf("sendjob really barfed");
	remove(busy);
	exit(1);
}

int
main(int argc, char *argv[])
{
	prog = argv[0];
	if (argc < 2) {
		eprintf("usage: transmit system");
		return 1;
	}
	scanq(argv[1], sendjob);
	return 0;
}
= 1)
		goto err;
	if (!attempt)
		goto out;

	if (!recvfile(2))
		goto err;

	rename(busy, done);

	fd = open("/dev/null", O_WRONLY);
	dup2(fd, 2);
	close(fd);
	return;

 out:
	/* continue with the next job */
	remove(busy);
	return;

 err:
	/* failure that's too hard to resynchroape/showq.c   644   3513      4         352  5030710545   6136 #include <stddef.h>
#include <stdio.h>
#include "dist.h"

static void
showq(char *job, int num, char *sys)
{
	printf("%s: %d %s\n", job, num, sys);
}

int
main(int argc, char *argv[])
{
	prog = argv[0];
	scanq(0, showq);
	return 0;
}
)
		goto err;
	if (!attempt)
		goto out;

	if (!recvfile(2))
		goto err;

	rename(busy, done);

	fd = open("/dev/null", O_WRONLY);
	dup2(fd, 2);
	close(fd);
	return;

 out:
	/* continue with the next job */
	remove(busy);
	return;

 err:
	/* failure that's too hard to resynchroape/TODO   644   3513      4         330  5023514043   5312 Pervasive error checking:

* dist.sh
	check exit code of mkpkg and other programs; don't
	make a valid queue entry unless everything went perfectly.
* scanq.c transmit.c:
	inspect for places that need error checking
wq);
	return 0;
}
)
		goto err;
	if (!attempt)
		goto out;

	if (!recvfile(2))
		goto err;

	rename(busy, done);

	fd = open("/dev/null", O_WRONLY);
	dup2(fd, 2);
	close(fd);
	return;

 out:
	/* continue with the next job */
	remove(busy);
	return;

 err:
	/* failure that's too hard to resynchroape/path.c   644   3513      4        4341  5027737356   5772 /* brutally hacked from ../pkg/path.c */

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "dist.h"

#define CHUNK 64

static char *r;
static unsigned size;

static char *
ralloc(char *ptr, size_t size)
{
	char *result;

	if (!ptr)
		result = malloc(size);
	else
		result = realloc(ptr, size);
	if (!result) {
		eprintf("out of memory in getpath");
		exit(1);
	}
	return result;
}

char *
getpath (FILE *file)
{
	register int c;
	register int len = 0;

	c = getc (file);

	while (!isspace(c) && c != EOF) {
		register int i = 0, n = 0;

		/* determine the next input character */
		if (c == '\\') {
			c = getc (file);
			switch (c) {

			case '\\':
				break;
			
			case 'n':
				c = '\n';
				break;

			case 'r':
				c = '\r';
				break;

			case 't':
				c = '\t';
				break;

			case 'b':
				c = '\b';
				break;
			
			case 'f':
				c = '\f';
				break;
			
			case 'v':
				c = '\v';
				break;
			
			case ' ':
			     /* c = ' '; */
				break;

			default:
				while (c >= '0' && c <= '7' && i < 3) {
					n = (n << 3) + c - '0';
					i++;
					c = getc (file);
				}
				ungetc (c, file);
				c = n;
				break;
			}
		}

		/* ensure there's room in the buffer */
		if (len >= size)
			r = ralloc (r, size += CHUNK);

		/* put the character in the buffer */
		r[len++] = c;

		/* read the next character */
		c = getc (file);
	}

	/* unless we hit eof, we read one character too far. */
	if (c != EOF)
		ungetc (c, file);
	
	/* put a final null into the buffer */
	if (len >= size)
		r = ralloc (r, size += CHUNK);
	r[len] = '\0';

	return r;
}

void
putpath (FILE *file, char *path)
{
	register char *p = path;
	register int c;
	
	while ((c = *p++) != NULL) {
		switch (c) {

		case '\n':
			fprintf (file, "\\n");
			break;

		case '\r':
			fprintf (file, "\\r");
			break;

		case '\b':
			fprintf (file, "\\b");
			break;

		case '\t':
			fprintf (file, "\\t");
			break;

		case '\f':
			fprintf (file, "\\f");
			break;
		
		case '\v':
			fprintf (file, "\\v");
			break;
		
		case '\\':
			fprintf (file, "\\\\");
			break;
		
		case ' ':
			fprintf (file, "\\ ");
			break;
		
		default:
			if (iscntrl (c))
				fprintf (file,
				    *p >= '0' && *p <= '7'? "\\%.3o": "\\%o",
				    c);
			else
				putc (c, file);
			break;
		}
	}
}
e '\r':
			fprintf (file, "\\r");
			break;

		case '\b':
			fprintf (file, "\\b");
			break;

		case '\t':
			fprintf (file, "\\t");
			break;

		case '\f':
			fprintf (file, "\\f");
			break;
		
		case '\v':
			fprintf (file, "\\v");
			break;
		
		case '\\':
			fprintf (file, "\\\\")ape/crc.c   644   3513      4        7124  5030710503   5562 #include <stddef.h>
#include <stdio.h>
#include "dist.h"

/* CRC table for cksum from IEEE 1003.2 draft 11. */
const unsigned long crctab[] = {
	0x7FFFFFFF, 0x77073096, 0xEE0E612C, 0x990951BA,
	0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
	0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
	0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
	0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
	0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
	0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
	0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
	0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
	0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
	0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
	0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
	0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
	0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
	0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
	0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
	0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
	0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
	0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
	0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
	0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
	0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
	0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
	0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
	0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
	0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
	0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
	0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
	0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
	0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
	0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
	0xB3667A2E, 0xC4619AB8, 0x5D681B02, 0x2A6F2B94,
	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};

void
crcinit(int *aux)
{
	*aux = 0;
}

/* incrementally compute crc for part of a block */
unsigned long
crcincr(unsigned char *addr, size_t size, unsigned long crc, int *aux)
{
	int i;

	while (size--) {
		i = (crc >> 24) ^ *addr++;
		if (i == 0) {
			i = (*aux)++;
			if (*aux >= sizeof crctab / sizeof crctab[0])
				*aux = 0;
		}
		crc = (crc << 8) ^ crctab[i];
	}
	return crc;
}
, 0x54DE5729, 0x23D967BF,
	0xB3667A2E, 0xC4619AB8, 0x5D681B02, 0x2A6F2B94,
	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
};

void
crcinit(int *aux)
{
	*aux = 0;
}

/* incrementally compute crc for part of a block */
unsigned long
crcincr(unsigned char *addr, size_t size, unsigned long crc, int *aux)
{
	int i;

	while (size--) {
		i = (crc >> 24) ^ *addr++;
		if (i == 0) {
			i = (*aux)++;
			if (*aux >= sizeof crctab / siape/genmail.sh   644   3513      4        1605  5031142116   6615 #! /bin/sh -
# send mail to a user for the given job
# option -f: say this is the final report
exec 2>> %SDIR%/log

PATH=%LDIR%:/bin:/usr/bin:/usr/ucb:/usr/bsd
cd %SDIR%

if [ "x$1" = x-f ]
then
	shift
	final=1
else
	final=0
fi

if [ $# != 1 ]
then
	exit 1
fi

user=`ls -ld $1 | awk '{print $3}'`
host=`hostname`

trap 'rm -f /tmp/genmail.$$' 0 1 2 3
rm -f /tmp/genmail.$$

if [ $final = 0 ]
then
	echo current status report of dist job $host!$1
else
	echo final status report of dist job $host!$1
fi > /tmp/genmail.$$

while read num sys
do
	if [ -f $1/$num.mail ]
	then
		:
	else
		if [ -s $1/$num.done ]
		then
			echo $sys completed with errors:
			sed 's/^/	/' $1/$num.done
			touch $1/$num.mail
		elif [ -f $1/$num.done ]
		then
			echo $sys completed successfully.
			touch $1/$num.mail
		else
			echo $sys not completed.
		fi
	fi
done < $1/ctl >> /tmp/genmail.$$

mail $user < /tmp/genmail.$$
 ]
then
	echo current status report of dist job $host!$1
else
	echo final status report of dist job $host!$1
fi > /tmp/genmape/nightly.sh   644   3513      4         173  5021521457   6646 #! /bin/sh -
# nightly shell script to send mail for unfinished jobs
cd %SDIR%
for job in Q.*
do
	%LDIR%/genmail $job
done
d with errors:
			sed 's/^/	/' $1/$num.done
			touch $1/$num.mail
		elif [ -f $1/$num.done ]
		then
			echo $sys completed successfully.
			touch $1/$num.mail
		else
			echo $sys not completed.
		fi
	fi
done < $1/ctl >> /tmp/genmail.$$

mail $user < /tmp/genmail.$$
 ]
then
	echo current status report of dist job $host!$1
else
	echo final status report of dist job $host!$1
fi > /tmp/genmape/cleanq.c   644   3513      4         211  5031454571   6237 #include <stddef.h>
#include <stdio.h>
#include "dist.h"

int
main(int argc, char *argv[])
{
	prog = argv[0];
	scanq(0, 0);
	return 0;
}

			sed 's/^/	/' $1/$num.done
			touch $1/$num.mail
		elif [ -f $1/$num.done ]
		then
			echo $sys completed successfully.
			touch $1/$num.mail
		else
			echo $sys not completed.
		fi
	fi
done < $1/ctl >> /tmp/genmail.$$

mail $user < /tmp/genmail.$$
 ]
then
	echo current status report of dist job $host!$1
else
	echo final status report of dist job $host!$1
fi > /tmp/genmdoc.ms   644   3513      4        1177  5032532571   5223 .TL
A System for Automatic Source Distribution
.AU
Mike Haertel
.AI
AT&T Bell Laboratories
Murray Hill, NJ  07974
.AB
.\"
.\" "Single Heterogeneous network seeks automatic software distribution mechanism..."
.\"	\(em Greg Lindahl
.\"
With the advent of wildly heterogeneous networks, automatic software
distribution has become a nightmare.  Binaries are useless, and source
code often fails to recompile across ostensibly standard systems.
Finally, security is, as always, a concern, especially when the automatic
installation of priviliged system software is desired.  We describe
yet another attempt to address some of these issues.
.AE
Single Heterogeneous network seeks automatic software distribution mechanism..."
.\"	\(em Greg Lindahl
.\"
With the advent of wildly heterogeneous networks, automatic software
distribution has become a nightmare.  Binaries are useless, and source
code often fails to recompile across ostensibly standard systems.
Finally, security is, as always, a concern, especially when the automatigenmkfile.sh   644   3513      4         721  5031150727   6362 #! /bin/sh
echo "<mkconf.$1" > mkfile

cat << 'EOF' >> mkfile
DIRS=ape pkg $SYS

%-compile:V: paths.h
	cd $stem; mk compile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatiman/   755   3513      4           0  5031450027   4567 man/dist.1   644   3513      4        3344  5031462000   5677 .TH DIST 1
.SH NAME
dist \(mi distribute files to remote systems
.SH SYNOPSIS
.\".BI "dist [ " system " | -[Ff] " file " ] [ -n ] " files
.BI "dist [ " system " | -[Ff] " file " ] " files
.PP
.B "dist -q ["
.I system
.B "| -[Ff]"
.I file
.B "]"
.PP
.B "dist -r ["
.I system
.B "| -[Ff]"
.I file
.B "]"
.SH DESCRIPTION
.I Dist
distributes files to other systems, where they are installed
under the same names.
.I Dist
operates by packaging the files with
.IR mkpkg (1),
and queuing the resulting package in a spool directory to be
picked up by the remote systems.
.PP
The remote systems' names are given as a single argument, containing
the system names (in the format of
.IR ipc (3))
separated by white space; alternatively, the
.B -f
option may be used to specify a file containing a list of system names.
The
.B -F
option is identical to
.B -f
except
.I dist
looks for the file in a standard directory.
.PP
The
.I dist
command has two forms of use.  In the first form,
.I dist
packages a group of files and queues them for transmission.
.\"If the
.\".B -n
.\"option is specified, the remote systems are notified that the package
.\"is available.
The
.I file
arguments may be either file names or options for
.IR mkpkg (1).
.PP
When 
.B -q
is given,
.I dist
queries the named systems and displays the contents of their transmission
queues; if no systems are given the local queue is displayed
by default.
.PP
When
.B -r
is given,
.I dist
calls the named system and installs any packages it has queued for
the local system.
.SH EXAMPLES
Distribute a new binary for grep to all vaxes:
.IP
.B "dist -F vaxes /bin/grep"
.SH FILES
.B /usr/lib/dist/*
.br
.B /usr/lib/dist/destinations/*
.br
.B /usr/spool/dist/*
.SH "SEE ALSO"
.IR mkpkg (1),
.IR dist (5),
.IR dist (8)
I dist
queries the named systems and displays the contents of their transmission
queues; if no systems are given the local queue is displayed
by default.
.PP
When
.B -r
is given,
.I dist
calls the named system and installs any packages it has queued for
the local system.
.SH EXAMPLESman/dist.5   644   3513      4        3634  5017041737   5723 .TH DIST 5
.SH NAME
dist \(mi spool directory structure for
.B dist
.SH SYNOPSIS
.ds sd /usr/spool/dist
.B \*(sd/Q.*/
.PP
.B \*(sd/Q.*/ctl
.PP
.B \*(sd/Q.*/data
.PP
.B \*(sd/Q.*/files
.PP
.B \*(sd/Q.*/[1-9]*.busy
.PP
.B \*(sd/Q.*/[1-9]*.done
.SH DESCRIPTION
The
.I dist
spool directory contains distributions queued for transmission
to remote systems, and is also used as the working directory when
unpacking distributions received from remote systems.
.PP
Each job has its own subdirectory
of the spool directory.  Several files with conventional names
appear in this per-job directory, as well as files with
generated names containing status information for each remote
system in the job.
.PP
The files in a job's spool directory include:
.TP
.B ctl
The control file contains a list of identifying numbers
and remote system names.  The identifying number
is used in file names containing status information for corresponding
remote system, since network names may not be legal file names.
The file contains a sequence of lines; each line contains
an identifying number, a space, and the corresponding remote system name.
.TP
.B data
The data file contains the output of
.IR mkpkg (1)
for the distribution.
.TP
.B files
A list of file names specified in the command line
that created the job.  This is mainly used as a key
for superseding jobs:  if a new job is created that
contains a superset of the files of some old
job, the old job is marked as completed for all remote
systems it has in common with the new job.
.TP
.B [1-9]*.busy
An empty lock file indicating that the identified system
is currently receiving the distribution.
.TP
.B [1-9]*.done
Status file indicating that the identified system is
finished with the distribution.  This file is empty
if and only if the distribution was successfully installed;
otherwise it contains any error messages from the remote
system.
.SH FILES
.B \*(sd/*
.SH "SEE ALSO"
.IR dist (1),
.IR dist (8)
b is marked as completed for all remote
systems it has in common with the new job.
.TP
.B [1-9]*.busman/dist.8   644   3513      4        7340  5017051644   5722 .TH DIST 8
.ds ld /usr/lib/dist
.SH NAME
connect, dispatch \(mi generic network client and server
.PP
query, receive, notify \(mi network clients
.PP
answer, transmit, notified \(mi network servers
.SH SYNOPSIS
.B \*(ld/connect
.I remote-system remote-cmd io local-cmd local-args
.PP
.B \*(ld/query
.PP
.B \*(ld/receive
.I package-id
.PP
.B \*(ld/notify
.I package-id
.PP
.B \*(ld/dispatch
.I remote-system remote-user
.PP
.B \*(ld/answer
.I remote-system remote-user
.PP
.B \*(ld/transmit
.I remote-system remote-user
.PP
.B \*(ld/notified
.I remote-system remote-user
.SH DESCRIPTION
These programs act behind the scenes on behalf of
.IR dist (1).
.I Connect
and
.I dispatch
deal with all the details of establishing and authenticating connections
on the network.  The remaining programs are independent of the underlying
network.
.PP
.I Connect
encapsulates all the details of making a call on the underlying network.
Its arguments are mostly self explanatory.
.I Remote-cmd
must be one of
.BR answer ", " transmit ", or " notified "."
If
.I io
is
.BR i ,
the standard input of the local command is connected
to the standard output of the remote command.  If
.B i
is not specified, the local command inherits its local
standard input, and the remote command has its standard
output directed to a log file.
Similarly,
.B o
means the standard output of the local command is connected
to the standard input of the remote command.  If
.B o
is not specified, the local command inherits its local
standard output, and the remote command has its standard
input attached to
.BR /dev/null .
Legal possibilities are
.BR i ,
.BR o ,
and
.BR io.
.PP
.I Dispatch
is intended to be called by a generic network daemon
such as
.IR svcmgr (8).
It talks to
.I connect
and takes care of establishing the appropriate standard input and
output before calling
.IR answer ,
.IR transmit ,
or
.IR notified .
.I Dispatch
expects arguments giving the remote system, remote user, and remote
address, and passes these to whatever program it calls.
.PP
.I Query
is a simple program called by
.I connect
with its standard input attached to the remote
.IR answer .
.I Query
displays a formatted version of the queue list from the remote machine.
(It may even turn out to be the same as
.BR /bin/cat .)
.PP
.I Receive
is a more complicated program that is called by
.I connect
with both its input and output attached to the remote
.IR transmit .
.I Receive
performs actual software installation and sends a transcript of any
errors back to the remote system.
.PP
.I Notify
is a simple program called by
.I connect
with its standard output attached to the remote
.IR notified .
.I Notify
sends an announcement of the availability of some specific package.
.PP
All of the servers read a configuration file,
.BR \*(ld/conf ,
to determine how to handle installation on behalf
of a given remote system and user.  The file consists of lines
containing patterns and actions.  Empty lines or lines beginning
with a '\c
.BR "#" "'"
are ignored.  The first three fields (separated by white space)
of each line are regular
expressions to be matched the remote system name, remote user name,
and file name respectively.  The first line in which all three match
will be chosen.
The remainder of the line contains
the associated actions.
Each action is an alphanumeric name, optionally followed immediately
by a parenthesized argument.
.PP
Someday the actions will be enumerated here, but I don't know what
they are yet.
.SH EXAMPLES
A simple configuration file:
.EX
.ta \w'00000000'u +\w'00000000'u +\w'00000000'u +\w'00000000'u +\w'00000000'u +\w'00000000'u
# system	user		pathname	action
# we are willing to distribute stuff to coma and pyxis.
(coma|pyxis)	.*		.*		accept(yes)
\&.*		.*		.*		accept(no)
.EE
.SH "SEE ALSO"
.IR dist (1),
.IR dist (5)
ach action is an alphanumeric name, optionally followed immediately
by a parenthesized argument.
.PP
Someday the actions will be enumerated here, but I don't know what
they are yet.
.SH EXAMPLES
A simple configuration file:
.EX
.ta \w'00000000'u +\w'00000000'u +\w'00000000'u +\w'00000000mkconf.bsd   644   3513      4         106  5031147027   6030 SYS=bsd
BDIR=/usr/mjh/bin
LDIR=/usr/mjh/dist
SDIR=/usr/mjh/dist/spool
 pkg $SYS

%-compile:V: paths.h
	cd $stem; mk compile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatimkconf.sysv   644   3513      4          73  5031452264   6251 SYS=sysv
BDIR=/v/bin
LDIR=/v/lib/dist
SDIR=/usr/spool/dist
dist/spool
 pkg $SYS

%-compile:V: paths.h
	cd $stem; mk compile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatimkconf.v10   644   3513      4          76  5031450436   5655 SYS=v10
BDIR=/usr/bin
LDIR=/usr/lib/dist
SDIR=/usr/spool/dist
t/spool
 pkg $SYS

%-compile:V: paths.h
	cd $stem; mk compile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatimkrules.bsd   644   3513      4          57  5031147365   6227 CC=cc -g
CCLIB=
O=o
OS=o
SH=sh
AR=ar
RL=ranlib
usr/spool/dist
t/spool
 pkg $SYS

%-compile:V: paths.h
	cd $stem; mk compile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatimkrules.sysv   644   3513      4          64  5031457630   6460 CC=cc -g -I../sysv
CCLIB=
O=o
OS=o
SH=sh
AR=ar
RL=:
pool/dist
t/spool
 pkg $SYS

%-compile:V: paths.h
	cd $stem; mk compile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatimkrules.v10   644   3513      4         166  5032136552   6103 CC=/usr/ape/apebin/pcc -g -D_POSIX_SOURCE -D_RESEARCH_SOURCE
CCLIB=/usr/ape/lib/libv.a
O=o
OS=o
SH=sh
AR=ar
RL=ranlib
mpile

%-install:V: %-compile
	cd $stem; mk install

%-clean:V:
	cd $stem; mk clean

ape-compile pkg-compile:Pexit 1: $SYS-compile

compile:V: ${DIRS:%=%-compile}

install:V: ${DIRS:%=%-install}

clean:V: ${DIRS:%=%-clean}
	rm -f paths.h

paths.h: mkconf.$SYS
	echo '#define LDIR "'$LDIR'"' > paths.h
	echo '#define SDIR "'$SDIR'"' >> paths.h
EOF
always, a concern, especially when the automatinotes/   755   3513      4           0  5031450036   5144 notes/IDEAS   644   3513      4        1446  5013610625   6010 Use APE everywhere.  Keep inspkg, mkpkg, seal, and unseal essential unchanged
from old ASD stuff.

Client distributee calls distributor rather than vice versa;
eliminate the need for trust.

Eliminate the crypto stuff; nobody uses it.  Either that or figure out
a good way to put it in avoiding the problem Dennis mentioned about
delayed replies.

What about user ids and group ids?  There seem to be some hacks
for when running setuid under Unix.  Does any of that mean anything
real, or is it just feeping creaturism?

Take out the feature for shipping special files--there is no
real support of special files in APE, and we want to run under
that everywhere.  If you really want to you can ship a script
to make special files on the remote machine anyway.  (How calvinist
are you feeling, Andrew asks?)
 the problem Dennis mentioned about
delayed replies.

What about user ids and group ids?  There seem to be some hacks
for when running setuid under Unix.  Does any of that mean anything
real, or is it just feeping creanotes/PLAN   644   3513      4        6110  5012057047   5710 The ship system will live in two places, the library directory $L (typically
/usr/lib/ship) and the spool directory $S (typically /usr/spool/ship).
Operations are of two classes: client functions and server functions.
A single machine may operate as both a client and a server.  The whole
setup is controlled by a single configuration file, $L/conf.

The configuration file consists of a sequence of pattern lines interspersed
with definitions pertaining to clients or servers matching the patterns.

Patterns are of the form 'key: match (match ...) (key: match ...)'; the whole
pattern may be prefixed by an exclamation point to negate it.  Definitions
are of the form var=value, in shell syntax, and appear one to a line prefixed
by a tab character.

Each match is a restricted globbing expression, of the form understood by the shell.

Client and server programs scan the configuration file in order, choosing
only the first configuration that applies to a given situation.

Lines beginning with a # are comments.

For example, the following excerpt might occur in the configuration file of
a sources repository machine.

	# We accept connections from client1, client2, and client3.
	client: client1 client2 client3
		accept=yes
	client: *
		accept=no
	# We periodically poll server1, which sends us some stuff now and then.
	poll: server1
		poll=hourly
	# The user fred on server1 is a klutz.
	server: server1 user: fred
		accept=no
	# We also don't accept stuff from guests.
	server: server1 group: guest
		accept=no
	# This line applies if none of the rejections above do.
	server: server1
		accept=yes

For each configuration (server, client, poll, or other to be invented), some
assignments may be optional and others mandatory.  For example, for client:
and server: configurations, the 'accept=' assignment is probably mandatory.
However, for clients the 'notify=' (do we notify them when we have a new package
for them, or do we wait for them to call?) is optional and defaults (probably)
to 'no'.

One uniform option understood by all configuration types is the 'transport='
option, which specifies a program to use to place the network call.  On most
machines this will probably be subsumed by the networking library, but some
might require special treatment.

There should be some sort of mechanism for file inclusion.  This would allow
system administrators to delegate administration of some aspects of the system
to other users without actually granting write permission for the $L/conf file.

Some specific programs include:

$L/poll - a program run periodically on clients to poll appropriate servers
$L/client - a program run on the client to accept a shipment from a particular server
$L/server - the program run on the server that actually makes shipments
$L/notify - a program run on the server to notify clients
$L/notified - notify's peer on clients

The spool directory will be organized to have one subdirectory for each
unfinished job.  Each job's subdirectory will contain a data file and
control files for each client.  This organization makes it easy to
atomically access and modify the status of any ongoing job.
 program run on the client to accept a shipment from a particular server
$L/server - the program run on the server that actually makes shipments
$L/notify - a program run on the server to notify clients
$L/notified - notify's peer on clients

The spool directory will be organized to have one subdirectory for each
unfinished job.  Each job's subdirectory will contain a data file and
control files for each client.  This organization makesnotes/PLAN2   644   3513      4        6620  5015021031   5763 The nasd (pronounced "nasty") system will live in two places, the library
directory $L (typically /usr/lib/nasd) and the spool directory $S (typically
/usr/spool/nasd).

Operations are of two classes: client functions, and server functions.
A machine may act as both a client and a server.

The user interface to the system is the 'dist' command (details to be worked out,
but mostly like ship, except the destination is taken from argument(s) rather than
the environment).

Several programs work behind the scenes:

$L/connect - make a network connection and call $L/query, $L/receive, or $L/notify
$L/query - query a server for pending jobs
$L/receive - request a package from a server and optionally install it
$L/notify - notify a client that a package is a available

$L/dispatch - dispatch incoming network connections to $L/answer, $L/send, or $L/notice
$L/answer - the server for query
$L/send - the server for receive
$L/notice - the server for notify

The network programs are organized so they can work on a batch network as well
as an interactive network.  $L/query, $L/receive expect only input from the
network connection; $L/connect passes any initial arguments to the remote server.
$L/notify produces only output for the network connection.

$L/dispatch, $L/answer, $L/send, and $L/notice are similarly organized.

The whole thing is driven by a configuration file $L/conf describing the
allowed operations to be requested by remote machines.  The format of the
file is as follows:  Lines beginning with a # are comments and are ignored.
Other lines are of the form:

	service system user pathname action

Service is "server" or "client"; system, user, and pathname are regular
expressions, and action is a list of actions, separated by +.  A sample
configuration file might be:

	# service	system		user	pathname	action

	# we are willing to distribute stuff to coma and pyxis.
	server		(coma|pyxis)	.*	.*		accept(yes)
	server		.*		.*	.*		accept(no)
	
	# we don't like fred
	client		.*		fred	.*		accept(no)
	# we also refuse to accept stuff from root as a matter of principle
	client		.*		root	.*		accept(no)
	# stuff from bowell!mjh is installed in /usr/bin as root.
	client		bowell		mjh	/usr/bin/.*	accept(yes)+user(root)
	# we accept files in /usr/pub from anyone on alice, but we don't
	# execute random commands for them
	client		alice		.*	/usr/pub/.*	accept(yes)+cmds(no)

The configuration file is scanned for the first match to get actions.  If no
match is found the request is rejected.  Some actions, such as "accept", must
always be provided; others, such as "cmds" have defaults or are otherwise
	# service	system		user	pathname	action

	# we are willing to distribute stuff to coma and pyxis.
	transmit	(coma|pyxis)	.*	.*		accept(yes)
	transmit	.*		.*	.*		accept(no)
	
	# we don't like fred
	receive		.*		fred	.*		accept(no)
	# we also refuse to accept stuff from root as a matter of principle
	receive		.*		root	.*		accept(no)
	# stuff from bowell!mjh is installed in /usr/bin as root.
	receive		bowell		mjh	/usr/bin/.*	accept(yes)+user(root)
	# we accept files in /usr/pub from anyone on alice, but we don't
	# execute random commands for them
	receive		alice		.*	/usr/pub/.*	accept(yes)+cmds(no)

The configuration file is scanned for the first match to get actions.  If no
match is found the request is rejected.  Some actions, such as "accept", must
always be provided; others, such as "cmds" have defaults or are otherwise
unnecessary.
 stuff from bowell!mjh is installed in /usr/bin as root.
	receive		bowell		mjh	/usr/bin/.*	accept(yes)+user(rootnotes/PLAN2+   644   3513      4           0  5012311223   5742 notes/STRATEGY   644   3513      4        2401  5022742334   6420 The client loop:

	* for each package it receives, it checks if file system permissions
	will permit that package to be installed.  if not, it rejects the
	package and the server will retransmit it at a later date.
	* it makes a backup package.
	* it actually installs the package.  if installation fails, it installs
	the backup package and reports errors to the server.

The server loop:
	* for each queued package matching the remote system name, check if
	the current user has read access to each component of the package.
	if not, continue with the next package.
	* transmit the package.
	* wait for the client to check file system permissions against the package.
	the client may decide not to try installing it.  if so, defer the package
	until later, and continue with the next package.
	* the client has decided to install the package.  record the error
	transcript the client returns (if any), and mark the package as done
	for that system.  (if it was the last outstanding system for the given
	package, send mail to the owner of the package saying it was done.)

spool directory management:
	* the spool directory and all files therein are owned by daemon.
	the queue maker and the file server run setuid daemon so they can
	make and remove queue entries respectively.
ue with the next package.
	* the client has decided to install the package.  record the error
	transcript the client returns (if any), and mark the package as done
	for that system.  (if it was the last outstanding system for the given
	package, send mailnotes/TODO   644   3513      4         511  5020574003   5675 Figure out which regexp library to use.  POSIX mandates one.
Perhaps I should write it.

Use alarm() on network reads and writes.

Write educated mkfiles.

Replace NAME_MAX with something that might be less
pessimly large, considering that we have control over
all file names in use.

Add cleanq to the man page.
Also add canon.
ge.  record the error
	transcript the client returns (if any), and mark the package as done
	for that system.  (if it was the last outstanding system for the given
	package, send mailpkg/   755   3513      4           0  5032703620   4576 pkg/HISTORY   644   3513      4        3472  5013610562   5756 04/20/82	Initial version.
05/24/82	Added -b option for backup, created local versions
		of tmpnam and ftw functions.
06/10/82	Handle strange characters in names.
08/04/82	Packaging a nonexistent file arranges to delete
		the file during installation.
03/02/83	Handle character uid/gid not present on host
05/02/83	Added seal, unseal.
05/03/83	Split asd command into mkpkg, inspkg; general cleanup
05/12/83	In asdrcv, make separate keyfiles and permfiles.
05/15/83	Seal and unseal now handle lines beginning with "From"
08/26/83	Handle \ in file names properly
08/27/83	Ship is now a real command (well, a shell script...)
		Asdrcv now looks in /etc/asd/keys and /etc/asd/perm.
09/10/83	It is now possible to package and install special files.
09/15/83	Asdrcv no longer passes -v to inspkg.
09/23/83	Renamed tmpnam to tmpname to avoid conflicts.
09/24/83	Change SIG_TYP to Sig_typ and declare it ("portability").
04/08/85	Change BMASK to BYTEMASK to avoid clashes with system.
04/10/85	Robustness changes in ship.sh
06/29/85	Makefile now conforms to reality again.
09/10/85	Handle symbolic links in package.c, inspkg.c, mkdir.c
09/10/85	Path.c accounts for \v
09/25/85	added -x and -X to mkpkg and inspkg for execution after installation
09/25/85	asdrcv now sends back stdout as well as stderr
01/29/86	ftw.c now closes directory before calling FTW_DP
05/29/86	numuid() and numgid() return real rather than
		effective uid and gid on failure
07/04/86	adapted to UNIX PC
07/25/86	reworked system configuration stuff
09/06/86	removed duplicate free() in inspkg.c
09/11/86	arguments to struid() and strgid() should be unsigned
09/25/86	allow imbedded '.' and '-' in machine and user names
11/18/86	inspkg checks for error returns when closing files
01/20/89	more portable installation procedure
01/20/89	remove a special file before trying to install it
lling FTW_DP
05/29/86	numuid() and numgid() return real rather than
		effective uid and gid on failure
07/04/86	adapted to UNIX PC
07/25/86	reworked system configuration stuff
09/06/86	removed duplipkg/TODO   644   3513      4         276  5013610563   5342 Fix up the #include files so they aren't so redundantly included.

Make schk() and nchk() more informative.

Look into Sig_type.

Declare all the externs from "asd.h" in appropriate places.
when closing files
01/20/89	more portable installation procedure
01/20/89	remove a special file before trying to install it
lling FTW_DP
05/29/86	numuid() and numgid() return real rather than
		effective uid and gid on failure
07/04/86	adapted to UNIX PC
07/25/86	reworked system configuration stuff
09/06/86	removed duplipkg/alloc.c   644   3513      4        1014  5013610563   6117 /*
 *	storage allocator
 *
 *	calls malloc or realloc and aborts if unsuccessful
 */

#include "asd.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void *
alloc (size_t n)
{
	register void *p;

	p = malloc (n);
	schk (p);
	return p;
}

void *
ralloc (void *s, size_t n)
{
	register void *p;

	if (s == NULL)
		return alloc (n);
	
	p = realloc (s, n);
	schk (p);
	return p;
}

/* return a copy of a string */
char *
copy (char *s)
{
	register char *r;
	r = alloc (strlen (s) + 1);
	strcpy (r, s);
	return r;
}
e allocator
 *
 *	calls malloc or realloc and aborts if unsuccessful
 */

#include "asd.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void *
alloc (size_t n)
{
	register void *p;

	p = malloc (n);
	schk (p);
	return p;
}

void *
ralloc (void *s, size_t n)
{
	register void *p;

	if (s == NULL)
		return alloc (n);
	
	p = realloc (s, n);
	schk (p);
	return p;
}

/* return a copy of a string */
char *
copy (char *s)
{
	register char *r;
	r = alloc (strlen (s) + 1);
	strcpy (r, s);
	pkg/ar.h   644   3513      4         324  5013610563   5417 #define	ARMAG	"!<arch>\n"
#define	SARMAG	8

#define	ARFMAG	"`\n"

struct ar_hdr {
	char	ar_name[16];
	char	ar_date[12];
	char	ar_uid[6];
	char	ar_gid[6];
	char	ar_mode[8];
	char	ar_size[10];
	char	ar_fmag[2];
};
= malloc (n);
	schk (p);
	return p;
}

void *
ralloc (void *s, size_t n)
{
	register void *p;

	if (s == NULL)
		return alloc (n);
	
	p = realloc (s, n);
	schk (p);
	return p;
}

/* return a copy of a string */
char *
copy (char *s)
{
	register char *r;
	r = alloc (strlen (s) + 1);
	strcpy (r, s);
	pkg/args.c   644   3513      4        6462  5013610564   5776 #include "asd.h"
#include <libv.h>
#include <string.h>

int bflag;			/* -b make a backup package */
int kflag;			/* -k crypto key (deprecated) */
int Kflag;			/* -K crypto key from file (deprecated) */
int nflag;			/* -n don't actually install files */
int vflag;			/* -v verbose output */
char *xstr;			/* -x command to execute */
char *Xstr;			/* -X file to execute */
struct replist *replist;	/* -D substitutions */

int
getargs (int argc, char **argv, char *optkey, int (*func)(FILE *, char *))
{
	register int c;
	int rc = 0;
	char *keyfile;

	while ((c = getopt (argc, argv, optkey)) != EOF) {
		register struct replist *rl;
		register char *p, *q;

		switch (c) {

		case 'b':
			bflag++;
			break;

		case 'k':
			kflag++;
			break;

		case 'n':
			nflag++;
			break;
		
		case 'v':
			vflag++;
			break;

		case 'x':
			if (xstr) {
				fprintf (stderr, "duplicate -x ignored\n");
				rc++;
			} else if (Xstr) {
				fprintf (stderr, "cannot have both -x and -X\n");
				rc++;
			} else
				xstr = optarg;
			break;

		case 'X':
			if (Xstr) {
				fprintf (stderr, "duplicate -X ignored\n");
				rc++;
			} else if (xstr) {
				fprintf (stderr, "cannot have both -x and -X\n");
				rc++;
			} else
				Xstr = copy (transname (optarg));
			break;

		case 'D':
			p = strchr (optarg, '=');
			if (p == NULL) {
				fprintf (stderr, "invalid option %s\n", optarg);
				exit (1);
			}
			rl = new (struct replist);

			/* copy the pathname to rl->source */
			rl->source = alloc ((unsigned) (p - optarg + 1));
			p = rl->source;
			q = optarg;
			while (*q != '=')
				*p++ = *q++;
			*p = '\0';

			/* now expand rl->source */
			p = rl->source;
			rl->source = copy (fullname (p));
			free (p);

			/* expand rl->dest */
			rl->dest = copy (fullname (q + 1));

			/* link rl into the chain */
			rl->link = replist;
			replist = rl;
			break;

		case 'K':
			Kflag++;
			keyfile = optarg;
			break;

		case '?':
		default:
			rc++;
			break;
		}
	}

	if (rc) {
		fprintf (stderr, "%s: bad argument\n", argv[0]);
		exit (rc);
	}

	if (kflag && Kflag) {
		fprintf (stderr, "%s: cannot specify both k and K\n", argv[0]);
		exit (1);
	}

	/* read key from terminal if requested */
	if (kflag) {
		register char *p;
		p = getpass ("Key:");

		/* a null key is treated as no key at all */
		if (p && *p)
			setup (p);
		else
			kflag = 0;
	}
	
	/* read key from file if requested */
	if (Kflag) {
		char key[100];
		register FILE *kf;
		register char *p;

		/* try to open the file */
		kf = fopen (keyfile, "r");
		if (kf == NULL) {
			perror (keyfile);
			exit (1);
		}

		/* read the first line */
		p = fgets (key, sizeof (key), kf);

		fclose (kf);

		/* if EOF, assume no key */
		if (p == NULL) {
			Kflag = 0;
		} else {

			/* delete the trailing newline */
			p = key;
			while (*p != '\n' && *p != '\0')
				p++;
			*p = '\0';

			/* if the key is empty, assume no key */
			if (key[0] == '\0')
				Kflag = 0;
			else
				setup (key);
		}
	}

	if (func) {
		/* process the arguments */
		if (optind >= argc)
			rc = (*func) (stdin, "standard input");
		else {
			register int i;
			for (i = optind; i < argc; i++) {
				register char *fn = argv[i];
				register FILE *f = fopen (fn, "r");
				if (f) {
					rc += (*func) (f, argv[i]);
					fclose (f);
				} else {
					fprintf (stderr, "%s: can't open %s\n", argv[0], fn);
					rc++;
				}
			}
		}
	}

	return rc;
}
ssume no key */
			if (key[0] == '\0')
				Kflag = 0;
			else
				setup (key);
		}
	}

	if (func) {
		/* process the arguments */
		if (optind >= argc)
			rc = (*func) (stdin, "standard input");
		else {
		pkg/asd.h   644   3513      4        4124  5014037413   5604 #include "ar.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>

#if 0
/* system-dependent stuff */
#ifdef unix
#ifndef major
#include <sys/sysmacros.h>
#endif
#endif
#endif

/* longest archive component name we will generate */
#define MAXCOMP 14

/* macro to allocate storage of a given type */
#define new(t) ((t *) alloc (sizeof (t)))

/* some systems define SIG_TYP, others don't, so we make our own */
#ifdef __STDC__
typedef void (*Sig_typ)(int);
#else
typedef int	(*Sig_typ)();
#endif

struct replist {
	char *source;
	char *dest;
	struct replist *link;
};

extern struct replist *replist;

/* structures to deal with archive headers */
struct ar_hdr ar_hdr;
struct hdr {
	long size;
	int mode;
	long date;
};
extern struct hdr hdr;

/* alloc.c */
extern void *alloc(size_t);
extern void *ralloc(void *, size_t);
extern char *copy(char *);

/* args.c */
extern int bflag;
extern int kflag;
extern int Kflag;
extern int nflag;
extern int vflag;
extern char *xstr;
extern char *Xstr;
extern int getargs(int, char **, char *, int (*)(FILE *, char *));

/* chk.c */
extern void nchk(int);
extern void schk(void *);

/* crypt.c */
extern void resetN12(void);
extern void setup(char *);
extern void mangle(char *, char *);

/* data.c */
extern char *hextab;
extern char *instr;

/* fullname.c */
extern char *fullname(char *);

/* gid.c */
extern char *gidstr(gid_t);
extern gid_t gidnum(char *);

/* header.c */
extern long cvlong(char *, size_t, int);
extern long read_header(char *, FILE *);
extern void next_header(FILE *);
extern char *getfield(FILE *);
extern void geteol(FILE *);

/* mkdir.c */
extern int mkd(char *);
extern int rmdir(char *);
extern int rmall(char *);

/* package.c */
extern void pkgstart(void);
extern void pkgfile(char *);
extern int pkgend(void);

/* path.c */
extern char *getpath(FILE *);
extern void putpath(FILE *, char *);

/* pwd.c */
extern char *pwd(void);

/* transname.c */
extern char *transname(char *);

/* uid.c */
extern char *uidstr(uid_t);
extern uid_t uidnum(char *);
id next_header(FILE *);
extern char *getfield(FILE *);
extern void geteol(FILE *);

/* mkdir.c */
extern int mkd(char *);
extern int rmdir(char *);
extern int rmall(char *);

/* package.c */
extern void pkgstart(void);
extern void pkgfile(char *);
extern int pkgend(void);

/* path.c */
extern char *getpath(FILE *);
extern void putpath(FILE *, char *);

/* pwd.c */
extern char *pwd(void);

/* transname.c */
extern char *transpkg/chk.c   644   3513      4         472  5013610565   5563 #include "asd.h"
#include <stdio.h>

/*
 *	little subroutines to check return codes
 */

void
nchk (int n)
{
	if (n < 0) {
		fprintf (stderr, "unexpected error return -- help!\n");
		exit (1);
	}
}

void
schk (void *s)
{
	if (s == NULL) {
		fprintf (stderr, "unexpected error return -- help!\n");
		exit (1);
	}
}
 pkgfile(char *);
extern int pkgend(void);

/* path.c */
extern char *getpath(FILE *);
extern void putpath(FILE *, char *);

/* pwd.c */
extern char *pwd(void);

/* transname.c */
extern char *transpkg/crypt.c   644   3513      4        3604  5013610566   6200 /*
 *	encryption service routines
 */

#include "asd.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

/* encryption parameters and tables */
#define ROTORSZ 256
#define MASK 0377
static char	t1[ROTORSZ];
static char	t2[ROTORSZ];
static char	t3[ROTORSZ];
static char	t4[ROTORSZ];

/* current rotor settings */
static int N1, N2;

void
resetN12(void)
{
	N1 = N2 = 0;
}

void
setup(char *pw)
{
	int ic, i, k, temp, pf[2];
	unsigned random;
	char buf[13];
	long seed;
	int pid;

	resetN12();

	strncpy(buf, pw, 8);
	while (*pw)
		*pw++ = '\0';
	buf[8] = buf[0];
	buf[9] = buf[1];
	pipe(pf);

	switch (pid = fork()) {

	case -1:
		fprintf (stderr, "seal: cannot fork\n");
		exit (1);

	case 0:
		close(0);
		close(1);
		dup(pf[0]);
		dup(pf[1]);
		execl("/usr/lib/makekey", "-", 0);
		execl("/lib/makekey", "-", 0);
		exit(1);

	default:
		write(pf[1], buf, 10);
		while (wait ((int *) NULL) != pid)
			;
	}

	if (read(pf[0], buf, 13) != 13) {
		fprintf(stderr, "seal: cannot generate key\n");
		exit(1);
	}
	seed = 123;
	for (i=0; i<13; i++)
		seed = seed*buf[i] + i;
	for(i=0;i<ROTORSZ;i++)
		t1[i] = i;
	for(i=0;i<ROTORSZ;i++) {
		seed = 5*seed + buf[i%13];
		random = seed % 65521;
		k = ROTORSZ-1 - i;
		ic = (random&MASK)%(k+1);
		random >>= 8;
		temp = t1[k];
		t1[k] = t1[ic];
		t1[ic] = temp;
		if(t3[k]!=0) continue;
		ic = (random&MASK) % k;
		while(t3[ic]!=0) ic = (ic+1) % k;
		t3[k] = ic;
		t3[ic] = k;
	}
	for(i=0;i<ROTORSZ;i++){
		t2[t1[i]&MASK] = i;
		t4[i] = (t1[i] + t3[i]) & 0377;
	}
}

void
mangle (char *buf, char *limit)
{
	register int i;
	register char *p;
	register int n1 = N1, n2 = N2;
	int n3;

	p = buf;

	while(p < limit) {
		i = *p;
		n3 = t4[n1];
		i = t2[(t3[(t1[(i+n3)&MASK]+n2)&MASK]-n2)&MASK]-n3;
		*p++ = i;
		n1++;
		if(n1==ROTORSZ) {
			n1 = 0;
			n2++;
			if(n2==ROTORSZ) n2 = 0;
		}
	}
	N1 = n1;
	N2 = n2;
}
dom&MASK) % k;
		while(t3[ic]!=0) ic = (ic+1) % k;
		t3[k] = ic;
		t3[ic] = k;
	}
	for(i=0;i<ROTORSZ;i++){
		t2[t1[i]&MASK] pkg/data.c   644   3513      4         156  5013610566   5727 /*
 *	Initializations
 */

#include "asd.h"

char *hextab = "0123456789abcdef";
char *instr = "Instructions";
 char *p;
	register int n1 = N1, n2 = N2;
	int n3;

	p = buf;

	while(p < limit) {
		i = *p;
		n3 = t4[n1];
		i = t2[(t3[(t1[(i+n3)&MASK]+n2)&MASK]-n2)&MASK]-n3;
		*p++ = i;
		n1++;
		if(n1==ROTORSZ) {
			n1 = 0;
			n2++;
			if(n2==ROTORSZ) n2 = 0;
		}
	}
	N1 = n1;
	N2 = n2;
}
dom&MASK) % k;
		while(t3[ic]!=0) ic = (ic+1) % k;
		t3[k] = ic;
		t3[ic] = k;
	}
	for(i=0;i<ROTORSZ;i++){
		t2[t1[i]&MASK] pkg/fullname.c   644   3513      4        1461  5013610567   6642 /*
 *	fullname -- return the full pathname corresponding to the
 *	abbreviated pathname given as argument.  Returned value
 *	is in a buffer that will stay around no longer than its
 *	argument or the next call to fullname, whichever is earlier.
 */

#include "asd.h"
#include <string.h>

char *
fullname (char *s)
{
	register char *t;
	static char *r;
	static int size;
	register unsigned n;

	/* if first char is slash, absolute path */
	if (s[0] == '/')
		return s;
	
	/* strip leading './' */
	while (s[0] == '.' && s[1] == '/')
		s += 2;
	
	t = pwd();

	/* null string or "." means current directory */
	if (s[0] == '\0' || strcmp (s, ".") == 0)
		return t;
	
	n = strlen (s) + strlen (t) + 2;
	if (n > size) {
		r = ralloc (r, n);
		size = n;
	}

	strcpy (r, t);
	strcat (r, "/");
	strcat (r, s);

	return r;
}
(char *s)
{
	register char *t;
	static char *r;
	static int size;
	register unsigned n;

	/* if first char is slash, absolute path */
	if (s[0] == '/')
		return s;
	
	/* strip leading './' */
	while (s[0] ==pkg/gid.c   644   3513      4        2533  5013610570   5575 #include "asd.h"
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define CHUNK 16

static struct gtab {
	unsigned gid;
	char *name;
} *gtab;

static int size, salloc;

char *
gidstr (gid_t gid)
{
	register int i;
	static char buf[12];
	struct group *g;

	/* search the cache for the gid */
	for (i = 0; i < size; i++)
		if (gtab[i].gid == gid)
			return gtab[i].name;

	/* try to find it in the system's database */
	if (g = getgrgid(gid)) {
		if (size % CHUNK == 0)
			gtab = (struct gtab *) ralloc((char *) gtab, salloc += CHUNK);
		gtab[size].gid = g->gr_gid;
		gtab[size].name = copy(g->gr_name);
		++size;
		return gtab[size - 1].name;
	}

	/* failure, invent a string */
	sprintf (buf, "#%u", gid);
	return buf;
}

gid_t
gidnum (char *name)
{
	register int i;
	struct group *g;

	/* if it starts with a #, use the number */
	if (name[0] == '#')
		return atoi (name + 1);

	/* search the cache */
	for (i = 0; i < size; i++)
		if (strcmp (gtab[i].name, name) == 0)
			return gtab[i].gid;

	/* try to find it in the system's database */
	if (g = getgrnam(name)) {
		if (size % CHUNK == 0)
			gtab = (struct gtab *) ralloc((char *) gtab, salloc += CHUNK);
		gtab[size].gid = g->gr_gid;
		gtab[size].name = copy(g->gr_name);
		++size;
		return gtab[size - 1].gid;
	}


	/* failure, invent a value */
	return getgid();
}
, use the number */
	if (name[0] == '#')
		return atoi (name + 1);

	/* search the cache */
	for (i = 0; i < size; i++)
		if (strcmp (gtab[i].name, name) == 0)
			repkg/header.c   644   3513      4        4144  5013610570   6262 /*
 *	various subroutines to deal with archive headers
 */

#include "asd.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>

struct hdr hdr;

/*
 *	convert p to a long value.  maximum input length is len,
 *	input is to be interpreted in base b.  No negative values.
 */
long
cvlong (char *p, size_t len, int base)
{
	register int i;
	register long r;

	r = 0;
	i = len;

	do {
		register int c = *p++;
		if (isdigit (c))
			r = r * base + c - '0';
	} while (--i > 0);

	return r;
}

long
read_header (char *name, FILE *file)
{
	register int n;
	register int i;
	register char *p, *q;

	n = fread ((char *) &ar_hdr, sizeof (ar_hdr), 1, file);
	if (n != 1) {
		fprintf (stderr, "can't read %s\n", name);
		exit (1);
	}

	if (strncmp (ar_hdr.ar_fmag, ARFMAG, sizeof (ar_hdr.ar_fmag)) != 0) {
		fprintf (stderr, "input phase error on %s\n", name);
		exit (1);
	}

	/* check the component name, allowing for trailing blanks */
	p = name;
	q = ar_hdr.ar_name;
	for (i = 0; i < sizeof (ar_hdr.ar_name); i++) {
		if (*q++ != (*p? *p++: ' ')) {
			fprintf (stderr, "expected %s, got %.*s\n",
			    name, sizeof (ar_hdr.ar_name), ar_hdr.ar_name);
		}
	}

	/* crack the archive header and put the information in "hdr" */
	hdr.size = cvlong (ar_hdr.ar_size, sizeof (ar_hdr.ar_size), 10);
	hdr.mode = cvlong (ar_hdr.ar_mode, sizeof (ar_hdr.ar_mode), 8);
	hdr.date = cvlong (ar_hdr.ar_date, sizeof (ar_hdr.ar_date), 10);

	return hdr.size;
}

/* advance to the start of the next archive header */
void
next_header(FILE *f)
{
	if (hdr.size & 1)
		getc(f);
}

/* skip leading white space, return a field */
char *
getfield (FILE *f)
{
	register char c;

	/* skip leading white space */
	do c = getc (f);
	while (isspace (c) && c != '\n');

	/* if we hit a newline, something's wrong */
	if (c == '\n') {
		fprintf (stderr, "unexpected newline\n");
		exit (1);
	}

	/* return the nonblank, read a "pathname" and return it */
	ungetc (c, f);
	return getpath (f);
}

/* insist on an end of line right here */
void
geteol (FILE *f)
{
	register int c;

	c = getc (f);
	if (c != '\n') {
		fprintf (stderr, "expected newline, got %c\n", c);
		exit (1);
	}
}
ister char c;

	/* skip leading white space */
	do c = getc (f);
	while (isspace (c) && c != '\n');

	/* if we hit a newline, something's wrong */
	if (c == '\n') {
		fprintf (stderr, "unexpected newline\n");
		exit (1);
	}

	/* return the nonblank, read a "pathname" and return it */
	ungetc (c, f);
	return getpath (f);
}

/* insist on an end of line right here */
void
geteol (FILE *f)
{
	register int c;

	c pkg/inspkg.c   644   3513      4       25371  5013610572   6354 #include "asd.h"
#include <libv.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <utime.h>

#define CHUNK 64

/* type codes for installation subroutine */
#define BACKUP 0
#define INSTALL 1

static void readtemp(int, FILE *);

/*
 *	The following declarations and functions manipulate
 *	a list of directory names.  This list is used to decide
 *	which files should be backed up and which have already been.
 */

struct list {
	char *name;
	struct list *next;
};

static struct list *dirs;

/* is the name given a subdirectory of the name on the list? */
static int
subsumed (char *name)
{
	register struct list *item;
	register char *p, *q;

	for (item = dirs; item; item = item->next) {
		p = item->name;
		q = name;
		while (*p && *p == *q)
			p++, q++;
		if (*p == '\0' && (*q == '/' || *q == '\0'))
			return 1;
	}

	return 0;
}

/* add the name given to the list */
static void
addlist (char *name)
{
	register struct list *l;

	l = new (struct list);
	l->next = dirs;
	l->name = copy (name);
	dirs = l;
}

/* clear the entire list */
static void
clearlist(void)
{
	register struct list *l;

	while (l = dirs) {
		dirs = l->next;
		free (l->name);
		free ((char *) l);
	}
}

static char tfname[L_tmpnam];
static void delete(int);

/* process a single archive in a concatenation */
static int
doarch (FILE *file)
{
	register FILE *tf;
	Sig_typ sigsav;
	register long size;
	register int c;
	char armag[SARMAG];

	/* Make sure the file is an archive */
	if (fread (armag, sizeof (*armag), SARMAG, file) != SARMAG) {
		fprintf (stderr, "inspkg: unexpected EOF\n");
		exit (1);
	}
	if (strncmp (armag, ARMAG, SARMAG) != 0) {
		fprintf (stderr, "inspkg: input not a package\n");
		exit (1);
	}

	/* establish a temporary file */
	(void) tmpnam (tfname);
	tf = fopen (tfname, "w");
	sigsav = signal (SIGINT, SIG_IGN);
	if (sigsav != SIG_IGN)
		signal (SIGINT, delete);
	chmod (tfname, 0600);

	/* copy the installation instructions to the temp file */
	size = read_header (instr, file);
	while (--size >= 0) {
		c = getc (file);
		if (c == EOF) {
			fprintf (stderr, "inspkg: premature EOF\n");
			exit (1);
		}
		if (putc (c, tf) == EOF) {
			perror ("inspkg: Instructions");
			exit (1);
		}
	}
	if (fclose (tf) == EOF) {
		perror ("inspkg: Instructions fclose");
		exit (1);
	}

	next_header (file);

	/* create the optional backup package */
	if (bflag) {
		pkgstart();
		readtemp (BACKUP, file);
		pkgend();
		clearlist();
	}

	/* do the actual work */
	readtemp (INSTALL, file);

	/* delete the temporary file */
	nchk (unlink (tfname));
	signal (SIGINT, sigsav);

	return 0;
}

/*
 *	install the given file
 */
static int
process (FILE *file, char *fname)
{
	register int c, rc = 0;

	if (vflag)
		fprintf (stderr, "%s:\n", fname);

	while ((c = getc (file)) != EOF) {
		ungetc (c, file);
		rc += doarch (file);
	}

	return rc;
}

int
main (int argc, char **argv)
{
	static char errbuf[BUFSIZ];

	setbuf (stderr, errbuf);
	umask (0);
	return getargs (argc, argv, "nvbD:", process);
}

/*
 *	Make a pass through the temp file.
 */
static void
readtemp (int code, FILE *file)
{
	register FILE *tf;
	register int c;

	/* we're done writing the temp file, time to read it */
	tf = fopen (tfname, "r");
	schk ((char *) tf);

	/*
	 *	The main loop -- one iteration per line
	 *	We are careful in use and reuse of storage here;
	 *	if you change this code make sure you understand
	 *	the times at which getfield and transname
	 *	recycle storage or strange things will happen.
	 */
	while ((c = getc (tf)) != EOF) {
		char *param, *path, *path2;
		register FILE *outfd;
		int uid, gid, mode, dmajor, dminor, dev;
		register long size;
		char component[MAXCOMP+1];

		switch (c) {

#if 0
		/* special files */
		case 'b':
		case 'c':
			/* read the parameters */
			param = getfield (tf);
			mode = cvlong (param, strlen (param), 8) |
			    (c == 'c'? S_IFCHR: S_IFBLK);
			param = getfield (tf);
			dmajor = cvlong (param, strlen (param), 10);
			param = getfield (tf);
			dminor = cvlong (param, strlen (param), 10);
			dev = makedev (dmajor, dminor);
			uid = uidnum (getfield (tf));
			gid = gidnum (getfield (tf));
			path = transname (getfield (tf));
			geteol (tf);

			switch (code) {

			case BACKUP:
				if (!subsumed (path)) {
					pkgfile (path);
					addlist (path);
				}
				break;

			case INSTALL:
				if (vflag) {
					fprintf (stderr, "special file ");
					putpath (stderr, path);
					fprintf (stderr, "\n");
				}

				if (!nflag) {
					rmall (path);
					if (mknod (path, mode, dev) >= 0)
						chown (path, uid, gid);
					else
						perror (path);
				}
				break;
			}
			break;
#endif

		/* directory */
		case 'd':
			/* read the parameters */
			param = getfield (tf);
			mode = cvlong (param, strlen (param), 8);
			uid = uidnum (getfield (tf));
			gid = gidnum (getfield (tf));
			path = transname (getfield (tf));
			geteol (tf);

			switch (code) {

			case BACKUP:
				if (!subsumed (path)) {
					pkgfile (path);
					addlist (path);
				}
				break;

			case INSTALL:
				/* make the directory */
				if (vflag) {
					fprintf (stderr, "directory ");
					putpath (stderr, path);
					putc ('\n', stderr);
				}
				if (!nflag) {
					rmall (path);
					mkd (path);
					chmod (path, mode);
					chown (path, uid, gid);
					chmod (path, mode);
				}
				break;
			}

			break;

		/* file */
		case 'f':
			/* read parameters */
			param = getfield (tf);
			if (strlen (param) > MAXCOMP) {
				fprintf (stderr,
				    "inspkg: impossibly long component name\n");
				delete(0);
				exit (1);
			}
			strcpy (component, param);
			uid = uidnum (getfield (tf));
			gid = gidnum (getfield (tf));
			path = transname (getfield (tf));
			geteol (tf);

			switch (code) {

			case BACKUP:
				if (!subsumed (path))
					pkgfile (path);
				break;

			case INSTALL:
				/* read the corresponding archive header */
				size = read_header (component, file);

				if (vflag) {
					fprintf (stderr, "file ");
					putpath (stderr, path);
					putc ('\n', stderr);
				}

				/* create and open the file */
				if (!nflag) {
					rmall (path);
					umask (077);
					outfd = fopen (path, "w");
					umask (0);
					if (outfd == NULL) {
						fprintf (stderr,
						    "inspkg: cannot create ");
						putpath (stderr, path);
						putc ('\n', stderr);
					}
				}
				if (nflag || outfd == NULL) {
					outfd = fopen ("/dev/null", "w");
					schk ((char *) outfd);
				}

				/* copy the file, advance input */
				while (--size >= 0)
					putc (getc (file), outfd);
				next_header (file);

				/* check successful completion, close output */
				fflush (outfd);
				if (feof (file) || ferror (file) ||
				    ferror (outfd)) {
					fprintf (stderr, "inspkg: can't write ");
					putpath (stderr, path);
					putc ('\n', stderr);
				}
				if (fclose (outfd) == EOF) {
					fprintf (stderr, "inspkg: can't close ");
					putpath (stderr, path);
					fprintf (stderr, ": ");
					perror ("");
				}
				
				/*
				 *	Update output modification times
				 *	and change mode and owner.
				 *	This is done here to cater to systems
				 *	that allow people to give files away.
				 *	The chmod is done twice because
				 *	systems that let you give files away
				 *	won't let you change the mode after
				 *	you've done so, and some other systems
				 *	turn off the setuid bit as a side
				 *	effect of chown, so the second chmod
				 *	will restore that bit.
				 */
				if (!nflag) {
					struct utimbuf utb;
					utb.actime = utb.modtime = hdr.date;
					utime (path, &utb);
					chmod (path, hdr.mode & 07777);
					chown (path, uid, gid);
					chmod (path, hdr.mode & 07777);
				}

				break;
			}
			break;

		/* symbolic link */
		case 's':
			/* read parameters */
			path = copy (transname (getfield (tf)));
			path2 = transname (getfield (tf));
			geteol (tf);

			switch (code) {
			case BACKUP:
				if (!subsumed (path2))
					pkgfile (path2);
				break;

			case INSTALL:
				/* log it if requested */
				if (vflag) {
					fprintf (stderr, "symlink ");
					putpath (stderr, path2);
					fprintf (stderr, " to ");
					putpath (stderr, path);
					putc ('\n', stderr);
				}
#ifdef	S_ISLNK

				/* make the link */
				if (!nflag) {
					rmall (path2);
					if (symlink (path, path2) < 0)
						perror (path2);
				}
#else
				fprintf(stderr, "This system does not support symbolic links\n");
#endif

				break;
			}
			free (path);
			break;
		
		/* link */
		case 'l':
			/* read parameters */
			path = copy (transname (getfield (tf)));
			path2 = transname (getfield (tf));
			geteol (tf);

			switch (code) {

			case BACKUP:
				if (!subsumed (path2))
					pkgfile (path2);
				break;

			case INSTALL:
				/* log it if requested */
				if (vflag) {
					fprintf (stderr, "link ");
					putpath (stderr, path);
					fprintf (stderr, " to ");
					putpath (stderr, path2);
					putc ('\n', stderr);
				}

				/* make the link */
				if (!nflag) {
					struct stat sb, sb2;

					/* are we about to link x to x? */
					if (stat (path, &sb) < 0
					    || stat (path2, &sb2) < 0
					    || sb.st_dev != sb2.st_dev
					    || sb.st_ino != sb2.st_ino) {
						rmall (path2);
						if (link (path, path2) < 0)
							perror (path2);
					}
				}

				break;
			}
			free (path);
			break;
		
		/* remove */
		case 'r':
			/* get parameters */
			path = transname (getfield (tf));
			geteol (tf);

			switch (code) {

			case BACKUP:
				if (!subsumed (path))
					pkgfile (path);
				break;

			case INSTALL:
				if (vflag) {
					fprintf (stderr, "remove file ");
					putpath (stderr, path);
					putc ('\n', stderr);
				}
				if (!nflag)
					rmall (path);
				break;
			}

			break;

		case 'x':
			xstr = getfield (tf);
			geteol (tf);
			if (code == INSTALL) {
				if (vflag) {
					fprintf (stderr, "execute: ");
					putpath (stderr, xstr);
					fprintf (stderr, "\n");
				}
				if (!nflag) {
					fflush (stderr);
					system (xstr);
				}
			}
			xstr = NULL;
			break;

		case 'X':
			Xstr = transname (getfield (tf));
			geteol (tf);
			if (code == INSTALL) {
				if (vflag) {
					fprintf (stderr, "exec file: ");
					putpath (stderr, Xstr);
					fprintf (stderr, "\n");
				}
				if (!nflag) {
					int status, pid, w;
					Sig_typ istat, qstat;

					fflush (stderr);
					if ((pid = fork()) == 0) {
						execl (Xstr, Xstr, (char *)0);
						execl ("/bin/sh", "sh", Xstr, (char *) 0);
						putpath (stderr, Xstr);
						fprintf (stderr, ": ");
						fflush (stderr);
						perror ("");
						_exit(127);
					}
					istat = signal (SIGINT, SIG_IGN);
					qstat = signal (SIGQUIT, SIG_IGN);
					while ((w=wait(&status)) != pid && w != -1)
						;
					signal(SIGINT, istat);
					signal(SIGQUIT, qstat);
				}
			}
			Xstr = NULL;
			break;

		default:
			fprintf (stderr, "inspkg: invalid package\n");
			delete(0);
			exit (1);
		}
	}

	if (ferror (tf))
		perror ("inspkg: internal temp file");

	fclose (tf);

}

static void
delete(int sigarg)
{
	unlink (tfname);
	exit (3);
}
					perror ("");
						_exit(127);
					}
					istat = signal (SIGINT, SIG_IGN);
					qstat = signal (SIGQUIT, SIG_IGN);
					while ((w=wait(&status)) != pid && w != -1)
						;
					signal(SIGINT, istat);
					signal(SIGQUIT, qstat);
				}
			}
			Xstr = NULL;
pkg/mkcsum.c   644   3513      4         436  5013610572   6313 #include "seal.h"

unsigned long
mkcsum (unsigned long csum, char *start, char *limit)
{
	register int c;

	while (start < limit) {
		c = (unsigned char) *start++;
		if (csum & 1)
			csum = (csum >> 1) | CSHIBIT;
		else

			csum >>= 1;
		csum += c;
		csum &= CSMASK;
	}
	return csum;
}
				}
					istat = signal (SIGINT, SIG_IGN);
					qstat = signal (SIGQUIT, SIG_IGN);
					while ((w=wait(&status)) != pid && w != -1)
						;
					signal(SIGINT, istat);
					signal(SIGQUIT, qstat);
				}
			}
			Xstr = NULL;
pkg/mkdir.c   644   3513      4        4363  5031450263   6144 #include "asd.h"
#include <sys/wait.h>
#include <unistd.h>
#include "ftw.h"

#ifndef S_ISLNK
#ifdef S_IFLNK
#define S_ISLNK(M) (((M)&S_IFMT) == S_IFLNK)
#endif
#define S_ISREG(M) (((M)&S_IFMT) == S_IFREG)
#define S_ISDIR(M) (((M)&S_IFMT) == S_IFDIR)
#define S_ISCHR(M) (((M)&S_IFMT) == S_IFCHR)
#define S_ISBLK(M) (((M)&S_IFMT) == S_IFBLK)
#endif

/*
 *	mkd function -- tries to make a directory whose name is "d".
 *	returns 0 if successful or if d already exists and is a
 *	directory.  On failure, returns mkdir's return code.
 */

int
mkd (char *d)
{
	register int pid, w;
	int status;
	struct stat sb;

	if (stat (d, &sb) >= 0)
		return !S_ISDIR(sb.st_mode);

	switch (pid = fork()) {
	case 0:
		/* we might be executed from a setuid program */
		setgid (getegid());
		setuid (geteuid());
		execl ("/bin/mkdir", "mkdir", d, 0);
		/* No break */
	case -1:
		return 1;

	default:
		do w = wait (&status);
		while (w != pid && w > 0);
		if (w == pid)
			return status;
		return w;
	}
}


static int
rm (char *name, struct stat *sb, int type, struct FTW *ftw)
{
	register int r;

	switch (type) {

	case FTW_F:
	case FTW_SL:
		r = unlink (name);
		if (r < 0) {
			perror (name);
			return r;
		}
		break;
	
	case FTW_D:
		break;
	
	case FTW_DNR:
		fprintf (stderr, "cannot read directory %s\n", name);
		exit (1);
	
	case FTW_NS:
		fprintf (stderr, "cannot stat %s\n", name);
		exit (1);
	
	case FTW_DP:
		r = rmdir (name);
		if (r != 0) {
			fprintf (stderr,
			    "trouble removing directory %s\n", name);
			return r;
		}
	}

	return 0;
}

/*
 *	rmdir function -- tries to remove a directory whose name is "d".
 *	returns 0 if successful.  On failure, returns rmdir's return code.
 */

int
rmdir (char *d)
{
	register int pid, w;
	int status;
	struct stat sb;

	if (stat (d, &sb) >= 0 && !S_ISDIR(sb.st_mode))
		return -1;

	switch (pid = fork()) {
	case 0:
		/* we might be executed from a setuid program */
		setgid (getegid());
		setuid (geteuid());
		execl ("/bin/rmdir", "rmdir", d, 0);
		/* No break */
	case -1:
		return 1;

	default:
		do w = wait (&status);
		while (w != pid && w > 0);
		if (w == pid)
			return status;
		return w;
	}
}

/* rmall (s) recursively removes the object named s */
int
rmall (char *s)
{
	if (access(s, 0) < 0)
		return 0;
	return ftw (s, rm, 8);
}
 &sb) >= 0 && !S_ISDIR(sb.st_mode))
		return -1;

	switch (pid = fork()) {
	case 0:
		/* we might be executed from a setuid program */
		setgid (getegid());
		setuid (geteuid());
		execl ("/bin/rmdir", "rmdir", d, 0);
		/* No break */
	case -1:
		return 1;

	default:
	pkg/mkfile   644   3513      4        1607  5031450307   6061 <../mkconf.$SYS
<../mkrules.$SYS

LPROG=mkpkg inspkg seal unseal
LIB=lib-$O.a
LIBOBJ=alloc.$O args.$O chk.$O crypt.$O data.$O ftw.$O fullname.$O \
 gid.$O header.$O mkcsum.$O mkdir.$O package.$O path.$O pwd.$O \
 transname.$O uid.$O

compile:V: $LPROG

install:V: compile
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR

mkpkg: mkpkg.$O $LIB
	$CC -o $target $prereq $CCLIB

inspkg: inspkg.$O $LIB
	$CC -o $target $prereq $CCLIB

seal: seal.$O $LIB
	$CC -o $target $prereq $CCLIB

unseal: unseal.$O $LIB
	$CC -o $target $prereq $CCLIB

lib-$O.a: $LIBOBJ
	rm -f lib-$O.a
	ar r lib-$O.a $LIBOBJ
	$RL lib-$O.a

# Need to check these.
alloc.$O args.$O data.$O fullname.$O gid.$O: asd.h ar.h
header.$O inspkg.$O mkdir.$O: asd.h ar.h
mkpkg.$O package.$O path.$O pwd.$O seal.$O: asd.h ar.h
transname.$O uid.$O unseal.$O: asd.h ar.h
mkcsum.$O seal.$O unseal.$O: seal.h

clean:V:
	rm -f *.[$OS] lib-[$OS].a $LPROG
$LIB
	$CC -o $target $prereq $CCLIB

seal: seal.$O $LIB
	$CC -o $target $prereq $CCLIB

unseal: unseal.$O $LIB
	$CC -o $tpkg/mkpkg.c   644   3513      4         453  5013610574   6126 #include "asd.h"
#include <libv.h>
#include <stdio.h>

int
main (int argc, char **argv)
{
	register int i;
	static char errbuf[BUFSIZ];

	setbuf (stderr, errbuf);

	getargs (argc, argv, "vx:X:D:", 0);

	pkgstart();
	for (i = optind; i < argc; i++)
		pkgfile (argv[i]);

	i = pkgend();

	return i;
}
 asd.h ar.h
mkcsum.$O seal.$O unseal.$O: seal.h

clean:V:
	rm -f *.[$OS] lib-[$OS].a $LPROG
$LIB
	$CC -o $target $prereq $CCLIB

seal: seal.$O $LIB
	$CC -o $target $prereq $CCLIB

unseal: unseal.$O $LIB
	$CC -o $tpkg/package.c   644   3513      4       23235  5032702500   6443 #include "asd.h"
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "ftw.h"

FILE *tf;
static Sig_typ sigsav;
static int rc;
static char tfname[L_tmpnam];
static struct stat outsb;
static struct pack *pkhead, *pktail;

/*
 *	The following structure helps keep track of things being packaged.
 *	iname is the internal name of the component -- in other words,
 *	the archive element name.  ename is the (short) pathname of the
 *	file.  The structures are chained by the "link" field.  All the
 *	other fields are copies of things returned by "stat" and are
 *	used mostly to make sure nothing changed while we were packaging.
 *	head and tail point to the first and last items in the chain.
 *	The first item is known to refer to the "Instructions" component.
 */
struct pack {
	char *iname;
	char *ename;
	struct pack *link;
	dev_t dev;
	ino_t ino;
	int uid, gid, mode;
	time_t time;
	off_t size;
};

/*
 *	Prepare to build a package.  The package will appear on stdout.
 *	The argument is nonzero if remarks are to be read.
 */

static void
delete(int arg)
{
	unlink (tfname);
	exit (3);
}

void
pkgstart(void)
{
	struct stat pks;

	rc = 0;

	nchk (fstat (fileno (stdout), &outsb));

	/* establish a temporary file to hold the instruction information */
	tmpnam (tfname);
	tf = fopen (tfname, "w");
	sigsav = signal (SIGINT, SIG_IGN);
	if (sigsav != SIG_IGN)
		signal (SIGINT, delete);
	nchk (chmod (tfname, 0644));
	schk ((char *) tf);

	/* create the initial element in the component chain */
	pkhead = pktail = new (struct pack);
	pkhead->iname = copy (instr);
	pkhead->ename = copy (tfname);
	pkhead->time = 0;
	pkhead->link = NULL;
	pkhead->uid = getuid();
	nchk (fstat (fileno(tf), &pks));
	pkhead->gid = pks.st_gid;
	pkhead->mode = 0100644;
}

static int consider(char *, struct stat *, int, struct FTW *);

/*
 *	put a file (or directory) into a package
 */
void
pkgfile (char *file)
{
	register int x;
	struct stat sb;

	/* if the file is truly not present, generate a remove request */
#ifdef S_IFLNK
	if (lstat (file, &sb) < 0 && errno == ENOENT) {
#else
	if (stat (file, &sb) < 0 && errno == ENOENT) {
#endif
		fprintf (tf, "r ");
		putpath (tf, transname (file));
		putc ('\n', tf);
	} else {
		x = ftw (file, consider, 8);
		if (x != 0) {
			rc++;
			if (x == -1)
				perror (file);
		}
	}
}

/*
 *	we are done building a package.  This writes the actual file
 *	contents, so make sure the files are still around
 */
int
pkgend(void)
{
	register struct pack *pack;
	struct stat s;

	/* write 'x' or 'X' execution item if requested */
	if (xstr) {
		fprintf (tf, "x ");
		putpath (tf, xstr);
		fprintf (tf, "\n");
	}
	if (Xstr) {
		fprintf (tf, "X ");
		putpath (tf, Xstr);
		fprintf (tf, "\n");
	}

	/* we now know how long the first component is */
	pkhead->size = ftell (tf);

	/* we no longer need to write the temporary file */
	fclose (tf);

	/* describe the temp file correctly so it will pass later checks */
	if (pkhead->time == 0)
		(void) time (&pkhead->time);
	nchk (stat (tfname, &s));
	pkhead->dev = s.st_dev;
	pkhead->ino = s.st_ino;

	/*
	 * write the files out into an archive
	 */

	/* first the archive header */
	printf (ARMAG);

	/*
	 *	run through the list, creating the archive components
	 *	and deleting the list entries.  One iteration per component.
	 *	We know there is at least one component, because the
	 *	"Instructions" component must be represented.
	 */
	do {
		struct ar_hdr ah;
		char buf[30];
		register int c;

		/* "pack" is the package component under consideration */
		pack = pkhead;

		if (pack->iname) {	/* non-regular file entry, no data */

			/* log it if requested */
			if (vflag)
				fprintf (stderr, "package %s\n",
				    strcmp (pack->iname, instr)? pack->ename: instr);

			/* write the archive element header */

#		define ent(a,x) sprintf(buf, "%-*s", sizeof(ah.a), x); \
			strncpy (ah.a, buf, sizeof (ah.a))
			ent (ar_name, pack->iname);
			ent (ar_fmag, ARFMAG);
#		undef ent

#		define ent(a,x) sprintf(buf, "%*ld", sizeof(ah.a), (long) x); \
			strncpy (ah.a, buf, sizeof (ah.a))
			ent (ar_date, pack->time);
			ent (ar_uid, pack->uid);
			ent (ar_gid, pack->gid);
			ent (ar_size, pack->size);
#		undef ent

#		define ent(a,x) sprintf(buf, "%*o", sizeof(ah.a), x); \
			strncpy (ah.a, buf, sizeof (ah.a))
			ent (ar_mode, pack->mode);
#		undef ent

			fwrite ((char *) &ah, sizeof (ah), 1, stdout);

			/* write the archive element itself */
			tf = fopen (pack->ename, "r");
			if (tf == NULL) {
				perror (pack->iname);
				exit (1);
			}

			while ((c = getc (tf)) != EOF)
				putchar (c);
			
			/* if things now don't match, complain */
			if (fstat (fileno (tf), &s) < 0 || s.st_size != pack->size ||
			    (s.st_mtime != pack->time && strcmp (pack->iname, instr)) ||
			    s.st_dev != pack->dev || s.st_ino != pack->ino ||
			    s.st_uid != pack->uid || s.st_gid != pack->gid ||
			    (s.st_mode & 07777) != (pack->mode & 07777)) {
				fprintf (stderr, "phase error on %s\n",
				    pack->ename);
				rc++;
			}

			fclose (tf);

			if (pack->size & 1)
				putchar ('\n');
		}
		
		/* delete the element, move on to the next */
		if (pack->iname) free (pack->iname);
		free (pack->ename);
		pkhead = pack->link;
		free ((char *) pack);
	} while (pkhead);

	/* zap the tail pointer for general cleanliness */
	pktail = NULL;

	nchk (unlink (tfname));
	signal (SIGINT, sigsav);

	return rc;
}

static void hdrsub(char *, struct stat *);
static char *iname(char *);

/* internal function for package creation */
static int
consider (char *name, struct stat *buf, int type, struct FTW *ftw)
{
	register struct pack *pack;
	register int mode;
	char *biname;
#ifdef	S_ISLNK
	char *slname;
#endif

	switch (type) {
	case FTW_D:
		fprintf (tf, "d %-*.4o ", MAXCOMP, buf->st_mode & 07777);
		hdrsub (name, buf);
		fprintf (tf, "\n");
		break;

	case FTW_SL:
		if (ftw->level == 0) {
			ftw->quit = FTW_FOLLOW;
			return 0;
		}
		/* fall through */

	case FTW_F:
		mode = buf->st_mode;

		/* Has this file already appeared?  If so, it's a link */
		for (pack = pkhead->link; pack; pack = pack->link) {
			if (buf->st_dev == pack->dev &&
			    buf->st_ino == pack->ino) {
				fprintf (tf, "l %s ", transname (pack->ename));
				fprintf (tf, "%s\n", transname (name));
				return 0;
			}
		}

		if (S_ISREG(mode)) {
			/* refuse to package the standard output */
			if (buf->st_dev == outsb.st_dev &&
			    buf->st_ino == outsb.st_ino) {
				fprintf (stderr, "skipping output file %s\n",
				    fullname (name));
				return 0;
			}
			biname = iname (name);
			fprintf (tf, "f ");
			putpath (tf, biname);
			fprintf (tf, " ");
			hdrsub (name, buf);
			fprintf (tf, "\n");
		}
#ifdef	S_ISLNK
		else if (S_ISLNK(mode)) {
			slname = alloc((unsigned)buf->st_size+1);
			slname[buf->st_size] = '\0';
			if (readlink(name, slname, buf->st_size) !=
			    buf->st_size) {
				perror(name);
				return (0);
			}
			fprintf (tf, "s %s ", transname (slname));
			fprintf (tf, "%s\n", transname (name));
			biname = NULL;
		}
#endif
#if 0 /* We don't handle special files any more.  */
		else if (S_ISBLK(mode) || S_ISCHR(mode)) {
			fprintf (tf, "%c %#o %d %d ",
			    mode == S_IFBLK? 'b': 'c',
			    buf->st_mode & 07777,
			    major (buf->st_rdev),
		 	    minor (buf->st_rdev));
			hdrsub (name, buf);
			fprintf (tf, "\n");
			biname = NULL;
		}
#endif
		else {
			fprintf (stderr, "%s: unrecognized file type\n",
				 fullname (name));
			break;
		}


		/* package the file */
		pack = new (struct pack);
		pack->ename = copy (name);
		pack->dev = buf->st_dev;
		pack->ino = buf->st_ino;
		pack->uid = buf->st_uid;
		pack->gid = buf->st_gid;
		pack->time = buf->st_mtime;
		if (pack->time > pkhead->time)
			pkhead->time = pack->time;
		pack->size = buf->st_size;
		pack->mode = buf->st_mode;
		pack->link = NULL;
		pack->iname = biname;
		pktail->link = pack;
		pktail = pack;
		break;

	case FTW_DNR:
		fprintf (stderr, "cannot read directory %s\n", name);
		return 1;

	case FTW_NS:
		fprintf (stderr, "cannot stat %s\n", name);
		return 1;

	case FTW_DP:
		break;

	default:
		fprintf (stderr, "impossible code %d from ftw\n", type);
		exit (1);
	}
	return 0;
}

static void
hdrsub (char *name, struct stat *buf)
{
	putpath (tf, uidstr (buf->st_uid));
	putc ('\t', tf);
	putpath (tf, gidstr (buf->st_gid));
	putc ('\t', tf);
	putpath (tf, transname (name));
}

/*
 *	generate a unique internal name for a file
 */
static char *
iname (char *s)
{
	register char *p;
	register char *lastcomp;
	register struct pack *pack;
	char trial[MAXCOMP+1];

	/* point lastcomp at the last pathname component */
	lastcomp = s;
	for (p = s; *p; p++) {
		if (*p == '/')
			lastcomp = p + 1;
	}

	/* if the name is acceptably short, modify it slightly */
	if (strlen (lastcomp) <= MAXCOMP) {

		char prefix[MAXCOMP+1], suffix[MAXCOMP+1], num[30];
		register int n;

		/* split the name, remove unprintables */
		strcpy (prefix, lastcomp);
		for (p = prefix; *p; p++)
			if (*p == ' ' || !isprint (*p))
				*p = '$';
		suffix[0] = '\0';
		p = strrchr (prefix, '.');
		if (p != NULL) {
			strcpy (suffix, p);
			*p = '\0';
		}

		/* generate trial names until we run out of space */
		for (n = 0, num[0] = '\0';
		    strlen(prefix) + strlen(suffix) + strlen(num) <= MAXCOMP;
		    n++, sprintf (num, "%.0d", n)) {
			
			/* generate the trial name */
			strcpy (trial, prefix);
			strcat (trial, num);
			strcat (trial, suffix);

			/* if the name is unique, we're done */
			pack = pkhead;
			while (pack != NULL && strcmp (pack->iname, trial) != 0)
				pack = pack->link;
			if (pack == NULL)
				return copy(trial);

		}
	}

	/* punt -- generate a completely new name */
	do {
		static int tempno;

		tempno++;
		sprintf (trial, "Temp%d", tempno);
		pack = pkhead;
		while (pack != NULL && strcmp (trial, pack->iname) != 0)
			pack = pack->link;
	} while (pack != NULL);
	return copy(trial);
}
at (trial, num);
			strcat (trial, suffix);

			/* if the name is unique, we're done */
			pack = pkhead;
			while (pack != NULL && strcmp (pack->iname, trial) != 0)
				pack = pack->link;
			if (pack == NULL)
				return copy(trial);

		}
	}

	/* punt -- generate a completely new name */
	do {
		static int tempno;

		tempno++;
		sprintf (trial, "Temp%d"pkg/path.c   644   3513      4        6137  5013610576   6000 /*
 *	getpath (file) - read a path name
 *	putpath (file, path) - write a path name
 *
 *	These subroutines cater to the possibility of unprintable
 *	characters in the path names being read or written, by
 *	using the same sort of \ conventions commonly found in
 *	C character constants.  The result of getpath is a pointer
 *	to a static buffer whose contents will stay around no longer
 *	than the next call to getpath.  When getpath is called, the
 *	character about to be read from the input file must be the
 *	first character of the path name.
 *
 *	There are a few problems, mostly relating to bugs and language
 *	changes, to watch out for in these routines.  First of all,
 *	we assume that \v is known by the C compiler, even though
 *	it is not mentioned in Kernighan and Ritchie.  The reason for
 *	this is that if we do not make this assumption, we run into
 * 	a common bug in the handling of iscntrl().  Although the
 *	manuals all say that if c is a white-space character that is
 *	not a blank, then iscntrl(c) is true, several versions of the
 *	C library disagree with the documentation.  Thus we try to
 *	list all the white-space characters explicitly.
 */

#include "asd.h"
#include <ctype.h>
#include <stdio.h>

#define CHUNK 64

static char *r;
static unsigned size;

char *
getpath (FILE *file)
{
	register int c;
	register int len = 0;

	c = getc (file);

	while (!isspace(c) && c != EOF) {
		register int i = 0, n = 0;

		/* determine the next input character */
		if (c == '\\') {
			c = getc (file);
			switch (c) {

			case '\\':
				break;
			
			case 'n':
				c = '\n';
				break;

			case 'r':
				c = '\r';
				break;

			case 't':
				c = '\t';
				break;

			case 'b':
				c = '\b';
				break;
			
			case 'f':
				c = '\f';
				break;
			
			case 'v':
				c = '\v';
				break;
			
			case ' ':
			     /* c = ' '; */
				break;

			default:
				while (c >= '0' && c <= '7' && i < 3) {
					n = (n << 3) + c - '0';
					i++;
					c = getc (file);
				}
				ungetc (c, file);
				c = n;
				break;
			}
		}

		/* ensure there's room in the buffer */
		if (len >= size)
			r = ralloc (r, size += CHUNK);

		/* put the character in the buffer */
		r[len++] = c;

		/* read the next character */
		c = getc (file);
	}

	/* unless we hit eof, we read one character too far. */
	if (c != EOF)
		ungetc (c, file);
	
	/* put a final null into the buffer */
	if (len >= size)
		r = ralloc (r, size += CHUNK);
	r[len] = '\0';

	return r;
}

void
putpath (FILE *file, char *path)
{
	register char *p = path;
	register int c;
	
	while ((c = *p++) != NULL) {
		switch (c) {

		case '\n':
			fprintf (file, "\\n");
			break;

		case '\r':
			fprintf (file, "\\r");
			break;

		case '\b':
			fprintf (file, "\\b");
			break;

		case '\t':
			fprintf (file, "\\t");
			break;

		case '\f':
			fprintf (file, "\\f");
			break;
		
		case '\v':
			fprintf (file, "\\v");
			break;
		
		case '\\':
			fprintf (file, "\\\\");
			break;
		
		case ' ':
			fprintf (file, "\\ ");
			break;
		
		default:
			if (iscntrl (c))
				fprintf (file,
				    *p >= '0' && *p <= '7'? "\\%.3o": "\\%o",
				    c);
			else
				putc (c, file);
			break;
		}
	}
}
e '\r':
			fprintf (file, "\\r");
			break;

		case '\b':
			fprintf (file, "\\b");
			break;

		case '\t':
			fprintf (file, "\\t");
			break;

		case '\f':
			fprintf (file, "\\f");
			break;
		
		case '\v':
			fprintf (file, "\\v");
			break;
		
		case '\\':
			fprintf (file, "\\\\");
			break;
		
		case ' ':
			fprintf (file, "\\ ");
			break;
		
		default:
			if (iscntrl (c))
				fprintf (file,
				    *p >= pkg/pwd.c   644   3513      4        1113  5013610576   5623 /*
 *	pwd() - return the name of the current directory.
 *	We assume that the current directory never changes.
 */

#include "asd.h"
#include <libv.h>
#include <stdio.h>

#define CHUNK 64

char *
pwd(void)
{
	register FILE *f;
	static char *r;
	static unsigned size;
	register int n, c;

	if (r == NULL) {
		f = popen ("pwd", "r");
		schk ((char *) f);
		
		n = 0;
		while ((c = getc (f)) != EOF) {
			if (n >= size) {
				size += CHUNK;
				r = ralloc (r, size);
			}
			r[n++] = c;
		}

		/* replace the trailing newline by a null */
		r[n - 1] = '\0';

		pclose (f);
	}

	return r;
}
he current directory never changes.
 */

#include "asd.h"
#include <libv.h>
#include <stdio.h>

#define CHUNK 64

char *
pwd(void)
{
	register FILE *f;
	static char *r;
	static unsigned size;
	register int n, c;

	if (r == NULL) {
		f = popen ("pwd", "r");
		schk ((char *) f);
		
		n = 0;
		while ((c = getc (f)) != EOF) {
			if (n >= size) {
				size += CHUNK;
				r = ralloc (r, size);
			}
			r[n++] = c;
		}

		/* replace the trailipkg/seal.c   644   3513      4        5522  5013610577   5766 /*
 *	seal - prepare a package for shipment
 */

#include "asd.h"
#include "seal.h"
#include <ctype.h>
#include <string.h>

static long length;
static unsigned long checksum;

/*
 *	convert the characters in the range (in,inend] to
 *	storage starting at "out" -- return the number of
 *	output characters.
 */

static int
hrform (char *in, char *inend, char *out)
{
	register char *r = out;

	/* special handling for the first character(s) */
	if (in < inend) {
		if (*in == '.' || *in == '!' ||
		    (*in == 'F' && strncmp (in, "From", 4) == 0))
			*r++ = '\\';

		do {
			register int ch = (unsigned char) *in++;

			if (isprint (ch)) {
				if (ch == '\\')
					*r++ = '\\';
				*r++ = ch;
			} else {
				if (ch == ' ' || ch == '\t' || ch == '\n')
					*r++ = ch;
				else {
					*r++ = '\\';
					*r++ = hextab[(ch >> 4) & 0xf];
					*r++ = hextab[ch & 0xf];
				}
			}
		} while (in < inend);

		if (r[-1] != '\n') {
			*r++ = '\\';
			*r++ = '\n';
		}
	}

	return r - out;
}

static int
mrform (char *in, char *inend, char *out)
{
	char *r;
	register int len;

	len = inend - in;
	if (len <= 0)
		return 0;

	r = out;

	*r++ = '.';

	do {
		register unsigned long bits;
		register int n, outn;
		register char *rr;

		n = len;
		if (n > INCPW)
			n = INCPW;
		len -= n;
		outn = n + OUTCPW - INCPW;

		bits = 0;
		do	bits = (bits << BPC) | (*in++ & BYTEMASK);
		while (--n > 0);

		rr = r = r + outn;
		do {
			*--rr = RADBASE + bits % RADIX;
			bits /= RADIX;
		} while (--outn > 0);
	} while (len > 0);

	*r++ = '\n';

	return r - out;
}


static int
seal (FILE *f, char *fname)
{
	static int first = 1;

	if (first) {
		first = 0;
		printf ("!<seal>\n");
	}

	do {
		char line[MAXLINE];
		char outline[MAXLINE*3+10];
		register char *p, *endl;
		register int ch;

		/* read a line, possibly short */
		p = line;
		endl = line + MAXLINE;

		do {
			ch = getc (f);
			if (ch == EOF)
				break;
			*p++ = ch;
		} while (ch != '\n' && p < endl);

		endl = p;

		/*
		 * endl now points one past the last char
		 * in the line we have read.  If we didn't
		 * get any characters at all, we're done.
		 */

		if (line == endl)
			return ferror (f) != 0;

		length += endl - line;

		/* now convert the line to external form */
		ch = hrform (line, endl, outline);
		if (ch > (endl - line + INCPW - 1) / INCPW * OUTCPW + 2)
			ch = mrform (line, endl, outline);
		p = outline;

		/* if encrypting, do so */
		if (kflag || Kflag)
			mangle (line, endl);

		/* accumulate the (possibly encrypted) checksum */
		checksum = mkcsum (checksum, line, endl);

		while (--ch >= 0)
			putchar (*p++);
	} while (!feof (f) && !ferror (f));

	return ferror (f) != 0;
}

int
main (int argc, char **argv)
{
	int rc = 0;
	static char stdbuf[BUFSIZ];

	setbuf (stdout, stdbuf);

	length = 0;
	checksum = 0;

	rc = getargs (argc, argv, "kK:", seal);

	printf ("!end %ld %lu\n", length, checksum);

	return rc;
}
 if encrypting, do so */
		if (kflag || Kflag)
			mangle (line, endl);

		/* accumulate the (possibly encrypted) checksum */
		checksum = mkcsum (checksum, line, endl);

		whpkg/seal.h   644   3513      4         515  5013610577   5750 /*
 *	common parameters for seal and unseal
 */

#define	MAXLINE 100
#define	MAXULINE 200
#define	RADBASE (' ' + 1)
#define	INCPW 4
#define	OUTCPW 5
#define	RADIX 94
#define	BPC 8
#define	BYTEMASK 0xff
#define	CSMASK 0xffffffffL
#define	CSHIBIT	0x80000000L

/* mkcsum.c */
extern unsigned long mkcsum(unsigned long, char *, char *);
c;
}
 if encrypting, do so */
		if (kflag || Kflag)
			mangle (line, endl);

		/* accumulate the (possibly encrypted) checksum */
		checksum = mkcsum (checksum, line, endl);

		whpkg/transname.c   644   3513      4        1701  5013610600   7010 /*
 *	transname - take a pathname, expand it, and translate it
 *	according to the replist.  The result is in a buffer
 *	that will stay around no longer than the next call
 *	to transname.  If no translation, transname will
 *	just return fullname applied to its argument.
 */

#include "asd.h"
#include <string.h>

char *
transname (char *s)
{
	register struct replist *rl;
	static char *res;
	static int size;
	register int n;

	s = fullname (s);

	/* look for substitution */
	for (rl = replist; rl; rl = rl->link) {
		register char *p = rl->source;
		register char *q = s;

		/* comparison loop */
		while (*p != '\0' && *p == *q) {
			p++;
			q++;
		}

		if (*p == '\0') {
			/* comparison successful */
			n = strlen (rl->dest) + strlen (q) + 1;
			if (n > size) {
				size = n;
				res = ralloc (res, (unsigned) n);
			}
			strcpy (res, rl->dest);
			strcat (res, q);
			return res;
		}
	}

	/* search loop failed, return expanded input */
	return s;
}


	/* look for substitution */
	for (rl = replist; rl; rl = rl-pkg/uid.c   644   3513      4        2535  5013610601   5610 #include "asd.h"
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


#define CHUNK 16

static struct utab {
	unsigned uid;
	char *name;
} *utab;

static int size, salloc;

char *
uidstr (uid_t uid)
{
	register int i;
	static char buf[12];
	struct passwd *p;

	/* search the cache for the uid */
	for (i = 0; i < size; i++)
		if (utab[i].uid == uid)
			return utab[i].name;

	/* try to find it in the system's database */
	if (p = getpwuid(uid)) {
		if (size % CHUNK == 0)
			utab = (struct utab *) ralloc((char *) utab, salloc += CHUNK);
		utab[size].uid = p->pw_uid;
		utab[size].name = copy(p->pw_name);
		++size;
		return utab[size - 1].name;
	}

	/* failure, invent a string */
	sprintf (buf, "#%u", uid);
	return buf;
}

uid_t
uidnum (char *name)
{
	register int i;
	struct passwd *p;

	/* if it starts with a #, use the number */
	if (name[0] == '#')
		return atoi (name + 1);

	/* try to find it in the system's database */
	if (p = getpwnam(name)) {
		if (size % CHUNK == 0)
			utab = (struct utab *) ralloc((char *) utab, salloc += CHUNK);
		utab[size].uid = p->pw_uid;
		utab[size].name = copy(p->pw_name);
		++size;
		return utab[size - 1].uid;
	}

	/* search the cache */
	for (i = 0; i < size; i++)
		if (strcmp (utab[i].name, name) == 0)
			return utab[i].uid;

	/* failure, invent a value */
	return getuid();
}
#, use the number */
	if (name[0] == '#')
		return atoi (name + 1);

	/* try to find it in the system's database */
	if (p = getpwnam(name)) {
		if (size % CHUNK =pkg/unseal.c   644   3513      4       10352  5013610601   6332 /*
 *	unseal - disclose and verify the contents of a sealed package
 */

#include "asd.h"
#include "seal.h"
#include <ctype.h>
#include <string.h>
#include <unistd.h>

static FILE *outfd;
static char outf[L_tmpnam];
static char line[MAXULINE];

static unsigned long length, checksum;

static char *
csverify (char *p, unsigned long value)
{
	register unsigned long n = 0;

	while (isspace (*p))
		p++;

	if (!isdigit (*p))
		return NULL;

	do	n = n * 10 + *p++ - '0';
	while (isdigit (*p));

	if (!isspace (*p))
		return NULL;

	if (n != value)
		return NULL;

	return p;
}

int
docksum (char *line, unsigned long length, unsigned long checksum)
{
	register char *p = line + 5;

	p = csverify (p, length);
	if (p == NULL) {
		fprintf (stderr, "unseal: invalid length\n");
		return 1;
	}
	p = csverify (p, checksum);
	if (p == NULL) {
		fprintf (stderr, "unseal: invalid checksum\n");
		return 1;
	}
	return 0;
}

static int
unhex (int c)
{
	register char *p;

	p = hextab;
	while (*p && *p != c)
		p++;
	if (*p)
		return p - hextab;
	return -1;
}

static int
hrout (char *line, char *out)
{
	register char *p, *q;
	register int ch;

	p = line;
	q = out;

	while ((ch = *p++) != '\0') {
		if (ch != '\\') {
			*q++ = ch;
		} else {
			ch = *p++;
			if (ch == '\\' || ch == '.' || ch == '!' || ch == 'F') {
				*q++ = ch;
			} else if (ch != '\n') {
				register int n = 0, i = 1;

				do {
					ch = unhex (ch);
					if (ch < 0) {
						fprintf (stderr,
							"bad hex char: %s", line);
						return -1;
					}
					n = (n << 4) | ch;
					if (i)
						ch = *p++;
				} while (--i >= 0);

				*q++ = n;
			}
		}
	}

	return q - out;
}

static int
mrout (char *line, char *out)
{
	register char *p = line + 1;
	char *q = out;

	while (*p != '\n' && *p != '\0') {
		register unsigned long bits;
		register int n;
		register char *rq;

		n = 0;
		bits = 0;
		do {
			register int ch = *p++;
			if (ch == '\n')
				break;
			if (ch < RADBASE || ch >= RADBASE + RADIX) {
				fprintf (stderr, "bad input char: %s", line);
				return -1;
			}
			bits = bits * RADIX + ch - RADBASE;
			n++;
		} while (n < OUTCPW);

		n -= OUTCPW - INCPW;
		if (n <= 0) {
			fprintf (stderr, "non-positive output count: %s", line);
			return -1;
		}

		rq = q = q + n;
		do {
			*--rq = bits;
			bits >>= BPC;
		} while (--n > 0);
	}

	return q - out;
}

static int
dodata (char *line)
{
	char out[MAXULINE * 2];
	int r;

	r = (*(line[0] == '.'? mrout : hrout)) (line, out);
	if (r < 0)
		return 1;
	fwrite (out, sizeof(*out), r, outfd);
	length += r;

	if (kflag || Kflag)
		mangle (out, out + r);

	checksum = mkcsum (checksum, out, out + r);

	return 0;
}

static int
unseal (FILE *f, char *fname)
{
	int intext = 0, rc = 0, nulltext = 1;

	length = checksum = 0;
	resetN12();

	while (fgets (line, MAXULINE, f) != NULL) {

		/* check for a control line, which starts with "!" */
		if (line[0] == '!') {
			if (intext) {
				/* only thing allowed is !end */
				if (strncmp (line + 1, "end ", 4) == 0) {
					rc += docksum (line, length, checksum);
					intext = 0;
				} else {
					fprintf (stderr, "invalid control line %s", line);
					rc++;
				}
			} else {
				/* look for header, else quietly ignore */
				if (strcmp (line + 1, "<seal>\n") == 0) {
					intext++;
					nulltext = 0;
				}
			}
		/* data lines are quietly ignored if not in text */
		} else if (intext) {
			rc += dodata (line);
		}
	}

	if (nulltext) {
		fprintf (stderr, "unseal: no contents\n");
		rc++;
	}

	if (intext) {
		fprintf (stderr, "unseal: no checksum\n");
		rc++;
	}

	return rc;
}

int
main (int argc, char **argv)
{
	int rc = 0;
	int c;
	static char stdbuf[BUFSIZ];

	setbuf (stdout, stdbuf);

	umask (077);
	tmpnam (outf);
	outfd = fopen (outf, "w+");
	if (outfd == NULL) {
		fprintf (stderr, "unseal: can't create temp file\n");
		exit (1);
	}

	/* don't leave dregs */
	unlink (outf);

	rc = getargs (argc, argv, "kK:", unseal);
	
	/* if successful, copy the temp file to the output */
	if (rc == 0) {
		register FILE *in = outfd, *out = stdout;
		register int ch;

		rewind (in);

		while ((ch = getc (in)) != EOF)
			putc (ch, out);
		
		fflush (out);
		
		if (ferror (in)) {
			fprintf (stderr, "unseal: error reading temp file\n");
			rc++;
		}

		if (ferror (out)) {
			fprintf (stderr, "unseal: error writing stdout\n");
			rc++;
		}
	}

	return rc;
}
* don't leave dregs */
	unlink (outf);

	rc = getargs (argc, argv, "kK:", unseal);
	
	/* if successful, copy the temp file to the output */
	if (rc == 0) {
		register FILE *in = outfd, *out = stdout;
		register int ch;

		rewind (in);

		while ((ch = getc (in)) != EOF)
			putc pkg/libx.a   644   3513      4          44  5013644572   5732 674187646   f (ferror (in)) {
			fprintf (stderr, "unseal: error reading temp file\n");
			rc++;
		}

		if (ferror (out)) {
			fprintf (stderr, "unseal: error writing stdout\n");
			rc++;
		}
	}

	return rc;
}
* don't leave dregs */
	unlink (outf);

	rc = getargs (argc, argv, "kK:", unseal);
	
	/* if successful, copy the temp file to the output */
	if (rc == 0) {
		register FILE *in = outfd, *out = stdout;
		register int ch;

		rewind (in);

		while ((ch = getc (in)) != EOF)
			putc pkg/INSTRUCTIONS   644   3513      4        2022  5027730714   6556 The format of the Instructions file in a package archive
is as follows.

Each instruction is a line by itself.  Each instruction consists of a
single character instruction code followed by a number of fields.  Fields
do not contain spaces.

Various standard kinds of fields are:
<command>		shell command (via putpath())
<component>		archive component name (via putpath())
<mode>			octal permissions
<dmajor>, <dminor>	major and minor decimal device numbers
<uid>, <gid>		user and group names (via putpath())
<path>			path name (via putpath())

b <mode> <dmajor> <dminor> <uid> <gid> <path>
	block device
c <mode> <dmajor> <dminor> <uid> <gid> <path>
	character device
d <mode> <uid> <gid> <path>
	directory
f <component> <uid> <gid> <path>
	ordinary file (rest of the information is in the archive component)
l <path1> <path2>
	hard link -- <path2> is the link to be created.
s <path1> <path2>
	symbolic link -- <path2> is the link to be created.
r <path>
	file to be removed
x <command>
	command to be executed
X <path>
	file to be executed
a putpath())

b <mode> <dmajor> <dminor> <uid> <gid> <path>
	block device
c <mode> <dmajor> <dminor> <uid> <gid> <path>
	character device
d <mode> <uid> <gid> <path>
	directory
f <component> <uid> <gid> <path>
	ordinary file (rest of the information is in the archive component)
l <path1> <path2>
	hard link -- <path2> is the link to be created.
s <path1> <path2>
	symbolic link -- <path2> is the link to be created.
r <path>
	file to be removed
x <command>
	command to be executed
X <path>
	fipkg/ftw.c   644   3513      4       24531  5031452625   5661 /*
 *	ftw - file tree walk
 *
 *	int ftw (path, fn, depth)  char *path; int (*fn)(); int depth;
 *
 *	Given a path name, ftw starts from the file given by that path
 *	name and visits each file and directory in the tree beneath
 *	that file.  If a single file has multiple links within the
 *	structure, it will be visited once for each such link.
 *	For each object visited, fn is called with four arguments.
 *	The fourth can often be ignored; it is a pointer, say S,
 *	declared "struct FTW *S", discussed in more detail below.
 *	The first contains the path name of the object, the second
 *	contains a pointer to a stat buffer which will usually hold
 *	appropriate information for the object and the third contains
 *	an integer value giving additional information about the
 *	object, as follows:
 *
 *		FTW_F	The object is a file for which stat was
 *			successful.  It does not guarantee that the
 *			file can actually be read.
 *
 *		FTW_D	The object is a directory for which stat and
 *			open for read were both successful.  This is
 *			a preorder visit -- objects in the directory
 *			are yet to be visited.
 *
 *		FTW_DNR	The object is a directory for which stat
 *			succeeded, but which cannot be read.  Because
 *			the directory cannot be read, fn will not be
 *			called for any descendants of this directory.
 *
 *		FTW_DP	The object is a directory for which stat and
 *			open for read were both successful.  This is
 *			a postorder visit -- everything in the directory
 *			has already been visited.
 *
 *		FTW_NS	Lstat failed on the object.  If errno is EACCES,
 *			then the failure stems from lack of
 *			appropriate permission.  This indication will
 *			be given, for example, for each file in a directory
 *			with read but no execute permission.  Whenever
 *			stat fails, it is not possible to determine
 *			whether this object is a file or a directory.
 *			The stat buffer passed to fn will contain garbage.
 *
 *		FTW_SL  The object is a symbolic link.  Set S->quit
 *			(a component of the structure pointed to by
 *			the fourth parameter to fn) to FTW_FOLLOW to
 *			have the link followed and the object to which
 *			it points visited.
 *
 *		FTW_NSL Lstat succeeded, but stat failed on the object.
 *			This is only possible when following a symbolic
 *			link.
 *
 *	Among the components of the structure to which the fourth
 *	parameter, S, to fn points is S->quit.  If the caller sets
 *	S->quit to FTW_SKR, then no more files in the current directory
 *	will be visited.  (The current directory is the one containing
 *	the object being visited.)  If the third parameter to fn is
 *	FTW_D and the caller sets S->quit to FTW_SKD, then this directory
 *	(the one named in the first parameter to fn) will be skipped.
 *
 *	Other components pointed to by the fourth parameter S are
 *	the current recursion level S->level (top level = 0) and
 *	the offset S->base in the pathname of the current object
 *	(the first parameter to fn) of the object's base name.
 *	By expanding the definition of struct FTW given below and
 *	including the files included below, one can arrange for
 *	S to point to a larger structure, components of which can
 *	be initialized (for example) on calls to fn with third
 *	parameter FTW_D.
 *
 *	If fn returns nonzero, ftw stops and returns the same value
 *	to its caller.  Ftw only initiates a nonzero return if malloc
 *	fails; in this case ftw sets errno to ENOMEM and returns -1.
 *
 *	The third argument to ftw does not limit the depth to which
 *	ftw will go.  Rather, it limits the depth to which ftw will
 *	go before it starts recycling file descriptors.  In general,
 *	it is necessary to use a file descriptor for each level of the
 *	tree, but they can be recycled for deep trees by saving the position,
 *	closing, re-opening, and seeking.  It is possible to start
 *	recycling file descriptors by sensing when we have run out, but
 *	in general this will not be terribly useful if fn expects to be
 *	able to open files.  We could also figure out how many file descriptors
 *	are available and guarantee a certain number to fn, but we would not
 *	know how many to guarantee, and we do not want to impose the extra
 *	overhead on a caller who knows how many are available without
 *	having to figure it out.
 *
 *	It is possible for ftw to die with a memory fault in the event
 *	of a file system so deeply nested that the stack overflows.
 */

#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include "ftw.h"
/*
 * Struct FTW (whose definition starts at the end of ftw.h) must
 * must include at least the integers quit, base, and level.
 */

#define FTW_PATHLEN0 1000
#define FTW_PATHINC 1000

#ifndef S_ISLNK
#define lstat stat
#endif

#ifndef ENOMEM
#include <errno.h>
#endif

	extern int errno;

/*
 *  Each generation of ftw1 (the real ftw) allocates one copy, R, of the
 *  following structure; it passes a pointer to this structure when it
 *  recursively invokes itself.  These structures are chained together,
 *  so that if it becomes necessary to recycle file descriptors, then
 *  the oldest descriptor (the one at the shallowest depth still open)
 *  can be recycled.
 */

	struct FTW_rec {
		struct FTW_rec *prev;
		long here;	/* seek to here when reopening at this level */
		DIR *fd;	/* file descriptor at this level */
		};

/*
 *  One instance, T, of the following structure is allocated by ftw; a
 *  pointer to it is passed to all generations of ftw1 (the real ftw).
 *  T could often be a global variable, but this way the parameter fn
 *  can invoke ftw for an independent tree walk.
 *  Component T->path points to storage for the object path-names;
 *  this storage may be relocated by realloc if T->path needs to be
 *  more than T->pathlast characters long.
 *  T->path[T->pathnext] is the next free character in the pathnames.
 *  T->depth = parameter depth to ftw.  T->lastout is the deepest level at
 *  which a file descriptor has been recycled.
 */

	struct FTW_top {
		int (*fn)();
		char *path;
		unsigned pathlast, pathnext;
		int lastout;
		int depth;
		};

static ftw_1_();

int
ftw (path, fn, depth)
	char *path;
	int (*fn)();
	int depth;
{
	struct FTW_top T;
	struct FTW_rec R;
	struct FTW S;
	int rc;
	char *malloc(), *strcpy();

	T.depth = depth;
	T.lastout = -1;
	T.fn = fn;
	S.quit = 0;
	S.level = -1;

	/* initialize S.base, T.pathnext... */
		{
		register char c, *p, *q;
		for (p = q = path; c = *p; p++) if (c == '/') q = p + 1;
		S.base = q - path;
		T.pathnext = p - path;
		}

	T.pathlast = T.pathnext + FTW_PATHLEN0;
	T.path = malloc(T.pathlast);
	if (!T.path) { errno = ENOMEM; return -1; }
	strcpy(T.path, path);
	rc = ftw_1_(&R, &T, 0, &S);
	free(T.path);
	return rc;
}

int
static
ftw_1_ (R, T, level, S1)
	register struct FTW_rec *R;
	register struct FTW_top *T;
	int level;
	struct FTW *S1;
{
	int rc, n;
	DIR *fd;
	struct dirent *dirp;
	char *component, *path;
	struct stat sb;
	struct FTW_rec mr;
	unsigned nextsave;
	struct FTW S;
	char *realloc();
	long lseek();

	mr.prev = R;
	path = T->path;
	S.level = level;
	S.quit = 0;
	S.base = S1->base;

	/* Try to get file status.  If unsuccessful, errno will say why. */
	if (lstat(path, &sb) < 0) {
		rc = (*T->fn) (path, &sb, FTW_NS, &S);
		S1->quit = S.quit;
		return rc;
		};

	/*
	 *	The stat succeeded, so we know the object exists.
	 *	If not a directory, call the user function and return.
	 */
#ifdef S_ISLNK
	if (S_ISLNK(sb.st_mode )) {
		rc = (*T->fn) (path, &sb, FTW_SL, &S);
		S1->quit = S.quit;
		if (rc || S.quit == FTW_SKR) return rc;
		if (S.quit != FTW_FOLLOW) return 0;
		S1->quit = S.quit = 0;
		if (stat(path, &sb) < 0) {
			rc = (*T->fn) (path, &sb, FTW_NSL, &S);
			S1->quit = S.quit;
			return rc;
			};
		}
#endif
		
	if (!S_ISDIR(sb.st_mode)) {
		rc = (*T->fn) (path, &sb, FTW_F, &S);
		S1->quit = S.quit;
		return rc;
		}

	/*
	 *	The object was a directory.
	 *
	 *	Open a file to read the directory
	 */
	mr.fd = fd = opendir(path);

	/*
	 *	Call the user function, telling it whether
	 *	the directory can be read.  If it can't be read
	 *	call the user function or indicate an error,
	 *	depending on the reason it couldn't be read.
	 */
	if (!fd) {
		rc = (*T->fn) (path, &sb, FTW_DNR, &S);
		S1->quit = S.quit;
		return rc;
		}

	/* We could read the directory.  Call user function. */
	rc = (*T->fn) (path, &sb, FTW_D, &S);
	if (rc != 0)
		goto rtrn;
	if (S.quit == FTW_SKD) goto rtrn;
	if (S.quit == FTW_SKR) {S1->quit = FTW_SKR; goto rtrn;}

	/* Make sure path is big enough to hold generated pathnames. */

	n = nextsave = T->pathnext;
	if (n + MAXNAMLEN + 1 >= T->pathlast) {
		T->pathlast += FTW_PATHINC;
		path = T->path = realloc(T->path, T->pathlast);
		if (!path) {
			errno = ENOMEM;
			rc = -1;
			goto rtrn;
			}
		}
	
	/* Create a prefix to which we will append component names */

	if (n > 0 && path[n-1] != '/') path[n++] = '/';
	component = path + n;

	/*
	 *	Read the directory one component at a time.
	 *	We must ignore "." and "..", but other than that,
	 *	just create a path name and call self to check it out.
	 */
	while (dirp = readdir(fd)) {
		if (dirp->d_ino != 0
		    && strcmp (dirp->d_name, ".") != 0
		    && strcmp (dirp->d_name, "..") != 0) {
			int i;
			struct FTW_rec *pr;

			/* Append the component name to the working path */
			strcpy(component, dirp->d_name);
			T->pathnext = n + strlen(dirp->d_name);

			/*
			 *	If we are about to exceed our depth,
			 *	remember where we are and close the file.
			 */
			if (level - T->lastout >= T->depth) {
				pr = &mr;
				i = T->lastout++;
				while (++i < level) pr = pr->prev;
				pr->here = telldir(pr->fd);
				closedir(pr->fd);
			}

			/*
			 *	Do a recursive call to process the file.
			 */
			S.quit = 0;
			S.base = n;
			rc = ftw_1_(&mr, T, level+1, &S);
			if (rc != 0 || S.quit == FTW_SKR) {
				if (level > T->lastout) closedir(fd);
				T->pathnext = nextsave;
				return rc;
			}

			/*
			 *	If we closed the file, try to reopen it.
			 */
			if (level <= T->lastout) {
				char c = path[nextsave];
				path[nextsave] = 0;
				T->lastout = level - 1;
				mr.fd = fd = opendir(path);
				if (!fd) {
					rc = (*T->fn) (path, &sb, FTW_DNR, &S);
					S1->quit = S.quit;
					T->pathnext = nextsave;
					return rc;
					}
				path[nextsave] = c;
				seekdir(fd, mr.here);
				}
			}
		}
	T->pathnext = nextsave;
	path[nextsave] = 0;

	/*
	 *	We got out of the subdirectory loop.  Call the user
	 *	function again at the end and clean up.
	 */

	rc = (*T->fn) (path, &sb, FTW_DP, &S);
	S1->quit = S.quit;
rtrn:
	closedir(fd);
	return rc;
}
			T->lastout = level - 1;
				mr.fd = fd = opendir(path);
				if (!fd) {
					rc = (*T->fn) (path, &sb, FTW_DNR, &S);
					S1->quit = S.quit;
					T->pathnext = nextspkg/ftw.h   644   3513      4        1462  5031452570   5643 #ifndef __FTW
#define __FTW

/*
 *	Codes for the third argument to the user-supplied function
 *	which is passed as the second argument to ftw...
 */

#define	FTW_F	0	/* file */
#define	FTW_D	1	/* directory */
#define	FTW_DNR	2	/* directory without read permission */
#define	FTW_NS	3	/* unknown type, stat failed */
#define FTW_DP	4	/* directory, postorder visit */
#define FTW_SL	5	/* symbolic link */
#define FTW_NSL 6	/* stat failed (errno = ENOENT) on symbolic link */

/*	Values the user-supplied function may wish to assign to
	component quit of struct FTW...
 */

#define FTW_SKD 1	/* skip this directory (2nd par = FTW_D) */
#define FTW_SKR 2	/* skip rest of current directory */
#define FTW_FOLLOW 3	/* follow symbolic link */

struct FTW { int quit, base, level;
#ifndef FTW_more_to_come
	};
#endif

#endif
 failed */
#define FTW_DP	4	/* directory, postorder visit */
#define FTW_SL	5	/* symbolic link */
#define FTW_NSL 6	/* stat failed (errno = ENOENT) on symbolic link */

/*	Values the user-supplied function plan9/   755   3513      4           0  5031450043   5035 sysv/   755   3513      4           0  5031457617   5034 sysv/lcreat.c   644   3513      4         172  5031151403   6477 #include <fcntl.h>

int
lcreat(char *name, int mode)
{
	return open(name, O_EXCL | O_CREAT | O_TRUNC | O_WRONLY, mode);
}
#define �<     �< ����9 of 05031457617ctory �<  ����9_FOL00000005034low symbolic link */

struct FTW { int quit, base, level;
#ifndef FTW_more_to_come
	};
#endif

#endif
 failed */
#define FTW_DP	4	/* directory, postorder visit */
#define FTW_SL	5	/* symbolink */
����/������D5����/����D5��e�#�����.$����$e�sysv/canon.c   644   3513      4         531  5031141175   6327 #include <string.h>

/* reduce tcp and dk names to their final component */
void
canon(char *sys, char cansys[])
{
	if (strncmp(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
y, postorder visit */
#define FTW_SL	5	/* symbolink */
����/������D5����/����D5��e�#�����.$����$e�sysv/canonmain.c   644   3513      4         176  5031141232   7173 main(int argc, char **argv)
{
	char cansys[256];

	while (--argc) {
		canon(*++argv, cansys);
		puts(cansys);
	}
	return 0;
}
p(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
y, postorder visit */
#define FTW_SL	5	/* symbolink */
����/������D5����/����D5��e�#�����.$����$e�sysv/connect.c   644   3513      4        3221  5031146510   6677 /* usage: connect hostname (answer|send|notice) (in|out) program [ args ... ] */
/* TODO: should librarify the bit for opening an rsh-authenticated connection.  */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include "../paths.h"

int
main(int argc, char *argv[])
{
	int fd;
	struct hostent *host;
	struct servent *serv;
	struct passwd *pw;
	int lport;
	struct sockaddr_in sin;
	char byte;

	if (argc < 5)
		exit(1);

	host = gethostbyname(argv[1]);
	if (!host) {
		fprintf(stderr, "connect: can't get host '%s'\n", argv[1]);
		exit(1);
	}

	serv = getservbyname("dist", "tcp");
	if (!serv) {
		fprintf(stderr, "connect: can't get 'dist' port number\n");
		exit(1);
	}

	pw = getpwuid(getuid());	/* we assume unique uid/name map */
	if (!pw) {
		fprintf(stderr, "connect: can't get user name\n");
		exit(1);
	}

	chdir(LDIR);

	lport = 1023;
	fd = rresvport(&lport);
	if (fd < 0) {
		perror("connect: getting socket");
		exit(1);
	}

	sin.sin_family = host->h_addrtype;
	memcpy(&sin.sin_addr, host->h_addr, host->h_length);
	sin.sin_port = serv->s_port;
	if (connect(fd, &sin, sizeof sin) < 0) {
		perror("connect: opening connection");
		exit(1);
	}

	write(fd, "", 1);	/* a NUL byte */
	write(fd, pw->pw_name, strlen(pw->pw_name) + 1);
	write(fd, pw->pw_name, strlen(pw->pw_name) + 1);
	if (read(fd, &byte, 1) != 1 || byte != '\0') {
		fprintf(stderr, "connect: rsh authentication failed\n");
		exit(1);
	}

	write(fd, argv[2], strlen(argv[2]) + 1);

	if (strchr(argv[3], 'i'))
		dup2(fd, 0);
	if (strchr(argv[3], 'o'))
		dup2(fd, 1);
	close(fd);
	execv(argv[4], &argv[4]);
}
(fd, &sin, sizeof sin) < 0) {
		perror("connect: opening connection");
		exit(1);
	}

	write(fd, "", 1);	/* a NUL byte */
	write(fd, pw->pw_name, strlen(pw->pw_name) + 1);
	write(fd, pw->pw_name, strlen(pw->pw_name) + 1);
	if (read(fd, &byte, 1) != 1 || byte != '\0') {
		fprintf(stderr, "connect: rsh authentication failed\n");
		exit(1);
	}

	write(fd, argv[2], strsysv/dispatch.c   644   3513      4        1700  5031146670   7054 /* usage: dispatch <ipc args> */
/* TODO: connect input to /dev/null if peer wants no output,
   connect output to logfile if peer wants no input.  */

#include <sys/types.h>
#include <sys/sockets.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include "../paths.h"

int
main(int argc, char *argv[])
{
	char c, d;
	char *args[3];
	int fd;

	if (chdir(LDIR) < 0)
		return 1;

	/* TODO: at this point, perform rshd style authentication check,
	   set the appropriate user id, and all that.  See what kind of
	   args we can get from inetd.  */

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;
	while (d);

	fd = open("/dev/null", 1);
	dup2(fd, 2);
	if (fd > 2)
		close(fd);

	switch (c) {
	case 's':
		args[0] = "showq";
		execv("showq", args);
		break;
	case 't':
		args[0] = "transmit";
		execv("transmit", args);
		break;
	case 'n':
		args[0] = "notice";
		execv("notice", args);
		break;
	}

	return 1;
}
tion check,
	   set the appropriate user id, and all that.  See sysv/mkfile   644   3513      4        1012  5031452776   6306 <../mkconf.sysv

CC=cc
LPROG=connect canon #dispatch
LIBS=lib.a
LIBOBJ=canon.o lcreat.o

%: %.sh
	cp $stem.sh $target
	chmod +x $target

connect: connect.o
	$CC $CFLAGS -o connect connect.o

dispatch: dispatch.o
	$CC $CFLAGS -o dispatch dispatch.o

canon: canonmain.o lib.a
	$CC $CFLAGS -o canon canonmain.o lib.a

compile:V: $LPROG $LIBS

install:V:
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR
	chown root $LDIR/connect && chmod 4755 $LDIR/connect

lib.a: $LIBOBJ
	ar r lib.a $LIBOBJ

clean:V:
	rm -f $LPROG $LIBS *.o
.sysv

CC=cc
LPROG=connect canon #dispatch
LIBS=lib.a
LIBOBJ=canon.o lcreat.o

%: %.sh
	cp $stem.sh $target
	chmod +x $target

connect: connect.o
	$CC $CFLAGS -o connect connect.o

dispatch: dispatch.o
	$CC $CFLAGS -o dispatch dispatch.o

canon: canonmain.o lib.a
	$CC $CFLAGS -o canon canonmain.o lib.a

compile:V: $LPROG $LIBS

install:V:
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR
	chown root $LDIR/connect && chmod 4755 $LDIR/connect

lib.a: $LIBOBJ
	ar r lib.a $LIBOBJ

clean:V:
	rm -f $LPROG sysv/libv.h   644   3513      4          50  5031457617   6161 extern int optind;
extern char *optarg;
on #dispatch
LIBS=lib.a
LIBOBJ=canon.o lcreat.o

%: %.sh
	cp $stem.sh $target
	chmod +x $target

connect: connect.o
	$CC $CFLAGS -o connect connect.o

dispatch: dispatch.o
	$CC $CFLAGS -o dispatch dispatch.o

canon: canonmain.o lib.a
	$CC $CFLAGS -o canon canonmain.o lib.a

compile:V: $LPROG $LIBS

install:V:
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR
	chown root $LDIR/connect && chmod 4755 $LDIR/connect

lib.a: $LIBOBJ
	ar r lib.a $LIBOBJ

clean:V:
	rm -f $LPROG v10/   755   3513      4           0  5032703620   4423 v10/mkfile   644   3513      4         766  5030710404   5667 <../mkconf.v10

CC=lcc
LPROG=connect dispatch canon hostname
LIBS=lib.a
LIBOBJ=canon.o lcreat.o

%: %.sh
	cp $stem.sh $target
	chmod +x $target

connect: connect.o
	$CC $CFLAGS -o connect connect.o -lipc

dispatch: dispatch.o
	$CC $CFLAGS -o dispatch dispatch.o -lipc

canon: canonmain.o lib.a
	$CC $CFLAGS -o canon canonmain.o lib.a

compile:V: $LPROG $LIBS

install:V:
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR

lib.a: $LIBOBJ
	ar r lib.a $LIBOBJ
	ranlib lib.a

clean:V:
	rm -f $LPROG $LIBS *.o
�$e�v10/connect.c   644   3513      4        1000  5030753426   6303 /* usage: connect hostname (answer|send|notice) (in|out) program [ args ... ] */

#include <ipc.h>
#include <string.h>
#include "../paths.h"

int
main(int argc, char *argv[])
{
	int fd;

	if (argc < 5)
		return 1;

	chdir(LDIR);

	fd = ipcopen(ipcpath(argv[1], "dk", "dist"), "heavy bsdauth");
	if (fd < 0) {
		perror(argv[1]);
		return 1;
	}

	write(fd, argv[2], strlen(argv[2]) + 1);

	if (strchr(argv[3], 'i'))
		dup2(fd, 0);
	if (strchr(argv[3], 'o'))
		dup2(fd, 1);
	close(fd);
	execv(argv[4], &argv[4]);
}
v10/dispatch.c   644   3513      4        1475  5024760412   6465 /* usage: dispatch <ipc args> */
/* TODO: connect input to /dev/null if peer wants no output,
   connect output to logfile if peer wants no input.  */

#include <ipc.h>
#include <string.h>
#include "../paths.h"

int
main(int argc, char *argv[])
{
	char c, d;
	char *args[3];
	int fd;

	if (chdir(LDIR) < 0)
		return 1;

	(args[1] = strchr(argv[1], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;
	while (d);

	fd = open("/dev/null", 1);
	dup2(fd, 2);
	if (fd > 2)
		close(fd);

	switch (c) {
	case 's':
		args[0] = "showq";
		execv("showq", args);
		break;
	case 't':
		args[0] = "transmit";
		execv("transmit", args);
		break;
	case 'n':
		args[0] = "notice";
		execv("notice", args);
		break;
	}

	return 1;
}
;

	(args[1] = strchr(argv[1], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/lcreat.c   644   3513      4         443  5020263747   6117 int
lcreat(char *name, int mode)
{
	char temp[14];
	int fd;

	sprintf(temp, "lcreat.%d", getpid());	/* only works in same file system */
	fd = creat(temp, mode);
	if (fd < 0)
		return fd;
	if (link(temp, name) < 0) {
		close(fd);
		unlink(temp);
		return -1;
	}
	unlink(temp);
	return fd;
}
		break;
	}

	return 1;
}
;

	(args[1] = strchr(argv[1], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/canon.c   644   3513      4         531  5030711060   5724 #include <string.h>

/* reduce tcp and dk names to their final component */
void
canon(char *sys, char cansys[])
{
	if (strncmp(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/canonmain.c   644   3513      4         176  5030712000   6571 main(int argc, char **argv)
{
	char cansys[256];

	while (--argc) {
		canon(*++argv, cansys);
		puts(cansys);
	}
	return 0;
}
p(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/hostname.sh   644   3513      4          35  5021475777   6641 #! /bin/sh -
cat /etc/whoami

	char cansys[256];

	while (--argc) {
		canon(*++argv, cansys);
		puts(cansys);
	}
	return 0;
}
p(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;sysv/libv.h   644   3513      4          50  5031457617   6161 extern int optind;
extern char *optarg;
on #dispatch
LIBS=lib.a
LIBOBJ=canon.o lcreat.o

%: %.sh
	cp $stem.sh $target
	chmod +x $target

connect: connect.o
	$CC $CFLAGS -o connect connect.o

dispatch: dispatch.o
	$CC $CFLAGS -o dispatch dispatch.o

canon: canonmain.o lib.a
	$CC $CFLAGS -o canon canonmain.o lib.a

compile:V: $LPROG $LIBS

install:V:
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR
	chown root $LDIR/connect && chmod 4755 $LDIR/connect

lib.a: $LIBOBJ
	ar r lib.a $LIBOBJ

clean:V:
	rm -f $LPROG v10/   755   3513      4           0  5032703620   4423 v10/mkfile   644   3513      4         766  5030710404   5667 <../mkconf.v10

CC=lcc
LPROG=connect dispatch canon hostname
LIBS=lib.a
LIBOBJ=canon.o lcreat.o

%: %.sh
	cp $stem.sh $target
	chmod +x $target

connect: connect.o
	$CC $CFLAGS -o connect connect.o -lipc

dispatch: dispatch.o
	$CC $CFLAGS -o dispatch dispatch.o -lipc

canon: canonmain.o lib.a
	$CC $CFLAGS -o canon canonmain.o lib.a

compile:V: $LPROG $LIBS

install:V:
	test -d $LDIR || mkdir $LDIR
	cp $LPROG $LDIR

lib.a: $LIBOBJ
	ar r lib.a $LIBOBJ
	ranlib lib.a

clean:V:
	rm -f $LPROG $LIBS *.o
�$e�v10/connect.c   644   3513      4        1000  5030753426   6303 /* usage: connect hostname (answer|send|notice) (in|out) program [ args ... ] */

#include <ipc.h>
#include <string.h>
#include "../paths.h"

int
main(int argc, char *argv[])
{
	int fd;

	if (argc < 5)
		return 1;

	chdir(LDIR);

	fd = ipcopen(ipcpath(argv[1], "dk", "dist"), "heavy bsdauth");
	if (fd < 0) {
		perror(argv[1]);
		return 1;
	}

	write(fd, argv[2], strlen(argv[2]) + 1);

	if (strchr(argv[3], 'i'))
		dup2(fd, 0);
	if (strchr(argv[3], 'o'))
		dup2(fd, 1);
	close(fd);
	execv(argv[4], &argv[4]);
}
v10/dispatch.c   644   3513      4        1475  5024760412   6465 /* usage: dispatch <ipc args> */
/* TODO: connect input to /dev/null if peer wants no output,
   connect output to logfile if peer wants no input.  */

#include <ipc.h>
#include <string.h>
#include "../paths.h"

int
main(int argc, char *argv[])
{
	char c, d;
	char *args[3];
	int fd;

	if (chdir(LDIR) < 0)
		return 1;

	(args[1] = strchr(argv[1], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;
	while (d);

	fd = open("/dev/null", 1);
	dup2(fd, 2);
	if (fd > 2)
		close(fd);

	switch (c) {
	case 's':
		args[0] = "showq";
		execv("showq", args);
		break;
	case 't':
		args[0] = "transmit";
		execv("transmit", args);
		break;
	case 'n':
		args[0] = "notice";
		execv("notice", args);
		break;
	}

	return 1;
}
;

	(args[1] = strchr(argv[1], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/lcreat.c   644   3513      4         443  5020263747   6117 int
lcreat(char *name, int mode)
{
	char temp[14];
	int fd;

	sprintf(temp, "lcreat.%d", getpid());	/* only works in same file system */
	fd = creat(temp, mode);
	if (fd < 0)
		return fd;
	if (link(temp, name) < 0) {
		close(fd);
		unlink(temp);
		return -1;
	}
	unlink(temp);
	return fd;
}
		break;
	}

	return 1;
}
;

	(args[1] = strchr(argv[1], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/canon.c   644   3513      4         531  5030711060   5724 #include <string.h>

/* reduce tcp and dk names to their final component */
void
canon(char *sys, char cansys[])
{
	if (strncmp(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/canonmain.c   644   3513      4         176  5030712000   6571 main(int argc, char **argv)
{
	char cansys[256];

	while (--argc) {
		canon(*++argv, cansys);
		puts(cansys);
	}
	return 0;
}
p(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;v10/hostname.sh   644   3513      4          35  5021475777   6641 #! /bin/sh -
cat /etc/whoami

	char cansys[256];

	while (--argc) {
		canon(*++argv, cansys);
		puts(cansys);
	}
	return 0;
}
p(sys, "dk!", 3) == 0)
		sys += 3;
	if (strncmp(sys, "tcp!", 4) == 0)
		sys += 4;
	if (strrchr(sys, '/'))
		sys = strrchr(sys, '/') + 1;
	strcpy(cansys, sys);
	if (strrchr(cansys, '.'))
		*strchr(cansys, '.') = '\0';
}
], '=')) && ++args[1];
	(args[2] = strchr(argv[2], '=')) && ++args[2];
	args[3] = 0;

	if (read(0, &c, 1) != 1)
		return 1;
	do
		if (read(0, &d, 1) != 1)
			return 1;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.