echo x - Makefile.ansi
sed '/^X/s///' > Makefile.ansi << '/'
X# Makefile for simple (i.e., single-file) commands
X
Xl=/usr/lib
XCC=exec cc
X
XCFLAGS= -s -i -m -D_MINIX -D_POSIX_SOURCE -I/include
XPRINTK= -Dprintf=printk -Dfprintf=fprintk
X
X# The normal printf routine provided by MINIX is quite large (5K), at least
X# by MINIX standards, because it has to include all kinds of weird features
X# required by the ANSI standard.  However, many programs do not need all
X# these features.  These programs can get away with a much simpler version 
X# of printf (and fprintf) called printk (and fprintk).  The stunt below with
X# OBJ1 and OBJ2 divides the contents of this directory into files that can
X# use printk (OBJ1) and those that cannot (OBJ2).  
X
XOBJ1=animals ascii backup badblocks banner basename cal cat cd cdiff \
X    cgrep chmem chmod chown cksum clr cmp comm cp crc \
X    date dd decomp16 df dhrystone diskcheck du dw echo expand expr factor \
X    fgrep file find fix fold fortune fsck gather getlf getty grep gres \
X    head hyphenate id ifdef inodes join kill leave ln login look lpr machine \
X    man men mkdir mkfifo mknod modem more mount mv ncheck od \
X    paste pathchk prep pretty printenv printroot proto pwd readall recover \
X    rev rm rmdir shar size sleep sort split strings strip stty su \
X    sum swapfs sync tail tee term test time touch tr traverse treecmp tset \
X    tsort ttt tty umount uname unexpand uniq update vol wc \
X    whatsnew which whoami width xargs
X
XOBJ2=at atrun btoa calendar ci co compress cron cut diff diskusage ed fsck2 \
X    last ls mail mkfs mkproto mref nm passwd pr ps readfs roff sed tar \
X    termcap unshar users uud uue who write
X
XOBJ3=life gomoku
X
Xall:	$(OBJ1) $(OBJ2)
X
X$(OBJ1):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) $(PRINTK) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
X$(OBJ2):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
X$(OBJ3):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) -o bin/$@ $@.c -lcurses
X	@chmem =30000 bin/$@ >/dev/null 2>&1
X
X
Xclean:	
X	@rm -f *.o *.s *.bak
X
X
/
echo x - Makefile.kr
sed '/^X/s///' > Makefile.kr << '/'
X# Makefile for simple (i.e., single-file) commands
X
Xl=/usr/lib
XCC=exec cc
X
XCFLAGS= -i -D_MINIX -D_POSIX_SOURCE -I/include
XPRINTK= -Dprintf=printk -Dfprintf=fprintk
X
X# The normal printf routine provided by MINIX is quite large (5K), at least
X# by MINIX standards, because it has to include all kinds of weird features
X# required by the ANSI standard.  However, many programs do not need all
X# these features.  These programs can get away with a much simpler version 
X# of printf (and fprintf) called printk (and fprintk).  The stunt below with
X# OBJ1 and OBJ2 divides the contents of this directory into files that can
X# use printk (OBJ1) and those that cannot (OBJ2).  
X
XOBJ1=animals ascii backup badblocks banner basename cal cat cd cdiff \
X    cgrep chmem chmod chown cksum clr cmp comm cp crc \
X    date dd decomp16 df dhrystone diskcheck du dw echo expand expr factor \
X    fgrep file find fix fold fortune fsck gather getlf getty grep gres \
X    head hyphenate id ifdef inodes join kill leave ln login look lpr machine \
X    man men mkdir mkfifo mknod modem more mount mv ncheck od \
X    paste pathchk prep pretty printenv printroot proto pwd readall recover \
X    rev rm rmdir shar size sleep sort split strings strip stty su \
X    sum swapfs sync tail tee term test time touch tr traverse treecmp tset \
X    tsort ttt tty umount uname unexpand uniq update vol wc \
X    whatsnew which whoami width xargs
X
XOBJ2=at atrun btoa calendar ci co compress cron cut diff diskusage ed fsck2 \
X    last ls mail mkfs mkproto mref nm passwd pr ps readfs roff sed tar \
X    termcap unshar users uud uue who write
X
XOBJ3=life gomoku
X
Xall:	$(OBJ1) $(OBJ2)
X
X$(OBJ1):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) $(PRINTK) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
X$(OBJ2):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
X$(OBJ3):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) -o bin/$@ $@.c -lcurses
X	@chmem =30000 bin/$@ >/dev/null 2>&1
X
X
Xclean:	
X	@rm -f *.o *.s *.bak
X
X
/
echo x - calendar.c
sed '/^X/s///' > calendar.c << '/'
X/* calendar - reminder service		Authors: S. & K. Hirabayashi */
X
X/* Permission is hereby granted for nonprofit use. */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <time.h>
X#include <regexp.h>
X#include <limits.h>
X#include <stdlib.h>
X#include <string.h>
X#include <termcap.h>
X#include <unistd.h>
X#include <utime.h>
X#include <stdio.h>
X
X/* Change these two lines for your system needs. */
X#define MAIL1	"/usr/bin/mail"
X#define MAIL2	"/bin/mail"
X#define PASSWD	"/etc/passwd"	/* system password file */
X#define MAX_EXP		4	/* see date_exp() function */
X
Xchar *mail;			/* mail command path ("/bin/mail" etc) */
Xregexp *exp[MAX_EXP];		/* date expressions */
Xint nexp;			/* # of the date expressions */
Xchar calfile[PATH_MAX];		/* calendar file for the user */
X
Xint rflg;			/* consult aged 'calendar' file and touch */
Xint mflg;			/* mail (multi user) service */
Xchar *cmd;			/* the name of this command */
Xchar buf[BUFSIZ];
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void calendar, (void));
X_PROTOTYPE(char *getstr, (char *s, int n));
X_PROTOTYPE(int newaccess, (char *file));
X_PROTOTYPE(void grep, (char *file, char *user));
X_PROTOTYPE(int date_exp, (void));
X_PROTOTYPE(char *date_pat, (time_t t));
X_PROTOTYPE(void regerror, (char *s));
X_PROTOTYPE(void error, (char *s, char *t));
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  char *s;
X
X  cmd = *argv;
X  while (--argc > 0 && (*++argv)[0] == '-') {
X	s = argv[0] + 1;
X	if (*s == '\0')
X		mflg++;		/* mail service */
X	else if (strcmp(s, "r") == 0)
X		rflg++, mflg++;
X  }
X
X  if (mflg) {			/* check mailing agent */
X	if (access(MAIL1, X_OK) == 0)
X		mail = MAIL1;
X	else if (access(MAIL2, X_OK) == 0)
X		mail = MAIL2;
X	else
X		error("cannot find %s", MAIL1);
X  }
X  nexp = date_exp();
X  calendar();
X  exit(0);
X}
X
Xvoid calendar()
X{
X  int i;
X  char *s;
X  FILE *fp;
X
X  if (!mflg) {
X	grep("calendar", "");
X	return;
X  }
X
X  /* Mail sevice */
X  if ((fp = fopen(PASSWD, "r")) == (FILE *) NULL)
X	error("cannot open %s", PASSWD);
X
X  while (fgets(buf, BUFSIZ, fp) != (char *) NULL) {
X	for (i = 0, s = buf; *s && *s != '\n'; s++)
X		if (*s == ':') i++;
X	*s = '\0';
X	if (i != 6) error("illegal '/etc/passwd' format: %s", buf);
X
X	/* Calendar file = ${HOME}/calendar */
X	sprintf(calfile, "%s/%s", getstr(buf, 5), "calendar");
X
X	if ((access(calfile, R_OK) != 0) || (rflg && !newaccess(calfile)))
X		continue;
X
X	grep(calfile, getstr(buf, 0));
X  }
X
X  fclose(fp);
X}
X
Xchar *getstr(s, n)
Xchar *s;
Xint n;
X{
X/* Returns the string value of the n-th field in the record (s) */
X  int i;
X  char *t;
X  static char str[512];
X
X  for (i = 0; i < n && *s; s++)
X	if (*s == ':') i++;		/* field separator */
X  for (i = 0, t = str; *s && *s != ':' && i < 511; i++) *t++ = *s++;
X  *t = '\0';
X  return str;
X}
X
Xint newaccess(file)
Xchar *file;			/* file name */
X{
X/* Check whether the file has been touched today. */
X
X  int r = 0;
X  struct tm *tm;
X  struct stat stbuf;
X  time_t clk;
X  char newdate[8], olddate[8];
X
X  time(&clk);
X  tm = localtime(&clk);
X  sprintf(newdate, "%02d%02d%02d", tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
X
X  if (stat(file, &stbuf) == -1) error("cannot stat %s", file);
X  tm = localtime(&stbuf.st_mtime);
X  sprintf(olddate, "%02d%02d%02d", tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
X
X  if (strcmp(newdate, olddate) != 0) {
X	utime(file, NULL);	/* touch */
X	r++;
X  }
X  return r;
X}
X
Xvoid grep(file, user)
Xchar *file, *user;
X{				/* grep 'exp[]' [| mail user] */
X  int i;
X  char command[128];		/* mail command */
X  FILE *ifp, *ofp;
X
X  if ((ifp = fopen(file, "r")) == (FILE *) NULL)
X	error("cannot open %s", file);
X  if (*user != '\0') {
X	sprintf(command, "%s %s", mail, user);
X	ofp = (FILE *) NULL;
X  } else {
X	ofp = stdout;
X  }
X
X  while (fgets(buf, BUFSIZ, ifp) != (char *) NULL) {
X	for (i = 0; i < nexp; i++) {
X		if (regexec(exp[i], buf, 1)) {
X			if ((ofp == (FILE *) NULL) &&
X				  (ofp = popen(command, "w")) == (FILE *) NULL)
X				error("cannot popen %s", mail);
X			fputs(buf, ofp);
X		}
X	}
X  }
X
X  fclose(ifp);
X  if (ofp == stdout)
X	fflush(ofp);
X  else if (ofp != (FILE *) NULL)
X	pclose(ofp);
X}
X
Xint date_exp()
X{
X/* Set compiled regular expressions into the exp[] array. */
X  static int n[] = {2, 2, 2, 2, 2, 4, 3};
X  int i, r, wday;
X  time_t clk;
X
X  time(&clk);
X  wday = localtime(&clk)->tm_wday;
X  r = n[wday];
X  if (r > MAX_EXP) error("too many date expressions", "");
X  for (i = 0; i < r; i++) {
X	exp[i] = regcomp(date_pat(clk));
X	clk += 60 * 60 * 24L;	/* 24 hours */
X  }
X  return(r);
X}
X
Xchar *date_pat(t)
Xtime_t t;
X{				/* returns date expression for the time (t) */
X  static char *month[] = {
X	 "[Jj]an", "[Ff]eb", "[Mm]ar", "[Aa]pr", "[Mm]ay", "[Jj]un",
X	  "[Jj]ul", "[Aa]ug", "[Ss]ep", "[Oo]ct", "[Nn]ov", "[Dd]ec"
X  };
X  static char str[512];
X  struct tm *tm;
X
X  tm = localtime(&t);
X  sprintf(str,
X	"(^|[ \t(,;])(((%s[^ \t]*[ \t])|0*%d/|\\*/)(0*%d|\\*))([^0123456789]|$)",
X	month[tm->tm_mon], tm->tm_mon + 1, tm->tm_mday);
X
X  return str;
X}
X
Xvoid regerror(s)
Xchar *s;
X{				/* regcomp() needs this */
X  error("REGULAR EXPRESSION ERROR (%s)", s);
X}
X
Xvoid error(s, t)
Xchar *s, *t;
X{
X  fprintf(stderr, "%s: ", cmd);
X  fprintf(stderr, s, t);
X  fprintf(stderr, "\n");
X  exit(1);
X}
/
echo x - cd.c
sed '/^X/s///' > cd.c << '/'
X/* cd -- change working directory	Author: Thomas Brupbacher */
X
X
X/* -------------------------------------------------------------------------
X * lit.: 	POSIX 1003.2/D10 section 4.5
X *
X * Thomas Brupbacher (tobr@mw.lpc.ethz.ch)	Oct 1990
X * -------------------------------------------------------------------------
X *
X * This is a new implementation of cd, written from scratch.
X * cd uses the environment variables HOME and CDPATH to determine where
X * to chdir.
X */
X
X#include <sys/types.h>
X#include <stdlib.h>
X#include <limits.h>
X#include <string.h>
X#include <unistd.h>
X#include <stdio.h>
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void get_next_prefix, (char *string, char prefix [PATH_MAX ]));
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  char *string;
X  char *prog = *argv;
X  char prefix[PATH_MAX];
X  int cdflag, cdpath_flag;
X
X  if (argc == 1) {		/* no directory on command line, cd to home
X			 * dir						 */
X	string = getenv("HOME");
X	if (string == NULL) {
X		fprintf(stderr, "no home directory, directory not changed\n");
X		return(1);
X	}
X  }
X  if (argc > 2)			/* more than one dir on the command line */
X	fprintf(stderr, "%s: ignoring arguments\n", prog);
X
X  argv++;
X  string = getenv("CDPATH");
X  if (string == NULL)/* CDPATH not set, cd relative to .	 */
X	cdflag = chdir(*argv);
X
X  else {
X	cdpath_flag = 1;
X	do {
X		get_next_prefix(string, prefix);
X		if (prefix[0] != '\0') {
X			strcat(prefix, "/");
X			strcat(prefix, *argv);
X			cdflag = chdir(prefix);
X		}
X	} while ((cdflag != 0) && (prefix[0] != '\0'));
X  }
X
X  if (cdflag != 0) {
X	fprintf(stderr, "%s: cannot cd to %s\n", prog, *argv);
X	return(1);
X  }
X  if (cdpath_flag == 1) printf("%s\n", prefix);
X
X  return(0);
X}
X
X/* Get_next_prefix() parses the string <string> for the next : or the
X * end of <string> and copies the parsed chars to <prefix>.
X */
Xvoid get_next_prefix(string, prefix)
Xchar *string;
Xchar prefix[PATH_MAX];
X{
X  int index;
X
X  if (*(++string) == ':')	/* CDPATH contains "::" 		 */
X	prefix[index++] = ' ';
X  while ((*string != ':') && (*string != '\0'))
X	prefix[index++] = *(string++);
X  prefix[index++] = '\0';
X}
/
echo x - cksum.c
sed '/^X/s///' > cksum.c << '/'
X/* cksum.c - Display file checksums and block counts	Author: V. Archer */
X
X/* Copyright 1991 by Vincent Archer
X *	You may freely redistribute this software, in source or binary
X *	form, provided that you do not alter this copyright mention in any
X *	way.
X */
X
X#include <sys/types.h>
X#include <fcntl.h>
X#include <unistd.h>
X#include <stdio.h>
X
Xint error;
X
X/* Table from P1003.2 (4.9/Fig 4.1). In fact, this table was taken from zmodem
X * and rewritten to look like the Draft 11 example.
X */
Xunsigned long crctab[] = {
X		  0x7fffffff,
X	 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
X	 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e,
X	 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
X	 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d,
X	 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0,
X	 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63,
X	 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
X	 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa,
X	 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
X	 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180,
X	 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
X	 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87,
X	 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
X	 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5,
X	 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
X	 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
X	 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b,
X	 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
X	 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
X	 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541,
X	 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc,
X	 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f,
X	 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
X	 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e,
X	 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
X	 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c,
X	 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
X	 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b,
X	 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2,
X	 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671,
X	 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
X	 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
X	 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
X	 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
X	 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
X	 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795,
X	 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
X	 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b,
X	 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
X	 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82,
X	 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d,
X	 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8,
X	 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
X	 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff,
X	 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee,
X	 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d,
X	 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
X	 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c,
X	 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
X	 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02,
X	  0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
X};
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void crc, (int fd, char *name));
X_PROTOTYPE(unsigned long strncrc, (unsigned char *b, int n, unsigned long s));
X
Xstatic int aux;
X
X/* Routine straight out of 4.9.10 */
Xunsigned long strncrc(b, n, s)
Xregister unsigned char *b;	/* byte sequence to checksum */
Xregister int n;			/* length of sequence */
Xregister unsigned long s;	/* initial checksum value */
X{
X  register int i;
X
X  while (n-- > 0) {
X	/* Compute the index to the crc table */
X	i = (s >> 24) ^ ((unsigned int) (*b++));
X
X	if (i == 0) {
X		/* Replace an intermediate zero with the next value
X		 * from the sequence */
X		i = aux++;
X		if (aux >= sizeof(crctab) / sizeof(crctab[0])) aux = 0;
X	}
X
X	/* New checksum value */
X	s = (s << 8) ^ crctab[i];
X  }
X  return(s);
X}
X
X/* Main module. No options switches allowed, none parsed. */
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  argc--;
X  error = 0;
X  if (!argc)
X	crc(0, (char *) 0);
X  else
X	for (argv++; argc--; argv++) crc(open(*argv, O_RDONLY), *argv);
X  return(error);
X}
X
X/* Compute crc and size of input file descriptor. */
Xvoid crc(fd, name)
Xint fd;
Xchar *name;
X{
X  off_t f_size;
X  unsigned long crc;
X  int nb;
X  unsigned char buffer[1024];
X
X  if (fd < 0) {
X	perror(name);
X	error = 1;
X	return;
X  }
X  crc = 0;
X  f_size = 0;
X  aux = 0;
X  for (;;) {
X	nb = read(fd, (char *) buffer, sizeof(buffer));
X	if (nb < 0) {
X		close(fd);
X		perror(name ? name : "stdin");
X		error = 1;
X		return;
X	}
X	if (!nb) break;
X	f_size += nb;
X	crc = strncrc(buffer, nb, crc);
X  }
X  close(fd);
X  printf("%lu %ld", crc, f_size);
X  if (name)
X	printf(" %s\n", name);
X  else
X	putchar('\n');
X}
/
echo x - comic.c
sed '/^X/s///' > comic.c << '/'
X#define VERSION "2.5"
X/*
X   This is COMIC (CO_mpress MI_nix C). It was written (p)
X   by Jan-Mark Wams (email: jms@cs.vu.nl) in 1991.
X  
X   `Comic' is tuned to compress the minix source (kernel, fs, mm, commands).
X   The algorithm replaces repeated strings with an <offset,length> pair.
X   The longer the repeated string, the better the compression. If the text 
X   contains a lot of short repeated strings, (eg. font-files) use an other 
X   compression method like LZW (ie. ``compress'').
X  
X   It should compile under MINIX, UNIX, MS-DOS, etc. But if you have
X   to make any chainges for a new OS. (ie. if you port it.) PLEASE
X   let me know.  (email: jms@cs.vu.nl).
X  
X   Define one of following:
X        _MINIX, AMOEBA, UNIX, DOS, C89, DOS, MSC, GCC, M68
X  
X   Compiler Defines it checks for:
X        _POSIX_SOURCE, __BCC__, __TURBOC__, __STDC__
X  
X   Extra options:
X        H1_SIZE=2^n, H2_SIZE=2^n, LINT, DEBUG, NDEBUG
X   Don't define H2_SIZE without defining H1_SIZE. On big boxes, use
X   256 for both, this will give you a speed up.
X  
X   The file format is as follows. (Note in version 2.0 N is always zero).
X  
X   name                 size            index   remark
X  ---------------------------------------------------------------------
X   MAGIC                1 byte          0       0x69
X   MAGIC and FLAGS      1 byte          1       (0x60 | flags)
X   optional FLAGS       N bytes         2       Encription etc.
X   optional DOS SUFFIX  2 bytes         2+N     Original dos suffix.
X   optional DATA        M > 0 bytes     4+N     Compressed original.
X  
X   History:
X    VERSION |  USER  |  WHAT
X      2.0      jms      Made one source file version.
X      2.1      jms      Made compilable under gcc, turbo-C++ 1.0, ncc etc.
X      2.2      jms      Speedup in Eqlen(). Newstyle layout.
X      2.3      jms      Added ``0xFF & (int)'' twice in output_pair().
X      2.4      jms	Added stack hog in hash_init().
X      2.5      jms	s/MINIX/_MINIX/g
X*/
X
X/* General includes and defines.
X*/
X#ifdef DOS
X#  include <fcntl.h>    /* Use O_BINARY by `setmode()' in SM-DOS. */
X#  include <io.h>       /* For `setmode()' to. */
X# ifdef MSC
X#  include <stdlib.h>
X# endif
X#endif
X#if __STDC__ && ! GCC
X# include <stdlib.h>
X#endif
X#include <assert.h>
X#include <stdio.h>
X#include <errno.h>
X#include <string.h>             /* Included for strxxx(). */
X#include <ctype.h>              /* For isupper() and tolower(). */
X#include <sys/types.h>          /* Included for stat(). */
X#include <sys/stat.h>           /* Idem. */
X#include <unistd.h>
X
X/*
X   The S_ISREG works with Turbo C! Isn't life beautiful?
X*/
X#ifndef S_ISREG 
X#define S_ISREG(m) (((m) & 0170000) == 0100000)
X#endif
X
X#ifdef DOS
X# define TTY    "CON"           /* The terminal device under MS-DOS. */
X#else   /* DOS */
X# define TTY    "/dev/tty"
X#endif /* DOS */
X
X# define next_arg()\
X    (argc-- <= 0 ? NULL : *(argv++))
X
X#define str_equel(s1,s2)    (strcmp(s1, s2) == 0)
X
X#define NAMELEN_MAX     128
X
Xchar *COMIC      = "comic";
Xchar *XCAT       = "xcat";
Xchar *DECOMIC    = "decomic";
Xchar *STDIN      = "stdin"; /* Name of the current std* files. */
Xchar *STDOUT     = "stdout";
X
Xchar *SUFFIX     = "-X"; /* Suffix for comiced files. */
X#define SUFFIX_LEN 2     /* Change SUFFIX and SUFFIX_LEN together. */
X
X/* Compress constants.
X*/
X#define HUFFMAN_BITS    8       /* Huffman codes are 8 bits. */
X#define LENGTH_BITS     8       /* # of bits in length info. */
X#define OFFSET_BITS     13      /* # of bits in offset info. */
X#define PAIR_MAX        1       /* There are two pairs. */
X#define HUFFMAN_SIZE    256     /* Max for 8 bits. */
X#define LENGTH_SIZE     256     /* Max for 8 bits. */
X#define OFFSET_SIZE     8192    /* 13 Bits. OFFSET_SIZE > LENGHT_SIZE * 2 */
X#define OFFSET_MIN      1       /* Minimum offset. */
X#define LENGTH_MIN      2       /* Minimum length. */
X#define OFFSET_MAX      (OFFSET_SIZE + OFFSET_MIN - 1)
X#define LENGTH_MAX      (LENGTH_SIZE + LENGTH_MIN - 1)
X#define INPUT_SIZE      (LENGTH_SIZE + PAIR_MAX + LENGTH_MIN)
X#define BUFF_SIZE       (INPUT_SIZE + OFFSET_SIZE + OFFSET_MIN)
X#define BUFF_MAX        (BUFF_SIZE - 1)
X#define NON_INPUT_SIZE  (BUFF_SIZE - INPUT_SIZE)
X#define LOW_OFFSET_BITS (OFFSET_BITS - HUFFMAN_BITS)
X
X/* To shut up lint, a bit ;-(
X*/
X#ifdef LINT
Xextern char *memset();
Xextern void *malloc();
X#endif
X
X/* Global variables.
X*/
Xchar *pname;                    /* Name of program. */
Xchar suffix[SUFFIX_LEN];       /* Last two DOS suffix characters. */
X
X/* Pairs are built of a start pointer and a length pointer.
X*/
Xtypedef struct pair {           /* Part descriptor type. */
X        char * start;           /* Pointer in the circular buffer. */
X        int length;             /* Length of part. */
X} pair_t, *pair_p;
X
Xpair_t pairs[2];                /* Buffer for pair descriptors. */
Xpair_p pair_0 = &(pairs[0]);    /* Short hands. */
Xpair_p pair_1 = &(pairs[1]);
X
Xchar Buff[BUFF_SIZE + 1];       /* The Buffer. Add one for Sentinel. */
Xchar *Bend;                     /* Pointer to the last char in Buff. */
X#define Sentp (Bend + 1)	/* First char after buffer. */
Xchar *Bp = Buff;                /* Pointer to unprocessed char. */
Xchar *Binputend = Buff;         /* End of read ahead input. */
Xint  Bsize;
X
Xlong Nin = 0, Nout = 0;         /* Total # of bytes read/written. */
X
Xint v_flag = 0;                 /* Verbose flag given. */
Xint c_flag = 0;                 /* Cat (output to stdout) flag. */
Xint f_flag = 0;                 /* Force flag. */
Xint d_flag = 0;                 /* Decomic flag. */
Xint r_flag = 0;                 /* Raw flag, no header, only data. */
X#ifdef DOS
Xint s_flag = 1;                 /* Save suffix MS-DOS like. */
Xint a_flag = 0;                 /* Ascii option, cast \r\n to \n. */
X#else
Xint s_flag = 0;                 /* No MS-DOS, no default suffix savage. */
X#endif
X
X#ifdef __TURBOC__
Xextern unsigned _stklen = 256;
X#endif
X
X#ifdef DOS
X# define str_2_upper(s) (void)strupr(s)
X# define str_2_lower(s) (void)strlwr(s)
X#endif /* DOS */
X
X/* Index type is used for indexing the buffer and the hash tables.
X*/
Xtypedef unsigned short indext;
X#define INDEX_END       ((indext)BUFF_SIZE + 1)
X
X/* Buffer macros.
X*/
X#define Bsucc(p) ((p) == Bend ? Buff : (p) + 1)
X#define Bpred(p) ((p) == Buff ? Bend : (p) - 1)
X#define Badd(p, n) ((p) + (n) - ((p) + (n) > Bend ? Bsize : 0))
X#define Bsub(p, n) ((p) - (n) + ((p) < Buff + (n) ? Bsize : 0))
X#define Bdelta(p, q) (int)((p) - (q) + ((p) < (q) ? Bsize : 0))
X#define Blookupstart() Bsub(Bp, NON_INPUT_SIZE)
X#define Bindex(p) (indext)((p) - Buff)
X#define Binit() (void)memset (Buff, '\0', Bsize)
X
X/*
X   Pre filling the buffer might give better compression, but
X   would enlarge the compress program. '-) Perhaps a pseudo
X   random generator, filling the buffer with the most likely
X   (lowest number of bits in their huffman code) characters.
X   Note: the buffer (Buff) must be filled with something.
X*/
X
X/* 
X   If H1_SIZE and H2_SIZE are defined on compile time, the hash 
X   functions might be quicker on some compilers if not the maximum
X   values for H1_SIZE and H2_SIZE will be found at run time.
X*/
X#ifndef H2_SIZE
Xint H1_SIZE = 256;   /* Max value for SIZE = 256. */
Xint H2_SIZE = 256;
X#endif
X
X/* Define Hash functions.
X*/
X#define H1(i) ((indext)((i) & (H1_SIZE -1)))
X#define H2(i) ((indext)((i) & (H2_SIZE -1)))
X
X/* The buffer index macros.
X*/
X#define Ipred(i) (((i) == 0 ? BUFF_SIZE : (i)) - 1)
X#define Isucc(i) ((i) == BUFF_SIZE - 1 ? 0 : (i) + 1)
X#define hash_entry(i,j) hash_tbl[H1(i) + H1_SIZE * H2(j)]
X
X/* 
X   About magic; The first byte is a normal magic byte. The second byte 
X   is 0x6X, where the X nybble contains extra info.
X*/
X
X#define MAGIC1          (char)0x69      /* Magic number. */
X#define MAGIC2          (char)0x60      /* High part of 2d byte. */
X
X#define STATIC_BIT      (char)0x8       /* Use builtin Huffman tables. */
X#define DYNAMIC_BIT     (char)0x4       /* Huffman tables precede data. */
X#define SUFFIX_BIT      (char)0x2       /* Next two bytes are old suffix. */
X#define EXTEND_BIT      (char)0x1       /* More header data. */
X
X/*
X   Third byte indicates extra data-processing. To allow a third byte
X   the EXTEND_BIT has to been set in the second header byte. This leaves
X   room for futer expansions like encription etc. This will make the
X   current version signal something is wrong incase it gets data from
X   a new version jet to come.
X*/
X
X#define EXTRA_EXTEND    (char)0x0       /* Extra extension bytes. */
X#define TRANSLATE       (char)0x1       /* Input was xlated. */
X
X/* Huffman types.
X*/
Xtypedef long bitstr_t;
X
Xtypedef struct tree_s {
X        int _0, _1;
X} tree_t[];
X
Xtypedef struct ctab_s {
X        bitstr_t code;
X	char     length; /* Has to hold up to sizeof(bitstr_t) * 8 bits. */
X} ctab_t[];
X
X#define Hchar 0
X#define Hoff 1
X#define Hlen 2
X
X/* 
X   There is a big redundancy in the defined tables: both encode and 
X   decode tables are included. (The bit length per code would be 
X   enough but this would mean timeconsuming run time generation.) Ctab 
X   tables hold <bitpattern,length> pairs. Tree tables hold a binary 
X   decsent tree with per node a 0 and a 1 side.
X*/
X
X/* Huffman Tables these are generated by comicgen.
X*/
Xctab_t ctab_char = {
X        {0x54L,9},{0x3B6L,10},{0x67AL,11},{0x242L,10},
X        {0x33DCL,14},{0xD99L,13},{0xD98L,13},{0x76BL,11},
X        {0xCF6L,12},{0x17L,5},{0x2CL,6},{0x1977L,14},
X        {0xCF749L,20},{0x1B6L,10},{0xAAL,10},{0x13BL,9},
X        {0x6DEL,12},{0xCF748L,20},{0x6CFL,12},{0x1976L,14},
X        {0x1975L,14},{0xD97L,13},{0x76AL,11},{0xB4DL,12},
X        {0xD96L,13},{0xB4CL,12},{0x1974L,14},{0x1973L,14},
X        {0xB4BL,12},{0xB4AL,12},{0xB49L,12},{0x1972L,14},
X        {0x8L,5},{0x4FL,7},{0x1CL,6},{0x120L,9},
X        {0x3B4L,10},{0x31L,8},{0x75L,7},{0x28L,6},
X        {0x1AL,5},{0x10L,5},{0x1CL,7},{0x30L,8},
X        {0x3L,6},{0x26L,6},{0x31L,6},{0x3AL,7},
X        {0x15L,6},{0x2L,6},{0xBL,6},{0x1L,7},
X        {0x3EL,7},{0x54L,7},{0x74L,7},{0x61L,7},
X        {0x55L,7},{0x13L,8},{0x1DL,7},{0xFL,6},
X        {0x77L,7},{0x29L,7},{0x56L,7},{0x38L,9},
X        {0x12L,8},{0x14L,7},{0x2BL,8},{0x2FL,7},
X        {0x6EL,7},{0x13L,7},{0x66L,7},{0x51L,8},
X        {0xB5L,8},{0x45L,7},{0x19FL,9},{0xA1L,9},
X        {0x37L,7},{0x6FL,7},{0x57L,7},{0x3DL,7},
X        {0x60L,7},{0x156L,11},{0x44L,7},{0xFL,7},
X        {0x2EL,7},{0x5BL,7},{0xC9L,9},{0x9CL,8},
X        {0xDAL,9},{0xC8L,9},{0x13AL,9},{0x3CL,7},
X        {0x39L,9},{0x19L,7},{0x33CL,10},{0x36L,6},
X        {0xD95L,13},{0xDL,6},{0x32L,6},{0x1CL,5},
X        {0x8L,6},{0x1FL,5},{0x16L,6},{0x8L,7},
X        {0x33L,7},{0x6L,6},{0xCEL,8},{0x3BL,7},
X        {0x25L,6},{0x23L,6},{0x5L,6},{0x1L,6},
X        {0x18L,6},{0x168L,9},{0x1AL,6},{0x9L,5},
X        {0x1EL,5},{0x29L,6},{0x3FL,7},{0x12L,7},
X	{0x1DL,8},{0,7},{0xECL,8},{0x91L,8},
X        {0xA0L,9},{0x49L,7},{0x5A7L,11},{0xCF747L,20},
X        {0xB48L,12},{0xCF746L,20},{0x1971L,14},{0xCF745L,20},
X        {0x1970L,14},{0xCF744L,20},{0x196FL,14},{0xCF743L,20},
X        {0xD94L,13},{0xCF742L,20},{0xCF741L,20},{0xCF740L,20},
X        {0x67BBFL,19},{0x196EL,14},{0x67BBEL,19},{0x67BBDL,19},
X        {0x196DL,14},{0x67BBCL,19},{0x67BBBL,19},{0x67BBAL,19},
X        {0xD93L,13},{0x67BB9L,19},{0x196CL,14},{0x67BB8L,19},
X        {0x67BB7L,19},{0x196BL,14},{0xD92L,13},{0x196AL,14},
X        {0x1969L,14},{0x1968L,14},{0x1967L,14},{0x1966L,14},
X        {0x1965L,14},{0xD91L,13},{0xD90L,13},{0xD8FL,13},
X        {0x3B7L,10},{0xD8EL,13},{0xD8DL,13},{0x1964L,14},
X        {0x1963L,14},{0xD8CL,13},{0x1962L,14},{0xD8BL,13},
X        {0x1961L,14},{0xD8AL,13},{0x1960L,14},{0x195FL,14},
X        {0x90FL,12},{0xD89L,13},{0x195EL,14},{0xD88L,13},
X        {0x195DL,14},{0x90EL,12},{0x195CL,14},{0xD87L,13},
X        {0x195BL,14},{0x195AL,14},{0x1959L,14},{0xD86L,13},
X        {0x67BB6L,19},{0xD85L,13},{0x67BB5L,19},{0x1958L,14},
X        {0x1957L,14},{0x36EL,11},{0xD84L,13},{0x1956L,14},
X        {0x1955L,14},{0xD83L,13},{0x1954L,14},{0x1953L,14},
X        {0x67BB4L,19},{0x1952L,14},{0x1951L,14},{0x1950L,14},
X        {0x194FL,14},{0x194EL,14},{0x67BB3L,19},{0x194DL,14},
X        {0x67BB2L,19},{0x194CL,14},{0x67BB1L,19},{0xD82L,13},
X        {0x67BB0L,19},{0x194BL,14},{0x67BAFL,19},{0x194AL,14},
X        {0x67BAEL,19},{0x1949L,14},{0x67BADL,19},{0x1948L,14},
X        {0x67BACL,19},{0x1947L,14},{0x67BABL,19},{0x1946L,14},
X        {0x67BAAL,19},{0x1945L,14},{0x1944L,14},{0x1943L,14},
X        {0x1942L,14},{0x1941L,14},{0x67BA9L,19},{0x1940L,14},
X        {0x67BA8L,19},{0xD81L,13},{0x67BA7L,19},{0xD80L,13},
X        {0x67BA6L,19},{0x6CEL,12},{0xABFL,14},{0xABEL,14},
X        {0xABDL,14},{0x90DL,12},{0xABCL,14},{0x6CDL,12},
X        {0x67BA5L,19},{0xCBFL,13},{0xABBL,14},{0xCBEL,13},
X        {0xABAL,14},{0xCBDL,13},{0xAB9L,14},{0x90CL,12},
X        {0xAB8L,14},{0xCBCL,13},{0x19EFL,13},{0x6DFL,12}
X};
X
Xtree_t tree_char = {
X        {17,12},{129,127},{133,131},{137,135},
X        {139,138},{142,140},{145,143},{147,146},
X        {151,149},{188,152},{200,190},{208,206},
X        {212,210},{216,214},{220,218},{224,222},
X        {232,230},{236,234},{256,244},{258,257},
X        {260,259},{262,261},{264,263},{266,265},
X        {268,267},{270,269},{272,271},{274,273},
X        {276,275},{278,277},{280,279},{282,281},
X        {284,283},{286,285},{288,287},{290,289},
X        {4,291},{19,11},{26,20},{31,27},
X        {132,130},{141,134},{150,144},{155,153},
X        {157,156},{159,158},{167,160},{170,168},
X        {174,172},{178,175},{182,180},{185,184},
X        {191,186},{195,192},{198,196},{201,199},
X        {203,202},{205,204},{209,207},{215,213},
X        {219,217},{223,221},{226,225},{228,227},
X        {231,229},{239,238},{242,240},{248,246},
X        {252,250},{292,254},{6,5},{24,21},
X        {136,96},{154,148},{162,161},{165,163},
X        {169,166},{173,171},{179,177},{187,183},
X        {194,189},{211,197},{235,233},{247,245},
X        {253,249},{294,293},{296,295},{298,297},
X        {300,299},{302,301},{304,303},{306,305},
X        {308,307},{310,309},{312,311},{314,313},
X        {316,315},{318,317},{320,319},{322,321},
X        {324,323},{8,325},{25,23},{29,28},
X        {128,30},{181,176},{251,241},{16,255},
X        {237,18},{326,243},{328,327},{330,329},
X        {332,331},{334,333},{336,335},{338,337},
X        {340,339},{342,341},{344,343},{346,345},
X	{348,347},{350,349},{352,351},{354,353},
X	{356,355},{22,7},{2,357},{358,126},
X        {360,359},{362,361},{193,363},{365,364},
X        {367,366},{369,368},{371,370},{373,372},
X        {375,374},{377,376},{379,378},{81,380},
X        {1,164},{36,381},{94,382},{384,383},
X        {3,385},{13,386},{388,387},{390,389},
X        {392,391},{394,393},{14,395},{397,396},
X        {398,74},{113,399},{90,15},{35,400},
X        {88,401},{403,402},{405,404},{89,86},
X        {124,75},{0,406},{63,92},{122,407},
X        {106,408},{409,72},{87,410},{411,123},
X        {413,412},{415,414},{416,71},{43,37},
X        {417,66},{418,120},{64,57},{419,60},
X        {54,38},{68,77},{70,420},{80,55},
X        {421,85},{62,78},{53,56},{422,33},
X        {423,125},{82,73},{52,118},{91,79},
X        {47,107},{424,76},{425,104},{84,67},
X        {426,61},{42,58},{427,93},{65,428},
X        {119,69},{429,83},{103,430},{121,51},
X        {432,431},{95,433},{98,434},{435,46},
X        {10,436},{438,437},{39,117},{45,439},
X        {440,108},{441,109},{443,442},{34,444},
X        {114,445},{112,446},{102,447},{448,48},
X        {449,59},{450,97},{451,50},{100,452},
X        {105,453},{454,110},{49,44},{455,111},
X        {116,101},{99,456},{40,457},{459,458},
X        {460,9},{462,461},{464,463},{41,465},
X        {467,466},{469,468},{471,470},{32,115},
X        {473,472},{475,474},{477,476},{479,478},
X        {481,480},{483,482},{485,484},{487,486},
X        {489,488},{491,490},{493,492},{495,494},
X        {497,496},{499,498},{501,500},{503,502},
X        {505,504},{507,506},{509,508}
X};
X
Xctab_t ctab_len = {
X	{0x2L,3},{0,3},{0x3L,3},{0x5L,3},
X        {0x6L,3},{0x3L,4},{0x9L,4},{0xFL,4},
X        {0x5L,5},{0x1CL,5},{0x8L,6},{0x21L,6},
X        {0x3AL,6},{0x13L,7},{0x41L,7},{0x45L,7},
X        {0x76L,7},{0x24L,8},{0x8CL,8},{0x88L,8},
X        {0x8EL,8},{0xEEL,8},{0x4AL,9},{0x100L,9},
X        {0x102L,9},{0x101L,9},{0x11EL,9},{0x206L,10},
X        {0x225L,10},{0x207L,10},{0x235L,10},{0x1DFL,9},
X        {0x237L,10},{0x47DL,11},{0x3BDL,10},{0x448L,11},
X        {0x234L,10},{0x44CL,11},{0x12EL,11},{0x47CL,11},
X        {0x46DL,11},{0x258L,12},{0x779L,11},{0x778L,11},
X        {0x25EL,12},{0x8D9L,12},{0x259D41L,24},{0x4BEL,13},
X        {0x892L,12},{0x8D8L,12},{0x89FL,12},{0x966L,14},
X        {0x8FCL,12},{0x4B7L,13},{0x4B6L,13},{0x11FFL,13},
X        {0x113DL,13},{0x11FEL,13},{0x259D40L,24},{0x11FDL,13},
X        {0x4B5L,13},{0x2275L,14},{0x11FCL,13},{0x259CL,16},
X        {0x2274L,14},{0x259D3FL,24},{0x2273L,14},{0x2272L,14},
X        {0x2271L,14},{0x2270L,14},{0x226FL,14},{0x4B4L,13},
X        {0x226EL,14},{0x226DL,14},{0x259D3EL,24},{0x44D1L,15},
X        {0x226CL,14},{0x4B2L,13},{0x113CL,13},{0x113BL,13},
X        {0x44D0L,15},{0x449FL,15},{0x449EL,15},{0x11FBL,13},
X        {0x259D3DL,24},{0x259D3CL,24},{0x259D3BL,24},{0x259D3AL,24},
X        {0x226BL,14},{0x259D39L,24},{0x449DL,15},{0x449CL,15},
X        {0x449BL,15},{0x449AL,15},{0x259D38L,24},{0x226AL,14},
X        {0x11FAL,13},{0x4499L,15},{0x259D37L,24},{0x259D36L,24},
X        {0x4498L,15},{0x2269L,14},{0x259D35L,24},{0x259D34L,24},
X        {0x259D33L,24},{0x259D32L,24},{0x259D31L,24},{0x259D30L,24},
X        {0x259D2FL,24},{0x259D2EL,24},{0x259D2DL,24},{0x259D2CL,24},
X        {0x259D2BL,24},{0x259D2AL,24},{0x259D29L,24},{0x12FFL,15},
X        {0x259D28L,24},{0x259D27L,24},{0x259D26L,24},{0x259D25L,24},
X        {0x259D24L,24},{0x259D23L,24},{0x259D22L,24},{0x259D21L,24},
X        {0x259D20L,24},{0x259D1FL,24},{0x12FEL,15},{0x259D1EL,24},
X        {0x259D1DL,24},{0x259D1CL,24},{0x259D1BL,24},{0x259D1AL,24},
X        {0x259D19L,24},{0x259D18L,24},{0x259D17L,24},{0x259D16L,24},
X        {0x259D15L,24},{0x12FDL,15},{0x259D14L,24},{0x259D13L,24},
X        {0x259D12L,24},{0x259D11L,24},{0x259D10L,24},{0x259D0FL,24},
X        {0x259D0EL,24},{0x259D0DL,24},{0x259D0CL,24},{0x259D0BL,24},
X        {0x259D0AL,24},{0x259D09L,24},{0x259D08L,24},{0x259D07L,24},
X        {0x259D06L,24},{0x259D05L,24},{0x12FCL,15},{0x259D04L,24},
X        {0x259D03L,24},{0x259D02L,24},{0x259D01L,24},{0x259D00L,24},
X        {0x12CEFFL,23},{0x12CEFEL,23},{0x12CEFDL,23},{0x12CEFCL,23},
X        {0x12CEFBL,23},{0x12CEFAL,23},{0x12CEF9L,23},{0x12CEF8L,23},
X        {0x12CEF7L,23},{0x12CEF6L,23},{0x12CEF5L,23},{0x12CFL,15},
X        {0x12CEF4L,23},{0x12CEF3L,23},{0x12CEF2L,23},{0x12CEF1L,23},
X        {0x12CEF0L,23},{0x12CEEFL,23},{0x12CEEEL,23},{0x12CEEDL,23},
X        {0x12CEECL,23},{0x12CEEBL,23},{0x12CEEAL,23},{0x12CEE9L,23},
X        {0x12CEE8L,23},{0x12CEE7L,23},{0x12CEE6L,23},{0x12CEE5L,23},
X        {0x12CEE4L,23},{0x12CEE3L,23},{0x12CEE2L,23},{0x12CEE1L,23},
X        {0x12CEE0L,23},{0x12CEDFL,23},{0x12CEDEL,23},{0x12CEDDL,23},
X        {0x12CEDCL,23},{0x12CEDBL,23},{0x12CEDAL,23},{0x12CED9L,23},
X        {0x12CED8L,23},{0x12CED7L,23},{0x12CED6L,23},{0x12CED5L,23},
X        {0x12CED4L,23},{0x12CED3L,23},{0x12CED2L,23},{0x12CED1L,23},
X        {0x12CED0L,23},{0x12CECFL,23},{0x12CECEL,23},{0x12CECDL,23},
X        {0x12CECCL,23},{0x12CECBL,23},{0x12CECAL,23},{0x12CEC9L,23},
X        {0x12CEC8L,23},{0x12CEC7L,23},{0x12CEC6L,23},{0x12CEC5L,23},
X        {0x12CEC4L,23},{0x12CEC3L,23},{0x12CEC2L,23},{0x12CEC1L,23},
X        {0x12CEC0L,23},{0x12CEBFL,23},{0x12CEBEL,23},{0x12CEBDL,23},
X        {0x12CEBCL,23},{0x12CEBBL,23},{0x12CEBAL,23},{0x12CEB9L,23},
X        {0x12CEB8L,23},{0x12CEB7L,23},{0x12CEB6L,23},{0x12CEB5L,23},
X        {0x12CEB4L,23},{0x12CEB3L,23},{0x12CEB2L,23},{0x12CEB1L,23},
X        {0x12CEB0L,23},{0x12CEAFL,23},{0x12CEAEL,23},{0x12CEADL,23},
X        {0x12CEACL,23},{0x12CEABL,23},{0x12CEAAL,23},{0x12CEA9L,23},
X        {0x12CEA8L,23},{0x12CEA7L,23},{0x12CEA6L,23},{0x12CEA5L,23},
X        {0x12CEA4L,23},{0x12CEA3L,23},{0x12CEA2L,23},{0x12CEA1L,23}
X};
X
Xtree_t tree_len = {
X        {58,46},{74,65},{85,84},{87,86},
X        {94,89},{99,98},{103,102},{105,104},
X        {107,106},{109,108},{111,110},{113,112},
X        {116,114},{118,117},{120,119},{122,121},
X        {124,123},{127,125},{129,128},{131,130},
X        {133,132},{135,134},{138,136},{140,139},
X        {142,141},{144,143},{146,145},{148,147},
X        {150,149},{152,151},{155,153},{157,156},
X        {159,158},{161,160},{163,162},{165,164},
X        {167,166},{169,168},{172,170},{174,173},
X        {176,175},{178,177},{180,179},{182,181},
X        {184,183},{186,185},{188,187},{190,189},
X        {192,191},{194,193},{196,195},{198,197},
X        {200,199},{202,201},{204,203},{206,205},
X        {208,207},{210,209},{212,211},{214,213},
X        {216,215},{218,217},{220,219},{222,221},
X        {224,223},{226,225},{228,227},{230,229},
X        {232,231},{234,233},{236,235},{238,237},
X        {240,239},{242,241},{244,243},{246,245},
X        {248,247},{250,249},{252,251},{254,253},
X        {256,255},{258,257},{260,259},{262,261},
X        {264,263},{266,265},{268,267},{270,269},
X        {272,271},{274,273},{276,275},{278,277},
X        {280,279},{282,281},{284,283},{286,285},
X        {288,287},{290,289},{292,291},{294,293},
X        {296,295},{298,297},{300,299},{302,301},
X        {304,303},{306,305},{308,307},{310,309},
X        {312,311},{314,313},{316,315},{318,317},
X        {320,319},{322,321},{324,323},{326,325},
X        {328,327},{330,329},{332,331},{334,333},
X        {336,335},{338,337},{340,339},{342,341},
X        {344,343},{346,345},{348,347},{350,349},
X        {352,351},{354,353},{356,355},{358,357},
X        {360,359},{362,361},{364,363},{366,365},
X        {368,367},{370,369},{372,371},{374,373},
X        {376,375},{378,377},{380,379},{382,381},
X        {384,383},{386,385},{388,387},{390,389},
X        {392,391},{394,393},{396,395},{398,397},
X        {400,399},{402,401},{404,403},{406,405},
X        {408,407},{410,409},{412,411},{414,413},
X        {63,415},{80,75},{82,81},{91,90},
X        {93,92},{100,97},{126,115},{154,137},
X        {416,171},{64,61},{67,66},{69,68},
X        {72,70},{76,73},{95,88},{417,101},
X        {419,418},{421,420},{423,422},{51,424},
X        {57,55},{62,59},{96,83},{78,56},
X        {425,79},{427,426},{429,428},{431,430},
X        {433,432},{47,434},{54,53},{71,60},
X        {77,435},{437,436},{52,438},{49,45},
X        {439,50},{441,440},{443,442},{48,444},
X        {44,445},{447,446},{41,448},{43,42},
X        {450,449},{39,33},{451,40},{453,452},
X        {37,454},{35,455},{38,456},{458,457},
X        {459,34},{461,460},{462,32},{36,30},
X        {464,463},{465,28},{27,29},{467,466},
X        {468,31},{26,469},{471,470},{473,472},
X        {24,474},{23,25},{22,475},{21,476},
X        {20,477},{18,478},{19,479},{481,480},
X        {17,482},{16,483},{485,484},{486,15},
X        {487,14},{488,13},{12,489},{491,490},
X        {492,11},{10,493},{9,494},{496,495},
X        {497,8},{498,7},{499,6},{500,5},
X        {4,501},{502,3},{0,2},{1,503},
X        {505,504},{507,506},{509,508}
X};
X
Xctab_t ctab_off = {
X        {0x7L,3},{0x3L,4},{0xCL,4},{0xAL,5},
X        {0x12L,5},{0x1BL,5},{0x8L,6},{0x10L,6},
X        {0x1CL,6},{0x1FL,6},{0x28L,6},{0x8L,7},
X        {0x35L,6},{0x3L,7},{0xBL,7},{0x2FL,6},
X        {0xEL,7},{0x24L,7},{0x26L,7},{0x3AL,7},
X        {0x3CL,7},{0x40L,7},{0x4EL,7},{0x45L,7},
X        {0x5L,8},{0x57L,7},{0x5AL,7},{0x3L,8},
X        {0xCL,8},{0x2AL,8},{0x1FL,8},{0x2L,8},
X        {0xAL,8},{0x4CL,7},{0x9L,8},{0x2CL,8},
X        {0x4FL,8},{0x19L,8},{0x65L,8},{0x89L,8},
X        {0x87L,8},{0x29L,8},{0x2FL,8},{0x8DL,8},
X        {0x6BL,8},{0x63L,8},{0x6DL,8},{0x5AL,8},
X        {0x85L,8},{0x60L,8},{0x5CL,8},{0x9BL,8},
X        {0xA5L,8},{0x6FL,8},{0xA4L,8},{0x83L,8},
X        {0xACL,8},{0x84L,8},{0x8EL,8},{0x9AL,8},
X        {0xD2L,8},{0xBBL,8},{0x2BL,9},{0xABL,8},
X        {0x17L,9},{0xBAL,8},{0xAAL,8},{0x35L,9},
X        {0xA8L,8},{0x16L,9},{0xB9L,8},{0x8L,9},
X        {0x3DL,9},{0x8AL,9},{0x26L,9},{0x9L,9},
X	{0xB8L,8},{0x1DL,9},{0,9},{0xB7L,8},
X        {0x2AL,9},{0x5DL,9},{0x95L,9},{0x50L,9},
X        {0x4AL,9},{0xBFL,9},{0x4FL,9},{0xBBL,9},
X        {0x8DL,9},{0x4EL,9},{0x3CL,9},{0x9CL,9},
X        {0xCFL,9},{0xC5L,9},{0x57L,9},{0x88L,9},
X        {0xD8L,9},{0x37L,9},{0x14FL,9},{0x56L,9},
X        {0x94L,9},{0x51L,9},{0xB0L,9},{0xCEL,9},
X        {0x5CL,9},{0xF7L,9},{0x97L,9},{0xDDL,9},
X        {0xD5L,9},{0xD4L,9},{0x8CL,9},{0xB6L,9},
X        {0xF6L,9},{0xD3L,9},{0xBEL,9},{0x118L,9},
X        {0x16CL,9},{0xD2L,9},{0xBDL,9},{0x23L,10},
X        {0xDCL,9},{0x105L,9},{0x167L,9},{0xF5L,9},
X        {0x111L,9},{0x4BL,10},{0xF4L,9},{0xC4L,9},
X        {0x13EL,9},{0xC9L,9},{0xCDL,9},{0x4AL,10},
X        {0xC3L,9},{0x11FL,9},{0x14EL,9},{0x167L,10},
X        {0x1A1L,9},{0x153L,9},{0x119L,9},{0xEDL,9},
X        {0x39L,10},{0x9BL,10},{0xD1L,9},{0x163L,9},
X        {0xB7L,10},{0x162L,9},{0x52L,10},{0x152L,9},
X        {0x51L,10},{0x68L,10},{0x38L,10},{0xBCL,9},
X        {0x37L,10},{0x14DL,9},{0x13DL,9},{0x7L,10},
X        {0x10CL,9},{0x161L,9},{0x49L,10},{0x6L,10},
X        {0x11EL,9},{0x6DL,10},{0x160L,9},{0x1A6L,9},
X        {0x104L,9},{0x166L,9},{0x48L,10},{0x1A3L,9},
X        {0x14CL,9},{0x15BL,9},{0x165L,9},{0x36L,10},
X        {0x63L,10},{0x1A0L,9},{0x5L,10},{0x164L,9},
X        {0x93L,10},{0x22L,10},{0x110L,9},{0x6CL,10},
X        {0x4L,10},{0x13CL,9},{0x3L,10},{0x3FL,10},
X        {0x2L,10},{0x1A2L,9},{0x9AL,10},{0x35L,10},
X        {0x116L,10},{0x1A7L,9},{0x13FL,9},{0x50L,10},
X        {0x4FL,10},{0x113L,10},{0x12CL,10},{0x92L,10},
X        {0x34L,10},{0x175L,10},{0x166L,10},{0x91L,10},
X        {0x99L,10},{0x1D8L,10},{0x3EL,10},{0x112L,10},
X        {0xB6L,10},{0x190L,10},{0x1A0L,10},{0x4EL,10},
X        {0x13AL,10},{0x15AL,9},{0x1B3L,10},{0x21BL,10},
X        {0x165L,10},{0x62L,10},{0x98L,10},{0x97L,10},
X        {0x21L,10},{0x69L,10},{0x61L,10},{0x164L,10},
X        {0x11FL,10},{0x163L,10},{0x174L,10},{0x12DL,10},
X        {0x1B2L,10},{0x96L,10},{0x11EL,10},{0x11DL,10},
X        {0x1A1L,10},{0x90L,10},{0x199L,10},{0x3DL,10},
X        {0xB5L,10},{0x162L,10},{0x1DFL,10},{0x16FL,10},
X        {0x185L,10},{0x3CL,10},{0x1DEL,10},{0x11CL,10},
X        {0x13BL,10},{0x184L,10},{0x2DBL,10},{0x198L,10},
X        {0x21AL,10},{0xB4L,10},{0x2DAL,10},{0x60L,10},
X        {0x1DDL,10},{0x1DCL,10},{0x1D9L,10},{0x53L,10},
X        {0x117L,10},{0x20L,10},{0x191L,10},{0x16EL,10}
X};
X
Xtree_t tree_off = {
X        {246,242},{244,211},{238,234},{249,248},
X        {201,250},{224,210},{206,228},{243,230},
X        {205,254},{241,236},{222,197},{255,235},
X        {198,135},{219,212},{233,221},{208,240},
X        {194,223},{226,220},{239,227},{188,252},
X        {203,193},{204,144},{245,232},{186,141},
X        {214,200},{225,215},{195,176},{229,199},
X        {179,161},{149,217},{213,172},{247,218},
X        {146,251},{191,148},{207,192},{131,125},
X        {166,158},{202,183},{237,231},{150,140},
X        {171,152},{196,187},{177,119},{253,216},
X        {159,155},{180,174},{184,182},{163,189},
X        {185,167},{173,136},{116,256},{165,122},
X        {175,170},{145,143},{162,157},{209,169},
X        {147,137},{134,98},{168,153},{128,190},
X        {181,154},{160,133},{115,138},{178,124},
X        {156,257},{164,121},{112,105},{126,123},
X        {259,258},{260,139},{120,107},{96,261},
X        {109,108},{117,113},{262,142},{103,92},
X        {263,130},{264,129},{127,93},{265,132},
X        {114,85},{151,118},{266,87},{111,267},
X        {269,268},{102,270},{91,271},{272,106},
X        {100,82},{274,273},{110,88},{73,275},
X        {95,276},{104,81},{278,277},{99,94},
X        {83,101},{89,86},{280,279},{84,281},
X        {283,282},{90,72},{284,97},{285,67},
X        {287,286},{80,62},{289,288},{74,290},
X        {292,291},{294,293},{295,77},{297,296},
X        {69,64},{299,298},{71,75},{301,300},
X        {78,302},{60,303},{305,304},{65,61},
X        {76,70},{306,79},{308,307},{310,309},
X        {56,311},{66,63},{68,312},{314,313},
X        {54,52},{316,315},{59,51},{58,317},
X        {318,43},{319,39},{320,40},{57,48},
X        {321,55},{323,322},{325,324},{326,53},
X        {327,46},{328,44},{330,329},{332,331},
X        {333,38},{334,45},{49,335},{337,336},
X        {50,338},{47,339},{341,340},{342,36},
X        {344,343},{346,345},{348,347},{349,42},
X        {35,350},{29,351},{352,41},{354,353},
X        {356,355},{357,30},{359,358},{360,37},
X        {362,361},{364,363},{366,365},{28,367},
X        {32,368},{369,34},{370,24},{31,27},
X        {372,371},{374,373},{376,375},{26,377},
X        {379,378},{380,25},{382,381},{384,383},
X        {22,385},{33,386},{388,387},{389,23},
X        {391,390},{21,392},{20,393},{19,394},
X        {396,395},{398,397},{400,399},{402,401},
X        {404,403},{406,405},{18,407},{17,408},
X        {410,409},{412,411},{414,413},{416,415},
X        {16,417},{419,418},{420,14},{11,421},
X        {423,422},{425,424},{426,13},{428,427},
X        {429,12},{430,15},{432,431},{434,433},
X        {10,435},{437,436},{439,438},{441,440},
X        {442,9},{8,443},{445,444},{447,446},
X        {449,448},{451,450},{7,452},{454,453},
X        {6,455},{457,456},{459,458},{461,460},
X        {463,462},{464,5},{466,465},{468,467},
X        {4,469},{471,470},{473,472},{475,474},
X        {3,476},{478,477},{480,479},{482,481},
X        {484,483},{2,485},{487,486},{489,488},
X        {491,490},{493,492},{494,1},{496,495},
X        {497,0},{499,498},{501,500},{503,502},
X        {505,504},{507,506},{509,508}
X};
X
X/*
X   The bits are put on a file, the first bit putted with ``put_bit()''
X   is the high bit of the first byte in the file. `Flush_bits()' will 
X   add a `1' and pad the byte up to a full byte with zeroes. This will
X   make the last bit in the last byte the eof marker. No original length 
X   information is stored in the output file.
X*/
X
X#define BIT_BUFF_SIZE    1024
Xchar bit_buff[BIT_BUFF_SIZE];
X#define eo_buff (bit_buff + BIT_BUFF_SIZE)
Xchar *bit_index = bit_buff;
Xchar *eof_index = bit_buff;
Xint put_bits = 0;
Xint put_room;
Xint get_bits = 0;
X
X#define next()          (bit_index++)            /* The next char. */
X#define no_next()       (bit_index == eof_index) /* There is no next. */
X#define bit_buff_full() (bit_index == eo_buff)   /* Buffer full. */
X
X
X_PROTOTYPE(void fatal, (char *failed ));
X_PROTOTYPE(void write_bit_buff, (void));
X_PROTOTYPE(void read_bit_buff, (void));
X_PROTOTYPE(void put_bit, (int bit ));
X_PROTOTYPE(int get_bit, (void));
X_PROTOTYPE(void init_bits, (void));
X_PROTOTYPE(void flush_bits, (void));
X_PROTOTYPE(void put_n_bits, (long code, int n ));
X_PROTOTYPE(int get_n_bits, (int n ));
X_PROTOTYPE(char *basename, (char *name ));
X_PROTOTYPE(char *new_name, (char *fname ));
X_PROTOTYPE(char *org_name, (char *fname ));
X_PROTOTYPE(int new_stdin, (char *newin ));
X_PROTOTYPE(int new_stdout, (char *newout ));
X_PROTOTYPE(void print_ratio, (void));
X_PROTOTYPE(void verbose_info, (void));
X_PROTOTYPE(void usage, (void));
X_PROTOTYPE(void file_start, (void));
X_PROTOTYPE(void file_done, (void));
X_PROTOTYPE(void hash_init, (void));
X_PROTOTYPE(void hash_update, (void));
X_PROTOTYPE(void decode_pair, (void));
X_PROTOTYPE(void decode_char, (void));
X_PROTOTYPE(int get_input, (void));
X_PROTOTYPE(int eqlen, (char *p, char *q, int count ));
X_PROTOTYPE(void get_token, (int pair_0used ));
X_PROTOTYPE(int magic_ok, (void));
X_PROTOTYPE(void put_magic, (void));
X_PROTOTYPE(int descend, (struct tree_s *tree ));
X_PROTOTYPE(void Hinit, (void));
X_PROTOTYPE(int Hdecode, (int index ));
X_PROTOTYPE(int Hcodelen, (int index, int c ));
X_PROTOTYPE(void Hencode, (int index, int i ));
X_PROTOTYPE(void decode, (void));
X_PROTOTYPE(void output_pair, (int *done ));
X_PROTOTYPE(void output_char, (void));
X_PROTOTYPE(void encode, (void));
X_PROTOTYPE(int main, (int argc, char **argv ));
X
X
X/* fatal: Print a error on stderr, and exit.
X*/
Xvoid fatal (failed)
Xchar *failed;
X{
X  fprintf(stderr, "\r%s: Fatal couldn't %s ", pname, failed);
X  if (errno != 0)
X        perror("");             /* Prints EOLN to ;-( */
X  else
X        printf("\n");
X  exit(-1);
X}
X
X
X/* write_bit_buff: write the bit i/o buffer to stdout.
X*/
Xvoid write_bit_buff()
X{
X  if (write(1, bit_buff, bit_index - bit_buff) != bit_index - bit_buff)
X        fatal("write");
X  Nout += bit_index - bit_buff;
X  bit_index = bit_buff;
X}
X
X/* read_bit_buff: read the bit i/o buffer from stdin.
X*/
Xvoid read_bit_buff()
X{
X  if ((eof_index = bit_buff + read(0, bit_buff, BIT_BUFF_SIZE)) < bit_buff)
X        fatal("read");
X
X  Nin += eof_index - bit_buff;
X  bit_index = bit_buff;
X}
X
X
X/* put_bit: put a bit on stdout.
X*/
Xvoid put_bit(bit)
Xint bit;
X{
X  assert(bit == 1 || bit == 0);
X
X  put_bits = (put_bits << 1) | bit;
X
X  if (--put_room == 0) {
X        *next() = put_bits;
X	if (bit_buff_full()) write_bit_buff();
X        put_bits = 0;           /* Flag. */
X        put_room = 8;
X  }
X}
X
X
X/* get_bit: get a bit from stdin.
X*/
Xint get_bit()
X{
X  if ((get_bits & 0x7F) == 0) {
X        if (get_bits == 0) {    /* First time only. */
X                read_bit_buff();
X                if (no_next()) {
X                        fprintf(stderr, "\r%s: Warning empty file.\n", pname);
X                        fflush(stderr);
X                        return EOF;
X                }
X	}                                   
X        if (no_next()) return EOF;
X	get_bits = (0xFF & (int)*next()) << 1;
X        if (no_next()) read_bit_buff();
X        if (no_next()) {
X                if (get_bits == 0x100)
X                        return EOF;     /* Bad luck, think ;-) */
X        } else
X                get_bits |= 1;  /* Last byte has own EOF marker. */
X  } else
X        get_bits <<= 1;
X
X  return(get_bits >> 8) & 1;
X}
X
X/* Init_bits: Init the bits package.
X*/
Xvoid init_bits()
X{
X  bit_index = bit_buff;         /* Not necessary, but nice. */
X  eof_index = bit_buff;
X  put_bits = 0;                 /* Very necessary. */
X  put_room = 8;
X  get_bits = 0;
X}
X
X
X/* Flush_bits: Flush the buffered bits to stdout.
X*/
Xvoid flush_bits()
X{
X  int i;
X  put_bit(1);                            /* Eof marker. */
X  for (i = 0; i < 7; i++) put_bit(0);    /* Fillup byte. */
X  write_bit_buff();
X}
X
X/* put_n_bits: put low `n' bits from code on stream.
X*/
Xvoid put_n_bits(code, n)
Xlong code;
Xint n;
X{
X  int uggy_buggy;       /* The Minix C compiler won't handle longs properly */
X
X  if (n < 0 || n > sizeof(long) * 8)
X        n = n;
X  assert(n >= 0 && n < sizeof(long) * 8);
X
X  code &= ((long) 1 << n) - 1;
X  while (n > put_room) {
X        n -= put_room;
X	uggy_buggy = (int)(code >> n) & ((1 << put_room) - 1);
X        *next() = (put_bits << put_room) | uggy_buggy;
X	if (bit_buff_full()) write_bit_buff();
X        put_bits = 0;           /* Flag. */
X        put_room = 8;
X  }
X  put_bits = (put_bits << n) | (int)code;
X  if ((put_room -= n) == 0) {
X        *next() = put_bits;
X	if (bit_buff_full()) write_bit_buff();
X        put_bits = 0;
X        put_room = 8;
X  }
X}
X
X/* get_n_bits: Get `n' bits from stdin.
X*/
Xint get_n_bits(n)
Xint n;
X{
X  int ret = 0;                  /* Return value. */
X  int bit;
X
X  assert(n > 0 && n < sizeof(int) * 8);
X
X  while (n-- > 0) {
X        ret <<= 1;
X        bit = get_bit();
X        if (bit == 0) {
X                /* EMPTY */
X        } else if (bit == 1) {
X                ret |= 1;
X        } else if (bit == EOF) {
X                fprintf(stderr, "\r%s: Unexpected EOF\n", pname);
X                exit(-1);
X        } else {
X                fprintf(stderr, "\r%s: funny bit\n", pname);
X                exit(-1);
X        }
X  }
X  return ret;
X}
X
X/* Basename: Do a check on name, only comic, decomic and xcat are allowed.
X*/
Xchar *basename(name)
Xchar *name;
X{
X  char *p;
X#ifdef DOS
X  /* DOS needs special attention. Uppercase letters and leading path
X  ** must be removed. Also .com or .exe suffixes have to be removed.
X  */
X  p = strrchr(name, '\\');
X  if (p != NULL)
X        name = p + 1;                   /* Kill path prefix. */
X
X  str_2_lower (p);                         /* Make name lower case. */
X
X  p = strrchr(name, '.');
X  if (p != NULL) {
X	if (!str_equel(p, ".exe") && !str_equel(p, ".com")) {
X		fprintf(stderr, "\r%s: Warning funny suffix %s\n", pname, p);
X        }
X        *p = '\0';                      /* Kill the .exe or .com suffix. */
X  }
X  else
X	fprintf(stderr, "\r%s: Warning no DOS suffix\n", pname);
X
X#else /* Non DOS. */
X  p = strrchr(name, '/');
X  if (p != NULL)
X	name = p + 1;                   /* Kill path prefix. */
X#endif
X  if (strncmp(name, "[de]comic", 9) == 0) {
X#ifdef DOS
X	printf("\rHUH?\n");
X#else
X	printf("\rYou are FUNNY!\n");
X#endif
X	exit(-99);
X  }
X  if (!str_equel(name, COMIC)
X   && !str_equel(name, DECOMIC)
X   && !str_equel(name, XCAT)) {
X	fprintf(stderr, "\rThis program must be called [de]comic ");
X	fprintf(stderr, "or xcat, not \"%s\".\n", name);
X#ifndef DEBUG
X        /* In debug or force mode, allow other names.
X        */
X	if (f_flag < 2) exit(1);
X#endif
X  }
X  return name;
X}
X
X
X/* new_name: generate new output name according to the given name.
X*/
Xchar *new_name(fname)
Xchar *fname;
X{
X  static char ret_name[NAMELEN_MAX];   /* Buffer for return value. */
X  char *p;
X
X  /* Check the tail. If the suffix is present, just return it.
X  */
X  if ((p = strrchr(fname, SUFFIX[0])) != NULL
X  && str_equel(p, SUFFIX))
X        return fname;
X
X  strncpy(ret_name, fname, NAMELEN_MAX);
X  ret_name[(NAMELEN_MAX - 1) - strlen(SUFFIX)] = '\0'; /* Truncate. */
X
X  /* Truncate suffix to be able to hold the SUFFIX. Save the suffix 
X  ** for the header. If there is no suffix, add a "." string (DOS).
X  */
X#ifndef DOS
X  if (s_flag) {
X#endif
X	  if ((p = strrchr(ret_name, '.')) != NULL) {
X		if (!f_flag && strlen(p) > 4) {
X			fprintf(stderr, "%s: Warning ", pname);
X			fprintf(stderr, "suffix %s ", p);
X			fprintf(stderr, "will be trucated ");
X			p[4] = '\0';
X			fprintf(stderr, "to %s\n", p);
X                }
X                if (!d_flag && s_flag)
X			strncpy(suffix, p + 4 - SUFFIX_LEN, SUFFIX_LEN);
X		p[4 - SUFFIX_LEN] = '\0';              /* Truncate. */
X          }
X#ifdef DOS
X          else
X		strcat(ret_name, ".");
X#else
X  }
X#endif
X  strcat(ret_name, SUFFIX);
X  return ret_name;
X}
X
X
X/* org_name: generate original name according to the given name.
X*/
Xchar *org_name(fname)
Xchar *fname;
X{
X  static char ret_name[NAMELEN_MAX];   /* Buffer for return value. */
X  char *p;
X
X  strncpy(ret_name, fname, NAMELEN_MAX);       /* Make private copy. */
X  ret_name[NAMELEN_MAX - 1] = '\0';            /* Terminate. */
X
X  /* If the -X suffix is there delete it.
X  */
X  if ((p = strrchr(ret_name, SUFFIX[0])) != NULL
X  && str_equel(p, SUFFIX))
X        *p = '\0';
X
X  if (d_flag && suffix[0] != '\0') {           /* If there is a suffix, */
X	p = strchr(ret_name, '.');
X	if (p!= NULL)                   /* Allow one suffix char. */
X		p[2] = '\0';
X	strncat(ret_name, suffix, SUFFIX_LEN); /* Add original suffix. */
X  }
X
X#ifdef DOS
X  p = ret_name + strlen(ret_name) -1;
X  if (*p == '.')
X        *p = '\0';   /* Kill empty suffix. */
X#endif /* DOS */
X
X  return ret_name;
X}
X
X/* new_stin: Set stdin to newin. Return success or fail.
X*/
Xint new_stdin(newin)
Xchar *newin;
X{
X  if (freopen(newin, "r", stdin) == (FILE *)NULL) {
X	fprintf(stderr, "\r%s: Can't open \"%s\"", pname, newin);
X	perror(" for reading: ");
X	fflush(stderr);
X        return 0;               /* Report error. */
X  }
X  Nin = 0;                      /* Reset input bytecounter. */
X  STDIN = newin;
X
X  return 1;
X}
X
X/* new_stdout: Set stdout to newout. Return success or fail.
X*/
Xint new_stdout(newout)
Xchar *newout;
X{
X  FILE *tty;                    /* File pointer for "/dev/tty" */
X  static char buf[2];
X  char *ans = buf;              /* To contain the answer, "y" or "n" */
X
X  Nout = 0;
X
X  /* If the cat flag is set, don't reopen stdout.
X  */
X  if (c_flag)
X          return 1;             /* Return success. */
X
X  /* Check if we will overwrite a file. (Unless the -f flag was given.)
X  */
X  if (!f_flag && access (newout, 0) == 0) {
X	if (!isatty(2) || (tty = fopen(TTY, "r")) == (FILE *)NULL) {
X		fprintf(stderr, "\r%s: Won't overwrite %s\n", pname, newout);
X		fflush(stderr);
X                return 0;
X        }
X	fprintf(stderr, "\r%s: Overwrite %s (y/n)? ", pname, newout);
X	fflush(stderr);
X	ans = fgets(ans, 2, tty);
X	if (tty != (FILE *)NULL) fclose(tty);
X	if (ans == NULL || *ans != 'y')
X		return 0;
X  }
X
X  /* Reopen stdout.
X  */
X  if (freopen(newout, "w", stdout) == (FILE *)NULL) {
X	fprintf(stderr, "\r%s: Can't open \"%s\"", pname, newout);
X	perror(" for writing: ");
X	fflush(stderr);
X        return 0;               /* Report fail. */
X  }
X  STDOUT = newout;
X  return 1;                     /* Return success. */
X}
X
X/* print_ratio: print the compression ratio if its negative, or the
X** verbose flag (v_flag) is TRUE. 
X*/
Xvoid print_ratio()
X{
X  long rat;
X
X  if (Nin == 0) {
X	if (!v_flag)
X		fprintf(stderr, "\r%s: Warning %s ", pname, STDIN);
X	fprintf(stderr, "is empty\n");
X        return;
X  }
X
X  /* Divide Nin and Nout by 2 as long as they are too big, to 
X  ** prevent overflowing the rat variable.
X  */
X  while (Nin > 10000 || Nout > 10000) { /* Get smaller value. */
X        Nin >>= 1;
X        Nout >>= 1;
X  }
X  if (Nin == 0) 
X	Nin = 1;
X  rat = ((Nin - Nout) * 10000) / Nin;
X
X  if (rat < 0L) {
X	if (!v_flag)
X		fprintf(stderr, "\r%s: ", pname);
X	fprintf(stderr, "Warning ");
X	if (!v_flag)
X		fprintf(stderr, "%s ", STDIN);
X  }
X
X  if (rat < 0L || v_flag) {
X	fprintf(stderr, "compression: %d", (int)(rat / 100));
X	fprintf(stderr, ".%02d%%\n", abs ((int)(rat % 100)));
X  }
X}
X
X/* Verbose option displays the info structure.
X*/
Xchar *info[] = {
X  "\rThis is comic Version ", VERSION, "\t  ",
X  "(p) Jan-Mark Wams (email: jms@cs.vu.nl)\n",
X#ifdef __DATE__
X  "Compiled on: ", __DATE__, "\n",
X#endif
X  "Flags: ",
X#ifdef DEBUG
X  "DEBUG ",
X#endif
X#ifdef C89
X  "C89 ",
X#endif
X#ifdef _MINIX
X  "MINIX ",
X#endif
X#ifdef UNIX
X  "UNIX ",
X#endif
X#ifdef AMOEBA
X  "AMOEBA ",
X#endif
X#ifdef M68
X  "M68 ",
X#endif
X#ifdef __BCC__
X  "BCC ",
X#endif
X#ifdef GCC
X  "GCC ",
X#endif
X#ifdef DOS
X  "DOS ",
X#endif
X#ifdef MSC
X  "MSC ",
X#endif
X#ifdef __TURBOC__
X  "TURBOC ",
X#else
X# ifdef __STDC__
X#  if ! __STDC__
X  "!",
X#  endif
X  "STDC ",
X# endif
X#endif
X#ifdef NDEBUG
X  "NDEBUG ",
X#endif
X#ifdef _POSIX_SOURCE
X  "_POSIX_SOURCE ",
X#endif
X  "\n",
X#ifdef H2_SIZE
X  "Hash table: %d,%d",
X#else
X  "Dynamic hash table",
X#endif
X  "\n",
X  NULL,
X};
X
X/* verbose_info: Give verbose information about this program.
X*/
Xvoid verbose_info()
X{
X  char **p;
X  for (p = info; *p != NULL; p++)
X	fprintf(stderr, *p, H1_SIZE, H2_SIZE); /* SIZEs not always needed. */
X}
X
X/* Usage: print the usage of comic.
X*/
Xvoid usage()
X{
X#ifndef DOS
X  char *options = "cdfrsvV?";
X
X  if (str_equel(pname, DECOMIC))
X        options = "cfrvV?";
X  else if (str_equel(pname, XCAT))
X        options = "rvV?";
X#else
X  char *options = "acdfrSvV?";
X  char *optstr;
X
X  if (str_equel(pname, DECOMIC))
X        options = "acfrvV?";
X  else if (str_equel(pname, XCAT))
X        options = "arvV?";
X#endif /* DOS */
X
X  fprintf(stderr, "Usage: %s [-%s] [<file>[-X]...]\n", pname, options);
X
X#ifdef DOS              /* DOS has no manual pages so we add extra info. */
X  while (*options != '\0') {
X        switch (*options) {
X          case 'r': optstr = "Raw; don't use a header";            break;
X          case 'c': optstr = "Cat; generate ouput on stdout";      break;
X          case 'd': optstr = "De-comic; decomic given files";      break;
X          case 'f': optstr = "Force; just carry on";               break;
X          case 'S': optstr = "Suffix; don't save the suffix";      break;
X          case 'a': optstr = "Ascii; %ss ascii files only";        break;
X          case 'v': optstr = "Verbose; tell what's going on";      break;
X          case 'V': optstr = "Version; give %ss version";          break;
X          case '?': optstr = "What; give usage of %s";             break;
X          default:  optstr = "even I don't know this one";
X        }
X	fprintf(stderr, "    -%c:  ", *options);
X	fprintf(stderr, optstr, pname); /* Pname not always needed. */
X	fprintf(stderr, ".\n");
X        options ++;
X  }
X  fprintf(stderr, "   -ff:  Carry on through fatal errors.\n");
X  if (str_equel(pname, COMIC))
X	fprintf(stderr, "   -vv:  Extra verbose output.\n");
X# ifdef DEBUG
X  fprintf(stderr, "  -vvv:  Super verbose (debug) output.\n");
X# endif /* DEBUG */
X#endif /* DOS */
X}
X
X
X/* File_start: Print a message if verbose option.
X*/
Xvoid file_start()
X{
X  if (v_flag) {
X	fprintf(stderr, "%s: ", STDIN);
X        if (d_flag)
X		fprintf(stderr, "decomicing");
X  }
X  fflush(stderr);
X}
X
X/* File_done: Print a message if verbose option.
X*/
Xvoid file_done()
X{
X  if (v_flag && d_flag)
X	fprintf(stderr, "\b\b\bed to %s\n", STDOUT);
X  if (!d_flag)
X	print_ratio();
X  fflush(stderr);
X}
X
X/* 
X   For speed's sake, a (two dimensional) hash table is implemented
X   on top of the existing structure (circular buffer).
X   For each character pair {c1, c2} there exists an index(at hash_tbl 
X   [H1(c1), H2(c2)]) containing the index of the first pair {d1, d2}
X   in the buffer so that H1(c1) == H1(d1) and H2(c2) == H2(d2). 
X   Both Hs are functions ie. if H (c) != H (d) than c != d. The same 
X   index is used as an index to the index list, to find the next index. 
X   Again this index is used in both the buffer and the index list 
X   (next_list) etc. The final index is INDEX_END. There is also an 
X   index list pointing back, so the index list can be quickly updated. 
X   This leaves us with a double linked list like construction.
X*/
X
Xindext *hash_tbl = (indext *)NULL;
Xindext next_list[BUFF_SIZE];                   /* The index list. */
Xindext back_list[BUFF_SIZE];                   /* The back list. */
X
X  static char *Hash_Mem = NULL;
X
X/* hash_init: Initialise the hash table.
X*/
Xvoid hash_init()
X{
X  int i;
X#ifndef H2_SIZE
X  char _stack_space_needed_by_program[2048];
X  _stack_space_needed_by_program[0] |= 1;
X#endif
X
X  /* First time Hash_Mem == NULL
X  */
X  if (Hash_Mem == NULL)
X	Hash_Mem = malloc(H1_SIZE * H2_SIZE * sizeof(indext));
X
X#ifndef H2_SIZE
X  /* Find the maximum amount of memory, Note that this 
X  ** might leave us with a stack space shortage ;-(.
X  */ 
X  while (Hash_Mem == NULL && H1_SIZE > 4) {
X        if (H1_SIZE == H2_SIZE)
X	       H2_SIZE >>= 1;
X        else 
X               H1_SIZE >>= 1;
X	Hash_Mem = (char *)malloc(H1_SIZE * H2_SIZE * sizeof(indext));
X  }
X  if (v_flag > 1)
X	fprintf(stderr, "\r%s: Hash size %d,%d\n", pname, H1_SIZE, H2_SIZE);
X#endif /* H2_SIZE */
X
X  if (Hash_Mem == NULL) {
X	fprintf(stderr, "\r%s: Out of memory.\n", pname);
X	exit(-1);
X  }
X  hash_tbl = (indext *)Hash_Mem;
X
X  /* Init the hash table.
X  */
X  for (i = 0; i < H1_SIZE * H2_SIZE; i++)
X	hash_tbl[i] = INDEX_END;
X
X  /* Fill the next_list and back_list.
X  */
X  next_list[0] = BUFF_SIZE - 1;
X  back_list[BUFF_SIZE - 1] = 0;
X  for (i = 1; i < BUFF_SIZE; i++) {
X	next_list[i] = i - 1;
X	back_list[i - 1] = i;
X  }
X
X  /* Update the hash table for a buffer full of zeros.
X  */
X  hash_entry('\0', '\0') = i = Bindex(Bsub(Bp, 2));
X  back_list[i] = INDEX_END;
X  next_list[Bindex(Bsub(Bp, OFFSET_MAX))] = INDEX_END;
X}
X
X
X/* Hash_update: Update the hash table. (Using the char at Bp)
X*/
Xvoid hash_update()
X{
X  char p = *Bpred(Bp);                         /* Previous char. */
X  char c = *Bp;                                 /* Current char. */
X  indext icur = Bindex(Bp);                    /* Current index. */
X  indext ipre = Ipred(icur);                   /* Previous index. */
X  char *  tail = Bsub(Bp, OFFSET_MAX);         /* Tail of offset buff. */
X  indext new_tail = back_list[Bindex(tail)];  /* New tail of next list. */
X  indext ipc = hash_entry(p, c);               /* Index of hash (p,c). */
X
X  if (next_list[Bindex(tail)] != INDEX_END)
X        *Bp = *Bp;
X
X  /* assert (next_list[Bindex(tail)] == INDEX_END); @@@ */
X
X  if ((next_list[ipre] = ipc) != INDEX_END)
X  back_list[ipc] = ipre;
X  hash_entry(p, c) = ipre;             /* Update list at head of buffer. */
X  back_list[ipre] = INDEX_END;
X
X  if (new_tail == INDEX_END) {          /* Idem tail. */
X	hash_entry(*tail, *Bsucc (tail)) = INDEX_END;
X  }
X  else {
X	next_list[new_tail] = INDEX_END;
X  }
X}
X
X/*
X   Decoding: Note we always decode stdin to stdout. Get a bit, 
X   if it's a 0, decode a pair, if it's a 1, decode a char. If 
X   it's 1 nor 0, fly the broomstick. *8-)
X*/
X
X/* decode_pair: Read offset and length, and put substring on stdout.
X*/
Xvoid decode_pair()
X{
X  int len, off = Hdecode(Hoff);
X  char *p;
X
X  off = off << LOW_OFFSET_BITS;
X  off |= get_n_bits(LOW_OFFSET_BITS);
X  off += OFFSET_MIN;
X  len = Hdecode(Hlen) + LENGTH_MIN;
X#ifdef DEBUG
X  if (v_flag > 1)
X	printf("<%d,%d>\"", off, len);
X#endif
X  p = Bsub(Bp, off);
X  while (len --) {
X        putchar (*p);
X        *Bp = *p;
X	p = Bsucc(p);
X	Bp = Bsucc(Bp);
X  }
X#ifdef DEBUG
X  if (v_flag > 1)
X# ifdef DOS
X	printf("\"\r\n");
X# else
X	printf("\"\n");
X# endif
X#endif
X}
X
X/* decode_char: Get a huffman encoded char and put it on stdout.
X*/
Xvoid decode_char()
X{
X  int c = Hdecode(Hchar);
X  putchar (c);
X#ifdef DEBUG
X  if (v_flag > 1) {
X# ifdef DOS
X        putchar ('\r');
X# endif
X        putchar ('\n');
X  }
X#endif
X  *Bp = c;
X  Bp = Bsucc(Bp);
X}
X
X/* get_input: Get input buffer full, return EOF if end of file, SPC otherwise.
X*/
Xint get_input()
X{
X  static unsigned long fsize = 0L;
X  static struct stat st[1];
X  static int printed = -1;              /* -1 Means don't print. */
X  int percent, c;
X  char *stop = Blookupstart(), *Oinputend = Binputend;
X
X  if (v_flag > 1 && Nin == 0 && fstat (0, st) == 0 
X      && S_ISREG (st[0].st_mode)) {
X	fsize = (unsigned long) (st[0].st_size);
X	fprintf(stderr, "  0%%");
X	fflush(stderr);
X        printed = 0;
X  }
X
X/*
X   Read stdin till stop. This code may look complicated, but it
X   isn't. Most of it is about printing.
X*/
X
X  while (Binputend != stop && (c = getchar()) != EOF) {
X        *Binputend = c;
X#ifdef DOS
X        if (a_flag && c == '\n')        /* Size of file is including \r. */
X                Nin += 1;               /* But we don't read it, so adjust. */
X#endif
X	Binputend = Bsucc(Binputend);  /* Increase the input end marker. */
X  }
X  Nin += Bdelta(Binputend, Oinputend); /* Count the number of char's read. */
X
X  if (Nin < fsize) {    /* Note 0 <=  Nin < fsize A thus 0 < fsize */
X        percent = 100 - (int)((fsize - Nin) / (fsize / 100));
X        if (percent > printed) {
X		fprintf(stderr, "\b\b\b\b%3d%%", percent);
X		fflush(stderr);
X                printed = percent;
X        }
X  }
X
X  if (Bp == Binputend) {
X        assert (Oinputend == Binputend);
X#ifdef DOS
X        if (a_flag && fsize != 0 && Nin != fsize && Nin != fsize -1) {
X		fprintf(stderr, "\r%s: -a used on binary data:", pname);
X		fprintf(stderr, " aberrant decomic results\n");
X        }
X        else
X                assert (fsize == 0 || Nin == fsize || Nin == fsize - 1);
X#else
X        /* This assertion might fail if one comics a binary file under MS-DOS.
X        */
X        assert (fsize == 0 || Nin == fsize);
X#endif /* DOS */
X        if (printed != -1) {
X		fprintf(stderr, "\b\b\b\b");
X		fflush(stderr);
X        }
X        return EOF;
X  }
X  else
X	return (int)' ';
X}
X
X/*
X   To find the best (longest) part to output we try to find the longest 
X   part matching the input in the lookup buffer. Well actually, we look 
X   for two srings, one, matching the current input, starting at the current 
X   buffer start, and one matching the string starting at the next input 
X   byte, (as if we decoded a char.) This is just in case decoding two 
X   pairs could have been done, using one char and pair. (This will save 
X   a few % extra.) To show what I mean, consider:
X  
X                                        xxxxx.AxAxxxxx
X        This would be parsed            x xxxx . A x Ax xxxx
X        but xxxx costs (about) as
X        much as xxxxx. So               x xxxx . A x A xxxxx
X        will be better.
X*/
X
X
X/* Eqlen: Return the number of bytes for which p[i] and q[i] are the same.
X*/
Xint eqlen(p, q, count)
Xchar *p;
Xregister char *q;
Xint count;
X{
X  register char *r;
X  char *stop, save;
X
X  assert (p != q);
X
X#ifdef OLD_SLOW_CODE
X  /*
X      If the code below look fussy, it's just a quick version of:
X  */
X  while (*r == *q && r != stop) {
X	r = Bsucc(r);
X	q = Bsucc(q);
X  }
X#else
X
X  if (p > q) {
X	r = q;
X	q = p;
X	p = r;
X  }
X  else
X	r = p;
X
X  /*
X      +-------------------------+-+
X      |           Buff          | | 
X      +-------------------------+-+
X      p=r^   q^   stop^    Bend^ ^Sentp
X  */
X
X  assert (r < q);
X
X  /* Prevent q from equeling stop in while loop. */
X  if (q - r <= count) {
X	stop = Badd(q, count);
X	save = *stop;
X	*stop = ~*Badd(r, count);
X  }
X  else {
X	stop = Badd(r, count);
X	save = *stop;
X	*stop = ~*Badd(q, count);
X  }
X
X  *Sentp = ~r[Sentp - q];
X  while (*r == *q) {
X	r++; 
X	q++;
X  }
X  if (q == Sentp) {
X	q = Buff;
X	*Sentp = ~Buff[Sentp - r];
X	while (*r == *q) {
X		r++;
X		q++;
X	}
X	if (r == Sentp) {
X		r = Buff;
X		while (*r == *q) {
X			r++;
X			q++;
X		}
X	}
X  }
X  *stop = save;
X#endif 
X
X  assert (Bdelta(r, p) <= count);
X  return Bdelta(r, p);
X}
X
X
X/* get_token: Find the best (longest) part to output.
X*/
Xvoid get_token(pair_0used)
Xint pair_0used;             /* Indicate if pair_0 was used. */
X{
X  register indext i;
X  register int len;             /* Used to store the result of eqlen. */
X  register int length;          /* Used for p[01]->length. */
X  register char *start = NULL;  /* Used for p[01]->start. */
X
X  /* Itail is a valid start value for pair_0, but not for pair_1.
X  */
X  indext itail = Bindex(Bsub(Bp, OFFSET_MAX)); /* Last index. */
X
X  int maxlen = Bdelta(Binputend, Bp);  /* Max match length. */
X  char *Bp1 = Bsucc(Bp);            /* Successor of Bp. */
X  char *Bp2 = Bsucc(Bp1);           /* Guess... */
X  char *Bp_1 = Bpred(Bp);
X
X  if (maxlen < LENGTH_MIN) {
X	pair_0->length = 0;
X        return;
X  }
X
X  if (maxlen > LENGTH_MAX) {
X        assert (maxlen <= LENGTH_MAX + PAIR_MAX + 1);
X        maxlen = LENGTH_MAX;
X  }
X
X  if (!pair_0used) {                      /* If pair_0 wasn't used, pair_1 */
X	pair_0->start = pair_1->start;   /* will be the new pair_0. */
X	     pair_0->length = pair_1->length; /* pair_1->length might be */
X	     if (pair_0->length >= maxlen) {   /* one too big. */
X			  pair_0->length = maxlen;
X			  pair_1->length = 0;
X		          return;                    /* We can't beat maxlen. */
X        }
X  }
X  else {
X        if (*Bp_1 == *Bp && *Bp == *Bp1) {    /* Bp - 1 isn't in the hash */
X                 start = Bp_1;
X		 length = eqlen(Bp_1, Bp, maxlen);
X                 if (length == maxlen) {
X                         pair_0->start = start;   /* This test saves time */
X                         pair_0->length = length; /* while comic-ing binary */
X                         pair_1->length = 0;      /* data (eg. tar files). */
X                         return;
X                 }
X        }         
X        else
X                length = 0;
X
X	i = hash_entry(*Bp, *Bp1);
X
X        while (i != INDEX_END) {
X		if (*Badd(Buff + i, length) == *Badd(Bp, length)
X		&& (len = eqlen(Buff + i, Bp, maxlen)) > length) {
X                        start = Buff + i;
X                        length = len;
X                }
X		i = next_list[i];
X        }
X	pair_0->start = start;
X	pair_0->length = length;
X  }
X
X  /* We should adjust maxlen here, but we get faster code if we just check 
X  ** if pair_1->length is (one) too long whilst copying pair_1 to pair_0.
X  */
X
X  if (*Bp == *Bp1 && *Bp1 == *Bp2) {   /* Bp1 - 1 isn't in the hash. */
X        start = Bp;
X	length = eqlen(Bp, Bp1, maxlen);
X        if (length == maxlen) {
X		pair_1->start = start;
X		pair_1->length = length;
X                return;
X        }
X  }
X  else if (*Bp_1 == *Bp1) {             /* Bp1 - 2 neither. */
X        start = Bp_1;
X	length = eqlen(Bp_1, Bp1, maxlen);
X        if (length == maxlen) {
X		pair_1->start = start;
X		pair_1->length = length;
X                return;
X        }
X  }
X  else
X        length = 0;
X
X  i = hash_entry(*Bp1, *Bp2);          /* Do pair_1. */
X
X  while (i != INDEX_END /* (i != itail) is done in if below. */) {
X	if (*Bp != Buff[Ipred(i)])
X	if (*Badd(Buff + i, length) == *Badd(Bp1, length))
X	if ((len = eqlen(Buff + i, Bp1, maxlen)) > length)
X	if (i != itail) {
X		start = Buff + i;
X		length = len;
X	}
X	i = next_list[i];
X  }
X
X  pair_1->start = start;
X  pair_1->length = length;
X
X  assert (pair_0->length <= maxlen);
X  assert (pair_1->length <= maxlen);
X}
X
X/* Magic_ok: Check the first bytes on stdin. They should be ok.
X** Return True if magic is ok, else False. Also set suffix if one
X** is there.
X*/
Xint magic_ok()
X{
X  char c1, c2;
X
X  if (r_flag)
X        return 1; /* No header in raw mode. */
X
X#ifdef DOS
X  setmode(0, O_BINARY);
X#endif
X
X  if (read (0, &c1, 1) != 1) {
X	fprintf(stderr, "\r%s: Can't read header\n", pname);
X        if (f_flag < 2) return 0;
X  }
X
X  if (read (0, &c2, 1) != 1) {
X	fprintf(stderr, "\r%s: Can't read header's 2nd byte\n", pname);
X        if (f_flag < 2) return 0;
X  }
X
X  if (c1 != MAGIC1 || (c2 & 0xF0) != MAGIC2) {
X	fprintf(stderr, "\r%s: Wrong magic in header\n", pname);
X        if (f_flag < 2) return 0;
X  }
X
X  suffix[0] = '\0';
X  if ((c2 & SUFFIX_BIT) != 0 && read (0, suffix, SUFFIX_LEN) != SUFFIX_LEN) {
X	fprintf(stderr, "\r%s: Can't read suffix bytes\n", pname);
X        if (f_flag < 2) return 0;
X  }
X
X  if ((c2 & DYNAMIC_BIT) != 0 || (c2 & STATIC_BIT) == 0) {
X	fprintf(stderr, "\r%s: Version %s ", pname, VERSION);
X	fprintf(stderr, "can't handle dynamic bit\n");
X        if (f_flag < 2) return 0;
X  }
X  if ((c2 & EXTEND_BIT) != 0) {
X	fprintf(stderr, "\r%s: Version %s ", pname, VERSION);
X	fprintf(stderr, "can't handle extend bit\n");
X        if (f_flag < 2) return 0;
X  }
X
X  return 1;
X}
X
X/* Put_magic: Write magic header on stdout. Append MS-DOS suffix to.
X*/
Xvoid put_magic()
X{
X  char c1 = MAGIC1, c2 = (MAGIC2 | STATIC_BIT);
X
X  if (r_flag)
X        return; /* Don't put magic in raw mode. */
X
X  /* Put the suffix bits if necessary.
X  */
X  if (s_flag && suffix[0] != '\0')
X      c2 |= SUFFIX_BIT;
X
X  if (write (1, &c1, 1) != 1 || write (1, &c2, 1) != 1) {
X	fprintf(stderr, "\r%s: Can't write header\n", pname);
X	exit(-1);
X  }
X#ifdef DOS
X  setmode(1, O_BINARY);
X#endif
X  if (s_flag && suffix[0] != '\0') {
X        if (write (1, suffix, SUFFIX_LEN) != SUFFIX_LEN) {
X		fprintf(stderr, "\r%s: Can't write suffix\n", pname);
X		exit(-1);
X        }
X        Nout += SUFFIX_LEN;  /* Account two byte suffix. */
X  }
X  Nout += 2;    /* Account two bytes magic. */
X}
X
X/* 
X   H (huffman) routines to get and put huffman codes. Note: If the 
X   Hencode is called for SWITCH codes with a codelength > HUFFMAN_BITS,
X   the actual code is used. This is mainly an optimisation for binary 
X   chunks in the text. This could be replaced by dynamic huffman code.
X   (See f.e. "Data Compression" ACM Computing Surveys, Vol.19 No. 3 
X   September 1987). I tried modified BSTW, but that wasn't too good.
X*/
X
X#define SWITCH 8
X
X#if OFFSET_BITS != 13
X# include "COMILER ERROR: the tables are generated for 13 bits."
X#endif
X
Xstruct ctab_s * ctab_tab[] = { ctab_char, ctab_off, ctab_len };
Xstruct tree_s * tree_tab[] = { tree_char, tree_off, tree_len };
Xint Ntolong[3];                /* Ntolong for each table. */
X
X/* Descend: descend down the tree.
X*/
Xint descend (tree)
Xstruct tree_s *tree;
X{
X  int i = (HUFFMAN_SIZE * 2) - 2;
X  int bit;
X
X  while (i >= HUFFMAN_SIZE) {
X        bit = get_bit();
X        if (bit == 0) {
X                i = tree[i - HUFFMAN_SIZE]._0;
X        } else
X        if (bit == 1) {
X                i = tree[i - HUFFMAN_SIZE]._1;
X        } else
X        if (bit == EOF) {
X                fprintf(stderr, "\r%s: Unexpected EOF\n", pname);
X                exit(-1);
X        } else {
X                fprintf(stderr, "\r%s: Funny bit\n", pname);
X                exit(-1);
X        }
X  }
X  return i;
X}
X
X
X/* Hinit: Get the proper huffman code tables.
X*/
Xvoid Hinit()
X{
X  Ntolong[0] = 0;
X  Ntolong[1] = 0;
X  Ntolong[2] = 0;
X}
X
X
X/* Hdecode: Get an int using a huffman tree.
X*/
Xint Hdecode(index)
Xint index;
X{
X  struct tree_s *tree = tree_tab[index];
X  struct ctab_s *ctab = ctab_tab[index];
X  int i;
X
X  if (Ntolong[index] > SWITCH) {
X	i = (int)get_n_bits(HUFFMAN_BITS);
X	if (ctab[i].length > HUFFMAN_BITS)
X		Ntolong[index] = SWITCH << 1;
X        else
X		Ntolong[index] -= 1;
X  }
X  else {
X        i = descend (tree);
X	if (ctab[i].length > HUFFMAN_BITS)
X		Ntolong[index] += 1;
X        else
X		Ntolong[index] = 0;
X  }
X  return i;
X}
X
X
X/* Hcodelen: Return the length of the encoded word in bits.
X*/
Xint Hcodelen(index, c)
Xint index;
Xint c;
X{
X  return Ntolong[index] > SWITCH ? HUFFMAN_BITS : ctab_tab[index][c].length;
X}
X
X/* Hencode: output code i from code table ctab
X*/
Xvoid Hencode(index, i)
Xint index, i;
X{
X  struct ctab_s *ctab = ctab_tab[index];
X  int len = ctab[i].length;
X
X  if (Ntolong[index] > SWITCH) {
X	put_n_bits((long)i, HUFFMAN_BITS);
X        if (len > HUFFMAN_BITS)
X		Ntolong[index] = SWITCH << 1;
X        else
X		Ntolong[index] -= 1;
X  }
X  else {
X	put_n_bits((long)(ctab[i].code), len);
X        if (len > HUFFMAN_BITS)
X		Ntolong[index] += 1;
X        else
X		Ntolong[index] = 0;
X  }
X}
X
X
X/* Decode: decode stdin. Read a bit from stdin, if it's a 0, decode a pair,
X** if it's a 1 decode a char, if it's EOF, return.
X*/
Xvoid decode()
X{
X  int bit;
X
X  Bsize = OFFSET_SIZE + OFFSET_MIN;
X  Bend = &(Buff[OFFSET_MAX]);
X  Bp = Binputend = Buff;        /* Not necessary, but.. */
X  Binit();                     /* Init the buffer. */
X  Hinit();                     /* Init the huffman tables. */
X  init_bits();                 /* Init the bit package. */
X
X#ifdef DOS
X  setmode(0, O_BINARY);        /* And you wonder why they call it SM_DOS. */
X  if (a_flag)
X	setmode(1, O_TEXT);
X  else
X	setmode(1, O_BINARY);
X#endif
X
X  for (;;) {
X        bit = get_bit();
X        if (bit == 0) {
X                decode_pair();
X        } else
X        if (bit == 1) {
X                decode_char();
X        } else
X        if (bit == EOF) {
X                fflush(stdout);
X                return;                 /* EOF: we're done */
X        } else {
X                fprintf(stderr, "\r%s: Funny bit\n", pname);
X                exit(-1);
X        }
X  }
X}
X
X
X/*
X   Encoding is simple: Get next two longest strings, if the second 
X   one is longer, or the first one isn't long enough, encode a char,
X   else encode a pair, (offset, length).
X*/
X
X/* output_pair: Output pair_0's length and offset.
X*/
Xvoid output_pair(done)
Xint *done;      /* Set to False if pair codes are longer than char codes. */
X{
X  int offset = Bdelta(Bp, pair_0->start) - OFFSET_MIN;
X  int length = pair_0->length;
X
X  assert (offset >= 0);
X  assert (offset < OFFSET_SIZE);
X  assert (length >= LENGTH_MIN);
X  assert (length - LENGTH_MIN < HUFFMAN_SIZE);
X
X#if LENGTH_MIN <= 2
X  if (length == 2
X  &&
X      Hcodelen(Hoff, offset >> LOW_OFFSET_BITS) + LOW_OFFSET_BITS
X    + Hcodelen(Hlen, 2 - LENGTH_MIN)
X    >
X      Hcodelen(Hchar, 0xFF & (int)*Bp) 
X    + Hcodelen(Hchar, 0xFF & (int)*Bsucc(Bp))) {
X	*done = 0;
X	return;
X  }
X#endif
X
X  put_bit(0);                                  /* Put a 0. */
X  Hencode(Hoff, offset >> LOW_OFFSET_BITS);    /* Put offset high. */
X  put_n_bits((long)offset, LOW_OFFSET_BITS);   /* Put offset low. */
X  Hencode(Hlen, length - LENGTH_MIN);          /* Put index length. */
X
X#ifdef DEBUG
X  if (v_flag > 2) {
X	fprintf(stderr, "(%d,%d)", offset + OFFSET_MIN, length);
X	putc('"', stderr);
X  }
X#endif
X        while (length -- > 0) {
X#ifdef DEBUG
X		if (v_flag > 2) putc(*Bp, stderr);
X#endif
X		hash_update();         /* Update hash tables. */
X		Bp = Bsucc(Bp);
X        }
X#ifdef DEBUG
X        if (v_flag > 2) {
X		fprintf(stderr, "\"\n");
X		fflush(stderr);
X        }
X#endif /* DEBUG */
X  assert (done);
X}
X
X/* output_char: Output char *Bp.
X*/
Xvoid output_char()
X{
X  put_bit(1);                          /* Put a 1. */
X  Hencode(Hchar, (0xFF & (int)*Bp));   /* Put this char. */
X#ifdef DEBUG
X  if (v_flag > 2) {
X	putc('`', stderr);
X	putc(*Bp, stderr);
X	putc('\'', stderr);
X	putc('\n', stderr);
X  }
X#endif /* DEBUG */
X  hash_update();
X  Bp = Bsucc(Bp);                      /* Increase Bp. */
X}
X
X
X/* Encode: parse stdin, write huffman codes and bits on stdout.
X*/
Xvoid encode()
X{
X  /* Pairout indicates the pair pair_0 will be output, not just char *Bp.
X  */
X  int pairout = 1;
X  Bsize = BUFF_SIZE;
X  Bend = &(Buff[BUFF_MAX]);
X  Bp = Binputend = Buff;        /* Not necessary, but.. */
X  Binit();                     /* Init the buffer. */
X  Hinit();                     /* Init the huffman tables. */
X  init_bits();                 /* Init the bit package. */
X  hash_init();                 /* Init the hash tables. */
X
X#ifdef DOS
X  if (a_flag)
X	setmode(0, O_TEXT);
X  else
X	setmode(0, O_BINARY);  /* And you wonder why they call it SM_DOS. */
X
X  setmode(1, O_BINARY);
X#endif
X
X  while (get_input() != EOF) {
X	get_token(pairout);                      /* Find matching strings. */
X	pairout =  pair_0->length >= LENGTH_MIN  /* Long enough? */
X		&& pair_0->length >= pair_1->length;
X        if (pairout)
X		output_pair(&pairout);           /* If so, output its pair. */
X	if (!pairout)
X		output_char();                   /* Else do one char. */
X  }
X  flush_bits();                                  /* Flush buffered bits. */
X}
X
X/* main: Parse arguments, call proper (en/de) code routine.
X*/
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  char *p;              /* Used for flag processing etc. */
X  char *fname;
X
X#ifdef DOS
X  /* DOS-file names are in UPPER case.
X  */
X  str_2_upper(SUFFIX);
X#endif
X
X  pname = basename(*argv);
X
X  argc --;
X  argv ++;      /* Skip pname. */
X
X
X  if (str_equel(pname, DECOMIC))   /* If this program is called */
X        d_flag = -1;            /* decomic set the decode flag. */
X
X  if (str_equel(pname, XCAT)) {    /* If this program is called */
X        d_flag = -1;            /* xcat set the decode */
X        c_flag = -1;            /* and cat flag. */
X  }
X
X  while (argc > 0 && (*argv)[0] == '-' && (*argv)[1] != '\0') {
X        for (p = *argv + 1; *p != '\0'; p++) {
X                switch (*p) {
X                case 'd': d_flag = 1; break;           /* decode flag on. */
X                case 'r': r_flag = 1; break;           /* Raw flag. */
X                case 'v': v_flag ++; break;            /* Verbose flag. */
X                case 'f': f_flag ++; break;            /* Force flag on. */
X#ifdef DOS
X                case 'a': a_flag = 1; break;           /* Ascii mode. */
X                case 'S': s_flag = 0; break;           /* No suffix save. */
X#else
X                case 's': s_flag = 1; break;           /* Save suffix. */
X#endif
X                case 'c': c_flag = 1; break;           /* Cat flag on. */
X		case 'V': verbose_info(); exit(0);   /* Verbose info. */
X		case '?': usage(); exit(0);          /* Usage and exit. */
X                default :
X		    fprintf(stderr, "\r%s: -%c ignored\n", pname, *p);
X		    fflush(stderr);
X                }
X        }
X        argc --; argv ++;	/* Next please. */
X  }
X
X  if (argc == 0) {		/* No args, do stdin to stdout. */
X        c_flag = 1;		/* Cat mode. */
X	file_start();
X        if (d_flag) {
X		if (magic_ok())
X			decode();
X        }
X        else {
X		put_magic();
X		encode();
X        }
X	file_done();
X  }
X  else {
X        if (c_flag && !d_flag && f_flag < 2 && argc > 1) {
X		fprintf(stderr, "\r%s: Won't concatanate ", pname);
X		fprintf(stderr, "multiple files.\n");
X		exit(-1);
X        }
X  }
X
X  while ((fname = next_arg()) != NULL) {
X#ifdef DOS
X	str_2_upper(fname);
X#endif
X        if (d_flag) {   /* Decode. */
X		if ( !new_stdin(new_name(fname))
X		||   !magic_ok()
X		||   !new_stdout(org_name(fname)))
X                        continue;       /* If not reopened, do next file. */
X		file_start();
X		decode();      /* Decode stdin. */
X		file_done();
X        }
X        else /* No d_flag */ {  /* Encode. */
X		if ((p = strrchr(fname, *SUFFIX)) != NULL
X		&&  strncmp(p, SUFFIX, SUFFIX_LEN) == 0) {
X                        if (v_flag) {
X				fprintf(stderr, "\r%s: ", pname);
X				fprintf(stderr, "%s already has ", fname);
X				fprintf(stderr, "%s suffix\n", SUFFIX);
X				fflush(stderr);
X                        }
X                        continue;
X                }
X		if ( !new_stdin(org_name(fname))
X		||   !new_stdout(new_name(fname)))
X                        continue;       /* If not reopened, do next file. */
X		file_start();
X		put_magic();
X		encode();              /* Put data on stdout. */
X		file_done();
X        }
X  }
X  return 0;
X}
/
echo x - decomp16.c
sed '/^X/s///' > decomp16.c << '/'
X/* decomp16: decompress 16bit compressed files on a 16bit Intel processor
X *
X * Version 1.3 of 25 Mar 92.
X *
X * This was written by John N. White on 6/30/91 and is Public Domain.
X * Patched to run under news by Will Rose, Feb 92.
X * J N White's (earlier) patches added by Will Rose, 20 Feb 92.
X * Unsigned int increment/wrap bug fixed by Will Rose, 24 Mar 92.
X * Argument bug fixed, stdio generalised by Will Rose, 25 Mar 92.
X *
X * decomp16 can use as as little as 512 bytes of stack; since it forks
X * four additional copies, it's probably worth using minimum stack rather
X * than the 8192 byte Minix default.  To reduce memory still further,
X * change BUFSZ below to 256; it is currently set to 1024 for speed.  The
X * minimal decomp16 needs about 280k to run in pipe mode (56k per copy).
X *
X * This program acts as a filter:
X *    decomp16 < compressed_file > decompressed_file
X * The arguments -0 to -4 run only the corresponding pass.
X * Thus:
X *    decomp16 -4 < compressed_file > 3;
X *    decomp16 -3 < 3 > 2;
X *    decomp16 -2 < 2 > 1;
X *    decomp16 -1 < 1 > 0;
X *    decomp16 -0 < 0 > decompressed_file
X * will also work, as will connecting the passes by explicit pipes if
X * there is enough memory to do so.  File name arguments can also be
X * given directly on the command line.
X *
X * Compress uses a modified LZW compression algorithm. A compressed file
X * is a set of indices into a dictionary of strings. The number of bits
X * used to store each index depends on the number of entries currently
X * in the dictionary. If there are between 257 and 512 entries, 9 bits
X * are used. With 513 entries, 10 bits are used, etc. The initial dictionary
X * consists of 0-255 (which are the corresponding chars) and 256 (which
X * is a special CLEAR code). As each index in the compressed file is read,
X * a new entry is added to the dictionary consisting of the current string
X * with the first char of the next string appended. When the dictionary
X * is full, no further entries are added. If a CLEAR code is received,
X * the dictionary will be completely reset. The first two bytes of the
X * compressed file are a magic number, and the third byte indicates the
X * maximum number of bits, and whether the CLEAR code is used (older versions
X * of compress didn't have CLEAR).
X *
X * This program works by forking four more copies of itself. The five
X * programs form a pipeline. Copy 0 writes to stdout, and forks copy 1
X * to supply its input, which in turn forks and reads from copy 2, etc.
X * This sequence is used so that when the program exits, all writes
X * are completed and a program that has exec'd uncompress (such as news)
X * can immediately use the uncompressed data when the wait() call returns.
X *
X * If given a switch -#, where # is a digit from 0 to 4 (example: -2), the
X * program will run as that copy, reading from stdin and writing to stdout.
X * This allows decompressing with very limited RAM because only one of the
X * five passes is in memory at a time.
X *
X * The compressed data is a series of string indices (and a header at
X * the beginning and an occasional CLEAR code). As these indices flow
X * through the pipes, each program decodes the ones it can. The result
X * of each decoding will be indices that the following programs can handle.
X *
X * Each of the 65536 strings in the dictionary is an earlier string with
X * some character added to the end (except for the the 256 predefined
X * single char strings). When new entries are made to the dictionary,
X * the string index part will just be the last index to pass through.
X * But the char part is the first char of the next string, which isn't
X * known yet. So the string can be stored as a pair of indices. When
X * this string is specified, it is converted to this pair of indices,
X * which are flagged so that the first will be decoded in full while
X * the second will be decoded to its first char. The dictionary takes
X * 256k to store (64k strings of 2 indices of 2 bytes each). This is
X * too big for a 64k data segment, so it is divided into 5 equal parts.
X * Copy 4 of the program maintains the high part and copy 0 holds the
X * low part.
X */
X
X#include <sys/types.h>
X#include <fcntl.h>
X#include <stdlib.h>
X#include <unistd.h>
X
X#define BUFSZ		1024	/* size of i/o buffers */
X#define BUFSZ_2		(BUFSZ/2)	/* # of unsigned shorts in i/o bufs */
X#define DICTSZ		(unsigned)13056	/* # of local dictionary entries */
X#define EOF_INDEX	(unsigned short)0xFFFF	/* EOF flag for pipeline */
X#define FALSE		0
X#define TRUE		~FALSE
X
Xint fdin, fdout, fderr;		/* input, output, and error file descriptors */
Xint ibufstart, obufind, ibufend;/* i/o buffer indices */
Xint ipbufind = BUFSZ_2;		/* pipe buffer indices */
Xint opbufind = 0;
Xint pnum = -1;			/* ID of this copy */
Xunsigned short ipbuf[BUFSZ_2];	/* for buffering input */
Xunsigned short opbuf[BUFSZ_2];	/* for buffering output */
Xunsigned char *ibuf = (unsigned char *) ipbuf;
Xunsigned char *obuf = (unsigned char *) opbuf;
X
Xunsigned short dindex[DICTSZ];	/* dictionary: index to substring */
Xunsigned short dchar[DICTSZ];	/* dictionary: last char of string */
Xunsigned iindex, tindex, tindex2;	/* holds index being processed */
Xunsigned base;			/* where in global dict local dict starts */
Xunsigned tbase;
Xunsigned locend;		/* where in global dict local dict ends */
Xunsigned curend = 256;		/* current end of global dict */
Xunsigned maxend;		/* max end of global dict */
Xint dcharp;			/* ptr to dchar that needs next index entry */
Xint curbits;			/* number of bits for getbits() to read */
Xint maxbits;			/* limit on number of bits */
Xint clearflg;			/* if set, allow CLEAR */
Xint inmod;			/* mod 8 for getbits() */
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void ffork, (void));
X_PROTOTYPE(void die, (char *s));
X_PROTOTYPE(void myputc, (unsigned c));
X_PROTOTYPE(unsigned mygetc, (void));
X_PROTOTYPE(void getbits, (void));
X_PROTOTYPE(void getpipe, (void));
X_PROTOTYPE(void putpipe, (unsigned u, int flag));
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  char c, *cp;
X  int j, k, fdtmp;
X  unsigned int len;
X
X  /* Find the program name */
X  j = 0;
X  while (argv[0][j] != '\0') j++;
X  len = (unsigned int) j;
X  while (j--)
X	if (argv[0][j] == '/') break;
X  if (argv[0][j] == '/') j++;
X  cp = argv[0] + j;
X  len -= j;
X
X  /* Sort out the flags */
X  for (k = 1; k < argc; k++) {
X	if (argv[k][0] == '-') {
X		c = argv[k][1];
X		switch (c) {
X		    case '0':	/* pass numbers */
X		    case '1':
X		    case '2':
X		    case '3':
X		    case '4':	pnum = c - '0';	break;
X		    case 'd':	/* used by news */
X			break;
X		    default:
X			(void) write(1, "Usage: ", 7);
X			(void) write(1, cp, len);
X			(void) write(1, " [-#] [in] [out]\n", 17);
X			exit(0);
X			break;
X		}
X
X		/* Once it's checked, lose it anyway */
X		for (j = k; j < argc; j++) argv[j] = argv[j + 1];
X		argc--;
X		k--;
X	}
X  }
X
X  /* Default i/o settings */
X  fdin = 0;
X  fdout = 1;
X  fderr = 2;
X
X  /* Try to open specific files and connect them to stdin/stdout */
X  if (argc > 1) {
X	if ((fdtmp = open(argv[1], 0)) == -1) die("input open failed");
X	(void) close(0);
X	if ((fdin = dup(fdtmp)) == -1) die("input dup failed\n");
X	(void) close(fdtmp);
X  }
X  if (argc > 2) {
X	(void) unlink(argv[2]);
X	if ((fdtmp = creat(argv[2], 0666)) == -1) die("output creat failed");
X	(void) close(1);
X	if ((fdout = dup(fdtmp)) == -1) die("output dup failed\n");
X	(void) close(fdtmp);
X  }
X
X  /* Sort out type of compression */
X  if (pnum == -1 || pnum == 4) {/* if this is pass 4 */
X	/* Check header of compressed file */
X	if (mygetc() != 0x1F || mygetc() != 0x9D)      /* check magic number */
X		die("not a compressed file\n");
X	iindex = mygetc();	/* get compression style */
X  } else
X	getpipe();		/* get compression style */
X
X  maxbits = iindex & 0x1F;
X  clearflg = ((iindex & 0x80) != 0) ? TRUE : FALSE;
X  if (maxbits < 9 || maxbits > 16)	/* check for valid maxbits */
X	die("can't decompress\n");
X  if (pnum != -1 && pnum != 0)
X	putpipe(iindex, 0);	/* pass style to next copy */
X
X  /* Fork off an ancestor if necessary - ffork() increments pnum */
X  if (pnum == -1) {
X	pnum = 0;
X	if (pnum == 0) ffork();
X	if (pnum == 1) ffork();
X	if (pnum == 2) ffork();
X	if (pnum == 3) ffork();
X  }
X
X  /* Preliminary inits. Note: end/maxend/curend are highest, not
X   * highest + 1 */
X  base = DICTSZ * pnum + 256;
X  locend = base + DICTSZ - 1;
X  maxend = (1 << maxbits) - 1;
X  if (maxend > locend) maxend = locend;
X
X  while (TRUE) {
X	curend = 255 + (clearflg ? 1 : 0);	/* init dictionary */
X	dcharp = DICTSZ;	/* flag for none needed */
X	curbits = 9;		/* init curbits (for copy 0) */
X	while (TRUE) {		/* for each index in input */
X		if (pnum == 4) {/* get index using getbits() */
X			if (curbits < maxbits && (1 << curbits) <= curend) {
X				/* Curbits needs to be increased */
X				/* Due to uglyness in compress, these
X				 * indices in the compressed file are
X				 * wasted */
X				while (inmod) getbits();
X				curbits++;
X			}
X			getbits();
X		} else
X			getpipe();	/* get next index */
X
X		if (iindex == 256 && clearflg) {
X			if (pnum > 0) putpipe(iindex, 0);
X			/* Due to uglyness in compress, these indices
X			 * in the compressed file are wasted */
X			while (inmod) getbits();
X			break;
X		}
X		tindex = iindex;
X		/* Convert the index part, ignoring spawned chars */
X		while (tindex >= base) tindex = dindex[tindex - base];
X		/* Pass on the index */
X		putpipe(tindex, 0);
X		/* Save the char of the last added entry, if any */
X		if (dcharp < DICTSZ) dchar[dcharp++] = tindex;
X		if (curend < maxend && ++curend > (base - 1))
X			dindex[dcharp = (curend - base)] = iindex;
X
X		/* Do spawned chars. They are naturally produced in
X		 * the wrong order. To get them in the right order
X		 * without using memory, a series of passes,
X		 * progressively less deep, are used */
X		tbase = base;
X		while ((tindex = iindex) >= tbase) {/* for each char to spawn*/
X			while ((tindex2 = dindex[tindex - base]) >= tbase)
X				tindex = tindex2;    /* scan to desired char */
X			putpipe(dchar[tindex-base], 1); /* put it to the pipe*/
X			tbase = tindex + 1;
X			if (tbase == 0) break;	/* it's a wrap */
X		}
X	}
X  }
X}
X
X
X/* F f o r k
X *
X * Fork off the previous pass - the parent reads from the child.
X */
Xvoid ffork()
X{
X  int j, pfd[2];
X
X  if (pipe(pfd) == -1) die("pipe() error\n");
X  if ((j = fork()) == -1) die("fork() error\n");
X  if (j == 0) {			/* this is the child */
X	if (close(1) == -1) die("close(1) error\n");
X	if (dup(pfd[1]) != 1) die("dup(1) error\n");
X	(void) close(pfd[0]);
X	pnum++;
X  } else {			/* this is the parent */
X	if (close(0) == -1) die("close(0) error\n");
X	if (dup(pfd[0]) != 0) die("dup(0) error\n");
X	(void) close(pfd[1]);
X  }
X}
X
X
X/* D i e
X *
X * If s is a message, write it to stderr. Flush buffers if needed. Then exit.
X */
Xvoid die(s)
Xchar *s;
X{
X  /* Flush stdout buffer if needed */
X  if (obufind != 0) {
X	if (write(fdout, (char *) obuf, (unsigned) obufind) != obufind)
X		s = "bad stdout write\n";
X	obufind = 0;
X  }
X
X  /* Flush pipe if needed */
X  do
X	putpipe(EOF_INDEX, 0);
X  while (opbufind);
X  /* Write any error message */
X  if (s != (char *) NULL) {
X	while (*s) (void) write(fderr, s++, 1);
X  }
X  exit((s == (char *) NULL) ? 0 : 1);
X}
X
X
X/* M p u t c
X *
X * Put a char to stdout.
X */
Xvoid myputc(c)
Xunsigned c;
X{
X  obuf[obufind++] = c;
X  if (obufind >= BUFSZ) {	/* if stdout buffer full */
X	if (write(fdout, (char *) obuf, BUFSZ) != BUFSZ)	/* flush to stdout */
X		die("bad stdout write\n");
X	obufind = 0;
X  }
X}
X
X
X/* M y g e t c
X *
X * Get a char from stdin. If EOF, then die() and exit.
X */
Xunsigned mygetc()
X{
X  if (ibufstart >= ibufend) {	/* if stdin buffer empty */
X	if ((ibufend = read(fdin, (char *) ibuf, BUFSZ)) <= 0)
X		die((char *) NULL);	/* if EOF, do normal exit */
X	ibufstart = 0;
X  }
X  return(ibuf[ibufstart++] & 0xff);
X}
X
X
X/* G e t b i t s
X *
X * Put curbits bits into index from stdin. Note: only copy 4 uses this.
X * The bits within a byte are in the correct order. But when the bits
X * cross a byte boundry, the lowest bits will be in the higher part of
X * the current byte, and the higher bits will be in the lower part of
X * the next byte.
X */
Xvoid getbits()
X{
X  int have;
X  static unsigned curbyte;	/* byte having bits extracted from it */
X  static int left;		/* how many bits are left in curbyte */
X
X  inmod = (inmod + 1) & 7;	/* count input mod 8 */
X  iindex = curbyte;
X  have = left;
X  if (curbits - have > 8) {
X	iindex |= mygetc() << have;
X	have += 8;
X  }
X  iindex |= ((curbyte = mygetc()) << have) & ~((unsigned) 0xFFFF << curbits);
X  curbyte >>= curbits - have;
X  left = 8 - (curbits - have);
X}
X
X
X/* G e t p i p e
X *
X * Get an index from the pipeline. If flagged firstonly, handle it here.
X */
Xvoid getpipe()
X{
X  static short flags;
X  static int n = 0;		/* number of flags in flags */
X
X  while (TRUE) {		/* while index with firstonly flag set */
X	if (n <= 0) {
X		if (ipbufind >= BUFSZ_2) {	/* if pipe input buffer
X						 * empty */
X			if (read(fdin, (char *) ipbuf, BUFSZ) != BUFSZ)
X				die("bad pipe read\n");
X			ipbufind = 0;
X		}
X		flags = ipbuf[ipbufind++];
X		n = 15;
X	}
X	iindex = ipbuf[ipbufind++];
X	if (iindex > curend)
X		die((iindex == EOF_INDEX) ? (char *) NULL : "invalid data\n");
X	flags <<= 1;
X	n--;
X	/* Assume flags < 0 if highest remaining flag is set */
X	if (flags < 0) {	/* if firstonly flag for index is not set */
X		while (iindex >= base) iindex = dindex[iindex - base];
X		putpipe(iindex, 1);
X	} else
X		return;		/* return with valid non-firstonly index */
X  }
X}
X
X
X/* P u t p i p e
X *
X * put an index into the pipeline.
X */
Xvoid putpipe(u, flag)
Xunsigned u;
Xint flag;
X{
X  static unsigned short flags, *flagp;
X  static int n = 0;		/* number of flags in flags */
X
X  if (pnum == 0) {		/* if we should write to stdout */
X	myputc(u);		/* index will be the char value */
X	return;
X  }
X  if (n == 0) {			/* if we need to reserve a flag entry */
X	flags = 0;
X	flagp = opbuf + opbufind;
X	opbufind++;
X  }
X  opbuf[opbufind++] = u;	/* add index to buffer */
X  flags = (flags << 1) | flag;	/* add firstonly flag */
X  if (++n >= 15) {		/* if block of 15 indices */
X	n = 0;
X	*flagp = flags;		/* insert flags entry */
X	if (opbufind >= BUFSZ_2) {	/* if pipe out buffer full */
X		opbufind = 0;
X		if (write(fdout, (char *) opbuf, BUFSZ) != BUFSZ)
X			die("bad pipe write\n");
X	}
X  }
X}
/
echo x - diskusage.c
sed '/^X/s///' > diskusage.c << '/'
X/* Diskusg - determines usage disk	  Author: Don Chapman */
X
X/*
X *
X * Diskusg -	Patterned after System V Administrative command
X *		but written for MINIX V1.5 or V1.6 from scratch.
X *		Does not access disk structures directly.  Should
X *		be fairly portable to C with dirent.  This version
X *		will count files that are linked to other names for
X *		each name.
X *
X * Output:	Output is a listing, on stdout, by uid of the blocks
X *		in use on a special device (block structured, ie. disk)
X *		sorted by uid.  Shows total blocks in use on the
X *		device for each uid. Form: uid username longint.
X *
X * Usage:	diskusg [-p fil] [-u fil] [-s] [-v] [-i flst] spec.file ...
X *
X * Flags:	-p fil	Use "fil" to obtain a list of the usernames and
X *			uids rather than /etc/passwd.  The file must be
X *			similar in form to /etc/passwd at least beyond
X *			the uid. eg: ast:Oky||V|yoZ7vO:8: or ast::8:
X *
X *		-u fil	Make an ascii list in "fil" of files that seem to
X *			belong to nobody.  The form of the list is:
X *			    special-file-name i-node-number user-ID.
X *
X *		-s	The input files are files of diskusg outputs and
X *			the new output should be the cumulative sum of the
X *			usages.  The files were probably made using the
X *			command diskusg /specdev > file.  This one deletes
X *			any duplicate usernames and charges all to the
X *			first username it sees.
X *
X *		-v	Verbose makes a listing on stderr of the files or
X *			directorys found with unknown owners.
X *
X *		-i flst	Ignore the data on the file systems whose name is
X *			in flst.  Flst is a list of names separated by
X *			commas or enclosed within quotes. Diskusg compares
X *			each name with the names on the spec. file relative
X *			to the root (/) of the spec. file.
X *			ie: dskusg -i /tmp/ignoreme,/joe,/lib /dev/fd1
X *
X *		specfil	The name of a special file (block structured) to be
X *			searched for disk usage.
X *			eg.: /dev/hd2
X *
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <string.h>
X#include <dirent.h>
X#include <errno.h>
X#include <limits.h>
X#include <blocksize.h>
X#include <stdlib.h>
X#include <ctype.h>
X#include <unistd.h>
X#include <stdio.h>
X
X/* Un-comment or compile -DREMOVE_DUPES if you wish */
X /* #define REMOVE_DUPES *//* option to always remove duplicate usernames */
X#define FALSE 0
X#define TRUE ~FALSE
X#define PWLEN 100
X#define PLENGTH 40
X
X#define USEREC struct userecord
XUSEREC {
X  char *name;
X  uid_t uid;
X  long blocks;
X  USEREC *next;
X};
X
X#define IGNREC struct ignrecord
XIGNREC {
X  char *structname;
X  IGNREC *next;
X};
X
Xstatic char *Version = "@(#) DISKUSG 1.00 D.E.C. (04/10/91)";
X
X/* Globals */
Xchar *progname;
Xchar *passwd = "/etc/passwd";
Xchar *ufile = NULL;
Xint uflag = FALSE;
XFILE *ufd;
XUSEREC *list_head = NULL;
Xint verbose = FALSE;
Xint sflag = FALSE;
Xchar *spec_name = "\0";
Xstruct stat *this_stat;
Xdev_t real_dev;
Xchar *ilist = NULL;
Xint iflag = FALSE;
XIGNREC *ign_head = NULL;
Xint didmount = FALSE;
Xint mountlength;
X
X_PROTOTYPE(int exists, (USEREC * head, Uid_t uid));
X_PROTOTYPE(void insert, (USEREC ** head, USEREC * rec));
X_PROTOTYPE(void make_userlist, (void));
X_PROTOTYPE(void showlist, (void));
X_PROTOTYPE(int update_list, (Uid_t uid, off_t bytes));
X_PROTOTYPE(void search_all, (char *cur_dir));
X_PROTOTYPE(int ilist_search, (char *path));
X_PROTOTYPE(void usage, (void));
X_PROTOTYPE(int main, (int argc, char *argv[]));
X_PROTOTYPE(void malloc_chk, (void *p));
X
X
X/* For -s flag that builds the list as it goes */
Xint exists(head, uid)		/* See if uid already exists.    */
XUSEREC *head;			/* In -s list disallow dupes. */
XUid_t uid;
X{
X  USEREC *curs;
X  for (curs = head; curs != NULL; curs = curs->next)
X	if (curs->uid == uid) return(TRUE);
X  return(FALSE);
X}
X
Xvoid insert(head, rec)		/* Sorted by uid (keep duplicates)   */
XUSEREC **head;			/* Normally there should be none but */
XUSEREC *rec;			/* I wanted option to see them...    */
X{
X  if (*head == NULL) {
X	rec->next = *head;
X	*head = rec;
X#ifdef REMOVE_DUPES
X  } else if ((*head)->uid == rec->uid) {
X	return;
X#endif
X  } else if ((*head)->uid > rec->uid) {
X	rec->next = *head;
X	*head = rec;
X  } else
X	insert(&((*head)->next), rec);
X}
X
Xvoid make_userlist()
X{				/* Make list of known users.  */
X  FILE *fp1;			/* do not remove duplicates   */
X  USEREC *temp_rec;		/* however the blocks will    */
X  char line[PWLEN];		/* counted against first name */
X  char *p1;
X  size_t name_length;
X
X  fp1 = fopen(passwd, "r");
X  while (!feof(fp1)) {
X	if (fgets(line, PWLEN, fp1)) {
X		temp_rec = (USEREC *) malloc(sizeof(USEREC));
X		malloc_chk(temp_rec);
X		p1 = line;
X		name_length = 0;
X		while (*p1 && *p1 != ':') {
X			p1++;
X			name_length++;
X		}
X		*p1++ = '\0';
X		temp_rec->name = (char *) malloc(name_length + 1);
X		malloc_chk(temp_rec);
X		strcpy(temp_rec->name, line);
X		while (*p1 && *p1 != ':') p1++;	/* skip passwd */
X		temp_rec->uid = atoi(++p1);
X		temp_rec->blocks = 0L;
X		insert(&list_head, temp_rec);
X	}
X  }
X  fclose(fp1);
X}
X
Xvoid showlist()
X{
X  USEREC *curs;
X  for (curs = list_head; curs != NULL; curs = curs->next)
X	printf("%d\t%-14s\t%ld\n", curs->uid, curs->name, curs->blocks);
X}
X
Xint update_list(uid, bytes)	/* Increment uid's total.   */
XUid_t uid;			/* If uid has duplicates    */
Xoff_t bytes;			/* will be charged to first. */
X{
X  USEREC *curs;
X  int found = 0;
X  for (curs = list_head; curs != NULL; curs = curs->next) {
X	if (curs->uid == uid) {
X		found++;
X		curs->blocks += (bytes + BLOCK_SIZE - 1) / BLOCK_SIZE;	/* ceiling */
X		break;
X	}
X  }
X  return(found);		/* -u and -v option need to know */
X}
X
X/* Traverse recursively: all directories on volume. */
Xvoid search_all(cur_dir)		/* If another volume is mounted on this vol */
Xchar *cur_dir;			/* only the files really on this volume are */
X{				/* to be counted in the accumulated total.  */
X  struct dirent *this_file;
X  DIR *dp1;			/* Activation record 4 pointers 1 int so */
X  char *next_entry;		/* should be able to recurse very deep.  */
X  int dir_length;		/* Uses malloc and free for temporary space */
X  int s;
X
X  dir_length = strlen(cur_dir);
X  next_entry = (char *) malloc(strlen(cur_dir) + NAME_MAX + 2);
X  malloc_chk(next_entry);
X  strcpy(next_entry, cur_dir);
X  if (next_entry[dir_length - 1] != '/') {
X	strcat(next_entry, "/");
X	dir_length++;
X  }
X  dp1 = opendir(cur_dir);
X  if (dp1 == NULL) {
X	fprintf(stderr, "Opendir returned NULL.  (%s).\n", strerror(errno));
X	exit(EXIT_FAILURE);
X  }
X  while ((this_file = readdir(dp1)) != NULL) {
X	/* Iterate through this directory */
X	if (strcmp(this_file->d_name, ".") &&
X	    strcmp(this_file->d_name, "..")) {
X		strcpy(&next_entry[dir_length], this_file->d_name);
X		stat(next_entry, this_stat);
X		if (real_dev != this_stat->st_dev) continue;
X		if (iflag) {
X			if (ilist_search(next_entry)) continue;
X		}
X		if (S_ISDIR(this_stat->st_mode)) {
X			/* Is a directory need to recurse */
X			s = update_list((Uid_t) this_stat->st_uid, 
X							   this_stat->st_size);
X			if (!s) {
X				if (verbose) fprintf(stderr,
X						"%s: Directory, No Owner, %s\n",
X					      progname, next_entry);
X				if (uflag) fprintf(ufd, "%s %d %d\n",
X						spec_name,
X						this_stat->st_ino,
X						this_stat->st_uid);
X			}
X			search_all(next_entry);	/* recursive call */
X		} else {
X			/* Is regular file or spec. file */
X			if (S_ISREG(this_stat->st_mode)) {
X				s = update_list((Uid_t) this_stat->st_uid,
X							   this_stat->st_size);
X				if (!s) {
X					if (verbose) fprintf(stderr,
X							"%s: File, No Owner, %s\n",
X							progname, next_entry);
X					if (uflag) fprintf(ufd, "%s %d %d\n",
X						spec_name, this_stat->st_ino,
X						this_stat->st_uid);
X				}	/* endif !update */
X			}	/* end S_ISREG */
X			/* Ignores any Specials: b, c, pipe, etc. */
X		}		/* endelse */
X	}			/* endif "." */
X  }				/* endwhile */
X  closedir(dp1);
X  free(next_entry);
X}
X
Xint ilist_search(path)
Xchar *path;
X{
X  IGNREC *ptr;
X  for (ptr = ign_head; ptr != NULL; ptr = ptr->next) {
X	if (!strcmp(&path[mountlength], ptr->structname)) return(TRUE);
X  }
X  return(FALSE);
X}
X
Xvoid usage()
X{
X  fprintf(stderr,
X   "Usage: %s [-p file] [-s] [-u file] [-v] [spec file]\n", progname);
X  exit(EXIT_FAILURE);
X}
X
X/* Later be sure have counted the directory file sizes too ! */
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  FILE *mtb;
X  FILE *dskusg;
X  USEREC *m_rec;
X  IGNREC *i_temp;
X  char line[PLENGTH];
X  char mountedon[PLENGTH];
X  char mf1[PLENGTH], mf2[PLENGTH], mf3[PLENGTH], mf4[PLENGTH], mf5[PLENGTH];
X  char *p1, *p2, *p3;
X  int r;
X  size_t siz;
X  uid_t m_uid;
X  long m_blocks;
X  unsigned scan_uid;
X  progname = argv[0];
X  argc--;
X  argv++;
X  while (argv[0][0] == '-') {
X	switch (argv[0][1]) {
X	    case 'p':
X		if (argc > 1) passwd = argv[1];
X		argc--;
X		argv++;
X		break;
X	    case 'v':	verbose++;	break;
X	    case 'u':
X		if (argc > 1) {
X			ufile = argv[1];
X			uflag++;
X			argc--;
X			argv++;
X			break;
X		} else
X			usage();
X	    case 'i':
X		if (argc > 1) {
X			ilist = argv[1];
X			iflag++;
X			argc--;
X			argv++;
X			break;
X		} else
X			usage();
X	    case 's':	sflag++;	break;
X	    default:	usage();
X	}
X	/* Else spec file ? */
X
X	argc--;
X	argv++;
X  }				/* end while '-' */
X  if (!argc) {
X	fprintf(stderr, "Usage: %s special\n", progname);
X	exit(EXIT_FAILURE);
X  }
X  if (!sflag) make_userlist();
X  if (iflag) {			/* parse the ignore string and make list */
X	p1 = p2 = ilist;
X	if (!*p1) {
X		fprintf(stderr, "%s: Bad -i list\n", progname);
X		exit(EXIT_FAILURE);
X	}
X	while (*p1) {
X		while (*p1 && !isspace(*p1) && *p1 != ',') p1++;
X		if (*p1) {
X			*p1 = '\0';
X			p1++;
X			while (isspace(*p1)) p1++;
X		}
X		i_temp = (IGNREC *) malloc(sizeof(IGNREC));
X		malloc_chk(i_temp);
X		siz = strlen(p2) + 1;
X		p3 = (char *) malloc(siz);
X		malloc_chk(p3);
X		i_temp->structname = p3;
X		strcpy(i_temp->structname, p2);
X		p2 = p1;
X		i_temp->next = ign_head;	/* just stack'em */
X		ign_head = i_temp;
X	}			/* end while */
X  }				/* if iflag */
X  if (uflag && !sflag) ufd = fopen(ufile, "w");
X
X/* While there are more "files" to this command */
X  while (argc > 0) {		/* more to do */
X	spec_name = argv[0];
X	argc--;
X	argv++;
X
X	/* Option -s sum values from previous diskusg output */
X	if (sflag) {
X		/* Read output of previous diskusg output and total it */
X		if ((dskusg = fopen(spec_name, "r")) == NULL) {
X			fprintf(stderr, "%s: -s open failed on %s\n", progname, spec_name);
X			exit(EXIT_FAILURE);
X		}
X		while (fgets(line, PLENGTH, dskusg)) {
X			sscanf(line, "%u%s%ld", &scan_uid, mf1, &m_blocks);
X			m_uid = scan_uid;
X			if (!exists(list_head, m_uid)) {
X				m_rec = (USEREC *) malloc(sizeof(USEREC));
X				malloc_chk(m_rec);
X				m_rec->name = (char *) malloc(strlen(mf1) + 1);
X				malloc_chk(m_rec->name);
X				strcpy(m_rec->name, mf1);
X				m_rec->uid = m_uid;
X				m_rec->blocks = 0L;
X				insert(&list_head, m_rec);
X			}	/* if !exist */
X			update_list((Uid_t) m_uid,
X				    (off_t) BLOCK_SIZE * m_blocks);
X		}		/* while fgets */
X		fclose(dskusg);
X		continue;	/* go on to next "while" file */
X	}			/* if sflag */
X	/* Search all the files on the special device (not option -s) */
X	stat(spec_name, this_stat);	/* will ignore "mounted on
X					 * spec.dev" */
X	real_dev = this_stat->st_rdev;	/* using only files really on
X					 * device */
X	/* See if is block special */
X	if (!S_ISBLK(this_stat->st_mode)) usage();
X
X	/* See if device is mounted already by searching mtab (old or new) */
X	if ((mtb = fopen("/etc/mtab", "r")) == NULL) {
X		fprintf(stderr, "%s: No /etc/mtab found.\n", progname);
X		exit(EXIT_FAILURE);
X	}
X	mountedon[0] = '\0';
X	while (!feof(mtb)) {	/* see if mounted already */
X		if (fgets(line, PLENGTH, mtb)) {
X			mf1[0] = mf2[0] = mf3[0] = mf4[0] = mf5[0] = '\0';
X			r = sscanf(line, "%s%s%s%s%s", mf1, mf2, mf3, mf4, mf5);
X			if (!strcmp(spec_name, mf1)) {
X				if (r > 4)
X					strcpy(mountedon, mf5);	/* hmmm.. old mtab */
X				else {
X					if (!strcmp(mf3, "root"))
X						strcpy(mountedon, "/");	/* old mtab */
X					else
X						strcpy(mountedon, mf2);	/* new mtab */
X				}
X				break;
X			}
X		}
X	}
X	fclose(mtb);
X	if (!mountedon[0]) {	/* not mounted so mount temporarily */
X		strcpy(mountedon, "tmpXXXXXX");
X		mktemp(mountedon);
X		if (mkdir(mountedon, 0700)) {
X			fprintf(stderr, "%s: Can not make a temporary directory in pwd\n", progname);
X			exit(EXIT_FAILURE);
X		}
X		if (mount(spec_name, mountedon, 1)) {	/* read only */
X			rmdir(mountedon);	/* clean up before leaving */
X			if (geteuid() != 0) {
X				fprintf(stderr, "%s: Must run as root in order to mount %s\n", progname, spec_name);
X				exit(EXIT_FAILURE);
X			}
X			fprintf(stderr, "%s: Could not mount %s\n", progname, spec_name);
X			exit(EXIT_FAILURE);
X		}
X		didmount = TRUE;
X	}
X	mountlength = strlen(mountedon);	/* Note: means -i names
X						 * begin with / */
X	search_all(mountedon);	/* call the "traverse and accumulate"
X				 * routine */
X	if (didmount) {
X		umount(spec_name);
X		rmdir(mountedon);
X		didmount = FALSE;
X	}
X	spec_name[0] = '\0';
X	mountedon[0] = '\0';
X  }				/* while argc > 0 .. spec_name */
X  if (uflag && !sflag) fclose(ufd);
X  showlist();			/* list results to stdout */
X  return(EXIT_SUCCESS);
X}
X
Xvoid malloc_chk(ptr)
Xvoid *ptr;
X{
X  if (ptr == NULL) {
X	fprintf(stderr, 
X		  "Malloc returned NULL.  Use chmem to allocate more stack\n");
X	exit(EXIT_FAILURE);
X  }
X}
/
echo x - dw.c
sed '/^X/s///' > dw.c << '/'
X/* dw - find duplicate words in a file		Author: Nelson Beebe */
X
X/* Usage: dw [file] */
X
X#include <stdlib.h>
X#include <string.h>
X#include <ctype.h>
X#include <stdio.h>
X
X_PROTOTYPE(int main, (int argc, char *argv []));
X_PROTOTYPE(int get_token, (FILE *f ));
X_PROTOTYPE(void make_lower, (void));
X_PROTOTYPE(void other, (void));
X_PROTOTYPE(void word, (void));
X
Xchar last_word[1024];
Xchar yytext[1024];
Xint yyleng;
Xlong last_line_number = 0L;
Xlong line_number = 1L;
X
X#define	T_EOF	EOF
X#define	T_WORD	0
X#define T_WHITE	1
X#define T_OTHER	2
X
X#define	isinitial(c)	(isalpha(c) || ((c) == '_'))
X#define ismiddle(c)	(isinitial(c) || isdigit(c))
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  register int token;
X  FILE *f;
X
X  if (argc > 2) {
X	fprintf(stderr, "Usage: dw [file]\n");
X	exit(1);
X  }
X
X  if (argc == 2) {
X	f = fopen(argv[1], "r");
X	if (f == NULL) {
X		fprintf(stderr, "dw: cannot open file %s\n", argv[1]);
X		exit(1);
X	}
X  } else {
X	f = stdin;
X  }
X  last_word[0] = '\0';
X
X  while ((token = get_token(f)) != T_EOF) {
X	switch (token) {
X	    case T_WORD:	word();		break;
X	    case T_WHITE:			break;
X	    case T_OTHER:	other();	break;
X	    default:				break;
X	}
X  }
X  exit(EXIT_SUCCESS);
X  return(0);			/* keep optimizers happy */
X}
X
Xint get_token(f)
XFILE *f;
X{
X  register int c;
X  register char *p;
X  register int token;
X
X  p = yytext;
X  c = fgetc(f);
X  if (c == EOF)
X	token = T_EOF;
X  else if (isinitial(c)) {
X	token = T_WORD;
X	while (ismiddle(c)) {
X		*p++ = c;
X		c = fgetc(f);
X	}
X	ungetc(c, f);		/* push back lookahead */
X  } else if (isspace(c)) {	/* whitespace forms single token */
X	token = T_WHITE;
X	while (isspace(c)) {
X		if (c == '\n') line_number++;
X		*p++ = c;
X		c = fgetc(f);
X	}
X	ungetc(c, f);		/* push back lookahead */
X  } else {			/* all other tokens are single char */
X	token = T_OTHER;
X  }
X  *p = '\0';			/* terminate token in yytext[] */
X  yyleng = (int) (p - yytext);
X  return(token);
X}
X
Xvoid make_lower()
X{
X  int n;
X  for (n = 0; n < yyleng; ++n)
X	if (isupper(yytext[n])) yytext[n] = tolower(yytext[n]);
X}
X
Xvoid other()
X{
X  strcpy(last_word, yytext);	/* so intervening 'words' do not */
X  /* Trigger output of duplicates */
X}
X
Xvoid word()
X{
X  make_lower();
X  if (strcmp(yytext, last_word) == 0) {
X	if (last_line_number == line_number)
X		printf("%ld: %s\n", line_number, yytext);
X	else
X		printf("%ld-%ld: %s\n", last_line_number, line_number, yytext);
X  }
X  strcpy(last_word, yytext);
X  last_line_number = line_number;
X}
/
echo x - fsck2.c
sed '/^X/s///' > fsck2.c << '/'
X/* Hacks for version 1.6 */					
X
X#define INODES_PER_BLOCK V2_INODES_PER_BLOCK
X#define INODE_SIZE ((int) V2_INODE_SIZE)
X#define INTS_PER_BLOCK (BLOCK_SIZE / (int) sizeof(int))
X#define MAX_ZONES (V2_NR_DZONES+V2_INDIRECTS+(long)V2_INDIRECTS*V2_INDIRECTS)
X#define NR_DZONE_NUM V2_NR_DZONES
X#define NR_INDIRECTS V2_INDIRECTS
X#define NR_ZONE_NUMS V2_NR_TZONES
X#define ZONE_NUM_SIZE V2_ZONE_NUM_SIZE
X#define bit_nr bit_t
X#define block_nr block_t
X#define d_inode d2_inode
X#define d_inum d_ino
X#define dir_struct struct direct
X#define i_mode d2_mode
X#define i_nlinks d2_nlinks
X#define i_size d2_size
X#define i_zone d2_zone
X#define zone_nr zone_t
X
X/* fsck - file system checker		Author: Robbert van Renesse */
X
X/* Modified by Norbert Schlenker
X*   Removed vestiges of standalone/DOS versions:
X*     - various unused variables and buffers removed
X*     - now uses library functions rather than private internal routines
X*     - bytewise structure copies replaced by structure assignment
X*     - fixed one bug with 14 character file names
X*     - other small tweaks for speed
X*
X* Modified by Lars Fredriksen at the request of Andy Tanenbaum, 90-03-10.
X*   Removed -m option, by which fsck could be told to make a file
X*   system on a 360K floppy.  The code had limited utility, was buggy,
X*   and failed due to a bug in the ACK C compiler.  Use mkfs instead!
X*/
X
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <ctype.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <limits.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X#include <minix/config.h>
X#include <minix/const.h>
X#include <minix/type.h>
X#include "../fs/const.h"
X#include "../fs/inode.h"
X#include "../fs/type.h"
X#include <minix/fslib.h>
X
X#undef printf			/* defined as printk in "../fs/const.h" */
X
X#include <stdio.h>
X
X#if INTEL_32BITS || (CHIP == SPARC)
X#define BITSHIFT	  5	/* = log2(#bits(int)) */
X#else
X#define BITSHIFT	  4	/* = log2(#bits(int)) */
X#endif
X
X#define MAXPRINT	  8	/* max. number of error lines in chkmap */
X#define MAXDIRSIZE     5000	/* max. size of a reasonable directory */
X#define CINDIR		128	/* number of indirect zno's read at a time */
X#define CDIRECT		 16	/* number of dir entries read at a time */
X
X/* Macros for handling bitmaps.  Now bit_t is long, these are bulky and the
X * type demotions produce a lot of lint.  The explicit demotion in POWEROFBIT
X * is for efficiency and assumes 2's complement ints.  Lint should be clever
X * enough not to warn about it since BITMASK is small, but isn't.  (It would
X * be easier to get right if bit_t was was unsigned (long) since then there
X * would be no danger from wierd sign representations.  Lint doesn't know
X * we only use non-negative bit numbers.) There will usually be an implicit
X * demotion when WORDOFBIT is used as an array index.  This should be safe
X * since memory for bitmaps will run out first.
X */
X#define BITMASK		((1 << BITSHIFT) - 1)
X#define WORDOFBIT(b)	((b) >> BITSHIFT)
X#define POWEROFBIT(b)	(1 << ((int) (b) & BITMASK))
X#define setbit(w, b)	(w[WORDOFBIT(b)] |= POWEROFBIT(b))
X#define clrbit(w, b)	(w[WORDOFBIT(b)] &= ~POWEROFBIT(b))
X#define bitset(w, b)	(w[WORDOFBIT(b)] & POWEROFBIT(b))
X
X#define ZONE_CT 	360	/* default zones  (when making file system) */
X#define INODE_CT	 95	/* default inodes (when making file system) */
X
X#include "../fs/super.h"
Xstruct super_block sb;
X
X#define STICKY_BIT	01000	/* not defined anywhere else */
X
X/* Ztob gives the block address of a zone
X * btoa gives the byte address of a block
X */
X#define ztob(z)		((block_nr) (z) << sb.s_log_zone_size)
X#define btoa(b)		((long) (b) * BLOCK_SIZE)
X#define SCALE		((int) ztob(1))	/* # blocks in a zone */
X#define FIRST		((zone_nr) sb.s_firstdatazone)	/* as the name says */
X
X/* # blocks of each type */
X#define N_SUPER		1
X#define N_IMAP		(sb.s_imap_blocks)
X#define N_ZMAP		(sb.s_zmap_blocks)
X#define N_ILIST		((sb.s_ninodes+INODES_PER_BLOCK-1) / INODES_PER_BLOCK)
X#define N_DATA		(sb.s_zones - FIRST)
X
X/* Block address of each type */
X#define BLK_SUPER	(SUPER_BLOCK)
X#define BLK_IMAP	(BLK_SUPER + N_SUPER)
X#define BLK_ZMAP	(BLK_IMAP  + N_IMAP)
X#define BLK_ILIST	(BLK_ZMAP  + N_ZMAP)
X#define BLK_FIRST	ztob(FIRST)
X#define ZONE_SIZE	((int) ztob(BLOCK_SIZE))
X#define NLEVEL		(NR_ZONE_NUMS - NR_DZONE_NUM + 1)
X
X/* Byte address of a zone/of an inode */
X#define zaddr(z)	btoa(ztob(z))
X#define inoaddr(i)	((long) (i - 1) * INODE_SIZE + (long) btoa(BLK_ILIST))
X#define INDCHUNK	((int) (CINDIR * ZONE_NUM_SIZE))
X#define DIRCHUNK	((int) (CDIRECT * DIR_ENTRY_SIZE))
X
Xchar *prog, *device;		/* program name (fsck), device name */
Xint firstcnterr;		/* is this the first inode ref cnt error? */
Xunsigned *imap, *spec_imap;	/* inode bit maps */
Xunsigned *zmap, *spec_zmap;	/* zone bit maps */
Xunsigned *dirmap;		/* directory (inode) bit map */
Xchar rwbuf[BLOCK_SIZE];		/* one block buffer cache */
Xblock_nr thisblk;		/* block in buffer cache */
Xchar nullbuf[BLOCK_SIZE];	/* null buffer */
Xnlink_t *count;			/* inode count */
Xint changed;			/* has the diskette been written to? */
Xstruct stack {
X  dir_struct *st_dir;
X  struct stack *st_next;
X  char st_presence;
X} *ftop;
X
Xint dev;			/* file descriptor of the device */
X
X#define DOT	1
X#define DOTDOT	2
X
X/* Counters for each type of inode/zone. */
Xint nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;
Xint npipe, nsyml, ztype[NLEVEL];
Xlong nfreezone;
X
Xint repair, automatic, listing, listsuper;	/* flags */
Xint firstlist;			/* has the listing header been printed? */
Xunsigned part_offset;		/* sector offset for this partition */
Xchar answer[] = "Answer questions with y or n.  Then hit RETURN";
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void initvars, (void));
X_PROTOTYPE(void fatal, (char *s));
X_PROTOTYPE(int eoln, (int c));
X_PROTOTYPE(int yes, (char *question));
X_PROTOTYPE(int atoo, (char *s));
X_PROTOTYPE(int input, (char *buf, int size));
X_PROTOTYPE(char *alloc, (unsigned nelem, unsigned elsize));
X_PROTOTYPE(void printname, (char *s));
X_PROTOTYPE(void printrec, (struct stack *sp));
X_PROTOTYPE(void printpath, (int mode, int nlcr));
X_PROTOTYPE(void devopen, (void));
X_PROTOTYPE(void devclose, (void));
X_PROTOTYPE(void devio, (block_nr bno, int dir));
X_PROTOTYPE(void devread, (long offset, char *buf, int size));
X_PROTOTYPE(void devwrite, (long offset, char *buf, int size));
X_PROTOTYPE(void pr, (char *fmt, int cnt, char *s, char *p));
X_PROTOTYPE(void lpr, (char *fmt, long cnt, char *s, char *p));
X_PROTOTYPE(bit_nr getnumber, (char *s));
X_PROTOTYPE(char **getlist, (char ***argv, char *type));
X_PROTOTYPE(void lsuper, (void));
X_PROTOTYPE(void getsuper, (void));
X_PROTOTYPE(void chksuper, (void));
X_PROTOTYPE(void lsi, (char **clist));
X_PROTOTYPE(unsigned *allocbitmap, (int nblk));
X_PROTOTYPE(void loadbitmap, (unsigned *bitmap, block_nr bno, int nblk));
X_PROTOTYPE(void dumpbitmap, (unsigned *bitmap, block_nr bno, int nblk));
X_PROTOTYPE(void initbitmap, (unsigned *bitmap, bit_nr bit, int nblk));
X_PROTOTYPE(void fillbitmap, (unsigned *bitmap, bit_nr lwb, bit_nr upb, char **list));
X_PROTOTYPE(void freebitmap, (unsigned *p));
X_PROTOTYPE(void getbitmaps, (void));
X_PROTOTYPE(void putbitmaps, (void));
X_PROTOTYPE(void chkword, (unsigned w1, unsigned w2, bit_nr bit, bit_nr nbit, char *type, int *n, int *report));
X_PROTOTYPE(void chkmap, (unsigned *cmap, unsigned *dmap, bit_nr bit, block_nr blkno, int nblk, bit_nr nbit, char *type));
X_PROTOTYPE(void chkilist, (void));
X_PROTOTYPE(void getcount, (void));
X_PROTOTYPE(void counterror, (Ino_t ino));
X_PROTOTYPE(void chkcount, (void));
X_PROTOTYPE(void freecount, (void));
X_PROTOTYPE(void printperm, (Mode_t mode, int shift, int special, int overlay));
X_PROTOTYPE(void list, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int Remove, (dir_struct *dp));
X_PROTOTYPE(void make_printable_name, (char *dst, char *src, int n));
X_PROTOTYPE(int chkdots, (Ino_t ino, off_t pos, dir_struct *dp, Ino_t exp));
X_PROTOTYPE(int chkname, (Ino_t ino, dir_struct *dp));
X_PROTOTYPE(int chkentry, (Ino_t ino, off_t pos, dir_struct *dp));
X_PROTOTYPE(int chkdirzone, (Ino_t ino, d_inode *ip, off_t pos, zone_nr zno));
X_PROTOTYPE(void errzone, (char *mess, zone_nr zno, int level, off_t pos));
X_PROTOTYPE(int markzone, (zone_nr zno, int level, off_t pos));
X_PROTOTYPE(int chkindzone, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr zno, int level));
X_PROTOTYPE(off_t jump, (int level));
X_PROTOTYPE(int zonechk, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr zno, int level));
X_PROTOTYPE(int chkzones, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr *zlist, int len, int level));
X_PROTOTYPE(int chkfile, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int chkdirectory, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int chklink, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int chkspecial, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int chkmode, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int chkinode, (Ino_t ino, d_inode *ip));
X_PROTOTYPE(int descendtree, (dir_struct *dp));
X_PROTOTYPE(void chktree, (void));
X_PROTOTYPE(void printtotal, (void));
X_PROTOTYPE(void chkdev, (char *f, char **clist, char **ilist, char **zlist));
X
X/* Initialize the variables used by this program. */
Xvoid initvars()
X{
X  register level;
X
X  nregular = ndirectory = nblkspec = ncharspec = nbadinode = npipe = nsyml = 0;
X  for (level = 0; level < NLEVEL; level++) ztype[level] = 0;
X  changed = 0;
X  thisblk = NO_BLOCK;
X  firstlist = 1;
X  firstcnterr = 1;
X}
X
X/* Print the string `s' and exit. */
Xvoid fatal(s)
Xchar *s;
X{
X  printf("%s\nfatal\n", s);
X  exit(-1);
X}
X
X/* Test for end of line. */
Xint eoln(c)
Xint c;
X{
X  return(c == EOF || c == '\n' || c == '\r');
X}
X
X/* Ask a question and get the answer unless automatic is set. */
Xint yes(question)
Xchar *question;
X{
X  register int c, answerchar;
X
X  if (!repair) {
X	printf("\n");
X	return(0);
X  }
X  printf("%s? ", question);
X  if (automatic) {
X	printf("yes\n");
X	return(1);
X  }
X  fflush(stdout);
X  if ((c = answerchar = getchar()) == 'q' || c == 'Q') exit(1);
X  while (!eoln(c)) c = getchar();
X  return !(answerchar == 'n' || answerchar == 'N');
X}
X
X/* Convert string to integer.  Representation is octal. */
Xint atoo(s)
Xregister char *s;
X{
X  register int n = 0;
X
X  while ('0' <= *s && *s < '8') {
X	n <<= 3;
X	n += *s++ - '0';
X  }
X  return n;
X}
X
X/* If repairing the file system, print a prompt and get a string from user. */
Xint input(buf, size)
Xchar *buf;
Xint size;
X{
X  register char *p = buf;
X
X  printf("\n");
X  if (repair) {
X	printf("--> ");
X	fflush(stdout);
X	while (--size) {
X		*p = getchar();
X		if (eoln(*p)) {
X			*p = 0;
X			return(p > buf);
X		}
X		p++;
X	}
X	*p = 0;
X	while (!eoln(getchar()));
X	return(1);
X  }
X  return(0);
X}
X
X/* Allocate some memory and zero it. */
Xchar *alloc(nelem, elsize)
Xunsigned nelem, elsize;
X{
X  char *p;
X
X  if ((p = (char *)malloc((size_t)nelem * elsize)) == 0)fatal("out of memory");
X  memset((void *) p, 0, (size_t)nelem * elsize);
X  return(p);
X}
X
X/* Print the name in a directory entry. */
Xvoid printname(s)
Xchar *s;
X{
X  register n = NAME_MAX;
X  int c;
X
X  do {
X	if ((c = *s) == 0) break;
X	if (!isprint(c)) c = '?';
X	putchar(c);
X	s++;
X  } while (--n);
X}
X
X/* Print the pathname given by a linked list pointed to by `sp'.  The
X * names are in reverse order.
X */
Xvoid printrec(sp)
Xstruct stack *sp;
X{
X  if (sp->st_next != 0) {
X	printrec(sp->st_next);
X	putchar('/');
X	printname(sp->st_dir->d_name);
X  }
X}
X
X/* Print the current pathname.  */
Xvoid printpath(mode, nlcr)
Xint mode;
Xint nlcr;
X{
X  if (ftop->st_next == 0)
X	putchar('/');
X  else
X	printrec(ftop);
X  switch (mode) {
X      case 1:
X	printf(" (ino = %u, ", ftop->st_dir->d_inum);
X	break;
X      case 2:
X	printf(" (ino = %u)", ftop->st_dir->d_inum);
X	break;
X  }
X  if (nlcr) printf("\n");
X}
X
X/* Open the device.  */
Xvoid devopen()
X{
X  if ((dev = open(device, repair ? O_RDWR : O_RDONLY)) < 0) {
X	perror(device);
X	fatal("");
X  }
X}
X
X/* Close the device. */
Xvoid devclose()
X{
X  if (close(dev) != 0) {
X	perror("close");
X	fatal("");
X  }
X}
X
X/* Read or write a block. */
Xvoid devio(bno, dir)
Xblock_nr bno;
Xint dir;
X{
X  if (dir == READING && bno == thisblk) return;
X  thisblk = bno;
X
X#if 0
Xprintf("%s at block %5d\n", dir == READING ? "reading " : "writing", bno);
X#endif
X  lseek(dev, (off_t) btoa(bno), SEEK_SET);
X  if (dir == READING) {
X	if (read(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE)
X		return;
X  } else {
X	if (write(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE)
X		return;
X  }
X
X  printf("%s: can't %s block %ld (error = 0x%x)\n", prog,
X         dir == READING ? "read" : "write", (long) bno, errno);
X  if (dir == READING) {
X	printf("Continuing with a zero-filled block.\n");
X	memset(rwbuf, 0, BLOCK_SIZE);
X	return;
X  }
X  fatal("");
X}
X
X/* Read `size' bytes from the disk starting at byte `offset'. */
Xvoid devread(offset, buf, size)
Xlong offset;
Xchar *buf;
Xint size;
X{
X  devio((block_nr) (offset / BLOCK_SIZE), READING);
X  memmove(buf, &rwbuf[(int) (offset % BLOCK_SIZE)], (size_t)size);  /* lint but OK */
X}
X
X/* Write `size' bytes to the disk starting at byte `offset'. */
Xvoid devwrite(offset, buf, size)
Xlong offset;
Xchar *buf;
Xint size;
X{
X  if (!repair) fatal("internal error (devwrite)");
X  if (size != BLOCK_SIZE) devio((block_nr) (offset / BLOCK_SIZE), READING);
X  memmove(&rwbuf[(int) (offset % BLOCK_SIZE)], buf, (size_t)size);  /* lint but OK */
X  devio((block_nr) (offset / BLOCK_SIZE), WRITING);
X  changed = 1;
X}
X
X/* Print a string with either a singular or a plural pronoun. */
Xvoid pr(fmt, cnt, s, p)
Xchar *fmt, *s, *p;
Xint cnt;
X{
X  printf(fmt, cnt, cnt == 1 ? s : p);
X}
X
X/* Same as above, but with a long argument */
Xvoid lpr(fmt, cnt, s, p)
Xchar *fmt, *s, *p;
Xlong cnt;
X{
X  printf(fmt, cnt, cnt == 1 ? s : p);
X}
X
X/* Convert string to number. */
Xbit_nr getnumber(s)
Xregister char *s;
X{
X  register bit_nr n = 0;
X
X  if (s == NULL)
X	return NO_BIT;
X  while (isdigit(*s))
X	n = (n << 1) + (n << 3) + *s++ - '0';
X  return (*s == '\0') ? n : NO_BIT;
X}
X
X/* See if the list pointed to by `argv' contains numbers. */
Xchar **getlist(argv, type)
Xchar ***argv, *type;
X{
X  register char **list = *argv;
X  register empty = 1;
X
X  while (getnumber(**argv) != NO_BIT) {
X	(*argv)++;
X	empty = 0;
X  }
X  if (empty) {
X	printf("warning: no %s numbers given\n", type);
X	return(NULL);
X  }
X  return(list);
X}
X
X/* Make a listing of the super block.  If `repair' is set, ask the user
X * for changes.
X */
Xvoid lsuper()
X{
X  char buf[80];
X
X  do {
X	/* Most of the following atol's enrage lint, for good reason. */  
X	printf("ninodes       = %u", sb.s_ninodes);
X	if (input(buf, 80)) sb.s_ninodes = atol(buf);
X	printf("nzones        = %ld", sb.s_zones);
X	if (input(buf, 80)) sb.s_zones = atol(buf);
X	printf("imap_blocks   = %u", sb.s_imap_blocks);
X	if (input(buf, 80)) sb.s_imap_blocks = atol(buf);
X	printf("zmap_blocks   = %u", sb.s_zmap_blocks);
X	if (input(buf, 80)) sb.s_zmap_blocks = atol(buf);
X	printf("firstdatazone = %u", sb.s_firstdatazone);
X	if (input(buf, 80)) sb.s_firstdatazone = atol(buf);
X	printf("log_zone_size = %u", sb.s_log_zone_size);
X	if (input(buf, 80)) sb.s_log_zone_size = atol(buf);
X	printf("maxsize       = %ld", sb.s_max_size);
X	if (input(buf, 80)) sb.s_max_size = atol(buf);
X	if (yes("ok now")) {
X		devwrite(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
X		return;
X	}
X  } while (yes("Do you want to try again"));
X  if (repair) exit(0);
X}
X
X/* Get the super block from either disk or user.  Do some initial checks. */
Xvoid getsuper()
X{
X  devread(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
X  if (listsuper) lsuper();
X  if (sb.s_magic == SUPER_MAGIC) fatal("Cannot handle V1 file systems");
X  if (sb.s_magic != SUPER_V2) fatal("bad magic number in super block");
X  if (sb.s_ninodes <= 0) fatal("no inodes");
X  if (sb.s_zones <= 0) fatal("no zones");
X  if (sb.s_imap_blocks <= 0) fatal("no imap");
X  if (sb.s_zmap_blocks <= 0) fatal("no zmap");
X  if (sb.s_firstdatazone <= 4) fatal("first data zone too small");
X  if (sb.s_log_zone_size < 0) fatal("zone size < block size");
X  if (sb.s_max_size <= 0) fatal("max. file size <= 0");
X}
X
X/* Check the super block for reasonable contents. */
Xvoid chksuper()
X{
X  register n;
X  register off_t maxsize;
X
X  n = bitmapsize((bit_t) sb.s_ninodes + 1);
X  if (sb.s_magic != SUPER_V2) fatal("bad magic number in super block");
X  if (sb.s_imap_blocks < n) fatal("too few imap blocks");
X  if (sb.s_imap_blocks != n) {
X	pr("warning: expected %d imap_block%s", n, "", "s");
X	printf(" instead of %d\n", sb.s_imap_blocks);
X  }
X  n = bitmapsize((bit_t) sb.s_zones);
X  if (sb.s_zmap_blocks < n) fatal("too few zmap blocks");
X  if (sb.s_zmap_blocks != n) {
X	pr("warning: expected %d zmap_block%s", n, "", "s");
X	printf(" instead of %d\n", sb.s_zmap_blocks);
X  }
X  if (sb.s_firstdatazone >= sb.s_zones)
X	fatal("first data zone too large");
X  if (sb.s_log_zone_size >= 8 * sizeof(block_nr))
X	fatal("log_zone_size too large");
X  if (sb.s_log_zone_size > 8) printf("warning: large log_zone_size (%d)\n",
X	       sb.s_log_zone_size);
X  n = (BLK_ILIST + N_ILIST + SCALE - 1) >> sb.s_log_zone_size;
X  if (sb.s_firstdatazone < n) fatal("first data zone too small");
X  if (sb.s_firstdatazone != n) {
X	printf("warning: expected first data zone to be %d ", n);
X	printf("instead of %u\n", sb.s_firstdatazone);
X  }
X  maxsize = MAX_FILE_POS;
X  if (((maxsize - 1) >> sb.s_log_zone_size) / BLOCK_SIZE >= MAX_ZONES)
X	maxsize = ((long) MAX_ZONES * BLOCK_SIZE) << sb.s_log_zone_size;
X  if (sb.s_max_size != maxsize) {
X	printf("warning: expected max size to be %ld ", maxsize);
X	printf("instead of %ld\n", sb.s_max_size);
X  }
X}
X
X/* Make a listing of the inodes given by `clist'.  If `repair' is set, ask
X * the user for changes.
X */
Xvoid lsi(clist)
Xchar **clist;
X{
X  register bit_nr bit;
X  register ino_t ino;
X  d_inode inode, *ip = &inode;
X  char buf[80];
X
X  if (clist == 0) return;
X  while ((bit = getnumber(*clist++)) != NO_BIT) {
X	setbit(spec_imap, bit);
X	ino = bit;
X	do {
X		devread(inoaddr(ino), (char *) ip, INODE_SIZE);
X		printf("inode %u:\n", ino);
X		printf("    mode   = %6o", ip->i_mode);
X		if (input(buf, 80)) ip->i_mode = atoo(buf);
X		printf("    nlinks = %6u", ip->i_nlinks);
X		if (input(buf, 80)) ip->i_nlinks = atol(buf);
X		printf("    size   = %6ld", ip->i_size);
X		if (input(buf, 80)) ip->i_size = atol(buf);
X		if (yes("Write this back")) {
X			devwrite(inoaddr(ino), (char *) ip, INODE_SIZE);
X			break;
X		}
X	} while (yes("Do you want to change it again"));
X  }
X}
X
X/* Allocate `nblk' blocks worth of bitmap. */
Xunsigned *allocbitmap(nblk)
Xint nblk;
X{
X  register unsigned *bitmap;
X
X  bitmap = (unsigned *) alloc((unsigned) nblk, BLOCK_SIZE);
X  *bitmap |= 1;
X  return(bitmap);
X}
X
X/* Load the bitmap starting at block `bno' from disk. */
Xvoid loadbitmap(bitmap, bno, nblk)
Xunsigned *bitmap;
Xblock_nr bno;
Xint nblk;
X{
X  register i;
X  register unsigned *p;
X
X  p = bitmap;
X  for (i = 0; i < nblk; i++, bno++, p += INTS_PER_BLOCK)
X	devread(btoa(bno), (char *) p, BLOCK_SIZE);
X  *bitmap |= 1;
X}
X
X/* Write the bitmap starting at block `bno' to disk. */
Xvoid dumpbitmap(bitmap, bno, nblk)
Xunsigned *bitmap;
Xblock_nr bno;
Xint nblk;
X{
X  register i;
X  register unsigned *p = bitmap;
X
X  for (i = 0; i < nblk; i++, bno++, p += INTS_PER_BLOCK)
X	devwrite(btoa(bno), (char *) p, BLOCK_SIZE);
X}
X
X/* Initialize the given bitmap by setting all the bits starting at `bit'. */
Xvoid initbitmap(bitmap, bit, nblk)
Xunsigned *bitmap;
Xbit_nr bit;
Xint nblk;
X{
X  register unsigned *first, *last;
X
X  while (bit & BITMASK) {
X	setbit(bitmap, bit);
X	bit++;
X  }
X  first = &bitmap[bit >> BITSHIFT];
X  last = &bitmap[nblk * INTS_PER_BLOCK];
X  while (first < last) *first++ = ~(unsigned) 0;
X}
X
X/* Set the bits given by `list' in the bitmap. */
Xvoid fillbitmap(bitmap, lwb, upb, list)
Xunsigned *bitmap;
Xbit_nr lwb, upb;
Xchar **list;
X{
X  register bit_nr bit;
X
X  if (list == 0) return;
X  while ((bit = getnumber(*list++)) != NO_BIT)
X	if (bit < lwb || bit >= upb) {
X		if (bitmap == spec_imap)
X			printf("inode number %ld ", bit);
X		else
X			printf("zone number %ld ", bit);
X		printf("out of range (ignored)\n");
X	} else
X		setbit(bitmap, bit - lwb + 1);
X}
X
X/* Deallocate the bitmap `p'. */
Xvoid freebitmap(p)
Xunsigned *p;
X{
X  free((char *) p);
X}
X
X/* Get all the bitmaps used by this program. */
Xvoid getbitmaps()
X{
X  imap = allocbitmap(N_IMAP);
X  zmap = allocbitmap(N_ZMAP);
X  spec_imap = allocbitmap(N_IMAP);
X  spec_zmap = allocbitmap(N_ZMAP);
X  dirmap = allocbitmap(N_IMAP);
X}
X
X/* Release all the space taken by the bitmaps. */
Xvoid putbitmaps()
X{
X  freebitmap(imap);
X  freebitmap(zmap);
X  freebitmap(spec_imap);
X  freebitmap(spec_zmap);
X  freebitmap(dirmap);
X}
X
X/* `w1' and `w2' are differing words from two bitmaps that should be
X * identical.  Print what's the matter with them.
X */
Xvoid chkword(w1, w2, bit, nbit, type, n, report)
Xunsigned w1, w2;
Xchar *type;
Xbit_nr bit, nbit;
Xint *n, *report;
X{
X  for (; (w1 | w2) && bit < nbit; w1 >>= 1, w2 >>= 1, bit++)
X	if ((w1 ^ w2) & 1 && ++(*n) % MAXPRINT == 0 && *report &&
X	    (!repair || automatic || yes("stop this listing")))
X		*report = 0;
X	else if (*report)
X		if ((w1 & 1) && !(w2 & 1))
X			printf("%s %ld is missing\n", type, bit);
X		else if (!(w1 & 1) && (w2 & 1))
X			printf("%s %ld is not free\n", type, bit);
X}
X
X/* Check if the given (correct) bitmap is identical with the one that is
X * on the disk.  If not, ask if the disk should be repaired.
X */
Xvoid chkmap(cmap, dmap, bit, blkno, nblk, nbit, type)
Xunsigned *cmap, *dmap;
Xbit_nr bit, nbit;
Xblock_nr blkno;
Xint nblk;
Xchar *type;
X{
X  register unsigned *p = dmap, *q = cmap;
X  int report = 1, nerr = 0;
X
X  printf("Checking %s map\n", type);
X  loadbitmap(dmap, blkno, nblk);
X  do {
X	if (*p != *q) chkword(*p, *q, bit, nbit, type, &nerr, &report);
X	p++;
X	q++;
X  } while ((bit += 8 * sizeof(unsigned)) < nbit
X	 && bit >= 8 * sizeof(unsigned));	/* += may overflow */
X  if ((!repair || automatic) && !report) printf("etc. ");
X  if (nerr > MAXPRINT || nerr > 10) printf("%d errors found. ", nerr);
X  if (nerr != 0 && yes("install a new map")) dumpbitmap(cmap, blkno, nblk);
X  if (nerr > 0) printf("\n");
X}
X
X/* See if the inodes that aren't allocated are cleared. */
Xvoid chkilist()
X{
X  register ino_t ino = 1;
X  mode_t mode;
X
X  printf("Checking inode list\n");
X  do
X	if (!bitset(imap, (bit_nr) ino)) {
X		devread(inoaddr(ino), (char *) &mode, sizeof(mode));
X		if (mode != I_NOT_ALLOC) {
X			printf("mode inode %u not cleared", ino);
X			if (yes(". clear")) devwrite(inoaddr(ino), nullbuf,
X					 INODE_SIZE);
X		}
X	}
X  while (++ino <= sb.s_ninodes);
X  printf("\n");
X}
X
X/* Allocate an array to maintain the inode reference counts in. */
Xvoid getcount()
X{
X  count = (nlink_t *) alloc((unsigned) (sb.s_ninodes + 1), sizeof(nlink_t));
X}
X
X/* The reference count for inode `ino' is wrong.  Ask if it should be adjusted. */
Xvoid counterror(ino)
Xino_t ino;
X{
X  d_inode inode;
X
X  if (firstcnterr) {
X	printf("INODE NLINK COUNT\n");
X	firstcnterr = 0;
X  }
X  devread(inoaddr(ino), (char *) &inode, INODE_SIZE);
X  count[ino] += inode.i_nlinks;	/* it was already subtracted; add it back */
X  printf("%5u %5u %5u", ino, (unsigned) inode.i_nlinks, count[ino]);
X  if (yes(" adjust")) {
X	if ((inode.i_nlinks = count[ino]) == 0) {
X		fatal("internal error (counterror)");
X		inode.i_mode = I_NOT_ALLOC;
X		clrbit(imap, (bit_nr) ino);
X	}
X	devwrite(inoaddr(ino), (char *) &inode, INODE_SIZE);
X  }
X}
X
X/* Check if the reference count of the inodes are correct.  The array `count'
X * is maintained as follows:  an entry indexed by the inode number is
X * incremented each time a link is found; when the inode is read the link
X * count in there is substracted from the corresponding entry in `count'.
X * Thus, when the whole file system has been traversed, all the entries
X * should be zero.
X */
Xvoid chkcount()
X{
X  register ino_t ino;
X
X  for (ino = 1; ino <= sb.s_ninodes; ino++)
X	if (count[ino] != 0) counterror(ino);
X  if (!firstcnterr) printf("\n");
X}
X
X/* Deallocate the `count' array. */
Xvoid freecount()
X{
X  free((char *) count);
X}
X
X/* Print the inode permission bits given by mode and shift. */
Xvoid printperm(mode, shift, special, overlay)
Xmode_t mode;
Xint shift;
Xint special;
Xint overlay;
X{
X  if (mode >> shift & R_BIT)
X	putchar('r');
X  else
X	putchar('-');
X  if (mode >> shift & W_BIT)
X	putchar('w');
X  else
X	putchar('-');
X  if (mode & special)
X	putchar(overlay);
X  else
X	if (mode >> shift & X_BIT)
X		putchar('x');
X	else
X		putchar('-');
X}
X
X/* List the given inode. */
Xvoid list(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  if (firstlist) {
X	firstlist = 0;
X	printf(" inode permission link   size name\n");
X  }
X  printf("%6u ", ino);
X  switch (ip->i_mode & I_TYPE) {
X      case I_REGULAR:		putchar('-');	break;
X      case I_DIRECTORY:		putchar('d');	break;
X      case I_CHAR_SPECIAL:	putchar('c');	break;
X      case I_BLOCK_SPECIAL:	putchar('b');	break;
X      case I_NAMED_PIPE:	putchar('p');	break;
X#ifdef I_SYMBOLIC_LINK
X      case I_SYMBOLIC_LINK:	putchar('l');	break;
X#endif
X      default:			putchar('?');
X}
X  printperm(ip->i_mode, 6, I_SET_UID_BIT, 's');
X  printperm(ip->i_mode, 3, I_SET_GID_BIT, 's');
X  printperm(ip->i_mode, 0, STICKY_BIT, 't');
X  printf(" %3u ", ip->i_nlinks);
X  switch (ip->i_mode & I_TYPE) {
X      case I_CHAR_SPECIAL:
X      case I_BLOCK_SPECIAL:
X	printf("  %2x,%2x ", (dev_t) ip->i_zone[0] >> MAJOR & 0xFF,
X	       (dev_t) ip->i_zone[0] >> MINOR & 0xFF);
X	break;
X      default:	printf("%7ld ", ip->i_size);
X  }
X  printpath(0, 1);
X}
X
X/* Remove an entry from a directory if ok with the user.
X * Don't name the function remove() - that is owned by ANSI, and chaos results
X * when it is a macro.
X */
Xint Remove(dp)
Xdir_struct *dp;
X{
X  setbit(spec_imap, (bit_nr) dp->d_inum);
X  if (yes(". remove entry")) {
X	count[dp->d_inum]--;
X	memset((void *) dp, 0, sizeof(dir_struct));
X	return(1);
X  }
X  return(0);
X}
X
X/* Convert string so that embedded control characters are printable. */
Xvoid make_printable_name(dst, src, n)
Xregister char *dst;
Xregister char *src;
Xregister int n;
X{
X  register int c;
X
X  while (--n >= 0 && (c = *src++) != '\0') {
X	if (isprint(c) && c != '\\')
X		*dst++ = c;
X	else {
X		*dst++ = '\\';
X		switch (c) {
X		      case '\\':
X			*dst++ = '\\'; break;
X		      case '\b':
X			*dst++ = 'b'; break;
X		      case '\f':
X			*dst++ = 'f'; break;
X		      case '\n':
X			*dst++ = 'n'; break;
X		      case '\r':
X			*dst++ = 'r'; break;
X		      case '\t':
X			*dst++ = 't'; break;
X		      default:
X			*dst++ = '0' + ((c >> 6) & 03);
X			*dst++ = '0' + ((c >> 3) & 07);
X			*dst++ = '0' + (c & 07);
X		}
X	}
X  }
X  *dst = '\0';
X}
X
X/* See if the `.' or `..' entry is as expected. */
Xint chkdots(ino, pos, dp, exp)
Xino_t ino, exp;
Xoff_t pos;
Xdir_struct *dp;
X{
X  char printable_name[4 * NAME_MAX + 1];
X
X  if (dp->d_inum != exp) {
X	make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
X	printf("bad %s in ", printable_name);
X	printpath(1, 0);
X	printf("%s is linked to %u ", printable_name, dp->d_inum);
X	printf("instead of %u)", exp);
X	setbit(spec_imap, (bit_nr) ino);
X	setbit(spec_imap, (bit_nr) dp->d_inum);
X	setbit(spec_imap, (bit_nr) exp);
X	if (yes(". repair")) {
X		count[dp->d_inum]--;
X		dp->d_inum = exp;
X		count[exp]++;
X		return(0);
X	}
X  } else if (pos != (dp->d_name[1] ? DIR_ENTRY_SIZE : 0)) {
X	make_printable_name(printable_name, dp->d_name, sizeof(dp->d_name));
X	printf("warning: %s has offset %ld in ", printable_name, pos);
X	printpath(1, 0);
X	printf("%s is linked to %u)\n", printable_name, dp->d_inum);
X	setbit(spec_imap, (bit_nr) ino);
X	setbit(spec_imap, (bit_nr) dp->d_inum);
X	setbit(spec_imap, (bit_nr) exp);
X  }
X  return(1);
X}
X
X/* Check the name in a directory entry. */
Xint chkname(ino, dp)
Xino_t ino;
Xdir_struct *dp;
X{
X  register n = NAME_MAX + 1;
X  register char *p = dp->d_name;
X
X  if (*p == '\0') {
X	printf("null name found in ");
X	printpath(0, 0);
X	setbit(spec_imap, (bit_nr) ino);
X	if (Remove(dp)) return(0);
X  }
X  while (*p != '\0' && --n != 0)
X	if (*p++ == '/') {
X		printf("found a '/' in entry of directory ");
X		printpath(1, 0);
X		setbit(spec_imap, (bit_nr) ino);
X		printf("entry = '");
X		printname(dp->d_name);
X		printf("')");
X		if (Remove(dp)) return(0);
X		break;
X	}
X  return(1);
X}
X
X/* Check a directory entry.  Here the routine `descendtree' is called
X * recursively to check the file or directory pointed to by the entry.
X */
Xint chkentry(ino, pos, dp)
Xino_t ino;
Xoff_t pos;
Xdir_struct *dp;
X{
X  if (dp->d_inum < ROOT_INODE || dp->d_inum > sb.s_ninodes) {
X	printf("bad inode found in directory ");
X	printpath(1, 0);
X	printf("ino found = %u, ", dp->d_inum);
X	printf("name = '");
X	printname(dp->d_name);
X	printf("')");
X	if (yes(". remove entry")) {
X		memset((void *) dp, 0, sizeof(dir_struct));
X		return(0);
X	}
X	return(1);
X  }
X  if ((unsigned) count[dp->d_inum] == LINK_MAX) {
X	printf("too many links to ino %u\n", dp->d_inum);
X	printf("discovered at entry '");
X	printname(dp->d_name);
X	printf("' in directory ");
X	printpath(0, 1);
X	if (Remove(dp)) return(0);
X  }
X  count[dp->d_inum]++;
X  if (strcmp(dp->d_name, ".") == 0) {
X	ftop->st_presence |= DOT;
X	return(chkdots(ino, pos, dp, ino));
X  }
X  if (strcmp(dp->d_name, "..") == 0) {
X	ftop->st_presence |= DOTDOT;
X	return(chkdots(ino, pos, dp, ino == ROOT_INODE ? ino :
X			ftop->st_next->st_dir->d_inum));
X  }
X  if (!chkname(ino, dp)) return(0);
X  if (bitset(dirmap, (bit_nr) dp->d_inum)) {
X	printf("link to directory discovered in ");
X	printpath(1, 0);
X	printf("name = '");
X	printname(dp->d_name);
X	printf("', dir ino = %u)", dp->d_inum);
X	return !Remove(dp);
X  }
X  return(descendtree(dp));
X}
X
X/* Check a zone of a directory by checking all the entries in the zone.
X * The zone is split up into chunks to not allocate too much stack.
X */
Xint chkdirzone(ino, ip, pos, zno)
Xino_t ino;
Xd_inode *ip;
Xoff_t pos;
Xzone_nr zno;
X{
X  dir_struct dirblk[CDIRECT];
X  register dir_struct *dp;
X  register n = SCALE * (NR_DIR_ENTRIES / CDIRECT), dirty;
X  register long offset = zaddr(zno);
X
X  do {
X	devread(offset, (char *) dirblk, DIRCHUNK);
X	dirty = 0;
X	for (dp = dirblk; dp < &dirblk[CDIRECT]; dp++) {
X		if (ip->i_size - pos < DIR_ENTRY_SIZE) {
X			printf("bad format in directory ");
X			printpath(2, 0);
X			if (yes(". truncate")) {
X				setbit(spec_imap, (bit_nr) ino);
X				ip->i_size = pos;
X				dirty = 1;
X			} else
X				return(0);
X		}
X		if (dp->d_inum != NO_ENTRY && !chkentry(ino, pos, dp))dirty= 1;
X		if ((pos += DIR_ENTRY_SIZE) >= ip->i_size) break;
X	}
X	if (dirty) devwrite(offset, (char *) dirblk, DIRCHUNK);
X	offset += DIRCHUNK;
X  } while (--n && pos < ip->i_size);
X  return(1);
X}
X
X/* There is something wrong with the given zone.  Print some details. */
Xvoid errzone(mess, zno, level, pos)
Xchar *mess;
Xzone_nr zno;
Xint level;
Xoff_t pos;
X{
X  printf("%s zone in ", mess);
X  printpath(1, 0);
X  printf("zno = %ld, type = ", zno);
X  switch (level) {
X      case 0:	printf("DATA");	break;
X      case 1:	printf("SINGLE INDIRECT");	break;
X      case 2:	printf("DOUBLE INDIRECT");	break;
X      default:	printf("VERY INDIRECT");
X  }
X  printf(", pos = %ld)\n", pos);
X}
X
X/* Found the given zone in the given inode.  Check it, and if ok, mark it
X * in the zone bitmap.
X */
Xint markzone(zno, level, pos)
Xzone_nr zno;
Xint level;
Xoff_t pos;
X{
X  register bit_nr bit = (bit_nr) zno - FIRST + 1;
X
X  ztype[level]++;
X  if (zno < FIRST || zno >= sb.s_zones) {
X	errzone("out-of-range", zno, level, pos);
X	return(0);
X  }
X  if (bitset(zmap, bit)) {
X	setbit(spec_zmap, bit);
X	errzone("duplicate", zno, level, pos);
X	return(0);
X  }
X  nfreezone--;
X  if (bitset(spec_zmap, bit)) errzone("found", zno, level, pos);
X  setbit(zmap, bit);
X  return(1);
X}
X
X/* Check an indirect zone by checking all of its entries.
X * The zone is split up into chunks to not allocate too much stack.
X */
Xint chkindzone(ino, ip, pos, zno, level)
Xino_t ino;
Xd_inode *ip;
Xoff_t *pos;
Xzone_nr zno;
Xint level;
X{
X  zone_nr indirect[CINDIR];
X  register n = NR_INDIRECTS / CINDIR;
X  register long offset = zaddr(zno);
X
X  do {
X	devread(offset, (char *) indirect, INDCHUNK);
X	if (!chkzones(ino, ip, pos, indirect, CINDIR, level - 1)) return(0);
X	offset += INDCHUNK;
X  } while (--n && *pos < ip->i_size);
X  return(1);
X}
X
X/* Return the size of a gap in the file, represented by a null zone number
X * at some level of indirection.
X */
Xoff_t jump(level)
Xint level;
X{
X  off_t power = ZONE_SIZE;
X
X  if (level != 0) do
X		power *= NR_INDIRECTS;
X	while (--level);
X  return(power);
X}
X
X/* Check a zone, which may be either a normal data zone, a directory zone,
X * or an indirect zone.
X */
Xint zonechk(ino, ip, pos, zno, level)
Xino_t ino;
Xd_inode *ip;
Xoff_t *pos;
Xzone_nr zno;
Xint level;
X{
X  if (level == 0) {
X	if ((ip->i_mode & I_TYPE) == I_DIRECTORY &&
X	    !chkdirzone(ino, ip, *pos, zno))
X		return(0);
X	*pos += ZONE_SIZE;
X	return(1);
X  } else
X	return chkindzone(ino, ip, pos, zno, level);
X}
X
X/* Check a list of zones given by `zlist'. */
Xint chkzones(ino, ip, pos, zlist, len, level)
Xino_t ino;
Xd_inode *ip;
Xoff_t *pos;
Xzone_nr *zlist;
Xint len;
Xint level;
X{
X  register ok = 1, i;
X
X  /* The check on the position in the next loop is commented out, since FS
X   * now requires valid zone numbers in each level that is necessary and FS
X   * always deleted all the zones in the double indirect block.
X   */
X  for (i = 0; i < len /* && *pos < ip->i_size */ ; i++)
X	if (zlist[i] == NO_ZONE)
X		*pos += jump(level);
X	else if (!markzone(zlist[i], level, *pos)) {
X		*pos += jump(level);
X		ok = 0;
X	} else if (!zonechk(ino, ip, pos, zlist[i], level))
X		ok = 0;
X  return(ok);
X}
X
X/* Check a file or a directory. */
Xint chkfile(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  register ok, i, level;
X  off_t pos = 0;
X
X  ok = chkzones(ino, ip, &pos, &ip->i_zone[0], NR_DZONE_NUM, 0);
X  for (i = NR_DZONE_NUM, level = 1; i < NR_ZONE_NUMS; i++, level++)
X	ok &= chkzones(ino, ip, &pos, &ip->i_zone[i], 1, level);
X  return(ok);
X}
X
X/* Check a directory by checking the contents.  Check if . and .. are present. */
Xint chkdirectory(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  register ok;
X
X  setbit(dirmap, (bit_nr) ino);
X  if (ip->i_size > MAXDIRSIZE) {
X	printf("warning: huge directory: ");
X	printpath(2, 1);
X  }
X  ok = chkfile(ino, ip);
X  if (!(ftop->st_presence & DOT)) {
X	printf(". missing in ");
X	printpath(2, 1);
X	ok = 0;
X  }
X  if (!(ftop->st_presence & DOTDOT)) {
X	printf(".. missing in ");
X	printpath(2, 1);
X	ok = 0;
X  }
X  return(ok);
X}
X
X#ifdef I_SYMBOLIC_LINK
X
X/* Check the validity of a symbolic link. */
Xint chklink(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  int ok;
X
X  ok = chkfile(ino, ip);
X  if (ip->i_size <= 0 || ip->i_size > BLOCK_SIZE) {
X	if (ip->i_size == 0)
X		printf("empty symbolic link ");
X	else
X		printf("symbolic link too large (size %ld) ", ip->i_size);
X	printpath(2, 1);
X	ok = 0;
X  }
X  return(ok);
X}
X
X#endif
X
X/* Check the validity of a special file. */
Xint chkspecial(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  int i, ok;
X
X  ok = 1;
X  if ((dev_t) ip->i_zone[0] == NO_DEV) {
X	printf("illegal device number %ld for special file ", ip->i_zone[0]);
X	printpath(2, 1);
X	ok = 0;
X  }
X
X  /* FS will not use the remaining "zone numbers" but 1.6.11++ will panic if
X   * they are nonzero, since this should not happen.
X   */
X  for (i = 1; i < NR_ZONE_NUMS; i++)
X	if (ip->i_zone[i] != NO_ZONE) {
X		printf("nonzero zone number %ld for special file ",
X		       ip->i_zone[i]);
X		printpath(2, 1);
X		ok = 0;
X	}
X  return(ok);
X}
X
X/* Check the mode and contents of an inode. */
Xint chkmode(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  switch (ip->i_mode & I_TYPE) {
X      case I_REGULAR:
X	nregular++;
X	return chkfile(ino, ip);
X      case I_DIRECTORY:
X	ndirectory++;
X	return chkdirectory(ino, ip);
X      case I_BLOCK_SPECIAL:
X	nblkspec++;
X	return chkspecial(ino, ip);
X      case I_CHAR_SPECIAL:
X	ncharspec++;
X	return chkspecial(ino, ip);
X      case I_NAMED_PIPE:
X	npipe++;
X	return chkfile(ino, ip);
X#ifdef I_SYMBOLIC_LINK
X      case I_SYMBOLIC_LINK:
X	nsyml++;
X	return chklink(ino, ip);
X#endif
X      default:
X	nbadinode++;
X	printf("bad mode of ");
X	printpath(1, 0);
X	printf("mode = %o)", ip->i_mode);
X	return(0);
X  }
X}
X
X/* Check an inode. */
Xint chkinode(ino, ip)
Xino_t ino;
Xd_inode *ip;
X{
X  if (ino == ROOT_INODE && (ip->i_mode & I_TYPE) != I_DIRECTORY) {
X	printf("root inode is not a directory ");
X	printf("(ino = %u, mode = %o)\n", ino, ip->i_mode);
X	fatal("");
X  }
X  if (ip->i_nlinks == 0) {
X	printf("link count zero of ");
X	printpath(2, 0);
X	return(0);
X  }
X  nfreeinode--;
X  setbit(imap, (bit_nr) ino);
X  if ((unsigned) ip->i_nlinks > LINK_MAX) {
X	printf("link count too big in ");
X	printpath(1, 0);
X	printf("cnt = %u)\n", (unsigned) ip->i_nlinks);
X	count[ino] -= LINK_MAX;
X	setbit(spec_imap, (bit_nr) ino);
X  } else {
X	count[ino] -= (unsigned) ip->i_nlinks;
X  }
X  return chkmode(ino, ip);
X}
X
X/* Check the directory entry pointed to by dp, by checking the inode. */
Xint descendtree(dp)
Xdir_struct *dp;
X{
X  d_inode inode;
X  register ino_t ino = dp->d_inum;
X  register visited;
X  struct stack stk;
X
X  stk.st_dir = dp;
X  stk.st_next = ftop;
X  ftop = &stk;
X  if (bitset(spec_imap, (bit_nr) ino)) {
X	printf("found inode %u: ", ino);
X	printpath(0, 1);
X  }
X  visited = bitset(imap, (bit_nr) ino);
X  if (!visited || listing) {
X	devread(inoaddr(ino), (char *) &inode, INODE_SIZE);
X	if (listing) list(ino, &inode);
X	if (!visited && !chkinode(ino, &inode)) {
X		setbit(spec_imap, (bit_nr) ino);
X		if (yes("remove")) {
X			count[ino] += inode.i_nlinks - 1;
X			clrbit(imap, (bit_nr) ino);
X			devwrite(inoaddr(ino), nullbuf, INODE_SIZE);
X			memset((void *) dp, 0, sizeof(dir_struct));
X			ftop = ftop->st_next;
X			return(0);
X		}
X	}
X  }
X  ftop = ftop->st_next;
X  return(1);
X}
X
X/* Check the file system tree. */
Xvoid chktree()
X{
X  dir_struct dir;
X
X  nfreeinode = sb.s_ninodes;
X  nfreezone = N_DATA;
X  dir.d_inum = ROOT_INODE;
X  dir.d_name[0] = 0;
X  if (!descendtree(&dir)) fatal("bad root inode");
X  putchar('\n');
X}
X
X/* Print the totals of all the objects found. */
Xvoid printtotal()
X{
X  printf("blocksize = %5d        ", BLOCK_SIZE);
X  printf("zonesize  = %5d\n", ZONE_SIZE);
X  printf("\n");
X  pr("%6u    Regular file%s\n", nregular, "", "s");
X  pr("%6u    Director%s\n", ndirectory, "y", "ies");
X  pr("%6u    Block special file%s\n", nblkspec, "", "s");
X  pr("%6u    Character special file%s\n", ncharspec, "", "s");
X  if (nbadinode != 0) pr("%6u    Bad inode%s\n", nbadinode, "", "s");
X  pr("%6u    Free inode%s\n", nfreeinode, "", "s");
X  pr("%6u    Named pipe%s\n", npipe, "", "s");
X  pr("%6u    Symbolic link%s\n", nsyml, "", "s");
X/* Don't print some fields.
X  printf("\n");
X  pr("%6u    Data zone%s\n",		  ztype[0],	 "",   "s");
X  pr("%6u    Single indirect zone%s\n",	  ztype[1],	 "",   "s");
X  pr("%6u    Double indirect zone%s\n",	  ztype[2],	 "",   "s");
X*/
X  lpr("%6ld    Free zone%s\n", nfreezone, "", "s");
X}
X
X/* Check the device which name is given by `f'.  The inodes listed by `clist'
X * should be listed separately, and the inodes listed by `ilist' and the zones
X * listed by `zlist' should be watched for while checking the file system.
X */
X
Xvoid chkdev(f, clist, ilist, zlist)
Xchar *f, **clist, **ilist, **zlist;
X{
X  if (automatic) repair = 1;
X  device = f;
X  initvars();
X
X  devopen();
X
X  getsuper();
X  chksuper();
X
X  lsi(clist);
X
X  getbitmaps();
X  initbitmap(imap, (bit_nr) sb.s_ninodes + 1, N_IMAP);
X  initbitmap(zmap, (bit_nr) sb.s_zones - (bit_nr) FIRST + 1, N_ZMAP);
X
X  fillbitmap(spec_imap, (bit_nr) 1, (bit_nr) sb.s_ninodes + 1, ilist);
X  fillbitmap(spec_zmap, (bit_nr) FIRST, (bit_nr) sb.s_zones, zlist);
X
X  getcount();
X  chktree();
X  chkmap(zmap, spec_zmap, (bit_nr) FIRST - 1, BLK_ZMAP, N_ZMAP,
X         (bit_nr) sb.s_zones, "zone");
X  chkcount();
X  chkmap(imap, spec_imap, (bit_nr) 0, BLK_IMAP, N_IMAP,
X         (bit_nr) sb.s_ninodes + 1, "inode");
X  chkilist();
X  printtotal();
X
X  putbitmaps();
X  freecount();
X  devclose();
X
X  if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
X}
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  register char **clist = 0, **ilist = 0, **zlist = 0;
X
X  register devgiven = 0;
X  register char *arg;
X
X  if ((1 << BITSHIFT) != 8 * sizeof(int)) {
X	printf("Fsck was compiled with the wrong BITSHIFT!\n");
X	exit(1);
X  }
X
X  sync();
X  prog = *argv++;
X  while ((arg = *argv++) != 0)
X	if (arg[0] == '-' && arg[1] != 0 && arg[2] == 0) switch (arg[1]) {
X		    case 'a':	automatic ^= 1;	break;
X		    case 'c':
X			clist = getlist(&argv, "inode");
X			break;
X		    case 'i':
X			ilist = getlist(&argv, "inode");
X			break;
X		    case 'z':
X			zlist = getlist(&argv, "zone");
X			break;
X		    case 'r':	repair ^= 1;	break;
X		    case 'l':	listing ^= 1;	break;
X		    case 's':	listsuper ^= 1;	break;
X		    default:
X			printf("%s: unknown flag '%s'\n", prog, arg);
X		}
X	else {
X		chkdev(arg, clist, ilist, zlist);
X		clist = 0;
X		ilist = 0;
X		zlist = 0;
X		devgiven = 1;
X	}
X  if (!devgiven) {
X	printf("Usage: fsck [-acilrsz] file\n");
X	exit(1);
X  }
X  return(0);
X}
/
echo x - gomoku.c
sed '/^X/s///' > gomoku.c << '/'
X/* gomoku - 5 in a row game		Author: ? */
X
X/* This program plays a very old Japanese game called GO-MOKU,
X   perhaps better known as  5-in-line.   The game is played on
X   a board with 19 x 19 squares, and the object of the game is
X   to get 5 stones in a row.
X*/
X
X#include <sys/types.h>
X#include <curses.h>
X#include <ctype.h>
X#include <stdlib.h>
X#include <unistd.h>
X#include <sgtty.h>
X
X/* Size of the board */
X#define SIZE 19
X
X/* Importance of attack (1..16) */
X#define AttackFactor 4
X
X/* Value of having 0, 1,2,3,4 or 5 pieces in line */
Xint Weight[7] = {0, 0, 4, 20, 100, 500, 0};
X
X#define Null 0
X#define Horiz 1
X#define DownLeft 2
X#define DownRight 3
X#define Vert 4
X
X/* The two players */
X#define Empty 0
X#define Cross 1
X#define Nought 2
X
Xchar PieceChar[Nought + 1] = {' ', 'X', '0'};
X
Xint Board[SIZE + 1][SIZE + 1];/* The board */
Xint Player;			/* The player whose move is next */
Xint TotalLines;			/* The number of Empty lines left */
Xint GameWon;			/* Set if one of the players has won */
X
Xint Line[4][SIZE + 1][SIZE + 1][Nought + 1];
X
X/* Value of each square for each player */
Xint Value[SIZE + 1][SIZE + 1][Nought + 1];
X
Xint X, Y;			/* Move coordinates */
Xchar Command;			/* Command from keyboard */
Xint AutoPlay = FALSE;		/* The program plays against itself */
X
Xstruct sgttyb old_tty, new_tty;
X
X_PROTOTYPE(void Initialize, (void));
X_PROTOTYPE(int Abort, (char *s));
X_PROTOTYPE(void WriteLetters, (void));
X_PROTOTYPE(void WriteLine, (int j, int *s));
X_PROTOTYPE(void WriteBoard, (int N, int *Top, int *Middle, int *Bottom));
X_PROTOTYPE(void SetUpScreen, (void));
X_PROTOTYPE(void GotoSquare, (int x, int y));
X_PROTOTYPE(void PrintMove, (int Piece, int X, int Y));
X_PROTOTYPE(void ClearMove, (void));
X_PROTOTYPE(void PrintMsg, (char *Str));
X_PROTOTYPE(void ClearMsg, (void));
X_PROTOTYPE(void WriteCommand, (char *S));
X_PROTOTYPE(void ResetGame, (int FirstGame));
X_PROTOTYPE(int OpponentColor, (int Player));
X_PROTOTYPE(void BlinkRow, (int X, int Y, int Dx, int Dy, int Piece));
X_PROTOTYPE(void BlinkWinner, (int Piece, int X, int Y, int WinningLine));
X_PROTOTYPE(int Random, (int x));
X_PROTOTYPE(void Add, (int *Num));
X_PROTOTYPE(void Update, (int Lin[], int Valu[], int Opponent));
X_PROTOTYPE(void MakeMove, (int X, int Y));
X_PROTOTYPE(int GameOver, (void));
X_PROTOTYPE(void FindMove, (int *X, int *Y));
X_PROTOTYPE(char GetChar, (void));
X_PROTOTYPE(void ReadCommand, (int X, int Y, char *Command));
X_PROTOTYPE(void InterpretCommand, (int Command));
X_PROTOTYPE(void PlayerMove, (void));
X_PROTOTYPE(void ProgramMove, (void));
X_PROTOTYPE(int main, (void));
X
X/* Get the termcap entry and set terminal to raw mode. */
Xvoid Initialize()
X{
X  /* Save old terminal parameters. */
X  ioctl(0, TIOCGETP, &old_tty);
X
X  /* Set tty to CBREAK mode */
X  ioctl(0, TIOCGETP, &new_tty);
X  new_tty.sg_flags |= CBREAK;
X  new_tty.sg_flags &= ~ECHO;
X  ioctl(0, TIOCSETP, &new_tty);
X
X  srand(getpid() + 13);		/* Initialize the random seed with our pid */
X  initscr();
X  raw();
X  noecho();
X  clear();
X}
X
X/* Reset terminal and exit from the program. */
Xint Abort(s)
Xchar *s;
X{
X  move(LINES - 1, 0);
X  refresh();
X  endwin();
X  ioctl(0, TIOCSETP, &old_tty);	/* restore terminal parameters */
X  exit(0);
X}
X
X/* Set up the screen ----------------------------------------------- */
X
X/* Write the letters */
Xvoid WriteLetters()
X{
X  int i;
X
X  addch(' ');
X  addch(' ');
X  for (i = 1; i <= SIZE; i++) printw(" %c", 'A' + i - 1);
X  addch('\n');
X}
X
X/* Write one line of the board */
Xvoid WriteLine(j, s)
Xint j;
Xint *s;
X{
X  int i;
X
X  printw("%2d ", j);
X  addch(s[0]);
X  for (i = 2; i <= SIZE - 1; i++) {
X	addch(s[1]);
X	addch(s[2]);
X  }
X  addch(s[1]);
X  addch(s[3]);
X  printw(" %-2d\n", j);
X}
X
X/* Print the Empty board and the border */
Xvoid WriteBoard(N, Top, Middle, Bottom)
Xint N;
Xint *Top, *Middle, *Bottom;
X{
X  int j;
X
X  move(1, 0);
X  WriteLetters();
X  WriteLine(N, Top);
X  for (j = N - 1; j >= 2; j--) WriteLine(j, Middle);
X  WriteLine(1, Bottom);
X  WriteLetters();
X}
X
X/* Sets up the screen with an Empty board */
Xvoid SetUpScreen()
X{
X  int top[4], middle[4], bottom[4];
X
X  top[0] = ACS_ULCORNER;
X  top[1] = ACS_HLINE;
X  top[2] = ACS_TTEE;
X  top[3] = ACS_URCORNER;
X
X  middle[0] = ACS_LTEE;
X  middle[1] = ACS_HLINE;
X  middle[2] = ACS_PLUS;
X  middle[3] = ACS_RTEE;
X
X  bottom[0] = ACS_LLCORNER;
X  bottom[1] = ACS_HLINE;
X  bottom[2] = ACS_BTEE;
X  bottom[3] = ACS_LRCORNER;
X
X  WriteBoard(SIZE, top, middle, bottom);
X}
X
X/* Show moves ----------------------------------------------- */
X
Xvoid GotoSquare(x, y)
Xint x, y;
X{
X  move(SIZE + 2 - y, 1 + x * 2);
X}
X
X/* Prints a move */
Xvoid PrintMove(Piece, X, Y)
Xint Piece;
Xint X, Y;
X{
X  move(22, 49);
X  printw("%c %c %d", PieceChar[Piece], 'A' + X - 1, Y);
X  clrtoeol();
X  GotoSquare(X, Y);
X  addch(PieceChar[Piece]);
X  GotoSquare(X, Y);
X  refresh();
X}
X
X/* Clears the line where a move is displayed */
Xvoid ClearMove()
X{
X  move(22, 49);
X  clrtoeol();
X}
X
X/* Message handling ---------------------------------------------- */
X
X/* Prints a message */
Xvoid PrintMsg(Str)
Xchar *Str;
X{
X  mvprintw(23, 1, "%s", Str);
X}
X
X/* Clears the message about the winner */
Xvoid ClearMsg()
X{
X  move(23, 1);
X  clrtoeol();
X}
X
X/* Highlights the first letter of S */
Xvoid WriteCommand(S)
Xchar *S;
X{
X  standout();
X  addch(*S);
X  standend();
X  printw("%s", S + 1);
X}
X
X/* Display the board ----------------------------------------------- */
X
X/* Resets global variables to start a new game */
Xvoid ResetGame(FirstGame)
Xint FirstGame;
X{
X  int I, J;
X  int C, D;
X
X  SetUpScreen();
X  if (FirstGame) {
X	move(1, 49);
X	addstr("G O M O K U");
X	move(3, 49);
X	WriteCommand("Newgame    ");
X	WriteCommand("Quit ");
X	move(5, 49);
X	WriteCommand("Auto");
X	move(7, 49);
X	WriteCommand("Play");
X	move(9, 49);
X	WriteCommand("Hint");
X	move(14, 60);
X	WriteCommand("Left, ");
X	WriteCommand("Right, ");
X	move(16, 60);
X	WriteCommand("Up, ");
X	WriteCommand("Down");
X	move(18, 60);
X	standout();
X	addstr("SPACE");
X	move(20, 49);
X	WriteCommand(" NOTE: Use Num Lock & arrows");
X	standend();
X	mvaddstr(14, 49, "7  8  9");
X	mvaddch(15, 52, ACS_UARROW);
X	mvaddch(16, 49, '4');
X	addch(ACS_LARROW);
X	mvaddch(16, 54, ACS_RARROW);
X	addch('6');
X	mvaddch(17, 52, ACS_DARROW);
X	mvaddstr(18, 49, "1  2  3");
X	FirstGame = FALSE;
X  } else {
X	ClearMsg();
X	ClearMove();
X  }
X
X  /* Clear tables */
X  for (I = 1; I <= SIZE; I++) for (J = 1; J <= SIZE; J++) {
X		Board[I][J] = Empty;
X		for (C = Cross; C <= Nought; C++) {
X			Value[I][J][C] = 0;
X			for (D = 0; D <= 3; D++) Line[D][I][J][C] = 0;
X		}
X	}
X
X  /* Cross starts */
X  Player = Cross;
X  /* Total number of lines */
X  TotalLines = 2 * 2 * (SIZE * (SIZE - 4) + (SIZE - 4) * (SIZE - 4));
X  GameWon = FALSE;
X}
X
Xint OpponentColor(Player)
Xint Player;
X{
X  if (Player == Cross)
X	return Nought;
X  else
X	return Cross;
X}
X
X/* Blink the row of 5 stones */
Xvoid BlinkRow(X, Y, Dx, Dy, Piece)
Xint X, Y, Dx, Dy, Piece;
X{
X  int I;
X
X  attron(A_BLINK);
X  for (I = 1; I <= 5; I++) {
X	GotoSquare(X, Y);
X	addch(PieceChar[Piece]);
X	X = X - Dx;
X	Y = Y - Dy;
X  }
X  attroff(A_BLINK);
X}
X
X/* Prints the 5 winning stones in blinking color */
Xvoid BlinkWinner(Piece, X, Y, WinningLine)
Xint Piece, X, Y, WinningLine;
X{
X  /* Used to store the position of the winning move */
X  int XHold, YHold;
X  /* Change in X and Y */
X  int Dx, Dy;
X
X  /* Display winning move */
X  PrintMove(Piece, X, Y);
X  /* Preserve winning position */
X  XHold = X;
X  YHold = Y;
X  switch (WinningLine) {
X      case Horiz:
X	{
X		Dx = 1;
X		Dy = 0;
X		break;
X	}
X
X      case DownLeft:
X	{
X		Dx = 1;
X		Dy = 1;
X		break;
X	}
X
X      case Vert:
X	{
X		Dx = 0;
X		Dy = 1;
X		break;
X	}
X
X      case DownRight:
X	{
X		Dx = -1;
X		Dy = 1;
X		break;
X	}
X  }
X
X  /* Go to topmost, leftmost */
X  while (Board[X + Dx][Y + Dy] != Empty && Board[X + Dx][Y + Dy] == Piece) {
X	X = X + Dx;
X	Y = Y + Dy;
X  }
X  BlinkRow(X, Y, Dx, Dy, Piece);
X  /* Restore winning position */
X  X = XHold;
X  Y = YHold;
X  /* Go back to winning square */
X  GotoSquare(X, Y);
X}
X
X/* Functions for playing a game -------------------------------- */
X
Xint Random(x)
Xint x;
X{
X  return((rand() / 19) % x);
X}
X
X/* Adds one to the number of pieces in a line */
Xvoid Add(Num)
Xint *Num;
X{
X  /* Adds one to the number.     */
X  *Num = *Num + 1;
X  /* If it is the first piece in the line, then the opponent cannot use
X   * it any more.  */
X  if (*Num == 1) TotalLines = TotalLines - 1;
X  /* The game is won if there are 5 in line. */
X  if (*Num == 5) GameWon = TRUE;
X}
X
X/* Updates the value of a square for each player, taking into
X   account that player has placed an extra piece in the square.
X   The value of a square in a usable line is Weight[Lin[Player]+1]
X   where Lin[Player] is the number of pieces already placed
Xin the line */
Xvoid Update(Lin, Valu, Opponent)
Xint Lin[];
Xint Valu[];
Xint Opponent;
X{
X  /* If the opponent has no pieces in the line, then simply update the
X   * value for player */
X  if (Lin[Opponent] == 0)
X	Valu[Player] += Weight[Lin[Player] + 1] - Weight[Lin[Player]];
X  else
X	/* If it is the first piece in the line, then the line is
X	 * spoiled for the opponent */
X  if (Lin[Player] == 1) Valu[Opponent] -= Weight[Lin[Opponent] + 1];
X}
X
X/* Performs the move X,Y for player, and updates the global variables
X(Board, Line, Value, Player, GameWon, TotalLines and the screen) */
Xvoid MakeMove(X, Y)
Xint X, Y;
X{
X  int Opponent;
X  int X1, Y1;
X  int K, L, WinningLine;
X
X  WinningLine = Null;
X  Opponent = OpponentColor(Player);
X  GameWon = FALSE;
X
X  /* Each square of the board is part of 20 different lines. The adds
X   * one to the number of pieces in each of these lines. Then it
X   * updates the value for each of the 5 squares in each of the 20
X   * lines. Finally Board is updated, and the move is printed on the
X   * screen. */
X
X  /* Horizontal lines, from left to right */
X  for (K = 0; K <= 4; K++) {
X	X1 = X - K;		/* Calculate starting point */
X	Y1 = Y;
X	if ((1 <= X1) && (X1 <= SIZE - 4)) {	/* Check starting point */
X		Add(&Line[0][X1][Y1][Player]);	/* Add one to line */
X		if (GameWon && (WinningLine == Null))	/* Save winning line */
X			WinningLine = Horiz;
X		for (L = 0; L <= 4; L++)	/* Update value for the
X						 * 5 squares in the line */
X			Update(Line[0][X1][Y1], Value[X1 + L][Y1], Opponent);
X	}
X  }
X
X  for (K = 0; K <= 4; K++) {	/* Diagonal lines, from lower left to
X				 * upper right */
X	X1 = X - K;
X	Y1 = Y - K;
X	if ((1 <= X1) && (X1 <= SIZE - 4) &&
X	    (1 <= Y1) && (Y1 <= SIZE - 4)) {
X		Add(&Line[1][X1][Y1][Player]);
X		if (GameWon && (WinningLine == Null))	/* Save winning line */
X			WinningLine = DownLeft;
X		for (L = 0; L <= 4; L++)
X			Update(Line[1][X1][Y1], Value[X1 + L][Y1 + L], Opponent);
X	}
X  }				/* for */
X
X  for (K = 0; K <= 4; K++) {	/* Diagonal lines, down right to upper left */
X	X1 = X + K;
X	Y1 = Y - K;
X	if ((5 <= X1) && (X1 <= SIZE) &&
X	    (1 <= Y1) && (Y1 <= SIZE - 4)) {
X		Add(&Line[3][X1][Y1][Player]);
X		if (GameWon && (WinningLine == Null))	/* Save winning line */
X			WinningLine = DownRight;
X		for (L = 0; L <= 4; L++)
X			Update(Line[3][X1][Y1], Value[X1 - L][Y1 + L], Opponent);
X	}
X  }				/* for */
X
X  for (K = 0; K <= 4; K++) {	/* Vertical lines, from down to up */
X	X1 = X;
X	Y1 = Y - K;
X	if ((1 <= Y1) && (Y1 <= SIZE - 4)) {
X		Add(&Line[2][X1][Y1][Player]);
X		if (GameWon && (WinningLine == Null))	/* Save winning line */
X			WinningLine = Vert;
X		for (L = 0; L <= 4; L++)
X			Update(Line[2][X1][Y1], Value[X1][Y1 + L], Opponent);
X	}
X  }
X
X  Board[X][Y] = Player;		/* Place piece in board */
X  if (GameWon)
X	BlinkWinner(Player, X, Y, WinningLine);
X  else
X	PrintMove(Player, X, Y);/* Print move on screen */
X  Player = Opponent;		/* The opponent is next to move */
X}
X
Xint GameOver()
X/* A game is over if one of the players have
Xwon, or if there are no more Empty lines */
X{
X  return(GameWon || (TotalLines <= 0));
X}
X
X/* Finds a move X,Y for player, simply by picking the one with the
Xhighest value */
Xvoid FindMove(X, Y)
Xint *X, *Y;
X{
X  int Opponent;
X  int I, J;
X  int Max, Valu;
X
X  Opponent = OpponentColor(Player);
X  Max = -10000;
X  /* If no square has a high value then pick the one in the middle */
X  *X = (SIZE + 1) / 2;
X  *Y = (SIZE + 1) / 2;
X  if (Board[*X][*Y] == Empty) Max = 4;
X  /* The evaluation for a square is simply the value of the square for
X   * the player (attack points) plus the value for the opponent
X   * (defense points). Attack is more important than defense, since it
X   * is better to get 5 in line yourself than to prevent the op- ponent
X   * from getting it. */
X
X  /* For all Empty squares */
X  for (I = 1; I <= SIZE; I++) for (J = 1; J <= SIZE; J++)
X		if (Board[I][J] == Empty) {
X			/* Calculate evaluation */
X			Valu = Value[I][J][Player] * (16 + AttackFactor) / 16 + Value[I][J][Opponent] + Random(4);
X			/* Pick move with highest value */
X			if (Valu > Max) {
X				*X = I;
X				*Y = J;
X				Max = Valu;
X			}
X		}
X}
X
Xchar GetChar()
X/* Get a character from the keyboard */
X{
X  int c;
X
X  c = getch();
X  if (c < 0) abort();
X  if (islower(c))
X	return toupper(c);
X  else
X	return c;
X}
X
X/* Reads in a valid command character */
Xvoid ReadCommand(X, Y, Command)
Xint X, Y;
Xchar *Command;
X{
X  int ValidCommand;
X
X  do {
X	ValidCommand = TRUE;
X	GotoSquare(X, Y);	/* Goto square */
X	refresh();
X	*Command = GetChar();	/* Read from keyboard */
X	switch (*Command) {
X	    case '\n':		/* '\n' or space means place a */
X	    case ' ':
X		*Command = 'E';
X		break;		/* stone at the cursor position  */
X
X	    case 'L':
X	    case 'R':
X	    case 'U':
X	    case '7':
X	    case '9':
X	    case '1':
X	    case '3':
X	    case 'N':
X	    case 'Q':
X	    case 'A':
X	    case 'P':
X	    case 'H':
X		break;
X
X	    case '8':	*Command = 'U';	break;
X	    case '2':	*Command = 'D';	break;
X	    case '4':	*Command = 'L';	break;
X	    case '6':	*Command = 'R';	break;
X	    default:
X		{
X			if (GameOver())
X				*Command = 'P';
X			else
X				ValidCommand = FALSE;
X			break;
X		}
X	}
X  } while (!ValidCommand);
X}
X
Xvoid InterpretCommand(Command)
Xchar Command;
X{
X  int Temp;
X
X  switch (Command) {
X      case 'N':{		/* Start new game */
X		ResetGame(FALSE);	/* ResetGame but only redraw
X					 * the board */
X		X = (SIZE + 1) / 2;
X		Y = X;
X		break;
X	}
X      case 'H':
X	FindMove(&X, &Y);
X	break;			/* Give the user a hint */
X      case 'L':
X	X = (X + SIZE - 2) % SIZE + 1;
X	break;			/* Left  */
X      case 'R':
X	X = X % SIZE + 1;
X	break;			/* Right */
X      case 'D':
X	Y = (Y + SIZE - 2) % SIZE + 1;
X	break;			/* Down  */
X      case 'U':
X	Y = Y % SIZE + 1;
X	break;			/* Up    */
X      case '7':{
X		if ((X == 1) || (Y == SIZE)) {	/* Move diagonally    *//* t
X						 * owards upper left */
X			Temp = X;
X			X = Y;
X			Y = Temp;
X		} else {
X			X = X - 1;
X			Y = Y + 1;
X		}
X		break;
X	}
X      case '9':{		/* Move diagonally    */
X		if (X == SIZE) {/* toward upper right */
X			X = (SIZE - Y) + 1;
X			Y = 1;
X		} else if (Y == SIZE) {
X			Y = (SIZE - X) + 1;
X			X = 1;
X		} else {
X			X = X + 1;
X			Y = Y + 1;
X		}
X		break;
X	}
X      case '1':{		/* Move diagonally   */
X		if (Y == 1) {	/* toward lower left */
X			Y = (SIZE - X) + 1;
X			X = SIZE;
X		} else if (X == 1) {
X			X = (SIZE - Y) + 1;
X			Y = SIZE;
X		} else {
X			X = X - 1;
X			Y = Y - 1;
X		}
X		break;
X	}
X      case '3':{		/* Move diagonally    */
X		if ((X == SIZE) || (Y == 1)) {	/* toward lower right */
X			Temp = X;
X			X = Y;
X			Y = Temp;
X		} else {
X			X = X + 1;
X			Y = Y - 1;
X		}
X		break;
X	}
X      case 'A':
X	AutoPlay = TRUE;
X	break;			/* Auto play mode */
X  }				/* case */
X}				/* InterpretCommand */
X
Xvoid PlayerMove()
X/* Enter and make a move */
X{
X  if (Board[X][Y] == Empty) {
X	MakeMove(X, Y);
X	if (GameWon) PrintMsg("Congratulations, You won!");
X	Command = 'P';
X  }
X  refresh();
X}				/* PlayerMove */
X
Xvoid ProgramMove()
X/* Find and perform programs move */
X{
X  do {
X	if (GameOver()) {
X		AutoPlay = FALSE;
X		if ((Command != 'Q') && (!GameWon)) PrintMsg("Tie game!");
X	} else {
X		FindMove(&X, &Y);
X		MakeMove(X, Y);
X		if (GameWon) PrintMsg("I won!");
X	}
X	refresh();
X  } while (AutoPlay);
X}
X
Xint main()
X{
X  Initialize();
X  ResetGame(TRUE);		/* ResetGame and draw the entire screen */
X  refresh();
X  X = (SIZE + 1) / 2;		/* Set starting position to */
X  Y = X;			/* the middle of the board  */
X  do {
X	ReadCommand(X, Y, &Command);
X	if (GameOver())
X		if (Command != 'Q') Command = 'N';
X	InterpretCommand(Command);
X	if (Command == 'E') PlayerMove();
X	if (Command == 'P' || Command == 'A') ProgramMove();
X  } while (Command != 'Q');
X  Abort("Good bye!");
X  return(0);
X}
/
echo x - hyphenate.c
sed '/^X/s///' > hyphenate.c << '/'
X/* Hyphenate English text for mroff	Author: Alan I. Holub */
X
X/* This filter reads English text and ouputs it with \% at reasonable
X * places to hyphenate words.  It is normally used as an mroff preprocessor.
X * The original algorithm is due to Donald Knuth.  The program itself
X * came with Michael Haardt's mroff package.
X */
X
X#include <ctype.h>
X#include <string.h>
X#include <stdlib.h>
X#include <stdio.h>
X
Xtypedef enum { FALSE, TRUE} bool;
X
X#define HYPHEN          0x80
X#define HYPHENATE(c)    ( (c) |=  HYPHEN )
X#define UNHYPHENATE(c)  ( (c) &= ~HYPHEN )
X#define HAS_HYPHEN(c)   ( (c) &   HYPHEN )
X
Xchar **States;
Xextern char *Suffixes[];
Xextern char *Prefixes[];
X
X#define ER(p,end) ((* p & 0x7f)=='e' && (*(p+1) & 0x7f) == 'r' && (p+1) == end)
X
X#define CH ('z' + 1 )		/* {   0x7b  \173    */
X#define GH ('z' + 2 )		/* |   0x7c  \174    */
X#define PH ('z' + 3 )		/* }   0x7d  \175    */
X#define SH ('z' + 4 )		/* ~   0x7e  \176    */
X#define TH ('z' + 5 )		/* DEL   0x7f  \177    */
X
X/* a b c d e f g h i j k l m n o p q r s t u v w x y z */
Xchar vt[] = {1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0};
X
X#define isvowel(c)  ( islower((c) & 0x7f)  &&  vt[ ((c) & 0x7f) - 'a'] )
X#define isconsonant(c)  ((c) && !isvowel(c))
X
Xtypedef struct
X{
X  char arg, type;
X  void *variable;
X} ARG;
X
X
X_PROTOTYPE(char *suffix, (char *beg, char *end ));
X_PROTOTYPE(char *prefix, (char *beg, char *end ));
X_PROTOTYPE(char nextch, (char **pp, char *endp ));
X_PROTOTYPE(int isweird, (int x, int y, char *p ));
X_PROTOTYPE(void consonants, (char *beg, char *end ));
X_PROTOTYPE(int hyphen, (char *beg, char *end ));
X_PROTOTYPE(int next, (int cur_state, int cur_char ));
X_PROTOTYPE(bool process_word, (char *w ));
X_PROTOTYPE(int wcmp, (const void *word2, const void *tabp1 ));
X_PROTOTYPE(int exception, (char *word, char *end ));
X_PROTOTYPE(char *setarg, (ARG *argp, char *linep ));
X_PROTOTYPE(ARG *findarg, (int c, ARG *tabp, int tabsize ));
X_PROTOTYPE(int argparse, (int argc, char **argv, ARG *tabp, int tabsize ));
X_PROTOTYPE(void fail, (char *word ));
X_PROTOTYPE(void outtext, (int c ));
X_PROTOTYPE(void outspec, (int c ));
X_PROTOTYPE(int nextchar, (void));
X_PROTOTYPE(int escapeseq, (void));
X_PROTOTYPE(void nonletter, (void));
X_PROTOTYPE(int special, (void));
X_PROTOTYPE(int letter, (void));
X_PROTOTYPE(void word1, (void));
X_PROTOTYPE(void words, (void));
X_PROTOTYPE(int macro, (void));
X_PROTOTYPE(void line, (void));
X_PROTOTYPE(void text, (FILE *fd ));
X_PROTOTYPE(int main, (int argc, char *argv []));
X
X
Xchar *suffix(beg, end)
Xchar *beg, *end;
X{
X  register char *p, c, c2;
X  register int state;
X  register unsigned int times;
X
X  state = 1;
X  times = 0;
X  States = Suffixes;
X
X  for (p = end; p >= beg;) {
X	state = next(state, c = *p-- & 0x7f);
X
X	if (!('a' <= c && c <= 'z'))	/* Worter mit Grossbuch-  */
X		return end;	/* staben werden nicht   */
X
X	if (state == 0) {
X		if (times == 0)
X			p = end;	/* entferne endendes e,d */
X		else if (times == 1)	/* entf. endendes ed, de */
X			p = end - 1;	/* ee oder dd            */
X		else
X			return end;
X
X		times++;
X	}
X	switch (state) {
X	    case 86:
X		c = *p & 0x7f;
X		c2 = *(p - 1) & 0x7f;
X
X		if (p - beg < 3) return end;	/* FAIL */
X		else if ((c == c2) && (!isvowel(c))
X			 && (c != 'f') && (c != 's')
X			 && (c != 'l') && (c != 'z')) {
X			--p;
X		} else if (c == 'l' && strchr("bcdfghkptz", c2)) {
X			p -= (c2 == 'k' && (*(p - 2) & 0x7f) == 'c')
X				? 1 : 2;
X		}
X
X	    case 87:
X		HYPHENATE(*(p + 1));
X		return p;
X
X	    case 88:
X		HYPHENATE(*(p + 2));
X		return(p + 1);
X
X	    case 89:
X		HYPHENATE(*(p + 5));
X		HYPHENATE(*(p + 1));
X		return p;
X
X	    case 82:
X		p++;		/* p += 3 */
X	    case 81:
X		p++;		/* p += 2 */
X	    case 80:
X		p++;		/* P += 1 */
X	    case 83:
X		end = p;
X		HYPHENATE(*(p + 1));
X		state = 1;
X		break;
X
X	    case 84:		/* Fehl-Status */
X		return end;
X	}
X  }
X
X  return end;
X}
Xchar *prefix(beg, end)
Xchar *beg, *end;
X{
X
X  register char *p, c;
X  register int state;
X
X  state = 1;
X  States = Prefixes;
X
X  for (p = beg; p < end;) {
X	switch (state = next(state, c = *p++ & 0x7f)) {
X	    case 82:
X		HYPHENATE(*p);
X		HYPHENATE(*(p - 1));
X		return p;
X	    case 83:
X		HYPHENATE(*p);
X		HYPHENATE(*(p - 2));
X		return p;
X	    case 84:
X		HYPHENATE(*p);
X		HYPHENATE(*(p - 3));
X		return p;
X
X	    case 81:
X		--p;
X	    case 87:
X		HYPHENATE(*p);
X		return p;
X
X	    case 85:
X		--p;
X	    case 86:
X		beg = p;
X		state = 1;
X	    case 69:	HYPHENATE(*p);	break;
X
X	    case 70:	HYPHENATE(*(p - 1));	break;
X	    case 71:
X	    case 72:
X	    case 73:
X	    case 74:
X	    case 75:
X	    case 76:
X	    case 77:
X	    case 78:	case 79:	break;
X	}
X  }
X
X  return beg;
X}
X
Xchar *vccv_except[] =
X{
X  /* A  */ "",
X  /* B  */ "lr",
X  /* C  */ "lr",
X  /* D  */ "gr",
X  /* E  */ "",
X  /* F  */ "lr",
X  /* G  */ "lr",
X  /* H  */ "",
X  /* I  */ "",
X  /* J  */ "",
X  /* K  */ "n",
X  /* L  */ "kq",
X  /* M  */ "",
X  /* N  */ "{kx",		/* CH, k, x */
X  /* O  */ "",
X  /* P  */ "lr",
X  /* Q  */ "",
X  /* R  */ "k",
X  /* S  */ "pq",
X  /* T  */ "{r",		/* CH, r    */
X  /* U  */ "",
X  /* V  */ "",
X  /* W  */ "hlnr",
X  /* X  */ "",
X  /* Y  */ "",
X  /* Z  */ "",
X  /* CH */ "lr",
X  /* GH */ "t",
X  /* PH */ "r",
X  /* SH */ "",
X  /* TH */ "r"
X};
Xchar nextch(pp, endp)
Xchar **pp, *endp;
X{
X
X  register char rval, *p;
X
X  if ((p = *pp) > endp) return(char) 0;
X
X  rval = *p++ & 0x7f;
X
X  if ((*p & 0x7f) == 'h') {
X	switch ((int) rval) {
X	    case 't':
X		rval = TH;
X		p++;
X		break;
X	    case 's':
X		rval = SH;
X		p++;
X		break;
X	    case 'p':
X		rval = PH;
X		p++;
X		break;
X	    case 'c':
X		rval = CH;
X		p++;
X		break;
X	    case 'g':
X		rval = GH;
X		p++;
X		break;
X	}
X  }
X  *pp = p;
X  return rval;
X}
Xint isweird(x, y, p)
Xchar x, y, *p;
X{
X
X  register unsigned int c1, c2, c3;
X
X  c1 = *p++ & 0x7f;
X  c2 = *p++ & 0x7f;
X  c3 = *p & 0x7f;
X
X  x &= 0x7f;
X  y &= 0x7f;
X
X  return(
X	(
X	 (c1 == 'e' && c2 == 'r')
X	 || (c1 == 'a' && c2 == 'g' && c3 == 'e')
X	 || (c1 == 'e' && c2 == 's' && c3 == 't')
X	 )
X	&&
X	((x == 'f' && y == 't')
X	 || (x == 'l' && y == 'd')
X	 || (x == 'm' && y == 'p')
X	 || (x == 's' && y == 't')
X	 || (x == 'n' && strchr("dgst", (int) (y & 0x7f)))
X	 || (x == 'r' && strchr("gmnt", (int) (y & 0x7f)))
X	 )
X	);
X}
Xvoid consonants(beg, end)
Xchar *beg, *end;
X{
X
X  register char c1, c2, *cp;
X  register char *p;
X
X  while (1) {
Xstate1:
X
X	do {
X		c2 = nextch(&beg, end);
X	} while (isconsonant(c2));
X
X	do {
X		for (c1 = c2; isvowel(c1);) {
X			cp = beg;
X			c1 = nextch(&beg, end);
X		}
X
X
X		if (c1 == 'q' && *beg == 'u') {	/* Vqu */
X			HYPHENATE(*cp);	/* V-qu */
X			nextch(&beg, end);	/* uberspringe u */
X			goto state1;
X		}
X		cp = beg;
X		c2 = nextch(&beg, end);
X
X	} while (isvowel(c2));
X
X	if (!c1 || !c2) break;
X
X	if (c1 == 'c' && c2 == 'k') {	/* Vck  */
X		if (*beg) HYPHENATE(*beg);	/* Vck- */
X	} else if (c1 == c2) {	/* ller(s) */
X		if ((c1 != 'l' && c1 != 's') ||
X		    (isvowel(*beg) && !ER(beg, end)))
X			HYPHENATE(*cp);
X	} else if (isvowel(*beg)) {	/* VCCV */
X		if (!isweird(c1, c2, beg)) {
X			if (!((p = vccv_except[(int) c1 - 'a'])
X			      && strchr(p, (int) c2)))
X				HYPHENATE(*cp);
X		}
X	}
X  }
X
X  UNHYPHENATE(*end);
X}
X
Xint hyphen(beg, end)
Xchar *beg, *end;
X{
X
X  register char *prefixp, *suffixp;
X  int c;
X
X  if (end - beg <= 4) return 0;
X
X  for (prefixp = beg; prefixp <= end; prefixp++) {
X	if (HAS_HYPHEN(*prefixp)) return 1;
X
X	if (!islower(*prefixp)) return 0;
X  }
X
X  if (exception(beg, end)) return 1;
X
X  suffixp = suffix(beg, end);	/* Trenne und entferne alle     */
X  /* Endungen (Suffixe)           */
X  if (suffixp == end) {
X	c = *end & 0x7f;
X
X	if (c == 's' || c == 'e') suffixp = end - 1;
X
X	else if ((*(end - 1) & 0x7f) == 'e' && c == 'd')
X		suffixp = end - 2;
X  }
X  prefixp = prefix(beg, suffixp);	/* Trenne und entferne alle */
X  /* Vorsilben (Prafixe)      */
X
X  if ((suffixp - prefixp) >= 3) {
X	/* Die Anwendung der Konsonantenpaar-Regel findet nur auf
X	 * Worter mit mindestens 4 Buchsten statt (nachdem Vor- und
X	 * Nachsilben entfernt wurden) */
X
X	consonants(prefixp, suffixp);
X  }
X  return 1;
X}
Xint next(cur_state, cur_char)
Xchar cur_char;
Xint cur_state;
X{
X  char *p = States[cur_state];
X  int rval, i, c;
X
X  c = cur_char & 0x7f;
X
X
X  if (!*p)
X	rval = (int) (p[(c - 'a') + 1]);
X  else {
X	for (rval = 0, i = *p++; --i >= 0; p += 2)
X		if (c == p[0]) {
X			rval = p[1];
X			break;
X		}
X  }
X
X
X  return(rval);
X}
X
X#define S(x)  char x[]
X
XS(s0) =
X{0,84,84,84,1,1,84,84,84,84,84,84,84,84,84,84,84,84,84,1,84,84,84,84,84,84,84};
X
XS(s1) = {0,0,0,2,0,7,0,21,0,0,0,0,23,0,30,0,0,0,33,38,45,0,0,0,0,49,0};
XS(s2) ={  1, 'i', 3};
XS(s3) ={  1, 'p', 4};
XS(s4) ={  1, 'o', 5};
XS(s5) ={  1, 'c', 6};
XS(s6) ={  1, 's', 87};
XS(s7) ={0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,4,0,10,0,16,0,15,0,0,0,19};
XS(s8) ={  1, 'b', 9};
XS(s9) ={  1, 'a', 55};
XS(s10) ={  2, 'e', 11, 'u', 14};
XS(s11) ={  1, 'h', 12};
XS(s12) ={  1, 'p', 6};
XS(s13) ={  2, 'n', 81, 'r', 81};
XS(s14) ={  1, 't', 87};
XS(s15) ={  1, 'i', 14};
XS(s16) ={  1, 'a', 17};
XS(s17) ={  2, 'c', 18, 'l', 18};
XS(s18) ={0,88,0,0,0,88,0,0,0,88,0,0,0,0,0,88,0,0,0,0,0,88,0,0,0,88,0};
XS(s19) ={  1, 'i', 20};
XS(s20) ={  1, 'l', 80};
XS(s21) ={  1, 'n', 22};
XS(s22) ={  1, 'i', 86};
XS(s23) ={  2, 'a', 25, 'u', 24};
XS(s24) ={  1, 'f', 83};
XS(s25) ={0,0,0,87,0,0,0,0,0,26,0,0,0,0,27,0,0,0,0,0,87,0,0,0,0,0,0};
XS(s26) ={  2, 't', 87, 'c', 87};
XS(s27) ={  1, 'o', 28};
XS(s28) ={  1, 'i', 29};
XS(s29) ={  1, 't', 89};
XS(s30) ={  1, 'o', 31};
XS(s31) ={  1, 'i', 32};
XS(s32) ={  2, 't', 87, 'c', 6};
XS(s33) ={  1, 'e', 34};
XS(s34) ={  1, 'h', 35};
XS(s35) ={  1, 'p', 36};
XS(s36) ={  1, 'a', 37};
XS(s37) ={  1, 'r', 87};
XS(s38) ={  2, 's', 39, 'u', 41};
XS(s39) ={  1, 'e', 40};
XS(s40) ={  2, 'l', 83, 'n', 83};
XS(s41) ={  1, 'o', 42};
XS(s42) ={  1, 'i', 43};
XS(s43) ={  1, 'c', 44};
XS(s44)={0,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,87,
X							88,88,88,88,88,88,88};
XS(s45) ={  1, 'n', 46};
XS(s46) ={  1, 'e', 47};
XS(s47)={0,0,0,0,87,0,0,0,0,48,0,0,0,83,0,0,0,0,0,0,0,0,0,0,0,0,0};
XS(s48) ={  1, 'c', 87};
XS(s49)={0,0,0,0,0,0,0,50,35,0,0,0,83,0,0,0,0,0,51,0,0,0,0,0,0,0,0};
XS(s50) ={  1, 'o', 87};
XS(s51) ={  1, 'a', 52};
XS(s52) ={  1, 'n', 53};
XS(s53)={0,88,88,88,88,81,88,88,88,88,88,88,88,88,88,54,88,88,
X						88,88,88,88,88,88,88,88,88};
XS(s54) ={  1, 'i', 82};
XS(s55)={0,0,0,0,0,80,0,0,80,80,0,80,80,0,0,80,0,0,0,0,13,80,80,80,80,80,0};
X
X
Xchar *Suffixes[] =
X{
X s0, s1, s2, s3, s4, s5, s6, s7, s8, s9,
X s10, s11, s12, s13, s14, s15, s16, s17, s18, s19,
X s20, s21, s22, s23, s24, s25, s26, s27, s28, s29,
X s30, s31, s32, s33, s34, s35, s36, s37, s38, s39,
X s40, s41, s42, s43, s44, s45, s46, s47, s48, s49,
X s50, s51, s52, s53, s54, s55
X};
XS(p0) =
X{
X  1, 0, 0
X};
X
XS(p1) =
X{
X  0, 0, 2, 4, 6, 9, 0, 0, 13, 22, 0, 0, 26, 29, 39, 41, 45, 50, 0, 53, 57, 64,
X	0, 0, 0, 0, 0
X};
X
XS(p2) =
X{
X  1, 'e', 3
X};
X
XS(p3) =
X{
X  0, 0, 0, 81, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0
X};
X
XS(p4) =
X{
X  1, 'o', 5
X};
X
XS(p5) =
X{
X  2, 'm', 87, 'n', 87
X};
X
XS(p6) =
X{
X  1, 'i', 7
X};
X
XS(p7) =
X{
X  1, 's', 8
X};
X
XS(p8) =
X{
X  0, 85, 85, 85, 85, 85, 85, 85, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
X	85, 85, 85, 85, 0, 85
X};
X
XS(p9) =
X{
X  2, 'q', 10, 'x', 87
X};
X
XS(p10) =
X{
X  1, 'u', 11
X};
X
XS(p11) =
X{
X  1, 'i', 12
X};
X
XS(p12) =
X{
X  0, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
X	81, 0, 81, 81, 81, 81
X};
X
XS(p13) =
X{
X  0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0
X};
X
XS(p14) =
X{
X  1, 'n', 15
X};
X
XS(p15) =
X{
X  1, 'd', 87
X};
X
XS(p16) =
X{
X  1, 'r', 17
X};
X
XS(p17) =
X{
X  1, 's', 18
X};
X
XS(p18) =
X{
X  1, 'e', 87
X};
X
XS(p19) =
X{
X  1, 'p', 20
X};
X
XS(p20) =
X{
X  1, 'e', 21
X};
X
XS(p21) =
X{
X  1, 'r', 84
X};
X
XS(p22) =
X{
X  2, 'n', 69, 'm', 86
X};
X
XS(p23) =
X{
X  0, 81, 0, 0, 0, 0, 81, 81, 0, 0, 0, 0, 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
X};
X
XS(p24) =
X{
X  2, 'e', 21, 'r', 25
X};
X
XS(p25) =
X{
X  1, 'o', 87
X};
X
XS(p26) =
X{
X  1, 'e', 27
X};
X
XS(p27) =
X{
X  1, 'x', 35
X};
X
XS(p28) =
X{
X  1, 'i', 87
X};
X
XS(p29) =
X{
X  0, 30, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0
X};
X
XS(p30) =
X{
X  0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 35, 0, 0
X};
X
XS(p31) =
X{
X  1, 'r', 32
X};
X
XS(p32) =
X{
X  1, 'o', 83
X};
X
XS(p33) =
X{
X  1, 'h', 34
X};
X
XS(p34) =
X{
X  1, 'e', 82
X};
X
XS(p35) =
X{
X  1, 'i', 82
X};
X
XS(p36) =
X{
X  1, 'n', 35
X};
X
XS(p37) =
X{
X  1, 'l', 38
X};
X
XS(p38) =
X{
X  1, 't', 65
X};
X
XS(p39) =
X{
X  1, 'o', 40
X};
X
XS(p40) =
X{
X  1, 'n', 86
X};
X
XS(p41) =
X{
X  2, 'u', 42, 'v', 43
X};
X
XS(p42) =
X{
X  1, 't', 87
X};
X
XS(p43) =
X{
X  1, 'e', 44
X};
X
XS(p44) =
X{
X  1, 'r', 86
X};
X
XS(p45) =
X{
X  1, 's', 46
X};
X
XS(p46) =
X{
X  1, 'e', 47
X};
X
XS(p47) =
X{
X  1, 'u', 48
X};
X
XS(p48) =
X{
X  1, 'd', 49
X};
X
XS(p49) =
X{
X  1, 'o', 83
X};
X
XS(p50) =
X{
X  1, 'u', 51
X};
X
XS(p51) =
X{
X  1, 'a', 52
X};
X
XS(p52) =
X{
X  1, 'd', 87
X};
X
XS(p53) =
X{
X  0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0
X};
X
XS(p54) =
X{
X  1, 'm', 28
X};
X
XS(p55) =
X{
X  1, 'm', 18
X};
X
XS(p56) =
X{
X  2, 'b', 87, 'p', 20
X};
X
XS(p57) =
X{
X  2, 'h', 58, 'r', 61
X};
X
XS(p58) =
X{
X  1, 'e', 59
X};
X
XS(p59) =
X{
X  1, 'r', 60
X};
X
XS(p60) =
X{
X  1, 'e', 87
X};
X
XS(p61) =
X{
X  2, 'a', 62, 'i', 68
X};
X
XS(p62) =
X{
X  1, 'n', 63
X};
X
XS(p63) =
X{
X  1, 's', 23
X};
X
XS(p64) =
X{
X  1, 'n', 66
X};
X
XS(p65) =
X{
X  1, 'i', 83
X};
X
XS(p66) =
X{
X  0, 85, 85, 85, 70, 85, 85, 85, 85, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85,
X	85, 85, 85, 85, 85, 85, 85, 85
X};
X
XS(p67) =
X{
X  1, 'r', 87
X};
X
XS(p68) =
X{
X  0, 81, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0
X};
X
XS(p69) =
X{
X  0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
X	85, 24, 85, 85, 85, 85, 85, 85
X};
X
XS(p70) =
X{
X  1, 'e', 67
X};
X
Xchar *Prefixes[] =
X{
X p0, p1, p2, p3, p4, p5, p6, p7, p8, p9,
X p10, p11, p12, p13, p14, p15, p16, p17, p18, p19,
X p20, p21, p22, p23, p24, p25, p26, p27, p28, p29,
X p30, p31, p32, p33, p34, p35, p36, p37, p38, p39,
X p40, p41, p42, p43, p44, p45, p46, p47, p48, p49,
X p50, p51, p52, p53, p54, p55, p56, p57, p58, p59,
X p60, p61, p62, p63, p64, p65, p66, p67, p68, p69,
X p70
X};
X
Xbool process_word(w)
Xchar *w;
X{
X  char word[80], *s = word;
X
X  hyphen(w, w + strlen(w) - 1);
X  strcpy(word, w);
X  while (*s) {
X	if (HAS_HYPHEN(*s)) {
X		*w++ = '\\';
X		*w++ = '%';
X	}
X	*w++ = UNHYPHENATE(*s++);
X  }
X  *w++ = '\0';
X  return TRUE;
X}
X
X
Xchar *Hyexcept[] =
X{
X "ab-sorb-ent", "ac-cept-able", "ac-ceptor",
X "ac-cord-ance", "ac-count-ant", "ac-know-ledge",
X "adapt-able", "adapt-er", "af-firm-ative",
X "al-go-rithm", "an-nouncer", "ant-acid",
X "ant-eater", "ant-hill", "an-tiq-uity",
X "any-thing", "apart-heid", "arch-an-gel",
X "arch-ery", "ar-mi-stice", "art-ist",
X "askance", "astig-ma-tism", "astir",
X "astonish-ment", "at-mos-phere", "bal-ding",
X "bar-on-ess", "beach-comber", "beck-on",
X "bes-tial", "be-tween", "bib-li-og-raphy",
X "bind-ery", "bi-no-mial", "blast-off",
X "board-er", "bomb-er", "bouncer",
X "bound-ary", "buff-er", "bull-ish",
X "buzz-er", "by-stand-er", "candle-stick",
X "carb-on", "cast-away", "cast-off",
X "cat-ion", "cav-ern-ous", "cen-ter",
X "change-over", "child-ish", "chordal",
X "civ-i-lize", "class-ify", "class-room",
X "climb-er", "clinch-er",
X "coars-en", "cognac",
X "cole-slaw", "com-a-tose", "com-bat-ive",
X "come-back", "co-me-dian", "com-men-da-tory",
X "comp-troller", "com-put-abil-ity", "con-de-scend",
X "cone-flower", "con-form-ity", "con-sult-ant",
X "con-test-ant", "con-trol-lable", "co-nun-drum",
X "con-vert-ible", "co-star", "count-ess",
X "court-house", "court-yard", "cre-scendo",
X "crest-fallen", "cross-over", "crypt-analysis",
X "crys-tal-lize", "curl-i-cue", "damp-en",
X "damp-est", "dar-ling", "debt-or",
X "dec-la-ra-tion", "de-cre-scendo", "de-duct-ible",
X "de-form-ity", "de-gree", "de-pend-able",
X "de-pend-ent", "de-scend-ent", "de-scent",
X "de-test-able", "di-gest-ible", "dis-cern-ible",
X "dis-miss-al", "dis-till-ery", "dump-ling",
X "earth-en-ware", "east-ern", "egg-head",
X "egg-nog", "eld-est", "else-where",
X "eq-uable", "equipped", "err-ing",
X "es-tab-lish", "eu-logy", "eve-ning",
X "every-thing", "ex-ac-ti-tude", "ex-ist-ence",
X "ex-pend-able", "ex-press-ible", "fall-out",
X "false-hood", "far-thing", "fencer",
X "fiend-ish", "for-eign-er", "fore-short-en",
X "fore-stall", "found-ling", "gen-er-ator",
X "gold-en", "handle-bar", "hang-out",
X "hang-over", "hap-hazard", "ha-rangue",
X "hard-en", "hard-ened", "hard-est",
X "harp-ist", "haz-ard-ous", "heart-ache",
X "heart-ily", "hence-forth", "her-bal",
X "hogs-head", "hold-out", "hold-over",
X "hold-up",
X "idler", "im-mo-bi-lize",
X "im-pass-able", "im-per-turb-able", "inch-worm",
X "in-clem-ent", "in-con-test-able", "in-de-pend-ent",
X "in-di-gest-ible", "ineq-uity", "in-ex-acti-tude",
X "in-ex-haust-ible", "in-form-ant", "iniq-uity",
X "ink-blot", "ink-ling", "inn-keeper",
X "in-sa-tiable", "in-te-rior", "in-ter-rupt-ible",
X "ir-re-vers-ible", "jeop-ard-ize", "kib-itzer",
X "land-owner", "launch-er", "left-ist",
X "left-over", "less-en", "life-style",
X "lift-off", "lime-stone", "li-on-ess",
X "liq-uefy", "liq-uid", "liq-ui-date",
X "liq-ui-da-tion", "liq-uor", "live-stock",
X "lull-aby", "lunch-eon", "lus-cious",
X "main-spring", "mast-head", "me-ringue",
X "me-ta-bo-lize", "met-al", "mile-stone",
X "mince-meat", "min-is-ter", "min-is-try",
X "mo-bi-lize", "mod-ern-ize", "mo-nop-o-lize",
X "morgue", "needle-work", "neg-li-gible",
X "ne-go-tiable", "nerv-ous", "nest-ling",
X "non-con-form-ist", "none-the-less", "non-ex-ist-ent",
X "non-metal", "north-east", "north-ern",
X "nurse-maid", "nurs-ery", "ob-serv-able",
X "ob-server", "off-beat", "off-hand",
X "off-print", "off-shoot", "off-shore",
X "off-spring", "orange-ade", "out-land-ish",
X "pal-ate", "pass-able", "ped-a-gogy",
X "pent-house", "per-cent-age", "pe-ri-odic",
X "per-sist-ent", "pet-al", "pho-to-stat",
X "play-thing", "pleb-i-scite", "plumb-er",
X "poly-no-mial", "port-hole", "post-al",
X "post-hu-mous", "pre-dict-able", "pre-req-ui-site",
X "pre-school", "pre-serv-ative", "pre-vious",
X "priest-hood", "prob-abil-ity", "prob-able",
X "pro-ce-dure", "pro-gram", "pro-gram-mer",
X "pro-grams", "psalm-ist", "pub-li-ca-tion",
X "pub-lish", "qua-drille", "ranch-er",
X "rattle-snake", "re-corder", "re-hears-al",
X "rent-al", "re-place-ment", "rep-re-sentative",
X "req-ui-si-tion", "re-scind", "re-search-er",
X "re-solv-able", "re-spect-able", "re-start-ed",
X "re-state-ment", "re-store", "re-vers-ible",
X "re-volv-er", "roll-away", "round-about",
X "sap-ling", "sea-scape", "self-ish",
X "sell-out", "send-off", "sense-less",
X "serv-er", "serv-ice-able", "sharpen",
X "shoe-string", "short-en", "shy-ster",
X "sib-ling", "side-step", "side-swipe",
X "si-lencer",
X "smoke-stack",
X "snake-skin", "so-ciable", "soft-hearted",
X "solv-able", "som-er-sault", "some-thing",
X "sta-bi-lize", "stand-ard-ize", "stand-out",
X "star-ling", "stat-ure", "ster-ling",
X "stew-ard-ess", "stiff-en", "sub-se-quence",
X "sug-gest-ible", "su-pe-rior", "surf-er",
X "tan-ta-lize", "thermo-stat", "tongue",
X "torque", "toss-up", "trench-ant",
X "turn-about", "turn-over", "turn-table",
X "ubiq-ui-tous", "una-nim-ity", "u-nan-i-mous",
X "un-civ-i-lized", "un-class-ified", "un-con-trollable",
X "unc-tuous", "un-der-stand-able", "un-err-ing",
X "un-gov-ern-able", "un-pre-dict-able", "un-search-able",
X "un-so-ciable", "un-solv-able", "up-swing",
X "venge-ance", "vict-ual", "vignette",
X "volt-age", "wall-eye", "waste-bas-ket",
X "waste-land", "watt-meter", "weak-ling",
X "west-ern-ize", "when-ever", "whisk-er",
X "wors-en", "yard-age", "year-ling"
X};
X
X#define TABSIZE ( sizeof( Hyexcept ) / sizeof(char *) )
X
Xint wcmp(word2, tabp1)
X_CONST void *word2;
X_CONST void *tabp1;
X{
X  /* Zur Behandlung des Plurals modifiziert am 17.7.87. Die Funktion
X   * liefert TRUE, falls das Wort passt, jedoch auf ein s oder es endet. */
X
X  char *word = (char *) word2;
X  char **tabp = (char **) tabp1;
X  register char *p = *tabp;
X
X  while (*word && *p) {
X	if (*p == '-') p++;
X
X	if (*word != *p) break;
X
X	word++;
X	p++;
X  }
X
X  if (!*p && (word[0] == 's' ||
X	    (word[0] == 'e' && word[1] == 's')))
X	return 0;
X
X  return(*word - *p);
X}
X
Xint exception(word, end)
Xchar *word, *end;
X{
X  /* Durchsucht die Ausnahmeliste und liefert einen Zeiger auf den
X   * Eintrag, falls es einen gibt, Null, falls nicht. */
X
X  char **pp, *p;
X  char oend;
X  int rval = 0;
X
X  oend = *++end;
X  *end = 0;
X
X  pp = (char **) bsearch(word, Hyexcept, TABSIZE, sizeof(char *),  wcmp);
X
X  if (pp) {
X	for (p = *pp; *p; word++, p++) {
X		if (*p == '-') {
X			HYPHENATE(*word);
X			p++;
X		}
X	}
X
X	rval = 1;
X  }
X  *end = oend;
X  return rval;
X}
X
Xchar linebuf[512], *s;
Xbool font4 = FALSE, only_font4 = FALSE, usage = FALSE;
X
X#define INT_ARG 0
X#define BOOL_ARG 1
X#define CHAR_ARG 2
X#define STRING_ARG 3
X
Xchar *setarg( argp, linep ) ARG *argp; char *linep;
X/* set an argument.  argp points to the entry in the argument table, which
X * fits to *linep.  returns linep which points after the processed argument.
X */
X{
X  char *not_s;			/* too many variables named s, s1, ... */
X
X  ++linep;
X
X  switch( argp->type )
X  {
X    case INT_ARG:
X	*(int*)argp->variable=atoi(linep);
X	while (*linep) linep++;
X	break;
X
X    case BOOL_ARG: 
X	*(int*)argp->variable = 1; break;
X
X    case CHAR_ARG: 
X	 *(char*)argp->variable = *linep++; break;
X
X    case STRING_ARG:
X	not_s = (char*) argp->variable;
X	while (*linep) *not_s++ = *linep++;
X	*not_s='\0';
X	break;
X  }
X  return(linep);
X}
X
XARG *findarg(c, tabp, tabsize) 
Xchar c; ARG *tabp; 
Xint tabsize;
X{
X  for (; --tabsize >= 0 ; tabp++ )
X  if (tabp->arg == c ) return tabp;
X
X  return NULL;
X}
X
Xint argparse(argc,argv,tabp,tabsize)
Xint argc; char **argv; 
XARG *tabp; 
Xint tabsize;
X{
X  int nargc;
X  char **nargv, *p;
X  ARG   *argp;
X
X  nargc = 1 ;
X  for(nargv = ++argv ; --argc > 0 ; argv++ )
X  {
X    if (**argv=='-' && (argp = findarg(*(p=argv[0]+1), tabp, tabsize)))
X      do 
X        if (*(p=setarg(argp,p))) argp=findarg(*p,tabp,tabsize);
X      while (*p);
X    else
X    {
X      *nargv++ = *argv ;
X      nargc++;
X    }
X  }
X  return nargc ;
X}
X
X
Xvoid fail(word)
Xchar *word;
X{
X  fprintf(stderr, "Can't process '%s'\nLine: %s\n", word, linebuf);
X}
X
Xchar transbuf[512], *t = transbuf;
X
Xvoid outtext(c)
Xchar c;
X{
X  *t++ = c;
X}
X
Xvoid outspec(c)
Xchar c;
X{
X  if (t != transbuf) {
X	*t++ = '\0';
X	if (only_font4 && !font4)
X		printf("%s", transbuf);
X	else if (process_word(transbuf))
X		printf("%s", transbuf);
X	t = transbuf;
X  }
X  putchar(c);
X}
X
Xint nextchar()
X{
X  if (*s == '\0') return 0;
X  s++;
X  return 1;
X}
X
X/* I don't echo the backslash, because special did it when it failed to match
X   the special rule.  Not the best way, but who cares.
X*/
Xint escapeseq()
X{
X  if (*s != '\\') return 0;
X  nextchar();
X  switch (*s) {
X      case '*':
X      case 'n':
X	{
X		outspec(*s);
X		nextchar();
X		if (*s == '(') {
X			outspec('(');
X			nextchar();
X			outspec(*s);
X			nextchar();
X		}
X		outspec(*s);
X		nextchar();
X		break;
X	}
X      default:
X	outspec(*s);
X	nextchar();
X  }
X  return 1;
X}
X
Xvoid nonletter()
X{
X  if (!escapeseq()) {
X	outspec(*s);
X	nextchar();
X  }
X}
X
X/* This rule is context-sensitive, because not all special characters are
X * accepted as a letter, see the return codes.
X */
Xint special()
X{
X  char *olds;
X
X  if (*s != '\\') return 0;
X  olds = s;
X  nextchar();
X  switch (*s) {
X      case '%':
X	outspec('\\');
X	outspec('%');
X	nextchar();
X	return 1;
X      case 'z':
X	outspec('\\');
X	outspec('z');
X	nextchar();
X	return 1;
X      case 'f':			/* font ::= 'f' anychar */
X	{
X		outspec('\\');
X		outspec('f');
X		nextchar();
X		font4 = (*s == '4');
X		outspec(*s);
X		nextchar();
X		return 1;
X	}
X
X      case 's':			/* size ::= [ '+' | '-' ] { digit } */
X	{
X		outspec('\\');
X		outspec('s');
X		nextchar();
X		if (*s == '-' || *s == '+') nextchar();
X		while (*s >= '0' && *s <= '9') nextchar();
X		return 1;
X	}
X
X      case '(':
X	{
X		outspec('\\');
X		outspec('(');
X		nextchar();
X		outspec(*s);
X		nextchar();
X		return 2;
X	}
X
X      default:
X	outspec('\\');
X	s = olds;
X	return 0;
X  }
X}
X
Xint letter()
X{
X  int x;
X
X  x = special();
X  if (x) return 1;
X  if (x == 0)
X	if ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z')) {
X		outtext(*s);
X		nextchar();
X		return 1;
X	}
X  return 0;
X}
X
Xvoid word1()
X{
X  if (letter()) {
X	while (letter());
X  }
X}
X
Xvoid words()
X{
X  while (*s) {
X	word1();
X	if (*s) nonletter();
X  }
X}
X
X/* Arguments not implemented yet */
Xint macro()
X{
X  if (*s == '.') {
X	printf("%s", s);
X	return 1;
X  } else
X	return 0;
X}
X
Xvoid line()
X{
X  if (!macro()) words();
X}
X
Xvoid text(fd)
XFILE *fd;
X{
X  int l;
X
X  while (fgets(linebuf, sizeof(linebuf), fd)) {
X	if ((l = strlen(linebuf)) != 0) linebuf[l - 1] = '\0';
X	s = linebuf;
X	line();
X	outspec('\n');
X  }
X}
X
X#define argnum 2
X
XARG argtab[argnum] =
X{
X '?', BOOL_ARG, (void *) &usage,
X '4', BOOL_ARG, (void *) &only_font4
X};
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  FILE *in;
X
X  argc = argparse(argc, argv, argtab, argnum);
X  if (usage) {
X	fprintf(stderr, "Usage: %s {-4} {file}\n", argv[0]);
X	exit(0);
X  }
X  if (argc == 2) {
X	if ((in = fopen(argv[1], "r")) == NULL) {
X		fprintf(stderr, "%s: unvalid argument\n", argv[0]);
X		exit(1);
X	}
X  } else
X	in = stdin;
X  text(in);
X  if (in != stdin) fclose(in);
X  return 0;
X}
/
echo x - join.c
sed '/^X/s///' > join.c << '/'
X/* join - relation data base operator	Author:  Saeko Hirabayashi */
X
X/* Written by Saeko Hirabayashi, 1989.
X * 1992-01-28 Modified by Kouichi Hirabayashi to add some POSIX1003.2 options.
X *
X * This a free program.
X */
X
X#include <string.h>
X#include <stdio.h>
X
X#define MAXFLD	200		/* maximum # of fields to accept */
X
X_PROTOTYPE(long ftell, (FILE * fp));
X_PROTOTYPE(void main, (int argc, char **argv));
X_PROTOTYPE(void error, (char *s, char *t));
X_PROTOTYPE(void usage, (void));
X_PROTOTYPE(void match, (void));
X_PROTOTYPE(void f1_only, (void));
X_PROTOTYPE(void f2_only, (void));
X_PROTOTYPE(void output, (int flag));
X_PROTOTYPE(void outfld, (int file));
X_PROTOTYPE(void outputf, (int flag));
X_PROTOTYPE(int compare, (void));
X_PROTOTYPE(int get1, (void));
X_PROTOTYPE(int get2, (int back));
X_PROTOTYPE(int getrec, (int file));
X_PROTOTYPE(int split, (int file));
X_PROTOTYPE(int atoi, (char *str));
X_PROTOTYPE(int exit, (int val));
X_PROTOTYPE(FILE * efopen, (char *file, char *mode));
X_PROTOTYPE(void (*outfun), (int file));	/* output func: output() or outputf()*/
X
X#define F1	1
X#define F2	2
X#define SEP	(sep ? sep : ' ')
X
XFILE *fp[2];			/* file pointer for file1 and file2 */
Xlong head;			/* head of the current (same)key group of the
X				 * file2 */
X
Xchar buf[2][BUFSIZ];		/* input buffer for file1 and file2 */
Xchar *fld[2][MAXFLD];		/* field vector for file1 and file2 */
Xint nfld[2];			/* # of fields for file1 and file2 */
X
Xint kpos[2];			/* key field position for file1 and file2
X				 * (from 0) */
Xchar oldkey[BUFSIZ];		/* previous key of the file1 */
X
Xstruct {			/* output list by -o option */
X  int o_file;			/* file #: 0 or 1 */
X  int o_field;			/* field #: 0, 1, 2, .. */
X} olist[MAXFLD];
Xint nout;			/* # of output filed */
X
Xint aflag;			/* n for '-an': F1 or F2 or both */
Xint vflag;			/* n for '-vn': F1 or F2 or both */
Xchar *es;			/* s for '-e s' */
Xchar sep;			/* c for -tc: filed separator */
Xchar *cmd;			/* name of this program */
X
Xvoid main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  register char *s;
X  int c, i, j;
X
X  cmd = argv[0];
X  outfun = output;		/* default output form */
X
X  while (--argc > 0 && (*++argv)[0] == '-' && (*argv)[1]) {
X	/* "-" is a file name (stdin) */
X	s = argv[0] + 1;
X	if ((c = *s) == '-' && !s[1]) {
X		++argv;
X		--argc;
X		break;		/* -- */
X	}
X	if (*++s == '\0') {
X		s = *++argv;
X		--argc;
X	}
X	switch (c) {
X	    case 'a':		/* add unpairable line to output */
X		vflag = 0;
X		switch (*s) {
X		    case '1':	aflag |= F1;	break;
X		    case '2':	aflag |= F2;	break;
X		    default:	aflag |= (F1 | F2);	break;
X		}
X		break;
X
X	    case 'e':		/* replace empty field by es */
X		es = s;
X		break;
X
X	    case 'j':		/* key field (obsolute) */
X		c = *s++;
X		if (*s == '\0') {
X			s = *++argv;
X			--argc;
X		}
X
X	    case '1':		/* key field of file1 */
X	    case '2':		/* key field of file2 */
X		i = atoi(s) - 1;
X
X		switch (c) {
X		    case '1':	kpos[0] = i;	break;
X		    case '2':	kpos[1] = i;	break;
X	            default:	kpos[0] = kpos[1] = i;
X				break;
X		}
X		break;
X
X	    case 'o':		/* specify output format */
X		do {
X			i = j = 0;
X			sscanf(s, "%d.%d", &i, &j);
X			if (i < 1 || j < 1 || i > 2) usage();
X			olist[nout].o_file = i - 1;
X			olist[nout].o_field = j - 1;
X			nout++;
X			if ((s = strchr(s, ',')) != (char *) 0)
X				s++;
X			else {
X				s = *++argv;
X				--argc;
X			}
X		} while (argc > 2 && *s != '-');
X		++argc;
X		--argv;		/* compensation */
X		outfun = outputf;
X		break;
X
X	    case 't':		/* tab char */
X		sep = *s;
X		break;
X
X	    case 'v':		/* output unpairable line only */
X		aflag = 0;
X		switch (*s) {
X		    case '1':	vflag |= F1;	break;
X		    case '2':	vflag |= F2;	break;
X		    default:	vflag |= (F1 | F2);	break;
X		}
X		break;
X
X	    default:	usage();
X	}
X  }
X  if (argc != 2) usage();
X
X  fp[0] = strcmp(argv[0], "-") ? efopen(argv[0], "r") : stdin;
X  fp[1] = efopen(argv[1], "r");
X
X  nfld[0] = get1();		/* read file1 */
X  nfld[1] = get2(0);		/* read file2 */
X
X  while (nfld[0] || nfld[1]) {
X	if ((i = compare()) == 0)
X		match();
X	else if (i < 0)
X		f1_only();
X	else
X		f2_only();
X  }
X  fflush(stdout);
X
X  exit(0);
X}
X
Xvoid usage()
X{
X  fprintf(stderr,
X    "Usage: %s [-an|-vn] [-e str] [-o list] [-tc] [-1 f] [-2 f] file1 file2\n",
X    cmd);
X  exit(1);
X}
X
Xint compare()
X{				/* compare key field */
X  register int r;
X
X  if (nfld[1] == 0)		/* file2 EOF */
X	r = -1;
X  else if (nfld[0] == 0)	/* file1 EOF */
X	r = 1;
X  else {
X	if (nfld[0] <= kpos[0])
X		error("missing key field in file1", (char *) 0);
X	if (nfld[1] <= kpos[1])
X		error("missing key field in file2", (char *) 0);
X
X	r = strcmp(fld[0][kpos[0]], fld[1][kpos[1]]);
X  }
X  return r;
X}
X
Xvoid match()
X{
X  long p;
X
X  if (!vflag) (*outfun) (F1 | F2);
X
X  p = ftell(fp[1]);
X  nfld[1] = get2(0);		/* check key order */
X  if (nfld[1] == 0 || strcmp(fld[0][kpos[0]], fld[1][kpos[1]])) {
X	nfld[0] = get1();
X	if (strcmp(fld[0][kpos[0]], oldkey) == 0) {
X		fseek(fp[1], head, 0);	/* re-do from head */
X		nfld[1] = get2(1);	/* don't check key order */
X	} else
X		head = p;	/* mark here */
X  }
X}
X
Xvoid f1_only()
X{
X  if ((aflag & F1) || (vflag & F1)) (*outfun) (F1);
X  nfld[0] = get1();
X}
X
Xvoid f2_only()
X{
X  if ((aflag & F2) || (vflag & F2)) (*outfun) (F2);
X  head = ftell(fp[1]);		/* mark */
X  nfld[1] = get2(0);		/* check key order */
X}
X
Xvoid output(f)
X{				/* default output form */
X  if (f & F1)
X	fputs(fld[0][kpos[0]], stdout);
X  else
X	fputs(fld[1][kpos[1]], stdout);
X  if (f & F1) outfld(0);
X  if (f & F2) outfld(1);
X  fputc('\n', stdout);
X}
X
Xvoid outfld(file)
X{				/* output all fields except key_field */
X  register int i;
X  int k, n;
X
X  k = kpos[file];
X  n = nfld[file];
X  for (i = 0; i < n; i++)
X	if (i != k) {
X		fputc(SEP, stdout);
X		fputs(fld[file][i], stdout);
X	}
X}
X
Xvoid outputf(f)
X{				/* output by '-o list' */
X  int i, j, k;
X  register char *s;
X
X  for (i = k = 0; i < nout; i++) {
X	j = olist[i].o_file;
X	if ((f & (j + 1)) && (olist[i].o_field < nfld[j]))
X		s = fld[j][olist[i].o_field];
X	else
X		s = es;
X	if (s) {
X		if (k++) fputc(SEP, stdout);
X		fputs(s, stdout);
X	}
X  }
X  fputc('\n', stdout);
X}
X
Xint get1()
X{				/* read file1 */
X  int r;
X  static char oldkey1[BUFSIZ];
X
X  strcpy(oldkey, fld[0][kpos[0]]);	/* save previous key for control */
X  r = getrec(0);
X
X  if (r && strcmp(oldkey1, fld[0][kpos[0]]) > 0)
X	error("file1 is not sorted", (char *) 0);
X  strcpy(oldkey1, fld[0][kpos[0]]);	/* save previous key for sort check */
X
X  return r;
X}
X
Xint get2(back)
X{				/* read file2 */
X  static char oldkey2[BUFSIZ];
X  int r;
X
X  r = getrec(1);
X
X  if (!back && r && strcmp(oldkey2, fld[1][kpos[1]]) > 0)
X	error("file2 is not sorted", (char *) 0);
X  strcpy(oldkey2, fld[1][kpos[1]]);	/* save previous key for sort check */
X
X  return r;
X}
X
Xint getrec(file)
X{				/* read one line to split it */
X  if (fgets(buf[file], BUFSIZ, fp[file]) == (char *) 0)
X	*buf[file] = '\0';
X  else if (*buf[file] == '\n' || *buf[file] == '\r')
X	error("null line in file%s", file ? "1" : "0");
X
X  return split(file);
X}
X
Xint split(file)
X{				/* setup fields */
X  register int n;
X  register char *s, *t;
X
X  for (n = 0, s = buf[file]; *s && *s != '\n' && *s != '\r';) {
X	if (sep) {
X		for (t = s; *s && *s != sep && *s != '\n' && *s != '\r'; s++);
X	} else {
X		while (*s == ' ' || *s == '\t')
X			s++;	/* skip leading white space */
X		for (t = s; *s && *s != ' ' && *s != '\t'
X		     && *s != '\n' && *s != '\r'; s++);
X		/* We will treat trailing white space as NULL field */
X	}
X	if (*s) *s++ = '\0';
X	fld[file][n++] = t;
X	if (n == MAXFLD) error("too many filed in file%s", file ? "1" : "0");
X  }
X  fld[file][n] = (char *) 0;
X
X  return n;
X}
X
XFILE *efopen(file, mode)
Xchar *file, *mode;
X{
X  FILE *fp;
X
X  if ((fp = fopen(file, mode)) == (FILE *) 0) error("can't open %s", file);
X
X  return fp;
X}
X
Xvoid error(s, t)
Xchar *s, *t;
X{
X  fprintf(stderr, "%s: ", cmd);
X  fprintf(stderr, s, t);
X  fprintf(stderr, "\n");
X
X  exit(1);
X}
/
echo x - life.c
sed '/^X/s///' > life.c << '/'
X
X/* life - Conway's game of life		Author: Jim King */
X
X/* clife.c - curses life simulator.  Translated from Pascal to C implementing
X *           curses Oct 1988 by pulsar@lsrhs, not jek5036@ritvax.isc.rit.edu
X *           life needs about 18kb stack space on MINIX.
X *
X * Flags:	-d  draw your own screen using arrows and space bar
X *		-p  print statistics on the bottom line during the game
X */
X
X#include <sys/types.h>
X#include <signal.h>
X#include <time.h>
X#include <curses.h>
X#include <stdlib.h>
X#include <sgtty.h>
X#include <unistd.h>
X#include <stdio.h>
X
X/* A value of -1 will make it go forever */
X/* A value of 0 will make it exit immediately */
X#define	REPSTOP		-1	/* number of repetitions before stop */
X
Xint present[23][80];		/* screen 1 cycle ago */
Xint past[23][80];		/* screen this cycle */
Xint total;			/* total # of changes */
Xint icnt;			/* counter to check for repetition */
Xint maxrow = 22;		/* some defines to represent the screen */
Xint maxcol = 79;
Xint minrow = 0;
Xint mincol = 0; 
Xint pri = 0;			/* flag for printing stats on bottom line */
Xint draw = 0;			/* flag for drawing your own screen */
Xint i, j, k;			/* loop counters */
Xint cycle;			/* current cycle # */
Xint changes;			/* # of changes this cycle (live + die) */
Xint die;			/* number of deaths this cycle */
Xint live;			/* number of births this cycle */
X
XWINDOW *mns;			/* Main Screen */
XWINDOW *info;			/* Bottom line */
X
Xstruct sgttyb old_tty, new_tty;
X
X_PROTOTYPE(void cleanup, (int s));
X_PROTOTYPE(void initialize, (void));
X_PROTOTYPE(void makscr, (void));
X_PROTOTYPE(void update, (void));
X_PROTOTYPE(void print, (void));
X_PROTOTYPE(int main, (int ac, char *av[]));
X
X/* Cleanup - cleanup then exit */
Xvoid cleanup(s)
Xint s;
X{
X  move(23, 0);			/* go to bottom of screen */
X  refresh();			/* update cursor */
X
X  endwin();			/* shutdown curses */
X  ioctl(0, TIOCSETP, &old_tty);	/* restore terminal parameters */
X  exit(1);			/* exit */
X}
X
X/* Initialize - init windows, variables, and signals */
X
Xvoid initialize()
X{
X
X  /* Save old terminal parameters. */
X  ioctl(0, TIOCGETP, &old_tty);
X
X  /* Set tty to CBREAK mode */
X  ioctl(0, TIOCGETP, &new_tty);
X  new_tty.sg_flags |= CBREAK;
X  new_tty.sg_flags &= ~ECHO;
X  ioctl(0, TIOCSETP, &new_tty);
X
X  srand(getpid());		/* init random seed */
X  initscr();			/* init curses */
X  noecho();
X  curs_set(0);
X  signal(SIGINT, cleanup);	/* catch ^C */
X  mns = newwin(maxrow, maxcol, 0, 0);	/* new window */
X  scrollok(mns, FALSE);
X  info = newwin(1, 80, 23, 0);
X  scrollok(info, FALSE);
X  wclear(mns);
X  wclear(info);
X  wmove(info, 0, 0);
X  wrefresh(info);
X  if (!draw) {			/* if no draw, make random pattern */
X	for (j = 0; j < maxrow; j++) {
X		for (k = 0; k < maxcol; k++) {
X			present[j][k] = rand() % 2;
X			if (present[j][k] == 1) changes++, live++;
X		}
X	}
X  }
X}
X
X/* Makscr - make your own screen using arrow keys and space bar */
Xvoid makscr()
X{
X  int curx, cury;		/* current point on screen */
X  char c;			/* input char */
X
X  wclear(info);
X  wmove(info, 0, 0);
X  wprintw(info, "Use arrow keys to move, space to place / erase, ^D to start", NULL);
X  wrefresh(info);
X  curx = cury = 1;
X  wmove(mns, cury - 1, curx - 1);
X  wrefresh(mns);
X  noecho();
X  for (;;) {
X	c = wgetch(mns);
X	if (c == '\004')
X		break;
X	else if (c == ' ') {
X		if (present[cury][curx]) {
X			--present[cury][curx];
X			changes++;
X			die++;
X			mvwaddch(mns, cury, curx, ' ');
X		} else {
X			++present[cury][curx];
X			changes++;
X			live++;
X			mvwaddch(mns, cury, curx, '*');
X		}
X	} else if (c == '\033') {
X		wgetch(mns);
X		switch (wgetch(mns)) {
X		    case 'A':	--cury;	break;
X		    case 'B':	++cury;	break;
X		    case 'C':	++curx;	break;
X		    case 'D':	--curx;	break;
X		    default:	break;
X		}
X	}
X	if (cury > maxrow) cury = minrow;
X	if (cury < minrow) cury = maxrow;
X	if (curx > maxcol) curx = mincol;
X	if (curx < mincol) curx = maxcol;
X	wmove(mns, cury, curx);
X	wrefresh(mns);
X  }
X  wclear(info);
X}
X
X/* Update rules:  2 or 3 adjacent alive --- stay alive
X *                3 adjacent alive -- dead to live
X *                all else die or stay dead
X */
Xvoid update()
X{				/* Does all mathmatical calculations */
X  int howmany, w, x, y, z;
X  changes = die = live = 0;
X  for (j = 0; j < maxrow; j++) {
X	for (k = 0; k < maxcol; k++) {
X		w = j - 1;
X		x = j + 1;
X		y = k - 1;
X		z = k + 1;
X
X		howmany = (past[w][y] + past[w][k] + past[w][z] +
X			   past[j][y] + past[j][z] + past[x][y] +
X			   past[x][k] + past[x][z]);
X
X		switch (howmany) {
X		    case 0:
X		    case 1:
X		    case 4:
X		    case 5:
X		    case 6:
X		    case 7:
X		    case 8:
X			present[j][k] = 0;
X			if (past[j][k]) changes++, die++;
X			break;
X		    case 3:
X			present[j][k] = 1;
X			if (!past[j][k]) changes++, live++;
X			break;
X		    default:	break;
X		}
X	}
X  }
X  if (live == die)
X	++icnt;
X  else
X	icnt = 0;
X
X  if (icnt == REPSTOP) cleanup(0);
X}
X
X/* Print - updates the screen according to changes from past to present */
Xvoid print()
X{	
X/* Updates the screen, greatly improved using curses */
X  if (pri) {
X	wmove(info, 0, 0);
X	total += changes;
X	cycle++;
X	wprintw(info, "Cycle %5d | %5d changes: %5d died + %5d born = %5u total changes", (char *) cycle, changes, die, live, total);
X	wclrtoeol(info);
X  }
X  for (j = 1; j < maxrow; j++) {
X	for (k = 1; k < maxcol; k++) {
X		if (present[j][k] != past[j][k] && present[j][k] == 1) {
X			wmove(mns, j, k);
X			wprintw(mns, "*", NULL);
X		} else if (present[j][k] != past[j][k] && present[j][k] == 0) {
X			wmove(mns, j, k);
X			wprintw(mns, " ", NULL);
X		}
X	}
X  }
X  if (pri) wrefresh(info);
X  wrefresh(mns);
X}
X
X/* Main - main procedure */
Xint main(ac, av)
Xint ac;
Xchar *av[];
X{
X  if (ac > 1) {
X	for (j = 1; j < ac; j++) {
X		switch (av[j][1]) {
X		    case 'd':	++draw;	break;
X		    case 'p':	++pri;	break;
X		    default:
X			fprintf(stderr, "%s: usage: %s [-d] [-p]\n", av[0], av[0]);
X			exit(1);
X		}
X	}
X  }
X
X  initialize();
X  if (draw) makscr();
X
X  for (;;) {
X	print();
X	for (j = 0; j < maxrow; j++) {
X		for (k = 0; k < maxcol; k++) past[j][k] = present[j][k];
X	}
X	update();
X  }
X}
/
echo x - men.c
sed '/^X/s///' > men.c << '/'
X/* men - menu system for MINIX		Author: Andy Tanenbaum */
X
X/* This is a simple menu system for MINIX.  By creating a .menu file and
X * putting men at the end of a users .profile, when the user logs in, a
X * menu appears.  The user can select items from the menu by typing short
X * commands.  The .menu file consists of lines, one per menu entry.
X * Each line has three parts, separated by semicolons.  The first is the
X * string to be typed to invoke the menu item.  The second is text to
X * appear on the screen.  The third is the command sequence to execute
X * when the item is selected.  The command sequence may need parameters,
X * so this program allows prompting for them.  At the place where a
X * parameter must be filled in, the menu writer should put %<prompt>%
X * where <prompt> tells the user what to fill in.  Many commands produce
X * some sort of output for the user to inspect (e.g. ls).  To allow this
X * output to remain on the screen until the user has read it, the special
X * action: # may be used.  This is a macro for: 
X *
X *	getlf "Hit RETURN to menu"
X *
X * Here is an example of the .menu file:
X *
X * ca:Calendar:cal %month% %year%;getlf "Hit RETURN to continue"
X * cp:Copy file:cp %source file% %destination file%
X * da:Date:date;sleep 3
X * du:Disk Usage:du %directory name%;getlf "Hit RETURN to continue"
X * e:ELLE:elle %file name%
X * f:Tell fortune:fortune;getlf "Hit RETURN to continue"
X * g:Grep:grep %pattern% %file(s)%;getlf "Hit RETURN to continue"
X * k:Kermit:kermit 
X * ls:List directory (short):ls -C;getlf "Hit RETURN to continue"
X * ll:List directory (long):ls -l;getlf "Hit RETURN to continue"
X * mi:Mined:mined %file name%
X * mk:Make file system:mkfs %special% %size or prototype name%
X * mor:Examine file:more %file name%
X * mou:Mount floppy:/etc/mount /dev/fd0 %directory to mount on%
X * mv:Rename a file:mv %old name% %new name%
X * p:Print current dir name:pwd;getlf Hit RETURN to continue"
X * rec:Recover lost file:recover %file name%
X * rm:Remove file:rm %file name(s)%
X * v:vi:/bin/vi
X * +:RPN calculator:ic
X * q:Exit menu system:exit
X * !:Temporary escape to shell:/bin/sh
X * 
X */
X
X#include <sys/types.h>
X#include <fcntl.h>
X#include <sgtty.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X#include <stdio.h>
X
X#define MAX_ITEMS 44		/* max items in all the visible menus */
X#define EXEC_BUF_SIZE 1024	/* max chars in an executable command */
X#define MAX_FILE_SIZE 5000	/* # bytes in the .menu file */
X#define PROMPT_SIZE 256		/* size of the prompt buffer */
X#define DEFAULT_FILE ".menu"	/* default file where menu is found */
X#define ENTRIES_PER_COL 11	/* each menu is limited to this many entries */
X#define LINE_SIZE 80		/* input buffer size */
X#define SCREEN_WIDTH 80		/* # columns in the screen */
X#define LINES 23		/* lines on the screen */
X#define SCREEN_SIZE (LINES * (SCREEN_WIDTH + 1))
X
X/* These items define the characters used for building frames around menus. */
X#define ULCORNER 201
X#define MIDDLE   205
X#define URCORNER 187
X#define LLCORNER 200
X#define LRCORNER 188
X#define SINGLE   179
X#define DOUBLE   186
X#define LMIDT    204
X#define RMIDT    185
X#define DOWN     209
X#define UP       207
X#define CROSS    216
X
Xstruct item {
X  char *code;			/* pointer to code symbol for invocation */
X  char *desc;			/* pointer to text describing menu item */
X  char *exec;			/* pointer to commands to execute */
X} item[MAX_ITEMS];
X
Xint nitems;			/* number of items in item table */
Xchar file_buf[MAX_FILE_SIZE+2];	/* buffer for holding .menu file */
Xchar screen[SCREEN_SIZE];	/* screen buffer image */
Xchar backspace = '\b';		/* backspace */
Xchar newline = '\n';		/* newline */
Xchar separator = ':';		/* menu items are separated by this char */
Xchar prompt = '%';		/* separator for prompts in commands */
Xchar ret = '#';			/* generates special message */
Xchar *clr_str = "\033[H\033[0J";	/* ANSI for clear the screen */
Xchar *ret_str = "getlf \"\n\nPlease hit RETURN to go back to the menu\"";
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void read_file, (int argc, char *argv []));
X_PROTOTYPE(void build_item_table, (void));
X_PROTOTYPE(void legality_check, (void));
X_PROTOTYPE(void build_display, (void));
X_PROTOTYPE(void init_screen, (void));
X_PROTOTYPE(void build_col, (struct item *ip, int count, int offset, int wid1, int wid2));
X_PROTOTYPE(void draw, (void));
X_PROTOTYPE(void barfill, (char *s, int lt, int mid, int rt, int wid1, int wid2));
X_PROTOTYPE(void execute, (void));
X_PROTOTYPE(void expand, (char *menu, char *exec));
X_PROTOTYPE(void clr_screen, (void));
X_PROTOTYPE(void syntax_err, (char *s));
X_PROTOTYPE(void code_err, (struct item *ip, struct item *jp));
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X  read_file(argc, argv);	/* read in the menu file */
X  build_item_table();		/* extract info from menu file */
X  legality_check();		/* check for duplicates etc. */
X  build_display();
X
X  /* Display the menu and get a command to execute. */
X  while (1) {
X	draw();
X	execute();
X  }
X  return(0);
X}
X
Xvoid read_file(argc, argv)
Xint argc;
Xchar *argv[];
X{
X/* Read the menu file into screen. */
X
X  char *file_name;
X  int fd, n;
X
X  if (argc > 2) {
X	fprintf(stderr, "Usage: men [file]\n");
X	exit(1);
X  }
X
X  file_name = (argc == 2 ? argv[1] : DEFAULT_FILE);
X  fd = open(file_name, O_RDONLY);
X  if (fd < 0) {
X	fprintf(stderr, "Cannot open %s\n", file_name);
X	exit(1);
X  }
X
X  n = read(fd, file_buf, MAX_FILE_SIZE);
X  if (n == MAX_FILE_SIZE) {
X	fprintf(stderr, "%s is too large\n", file_name);
X	exit(1);
X  }
X
X  file_buf[n+1] = '\n';
X  file_buf[n+2] = '\0';
X}
X
Xvoid build_item_table()
X{
X/* Examine the menu file line by line and build struct item. */
X
X  char *p;
X  struct item *ip;
X
X  p = file_buf;
X  ip = &item[0];
X  nitems = 0;
X
X  while (*p != 0) {
X	/* Check for too many items. */
X	if (nitems > MAX_ITEMS) {
X		fprintf(stderr, "Too many items in the menu (%d)\n", nitems);
X		exit(1);
X	}
X
X	ip->code = p;		/* p points to the code for this item */
X
X	/* Search line for first separator.  It's absence is an error. */
X	while (*p != separator && *p != '\n') p++;
X	if (*p == '\n') syntax_err(ip->code);
X	*p++ = '\0';
X
X	/* Search line for second separator.  It's absence is also an error. */
X	ip->desc = p;		/* p points to the description for this item */
X	while (*p != separator && *p != '\n') p++;
X	if (*p == '\n') syntax_err(ip->code);
X	*p++ = '\0';
X	
X	/* Search line for line feed.  It cannot be absent (one was added). */
X	ip->exec = p;
X	while (*p != '\n') p++;
X	*p++ = '\0';
X
X	/* Move on to next item. */
X	ip++;
X	nitems++;
X  }
X}
X
Xvoid legality_check()
X{
X/* It is forbidden to repeat a code in the menu.  It is also forbidden to
X * have one code be the prefix of another code, i.e., you can't have a
X * code 'a' and a code 'am' because carriage returns are not used.  As soon
X * as you type 'a', the first item will be executed.
X */
X
X  size_t n1, n2;
X  int prompt_count;
X  char *p;
X  struct item *ip, *jp;
X
X  for (ip = &item[0]; ip < &item[nitems]; ip++) {
X	for (jp = ip + 1; jp < &item[nitems]; jp++) {
X		if (strcmp(ip->code, jp->code) == 0) code_err(ip, jp);
X		n1 = strlen(ip->code);
X		n2 = strlen(jp->code);
X		if (strncmp(ip->code, jp->code, n1) == 0) code_err(ip, jp);
X		if (strncmp(ip->code, jp->code, n2) == 0) code_err(ip, jp);
X	}
X
X	/* If the exec part uses %, they better be balanced. */
X	prompt_count = 0;
X	p = ip->exec;
X	while (*p != '\0') {
X		if (*p == prompt) prompt_count++;
X		p++;
X	}
X
X	/* Check to see that it is even. */
X	if (prompt_count & 01) {
X		fprintf(stderr,"Unbalanced %% ... %% in: %s\n",ip->exec);
X		exit(1);
X	}
X  }
X  	
X}
X	
X
Xvoid build_display()
X{
X/* The display is constructed in screen and written out in one blow. */
X
X  int wid1, wid2, wid3, cols, k, offset, left, count;
X  struct item *ip;
X
X  /* Determine how wide the columns must be. */
X  wid1 = 0;			/* code string column width */
X  wid2 = 0;			/* description column width */
X  for (ip = &item[0]; ip < &item[nitems]; ip++) {
X	if (strlen(ip->code) > wid1) wid1 = strlen(ip->code);
X	if (strlen(ip->desc) > wid2) wid2 = strlen(ip->desc);
X  }
X
X  /* Is there enough room on the screen? */
X  wid3 = wid1 + wid2 + 9;	/* allow for spaces around strings, etc. */
X  cols = (nitems + ENTRIES_PER_COL - 1)/ENTRIES_PER_COL;
X  if (cols * wid3 > SCREEN_WIDTH) {
X	fprintf(stderr, "Menus are too wide to fit %d of them on the screen\n",
X								cols);
X	exit(1);
X  }
X
X  /* There may be several menus next to each other.  Build them separately. */
X  k = 0;
X  offset = 0;			/* which column to display the menu in */
X  left = nitems;		/* how many items left to display */
X  init_screen();
X
X  while (left > 0) {
X	count = (left < ENTRIES_PER_COL ? left : ENTRIES_PER_COL);
X	build_col(&item[k], count, offset, wid1, wid2);
X	left -= count;
X	k += count;
X	offset += wid1 + wid2 + 9;
X  }
X}
X
Xvoid init_screen()
X{
X/* Clear the screen buffer */
X
X  char *p;
X
X  for (p = &screen[0]; p < &screen[SCREEN_SIZE]; p++) *p = ' ';
X  for (p = &screen[SCREEN_WIDTH]; p < &screen[SCREEN_SIZE]; p +=SCREEN_WIDTH+1)
X	*p = '\n';
X}
X
Xvoid build_col(ip, count, offset, wid1, wid2)
Xstruct item *ip;		/* pointer into item table */
Xint count;			/* number of items to display */
Xint offset;			/* column offset for this menu */
Xint wid1;			/* width of code string */
Xint wid2;			/* width of description screen */
X{
X/* Build one vertical menu in screen. */
X
X  int k;
X  char *s, *base;
X
X  /* Build top of menu. */
X  s = &screen[offset];
X  barfill(s, ULCORNER, DOWN, URCORNER, wid1, wid2);
X  base = s += SCREEN_WIDTH + 1;
X
X  for (k = 0; k < count; k++) {
X	/* Iterate on each line to be entered. */
X	s = base;
X	*s++ = DOUBLE;
X	*s++ = ' ';
X	strcpy(s, ip->code);
X	s = base + wid1 + 3;
X	*s = SINGLE;
X
X	strcpy(base + wid1 + 5, ip->desc);
X	s = base + wid1 + wid2 + 6;
X	*s = DOUBLE;
X
X	/* Draw the line under the entry.  Last one is different. */
X	s = base + SCREEN_WIDTH + 1;
X	if (k != count -1) {
X		barfill(s, LMIDT, CROSS, RMIDT, wid1, wid2);
X	} else {
X		barfill(s, LLCORNER, UP, LRCORNER, wid1, wid2);
X	}
X	base += 2 * SCREEN_WIDTH + 2;
X	ip++;
X  }
X}
X
Xvoid draw()
X{
X/* Draw the menu on the screen. */
X  char *p;
X
X  for (p = &screen[0]; p < &screen[SCREEN_SIZE]; p++)
X	if (*p == '\0') *p = ' ';
X
X  write(1, "\n", 1);
X  write(1, screen, SCREEN_SIZE);
X}
X
X
Xvoid barfill(s, lt, mid, rt, wid1, wid2)
Xchar *s;			/* where to start */
Xint lt;				/* symbol to use on left */
Xint mid;			/* symbol to use in middle */
Xint rt;				/* symbol to use on right */
Xint wid1;			/* col1 width */
Xint wid2;			/* col2 width */
X{
X/* Draw a bar of symbols. */
X
X  int i;
X
X  *s++ = lt;
X  for (i = 0; i < wid1 + 2; i++) *s++ = MIDDLE;
X  *s++ = mid;
X  for (i = 0; i < wid2 + 2; i++) *s++ = MIDDLE;
X  *s++ = rt;
X}
X
X  
Xvoid execute()
X{
X/* Get input and execute a command. */
X
X  struct sgttyb save, argp;
X  struct item *ip;
X  char c[LINE_SIZE], exec_buf[EXEC_BUF_SIZE], *cp;
X
X  /* Put terminal in cbreak mode. */
X  ioctl(fileno(stdin), TIOCGETP, &save);
X  argp = save;
X  argp.sg_flags |= CBREAK;
X
X  /* Read in characters */
X  cp = &c[0];
X  while (1) {
X	ioctl(fileno(stdin), TIOCSETP, &argp);
X	read(fileno(stdin), cp, 1);
X	ioctl(fileno(stdin), TIOCSETP, &save);
X	if (*cp == newline) {
X		cp = &c[0]; /* restart */
X		continue;
X	}
X	if (*cp == backspace && cp > c) {
X		cp--;
X		write(1, " \b", 2);
X		continue;
X	}	
X	*(cp+1) = 0;
X
X	/* Search for a match. */
X	for (ip = &item[0]; ip < &item[nitems]; ip++) {
X		if (strcmp(c, ip->code) == 0) {
X			/* Hit found. */
X			if (strcmp(ip->exec, "exit") == 0) {
X				clr_screen();
X				exit(0);
X			}
X			expand(ip->exec, exec_buf);
X			clr_screen();
X			system(exec_buf);
X			return;
X		}
X	}
X	cp++;
X  }
X}
X
X
Xvoid expand(menu, exec)
Xchar *menu;			/* pointer to exec part of menu item */
Xchar *exec;			/* pointer to exec buffer */
X{
X/* The exec part of the menu item may have parameters, delimited by %...%
X * with a prompt in between.  The command is copied to the exec buffer,
X * and the parameters prompted for and filled in.  The final executable
X * command is passed by in exec.
X */
X
X  register char *mp, *ep;
X  int n;
X  char prompt_buf[PROMPT_SIZE], *pb;
X
X  mp = menu;
X  ep = exec;
X  *ep = 0;
X
X  /* Loop need here.  One iteration per parameter prompted for. */
X  while (1) {
X	while (*mp != '\0' && *mp != prompt && *mp != ret) *ep++ = *mp++;
X	if (*mp == '\0') {
X		*ep = '\0';
X		return;
X	}
X
X	/* '#' is a macro for calling getlf. */
X	if (*mp == ret) {
X		pb = ret_str;
X		while (*pb != '\0') *ep++ = *pb++;
X		mp++;
X		continue;
X	}
X
X	/* Start of parameter prompt. Copy it to prompt_buf. */
X	mp++;
X	pb = &prompt_buf[0];
X	while (*mp != prompt) *pb++ = *mp++;
X	*pb = '\0';
X	mp++;
X	*ep = '\0';
X
X	/* Prompt the user for the parameter. */
X	clr_screen();
X
X	printf("Please enter:\n\n\t%s\n\nThen hit RETURN\n\n%s",
X							prompt_buf, exec);
X	fflush(stdout);
X
X	/* Get the reply. */
X	n = read(0, prompt_buf, PROMPT_SIZE);
X	prompt_buf[n-1] = '\0';
X	pb = &prompt_buf[0];
X	while (*pb != '\0') *ep++ = *pb++;
X  }		
X}
X
X
Xvoid clr_screen()
X{
X  /* Could use Termcap, but this is simpler and probably faster. */
X  write(1, clr_str, strlen(clr_str));
X}
X
Xvoid syntax_err(s)
Xchar *s;
X{
X  fprintf(stderr, "Syntax error in menu file in line:\n%s\n",s);
X  exit(1);
X}
X
Xvoid code_err(ip, jp)
Xstruct item *ip, *jp;
X{
X  fprintf(stderr, "The following lines have strings that conflict:\n");
X  fprintf(stderr, "%s;%s;%s\n",ip->code,ip->desc,ip->exec);
X  fprintf(stderr, "%s;%s;%s\n",jp->code,jp->desc,jp->exec);
X  exit(1);
X}
/
echo x - mkfifo.c
sed '/^X/s///' > mkfifo.c << '/'
X/* mkfifo - Make FIFO special files		Author: V. Archer */
X
X/* Copyright 1991 by Vincent Archer
X *	You may freely redistribute this software, in source or binary
X *	form, provided that you do not alter this copyright mention in any
X *	way.
X */
X
X#include <sys/types.h>
X#include <stdlib.h>
X#include <sys/stat.h>
X#include <string.h>
X#include <unistd.h>
X#include <minix/minlib.h>
X#include <stdio.h>
X
X#define USR_MODES (S_ISUID|S_IRWXU)
X#define GRP_MODES (S_ISGID|S_IRWXG)
X#define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
X#ifdef S_ISVTX
X#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
X#else
X#define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
X#endif
X#define DEFAULT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
X
X
X/* Global u_mask needed in changemode.h */
Xmode_t u_mask;
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(mode_t parsemode, (char *symbolic, Mode_t oldmode));
X_PROTOTYPE(void usage, (void));
X
X/* Parse a P1003.2 4.7.7-conformant symbolic mode. */
Xmode_t parsemode(symbolic, oldmode)
Xchar *symbolic;
Xmode_t oldmode;
X{
X  mode_t who, mask, newmode, tmpmask;
X  char action;
X
X  newmode = oldmode & ALL_MODES;
X  while (*symbolic) {
X	who = 0;
X	for (; *symbolic; symbolic++) {
X		if (*symbolic == 'a') {
X			who |= ALL_MODES;
X			continue;
X		}
X		if (*symbolic == 'u') {
X			who |= USR_MODES;
X			continue;
X		}
X		if (*symbolic == 'g') {
X			who |= GRP_MODES;
X			continue;
X		}
X		if (*symbolic == 'o') {
X			who |= S_IRWXO;
X			continue;
X		}
X		break;
X	}
X	if (!*symbolic || *symbolic == ',') usage();
X	while (*symbolic) {
X		if (*symbolic == ',') break;
X		switch (*symbolic) {
X		    default:
X			usage();
X		    case '+':
X		    case '-':
X		    case '=':	action = *symbolic++;
X		}
X		mask = 0;
X		for (; *symbolic; symbolic++) {
X			if (*symbolic == 'u') {
X				tmpmask = newmode & S_IRWXU;
X				mask |= tmpmask | (tmpmask << 3) | (tmpmask << 6);
X				symbolic++;
X				break;
X			}
X			if (*symbolic == 'g') {
X				tmpmask = newmode & S_IRWXG;
X				mask |= tmpmask | (tmpmask >> 3) | (tmpmask << 3);
X				symbolic++;
X				break;
X			}
X			if (*symbolic == 'o') {
X				tmpmask = newmode & S_IRWXO;
X				mask |= tmpmask | (tmpmask >> 3) | (tmpmask >> 6);
X				symbolic++;
X				break;
X			}
X			if (*symbolic == 'r') {
X				mask |= S_IRUSR | S_IRGRP | S_IROTH;
X				continue;
X			}
X			if (*symbolic == 'w') {
X				mask |= S_IWUSR | S_IWGRP | S_IWOTH;
X				continue;
X			}
X			if (*symbolic == 'x') {
X				mask |= EXE_MODES;
X				continue;
X			}
X			if (*symbolic == 's') {
X				mask |= S_ISUID | S_ISGID;
X				continue;
X			}
X			if (*symbolic == 'X') {
X				if (S_ISDIR(oldmode) || (oldmode & EXE_MODES))
X					mask |= EXE_MODES;
X				continue;
X			}
X#ifdef S_ISVTX
X			if (*symbolic == 't') {
X				mask |= S_ISVTX;
X				who |= S_ISVTX;
X				continue;
X			}
X#endif
X			break;
X		}
X		switch (action) {
X		    case '=':
X			if (who)
X				newmode &= ~who;
X			else
X				newmode = 0;
X		    case '+':
X			if (who)
X				newmode |= who & mask;
X			else
X				newmode |= mask & (~u_mask);
X			break;
X		    case '-':
X			if (who)
X				newmode &= ~(who & mask);
X			else
X				newmode &= ~mask | u_mask;
X		}
X	}
X	if (*symbolic) symbolic++;
X  }
X  return(newmode);
X}
X
X
X/* Main module. Since only one option (-m mode) is allowed, there's no need
X * to include the whole getopt() stuff.
X */
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  int errors = 0;
X  char *symbolic;
X
X  if (argc > 2 && *argv[1] == '-' && strcmp(argv[1], "-m") != 0) usage();
X  argc--;
X  argv++;
X  if (argc && strncmp(*argv, "-m", (size_t) 2) == 0) {
X	argc--;
X	if ((argv[0])[2])
X		symbolic = (*argv++) + 2;
X	else {
X		if (!argc--) usage();
X		argv++;
X		symbolic = *argv++;
X	}
X	u_mask = umask(0);
X	umask(u_mask);
X  } else
X	symbolic = (char *) 0;
X
X  if (!argc) usage();
X  for (; argc--; argv++)
X	if (mkfifo(*argv, DEFAULT_MODE)) {
X		perror(*argv);
X		errors = 1;
X	} else if (symbolic && chmod(*argv, parsemode(symbolic, DEFAULT_MODE))) {
X		unlink(*argv);
X		perror(*argv);
X		errors = 1;
X	}
X  return(errors);
X}
X
X
X/* Posix command prototype. */
Xvoid usage()
X{
X  std_err("Usage: mkfifo [-m mode] file...\n");
X  exit(1);
X}
/
echo x - ncheck.c
sed '/^X/s///' > ncheck.c << '/'
X/* ncheck   name check			  Author:  Raymond Michiels */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <dirent.h>
X#include <string.h>
X#include <limits.h>
X#include <ctype.h>
X#include <errno.h>
X#include <stdlib.h>
X#include <unistd.h>
X#include <stdio.h>
X
Xino_t *ilist;
Xint iflag = 0, aflag = 0, sflag = 0, nr_inodes = 0, opt, skip_len;
Xchar *progname;
Xchar *filesystem = NULL;
Xchar *mnt_point = NULL;
Xchar path[PATH_MAX];
X
Xextern int optind;
Xextern char *optarg;
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void usage, (void));
X_PROTOTYPE(void myexit, (int n));
X_PROTOTYPE(void readilist, (char *p));
X_PROTOTYPE(int inlist, (Ino_t inode));
X_PROTOTYPE(int dotfile, (char *fullname));
X_PROTOTYPE(int toprint, (struct stat *statbuf, char *name));
X_PROTOTYPE(void traverse, (char *dirname));
X
Xvoid myexit(n)		/* maybe I could use something like _cleanup() */
Xint n;
X{
X  if (filesystem != NULL)
X	umount(filesystem);
X  if (mnt_point != NULL)
X	rmdir(mnt_point);
X  exit(n);
X}
X
X
Xvoid usage()
X{
X  fprintf(stderr, "usage: %s [ -i numbers] [-s] [-a] file_system\n", progname);
X  myexit(1);
X}
X
X
Xvoid readilist(p)
Xchar *p;
X{
X  ilist = (ino_t *)malloc(strlen(p)/2+1);
X  if (ilist == NULL) {
X	fprintf(stderr, "couldn't malloc i-node list\n");
X	myexit(1);
X  }
X  do {
X	if (*p == ',') p++;	/* skip comma's */
X	if (!isdigit(*p)) {
X		fprintf(stderr, "malformed i-node list\n");
X		myexit(1);
X	}
X	ilist[nr_inodes++] = atoi(p);
X  } while ((p = strchr(p, ',')) != NULL);
X}
X
X
Xint inlist(inode)
Xino_t inode;
X{
X  int i;
X
X  for (i = 0; i < nr_inodes; i++) {
X	if (ilist[i] == inode)
X		return(1);
X  }
X  return(0);
X}
X
X
Xint dotfile(fullname)
Xchar *fullname;
X{
X  char *name;
X
X  name = strrchr(fullname, '/') + 1;
X
X  return(!(strcmp(name, ".") && strcmp(name, "..")));
X}
X
X
Xint toprint(statbuf, name)
Xstruct stat *statbuf;
Xchar *name;
X{
X#define S_SPECIAL(x) (x & (S_ISUID | S_ISGID) || S_ISCHR(x) || S_ISBLK(x))
X
X  return ((!iflag || inlist(statbuf->st_ino)) &&
X	(aflag || !dotfile(name)) &&
X	(!sflag || S_SPECIAL(statbuf->st_mode)));
X}
X
X
Xvoid traverse(dirname)
Xchar *dirname;
X{
X  struct dirent *dirent;
X  DIR *dir;
X  struct stat statbuf;
X  int len;
X
X  len = strlen(dirname);
X  if (stat(dirname, &statbuf) < 0) {
X	fprintf(stderr, "could not stat %s: %s\n", dirname, strerror(errno));
X	return;
X  }
X  if (toprint(&statbuf, dirname))
X	printf("%5ld %s\n", (long) statbuf.st_ino, dirname+skip_len);
X
X  if (!dotfile(dirname) && S_ISDIR(statbuf.st_mode)) {
X	if ((dir = opendir(dirname)) == NULL) {
X		fprintf(stderr, "could not open %s: %s\n", dirname,
X			strerror(errno));
X		return;
X	}
X	dirname[len++] = '/';
X	while ((dirent = readdir(dir)) != NULL) {
X		strcpy(dirname+len, dirent->d_name);
X		traverse(dirname);
X	}
X	closedir(dir);
X  }
X}
X
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  progname = argv[0];
X
X  while ((opt = getopt(argc, argv, "i:as")) != EOF) {
X	switch (opt) {
X	case 'i':
X		if (nr_inodes > 0)
X			usage();
X		iflag = 1;
X		readilist(optarg);
X		break;
X	case 'a':
X		aflag = 1;
X		break;
X	case 's':
X		sflag = 1;
X		break;
X	}
X  }
X  if (optind > argc-1)
X	usage();
X  filesystem = argv[optind];
X
X  mnt_point = tmpnam((char *)NULL);
X  mkdir(mnt_point, 0777);
X  if (mount(filesystem, mnt_point, 1) < 0) {
X	perror("mount");
X	myexit(1);
X  }
X  strcpy(path, mnt_point);
X  skip_len = strlen(path);
X  
X  traverse(path);
X  myexit(0);
X
X  /* NOTREACHED */
X  return(0);
X}
/
echo x - pathchk.c
sed '/^X/s///' > pathchk.c << '/'
X/* pathchk - check pathnames		Author: V. Archer */
X
X/* Copyright 1991 by Vincent Archer
X *	You may freely redistribute this software, in source or binary
X *	form, provided that you do not alter this copyright mention in any
X *	way.
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <limits.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X#include <minix/minlib.h>
X#include <stdio.h>
X
X/* Global variables. */
Xchar directory[PATH_MAX + 1];
Xchar POSIX_CHAR_SET[] = "\
X.#-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_~";
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void perr, (char *name, char *msg));
X_PROTOTYPE(void usage, (void));
X
X/* Perror-like function, but with a user supplied message rather than an
X * error one. The standard limits-related messages are not very clear on
X * what is wrong. :-)
X */
Xvoid perr(name, msg)
Xchar *name, *msg;
X{
X  std_err(name);
X  std_err(":");
X  std_err(msg);
X}
X
X
X/* Main module. Since only one option (-p) is allowed, do not include all
X * the getopt() stuff.
X */
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  char *name, *arg;
X  int pflag, length, maxl;
X  int rtstat = 0;
X  uid_t uid;
X  gid_t gid;
X  mode_t mask;
X  struct stat perms;
X  int Maxname;
X
X  argc--;
X  argv++;
X  if (argc && !strcmp(*argv, "-p")) {
X	argc--;
X	argv++;
X	pflag = 1;
X  } else
X	pflag = 0;
X  uid = getuid();
X  gid = getgid();
X
X  if (!argc) usage();
X
X  while (argc--) {
X	arg = *argv++;
X#if PATH_MAX != _POSIX_PATH_MAX
X	if (pflag) {
X		if (strlen(arg) > _POSIX_PATH_MAX) {
X			perr(arg, "pathname too long for Posix\n");
X			rtstat = 1;
X			continue;
X		}
X	} else
X#endif
X	if (strlen(arg) > PATH_MAX) {
X		perr(arg, "pathname too long\n");
X		rtstat = 1;
X		continue;
X	}
X	length = 0;
X	maxl = 0;
X	directory[0] = '.';
X	directory[1] = '\0';
X	if (pflag) {
X		Maxname = _POSIX_NAME_MAX;
X	} else
X		Maxname = pathconf(directory, _PC_NAME_MAX);
X
X	for (name = arg; *name; name++) {
X		if (*name == '/') {
X			if (length > Maxname) break;
X/* I do not allow a//b (empty component). Too ugly. */
X			if (length == 0 && maxl) {
X				perr(arg, "empty component\n");
X				rtstat = 1;
X				break;
X			}
X			length = 0;
X
X			if (!pflag && directory[0]) {
X				if (maxl == 0) {
X					directory[0] = '/';
X					directory[1] = '\0';
X				} else {
X					strncpy(directory, arg, (size_t) maxl);
X					directory[maxl] = '\0';
X				}
X
X				if (stat(directory, &perms) == 0) {
X					Maxname = pathconf(directory, _PC_NAME_MAX);
X					if (uid) {
X						if (uid == perms.st_uid)
X							mask = S_IXUSR;
X						else if (gid == perms.st_gid)
X							mask = S_IXGRP;
X						else
X							mask = S_IXOTH;
X						if (!(mask & perms.st_mode)) {
X							perr(arg, "not searchable\n");
X							rtstat = 1;
X							break;
X						}
X					}
X				} else
X					directory[0] = '\0';
X			}
X		} else {
X			if (!strchr(POSIX_CHAR_SET, *name)) {
X				perr(arg, "illegal character\n");
X				rtstat = 1;
X				name = "";
X				length = 0;	/* do not print 2 msgs */
X				break;
X			}
X			length++;
X		}
X		maxl++;
X	}
X	if (length > Maxname) {
X		perr(arg, pflag ? "component name too long for Posix\n"
X		     : "component name too long\n");
X		rtstat = 1;
X	}
X  }
X  return(rtstat);
X}
X
X
X/* Posix command prototype. */
Xvoid usage()
X{
X  std_err("Usage: pathchk [-p] file...\n");
X  exit(1);
X}
/
echo x - proto.c
sed '/^X/s///' > proto.c << '/'
X/* proto - Generate ANSI C prototypes.	Author:	Eric R. Smith */
X
X/* Program to extract function declarations from C source code
X * Written by Eric R. Smith and placed in the public domain
X * Thanks are due to Jwahar R. Bammi for fixing several bugs
X * And providing the Unix makefiles.
X */
X#define EXIT_SUCCESS  0
X#define EXIT_FAILURE  1
X
X#include <string.h>
X#include <ctype.h>
X#include <stdlib.h>
X#include <stdio.h>
X
X#define ISCSYM(x) ((x) > 0 && (isalnum(x) || (x) == '_' ))
X#define ABORTED ( (Word *) -1 )
X#define MAXPARAM 20		/* max. number of parameters to a function */
X
Xtypedef struct word {
X  struct word *next;
X  char string[1];
X} Word;
X
Xint inquote = 0;		/* in a quote? */
Xint newline_seen = 1;		/* are we at the start of a line */
Xlong linenum = 1L;		/* line number in current file */
Xlong endline = 0L;		/* the last line before the { of a f'n */
Xlong symline = 0L;		/* Line that symbol was on, set by getsym() */
Xint dostatic = 0;		/* do static functions? */
Xint donum = 0;			/* print line numbers? */
Xint dohead = 1;			/* do file headers? */
Xint docond = 1;			/* conditionalize for non-ANSI compilers? */
Xint dodiff = 0;			/* Output a diff file to prototype original */
Xint doold = 0;			/* do old style: P() */
Xint glastc = ' ';		/* last char. seen by getsym() */
XWord *endlist;			/* Parentheses after the parameters */
Xchar *progname;			/* name of program (for error messages) */
X
X
X_PROTOTYPE(Word * word_alloc, (char *s));
X_PROTOTYPE(void word_free, (Word * w));
X_PROTOTYPE(int List_len, (Word * w));
X_PROTOTYPE(Word * word_append, (Word * w1, Word * w2));
X_PROTOTYPE(int foundin, (Word * w1, Word * w2));
X_PROTOTYPE(void addword, (Word * w, char *s));
X_PROTOTYPE(void printlist, (Word * p));
X_PROTOTYPE(Word * typelist, (Word * p));
X_PROTOTYPE(void typefixhack, (Word * w));
X_PROTOTYPE(int ngetc, (FILE * f));
X_PROTOTYPE(int fnextch, (FILE * f));
X_PROTOTYPE(int nextch, (FILE * f));
X_PROTOTYPE(int getsym, (char *buf, FILE * f));
X_PROTOTYPE(int skipit, (char *buf, FILE * f));
X_PROTOTYPE(Word * getparamlist, (FILE * f));
X_PROTOTYPE(void emit, (Word * wlist, Word * plist, long startline));
X_PROTOTYPE(void getdecl, (FILE * f));
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void Usage, (void));
X
X/* Routines for manipulating lists of words. */
X
XWord *word_alloc(s)
Xchar *s;
X{
X  Word *w;
X
X  w = (Word *) malloc(sizeof(Word) + strlen(s) + 1);
X  if (w == NULL) {
X	fprintf(stderr, "%s: out of memory\n", progname);
X	exit(1);
X  }
X  (void) strcpy(w->string, s);
X  w->next = NULL;
X  return w;
X}
X
Xvoid word_free(w)
XWord *w;
X{
X  Word *oldw;
X  while (w) {
X	oldw = w;
X	w = w->next;
X	free((char *) oldw);
X  }
X}
X
X/* Return the length of a list; empty words are not counted */
Xint List_len(w)
XWord *w;
X{
X  int count = 0;
X
X  while (w) {
X	if (*w->string) count++;
X	w = w->next;
X  }
X  return count;
X}
X
X/* Append two lists, and return the result */
XWord *word_append(w1, w2)
XWord *w1, *w2;
X{
X  Word *r, *w;
X
X  r = w = word_alloc("");
X
X  while (w1) {
X	w->next = word_alloc(w1->string);
X	w = w->next;
X	w1 = w1->next;
X  }
X  while (w2) {
X	w->next = word_alloc(w2->string);
X	w = w->next;
X	w2 = w2->next;
X  }
X
X  return r;
X}
X
X/* See if the last entry in w2 is in w1 */
Xint foundin(w1, w2)
XWord *w1, *w2;
X{
X  while (w2->next) w2 = w2->next;
X
X  while (w1) {
X	if (!strcmp(w1->string, w2->string)) return 1;
X	w1 = w1->next;
X  }
X  return 0;
X}
X
X/* Add the string s to the given list of words */
Xvoid addword(w, s)
XWord *w;
Xchar *s;
X{
X  while (w->next) w = w->next;
X  w->next = word_alloc(s);
X}
X
X/* Printlist: print out a list */
Xvoid printlist(p)
XWord *p;
X{
X  Word *w;
X  int i = 0;
X
X  for (w = p; w; w = w->next) {
X	printf("%s", w->string);
X	if (ISCSYM(w->string[0]) && i > 0) printf(" ");
X	i++;
X  }
X}
X
X/* Given a list representing a type and a variable name, extract just
X * the base type, e.g. "struct word *x" would yield "struct word".
X * Similarly, "unsigned char x[]" would yield "unsigned char".
X */
XWord *typelist(p)
XWord *p;
X{
X  Word *w, *r, *last;
X
X  last = r = w = word_alloc("");
X  while (p && p->next) {
X	if (p->string[0] == '[') {
X		word_free(w);
X		last->next = NULL;
X		break;
X	}
X	if (p->string[0] && !ISCSYM(p->string[0])) break;
X	w->next = word_alloc(p->string);
X	last = w;
X	w = w->next;
X	p = p->next;
X  }
X  return r;
X}
X
X/* Typefixhack: promote formal parameters of type "char", "unsigned char",
X * "short", or "unsigned short" to "int".
X */
Xvoid typefixhack(w)
XWord *w;
X{
X  Word *oldw = 0;
X
X  while (w) {
X	if (*w->string) {
X		if ((!strcmp(w->string, "char") ||
X		     !strcmp(w->string, "short"))
X		    && (List_len(w->next) < 2)) {
X			if (oldw && !strcmp(oldw->string, "unsigned")) {
X				oldw->next = w->next;
X				free((char *) w);
X				w = oldw;
X			}
X			(void) strcpy(w->string, "int");
X		}
X	}
X	w = w->next;
X  }
X}
X
X/* Read a character: if it's a newline, increment the line count */
Xint ngetc(f)
XFILE *f;
X{
X  int c;
X
X  c = getc(f);
X  if (c == '\n') linenum++;
X
X  return c;
X}
X
X/* Read the next character from the file. If the character is '\' then
X * read and skip the next character. Any comment sequence is converted
X * to a blank.
X */
Xint fnextch(f)
XFILE *f;
X{
X  int c, lastc, incomment;
X
X  c = ngetc(f);
X  while (c == '\\') {
X	c = ngetc(f);		/* skip a character */
X	c = ngetc(f);
X  }
X  if (c == '/' && !inquote) {
X	c = ngetc(f);
X	if (c == '*') {
X		incomment = 1;
X		c = ' ';
X		while (incomment) {
X			lastc = c;
X			c = ngetc(f);
X			if (lastc == '*' && c == '/')
X				incomment = 0;
X			else if (c < 0)
X				return c;
X		}
X		return fnextch(f);
X	} else {
X		if (c == '\n') linenum--;
X		(void) ungetc(c, f);
X		return '/';
X	}
X  }
X  return c;
X}
X
X
X/* Get the next "interesting" character. Comments are skipped, and strings
X * are converted to "0". Also, if a line starts with "#" it is skipped.
X */
Xint nextch(f)
XFILE *f;
X{
X  int c;
X
X  c = fnextch(f);
X  if (newline_seen && c == '#') {
X	do {
X		c = fnextch(f);
X	} while (c >= 0 && c != '\n');
X	if (c < 0) return c;
X  }
X  newline_seen = (c == '\n');
X
X  if (c == '\'' || c == '\"') {
X	inquote = c;
X	while ((c = fnextch(f)) >= 0) {
X		if (c == inquote) {
X			inquote = 0;
X			return '0';
X		}
X	}
X  }
X  return c;
X}
X
X/* Get the next symbol from the file, skipping blanks.
X * Return 0 if OK, -1 for EOF.
X * Also collapses everything between { and }
X */
Xint getsym(buf, f)
Xchar *buf;
XFILE *f;
X{
X  register int c;
X  int inbrack = 0;
X
X  c = glastc;
X  while ((c > 0) && isspace(c)) c = nextch(f);
X  if (c < 0) return -1;
X  if (c == '{') {
X	inbrack = 1;
X	endline = linenum;
X	while (inbrack) {
X		c = nextch(f);
X		if (c < 0) {
X			glastc = c;
X			return c;
X		}
X		if (c == '{')
X			inbrack++;
X		else if (c == '}')
X			inbrack--;
X	}
X	(void) strcpy(buf, "{}");
X	glastc = nextch(f);
X	return 0;
X  }
X  if (!ISCSYM(c)) {
X	*buf++ = c;
X	glastc = nextch(f);
X	if (c == '(' && glastc == '*') {	/* Look for a 'f'n pointer */
X		*buf++ = glastc;
X		glastc = nextch(f);
X	}
X	*buf = 0;
X	return 0;
X  }
X  symline = linenum;
X  while (ISCSYM(c)) {
X	*buf++ = c;
X	c = nextch(f);
X  }
X  *buf = 0;
X  glastc = c;
X  return 0;
X}
X
X
X/* Skipit: skip until a ";" or the end of a function declaration is seen */
Xint skipit(buf, f)
Xchar *buf;
XFILE *f;
X{
X  int i;
X
X  do {
X	i = getsym(buf, f);
X	if (i < 0) return i;
X  } while (*buf != ';' && *buf != '{');
X
X  return 0;
X}
X
X/* Get a parameter list; when this is called the next symbol in line
X * should be the first thing in the list.
X */
XWord *getparamlist(f)
XFILE *f;
X{
X  static Word *pname[MAXPARAM];	/* parameter names */
X  Word *tlist,			/* type name */
X  *plist;			/* temporary */
X  int np = 0;			/* number of parameters */
X  int typed[MAXPARAM];		/* parameter has been given a type */
X  int tlistdone;		/* finished finding the type name */
X  int sawsomething;
X  int i;
X  int inparen = 0;
X  char buf[80];
X
X  for (i = 0; i < MAXPARAM; i++) typed[i] = 0;
X
X  plist = word_alloc("");
X  endlist = word_alloc("");
X
X  /* First, get the stuff inside brackets (if anything) */
X
X  sawsomething = 0;		/* gets set nonzero when we see an arg */
X  for (;;) {
X	if (getsym(buf, f) < 0) return(NULL);
X	if (*buf == ')' && (--inparen < 0)) {
X		if (sawsomething) {	/* if we've seen an arg */
X			pname[np] = plist;
X			plist = word_alloc("");
X			np++;
X		}
X		break;
X	}
X	if (*buf == ';') {	/* something weird */
X		return ABORTED;
X	}
X	sawsomething = 1;	/* there's something in the arg. list */
X	if (*buf == ',' && inparen == 0) {
X		pname[np] = plist;
X		plist = word_alloc("");
X		np++;
X	} else {
X		addword(plist, buf);
X		if (*buf == '(') inparen++;
X	}
X  }
X
X  /* Next, get the declarations after the function header */
X  inparen = 0;
X  tlist = word_alloc("");
X  plist = word_alloc("");
X  tlistdone = 0;
X  sawsomething = 0;
X  for (;;) {
X	if (getsym(buf, f) < 0) return(NULL);
X
X	/* Handle parentheses, which should indicate func pointer rtn values */
X	if (*buf == '(') {
X		addword(endlist, buf);
X		addword(endlist, " void ");
X		inparen++;
X	} else if (*buf == ')') {
X		if (symline == linenum) {
X			addword(endlist, buf);
X			addword(endlist, buf);
X		}
X		inparen--;
X	} else if (*buf == ',' && !inparen) {
X		/* Handle a list like "int x,y,z" */
X		if (!sawsomething) return(NULL);
X		for (i = 0; i < np; i++) {
X			if (!typed[i] && foundin(plist, pname[i])) {
X				typed[i] = 1;
X				word_free(pname[i]);
X				pname[i] = word_append(tlist, plist);
X				/* Promote types */
X				typefixhack(pname[i]);
X				break;
X			}
X		}
X		if (!tlistdone) {
X			tlist = typelist(plist);
X			tlistdone = 1;
X		}
X		word_free(plist);
X		plist = word_alloc("");
X	} else if (*buf == ';') {
X		/* Handle the end of a list */
X		if (!sawsomething) return ABORTED;
X		for (i = 0; i < np; i++) {
X			if (!typed[i] && foundin(plist, pname[i])) {
X				typed[i] = 1;
X				word_free(pname[i]);
X				pname[i] = word_append(tlist, plist);
X				typefixhack(pname[i]);
X				break;
X			}
X		}
X		tlistdone = 0;
X		word_free(tlist);
X		word_free(plist);
X		tlist = word_alloc("");
X		plist = word_alloc("");
X	} else if (!strcmp(buf, "{}"))
X		break;	/* Handle the  beginning of the function */
X		/* Otherwise, throw word into list (except for "register") */
X	else if (strcmp(buf, "register")) {
X		sawsomething = 1;
X		addword(plist, buf);
X		if (*buf == '(') inparen++;
X		if (*buf == ')') inparen--;
X	}
X  }
X
X  /* Now take the info we have and build a prototype list */
X
X  /* Empty parameter list means "void" */
X  if (np == 0) return word_alloc("void");
X
X  plist = tlist = word_alloc("");
X  for (i = 0; i < np; i++) {
X
X  /* If no type provided, make it an "int" */
X	if (!(pname[i]->next) ||
X	    (!(pname[i]->next->next)&&strcmp(pname[i]->next->string,"void"))) {
X		addword(tlist, "int");
X	}
X	while (tlist->next) tlist = tlist->next;
X	tlist->next = pname[i];
X	if (i < np - 1) addword(tlist, ", ");
X  }
X  return plist;
X}
X
X/* Emit a function declaration. The attributes and name of the function
X * are in wlist; the parameters are in plist.
X */
Xvoid emit(wlist, plist, startline)
XWord *wlist, *plist;
Xlong startline;
X{
X  Word *w;
X  int count = 0;
X
X  if (doold == 0) printf("_PROTOTYPE(");
X  if (dodiff) {
X	printf("%lda%ld,%ld\n", startline - 1, startline, startline +2);
X	printf("> #ifdef __STDC__\n> ");
X  }
X  if (donum) printf("/*%8ld */ ", startline);
X  for (w = wlist; w; w = w->next) {
X	if (w->string[0]) count++;
X  }
X  if (count < 2) printf("int ");
X  printlist(wlist);
X  if (docond) {
X	if (doold)
X		printf("P((");
X	else
X		printf(", (");
X  } else {
X	printf("( ");
X  }
X
X  printlist(plist);
X  printlist(endlist);
X
X  if (docond)
X	printf("))");
X  else
X	printf(")");
X
X  if (!dodiff)
X	printf(";\n");
X  else
X	printf("\n");
X
X  if (dodiff) {
X	printf("> #else\n");
X	printf("%lda%ld\n", endline - 1, endline);
X	printf("> #endif\n");
X  }
X}
X
X/* Get all the function declarations */
Xvoid getdecl(f)
XFILE *f;
X{
X  Word *plist, *wlist = NULL;
X  char buf[80];
X  int sawsomething;
X  long startline = 0L;		/* line where declaration started */
X  int oktoprint;
X
Xagain:				/* SHAME SHAME */
X  word_free(wlist);
X  wlist = word_alloc("");
X  sawsomething = 0;
X  oktoprint = 1;
X
X  for (;;) {
X	if (getsym(buf, f) < 0) return;
X
X	/* Guess when a declaration is not an external function definition */
X	if (!strcmp(buf, ",") || !strcmp(buf, "{}") ||
X	    !strcmp(buf, "=") || !strcmp(buf, "typedef") ||
X	    !strcmp(buf, "extern")) {
X		(void) skipit(buf, f);
X		goto again;
X	}
X	if (!dostatic && !strcmp(buf, "static")) oktoprint = 0;
X
X	/* For the benefit of compilers that allow "inline" declarations */
X	if (!strcmp(buf, "inline") && !sawsomething) continue;
X	if (!strcmp(buf, ";")) goto again;
X
X	/* A left parenthesis *might* indicate a function definition */
X	if (!strcmp(buf, "(")) {
X		if (!sawsomething || !(plist = getparamlist(f))) {
X			(void) skipit(buf, f);
X			goto again;
X		}
X		if (plist == ABORTED) goto again;
X
X		/* It seems to have been what we wanted */
X		if (oktoprint) emit(wlist, plist, startline);
X		word_free(plist);
X		goto again;
X	}
X	addword(wlist, buf);
X	if (!sawsomething) startline = symline;
X	sawsomething = 1;
X  }
X}
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  FILE *f, *g;
X  char *t;
X  char newname[40];
X
X  progname = argv[0];
X  argv++;
X  argc--;
X  g = stdout;
X
X  while (*argv && **argv == '-') {
X	t = *argv++;
X	--argc;
X	t++;
X	while (*t) {
X		if (*t == 's')
X			dostatic = 1;
X		else if (*t == 'n')
X			donum = 1;
X		else if (*t == 'p')
X			docond = 0;
X		else if (*t == 'P')
X			doold =1;
X		else if (*t == 'd') {
X			dodiff = 1;
X			docond = 0;
X			donum = 0;
X			dostatic = 1;
X		} else
X			Usage();
X		t++;
X	}
X  }
X
X  if (docond && doold) {
X	printf("#ifdef __STDC__\n");
X	printf("# define\tP(s) s\n");
X	printf("#else\n");
X	printf("# define P(s) ()\n");
X	printf("#endif\n\n");
X  }
X  if (argc == 0)
X	getdecl(stdin);
X  else
X	while (argc > 0 && *argv) {
X		if (!(f = fopen(*argv, "r"))) {
X			perror(*argv);
X			exit(EXIT_FAILURE);
X		}
X		if (dodiff) {
X			(void) sprintf(newname, "%sdif", *argv);
X			(void) fclose(g);
X			if (!(g = fopen(newname, "w"))) {
X				perror(newname);
X				exit(EXIT_FAILURE);
X			}
X		}
X		if (doold && dohead && !dodiff) printf("\n/* %s */\n", *argv);
X		linenum = 1;
X		newline_seen = 1;
X		glastc = ' ';
X		getdecl(f);
X		argc--;
X		argv++;
X		(void) fclose(f);
X	}
X  if (docond && doold) printf("\n#undef P\n");	/* clean up namespace */
X  (void) fclose(g);
X  return(EXIT_SUCCESS);
X}
X
X
Xvoid Usage()
X{
X  fputs("Usage: ", stderr);
X  fputs(progname, stderr);
X  fputs(" [-d][-n][-p][-s] [files ...]\n", stderr);
X  fputs("   -P: use P() style instead of _PROTOTYPE\n", stderr);
X  fputs("   -d: produce a diff file to prototype original source\n", stderr);
X  fputs("   -n: put line numbers of declarations as comments\n", stderr);
X  fputs("   -p: don't make header files readable by K&R compilers\n", stderr);
X  fputs("   -s: include declarations for static functions\n", stderr);
X  exit(EXIT_FAILURE);
X}
/
echo x - swapfs.c
sed '/^X/s///' > swapfs.c << '/'
X/* swapfs - swap a Minix file system	    Author: Niels C. Willems */
X
X
X/* $Id: swapfs.c,v 1.10 1992/04/15 10:51:46 ncwille Exp $ */
X
X/* Swapfs, a program to convert V1 or V2 Minix file systems from big endian
X   byte order to little endian and vv.
X
X   Some examples:
X   swapfs -v disk.01			! only show verbose information.
X   swapfs /dev/fd0 | compress > fd0r.Z	! convert and compress filesystem.
X   swapfs -v fileA fileA	! read, convert and write the same filesystem.
X
X  This program uses one byte of heap memory for each data block (1Kbytes)
X  in the file system, so with Minix-PC 16-bit you can't swap file systems
X  bigger than about 32 Mbytes
X
X  Be careful with 'swapfs fileA fileA'. If the program aborts e.g. by
X  user interrupt, power failure or an inconsistent file system, you
X  better have a backup of fileA
X
X  This program only converts directories and indirect blocks of files
X  that are in use. Converting indirect blocks or directories of deleted
X  files is hard and not yet done.
X
X  If you have a (1.6.xx, xx < 18) version of Minix that supports the
X  mounting of reversed file systems always mount them read-only and
X  avoid any attemp to modify them (mkdir, open, creat) too!
X  These problems have been fixed in Minix 1.6.18.
X
X  In this version you can get some more information about the
X  file system with the -d (debug) flag.
X
X      Please send your bug reports or ideas to ncwille@cs.vu.nl
X */
X
X
X#define _POSIX_SOURCE	1
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdlib.h>
X#include <fcntl.h>
X#include <string.h>
X#include <unistd.h>
X#include <stdio.h>
X
X#include <assert.h>
X
X#if __STDC__ == 1
X#define	_PROTOTYPE(function, params)	function params
X#else
X#define	_PROTOTYPE(function, params)	function()
X#endif
X
X#define BLOCK_SIZE	1024
X
X#define BOOT_BLOCK_OFF	   (blockn_t) 0
X#define SUPER_BLOCK_OFF    (blockn_t) 1
X
X#define V1_MAGIC		0x137F
X#define V2_MAGIC		0x2468
X#define NINODES_OFFSET		     0
X#define V1_ZONES_OFFSET		     2
X#define IMAP_BLOCKS_OFFSET	     4
X#define ZMAP_BLOCKS_OFFSET	     6
X#define FIRSTDATAZONE_OFFSET	     8
X#define LOG_ZONE_SIZE_OFFSET        10
X#define MAGIC_OFFSET		    16
X#define V2_ZONES_OFFSET		    20
X
X
X#define NR_DIRECT_ZONES	 7
X#define V1_NR_TZONES	 9
X#define V2_NR_TZONES	10
X#define V1_INODE_SIZE	32
X#define V2_INODE_SIZE	64
X
X#define INODE1_MODE_OFF		 0
X#define INODE1_SIZE_OFF		 4
X#define INODE1_DIRECT_OFF	14
X#define INODE1_IND1_OFF		28
X#define INODE1_IND2_OFF		30
X
X#define INODE2_MODE_OFF		 0
X#define INODE2_SIZE_OFF		 8
X#define INODE2_DIRECT_OFF	24
X#define INODE2_IND1_OFF		52
X#define INODE2_IND2_OFF		56
X#define INODE2_IND3_OFF		60
X
X#define INODE_MODE_MASK		0xf000	/* file type mask    */
X#define INODE_DIR_MODE		0x4000	/* directory         */
X#define INODE_BLK_SPECIAL_MODE	0x6000	/* block special     */
X#define INODE_CHR_SPECIAL_MODE  0x2000	/* character special */
X
X#define T_MASK		0x1c
X#define T_UNKNOWN	0x00
X#define T_MAYBE_OLD_DIR	0x04
X#define T_OLD_NON_DIR	0x08
X#define T_DIR		0x0c
X#define T_NON_DIR	0x10
X
X#define INDIRECT_MASK	0x03
X
X#define IND_PROCESSED_BIT 0x20	/* set when all blocks in ind block are
X			 * marked */
X#define IND_CONFLICT_BIT  0x40
X#define TYPE_CONFLICT_BIT 0x80
X
X#define DIR_ENTRY_SIZE    16
X
Xtypedef enum {
X  Unused_zone, Old_zone, In_use_zone
X} class_t;
X
Xtypedef unsigned long blockn_t;
Xtypedef unsigned int inodesn_t;
X
Xtypedef struct {
X  inodesn_t ninodes;		/* # usable inodes on the minor device */
X  blockn_t imap_blocks;		/* # of blocks used by inode bit map */
X  blockn_t zmap_blocks;		/* # of blocks used by zone bit map */
X  blockn_t firstdatazone;	/* number of first data zone */
X  int log_zone_size;		/* log2 of blocks/zone */
X  blockn_t zones;		/* number of zones */
X
X  int version;			/* file system version */
X  inodesn_t inodes_per_block;
X  blockn_t first_imap_block;
X  blockn_t first_zmap_block;
X  blockn_t first_inode_block;	/* number of first block with inodes */
X  size_t dzmap_size;		/* # of data zone blocks */
X} super_t;
X
X
Xtypedef struct {		/* summary of inode */
X  long size;			/* current file size in bytes */
X  blockn_t direct[NR_DIRECT_ZONES];	/* block numbers for direct,
X					 * ind, ... */
X  blockn_t ind1;		/* single indirect block number */
X  blockn_t ind2;		/* double indirect block number */
X  blockn_t ind3;		/* triple indirect block number */
X  int ztype;			/* type of zones that belong to this inode */
X} inode_t;
X
Xstatic char rcsid[] = "$Id: swapfs.c,v 1.10 1992/04/15 10:51:46 ncwille Exp $";
X
Xstatic int super_format[] = {2, 2, 2, 2, 2, 2, 4, 2, 2, 4, 0};
Xstatic int inode1_format[] = {2, 2, 4, 4, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0};
Xstatic int inode2_format[] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
X		      4, 4, 0};
X
Xstatic char *ind_str[4] = {"direct", "single indirect",
X		   "double indirect", "triple indirect"};
X
Xstatic int big_endian_fs;	/* set in init_super(), 1 iff file system has
X			 * big endian byte order */
Xstatic int verbose_flag;
Xstatic int debug_flag;
Xstatic int test_flag;
X
Xtypedef unsigned char *dzmap_t;
X
X
Xint _PROTOTYPE(main, (int argc, char *argv[]));
Xstatic void _PROTOTYPE(parse_args_init_io, (int argc, char *argv[]));
Xstatic void _PROTOTYPE(rw_boot, (void));
Xstatic void _PROTOTYPE(rw_init_super, (super_t * sp));
Xstatic void _PROTOTYPE(init_dzmap, (dzmap_t * dzmap_ptr, size_t dzmap_size));
Xstatic void _PROTOTYPE(rw_ibmap, (super_t super));
Xstatic void _PROTOTYPE(rw_zbmap, (super_t super));
Xstatic void _PROTOTYPE(print_stat, (dzmap_t dzmap, super_t super));
Xstatic void _PROTOTYPE(p1_rw_inodes, (dzmap_t dzmap, super_t super));
Xstatic void _PROTOTYPE(rd_indirects, (dzmap_t dzmap, super_t super, int ind,
X			       class_t required_class));
Xstatic void _PROTOTYPE(rw_data_zones, (dzmap_t dzmap, super_t super));
X
Xstatic int _PROTOTYPE(read_block, (char *buf, blockn_t offset));
Xstatic void _PROTOTYPE(write_block, (char *buf));
Xstatic int _PROTOTYPE(convcpy, (char *dst, char *src, int *format));
Xstatic void _PROTOTYPE(conv2_blkcpy, (char *dst, char *src));
Xstatic void _PROTOTYPE(conv4_blkcpy, (char *dst, char *src));
Xstatic void _PROTOTYPE(conv2cpy, (char *dst, char *src));
Xstatic int _PROTOTYPE(inode_size, (int version));
X
Xstatic void _PROTOTYPE(init_super, (super_t * sp, char *buf));
Xstatic void _PROTOTYPE(get_inode, (inode_t * ip, char *buf, int version));
Xstatic int _PROTOTYPE(check_inode, (inode_t inode, super_t super));
Xstatic int _PROTOTYPE(was_blk_special, (inode_t inode));
Xstatic int _PROTOTYPE(check_blk_number, (blockn_t num, super_t super));
Xstatic void _PROTOTYPE(cw_inode_block, (char *buf, inodesn_t ninodes,
X				 int version));
Xstatic void _PROTOTYPE(proc_ind, (dzmap_t dzmap, size_t curr_ind,
X			   char *buf, super_t super));
Xstatic void _PROTOTYPE(cw_dir_block, (char *buf));
Xstatic void _PROTOTYPE(dzmap_add_inode, (dzmap_t dzmap, inode_t inode,
X				  super_t super));
Xstatic void _PROTOTYPE(dz_update, (dzmap_t dzmap, blockn_t blknum,
X		     int new_indnum, int new_ztype, super_t super));
Xstatic class_t _PROTOTYPE(ztype_class, (int ztype));
X
Xstatic unsigned int _PROTOTYPE(two_bytes, (char buf[2]));
Xstatic long _PROTOTYPE(four_bytes, (char buf[4]));
X
Xstatic void _PROTOTYPE(fail, (char *string));
Xstatic void _PROTOTYPE(usage, (char *arg0));
X
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  super_t super;
X  dzmap_t dzmap;
X
X  parse_args_init_io(argc, argv);
X  rw_boot();
X  rw_init_super(&super);
X  init_dzmap(&dzmap, super.dzmap_size);
X  rw_ibmap(super);
X  rw_zbmap(super);
X  p1_rw_inodes(dzmap, super);
X
X  rd_indirects(dzmap, super, 3, In_use_zone);
X  rd_indirects(dzmap, super, 2, In_use_zone);
X  rd_indirects(dzmap, super, 1, In_use_zone);
X  if (verbose_flag) putc('\n', stderr);
X
X  print_stat(dzmap, super);
X  rw_data_zones(dzmap, super);
X  return 0;
X}
X
X
Xstatic void parse_args_init_io(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  char *str;
X  struct stat buf;
X  ino_t src_ino;
X  int i;
X
X  debug_flag = 0;
X  verbose_flag = 0;
X  test_flag = 0;
X
X  for (i = 1; i < argc; i++) {
X	str = argv[i];
X	if (*str != '-') break;
X	switch (*++str) {
X	    case 'v':	verbose_flag = 1;	break;
X	    case 'd':
X		debug_flag = 1;
X		verbose_flag = 1;
X		break;
X	    case 't':	test_flag = 1;	break;
X	    default:	usage(argv[0]);
X	}
X  }
X  if ((argc - i == 0 && isatty(0)) || (argc - i) > 2) usage(argv[0]);
X
X  if (argc - i > 0) {
X	(void) close(0);
X	if (open(argv[i], O_RDONLY) != 0) {
X		fprintf(stderr, "Can't open input file %s", argv[i]);
X		fail("");
X	}
X  }
X  if (isatty(1) || argc - i == 2) {
X	if (argc - i < 2)
X		test_flag = 1;
X	else {
X		i++;
X		(void) close(1);
X		(void) fstat(0, &buf);
X		src_ino = buf.st_ino;
X		if (stat(argv[i], &buf) == 0 && src_ino == buf.st_ino) {
X			/* Src and dest are the same */
X			if (open(argv[i], O_WRONLY) != 1) {
X				fprintf(stderr, "Can't open output file %s", argv[i]);
X				fail("");
X			}
X		} else if (creat(argv[i], 0644) != 1) {
X			fprintf(stderr, "Can't creat output file %s", argv[i]);
X			fail("");
X		}
X	}
X  }
X}
X
X
Xstatic void rw_boot()
X{
X  char buf[BLOCK_SIZE];
X
X  if (read_block(buf, BOOT_BLOCK_OFF) != BLOCK_SIZE)
X	fail("Can't read bootblock");
X  write_block(buf);
X}
X
X
Xstatic void rw_init_super(sp)
Xsuper_t *sp;
X{
X  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
X
X  if (read_block(ibuf, SUPER_BLOCK_OFF) != BLOCK_SIZE)
X	fail("Can't read superblock");
X
X  init_super(sp, ibuf);
X
X  memcpy(obuf, ibuf, (size_t) BLOCK_SIZE);	/* preserve 'unused' data */
X  (void) convcpy(obuf, ibuf, super_format);
X
X  write_block(obuf);
X}
X
X
Xstatic void init_dzmap(dzmap_ptr, dzmap_size)
Xdzmap_t *dzmap_ptr;
Xsize_t dzmap_size;
X{
X  if ((*dzmap_ptr = (dzmap_t) malloc(dzmap_size)) == (dzmap_t) NULL)
X	fail("Not enough space for data zone map");
X  memset(*dzmap_ptr, '\0', (size_t) dzmap_size);
X}
X
X
Xstatic void rw_ibmap(super)
Xsuper_t super;
X{
X  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
X  blockn_t i;
X
X  for (i = 0; i < super.imap_blocks; i++) {
X	if (read_block(ibuf, super.first_imap_block + i) != BLOCK_SIZE)
X		fail("Can't read inode bit map");
X	conv2_blkcpy(obuf, ibuf);
X	write_block(obuf);
X  }
X}
X
X
Xstatic void rw_zbmap(super)
Xsuper_t super;
X{
X  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
X  blockn_t i;
X
X  for (i = 0; i < super.zmap_blocks; i++) {
X	if (read_block(ibuf, super.first_zmap_block + i) != BLOCK_SIZE)
X		fail("Can't read zone bit map");
X	conv2_blkcpy(obuf, ibuf);
X	write_block(obuf);
X  }
X}
X
X
Xstatic void p1_rw_inodes(dzmap, super)
Xdzmap_t dzmap;
Xsuper_t super;
X{
X  char buf[BLOCK_SIZE], *buf_ptr;
X  inodesn_t i, num_inodes;
X  blockn_t next_block;
X  inode_t inode;
X
X
X  next_block = super.first_inode_block;
X
X  for (i = 1; i <= super.ninodes; i++) {
X	if ((i - 1) % super.inodes_per_block == 0) {
X		if (read_block(buf, next_block) != BLOCK_SIZE)
X			fail("read failed in inode block");
X		buf_ptr = buf;
X		next_block++;
X		num_inodes = super.ninodes + 1 - i;
X		if (num_inodes > super.inodes_per_block)
X			num_inodes = super.inodes_per_block;
X		cw_inode_block(buf, num_inodes, super.version);
X	}
X	get_inode(&inode, buf_ptr, super.version);
X	dzmap_add_inode(dzmap, inode, super);
X	buf_ptr += inode_size(super.version);
X  }
X}
X
X
Xstatic void print_stat(dzmap, super)
Xdzmap_t dzmap;
Xsuper_t super;
X{
X  size_t i;
X  register unsigned char dz;
X  int both_conflict = 0, ind_conflict = 0, type_conflict = 0, unreferenced = 0;
X  int not_in_use = 0;
X
X  if (!verbose_flag) return;
X
X  for (i = 0; i < super.dzmap_size; i++) {
X	dz = dzmap[i];
X	if (dz & IND_CONFLICT_BIT && dz & TYPE_CONFLICT_BIT)
X		both_conflict++;
X	else if (dz & IND_CONFLICT_BIT)
X		ind_conflict++;
X	else if (dz & TYPE_CONFLICT_BIT)
X		type_conflict++;
X
X	if (dz == 0) unreferenced++;
X	if (ztype_class(dz & T_MASK) < In_use_zone) not_in_use++;
X
X  }
X  if (debug_flag) {
X	fprintf(stderr, "%5d zone blocks with conflicting indir.\n",
X		ind_conflict);
X	fprintf(stderr, "%5d zone blocks with conflicting types.\n",
X		type_conflict);
X	fprintf(stderr, "%5d zone blocks with conflicting types and indir.\n",
X		both_conflict);
X	fprintf(stderr, "%5d zone blocks never referenced.\n", unreferenced);
X  }
X  fprintf(stderr, "%5d zone blocks not in use.\n", not_in_use);
X  putc('\n', stderr);
X}
X
X
Xstatic void rd_indirects(dzmap, super, ind, required_class)
Xdzmap_t dzmap;
Xsuper_t super;
Xint ind;
Xclass_t required_class;
X{
X  size_t i;
X  int ind_cnt;
X  off_t dz_offset;
X  char buf[BLOCK_SIZE];
X
X  dz_offset = super.firstdatazone;
X  ind_cnt = 0;
X  for (i = 0; i < super.dzmap_size; i++) {
X	if (ztype_class(dzmap[i] & T_MASK) != required_class ||
X	    (dzmap[i] & INDIRECT_MASK) != ind ||
X	    (dzmap[i] & IND_PROCESSED_BIT))
X		continue;
X
X	ind_cnt++;
X	if (read_block(buf, dz_offset + i) != BLOCK_SIZE) {
X		fprintf(stderr, "Can't read %s block", ind_str[ind]);
X		fail("");
X	}
X	proc_ind(dzmap, i, buf, super);
X  }
X  if ((verbose_flag && ind_cnt > 0) || debug_flag)
X	fprintf(stderr, "%5d %s zone blocks.\n", ind_cnt, ind_str[ind]);
X}
X
X
Xstatic void rw_data_zones(dzmap, super)
Xdzmap_t dzmap;
Xsuper_t super;
X{
X  char ibuf[BLOCK_SIZE], obuf[BLOCK_SIZE];
X  size_t i;
X  int ztype, ind, last_read;
X  off_t dz_offset;
X
X  dz_offset = super.firstdatazone;
X  for (i = 0; i < super.dzmap_size; i++) {
X	last_read = read_block(ibuf, dz_offset + i);
X	if (last_read != BLOCK_SIZE) break;
X
X	ind = dzmap[i] & INDIRECT_MASK;
X	if (ind == 0) {
X		ztype = dzmap[i] & T_MASK;
X		if (ztype == T_DIR)
X			cw_dir_block(ibuf);
X		else
X			write_block(ibuf);
X	} else {
X		if (super.version == 1)
X			conv2_blkcpy(obuf, ibuf);
X		else
X			conv4_blkcpy(obuf, ibuf);
X		write_block(obuf);
X	}
X	if (verbose_flag && i && i % 1024 == 0) {
X		fprintf(stderr, ".");
X		fflush(stderr);
X	}
X  }
X  if (verbose_flag && i > 1024) putc('\n', stderr);
X
X  if (last_read != BLOCK_SIZE) for (; i < super.dzmap_size; i++)
X		if (ztype_class(dzmap[i] & T_MASK) == In_use_zone)
X			fail("Can't read data zone");
X}
X
X
Xstatic int read_block(buf, offset)
Xchar *buf;
Xblockn_t offset;
X{
X  static blockn_t curr_offset = 0;
X  int bytes;
X
X  if (offset != curr_offset) {
X	if (lseek(0, (off_t) offset * BLOCK_SIZE, 0) == -1)
X		fail("lseek failed on input file");
X	curr_offset = offset;
X  }
X  bytes = read(0, buf, BLOCK_SIZE);
X  if (bytes < 0) fail("read failed on input file");
X
X  curr_offset += bytes;
X
X  return bytes;
X}
X
X
Xstatic void write_block(buf)
Xchar *buf;
X{
X  if (test_flag) return;
X
X  if (write(1, buf, BLOCK_SIZE) != BLOCK_SIZE)
X	fail("write failed on output file");
X}
X
X
Xstatic int convcpy(dst, src, format)
Xchar *dst;
Xchar *src;
Xint *format;
X{
X  char *old_src = src;
X  register char tmp;
X  int i;
X
X  for (i = 0; format[i] > 0; i++) {
X	switch (format[i]) {
X	    case 1:	*dst++ = *src++;	break;
X	    case 2:
X		tmp = *src++;
X		*dst++ = *src++;
X		*dst++ = tmp;
X		break;
X	    case 4:
X		tmp = src[0];
X		dst[0] = src[3];
X		dst[3] = tmp;
X		tmp = src[1];
X		dst[1] = src[2];
X		dst[2] = tmp;
X		src += 4;
X		dst += 4;
X		break;
X	    default:
X		fail("wrong format array for convcpy");
X	}
X  }
X  return(src - old_src);
X}
X
X
Xstatic void conv2_blkcpy(dst, src)
Xchar *dst;
Xchar *src;
X{
X  int i;
X  register char tmp;
X
X  for (i = 0; i < BLOCK_SIZE; i += 2) {
X	tmp = *src++;
X	*dst++ = *src++;
X	*dst++ = tmp;
X  }
X}
X
X
Xstatic void conv4_blkcpy(dst, src)
Xchar *dst;
Xchar *src;
X{
X  int i;
X  register char tmp;
X
X  for (i = 0; i < BLOCK_SIZE; i += 4) {
X	tmp = src[0];
X	dst[0] = src[3];
X	dst[3] = tmp;
X
X	tmp = src[1];
X	dst[1] = src[2];
X	dst[2] = tmp;
X
X	src += 4;
X	dst += 4;
X  }
X}
X
X
Xstatic void conv2cpy(dst, src)
Xchar *dst;
Xchar *src;
X{
X  register char tmp;
X  tmp = *src++;
X  *dst++ = *src++;
X  *dst++ = tmp;
X}
X
X
Xstatic int inode_size(version)
Xint version;
X{
X  return(version == 1) ? V1_INODE_SIZE : V2_INODE_SIZE;
X}
X
X
Xstatic void init_super(sp, buf)
Xsuper_t *sp;
Xchar *buf;
X{
X  int magic;
X  long imapblks, zmapblks;
X
X  big_endian_fs = 0;		/* guess the file system is little endian */
X  magic = two_bytes(buf + MAGIC_OFFSET);
X
X  if (magic != V1_MAGIC && magic != V2_MAGIC) {
X	big_endian_fs = 1;
X	magic = two_bytes(buf + MAGIC_OFFSET);
X  }
X  switch (magic) {
X      case V1_MAGIC:	sp->version = 1;	break;
X      case V2_MAGIC:	sp->version = 2;	break;
X      default:	fail("Not a Minix file system");
X}
X
X  if (verbose_flag) fprintf(stderr, "\nVersion = V%d, %s endian.\n",
X		sp->version, big_endian_fs ? "big" : "little");
X
X  sp->ninodes = two_bytes(buf + NINODES_OFFSET);
X  imapblks = two_bytes(buf + IMAP_BLOCKS_OFFSET);
X  sp->imap_blocks = imapblks;
X  zmapblks = two_bytes(buf + ZMAP_BLOCKS_OFFSET);
X  sp->zmap_blocks = zmapblks;
X  sp->firstdatazone = two_bytes(buf + FIRSTDATAZONE_OFFSET);
X  sp->log_zone_size = two_bytes(buf + LOG_ZONE_SIZE_OFFSET);
X
X  if (sp->version == 1)
X	sp->zones = two_bytes(buf + V1_ZONES_OFFSET);
X  else
X	sp->zones = four_bytes(buf + V2_ZONES_OFFSET);
X
X  sp->inodes_per_block = BLOCK_SIZE / inode_size(sp->version);
X
X  if (imapblks < 0 || zmapblks < 0 || sp->ninodes < 1 || sp->zones < 1)
X	fail("Bad superblock");
X
X
X  if (sp->log_zone_size != 0)
X	fail("Can't swap file systems with different zone and block sizes");
X
X  sp->first_imap_block = SUPER_BLOCK_OFF + 1;
X  sp->first_zmap_block = sp->first_imap_block + sp->imap_blocks;
X  sp->first_inode_block = sp->first_zmap_block + sp->zmap_blocks;
X
X  sp->dzmap_size = sp->zones - sp->firstdatazone;
X  if (verbose_flag) {
X	fprintf(stderr, "nzones = %ld, ", sp->zones);
X	fprintf(stderr, "ninodes = %u, ", sp->ninodes);
X	fprintf(stderr, "first data zone = %ld.\n\n", sp->firstdatazone);
X  }
X}
X
X
Xstatic void get_inode(ip, buf, version)
Xinode_t *ip;
Xchar *buf;
Xint version;
X{
X  int i;
X  int mode;
X
X  if (version == 1) {
X	mode = two_bytes(buf + INODE1_MODE_OFF);
X	ip->size = four_bytes(buf + INODE1_SIZE_OFF);
X	ip->ind1 = two_bytes(buf + INODE1_IND1_OFF);
X	ip->ind2 = two_bytes(buf + INODE1_IND2_OFF);
X	ip->ind3 = 0;
X	for (i = 0; i < NR_DIRECT_ZONES; i++)
X		ip->direct[i] = two_bytes(buf + INODE1_DIRECT_OFF + 2 * i);
X  } else {
X	mode = two_bytes(buf + INODE2_MODE_OFF);
X	ip->size = four_bytes(buf + INODE2_SIZE_OFF);
X	ip->ind1 = four_bytes(buf + INODE2_IND1_OFF);
X	ip->ind2 = four_bytes(buf + INODE2_IND2_OFF);
X	ip->ind3 = four_bytes(buf + INODE2_IND3_OFF);
X	for (i = 0; i < NR_DIRECT_ZONES; i++)
X		ip->direct[i] = four_bytes(buf + INODE2_DIRECT_OFF + 4 * i);
X  }
X
X  if (mode == 0) {
X	if (ip->size % DIR_ENTRY_SIZE == 0)
X		ip->ztype = T_MAYBE_OLD_DIR;
X	else
X		ip->ztype = T_OLD_NON_DIR;
X	if (was_blk_special(*ip)) ip->size = 0;
X  } else {
X	mode = mode & INODE_MODE_MASK;
X	if (mode == INODE_BLK_SPECIAL_MODE || mode == INODE_CHR_SPECIAL_MODE)
X		ip->size = 0;	/* prevent the use of the block numbers. */
X	ip->ztype = (mode == INODE_DIR_MODE) ? T_DIR : T_NON_DIR;
X  }
X}
X
X
Xstatic int check_inode(inode, super)
Xinode_t inode;
Xsuper_t super;
X{
X  int i;
X
X  for (i = 0; i < NR_DIRECT_ZONES; i++)
X	if (!check_blk_number(inode.direct[i], super)) return 0;
X
X  return(check_blk_number(inode.ind1, super) &&
X	check_blk_number(inode.ind2, super) &&
X	check_blk_number(inode.ind3, super));
X}
X
X
Xstatic int check_blk_number(num, super)
Xblockn_t num;
Xsuper_t super;
X{
X  if (num == 0 || (num >= super.firstdatazone && num < super.zones))
X	return 1;
X
X  fprintf(stderr, "warning bad block number %ld in inode.\n", num);
X  return 0;
X}
X
X
Xstatic int was_blk_special(inode)
Xinode_t inode;
X{
X  int i, result;
X  blockn_t block_size;
X
X  if (inode.size % BLOCK_SIZE || inode.ind1) return 0;
X  block_size = inode.size / BLOCK_SIZE;
X
X  for (i = NR_DIRECT_ZONES - 1; i >= 0; i--)
X	if (inode.direct[i] != 0) break;
X
X  result = (i < 1 && block_size > i + 1);
X
X  if (debug_flag && result) {
X	fprintf(stderr, "old block special file detected (slot = %d).\n", i);
X  }
X  return result;
X}
X
X
Xstatic void cw_inode_block(buf, ninodes, version)
Xchar *buf;
Xinodesn_t ninodes;
Xint version;
X{
X  char output_buf[BLOCK_SIZE];
X  char *src, *dst;
X  inodesn_t i;
X  int cnt, free_bytes;
X  int *format;
X
X  src = buf;
X  dst = output_buf;
X
X  format = (version == 1) ? inode1_format : inode2_format;
X  for (i = 0; i < ninodes; i++) {
X	cnt = convcpy(dst, src, format);
X	src += cnt;
X	dst += cnt;
X  }
X
X  assert(cnt == inode_size(version));
X
X  free_bytes = BLOCK_SIZE - (src - buf);
X  assert(free_bytes >= 0);
X  if (verbose_flag && free_bytes > 0) {
X	/* There is a small change that the last free inode has no
X	 * matching bit in the last inode bit map block: e.g. if
X	 * sp->ninodes == 8191. */
X	fprintf(stderr, "%5d bytes (%d inodes) free in last inode block.\n",
X		free_bytes, free_bytes / inode_size(version));
X	memcpy(dst, src, (size_t) free_bytes);
X  }
X  write_block(output_buf);
X}
X
X
Xstatic void proc_ind(dzmap, curr_ind, buf, super)
Xdzmap_t dzmap;
Xsize_t curr_ind;
Xchar *buf;
Xsuper_t super;
X{
X  int indnum, i, ztype;
X  int word_size;		/* size of zone block number in ind. block in
X			 * bytes */
X  unsigned char dz, tmp_dz;
X  blockn_t blk, ind_blk;
X  int bad_range = 0, hidden_zero = 0, zero_flag = 0, expired = 0;
X  size_t blk_index;
X
X  dz = dzmap[curr_ind];
X  indnum = dz & INDIRECT_MASK;
X  ztype = dz & T_MASK;
X  ind_blk = curr_ind + super.firstdatazone;
X
X  word_size = (super.version == 1) ? 2 : 4;
X  assert(indnum > 0);
X
X  for (i = 0; i < BLOCK_SIZE; i += word_size) {
X	if (word_size == 2)
X		blk = two_bytes(buf + i);
X	else
X		blk = four_bytes(buf + i);
X
X	if (blk == 0)
X		zero_flag = 1;
X	else if (blk < super.firstdatazone || blk >= super.zones)
X		bad_range = 1;
X	else {
X		if (zero_flag) hidden_zero = 1;
X		blk_index = blk - super.firstdatazone;
X		tmp_dz = dzmap[blk_index];
X		if (ztype_class(tmp_dz & T_MASK) == In_use_zone) expired = 1;
X	}
X
X  }
X
X  if (ztype_class(ztype) == In_use_zone) {
X	if (bad_range) {
X		fprintf(stderr, "%s zone block contains ", ind_str[indnum]);
X		fail("illegal value");
X	}
X	if ((ztype == T_DIR || indnum > 1) && hidden_zero) {
X		fprintf(stderr, "WARNING: %s zone block %ld contains ",
X			ind_str[indnum], ind_blk);
X		fprintf(stderr, "unexpected zero block numbers\n");
X	}
X  } else {
X	if (expired) {
X		dzmap[curr_ind] &= ~(INDIRECT_MASK & IND_CONFLICT_BIT);
X		return;
X	}
X
X	/* Not yet implemented. :-( if (bad_range || (indnum > 1 &&
X	 * hidden_zero) || equal_values(buf, super.version ) { } */
X  }
X
X  for (i = 0; i < BLOCK_SIZE; i += word_size) {
X	if (word_size == 2)
X		blk = two_bytes(buf + i);
X	else
X		blk = four_bytes(buf + i);
X
X	if (blk == 0) continue;
X	blk_index = blk - super.firstdatazone;
X	tmp_dz = dzmap[blk_index];
X	if (ztype_class(tmp_dz & T_MASK) == In_use_zone) {	/* trouble */
X		if ((tmp_dz & INDIRECT_MASK) == indnum - 1 &&
X		    (tmp_dz & T_MASK) == ztype)
X			fprintf(stderr, "WARNING: %s zone block %ld used more \
Xthan once\n", ind_str[indnum - 1], blk);
X		else {
X			fprintf(stderr, "Block %ld used more than ", blk);
X			fail("once with different types");
X		}
X	}
X	dzmap[blk_index] = (dz & ~INDIRECT_MASK) | (indnum - 1);
X  }
X  dzmap[curr_ind] |= IND_PROCESSED_BIT;
X}
X
X
Xstatic void cw_dir_block(buf)
Xchar *buf;
X{
X  char output_buf[BLOCK_SIZE];
X  int ino, i, old_ino_offset;
X
X  memcpy(output_buf, buf, BLOCK_SIZE);
X
X  for (i = 0; i < BLOCK_SIZE; i += DIR_ENTRY_SIZE) {
X	ino = two_bytes(buf + i);
X	if (ino == 0) {
X		old_ino_offset = i + DIR_ENTRY_SIZE - 2;
X		conv2cpy(output_buf + old_ino_offset, buf + old_ino_offset);
X	} else
X		conv2cpy(output_buf + i, buf + i);
X  }
X  write_block(output_buf);
X}
X
X
Xstatic void dzmap_add_inode(dzmap, inode, super)
Xdzmap_t dzmap;
Xinode_t inode;
Xsuper_t super;
X{
X  int i;
X
X  if (inode.size == 0 || !check_inode(inode, super)) return;
X
X  for (i = 0; i < NR_DIRECT_ZONES; i++)
X	dz_update(dzmap, inode.direct[i], 0, inode.ztype, super);
X
X  dz_update(dzmap, inode.ind1, 1, inode.ztype, super);
X  dz_update(dzmap, inode.ind2, 2, inode.ztype, super);
X  dz_update(dzmap, inode.ind3, 3, inode.ztype, super);
X}
X
X
Xstatic void dz_update(dzmap, blknum, new_indnum, new_ztype, super)
Xdzmap_t dzmap;
Xblockn_t blknum;
Xint new_indnum;
Xint new_ztype;
Xsuper_t super;
X{
X  size_t dznum;
X  int old_indnum;
X  int old_ztype;
X  unsigned char *dz;
X  char new_dz;
X
X
X  if (blknum == 0) return;
X
X  dznum = (size_t) (blknum - super.firstdatazone);
X
X  dz = &dzmap[dznum];
X  old_indnum = *dz & INDIRECT_MASK;
X  old_ztype = *dz & T_MASK;
X
X  new_dz = new_ztype | new_indnum;
X
X  if (ztype_class(new_ztype) > ztype_class(old_ztype)) {
X	*dz = new_dz;
X	return;
X  } else if (ztype_class(new_ztype) < ztype_class(old_ztype))
X	return;
X
X  /* Collision: old and new have the same class */
X
X  if (ztype_class(old_ztype) == In_use_zone) {	/* trouble */
X	if (new_indnum == old_indnum && new_ztype == old_ztype) {
X		fprintf(stderr, "WARNING: file system corrupt, zone block %ld \
Xis used more than once.\n", blknum);
X		return;
X	}
X	fprintf(stderr, "ERROR: file system corrupt, zone block %ld is used \
Xmore than once.\n", blknum);
X	fail("Can't determine its type");
X  }
X  assert(ztype_class(old_ztype) == Old_zone);
X
X
X  if (new_indnum != old_indnum) {
X	*dz |= IND_CONFLICT_BIT;
X	if (new_indnum > old_indnum) {
X		*dz &= ~INDIRECT_MASK;
X		*dz |= new_indnum;
X	}
X  }
X  if (new_ztype == T_MAYBE_OLD_DIR || old_ztype == T_MAYBE_OLD_DIR) {
X	*dz |= TYPE_CONFLICT_BIT;
X	*dz &= ~T_MASK;
X	*dz |= T_MAYBE_OLD_DIR;
X  }
X}
X
X
Xstatic class_t ztype_class(ztype)
Xint ztype;
X{
X  class_t class;
X
X  if (ztype == T_MAYBE_OLD_DIR || ztype == T_OLD_NON_DIR)
X	class = Old_zone;
X  else if (ztype == T_DIR || ztype == T_NON_DIR)
X	class = In_use_zone;
X  else
X	class = Unused_zone;
X
X  return class;
X}
X
X
Xstatic void fail(str)
Xchar *str;
X{
X  fprintf(stderr, "%s\n", str);
X  exit(1);
X}
X
X
Xstatic unsigned int two_bytes(buf)
Xchar buf[2];
X{
X  unsigned char *ubuf = (unsigned char *) buf;
X
X  if (big_endian_fs)
X	return(ubuf[0] << 8) | ubuf[1];
X  else
X	return(ubuf[1] << 8) | ubuf[0];
X}
X
X
Xstatic long four_bytes(buf)
Xchar buf[4];
X{
X  unsigned char *ubuf = (unsigned char *) buf;
X  register int r1, r2;
X
X  if (big_endian_fs) {
X	r1 = (ubuf[0] << 8) | ubuf[1];
X	r2 = (ubuf[2] << 8) | ubuf[3];
X  } else {
X	r2 = (ubuf[1] << 8) | ubuf[0];
X	r1 = (ubuf[3] << 8) | ubuf[2];
X  }
X  return((long) r1 << 16) | r2;
X}
X
X
Xstatic void usage(arg0)
Xchar *arg0;
X{
X  fprintf(stderr, "usage: %s [-v] srcfs [destfs]\n", arg0);
X  exit(2);
X}
/
echo x - term.c
sed '/^X/s///' > term.c << '/'
X/* term - terminal simulator		Author: Andy Tanenbaum */
X
X/* This program allows the user to turn a MINIX system into a dumb
X * terminal to communicate with a remote computer through one of the ttys.
X * It forks into two processes.  The parent sits in a tight loop copying
X * from stdin to the tty.  The child sits in a tight loop copying from
X * the tty to stdout.
X *
X * 2 Sept 88 BDE (Bruce D. Evans): Massive changes to make current settings the
X * default, allow any file as the "tty", support fancy baud rates and remove
X * references to and dependencies on modems and keyboards, so (e.g.)
X * a local login on /dev/tty1 can do an external login on /dev/tty2.
X *
X * 3 Sept 88 BDE: Split parent again to main process copies from stdin to a
X * pipe which is copied to the tty.  This stops a blocked write to the
X * tty from hanging the program.
X *
X * 11 Oct 88 BDE: Cleaned up baud rates and parity stripping.
X *
X * 09 Oct 90 MAT (Michael A. Temari): Fixed bug where terminal isn't reset
X * if an error occurs.
X *
X * Nov 90 BDE: Don't broadcast kill(0, SIGINT) since two or more of these
X * in a row will kill the parent shell.
X *
X * 19 Oct 89 RW (Ralf Wenk): Adapted to MINIX ST 1.1 + RS232 driver. Split
X * error into error_n and error. Added resetting of the terminal settings
X * in error.
X *
X * 24 Nov 90 RW: Adapted to MINIX ST 1.5.10.2. Forked processes are now
X * doing an exec to get a better performance. This idea is stolen from
X * a terminal program written by Felix Croes.
X *
X * 01 May 91 RW: Merged the MINIX ST patches with Andys current version.
X * Most of the 19 Oct 89 patches are deleted because they are already there.
X *
X * Example usage:
X *	term			: baud, bits/char, parity from /dev/tty1
X *	term 9600 7 even	: 9600 baud, 7 bits/char, even parity
X *	term odd 300 7		:  300 baud, 7 bits/char, odd parity
X *	term /dev/tty2		: use /dev/tty2 rather than /dev/tty1
X *				: Any argument starting with "/" is
X *				: taken as the communication device.
X */
X
X#include <sys/types.h>
X#include <minix/config.h>
X#include <fcntl.h>
X#include <sgtty.h>
X#include <signal.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X
X#define MAXARGS  3		/* maximum number of uart params */
X#define CHUNK 1024		/* how much to read at once */
X
X/* Hack some new baud rates for Minix. Minix uses a divide-by-100 encoding. */
X#define B200     2
X#define B600     6
X#define B1800   18
X#define B3600   36
X#define B7200   72
X#define B19200 192
X#define EXTA   192
X
X/* We can't handle some standard (slow) V7 speeds and speeds above 25500 since
X * since the speed is packed into a char :-(. Trap them with an illegal value.
X */
X#define B50      0
X#define B75      0
X#define B134     0
X#define EXTB     0
X#ifndef B38400
X#define B38400   0
X#endif
X#ifndef B57600
X#define B57600   0
X#endif
X#ifndef B115200
X#define B115200  0
X#endif
X
X#define TERM_LINE "/dev/tty1"	/* which serial port to use */
X
Xint commfd;			/* open file no. for comm device */
Xint readpid;			/* pid of child reading commfd */
Xstruct sgttyb sgcommfd;		/* saved terminal parameters for commfd */
Xstruct sgttyb sgstdin;		/* saved terminal parameters for stdin */
Xint writepid;			/* pid of child writing commfd */
X
X/* Sequence to leave simulator.  It must arrive in a single read. */
X#if (MACHINE == ATARI)
X#if 0
Xchar endseq[] = "\033OY";	/* 'F10' (pre 1.6.20) */
X#endif
Xchar endseq[] = "\033[20~";	/* 'F10' */
X#endif
X#if (CHIP == INTEL)
X#if 0
Xchar endseq[] = "\005";		/* Ctrl-E (if no numeric keypad) */
X#endif
Xchar endseq[] = "\033[G";	/* numeric keypad '5' */
X#endif
X
Xstruct param_s {
X  char *pattern;
X  int value;
X  char type;
X#define BAD      0
X#define BITS     1
X#define NOSTRIP  2
X#define PARITY   3
X#define SPEED    4
X}
X
X params[] =
X{
X  "5", BITS5, BITS,
X  "6", BITS6, BITS,
X  "7", BITS7, BITS,
X  "8", BITS8, BITS,
X
X  "even", EVENP, PARITY,
X  "odd", ODDP, PARITY,
X  "nostrip", 0, NOSTRIP,
X
X  "50", B50, SPEED,
X  "75", B75, SPEED,
X  "110", B110, SPEED,
X  "134", B134, SPEED,
X  "200", B200, SPEED,
X  "300", B300, SPEED,
X  "600", B600, SPEED,
X  "1200", B1200, SPEED,
X  "1800", B1800, SPEED,
X  "2400", B2400, SPEED,
X  "3600", B3600, SPEED,
X  "4800", B4800, SPEED,
X  "7200", B7200, SPEED,
X  "9600", B9600, SPEED,
X  "19200", B19200, SPEED,
X  "EXTA", EXTA, SPEED,
X  "EXTB", EXTB, SPEED,
X  "38400", B38400, SPEED,
X  "57600", B57600, SPEED,
X  "115200", B115200, SPEED,
X  "", 0, BAD,			/* BAD type to end list */
X};
Xunsigned char strip_parity = 1;	/* nonzero to strip high bits before output */
X
X_PROTOTYPE(int main, (int argc, char *argv[]));
X_PROTOTYPE(void set_uart, (int argc, char *argv[]));
X_PROTOTYPE(void set_mode, (int fd, int speed, int parity, int bits,
X			   struct sgttyb * sgsavep));
X_PROTOTYPE(void copy, (int in, char *inname, int out,char *outname,char *end));
X_PROTOTYPE(void error, (char *s1, char *s2));
X_PROTOTYPE(void quit, (int dummy));
X_PROTOTYPE(void write2sn, (char *s1, char *s2));
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  char *commdev = (char *) NULL;
X  int i;
X  int pipefd[2];
X#if ( CHIP == M68000 )
X  char in[2], out[2];
X  in[1] = out[1] = '\0';
X
X/* Ugly way to process both hidden special arguments "read" or "write" early
X * enough. If one of the special arguments is given the other arguments are
X * ASCII values used by the copy() function. File descriptors are encoded
X * as characters starting with '0'.
X */
X  if (argc > 1 &&
X      (strcmp(argv[1], "-read") == 0 || strcmp(argv[1], "-write") == 0))
X	copy(*argv[2] - '0', argv[3], *argv[4] - '0', argv[5], argv[6]);
X#endif
X
X  sync();
X  for (i = 1; i < argc; ++i)
X	if (argv[i][0] == '/') {
X		if (commdev != (char *) NULL) {
X			write2sn("Too many communication devices", "");
X			exit(1);
X		}
X		commdev = argv[i];
X	}
X  if (commdev == (char *) NULL) {
X	i = MAXARGS + 1;
X	commdev = TERM_LINE;
X  } else
X	i = MAXARGS + 2;
X  if (argc > i) {
X	write2sn("Usage: term [baudrate] [data_bits] [parity]", "");
X	exit(1);
X  }
X  commfd = open(commdev, O_RDWR);
X  if (commfd < 0) {
X	write2sn("Can't open ", commdev);
X	exit(1);
X  }
X
X  /* Save state of both devices before altering either (may be identical!). */
X  ioctl(0, TIOCGETP, &sgstdin);
X  ioctl(commfd, TIOCGETP, &sgcommfd);
X  set_mode(0, -1, -1, -1, &sgstdin);	/* RAW mode on stdin, others
X					 * current */
X  set_uart(argc, argv);
X
X  /* Main body of the terminal simulator. */
X  signal(SIGINT, quit);
X  signal(SIGPIPE, quit);
X  if (pipe(pipefd) < 0) error("Can't create pipe", "");
X  switch ((writepid = fork())) {
X      case -1:
X	error("Can't create process to write to comm device", "");
X      case 0:
X	/* Piped stdin to tty */
X	close(pipefd[1]);
X#if (CHIP == M68000)
X	in[0] = '0' + pipefd[0];
X	out[0] = '0' + commfd;
X	execlp(argv[0], argv[0], "-write", in, "piped stdin", out, commdev, "",
X	       (char *) NULL);
X	/* If execlp() failed, try the usual way. */
X#endif
X	copy(pipefd[0], "piped stdin", commfd, commdev, "");
X  }
X  close(pipefd[0]);
X  switch ((readpid = fork())) {
X      case -1:
X	error("Can't create process to read from comm device", "");
X      case 0:
X	/* Tty to stdout */
X#if (CHIP == M68000)
X	in[0] = '0' + commfd;
X	out[0] = '0' + 1;
X	execlp(argv[0], argv[0], "-read", in, commdev, out, "stdout", "",
X	       (char *) NULL);
X	/* If execlp() failed, try the usual way. */
X#endif
X	copy(commfd, commdev, 1, "stdout", "");
X  }
X
X  /* Stdin to pipe */
X  copy(0, "stdin", pipefd[1], "redirect stdin", endseq);
X  return(0);
X}
X
X
Xvoid set_uart(argc, argv)
Xint argc;
Xchar *argv[];
X{
X/* Set up the UART parameters. */
X
X  int i, j, bits, nbits, parity, nparities, speed, nspeeds;
X  char *arg;
X  register struct param_s *param;
X
X  /* Examine all the parameters and check for validity. */
X  nspeeds = nparities = nbits = 0;
X  speed = parity = bits = -1;	/* -1 means use current value */
X  for (i = 1; i < argc; ++i) {
X	if ((arg = argv[i])[0] == '/') continue;
X
X	/* Check parameter for legality. */
X	for (j = 0, param = &params[0];
X	     param->type != BAD && strcmp(arg, param->pattern) != 0;
X	     ++j, ++param);
X	switch (param->type) {
X	    case BAD:
X		error("Invalid parameter: ", arg);
X	    case BITS:
X		bits = param->value;
X		if (++nbits > 1) error("Too many character sizes", "");
X		break;
X	    case PARITY:
X		parity = param->value;
X		if (++nparities > 1) error("Too many parities", "");
X		break;
X	    case SPEED:
X		speed = param->value;
X		if (speed == 0) error("Invalid speed: ", arg);
X		if (++nspeeds > 1) error("Too many speeds", "");
X		break;
X	    case NOSTRIP:	strip_parity = 0;	break;
X	}
X  }
X  set_mode(commfd, speed, parity, bits, &sgcommfd);
X}
X
X
Xvoid set_mode(fd, speed, parity, bits, sgsavep)
Xint fd;
Xint speed;
Xint parity;
Xint bits;
Xstruct sgttyb *sgsavep;
X{
X  /* Set open file fd to RAW mode with the given other modes. If fd is
X   * not a tty, this may do nothing but connecting ordinary files as
X   * ttys may have some use. */
X
X  struct sgttyb sgtty;
X  int tabs;
X
X  sgtty = *sgsavep;
X  tabs = sgtty.sg_flags & XTABS;
X  if (speed == -1) speed = sgtty.sg_ispeed;
X  if (parity == -1) parity = sgtty.sg_flags & (EVENP | ODDP);
X  if (bits == -1)
X	bits = sgtty.sg_flags & BITS8;	/* BITS8 is actually a mask */
X  sgtty.sg_ispeed = speed;
X  sgtty.sg_ospeed = speed;
X  sgtty.sg_flags = RAW | parity | bits | tabs;
X  ioctl(fd, TIOCSETP, &sgtty);
X}
X
X
Xvoid copy(in, inname, out, outname, end)
Xint in;
Xchar *inname;
Xint out;
Xchar *outname;
Xchar *end;
X{
X/* Copy from one open file to another. If the 'end' sequence is not "", and
X * precisely matches the input, terminate the copy and various children.
X * The end sequence is best provided by keyboard input from one of the
X * special keys which always produces chars in a bunch. RAW mode almost
X * guarantees exactly one keystroke's worth of input at a time.
X */
X
X  static char buf[CHUNK];
X  char *bufend;
X  register char *bufp;
X  int count;
X  int len;
X
X  len = strlen(end);
X  while (1) {
X	if ((count = read(in, buf, CHUNK)) <= 0) {
X		write2sn("Can't read from ", inname);
X		quit(0);
X	}
X	if (count == len && strncmp(buf, end, (size_t) count) == 0) quit(0);
X	if (strip_parity) for (bufp = buf, bufend = bufp + count;
X		     bufp < bufend; ++bufp)
X			*bufp &= 0x7F;
X	if (write(out, buf, (size_t) count) != count) {
X		write2sn("Can't write to ", outname);
X		quit(0);
X	}
X  }
X}
X
X
Xvoid error(s1, s2)
Xchar *s1;
Xchar *s2;
X{
X  ioctl(commfd, TIOCSETP, &sgcommfd);
X  ioctl(0, TIOCSETP, &sgstdin);
X  write2sn(s1, s2);
X  exit(1);
X}
X
X
Xvoid quit(s)
Xint s;				/* not used, just to make prototype ok */
X{
X  if (readpid != 0 && writepid != 0) {
X	/* This is the parent of the other two processes.  It cleans up. */
X	ioctl(commfd, TIOCSETP, &sgcommfd);
X	ioctl(0, TIOCSETP, &sgstdin);
X	kill(readpid, SIGINT);
X	kill(writepid, SIGINT);
X  }
X  exit(0);
X}
X
X
Xvoid write2sn(s1, s2)
Xchar *s1;
Xchar *s2;
X{
X  write(1, s1, strlen(s1));
X  write(1, s2, strlen(s2));
X  write(1, "\r\n", 2);
X}
/
echo x - uname.c
sed '/^X/s///' > uname.c << '/'
X/*  uname - print system name			Author: Earl Chew */
X
X/* The system name is printed based on the file /etc/uname. This should be
X * world readable but only writeable by system administrators. The
X * file contains lines of text. Lines beginning with # are treated
X * as comments. All other lines contain information to be read into
X * the uname structure. The sequence of the lines matches the sequence
X * in which the structure components are declared:
X *
X *	system name		Minix
X *	node name		waddles
X *	release name		1.5
X *	version			10
X *	machine name		IBM_PC
X *	serial number		N/A
X */
X
X#include <sys/types.h>
X#include <sys/utsname.h>
X#include <stdarg.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X
X/* Define the uname components. */
X#define ALL	 ((unsigned) ~0x0)
X#define SYSNAME  ((unsigned) 0x01)
X#define NODENAME ((unsigned) 0x02)
X#define RELEASE  ((unsigned) 0x04)
X#define VERSION  ((unsigned) 0x08)
X#define MACHINE  ((unsigned) 0x10)
X
X_PROTOTYPE(int main, (int argc, char **argv ));
X_PROTOTYPE(void print, (int fd, ... ));
X_PROTOTYPE(void usage, (void ));
X
X#ifdef __STDC__
Xvoid print(int fd, ...)
X#else
Xvoid print(fd)
Xint fd;
X#endif
X{
X/* Print a sequence of strings onto the named channel. */
X  va_list argp;
X  char *p;
X
X  va_start(argp, fd);
X  while (1) {
X	p = va_arg(argp, char *);
X	if (p == (char *) NULL) break;
X	write(fd, p, strlen(p));
X  }
X  va_end(argp);
X}
X
Xvoid usage()
X{
X  print(STDERR_FILENO, "Usage: uname -amnrsv\n", (char *) NULL);
X  exit(EXIT_FAILURE);
X}
X
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X  int info;
X  char *p;
X  struct utsname un;
X
X  for (info = 0; argc > 1; argc--, argv++) {
X  	if (argv[1][0] == '-') {
X  		for (p = &argv[1][1]; *p; p++) {
X  			switch (*p) {
X				case 'a': info |= ALL;      break;
X				case 'm': info |= MACHINE;  break;
X				case 'n': info |= NODENAME; break;
X				case 'r': info |= RELEASE;  break;
X				case 's': info |= SYSNAME;  break;
X				case 'v': info |= VERSION;  break;
X				default: usage();
X  			}
X		}
X	} else {
X		usage();
X	}
X  }
X
X  if (uname(&un) != 0) {
X	print(STDERR_FILENO, "unable to determine uname values\n", (char *) NULL);
X	exit(EXIT_FAILURE);
X  }
X
X  if (info == 0 || (info & SYSNAME) != 0)
X	print(STDOUT_FILENO, un.sysname, (char *) NULL);
X  if ((info & NODENAME) != 0) {
X	if ((info & (SYSNAME)) != 0)
X		print(STDOUT_FILENO, " ", (char *) NULL);
X	print(STDOUT_FILENO, un.nodename, (char *) NULL);
X  }
X  if ((info & RELEASE) != 0) {
X	if ((info & (SYSNAME|NODENAME)) != 0)
X		print(STDOUT_FILENO, " ", (char *) NULL);
X	print(STDOUT_FILENO, un.release, (char *) NULL);
X  }
X  if ((info & VERSION) != 0) {
X	if ((info & (SYSNAME|NODENAME|RELEASE)) != 0)
X		print(STDOUT_FILENO, " ", (char *) NULL);
X	print(STDOUT_FILENO, un.version, (char *) NULL);
X  }
X  if ((info & MACHINE) != 0) {
X	if ((info & (SYSNAME|NODENAME|RELEASE|VERSION)) != 0)
X		print(STDOUT_FILENO, " ", (char *) NULL);
X	print(STDOUT_FILENO, un.machine, (char *) NULL);
X  }
X  print(STDOUT_FILENO, "\n", (char *) NULL);
X  return EXIT_SUCCESS;
X}
/
echo x - xargs.c
sed '/^X/s///' > xargs.c << '/'
X/* xargs - Make and execute commands	     Author: Ian Nicholls:  1 Mar 90 */
X
X/*
X * xargs  - Accept words from stdin until, combined with the arguments
X *	    given on the command line, just fit into the command line limit.
X *	    Then, execute the result.
X * 		e.g.    ls | xargs compress
X *			find . -name '*.s' -print | xargs ar qv libc.a
X *
X * flags: -t		Print the command just before it is run
X *	  -l len	Use len as maximum line length (default 490, max 1023)
X *	  -e ending	Append ending to the command before executing it.
X *
X * Exits with:	0  No errors.
X *		1  If any system(3) call returns a nonzero status.
X *		2  Usage error
X *		3  Line length too short to contain some single argument.
X *
X * Examples:	xargs ar qv libc.a < liborder		# Create a new libc.a
X *		find . -name '*.s' -print | xargs rm	# Remove all .s files
X *		find . -type f ! -name '*.Z' \		# Compress old files.
X *		       -atime +60 -print  | xargs compress -v
X *
X * Bugs:  If the command contains unquoted wildflags, then the system(3) call
X *		call may expand this to larger than the maximum line size.
X *	  The command is not executed if nothing was read from stdin.
X *	  xargs may give up too easily when the command returns nonzero.
X */
X#define USAGE "usage: xargs [-t] [-l len] [-e endargs] command [args...]\n"
X
X#include <errno.h>
X#include <stdlib.h>
X#include <string.h>
X#include <stdio.h>
X
Xextern int optind;
Xextern char *optarg;
X
X#ifndef MAX_ARGLINE
X# define MAX_ARGLINE 1023
X#endif
X#ifndef min
X# define min(a,b) ((a) < (b) ? (a) : (b))
X#endif
X
Xchar outlin[MAX_ARGLINE];
Xchar inlin[MAX_ARGLINE];
Xchar startlin[MAX_ARGLINE];
Xchar *ending = NULL;
Xchar traceflag = 0;
X
X_PROTOTYPE(int main, (int argc, char **argv));
X
Xint main(ac,av)
Xint ac;
Xchar *av[];
X{
X   int outlen, inlen, startlen, endlen=0, i;
X   char errflg = 0;
X   int maxlin = MAX_ARGLINE;
X
X   while ((i = getopt(ac, av, "tl:e:")) != EOF)
X       switch (i) {
X	   case 't': traceflag = 1;	  break;
X	   case 'l': maxlin = min(MAX_ARGLINE, atoi(optarg)); break;
X	   case 'e': ending = optarg;	  break;
X	   case '?': errflg++;		  break;
X       }
X   if (errflg)	{
X       fprintf(stderr, USAGE);
X       exit(2);
X   }
X
X   startlin[0] = 0;
X   if (optind == ac) {
X       strcat(startlin, "echo ");
X   }
X   else for ( ; optind < ac; optind++) {
X       strcat(startlin, av[optind]);
X       strcat(startlin, " ");
X   }
X   startlen = strlen(startlin);
X   if (ending) endlen = strlen(ending);
X   maxlin = maxlin - 1 - endlen;	/* Pre-compute */
X
X   strcpy(outlin, startlin);
X   outlen = startlen;
X
X   while (gets(inlin) != NULL) {
X       inlen = strlen(inlin);
X       if (maxlin <= (outlen + inlen)) {
X	   if (outlen == startlen) {
X	       fprintf(stderr, "%s: Line length too short to process '%s'\n",
X		       av[0], inlin);
X	       exit(3);
X	   }
X	   if (ending) strcat(outlin, ending);
X	   if (traceflag) fputs(outlin,stderr);
X	   errno = 0;
X	   if (0 != system(outlin)) {
X	       if (errno != 0) perror("xargs");
X	       exit(1);
X	   }
X	   strcpy(outlin, startlin);
X	   outlen = startlen;
X       }
X       strcat(outlin, inlin);
X       strcat(outlin, " ");
X       outlen = outlen + inlen + 1;
X   }
X   if (outlen != startlen) {
X       if (ending) strcat(outlin, ending);
X       if (traceflag) fputs(outlin,stderr);
X       errno = 0;
X       if (0 != system(outlin)) {
X	   if (errno != 0) perror("xargs");
X	   exit(1);
X       }
X   }    
X   return 0;
X}
/
echo x - simple.cd
sed '/^X/s///' > simple.cd << '/'
Xecho x - animals.c.d
Xsed '/^X/s///' > animals.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/animals.c  crc=15992   5677	Sun Apr 25 21:34:44 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/animals.c  crc=37998   6167	Wed Nov  4 04:19:03 1992
XX***************
XX*** 6,11 ****
XX--- 6,14 ----
XX  #include <sgtty.h>
XX  #include <ctype.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX+ #include <sys/stat.h>
XX+ #include <minix/minlib.h>
XX  #include <stdio.h>
XX  
XX  #define  ANIMALS	"/usr/lib/animals"
XX***************
XX*** 13,23 ****
XX  #define  MAX_NODES	999	/* Enough for 500 animals  */
XX  #define  MAX_LINE	90
XX  
XX! void Abort();
XX! char *Get_Animal();
XX! char *Get_Question();
XX! char *A_or_An();
XX! char *Alloc();
XX  
XX  struct node {
XX    int question;
XX--- 16,31 ----
XX  #define  MAX_NODES	999	/* Enough for 500 animals  */
XX  #define  MAX_LINE	90
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void Read_Animals, (char *animal_file));
XX! _PROTOTYPE(void Write_Animals, (char *animal_file));
XX! _PROTOTYPE(int Ask, (char *question));
XX! _PROTOTYPE(char *Get_Animal, (void));
XX! _PROTOTYPE(char *Get_Question, (void));
XX! _PROTOTYPE(char *A_or_An, (char *word));
XX! _PROTOTYPE(char *Alloc, (int size));
XX! _PROTOTYPE(void Abort, (int dummy));
XX! _PROTOTYPE(void Error, (char *message));
XX  
XX  struct node {
XX    int question;
XX***************
XX*** 30,39 ****
XX  struct sgttyb old_tty_mode;
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX- 
XX  {
XX    char *animal_file = ANIMALS;
XX  
XX--- 38,46 ----
XX  struct sgttyb old_tty_mode;
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    char *animal_file = ANIMALS;
XX  
XX***************
XX*** 122,135 ****
XX    sleep(1);
XX    printf("\nBye.\n");
XX  
XX!   exit(0);
XX  }
XX  
XX  
XX  /*  Reading and writing the animal data base */
XX  
XX  
XX! Read_Animals(animal_file)
XX  char *animal_file;
XX  
XX  {
XX--- 129,142 ----
XX    sleep(1);
XX    printf("\nBye.\n");
XX  
XX!   return(0);
XX  }
XX  
XX  
XX  /*  Reading and writing the animal data base */
XX  
XX  
XX! void Read_Animals(animal_file)
XX  char *animal_file;
XX  
XX  {
XX***************
XX*** 160,166 ****
XX  	string = Alloc(string_length + 1);
XX  
XX  	string[0] = '\0';
XX! 	strncat(string, buffer + 1, string_length);
XX  
XX  	animals[count].text = string;
XX  
XX--- 167,173 ----
XX  	string = Alloc(string_length + 1);
XX  
XX  	string[0] = '\0';
XX! 	strncat(string, buffer + 1, (size_t)string_length);
XX  
XX  	animals[count].text = string;
XX  
XX***************
XX*** 171,177 ****
XX  }
XX  
XX  
XX! Write_Animals(animal_file)
XX  char *animal_file;
XX  
XX  {
XX--- 178,184 ----
XX  }
XX  
XX  
XX! void Write_Animals(animal_file)
XX  char *animal_file;
XX  
XX  {
XX***************
XX*** 232,238 ****
XX    text_length = strlen(s);
XX    text = Alloc(text_length);
XX    text[0] = '\0';
XX!   strncat(text, s, text_length - 1);
XX    return(text);
XX  }
XX  
XX--- 239,245 ----
XX    text_length = strlen(s);
XX    text = Alloc(text_length);
XX    text[0] = '\0';
XX!   strncat(text, s, (size_t)(text_length - 1));
XX    return(text);
XX  }
XX  
XX***************
XX*** 274,290 ****
XX  char *Alloc(size)
XX  int size;
XX  {
XX-   char *malloc();
XX    char *memory;
XX  
XX!   if ((memory = malloc(size)) == NULL)
XX  	Error("No room in memory for all the animals");
XX  
XX    return(memory);
XX  }
XX  
XX  
XX! void Abort()
XX  {
XX    ioctl(0, TIOCSETP, &old_tty_mode);
XX  
XX--- 281,297 ----
XX  char *Alloc(size)
XX  int size;
XX  {
XX    char *memory;
XX  
XX!   if ((memory = (char *)malloc((size_t)size)) == NULL)
XX  	Error("No room in memory for all the animals");
XX  
XX    return(memory);
XX  }
XX  
XX  
XX! void Abort(dummy)
XX! int dummy; /* to keep the compiler happy */
XX  {
XX    ioctl(0, TIOCSETP, &old_tty_mode);
XX  
XX***************
XX*** 296,302 ****
XX  }
XX  
XX  
XX! Error(message)
XX  char *message;
XX  {
XX    ioctl(0, TIOCSETP, &old_tty_mode);
XX--- 303,309 ----
XX  }
XX  
XX  
XX! void Error(message)
XX  char *message;
XX  {
XX    ioctl(0, TIOCSETP, &old_tty_mode);
X/
Xecho x - ascii.c.d
Xsed '/^X/s///' > ascii.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ascii.c  crc=19229   2115	Sun Apr 25 21:34:44 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ascii.c  crc=29389   2270	Wed Nov  4 04:19:03 1992
XX***************
XX*** 4,9 ****
XX--- 4,11 ----
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <minix/minlib.h>
XX  #include <stdio.h>
XX  
XX  #define BUFSIZE 4*1024
XX***************
XX*** 11,16 ****
XX--- 13,20 ----
XX  static char buf[BUFSIZE + 1];	/* input buffer - +1 for sentinel */
XX  static char carry[BUFSIZE];	/* buffer for partial line carryover */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ 
XX  int main(argc, argv)
XX  int argc;
XX  char **argv;
XX***************
XX*** 58,72 ****
XX  		if ((*end & 0x80) != 0) {
XX  			ascii_line = 0;
XX  			ascii_file = 0;
XX! 			end = (char *) memchr(end, '\n', BUFSIZE);
XX  			break;
XX  		}
XX  	if (end != sentinel) {
XX  		++end;
XX  		if (ascii_line != nflag) {
XX  			if (carry_count != 0)
XX! 				fwrite(carry, carry_count, 1, stdout);
XX! 			fwrite(start, (int)(end - start), 1, stdout);
XX  		}
XX  		carry_count = 0;
XX  		start = end;
XX--- 62,76 ----
XX  		if ((*end & 0x80) != 0) {
XX  			ascii_line = 0;
XX  			ascii_file = 0;
XX! 			end = (char *) memchr(end, '\n', (size_t)BUFSIZE);
XX  			break;
XX  		}
XX  	if (end != sentinel) {
XX  		++end;
XX  		if (ascii_line != nflag) {
XX  			if (carry_count != 0)
XX! 				fwrite(carry, (size_t)carry_count, (size_t)1, stdout);
XX! 			fwrite(start, (size_t)(end - start), (size_t)1, stdout);
XX  		}
XX  		carry_count = 0;
XX  		start = end;
XX***************
XX*** 78,84 ****
XX  		}
XX  		if (ascii_line != nflag) {
XX  			carry_count = end - start;
XX! 			memcpy(carry, start, carry_count);
XX  		}
XX  		if ((count = read(0, buf, BUFSIZE)) <= 0) break;
XX  		*(sentinel = &buf[count]) = '\n';
XX--- 82,88 ----
XX  		}
XX  		if (ascii_line != nflag) {
XX  			carry_count = end - start;
XX! 			memcpy(carry, start, (size_t)carry_count);
XX  		}
XX  		if ((count = read(0, buf, BUFSIZE)) <= 0) break;
XX  		*(sentinel = &buf[count]) = '\n';
XX***************
XX*** 86,92 ****
XX  	}
XX    }
XX    if (ascii_line != nflag && carry_count != 0)
XX! 	fwrite(carry, carry_count, 1, stdout);
XX  
XX!   exit(ascii_file == 0);
XX  }
XX--- 90,96 ----
XX  	}
XX    }
XX    if (ascii_line != nflag && carry_count != 0)
XX! 	fwrite(carry, (size_t)carry_count, (size_t)1, stdout);
XX  
XX!   return(ascii_file == 0);
XX  }
X/
Xecho x - at.c.d
Xsed '/^X/s///' > at.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/at.c  crc=62419   4819	Sun Apr 25 21:34:45 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/at.c  crc=60318   5181	Wed Nov  4 04:19:03 1992
XX***************
XX*** 3,8 ****
XX--- 3,12 ----
XX  #include <sys/types.h>
XX  #include <time.h>
XX  #include <fcntl.h>
XX+ #include <unistd.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <sys/stat.h>
XX  #include <stdio.h>
XX  
XX  #define	STARTDAY	0	/* see ctime(3)	 */
XX***************
XX*** 10,25 ****
XX  #define	MAXDAYNR	STARTDAY+365
XX  #define	NODAY		-2
XX  
XX  
XX! main(argc, argv, envp)
XX  int argc;
XX  char **argv, **envp;
XX  {
XX!   int i, count, ltim, year, getltim(), getlday(), lday = NODAY;
XX!   char c, buf[10], job[30], *dp, *sp;
XX!   struct tm *p, *localtime();
XX!   long clock;
XX!   FILE *fp, *pin, *popen();
XX  
XX  /*-------------------------------------------------------------------------*
XX   *	check arguments	& pipe to "pwd"				           *
XX--- 14,33 ----
XX  #define	MAXDAYNR	STARTDAY+365
XX  #define	NODAY		-2
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv, char **envp));
XX+ _PROTOTYPE(int getltim, (char *t));
XX+ _PROTOTYPE(int getlday, (char *m, char *d));
XX+ _PROTOTYPE(int digitstring, (char *s));
XX  
XX! int main(argc, argv, envp)
XX  int argc;
XX  char **argv, **envp;
XX  {
XX!   int i, c, count, ltim, year, lday = NODAY;
XX!   char buf[10], job[30], *dp, *sp;
XX!   struct tm *p;
XX!   long clk;
XX!   FILE *fp, *pin;
XX  
XX  /*-------------------------------------------------------------------------*
XX   *	check arguments	& pipe to "pwd"				           *
XX***************
XX*** 48,61 ****
XX  /*-------------------------------------------------------------------------*
XX   *	determine execution time and create 'at' job file		   *
XX   *-------------------------------------------------------------------------*/
XX!   time(&clock);
XX!   p = localtime(&clock);
XX    year = p->tm_year;
XX    if (lday == NODAY) {		/* no [month day] given */
XX  	lday = p->tm_yday;
XX  	if (ltim <= (p->tm_hour * 100 + p->tm_min)) {
XX  		lday++;
XX! 		if (lday == MAXDAYNR && (year % 4) || lday == MAXDAYNR + 1) {
XX  			lday = STARTDAY;
XX  			year++;
XX  		}
XX--- 56,69 ----
XX  /*-------------------------------------------------------------------------*
XX   *	determine execution time and create 'at' job file		   *
XX   *-------------------------------------------------------------------------*/
XX!   time(&clk);
XX!   p = localtime(&clk);
XX    year = p->tm_year;
XX    if (lday == NODAY) {		/* no [month day] given */
XX  	lday = p->tm_yday;
XX  	if (ltim <= (p->tm_hour * 100 + p->tm_min)) {
XX  		lday++;
XX! 		if ((lday == MAXDAYNR && (year % 4)) || lday == MAXDAYNR + 1) {
XX  			lday = STARTDAY;
XX  			year++;
XX  		}
XX***************
XX*** 63,70 ****
XX    } else
XX  	switch (year % 4) {
XX  	    case 0:
XX! 		if (lday < p->tm_yday || lday == p->tm_yday &&
XX! 		    ltim <= (p->tm_hour * 100 + p->tm_min)) {
XX  			year++;
XX  			if (lday > LEAPDAY) lday--;
XX  		}
XX--- 71,79 ----
XX    } else
XX  	switch (year % 4) {
XX  	    case 0:
XX! 		if (lday < p->tm_yday ||
XX! 		    (lday == p->tm_yday &&
XX! 		    ltim <= (p->tm_hour * 100 + p->tm_min))) {
XX  			year++;
XX  			if (lday > LEAPDAY) lday--;
XX  		}
XX***************
XX*** 72,85 ****
XX  	    case 1:
XX  	    case 2:
XX  		if (lday > LEAPDAY) lday--;
XX! 		if (lday < p->tm_yday || lday == p->tm_yday &&
XX! 		    ltim <= (p->tm_hour * 100 + p->tm_min))
XX  			year++;
XX  		break;
XX  	    case 3:
XX  		if (lday < ((lday > LEAPDAY) ? p->tm_yday + 1 : p->tm_yday) ||
XX! 		    lday == ((lday > LEAPDAY) ? p->tm_yday + 1 : p->tm_yday) &&
XX! 		    ltim <= (p->tm_hour * 100 + p->tm_min))
XX  			year++;
XX  		else if (lday > LEAPDAY)
XX  			lday--;
XX--- 81,95 ----
XX  	    case 1:
XX  	    case 2:
XX  		if (lday > LEAPDAY) lday--;
XX! 		if (lday < p->tm_yday ||
XX! 		    (lday == p->tm_yday &&
XX! 		     ltim <= (p->tm_hour * 100 + p->tm_min)))
XX  			year++;
XX  		break;
XX  	    case 3:
XX  		if (lday < ((lday > LEAPDAY) ? p->tm_yday + 1 : p->tm_yday) ||
XX! 		    (lday ==((lday > LEAPDAY) ? p->tm_yday + 1 : p->tm_yday) &&
XX! 		     ltim <= (p->tm_hour * 100 + p->tm_min)))
XX  			year++;
XX  		else if (lday > LEAPDAY)
XX  			lday--;
XX***************
XX*** 106,130 ****
XX    }
XX    fprintf(fp, "cd ");
XX    while ((c = getc(pin)) != EOF) putc(c, fp);
XX!   fprintf(fp, "umask %o\n", umask());
XX    if (argc == 3 || argc == 5)
XX  	fprintf(fp, "%s\n", argv[argc - 1]);
XX    else				/* read from stdinput */
XX  	while ((c = getchar()) != EOF) putc(c, fp);
XX  
XX    printf("%s: %s created\n", argv[0], job);
XX!   exit(0);
XX  }
XX  
XX  /*-------------------------------------------------------------------------*
XX   *	getltim()		return((time OK) ? daytime : -1)	   *
XX   *-------------------------------------------------------------------------*/
XX! getltim(t)
XX  char *t;
XX  {
XX    if (t[4] == '\0' && t[3] >= '0' && t[3] <= '9' &&
XX        t[2] >= '0' && t[2] <= '5' && t[1] >= '0' && t[1] <= '9' &&
XX!       (t[0] == '0' || t[0] == '1' || t[1] <= '3' && t[0] == '2'))
XX  	return(atoi(t));
XX    else
XX  	return(-1);
XX--- 116,143 ----
XX    }
XX    fprintf(fp, "cd ");
XX    while ((c = getc(pin)) != EOF) putc(c, fp);
XX!   fprintf(fp, "umask %o\n", umask(0));
XX    if (argc == 3 || argc == 5)
XX  	fprintf(fp, "%s\n", argv[argc - 1]);
XX    else				/* read from stdinput */
XX  	while ((c = getchar()) != EOF) putc(c, fp);
XX+   fclose(fp);
XX  
XX+   if (chown(job, getuid(), getgid()) == -1)
XX+ 	unlink(job);		 /* else there could be a security hole */
XX    printf("%s: %s created\n", argv[0], job);
XX!   return(0);
XX  }
XX  
XX  /*-------------------------------------------------------------------------*
XX   *	getltim()		return((time OK) ? daytime : -1)	   *
XX   *-------------------------------------------------------------------------*/
XX! int getltim(t)
XX  char *t;
XX  {
XX    if (t[4] == '\0' && t[3] >= '0' && t[3] <= '9' &&
XX        t[2] >= '0' && t[2] <= '5' && t[1] >= '0' && t[1] <= '9' &&
XX!       (t[0] == '0' || t[0] == '1' || (t[1] <= '3' && t[0] == '2')))
XX  	return(atoi(t));
XX    else
XX  	return(-1);
XX***************
XX*** 133,142 ****
XX  /*-------------------------------------------------------------------------*
XX   *	getlday()		return ((date OK) ? yearday : -1)	   *
XX   *-------------------------------------------------------------------------*/
XX! getlday(m, d)
XX  char *m, *d;
XX  {
XX!   int i, month, day, im;
XX    static int cumday[] = {0, 0, 31, 60, 91, 121, 152,
XX  		       182, 213, 244, 274, 305, 335};
XX    static struct date {
XX--- 146,155 ----
XX  /*-------------------------------------------------------------------------*
XX   *	getlday()		return ((date OK) ? yearday : -1)	   *
XX   *-------------------------------------------------------------------------*/
XX! int getlday(m, d)
XX  char *m, *d;
XX  {
XX!   int i, day, im;
XX    static int cumday[] = {0, 0, 31, 60, 91, 121, 152,
XX  		       182, 213, 244, 274, 305, 335};
XX    static struct date {
XX***************
XX*** 162,168 ****
XX  
XX  
XX  
XX! digitstring(s)
XX  char *s;
XX  {
XX    while (*s >= '0' && *s <= '9') s++;
XX--- 175,181 ----
XX  
XX  
XX  
XX! int digitstring(s)
XX  char *s;
XX  {
XX    while (*s >= '0' && *s <= '9') s++;
X/
Xecho x - atrun.c.d
Xsed '/^X/s///' > atrun.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/atrun.c  crc=02442   1817	Sun Apr 25 21:34:45 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/atrun.c  crc=52423   1905	Wed Nov  4 07:51:31 1992
XX***************
XX*** 4,53 ****
XX   *	atrun scans directory /usr/spool/at for 'at' jobs to be executed.  *
XX   *	Finished jobs have been moved to directory /usr/spool/at/past.     *
XX   *-------------------------------------------------------------------------*/
XX  #include <sys/types.h>
XX  #include <sys/dir.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <time.h>
XX  #include <stdio.h>
XX  
XX! main()
XX  {
XX-   int fd, nr;
XX    char realtime[15], procname[35], procpast[35];
XX!   struct direct dirbuf;
XX!   struct tm *p, *localtime();
XX    struct stat sbuf;
XX!   time_t clock;
XX  
XX  /*-------------------------------------------------------------------------*
XX   *	Compute real time,  move 'at' jobs whose filenames < real time to  *
XX   *	/usr/spool/at/past and start a sh for each job.			   *
XX   *-------------------------------------------------------------------------*/
XX!   time(&clock);
XX!   p = localtime(&clock);
XX    sprintf(realtime, "%02d.%03d.%02d%02d.00",
XX  	p->tm_year % 100, p->tm_yday, p->tm_hour, p->tm_min);
XX!   if ((fd = open("/usr/spool/at", O_RDONLY)) > 0)
XX! 	while (read(fd, (char *) &dirbuf, sizeof(dirbuf)) > 0)
XX! 		if (dirbuf.d_ino > 0 &&
XX! 		    dirbuf.d_name[0] != '.' &&
XX! 		    dirbuf.d_name[0] != 'p' &&
XX! 		    strncmp(dirbuf.d_name, realtime, 11) <= 0) {
XX  
XX! 			sprintf(procname, "/usr/spool/at/%.14s", dirbuf.d_name);
XX! 			sprintf(procpast, "/usr/spool/at/past/%.14s", dirbuf.d_name);
XX  
XX  			if (fork() == 0)	/* code for child */
XX  				if (link(procname, procpast) == 0) {	/* link ok? */
XX  					unlink(procname);
XX  					stat(procpast, &sbuf);
XX! 					setgid(sbuf.st_uid);
XX! 					setuid(sbuf.st_gid);
XX  					execl("/bin/sh", "sh", procpast, (char *) 0);
XX  					fprintf(stderr, "proc %s can't start\n", procpast);
XX  					exit(1);
XX  				}
XX  		}
XX  }
XX--- 4,61 ----
XX   *	atrun scans directory /usr/spool/at for 'at' jobs to be executed.  *
XX   *	Finished jobs have been moved to directory /usr/spool/at/past.     *
XX   *-------------------------------------------------------------------------*/
XX+ 
XX  #include <sys/types.h>
XX  #include <sys/dir.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <time.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX+ #include <dirent.h>
XX  
XX! _PROTOTYPE(int main, (void));
XX! 
XX! int main()
XX  {
XX    char realtime[15], procname[35], procpast[35];
XX!   DIR *dir;
XX!   struct dirent *entry;
XX!   struct tm *p;
XX    struct stat sbuf;
XX!   time_t clk;
XX  
XX  /*-------------------------------------------------------------------------*
XX   *	Compute real time,  move 'at' jobs whose filenames < real time to  *
XX   *	/usr/spool/at/past and start a sh for each job.			   *
XX   *-------------------------------------------------------------------------*/
XX!   time(&clk);
XX!   p = localtime(&clk);
XX    sprintf(realtime, "%02d.%03d.%02d%02d.00",
XX  	p->tm_year % 100, p->tm_yday, p->tm_hour, p->tm_min);
XX!   if ((dir = opendir("/usr/spool/at")) != NULL)
XX! 	while ((entry = readdir(dir)) != NULL)
XX! 		if (entry->d_ino > 0 &&
XX! 		    entry->d_name[0] != '.' &&
XX! 		    entry->d_name[0] != 'p' &&
XX! 		strncmp(entry->d_name, realtime, (size_t) 11) <= 0) {
XX  
XX! 			sprintf(procname, "/usr/spool/at/%s", entry->d_name);
XX! 			sprintf(procpast, "/usr/spool/at/past/%s", entry->d_name);
XX  
XX  			if (fork() == 0)	/* code for child */
XX  				if (link(procname, procpast) == 0) {	/* link ok? */
XX  					unlink(procname);
XX  					stat(procpast, &sbuf);
XX! 					setgid(sbuf.st_gid);
XX! 					setuid(sbuf.st_uid);
XX  					execl("/bin/sh", "sh", procpast, (char *) 0);
XX  					fprintf(stderr, "proc %s can't start\n", procpast);
XX  					exit(1);
XX  				}
XX  		}
XX+   return(0);
XX  }
X/
Xecho x - backup.c.d
Xsed '/^X/s///' > backup.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/backup.c  crc=35148  12464	Sun Apr 25 21:34:45 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/backup.c  crc=47386  14512	Wed Nov  4 04:19:03 1992
XX***************
XX*** 17,35 ****
XX   *	-j  Don't copy junk: *.o, *.Z, *.bak, *.log, a.out, and core
XX   *	-m  If ENOSPC encountered, ask for another diskette
XX   *	-n  No directories, only loose files are backed up
XX   *	-s  Don't copy *.s files
XX   *      -t  set creation date of target-file equal to cdate of source-file
XX   *	-v  Verbose (announce what is being done)
XX   *	-z  Compress the backed up files
XX   *
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <errno.h>
XX- #include <stdio.h>
XX  #include <fcntl.h>
XX  #include <utime.h>
XX  
XX  #define COPY_SIZE 4096
XX  #define MAX_ENTRIES 512
XX--- 17,43 ----
XX   *	-j  Don't copy junk: *.o, *.Z, *.bak, *.log, a.out, and core
XX   *	-m  If ENOSPC encountered, ask for another diskette
XX   *	-n  No directories, only loose files are backed up
XX+  *	-o  Don't copy *.o files
XX+  *	-r  Restore filenames (ie. uncompress if necessary)
XX   *	-s  Don't copy *.s files
XX   *      -t  set creation date of target-file equal to cdate of source-file
XX   *	-v  Verbose (announce what is being done)
XX   *	-z  Compress the backed up files
XX   *
XX+  * Patches:
XX+  *	30 Mar 91.  Added restore option.  cwr. 
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <errno.h>
XX  #include <fcntl.h>
XX  #include <utime.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <sys/wait.h>
XX+ #include <stdio.h>
XX  
XX  #define COPY_SIZE 4096
XX  #define MAX_ENTRIES 512
XX***************
XX*** 41,50 ****
XX  #define NO_SAVINGS 512		/* compress can return code 2 */
XX  #define OUT_OF_SPACE 2
XX  
XX- typedef unsigned short unshort;
XX- 
XX  struct dir_buf {		/* list of the src directory */
XX!   unshort ino;
XX    char name[NAME_SIZE];
XX  } dir_buf[MAX_ENTRIES];
XX  
XX--- 49,56 ----
XX  #define NO_SAVINGS 512		/* compress can return code 2 */
XX  #define OUT_OF_SPACE 2
XX  
XX  struct dir_buf {		/* list of the src directory */
XX!   unsigned short ino;
XX    char name[NAME_SIZE];
XX  } dir_buf[MAX_ENTRIES];
XX  
XX***************
XX*** 56,76 ****
XX  } sorted[MAX_ENTRIES];
XX  
XX  char copybuf[COPY_SIZE];
XX  
XX- unshort dflag, jflag, mflag, nflag, rflag, sflag, tflag, vflag, zflag;
XX- 
XX  extern int errno;
XX! extern char *environ;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int i, ct, n, m, fd;
XX    char *dir1, *dir2, *cp, c;
XX  
XX    /* Get the flags. */
XX    sync();
XX    if (argc < 3 || argc > 4) usage();
XX    if (argc == 4) {
XX  	cp = argv[1];
XX--- 62,97 ----
XX  } sorted[MAX_ENTRIES];
XX  
XX  char copybuf[COPY_SIZE];
XX+ char *pname;
XX+ int dflag, jflag, mflag, nflag, oflag, rflag, sflag, tflag, vflag, zflag;
XX  
XX  extern int errno;
XX! extern char **environ;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void maketarget, (char *dir2));
XX! _PROTOTYPE(int make_dir, (char *dir));
XX! _PROTOTYPE(int stat_all, (char *dir1, int n));
XX! _PROTOTYPE(void sort_dir, (int m));
XX! _PROTOTYPE(void process, (int m, char *dir1, char *dir2));
XX! _PROTOTYPE(void swap, (struct sorted *sp1, struct sorted *sp2));
XX! _PROTOTYPE(int copy, (char *dir1, struct sorted *sp, char *cbuf2));
XX! _PROTOTYPE(int zcopy, (char *src, char *targ));
XX! _PROTOTYPE(void copydir, (char *dir1, char *dir2, char *namep));
XX! _PROTOTYPE(void newdisk, (char *dir));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(void error, (int type, char *s1, char *s2, char *s3));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int ct, n, m, fd;
XX    char *dir1, *dir2, *cp, c;
XX  
XX    /* Get the flags. */
XX    sync();
XX+   pname = argv[0];
XX    if (argc < 3 || argc > 4) usage();
XX    if (argc == 4) {
XX  	cp = argv[1];
XX***************
XX*** 81,86 ****
XX--- 102,108 ----
XX  		    case 'j':	jflag++;	break;
XX  		    case 'm':	mflag++;	break;
XX  		    case 'n':	nflag++;	break;
XX+ 		    case 'o':	oflag++;	break;
XX  		    case 's':	sflag++;	break;
XX  		    case 'r':	rflag++;	break;
XX  		    case 't':	tflag++;	break;
XX***************
XX*** 95,106 ****
XX  	dir1 = argv[1];
XX  	dir2 = argv[2];
XX    }
XX  
XX    /* Read in the source directory */
XX  
XX    fd = open(dir1, O_RDONLY);
XX    if (fd < 0) error(FATAL, "cannot open ", dir1, "");
XX!   ct = read(fd, &dir_buf[0], MAX_ENTRIES * DIR_ENT_SIZE);
XX    close(fd);
XX    if (ct == MAX_ENTRIES * DIR_ENT_SIZE)
XX  	error(FATAL, "directory ", dir1, " is too large");
XX--- 117,129 ----
XX  	dir1 = argv[1];
XX  	dir2 = argv[2];
XX    }
XX+   if (!strcmp(pname, "restore") && !rflag) rflag++;
XX  
XX    /* Read in the source directory */
XX  
XX    fd = open(dir1, O_RDONLY);
XX    if (fd < 0) error(FATAL, "cannot open ", dir1, "");
XX!   ct = read(fd, (char *)&dir_buf[0], MAX_ENTRIES * DIR_ENT_SIZE);
XX    close(fd);
XX    if (ct == MAX_ENTRIES * DIR_ENT_SIZE)
XX  	error(FATAL, "directory ", dir1, " is too large");
XX***************
XX*** 117,127 ****
XX  
XX    /* Process each of the m entries one at a time. */
XX    process(m, dir1, dir2);
XX!   exit(0);
XX  }
XX  
XX  
XX! maketarget(dir2)
XX  char *dir2;
XX  {
XX  /* The target directory is created if it does not already exist. */
XX--- 140,150 ----
XX  
XX    /* Process each of the m entries one at a time. */
XX    process(m, dir1, dir2);
XX!   return(0);
XX  }
XX  
XX  
XX! void maketarget(dir2)
XX  char *dir2;
XX  {
XX  /* The target directory is created if it does not already exist. */
XX***************
XX*** 165,170 ****
XX--- 188,194 ----
XX  	execle("/usr/bin/mkdir", "mkdir", dir, (char *) 0, environ);
XX  	error(FATAL, "cannot execute mkdir", "", "");
XX    }
XX+   return(0);
XX  }
XX  
XX  
XX***************
XX*** 179,186 ****
XX    int i, j;
XX    char cbuf[MAX_PATH];
XX    struct stat s;
XX-   struct dir_buf *dp;
XX-   struct sorted *sp;
XX  
XX    for (i = 0; i < n; i++) {
XX  	/* Mark "." and ".." as null entries, as well as unstatable ones. */
XX--- 203,208 ----
XX***************
XX*** 190,197 ****
XX  
XX  	/* Stat the file. */
XX  	strcpy(cbuf, dir1);
XX! 	strncat(cbuf, "/", 1);
XX! 	strncat(cbuf, dir_buf[i].name, NAME_SIZE);
XX  	if (stat(cbuf, &s) < 0) {
XX  		error(NONFATAL, "cannot stat ", cbuf, "");
XX  		dir_buf[i].ino = 0;	/* mark as unusable */
XX--- 212,219 ----
XX  
XX  	/* Stat the file. */
XX  	strcpy(cbuf, dir1);
XX! 	strncat(cbuf, "/", (size_t)1);
XX! 	strncat(cbuf, dir_buf[i].name, (size_t)NAME_SIZE);
XX  	if (stat(cbuf, &s) < 0) {
XX  		error(NONFATAL, "cannot stat ", cbuf, "");
XX  		dir_buf[i].ino = 0;	/* mark as unusable */
XX***************
XX*** 215,221 ****
XX  }
XX  
XX  
XX! int sort_dir(m)
XX  int m;
XX  {
XX  /* Sort the directory using bubble sort. */
XX--- 237,243 ----
XX  }
XX  
XX  
XX! void sort_dir(m)
XX  int m;
XX  {
XX  /* Sort the directory using bubble sort. */
XX***************
XX*** 224,237 ****
XX  
XX    for (sp1 = &sorted[0]; sp1 < &sorted[m - 1]; sp1++) {
XX  	for (sp2 = sp1 + 1; sp2 < &sorted[m]; sp2++) {
XX! 		if (strncmp(sp1->namep, sp2->namep, NAME_SIZE) > 0)
XX  			swap(sp1, sp2);
XX  	}
XX    }
XX  }
XX  
XX  
XX! process(m, dir1, dir2)
XX  int m;
XX  char *dir1, *dir2;
XX  {
XX--- 246,259 ----
XX  
XX    for (sp1 = &sorted[0]; sp1 < &sorted[m - 1]; sp1++) {
XX  	for (sp2 = sp1 + 1; sp2 < &sorted[m]; sp2++) {
XX! 		if (strncmp(sp1->namep, sp2->namep, (size_t)NAME_SIZE) > 0)
XX  			swap(sp1, sp2);
XX  	}
XX    }
XX  }
XX  
XX  
XX! void process(m, dir1, dir2)
XX  int m;
XX  char *dir1, *dir2;
XX  {
XX***************
XX*** 250,261 ****
XX  	if (fmode == S_IFREG) {
XX  		/* Regular file.  Construct target name and stat it. */
XX  		strcpy(cbuf, dir2);
XX! 		strncat(cbuf, "/", 1);
XX! 		strncat(cbuf, sp->namep, NAME_SIZE);
XX  		namlen = strlen(sp->namep);
XX! 		if (sp->namep[namlen - 2] != '.' || sp->namep[namlen - 1] != 'Z')
XX! 			if (zflag && (namlen <= (NAME_SIZE - 2)))
XX! 				strncat(cbuf, ".Z", 2);
XX  		er = stat(cbuf, &s);
XX  		if (er < 0 || sp->modtime > s.st_mtime) {
XX  			res = copy(dir1, sp, cbuf);
XX--- 272,286 ----
XX  	if (fmode == S_IFREG) {
XX  		/* Regular file.  Construct target name and stat it. */
XX  		strcpy(cbuf, dir2);
XX! 		strncat(cbuf, "/", (size_t)1);
XX! 		strncat(cbuf, sp->namep, (size_t)NAME_SIZE);
XX  		namlen = strlen(sp->namep);
XX! 		/* Switch between compressed and uncompressed file names */
XX! 		if (zflag && !rflag && strncmp((sp->namep + namlen - 2), ".Z", (size_t)2)
XX! 				&& (namlen <= (NAME_SIZE - 2)))
XX! 			strncat(cbuf, ".Z", (size_t)2);
XX! 		if (zflag && rflag && !strncmp((sp->namep + namlen - 2), ".Z", (size_t)2))
XX! 			cbuf[strlen(cbuf) - 2] = '\0';
XX  		er = stat(cbuf, &s);
XX  		if (er < 0 || sp->modtime > s.st_mtime) {
XX  			res = copy(dir1, sp, cbuf);
XX***************
XX*** 280,286 ****
XX  		copydir(dir1, dir2, sp->namep);
XX  	} else if (fmode == S_IFBLK || fmode == S_IFCHR) {
XX  		/* Special file. */
XX! 		strncpy(cbuf, sp->namep, NAME_SIZE);
XX  		printf("%s is special file.  Not backed up.\n", cbuf);
XX  	}
XX    }
XX--- 305,311 ----
XX  		copydir(dir1, dir2, sp->namep);
XX  	} else if (fmode == S_IFBLK || fmode == S_IFCHR) {
XX  		/* Special file. */
XX! 		strncpy(cbuf, sp->namep, (size_t)NAME_SIZE);
XX  		printf("%s is special file.  Not backed up.\n", cbuf);
XX  	}
XX    }
XX***************
XX*** 289,295 ****
XX  
XX  
XX  
XX! swap(sp1, sp2)
XX  struct sorted *sp1, *sp2;
XX  {
XX  /* Swap two directory entries. */
XX--- 314,320 ----
XX  
XX  
XX  
XX! void swap(sp1, sp2)
XX  struct sorted *sp1, *sp2;
XX  {
XX  /* Swap two directory entries. */
XX***************
XX*** 309,335 ****
XX  /* Copy a regular file. */
XX  
XX    int fd1, fd2, nr, nw, res, n, namlen;
XX!   char cbuf1[MAX_PATH], *p;
XX  
XX    /* If the -j or -s flags were given, suppress certain files. */
XX    p = sp->namep;
XX    n = strlen(p);
XX    if (jflag) {
XX  	if (strcmp(p, "a.out") == 0) return(0);
XX  	if (strcmp(p, "core") == 0) return (0);
XX- 	if (strcmp(p + n - 2, ".o") == 0) return (0);
XX  	if (strcmp(p + n - 2, ".Z") == 0) return (0);
XX  	if (strcmp(p + n - 4, ".bak") == 0) return (0);
XX  	if (strcmp(p + n - 4, ".log") == 0) return (0);
XX    }
XX    if (sflag) {
XX  	if (strcmp(p + n - 2, ".s") == 0) return(0);
XX    }
XX    res = 0;
XX    if (dflag) return(0);		/* backup -d means only directories */
XX    strcpy(cbuf1, dir1);
XX!   strncat(cbuf1, "/", 1);
XX!   strncat(cbuf1, sp->namep, NAME_SIZE);	/* cbuf1 = source file name */
XX  
XX    /* At this point, cbuf1 contains the source file name, cbuf2 the target. */
XX    fd1 = open(cbuf1, O_RDONLY);
XX--- 334,368 ----
XX  /* Copy a regular file. */
XX  
XX    int fd1, fd2, nr, nw, res, n, namlen;
XX!   char cbuf1[MAX_PATH], *p, msg[20];
XX  
XX+   /* The message changes with the program name */
XX+   if (!strcmp(pname, "restore"))
XX+ 	strcpy(msg, "Restored");
XX+   else
XX+ 	strcpy(msg, "Backed up");
XX+ 
XX    /* If the -j or -s flags were given, suppress certain files. */
XX    p = sp->namep;
XX    n = strlen(p);
XX    if (jflag) {
XX  	if (strcmp(p, "a.out") == 0) return(0);
XX  	if (strcmp(p, "core") == 0) return (0);
XX  	if (strcmp(p + n - 2, ".Z") == 0) return (0);
XX  	if (strcmp(p + n - 4, ".bak") == 0) return (0);
XX  	if (strcmp(p + n - 4, ".log") == 0) return (0);
XX    }
XX+   if (oflag) {
XX+ 	if (strcmp(p + n - 2, ".o") == 0) return(0);
XX+   }
XX    if (sflag) {
XX  	if (strcmp(p + n - 2, ".s") == 0) return(0);
XX    }
XX    res = 0;
XX    if (dflag) return(0);		/* backup -d means only directories */
XX    strcpy(cbuf1, dir1);
XX!   strncat(cbuf1, "/", (size_t)1);
XX!   strncat(cbuf1, sp->namep, (size_t)NAME_SIZE);	/* cbuf1 = source file name */
XX  
XX    /* At this point, cbuf1 contains the source file name, cbuf2 the target. */
XX    fd1 = open(cbuf1, O_RDONLY);
XX***************
XX*** 350,364 ****
XX  
XX    /* Both files are now open.  Do the copying. */
XX    namlen = strlen(sp->namep);
XX!   if (sp->namep[namlen - 2] != '.' || sp->namep[namlen - 1] != 'Z')
XX! 	if (zflag && (namlen <= (NAME_SIZE - 2))) {
XX  		close(fd1);
XX  		close(fd2);
XX  		res = zcopy(cbuf1, cbuf2);
XX  		if (tflag) utime(cbuf2, (struct utimbuf *) & (sp->acctime));
XX  		if (res != 0) unlink(cbuf2);	/* if error, get rid of the
XX  					 * corpse */
XX! 		if (vflag && res == 0) printf("Backing up %s\n", cbuf1);
XX  		return(res);
XX  	}
XX    while (1) {
XX--- 383,398 ----
XX  
XX    /* Both files are now open.  Do the copying. */
XX    namlen = strlen(sp->namep);
XX!   if ((!rflag && strncmp((sp->namep + namlen - 2), ".Z", (size_t)2)) ||
XX! 		(rflag && !strncmp((sp->namep + namlen - 2), ".Z", (size_t)2)))
XX! 	if (zflag && (rflag || (namlen <= (NAME_SIZE - 2)))) {
XX  		close(fd1);
XX  		close(fd2);
XX  		res = zcopy(cbuf1, cbuf2);
XX  		if (tflag) utime(cbuf2, (struct utimbuf *) & (sp->acctime));
XX  		if (res != 0) unlink(cbuf2);	/* if error, get rid of the
XX  					 * corpse */
XX! 		if (vflag && res == 0) printf("%s %s\n", msg, cbuf1);
XX  		return(res);
XX  	}
XX    while (1) {
XX***************
XX*** 384,390 ****
XX  	}
XX    }
XX    if (res == 0) {
XX! 	if (vflag) printf("Backing up %s\n", cbuf1);
XX    } else {
XX  	unlink(cbuf2);
XX    }
XX--- 418,424 ----
XX  	}
XX    }
XX    if (res == 0) {
XX! 	if (vflag) printf("%s %s\n", msg, cbuf1);
XX    } else {
XX  	unlink(cbuf2);
XX    }
XX***************
XX*** 400,406 ****
XX--- 434,447 ----
XX  {
XX  
XX    int pid, status, res, s;
XX+   char fbuf[20];
XX  
XX+   strcpy(fbuf, "-c");
XX+   if (rflag)
XX+ 	strcat(fbuf, "d");
XX+   else
XX+ 	strcat(fbuf, "f");
XX+ 
XX    if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
XX    if (pid > 0) {
XX  	wait(&status);
XX***************
XX*** 413,464 ****
XX  	close(1);
XX  	s = open(targ, O_RDWR);
XX  	if (s < 0) error(FATAL, "cannot write on ", "targ", "");
XX! 	execle("/bin/compress", "compress", "-fc", src, (char *) 0, environ);
XX! 	execle("/usr/bin/compress", "compress", "-fc", src, (char *)0,environ);
XX  	error(FATAL, "cannot exec compress", "", "");
XX    }
XX  }
XX  
XX  
XX! copydir(dir1, dir2, namep)
XX  char *dir1, *dir2, *namep;
XX  {
XX  /* Copy a directory. */
XX  
XX!   int pid, res, status;
XX    char fbuf[20], d1buf[MAX_PATH], d2buf[MAX_PATH];
XX  
XX!   res = 0;
XX!   if (nflag) return(res);	/* backup -n means no directories */
XX  
XX    /* Handle directory copy by forking off 'backup' ! */
XX!   strcpy(fbuf, "-r");
XX    if (jflag) strcat(fbuf, "j");
XX    if (mflag) strcat(fbuf, "m");
XX    if (sflag) strcat(fbuf, "s");
XX    if (tflag) strcat(fbuf, "t");
XX    if (vflag) strcat(fbuf, "v");
XX    if (zflag) strcat(fbuf, "z");
XX    strcpy(d1buf, dir1);
XX!   strcat(d1buf, "/", 1);
XX!   strncat(d1buf, namep, NAME_SIZE);
XX    strcpy(d2buf, dir2);
XX!   strcat(d2buf, "/", 2);
XX!   strncat(d2buf, namep, NAME_SIZE);
XX  
XX    if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
XX    if (pid > 0) {
XX  	wait(&status);
XX  	return;
XX!   } else {
XX  	execle("backup", "backup", fbuf, d1buf, d2buf, (char *) 0, environ);
XX  	execle("/bin/backup", "backup", fbuf, d1buf, d2buf, (char *)0,environ);
XX  	execle("/usr/bin/backup","backup",fbuf,d1buf,d2buf,(char *)0,environ);
XX  	error(FATAL, "cannot recursively exec backup", "", "");
XX    }
XX  }
XX  
XX! newdisk(dir)
XX  char *dir;
XX  {
XX  /* Ask for a new diskette. A big problem is that this program does not
XX--- 454,517 ----
XX  	close(1);
XX  	s = open(targ, O_RDWR);
XX  	if (s < 0) error(FATAL, "cannot write on ", "targ", "");
XX! 	execle("/bin/compress", "compress", fbuf, src, (char *)0, environ);
XX! 	execle("/usr/bin/compress", "compress", fbuf, src, (char *)0, environ);
XX  	error(FATAL, "cannot exec compress", "", "");
XX    }
XX+   return(0);
XX  }
XX  
XX  
XX! void copydir(dir1, dir2, namep)
XX  char *dir1, *dir2, *namep;
XX  {
XX  /* Copy a directory. */
XX  
XX!   int pid, status;
XX    char fbuf[20], d1buf[MAX_PATH], d2buf[MAX_PATH];
XX  
XX!   if (nflag) return;	/* backup -n means no directories */
XX  
XX+   fbuf[0] = '\0';
XX+ 
XX    /* Handle directory copy by forking off 'backup' ! */
XX!   if (jflag || mflag || rflag || sflag || tflag || vflag || zflag)
XX! 	strcpy(fbuf, "-");
XX    if (jflag) strcat(fbuf, "j");
XX    if (mflag) strcat(fbuf, "m");
XX+   if (rflag) strcat(fbuf, "r");
XX    if (sflag) strcat(fbuf, "s");
XX    if (tflag) strcat(fbuf, "t");
XX    if (vflag) strcat(fbuf, "v");
XX    if (zflag) strcat(fbuf, "z");
XX    strcpy(d1buf, dir1);
XX!   strcat(d1buf, "/");
XX!   strncat(d1buf, namep, (size_t)NAME_SIZE);
XX    strcpy(d2buf, dir2);
XX!   strcat(d2buf, "/");
XX!   strncat(d2buf, namep, (size_t)NAME_SIZE);
XX  
XX    if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
XX    if (pid > 0) {
XX+ 	/* Parent waits for child, then returns. */
XX  	wait(&status);
XX  	return;
XX!   }
XX! 
XX!   if (fbuf[0] == '-') {
XX  	execle("backup", "backup", fbuf, d1buf, d2buf, (char *) 0, environ);
XX  	execle("/bin/backup", "backup", fbuf, d1buf, d2buf, (char *)0,environ);
XX  	execle("/usr/bin/backup","backup",fbuf,d1buf,d2buf,(char *)0,environ);
XX  	error(FATAL, "cannot recursively exec backup", "", "");
XX+   } else {
XX+ 	execle("backup", "backup", d1buf, d2buf, (char *) 0, environ);
XX+ 	execle("/bin/backup", "backup", d1buf, d2buf, (char *)0,environ);
XX+ 	execle("/usr/bin/backup","backup", d1buf, d2buf, (char *)0,environ);
XX+ 	error(FATAL, "cannot recursively exec backup", "", "");
XX    }
XX  }
XX  
XX! void newdisk(dir)
XX  char *dir;
XX  {
XX  /* Ask for a new diskette. A big problem is that this program does not
XX***************
XX*** 472,478 ****
XX    printf("   1. Unmount the diskette using /etc/umount\n");
XX    printf("   2. Physically replace the diskette by the next one.\n");
XX    printf("   3. Mount the new diskette using /etc/mount\n");
XX!   printf("   4. Type CTRL-D to return to the backup program\n");
XX  
XX    if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
XX    if (pid > 0) {
XX--- 525,531 ----
XX    printf("   1. Unmount the diskette using /etc/umount\n");
XX    printf("   2. Physically replace the diskette by the next one.\n");
XX    printf("   3. Mount the new diskette using /etc/mount\n");
XX!   printf("   4. Type CTRL-D to return to the backup/restore program\n");
XX  
XX    if ((pid = fork()) < 0) error(FATAL, "cannot fork", "", "");
XX    if (pid > 0) {
XX***************
XX*** 485,501 ****
XX    }
XX  }
XX  
XX! usage()
XX  {
XX!   error(2, "Usage: backup [-djmnstvz] dir1 dir2", "", "");
XX  }
XX  
XX  
XX! error(type, s1, s2, s3)
XX  int type;
XX  char *s1, *s2, *s3;
XX  {
XX!   fprintf(stderr, "backup: %s%s%s\n", s1, s2, s3);
XX  
XX    if (type == NONFATAL)
XX  	return;
XX--- 538,555 ----
XX    }
XX  }
XX  
XX! void usage()
XX  {
XX!   fprintf(stderr, "Usage: backup [-djmnorstvz] dir1 dir2\n");
XX!   exit(2);
XX  }
XX  
XX  
XX! void error(type, s1, s2, s3)
XX  int type;
XX  char *s1, *s2, *s3;
XX  {
XX!   fprintf(stderr, "%s: %s%s%s\n", pname, s1, s2, s3);
XX  
XX    if (type == NONFATAL)
XX  	return;
X/
Xecho x - badblocks.c.d
Xsed '/^X/s///' > badblocks.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/badblocks.c  crc=49945  13140	Sun Apr 25 21:34:46 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/badblocks.c  crc=62664  15472	Sun Jan 10 14:26:15 1993
XX***************
XX*** 4,10 ****
XX  
XX  /* This program is written to handle BADBLOCKS on a hard or floppy disk.
XX   * The program asks for block_numbers. These numbers can be obtained with
XX!  * the program disk_check; written by A. Tanenbaum.  It then creates a
XX   * file on the disk containing up to 7 bad blocks.
XX   *
XX   * BUG:
XX--- 4,10 ----
XX  
XX  /* This program is written to handle BADBLOCKS on a hard or floppy disk.
XX   * The program asks for block_numbers. These numbers can be obtained with
XX!  * the program readall, written by A. Tanenbaum.  It then creates a
XX   * file on the disk containing up to 7 bad blocks.
XX   *
XX   * BUG:
XX***************
XX*** 19,35 ****
XX   *
XX   */
XX  
XX- #include <minix/config.h>
XX- #include <minix/type.h>
XX- 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX! #include <stdio.h>
XX  
XX  
XX  
XX  /* 		Super block table.
XX   *
XX   * 	The disk layout is:
XX--- 19,58 ----
XX   *
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <minix/config.h>
XX+ #include <minix/type.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX! #include <stdlib.h>
XX  
XX+ #include "../fs/const.h"	/* must be included before stdio.h */
XX+ #undef printf			/* so its define of printf can be undone */
XX+ #include "../fs/type.h"
XX  
XX+ #include <string.h>
XX+ #include <stdio.h>
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void rw_super, (int flag));
XX+ _PROTOTYPE(void get_super, (void));
XX+ _PROTOTYPE(void put_super, (void));
XX+ _PROTOTYPE(void rw_inode, (struct stat * stat_ptr, int rw_mode));
XX+ _PROTOTYPE(void get_inode, (struct stat * stat_ptr));
XX+ _PROTOTYPE(void put_inode, (struct stat * stat_ptr));
XX+ _PROTOTYPE(long rd_cmdline, (int argc, char *argv[]));
XX+ _PROTOTYPE(void modify, (int nr_blocks));
XX+ _PROTOTYPE(void save_blk, (block_t blk_num));
XX+ _PROTOTYPE(void reset_blks, (void));
XX+ _PROTOTYPE(void show_blks, (void));
XX+ _PROTOTYPE(int blk_is_used, (block_t blk_num));
XX+ _PROTOTYPE(int blk_ok, (block_t num));
XX+ _PROTOTYPE(void set_bit, (zone_t num));
XX+ _PROTOTYPE(long rd_num, (void));
XX+ _PROTOTYPE(int ok, (char *str));
XX+ _PROTOTYPE(void done, (int nr));
XX+ 
XX  /* 		Super block table.
XX   *
XX   * 	The disk layout is:
XX***************
XX*** 39,80 ****
XX   *    super block     1
XX   *    inode map     s_imap_blocks
XX   *    zone map      s_zmap_blocks
XX!  *    inodes        (s_ninodes + 1 + INODES_PER_BLOCK - 1)/INODES_PER_BLOCK
XX   *    unused
XX   *    data zones    (s_nzones - s_firstdatazone) << s_log_zone_size
XX   *
XX   */
XX  
XX- 
XX- struct super_block {
XX-   ino_t s_ninodes;		/* # usable inodes on the minor device */
XX-   zone_nr s_nzones;		/* total device size, including bit maps etc */
XX-   unshort s_imap_block;		/* # of block used by inode bit map */
XX-   unshort s_zmap_block;		/* # of block used by zone bit map */
XX-   zone_nr s_firstdatazone;	/* number of first data zone */
XX-   short int s_log_zone_size;	/* log2 of block/zone */
XX-   off_t s_max_size;		/* maximum file size on this device */
XX-   int s_magic;			/* magic number to recognize super-block */
XX- } super_block;
XX- 
XX- #define SUPER_MAGIC	0x137F
XX- 
XX- 
XX- #define NR_ZONE_NUMS	9
XX- #define NR_DZONE_NUMS	(NR_ZONE_NUMS -2 )
XX- 
XX- struct d_inode {		/* disk inode. */
XX-   mode_t i_mode;		/* file type, protection, etc. */
XX-   uid_t i_uid;			/* user id of the file's owner */
XX-   off_t i_size;			/* current file size in bytes */
XX-   time_t i_mtime;		/* when was file data last changed */
XX-   gid_t i_gid;			/* group number */
XX-   nlink_t i_nlinks;		/* how many links to this file */
XX-   zone_nr i_zone[NR_ZONE_NUMS];	/* blocks nums for direct, ind, and dbl ind */
XX- } d_inode;
XX- 
XX- 
XX- 
XX  #define OK	0
XX  #define NOT_OK	1
XX  #define QUIT	2
XX--- 62,73 ----
XX   *    super block     1
XX   *    inode map     s_imap_blocks
XX   *    zone map      s_zmap_blocks
XX!  *    inodes        (s_ninodes + 1 + inodes_per_block - 1)/inodes_per_block
XX   *    unused
XX   *    data zones    (s_nzones - s_firstdatazone) << s_log_zone_size
XX   *
XX   */
XX  
XX  #define OK	0
XX  #define NOT_OK	1
XX  #define QUIT	2
XX***************
XX*** 88,100 ****
XX  #define FILE_EXISTS	3
XX  #define SUCCESS		4
XX  
XX! #define BLOCK_SIZE	1024
XX! #define INODES_PER_BLOCK	(BLOCK_SIZE/sizeof(struct d_inode))
XX! 
XX! #define INODE_SIZE (sizeof (struct d_inode) )
XX! #define SUPER_SIZE (sizeof (struct super_block) )
XX  #define SIZE_OF_INT   (sizeof (int) )
XX  
XX   /* ====== globals ======= */
XX  
XX  char *dev_name;
XX--- 81,112 ----
XX  #define FILE_EXISTS	3
XX  #define SUCCESS		4
XX  
XX! #define BYTE         0377
XX! #define BLOCK_SIZE   1024
XX  #define SIZE_OF_INT   (sizeof (int) )
XX  
XX+ /* Define V_NR_DZONES as the larger of V1_NR_DZONES and V2_NR_DZONES. */
XX+ #if (V1_NR_DZONES > V2_NR_DZONES)
XX+ #define V_NR_DZONES V1_NR_DZONES
XX+ #define V_SMALLER   V2_NR_DZONES
XX+ #else
XX+ #define V_NR_DZONES V2_NR_DZONES
XX+ #define V_SMALLER   V1_NR_DZONES
XX+ #endif
XX+ 
XX+ struct super_block {
XX+   ino_t s_ninodes;		/* # usable inodes on the minor device */
XX+   zone1_t s_nzones;		/* total device size, including bit maps etc */
XX+   short s_imap_blocks;		/* # of blocks used by inode bit map */
XX+   short s_zmap_blocks;		/* # of blocks used by zone bit map */
XX+   zone1_t s_firstdatazone;	/* number of first data zone */
XX+   short s_log_zone_size;	/* log2 of blocks/zone */
XX+   off_t s_max_size;		/* maximum file size on this device */
XX+   short s_magic;		/* magic number to recognize super-blocks */
XX+   short s_pad;			/* try to avoid compiler-dependent padding */
XX+   zone_t s_zones;		/* number of zones (replaces s_nzones in V2) */
XX+ } super_block;
XX+ 
XX   /* ====== globals ======= */
XX  
XX  char *dev_name;
XX***************
XX*** 102,124 ****
XX  char file_name[50];
XX  char dir_name[] = "/tmpXXXXXX";
XX  
XX! int block[NR_DZONE_NUMS + 1];	/* last block contains zero */
XX  int interactive;		/* 1 if interactive (argc == 2) */
XX  int position = 2;		/* next block # is argv[position] */
XX  
XX! FILE *fp, *fopen();
XX  int fd;
XX  int eofseen;			/* set if '\n' seen */
XX  struct stat stat_buf;
XX- struct d_inode *ip;
XX  struct super_block *sp;
XX  
XX! extern char *strcat();
XX  
XX  
XX   /* ====== super block routines ======= */
XX  
XX! rw_super(flag)
XX  {				/* read or write a superblock */
XX    int rwd;
XX  
XX--- 114,142 ----
XX  char file_name[50];
XX  char dir_name[] = "/tmpXXXXXX";
XX  
XX! block_t block[V_NR_DZONES + 1];	/* last block contains zero */
XX  int interactive;		/* 1 if interactive (argc == 2) */
XX  int position = 2;		/* next block # is argv[position] */
XX  
XX! FILE *f;
XX  int fd;
XX  int eofseen;			/* set if '\n' seen */
XX  struct stat stat_buf;
XX  struct super_block *sp;
XX+ int inodes_per_block;
XX+ size_t inode_size;
XX+ int v1fs;			/* TRUE for V1 file system, FALSE for V2 */
XX  
XX! d1_inode d1inode;		/* declare a V1 disk inode */
XX! d1_inode *ip1;
XX! d2_inode d2inode;		/* declare a V2 disk inode */
XX! d2_inode *ip2;
XX  
XX  
XX   /* ====== super block routines ======= */
XX  
XX! void rw_super(flag)
XX! int flag;
XX  {				/* read or write a superblock */
XX    int rwd;
XX  
XX***************
XX*** 130,194 ****
XX    else
XX  	rwd = write(fd, (char *) sp, SUPER_SIZE);
XX    if (rwd != SUPER_SIZE) {	/* ok ? */
XX! 	printf("Bad %s in get_super() (should be %d is %d)\n",
XX  	       flag == READ ? "read" : "write",
XX! 	       SUPER_SIZE, rwd);
XX  	done(DIR_CREATED);
XX    }
XX  }
XX  
XX! get_super()
XX   /* Get super_block. global pointer sp is used */
XX  {
XX    rw_super(READ);
XX  
XX!   if (sp->s_magic != SUPER_MAGIC) {	/* check */
XX! 	printf("Bad magic number in super_block?!\n");
XX  	done(DIR_CREATED);
XX    }
XX  }
XX  
XX  
XX! put_super()
XX  {
XX    rw_super(WRITE);
XX  }
XX  
XX   /* ========== inode routines =========== */
XX  
XX! rw_inode(stat_ptr, rw_mode)
XX  struct stat *stat_ptr;
XX  {
XX!   int rwd, i_num;
XX!   long blk, offset;
XX  
XX  
XX    i_num = stat_ptr->st_ino;
XX  
XX!   blk = (long) (2 + sp->s_imap_block + sp->s_zmap_block);
XX!   blk += (long) ((i_num - 1) / INODES_PER_BLOCK);
XX!   blk *= (long) (BLOCK_SIZE);	/* this block */
XX  
XX!   offset = (long) ((i_num - 1) % INODES_PER_BLOCK);
XX!   offset *= (long) (INODE_SIZE);/* and this offset */
XX  
XX!   lseek(fd, 0L, SEEK_SET);	/* rewind */
XX!   lseek(fd, (long) (blk + offset), SEEK_SET);	/* seek */
XX  
XX    /* Pointer is at the inode */
XX!   if (rw_mode == READ) {	/* read it */
XX! 	rwd = read(fd, (char *) ip, INODE_SIZE);
XX!   } else {			/* write it */
XX! 	rwd = write(fd, (char *) ip, INODE_SIZE);
XX    }
XX!   if (rwd != INODE_SIZE) {	/* ok ? */
XX  	printf("Bad %s in get_inode()\n", (rw_mode == READ) ? "read" :
XX  	       "write");
XX  	done(DIR_CREATED);
XX    }
XX  }
XX  
XX! get_inode(stat_ptr)
XX  struct stat *stat_ptr;
XX  {
XX  
XX--- 148,233 ----
XX    else
XX  	rwd = write(fd, (char *) sp, SUPER_SIZE);
XX    if (rwd != SUPER_SIZE) {	/* ok ? */
XX! 	printf("Bad %s in get_super() (should be %u is %d)\n",
XX  	       flag == READ ? "read" : "write",
XX! 	       (unsigned) SUPER_SIZE, rwd);
XX  	done(DIR_CREATED);
XX    }
XX  }
XX  
XX! void get_super()
XX   /* Get super_block. global pointer sp is used */
XX  {
XX    rw_super(READ);
XX  
XX!   if (sp->s_magic == SUPER_MAGIC) {
XX! 	/* This is a V1 file system. */
XX! 	v1fs = 1;		/* file system is not V2 */
XX!   } else if (sp->s_magic == SUPER_V2) {
XX! 	/* This is a V2 file system. */
XX! 	v1fs = 0;		/* this is a V2 file system */
XX!   } else {
XX! 	/* Neither V1 nor V2. */
XX! 	printf("Bad magic number in super_block (0x%x)\n",
XX! 	       (unsigned) sp->s_magic);
XX  	done(DIR_CREATED);
XX    }
XX  }
XX  
XX  
XX! void put_super()
XX  {
XX    rw_super(WRITE);
XX  }
XX  
XX   /* ========== inode routines =========== */
XX  
XX! void rw_inode(stat_ptr, rw_mode)
XX  struct stat *stat_ptr;
XX+ int rw_mode;
XX  {
XX!   int rwd;
XX!   ino_t i_num;
XX!   block_t blk, offset;
XX  
XX  
XX    i_num = stat_ptr->st_ino;
XX  
XX!   blk = (block_t) (2 + sp->s_imap_blocks + sp->s_zmap_blocks);
XX!   blk += (block_t) ((i_num - 1) / inodes_per_block);
XX!   blk *= (block_t) (BLOCK_SIZE);/* this block */
XX  
XX!   offset = (block_t) ((i_num - 1) % inodes_per_block);
XX!   offset *= (block_t) (inode_size);	/* and this offset */
XX  
XX!   lseek(fd, (off_t) 0, SEEK_SET);	/* rewind */
XX!   lseek(fd, (off_t) (blk + offset), SEEK_SET);	/* seek */
XX  
XX    /* Pointer is at the inode */
XX!   if (v1fs) {
XX! 	/* This is a V1 file system. */
XX! 	if (rw_mode == READ) {	/* read it */
XX! 		rwd = read(fd, (char *) ip1, inode_size);
XX! 	} else {		/* write it */
XX! 		rwd = write(fd, (char *) ip1, inode_size);
XX! 	}
XX!   } else {
XX! 	/* This is a V2 file system. */
XX! 	if (rw_mode == READ) {	/* read it */
XX! 		rwd = read(fd, (char *) ip2, inode_size);
XX! 	} else {		/* write it */
XX! 		rwd = write(fd, (char *) ip2, inode_size);
XX! 	}
XX    }
XX! 
XX!   if (rwd != inode_size) {	/* ok ? */
XX  	printf("Bad %s in get_inode()\n", (rw_mode == READ) ? "read" :
XX  	       "write");
XX  	done(DIR_CREATED);
XX    }
XX  }
XX  
XX! void get_inode(stat_ptr)
XX  struct stat *stat_ptr;
XX  {
XX  
XX***************
XX*** 196,206 ****
XX  
XX    rw_inode(stat_ptr, READ);
XX  
XX!   for (cnt = 0; cnt < NR_ZONE_NUMS; cnt++)
XX! 	ip->i_zone[cnt] = 0;	/* Just to be safe */
XX  }
XX  
XX! put_inode(stat_ptr)
XX  struct stat *stat_ptr;
XX  {
XX    rw_inode(stat_ptr, WRITE);
XX--- 235,250 ----
XX  
XX    rw_inode(stat_ptr, READ);
XX  
XX!   if (v1fs) {
XX! 	for (cnt = 0; cnt < V1_NR_TZONES; cnt++)
XX! 		ip1->d1_zone[cnt] = 0;	/* Just to be safe */
XX!   } else {
XX! 	for (cnt = 0; cnt < V2_NR_TZONES; cnt++)
XX! 		ip2->d2_zone[cnt] = 0;	/* Just to be safe */
XX!   }
XX  }
XX  
XX! void put_inode(stat_ptr)
XX  struct stat *stat_ptr;
XX  {
XX    rw_inode(stat_ptr, WRITE);
XX***************
XX*** 208,228 ****
XX  
XX  
XX   /* ==============  main program ================= */
XX! main(argc, argv)
XX  char *argv[];
XX  {
XX    int cnt, finished;
XX!   unsigned blk_nr;
XX    struct stat dev_stat;
XX  
XX    sp = &super_block;
XX!   ip = &d_inode;
XX  
XX    if (argc < 2 || argc > 9) {
XX  	fprintf(stderr, "Usage: %s block_special [up_to_7_blocks]\n", argv[0]);
XX  	done(HARMLESS);
XX    }
XX- 
XX    interactive = (argc == 2 ? 1 : 0);
XX  
XX    /* Do some test. */
XX--- 252,274 ----
XX  
XX  
XX   /* ==============  main program ================= */
XX! int main(argc, argv)
XX! int argc;
XX  char *argv[];
XX  {
XX    int cnt, finished;
XX!   block_t blk_nr;
XX    struct stat dev_stat;
XX+   FILE *fp;
XX  
XX    sp = &super_block;
XX!   ip1 = &d1inode;
XX!   ip2 = &d2inode;
XX  
XX    if (argc < 2 || argc > 9) {
XX  	fprintf(stderr, "Usage: %s block_special [up_to_7_blocks]\n", argv[0]);
XX  	done(HARMLESS);
XX    }
XX    interactive = (argc == 2 ? 1 : 0);
XX  
XX    /* Do some test. */
XX***************
XX*** 299,313 ****
XX  	printf("This program can not handle it\n");
XX  	done(DIR_CREATED);
XX    }
XX    get_inode(&stat_buf);
XX  
XX    for (finished = 0; !finished;) {
XX  	if (interactive)
XX  		printf("Give up to %d bad block numbers separated by spaces\n",
XX! 							       NR_DZONE_NUMS);
XX  	reset_blks();
XX  	cnt = 0;		/* cnt keep track of the zone's */
XX! 	while (cnt < NR_DZONE_NUMS) {
XX  		int tst;
XX  
XX  		if (interactive)
XX--- 345,369 ----
XX  	printf("This program can not handle it\n");
XX  	done(DIR_CREATED);
XX    }
XX+ 
XX+   /* The number of inodes in a block differs in V1 and V2. */
XX+   if (v1fs) {
XX+ 	inodes_per_block = V1_INODES_PER_BLOCK;
XX+ 	inode_size = V1_INODE_SIZE;
XX+   } else {
XX+ 	inodes_per_block = V2_INODES_PER_BLOCK;
XX+ 	inode_size = V2_INODE_SIZE;
XX+   }
XX+ 
XX    get_inode(&stat_buf);
XX  
XX    for (finished = 0; !finished;) {
XX  	if (interactive)
XX  		printf("Give up to %d bad block numbers separated by spaces\n",
XX! 		       V_SMALLER);
XX  	reset_blks();
XX  	cnt = 0;		/* cnt keep track of the zone's */
XX! 	while (cnt < V_SMALLER) {
XX  		int tst;
XX  
XX  		if (interactive)
XX***************
XX*** 327,337 ****
XX  	if (interactive) show_blks();
XX  	if (!cnt) done(FILE_EXISTS);
XX  	if (interactive) {
XX! 	   switch (ok("All these blocks ok <y/n/q> (y:Device will change) ")) {
XX! 		case OK:	finished = 1; break;
XX! 		case NOT_OK:	break;
XX! 		case QUIT:	done(FILE_EXISTS);
XX! 	   }
XX  	} else {
XX  		finished = 1;
XX  	}
XX--- 383,394 ----
XX  	if (interactive) show_blks();
XX  	if (!cnt) done(FILE_EXISTS);
XX  	if (interactive) {
XX! 		switch (ok("All these blocks ok <y/n/q> (y:Device will change) ")) {
XX! 		    case OK:	finished = 1;	break;
XX! 		    case NOT_OK:
XX! 			break;
XX! 		    case QUIT:	done(FILE_EXISTS);
XX! 		}
XX  	} else {
XX  		finished = 1;
XX  	}
XX***************
XX*** 340,366 ****
XX    modify(cnt);
XX    close(fd);			/* free device */
XX    done(SUCCESS);
XX  }
XX  
XX! rd_cmdline(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    if (position == argc) return(-1);
XX!   return(atoi(argv[position++]));
XX  }
XX  
XX  
XX! modify(nr_blocks)
XX  {
XX    int i;
XX  
XX    if (nr_blocks == 0) return;
XX!   for (i = 0; i < nr_blocks; i++) {
XX! 	set_bit(block[i]);
XX! 	ip->i_zone[i] = block[i];
XX    }
XX!   ip->i_size = (long) (BLOCK_SIZE * nr_blocks);	/* give file size */
XX    put_inode(&stat_buf);		/* save the inode on disk */
XX    put_super();			/* bit_maps too */
XX  }
XX--- 397,441 ----
XX    modify(cnt);
XX    close(fd);			/* free device */
XX    done(SUCCESS);
XX+   return(0);
XX  }
XX  
XX! long rd_cmdline(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    if (position == argc) return(-1);
XX!   return(atol(argv[position++]));
XX  }
XX  
XX  
XX! void modify(nr_blocks)
XX! int nr_blocks;
XX  {
XX    int i;
XX  
XX    if (nr_blocks == 0) return;
XX!   if (v1fs) {
XX! 	/* This is a V1 file system. */
XX! 	for (i = 0; i < nr_blocks; i++) {
XX! 		set_bit(block[i]);
XX! 		ip1->d1_zone[i] = block[i];
XX! 	}
XX!   } else {
XX! 	/* This is a V2 file system. */
XX! 	for (i = 0; i < nr_blocks; i++) {
XX! 		set_bit(block[i]);
XX! 		ip2->d2_zone[i] = block[i];
XX! 	}
XX    }
XX!   if (v1fs) {
XX! 	ip1->d1_size = (long) (BLOCK_SIZE * nr_blocks);	/* give file size */
XX! 	ip1->d1_mtime = 0;	/* Who wants a file from 1970? */
XX!   } else {
XX! 	ip2->d2_size = (long) (BLOCK_SIZE * nr_blocks);	/* give file size */
XX! 	ip2->d2_atime = ip2->d2_mtime = ip2->d2_ctime = 0;
XX!   }
XX! 
XX    put_inode(&stat_buf);		/* save the inode on disk */
XX    put_super();			/* bit_maps too */
XX  }
XX***************
XX*** 368,397 ****
XX  
XX  static blk_cnt = 0;
XX  
XX! save_blk(blk_num)
XX! int blk_num;
XX  {
XX    block[blk_cnt++] = blk_num;
XX  }
XX  
XX! reset_blks()
XX  {
XX    int i;
XX  
XX!   for (i = 0; i <= NR_DZONE_NUMS; i++)
XX  	block[i] = 0;		/* Note: Last block_number is set to zero */
XX    blk_cnt = 0;
XX  }
XX  
XX! show_blks()
XX  {
XX    int i;
XX  
XX!   for (i = 0; i < blk_cnt; i++) printf("Block[%d] = %d\n", i, block[i]);
XX  }
XX  
XX! blk_is_used(blk_num)
XX! int blk_num;
XX  {				/* return TRUE(1) if used */
XX    int i;
XX  
XX--- 443,473 ----
XX  
XX  static blk_cnt = 0;
XX  
XX! void save_blk(blk_num)
XX! block_t blk_num;
XX  {
XX    block[blk_cnt++] = blk_num;
XX  }
XX  
XX! void reset_blks()
XX  {
XX    int i;
XX  
XX!   for (i = 0; i <= V_NR_DZONES; i++)
XX  	block[i] = 0;		/* Note: Last block_number is set to zero */
XX    blk_cnt = 0;
XX  }
XX  
XX! void show_blks()
XX  {
XX    int i;
XX  
XX!   for (i = 0; i < blk_cnt; i++)
XX! 	printf("Block[%d] = %lu\n", i, (unsigned long) block[i]);
XX  }
XX  
XX! int blk_is_used(blk_num)
XX! block_t blk_num;
XX  {				/* return TRUE(1) if used */
XX    int i;
XX  
XX***************
XX*** 405,423 ****
XX  #define BIT_MAP_SHIFT	13
XX  #define INT_BITS	(SIZE_OF_INT << 3)
XX  
XX! blk_ok(num)			/* is this zone free (y/n) */
XX! unsigned num;
XX  {
XX!   long blk_offset;
XX    int rd;
XX!   int block, offset, words, bit, tst_word;
XX!   unsigned z_num;
XX  
XX-   if (num < 0) {
XX- 	return QUIT;		/* negative number is not allowed */
XX-   }
XX    if (blk_is_used(num)) {
XX! 	printf("Duplicate block (%d) given\n", num);
XX  	return NOT_OK;
XX    }
XX  
XX--- 481,496 ----
XX  #define BIT_MAP_SHIFT	13
XX  #define INT_BITS	(SIZE_OF_INT << 3)
XX  
XX! int blk_ok(num)			/* is this zone free (y/n) */
XX! block_t num;
XX  {
XX!   block_t blk_offset;
XX    int rd;
XX!   int blk, offset, words, bit, tst_word;
XX!   zone_t z_num;
XX  
XX    if (blk_is_used(num)) {
XX! 	printf("Duplicate block (%lu) given\n", (unsigned long) num);
XX  	return NOT_OK;
XX    }
XX  
XX***************
XX*** 426,442 ****
XX    z_num = num - (sp->s_firstdatazone - 1);	/* account offset */
XX  
XX    /* Calculate the word in the bitmap. */
XX!   block = z_num >> BIT_MAP_SHIFT;	/* which block */
XX!   offset = z_num - (block << BIT_MAP_SHIFT);	/* offset */
XX    words = z_num / INT_BITS;	/* which word */
XX  
XX!   blk_offset = (long) (2 + sp->s_imap_block);	/* zone map */
XX!   blk_offset *= (long) BLOCK_SIZE;	/* of course in block */
XX!   blk_offset += (long) (words * SIZE_OF_INT);	/* offset */
XX  
XX  
XX!   lseek(fd, 0L, SEEK_SET);	/* rewind */
XX!   lseek(fd, blk_offset, SEEK_SET);	/* set pointer at word */
XX  
XX    rd = read(fd, (char *) &tst_word, SIZE_OF_INT);
XX    if (rd != SIZE_OF_INT) {
XX--- 499,515 ----
XX    z_num = num - (sp->s_firstdatazone - 1);	/* account offset */
XX  
XX    /* Calculate the word in the bitmap. */
XX!   blk = z_num >> BIT_MAP_SHIFT;	/* which block */
XX!   offset = z_num - (blk << BIT_MAP_SHIFT);	/* offset */
XX    words = z_num / INT_BITS;	/* which word */
XX  
XX!   blk_offset = (block_t) (2 + sp->s_imap_blocks);	/* zone map */
XX!   blk_offset *= (block_t) BLOCK_SIZE;	/* of course in block */
XX!   blk_offset += (block_t) (words * SIZE_OF_INT);	/* offset */
XX  
XX  
XX!   lseek(fd, (off_t) 0, SEEK_SET);	/* rewind */
XX!   lseek(fd, (off_t) blk_offset, SEEK_SET);	/* set pointer at word */
XX  
XX    rd = read(fd, (char *) &tst_word, SIZE_OF_INT);
XX    if (rd != SIZE_OF_INT) {
XX***************
XX*** 450,483 ****
XX    if (((tst_word >> bit) & 01) == 0)	/* free */
XX  	return OK;
XX    else {
XX! 	printf("Bad number %d. ", num);
XX  	printf("This zone (block) is marked in bitmap\n");
XX  	return NOT_OK;
XX    }
XX  }
XX  
XX! set_bit(num)			/* write in the bitmap */
XX! unsigned num;
XX  {
XX    int rwd;
XX    long blk_offset;
XX!   int block, offset, words, tst_word, bit;
XX    unsigned z_num;
XX-   char wrd_str[17], bit_str[17];
XX  
XX!   z_num = num + 1 - sp->s_firstdatazone;
XX  
XX!   block = z_num >> BIT_MAP_SHIFT;	/* which block */
XX!   offset = z_num - (block << BIT_MAP_SHIFT);	/* offset in block */
XX!   words = offset / INT_BITS;	/* which word */
XX  
XX!   blk_offset = (long) (2 + sp->s_imap_block);
XX    blk_offset *= (long) BLOCK_SIZE;
XX    blk_offset += (long) (words * SIZE_OF_INT);
XX  
XX  
XX!   lseek(fd, 0L, SEEK_SET);	/* rewind */
XX!   lseek(fd, blk_offset, SEEK_SET);
XX  
XX    rwd = read(fd, (char *) &tst_word, SIZE_OF_INT);
XX    if (rwd != SIZE_OF_INT) {
XX--- 523,555 ----
XX    if (((tst_word >> bit) & 01) == 0)	/* free */
XX  	return OK;
XX    else {
XX! 	printf("Bad number %lu. ", (unsigned long) num);
XX  	printf("This zone (block) is marked in bitmap\n");
XX  	return NOT_OK;
XX    }
XX  }
XX  
XX! void set_bit(num)		/* write in the bitmap */
XX! zone_t num;
XX  {
XX    int rwd;
XX    long blk_offset;
XX!   int blk, offset, words, tst_word, bit;
XX    unsigned z_num;
XX  
XX!   z_num = num - (sp->s_firstdatazone - 1);
XX  
XX!   blk = z_num >> BIT_MAP_SHIFT;	/* which block */
XX!   offset = z_num - (blk << BIT_MAP_SHIFT);	/* offset in block */
XX!   words = z_num / INT_BITS;	/* which word */
XX  
XX!   blk_offset = (long) (2 + sp->s_imap_blocks);
XX    blk_offset *= (long) BLOCK_SIZE;
XX    blk_offset += (long) (words * SIZE_OF_INT);
XX  
XX  
XX!   lseek(fd, (off_t) 0, SEEK_SET);	/* rewind */
XX!   lseek(fd, (off_t) blk_offset, SEEK_SET);
XX  
XX    rwd = read(fd, (char *) &tst_word, SIZE_OF_INT);
XX    if (rwd != SIZE_OF_INT) {
XX***************
XX*** 487,493 ****
XX    bit = offset % INT_BITS;
XX    if (((tst_word >> bit) & 01) == 0) {	/* free */
XX  	lseek(fd, 0L, SEEK_SET);/* rewind */
XX! 	lseek(fd, blk_offset, SEEK_SET);
XX  	tst_word |= (1 << bit);	/* not free anymore */
XX  	rwd = write(fd, (char *) &tst_word, SIZE_OF_INT);
XX  	if (rwd != SIZE_OF_INT) {
XX--- 559,565 ----
XX    bit = offset % INT_BITS;
XX    if (((tst_word >> bit) & 01) == 0) {	/* free */
XX  	lseek(fd, 0L, SEEK_SET);/* rewind */
XX! 	lseek(fd, (off_t) blk_offset, SEEK_SET);
XX  	tst_word |= (1 << bit);	/* not free anymore */
XX  	rwd = write(fd, (char *) &tst_word, SIZE_OF_INT);
XX  	if (rwd != SIZE_OF_INT) {
XX***************
XX*** 497,512 ****
XX  	}
XX  	return;
XX    }
XX!   printf("Bit map indicates that block %u is in use. Not marked.\n",num);
XX  /*  done(DIR_CREATED); */
XX    return;
XX  }
XX  
XX   /* ======= interactive interface ======= */
XX  
XX! rd_num()
XX  {				/* read a number from stdin */
XX!   static num;
XX    int c;
XX  
XX    if (eofseen) return(-1);
XX--- 569,585 ----
XX  	}
XX  	return;
XX    }
XX!   printf("Bit map indicates that block %lu is in use. Not marked.\n",
XX! 	 (unsigned long) num);
XX  /*  done(DIR_CREATED); */
XX    return;
XX  }
XX  
XX   /* ======= interactive interface ======= */
XX  
XX! long rd_num()
XX  {				/* read a number from stdin */
XX!   long num;
XX    int c;
XX  
XX    if (eofseen) return(-1);
XX***************
XX*** 531,537 ****
XX  
XX  
XX  
XX! ok(str)
XX  char *str;
XX  {
XX    int c;
XX--- 604,610 ----
XX  
XX  
XX  
XX! int ok(str)
XX  char *str;
XX  {
XX    int c;
XX***************
XX*** 542,558 ****
XX  	       c != 'y' && c != 'n' && c != 'q')
XX  		if (c != '\n') printf(" Bad character %c\n", (char) c);
XX  	switch (c) {
XX! 	    case EOF:		return QUIT;
XX! 	    case 'y':		return OK;
XX! 	    case 'n':		return NOT_OK;
XX! 	    case 'q':		return QUIT;
XX  	}
XX  	printf("\n");
XX    }
XX  }
XX  
XX  
XX! done(nr)
XX  int nr;
XX  {
XX    switch (nr) {
XX--- 615,634 ----
XX  	       c != 'y' && c != 'n' && c != 'q')
XX  		if (c != '\n') printf(" Bad character %c\n", (char) c);
XX  	switch (c) {
XX! 	    case EOF:
XX! 		return QUIT;
XX! 	    case 'y':
XX! 		return OK;
XX! 	    case 'n':
XX! 		return NOT_OK;
XX! 	    case 'q':	return QUIT;
XX  	}
XX  	printf("\n");
XX    }
XX  }
XX  
XX  
XX! void done(nr)
XX  int nr;
XX  {
XX    switch (nr) {
XX***************
XX*** 562,571 ****
XX        case DEV_MOUNTED:
XX  	umount(dev_name);
XX        case DIR_CREATED:
XX! 	unlink(dir_name);
XX        case HARMLESS:;
XX    }
XX    sync();
XX    exit(nr == SUCCESS ? 0 : 1);
XX  }
XX- 
XX--- 638,646 ----
XX        case DEV_MOUNTED:
XX  	umount(dev_name);
XX        case DIR_CREATED:
XX! 	rmdir(dir_name);
XX        case HARMLESS:;
XX    }
XX    sync();
XX    exit(nr == SUCCESS ? 0 : 1);
XX  }
X/
Xecho x - banner.c.d
Xsed '/^X/s///' > banner.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/banner.c  crc=00311   6597	Sun Apr 25 21:34:46 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/banner.c  crc=52356   6710	Wed Nov  4 07:51:29 1992
XX***************
XX*** 20,59 ****
XX   *
XX   *****************************************************************/
XX  
XX  #include <stdio.h>
XX  
XX  char *glyphs[] = {
XX! 	  "         @@@  @@@ @@@  @ @   @@@@@ @@@   @  @@     @@@  ",
XX! 	"         @@@  @@@ @@@  @ @  @  @  @@ @  @  @  @    @@@   ",
XX! 	  "         @@@   @   @ @@@@@@@@  @   @@@ @    @@      @   ",
XX  	  "          @            @ @   @@@@@    @    @@@     @    ",
XX! 	  "                     @@@@@@@   @  @  @ @@@@   @ @       ",
XX! 	  "         @@@           @ @  @  @  @ @  @ @@    @        ",
XX! 	  "         @@@           @ @   @@@@@ @   @@@ @@@@ @       ",
XX  
XX  	  "   @@    @@                                            @",
XX  	  "  @        @   @   @    @                             @ ",
XX  	  " @          @   @ @     @                            @  ",
XX! 	  " @          @ @@@ @@@ @@@@@   @@@   @@@@@           @   ",
XX! 	  " @          @   @ @     @     @@@           @@@    @    ",
XX  	  "  @        @   @   @    @      @            @@@   @     ",
XX  	  "   @@    @@                   @             @@@  @      ",
XX  
XX  	  "  @@@     @    @@@@@  @@@@@ @      @@@@@@@ @@@@@ @@@@@@@",
XX  	  " @   @   @@   @     @@     @@    @ @      @     @@    @ ",
XX! 	  "@ @   @ @ @         @      @@    @ @      @          @  ",
XX  	  "@  @  @   @    @@@@@  @@@@@ @@@@@@@ @@@@@ @@@@@@    @   ",
XX! 	  "@   @ @   @   @            @     @       @@     @  @    ",
XX  	  " @   @    @   @      @     @     @ @     @@     @  @    ",
XX  	  "  @@@   @@@@@ @@@@@@@ @@@@@      @  @@@@@  @@@@@   @    ",
XX  
XX! 	  " @@@@@  @@@@@    @     @@@      @           @     @@@@@ ",
XX! 	  "@     @@     @  @ @    @@@     @             @   @     @",
XX! 	  "@     @@     @   @            @     @@@@@     @        @",
XX  	  " @@@@@  @@@@@@         @@@   @                 @     @@ ",
XX! 	  "@     @      @   @     @@@    @     @@@@@     @     @   ",
XX! 	  "@     @@     @  @ @     @      @             @          ",
XX! 	  " @@@@@  @@@@@    @     @        @           @       @   ",
XX  
XX  	  " @@@@@    @   @@@@@@  @@@@@ @@@@@@ @@@@@@@@@@@@@@ @@@@@ ",
XX  	  "@     @  @ @  @     @@     @@     @@      @      @     @",
XX--- 20,62 ----
XX   *
XX   *****************************************************************/
XX  
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ 
XX  char *glyphs[] = {
XX! 	  "         @@@  @@   @@  @ @   @@@@@          @@     @@@  ",
XX! 	  "         @@@  @@   @@  @ @  @  @  @@@   @  @  @    @@@  ",
XX! 	  "         @@@   @   @ @@@@@@@@  @   @@  @    @@      @   ",
XX  	  "          @            @ @   @@@@@    @    @@@     @    ",
XX! 	  "                     @@@@@@@   @  @  @    @   @ @       ",
XX! 	  "         @@@           @ @  @  @  @ @  @@ @    @        ",
XX! 	  "         @@@           @ @   @@@@@ @   @@  @@@@ @       ",
XX  
XX  	  "   @@    @@                                            @",
XX  	  "  @        @   @   @    @                             @ ",
XX  	  " @          @   @ @     @                            @  ",
XX! 	  " @          @ @@@@@@@ @@@@@   @@@   @@@@@           @   ",
XX! 	  " @          @   @ @     @     @@@                  @    ",
XX  	  "  @        @   @   @    @      @            @@@   @     ",
XX  	  "   @@    @@                   @             @@@  @      ",
XX  
XX  	  "  @@@     @    @@@@@  @@@@@ @      @@@@@@@ @@@@@ @@@@@@@",
XX  	  " @   @   @@   @     @@     @@    @ @      @     @@    @ ",
XX! 	  "@   @ @ @ @         @      @@    @ @      @          @  ",
XX  	  "@  @  @   @    @@@@@  @@@@@ @@@@@@@ @@@@@ @@@@@@    @   ",
XX! 	  "@ @   @   @   @            @     @       @@     @  @    ",
XX  	  " @   @    @   @      @     @     @ @     @@     @  @    ",
XX  	  "  @@@   @@@@@ @@@@@@@ @@@@@      @  @@@@@  @@@@@   @    ",
XX  
XX! 	  " @@@@@  @@@@@          @@@      @           @     @@@@@ ",
XX! 	  "@     @@     @  @@@    @@@     @             @   @     @",
XX! 	  "@     @@     @  @@@           @     @@@@@     @        @",
XX  	  " @@@@@  @@@@@@         @@@   @                 @     @@ ",
XX! 	  "@     @      @         @@@    @     @@@@@     @     @   ",
XX! 	  "@     @@     @  @@@     @      @             @          ",
XX! 	  " @@@@@  @@@@@   @@@    @        @           @       @   ",
XX  
XX  	  " @@@@@    @   @@@@@@  @@@@@ @@@@@@ @@@@@@@@@@@@@@ @@@@@ ",
XX  	  "@     @  @ @  @     @@     @@     @@      @      @     @",
XX***************
XX*** 117,126 ****
XX  	  "   @@      @      @  @@                 @@        @ @ @ ",
XX  	  "   @@      @     @    @        @        @        @ @ @ @",
XX  	  "  @  @     @    @     @        @        @         @ @ @ ",
XX! 	" @    @    @   @@@@@@  @@@     @     @@@         @ @ @ @"};
XX  
XX! 
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 120,129 ----
XX  	  "   @@      @      @  @@                 @@        @ @ @ ",
XX  	  "   @@      @     @    @        @        @        @ @ @ @",
XX  	  "  @  @     @    @     @        @        @         @ @ @ ",
XX! 	  " @    @    @   @@@@@@  @@@     @     @@@         @ @ @ @"
XX! };
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 134,140 ****
XX  		for (b = 0; b < len; b++) {
XX  			if ((ind = (*argv)[b] - ' ') < 0) ind = 0;
XX  			for (c = 0; c < 7; c++) {
XX! 				line[b * 8 + c] = glyphs[(ind / 8 * 7) + a][(ind % 8 * 7) + c];
XX  			}
XX  			line[b * 8 + 7] = ' ';
XX  		}
XX--- 137,143 ----
XX  		for (b = 0; b < len; b++) {
XX  			if ((ind = (*argv)[b] - ' ') < 0) ind = 0;
XX  			for (c = 0; c < 7; c++) {
XX! 				line[b * 8 + c] = glyphs[(ind / 8 * 7) + a][(ind % 8 * 7) + c] == '@' ? ind + ' ' : ' ';
XX  			}
XX  			line[b * 8 + 7] = ' ';
XX  		}
XX***************
XX*** 146,149 ****
XX--- 149,153 ----
XX  	}
XX  	printf("\n");
XX    }
XX+   return(0);
XX  }
X/
Xecho x - basename.c.d
Xsed '/^X/s///' > basename.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/basename.c  crc=39542    609	Sun Apr 25 21:34:46 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/basename.c  crc=16635   1896	Wed Nov  4 04:19:04 1992
XX***************
XX*** 1,35 ****
XX! /* basename - print the last part of a path:	Author: Blaine Garfolo */
XX  
XX! #define NULL 0
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int j, suflen;
XX!   char *c;
XX!   char *d;
XX!   extern char *rindex();
XX  
XX!   if (argc < 2) {
XX! 	std_err("Usage: basename string [suffix]  \n");
XX  	exit(1);
XX    }
XX-   c = argv[1];
XX-   d = rindex(argv[1], '/');
XX-   if (d == NULL)
XX- 	d = argv[1];
XX-   else
XX- 	d++;
XX  
XX!   if (argc == 2) {		/* if no suffix */
XX! 	prints("%s\n", d);
XX  	exit(0);
XX-   } else {			/* if suffix is present */
XX- 	c = d;
XX- 	suflen = strlen(argv[2]);
XX- 	j = strlen(c) - suflen;
XX- 	if (strcmp(c + j, argv[2]) == 0) *(c + j) = 0;
XX    }
XX!   prints("%s\n", c);
XX  }
XX--- 1,76 ----
XX! /* basename - print last part of a path      Authors: B. Garfolo & P. Nelson */
XX  
XX! /* Basename - print the last part of a path.
XX!  *
XX!  *    For MINIX  --  Conforms to POSIX - P1003.2/D10
XX!  *      Exception -- it ignores the LC environment variables.
XX!  *
XX!  *    Original MINIX author:  Blaine Garfolo
XX!  *    POSIX rewrite author:   Philip A. Nelson
XX!  *
XX!  *    POSIX version - October 20, 1990
XX!  *      Feb 14, 1991: changed rindex to strrchr. (PAN)
XX!  *
XX!  */
XX  
XX! 
XX! #include <string.h>
XX! #include <stdlib.h>
XX! #include <stdio.h>
XX! 
XX! #define EOS '\0'
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   char *result_string;		/* The pointer into argv[1]. */
XX!   char *temp;			/* Used to move around in argv[1]. */
XX!   int suffix_len;		/* Length of the suffix. */
XX!   int suffix_start;		/* Where the suffix should start. */
XX  
XX! 
XX!   /* Check for the correct number of arguments. */
XX!   if ((argc < 2) || (argc > 3)) {
XX! 	fprintf(stderr, "Usage: basename string [suffix] \n");
XX  	exit(1);
XX    }
XX  
XX!   /* Check for all /'s */
XX!   for (temp = argv[1]; *temp == '/'; temp++)	/* Move to next char. */
XX! 	;
XX!   if (*temp == EOS) {
XX! 	printf("/\n");
XX  	exit(0);
XX    }
XX! 
XX!   /* Build the basename. */
XX!   result_string = argv[1];
XX! 
XX!   /* Find the last /'s */
XX!   temp = strrchr(result_string, '/');
XX! 
XX!   if (temp != NULL) {
XX! 	/* Remove trailing /'s. */
XX! 	while ((*(temp + 1) == EOS) && (*temp == '/')) *temp-- = EOS;
XX! 
XX! 	/* Set result_string to last part of path. */
XX! 	if (*temp != '/') temp = strrchr(result_string, '/');
XX! 	if (temp != NULL && *temp == '/') result_string = temp + 1;
XX!   }
XX! 
XX!   /* Remove the suffix, if any. */
XX!   if (argc > 2) {
XX! 	suffix_len = strlen(argv[2]);
XX! 	suffix_start = strlen(result_string) - suffix_len;
XX! 	if (suffix_start > 0)
XX! 		if (strcmp(result_string + suffix_start, argv[2]) == EOS)
XX! 			*(result_string + suffix_start) = EOS;
XX!   }
XX! 
XX!   /* Print the resultant string. */
XX!   printf("%s\n", result_string);
XX!   return(0);
XX  }
X/
Xecho x - btoa.c.d
Xsed '/^X/s///' > btoa.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/btoa.c  crc=57022  28324	Sun Apr 25 21:34:47 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/btoa.c  crc=24998  27635	Wed Nov  4 04:19:05 1992
XX***************
XX*** 71,76 ****
XX--- 71,77 ----
XX  #include <sys/types.h>
XX  #include <ctype.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define MAXPERLINE      78
XX***************
XX*** 91,140 ****
XX    struct Diagnosis *next, *last;
XX  };
XX  
XX- extern char *malloc();
XX- 
XX  /* Following functions have been converted to macros:  calcchecksum() */
XX  
XX  
XX- #if LATTICE			/* Prototypes for Lattice C */
XX- 
XX- void asciiout(int), exit(int),
XX-  intodiaglist(struct Diagnosis *, LONG, LONG),
XX-  outdiaglist(struct Diagnosis *, LONG *, LONG *), printhelp(void),
XX-  producediag(struct Diagnosis *, FILE *), wordout(LONG);
XX- 
XX- BYTE atob(FILE *), btoa(FILE *, BYTE *), copyfile(FILE *, FILE *, BYTE *),
XX-  decode_line(BYTE *, int), new_decodefile(FILE *, LONG *, LONG, int),
XX-  old_decodefile(FILE *, LONG *), performrepair(FILE *),
XX-  pro_repair(FILE *), readbuffer(BYTE *, BYTE *, FILE *),
XX- *truncname(BYTE *);
XX- 
XX- int nextbyte(FILE *);
XX- 
XX- FILE *fopen_read(BYTE *), *fopen_write(BYTE *);
XX- 
XX- #if USE_MACROS
XX- void calcchecksum(int);
XX- #endif /* USE_MACROS */
XX- 
XX- #else /* !LATTICE */	/* For compilers which don't know about prototypes. */
XX- 
XX- void asciiout(), exit(), intodiaglist(), outdiaglist(),
XX-  printhelp(), producediag(), wordout();
XX- 
XX- BYTE atob(), btoa(), copyfile(), decode_line(), new_decodefile(),
XX-  old_decodefile(), performrepair(), pro_repair(), readbuffer(),
XX- *truncname();
XX- 
XX- int nextbyte();
XX- 
XX- FILE *fopen_read(), *fopen_write();
XX- 
XX- #if USE_MACROS
XX- void calcchecksum();
XX- #endif /* USE_MACROS */
XX- 
XX- #endif /* LATTICE */
XX  /* Chksum.h */
XX  /* Calcchecksum() was converted to a macro for effectivity reasons. */
XX  /* Don't (!!) give it an argument that has to be evaluated. This    */
XX--- 92,121 ----
XX    struct Diagnosis *next, *last;
XX  };
XX  
XX  /* Following functions have been converted to macros:  calcchecksum() */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(BYTE btoa, (FILE *infile, BYTE *infilename));
XX+ _PROTOTYPE(void printhelp, (void));
XX+ _PROTOTYPE(void calcchecksum, (int ch));
XX+ _PROTOTYPE(void wordout, (LONG codeword));
XX+ _PROTOTYPE(void asciiout, (int ch));
XX+ _PROTOTYPE(BYTE *truncname, (BYTE *name));
XX+ _PROTOTYPE(BYTE atob, (FILE *infile));
XX+ _PROTOTYPE(int nextbyte, (FILE *infile));
XX+ _PROTOTYPE(BYTE new_decodefile, (FILE *infile, LONG *lastline, LONG filepos, int maxperline));
XX+ _PROTOTYPE(BYTE old_decodefile, (FILE *infile, LONG *lastline));
XX+ _PROTOTYPE(BYTE decode_line, (BYTE *buffer, int length));
XX+ _PROTOTYPE(void producediag, (struct Diagnosis *diaglist, FILE *infile));
XX+ _PROTOTYPE(void intodiaglist, (struct Diagnosis *diaglist, LONG startpos, LONG endpos));
XX+ _PROTOTYPE(void outdiaglist, (struct Diagnosis *diaglist, LONG *startpos, LONG *endpos));
XX+ _PROTOTYPE(BYTE copyfile, (FILE *infile, FILE *outfile, BYTE *searchstring));
XX+ _PROTOTYPE(BYTE readbuffer, (BYTE *buffer, BYTE *errormsg, FILE *infile));
XX+ _PROTOTYPE(FILE *fopen_read, (BYTE *filename));
XX+ _PROTOTYPE(FILE *fopen_write, (BYTE *filename));
XX+ _PROTOTYPE(BYTE pro_repair, (FILE *infile));
XX+ _PROTOTYPE(BYTE performrepair, (FILE *infile));
XX  
XX  /* Chksum.h */
XX  /* Calcchecksum() was converted to a macro for effectivity reasons. */
XX  /* Don't (!!) give it an argument that has to be evaluated. This    */
XX***************
XX*** 144,151 ****
XX  
XX  #define calcchecksum(ch)        \
XX  {                               \
XX-   extern LONG Ceor, Csum, Crot; \
XX-                                 \
XX    Ceor ^= ch;                   \
XX    Csum += ch + 1;               \
XX                                  \
XX--- 125,130 ----
XX***************
XX*** 177,191 ****
XX  FILE *outfile;
XX  
XX  
XX! void main(argc, argv)
XX  int argc;
XX! BYTE **argv;
XX  {
XX    register BYTE openinput, error, ch, a_to_b, diag, repair;
XX    register BYTE *infilename, *text;
XX    register FILE *infile;
XX-   extern BYTE new_version, openoutput;
XX-   extern FILE *outfile;
XX  #ifdef AMIGA
XX    extern int _bufsiz;
XX  
XX--- 156,168 ----
XX  FILE *outfile;
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX! char **argv;
XX  {
XX    register BYTE openinput, error, ch, a_to_b, diag, repair;
XX    register BYTE *infilename, *text;
XX    register FILE *infile;
XX  #ifdef AMIGA
XX    extern int _bufsiz;
XX  
XX***************
XX*** 267,272 ****
XX--- 244,250 ----
XX    if (openoutput) fclose(outfile);
XX  
XX    if (error) exit(1);
XX+   return(0);
XX  }
XX  
XX  
XX***************
XX*** 276,284 ****
XX  {
XX    register LONG codeword, filesize;
XX    register int ch1, ch2, ch3, ch4, readbytes;
XX-   extern FILE *outfile;
XX-   extern BYTE new_version, buffer[BUFSIZE];
XX-   extern LONG Ceor, Csum, Crot;
XX  
XX    Ceor = Csum = Crot = 0;
XX  
XX--- 254,259 ----
XX***************
XX*** 292,298 ****
XX    /* Encode entire input file. */
XX    filesize = 0;
XX    do {
XX! 	readbytes = fread(buffer, 1, 4, infile);
XX  
XX  	if (readbytes < 4) {
XX  		ch1 = (readbytes > 0) ? ((int) buffer[0] & 0xFF) : 0;
XX--- 267,273 ----
XX    /* Encode entire input file. */
XX    filesize = 0;
XX    do {
XX! 	readbytes = fread(buffer, (size_t)1, (size_t)4, infile);
XX  
XX  	if (readbytes < 4) {
XX  		ch1 = (readbytes > 0) ? ((int) buffer[0] & 0xFF) : 0;
XX***************
XX*** 362,369 ****
XX  void calcchecksum(ch)
XX  register int ch;
XX  {
XX-   extern LONG Ceor, Csum, Crot;
XX- 
XX    Ceor ^= ch;
XX    Csum += ch + 1;
XX  
XX--- 337,342 ----
XX***************
XX*** 380,386 ****
XX  register LONG codeword;
XX  {
XX    register int tmp, quote;
XX-   extern BYTE new_version;
XX  
XX    if (codeword == 0)		/* Encode 4 zeros as a 'z'. */
XX  	asciiout('z');
XX--- 353,358 ----
XX***************
XX*** 429,437 ****
XX  register int ch;
XX  {
XX    static WORD linepos = 0;
XX-   extern FILE *outfile;
XX-   extern LONG Csum;
XX-   extern BYTE new_version;
XX  
XX    if (ch == EOF) {		/* Signal to flush buffer. */
XX  	/* Linepos == 0 means '\n' just written in asciiout(). This */
XX--- 401,406 ----
XX***************
XX*** 495,503 ****
XX    int maxperline;
XX    LONG n1, n2, oeor, osum, orot, lastline;
XX    static BYTE outfilename[BUFSIZE];
XX-   extern LONG Ceor, Csum, Crot;
XX-   extern FILE *outfile;
XX-   extern BYTE new_version, openoutput, buffer[BUFSIZE];
XX  
XX    error = FALSE;
XX  
XX--- 464,469 ----
XX***************
XX*** 507,513 ****
XX  
XX  	if (readbuffer(buffer, "archive", infile)) error = TRUE;
XX    }
XX!   while (!(error || strncmp(buffer, "xbtoa", 5) == 0));
XX  
XX    if (!error)
XX  	if (strcmp(buffer, "xbtoa Begin\n") == 0) {
XX--- 473,479 ----
XX  
XX  	if (readbuffer(buffer, "archive", infile)) error = TRUE;
XX    }
XX!   while (!(error || strncmp(buffer, "xbtoa", (size_t)5) == 0));
XX  
XX    if (!error)
XX  	if (strcmp(buffer, "xbtoa Begin\n") == 0) {
XX***************
XX*** 577,584 ****
XX    register BYTE stop, error, newerror, errorstart;
XX    register LONG line, prevfilepos, startpos;
XX    struct Diagnosis diaglist;
XX-   extern LONG Csum;
XX-   extern BYTE buffer[BUFSIZE];
XX  
XX    error = FALSE;
XX  
XX--- 543,548 ----
XX***************
XX*** 620,644 ****
XX  		}
XX  		if (newerror)
XX  			fprintf(stderr, "btoa: Bad line length on line %ld.\n", line);
XX! 	}
XX! 	if (!(newerror || stop)) {
XX! 		if (decode_line(buffer, length - 1)) {
XX! 			if (!error)
XX! 				fprintf(stderr, "btoa: Bad character on line %ld.\n", line);
XX! 			newerror = TRUE;
XX! 		}
XX! 
XX! 		/* Examine checksum. */
XX! 		if ((ch = buffer[length - 1]) == ENCODE(Csum % 85)) {
XX! 			if (errorstart) {
XX! 				intodiaglist(&diaglist, startpos, filepos);
XX! 				errorstart = FALSE;
XX  			}
XX! 		} else {
XX! 			newerror = TRUE;
XX! 			fprintf(stderr, "btoa: Bad checksum on line %ld.\n", line);
XX! 			Csum = DECODE(ch);	/* Make Csum correct
XX! 						 * (modulo 85). */
XX  		}
XX  	}
XX  	if (newerror) {
XX--- 584,608 ----
XX  		}
XX  		if (newerror)
XX  			fprintf(stderr, "btoa: Bad line length on line %ld.\n", line);
XX! 		if (!(newerror || stop)) {
XX! 			if (decode_line(buffer, length - 1)) {
XX! 				if (!error)
XX! 					fprintf(stderr, "btoa: Bad character on line %ld.\n", line);
XX! 				newerror = TRUE;
XX  			}
XX! 	
XX! 			/* Examine checksum. */
XX! 			if ((ch = buffer[length - 1]) == ENCODE(Csum % 85)) {
XX! 				if (errorstart) {
XX! 					intodiaglist(&diaglist, startpos, filepos);
XX! 					errorstart = FALSE;
XX! 				}
XX! 			} else {
XX! 				newerror = TRUE;
XX! 				fprintf(stderr, "btoa: Bad checksum on line %ld.\n", line);
XX! 				Csum = DECODE(ch);	/* Make Csum correct
XX! 							 * (modulo 85). */
XX! 			}
XX  		}
XX  	}
XX  	if (newerror) {
XX***************
XX*** 672,678 ****
XX    register int length;
XX    register BYTE stop, error;
XX    register LONG line;
XX-   extern BYTE buffer[BUFSIZE];
XX  
XX    error = FALSE;
XX  
XX--- 636,641 ----
XX***************
XX*** 690,703 ****
XX  		if (buffer[length] != '\n')
XX  			error = stop = TRUE;	/* The line was longer
XX  						 * than the buffer. */
XX! 	}
XX! 
XX! 	if (!stop) {
XX! 		if (decode_line(buffer, length)) {
XX! 			fprintf(stderr, "btoa: Bad character on line %ld.\n", line);
XX! 			error = stop = TRUE;
XX  		}
XX  	}
XX    }
XX  
XX    *lastline = line;
XX--- 653,666 ----
XX  		if (buffer[length] != '\n')
XX  			error = stop = TRUE;	/* The line was longer
XX  						 * than the buffer. */
XX! 		else {
XX! 			if (decode_line(buffer, length)) {
XX! 				fprintf(stderr, "btoa: Bad character on line %ld.\n", line);
XX! 				error = stop = TRUE;
XX! 			}
XX  		}
XX  	}
XX+ 
XX    }
XX  
XX    *lastline = line;
XX***************
XX*** 706,727 ****
XX  }
XX  
XX  
XX! BYTE decode_line(buffer, length)
XX! register BYTE *buffer;
XX  register int length;
XX  {
XX    register int ch;
XX    register BYTE error;
XX    register LONG tmp_codeword;
XX-   extern BYTE new_version;
XX-   extern FILE *outfile;
XX    static LONG codeword;
XX    static int ch1, ch2, ch3, ch4;
XX    static BYTE bytecount = 0;
XX  
XX    error = FALSE;
XX  
XX!   if (buffer == NULL) {		/* Flush last characters. */
XX  	if (bytecount > 0) {
XX  		fputc(ch1, outfile);
XX  		if (length > 0) fputc(ch2, outfile);
XX--- 669,688 ----
XX  }
XX  
XX  
XX! BYTE decode_line(buf, length)
XX! register BYTE *buf;
XX  register int length;
XX  {
XX    register int ch;
XX    register BYTE error;
XX    register LONG tmp_codeword;
XX    static LONG codeword;
XX    static int ch1, ch2, ch3, ch4;
XX    static BYTE bytecount = 0;
XX  
XX    error = FALSE;
XX  
XX!   if (buf == NULL) {		/* Flush last characters. */
XX  	if (bytecount > 0) {
XX  		fputc(ch1, outfile);
XX  		if (length > 0) fputc(ch2, outfile);
XX***************
XX*** 731,737 ****
XX    } else {
XX  	while (length > 0) {
XX  		length--;
XX! 		ch = *buffer++;
XX  
XX  		/* Delayed output. This is to make sure that files
XX  		 * with lengths */
XX--- 692,698 ----
XX    } else {
XX  	while (length > 0) {
XX  		length--;
XX! 		ch = *buf++;
XX  
XX  		/* Delayed output. This is to make sure that files
XX  		 * with lengths */
XX***************
XX*** 760,766 ****
XX  					codeword = codeword * 85 + DECODE(ch);
XX  
XX  				for (bytecount++; bytecount < 5; bytecount++) {
XX! 					ch = *buffer++;
XX  					if (new_version) calcchecksum(ch);
XX  					codeword = codeword * 85 + DECODE(ch);
XX  				}
XX--- 721,727 ----
XX  					codeword = codeword * 85 + DECODE(ch);
XX  
XX  				for (bytecount++; bytecount < 5; bytecount++) {
XX! 					ch = *buf++;
XX  					if (new_version) calcchecksum(ch);
XX  					codeword = codeword * 85 + DECODE(ch);
XX  				}
XX***************
XX*** 842,848 ****
XX    register FILE *diagfile;
XX    LONG startpos, endpos;
XX    register LONG currentpos;
XX-   extern BYTE *diagname, *diagheader, buffer[BUFSIZE];
XX  
XX    currentpos = ftell(infile);
XX  
XX--- 803,808 ----
XX***************
XX*** 918,932 ****
XX  
XX  	diaglist->next = diagitem->next;
XX  	free((BYTE *) diagitem);
XX! 	if (diaglist->next == NULL) diaglist->last = NULL;
XX    }
XX  }
XX  
XX  
XX  /* Copy infile to outfile until searchstring is found. If outfile */
XX  /* Is NULL nothing will be written.                               */
XX! BYTE copyfile(infile, outfile, searchstring)
XX! register FILE *infile, *outfile;
XX  register BYTE *searchstring;
XX  {
XX    register BYTE stop, error;
XX--- 878,893 ----
XX  
XX  	diaglist->next = diagitem->next;
XX  	free((BYTE *) diagitem);
XX! 	if (diaglist->next == NULL)
XX! 	    diaglist->last = NULL;
XX    }
XX  }
XX  
XX  
XX  /* Copy infile to outfile until searchstring is found. If outfile */
XX  /* Is NULL nothing will be written.                               */
XX! BYTE copyfile(infile, outfil, searchstring)
XX! register FILE *infile, *outfil;
XX  register BYTE *searchstring;
XX  {
XX    register BYTE stop, error;
XX***************
XX*** 937,943 ****
XX  	if (readbuffer(copybuffer, "archive", infile))
XX  		error = TRUE;
XX  	else {
XX! 		if (outfile != NULL) fputs(copybuffer, outfile);
XX  		if (strcmp(copybuffer, searchstring) == 0) stop = TRUE;
XX  	}
XX  
XX--- 898,904 ----
XX  	if (readbuffer(copybuffer, "archive", infile))
XX  		error = TRUE;
XX  	else {
XX! 		if (outfil != NULL) fputs(copybuffer, outfil);
XX  		if (strcmp(copybuffer, searchstring) == 0) stop = TRUE;
XX  	}
XX  
XX***************
XX*** 947,960 ****
XX  
XX  /* Read a line from infile into buffer. Returns TRUE if */
XX  /* End-of-file has been reached.                        */
XX! BYTE readbuffer(buffer, errormsg, infile)
XX! register BYTE *buffer, *errormsg;
XX  register FILE *infile;
XX  {
XX    register BYTE error;
XX  
XX    error = FALSE;
XX!   if (fgets(buffer, BUFSIZE, infile) == NULL) {
XX  	fprintf(stderr, "btoa: Unexpected end of %s file.\n", errormsg);
XX  	error = TRUE;
XX    }
XX--- 908,921 ----
XX  
XX  /* Read a line from infile into buffer. Returns TRUE if */
XX  /* End-of-file has been reached.                        */
XX! BYTE readbuffer(buf, errormsg, infile)
XX! register BYTE *buf, *errormsg;
XX  register FILE *infile;
XX  {
XX    register BYTE error;
XX  
XX    error = FALSE;
XX!   if (fgets(buf, BUFSIZE, infile) == NULL) {
XX  	fprintf(stderr, "btoa: Unexpected end of %s file.\n", errormsg);
XX  	error = TRUE;
XX    }
XX***************
XX*** 977,988 ****
XX  FILE *fopen_write(filename)
XX  register BYTE *filename;
XX  {
XX!   register FILE *outfile;
XX  
XX!   if ((outfile = fopen(filename, "w")) == NULL)
XX  	fprintf(stderr, "btoa: Can't open '%s' for output.\n", filename);
XX  
XX!   return(outfile);
XX  }
XX  
XX  
XX--- 938,949 ----
XX  FILE *fopen_write(filename)
XX  register BYTE *filename;
XX  {
XX!   register FILE *outfil;
XX  
XX!   if ((outfil = fopen(filename, "w")) == NULL)
XX  	fprintf(stderr, "btoa: Can't open '%s' for output.\n", filename);
XX  
XX!   return(outfil);
XX  }
XX  
XX  
XX***************
XX*** 993,999 ****
XX    register FILE *repairfile, *diagfile;
XX    register BYTE error, stop;
XX    static BYTE *errormsg = "diag";
XX-   extern BYTE *diagname, *diagheader, *repairname, *repairheader, buffer[BUFSIZE];
XX  
XX    error = FALSE;
XX    diagfile = repairfile = NULL;
XX--- 954,959 ----
XX***************
XX*** 1059,1065 ****
XX    register FILE *repairfile, *outfile;
XX    register BYTE error, stop;
XX    static BYTE *errormsg = "repair";
XX-   extern BYTE *repairname, *repairedname, *repairheader, buffer[BUFSIZE];
XX  
XX    error = FALSE;
XX    repairfile = outfile = NULL;
XX--- 1019,1024 ----
XX***************
XX*** 1104,1114 ****
XX    }
XX  
XX    if (!error)			/* Write rest of archive. */
XX! 	while (fgets(buffer, BUFSIZE, infile) != NULL)
XX  		fputs(buffer, outfile);
XX  
XX!   if (outfile != NULL) fclose(outfile);
XX!   if (repairfile != NULL) fclose(repairfile);
XX  
XX    return(error);
XX  }
XX--- 1063,1073 ----
XX    }
XX  
XX    if (!error)			/* Write rest of archive. */
XX! 	while (fgets(buffer, BUFSIZE, infile) != (char *)NULL)
XX  		fputs(buffer, outfile);
XX  
XX!   if (outfile != (FILE *)NULL) fclose(outfile);
XX!   if (repairfile != (FILE *)NULL) fclose(repairfile);
XX  
XX    return(error);
XX  }
X/
Xecho x - cal.c.d
Xsed '/^X/s///' > cal.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cal.c  crc=01661   7795	Sun Apr 25 21:34:47 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cal.c  crc=26281   8318	Wed Nov  4 04:19:05 1992
XX***************
XX*** 1,5 ****
XX--- 1,7 ----
XX  /* cal - print a calendar		Author: Maritn Minow */
XX  
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  #define do3months	domonth
XX***************
XX*** 31,41 ****
XX  	     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
XX  };
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX-   register int month;
XX    register int year;
XX  
XX    register int arg1val;
XX--- 33,53 ----
XX  	     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
XX  };
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void doyear, (int year));
XX! _PROTOTYPE(void domonth, (int year, int month));
XX! _PROTOTYPE(void output, (int nmonths));
XX! _PROTOTYPE(void calendar, (int year, int month, int indx));
XX! _PROTOTYPE(void usage, (char *s));
XX! _PROTOTYPE(int date, (int year, int month, int week, int wday));
XX! _PROTOTYPE(void setmonth, (int year, int month));
XX! _PROTOTYPE(int getdate, (int week, int wday));
XX! _PROTOTYPE(static int Jan1, (int year));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    register int year;
XX  
XX    register int arg1val;
XX***************
XX*** 64,73 ****
XX  			do3months(arg2val, arg1val);
XX  	}
XX    }
XX!   exit(IO_SUCCESS);
XX  }
XX  
XX! doyear(year)
XX  int year;
XX  /* Print the calendar for an entire year. */
XX  {
XX--- 76,85 ----
XX  			do3months(arg2val, arg1val);
XX  	}
XX    }
XX!   return(IO_SUCCESS);
XX  }
XX  
XX! void doyear(year)
XX  int year;
XX  /* Print the calendar for an entire year. */
XX  {
XX***************
XX*** 95,101 ****
XX    printf("\n\n\n");
XX  }
XX  
XX! domonth(year, month)
XX  int year;
XX  int month;
XX  /* Do one specific month -- note: no longer used */
XX--- 107,113 ----
XX    printf("\n\n\n");
XX  }
XX  
XX! void domonth(year, month)
XX  int year;
XX  int month;
XX  /* Do one specific month -- note: no longer used */
XX***************
XX*** 108,114 ****
XX    printf("\n\n");
XX  }
XX  
XX! output(nmonths)
XX  int nmonths;			/* Number of months to do	 */
XX  /* Clean up and output the text. */
XX  {
XX--- 120,126 ----
XX    printf("\n\n");
XX  }
XX  
XX! void output(nmonths)
XX  int nmonths;			/* Number of months to do	 */
XX  /* Clean up and output the text. */
XX  {
XX***************
XX*** 135,144 ****
XX    }
XX  }
XX  
XX! calendar(year, month, index)
XX  int year;
XX  int month;
XX! int index;			/* Which of the three months		 */
XX  /* Actually build the calendar for this month. */
XX  {
XX    register char *tp;
XX--- 147,156 ----
XX    }
XX  }
XX  
XX! void calendar(year, month, indx)
XX  int year;
XX  int month;
XX! int indx;			/* Which of the three months		 */
XX  /* Actually build the calendar for this month. */
XX  {
XX    register char *tp;
XX***************
XX*** 149,155 ****
XX    setmonth(year, month);
XX    for (week = 0; week < WEEKS_PER_MONTH; week++) {
XX  	for (wday = 0; wday < DAYS_PER_WEEK; wday++) {
XX! 		tp = &layout[index][week][wday][0];
XX  		*tp++ = ' ';
XX  		today = getdate(week, wday);
XX  		if (today <= 0) {
XX--- 161,167 ----
XX    setmonth(year, month);
XX    for (week = 0; week < WEEKS_PER_MONTH; week++) {
XX  	for (wday = 0; wday < DAYS_PER_WEEK; wday++) {
XX! 		tp = &layout[indx][week][wday][0];
XX  		*tp++ = ' ';
XX  		today = getdate(week, wday);
XX  		if (today <= 0) {
XX***************
XX*** 166,172 ****
XX    }
XX  }
XX  
XX! usage(s)
XX  char *s;
XX  {
XX  /* Fatal parameter error. */
XX--- 178,184 ----
XX    }
XX  }
XX  
XX! void usage(s)
XX  char *s;
XX  {
XX  /* Fatal parameter error. */
XX***************
XX*** 220,226 ****
XX    return(getdate(week, wday));
XX  }
XX  
XX! setmonth(year, month)
XX  int year;			/* Year to compute		 */
XX  int month;			/* Month, January is month 1	 */
XX  /* Setup the parameters needed to compute this month
XX--- 232,238 ----
XX    return(getdate(week, wday));
XX  }
XX  
XX! void setmonth(year, month)
XX  int year;			/* Year to compute		 */
XX  int month;			/* Month, January is month 1	 */
XX  /* Setup the parameters needed to compute this month
X/
Xecho x - cat.c.d
Xsed '/^X/s///' > cat.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cat.c  crc=32311   1702	Sun Apr 25 21:34:47 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cat.c  crc=45262   1967	Wed Nov  4 04:19:05 1992
XX***************
XX*** 8,19 ****
XX--- 8,27 ----
XX  #include <fcntl.h>
XX  #include <string.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX  static int unbuffered;
XX  static char ibuf[BLOCK_SIZE];
XX  static char obuf[BLOCK_SIZE];
XX  static char *op = obuf;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void copyfile, (int ifd, int ofd));
XX+ _PROTOTYPE(void flush, (void));
XX+ _PROTOTYPE(void fatal, (void));
XX+ 
XX  int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX***************
XX*** 46,55 ****
XX  	}
XX    }
XX    flush();
XX!   exit(0);
XX  }
XX  
XX! copyfile(ifd, ofd)
XX  int ifd, ofd;
XX  {
XX    int n;
XX--- 54,63 ----
XX  	}
XX    }
XX    flush();
XX!   return(0);
XX  }
XX  
XX! void copyfile(ifd, ofd)
XX  int ifd, ofd;
XX  {
XX    int n;
XX***************
XX*** 65,91 ****
XX  
XX  		bytes_left = &obuf[BLOCK_SIZE] - op;
XX  		if (n <= bytes_left) {
XX! 			memcpy(op, ibuf, n);
XX  			op += n;
XX  		} else {
XX! 			memcpy(op, ibuf, bytes_left);
XX  			if (write(ofd, obuf, BLOCK_SIZE) != BLOCK_SIZE)
XX  				fatal();
XX  			n -= bytes_left;
XX! 			memcpy(obuf, ibuf + bytes_left, n);
XX  			op = obuf + n;
XX  		}
XX  	}
XX    }
XX  }
XX  
XX! flush()
XX  {
XX    if (op != obuf)
XX  	if (write(STDOUT_FILENO, obuf, (size_t) (op - obuf)) <= 0) fatal();
XX  }
XX  
XX! fatal()
XX  {
XX    perror("cat");
XX    exit(1);
XX--- 73,99 ----
XX  
XX  		bytes_left = &obuf[BLOCK_SIZE] - op;
XX  		if (n <= bytes_left) {
XX! 			memcpy(op, ibuf, (size_t)n);
XX  			op += n;
XX  		} else {
XX! 			memcpy(op, ibuf, (size_t)bytes_left);
XX  			if (write(ofd, obuf, BLOCK_SIZE) != BLOCK_SIZE)
XX  				fatal();
XX  			n -= bytes_left;
XX! 			memcpy(obuf, ibuf + bytes_left, (size_t)n);
XX  			op = obuf + n;
XX  		}
XX  	}
XX    }
XX  }
XX  
XX! void flush()
XX  {
XX    if (op != obuf)
XX  	if (write(STDOUT_FILENO, obuf, (size_t) (op - obuf)) <= 0) fatal();
XX  }
XX  
XX! void fatal()
XX  {
XX    perror("cat");
XX    exit(1);
X/
Xecho x - cdiff.c.d
Xsed '/^X/s///' > cdiff.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cdiff.c  crc=55503   5669	Sun Apr 25 21:34:47 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cdiff.c  crc=41225   7712	Sun Jan 17 20:52:39 1993
XX***************
XX*** 9,21 ****
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <ctype.h>
XX  #include <stdio.h>
XX  
XX  char buff[512];
XX  
XX  FILE *inputfp, *oldfp, *newfp;
XX- char *ctime();
XX  
XX  int oldmin, oldmax, newmin, newmax;
XX  int oldbeg, oldend, newbeg, newend;
XX--- 9,27 ----
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <sys/wait.h>
XX  #include <ctype.h>
XX+ #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <time.h>
XX+ #include <unistd.h>
XX+ #include <limits.h>
XX  #include <stdio.h>
XX  
XX  char buff[512];
XX  
XX  FILE *inputfp, *oldfp, *newfp;
XX  
XX  int oldmin, oldmax, newmin, newmax;
XX  int oldbeg, oldend, newbeg, newend;
XX***************
XX*** 24,60 ****
XX  int oldwanted, newwanted;
XX  
XX  char *oldhunk, *newhunk;
XX! unsigned oldsize, oldalloc, newsize, newalloc;
XX  
XX! void dumphunk();
XX! char *getold();
XX! char *getnew();
XX! char *malloc();
XX! char *realloc();
XX! char *fgets();
XX! FILE *popen();
XX  
XX  #define Nullfp (FILE*)0
XX  #define Nullch (char*)0
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX    char *old, *new;
XX    int context = 3;
XX    struct stat statbuf;
XX    register char *s;
XX    char op;
XX    char *newmark, *oldmark;
XX    int len;
XX    char *line;
XX    int i;
XX  
XX    oldalloc = 512;
XX!   oldhunk = malloc(oldalloc);
XX    newalloc = 512;
XX!   newhunk = malloc(newalloc);
XX  
XX    for (argc--, argv++; argc; argc--, argv++) {
XX  	if (argv[0][0] != '-') break;
XX--- 30,72 ----
XX  int oldwanted, newwanted;
XX  
XX  char *oldhunk, *newhunk;
XX! char *progname;
XX! size_t oldsize, oldalloc, newsize, newalloc;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void dumphunk, (void));
XX! _PROTOTYPE(char *getold, (int targ));
XX! _PROTOTYPE(char *getnew, (int targ));
XX! _PROTOTYPE(void *xmalloc, (size_t size));
XX! _PROTOTYPE(void *xrealloc, (void *ptr, size_t size));
XX  
XX  #define Nullfp (FILE*)0
XX  #define Nullch (char*)0
XX+ #define ENOUGH (NAME_MAX + PATH_MAX + 1)
XX+ #define CRC_END 12
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX+   FILE *crcfp;
XX    char *old, *new;
XX    int context = 3;
XX    struct stat statbuf;
XX    register char *s;
XX    char op;
XX    char *newmark, *oldmark;
XX+   char sysbuf1[ENOUGH], sysbuf2[ENOUGH];
XX    int len;
XX    char *line;
XX    int i;
XX+   int status;
XX  
XX+   progname = argv[0];
XX    oldalloc = 512;
XX!   oldhunk = (char *) xmalloc(oldalloc);
XX    newalloc = 512;
XX!   newhunk = (char *) xmalloc(newalloc);
XX  
XX    for (argc--, argv++; argc; argc--, argv++) {
XX  	if (argv[0][0] != '-') break;
XX***************
XX*** 64,94 ****
XX  
XX    if (argc != 2) {
XX  	fprintf(stderr, "Usage: cdiff old new\n");
XX! 	exit(1);
XX    }
XX    old = argv[0];
XX    new = argv[1];
XX  
XX-   sprintf(buff, "diff %s %s", old, new);
XX-   inputfp = popen(buff, "r");
XX-   if (!inputfp) {
XX- 	fprintf(stderr, "Can't execute diff %s %s\n", old, new);
XX- 	exit(1);
XX-   }
XX    oldfp = fopen(old, "r");
XX    if (!oldfp) {
XX  	fprintf(stderr, "Can't open %s\n", old);
XX! 	exit(1);
XX    }
XX    newfp = fopen(new, "r");
XX    if (!newfp) {
XX  	fprintf(stderr, "Can't open %s\n", new);
XX! 	exit(1);
XX    }
XX    fstat(fileno(oldfp), &statbuf);
XX!   printf("*** %s\t%s", old, ctime(&statbuf.st_mtime));
XX    fstat(fileno(newfp), &statbuf);
XX!   printf("--- %s\t%s", new, ctime(&statbuf.st_mtime));
XX  
XX    preoldend = -1000;
XX  
XX--- 76,142 ----
XX  
XX    if (argc != 2) {
XX  	fprintf(stderr, "Usage: cdiff old new\n");
XX! 	exit(2);
XX    }
XX    old = argv[0];
XX    new = argv[1];
XX  
XX    oldfp = fopen(old, "r");
XX    if (!oldfp) {
XX  	fprintf(stderr, "Can't open %s\n", old);
XX! 	exit(2);
XX    }
XX    newfp = fopen(new, "r");
XX    if (!newfp) {
XX  	fprintf(stderr, "Can't open %s\n", new);
XX! 	exit(2);
XX    }
XX+ 
XX+   /* Compute crcs by popen()ing crc and reading the output.  Do this before
XX+    * popen()ing diff to do the work.  popen() attempts to support multiple
XX+    * clients, but the 1.3-1.6.24b versions don't succeed.
XX+    */
XX+   sprintf(sysbuf1, "crc %s", old);
XX+   crcfp = popen(sysbuf1, "r");
XX+   if (!crcfp) {
XX+ 	/* The only advantage of cdiff over diff is that it prints crcs, so
XX+ 	 * give up easily if crc fails.
XX+ 	 */
XX+ 	fprintf(stderr, "Can't execute crc %s\n", old);
XX+ 	exit(2);
XX+   }
XX+   fgets(sysbuf1, sizeof(sysbuf1), crcfp);
XX+   sysbuf1[CRC_END] = '\0';
XX+   status = pclose(crcfp);
XX+   if (status != 0) {
XX+ 	fprintf(stderr, "crc %s returned bad status %d\n", old, status);
XX+ 	exit(2);
XX+   }
XX+   sprintf(sysbuf2, "crc %s", new);
XX+   crcfp = popen(sysbuf2, "r");
XX+   if (!crcfp) {
XX+ 	fprintf(stderr, "Can't execute crc %s\n", new);
XX+ 	exit(2);
XX+   }
XX+   fgets(sysbuf2, sizeof(sysbuf2), crcfp);
XX+   sysbuf2[CRC_END] = '\0';
XX+   status = pclose(crcfp);
XX+   if (status != 0) {
XX+ 	fprintf(stderr, "crc %s returned bad status %d\n", new, status);
XX+ 	exit(2);
XX+   }
XX+ 
XX+   sprintf(buff, "diff %s %s 2>/dev/null", old, new);
XX+   inputfp = popen(buff, "r");
XX+   if (!inputfp) {
XX+ 	fprintf(stderr, "Can't execute diff %s %s\n", old, new);
XX+ 	exit(2);
XX+   }
XX+ 
XX    fstat(fileno(oldfp), &statbuf);
XX!   printf("*** %s  crc=%s\t%s", old, sysbuf1, ctime(&statbuf.st_mtime));
XX    fstat(fileno(newfp), &statbuf);
XX!   printf("--- %s  crc=%s\t%s", new, sysbuf2, ctime(&statbuf.st_mtime));
XX  
XX    preoldend = -1000;
XX  
XX***************
XX*** 104,111 ****
XX  			oldmax = oldmin;
XX  		}
XX  		if (*s != 'a' && *s != 'd' && *s != 'c') {
XX! 			fprintf(stderr, "Unparseable input: %s", s);
XX! 			exit(1);
XX  		}
XX  		op = *s;
XX  		s++;
XX--- 152,159 ----
XX  			oldmax = oldmin;
XX  		}
XX  		if (*s != 'a' && *s != 'd' && *s != 'c') {
XX! 			fprintf(stderr, "Unparseable input: %s\n", s);
XX! 			exit(2);
XX  		}
XX  		op = *s;
XX  		s++;
XX***************
XX*** 119,126 ****
XX  			newmax = newmin;
XX  		}
XX  		if (*s != '\n' && *s != ' ') {
XX! 			fprintf(stderr, "Unparseable input: %s", s);
XX! 			exit(1);
XX  		}
XX  		newmark = oldmark = "! ";
XX  		if (op == 'a') {
XX--- 167,174 ----
XX  			newmax = newmin;
XX  		}
XX  		if (*s != '\n' && *s != ' ') {
XX! 			fprintf(stderr, "Unparseable input: %s\n", s);
XX! 			exit(2);
XX  		}
XX  		newmark = oldmark = "! ";
XX  		if (op == 'a') {
XX***************
XX*** 153,166 ****
XX  
XX  		for (i = oldbeg; i <= oldmax; i++) {
XX  			line = getold(i);
XX! 			if (!*line) {
XX  				oldend = oldmax = i - 1;
XX  				break;
XX  			}
XX  			len = strlen(line) + 2;
XX  			if (oldsize + len + 1 >= oldalloc) {
XX  				oldalloc *= 2;
XX! 				oldhunk = realloc(oldhunk, oldalloc);
XX  			}
XX  			if (i >= oldmin) {
XX  				strcpy(oldhunk + oldsize, oldmark);
XX--- 201,214 ----
XX  
XX  		for (i = oldbeg; i <= oldmax; i++) {
XX  			line = getold(i);
XX! 			if (!line) {
XX  				oldend = oldmax = i - 1;
XX  				break;
XX  			}
XX  			len = strlen(line) + 2;
XX  			if (oldsize + len + 1 >= oldalloc) {
XX  				oldalloc *= 2;
XX! 				oldhunk = (char *) xrealloc(oldhunk, oldalloc);
XX  			}
XX  			if (i >= oldmin) {
XX  				strcpy(oldhunk + oldsize, oldmark);
XX***************
XX*** 176,189 ****
XX  
XX  		for (i = newbeg; i <= newmax; i++) {
XX  			line = getnew(i);
XX! 			if (!*line) {
XX  				newend = newmax = i - 1;
XX  				break;
XX  			}
XX  			len = strlen(line) + 2;
XX  			if (newsize + len + 1 >= newalloc) {
XX  				newalloc *= 2;
XX! 				newhunk = realloc(newhunk, newalloc);
XX  			}
XX  			if (i >= newmin) {
XX  				strcpy(newhunk + newsize, newmark);
XX--- 224,237 ----
XX  
XX  		for (i = newbeg; i <= newmax; i++) {
XX  			line = getnew(i);
XX! 			if (!line) {
XX  				newend = newmax = i - 1;
XX  				break;
XX  			}
XX  			len = strlen(line) + 2;
XX  			if (newsize + len + 1 >= newalloc) {
XX  				newalloc *= 2;
XX! 				newhunk = (char *) xrealloc(newhunk, newalloc);
XX  			}
XX  			if (i >= newmin) {
XX  				strcpy(newhunk + newsize, newmark);
XX***************
XX*** 202,207 ****
XX--- 250,259 ----
XX    if (preoldend >= 0) {
XX  	dumphunk();
XX    }
XX+   status = pclose(inputfp);
XX+   if (!WIFEXITED(status)) exit(2);
XX+   status = WEXITSTATUS(status);
XX+   return(status == 0 || status == 1 ? status : 2);
XX  }
XX  
XX  void dumphunk()
XX***************
XX*** 219,225 ****
XX  	len = strlen(line) + 2;
XX  	if (oldsize + len + 1 >= oldalloc) {
XX  		oldalloc *= 2;
XX! 		oldhunk = realloc(oldhunk, oldalloc);
XX  	}
XX  	strcpy(oldhunk + oldsize, "  ");
XX  	strcpy(oldhunk + oldsize + 2, line);
XX--- 271,277 ----
XX  	len = strlen(line) + 2;
XX  	if (oldsize + len + 1 >= oldalloc) {
XX  		oldalloc *= 2;
XX! 		oldhunk = (char *) xrealloc(oldhunk, oldalloc);
XX  	}
XX  	strcpy(oldhunk + oldsize, "  ");
XX  	strcpy(oldhunk + oldsize + 2, line);
XX***************
XX*** 234,253 ****
XX  	len = strlen(line) + 2;
XX  	if (newsize + len + 1 >= newalloc) {
XX  		newalloc *= 2;
XX! 		newhunk = realloc(newhunk, newalloc);
XX  	}
XX  	strcpy(newhunk + newsize, "  ");
XX  	strcpy(newhunk + newsize + 2, line);
XX  	newsize += len;
XX    }
XX!   fputs("***************\n", stdout);
XX    if (preoldbeg >= preoldend) {
XX  	printf("*** %d ****\n", preoldend);
XX    } else {
XX  	printf("*** %d,%d ****\n", preoldbeg, preoldend);
XX    }
XX    if (oldwanted) {
XX! 	fputs(oldhunk, stdout);
XX    }
XX    oldsize = 0;
XX    *oldhunk = '\0';
XX--- 286,305 ----
XX  	len = strlen(line) + 2;
XX  	if (newsize + len + 1 >= newalloc) {
XX  		newalloc *= 2;
XX! 		newhunk = (char *) xrealloc(newhunk, newalloc);
XX  	}
XX  	strcpy(newhunk + newsize, "  ");
XX  	strcpy(newhunk + newsize + 2, line);
XX  	newsize += len;
XX    }
XX!   printf("***************\n");
XX    if (preoldbeg >= preoldend) {
XX  	printf("*** %d ****\n", preoldend);
XX    } else {
XX  	printf("*** %d,%d ****\n", preoldbeg, preoldend);
XX    }
XX    if (oldwanted) {
XX! 	printf("%s", oldhunk);
XX    }
XX    oldsize = 0;
XX    *oldhunk = '\0';
XX***************
XX*** 257,270 ****
XX  	printf("--- %d,%d ----\n", prenewbeg, prenewend);
XX    }
XX    if (newwanted) {
XX! 	fputs(newhunk, stdout);
XX    }
XX    newsize = 0;
XX    *newhunk = '\0';
XX  }
XX  
XX! char *
XX!  getold(targ)
XX  int targ;
XX  {
XX    static int oldline = 0;
XX--- 309,321 ----
XX  	printf("--- %d,%d ----\n", prenewbeg, prenewend);
XX    }
XX    if (newwanted) {
XX! 	printf("%s", newhunk);
XX    }
XX    newsize = 0;
XX    *newhunk = '\0';
XX  }
XX  
XX! char *getold(targ)
XX  int targ;
XX  {
XX    static int oldline = 0;
XX***************
XX*** 276,283 ****
XX    return Nullch;
XX  }
XX  
XX! char *
XX!  getnew(targ)
XX  int targ;
XX  {
XX    static int newline = 0;
XX--- 327,333 ----
XX    return Nullch;
XX  }
XX  
XX! char *getnew(targ)
XX  int targ;
XX  {
XX    static int newline = 0;
XX***************
XX*** 287,290 ****
XX--- 337,365 ----
XX  	if (newline == targ) return buff;
XX    }
XX    return Nullch;
XX+ }
XX+ 
XX+ void *xmalloc(size)
XX+ size_t size;
XX+ {
XX+   void *ptr;
XX+ 
XX+   ptr = malloc(size);
XX+   if (ptr == NULL) {
XX+ 	fprintf(stderr, "%s: out of memory\n", progname);
XX+ 	exit(2);
XX+   }
XX+   return(ptr);
XX+ }
XX+ 
XX+ void *xrealloc(ptr, size)
XX+ void *ptr;
XX+ size_t size;
XX+ {
XX+   ptr = realloc(ptr, size);
XX+   if (ptr == NULL) {
XX+ 	fprintf(stderr, "%s: out of memory\n", progname);
XX+ 	exit(2);
XX+   }
XX+   return(ptr);
XX  }
X/
Xecho x - cgrep.c.d
Xsed '/^X/s///' > cgrep.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cgrep.c  crc=27074   9044	Sun Apr 25 21:34:48 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cgrep.c  crc=50864   9281	Wed Nov  4 04:19:05 1992
XX***************
XX*** 71,76 ****
XX--- 71,81 ----
XX  
XX  /* Internal routines */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void dosrch, (char *ifnm));
XX+ _PROTOTYPE(void shwlin, (char *fnm, int linnum, char *line));
XX+ _PROTOTYPE(int matlin, (char *line));
XX+ _PROTOTYPE(void regerror, (char *s));
XX  
XX  /* External data */
XX  
XX***************
XX*** 79,85 ****
XX  
XX  static int Debug = {FALSE};	/* Debug enabled flag */
XX  static int Lcur = {0};		/* Current line (in Lines array) */
XX! static char **Lines = {(char **) NULL};	/* Lines pointer array */
XX  static int Linlen = {100};	/* Line length */
XX  static int Lone = {0};		/* Line one (in Lines array) */
XX  static int Nmr = {0};		/* Number of matched regions */
XX--- 84,90 ----
XX  
XX  static int Debug = {FALSE};	/* Debug enabled flag */
XX  static int Lcur = {0};		/* Current line (in Lines array) */
XX! static char **Lines = {NULL};	/* Lines pointer array */
XX  static int Linlen = {100};	/* Line length */
XX  static int Lone = {0};		/* Line one (in Lines array) */
XX  static int Nmr = {0};		/* Number of matched regions */
XX***************
XX*** 92,98 ****
XX  
XX  regexp *Re;			/* Result from reg compilation */
XX  
XX! main(argc, argv)
XX  int argc;			/* Argument count */
XX  char **argv;			/* Argument values */
XX  
XX--- 97,103 ----
XX  
XX  regexp *Re;			/* Result from reg compilation */
XX  
XX! int main(argc, argv)
XX  int argc;			/* Argument count */
XX  char **argv;			/* Argument values */
XX  
XX***************
XX*** 149,155 ****
XX  
XX  		    case 'b':	/* Lines before */
XX  			Wbef = atoi(aptr);
XX! 			Lines = (char **) NULL;
XX  			i = n;
XX  			break;
XX  
XX--- 154,160 ----
XX  
XX  		    case 'b':	/* Lines before */
XX  			Wbef = atoi(aptr);
XX! 			Lines = NULL;
XX  			i = n;
XX  			break;
XX  
XX***************
XX*** 191,196 ****
XX--- 196,202 ----
XX    }
XX    if (nf == 0)			/* No files processed ? */
XX  	dosrch((char *)NULL);		/* Do standard input */
XX+   return(0);
XX  }
XX  
XX   /* Dosrch (ifnm) Perform the search 
XX***************
XX*** 204,210 ****
XX    * 
XX    */
XX  
XX! dosrch(ifnm)
XX  char *ifnm;			/* Input filelname */
XX  
XX  {
XX--- 210,216 ----
XX    * 
XX    */
XX  
XX! void dosrch(ifnm)
XX  char *ifnm;			/* Input filelname */
XX  
XX  {
XX***************
XX*** 226,235 ****
XX  
XX    if (Lines == NULL) {		/* If no line table allocated.. */
XX  	Wsiz = Wbef + 2;	/* Determine total window size */
XX! 	Lines = (char **) calloc(Wsiz, sizeof(char *));
XX  	/* Allocate pointer table */
XX  	for (i = 0; i < Wsiz; i++)	/* Allocate line buffers */
XX! 		Lines[i] = (char *) calloc(Linlen, sizeof(char));
XX    }
XX    Lcur = Lone = 0;		/* Setup line pointers */
XX    nlb = 0;			/* No lines buffered */
XX--- 232,241 ----
XX  
XX    if (Lines == NULL) {		/* If no line table allocated.. */
XX  	Wsiz = Wbef + 2;	/* Determine total window size */
XX! 	Lines = (char **) calloc((size_t)Wsiz, sizeof(char *));
XX  	/* Allocate pointer table */
XX  	for (i = 0; i < Wsiz; i++)	/* Allocate line buffers */
XX! 		Lines[i] = (char *) calloc((size_t)Linlen, sizeof(char));
XX    }
XX    Lcur = Lone = 0;		/* Setup line pointers */
XX    nlb = 0;			/* No lines buffered */
XX***************
XX*** 288,301 ****
XX    * 
XX    */
XX  
XX! shwlin(fnm, linnum, line)
XX  char *fnm;			/* File name */
XX  int linnum;			/* Line number */
XX  char *line;			/* Line (with newline at end) to print */
XX  
XX  {
XX    if (Shwfile && (fnm != NULL)) printf("%s%s", fnm, Shwline ? " " : ":");
XX!   if (Shwline) printf("@%05d%:", linnum);
XX    printf("%s", line);
XX  }
XX  
XX--- 294,307 ----
XX    * 
XX    */
XX  
XX! void shwlin(fnm, linnum, line)
XX  char *fnm;			/* File name */
XX  int linnum;			/* Line number */
XX  char *line;			/* Line (with newline at end) to print */
XX  
XX  {
XX    if (Shwfile && (fnm != NULL)) printf("%s%s", fnm, Shwline ? " " : ":");
XX!   if (Shwline) printf("@%05d:", linnum);
XX    printf("%s", line);
XX  }
XX  
XX***************
XX*** 333,339 ****
XX  #endif	/* REGEX */
XX  
XX  #ifdef	REGCMP
XX!   rtncode = (regexec(Re, line, TRUE) != (int) NULL);
XX  #endif /* REGCMP */
XX  
XX  #ifdef	NOREGEX			/* Have to do menial comparison.. */
XX--- 339,345 ----
XX  #endif	/* REGEX */
XX  
XX  #ifdef	REGCMP
XX!   rtncode = (regexec(Re, line, TRUE) != 0);
XX  #endif /* REGCMP */
XX  
XX  #ifdef	NOREGEX			/* Have to do menial comparison.. */
X/
Xecho x - chmem.c.d
Xsed '/^X/s///' > chmem.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/chmem.c  crc=28568   3571	Sun Apr 25 21:34:48 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/chmem.c  crc=11962   3289	Sun Jan 10 14:26:16 1993
XX***************
XX*** 1,27 ****
XX  /* chmem - set total memory size for execution	Author: Andy Tanenbaum */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <stdlib.h>
XX  #include <unistd.h>
XX  
XX! /* Should include a.out.h or exec.h.  Here is an approximation. */
XX! #define HLONG            8	/* header size in longs */
XX! #define TEXT             2	/* where is text size in header */
XX! #define DATA             3	/* where is data size in header */
XX! #define BSS              4	/* where is bss size in header */
XX! #define TOT              6	/* where in header is total allocation */
XX! #define TOTPOS          24	/* where is total in header */
XX! #define SEPBIT  0x00200000	/* this bit is set for separate I/D */
XX! #define MAGIC       0x0301	/* magic number for executable progs */
XX! #define MAX_8086   0x10000L	/* maximum allocation size for 8086 */
XX! #define MAX_386 0x7FFFFFFFL	/* etc */
XX! #define MAX_68K 0x7FFFFFFFL
XX! #define CPU_8086         4	/* CPU code for 8086 executables */
XX! #define CPU_386       0x10	/* etc */
XX! #define CPU_68K       0x0B	/* from Minix-PC a.out.h - unreliable */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 1,26 ----
XX  /* chmem - set total memory size for execution	Author: Andy Tanenbaum */
XX  
XX+ #include <minix/config.h>
XX  #include <sys/types.h>
XX+ #include <a.out.h>
XX+ #include <errno.h>
XX  #include <fcntl.h>
XX  #include <stdlib.h>
XX  #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! #define MAX_8086     0x10000L	/* maximum allocation size for 8086 */
XX! #define MAX_386	  0x7FFFFFFFL	/* etc */
XX! #define MAX_68K   0x7FFFFFFFL
XX! #define MAX_SPARC 0x20000000L	/* No more than 512MB on a SparcStation! */
XX  
XX! char *progname;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void error, (char *s1, char *s2));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 38,108 ****
XX  
XX    char *p;
XX    int fd, separate;
XX!   long lsize, olddynam, newdynam, newtot, overflow, header[HLONG];
XX    char cpu;
XX    long max;
XX  
XX!   if (argc != 3) usage();
XX    p = argv[1];
XX    if (*p != '=' && *p != '+' && *p != '-') usage();
XX    lsize = atol(p + 1);
XX  
XX!   fd = open(argv[2], O_RDWR);
XX!   if (fd < 0) stderr3("chmem: can't open ", argv[2], "\n");
XX  
XX!   if (read(fd, (char *) header, sizeof(header)) != sizeof(header))
XX! 	stderr3("chmem: ", argv[2], "bad header\n");
XX!   if ((header[0] & 0xFFFFL) != MAGIC)
XX! 	stderr3("chmem: ", argv[2], " not executable\n");
XX!   separate = (header[0] & SEPBIT ? 1 : 0);
XX  
XX!   cpu = (char) (header[0] >> 24);	/* cpu byte is most significant */
XX!   if (cpu == CPU_8086 && *(unsigned short *) &header[0] != MAGIC)
XX! 	cpu = CPU_68K;		/* 8086 code with 68K byte order == 68K */
XX!   switch(cpu) {
XX! 	case CPU_8086:	max = MAX_8086;	break;
XX! 	case CPU_386:	max = MAX_386;	break;
XX! 	case CPU_68K:	max = MAX_68K;	break;
XX! 	default:	stderr3("chmem: ", argv[2], "bad CPU type\n");
XX!   }  
XX  
XX!   if (lsize < 0) stderr3("chmem: ", p+1, " negative size not allowed\n");
XX!   if (lsize > max) stderr3("chmem: ", p + 1, " too large\n");
XX  
XX!   olddynam = header[TOT] - header[DATA] - header[BSS];
XX!   if (separate == 0) olddynam -= header[TEXT];
XX  
XX!   if (*p == '=')
XX! 	newdynam = lsize;
XX!   else if (*p == '+')
XX! 	newdynam = olddynam + lsize;
XX!   else if (*p == '-')
XX! 	newdynam = olddynam - lsize;
XX  
XX!   newtot = header[DATA] + header[BSS] + newdynam;
XX!   if (separate == 0) newtot += header[TEXT];
XX!   overflow = (newtot > max ? newtot - max : 0);
XX!   newdynam -= overflow;
XX!   newtot -= overflow;
XX!   lseek(fd, (long) TOTPOS, SEEK_SET);
XX!   if (write(fd, (char *) &newtot, 4) < 0)
XX! 	stderr3("chmem: can't modify ", argv[2], "\n");
XX!   printf("%s: Stack+malloc area changed from %ld to %ld bytes.\n",
XX!          argv[2], olddynam, newdynam);
XX!   exit(0);
XX  }
XX  
XX! usage()
XX  {
XX!   std_err("chmem {=+-} amount file\n");
XX!   exit(1);
XX  }
XX  
XX! stderr3(s1, s2, s3)
XX! char *s1, *s2, *s3;
XX  {
XX!   std_err(s1);
XX!   std_err(s2);
XX!   std_err(s3);
XX    exit(1);
XX  }
XX--- 37,140 ----
XX  
XX    char *p;
XX    int fd, separate;
XX!   size_t s;
XX!   long lsize, olddynam, newdynam, newtot, overflow;
XX!   struct exec exec;
XX    char cpu;
XX    long max;
XX  
XX!   progname = argv[0];
XX!   if (argc < 3) usage();
XX    p = argv[1];
XX    if (*p != '=' && *p != '+' && *p != '-') usage();
XX    lsize = atol(p + 1);
XX+   s = sizeof(struct exec);
XX  
XX!   if (lsize < 0) {
XX! 	error(p + 1, "is negative");
XX! 	exit(1);
XX!   }
XX!   argc -= 1;
XX!   argv += 1;
XX  
XX!   while (--argc) {
XX! 	++argv;
XX! 	fd = open(*argv, O_RDWR);
XX! 	if (fd < 0) {
XX! 		error("can't open", *argv);
XX! 		continue;
XX! 	}
XX! 	if (read(fd, (char *) &exec, s) != s) {
XX! 		error("can't read header in", *argv);
XX! 		continue;
XX! 	}
XX! 	if (BADMAG(exec)) {
XX! 		error(*argv, "is not executable");
XX! 		continue;
XX! 	}
XX! 	separate = (exec.a_flags & A_SEP ? 1 : 0);
XX! 	cpu = exec.a_cpu;
XX  
XX! #if (CHIP == M68000)
XX! 	if (cpu == A_I8086) cpu = A_M68K;
XX! #endif
XX  
XX! 	switch (cpu) {
XX! 	    case A_I8086:	max = MAX_8086;	break;
XX! 	    case A_I80386:	max = MAX_386;	break;
XX! 	    case A_M68K:	max = MAX_68K;	break;
XX! 	    case A_SPARC:	max = MAX_SPARC;	break;
XX! 	    default:
XX! 		error("bad CPU type in", *argv);
XX! 		continue;
XX! 	}
XX  
XX! 	if (lsize > max) {
XX! 		error("size is too large for", *argv);
XX! 		continue;
XX! 	}
XX! 	olddynam = exec.a_total - exec.a_data - exec.a_bss;
XX! 	if (separate == 0) olddynam -= exec.a_text;
XX  
XX! 	if (*p == '=')
XX! 		newdynam = lsize;
XX! 	else if (*p == '+')
XX! 		newdynam = olddynam + lsize;
XX! 	else if (*p == '-')
XX! 		newdynam = olddynam - lsize;
XX  
XX! 	newtot = exec.a_data + exec.a_bss + newdynam;
XX! 	if (separate == 0) newtot += exec.a_text;
XX! 	overflow = (newtot > max ? newtot - max : 0);
XX! 	newdynam -= overflow;
XX! 	newtot -= overflow;
XX! 	exec.a_total = newtot;
XX! 	lseek(fd, (long) 0, SEEK_SET);
XX! 	if (write(fd, (char *) &exec, s) != s) {
XX! 		error("can't modify", *argv);
XX! 		continue;
XX! 	}
XX! 	printf("%s: Stack+malloc area changed from %ld to %ld bytes.\n",
XX! 	       *argv, olddynam, newdynam);
XX! 	close(fd);
XX!   }
XX!   return(0);
XX  }
XX  
XX! void error(s1, s2)
XX! char *s1;
XX! char *s2;
XX  {
XX!   fprintf(stderr, "%s: %s ", progname, s1);
XX!   if (errno != 0)
XX! 	perror(s2);
XX!   else
XX! 	fprintf(stderr, "%s\n", s2);
XX!   errno = 0;
XX  }
XX  
XX! void usage()
XX  {
XX!   fprintf(stderr, "Usage: %s {=+-} amount file\n", progname);
XX    exit(1);
XX  }
X/
Xecho x - chmod.c.d
Xsed '/^X/s///' > chmod.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/chmod.c  crc=16117   5948	Sun Apr 25 21:34:48 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/chmod.c  crc=15392   5004	Wed Nov  4 04:19:06 1992
XX***************
XX*** 1,275 ****
XX! /* chmod - change mode		Author: James da Silva */
XX  
XX! 
XX! /* Author James da Silva (ihnp4!killer!jaime)
XX!  *
XX!  *  a (hopefully) 7th Edition Unix compatible chmod for Minix.
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  
XX! #define isop(c)         ((c=='+')||(c=='-')||(c=='='))
XX! #define isperm(c)       ((c=='r')||(c=='w')||(c=='x')||(c=='s')||(c=='t')||\
XX!                          (c=='u')||(c=='g')||(c=='o'))
XX  
XX- /* The bits associated with user, group, other */
XX- #define U_MSK   (0700 | S_ISUID)
XX- #define G_MSK   (0070 | S_ISGID)
XX- #define O_MSK    0007
XX  
XX! typedef unsigned short bitset;	/* type used for modes */
XX  
XX! struct stat st;			/* structure returned by stat() */
XX! char *pname, *arg;
XX! bitset newmode, absolute(), symbolic();
XX! int isabsolute;
XX  
XX! main(argc, argv)
XX! int argc;
XX! char **argv;
XX  {
XX!   int i;
XX  
XX!   pname = *(argv++);
XX!   if (argc < 3) usage();
XX!   arg = *argv;			/* save pointer to mode arg */
XX! 
XX!   /* Check for octal mode */
XX!   if (isabsolute = ((*arg >= '0') && (*arg <= '7'))) newmode = absolute();
XX! 
XX!   /* Apply the mode to all files listed */
XX!   for (i = 2; i < argc; i++) {
XX! 	argv++;
XX! 	if (stat(*argv, &st)) {	/* get current file mode */
XX! 		printf("%s: cannot find `%s'\n", pname, *argv);
XX! 		exit(1);
XX  	}
XX! 
XX! 	/* Calculate new mode for this file */
XX! 	if (!isabsolute) newmode = symbolic(st.st_mode);
XX! 
XX! 	if (chmod(*argv, newmode)) {	/* change the mode */
XX! 		printf("%s: cannot chmod `%s'\n", pname, *argv);
XX! 		exit(1);
XX  	}
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX! /* Absolute interprets an octal mode.
XX!  * The file modes will be set to this value.
XX   */
XX! bitset absolute()
XX  {
XX!   bitset m;
XX!   char *s;
XX  
XX!   m = 0;
XX!   s = arg;
XX  
XX!   /* Convert octal string to integer */
XX!   while ((*s >= '0') && (*s <= '7')) m = m * 8 + (*(s++) - '0');
XX  
XX!   /* If something else is there, choke */
XX!   if (*s) badmode(s);
XX  
XX!   return m;
XX  }
XX  
XX  
XX! /* Symbolic
XX!  *
XX!  * Processes symbolic mode of the form (in EBNF):
XX!  *      <symbolic> ::= <pgroup> { ',' <pgroup> }.
XX!  *      <pgroup> ::= [ <who> ] <op> <permissions> { <op> <permissions> }.
XX!  *
XX!  *      <who> ::= <whoch> { <whoch> }.
XX!  *      <whoch> ::= 'a' | 'u' | 'g' | 'o'.
XX!  *
XX!  *      <op> ::= '+' | '-' | '='.
XX!  *
XX!  *      <permissions> ::= <permch> { <permch> }.
XX!  *      <permch> ::= 'r' | 'w' | 'x' | 's' | 't' | 'u' | 'g' | 'o'.
XX!  *
XX!  * If <who> is omitted, 'a' is assumed, BUT umask()ed bits are uneffected.
XX!  * If <op> is '=', all unspecified permissions are turned off for this <who>.
XX!  * For permissions 'u', 'g', and 'o', the permissions are taken from the
XX!  * specified set.  i.e.  o=g sets the permissions for other the same as for
XX!  * group.
XX!  *
XX!  * Pain in the duff, isn't it?
XX   */
XX! bitset symbolic(mode)
XX! bitset mode;
XX  {
XX!   int g, o, u, haswho, haspcopy;
XX!   bitset u_mask, emask, partial, other, applyop();
XX!   char *s, c, op;
XX  
XX!   s = arg;
XX!   u_mask = umask(0);		/* get the umasked bits */
XX  
XX!   do {				/* pgroup */
XX! 	haswho = u = g = o = 0;
XX! 
XX! 	while (!isop(*s)) {
XX! 		/* We must have a 'who' then */
XX! 		haswho = 1;
XX! 		switch (*s) {
XX! 		    case 'a':	u = g = o = 1;	break;
XX! 		    case 'u':	u = 1;	break;
XX! 		    case 'g':	g = 1;	break;
XX! 		    case 'o':	o = 1;	break;
XX! 
XX! 		    default:	badmode(s);
XX! 		}
XX! 		s++;
XX  	}
XX! 
XX! 	if (!haswho) {
XX! 		u = g = o = 1;	/* assume all */
XX! 		emask = ~u_mask;/* effective umask */
XX! 	} else
XX! 		emask = ~0;
XX! 
XX! 
XX! 	/* Process each given operator */
XX! 	while (isop(*s)) {
XX! 		op = *(s++);
XX! 		other = partial = haspcopy = 0;
XX! 
XX! 		/* Collect the specified permissions */
XX! 
XX! 		while (isperm(*s)) {
XX! 
XX! 			/* Berkeley only allows one of 'u' 'g' or 'o'
XX! 			 * as permissions */
XX! 
XX! 			if ((*s == 'u') || (*s == 'g') || (*s == 'o'))
XX! 				if (haspcopy)
XX! 					badmode(s);
XX! 				else
XX! 					haspcopy = 1;
XX! 
XX! 			switch (*s) {
XX! 			    case 'r':
XX! 				partial |= 4;
XX! 				break;
XX! 			    case 'w':
XX! 				partial |= 2;
XX! 				break;
XX! 			    case 'x':
XX! 				partial |= 1;
XX! 				break;
XX! 
XX! 			    case 'u':
XX! 				partial |= (mode & U_MSK & ~S_ISUID) >> 6;
XX! 				other |= mode & S_ISUID;
XX! 				break;
XX! 			    case 'g':
XX! 				partial |= (mode & G_MSK & ~S_ISGID) >> 3;
XX! 				other |= mode & S_ISGID;
XX! 				break;
XX! 			    case 'o':
XX! 				partial |= (mode & O_MSK);
XX! 				break;
XX! 
XX! #ifdef S_ISVTX
XX! 			    case 't':
XX! 				other |= S_ISVTX;
XX! 				break;
XX! #endif
XX! 
XX! 			    case 's':
XX! 				if (u) other |= S_ISUID;
XX! 				if (g) other |= S_ISGID;
XX! 				break;
XX! 
XX! 			    default:	badmode(s);
XX! 			}
XX! 			s++;
XX  		}
XX! 
XX! 		/* Apply the op using the affected bits and masks */
XX! 		if (u)
XX! 			mode = applyop(mode, op, (other | (partial << 6)), emask, U_MSK);
XX! 		if (g)
XX! 			mode = applyop(mode, op, (other | (partial << 3)), emask, G_MSK);
XX! 		if (o)
XX! 			mode = applyop(mode, op, (other | partial), emask, O_MSK);
XX! 	}
XX! 
XX!   } while (*(s++) == ',');
XX! 
XX!   /* Not at end - choke */
XX! 
XX!   if (*(--s)) badmode(s);
XX! 
XX!   return mode;
XX! }
XX! 
XX! 
XX! /* Applyop
XX!  *
XX!  * applies the operator to the current mode using the specified bitset
XX!  * and mask.  'bits' will contain 1's in every bit affected by the
XX!  * operator '+', '-', or '='.  In the case of '=', msk is used to
XX!  * determine which bits will be forced off. 'emask' is the effective
XX!  * umask.
XX!  */
XX! bitset applyop(mode, op, bits, emask, msk)
XX! char op;
XX! bitset mode, bits, emask, msk;
XX! {
XX!   switch (op) {
XX!       case '+':
XX! 	mode |= bits & emask;	/* turn these bits on */
XX! 	break;
XX!       case '-':
XX! 	mode &= ~(bits & emask);/* turn these off */
XX! 	break;
XX!       case '=':
XX! 	mode |= bits & emask;	/* turn these bits on */
XX! 	mode &= ~(~bits & msk & emask);	/* others off */
XX! 	break;
XX!       default:			/* should never get here (famous last words) */
XX! 	printf("%s: panic: bad op `%c' passed\n", pname, op);
XX    }
XX!   return mode;
XX  }
XX  
XX  
XX! /* Usage
XX!  *
XX!  * Prints a terse usage message and exits.
XX!  */
XX! usage()
XX  {
XX!   printf("Usage: %s [absolute-mode | symbolic-mode] files\n", pname);
XX!   exit(1);
XX! }
XX! 
XX! 
XX! /* Badmode
XX!  *
XX!  * Called when the parser chokes on the given mode.
XX!  * Prints a message showing the offending character and exits.
XX!  */
XX! badmode(s)
XX! char *s;
XX! {
XX!   int i, sp;
XX!   char buffer[80], *bp;
XX! 
XX!   sp = s - arg + strlen(pname) + 21;
XX!   sp = sp > 79 ? 79 : sp;	/* check for buffer overflow */
XX! 
XX!   for (i = 0, bp = buffer; i < sp; i++, bp++) *bp = ' ';
XX!   *bp = '\0';
XX! 
XX!   printf("%s: badly formed mode `%s'\n", pname, arg);
XX!   printf("%s^\n", buffer);
XX    exit(1);
XX  }
XX--- 1,253 ----
XX! /* chmod - Change file modes				Author: V. Archer */
XX  
XX! /* Copyright 1991 by Vincent Archer
XX!  *	You may freely redistribute this software, in source or binary
XX!  *	form, provided that you do not alter this copyright mention in any
XX!  *	way.
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <dirent.h>
XX+ #include <errno.h>
XX+ #include <limits.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX! #define USR_MODES (S_ISUID|S_IRWXU)
XX! #define GRP_MODES (S_ISGID|S_IRWXG)
XX! #define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
XX! #ifdef S_ISVTX
XX! #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
XX! #else
XX! #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
XX! #endif
XX  
XX  
XX! /* Common variables */
XX! char *symbolic;
XX! mode_t new_mode, u_mask;
XX! int rflag, errors;
XX! struct stat st;
XX! uid_t userid;
XX! char path[PATH_MAX + 1];
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(mode_t parsemode, (char *symbolic, Mode_t oldmode));
XX! _PROTOTYPE(int do_change, (char *name));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! /* Parse a P1003.2 4.7.7-conformant symbolic mode. */
XX! mode_t parsemode(symbolic, oldmode)
XX! char *symbolic;
XX! mode_t oldmode;
XX  {
XX!   mode_t who, mask, newmode, tmpmask;
XX!   char action;
XX  
XX!   newmode = oldmode & ALL_MODES;
XX!   while (*symbolic) {
XX! 	who = 0;
XX! 	for (; *symbolic; symbolic++) {
XX! 		if (*symbolic == 'a') {
XX! 			who |= ALL_MODES;
XX! 			continue;
XX! 		}
XX! 		if (*symbolic == 'u') {
XX! 			who |= USR_MODES;
XX! 			continue;
XX! 		}
XX! 		if (*symbolic == 'g') {
XX! 			who |= GRP_MODES;
XX! 			continue;
XX! 		}
XX! 		if (*symbolic == 'o') {
XX! 			who |= S_IRWXO;
XX! 			continue;
XX! 		}
XX! 		break;
XX  	}
XX! 	if (!*symbolic || *symbolic == ',') usage();
XX! 	while (*symbolic) {
XX! 		if (*symbolic == ',') break;
XX! 		switch (*symbolic) {
XX! 		    default:
XX! 			usage();
XX! 		    case '+':
XX! 		    case '-':
XX! 		    case '=':	action = *symbolic++;
XX! 		}
XX! 		mask = 0;
XX! 		for (; *symbolic; symbolic++) {
XX! 			if (*symbolic == 'u') {
XX! 				tmpmask = newmode & S_IRWXU;
XX! 				mask |= tmpmask | (tmpmask << 3) | (tmpmask << 6);
XX! 				symbolic++;
XX! 				break;
XX! 			}
XX! 			if (*symbolic == 'g') {
XX! 				tmpmask = newmode & S_IRWXG;
XX! 				mask |= tmpmask | (tmpmask >> 3) | (tmpmask << 3);
XX! 				symbolic++;
XX! 				break;
XX! 			}
XX! 			if (*symbolic == 'o') {
XX! 				tmpmask = newmode & S_IRWXO;
XX! 				mask |= tmpmask | (tmpmask >> 3) | (tmpmask >> 6);
XX! 				symbolic++;
XX! 				break;
XX! 			}
XX! 			if (*symbolic == 'r') {
XX! 				mask |= S_IRUSR | S_IRGRP | S_IROTH;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 'w') {
XX! 				mask |= S_IWUSR | S_IWGRP | S_IWOTH;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 'x') {
XX! 				mask |= EXE_MODES;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 's') {
XX! 				mask |= S_ISUID | S_ISGID;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 'X') {
XX! 				if (S_ISDIR(oldmode) || (oldmode & EXE_MODES))
XX! 					mask |= EXE_MODES;
XX! 				continue;
XX! 			}
XX! #ifdef S_ISVTX
XX! 			if (*symbolic == 't') {
XX! 				mask |= S_ISVTX;
XX! 				who |= S_ISVTX;
XX! 				continue;
XX! 			}
XX! #endif
XX! 			break;
XX! 		}
XX! 		switch (action) {
XX! 		    case '=':
XX! 			if (who)
XX! 				newmode &= ~who;
XX! 			else
XX! 				newmode = 0;
XX! 		    case '+':
XX! 			if (who)
XX! 				newmode |= who & mask;
XX! 			else
XX! 				newmode |= mask & (~u_mask);
XX! 			break;
XX! 		    case '-':
XX! 			if (who)
XX! 				newmode &= ~(who & mask);
XX! 			else
XX! 				newmode &= ~mask | u_mask;
XX! 		}
XX  	}
XX+ 	if (*symbolic) symbolic++;
XX    }
XX!   return(newmode);
XX  }
XX  
XX  
XX! /* Main module. The single option possible (-R) does not warrant a call to
XX!  * the getopt() stuff.
XX   */
XX! int main(argc, argv)
XX! int argc;
XX! char *argv[];
XX  {
XX!   argc--;
XX!   argv++;
XX  
XX!   if (argc && strcmp(*argv, "-R") == 0) {
XX! 	argc--;
XX! 	argv++;
XX! 	rflag = 1;
XX!   } else
XX! 	rflag = 0;
XX  
XX!   if (!argc--) usage();
XX!   if (!strcmp(argv[0], "--")) {	/* Allow chmod -- -r, as in Draft11 example */
XX! 	if (!argc--) usage();
XX! 	argv++;
XX!   }
XX!   symbolic = *argv++;
XX!   if (!argc) usage();
XX  
XX!   if (*symbolic >= '0' && *symbolic <= '7') {
XX! 	new_mode = 0;
XX! 	while (*symbolic >= '0' && *symbolic <= '7')
XX! 		new_mode = (new_mode << 3) | (*symbolic++ & 07);
XX! 	if (*symbolic) usage();
XX! 	new_mode &= ALL_MODES;
XX! 	symbolic = (char *) 0;
XX!   } else
XX! 	u_mask = umask(0);
XX  
XX!   userid = getuid();
XX! 
XX!   while (argc--)
XX! 	if (do_change(*argv++)) exit(1);
XX!   return(0);
XX  }
XX  
XX  
XX! /* Apply a mode change to a given file system element. chmod(1) may be
XX!  * setuid root, in which case it will enforce the protection itself.
XX   */
XX! int do_change(name)
XX! char *name;
XX  {
XX!   mode_t m;
XX!   DIR *dirp;
XX!   struct dirent *entp;
XX!   char *namp;
XX  
XX!   if (stat(name, &st)) {
XX! 	perror(name);
XX! 	return(1);
XX!   }
XX!   if (!symbolic)
XX! 	m = new_mode;
XX!   else
XX! 	m = parsemode(symbolic, st.st_mode);
XX!   if (chmod(name, m)) {
XX! 	perror(name);
XX! 	errors = 1;
XX!   } else
XX! 	errors = 0;
XX  
XX!   if (S_ISDIR(st.st_mode) && rflag) {
XX! 	if (!(dirp = opendir(name))) {
XX! 		perror(name);
XX! 		return(1);
XX  	}
XX! 	if (name != path) strcpy(path, name);
XX! 	namp = path + strlen(path);
XX! 	*namp++ = '/';
XX! 	while (entp = readdir(dirp))
XX! 		if (entp->d_name[0] != '.' ||
XX! 		    (entp->d_name[1] &&
XX! 		     (entp->d_name[1] != '.' || entp->d_name[2]))) {
XX! 			strcpy(namp, entp->d_name);
XX! 			errors |= do_change(path);
XX  		}
XX! 	closedir(dirp);
XX! 	*--namp = '\0';
XX    }
XX!   return(errors);
XX  }
XX  
XX  
XX! /* Display Posix prototype */
XX! void usage()
XX  {
XX!   std_err("Usage: chmod [-R] mode file...\n");
XX    exit(1);
XX  }
X/
Xecho x - chown.c.d
Xsed '/^X/s///' > chown.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/chown.c  crc=18709   2793	Sun Apr 25 21:34:49 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/chown.c  crc=00602   3652	Wed Nov  4 04:19:06 1992
XX***************
XX*** 1,105 ****
XX! /*
XX!  * chown-	Change the owner and/or group ID of a file.
XX!  *
XX!  * Author:	Bert Reuling (bert@kyber.UUCP) 
XX!  *
XX!  * Revision History:
XX!  *	1.1  89/09/25 bert@kyber.UUCP 		Initial revision
XX!  *	     89/10/04 waltje@kyber.UUCP		Adapted to MINIX Style Sheet
XX   */
XX  #include <sys/types.h>
XX  #include <ctype.h>
XX! #include <grp.h>
XX  #include <pwd.h>
XX  #include <string.h>
XX! #include <sys/stat.h>
XX  #include <stdio.h>
XX  
XX! #ifndef TRUE
XX! #	define TRUE  1
XX! #	define FALSE 0
XX! #endif
XX  
XX! static char rcsid[] = "$Header: chown.c,v 1.1 89/10/04 20:45:00 bert Exp $";
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int i, uid, gid, Chown, status = 0;
XX!   char *pgmname, *uids, *gids;
XX!   struct passwd *pwd;
XX    struct group *grp;
XX    struct stat st;
XX  
XX!   if ((pgmname = strrchr(argv[0], '/')) != NULL) pgmname++;
XX!     else pgmname = argv[0];
XX!   if (strcmp(pgmname, "chown") == 0) Chown = TRUE;
XX!     else if (strcmp(pgmname, "chgrp") == 0) Chown = FALSE;
XX!            else {
XX!       		 (void) fprintf(stderr, "%s: should be named \"chown\" or \"chgrp\"\n", argv[0]);
XX! 	         (void) exit(-1);
XX!    	   }
XX!   if (argc < 3) {
XX! 	(void) fprintf(stderr,"Usage: %s %s file ...\n", pgmname, (Chown) ? "owner" : "group");
XX!       	(void) exit(1);
XX    }
XX!   if ((gids = strchr(argv[1], '.')) != NULL) {
XX!   	*gids++ = '\0';
XX!       	uids = argv[1];
XX    } else {
XX!           if (Chown) {
XX!          	uids = argv[1];
XX!          	gids = NULL;
XX!       	  } else {
XX!          	  uids = NULL;
XX!          	  gids = argv[1];
XX!       	    }
XX    }
XX!   if (uids == NULL) pwd = NULL;
XX!     else {
XX!           if (isdigit(*uids)) pwd = getpwuid(atoi(uids));
XX!       	    else pwd = getpwnam(uids);
XX!           if (pwd == NULL) {
XX!          	(void) fprintf(stderr, "%s: unknown user id %s\n", pgmname, uids);
XX!          	(void) exit(-1);
XX!       	  }
XX!     }
XX!   if (gids == NULL) grp = NULL;
XX!     else {
XX!           if (isdigit(*gids)) grp = getgrgid(atoi(gids));
XX!             else grp = getgrnam(gids);
XX!           if (grp == NULL) {
XX!          	(void) fprintf(stderr, "%s: unknown group: %s\n", pgmname, gids);
XX!          	(void) exit(-1);
XX!       	  }
XX!     }
XX!   for (i = 2; i < argc; i++) {
XX!   	if (stat(argv[i], &st) != -1) {
XX!         uid = (pwd == NULL) ? st.st_uid : pwd->pw_uid;
XX!         gid = (grp == NULL) ? st.st_gid : grp->gr_gid;
XX!         if (chown(argv[i], uid, gid) == -1) {
XX!         	(void) fprintf(stderr,"%s: not changed\n", argv[i]);
XX!             	status++;
XX!         }
XX! #ifdef _MINIX
XX!         /*
XX!          * chown(2) should do this ...
XX!          */
XX!         if (getuid() != 0) {
XX! 		st.st_mode &= ~S_ISUID;
XX!             	st.st_mode &= ~S_ISGID;
XX!             	if (chmod(argv[i], st.st_mode) == -1) {
XX!                		(void) fprintf(stderr, "%s: mode not changed\n", argv[i]);
XX!                		status++;
XX!             	}
XX!         }
XX! #endif
XX!      } else {
XX!              (void) perror(argv[i]);
XX!              status++;
XX!        }
XX    }
XX!   (void) exit(status);
XX  }
XX--- 1,171 ----
XX! /* chown/chgrp - Change file ownership			Author: V. Archer */
XX! 
XX! /* Copyright 1991 by Vincent Archer
XX!  *	You may freely redistribute this software, in source or binary
XX!  *	form, provided that you do not alter this copyright mention in any
XX!  *	way.
XX   */
XX+ 
XX  #include <sys/types.h>
XX+ #include <sys/stat.h>
XX  #include <ctype.h>
XX! #include <dirent.h>
XX  #include <pwd.h>
XX+ #include <grp.h>
XX  #include <string.h>
XX! #include <limits.h>
XX! #include <errno.h>
XX! #include <stdlib.h>
XX! #include <unistd.h>
XX! #include <minix/minlib.h>
XX  #include <stdio.h>
XX  
XX! #define S_IUGID (S_ISUID|S_ISGID)
XX  
XX! /* Global variables, such as flags and path names */
XX! int gflag, oflag, rflag, error;
XX! char *pgmname, path[PATH_MAX + 1];
XX! uid_t nuid, ouid;
XX! gid_t ngid;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void do_chown, (char *file));
XX+ _PROTOTYPE(void usage, (void));
XX  
XX! /* Main module. If chown(1) is invoked as chgrp(1), the behaviour is nearly
XX!  * identical, except that the default when a single name is given as an
XX!  * argument is to take a group id rather than an user id. This allow the
XX!  * non-Posix "chgrp user:group file".
XX!  * The single option switch used by chown/chgrp (-R) does not warrant a
XX!  * call to the getopt stuff. The two others flags (-g, -u) are set from
XX!  * the program name and arguments.
XX!  */
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   char *id, *id2;
XX    struct group *grp;
XX+   struct passwd *pwp;
XX+ 
XX+   if (pgmname = strrchr(*argv, '/'))
XX+ 	pgmname++;
XX+   else
XX+ 	pgmname = *argv;
XX+   argc--;
XX+   argv++;
XX+   gflag = strcmp(pgmname, "chgrp");
XX+ 
XX+   if (argc && **argv == '-' && argv[0][1] == 'R') {
XX+ 	argc--;
XX+ 	argv++;
XX+ 	rflag = 1;
XX+   }
XX+   if (argc < 2) usage();
XX+ 
XX+   id = *argv++;
XX+   argc--;
XX+   if (id2 = strchr(id, ':')) *id2++ = '\0';
XX+   if (!id2 && !gflag) {
XX+ 	id2 = id;
XX+ 	id = 0;
XX+   }
XX+   if (id) {
XX+ 	if (isdigit(*id))
XX+ 		nuid = atoi(id);
XX+ 	else {
XX+ 		if (!(pwp = getpwnam(id))) {
XX+ 			std_err(id);
XX+ 			std_err(": unknown user name\n");
XX+ 			exit(1);
XX+ 		}
XX+ 		nuid = pwp->pw_uid;
XX+ 	}
XX+ 	oflag = 1;
XX+   } else
XX+ 	oflag = 0;
XX+ 
XX+   if (id2) {
XX+ 	if (isdigit(*id2))
XX+ 		ngid = atoi(id2);
XX+ 	else {
XX+ 		if (!(grp = getgrnam(id2))) {
XX+ 			std_err(id2);
XX+ 			std_err(": unknown group name\n");
XX+ 			exit(1);
XX+ 		}
XX+ 		ngid = grp->gr_gid;
XX+ 	}
XX+ 	gflag = 1;
XX+   } else
XX+ 	gflag = 0;
XX+ 
XX+   ouid = getuid();
XX+   error = 0;
XX+   while (argc--) do_chown(*argv++);
XX+   return(error);
XX+ }
XX+ 
XX+ /* Apply the user/group modification here. If chown/chgrp is setuid root
XX+  * (when POSIX_CHOWN_RESTRICTED is true, as in Minix), chown/chgrp will
XX+  * apply its own protection (you must be owner to change either group/user,
XX+  * and doing so always clears BOTH setuid and setgid bits) if the caller is
XX+  * not 'root'.
XX+  */
XX+ void do_chown(file)
XX+ char *file;
XX+ {
XX+   DIR *dirp;
XX+   struct dirent *entp;
XX+   char *namp;
XX    struct stat st;
XX  
XX!   if (stat(file, &st)) {
XX! 	perror(file);
XX! 	error = 1;
XX! 	return;
XX    }
XX!   if (ouid && ouid != st.st_uid) {
XX! 	errno = EACCES;
XX! 	perror(file);
XX! 	error = 1;
XX    } else {
XX! 	if ((st.st_mode & S_IUGID) && ouid)
XX! 		chmod(file, st.st_mode & ~S_IUGID);
XX! 
XX! 	if (chown(file, oflag ? nuid : st.st_uid, gflag ? ngid : st.st_gid)) {
XX! 		perror(file);
XX! 		error = 1;
XX! 	}
XX    }
XX! 
XX!   if (S_ISDIR(st.st_mode) && rflag) {
XX! 	if (!(dirp = opendir(file))) {
XX! 		perror(file);
XX! 		error = 1;
XX! 		return;
XX! 	}
XX! 	if (path != file) strcpy(path, file);
XX! 	namp = path + strlen(path);
XX! 	*namp++ = '/';
XX! 	while (entp = readdir(dirp))
XX! 		if (entp->d_name[0] != '.' ||
XX! 		    (entp->d_name[1] &&
XX! 		     (entp->d_name[1] != '.' || entp->d_name[2]))) {
XX! 			strcpy(namp, entp->d_name);
XX! 			do_chown(path);
XX! 		}
XX! 	closedir(dirp);
XX! 	*--namp = '\0';
XX    }
XX! }
XX! 
XX! /* Posix prototype of the chown/chgrp function */
XX! void usage()
XX! {
XX!   std_err("Usage: ");
XX!   std_err(pgmname);
XX!   std_err(gflag ? " owner[:group]" : " [owner:]group");
XX!   std_err(" file...\n");
XX!   exit(1);
XX  }
X/
Xecho x - ci.c.d
Xsed '/^X/s///' > ci.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ci.c  crc=39359   7477	Sun Apr 25 21:34:49 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ci.c  crc=40916   7973	Wed Nov  4 04:19:06 1992
XX***************
XX*** 5,10 ****
XX--- 5,15 ----
XX  #include <sys/stat.h>
XX  #include <pwd.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <time.h>
XX+ #include <fcntl.h>
XX+ #include <sys/wait.h>
XX  #include <stdio.h>
XX  
XX  #define SUFFIX		",S"	/* svc indicator */
XX***************
XX*** 41,53 ****
XX  char original[] = "/tmp/cioXXXXXX";	/* previous revision */
XX  char diffout[] = "/tmp/cidXXXXXX";	/* diffs */
XX  
XX! extern char *mktemp();
XX! extern char *ctime();
XX  
XX! char *whoami();
XX! void onintr();
XX! 
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 46,62 ----
XX  char original[] = "/tmp/cioXXXXXX";	/* previous revision */
XX  char diffout[] = "/tmp/cidXXXXXX";	/* diffs */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void rundiff, (void));
XX! _PROTOTYPE(void logmsg, (FILE *fp));
XX! _PROTOTYPE(void fname, (char *src, char *dst));
XX! _PROTOTYPE(void svcname, (char *src, char *dst));
XX! _PROTOTYPE(int lockcheck, (FILE *fp, int rev));
XX! _PROTOTYPE(void onintr, (int dummy));
XX! _PROTOTYPE(void clean, (void));
XX! _PROTOTYPE(char *whoami, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 91,97 ****
XX  	++p;
XX  
XX    if (strlen(p) > 13) {
XX! 	fprintf(stderr, "ci: filename %s is too long\n");
XX  	exit(1);
XX    }
XX  #endif /* !BSD */
XX--- 100,106 ----
XX  	++p;
XX  
XX    if (strlen(p) > 13) {
XX! 	fprintf(stderr, "ci: filename %s is too long\n", p);
XX  	exit(1);
XX    }
XX  #endif /* !BSD */
XX***************
XX*** 121,127 ****
XX  	}
XX  	if (NULL == (origfp = fopen(original, "w"))) {
XX  		fprintf(stderr, "ci: can't create %s", original);
XX! 		perror("");
XX  	}
XX  	fgets(line, LINELEN, svcfp);	/* skip "cat <<***MAIN-eof***" line */
XX  
XX--- 130,136 ----
XX  	}
XX  	if (NULL == (origfp = fopen(original, "w"))) {
XX  		fprintf(stderr, "ci: can't create %s", original);
XX! 		perror(" ");
XX  	}
XX  	fgets(line, LINELEN, svcfp);	/* skip "cat <<***MAIN-eof***" line */
XX  
XX***************
XX*** 170,176 ****
XX  	fprintf(newfp, "***%d-eof***\n", rev);
XX  	fputs((original == p) ? "mv Fix.$1 $1\n" : FIX, newfp);
XX  	logmsg(newfp);
XX! 	while (NULL != fgets(line, LINELEN, svcfp) && strncmp(line, "#***SVCLOCK***", 14))
XX  		fputs(line, newfp);
XX    } else {
XX  	logmsg(newfp);
XX--- 179,185 ----
XX  	fprintf(newfp, "***%d-eof***\n", rev);
XX  	fputs((original == p) ? "mv Fix.$1 $1\n" : FIX, newfp);
XX  	logmsg(newfp);
XX! 	while (NULL != fgets(line, LINELEN, svcfp) && strncmp(line, "#***SVCLOCK***", (size_t)14))
XX  		fputs(line, newfp);
XX    } else {
XX  	logmsg(newfp);
XX***************
XX*** 205,214 ****
XX  	unlink(file);
XX  
XX    clean();
XX!   exit(0);
XX  }
XX  
XX! rundiff()
XX  {				/* do "diff file original > diffout" */
XX    int fd;			/* redirected output file */
XX  
XX--- 214,223 ----
XX  	unlink(file);
XX  
XX    clean();
XX!   return(0);
XX  }
XX  
XX! void rundiff()
XX  {				/* do "diff file original > diffout" */
XX    int fd;			/* redirected output file */
XX  
XX***************
XX*** 239,245 ****
XX    }
XX  }
XX  
XX! logmsg(fp)
XX  FILE *fp;
XX  {
XX    long now;
XX--- 248,254 ----
XX    }
XX  }
XX  
XX! void logmsg(fp)
XX  FILE *fp;
XX  {
XX    long now;
XX***************
XX*** 251,257 ****
XX  	fprintf(fp, "#***SVC*** %s\n", line);
XX  }
XX  
XX! fname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX--- 260,266 ----
XX  	fprintf(fp, "#***SVC*** %s\n", line);
XX  }
XX  
XX! void fname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX***************
XX*** 260,266 ****
XX    if (!strcmp(p, SUFFIX)) *p = '\0';
XX  }
XX  
XX! svcname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX--- 269,275 ----
XX    if (!strcmp(p, SUFFIX)) *p = '\0';
XX  }
XX  
XX! void svcname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX***************
XX*** 271,277 ****
XX    if (0 != access(dst, 4)) {
XX  	char dirname[PATHLEN];
XX  	if (NULL != (p = strrchr(src, '/')))
XX! 		strncpy(dirname, src, p - src + 1);
XX  	else
XX  		dirname[0] = '\0';
XX  	strcat(dirname, SVCDIR);
XX--- 280,286 ----
XX    if (0 != access(dst, 4)) {
XX  	char dirname[PATHLEN];
XX  	if (NULL != (p = strrchr(src, '/')))
XX! 		strncpy(dirname, src, (size_t)(p - src + 1));
XX  	else
XX  		dirname[0] = '\0';
XX  	strcat(dirname, SVCDIR);
XX***************
XX*** 288,294 ****
XX    }
XX  }
XX  
XX! lockcheck(fp, rev)
XX  FILE *fp;
XX  int rev;
XX  {
XX--- 297,303 ----
XX    }
XX  }
XX  
XX! int lockcheck(fp, rev)
XX  FILE *fp;
XX  int rev;
XX  {
XX***************
XX*** 307,320 ****
XX    return ret;
XX  }
XX  
XX! void onintr()
XX  {
XX    fprintf(stderr, "Interrupt - Aborting checkin, cleaning up\n");
XX    clean();
XX    exit(1);
XX  }
XX  
XX! clean()
XX  {
XX    if (strlen(original))		/* if only more programs made this check! */
XX  	unlink(original);
XX--- 316,330 ----
XX    return ret;
XX  }
XX  
XX! void onintr(dummy)
XX! int dummy; /* to keep the compiler happy */
XX  {
XX    fprintf(stderr, "Interrupt - Aborting checkin, cleaning up\n");
XX    clean();
XX    exit(1);
XX  }
XX  
XX! void clean()
XX  {
XX    if (strlen(original))		/* if only more programs made this check! */
XX  	unlink(original);
X/
Xecho x - clr.c.d
Xsed '/^X/s///' > clr.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/clr.c  crc=54599   1518	Sun Apr 25 21:34:49 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/clr.c  crc=32622   1614	Wed Nov  4 04:19:06 1992
XX***************
XX*** 8,13 ****
XX--- 8,17 ----
XX  #include <sys/stat.h>
XX  #include <sgtty.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <termcap.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define reverse()	write(1, SO, strlen(SO))	/* reverse video */
XX***************
XX*** 15,23 ****
XX  #define clearln()	write(1,"\r",1); \
XX  		write(1, CD, strlen(CD))	/* clear line */
XX  
XX- extern char *getenv();
XX- extern char *tgetstr();
XX- extern char *index();
XX  
XX  #define  TC_BUFFER  1024	/* Size of termcap(3) buffer	 */
XX  
XX--- 19,24 ----
XX***************
XX*** 28,35 ****
XX  char clear[30];
XX  char *p = &clear[0];
XX  
XX  
XX! main()
XX  {
XX  
XX    get_termcap();
XX--- 29,39 ----
XX  char clear[30];
XX  char *p = &clear[0];
XX  
XX+ _PROTOTYPE(int main, (void));
XX+ _PROTOTYPE(void get_termcap, (void));
XX+ _PROTOTYPE(void Error, (char *str));
XX  
XX! int main()
XX  {
XX  
XX    get_termcap();
XX***************
XX*** 39,51 ****
XX    clearln();
XX    printf("%s", clear);
XX  
XX!   exit(0);
XX  }
XX  
XX! get_termcap()
XX  {
XX    static char termbuf[50];
XX-   extern char *tgetstr(), *getenv();
XX    char *loc = termbuf;
XX    char entry[1024];
XX  
XX--- 43,54 ----
XX    clearln();
XX    printf("%s", clear);
XX  
XX!   return(0);
XX  }
XX  
XX! void get_termcap()
XX  {
XX    static char termbuf[50];
XX    char *loc = termbuf;
XX    char entry[1024];
XX  
XX***************
XX*** 70,76 ****
XX  
XX  }
XX  
XX! Error(str)
XX  char *str;
XX  {
XX    fprintf(stderr, "clr: %s\n", str);
XX--- 73,79 ----
XX  
XX  }
XX  
XX! void Error(str)
XX  char *str;
XX  {
XX    fprintf(stderr, "clr: %s\n", str);
X/
Xecho x - cmp.c.d
Xsed '/^X/s///' > cmp.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cmp.c  crc=15254   2647	Sun Apr 25 21:34:49 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cmp.c  crc=25405   2383	Wed Apr 14 22:40:34 1993
XX***************
XX*** 1,132 ****
XX! /* cmp - compare two files	Authors: Paul Polderman & Michiel Huisjes */
XX  
XX! /* 90-04-10 Schlenker
XX!  *	Fixed incorrect handling of flags.
XX!  *	Reduced buffer size to accommodate 7K pipes (Minix restriction).
XX!  *	Better trapping of file reading errors.
XX!  *	Considerable speedup when using -s flag.
XX!  *	Buffering strategy remains seriously error prone; should be fixed.
XX!  */
XX  
XX! #include <sys/types.h>
XX! #include <fcntl.h>
XX! #include <unistd.h>
XX! #include <stdio.h>
XX  
XX! #define BLOCK_SIZE 6144
XX  
XX! char *file_1, *file_2;
XX! char buf1[BLOCK_SIZE];
XX! char buf2[BLOCK_SIZE];
XX! char lflag, sflag;
XX  
XX! main(argc, argv)
XX  int argc;
XX! char *argv[];
XX  {
XX!   int fd1, fd2, i, exit_status;
XX  
XX!   if (argc < 3 || argc > 4) usage();
XX!   lflag = 0;
XX!   sflag = 0;
XX  
XX!   i = 1;
XX!   if (strcmp(argv[i], "-l") == 0) {
XX! 	lflag++;
XX! 	i++;
XX!   } else
XX!   if (strcmp(argv[i], "-s") == 0) {
XX! 	sflag++;
XX! 	i++;
XX    }
XX  
XX!   if (strcmp(argv[i], "-") == 0) {
XX  	fd1 = 0;
XX- 	file_1 = "<stdin>";
XX    } else {
XX! 	if ((fd1 = open(argv[i], O_RDONLY)) < 0)
XX! 		cantopen(argv[i]);
XX! 	file_1 = argv[i];
XX    }
XX-   i++;
XX  
XX!   if (i == argc || (fd2 = open(argv[i], O_RDONLY)) < 0)
XX! 	cantopen(argv[i]);
XX!   file_2 = argv[i];
XX  
XX!   exit_status = sflag ? fastcmp(fd1, fd2) : cmp(fd1, fd2);
XX! 
XX!   close(fd1);
XX!   close(fd2);
XX! 
XX!   exit(exit_status);
XX  }
XX  
XX! cmp(fd1, fd2)
XX  int fd1, fd2;
XX  {
XX!   register unsigned long char_cnt, line_cnt;
XX!   register int i;
XX!   int n1, n2, n, exit_status;
XX  
XX!   char_cnt = 1L;
XX!   line_cnt = 1L;
XX!   exit_status = 0;
XX!   do {
XX! 	n1 = read(fd1, buf1, BLOCK_SIZE);
XX! 	n2 = read(fd2, buf2, BLOCK_SIZE);
XX! 	n = (n1 < n2) ? n1 : n2;
XX! 	if (n < 0) {
XX! 		printf("cmp: Error on %s\n", (n1 < 0) ? file_1 : file_2);
XX! 		return(1);
XX  	}
XX! 	for (i = 0; i < n; i++) {	/* Check buffers for equality */
XX! 		if (buf1[i] != buf2[i]) {
XX! 			if (!lflag) {
XX  				printf("%s %s differ: char %ld, line %ld\n",
XX! 				file_1, file_2, char_cnt, line_cnt);
XX! 				return(1);
XX  			}
XX! 			printf("%10lu %03o %03o\n",
XX! 			       char_cnt, buf1[i] & 0377, buf2[i] & 0377);
XX! 			exit_status = 1;
XX  		}
XX! 		if (buf1[i] == '\n') line_cnt++;
XX! 		char_cnt++;
XX  	}
XX! 	if (n1 != n2) {		/* EOF on one of the input files. */
XX! 		printf("cmp: EOF on %s\n", (n1 < n2) ? file_1 : file_2);
XX! 		return(1);
XX! 	}
XX!   } while (n > 0);		/* While not EOF on any file */
XX!   return(exit_status);
XX  }
XX  
XX! fastcmp(fd1, fd2)
XX! int fd1, fd2;
XX  {
XX!   int n1, n2;
XX! 
XX!   while (1) {
XX! 	n1 = read(fd1, buf1, BLOCK_SIZE);
XX! 	n2 = read(fd2, buf2, BLOCK_SIZE);
XX! 	if (n1 != n2) return(1);	/* Bug! - depends on buffering */
XX! 	if (n1 == 0) return(0);
XX! 	if (n1 < 0) return(1);
XX! 	if (memcmp((void *) buf1, (void *) buf2, (size_t) n1) != 0)
XX! 		return(1);
XX    }
XX  }
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: cmp [-l | -s] file1 file2\n");
XX    exit(2);
XX- }
XX- 
XX- cantopen(s)
XX- char *s;
XX- {
XX-   fprintf(stderr, "cmp: cannot open %s\n", s);
XX-   exit(1);
XX  }
XX--- 1,132 ----
XX! /* cmp - compare two files		Author: Kees J. Bot.  */
XX  
XX! #include "sys/types.h"
XX! #include "fcntl.h"
XX! #include "stdlib.h"
XX! #include "unistd.h"
XX! #include "stdio.h"
XX  
XX! _PROTOTYPE(void fatal, (char *label));
XX! _PROTOTYPE(int cmp, (int fd1, int fd2));
XX! _PROTOTYPE(void Usage, (void));
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX  
XX! #define BLOCK	4096
XX  
XX! static int loud = 0, silent = 0;
XX! static char *name1, *name2;
XX  
XX! int main(argc, argv)
XX  int argc;
XX! char **argv;
XX  {
XX!   int fd1, fd2;
XX!   char *opt;
XX  
XX!   /* Process the '-l' or '-s' option. */
XX!   while (argc > 1 && argv[1][0] == '-' && argv[1][1] != 0) {
XX!   	if (argv[1][2] != 0) Usage();
XX  
XX!   	switch (argv[1][1]) {
XX!   	case '-':
XX!   		/* '--': no-op option. */
XX!   		break;
XX!   	case 'l':
XX! 		loud = 1;
XX! 		break;
XX! 	case 's':
XX! 		silent = 1;
XX! 		break;
XX! 	default:
XX! 		Usage();
XX! 	}
XX! 	argc--;
XX! 	argv++;
XX    }
XX+   if (argc != 3) Usage();
XX  
XX!   /* Open the first file, '-' means standard input. */
XX!   if (argv[1][0] == '-' && argv[1][1] == 0) {
XX! 	name1 = "stdin";
XX  	fd1 = 0;
XX    } else {
XX! 	name1 = argv[1];
XX! 	if ((fd1 = open(name1, 0)) < 0) fatal(name1);
XX    }
XX  
XX!   /* Second file likewise. */
XX!   if (argv[2][0] == '-' && argv[2][1] == 0) {
XX! 	name2 = "stdin";
XX! 	fd2 = 0;
XX!   } else {
XX! 	name2 = argv[2];
XX! 	if ((fd2 = open(name2, 0)) < 0) fatal(name2);
XX!   }
XX  
XX!   exit(cmp(fd1, fd2));
XX  }
XX  
XX! int cmp(fd1, fd2)
XX  int fd1, fd2;
XX  {
XX!   static char buf1[BLOCK], buf2[BLOCK];
XX!   int n1 = 0, n2 = 0, i1 = 0, i2 = 0, c1, c2;
XX!   off_t pos = 0, line = 1;
XX!   int eof = 0, differ = 0;
XX  
XX!   for (;;) {
XX! 	if (i1 == n1) {
XX! 		pos += n1;
XX! 
XX! 		if ((n1 = read(fd1, buf1, sizeof(buf1))) <= 0) {
XX! 			if (n1 < 0) fatal(name1);
XX! 			eof |= 1;
XX! 		}
XX! 		i1 = 0;
XX  	}
XX! 	if (i2 == n2) {
XX! 		if ((n2 = read(fd2, buf2, sizeof(buf2))) <= 0) {
XX! 			if (n2 < 0) fatal(name2);
XX! 			eof |= 2;
XX! 		}
XX! 		i2 = 0;
XX! 	}
XX! 	if (eof != 0) break;
XX! 
XX! 	c1 = buf1[i1++];
XX! 	c2 = buf2[i2++];
XX! 
XX! 	if (c1 != c2) {
XX! 		if (!loud) {
XX! 			if (!silent) {
XX  				printf("%s %s differ: char %ld, line %ld\n",
XX! 				       name1, name2, pos + i1, line);
XX  			}
XX! 			return(1);
XX  		}
XX! 		printf("%10ld %3o %3o\n", pos + i1, c1 & 0xFF, c2 & 0xFF);
XX! 		differ = 1;
XX  	}
XX! 	if (c1 == '\n') line++;
XX!   }
XX!   if (eof == (1 | 2)) return(differ);
XX!   if (!silent) fprintf(stderr, "cmp: EOF on %s\n", eof == 1 ? name1 : name2);
XX!   return(1);
XX  }
XX  
XX! void fatal(label)
XX! char *label;
XX  {
XX!   if (!silent) {
XX! 	fprintf(stderr, "cmp: ");
XX! 	fflush(stderr);
XX! 	perror(label);
XX    }
XX+   exit(2);
XX  }
XX  
XX! void Usage()
XX  {
XX    fprintf(stderr, "Usage: cmp [-l | -s] file1 file2\n");
XX    exit(2);
XX  }
X/
Xecho x - co.c.d
Xsed '/^X/s///' > co.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/co.c  crc=08933   5572	Sun Apr 25 21:34:50 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/co.c  crc=20440   5786	Wed Nov  4 04:19:07 1992
XX***************
XX*** 4,9 ****
XX--- 4,11 ----
XX  #include <sys/stat.h>
XX  #include <string.h>
XX  #include <pwd.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define SUFFIX		",S"	/* svc indicator */
XX***************
XX*** 27,44 ****
XX  int rev;			/* old revision number */
XX  int lastrev, lockrev;		/* latest file revision, lock into */
XX  int status;			/* wait() buffer */
XX! int lock;			/* lock the SVC file */
XX  struct stat stb;		/* stat() buffer */
XX  char *base;			/* basename of file */
XX  
XX  char difftemp[PATHLEN];		/* extract() fix/patch input */
XX  
XX! extern char *mktemp();
XX! extern struct passwd *getpwuid();
XX  
XX! char *whoami(), *basename();
XX! 
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 29,49 ----
XX  int rev;			/* old revision number */
XX  int lastrev, lockrev;		/* latest file revision, lock into */
XX  int status;			/* wait() buffer */
XX! int svclock;			/* lock the SVC file */
XX  struct stat stb;		/* stat() buffer */
XX  char *base;			/* basename of file */
XX  
XX  char difftemp[PATHLEN];		/* extract() fix/patch input */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void fname, (char *src, char *dst));
XX! _PROTOTYPE(void svcname, (char *src, char *dst));
XX! _PROTOTYPE(void extract, (char *script, char *out, int rev));
XX! _PROTOTYPE(char *basename, (char *name));
XX! _PROTOTYPE(char *whoami, (void));
XX! _PROTOTYPE(int getyn, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 58,64 ****
XX  				exit(1);
XX  			}
XX  		} else if ('l' == (*argv)[1])
XX! 			++lock;
XX  		else {
XX  			fprintf(stderr, "co: illegal option -%c\n", (*argv)[1]);
XX  			exit(1);
XX--- 63,69 ----
XX  				exit(1);
XX  			}
XX  		} else if ('l' == (*argv)[1])
XX! 			++svclock;
XX  		else {
XX  			fprintf(stderr, "co: illegal option -%c\n", (*argv)[1]);
XX  			exit(1);
XX***************
XX*** 76,82 ****
XX  
XX    fprintf(stderr, "%s -> %s\n", svc, base = basename(file));
XX  
XX!   if ((FILE *) NULL == (svcfp = fopen(svc, "r"))) {
XX  	perror("co: can't read SVC file");
XX  	exit(1);
XX    }
XX--- 81,87 ----
XX  
XX    fprintf(stderr, "%s -> %s\n", svc, base = basename(file));
XX  
XX!   if (NULL == (svcfp = fopen(svc, "r"))) {
XX  	perror("co: can't read SVC file");
XX  	exit(1);
XX    }
XX***************
XX*** 98,104 ****
XX    fprintf(stderr, "Checking out revision %d", rev);
XX    extract(svc, base, rev);
XX  
XX!   if (lock) {
XX  	lockrev = lastrev + 1;
XX  	fprintf(stderr, "; Locking into revision %d\n", lockrev);
XX  	if (stat(svc, &stb) < 0 || chmod(svc, stb.st_mode | 0200) < 0)
XX--- 103,109 ----
XX    fprintf(stderr, "Checking out revision %d", rev);
XX    extract(svc, base, rev);
XX  
XX!   if (svclock) {
XX  	lockrev = lastrev + 1;
XX  	fprintf(stderr, "; Locking into revision %d\n", lockrev);
XX  	if (stat(svc, &stb) < 0 || chmod(svc, stb.st_mode | 0200) < 0)
XX***************
XX*** 107,113 ****
XX  	if (stat(base, &stb) < 0 || chmod(base, stb.st_mode | 0200) < 0)
XX  		perror("co: can't chmod source file");
XX  
XX! 	if ((FILE *) NULL == (svcfp = fopen(svc, "a"))
XX  	    || (fprintf(svcfp, "#***SVCLOCK*** %s %d\n", whoami(), lockrev), ferror(svcfp))) {
XX  		fprintf(stderr, "co: can't lock %s\n", svc);
XX  		exit(1);
XX--- 112,118 ----
XX  	if (stat(base, &stb) < 0 || chmod(base, stb.st_mode | 0200) < 0)
XX  		perror("co: can't chmod source file");
XX  
XX! 	if (NULL == (svcfp = fopen(svc, "a"))
XX  	    || (fprintf(svcfp, "#***SVCLOCK*** %s %d\n", whoami(), lockrev), ferror(svcfp))) {
XX  		fprintf(stderr, "co: can't lock %s\n", svc);
XX  		exit(1);
XX***************
XX*** 120,130 ****
XX  		perror("co: can't chmod source file");
XX    }
XX  
XX!   exit(0);
XX  }
XX  
XX  
XX! fname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX--- 125,135 ----
XX  		perror("co: can't chmod source file");
XX    }
XX  
XX!   return(0);
XX  }
XX  
XX  
XX! void fname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX***************
XX*** 133,139 ****
XX    if (!strcmp(p, SUFFIX)) *p = '\0';
XX  }
XX  
XX! svcname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX--- 138,144 ----
XX    if (!strcmp(p, SUFFIX)) *p = '\0';
XX  }
XX  
XX! void svcname(src, dst)
XX  char *src, *dst;
XX  {
XX    char *p;
XX***************
XX*** 143,157 ****
XX  
XX    if (0 != access(dst, 4)) {
XX  	char dirname[PATHLEN];
XX! 	if ( (char *) NULL != (p = strrchr(src, '/')))
XX! 		strncpy(dirname, src, (int)(p - src) + 1);
XX  	else
XX  		dirname[0] = '\0';
XX  	strcat(dirname, SVCDIR);
XX  
XX  	if (0 == access(dirname, 1)) {
XX  		strcpy(dst, dirname);
XX! 		if ((char *) NULL == p) {
XX  			strcat(dst, "/");
XX  			strcat(dst, src);
XX  		} else
XX--- 148,162 ----
XX  
XX    if (0 != access(dst, 4)) {
XX  	char dirname[PATHLEN];
XX! 	if (NULL != (p = strrchr(src, '/')))
XX! 		strncpy(dirname, src, (size_t)(p - src) + 1);
XX  	else
XX  		dirname[0] = '\0';
XX  	strcat(dirname, SVCDIR);
XX  
XX  	if (0 == access(dirname, 1)) {
XX  		strcpy(dst, dirname);
XX! 		if (NULL == p) {
XX  			strcat(dst, "/");
XX  			strcat(dst, src);
XX  		} else
XX***************
XX*** 161,167 ****
XX    }
XX  }
XX  
XX! extract(script, out, rev)
XX  char *script, *out;
XX  int rev;
XX  {
XX--- 166,172 ----
XX    }
XX  }
XX  
XX! void extract(script, out, rev)
XX  char *script, *out;
XX  int rev;
XX  {
XX***************
XX*** 175,213 ****
XX    fgets(line, LINELEN, svcfp);	/* skip '# rev' line */
XX    fgets(line, LINELEN, svcfp);	/* skip 'cat <***MAIN-eof***' line */
XX  
XX!   if ((FILE *) NULL == (outfp = fopen(out, "w"))) {
XX  	perror("co: can't create output file");
XX  	return;
XX    }
XX!   while ((char *) NULL != fgets(line, LINELEN, svcfp) &&
XX  	  strcmp(line, "***MAIN-eof***\n"))
XX  	fputs(line, outfp);
XX  
XX    fclose(outfp);
XX  
XX!   while ((char *) NULL != fgets(line, LINELEN, svcfp)) {
XX! 	if (!strncmp(line, "if ", 3)) {
XX  		sscanf(line, "if test $2 -ge %d", &testrev);
XX  		if (rev >= testrev) {
XX  			unlink(difftemp);
XX  			return;
XX  		}
XX! 		if ((FILE *) NULL == (outfp = fopen(difftemp, "w"))) {
XX  			perror("co: can't create output file");
XX  			return;
XX  		}
XX  		sprintf(buf, "***%d-eof***\n", testrev);
XX! 		while ((char *) NULL != fgets(line, LINELEN, svcfp) &&
XX  							strcmp(line, buf))
XX  			fputs(line, outfp);
XX  		fclose(outfp);
XX! 	} else if (!strncmp(line, "mv ", 3)) {
XX  		sprintf(buf, "mv Fix.%s %s", out, out);
XX  		system(buf);
XX! 	} else if (!strncmp(line, "fix ", 4)) {
XX  		sprintf(buf, "fix %s Fix.%s > New.%s; mv New.%s %s", out, out, out, out, out);
XX  		system(buf);
XX! 	} else if (!strncmp(line, "patch ", 6)) {
XX  		sprintf(buf, "patch -n -s %s < Fix.%s; rm -f %s.orig", out, out, out);
XX  		system(buf);
XX  	} else {		/* ignore */
XX--- 180,218 ----
XX    fgets(line, LINELEN, svcfp);	/* skip '# rev' line */
XX    fgets(line, LINELEN, svcfp);	/* skip 'cat <***MAIN-eof***' line */
XX  
XX!   if (NULL == (outfp = fopen(out, "w"))) {
XX  	perror("co: can't create output file");
XX  	return;
XX    }
XX!   while (NULL != fgets(line, LINELEN, svcfp) &&
XX  	  strcmp(line, "***MAIN-eof***\n"))
XX  	fputs(line, outfp);
XX  
XX    fclose(outfp);
XX  
XX!   while (NULL != fgets(line, LINELEN, svcfp)) {
XX! 	if (!strncmp(line, "if ", (size_t)3)) {
XX  		sscanf(line, "if test $2 -ge %d", &testrev);
XX  		if (rev >= testrev) {
XX  			unlink(difftemp);
XX  			return;
XX  		}
XX! 		if (NULL == (outfp = fopen(difftemp, "w"))) {
XX  			perror("co: can't create output file");
XX  			return;
XX  		}
XX  		sprintf(buf, "***%d-eof***\n", testrev);
XX! 		while (NULL != fgets(line, LINELEN, svcfp) &&
XX  							strcmp(line, buf))
XX  			fputs(line, outfp);
XX  		fclose(outfp);
XX! 	} else if (!strncmp(line, "mv ", (size_t)3)) {
XX  		sprintf(buf, "mv Fix.%s %s", out, out);
XX  		system(buf);
XX! 	} else if (!strncmp(line, "fix ", (size_t)4)) {
XX  		sprintf(buf, "fix %s Fix.%s > New.%s; mv New.%s %s", out, out, out, out, out);
XX  		system(buf);
XX! 	} else if (!strncmp(line, "patch ", (size_t)6)) {
XX  		sprintf(buf, "patch -n -s %s < Fix.%s; rm -f %s.orig", out, out, out);
XX  		system(buf);
XX  	} else {		/* ignore */
XX***************
XX*** 223,229 ****
XX  {
XX    char *p;
XX  
XX!   if ((char *) NULL == (p = strrchr(name, '/')))
XX  	return name;
XX    else
XX  	return p + 1;
XX--- 228,234 ----
XX  {
XX    char *p;
XX  
XX!   if (NULL == (p = strrchr(name, '/')))
XX  	return name;
XX    else
XX  	return p + 1;
XX***************
XX*** 233,239 ****
XX  {
XX    struct passwd *pw;
XX  
XX!   if ((struct passwd *) NULL != (pw = getpwuid(getuid())))
XX  	return pw->pw_name;
XX    else
XX  	return "nobody";
XX--- 238,244 ----
XX  {
XX    struct passwd *pw;
XX  
XX!   if (NULL != (pw = getpwuid(getuid())))
XX  	return pw->pw_name;
XX    else
XX  	return "nobody";
XX***************
XX*** 243,247 ****
XX  {
XX    char ans[10];
XX  
XX!   return((char *) NULL != fgets(ans, 10, stdin)) && ('y' == ans[0] || 'Y' == ans[0]);
XX  }
XX--- 248,252 ----
XX  {
XX    char ans[10];
XX  
XX!   return(NULL != fgets(ans, 10, stdin)) && ('y' == ans[0] || 'Y' == ans[0]);
XX  }
X/
Xecho x - comm.c.d
Xsed '/^X/s///' > comm.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/comm.c  crc=00730   3509	Sun Apr 25 21:34:50 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/comm.c  crc=41699   4036	Wed Nov  4 04:19:07 1992
XX***************
XX*** 13,26 ****
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  
XX! #define BUFSIZ (512)
XX  #define LINMAX (600)
XX  
XX  struct file {
XX    char *name;			/* the file's name */
XX    int fd;			/* the file descripter */
XX!   char buf[BUFSIZ];		/* buffer storage */
XX    char *next;			/* the next character to read */
XX    char *endp;			/* the first invalid character */
XX    int seeneof;			/* an end of file has been seen */
XX--- 13,31 ----
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX! #define BUFFER_SIZE (512)
XX  #define LINMAX (600)
XX  
XX  struct file {
XX    char *name;			/* the file's name */
XX    int fd;			/* the file descripter */
XX!   char buf[BUFFER_SIZE];		/* buffer storage */
XX    char *next;			/* the next character to read */
XX    char *endp;			/* the first invalid character */
XX    int seeneof;			/* an end of file has been seen */
XX***************
XX*** 32,38 ****
XX  
XX  static char *umsg = "Usage: comm [-[123]] file1 file2\n";
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 37,53 ----
XX  
XX  static char *umsg = "Usage: comm [-[123]] file1 file2\n";
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(void error, (char *s, char *f));
XX! _PROTOTYPE(void eopen, (char *fn, struct file *file));
XX! _PROTOTYPE(int getbuf, (struct file *file));
XX! _PROTOTYPE(int readline, (int fno));
XX! _PROTOTYPE(void comm, (void));
XX! _PROTOTYPE(void putcol, (int col, char *buf));
XX! _PROTOTYPE(void cpycol, (int col));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 57,73 ****
XX    eopen(argv[1], &files[0]);
XX    eopen(argv[2], &files[1]);
XX    comm();
XX!   exit(0);
XX  }
XX  
XX! usage()
XX  {
XX  
XX    std_err(umsg);
XX    exit(1);
XX  }
XX  
XX! error(s, f)
XX  char *s, *f;
XX  {
XX    std_err("comm: ");
XX--- 72,88 ----
XX    eopen(argv[1], &files[0]);
XX    eopen(argv[2], &files[1]);
XX    comm();
XX!   return(0);
XX  }
XX  
XX! void usage()
XX  {
XX  
XX    std_err(umsg);
XX    exit(1);
XX  }
XX  
XX! void error(s, f)
XX  char *s, *f;
XX  {
XX    std_err("comm: ");
XX***************
XX*** 77,83 ****
XX    exit(1);
XX  }
XX  
XX! int eopen(fn, file)
XX  char *fn;
XX  struct file *file;
XX  {
XX--- 92,98 ----
XX    exit(1);
XX  }
XX  
XX! void eopen(fn, file)
XX  char *fn;
XX  struct file *file;
XX  {
XX***************
XX*** 100,106 ****
XX    int n;
XX  
XX    if (file->seeneof) return(1);
XX!   if ((n = read(file->fd, &file->buf[0], BUFSIZ)) < 0)
XX  	error("read error on ", file->name);
XX    if (n == 0) {
XX  	file->seeneof++;
XX--- 115,121 ----
XX    int n;
XX  
XX    if (file->seeneof) return(1);
XX!   if ((n = read(file->fd, &file->buf[0], BUFFER_SIZE)) < 0)
XX  	error("read error on ", file->name);
XX    if (n == 0) {
XX  	file->seeneof++;
XX***************
XX*** 133,139 ****
XX    return(1);
XX  }
XX  
XX! comm()
XX  {
XX    register int res;
XX  
XX--- 148,154 ----
XX    return(1);
XX  }
XX  
XX! void comm()
XX  {
XX    register int res;
XX  
XX***************
XX*** 172,189 ****
XX    /* NOTREACHED */
XX  }
XX  
XX! putcol(col, buf)
XX  int col;
XX  char *buf;
XX  {
XX    int cnt;
XX  
XX    if (colflgs[col] == 0) return;
XX!   for (cnt = 0; cnt < colflgs[col] - 1; cnt++) prints("\t");
XX!   prints("%s", buf);
XX  }
XX  
XX! cpycol(col)
XX  int col;
XX  {
XX    if (colflgs[col]) while (readline(col))
XX--- 187,204 ----
XX    /* NOTREACHED */
XX  }
XX  
XX! void putcol(col, buf)
XX  int col;
XX  char *buf;
XX  {
XX    int cnt;
XX  
XX    if (colflgs[col] == 0) return;
XX!   for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
XX!   printf("%s", buf);
XX  }
XX  
XX! void cpycol(col)
XX  int col;
XX  {
XX    if (colflgs[col]) while (readline(col))
X/
Xecho x - compress.c.d
Xsed '/^X/s///' > compress.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/compress.c  crc=49047  38455	Sun Apr 25 21:34:50 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/compress.c  crc=10051  38972	Wed Nov  4 04:19:07 1992
XX***************
XX*** 73,80 ****
XX  #define DOTZ ".Z"
XX  
XX  #ifdef AZTEC86 
XX- void prratio(),cl_block(),cl_hash(),output(),decompress(),
XX- copystat(),writeerr(),compress(),Usage(),version();
XX  #ifdef AZTECBITS
XX  # define BITS   AZTECBITS
XX  #else
XX--- 73,78 ----
XX***************
XX*** 148,154 ****
XX  #else
XX   typedef	unsigned char	char_type;
XX  #endif /* UCHAR */
XX! char_type magic_header[] = { "\037\235" };	/* 1F 9D */
XX  
XX  /* Defines for third byte of header */
XX  #define BIT_MASK	0x1f
XX--- 146,152 ----
XX  #else
XX   typedef	unsigned char	char_type;
XX  #endif /* UCHAR */
XX! char_type magic_header[] = "\037\235";	/* 1F 9D */
XX  
XX  /* Defines for third byte of header */
XX  #define BIT_MASK	0x1f
XX***************
XX*** 163,168 ****
XX--- 161,170 ----
XX  #include <fcntl.h>
XX  #include <ctype.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <utime.h>
XX  #include <stdio.h>
XX  
XX  #define ARGVAL() (*++(*argv) || (--argc && *++argv))
XX***************
XX*** 183,190 ****
XX  #else
XX  	count_int *htab;
XX  	unsigned short *codetab;
XX! #	define HTABSIZE ((unsigned)(HSIZE*sizeof(count_int)))
XX! #	define CODETABSIZE ((unsigned)(HSIZE*sizeof(unsigned short)))
XX  
XX  
XX  #define htabof(i)	htab[i]
XX--- 185,192 ----
XX  #else
XX  	count_int *htab;
XX  	unsigned short *codetab;
XX! #	define HTABSIZE ((size_t)(HSIZE*sizeof(count_int)))
XX! #	define CODETABSIZE ((size_t)(HSIZE*sizeof(unsigned short)))
XX  
XX  
XX  #define htabof(i)	htab[i]
XX***************
XX*** 214,220 ****
XX  code_int free_ent = 0;			/* first unused entry */
XX  int exit_stat = 0;
XX  
XX! code_int getcode();
XX  
XX  void Usage() {
XX  #ifdef DEBUG
XX--- 216,237 ----
XX  code_int free_ent = 0;			/* first unused entry */
XX  int exit_stat = 0;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void Usage, (void));
XX! _PROTOTYPE(void compress, (void));
XX! _PROTOTYPE(void onintr, (int dummy));
XX! _PROTOTYPE(void oops, (int dummy));
XX! _PROTOTYPE(void output, (code_int code));
XX! _PROTOTYPE(int foreground, (void));
XX! _PROTOTYPE(void decompress, (void));
XX! _PROTOTYPE(code_int getcode, (void)); 
XX! _PROTOTYPE(void writeerr, (void));
XX! _PROTOTYPE(void copystat, (char *ifname, char *ofname));
XX! _PROTOTYPE(int foreground, (void));
XX! _PROTOTYPE(void cl_block , (void));
XX! _PROTOTYPE(void cl_hash, (count_int hsize));
XX! _PROTOTYPE(void prratio, (FILE *stream, long int num, long int den));
XX! _PROTOTYPE(void version, (void));
XX  
XX  void Usage() {
XX  #ifdef DEBUG
XX***************
XX*** 257,278 ****
XX  #else
XX  int
XX  #endif
XX  (*bgnd_flag)();
XX  #endif
XX  
XX  int do_decomp = 0;
XX  
XX  
XX! void main( argc, argv )
XX! REGISTER int argc; char **argv;
XX  {
XX      int overwrite = 0;	/* Do not overwrite unless given -f flag */
XX      char tempname[100];
XX      char **filelist, **fileptr;
XX!     char *cp;extern char *strrchr(), *malloc();
XX      struct stat statbuf;
XX  #ifndef METAWARE
XX-     extern void onintr(), oops();
XX      if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
XX  	signal ( SIGINT, onintr );
XX  	signal ( SIGSEGV, oops );
XX--- 274,299 ----
XX  #else
XX  int
XX  #endif
XX+ #ifndef __STDC__
XX  (*bgnd_flag)();
XX+ #else
XX+ (*bgnd_flag)(int);
XX  #endif
XX+ #endif
XX  
XX  int do_decomp = 0;
XX  
XX  
XX! int main(argc, argv)
XX! int argc;
XX! char **argv;
XX  {
XX      int overwrite = 0;	/* Do not overwrite unless given -f flag */
XX      char tempname[100];
XX      char **filelist, **fileptr;
XX!     char *cp;
XX      struct stat statbuf;
XX  #ifndef METAWARE
XX      if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
XX  	signal ( SIGINT, onintr );
XX  	signal ( SIGSEGV, oops );
XX***************
XX*** 300,306 ****
XX      nomagic = 1;	/* Original didn't have a magic number */
XX  #endif /* COMPATIBLE */
XX  
XX!     filelist = fileptr = (char **)(malloc((unsigned)(argc * sizeof(*argv))));
XX      *filelist = NULL;
XX  
XX      if((cp = strrchr(argv[0], '/')) != 0) {
XX--- 321,327 ----
XX      nomagic = 1;	/* Original didn't have a magic number */
XX  #endif /* COMPATIBLE */
XX  
XX!     filelist = fileptr = (char **)(malloc((size_t)(argc * sizeof(*argv))));
XX      *filelist = NULL;
XX  
XX      if((cp = strrchr(argv[0], '/')) != 0) {
XX***************
XX*** 428,434 ****
XX  #else
XX  					/* either tack one on or replace last character */
XX  					{
XX! 						char *dot;extern char *strchr();
XX  						if (NULL == (dot = strchr(tempname,'.')))
XX  						{
XX  							strcat(tempname,".Z");
XX--- 449,455 ----
XX  #else
XX  					/* either tack one on or replace last character */
XX  					{
XX! 						char *dot;
XX  						if (NULL == (dot = strchr(tempname,'.')))
XX  						{
XX  							strcat(tempname,".Z");
XX***************
XX*** 482,488 ****
XX  #else
XX  				/* kludge to handle various common three character extension */
XX  				{
XX! 					char *dot; extern char *strchr();
XX  					char fixup = '\0';
XX  					/* first off, map name to upper case */
XX  					for (dot = ofname; *dot; dot++)
XX--- 503,509 ----
XX  #else
XX  				/* kludge to handle various common three character extension */
XX  				{
XX! 					char *dot; 
XX  					char fixup = '\0';
XX  					/* first off, map name to upper case */
XX  					for (dot = ofname; *dot; dot++)
XX***************
XX*** 561,567 ****
XX  				else
XX  				{
XX  					/* either tack one on or replace last character */
XX! 					char *dot;extern char *strchr();
XX  					if (NULL == (dot = strchr(cp,'.')))
XX  					{
XX  						strcat(cp,".Z");
XX--- 582,588 ----
XX  				else
XX  				{
XX  					/* either tack one on or replace last character */
XX! 					char *dot;
XX  					if (NULL == (dot = strchr(cp,'.')))
XX  					{
XX  						strcat(cp,".Z");
XX***************
XX*** 690,696 ****
XX  #endif /* DEBUG */
XX  		}
XX      }
XX!     exit(exit_stat);
XX  }
XX  
XX  static int offset;
XX--- 711,717 ----
XX  #endif /* DEBUG */
XX  		}
XX      }
XX!     return(exit_stat);
XX  }
XX  
XX  static int offset;
XX***************
XX*** 913,922 ****
XX  	temp = (code << r_off) & lmask[r_off];
XX  	*bp |= temp;
XX  #else
XX! 	*bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
XX  #endif
XX  #else
XX! 	*bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
XX  #endif
XX  	bp++;
XX  	bits -= (8 - r_off);
XX--- 934,943 ----
XX  	temp = (code << r_off) & lmask[r_off];
XX  	*bp |= temp;
XX  #else
XX! 	*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
XX  #endif
XX  #else
XX! 	*bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]);
XX  #endif
XX  	bp++;
XX  	bits -= (8 - r_off);
XX***************
XX*** 956,962 ****
XX  	     */
XX  	    if ( offset > 0 ) 
XX  		{
XX! 			if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
XX  				writeerr();
XX  			bytes_out += n_bits;
XX  	    }
XX--- 977,983 ----
XX  	     */
XX  	    if ( offset > 0 ) 
XX  		{
XX! 			if( fwrite( buf, (size_t)1, (size_t)n_bits, stdout ) != n_bits)
XX  				writeerr();
XX  			bytes_out += n_bits;
XX  	    }
XX***************
XX*** 989,995 ****
XX  	 * At EOF, write the rest of the buffer.
XX  	 */
XX  	if ( offset > 0 )
XX! 	    fwrite( buf, 1, (offset + 7) / 8, stdout );
XX  	bytes_out += (offset + 7) / 8;
XX  	offset = 0;
XX  	fflush( stdout );
XX--- 1010,1016 ----
XX  	 * At EOF, write the rest of the buffer.
XX  	 */
XX  	if ( offset > 0 )
XX! 	    fwrite( buf, (size_t)1, (size_t)(offset + 7) / 8, stdout );
XX  	bytes_out += (offset + 7) / 8;
XX  	offset = 0;
XX  	fflush( stdout );
XX***************
XX*** 1132,1138 ****
XX      	    maxcode = MAXCODE (n_bits = INIT_BITS);
XX  		    clear_flg = 0;
XX  		}
XX! 		size = fread( buf, 1, n_bits, stdin );
XX  		if ( size <= 0 )
XX  		    return -1;			/* end of file */
XX  		offset = 0;
XX--- 1153,1159 ----
XX      	    maxcode = MAXCODE (n_bits = INIT_BITS);
XX  		    clear_flg = 0;
XX  		}
XX! 		size = fread( buf, (size_t)1, (size_t)n_bits, stdin );
XX  		if ( size <= 0 )
XX  		    return -1;			/* end of file */
XX  		offset = 0;
XX***************
XX*** 1188,1205 ****
XX  	return(p);
XX  }
XX  #endif
XX- #ifdef _MINIX
XX- char *
XX- strrchr(s, c)		/* For those who don't have it in libc.a */
XX- REGISTER char *s, c;
XX- {
XX- 	char *p;
XX- 	for (p = NULL; *s; s++)
XX- 	    if (*s == c)
XX- 		p = s;
XX- 	return(p);
XX- }
XX- #endif
XX  
XX  
XX  #ifndef METAWARE
XX--- 1209,1214 ----
XX***************
XX*** 1266,1272 ****
XX  						stack_top);
XX  		}
XX  		stack_top = in_stack(ent, stack_top);
XX! 		fwrite( &stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
XX  	   	stack_top = STACK_SIZE;
XX  	}
XX     } else if(!debug) {	/* decompressing */
XX--- 1275,1281 ----
XX  						stack_top);
XX  		}
XX  		stack_top = in_stack(ent, stack_top);
XX! 		fwrite( &stack[stack_top], (size_t)1, (size_t)(STACK_SIZE-stack_top), stderr);
XX  	   	stack_top = STACK_SIZE;
XX  	}
XX     } else if(!debug) {	/* decompressing */
XX***************
XX*** 1286,1292 ****
XX  		   ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
XX  	       stack_top = in_stack(tab_suffixof(ent), stack_top);
XX  	   }
XX! 	   fwrite( &stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
XX  	   stack_top = STACK_SIZE;
XX         }
XX      }
XX--- 1295,1301 ----
XX  		   ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
XX  	       stack_top = in_stack(tab_suffixof(ent), stack_top);
XX  	   }
XX! 	   fwrite( &stack[stack_top], (size_t)1, (size_t)(STACK_SIZE - stack_top), stderr );
XX  	   stack_top = STACK_SIZE;
XX         }
XX      }
XX***************
XX*** 1389,1395 ****
XX  		timep[0] = statbuf.st_mtime;
XX  		timep[1] = statbuf.st_mtime;
XX  #endif
XX! 		utime(ofname, timep);	/* Update last accessed and modified times */
XX  /*
XX  		if (unlink(ifname))
XX  		    perror(ifname);
XX--- 1398,1404 ----
XX  		timep[0] = statbuf.st_mtime;
XX  		timep[1] = statbuf.st_mtime;
XX  #endif
XX! 		utime(ofname, (struct utimbuf *)timep);	/* Update last accessed and modified times */
XX  /*
XX  		if (unlink(ifname))
XX  		    perror(ifname);
XX***************
XX*** 1427,1440 ****
XX  #endif
XX  }
XX  #ifndef METAWARE
XX! void onintr ( )
XX  {
XX  	(void)signal(SIGINT,SIG_IGN);
XX      unlink ( ofname );
XX      exit ( 1 );
XX  }
XX  
XX! void oops ( )	/* wild pointer -- assume bad input */
XX  {
XX  	(void)signal(SIGSEGV,SIG_IGN);
XX      if ( do_decomp == 1 ) 
XX--- 1436,1451 ----
XX  #endif
XX  }
XX  #ifndef METAWARE
XX! void onintr (dummy)
XX! int dummy; /* to keep the compiler happy */
XX  {
XX  	(void)signal(SIGINT,SIG_IGN);
XX      unlink ( ofname );
XX      exit ( 1 );
XX  }
XX  
XX! void oops (dummy)	/* wild pointer -- assume bad input */
XX! int dummy; /* to keep the compiler happy */
XX  {
XX  	(void)signal(SIGSEGV,SIG_IGN);
XX      if ( do_decomp == 1 ) 
XX***************
XX*** 1491,1497 ****
XX  #ifdef AZTEC86
XX  #ifdef PCDOS
XX  	/* This function only in PC-DOS lib, not in MINIX lib */
XX! 	memset(htab,-1,(int)(hsize * sizeof(count_int)));
XX  #else
XX  /* MINIX and all non-PC machines do it this way */	
XX  #ifndef XENIX_16	/* Normal machine */
XX--- 1502,1508 ----
XX  #ifdef AZTEC86
XX  #ifdef PCDOS
XX  	/* This function only in PC-DOS lib, not in MINIX lib */
XX! 	memset(htab,-1, hsize * sizeof(count_int));
XX  #else
XX  /* MINIX and all non-PC machines do it this way */	
XX  #ifndef XENIX_16	/* Normal machine */
XX***************
XX*** 1551,1557 ****
XX  
XX  void prratio(stream, num, den)
XX  FILE *stream;
XX! long int num, den;
XX  {
XX  	REGISTER int q;			/* Doesn't need to be long */
XX  	if(num > 214748L) 
XX--- 1562,1569 ----
XX  
XX  void prratio(stream, num, den)
XX  FILE *stream;
XX! long int num;
XX! long int den;
XX  {
XX  	REGISTER int q;			/* Doesn't need to be long */
XX  	if(num > 214748L) 
X/
Xecho x - cp.c.d
Xsed '/^X/s///' > cp.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cp.c  crc=27469   3954	Sun Apr 25 21:34:51 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cp.c  crc=24572  12871	Mon Mar  1 12:39:55 1993
XX***************
XX*** 1,210 ****
XX! /* cp - copy files		Author: Andy Tanenbaum */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  
XX! #define TRANSFER_UNIT    16384
XX! char cpbuf[TRANSFER_UNIT];
XX! int isfloppy;			/* set to 1 for cp x /dev/fd? */
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int fd1, fd2, m, s;
XX!   struct stat sbuf, sbuf2;
XX  
XX!   if (argc < 3) usage();
XX! 
XX!   /* Get the status of the last named file.  See if it is a directory. */
XX!   s = stat(argv[argc - 1], &sbuf);
XX!   m = sbuf.st_mode & S_IFMT;
XX!   if (s >= 0 && m == S_IFDIR) {
XX! 	/* Last argument is a directory. */
XX! 	exit(cp_to_dir(argc, argv));
XX!   } else if (argc > 3) {
XX! 	/* More than 2 arguments and last one is not a directory. */
XX! 	usage();
XX!   } else if (s < 0 || m == S_IFREG || m == S_IFCHR || m == S_IFBLK) {
XX! 	/* Exactly two arguments.  Check for cp f1 f1. */
XX! 	if (equal(argv[1], argv[2])) {
XX! 		std_err("cp: cannot copy a file to itself\n");
XX! 		exit(-1);
XX  	}
XX  
XX! 	/* Command is of the form cp f1 f2. */
XX! 	fd1 = open(argv[1], O_RDONLY);
XX! 	if (fd1 < 0) {
XX! 		stderr3("cannot open ", argv[1], "\n");
XX! 		exit(1);
XX  	}
XX! 	fstat(fd1, &sbuf);
XX! 	m = sbuf.st_mode & S_IFMT;
XX! 	if (m == S_IFDIR) {
XX! 		stderr3("<", argv[1], "> directory\n");
XX! 		exit(1);
XX! 	}
XX! 	fd2 = creat(argv[2], sbuf.st_mode & 0777);
XX! 	if (fd2 < 0) {
XX! 		stderr3("cannot create ", argv[2], "\n");
XX! 		exit(2);
XX! 	}
XX! 	fstat(fd2, &sbuf2);
XX! 	if ((sbuf2.st_mode & S_IFMT) == S_IFBLK) isfloppy = 1;
XX! 	copyfile(fd1, fd2, argv[2]);
XX!   } else {
XX! 	stderr3("cannot copy to ", argv[2], "\n");
XX! 	exit(3);
XX!   }
XX!   exit(0);
XX  }
XX  
XX  
XX  
XX  
XX  
XX! cp_to_dir(argc, argv)
XX! int argc;
XX! char *argv[];
XX  {
XX!   int i, mode, fd1, fd2, exit_status = 0;
XX!   char dirname[256], *ptr, *dp;
XX!   struct stat sbuf;
XX  
XX!   for (i = 1; i < argc - 1; i++) {
XX! 	fd1 = open(argv[i], O_RDONLY);
XX! 	if (fd1 < 0) {
XX! 		stderr3("cannot open ", argv[i], "\n");
XX! 		exit_status = 1;
XX! 		continue;
XX! 	}
XX! 	ptr = argv[argc - 1];
XX! 	dp = dirname;
XX! 	while (*ptr != 0) *dp++ = *ptr++;
XX  
XX- 	*dp++ = '/';
XX- 	ptr = argv[i];
XX  
XX! 	/* Concatenate dir and file name in dirname buffer. */
XX! 	while (*ptr != 0) ptr++;/* go to end of file name */
XX! 	while (ptr > argv[i] && *ptr != '/') ptr--;	/* get last component */
XX! 	if (*ptr == '/') ptr++;
XX! 	while (*ptr != 0) *dp++ = *ptr++;
XX! 	*dp++ = 0;
XX! 	fstat(fd1, &sbuf);
XX! 	mode = sbuf.st_mode & S_IFMT;
XX! 	if (mode == S_IFDIR) {
XX! 		stderr3("<", argv[i], "> directory\n");
XX! 		exit_status = 1;
XX! 		close(fd1);
XX! 		continue;
XX! 	}
XX! 	fd2 = creat(dirname, sbuf.st_mode & 0777);
XX! 	if (fd2 < 0) {
XX! 		stderr3("cannot create ", dirname, "\n");
XX! 		exit_status = 2;
XX! 		close(fd1);
XX! 		continue;
XX! 	}
XX! 	copyfile(fd1, fd2, dirname);
XX    }
XX!   return(exit_status);
XX  }
XX  
XX  
XX  
XX  
XX  
XX! copyfile(fd1, fd2, name)
XX! int fd1, fd2;
XX! char *name;
XX  {
XX!   int n, m, mode;
XX!   struct stat sbuf;
XX  
XX!   do {
XX! 	n = read(fd1, cpbuf, TRANSFER_UNIT);
XX  	if (n < 0) {
XX! 		std_err("cp: read error\n");
XX  		break;
XX  	}
XX! 	if (n > 0) {
XX! 		m = write(fd2, cpbuf, n);
XX! 		if (m != n) {
XX! 			/* Write failed.  Don't keep truncated
XX! 			 * regular file. */
XX! 			perror("cp");
XX! 			fstat(fd2, &sbuf);	/* check for special files */
XX! 			mode = sbuf.st_mode & S_IFMT;
XX! 			if (mode == S_IFREG) unlink(name);
XX! 			exit(1);
XX  		}
XX! 		if (isfloppy) sync();	/* purge the cache all at once */
XX  	}
XX!   } while (n == TRANSFER_UNIT);
XX!   close(fd1);
XX    close(fd2);
XX  }
XX  
XX! usage()
XX  {
XX!   std_err("Usage:  cp f1 f2;  or  cp f1 ... fn d2\n");
XX!   exit(-1);
XX! }
XX  
XX! typedef char *cptr;
XX  
XX! int equal(s1, s2)
XX! char *s1, *s2;
XX! {
XX!   struct stat sb1, sb2;
XX  
XX!   /* Same file, different name? */
XX!   stat(s1, &sb1);
XX!   stat(s2, &sb2);
XX!   if (memcmp((cptr) & sb1, (cptr) & sb2, sizeof(struct stat)) == 0)
XX! 	return(1);
XX!   /* Same file, same name? */
XX!   while (1) {
XX! 	if (*s1 == 0 && *s2 == 0) return(1);
XX! 	if (*s1 != *s2) return (0);
XX! 	if (*s1 == 0 || *s2 == 0) return (0);
XX! 	s1++;
XX! 	s2++;
XX    }
XX- }
XX  
XX! int match(s1, s2, n)
XX! char *s1, *s2;
XX! int n;
XX! {
XX!   while (n--) {
XX! 	if (*s1++ != *s2++) return(0);
XX    }
XX-   return(1);
XX  }
XX  
XX  
XX! stderr3(s1, s2, s3)
XX! char *s1, *s2, *s3;
XX  {
XX!   std_err("cp: ");
XX!   std_err(s1);
XX!   std_err(s2);
XX!   std_err(s3);
XX  }
XX  
XX  
XX! int memcmp(b1, b2, n)
XX! cptr b1, b2;
XX! int n;
XX  {
XX!   while (n--) {
XX! 	if (*b1 != *b2) return((int) (*b1 - *b2));
XX! 	++b1;
XX! 	++b2;
XX!   }
XX!   return(0);
XX  }
XX--- 1,600 ----
XX! /* cp - Copy files					Author: V. Archer */
XX  
XX+ /* Copyright 1991 by Vincent Archer
XX+  *	You may freely redistribute this software, in source or binary
XX+  *	form, provided that you do not alter this copyright mention in any
XX+  *	way.
XX+  */
XX+ 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <minix/minlib.h>
XX  #include <fcntl.h>
XX+ #include <dirent.h>
XX+ #include <errno.h>
XX+ #include <limits.h>
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <utime.h>
XX+ #include <blocksize.h>
XX+ #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! #define ALL_MODES (S_IRWXU|S_IRWXG|S_IRWXO)
XX! #define NONE ((char *)0)
XX  
XX+ /* A link (for cpdir) descriptor. Link are never un-allocated, this allow
XX+  * race conditions (a user creating links while another is busy copying the
XX+  * hierarchy in which they reside, for example), at the price of memory
XX+  * shortage...
XX+  */
XX+ typedef struct _link_ {
XX+   struct _link_ *next;
XX+   dev_t st_dev;
XX+   ino_t st_ino;
XX+   char *path;
XX+ } LINK;
XX  
XX! /* A tree (for cp -Rr/cpdir) descriptor. It is used when a directory cannot
XX!  * be opened due to file descriptor shortage. For cp, it would be safe to
XX!  * block on that condition. For mv (which calls cpdir -p), however, P1003.2
XX!  * requires that the copy should NOT fail! Therefore, for each directory to
XX!  * be opened, another might be closed. When we get back to that directory's
XX!  * level, however, we'll have to reopen it and move to our previous position
XX!  * within this directory.
XX!  */
XX! typedef struct _tree_ {
XX!   struct _tree_ *next;
XX!   DIR *dirp;
XX!   off_t pos;
XX!   struct stat st;
XX! } TREE;
XX! 
XX! int cflag, dflag, fflag, iflag, pflag, rflag, rrflag, vflag;
XX! int errors;
XX! 
XX! /* Common variables. The copy buffer is limited to PIPE_BUF to avoid errors
XX!  * in cp -r (lowercase r) while copying from a pipe.
XX!  */
XX! char *dest;
XX! char dst_path[PATH_MAX + 1], src_path[PATH_MAX + 1];
XX! char buffer[PIPE_BUF];
XX! LINK *links;
XX! TREE *toplevel;
XX! struct stat st2;
XX! uid_t userid;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int negative, (void));
XX! _PROTOTYPE(char *octal, (Mode_t num));
XX! _PROTOTYPE(void doing, (char *what, char *with, char *on));
XX! _PROTOTYPE(void do_close, (void));
XX! _PROTOTYPE(void similar, (struct stat *sp));
XX! _PROTOTYPE(void do_cpfile, (int new, struct stat *st));
XX! _PROTOTYPE(void do_cpdir, (int new, struct stat *oldmode, TREE *dotdot));
XX! _PROTOTYPE(int do_cp, (char *source));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! extern int optind, opterr;
XX! 
XX! /* Main module. If cp is invoked as "cpdir", the -R flag is automatically
XX!  * turned on. Furthermore, the 'c' pseudo-flag is set, meaning that links
XX!  * to the same source file should be preserved across the copy. 'c' cancels
XX!  * any '-r' invocation.
XX!  * The '-v' flag is maintained for compatibility with old cpdir.
XX!  */
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   char *s;
XX!   int c;
XX!   struct stat st;
XX  
XX!   if ((s = strrchr(*argv, '/')) != NULL)
XX! 	s++;
XX!   else
XX! 	s = *argv;
XX!   if (strcmp(s, "cpdir") == 0) {
XX! 	cflag = 1;
XX! 	rflag = 1;
XX! 	rrflag = 1;
XX!   }
XX!   opterr = 0;
XX!   while ((c = getopt(argc, argv, "Rfimprsv")) != EOF) switch (c) {
XX! 	    case 'f':
XX! 		fflag = 1;
XX! 		iflag = 0;
XX! 		break;
XX! 	    case 'i':
XX! 		iflag = 1;
XX! 		fflag = 0;
XX! 		break;
XX! 	    case 'm':
XX! 		break;
XX! 	    case 's':
XX! 	    case 'p':	pflag = 1;	break;
XX! 	    case 'v':	vflag = 1;	break;
XX! 	    case 'R':	rrflag = 1;
XX! 	    case 'r':	rflag = 1;	break;
XX! 	    default:	usage();
XX  	}
XX+   argc -= optind;
XX+   if (argc < 2) usage();
XX+   if (argc > 2 && cflag) usage();
XX+   argv += optind;
XX+   dest = argv[--argc];
XX+   userid = getuid();
XX  
XX!   if (!cflag)
XX! 	if (stat(dest, &st)) {
XX! 		if (argc > 1) {
XX! 			perror(dest);
XX! 			return(1);
XX! 		}
XX! 	} else if (S_ISDIR(st.st_mode))
XX! 		dflag = 1;
XX! 	else if (argc > 1 || rflag) {
XX! 		errno = ENOTDIR;
XX! 		perror(dest);
XX! 		return(1);
XX  	}
XX!   while (argc--) errors |= do_cp(*argv++);
XX!   return(errors);
XX  }
XX  
XX  
XX+ /* Wait for a user answer from the stdin stream (but do not use stdio which
XX+  * is bulky and unneeded in most tools). An error (or end of file) on file
XX+  * descriptor 0 is assumed to mean a NEGATIVE answer. LC_* locale could be
XX+  * handled here.
XX+  */
XX+ int negative()
XX+ {
XX+   char c, t;
XX  
XX+   if (read(0, &c, 1) != 1) return(1);
XX+   t = c;
XX+   while (t != '\n')
XX+ 	if (read(0, &t, 1) != 1) break;
XX+   return(c != 'y' && c != 'Y');
XX+ }
XX  
XX  
XX! /* Quick transformation of a mode_t in 3-digits octal form. */
XX! char *octal(num)
XX! mode_t num;
XX  {
XX!   static char a[4];
XX  
XX!   a[0] = (((num >> 6) & 7) + '0');
XX!   a[1] = (((num >> 3) & 7) + '0');
XX!   a[2] = ((num & 7) + '0');
XX!   a[3] = 0;
XX!   return(a);
XX! }
XX  
XX  
XX! /* Verbose output of the operation. mknod4 could be better shown than thru
XX!  * this, but I don't care...
XX!  */
XX! void doing(what, with, on)
XX! char *what, *with, *on;
XX! {
XX!   std_err(what);
XX!   std_err(with);
XX!   if (on) {
XX! 	std_err(" ");
XX! 	std_err(on);
XX    }
XX!   std_err("\n");
XX  }
XX  
XX  
XX+ /* Close a previously opened directory stream when file descriptors are
XX+  * needed. The streams are closed in a First-Open-First-Closed (FIFO) order,
XX+  * because high-level directories are less likely to be needed soon than
XX+  * lower-level directories.
XX+  */
XX+ void do_close()
XX+ {
XX+   TREE *sweep;
XX  
XX+   for (sweep = toplevel; sweep; sweep = sweep->next)
XX+ 	if (sweep->dirp) {
XX+ 		closedir(sweep->dirp);
XX+ 		sweep->dirp = (DIR *) 0;
XX+ 		return;
XX+ 	}
XX+   std_err("FATAL:");
XX+   perror("cpdir");
XX+   exit(1);
XX+ }
XX  
XX  
XX! /* This function handles the "-p" option. */
XX! void similar(sp)
XX! struct stat *sp;
XX  {
XX!   struct utimbuf timer;
XX  
XX!   timer.actime = sp->st_atime;
XX!   timer.modtime = sp->st_mtime;
XX!   if (utime(dst_path, &timer)) {
XX! 	perror(dst_path);
XX! 	errors = 1;
XX!   }
XX!   if (chown(dst_path, sp->st_uid, sp->st_gid) || userid != 0)
XX! 	sp->st_mode &= ALL_MODES;
XX!   if (chmod(dst_path, sp->st_mode)) {
XX! 	perror(dst_path);
XX! 	errors = 1;
XX!   }
XX! }
XX! 
XX! 
XX! /* This copy a directory entry (non-directory inode) to a (possibly new)
XX!  * destination. Prompting, linking and mkfifo/mknod4 are done here.
XX!  */
XX! void do_cpfile(new, st)
XX! int new;
XX! struct stat *st;
XX! {
XX!   int fd, fd2, n, m;
XX!   char *bufp;
XX!   long s;
XX!   LINK *linkp;
XX! 
XX!   if (!new) {
XX! 	if (iflag) {
XX! 		std_err(dst_path);
XX! 		std_err(": replace ? ");
XX! 		if (negative()) return;
XX! 	}
XX! 	if (access(dst_path, 2)) {
XX! 		perror(dst_path);
XX! 		errors = 1;
XX! 		return;
XX! 	}
XX!   }
XX!   if (cflag && st->st_nlink > 1) {
XX! 	n = 0;
XX! 	for (linkp = links; linkp; linkp = linkp->next)
XX! 		if (linkp->st_dev == st->st_dev &&
XX! 		    linkp->st_ino == st->st_ino) {
XX! 			if (!new) {
XX! 				if (vflag) doing("unlink ", dst_path, NONE);
XX! 				if (unlink(dst_path)) {
XX! 					perror(dst_path);
XX! 					errors = 1;
XX! 					return;
XX! 				} else
XX! 					new = 1;
XX! 			}
XX! 			if (vflag) doing("link ", linkp->path, dst_path);
XX! 			if (!link(linkp->path, dst_path)) {
XX! 				return;
XX! 			}
XX! 			if (errno != EXDEV) {
XX! 				std_err(src_path);
XX! 				std_err(", ");
XX! 				perror(dst_path);
XX! 			} else if (!n) {
XX! 				std_err(dst_path);
XX! 				std_err(": cross device link snapped\n");
XX! 			}
XX! 			n = 1;	/* display snap once */
XX! 		}
XX! 	if ((linkp = (LINK *) malloc(sizeof(LINK))) == (LINK *) 0)
XX! 		perror(dst_path);
XX! 	else if ((linkp->path = (char *)malloc(strlen(dst_path) + 1)) == NONE){
XX! 		perror(dst_path);
XX! 		free(linkp);
XX! 	} else {
XX! 		strcpy(linkp->path, dst_path);
XX! 		linkp->st_dev = st->st_dev;
XX! 		linkp->st_ino = st->st_ino;
XX! 		linkp->next = links;
XX! 		links = linkp;
XX! 	}
XX!   }
XX!   if (
XX! #ifdef S_IFLNK
XX!       S_ISLNK(st->st_mode) ||
XX! #endif
XX!       rrflag && (S_ISBLK(st->st_mode) ||
XX! 		S_ISCHR(st->st_mode) || S_ISFIFO(st->st_mode))) {
XX! 	if (!new) {
XX! 		if (vflag) doing("unlink ", dst_path, NONE);
XX! 		if (unlink(dst_path)) {
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			return;
XX! 		}
XX! 	}
XX! 	if (S_ISFIFO(st->st_mode)) {
XX! 		if (vflag) doing("mkfifo ", dst_path, octal(st->st_mode));
XX! 		if (mkfifo(dst_path, st->st_mode & ALL_MODES)) {
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			return;
XX! 		}
XX! 	} else if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) {
XX! 		if (vflag) doing("mknod4 ", dst_path, octal(st->st_mode));
XX! 		s = (long) st->st_size / BLOCK_SIZE;
XX! 		if (mknod4(dst_path, st->st_mode, st->st_rdev, s)) {
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			return;
XX! 		}
XX! 	}
XX! #ifdef S_IFLNK
XX! 	else if (S_ISLNK(st->st_mode)) {
XX! 		static char linkname[PATH_MAX + 1];
XX! 		int len;
XX! 
XX! 		len = readlink(src_path, linkname, sizeof(linkname) - 1);
XX! 		if (len < 0) {
XX! 			perror(src_path);
XX! 			errors = 1;
XX! 			return;
XX! 		}
XX! 		linkname[len] = 0;
XX! 		if (vflag) doing("symlink ", linkname, dst_path);
XX! 		if (symlink(linkname, dst_path)) {
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			return;
XX! 		}
XX! 	}
XX! #endif
XX! 	if (pflag) similar(st);
XX! 	return;
XX!   }
XX!   while ((fd = open(src_path, O_RDONLY)) < 0) {
XX! 	if (errno != EMFILE && errno != ENFILE) {
XX! 		perror(src_path);
XX! 		errors = 1;
XX! 		return;
XX! 	}
XX! 	do_close();
XX!   }
XX! 
XX!   if (vflag) doing("cp ", src_path, dst_path);
XX!   if (new) {
XX! 	while ((fd2 = open(dst_path, O_WRONLY | O_CREAT,
XX! 			   st->st_mode & ALL_MODES)) < 0)
XX! 		if (errno == EMFILE || errno == ENFILE)
XX! 			do_close();
XX! 		else
XX! 			break;
XX!   } else {
XX! 	while ((fd2 = open(dst_path, O_WRONLY | O_TRUNC)) < 0)
XX! 		if (errno == EMFILE || errno == ENFILE)
XX! 			do_close();
XX! 		else
XX! 			break;
XX!   }
XX!   if (fd2 < 0) {
XX! 	perror(dst_path);
XX! 	close(fd);
XX! 	errors = 1;
XX! 	return;
XX!   }
XX!   while ((n = read(fd, buffer, sizeof(buffer))) != 0) {
XX  	if (n < 0) {
XX! 		perror(src_path);
XX! 		errors = 1;
XX  		break;
XX  	}
XX! 	bufp = buffer;
XX! 	while (n) {
XX! 		m = write(fd2, bufp, n);
XX! 		if (!m) {
XX! 			m = -1;
XX! 			errno = 0;
XX  		}
XX! 		if (m < 0) {
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			n = -1;
XX! 			break;
XX! 		}
XX! 		n -= m;
XX! 		bufp += m;
XX  	}
XX! 	if (n < 0) break;
XX!   }
XX! 
XX!   close(fd);
XX    close(fd2);
XX+   if (new && pflag) similar(st);
XX  }
XX  
XX! 
XX! /* Copying a directory's contents is done here. If necessary, the
XX!  * directory will be created, but protected by 'a=,u=rwx' mode until the
XX!  * entire copy is done (or failed, somehow). The mode is the reverted to
XX!  * the "correct" creation mode at the end of the directory copy.
XX!  */
XX! void do_cpdir(new, oldmode, dotdot)
XX! int new;
XX! struct stat *oldmode;
XX! TREE *dotdot;
XX  {
XX!   TREE d;
XX!   char *src, *dst;
XX!   mode_t oldmask;
XX!   int new2;
XX!   struct dirent *entp;
XX  
XX!   if (vflag) doing("cpdir ", src_path, dst_path);
XX!   if (new) {
XX! 	oldmask = umask(0);
XX! 	if (vflag) doing("mkdir ", dst_path, NONE);
XX! 	if (mkdir(dst_path, S_IRWXU)) {
XX! 		perror(dst_path);
XX! 		umask(oldmask);
XX! 		errors = 1;
XX! 		return;
XX! 	}
XX! 	umask(oldmask);
XX!   }
XX!   while ((d.dirp = opendir(src_path)) == (DIR *) 0)
XX! 	if (errno == EMFILE || errno == ENFILE || errno == ENOMEM)
XX! 		do_close();
XX! 	else {
XX! 		perror(src_path);
XX! 		if (new) {
XX! 			if (pflag)
XX! 				similar(oldmode);
XX! 			else
XX! 				chmod(dst_path, oldmode->st_mode & ALL_MODES & ~oldmask);
XX! 		}
XX! 		errors = 1;
XX! 		return;
XX! 	}
XX  
XX!   src = src_path + strlen(src_path);
XX!   dst = dst_path + strlen(dst_path);
XX!   *src++ = '/';
XX!   *dst++ = '/';
XX  
XX!   if (dotdot)
XX! 	dotdot->next = &d;
XX!   else
XX! 	toplevel = &d;
XX! 
XX!   d.pos = 0;
XX! 
XX!   for (;;) {
XX! 	if (d.dirp == (DIR *) 0) {
XX! 		dst[-1] = '\0';
XX! 		if ((d.dirp = opendir(dst_path)) == (DIR *) 0) {
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			break;
XX! 		}
XX! 		dst[0] = '/';
XX! 		seekdir(d.dirp, d.pos);
XX! 		if ((entp = readdir(d.dirp)) && entp->d_off == d.pos)
XX! 			entp = readdir(d.dirp);	/* Already processed! */
XX! 	} else
XX! 		entp = readdir(d.dirp);
XX! 
XX! 	if (entp == (struct dirent *) 0) break;
XX! 
XX! 	if (entp->d_name[0] != '.' ||
XX! 	    (entp->d_name[1] &&
XX! 	     (entp->d_name[1] != '.' || entp->d_name[2]))) {
XX! 		strcpy(src, entp->d_name);
XX! 		strcpy(dst, entp->d_name);
XX! 		if (
XX! #ifdef S_IFLNK
XX! 		    cflag && lstat(src_path, &d.st) ||
XX! 		    !cflag && stat(src_path, &d.st)
XX! #else
XX! 		    stat(src_path, &d.st)
XX! #endif
XX! 		   ) {
XX! 			perror(src);
XX! 			errors = 1;
XX! 			continue;
XX! 		}
XX! 		d.pos = entp->d_off;
XX! 
XX! 		if ((new2 = stat(dst_path, &st2)) != 0) {
XX! 			if (S_ISDIR(d.st.st_mode)) {
XX! 				do_cpdir(new2, &d.st, &d);
XX! 				continue;
XX! 			}
XX! 		} else if (S_ISDIR(d.st.st_mode)) {
XX! 			if (S_ISDIR(st2.st_mode)) {
XX! 				do_cpdir(new2, &d.st, &d);
XX! 				continue;
XX! 			}
XX! 			errno = EISDIR;
XX! 			perror(dst_path);
XX! 			errors = 1;
XX! 			continue;
XX! 		}
XX! 		do_cpfile(new2, &d.st);
XX! 	}
XX    }
XX  
XX!   closedir(d.dirp);
XX!   *--src = '\0';
XX!   *--dst = '\0';
XX!   if (dotdot)
XX! 	dotdot->next = (TREE *) 0;
XX!   else
XX! 	toplevel = (TREE *) 0;
XX! 
XX!   if (new) {
XX! 	if (pflag)
XX! 		similar(oldmode);
XX! 	else
XX! 		chmod(dst_path, oldmode->st_mode & ALL_MODES & ~oldmask);
XX    }
XX  }
XX  
XX  
XX! /* This is called to copy each of the ARGUMENTS (specified in cp) to its
XX!  * destination, either the 2nd argument to cp, or somewhere in the
XX!  * specified directory.
XX!  */
XX! int do_cp(source)
XX! char *source;
XX  {
XX!   struct stat st, st2;
XX!   char *s;
XX!   int newfile;
XX! 
XX!   if (stat(source, &st)) {
XX! 	perror(source);
XX! 	return(1);
XX!   }
XX!   strcpy(dst_path, dest);
XX!   if (dflag) {
XX! 	if ((s = strrchr(source, '/')) != NULL)
XX! 		strcat(dst_path, s);
XX! 	else {
XX! 		strcat(dst_path, "/");
XX! 		strcat(dst_path, source);
XX! 	}
XX!   }
XX!   if (!(newfile = stat(dst_path, &st2)))
XX! 	if (st.st_dev == st2.st_dev && st.st_ino == st2.st_ino) {
XX! 		std_err(source);
XX! 		std_err(",");
XX! 		std_err(dst_path);
XX! 		std_err(": Same file\n");
XX! 		return(1);
XX! 	}
XX!   strcpy(src_path, source);
XX!   if (S_ISDIR(st.st_mode)) {
XX! 	if (!rflag) {
XX! 		errno = EISDIR;
XX! 		perror(source);
XX! 		return(1);
XX! 	}
XX! 	if (!newfile && !S_ISDIR(st2.st_mode)) {
XX! 		errno = ENOTDIR;
XX! 		perror(dst_path);
XX! 		return(1);
XX! 	}
XX! 	do_cpdir(newfile, &st, (TREE *) 0);
XX! 	return(0);
XX!   }
XX!   do_cpfile(newfile, &st);
XX!   return(0);
XX  }
XX  
XX  
XX! /* Posix prototype of the command */
XX! void usage()
XX  {
XX!   std_err(cflag ? "Usage: cpdir [-fipv] source_dir target_dir\n"
XX! 	: "Usage: cp [-R|-r] [-fip] source_file... target\n");
XX!   exit(1);
XX  }
X/
Xecho x - crc.c.d
Xsed '/^X/s///' > crc.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/crc.c  crc=50933   3844	Sun Apr 25 21:34:51 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/crc.c  crc=49286   4016	Wed Nov  4 04:19:08 1992
XX***************
XX*** 1,10 ****
XX  /* Compute checksum			Author: Johan W. Stevenson */
XX  
XX  #include <stdio.h>
XX  
XX  int errs;
XX  
XX! main(argc, argv)
XX  char **argv;
XX  {
XX    char line[256];
XX--- 1,18 ----
XX  /* Compute checksum			Author: Johan W. Stevenson */
XX  
XX+ /* Copyright 1988 by Johan W. Stevenson */
XX+ 
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  int errs;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void crc, (char *fname));
XX! 
XX! int main(argc, argv)
XX! int argc;
XX  char **argv;
XX  {
XX    char line[256];
XX***************
XX*** 23,29 ****
XX  		argv++;
XX  		argc--;
XX  	} while (argc > 1);
XX!   exit(errs != 0);
XX  }
XX  
XX  /* Crctab calculated by Mark G. Mendel, Network Systems Corporation */
XX--- 31,37 ----
XX  		argv++;
XX  		argc--;
XX  	} while (argc > 1);
XX!   return(errs != 0);
XX  }
XX  
XX  /* Crctab calculated by Mark G. Mendel, Network Systems Corporation */
XX***************
XX*** 75,85 ****
XX  
XX  #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
XX  
XX! crc(fname)
XX  char *fname;
XX  {
XX    register int c;
XX-   register int i;
XX    register long len = 0;
XX    register unsigned short crc = 0;
XX    register FILE *fp;
XX--- 83,92 ----
XX  
XX  #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
XX  
XX! void crc(fname)
XX  char *fname;
XX  {
XX    register int c;
XX    register long len = 0;
XX    register unsigned short crc = 0;
XX    register FILE *fp;
X/
Xecho x - cron.c.d
Xsed '/^X/s///' > cron.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cron.c  crc=12322   7203	Sun Apr 25 21:34:51 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cron.c  crc=65530   8519	Sun Jan 10 14:26:16 1993
XX***************
XX*** 1,183 ****
XX! /* Cron - clock daemon			Author: S.R. Sampson */
XX  
XX! /*	Cron is the clock daemon.  It is typically started up from the
XX!  *	/etc/rc file by the line:
XX!  *		/usr/bin/cron
XX!  *	Cron automatically puts itself in the background, so no & is needed.
XX!  *	If cron is used, it runs all day, spending most of its time asleep.
XX!  *	Once a minute it wakes up and examines /usr/lib/crontab to see if there
XX!  *	are any commands to be executed.  The format of this table is the same
XX!  *	as in UNIX, except that % is not allowed to indicate 'new line.'
XX   *
XX!  *	Each crontab entry has six fields:
XX!  *	   minute    hour  day-of-the-month  month  day-of-the-week  command
XX!  *	Each entry is checked in turn, and any entry matching the current time
XX!  *	is executed.  The entry * matches anything.  Some examples:
XX   *
XX!  *   min hr dat mo day   command
XX!  *    *  *   *  *   *    /usr/bin/date >/dev/tty0   #print date every minute
XX!  *    0  *   *  *   *    /usr/bin/date >/dev/tty0   #print date on the hour
XX!  *   30  4   *  *  1-5   /bin/backup /dev/fd1       #do backup Mon-Fri at 0430
XX!  *   30 19   *  *  1,3,5 /etc/backup /dev/fd1       #Mon, Wed, Fri at 1930
XX!  *    0  9  25 12   *    /usr/bin/sing >/dev/tty0   #Xmas morning at 0900 only
XX   *
XX!  * Version 1.6  SrT  90/04/08
XX!  *      Added casting fixes by Ralf Wenk, and integrated net
XX!  *      changes that release current directory, and use the
XX!  *      1.5.5 include files.  Altered assign, so no temporary
XX!  *	buffer is needed.
XX   *
XX!  * Version 1.5  SrT  89/04/10
XX!  *	Changed sleep code, to type SRS sent me.
XX   *
XX!  * Version 1.4  SrT  89/03/17
XX!  *	Fixed a pointer problem, when reloading crontab.
XX   *
XX!  * Version 1.3  SrT  89/03/16
XX!  *	Loads crontab, into memory and only rereads the disk
XX!  *	version if it changes.  (Free up those clock cycles!)
XX   *
XX!  * Fixed 03/10/89, by Simmule Turner, simmy@nu.cs.fsu.edu
XX!  *	Now correctly cleans up zombie processes
XX!  *	Logs actions to /usr/adm/cronlog
XX!  *	Syncs with clock after each minute
XX!  *	Comments allowed in crontab
XX!  *	Fixed bug that prevented month, from matching
XX! */
XX! 
XX! 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <signal.h>
XX! #include <time.h>
XX  #include <string.h>
XX! #include <fcntl.h>
XX  #include <stdio.h>
XX  
XX! #ifndef DEBUG
XX! #define CRONTAB "/usr/lib/crontab"
XX! #define LOGFILE "/usr/adm/cronlog"
XX! #else
XX! #define LOGFILE "/usr/adm/cronlog.dbg"
XX! #define CRONTAB "/usr/adm/crontab.dbg"
XX! #endif
XX  
XX! #define NULLDEV "/dev/null"
XX! #define SEPARATOR " \t"
XX! #define CRONSIZE  2048
XX! #define CRONSTRUCT struct cron_entry
XX  
XX! #define	TRUE	1
XX! #define	FALSE	0
XX  
XX- struct cron_entry {
XX-   char *mn;
XX-   char *hr;
XX-   char *day;
XX-   char *mon;
XX-   char *wkd;
XX-   char *cmd;
XX-   struct cron_entry *next;
XX- } *head, *entry_ptr;
XX  
XX! char crontab[CRONSIZE];
XX! FILE *cronlog;
XX  
XX- int wakeup(), ret();
XX  
XX! time_t previous_time = 0L;
XX  
XX! main()
XX  {
XX!   int status;
XX!   time_t clock;
XX  
XX!   status = fork();
XX!   if (status == -1) {
XX! 	fprintf(stderr, "Can't fork cron\n");
XX! 	exit(1);
XX    }
XX  
XX-   if (status > 0) exit(0);
XX  
XX!   signal(SIGINT, SIG_IGN);
XX!   signal(SIGHUP, SIG_IGN);
XX!   signal(SIGQUIT, SIG_IGN);
XX  
XX-   close(0);
XX-   close(1);
XX-   close(2);
XX  
XX!   chdir("/");
XX  
XX!   open(NULLDEV, O_RDONLY);
XX!   if ((cronlog = fopen(LOGFILE, "a")) == (FILE *) NULL) {
XX! 	open(NULLDEV, O_WRONLY);
XX! 	open(NULLDEV, O_WRONLY);
XX!   } else {
XX! 	setbuf(cronlog, (char *) NULL);
XX! 	dup(fileno(cronlog));
XX    }
XX  
XX!   entry_ptr = (CRONSTRUCT *) malloc(sizeof(CRONSTRUCT));
XX!   entry_ptr->next = (CRONSTRUCT *) NULL;
XX!   head = entry_ptr;
XX  
XX!   while (TRUE) {
XX! 	signal(SIGALRM, wakeup);
XX! 	time(&clock);
XX! 	alarm((unsigned) (60 - clock % 60));
XX! 	pause();
XX! 
XX! 	signal(SIGALRM, ret);
XX! 	alarm(1);
XX! 	while (wait((int *) NULL) != (-1));
XX    }
XX! }
XX  
XX! int ret() {}
XX  
XX! wakeup()
XX! {
XX!   register struct tm *tm;
XX!   time_t cur_time;
XX!   CRONSTRUCT *this_entry = head;
XX  
XX!   load_crontab();
XX! 
XX!   time(&cur_time);
XX!   tm = localtime(&cur_time);
XX! 
XX!   while (this_entry->next && this_entry->mn) {
XX! 	if (match(this_entry->mn, tm->tm_min) &&
XX! 	    match(this_entry->hr, tm->tm_hour) &&
XX! 	    match(this_entry->day, tm->tm_mday) &&
XX! 	    match(this_entry->mon, tm->tm_mon + 1) &&
XX! 	    match(this_entry->wkd, tm->tm_wday)) {
XX! 		fprintf(cronlog, "%02d/%02d-%02d:%02d  %s\n",
XX! 			tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
XX! 			tm->tm_min, this_entry->cmd);
XX! 		if (fork() == 0) {
XX! 			execl("/bin/sh", "/bin/sh", "-c",
XX! 	                      this_entry->cmd, (char *) 0);
XX! 			exit(1);
XX! 		}
XX  	}
XX! 	this_entry = this_entry->next;
XX    }
XX  }
XX  
XX  /*
XX!  *	This routine will match the left string with the right number.
XX   *
XX!  *	The string can contain the following syntax *
XX!  *	*		This will return TRUE for any number
XX!  *	x,y [,z, ...]	This will return TRUE for any number given.
XX!  *	x-y		This will return TRUE for any number within
XX   *			the range of x thru y.
XX   */
XX! 
XX! match(left, right)
XX  register char *left;
XX  register int right;
XX  {
XX--- 1,182 ----
XX! /* Cron - clock daemon.			Author: S.R. Sampson */
XX  
XX! /*
XX!  * cron		clock daemon.
XX!  *		Cron is the clock daemon.  It is typically started up from
XX!  *		the system initialization file (/etc/rc or /etc/inittab) by
XX!  *		the INIT program.
XX   *
XX!  *		If started by hand it must be done by the superuser.
XX   *
XX!  *		Since it is a true daemon, cron automatically puts itself in
XX!  *		the background, to release its control terminal.  If cron is
XX!  *		used, it runs all day, spending most of its time asleep.
XX!  *		Once a minute it wakes up and forks off a child which then
XX!  *		examines /usr/lib/crontab to see if there are any commands to
XX!  *		be executed. The format of this table is the same as in UNIX,
XX!  *		except that % is not allowed to indicate 'new line'.
XX   *
XX!  * Usage:	/usr/bin/cron
XX   *
XX!  * Datafile:	/usr/lib/crontab
XX!  *		Each crontab entry has six fields:
XX   *
XX!  *		 minute hour day-of-month month day-of-week command
XX   *
XX!  *		Each entry is checked in turn, and any entry matching the
XX!  *		current time is executed.  The entry * matches anything.
XX   *
XX!  * Version:	1.9	03/02/91
XX!  *
XX!  * Authors:	Steven R. Sampson, Fred van Kempen, Simmule Turner,
XX!  *		Peter de Vrijer
XX!  */
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <fcntl.h>
XX+ #include <limits.h>
XX  #include <signal.h>
XX! #include <stdarg.h>
XX! #include <stdlib.h>
XX  #include <string.h>
XX! #include <time.h>
XX! #include <unistd.h>
XX! #include <sys/wait.h>
XX  #include <stdio.h>
XX  
XX! #define CRONTAB		"/usr/lib/crontab"
XX! #define LOGFILE		"/usr/adm/cronlog"
XX  
XX! #define SEPARATOR	" \t"
XX! #define CRONSIZE	2048
XX  
XX! typedef struct cron_entry {
XX!   struct cron_entry	*next;
XX!   char			*mn;
XX!   char			*hr;
XX!   char			*day;
XX!   char			*mon;
XX!   char			*wkd;
XX!   char			*cmd;
XX! } CRON;
XX  
XX  
XX! static char *Version = "@(#) cron 1.9 (03/02/91)";
XX  
XX  
XX! static char crontab[CRONSIZE];		/* memory for the entries	*/
XX! static CRON *head, *entry_ptr;		/* crontab entry pointers	*/
XX! static time_t prv_time = (time_t) 0;	/* timekeeper: previous wakeup	*/
XX! static FILE *log, *logf;		/* FILE pointer to logfile	*/
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void log_error, (char *error, ...));
XX! _PROTOTYPE(void assign, (CRON *entry, char *line));
XX! _PROTOTYPE(void load_crontab, (void));
XX! _PROTOTYPE(int match, (char *left, int right));
XX! _PROTOTYPE(void wakeup, (void));
XX! 
XX! /* Write a record to the log file. */
XX! #ifdef __STDC__
XX! void log_error(char *error, ...)
XX  {
XX!   va_list args;
XX  
XX!   va_start (args, error);
XX!   if ((logf = fopen(LOGFILE, "a")) != NULL) {
XX! 	vfprintf(logf, error, args);
XX! 	fclose(logf);
XX    }
XX+   va_end(args);
XX+ }
XX+ #else
XX+ /* the K&R lib does not have vfprintf */
XX+ void log_error(error)
XX+ char *error;
XX+ {
XX+   if ((logf = fopen(LOGFILE, "a")) != NULL) {
XX+ 	fprintf(logf, error);
XX+ 	fclose(logf);
XX+   }
XX+ }
XX+ #endif
XX  
XX  
XX! /* Assign the field values to the current crontab entry in core. */
XX! void assign(entry, line)
XX! CRON *entry;
XX! char *line;
XX! {
XX!   entry->mn	= strtok(line, SEPARATOR);
XX!   entry->hr	= strtok( (char *)NULL, SEPARATOR);
XX!   entry->day	= strtok( (char *)NULL, SEPARATOR);
XX!   entry->mon	= strtok( (char *)NULL, SEPARATOR);
XX!   entry->wkd	= strtok( (char *)NULL, SEPARATOR);
XX!   entry->cmd	= strchr(entry->wkd, '\0') + 1;
XX! }
XX  
XX  
XX! /* Read the on-disk crontab file into core. */
XX! void load_crontab()
XX! {
XX!   int len, pos;
XX!   FILE *cfp;
XX!   struct stat buf;
XX  
XX!   if (stat(CRONTAB, &buf)) {
XX! 	if (prv_time == (time_t) 0) fprintf(log, "Can't stat crontab\n");
XX! 	prv_time = (time_t) 0;
XX! 	return;
XX    }
XX  
XX!   if (buf.st_mtime <= prv_time) return;
XX  
XX!   if ((cfp = fopen(CRONTAB, "r")) == NULL) {
XX! 	if (prv_time == (time_t) 0) fprintf(log, "Can't open crontab\n");
XX! 	prv_time = (time_t) 0;
XX! 	return;
XX    }
XX!   prv_time = buf.st_mtime;
XX!   len = pos = 0;
XX!   entry_ptr = head;
XX  
XX!   while (fgets(&crontab[pos], CRONSIZE - pos, cfp) != NULL) {
XX! 	if (crontab[pos] == '#' || crontab[pos] == '\n') continue;
XX! 	len = strlen(&crontab[pos]);
XX! 	if (crontab[pos + len - 1] == '\n') {
XX! 		len--;
XX! 		crontab[pos + len] = '\0';
XX! 	}
XX  
XX! 	assign(entry_ptr, &crontab[pos]);
XX  
XX! 	if (entry_ptr->next == NULL) {
XX! 		entry_ptr->next = (CRON *)malloc(sizeof(CRON));
XX! 		entry_ptr->next->next = NULL;
XX  	}
XX! 	entry_ptr = entry_ptr->next;
XX! 	pos += ++len;
XX! 	if (pos >= CRONSIZE) break;
XX    }
XX+   (void) fclose(cfp);
XX+ 
XX+   while (entry_ptr) {
XX+ 	entry_ptr->mn = NULL;
XX+ 	entry_ptr = entry_ptr->next;
XX+   }
XX  }
XX  
XX+ 
XX  /*
XX!  * This routine will match the left string with the right number.
XX   *
XX!  * The string can contain the following syntax *
XX!  *	*		This will return 1 for any number
XX!  *	x,y [,z, ...]	This will return 1 for any number given.
XX!  *	x-y		This will return 1 for any number within
XX   *			the range of x thru y.
XX   */
XX! int match(left, right)
XX  register char *left;
XX  register int right;
XX  {
XX***************
XX*** 185,305 ****
XX    register char c;
XX  
XX    n = 0;
XX!   if (!strcmp(left, "*")) return(TRUE);
XX  
XX    while ((c = *left++) && (c >= '0') && (c <= '9')) n = (n * 10) + c - '0';
XX  
XX    switch (c) {
XX!       case '\0':
XX! 	return(right == n);
XX  
XX!       case ',':
XX! 	if (right == n) return(TRUE);
XX! 	do {
XX  		n = 0;
XX  		while ((c = *left++) && (c >= '0') && (c <= '9'))
XX  			n = (n * 10) + c - '0';
XX  
XX- 		if (right == n) return(TRUE);
XX- 	} while (c == ',');
XX- 	return(FALSE);
XX  
XX!       case '-':
XX! 	if (right < n) return(FALSE);
XX  
XX! 	n = 0;
XX! 	while ((c = *left++) && (c >= '0') && (c <= '9'))
XX! 		n = (n * 10) + c - '0';
XX  
XX! 	return(right <= n);
XX    }
XX  }
XX  
XX! load_crontab()
XX  {
XX!   int pos = 0;
XX!   FILE *cfp;
XX!   struct stat buf;
XX  
XX!   if (stat(CRONTAB, &buf)) {
XX! 	if (previous_time == 0L) printf("Can't stat crontab\n");
XX! 	previous_time = 0L;
XX! 	return;
XX!   }
XX! #ifdef DEBUG
XX!   printf("Crontab Time:%ld In_Core:%ld\n", buf.st_mtime, previous_time);
XX! #endif
XX  
XX!   if (buf.st_mtime <= previous_time) return;
XX  
XX!   if ((cfp = fopen(CRONTAB, "r")) == (FILE *) NULL) {
XX! 	if (previous_time == 0L) printf("Can't open crontab\n");
XX! 	previous_time = 0L;
XX! 	return;
XX!   }
XX!   previous_time = buf.st_mtime;
XX  
XX!   entry_ptr = head;
XX!   while (fgets(&crontab[pos], CRONSIZE - pos, cfp) != (char *) NULL) {
XX! 	int len;
XX  
XX! 	if (crontab[pos] == '#') continue;
XX! 	len = strlen(&crontab[pos]);
XX! 	if (crontab[pos + len - 1] == '\n') {
XX! 		len--;
XX! 		crontab[pos + len] = '\0';
XX! 	}
XX! 	assign(entry_ptr, &crontab[pos]);
XX! 	if (entry_ptr->next == (CRONSTRUCT *) NULL) {
XX! 		entry_ptr->next = (CRONSTRUCT *) malloc(sizeof(CRONSTRUCT));
XX! 		entry_ptr->next->next = (CRONSTRUCT *) NULL;
XX! 	}
XX! 	entry_ptr = entry_ptr->next;
XX! 	pos += ++len;
XX! 	if (pos >= CRONSIZE) break;
XX    }
XX-   fclose(cfp);
XX  
XX!   while (entry_ptr) {
XX! 	entry_ptr->mn = (char *) NULL;
XX! 	entry_ptr = entry_ptr->next;
XX!   }
XX  
XX! #ifdef DEBUG
XX!   printf("Crontab uses %d/%d bytes\n", pos, CRONSIZE);
XX!   {
XX! 	CRONSTRUCT *start = head;
XX! 	dumptable(start);
XX!   }
XX! #endif
XX! }
XX  
XX! assign(entry, line)
XX! CRONSTRUCT *entry;
XX! char *line;
XX! {
XX!   entry->mn = strtok(line, SEPARATOR);
XX!   entry->hr = strtok((char *) NULL, SEPARATOR);
XX!   entry->day = strtok((char *) NULL, SEPARATOR);
XX!   entry->mon = strtok((char *) NULL, SEPARATOR);
XX!   entry->wkd = strtok((char *) NULL, SEPARATOR);
XX!   entry->cmd = strchr(entry->wkd,'\0') + 1;
XX! }
XX  
XX! #ifdef DEBUG
XX! dumptable(table)
XX! CRONSTRUCT *table;
XX! {
XX!   time_t clock;
XX!   time(&clock);
XX  
XX!   printf("\nContents of crontab at: %s", ctime(&clock));
XX!   printf("Minute\tHour\tDay\tMonth\tWeekday\tCommand\n");
XX!   while (table->next && table->mn) {
XX! 	printf("%s\t%s\t%s\t%s\t%s\t%s\n",
XX! 	       table->mn, table->hr, table->day, table->mon,
XX! 	       table->wkd, table->cmd);
XX! 	table = table->next;
XX    }
XX  }
XX- #endif
XX--- 184,356 ----
XX    register char c;
XX  
XX    n = 0;
XX!   if (!strcmp(left, "*")) return(1);
XX  
XX    while ((c = *left++) && (c >= '0') && (c <= '9')) n = (n * 10) + c - '0';
XX  
XX    switch (c) {
XX! 	case '\0':
XX! 		return(right == n);
XX! 		/*NOTREACHED*/
XX! 		break;
XX! 	case ',':
XX! 		if (right == n) return(1);
XX! 		do {
XX! 			n = 0;
XX! 			while ((c = *left++) && (c >= '0') && (c <= '9'))
XX! 				n = (n * 10) + c - '0';
XX  
XX! 			if (right == n) return(1);
XX! 		} while (c == ',');
XX! 		return(0);
XX! 		/*NOTREACHED*/
XX! 		break;
XX! 	case '-':
XX! 		if (right < n) return(0);
XX  		n = 0;
XX  		while ((c = *left++) && (c >= '0') && (c <= '9'))
XX  			n = (n * 10) + c - '0';
XX+ 		return(right <= n);
XX+ 		/*NOTREACHED*/
XX+ 		break;
XX+ 	default:
XX+ 		break;
XX+   }
XX+   return(0);
XX+ }
XX  
XX  
XX! /* Wakeup from the sleep(), and check for any work. */
XX! void wakeup()
XX! {
XX!   register struct tm *tm;
XX!   time_t cur_time;
XX!   CRON *this_entry;
XX!   int st, pid;
XX  
XX!   this_entry = head;
XX!   load_crontab();
XX  
XX!   time(&cur_time);
XX!   tm = localtime(&cur_time);
XX! 
XX!   while (this_entry->next && this_entry->mn) {
XX! 	if (match(this_entry->mn, tm->tm_min) &&
XX! 	    match(this_entry->hr, tm->tm_hour) &&
XX! 	    match(this_entry->day, tm->tm_mday) &&
XX! 	    match(this_entry->mon, tm->tm_mon + 1) &&
XX! 	    match(this_entry->wkd, tm->tm_wday)) {
XX! 		fprintf(log, "%02d/%02d-%02d:%02d  %s\n",
XX! 			tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
XX! 							this_entry->cmd);
XX! 		if ((pid = fork()) == 0) {
XX! 			st = execl("/bin/sh", "/bin/sh", "-c",
XX! 						this_entry->cmd, (char *)NULL);
XX! 			log_error("EXEC failed with status = %d\n", st);
XX! 		} else {
XX! 			if (pid < 0)
XX! 				log_error("cron grandchild: Fork failed!\n\n");
XX! 		}
XX! 	}
XX! 	this_entry = this_entry->next;
XX    }
XX  }
XX  
XX! 
XX! int main(argc, argv)
XX! int argc;
XX! char *argv[];
XX  {
XX!   register struct tm *tm;
XX!   int status, i, pid;
XX!   time_t clk;
XX  
XX!   (void) chdir("/usr/adm");
XX  
XX!   if ((status = fork()) < 0) {
XX! 	fprintf(stderr, "cron: cannot fork!\n");
XX! 	exit(1);
XX!   } else if (status > 0) exit(0);
XX  
XX!   /* We are now the child. Ignore ALL signals. */
XX!   for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN);
XX  
XX!   /* Attempt to free all open file descriptors (we mostly don't have any
XX!    * files open, and reopen CRONTAB and LOGFILE as necessary).
XX!    */
XX!   for (i = 0; i < OPEN_MAX; i++) close(i);
XX  
XX!   /* Create a logfile, appending to the previous one. */
XX!   if ((log = fopen(LOGFILE, "a")) != NULL) {
XX! 	time(&clk);
XX! 	tm = localtime(&clk);  
XX! 	fprintf(log, "cron started at: %02d/%02d-%02d:%02d\n",
XX!  		tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
XX! 	fclose(log);
XX    }
XX  
XX!   entry_ptr = (CRON *)malloc(sizeof(CRON));
XX!   entry_ptr->next = NULL;
XX!   head = entry_ptr;
XX  
XX!   /* The endless loop. */
XX!   while (1) {
XX! 	/* Sleep till the next full minute */
XX! 	(void) time(&clk);
XX! 	sleep((unsigned) (60 - clk % 60));
XX  
XX! 	/*
XX! 	 * Now fork twice. The grandchild will run wakeup() .
XX! 	 * In that way cron will never have to wait longer than 
XX! 	 * a few seconds
XX! 	 */
XX! 	if ((pid = fork()) == 0) {
XX! 		/*
XX! 		 * This is the child, lets set the process group and
XX! 		 * fork again.  This is the way it should be done in
XX! 		 * a true daemon.
XX! 		 */
XX! 		/* setpgrp();*/ /* make this line a comment if not available */
XX  
XX! 		if ((pid = fork()) == 0) {
XX! 			/*
XX! 			 * This is the grandchild, it has to do all the
XX! 			 * work.  Set up standard file descriptors.  No
XX! 			 * files are open at this point, so their numbers
XX! 			 * will be 0, 1 and 2 as required.  Open the logfile
XX! 			 * if present, otherwise create it.
XX! 			 */
XX! 			(void) open("/dev/null", O_RDWR);
XX! 			if ((log = fopen(LOGFILE, "a")) != NULL) {
XX! 				setbuf(log, (char *)NULL);
XX! 				(void) dup(fileno(log));
XX! 			} else {
XX! 				(void) dup(0);
XX! 				(void) dup(0);
XX! 			}
XX  
XX! 			wakeup();
XX! 
XX! 			/* The grandchild has to do an exit() also. */
XX! 			exit(0);
XX! 		} else {
XX! 			/*
XX! 			 * Here we are still the child, check if everything
XX! 			 * is ok. In any case we do an exit.
XX! 			 */
XX! 			if (pid < 0) {
XX! 			    log_error("cron: fork of grandchild failed\n");
XX! 			}
XX! 			exit(0);
XX! 		}
XX! 	} else {
XX! 		/* This is the parent. */
XX! 		if (pid < 0) {
XX! 			log_error("cron: fork of child failed.\n");
XX! 		} else {
XX! 			/* Wait for the child to change process group. */
XX! 			while (wait( (int *)NULL ) != pid);
XX! 		}
XX! 	}
XX    }
XX  }
X/
Xecho x - cut.c.d
Xsed '/^X/s///' > cut.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/cut.c  crc=06673   4125	Sun Apr 25 21:34:52 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/cut.c  crc=63369   7671	Wed Nov  4 04:19:08 1992
XX***************
XX*** 11,59 ****
XX   *          JANET sq79@uk.ac.liv
XX   *          ARPA  sq79%liv.ac.uk@nsfnet-relay.ac.uk
XX   *          UUCP  ...!mcvax!ukc!liv.ac.uk!sq79
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <ctype.h>
XX  #include <string.h>
XX  #include <errno.h>
XX  #include <stdio.h>
XX  
XX  #define MAX_FIELD	80	/* Pointers to the beginning of each field
XX  			 * are stored in columns[], if a line holds
XX  			 * more than MAX_FIELD columns the array
XX  			 * boundary is exceed. But unlikely at 80 */
XX- char *columns[MAX_FIELD];
XX  
XX  #define MAX_ARGS	32	/* Maximum number of fields following -f or
XX! 			 * -c switches			  	  */
XX  int args[MAX_ARGS * 2];
XX  int num_args;
XX  
XX  int mode;			/* 0 = dump stdin to stdout, 1=-f, 2=-c   */
XX! int flagi;			/* 1=-i, 0=no -i 		  */
XX  char delim = '\t';		/* default delimiting character	  */
XX  FILE *fd;
XX  char *name;
XX  char line[BUFSIZ];
XX! extern int errno;
XX  
XX  void cuterror(err)
XX  int err;
XX  {
XX    static char *err_mes[] = {
XX  			  "%s: syntax error\n",
XX  			  "%s: position must be >0\n",
XX! 			  "%s: unknown option\n",
XX! 			  "%s: usage: cut [-f{args} [-i] [-d'x']]|[-c{args}] [filename [...]]\n",
XX  			  "%s: line longer than BUFSIZ\n",
XX- 			  "%s: -d option not applicable\n",
XX- 			  "%s: -i option not applicable\n",
XX  		 "%s: range must not decrease from left to right\n",
XX  			  "%s: MAX_FIELD exceeded\n",
XX  			  "%s: MAX_ARGS exceeded\n"
XX    };
XX!   printf(err_mes[err - 1], name);
XX    exit(err);
XX  }
XX  
XX--- 11,113 ----
XX   *          JANET sq79@uk.ac.liv
XX   *          ARPA  sq79%liv.ac.uk@nsfnet-relay.ac.uk
XX   *          UUCP  ...!mcvax!ukc!liv.ac.uk!sq79
XX+  *-------------------------------------------------------------------------
XX+  *	Changed for POSIX1003.2/Draft10 conformance
XX+  *	Thomas Brupbacher (tobr@mw.lpc.ethz.ch), September 1990.
XX+  *	Changes:
XX+  *	    - separation of error messages ( stderr) and output (stdout).
XX+  *	    - support for -b and -n (no effect, -b acts as -c)
XX+  *	    - support for -s
XX+  *-------------------------------------------------------------------------
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <ctype.h>
XX  #include <string.h>
XX  #include <errno.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define MAX_FIELD	80	/* Pointers to the beginning of each field
XX  			 * are stored in columns[], if a line holds
XX  			 * more than MAX_FIELD columns the array
XX  			 * boundary is exceed. But unlikely at 80 */
XX  
XX  #define MAX_ARGS	32	/* Maximum number of fields following -f or
XX! 			 * -c switches												  	  */
XX  int args[MAX_ARGS * 2];
XX  int num_args;
XX  
XX+ /* Lots of new defines, should easen maintainance...			*/
XX+ #define DUMP_STDIN	0	/* define for mode: no options	 */
XX+ #define OPTIONF		1	/* define for mode: option -f 	 */
XX+ #define OPTIONC		2	/* define for mode: option -c	 */
XX+ #define OPTIONB		3	/* define for mode: option -b	 */
XX+ #define NOTSET		0	/* option not selected		 */
XX+ #define SET		1	/* option selected		 */
XX+ 
XX+ /* Defines for the warnings						*/
XX+ #define DELIMITER_NOT_APPLICABLE	0
XX+ #define OVERRIDING_PREVIOUS_MODE	1
XX+ #define OPTION_NOT_APPLICABLE		2
XX+ #define UNKNOWN_OPTION			3
XX+ #define FILE_NOT_READABLE		4
XX+ 
XX+ /* Defines for the fatal errors						*/
XX+ #define SYNTAX_ERROR			101
XX+ #define POSITION_ERROR			102
XX+ #define USAGE				103
XX+ #define LINE_TO_LONG_ERROR		104
XX+ #define RANGE_ERROR			105
XX+ #define MAX_FIELDS_EXEEDED_ERROR	106
XX+ #define MAX_ARGS_EXEEDED_ERROR		107
XX+ 
XX+ 
XX  int mode;			/* 0 = dump stdin to stdout, 1=-f, 2=-c   */
XX! int flag_i;			/* SET = -i set on command line	 */
XX! int flag_s;			/* SET = -s set on command line	 */
XX  char delim = '\t';		/* default delimiting character	  */
XX  FILE *fd;
XX  char *name;
XX  char line[BUFSIZ];
XX! int exit_status;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void warn, (int warn_number, char *option));
XX+ _PROTOTYPE(void cuterror, (int err));
XX+ _PROTOTYPE(void get_args, (void));
XX+ _PROTOTYPE(void cut, (void));
XX+ 
XX+ void warn(warn_number, option)
XX+ int warn_number;
XX+ char *option;
XX+ {
XX+   static char *warn_msg[] = {
XX+ 			   "%s: Option -d allowed only with -f\n",
XX+ 			   "%s: -%s overrides earlier option\n",
XX+ 			   "%s: -%s not allowed in current mode\n",
XX+ 			   "%s: Cannot open %s\n"
XX+   };
XX+ 
XX+   fprintf(stderr, warn_msg[warn_number], name, option);
XX+   exit_status = warn_number + 1;
XX+ 
XX+ }
XX+ 
XX  void cuterror(err)
XX  int err;
XX  {
XX    static char *err_mes[] = {
XX  			  "%s: syntax error\n",
XX  			  "%s: position must be >0\n",
XX!   "%s: usage: cut [-f args [-i] [-d x]]|[-c args] [filename [...]]\n",
XX  			  "%s: line longer than BUFSIZ\n",
XX  		 "%s: range must not decrease from left to right\n",
XX  			  "%s: MAX_FIELD exceeded\n",
XX  			  "%s: MAX_ARGS exceeded\n"
XX    };
XX! 
XX!   fprintf(stderr, err_mes[err - 101], name);
XX    exit(err);
XX  }
XX  
XX***************
XX*** 66,73 ****
XX  
XX    num_args = 0;
XX    do {
XX! 	if (num_args == MAX_ARGS) cuterror(10);
XX! 	if (!isdigit(line[i]) && line[i] != '-') cuterror(1);
XX  
XX  	args[arg_ptr] = 1;
XX  	args[arg_ptr + 1] = BUFSIZ;
XX--- 120,127 ----
XX  
XX    num_args = 0;
XX    do {
XX! 	if (num_args == MAX_ARGS) cuterror(MAX_ARGS_EXEEDED_ERROR);
XX! 	if (!isdigit(line[i]) && line[i] != '-') cuterror(SYNTAX_ERROR);
XX  
XX  	args[arg_ptr] = 1;
XX  	args[arg_ptr + 1] = BUFSIZ;
XX***************
XX*** 78,84 ****
XX  			args[arg_ptr] = 0;
XX  			while (isdigit(line[i]))
XX  				args[arg_ptr] = 10 * args[arg_ptr] + line[i++] - '0';
XX! 			if (!args[arg_ptr]) cuterror(2);
XX  			arg_ptr++;
XX  		}
XX  		if (line[i] == '-') {
XX--- 132,138 ----
XX  			args[arg_ptr] = 0;
XX  			while (isdigit(line[i]))
XX  				args[arg_ptr] = 10 * args[arg_ptr] + line[i++] - '0';
XX! 			if (!args[arg_ptr]) cuterror(POSITION_ERROR);
XX  			arg_ptr++;
XX  		}
XX  		if (line[i] == '-') {
XX***************
XX*** 88,94 ****
XX  		}
XX  	}
XX  	if (flag && arg_ptr & 1) args[arg_ptr] = args[arg_ptr - 1];
XX! 	if (args[num_args * 2] > args[num_args * 2 + 1]) cuterror(8);
XX  	num_args++;
XX  	arg_ptr = num_args * 2;
XX    }
XX--- 142,149 ----
XX  		}
XX  	}
XX  	if (flag && arg_ptr & 1) args[arg_ptr] = args[arg_ptr - 1];
XX! 	if (args[num_args * 2] > args[num_args * 2 + 1])
XX! 		cuterror(RANGE_ERROR);
XX  	num_args++;
XX  	arg_ptr = num_args * 2;
XX    }
XX***************
XX*** 99,193 ****
XX  void cut()
XX  {
XX    int i, j, length, maxcol;
XX  
XX    while (fgets(line, BUFSIZ, fd)) {
XX  	length = strlen(line) - 1;
XX  	*(line + length) = 0;
XX  	switch (mode) {
XX! 	    case 0:	printf("%s", line);	break;
XX! 	    case 1:
XX  		maxcol = 0;
XX  		columns[maxcol++] = line;
XX  		for (i = 0; i < length; i++) {
XX  			if (*(line + i) == delim) {
XX  				*(line + i) = 0;
XX! 				if (maxcol == MAX_FIELD) cuterror(9);
XX  				columns[maxcol] = line + i + 1;
XX! 				while (*(line + i + 1) == delim && flagi) {
XX  					columns[maxcol]++;
XX  					i++;
XX  				}
XX  				maxcol++;
XX  			}
XX  		}
XX! 		for (i = 0; i < num_args; i++) {
XX! 			for (j = args[i * 2]; j <= args[i * 2 + 1]; j++)
XX! 				if (j <= maxcol) {
XX! 					printf("%s", columns[j - 1]);
XX! 					if (i != num_args - 1 || j != args[i * 2 + 1])
XX! 						putchar(delim);
XX! 				}
XX  		}
XX  		break;
XX! 	    case 2:
XX  		for (i = 0; i < num_args; i++) {
XX  			for (j = args[i * 2]; j <= (args[i * 2 + 1] > length ? length :
XX  					      args[i * 2 + 1]); j++)
XX  				putchar(*(line + j - 1));
XX  		}
XX  	}
XX! 	putchar('\n');
XX    }
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX-   int flag;
XX    int i = 1;
XX! 
XX    name = argv[0];
XX-   if (argc == 1) cuterror(4);
XX  
XX!   while (argv[i] != NULL && argv[i][0] == '-') {
XX! 	switch (argv[i][1]) {
XX! 	    case 'd':
XX! 		if (mode == 2) cuterror(6);
XX! 		sprintf(line, "%.1s", &argv[i++][2]);
XX! 		delim = line[0];
XX! 		break;
XX! 	    case 'f':
XX! 		sprintf(line, "%s", &argv[i++][2]);
XX! 		mode = 1;
XX! 		get_args();
XX! 		break;
XX! 	    case 'c':
XX! 		sprintf(line, "%s", &argv[i++][2]);
XX! 		mode = 2;
XX! 		get_args();
XX! 		break;
XX! 	    case 'i':
XX! 		if (mode == 2) cuterror(7);
XX! 		flagi = 1;
XX  		i++;
XX! 		break;
XX! 	    default:	cuterror(3);
XX  	}
XX    }
XX  
XX!   if (i < argc)
XX! 	if ((fd = fopen(argv[i], "r")) == NULL) {
XX! 		printf("%s: couldn't open %s\n", name, argv[i]);
XX! 		exit(errno);
XX! 	} else {
XX! 		cut();
XX! 		fclose(fd);
XX  	}
XX!   else {
XX  	fd = stdin;
XX  	cut();
XX    }
XX!   exit(0);
XX  }
XX--- 154,310 ----
XX  void cut()
XX  {
XX    int i, j, length, maxcol;
XX+   char *columns[MAX_FIELD];
XX  
XX    while (fgets(line, BUFSIZ, fd)) {
XX  	length = strlen(line) - 1;
XX  	*(line + length) = 0;
XX  	switch (mode) {
XX! 	    case DUMP_STDIN:	printf("%s", line);	break;
XX! 	    case OPTIONF:
XX  		maxcol = 0;
XX  		columns[maxcol++] = line;
XX  		for (i = 0; i < length; i++) {
XX  			if (*(line + i) == delim) {
XX  				*(line + i) = 0;
XX! 				if (maxcol == MAX_FIELD)
XX! 					cuterror(MAX_FIELDS_EXEEDED_ERROR);
XX  				columns[maxcol] = line + i + 1;
XX! 				while (*(line + i + 1) == delim && flag_i) {
XX  					columns[maxcol]++;
XX  					i++;
XX  				}
XX  				maxcol++;
XX  			}
XX  		}
XX! 		if (maxcol == 1) {
XX! 			if (flag_s != SET) printf("%s", line);
XX! 		} else {
XX! 			for (i = 0; i < num_args; i++) {
XX! 				for (j = args[i * 2]; j <= args[i * 2 + 1]; j++)
XX! 					if (j <= maxcol) {
XX! 						printf("%s", columns[j - 1]);
XX! 						if (i != num_args - 1 || j != args[i * 2 + 1])
XX! 							putchar(delim);
XX! 					}
XX! 			}
XX  		}
XX  		break;
XX! 	    case OPTIONC:
XX  		for (i = 0; i < num_args; i++) {
XX  			for (j = args[i * 2]; j <= (args[i * 2 + 1] > length ? length :
XX  					      args[i * 2 + 1]); j++)
XX  				putchar(*(line + j - 1));
XX  		}
XX  	}
XX! 	if (maxcol == 1 && flag_s == SET);
XX! 	else
XX! 		putchar('\n');
XX    }
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int i = 1;
XX!   int numberFilenames = 0;
XX    name = argv[0];
XX  
XX!   if (argc == 1) cuterror(USAGE);
XX! 
XX!   while (i < argc) {
XX! 	if (argv[i][0] == '-') {
XX! 		switch (argv[i++][1]) {
XX! 		    case 'd':
XX! 			if (mode == OPTIONC || mode == OPTIONB)
XX! 				warn(DELIMITER_NOT_APPLICABLE, "d");
XX! 			delim = argv[i++][0];
XX! 			break;
XX! 		    case 'f':
XX! 			sprintf(line, "%s", argv[i++]);
XX! 			if (mode == OPTIONC || mode == OPTIONB)
XX! 				warn(OVERRIDING_PREVIOUS_MODE, "f");
XX! 			mode = OPTIONF;
XX! 			break;
XX! 		    case 'b':
XX! 			sprintf(line, "%s", argv[i++]);
XX! 			if (mode == OPTIONF || mode == OPTIONC)
XX! 				warn(OVERRIDING_PREVIOUS_MODE, "b");
XX! 			mode = OPTIONB;
XX! 			break;
XX! 		    case 'c':
XX! 			sprintf(line, "%s", argv[i++]);
XX! 			if (mode == OPTIONF || mode == OPTIONB)
XX! 				warn(OVERRIDING_PREVIOUS_MODE, "c");
XX! 			mode = OPTIONC;
XX! 			break;
XX! 		    case 'i':	flag_i = SET;	break;
XX! 		    case 's':	flag_s = SET;	break;
XX! 		    case '\0':	/* - means: read from stdin		 */
XX! 			numberFilenames++;
XX! 			break;
XX! 		    case 'n':	/* needed for Posix, but no effect here	 */
XX! 			if (mode != OPTIONB)
XX! 				warn(OPTION_NOT_APPLICABLE, "n");
XX! 			break;
XX! 		    default:
XX! 			warn(UNKNOWN_OPTION, &(argv[i - 1][1]));
XX! 		}
XX! 	} else {
XX  		i++;
XX! 		numberFilenames++;
XX  	}
XX    }
XX  
XX! /* Here follow the checks, if the selected options are reasonable.	*/
XX!   if (mode == OPTIONB)		/* since in Minix char := byte		 */
XX! 	mode = OPTIONC;
XX! /* Flag -s is only allowed with -f, otherwise warn and reset flag_s	*/
XX!   if (flag_s == SET && (mode == OPTIONB || mode == OPTIONC)) {
XX! 	warn(OPTION_NOT_APPLICABLE, "s");
XX! 	flag_s = NOTSET;
XX!   }
XX! 
XX! /* Flag -i is only allowed with -f, otherwise warn and reset flag_i	*/
XX!   if (flag_i == SET && mode == OPTIONF) {
XX! 	warn(OPTION_NOT_APPLICABLE, "s");
XX! 	flag_i = NOTSET;
XX!   }
XX!   get_args();
XX!   if (numberFilenames != 0) {
XX! 	i = 1;
XX! 	while (i < argc) {
XX! 		if (argv[i][0] == '-') {
XX! 			switch (argv[i][1]) {
XX! 			    case 'f':
XX! 			    case 'c':
XX! 			    case 'b':
XX! 			    case 'd':	i += 2;	break;
XX! 			    case 'n':
XX! 			    case 'i':
XX! 			    case 's':	i++;	break;
XX! 			    case '\0':
XX! 				fd = stdin;
XX! 				i++;
XX! 				cut();
XX! 				break;
XX! 			    default:	i++;
XX! 			}
XX! 		} else {
XX! 			if ((fd = fopen(argv[i++], "r")) == NULL) {
XX! 				warn(FILE_NOT_READABLE, argv[i - 1]);
XX! 			} else {
XX! 				cut();
XX! 				fclose(fd);
XX! 			}
XX! 		}
XX  	}
XX!   } else {
XX  	fd = stdin;
XX  	cut();
XX    }
XX! 
XX!   return(exit_status);
XX  }
X/
Xecho x - date.c.d
Xsed '/^X/s///' > date.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/date.c  crc=40785   2209	Sun Apr 25 21:34:52 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/date.c  crc=46852   7911	Wed Nov  4 04:19:08 1992
XX***************
XX*** 1,113 ****
XX- /* date - print or set time and date		Author: Jan Looyen */
XX  
XX  #include <sys/types.h>
XX  #include <stddef.h>
XX  #include <time.h>
XX  #include <stdio.h>
XX  
XX  #define	MIN	60L		/* # seconds in a minute */
XX  #define	HOUR	(60 * MIN)	/* # seconds in an hour */
XX  #define	DAY	(24 * HOUR)	/* # seconds in a day */
XX! #define	YEAR	(365 * DAY)	/* # seconds in a year */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   int qflag;
XX!   long t;
XX!   char time_buf[15];
XX  
XX!   if (argc > 2) usage();
XX!   if (argc == 2) {
XX! 	if (*argv[1] == '-' && (argv[1][1] | 0x60) == 'q') {
XX! 		freopen("/dev/tty0", "r", stdin);
XX  		printf("\nPlease enter date: MMDDYYhhmmss. Then hit the RETURN key.\n");
XX! 		gets(time_buf);
XX  		set_time(time_buf);
XX! 	} else
XX! 		set_time(argv[1]);
XX    }
XX!   time(&t);
XX!   printf("%s", ctime(&t));
XX!   exit(0);
XX! }
XX  
XX  
XX! set_time(t)
XX! char *t;
XX! {
XX!   char *tp;
XX!   long ct;
XX!   int len;
XX!   static int days_per_month[] = {
XX! 		      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
XX!   };
XX!   struct tm *p;
XX  
XX!   time(&ct);
XX!   p = localtime(&ct);
XX!   p->tm_year -= 70;
XX!   p->tm_mon++;
XX!   len = strlen(t);
XX!   if (len != 12 && len != 10 && len != 6 && len != 4) usage();
XX!   tp = t;
XX!   while (*tp)
XX! 	if (!isdigit(*tp++)) bad();
XX!   if (len == 6 || len == 12) p->tm_sec = conv(&tp, 59);
XX!   p->tm_min = conv(&tp, 59);
XX!   p->tm_hour = conv(&tp, 23);
XX!   if (len == 12 || len == 10) {
XX! 	p->tm_year = conv(&tp, 99);
XX! 	p->tm_mday = conv(&tp, 31);
XX! 	p->tm_mon = conv(&tp, 12);
XX! 	p->tm_year -= 70;
XX! 	if (p->tm_year < 0) p->tm_year += 100;
XX!   }
XX!   ct = p->tm_year * YEAR;
XX!   ct += ((p->tm_year + 1) / 4) * DAY;
XX!   days_per_month[1] = 28;
XX!   if (((p->tm_year + 2) % 4) == 0) days_per_month[1]++;
XX!   len = 0;
XX!   p->tm_mon--;
XX!   while (len < p->tm_mon) ct += days_per_month[len++] * DAY;
XX!   ct += --p->tm_mday * DAY;
XX!   ct += p->tm_hour * HOUR;
XX!   ct += p->tm_min * MIN;
XX!   ct += p->tm_sec;
XX!   if (stime(&ct)) fprintf(stderr, "Set date not allowed\n");
XX  }
XX  
XX! conv(ptr, max)
XX! char **ptr;
XX! int max;
XX  {
XX!   int buf;
XX  
XX!   *ptr -= 2;
XX!   buf = atoi(*ptr);
XX!   **ptr = 0;
XX!   if (buf < 0 || buf > max) bad();
XX!   return(buf);
XX  }
XX  
XX! bad()
XX  {
XX!   fprintf(stderr, "Date: bad conversion\n");
XX!   exit(1);
XX  }
XX  
XX! usage()
XX  {
XX!   fprintf(stderr, "Usage: date [-q] [[MMDDYY]hhmm[ss]]\n");
XX!   exit(1);
XX  }
XX  
XX! isdigit(c)
XX! char c;
XX  {
XX!   if (c >= '0' && c <= '9')
XX! 	return(1);
XX!   else
XX! 	return(0);
XX  }
XX--- 1,344 ----
XX  
XX+ /* date - Display (or set) the date and time		Author: V. Archer */
XX+ 
XX  #include <sys/types.h>
XX+ #include <ctype.h>
XX  #include <stddef.h>
XX+ #include <stdlib.h>
XX  #include <time.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  #define	MIN	60L		/* # seconds in a minute */
XX  #define	HOUR	(60 * MIN)	/* # seconds in an hour */
XX  #define	DAY	(24 * HOUR)	/* # seconds in a day */
XX! #define	YEAR	(365 * DAY)	/* # seconds in a (non-leap) year */
XX  
XX! int uflag;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void pstring, (char *s, int len));
XX! _PROTOTYPE(void pdecimal, (int d, int digits));
XX! _PROTOTYPE(void fmtdate, (FILE *fp, char *format, struct tm *p));
XX! _PROTOTYPE(void set_time, (char *t));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! /* Main module. Handles P1003.2 date and system administrator's date. The
XX!  * date entered should be given GMT, regardless of the system's TZ!
XX!  */
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   time_t t;
XX!   char *format;
XX!   char time_buf[40];
XX  
XX!   argc--;
XX!   argv++;
XX!   if (argc) {
XX! 	if (**argv == '-' && argv[0][1] == 'q') {
XX  		printf("\nPlease enter date: MMDDYYhhmmss. Then hit the RETURN key.\n");
XX! 		fgets(time_buf, sizeof time_buf, stdin);
XX  		set_time(time_buf);
XX! 		argc--;
XX! 		argv++;
XX! 	} else if (isdigit(argv[0][1])) {
XX! 		set_time(argv[0]);
XX! 		argc--;
XX! 		argv++;
XX! 	}
XX    }
XX!   if (argc && **argv == '-' && argv[0][1] == 'u') {
XX! 	uflag = 1;
XX! 	argc--;
XX! 	argv++;
XX!   } else
XX! 	uflag = 0;
XX  
XX+   if (argc > 1 || (argc && **argv != '+')) usage();
XX  
XX!   if (argc)
XX! 	format = argv[0] + 1;
XX!   else
XX! 	format = "%c";
XX  
XX!   time(&t);
XX!   fmtdate(stdout, format, uflag ? gmtime(&t) : localtime(&t));
XX!   putchar('\n');
XX!   fflush(stdout);
XX!   return(0);
XX  }
XX  
XX! /* Internal function that prints a n-digits number. Replaces stdio in our
XX!  * specific case.
XX!  */
XX! void pdecimal(d, digits)
XX! int d, digits;
XX  {
XX!   digits--;
XX!   if (d > 9 || digits > 0) pdecimal(d / 10, digits);
XX!   putchar('0' + (d % 10));
XX! }
XX  
XX! /* Internal function that prints a fixed-size string. Replaces stdio in our
XX!  * specific case.
XX!  */
XX! void pstring(s, len)
XX! char *s;
XX! int len;
XX! {
XX!   while (*s)
XX! 	if (len--)
XX! 		putchar(*s++);
XX! 	else
XX! 		break;
XX  }
XX  
XX! /* Format the date, using the given locale string. A special case is the
XX!  * TZ which might be a sign followed by four digits (New format time zone).
XX!  */
XX! void fmtdate(fp, format, p)
XX! FILE *fp;
XX! char *format;
XX! struct tm *p;
XX  {
XX!   int i;
XX!   char *s;
XX!   static char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
XX! 		       "Thursday", "Friday", "Saturday"};
XX!   static char *month[] = {"January", "February", "March", "April",
XX! 			"May", "June", "July", "August",
XX! 		    "September", "October", "November", "December"};
XX! 
XX!   while (*format)
XX! 	if (*format == '%') {
XX! 		switch (*++format) {
XX! 		    case 'A':
XX! 			pstring(wday[p->tm_wday], -1);
XX! 			break;
XX! 		    case 'B':
XX! 			pstring(month[p->tm_mon], -1);
XX! 			break;
XX! 		    case 'D':
XX! 			pdecimal(p->tm_mon + 1, 2);
XX! 			putchar('/');
XX! 			pdecimal(p->tm_mday, 2);
XX! 			putchar('/');
XX! 		    case 'y':
XX! 			pdecimal(p->tm_year % 100, 2);
XX! 			break;
XX! 		    case 'H':
XX! 			pdecimal(p->tm_hour, 2);
XX! 			break;
XX! 		    case 'I':
XX! 			i = p->tm_hour % 12;
XX! 			pdecimal(i ? i : 12, 2);
XX! 			break;
XX! 		    case 'M':
XX! 			pdecimal(p->tm_min, 2);
XX! 			break;
XX! 		    case 'X':
XX! 		    case 'T':
XX! 			pdecimal(p->tm_hour, 2);
XX! 			putchar(':');
XX! 			pdecimal(p->tm_min, 2);
XX! 			putchar(':');
XX! 		    case 'S':
XX! 			pdecimal(p->tm_sec, 2);
XX! 			break;
XX! 		    case 'U':
XX! 			pdecimal((p->tm_yday - p->tm_wday + 13) / 7, 2);
XX! 			break;
XX! 		    case 'W':
XX! 			if (--(p->tm_wday) < 0) p->tm_wday = 6;
XX! 			pdecimal((p->tm_yday - p->tm_wday + 13) / 7, 2);
XX! 			if (++(p->tm_wday) > 6) p->tm_wday = 0;
XX! 			break;
XX! 		    case 'Y':
XX! 			pdecimal(p->tm_year + 1900, 4);
XX! 			break;
XX! 		    case 'Z':
XX! 			if (uflag)
XX! 				s = "GMT";	/* or "Z" as in X400 */
XX! 			else if (!(s = getenv("TZ")))
XX! 				s = "";
XX! 			if (*s == '+' || *s == '-')
XX! 				pstring(s, 5);
XX! 			else
XX! 				pstring(s, 3);
XX! 			break;
XX! 		    case 'a':
XX! 			pstring(wday[p->tm_wday], 3);
XX! 			break;
XX! 		    case 'b':
XX! 		    case 'h':
XX! 			pstring(month[p->tm_mon], 3);
XX! 			break;
XX! 		    case 'c':
XX! 			if (!(s = getenv("LC_TIME")))
XX! 				s = "%a %b %e %T %Z %Y";
XX! 			fmtdate(fp, s, p);
XX! 			break;
XX! 		    case 'd':
XX! 			pdecimal(p->tm_mday, 2);
XX! 			break;
XX! 		    case 'e':
XX! 			if (p->tm_mday < 10) putchar(' ');
XX! 			pdecimal(p->tm_mday, 1);
XX! 			break;
XX! 		    case 'j':
XX! 			pdecimal(p->tm_yday + 1, 3);
XX! 			break;
XX! 		    case 'm':
XX! 			pdecimal(p->tm_mon + 1, 2);
XX! 			break;
XX! 		    case 'n':	putchar('\n');	break;
XX! 		    case 'p':
XX! 			if (p->tm_hour < 12)
XX! 				putchar('A');
XX! 			else
XX! 				putchar('P');
XX! 			putchar('M');
XX! 			break;
XX! 		    case 'r':
XX! 			fmtdate(fp, "%I:%M:%S %p", p);
XX! 			break;
XX! 		    case 't':	putchar('\t');	break;
XX! 		    case 'w':
XX! 			putchar('0' + p->tm_wday);
XX! 			break;
XX! 		    case 'x':
XX! 			fmtdate(fp, "%B %e %Y", p);
XX! 			break;
XX! 		    case '%':	putchar('%');	break;
XX! 		    case '\0':	format--;
XX! 		}
XX! 		format++;
XX! 	} else
XX! 		putchar(*format++);
XX  }
XX  
XX! /* Set a new GMT time and maybe date. */
XX! void set_time(t)
XX! char *t;
XX  {
XX!   struct tm tm;				/* user specified time */
XX!   time_t now;				/* current time */
XX!   int leap;				/* current year is leap year */
XX!   int i;				/* general index */
XX!   int fld;				/* number of fields */
XX!   int f[6];				/* time fields */
XX!   static int days_per_month[2][12] = {
XX!   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
XX!   { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};
XX! 
XX! /* Get current time just in case */
XX!   now = time((time_t *) 0);
XX!   tm  = *localtime(&now);
XX!   tm.tm_sec   = 0;
XX!   tm.tm_mon++;
XX!   tm.tm_year %= 100;
XX! 
XX! /* Parse the time */
XX! #if '0'+1 != '1' || '1'+1 != '2' || '2'+1 != '3' || '3'+1 != '4' || \
XX!     '4'+1 != '5' || '5'+1 != '6' || '6'+1 != '7' || '7'+1 != '8' || '8'+1 != '9'
XX!   << Code unsuitable for character collating sequence >>
XX! #endif
XX! 
XX!   for (fld = 0; fld < sizeof(f)/sizeof(f[0]); fld++) {
XX! 	if (*t == 0) break;
XX! 	f[fld] = 0;
XX! 	for (i = 0; i < 2; i++, t++) {
XX! 		if (*t < '0' || *t > '9') usage();
XX! 		f[fld] = f[fld] * 10 + *t - '0';
XX! 	}
XX!   }
XX! 
XX!   switch (fld) {
XX!   case 2:
XX! 	tm.tm_hour = f[0]; tm.tm_min  = f[1]; break;
XX! 
XX!   case 3:
XX! 	tm.tm_hour = f[0]; tm.tm_min  = f[1]; tm.tm_sec  = f[2];
XX! 	break;
XX! 
XX!   case 5:
XX!   	tm.tm_mon  = f[0]; tm.tm_mday = f[1]; tm.tm_year = f[2];
XX! 	tm.tm_hour = f[3]; tm.tm_min  = f[4];
XX! 	break;
XX! 
XX!   case 6:
XX! 	tm.tm_mon  = f[0]; tm.tm_mday = f[1]; tm.tm_year = f[2];
XX! 	tm.tm_hour = f[3]; tm.tm_min  = f[4]; tm.tm_sec  = f[5];
XX! 	break;
XX! 
XX!   default:
XX! 	usage();
XX!   }
XX! 
XX! /* Convert the time into seconds since 1 January 1970 */
XX!   if (tm.tm_year < 70)
XX!     tm.tm_year += 100;
XX!   leap = (tm.tm_year % 4 == 0 && tm.tm_year % 400 != 0);
XX!   if (tm.tm_mon  < 1  || tm.tm_mon  > 12 ||
XX!       tm.tm_mday < 1  || tm.tm_mday > days_per_month[leap][tm.tm_mon-1] ||
XX!       tm.tm_hour > 23 || tm.tm_min  > 59) {
XX!     fputs("Illegal date format\n", stderr);
XX!     exit(1);
XX!   }
XX! 
XX! /* Convert the time into Minix time - zone independent code */
XX!   {
XX!     time_t utctime;			/* guess at unix time */
XX!     time_t nextbit;			/* next bit to try */
XX!     int rv;				/* result of try */
XX!     struct tm *tmp;			/* local time conversion */
XX! 
XX! #define COMPARE(a,b)	((a) != (b)) ? ((a) - (b)) :
XX! 
XX!     utctime = 1;
XX!     do {
XX!       nextbit = utctime;
XX!       utctime = nextbit << 1;
XX!     } while (utctime >= 1);
XX! 
XX!     for (utctime = 0; ; nextbit >>= 1) {
XX! 
XX!       utctime |= nextbit;
XX!       tmp = localtime(&utctime);
XX!       if (tmp == 0) continue;
XX! 
XX!       rv = COMPARE(tmp->tm_year,    tm.tm_year)
XX!            COMPARE(tmp->tm_mon + 1, tm.tm_mon)
XX! 	   COMPARE(tmp->tm_mday,    tm.tm_mday)
XX! 	   COMPARE(tmp->tm_hour,    tm.tm_hour)
XX! 	   COMPARE(tmp->tm_min,     tm.tm_min)
XX! 	   COMPARE(tmp->tm_sec,     tm.tm_sec)
XX! 	   0;
XX! 
XX!       if (rv > 0)
XX!         utctime &= ~nextbit;
XX!       else if (rv == 0)
XX!         break;
XX! 
XX!       if (nextbit == 0) {
XX! 	uflag = 1;
XX!         fputs("Inexact conversion to UTC from ", stderr);
XX!         fmtdate(stderr, "%c\n", localtime(&utctime) );
XX! 	exit(1);
XX!       }
XX!     }
XX!     if (stime(&utctime)) {
XX!       fputs("No permission to set time\n", stderr);
XX!       exit(1);
XX!     }
XX!   }
XX  }
XX  
XX! /* (Extended) Posix prototype of date. */
XX! void usage()
XX  {
XX!   fputs("Usage: date [-q | [MMDDYY]hhmm[ss]] [-u] [+format]\n", stderr);
XX!   exit(1);
XX  }
X/
Xecho x - dd.c.d
Xsed '/^X/s///' > dd.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/dd.c  crc=29987   5773	Sun Apr 25 21:34:52 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/dd.c  crc=63062   6504	Mon Jan 18 14:30:50 1993
XX***************
XX*** 1,9 ****
XX--- 1,12 ----
XX  /* dd - disk dumper */
XX  
XX  #include <sys/types.h>
XX+ #include <sys/stat.h>
XX  #include <signal.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define EOS '\0'
XX***************
XX*** 11,18 ****
XX  #define TRUE 1
XX  #define FALSE 0
XX  
XX  
XX! char *pch, *errorp; 
XX  
XX  BOOLEAN is(pc)
XX  char *pc;
XX--- 14,31 ----
XX  #define TRUE 1
XX  #define FALSE 0
XX  
XX+ char *pch, *errorp;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(BOOLEAN is, (char *pc));
XX! _PROTOTYPE(int num, (void));
XX! _PROTOTYPE(void puto, (void));
XX! _PROTOTYPE(void statistics, (void));
XX! _PROTOTYPE(int ulcase, (int c));
XX! _PROTOTYPE(void cnull, (int c));
XX! _PROTOTYPE(void null, (int c));
XX! _PROTOTYPE(void extra, (void));
XX! _PROTOTYPE(void over, (int dummy));
XX  
XX  BOOLEAN is(pc)
XX  char *pc;
XX***************
XX*** 38,59 ****
XX    ans = 0L;
XX    while ((*pc >= '0') && (*pc <= '9'))
XX  	ans = (long) ((*pc++ - '0') + (ans * 10));
XX!   while (TRUE)
XX! 	switch (*pc++) {
XX! 	 case 'w':   ans *= 2L;
XX! 		     continue;
XX! 	 case 'b':   ans *= 512L;
XX! 		     continue;
XX! 	 case 'k':   ans *= 1024L;
XX! 		     continue;
XX! 	 case 'x':   pch = pc;
XX! 		     ans *= (long) num();
XX! 	 case EOS:   if ((ans >= BIGNUM) || (ans < 0)) {
XX! 		       fprintf(stderr, "dd: argument %s out of range\n",
XX! 				       errorp);
XX! 		       exit(1);
XX! 		     }
XX! 		     return((int) ans);
XX  	}
XX  }
XX  
XX--- 51,76 ----
XX    ans = 0L;
XX    while ((*pc >= '0') && (*pc <= '9'))
XX  	ans = (long) ((*pc++ - '0') + (ans * 10));
XX!   while (TRUE) switch (*pc++) {
XX! 	    case 'w':
XX! 		ans *= 2L;
XX! 		continue;
XX! 	    case 'b':
XX! 		ans *= 512L;
XX! 		continue;
XX! 	    case 'k':
XX! 		ans *= 1024L;
XX! 		continue;
XX! 	    case 'x':
XX! 		pch = pc;
XX! 		ans *= (long) num();
XX! 	    case EOS:
XX! 		if ((ans >= BIGNUM) || (ans < 0)) {
XX! 			fprintf(stderr, "dd: argument %s out of range\n",
XX! 				errorp);
XX! 			exit(1);
XX! 		}
XX! 		return((int) ans);
XX  	}
XX  }
XX  
XX***************
XX*** 66,71 ****
XX--- 83,89 ----
XX  #define DEFAULT 512
XX  
XX  unsigned cbs, bs, skip, nseek, count;
XX+ int seekseen = FALSE;
XX  unsigned ibs = DEFAULT;
XX  unsigned obs = DEFAULT;
XX  unsigned files = 1;
XX***************
XX*** 74,98 ****
XX  
XX  int convflag = 0;
XX  int flag = 0;
XX- int cnull(), ibm(), null();
XX- void over();
XX  int ifd, ofd, ibc;
XX  char *ibuf, *obuf, *op;
XX- extern char *sbrk();
XX  unsigned nifull, nipartial, nofull, nopartial;
XX  int cbc;
XX  unsigned ntr, obc;
XX  int ns;
XX! char mlen[] = {64,45,82,45,83,96,109,100,109,97,96,116,108,9};
XX  
XX! puto()
XX  {
XX    int n;
XX  
XX    if (obc == 0) return;
XX    if (obc == obs)
XX  	nofull++;
XX!   else    nopartial++;
XX    if ((n = write(ofd, obuf, obc)) != obc) {
XX  	fprintf(stderr, "dd: write error\n");
XX  	exit(1);
XX--- 92,114 ----
XX  
XX  int convflag = 0;
XX  int flag = 0;
XX  int ifd, ofd, ibc;
XX  char *ibuf, *obuf, *op;
XX  unsigned nifull, nipartial, nofull, nopartial;
XX  int cbc;
XX  unsigned ntr, obc;
XX  int ns;
XX! char mlen[] = {64, 45, 82, 45, 83, 96, 109, 100, 109, 97, 96, 116, 108, 9};
XX  
XX! void puto()
XX  {
XX    int n;
XX  
XX    if (obc == 0) return;
XX    if (obc == obs)
XX  	nofull++;
XX!   else
XX! 	nopartial++;
XX    if ((n = write(ofd, obuf, obc)) != obc) {
XX  	fprintf(stderr, "dd: write error\n");
XX  	exit(1);
XX***************
XX*** 100,121 ****
XX    obc = 0;
XX  }
XX  
XX! statistics()
XX  {
XX!   fprintf(stderr, "%u+%u records in\n", nifull, nipartial);       
XX!   fprintf(stderr, "%u+%u records out\n", nofull, nopartial);      
XX!   if (ntr)
XX! 	fprintf(stderr, "%d truncated records\n", ntr);
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int (*convert)();
XX    char *iptr;
XX!   int i,j;
XX  
XX    convert = null;
XX    argc--;
XX--- 116,140 ----
XX    obc = 0;
XX  }
XX  
XX! void statistics()
XX  {
XX!   fprintf(stderr, "%u+%u records in\n", nifull, nipartial);
XX!   fprintf(stderr, "%u+%u records out\n", nofull, nopartial);
XX!   if (ntr) fprintf(stderr, "%d truncated records\n", ntr);
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX! #ifdef __STDC__
XX!   void (*convert) (int);
XX! #else
XX!   void (*convert) ();
XX! #endif
XX    char *iptr;
XX!   int i, j;
XX  
XX    convert = null;
XX    argc--;
XX***************
XX*** 153,158 ****
XX--- 172,178 ----
XX  	if (is("seek=")) {
XX  		errorp = pch;
XX  		nseek = num();
XX+ 		seekseen = TRUE;
XX  		continue;
XX  	}
XX  	if (is("count=")) {
XX***************
XX*** 167,173 ****
XX  	}
XX  	if (is("length=")) {
XX  		errorp = pch;
XX! 		for (j=0; j<13; j++) mlen[j]++;
XX  		write(2, mlen, 14);
XX  		continue;
XX  	}
XX--- 187,193 ----
XX  	}
XX  	if (is("length=")) {
XX  		errorp = pch;
XX! 		for (j = 0; j < 13; j++) mlen[j]++;
XX  		write(2, mlen, 14);
XX  		continue;
XX  	}
XX***************
XX*** 193,227 ****
XX  				convflag |= SWAB;
XX  				continue;
XX  			}
XX! 			if (is(","))
XX! 				continue;
XX  			fprintf(stderr, "dd: bad argument: %s\n",
XX! 					pch);
XX  			exit(1);
XX  		}
XX! 		if (*pch == EOS)
XX! 			continue;
XX  	}
XX  	fprintf(stderr, "dd: bad argument: %s \n",
XX! 			pch);
XX  	exit(1);
XX    }
XX!   if ((convert == null) && (convflag & (UCASE | LCASE)))
XX! 	convert = cnull;
XX    if ((ifd = ((ifilename) ? open(ifilename, O_RDONLY) : dup(0))) < 0) {
XX  	fprintf(stderr, "dd: cannot open %s\n",
XX! 			 (ifilename) ? ifilename : "stdin");
XX  	exit(1);
XX    }
XX!   if ((ofd = ((ofilename) ? creat(ofilename, 0666) : dup(1))) < 0) {
XX  	fprintf(stderr, "dd: cannot creat %s\n",
XX! 			 (ofilename) ? ofilename : "stdout");
XX  	exit(1);
XX    }
XX    if (bs) {
XX  	ibs = obs = bs;
XX! 	if (convert == null)
XX! 		flag++;
XX    }
XX    if (ibs == 0) {
XX  	fprintf(stderr, "dd: ibs cannot be zero\n");
XX--- 213,245 ----
XX  				convflag |= SWAB;
XX  				continue;
XX  			}
XX! 			if (is(",")) continue;
XX  			fprintf(stderr, "dd: bad argument: %s\n",
XX! 				pch);
XX  			exit(1);
XX  		}
XX! 		if (*pch == EOS) continue;
XX  	}
XX  	fprintf(stderr, "dd: bad argument: %s \n",
XX! 		pch);
XX  	exit(1);
XX    }
XX!   if ((convert == null) && (convflag & (UCASE | LCASE))) convert = cnull;
XX    if ((ifd = ((ifilename) ? open(ifilename, O_RDONLY) : dup(0))) < 0) {
XX  	fprintf(stderr, "dd: cannot open %s\n",
XX! 		(ifilename) ? ifilename : "stdin");
XX  	exit(1);
XX    }
XX!   if ((ofd = ((ofilename) ?
XX! 	    open(ofilename, seekseen ? O_WRONLY | O_CREAT : O_WRONLY | O_CREAT | O_TRUNC,
XX! 		 0666) : dup(1))) < 0) {
XX  	fprintf(stderr, "dd: cannot creat %s\n",
XX! 		(ofilename) ? ofilename : "stdout");
XX  	exit(1);
XX    }
XX    if (bs) {
XX  	ibs = obs = bs;
XX! 	if (convert == null) flag++;
XX    }
XX    if (ibs == 0) {
XX  	fprintf(stderr, "dd: ibs cannot be zero\n");
XX***************
XX*** 241,286 ****
XX    }
XX    ibc = obc = cbc = 0;
XX    op = obuf;
XX!   if (signal(SIGINT, SIG_IGN) != SIG_IGN)
XX! 	signal(SIGINT, over);
XX!   for (; skip; skip--)
XX! 	read(ifd, ibuf, ibs);
XX!   for (; nseek; nseek--)
XX! 	lseek(ofd, (long) obs, SEEK_CUR);
XX  outputall:
XX    if (ibc-- == 0) {
XX  	ibc = 0;
XX  	if ((count == 0) || ((nifull + nipartial) != count)) {
XX  		if (convflag & (NOERROR | SYNC))
XX! 			for (iptr = ibuf + ibs; iptr > ibuf;)
XX! 				*--iptr = 0;
XX  		ibc = read(ifd, ibuf, ibs);
XX  	}
XX  	if (ibc == -1) {
XX  		fprintf(stderr, "dd: read error\n");
XX  		if ((convflag & NOERROR) == 0) {
XX  			puto();
XX! 			over();
XX  		}
XX  		ibc = 0;
XX  		for (i = 0; i < ibs; i++)
XX! 			if (ibuf[i] != 0)
XX! 				ibc = i;
XX  		statistics();
XX  	}
XX  	if ((ibc == 0) && (--files <= 0)) {
XX  		puto();
XX! 		over();
XX  	}
XX  	if (ibc != ibs) {
XX  		nipartial++;
XX! 		if (convflag & SYNC)
XX! 			ibc = ibs;
XX! 	} else  nifull++;
XX  	iptr = ibuf;
XX  	i = ibc >> 1;
XX! 	if ((convflag & SWAB) && i)
XX! 		do {
XX  			int temp;
XX  			temp = *iptr++;
XX  			iptr[-1] = *iptr;
XX--- 259,307 ----
XX    }
XX    ibc = obc = cbc = 0;
XX    op = obuf;
XX!   if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, over);
XX!   if (skip != 0) {
XX! 	struct stat st;
XX! 	if (fstat(ifd,&st) < 0 || !(S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
XX! 	   || lseek(ifd, (off_t) ibs * (off_t) skip, SEEK_SET) == (off_t) -1) {
XX! 		do
XX! 			read(ifd, ibuf, ibs);
XX! 		while (--skip != 0);
XX! 	}
XX!   }
XX!   if (nseek != 0) lseek(ofd, (off_t) obs * (off_t) nseek, SEEK_SET);
XX! 
XX  outputall:
XX    if (ibc-- == 0) {
XX  	ibc = 0;
XX  	if ((count == 0) || ((nifull + nipartial) != count)) {
XX  		if (convflag & (NOERROR | SYNC))
XX! 			for (iptr = ibuf + ibs; iptr > ibuf;) *--iptr = 0;
XX  		ibc = read(ifd, ibuf, ibs);
XX  	}
XX  	if (ibc == -1) {
XX  		fprintf(stderr, "dd: read error\n");
XX  		if ((convflag & NOERROR) == 0) {
XX  			puto();
XX! 			over(0);
XX  		}
XX  		ibc = 0;
XX  		for (i = 0; i < ibs; i++)
XX! 			if (ibuf[i] != 0) ibc = i;
XX  		statistics();
XX  	}
XX  	if ((ibc == 0) && (--files <= 0)) {
XX  		puto();
XX! 		over(0);
XX  	}
XX  	if (ibc != ibs) {
XX  		nipartial++;
XX! 		if (convflag & SYNC) ibc = ibs;
XX! 	} else
XX! 		nifull++;
XX  	iptr = ibuf;
XX  	i = ibc >> 1;
XX! 	if ((convflag & SWAB) && i) do {
XX  			int temp;
XX  			temp = *iptr++;
XX  			iptr[-1] = *iptr;
XX***************
XX*** 293,301 ****
XX  		ibc = 0;
XX  	}
XX  	goto outputall;
XX!   }       
XX    i = *iptr++ & 0377;
XX!   (*convert)(i);
XX    goto outputall;
XX  }
XX  
XX--- 314,322 ----
XX  		ibc = 0;
XX  	}
XX  	goto outputall;
XX!   }
XX    i = *iptr++ & 0377;
XX!   (*convert) (i);
XX    goto outputall;
XX  }
XX  
XX***************
XX*** 313,326 ****
XX    return(ans);
XX  }
XX  
XX! cnull(c)
XX  int c;
XX  {
XX    c = ulcase(c);
XX    null(c);
XX  }
XX  
XX! null(c)
XX  int c;
XX  {
XX    *op++ = c;
XX--- 334,347 ----
XX    return(ans);
XX  }
XX  
XX! void cnull(c)
XX  int c;
XX  {
XX    c = ulcase(c);
XX    null(c);
XX  }
XX  
XX! void null(c)
XX  int c;
XX  {
XX    *op++ = c;
XX***************
XX*** 330,336 ****
XX    }
XX  }
XX  
XX! extra()
XX  {
XX    if (++cbc >= cbs) {
XX  	null('\n');
XX--- 351,357 ----
XX    }
XX  }
XX  
XX! void extra()
XX  {
XX    if (++cbc >= cbs) {
XX  	null('\n');
XX***************
XX*** 339,345 ****
XX    }
XX  }
XX  
XX! void over()
XX  {
XX    statistics();
XX    exit(0);
XX--- 360,367 ----
XX    }
XX  }
XX  
XX! void over(dummy)
XX! int dummy;			/* to keep the compiler happy */
XX  {
XX    statistics();
XX    exit(0);
X/
Xecho x - df.c.d
Xsed '/^X/s///' > df.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/df.c  crc=46980   4834	Sun Apr 25 21:34:53 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/df.c  crc=59613   5541	Sun Dec 20 23:53:24 1992
XX***************
XX*** 6,13 ****
XX  #include <fcntl.h>
XX  #include <errno.h>
XX  #include <unistd.h>
XX! #include <stdio.h>
XX  
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX--- 6,15 ----
XX  #include <fcntl.h>
XX  #include <errno.h>
XX  #include <unistd.h>
XX! #include <stdlib.h>
XX! #include <string.h>
XX  
XX+ #include <minix/minlib.h>
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX***************
XX*** 15,65 ****
XX  #include "../fs/type.h"
XX  #include "../fs/super.h"
XX  
XX! #define block_nr long		/* Allow big devices even if FS doesn't */
XX  
XX- extern int errno;
XX- long bit_count();
XX- char *mtab = "/etc/mtab";
XX- 
XX  #define REPORT 0
XX  #define SILENT 1
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    register int i;
XX  
XX    sync();			/* have to make sure disk is up-to-date */
XX!   fprintf(stdout, "\nDevice     Inodes  Inodes  Inodes       Blocks  Blocks  Blocks    ");
XX    if (argc == 1)
XX! 	fprintf(stdout, "Mounted on\n");
XX    else
XX  	fprintf(stdout, "\n");
XX  
XX!   fprintf(stdout, "           total   used    free         total   used    free\n");
XX!   fprintf(stdout, "           -----   -----   -----        -----   -----   -----\n");
XX  
XX    if (argc == 1) defaults();
XX  
XX!   for (i = 1; i < argc; i++) df(argv[i], "", SILENT);
XX!   exit(0);
XX  }
XX  
XX  
XX  #define percent(num, tot)  ((int) ((100L * (num) + ((tot) - 1)) / (tot)))
XX  
XX! df(name, mnton, silent)
XX! char *name, *mnton;
XX  int silent;
XX  {
XX!   register int fd;
XX!   ino_t i_count;
XX!   long z_count;
XX!   block_nr totblocks, busyblocks;
XX!   int i, j;
XX!   char buf[BLOCK_SIZE], *s0;
XX    struct super_block super, *sp;
XX  
XX    if ((fd = open(name, O_RDONLY)) < 0) {
XX--- 17,77 ----
XX  #include "../fs/type.h"
XX  #include "../fs/super.h"
XX  
XX! #include <stdio.h>
XX  
XX  #define REPORT 0
XX  #define SILENT 1
XX+ #define NL    12		/* name length */
XX  
XX+ _PROTOTYPE(int main, (int argc, char *argv []));
XX+ _PROTOTYPE(void df, (char *name, char *mnton, char *version, char *rw_flag, int silent ));
XX+ _PROTOTYPE(bit_t bit_count, (int blocks, bit_t bits, int fd ));
XX+ _PROTOTYPE(void defaults, (void ));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    register int i;
XX  
XX    sync();			/* have to make sure disk is up-to-date */
XX!   fprintf(stdout, "\nDevice     Inodes  Inodes  Inodes     Blocks  Blocks  Blocks");
XX    if (argc == 1)
XX! 	fprintf(stdout, "  Mounted      V Pr\n");
XX    else
XX  	fprintf(stdout, "\n");
XX  
XX!   fprintf(stdout, "           total   used    free       total   used    free");
XX  
XX+   if (argc == 1)
XX+ 	fprintf(stdout, "      on\n");
XX+   else
XX+ 	fprintf(stdout, "\n");
XX+ 
XX+   fprintf(stdout, "           -----   -----   -----      -----   -----   -----");
XX+ 
XX+   if (argc == 1)
XX+ 	fprintf(stdout, "   -------      - --\n");
XX+   else
XX+ 	fprintf(stdout, "\n");
XX+ 
XX    if (argc == 1) defaults();
XX  
XX!   for (i = 1; i < argc; i++) df(argv[i], "", "", "", SILENT);
XX!   return(0);
XX  }
XX  
XX  
XX  #define percent(num, tot)  ((int) ((100L * (num) + ((tot) - 1)) / (tot)))
XX  
XX! void df(name, mnton, version, rw_flag, silent)
XX! char *name, *mnton, *version, *rw_flag;
XX  int silent;
XX  {
XX!   register int j, fd;
XX!   char devname[32];
XX!   bit_t i_count, z_count, b;
XX!   block_t totblocks, busyblocks;
XX    struct super_block super, *sp;
XX  
XX    if ((fd = open(name, O_RDONLY)) < 0) {
XX***************
XX*** 72,91 ****
XX  	}
XX  	return;
XX    }
XX!   lseek(fd, (long) BLOCK_SIZE, SEEK_SET);	/* skip boot block */
XX!   if (read(fd, (char *) &super, SUPER_SIZE) != (int) SUPER_SIZE) {
XX  	fprintf(stderr, "df: Can't read super block of %s\n", name);
XX  	close(fd);
XX  	return;
XX    }
XX!   lseek(fd, (long) BLOCK_SIZE * 2L, SEEK_SET);	/* skip rest of super block */
XX    sp = &super;
XX!   if (sp->s_magic != SUPER_MAGIC) {
XX! 	fprintf(stderr, "df: %s: Not a valid file system\n", name);
XX  	close(fd);
XX  	return;
XX    }
XX!   i_count = (ino_t) bit_count(sp->s_imap_blocks, sp->s_ninodes + 1, fd);
XX    if (i_count == -1) {
XX  	fprintf(stderr, "df: Can't find bit maps of %s\n", name);
XX  	close(fd);
XX--- 84,108 ----
XX  	}
XX  	return;
XX    }
XX!   lseek(fd, (off_t) BLOCK_SIZE, SEEK_SET);	/* skip boot block */
XX!   if (read(fd, (char *) &super, (unsigned) SUPER_SIZE) != SUPER_SIZE) {
XX  	fprintf(stderr, "df: Can't read super block of %s\n", name);
XX  	close(fd);
XX  	return;
XX    }
XX!   lseek(fd, (off_t) BLOCK_SIZE * 2L, SEEK_SET);	/* skip rest of super block */
XX    sp = &super;
XX!   if (sp->s_magic == SUPER_MAGIC)
XX! 	sp->s_zones = sp->s_nzones;
XX!   else if (sp->s_magic != SUPER_V2) {
XX  	close(fd);
XX+ 	if (sp->s_magic == SUPER_REV || sp->s_magic == SUPER_V2_REV) 
XX+ 		fprintf(stderr, "df: %s: Foreign (byte-swapped) file system\n", name);
XX+ 	else
XX+ 		fprintf(stderr, "df: %s: Not a valid file system\n", name);
XX  	return;
XX    }
XX!   i_count = bit_count(sp->s_imap_blocks, (bit_t) sp->s_ninodes + 1, fd);
XX    if (i_count == -1) {
XX  	fprintf(stderr, "df: Can't find bit maps of %s\n", name);
XX  	close(fd);
XX***************
XX*** 93,107 ****
XX    }
XX    i_count--;			/* There is no inode 0. */
XX  
XX!   z_count = bit_count(sp->s_zmap_blocks, sp->s_nzones, fd);
XX    if (z_count == -1) {
XX  	fprintf(stderr, "df: Can't find bit maps of %s\n", name);
XX  	close(fd);
XX  	return;
XX    }
XX!   totblocks = (block_nr) sp->s_nzones << sp->s_log_zone_size;
XX!   busyblocks = (block_nr) z_count << sp->s_log_zone_size;
XX  
XX    /* Print results. */
XX    fprintf(stdout, "%s", name);
XX    j = 10 - strlen(name);
XX--- 110,132 ----
XX    }
XX    i_count--;			/* There is no inode 0. */
XX  
XX!   b = (bit_t) sp->s_zones - (sp->s_firstdatazone - 1);
XX!   z_count = bit_count(sp->s_zmap_blocks, b, fd);
XX    if (z_count == -1) {
XX  	fprintf(stderr, "df: Can't find bit maps of %s\n", name);
XX  	close(fd);
XX  	return;
XX    }
XX!   totblocks = (block_t) sp->s_zones << sp->s_log_zone_size;
XX!   z_count += sp->s_firstdatazone - 1;
XX!   busyblocks = (block_t) z_count << sp->s_log_zone_size;
XX  
XX+   /* Truncate device name to NL chars. */
XX+   for (j = 0; j < NL; j++) devname[j] = ' ';
XX+   strncpy(devname, (strcmp(mnton, "/") == 0 ? "(root dev)" : mnton), (size_t)NL);
XX+   for (j = 0; j < NL; j++) if(devname[j] == '\0') devname[j] = ' ';
XX+   devname[NL] = '\0';
XX+ 
XX    /* Print results. */
XX    fprintf(stdout, "%s", name);
XX    j = 10 - strlen(name);
XX***************
XX*** 110,141 ****
XX  	j--;
XX    }
XX  
XX!   fprintf(stdout, " %5u   %5u   %5u      %7ld %7ld %7ld     %s\n",
XX  	sp->s_ninodes,		/* total inodes */
XX  	i_count,		/* inodes used */
XX  	sp->s_ninodes - i_count,/* inodes free */
XX  
XX  	totblocks,		/* total blocks */
XX  	busyblocks,		/* blocks used */
XX! 	totblocks - busyblocks,	/* blocsk free */
XX  
XX! 	strcmp(mnton, "device") == 0 ? "(root dev)" : mnton
XX! 
XX  	);
XX    close(fd);
XX  }
XX  
XX! long bit_count(blocks, bits, fd)
XX! unsigned blocks;
XX! unsigned bits;
XX  int fd;
XX  {
XX    register char *wptr;
XX    register int i;
XX    register int b;
XX!   register unsigned busy;	/* bits fits in unsigned, so busy does too */
XX    register char *wlim;
XX-   register int j;
XX    static char buf[BLOCK_SIZE];
XX    static unsigned bits_in_char[1 << CHAR_BIT];
XX  
XX--- 135,167 ----
XX  	j--;
XX    }
XX  
XX!  
XX!   fprintf(stdout, " %5u   %5ld   %5ld    %7ld %7ld %7ld   %s %s %s\n",
XX  	sp->s_ninodes,		/* total inodes */
XX  	i_count,		/* inodes used */
XX  	sp->s_ninodes - i_count,/* inodes free */
XX  
XX  	totblocks,		/* total blocks */
XX  	busyblocks,		/* blocks used */
XX! 	totblocks - busyblocks,	/* blocks free */
XX  
XX! 	devname,		/* mounted on */
XX! 	version,		/* 1 or 2 */
XX! 	rw_flag			/* rw or ro */
XX  	);
XX    close(fd);
XX  }
XX  
XX! bit_t bit_count(blocks, bits, fd)
XX! int blocks;
XX! bit_t bits;
XX  int fd;
XX  {
XX    register char *wptr;
XX    register int i;
XX    register int b;
XX!   register bit_t busy;
XX    register char *wlim;
XX    static char buf[BLOCK_SIZE];
XX    static unsigned bits_in_char[1 << CHAR_BIT];
XX  
XX***************
XX*** 149,162 ****
XX    /* Loop on blocks, reading one at a time and counting bits. */
XX    busy = 0;
XX    for (i = 0; i < blocks && bits != 0; i++) {
XX! 	if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) return(-1);
XX  
XX  	wptr = &buf[0];
XX  	if (bits >= CHAR_BIT * BLOCK_SIZE) {
XX  		wlim = &buf[BLOCK_SIZE];
XX  		bits -= CHAR_BIT * BLOCK_SIZE;
XX  	} else {
XX! 		b = bits / CHAR_BIT;	/* whole chars in map */
XX  		wlim = &buf[b];
XX  		bits -= b * CHAR_BIT;	/* bits in last char, if any */
XX  		b = *wlim & ((1 << bits) - 1);	/* bit pattern from last ch */
XX--- 175,188 ----
XX    /* Loop on blocks, reading one at a time and counting bits. */
XX    busy = 0;
XX    for (i = 0; i < blocks && bits != 0; i++) {
XX! 	if (read(fd, buf, (unsigned) BLOCK_SIZE) != BLOCK_SIZE) return(-1);
XX  
XX  	wptr = &buf[0];
XX  	if (bits >= CHAR_BIT * BLOCK_SIZE) {
XX  		wlim = &buf[BLOCK_SIZE];
XX  		bits -= CHAR_BIT * BLOCK_SIZE;
XX  	} else {
XX! 		b = (int) bits / CHAR_BIT;	/* whole chars in map */
XX  		wlim = &buf[b];
XX  		bits -= b * CHAR_BIT;	/* bits in last char, if any */
XX  		b = *wlim & ((1 << bits) - 1);	/* bit pattern from last ch */
XX***************
XX*** 172,216 ****
XX  }
XX  
XX  
XX- char mtabbuf[1024];
XX- int mtabcnt;
XX  
XX! getname(d, m)
XX! char **d, **m;
XX  {
XX-   int c;
XX-   static char *mp = mtabbuf;
XX- 
XX-   *d = mp;
XX-   *m = "";
XX- 
XX-   do {
XX- 	if (--mtabcnt < 0) exit(0);
XX- 	c = *mp++;
XX- 	if (c == ' ') {
XX- 		mp[-1] = 0;
XX- 		*m = mp;
XX- 	}
XX-   } while (c != '\n');
XX-   mp[-1] = 0;
XX- }
XX- 
XX-     defaults()
XX- {
XX  /* Use the root file system and all mounted file systems. */
XX  
XX!   char *dev, *dir;
XX  
XX!   close(0);
XX!   if (open(mtab, O_RDONLY) < 0 || (mtabcnt = read(0, mtabbuf, sizeof(mtabbuf))) <= 0) {
XX! 	fprintf(stderr, "df: cannot read %s\n", mtab);
XX! 	exit(1);
XX!   }
XX  
XX    /* Read /etc/mtab and iterate on the lines. */
XX    while (1) {
XX! 	getname(&dev, &dir);	/* getname exits upon hitting EOF */
XX! 	df(dev, dir, REPORT);
XX    }
XX  
XX  }
XX--- 198,219 ----
XX  }
XX  
XX  
XX  
XX! void defaults()
XX  {
XX  /* Use the root file system and all mounted file systems. */
XX  
XX!   char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
XX  
XX!   /* Read in /etc/mtab. */
XX!   if (load_mtab("df") < 0) exit(1);
XX  
XX    /* Read /etc/mtab and iterate on the lines. */
XX    while (1) {
XX! 	get_mtab_entry(special, mounted_on, version, rw_flag);
XX! 	if (special[0] == '\0') exit(0);
XX! 	df(special, mounted_on, version, rw_flag, REPORT);
XX    }
XX  
XX  }
XX+ 
X/
Xecho x - dhrystone.c.d
Xsed '/^X/s///' > dhrystone.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/dhrystone.c  crc=29278  11212	Sun Apr 25 21:34:53 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/dhrystone.c  crc=31105  12078	Mon Mar  8 22:11:35 1993
XX***************
XX*** 86,114 ****
XX   */
XX  
XX  
XX  /* Accuracy of timings and human fatigue controlled by next two lines */
XX  #define LOOPS	50000		/* Use this for slow or 16 bit machines */
XX! /*#define LOOPS	500000		/* Use this for faster machines */
XX  
XX  
XX  /* Compiler dependent options */
XX  #define	NOENUM			/* Define if compiler has no enum's */
XX! #define	NOSTRUCTASSIGN		/* Define if compiler can't assign structures */
XX  
XX  
XX  /* Define only one of the next two defines */
XX! /*#define TIMES			/* Use times(2) time function */
XX  #define TIME			/* Use time(2) time function */
XX  
XX  
XX  /* Define the granularity of your times(2) function (when used) */
XX! /*#define HZ	50		/* times(2) returns 1/50 second (europe?) */
XX  #define HZ	60		/* times(2) returns 1/60 second (most) */
XX! /*#define HZ	100		/* times(2) returns 1/100 second (WECo) */
XX  
XX  
XX  /* For compatibility with goofed up version */
XX! /*#undef GOOF			/* Define if you want the goofed up version */
XX  
XX  
XX  #ifdef GOOF
XX--- 86,120 ----
XX   */
XX  
XX  
XX+ #include <sys/types.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <time.h>
XX+ #include <stdio.h>
XX+ 
XX  /* Accuracy of timings and human fatigue controlled by next two lines */
XX  #define LOOPS	50000		/* Use this for slow or 16 bit machines */
XX! /*#define LOOPS	500000 */	/* Use this for faster machines */
XX  
XX  
XX  /* Compiler dependent options */
XX  #define	NOENUM			/* Define if compiler has no enum's */
XX! /* #define NOSTRUCTASSIGN */	/* Define if compiler can't assign structures*/
XX  
XX  
XX  /* Define only one of the next two defines */
XX! /*#define TIMES		*/	/* Use times(2) time function */
XX  #define TIME			/* Use time(2) time function */
XX  
XX  
XX  /* Define the granularity of your times(2) function (when used) */
XX! /*#define HZ	50 */		/* times(2) returns 1/50 second (europe?) */
XX  #define HZ	60		/* times(2) returns 1/60 second (most) */
XX! /*#define HZ	100 	*/	/* times(2) returns 1/100 second (WECo) */
XX  
XX  
XX  /* For compatibility with goofed up version */
XX! /*#undef GOOF		*/	/* Define if you want the goofed up version */
XX  
XX  
XX  #ifdef GOOF
XX***************
XX*** 136,145 ****
XX  typedef enum {
XX    Ident1, Ident2, Ident3, Ident4, Ident5
XX  } Enumeration;
XX- 
XX  #endif
XX  
XX- 
XX  typedef int OneToThirty;
XX  typedef int OneToFifty;
XX  typedef char CapitalLetter;
XX--- 142,149 ----
XX***************
XX*** 147,153 ****
XX  typedef int Array1Dim[51];
XX  typedef int Array2Dim[51][51];
XX  
XX- 
XX  struct Record {
XX    struct Record *PtrComp;
XX    Enumeration Discr;
XX--- 151,156 ----
XX***************
XX*** 156,191 ****
XX    String30 StringComp;
XX  };
XX  
XX- 
XX  typedef struct Record RecordType;
XX  typedef RecordType *RecordPtr;
XX  typedef int boolean;
XX  
XX  
XX  #define	NULL		0
XX  #define	TRUE		1
XX  #define	FALSE		0
XX  
XX- 
XX  #ifndef REG
XX  #define	REG
XX  #endif
XX  
XX  
XX- extern Enumeration Func1();
XX- extern boolean Func2();
XX- 
XX- 
XX  #ifdef TIMES
XX- #include <sys/types.h>
XX  #include <sys/times.h>
XX  #endif
XX  
XX  
XX! main()
XX  {
XX    Proc0();
XX!   exit(0);
XX  }
XX  
XX  
XX--- 159,208 ----
XX    String30 StringComp;
XX  };
XX  
XX  typedef struct Record RecordType;
XX  typedef RecordType *RecordPtr;
XX  typedef int boolean;
XX  
XX+ #ifdef NULL
XX+ #undef NULL
XX+ #endif
XX  
XX  #define	NULL		0
XX  #define	TRUE		1
XX  #define	FALSE		0
XX  
XX  #ifndef REG
XX  #define	REG
XX  #endif
XX  
XX  
XX  #ifdef TIMES
XX  #include <sys/times.h>
XX  #endif
XX  
XX+ _PROTOTYPE(int main, (void));
XX+ _PROTOTYPE(void Proc0, (void));
XX+ _PROTOTYPE(void Proc1, (RecordPtr PtrParIn));
XX+ _PROTOTYPE(void Proc2, (OneToFifty *IntParIO));
XX+ _PROTOTYPE(void Proc3, (RecordPtr *PtrParOut));
XX+ _PROTOTYPE(void Proc4, (void));
XX+ _PROTOTYPE(void Proc5, (void));
XX+ _PROTOTYPE(void Proc6, (Enumeration EnumParIn, Enumeration *EnumParOut));
XX+ _PROTOTYPE(void Proc7, (OneToFifty IntParI1, OneToFifty IntParI2, 
XX+ 						OneToFifty *IntParOut));
XX+ _PROTOTYPE(void Proc8, (Array1Dim Array1Par, Array2Dim Array2Par, 
XX+ 				OneToFifty IntParI1, OneToFifty IntParI2));
XX+ /*_PROTOTYPE(Enumeration Func1,(CapitalLetter CharPar1, CapitalLetter CharPar2));*/
XX+ _PROTOTYPE(boolean Func2, (String30 StrParI1, String30 StrParI2));
XX+ _PROTOTYPE(boolean Func3, (Enumeration EnumParIn));
XX  
XX! _PROTOTYPE(Enumeration Func1, (int CharPar1, int CharPar2));
XX! 
XX! 
XX! int main()
XX  {
XX    Proc0();
XX!   return(0);
XX  }
XX  
XX  
XX***************
XX*** 200,221 ****
XX  RecordPtr PtrGlbNext;
XX  
XX  
XX! Proc0()
XX  {
XX    OneToFifty IntLoc1;
XX    REG OneToFifty IntLoc2;
XX    OneToFifty IntLoc3;
XX-   REG char CharLoc;
XX    REG char CharIndex;
XX    Enumeration EnumLoc;
XX    String30 String1Loc;
XX    String30 String2Loc;
XX!   extern char *malloc();
XX!   register unsigned int i;
XX  
XX  
XX  #ifdef TIME
XX-   long time();
XX    long starttime;
XX    long benchtime;
XX    long nulltime;
XX--- 217,235 ----
XX  RecordPtr PtrGlbNext;
XX  
XX  
XX! void Proc0()
XX  {
XX    OneToFifty IntLoc1;
XX    REG OneToFifty IntLoc2;
XX    OneToFifty IntLoc3;
XX    REG char CharIndex;
XX    Enumeration EnumLoc;
XX    String30 String1Loc;
XX    String30 String2Loc;
XX!   register unsigned long i;
XX  
XX  
XX  #ifdef TIME
XX    long starttime;
XX    long benchtime;
XX    long nulltime;
XX***************
XX*** 320,326 ****
XX  }
XX  
XX  
XX! Proc1(PtrParIn)
XX  REG RecordPtr PtrParIn;
XX  {
XX  #define	NextRecord	(*(PtrParIn->PtrComp))
XX--- 334,340 ----
XX  }
XX  
XX  
XX! void Proc1(PtrParIn)
XX  REG RecordPtr PtrParIn;
XX  {
XX  #define	NextRecord	(*(PtrParIn->PtrComp))
XX***************
XX*** 330,336 ****
XX    PtrParIn->IntComp = 5;
XX    NextRecord.IntComp = PtrParIn->IntComp;
XX    NextRecord.PtrComp = PtrParIn->PtrComp;
XX!   Proc3(NextRecord.PtrComp);
XX    if (NextRecord.Discr == Ident1) {
XX  	NextRecord.IntComp = 6;
XX  	Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp);
XX--- 344,350 ----
XX    PtrParIn->IntComp = 5;
XX    NextRecord.IntComp = PtrParIn->IntComp;
XX    NextRecord.PtrComp = PtrParIn->PtrComp;
XX!   Proc3((RecordPtr *)NextRecord.PtrComp);
XX    if (NextRecord.Discr == Ident1) {
XX  	NextRecord.IntComp = 6;
XX  	Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp);
XX***************
XX*** 344,350 ****
XX  }
XX  
XX  
XX! Proc2(IntParIO)
XX  OneToFifty *IntParIO;
XX  {
XX    REG OneToFifty IntLoc;
XX--- 358,364 ----
XX  }
XX  
XX  
XX! void Proc2(IntParIO)
XX  OneToFifty *IntParIO;
XX  {
XX    REG OneToFifty IntLoc;
XX***************
XX*** 363,369 ****
XX  }
XX  
XX  
XX! Proc3(PtrParOut)
XX  RecordPtr *PtrParOut;
XX  {
XX    if (PtrGlb != NULL)
XX--- 377,383 ----
XX  }
XX  
XX  
XX! void Proc3(PtrParOut)
XX  RecordPtr *PtrParOut;
XX  {
XX    if (PtrGlb != NULL)
XX***************
XX*** 374,380 ****
XX  }
XX  
XX  
XX! Proc4()
XX  {
XX    REG boolean BoolLoc;
XX  
XX--- 388,394 ----
XX  }
XX  
XX  
XX! void Proc4()
XX  {
XX    REG boolean BoolLoc;
XX  
XX***************
XX*** 385,401 ****
XX  }
XX  
XX  
XX! Proc5()
XX  {
XX    Char1Glob = 'A';
XX    BoolGlob = FALSE;
XX  }
XX  
XX  
XX! extern boolean Func3();
XX! 
XX! 
XX! Proc6(EnumParIn, EnumParOut)
XX  REG Enumeration EnumParIn;
XX  REG Enumeration *EnumParOut;
XX  {
XX--- 399,412 ----
XX  }
XX  
XX  
XX! void Proc5()
XX  {
XX    Char1Glob = 'A';
XX    BoolGlob = FALSE;
XX  }
XX  
XX  
XX! void Proc6(EnumParIn, EnumParOut)
XX  REG Enumeration EnumParIn;
XX  REG Enumeration *EnumParOut;
XX  {
XX***************
XX*** 417,423 ****
XX  }
XX  
XX  
XX! Proc7(IntParI1, IntParI2, IntParOut)
XX  OneToFifty IntParI1;
XX  OneToFifty IntParI2;
XX  OneToFifty *IntParOut;
XX--- 428,434 ----
XX  }
XX  
XX  
XX! void Proc7(IntParI1, IntParI2, IntParOut)
XX  OneToFifty IntParI1;
XX  OneToFifty IntParI2;
XX  OneToFifty *IntParOut;
XX***************
XX*** 430,436 ****
XX  }
XX  
XX  
XX! Proc8(Array1Par, Array2Par, IntParI1, IntParI2)
XX  Array1Dim Array1Par;
XX  Array2Dim Array2Par;
XX  OneToFifty IntParI1;
XX--- 441,447 ----
XX  }
XX  
XX  
XX! void Proc8(Array1Par, Array2Par, IntParI1, IntParI2)
XX  Array1Dim Array1Par;
XX  Array2Dim Array2Par;
XX  OneToFifty IntParI1;
X/
Xecho x - diff.c.d
Xsed '/^X/s///' > diff.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/diff.c  crc=33684   6080	Sun Apr 25 21:34:53 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/diff.c  crc=10827  31053	Sun Jan 17 20:52:39 1993
XX***************
XX*** 1,86 ****
XX  /* diff  - print differences between 2 files	  Author: Erik Baalbergen */
XX  
XX! /* Poor man's implementation of diff(1)
XX!  - no options available
XX!  - may give more output than other diffs, due to the straight-forward algorithm
XX!  - runs out of memory if the differing chunks become too large
XX!  - input line length should not exceed LINELEN; longer lines are truncated,
XX!    while only the first LINELEN characters are compared
XX! 
XX!  - Bug fixes by Rick Thomas Sept. 1989
XX! 
XX!  Please report bugs and suggestions to erikb@cs.vu.nl
XX  */
XX  
XX  #include <stdio.h>
XX  
XX! #define LINELEN 128
XX  
XX! FILE *fopen();
XX  
XX- char *prog;
XX- int diffs = 0;
XX  
XX! main(argc, argv)
XX  char **argv;
XX  {
XX!   FILE *fp1 = NULL, *fp2 = NULL;
XX  
XX!   prog = *argv++;
XX!   if (argc != 3) fatal("Usage: %s file1 file2", prog);
XX!   if (strcmp(argv[0], "-") == 0)
XX! 	fp1 = stdin;
XX!   else if (strcmp(argv[1], "-") == 0)
XX! 	fp2 = stdin;
XX!   if (fp1 == NULL && (fp1 = fopen(argv[0], "r")) == NULL)
XX! 	fatal("can't read %s", argv[0]);
XX!   if (fp2 == NULL && (fp2 = fopen(argv[1], "r")) == NULL)
XX! 	fatal("can't read %s", argv[1]);
XX!   diff(fp1, fp2);
XX!   exit(diffs > 0);
XX  }
XX  
XX! fatal(fmt, s)
XX! char *fmt, *s;
XX  {
XX!   fprintf(stderr, "%s: ", prog);
XX    fprintf(stderr, fmt, s);
XX    fprintf(stderr, "\n");
XX    exit(2);
XX  }
XX  
XX! /* The line module */
XX! char *malloc();
XX! char *fgets();
XX  
XX  struct line {
XX!   struct line *l_next;
XX!   char l_text[LINELEN + 2];
XX!   char l_eof;
XX  };
XX  
XX  struct line *freelist = 0;
XX  #define stepup(ll) ( ((ll) && ((ll)->l_eof==0)) ? (ll)->l_next : (ll) )
XX  
XX! struct line *
XX!  new_line()
XX  {
XX    register struct line *l;
XX  
XX!   if (l = freelist)
XX  	freelist = freelist->l_next;
XX!   else if ((l = (struct line *) malloc(sizeof(struct line))) == 0)
XX! 	fatal("out of memory");
XX    return l;
XX  }
XX  
XX! free_line(l)
XX  register struct line *l;
XX  {
XX    l->l_next = freelist;
XX    freelist = l;
XX  }
XX  
XX  int equal_line(l1, l2)
XX  struct line *l1, *l2;
XX  {
XX--- 1,442 ----
XX  /* diff  - print differences between 2 files	  Author: Erik Baalbergen */
XX  
XX! /* Poor man's implementation of diff(1) 	- no options available
XX! * 	- may give more output than other diffs,
XX! *	  due to the straight-forward algorithm
XX! * 	- runs out of memory if the differing chunks become too large
XX! * 	- input line length should not exceed LINELEN; longer lines are
XX! *	  truncated, while only the first LINELEN characters are compared
XX! *
XX! * 	- Bug fixes by Rick Thomas Sept. 1989
XX! *
XX! * Please report bugs and suggestions to erikb@cs.vu.nl
XX! *------------------------------------------------------------------------------
XX! * Changed diff to conform to POSIX 1003.2 ( Draft 11) by Thomas Brupbacher
XX! * ( tobr@mw.lpc.ethz.ch).
XX! *
XX! * To incorporate the context diff option -c in the program, the source code
XX! * for the program cdiff has been copied to the end of this program. Only
XX! * slight modifications for the cdiff code to work within the program diff
XX! * were made( e.g. main() -> context_diff()).
XX! *
XX! * New options:
XX! * -c, -C n where n=0,1,...:
XX! *  	produces a context diff as the program cdiff. The default is to
XX! *  	print 3 lines of context, this value can be changed with -C
XX! *	( e.g. -C 5 prints five lines of context.)
XX! * -e :	Prints an ed script, so you can convert <file1> to <file2> with
XX! *  	the command ed <file1> < `diff -e <file1> <file2>`.
XX! * -b :	Causes trailing blanks to be ignored and spaces of multiple blanks
XX! *  	to be reduced to one blank before comparison.
XX! *-----------------------------------------------------------------------------
XX  */
XX  
XX+ #include <stdlib.h>
XX+ #include <limits.h>		/* NAME_MAX for maximal filename length	 */
XX+ #include <string.h>		/* string manipulation			 */
XX+ #include <sys/types.h>
XX+ #include <sys/stat.h>
XX+ #include <ctype.h>
XX+ #include <time.h>
XX+ #include <dirent.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX! /* These definitions are needed only to suppress warning messages. */
XX! #define Nullfp 		((FILE*)0)
XX! #define Nullch 		((char*)0)
XX! #define NullStructLine	((struct line *)0)
XX  
XX! #define LINELEN 128		/* max line length included in diff	 */
XX  
XX  
XX! #define NOT_SET 0		/* Defines to characterise if a flag 	 */
XX! #define SET	1		/* is set				 */
XX! 
XX!  /* Indexes of the warning-message array	 */
XX! #define EXCLUSIVE_OPTIONS	0
XX! #define CANNOT_OPEN_FILE	1
XX! 
XX!  /* Used to define the mode 		 */
XX! typedef enum {
XX!   undefined, context, ed_mode
XX! } MODE;
XX! 
XX!  /* Global variables for the 'normal' diff part	 */
XX! char *progname;			/* program name	(on command line)	 */
XX! int diffs = 0;			/* number of differences		 */
XX! MODE mode;			/* which mode is used			 */
XX! int severe_error;		/* nonzero after severe, non-fatal error */
XX! 
XX! /* The following global variables are used with the -r option:
XX!  * for every pair of files that are different, a "command line" of the
XX!  * form "diff <options> <oldfile> <newfile>" is printed before the real
XX!  * output starts.							 */
XX! int firstoutput = 1;		/* flag to print one time		 */
XX! char options_string[10];	/* string to hold command line options 	 */
XX! char oldfile[PATH_MAX];		/* first file				 */
XX! char newfile[PATH_MAX];		/* second file				 */
XX! 
XX! 
XX!  /* Global variables for the command-line options */
XX! int trim_blanks = NOT_SET;	/* SET if -b specified	 		 */
XX! int recursive_dir = NOT_SET;	/* SET if -r specified	 		 */
XX! int context_lines = 3;		/* numbers of lines in a context	 */
XX! static int offset;		/* offset of the actual line number for -e */
XX! 
XX!  /* Function prototypes for the functions in this file	 */
XX! struct f;
XX! _PROTOTYPE(int main, (int argc, char **argv ));
XX! _PROTOTYPE(void process_command_line, (int argc, char **argv ));
XX! _PROTOTYPE(void analyse_input_files, (char *arg1, char *arg2, char *input1, 
XX! 							char *input2 ));
XX! _PROTOTYPE(void diff, (char *filename1, char *filename2 ));
XX! _PROTOTYPE(FILE *check_file, (char *name ));
XX! _PROTOTYPE(void build_option_string, (void ));
XX! _PROTOTYPE(void fatal_error, (char *fmt, char *s ));
XX! _PROTOTYPE(void warn, (int number, char *string ));
XX! _PROTOTYPE(void trimming_blanks, (char *l_text ));
XX! _PROTOTYPE(char *filename, (char *path_string));
XX! _PROTOTYPE(struct line *new_line, (int size ));
XX! _PROTOTYPE(void free_line, (struct line *l ));
XX! _PROTOTYPE(int equal_line, (struct line *l1, struct line *l2 ));
XX! _PROTOTYPE(int equal_3, (struct line *l1, struct line *l2 ));
XX! _PROTOTYPE(struct line *read_line, (FILE *fp ));
XX! _PROTOTYPE(void advance, (struct f *f ));
XX! _PROTOTYPE(void aside, (struct f *f, struct line *l ));
XX! _PROTOTYPE(struct line *next, (struct f *f ));
XX! _PROTOTYPE(void init_f, (struct f *f, FILE *fp ));
XX! _PROTOTYPE(void update, (struct f *f, char *s ));
XX! _PROTOTYPE(void __diff, (FILE *fp1, FILE *fp2 ));
XX! _PROTOTYPE(void differ, (struct f *f1, struct f *f2 ));
XX! _PROTOTYPE(int wlen, (struct f *f ));
XX! _PROTOTYPE(void range, (int a, int b ));
XX! _PROTOTYPE(void cdiff, (char *old, char *new, FILE *file1, FILE *file2 ));
XX! _PROTOTYPE(void dumphunk, (void ));
XX! _PROTOTYPE(char *getold, (int targ ));
XX! _PROTOTYPE(char *getnew, (int targ ));
XX! _PROTOTYPE(int isdir, (char *path ));
XX! _PROTOTYPE(void diff_recursive, (char *dir1, char *dir2 ));
XX! _PROTOTYPE(void file_type_error, (char *filename1, char *filename2, 
XX! 			struct stat *statbuf1, struct stat *statbuf2 ));
XX! _PROTOTYPE(void *xmalloc, (size_t size));
XX! _PROTOTYPE(void *xrealloc, (void *ptr, size_t size));
XX! 
XX! int main(argc, argv)
XX! int argc;
XX  char **argv;
XX  {
XX!   char file1[PATH_MAX], file2[PATH_MAX];
XX!   extern int optind;		/* index of the current string in argv	 */
XX  
XX!   progname = argv[0];
XX!   process_command_line(argc, argv);
XX! 
XX!   analyse_input_files(argv[optind], argv[optind + 1], file1, file2);
XX!   optind++;
XX! 
XX!   if (recursive_dir == SET) {
XX! 	build_option_string();
XX! 	diff_recursive(file1, file2);
XX!   } else {
XX! 	diff(file1, file2);
XX!   }
XX! 
XX!   return(severe_error ? 2 : diffs > 0 ? 1 : 0);
XX  }
XX  
XX! /* Process the command line and set the flags for the different
XX!  * options. the processing of the command line is done with the
XX!  * getopt() library function. a minimal error processing is done
XX!  * for the number of command line arguments.				 */
XX! void process_command_line(argc, argv)
XX! int argc;			/* number of arguments on command line	 */
XX! char **argv;			/* ** to arguments on command line	 */
XX  {
XX!   int c;
XX!   extern char *optarg;		/* points to string with options	 */
XX!   extern int optind;		/* index of the current string in argv	 */
XX! 
XX!   /* Are there enough arguments?		 */
XX!   if (argc < 3) {
XX! 	fatal_error("Usage: %s [-c|-e|-C n][-br] file1 file2\n", progname);
XX!   }
XX! 
XX!   /* Process all options using getopt()	 */
XX!   while ((c = getopt(argc, argv, "ceC:br")) != -1) {
XX! 	switch (c) {
XX! 	    case 'c':
XX! 		if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "c");
XX! 		mode = context;
XX! 		context_lines = 3;
XX! 		break;
XX! 	    case 'e':
XX! 		if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "e");
XX! 		mode = ed_mode;
XX! 		break;
XX! 	    case 'C':
XX! 		if (mode != undefined) warn(EXCLUSIVE_OPTIONS, "C");
XX! 		mode = context;
XX! 		context_lines = atoi(optarg);
XX! 		break;
XX! 	    case 'b':	trim_blanks = SET;	break;
XX! 	    case 'r':	recursive_dir = SET;	break;
XX! 	    case '?':
XX! 		exit(2);
XX! 	}
XX!   }
XX! 
XX!   /* We should have two arguments left	 */
XX!   if ((argc - optind) != 2)
XX! 	fatal_error("Need exactly two input file-names!\n", "");
XX! }
XX! 
XX! /* Analyse_input_files takes the two input files on the command line
XX!  * and decides what to do. returns the (corrected) filenames that
XX!  * can be used to call diff().
XX!  * if two directories are given, then a recursive diff is done.
XX!  * one directory and one filename compares the file with <filename>
XX!  * in the directory <directory> with <filename>.
XX!  * if two filenames are specified, no special action takes place.
XX!  */
XX! void analyse_input_files(arg1, arg2, input1, input2)
XX! char *arg1, *arg2;		/* filenames on the command line	 */
XX! char *input1, *input2;		/* filenames to be used with diff()	 */
XX! {
XX!   int stat1 = 0, stat2 = 0;
XX! 
XX!   if (strcmp(arg1, "-") != 0)
XX! 	stat1 = isdir(arg1);	/* != 0 <-> arg1 is directory		 */
XX!   if (strcmp(arg2, "-") != 0) stat2 = isdir(arg2);
XX! #ifdef DEBUG
XX!   fprintf(stderr, "%s, stat = %d\n", arg1, stat1);
XX!   fprintf(stderr, "%s, stat = %d\n", arg2, stat2);
XX! #endif
XX!   if (stat1 && stat2) {		/* both arg1 and arg2 are directories */
XX! 	recursive_dir = SET;
XX! 	strcpy(input1, arg1);
XX! 	strcpy(input2, arg2);
XX! 	return;
XX!   }
XX!   if (stat1 != 0) {		/* arg1 is a dir, arg2 not		 */
XX! 	if (strcmp(arg2, "-") != 0) {	/* arg2 != stdin	 */
XX! 		strcpy(input1, arg1);
XX! 		strcat(input1, "/");
XX! 		strcat(input1, arg2);
XX! 		strcpy(input2, arg2);
XX! 		return;
XX! 	} else {
XX! 		fatal_error("cannot compare stdin (-) with a directory!", "");
XX! 	}
XX!   }
XX!   if (stat2 != 0) {		/* arg2 is a dir, arg1 not		 */
XX! 	if (strcmp(arg1, "-") != 0) {	/* arg1 != stdin	 */
XX! 		strcpy(input1, arg1);
XX! 		strcpy(input2, arg2);
XX! 		strcat(input2, "/");
XX! 		strcat(input2, arg1);
XX! 		return;
XX! 	} else {		/* arg1 == stdin			 */
XX! 		fatal_error("cannot compare stdin (-) with a directory!", "");
XX! 	}
XX!   }
XX! 
XX!   /* Both arg1 and arg2 are normal  files	 */
XX!   strcpy(input1, arg1);
XX!   strcpy(input2, arg2);
XX! }
XX! 
XX! /* Diff() is the front end for all modes of the program diff, execpt
XX!  * the recursive_dir option.
XX!  * diff() expects the filenames of the two files to be compared as
XX!  * arguments. the mode is determined from the global variable mode.
XX!  */
XX! void diff(filename1, filename2)
XX! char *filename1, *filename2;
XX! {
XX!   FILE *file1 = check_file(filename1);
XX!   FILE *file2 = check_file(filename2);
XX!   struct stat statbuf1, statbuf2;
XX! 
XX!   if ((file1 != Nullfp) && (file2 != Nullfp)) {
XX! 	/* If we do a recursive diff, then we don't compare block
XX! 	 * special, character special or FIFO special files to any
XX! 	 * file.			  */
XX! 	fstat(fileno(file1), &statbuf1);
XX! 	fstat(fileno(file2), &statbuf2);
XX! 	if ((((statbuf1.st_mode & S_IFREG) != S_IFREG) ||
XX! 	     ((statbuf2.st_mode & S_IFREG) != S_IFREG)) &&
XX! 	    (recursive_dir == SET)) {
XX! 		file_type_error(filename1, filename2, &statbuf1, &statbuf2);
XX! 	} else {
XX! 		switch (mode) {
XX! 		    case context:
XX! 			cdiff(filename1, filename2, file1, file2);
XX! 			break;
XX! 		    case ed_mode:
XX! 		    case undefined:
XX! 			__diff(file1, file2);
XX! 			if (mode == ed_mode) printf("w\n");
XX! 			break;
XX! 		}
XX! 	}
XX!   } else
XX! 	severe_error = 1;
XX!   if (file1 != Nullfp) fclose(file1);
XX!   if (file2 != Nullfp) fclose(file2);
XX! }
XX! 
XX! /* Check_file() opens the fileptr with name <filename>. if <filename>
XX!  * equals "-" stdin is associated with the return value.
XX!  */
XX! FILE *check_file(name)
XX! char *name;
XX! {
XX!   FILE *temp;
XX! 
XX!   if (strcmp(name, "-") == 0) {
XX! 	return(stdin);
XX!   } else {
XX! 	temp = fopen(name, "r");
XX! 	if (temp == Nullfp) warn(CANNOT_OPEN_FILE, name);
XX! 	return(temp);
XX!   }
XX! }
XX! 
XX! /* Build_option_string() is called before recursive_dir() is called
XX!  * from the main() function. its purpose is to build the string that
XX!  * is used on the command line to get the current operation mode.
XX!  * e.g. "-C 6 -b".
XX!  */
XX! void build_option_string()
XX! {
XX!   switch (mode) {
XX! 	    case ed_mode:sprintf(options_string, "-e");
XX! 	break;
XX!       case context:
XX! 	if (context_lines == 3)
XX! 		sprintf(options_string, "-c");
XX! 	else
XX! 		sprintf(options_string, "-C %d", context_lines);
XX! 	break;
XX!   }
XX! 
XX! }
XX! 
XX! 
XX! /* The fatal error handler.
XX!  * Expects a format string and a string as arguments. The arguments
XX!  * are printed to stderr and the program exits with an error code 2.
XX!  */
XX! void fatal_error(fmt, s)
XX! char *fmt;			/* the format sttring to be printed	 */
XX! char *s;			/* string to be inserted into the format
XX! 				 * string				 */
XX! {
XX!   fprintf(stderr, "%s: ", progname);
XX    fprintf(stderr, fmt, s);
XX    fprintf(stderr, "\n");
XX    exit(2);
XX  }
XX  
XX! /* This function prints non fatal error messages to stderr.
XX!  * Expects the index of the message to be printed and a pointer
XX!  * to the (optional) string to be printed.
XX!  * Returns no value.
XX!  */
XX! void warn(number, string)
XX! int number;			/* index of the warning			 */
XX! char *string;			/* string to be inserted to the warning	 */
XX! {
XX!   static char *warning[] = {
XX!     "%s: The options -c, -e, -C n are mutually exclusive! Assuming -%c\n",
XX!     "%s: cannot open file %s for reading\n",
XX!   };
XX!   fprintf(stderr, warning[number], progname, string);
XX! }
XX  
XX+ /* Function used with the optione -b, trims the blanks in a input line:
XX+  * - blanks between words are reduced to one
XX+  * - trailing blanks are eliminated.
XX+  */
XX+ void trimming_blanks(l_text)
XX+ char *l_text;			/* begin of the char array		 */
XX+ {
XX+   char *line = l_text;
XX+   char *copy_to, *copy_from;
XX+ 
XX+   do {
XX+ 	if (*line == ' ') {
XX+ 		copy_from = line;
XX+ 		copy_to = line;
XX+ 		while (*(++copy_from) == ' ');
XX+ 		if (*copy_from != '\n') copy_to++;
XX+ 		while (*copy_from != '\0') *(copy_to++) = *(copy_from++);
XX+ 		*copy_to = '\0';
XX+ 	}
XX+   } while (*(++line) != '\0');
XX+ }
XX+ 
XX+ 
XX+ /* Filename separates the filename and the relative path in path_string.
XX+  * Returns the filename with a leading /
XX+  */
XX+ char *filename(path_string)
XX+ char *path_string;
XX+ {
XX+   char name[NAME_MAX + 2];	/* filename plus /		 	 */
XX+   char *ptr;
XX+ 
XX+   name[0] = '/';
XX+   ptr = strrchr(path_string, '/');
XX+ 
XX+   if (ptr == 0) {		/* no / in path_string, only a filename	 */
XX+ 	strcat(name, path_string);
XX+   } else {
XX+ 	strcat(name, ptr);
XX+   }
XX+ 
XX+   return(name);
XX+ }
XX+ 
XX+ /* The line module: one member in a linked list of lines. */
XX  struct line {
XX!   struct line *l_next;		/* pointer to the next line	 */
XX!   char l_eof;			/* == 0 if last line in file	 */
XX!   char *l_text;			/* array with the text		 */
XX  };
XX  
XX  struct line *freelist = 0;
XX  #define stepup(ll) ( ((ll) && ((ll)->l_eof==0)) ? (ll)->l_next : (ll) )
XX  
XX! /* Function to allocate space for a new line containing SIZE chars	*/
XX! struct line *new_line(size)
XX! int size;
XX  {
XX    register struct line *l;
XX  
XX!   if ((l = freelist) != NullStructLine)
XX  	freelist = freelist->l_next;
XX!   else {
XX! 	l = (struct line *) xmalloc(3 * sizeof(void *));
XX! 	l->l_text = (char *) xmalloc((size + 2) * sizeof(char));
XX! 	if ((l == 0) || (l->l_text == 0)) fatal_error("Out of memory", "");
XX!   }
XX    return l;
XX  }
XX  
XX! 
XX! /* Free_line() releases storage allocated for <l>. */
XX! void free_line(l)
XX  register struct line *l;
XX  {
XX    l->l_next = freelist;
XX    freelist = l;
XX  }
XX  
XX+ /* Equal_line() compares two lines, <l1> and <l2>.
XX+  * the returned value is the result of the strcmp() function.
XX+  */
XX  int equal_line(l1, l2)
XX  struct line *l1, *l2;
XX  {
XX***************
XX*** 130,142 ****
XX   read_line(fp)
XX  FILE *fp;
XX  {
XX!   register struct line *l = new_line();
XX    register char *p;
XX    register int c;
XX  
XX    (p = &(l->l_text[LINELEN]))[1] = '\377';
XX    l->l_eof = 0;
XX!   if (fgets(l->l_text, LINELEN + 2, fp) == NULL) {
XX  	l->l_eof = 1;
XX  	l->l_text[0] = 0;
XX    } else if ((p[1] & 0377) != 0377 && *p != '\n') {
XX--- 486,498 ----
XX   read_line(fp)
XX  FILE *fp;
XX  {
XX!   register struct line *l = new_line(LINELEN);
XX    register char *p;
XX    register int c;
XX  
XX    (p = &(l->l_text[LINELEN]))[1] = '\377';
XX    l->l_eof = 0;
XX!   if (fgets(l->l_text, LINELEN + 2, fp) == 0) {
XX  	l->l_eof = 1;
XX  	l->l_text[0] = 0;
XX    } else if ((p[1] & 0377) != 0377 && *p != '\n') {
XX***************
XX*** 146,151 ****
XX--- 502,516 ----
XX  	*p = '\0';
XX    }
XX    l->l_next = 0;
XX+   if (trim_blanks == SET) {
XX+ #ifdef DEBUG
XX+ 	printf("xxx %s xxx\n", l->l_text);
XX+ #endif
XX+ 	trimming_blanks(l->l_text);
XX+ #ifdef DEBUG
XX+ 	printf("xxx %s xxx\n", l->l_text);
XX+ #endif
XX+   }
XX    return l;
XX  }
XX  
XX***************
XX*** 157,168 ****
XX    FILE *f_fp;
XX  };
XX  
XX! advance(f)
XX  register struct f *f;
XX  {
XX    register struct line *l;
XX  
XX!   if (l = f->f_bwin) {
XX  	if (f->f_ewin == l)
XX  		f->f_bwin = f->f_ewin = 0;
XX  	else
XX--- 522,533 ----
XX    FILE *f_fp;
XX  };
XX  
XX! void advance(f)
XX  register struct f *f;
XX  {
XX    register struct line *l;
XX  
XX!   if ((l = f->f_bwin) != NullStructLine) {
XX  	if (f->f_ewin == l)
XX  		f->f_bwin = f->f_ewin = 0;
XX  	else
XX***************
XX*** 172,185 ****
XX    }
XX  }
XX  
XX! aside(f, l)
XX  struct f *f;
XX  struct line *l;
XX  {
XX    register struct line *ll;
XX  
XX    if (l == 0) return;
XX!   if (ll = l->l_next) {
XX  	while (ll->l_next) ll = ll->l_next;
XX  	ll->l_next = f->f_aside;
XX  	f->f_aside = l->l_next;
XX--- 537,550 ----
XX    }
XX  }
XX  
XX! void aside(f, l)
XX  struct f *f;
XX  struct line *l;
XX  {
XX    register struct line *ll;
XX  
XX    if (l == 0) return;
XX!   if ((ll = l->l_next) != NullStructLine) {
XX  	while (ll->l_next) ll = ll->l_next;
XX  	ll->l_next = f->f_aside;
XX  	f->f_aside = l->l_next;
XX***************
XX*** 188,200 ****
XX    }
XX  }
XX  
XX! struct line *
XX!  next(f)
XX  register struct f *f;
XX  {
XX    register struct line *l;
XX  
XX!   if (l = f->f_aside) {
XX  	f->f_aside = l->l_next;
XX  	l->l_next = 0;
XX    } else
XX--- 553,565 ----
XX    }
XX  }
XX  
XX! 
XX! struct line *next(f)
XX  register struct f *f;
XX  {
XX    register struct line *l;
XX  
XX!   if ((l = f->f_aside) != NullStructLine) {
XX  	f->f_aside = l->l_next;
XX  	l->l_next = 0;
XX    } else
XX***************
XX*** 214,220 ****
XX    return l;
XX  }
XX  
XX! init_f(f, fp)
XX  register struct f *f;
XX  FILE *fp;
XX  {
XX--- 579,589 ----
XX    return l;
XX  }
XX  
XX! 
XX! /* Init_f() initialises a window structure (struct f). <fp> is the
XX!  * file associated with <f>.
XX!  */
XX! void init_f(f, fp)
XX  register struct f *f;
XX  FILE *fp;
XX  {
XX***************
XX*** 223,240 ****
XX    f->f_fp = fp;
XX  }
XX  
XX! update(f, s)
XX  register struct f *f;
XX  char *s;
XX  {
XX    while (f->f_bwin && f->f_bwin != f->f_ewin) {
XX! 	printf("%s%s", s, f->f_bwin->l_text);
XX  	advance(f);
XX    }
XX  }
XX  
XX! /* Diff procedure */
XX! diff(fp1, fp2)
XX  FILE *fp1, *fp2;
XX  {
XX    struct f f1, f2;
XX--- 592,658 ----
XX    f->f_fp = fp;
XX  }
XX  
XX! 
XX! /* Update() prints a window. <f> is a pointer to the window, <s> is the
XX!  * string containing the "prefix" to the printout( either "<" or ">").
XX!  * after completion of update(), the window is empty.
XX!  */
XX! void update(f, s)
XX  register struct f *f;
XX  char *s;
XX  {
XX+   char *help;
XX+   int only_dot = 0;
XX+ 
XX+   if (firstoutput && (recursive_dir == SET)) {
XX+ 	printf("diff %s %s %s\n", options_string, oldfile, newfile);
XX+ 	firstoutput = 0;
XX+   }
XX    while (f->f_bwin && f->f_bwin != f->f_ewin) {
XX! 	if (mode != ed_mode) {
XX! 		printf("%s%s", s, f->f_bwin->l_text);
XX! 	} else {
XX! #ifdef DEBUG
XX! 		printf("ed_mode: test for only dot");
XX! 		printf("%s", f->f_bwin->l_text);
XX! #endif
XX! 		help = f->f_bwin->l_text;
XX! 		while ((*help == ' ') ||
XX! 		       (*help == '.') ||
XX! 		       (*help == '\t')) {
XX! 			if (*(help++) == '.') only_dot++;
XX! 			if (only_dot > 1) break;
XX! 		}
XX! 
XX! 		/* If only_dot is equal 1, there is only one dot on
XX! 		 * the line, so we have to take special actions.
XX! 		 * f the line with only one dot is found, we output
XX! 		 * two dots (".."), terminate the append modus and
XX! 		 * substitute "." for "..". Afterwards we restart
XX! 		 * with the append command.			 */
XX! 		if (*help == '\n' && only_dot == 1) {
XX! 			help = f->f_bwin->l_text;
XX! 			while (*help != '\0') {
XX! 				if (*help == '.') printf(".");
XX! 				putchar((int) *(help++));
XX! 			}
XX! 			printf(".\n");
XX! 			printf(".s/\\.\\././\n");
XX! 			printf("a\n");
XX! 		} else {
XX! 			printf("%s%s", s, f->f_bwin->l_text);
XX! 		}
XX! 	}
XX  	advance(f);
XX    }
XX  }
XX  
XX! /* __Diff(), performs the "core operation" of the program.
XX!  * Expects two file-pointers as arguments. This functions does
XX!  * *not* check if the file-pointers are valid.
XX!  */
XX! 
XX! void __diff(fp1, fp2)
XX  FILE *fp1, *fp2;
XX  {
XX    struct f f1, f2;
XX***************
XX*** 290,296 ****
XX  			differ(&f1, &f2);
XX  			goto equal;
XX  		}
XX! 		if (ll->l_eof) break;
XX  		ll = stepup(ll);
XX  	} while (ll);
XX  	b1 = stepup(b1);
XX--- 708,714 ----
XX  			differ(&f1, &f2);
XX  			goto equal;
XX  		}
XX! 		if (ll->l_eof != 0) break;
XX  		ll = stepup(ll);
XX  	} while (ll);
XX  	b1 = stepup(b1);
XX***************
XX*** 301,332 ****
XX    /* Both of the files reached EOF */
XX  }
XX  
XX! differ(f1, f2)
XX  register struct f *f1, *f2;
XX  {
XX!   int cnt1 = f1->f_linecnt, len1 = wlen(f1), cnt2 = f2->f_linecnt, len2 = wlen(f2);
XX! 
XX!   if ((len1 = wlen(f1)) || (len2 = wlen(f2))) {
XX  	if (len1 == 0) {
XX! 		printf("%da", cnt1);
XX! 		range(cnt2 + 1, cnt2 + len2);
XX  	} else if (len2 == 0) {
XX! 		range(cnt1 + 1, cnt1 + len1);
XX! 		printf("d%d", cnt2);
XX  	} else {
XX! 		range(cnt1 + 1, cnt1 + len1);
XX! 		putchar('c');
XX! 		range(cnt2 + 1, cnt2 + len2);
XX  	}
XX! 	putchar('\n');
XX! 	if (len1) update(f1, "< ");
XX! 	if (len1 && len2) printf("---\n");
XX! 	if (len2) update(f2, "> ");
XX  	diffs++;
XX    }
XX  }
XX  
XX! wlen(f)
XX  struct f *f;
XX  {
XX    register cnt = 0;
XX--- 719,793 ----
XX    /* Both of the files reached EOF */
XX  }
XX  
XX! /* Differ() prints the differences between files. the arguments <f1> and
XX!  * <f2> are pointers to the two windows, where the differences are.
XX!  */
XX! void differ(f1, f2)
XX  register struct f *f1, *f2;
XX  {
XX!   int cnt1 = f1->f_linecnt, len1 = wlen(f1);
XX!   int cnt2 = f2->f_linecnt, len2 = wlen(f2);
XX!   if ((len1 != 0) || (len2 != 0)) {
XX  	if (len1 == 0) {
XX! 		if (mode == ed_mode) {
XX! 			cnt1 += offset;
XX! 			printf("%d a\n", cnt1);
XX! 			update(f2, "");
XX! 			printf(".\n");
XX! 			offset += len2;
XX! 		} else {
XX! 			printf("%da", cnt1);
XX! 			range(cnt2 + 1, cnt2 + len2);
XX! 		}
XX  	} else if (len2 == 0) {
XX! 		if (mode == ed_mode) {
XX! 			cnt1 += offset;
XX! 			range(cnt1 + 1, cnt1 + len1);
XX! 			printf("d\n");
XX! 			offset -= len1;
XX! 			while (f1->f_bwin && f1->f_bwin != f1->f_ewin)
XX! 				advance(f1);
XX! 		} else {
XX! 			range(cnt1 + 1, cnt1 + len1);
XX! 			printf("d%d", cnt2);
XX! 		}
XX  	} else {
XX! 		if (mode != ed_mode) {
XX! 			range(cnt1 + 1, cnt1 + len1);
XX! 			putchar('c');
XX! 			range(cnt2 + 1, cnt2 + len2);
XX! 		} else {
XX! 			cnt1 += offset;
XX! 			if (len1 == len2) {
XX! 				range(cnt1 + 1, cnt1 + len1);
XX! 				printf("c\n");
XX! 				update(f2, "");
XX! 				printf(".\n");
XX! 			} else {
XX! 				range(cnt1 + 1, cnt1 + len1);
XX! 				printf("d\n");
XX! 				printf("%d a\n", cnt1);
XX! 				update(f2, "");
XX! 				printf(".\n");
XX! 				offset -= len1 - len2;
XX! 			}
XX! 			while (f1->f_bwin && f1->f_bwin != f1->f_ewin)
XX! 				advance(f1);
XX! 		}
XX  	}
XX! 	if (mode != ed_mode) {
XX! 		putchar('\n');
XX! 		if (len1 != 0) update(f1, "< ");
XX! 		if ((len1 != 0) && (len2 != 0)) printf("---\n");
XX! 		if (len2 != 0) update(f2, "> ");
XX! 	}
XX  	diffs++;
XX    }
XX  }
XX  
XX! 
XX! /* Function wlen() calculates the number of lines in a window. */
XX! int wlen(f)
XX  struct f *f;
XX  {
XX    register cnt = 0;
XX***************
XX*** 339,345 ****
XX    return cnt;
XX  }
XX  
XX! range(a, b)
XX  {
XX    printf(((a == b) ? "%d" : "%d,%d"), a, b);
XX  }
XX--- 800,1251 ----
XX    return cnt;
XX  }
XX  
XX! 
XX! /* Range() prints the line numbers of a range. the arguments <a> and <b>
XX!  * are the beginning and the ending line number of the range. if
XX!  * <a> == <b>, only one line number is printed. otherwise <a> and <b> are
XX!  * separated by a ",".
XX!  */
XX! void range(a, b)
XX! int a, b;
XX  {
XX    printf(((a == b) ? "%d" : "%d,%d"), a, b);
XX+ }
XX+ 
XX+ /* Here follows the code for option -c.
XX+  * This code is from the cdiff program by Larry Wall. I changed it only
XX+  * slightly to reflect the POSIX standard and to call the main routine
XX+  * as function context_diff().
XX+  */
XX+ 
XX+ /* Cdiff - context diff			Author: Larry Wall */
XX+ 
XX+ /* These global variables are still here from the original cdiff program...
XX+  * I was to lazy just to sort them out...
XX+  */
XX+ char buff[512];
XX+ FILE *oldfp, *newfp;
XX+ 
XX+ int oldmin, oldmax, newmin, newmax;
XX+ int oldbeg, oldend, newbeg, newend;
XX+ int preoldmax, prenewmax;
XX+ int preoldbeg, preoldend, prenewbeg, prenewend;
XX+ int oldwanted, newwanted;
XX+ 
XX+ char *oldhunk, *newhunk;
XX+ size_t oldsize, oldalloc, newsize, newalloc;
XX+ 
XX+ void cdiff(old, new, file1, file2)
XX+ char *old, *new;		/* The names of the two files to be compared */
XX+ FILE *file1, *file2;		/* The corresponding file-pointers	 */
XX+ {
XX+   FILE *inputfp;
XX+   struct stat statbuf;
XX+   register char *s;
XX+   char op;
XX+   char *newmark, *oldmark;
XX+   int len;
XX+   char *line;
XX+   int i;
XX+ 
XX+   oldfp = file1;
XX+   newfp = file2;
XX+ 
XX+   oldalloc = 512;
XX+   oldhunk = (char *) xmalloc(oldalloc);
XX+   newalloc = 512;
XX+   newhunk = (char *) xmalloc(newalloc);
XX+ 
XX+ 
XX+ /* The context diff spawns a new process that executes a normal diff
XX+  * and parses the output.
XX+  */
XX+   if (trim_blanks == SET)
XX+ 	sprintf(buff, "diff -b %s %s", old, new);
XX+   else
XX+ 	sprintf(buff, "diff %s %s", old, new);
XX+ 
XX+   inputfp = popen(buff, "r");
XX+   if (!inputfp) {
XX+ 	fprintf(stderr, "Can't execute diff %s %s\n", old, new);
XX+ 	exit(1);
XX+   }
XX+   preoldend = -1000;
XX+   firstoutput = 1;
XX+   while (fgets(buff, sizeof buff, inputfp) != Nullch) {
XX+ 	if (firstoutput) {
XX+ 		if (recursive_dir == SET) {
XX+ 			printf("diff %s %s %s\n", options_string,
XX+ 			       oldfile, newfile);
XX+ 		}
XX+ 		fstat(fileno(oldfp), &statbuf);
XX+ 		printf("*** %s %s", old, ctime(&statbuf.st_mtime));
XX+ 		fstat(fileno(newfp), &statbuf);
XX+ 		printf("--- %s %s", new, ctime(&statbuf.st_mtime));
XX+ 		printf("***************\n");
XX+ 		firstoutput = 0;
XX+ 	}
XX+ 	if (isdigit(*buff)) {
XX+ 		oldmin = atoi(buff);
XX+ 		for (s = buff; isdigit(*s); s++);
XX+ 		if (*s == ',') {
XX+ 			s++;
XX+ 			oldmax = atoi(s);
XX+ 			for (; isdigit(*s); s++);
XX+ 		} else {
XX+ 			oldmax = oldmin;
XX+ 		}
XX+ 		if (*s != 'a' && *s != 'd' && *s != 'c') {
XX+ 			fprintf(stderr, "Unparseable input: %s", s);
XX+ 			exit(1);
XX+ 		}
XX+ 		op = *s;
XX+ 		s++;
XX+ 		newmin = atoi(s);
XX+ 		for (; isdigit(*s); s++);
XX+ 		if (*s == ',') {
XX+ 			s++;
XX+ 			newmax = atoi(s);
XX+ 			for (; isdigit(*s); s++);
XX+ 		} else {
XX+ 			newmax = newmin;
XX+ 		}
XX+ 		if (*s != '\n' && *s != ' ') {
XX+ 			fprintf(stderr, "Unparseable input: %s", s);
XX+ 			exit(1);
XX+ 		}
XX+ 		newmark = oldmark = "! ";
XX+ 		if (op == 'a') {
XX+ 			oldmin++;
XX+ 			newmark = "+ ";
XX+ 		}
XX+ 		if (op == 'd') {
XX+ 			newmin++;
XX+ 			oldmark = "- ";
XX+ 		}
XX+ 		oldbeg = oldmin - context_lines;
XX+ 		oldend = oldmax + context_lines;
XX+ 		if (oldbeg < 1) oldbeg = 1;
XX+ 		newbeg = newmin - context_lines;
XX+ 		newend = newmax + context_lines;
XX+ 		if (newbeg < 1) newbeg = 1;
XX+ 
XX+ 		if (preoldend < oldbeg - 1) {
XX+ 			if (preoldend >= 0) {
XX+ 				dumphunk();
XX+ 			}
XX+ 			preoldbeg = oldbeg;
XX+ 			prenewbeg = newbeg;
XX+ 			oldwanted = newwanted = 0;
XX+ 			oldsize = newsize = 0;
XX+ 		} else {	/* we want to append to previous hunk */
XX+ 			oldbeg = preoldmax + 1;
XX+ 			newbeg = prenewmax + 1;
XX+ 		}
XX+ 
XX+ 		for (i = oldbeg; i <= oldmax; i++) {
XX+ 			line = getold(i);
XX+ 			if (!line) {
XX+ 				oldend = oldmax = i - 1;
XX+ 				break;
XX+ 			}
XX+ 			len = strlen(line) + 2;
XX+ 			if (oldsize + len + 1 >= oldalloc) {
XX+ 				oldalloc *= 2;
XX+ 				oldhunk = (char *) xrealloc(oldhunk, oldalloc);
XX+ 			}
XX+ 			if (i >= oldmin) {
XX+ 				strcpy(oldhunk + oldsize, oldmark);
XX+ 				oldwanted++;
XX+ 			} else {
XX+ 				strcpy(oldhunk + oldsize, "  ");
XX+ 			}
XX+ 			strcpy(oldhunk + oldsize + 2, line);
XX+ 			oldsize += len;
XX+ 		}
XX+ 		preoldmax = oldmax;
XX+ 		preoldend = oldend;
XX+ 
XX+ 		for (i = newbeg; i <= newmax; i++) {
XX+ 			line = getnew(i);
XX+ 			if (!line) {
XX+ 				newend = newmax = i - 1;
XX+ 				break;
XX+ 			}
XX+ 			len = strlen(line) + 2;
XX+ 			if (newsize + len + 1 >= newalloc) {
XX+ 				newalloc *= 2;
XX+ 				newhunk = (char *) xrealloc(newhunk, newalloc);
XX+ 			}
XX+ 			if (i >= newmin) {
XX+ 				strcpy(newhunk + newsize, newmark);
XX+ 				newwanted++;
XX+ 			} else {
XX+ 				strcpy(newhunk + newsize, "  ");
XX+ 			}
XX+ 			strcpy(newhunk + newsize + 2, line);
XX+ 			newsize += len;
XX+ 		}
XX+ 		prenewmax = newmax;
XX+ 		prenewend = newend;
XX+ 	}
XX+   }
XX+   if (pclose(inputfp) != 0) severe_error = 1;
XX+ 
XX+   if (preoldend >= 0) {
XX+ 	dumphunk();
XX+   }
XX+ }
XX+ 
XX+ void dumphunk()
XX+ {
XX+   int i;
XX+   char *line;
XX+   int len;
XX+ 
XX+   for (i = preoldmax + 1; i <= preoldend; i++) {
XX+ 	line = getold(i);
XX+ 	if (!line) {
XX+ 		preoldend = i - 1;
XX+ 		break;
XX+ 	}
XX+ 	len = strlen(line) + 2;
XX+ 	if (oldsize + len + 1 >= oldalloc) {
XX+ 		oldalloc *= 2;
XX+ 		oldhunk = (char *) xrealloc(oldhunk, oldalloc);
XX+ 	}
XX+ 	strcpy(oldhunk + oldsize, "  ");
XX+ 	strcpy(oldhunk + oldsize + 2, line);
XX+ 	oldsize += len;
XX+   }
XX+   for (i = prenewmax + 1; i <= prenewend; i++) {
XX+ 	line = getnew(i);
XX+ 	if (!line) {
XX+ 		prenewend = i - 1;
XX+ 		break;
XX+ 	}
XX+ 	len = strlen(line) + 2;
XX+ 	if (newsize + len + 1 >= newalloc) {
XX+ 		newalloc *= 2;
XX+ 		newhunk = (char *) xrealloc(newhunk, newalloc);
XX+ 	}
XX+ 	strcpy(newhunk + newsize, "  ");
XX+ 	strcpy(newhunk + newsize + 2, line);
XX+ 	newsize += len;
XX+   }
XX+ 
XX+   if (preoldbeg >= preoldend) {
XX+ 	printf("*** %d ****\n", preoldend);
XX+   } else {
XX+ 	printf("*** %d,%d ****\n", preoldbeg, preoldend);
XX+   }
XX+   if (oldwanted) {
XX+ 	fputs(oldhunk, stdout);
XX+   }
XX+   oldsize = 0;
XX+   *oldhunk = '\0';
XX+   if (prenewbeg >= prenewend) {
XX+ 	printf("--- %d ----\n", prenewend);
XX+   } else {
XX+ 	printf("--- %d,%d ----\n", prenewbeg, prenewend);
XX+   }
XX+   if (newwanted) {
XX+ 	fputs(newhunk, stdout);
XX+   }
XX+   newsize = 0;
XX+   *newhunk = '\0';
XX+ }
XX+ 
XX+ char *getold(targ)
XX+ int targ;
XX+ {
XX+   static int oldline = 0;
XX+ 
XX+   while (fgets(buff, sizeof buff, oldfp) != Nullch) {
XX+ 	oldline++;
XX+ 	if (oldline == targ) return buff;
XX+   }
XX+   return Nullch;
XX+ }
XX+ 
XX+ char *getnew(targ)
XX+ int targ;
XX+ {
XX+   static int newline = 0;
XX+ 
XX+   while (fgets(buff, sizeof buff, newfp) != Nullch) {
XX+ 	newline++;
XX+ 	if (newline == targ) return buff;
XX+   }
XX+   return Nullch;
XX+ }
XX+ 
XX+ 
XX+ /* Isdir() checks, if <path> is the name of a directory. a return value
XX+  * is 0, <path> is a normal file. otherwise the <path> is a directory.
XX+  */
XX+ int isdir(path)
XX+ char *path;
XX+ {
XX+   struct stat buf;
XX+   stat(path, &buf);
XX+   if (buf.st_mode & S_IFDIR) {	/* path is a directory		 */
XX+ 	return(~0);
XX+   } else {
XX+ 	return(0);
XX+   }
XX+ }
XX+ 
XX+ 
XX+ 
XX+ /* This is the "main" function if a diff of two directories has to be
XX+  * done. diff_recursive() expects the names of the two directories to
XX+  * be compared. 							 */
XX+ void diff_recursive(dir1, dir2)
XX+ char *dir1, *dir2;
XX+ {
XX+   FILE *ls1, *ls2;
XX+   char file1[PATH_MAX], file2[PATH_MAX];
XX+   char jointfile1[PATH_MAX], jointfile2[PATH_MAX];
XX+   char command[PATH_MAX];
XX+   int difference, eof1, eof2;
XX+ 
XX+   sprintf(command, "ls %s", dir1);
XX+   ls1 = popen(command, "r");
XX+   sprintf(command, "ls %s", dir2);
XX+   ls2 = popen(command, "r");
XX+ 
XX+   if ((ls1 == NULL) || (ls2 == NULL))
XX+ 	fatal_error("cannot execute ls!", "");
XX+ 
XX+   file1[0] = '\0';
XX+   eof1 = fscanf(ls1, "%s\n", file1);
XX+   file2[0] = '\0';
XX+   eof2 = fscanf(ls2, "%s\n", file2);
XX+ 
XX+   while ((file1[0] != '\0') && (file2[0] != '\0')) {
XX+ 	difference = strcmp(file1, file2);
XX+ 	while (difference != 0) {
XX+ 		if (difference < 0) {
XX+ 			printf("Only in %s: %s\n", dir1, file1);
XX+ 			file1[0] = '\0';
XX+ 			eof1 = fscanf(ls1, "%s\n", file1);
XX+ 			if (file1[0] == '\0') break;
XX+ 		} else {
XX+ 			printf("Only in %s: %s\n", dir2, file2);
XX+ 			file2[0] = '\0';
XX+ 			eof2 = fscanf(ls2, "%s\n", file2);
XX+ 			if (file2[0] == '\0') break;
XX+ 		}
XX+ 		difference = strcmp(file1, file2);
XX+ 	}
XX+ 	if (eof1 != EOF && eof2 != EOF) {
XX+ 		strcpy(jointfile1, dir1);
XX+ 		strcat(jointfile1, "/");
XX+ 		strcat(jointfile1, file1);
XX+ 		strcpy(jointfile2, dir2);
XX+ 		strcat(jointfile2, "/");
XX+ 		strcat(jointfile2, file2);
XX+ 
XX+ 		if ((isdir(jointfile1) != 0) && (isdir(jointfile2) != 0)) {
XX+ 			printf("Common subdirectories: %s and %s\n",
XX+ 			       jointfile1, jointfile2);
XX+ 			diff_recursive(jointfile1, jointfile2);
XX+ 		} else {
XX+ 			firstoutput = 1;
XX+ 			strcpy(oldfile, jointfile1);
XX+ 			strcpy(newfile, jointfile2);
XX+ 			diff(jointfile1, jointfile2);
XX+ 		}
XX+ 		file1[0] = '\0';
XX+ 		eof1 = fscanf(ls1, "%s\n", file1);
XX+ 		file2[0] = '\0';
XX+ 		eof2 = fscanf(ls2, "%s\n", file2);
XX+ 	}
XX+   }
XX+ 
XX+   if (file1[0] != '\0') {	/* first arg still has files 		 */
XX+ 	do {
XX+ 		printf("Only in %s: %s\n", dir1, file1);
XX+ 		eof1 = fscanf(ls1, " %s\n", file1);
XX+ 	} while (eof1 != EOF);
XX+   }
XX+   if (file2[0] != '\0') {
XX+ 	do {
XX+ 		printf("Only in %s: %s\n", dir2, file2);
XX+ 		eof2 = fscanf(ls2, " %s\n", file2);
XX+ 	} while (eof2 != EOF);
XX+   }
XX+   if (pclose(ls1) != 0) severe_error = 1;
XX+   if (pclose(ls2) != 0) severe_error = 1;
XX+ }
XX+ 
XX+ 
XX+ /* File_type_error is called, if in a recursive diff ( -r) one of the two
XX+  * files a block special, a character special or a FIFO special file is.
XX+  * The corresponding error message is printed here.			  */
XX+ void file_type_error(filename1, filename2, statbuf1, statbuf2)
XX+ char *filename1, *filename2;
XX+ struct stat *statbuf1, *statbuf2;
XX+ {
XX+   char type1[25], type2[25];
XX+ 
XX+   switch (statbuf1->st_mode & S_IFMT) {	/* select only file mode */
XX+       case S_IFREG:
XX+ 	sprintf(type1, "regular file ");
XX+ 	break;
XX+       case S_IFBLK:
XX+ 	sprintf(type1, "block special file ");
XX+ 	break;
XX+       case S_IFDIR:	sprintf(type1, "directory ");	break;
XX+       case S_IFCHR:
XX+ 	sprintf(type1, "character special file ");
XX+ 	break;
XX+       case S_IFIFO:
XX+ 	sprintf(type1, "FIFO special file ");
XX+ 	break;
XX+   }
XX+ 
XX+   switch (statbuf2->st_mode & S_IFMT) {	/* select only file mode */
XX+       case S_IFREG:
XX+ 	sprintf(type2, "regular file ");
XX+ 	break;
XX+       case S_IFBLK:
XX+ 	sprintf(type2, "block special file ");
XX+ 	break;
XX+       case S_IFDIR:	sprintf(type2, "directory ");	break;
XX+       case S_IFCHR:
XX+ 	sprintf(type2, "character special file ");
XX+ 	break;
XX+       case S_IFIFO:
XX+ 	sprintf(type2, "FIFO special file ");
XX+ 	break;
XX+   }
XX+   printf("File %s is a %s while file %s is a %s\n",
XX+          filename1, type1, filename2, type2);
XX+ }
XX+ 
XX+ void *xmalloc(size)
XX+ size_t size;
XX+ {
XX+   void *ptr;
XX+ 
XX+   ptr = malloc(size);
XX+   if (ptr == NULL) {
XX+ 	fprintf(stderr, "%s: out of memory\n", progname);
XX+ 	exit(1);
XX+   }
XX+   return(ptr);
XX+ }
XX+ 
XX+ void *xrealloc(ptr, size)
XX+ void *ptr;
XX+ size_t size;
XX+ {
XX+   ptr = realloc(ptr, size);
XX+   if (ptr == NULL) {
XX+ 	fprintf(stderr, "%s: out of memory\n", progname);
XX+ 	exit(1);
XX+   }
XX+   return(ptr);
XX  }
X/
Xecho x - diskcheck.c.d
Xsed '/^X/s///' > diskcheck.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/diskcheck.c  crc=45665   4220	Sun Apr 25 21:34:54 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/diskcheck.c  crc=25422   5487	Sun Jan 10 14:26:17 1993
XX***************
XX*** 1,22 ****
XX  /* diskcheck - test a disk for bad blocks	Author: Andy Tanenbaum */
XX  
XX  #include <sys/types.h>
XX  #include <signal.h>
XX  #include <errno.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX  
XX! #include <minix/config.h>
XX! #include <minix/const.h>
XX! 
XX! #undef printf
XX  #define OK 0
XX  #define PRINTFREQ  10
XX  #define N 30
XX  
XX  char purgebuf[BLOCK_SIZE * N];
XX  char buf[BLOCK_SIZE], zero[BLOCK_SIZE];
XX! int pat1[BLOCK_SIZE / 2], pat2[BLOCK_SIZE / 2];
XX  int blk = -1;			/* number of the block in buf, or -1 */
XX  int pfd;			/* file descriptor for purging */
XX  int fd;				/* file descriptor for data I/O */
XX--- 1,27 ----
XX  /* diskcheck - test a disk for bad blocks	Author: Andy Tanenbaum */
XX  
XX+ #include <minix/config.h>
XX+ #include <minix/const.h>
XX+ 
XX  #include <sys/types.h>
XX+ #include <sys/stat.h>
XX  #include <signal.h>
XX  #include <errno.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX  #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! #undef ERROR			/* ERROR might be defined in <errno.h> :-( */
XX! #define ERROR (-99)
XX  #define OK 0
XX  #define PRINTFREQ  10
XX  #define N 30
XX+ #define SHORTS_PER_BLOCK (BLOCK_SIZE / sizeof(short))
XX  
XX  char purgebuf[BLOCK_SIZE * N];
XX  char buf[BLOCK_SIZE], zero[BLOCK_SIZE];
XX! short pat1[SHORTS_PER_BLOCK], pat2[SHORTS_PER_BLOCK];
XX  int blk = -1;			/* number of the block in buf, or -1 */
XX  int pfd;			/* file descriptor for purging */
XX  int fd;				/* file descriptor for data I/O */
XX***************
XX*** 26,51 ****
XX  unsigned errors;		/* # errors so far */
XX  unsigned ct;			/* # blocks read so far */
XX  int intflag;			/* set when signal seen */
XX! extern errno;
XX! long pos;
XX  char *purgefile = "/dev/ram";
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    unsigned b;
XX    int i;
XX!   void catch();
XX  
XX    signal(SIGINT, catch);
XX    signal(SIGQUIT, catch);
XX    if (argc != 4) usage();
XX    if ((fd = open(argv[1], O_RDWR)) < 0) {
XX  	printf("Cannot open %s\n", argv[1]);
XX  	exit(1);
XX    }
XX!   if ((pfd = open(purgefile, O_RDWR)) < 0) {
XX  	printf("Cannot open %s\n", purgefile);
XX  	exit(1);
XX    }
XX--- 31,70 ----
XX  unsigned errors;		/* # errors so far */
XX  unsigned ct;			/* # blocks read so far */
XX  int intflag;			/* set when signal seen */
XX! int rawdev;			/* set when I/O done on raw device */
XX  char *purgefile = "/dev/ram";
XX  
XX! _PROTOTYPE(int main, (int argc , char *argv []));
XX! _PROTOTYPE(int testblock, (unsigned b ));
XX! _PROTOTYPE(void status, (void ));
XX! _PROTOTYPE(void nonfatal, (char *s , unsigned b ));
XX! _PROTOTYPE(void fatal, (char *s , unsigned b ));
XX! _PROTOTYPE(void catch, (int sig ));
XX! _PROTOTYPE(void usage, (void ));
XX! _PROTOTYPE(int wtest, (off_t pos , short *pat ));
XX! _PROTOTYPE(void purge_cache, (void ));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    unsigned b;
XX    int i;
XX!   struct stat s;
XX  
XX    signal(SIGINT, catch);
XX    signal(SIGQUIT, catch);
XX    if (argc != 4) usage();
XX+   if (stat(argv[1], &s)) {
XX+ 	printf("Cannot stat %s\n", argv[1]);
XX+ 	exit(1);
XX+   }
XX+   rawdev = S_ISCHR(s.st_mode);
XX    if ((fd = open(argv[1], O_RDWR)) < 0) {
XX  	printf("Cannot open %s\n", argv[1]);
XX  	exit(1);
XX    }
XX!   if ((pfd = open(purgefile, O_RDONLY)) < 0) {
XX  	printf("Cannot open %s\n", purgefile);
XX  	exit(1);
XX    }
XX***************
XX*** 53,59 ****
XX    limit = initblock + atoi(argv[3]);
XX    if (limit <= initblock) usage();
XX  
XX!   for (i = 0; i < BLOCK_SIZE / 2; i++) {
XX  	pat1[i] = i;
XX  	pat2[i] = 1000 - i;
XX    }
XX--- 72,78 ----
XX    limit = initblock + atoi(argv[3]);
XX    if (limit <= initblock) usage();
XX  
XX!   for (i = 0; i < SHORTS_PER_BLOCK; i++) {
XX  	pat1[i] = i;
XX  	pat2[i] = 1000 - i;
XX    }
XX***************
XX*** 64,70 ****
XX  		errors++;
XX  		if (blk == b) {
XX  			/* Read ok, write failed; try to restore block. */
XX! 			lseek(fd, pos, SEEK_SET);
XX  			write(fd, buf, BLOCK_SIZE);
XX  		}
XX  	}
XX--- 83,89 ----
XX  		errors++;
XX  		if (blk == b) {
XX  			/* Read ok, write failed; try to restore block. */
XX! 			lseek(fd, (off_t) BLOCK_SIZE * (off_t) b, SEEK_SET);
XX  			write(fd, buf, BLOCK_SIZE);
XX  		}
XX  	}
XX***************
XX*** 74,80 ****
XX    }
XX  
XX    status();
XX!   exit(0);
XX  }
XX  
XX  
XX--- 93,100 ----
XX    }
XX  
XX    status();
XX!   printf("\n");
XX!   return(0);
XX  }
XX  
XX  
XX***************
XX*** 86,95 ****
XX   * Return OK or ERROR.
XX   */
XX  
XX    int s;
XX  
XX    blk = -1;
XX!   pos = (long) BLOCK_SIZE *(long) b;
XX    purge_cache();
XX    if (lseek(fd, pos, SEEK_SET) != pos) fatal("Cannot seek to block ", b);
XX  
XX--- 106,116 ----
XX   * Return OK or ERROR.
XX   */
XX  
XX+   off_t pos;
XX    int s;
XX  
XX    blk = -1;
XX!   pos = (off_t) BLOCK_SIZE * (off_t) b;
XX    purge_cache();
XX    if (lseek(fd, pos, SEEK_SET) != pos) fatal("Cannot seek to block ", b);
XX  
XX***************
XX*** 122,143 ****
XX  
XX  
XX    nonfatal("Read size error on block ", b);
XX  }
XX  
XX! status()
XX  {
XX    printf("%8u blocks tested, %u errors detected (last block tested = %5u)\r",
XX           ct, errors, curblock);
XX  }
XX  
XX! nonfatal(s, b)
XX  char *s;
XX  unsigned b;
XX  {
XX    printf("\n%s%u\n", s, b);
XX  }
XX  
XX! fatal(s, b)
XX  char *s;
XX  unsigned b;
XX  {
XX--- 143,166 ----
XX  
XX  
XX    nonfatal("Read size error on block ", b);
XX+   return(ERROR);
XX  }
XX  
XX! void status()
XX  {
XX    printf("%8u blocks tested, %u errors detected (last block tested = %5u)\r",
XX           ct, errors, curblock);
XX+   fflush(stdout);
XX  }
XX  
XX! void nonfatal(s, b)
XX  char *s;
XX  unsigned b;
XX  {
XX    printf("\n%s%u\n", s, b);
XX  }
XX  
XX! void fatal(s, b)
XX  char *s;
XX  unsigned b;
XX  {
XX***************
XX*** 156,172 ****
XX  }
XX  
XX  
XX! usage()
XX  {
XX    printf("Usage: diskcheck device start-block block-count\n");
XX    exit(1);
XX  }
XX  
XX! wtest(pos, pat)
XX! long pos;
XX! int pat[];
XX  {
XX!   int testb[BLOCK_SIZE / 2];
XX    int i;
XX  
XX    lseek(fd, pos, SEEK_SET);
XX--- 179,195 ----
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    printf("Usage: diskcheck device start-block block-count\n");
XX    exit(1);
XX  }
XX  
XX! int wtest(pos, pat)
XX! off_t pos;
XX! short *pat;
XX  {
XX!   short testb[SHORTS_PER_BLOCK];
XX    int i;
XX  
XX    lseek(fd, pos, SEEK_SET);
XX***************
XX*** 175,181 ****
XX    purge_cache();
XX    lseek(fd, pos, SEEK_SET);
XX    if (read(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE) return(ERROR);
XX!   for (i = 0; i < BLOCK_SIZE / 2; i++)
XX  	if (testb[i] != pat[i]) {
XX  		printf("%d %d\n", testb[i], pat[i]);
XX  		return(ERROR);
XX--- 198,204 ----
XX    purge_cache();
XX    lseek(fd, pos, SEEK_SET);
XX    if (read(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE) return(ERROR);
XX!   for (i = 0; i < SHORTS_PER_BLOCK; i++)
XX  	if (testb[i] != pat[i]) {
XX  		printf("%d %d\n", testb[i], pat[i]);
XX  		return(ERROR);
XX***************
XX*** 183,201 ****
XX    return(OK);
XX  }
XX  
XX! purge_cache()
XX  {
XX  /* Do enough reads that the cache is purged. */
XX! 
XX    int left, count, r;
XX  
XX    pfd = open(purgefile, O_RDONLY);
XX    left = NR_BUFS;
XX    while (left > 0) {
XX  	count = (left < N ? left : N);
XX! 	if ((r = read(pfd, purgebuf, count * BLOCK_SIZE)) != count * BLOCK_SIZE) {
XX  		printf("ERROR: count=%d  left=%d r=%d.  ", count, left, r);
XX! 		fatal("Cannot purge cache.  errno= ", errno);
XX  	}
XX  	left -= count;
XX    }
XX--- 206,239 ----
XX    return(OK);
XX  }
XX  
XX! void purge_cache()
XX  {
XX  /* Do enough reads that the cache is purged. */
XX!   static int warned = 0;
XX    int left, count, r;
XX  
XX+   if (rawdev) return;
XX    pfd = open(purgefile, O_RDONLY);
XX+ #ifdef NR_BUFS
XX    left = NR_BUFS;
XX+ #else
XX+   /* XXX - buffers are dynamically allocated and there are likely to be
XX+    * several MB worth.  This purge is unlikely to work.  There should be
XX+    * raw devices to avoid such complications.
XX+    */
XX+   left = 8000;
XX+ #endif
XX    while (left > 0) {
XX  	count = (left < N ? left : N);
XX! 	r = read(pfd, purgebuf, (size_t) (count * BLOCK_SIZE));
XX! 	if (r != count * BLOCK_SIZE) {
XX! 		if (r == 0) {
XX! 			if (!warned) printf("WARNING: Cannot purge cache.\n");
XX! 			warned = 1;
XX! 			break;
XX! 		}
XX  		printf("ERROR: count=%d  left=%d r=%d.  ", count, left, r);
XX! 		fatal("Cannot purge cache.  errno= ", (unsigned) errno);
XX  	}
XX  	left -= count;
XX    }
X/
Xecho x - du.c.d
Xsed '/^X/s///' > du.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/du.c  crc=53152   5109	Sun Apr 25 21:34:54 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/du.c  crc=45864   4763	Sat Mar 13 19:32:31 1993
XX***************
XX*** 5,10 ****
XX--- 5,13 ----
XX   *			1.2	24 Mar 89	nick@nswitgould.oz
XX   *			1.3	31 Mar 89	nick@nswitgould.oz
XX   *			1.4	22 Feb 90	meulenbr@cst.prl.philips.nl
XX+  *			1.5	09 Jul 91	hp@vmars.tuwien.ac.at
XX+  *			1.6	01 Oct 92	kjb@cs.vu.nl
XX+  *			1.7	04 Jan 93	bde
XX   *
XX   *	Copyright 1987, Joypace Ltd., London UK. All rights reserved.
XX   *	This code may be freely distributed, provided that this notice
XX***************
XX*** 15,122 ****
XX   *  1.2: 	Fixed bug involving 14 character long filenames
XX   *  1.3:	Add [-l levels] option to restrict printing.
XX   *  1.4:	Added processing of multiple arguments
XX!  *
XX   */
XX  
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  #include <blocksize.h>
XX  #include <stdio.h>
XX  
XX! char *prog;			/* program name */
XX! char *optstr = "asl:";		/* -a and -s arguments */
XX! int silent = 0;			/* silent mode */
XX! int all = 0;			/* all directory entries mode */
XX! char *startdir = ".";		/* starting from here */
XX! int levels = 255;		/* # of directory levels to print */
XX  
XX! #define	LINELEN 256
XX  
XX! #define DIRNAMELEN 14
XX  #define	LSTAT stat
XX! typedef struct _dirstr {
XX!   ino_t inum;
XX!   char d_name[DIRNAMELEN];
XX! } DIR;
XX! DIR dir;
XX  
XX! typedef struct _alstr {
XX    int al_dev;
XX    ino_t al_inum;
XX  } ALREADY;
XX  
XX! #define	MAXALREADY	50
XX  ALREADY already[MAXALREADY];
XX! int alc = 0;
XX  
XX- /*
XX-  *	myindex - stop the scanf bug
XX-  */
XX- char *myindex(s, c)
XX- register char *s;
XX- register char c;
XX- {
XX-   for (; *s; s++)
XX- 	if (*s == c) return(s);
XX-   return(NULL);
XX- }
XX  
XX- 
XX  /*
XX-  *	getopt - parse the arguments given.
XX-  *	retrieved from net.sources
XX-  */
XX- int opterr = 1;
XX- int optind = 1;
XX- int optopt;
XX- char *optarg;
XX- 
XX- #define BADCH	(int)'?'
XX- #define EMSG	""
XX- #define TELL(s)	fputs(*nargv, stderr); fputs(s, stderr);\
XX-   fputc(optopt, stderr); fputc('\n', stderr);\
XX-   return(BADCH);
XX- 
XX- int getopt(nargc, nargv, ostr)
XX- int nargc;
XX- char **nargv;
XX- char *ostr;
XX- {
XX-   register char *oli;
XX-   static char *place = EMSG;
XX- 
XX-   if (!*place) {
XX- 	if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
XX- 		return(EOF);
XX- 	if (*place == '-') {
XX- 		++optind;
XX- 		return(EOF);
XX- 	}
XX-   }
XX-   if ((optopt = (int) *place++) == (int) ':' || !(oli = myindex(ostr, optopt))) {
XX- 	if (!*place) ++optind;
XX- 	TELL(": illegal option -- ");
XX-   }
XX-   if (*++oli != ':') {
XX- 	optarg = NULL;
XX- 	if (!*place) ++optind;
XX-   } else {
XX- 	if (*place)
XX- 		optarg = place;
XX- 	else if (nargc <= ++optind) {
XX- 		place = EMSG;
XX- 		TELL(": option requires an argument -- ");
XX- 	} else
XX- 		optarg = nargv[optind];
XX- 	place = EMSG;
XX- 	++optind;
XX-   }
XX-   return(optopt);
XX- }
XX- 
XX- /*
XX   *	makedname - make the pathname from the directory name, and the
XX   *	directory entry, placing it in out. If this would overflow,
XX   *	return 0, otherwise 1.
XX--- 18,81 ----
XX   *  1.2: 	Fixed bug involving 14 character long filenames
XX   *  1.3:	Add [-l levels] option to restrict printing.
XX   *  1.4:	Added processing of multiple arguments
XX!  *  1.5:	Fixed processing of multiple arguments. General cleanup.
XX!  *  1.6:	Use readdir
XX!  *  1.7:	Merged 1.5 and 1.6.
XX!  *		Print totals even for non-dirs at top level.
XX!  *		Count blocks for each dir before printing total for the dir.
XX!  *		Count blocks for all non-special files.
XX!  *		Don't clutter link buffer with directories.
XX!  *  TODO	Report all errors.  Count indirect blocks.  Don't forget
XX!  *		links.
XX   */
XX  
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <blocksize.h>
XX  #include <fcntl.h>
XX  #include <blocksize.h>
XX+ #include <errno.h>
XX+ #include <limits.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX+ #include <dirent.h>
XX  
XX! extern char *optarg;
XX! extern int optind;
XX  
XX! #define	LINELEN		256
XX! #define	MAXALREADY	512
XX  
XX! #ifdef S_IFLNK
XX! #define	LSTAT lstat
XX! #else
XX  #define	LSTAT stat
XX! #endif
XX  
XX! typedef struct {
XX    int al_dev;
XX    ino_t al_inum;
XX  } ALREADY;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int makedname, (char *d, char *f, char *out, int outlen));
XX! _PROTOTYPE(int done, (int dev, Ino_t inum));
XX! _PROTOTYPE(long dodir, (char *d, int thislev));
XX! 
XX! char *prog;			/* program name */
XX! char *optstr = "asl:";		/* -a and -s arguments */
XX! int silent = 0;			/* silent mode */
XX! int all = 0;			/* all directory entries mode */
XX! char *startdir = ".";		/* starting from here */
XX! int levels = 20000;		/* # of directory levels to print */
XX  ALREADY already[MAXALREADY];
XX! int alc;
XX  
XX  
XX  /*
XX   *	makedname - make the pathname from the directory name, and the
XX   *	directory entry, placing it in out. If this would overflow,
XX   *	return 0, otherwise 1.
XX***************
XX*** 130,139 ****
XX    char *cp;
XX    int length;
XX  
XX!   /* Find length (1-14) of directory entry */
XX!   cp = f;
XX!   for (length = 0; *cp && (length < 14); ++cp) ++length;
XX! 
XX    if (strlen(d) + length + 2 > outlen) return(0);
XX    for (cp = out; *d; *cp++ = *d++);
XX    if (*(cp - 1) != '/') *cp++ = '/';
XX--- 89,95 ----
XX    char *cp;
XX    int length;
XX  
XX!   length = strlen(f);
XX    if (strlen(d) + length + 2 > outlen) return(0);
XX    for (cp = out; *d; *cp++ = *d++);
XX    if (*(cp - 1) != '/') *cp++ = '/';
XX***************
XX*** 174,221 ****
XX  char *d;
XX  int thislev;
XX  {
XX    struct stat s;
XX!   long total = 0L;
XX    char dent[LINELEN];
XX!   int fd;
XX  
XX!   if ((fd = open(d, O_RDONLY)) < 0) return(0L);
XX!   while (read(fd, &dir, sizeof(dir)) > 0) {
XX! 	if (strcmp(dir.d_name, ".") == 0 ||
XX! 	    strcmp(dir.d_name, "..") == 0)
XX! 		continue;
XX! 	if (dir.inum == 0) continue;
XX! 	if (!makedname(d, dir.d_name, dent, sizeof(dent))) continue;
XX! 	if (LSTAT(dent, &s) < 0) continue;
XX! 	if (s.st_nlink > 1 && done(s.st_dev, s.st_ino)) continue;
XX! 	if ((s.st_mode & S_IFMT) == S_IFDIR)
XX  		total += dodir(dent, thislev - 1);
XX- 	switch (s.st_mode & S_IFMT) {
XX- 	    case S_IFREG:
XX- 	    case S_IFDIR:
XX- 		total += (s.st_size + BLOCK_SIZE) / BLOCK_SIZE;
XX- 		break;
XX  	}
XX! 	if (all && (s.st_mode & S_IFMT) != S_IFDIR)
XX! 		if (thislev > 0)	/* this is correct - file in subdir */
XX! 			printf("%ld\t%s\n",
XX! 				(s.st_size + BLOCK_SIZE) / BLOCK_SIZE, dent);
XX    }
XX!   close(fd);
XX!   if (!silent)
XX! 	if (thislev >= 0)	/* this is correct - subdir itself */
XX! 		printf("%ld\t%s\n", total, d);
XX    return(total);
XX  }
XX  
XX! /*
XX!  *	OK, here goes...
XX!  */
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX-   long tot;
XX    int c;
XX  
XX    prog = argv[0];
XX--- 130,183 ----
XX  char *d;
XX  int thislev;
XX  {
XX+   int maybe_print;
XX    struct stat s;
XX!   long total;
XX    char dent[LINELEN];
XX!   DIR *dp;
XX!   struct dirent *entry;
XX  
XX!   if (LSTAT(d, &s) < 0) {
XX! 	fprintf(stderr,
XX! 		"%s: %s: %s\n", prog, d, strerror(errno));
XX!     	return 0L;
XX!   }
XX!   total = (s.st_size + (BLOCK_SIZE - 1)) / BLOCK_SIZE;
XX!   switch (s.st_mode & S_IFMT) {
XX!     case S_IFDIR:
XX! 	/* Directories should not be linked except to "." and "..", so this
XX! 	 * directory should not already have been done.
XX! 	 */
XX! 	maybe_print = !silent;
XX! 	if ((dp = opendir(d)) == NULL) break;
XX! 	while ((entry = readdir(dp)) != NULL) {
XX! 		if (strcmp(entry->d_name, ".") == 0 ||
XX! 		    strcmp(entry->d_name, "..") == 0)
XX! 			continue;
XX! 		if (!makedname(d, entry->d_name, dent, sizeof(dent))) continue;
XX  		total += dodir(dent, thislev - 1);
XX  	}
XX! 	closedir(dp);
XX! 	break;
XX!     case S_IFBLK:
XX!     case S_IFCHR:
XX! 	/* st_size for special files is not related to blocks used. */
XX! 	total = 0;
XX! 	/* Fall through. */
XX!     default:
XX! 	if (s.st_nlink > 1 && done(s.st_dev, s.st_ino)) return 0L;
XX! 	maybe_print = all;
XX! 	break;
XX    }
XX!   if (thislev >= levels || (maybe_print && thislev >= 0))
XX! 	printf("%ld\t%s\n", total, d);
XX    return(total);
XX  }
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX    int c;
XX  
XX    prog = argv[0];
XX***************
XX*** 229,237 ****
XX  		exit(1);
XX  	}
XX    do {
XX!     if (optind < argc) startdir = argv[optind++];
XX!     tot = dodir(startdir, levels);
XX!     if (silent) printf("%ld\t%s\n", tot, startdir);
XX    } while (optind < argc);
XX!   exit(0);
XX  }
XX--- 191,199 ----
XX  		exit(1);
XX  	}
XX    do {
XX! 	if (optind < argc) startdir = argv[optind++];
XX! 	alc = 0;
XX! 	(void) dodir(startdir, levels);
XX    } while (optind < argc);
XX!   return(0);
XX  }
X/
Xecho x - echo.c.d
Xsed '/^X/s///' > echo.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/echo.c  crc=26577    699	Sun Apr 25 21:34:54 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/echo.c  crc=37265    860	Wed Nov  4 04:19:10 1992
XX***************
XX*** 1,9 ****
XX  /* echo - echo arguments	Author: Andy Tanenbaum */
XX  
XX  #define SIZE 1024
XX  char buf[SIZE];
XX  int count;
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 1,17 ----
XX  /* echo - echo arguments	Author: Andy Tanenbaum */
XX  
XX+ #include <sys/types.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ 
XX  #define SIZE 1024
XX  char buf[SIZE];
XX  int count;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void collect, (char *s));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 24,33 ****
XX  
XX    /* Print accumulated output. */
XX    if (count > 0) write(1, buf, count);
XX!   exit(0);
XX  }
XX  
XX! collect(s)
XX  char *s;
XX  {
XX  /* Collect characters.  For efficiency, write them in large chunks. */
XX--- 32,41 ----
XX  
XX    /* Print accumulated output. */
XX    if (count > 0) write(1, buf, count);
XX!   return(0);
XX  }
XX  
XX! void collect(s)
XX  char *s;
XX  {
XX  /* Collect characters.  For efficiency, write them in large chunks. */
X/
Xecho x - ed.c.d
Xsed '/^X/s///' > ed.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ed.c  crc=54463  41768	Sun Apr 25 21:34:55 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ed.c  crc=31156  43613	Wed Nov  4 04:19:11 1992
XX***************
XX*** 21,27 ****
XX    doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\
XX    getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\
XX    move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\
XX!   unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s system.s
XX  
XX  ed:	$(OBJS)
XX    cc -T. -i -o ed $(OBJS)
XX--- 21,27 ----
XX    doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\
XX    getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\
XX    move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\
XX!   unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s System.s
XX  
XX  ed:	$(OBJS)
XX    cc -T. -i -o ed $(OBJS)
XX***************
XX*** 29,34 ****
XX--- 29,38 ----
XX  
XX  #include <sys/types.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <sys/wait.h>
XX  #include <stdio.h>
XX  
XX  /****************************/
XX***************
XX*** 129,151 ****
XX  #define MAXSTR	132		/* Maximum numbers of characters in a line */
XX  
XX  
XX- extern char *matchs();
XX- extern char *amatch();
XX- extern char *in_string();
XX- extern TOKEN *getpat();
XX- extern int esc();
XX- extern char *dodash();
XX- extern TOKEN *makepat();
XX- extern int unmakepat();
XX- extern int insert();
XX- extern int delete();
XX- extern int isalphanum();
XX- extern char *stoupper();
XX- extern int pr_tok();
XX- extern int pr_line();
XX- extern BITMAP *makebitmap();
XX- void set_buf();
XX- 
XX  /* Macros */
XX  #define max(a,b)	((a>b)?a:b)
XX  #define min(a,b)	((a<b)?a:b)
XX--- 133,138 ----
XX***************
XX*** 186,206 ****
XX  #define nextln(l)	((l)+1 > lastln ? 0 : (l)+1)
XX  #define prevln(l)	((l)-1 < 0 ? lastln : (l)-1)
XX  
XX- extern char *getfn();
XX- extern LINE *getptr();
XX- extern char *gettxt();
XX- extern char *maksub();
XX- extern TOKEN *optpat();
XX- 
XX- extern char *catsub();
XX- 
XX- extern char *strcpy(), *strcat();
XX- extern char *malloc();
XX- 
XX  /*	amatch.c	*/
XX  /* #include <stdio.h> */
XX  /* #include "tools.h" */
XX  
XX  /*     Scans throught the pattern template looking for a match
XX   * with lin.  Each element of lin is compared with the template
XX   * until either a mis-match is found or the end of the template
XX--- 173,232 ----
XX  #define nextln(l)	((l)+1 > lastln ? 0 : (l)+1)
XX  #define prevln(l)	((l)-1 < 0 ? lastln : (l)-1)
XX  
XX  /*	amatch.c	*/
XX  /* #include <stdio.h> */
XX  /* #include "tools.h" */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(static char *match, (char *lin, TOKEN *pat, char *boln));
XX+ _PROTOTYPE(char *amatch, (char *lin, TOKEN *pat, char *boln));
XX+ _PROTOTYPE(int append, (int line, int glob));
XX+ _PROTOTYPE(BITMAP *makebitmap, (unsigned size));
XX+ _PROTOTYPE(int setbit, (unsigned c, char *map, unsigned val));
XX+ _PROTOTYPE(int testbit, (unsigned c, char *map));
XX+ _PROTOTYPE(char *catsub, (char *from, char *to, char *sub, char *new, char *newend));
XX+ _PROTOTYPE(int ckglob, (void));
XX+ _PROTOTYPE(int deflt, (int def1, int def2));
XX+ _PROTOTYPE(int del, (int from, int to));
XX+ _PROTOTYPE(int docmd, (int glob));
XX+ _PROTOTYPE(int dolst, (int line1, int line2));
XX+ _PROTOTYPE(char *dodash, (int delim, char *src, char *map));
XX+ _PROTOTYPE(int doglob, (void));
XX+ _PROTOTYPE(int doprnt, (int from, int to));
XX+ _PROTOTYPE(void prntln, (char *str, int vflg, int lin));
XX+ _PROTOTYPE(void putcntl, (int c, FILE *stream));
XX+ _PROTOTYPE(int doread, (int lin, char *fname));
XX+ _PROTOTYPE(int dowrite, (int from, int to, char *fname, int apflg));
XX+ _PROTOTYPE(void intr, (int sig));
XX+ _PROTOTYPE(int egets, (char *str, int size, FILE *stream));
XX+ _PROTOTYPE(int esc, (char **s));
XX+ _PROTOTYPE(int find, (TOKEN *pat, int dir));
XX+ _PROTOTYPE(char *getfn, (void));
XX+ _PROTOTYPE(int getlst, (void));
XX+ _PROTOTYPE(int getnum, (int first));
XX+ _PROTOTYPE(int getone, (void));
XX+ _PROTOTYPE(TOKEN *getpat, (char *arg));
XX+ _PROTOTYPE(LINE *getptr, (int num));
XX+ _PROTOTYPE(int getrhs, (char *sub));
XX+ _PROTOTYPE(char *gettxt, (int num));
XX+ _PROTOTYPE(int ins, (char *str));
XX+ _PROTOTYPE(int System, (char *c));
XX+ _PROTOTYPE(int join, (int first, int last));
XX+ _PROTOTYPE(TOKEN *makepat, (char *arg, int delim));
XX+ _PROTOTYPE(char *maksub, (char *sub, int subsz));
XX+ _PROTOTYPE(char *matchs, (char *line, TOKEN *pat, int ret_endp));
XX+ _PROTOTYPE(int move, (int num));
XX+ _PROTOTYPE(int transfer, (int num));
XX+ _PROTOTYPE(int omatch, (char **linp, TOKEN *pat, char *boln));
XX+ _PROTOTYPE(TOKEN *optpat, (void));
XX+ _PROTOTYPE(int set, (void));
XX+ _PROTOTYPE(int show, (void));
XX+ _PROTOTYPE(void relink, (LINE *a, LINE *x, LINE *y, LINE *b));
XX+ _PROTOTYPE(void clrbuf, (void));
XX+ _PROTOTYPE(void set_buf, (void));
XX+ _PROTOTYPE(int subst, (TOKEN *pat, char *sub, int gflg, int pflag));
XX+ _PROTOTYPE(void unmakepat, (TOKEN *head));
XX+ 
XX  /*     Scans throught the pattern template looking for a match
XX   * with lin.  Each element of lin is compared with the template
XX   * until either a mis-match is found or the end of the template
XX***************
XX*** 216,222 ****
XX  
XX  char *paropen[9], *parclose[9];
XX  int between, parnum;
XX- static char *match();
XX  
XX  char *amatch(lin, pat, boln)
XX  char *lin;
XX--- 242,247 ----
XX***************
XX*** 331,337 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! append(line, glob)
XX  int line, glob;
XX  {
XX    int stat;
XX--- 356,362 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int append(line, glob)
XX  int line, glob;
XX  {
XX    int stat;
XX***************
XX*** 388,394 ****
XX    return((BITMAP *) map);
XX  }
XX  
XX! setbit(c, map, val)
XX  unsigned c, val;
XX  char *map;
XX  {
XX--- 413,419 ----
XX    return((BITMAP *) map);
XX  }
XX  
XX! int setbit(c, map, val)
XX  unsigned c, val;
XX  char *map;
XX  {
XX***************
XX*** 408,414 ****
XX    return 1;
XX  }
XX  
XX! testbit(c, map)
XX  unsigned c;
XX  char *map;
XX  {
XX--- 433,439 ----
XX    return 1;
XX  }
XX  
XX! int testbit(c, map)
XX  unsigned c;
XX  char *map;
XX  {
XX***************
XX*** 463,469 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! ckglob()
XX  {
XX    TOKEN *glbpat;
XX    char c, delim;
XX--- 488,494 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int ckglob()
XX  {
XX    TOKEN *glbpat;
XX    char c, delim;
XX***************
XX*** 506,512 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! deflt(def1, def2)
XX  int def1, def2;
XX  {
XX    if (nlines == 0) {
XX--- 531,537 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int deflt(def1, def2)
XX  int def1, def2;
XX  {
XX    if (nlines == 0) {
XX***************
XX*** 522,528 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! del(from, to)
XX  int from, to;
XX  {
XX    LINE *first, *last, *next, *tmp;
XX--- 547,553 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int del(from, to)
XX  int from, to;
XX  {
XX    LINE *first, *last, *next, *tmp;
XX***************
XX*** 553,559 ****
XX  
XX  extern int mark[];
XX  
XX! docmd(glob)
XX  int glob;
XX  {
XX    static char rhs[MAXPAT];
XX--- 578,584 ----
XX  
XX  extern int mark[];
XX  
XX! int docmd(glob)
XX  int glob;
XX  {
XX    static char rhs[MAXPAT];
XX***************
XX*** 840,846 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! doglob()
XX  {
XX    int lin, stat;
XX    char *cmd;
XX--- 865,871 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int doglob()
XX  {
XX    int lin, stat;
XX    char *cmd;
XX***************
XX*** 870,876 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! doprnt(from, to)
XX  int from, to;
XX  {
XX    int i;
XX--- 895,901 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int doprnt(from, to)
XX  int from, to;
XX  {
XX    int i;
XX***************
XX*** 890,896 ****
XX    return(0);
XX  }
XX  
XX! prntln(str, vflg, lin)
XX  char *str;
XX  int vflg, lin;
XX  {
XX--- 915,921 ----
XX    return(0);
XX  }
XX  
XX! void prntln(str, vflg, lin)
XX  char *str;
XX  int vflg, lin;
XX  {
XX***************
XX*** 922,928 ****
XX    putc('\n', stdout);
XX  }
XX  
XX! putcntl(c, stream)
XX  char c;
XX  FILE *stream;
XX  {
XX--- 947,953 ----
XX    putc('\n', stdout);
XX  }
XX  
XX! void putcntl(c, stream)
XX  char c;
XX  FILE *stream;
XX  {
XX***************
XX*** 937,947 ****
XX  
XX  extern int diag;
XX  
XX! doread(lin, fname)
XX  int lin;
XX  char *fname;
XX  {
XX-   extern FILE *fopen();
XX    FILE *fp;
XX    int err;
XX    long bytes;
XX--- 962,971 ----
XX  
XX  extern int diag;
XX  
XX! int doread(lin, fname)
XX  int lin;
XX  char *fname;
XX  {
XX    FILE *fp;
XX    int err;
XX    long bytes;
XX***************
XX*** 983,994 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! dowrite(from, to, fname, apflg)
XX  int from, to;
XX  char *fname;
XX  int apflg;
XX  {
XX-   extern FILE *fopen();
XX    FILE *fp;
XX    int lin, err;
XX    int lines;
XX--- 1007,1017 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int dowrite(from, to, fname, apflg)
XX  int from, to;
XX  char *fname;
XX  int apflg;
XX  {
XX    FILE *fp;
XX    int lin, err;
XX    int lines;
XX***************
XX*** 1061,1067 ****
XX    longjmp(env, 1);
XX  }
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 1084,1090 ----
XX    longjmp(env, 1);
XX  }
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 1096,1102 ****
XX  	if (*inlin == '!') {
XX  		for (inptr = inlin; *inptr != NL; inptr++);
XX  		*inptr = EOS;
XX! 		system(inlin + 1);
XX  		continue;
XX  	}
XX  	inptr = inlin;
XX--- 1119,1125 ----
XX  	if (*inlin == '!') {
XX  		for (inptr = inlin; *inptr != NL; inptr++);
XX  		*inptr = EOS;
XX! 		System(inlin + 1);
XX  		continue;
XX  	}
XX  	inptr = inlin;
XX***************
XX*** 1121,1126 ****
XX--- 1144,1150 ----
XX  	}
XX  	printf("?\n");
XX    }
XX+   return(0);
XX  }
XX  
XX  /*	egets.c	*/
XX***************
XX*** 1130,1136 ****
XX  
XX  int eightbit = 1;		/* save eight bit */
XX  int nonascii, nullchar, truncated;
XX! egets(str, size, stream)
XX  char *str;
XX  int size;
XX  FILE *stream;
XX--- 1154,1160 ----
XX  
XX  int eightbit = 1;		/* save eight bit */
XX  int nonascii, nullchar, truncated;
XX! int egets(str, size, stream)
XX  char *str;
XX  int size;
XX  FILE *stream;
XX***************
XX*** 1183,1189 ****
XX   * is untouched and *s is returned, otherwise **s is advanced to point
XX   * at the escaped character and the translated character is returned.
XX   */
XX! esc(s)
XX  char **s;
XX  {
XX    register int rval;
XX--- 1207,1213 ----
XX   * is untouched and *s is returned, otherwise **s is advanced to point
XX   * at the escaped character and the translated character is returned.
XX   */
XX! int esc(s)
XX  char **s;
XX  {
XX    register int rval;
XX***************
XX*** 1213,1219 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! find(pat, dir)
XX  TOKEN *pat;
XX  int dir;
XX  {
XX--- 1237,1243 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int find(pat, dir)
XX  TOKEN *pat;
XX  int dir;
XX  {
XX***************
XX*** 1285,1291 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! getlst()
XX  {
XX    int num;
XX  
XX--- 1309,1315 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int getlst()
XX  {
XX    int num;
XX  
XX***************
XX*** 1315,1321 ****
XX  
XX  int mark['z' - 'a' + 1];
XX  
XX! getnum(first)
XX  int first;
XX  {
XX    TOKEN *srchpat;
XX--- 1339,1345 ----
XX  
XX  int mark['z' - 'a' + 1];
XX  
XX! int getnum(first)
XX  int first;
XX  {
XX    TOKEN *srchpat;
XX***************
XX*** 1343,1349 ****
XX        case '/':
XX        case '?':
XX  	srchpat = optpat();
XX! 	if (*inptr == c) *inptr++;
XX  	return(find(srchpat, c == '/' ? 1 : 0));
XX  
XX        case '-':
XX--- 1367,1373 ----
XX        case '/':
XX        case '?':
XX  	srchpat = optpat();
XX! 	if (*inptr == c) inptr++;
XX  	return(find(srchpat, c == '/' ? 1 : 0));
XX  
XX        case '-':
XX***************
XX*** 1369,1375 ****
XX  #define FIRST 1
XX  #define NOTFIRST 0
XX  
XX! getone()
XX  {
XX    int c, i, num;
XX  
XX--- 1393,1399 ----
XX  #define FIRST 1
XX  #define NOTFIRST 0
XX  
XX! int getone()
XX  {
XX    int c, i, num;
XX  
XX***************
XX*** 1432,1438 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! getrhs(sub)
XX  char *sub;
XX  {
XX    if (inptr[0] == NL || inptr[1] == NL)	/* check for eol */
XX--- 1456,1462 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int getrhs(sub)
XX  char *sub;
XX  {
XX    if (inptr[0] == NL || inptr[1] == NL)	/* check for eol */
XX***************
XX*** 1443,1449 ****
XX    inptr++;			/* skip over delimter */
XX    while (*inptr == SP || *inptr == HT) inptr++;
XX    if (*inptr == 'g') {
XX! 	*inptr++;
XX  	return(1);
XX    }
XX    return(0);
XX--- 1467,1473 ----
XX    inptr++;			/* skip over delimter */
XX    while (*inptr == SP || *inptr == HT) inptr++;
XX    if (*inptr == 'g') {
XX! 	inptr++;
XX  	return(1);
XX    }
XX    return(0);
XX***************
XX*** 1472,1478 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! ins(str)
XX  char *str;
XX  {
XX    char buf[MAXLINE], *cp;
XX--- 1496,1502 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int ins(str)
XX  char *str;
XX  {
XX    char buf[MAXLINE], *cp;
XX***************
XX*** 1511,1517 ****
XX  
XX  extern int fchanged;
XX  
XX! join(first, last)
XX  int first, last;
XX  {
XX    char buf[MAXLINE];
XX--- 1535,1541 ----
XX  
XX  extern int fchanged;
XX  
XX! int join(first, last)
XX  int first, last;
XX  {
XX    char buf[MAXLINE];
XX***************
XX*** 1709,1715 ****
XX  		if (size >= subsz) return(NULL);
XX  
XX  		switch (toupper(*inptr)) {
XX! 		    case NL:	*cp++ == ESCAPE;	break;
XX  		    case 'S':
XX  			*cp++ = SP;
XX  			inptr++;
XX--- 1733,1740 ----
XX  		if (size >= subsz) return(NULL);
XX  
XX  		switch (toupper(*inptr)) {
XX! 		    case NL:	*cp++ = ESCAPE;		break;
XX! 			break;
XX  		    case 'S':
XX  			*cp++ = SP;
XX  			inptr++;
XX***************
XX*** 1844,1855 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! move(num)
XX  int num;
XX  {
XX    LINE *k0, *k1, *k2, *k3;
XX  
XX!   if (line1 <= 0 || line2 < line1 || line1 <= num && num <= line2)
XX  	return(ERR);
XX    k0 = getptr(prevln(line1));
XX    k1 = getptr(line1);
XX--- 1869,1880 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int move(num)
XX  int num;
XX  {
XX    LINE *k0, *k1, *k2, *k3;
XX  
XX!   if (line1 <= 0 || line2 < line1 || (line1 <= num && num <= line2))
XX  	return(ERR);
XX    k0 = getptr(prevln(line1));
XX    k1 = getptr(line1);
XX***************
XX*** 1910,1916 ****
XX   * strings, 1 otherwise.  "boln" should point at the position that will
XX   * match a BOL token.
XX   */
XX! omatch(linp, pat, boln)
XX  char **linp;
XX  TOKEN *pat;
XX  char *boln;
XX--- 1935,1941 ----
XX   * strings, 1 otherwise.  "boln" should point at the position that will
XX   * match a BOL token.
XX   */
XX! int omatch(linp, pat, boln)
XX  char **linp;
XX  TOKEN *pat;
XX  char *boln;
XX***************
XX*** 1998,2004 ****
XX    0
XX  };
XX  
XX! set()
XX  {
XX    char word[16];
XX    int i;
XX--- 2023,2029 ----
XX    0
XX  };
XX  
XX! int set()
XX  {
XX    char word[16];
XX    int i;
XX***************
XX*** 2025,2031 ****
XX    return(0);
XX  }
XX  
XX! show()
XX  {
XX    extern int version;
XX  
XX--- 2050,2056 ----
XX    return(0);
XX  }
XX  
XX! int show()
XX  {
XX    extern int version;
XX  
XX***************
XX*** 2039,2052 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! relink(a, x, y, b)
XX  LINE *a, *x, *y, *b;
XX  {
XX    x->l_prev = a;
XX    y->l_next = b;
XX  }
XX  
XX! clrbuf()
XX  {
XX    del(1, lastln);
XX  }
XX--- 2064,2077 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! void relink(a, x, y, b)
XX  LINE *a, *x, *y, *b;
XX  {
XX    x->l_prev = a;
XX    y->l_next = b;
XX  }
XX  
XX! void clrbuf()
XX  {
XX    del(1, lastln);
XX  }
XX***************
XX*** 2062,2068 ****
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! subst(pat, sub, gflg, pflag)
XX  TOKEN *pat;
XX  char *sub;
XX  int gflg, pflag;
XX--- 2087,2093 ----
XX  /* #include "tools.h" */
XX  /* #include "ed.h" */
XX  
XX! int subst(pat, sub, gflg, pflag)
XX  TOKEN *pat;
XX  char *sub;
XX  int gflg, pflag;
XX***************
XX*** 2110,2120 ****
XX    return(nchngd);
XX  }
XX  
XX! /*	system.c	*/
XX  #define SHELL	"/bin/sh"
XX  #define SHELL2	"/usr/bin/sh"
XX  
XX! system(c)
XX  char *c;
XX  {
XX    int pid, status;
XX--- 2135,2145 ----
XX    return(nchngd);
XX  }
XX  
XX! /*	System.c	*/
XX  #define SHELL	"/bin/sh"
XX  #define SHELL2	"/usr/bin/sh"
XX  
XX! int System(c)
XX  char *c;
XX  {
XX    int pid, status;
XX***************
XX*** 2136,2142 ****
XX  /* #include "tools.h" */
XX  
XX  /* Free up the memory usde for token string */
XX! unmakepat(head)
XX  TOKEN *head;
XX  {
XX  
XX--- 2161,2167 ----
XX  /* #include "tools.h" */
XX  
XX  /* Free up the memory usde for token string */
XX! void unmakepat(head)
XX  TOKEN *head;
XX  {
XX  
X/
Xecho x - expand.c.d
Xsed '/^X/s///' > expand.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/expand.c  crc=28176   1624	Sun Apr 25 21:34:55 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/expand.c  crc=60044   1767	Wed Nov  4 04:19:11 1992
XX***************
XX*** 4,16 ****
XX  
XX  #include <stddef.h>
XX  #include <string.h>
XX  #include <stdio.h>
XX  
XX  #define MAX_TABS 32
XX  
XX  int column = 0;			/* Current column, retained between files  */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 4,20 ----
XX  
XX  #include <stddef.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define MAX_TABS 32
XX  
XX  int column = 0;			/* Current column, retained between files  */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void Expand, (FILE *f, int tab_index, int tabs []));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 50,60 ****
XX  		fclose(f);
XX  	}
XX  
XX!   exit(0);
XX  }
XX  
XX  
XX! Expand(f, tab_index, tabs)
XX  FILE *f;
XX  int tab_index;
XX  int tabs[];
XX--- 54,64 ----
XX  		fclose(f);
XX  	}
XX  
XX!   return(0);
XX  }
XX  
XX  
XX! void Expand(f, tab_index, tabs)
XX  FILE *f;
XX  int tab_index;
XX  int tabs[];
X/
Xecho x - expr.c.d
Xsed '/^X/s///' > expr.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/expr.c  crc=64386  13227	Sun Apr 25 21:34:55 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/expr.c  crc=14964  13440	Wed Nov  4 04:19:11 1992
XX***************
XX*** 2,11 ****
XX  
XX  #include <string.h>
XX  #include <ctype.h>
XX  #include <stdio.h>
XX  
XX- extern char *malloc( 	/* size_t nbytes */ );
XX- 
XX  struct value {
XX    long numval;			/* numeric value */
XX    int nf_valid;			/* "numeric value field valid" flag */
XX--- 2,10 ----
XX  
XX  #include <string.h>
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  struct value {
XX    long numval;			/* numeric value */
XX    int nf_valid;			/* "numeric value field valid" flag */
XX***************
XX*** 17,40 ****
XX  	 ((valp)->strval = NULL),		\
XX  	 ((valp)->numval = (number)))
XX  
XX! void invalid( 	/* char *err */ );
XX! char *strvalue( 	/* struct value *valp */ );
XX! int numvalue( 	/* struct value *valp */ );
XX! char *strsave( 	/* char *string */ );
XX! void expr1( 	/* struct value *valp */ ),
XX!  expr2( 	/* struct value *valp */ ),
XX!  expr3( 	/* struct value *valp */ ),
XX!  expr4( 	/* struct value *valp */ ),
XX!  expr5( 	/* struct value *valp */ ),
XX!  expr6( 	/* struct value *valp */ ),
XX!  expr7( 	/* struct value *valp */ );
XX! void docolon( 	/* value *match, *pattern */ );
XX  
XX  char *progname;
XX  char **argp;
XX  char NUMARG[] = "numeric argument required";
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 16,45 ----
XX  	 ((valp)->strval = NULL),		\
XX  	 ((valp)->numval = (number)))
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void expr1, (struct value *valp));
XX! _PROTOTYPE(void expr2, (struct value *valp));
XX! _PROTOTYPE(void expr3, (struct value *valp));
XX! _PROTOTYPE(void expr4, (struct value *valp));
XX! _PROTOTYPE(void expr5, (struct value *valp));
XX! _PROTOTYPE(void expr6, (struct value *valp));
XX! _PROTOTYPE(void expr7, (struct value *valp));
XX! _PROTOTYPE(int nullz, (struct value *valp));
XX! _PROTOTYPE(int numvalue, (struct value *valp));
XX! _PROTOTYPE(char *strvalue, (struct value *valp));
XX! _PROTOTYPE(char *strsave, (char *string));
XX! _PROTOTYPE(void invalid, (char *err));
XX! _PROTOTYPE(void docolon, (struct value *match, struct value *pattern));
XX! _PROTOTYPE(void rcomp, (char *regexp));
XX! _PROTOTYPE(void rmatch, (char *str));
XX! _PROTOTYPE(char *rtry, (char *str, unsigned char **pcp));
XX! _PROTOTYPE(char *tryone, (char *str, unsigned char **pcp));
XX  
XX  char *progname;
XX  char **argp;
XX  char NUMARG[] = "numeric argument required";
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 45,51 ****
XX    expr1(&val0);
XX    if (*argp != NULL) invalid("syntax error");
XX    (void) puts(strvalue(&val0));
XX!   exit(nullz(&val0));
XX  }
XX  
XX  /* Yet Another recursive descent parser. */
XX--- 50,56 ----
XX    expr1(&val0);
XX    if (*argp != NULL) invalid("syntax error");
XX    (void) puts(strvalue(&val0));
XX!   return(nullz(&val0));
XX  }
XX  
XX  /* Yet Another recursive descent parser. */
XX***************
XX*** 297,303 ****
XX  {
XX    char *p;
XX  
XX!   if ((p = malloc(strlen(string) + 1)) == NULL) invalid("out of memory");
XX  
XX    (void) strcpy(p, string);
XX  
XX--- 302,308 ----
XX  {
XX    char *p;
XX  
XX!   if ((p = (char *)malloc(strlen(string) + 1)) == NULL) invalid("out of memory");
XX  
XX    (void) strcpy(p, string);
XX  
XX***************
XX*** 344,354 ****
XX  char *rends[10];		/* pointers to \) endings */
XX  int rlevel;			/* \(...\) level */
XX  
XX- void rcomp( 	/* char *regexp */ );
XX- void rmatch( 	/* char *str */ );
XX- char *rtry( 	/* char *str, unsigned char **pcp */ );
XX- char *tryone( 	/* char *str, unsigned char **pcp */ );
XX- 
XX  /* Compile the regexp, match it against the string, and return the
XX   * proper result (a string if \(...\) used, and the match length otherwise.
XX   */
XX--- 349,354 ----
XX***************
XX*** 456,462 ****
XX  			*rpc++ = '*';
XX  			break;
XX  		} else {
XX! 			memmove(starable + 1, starable, rpc - starable);
XX  			*starable = RSTAR;
XX  			starable = NULL;
XX  			++rpc;
XX--- 456,462 ----
XX  			*rpc++ = '*';
XX  			break;
XX  		} else {
XX! 			memmove(starable + 1, starable, (size_t)(rpc - starable));
XX  			*starable = RSTAR;
XX  			starable = NULL;
XX  			++rpc;
X/
Xecho x - factor.c.d
Xsed '/^X/s///' > factor.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/factor.c  crc=57874    776	Sun Apr 25 21:34:56 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/factor.c  crc=17500    885	Wed Nov  4 04:19:11 1992
XX***************
XX*** 1,12 ****
XX  /* factor - print the prime factors of a number      Author: Andy Tanenbaum */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  /* Factor a number */
XX  
XX!   long i, n, flag = 0, first(), atol();
XX  
XX    if (argc != 2 || (n = atol(argv[1])) < 2) {
XX  	printf("Usage: factor n   (2 <= n < 2**31)\n");
XX--- 1,18 ----
XX  /* factor - print the prime factors of a number      Author: Andy Tanenbaum */
XX  
XX! #include <stdlib.h>
XX! #include <stdio.h>
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(long first, (long k));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  /* Factor a number */
XX  
XX!   long i, n, flag = 0;
XX  
XX    if (argc != 2 || (n = atol(argv[1])) < 2) {
XX  	printf("Usage: factor n   (2 <= n < 2**31)\n");
X/
Xecho x - fgrep.c.d
Xsed '/^X/s///' > fgrep.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/fgrep.c  crc=65281   5269	Sun Apr 25 21:34:56 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/fgrep.c  crc=02577   9135	Wed Nov  4 04:19:11 1992
XX***************
XX*** 1,285 ****
XX! /* fgrep - fast grep			Author: Jan Christiaan van Winkel */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <stdio.h>
XX  
XX  int argc;
XX  char **argv;
XX! int stringlen, offset, boundary;
XX! int i, j, k, count, linum;
XX! char stringarea[1024];
XX! int strptr;
XX! int strcount;
XX! unsigned char tbl[32][256];
XX! int lengths[32];
XX! char *tststring[32];
XX! char string[512];
XX! char tmpstring[512];
XX! int vflag, cflag, nofname, hadone, lflag, nflag, sflag, hflag, eflag, fflag;
XX! int fp;
XX  
XX! main(oargc, oargv)
XX! int oargc;
XX! char *oargv[];
XX  
XX! {
XX!   int find();
XX!   void exparg();
XX!   void getargs();
XX!   void gotone();
XX  
XX!   argc = oargc;
XX!   argv = oargv;
XX!   getargs();
XX  
XX!   fp = 0;
XX!   if (i >= argc - 2 || hflag)	/* stdin, 1 file, hflag */
XX! 	nofname = 1;
XX  
XX    do {
XX! 	if (i < argc && (fp = open(argv[i], O_RDONLY)) < 0) {
XX! 		fprintf(stderr, "%s: can't open %s\n", argv[0], argv[i]);
XX! 		continue;
XX! 	}
XX  	count = 0;
XX! 	linum = 0;
XX! 
XX! 	while ((stringlen = getlin(fp, string, 512)) != EOF) {
XX! 		linum++;
XX! 		for (j = 0; j < strcount; j++) {
XX! 			if (find(tststring[j], tbl[j], lengths[j]) != vflag) {
XX! 				gotone();
XX! 				break;
XX! 			}
XX  		}
XX! 		if (lflag && count) break;
XX  	}
XX! 	close(fp);
XX! 
XX  	if (cflag) {
XX! 		printf("%s: %d times\n", argv[i], count);
XX  	}
XX! 	if (lflag && count > 0) {
XX! 		printf("%s\n", argv[i]);
XX! 	}
XX!   } while (++i < argc);
XX  
XX!   fflush(stdout);
XX!   if (hadone)
XX! 	exit(0);
XX!   else
XX! 	exit(1);
XX  }
XX  
XX! void getargs()
XX  {
XX!   int tmp;
XX!   void maktbl();
XX!   for (i = 1; i < argc && argv[i][0] == '-'; i++) {
XX! 	switch (argv[i][1]) {
XX! 	    case 'e':
XX! 		eflag = 1;
XX! 		if (fflag) {
XX! 			fprintf(stderr, "%s: can't have -e and -f at the same time\n", argv[0]);
XX! 			exit(2);
XX! 		}
XX! 		if (i < argc - 1) {
XX! 			i++;
XX! 			tststring[0] = argv[i];
XX! 			strcount = 1;
XX! 		} else {
XX! 			fprintf(stderr, "%s: not enough arguments\n");
XX! 			exit(2);
XX! 		}
XX! 		break;
XX! 	    case 'v':	vflag = 1;	break;
XX! 	    case 'c':	cflag = 1;	break;
XX! 	    case 'l':	lflag = 1;	break;
XX! 	    case 's':	sflag = 1;	break;
XX! 	    case 'h':	hflag = 1;	break;
XX! 	    case 'n':	nflag = 1;	break;
XX! 	    case 'f':
XX! 		fflag = 1;
XX! 		if (eflag) {
XX! 		    fprintf(stderr, 
XX! 		       "%s: can't have -e and -f at the same time\n", argv[0]);
XX! 		    exit(2);
XX! 		}
XX! 		if (i >= argc - 1) {
XX! 			fprintf(stderr, "%s: not enough arguments\n");
XX! 			exit(2);
XX! 		} else {
XX! 			i++;
XX! 			if ((fp = open(argv[i], O_RDONLY)) < 0) {
XX! 				fprintf(stderr, 
XX! 				      "%s: can't open %s\n", argv[0], argv[i]);
XX! 				exit(2);
XX! 			}
XX! 			strcount = 0;
XX! 			while ((tmp = getlin(fp, &stringarea[strptr], 128)) != EOF) {
XX! 				tststring[strcount++] = &stringarea[strptr];
XX! 				strptr = strptr + tmp + 1;
XX! 				if (strptr >= 1024 - 128 || strcount == 32) {
XX! 					fprintf(stderr, "%s: not enough room\n", argv[0]);
XX! 					exit(2);
XX! 				}
XX! 			}
XX! 			close(fp);
XX! 		}
XX! 		break;
XX! 	    default:
XX! 		fprintf(stderr, "%s: invalid command line option\n", argv[0]);
XX! 		exit(2);
XX! 		break;
XX! 	}
XX! 	if (cflag && lflag) {
XX! 		fprintf(stderr, "%s: cannot have -l and -c at the same time\n", argv[0]);
XX! 		exit(2);
XX! 	}
XX!   }
XX  
XX!   if (!eflag && !fflag) {
XX! 	if (i < argc) {
XX! 		tststring[0] = argv[i++];
XX! 		strcount = 1;
XX! 	} else {
XX! 		fprintf(stderr, "%s: no search string.\n", argv[0]);
XX! 		exit(2);
XX! 	}
XX!   }
XX!   for (j = 0; j < strcount; j++) {
XX! 	if (tststring[j][0] == '"') {
XX! 		count = strlen(tststring[j]);
XX! 		movmem(&tststring[j][1], tststring[j], count - 2);
XX! 		tststring[j][count - 2] = '\0';
XX! 	}
XX! 	maktbl(tststring[j], tbl[j], &lengths[j]);
XX!   }
XX  }
XX  
XX! 
XX! movmem(src, dst, len)
XX! char *src, *dst;
XX! int len;
XX  {
XX!   while (len--) *dst++ = *src++;
XX  }
XX  
XX! setmem(mem, len, filler)
XX! char *mem;
XX! int len;
XX! char filler;
XX  {
XX!   while (len--) *mem++ = filler;
XX  }
XX  
XX! 
XX! int find(findword, table, wordlen)
XX! unsigned char *findword;
XX! unsigned char *table;
XX! int wordlen;
XX  {
XX!   auto int lastletter, tmp;
XX  
XX!   boundary = stringlen - wordlen;
XX!   lastletter = wordlen - 1;
XX!   offset = 0;
XX!   while (offset <= boundary) {
XX! 	tmp = table[string[offset + lastletter]];
XX! 	if (tmp) {
XX! 		offset += tmp;
XX! 	} else {
XX! 		for (k = lastletter - 1; k >= 0; k--) {
XX! 			if ((string[k + offset]) != findword[k]) {
XX! 				offset++;
XX! 				break;
XX! 			}
XX! 		}
XX! 		if (k < 0) return(1);
XX  	}
XX    }
XX!   return(0);
XX  }
XX  
XX! 
XX! void maktbl(findword, table, wordlen)
XX! unsigned char *findword;
XX! unsigned char *table;
XX! int *wordlen;
XX  {
XX  
XX!   auto int i, len;
XX! 
XX!   *wordlen = len = strlen(findword);
XX!   setmem(table, 256, len);
XX!   for (i = 0; i < len; i++) table[findword[i]] = len - i - 1;
XX  }
XX  
XX! 
XX! void gotone()
XX  {
XX!   hadone = 1;
XX  
XX!   if (cflag || lflag || sflag) {
XX! 	count++;
XX! 	return;
XX    }
XX!   if (!nofname) printf("%s:", argv[i]);
XX  
XX!   if (nflag) printf("%d:", linum);
XX! 
XX!   printf("%s\n", string);
XX  }
XX  
XX! 
XX! int getlin(infile, buf, maxlen)
XX! int infile;
XX! char *buf;
XX! int maxlen;
XX  {
XX!   static char mybuf[2048];
XX!   static char *low;
XX!   static char *high;
XX  
XX!   auto int status;
XX!   auto char *p = buf;
XX!   auto int endline;
XX! 
XX!   *p = '\0';
XX!   maxlen--;
XX    while (1) {
XX! 	endline = 0;
XX! 	while (low < high && !endline) {
XX! 		if (p >= &buf[maxlen]) {	/* overflow, skip all
XX! 						 * until \n */
XX! 			while (low < high && *low != '\n') low++;
XX! 			endline = (*low == '\n');
XX! 		} else
XX! 			endline = ((*p++ = *low++) == '\n');
XX! 
XX! 	}			/* exhausted buffer or found \n */
XX! 
XX! 	/* Don't continue if \n found */
XX! 	if (endline) {
XX! 		*(p - 1) = '\0';
XX! 		return(p - buf - 1);
XX  	}
XX- 	status = read(infile, mybuf, 2048);
XX- 	if (status <= 0) break;
XX  
XX! 	low = mybuf;
XX! 	high = &mybuf[status];
XX  
XX    }
XX  
XX!   /* Empty line or a bit filled ? */
XX!   *p = '\0';
XX!   if (status < 0) {
XX! 	perror("read error");
XX! 	return(EOF);
XX!   }
XX!   if (p - buf) return(p - buf);
XX!   return(EOF);
XX! 
XX! }				/* of getlin() */
XX--- 1,355 ----
XX! /* fgrep - fast grep			Author: Bert Gijsbers */
XX  
XX+ /* Copyright (c) 1991 by Bert Gijsbers.  All rights reserved.
XX+  * Permission to use and redistribute this software is hereby granted provided
XX+  * that this copyright notice remains intact and that any modifications are
XX+  * clearly marked as such.
XX+  *
XX+  * syntax:
XX+  *	fgrep -chlnsv <[-e string] ... [-f file] ... | string> [file] ...
XX+  * options:
XX+  *	-c : print the number of matching lines
XX+  *	-h : don't print file name headers if more than one file
XX+  *	-l : print only the file names of the files containing a match
XX+  *	-n : print line numbers
XX+  *	-s : don't print, return status only
XX+  *	-v : reverse, lines not containing one of the strings match
XX+  *	-e string : search for this string
XX+  *	-f file : file contains strings to search for
XX+  * notes:
XX+  *	Options are processed by getopt(3).
XX+  *	Multiple strings per command line are supported, eg.
XX+  *		fgrep -e str1 -e str2 *.c
XX+  *	Instead of a filename - is allowed, meaning standard input.
XX+  */
XX+ 
XX+ /* #include <ansi.h> */
XX  #include <sys/types.h>
XX+ #include <unistd.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX+ #define MAX_STR_LEN	 256	/* maximum length of strings to search for */
XX+ #define BYTE		0xFF	/* convert from char to int */
XX+ #define READ_SIZE	4096	/* read() request size */
XX+ #define BUF_SIZE (2*READ_SIZE)	/* size of buffer */
XX+ 
XX+ typedef struct test_str {
XX+   struct test_str *next;	/* linked list */
XX+   char *str;			/* string to be found */
XX+   char *str_end;		/* points to last character */
XX+   int len;			/* string length */
XX+   char *bufp;			/* pointer into input buffer */
XX+   unsigned char table[256];	/* table for Boyer-Moore algorithm */
XX+ } test_str;
XX+ 
XX+ test_str *strings;
XX+ char *prog_name;
XX+ int cflag, hflag, lflag, nflag, sflag, vflag;
XX+ unsigned line_num;		/* line number in current file */
XX+ 
XX+ int fd_in, eof_seen;		/* file descriptor for input and eof status */
XX+ char input_buffer[BUF_SIZE + 2];/* buffer + sentinel margin */
XX+ #define buffer	(&input_buffer[2])
XX+ 
XX+ /* Pointers into the input buffer */
XX+ char *input;			/* points to current input char */
XX+ char *max_input;		/* points to first invalid char */
XX+ char *buf_end;			/* points to first char not read */
XX+ 
XX+ /* Error messages */
XX+ char no_mem[] = "not enough memory";
XX+ char no_arg[] = "argument missing";
XX+ 
XX+ extern char *optarg;
XX+ extern int optind;
XX+ 
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(char *search_str, (test_str * ts));
XX+ _PROTOTYPE(int fill_buffer, (void));
XX+ _PROTOTYPE(void failure, (char *mesg));
XX+ _PROTOTYPE(void file_open, (void));
XX+ _PROTOTYPE(void usage, (void));
XX+ _PROTOTYPE(char *get_line, (void));
XX+ _PROTOTYPE(void string_file, (void));
XX+ _PROTOTYPE(void add_string, (char *str));
XX+ _PROTOTYPE(int getopt, (int argc, char **argv, char *optstring));
XX+ 
XX+ int main(argc, argv)
XX  int argc;
XX  char **argv;
XX! {
XX!   char *line;
XX!   int c;
XX!   unsigned count;		/* number of matching lines in current file */
XX!   unsigned found_one = 0;	/* was there any match in any file at all ? */
XX  
XX! #ifdef noperprintf
XX!   noperprintf(stdout);
XX! #else
XX!   static char outbuf[BUFSIZ];
XX  
XX!   setvbuf(stdout, outbuf, _IOFBF, sizeof outbuf);
XX! #endif
XX  
XX!   prog_name = argv[0];
XX!   if (argc == 1) usage();
XX!   while ((c = getopt(argc, argv, "ce:f:hlnsv")) != EOF) {
XX! 	switch (c) {
XX! 	    case 'c':	cflag++;	break;
XX! 	    case 'e':	add_string(optarg);	break;
XX! 	    case 'f':	string_file();	break;
XX! 	    case 'h':	hflag++;	break;
XX! 	    case 'l':	lflag++;	break;
XX! 	    case 'n':	nflag++;	break;
XX! 	    case 's':	sflag++;	break;
XX! 	    case 'v':	vflag++;	break;
XX! 	    default:	usage();	break;
XX! 	}
XX!   }
XX  
XX!   /* If no -e or -f option is used take a string from the command line. */
XX!   if (strings == (test_str *) NULL) {
XX! 	if (optind == argc) failure(no_arg);
XX! 	add_string(argv[optind++]);
XX!   }
XX!   if (argc - optind < 2)
XX! 	hflag++;		/* don't print filenames if less than two
XX! 			 * files */
XX  
XX+   /* Handle every matching line according to the flags. */
XX    do {
XX! 	optarg = argv[optind];
XX! 	file_open();
XX  	count = 0;
XX! 	while ((line = get_line()) != (char *) NULL) {
XX! 		count++;
XX! 		if (sflag) return 0;
XX! 		if (lflag) {
XX! 			printf("%s\n", optarg);
XX! 			fflush(stdout);
XX! 			break;
XX  		}
XX! 		if (cflag) continue;
XX! 		if (hflag == 0) printf("%s:", optarg);
XX! 		if (nflag) printf("%u:", line_num);
XX! 		do {
XX! 			putchar(*line);
XX! 		} while (++line < input);
XX! 		fflush(stdout);
XX  	}
XX! 	found_one |= count;
XX  	if (cflag) {
XX! 		if (hflag == 0) printf("%s: ", optarg);
XX! 		printf("%u\n", count);
XX! 		fflush(stdout);
XX  	}
XX! 	close(fd_in);
XX!   } while (++optind < argc);
XX  
XX!   /* Exit nonzero if no match is found. */
XX!   return found_one ? 0 : 1;
XX  }
XX  
XX! void usage()
XX  {
XX!   fprintf(stderr,
XX! 	"Usage: %s -chlnsv <[-e string] ... [-f file] ... | string> [file] ...\n",
XX! 	prog_name);
XX!   exit(2);
XX! }
XX  
XX! void failure(mesg)
XX! char *mesg;
XX! {
XX!   fprintf(stderr, "%s: %s\n", prog_name, mesg);
XX!   exit(1);
XX  }
XX  
XX! /* Add a string to search for to the global linked list `strings'. */
XX! void add_string(str)
XX! char *str;
XX  {
XX!   test_str *ts;
XX!   int len;
XX! 
XX!   if (str == (char *) NULL || (len = strlen(str)) == 0) return;
XX!   if (len > MAX_STR_LEN) failure("string too long");
XX!   if ((ts = (test_str *) malloc(sizeof(*ts))) == (test_str *) NULL)
XX! 	failure(no_mem);
XX! 
XX!   /* Initialize Boyer-Moore table. */
XX!   memset(ts->table, len, sizeof(ts->table));
XX!   ts->len = len;
XX!   ts->str = str;
XX!   ts->str_end = str + len - 1;
XX!   for (; --len >= 0; str++) ts->table[*str & BYTE] = len;
XX! 
XX!   /* Put it on the list */
XX!   ts->next = strings;
XX!   strings = ts;
XX  }
XX  
XX! /* Open a file for reading.  Initialize input buffer pointers. */
XX! void file_open()
XX  {
XX!   /* Use stdin if no file arguments are given on the command line. */
XX!   if (optarg == (char *) NULL || strcmp(optarg, "-") == 0) {
XX! 	fd_in = 0;
XX! 	optarg = "stdin";
XX!   } else if ((fd_in = open(optarg, O_RDONLY)) == -1) {
XX! 	fprintf(stderr, "%s: can't open %s\n", prog_name, optarg);
XX! 	exit(1);
XX!   }
XX!   input = max_input = buf_end = buffer;
XX!   buffer[-1] = '\n';		/* sentinel */
XX!   eof_seen = 0;
XX!   line_num = 0;
XX  }
XX  
XX! /* Move any leftover characters to the head of the buffer.
XX!  * Read characters into the rest of the buffer.
XX!  * Round off the available input to whole lines.
XX!  * Return the number of valid input characters.
XX!  */
XX! int fill_buffer()
XX  {
XX!   char *bufp;
XX!   int size;
XX  
XX!   if (eof_seen) return 0;
XX! 
XX!   size = buf_end - max_input;
XX!   memmove(buffer, max_input, size);
XX!   bufp = &buffer[size];
XX! 
XX!   do {
XX! 	if ((size = read(fd_in, bufp, READ_SIZE)) <= 0) {
XX! 		if (size != 0) failure("read error");
XX! 		eof_seen++;
XX! 		if (bufp == buffer)	/* no input left */
XX! 			return 0;
XX! 		/* Make sure the last char of a file is '\n'. */
XX! 		*bufp++ = '\n';
XX! 		break;
XX  	}
XX+ 	bufp += size;
XX+   } while (bufp - buffer < READ_SIZE && bufp[-1] != '\n');
XX+ 
XX+   buf_end = bufp;
XX+   while (*--bufp != '\n');
XX+   if (++bufp == buffer) {
XX+ 	/* Line too long. */
XX+ 	*buf_end++ = '\n';
XX+ 	bufp = buf_end;
XX    }
XX!   max_input = bufp;
XX!   input = buffer;
XX! 
XX!   return max_input - buffer;
XX  }
XX  
XX! /* Read strings from a file.  Give duplicates to add_string(). */
XX! void string_file()
XX  {
XX+   char *str, *p;
XX  
XX!   file_open();
XX!   while (input < max_input || fill_buffer() > 0) {
XX! 	p = (char *) memchr(input, '\n', BUF_SIZE);
XX! 	*p++ = '\0';
XX! 	if ((str = (char *) malloc(p - input)) == (char *) NULL)
XX! 		failure(no_mem);
XX! 	memcpy(str, input, p - input);
XX! 	add_string(str);
XX! 	input = p;
XX!   }
XX!   close(fd_in);
XX  }
XX  
XX! /* Scan the rest of the available input for a string using Boyer-Moore.
XX!  * Return a pointer to the match or a pointer beyond end of input if no match.
XX!  * Record how far the input is scanned.
XX!  */
XX! char *search_str(ts)
XX! test_str *ts;
XX  {
XX!   char *bufp, *prevbufp, *s;
XX  
XX!   bufp = input + ts->len - 1;
XX!   while (bufp < max_input) {
XX! 	prevbufp = bufp;
XX! 	bufp += ts->table[*bufp & BYTE];
XX! 	if (bufp > prevbufp) continue;
XX! 	s = ts->str_end;
XX! 	do {
XX! 		if (s == ts->str) {	/* match found */
XX! 			ts->bufp = bufp;
XX! 			return bufp;
XX! 		}
XX! 	} while (*--bufp == *--s);
XX! 	bufp = prevbufp + 1;
XX    }
XX!   ts->bufp = bufp;
XX  
XX!   return bufp;
XX  }
XX  
XX! /* Return the next line in which one of the strings occurs.
XX!  * Or, if the -v option is used, the next line without a match.
XX!  * Or NULL on EOF.
XX!  */
XX! char *get_line()
XX  {
XX!   test_str *ts;
XX!   char *match, *line;
XX  
XX!   /* Loop until a line is found. */
XX    while (1) {
XX! 	if (input >= max_input && fill_buffer() == 0) {	/* EOF */
XX! 		line = (char *) NULL;
XX! 		break;
XX  	}
XX  
XX! 	/* If match is still equal to max_input after the next loop
XX! 	 * then no match is found. */
XX! 	match = max_input;
XX! 	ts = strings;
XX! 	do {
XX! 		if (input == buffer) {
XX! 			if (search_str(ts) < match) match = ts->bufp;
XX! 		} else if (ts->bufp < match) {
XX! 			if (ts->bufp >= input || search_str(ts) < match)
XX! 				match = ts->bufp;
XX! 		}
XX! 	} while ((ts = ts->next) != (test_str *) NULL);
XX  
XX+ 	/* Determine if and in what line a match is found. Only do
XX+ 	 * line number counting if it is necessary or very easy. */
XX+ 	if (vflag) {
XX+ 		line_num++;
XX+ 		line = input;
XX+ 		input = 1 + (char *) memchr(line, '\n', BUF_SIZE);
XX+ 		if (input <= match) break;	/* no match in current line */
XX+ 	} else if (nflag) {
XX+ 		do {
XX+ 			line_num++;
XX+ 			line = input;
XX+ 			input = 1 + (char *) memchr(line, '\n', BUF_SIZE);
XX+ 		} while (input < match ||
XX+ 			 (input == match && match < max_input));
XX+ 		if (match < max_input) break;	/* match found */
XX+ 	} else if (match < max_input) {
XX+ 		/* Match found. */
XX+ 		for (line = match; *--line != '\n';);
XX+ 		line++;
XX+ 		input = 1 + (char *) memchr(match, '\n', BUF_SIZE);
XX+ 		break;
XX+ 	} else
XX+ 		input = max_input;
XX    }
XX  
XX!   return line;
XX! }
X/
Xecho x - file.c.d
Xsed '/^X/s///' > file.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/file.c  crc=33491   4174	Sun Apr 25 21:34:56 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/file.c  crc=26023   5386	Wed Nov  4 04:19:11 1992
XX***************
XX*** 1,26 ****
XX  /* file - report on file type.		Author: Andy Tanenbaum */
XX  
XX  #include <blocksize.h>
XX- #include <ar.h>
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX! #include <minix/config.h>
XX  
XX- #if (CHIP == M68000)
XX- #define A_OUT		0x410	/* magic number for executables */
XX- #define A_OUT_SPLIT	0x420	/* magic number for executables split I/D */
XX- #define A_OUT_SEC	0x301	/* second check for executables */
XX- #define OBJECT		0x102	/* minix/st object */
XX- #else
XX- #define A_OUT 001401		/* magic number for executables */
XX- #define SPLIT 002040		/* second word on split I/D binaries */
XX- #endif
XX  #define XBITS 00111		/* rwXrwXrwX (x bits in the mode) */
XX  #define ENGLISH 25		/* cutoff for determining if text is Eng. */
XX! char buf[BLOCK_SIZE];
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 1,72 ----
XX  /* file - report on file type.		Author: Andy Tanenbaum */
XX+ /* Magic number detection changed to look-up table 08-Jan-91 - ajm */
XX  
XX  #include <blocksize.h>
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX! #include <stdlib.h>
XX! #include <unistd.h>
XX! #include <stdio.h>
XX  
XX  #define XBITS 00111		/* rwXrwXrwX (x bits in the mode) */
XX  #define ENGLISH 25		/* cutoff for determining if text is Eng. */
XX! unsigned char buf[BLOCK_SIZE];
XX  
XX! struct info {
XX!   int match;			/* No of bytes to match for success */
XX!   int execflag;			/* 1 == ack executable, 2 == gnu executable */
XX!   unsigned char magic[4];	/* First four bytes of the magic number */
XX!   char *description;		/* What it means */
XX! } table[] = {
XX!   0x03, 0x00, 0x1f, 0x9d, 0x8d, 0x00,
XX! 	"13-bit compressed file",
XX!   0x03, 0x00, 0x1f, 0x9d, 0x90, 0x00,
XX! 	"16-bit compressed file",
XX!   0x02, 0x00, 0x65, 0xff, 0x00, 0x00,
XX! 	"MINIX-PC bcc archive",
XX!   0x02, 0x00, 0x2c, 0xff, 0x00, 0x00, 
XX! 	"MINIX-68k ack archive",
XX!   0x02, 0x00, 0x65, 0xff, 0x00, 0x00, 
XX! 	"MINIX-PC ack archive",
XX!   0x04, 0x00, 0x47, 0x6e, 0x75, 0x20, 
XX! 	"MINIX-68k gnu archive",
XX!   0x04, 0x00, 0x21, 0x3c, 0x61, 0x72, 
XX! 	"MINIX-PC gnu archive",
XX!   0x02, 0x00, 0x01, 0x02, 0x00, 0x00, 
XX! 	"MINIX-68k ack object file",
XX!   0x02, 0x00, 0xa3, 0x86, 0x00, 0x00, 
XX! 	"MINIX-PC bcc object file",
XX!   0x04, 0x00, 0x00, 0x00, 0x01, 0x07, 
XX! 	"MINIX-68k gnu object file",
XX!   0x04, 0x00, 0x07, 0x01, 0x00, 0x00, 
XX! 	"MINIX-PC gnu object file",
XX!   0x04, 0x01, 0x01, 0x03, 0x10, 0x04, 
XX! 	"MINIX-PC 16-bit executable combined I & D space",
XX!   0x04, 0x01, 0x01, 0x03, 0x20, 0x04, 
XX! 	"MINIX-PC 16-bit executable separate I & D space",
XX!   0x04, 0x01, 0x01, 0x03, 0x20, 0x10, 
XX! 	"MINIX-PC 32-bit executable combined I & D space",
XX!   0x04, 0x01, 0x01, 0x03, 0x10, 0x10, 
XX! 	"MINIX-PC 32-bit executable separate I & D space",
XX!   0x04, 0x01, 0x04, 0x10, 0x03, 0x01, 
XX! 	"MINIX-68k old style executable",
XX!   0x04, 0x01, 0x01, 0x03, 0x10, 0x0b, 
XX! 	"MINIX-68k new style executable",
XX!   0x04, 0x02, 0x0b, 0x01, 0x00, 0x00, 
XX! 	"MINIX-PC 32-bit gnu executable combined I & D space",
XX!   0x04, 0x02, 0x00, 0x00, 0x0b, 0x01, 
XX! 	"MINIX-68k gnu executable"
XX! };
XX! 
XX! int tabsize = sizeof(table) / sizeof(struct info);
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void file, (char *name));
XX! _PROTOTYPE(void do_strip, (int type));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 32,46 ****
XX  
XX    if (argc < 2) usage();
XX    for (i = 1; i < argc; i++) file(argv[i]);
XX  }
XX  
XX! file(name)
XX  char *name;
XX  {
XX!   int i, fd, n, magic, second, mode, nonascii, special, funnypct, etaoins;
XX!   int symbols;
XX    long engpct;
XX!   char c;
XX    struct stat st_buf;
XX  
XX    printf("%s: ", name);
XX--- 78,93 ----
XX  
XX    if (argc < 2) usage();
XX    for (i = 1; i < argc; i++) file(argv[i]);
XX+   return(0);
XX  }
XX  
XX! void file(name)
XX  char *name;
XX  {
XX!   int i, fd, n, mode, nonascii, special, funnypct, etaoins;
XX!   int j, matches;
XX    long engpct;
XX!   int c;
XX    struct stat st_buf;
XX  
XX    printf("%s: ", name);
XX***************
XX*** 75,139 ****
XX  	close(fd);
XX  	return;
XX    }
XX!   n = read(fd, buf, BLOCK_SIZE);
XX    if (n < 0) {
XX  	printf("cannot read\n");
XX  	close(fd);
XX  	return;
XX    }
XX! 
XX!   /* Check to see if file is an archive. */
XX! #if (CHIP == M68000)
XX!   magic = (buf[0] << 8) | (buf[1] & 0377);
XX!   if (magic == 026377) {
XX! #else
XX!   magic = (buf[1] << 8) | (buf[0] & 0377);
XX!   if (magic == ARMAG) {
XX! #endif
XX! 	printf("archive\n");
XX! 	close(fd);
XX! 	return;
XX    }
XX- #if (CHIP == M68000)
XX-   /* Check to see if file is an object file. */
XX-   if (magic == OBJECT) {
XX- 	printf("MINIX/ST object file\n");
XX- 	close(fd);
XX- 	return;
XX-   }
XX- #endif
XX  
XX!   /* Check to see if file is an executable binary. */
XX! #if (CHIP != M68000)
XX!   if (magic == A_OUT) {
XX! 	/* File is executable.  Check for split I/D. */
XX! 	printf("MINIX/PC executable");
XX! 	second = (buf[3] << 8) | (buf[2] & 0377);
XX! 	if (second == SPLIT)
XX! 		printf("   separate I & D space");
XX! 	else
XX! 		printf("   combined I & D space");
XX! #else
XX!   if (magic == A_OUT || magic == A_OUT_SPLIT) {
XX! 	/* File is executable.  Check for split I/D. */
XX! 	printf("MINIX/ST executable");
XX! 	second = (buf[2] << 8) | (buf[3] & 0377);
XX! 	if (second == A_OUT_SEC) {
XX! 		if (magic == A_OUT_SPLIT)
XX! 			printf("   separate I & D space");
XX! 		else
XX! 			printf("   combined I & D space");
XX! 	}
XX! #endif
XX! 	symbols = buf[28] | buf[29] | buf[30] | buf[31];
XX! 	if (symbols != 0)
XX! 		printf("   not stripped\n");
XX! 	else
XX! 		printf("   stripped\n");
XX! 	close(fd);
XX! 	return;
XX    }
XX  
XX    /* Check to see if file is a shell script. */
XX    if (mode & XBITS) {
XX  	/* Not a binary, but executable.  Probably a shell script. */
XX--- 122,153 ----
XX  	close(fd);
XX  	return;
XX    }
XX!   n = read(fd, (char *)buf, BLOCK_SIZE);
XX    if (n < 0) {
XX  	printf("cannot read\n");
XX  	close(fd);
XX  	return;
XX    }
XX!   if (n == 0) {       /* must check this, for loop will fail otherwise !! */
XX!       printf("empty file\n");
XX!       close(fd);
XX!       return;
XX    }
XX  
XX!   for (i = 0; i < tabsize; i++) {
XX! 	matches = 0;
XX! 	for (j = 0; j < table[i].match; j++)
XX! 		if (buf[j] == table[i].magic[j])
XX! 			matches++;
XX! 	if (matches == table[i].match) {
XX! 		printf("%s", table[i].description);
XX! 		do_strip(table[i].execflag);
XX! 		close(fd);
XX! 		return;
XX! 		}
XX    }
XX  
XX+ 
XX    /* Check to see if file is a shell script. */
XX    if (mode & XBITS) {
XX  	/* Not a binary, but executable.  Probably a shell script. */
XX***************
XX*** 166,172 ****
XX  		if (engpct > (long) ENGLISH)
XX  			printf("English text\n");
XX  		else
XX! 			printf("ASCII text\n", engpct);
XX  	}
XX  	close(fd);
XX  	return;
XX--- 180,186 ----
XX  		if (engpct > (long) ENGLISH)
XX  			printf("English text\n");
XX  		else
XX! 			printf("ASCII text\n");
XX  	}
XX  	close(fd);
XX  	return;
XX***************
XX*** 178,184 ****
XX    return;
XX  }
XX  
XX! usage()
XX  {
XX    printf("Usage: file name ...\n");
XX    exit(1);
XX--- 192,220 ----
XX    return;
XX  }
XX  
XX! void do_strip(type)
XX! int type;
XX! {
XX!   if (type == 1) {	/* Non-GNU executable */
XX! 	if (( buf[28] | buf[29] | buf[30] | buf[31]) != 0)
XX! 		printf(" not stripped\n");
XX! 	else
XX! 		printf(" stripped\n");
XX! 	return;
XX!   }
XX! 
XX!   if (type == 2) {	/* GNU format executable */
XX!      if ((buf[16] | buf[17] | buf[18] | buf[19]) != 0)
XX! 	 printf(" not stripped\n");
XX!      else
XX! 	 printf(" stripped\n");
XX!      return;
XX!   }
XX! 
XX!   printf("\n");		/* Not an executable file */
XX!  }
XX! 
XX! void usage()
XX  {
XX    printf("Usage: file name ...\n");
XX    exit(1);
X/
Xecho x - find.c.d
Xsed '/^X/s///' > find.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/find.c  crc=14843  12930	Sun Apr 25 21:34:57 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/find.c  crc=18379  21160	Sun Jan 17 20:52:40 1993
XX***************
XX*** 1,90 ****
XX! /* find - look for files satisfying a predicat	Author: Erik Baalbergen */
XX  
XX! /*
XX!    *** Check the switches in the SWITCHES section below. ***
XX  
XX-    Differences from UNIX version 7 find(1):
XX-   * -name: no name allowed; only uid
XX- 	e.g. find all core files: "find . -name core -a -print"
XX-   * -xdev: do not cross file system boundaries
XX- 
XX-    The "-atime" may not work well on Minix.
XX-    Please report bugs and suggestions to erikb@cs.vu.nl
XX- */
XX- 
XX- 
XX  #include <sys/types.h>
XX- #include <fcntl.h>
XX  #include <sys/stat.h>
XX  #include <stdio.h>
XX  
XX! #define SHELL "/usr/bin/sh"
XX  
XX! #define PLEN	256		/* maximum path length; overflows are not
XX! 			 * detected */
XX! #define DIRSIZ	16		/* size of a directory entry */
XX! #define MAXARG	256		/* maximum length for an argv */
XX! #define NPATHS	256		/* maximum number of paths in path-list */
XX! #define BSIZE  1024		/* bytes per block */
XX  
XX! /*######################## DEFINITIONS ##############################*/
XX! #define SECS_PER_DAY	(24L * 60L * 60L)	/* check your planet */
XX  
XX  struct exec {
XX    int e_cnt;
XX    char *e_vec[MAXARG];
XX  };
XX  
XX- #define OP_NAME		1
XX- #define OP_PERM		2
XX- #define OP_TYPE		3
XX- #define OP_LINKS	4
XX- #define OP_USER		5
XX- #define OP_GROUP	6
XX- #define OP_SIZE		7
XX- #define OP_INUM		8
XX- #define OP_ATIME	9
XX- #define OP_MTIME	10
XX- #define OP_EXEC		11
XX- #define OP_OK		12
XX- #define OP_PRINT	13
XX- #define OP_NEWER	14
XX- #define OP_AND		15
XX- #define OP_OR		16
XX- #define OP_XDEV		17	/* do not cross file-system boundaries */
XX- 
XX- struct oper {
XX-   char *op_str;
XX-   int op_val;
XX- } ops[] = {
XX-   {	"name",		OP_NAME  },
XX-   {	"perm",		OP_PERM  },
XX-   {	"type",		OP_TYPE  },
XX-   {	"links",	OP_LINKS  },
XX-   {	"user",		OP_USER  },
XX-   {	"group",	OP_GROUP  },
XX-   {	"size",		OP_SIZE  },
XX-   {	"inum",		OP_INUM  },
XX-   {	"atime",	OP_ATIME  },
XX-   {	"mtime",	OP_MTIME  },
XX-   {	"exec",		OP_EXEC  },
XX-   {	"ok",		OP_OK  },
XX-   {	"print",	OP_PRINT  },
XX-   {	"newer",	OP_NEWER  },
XX-   {	"a",		OP_AND  },
XX-   {	"o",		OP_OR  },
XX-   {	"xdev",		OP_XDEV  },
XX-   {	0, 0  }
XX- };
XX- 
XX- #define EOI	-1
XX- #define NONE	0
XX- #define LPAR	20
XX- #define RPAR	21
XX- #define NOT	22
XX- 
XX- char *prog, *strcpy(), *Malloc(), *find_bin();
XX- 
XX  struct node {
XX    int n_type;			/* any OP_ or NOT */
XX    union {
XX--- 1,81 ----
XX! /* find - look for files satisfying a predicate       Author: E. Baalbergen */
XX  
XX! /* Original author: Erik Baalbergen; POSIX compliant version: Bert Laverman */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <sys/wait.h>
XX+ #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <time.h>
XX+ #include <pwd.h>
XX+ #include <grp.h>
XX+ #include <dirent.h>
XX+ #include <limits.h>
XX  #include <stdio.h>
XX  
XX! /*######################## DEFINITIONS ##############################*/
XX  
XX! #ifdef S_IFLNK
XX! #define LSTAT lstat
XX! #else
XX! #define LSTAT stat
XX! #endif
XX  
XX! #define SHELL "/bin/sh"
XX! #define MAXARG          256	/* maximum length for an argv            */
XX! #define NPATHS          256	/* maximum number of paths in path-list */
XX! #define BSIZE           512	/* POSIX wants 512 byte blocks           */
XX! #define SECS_PER_DAY    (24L*60L*60L)	/* check your planet             */
XX  
XX+ #define OP_NAME          1	/* match name                            */
XX+ #define OP_PERM          2	/* check file permission bits            */
XX+ #define OP_TYPE          3	/* check file type bits                  */
XX+ #define OP_LINKS         4	/* check link count                      */
XX+ #define OP_USER          5	/* check owner                           */
XX+ #define OP_GROUP         6	/* check group ownership                 */
XX+ #define OP_SIZE          7	/* check size, blocks or bytes           */
XX+ #define OP_SIZEC         8	/* this is a fake for -size with 'c'     */
XX+ #define OP_INUM          9	/* compare inode number                  */
XX+ #define OP_ATIME        10	/* check last access time                */
XX+ #define OP_CTIME        11	/* check creation time                   */
XX+ #define OP_MTIME        12	/* check last modification time          */
XX+ #define OP_EXEC         13	/* execute command                       */
XX+ #define OP_OK           14	/* execute with confirmation             */
XX+ #define OP_PRINT        15	/* print name                            */
XX+ #define OP_NEWER        16	/* compare modification times            */
XX+ #define OP_AND          17	/* logical and (short circuit)           */
XX+ #define OP_OR           18	/* logical or (short circuit)            */
XX+ #define OP_XDEV         19	/* do not cross file-system boundaries   */
XX+ #define OP_DEPTH        20	/* descend directory before testing      */
XX+ #define OP_PRUNE        21	/* don't descend into current directory  */
XX+ #define OP_NOUSER       22	/* check validity of user id             */
XX+ #define OP_NOGROUP      23	/* check validity of group id            */
XX+ #define LPAR            24	/* left parenthesis                      */
XX+ #define RPAR            25	/* right parenthesis                     */
XX+ #define NOT             26	/* logical not                           */
XX+ 
XX+ /* Some return values: */
XX+ #define EOI             -1	/* end of expression                     */
XX+ #define NONE             0	/* not a valid predicate                 */
XX+ 
XX+ /* For -perm with symbolic modes: */
XX+ #define ISWHO(c)        ((c == 'u') || (c == 'g') || (c == 'o') || (c == 'a'))
XX+ #define ISOPER(c)       ((c == '-') || (c == '=') || (c == '+'))
XX+ #define ISMODE(c)       ((c == 'r') || (c == 'w') || (c == 'x') || \
XX+ 			 (c == 's') || (c == 't'))
XX+ #define MUSER           1
XX+ #define MGROUP          2
XX+ #define MOTHERS         4
XX+ 
XX+ 
XX  struct exec {
XX    int e_cnt;
XX    char *e_vec[MAXARG];
XX  };
XX  
XX  struct node {
XX    int n_type;			/* any OP_ or NOT */
XX    union {
XX***************
XX*** 99,160 ****
XX  	} n_opnd;
XX    } n_info;
XX  };
XX- struct node *expr();
XX  
XX! char **ipp;
XX! int tty;			/* fd for /dev/tty when using -ok */
XX! long current_time;
XX! int xdev_flag = 0;
XX! int devnr;
XX  
XX! char *
XX!  Malloc(n)
XX  {
XX!   char *malloc(), *m;
XX  
XX!   if ((m = malloc(n)) == 0) fatal("out of memory", "");
XX    return m;
XX  }
XX  
XX! char *
XX!  Salloc(s)
XX  char *s;
XX  {
XX    return strcpy(Malloc(strlen(s) + 1), s);
XX  }
XX  
XX! main(argc, argv)
XX  char *argv[];
XX  {
XX    char *pathlist[NPATHS];
XX!   int pathcnt = 0;
XX!   register i;
XX    struct node *pred;
XX  
XX!   prog = *argv++;
XX!   while (--argc > 0 && lex(*argv) == NONE) pathlist[pathcnt++] = *argv++;
XX!   if (pathcnt == 0 || argc == 0)
XX! 	fatal("Usage: path-list predicate-list", "");
XX!   ipp = argv;
XX!   time(&current_time);
XX!   pred = expr(lex(*ipp));
XX!   if (lex(*++ipp) != EOI)
XX! 	fatal("syntax error: garbage at end of predicate", "");
XX    for (i = 0; i < pathcnt; i++) {
XX  	if (xdev_flag) xdev_flag = 2;
XX  	find(pathlist[i], pred, "");
XX    }
XX!   exit(0);
XX  }
XX  
XX! find(path, pred, last)
XX  char *path, *last;
XX  struct node *pred;
XX  {
XX!   char spath[PLEN], ent[DIRSIZ + 1];
XX    struct stat st;
XX!   register char *send = spath;
XX!   FILE *fp, *fopen();
XX  
XX    if (path[1] == '\0' && *path == '/') {
XX  	*send++ = '/';
XX--- 90,273 ----
XX  	} n_opnd;
XX    } n_info;
XX  };
XX  
XX! struct oper {
XX!   char *op_str;
XX!   int op_val;
XX! } ops[] = {
XX  
XX!   {
XX! 	"name", OP_NAME
XX!   },
XX!   {
XX! 	"perm", OP_PERM
XX!   },
XX!   {
XX! 	"type", OP_TYPE
XX!   },
XX!   {
XX! 	"links", OP_LINKS
XX!   },
XX!   {
XX! 	"user", OP_USER
XX!   },
XX!   {
XX! 	"group", OP_GROUP
XX!   },
XX!   {
XX! 	"size", OP_SIZE
XX!   },
XX!   {
XX! 	"inum", OP_INUM
XX!   },
XX!   {
XX! 	"atime", OP_ATIME
XX!   },
XX!   {
XX! 	"ctime", OP_CTIME
XX!   },
XX!   {
XX! 	"mtime", OP_MTIME
XX!   },
XX!   {
XX! 	"exec", OP_EXEC
XX!   },
XX!   {
XX! 	"ok", OP_OK
XX!   },
XX!   {
XX! 	"print", OP_PRINT
XX!   },
XX!   {
XX! 	"newer", OP_NEWER
XX!   },
XX!   {
XX! 	"a", OP_AND
XX!   },
XX!   {
XX! 	"o", OP_OR
XX!   },
XX!   {
XX! 	"xdev", OP_XDEV
XX!   },
XX!   {
XX! 	"depth", OP_DEPTH
XX!   },
XX!   {
XX! 	"prune", OP_PRUNE
XX!   },
XX!   {
XX! 	"nouser", OP_NOUSER
XX!   },
XX!   {
XX! 	"nogroup", OP_NOGROUP
XX!   },
XX!   {
XX! 	0, 0
XX!   }
XX! };
XX! 
XX! 
XX! char **ipp;			/* pointer to next argument during parsing       */
XX! char *prog;			/* program name (== argv [0])                    */
XX! char *epath;			/* value of PATH environment string              */
XX! long current_time;		/* for computing age                             */
XX! int tty;			/* fd for /dev/tty when using -ok                */
XX! int xdev_flag = 0;		/* cross device boundaries?                      */
XX! int devnr;			/* device nr of first inode                      */
XX! int depth_flag = 0;		/* descend before check?                         */
XX! int prune_here;			/* This is Baaaad! Don't ever do this again!     */
XX! int um;				/* current umask()                               */
XX! int needprint = 1;		/* implicit -print needed?                       */
XX! 
XX! 
XX! /* The prototypes: */
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(char *Malloc, (int n));
XX! _PROTOTYPE(char *Salloc, (char *s));
XX! _PROTOTYPE(void find, (char *path, struct node * pred, char *last));
XX! _PROTOTYPE(int check, (char *path, struct stat * st, struct node * n, char *last));
XX! _PROTOTYPE(int ichk, (long val, struct node * n));
XX! _PROTOTYPE(int lex, (char *str));
XX! _PROTOTYPE(struct node * newnode, (int t));
XX! _PROTOTYPE(int isnumber, (char *str, int base, int sign));
XX! _PROTOTYPE(void number, (char *str, int base, long *pl, int *ps));
XX! _PROTOTYPE(void fmode, (char *str, long *pl, int *ps));
XX! _PROTOTYPE(struct node * expr, (int t));
XX! _PROTOTYPE(struct node * primary, (int t));
XX! _PROTOTYPE(struct node * secondary, (int t));
XX! _PROTOTYPE(void checkarg, (char *arg));
XX! _PROTOTYPE(struct node * simple, (int t));
XX! _PROTOTYPE(void nonfatal, (char *s1, char *s2));
XX! _PROTOTYPE(void fatal, (char *s1, char *s2));
XX! _PROTOTYPE(int smatch, (char *s, char *t));
XX! _PROTOTYPE(char *find_bin, (char *s));
XX! _PROTOTYPE(int execute, (int op, struct exec * e, char *path));
XX! _PROTOTYPE(void domode, (int op, int *mode, int bits));
XX! 
XX! 
XX! /* Malloc: a certified malloc */
XX! char *Malloc(n)
XX! int n;
XX  {
XX!   char *m;
XX  
XX!   if ((m = (char *) malloc(n)) == (char *) NULL) fatal("out of memory", "");
XX    return m;
XX  }
XX  
XX! /* Salloc: allocate space for a string */
XX! char *Salloc(s)
XX  char *s;
XX  {
XX    return strcpy(Malloc(strlen(s) + 1), s);
XX  }
XX  
XX! 
XX! /* Main: the main body */
XX! int main(argc, argv)
XX! int argc;
XX  char *argv[];
XX  {
XX    char *pathlist[NPATHS];
XX!   int pathcnt = 0, i;
XX    struct node *pred;
XX  
XX!   prog = *argv++;		/* set program name (for diagnostics)    */
XX!   if ((epath = getenv("PATH")) == (char *) NULL)
XX! 	fatal("Can't get path from environment", "");
XX!   (void) umask(um = umask(0));	/* non-destructive get-umask :-)         */
XX!   time(&current_time);		/* get current time                      */
XX! 
XX!   while (--argc > 0 && lex(*argv) == NONE)	/* copy paths            */
XX! 	pathlist[pathcnt++] = *argv++;
XX!   if (pathcnt == 0)		/* there must be at least one path       */
XX! 	fatal("Usage: path-list [predicate-list]", "");
XX! 
XX!   ipp = argv;			/* prepare for parsing                   */
XX!   if (argc != 0) {		/* If there is anything to parse,        */
XX! 	pred = expr(lex(*ipp));	/* then do so                            */
XX! 	if (lex(*++ipp) != EOI)	/* Make sure there's nothing left        */
XX! 		fatal("syntax error: garbage at end of predicate", "");
XX!   } else			/* No predicate list                     */
XX! 	pred = (struct node *) NULL;
XX! 
XX    for (i = 0; i < pathcnt; i++) {
XX  	if (xdev_flag) xdev_flag = 2;
XX  	find(pathlist[i], pred, "");
XX    }
XX!   return 0;
XX  }
XX  
XX! void find(path, pred, last)
XX  char *path, *last;
XX  struct node *pred;
XX  {
XX!   char spath[PATH_MAX];
XX!   register char *send = spath, *p;
XX    struct stat st;
XX!   DIR *dp;
XX!   struct dirent *de;
XX  
XX    if (path[1] == '\0' && *path == '/') {
XX  	*send++ = '/';
XX***************
XX*** 163,274 ****
XX  	while (*send++ = *path++) {
XX  	}
XX  
XX!   if (stat(spath, &st) == -1)
XX  	nonfatal("can't get status of ", spath);
XX    else {
XX  	switch (xdev_flag) {
XX! 	    case 0:
XX  		break;
XX! 	    case 1:
XX  		if (st.st_dev != devnr) return;
XX  		break;
XX! 	    case 2:		/* set current device number */
XX  		xdev_flag = 1;
XX  		devnr = st.st_dev;
XX  		break;
XX  	}
XX  
XX! 	(void) check(spath, &st, pred, last);
XX! 	if ((st.st_mode & S_IFMT) == S_IFDIR) {
XX! 		if ((fp = fopen(spath, "r")) == NULL) {
XX  			nonfatal("can't read directory ", spath);
XX  			return;
XX  		}
XX  		send[-1] = '/';
XX! 		ent[DIRSIZ] = '\0';
XX! 		while (fread(ent, DIRSIZ, 1, fp) == 1) {
XX! 			if (!((*ent == '\0' && ent[1] == '\0')
XX! 			      || (ent[2] == '.') &&
XX! 			      (ent[3] == '\0'
XX! 			       || (ent[3] == '.' && ent[4] == '\0'))
XX! 			      )) {
XX! 				strcpy(send, ent + 2);
XX! 				find(spath, pred, ent + 2);
XX  			}
XX  		}
XX! 		fclose(fp);
XX  	}
XX    }
XX  }
XX  
XX! check(path, st, n, last)
XX  char *path, *last;
XX  register struct stat *st;
XX  register struct node *n;
XX  {
XX    switch (n->n_type) {
XX!       case OP_AND:
XX  	return check(path, st, n->n_info.n_opnd.n_left, last) &&
XX  		check(path, st, n->n_info.n_opnd.n_right, last);
XX!       case OP_OR:
XX  	return check(path, st, n->n_info.n_opnd.n_left, last) ||
XX  		check(path, st, n->n_info.n_opnd.n_right, last);
XX!       case NOT:
XX  	return !check(path, st, n->n_info.n_opnd.n_left, last);
XX!       case OP_NAME:
XX  	return smatch(last, n->n_info.n_str);
XX!       case OP_PERM:
XX  	if (n->n_info.n_int.n_sign < 0)
XX! 		return st->st_mode == (int) n->n_info.n_int.n_val;
XX! 	return(st->st_mode & 0777) == (int) n->n_info.n_int.n_val;
XX!       case OP_NEWER:
XX  	return st->st_mtime > n->n_info.n_int.n_val;
XX!       case OP_TYPE:
XX! 	return(st->st_mode & S_IFMT) == n->n_info.n_int.n_val;
XX!       case OP_LINKS:
XX  	return ichk((long) (st->st_nlink), n);
XX!       case OP_USER:
XX  	return st->st_uid == n->n_info.n_int.n_val;
XX!       case OP_GROUP:
XX  	return st->st_gid == n->n_info.n_int.n_val;
XX!       case OP_SIZE:
XX  	return ichk((st->st_size == 0) ? 0L :
XX! 		    ((st->st_size - 1) / BSIZE + 1), n);
XX!       case OP_INUM:
XX  	return ichk((long) (st->st_ino), n);
XX!       case OP_ATIME:
XX  	return ichk(st->st_atime, n);
XX!       case OP_MTIME:
XX  	return ichk(st->st_mtime, n);
XX!       case OP_EXEC:
XX!       case OP_OK:
XX  	return execute(n->n_type, n->n_info.n_exec, path);
XX!       case OP_PRINT:
XX! 	prints("%s\n", path);
XX  	return 1;
XX!       case OP_XDEV:	return 1;
XX! }
XX    fatal("ILLEGAL NODE", "");
XX  }
XX  
XX! ichk(val, n)
XX  long val;
XX  struct node *n;
XX  {
XX    switch (n->n_info.n_int.n_sign) {
XX!       case 0:
XX  	return val == n->n_info.n_int.n_val;
XX!       case 1:
XX  	return val > n->n_info.n_int.n_val;
XX!       case -1:	return val < n->n_info.n_int.n_val;
XX  }
XX    fatal("internal: bad n_sign", "");
XX  }
XX  
XX! lex(str)
XX  char *str;
XX  {
XX!   if (str == 0) return EOI;
XX    if (*str == '-') {
XX  	register struct oper *op;
XX  
XX--- 276,409 ----
XX  	while (*send++ = *path++) {
XX  	}
XX  
XX!   if (LSTAT(spath, &st) == -1)
XX  	nonfatal("can't get status of ", spath);
XX    else {
XX  	switch (xdev_flag) {
XX! 	  case 0:
XX  		break;
XX! 	  case 1:
XX  		if (st.st_dev != devnr) return;
XX  		break;
XX! 	  case 2:		/* set current device number */
XX  		xdev_flag = 1;
XX  		devnr = st.st_dev;
XX  		break;
XX  	}
XX  
XX! 	prune_here = 0;
XX! 	if (!depth_flag && check(spath, &st, pred, last) && needprint)
XX! 		printf("%s\n", spath);
XX! 	if (!prune_here && (st.st_mode & S_IFMT) == S_IFDIR) {
XX! 		if ((dp = opendir(spath)) == NULL) {
XX  			nonfatal("can't read directory ", spath);
XX  			return;
XX  		}
XX  		send[-1] = '/';
XX! 		while ((de = readdir(dp)) != NULL) {
XX! 			p = de->d_name;
XX! 			if ((de->d_name[0] != '.') || ((de->d_name[1])
XX! 					  && ((de->d_name[1] != '.')
XX! 					      || (de->d_name[2])))) {
XX! 				strcpy(send, de->d_name);
XX! 				find(spath, pred, send);
XX  			}
XX  		}
XX! 		closedir(dp);
XX  	}
XX+ 	if (depth_flag) {
XX+ 		send[-1] = '\0';
XX+ 		if (check(spath, &st, pred, last) && needprint)
XX+ 			printf("%s\n", spath);
XX+ 	}
XX    }
XX  }
XX  
XX! int check(path, st, n, last)
XX  char *path, *last;
XX  register struct stat *st;
XX  register struct node *n;
XX  {
XX+   if (n == (struct node *) NULL) return 1;
XX    switch (n->n_type) {
XX!     case OP_AND:
XX  	return check(path, st, n->n_info.n_opnd.n_left, last) &&
XX  		check(path, st, n->n_info.n_opnd.n_right, last);
XX!     case OP_OR:
XX  	return check(path, st, n->n_info.n_opnd.n_left, last) ||
XX  		check(path, st, n->n_info.n_opnd.n_right, last);
XX!     case NOT:
XX  	return !check(path, st, n->n_info.n_opnd.n_left, last);
XX!     case OP_NAME:
XX  	return smatch(last, n->n_info.n_str);
XX!     case OP_PERM:
XX  	if (n->n_info.n_int.n_sign < 0)
XX! 		return(st->st_mode & (int) n->n_info.n_int.n_val) ==
XX! 			(int) n->n_info.n_int.n_val;
XX! 	return(st->st_mode & 07777) == (int) n->n_info.n_int.n_val;
XX!     case OP_NEWER:
XX  	return st->st_mtime > n->n_info.n_int.n_val;
XX!     case OP_TYPE:
XX! 	return(st->st_mode & S_IFMT) == (mode_t) n->n_info.n_int.n_val;
XX!     case OP_LINKS:
XX  	return ichk((long) (st->st_nlink), n);
XX!     case OP_USER:
XX  	return st->st_uid == n->n_info.n_int.n_val;
XX!     case OP_GROUP:
XX  	return st->st_gid == n->n_info.n_int.n_val;
XX!     case OP_SIZE:
XX  	return ichk((st->st_size == 0) ? 0L :
XX! 		    (long) ((st->st_size - 1) / BSIZE + 1), n);
XX!     case OP_SIZEC:
XX! 	return ichk((long) st->st_size, n);
XX!     case OP_INUM:
XX  	return ichk((long) (st->st_ino), n);
XX!     case OP_ATIME:
XX  	return ichk(st->st_atime, n);
XX!     case OP_CTIME:
XX! 	return ichk(st->st_ctime, n);
XX!     case OP_MTIME:
XX  	return ichk(st->st_mtime, n);
XX!     case OP_EXEC:
XX!     case OP_OK:
XX  	return execute(n->n_type, n->n_info.n_exec, path);
XX!     case OP_PRINT:
XX! 	printf("%s\n", path);
XX  	return 1;
XX!     case OP_XDEV:
XX!     case OP_DEPTH:
XX! 	return 1;
XX!     case OP_PRUNE:
XX! 	prune_here = 1;
XX! 	return 1;
XX!     case OP_NOUSER:
XX! 	return(getpwuid(st->st_uid) == (struct passwd *) NULL);
XX!     case OP_NOGROUP:
XX! 	return(getgrgid(st->st_gid) == (struct group *) NULL);
XX!   }
XX    fatal("ILLEGAL NODE", "");
XX+   return 0;			/* Never reached */
XX  }
XX  
XX! int ichk(val, n)
XX  long val;
XX  struct node *n;
XX  {
XX    switch (n->n_info.n_int.n_sign) {
XX!     case 0:
XX  	return val == n->n_info.n_int.n_val;
XX!     case 1:
XX  	return val > n->n_info.n_int.n_val;
XX!     case -1:	return val < n->n_info.n_int.n_val;
XX  }
XX    fatal("internal: bad n_sign", "");
XX+   return 0;			/* Never reached */
XX  }
XX  
XX! int lex(str)
XX  char *str;
XX  {
XX!   if (str == (char *) NULL) return EOI;
XX    if (*str == '-') {
XX  	register struct oper *op;
XX  
XX***************
XX*** 279,289 ****
XX    }
XX    if (str[1] == 0) {
XX  	switch (*str) {
XX! 	    case '(':
XX  		return LPAR;
XX! 	    case ')':
XX  		return RPAR;
XX! 	    case '!':	return NOT;
XX  	}
XX    }
XX    return NONE;
XX--- 414,424 ----
XX    }
XX    if (str[1] == 0) {
XX  	switch (*str) {
XX! 	  case '(':
XX  		return LPAR;
XX! 	  case ')':
XX  		return RPAR;
XX! 	  case '!':	return NOT;
XX  	}
XX    }
XX    return NONE;
XX***************
XX*** 291,296 ****
XX--- 426,432 ----
XX  
XX  struct node *
XX   newnode(t)
XX+ int t;
XX  {
XX    struct node *n = (struct node *) Malloc(sizeof(struct node));
XX  
XX***************
XX*** 300,314 ****
XX  
XX  /*########################### PARSER ###################################*/
XX  /* Grammar:
XX!   expr : primary | primary OR expr;
XX!   primary : secondary | secondary AND primary | secondary primary;
XX!   secondary : NOT secondary | LPAR expr RPAR | simple;
XX!   simple : -OP args...
XX! */
XX! struct node *expr(), *primary(), *secondary(), *simple();
XX  
XX! number(str, base, pl, ps)
XX  char *str;
XX  long *pl;
XX  int *ps;
XX  {
XX--- 436,464 ----
XX  
XX  /*########################### PARSER ###################################*/
XX  /* Grammar:
XX!  * expr        : primary | primary OR expr;
XX!  * primary     : secondary | secondary AND primary | secondary primary;
XX!  * secondary   : NOT secondary | LPAR expr RPAR | simple;
XX!  * simple      : -OP args...
XX!  */
XX  
XX! /* Isnumber checks correct number syntax. A sign is allowed, but the '+'
XX!  * only if the number is to be in decimal.
XX!  */
XX! int isnumber(str, base, sign)
XX! register char *str;
XX! int base;
XX! int sign;
XX! {
XX!   if (sign && ((*str == '-') || ((base == 8) && (*str == '+')))) str++;
XX!   while ((*str >= '0') && (*str < ('0' + base))) str++;
XX!   return(*str == '\0' ? 1 : 0);
XX! }
XX! 
XX! /* Convert a string to an integer, storing sign info in *ps. */
XX! void number(str, base, pl, ps)
XX  char *str;
XX+ int base;
XX  long *pl;
XX  int *ps;
XX  {
XX***************
XX*** 321,328 ****
XX--- 471,573 ----
XX    *pl = val;
XX  }
XX  
XX+ 
XX+ void domode(op, mode, bits)
XX+ int op;
XX+ int *mode;
XX+ int bits;
XX+ {
XX+   switch (op) {
XX+     case '-':
XX+ 	*mode &= ~bits;
XX+ 	break;			/* clear bits */
XX+     case '=':
XX+ 	*mode |= bits;
XX+ 	break;			/* set bits */
XX+     case '+':
XX+ 	*mode |= (bits & ~um);	/* set, but take umask in account */
XX+   }
XX+ }
XX+ 
XX+ void fmode(str, pl, ps)
XX+ char *str;
XX+ long *pl;
XX+ int *ps;
XX+ {
XX+   int m = 0, w, op;
XX+   char *p = str;
XX+ 
XX+   if (*p == '-') {
XX+ 	*ps = -1;
XX+ 	p++;
XX+   } else
XX+ 	*ps = 0;
XX+ 
XX+   while (*p) {
XX+ 	w = 0;
XX+ 	if (ISOPER(*p))
XX+ 		w = MUSER | MGROUP | MOTHERS;
XX+ 	else if (!ISWHO(*p))
XX+ 		fatal("u, g, o, or a expected: ", p);
XX+ 	else {
XX+ 		while (ISWHO(*p)) {
XX+ 			switch (*p) {
XX+ 			  case 'u':
XX+ 				w |= MUSER;
XX+ 				break;
XX+ 			  case 'g':
XX+ 				w |= MGROUP;
XX+ 				break;
XX+ 			  case 'o':
XX+ 				w |= MOTHERS;
XX+ 				break;
XX+ 			  case 'a':
XX+ 				w = MUSER | MGROUP | MOTHERS;
XX+ 			}
XX+ 			p++;
XX+ 		}
XX+ 		if (!ISOPER(*p)) fatal("-, + or = expected: ", p);
XX+ 	}
XX+ 	op = *p++;
XX+ 	while (ISMODE(*p)) {
XX+ 		switch (*p) {
XX+ 		  case 'r':
XX+ 			if (w & MUSER) domode(op, &m, S_IRUSR);
XX+ 			if (w & MGROUP) domode(op, &m, S_IRGRP);
XX+ 			if (w & MOTHERS) domode(op, &m, S_IROTH);
XX+ 			break;
XX+ 		  case 'w':
XX+ 			if (w & MUSER) domode(op, &m, S_IWUSR);
XX+ 			if (w & MGROUP) domode(op, &m, S_IWGRP);
XX+ 			if (w & MOTHERS) domode(op, &m, S_IWOTH);
XX+ 			break;
XX+ 		  case 'x':
XX+ 			if (w & MUSER) domode(op, &m, S_IXUSR);
XX+ 			if (w & MGROUP) domode(op, &m, S_IXGRP);
XX+ 			if (w & MOTHERS) domode(op, &m, S_IXOTH);
XX+ 			break;
XX+ 		  case 's':
XX+ 			if (w & MUSER) domode(op, &m, S_ISUID);
XX+ 			if (w & MGROUP) domode(op, &m, S_ISGID);
XX+ 			break;
XX+ 		  case 't':
XX+ 			domode(op, &m, S_ISVTX);
XX+ 		}
XX+ 		p++;
XX+ 	}
XX+ 	if (*p) {
XX+ 		if (*p == ',')
XX+ 			p++;
XX+ 		else
XX+ 			fatal("garbage at end of mode string: ", p);
XX+ 	}
XX+   }
XX+   *pl = m;
XX+ }
XX+ 
XX  struct node *
XX   expr(t)
XX+ int t;
XX  {
XX    struct node *nd, *p, *nd2;
XX  
XX***************
XX*** 340,345 ****
XX--- 585,591 ----
XX  
XX  struct node *
XX   primary(t)
XX+ int t;
XX  {
XX    struct node *nd, *p, *nd2;
XX  
XX***************
XX*** 357,362 ****
XX--- 603,609 ----
XX  
XX  struct node *
XX   secondary(t)
XX+ int t;
XX  {
XX    struct node *n, *p;
XX  
XX***************
XX*** 374,380 ****
XX    return simple(t);
XX  }
XX  
XX! checkarg(arg)
XX  char *arg;
XX  {
XX    if (arg == 0) fatal("syntax error, argument expected", "");
XX--- 621,627 ----
XX    return simple(t);
XX  }
XX  
XX! void checkarg(arg)
XX  char *arg;
XX  {
XX    if (arg == 0) fatal("syntax error, argument expected", "");
XX***************
XX*** 382,433 ****
XX  
XX  struct node *
XX   simple(t)
XX  {
XX    struct node *p = newnode(t);
XX    struct exec *e;
XX    struct stat est;
XX    long l;
XX  
XX    switch (t) {
XX!       case OP_TYPE:
XX  	checkarg(*++ipp);
XX  	switch (**ipp) {
XX! 	    case 'b':
XX  		p->n_info.n_int.n_val = S_IFBLK;
XX  		break;
XX! 	    case 'c':
XX  		p->n_info.n_int.n_val = S_IFCHR;
XX  		break;
XX! 	    case 'd':
XX  		p->n_info.n_int.n_val = S_IFDIR;
XX  		break;
XX! 	    case 'f':
XX  		p->n_info.n_int.n_val = S_IFREG;
XX  		break;
XX! 	    default:
XX  		fatal("-type needs b, c, d or f", "");
XX  	}
XX  	break;
XX!       case OP_LINKS:
XX!       case OP_USER:
XX!       case OP_GROUP:
XX!       case OP_SIZE:
XX!       case OP_INUM:
XX!       case OP_PERM:
XX  	checkarg(*++ipp);
XX! 	number(*ipp, (t == OP_PERM) ? 8 : 10, &(p->n_info.n_int.n_val),
XX  	       &(p->n_info.n_int.n_sign));
XX  	break;
XX!       case OP_ATIME:
XX!       case OP_MTIME:
XX  	checkarg(*++ipp);
XX  	number(*ipp, 10, &l, &(p->n_info.n_int.n_sign));
XX  	p->n_info.n_int.n_val = current_time - l * SECS_PER_DAY;
XX  	/* More than n days old means less than the absolute time */
XX  	p->n_info.n_int.n_sign *= -1;
XX  	break;
XX!       case OP_EXEC:
XX!       case OP_OK:
XX  	checkarg(*++ipp);
XX  	e = (struct exec *) Malloc(sizeof(struct exec));
XX  	e->e_cnt = 2;
XX--- 629,734 ----
XX  
XX  struct node *
XX   simple(t)
XX+ int t;
XX  {
XX    struct node *p = newnode(t);
XX    struct exec *e;
XX    struct stat est;
XX+   struct passwd *pw;
XX+   struct group *gr;
XX    long l;
XX+   int i;
XX  
XX    switch (t) {
XX!     case OP_TYPE:
XX  	checkarg(*++ipp);
XX  	switch (**ipp) {
XX! 	  case 'b':
XX  		p->n_info.n_int.n_val = S_IFBLK;
XX  		break;
XX! 	  case 'c':
XX  		p->n_info.n_int.n_val = S_IFCHR;
XX  		break;
XX! 	  case 'd':
XX  		p->n_info.n_int.n_val = S_IFDIR;
XX  		break;
XX! 	  case 'f':
XX  		p->n_info.n_int.n_val = S_IFREG;
XX  		break;
XX! #ifdef S_IFLNK
XX! 	  case 'l':
XX! 		p->n_info.n_int.n_val = S_IFLNK;
XX! 		break;
XX! #endif
XX! 	  default:
XX! #ifdef S_IFLNK
XX! 		fatal("-type needs b, c, d, f or l", "");
XX! #else
XX  		fatal("-type needs b, c, d or f", "");
XX+ #endif
XX  	}
XX  	break;
XX!     case OP_USER:
XX  	checkarg(*++ipp);
XX! 	if (((pw = getpwnam(*ipp)) == NULL)
XX! 	    && isnumber(*ipp, 10, 0))
XX! 		number(*ipp, 10, &(p->n_info.n_int.n_val),
XX! 		       &(p->n_info.n_int.n_sign));
XX! 	else {
XX! 		if (pw == NULL)
XX! 			fatal("unknown user: ", *ipp);
XX! 		p->n_info.n_int.n_val = pw->pw_uid;
XX! 		p->n_info.n_int.n_sign = 0;
XX! 	}
XX! 	break;
XX!     case OP_GROUP:
XX! 	checkarg(*++ipp);
XX! 	if (((gr = getgrnam(*ipp)) == NULL)
XX! 	    && isnumber(*ipp, 10, 0))
XX! 		number(*ipp, 10, &(p->n_info.n_int.n_val),
XX! 		       &(p->n_info.n_int.n_sign));
XX! 	else {
XX! 		if (gr == NULL)
XX! 			fatal("unknown group: ", *ipp);
XX! 		p->n_info.n_int.n_val = gr->gr_gid;
XX! 		p->n_info.n_int.n_sign = 0;
XX! 	}
XX! 	break;
XX!     case OP_SIZE:
XX! 	checkarg(*++ipp);
XX! 	i = strlen(*ipp) - 1;
XX! 	if ((*ipp)[i] == 'c') {
XX! 		p->n_type = OP_SIZEC;	/* Count in bytes i.s.o. blocks */
XX! 		(*ipp)[i] = '\0';
XX! 	}
XX! 	number(*ipp, 10, &(p->n_info.n_int.n_val),
XX  	       &(p->n_info.n_int.n_sign));
XX  	break;
XX!     case OP_LINKS:
XX!     case OP_INUM:
XX  	checkarg(*++ipp);
XX+ 	number(*ipp, 10, &(p->n_info.n_int.n_val),
XX+ 	       &(p->n_info.n_int.n_sign));
XX+ 	break;
XX+     case OP_PERM:
XX+ 	checkarg(*++ipp);
XX+ 	if (isnumber(*ipp, 8, 1)) number(*ipp, 8, &(p->n_info.n_int.n_val),
XX+ 		       &(p->n_info.n_int.n_sign));
XX+ 	else
XX+ 		fmode(*ipp, &(p->n_info.n_int.n_val),
XX+ 		      &(p->n_info.n_int.n_sign));
XX+ 	break;
XX+     case OP_ATIME:
XX+     case OP_CTIME:
XX+     case OP_MTIME:
XX+ 	checkarg(*++ipp);
XX  	number(*ipp, 10, &l, &(p->n_info.n_int.n_sign));
XX  	p->n_info.n_int.n_val = current_time - l * SECS_PER_DAY;
XX  	/* More than n days old means less than the absolute time */
XX  	p->n_info.n_int.n_sign *= -1;
XX  	break;
XX!     case OP_EXEC:
XX!     case OP_OK:
XX  	checkarg(*++ipp);
XX  	e = (struct exec *) Malloc(sizeof(struct exec));
XX  	e->e_cnt = 2;
XX***************
XX*** 450,487 ****
XX  		if ((tty = open("/dev/tty", O_RDWR)) < 0)
XX  			fatal("can't open /dev/tty", "");
XX  	break;
XX!       case OP_NEWER:
XX  	checkarg(*++ipp);
XX! 	if (stat(*ipp, &est) == -1)
XX  		fatal("-newer: can't get status of ", *ipp);
XX  	p->n_info.n_int.n_val = est.st_mtime;
XX  	break;
XX!       case OP_NAME:
XX  	checkarg(*++ipp);
XX  	p->n_info.n_str = *ipp;
XX  	break;
XX!       case OP_XDEV:	xdev_flag = 1;	break;
XX!       case OP_PRINT:
XX! 	break;
XX!       default:
XX  	fatal("syntax error, operator expected", "");
XX    }
XX    return p;
XX  }
XX  
XX  /*######################## DIAGNOSTICS ##############################*/
XX  
XX! nonfatal(s1, s2)
XX  char *s1, *s2;
XX  {
XX!   std_err(prog);
XX!   std_err(": ");
XX!   std_err(s1);
XX!   std_err(s2);
XX!   std_err("\n");
XX  }
XX  
XX! fatal(s1, s2)
XX  char *s1, *s2;
XX  {
XX    nonfatal(s1, s2);
XX--- 751,788 ----
XX  		if ((tty = open("/dev/tty", O_RDWR)) < 0)
XX  			fatal("can't open /dev/tty", "");
XX  	break;
XX!     case OP_NEWER:
XX  	checkarg(*++ipp);
XX! 	if (LSTAT(*ipp, &est) == -1)
XX  		fatal("-newer: can't get status of ", *ipp);
XX  	p->n_info.n_int.n_val = est.st_mtime;
XX  	break;
XX!     case OP_NAME:
XX  	checkarg(*++ipp);
XX  	p->n_info.n_str = *ipp;
XX  	break;
XX!     case OP_XDEV:	xdev_flag = 1;	break;
XX!     case OP_DEPTH:	depth_flag = 1;	break;
XX!     case OP_PRUNE:
XX!     case OP_PRINT:
XX!     case OP_NOUSER:	case OP_NOGROUP:	break;
XX!           default:
XX  	fatal("syntax error, operator expected", "");
XX    }
XX+   if ((t == OP_PRINT) || (t == OP_EXEC) || (t == OP_OK)) needprint = 0;
XX+ 
XX    return p;
XX  }
XX  
XX  /*######################## DIAGNOSTICS ##############################*/
XX  
XX! void nonfatal(s1, s2)
XX  char *s1, *s2;
XX  {
XX!   fprintf(stderr, "%s: %s%s\n", prog, s1, s2);
XX  }
XX  
XX! void fatal(s1, s2)
XX  char *s1, *s2;
XX  {
XX    nonfatal(s1, s2);
XX***************
XX*** 490,496 ****
XX  
XX  /*################### SMATCH #########################*/
XX  /* Don't try to understand the following one... */
XX! smatch(s, t)			/* shell-like matching */
XX  char *s, *t;
XX  {
XX    register n;
XX--- 791,797 ----
XX  
XX  /*################### SMATCH #########################*/
XX  /* Don't try to understand the following one... */
XX! int smatch(s, t)		/* shell-like matching */
XX  char *s, *t;
XX  {
XX    register n;
XX***************
XX*** 533,566 ****
XX  /*####################### EXECUTE ###########################*/
XX  /* Do -exec or -ok */
XX  
XX- char *epath = 0;
XX- 
XX  char *
XX-  getpath()
XX- {
XX-   extern char **environ;
XX-   register char **e = environ;
XX- 
XX-   if (epath)			/* retrieve PATH only once */
XX- 	return epath;
XX-   while (*e) {
XX- 	if (strncmp("PATH=", *e, 5) == 0) {
XX- 		return epath = *e + 5;
XX- 	}
XX- 	e++;
XX-   }
XX-   fatal("can't get PATH from environment", "");
XX- }
XX- 
XX- char *
XX   find_bin(s)
XX  char *s;
XX  {
XX!   char *f, *l, buf[PLEN];
XX  
XX    if (*s == '/')		/* absolute path name */
XX  	return(access(s, 1) == 0) ? s : 0;
XX!   l = f = getpath();
XX    for (;;) {
XX  	if (*l == ':' || *l == 0) {
XX  		if (l == f) {
XX--- 834,848 ----
XX  /*####################### EXECUTE ###########################*/
XX  /* Do -exec or -ok */
XX  
XX  char *
XX   find_bin(s)
XX  char *s;
XX  {
XX!   char *f, *l, buf[PATH_MAX];
XX  
XX    if (*s == '/')		/* absolute path name */
XX  	return(access(s, 1) == 0) ? s : 0;
XX!   l = f = epath;
XX    for (;;) {
XX  	if (*l == ':' || *l == 0) {
XX  		if (l == f) {
XX***************
XX*** 583,589 ****
XX    return 0;
XX  }
XX  
XX! execute(op, e, path)
XX  struct exec *e;
XX  char *path;
XX  {
XX--- 865,872 ----
XX    return 0;
XX  }
XX  
XX! int execute(op, e, path)
XX! int op;
XX  struct exec *e;
XX  char *path;
XX  {
X/
Xecho x - fix.c.d
Xsed '/^X/s///' > fix.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/fix.c  crc=16961   4580	Sun Apr 25 21:34:57 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/fix.c  crc=26968   5238	Wed Nov  4 04:19:11 1992
XX***************
XX*** 22,27 ****
XX--- 22,31 ----
XX       it is applied; an error is printed if there is a conflict
XX  */
XX  
XX+ #include <ctype.h>
XX+ #include <stdarg.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  #define IGNORE_WHITE_SPACE	/* This makes it white space insensitive */
XX***************
XX*** 30,47 ****
XX  #define strcmp strwcmp
XX  #endif
XX  
XX- extern char *fgets();
XX- extern FILE *fopen();
XX  #define LINELEN	1024
XX  
XX  char *prog = 0, *processing = 0;
XX  
XX  char *
XX   getline(fp, b)
XX  FILE *fp;
XX  char *b;
XX  {
XX-   int slen;
XX    if (fgets(b, LINELEN, fp) == NULL) fatal("unexpected eof");
XX  
XX    return b;
XX--- 34,56 ----
XX  #define strcmp strwcmp
XX  #endif
XX  
XX  #define LINELEN	1024
XX  
XX  char *prog = 0, *processing = 0;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(char *getline, (FILE *fp, char *b));
XX+ _PROTOTYPE(char *range, (char *s, int *p1, int *p2));
XX+ _PROTOTYPE(int getcommand, (FILE *fp, int *o1, int *o2, char *pcmd, int *n1, int *n2));
XX+ _PROTOTYPE(void fatal, (char *s, ...));
XX+ _PROTOTYPE(int strwcmp, (char *s1, char *s2));
XX+ _PROTOTYPE(int whitespace, (int ch));
XX+ 
XX  char *
XX   getline(fp, b)
XX  FILE *fp;
XX  char *b;
XX  {
XX    if (fgets(b, LINELEN, fp) == NULL) fatal("unexpected eof");
XX  
XX    return b;
XX***************
XX*** 49,55 ****
XX  
XX  #define copy(str) printf("%s", str)
XX  
XX! main(argc, argv)
XX  char **argv;
XX  {
XX    char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
XX--- 58,65 ----
XX  
XX  #define copy(str) printf("%s", str)
XX  
XX! int main(argc, argv)
XX! int argc;
XX  char **argv;
XX  {
XX    char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN];
XX***************
XX*** 75,81 ****
XX  			fl = getline(fpf, obuf);
XX  			here++;
XX  			fd = getline(fpd, nbuf);
XX! 			if (strncmp(fd, "<", 1))
XX  				fatal("illegal delete line");
XX  			if (strcmp(fl, fd + 2))
XX  				fatal("delete line conflict");
XX--- 85,91 ----
XX  			fl = getline(fpf, obuf);
XX  			here++;
XX  			fd = getline(fpd, nbuf);
XX! 			if (strncmp(fd, "<", (size_t)1))
XX  				fatal("illegal delete line");
XX  			if (strcmp(fl, fd + 2))
XX  				fatal("delete line conflict");
XX***************
XX*** 92,98 ****
XX  			here++;
XX  		}
XX  		while (n1 <= n2) {
XX! 			if (strncmp(getline(fpd, nbuf), ">", 1))
XX  				fatal("illegal append line");
XX  			copy(nbuf + 2);
XX  			n1++;
XX--- 102,108 ----
XX  			here++;
XX  		}
XX  		while (n1 <= n2) {
XX! 			if (strncmp(getline(fpd, nbuf), ">", (size_t)1))
XX  				fatal("illegal append line");
XX  			copy(nbuf + 2);
XX  			n1++;
XX***************
XX*** 101,115 ****
XX  	}
XX    }
XX    while (fgets(obuf, LINELEN, fpf) != NULL) copy(obuf);
XX!   exit(0);
XX  }
XX  
XX- isdigit(c)
XX- char c;
XX- {
XX-   return c >= '0' && c <= '9';
XX- }
XX- 
XX  char *
XX   range(s, p1, p2)
XX  char *s;
XX--- 111,119 ----
XX  	}
XX    }
XX    while (fgets(obuf, LINELEN, fpf) != NULL) copy(obuf);
XX!   return(0);
XX  }
XX  
XX  char *
XX   range(s, p1, p2)
XX  char *s;
XX***************
XX*** 130,136 ****
XX    return s;
XX  }
XX  
XX! getcommand(fp, o1, o2, pcmd, n1, n2)
XX  FILE *fp;
XX  int *o1, *o2, *n1, *n2;
XX  char *pcmd;
XX--- 134,140 ----
XX    return s;
XX  }
XX  
XX! int getcommand(fp, o1, o2, pcmd, n1, n2)
XX  FILE *fp;
XX  int *o1, *o2, *n1, *n2;
XX  char *pcmd;
XX***************
XX*** 150,156 ****
XX    return 1;
XX  }
XX  
XX! fatal(s, a)
XX  char *s, *a;
XX  {
XX    fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
XX--- 154,174 ----
XX    return 1;
XX  }
XX  
XX! #ifdef __STDC__
XX! void fatal(char *s, ...)
XX! {
XX!   va_list args;
XX! 
XX!   va_start (args, s);
XX!   fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
XX!   vfprintf(stderr, s, args);
XX!   fprintf(stderr, "\n");
XX!   va_end(args);
XX!   exit(1);
XX! }
XX! #else
XX! /* the K&R lib does not have vfprintf */
XX! void fatal(s, a)
XX  char *s, *a;
XX  {
XX    fprintf(stderr, "%s: processing: %s fatal: ", prog, processing);
XX***************
XX*** 158,163 ****
XX--- 176,182 ----
XX    fprintf(stderr, "\n");
XX    exit(1);
XX  }
XX+ #endif
XX  
XX  #ifdef IGNORE_WHITE_SPACE
XX  
X/
Xecho x - fold.c.d
Xsed '/^X/s///' > fold.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/fold.c  crc=60890   1052	Sun Apr 25 21:34:57 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/fold.c  crc=32557   1175	Wed Nov  4 04:19:11 1992
XX***************
XX*** 1,7 ****
XX! /*  fold - folds long lines		Author: Terrence W. Holm */
XX  
XX  /*  Usage:  fold  [ -width ]  [ file ... ]  */
XX  
XX  #include <stdio.h>
XX  
XX  #define  TAB		8
XX--- 1,8 ----
XX! /* fold - folds long lines		Author: Terrence W. Holm */
XX  
XX  /*  Usage:  fold  [ -width ]  [ file ... ]  */
XX  
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define  TAB		8
XX***************
XX*** 9,15 ****
XX  
XX  int column = 0;			/* Current column, retained between files  */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 10,19 ----
XX  
XX  int column = 0;			/* Current column, retained between files  */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void Fold, (FILE *f, int width));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 37,47 ****
XX  		fclose(f);
XX  	}
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX! Fold(f, width)
XX  FILE *f;
XX  int width;
XX  {
XX--- 41,51 ----
XX  		fclose(f);
XX  	}
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX! void Fold(f, width)
XX  FILE *f;
XX  int width;
XX  {
X/
Xecho x - fortune.c.d
Xsed '/^X/s///' > fortune.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/fortune.c  crc=13554   1989	Sun Apr 25 21:34:58 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/fortune.c  crc=05555   1847	Wed Nov  4 04:19:12 1992
XX***************
XX*** 3,40 ****
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <time.h>
XX  #include <stdio.h>
XX  
XX! #define COOKIEJAR "/usr/lib/fortune.dat"
XX  
XX! static char *Copyright = "\0fortune v1.1 Copyright (c) 1988 Bert Reuling";
XX  
XX! long seed;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int c1, c2, c3;
XX-   long magic();
XX    struct stat cookie_stat;
XX!   FILE *cookie, *out, *fopen(), *popen();
XX  
XX    if ((cookie = fopen(COOKIEJAR, "r")) == NULL) {
XX! 	fprintf(stderr, "%s:\nCan't open %s\n", argv[0], COOKIEJAR);
XX! 	exit(-1);
XX    }
XX  
XX!   /* Create seed from : date, time, user-id and process-id we can't get
XX!    * the position of the moon, unfortunately.
XX     */
XX!   seed = time((time_t *) 0) * (long) (getuid() + 1) * (long) getpid();
XX  
XX    if (stat(COOKIEJAR, &cookie_stat) != 0) {
XX! 	fprintf(stderr, "%s:\nCannot stat cookie jar\n", argv[0]);
XX! 	exit(-1);
XX    }
XX!   fseek(cookie, magic((long) cookie_stat.st_size), 0);	/* move by magic... */
XX  
XX    c2 = c3 = '\n';
XX    while (((c1 = getc(cookie)) != EOF) && ((c1 != '%') || (c2 != '%') || (c3 != '\n'))) {
XX--- 3,44 ----
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <time.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX! #define COOKIEJAR "/usr/games/lib/fortunes.dat"
XX  
XX! static char *Copyright = "\0Copyright (c) 1990 Bert Reuling";
XX! static unsigned long seed;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(unsigned long magic, (unsigned long range));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int c1, c2, c3;
XX    struct stat cookie_stat;
XX!   FILE *cookie;
XX  
XX    if ((cookie = fopen(COOKIEJAR, "r")) == NULL) {
XX! 	printf("\nSome things better stay closed.\n  - %s\n", argv[0]);
XX! 	exit (-1);
XX    }
XX  
XX!   /* Create seed from : date, time, user-id and process-id. we can't get
XX!    * the position of the moon, unfortunately. Note that super cookies
XX!    * are not affected by chance...
XX     */
XX!   seed = time( (time_t *) 0) * (long) getuid() * (long) getpid();
XX  
XX    if (stat(COOKIEJAR, &cookie_stat) != 0) {
XX! 	printf("\nIt furthers one to see the super guru.\n  - %s\n", argv[0]);
XX! 	exit (-1);
XX    }
XX!   fseek(cookie, magic((unsigned long) cookie_stat.st_size), 0); /* m ove bu magic... */
XX  
XX    c2 = c3 = '\n';
XX    while (((c1 = getc(cookie)) != EOF) && ((c1 != '%') || (c2 != '%') || (c3 != '\n'))) {
XX***************
XX*** 43,61 ****
XX    }
XX  
XX    if (c1 == EOF) {
XX! 	fprintf(stderr, "%s:\n", argv[0]);
XX! 	fprintf(stderr, "The cookie jar does not have a bottom!\n");
XX! 	fprintf(stderr, "All cookies have fallen out...\n");
XX! 	exit(-1);
XX    }
XX- #ifdef FORMATTER
XX-   if ((out = popen(FORMATTER, "w")) == NULL) {
XX- 	fprintf(stderr, "%s:\nIt furthers one to see a plumber!\n", argv[0]);
XX- 	exit(-1);
XX-   }
XX- #else
XX-   out = stdout;
XX- #endif
XX  
XX    c2 = c3 = '\n';
XX    while (((c1 = getc(cookie)) != '%') || (c2 != '%') || (c3 != '\n')) {
XX--- 47,55 ----
XX    }
XX  
XX    if (c1 == EOF) {
XX! 	printf("\nSomething unexpected has happened.\n  - %s", argv[0]);
XX! 	exit (-1);
XX    }
XX  
XX    c2 = c3 = '\n';
XX    while (((c1 = getc(cookie)) != '%') || (c2 != '%') || (c3 != '\n')) {
XX***************
XX*** 63,89 ****
XX  		rewind(cookie);
XX  		continue;
XX  	}
XX! 	putc(c2, out);
XX  	c3 = c2;
XX  	c2 = c1;
XX    }
XX!   putc('\n', out);
XX    fclose(cookie);
XX! 
XX! #ifdef FORMATTER
XX!   pclose(out);
XX! #endif
XX! 
XX!   exit(0);
XX  }
XX  
XX  /*  magic  -  please study carefull: there is more than meets the eye */
XX! long magic(range)
XX! long range;
XX  {
XX-   int i;
XX  
XX!   for (i = 0; i < 1234; i++)
XX! 	seed = 883L * (seed % 881L) - 2 * (seed / 883L) + 1L;
XX!   return((long) ((int) (seed & 0x7fffL) * range / 0x7fffL));
XX  }
XX--- 57,76 ----
XX  		rewind(cookie);
XX  		continue;
XX  	}
XX! 	putc(c2, stdout);
XX  	c3 = c2;
XX  	c2 = c1;
XX    }
XX!   putc('\n', stdout);
XX    fclose(cookie);
XX!   return (0);
XX  }
XX  
XX  /*  magic  -  please study carefull: there is more than meets the eye */
XX! unsigned long magic(range)
XX! unsigned long range;
XX  {
XX  
XX!   seed = 9065531L * (seed % 9065533L) - 2 * (seed / 9065531L) + 1L;
XX!   return (seed % range);
XX  }
X/
Xecho x - fsck.c.d
Xsed '/^X/s///' > fsck.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/fsck.c  crc=25152  34174	Sun Apr 25 21:34:59 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/fsck.c  crc=12324  39300	Sun Jan 17 20:52:40 1993
XX***************
XX*** 1,3 ****
XX--- 1,26 ----
XX+ /* Hacks for version 1.6 */					
XX+ 
XX+ #define INODES_PER_BLOCK V1_INODES_PER_BLOCK
XX+ #define INODE_SIZE V1_INODE_SIZE
XX+ #define INTS_PER_BLOCK (BLOCK_SIZE / (int) sizeof(int))
XX+ #define MAX_ZONES (V1_NR_DZONES+V1_INDIRECTS+(long)V1_INDIRECTS*V1_INDIRECTS)
XX+ #define NR_DZONE_NUM V1_NR_DZONES
XX+ #define NR_INDIRECTS V1_INDIRECTS
XX+ #define NR_ZONE_NUMS V1_NR_TZONES
XX+ #define ZONE_NUM_SIZE V1_ZONE_NUM_SIZE
XX+ #define bit_nr u16_t	/* perhaps bit_t should be used, although slower */
XX+ #define Bit_nr U16_t
XX+ #define block_nr block_t
XX+ #define d_inode d1_inode
XX+ #define d_inum d_ino
XX+ #define dir_struct struct direct
XX+ #define i_mode d1_mode
XX+ #define i_nlinks d1_nlinks
XX+ #define i_size d1_size
XX+ #define i_zone d1_zone
XX+ #define zone_nr zone1_t
XX+ #define Zone_nr Zone1_t
XX+ 
XX  /* fsck - file system checker		Author: Robbert van Renesse */
XX  
XX  /* Modified by Norbert Schlenker
XX***************
XX*** 15,43 ****
XX  */
XX  
XX  #include <sys/types.h>
XX  #include <ctype.h>
XX  #include <errno.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <stdlib.h>
XX  #include <unistd.h>
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  #include "../fs/const.h"
XX  #include "../fs/type.h"
XX  
XX  #undef printf			/* defined as printk in "../fs/const.h" */
XX  
XX  #include <stdio.h>
XX  
XX! #if INTEL_32BITS
XX  #define BITSHIFT	  5	/* = log2(#bits(int)) */
XX  #else
XX  #define BITSHIFT	  4	/* = log2(#bits(int)) */
XX  #endif
XX  
XX- #define BITMAPSHIFT	 13	/* = log2(#bits(block)); 13 means 1K blocks */
XX  #define MAXPRINT	  8	/* max. number of error lines in chkmap */
XX  #define MAXDIRSIZE     5000	/* max. size of a reasonable directory */
XX  #define CINDIR		128	/* number of indirect zno's read at a time */
XX--- 38,69 ----
XX  */
XX  
XX  #include <sys/types.h>
XX+ #include <sys/dir.h>
XX  #include <ctype.h>
XX  #include <errno.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <stdlib.h>
XX+ #include <string.h>
XX  #include <unistd.h>
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  #include "../fs/const.h"
XX+ #include "../fs/inode.h"
XX  #include "../fs/type.h"
XX+ #include <minix/fslib.h>
XX  
XX  #undef printf			/* defined as printk in "../fs/const.h" */
XX  
XX  #include <stdio.h>
XX  
XX! #if INTEL_32BITS || (CHIP == SPARC)
XX  #define BITSHIFT	  5	/* = log2(#bits(int)) */
XX  #else
XX  #define BITSHIFT	  4	/* = log2(#bits(int)) */
XX  #endif
XX  
XX  #define MAXPRINT	  8	/* max. number of error lines in chkmap */
XX  #define MAXDIRSIZE     5000	/* max. size of a reasonable directory */
XX  #define CINDIR		128	/* number of indirect zno's read at a time */
XX***************
XX*** 50,69 ****
XX  #define ZONE_CT 	360	/* default zones  (when making file system) */
XX  #define INODE_CT	 95	/* default inodes (when making file system) */
XX  
XX! /* DEBUG FIXME.  This and other things repeat stuff from fs, not necessarily
XX!  * identically.  This is part of a structure in fs/super.h, and old versions
XX!  * had the wrong type for s_magic.
XX!  */
XX! struct dsb {
XX!   ino_t s_ninodes;		/* # inodes on the minor device */
XX!   zone_nr s_nzones;		/* total dev size, incl. bit maps etc */
XX!   unsigned short s_imap_blocks;	/* # of blocks used by inode bit map */
XX!   unsigned short s_zmap_blocks;	/* # of blocks used by zone bit map */
XX!   zone_nr s_firstdatazone;	/* number of first data zone */
XX!   short s_log_zone_size;	/* log2 of blocks/zone */
XX!   off_t s_maxsize;		/* maximum file size on this device */
XX!   short s_magic;		/* magic number for super blocks */
XX! } sb;
XX  
XX  #define STICKY_BIT	01000	/* not defined anywhere else */
XX  
XX--- 76,83 ----
XX  #define ZONE_CT 	360	/* default zones  (when making file system) */
XX  #define INODE_CT	 95	/* default inodes (when making file system) */
XX  
XX! #include "../fs/super.h"
XX! struct super_block sb;
XX  
XX  #define STICKY_BIT	01000	/* not defined anywhere else */
XX  
XX***************
XX*** 73,79 ****
XX  #define ztob(z)		((block_nr) (z) << sb.s_log_zone_size)
XX  #define btoa(b)		((long) (b) * BLOCK_SIZE)
XX  #define SCALE		((int) ztob(1))	/* # blocks in a zone */
XX! #define FIRST		sb.s_firstdatazone	/* as the name says */
XX  
XX  /* # blocks of each type */
XX  #define N_SUPER		1
XX--- 87,93 ----
XX  #define ztob(z)		((block_nr) (z) << sb.s_log_zone_size)
XX  #define btoa(b)		((long) (b) * BLOCK_SIZE)
XX  #define SCALE		((int) ztob(1))	/* # blocks in a zone */
XX! #define FIRST		((zone_nr) sb.s_firstdatazone)	/* as the name says */
XX  
XX  /* # blocks of each type */
XX  #define N_SUPER		1
XX***************
XX*** 120,138 ****
XX  
XX  /* Counters for each type of inode/zone. */
XX  int nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;
XX! int npipe, nfreezone, ztype[NLEVEL];
XX  
XX  int repair, automatic, listing, listsuper;	/* flags */
XX  int firstlist;			/* has the listing header been printed? */
XX  unsigned part_offset;		/* sector offset for this partition */
XX! char answer[] = {"Answer questions with y or n.  Then hit RETURN"};
XX  
XX  /* Initialize the variables used by this program. */
XX! initvars()
XX  {
XX    register level;
XX  
XX!   nregular = ndirectory = nblkspec = ncharspec = nbadinode = npipe = 0;
XX    for (level = 0; level < NLEVEL; level++) ztype[level] = 0;
XX    changed = 0;
XX    thisblk = NO_BLOCK;
XX--- 134,215 ----
XX  
XX  /* Counters for each type of inode/zone. */
XX  int nfreeinode, nregular, ndirectory, nblkspec, ncharspec, nbadinode;
XX! int npipe, nsyml, nfreezone, ztype[NLEVEL];
XX  
XX  int repair, automatic, listing, listsuper;	/* flags */
XX  int firstlist;			/* has the listing header been printed? */
XX  unsigned part_offset;		/* sector offset for this partition */
XX! char answer[] = "Answer questions with y or n.  Then hit RETURN";
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void initvars, (void));
XX+ _PROTOTYPE(void fatal, (char *s));
XX+ _PROTOTYPE(int eoln, (int c));
XX+ _PROTOTYPE(int yes, (char *question));
XX+ _PROTOTYPE(int atoo, (char *s));
XX+ _PROTOTYPE(int input, (char *buf, int size));
XX+ _PROTOTYPE(char *alloc, (unsigned nelem, unsigned elsize));
XX+ _PROTOTYPE(void printname, (char *s));
XX+ _PROTOTYPE(void printrec, (struct stack *sp));
XX+ _PROTOTYPE(void printpath, (int mode, int nlcr));
XX+ _PROTOTYPE(void devopen, (void));
XX+ _PROTOTYPE(void devclose, (void));
XX+ _PROTOTYPE(void devio, (block_nr bno, int dir));
XX+ _PROTOTYPE(void devread, (long offset, char *buf, int size));
XX+ _PROTOTYPE(void devwrite, (long offset, char *buf, int size));
XX+ _PROTOTYPE(void pr, (char *fmt, int cnt, char *s, char *p));
XX+ _PROTOTYPE(bit_nr getnumber, (char *s));
XX+ _PROTOTYPE(char **getlist, (char ***argv, char *type));
XX+ _PROTOTYPE(void lsuper, (void));
XX+ _PROTOTYPE(void getsuper, (void));
XX+ _PROTOTYPE(void chksuper, (void));
XX+ _PROTOTYPE(void lsi, (char **clist));
XX+ _PROTOTYPE(unsigned *allocbitmap, (int nblk));
XX+ _PROTOTYPE(void loadbitmap, (unsigned *bitmap, block_nr bno, int nblk));
XX+ _PROTOTYPE(void dumpbitmap, (unsigned *bitmap, block_nr bno, int nblk));
XX+ _PROTOTYPE(void initbitmap, (unsigned *bitmap, Bit_nr bit, int nblk));
XX+ _PROTOTYPE(void fillbitmap, (unsigned *bitmap, Bit_nr lwb, Bit_nr upb, char **list));
XX+ _PROTOTYPE(void freebitmap, (unsigned *p));
XX+ _PROTOTYPE(void getbitmaps, (void));
XX+ _PROTOTYPE(void putbitmaps, (void));
XX+ _PROTOTYPE(void chkword, (unsigned w1, unsigned w2, Bit_nr bit, Bit_nr nbit, char *type, int *n, int *report));
XX+ _PROTOTYPE(void chkmap, (unsigned *cmap, unsigned *dmap, Bit_nr bit, block_nr blkno, int nblk, Bit_nr nbit, char *type));
XX+ _PROTOTYPE(void chkilist, (void));
XX+ _PROTOTYPE(void getcount, (void));
XX+ _PROTOTYPE(void counterror, (Ino_t ino));
XX+ _PROTOTYPE(void chkcount, (void));
XX+ _PROTOTYPE(void freecount, (void));
XX+ _PROTOTYPE(void printperm, (Mode_t mode, int shift, int special, int overlay));
XX+ _PROTOTYPE(void list, (Ino_t ino, d_inode *ip));
XX+ _PROTOTYPE(int Remove, (dir_struct *dp));
XX+ _PROTOTYPE(void make_printable_name, (char *dst, char *src, int n));
XX+ _PROTOTYPE(int chkdots, (Ino_t ino, off_t pos, dir_struct *dp, Ino_t exp));
XX+ _PROTOTYPE(int chkname, (Ino_t ino, dir_struct *dp));
XX+ _PROTOTYPE(int chkentry, (Ino_t ino, off_t pos, dir_struct *dp));
XX+ _PROTOTYPE(int chkdirzone, (Ino_t ino, d_inode *ip, off_t pos, Zone_nr zno));
XX+ _PROTOTYPE(void errzone, (char *mess, Zone_nr zno, int level, off_t pos));
XX+ _PROTOTYPE(int markzone, (Ino_t ino, Zone_nr zno, int level, off_t pos));
XX+ _PROTOTYPE(int chkindzone, (Ino_t ino, d_inode *ip, off_t *pos, Zone_nr zno, int level));
XX+ _PROTOTYPE(off_t jump, (int level));
XX+ _PROTOTYPE(int zonechk, (Ino_t ino, d_inode *ip, off_t *pos, Zone_nr zno, int level));
XX+ _PROTOTYPE(int chkzones, (Ino_t ino, d_inode *ip, off_t *pos, zone_nr *zlist, int len, int level));
XX+ _PROTOTYPE(int chkfile, (Ino_t ino, d_inode *ip));
XX+ _PROTOTYPE(int chkdirectory, (Ino_t ino, d_inode *ip));
XX+ _PROTOTYPE(int chklink, (Ino_t ino, d_inode *ip));
XX+ _PROTOTYPE(int chkmode, (Ino_t ino, d_inode *ip));
XX+ _PROTOTYPE(int chkinode, (Ino_t ino, d_inode *ip));
XX+ _PROTOTYPE(int chkspecial, (Ino_t ino, d_inode *ip) );
XX+ _PROTOTYPE(int descendtree, (dir_struct *dp));
XX+ _PROTOTYPE(void chktree, (void));
XX+ _PROTOTYPE(void printtotal, (void));
XX+ _PROTOTYPE(void chkdev, (char *f, char **clist, char **ilist, char **zlist));
XX+ 
XX  /* Initialize the variables used by this program. */
XX! void initvars()
XX  {
XX    register level;
XX  
XX!   nregular = ndirectory = nblkspec = ncharspec = nbadinode = npipe = nsyml = 0;
XX    for (level = 0; level < NLEVEL; level++) ztype[level] = 0;
XX    changed = 0;
XX    thisblk = NO_BLOCK;
XX***************
XX*** 149,155 ****
XX  }
XX  
XX  /* Test for end of line. */
XX! eoln(c)
XX  {
XX    return(c == EOF || c == '\n' || c == '\r');
XX  }
XX--- 226,233 ----
XX  }
XX  
XX  /* Test for end of line. */
XX! int eoln(c)
XX! int c;
XX  {
XX    return(c == EOF || c == '\n' || c == '\r');
XX  }
XX***************
XX*** 189,196 ****
XX  }
XX  
XX  /* If repairing the file system, print a prompt and get a string from user. */
XX! input(buf, size)
XX  char *buf;
XX  {
XX    register char *p = buf;
XX  
XX--- 267,275 ----
XX  }
XX  
XX  /* If repairing the file system, print a prompt and get a string from user. */
XX! int input(buf, size)
XX  char *buf;
XX+ int size;
XX  {
XX    register char *p = buf;
XX  
XX***************
XX*** 219,226 ****
XX  {
XX    char *p;
XX  
XX!   if ((p = (char *) malloc(nelem * elsize)) == 0) fatal("out of memory");
XX!   memset(p, 0, nelem * elsize);
XX    return(p);
XX  }
XX  
XX--- 298,305 ----
XX  {
XX    char *p;
XX  
XX!   if ((p = (char *) malloc((size_t)nelem * elsize)) == 0) fatal("out of memory");
XX!   memset(p, 0, (size_t)nelem * elsize);
XX    return(p);
XX  }
XX  
XX***************
XX*** 242,248 ****
XX  /* Print the pathname given by a linked list pointed to by `sp'.  The
XX   * names are in reverse order.
XX   */
XX! printrec(sp)
XX  struct stack *sp;
XX  {
XX    if (sp->st_next != 0) {
XX--- 321,327 ----
XX  /* Print the pathname given by a linked list pointed to by `sp'.  The
XX   * names are in reverse order.
XX   */
XX! void printrec(sp)
XX  struct stack *sp;
XX  {
XX    if (sp->st_next != 0) {
XX***************
XX*** 253,259 ****
XX  }
XX  
XX  /* Print the current pathname.  */
XX! printpath(mode, nlcr)
XX  {
XX    if (ftop->st_next == 0)
XX  	putchar('/');
XX--- 332,340 ----
XX  }
XX  
XX  /* Print the current pathname.  */
XX! void printpath(mode, nlcr)
XX! int mode;
XX! int nlcr;
XX  {
XX    if (ftop->st_next == 0)
XX  	putchar('/');
XX***************
XX*** 271,277 ****
XX  }
XX  
XX  /* Open the device.  */
XX! devopen()
XX  {
XX    if ((dev = open(device, repair ? O_RDWR : O_RDONLY)) < 0) {
XX  	perror(device);
XX--- 352,358 ----
XX  }
XX  
XX  /* Open the device.  */
XX! void devopen()
XX  {
XX    if ((dev = open(device, repair ? O_RDWR : O_RDONLY)) < 0) {
XX  	perror(device);
XX***************
XX*** 280,286 ****
XX  }
XX  
XX  /* Close the device. */
XX! devclose()
XX  {
XX    if (close(dev) != 0) {
XX  	perror("close");
XX--- 361,367 ----
XX  }
XX  
XX  /* Close the device. */
XX! void devclose()
XX  {
XX    if (close(dev) != 0) {
XX  	perror("close");
XX***************
XX*** 289,301 ****
XX  }
XX  
XX  /* Read or write a block. */
XX! devio(bno, dir)
XX  block_nr bno;
XX  {
XX    if (dir == READING && bno == thisblk) return;
XX    thisblk = bno;
XX  
XX!   lseek(dev, btoa(bno), SEEK_SET);
XX    if (dir == READING) {
XX  	if (read(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE)
XX  		return;
XX--- 370,383 ----
XX  }
XX  
XX  /* Read or write a block. */
XX! void devio(bno, dir)
XX  block_nr bno;
XX+ int dir;
XX  {
XX    if (dir == READING && bno == thisblk) return;
XX    thisblk = bno;
XX  
XX!   lseek(dev, (off_t) btoa(bno), SEEK_SET);
XX    if (dir == READING) {
XX  	if (read(dev, rwbuf, BLOCK_SIZE) == BLOCK_SIZE)
XX  		return;
XX***************
XX*** 306,338 ****
XX  
XX    printf("%s: can't %s block %ld (error = 0x%x)\n", prog,
XX           dir == READING ? "read" : "write", (long) bno, errno);
XX    fatal("");
XX  }
XX  
XX  /* Read `size' bytes from the disk starting at byte `offset'. */
XX! devread(offset, buf, size)
XX  long offset;
XX  char *buf;
XX  {
XX    devio((block_nr) (offset / BLOCK_SIZE), READING);
XX!   memmove(buf, &rwbuf[(int) (offset % BLOCK_SIZE)], size);
XX  }
XX  
XX  /* Write `size' bytes to the disk starting at byte `offset'. */
XX! devwrite(offset, buf, size)
XX  long offset;
XX  char *buf;
XX  {
XX    if (!repair) fatal("internal error (devwrite)");
XX    if (size != BLOCK_SIZE) devio((block_nr) (offset / BLOCK_SIZE), READING);
XX!   memmove(&rwbuf[(int) (offset % BLOCK_SIZE)], buf, size);
XX    devio((block_nr) (offset / BLOCK_SIZE), WRITING);
XX    changed = 1;
XX  }
XX  
XX  /* Print a string with either a singular or a plural pronoun. */
XX! pr(fmt, cnt, s, p)
XX  char *fmt, *s, *p;
XX  {
XX    printf(fmt, cnt, cnt == 1 ? s : p);
XX  }
XX--- 388,428 ----
XX  
XX    printf("%s: can't %s block %ld (error = 0x%x)\n", prog,
XX           dir == READING ? "read" : "write", (long) bno, errno);
XX+   if (dir == READING) {
XX+ 	printf("Continuing with a zero-filled block.\n");
XX+ 	memset(rwbuf, 0, BLOCK_SIZE);
XX+ 	return;
XX+   }
XX    fatal("");
XX  }
XX  
XX  /* Read `size' bytes from the disk starting at byte `offset'. */
XX! void devread(offset, buf, size)
XX  long offset;
XX  char *buf;
XX+ int size;
XX  {
XX    devio((block_nr) (offset / BLOCK_SIZE), READING);
XX!   memmove(buf, &rwbuf[(int) (offset % BLOCK_SIZE)], (size_t)size);
XX  }
XX  
XX  /* Write `size' bytes to the disk starting at byte `offset'. */
XX! void devwrite(offset, buf, size)
XX  long offset;
XX  char *buf;
XX+ int size;
XX  {
XX    if (!repair) fatal("internal error (devwrite)");
XX    if (size != BLOCK_SIZE) devio((block_nr) (offset / BLOCK_SIZE), READING);
XX!   memmove(&rwbuf[(int) (offset % BLOCK_SIZE)], buf, (size_t)size);
XX    devio((block_nr) (offset / BLOCK_SIZE), WRITING);
XX    changed = 1;
XX  }
XX  
XX  /* Print a string with either a singular or a plural pronoun. */
XX! void pr(fmt, cnt, s, p)
XX  char *fmt, *s, *p;
XX+ int cnt;
XX  {
XX    printf(fmt, cnt, cnt == 1 ? s : p);
XX  }
XX***************
XX*** 343,349 ****
XX  {
XX    register bit_nr n = 0;
XX  
XX!   if (s == (char *) NULL)
XX  	return NO_BIT;
XX    while (isdigit(*s))
XX  	n = (n << 1) + (n << 3) + *s++ - '0';
XX--- 433,439 ----
XX  {
XX    register bit_nr n = 0;
XX  
XX!   if (s == NULL)
XX  	return NO_BIT;
XX    while (isdigit(*s))
XX  	n = (n << 1) + (n << 3) + *s++ - '0';
XX***************
XX*** 363,369 ****
XX    }
XX    if (empty) {
XX  	printf("warning: no %s numbers given\n", type);
XX! 	return(0);
XX    }
XX    return(list);
XX  }
XX--- 453,459 ----
XX    }
XX    if (empty) {
XX  	printf("warning: no %s numbers given\n", type);
XX! 	return(NULL);
XX    }
XX    return(list);
XX  }
XX***************
XX*** 371,377 ****
XX  /* Make a listing of the super block.  If `repair' is set, ask the user
XX   * for changes.
XX   */
XX! lsuper()
XX  {
XX    char buf[80];
XX  
XX--- 461,467 ----
XX  /* Make a listing of the super block.  If `repair' is set, ask the user
XX   * for changes.
XX   */
XX! void lsuper()
XX  {
XX    char buf[80];
XX  
XX***************
XX*** 388,395 ****
XX  	if (input(buf, 80)) sb.s_firstdatazone = atol(buf);
XX  	printf("log_zone_size = %u", sb.s_log_zone_size);
XX  	if (input(buf, 80)) sb.s_log_zone_size = atol(buf);
XX! 	printf("maxsize       = %lu", sb.s_maxsize);
XX! 	if (input(buf, 80)) sb.s_maxsize = atol(buf);
XX  	if (yes("ok now")) {
XX  		devwrite(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
XX  		return;
XX--- 478,485 ----
XX  	if (input(buf, 80)) sb.s_firstdatazone = atol(buf);
XX  	printf("log_zone_size = %u", sb.s_log_zone_size);
XX  	if (input(buf, 80)) sb.s_log_zone_size = atol(buf);
XX! 	printf("maxsize       = %lu", sb.s_max_size);
XX! 	if (input(buf, 80)) sb.s_max_size = atol(buf);
XX  	if (yes("ok now")) {
XX  		devwrite(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
XX  		return;
XX***************
XX*** 399,408 ****
XX  }
XX  
XX  /* Get the super block from either disk or user.  Do some initial checks. */
XX! getsuper()
XX  {
XX    devread(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
XX    if (listsuper) lsuper();
XX    if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block");
XX    if ((short) sb.s_ninodes <= 0) fatal("no inodes");
XX    if (sb.s_nzones <= 2) fatal("no zones");
XX--- 489,499 ----
XX  }
XX  
XX  /* Get the super block from either disk or user.  Do some initial checks. */
XX! void getsuper()
XX  {
XX    devread(btoa(BLK_SUPER), (char *) &sb, sizeof(sb));
XX    if (listsuper) lsuper();
XX+   if (sb.s_magic == SUPER_V2) fatal("Cannot handle V2 file systems");
XX    if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block");
XX    if ((short) sb.s_ninodes <= 0) fatal("no inodes");
XX    if (sb.s_nzones <= 2) fatal("no zones");
XX***************
XX*** 410,438 ****
XX    if ((short) sb.s_zmap_blocks <= 0) fatal("no zmap");
XX    if ((short) sb.s_firstdatazone <= 1) fatal("first data zone too small");
XX    if ((short) sb.s_log_zone_size < 0) fatal("zone size < block size");
XX!   if (sb.s_maxsize <= 0) fatal("max. file size <= 0");
XX  }
XX  
XX  /* Check the super block for reasonable contents. */
XX! chksuper()
XX  {
XX    register n;
XX    register off_t maxsize;
XX  
XX!   n = bitmapsize(1 + sb.s_ninodes);
XX    if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block");
XX    if ((short) sb.s_imap_blocks < n) fatal("too few imap blocks");
XX    if (sb.s_imap_blocks != n) {
XX  	pr("warning: expected %d imap_block%s", n, "", "s");
XX  	printf(" instead of %d\n", sb.s_imap_blocks);
XX    }
XX!   n = bitmapsize(sb.s_nzones);
XX    if ((short) sb.s_zmap_blocks < n) fatal("too few zmap blocks");
XX    if (sb.s_zmap_blocks != n) {
XX  	pr("warning: expected %d zmap_block%s", n, "", "s");
XX  	printf(" instead of %d\n", sb.s_zmap_blocks);
XX    }
XX!   if ((short) sb.s_firstdatazone >= sb.s_nzones)
XX  	fatal("first data zone too large");
XX    if ((unsigned short) sb.s_log_zone_size >= 8 * sizeof(block_nr))
XX  	fatal("log_zone_size too large");
XX--- 501,529 ----
XX    if ((short) sb.s_zmap_blocks <= 0) fatal("no zmap");
XX    if ((short) sb.s_firstdatazone <= 1) fatal("first data zone too small");
XX    if ((short) sb.s_log_zone_size < 0) fatal("zone size < block size");
XX!   if (sb.s_max_size <= 0) fatal("max. file size <= 0");
XX  }
XX  
XX  /* Check the super block for reasonable contents. */
XX! void chksuper()
XX  {
XX    register n;
XX    register off_t maxsize;
XX  
XX!   n = bitmapsize((bit_t) sb.s_ninodes + 1);
XX    if (sb.s_magic != SUPER_MAGIC) fatal("bad magic number in super block");
XX    if ((short) sb.s_imap_blocks < n) fatal("too few imap blocks");
XX    if (sb.s_imap_blocks != n) {
XX  	pr("warning: expected %d imap_block%s", n, "", "s");
XX  	printf(" instead of %d\n", sb.s_imap_blocks);
XX    }
XX!   n = bitmapsize((bit_t) sb.s_nzones);
XX    if ((short) sb.s_zmap_blocks < n) fatal("too few zmap blocks");
XX    if (sb.s_zmap_blocks != n) {
XX  	pr("warning: expected %d zmap_block%s", n, "", "s");
XX  	printf(" instead of %d\n", sb.s_zmap_blocks);
XX    }
XX!   if (sb.s_firstdatazone >= sb.s_nzones)
XX  	fatal("first data zone too large");
XX    if ((unsigned short) sb.s_log_zone_size >= 8 * sizeof(block_nr))
XX  	fatal("log_zone_size too large");
XX***************
XX*** 447,482 ****
XX    maxsize = MAX_FILE_POS;
XX    if (((maxsize - 1) >> sb.s_log_zone_size) / BLOCK_SIZE >= MAX_ZONES)
XX  	maxsize = ((long) MAX_ZONES * BLOCK_SIZE) << sb.s_log_zone_size;
XX!   if (sb.s_maxsize != maxsize) {
XX  	printf("warning: expected max size to be %ld ", maxsize);
XX! 	printf("instead of %ld\n", sb.s_maxsize);
XX    }
XX  }
XX  
XX- /* Convert from bit count to a block count. The usual expression
XX-  *
XX-  *	(nr_bits + (1 << BITMAPSHIFT) - 1) >> BITMAPSHIFT
XX-  *
XX-  * doesn't work because of overflow.
XX-  *
XX-  * Other overflow bugs, such as the expression for N_ILIST overflowing when
XX-  * s_inodes is just over INODES_PER_BLOCK less than the maximum+1, are not
XX-  * fixed yet, because that number of inodes is silly.
XX-  */
XX- int bitmapsize(nr_bits)
XX- bit_nr nr_bits;
XX- {
XX-   int nr_blocks;
XX- 
XX-   nr_blocks = nr_bits >> BITMAPSHIFT;
XX-   if ((nr_blocks << BITMAPSHIFT) < nr_bits) ++nr_blocks;
XX-   return(nr_blocks);
XX- }
XX- 
XX  /* Make a listing of the inodes given by `clist'.  If `repair' is set, ask
XX   * the user for changes.
XX   */
XX! lsi(clist)
XX  char **clist;
XX  {
XX    register bit_nr bit;
XX--- 538,553 ----
XX    maxsize = MAX_FILE_POS;
XX    if (((maxsize - 1) >> sb.s_log_zone_size) / BLOCK_SIZE >= MAX_ZONES)
XX  	maxsize = ((long) MAX_ZONES * BLOCK_SIZE) << sb.s_log_zone_size;
XX!   if (sb.s_max_size != maxsize) {
XX  	printf("warning: expected max size to be %ld ", maxsize);
XX! 	printf("instead of %ld\n", sb.s_max_size);
XX    }
XX  }
XX  
XX  /* Make a listing of the inodes given by `clist'.  If `repair' is set, ask
XX   * the user for changes.
XX   */
XX! void lsi(clist)
XX  char **clist;
XX  {
XX    register bit_nr bit;
XX***************
XX*** 507,512 ****
XX--- 578,584 ----
XX  
XX  /* Allocate `nblk' blocks worth of bitmap. */
XX  unsigned *allocbitmap(nblk)
XX+ int nblk;
XX  {
XX    register unsigned *bitmap;
XX  
XX***************
XX*** 516,524 ****
XX  }
XX  
XX  /* Load the bitmap starting at block `bno' from disk. */
XX! loadbitmap(bitmap, bno, nblk)
XX  unsigned *bitmap;
XX  block_nr bno;
XX  {
XX    register i;
XX    register unsigned *p;
XX--- 588,597 ----
XX  }
XX  
XX  /* Load the bitmap starting at block `bno' from disk. */
XX! void loadbitmap(bitmap, bno, nblk)
XX  unsigned *bitmap;
XX  block_nr bno;
XX+ int nblk;
XX  {
XX    register i;
XX    register unsigned *p;
XX***************
XX*** 530,538 ****
XX  }
XX  
XX  /* Write the bitmap starting at block `bno' to disk. */
XX! dumpbitmap(bitmap, bno, nblk)
XX  unsigned *bitmap;
XX  block_nr bno;
XX  {
XX    register i;
XX    register unsigned *p = bitmap;
XX--- 603,612 ----
XX  }
XX  
XX  /* Write the bitmap starting at block `bno' to disk. */
XX! void dumpbitmap(bitmap, bno, nblk)
XX  unsigned *bitmap;
XX  block_nr bno;
XX+ int nblk;
XX  {
XX    register i;
XX    register unsigned *p = bitmap;
XX***************
XX*** 542,550 ****
XX  }
XX  
XX  /* Initialize the given bitmap by setting all the bits starting at `bit'. */
XX! initbitmap(bitmap, bit, nblk)
XX  unsigned *bitmap;
XX  bit_nr bit;
XX  {
XX    register unsigned *first, *last;
XX  
XX--- 616,625 ----
XX  }
XX  
XX  /* Initialize the given bitmap by setting all the bits starting at `bit'. */
XX! void initbitmap(bitmap, bit, nblk)
XX  unsigned *bitmap;
XX  bit_nr bit;
XX+ int nblk;
XX  {
XX    register unsigned *first, *last;
XX  
XX***************
XX*** 558,564 ****
XX  }
XX  
XX  /* Set the bits given by `list' in the bitmap. */
XX! fillbitmap(bitmap, lwb, upb, list)
XX  unsigned *bitmap;
XX  bit_nr lwb, upb;
XX  char **list;
XX--- 633,639 ----
XX  }
XX  
XX  /* Set the bits given by `list' in the bitmap. */
XX! void fillbitmap(bitmap, lwb, upb, list)
XX  unsigned *bitmap;
XX  bit_nr lwb, upb;
XX  char **list;
XX***************
XX*** 578,591 ****
XX  }
XX  
XX  /* Deallocate the bitmap `p'. */
XX! freebitmap(p)
XX  unsigned *p;
XX  {
XX    free((char *) p);
XX  }
XX  
XX  /* Get all the bitmaps used by this program. */
XX! getbitmaps()
XX  {
XX    imap = allocbitmap(N_IMAP);
XX    zmap = allocbitmap(N_ZMAP);
XX--- 653,666 ----
XX  }
XX  
XX  /* Deallocate the bitmap `p'. */
XX! void freebitmap(p)
XX  unsigned *p;
XX  {
XX    free((char *) p);
XX  }
XX  
XX  /* Get all the bitmaps used by this program. */
XX! void getbitmaps()
XX  {
XX    imap = allocbitmap(N_IMAP);
XX    zmap = allocbitmap(N_ZMAP);
XX***************
XX*** 595,601 ****
XX  }
XX  
XX  /* Release all the space taken by the bitmaps. */
XX! putbitmaps()
XX  {
XX    freebitmap(imap);
XX    freebitmap(zmap);
XX--- 670,676 ----
XX  }
XX  
XX  /* Release all the space taken by the bitmaps. */
XX! void putbitmaps()
XX  {
XX    freebitmap(imap);
XX    freebitmap(zmap);
XX***************
XX*** 607,613 ****
XX  /* `w1' and `w2' are differing words from two bitmaps that should be
XX   * identical.  Print what's the matter with them.
XX   */
XX! chkword(w1, w2, bit, nbit, type, n, report)
XX  unsigned w1, w2;
XX  char *type;
XX  bit_nr bit, nbit;
XX--- 682,688 ----
XX  /* `w1' and `w2' are differing words from two bitmaps that should be
XX   * identical.  Print what's the matter with them.
XX   */
XX! void chkword(w1, w2, bit, nbit, type, n, report)
XX  unsigned w1, w2;
XX  char *type;
XX  bit_nr bit, nbit;
XX***************
XX*** 627,636 ****
XX  /* Check if the given (correct) bitmap is identical with the one that is
XX   * on the disk.  If not, ask if the disk should be repaired.
XX   */
XX! chkmap(cmap, dmap, bit, blkno, nblk, nbit, type)
XX  unsigned *cmap, *dmap;
XX  bit_nr bit, nbit;
XX  block_nr blkno;
XX  char *type;
XX  {
XX    register unsigned *p = dmap, *q = cmap;
XX--- 702,712 ----
XX  /* Check if the given (correct) bitmap is identical with the one that is
XX   * on the disk.  If not, ask if the disk should be repaired.
XX   */
XX! void chkmap(cmap, dmap, bit, blkno, nblk, nbit, type)
XX  unsigned *cmap, *dmap;
XX  bit_nr bit, nbit;
XX  block_nr blkno;
XX+ int nblk;
XX  char *type;
XX  {
XX    register unsigned *p = dmap, *q = cmap;
XX***************
XX*** 651,657 ****
XX  }
XX  
XX  /* See if the inodes that aren't allocated are cleared. */
XX! chkilist()
XX  {
XX    register ino_t ino = 1;
XX    mode_t mode;
XX--- 727,733 ----
XX  }
XX  
XX  /* See if the inodes that aren't allocated are cleared. */
XX! void chkilist()
XX  {
XX    register ino_t ino = 1;
XX    mode_t mode;
XX***************
XX*** 671,683 ****
XX  }
XX  
XX  /* Allocate an array to maintain the inode reference counts in. */
XX! getcount()
XX  {
XX    count = (nlink_t *) alloc(sb.s_ninodes + 1, sizeof(nlink_t));
XX  }
XX  
XX  /* The reference count for inode `ino' is wrong.  Ask if it should be adjusted. */
XX! counterror(ino)
XX  ino_t ino;
XX  {
XX    d_inode inode;
XX--- 747,759 ----
XX  }
XX  
XX  /* Allocate an array to maintain the inode reference counts in. */
XX! void getcount()
XX  {
XX    count = (nlink_t *) alloc(sb.s_ninodes + 1, sizeof(nlink_t));
XX  }
XX  
XX  /* The reference count for inode `ino' is wrong.  Ask if it should be adjusted. */
XX! void counterror(ino)
XX  ino_t ino;
XX  {
XX    d_inode inode;
XX***************
XX*** 708,714 ****
XX   * Thus, when the whole file system has been traversed, all the entries
XX   * should be zero.
XX   */
XX! chkcount()
XX  {
XX    register ino_t ino;
XX  
XX--- 784,790 ----
XX   * Thus, when the whole file system has been traversed, all the entries
XX   * should be zero.
XX   */
XX! void chkcount()
XX  {
XX    register ino_t ino;
XX  
XX***************
XX*** 718,731 ****
XX  }
XX  
XX  /* Deallocate the `count' array. */
XX! freecount()
XX  {
XX    free((char *) count);
XX  }
XX  
XX  /* Print the inode permission bits given by mode and shift. */
XX! printperm(mode, shift, special, overlay)
XX  mode_t mode;
XX  {
XX    if (mode >> shift & R_BIT)
XX  	putchar('r');
XX--- 794,810 ----
XX  }
XX  
XX  /* Deallocate the `count' array. */
XX! void freecount()
XX  {
XX    free((char *) count);
XX  }
XX  
XX  /* Print the inode permission bits given by mode and shift. */
XX! void printperm(mode, shift, special, overlay)
XX  mode_t mode;
XX+ int shift;
XX+ int special;
XX+ int overlay;
XX  {
XX    if (mode >> shift & R_BIT)
XX  	putchar('r');
XX***************
XX*** 745,751 ****
XX  }
XX  
XX  /* List the given inode. */
XX! list(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX--- 824,830 ----
XX  }
XX  
XX  /* List the given inode. */
XX! void list(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX***************
XX*** 760,765 ****
XX--- 839,847 ----
XX        case I_CHAR_SPECIAL:	putchar('c');	break;
XX        case I_BLOCK_SPECIAL:	putchar('b');	break;
XX        case I_NAMED_PIPE:	putchar('p');	break;
XX+ #ifdef I_SYMBOLIC_LINK
XX+       case I_SYMBOLIC_LINK:	putchar('l');	break;
XX+ #endif
XX        default:			putchar('?');
XX  }
XX    printperm(ip->i_mode, 6, I_SET_UID_BIT, 's');
XX***************
XX*** 773,779 ****
XX  	       (dev_t) ip->i_zone[0] >> MINOR & 0xFF);
XX  	break;
XX        default:	printf("%7ld ", ip->i_size);
XX! }
XX    printpath(0, 1);
XX  }
XX  
XX--- 855,861 ----
XX  	       (dev_t) ip->i_zone[0] >> MINOR & 0xFF);
XX  	break;
XX        default:	printf("%7ld ", ip->i_size);
XX!   }
XX    printpath(0, 1);
XX  }
XX  
XX***************
XX*** 781,787 ****
XX   * Don't name the function remove() - that is owned by ANSI, and chaos results
XX   * when it is a macro.
XX   */
XX! Remove(dp)
XX  dir_struct *dp;
XX  {
XX    setbit(spec_imap, (bit_nr) dp->d_inum);
XX--- 863,869 ----
XX   * Don't name the function remove() - that is owned by ANSI, and chaos results
XX   * when it is a macro.
XX   */
XX! int Remove(dp)
XX  dir_struct *dp;
XX  {
XX    setbit(spec_imap, (bit_nr) dp->d_inum);
XX***************
XX*** 830,836 ****
XX  }
XX  
XX  /* See if the `.' or `..' entry is as expected. */
XX! chkdots(ino, pos, dp, exp)
XX  ino_t ino, exp;
XX  off_t pos;
XX  dir_struct *dp;
XX--- 912,918 ----
XX  }
XX  
XX  /* See if the `.' or `..' entry is as expected. */
XX! int chkdots(ino, pos, dp, exp)
XX  ino_t ino, exp;
XX  off_t pos;
XX  dir_struct *dp;
XX***************
XX*** 865,871 ****
XX  }
XX  
XX  /* Check the name in a directory entry. */
XX! chkname(ino, dp)
XX  ino_t ino;
XX  dir_struct *dp;
XX  {
XX--- 947,953 ----
XX  }
XX  
XX  /* Check the name in a directory entry. */
XX! int chkname(ino, dp)
XX  ino_t ino;
XX  dir_struct *dp;
XX  {
XX***************
XX*** 895,901 ****
XX  /* Check a directory entry.  Here the routine `descendtree' is called
XX   * recursively to check the file or directory pointed to by the entry.
XX   */
XX! chkentry(ino, pos, dp)
XX  ino_t ino;
XX  off_t pos;
XX  dir_struct *dp;
XX--- 977,983 ----
XX  /* Check a directory entry.  Here the routine `descendtree' is called
XX   * recursively to check the file or directory pointed to by the entry.
XX   */
XX! int chkentry(ino, pos, dp)
XX  ino_t ino;
XX  off_t pos;
XX  dir_struct *dp;
XX***************
XX*** 946,952 ****
XX  /* Check a zone of a directory by checking all the entries in the zone.
XX   * The zone is split up into chunks to not allocate too much stack.
XX   */
XX! chkdirzone(ino, ip, pos, zno)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t pos;
XX--- 1028,1034 ----
XX  /* Check a zone of a directory by checking all the entries in the zone.
XX   * The zone is split up into chunks to not allocate too much stack.
XX   */
XX! int chkdirzone(ino, ip, pos, zno)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t pos;
XX***************
XX*** 982,990 ****
XX  }
XX  
XX  /* There is something wrong with the given zone.  Print some details. */
XX! errzone(mess, zno, level, pos)
XX  char *mess;
XX  zone_nr zno;
XX  off_t pos;
XX  {
XX    printf("%s zone in ", mess);
XX--- 1064,1073 ----
XX  }
XX  
XX  /* There is something wrong with the given zone.  Print some details. */
XX! void errzone(mess, zno, level, pos)
XX  char *mess;
XX  zone_nr zno;
XX+ int level;
XX  off_t pos;
XX  {
XX    printf("%s zone in ", mess);
XX***************
XX*** 995,1010 ****
XX        case 1:	printf("SINGLE INDIRECT");	break;
XX        case 2:	printf("DOUBLE INDIRECT");	break;
XX        default:	printf("VERY INDIRECT");
XX! }
XX    printf(", pos = %ld)\n", pos);
XX  }
XX  
XX  /* Found the given zone in the given inode.  Check it, and if ok, mark it
XX   * in the zone bitmap.
XX   */
XX! markzone(ino, zno, level, pos)
XX  ino_t ino;
XX  zone_nr zno;
XX  off_t pos;
XX  {
XX    register bit_nr bit = (bit_nr) zno - FIRST + 1;
XX--- 1078,1094 ----
XX        case 1:	printf("SINGLE INDIRECT");	break;
XX        case 2:	printf("DOUBLE INDIRECT");	break;
XX        default:	printf("VERY INDIRECT");
XX!   }
XX    printf(", pos = %ld)\n", pos);
XX  }
XX  
XX  /* Found the given zone in the given inode.  Check it, and if ok, mark it
XX   * in the zone bitmap.
XX   */
XX! int markzone(ino, zno, level, pos)
XX  ino_t ino;
XX  zone_nr zno;
XX+ int level;
XX  off_t pos;
XX  {
XX    register bit_nr bit = (bit_nr) zno - FIRST + 1;
XX***************
XX*** 1020,1026 ****
XX  	return(0);
XX    }
XX    nfreezone--;
XX!   if (bitset(spec_zmap, bit)) errzone("found", ino, zno, level, pos, bit);
XX    setbit(zmap, bit);
XX    return(1);
XX  }
XX--- 1104,1110 ----
XX  	return(0);
XX    }
XX    nfreezone--;
XX!   if (bitset(spec_zmap, bit)) errzone("found", zno, level, pos);
XX    setbit(zmap, bit);
XX    return(1);
XX  }
XX***************
XX*** 1028,1038 ****
XX  /* Check an indirect zone by checking all of its entries.
XX   * The zone is split up into chunks to not allocate too much stack.
XX   */
XX! chkindzone(ino, ip, pos, zno, level)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t *pos;
XX  zone_nr zno;
XX  {
XX    zone_nr indirect[CINDIR];
XX    register n = NR_INDIRECTS / CINDIR;
XX--- 1112,1123 ----
XX  /* Check an indirect zone by checking all of its entries.
XX   * The zone is split up into chunks to not allocate too much stack.
XX   */
XX! int chkindzone(ino, ip, pos, zno, level)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t *pos;
XX  zone_nr zno;
XX+ int level;
XX  {
XX    zone_nr indirect[CINDIR];
XX    register n = NR_INDIRECTS / CINDIR;
XX***************
XX*** 1050,1055 ****
XX--- 1135,1141 ----
XX   * at some level of indirection.
XX   */
XX  off_t jump(level)
XX+ int level;
XX  {
XX    off_t power = ZONE_SIZE;
XX  
XX***************
XX*** 1062,1072 ****
XX  /* Check a zone, which may be either a normal data zone, a directory zone,
XX   * or an indirect zone.
XX   */
XX! zonechk(ino, ip, pos, zno, level)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t *pos;
XX  zone_nr zno;
XX  {
XX    if (level == 0) {
XX  	if ((ip->i_mode & I_TYPE) == I_DIRECTORY &&
XX--- 1148,1159 ----
XX  /* Check a zone, which may be either a normal data zone, a directory zone,
XX   * or an indirect zone.
XX   */
XX! int zonechk(ino, ip, pos, zno, level)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t *pos;
XX  zone_nr zno;
XX+ int level;
XX  {
XX    if (level == 0) {
XX  	if ((ip->i_mode & I_TYPE) == I_DIRECTORY &&
XX***************
XX*** 1079,1093 ****
XX  }
XX  
XX  /* Check a list of zones given by `zlist'. */
XX! chkzones(ino, ip, pos, zlist, len, level)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t *pos;
XX  zone_nr *zlist;
XX  {
XX    register ok = 1, i;
XX  
XX!   for (i = 0; i < len && *pos < ip->i_size; i++)
XX  	if (zlist[i] == NO_ZONE)
XX  		*pos += jump(level);
XX  	else if (!markzone(ino, zlist[i], level, *pos)) {
XX--- 1166,1186 ----
XX  }
XX  
XX  /* Check a list of zones given by `zlist'. */
XX! int chkzones(ino, ip, pos, zlist, len, level)
XX  ino_t ino;
XX  d_inode *ip;
XX  off_t *pos;
XX  zone_nr *zlist;
XX+ int len;
XX+ int level;
XX  {
XX    register ok = 1, i;
XX  
XX!   /* The check on the position in the next loop is commented out, since FS
XX!    * now requires valid zone numbers in each level that is necessary and FS
XX!    * always deleted all the zones in the double indirect block.
XX!    */
XX!   for (i = 0; i < len /* && *pos < ip->i_size */ ; i++)
XX  	if (zlist[i] == NO_ZONE)
XX  		*pos += jump(level);
XX  	else if (!markzone(ino, zlist[i], level, *pos)) {
XX***************
XX*** 1099,1119 ****
XX  }
XX  
XX  /* Check a file or a directory. */
XX! chkfile(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX    register ok, i, level;
XX    off_t pos = 0;
XX  
XX!   ok = chkzones(ino, ip, &pos, &ip->i_zone[0], NR_DZONE_NUM, 0);
XX    for (i = NR_DZONE_NUM, level = 1; i < NR_ZONE_NUMS; i++, level++)
XX! 	ok &= chkzones(ino, ip, &pos, &ip->i_zone[i], 1, level);
XX    return(ok);
XX  }
XX  
XX  /* Check a directory by checking the contents.  Check if . and .. are present. */
XX! chkdirectory(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX--- 1192,1212 ----
XX  }
XX  
XX  /* Check a file or a directory. */
XX! int chkfile(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX    register ok, i, level;
XX    off_t pos = 0;
XX  
XX!   ok = chkzones(ino, ip, &pos, (zone_nr *)&ip->i_zone[0], NR_DZONE_NUM, 0);
XX    for (i = NR_DZONE_NUM, level = 1; i < NR_ZONE_NUMS; i++, level++)
XX! 	ok &= chkzones(ino, ip, &pos, (zone_nr *)&ip->i_zone[i], 1, level);
XX    return(ok);
XX  }
XX  
XX  /* Check a directory by checking the contents.  Check if . and .. are present. */
XX! int chkdirectory(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX***************
XX*** 1138,1167 ****
XX    return(ok);
XX  }
XX  
XX! /* Check the mode of an inode, and if it is a file or a directory, check
XX!  * the contents.
XX!  */
XX! chkmode(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX    switch (ip->i_mode & I_TYPE) {
XX        case I_REGULAR:
XX  	nregular++;
XX  	return chkfile(ino, ip);
XX- 	break;
XX        case I_DIRECTORY:
XX  	ndirectory++;
XX  	return chkdirectory(ino, ip);
XX        case I_BLOCK_SPECIAL:
XX  	nblkspec++;
XX! 	return(1);
XX        case I_CHAR_SPECIAL:
XX  	ncharspec++;
XX! 	return(1);
XX        case I_NAMED_PIPE:
XX  	npipe++;
XX! 	return(1);
XX        default:
XX  	nbadinode++;
XX  	printf("bad mode of ");
XX--- 1231,1312 ----
XX    return(ok);
XX  }
XX  
XX! #ifdef I_SYMBOLIC_LINK
XX! 
XX! /* Check the validity of a symbolic link. */
XX! int chklink(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX+   int ok;
XX+ 
XX+   ok = chkfile(ino, ip);
XX+   if (ip->i_size <= 0 || ip->i_size > BLOCK_SIZE) {
XX+ 	if (ip->i_size == 0)
XX+ 		printf("empty symbolic link ");
XX+ 	else
XX+ 		printf("symbolic link too large (size %ld) ", ip->i_size);
XX+ 	printpath(2, 1);
XX+ 	ok = 0;
XX+   }
XX+   return(ok);
XX+ }
XX+ 
XX+ #endif
XX+ 
XX+ /* Check the validity of a special file. */
XX+ int chkspecial(ino, ip)
XX+ ino_t ino;
XX+ d_inode *ip;
XX+ {
XX+   int i, ok;
XX+ 
XX+   ok = 1;
XX+   if ((dev_t) ip->i_zone[0] == NO_DEV) {
XX+ 	printf("illegal device number %u for special file ", ip->i_zone[0]);
XX+ 	printpath(2, 1);
XX+ 	ok = 0;
XX+   }
XX+ 
XX+   /* FS will not use the remaining "zone numbers" but 1.6.11++ will panic if
XX+    * they are nonzero, since this should not happen.
XX+    */
XX+   for (i = 1; i < NR_ZONE_NUMS; i++)
XX+ 	if (ip->i_zone[i] != NO_ZONE) {
XX+ 		printf("nonzero zone number %u for special file ",
XX+ 		       ip->i_zone[i]);
XX+ 		printpath(2, 1);
XX+ 		ok = 0;
XX+ 	}
XX+   return(ok);
XX+ }
XX+ 
XX+ /* Check the mode and contents of an inode. */
XX+ int chkmode(ino, ip)
XX+ ino_t ino;
XX+ d_inode *ip;
XX+ {
XX    switch (ip->i_mode & I_TYPE) {
XX        case I_REGULAR:
XX  	nregular++;
XX  	return chkfile(ino, ip);
XX        case I_DIRECTORY:
XX  	ndirectory++;
XX  	return chkdirectory(ino, ip);
XX        case I_BLOCK_SPECIAL:
XX  	nblkspec++;
XX! 	return chkspecial(ino, ip);
XX        case I_CHAR_SPECIAL:
XX  	ncharspec++;
XX! 	return chkspecial(ino, ip);
XX        case I_NAMED_PIPE:
XX  	npipe++;
XX! 	return chkfile(ino, ip);
XX! #ifdef I_SYMBOLIC_LINK
XX!       case I_SYMBOLIC_LINK:
XX! 	nsyml++;
XX! 	return chklink(ino, ip);
XX! #endif
XX        default:
XX  	nbadinode++;
XX  	printf("bad mode of ");
XX***************
XX*** 1172,1178 ****
XX  }
XX  
XX  /* Check an inode. */
XX! chkinode(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX--- 1317,1323 ----
XX  }
XX  
XX  /* Check an inode. */
XX! int chkinode(ino, ip)
XX  ino_t ino;
XX  d_inode *ip;
XX  {
XX***************
XX*** 1200,1206 ****
XX  }
XX  
XX  /* Check the directory entry pointed to by dp, by checking the inode. */
XX! descendtree(dp)
XX  dir_struct *dp;
XX  {
XX    d_inode inode;
XX--- 1345,1351 ----
XX  }
XX  
XX  /* Check the directory entry pointed to by dp, by checking the inode. */
XX! int descendtree(dp)
XX  dir_struct *dp;
XX  {
XX    d_inode inode;
XX***************
XX*** 1236,1242 ****
XX  }
XX  
XX  /* Check the file system tree. */
XX! chktree()
XX  {
XX    dir_struct dir;
XX  
XX--- 1381,1387 ----
XX  }
XX  
XX  /* Check the file system tree. */
XX! void chktree()
XX  {
XX    dir_struct dir;
XX  
XX***************
XX*** 1249,1255 ****
XX  }
XX  
XX  /* Print the totals of all the objects found. */
XX! printtotal()
XX  {
XX    printf("blocksize = %5d        ", BLOCK_SIZE);
XX    printf("zonesize  = %5d\n", ZONE_SIZE);
XX--- 1394,1400 ----
XX  }
XX  
XX  /* Print the totals of all the objects found. */
XX! void printtotal()
XX  {
XX    printf("blocksize = %5d        ", BLOCK_SIZE);
XX    printf("zonesize  = %5d\n", ZONE_SIZE);
XX***************
XX*** 1261,1266 ****
XX--- 1406,1412 ----
XX    if (nbadinode != 0) pr("%6u    Bad inode%s\n", nbadinode, "", "s");
XX    pr("%6u    Free inode%s\n", nfreeinode, "", "s");
XX    pr("%6u    Named pipe%s\n", npipe, "", "s");
XX+   pr("%6u    Symbolic link%s\n", nsyml, "", "s");
XX  /* Don't print some fields.
XX    printf("\n");
XX    pr("%6u    Data zone%s\n",		  ztype[0],	 "",   "s");
XX***************
XX*** 1275,1281 ****
XX   * listed by `zlist' should be watched for while checking the file system.
XX   */
XX  
XX! chkdev(f, clist, ilist, zlist)
XX  char *f, **clist, **ilist, **zlist;
XX  {
XX    if (automatic) repair = 1;
XX--- 1421,1427 ----
XX   * listed by `zlist' should be watched for while checking the file system.
XX   */
XX  
XX! void chkdev(f, clist, ilist, zlist)
XX  char *f, **clist, **ilist, **zlist;
XX  {
XX    if (automatic) repair = 1;
XX***************
XX*** 1313,1319 ****
XX    if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
XX  }
XX  
XX! main(argc, argv)
XX  char **argv;
XX  {
XX    register char **clist = 0, **ilist = 0, **zlist = 0;
XX--- 1459,1466 ----
XX    if (changed) printf("----- FILE SYSTEM HAS BEEN MODIFIED -----\n\n");
XX  }
XX  
XX! int main(argc, argv)
XX! int argc;
XX  char **argv;
XX  {
XX    register char **clist = 0, **ilist = 0, **zlist = 0;
XX***************
XX*** 1359,1362 ****
XX    }
XX    return(0);
XX  }
XX- 
XX--- 1506,1508 ----
X/
Xecho x - gather.c.d
Xsed '/^X/s///' > gather.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/gather.c  crc=44735   8145	Sun Apr 25 21:34:59 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/gather.c  crc=36111   8579	Wed Nov  4 04:19:12 1992
XX***************
XX*** 28,33 ****
XX--- 28,36 ----
XX  #include <sys/stat.h>
XX  #include <dirent.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define DEFAULT        60000	/* default archive size */
XX***************
XX*** 50,59 ****
XX    long file_size;
XX  } dir_ent[MAX_DIR_ENT];
XX  
XX! long atol(), heuristic();
XX! char *getcwd();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 53,68 ----
XX    long file_size;
XX  } dir_ent[MAX_DIR_ENT];
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int collect, (int first, int limit, long cutoff));
XX! _PROTOTYPE(long heuristic, (long m));
XX! _PROTOTYPE(void sort_dir, (int limit));
XX! _PROTOTYPE(void swap, (struct dir_ent *p, struct dir_ent *q));
XX! _PROTOTYPE(void fudge, (struct dir_ent *p, struct dir_ent *endp, long size));
XX! _PROTOTYPE(void get_basename, (char *s, char *file));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 104,110 ****
XX    /* Open the source directory. */
XX    i = 0;
XX    p = heap;
XX!   if ((dirp = opendir(src_dir)) == (DIR *) NULL) {
XX  	fprintf(stderr, "gather: cannot open %s\n", src_dir);
XX  	exit(2);
XX    }
XX--- 113,119 ----
XX    /* Open the source directory. */
XX    i = 0;
XX    p = heap;
XX!   if ((dirp = opendir(src_dir)) == NULL) {
XX  	fprintf(stderr, "gather: cannot open %s\n", src_dir);
XX  	exit(2);
XX    }
XX***************
XX*** 112,118 ****
XX    /* Read in all the file names. */
XX    while (1) {
XX  	d = readdir(dirp);
XX! 	if (d == (struct dirent *) NULL) break;
XX  	l = strlen(d->d_name);
XX  	if (p + l >= &heap[HEAP_SIZE] || i >= MAX_DIR_ENT) {
XX  		fprintf(stderr, "gather: %s is too large\n", src_dir);
XX--- 121,127 ----
XX    /* Read in all the file names. */
XX    while (1) {
XX  	d = readdir(dirp);
XX! 	if (d == NULL) break;
XX  	l = strlen(d->d_name);
XX  	if (p + l >= &heap[HEAP_SIZE] || i >= MAX_DIR_ENT) {
XX  		fprintf(stderr, "gather: %s is too large\n", src_dir);
XX***************
XX*** 193,198 ****
XX--- 202,208 ----
XX  
XX  	counter++;
XX    }
XX+   return(0);
XX  }
XX  
XX  int collect(first, limit, cutoff)
XX***************
XX*** 250,256 ****
XX  
XX  
XX  
XX! sort_dir(limit)
XX  int limit;			/* how many entries in dir_ent */
XX  {
XX  /* Sort the directory using bubble sort. */
XX--- 260,266 ----
XX  
XX  
XX  
XX! void sort_dir(limit)
XX  int limit;			/* how many entries in dir_ent */
XX  {
XX  /* Sort the directory using bubble sort. */
XX***************
XX*** 264,270 ****
XX    }
XX  }
XX  
XX! swap(p, q)
XX  struct dir_ent *p, *q;
XX  {
XX    /* Exchange two entries. */
XX--- 274,280 ----
XX    }
XX  }
XX  
XX! void swap(p, q)
XX  struct dir_ent *p, *q;
XX  {
XX    /* Exchange two entries. */
XX***************
XX*** 281,287 ****
XX  }
XX  
XX  
XX! fudge(p, endp, size)
XX  struct dir_ent *p, *endp;
XX  long size;
XX  {
XX--- 291,297 ----
XX  }
XX  
XX  
XX! void fudge(p, endp, size)
XX  struct dir_ent *p, *endp;
XX  long size;
XX  {
XX***************
XX*** 300,317 ****
XX  }
XX  
XX  
XX! get_basename(s, file)
XX  char *s;
XX  char *file;
XX  {
XX  /* Determine the basename and copy it to base_name. */
XX  
XX-   int fd, n;
XX    char *p, *q;
XX  
XX    if (*file != 0) p = file;
XX    else if (strcmp(s, ".") == 0) {
XX! 	if (getcwd(work, NAME_SIZE) == (char *) NULL) {
XX  		fprintf(stderr, "gather: could not get name of working dir\n");
XX  		exit(2);
XX  	}
XX--- 310,326 ----
XX  }
XX  
XX  
XX! void get_basename(s, file)
XX  char *s;
XX  char *file;
XX  {
XX  /* Determine the basename and copy it to base_name. */
XX  
XX    char *p, *q;
XX  
XX    if (*file != 0) p = file;
XX    else if (strcmp(s, ".") == 0) {
XX! 	if (getcwd(work, NAME_SIZE) == NULL) {
XX  		fprintf(stderr, "gather: could not get name of working dir\n");
XX  		exit(2);
XX  	}
XX***************
XX*** 329,338 ****
XX  	if (q < p || *q == '/') break;
XX  	q--;
XX    }
XX!   strncpy(base_name, q + 1, BASE_SIZE);
XX  }
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: gather [-b bytes] [-s src_dir] [-d dst_dir] [-f file]\n");
XX    exit(1);
XX--- 338,347 ----
XX  	if (q < p || *q == '/') break;
XX  	q--;
XX    }
XX!   strncpy(base_name, q + 1, (size_t)BASE_SIZE);
XX  }
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: gather [-b bytes] [-s src_dir] [-d dst_dir] [-f file]\n");
XX    exit(1);
X/
Xecho x - getlf.c.d
Xsed '/^X/s///' > getlf.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/getlf.c  crc=03908    388	Sun Apr 25 21:35:00 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/getlf.c  crc=46770    487	Sun Jan 17 20:52:41 1993
XX***************
XX*** 2,9 ****
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 2,14 ----
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 14,25 ****
XX  	std_err(argv[1]);
XX  	std_err("\n");
XX    }
XX    close(0);
XX    open("/dev/tty", O_RDONLY);
XX  
XX    do {
XX  	if (read(0, &c, 1) <= 0) exit(1);
XX- 	if (c <= 0) exit(1);
XX    } while (c != '\n');
XX!   exit(0);
XX  }
XX--- 19,30 ----
XX  	std_err(argv[1]);
XX  	std_err("\n");
XX    }
XX+ 
XX    close(0);
XX    open("/dev/tty", O_RDONLY);
XX  
XX    do {
XX  	if (read(0, &c, 1) <= 0) exit(1);
XX    } while (c != '\n');
XX!   return(0);
XX  }
X/
Xecho x - getty.c.d
Xsed '/^X/s///' > getty.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/getty.c  crc=30219  17202	Sun Apr 25 21:35:01 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/getty.c  crc=05986  17622	Sun Jan 17 20:52:41 1993
XX***************
XX*** 26,42 ****
XX  #include <string.h>
XX  #include <fcntl.h>
XX  #include <pwd.h>
XX  
XX- #ifdef NULL	/* ugly, I know... */
XX- #	undef NULL
XX- #endif	/* NULL */
XX- #define NULL 0
XX- 
XX- #ifdef SIG_IGN	/* even more ugly... */
XX- #	undef SIG_IGN
XX- #	define SIG_IGN 1
XX- #endif	/* SIG_IGN */
XX- 
XX  #ifndef BITS8	/* new-style UNIX or MINIX */
XX  #	define BITS5 CS5
XX  #	define BITS6 CS6
XX--- 26,34 ----
XX  #include <string.h>
XX  #include <fcntl.h>
XX  #include <pwd.h>
XX+ #include <time.h>
XX+ #include <stdio.h>
XX  
XX  #ifndef BITS8	/* new-style UNIX or MINIX */
XX  #	define BITS5 CS5
XX  #	define BITS6 CS6
XX***************
XX*** 51,57 ****
XX  #define COMMENT     		 '#'	/* this char starts a comment-line */
XX  #define SEPA        		 '#'	/* this char separates the fields */
XX  #define EOT         	     '\004'
XX! #define EOF		   (char) 0
XX  #define STARTC	 		021	/* CTRL-Q */
XX  #define STOPC	 		023	/* CTRL-S */
XX  #define QUITC	 		034	/* CTRL-\ */
XX--- 43,49 ----
XX  #define COMMENT     		 '#'	/* this char starts a comment-line */
XX  #define SEPA        		 '#'	/* this char separates the fields */
XX  #define EOT         	     '\004'
XX! #define E_O_F		   (char) 0
XX  #define STARTC	 		021	/* CTRL-Q */
XX  #define STOPC	 		023	/* CTRL-S */
XX  #define QUITC	 		034	/* CTRL-\ */
XX***************
XX*** 87,96 ****
XX  int state = ST_IDLE;		/* the IDLE/SUSPEND/RUNNING state flag */
XX  struct sgttyb tty;		/* the current terminal state */
XX  
XX  
XX- void do_stty();			/* forward declaration */
XX-   
XX- 
XX  void sigcatch(sig)
XX  int sig;
XX  {
XX--- 79,101 ----
XX  int state = ST_IDLE;		/* the IDLE/SUSPEND/RUNNING state flag */
XX  struct sgttyb tty;		/* the current terminal state */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void sigcatch, (int sig));
XX+ _PROTOTYPE(char agetchar, (int fd));
XX+ _PROTOTYPE(char *readline, (int fd));
XX+ _PROTOTYPE(void decode, (char *text, ENTRY *ep));
XX+ _PROTOTYPE(int readdefs, (char *name, char *label));
XX+ _PROTOTYPE(void select_speed, (void));
XX+ _PROTOTYPE(void showfile, (char *name));
XX+ _PROTOTYPE(void wtmp, (char *line));
XX+ _PROTOTYPE(int areadch, (void));
XX+ _PROTOTYPE(void do_getty, (char *name));
XX+ _PROTOTYPE(void do_login, (char *name));
XX+ _PROTOTYPE(int getspeed, (char *spd));
XX+ _PROTOTYPE(void do_stty, (char *parms));
XX+ _PROTOTYPE(void do_carrier, (void));
XX+ _PROTOTYPE(void usage, (void));
XX  
XX  void sigcatch(sig)
XX  int sig;
XX  {
XX***************
XX*** 116,122 ****
XX  char agetchar(fd)
XX  int fd;
XX  {
XX! /* Read a character, or EOF if zero chars read. */
XX  
XX    static char buf[1024];
XX    static char *bufp = buf;
XX--- 121,127 ----
XX  char agetchar(fd)
XX  int fd;
XX  {
XX! /* Read a character, or E_O_F if zero chars read. */
XX  
XX    static char buf[1024];
XX    static char *bufp = buf;
XX***************
XX*** 126,132 ****
XX  	nleft = read(fd, buf, 1024);
XX  	bufp = buf;
XX    }
XX!   return((--nleft >= 0) ? *bufp++ : EOF);
XX  }
XX  
XX  
XX--- 131,137 ----
XX  	nleft = read(fd, buf, 1024);
XX  	bufp = buf;
XX    }
XX!   return((--nleft >= 0) ? *bufp++ : E_O_F);
XX  }
XX  
XX  
XX***************
XX*** 136,149 ****
XX  /* Read one line from the defs-file. */
XX  
XX    char linbuff[512];
XX!   register int c, len;
XX    register char *bp = linbuff;
XX  
XX    /* Read a line of text. */
XX    len = 0;
XX    while (1) {
XX  	c = agetchar(fd);
XX! 	if (c == '\n' || c == EOF) break;
XX  	*bp++ = c;
XX  	len++;
XX    }
XX--- 141,155 ----
XX  /* Read one line from the defs-file. */
XX  
XX    char linbuff[512];
XX!   register int c;
XX!   register size_t len;
XX    register char *bp = linbuff;
XX  
XX    /* Read a line of text. */
XX    len = 0;
XX    while (1) {
XX  	c = agetchar(fd);
XX! 	if (c == '\n' || c == E_O_F) break;
XX  	*bp++ = c;
XX  	len++;
XX    }
XX***************
XX*** 151,162 ****
XX  
XX    /* Now allocate a buffer for it. */
XX    bp = (char *)malloc(len + 1);
XX!   if (bp == (char *) NULL) return((char *) NULL);
XX  
XX    /* Copy this line to its buffer. */
XX    strcpy(bp, linbuff);
XX  
XX!   return((c == EOF) ? (char *) NULL : bp);
XX  }
XX  
XX  
XX--- 157,168 ----
XX  
XX    /* Now allocate a buffer for it. */
XX    bp = (char *)malloc(len + 1);
XX!   if (bp == NULL) return(NULL);
XX  
XX    /* Copy this line to its buffer. */
XX    strcpy(bp, linbuff);
XX  
XX!   return((c == E_O_F) ? NULL : bp);
XX  }
XX  
XX  
XX***************
XX*** 207,213 ****
XX    defs = &gdefs[defidx];	/* set DEFAULT definition */
XX    while (1) {
XX  	bp = readline(defsfd);
XX! 	if (bp == (char *) NULL) break;
XX  	switch (*bp) {
XX  	    case '\0':		/* blank line */
XX  		continue;
XX--- 213,219 ----
XX    defs = &gdefs[defidx];	/* set DEFAULT definition */
XX    while (1) {
XX  	bp = readline(defsfd);
XX! 	if (bp == NULL) break;
XX  	switch (*bp) {
XX  	    case '\0':		/* blank line */
XX  		continue;
XX***************
XX*** 215,221 ****
XX  		continue;
XX  	    default:		/* data! */
XX  		decode(bp, &gdefs[defidx]);
XX! 		if (label != (char *) NULL) {
XX  			if (!strcmp(gdefs[defidx].label, label))
XX  				defs = &gdefs[defidx];
XX  		}
XX--- 221,227 ----
XX  		continue;
XX  	    default:		/* data! */
XX  		decode(bp, &gdefs[defidx]);
XX! 		if (label != NULL) {
XX  			if (!strcmp(gdefs[defidx].label, label))
XX  				defs = &gdefs[defidx];
XX  		}
XX***************
XX*** 227,233 ****
XX  }
XX  
XX  
XX! void select()
XX  {
XX  /* Select next speed from the chain. */
XX  
XX--- 233,239 ----
XX  }
XX  
XX  
XX! void select_speed()
XX  {
XX  /* Select next speed from the chain. */
XX  
XX***************
XX*** 277,283 ****
XX    char *blank = "               ";
XX    register char *sp;
XX    int fd, recno;
XX!   extern long time();
XX  
XX    /* Strip off the /dev part of the TTY name. */
XX    sp = strrchr(line, '/');
XX--- 283,289 ----
XX    char *blank = "               ";
XX    register char *sp;
XX    int fd, recno;
XX!   off_t recoff;
XX  
XX    /* Strip off the /dev part of the TTY name. */
XX    sp = strrchr(line, '/');
XX***************
XX*** 295,301 ****
XX  	recno++;
XX    }
XX    close(fd);
XX!   recno *= sizeof(struct utmp);
XX  
XX    /* Clear out the new string fields. */
XX    strncpy(entry.ut_name, blank, sizeof(entry.ut_name));
XX--- 301,307 ----
XX  	recno++;
XX    }
XX    close(fd);
XX!   recoff = recno * (off_t) sizeof(struct utmp);
XX  
XX    /* Clear out the new string fields. */
XX    strncpy(entry.ut_name, blank, sizeof(entry.ut_name));
XX***************
XX*** 316,322 ****
XX  
XX    /* Write a WTMP record. */
XX    if ((fd = open(WTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, 0L, SEEK_END) >= 0L) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX--- 322,328 ----
XX  
XX    /* Write a WTMP record. */
XX    if ((fd = open(WTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, 0L, SEEK_END) != (off_t)-1) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX***************
XX*** 324,330 ****
XX  
XX    /* Rewrite the UTMP entry. */
XX    if ((fd = open(UTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, (long) recno, SEEK_SET) >= 0L) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX--- 330,336 ----
XX  
XX    /* Rewrite the UTMP entry. */
XX    if ((fd = open(UTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, recoff, SEEK_SET) != (off_t)-1) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX***************
XX*** 349,355 ****
XX  	if (keyboard == 1) return(ch);
XX  
XX  	if ((ch == 0) || ((ch & 128) == 128)) {
XX! 		select();
XX  		ioctl(0, TIOCGETP, &tty);
XX  		tty.sg_flags |= RAW;
XX  		tty.sg_flags &= ~ECHO;
XX--- 355,361 ----
XX  	if (keyboard == 1) return(ch);
XX  
XX  	if ((ch == 0) || ((ch & 128) == 128)) {
XX! 		select_speed();
XX  		ioctl(0, TIOCGETP, &tty);
XX  		tty.sg_flags |= RAW;
XX  		tty.sg_flags &= ~ECHO;
XX***************
XX*** 386,398 ****
XX    /* Display prompt, and try to match the caller's speed. */
XX    ch = ' ';
XX    *name = '\0';
XX!   while (ch != EOF) {
XX  	/* Give us a new line */
XX  	write(1, "\r\n", 2);
XX  	write(1, defs->prompt, (unsigned) strlen(defs->prompt));
XX  	ioctl(0, TIOCFLUSH, (struct sgttyb *) NULL);
XX  	np = name;
XX! 	while (ch != EOF) {
XX  		ch = areadch();	/* adaptive READ */
XX  		switch (ch) {
XX  		    case -1:	/* signalled! */
XX--- 392,404 ----
XX    /* Display prompt, and try to match the caller's speed. */
XX    ch = ' ';
XX    *name = '\0';
XX!   while (ch != E_O_F) {
XX  	/* Give us a new line */
XX  	write(1, "\r\n", 2);
XX  	write(1, defs->prompt, (unsigned) strlen(defs->prompt));
XX  	ioctl(0, TIOCFLUSH, (struct sgttyb *) NULL);
XX  	np = name;
XX! 	while (ch != E_O_F) {
XX  		ch = areadch();	/* adaptive READ */
XX  		switch (ch) {
XX  		    case -1:	/* signalled! */
XX***************
XX*** 434,440 ****
XX  		    case '\n':
XX  			write(1, "\r\n", 2);	/* should map this */
XX  			*np = '\0';
XX! 			ch = EOF;
XX  			break;
XX  		    default:
XX  			ch1 = ch;
XX--- 440,446 ----
XX  		    case '\n':
XX  			write(1, "\r\n", 2);	/* should map this */
XX  			*np = '\0';
XX! 			ch = E_O_F;
XX  			break;
XX  		    default:
XX  			ch1 = ch;
XX***************
XX*** 526,532 ****
XX    ioctl(0, TIOCGETC, (struct sgttyb *) &tch);
XX    tty.sg_flags = 0;
XX  
XX!   strncpy(prms, parms, 79);
XX    sp = prms;
XX  
XX    /* Process all options. */
XX--- 532,538 ----
XX    ioctl(0, TIOCGETC, (struct sgttyb *) &tch);
XX    tty.sg_flags = 0;
XX  
XX!   strncpy(prms, parms, (size_t)79);
XX    sp = prms;
XX  
XX    /* Process all options. */
XX***************
XX*** 671,677 ****
XX  char *argv[];
XX  {
XX    char *defsfile = GDEFS;
XX!   char *label = (char *) NULL;
XX    struct passwd *pw;
XX    register char *s;
XX    char uname[30];
XX--- 677,683 ----
XX  char *argv[];
XX  {
XX    char *defsfile = GDEFS;
XX!   char *label = NULL;
XX    struct passwd *pw;
XX    register char *s;
XX    char uname[30];
XX***************
XX*** 682,694 ****
XX  
XX    /* Determine if we were called as 'uugetty'. */
XX    s = strrchr(argv[0], '/');
XX!   if (s == (char *) NULL) s = argv[0];
XX      else s++;
XX    if (*s == 'u') uugetty = 1;
XX  
XX  
XX    c = 1;
XX!   tty_name = (char *) NULL;
XX    while (c < argc) {
XX  	s = argv[c++];
XX  	if (*s == '-') switch (*++s) {
XX--- 688,700 ----
XX  
XX    /* Determine if we were called as 'uugetty'. */
XX    s = strrchr(argv[0], '/');
XX!   if (s == NULL) s = argv[0];
XX      else s++;
XX    if (*s == 'u') uugetty = 1;
XX  
XX  
XX    c = 1;
XX!   tty_name = NULL;
XX    while (c < argc) {
XX  	s = argv[c++];
XX  	if (*s == '-') switch (*++s) {
XX***************
XX*** 707,713 ****
XX  		    default:
XX  			usage();
XX  			exit(-1);
XX! 	} else if (tty_name == (char *) NULL)
XX  		tty_name = argv[c - 1];
XX  	else
XX  		label = argv[c - 1];
XX--- 713,719 ----
XX  		    default:
XX  			usage();
XX  			exit(-1);
XX! 	} else if (tty_name == NULL)
XX  		tty_name = argv[c - 1];
XX  	else
XX  		label = argv[c - 1];
XX***************
XX*** 718,724 ****
XX    tty.sg_ospeed = B0;
XX    if (keyboard == 0) ioctl(0, TIOCSETP, &tty);	/* hangup the line */
XX  
XX!   if (tty_name == (char *) NULL)	/* new INIT */
XX  	tty_name = ttyname(0);
XX  
XX    c = readdefs(defsfile, label);/* GETTYDEFS file into core */
XX--- 724,730 ----
XX    tty.sg_ospeed = B0;
XX    if (keyboard == 0) ioctl(0, TIOCSETP, &tty);	/* hangup the line */
XX  
XX!   if (tty_name == NULL)	/* new INIT */
XX  	tty_name = ttyname(0);
XX  
XX    c = readdefs(defsfile, label);/* GETTYDEFS file into core */
XX***************
XX*** 726,732 ****
XX  
XX    if (uugetty) {
XX  	pw = getpwnam("uucp");	/* get UUCP user ID and group ID */
XX!         if (pw != (struct passwd *) NULL)
XX  		chown(tty_name, pw->pw_uid, pw->pw_gid);
XX  	  else uugetty = 0;
XX    }
XX--- 732,738 ----
XX  
XX    if (uugetty) {
XX  	pw = getpwnam("uucp");	/* get UUCP user ID and group ID */
XX!         if (pw != NULL)
XX  		chown(tty_name, pw->pw_uid, pw->pw_gid);
XX  	  else uugetty = 0;
XX    }
X/
Xecho x - grep.c.d
Xsed '/^X/s///' > grep.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/grep.c  crc=22781   6802	Sun Apr 25 21:35:01 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/grep.c  crc=43047   6858	Wed Nov  4 04:19:12 1992
XX***************
XX*** 35,66 ****
XX  #include <string.h>
XX  #include <stdio.h>
XX  
XX- extern int getopt();		/* Thanks to Henry Spencer */
XX- extern char *optarg;
XX- extern int optind;
XX- 
XX- 
XX  /* Internal constants */
XX  #define MATCH		0	/* exit code: some match somewhere */
XX  #define NO_MATCH	1	/* exit code: no match on any line */
XX  #define FAILURE		2	/* exit code: syntax error or bad file name */
XX  
XX- 
XX  /* Macros */
XX  #define SET_FLAG(c)	(flags[(c)-'a'] = 1)
XX  #define FLAG(c)		(flags[(c)-'a'] != 0)
XX  
XX- 
XX  /* Private storage */
XX  static char *program;		/* program name */
XX  static char flags[26];		/* invocation flags */
XX  static regexp *expression;	/* compiled search pattern */
XX  
XX  
XX  /* Internal interfaces */
XX! static int match();
XX! static char *get_line();
XX! static void error_exit();
XX  
XX  
XX  int main(argc, argv)
XX--- 35,64 ----
XX  #include <string.h>
XX  #include <stdio.h>
XX  
XX  /* Internal constants */
XX  #define MATCH		0	/* exit code: some match somewhere */
XX  #define NO_MATCH	1	/* exit code: no match on any line */
XX  #define FAILURE		2	/* exit code: syntax error or bad file name */
XX  
XX  /* Macros */
XX  #define SET_FLAG(c)	(flags[(c)-'a'] = 1)
XX  #define FLAG(c)		(flags[(c)-'a'] != 0)
XX  
XX  /* Private storage */
XX  static char *program;		/* program name */
XX  static char flags[26];		/* invocation flags */
XX  static regexp *expression;	/* compiled search pattern */
XX  
XX+ /* External variables. */
XX+ extern int optind;
XX+ extern char *optarg;
XX  
XX  /* Internal interfaces */
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(static int match, (FILE *input, char *label, char *filename));
XX! _PROTOTYPE(static char *get_line, (FILE *input));
XX! _PROTOTYPE(static void error_exit, (char *msg));
XX! _PROTOTYPE(void regerror , (char *s ) );
XX  
XX  
XX  int main(argc, argv)
XX***************
XX*** 75,81 ****
XX  
XX    program = argv[0];
XX    memset(flags, 0, sizeof(flags));
XX!   pattern = (char *) NULL;
XX  
XX  /* Process any command line flags. */
XX    while ((opt = getopt(argc, argv, "e:lnsv")) != EOF) {
XX--- 73,79 ----
XX  
XX    program = argv[0];
XX    memset(flags, 0, sizeof(flags));
XX!   pattern = NULL;
XX  
XX  /* Process any command line flags. */
XX    while ((opt = getopt(argc, argv, "e:lnsv")) != EOF) {
XX***************
XX*** 89,101 ****
XX    }
XX  
XX  /* Detect a few problems. */
XX!   if ((exit_status == FAILURE) || (optind == argc && pattern == (char *) NULL))
XX  	error_exit("Usage: %s [-lnsv] [-e] expression [file ...]\n");
XX  
XX  /* Ensure we have a usable pattern. */
XX!   if (pattern == (char *) NULL)
XX  	pattern = argv[optind++];
XX!   if ((expression = regcomp(pattern)) == (regexp *) NULL)
XX  	error_exit("%s: bad regular expression\n");
XX  
XX  /* Process the files appropriately. */
XX--- 87,99 ----
XX    }
XX  
XX  /* Detect a few problems. */
XX!   if ((exit_status == FAILURE) || (optind == argc && pattern == NULL))
XX  	error_exit("Usage: %s [-lnsv] [-e] expression [file ...]\n");
XX  
XX  /* Ensure we have a usable pattern. */
XX!   if (pattern == NULL)
XX  	pattern = argv[optind++];
XX!   if ((expression = regcomp(pattern)) == NULL)
XX  	error_exit("%s: bad regular expression\n");
XX  
XX  /* Process the files appropriately. */
XX***************
XX*** 107,118 ****
XX  	if (strcmp(argv[optind], "-") == 0) {
XX  		exit_status = match(stdin, (char *) NULL, "-");
XX  	} else {
XX! 		if ((input = fopen(argv[optind], "r")) == (FILE *) NULL) {
XX  			fprintf(stderr, "%s: couldn't open %s\n",
XX  							program, argv[optind]);
XX  			exit_status = FAILURE;
XX  		}
XX! 		exit_status = match(input, (char *) NULL, argv[optind]);
XX  	}
XX    }
XX    else
XX--- 105,118 ----
XX  	if (strcmp(argv[optind], "-") == 0) {
XX  		exit_status = match(stdin, (char *) NULL, "-");
XX  	} else {
XX! 		if ((input = fopen(argv[optind], "r")) == NULL) {
XX  			fprintf(stderr, "%s: couldn't open %s\n",
XX  							program, argv[optind]);
XX  			exit_status = FAILURE;
XX  		}
XX! 		else {
XX! 			exit_status = match(input, (char *) NULL, argv[optind]);
XX! 		}
XX  	}
XX    }
XX    else
XX***************
XX*** 120,126 ****
XX  	if (strcmp(argv[optind], "-") == 0) {
XX  		file_status = match(stdin, "-", "-");
XX  	} else {
XX! 		if ((input = fopen(argv[optind], "r")) == (FILE *) NULL) {
XX  			fprintf(stderr, "%s: couldn't open %s\n",
XX  							program, argv[optind]);
XX  			exit_status = FAILURE;
XX--- 120,126 ----
XX  	if (strcmp(argv[optind], "-") == 0) {
XX  		file_status = match(stdin, "-", "-");
XX  	} else {
XX! 		if ((input = fopen(argv[optind], "r")) == NULL) {
XX  			fprintf(stderr, "%s: couldn't open %s\n",
XX  							program, argv[optind]);
XX  			exit_status = FAILURE;
XX***************
XX*** 133,139 ****
XX  		exit_status &= file_status;
XX  	++optind;
XX    }
XX!   exit(exit_status);
XX  }
XX  
XX  
XX--- 133,139 ----
XX  		exit_status &= file_status;
XX  	++optind;
XX    }
XX!   return(exit_status);
XX  }
XX  
XX  
XX***************
XX*** 152,158 ****
XX    int status = NO_MATCH;	/* summary of what was found in this file */
XX  
XX    if (FLAG('s') || FLAG('l')) {
XX! 	while ((line = get_line(input)) != (char *) NULL)
XX  		if (regexec(expression, line, 1)) {
XX  			status = MATCH;
XX  			break;
XX--- 152,158 ----
XX    int status = NO_MATCH;	/* summary of what was found in this file */
XX  
XX    if (FLAG('s') || FLAG('l')) {
XX! 	while ((line = get_line(input)) != NULL)
XX  		if (regexec(expression, line, 1)) {
XX  			status = MATCH;
XX  			break;
XX***************
XX*** 164,175 ****
XX  	return status;
XX    }
XX  
XX!   while ((line = get_line(input)) != (char *) NULL) {
XX  	++lineno;
XX  	if (regexec(expression, line, 1)) {
XX  		status = MATCH;
XX  		if (!FLAG('v')) {
XX! 			if (label != (char *) NULL)
XX  				printf("%s:", label);
XX  			if (FLAG('n'))
XX  				printf("%ld:", lineno);
XX--- 164,175 ----
XX  	return status;
XX    }
XX  
XX!   while ((line = get_line(input)) != NULL) {
XX  	++lineno;
XX  	if (regexec(expression, line, 1)) {
XX  		status = MATCH;
XX  		if (!FLAG('v')) {
XX! 			if (label != NULL)
XX  				printf("%s:", label);
XX  			if (FLAG('n'))
XX  				printf("%ld:", lineno);
XX***************
XX*** 177,183 ****
XX  		}
XX  	} else {
XX  		if (FLAG('v')) {
XX! 			if (label != (char *) NULL)
XX  				printf("%s:", label);
XX  			if (FLAG('n'))
XX  				printf("%ld:", lineno);
XX--- 177,183 ----
XX  		}
XX  	} else {
XX  		if (FLAG('v')) {
XX! 			if (label != NULL)
XX  				printf("%s:", label);
XX  			if (FLAG('n'))
XX  				printf("%ld:", lineno);
XX***************
XX*** 196,204 ****
XX   * The trailing newline is stripped before returning to the caller.
XX   */
XX  
XX! #define FIRST_BUFFER 256		/* first buffer size */
XX  
XX! static char *buf = (char *) NULL;	/* input buffer */
XX  static size_t buf_size = 0;		/* input buffer size */
XX  
XX  static char *get_line(input)
XX--- 196,204 ----
XX   * The trailing newline is stripped before returning to the caller.
XX   */
XX  
XX! #define FIRST_BUFFER (size_t)256		/* first buffer size */
XX  
XX! static char *buf = NULL;	/* input buffer */
XX  static size_t buf_size = 0;		/* input buffer size */
XX  
XX  static char *get_line(input)
XX***************
XX*** 211,217 ****
XX    size_t new_size;
XX  
XX    if (buf_size == 0) {
XX! 	if ((buf = (char *) malloc(FIRST_BUFFER)) == (char *) NULL)
XX  		error_exit("%s: not enough memory\n");
XX  	buf_size = FIRST_BUFFER;
XX    }
XX--- 211,217 ----
XX    size_t new_size;
XX  
XX    if (buf_size == 0) {
XX! 	if ((buf = (char *) malloc(FIRST_BUFFER)) == NULL)
XX  		error_exit("%s: not enough memory\n");
XX  	buf_size = FIRST_BUFFER;
XX    }
XX***************
XX*** 227,235 ****
XX  		*bp++ = c;
XX  	}
XX  	if (c == EOF)
XX! 		return (ferror(input) || bp == buf) ? (char *) NULL : buf;
XX  	new_size = buf_size << 1;
XX! 	if ((new_buf = (char *) realloc(buf, new_size)) == (char *) NULL) {
XX  		fprintf(stderr, "%s: line too long - truncated\n", program);
XX  		while ((c = getc(input)) != EOF && c != '\n') ;
XX  		*bp = '\0';
XX--- 227,235 ----
XX  		*bp++ = c;
XX  	}
XX  	if (c == EOF)
XX! 		return (ferror(input) || bp == buf) ? NULL : buf;
XX  	new_size = buf_size << 1;
XX! 	if ((new_buf = (char *) realloc(buf, new_size)) == NULL) {
XX  		fprintf(stderr, "%s: line too long - truncated\n", program);
XX  		while ((c = getc(input)) != EOF && c != '\n') ;
XX  		*bp = '\0';
X/
Xecho x - gres.c.d
Xsed '/^X/s///' > gres.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/gres.c  crc=35492   3167	Sun Apr 25 21:35:01 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/gres.c  crc=58926   3524	Wed Nov  4 04:19:12 1992
XX***************
XX*** 19,24 ****
XX--- 19,26 ----
XX  
XX  #include <regexp.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <minix/minlib.h>
XX  #include <stdio.h>
XX  
XX  #define MAXLINE (1024)
XX***************
XX*** 28,34 ****
XX  char *progname;
XX  int gflag = 0;			/* != 0 => only do first substitution on line */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 30,43 ----
XX  char *progname;
XX  int gflag = 0;			/* != 0 => only do first substitution on line */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void process, (FILE *inf, regexp *exp, char *repstr));
XX! _PROTOTYPE(void regerror, (char *s));
XX! _PROTOTYPE(char *getbuf, (regexp *exp, char *repstr));
XX! _PROTOTYPE(void pline, (regexp *exp, char ibuf [], char *repstr));
XX! _PROTOTYPE(void dosub, (regexp *exp, char ibuf [], char *repstr));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 49,55 ****
XX  	std_err("gres: null match string is silly\n");
XX  	exit(2);
XX    }
XX!   if ((exp = regcomp(*argp++)) == (regexp *) NULL) {
XX  	std_err("gres: regcomp failed\n");
XX  	exit(2);
XX    }
XX--- 58,64 ----
XX  	std_err("gres: null match string is silly\n");
XX  	exit(2);
XX    }
XX!   if ((exp = regcomp(*argp++)) == NULL) {
XX  	std_err("gres: regcomp failed\n");
XX  	exit(2);
XX    }
XX***************
XX*** 63,69 ****
XX  		if (strcmp(*argp, "-") == 0)
XX  			process(stdin, exp, repstr);
XX  		else {
XX! 			if ((inf = fopen(*argp, "r")) == (FILE *) NULL) {
XX  				std_err("gres: Can't open ");
XX  				std_err(*argp);
XX  				std_err("\n");
XX--- 72,78 ----
XX  		if (strcmp(*argp, "-") == 0)
XX  			process(stdin, exp, repstr);
XX  		else {
XX! 			if ((inf = fopen(*argp, "r")) == NULL) {
XX  				std_err("gres: Can't open ");
XX  				std_err(*argp);
XX  				std_err("\n");
XX***************
XX*** 75,92 ****
XX  		}
XX  		argp++;
XX  	}
XX!   exit(status);
XX  }
XX  
XX  /* This routine does the processing. */
XX! process(inf, exp, repstr)
XX  FILE *inf;
XX  regexp *exp;
XX  char *repstr;
XX  {
XX    char ibuf[MAXLINE];
XX  
XX!   while (fgets(ibuf, MAXLINE, inf) != (char *) NULL) {
XX  	char *cr = strchr(ibuf, '\n');
XX  	if (cr == 0)
XX  		std_err("gres: Line broken\n");
XX--- 84,101 ----
XX  		}
XX  		argp++;
XX  	}
XX!   return(status);
XX  }
XX  
XX  /* This routine does the processing. */
XX! void process(inf, exp, repstr)
XX  FILE *inf;
XX  regexp *exp;
XX  char *repstr;
XX  {
XX    char ibuf[MAXLINE];
XX  
XX!   while (fgets(ibuf, MAXLINE, inf) != NULL) {
XX  	char *cr = strchr(ibuf, '\n');
XX  	if (cr == 0)
XX  		std_err("gres: Line broken\n");
XX***************
XX*** 113,123 ****
XX  regexp *exp;
XX  char *repstr;
XX  {
XX-   char *malloc();
XX-   void free();
XX    static bufsize = 0;
XX    static char *buf = 0;
XX!   int guess = 10;
XX    int ch;
XX  
XX    while (*repstr) {
XX--- 122,130 ----
XX  regexp *exp;
XX  char *repstr;
XX  {
XX    static bufsize = 0;
XX    static char *buf = 0;
XX!   size_t guess = 10;
XX    int ch;
XX  
XX    while (*repstr) {
XX***************
XX*** 139,150 ****
XX    }
XX    if (bufsize < guess) {
XX  	if (buf != 0) free((char *) buf);
XX! 	buf = malloc(guess);
XX    }
XX    return buf;
XX  }
XX  
XX! pline(exp, ibuf, repstr)
XX  regexp *exp;
XX  char ibuf[];
XX  char *repstr;
XX--- 146,157 ----
XX    }
XX    if (bufsize < guess) {
XX  	if (buf != 0) free((char *) buf);
XX! 	buf = (char *)malloc(guess);
XX    }
XX    return buf;
XX  }
XX  
XX! void pline(exp, ibuf, repstr)
XX  regexp *exp;
XX  char ibuf[];
XX  char *repstr;
XX***************
XX*** 159,165 ****
XX  }
XX  
XX  /* Print one subsitution. */
XX! dosub(exp, ibuf, repstr)
XX  regexp *exp;
XX  char ibuf[];
XX  char *repstr;
XX--- 166,172 ----
XX  }
XX  
XX  /* Print one subsitution. */
XX! void dosub(exp, ibuf, repstr)
XX  regexp *exp;
XX  char ibuf[];
XX  char *repstr;
X/
Xecho x - head.c.d
Xsed '/^X/s///' > head.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/head.c  crc=27040   1108	Sun Apr 25 21:35:02 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/head.c  crc=39424   1268	Wed Nov  4 04:19:12 1992
XX***************
XX*** 1,10 ****
XX  /* head - print the first few lines of a file	Author: Andy Tanenbaum */
XX  
XX  #include <stdio.h>
XX  
XX  #define DEFAULT 10
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 1,15 ----
XX  /* head - print the first few lines of a file	Author: Andy Tanenbaum */
XX  
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define DEFAULT 10
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void do_file, (int n, FILE *f));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 41,52 ****
XX  	k++;
XX  	if (k < argc) printf("\n");
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX  
XX! do_file(n, f)
XX  int n;
XX  FILE *f;
XX  {
XX--- 46,57 ----
XX  	k++;
XX  	if (k < argc) printf("\n");
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX  
XX! void do_file(n, f)
XX  int n;
XX  FILE *f;
XX  {
XX***************
XX*** 63,69 ****
XX  }
XX  
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: head [-n] [file ...]\n");
XX    exit(1);
XX--- 68,74 ----
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: head [-n] [file ...]\n");
XX    exit(1);
X/
Xecho x - id.c.d
Xsed '/^X/s///' > id.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/id.c  crc=37920   1361	Sun Apr 25 21:35:02 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/id.c  crc=27853   1301	Wed Nov  4 04:19:12 1992
XX***************
XX*** 1,6 ****
XX  /* id - return uid and gid		Author: John J. Marco */
XX  
XX- 
XX  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
XX  /* 		----- id.c -----					*/
XX  /* Id - get real and effective user id and group id			*/
XX--- 1,5 ----
XX***************
XX*** 11,24 ****
XX  #include <sys/types.h>
XX  #include <pwd.h>
XX  #include <grp.h>
XX  #include <stdio.h>
XX  
XX! main()
XX  {
XX    struct passwd *pwd;
XX-   struct passwd *getpwuid();
XX    struct group *grp;
XX-   struct group *getgrgid();
XX    int uid, gid, euid, egid;
XX  
XX    uid = getuid();
XX--- 10,24 ----
XX  #include <sys/types.h>
XX  #include <pwd.h>
XX  #include <grp.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX! _PROTOTYPE(int main, (void));
XX! 
XX! int main()
XX  {
XX    struct passwd *pwd;
XX    struct group *grp;
XX    int uid, gid, euid, egid;
XX  
XX    uid = getuid();
XX***************
XX*** 26,52 ****
XX    euid = geteuid();
XX    egid = getegid();
XX  
XX!   if ((pwd = getpwuid(uid)) == (struct passwd *) NULL)
XX  	printf("%s%d%s", "uid=", uid, " ");
XX    else
XX  	printf("%s%d%s%s%s", "uid=", uid, "(", pwd->pw_name, ") ");
XX  
XX!   if ((grp = getgrgid(gid)) == (struct group *) NULL)
XX  	printf("%s%d%s", "gid=", gid, " ");
XX    else
XX  	printf("%s%d%s%s%s", "gid=", gid, "(", grp->gr_name, ") ");
XX  
XX    if (uid != euid)
XX! 	if ((pwd = getpwuid(euid)) != (struct passwd *) NULL)
XX  		printf("%s%d%s%s%s", "euid=", euid, "(", pwd->pw_name, ") ");
XX  	else
XX  		printf("%s%d%s", "euid=", euid, " ");
XX  
XX    if (gid != egid)
XX! 	if ((grp = getgrgid(egid)) != (struct group *) NULL)
XX  		printf("%s%d%s%s%s", "egid=", egid, "(", grp->gr_name, ") ");
XX  	else
XX  		printf("%s%d%s", "egid=", egid, " ");
XX  
XX    printf("\n");
XX  }
XX--- 26,53 ----
XX    euid = geteuid();
XX    egid = getegid();
XX  
XX!   if ((pwd = getpwuid(uid)) == NULL)
XX  	printf("%s%d%s", "uid=", uid, " ");
XX    else
XX  	printf("%s%d%s%s%s", "uid=", uid, "(", pwd->pw_name, ") ");
XX  
XX!   if ((grp = getgrgid(gid)) == NULL)
XX  	printf("%s%d%s", "gid=", gid, " ");
XX    else
XX  	printf("%s%d%s%s%s", "gid=", gid, "(", grp->gr_name, ") ");
XX  
XX    if (uid != euid)
XX! 	if ((pwd = getpwuid(euid)) != NULL)
XX  		printf("%s%d%s%s%s", "euid=", euid, "(", pwd->pw_name, ") ");
XX  	else
XX  		printf("%s%d%s", "euid=", euid, " ");
XX  
XX    if (gid != egid)
XX! 	if ((grp = getgrgid(egid)) != NULL)
XX  		printf("%s%d%s%s%s", "egid=", egid, "(", grp->gr_name, ") ");
XX  	else
XX  		printf("%s%d%s", "egid=", egid, " ");
XX  
XX    printf("\n");
XX+   return(0);
XX  }
X/
Xecho x - ifdef.c.d
Xsed '/^X/s///' > ifdef.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ifdef.c  crc=45151  10987	Sun Apr 25 21:35:03 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ifdef.c  crc=47681  11932	Wed Nov  4 04:19:12 1992
XX***************
XX*** 1,10 ****
XX! /* Ifdef - remove #ifdefs		Author: Warren Toomey */
XX  
XX! /* Ifdef: Remove unwanted ifdefs from C code	      */
XX! /* Written by Warren Toomey - 1989		      */
XX! /* You may freely copy or give away this source as    */
XX! /* Long as this notice remains intact.		      */
XX! /* 9/16/89 - Added usage() before getopt() - meb      */
XX  
XX  #include <sys/types.h>
XX  #include <string.h>
XX--- 1,16 ----
XX! /* ifdef - remove #ifdefs		Author: Warren Toomey */
XX  
XX! /* Copyright 1989 by Warren Toomey	wkt@cs.adfa.oz.au[@uunet.uu.net]
XX!  *
XX!  * You may freely copy or distribute this code as long as this notice
XX!  * remains intact.
XX!  *
XX!  * You may modify this code, as long as this notice remains intact, and
XX!  * you add another notice indicating that the code has been modified.
XX!  *
XX!  * You may NOT sell this code or in any way profit from this code without
XX!  * prior agreement from the author.
XX!  */
XX  
XX  #include <sys/types.h>
XX  #include <string.h>
XX***************
XX*** 16,22 ****
XX  /* Types of symbols */
XX  #define DEF	  1		/* Symbol is defined    */
XX  #define UNDEF	  2		/* Symbol isn't defined */
XX! #define IGN	  3		/* Ignore this symbol unless defined       */
XX  
XX  /* Redef mode values */
XX  #define MUTABLE   1		/* Symbol can change defined <-> undefined */
XX--- 22,28 ----
XX  /* Types of symbols */
XX  #define DEF	  1		/* Symbol is defined    */
XX  #define UNDEF	  2		/* Symbol isn't defined */
XX! #define IGN	  3		/* Ignore this symbol unless defined */
XX  
XX  /* Redef mode values */
XX  #define MUTABLE   1		/* Symbol can change defined <-> undefined */
XX***************
XX*** 42,52 ****
XX  int line = 1;			/* Current line number        */
XX  int table = 0;			/* Don't normally want a table */
XX  
XX  char fgetarg(stream, cbuf)	/* Get next arg from file into cbuf, */
XX  FILE *stream;			/* returning the character that      */
XX! char *cbuf;			/* terminated it. Cbuf returns NULL  */
XX  {				/* if no arg. EOF is returned if no  */
XX!   char ch;			/* args left in file.                */
XX    int i;
XX  
XX    i = 0;
XX--- 48,79 ----
XX  int line = 1;			/* Current line number        */
XX  int table = 0;			/* Don't normally want a table */
XX  
XX+ extern int optind;
XX+ extern char *optarg;
XX+ 
XX+ /* Prototypes. */
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(char fgetarg, (FILE *stream, char *cbuf));
XX+ _PROTOTYPE(int find, (char *symd));
XX+ _PROTOTYPE(void defit, (char *sym, int redef, int typed));
XX+ _PROTOTYPE(void stop, (void));
XX+ _PROTOTYPE(void gotoeoln, (void));
XX+ _PROTOTYPE(void prteoln, (void));
XX+ _PROTOTYPE(void printtable, (void));
XX+ _PROTOTYPE(char getendif, (void));
XX+ _PROTOTYPE(void gettable, (void));
XX+ _PROTOTYPE(void parse, (void));
XX+ _PROTOTYPE(void usage, (void));
XX+ 
XX+ #ifdef __STDC__
XX+ char fgetarg ( FILE *stream , char *cbuf )
XX+ #else
XX  char fgetarg(stream, cbuf)	/* Get next arg from file into cbuf, */
XX  FILE *stream;			/* returning the character that      */
XX! char *cbuf;			/* terminated it. Cbuf returns 0     */
XX! #endif
XX  {				/* if no arg. EOF is returned if no  */
XX!   int ch;			/* args left in file.                */
XX    int i;
XX  
XX    i = 0;
XX***************
XX*** 54,80 ****
XX  
XX    while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n'))
XX  	if (ch == '\n') return(ch);	/* Bypass leading */
XX!   /* Whitespace     */
XX    if (feof(stream)) return(EOF);
XX  
XX    cbuf[i++] = ch;
XX  
XX    while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n'))
XX! 	cbuf[i++] = ch;		/* Get the argument */
XX  
XX    cbuf[i] = 0;
XX    return(ch);
XX  }
XX  
XX  
XX! find(sym)
XX  char *sym;
XX  {				/* Return DEF if defined else UNDEF */
XX-   char found = 0;		/* IGN if symbol is ignored  */
XX-   /* 0 if not in the list */
XX  
XX    deftemp = defptr;
XX!   while (deftemp) {		/* Search for the symbol */
XX  	if (!strcmp(deftemp->symbol, sym))
XX  		return(deftemp->type);	/* Setting up the type */
XX  	deftemp = deftemp->next;
XX--- 81,109 ----
XX  
XX    while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n'))
XX  	if (ch == '\n') return(ch);	/* Bypass leading */
XX! 					/* Whitespace     */
XX    if (feof(stream)) return(EOF);
XX  
XX    cbuf[i++] = ch;
XX  
XX    while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n'))
XX! 	cbuf[i++] = ch;			/* Get the argument */
XX  
XX    cbuf[i] = 0;
XX    return(ch);
XX  }
XX  
XX  
XX! #ifdef __STDC__
XX! int find ( char *sym )
XX! #else
XX! int find(sym)
XX  char *sym;
XX+ #endif
XX  {				/* Return DEF if defined else UNDEF */
XX  
XX    deftemp = defptr;
XX!   while (deftemp) {			/* Search for the symbol */
XX  	if (!strcmp(deftemp->symbol, sym))
XX  		return(deftemp->type);	/* Setting up the type */
XX  	deftemp = deftemp->next;
XX***************
XX*** 88,97 ****
XX  #define Undefine(x,y)	defit(x,y,UNDEF)
XX  #define Ignore(x,y)	defit(x,y,IGN)
XX  
XX! defit(sym, redef, type)		/* Add symbol to the define list */
XX  char *sym;
XX  char redef;			/* Mode: MUTABLE etc      */
XX  char type;			/* Type: DEF, UNDEF, IGN  */
XX  {
XX    struct DEFINE *temp;
XX    char c;
XX--- 117,130 ----
XX  #define Undefine(x,y)	defit(x,y,UNDEF)
XX  #define Ignore(x,y)	defit(x,y,IGN)
XX  
XX! #ifdef __STDC__
XX! void defit ( char *sym , int redef , int type )
XX! #else
XX! void defit(sym, redef, type)	/* Add symbol to the define list */
XX  char *sym;
XX  char redef;			/* Mode: MUTABLE etc      */
XX  char type;			/* Type: DEF, UNDEF, IGN  */
XX+ #endif
XX  {
XX    struct DEFINE *temp;
XX    char c;
XX***************
XX*** 106,150 ****
XX  		deftemp->redef = redef;
XX  	}
XX    } else {			/* We must create a struct & add it */
XX! 	/* Malloc room for the struct */
XX! 	if ((temp = (struct DEFINE *) malloc(sizeof(struct DEFINE))) == NULL) {
XX! 		fprintf(stderr, "ifdef: could not malloc\n");
XX  		exit(1);
XX  	}
XX  
XX! 	/* Malloc room for symbol */
XX! 	if ((temp->symbol = (char *) malloc(strlen(sym) + 1)) == NULL) {
XX! 		fprintf(stderr, "ifdef: could not malloc\n");
XX  		exit(1);
XX  	}
XX! 	strcpy(temp->symbol, sym);	/* Copy symbol into struct      */
XX! 	temp->redef = redef;	/* and set its redef mode too   */
XX! 	temp->type = type;	/* as well as making it defined */
XX  
XX  
XX! 	/* Now add to the SLL */
XX! 	if (defptr == NULL)	/* If first node set  */
XX! 		defptr = temp;	/* the pointers to it */
XX  	else
XX  		defend->next = temp;	/* else add it to the */
XX! 	defend = temp;		/* end of the list.   */
XX    }
XX  }
XX  
XX  
XX  
XX! stop()
XX  {				/* Stop: Tidy up at EOF */
XX    if (table) printtable();
XX!   fclose(zin);
XX    exit(0);
XX  }
XX  
XX! #define Goto	{ line++; if (ch!='\n') gotoeoln(zin); }
XX! #define Print	{ line++; if (ch!='\n')  prteoln(zin); }
XX  
XX! gotoeoln(file)			/* Go to the end of the line */
XX! FILE *file;
XX  {
XX    int ch;
XX    while ((ch = fgetc(zin)) != '\n')
XX--- 139,190 ----
XX  		deftemp->redef = redef;
XX  	}
XX    } else {			/* We must create a struct & add it */
XX! 				/* Malloc room for the struct */
XX! 	if ((temp = (struct DEFINE *)malloc(sizeof(struct DEFINE))) == NULL) {
XX! 		(void)fprintf(stderr, "ifdef: could not malloc\n");
XX  		exit(1);
XX  	}
XX  
XX! 					/* Malloc room for symbol */
XX! 	if ((temp->symbol = (char *)malloc(strlen(sym) + 1)) == NULL) {
XX! 		(void)fprintf(stderr, "ifdef: could not malloc\n");
XX  		exit(1);
XX  	}
XX! 	(void)strcpy(temp->symbol, sym); /* Copy symbol into struct      */
XX! 	temp->redef = redef;		/* and set its redef mode too   */
XX! 	temp->type = type;		/* as well as making it defined */
XX  
XX  
XX! 					/* Now add to the SLL */
XX! 	if (defptr == NULL)		/* If first node set  */
XX! 		defptr = temp;		/* the pointers to it */
XX  	else
XX  		defend->next = temp;	/* else add it to the */
XX! 	defend = temp;			/* end of the list.   */
XX    }
XX  }
XX  
XX  
XX  
XX! #ifdef __STDC__
XX! void stop ( void )
XX! #else
XX! void stop()
XX! #endif
XX  {				/* Stop: Tidy up at EOF */
XX    if (table) printtable();
XX!   (void)fclose(zin);
XX    exit(0);
XX  }
XX  
XX! #define Goto	{ line++; if (ch!='\n') gotoeoln(); }
XX! #define Print	{ line++; if (ch!='\n') prteoln();  }
XX  
XX! #ifdef __STDC__
XX! void gotoeoln ( void )
XX! #else
XX! void gotoeoln()			/* Go to the end of the line */
XX! #endif
XX  {
XX    int ch;
XX    while ((ch = fgetc(zin)) != '\n')
XX***************
XX*** 152,298 ****
XX  }
XX  
XX  
XX! prteoln(file)			/* Print to the end of the line */
XX! FILE *file;
XX  {
XX    int ch;
XX    while ((ch = fgetc(zin)) != '\n')
XX  	if (ch == EOF)
XX  		stop();
XX  	else
XX! 		putchar(ch);
XX!   putchar('\n');
XX  }
XX  
XX  
XX! printtable()
XX! {				/* Print the defines in the SLL */
XX    struct DEFINE *temp;
XX  
XX!   printf("Defined\n\n");
XX  
XX    temp = defptr;
XX    while (temp) {
XX! 	if (temp->type == DEF) printf("%s\n", temp->symbol);
XX  	temp = temp->next;
XX    }
XX  
XX!   printf("\n\nUndefined\n\n");
XX  
XX    temp = defptr;
XX    while (temp) {
XX! 	if (temp->type == UNDEF) printf("%s\n", temp->symbol);
XX  	temp = temp->next;
XX    }
XX  }
XX  
XX! getendif()
XX  {				/* Find matching endif when ignoring */
XX    char word[80];		/* Buffer for symbols */
XX    int ch;
XX!   int skip;			/* Number of skipped #ifdefs		 */
XX  
XX    skip = 1;
XX  
XX    while (1) {
XX! 	/* Scan through the file looking for starting lines */
XX  	if ((ch = fgetc(zin)) == EOF)
XX  		stop();		/* Get first char on the line */
XX  	if (ch != '#') {	/* If not a # ignore line     */
XX! 		putchar(ch);
XX  		Print;
XX  		continue;
XX  	}
XX! 	ch = fgetarg(zin, word);/* Get the word after the # */
XX  
XX! 	if (!strcmp(word, "ifdef")) skip++;	/* Keep track of ifdefs & */
XX  	if (!strcmp(word, "endif")) skip--;	/* endifs		  */
XX  
XX! 	printf("#%s%c", word, ch);	/* Print the line out 	  */
XX  	Print;
XX! 	if (!skip) return('\n');/* If matching endif, return */
XX    }
XX  }
XX  
XX  
XX! gettable()
XX  {
XX- /* Get & print a table of defines etc.  */
XX  
XX    char word[80];		/* Buffer for symbols */
XX    int ch;
XX-   int proc;			/* Should we be processing this bit?    */
XX-   int skip;			/* Number of skipped #ifdefs		 */
XX  
XX-   proc = 1;
XX-   skip = 0;
XX- 
XX    while (1) {
XX! 	/* Scan through the file looking for starting lines */
XX  	if ((ch = fgetc(zin)) == EOF)
XX  		stop();		/* Get first char on the line */
XX  	if (ch != '#') {	/* If not a # ignore line     */
XX  		Goto;
XX  		continue;
XX  	}
XX! 	ch = fgetarg(zin, word);/* Get the word after the # */
XX  
XX! 	if (!strcmp(word, "define") && proc) {	/* Define: Define the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto   */
XX! 		Define(word, MUTABLE);	/* the end of line    */
XX  		Goto;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "undef") && proc) {	/* Undef: Undefine the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto    */
XX  		Undefine(word, MUTABLE);	/* the end of line     */
XX  		Goto;
XX  		continue;
XX! 	}
XX! 	if (!strcmp(word, "ifdef")) {	/* Ifdef:            */
XX! 		if (!proc)	/* If not processing */
XX! 			skip++;	/* skip it           */
XX! 		else {
XX! 			ch = fgetarg(zin, word);	/* Get the symbol */
XX! 			if (find(word) != DEF) {
XX! 				Undefine(word, MUTABLE);	/* undefine it */
XX! 				proc = 0;	/* & stop processing */
XX! 			}
XX! 		}
XX  		Goto;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "ifndef")) {	/* Ifndef:	  */
XX! 		if (!proc)	/* If not processing */
XX! 			skip++;	/* skip the line     */
XX! 		else {
XX! 			ch = fgetarg(zin, word);	/* Get the symbol */
XX! 			if (find(word) == DEF)	/* If defined, stop */
XX! 				proc = 0;	/* processing       */
XX! 		}
XX! 		Goto;
XX! 		continue;
XX! 	}
XX! 	if (!strcmp(word, "else") && !skip) {	/* Else: Flip processing */
XX! 		proc = !proc;
XX! 		Goto;
XX! 		continue;
XX! 	}
XX! 	if (!strcmp(word, "endif")) {	/* Endif: If no skipped */
XX! 		if (!skip)	/* on, else decrement the */
XX! 			proc = 1;	/* number of skips        */
XX! 		else
XX! 			skip--;
XX! 		Goto;
XX! 		continue;
XX! 	}
XX! 	Goto;			/* else ignore the line */
XX    }
XX  }
XX  
XX  
XX  
XX! parse()
XX  {				/* Parse & remove ifdefs from C source */
XX    char word[80];		/* Buffer for symbols */
XX    int ch;
XX--- 192,322 ----
XX  }
XX  
XX  
XX! #ifdef __STDC__
XX! void prteoln ( void )
XX! #else
XX! void prteoln()			/* Print to the end of the line */
XX! #endif
XX  {
XX    int ch;
XX    while ((ch = fgetc(zin)) != '\n')
XX  	if (ch == EOF)
XX  		stop();
XX  	else
XX! 		(void)putchar(ch);
XX!   (void)putchar('\n');
XX  }
XX  
XX  
XX! #ifdef __STDC__
XX! void printtable ( void )
XX! #else
XX! void printtable()		/* Print the defines in the SLL */
XX! #endif
XX! {
XX    struct DEFINE *temp;
XX  
XX!   (void)printf("Defined\n\n");
XX  
XX    temp = defptr;
XX    while (temp) {
XX! 	if (temp->type == DEF) (void)printf("%s\n", temp->symbol);
XX  	temp = temp->next;
XX    }
XX  
XX!   (void)printf("\n\nUndefined\n\n");
XX  
XX    temp = defptr;
XX    while (temp) {
XX! 	if (temp->type == UNDEF) (void)printf("%s\n", temp->symbol);
XX  	temp = temp->next;
XX    }
XX  }
XX  
XX! #ifdef __STDC__
XX! char getendif ( void )
XX! #else
XX! char getendif()
XX! #endif
XX  {				/* Find matching endif when ignoring */
XX    char word[80];		/* Buffer for symbols */
XX    int ch;
XX!   int skip;			/* Number of skipped #ifdefs */
XX  
XX    skip = 1;
XX  
XX    while (1) {
XX! 			/* Scan through the file looking for starting lines */
XX  	if ((ch = fgetc(zin)) == EOF)
XX  		stop();		/* Get first char on the line */
XX  	if (ch != '#') {	/* If not a # ignore line     */
XX! 		(void)putchar(ch);
XX  		Print;
XX  		continue;
XX  	}
XX! 	ch = fgetarg(zin, word);	/* Get the word after the # */
XX  
XX! 	if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) skip++;
XX! 						/* Keep track of ifdefs & */
XX  	if (!strcmp(word, "endif")) skip--;	/* endifs		  */
XX  
XX! 	(void)printf("#%s%c", word, ch);	/* Print the line out 	  */
XX  	Print;
XX! 	if (!skip) return('\n');	/* If matching endif, return */
XX    }
XX  }
XX  
XX  
XX! #ifdef __STDC__
XX! void gettable ( void )
XX! #else
XX! void gettable()			/* Get & print a table of defines etc.  */
XX! #endif
XX  {
XX  
XX    char word[80];		/* Buffer for symbols */
XX    int ch;
XX  
XX    while (1) {
XX! 			/* Scan through the file looking for starting lines */
XX  	if ((ch = fgetc(zin)) == EOF)
XX  		stop();		/* Get first char on the line */
XX  	if (ch != '#') {	/* If not a # ignore line     */
XX  		Goto;
XX  		continue;
XX  	}
XX! 	ch = fgetarg(zin, word);	/* Get the word after the # */
XX  
XX! 	if (!strcmp(word, "define")) {		/* Define: Define the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto   */
XX! 		Define(word, MUTABLE);		/* the end of line    */
XX  		Goto;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "undef")) {		/* Undef: Undefine the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto    */
XX  		Undefine(word, MUTABLE);	/* the end of line     */
XX  		Goto;
XX  		continue;
XX! 	}					/* Ifdef:            */
XX! 	if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) {
XX! 		ch = fgetarg(zin, word);	/* Get the symbol */
XX! 		if (find(word) != DEF)
XX! 			Undefine(word, MUTABLE);	/* undefine it */
XX  		Goto;
XX  		continue;
XX  	}
XX! 	Goto;				/* else ignore the line */
XX    }
XX  }
XX  
XX  
XX  
XX! #ifdef __STDC__
XX! void parse ( void )
XX! #else
XX! void parse()
XX! #endif
XX  {				/* Parse & remove ifdefs from C source */
XX    char word[80];		/* Buffer for symbols */
XX    int ch;
XX***************
XX*** 303,314 ****
XX    skip = 0;
XX  
XX    while (1) {
XX! 	/* Scan through the file looking for starting lines */
XX  	if ((ch = fgetc(zin)) == EOF)
XX  		stop();		/* Get first char on the line */
XX  	if (ch != '#')
XX  		if (proc) {	/* If not # and  we're processing */
XX! 			putchar(ch);	/* then print the line */
XX  			Print;
XX  			continue;
XX  		} else {
XX--- 327,338 ----
XX    skip = 0;
XX  
XX    while (1) {
XX! 			/* Scan through the file looking for starting lines */
XX  	if ((ch = fgetc(zin)) == EOF)
XX  		stop();		/* Get first char on the line */
XX  	if (ch != '#')
XX  		if (proc) {	/* If not # and  we're processing */
XX! 			(void)putchar(ch); /* then print the line */
XX  			Print;
XX  			continue;
XX  		} else {
XX***************
XX*** 316,353 ****
XX  			continue;
XX  		}
XX  
XX! 	ch = fgetarg(zin, word);/* Get the word after the # */
XX  
XX  	if (!strcmp(word, "define") && proc) {	/* Define: Define the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto   */
XX! 		Define(word, MUTABLE);	/* the end of line    */
XX! 		printf("#define %s%c", word, ch);
XX  		Print;
XX  		continue;
XX  	}
XX  	if (!strcmp(word, "undef") && proc) {	/* Undef: Undefine the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto    */
XX  		Undefine(word, MUTABLE);	/* the end of line     */
XX! 		printf("#undef %s%c", word, ch);
XX  		Print;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "ifdef")) {	/* Ifdef: */
XX! 		if (!proc)	/* If not processing */
XX! 			skip++;	/* skip it           */
XX  		else {
XX! 			ch = fgetarg(zin, word);	/* Get the symbol */
XX  			switch (find(word)) {
XX  			    case DEF:
XX  				break;
XX  			    case IGN:
XX! 				printf("#ifdef %s%c", word, ch);
XX  				Print;
XX! 				ch = getendif();	/* Get matching endif */
XX  				break;
XX! 				/* If symbol undefined */
XX  			    default:
XX! 				Undefine(word, MUTABLE);	/* undefine it */
XX  				proc = 0;	/* & stop processing */
XX  			}
XX  		}
XX--- 340,387 ----
XX  			continue;
XX  		}
XX  
XX! 	ch = fgetarg(zin, word);	/* Get the word after the # */
XX  
XX  	if (!strcmp(word, "define") && proc) {	/* Define: Define the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto   */
XX! 		Define(word, MUTABLE);		/* the end of line    */
XX! 		(void)printf("#define %s%c", word, ch);
XX  		Print;
XX  		continue;
XX  	}
XX  	if (!strcmp(word, "undef") && proc) {	/* Undef: Undefine the */
XX  		ch = fgetarg(zin, word);	/* symbol, and goto    */
XX  		Undefine(word, MUTABLE);	/* the end of line     */
XX! 		(void)printf("#undef %s%c", word, ch);
XX  		Print;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "if")) {	/* If: we cannot handle these */
XX! 		if (!proc)		/* at the moment, so just */
XX! 			skip++;		/* treat them as an ignored */
XX! 		else {			/* definition */
XX! 			(void)printf("#%s%c",word,ch);
XX! 			Print;
XX! 			ch = getendif();	/* Get matching endif */
XX! 			continue;
XX! 		     	}
XX! 	}
XX! 	if (!strcmp(word, "ifdef")) {	/* Ifdef:	     */
XX! 		if (!proc)		/* If not processing */
XX! 			skip++;		/* skip it           */
XX  		else {
XX! 			ch = fgetarg(zin, word); /* Get the symbol */
XX  			switch (find(word)) {
XX  			    case DEF:
XX  				break;
XX  			    case IGN:
XX! 				(void)printf("#ifdef %s%c", word, ch);
XX  				Print;
XX! 				ch = getendif(); /* Get matching endif */
XX  				break;
XX! 						/* If symbol undefined */
XX  			    default:
XX! 				Undefine(word, MUTABLE); /* undefine it */
XX  				proc = 0;	/* & stop processing */
XX  			}
XX  		}
XX***************
XX*** 359,373 ****
XX  		if (!proc)	/* If not processing */
XX  			skip++;	/* skip the line     */
XX  		else {
XX! 			ch = fgetarg(zin, word);	/* Get the symbol */
XX  			switch (find(word)) {	/* If defined, stop */
XX  			    case DEF:
XX  				proc = 0;	/* processing       */
XX  				break;
XX  			    case IGN:
XX! 				printf("#ifdef %s%c", word, ch);
XX  				Print;
XX! 				ch = getendif();	/* Get matching endif */
XX  				break;
XX  			}
XX  		}
XX--- 393,407 ----
XX  		if (!proc)	/* If not processing */
XX  			skip++;	/* skip the line     */
XX  		else {
XX! 			ch = fgetarg(zin, word); /* Get the symbol */
XX  			switch (find(word)) {	/* If defined, stop */
XX  			    case DEF:
XX  				proc = 0;	/* processing       */
XX  				break;
XX  			    case IGN:
XX! 				(void)printf("#ifdef %s%c", word, ch);
XX  				Print;
XX! 				ch = getendif(); /* Get matching endif */
XX  				break;
XX  			}
XX  		}
XX***************
XX*** 379,397 ****
XX  		Goto;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "endif")) {	/* Endif: If no skipped   *//* i
XX! 					 * fdefs turn processing */
XX! 		if (!skip)	/* on, else decrement the */
XX  			proc = 1;	/* number of skips        */
XX  		else
XX  			skip--;
XX  		Goto;
XX  		continue;
XX  	}
XX  	if (proc) {
XX! 		/* The word fails all of the above tests, so if we're
XX! 		 * processing, print the line. */
XX! 		printf("#%s%c", word, ch);
XX  		Print;
XX  	} else
XX  		Goto;
XX--- 413,431 ----
XX  		Goto;
XX  		continue;
XX  	}
XX! 	if (!strcmp(word, "endif")) {	/* Endif: If no skipped   */
XX! 					/* ifdefs turn processing */
XX! 		if (!skip)		/* on, else decrement the */
XX  			proc = 1;	/* number of skips        */
XX  		else
XX  			skip--;
XX  		Goto;
XX  		continue;
XX  	}
XX+ 		/* The word fails all of the above tests, so if we're */
XX+ 		/* processing, print the line. */
XX  	if (proc) {
XX! 		(void)printf("#%s%c", word, ch);
XX  		Print;
XX  	} else
XX  		Goto;
XX***************
XX*** 399,418 ****
XX  }
XX  
XX  
XX! usage()
XX  {
XX!   fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n");
XX    exit(0);
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX-   extern int optind;
XX-   extern char *optarg;
XX- 
XX    char sym[80];			/* Temp symbol storage */
XX    int c;
XX  
XX--- 433,457 ----
XX  }
XX  
XX  
XX! #ifdef __STDC__
XX! void usage ( void )
XX! #else
XX! void usage()
XX! #endif
XX  {
XX!   (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n");
XX    exit(0);
XX  }
XX  
XX  
XX! #ifdef __STDC__
XX! int main(int argc , char *argv [])
XX! #else
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX+ #endif
XX  {
XX    char sym[80];			/* Temp symbol storage */
XX    int c;
XX  
XX***************
XX*** 424,445 ****
XX  		break;
XX  
XX  	    case 'd':
XX! 		strcpy(sym, optarg);
XX  		Define(sym, MUTABLE);
XX  		break;
XX  
XX  	    case 'D':
XX! 		strcpy(sym, optarg);
XX  		Define(sym, IMMUTABLE);
XX  		break;
XX  
XX  	    case 'U':
XX! 		strcpy(sym, optarg);
XX  		Undefine(sym, IMMUTABLE);
XX  		break;
XX  
XX  	    case 'I':
XX! 		strcpy(sym, optarg);
XX  		Ignore(sym, IMMUTABLE);
XX  		break;
XX  
XX--- 463,484 ----
XX  		break;
XX  
XX  	    case 'd':
XX! 		(void)strcpy(sym, optarg);
XX  		Define(sym, MUTABLE);
XX  		break;
XX  
XX  	    case 'D':
XX! 		(void)strcpy(sym, optarg);
XX  		Define(sym, IMMUTABLE);
XX  		break;
XX  
XX  	    case 'U':
XX! 		(void)strcpy(sym, optarg);
XX  		Undefine(sym, IMMUTABLE);
XX  		break;
XX  
XX  	    case 'I':
XX! 		(void)strcpy(sym, optarg);
XX  		Ignore(sym, IMMUTABLE);
XX  		break;
XX  
XX***************
XX*** 447,455 ****
XX  	}
XX    }
XX  
XX!   zin = stdin;
XX!   if (*argv[argc - 1] != '-') {	/* If a C file is named *//* Open
XX! 				 * stdin with it   */
XX  	if ((zin = fopen(argv[argc - 1], "r")) == NULL) {
XX  		perror("ifdef");
XX  		exit(1);
XX--- 486,495 ----
XX  	}
XX    }
XX  
XX!   zin = stdin;		/* If a C file is named */
XX! 			/* Open stdin with it */
XX!   if (*argv[argc - 1] != '-') {
XX! 	(void)fclose(zin);
XX  	if ((zin = fopen(argv[argc - 1], "r")) == NULL) {
XX  		perror("ifdef");
XX  		exit(1);
XX***************
XX*** 459,462 ****
XX--- 499,503 ----
XX  	gettable();		/* Either generate a table or    */
XX    else
XX  	parse();		/* parse & replace with the file */
XX+   return(0);
XX  }
X/
Xecho x - inodes.c.d
Xsed '/^X/s///' > inodes.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/inodes.c  crc=29823   6249	Sun Apr 25 21:35:03 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/inodes.c  crc=46107   6586	Wed Nov  4 04:19:13 1992
XX***************
XX*** 1,12 ****
XX  /* inodes - print inode characteristics		Author: Johan W. Stevenson */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <stdio.h>
XX  
XX  #define	NAMSIZ	256
XX! #define major(x) (x>>8) & 0377
XX! #define minor(x) x&0377
XX  
XX  struct linkbuf {
XX    struct linkbuf *l_nxt;
XX--- 1,17 ----
XX  /* inodes - print inode characteristics		Author: Johan W. Stevenson */
XX  
XX+ /* Copyright 1984 by Johan W. Stevenson. */
XX+ 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define	NAMSIZ	256
XX! #define major(dev)	(((dev) >> 8) & 0xFF)
XX! #define minor(dev)	((dev) & 0xFF)
XX  
XX  struct linkbuf {
XX    struct linkbuf *l_nxt;
XX***************
XX*** 17,27 ****
XX  
XX  char line[NAMSIZ];
XX  struct stat statbuf;
XX! struct linkbuf *lhead = (struct linkbuf *) NULL;
XX  
XX! extern char *malloc();
XX  
XX! main()
XX  {
XX    while (gets(line)) {
XX  
XX--- 22,38 ----
XX  
XX  char line[NAMSIZ];
XX  struct stat statbuf;
XX! struct linkbuf *lhead = NULL;
XX  
XX! _PROTOTYPE(int main, (void));
XX! _PROTOTYPE(void dir, (void));
XX! _PROTOTYPE(void dev, (int c));
XX! _PROTOTYPE(void reg, (void));
XX! _PROTOTYPE(void lnk, (void));
XX! _PROTOTYPE(void sock, (void));
XX! _PROTOTYPE(int crc, (void));
XX  
XX! int main()
XX  {
XX    while (gets(line)) {
XX  
XX***************
XX*** 49,58 ****
XX  		continue;
XX  	}
XX    }
XX!   exit(0);
XX  }
XX  
XX! dir()
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX--- 60,69 ----
XX  		continue;
XX  	}
XX    }
XX!   return(0);
XX  }
XX  
XX! void dir()
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX***************
XX*** 66,72 ****
XX  	);
XX  }
XX  
XX! dev(c)
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX--- 77,84 ----
XX  	);
XX  }
XX  
XX! void dev(c)
XX! int c;
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX***************
XX*** 83,89 ****
XX  	);
XX  }
XX  
XX! reg()
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX--- 95,101 ----
XX  	);
XX  }
XX  
XX! void reg()
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX***************
XX*** 122,141 ****
XX  }
XX  
XX  #ifdef S_IFLNK
XX! lnk()
XX  {
XX    register struct stat *p = &statbuf;
XX    char buf[NAMSIZ];
XX    register i;
XX  
XX!   i = readlink(line, buf, sizeof(buf));
XX    if (i < 0) {
XX  	fprintf(stderr, "cannot readlink %s\n", line);
XX  	return;
XX    }
XX!   buf[i] = 0;
XX    printf(
XX!          "l %04o %2d %2d     X      X %s -> %s\n",
XX           p->st_mode & 07777,
XX           p->st_uid,
XX           p->st_gid,
XX--- 134,153 ----
XX  }
XX  
XX  #ifdef S_IFLNK
XX! void lnk()
XX  {
XX    register struct stat *p = &statbuf;
XX    char buf[NAMSIZ];
XX    register i;
XX  
XX!   i = readlink(line, buf, sizeof(buf)-1);
XX    if (i < 0) {
XX  	fprintf(stderr, "cannot readlink %s\n", line);
XX  	return;
XX    }
XX!   buf[i] = '\0';
XX    printf(
XX!          "l m=%04o  uid=%2d  gid=%2d %s -> %s\n",
XX           p->st_mode & 07777,
XX           p->st_uid,
XX           p->st_gid,
XX***************
XX*** 147,153 ****
XX  #endif
XX  
XX  #ifdef S_IFSOCK
XX! sock()
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX--- 159,165 ----
XX  #endif
XX  
XX  #ifdef S_IFSOCK
XX! void sock()
XX  {
XX    register struct stat *p = &statbuf;
XX  
XX***************
XX*** 211,220 ****
XX  
XX  #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
XX  
XX! crc()
XX  {
XX    register unsigned short crc;
XX!   register i, c;
XX    register FILE *f;
XX  
XX    if ((f = fopen(line, "r")) == NULL) {
XX--- 223,232 ----
XX  
XX  #define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
XX  
XX! int crc()
XX  {
XX    register unsigned short crc;
XX!   register c;
XX    register FILE *f;
XX  
XX    if ((f = fopen(line, "r")) == NULL) {
X/
Xecho x - kill.c.d
Xsed '/^X/s///' > kill.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/kill.c  crc=27774    601	Sun Apr 25 21:35:03 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/kill.c  crc=29018    747	Sun Jan 17 20:52:42 1993
XX***************
XX*** 1,11 ****
XX  /* kill - send a signal to a process	Author: Adri Koppes  */
XX  
XX  #include <sys/types.h>
XX  #include <signal.h>
XX  
XX! extern char *itoa();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 1,16 ----
XX  /* kill - send a signal to a process	Author: Adri Koppes  */
XX  
XX  #include <sys/types.h>
XX+ #include <errno.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <stdio.h>
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 23,37 ****
XX  	proc = atoi(*argv);
XX  	if (!proc && strcmp(*argv, "0")) usage();
XX  	if (kill(proc, signal)) {
XX! 		prints("Kill: %s no such process\n", itoa(proc));
XX  		exit(1);
XX  	}
XX    }
XX!   exit(0);
XX  }
XX  
XX! usage()
XX  {
XX!   prints("Usage: kill [-sig] pid\n");
XX    exit(1);
XX  }
XX--- 28,42 ----
XX  	proc = atoi(*argv);
XX  	if (!proc && strcmp(*argv, "0")) usage();
XX  	if (kill(proc, signal)) {
XX! 		printf("kill: %d: %s\n", proc, strerror(errno));
XX  		exit(1);
XX  	}
XX    }
XX!   return(0);
XX  }
XX  
XX! void usage()
XX  {
XX!   printf("Usage: kill [-sig] pid\n");
XX    exit(1);
XX  }
X/
Xecho x - last.c.d
Xsed '/^X/s///' > last.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/last.c  crc=17369   9191	Sun Apr 25 21:35:04 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/last.c  crc=46500   9660	Wed Nov  4 07:51:32 1992
XX***************
XX*** 68,74 ****
XX  } logout;
XX  
XX  
XX! static char *Version = "@(#) LAST 1.6 (01/09/90)";
XX  
XX  
XX  /* command-line option flags */
XX--- 68,74 ----
XX  } logout;
XX  
XX  
XX! static char *Version = "@(#) LAST 1.7 (10/24/92)";
XX  
XX  
XX  /* command-line option flags */
XX***************
XX*** 84,89 ****
XX--- 84,97 ----
XX  logout *first_link = NULL;	/* List of logout times */
XX  int interrupt = FALSE;		/* If sigint or sigquit occurs */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void Sigint, (int sig));
XX+ _PROTOTYPE(void Sigquit, (int sig));
XX+ _PROTOTYPE(void usage, (void));
XX+ _PROTOTYPE(void Process, (struct utmp *wtmp));
XX+ _PROTOTYPE(int Print_Record, (struct utmp *wtmp));
XX+ _PROTOTYPE(void Print_Duration, (long from, long to));
XX+ _PROTOTYPE(void Record_Logout_Time, (struct utmp *wtmp));
XX  
XX  /* Sigint() and Sigquit() Flag occurrence of an interrupt. */
XX  void Sigint(sig)
XX***************
XX*** 151,164 ****
XX   *
XX   *	   terry     tty0    Thu May 26 21:19   still logged in
XX   */
XX! Process(wtmp)
XX  struct utmp *wtmp;
XX  {
XX    logout *link;
XX    logout *next_link;
XX  
XX    /* suppress the job number on an "ftp" line */
XX!   if (!strncmp(wtmp->ut_line, "ftp", 3)) strncpy(wtmp->ut_line, "ftp", 8);
XX  
XX    if (!strcmp(wtmp->ut_line, "~")) {
XX  	/* A reboot or shutdown record  */
XX--- 159,172 ----
XX   *
XX   *	   terry     tty0    Thu May 26 21:19   still logged in
XX   */
XX! void Process(wtmp)
XX  struct utmp *wtmp;
XX  {
XX    logout *link;
XX    logout *next_link;
XX  
XX    /* suppress the job number on an "ftp" line */
XX!   if (!strncmp(wtmp->ut_line, "ftp", (size_t)3)) strncpy(wtmp->ut_line, "ftp", (size_t)8);
XX  
XX    if (!strcmp(wtmp->ut_line, "~")) {
XX  	/* A reboot or shutdown record  */
XX***************
XX*** 184,190 ****
XX    } else {
XX  	/* A login record */
XX  	for (link = first_link; link != NULL; link = link->next)
XX! 		if (!strncmp(link->line, wtmp->ut_line, 8)) {
XX  			/* found corresponding logout record */
XX  			if (Print_Record(wtmp)) {
XX  				printf("- %.5s ", ctime(&link->time) + 11);
XX--- 192,198 ----
XX    } else {
XX  	/* A login record */
XX  	for (link = first_link; link != NULL; link = link->next)
XX! 		if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {
XX  			/* found corresponding logout record */
XX  			if (Print_Record(wtmp)) {
XX  				printf("- %.5s ", ctime(&link->time) + 11);
XX***************
XX*** 211,217 ****
XX  /* Print_Record(wtmp) If the record was requested, then print out
XX   * the user name, terminal, host and time.
XX   */
XX! Print_Record(wtmp)
XX  struct utmp *wtmp;
XX  {
XX    int i;
XX--- 219,225 ----
XX  /* Print_Record(wtmp) If the record was requested, then print out
XX   * the user name, terminal, host and time.
XX   */
XX! int Print_Record(wtmp)
XX  struct utmp *wtmp;
XX  {
XX    int i;
XX***************
XX*** 221,227 ****
XX    if (count_limit && print_count == 0) exit(0);
XX  
XX    for (i = 0; i < arg_count; ++i)
XX! 	if (!strcmp(args[i], wtmp->ut_name) || !strcmp(args[i], wtmp->ut_line))
XX  		print_flag = TRUE;
XX  
XX    if (arg_count == 0 || print_flag) {
XX--- 229,236 ----
XX    if (count_limit && print_count == 0) exit(0);
XX  
XX    for (i = 0; i < arg_count; ++i)
XX! 	if (!strncmp(args[i], wtmp->ut_name, sizeof(wtmp->ut_name)) ||
XX! 	    !strncmp(args[i], wtmp->ut_line, sizeof(wtmp->ut_line)))
XX  		print_flag = TRUE;
XX  
XX    if (arg_count == 0 || print_flag) {
XX***************
XX*** 243,249 ****
XX  /* Print_Duration(from, to) Calculate and print the days and hh:mm between
XX   * the log-in and the log-out.
XX   */
XX! Print_Duration(from, to)
XX  long from;
XX  long to;
XX  {
XX--- 252,258 ----
XX  /* Print_Duration(from, to) Calculate and print the days and hh:mm between
XX   * the log-in and the log-out.
XX   */
XX! void Print_Duration(from, to)
XX  long from;
XX  long to;
XX  {
XX***************
XX*** 268,291 ****
XX  /* Record_Logout_Time(wtmp) A linked list of "last logout time" is kept.
XX   * Each element of the list is for one terminal.
XX   */
XX! Record_Logout_Time(wtmp)
XX  struct utmp *wtmp;
XX  {
XX    logout *link;
XX  
XX    /* see if the terminal is already in the list */
XX    for (link = first_link; link != NULL; link = link->next)
XX! 	if (!strncmp(link->line, wtmp->ut_line, 8)) {
XX  		link->time = wtmp->ut_time;
XX  		return;
XX  	}
XX    /* allocate a new logout record, for a tty not previously encountered */
XX    link = (logout *) malloc(sizeof(logout));
XX!   if (link == (logout *) NULL) {
XX  	fprintf(stderr, "last: malloc failure\n");
XX  	exit(1);
XX    }
XX!   strncpy(link->line, wtmp->ut_line, 8);
XX    link->time = wtmp->ut_time;
XX    link->next = first_link;
XX  
XX--- 277,300 ----
XX  /* Record_Logout_Time(wtmp) A linked list of "last logout time" is kept.
XX   * Each element of the list is for one terminal.
XX   */
XX! void Record_Logout_Time(wtmp)
XX  struct utmp *wtmp;
XX  {
XX    logout *link;
XX  
XX    /* see if the terminal is already in the list */
XX    for (link = first_link; link != NULL; link = link->next)
XX! 	if (!strncmp(link->line, wtmp->ut_line, (size_t)8)) {
XX  		link->time = wtmp->ut_time;
XX  		return;
XX  	}
XX    /* allocate a new logout record, for a tty not previously encountered */
XX    link = (logout *) malloc(sizeof(logout));
XX!   if (link == NULL) {
XX  	fprintf(stderr, "last: malloc failure\n");
XX  	exit(1);
XX    }
XX!   strncpy(link->line, wtmp->ut_line, (size_t)8);
XX    link->time = wtmp->ut_time;
XX    link->next = first_link;
XX  
XX***************
XX*** 293,299 ****
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 302,308 ----
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 326,332 ****
XX    arg_count = argc;
XX    args = argv;
XX  
XX!   if ((f = fopen(wtmp_file, "r")) == (FILE *) NULL) {
XX  	perror(wtmp_file);
XX  	exit(1);
XX    }
XX--- 335,341 ----
XX    arg_count = argc;
XX    args = argv;
XX  
XX!   if ((f = fopen(wtmp_file, "r")) == NULL) {
XX  	perror(wtmp_file);
XX  	exit(1);
XX    }
XX***************
XX*** 352,358 ****
XX  	fseek(f, size * sizeof(struct utmp), 0);
XX  
XX  
XX! 	if (fread(&wtmp_buffer[0], sizeof(struct utmp), wtmp_count, f)
XX  	    != wtmp_count) {
XX  		fprintf(stderr, "last: read error on wtmp file\n");
XX  		exit(1);
XX--- 361,367 ----
XX  	fseek(f, size * sizeof(struct utmp), 0);
XX  
XX  
XX! 	if (fread(&wtmp_buffer[0], sizeof(struct utmp), (size_t)wtmp_count, f)
XX  	    != wtmp_count) {
XX  		fprintf(stderr, "last: read error on wtmp file\n");
XX  		exit(1);
XX***************
XX*** 373,377 ****
XX    }				/* end while(size > 0) */
XX  
XX    printf("\nwtmp begins %.16s \n", ctime(&wtmp_buffer[0].ut_time));
XX!   exit(0);
XX  }
XX--- 382,386 ----
XX    }				/* end while(size > 0) */
XX  
XX    printf("\nwtmp begins %.16s \n", ctime(&wtmp_buffer[0].ut_time));
XX!   return(0);
XX  }
X/
Xecho x - leave.c.d
Xsed '/^X/s///' > leave.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/leave.c  crc=35436   4959	Sun Apr 25 21:35:04 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/leave.c  crc=02085   5255	Sun Jan 17 20:52:42 1993
XX***************
XX*** 1,5 ****
XX- /* leave - tell the user when to go home	Author: Terrence W. Holm */
XX  
XX  /* Usage:	leave [ [+] hhmm ]
XX   *
XX   * Author:	Terrence W. Holm
XX--- 1,5 ----
XX  
XX+ 
XX  /* Usage:	leave [ [+] hhmm ]
XX   *
XX   * Author:	Terrence W. Holm
XX***************
XX*** 15,20 ****
XX--- 15,23 ----
XX  #include <signal.h>
XX  #include <time.h>
XX  #include <utmp.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  
XX***************
XX*** 58,73 ****
XX  
XX  
XX  #ifdef _BSD
XX! long timezone;
XX  #else
XX! extern long timezone;
XX  #endif
XX  
XX  
XX- extern char *ttyname();
XX- extern char *cuserid();
XX- 
XX- 
XX  void Usage()
XX  {
XX     fprintf(stderr, "Usage: leave [[+]hhmm]\n");
XX--- 61,79 ----
XX  
XX  
XX  #ifdef _BSD
XX! time_t _timezone;
XX  #else
XX! #ifndef __STDC__
XX! #define _timezone timezone
XX  #endif
XX+ extern time_t _timezone;
XX+ #endif
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void Usage, (void));
XX+ _PROTOTYPE(void Get_Hour_Min, (char *when, int *hour, int *min));
XX+ _PROTOTYPE(int Still_Logged_On, (char *user, char *tty));
XX  
XX  void Usage()
XX  {
XX     fprintf(stderr, "Usage: leave [[+]hhmm]\n");
XX***************
XX*** 107,119 ****
XX    FILE *f;
XX    struct utmp login;
XX  
XX!   if ((f = fopen(UTMP, "r")) == (FILE *) NULL)
XX  	/* no login/logout records kept */
XX  	return(1);
XX  
XX!   while (fread(&login, sizeof(struct utmp), 1, f) == 1) {
XX! 	if (!strncmp(login.ut_line, tty, 8))
XX! 		if (!strncmp(login.ut_name, user, 8)) {
XX  			fclose(f);
XX  			return(1);
XX  		} else {
XX--- 113,125 ----
XX    FILE *f;
XX    struct utmp login;
XX  
XX!   if ((f = fopen(UTMP, "r")) == NULL)
XX  	/* no login/logout records kept */
XX  	return(1);
XX  
XX!   while (fread(&login, sizeof(struct utmp), (size_t)1, f) == 1) {
XX! 	if (!strncmp(login.ut_line, tty, (size_t)8))
XX! 		if (!strncmp(login.ut_name, user, (size_t)8)) {
XX  			fclose(f);
XX  			return(1);
XX  		} else {
XX***************
XX*** 126,146 ****
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    char when[STRING];
XX!   long now = time((time_t *)0);
XX!   long leave, delta;
XX    int hour, min;
XX    int pid, i;
XX!   char *user = cuserid( (char *) NULL);
XX    char *tty = ttyname(0) + 5;
XX  
XX    /* get the argument string "when" either from stdin, or argv */
XX    if (argc <= 1) {
XX  	printf("When do you have to leave? ");
XX  	if (fgets(when, STRING, stdin) == NULL || when[0] == '\n') exit(0);
XX    } else {
XX  	strcpy(when, argv[1]);
XX--- 132,153 ----
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    char when[STRING];
XX!   time_t now = time((time_t *)0);
XX!   time_t leave, delta;
XX    int hour, min;
XX    int pid, i;
XX!   char *user = cuserid( (char *)NULL);
XX    char *tty = ttyname(0) + 5;
XX  
XX    /* get the argument string "when" either from stdin, or argv */
XX    if (argc <= 1) {
XX  	printf("When do you have to leave? ");
XX+ 	fflush(stdout);
XX  	if (fgets(when, STRING, stdin) == NULL || when[0] == '\n') exit(0);
XX    } else {
XX  	strcpy(when, argv[1]);
XX***************
XX*** 148,165 ****
XX    }
XX  
XX    /* determine the leave time from the current time and "when" */
XX    if (when[0] == '+') {
XX  	Get_Hour_Min(&when[1], &hour, &min);
XX  	leave = now + hour * HOUR + min * MIN;
XX    } else {
XX  	/* user entered an absolute time */
XX  #ifdef _BSD
XX! 	timezone = -localtime(&now)->tm_gmtoff;
XX  #endif
XX  	Get_Hour_Min(&when[0], &hour, &min);
XX  	if (hour >= 1 && hour <= 12) {
XX  		/* 12-hour format: relative to previous midnight or noon */
XX! 		leave = now - (now - timezone) % HALF_DAY +
XX  			hour % 12 * HOUR + min * MIN;
XX  		if (leave < now - HOUR)
XX  			leave = leave + HALF_DAY;
XX--- 155,173 ----
XX    }
XX  
XX    /* determine the leave time from the current time and "when" */
XX+   tzset();
XX    if (when[0] == '+') {
XX  	Get_Hour_Min(&when[1], &hour, &min);
XX  	leave = now + hour * HOUR + min * MIN;
XX    } else {
XX  	/* user entered an absolute time */
XX  #ifdef _BSD
XX! 	_timezone = -localtime(&now)->tm_gmtoff;
XX  #endif
XX  	Get_Hour_Min(&when[0], &hour, &min);
XX  	if (hour >= 1 && hour <= 12) {
XX  		/* 12-hour format: relative to previous midnight or noon */
XX! 		leave = now - (now - _timezone) % HALF_DAY +
XX  			hour % 12 * HOUR + min * MIN;
XX  		if (leave < now - HOUR)
XX  			leave = leave + HALF_DAY;
XX***************
XX*** 169,175 ****
XX  		}
XX  	} else if (hour <= 24) {
XX  		/* 24-hour format: relative to previous midnight */
XX! 		leave = now - (now - timezone) % DAY +
XX  			hour * HOUR + min * MIN;
XX  		if (leave < now - HOUR)
XX  			leave = leave + DAY;
XX--- 177,183 ----
XX  		}
XX  	} else if (hour <= 24) {
XX  		/* 24-hour format: relative to previous midnight */
XX! 		leave = now - (now - _timezone) % DAY +
XX  			hour * HOUR + min * MIN;
XX  		if (leave < now - HOUR)
XX  			leave = leave + DAY;
XX***************
XX*** 202,207 ****
XX--- 210,216 ----
XX  	if (!Still_Logged_On(user, tty)) exit(0);
XX  
XX  	/* how much longer until the leave time? */
XX+ 	/* XXX - use difftime all over. */
XX  	delta = leave - time((time_t *)0);
XX  
XX  	/* which interval are we currently in? */
XX***************
XX*** 221,226 ****
XX  	/* Sleep until the next interval. For long periods, wake up
XX  	 * every hour to check if the user is still on (also required
XX  	 * because 16 bit ints don't allow long waits). */
XX! 	sleep((int) Min(delta + intervals[i], HOUR));
XX    }
XX  }
XX--- 230,235 ----
XX  	/* Sleep until the next interval. For long periods, wake up
XX  	 * every hour to check if the user is still on (also required
XX  	 * because 16 bit ints don't allow long waits). */
XX! 	sleep((unsigned) Min(delta + intervals[i], HOUR));
XX    }
XX  }
X/
Xecho x - ln.c.d
Xsed '/^X/s///' > ln.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ln.c  crc=32047   1095	Sun Apr 25 21:35:04 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ln.c  crc=54046   3299	Wed Nov  4 04:19:13 1992
XX***************
XX*** 1,64 ****
XX! /* ln - link a file		Author: Andy Tanenbaum */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  
XX- char name[256];
XX- struct stat stb;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   char *file1, *file2;
XX!   char *last_comp();
XX  
XX!   if (argc < 2 || argc > 3) usage();
XX!   if (access(argv[1], 0) < 0) {
XX! 	std_err("ln: cannot access ");
XX! 	std_err(argv[1]);
XX! 	std_err("\n");
XX! 	exit(1);
XX    }
XX-   if (stat(argv[1], &stb) >= 0 && (stb.st_mode & S_IFMT) == S_IFDIR) usage();
XX-   file1 = argv[1];
XX  
XX!   /* "ln file" means "ln file ." */
XX!   if (argc == 2)
XX! 	file2 = ".";
XX!   else
XX! 	file2 = argv[2];
XX  
XX  
XX  
XX    /* Check to see if target is a directory. */
XX!   if (stat(file2, &stb) >= 0 && (stb.st_mode & S_IFMT) == S_IFDIR) {
XX  	strcpy(name, file2);
XX  	strcat(name, "/");
XX! 	strcat(name, last_comp(file1));
XX  	file2 = name;
XX    }
XX!   if (link(file1, file2)) {
XX! 	std_err("ln: Can't link\n");
XX! 	exit(1);
XX    }
XX!   exit(0);
XX  }
XX  
XX! char *last_comp(s)
XX  char *s;
XX  {
XX  /* Return pointer to last component of string. */
XX!   int n;
XX!   n = strlen(s);
XX!   while (n--)
XX! 	if (*(s + n) == '/') return(s + n + 1);
XX    return(s);
XX  }
XX  
XX  
XX! usage()
XX  {
XX!   std_err("Usage: ln file1 [file2]\n");
XX    exit(1);
XX  }
XX--- 1,186 ----
XX! /* ln - Link files			Author: V. Archer */
XX  
XX+ /* Copyright 1991 by Vincent Archer
XX+  *	You may freely redistribute this software, in source or binary
XX+  *	form, provided that you do not alter this copyright mention in any
XX+  *	way.
XX+  */
XX+ 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX+ #include <errno.h>
XX+ #include <limits.h>
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX  
XX! /* Forward declaration. */
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void do_link, (char *file1, char *file2));
XX! _PROTOTYPE(char *basename, (char *s));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! 
XX! /* Global variables needed. */
XX! int sflag, cflag;
XX! int fflag, dflag, error;
XX! char name[PATH_MAX + 1];
XX! struct stat st;
XX! 
XX! 
XX! /* Main module. Only one option (-f) handled, so getopt() stuff not used.
XX!  * The non-Posix & old-Minix compatible "ln x" construct is allowed as an
XX!  * alias to "ln x ."
XX!  */
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   char *ap;
XX!   char *file;
XX  
XX!   argc--;
XX!   argv++;
XX!   while (argc && argv[0][0] == '-') {
XX! 	argc--;
XX! 	ap = *argv++;
XX! 	while (*++ap) {
XX! 		switch (*ap) {
XX! 		    case 'f':	fflag = 1;	break;
XX! #ifdef S_IFLNK
XX! 		    case 'c':
XX! 			cflag = 1;	/* Fall through to -s */
XX! 		    case 's':	sflag = 1;	break;
XX! #endif
XX! 		    default:	usage();
XX! 		}
XX! 	}
XX    }
XX  
XX!   switch (argc) {
XX!       default:	file = argv[--argc];	break;
XX!       case 1:
XX! #ifndef S_IFLNK
XX! 	file = ".";
XX! 	break;
XX! #else
XX! 	if (!cflag) {
XX! 		file = ".";
XX! 		break;
XX! 	}
XX  
XX+ 	/* Fall through to error. */
XX+ #endif
XX+       case 0:	usage();
XX+ }
XX  
XX+   if (
XX+ #ifdef S_IFLNK
XX+       !cflag &&
XX+ #endif
XX+       !stat(file, &st) && S_ISDIR(st.st_mode))
XX+ 	dflag = 1;
XX+   else if (argc > 1)
XX+ 	usage();
XX  
XX+   while (argc--) do_link(*argv++, file);
XX+   return(error);
XX+ }
XX+ 
XX+ 
XX+ /* Execute the linking between two files. Linking a directory will produce
XX+  * a warning, but will be allowed if you are super user. This is not a
XX+  * recommended practice, however...
XX+  */
XX+ void do_link(file1, file2)
XX+ char *file1, *file2;
XX+ {
XX+   if (!sflag) {
XX+ 	if (stat(file1, &st)) {
XX+ 		perror(file1);
XX+ 		error = 1;
XX+ 		return;
XX+ 	}
XX+ 	if (S_ISDIR(st.st_mode)) {
XX+ 		errno = EISDIR;
XX+ 		if (getuid() == 0) std_err("warning: ");
XX+ 		perror(file1);
XX+ 		if (getuid() != 0) {
XX+ 			error = 1;
XX+ 			return;
XX+ 		}
XX+ 	}
XX+   }
XX+ #ifdef S_IFLNK
XX+   /* Check to see if conditional symlink required. */
XX+   if (cflag) {
XX+ 	strcpy(name, " ");
XX+ 	strcat(name, file1);
XX+ 	file1 = name;
XX+   }
XX+ #endif
XX+ 
XX    /* Check to see if target is a directory. */
XX!   if (dflag) {
XX  	strcpy(name, file2);
XX  	strcat(name, "/");
XX! 	strcat(name, basename(file1));
XX  	file2 = name;
XX    }
XX!   if (
XX! #ifdef S_IFLNK
XX!       !lstat(file2, &st)
XX! #else
XX!       !stat(file2, &st)
XX! #endif
XX! 	) {
XX! 	if (!fflag) {
XX! 		errno = EEXIST;
XX! 		perror(file2);
XX! 		error = 1;
XX! 		return;
XX! 	}
XX! 	if (unlink(file2)) {
XX! 		perror(file2);
XX! 		error = 1;
XX! 		return;
XX! 	}
XX    }
XX!   if (
XX! #ifdef S_IFLNK
XX!       sflag && symlink(file1, file2) || !sflag && link(file1, file2)
XX! #else
XX!       link(file1, file2)
XX! #endif
XX! 	) {
XX! 	perror(file2);
XX! 	error = 1;
XX!   }
XX  }
XX  
XX! 
XX! char *basename(s)
XX  char *s;
XX  {
XX  /* Return pointer to last component of string. */
XX!   char *b;
XX! 
XX!   if (b = strrchr(s, '/')) return(b + 1);
XX    return(s);
XX  }
XX  
XX  
XX! /* (Extended) Posix command prototype. */
XX! void usage()
XX  {
XX! #ifdef S_IFLNK
XX!   std_err("Usage: ln [-fs] file... [target]\n");
XX!   std_err("       ln [-fc] conditional-link target\n");
XX! #else
XX!   std_err("Usage: ln [-f] file... [target]\n");
XX! #endif
XX    exit(1);
XX  }
X/
Xecho x - login.c.d
Xsed '/^X/s///' > login.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/login.c  crc=49175   8007	Sun Apr 25 21:35:05 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/login.c  crc=21420   8634	Sun Jan 17 20:52:43 1993
XX***************
XX*** 38,43 ****
XX--- 38,46 ----
XX   *
XX   * Andy Tanenbaum April 1990
XX   * - if /bin/sh cannot be located, try /usr/bin/sh
XX+  *
XX+  * Michael A. Temari	October 1990
XX+  *  - handle more than single digit tty devices
XX   */
XX  
XX  #include <sys/types.h>
XX***************
XX*** 49,59 ****
XX  #include <pwd.h>
XX  #include <unistd.h>
XX  #include <utmp.h>
XX  #include <stdio.h>
XX  
XX- #define DIGIT 			      3
XX  #define MOTD 		    "/etc/motd"
XX! #define TTY  		         "tty?"
XX  #define CONS 		         "tty0"
XX  
XX  static char *Version = "@(#) LOGIN 1.13 (02/10/90)";
XX--- 52,64 ----
XX  #include <pwd.h>
XX  #include <unistd.h>
XX  #include <utmp.h>
XX+ #include <stdlib.h>
XX+ #include <time.h>
XX+ #include <minix/minlib.h>
XX  #include <stdio.h>
XX  
XX  #define MOTD 		    "/etc/motd"
XX! #define TTY  		         "tty"
XX  #define CONS 		         "tty0"
XX  
XX  static char *Version = "@(#) LOGIN 1.13 (02/10/90)";
XX***************
XX*** 62,67 ****
XX--- 67,73 ----
XX  char logname[35];
XX  char home[64];
XX  char shell[64];
XX+ char minus_shell[1 + 64];
XX  char *env[] = {
XX    user,
XX    logname,
XX***************
XX*** 71,81 ****
XX    NULL
XX  };
XX  
XX! extern char *crypt();
XX! extern struct passwd *getpwnam();
XX! extern long time();
XX! extern long lseek();
XX! void Time_out();
XX  
XX  void wtmp(line, user)
XX  char *line;			/* tty device name */
XX--- 77,87 ----
XX    NULL
XX  };
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void wtmp, (char *line, char *user));
XX! _PROTOTYPE(void addlog, (char *nam, char *pwd, char *tty));
XX! _PROTOTYPE(void show_file, (char *nam));
XX! _PROTOTYPE(void Time_out, (int dummy));
XX  
XX  void wtmp(line, user)
XX  char *line;			/* tty device name */
XX***************
XX*** 87,93 ****
XX    register int fd;
XX    register char *sp;
XX    int lineno;
XX!   extern long time();
XX  
XX    /* Strip off the /dev part of the TTY name. */
XX    sp = strrchr(line, '/');
XX--- 93,99 ----
XX    register int fd;
XX    register char *sp;
XX    int lineno;
XX!   off_t lineoff;
XX  
XX    /* Strip off the /dev part of the TTY name. */
XX    sp = strrchr(line, '/');
XX***************
XX*** 105,113 ****
XX  	if (oldent.ut_pid == getpid()) break;
XX  	lineno++;
XX    }
XX!   lineno *= sizeof(struct utmp);
XX  
XX!   if (lseek(fd, (long) lineno, SEEK_SET) >= 0) {
XX  	read(fd, (char *) &oldent, sizeof(struct utmp));
XX    }
XX    close(fd);
XX--- 111,119 ----
XX  	if (oldent.ut_pid == getpid()) break;
XX  	lineno++;
XX    }
XX!   lineoff = lineno * (off_t) sizeof(struct utmp);
XX  
XX!   if (lseek(fd, lineoff, SEEK_SET) != (off_t)-1) {
XX  	read(fd, (char *) &oldent, sizeof(struct utmp));
XX    }
XX    close(fd);
XX***************
XX*** 131,144 ****
XX  
XX    /* Write a WTMP record. */
XX    if ((fd = open(WTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, 0L, SEEK_END) >= 0L) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX    }
XX    /* Rewrite the UTMP entry. */
XX    if ((fd = open(UTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, (long) lineno, SEEK_SET) >= 0) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX--- 137,150 ----
XX  
XX    /* Write a WTMP record. */
XX    if ((fd = open(WTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, (off_t)0, SEEK_END) != (off_t)-1) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX    }
XX    /* Rewrite the UTMP entry. */
XX    if ((fd = open(UTMP, O_WRONLY)) > 0) {
XX! 	if (lseek(fd, lineoff, SEEK_SET) != (off_t)-1) {
XX  		write(fd, (char *) &entry, sizeof(struct utmp));
XX  	}
XX  	close(fd);
XX***************
XX*** 162,168 ****
XX  
XX    if ((fd = open(BTMP, O_WRONLY)) < 0) return;
XX  
XX!   if (lseek(fd, 0L, SEEK_END) >= 0L) {
XX  	/* Append the entry to the btmp file. */
XX  	write(fd, (char *) &entry, sizeof(struct utmp));
XX    }
XX--- 168,174 ----
XX  
XX    if ((fd = open(BTMP, O_WRONLY)) < 0) return;
XX  
XX!   if (lseek(fd, (off_t)0, SEEK_END) != (off_t)-1) {
XX  	/* Append the entry to the btmp file. */
XX  	write(fd, (char *) &entry, sizeof(struct utmp));
XX    }
XX***************
XX*** 220,226 ****
XX  	strcpy(ttyname, CONS);	/* system console */
XX    else {
XX  	strcpy(ttyname, TTY);
XX! 	ttyname[DIGIT] = '0' + ttynr;
XX    }
XX  
XX    /* Get login name and passwd. */
XX--- 226,232 ----
XX  	strcpy(ttyname, CONS);	/* system console */
XX    else {
XX  	strcpy(ttyname, TTY);
XX! 	strcat(ttyname, itoa(ttynr));
XX    }
XX  
XX    /* Get login name and passwd. */
XX***************
XX*** 239,245 ****
XX  	}
XX  
XX  	/* Look up login/passwd. */
XX! 	if ((pwd = getpwnam(name)) == (struct passwd *) NULL) bad++;
XX  
XX  	/* If login name wrong or password exists, ask for pw. */
XX  	if (bad || strlen(pwd->pw_passwd) != 0) {
XX--- 245,251 ----
XX  	}
XX  
XX  	/* Look up login/passwd. */
XX! 	if ((pwd = getpwnam(name)) == NULL) bad++;
XX  
XX  	/* If login name wrong or password exists, ask for pw. */
XX  	if (bad || strlen(pwd->pw_passwd) != 0) {
XX***************
XX*** 263,269 ****
XX  		args.sg_flags |= ECHO;
XX  		ioctl(0, TIOCSETP, &args);
XX  
XX! 		if (bad && crypt(password, "aaaa") ||
XX  		    strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))) {
XX  #ifdef BADLOG
XX  			addlog(name, password, ttyname);
XX--- 269,275 ----
XX  		args.sg_flags |= ECHO;
XX  		ioctl(0, TIOCSETP, &args);
XX  
XX! 		if ((bad && crypt(password, "aaaa")) ||
XX  		    strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))) {
XX  #ifdef BADLOG
XX  			addlog(name, password, ttyname);
XX***************
XX*** 281,288 ****
XX  	wtmp(ttyname, name);
XX  
XX  	/* Create the argv[] array from the pw_shell field. */
XX! 	ap = 0;
XX! 	argx[ap++] = "-";	/* most shells need it for their .profile */
XX  	if (pwd->pw_shell[0]) {
XX  		sh = pwd->pw_shell;
XX  		bp = sh;
XX--- 287,293 ----
XX  	wtmp(ttyname, name);
XX  
XX  	/* Create the argv[] array from the pw_shell field. */
XX! 	ap = 1;
XX  	if (pwd->pw_shell[0]) {
XX  		sh = pwd->pw_shell;
XX  		bp = sh;
XX***************
XX*** 294,300 ****
XX  			}
XX  		}
XX  	} else
XX! 	argx[ap] = (char *) NULL;
XX  
XX  	/* Set the environment */
XX  	strcpy(user, "USER=");
XX--- 299,305 ----
XX  			}
XX  		}
XX  	} else
XX! 	argx[ap] = NULL;
XX  
XX  	/* Set the environment */
XX  	strcpy(user, "USER=");
XX***************
XX*** 321,338 ****
XX  
XX  	setgid(pwd->pw_gid);
XX  	setuid(pwd->pw_uid);
XX  	execve(sh, argx, env);
XX- 	execve(sh2, argx, env);		/* if /bin/sh absent, try /usr/bin/sh*/
XX  
XX! 	write(1, "exec failure\n", 13);
XX  	exit(1);
XX    }
XX  }
XX  
XX  
XX! void Time_out()
XX  {
XX     time_out = 1;
XX  }
XX- 
XX- 
XX--- 326,357 ----
XX  
XX  	setgid(pwd->pw_gid);
XX  	setuid(pwd->pw_uid);
XX+ 
XX+ 	/* Most shells need argv[0] to begin with "-" for a login shell.
XX+ 	 * Follow that with the name of the shell for ps.
XX+ 	 */
XX+ 	argx[0] = minus_shell;
XX+ 	minus_shell[0] = '-';
XX+ 	strcpy(minus_shell + 1, sh);
XX  	execve(sh, argx, env);
XX  
XX! 	/* Normal shell is absent, try /usr/bin/sh. */
XX! 	strcpy(minus_shell + 1, sh2);
XX! 	execve(sh2, argx, env);
XX! 
XX! 	write(1, "login: cannot exec ", 19);
XX! 	write(1, sh, strlen(sh));
XX! 	write(1, " or ", 4);
XX! 	write(1, sh2, strlen(sh2));
XX! 	write(1, "\n", 1);
XX  	exit(1);
XX    }
XX+   return(0);
XX  }
XX  
XX  
XX! void Time_out(dummy)
XX! int dummy;			/* to satisfy the prototype */
XX  {
XX     time_out = 1;
XX  }
X/
Xecho x - look.c.d
Xsed '/^X/s///' > look.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/look.c  crc=14635   3509	Sun Apr 25 21:35:05 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/look.c  crc=25554   3681	Wed Nov  4 04:19:13 1992
XX***************
XX*** 25,30 ****
XX--- 25,31 ----
XX  #include <sys/types.h>
XX  #include <string.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #ifdef UNIX
XX***************
XX*** 35,42 ****
XX  
XX  #define  MAX_WORD_LENGTH   80	/* including '\0'  */
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  
XX--- 36,46 ----
XX  
XX  #define  MAX_WORD_LENGTH   80	/* including '\0'  */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void Fold, (char *str));
XX+ _PROTOTYPE(void File_Error, (char *word_file));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  
XX***************
XX*** 117,123 ****
XX    {
XX  	/* Print out all the words starting with "prefix".  */
XX  
XX! 	int prefix_length = strlen(prefix);
XX  	int suffix_length = strlen(suffix);
XX  	int word_length;
XX  
XX--- 121,127 ----
XX    {
XX  	/* Print out all the words starting with "prefix".  */
XX  
XX! 	size_t prefix_length = strlen(prefix);
XX  	int suffix_length = strlen(suffix);
XX  	int word_length;
XX  
XX***************
XX*** 130,149 ****
XX  		cmp = strncmp(prefix, word, prefix_length);
XX  		if (cmp < 0) break;
XX  		if (cmp == 0)
XX! 			if (suffix_length == 0 || word_length >= suffix_length
XX! 			    && strcmp(suffix, word + word_length - suffix_length) == 0)
XX  				printf("%s\n", unfolded_word);
XX  	}
XX    }
XX  
XX    fclose(words);
XX  
XX!   exit(0);
XX  }
XX  
XX  
XX  
XX! Fold(str)
XX  char *str;
XX  
XX  {
XX--- 134,153 ----
XX  		cmp = strncmp(prefix, word, prefix_length);
XX  		if (cmp < 0) break;
XX  		if (cmp == 0)
XX! 			if (suffix_length == 0 || (word_length >= suffix_length
XX! 			    && strcmp(suffix, word + word_length - suffix_length) == 0))
XX  				printf("%s\n", unfolded_word);
XX  	}
XX    }
XX  
XX    fclose(words);
XX  
XX!   return(0);
XX  }
XX  
XX  
XX  
XX! void Fold(str)
XX  char *str;
XX  
XX  {
XX***************
XX*** 155,161 ****
XX  
XX  
XX  
XX! File_Error(word_file)
XX  char *word_file;
XX  
XX  {
XX--- 159,165 ----
XX  
XX  
XX  
XX! void File_Error(word_file)
XX  char *word_file;
XX  
XX  {
X/
Xecho x - lpr.c.d
Xsed '/^X/s///' > lpr.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/lpr.c  crc=64720   1710	Sun Apr 25 21:35:05 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/lpr.c  crc=60157   1972	Wed Nov  4 04:19:13 1992
XX***************
XX*** 3,15 ****
XX  #include <errno.h>
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  
XX  #define BLOCK 1024
XX  
XX  char in_buf[BLOCK], out_buf[BLOCK];
XX  int cur_in, in_count, out_count, column;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 3,23 ----
XX  #include <errno.h>
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX  
XX  #define BLOCK 1024
XX  
XX  char in_buf[BLOCK], out_buf[BLOCK];
XX  int cur_in, in_count, out_count, column;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void copy, (int fd));
XX! _PROTOTYPE(void myputchar, (int c));
XX! _PROTOTYPE(void flush, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 41,51 ****
XX  		}
XX  	}
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX! copy(fd)
XX  int fd;
XX  {
XX  /* Print a file, adding carriage returns and expanding tabs. */
XX--- 49,59 ----
XX  		}
XX  	}
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX! void copy(fd)
XX  int fd;
XX  {
XX  /* Print a file, adding carriage returns and expanding tabs. */
XX***************
XX*** 63,80 ****
XX  	}
XX  	c = in_buf[cur_in++];
XX  	if (c == '\n') {
XX! 		putc('\r');
XX! 		putc('\n');
XX  	} else if (c == '\t') {
XX  		do {
XX! 			putc(' ');
XX  		} while (column & 07);
XX  	} else
XX! 		putc(c);
XX    }
XX  }
XX  
XX! putc(c)
XX  char c;
XX  {
XX    out_buf[out_count++] = c;
XX--- 71,88 ----
XX  	}
XX  	c = in_buf[cur_in++];
XX  	if (c == '\n') {
XX! 		myputchar('\r');
XX! 		myputchar('\n');
XX  	} else if (c == '\t') {
XX  		do {
XX! 			myputchar(' ');
XX  		} while (column & 07);
XX  	} else
XX! 		myputchar(c);
XX    }
XX  }
XX  
XX! void myputchar(c)
XX  char c;
XX  {
XX    out_buf[out_count++] = c;
XX***************
XX*** 87,93 ****
XX    }
XX  }
XX  
XX! flush()
XX  {
XX    int n, count = 0;
XX  
XX--- 95,101 ----
XX    }
XX  }
XX  
XX! void flush()
XX  {
XX    int n, count = 0;
XX  
X/
Xecho x - ls.c.d
Xsed '/^X/s///' > ls.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ls.c  crc=28803  22577	Sun Apr 25 21:35:06 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ls.c  crc=51868  54672	Sun Apr  4 21:03:26 1993
XX***************
XX*** 1,806 ****
XX! /* ls - list files			Author: Peter Housel */
XX  
XX! /*@*Introduction.
XX!  * This file is part of \fIls\fP for Minix. It was written in the spring
XX!  * of 1989 by Peter S. Housel. This program is in the public domain and may
XX!  * be redistributed without restriction. As such, no warranty of any kind
XX!  * is provided.
XX!  * .PP
XX!  * The following changes to the program have been made:
XX!  * .IP \(bu
XX!  * Version 1.1 - removed references to \fB\-q\fP option, added |ONECOLUMN|
XX!  * and other compile-time options.
XX   */
XX  
XX! /*@ \fILs\fP is a version of standard Minix directory listing program. Because
XX!  * it use so often used, it should be as fast as possible. It should be
XX!  * somewhat "featureful" (Rob Pike nonwithstanding), but not in a way
XX!  * that interferes with its use as a "software tool." It should take
XX!  * up a small to medium amount of memory.
XX!  * .PP
XX!  * The program should be compiled using:
XX!  * .nf
XX!  *	\fBcc -o ls -D_MINIX -D_POSIX_SOURCE ls.c
XX!  *	chmem =4096 ls\fP
XX!  * or
XX!  *	\fBcc -o ls -DATARI_ST ls.c\fP
XX!  * .fi
XX!  * If you do not want multi-column listings to be the default when
XX!  * standard output is a tty, define |ONECOLUMN| (by adding
XX!  * \fB\-DONECOLUMN\fP to the compile flags). Similarly, |NFILE|,
XX!  * |STRINGSPACE|, and |LINEWIDTH| can be changed with appropriate
XX!  * predefines.
XX!  */
XX  
XX! #define ONECOLUMN		/* default is 1 column listings */
XX! #define major(x) ( (x>>8) & 0377)
XX! #define minor(x) (x & 0377)
XX  
XX! /*@ Since \fIls\fP has to know a lot about files, there are quite a few
XX!  * headers to include.
XX   */
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX- #include <errno.h>
XX- #include <limits.h>
XX- #include <dirent.h>
XX- #include <pwd.h>
XX- #include <grp.h>
XX- #include <time.h>
XX- #include <stdio.h>
XX  
XX! extern int errno;
XX  
XX! /*@ |DOTDIR()| determines whether or not a given |name| is one of the
XX!  * special directory files "." or "..".
XX   */
XX! #define DOTDIR(name)	\
XX!   (name[0] == '.'	\
XX!    && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
XX  
XX! /*@ We use |getopt()| to parse the command-line flag arguments. This
XX!  * annoys some people who are used to the (BSD pre-Tahoe release)
XX!  * "infinte args \fIls\fP" that doesn't complain about anything.
XX   */
XX! extern int getopt( 	/* int argc, char **argv, char *optstring */ );
XX! extern char *optarg;
XX! extern int optind;
XX  
XX! /*@ It may be necessary to |stat()| each file that is listed.
XX!  * The toplevel files (specified by the arguments) will need to be, to
XX!  * determine which ones are directories. Several of the options will
XX!  * make it necessary to have the |stat()| information (the \fB\-l\fP and
XX!  * \fB\-R\fP options, for example), and we will turn on |stateach|
XX!  * later on if any of these are set.
XX   */
XX! int stateach;
XX  
XX! /*@ \fILs\fP takes quite a few options: .IP \fB\-l\fP
XX!  * Print in "long listing" format. Sets |flags_l|, unsets |flags_C|.
XX!  * .IP \fB\-g\fP
XX!  * Include the group ownership along with the user ownership in the long
XX!  * format listing. Sets |flags_g|.
XX!  * .IP \fB\-t\fP
XX!  * Sort the listing by the modification time, with most recent times
XX!  * printed first. Sets |flags_t|.
XX!  * .IP \fB\-a\fP
XX!  * Include all files. By default, files whose names begin with "." are not
XX!  * included. Sets |flags_a|.
XX!  * .IP \fB\-A\fP
XX!  * Include all files, even those beginning with ".", except for "." and "..".
XX!  * This flag is automatically turned on for the superuser. Sets |flags_A|.
XX!  * .IP \fB\-s\fP
XX!  * Print the size of the file (in kilobytes) with each file. Sets |flags_s|.
XX!  * .IP \fB\-d\fP
XX!  * List named directories explicitly instead of their contents. Sets
XX!  * |flags_d|.
XX!  * .IP \fB\-r\fP
XX!  * Sort the listing in reverse order. Sets |flags_r|.
XX!  * .IP \fB\-u\fP
XX!  * Use the file access time instead of the modification time in the listings
XX!  * (\fB\-l\fP option) and/or as the sort key (\fB\-t\fP option). Sets
XX!  * |flags_u|. \fI(Currently ineffectual in Minix.)\fP
XX!  * .IP \fB\-c\fP
XX!  * Like \fB\-u\fP, except that the inode change time is used instead.
XX!  * Sets |flags_c|.
XX!  * .IP \fB\-i\fP
XX!  * Print the file's inode number with each file. Sets |flags_i|.
XX!  * .IP \fB\-f\fP
XX!  * Force the named files to be interpreted as directories, whether they
XX!  * are or not. (Actually, the POSIX-type directory routines cause problems
XX!  * with this. They reqire that the file be a directory.) Sets |flags_f|
XX!  * and |flags_a|, and unsets |flags_l|,
XX!  * |flags_t|, |flags_s|, and |flags_r|.
XX!  * .IP \fB\-F\fP
XX!  * After the filenames of directories, print "/". After executable files,
XX!  * print "*". Sets |flags_F|.
XX!  * .IP \fB\-R\fP
XX!  * Recursively print each subdirectory. Sets |flags_R|.
XX!  * .IP \fB\-1\fP
XX!  * Print in "one-column" format instead of columnar format. This is the
XX!  * default if standard output is not a tty. Unsets |flags_C|.
XX!  * .IP \fB\-C\fP
XX!  * Print in columnar format. This is the default if standard output is
XX!  * a tty, provided |ONECOLUMN| has not been defined. Sets |flags_C|.
XX   */
XX! #define VALID_FLAGS	"lgtaAsdrucifFR1C"
XX  
XX! int flags_l, flags_g, flags_t, flags_a, flags_A, flags_s, flags_d, flags_r, flags_u, flags_c, flags_i, flags_f, flags_F, flags_R, flags_C;
XX  
XX! /*@ */
XX! main(argc, argv)
XX! int argc;
XX! char *argv[];
XX  {
XX!   void add_args( 	/* int argc; char **argv; */ );
XX!   void listall( 	/* void */ );
XX  
XX!   int c;			/* option character */
XX! #ifdef noperprintf
XX!   noperprintf(stdout);
XX  #endif
XX  
XX! #ifndef ONECOLUMN
XX!   if (isatty(1)) flags_C = 1;
XX  #endif
XX  
XX!   while ((c = getopt(argc, argv, VALID_FLAGS)) != EOF) {
XX! 	switch (c) {
XX! 	    case 'l':	flags_l = 1;	break;
XX! 	    case 'g':	flags_g = 1;	break;
XX! 	    case 't':	flags_t = 1;	break;
XX! 	    case 'a':	flags_a = 1;	break;
XX! 	    case 'A':	flags_A = 1;	break;
XX! 	    case 's':	flags_s = 1;	break;
XX! 	    case 'd':	flags_d = 1;	break;
XX! 	    case 'r':	flags_r = 1;	break;
XX! 	    case 'u':	flags_u = 1;	break;
XX! 	    case 'c':	flags_c = 1;	break;
XX! 	    case 'i':	flags_i = 1;	break;
XX! 	    case 'f':	flags_f = 1;	break;
XX! 	    case 'F':	flags_F = 1;	break;
XX! 	    case 'R':	flags_R = 1;	break;
XX! 	    case '1':	flags_C = 0;	break;
XX! 	    case 'C':	flags_C = 1;	break;
XX  
XX- 	    case '?':
XX- 		fprintf(stderr, "Usage: ls -%s [file ...]\n",
XX- 			VALID_FLAGS);
XX- 		exit(1);
XX  	}
XX!   }
XX  
XX!   if (flags_f) {
XX! 	flags_l = flags_t = flags_s = flags_r = 0;
XX! 	flags_a = 1;
XX    }
XX!   if (flags_l || flags_s || flags_i) flags_C = 0;
XX  
XX!   flags_r = flags_r ? -1 : 1;	/* multiplier for comparisons */
XX  
XX!   if (geteuid() == 0 && !flags_a) flags_A = 1;
XX  
XX!   stateach = !flags_f;
XX!   add_args(argc - optind + 1, argv + optind - 1);
XX  
XX!   stateach = !flags_f && (flags_l || flags_t || flags_s || flags_i
XX! 			|| flags_F || flags_R);
XX!   listall();
XX  
XX!   exit(0);
XX  }
XX  
XX! /*@* The files table.
XX!  * The |struct lsfile| structure is the main data structure used by
XX!  * \fIls\fP. The |files| array is an array of these structures, with
XX!  * each entry representing one file to be listed by the program.
XX!  * The |f_stat| field is the result of a |stat()| call on the file, if
XX!  * one has been done. The |f_name| field points to the filename, either
XX!  * directly to the command-line argument, or to a copy in string space
XX!  * of a name read from a directory. The |f_parent| field points to the
XX!  * parent directory of a file, so that the entire relative pathname
XX!  * can be constructed using the |pathname()| function below.
XX!  * .PP
XX!  * There are at most |NFILE| entries in the staticaly-allocated table.
XX!  * Entries are added as a directory is read in, and removed when the
XX!  * listing of that directory is done. The |filep| variable is used to
XX!  * point to the next free entry.
XX   */
XX- #ifndef NFILE
XX- #define NFILE		512
XX- #endif
XX  
XX! struct lsfile {
XX!   struct stat f_stat;		/* file information from inode */
XX!   char *f_name;			/* file name */
XX!   struct lsfile *f_parent;	/* parent directory, if any */
XX! };
XX  
XX! struct lsfile files[NFILE];
XX! struct lsfile *filep = files;
XX  
XX! /*@ When a directory is sorted, the time spent exchanging entries is reduced
XX!  * by exchanging pointers to entries instead of the entries themselves.
XX!  * When a listing is printed, the file table entries are accessed
XX!  * indirectly through |sortindex| entries.
XX   */
XX- struct lsfile *sortindex[NFILE];
XX  
XX  
XX! /*@ The string area is used to store filenames read in from directories,
XX!  * as well as the lines of output for columnar listings. Like the file
XX!  * table, space in the string area is deallocated when it is no longer
XX!  * needed.
XX   */
XX! #ifndef STRINGSPACE
XX! #define STRINGSPACE	8192
XX  #endif
XX  
XX! char strings[STRINGSPACE];
XX! char *stringp = strings;
XX  
XX! /*@ The |ADDSTRING()| macro is used to add characters to the string
XX!  * table. A check for overflow is made.
XX!  */
XX! char stringerr[] = "ls: out of string space\n";
XX! #define ADDSTRING(c) 				\
XX!   if(stringp - strings >= STRINGSPACE)	\
XX!     {					\
XX!      fprintf(stderr, stringerr);		\
XX!      exit(1);				\
XX!     }					\
XX!   else					\
XX!      *stringp++ = c
XX  
XX! /*@ These are the forward declarations for the files table section. */
XX! void add_file(			/* char *filename, struct lsfile *parent,
XX!             ino_t inum, int savename */ );
XX! char *pathname( 	/* struct lsfile *entry */ );
XX  
XX! /*@ The |add_args()| function is used to add the files specified
XX!  * in the command line arguments to the files table. Note that
XX!  * \fIls\fP without any file arguments is equivalent to "\fIls\ .\fP"
XX   */
XX! void add_args(argc, argv)
XX! int argc;
XX! char *argv[];
XX  {
XX!   if (argc == 1)
XX! 	add_file(".", (struct lsfile *) NULL, 0, 0);
XX!   else
XX! 	while (++argv, --argc) {
XX! 		add_file(*argv, (struct lsfile *) NULL, 0, 0);
XX  	}
XX  }
XX  
XX! 
XX! /*@ |add_dir()| opens a directory and adds the files it contains to the
XX!  * files table. If "dot-files" are not being listed, they will be
XX!  * omitted.
XX   */
XX! void add_dir(entry)
XX! struct lsfile *entry;
XX  {
XX!   DIR *dirp;
XX!   struct dirent *dp;
XX!   struct lsfile *parent = NULL;
XX  
XX!   if (strcmp(entry->f_name, ".") != 0)	/* "./" is redundant */
XX! 	parent = entry;
XX  
XX!   if ((dirp = opendir(pathname(entry))) == NULL) {
XX! 	fprintf(stderr, "ls: can't open directory %s\n", pathname(entry));
XX! 	perror("ls");
XX! 	return;
XX!   }
XX!   while ((dp = readdir(dirp)) != NULL) {
XX! 	if (dp->d_name[0] == '.' && !(flags_A || flags_a)) continue;
XX! 	if (DOTDIR(dp->d_name) && !flags_a) continue;
XX! 	add_file(dp->d_name, parent, (ino_t) dp->d_ino, 1);
XX!   }
XX  
XX!   (void) closedir(dirp);
XX  }
XX  
XX! /*@ |add_file()| does the actual work of entering files into the table.
XX!  * If it is necessary to save the name in the string table, this is
XX!  * done. Also, if it is necessary to |stat()| the file, we do it here.
XX   */
XX  
XX! void add_file(filename, parent, inum, savename)
XX! char *filename;
XX! struct lsfile *parent;
XX! ino_t inum;
XX! int savename;
XX  {
XX!   if (filep - files >= NFILE) {
XX! 	fprintf(stderr, "ls: too many files\n");
XX! 	exit(1);
XX    }
XX!   if (filename[0] == '\0') {	/* POSIX doesn't like null pathnames (?) */
XX! 	fprintf(stderr, "ls: invalid null filename\n");
XX! 	return;
XX    }
XX-   if (savename) {
XX- 	filep->f_name = stringp;
XX- 	while (*filename) {
XX- 		ADDSTRING(*filename++);
XX- 	}
XX- 	ADDSTRING('\0');
XX-   } else
XX- 	filep->f_name = filename;
XX  
XX!   filep->f_parent = parent;
XX!   filep->f_stat.st_ino = inum;
XX  
XX!   sortindex[filep - files] = filep;
XX  
XX!   if (stateach)
XX! 	if (stat(pathname(filep), &filep->f_stat) < 0) {
XX! 		int saverrno = errno;
XX! 		fprintf(stderr, "ls: cannot stat %s", pathname(filep));
XX! 		errno = saverrno;
XX! 		perror("");
XX! 		return;
XX! 	}
XX!   ++filep;
XX  }
XX  
XX! /*@ The |pathname()| function reconstructs the relative pathname of a
XX!  * file from a pointer to its table entry. As a base case, it returns
XX!  * the stored filename of files which have no parents. Otherwise, it
XX!  * recursively determines the pathname of the parent directory and
XX!  * appends the stored name to it.
XX!  * .PP
XX!  * The name of the last parent directory searched is cached to save
XX!  * on recursive calls.
XX   */
XX! char *pathname(entry)
XX! struct lsfile *entry;
XX  {
XX!   static char name[PATH_MAX + 1];
XX  
XX!   static char parentname[PATH_MAX + 1];
XX!   static struct lsfile *parent;
XX  
XX!   register char *p, *q;
XX  
XX!   if (entry->f_parent == NULL) return entry->f_name;
XX  
XX!   if (entry->f_parent != parent) {
XX! 	strcpy(parentname, pathname(entry->f_parent));	/* recurse */
XX! 	parent = entry->f_parent;
XX    }
XX!   for (q = parentname, p = name; *q;) *p++ = *q++;
XX  
XX!   if (p[-1] != '/') *p++ = '/';
XX  
XX!   for (q = entry->f_name; *q;) *p++ = *q++;
XX  
XX!   *p = '\0';
XX  
XX!   return name;
XX  }
XX  
XX! /*@*Listing files.
XX!  * Most of the work of listing files is done in this section, in particular
XX!  * by the |listfiles()| function.
XX   */
XX  
XX! /*@ Forward declarations for this section: */
XX! void listfiles( 	/* int baseindex; int lastindex */ );
XX! void sortfiles( 	/* int baseindex; int nfiles */ );
XX! void listone( 	/* struct lsfile *entry */ );
XX! void listcol( 	/* struct lsfile *entry */ );
XX! void prdate( 	/* time_t filetime */ );
XX! void dumpcols( 	/* void */ );
XX  
XX! char *owner( 	/* int uid */ );
XX! char *groupname( 	/* int gid */ );
XX  
XX! /*@ */
XX! void listall()
XX  {
XX!   if (!flags_f) sortfiles(0, (int)(filep - files));
XX!   listfiles(0, (int)(filep - files), flags_d);
XX  }
XX  
XX! /*@ The |listfiles()| function is, effectively, the "heart" of \fIls\fP.
XX!  * First, the "total nnn" line (listing the total number of blocks
XX!  * taken up by the listed files) is computed and printed if necessary.
XX!  * Next, if we are listing files specified on the command line, list
XX!  * all except the directories. Otherwise, list all of the files. Next,
XX!  * go through all of the directories and recursively list them.
XX   */
XX! void listfiles(baseindex, lastindex, include_dirs)
XX! int baseindex;
XX! int lastindex;
XX! int include_dirs;
XX  {
XX!   int i;
XX!   char *name;
XX!   char *ostringp;
XX  
XX!   if (flags_l || flags_s) {
XX! 	int total = 0;
XX! 	int counted = 0;
XX! 	for (i = baseindex; i < lastindex; ++i) {
XX! 		if (include_dirs
XX! 		    || (sortindex[i]->f_stat.st_mode & S_IFMT) != S_IFDIR) {
XX! 			counted = 1;
XX! 			total += nblocks(sortindex[i]->f_stat.st_size);
XX  		}
XX  	}
XX- 	if (counted) printf("total %d\n", total);
XX    }
XX!   ostringp = stringp;
XX  
XX!   for (i = baseindex; i < lastindex; ++i) {
XX! 	if (!(flags_f && baseindex == 0) && (include_dirs
XX! 	     || (sortindex[i]->f_stat.st_mode & S_IFMT) != S_IFDIR))
XX! 		if (flags_C)
XX! 			listcol(sortindex[i]);
XX! 		else
XX! 			listone(sortindex[i]);
XX!   }
XX  
XX!   if (flags_C) dumpcols();
XX  
XX!   stringp = ostringp;
XX  
XX!   fflush(stdout);
XX!   if (flags_d || (baseindex > 0 && !flags_R)) return;
XX  
XX!   for (i = baseindex; i < lastindex; ++i) {
XX! 	name = sortindex[i]->f_name;
XX  
XX! 	if ((flags_f && baseindex == 0)
XX! 	    || ((sortindex[i]->f_stat.st_mode & S_IFMT) == S_IFDIR
XX! 		&& (baseindex == 0 || !DOTDIR(name)))) {
XX! 		struct lsfile *ofilep;
XX  
XX! 		if (lastindex - baseindex > 1)
XX! 			printf("\n%s:\n", pathname(sortindex[i]));
XX  
XX! 		ofilep = filep;
XX! 		ostringp = stringp;
XX  
XX! 		add_dir(sortindex[i]);
XX! 		if (!flags_f) sortfiles((int)(ofilep - files), (int)(filep - ofilep));
XX! 		listfiles((int)(ofilep - files), (int)(filep - files), 1);
XX  
XX! 		filep = ofilep;
XX! 		stringp = ostringp;
XX  	}
XX    }
XX  }
XX  
XX! /*@ Except for columnar listings, |listone()| does the work of listing
XX!  * individual files, on lines by themselves, to standard output.
XX!  * Special-case formatting is done for the "-l", "-s", "-i", and "-F"
XX!  * options.
XX   */
XX! void listone(entry)
XX! register struct lsfile *entry;
XX  {
XX!   unsigned short mode;
XX!   char c, fchar( 	/* unsigned short mode */ );
XX  
XX!   if (flags_i) printf("%5d ", entry->f_stat.st_ino);
XX  
XX!   if (flags_s) printf("%4d ", nblocks(entry->f_stat.st_size));
XX  
XX!   mode = entry->f_stat.st_mode;
XX  
XX!   if (flags_l) {
XX! 	static char *rwx[] = {"---", "--x", "-w-", "-wx",
XX! 			      "r--", "r-x", "rw-", "rwx"};
XX! 	char bits[11];
XX  
XX! 	switch (mode & S_IFMT) {
XX! 	    case S_IFDIR:	bits[0] = 'd';	break;
XX! 	    case S_IFBLK:	bits[0] = 'b';	break;
XX! 	    case S_IFCHR:	bits[0] = 'c';	break;
XX! 	    case S_IFIFO:	bits[0] = 'p';	break;
XX! 	    default:	bits[0] = '-';	break;
XX  	}
XX  
XX! 	strcpy(&bits[1], rwx[(mode >> 6) & 7]);
XX! 	strcpy(&bits[4], rwx[(mode >> 3) & 7]);
XX! 	strcpy(&bits[7], rwx[(mode & 7)]);
XX! 	if (mode & S_ISUID) bits[3] = 's';
XX! 	if (mode & S_ISGID) bits[6] = 's';
XX! /*  if(mode & S_ISVTX) bits[9] = 't';		NOT IMPLEMENTED */
XX! 	printf("%s %2d %-8.8s ", bits, entry->f_stat.st_nlink,
XX! 	       owner(entry->f_stat.st_uid));
XX! 	if (flags_g) printf("%-8.8s ", groupname(entry->f_stat.st_gid));
XX  
XX! 	if ((mode & S_IFMT) == S_IFCHR || (mode & S_IFMT) == S_IFBLK) {
XX! 		printf("%3d, %3d ", major(entry->f_stat.st_rdev),
XX! 		       minor(entry->f_stat.st_rdev));
XX! 	} else
XX! 		printf("%8ld ", (long) entry->f_stat.st_size);
XX  
XX! 	if (flags_u)
XX! 		prdate(entry->f_stat.st_atime);
XX! 	else if (flags_c)
XX! 		prdate(entry->f_stat.st_ctime);
XX  	else
XX! 		prdate(entry->f_stat.st_mtime);
XX    }
XX!   printf("%s", entry->f_name);
XX  
XX!   if (flags_F && (c = fchar(mode)) != '\0') putchar(c);
XX!   putchar('\n');
XX  }
XX  
XX! /*@ When the "-F" option is being used, |fchar()| computes the character
XX!  * which will follow the filename - '/' for directories, and '*' for
XX!  * executable files. If there were sockets, FIFO's and symbolic links,
XX!  * they would have cases here too.
XX   */
XX! char fchar(mode)
XX! unsigned short mode;
XX  {
XX!   if ((mode & S_IFMT) == S_IFDIR)
XX! 	return '/';
XX!   else if (mode & 0111)
XX! 	return '*';
XX    else
XX! 	return '\0';
XX  }
XX  
XX! /*@*Listing in columns.
XX!  * When the "-C" option is used, or an ordinary listing is done to
XX!  * a terminal, then the listing is in columns. As many columns as will
XX!  * fit on the screen are used. The |listcol()| function is used to
XX!  * add an entry to the column entries table, and is called instead
XX!  * of |listone()|. The string which will be printed for each file
XX!  * is stored in the string table. When the listing is done, |dumpcol()|
XX!  * will print it out.
XX   */
XX- #ifndef LINEWIDTH
XX- #define LINEWIDTH	79
XX- #endif
XX  
XX! int maxwidth = 0;
XX! char *colentries[NFILE];
XX! char **colentp = colentries;
XX  
XX! /*@ For now, |listcol()| copies the filename to the string table
XX!  * and leaves a pointer in the column entries table, optinally adding
XX!  * the postfix character for the "-F" option. It also maintains
XX!  * a "maximum width" so that |dumpcols()| can determine how many
XX!  * columns will fit on a terminal line.
XX   */
XX! void listcol(entry)
XX! register struct lsfile *entry;
XX  {
XX!   char *p;
XX!   char c;
XX!   int width;
XX  
XX!   *colentp = stringp;
XX!   for (p = entry->f_name; *p;) {
XX! 	ADDSTRING(*p++);
XX    }
XX  
XX!   width = stringp - *colentp;
XX!   if (width > maxwidth) maxwidth = width;
XX  
XX!   if (flags_F && (c = fchar(entry->f_stat.st_mode)) != '\0') ADDSTRING(c);
XX  
XX!   ADDSTRING('\0');
XX!   ++colentp;
XX  }
XX  
XX! /*@ |dumpcols()| computes how many columns will fit on the output
XX!  * line, and prints the filenames.
XX   */
XX! void dumpcols()
XX  {
XX!   int ncols;			/* number of columns that will fit */
XX!   int nrows;			/* number of rows required */
XX!   int colwidth;			/* how wide the evenly spaced columns are */
XX!   int i;
XX!   char **cp;			/* pointer to column entries */
XX  
XX!   if (maxwidth == 0) return;
XX  
XX!   ncols = LINEWIDTH / (maxwidth + 2);
XX!   if (ncols == 0) ncols = 1;
XX!   colwidth = LINEWIDTH / ncols;
XX!   nrows = (colentp - colentries) / ncols;
XX!   if ((colentp - colentries) % ncols > 0) ++nrows;
XX  
XX!   for (i = 0; i < nrows; ++i) {	/* loop on rows */
XX! 	for (cp = &colentries[i]; cp < colentp; cp += nrows) {	/* loop on columns */
XX! 		printf("%-*.*s", colwidth, colwidth, *cp);
XX! 	}
XX! 	putchar('\n');
XX    }
XX  
XX!   colentp = colentries;		/* re-initialize for next listing */
XX!   maxwidth = 0;
XX  }
XX  
XX! /*@*Sorting lists.
XX!  * Sorting is done using the standard library |qsort()| function.
XX!  * Depending on the options, either the file access time, the file
XX!  * modify time, the inode change time, or the filename will be used
XX!  * as the sort key. |sortfiles()| determines what comparison function to
XX!  * use based on this and calls |qsort()|.
XX   */
XX! void sortfiles(baseindex, nfiles)
XX! int baseindex;
XX! int nfiles;
XX  {
XX!   int (*compare) ();
XX!   int comp_atime(), comp_ctime(), comp_mtime(), comp_name();
XX  
XX!   if (nfiles < 2) return;
XX!   if (flags_t) {
XX! 	if (flags_u)
XX! 		compare = comp_atime;
XX! 	else if (flags_c)
XX! 		compare = comp_ctime;
XX! 	else
XX! 		compare = comp_mtime;
XX!   } else
XX! 	compare = comp_name;
XX  
XX!   qsort(&sortindex[baseindex], nfiles, sizeof sortindex[0], compare);
XX  }
XX  
XX! int comp_atime(one, two)	/* compare access times */
XX! struct lsfile **one;
XX! struct lsfile **two;
XX  {
XX!   register time_t diff;
XX  
XX!   diff = (*one)->f_stat.st_atime - (*two)->f_stat.st_atime;
XX  
XX!   if (diff == 0)
XX! 	return 0;
XX!   else if (diff < 0)
XX! 	return flags_r;
XX!   else
XX! 	return -flags_r;
XX  }
XX  
XX! int comp_ctime(one, two)	/* compare inode change times */
XX! struct lsfile **one;
XX! struct lsfile **two;
XX  {
XX!   register time_t diff;
XX  
XX!   diff = (*one)->f_stat.st_ctime - (*two)->f_stat.st_ctime;
XX  
XX!   if (diff == 0)
XX! 	return 0;
XX!   else if (diff < 0)
XX! 	return flags_r;
XX!   else
XX! 	return -flags_r;
XX  }
XX  
XX! int comp_mtime(one, two)	/* compare file modify times */
XX! struct lsfile **one;
XX! struct lsfile **two;
XX  {
XX!   register time_t diff;
XX  
XX!   diff = (*one)->f_stat.st_mtime - (*two)->f_stat.st_mtime;
XX  
XX!   if (diff == 0)
XX! 	return 0;
XX!   else if (diff < 0)
XX! 	return flags_r;
XX!   else
XX! 	return -flags_r;
XX  }
XX  
XX! int comp_name(one, two)		/* compare filenames */
XX! struct lsfile **one;
XX! struct lsfile **two;
XX  {
XX!   return flags_r * strcmp((*one)->f_name, (*two)->f_name);
XX  }
XX  
XX! /*@*User and group id's.
XX!  * |owner()| and |groupname()| are used to translate user and group
XX!  * id's to names for the long-format listing. The last id translated
XX!  * is cached.
XX   */
XX! char *owner(uid)
XX! int uid;
XX  {
XX!   static int ouid = -1;
XX!   static char uname[16];
XX!   struct passwd *pw, *getpwuid( /* int uid */ );
XX  
XX!   if (uid == ouid) return uname;
XX  
XX!   if ((pw = getpwuid(uid)) == NULL)
XX! 	sprintf(uname, "%d", uid);
XX!   else
XX! 	strcpy(uname, pw->pw_name);
XX  
XX!   return uname;
XX  }
XX  
XX! char *groupname(gid)
XX! int gid;
XX  {
XX!   static int ogid = -1;
XX!   static char gname[16];
XX!   struct group *gr, *getgrgid( 	/* int gid */ );
XX  
XX!   if (gid == ogid) return gname;
XX  
XX!   if ((gr = getgrgid(gid)) == NULL)
XX! 	sprintf(gname, "%d", gid);
XX!   else
XX! 	strcpy(gname, gr->gr_name);
XX  
XX!   return gname;
XX  }
XX  
XX! /*@*Date and time. |prdate()| prints the specified time in the format used by
XX!  * the long-format listing. The month and day are printed, along with the
XX!  * time of day if the time is recent. If it is not, the year is printed
XX!  * instead.
XX   */
XX  
XX! #define LONGAGO	((365L * 86400L) / 2L)	/* about six months */
XX  
XX! void prdate(filetime)
XX! time_t filetime;
XX  {
XX!   struct tm *timep, *localtime( /* time_t *clock */ );
XX!   static time_t now;		/* approximate current time */
XX  
XX!   static char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
XX! 			 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
XX  
XX!   if (now == 0) time(&now);
XX  
XX!   timep = localtime(&filetime);
XX  
XX!   printf("%s %2d ", months[timep->tm_mon], timep->tm_mday);
XX  
XX!   if (now - filetime >= LONGAGO || filetime > now)
XX! 	printf(" %d ", timep->tm_year + 1900);
XX!   else
XX! 	printf("%02d:%02d ", timep->tm_hour, timep->tm_min);
XX  }
XX  
XX! /*@*Counting blocks.
XX!  * This code is 'stolen' almost verbatim from Andrew S. Tanenbaum's
XX!  * original Minix "ls.c" program. It is the primary non-POSIX (OS-dependant)
XX!  * function in the program.
XX   */
XX- #include <minix/config.h>
XX- #include <minix/const.h>
XX- #include <minix/type.h>
XX- #include "../fs/const.h"
XX- #include "../fs/type.h"
XX  
XX! int nblocks(size)
XX! long size;
XX  {
XX! /* Convert file length to blocks, including indirect blocks. */
XX  
XX!   int blocks, fileb;
XX  
XX!   fileb = (size + (long) BLOCK_SIZE - 1) / BLOCK_SIZE;
XX    blocks = fileb;
XX!   if (fileb <= NR_DZONE_NUM) return(blocks);
XX!   blocks++;
XX!   fileb -= NR_DZONE_NUM;
XX!   if (fileb <= NR_INDIRECTS) return(blocks);
XX!   blocks++;
XX!   fileb -= NR_INDIRECTS;
XX!   blocks += (fileb + NR_INDIRECTS - 1) / NR_INDIRECTS;
XX!   return(blocks);
XX  }
XX--- 1,1942 ----
XX! /* ls - list directory			Author: C. E. Chew */
XX  
XX! /*			List Directory Entries
XX!  *
XX!  * (C) Copyright C E Chew
XX!  *
XX!  * Feel free to copy and use this software provided:
XX!  *
XX!  *	1. you do not pretend that you wrote it
XX!  *	2. you leave this copyright notice intact.
XX!  *
XX!  * This is an implementation of a BSD style ls(1) for Minix. This
XX!  * implementation is faster than the original ls(1) for Minix. There
XX!  * are no restrictions with regard to the size of the directory file
XX!  * since memory is allocated dynamically.
XX   */
XX  
XX! #ifndef		PASS1		/* hack for small compilers */
XX! # ifndef	PASS2
XX! #   define	PASS1
XX! #   define	PASS2
XX! # endif
XX! #endif
XX  
XX! #ifdef	PASS1
XX! char Version_[] = "@(#)els 3.17a 03-Jan-1993 (C) C E Chew";
XX! #endif
XX  
XX! /* Edit History:
XX!  * 03-Jan-1993  Merged Minix 1.6.23 changes (-DAST, larger field width for
XX!  *		file lengths, and silly parens for && within ||).
XX!  * 17-May-1992	Accommodated Minix 1.6.16 hacks and Bruce's minor patches.
XX!  * 02-May-1992	Bug with -f flag following null pointer.
XX!  *		Fix typo in blank padding calculation.
XX!  * 11-Jul-1991	Could not follow relative symlinks when invoked with
XX!  *		ls -l /usr/local/lib/mushtool.
XX!  * 14-Apr-1991	Incorporated mntent library source.
XX!  * 06-Apr-1991	Fix `ls -ld' problem.
XX!  * 30-Mar-1991	Fix uninitialised cw pointer in acrosspage().
XX!  * 12-Mar-1991	Strip out non-Minix conditional code into ls.h
XX!  * 08-Mar-1991	Need const qualifier in stringlength().
XX!  *		Fix for Mips gcc complaint about wrong printf format.
XX!  *		Don't initialise blanks[] at runtime.
XX!  * 06-Mar-1991	Fix date initialisation.
XX!  * 05-Mar-1991	Fix typos and avoid getcwd() and time() if possible.
XX!  * 03-Mar-1991	Add -0 option to reset options (to unset LSOPTS).
XX!  *		Add usage information.
XX!  * 22-Feb-1991	Add -S option to squeeze column widths.
XX!  * 21-Feb-1991	Use STDC locally to avoid __STDC__ brain damage.
XX!  *		Change order of dolsopts() and docmdname() scan.
XX!  * 20-Feb-1991	Some Coherent port problems.
XX!  * 15-Feb-1991	Coherent port included.
XX!  * 27-Dec-1990	Upgrade for Minix 2.0 filesystem.
XX!  * 30-Nov-1990	Fix nil dereference problem.
XX!  * 21-Nov-1990	Use lstat() on target of symlink so that multilevel
XX!  *		links are visible. Don't give up on failed readlink().
XX!  * 23-Jul-1990	POSIXfication.
XX!  * 10-May-1990	Miscellaneous patches.
XX!  * 23-Apr-1989	Reorder includes for 1.5.8. Support sticky and locking
XX!  *		bits. Support st_ctime and st_atime. Support for name
XX!  *		aliases.
XX!  * 20-Oct-1989	Change suffix for failed symbolic links.
XX!  * 21-Sep-1989	Changed names to _BSD and _MINIX. Use #ifdef for
XX!  *		portability.
XX!  * 19-Sep-1989	Sizes in kb rather than `blocks'.
XX!  * 14-Sep-1989	No longer need to define MINIX. Get rid of itoa().
XX!  *		Pyramid BSD coercions. Symbolic links and sockets.
XX!  * 27-Aug-1989	Added declaration of errno for old errno.h and
XX!  *		char *malloc() for old include files. Added
XX!  *		support for named FIFO's. Changed user and group
XX!  *		name format to %-6.6s so that long names won't
XX!  *		muck up columns. Later will have to add
XX!  *		symbolic link support for -l and -L.
XX!  * 16-May-1989	Option -n shouldn't look in /etc/passwd. Use new
XX!  *		strerror in string.h, add prototype for itoa().
XX!  * 30-Apr-1989	Changed stat failure message to not found. Include
XX!  *		dirent.h after stdio.h so that NULL is defined.
XX!  * 22-Mar-1989	Incompatible options processing, long sizes instead
XX!  *		of int and removed TURBOC conditional.
XX!  * 02-Mar-1989	Sort command line arguments.
XX!  * 22-Feb-1989	Fixed up bug regarding device number printing.
XX!  * 10-Sep-1988	Cleaned up for lint.
XX!  * 05-Sep-1988	Tidied up for network release.
XX   */
XX+ 
XX+ #ifndef		_SYSV
XX+ # ifndef	_BSD
XX+ #   ifndef	COHERENT
XX+ #     ifndef	_MINIX
XX+ #       define 	_MINIX
XX+ #     endif
XX+ #   endif
XX+ # endif
XX+ #endif
XX+ 
XX+ #define		TERMCAP		/* consult termcap for columns */
XX+ /*efine		USESTDLIB*/	/* stdlib.h available for use */
XX+ /*efine		USESTDDEF*/	/* stddef.h available for use */
XX+ 
XX+ #ifdef __STDC__			/* fix brain damage */
XX+ # if __STDC__ != 0
XX+ #   define STDC
XX+ # endif
XX+ #endif
XX+ #ifdef	STDC
XX+ # define CONST		const
XX+ # define P(x)		x
XX+ # define F4(t1,n1,t2,n2,t3,n3,t4,n4)	(t1 n1,t2 n2,t3 n3,t4 n4)
XX+ # define F3(t1,n1,t2,n2,t3,n3)		(t1 n1,t2 n2,t3 n3)
XX+ # define F2(t1,n1,t2,n2)		(t1 n1,t2 n2)
XX+ # define F1(t1,n1)			(t1 n1)
XX+ # define F0()				(void)
XX+ #else
XX+ # define CONST
XX+ # define P(x)		()
XX+ # define F4(t1,n1,t2,n2,t3,n3,t4,n4)	(n1,n2,n3,n4)t1 n1;t2 n2;t3 n3;t4 n4;
XX+ # define F3(t1,n1,t2,n2,t3,n3)		(n1,n2,n3)t1 n1;t2 n2;t3 n3;
XX+ # define F2(t1,n1,t2,n2)		(n1,n2)t1 n1;t2 n2;
XX+ # define F1(t1,n1)			(n1)t1 n1;
XX+ # define F0()				()
XX+ #endif
XX+ 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  
XX! #ifndef		_MINIX
XX! # include "ls.h"
XX! #else
XX! # ifndef	_POSIX_SOURCE
XX! #   define	_POSIX_SOURCE
XX! #   define	_POSIX_1_SOURCE 2
XX! # endif
XX! # include <stdlib.h>
XX! # define FREE_T void *
XX! # include <limits.h>
XX! # ifdef	PASS1
XX! #   include <ctype.h>
XX! #   include <grp.h>
XX! #   include <pwd.h>
XX! #   include <errno.h>
XX! #   include <dirent.h>
XX! #   include <string.h>
XX! #   include <time.h>
XX! #   include <stddef.h>
XX! #   define OFFSETOF(t,n)	offsetof(t,n)
XX! #   define USRGRPOTH(m)		(m)
XX! # endif
XX! # ifdef	PASS2
XX! #   include <limits.h>
XX! #   include <minix/config.h>
XX! #   include <minix/const.h>
XX! #   include <minix/type.h>
XX! #   include "../fs/const.h"
XX! #   include "../fs/type.h"
XX! #   undef printf
XX! #   define STD_BLK	BLOCK_SIZE
XX! #   define BYTESPERBLK	512
XX! #   ifndef V1_NR_DZONES
XX! #     define V1_NR_TZONES NR_ZONE_NUMS
XX! #     define V1_NR_DZONES NR_DZONE_NUM
XX! #     define V1_INDIRECTS NR_INDIRECTS
XX! #   else
XX! #     define USEMTAB
XX! #     ifdef USEMNTENTLIB
XX! #	include <mntent.h>
XX! #     else
XX! #	define MTAB		"/etc/mtab"
XX! struct mntent {
XX!   char *mnt_fsname;			/* device */
XX!   char *mnt_dir;			/* mount point */
XX!   char *mnt_type;			/* filesystem type */
XX!   char *mnt_opts;			/* options */
XX! };
XX! #   include <stdio.h>			/* we were trying to include this last
XX! 					 * to avoid Minix header braindamage
XX! 					 * (multiple definitions of NULL), but
XX! 					 * FILE * is needed now */
XX! #   undef NULL				/* fix the header braindamage */
XX! FILE *setmntent P((char *_file, char *));
XX! struct mntent *getmntent P((FILE *_mf));
XX! void endmntent P((FILE *_mf));
XX! #	define setmntent(n,t)	(fopen((n),(t)))
XX! #	define endmntent(f)	((void) fclose(f))
XX! #     endif
XX! #   endif
XX! # endif
XX! # include <unistd.h>
XX! # include <stdio.h>
XX! #endif
XX  
XX! #ifdef PASS2
XX! # ifdef	_POSIX_SOURCE
XX! #   undef BYTESPERBLK
XX! #   define BYTESPERBLK	512
XX! # endif
XX! #endif
XX! 
XX! /***********************************************************************\
XX!  *                            Common Definitions                       *
XX! \***********************************************************************/
XX! 
XX! #define NIL		(0)	/* nil pointer */
XX! 
XX! /* Mounted file system parameter table */
XX! 
XX! typedef struct filesystem {
XX!   struct filesystem *next;		/* link to next */
XX!   dev_t dev;				/* mounted device */
XX!   unsigned long *fs;			/* structure */
XX! } FILESYSTEM;
XX! 
XX! /***********************************************************************\
XX!  *                             Portable Code                           *
XX! \***********************************************************************/
XX! #ifdef		PASS1
XX! 
XX! #ifndef		SUPER_USER
XX! # define SUPER_USER	(0)
XX! #endif
XX! 
XX! #define DEFAULTDIR	"."	/* default for ls without args */
XX! #define ENVNAME		"LSOPTS"/* ls options */
XX! #define COLNAME		"COLUMNS"/* columns option */
XX! #define TERMNAME	"TERM"	/* name of terminal */
XX! #define LINKPOINTER	" -> "	/* symlink pointer indicator */
XX! #define COLUMNS		80	/* columns on terminal */
XX! #define INTERSPACE	2	/* spacing between columns */
XX! #define INODEWIDTH	5	/* width of field for inode */
XX! #define BLOCKWIDTH	6	/* width of field for blocks */
XX! 
XX! #define HALFYEAR	((long) 60*60*24*365/2)	/* half year in seconds */
XX! #define BASEYEAR	1900	/* struct tm.tm_year base */
XX! 
XX! /* Flags are maintained in a bitmap. */
XX! #define BPC		CHAR_BIT/* bits per character */
XX! #define BITTEST(m,b)	(m[b/BPC] & (1<<(b%BPC)))
XX! #define BITSET(m,b)	(m[b/BPC] |= (1<<(b%BPC)))
XX! #define BITCLEAR(m,b)	(m[b/BPC] &= ~(1<<(b%BPC)))
XX! #define BITCHARS(b)	((b+BPC-1)/BPC)
XX! 
XX! #define TEST(b)		BITTEST(flags,b)
XX! #define SET(b)		BITSET(flags,b)
XX! #define CLEAR(b)	BITCLEAR(flags,b)
XX! #define FLAGS		(1<<BPC)
XX! 
XX! /* These macros permit the shortens the short circuiting of
XX!  * complicated boolean expressions. This is particularly
XX!  * useful when working with the flags since these are
XX!  * read-only.
XX   */
XX! #define BOOL(b)		static char b = 0
XX! #define EVAL(b,a)	((b ? b : (b = (a)+1)) > 1)
XX  
XX! /* A descriptor is kept for each file in the directory. The
XX!  * descriptors are linked together in a linked list.
XX   */
XX! struct direntry {
XX!   struct direntry *next;	/* link list */
XX!   char *name;			/* name of entry */
XX!   char *suffix;			/* entry suffix */
XX!   int length;			/* length of name and suffix */
XX!   struct direntry *parent;	/* pointer to parent */
XX!   struct stat *status;		/* pointer to status */
XX! };
XX  
XX! typedef struct direntry DIRENTRY;	/* entry */
XX! typedef struct {
XX!   DIRENTRY *head;		/* head of list */
XX!   DIRENTRY **tail;		/* insertion point at tail */
XX! } DIRLIST;			/* list of entries */
XX! 
XX! #define EMPTY_dl(d)	((d).head=(DIRENTRY *)NIL,(d).tail=(&(d).head))
XX! #define APPEND_dl(d,p)	(*(d).tail=(p),(d).tail=(&(p)->next))
XX! #define TIE_dl(d,p)	APPEND_dl(d,p); \
XX! 		while (*(d).tail) (d).tail=(&(*(d).tail)->next)
XX! #define HEAD_dl(d)	(d).head
XX! #define LINKOFFSET	(OFFSETOF(DIRENTRY, next))
XX! 
XX! /* Name statistics are required to support multi-column output.
XX!  * The statistics are used to compute the optimal number of
XX!  * columns required for output.
XX   */
XX! typedef struct namestats {
XX!   int n;		/* number of entries */
XX!   int minwidth;		/* minimum width seen */
XX!   int maxwidth;		/* maximum width seen */
XX! } NAMESTATS;
XX  
XX! #define INIT_NS(x)	((x).n = 0, (x).minwidth = INT_MAX, (x).maxwidth = 0)
XX! #define MAX_NS(x,y)	((x)>(y)?(x):(y))
XX! #define MIN_NS(x,y)	((x)<(y)?(x):(y))
XX! #define UPDATE_NS(x,w)	((x).n++, \
XX! 			 (x).minwidth = MIN_NS((x).minwidth, (w)), \
XX!                          (x).maxwidth = MAX_NS((x).maxwidth, (w)))
XX! 
XX! /* These status bits are to help compute the correct suffix to append
XX!  * to a file name listing. The current working directory is required
XX!  * when following relative symbolic links.
XX   */
XX! #define LF_NORMAL	0x00		/* Normal unknown disposition */
XX! #define LF_SYMLINK	0x01		/* Known to be a symbolic link */
XX! #define LF_BADCWD	0x02		/* Current directory wrong */
XX  
XX! /* Function Pointers */
XX  
XX! typedef int (*statfunc) P((const char *, struct stat *));
XX! typedef int (*cmpfunc) P((void *, void *));
XX! typedef int (*strlenfunc) P((CONST char *));
XX! typedef void (*putstrfunc) P((char *));
XX! 
XX! /* External Functions */
XX! 
XX! int getopt P((int, char **, char *));	/* parse the options */
XX! 
XX! #ifdef	TERMCAP
XX! int tgetent P((char *, char *));/* get entry from termcap database */
XX! int tgetnum P((char *));	/* get numeric capability */
XX! #endif
XX! 
XX! /* Symbolic Links. */
XX! 
XX! #ifdef		S_IFLNK
XX! # define OPAQUESTAT	((statfunc) lstat)
XX! #else
XX! # define OPAQUESTAT	((statfunc) stat)
XX! #endif
XX! #define TRANSPARENTSTAT	((statfunc) stat)
XX! 
XX! /* Permission Classes */
XX! 
XX! #define	PERMCLASSES	3	/* Number of permission classes */
XX! #define	PERMUSR		2
XX! #define	PERMGRP		1
XX! #define	PERMOTH		0
XX! 
XX! #define	PERMBITS	3	/* Number of bits per class */
XX! 
XX! /* Permission Strings */
XX! 
XX! #define PERM_NORMAL	(0 * (1 << PERMBITS) * sizeof(permstrings[0]))
XX! #define PERM_SUID	(1 * (1 << PERMBITS) * sizeof(permstrings[0]))
XX! #define PERM_STICKY	(2 * (1 << PERMBITS) * sizeof(permstrings[0]))
XX! #ifdef	_SYSV
XX! # define PERM_LOCK	(3 * (1 << PERMBITS) * sizeof(permstrings[0]))
XX! #endif
XX! 
XX! static char permstrings[][PERMBITS + 1] = {	/* permission strings */
XX! 	      "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"
XX! 	     ,"--S", "--s", "-wS", "-ws", "r-S", "r-s", "rwS", "rws"
XX! 	     ,"--T", "--t", "-wT", "-wt", "r-T", "r-t", "rwT", "rwt"
XX! #ifdef	_SYSV
XX! 	     ,"--l", "--s", "-wl", "-ws", "r-l", "r-s", "rwl", "rws"
XX! #endif
XX! };
XX! 
XX! /* Symbolic link indicator. */
XX! 
XX! char linkpointer[] = LINKPOINTER;/* common link pointer string */
XX! #define ARROW		(linkpointer)
XX! #define ARROWLENGTH	(sizeof(ARROW)-1)
XX! 
XX! /* External Variables. */
XX! 
XX! extern int optind;		/* next argument */
XX! extern int errno;		/* error code */
XX! extern int sys_nerr;		/* errors */
XX! extern char *sys_errlist[];	/* errors by name */
XX! 
XX! /* Forward declarations. */
XX! 
XX! void acrosspage P((DIRENTRY *, DIRLIST *, NAMESTATS *));/* list across */
XX! void downpage P((DIRENTRY *, DIRLIST *, NAMESTATS *));	/* list down */
XX! void streamoutput P((DIRENTRY *, DIRLIST *));	/* stream output */
XX! void dolsopts P((void));	/* do environment variable */
XX! void docmdname P((char *));	/* do command name aliasing */
XX! void parse P((int, char **));	/* parse argument list */
XX! void setflag P((int));		/* set flag */
XX! void checkflag P((int, char *));/* check flag for incompatibilies */
XX! void init P((void));		/* initialise globals */
XX! void initpath P((DIRENTRY *));	/* initialise pathname */
XX! void initcols P((void));	/* initialise columns */
XX! int stringlength P((CONST char *));/* length of string with feeling */
XX! void printstring P((char *));	/* print string without feeling */
XX! void bprintstring P((char *));	/* print string with feeling */
XX! void qprintstring P((char *));	/* print string with feeling */
XX! unsigned long bytestoblk P((struct stat *));	/* convert bytes to blks */
XX! void error P((char *));		/* error message with prefix */
XX! FILESYSTEM *scanmtab P((void));	/* create file system database */
XX! void date P((time_t));		/* make date readable */
XX! char *makepath P((DIRENTRY *));	/* form the path */
XX! void longprint P((struct stat *));	/* long format */
XX! void printentry P((DIRENTRY *, DIRENTRY *, int, int));	/* print this entry */
XX! int optcols P((DIRLIST *, NAMESTATS *, DIRENTRY **, int **));
XX! 				/* optimise number of columns */
XX! DIRENTRY *newentry P((char *));	/* malloc a new entry */
XX! void freelist P((DIRLIST *));	/* free entries */
XX! void freeentry P((DIRENTRY *));	/* free an entry */
XX! int alphacmp P((DIRENTRY *, DIRENTRY *));/* alphabetic comparison */
XX! int mtimecmp P((DIRENTRY *, DIRENTRY *));/* compare by modification time */
XX! int ctimecmp P((DIRENTRY *, DIRENTRY *));/* compare by change time */
XX! int atimecmp P((DIRENTRY *, DIRENTRY *));/* compare by access time */
XX! void list P((DIRENTRY *, DIRLIST *, NAMESTATS *));/* file listing routine */
XX! void suffix P((DIRENTRY *, int));	/* do suffixes */
XX! int filestat P((int, statfunc, char *, struct stat *));	/* get status of file */
XX! void *safemalloc P((size_t));	/* malloc with feeling */
XX! DIRENTRY *makelist P((char *, NAMESTATS *,
XX! 	       unsigned long *));	/* create list of entries */
XX! void *lsort P((void *, int, cmpfunc));	/* linked list sort */
XX! 
XX! #ifdef	S_IFLNK
XX! char *followlink P((char *, int *));	/* follow symbolic link */
XX! #endif
XX! 
XX! /* Uninitialised Globals. */
XX! 
XX! DIRLIST rlist;			/* temporary recursive list */
XX! DIRLIST dlist;			/* list of directories */
XX! time_t today;			/* today's date */
XX! cmpfunc compare;		/* sort criteria */
XX! strlenfunc strlength;		/* (visible) string length */
XX! putstrfunc putstring;		/* (visible) string output */
XX! int columns;			/* number of columns */
XX! char *pathname;			/* current path name */
XX! FILESYSTEM *filesystems;	/* file system data base */
XX! FILESYSTEM *cfs;		/* current file system */
XX! 
XX! /* Initialised Globals. */
XX! 
XX! unsigned char flags[BITCHARS(FLAGS)] = { 0 }; /* switches */
XX! int exitstatus = EXIT_SUCCESS;                /* exit status */
XX! char cwd[2 * PATH_MAX + 1] = {0};             /* cwd and current pathname */
XX! int extrawidth = INTERSPACE;	/* implied extra space to add */
XX! char blanks[] =			/* blanks for quick padding */
XX! "                                                               ";
XX! char *incompatible[] = {	/* mutually exclusive flags */
XX! 		"aA", "mx1Cglno", "bq", "pF", "cu", (char *) NIL
XX! };
XX! char optlist[] = "abcdfgilmnopqrstux01ACFLRS";/* list of options */
XX! char *summary[] = {		/* summary of options */
XX! "",
XX! "a  All files             A  All except . and ..   R  Recursive",
XX! "d  No directory scan     f  Force directory scan  L  Opaque symlink",
XX! "0  Reset options",
XX! "",
XX! "l  Long format           g  Print group only      o  Print owner only",
XX! "x  Multicolumn across    C  Multicolumn down      S  Squeeze columns",
XX! "1  Single column         m  Stream format",
XX! "",
XX! "t  Sort by time          r  Reverse sort",
XX! "c  Status change time    u  Last access time",
XX! "",
XX! "i  Print inode number    s  Print size in blocks  n  Numeric uid and gid",
XX! "p  Suffix /              F  Suffix / @ = | *",
XX! "",
XX! "b  Non-graphic \\ddd      q  Non-graphic ?",
XX! (char *) NIL
XX! };
XX! 
XX! int main F2(int, argc, char **, argv)
XX  {
XX!   DIRENTRY *dp;			/* directory scanner */
XX!   DIRLIST nlist;		/* list of files */
XX!   int showdir;			/* print directory name */
XX!   int notfirst;			/* printing first directory */
XX!   BOOL(dototal);		/* show totals */
XX!   BOOL(dostat);			/* need to do a stat */
XX!   int isdir;			/* current argument is a directory name */
XX!   int symlinked;		/* file a symbolic link */
XX!   char *absname;		/* absolute current path name */
XX!   NAMESTATS ns;			/* statistics */
XX  
XX!   unsigned long blk;		/* blks in total */
XX! #ifdef	S_IFLNK
XX!   struct stat lsb;		/* stat of link */
XX  #endif
XX  
XX! /* Initialise by emptying the directory lists */
XX!   EMPTY_dl(dlist), EMPTY_dl(nlist);
XX!   showdir = 0;
XX!   notfirst = 0;
XX! 
XX! /* Parse the command line */
XX!   dolsopts();
XX!   docmdname(argv[0]);
XX!   parse(argc, argv);
XX!   init();
XX!   if (TEST('C') || TEST('x') || TEST('m')) initcols();
XX! 
XX! /* Insert arguments into the current list */
XX!   INIT_NS(ns);
XX!   do {
XX! 
XX! 	dp = newentry((optind >= argc) ? DEFAULTDIR : argv[optind]);
XX! 	symlinked = LF_NORMAL;
XX! 
XX! 	if (EVAL(dostat, (!TEST('f') && !TEST('d')) ||
XX! 			  TEST('t') ||  TEST('g') ||
XX! 			  TEST('o') ||  TEST('s') ||
XX! 			  TEST('F') ||  TEST('p') ||
XX! 			  TEST('R') ||  TEST('i'))) {
XX! 		dp->status = (struct stat *)
XX! 			     safemalloc(sizeof(*dp->status));
XX! 		if (filestat(0, OPAQUESTAT, dp->name, dp->status)) {
XX! 			freeentry(dp);
XX! 			continue;
XX! 		}
XX! 	}
XX! 
XX! /* Determine if this argument is a directory */
XX! 	if (TEST('f'))
XX! 		isdir = 1;
XX! 
XX! 	else if (TEST('d'))
XX! 		isdir = 0;
XX! 
XX! 	else {
XX! 
XX! #ifdef	S_IFLNK
XX! 		if (!TEST('L') && S_ISLNK(dp->status->st_mode) &&
XX! 		    !filestat(1, TRANSPARENTSTAT, dp->name, &lsb) &&
XX! 		    S_ISDIR(lsb.st_mode)) {
XX! 			symlinked = LF_SYMLINK;
XX! 			*dp->status = lsb;
XX! 		}
XX  #endif
XX  
XX! 		if (!S_ISDIR(dp->status->st_mode))
XX! 			isdir = 0;
XX! 		else {
XX! 			if (compare == (cmpfunc) alphacmp) {
XX! 				free((FREE_T) dp->status);
XX! 				dp->status = NIL;
XX! 			}
XX! 			isdir = 1;
XX! 		}
XX  
XX  	}
XX! 	if (isdir) {
XX! 		if (HEAD_dl(dlist)) showdir = 1;
XX! 		APPEND_dl(dlist, dp);
XX  
XX! 		continue;
XX! 	}
XX! 
XX! /* This argument is not a directory */
XX! 	suffix(dp, symlinked | LF_BADCWD);
XX! 	UPDATE_NS(ns, dp->length);
XX! 	APPEND_dl(nlist, dp);
XX! 
XX!   } while (++optind < argc);
XX! 
XX! /* List all the non-directory files */
XX!   if (ns.n) {
XX! 	showdir = 1;
XX! 	notfirst = 1;
XX    }
XX!   HEAD_dl(nlist) = (DIRENTRY *) lsort((void *) HEAD_dl(nlist),
XX! 				      LINKOFFSET, compare);
XX!   list((DIRENTRY *) NIL, &nlist, &ns);
XX  
XX! /* List all directories */
XX!   if (!TEST('f'))
XX! 	HEAD_dl(dlist) = (DIRENTRY *) lsort((void *) HEAD_dl(dlist),
XX! 					    LINKOFFSET, compare);
XX  
XX!   dp = HEAD_dl(dlist);
XX!   initpath(dp);
XX!   while (dp) {
XX! 	freelist(&nlist);
XX! 	absname = makepath(dp);
XX  
XX! 	if (showdir) {
XX! 		if (notfirst) (void) putchar('\n');
XX! 		(void) printf("%s:\n", pathname);
XX! 	}
XX! 	HEAD_dl(nlist) = makelist(absname, &ns, &blk);
XX  
XX! 	if (EVAL(dototal, TEST('g') || TEST('o') || TEST('s')))
XX! 		(void) printf("total %lu\n", blk);
XX  
XX! 	list(dp, &nlist, &ns);
XX! 
XX! 	notfirst = showdir = 1;
XX! 	dp = dp->next;
XX!   }
XX! 
XX!   return exitstatus;
XX  }
XX  
XX! /* Scan the options from the environment variable. This is
XX!  * done in a similar fashion to the command line option
XX!  * scan but no errors are flagged.
XX   */
XX  
XX! void dolsopts F0()
XX! {
XX!   register char *env;		/* environment options */
XX!   register int sw;		/* switch from environment */
XX  
XX! /* Output to tty allows environment settable options */
XX!   if (isatty(fileno(stdout))) {
XX! 	setflag('q');
XX! 	if ((env = getenv(ENVNAME)) != NIL) {
XX! 		while ((sw = *env) > 0 && sw < FLAGS) {
XX! 			setflag(sw);
XX! 			env++;
XX! 		}
XX! 	}
XX!   }
XX! }
XX  
XX! /* Look at the command name. The following options are set
XX!  * according to the name:
XX!  *
XX!  *	Name		Option
XX!  *	ls		NONE
XX!  *	l		-m
XX!  *	ll		-l
XX!  *	lx		-x
XX!  *	lc		-C
XX!  *	lf		-F
XX!  *	lr		-R
XX   */
XX  
XX+ void docmdname F1(char *, name)
XX+ {
XX+   register char *bp;		/* point to basename */
XX  
XX!   if ((bp = strrchr(name, '/')) == NIL)
XX! 	bp = name;
XX!   else
XX! 	bp++;
XX! 
XX!   if (bp[0] != 0) {
XX! 	switch (bp[1]) {
XX! 	    case '\0':	setflag('m');	break;
XX! 	    case 'l':	setflag('l');	break;
XX! 	    case 'x':	setflag('x');	break;
XX! 	    case 'c':	setflag('C');	break;
XX! 	    case 'f':	setflag('F');	break;
XX! 	    case 'r':	setflag('R');	break;
XX! 	}
XX!   }
XX! }
XX! 
XX! /* Determine the number of columns on the output terminal.
XX!  * The environment variable COLUMNS is preferred. If this
XX!  * is not set, and output is to a terminal, the termcap database
XX!  * is consulted. Failing this, a default assumed.
XX   */
XX! void initcols F0()
XX! {
XX!   register char *env;		/* environment variable */
XX!   register int cols;		/* columns */
XX! #ifdef	TERMCAP
XX!   char tspace[1024];		/* termcap work space */
XX  #endif
XX  
XX! /* Check environment first */
XX!   if ((env = getenv(COLNAME)) != NIL && (cols = atoi(env)) > 0)
XX! 	columns = cols;
XX  
XX! #ifdef	TERMCAP
XX! /* Try termcap library */
XX!   else if ((env = getenv(TERMNAME)) != NIL &&
XX! 	 tgetent(tspace, env) > 0 &&
XX! 	 (cols = tgetnum("co")) > 0)
XX! 	columns = cols;
XX! #endif
XX  
XX!   else
XX! 	columns = COLUMNS;
XX! }
XX  
XX! /* Parse the command line arguments. This function will set
XX!  * the switches in the global variable flags. No interpretation
XX!  * of the switches is performed at this point.
XX   */
XX! 
XX! void parse F2(int, argc, char **, argv)
XX  {
XX!   register int swch;		/* switch character */
XX!   register int i;		/* index */
XX! 
XX!   while ((swch = getopt(argc, argv, optlist)) != EOF) {
XX!   	if (swch == '0') {
XX!   		for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++)
XX!   			flags[i] = 0;
XX!   	} else if (swch != '?')
XX! 		setflag(swch);
XX! 	else {
XX! 		fprintf(stderr, "Usage: %s [-%s] [names]\n", argv[0], optlist);
XX! 		for (i = 0; summary[i] != NIL; i++)
XX! 			fprintf(stderr, "%s\n", summary[i]);
XX! 		exit(EXIT_FAILURE);
XX  	}
XX+   }
XX  }
XX  
XX! /* Set the specified option switch. This function knows about
XX!  * mutually exclusive options and will turn off options which
XX!  * are not compatible with the current one.
XX   */
XX! 
XX! void setflag F1(int, ch)
XX  {
XX!   register char **p;		/* scanner */
XX  
XX!   for (p = incompatible; *p != NIL; p++) checkflag(ch, *p);
XX!   SET(ch);
XX! }
XX  
XX! /* Check the specified flag against the list of mutually exclusive
XX!  * flags. If the flag appears, then all other flags in the list are
XX!  * turned off. If not, then nothing is done.
XX!  */
XX  
XX! void checkflag F2(int, ch, register char *, p)
XX! {
XX!   if (strchr(p, ch) != NIL) {
XX! 	while (*p != 0) {
XX! 		if (*p++ != ch) CLEAR(p[-1]);
XX! 	}
XX!   }
XX  }
XX  
XX! /* Scan the switches and initialise globals. This function will
XX!  * do some preliminary work on the switches to determine which
XX!  * globals will be needed and also which switches need to be
XX!  * set or cleared in addition to the current settings.
XX   */
XX  
XX! void init F0()
XX  {
XX! /* Turn on -A if we're the super user */
XX!   if (!TEST('a') && getuid() == SUPER_USER) SET('A');
XX! 
XX! /* Visible string length */
XX!   strlength = TEST('b') ? stringlength : (strlenfunc) strlen;
XX! 
XX! /* Visible string output */
XX!   putstring = TEST('q') ? qprintstring : TEST('b') ? bprintstring : printstring;
XX! 
XX! /* Force raw directory listing */
XX!   if (TEST('f')) {
XX! 	CLEAR('l');
XX! 	CLEAR('n');
XX! 	CLEAR('o');
XX! 	CLEAR('g');
XX! 	CLEAR('t');
XX! 	CLEAR('s');
XX! 	CLEAR('r');
XX! 	CLEAR('F');
XX! 	CLEAR('p');
XX! 	CLEAR('A');
XX! 	SET('a');
XX    }
XX! 
XX! /* Sort criterion */
XX!   compare = (cmpfunc) (TEST('t') ? TEST('u') ? atimecmp
XX! 		                             : TEST('c') ? ctimecmp : mtimecmp
XX! 		                 : alphacmp);
XX! 
XX! /* Open the password and group files if required */
XX!   if (TEST('l') || TEST('n')) {
XX! 	SET('o');
XX! /* Use -DAST to suppress groups on ls -l  (V7 style). */
XX! #ifndef AST
XX! 	SET('g');
XX! #endif
XX    }
XX  
XX! /* Accumulate extra width if required */
XX!   if (TEST('i')) extrawidth += INODEWIDTH + 1;
XX!   if (TEST('s')) extrawidth += BLOCKWIDTH + 1;
XX  
XX! /* Get today's date */
XX!   if (TEST('o') || TEST('g')) today = time((time_t *) 0);
XX  
XX! /* Initialise file system data base */
XX!   if (TEST('g') || TEST('o') || TEST('s'))
XX! 	cfs = filesystems = scanmtab();
XX  }
XX  
XX! /* Form the name of the current directory. Before each directory
XX!  * is scanned, its absolute name is formed. The name of the
XX!  * current directory is prefixed to relative names to obtain
XX!  * this.
XX   */
XX! void initpath F1(DIRENTRY *, dp)
XX  {
XX!   if (dp == NIL || (dp->next == NIL && !TEST('R')))
XX! 	pathname = cwd;
XX!   else {
XX! 	if (getcwd(cwd, sizeof(cwd)) == NIL) {
XX! 	      error("cannot locate cwd");
XX! 	      exit(EXIT_FAILURE);
XX! 	}
XX! 	pathname = strchr(cwd, 0);
XX! 	pathname[0] = '/';
XX! 	pathname[1] = 0;
XX! 	pathname++;
XX!   }
XX! }
XX  
XX! /* Make a linked list of entries using specified directory. The
XX!  * directory is rewound before being scanned. The function
XX!  * returns a pointer to the head of the list of entries. The
XX!  * function gathers two important statistics as the list
XX!  * is created. It will return the width required to print
XX!  * the files, and also the number of files in the list.
XX!  *
XX!  * The list will be sorted according to the current sorting
XX!  * criteria.
XX!  */
XX  
XX! DIRENTRY *makelist F3(char *, dirname, NAMESTATS *, np, unsigned long *, blk)
XX! {
XX!   DIR *dirp;			/* directory to scan */
XX!   register struct dirent *cp;	/* current entry */
XX!   DIRLIST nlist;		/* files in directory */
XX!   register DIRENTRY *p;		/* new entry */
XX!   BOOL(dostat);			/* perform a stat */
XX!   BOOL(doblock);		/* check block sizes */
XX  
XX!   EMPTY_dl(nlist);
XX!   INIT_NS(*np);
XX!   *blk = 0;
XX  
XX!   if ((dirp = opendir(dirname)) == NIL || chdir(dirname)) {
XX! 	error(dirname);
XX! 	return NIL;
XX    }
XX!   while ((cp = readdir(dirp)) != NIL) {
XX! 	if (cp->d_name[0] != '.' || TEST('a') ||
XX! 	    (cp->d_name[1] != 0 && (cp->d_name[1] != '.' || cp->d_name[2] != 0)
XX! 	     && TEST('A'))) {
XX  
XX! 		p = newentry(cp->d_name);
XX  
XX! 		if (EVAL(dostat, TEST('t') || TEST('g') ||
XX! 				 TEST('o') || TEST('s') ||
XX! 				 TEST('F') || TEST('p') ||
XX! 				 TEST('R') || TEST('i'))) {
XX! 			p->status = (struct stat *)
XX! 				    safemalloc(sizeof(*p->status));
XX! 			if (filestat(0, OPAQUESTAT, p->name, p->status)) {
XX! 				freeentry(p);
XX! 				continue;
XX! 			}
XX! 		}
XX! 		suffix(p, LF_NORMAL);
XX  
XX! 		UPDATE_NS(*np, p->length);
XX  
XX! 		if (EVAL(doblock, TEST('g') || TEST('o') || TEST('s')))
XX! 			*blk += bytestoblk(p->status);
XX! 
XX! 		APPEND_dl(nlist, p);
XX! 	}
XX!   }
XX! 
XX! #ifndef		_MINIX
XX!   (void) closedir(dirp);
XX! #else
XX!   if (closedir(dirp)) error(dirname);
XX! #endif
XX! 
XX!   return TEST('f') ? HEAD_dl(nlist)
XX! 	: (DIRENTRY *) lsort((void *) HEAD_dl(nlist),
XX! 			     LINKOFFSET, compare);
XX  }
XX  
XX! /* This function performs does the formatting and output for ls(1).
XX!  * The function is passed a list of files (not necessarily sorted)
XX!  * to list. All files will be listed. . and .. removal should have
XX!  * been done BEFORE calling this function.
XX   */
XX  
XX! void list F3(DIRENTRY *, parent, DIRLIST *, lp, NAMESTATS *, np)
XX! {
XX!   if (np->n) {
XX  
XX! /* Empty recursive directory list */
XX! 	EMPTY_dl(rlist);
XX  
XX! /* Select the correct output format */
XX! 	if (TEST('m'))
XX! 		streamoutput(parent, lp);
XX! 	else if (!TEST('C'))
XX! 		acrosspage(parent, lp, np);
XX! 	else
XX! 		downpage(parent, lp, np);
XX! 
XX! 	(void) putchar('\n');
XX! 
XX! /* Check recursive list */
XX! 	if (HEAD_dl(rlist)) {
XX! 		if (!TEST('f'))
XX! 			HEAD_dl(rlist) = (DIRENTRY *)
XX! 					 lsort((void *) HEAD_dl(rlist),
XX! 					       LINKOFFSET, compare);
XX! 		TIE_dl(dlist, HEAD_dl(rlist));
XX! 	}
XX!   }
XX! }
XX! 
XX! /* List the entries across the page. Single column output is
XX!  * treated as a special case of this. This is the easiest
XX!  * since the list of files can be scanned and dumped.
XX!  */
XX! 
XX! void acrosspage F3(DIRENTRY *, parent, DIRLIST *, lp, NAMESTATS *, np)
XX  {
XX!   register DIRENTRY *p;		/* entries to print */
XX!   int cols;			/* columns to print in */
XX!   int *cw;			/* column widths */
XX!   register int colno;		/* which column we're printing */
XX! 
XX!   if (!TEST('x')) {
XX!     cols = 1;
XX!     cw = NIL;
XX!   } else {
XX!     cols = optcols(lp, np, (DIRENTRY **) NIL, &cw);
XX!   }
XX! 
XX!   for (colno = 0, p = HEAD_dl(*lp); p; p = p->next) {
XX! 	if (++colno > cols) {
XX! 		colno = 1;
XX! 		(void) putchar('\n');
XX! 	}
XX! 	printentry(parent, p, cw ? cw[colno-1] : np->maxwidth, colno != cols);
XX!   }
XX  }
XX  
XX! /* Print the entries down the page. This is the default format
XX!  * for multicolumn listings. It's unfortunate that this is
XX!  * the most acceptable to the user, but it causes the program
XX!  * a little grief since the list of files is not in the
XX!  * most convenient order. Most of this code is taken up
XX!  * with rearranging the list to suit the output format.
XX   */
XX! 
XX! void downpage F3(DIRENTRY *, parent, DIRLIST *, lp, NAMESTATS *, np)
XX  {
XX!   static DIRENTRY **c = NIL;	/* column pointers */
XX!   int *cw;			/* column width vector */
XX!   int cols;			/* columns to print in */
XX!   int rows;			/* number of rows per column */
XX!   register int i, j;		/* general counters */
XX  
XX!   if (c == NIL) {
XX! 	cols = (columns+INTERSPACE-1) / INTERSPACE;
XX! 	c = (DIRENTRY **) safemalloc(sizeof(*c) * cols);
XX!   }
XX! 
XX!   cols = optcols(lp, np, c, &cw);
XX!   rows = (np->n + cols - 1) / cols;
XX! 
XX! /* Scan and print the listing */
XX!   for (i = 0; i < rows; i++) {
XX! 	if (i) (void) putchar('\n');
XX! 
XX! 	for (j = 0; j < cols; j++) {
XX! 		if (c[j]) {
XX! 			printentry(parent, c[j],
XX! 				   cw ? cw[j] : np->maxwidth, j != cols - 1);
XX! 			c[j] = c[j]->next;
XX  		}
XX  	}
XX    }
XX! }
XX  
XX! /* List the files using stream format. This code looks a bit
XX!  * kludgy because it is necessary to KNOW how wide the next
XX!  * entry is going to be. If the width would case the printout
XX!  * to exceed the width of the display, the entry must be printed
XX!  * on the next line.
XX!  */
XX  
XX! void streamoutput F2(DIRENTRY *, parent, DIRLIST *, lp)
XX! {
XX!   register DIRENTRY *p;		/* entries to print */
XX!   int colno;			/* current column */
XX!   int midline;			/* in middle of line */
XX!   register int tw;		/* width of this entry */
XX!   int x;			/* inode calculation */
XX!   BOOL(dopretty);		/* pretty print */
XX!   unsigned long blk;		/* size in blks */
XX  
XX!   for (midline = colno = 0, p = HEAD_dl(*lp); p; p = p->next) {
XX  
XX! /* Nominal length of the name */
XX! 	tw = p->length;
XX  
XX! /* Pretty printing adds an extra character */
XX! 	if (EVAL(dopretty, TEST('F') || TEST('p')) &&
XX! 	    (S_ISDIR(p->status->st_mode) ||
XX! 	     (TEST('F') && (
XX! #ifdef	S_IFLNK
XX! 			   S_ISLNK(p->status->st_mode) ||
XX! #endif
XX! #ifdef	S_IFIFO
XX! 			   S_ISFIFO(p->status->st_mode) ||
XX! #endif
XX! #ifdef	S_IFSOCK
XX! 			   S_ISSOCK(p->status->st_mode) ||
XX! #endif
XX! 			   (p->status->st_mode & 0111) != 0))))
XX! 		tw++;
XX  
XX! /* Size will add to the length */
XX! 	if (TEST('s')) {
XX! 		blk = bytestoblk(p->status);
XX! 		do {
XX! 			tw++;
XX! 		} while ((blk /= 10) != 0);
XX! 		tw++;
XX! 	}
XX  
XX! /* Inode number adds to the length (plus the separating space) */
XX! 	if (TEST('i')) {
XX! 		x = p->status->st_ino;
XX! 		tw++;
XX! 		do
XX! 			tw++;
XX! 		while ((x /= 10) != 0);
XX! 	}
XX  
XX! /* There will be a separating comma */
XX! 	if (p->next) tw++;
XX  
XX! /* There will be a separating space */
XX! 	if (midline) tw++;
XX  
XX! /* Begin a new line if necessary in which case there is no separating space */
XX! 	if (colno + tw >= columns) {
XX! 		(void) putchar('\n');
XX! 		midline = 0;
XX! 		colno = 0;
XX! 		tw--;
XX  	}
XX+ 
XX+ /* Separate entries if required */
XX+ 	if (midline) (void) putchar(' ');
XX+ 
XX+ /* Now the entry proper */
XX+ 	printentry(parent, p, 0, 0);
XX+ 
XX+ /* Now the separating comma */
XX+ 	if (p->next) (void) putchar(',');
XX+ 
XX+ 	midline = 1;
XX+ 	colno += tw;
XX    }
XX  }
XX  
XX! /* Optimise the number of columns taken to print listing.
XX!  * Attempt to squeeze as many columns across the page as
XX!  * possible. Return a pointer to a width vector and also
XX!  * the number of columns to print. If the -S option is
XX!  * not in effect, the number of columns returned might
XX!  * be overoptimistic.
XX   */
XX! 
XX! int optcols F4(DIRLIST *, lp, NAMESTATS *, np, DIRENTRY **, c, int **, cwp)
XX  {
XX!   static int *cw = NIL;		/* column widths */
XX!   int ccw;			/* width of current column */
XX!   int scw;			/* sum of column widths */
XX!   int cols;			/* column count */
XX!   int rows;			/* row count */
XX!   register DIRENTRY *p;		/* list scanner */
XX!   register int i, j;
XX  
XX!   if (! TEST('S')) {
XX  
XX! /* Nominal number of columns */
XX! 	if ((cols = columns / (np->maxwidth + extrawidth)) == 0)
XX! 		cols = 1;
XX! 	*cwp = NIL;
XX  
XX!   } else {
XX  
XX! /* Allocate space for column widths */
XX! 	if (cw == NIL) {
XX! 		cols = (columns+INTERSPACE-1) / INTERSPACE;
XX! 		cw = (int *) safemalloc(sizeof(*cw) * cols);
XX! 	}
XX  
XX! /* Allocate maximum number of columns */
XX! 	if ((cols = columns / (np->minwidth + extrawidth)) == 0)
XX! 		cols = 1;
XX! 	*cwp = cw;
XX!   }
XX! 
XX!   if (cols > np->n) cols = np->n;
XX! 
XX! /* Distribute the names and compute the column widths */
XX!   if (c) {
XX! 	while (1) {
XX! 		rows = (np->n + cols - 1) / cols;
XX! 		cols = (np->n + rows - 1) / rows;
XX! 
XX! 		scw = cols * extrawidth;
XX! 		for (i = 0, p = HEAD_dl(*lp); p; i++) {
XX! 			c[i] = p;
XX! 			ccw = p->length;
XX! 			for (j = rows; j-- && p; p = p->next)
XX! 				if (ccw < p->length) ccw = p->length;
XX! 			if ((scw += ccw) > columns)
XX! 				if (cols > 1) break;
XX! 			if (cw) cw[i] = ccw;
XX! 		}
XX! 		if (cols <= 1 || scw <= columns) break;
XX! 		cols--;
XX  	}
XX+   } else if (TEST('S')) {
XX+ 	while (1) {
XX+ 		for (i = cols; i--; )
XX+ 			cw[i] = 0;
XX+ 		scw = cols * extrawidth;
XX+ 		for (i = 0, p = HEAD_dl(*lp); p; p = p->next) {
XX+ 			if (cw[i] < p->length) {
XX+ 				scw -= cw[i];
XX+ 				cw[i] = p->length;
XX+ 				if ((scw += cw[i]) > columns)
XX+ 					if (cols > 1) break;
XX+ 			}
XX+ 			if (++i == cols) i = 0;
XX+ 		}
XX+ 		if (cols <= 1 || scw <= columns) break;
XX+ 		cols--;
XX+ 	}
XX+   }
XX  
XX!   return cols;
XX! }
XX  
XX! /* Print this entry on stdout. No newline is appended to the
XX!  * output. This function localises all the transformations
XX!  * which have to be carried out to make the output readable.
XX!  * Columnar magic is done elsewhere.
XX!  */
XX  
XX! void printentry F4(DIRENTRY *, parent,
XX! 	    register DIRENTRY *, p,
XX! 	    int, w,
XX! 	    register int, padout)
XX! {
XX!   int pad;			/* pad count */
XX!   BOOL(dolong);			/* long print */
XX!   DIRENTRY *ep;			/* new entry for recursion */
XX! 
XX!   if (TEST('i')) {
XX! 	if (sizeof(p->status->st_ino) == sizeof(unsigned int))
XX! 	       printf("%*u ",  w ? INODEWIDTH : 0,
XX! 			         (unsigned int)  p->status->st_ino);
XX  	else
XX! 	       printf("%*lu ", w ? INODEWIDTH : 0,
XX! 			         (unsigned long) p->status->st_ino);
XX    }
XX!   if (TEST('s'))
XX! 	(void) printf("%*lu ", w ? BLOCKWIDTH : 0, bytestoblk(p->status));
XX  
XX!   if (EVAL(dolong, TEST('o') || TEST('g'))) longprint(p->status);
XX! 
XX! /* Print the name of this file */
XX!   (*putstring)(p->name);
XX!   (*putstring)(p->suffix);
XX! 
XX! /* Only pad it if the caller requires it */
XX!   if (padout && (pad = w - p->length + INTERSPACE) > 0) {
XX! 	do {
XX! 		padout = pad;
XX! 		if (padout > sizeof(blanks)-1) padout = sizeof(blanks)-1;
XX! 		(void) fputs(&blanks[(sizeof(blanks)-1)-padout], stdout);
XX! 	} while ((pad -= padout) != 0);
XX!   }
XX! 
XX! /* If recursion is required, add to list if it's a directory */
XX!   if (TEST('R') && S_ISDIR(p->status->st_mode) &&
XX!       (p->name[0] != '.' ||
XX!        (p->name[1] != 0 && (p->name[1] != '.' || p->name[2] != 0)))) {
XX! 	ep = newentry(p->name);
XX! 	ep->parent = parent;
XX! 	APPEND_dl(rlist, ep);
XX!   }
XX  }
XX  
XX! /* Format and print out the information for a long listing.
XX!  * This function handles the conversion of the mode bits
XX!  * owner, etc. It assumes that the status has been obtained.
XX   */
XX! 
XX! void longprint F1(register struct stat *, sp)
XX  {
XX!   register unsigned int permbits;	/* file access permissions */
XX!   char filecode;		/* code for type of file */
XX!   static struct passwd *pwent = NIL;	/* password entry */
XX!   static struct group *grent = NIL;	/* group entry */
XX!   char *perm[PERMCLASSES];	/* permissions ogu */
XX! 
XX!   if (S_ISREG(sp->st_mode))       filecode = '-';
XX!   else if (S_ISDIR(sp->st_mode))  filecode = 'd';
XX!   else if (S_ISBLK(sp->st_mode))  filecode = 'b';
XX!   else if (S_ISCHR(sp->st_mode))  filecode = 'c';
XX! #ifdef		S_IFIFO
XX!   else if (S_ISFIFO(sp->st_mode)) filecode = 'p';
XX! #endif
XX! #ifdef		S_IFLNK
XX!   else if (S_ISLNK(sp->st_mode))  filecode = 'l';
XX! #endif
XX! #ifdef		S_IFSOCK
XX!   else if (S_ISSOCK(sp->st_mode)) filecode = 's';
XX! #endif
XX!   else                            filecode = '?';
XX! 
XX!   permbits = USRGRPOTH(sp->st_mode);
XX! 
XX!   perm[PERMUSR] = permstrings[(permbits >> 6) & 7];
XX!   perm[PERMGRP] = permstrings[(permbits >> 3) & 7];
XX!   perm[PERMOTH] = permstrings[(permbits)      & 7];
XX! 
XX!   if (sp->st_mode & S_ISUID) perm[PERMUSR] += PERM_SUID;
XX!   if (sp->st_mode & S_ISGID)
XX! #ifdef	_SYSV
XX! 	perm[PERMGRP] += PERM_LOCK;
XX! #else				/* _SYSV */
XX! 	perm[PERMGRP] += PERM_SUID;
XX! #endif
XX! #ifdef	S_ISVTX
XX!   if (sp->st_mode & S_ISVTX) perm[PERMOTH] += PERM_STICKY;
XX! #endif
XX! 
XX!   (void) printf("%c%s%s%s%c %2d ",
XX! 	      filecode,
XX! 	      perm[PERMUSR], perm[PERMGRP], perm[PERMOTH],
XX! 	      ' ', sp->st_nlink);
XX! 
XX!   if (TEST('o')) {
XX! 	if (!TEST('n') && ((pwent && pwent->pw_uid == sp->st_uid) ||
XX! 			   (pwent = getpwuid(sp->st_uid)) != NIL))
XX! 		(void) printf("%-8.8s\t", pwent->pw_name);
XX! 	else
XX! 		(void) printf("%-8d\t", (int) sp->st_uid);
XX!   }
XX!   if (TEST('g')) {
XX! 	if (!TEST('n') && ((grent && grent->gr_gid == sp->st_gid) ||
XX! 			   (grent = getgrgid(sp->st_gid)) != NIL))
XX! 		(void) printf("%-8.8s\t", grent->gr_name);
XX! 	else
XX! 		(void) printf("%-8d\t", (int) sp->st_gid);
XX!   }
XX! 
XX! /* Now show how big the file is */
XX!   if (!S_ISCHR(sp->st_mode) && !S_ISBLK(sp->st_mode))
XX! 	(void) printf("%7lu ", (unsigned long) sp->st_size);
XX    else
XX! 	(void) printf(" %2d,%3d ", (int) (sp->st_rdev >> 8) & 0377,
XX! 		      (int) sp->st_rdev & 0377);
XX! 
XX! /* Now the date */
XX!   date(TEST('u') ? sp->st_atime : TEST('c') ? sp->st_ctime : sp->st_mtime);
XX  }
XX  
XX! /* Given the time convert it into human readable form. The month and
XX!  * day are always printed. If the time is within about the last half year,
XX!  * the hour and minute are printed, otherwise the year.
XX   */
XX  
XX! void date F1(time_t, t)
XX! {
XX!   struct tm *tmbuf;		/* output time */
XX  
XX!   tmbuf = localtime(&t);
XX!   (void) printf("%.3s %2u ",
XX! 	 "JanFebMarAprMayJunJulAugSepOctNovDec" + tmbuf->tm_mon * 3,
XX! 	      (unsigned) tmbuf->tm_mday);
XX!   if (t <= today && (today - t) <= HALFYEAR)
XX! 	(void) printf("%02u:%02u ", (unsigned) tmbuf->tm_hour,
XX! 		      (unsigned) tmbuf->tm_min);
XX!   else
XX! 	(void) printf("%5d ", tmbuf->tm_year + BASEYEAR);
XX! }
XX! 
XX! /* Chase the parent pointers and make a path. This path is
XX!  * used to locate the current directory. The function returns
XX!  * the absolute pathname to the caller. The pathname relative
XX!  * to the directory specified by the user is available from
XX!  * the global variable pathname.
XX   */
XX! 
XX! char *makepath F1(DIRENTRY *, p)
XX  {
XX!   char tmppath[PATH_MAX + 1];	/* build it here */
XX!   register char *cp;		/* pointer to tmppath */
XX!   register char *cq;		/* pointer into name */
XX!   char *cr;			/* temporary pointer */
XX!   char absolute;		/* / for absolute file names */
XX  
XX! /* Work your way back up to the root */
XX!   for (cp = tmppath, *cp++ = 0, absolute = 0; p; p = p->parent) {
XX! 	for (cq = p->name, absolute = *cq; *cq; *cp++ = *cq++);
XX! 	*cp++ = 0;
XX    }
XX  
XX! /* Now flip the order */
XX!   for (cq = pathname, --cp; ; cp = cr) {
XX! 	while (*--cp);
XX! 	for (cr = cp++; *cp; *cq++ = *cp++);
XX! 	if (cr == tmppath) break;
XX! 	if (cq[-1] != '/') *cq++ = '/';
XX!   }
XX!   *cq = 0;
XX!   return absolute == '/' ? pathname : cwd;
XX! }
XX  
XX! /* Allocate memory for a new entry. Memory is allocated and
XX!  * filled in. The next, parent and status pointers are set
XX!  * to null. The function returns a pointer to the new entry.
XX!  */
XX  
XX! DIRENTRY *newentry F1(char *, name)
XX! {
XX!   register DIRENTRY *p;		/* pointer to entry */
XX! 
XX!   p = (DIRENTRY *) safemalloc(sizeof(*p));
XX!   p->name = (char *) safemalloc(strlen(name) + 1);
XX!   (void) strcpy(p->name, name);
XX!   p->suffix = NIL;
XX!   p->next = NIL;
XX!   p->parent = NIL;
XX!   p->status = NIL;
XX!   return p;
XX  }
XX  
XX! /* Free the memory associated with list of elements. The function
XX!  * assumes all memory has been allocated using malloc(), so that
XX!  * free() will work without suffering a heart attack. The list
XX!  * header is set to null before returning.
XX   */
XX! 
XX! void freelist F1(DIRLIST *, lp)
XX  {
XX!   register DIRENTRY *ep, *nep;
XX  
XX!   for (ep = HEAD_dl(*lp); ep; ep = nep) {
XX! 	nep = ep->next;
XX! 	freeentry(ep);
XX!   }
XX!   EMPTY_dl(*lp);
XX! }
XX  
XX! /* Free the memory associated with a directory entry. Remember that
XX!  * all the memory should have been allocated using malloc().
XX!  */
XX  
XX! void freeentry F1(register DIRENTRY *, p)
XX! {
XX!   if (p) {
XX! 	if (p->name) free((FREE_T) p->name);
XX! 	if (p->suffix && p->suffix[0] != 0 && p->suffix[1] != 0)
XX! 		free((FREE_T) p->suffix);
XX! 	if (p->status) free((FREE_T) p->status);
XX! 	free((FREE_T) p);
XX    }
XX+ }
XX  
XX! /* Compare entries in the file list. Pointers to two entries are
XX!  * expected as arguments (non null pointers). Compare the entries
XX!  * and return -1, 0 or 1 depending on whether the first argument
XX!  * is less than, equal to or greater than the second.
XX!  */
XX! 
XX! int alphacmp F2(DIRENTRY *, p, DIRENTRY *, q)
XX! {
XX!   register int rv = strcmp(p->name, q->name);
XX! 
XX!   return TEST('r') ? -rv : rv;
XX  }
XX  
XX! /* Compare entries on the basis of access time. Pointers to
XX!  * two entries are expected as arguments. It is assumed that the status
XX!  * has been obtained. The routine will return -1, 0 or 1 depending
XX!  * on whether the first argument is later than, equal to or earlier
XX!  * than the second.
XX   */
XX! 
XX! int atimecmp F2(DIRENTRY *, p, DIRENTRY *, q)
XX  {
XX!   register int rv;		/* comparison result */
XX!   long delta = p->status->st_atime - q->status->st_atime;
XX  
XX!   rv = delta > 0 ? -1 : delta ? 1 : 0;
XX  
XX!   return TEST('r') ? -rv : rv;
XX  }
XX  
XX! /* Compare entries on the basis of status change time. Pointers to
XX!  * two entries are expected as arguments. It is assumed that the status
XX!  * has been obtained. The routine will return -1, 0 or 1 depending
XX!  * on whether the first argument is later than, equal to or earlier
XX!  * than the second.
XX!  */
XX! 
XX! int ctimecmp F2(DIRENTRY *, p, DIRENTRY *, q)
XX  {
XX!   register int rv;		/* comparison result */
XX!   long delta = p->status->st_ctime - q->status->st_ctime;
XX  
XX!   rv = delta > 0 ? -1 : delta ? 1 : 0;
XX  
XX!   return TEST('r') ? -rv : rv;
XX  }
XX  
XX! /* Compare entries on the basis of modification time. Pointers to
XX!  * two entries are expected as arguments. It is assumed that the status
XX!  * has been obtained. The routine will return -1, 0 or 1 depending
XX!  * on whether the first argument is later than, equal to or earlier
XX!  * than the second.
XX!  */
XX! 
XX! int mtimecmp F2(DIRENTRY *, p, DIRENTRY *, q)
XX  {
XX!   register int rv;		/* comparison result */
XX!   long delta = p->status->st_mtime - q->status->st_mtime;
XX  
XX!   rv = delta > 0 ? -1 : delta ? 1 : 0;
XX  
XX!   return TEST('r') ? -rv : rv;
XX  }
XX  
XX! /* Append file name suffix. The suffix can be a simple file type
XX!  * indicator or can be the full path name if it is a symbolic
XX!  * link. If LF_SYMLINK is set, the entry is assumed to be a symbolic
XX!  * link. In this case, no further stat is performed and the entry
XX!  * in p->status is assumed to be that of the real file (not the link).
XX!  * If LF_BADCWD is set, the current working directory may not be
XX!  * correct for parsing the symbolic link. In this case, cwd[] and
XX!  * pathname are used as a scratch area for computing the correct name.
XX!  */
XX! 
XX! void suffix F2(register DIRENTRY *, p, int, linkflags)
XX  {
XX!   char *type;			/* file type */
XX!   BOOL(showtype);		/* show file type */
XX! #ifdef		S_IFLNK
XX!   BOOL(dolink);			/* follow link */
XX!   char *link;			/* link to */
XX!   char *u, *v, *w;		/* link name processing pointers */
XX!   int ltextlen;			/* length of link text */
XX!   struct stat lsb;		/* link stat buffer */
XX! #endif
XX  
XX!   p->length = (*strlength)(p->name);
XX  
XX! #ifdef		S_IFLNK
XX!   link = NIL;
XX! 
XX!   if (EVAL(dolink, TEST('o') || TEST('g')) &&
XX!       ((linkflags & LF_SYMLINK) != 0 || S_ISLNK(p->status->st_mode))) {
XX! 
XX! 	if ((link = followlink(p->name, &ltextlen)) != NIL) {
XX! 	    p->length += ARROWLENGTH + (*strlength)(link);
XX! 	    p->suffix = (char *) safemalloc(ltextlen + ARROWLENGTH + 2);
XX! 
XX! 	    u = link;
XX! 
XX! 	    if ((linkflags & LF_BADCWD) != 0 && link[0] != '/') {
XX! 	    	for (u = w = cwd, v = p->name; (*u = *v) != 0; u++, v++)
XX! 		    if (*u == '/')
XX! 			w = u+1;
XX! 		for (u = w, v = link; (*u = *v) != 0; u++, v++)
XX! 		    continue;
XX! 		u = cwd;
XX! 	    }
XX! 
XX! 	    if ((linkflags & LF_SYMLINK) == 0 && !TEST('L') &&
XX! 		!filestat(1, OPAQUESTAT, u, &lsb)) {
XX! 		linkflags |= LF_SYMLINK;
XX! 		*p->status = lsb;
XX! 	    }
XX! 
XX! 	    if ((linkflags & LF_SYMLINK) != 0) {
XX! 		(void) strcpy(p->suffix, ARROW);
XX! 		(void) strcpy(p->suffix+ARROWLENGTH, link);
XX! 	    }
XX! 	}
XX!   }
XX! #endif
XX! 
XX!   type = "";
XX!   if (EVAL(showtype, TEST('F') || TEST('p'))) {
XX! 	if (S_ISDIR(p->status->st_mode))
XX! 		type = "/";
XX! 	else if (TEST('F')) {
XX! 		if (p->status->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) type = "*";
XX! #ifdef		S_IFIFO
XX! 		if (S_ISFIFO(p->status->st_mode)) type = "|";
XX! #endif
XX! #ifdef		S_IFLNK
XX! 		if (S_ISLNK(p->status->st_mode)) type = "@";
XX! #endif
XX! #ifdef		S_IFSOCK
XX! 		if (S_ISSOCK(p->status->st_mode)) type = "=";
XX! #endif
XX! 	}
XX!   }
XX!   p->length += strlen(type);
XX! 
XX! #ifdef	S_IFLNK
XX!   if (link == NIL)
XX! 	p->suffix = type;
XX!   else if ((linkflags & LF_SYMLINK) != 0)
XX! 	strcpy(p->suffix+ARROWLENGTH+ltextlen, type);
XX!   else {
XX! 	(void) strcpy(p->suffix, type);
XX! 	(void) strcat(p->suffix+1, ARROW);
XX! 	(void) strcat(p->suffix+1+ARROWLENGTH, link);
XX!   }
XX! #else
XX!   p->suffix = type;
XX! #endif
XX  }
XX  
XX! /* Follow a symbolic link and return the name of the file
XX!  * to which it points. The function will return a pointer
XX!  * to a static area.
XX!  */
XX! 
XX! #ifdef		S_IFLNK
XX! char *followlink F2(char *, name, register int *, len)
XX  {
XX!   static char linkto[PATH_MAX + 1];	/* link to name */
XX! 
XX!   if ((*len = readlink(name, linkto, sizeof(linkto) - 1)) < 0) {
XX! 	error(name);
XX! 	return NIL;
XX!   }
XX!   linkto[*len] = 0;
XX!   return linkto;
XX  }
XX  
XX! #endif
XX! 
XX! /* Get the status of a file prepending the path before calling
XX!  * stat. The function pointer should indicate which status function
XX!  * to call. Return 0 if successful, non-zero if the name cannot
XX!  * be found.
XX   */
XX! 
XX! int filestat F4(int, silent, statfunc, status, char *, name,
XX! 	 struct stat *, statbuf)
XX  {
XX!   if ((*status) (name, statbuf)) {
XX! 	if (!silent) {
XX! 		if (errno == ENOENT)
XX! 			(void) fprintf(stderr, "ls: %s not found\n", name);
XX! 		else
XX! 			error(name);
XX! 	}
XX! 	return 1;
XX!   }
XX!   return 0;
XX! }
XX  
XX! /* Compute the length of the string taking into account the
XX!  * form of output. String lengths will increase if the
XX!  * visible output flag has been specified.
XX!  */
XX  
XX! int stringlength F1(register CONST char *, s)
XX! {
XX!   register int i;		/* length */
XX  
XX!   for (i = 0; *s != 0; s++)
XX! 	if (TEST('b') && !isprint(*s))
XX! 		i += 4;
XX! 	else
XX! 		i++;
XX!   return i;
XX  }
XX  
XX! /* Print a string without any conversion.
XX!  */
XX! 
XX! void printstring F1(char *, s)
XX  {
XX!   (void) fputs(s, stdout);
XX! }
XX  
XX! /* Print a string converting invisible characters into question marks.
XX!  */
XX  
XX! void qprintstring F1(register char *, s)
XX! {
XX!   for (; *s; s++) {
XX! 	if (isprint(*s))
XX! 		(void) putchar(*s);
XX! 	else
XX! 		(void) putchar('?');
XX!   }
XX! }
XX  
XX! /* Print a string converting invisible characters into visible sequences.
XX!  */
XX! 
XX! void bprintstring F1(register char *, s)
XX! {
XX!   for (; *s; s++) {
XX! 	if (isprint(*s))
XX! 		(void) putchar(*s);
XX! 	else
XX! 		(void) printf("\\%03d", *s & ((1 << CHAR_BIT) - 1));
XX!   }
XX  }
XX  
XX! /* This function does a malloc() with feeling. If malloc() returns
XX!  * null, indicating no more memory, the function will fail with
XX!  * an error message. The function will return a pointer to the
XX!  * allocated memory.
XX   */
XX  
XX! void *safemalloc F1(size_t, n)
XX! {
XX!   register void *p;		/* malloc'ed region */
XX  
XX!   if ((p = (void *) malloc(n)) == NIL) {
XX! 	(void) fputs("ls: insufficient memory\n", stderr);
XX! 	exit(EXIT_FAILURE);
XX!   }
XX!   return p;
XX! }
XX! 
XX! /* Wrapper for perror to prefix error codes with program name.
XX!  */
XX! 
XX! void error F1(char *, e)
XX  {
XX!   int err;			/* saved error code */
XX  
XX!   err = errno;
XX!   (void) fprintf(stderr, "ls: %s: ", e);
XX!   errno = err;
XX!   perror("");
XX! }
XX  
XX! /* This is a two way merge sort, but non-recursive and using a binary
XX!  * comb to combine the sublists. The problem with the straightforward
XX!  * two way merge is that switching the output from one bin to another
XX!  * is time consuming. In this approach, bin[i] contains either zero,
XX!  * or (1<<i) sorted elements (except for the last bin which can hold
XX!  * any number of elements). When a bin overflows (it will always double
XX!  * in size), it is emptied and merged with the next bin (hence the
XX!  * doubling effect). This cascading is forced to stop at the last bin.
XX!  * When all elements have been placed in bins, all bins are merged
XX!  * yielding a sorted list. If the number of bins is too small, the
XX!  * sort collapses, in the limit, into an insertion sort.
XX!  *
XX!  * The first is a pointer to the first element of the list.
XX!  * The second argument is the byte offset from the element pointer to
XX!  * find the pointer to the next element in the list. The third
XX!  * argument is a pointer to a comparison function that returns -ve, zero
XX!  * and +ve respectively if the first element is less than, equal to
XX!  * or greater that the second element.
XX!  */
XX  
XX! #define NEXT(p)		(* (void **) ((char *) p + offset))
XX  
XX! void *lsort F3(void *, head, int, offset, cmpfunc, cmp)
XX! {
XX!   register void *rp, *rq;		/* merge pointers */
XX!   register void **lp;			/* merge insertion pointer */
XX!   register void **bp;			/* list header scanner */
XX!   void **ep;				/* last header bin */
XX!   void *p;				/* next element */
XX!   void *q;				/* current element */
XX!   void *bin[9+1];			/* list headers */
XX  
XX!   ep = &bin[sizeof(bin)/sizeof(bin[0])-1];
XX!   for (bp = &bin[0]; bp <= ep; bp++)
XX! 	*bp = 0;
XX! 
XX!   for (p = head; p != 0; *bp = p, p = q) {
XX! 	q = NEXT(p);
XX! 	NEXT(p) = 0;
XX! 
XX! 	for (bp = &bin[0]; ;bp++) {
XX! 	      if ((rp = *bp) != 0) {
XX! 		    rq  = p;
XX! 		    lp  = &p;
XX! 		    *bp = 0;
XX! 
XX! 		    for (;;) {
XX! 		      if ((*cmp)(rp, rq) < 0) {
XX! 			*lp = rp;
XX! 			lp = &NEXT(rp);
XX! 			if ((rp = NEXT(rp)) == 0) {
XX! 			  *lp = rq;
XX! 			  break;
XX! 			}
XX! 		      } else {
XX! 			*lp = rq;
XX! 			lp = &NEXT(rq);
XX! 			if ((rq = NEXT(rq)) == 0) {
XX! 			  *lp = rp;
XX! 			  break;
XX! 			}
XX! 		      }
XX! 		    }
XX! 	      } else if (q != 0 || bp == ep)
XX! 		    break;
XX! 	}
XX! 	if (bp == ep) bp--;
XX!   }
XX!   return ep[-1];
XX  }
XX  
XX! /***********************************************************************\
XX!  *                             Portable Code                           *
XX! \***********************************************************************/
XX! #endif
XX! 
XX! /***********************************************************************\
XX!  *                            Unportable Code                          *
XX! \***********************************************************************/
XX! #ifdef	PASS2
XX! /* Convert the size of a file (in bytes) to the number of
XX!  * kilobytes of storage used. This figure will include the
XX!  * number of indirect blocks used to store the file.
XX!  * The Minix code was lifted from the original Minix ls.
XX   */
XX  
XX! #ifdef		_MINIX
XX! static unsigned long v1_zone_group[] = {
XX!   (unsigned long) V1_NR_DZONES,
XX!   (unsigned long) V1_INDIRECTS,
XX!   (unsigned long) 0};
XX! #if V1_NR_TZONES - V1_NR_DZONES != 2
XX!   << Wrong number of version 1 indirects >>
XX! #endif
XX! 
XX! #ifdef V2_NR_DZONES
XX! static unsigned long v2_zone_group[] = {
XX!   (unsigned long) V2_NR_DZONES,
XX!   (unsigned long) V2_INDIRECTS,
XX!   (unsigned long) V2_INDIRECTS*V2_INDIRECTS,
XX!   (unsigned long) 0};
XX! #if V2_NR_TZONES - V2_NR_DZONES != 3
XX!   << Wrong number of version 2 indirects >>
XX! #endif
XX! #endif
XX! 
XX! static unsigned long *filestructure[] = {	/* file structure */
XX!   v1_zone_group,			/* default version 1 */
XX!   v1_zone_group,			/* version 1 */
XX! #ifdef V2_NR_DZONES
XX!   v2_zone_group,			/* version 2 */
XX! #endif
XX! };
XX! #endif
XX! 
XX! unsigned long bytestoblk F1(struct stat *, sp)
XX  {
XX! #ifdef		_BSD
XX!   return (sp->st_blocks * STD_BLK + BYTESPERBLK - 1) / BYTESPERBLK;
XX! #endif
XX  
XX! #ifdef		_SYSV
XX!   return (sp->st_blocks * STD_BLK + BYTESPERBLK - 1) / BYTESPERBLK;
XX! #endif
XX  
XX! #ifdef		_MINIX
XX!   unsigned long blocks;		/* accumulated blocks */
XX!   unsigned long fileb;		/* size of file in blocks */
XX!   unsigned int filetype;	/* type of file */
XX!   unsigned long *fsp;		/* structure of filesystem for this file */
XX!   int i, j;			/* zone table scanner */
XX! 
XX! #ifndef		USEMTAB
XX!   fsp = filestructure[0];
XX! #else
XX!   static dev_t baddev = NO_DEV;	/* previous bad file system */
XX!   extern FILESYSTEM *cfs;	/* current file system */
XX!   extern FILESYSTEM *filesystems; /* list of file systems */
XX! 
XX! /* Locate the file system */
XX!   if (cfs->dev == sp->st_dev)
XX! 	fsp = cfs->fs;
XX!   else if (sp->st_dev == baddev)
XX! 	fsp = filestructure[0];
XX!   else {
XX! 	for (cfs = filesystems; cfs != NIL && cfs->dev != sp->st_dev; )
XX! 		cfs = cfs->next;
XX! 	if (cfs != NIL)
XX! 		fsp = cfs->fs;
XX! 	else {
XX! 		(void) fprintf(stderr, "ls: device %d/%d not in /etc/mtab\n",
XX! 				       (sp->st_dev >> MAJOR) & BYTE,
XX! 				       (sp->st_dev >> MINOR) & BYTE);
XX! 		baddev = sp->st_dev;
XX! 		cfs = filesystems;
XX! 		fsp = filestructure[0];
XX! 	}
XX!   }
XX! #endif
XX! 
XX! /* Compute raw file size */
XX!   fileb = ((unsigned long) sp->st_size + STD_BLK - 1) / STD_BLK;
XX    blocks = fileb;
XX!   filetype = sp->st_mode;
XX! 
XX! /* Compute indirect block overhead */
XX!   if (fileb > fsp[0] && !S_ISBLK(filetype) && !S_ISCHR(filetype)) {
XX! 	fileb -= fsp[0];
XX! 	for (i = 1; fileb > fsp[i] && fsp[i] != 0; i++) {
XX! 		blocks += (fsp[i] - 1)/(fsp[1] - 1);
XX! 		fileb -= fsp[i];
XX! 	}
XX! 	blocks++;
XX! 	for (j = 1; j < i; j++)
XX! 		blocks += (fileb + fsp[j] - 1)/fsp[j];
XX!   }
XX!   return (blocks * STD_BLK + BYTESPERBLK - 1) / BYTESPERBLK;
XX! #endif
XX  }
XX+ 
XX+ /* Build a table of mounted files systems. For Minix, each mounted file
XX+  * system is characterised by the number of zone numbers, the number of
XX+  * directs and the number of indirects within the inodes. Return a
XX+  * pointer to a list of file system entries. If /etc/mtab is empty or
XX+  * doesn't exist, a dummy list is returned.
XX+  */
XX+ 
XX+ FILESYSTEM *scanmtab F0()
XX+ {
XX+ #ifdef		_BSD
XX+   return NIL;
XX+ #endif
XX+ 
XX+ #ifdef		_SYSV
XX+   return NIL;
XX+ #endif
XX+ 
XX+ #ifdef		_MINIX
XX+ #ifndef		USEMTAB
XX+   return NIL;
XX+ #else
XX+   struct stat sb;			/* stat buffer */
XX+   FILESYSTEM *fs;			/* list of file systems */
XX+   FILESYSTEM *fsp;			/* pointer to file system entry */
XX+   int version;				/* file system version */
XX+   struct mntent *mp;			/* mounted file system */
XX+   FILE *mf;				/* mtab scanner */
XX+   static FILESYSTEM dummyfs = {NIL, NO_DEV, NIL};
XX+ 
XX+   if ((mf = setmntent(MTAB, "r")) == NIL) {
XX+     (void) fputs("ls: cannot access /etc/mtab\n", stderr);
XX+     return &dummyfs;
XX+   }
XX+ 
XX+   fs = NIL;
XX+   while ((mp = getmntent(mf)) != NIL) {
XX+ 	if (stat(mp->mnt_fsname, &sb) < 0) {
XX+ 		(void) fprintf(stderr,
XX+ 		               "ls: cannot get status of %s\n", mp->mnt_fsname);
XX+ 		continue;
XX+ 	}
XX+ 	if (S_ISBLK(sb.st_mode) == 0) {
XX+ 		(void) fprintf(stderr,
XX+ 		               "ls: %s not a block device\n", mp->mnt_fsname);
XX+ 		continue;
XX+ 	}
XX+ 
XX+ 	version = atoi(mp->mnt_type);
XX+ 	if (version < 1 ||
XX+ 	    version > sizeof(filestructure)/sizeof(filestructure[0])-1) {
XX+ 		(void) fprintf(stderr,
XX+ 		               "%s has bad filesystem version\n", mp->mnt_fsname);
XX+ 		continue;
XX+ 	}
XX+ 	fsp = (FILESYSTEM *) safemalloc(sizeof(*fsp));
XX+ 	fsp->dev = sb.st_rdev;
XX+ 	fsp->next = fs;
XX+ 	fsp->fs = filestructure[version];
XX+ 	fs = fsp;
XX+   }
XX+   endmntent(mf);
XX+   return fs == NIL ? &dummyfs : fs;
XX+ #endif
XX+ #endif
XX+ }
XX+ 
XX+ /****************************************************\
XX+  *                 mntent library                    *
XX+  *                                                   *
XX+  * Most Minix systems won't have the mntent library, *
XX+  * so the code is included here. This library is     *
XX+  * preferred to the mtab library because the data    *
XX+  * structures are allocated dynamically and the      *
XX+  * data space can be re-used later by ls.            *
XX+ \****************************************************/
XX+ #ifdef _MINIX
XX+ #ifndef USEMNTENTLIB
XX+ 
XX+ #include <string.h>
XX+ 
XX+ /* Read the next entry from the mtab file. The entry is parsed and returned
XX+  * as a struct mntent. A static structure is returned. Return NULL on end
XX+  * of file or error.
XX+  */
XX+ struct mntent *getmntent(mf)
XX+ FILE *mf;
XX+ {
XX+   int c;
XX+   char *p;
XX+   static char line[128];		/* local line buffer */
XX+   static struct mntent mt;		/* local mtab entry */
XX+   static char mde[] = " ";		/* delimiter */
XX+ 
XX+   while (fgets(line, sizeof line, mf) != NIL) {
XX+ 	p = strchr(line, 0);
XX+ 	if (p[-1] == '\n') {
XX+ 		*--p = 0;
XX+ 	} else {
XX+ 		while ((c = getc(mf)) != 'n' && c != EOF)
XX+ 			continue;
XX+ 	}
XX+ 	if (line[0] == '#') continue;
XX+ 	if ((mt.mnt_fsname = strtok(line, mde)) != NIL &&
XX+ 	    (mt.mnt_dir    = strtok((char *) NIL, mde)) != NIL &&
XX+ 	    (mt.mnt_type   = strtok((char *) NIL, mde)) != NIL &&
XX+ 	    (mt.mnt_opts   = strtok((char *) NIL, mde)) != NIL)
XX+ 		return &mt;
XX+ 	break;
XX+   }
XX+   return NIL;
XX+ }
XX+ #endif
XX+ #endif
XX+ #endif
X/
Xecho x - machine.c.d
Xsed '/^X/s///' > machine.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/machine.c  crc=12873   2726	Sun Apr 25 21:35:06 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/machine.c  crc=10893   2895	Wed Nov  4 04:19:14 1992
XX***************
XX*** 15,24 ****
XX   */
XX  
XX  #include <minix/config.h>
XX- #include <stdio.h>
XX  #include <ctype.h>
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 15,28 ----
XX   */
XX  
XX  #include <minix/config.h>
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <stdio.h>
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 32,38 ****
XX  
XX    /* let ptr point to the last 4 characters of argv[0] */
XX    ptr = argv[0] + strlen(argv[0]) - 4;
XX!   if (strncmp(ptr, "chip", 4) == 0)
XX    {
XX  #if (CHIP == INTEL)
XX      if (argc == 1) {
XX--- 36,42 ----
XX  
XX    /* let ptr point to the last 4 characters of argv[0] */
XX    ptr = argv[0] + strlen(argv[0]) - 4;
XX!   if (strncmp(ptr, "chip", (size_t)4) == 0)
XX    {
XX  #if (CHIP == INTEL)
XX      if (argc == 1) {
XX***************
XX*** 87,92 ****
XX--- 91,97 ----
XX      }
XX      else
XX      if (strcmp(argv[1], "SUN_4") == 0) exit(0);
XX+     else if (strcmp(argv[1], "SUN_4_60") == 0) exit(0);
XX      else exit(1);
XX  #endif
XX  
XX***************
XX*** 127,130 ****
XX--- 132,136 ----
XX      exit(1);
XX  #endif
XX    }
XX+   return(0);
XX  }
X/
Xecho x - mail.c.d
Xsed '/^X/s///' > mail.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mail.c  crc=51538  15774	Sun Apr 25 21:35:06 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mail.c  crc=51892  17012	Mon Jan 18 14:30:51 1993
XX***************
XX*** 1,4 ****
XX--- 1,5 ----
XX  /*  mail - send/receive mail 		 Author: Peter S. Housel */
XX+ /* Version 0.2 of September 1990: added -e, -t, * options - cwr */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX***************
XX*** 9,14 ****
XX--- 10,19 ----
XX  #include <time.h>
XX  #include <setjmp.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <fcntl.h>
XX+ #include <unistd.h>
XX+ #include <sys/wait.h>
XX  #include <stdio.h>
XX  
XX  #ifdef DEBUG
XX***************
XX*** 32,49 ****
XX  #define MAXRCPT		100	/* maximum number of recipients */
XX  #define LINELEN		512
XX  
XX! /* #define MAILER		"/usr/bin/smail"	/* smart mailer */
XX  #define MAILERARGS		/* (unused) */
XX  
XX  #define UNREAD		1	/* 'not read yet' status */
XX  #define DELETED		2	/* 'deleted' status */
XX  #define READ		3	/* 'has been read' status */
XX  
XX- extern int optind;		/* getopt() globals */
XX- extern char *optarg;
XX- extern int errno;
XX- extern char *malloc();
XX- 
XX  struct letter {
XX    struct letter *prev, *next;	/* linked letter list */
XX    int status;			/* letter status */
XX--- 37,49 ----
XX  #define MAXRCPT		100	/* maximum number of recipients */
XX  #define LINELEN		512
XX  
XX! /* #define MAILER		"/usr/bin/smail"	*/ /* smart mailer */
XX  #define MAILERARGS		/* (unused) */
XX  
XX  #define UNREAD		1	/* 'not read yet' status */
XX  #define DELETED		2	/* 'deleted' status */
XX  #define READ		3	/* 'has been read' status */
XX  
XX  struct letter {
XX    struct letter *prev, *next;	/* linked letter list */
XX    int status;			/* letter status */
XX***************
XX*** 59,82 ****
XX  int usedrop = 1;		/* read the maildrop (no -f given) */
XX  int verbose = 0;		/* pass "-v" flag on to mailer */
XX  int needupdate = 0;		/* need to update mailbox */
XX  char mailbox[PATHLEN];		/* user's mailbox/maildrop */
XX  char tempname[PATHLEN] = "/tmp/mailXXXXXX";	/* temporary file */
XX  FILE *boxfp = NULL;		/* mailbox file */
XX  jmp_buf printjump;		/* for quitting out of letters */
XX  unsigned oldmask;		/* saved umask() */
XX  
XX! int deliver();
XX! FILE *makerewindable();
XX! int copy();
XX! void readbox(), printall(), interact(), savelet(), updatebox();
XX! void printlet(), doshell(), usage();
XX! void onint();
XX! char *basename(), *whoami();
XX! extern FILE *fopen(), *freopen(), *fdopen();
XX! extern struct passwd *getpwnam(), *getpwuid();
XX! extern char *getenv();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 59,94 ----
XX  int usedrop = 1;		/* read the maildrop (no -f given) */
XX  int verbose = 0;		/* pass "-v" flag on to mailer */
XX  int needupdate = 0;		/* need to update mailbox */
XX+ int msgstatus = 0;		/* return the mail status */
XX+ int distlist = 0;		/* include distribution list */
XX  char mailbox[PATHLEN];		/* user's mailbox/maildrop */
XX  char tempname[PATHLEN] = "/tmp/mailXXXXXX";	/* temporary file */
XX  FILE *boxfp = NULL;		/* mailbox file */
XX  jmp_buf printjump;		/* for quitting out of letters */
XX  unsigned oldmask;		/* saved umask() */
XX  
XX! extern int optind;
XX! extern char *optarg;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int deliver, (int count, char *vec []));
XX! _PROTOTYPE(FILE *makerewindable, (void));
XX! _PROTOTYPE(int copy, (FILE *fromfp, FILE *tofp));
XX! _PROTOTYPE(void readbox, (void));
XX! _PROTOTYPE(void printall, (void));
XX! _PROTOTYPE(void interact, (void));
XX! _PROTOTYPE(void onint, (int dummy));
XX! _PROTOTYPE(void savelet, (struct letter *let, char *savefile));
XX! _PROTOTYPE(void updatebox, (void));
XX! _PROTOTYPE(void printlet, (struct letter *let, FILE *tofp));
XX! _PROTOTYPE(void doshell, (char *command));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(char *basename, (char *name));
XX! _PROTOTYPE(char *whoami, (void));
XX! _PROTOTYPE(void dohelp, (void));
XX! _PROTOTYPE(int filesize, (char *name));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 89,101 ****
XX  
XX    oldmask = umask(022);		/* change umask for security */
XX  
XX!   while (EOF != (c = getopt(argc, argv, "epqrf:t:dv"))) switch (c) {
XX! 	    case 'e':
XX! 	    case 't':
XX! 		fprintf(stderr, "option not implemented yet\n");
XX! 		/* Because I don't know what they do */
XX! 		exit(1);
XX  
XX  	    case 'p':	++printmode;	break;
XX  
XX  	    case 'q':	++quitmode;	break;
XX--- 101,111 ----
XX  
XX    oldmask = umask(022);		/* change umask for security */
XX  
XX!   while (EOF != (c = getopt(argc, argv, "epqrf:tdv"))) switch (c) {
XX! 	    case 'e':	++msgstatus;	break;	
XX  
XX+ 	    case 't':	++distlist;	break;
XX+ 
XX  	    case 'p':	++printmode;	break;
XX  
XX  	    case 'q':	++quitmode;	break;
XX***************
XX*** 105,111 ****
XX  	    case 'f':
XX  		setuid(getuid());	/* won't need to lock */
XX  		usedrop = 0;
XX! 		strncpy(mailbox, optarg, PATHLEN - 1);
XX  		break;
XX  
XX  	    case 'd':	usemailer = 0;	break;
XX--- 115,121 ----
XX  	    case 'f':
XX  		setuid(getuid());	/* won't need to lock */
XX  		usedrop = 0;
XX! 		strncpy(mailbox, optarg, (size_t)(PATHLEN - 1));
XX  		break;
XX  
XX  	    case 'd':	usemailer = 0;	break;
XX***************
XX*** 127,132 ****
XX--- 137,149 ----
XX  
XX    D(printf("mailbox=%s\n", mailbox));
XX  
XX+   if (msgstatus) {
XX+ 	if (filesize(mailbox))
XX+ 		exit(0);
XX+ 	else
XX+ 		exit(1);
XX+   }
XX+ 
XX    readbox();
XX  
XX    if (printmode)
XX***************
XX*** 136,155 ****
XX  
XX    if (needupdate) updatebox();
XX  
XX!   exit(0);
XX  }
XX  
XX  int deliver(count, vec)
XX  int count;
XX  char *vec[];
XX  {
XX!   int i;
XX    int errs = 0;			/* count of errors */
XX    int dropfd;			/* file descriptor for user's drop */
XX    int created = 0;		/* true if we created the maildrop */
XX    FILE *mailfp;			/* fp for mail */
XX    struct stat stb;		/* for checking drop modes, owners */
XX!   void (*sigint) (), (*sighup) (), (*sigquit) ();	/* saving signal state */
XX    time_t now;			/* for datestamping the postmark */
XX    char sender[32];		/* sender's login name */
XX    char lockname[PATHLEN];	/* maildrop lock */
XX--- 153,176 ----
XX  
XX    if (needupdate) updatebox();
XX  
XX!   return(0);
XX  }
XX  
XX  int deliver(count, vec)
XX  int count;
XX  char *vec[];
XX  {
XX!   int i, j;
XX    int errs = 0;			/* count of errors */
XX    int dropfd;			/* file descriptor for user's drop */
XX    int created = 0;		/* true if we created the maildrop */
XX    FILE *mailfp;			/* fp for mail */
XX    struct stat stb;		/* for checking drop modes, owners */
XX! #ifdef __STDC__
XX!   void (*sigint)(int), (*sighup)(int), (*sigquit)(int);/* saving signal state */
XX! #else
XX!   void (*sigint) (), (*sighup) (), (*sigquit) ();      /* saving signal state */
XX! #endif
XX    time_t now;			/* for datestamping the postmark */
XX    char sender[32];		/* sender's login name */
XX    char lockname[PATHLEN];	/* maildrop lock */
XX***************
XX*** 173,179 ****
XX  
XX  	for (i = 0; i < count; ++i) *argp++ = vec[i];
XX  
XX! 	*argp = (char *) NULL;
XX  	execv(MAILER, argvec);
XX  	fprintf(stderr, "mail: couldn't exec %s\n", MAILER);
XX  	return -1;
XX--- 194,200 ----
XX  
XX  	for (i = 0; i < count; ++i) *argp++ = vec[i];
XX  
XX! 	*argp = NULL;
XX  	execv(MAILER, argvec);
XX  	fprintf(stderr, "mail: couldn't exec %s\n", MAILER);
XX  	return -1;
XX***************
XX*** 187,193 ****
XX    strcpy(sender, pw->pw_name);
XX  
XX    /* If we need to rewind stdin and it isn't rewindable, make a copy */
XX!   if (isatty(0) || (count > 1 && lseek(0, 0L, 0) < 0L)) {
XX  	mailfp = makerewindable();
XX    } else
XX  	mailfp = stdin;
XX--- 208,214 ----
XX    strcpy(sender, pw->pw_name);
XX  
XX    /* If we need to rewind stdin and it isn't rewindable, make a copy */
XX!   if (isatty(0) || (count > 1 && lseek(0, 0L, 0) == (off_t) -1)) {
XX  	mailfp = makerewindable();
XX    } else
XX  	mailfp = stdin;
XX***************
XX*** 260,269 ****
XX  	}
XX  	(void) time(&now);
XX  	fprintf(boxfp, "From %s %24.24s\n", sender, ctime(&now));
XX! 
XX! 	if ((copy(mailfp, boxfp) < 0) | (fclose(boxfp) != 0)) {
XX  		fprintf(stderr, "mail: error delivering to user %s", vec[i]);
XX! 		perror("");
XX  		++errs;
XX  	}
XX  	unlink(lockname);
XX--- 281,296 ----
XX  	}
XX  	(void) time(&now);
XX  	fprintf(boxfp, "From %s %24.24s\n", sender, ctime(&now));
XX! 	if (distlist) {
XX! 		fprintf(boxfp, "Dist: ");
XX! 		for (j = 0; j < count; ++j)
XX! 			if (getpwnam(vec[j]) != NULL && j != i)
XX! 				fprintf(boxfp, "%s ", vec[j]) ;
XX! 		fprintf(boxfp, "\n\n");
XX! 	}
XX! 	if ((copy(mailfp, boxfp) < 0) || (fclose(boxfp) != 0)) {
XX  		fprintf(stderr, "mail: error delivering to user %s", vec[i]);
XX! 		perror(" ");
XX  		++errs;
XX  	}
XX  	unlink(lockname);
XX***************
XX*** 291,297 ****
XX    int state;			/* ".\n" detection state */
XX  
XX    if (NULL == (tempfp = fopen(tempname, "w"))) {
XX! 	fprintf(stderr, "mail: can't create temporary file");
XX  	return NULL;
XX    }
XX  
XX--- 318,324 ----
XX    int state;			/* ".\n" detection state */
XX  
XX    if (NULL == (tempfp = fopen(tempname, "w"))) {
XX! 	fprintf(stderr, "mail: can't create temporary file\n");
XX  	return NULL;
XX    }
XX  
XX***************
XX*** 328,334 ****
XX    return tempfp;
XX  }
XX  
XX! copy(fromfp, tofp)
XX  FILE *fromfp, *tofp;
XX  {
XX    int c;			/* character being copied */
XX--- 355,361 ----
XX    return tempfp;
XX  }
XX  
XX! int copy(fromfp, tofp)
XX  FILE *fromfp, *tofp;
XX  {
XX    int c;			/* character being copied */
XX***************
XX*** 414,420 ****
XX    while (1) {
XX  	if (NULL == fgets(linebuf, sizeof linebuf, boxfp)) break;
XX  
XX! 	if (!strncmp(linebuf, "From ", 5)) {
XX  		if (NULL == (let = (struct letter *) malloc(sizeof(struct letter)))) {
XX  			fprintf(stderr, "Out of memory.\n");
XX  			exit(1);
XX--- 441,447 ----
XX    while (1) {
XX  	if (NULL == fgets(linebuf, sizeof linebuf, boxfp)) break;
XX  
XX! 	if (!strncmp(linebuf, "From ", (size_t)5)) {
XX  		if (NULL == (let = (struct letter *) malloc(sizeof(struct letter)))) {
XX  			fprintf(stderr, "Out of memory.\n");
XX  			exit(1);
XX***************
XX*** 440,447 ****
XX  void printall()
XX  {
XX    struct letter *let;
XX-   off_t current, limit;
XX-   int c;
XX  
XX    let = reversemode ? firstlet : lastlet;
XX  
XX--- 467,472 ----
XX***************
XX*** 458,464 ****
XX  void interact()
XX  {
XX    char linebuf[512];		/* user input line */
XX-   char *p;
XX    struct letter *let, *next;	/* current and next letter */
XX    int interrupted = 0;		/* SIGINT hit during letter print */
XX    int needprint = 1;		/* need to print this letter */
XX--- 483,488 ----
XX***************
XX*** 522,532 ****
XX  	    case '!':
XX  		doshell(linebuf + 1);
XX  		continue;
XX! #ifdef NOTDEF
XX! 	    case '?':
XX  		dohelp();
XX  		continue;
XX- #endif /* NOTDEF */
XX  	    case 'q':
XX  		return;
XX  	    case 'x':
XX--- 546,554 ----
XX  	    case '!':
XX  		doshell(linebuf + 1);
XX  		continue;
XX! 	    case '*':
XX  		dohelp();
XX  		continue;
XX  	    case 'q':
XX  		return;
XX  	    case 'x':
XX***************
XX*** 538,544 ****
XX    }
XX  }
XX  
XX! void onint()
XX  {
XX    longjmp(printjump, 1);
XX  }
XX--- 560,567 ----
XX    }
XX  }
XX  
XX! void onint(dummy)
XX! int dummy;	/* to satisfy ANSI compilers */
XX  {
XX    longjmp(printjump, 1);
XX  }
XX***************
XX*** 666,672 ****
XX    umask(oldmask);
XX  
XX    execl(shell, shell, "-c", command, (char *) NULL);
XX!   fprintf(stderr, "can't exec shell");
XX    exit(127);
XX  }
XX  
XX--- 689,695 ----
XX    umask(oldmask);
XX  
XX    execl(shell, shell, "-c", command, (char *) NULL);
XX!   fprintf(stderr, "can't exec shell\n");
XX    exit(127);
XX  }
XX  
XX***************
XX*** 680,686 ****
XX  char *name;
XX  {
XX    char *p;
XX-   extern char *rindex();
XX  
XX    if (NULL == (p = rindex(name, '/')))
XX  	return name;
XX--- 703,708 ----
XX***************
XX*** 696,699 ****
XX--- 718,744 ----
XX  	return pw->pw_name;
XX    else
XX  	return "nobody";
XX+ }
XX+ 
XX+ void dohelp()
XX+ {
XX+   FILE *fp;
XX+   char buffer[80];
XX+ 
XX+   if ( (fp = fopen(HELPFILE, "r")) == NULL)
XX+ 	fprintf(stdout, "can't open helpfile %s\n", HELPFILE);
XX+   else
XX+ 	while (fgets(buffer, 80, fp))
XX+ 		fputs(buffer, stdout);
XX+ }
XX+ 
XX+ int filesize(name)
XX+ char *name ;
XX+ {
XX+   struct stat buf;
XX+  
XX+   if (stat(name, &buf) == -1)
XX+ 	buf.st_size = 0L;
XX+ 
XX+   return (buf.st_size ? 1 : 0);
XX  }
X/
Xecho x - man.c.d
Xsed '/^X/s///' > man.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/man.c  crc=36513  18218	Sun Apr 25 21:35:07 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/man.c  crc=18293  19118	Wed Nov  4 04:19:14 1992
XX***************
XX*** 19,24 ****
XX--- 19,26 ----
XX  #include <string.h>
XX  #include <ctype.h>
XX  #include <termcap.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #ifndef INDEX_H
XX***************
XX*** 37,50 ****
XX    char page_name[NAME_SIZE];	/* name of manual page */
XX  };
XX  
XX! extern char ar_name[AR_NAME_SIZE];	/* name of man archive file */
XX! extern char ar_index[AR_NAME_SIZE];	/* name of index file */
XX! extern struct INDEX *index_buf;	/* contains indices */
XX! extern int max_index_nr;	/* number of indices in index_buf */
XX! 
XX! /* Should be a prototype */
XX! extern void read_index();
XX  #endif
XX  #ifndef DISPLAY_H
XX  #define DISPLAY_H
XX  
XX--- 39,50 ----
XX    char page_name[NAME_SIZE];	/* name of manual page */
XX  };
XX  
XX! char ar_name[AR_NAME_SIZE];	/* name of man archive file */
XX! char ar_index[AR_NAME_SIZE];	/* name of index file */
XX! struct INDEX *index_buf;	/* contains indices */
XX! int max_index_nr;		/* number of indices in index_buf */
XX  #endif
XX+ 
XX  #ifndef DISPLAY_H
XX  #define DISPLAY_H
XX  
XX***************
XX*** 72,84 ****
XX  #define	GOTOXY(x, y)		fputs(tgoto(CM, (x), (y)), stdout)
XX  #define reverse(on)		fputs((on)?SO:SE, stdout)
XX  #define clrscr()		fputs(CL, stdout)
XX- 
XX- /* Should be prototypes */
XX- extern void display();
XX- extern int gettoken();
XX- extern void set_cursor();
XX- extern void term_init();
XX- extern void term_exit();
XX  #endif
XX  
XX  /* Arguments for do_wait() */
XX--- 72,77 ----
XX***************
XX*** 89,106 ****
XX  #define DO_REVERSE	0x01	/* modes for do_wait() */
XX  #define DO_DELETE	0x02
XX  
XX- extern char *malloc();
XX- extern char *getenv();
XX- 
XX  /* Forward declaration: */
XX! extern void Exit();
XX! static void man();
XX! static void _man();
XX! static void choose();
XX! static int do_choose();
XX! static int do_wait();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 82,114 ----
XX  #define DO_REVERSE	0x01	/* modes for do_wait() */
XX  #define DO_DELETE	0x02
XX  
XX  /* Forward declaration: */
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void read_index, (void));
XX! _PROTOTYPE(static void man, (FILE *man_fd, char **man_pages));
XX! _PROTOTYPE(static void _man, (FILE *man_fd, char *man_page));
XX! _PROTOTYPE(static void choose, (FILE *man_fd));
XX! _PROTOTYPE(static int do_choose, (int max_x, int max_y));
XX! _PROTOTYPE(static int do_wait, (char *message, int mode));
XX! _PROTOTYPE(static int index_cmp, (const void *index1, const void *index2));
XX! _PROTOTYPE(static void _read_index, (int index_fd, int index_size));
XX! _PROTOTYPE(static void build_index, (char *ar_name, char *ar_index));
XX! _PROTOTYPE(static int find_name, (FILE *man_fd, FILE *index_fd));
XX! _PROTOTYPE(static int find_delim, (FILE *man_fd, int ch));
XX! _PROTOTYPE(static void scr_up, (int count));
XX! _PROTOTYPE(static void scr_down, (int count));
XX! _PROTOTYPE(static void disp_all, (void));
XX! _PROTOTYPE(static void disp_fill, (int first_y, int last_y));
XX! _PROTOTYPE(static void disp_elem, (int x, int y));
XX! _PROTOTYPE(static void get_termcap, (void));
XX! _PROTOTYPE(void Exit, (int code));
XX! _PROTOTYPE(void term_init, (void));
XX! _PROTOTYPE(void term_exit, (void));
XX! _PROTOTYPE(void display, (int force));
XX! _PROTOTYPE(int gettoken, (void));
XX! _PROTOTYPE(void set_cursor, (int on));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 143,148 ****
XX--- 151,157 ----
XX    else
XX  	man(man_fd, argv);
XX    Exit(0);
XX+   return(0);
XX  }
XX  
XX  void Exit(code)
XX***************
XX*** 157,164 ****
XX  char **man_pages;
XX  {				/* copy all requested manual pages to
XX  			 * standard output */
XX-   int ch;
XX- 
XX    while (1) {
XX  	_man(man_fd, *man_pages);
XX  	man_pages++;
XX--- 166,171 ----
XX***************
XX*** 180,186 ****
XX    /* Search entries for man_page */
XX    for (index_nr = 0; index_nr < max_index_nr; index_nr++) {
XX  	if (strncmp(man_page, index_buf[index_nr].page_name,
XX! 		    NAME_SIZE) == 0)
XX  		break;
XX    }
XX    if (index_nr == max_index_nr) {
XX--- 187,193 ----
XX    /* Search entries for man_page */
XX    for (index_nr = 0; index_nr < max_index_nr; index_nr++) {
XX  	if (strncmp(man_page, index_buf[index_nr].page_name,
XX! 		    (size_t)NAME_SIZE) == 0)
XX  		break;
XX    }
XX    if (index_nr == max_index_nr) {
XX***************
XX*** 215,221 ****
XX  FILE *man_fd;
XX  {				/* driver one time chosing a page on the
XX  			 * screen */
XX!   int ch, index, max_x, max_y;
XX  
XX    if (!term_dialog) {
XX  	fprintf(stderr, "sorry, no terminal\n");
XX--- 222,228 ----
XX  FILE *man_fd;
XX  {				/* driver one time chosing a page on the
XX  			 * screen */
XX!   int index, max_x, max_y;
XX  
XX    if (!term_dialog) {
XX  	fprintf(stderr, "sorry, no terminal\n");
XX***************
XX*** 229,235 ****
XX  	index = do_choose(max_x, max_y);
XX  	if (index == STOP) break;
XX  	clrscr();
XX! 	_man(man_fd, index_buf[index].page_name, 1);
XX  	(void) do_wait(WAIT1, DO_REVERSE);
XX    };
XX  }
XX--- 236,242 ----
XX  	index = do_choose(max_x, max_y);
XX  	if (index == STOP) break;
XX  	clrscr();
XX! 	_man(man_fd, index_buf[index].page_name);
XX  	(void) do_wait(WAIT1, DO_REVERSE);
XX    };
XX  }
XX***************
XX*** 355,378 ****
XX  int max_index_nr = 0;		/* number of indices in index_buf */
XX  static long man_pos;		/* position in manual file */
XX  
XX- /* Forward declarations: */
XX- static void _read_index();
XX- static void build_index();
XX- static int find_name();
XX- static int find_delim();
XX- 
XX  static int index_cmp(index1, index2)
XX! struct INDEX *index1, *index2;
XX  {				/* used in qsort to sort the indexes read */
XX    int tmp;
XX!   tmp = strncmp(index1->page_name, index2->page_name, NAME_SIZE);
XX!   if (tmp == 0) tmp = index1 - index2;
XX    return(tmp);
XX  }
XX  
XX  extern void read_index()
XX! {				/* read index file, if necessary creat a new
XX! 			 * one */
XX    int index_fd, build = 1;	/* assume to build a new index */
XX    struct stat name_stat, index_stat;
XX  
XX--- 362,380 ----
XX  int max_index_nr = 0;		/* number of indices in index_buf */
XX  static long man_pos;		/* position in manual file */
XX  
XX  static int index_cmp(index1, index2)
XX! _CONST void *index1, *index2;
XX  {				/* used in qsort to sort the indexes read */
XX    int tmp;
XX!   tmp = strncmp(((struct INDEX *)index1)->page_name,
XX! 		((struct INDEX *)index2)->page_name,
XX! 		(size_t)NAME_SIZE);
XX!   if (tmp == 0) tmp = (struct INDEX *)index1 - (struct INDEX *)index2;
XX    return(tmp);
XX  }
XX  
XX  extern void read_index()
XX! {				/* read index file, if needed, creat new one */
XX    int index_fd, build = 1;	/* assume to build a new index */
XX    struct stat name_stat, index_stat;
XX  
XX***************
XX*** 389,401 ****
XX    close(index_fd);
XX  
XX    if (build) {			/* write new index out to index file */
XX! 	qsort(index_buf, max_index_nr, sizeof(struct INDEX), index_cmp);
XX  	index_fd = creat(ar_index, 0600);
XX  	if (index_fd == -1) {
XX  		fprintf(stderr, "can't create index\n");
XX  		return;		/* not fatal for now */
XX  	}
XX! 	if (write(index_fd, index_buf, INDEX_SIZE()) != INDEX_SIZE()) {
XX  		fprintf(stderr, "write error on index file\n");
XX  		unlink(ar_index);	/* don't leave partial index */
XX  		return;		/* not fatal for now */
XX--- 391,403 ----
XX    close(index_fd);
XX  
XX    if (build) {			/* write new index out to index file */
XX! 	qsort(index_buf, (size_t)max_index_nr, sizeof(struct INDEX), index_cmp);
XX  	index_fd = creat(ar_index, 0600);
XX  	if (index_fd == -1) {
XX  		fprintf(stderr, "can't create index\n");
XX  		return;		/* not fatal for now */
XX  	}
XX! 	if (write(index_fd, (char *)index_buf, INDEX_SIZE()) != INDEX_SIZE()) {
XX  		fprintf(stderr, "write error on index file\n");
XX  		unlink(ar_index);	/* don't leave partial index */
XX  		return;		/* not fatal for now */
XX***************
XX*** 408,419 ****
XX  int index_fd;
XX  int index_size;
XX  {				/* allocate index buffer and read index */
XX!   index_buf = (struct INDEX *) malloc(index_size);
XX    if (index_buf == NULL) {
XX  	fprintf(stderr, "can't allocate index buffer\n");
XX  	Exit(1);
XX    }
XX!   if (read(index_fd, index_buf, index_size) != index_size) {
XX  	fprintf(stderr, "can't read index file\n");
XX  	Exit(1);
XX    }
XX--- 410,421 ----
XX  int index_fd;
XX  int index_size;
XX  {				/* allocate index buffer and read index */
XX!   index_buf = (struct INDEX *) malloc((size_t)index_size);
XX    if (index_buf == NULL) {
XX  	fprintf(stderr, "can't allocate index buffer\n");
XX  	Exit(1);
XX    }
XX!   if (read(index_fd, (char *) index_buf, index_size) != index_size) {
XX  	fprintf(stderr, "can't read index file\n");
XX  	Exit(1);
XX    }
XX***************
XX*** 481,487 ****
XX  	if (index_record.page_name[0] == '\0')
XX  		continue;	/* no manual name */
XX  
XX! 	if (fwrite(&index_record, sizeof(struct INDEX), 1, index_fd) != 1) {
XX  		fprintf(stderr, "write error on index file\n");
XX  		unlink(ar_index);	/* don't leave partial index */
XX  		Exit(1);
XX--- 483,489 ----
XX  	if (index_record.page_name[0] == '\0')
XX  		continue;	/* no manual name */
XX  
XX! 	if (fwrite(&index_record, sizeof(struct INDEX), (size_t)1, index_fd) != 1) {
XX  		fprintf(stderr, "write error on index file\n");
XX  		unlink(ar_index);	/* don't leave partial index */
XX  		Exit(1);
XX***************
XX*** 534,558 ****
XX  static struct sgttyb termmode;	/* contains startup sgtty struct */
XX  static int term_used = 0;	/* set when terminal is initialised */
XX  
XX- extern char *tgetstr();
XX  
XX- /* Forward declarations */
XX- static void disp_all();
XX- static void scr_down();
XX- static void scr_up();
XX- static void disp_fill();
XX- static void disp_elem();
XX- static void get_termcap();
XX- 
XX  void term_init()
XX  {				/* initialize terminal and termcap functions */
XX    struct sgttyb argp;
XX    static int init_done = 0;
XX-   extern void Exit();
XX  
XX    if (init_done || !term_dialog) return;
XX    get_termcap();
XX!   setbuf(stdout, malloc(BUFSIZ));
XX    signal(SIGHUP, Exit);		/* we got to restore the term mode */
XX    signal(SIGINT, Exit);
XX    signal(SIGQUIT, Exit);
XX--- 536,550 ----
XX  static struct sgttyb termmode;	/* contains startup sgtty struct */
XX  static int term_used = 0;	/* set when terminal is initialised */
XX  
XX  
XX  void term_init()
XX  {				/* initialize terminal and termcap functions */
XX    struct sgttyb argp;
XX    static int init_done = 0;
XX  
XX    if (init_done || !term_dialog) return;
XX    get_termcap();
XX!   setbuf(stdout, malloc((size_t)BUFSIZ));
XX    signal(SIGHUP, Exit);		/* we got to restore the term mode */
XX    signal(SIGINT, Exit);
XX    signal(SIGQUIT, Exit);
XX***************
XX*** 703,708 ****
XX--- 695,703 ----
XX    char term_buf[1024];
XX    char *loc = entries;
XX    static int init_done = 0;
XX+ #ifdef TIOCGWINSZ
XX+   struct winsize win;
XX+ #endif
XX  
XX    if (init_done) return;
XX    init_done = 1;
XX***************
XX*** 711,718 ****
XX--- 706,725 ----
XX  	fprintf(stderr, "Unknown terminal\n");
XX  	Exit(-1);
XX    }
XX+ #ifdef TIOCGWINSZ
XX+   LI = CO = 0;
XX+   if (ioctl(2, TIOCGWINSZ, (struct sgttyb *) &win) >= 0) {
XX+ 	LI = win.ws_row;
XX+ 	CO = win.ws_col;
XX+   }
XX+   if (LI == 0  ||  CO == 0) {
XX+ 	LI = tgetnum("li");
XX+ 	CO = tgetnum("co");
XX+   }
XX+ #else
XX    CO = tgetnum("co");
XX    LI = tgetnum("li");
XX+ #endif
XX    AL = tgetstr("al", &loc);
XX    CL = tgetstr("cl", &loc);
XX    CM = tgetstr("cm", &loc);
X/
Xecho x - mkdir.c.d
Xsed '/^X/s///' > mkdir.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mkdir.c  crc=39830    899	Sun Apr 25 21:35:07 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mkdir.c  crc=42866   5272	Wed Nov  4 04:19:15 1992
XX***************
XX*** 1,52 ****
XX! /* mkdir - make a directory		Author: Adri Koppes */
XX  
XX  #include <sys/types.h>
XX! #include <signal.h>
XX  
XX! int error = 0;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   if (argc < 2) {
XX! 	std_err("Usage: mkdir directory...\n");
XX! 	exit(1);
XX    }
XX!   signal(SIGHUP, SIG_IGN);
XX!   signal(SIGINT, SIG_IGN);
XX!   signal(SIGQUIT, SIG_IGN);
XX!   signal(SIGTERM, SIG_IGN);
XX!   while (--argc) makedir(*++argv);
XX!   if (error) exit(1);
XX  }
XX  
XX! makedir(dirname)
XX  char *dirname;
XX  {
XX!   char dots[128], parent[128];
XX!   int sl = 0, i = 0;
XX! 
XX!   while (dirname[i])
XX! 	if (dirname[i++] == '/') sl = i;
XX!   strncpy(parent, dirname, sl);
XX!   parent[sl] = '\0';
XX!   strcat(parent, ".");
XX!   if (access(parent, 2)) {
XX! 	stderr3("mkdir: can't access ", parent, "\n");
XX! 	exit(1);
XX    }
XX!   if (mkdir(dirname, 0777)) {
XX! 	stderr3("mkdir: can't create ", dirname, "\n");
XX! 	error++;
XX! 	return;
XX    }
XX  }
XX  
XX! stderr3(s1, s2, s3)
XX! char *s1, *s2, *s3;
XX  {
XX!   std_err(s1);
XX!   std_err(s2);
XX!   std_err(s3);
XX  }
XX--- 1,259 ----
XX! /* mkdir - Make directories		Author: V. Archer */
XX  
XX+ /* Copyright 1991 by Vincent Archer
XX+  *	You may freely redistribute this software, in source or binary
XX+  *	form, provided that you do not alter this copyright mention in any
XX+  *	way.
XX+  */
XX+ 
XX  #include <sys/types.h>
XX! #include <sys/stat.h>
XX! #include <minix/minlib.h>
XX! #include <limits.h>
XX! #include <errno.h>
XX! #include <string.h>
XX! #include <stdlib.h>
XX! #include <stdio.h>
XX  
XX! extern int optind, opterr;
XX! extern char *optarg;
XX  
XX! #define USR_MODES (S_ISUID|S_IRWXU)
XX! #define GRP_MODES (S_ISGID|S_IRWXG)
XX! #define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
XX! #ifdef S_ISVTX
XX! #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
XX! #else
XX! #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
XX! #endif
XX! #define DEFAULT_MODE (S_IRWXU|S_IRWXG|S_IRWXO)
XX! #define USER_WX (S_IWUSR|S_IXUSR)
XX! 
XX! 
XX! /* Global variables */
XX! int pflag;
XX! char *symbolic;
XX! mode_t u_mask;
XX! struct stat st;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(mode_t parsemode, (char *symbolic, Mode_t oldmode));
XX! _PROTOTYPE(int makepath, (char *fordir));
XX! _PROTOTYPE(int makedir, (char *dirname));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! /* Parse a P1003.2 4.7.7-conformant symbolic mode. */
XX! mode_t parsemode(symbolic, oldmode)
XX! char *symbolic;
XX! mode_t oldmode;
XX! {
XX!   mode_t who, mask, newmode, tmpmask;
XX!   char action;
XX! 
XX!   newmode = oldmode & ALL_MODES;
XX!   while (*symbolic) {
XX! 	who = 0;
XX! 	for (; *symbolic; symbolic++) {
XX! 		if (*symbolic == 'a') {
XX! 			who |= ALL_MODES;
XX! 			continue;
XX! 		}
XX! 		if (*symbolic == 'u') {
XX! 			who |= USR_MODES;
XX! 			continue;
XX! 		}
XX! 		if (*symbolic == 'g') {
XX! 			who |= GRP_MODES;
XX! 			continue;
XX! 		}
XX! 		if (*symbolic == 'o') {
XX! 			who |= S_IRWXO;
XX! 			continue;
XX! 		}
XX! 		break;
XX! 	}
XX! 	if (!*symbolic || *symbolic == ',') usage();
XX! 	while (*symbolic) {
XX! 		if (*symbolic == ',') break;
XX! 		switch (*symbolic) {
XX! 		    default:
XX! 			usage();
XX! 		    case '+':
XX! 		    case '-':
XX! 		    case '=':	action = *symbolic++;
XX! 		}
XX! 		mask = 0;
XX! 		for (; *symbolic; symbolic++) {
XX! 			if (*symbolic == 'u') {
XX! 				tmpmask = newmode & S_IRWXU;
XX! 				mask |= tmpmask | (tmpmask << 3) | (tmpmask << 6);
XX! 				symbolic++;
XX! 				break;
XX! 			}
XX! 			if (*symbolic == 'g') {
XX! 				tmpmask = newmode & S_IRWXG;
XX! 				mask |= tmpmask | (tmpmask >> 3) | (tmpmask << 3);
XX! 				symbolic++;
XX! 				break;
XX! 			}
XX! 			if (*symbolic == 'o') {
XX! 				tmpmask = newmode & S_IRWXO;
XX! 				mask |= tmpmask | (tmpmask >> 3) | (tmpmask >> 6);
XX! 				symbolic++;
XX! 				break;
XX! 			}
XX! 			if (*symbolic == 'r') {
XX! 				mask |= S_IRUSR | S_IRGRP | S_IROTH;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 'w') {
XX! 				mask |= S_IWUSR | S_IWGRP | S_IWOTH;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 'x') {
XX! 				mask |= EXE_MODES;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 's') {
XX! 				mask |= S_ISUID | S_ISGID;
XX! 				continue;
XX! 			}
XX! 			if (*symbolic == 'X') {
XX! 				if (S_ISDIR(oldmode) || (oldmode & EXE_MODES))
XX! 					mask |= EXE_MODES;
XX! 				continue;
XX! 			}
XX! #ifdef S_ISVTX
XX! 			if (*symbolic == 't') {
XX! 				mask |= S_ISVTX;
XX! 				who |= S_ISVTX;
XX! 				continue;
XX! 			}
XX! #endif
XX! 			break;
XX! 		}
XX! 		switch (action) {
XX! 		    case '=':
XX! 			if (who)
XX! 				newmode &= ~who;
XX! 			else
XX! 				newmode = 0;
XX! 		    case '+':
XX! 			if (who)
XX! 				newmode |= who & mask;
XX! 			else
XX! 				newmode |= mask & (~u_mask);
XX! 			break;
XX! 		    case '-':
XX! 			if (who)
XX! 				newmode &= ~(who & mask);
XX! 			else
XX! 				newmode &= ~mask | u_mask;
XX! 		}
XX! 	}
XX! 	if (*symbolic) symbolic++;
XX!   }
XX!   return(newmode);
XX! }
XX! 
XX! 
XX! /* Main module. */
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   int error, c;
XX! 
XX!   opterr = 0;
XX!   pflag = 0;
XX!   symbolic = (char *) 0;
XX!   u_mask = umask(0);
XX!   umask(u_mask);
XX!   while ((c = getopt(argc, argv, "m:p")) != EOF) switch (c) {
XX! 	    case 'm':	symbolic = optarg;	break;
XX! 	    case 'p':	pflag = 1;	break;
XX! 	    default:	usage();
XX! 	}
XX!   if (optind >= argc) usage();
XX! 
XX!   error = 0;
XX!   while (optind < argc) error |= makedir(argv[optind++]);
XX!   return(error);
XX! }
XX! 
XX! 
XX! /* P1003.2 requires that missing intermediate pathname components should be
XX!  *	created if the -p option is specified (4.40.3).
XX!  */
XX! int makepath(fordir)
XX! char *fordir;
XX! {
XX!   char parent[PATH_MAX + 1], *end;
XX! 
XX!   strcpy(parent, fordir);
XX!   if (!(end = strrchr(parent, '/'))) return(0);
XX!   *end = '\0';
XX!   if (!parent[0]) return(0);
XX! 
XX!   if (!stat(parent, &st)) {
XX! 	if (S_ISDIR(st.st_mode)) return(0);
XX! 	errno = ENOTDIR;
XX! 	perror(parent);
XX! 	return(1);
XX    }
XX!   if (mkdir(parent, DEFAULT_MODE)) {
XX! 	if (makepath(parent)) return(1);
XX! 	if (mkdir(parent, DEFAULT_MODE)) {
XX! 		perror(parent);
XX! 		return(1);
XX! 	}
XX!   }
XX! 
XX! /* P1003.2 states that, regardless of umask() value, intermediate paths
XX!  *	should have at least write and search (x) permissions (4.40.10).
XX!  */
XX!   if ((u_mask & USER_WX) &&
XX!       chmod(parent, ((~u_mask) | USER_WX)) & DEFAULT_MODE) {
XX! 	perror(parent);
XX! 	return(1);
XX!   }
XX!   return(0);
XX  }
XX  
XX! 
XX! /* Actual directory creation, using a mkdir() system call. */
XX! int makedir(dirname)
XX  char *dirname;
XX  {
XX!   if (mkdir(dirname, DEFAULT_MODE)) {
XX! 	if (!pflag) {
XX! 		perror(dirname);
XX! 		return(1);
XX! 	}
XX! 	if (!stat(dirname, &st)) {
XX! 		if (S_ISDIR(st.st_mode)) return(0);
XX! 		errno = ENOTDIR;
XX! 		perror(dirname);
XX! 		return(1);
XX! 	}
XX! 	if (makepath(dirname)) return(1);
XX! 	if (mkdir(dirname, DEFAULT_MODE)) {
XX! 		perror(dirname);
XX! 		return(1);
XX! 	}
XX    }
XX!   if (symbolic && (stat(dirname, &st) ||
XX! 		 chmod(dirname, parsemode(symbolic, st.st_mode)))) {
XX! 	perror(dirname);
XX! 	return(1);
XX    }
XX+   return(0);
XX  }
XX  
XX! 
XX! /* Posix command prototype. */
XX! void usage()
XX  {
XX!   std_err("Usage: mkdir [-p] [-m mode] dir...\n");
XX!   exit(1);
XX  }
X/
Xecho x - mkfs.c.d
Xsed '/^X/s///' > mkfs.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mkfs.c  crc=43701  27989	Sun Apr 25 21:35:07 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mkfs.c  crc=51315  34883	Mon Jan 18 18:56:09 1993
XX***************
XX*** 1,37 ****
XX! /* mkfs  -  make the MINIX filesystem	Authors: A. Tanenbaum & P. Ogilvie */
XX  
XX! 
XX! /*		 Andy Tanenbaum & Paul Ogilvie, June 1986
XX   *
XX!  *	This program was initially designed to build a filesystem
XX!  *	with blocksize = zonesize. During the course of time the
XX!  *	program is being converted to handle zone_size > blocksize
XX!  *	but this isn't complete yet. Where routines can handle the
XX!  *	situation this is mentioned in the comment.
XX   *
XX-  *	To compile this program for MS-DOS, use: cc -DDOS mkfs.c diskio.asm
XX-  *	To compile this program for UNIX,   use: cc -DUNIX mkfs.c
XX-  *	To compile this program for MINIX,  use: cc mkfs.c
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <limits.h>
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  #include "../fs/const.h"
XX  
XX  #undef EXTERN
XX  #define EXTERN			/* get rid of EXTERN by making it null */
XX  #include "../fs/type.h"
XX  #include "../fs/super.h"
XX  
XX- #include <fcntl.h>
XX- #include <sys/stat.h>
XX- #include <unistd.h>
XX- #include <stdlib.h>
XX- #include <stdio.h>
XX- 
XX  #ifndef DOS
XX  #ifndef UNIX
XX  #undef printf			/* printf is a macro for printk */
XX--- 1,35 ----
XX! /* mkfs  -  make the MINIX filesystem	Authors: Tanenbaum et al. */
XX  
XX! /*	Authors: Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans
XX   *
XX!  * This program can make both version 1 and version 2 file systems, as follows:
XX!  *	mkfs /dev/fd0 1200	# Version 2 (default)
XX!  *	mkfs -1 /dev/fd0 360	# Version 1
XX   *
XX   */
XX  
XX  #include <sys/types.h>
XX+ #include <sys/dir.h>
XX+ #include <sys/stat.h>
XX+ #include <errno.h>
XX+ #include <fcntl.h>
XX  #include <limits.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <time.h>
XX+ #include <unistd.h>
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX+ #include <minix/minlib.h>
XX  #include "../fs/const.h"
XX  
XX  #undef EXTERN
XX  #define EXTERN			/* get rid of EXTERN by making it null */
XX  #include "../fs/type.h"
XX  #include "../fs/super.h"
XX+ #include <minix/fslib.h>
XX  
XX  #ifndef DOS
XX  #ifndef UNIX
XX  #undef printf			/* printf is a macro for printk */
XX***************
XX*** 39,208 ****
XX  #endif
XX  #endif
XX  
XX  
XX- 
XX  #define INODE_MAP            2
XX  #define MAX_TOKENS          10
XX  #define LINE_LEN           200
XX  #define BIN                  2
XX  #define BINGRP               2
XX  #define BIT_MAP_SHIFT       13
XX! #define N_BLOCKS       0x10000L	/* must be multiple of 8 */
XX  
XX  #ifdef DOS
XX!    maybedefine O_RDONLY	     4	/* O_RDONLY | BINARY_BIT */
XX!    maybedefine BWRITE	     5	/* O_WRONLY | BINARY_BIT */
XX  #endif
XX  
XX  #if (MACHINE == ATARI)
XX! int	isdev;
XX  #endif
XX  
XX  int next_zone, next_inode, zone_size, zone_shift = 0, zoff;
XX! unsigned nrblocks;
XX! int inode_offset, nrinodes, lct = 1, disk, fd, print = 0, file = 0;
XX  int override = 0, simple = 0, dflag;
XX  int donttest;			/* skip test if it fits on medium */
XX  
XX  long current_time, bin_time;
XX  char zero[BLOCK_SIZE], *lastp;
XX  char umap[(N_BLOCKS + 8) / 8];	/* bit map tells if block read yet */
XX! int zone_map = 3;		/* where is zone map? (depends on # inodes) */
XX  
XX  FILE *proto;
XX- char gwarning[] = {65, 46, 83, 46, 84, 97, 110, 101, 110, 98, 97, 117, 109, 10};
XX  
XX  
XX- 
XX  /*================================================================
XX   *                    mkfs  -  make filesystem
XX   *===============================================================*/
XX! 
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int i, mode, usrid, grpid, badusage = 0;
XX!   unsigned zones, inodes;
XX!   unsigned long blocks;
XX    char *token[MAX_TOKENS], line[LINE_LEN];
XX-   FILE *fopen();
XX-   long time(), ls;
XX    struct stat statbuf;
XX  
XX- 
XX    /* Get two times, the current time and the mod time of the binary of
XX     * mkfs itself.  When the -d flag is used, the later time is put into
XX     * the i_mtimes of all the files.  This feature is useful when
XX     * producing a set of file systems, and one wants all the times to be
XX     * identical. First you set the time of the mkfs binary to what you
XX!    * want, then go. */
XX!   current_time = time(0L);	/* time mkfs is being run */
XX    stat(argv[0], &statbuf);
XX    bin_time = statbuf.st_mtime;	/* time when mkfs binary was last modified */
XX  
XX!   /* Process parameters and switches */
XX!   if (argc != 3 && argc != 4) badusage = 1;
XX!   if (stat(argv[argc - 1], &statbuf) == 0) {
XX! 	if ((statbuf.st_mode & S_IFMT) != S_IFREG) badusage = 1;
XX!   }
XX!   if (badusage) {
XX! 	write(2, "Usage: mkfs [-ldt] special proto\n", 33);
XX! 	exit(1);
XX!   }
XX!   while (--argc) {
XX! 	switch (argv[argc][0]) {
XX! 	    case '-':
XX! 		while (*++argv[argc]) switch (*argv[argc]) {
XX! 			    case 'l':
XX! 			    case 'L':	print = 1;	break;
XX! 			    case 'o':
XX! 			    case 'O':
XX! 				override = 1;
XX! 				break;
XX! 			    case 'd':
XX! 			    case 'D':
XX! 				current_time = bin_time;
XX! 				dflag = 1;
XX! 				break;
XX! 			    case 't':
XX! 			    case 'T':
XX! 				donttest = 1;
XX! 				break;
XX! 			    default:
XX! 				printf("Bad switch %c, ignored.\n", *argv[argc]);
XX! 			}
XX  		break;
XX  
XX! 	    default:
XX  
XX! 		/* Process proto & special */
XX! 		proto = fopen(argv[argc], "r");
XX! 		if (proto != (FILE *) NULL) {
XX! 			/* Prototype file is readable. */
XX! 			getline(line, token);	/* skip boot block info. */
XX  
XX! 			/* Read the line with the block and inode counts. */
XX! 			getline(line, token);
XX! 			blocks = atol(token[0]);
XX! 			if (blocks > N_BLOCKS)
XX! 				pexit("Block count too large");
XX! 			inodes = atoi(token[1]);
XX  
XX! 			/* Process mode line for root directory. */
XX! 			getline(line, token);
XX! 			mode = mode_con(token[0]);
XX! 			usrid = atoi(token[1]);
XX! 			grpid = atoi(token[2]);
XX  
XX! 		} else {
XX  
XX! 			/* Maybe the prototype file is just a size.
XX! 			 * Check for that. */
XX! 			blocks = atol(argv[argc]);
XX! 			if (blocks < 4) pexit("Can't open prototype file");
XX! 			if (blocks > N_BLOCKS)
XX! 				pexit("Block count too large");
XX  
XX! 			/* Ok, make simple file system of given size,
XX! 			 * using defaults. */
XX! 			inodes = (blocks / 3) + 8;	/* default is 3
XX! 							 * blocks/file */
XX! 			mode = 040777;
XX! 			usrid = BIN;
XX! 			grpid = BINGRP;
XX! 			simple = 1;
XX! 		}
XX  
XX- 		/* Open special */
XX- 		argc--;
XX- 		special(argv[argc]);
XX- 
XX- 		nrblocks = blocks;
XX- 		nrinodes = inodes;
XX- 	}			/* end switch */
XX-   }				/* end while */
XX- 
XX- 
XX- 
XX  #ifdef UNIX
XX    if (!donttest) {
XX  	static short testb[BLOCK_SIZE / sizeof(short)];
XX  
XX  	/* Try writing the last block of partition or diskette. */
XX! 	ls = lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
XX  	testb[0] = 0x3245;
XX  	testb[1] = 0x11FF;
XX  	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
XX  		pexit("File system is too big for minor device");
XX  	sync();			/* flush write, so if error next read fails */
XX! 	lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
XX  	testb[0] = 0;
XX  	testb[1] = 0;
XX! 	i = read(fd, (char *) testb, BLOCK_SIZE);
XX! 	if (i != BLOCK_SIZE || testb[0] != 0x3245 || testb[1] != 0x11FF)
XX  		pexit("File system is too big for minor device");
XX! 	lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
XX  	testb[0] = 0;
XX  	testb[1] = 0;
XX  	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
XX--- 37,259 ----
XX  #endif
XX  #endif
XX  
XX+ #include <stdio.h>
XX  
XX  #define INODE_MAP            2
XX  #define MAX_TOKENS          10
XX  #define LINE_LEN           200
XX  #define BIN                  2
XX  #define BINGRP               2
XX  #define BIT_MAP_SHIFT       13
XX! #define N_BLOCKS       0x20000L	/* must be multiple of 8 */
XX! #define INODE_MAX ((unsigned) 65535)
XX  
XX+ 
XX  #ifdef DOS
XX! maybedefine O_RDONLY 4		/* O_RDONLY | BINARY_BIT */
XX!  maybedefine BWRITE 5		/* O_WRONLY | BINARY_BIT */
XX  #endif
XX  
XX  #if (MACHINE == ATARI)
XX! int isdev;
XX  #endif
XX  
XX+ extern char *optarg;
XX+ extern int optind;
XX+ 
XX  int next_zone, next_inode, zone_size, zone_shift = 0, zoff;
XX! block_t nrblocks;
XX! int inode_offset, lct = 0, disk, fd, print = 0, file = 0;
XX! unsigned int nrinodes;
XX  int override = 0, simple = 0, dflag;
XX  int donttest;			/* skip test if it fits on medium */
XX+ char *progname;
XX  
XX  long current_time, bin_time;
XX  char zero[BLOCK_SIZE], *lastp;
XX  char umap[(N_BLOCKS + 8) / 8];	/* bit map tells if block read yet */
XX! block_t zone_map = 3;		/* where is zone map? (depends on # inodes) */
XX! int inodes_per_block;
XX! int fs_version;
XX! block_t max_nrblocks;
XX  
XX  FILE *proto;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void super, (zone_t zones, Ino_t inodes));
XX+ _PROTOTYPE(void rootdir, (Ino_t inode));
XX+ _PROTOTYPE(void eat_dir, (Ino_t parent));
XX+ _PROTOTYPE(void eat_file, (Ino_t inode, int f));
XX+ _PROTOTYPE(void enter_dir, (Ino_t parent, char *name, Ino_t child));
XX+ _PROTOTYPE(void incr_size, (Ino_t n, long count));
XX+ _PROTOTYPE(PRIVATE ino_t alloc_inode, (int mode, int usrid, int grpid));
XX+ _PROTOTYPE(PRIVATE zone_t alloc_zone, (void));
XX+ _PROTOTYPE(void add_zone, (Ino_t n, zone_t z, long bytes, long cur_time));
XX+ _PROTOTYPE(void add_z_1, (Ino_t n, zone_t z, long bytes, long cur_time));
XX+ _PROTOTYPE(void add_z_2, (Ino_t n, zone_t z, long bytes, long cur_time));
XX+ _PROTOTYPE(void incr_link, (Ino_t n));
XX+ _PROTOTYPE(void insert_bit, (block_t block, int bit, int count));
XX+ _PROTOTYPE(int mode_con, (char *p));
XX+ _PROTOTYPE(void getline, (char line[LINE_LEN], char *parse[MAX_TOKENS]));
XX+ _PROTOTYPE(void check_mtab, (char *devname));
XX+ _PROTOTYPE(long file_time, (int f));
XX+ _PROTOTYPE(void pexit, (char *s));
XX+ _PROTOTYPE(void copy, (char *from, char *to, int count));
XX+ _PROTOTYPE(void print_fs, (void));
XX+ _PROTOTYPE(int read_and_set, (block_t n));
XX+ _PROTOTYPE(void special, (char *string));
XX+ _PROTOTYPE(void get_block, (block_t n, char buf[BLOCK_SIZE]));
XX+ _PROTOTYPE(void put_block, (block_t n, char buf[BLOCK_SIZE]));
XX+ _PROTOTYPE(void cache_init, (void));
XX+ _PROTOTYPE(void flush, (void));
XX+ _PROTOTYPE(void mx_read, (int blocknr, char buf[BLOCK_SIZE]));
XX+ _PROTOTYPE(void mx_write, (int blocknr, char buf[BLOCK_SIZE]));
XX+ _PROTOTYPE(void dexit, (char *s, int sectnum, int err));
XX+ _PROTOTYPE(void usage, (void));
XX  
XX  /*================================================================
XX   *                    mkfs  -  make filesystem
XX   *===============================================================*/
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int nread, mode, usrid, grpid, ch;
XX!   block_t blocks;
XX!   block_t i;
XX!   ino_t root_inum;
XX!   ino_t inodes;
XX!   zone_t zones;
XX    char *token[MAX_TOKENS], line[LINE_LEN];
XX    struct stat statbuf;
XX  
XX    /* Get two times, the current time and the mod time of the binary of
XX     * mkfs itself.  When the -d flag is used, the later time is put into
XX     * the i_mtimes of all the files.  This feature is useful when
XX     * producing a set of file systems, and one wants all the times to be
XX     * identical. First you set the time of the mkfs binary to what you
XX!    * want, then go.
XX!    */
XX!   current_time = time((time_t *) 0);	/* time mkfs is being run */
XX    stat(argv[0], &statbuf);
XX    bin_time = statbuf.st_mtime;	/* time when mkfs binary was last modified */
XX  
XX!   /* Process switches. */
XX!   progname = argv[0];
XX!   blocks = 0;
XX!   i = 0;
XX!   fs_version = 2;
XX!   inodes_per_block = V2_INODES_PER_BLOCK;
XX!   max_nrblocks = N_BLOCKS;
XX!   while ((ch = getopt(argc, argv, "1b:di:lot")) != EOF)
XX! 	switch (ch) {
XX! 	    case '1':
XX! 		fs_version = 1;
XX! 		inodes_per_block = V1_INODES_PER_BLOCK;
XX! 		max_nrblocks = 0xFFFF;
XX  		break;
XX+ 	    case 'b':
XX+ 		blocks = strtoul(optarg, (char **) NULL, 0);
XX+ 		break;
XX+ 	    case 'd':
XX+ 		dflag = 1;
XX+ 		current_time = bin_time;
XX+ 		break;
XX+ 	    case 'i':
XX+ 		i = strtoul(optarg, (char **) NULL, 0);
XX+ 		break;
XX+ 	    case 'l':	print = 1;	break;
XX+ 	    case 'o':	override = 1;	break;
XX+ 	    case 't':	donttest = 1;	break;
XX+ 	    default:	usage();
XX+ 	}
XX  
XX!   /* The remaining args must be 'special proto', or just 'special' if the
XX!    * block size has already been specified.
XX!    */
XX!   if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage();
XX  
XX!   /* Check special. */
XX!   check_mtab(argv[optind]);
XX  
XX!   /* Check and start processing proto. */
XX!   optarg = argv[++optind];
XX!   if (optind < argc && (proto = fopen(optarg, "r")) != NULL) {
XX! 	/* Prototype file is readable. */
XX! 	lct = 1;
XX! 	getline(line, token);	/* skip boot block info */
XX  
XX! 	/* Read the line with the block and inode counts. */
XX! 	getline(line, token);
XX! 	blocks = atol(token[0]);
XX! 	if (blocks > max_nrblocks) pexit("Block count too large");
XX! 	inodes = atoi(token[1]);
XX  
XX! 	/* Process mode line for root directory. */
XX! 	getline(line, token);
XX! 	mode = mode_con(token[0]);
XX! 	usrid = atoi(token[1]);
XX! 	grpid = atoi(token[2]);
XX!   } else {
XX! 	lct = 0;
XX! 	if (optind < argc) {
XX! 		/* Maybe the prototype file is just a size.  Check. */
XX! 		blocks = strtoul(optarg, (char **) NULL, 0);
XX! 		if (blocks == 0) pexit("Can't open prototype file");
XX! 	}
XX! 	if (i == 0) {
XX! 		/* The default for inodes is 3 blocks per inode, rounded up
XX! 		 * to fill an inode block.  Above 20M, the average files are
XX! 		 * sure to be larger because it is hard to fill up 20M with
XX! 		 * tiny files, so reduce the default number of inodes.  This
XX! 		 * default can always be overridden by using the -i option.
XX! 		 */
XX! 		i = blocks / 3;
XX! 		if (blocks >= 20000) i = blocks / 4;
XX! 		if (blocks >= 40000) i = blocks / 5;
XX! 		if (blocks >= 60000) i = blocks / 6;
XX! 		if (blocks >= 80000) i = blocks / 7;
XX! 		if (blocks >= 100000) i = blocks / 8;
XX! 		i += inodes_per_block - 1;
XX! 		i = i / inodes_per_block * inodes_per_block;
XX! 		if (i > INODE_MAX) i = INODE_MAX;
XX! 	}
XX! 	if (blocks < 5) pexit("Block count too small");
XX! 	if (blocks > max_nrblocks) pexit("Block count too large");
XX! 	if (i < 1) pexit("Inode count too small");
XX! 	if (i > INODE_MAX) pexit("Inode count too large");
XX! 	inodes = (ino_t) i;
XX  
XX! 	/* Make simple file system of the given size, using defaults. */
XX! 	mode = 040777;
XX! 	usrid = BIN;
XX! 	grpid = BINGRP;
XX! 	simple = 1;
XX!   }
XX!   nrblocks = blocks;
XX!   nrinodes = inodes;
XX  
XX!   /* Open special. */
XX!   special(argv[--optind]);
XX  
XX  #ifdef UNIX
XX    if (!donttest) {
XX  	static short testb[BLOCK_SIZE / sizeof(short)];
XX  
XX  	/* Try writing the last block of partition or diskette. */
XX! 	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);
XX  	testb[0] = 0x3245;
XX  	testb[1] = 0x11FF;
XX  	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
XX  		pexit("File system is too big for minor device");
XX  	sync();			/* flush write, so if error next read fails */
XX! 	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);
XX  	testb[0] = 0;
XX  	testb[1] = 0;
XX! 	nread = read(fd, (char *) testb, BLOCK_SIZE);
XX! 	if (nread != BLOCK_SIZE || testb[0] != 0x3245 || testb[1] != 0x11FF)
XX  		pexit("File system is too big for minor device");
XX! 	lseek(fd, (off_t) (blocks - 1) * BLOCK_SIZE, SEEK_SET);
XX  	testb[0] = 0;
XX  	testb[1] = 0;
XX  	if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
XX***************
XX*** 214,297 ****
XX    /* Make the file-system */
XX  
XX    cache_init();
XX  #if (MACHINE == ATARI)
XX    if (isdev) {
XX!     char block0[BLOCK_SIZE];
XX!     get_block(0, block0);	
XX!     /* need to read twice; first time gets an empty block */
XX!     get_block(0, block0);
XX!     /* zero parts of the boot block so the disk won't be recognized as
XX!        a tos disk any more. */
XX!     block0[0] = block0[1] = 0;	/* branch code to boot code    */
XX!     strncpy(&block0[2], "MINIX ", 6);
XX!     block0[16] = 0;		/* number of FATS              */
XX!     block0[17] = block0[18] = 0;/* number of dir entries       */
XX!     block0[22] = block0[23] = 0;/* sectors/FAT                 */
XX!     bzero(&block0[30], 480);	/* boot code                   */
XX!     put_block(0, block0);	
XX!   }
XX!   else
XX  #endif
XX-   put_block(0, zero);		/* Write a null boot block. */
XX  
XX    zone_shift = 0;		/* for future use */
XX    zones = nrblocks >> zone_shift;
XX  
XX    super(zones, inodes);
XX  
XX!   i = alloc_inode(mode, usrid, grpid);
XX!   rootdir(i);
XX!   if (simple == 0) eat_dir(i);
XX  
XX    if (print) print_fs();
XX    flush();
XX!   exit(0);
XX  
XX! 
XX  }				/* end main */
XX  
XX  
XX- 
XX- 
XX  /*================================================================
XX   *                 super  -  construct a superblock
XX   *===============================================================*/
XX  
XX! super(zones, inodes)
XX! unsigned zones, inodes;
XX  {
XX  
XX!   unsigned int i, inodeblks, initblks, initzones, nrzones;
XX!   unsigned int bit_map_len, b_needed, b_allocated, residual;
XX!   long zo;
XX    struct super_block *sup;
XX    char buf[BLOCK_SIZE], *cp;
XX  
XX!   sup = (struct super_block *) buf;
XX  
XX    sup->s_ninodes = inodes;
XX!   sup->s_nzones = zones;
XX!   sup->s_imap_blocks = bitmapsize(1 + inodes);
XX!   sup->s_zmap_blocks = bitmapsize(zones);
XX    inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
XX!   inodeblks = (inodes + INODES_PER_BLOCK - 1) / INODES_PER_BLOCK;
XX    initblks = inode_offset + inodeblks;
XX    initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;
XX    nrzones = nrblocks >> zone_shift;
XX    sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;
XX    zoff = sup->s_firstdatazone - 1;
XX    sup->s_log_zone_size = zone_shift;
XX!   sup->s_magic = SUPER_MAGIC;	/* identify super blocks */
XX!   zo = 7L + (long) NR_INDIRECTS
XX! 	+ (long) NR_INDIRECTS *NR_INDIRECTS;
XX    sup->s_max_size = zo * BLOCK_SIZE;
XX    zone_size = 1 << zone_shift;	/* nr of blocks per zone */
XX  
XX!   for (cp = buf + sizeof(*sup); cp < &buf[BLOCK_SIZE]; cp++) *cp = 0;
XX!   put_block(1, buf);
XX  
XX    /* Clear maps and inodes. */
XX!   for (i = 2; i < initblks; i++) put_block(i, zero);
XX  
XX    next_zone = sup->s_firstdatazone;
XX    next_inode = 1;
XX--- 265,365 ----
XX    /* Make the file-system */
XX  
XX    cache_init();
XX+ 
XX  #if (MACHINE == ATARI)
XX    if (isdev) {
XX! 	char block0[BLOCK_SIZE];
XX! 	get_block((block_t) 0, block0);
XX! 	/* Need to read twice; first time gets an empty block */
XX! 	get_block((block_t) 0, block0);
XX! 	/* Zero parts of the boot block so the disk won't be
XX! 	 * recognized as a tos disk any more. */
XX! 	block0[0] = block0[1] = 0;	/* branch code to boot code    */
XX! 	strncpy(&block0[2], "MINIX ", (size_t) 6);
XX! 	block0[16] = 0;		/* number of FATS              */
XX! 	block0[17] = block0[18] = 0;	/* number of dir entries       */
XX! 	block0[22] = block0[23] = 0;	/* sectors/FAT                 */
XX! 	bzero(&block0[30], 480);/* boot code                   */
XX! 	put_block((block_t) 0, block0);
XX!   } else
XX  #endif
XX  
XX+ 	put_block((block_t) 0, zero);	/* Write a null boot block. */
XX+ 
XX    zone_shift = 0;		/* for future use */
XX    zones = nrblocks >> zone_shift;
XX  
XX    super(zones, inodes);
XX  
XX!   root_inum = alloc_inode(mode, usrid, grpid);
XX!   rootdir(root_inum);
XX!   if (simple == 0) eat_dir(root_inum);
XX  
XX    if (print) print_fs();
XX    flush();
XX!   return(0);
XX  
XX!   /* NOTREACHED */
XX  }				/* end main */
XX  
XX  
XX  /*================================================================
XX   *                 super  -  construct a superblock
XX   *===============================================================*/
XX  
XX! void super(zones, inodes)
XX! zone_t zones;
XX! ino_t inodes;
XX  {
XX+   unsigned int i;
XX+   int inodeblks;
XX+   int initblks;
XX  
XX!   zone_t initzones, nrzones, v1sq, v2sq;
XX!   bit_t bit_map_len;
XX!   int b_needed;
XX!   int b_allocated;
XX!   int residual;
XX!   zone_t zo;
XX    struct super_block *sup;
XX    char buf[BLOCK_SIZE], *cp;
XX  
XX!   for (cp = buf; cp < &buf[BLOCK_SIZE]; cp++) *cp = 0;
XX!   sup = (struct super_block *) buf;	/* lint - might use a union */
XX  
XX    sup->s_ninodes = inodes;
XX!   if (fs_version == 1) {
XX! 	sup->s_nzones = zones;
XX!   } else {
XX! 	sup->s_nzones = 0;	/* not used in V2 - 0 forces errors early */
XX! 	sup->s_zones = zones;
XX!   }
XX!   sup->s_imap_blocks = bitmapsize((bit_t) (1 + inodes));
XX!   sup->s_zmap_blocks = bitmapsize((bit_t) zones);
XX    inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
XX!   inodeblks = (inodes + inodes_per_block - 1) / inodes_per_block;
XX    initblks = inode_offset + inodeblks;
XX    initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;
XX    nrzones = nrblocks >> zone_shift;
XX    sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;
XX    zoff = sup->s_firstdatazone - 1;
XX    sup->s_log_zone_size = zone_shift;
XX!   if (fs_version == 1) {
XX! 	sup->s_magic = SUPER_MAGIC;	/* identify super blocks */
XX! 	v1sq = (zone_t) V1_INDIRECTS * V1_INDIRECTS;
XX! 	zo = V1_NR_DZONES + (long) V1_INDIRECTS + v1sq;
XX!   } else {
XX! 	sup->s_magic = SUPER_V2;/* identify super blocks */
XX! 	v2sq = (zone_t) V2_INDIRECTS * V2_INDIRECTS;
XX! 	zo = V2_NR_DZONES + (zone_t) V2_INDIRECTS + v2sq;
XX!   }
XX    sup->s_max_size = zo * BLOCK_SIZE;
XX    zone_size = 1 << zone_shift;	/* nr of blocks per zone */
XX  
XX!   put_block((block_t) 1, buf);
XX  
XX    /* Clear maps and inodes. */
XX!   for (i = 2; i < initblks; i++) put_block((block_t) i, zero);
XX  
XX    next_zone = sup->s_firstdatazone;
XX    next_inode = 1;
XX***************
XX*** 311,383 ****
XX     * bit map by a few dozen bits, it would have prevented a number of
XX     * bugs in the early days.  This is an example of what happens when
XX     * one ignores the maxim:  First make it work, then make it optimal.
XX!    * For both maps, 0 = available, 1 = in use. */
XX  
XX    /* Mark bits beyond end of inodes as allocated. */
XX    bit_map_len = nrinodes + 1;	/* # bits needed in map */
XX!   residual = bit_map_len % (8 * BLOCK_SIZE);
XX    if (residual == 0) residual = 8 * BLOCK_SIZE;
XX    b_needed = bitmapsize(bit_map_len);
XX    zone_map += b_needed - 1;	/* if imap > 1, adjust start of zone map */
XX!   insert_bit(INODE_MAP + b_needed - 1, residual, 8 * BLOCK_SIZE - residual);
XX  
XX    bit_map_len = nrzones - initzones + 1;	/* # bits needed in map */
XX!   residual = bit_map_len % (8 * BLOCK_SIZE);
XX    if (residual == 0) residual = 8 * BLOCK_SIZE;
XX    b_needed = bitmapsize(bit_map_len);
XX!   b_allocated = bitmapsize(nrzones);
XX    insert_bit(zone_map + b_needed - 1, residual, 8 * BLOCK_SIZE - residual);
XX    if (b_needed != b_allocated) {
XX  	insert_bit(zone_map + b_allocated - 1, 0, 8 * BLOCK_SIZE);
XX    }
XX    insert_bit(zone_map, 0, 1);	/* bit zero must always be allocated */
XX!   insert_bit(INODE_MAP, 0, 1);	/* inode zero not used but must be
XX! 				 * allocated */
XX! 
XX  }
XX  
XX  
XX- 
XX- 
XX- /* The next routine is copied from fsck.c.  Modify some names for consistency.
XX-  * This sharing should be done better.
XX-  */
XX- #define BITMAPSHIFT BIT_MAP_SHIFT
XX- #define bit_nr unsigned
XX- 
XX- /* Convert from bit count to a block count. The usual expression
XX-  *
XX-  *	(nr_bits + (1 << BITMAPSHIFT) - 1) >> BITMAPSHIFT
XX-  *
XX-  * doesn't work because of overflow.
XX-  *
XX-  * Other overflow bugs, such as the expression for N_ILIST overflowing when
XX-  * s_inodes is just over INODES_PER_BLOCK less than the maximum+1, are not
XX-  * fixed yet, because that number of inodes is silly.
XX-  */
XX- int bitmapsize(nr_bits)
XX- bit_nr nr_bits;
XX- {
XX- 	int nr_blocks;
XX- 
XX- 	nr_blocks = nr_bits >> BITMAPSHIFT;
XX- 	if ((nr_blocks << BITMAPSHIFT) < nr_bits)
XX- 		++nr_blocks;
XX- 	return(nr_blocks);
XX- }
XX- 
XX- 
XX- 
XX- 
XX- 
XX  /*================================================================
XX   *              rootdir  -  install the root directory
XX   *===============================================================*/
XX! 
XX! rootdir(inode)
XX! int inode;
XX  {
XX!   int z;
XX  
XX    z = alloc_zone();
XX    add_zone(inode, z, 32L, current_time);
XX--- 379,417 ----
XX     * bit map by a few dozen bits, it would have prevented a number of
XX     * bugs in the early days.  This is an example of what happens when
XX     * one ignores the maxim:  First make it work, then make it optimal.
XX!    * For both maps, 0 = available, 1 = in use. 
XX!    */
XX  
XX    /* Mark bits beyond end of inodes as allocated. */
XX    bit_map_len = nrinodes + 1;	/* # bits needed in map */
XX!   residual = (int) (bit_map_len % (8 * BLOCK_SIZE));	/* lint but OK */
XX    if (residual == 0) residual = 8 * BLOCK_SIZE;
XX    b_needed = bitmapsize(bit_map_len);
XX    zone_map += b_needed - 1;	/* if imap > 1, adjust start of zone map */
XX!   insert_bit((block_t) INODE_MAP + b_needed - 1, residual, 8 * BLOCK_SIZE - residual);
XX  
XX    bit_map_len = nrzones - initzones + 1;	/* # bits needed in map */
XX!   residual = (int) (bit_map_len % (8 * BLOCK_SIZE));	/* lint but OK */
XX    if (residual == 0) residual = 8 * BLOCK_SIZE;
XX    b_needed = bitmapsize(bit_map_len);
XX!   b_allocated = bitmapsize((bit_t) nrzones);
XX    insert_bit(zone_map + b_needed - 1, residual, 8 * BLOCK_SIZE - residual);
XX    if (b_needed != b_allocated) {
XX  	insert_bit(zone_map + b_allocated - 1, 0, 8 * BLOCK_SIZE);
XX    }
XX    insert_bit(zone_map, 0, 1);	/* bit zero must always be allocated */
XX!   insert_bit((block_t) INODE_MAP, 0, 1);	/* inode zero not used but
XX! 						 * must be allocated */
XX  }
XX  
XX  
XX  /*================================================================
XX   *              rootdir  -  install the root directory
XX   *===============================================================*/
XX! void rootdir(inode)
XX! ino_t inode;
XX  {
XX!   zone_t z;
XX  
XX    z = alloc_zone();
XX    add_zone(inode, z, 32L, current_time);
XX***************
XX*** 388,407 ****
XX  }
XX  
XX  
XX- 
XX- 
XX- 
XX  /*================================================================
XX   *	    eat_dir  -  recursively install directory
XX   *===============================================================*/
XX! 
XX! eat_dir(parent)
XX! int parent;			/* parent's inode nr */
XX  {
XX    /* Read prototype lines and set up directory. Recurse if need be. */
XX    char *token[MAX_TOKENS], *p;
XX    char line[LINE_LEN];
XX!   int mode, n, usrid, grpid, z, maj, min, f;
XX    long size;
XX  
XX    while (1) {
XX--- 422,439 ----
XX  }
XX  
XX  
XX  /*================================================================
XX   *	    eat_dir  -  recursively install directory
XX   *===============================================================*/
XX! void eat_dir(parent)
XX! ino_t parent;
XX  {
XX    /* Read prototype lines and set up directory. Recurse if need be. */
XX    char *token[MAX_TOKENS], *p;
XX    char line[LINE_LEN];
XX!   int mode, usrid, grpid, maj, min, f;
XX!   ino_t n;
XX!   zone_t z;
XX    long size;
XX  
XX    while (1) {
XX***************
XX*** 412,418 ****
XX  	mode = mode_con(p);
XX  	usrid = atoi(token[2]);
XX  	grpid = atoi(token[3]);
XX! 	if (grpid & 0200) write(2, gwarning, 14);
XX  	n = alloc_inode(mode, usrid, grpid);
XX  
XX  	/* Enter name in directory and update directory's size. */
XX--- 444,450 ----
XX  	mode = mode_con(p);
XX  	usrid = atoi(token[2]);
XX  	grpid = atoi(token[3]);
XX! 	if (grpid & 0200) fprintf(stderr, "A.S.Tanenbaum\n");
XX  	n = alloc_inode(mode, usrid, grpid);
XX  
XX  	/* Enter name in directory and update directory's size. */
XX***************
XX*** 437,449 ****
XX  		size = 0;
XX  		if (token[6]) size = atoi(token[6]);
XX  		size = BLOCK_SIZE * size;
XX! 		add_zone(n, (maj << 8) | min, size, current_time);
XX  	} else {
XX  		/* Regular file. Go read it. */
XX  		if ((f = open(token[4], O_RDONLY)) < 0) {
XX! 			write(2, "Can't open file ", 16);
XX! 			write(2, token[4], strlen(token[4]));
XX! 			write(2, "\n", 1);
XX  		} else
XX  			eat_file(n, f);
XX  	}
XX--- 469,480 ----
XX  		size = 0;
XX  		if (token[6]) size = atoi(token[6]);
XX  		size = BLOCK_SIZE * size;
XX! 		add_zone(n, (zone_t) ((maj << 8) | min), size, current_time);
XX  	} else {
XX  		/* Regular file. Go read it. */
XX  		if ((f = open(token[4], O_RDONLY)) < 0) {
XX! 			fprintf(stderr, "%s: Can't open %s: %s\n",
XX! 				progname, token[4], strerror(errno));
XX  		} else
XX  			eat_file(n, f);
XX  	}
XX***************
XX*** 451,470 ****
XX  
XX  }
XX  
XX- 
XX- 
XX  /*================================================================
XX   * 		eat_file  -  copy file to MINIX
XX   *===============================================================*/
XX- 
XX  /* Zonesize >= blocksize */
XX! eat_file(inode, f)
XX! int inode, f;
XX  {
XX!   int z, ct, i, j, k;
XX    char buf[BLOCK_SIZE];
XX    long timeval;
XX-   extern long file_time();
XX  
XX    do {
XX  	for (i = 0, j = 0; i < zone_size; i++, j += ct) {
XX--- 482,499 ----
XX  
XX  }
XX  
XX  /*================================================================
XX   * 		eat_file  -  copy file to MINIX
XX   *===============================================================*/
XX  /* Zonesize >= blocksize */
XX! void eat_file(inode, f)
XX! ino_t inode;
XX! int f;
XX  {
XX!   int ct, i, j, k;
XX!   zone_t z;
XX    char buf[BLOCK_SIZE];
XX    long timeval;
XX  
XX    do {
XX  	for (i = 0, j = 0; i < zone_size; i++, j += ct) {
XX***************
XX*** 482,533 ****
XX  
XX  
XX  
XX- 
XX- 
XX  /*================================================================
XX   *	    directory & inode management assist group
XX   *===============================================================*/
XX! 
XX! enter_dir(parent, name, child)
XX! int parent, child;		/* inode nums */
XX  char *name;
XX  {
XX    /* Enter child in parent directory */
XX    /* Works for dir > 1 block and zone > block */
XX!   int i, j, k, l, b, z, off;
XX    char *p1, *p2;
XX!   struct {			/* FIXME, DEBUG - use <sys/dir.h> */
XX! 	ino_t inumb;
XX! 	char name[14];
XX!   } dir_entry[NR_DIR_ENTRIES];
XX  
XX!   d_inode ino[INODES_PER_BLOCK];
XX  
XX! 
XX!   b = ((parent - 1) / INODES_PER_BLOCK) + inode_offset;
XX!   off = (parent - 1) % INODES_PER_BLOCK;
XX!   get_block(b, ino);
XX! 
XX!   for (k = 0; k < NR_DZONE_NUM; k++) {
XX! 	z = ino[off].i_zone[k];
XX! 	if (z == 0) {
XX! 		z = alloc_zone();
XX! 		ino[off].i_zone[k] = z;
XX  	}
XX  	for (l = 0; l < zone_size; l++) {
XX! 		get_block((z << zone_shift) + l, dir_entry);
XX  		for (i = 0; i < NR_DIR_ENTRIES; i++) {
XX! 			if (dir_entry[i].inumb == 0) {
XX! 				dir_entry[i].inumb = child;
XX  				p1 = name;
XX! 				p2 = dir_entry[i].name;
XX  				j = 14;
XX  				while (j--) {
XX  					*p2++ = *p1;
XX  					if (*p1 != 0) p1++;
XX  				}
XX! 				put_block((z << zone_shift) + l, dir_entry);
XX! 				put_block(b, ino);
XX  				return;
XX  			}
XX  		}
XX--- 511,576 ----
XX  
XX  
XX  
XX  /*================================================================
XX   *	    directory & inode management assist group
XX   *===============================================================*/
XX! void enter_dir(parent, name, child)
XX! ino_t parent, child;
XX  char *name;
XX  {
XX    /* Enter child in parent directory */
XX    /* Works for dir > 1 block and zone > block */
XX!   int i, j, k, l, off;
XX!   block_t b;
XX!   zone_t z;
XX    char *p1, *p2;
XX!   struct direct dir_entry[NR_DIR_ENTRIES];
XX!   d1_inode ino1[V1_INODES_PER_BLOCK];
XX!   d2_inode ino2[V2_INODES_PER_BLOCK];
XX!   int nr_dzones;
XX  
XX!   b = ((parent - 1) / inodes_per_block) + inode_offset;
XX!   off = (parent - 1) % inodes_per_block;
XX  
XX!   if (fs_version == 1) {
XX! 	get_block(b, (char *) ino1);
XX! 	nr_dzones = V1_NR_DZONES;
XX!   } else {
XX! 	get_block(b, (char *) ino2);
XX! 	nr_dzones = V2_NR_DZONES;
XX!   }
XX!   for (k = 0; k < nr_dzones; k++) {
XX! 	if (fs_version == 1) {
XX! 		z = ino1[off].d1_zone[k];
XX! 		if (z == 0) {
XX! 			z = alloc_zone();
XX! 			ino1[off].d1_zone[k] = z;
XX! 		}
XX! 	} else {
XX! 		z = ino2[off].d2_zone[k];
XX! 		if (z == 0) {
XX! 			z = alloc_zone();
XX! 			ino2[off].d2_zone[k] = z;
XX! 		}
XX  	}
XX  	for (l = 0; l < zone_size; l++) {
XX! 		get_block((z << zone_shift) + l, (char *) dir_entry);
XX  		for (i = 0; i < NR_DIR_ENTRIES; i++) {
XX! 			if (dir_entry[i].d_ino == 0) {
XX! 				dir_entry[i].d_ino = child;
XX  				p1 = name;
XX! 				p2 = dir_entry[i].d_name;
XX  				j = 14;
XX  				while (j--) {
XX  					*p2++ = *p1;
XX  					if (*p1 != 0) p1++;
XX  				}
XX! 				put_block((z << zone_shift) + l, (char *) dir_entry);
XX! 				if (fs_version == 1) {
XX! 					put_block(b, (char *) ino1);
XX! 				} else {
XX! 					put_block(b, (char *) ino2);
XX! 				}
XX  				return;
XX  			}
XX  		}
XX***************
XX*** 540,658 ****
XX  }
XX  
XX  
XX  
XX! 
XX! add_zone(n, z, bytes, cur_time)
XX! int n, z;
XX  long bytes, cur_time;
XX  {
XX    /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
XX  
XX!   int b, off, indir, i;
XX!   zone_nr blk[NR_INDIRECTS];
XX!   d_inode *p;
XX!   d_inode inode[INODES_PER_BLOCK];
XX  
XX!   b = ((n - 1) / INODES_PER_BLOCK) + inode_offset;
XX!   off = (n - 1) % INODES_PER_BLOCK;
XX!   get_block(b, inode);
XX    p = &inode[off];
XX!   p->i_size += bytes;
XX!   p->i_mtime = cur_time;
XX!   for (i = 0; i < NR_DZONE_NUM; i++)
XX! 	if (p->i_zone[i] == 0) {
XX! 		p->i_zone[i] = z;
XX! 		put_block(b, inode);
XX  		return;
XX  	}
XX!   put_block(b, inode);
XX  
XX    /* File has grown beyond a small file. */
XX!   if (p->i_zone[NR_DZONE_NUM] == 0) p->i_zone[NR_DZONE_NUM] = alloc_zone();
XX!   indir = p->i_zone[NR_DZONE_NUM];
XX!   put_block(b, inode);
XX    b = indir << zone_shift;
XX!   get_block(b, blk);
XX!   for (i = 0; i < NR_INDIRECTS; i++)
XX  	if (blk[i] == 0) {
XX! 		blk[i] = (zone_nr) z;
XX! 		put_block(b, blk);
XX  		return;
XX  	}
XX    pexit("File has grown beyond single indirect");
XX  }
XX  
XX  
XX  
XX  
XX! incr_link(n)
XX! int n;
XX  {
XX    /* Increment the link count to inode n */
XX!   int b, off;
XX!   d_inode inode[INODES_PER_BLOCK];
XX  
XX!   b = ((n - 1) / INODES_PER_BLOCK) + inode_offset;
XX!   off = (n - 1) % INODES_PER_BLOCK;
XX!   get_block(b, inode);
XX!   inode[off].i_nlinks++;
XX!   put_block(b, inode);
XX! }
XX  
XX  
XX  
XX  
XX! incr_size(n, count)
XX! int n;
XX  long count;
XX  {
XX    /* Increment the file-size in inode n */
XX!   int b, off;
XX!   d_inode inode[INODES_PER_BLOCK];
XX  
XX!   b = ((n - 1) / INODES_PER_BLOCK) + inode_offset;
XX!   off = (n - 1) % INODES_PER_BLOCK;
XX!   get_block(b, inode);
XX!   inode[off].i_size += count;
XX!   put_block(b, inode);
XX! }
XX  
XX  
XX  
XX  
XX  /*================================================================
XX   * 	 	     allocation assist group
XX   *===============================================================*/
XX! 
XX! int alloc_inode(mode, usrid, grpid)
XX  int mode, usrid, grpid;
XX  {
XX!   int num, b, off;
XX!   d_inode inode[INODES_PER_BLOCK];
XX  
XX    num = next_inode++;
XX!   if (num >= nrinodes) pexit("File system does not have enough inodes");
XX!   b = ((num - 1) / INODES_PER_BLOCK) + inode_offset;
XX!   off = (num - 1) % INODES_PER_BLOCK;
XX!   get_block(b, inode);
XX!   inode[off].i_mode = mode;
XX!   inode[off].i_uid = usrid;
XX!   inode[off].i_gid = grpid;
XX!   put_block(b, inode);
XX  
XX    /* Set the bit in the bit map. */
XX!   insert_bit(INODE_MAP, num, 1);
XX    return(num);
XX  }
XX  
XX  
XX! 
XX! 
XX! int alloc_zone()
XX  {
XX    /* Allocate a new zone */
XX    /* Works for zone > block */
XX!   int b, z, i;
XX  
XX    z = next_zone++;
XX    b = z << zone_shift;
XX--- 583,785 ----
XX  }
XX  
XX  
XX+ void add_zone(n, z, bytes, cur_time)
XX+ ino_t n;
XX+ zone_t z;
XX+ long bytes, cur_time;
XX+ {
XX+   if (fs_version == 1) {
XX+ 	add_z_1(n, z, bytes, cur_time);
XX+   } else {
XX+ 	add_z_2(n, z, bytes, cur_time);
XX+   }
XX+ }
XX  
XX! void add_z_1(n, z, bytes, cur_time)
XX! ino_t n;
XX! zone_t z;
XX  long bytes, cur_time;
XX  {
XX    /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
XX  
XX!   int off, i;
XX!   block_t b;
XX!   zone_t indir;
XX!   zone1_t blk[V1_INDIRECTS];
XX!   d1_inode *p;
XX!   d1_inode inode[V1_INODES_PER_BLOCK];
XX  
XX!   b = ((n - 1) / V1_INODES_PER_BLOCK) + inode_offset;
XX!   off = (n - 1) % V1_INODES_PER_BLOCK;
XX!   get_block(b, (char *) inode);
XX    p = &inode[off];
XX!   p->d1_size += bytes;
XX!   p->d1_mtime = cur_time;
XX!   for (i = 0; i < V1_NR_DZONES; i++)
XX! 	if (p->d1_zone[i] == 0) {
XX! 		p->d1_zone[i] = (zone1_t) z;
XX! 		put_block(b, (char *) inode);
XX  		return;
XX  	}
XX!   put_block(b, (char *) inode);
XX  
XX    /* File has grown beyond a small file. */
XX!   if (p->d1_zone[V1_NR_DZONES] == 0)
XX! 	p->d1_zone[V1_NR_DZONES] = (zone1_t) alloc_zone();
XX!   indir = p->d1_zone[V1_NR_DZONES];
XX!   put_block(b, (char *) inode);
XX    b = indir << zone_shift;
XX!   get_block(b, (char *) blk);
XX!   for (i = 0; i < V1_INDIRECTS; i++)
XX  	if (blk[i] == 0) {
XX! 		blk[i] = (zone1_t) z;
XX! 		put_block(b, (char *) blk);
XX  		return;
XX  	}
XX    pexit("File has grown beyond single indirect");
XX  }
XX  
XX+ void add_z_2(n, z, bytes, cur_time)
XX+ ino_t n;
XX+ zone_t z;
XX+ long bytes, cur_time;
XX+ {
XX+   /* Add zone z to inode n. The file has grown by 'bytes' bytes. */
XX  
XX+   int off, i;
XX+   block_t b;
XX+   zone_t indir;
XX+   zone_t blk[V2_INDIRECTS];
XX+   d2_inode *p;
XX+   d2_inode inode[V2_INODES_PER_BLOCK];
XX  
XX+   b = ((n - 1) / V2_INODES_PER_BLOCK) + inode_offset;
XX+   off = (n - 1) % V2_INODES_PER_BLOCK;
XX+   get_block(b, (char *) inode);
XX+   p = &inode[off];
XX+   p->d2_size += bytes;
XX+   p->d2_mtime = cur_time;
XX+   for (i = 0; i < V2_NR_DZONES; i++)
XX+ 	if (p->d2_zone[i] == 0) {
XX+ 		p->d2_zone[i] = z;
XX+ 		put_block(b, (char *) inode);
XX+ 		return;
XX+ 	}
XX+   put_block(b, (char *) inode);
XX  
XX!   /* File has grown beyond a small file. */
XX!   if (p->d2_zone[V2_NR_DZONES] == 0) p->d2_zone[V2_NR_DZONES] = alloc_zone();
XX!   indir = p->d2_zone[V2_NR_DZONES];
XX!   put_block(b, (char *) inode);
XX!   b = indir << zone_shift;
XX!   get_block(b, (char *) blk);
XX!   for (i = 0; i < V2_INDIRECTS; i++)
XX! 	if (blk[i] == 0) {
XX! 		blk[i] = z;
XX! 		put_block(b, (char *) blk);
XX! 		return;
XX! 	}
XX!   pexit("File has grown beyond single indirect");
XX! }
XX! 
XX! 
XX! void incr_link(n)
XX! ino_t n;
XX  {
XX    /* Increment the link count to inode n */
XX!   int off;
XX!   block_t b;
XX  
XX!   b = ((n - 1) / inodes_per_block) + inode_offset;
XX!   off = (n - 1) % inodes_per_block;
XX!   if (fs_version == 1) {
XX! 	d1_inode inode1[V1_INODES_PER_BLOCK];
XX  
XX+ 	get_block(b, (char *) inode1);
XX+ 	inode1[off].d1_nlinks++;
XX+ 	put_block(b, (char *) inode1);
XX+   } else {
XX+ 	d2_inode inode2[V2_INODES_PER_BLOCK];
XX  
XX+ 	get_block(b, (char *) inode2);
XX+ 	inode2[off].d2_nlinks++;
XX+ 	put_block(b, (char *) inode2);
XX+   }
XX+ }
XX  
XX  
XX! void incr_size(n, count)
XX! ino_t n;
XX  long count;
XX  {
XX    /* Increment the file-size in inode n */
XX!   block_t b;
XX!   int off;
XX  
XX!   b = ((n - 1) / inodes_per_block) + inode_offset;
XX!   off = (n - 1) % inodes_per_block;
XX!   if (fs_version == 1) {
XX! 	d1_inode inode1[V1_INODES_PER_BLOCK];
XX  
XX+ 	get_block(b, (char *) inode1);
XX+ 	inode1[off].d1_size += count;
XX+ 	put_block(b, (char *) inode1);
XX+   } else {
XX+ 	d2_inode inode2[V2_INODES_PER_BLOCK];
XX  
XX+ 	get_block(b, (char *) inode2);
XX+ 	inode2[off].d2_size += count;
XX+ 	put_block(b, (char *) inode2);
XX+   }
XX+ }
XX  
XX  
XX  /*================================================================
XX   * 	 	     allocation assist group
XX   *===============================================================*/
XX! PRIVATE ino_t alloc_inode(mode, usrid, grpid)
XX  int mode, usrid, grpid;
XX  {
XX!   ino_t num;
XX!   int off;
XX!   block_t b;
XX  
XX    num = next_inode++;
XX!   if (num > nrinodes) pexit("File system does not have enough inodes");
XX!   b = ((num - 1) / inodes_per_block) + inode_offset;
XX!   off = (num - 1) % inodes_per_block;
XX!   if (fs_version == 1) {
XX! 	d1_inode inode1[V1_INODES_PER_BLOCK];
XX  
XX+ 	get_block(b, (char *) inode1);
XX+ 	inode1[off].d1_mode = mode;
XX+ 	inode1[off].d1_uid = usrid;
XX+ 	inode1[off].d1_gid = grpid;
XX+ 	put_block(b, (char *) inode1);
XX+   } else {
XX+ 	d2_inode inode2[V2_INODES_PER_BLOCK];
XX+ 
XX+ 	get_block(b, (char *) inode2);
XX+ 	inode2[off].d2_mode = mode;
XX+ 	inode2[off].d2_uid = usrid;
XX+ 	inode2[off].d2_gid = grpid;
XX+ 	put_block(b, (char *) inode2);
XX+   }
XX+ 
XX    /* Set the bit in the bit map. */
XX!   /* DEBUG FIXME.  This assumes the bit is in the first inode map block. */
XX!   insert_bit((block_t) INODE_MAP, (int) num, 1);
XX    return(num);
XX  }
XX  
XX  
XX! PRIVATE zone_t alloc_zone()
XX  {
XX    /* Allocate a new zone */
XX    /* Works for zone > block */
XX!   block_t b;
XX!   int i;
XX!   zone_t z;
XX  
XX    z = next_zone++;
XX    b = z << zone_shift;
XX***************
XX*** 660,695 ****
XX  	pexit("File system not big enough for all the files");
XX    for (i = 0; i < zone_size; i++)
XX  	put_block(b + i, zero);	/* give an empty zone */
XX!   insert_bit(zone_map, z - zoff, 1);
XX    return(z);
XX  }
XX  
XX  
XX! 
XX! 
XX! insert_bit(block, bit, count)
XX! int block, bit, count;
XX  {
XX    /* Insert 'count' bits in the bitmap */
XX!   int w, s, i;
XX    short buf[BLOCK_SIZE / sizeof(short)];
XX  
XX!   get_block(block, buf);
XX    for (i = bit; i < bit + count; i++) {
XX  	w = i / (8 * sizeof(short));
XX  	s = i % (8 * sizeof(short));
XX  	buf[w] |= (1 << s);
XX    }
XX!   put_block(block, buf);
XX  }
XX  
XX  
XX- 
XX- 
XX  /*================================================================
XX   * 		proto-file processing assist group
XX   *===============================================================*/
XX- 
XX  int mode_con(p)
XX  char *p;
XX  {
XX--- 787,825 ----
XX  	pexit("File system not big enough for all the files");
XX    for (i = 0; i < zone_size; i++)
XX  	put_block(b + i, zero);	/* give an empty zone */
XX!   /* DEBUG FIXME.  This assumes the bit is in the first zone map block. */
XX!   insert_bit(zone_map, (int) (z - zoff), 1);	/* lint, NOT OK because
XX! 						 * z hasn't been broken
XX! 						 * up into block +
XX! 						 * offset yet. */
XX    return(z);
XX  }
XX  
XX  
XX! void insert_bit(block, bit, count)
XX! block_t block;
XX! int bit;
XX! int count;
XX  {
XX    /* Insert 'count' bits in the bitmap */
XX!   int w, s;
XX!   int i;
XX    short buf[BLOCK_SIZE / sizeof(short)];
XX  
XX!   if (block < 0) pexit("insert_bit called with negative argument");
XX!   get_block(block, (char *) buf);
XX    for (i = bit; i < bit + count; i++) {
XX  	w = i / (8 * sizeof(short));
XX  	s = i % (8 * sizeof(short));
XX  	buf[w] |= (1 << s);
XX    }
XX!   put_block(block, (char *) buf);
XX  }
XX  
XX  
XX  /*================================================================
XX   * 		proto-file processing assist group
XX   *===============================================================*/
XX  int mode_con(p)
XX  char *p;
XX  {
XX***************
XX*** 713,721 ****
XX    return(mode);
XX  }
XX  
XX! 
XX! 
XX! getline(line, parse)
XX  char *parse[MAX_TOKENS];
XX  char line[LINE_LEN];
XX  {
XX--- 843,849 ----
XX    return(mode);
XX  }
XX  
XX! void getline(line, parse)
XX  char *parse[MAX_TOKENS];
XX  char line[LINE_LEN];
XX  {
XX***************
XX*** 759,771 ****
XX  }
XX  
XX  
XX- 
XX- 
XX  /*================================================================
XX   *			other stuff
XX   *===============================================================*/
XX  
XX  
XX  long file_time(f)
XX  int f;
XX  {
XX--- 887,917 ----
XX  }
XX  
XX  
XX  /*================================================================
XX   *			other stuff
XX   *===============================================================*/
XX+ void check_mtab(devname)
XX+ char *devname;			/* /dev/hd1 or whatever */
XX+ {
XX+ /* Check to see if the special file named in s is mounted. */
XX  
XX+   int n;
XX+   char special[PATH_MAX + 1], mounted_on[PATH_MAX + 1], version[10], rw_flag[10];
XX  
XX+   if (load_mtab("mkfs") < 0) return;
XX+   while (1) {
XX+ 	n = get_mtab_entry(special, mounted_on, version, rw_flag);
XX+ 	if (n < 0) return;
XX+ 	if (strcmp(devname, special) == 0) {
XX+ 		/* Can't mkfs on top of a mounted file system. */
XX+ 		fprintf(stderr, "%s: %s is mounted on %s\n",
XX+ 			progname, devname, mounted_on);
XX+ 		exit(1);
XX+ 	}
XX+   }
XX+ }
XX+ 
XX+ 
XX  long file_time(f)
XX  int f;
XX  {
XX***************
XX*** 779,801 ****
XX  }
XX  
XX  
XX! pexit(s)
XX  char *s;
XX  {
XX!   char *s0;
XX! 
XX!   s0 = s;
XX!   while (*s0 != 0) s0++;
XX!   write(2, "Error: ", 7);
XX!   write(2, s, (int) (s0 - s));
XX!   write(2, "\n", 1);
XX!   printf("Line %d being processed when error detected.\n", lct);
XX    flush();
XX    exit(2);
XX  }
XX  
XX  
XX! copy(from, to, count)
XX  char *from, *to;
XX  int count;
XX  {
XX--- 925,942 ----
XX  }
XX  
XX  
XX! void pexit(s)
XX  char *s;
XX  {
XX!   fprintf(stderr, "%s: %s\n", progname, s);
XX!   if (lct != 0)
XX! 	fprintf(stderr, "Line %d being processed when error detected.\n", lct);
XX    flush();
XX    exit(2);
XX  }
XX  
XX  
XX! void copy(from, to, count)
XX  char *from, *to;
XX  int count;
XX  {
XX***************
XX*** 803,850 ****
XX  }
XX  
XX  
XX! print_fs()
XX  {
XX  
XX!   int i, j, k;
XX!   d_inode inode[INODES_PER_BLOCK];
XX!   int ibuf[INTS_PER_BLOCK], b;
XX!   struct {			/* FIXME, DEBUG - use <sys/dir.h> */
XX! 	ino_t inum;
XX! 	char name[14];
XX!   } dir[NR_DIR_ENTRIES];
XX! 
XX! 
XX!   get_block(1, ibuf);
XX    printf("\nSuperblock: ");
XX!   for (i = 0; i < 8; i++) printf("%06o ", ibuf[i]);
XX!   get_block(2, ibuf);
XX!   printf("\nInode map:  ");
XX!   for (i = 0; i < 9; i++) printf("%06o ", ibuf[i]);
XX!   get_block(3, ibuf);
XX!   printf("\nZone  map:  ");
XX!   for (i = 0; i < 9; i++) printf("%06o ", ibuf[i]);
XX!   printf("\n");
XX!   for (b = 4; b < 8; b++) {
XX! 	get_block(b, inode);
XX! 	for (i = 0; i < INODES_PER_BLOCK; i++) {
XX! 		k = INODES_PER_BLOCK * (b - 4) + i + 1;
XX  		if (k > nrinodes) break;
XX! 		if (inode[i].i_mode != 0) {
XX! 			printf("Inode %2d:  mode=", k, inode[i].i_mode);
XX! 			printf("%06o", inode[i].i_mode);
XX! 			printf("  uid=%2d  gid=%2d  size=",
XX! 			       inode[i].i_uid, inode[i].i_gid);
XX! 			printf("%6ld", inode[i].i_size);
XX! 			printf("  zone[0]=%d\n", inode[i].i_zone[0]);
XX  		}
XX- 		if ((inode[i].i_mode & I_TYPE) == I_DIRECTORY) {
XX- 			/* This is a directory */
XX- 			get_block(inode[i].i_zone[0], dir);
XX- 			for (j = 0; j < NR_DIR_ENTRIES; j++)
XX- 				if (dir[j].inum)
XX- 					printf("\tInode %2d: %s\n", dir[j].inum, dir[j].name);
XX- 		}
XX  	}
XX    }
XX  
XX--- 944,1013 ----
XX  }
XX  
XX  
XX! void print_fs()
XX  {
XX+   int i, j;
XX+   ino_t k;
XX+   d1_inode inode1[V1_INODES_PER_BLOCK];
XX+   d2_inode inode2[V2_INODES_PER_BLOCK];
XX+   unsigned short usbuf[BLOCK_SIZE / sizeof(unsigned short)];
XX+   block_t b;
XX+   struct direct dir[NR_DIR_ENTRIES];
XX  
XX!   get_block((block_t) 1, (char *) usbuf);
XX    printf("\nSuperblock: ");
XX!   for (i = 0; i < 8; i++) printf("%06o ", usbuf[i]);
XX!   get_block((block_t) 2, (char *) usbuf);
XX!   printf("...\nInode map:  ");
XX!   for (i = 0; i < 9; i++) printf("%06o ", usbuf[i]);
XX!   get_block((block_t) 3, (char *) usbuf);
XX!   printf("...\nZone  map:  ");
XX!   for (i = 0; i < 9; i++) printf("%06o ", usbuf[i]);
XX!   printf("...\n");
XX! 
XX!   for (b = inode_offset; b < inode_offset + I_MAP_SLOTS; b++) {
XX! 	if (fs_version == 1) {
XX! 		get_block(b, (char *) inode1);
XX! 	} else {
XX! 		get_block(b, (char *) inode2);
XX! 	}
XX! 	for (i = 0; i < inodes_per_block; i++) {
XX! 		k = inodes_per_block * (int) (b - inode_offset) + i + 1;
XX! 		/* Lint but OK */
XX  		if (k > nrinodes) break;
XX! 		if (fs_version == 1) {
XX! 			if (inode1[i].d1_mode != 0) {
XX! 				printf("Inode %2d:  mode=", k);
XX! 				printf("%06o", inode1[i].d1_mode);
XX! 				printf("  uid=%2d  gid=%2d  size=",
XX! 				inode1[i].d1_uid, inode1[i].d1_gid);
XX! 				printf("%6ld", inode1[i].d1_size);
XX! 				printf("  zone[0]=%d\n", inode1[i].d1_zone[0]);
XX! 			}
XX! 			if ((inode1[i].d1_mode & I_TYPE) == I_DIRECTORY) {
XX! 				/* This is a directory */
XX! 				get_block(inode1[i].d1_zone[0], (char *) dir);
XX! 				for (j = 0; j < NR_DIR_ENTRIES; j++)
XX! 					if (dir[j].d_ino)
XX! 						printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
XX! 			}
XX! 		} else {
XX! 			if (inode2[i].d2_mode != 0) {
XX! 				printf("Inode %2d:  mode=", k);
XX! 				printf("%06o", inode2[i].d2_mode);
XX! 				printf("  uid=%2d  gid=%2d  size=",
XX! 				inode2[i].d2_uid, inode2[i].d2_gid);
XX! 				printf("%6ld", inode2[i].d2_size);
XX! 				printf("  zone[0]=%ld\n", inode2[i].d2_zone[0]);
XX! 			}
XX! 			if ((inode2[i].d2_mode & I_TYPE) == I_DIRECTORY) {
XX! 				/* This is a directory */
XX! 				get_block(inode2[i].d2_zone[0], (char *) dir);
XX! 				for (j = 0; j < NR_DIR_ENTRIES; j++)
XX! 					if (dir[j].d_ino)
XX! 						printf("\tInode %2d: %s\n", dir[j].d_ino, dir[j].d_name);
XX! 			}
XX  		}
XX  	}
XX    }
XX  
XX***************
XX*** 853,880 ****
XX  
XX  
XX  int read_and_set(n)
XX! int n;
XX  {
XX! /*  The first time a block is read, it returns alls 0s, unless there has
XX!  *  been a write.  This routine checks to see if a block has been accessed.
XX   */
XX  
XX    int w, s, mask, r;
XX  
XX!   w = n / 8;
XX!   s = n % 8;
XX    mask = 1 << s;
XX    r = (umap[w] & mask ? 1 : 0);
XX    umap[w] |= mask;
XX    return(r);
XX  }
XX  
XX  
XX- 
XX  /*================================================================
XX   *		      get_block & put_block for MS-DOS
XX   *===============================================================*/
XX- 
XX  #ifdef DOS
XX  
XX  /*
XX--- 1016,1049 ----
XX  
XX  
XX  int read_and_set(n)
XX! block_t n;
XX  {
XX! /* The first time a block is read, it returns all 0s, unless there has
XX!  * been a write.  This routine checks to see if a block has been accessed.
XX   */
XX  
XX    int w, s, mask, r;
XX  
XX!   w = n / 8;			/* lint, not quite OK, but checked soon */
XX!   s = n % 8;			/* lint but OK */
XX!   if (8 * (block_t) w + s != n) pexit("N_BLOCKS too large");
XX    mask = 1 << s;
XX    r = (umap[w] & mask ? 1 : 0);
XX    umap[w] |= mask;
XX    return(r);
XX  }
XX  
XX+ void usage()
XX+ {
XX+   fprintf(stderr,
XX+ 	  "Usage: %s [-1dlot] [-b blocks] [-i inodes] special [proto]\n",
XX+ 	  progname);
XX+   exit(1);
XX+ }
XX  
XX  /*================================================================
XX   *		      get_block & put_block for MS-DOS
XX   *===============================================================*/
XX  #ifdef DOS
XX  
XX  /*
XX***************
XX*** 906,912 ****
XX  	     "seek error",
XX  	     "unknown media type",
XX  	     "sector not found",
XX! 	     "printer out of paper (??)",
XX  	     "write fault",
XX  	     "read error",
XX  	     "general error"
XX--- 1075,1081 ----
XX  	     "seek error",
XX  	     "unknown media type",
XX  	     "sector not found",
XX! 	     "printer out of paper (?)",
XX  	     "write fault",
XX  	     "read error",
XX  	     "general error"
XX***************
XX*** 917,931 ****
XX  
XX  struct cache {
XX    char blockbuf[BLOCK_SIZE];
XX!   int blocknum;
XX    int dirty;
XX    int usecnt;
XX  } cache[CACHE_SIZE];
XX  
XX  
XX! 
XX! 
XX! special(string)
XX  char *string;
XX  {
XX  
XX--- 1086,1098 ----
XX  
XX  struct cache {
XX    char blockbuf[BLOCK_SIZE];
XX!   block_t blocknum;
XX    int dirty;
XX    int usecnt;
XX  } cache[CACHE_SIZE];
XX  
XX  
XX! void special(string)
XX  char *string;
XX  {
XX  
XX***************
XX*** 941,950 ****
XX    }
XX  }
XX  
XX! 
XX! 
XX! get_block(n, buf)
XX! int n;
XX  char buf[BLOCK_SIZE];
XX  {
XX    /* Get a block to the user */
XX--- 1108,1115 ----
XX    }
XX  }
XX  
XX! void get_block(n, buf)
XX! block_t n;
XX  char buf[BLOCK_SIZE];
XX  {
XX    /* Get a block to the user */
XX***************
XX*** 987,1002 ****
XX    copy(fp, buf, BLOCK_SIZE);
XX  }
XX  
XX! 
XX! 
XX! put_block(n, buf)
XX! int n;
XX  char buf[BLOCK_SIZE];
XX  {
XX    /* Accept block from user */
XX    struct cache *fp, *bp;
XX  
XX!   read_and_set(n);
XX  
XX    /* Look for block in cache */
XX    fp = 0;
XX--- 1152,1165 ----
XX    copy(fp, buf, BLOCK_SIZE);
XX  }
XX  
XX! void put_block(n, buf)
XX! block_t n;
XX  char buf[BLOCK_SIZE];
XX  {
XX    /* Accept block from user */
XX    struct cache *fp, *bp;
XX  
XX!   (void) read_and_set(n);
XX  
XX    /* Look for block in cache */
XX    fp = 0;
XX***************
XX*** 1028,1044 ****
XX    copy(buf, fp, BLOCK_SIZE);
XX  }
XX  
XX! 
XX! 
XX! cache_init()
XX  {
XX    struct cache *bp;
XX    for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) bp->blocknum = -1;
XX  }
XX  
XX! 
XX! 
XX! flush()
XX  {
XX    /* Flush all dirty blocks to disk */
XX    struct cache *bp;
XX--- 1191,1203 ----
XX    copy(buf, fp, BLOCK_SIZE);
XX  }
XX  
XX! void cache_init()
XX  {
XX    struct cache *bp;
XX    for (bp = cache; bp < &cache[CACHE_SIZE]; bp++) bp->blocknum = -1;
XX  }
XX  
XX! void flush()
XX  {
XX    /* Flush all dirty blocks to disk */
XX    struct cache *bp;
XX***************
XX*** 1050,1065 ****
XX  	}
XX  }
XX  
XX- 
XX- 
XX  /*==================================================================
XX   *			hard read & write etc.
XX   *=================================================================*/
XX- 
XX  #define MAX_RETRIES	5
XX  
XX  
XX! mx_read(blocknr, buf)
XX  int blocknr;
XX  char buf[BLOCK_SIZE];
XX  {
XX--- 1209,1221 ----
XX  	}
XX  }
XX  
XX  /*==================================================================
XX   *			hard read & write etc.
XX   *=================================================================*/
XX  #define MAX_RETRIES	5
XX  
XX  
XX! void mx_read(blocknr, buf)
XX  int blocknr;
XX  char buf[BLOCK_SIZE];
XX  {
XX***************
XX*** 1069,1075 ****
XX    int sectnum, retries, err;
XX  
XX    if (file) {
XX! 	lseek(fd, (long) blocknr * BLOCK_SIZE, 0);
XX  	if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE)
XX  		pexit("mx_read: error reading file");
XX    } else {
XX--- 1225,1231 ----
XX    int sectnum, retries, err;
XX  
XX    if (file) {
XX! 	lseek(fd, (off_t) blocknr * BLOCK_SIZE, 0);
XX  	if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE)
XX  		pexit("mx_read: error reading file");
XX    } else {
XX***************
XX*** 1089,1097 ****
XX    }
XX  }
XX  
XX! 
XX! 
XX! mx_write(blocknr, buf)
XX  int blocknr;
XX  char buf[BLOCK_SIZE];
XX  {
XX--- 1245,1251 ----
XX    }
XX  }
XX  
XX! void mx_write(blocknr, buf)
XX  int blocknr;
XX  char buf[BLOCK_SIZE];
XX  {
XX***************
XX*** 1122,1128 ****
XX  }
XX  
XX  
XX! dexit(s, sectnum, err)
XX  int sectnum, err;
XX  char *s;
XX  {
XX--- 1276,1282 ----
XX  }
XX  
XX  
XX! void dexit(s, sectnum, err)
XX  int sectnum, err;
XX  char *s;
XX  {
XX***************
XX*** 1136,1145 ****
XX  /*================================================================
XX   *		      get_block & put_block for UNIX
XX   *===============================================================*/
XX- 
XX  #ifdef UNIX
XX  
XX! special(string)
XX  char *string;
XX  {
XX    fd = creat(string, 0777);
XX--- 1290,1298 ----
XX  /*================================================================
XX   *		      get_block & put_block for UNIX
XX   *===============================================================*/
XX  #ifdef UNIX
XX  
XX! void special(string)
XX  char *string;
XX  {
XX    fd = creat(string, 0777);
XX***************
XX*** 1150,1157 ****
XX    {
XX  	struct stat statbuf;
XX  
XX! 	if (fstat(fd, &statbuf) < 0)
XX! 		return;
XX  	isdev = (statbuf.st_mode & S_IFMT) == S_IFCHR
XX  		||
XX  		(statbuf.st_mode & S_IFMT) == S_IFBLK
XX--- 1303,1309 ----
XX    {
XX  	struct stat statbuf;
XX  
XX! 	if (fstat(fd, &statbuf) < 0) return;
XX  	isdev = (statbuf.st_mode & S_IFMT) == S_IFCHR
XX  		||
XX  		(statbuf.st_mode & S_IFMT) == S_IFBLK
XX***************
XX*** 1162,1171 ****
XX  
XX  
XX  
XX! 
XX! 
XX! get_block(n, buf)
XX! int n;
XX  char buf[BLOCK_SIZE];
XX  {
XX  /* Read a block. */
XX--- 1314,1321 ----
XX  
XX  
XX  
XX! void get_block(n, buf)
XX! block_t n;
XX  char buf[BLOCK_SIZE];
XX  {
XX  /* Read a block. */
XX***************
XX*** 1177,1200 ****
XX  	copy(zero, buf, BLOCK_SIZE);
XX  	return;
XX    }
XX!   lseek(fd, (long) n * BLOCK_SIZE, SEEK_SET);
XX    k = read(fd, buf, BLOCK_SIZE);
XX    if (k != BLOCK_SIZE) {
XX  	pexit("get_block couldn't read");
XX    }
XX  }
XX  
XX! 
XX! 
XX! put_block(n, buf)
XX! int n;
XX  char buf[BLOCK_SIZE];
XX  {
XX  /* Write a block. */
XX  
XX!   read_and_set(n);
XX  
XX!   if (lseek(fd, (long) n * BLOCK_SIZE, SEEK_SET) < 0L) {
XX  	pexit("put_block couldn't seek");
XX    }
XX    if (write(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
XX--- 1327,1349 ----
XX  	copy(zero, buf, BLOCK_SIZE);
XX  	return;
XX    }
XX!   lseek(fd, (off_t) n * BLOCK_SIZE, SEEK_SET);
XX    k = read(fd, buf, BLOCK_SIZE);
XX    if (k != BLOCK_SIZE) {
XX  	pexit("get_block couldn't read");
XX    }
XX  }
XX  
XX! void put_block(n, buf)
XX! block_t n;
XX  char buf[BLOCK_SIZE];
XX  {
XX  /* Write a block. */
XX  
XX!   (void) read_and_set(n);
XX  
XX!   /* XXX - check other lseeks too. */
XX!   if (lseek(fd, (off_t) n * BLOCK_SIZE, SEEK_SET) == (off_t) -1) {
XX  	pexit("put_block couldn't seek");
XX    }
XX    if (write(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
XX***************
XX*** 1205,1218 ****
XX  
XX  /* Dummy routines to keep source file clean from #ifdefs */
XX  
XX! flush()
XX  {
XX    return;
XX  }
XX  
XX! 
XX! 
XX! cache_init()
XX  {
XX    return;
XX  }
XX--- 1354,1365 ----
XX  
XX  /* Dummy routines to keep source file clean from #ifdefs */
XX  
XX! void flush()
XX  {
XX    return;
XX  }
XX  
XX! void cache_init()
XX  {
XX    return;
XX  }
X/
Xecho x - mknod.c.d
Xsed '/^X/s///' > mknod.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mknod.c  crc=03711    933	Sun Apr 25 21:35:08 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mknod.c  crc=65186   1721	Wed Nov  4 07:51:28 1992
XX***************
XX*** 1,43 ****
XX  /* mknod - build a special file		Author: Andy Tanenbaum */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX! /* mknod name b/c major minor [size] makes a node. */
XX  
XX!   int mode, major, minor, dev;
XX!   unsigned int size;
XX  
XX!   if (argc < 5) badcomm();
XX!   if (*argv[2] != 'b' && *argv[2] != 'c') badcomm();
XX    if (*argv[2] == 'c' && argc != 5) badchar();
XX    if (*argv[2] == 'b' && argc != 6) badblock();
XX!   mode = (*argv[2] == 'b' ? 060666 : 020666);
XX!   major = atoi(argv[3]);
XX!   minor = atoi(argv[4]);
XX!   size = (*argv[2] == 'b' ? atoi(argv[5]) : 0);
XX!   if (major < 0 || minor < 0) badcomm();
XX!   dev =  (major << 8) | minor;
XX!   if (mknod(argv[1], mode, dev, size) < 0) perror("mknod");
XX!   exit(0);
XX  }
XX  
XX! badcomm()
XX  {
XX!   std_err("Usage: mknod name b/c major minor [size_in_blocks]\n");
XX    exit(1);
XX  }
XX  
XX! badchar()
XX  {
XX    std_err("Usage: mknod name c major minor\n");
XX    exit(1);
XX  }
XX  
XX! badblock()
XX  {
XX    std_err("Usage: mknod name b major minor size_in_blocks\n");
XX    exit(1);
XX  }
XX- 
XX--- 1,78 ----
XX  /* mknod - build a special file		Author: Andy Tanenbaum */
XX  
XX! #include <sys/types.h>
XX! #include <stdlib.h>
XX! #include <unistd.h>
XX! #include <minix/minlib.h>
XX! #include <errno.h>
XX! #include <stdio.h>
XX! 
XX! #ifdef _MINIX
XX! #define MKNOD(p,M,m,s) mknod4(p,M,m,s)
XX! #else
XX! #define MKNOD(p,M,m,s) mknod(p,M,m)
XX! #endif
XX! 
XX! _PROTOTYPE(int main, (int argc, char *argv []));
XX! _PROTOTYPE(void badcomm, (void));
XX! _PROTOTYPE(void badfifo, (void));
XX! _PROTOTYPE(void badchar, (void));
XX! _PROTOTYPE(void badblock, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX! /* Mknod name b/c major minor [size] makes a node. */
XX  
XX!   int mode, major, minor, dev, e;
XX!   long size;
XX  
XX!   if (argc < 3) badcomm();
XX!   if (*argv[2] != 'b' && *argv[2] != 'c' && *argv[2] != 'p') badcomm();
XX!   if (*argv[2] == 'p' && argc != 3) badfifo();
XX    if (*argv[2] == 'c' && argc != 5) badchar();
XX    if (*argv[2] == 'b' && argc != 6) badblock();
XX!   if (*argv[2] == 'p') {
XX! 	mode = 010666;
XX! 	dev = 0;
XX! 	size = 0;
XX!   } else {
XX! 	mode = (*argv[2] == 'b' ? 060666 : 020666);
XX! 	major = atoi(argv[3]);
XX! 	minor = atoi(argv[4]);
XX! 	size = (*argv[2] == 'b' ? atol(argv[5]) : 0);
XX! 	if (major - 1 > 0xFE || minor > 0xFF) badcomm();
XX! 	dev = (major << 8) | minor;
XX!   }
XX!   e = MKNOD(argv[1], mode, dev, size);
XX!   if (e < 0 && *argv[2] != 'p' && errno == EPERM)
XX! 	std_err("mknod: Inode not made. Only the superuser can make inodes\n");
XX!   else if (e < 0)
XX! 	perror("mknod");
XX!   return(0);
XX  }
XX  
XX! void badcomm()
XX  {
XX!   std_err("Usage: mknod name b/c/p [major minor [size_in_blocks]]\n");
XX    exit(1);
XX  }
XX  
XX! void badfifo()
XX  {
XX+   std_err("Usage: mknod name p\n");
XX+   exit(1);
XX+ }
XX+ 
XX+ void badchar()
XX+ {
XX    std_err("Usage: mknod name c major minor\n");
XX    exit(1);
XX  }
XX  
XX! void badblock()
XX  {
XX    std_err("Usage: mknod name b major minor size_in_blocks\n");
XX    exit(1);
XX  }
X/
Xecho x - mkproto.c.d
Xsed '/^X/s///' > mkproto.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mkproto.c  crc=50067   5847	Sun Apr 25 21:35:08 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mkproto.c  crc=51470   6026	Wed Nov  4 04:19:15 1992
XX***************
XX*** 7,12 ****
XX--- 7,13 ----
XX  #include <limits.h>
XX  #include <dirent.h>
XX  #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  /* The default values for the prototype file */
XX***************
XX*** 28,47 ****
XX  char *proto_file, *top;
XX  FILE *outfile;
XX  
XX- /* For getopt. */
XX- extern int getopt();
XX  extern int optind;
XX  extern char *optarg;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX-   int i;
XX-   register char *ptr;		/* Ptr to *argv in use */
XX    char *dir;
XX    struct stat st;
XX!   char op;
XX  
XX    gid = DEF_GID;
XX    uid = DEF_UID;
XX--- 29,50 ----
XX  char *proto_file, *top;
XX  FILE *outfile;
XX  
XX  extern int optind;
XX  extern char *optarg;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void descend, (char *dirname));
XX! _PROTOTYPE(void display_attrib, (char *name, struct stat *st));
XX! _PROTOTYPE(void usage, (char *binname));
XX! _PROTOTYPE(void open_outfile, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    char *dir;
XX    struct stat st;
XX!   int op;
XX  
XX    gid = DEF_GID;
XX    uid = DEF_UID;
XX***************
XX*** 118,135 ****
XX    fprintf(outfile, "\n");
XX    descend(dir);
XX    fprintf(outfile, "$\n");
XX  }
XX  
XX  /* Output the prototype spec for this directory. */
XX! descend(dirname)
XX  char *dirname;
XX  {
XX    struct dirent *dp;
XX    DIR *dirp;
XX!   char *bs, *name, *newdir, *temp, *tempend;
XX    int i;
XX    struct stat st;
XX!   unsigned short mode;
XX  
XX    dirp = opendir(dirname);
XX    if (dirp == NULL) {
XX--- 121,139 ----
XX    fprintf(outfile, "\n");
XX    descend(dir);
XX    fprintf(outfile, "$\n");
XX+   return(0);
XX  }
XX  
XX  /* Output the prototype spec for this directory. */
XX! void descend(dirname)
XX  char *dirname;
XX  {
XX    struct dirent *dp;
XX    DIR *dirp;
XX!   char *name, *temp, *tempend;
XX    int i;
XX    struct stat st;
XX!   mode_t mode;
XX  
XX    dirp = opendir(dirname);
XX    if (dirp == NULL) {
XX***************
XX*** 152,158 ****
XX  		fprintf(stderr, "cant get status of '%s' \n", temp);
XX  		continue;
XX  	}
XX! 	if (name[0] == '.' && (name[1] == 0 || name[1] == '.' && name[2] == 0))
XX  		continue;
XX  
XX  	display_attrib(name, &st);
XX--- 156,163 ----
XX  		fprintf(stderr, "cant get status of '%s' \n", temp);
XX  		continue;
XX  	}
XX! 	if (name[0] == '.' && (name[1] == 0 ||
XX! 	    (name[1] == '.' && name[2] == 0)))
XX  		continue;
XX  
XX  	display_attrib(name, &st);
XX***************
XX*** 190,196 ****
XX  }
XX  
XX  
XX! display_attrib(name, st)
XX  char *name;
XX  struct stat *st;
XX  {
XX--- 195,201 ----
XX  }
XX  
XX  
XX! void display_attrib(name, st)
XX  char *name;
XX  struct stat *st;
XX  {
XX***************
XX*** 217,223 ****
XX  	gid);
XX  }
XX  
XX! usage(binname)
XX  char *binname;
XX  {
XX    fprintf(stderr, "Usage: %s [options] source_directory [prototype_file]\n", binname);
XX--- 222,228 ----
XX  	gid);
XX  }
XX  
XX! void usage(binname)
XX  char *binname;
XX  {
XX    fprintf(stderr, "Usage: %s [options] source_directory [prototype_file]\n", binname);
XX***************
XX*** 233,239 ****
XX    exit(1);
XX  }
XX  
XX! open_outfile()
XX  {
XX    if (proto_file == NULL)
XX  	outfile = stdout;
XX--- 238,244 ----
XX    exit(1);
XX  }
XX  
XX! void open_outfile()
XX  {
XX    if (proto_file == NULL)
XX  	outfile = stdout;
X/
Xecho x - modem.c.d
Xsed '/^X/s///' > modem.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/modem.c  crc=65518   4875	Sun Apr 25 21:35:08 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/modem.c  crc=32974   5086	Wed Nov  4 04:19:15 1992
XX***************
XX*** 19,33 ****
XX  #include <signal.h>
XX  #include <string.h>
XX  #include <utmp.h>
XX  
XX  static char *Version = "@(#) MODEM 1.3 (12/30/89)";
XX  int debug = 0;			/* generate some debugging output */
XX  int rings = -999;		/* number of rings for dial-in */
XX  
XX  
XX- extern char *itoa();
XX- 
XX- 
XX  /* Tell modem to go into DIAL-IN mode.
XX   * We do this by resetting it and by setting the
XX   * S0-register to a positive value.
XX--- 19,37 ----
XX  #include <signal.h>
XX  #include <string.h>
XX  #include <utmp.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX  
XX  static char *Version = "@(#) MODEM 1.3 (12/30/89)";
XX  int debug = 0;			/* generate some debugging output */
XX  int rings = -999;		/* number of rings for dial-in */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(int dialin, (char *tty));
XX+ _PROTOTYPE(int dialout, (char *tty));
XX+ _PROTOTYPE(void usage, (void));
XX  
XX  /* Tell modem to go into DIAL-IN mode.
XX   * We do this by resetting it and by setting the
XX   * S0-register to a positive value.
XX***************
XX*** 134,140 ****
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 138,144 ----
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 180,186 ****
XX  	write(2, "modem: cannot open UTMP !\n", 26);
XX  	exit(-1);
XX    }
XX!   while (read(fd, &entry, sizeof(struct utmp)) == sizeof(struct utmp)) {
XX  	if (!strcmp(entry.ut_line, tty)) {
XX  		close(fd);
XX  		tty = entry.ut_line;
XX--- 184,190 ----
XX  	write(2, "modem: cannot open UTMP !\n", 26);
XX  	exit(-1);
XX    }
XX!   while (read(fd, (char *)&entry, sizeof(struct utmp)) == sizeof(struct utmp)) {
XX  	if (!strcmp(entry.ut_line, tty)) {
XX  		close(fd);
XX  		tty = entry.ut_line;
XX***************
XX*** 222,226 ****
XX  	kill(entry.ut_pid, SIGIOT);	/* send RESTART signal */
XX  	st = dialin(tty);		/* put MODEM in DIALIN */
XX    }
XX!   exit(st);
XX  }
XX--- 226,230 ----
XX  	kill(entry.ut_pid, SIGIOT);	/* send RESTART signal */
XX  	st = dialin(tty);		/* put MODEM in DIALIN */
XX    }
XX!   return(st);
XX  }
X/
Xecho x - more.c.d
Xsed '/^X/s///' > more.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/more.c  crc=27694  37921	Sun Apr 25 21:35:09 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/more.c  crc=47154  39770	Mon Dec 21 18:55:48 1992
XX***************
XX*** 33,39 ****
XX  #include <signal.h>
XX  #include <sgtty.h>
XX  #include <setjmp.h>
XX! #include <stdio.h>
XX  
XX  #undef SIGTSTP			/* POSIX requires it to be defined */
XX  
XX--- 33,44 ----
XX  #include <signal.h>
XX  #include <sgtty.h>
XX  #include <setjmp.h>
XX! #include <stdarg.h>
XX! #include <stdlib.h>
XX! #include <string.h>
XX! #include <termcap.h>
XX! #include <unistd.h>
XX! #include <sys/wait.h>
XX  
XX  #undef SIGTSTP			/* POSIX requires it to be defined */
XX  
XX***************
XX*** 42,58 ****
XX  #include <sys/file.h>
XX  #endif
XX  #include <a.out.h>
XX  
XX  /* varargs ------- */
XX  /*  varargs.h  */
XX  
XX- typedef char *va_list;
XX- 
XX- #define  va_dcl		int va_alist;
XX- #define  va_start(p)	(p) = (va_list) &va_alist;
XX- #define  va_arg(p,type)	( (type *) ((p)+=sizeof(type)) )[-1]
XX- #define  va_end(p)
XX- 
XX  #define  vfPrintf	_doPrintf
XX  #define  vPrintf(fmt,args)	vfPrintf(stdout,fmt,args)
XX  /* end of varargs.h -------- */
XX--- 47,57 ----
XX  #include <sys/file.h>
XX  #endif
XX  #include <a.out.h>
XX+ #include <stdio.h>
XX  
XX  /* varargs ------- */
XX  /*  varargs.h  */
XX  
XX  #define  vfPrintf	_doPrintf
XX  #define  vPrintf(fmt,args)	vfPrintf(stdout,fmt,args)
XX  /* end of varargs.h -------- */
XX***************
XX*** 87,99 ****
XX  #define ESC	'\033'
XX  #define QUIT	'\034'
XX  
XX- int Printf();
XX  
XX  struct sgttyb	otty, savetty;
XX- void		onquit(), end_it(), onsusp();
XX  long		file_pos, file_size;
XX  int		fnum, no_intty, no_tty, slow_tty;
XX! int		dum_opt, dlines, chgwinsz();
XX  int		nscroll = 11;	/* Number of lines scrolled by 'd' */
XX  int		fold_opt = 1;	/* Fold long lines */
XX  int		stop_opt = 1;	/* Stop after form feeds */
XX--- 86,96 ----
XX  #define ESC	'\033'
XX  #define QUIT	'\034'
XX  
XX  
XX  struct sgttyb	otty, savetty;
XX  long		file_pos, file_size;
XX  int		fnum, no_intty, no_tty, slow_tty;
XX! int		dum_opt, dlines;
XX  int		nscroll = 11;	/* Number of lines scrolled by 'd' */
XX  int		fold_opt = 1;	/* Fold long lines */
XX  int		stop_opt = 1;	/* Stop after form feeds */
XX***************
XX*** 130,150 ****
XX  char		*cursorm;	/* cursor movement */
XX  char		cursorhome[40];	/* contains cursor movement to home */
XX  char		*EodClr;	/* clear rest of screen */
XX- char		*tgetstr();
XX- char		*tgoto();
XX  int		Mcol = 80;	/* number of columns */
XX  int		Wrap = 1;	/* set if automargins */
XX  int		soglitch;	/* terminal has standout mode glitch */
XX  int		ulglitch;	/* terminal has underline mode glitch */
XX  int		pstate = 0;	/* current UL state */
XX- char		*getenv();
XX  struct {
XX      long chrctr, line;
XX  } context, screen_start;
XX  
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 127,192 ----
XX  char		*cursorm;	/* cursor movement */
XX  char		cursorhome[40];	/* contains cursor movement to home */
XX  char		*EodClr;	/* clear rest of screen */
XX  int		Mcol = 80;	/* number of columns */
XX  int		Wrap = 1;	/* set if automargins */
XX  int		soglitch;	/* terminal has standout mode glitch */
XX  int		ulglitch;	/* terminal has underline mode glitch */
XX  int		pstate = 0;	/* current UL state */
XX  struct {
XX      long chrctr, line;
XX  } context, screen_start;
XX  
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ #ifndef _MINIX
XX+ _PROTOTYPE(static magic, (FILE *f, char *fs));
XX+ #endif
XX+ _PROTOTYPE(void argscan, (char *s));
XX+ _PROTOTYPE(FILE *checkf, (char *fs, int *clearfirst));
XX+ _PROTOTYPE(void putch, (int ch));
XX+ _PROTOTYPE(void screen, (FILE *f, int num_lines));
XX+ _PROTOTYPE(void onquit, (int sig));
XX+ _PROTOTYPE(int chgwinsz, (void));
XX+ _PROTOTYPE(void end_it, (int sig));
XX+ _PROTOTYPE(void copy_file, (FILE *f));
XX+ _PROTOTYPE(int Printf, (char *fmt, ...));
XX+ _PROTOTYPE(int printd, (int n));
XX+ _PROTOTYPE(void scanstr, (int n, char *str));
XX+ _PROTOTYPE(void SPrintf, (int n));
XX+ _PROTOTYPE(int tailequ, (char *path, char *string));
XX+ _PROTOTYPE(void prompt, (char *filename));
XX+ _PROTOTYPE(int getline, (FILE *f, int *length));
XX+ _PROTOTYPE(void erase, (int col));
XX+ _PROTOTYPE(void kill_line, (void));
XX+ _PROTOTYPE(void cleareol, (void));
XX+ _PROTOTYPE(void clreos, (void));
XX+ _PROTOTYPE(int pr, (char *s1));
XX+ _PROTOTYPE(void prbuf, (char *s, int n));
XX+ _PROTOTYPE(void doclear, (void));
XX+ _PROTOTYPE(void home, (void));
XX+ _PROTOTYPE(int command, (char *filename, FILE *f));
XX+ _PROTOTYPE(int colon, (char *filename, int cmd, int nlines));
XX+ _PROTOTYPE(int number, (char *cmd));
XX+ _PROTOTYPE(void do_shell, (char *filename));
XX+ _PROTOTYPE(void search, (char buf [], FILE *file, int n));
XX+ _PROTOTYPE(void execute, (char *filename, char *cmd, ...));
XX+ _PROTOTYPE(void skiplns, (int n, FILE *f));
XX+ _PROTOTYPE(void skipf, (int nskip));
XX+ _PROTOTYPE(void initterm, (void));
XX+ _PROTOTYPE(int readch, (void));
XX+ _PROTOTYPE(void ttyin, (char buf [], int nmax, int pchar));
XX+ _PROTOTYPE(int expand, (char *outbuf, char *inbuf));
XX+ _PROTOTYPE(void show, (int ch));
XX+ _PROTOTYPE(void error, (char *mess));
XX+ _PROTOTYPE(void set_tty, (void));
XX+ _PROTOTYPE(void reset_tty, (void));
XX+ _PROTOTYPE(void rdline, (FILE *f));
XX+ _PROTOTYPE(void onsusp, (void));
XX+ _PROTOTYPE(char *re_comp, (char *str));
XX+ _PROTOTYPE(int re_exec, (char *str));
XX+ _PROTOTYPE(void regerror, (char *str));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 159,165 ****
XX      int			clearit = 0;
XX      int			initline;
XX      char		initbuf[80];
XX-     FILE		*checkf();
XX  
XX      nfiles = argc;
XX      fnames = argv;
XX--- 201,206 ----
XX***************
XX*** 207,214 ****
XX      if (nfiles > 1)
XX  	prnames++;
XX      if (!no_intty && nfiles == 0) {
XX- 	char *rindex();
XX- 
XX  	p = rindex(argv[0], '/');
XX  	fputs("Usage: ",stderr);
XX  	fputs(p ? p + 1 : argv[0],stderr);
XX--- 248,253 ----
XX***************
XX*** 321,330 ****
XX  	firstf = 0;
XX      }
XX      reset_tty ();
XX!     exit(0);
XX  }
XX  
XX! argscan(s)
XX  char *s;
XX  {
XX  	int seen_num = 0;
XX--- 360,369 ----
XX  	firstf = 0;
XX      }
XX      reset_tty ();
XX!     return(0);
XX  }
XX  
XX! void argscan(s)
XX  char *s;
XX  {
XX  	int seen_num = 0;
XX***************
XX*** 387,406 ****
XX  		if (clreol)
XX  			cleareol ();
XX  		perror(fs);
XX! 		return((FILE *)NULL);
XX  	}
XX  	if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
XX  		Printf("\n*** %s: directory ***\n\n", fs);
XX! 		return((FILE *)NULL);
XX  	}
XX  	if ((f = Fopen(fs, "r")) == NULL) {
XX  		(void)fflush(stdout);
XX  		perror(fs);
XX! 		return((FILE *)NULL);
XX  	}
XX  #ifndef _MINIX
XX  	if (magic(f, fs))
XX! 		return((FILE *)NULL);
XX  #endif /*  !_MINIX */
XX  	c = Getc(f);
XX  	*clearfirst = c == '\f';
XX--- 426,445 ----
XX  		if (clreol)
XX  			cleareol ();
XX  		perror(fs);
XX! 		return(NULL);
XX  	}
XX  	if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
XX  		Printf("\n*** %s: directory ***\n\n", fs);
XX! 		return(NULL);
XX  	}
XX  	if ((f = Fopen(fs, "r")) == NULL) {
XX  		(void)fflush(stdout);
XX  		perror(fs);
XX! 		return(NULL);
XX  	}
XX  #ifndef _MINIX
XX  	if (magic(f, fs))
XX! 		return(NULL);
XX  #endif /*  !_MINIX */
XX  	c = Getc(f);
XX  	*clearfirst = c == '\f';
XX***************
XX*** 423,429 ****
XX  {
XX  	struct exec ex;
XX  
XX! 	if (fread(&ex, sizeof(ex), 1, f) == 1)
XX  		switch(ex.a_magic) {
XX  		case OMAGIC:
XX  		case NMAGIC:
XX--- 462,468 ----
XX  {
XX  	struct exec ex;
XX  
XX! 	if (fread(&ex, sizeof(ex), (size_t)1, f) == 1)
XX  		switch(ex.a_magic) {
XX  		case OMAGIC:
XX  		case NMAGIC:
XX***************
XX*** 444,450 ****
XX  ** A real function, for the tputs routine in termlib
XX  */
XX  
XX! putch (ch)
XX  char ch;
XX  {
XX      putchar (ch);
XX--- 483,489 ----
XX  ** A real function, for the tputs routine in termlib
XX  */
XX  
XX! void putch (ch)
XX  char ch;
XX  {
XX      putchar (ch);
XX***************
XX*** 456,462 ****
XX  
XX  #define STOP -10
XX  
XX! screen (f, num_lines)
XX  register FILE *f;
XX  register int num_lines;
XX  {
XX--- 495,501 ----
XX  
XX  #define STOP -10
XX  
XX! void screen (f, num_lines)
XX  register FILE *f;
XX  register int num_lines;
XX  {
XX***************
XX*** 476,482 ****
XX  	    if (ssp_opt && length == 0 && prev_len == 0)
XX  		continue;
XX  	    prev_len = length;
XX! 	    if (bad_so || (Senter && *Senter == ' ') && promptlen > 0)
XX  		erase (0);
XX  	    /* must clear before drawing line since tabs on some terminals
XX  	     * do not erase what they tab over.
XX--- 515,521 ----
XX  	    if (ssp_opt && length == 0 && prev_len == 0)
XX  		continue;
XX  	    prev_len = length;
XX! 	    if (bad_so || (Senter && *Senter == ' ' && promptlen > 0))
XX  		erase (0);
XX  	    /* must clear before drawing line since tabs on some terminals
XX  	     * do not erase what they tab over.
XX***************
XX*** 489,495 ****
XX  	    else promptlen = 0;
XX  	    /* is this needed?
XX  	     * if (clreol)
XX! 	     *	cleareol();	/* must clear again in case we wrapped *
XX  	     */
XX  	    if (nchars < Mcol || !fold_opt)
XX  		prbuf("\n", 1);	/* will turn off UL if necessary */
XX--- 528,534 ----
XX  	    else promptlen = 0;
XX  	    /* is this needed?
XX  	     * if (clreol)
XX! 	     *	cleareol();	  must clear again in case we wrapped
XX  	     */
XX  	    if (nchars < Mcol || !fold_opt)
XX  		prbuf("\n", 1);	/* will turn off UL if necessary */
XX***************
XX*** 602,608 ****
XX      _exit(0);
XX  }
XX  
XX! copy_file(f)
XX  register FILE *f;
XX  {
XX      register int c;
XX--- 641,647 ----
XX      _exit(0);
XX  }
XX  
XX! void copy_file(f)
XX  register FILE *f;
XX  {
XX      register int c;
XX***************
XX*** 613,628 ****
XX  
XX  /* Simplified Printf function */
XX  
XX! int Printf (fmt, va_alist)
XX! register char *fmt;
XX! va_dcl
XX  {
XX  	va_list ap;
XX  	register char ch;
XX  	register int ccount;
XX  
XX  	ccount = 0;
XX! 	va_start(ap);
XX  	while (*fmt) {
XX  		while ((ch = *fmt++) != '%') {
XX  			if (ch == '\0')
XX--- 652,670 ----
XX  
XX  /* Simplified Printf function */
XX  
XX! #if __STDC__
XX! int Printf (char *fmt, ...)
XX! #else
XX! int Printf (fmt)
XX! char *fmt;
XX! #endif
XX  {
XX  	va_list ap;
XX  	register char ch;
XX  	register int ccount;
XX  
XX  	ccount = 0;
XX! 	va_start(ap, fmt);
XX  	while (*fmt) {
XX  		while ((ch = *fmt++) != '%') {
XX  			if (ch == '\0')
XX***************
XX*** 657,663 ****
XX  ** returning the length of the print representation.
XX  */
XX  
XX! printd (n)
XX  int n;
XX  {
XX      int a, nchars;
XX--- 699,705 ----
XX  ** returning the length of the print representation.
XX  */
XX  
XX! int printd (n)
XX  int n;
XX  {
XX      int a, nchars;
XX***************
XX*** 673,679 ****
XX  /* Put the print representation of an integer into a string */
XX  static char *sptr;
XX  
XX! scanstr (n, str)
XX  int n;
XX  char *str;
XX  {
XX--- 715,721 ----
XX  /* Put the print representation of an integer into a string */
XX  static char *sptr;
XX  
XX! void scanstr (n, str)
XX  int n;
XX  char *str;
XX  {
XX***************
XX*** 682,688 ****
XX      *sptr = '\0';
XX  }
XX  
XX! SPrintf (n)
XX  {
XX      int a;
XX  
XX--- 724,731 ----
XX      *sptr = '\0';
XX  }
XX  
XX! void SPrintf (n)
XX! int n;
XX  {
XX      int a;
XX  
XX***************
XX*** 693,714 ****
XX  
XX  static char bell = ctrl('G');
XX  
XX- strlen (s)
XX- char *s;
XX- {
XX-     register char *p;
XX  
XX-     p = s;
XX-     while (*p++)
XX- 	;
XX-     return (p - s - 1);
XX- }
XX- 
XX  /* See whether the last component of the path name "path" is equal to the
XX  ** string "string"
XX  */
XX  
XX! tailequ (path, string)
XX  char *path;
XX  register char *string;
XX  {
XX--- 736,747 ----
XX  
XX  static char bell = ctrl('G');
XX  
XX  
XX  /* See whether the last component of the path name "path" is equal to the
XX  ** string "string"
XX  */
XX  
XX! int tailequ (path, string)
XX  char *path;
XX  register char *string;
XX  {
XX***************
XX*** 725,731 ****
XX  	return(0);
XX  }
XX  
XX! prompt (filename)
XX  char *filename;
XX  {
XX      if (clreol)
XX--- 758,764 ----
XX  	return(0);
XX  }
XX  
XX! void prompt (filename)
XX  char *filename;
XX  {
XX      if (clreol)
XX***************
XX*** 765,771 ****
XX  ** Get a logical line
XX  */
XX  
XX! getline(f, length)
XX  register FILE *f;
XX  int *length;
XX  {
XX--- 798,804 ----
XX  ** Get a logical line
XX  */
XX  
XX! int getline(f, length)
XX  register FILE *f;
XX  int *length;
XX  {
XX***************
XX*** 797,803 ****
XX  	}
XX  	*p++ = c;
XX  	if (c == '\t')
XX! 	    if (!hardtabs || column < promptlen && !hard) {
XX  		if (hardtabs && eraseln && !dumb) {
XX  		    column = 1 + (column | 7);
XX  		    tputs (eraseln, 1, putch);
XX--- 830,836 ----
XX  	}
XX  	*p++ = c;
XX  	if (c == '\t')
XX! 	    if (!hardtabs || (column < promptlen && !hard)) {
XX  		if (hardtabs && eraseln && !dumb) {
XX  		    column = 1 + (column | 7);
XX  		    tputs (eraseln, 1, putch);
XX***************
XX*** 851,857 ****
XX  ** Erase the rest of the prompt, assuming we are starting at column col.
XX  */
XX  
XX! erase (col)
XX  register int col;
XX  {
XX  
XX--- 884,890 ----
XX  ** Erase the rest of the prompt, assuming we are starting at column col.
XX  */
XX  
XX! void erase (col)
XX  register int col;
XX  {
XX  
XX***************
XX*** 876,882 ****
XX  ** Erase the current line entirely
XX  */
XX  
XX! kill_line ()
XX  {
XX      erase (0);
XX      if (!eraseln || dumb) putchar ('\r');
XX--- 909,915 ----
XX  ** Erase the current line entirely
XX  */
XX  
XX! void kill_line ()
XX  {
XX      erase (0);
XX      if (!eraseln || dumb) putchar ('\r');
XX***************
XX*** 885,896 ****
XX  /*
XX   * force clear to end of line
XX   */
XX! cleareol()
XX  {
XX      tputs(eraseln, 1, putch);
XX  }
XX  
XX! clreos()
XX  {
XX      tputs(EodClr, 1, putch);
XX  }
XX--- 918,929 ----
XX  /*
XX   * force clear to end of line
XX   */
XX! void cleareol()
XX  {
XX      tputs(eraseln, 1, putch);
XX  }
XX  
XX! void clreos()
XX  {
XX      tputs(EodClr, 1, putch);
XX  }
XX***************
XX*** 899,905 ****
XX  **  Print string and return number of characters
XX  */
XX  
XX! pr(s1)
XX  char	*s1;
XX  {
XX      register char	*s;
XX--- 932,938 ----
XX  **  Print string and return number of characters
XX  */
XX  
XX! int pr(s1)
XX  char	*s1;
XX  {
XX      register char	*s;
XX***************
XX*** 913,919 ****
XX  
XX  /* Print a buffer of n characters */
XX  
XX! prbuf (s, n)
XX  register char *s;
XX  register int n;
XX  {
XX--- 946,952 ----
XX  
XX  /* Print a buffer of n characters */
XX  
XX! void prbuf (s, n)
XX  register char *s;
XX  register int n;
XX  {
XX***************
XX*** 955,961 ****
XX  **  Clear the screen
XX  */
XX  
XX! doclear()
XX  {
XX      if (Clear && !hard) {
XX  	tputs(Clear, 1, putch);
XX--- 988,994 ----
XX  **  Clear the screen
XX  */
XX  
XX! void doclear()
XX  {
XX      if (Clear && !hard) {
XX  	tputs(Clear, 1, putch);
XX***************
XX*** 971,977 ****
XX  /*
XX   * Go to home position
XX   */
XX! home()
XX  {
XX      tputs(Home,1,putch);
XX  }
XX--- 1004,1010 ----
XX  /*
XX   * Go to home position
XX   */
XX! void home()
XX  {
XX      tputs(Home,1,putch);
XX  }
XX***************
XX*** 987,993 ****
XX  ** in the current file, zero is returned.
XX  */
XX  
XX! command (filename, f)
XX  char *filename;
XX  register FILE *f;
XX  {
XX--- 1020,1026 ----
XX  ** in the current file, zero is returned.
XX  */
XX  
XX! int command (filename, f)
XX  char *filename;
XX  register FILE *f;
XX  {
XX***************
XX*** 997,1003 ****
XX      char colonch;
XX      FILE *helpf;
XX      int done;
XX!     char comchar, cmdbuf[80], *p;
XX  
XX  #define ret(val) retval=val;done++;break
XX  
XX--- 1030,1036 ----
XX      char colonch;
XX      FILE *helpf;
XX      int done;
XX!     char comchar, cmdbuf[80];
XX  
XX  #define ret(val) retval=val;done++;break
XX  
XX***************
XX*** 1085,1091 ****
XX  	    ret (nscroll);
XX  	case 'q':
XX  	case 'Q':
XX! 	    end_it ();
XX  	case 's':
XX  	case 'f':
XX  	    if (nlines == 0) nlines++;
XX--- 1118,1124 ----
XX  	    ret (nscroll);
XX  	case 'q':
XX  	case 'Q':
XX! 	    end_it ( 0 );
XX  	case 's':
XX  	case 'f':
XX  	    if (nlines == 0) nlines++;
XX***************
XX*** 1174,1180 ****
XX  	    break;
XX  	case '?':
XX  	case 'h':
XX! 	    if ((helpf = fopen (HELPFILE, "r")) == (FILE *)NULL)
XX  		error ("Can't open help file");
XX  	    if (noscroll) doclear ();
XX  	    copy_file (helpf);
XX--- 1207,1213 ----
XX  	    break;
XX  	case '?':
XX  	case 'h':
XX! 	    if ((helpf = fopen (HELPFILE, "r")) == NULL)
XX  		error ("Can't open help file");
XX  	    if (noscroll) doclear ();
XX  	    copy_file (helpf);
XX***************
XX*** 1228,1234 ****
XX   * more of the file to be printed.
XX   */
XX  
XX! colon (filename, cmd, nlines)
XX  char *filename;
XX  int cmd;
XX  int nlines;
XX--- 1261,1267 ----
XX   * more of the file to be printed.
XX   */
XX  
XX! int colon (filename, cmd, nlines)
XX  char *filename;
XX  int cmd;
XX  int nlines;
XX***************
XX*** 1250,1256 ****
XX  	case 'n':
XX  		if (nlines == 0) {
XX  			if (fnum >= nfiles - 1)
XX! 				end_it ();
XX  			nlines++;
XX  		}
XX  		putchar ('\r');
XX--- 1283,1289 ----
XX  	case 'n':
XX  		if (nlines == 0) {
XX  			if (fnum >= nfiles - 1)
XX! 				end_it (0);
XX  			nlines++;
XX  		}
XX  		putchar ('\r');
XX***************
XX*** 1273,1279 ****
XX  		return (-1);
XX  	case 'q':
XX  	case 'Q':
XX! 		end_it ();
XX  	default:
XX  		write (2, &bell, 1);
XX  		return (-1);
XX--- 1306,1312 ----
XX  		return (-1);
XX  	case 'q':
XX  	case 'Q':
XX! 		end_it (0);
XX  	default:
XX  		write (2, &bell, 1);
XX  		return (-1);
XX***************
XX*** 1285,1291 ****
XX  ** terminates the number.
XX  */
XX  
XX! number(cmd)
XX  char *cmd;
XX  {
XX  	register int i;
XX--- 1318,1324 ----
XX  ** terminates the number.
XX  */
XX  
XX! int number(cmd)
XX  char *cmd;
XX  {
XX  	register int i;
XX***************
XX*** 1305,1311 ****
XX  	return (i);
XX  }
XX  
XX! do_shell (filename)
XX  char *filename;
XX  {
XX  	char cmdbuf[80];
XX--- 1338,1344 ----
XX  	return (i);
XX  }
XX  
XX! void do_shell (filename)
XX  char *filename;
XX  {
XX  	char cmdbuf[80];
XX***************
XX*** 1334,1340 ****
XX  ** Search for nth ocurrence of regular expression contained in buf in the file
XX  */
XX  
XX! search (buf, file, n)
XX  char buf[];
XX  FILE *file;
XX  register int n;
XX--- 1367,1373 ----
XX  ** Search for nth ocurrence of regular expression contained in buf in the file
XX  */
XX  
XX! void search (buf, file, n)
XX  char buf[];
XX  FILE *file;
XX  register int n;
XX***************
XX*** 1344,1351 ****
XX      register long line2 = startline;
XX      register long line3 = startline;
XX      register int lncount;
XX!     int saveln, rv, re_exec();
XX!     char *s, *re_comp();
XX  
XX      context.line = saveln = Currline;
XX      context.chrctr = startline;
XX--- 1377,1384 ----
XX      register long line2 = startline;
XX      register long line3 = startline;
XX      register int lncount;
XX!     int saveln, rv;
XX!     char *s;
XX  
XX      context.line = saveln = Currline;
XX      context.chrctr = startline;
XX***************
XX*** 1402,1418 ****
XX  	}
XX  	else {
XX  	    pr ("\nPattern not found\n");
XX! 	    end_it ();
XX  	}
XX  	error ("Pattern not found");
XX      }
XX  }
XX  
XX  /*VARARGS2*/
XX! execute (filename, cmd, va_alist)
XX  char *filename;
XX  char *cmd;
XX! va_dcl
XX  {
XX  	int id;
XX  	int n;
XX--- 1435,1454 ----
XX  	}
XX  	else {
XX  	    pr ("\nPattern not found\n");
XX! 	    end_it (0);
XX  	}
XX  	error ("Pattern not found");
XX      }
XX  }
XX  
XX  /*VARARGS2*/
XX! #if __STDC__
XX! void execute (char *filename, char *cmd, ...)
XX! #else
XX! void execute (filename, cmd)
XX  char *filename;
XX  char *cmd;
XX! #endif
XX  {
XX  	int id;
XX  	int n;
XX***************
XX*** 1427,1434 ****
XX  		close(0);
XX  		open("/dev/tty", O_RDONLY);
XX  	    }
XX! 	    va_start(argp);
XX! 	    execv (cmd, argp);
XX  	    write (2, "exec failed\n", 12);
XX  	    exit (1);
XX  	    va_end(argp);	/* balance {}'s for some UNIX's */
XX--- 1463,1470 ----
XX  		close(0);
XX  		open("/dev/tty", O_RDONLY);
XX  	    }
XX! 	    va_start(argp, cmd);
XX! 	    execv (cmd, (char **)argp);
XX  	    write (2, "exec failed\n", 12);
XX  	    exit (1);
XX  	    va_end(argp);	/* balance {}'s for some UNIX's */
XX***************
XX*** 1457,1463 ****
XX  ** Skip n lines in the file f
XX  */
XX  
XX! skiplns (n, f)
XX  register int n;
XX  register FILE *f;
XX  {
XX--- 1493,1499 ----
XX  ** Skip n lines in the file f
XX  */
XX  
XX! void skiplns (n, f)
XX  register int n;
XX  register FILE *f;
XX  {
XX***************
XX*** 1477,1483 ****
XX  ** negative.
XX  */
XX  
XX! skipf (nskip)
XX  register int nskip;
XX  {
XX      if (nskip == 0) return;
XX--- 1513,1519 ----
XX  ** negative.
XX  */
XX  
XX! void skipf (nskip)
XX  register int nskip;
XX  {
XX      if (nskip == 0) return;
XX***************
XX*** 1516,1535 ****
XX  
XX  /*----------------------------- Terminal I/O -------------------------------*/
XX  
XX! initterm ()
XX  {
XX      char	buf[TBUFSIZ];
XX      static char	clearbuf[TBUFSIZ];
XX      char	*clearptr, *padstr;
XX!     int		ldisc;
XX      int		lmode;
XX      char	*term;
XX-     int		tgrp;
XX  #ifdef TIOCGWINSZ
XX      struct winsize win;
XX  #endif
XX  
XX  retry:
XX      if (!(no_tty = gtty(fileno(stdout), &otty))) {
XX  #ifdef TIOCLGET
XX  	if (ioctl(fileno(stdout), TIOCLGET, &lmode) < 0) {
XX--- 1552,1574 ----
XX  
XX  /*----------------------------- Terminal I/O -------------------------------*/
XX  
XX! void initterm ()
XX  {
XX      char	buf[TBUFSIZ];
XX      static char	clearbuf[TBUFSIZ];
XX      char	*clearptr, *padstr;
XX! #ifdef TIOCLGET
XX      int		lmode;
XX+ #endif
XX      char	*term;
XX  #ifdef TIOCGWINSZ
XX      struct winsize win;
XX  #endif
XX+ #ifdef TIOCGPGRP
XX+     int		tgrp;
XX  
XX  retry:
XX+ #endif
XX      if (!(no_tty = gtty(fileno(stdout), &otty))) {
XX  #ifdef TIOCLGET
XX  	if (ioctl(fileno(stdout), TIOCLGET, &lmode) < 0) {
XX***************
XX*** 1559,1565 ****
XX  	}
XX  	else {
XX  #ifdef TIOCGWINSZ
XX! 	    if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
XX  		Lpp = tgetnum("li");
XX  		Mcol = tgetnum("co");
XX  	    } else {
XX--- 1598,1604 ----
XX  	}
XX  	else {
XX  #ifdef TIOCGWINSZ
XX! 	    if (ioctl(fileno(stdout), TIOCGWINSZ, (struct sgttyb *)&win) < 0) {
XX  		Lpp = tgetnum("li");
XX  		Mcol = tgetnum("co");
XX  	    } else {
XX***************
XX*** 1581,1587 ****
XX  	    if (Mcol <= 0)
XX  		Mcol = 80;
XX  
XX! 	    if (tailequ (fnames[0], "page") || !hard && tgetflag("ns"))
XX  		noscroll++;
XX  	    Wrap = tgetflag("am");
XX  	    bad_so = tgetflag ("xs");
XX--- 1620,1626 ----
XX  	    if (Mcol <= 0)
XX  		Mcol = 80;
XX  
XX! 	    if (tailequ (fnames[0], "page") || (!hard && tgetflag("ns")))
XX  		noscroll++;
XX  	    Wrap = tgetflag("am");
XX  	    bad_so = tgetflag ("xs");
XX***************
XX*** 1648,1662 ****
XX      }
XX  }
XX  
XX! readch ()
XX  {
XX  	char ch;
XX- 	extern int errno;
XX  
XX  	errno = 0;
XX  	if (read (2, &ch, 1) <= 0)
XX  		if (errno != EINTR)
XX! 			end_it();
XX  		else
XX  			ch = otty.sg_kill;
XX  	return (ch);
XX--- 1687,1700 ----
XX      }
XX  }
XX  
XX! int readch ()
XX  {
XX  	char ch;
XX  
XX  	errno = 0;
XX  	if (read (2, &ch, 1) <= 0)
XX  		if (errno != EINTR)
XX! 			end_it(0);
XX  		else
XX  			ch = otty.sg_kill;
XX  	return (ch);
XX***************
XX*** 1671,1677 ****
XX      else \
XX  	write (2, &BS, sizeof(BS));
XX  
XX! ttyin (buf, nmax, pchar)
XX  char buf[];
XX  register int nmax;
XX  char pchar;
XX--- 1709,1715 ----
XX      else \
XX  	write (2, &BS, sizeof(BS));
XX  
XX! void ttyin (buf, nmax, pchar)
XX  char buf[];
XX  register int nmax;
XX  char pchar;
XX***************
XX*** 1752,1758 ****
XX  	error ("Line too long");
XX  }
XX  
XX! expand (outbuf, inbuf)
XX  char *outbuf;
XX  char *inbuf;
XX  {
XX--- 1790,1796 ----
XX  	error ("Line too long");
XX  }
XX  
XX! int expand (outbuf, inbuf)
XX  char *outbuf;
XX  char *inbuf;
XX  {
XX***************
XX*** 1795,1801 ****
XX      return (changed);
XX  }
XX  
XX! show (ch)
XX  register char ch;
XX  {
XX      char cbuf;
XX--- 1833,1839 ----
XX      return (changed);
XX  }
XX  
XX! void show (ch)
XX  register char ch;
XX  {
XX      char cbuf;
XX***************
XX*** 1810,1816 ****
XX      promptlen++;
XX  }
XX  
XX! error (mess)
XX  char *mess;
XX  {
XX      if (clreol)
XX--- 1848,1854 ----
XX      promptlen++;
XX  }
XX  
XX! void error (mess)
XX  char *mess;
XX  {
XX      if (clreol)
XX***************
XX*** 1831,1844 ****
XX  }
XX  
XX  
XX! set_tty ()
XX  {
XX  	otty.sg_flags |= MBIT;
XX  	otty.sg_flags &= ~ECHO;
XX  	stty(fileno(stderr), &otty);
XX  }
XX  
XX! reset_tty ()
XX  {
XX      if (no_tty)
XX  	return;
XX--- 1869,1882 ----
XX  }
XX  
XX  
XX! void set_tty ()
XX  {
XX  	otty.sg_flags |= MBIT;
XX  	otty.sg_flags &= ~ECHO;
XX  	stty(fileno(stderr), &otty);
XX  }
XX  
XX! void reset_tty ()
XX  {
XX      if (no_tty)
XX  	return;
XX***************
XX*** 1852,1858 ****
XX      stty(fileno(stderr), &savetty);
XX  }
XX  
XX! rdline (f)
XX  register FILE *f;
XX  {
XX      register char c;
XX--- 1890,1896 ----
XX      stty(fileno(stderr), &savetty);
XX  }
XX  
XX! void rdline (f)
XX  register FILE *f;
XX  {
XX      register char c;
XX***************
XX*** 1911,1923 ****
XX  char *str;
XX  {
XX   if(str == NULL)
XX!     return((char *)NULL);
XX  
XX   if(re_exp != NULL)
XX      free(re_exp);
XX  
XX   if((re_exp = regcomp(str)) != NULL)
XX!     return((char *)NULL);
XX  
XX   return re_err != NULL ? re_err : "string didn't compile";
XX  }
XX--- 1949,1961 ----
XX  char *str;
XX  {
XX   if(str == NULL)
XX!     return(NULL);
XX  
XX   if(re_exp != NULL)
XX      free(re_exp);
XX  
XX   if((re_exp = regcomp(str)) != NULL)
XX!     return(NULL);
XX  
XX   return re_err != NULL ? re_err : "string didn't compile";
XX  }
X/
Xecho x - mount.c.d
Xsed '/^X/s///' > mount.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mount.c  crc=49309   1245	Sun Apr 25 21:35:09 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mount.c  crc=29519   2404	Wed Nov  4 04:19:15 1992
XX***************
XX*** 2,23 ****
XX  
XX  #include <errno.h>
XX  #include <sys/types.h>
XX! #include <fcntl.h>
XX  #include <unistd.h>
XX  
XX! #define BUFSIZE 1024
XX  
XX! extern int errno;
XX! char *mounttable = "/etc/mtab";
XX! char buffer[BUFSIZE];
XX! 
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int ro, fd;
XX  
XX!   if (argc == 1) list();
XX    if (argc < 3 || argc > 4) usage();
XX    if (argc == 4 && *argv[3] != '-' && *(argv[3] + 1) != 'r') usage();
XX    ro = (argc == 4 ? 1 : 0);
XX--- 2,27 ----
XX  
XX  #include <errno.h>
XX  #include <sys/types.h>
XX! #include <limits.h>
XX! #include <stdlib.h>
XX! #include <string.h>
XX  #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void list, (void));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int ro, n, v;
XX!   char *vs;
XX!   char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
XX  
XX!   if (argc == 1) list();	/* just list /etc/mtab */
XX    if (argc < 3 || argc > 4) usage();
XX    if (argc == 4 && *argv[3] != '-' && *(argv[3] + 1) != 'r') usage();
XX    ro = (argc == 4 ? 1 : 0);
XX***************
XX*** 26,66 ****
XX  		std_err("mount: ");
XX  		std_err(argv[1]);
XX  		std_err(" is not a valid file system.\n");
XX! 	} else {
XX! 		perror("mount");
XX  	}
XX  	exit(1);
XX    }
XX    std_err(argv[1]);
XX    std_err(" mounted\n");
XX!   if ((fd = open(mounttable, O_RDWR)) < 0) exit(1);
XX!   lseek(fd, 0L, SEEK_END);	/* seek to EOF */
XX!   write(fd, argv[1], strlen(argv[1]));
XX!   write(fd, " is mounted on ", 15);
XX!   write(fd, argv[2], strlen(argv[2]));
XX!   write(fd, "\n", 1);
XX!   exit(0);
XX  }
XX  
XX  
XX! list()
XX  {
XX!   int fd, n;
XX  
XX!   fd = open(mounttable, O_RDONLY);
XX!   if (fd < 0) {
XX! 	std_err("mount: cannot open ");
XX! 	std_err(mounttable);
XX! 	std_err("\n");
XX! 	exit(1);
XX    }
XX-   n = read(fd, buffer, BUFSIZE);
XX-   write(1, buffer, n);
XX    exit(0);
XX  }
XX  
XX  
XX! usage()
XX  {
XX    std_err("Usage: mount special name [-r]\n");
XX    exit(1);
XX--- 30,107 ----
XX  		std_err("mount: ");
XX  		std_err(argv[1]);
XX  		std_err(" is not a valid file system.\n");
XX! 		exit(1);
XX  	}
XX+ 	if (errno == ENFILE) {
XX+ 		std_err("mount: not enough internal table space available\n");
XX+ 		exit(1);
XX+ 	}
XX+ 	perror("mount");
XX  	exit(1);
XX    }
XX+ 
XX+   /* The mount has completed successfully. Tell the user. */
XX    std_err(argv[1]);
XX    std_err(" mounted\n");
XX! 
XX!   /* Update /etc/mtab. */
XX!   n = load_mtab("mount");
XX!   if (n < 0) exit(1);		/* something is wrong. */
XX! 
XX!   /* Loop on all the /etc/mtab entries, copying each one to the output buf. */
XX!   while (1) {
XX! 	n = get_mtab_entry(special, mounted_on, version, rw_flag);
XX! 	if (n < 0) break;
XX! 	n = put_mtab_entry(special, mounted_on, version, rw_flag);
XX! 	if (n < 0) {
XX! 		std_err("mount: /etc/mtab has grown too large\n");
XX! 		exit(1);
XX! 	}
XX!   }
XX!   v = fsversion(argv[1], "mount");
XX!   if (v == 1)
XX! 	vs = "1";
XX!   else if (v == 2)
XX! 	vs = "2";
XX!   else
XX! 	vs = "0";
XX!   n = put_mtab_entry(argv[1], argv[2], vs, (ro ? "ro" : "rw") );
XX!   if (n < 0) {
XX! 	std_err("mount: /etc/mtab has grown too large\n");
XX! 	exit(1);
XX!   }
XX! 
XX!   n = rewrite_mtab("mount");
XX!   return(0);
XX  }
XX  
XX  
XX! void list()
XX  {
XX!   int n;
XX!   char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
XX  
XX!   /* Read and print /etc/mtab. */
XX!   n = load_mtab("mount");
XX!   if (n < 0) exit(1);
XX! 
XX!   while (1) {
XX! 	n = get_mtab_entry(special, mounted_on, version, rw_flag);
XX! 	if  (n < 0) break;
XX! 	write(1, special, strlen(special));
XX! 	if (strcmp(mounted_on, "/") == 0) {
XX! 		write(1, " is root device\n", 16);
XX! 	} else {
XX! 		write(1, " is mounted on ", 15);
XX! 		write(1, mounted_on, strlen(mounted_on));
XX! 		write(1, "\n", 1);
XX! 	}
XX    }
XX    exit(0);
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    std_err("Usage: mount special name [-r]\n");
XX    exit(1);
X/
Xecho x - mref.c.d
Xsed '/^X/s///' > mref.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mref.c  crc=43034  25486	Sun Apr 25 21:35:10 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mref.c  crc=01756  27149	Wed Nov  4 04:19:16 1992
XX***************
XX*** 47,52 ****
XX--- 47,56 ----
XX  #include <sys/types.h>
XX  #include <ctype.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <sys/wait.h>
XX  #include <stdio.h>
XX  
XX  #define LINE_SIZE     512
XX***************
XX*** 82,87 ****
XX--- 86,92 ----
XX  int phys_page = PHYS_PAGE;	/* total page size: top hdr+text+bottom hdr */
XX  int cur_line;			/* current line number */
XX  int cur_page = 1;		/* current page number */
XX+ int nsymbols;			/* number of symbols in symbol table */
XX  int ntokens;			/* number of tokens in the token[] array */
XX  int suppressing;		/* don't print numbers between procedures */
XX  int hunting;			/* set when hunting for end of declaration */
XX***************
XX*** 157,163 ****
XX  FILE *tmp;			/* for collecting cross references */
XX  FILE *sortf;			/* for sorting cross refernces */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 162,199 ----
XX  FILE *tmp;			/* for collecting cross references */
XX  FILE *sortf;			/* for sorting cross refernces */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int eat_flag, (char *argv [], int i));
XX! _PROTOTYPE(void make_files, (void));
XX! _PROTOTYPE(void process, (char *file));
XX! _PROTOTYPE(void list, (char *file));
XX! _PROTOTYPE(void get_sym, (void));
XX! _PROTOTYPE(void fill_page, (void));
XX! _PROTOTYPE(void eject, (void));
XX! _PROTOTYPE(void new_page, (char *file));
XX! _PROTOTYPE(void squash, (void));
XX! _PROTOTYPE(void strip, (char *string, char *s, int n));
XX! _PROTOTYPE(char *backup, (char *q));
XX! _PROTOTYPE(void enter_sym, (char *p, int value, int type));
XX! _PROTOTYPE(int find_slot, (char *p));
XX! _PROTOTYPE(int lookup, (char *p));
XX! _PROTOTYPE(unsigned int hash, (char *p));
XX! _PROTOTYPE(void print_sym, (void));
XX! _PROTOTYPE(int compact, (void));
XX! _PROTOTYPE(void swap, (struct symtab *ap, struct symtab *bp));
XX! _PROTOTYPE(void sort, (int n));
XX! _PROTOTYPE(void gen_xref, (char *file));
XX! _PROTOTYPE(char *skip_comment, (char *p));
XX! _PROTOTYPE(void collect_xref, (void));
XX! _PROTOTYPE(int new_name, (char *cur, int used, char *pname, int values []));
XX! _PROTOTYPE(void sort_xref, (void));
XX! _PROTOTYPE(void output_macros, (FILE *f, char *text []));
XX! _PROTOTYPE(void sym_macros, (void));
XX! _PROTOTYPE(void xref_macros, (void));
XX! _PROTOTYPE(void panic, (char *s));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 199,205 ****
XX    /* Print the symbol table. */
XX    if (definitions) print_sym();
XX  
XX!   exit(0);
XX  }
XX  
XX  
XX--- 235,241 ----
XX    /* Print the symbol table. */
XX    if (definitions) print_sym();
XX  
XX!   return(0);
XX  }
XX  
XX  
XX***************
XX*** 240,246 ****
XX  }
XX  
XX  
XX! make_files()
XX  {
XX  /* Create output files. */
XX  
XX--- 276,282 ----
XX  }
XX  
XX  
XX! void make_files()
XX  {
XX  /* Create output files. */
XX  
XX***************
XX*** 282,288 ****
XX  	}
XX  	close(fd);
XX  	tmp = fopen(TMP_FILE, "w");
XX! 	if (xr == NULL) {
XX  		fprintf(stderr,
XX  		       "%s: cannot open %s for output\n", prog_name, TMP_FILE);
XX  		exit(2);
XX--- 318,324 ----
XX  	}
XX  	close(fd);
XX  	tmp = fopen(TMP_FILE, "w");
XX! 	if (tmp == NULL) {
XX  		fprintf(stderr,
XX  		       "%s: cannot open %s for output\n", prog_name, TMP_FILE);
XX  		exit(2);
XX***************
XX*** 291,302 ****
XX  }
XX  
XX  
XX! process(file)
XX  char *file;
XX  {
XX  /* Process one file. */
XX  
XX-   int k;
XX    FILE *f;
XX  
XX    if ((f = fopen(file, "r")) == NULL) {
XX--- 327,337 ----
XX  }
XX  
XX  
XX! void process(file)
XX  char *file;
XX  {
XX  /* Process one file. */
XX  
XX    FILE *f;
XX  
XX    if ((f = fopen(file, "r")) == NULL) {
XX***************
XX*** 322,328 ****
XX  }
XX  
XX  
XX! list(file)
XX  char *file;
XX  {
XX  /* We are printing a listing. */
XX--- 357,363 ----
XX  }
XX  
XX  
XX! void list(file)
XX  char *file;
XX  {
XX  /* We are printing a listing. */
XX***************
XX*** 341,347 ****
XX  }
XX  
XX  
XX! get_sym()
XX  {
XX  /* Look for lines starting with PRIVATE, PUBLIC, EXTERN, SYMBOL or #define and
XX   * make a symbol table entry for them.  Life is slightly complicated by
XX--- 376,382 ----
XX  }
XX  
XX  
XX! void get_sym()
XX  {
XX  /* Look for lines starting with PRIVATE, PUBLIC, EXTERN, SYMBOL or #define and
XX   * make a symbol table entry for them.  Life is slightly complicated by
XX***************
XX*** 355,363 ****
XX   * in which the symbol 'name' is triggered on line 1000, but its value is 1003.
XX   */
XX  
XX!   int n, type;
XX    register char c;
XX!   char *p, *q, *backup();
XX  
XX    /* If we are hunting for the end of a declaration, the rules are
XX     * different. */
XX--- 390,398 ----
XX   * in which the symbol 'name' is triggered on line 1000, but its value is 1003.
XX   */
XX  
XX!   int type;
XX    register char c;
XX!   char *p, *q;
XX  
XX    /* If we are hunting for the end of a declaration, the rules are
XX     * different. */
XX***************
XX*** 383,393 ****
XX  
XX    /* Real check to see if this line is interesting. */
XX    type = 0;
XX!   if (strncmp(b, "#define", 7) == 0) type = DEF;
XX!   if (strncmp(b, "PRIVATE", 7) == 0) type = PRIV;
XX!   if (strncmp(b, "PUBLIC", 6) == 0) type = PUB;
XX!   if (strncmp(b, "EXTERN", 6) == 0) type = EXT;
XX!   if (strncmp(b, "SYMBOL", 6) == 0) type = SYM;
XX    if (type == 0) return;
XX  
XX    /* Process #define */
XX--- 418,428 ----
XX  
XX    /* Real check to see if this line is interesting. */
XX    type = 0;
XX!   if (strncmp(b, "#define", (size_t)7) == 0) type = DEF;
XX!   if (strncmp(b, "PRIVATE", (size_t)7) == 0) type = PRIV;
XX!   if (strncmp(b, "PUBLIC", (size_t)6) == 0) type = PUB;
XX!   if (strncmp(b, "EXTERN", (size_t)6) == 0) type = EXT;
XX!   if (strncmp(b, "SYMBOL", (size_t)6) == 0) type = SYM;
XX    if (type == 0) return;
XX  
XX    /* Process #define */
XX***************
XX*** 442,448 ****
XX  
XX  
XX  
XX! fill_page()
XX  {
XX  /* Fill out current page with line feeds. This routine is only called when
XX   * an end of file is encountered.  It fills out the current page to 50
XX--- 477,483 ----
XX  
XX  
XX  
XX! void fill_page()
XX  {
XX  /* Fill out current page with line feeds. This routine is only called when
XX   * an end of file is encountered.  It fills out the current page to 50
XX***************
XX*** 458,464 ****
XX  }
XX  
XX  
XX! eject()
XX  {
XX  /* Finish off the last 11 or so blank lines on a page (not for -t. */
XX  
XX--- 493,499 ----
XX  }
XX  
XX  
XX! void eject()
XX  {
XX  /* Finish off the last 11 or so blank lines on a page (not for -t. */
XX  
XX***************
XX*** 471,483 ****
XX  }
XX  
XX  
XX! new_page(file)
XX  char *file;
XX  {
XX  /* Top of page processing. */
XX  
XX-   int i;
XX- 
XX    if (tflag) {
XX  	/* Generate a troff macro that does the heading (odd/even). */
XX  	if (cur_page & 1)
XX--- 506,516 ----
XX  }
XX  
XX  
XX! void new_page(file)
XX  char *file;
XX  {
XX  /* Top of page processing. */
XX  
XX    if (tflag) {
XX  	/* Generate a troff macro that does the heading (odd/even). */
XX  	if (cur_page & 1)
XX***************
XX*** 493,499 ****
XX  }
XX  
XX  
XX! squash()
XX  {
XX  /* Copy line_buf to b, squeezing out white space, comments, and initializers. */
XX  
XX--- 526,532 ----
XX  }
XX  
XX  
XX! void squash()
XX  {
XX  /* Copy line_buf to b, squeezing out white space, comments, and initializers. */
XX  
XX***************
XX*** 523,529 ****
XX  
XX  
XX  
XX! strip(string, s, n)
XX  char *string;
XX  char *s;
XX  int n;
XX--- 556,562 ----
XX  
XX  
XX  
XX! void strip(string, s, n)
XX  char *string;
XX  char *s;
XX  int n;
XX***************
XX*** 556,562 ****
XX    return(q + 1);
XX  }
XX  
XX! enter_sym(p, value, type)
XX  char *p;			/* pointer to name of symbol */
XX  int value;			/* line number on which symbol occurs */
XX  int type;			/* PUB, PRIV, EXT, DEF, SYM */
XX--- 589,595 ----
XX    return(q + 1);
XX  }
XX  
XX! void enter_sym(p, value, type)
XX  char *p;			/* pointer to name of symbol */
XX  int value;			/* line number on which symbol occurs */
XX  int type;			/* PUB, PRIV, EXT, DEF, SYM */
XX***************
XX*** 568,573 ****
XX--- 601,608 ----
XX    int h, len;
XX    struct symtab *hp;
XX  
XX+   if (nsymbols >= NSYMS) panic("symbol table overflow");
XX+ 
XX    /* Watch out for the #define PUBLIC line, etc. */
XX    if (strlen(p) == 0) return;
XX    if (strcmp(p, "PUBLIC") == 0) return;
XX***************
XX*** 584,592 ****
XX    if (len > SYM_SIZE) len = SYM_SIZE;
XX  
XX    /* Enter the symbol.  Multiple definitions are allowed. */
XX!   strncpy(hp->sym_name, p, len);/* entry is SYM_SIZE+1 for \'0' */
XX    hp->sym_type = type;
XX    hp->sym_val = value;
XX  }
XX  
XX  
XX--- 619,628 ----
XX    if (len > SYM_SIZE) len = SYM_SIZE;
XX  
XX    /* Enter the symbol.  Multiple definitions are allowed. */
XX!   strncpy(hp->sym_name, p, (size_t)len);/* entry is SYM_SIZE+1 for \'0' */
XX    hp->sym_type = type;
XX    hp->sym_val = value;
XX+   nsymbols++;
XX  }
XX  
XX  
XX***************
XX*** 597,603 ****
XX   * occurs, the first consecutive free slot is used.
XX   */
XX  
XX!   unsigned int h, hash();
XX  
XX    /* Search all entries starting at h for a free slot. */
XX    h = hash(p);
XX--- 633,639 ----
XX   * occurs, the first consecutive free slot is used.
XX   */
XX  
XX!   unsigned int h;
XX  
XX    /* Search all entries starting at h for a free slot. */
XX    h = hash(p);
XX***************
XX*** 612,626 ****
XX  {
XX  /* Is p is in the symbol table?  Return slot if it is present, -1 if absent. */
XX  
XX!   unsigned int h, hash();
XX!   int n;
XX  
XX-   n = strlen(p);
XX-   if (n > SYM_SIZE) n = SYM_SIZE;
XX    h = hash(p);
XX    while (1) {
XX  	if (symtab[h].sym_type == 0) return(-1);	/* not present */
XX! 	if (strncmp(p, symtab[h].sym_name, n) == 0) return ((int) h);
XX  	h = (h + 1) % NSYMS;
XX    }
XX  }
XX--- 648,659 ----
XX  {
XX  /* Is p is in the symbol table?  Return slot if it is present, -1 if absent. */
XX  
XX!   unsigned int h;
XX  
XX    h = hash(p);
XX    while (1) {
XX  	if (symtab[h].sym_type == 0) return(-1);	/* not present */
XX! 	if (strcmp(p, symtab[h].sym_name) == 0) return ((int) h);
XX  	h = (h + 1) % NSYMS;
XX    }
XX  }
XX***************
XX*** 646,656 ****
XX  }
XX  
XX  
XX! print_sym()
XX  {
XX  /* Print all the definitions. */
XX  
XX!   int n, k, count, s, i, limit;
XX    struct symtab *ap, *bp, *cp;
XX  
XX    n = compact();		/* compact the symbol table */
XX--- 679,689 ----
XX  }
XX  
XX  
XX! void print_sym()
XX  {
XX  /* Print all the definitions. */
XX  
XX!   int n, k, i, limit;
XX    struct symtab *ap, *bp, *cp;
XX  
XX    n = compact();		/* compact the symbol table */
XX***************
XX*** 693,699 ****
XX  }
XX  
XX  
XX! compact()
XX  {
XX  /* Compact the symbol table to make sorting more efficient. */
XX  
XX--- 726,732 ----
XX  }
XX  
XX  
XX! int compact()
XX  {
XX  /* Compact the symbol table to make sorting more efficient. */
XX  
XX***************
XX*** 718,724 ****
XX  }
XX  
XX  
XX! swap(ap, bp)
XX  struct symtab *ap, *bp;
XX  {
XX  /* Swap two symbol table entries. */
XX--- 751,757 ----
XX  }
XX  
XX  
XX! void swap(ap, bp)
XX  struct symtab *ap, *bp;
XX  {
XX  /* Swap two symbol table entries. */
XX***************
XX*** 730,736 ****
XX    *bp = xp;
XX  }
XX  
XX! sort(n)
XX  int n;				/* number of nonnull entries in symtab */
XX  {
XX  /* Sort the symbol table.  Use bubble sort. */
XX--- 763,769 ----
XX    *bp = xp;
XX  }
XX  
XX! void sort(n)
XX  int n;				/* number of nonnull entries in symtab */
XX  {
XX  /* Sort the symbol table.  Use bubble sort. */
XX***************
XX*** 750,756 ****
XX  
XX  
XX  
XX! gen_xref(file)
XX  char *file;
XX  {
XX  /* Build the cross reference listing.  Reread file, looking up all
XX--- 783,789 ----
XX  
XX  
XX  
XX! void gen_xref(file)
XX  char *file;
XX  {
XX  /* Build the cross reference listing.  Reread file, looking up all
XX***************
XX*** 760,766 ****
XX  
XX    int i, k;
XX    register char *p;
XX!   char c, *skip_comment();
XX    FILE *f;
XX  
XX    if ((f = fopen(file, "r")) == NULL) {
XX--- 793,799 ----
XX  
XX    int i, k;
XX    register char *p;
XX!   char c;
XX    FILE *f;
XX  
XX    if ((f = fopen(file, "r")) == NULL) {
XX***************
XX*** 818,823 ****
XX--- 851,868 ----
XX  			continue;
XX  		}
XX  
XX+ 		/* Check to see if it is a character constant. */
XX+ 		if (c == '\'') {
XX+ 			p++;
XX+ 			while (*p != '\'') {
XX+ 				if (*p == '\\') p++;
XX+ 				p++;
XX+ 			}
XX+ 			p++;
XX+ 			c = *p;
XX+ 			continue;
XX+ 		}
XX+ 
XX  		/* It is not a token or a comment, just ignore it. */
XX  		p++;
XX  		c = *p;
XX***************
XX*** 830,836 ****
XX  		p = token[i];
XX  		if (strlen(p) > SYM_SIZE) *(p + SYM_SIZE) = 0;
XX  		k = lookup(p);
XX! 		if (k > 0) {
XX  			fprintf(tmp, "%s ", p);
XX  			if (cur_line < 10)
XX  				fprintf(tmp, "0000%d\n", cur_line);
XX--- 875,881 ----
XX  		p = token[i];
XX  		if (strlen(p) > SYM_SIZE) *(p + SYM_SIZE) = 0;
XX  		k = lookup(p);
XX! 		if (k >= 0) {
XX  			fprintf(tmp, "%s ", p);
XX  			if (cur_line < 10)
XX  				fprintf(tmp, "0000%d\n", cur_line);
XX***************
XX*** 867,877 ****
XX    }
XX  }
XX  
XX! collect_xref()
XX  {
XX  /* Sort the cross references and format them. */
XX  
XX!   int i, n, values[MAX_VALUES], used, nval, s, flag;
XX    register char *p;
XX    char *pname, *pnum;
XX    char cur[SYM_SIZE + 1];	/* name currently being processed. */
XX--- 912,922 ----
XX    }
XX  }
XX  
XX! void collect_xref()
XX  {
XX  /* Sort the cross references and format them. */
XX  
XX!   int i, values[MAX_VALUES], used, nval, s, flag;
XX    register char *p;
XX    char *pname, *pnum;
XX    char cur[SYM_SIZE + 1];	/* name currently being processed. */
XX***************
XX*** 916,921 ****
XX--- 961,967 ----
XX  	if (used == 0 || strcmp(pname, cur) != 0) {
XX  		nval = new_name(cur, used, pname, values);
XX  		xcount = nval;	/* # refs on this line so far */
XX+ 		prev_ref = -1;
XX  	}
XX  	used = 1;
XX  
XX***************
XX*** 948,957 ****
XX  
XX  
XX  int new_name(cur, used, pname, values)
XX! char *cur[SYM_SIZE + 1];	/* storage for current name */
XX  int used;			/* 0 only on first call. */
XX  char *pname;			/* pointer to the new name */
XX! int values[MAX_VALUES];		/* all the definitions of the new name */
XX  {
XX  /* A new name has been read.  Finish off the old one and prepare new one. */
XX  
XX--- 994,1003 ----
XX  
XX  
XX  int new_name(cur, used, pname, values)
XX! char *cur;			/* storage for current name */
XX  int used;			/* 0 only on first call. */
XX  char *pname;			/* pointer to the new name */
XX! int values[];			/* all the definitions of the new name */
XX  {
XX  /* A new name has been read.  Finish off the old one and prepare new one. */
XX  
XX***************
XX*** 1008,1014 ****
XX  
XX  
XX  
XX! sort_xref()
XX  {
XX  /* Sort the cross reference file by forking off a copy of 'sort'. */
XX  
XX--- 1054,1060 ----
XX  
XX  
XX  
XX! void sort_xref()
XX  {
XX  /* Sort the cross reference file by forking off a copy of 'sort'. */
XX  
XX***************
XX*** 1032,1038 ****
XX  }
XX  
XX  
XX! output_macros(f, text)
XX  FILE *f;
XX  char *text[];
XX  {
XX--- 1078,1084 ----
XX  }
XX  
XX  
XX! void output_macros(f, text)
XX  FILE *f;
XX  char *text[];
XX  {
XX***************
XX*** 1048,1066 ****
XX  }
XX  
XX  
XX! sym_macros()
XX  {
XX  }
XX  
XX  
XX! xref_macros()
XX  {
XX  }
XX  
XX  
XX  
XX  
XX! panic(s)
XX  char *s;
XX  {
XX    fprintf(stderr, "%s: %s\n", prog_name, s);
XX--- 1094,1112 ----
XX  }
XX  
XX  
XX! void sym_macros()
XX  {
XX  }
XX  
XX  
XX! void xref_macros()
XX  {
XX  }
XX  
XX  
XX  
XX  
XX! void panic(s)
XX  char *s;
XX  {
XX    fprintf(stderr, "%s: %s\n", prog_name, s);
XX***************
XX*** 1068,1074 ****
XX  }
XX  
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: %s [-<n>] [-dlmtsx] [-p pagenr] file ... \n",
XX  	prog_name);
XX--- 1114,1120 ----
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: %s [-<n>] [-dlmtsx] [-p pagenr] file ... \n",
XX  	prog_name);
X/
Xecho x - mv.c.d
Xsed '/^X/s///' > mv.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/mv.c  crc=36757   4932	Sun Apr 25 21:35:10 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/mv.c  crc=49785   4897	Mon Jan 18 18:56:09 1993
XX***************
XX*** 1,203 ****
XX! /* mv - move files		Author: Adri Koppes */
XX  
XX! /* 4/25/87 - J. Paradis		Bug fixes for directory handling
XX!  * 3/15/88 - P. Housel		More directory bug fixes
XX!  * 1/21/89 - B. Evans		Allow owner to move non-writable file.
XX!  *				Don't allow move to non-writable file.
XX!  *				Delete target file in case of moving to dir.
XX!  *				Requires making file readable before copy.
XX!  *				Fix up mode after copy (cp uses the target
XX!  *				mode, if any, and strips high bits).
XX!  *				Use adequate size for dotdot buffer.
XX!  * Jan  90 - B. Evans		The directory above /foo was calculated as
XX!  *				"" instead of "/", so "mv /bin /bin0" left
XX!  *				the old bin/. and bin/.. links in the
XX!  *				current directory or nowhere.
XX!  *
XX!  *				BUGS.
XX!  *				There are race conditions all over.
XX!  *				Error messages are not specific.
XX!  *				There are magic sizes 64 and 128 instead of
XX!  *				sizes related to PATH_MAX.
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX! #include <signal.h>
XX  #include <string.h>
XX  
XX! struct stat st, st1;
XX  
XX! main(argc, argv)
XX  int argc;
XX! char **argv;
XX  {
XX!   char *destdir;
XX  
XX!   if (argc < 3) {
XX! 	std_err("Usage: mv file1 file2 or mv dir1 dir2 or mv file1 file2 ... dir\n");
XX! 	exit(1);
XX!   }
XX!   if (argc == 3) {
XX! 	if (stat(argv[1], &st)) {
XX! 		std_err("mv: ");
XX! 		std_err(argv[1]);
XX! 		std_err(" doesn't exist\n");
XX! 		exit(1);
XX  	}
XX! 	move(argv[1], argv[2]);
XX!   } else {
XX! 	destdir = argv[--argc];
XX! 	if (stat(destdir, &st)) {
XX! 		std_err("mv: target directory ");
XX! 		std_err(destdir);
XX! 		std_err(" doesn't exist\n");
XX! 		exit(1);
XX  	}
XX! 	if ((st.st_mode & S_IFMT) != S_IFDIR) {
XX! 		std_err("mv: target ");
XX! 		std_err(destdir);
XX! 		std_err(" not a directory\n");
XX! 		exit(1);
XX  	}
XX! 	while (--argc) move(*++argv, destdir);
XX!   }
XX!   exit(0);
XX  }
XX  
XX! move(old, new)
XX! char *old, *new;
XX  {
XX!   int retval;
XX!   char name[64];
XX!   char parent[64];
XX!   char *oldbase;
XX!   int i;
XX  
XX!   if ((oldbase = strrchr(old, '/')) == 0)
XX! 	oldbase = old;
XX!   else
XX! 	++oldbase;
XX! 
XX!   /* It's too dangerous to fool with "." or ".." ! */
XX!   if ((strcmp(oldbase, ".") == 0) || (strcmp(oldbase, "..") == 0)) {
XX! 	cant(old);
XX    }
XX  
XX!   /* Don't move a non-existent file. */
XX!   if (stat(old, &st) != 0) cant(old);
XX  
XX-   /* If source is not writable, don't move it unless user owns it. */
XX-   if (access(old, 2) != 0 && st.st_uid != getuid()) cant(old);
XX  
XX!   /* If target is a directory, form its full name. The error of moving
XX!    * a directory to itself is caught later. */
XX!   if (stat(new, &st1) == 0 && (st1.st_mode & S_IFMT) == S_IFDIR) {
XX! 	if ((strlen(oldbase) + strlen(new) + 2) > 64) cant(old);
XX! 	strcpy(name, new);
XX! 	strcat(name, "/");
XX! 	strcat(name, oldbase);
XX! 	new = name;
XX!   }
XX  
XX!   /* If target exists, do various overwriting checks. */
XX!   if (stat(new, &st1) == 0) {
XX  
XX- 	/* Don't move a file to itself. */
XX- 	if (st.st_dev == st1.st_dev && st.st_ino == st1.st_ino) cant(old);
XX  
XX! 	/* Don't move on top of a directory. */
XX! 	if ((st1.st_mode & S_IFMT) == S_IFDIR) cant(old);
XX  
XX! 	/* Don't move on top of a non-writable file. */
XX! 	if (access(new, 2) != 0) cant(old);
XX!   }
XX!   strcpy(parent, new);
XX  
XX-   for (i = (strlen(parent) - 1); i > 0; i--) {
XX- 	if (parent[i] == '/') break;
XX-   }
XX  
XX!   if (i == 0) {
XX! 	if (parent[0] == '/')
XX! 		parent[1] = '\0';	/* parent of "/bin" is "/", not "." */
XX! 	else
XX! 		strcpy(parent, ".");
XX!   } else {
XX! 	/* Null-terminate name at last slash */
XX! 	parent[i] = '\0';
XX!   }
XX  
XX!   /* Prevent moving a directory into its own subdirectory */
XX!   if ((st.st_mode & S_IFMT) == S_IFDIR) {
XX! 	char lower[128];
XX! 	short int prevdev = -1;
XX! 	unsigned short previno;
XX! 
XX! 	strcpy(lower, parent);
XX! 	while (1) {
XX! 		if (stat(lower, &st1) || (st1.st_dev == st.st_dev
XX! 					&& st1.st_ino == st.st_ino))
XX! 			cant(old);
XX! 
XX! 		/* Stop at root */
XX! 		if (st1.st_dev == prevdev && st1.st_ino == previno) break;
XX! 		prevdev = st1.st_dev;
XX! 		previno = st1.st_ino;
XX! 		strcat(lower, "/..");
XX  	}
XX    }
XX! 
XX!   /* If target exists, it is a file. Delete it so that following link()
XX!    * works except across file systems, to avoid copying. */
XX!   if (stat(new, &st1) == 0) unlink(new);
XX! 
XX!   if (link(old, new))
XX! 	if ((st.st_mode & S_IFMT) != S_IFDIR) {
XX! 		switch (fork()) {
XX! 		    case 0:
XX! 			if (!(st.st_mode & S_IRUSR))
XX! 				chmod(old, st.st_mode | S_IRUSR);
XX! 			setgid(getgid());
XX! 			setuid(getuid());
XX! 			execl("/bin/cp", "cp", old, new, (char *) 0);
XX! 			execl("/usr/bin/cp", "cp", old, new, (char *) 0);
XX! 			cant(old);
XX! 		    case -1:
XX! 			std_err("mv: can't fork\n");
XX! 			exit(1);
XX! 		    default:
XX! 			wait(&retval);
XX! 			if (!(st.st_mode & S_IRUSR)) chmod(old, st.st_mode);
XX! 			if (retval) cant(old);
XX! 			chmod(new, st.st_mode);
XX  		}
XX! 	} else
XX! 		cant(old);
XX  
XX!   /* If this was a directory that we moved, then we have * to update
XX!    * its ".." entry (in case it was moved some- * where else in the
XX!    * tree...) */
XX!   if ((st.st_mode & S_IFMT) == S_IFDIR) {
XX! 	char dotdot[64 + 3];
XX! 
XX! 	/* Unlink the ".." entry */
XX! 	strcpy(dotdot, new);
XX! 	strcat(dotdot, "/..");
XX! 	unlink(dotdot);
XX! 
XX! 	/* Now link it to its parent */
XX! 	link(parent, dotdot);
XX    }
XX!   utime(new, &st.st_atime);
XX!   unlink(old);
XX  }
XX  
XX! cant(name)
XX! char *name;
XX  {
XX!   std_err("mv: can't move ");
XX!   std_err(name);
XX!   std_err("\n");
XX    exit(1);
XX  }
XX--- 1,238 ----
XX! /* mv - move files			Author: V. Archer */
XX  
XX! /* Copyright 1991 by Vincent Archer
XX!  *	You may freely redistribute this software, in source or binary
XX!  *	form, provided that you do not alter this copyright mention in any
XX!  *	way.
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX! #include <sys/wait.h>
XX! #include <minix/minlib.h>
XX! #include <errno.h>
XX! #include <limits.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! /* Global variables. */
XX! int dflag, fflag, iflag, tflag;
XX! struct stat st, st2;
XX  
XX! extern int optind, opterr;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int do_it, (char *cmd, char *options, char *file, char *target));
XX! _PROTOTYPE(int negative, (void));
XX! _PROTOTYPE(char *octal, (Mode_t num));
XX! _PROTOTYPE(int do_mv, (char *source, char *dest));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! /* Main module. The internal '-t' flag is set if the file descriptor 0
XX!  * refers to a tty device. It is not used if '-i' is set.
XX!  */
XX! int main(argc, argv)
XX  int argc;
XX! char *argv[];
XX  {
XX!   char *dest;
XX!   int c;
XX  
XX!   opterr = 0;
XX!   while ((c = getopt(argc, argv, "fi")) != EOF) switch (c) {
XX! 	    case 'f':
XX! 		fflag = 1;
XX! 		iflag = 0;
XX! 		break;
XX! 	    case 'i':
XX! 		iflag = 1;
XX! 		fflag = 0;
XX! 		break;
XX! 	    default:	usage();	break;
XX  	}
XX!   argc -= optind;
XX!   argv += optind;
XX!   if (argc < 2) usage();
XX! 
XX!   dest = argv[--argc];
XX!   if (stat(dest, &st)) {
XX! 	if (argc > 1) {
XX! 		perror(dest);
XX! 		return(1);
XX  	}
XX!   } else if (!S_ISDIR(st.st_mode)) {
XX! 	if (argc > 1) {
XX! 		errno = ENOTDIR;
XX! 		perror(dest);
XX! 		return(1);
XX  	}
XX!   } else
XX! 	dflag = 1;
XX!   if (!fflag) tflag = isatty(0);
XX! 
XX!   c = 0;
XX!   while (argc--) c |= do_mv(*argv++, dest);
XX!   return(c);
XX  }
XX  
XX! 
XX! /* This replaces a bulky, slow, and unnecessary system() call in the
XX!  * specific cases needed by a mv across file systems (rm/cpdir calls).
XX!  */
XX! int do_it(cmd, options, file, target)
XX! char *cmd, *options, *file, *target;
XX  {
XX!   pid_t pid, pid2;
XX!   int status;
XX  
XX!   if ((pid = fork()) != 0) {
XX! 	if (pid < 0) {
XX! 		std_err(file);
XX! 		perror(":fork()");
XX! 		return(1);
XX! 	}
XX! 	while ((pid2 = wait(&status)) != pid)
XX! 		if (pid2 <= 0 && errno != EAGAIN) {
XX! 			std_err(file);
XX! 			perror(":wait()");
XX! 			return(1);
XX! 		}
XX! 	if (WIFEXITED(status) && !WEXITSTATUS(status)) return(0);
XX! 	return(1);
XX    }
XX+   execlp(cmd, cmd, options, file, target, (char *) 0);
XX  
XX!   /* Control only passes here in the event execlp failed. */
XX!   std_err(file);
XX!   std_err(":execlp():");
XX!   perror(cmd);
XX!   exit(1);
XX!   return(0);
XX! }
XX  
XX  
XX! /* Wait for a user answer from the stdin stream (but do not use stdio which
XX!  * is bulky and unneeded in most tools). An error (or end of file) on file
XX!  * descriptor 0 is assumed to mean a NEGATIVE answer. LC_* locale could be
XX!  * handled here.
XX!  */
XX! int negative()
XX! {
XX!   char c, t;
XX  
XX!   if (read(0, &c, 1) != 1) return(1);
XX!   t = c;
XX!   while (t != '\n')
XX! 	if (read(0, &t, 1) != 1) break;
XX!   return(c != 'y' && c != 'Y');
XX! }
XX  
XX  
XX! /* Quick transformation of a mode_t in 3-digits octal form. */
XX! char *octal(num)
XX! mode_t num;
XX! {
XX!   static char a[4];
XX  
XX!   a[0] = (((num >> 6) & 7) + '0');
XX!   a[1] = (((num >> 3) & 7) + '0');
XX!   a[2] = ((num & 7) + '0');
XX!   a[3] = 0;
XX!   return(a);
XX! }
XX  
XX  
XX! /* Do the actual directory entry movement. This rely upon the rename()
XX!  * system call heavily.
XX!  */
XX! int do_mv(source, dest)
XX! char *source, *dest;
XX! {
XX!   int newfile;
XX!   char path[PATH_MAX + 1];
XX  
XX!   if (dflag) {
XX! 	strcpy(path, dest);
XX! 	if ((dest = strrchr(source, '/')) != NULL)
XX! 		strcat(path, dest);
XX! 	else {
XX! 		strcat(path, "/");
XX! 		strcat(path, source);
XX  	}
XX+ 	dest = path;
XX    }
XX!   if (access(source, 0) < 0) {
XX! 	perror(source);
XX! 	return(1);
XX!   }
XX!   if (
XX! #ifdef S_IFLNK
XX!       !(newfile = lstat(dest, &st))
XX! #else
XX!       !(newfile = stat(dest, &st))
XX! #endif
XX!      ) {
XX! 	if (S_ISDIR(st.st_mode)) {
XX! 		errno = EISDIR;
XX! 		perror(dest);
XX! 		return(1);
XX! 	}
XX! 	if (!fflag)
XX! 		if (
XX! #ifdef S_IFLNK
XX! 		    !S_ISLNK(st.st_mode) &&
XX! #endif
XX! 		    access(dest, 2) && tflag) {
XX! 			std_err(dest);
XX! 			std_err(": replace (mode = ");
XX! 			std_err(octal(st.st_mode));
XX! 			std_err(") ? ");
XX! 			if (negative()) return(0);
XX! 		} else if (iflag) {
XX! 			std_err(dest);
XX! 			std_err(": replace ? ");
XX! 			if (negative()) return(0);
XX  		}
XX!   }
XX!   if (rename(source, dest) == 0) return(0);
XX!   if (errno != EXDEV) {
XX! 	std_err(source);
XX! 	std_err(", ");
XX! 	perror(dest);
XX! 	return(1);
XX!   }
XX  
XX!   /* A copy is necessary. Make sure that the source and destination have
XX!    * the same "type" (i.e. they're both directories or non-directories).
XX!    */
XX!   if (stat(source, &st2)) {
XX! 	perror(source);
XX! 	return(1);
XX    }
XX!   if (!newfile) {
XX! 	if (S_ISDIR(st2.st_mode) && !S_ISDIR(st.st_mode)) {
XX! 		errno = ENOTDIR;
XX! 		perror(dest);
XX! 		return(1);
XX! 	} else if (!S_ISDIR(st2.st_mode) && S_ISDIR(st.st_mode)) {
XX! 		errno = EISDIR;
XX! 		perror(dest);
XX! 		return(1);
XX! 	}
XX!   }
XX!   if (!newfile && do_it("rm", "-Rf", dest, (char *) 0)) return(1);
XX!   if (do_it("cpdir", "-fp", source, dest) ||
XX!       do_it("rm", "-Rf", source, (char *) 0))
XX! 	return(1);
XX!   return(0);
XX  }
XX  
XX! 
XX! /* Posix command prototype. */
XX! void usage()
XX  {
XX!   std_err("Usage: mv [-fi] source_file... target\n");
XX    exit(1);
XX  }
X/
Xecho x - nm.c.d
Xsed '/^X/s///' > nm.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/nm.c  crc=51779   4419	Sun Apr 25 21:35:10 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/nm.c  crc=23842   5227	Wed Nov  4 04:19:16 1992
XX***************
XX*** 7,12 ****
XX--- 7,13 ----
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX  #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  /* Read the name list in memory, sort it, and print it.  */
XX***************
XX*** 43,49 ****
XX  struct exec header;		/* header of a.out file */
XX  int stbl_elems;			/* #elements in symbol table */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 44,56 ----
XX  struct exec header;		/* header of a.out file */
XX  int stbl_elems;			/* #elements in symbol table */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int nm_sort, (const void *tmp_stbl1, const void *tmp_stbl2));
XX! _PROTOTYPE(void nm, (char *file));
XX! _PROTOTYPE(int read_header, (int fd));
XX! _PROTOTYPE(void nm_print, (char *file, struct nlist *stbl));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 75,86 ****
XX  		nm(*argv);
XX  		argv++;
XX  	}
XX!   exit(0);
XX  }
XX  
XX! nm_sort(stbl1, stbl2)
XX! struct nlist *stbl1, *stbl2;
XX  {
XX    int cmp;
XX  
XX    if (n_flag) {			/* sort numerically */
XX--- 82,96 ----
XX  		nm(*argv);
XX  		argv++;
XX  	}
XX!   return(0);
XX  }
XX  
XX! int nm_sort(tmp_stbl1, tmp_stbl2)
XX! _CONST void *tmp_stbl1, *tmp_stbl2;
XX  {
XX+ 
XX+   struct nlist *stbl1 = (struct nlist *)tmp_stbl1;
XX+   struct nlist *stbl2 = (struct nlist *)tmp_stbl2;
XX    int cmp;
XX  
XX    if (n_flag) {			/* sort numerically */
XX***************
XX*** 95,103 ****
XX  	else if (stbl1->n_value > stbl2->n_value)
XX  		cmp = 1;
XX  	else
XX! 		cmp = strncmp(stbl1->n_name, stbl2->n_name, 8);
XX    } else {
XX! 	cmp = strncmp(stbl1->n_name, stbl2->n_name, 8);
XX  	if (cmp == 0) {
XX  		if (stbl1->n_value < stbl2->n_value)
XX  			cmp = -1;
XX--- 105,113 ----
XX  	else if (stbl1->n_value > stbl2->n_value)
XX  		cmp = 1;
XX  	else
XX! 		cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
XX    } else {
XX! 	cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
XX  	if (cmp == 0) {
XX  		if (stbl1->n_value < stbl2->n_value)
XX  			cmp = -1;
XX***************
XX*** 110,116 ****
XX    return(cmp);
XX  }
XX  
XX! nm(file)
XX  char *file;
XX  {
XX    struct nlist *stbl;
XX--- 120,126 ----
XX    return(cmp);
XX  }
XX  
XX! void nm(file)
XX  char *file;
XX  {
XX    struct nlist *stbl;
XX***************
XX*** 126,150 ****
XX  	close(fd);
XX  	return;
XX    }
XX!   if (header.a_syms != 0) {
XX!     stbl = (struct nlist *) malloc((int) (header.a_syms & 0xFFFF));
XX!     if (stbl == NULL) {
XX  	fprintf(stderr, "%s: can't allocate symbol table\n", file);
XX  	return;
XX-     }
XX-     if (read(fd, (char *) stbl, (int) (header.a_syms & 0xFFFF))
XX-         != (int) (header.a_syms & 0xFFFF)) {
XX- 	  fprintf(stderr, "%s: can't read symbol table\n", file);
XX- 	  return;
XX-     }
XX-     stbl_elems = (int) header.a_syms / sizeof(struct nlist);
XX-     if (!p_flag) qsort(stbl, stbl_elems, sizeof(struct nlist), nm_sort);
XX-     nm_print(file, stbl);
XX-     close(fd);
XX    }
XX  }
XX  
XX! read_header(fd)
XX  int fd;
XX  {
XX    if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
XX--- 136,176 ----
XX  	close(fd);
XX  	return;
XX    }
XX!   if (header.a_syms == 0) {
XX! 	close(fd);
XX! 	return;
XX!   }
XX!   if ((size_t) header.a_syms != header.a_syms) {
XX! 	fprintf(stderr, "%s: symbol table too large to allocate\n", file);
XX! 	close(fd);
XX! 	return;
XX!   }
XX!   if ((int) header.a_syms != header.a_syms) {
XX! 	/* This is necessary because we are too lazy to iterate the read. */
XX! 	fprintf(stderr, "%s: symbol table too large to read\n", file);
XX! 	close(fd);
XX! 	return;
XX!   }
XX!   stbl = (struct nlist *) malloc((size_t) header.a_syms);
XX!   if (stbl == NULL) {
XX  	fprintf(stderr, "%s: can't allocate symbol table\n", file);
XX+ 	close(fd);
XX  	return;
XX    }
XX+   if (read(fd, (char *) stbl, (unsigned) header.a_syms) != header.a_syms) {
XX+ 	fprintf(stderr, "%s: can't read symbol table\n", file);
XX+ 	free(stbl);
XX+ 	close(fd);
XX+ 	return;
XX+   }
XX+   stbl_elems = (int) header.a_syms / sizeof(struct nlist);
XX+   if (!p_flag) qsort(stbl, (size_t)stbl_elems, sizeof(struct nlist), nm_sort);
XX+   nm_print(file, stbl);
XX+   free(stbl);
XX+   close(fd);
XX  }
XX  
XX! int read_header(fd)
XX  int fd;
XX  {
XX    if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
XX***************
XX*** 155,161 ****
XX    return(0);
XX  }
XX  
XX! nm_print(file, stbl)
XX  char *file;
XX  register struct nlist *stbl;
XX  {
XX--- 181,187 ----
XX    return(0);
XX  }
XX  
XX! void nm_print(file, stbl)
XX  char *file;
XX  register struct nlist *stbl;
XX  {
XX***************
XX*** 182,188 ****
XX  	else
XX  		type = 'u';
XX  	if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
XX! 	strncpy(name, stbl->n_name, 8);
XX  	if (d_flag) {
XX  		/* Offsets in decimal. */
XX  		if (o_flag) 
XX--- 208,214 ----
XX  	else
XX  		type = 'u';
XX  	if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
XX! 	strncpy(name, stbl->n_name, (size_t)8);
XX  	if (d_flag) {
XX  		/* Offsets in decimal. */
XX  		if (o_flag) 
X/
Xecho x - od.c.d
Xsed '/^X/s///' > od.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/od.c  crc=30405   5305	Sun Apr 25 21:35:10 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/od.c  crc=19578   6039	Wed Nov  4 04:19:16 1992
XX***************
XX*** 3,25 ****
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  
XX! int bflag, cflag, dflag, oflag, xflag, hflag, linenr, width, state, ever;
XX  int prevwds[8];
XX  long off;
XX  char buf[512], buffer[BUFSIZ];
XX  int next;
XX  int bytespresent;
XX- char hexit();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int k, flags;
XX-   long offset();
XX    char *p;
XX  
XX    /* Process flags */
XX--- 3,39 ----
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  
XX! int bflag, cflag, dflag, oflag, xflag, hflag, vflag;
XX! int linenr, width, state, ever;
XX  int prevwds[8];
XX  long off;
XX  char buf[512], buffer[BUFSIZ];
XX  int next;
XX  int bytespresent;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(long offset, (int argc, char *argv [], int k));
XX! _PROTOTYPE(void dumpfile, (void));
XX! _PROTOTYPE(void wdump, (short *words, int k, int radix));
XX! _PROTOTYPE(void bdump, (char bytes [16 ], int k, int c));
XX! _PROTOTYPE(void byte, (int val, int c));
XX! _PROTOTYPE(int getwords, (short **words));
XX! _PROTOTYPE(int same, (short *w1, int *w2));
XX! _PROTOTYPE(void outword, (int val, int radix));
XX! _PROTOTYPE(void outnum, (int num, int radix));
XX! _PROTOTYPE(void addrout, (long l));
XX! _PROTOTYPE(char hexit, (int k));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int k, flags;
XX    char *p;
XX  
XX    /* Process flags */
XX***************
XX*** 37,42 ****
XX--- 51,57 ----
XX  		    case 'd':	dflag++;	break;
XX  		    case 'h':	hflag++;	break;
XX  		    case 'o':	oflag++;	break;
XX+ 		    case 'v':	vflag++;	break;	
XX  		    case 'x':	xflag++;	break;
XX  		    default:	usage();
XX  		}
XX***************
XX*** 63,71 ****
XX  	/* Explicit file name given. */
XX  	close(0);
XX  	if (open(argv[k], O_RDONLY) != 0) {
XX! 		std_err("od: cannot open ");
XX! 		std_err(argv[k]);
XX! 		std_err("\n");
XX  		exit(1);
XX  	}
XX  	k++;
XX--- 78,84 ----
XX  	/* Explicit file name given. */
XX  	close(0);
XX  	if (open(argv[k], O_RDONLY) != 0) {
XX! 		fprintf(stderr, "od: cannot open %s\n", argv[k]);
XX  		exit(1);
XX  	}
XX  	k++;
XX***************
XX*** 81,87 ****
XX    dumpfile();
XX    addrout(off);
XX    printf("\n");
XX!   exit(0);
XX  }
XX  
XX  
XX--- 94,100 ----
XX    dumpfile();
XX    addrout(off);
XX    printf("\n");
XX!   return(0);
XX  }
XX  
XX  
XX***************
XX*** 91,97 ****
XX  int k;
XX  {
XX    int dot, radix;
XX!   char str[80], *p, c;
XX    long val;
XX  
XX    /* See if the offset is decimal. */
XX--- 104,110 ----
XX  int k;
XX  {
XX    int dot, radix;
XX!   char *p, c;
XX    long val;
XX  
XX    /* See if the offset is decimal. */
XX***************
XX*** 120,140 ****
XX  }
XX  
XX  
XX! dumpfile()
XX  {
XX    int k;
XX    short *words;
XX  
XX    while ((k = getwords(&words))) {	/* 'k' is # bytes read */
XX! 	if (k == 16 && same(words, prevwds) && ever == 1) {
XX! 		if (state == 0) {
XX! 			printf("*\n");
XX! 			state = 1;
XX! 			off += 16;
XX! 			continue;
XX! 		} else if (state == 1) {
XX! 			off += 16;
XX! 			continue;
XX  		}
XX  	}
XX  	addrout(off);
XX--- 133,155 ----
XX  }
XX  
XX  
XX! void dumpfile()
XX  {
XX    int k;
XX    short *words;
XX  
XX    while ((k = getwords(&words))) {	/* 'k' is # bytes read */
XX! 	if (!vflag) {		/* ensure 'lazy' evaluation */
XX! 		if (k == 16 && ever == 1 && same(words, prevwds)) {
XX! 			if (state == 0) {
XX! 				printf("*\n");
XX! 				state = 1;
XX! 				off += 16;
XX! 				continue;
XX! 			} else if (state == 1) {
XX! 				off += 16;
XX! 				continue;
XX! 			}
XX  		}
XX  	}
XX  	addrout(off);
XX***************
XX*** 145,159 ****
XX  	if (oflag) wdump(words, k, 8);
XX  	if (dflag) wdump(words, k, 10);
XX  	if (xflag) wdump(words, k, 16);
XX! 	if (cflag) bdump(words, k, 'c');
XX! 	if (bflag) bdump(words, k, 'b');
XX  	for (k = 0; k < 8; k++) prevwds[k] = words[k];
XX  	for (k = 0; k < 8; k++) words[k] = 0;
XX    }
XX  }
XX  
XX  
XX! wdump(words, k, radix)
XX  short *words;
XX  int k, radix;
XX  {
XX--- 160,174 ----
XX  	if (oflag) wdump(words, k, 8);
XX  	if (dflag) wdump(words, k, 10);
XX  	if (xflag) wdump(words, k, 16);
XX! 	if (cflag) bdump((char *)words, k, (int)'c');
XX! 	if (bflag) bdump((char *)words, k, (int)'b');
XX  	for (k = 0; k < 8; k++) prevwds[k] = words[k];
XX  	for (k = 0; k < 8; k++) words[k] = 0;
XX    }
XX  }
XX  
XX  
XX! void wdump(words, k, radix)
XX  short *words;
XX  int k, radix;
XX  {
XX***************
XX*** 165,171 ****
XX  }
XX  
XX  
XX! bdump(bytes, k, c)
XX  char bytes[16];
XX  int k;
XX  char c;
XX--- 180,186 ----
XX  }
XX  
XX  
XX! void bdump(bytes, k, c)
XX  char bytes[16];
XX  int k;
XX  char c;
XX***************
XX*** 177,183 ****
XX    printf("\n");
XX  }
XX  
XX! byte(val, c)
XX  int val;
XX  char c;
XX  {
XX--- 192,198 ----
XX    printf("\n");
XX  }
XX  
XX! void byte(val, c)
XX  int val;
XX  char c;
XX  {
XX***************
XX*** 238,244 ****
XX    return(1);
XX  }
XX  
XX! outword(val, radix)
XX  int val, radix;
XX  {
XX  /* Output 'val' in 'radix' in a field of total size 'width'. */
XX--- 253,259 ----
XX    return(1);
XX  }
XX  
XX! void outword(val, radix)
XX  int val, radix;
XX  {
XX  /* Output 'val' in 'radix' in a field of total size 'width'. */
XX***************
XX*** 260,266 ****
XX  }
XX  
XX  
XX! outnum(num, radix)
XX  int num, radix;
XX  {
XX  /* Output a number with all leading 0s present.  Octal is 6 places,
XX--- 275,281 ----
XX  }
XX  
XX  
XX! void outnum(num, radix)
XX  int num, radix;
XX  {
XX  /* Output a number with all leading 0s present.  Octal is 6 places,
XX***************
XX*** 295,301 ****
XX  }
XX  
XX  
XX! addrout(l)
XX  long l;
XX  {
XX    int i;
XX--- 310,316 ----
XX  }
XX  
XX  
XX! void addrout(l)
XX  long l;
XX  {
XX    int i;
XX***************
XX*** 318,324 ****
XX  	return('A' + k - 10);
XX  }
XX  
XX! usage()
XX  {
XX!   std_err("Usage: od [-bcdhox] [file] [ [+] offset [.] [b] ]");
XX  }
XX--- 333,339 ----
XX  	return('A' + k - 10);
XX  }
XX  
XX! void usage()
XX  {
XX!   fprintf(stderr, "Usage: od [-bcdhovx] [file] [ [+] offset [.] [b] ]\n");
XX  }
X/
Xecho x - passwd.c.d
Xsed '/^X/s///' > passwd.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/passwd.c  crc=29630   2405	Sun Apr 25 21:35:11 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/passwd.c  crc=55779   4599	Sun Mar 14 00:11:34 1993
XX***************
XX*** 1,104 ****
XX! /* passwd - change a passwd		Author: Adri Koppes */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <string.h>
XX  #include <signal.h>
XX  #include <pwd.h>
XX  
XX! char pwd_file[] = "/etc/passwd";
XX! char pw_tmp[] = "/etc/pwtemp";
XX  char bad[] = "Permission denied\n";
XX! char buf[512];
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int uid, cn, n;
XX!   int fpin, fpout;
XX!   long salt;
XX!   struct passwd *pwd, *getpwnam(), *getpwuid(), *getpwent();
XX!   char name[9], password[14], sl[2];
XX!   char *getpass(), *crypt(), *itoa();
XX  
XX    uid = getuid();
XX  
XX!   if (!access(pw_tmp, 0)) {
XX! 	std_err("Temporary file in use.\nTry again later\n");
XX! 	exit(1);
XX!   }
XX!   if (argc < 2) {
XX  	pwd = getpwuid(uid);
XX! 	strcpy(name, pwd->pw_name);
XX    } else {
XX! 	strcpy(name, argv[1]);
XX  	pwd = getpwnam(name);
XX    }
XX!   if (!pwd || ((uid != pwd->pw_uid) && uid)) {
XX  	std_err(bad);
XX  	exit(1);
XX    }
XX    signal(SIGHUP, SIG_IGN);
XX    signal(SIGINT, SIG_IGN);
XX    signal(SIGQUIT, SIG_IGN);
XX    signal(SIGTERM, SIG_IGN);
XX!   prints("Changing password for %s\n", name);
XX!   if (pwd->pw_passwd[0] && uid)
XX! 	if (strcmp(pwd->pw_passwd, crypt(getpass("Old password: "), pwd->pw_passwd))) {
XX! 		std_err(bad);
XX  		exit(1);
XX  	}
XX-   strcpy(password, getpass("New password: "));
XX-   if (password[0] == '\0') {
XX- 	std_err("password cannot be null\n");
XX- 	exit(1);
XX    }
XX!   if (strcmp(password, getpass("Retype password: "))) {
XX! 	std_err("Passwords don't match\n");
XX! 	exit(1);
XX!   }
XX!   time(&salt);
XX!   sl[0] = (salt & 077) + '.';
XX!   sl[1] = ((salt >> 6) & 077) + '.';
XX!   for (cn = 0; cn < 2; cn++) {
XX! 	if (sl[cn] > '9') sl[cn] += 7;
XX! 	if (sl[cn] > 'Z') sl[cn] += 6;
XX!   }
XX!   if (password[0]) strcpy(password, crypt(password, sl));
XX!   umask(0);
XX!   close(1);
XX!   fpout = creat(pw_tmp, 0600);
XX!   if (fpout != 1) {
XX! 	std_err("Can't create temporary file\n");
XX! 	exit(1);
XX!   }
XX    setpwent();
XX    while ((pwd = getpwent()) != 0) {
XX! 	if (!strcmp(name, pwd->pw_name)) pwd->pw_passwd = password;
XX! 	prints("%s:%s:%s:", pwd->pw_name, pwd->pw_passwd, itoa(pwd->pw_uid));
XX! 	prints("%s:%s:%s:%s\n", itoa(pwd->pw_gid), pwd->pw_gecos, pwd->pw_dir,
XX! 	       pwd->pw_shell);
XX    }
XX    endpwent();
XX!   close(0);
XX!   if ((fpin = open(pw_tmp, 0)) != 0) {
XX! 	std_err("Can't reopen temporary file\n");
XX! 	exit(1);
XX!   }
XX!   close(fpout);
XX!   if ((fpout = open(pwd_file, O_RDWR)) < 0) {
XX! 	std_err("Can't recreate password file\n");
XX! 	unlink(pw_tmp);
XX! 	exit(1);
XX!   }
XX!   while (1) {
XX! 	n = read(fpin, buf, 512);
XX! 	if (n <= 0) break;
XX! 	write(1, buf, n);
XX!   }
XX  
XX!   close(fpin);
XX!   close(fpout);
XX!   unlink(pw_tmp);
XX  }
XX--- 1,236 ----
XX! /* passwd - change a passwd			Author: Adri Koppes */
XX  
XX+ /* Chfn, chsh - change full name, shell		Added by: Kees J. Bot */
XX+ 
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <string.h>
XX  #include <signal.h>
XX  #include <pwd.h>
XX+ #include <errno.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <time.h>
XX+ #include <sys/stat.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX! _PROTOTYPE(void report, (char *label));
XX! _PROTOTYPE(void quit, (int ex_stat));
XX! _PROTOTYPE(void fatal, (char *label));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(int goodchars, (char *s));
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! 
XX! char pw_file[] = "/etc/passwd";
XX! char pw_tmp[] = "/etc/ptmp";
XX  char bad[] = "Permission denied\n";
XX! char buf[1024];
XX  
XX! enum action {
XX!   PASSWD, CHFN, CHSH
XX! } action = PASSWD;
XX! 
XX! char *arg0;
XX! 
XX! void report(label)
XX! char *label;
XX! {
XX!   int e = errno;
XX!   fprintf(stderr, "%s: ", arg0);
XX!   fflush(stderr);
XX!   errno = e;
XX!   perror(label);
XX! }
XX! 
XX! void quit(ex_stat)
XX! int ex_stat;
XX! {
XX!   if (unlink(pw_tmp) < 0 && errno != ENOENT) {
XX! 	report(pw_tmp);
XX! 	ex_stat = 1;
XX!   }
XX!   exit(ex_stat);
XX! }
XX! 
XX! void fatal(label)
XX! char *label;
XX! {
XX!   report(label);
XX!   quit(1);
XX! }
XX! 
XX! void usage()
XX! {
XX!   static char *usages[] = {
XX! 	"passwd [user]\n",
XX! 	"chfn [user] fullname\n",
XX! 	"chsh [user] shell\n"
XX!   };
XX!   std_err(usages[(int) action]);
XX!   exit(1);
XX! }
XX! 
XX! int goodchars(s)
XX! char *s;
XX! {
XX!   int c;
XX! 
XX!   while ((c = *s++) != 0) {
XX! 	if (c == ':' || c < ' ' || c >= 127) return(0);
XX!   }
XX!   return(1);
XX! }
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int uid, cn, n;
XX!   int fd_pwd, fd_tmp;
XX!   FILE *fp_tmp;
XX!   time_t salt;
XX!   struct passwd *pwd;
XX!   char *name, pwname[9], password[14], sl[2];
XX!   char *argn;
XX  
XX+   if ((arg0 = strrchr(argv[0], '/')) != 0)
XX+ 	arg0++;
XX+   else
XX+ 	arg0 = argv[0];
XX+ 
XX+   if (strcmp(arg0, "chfn") == 0)
XX+ 	action = CHFN;
XX+   else if (strcmp(arg0, "chsh") == 0)
XX+ 	action = CHSH;
XX+ 
XX    uid = getuid();
XX  
XX!   n = action == PASSWD ? 1 : 2;
XX! 
XX!   if (argc != n && argc != n + 1) usage();
XX! 
XX!   if (argc == n) {
XX  	pwd = getpwuid(uid);
XX! 	strcpy(pwname, pwd->pw_name);
XX! 	name = pwname;
XX    } else {
XX! 	name = argv[1];
XX  	pwd = getpwnam(name);
XX    }
XX!   if (pwd == NULL || ((uid != pwd->pw_uid) && uid != 0)) {
XX  	std_err(bad);
XX  	exit(1);
XX    }
XX+ 
XX+   switch (action) {
XX+       case PASSWD:
XX+ 	printf("Changing password for %s\n", name);
XX+ 
XX+ 	if (pwd->pw_passwd[0] != '\0' && uid != 0) {
XX+ 		if (strcmp(pwd->pw_passwd,
XX+ 		    crypt(getpass("Old password:"), pwd->pw_passwd))
XX+ 			) {
XX+ 			std_err(bad);
XX+ 			exit(1);
XX+ 		}
XX+ 	}
XX+ 	for (;;) {
XX+ 		strcpy(password, getpass("New password:"));
XX+ 
XX+ 		if (password[0] == '\0')
XX+ 			std_err("Password cannot be null");
XX+ 		else if (strcmp(password, getpass("Retype password:")) != 0)
XX+ 			std_err("Passwords don't match");
XX+ 		else
XX+ 			break;
XX+ 
XX+ 		std_err(", try again\n");
XX+ 	}
XX+ 	time(&salt);
XX+ 	sl[0] = (salt & 077) + '.';
XX+ 	sl[1] = ((salt >> 6) & 077) + '.';
XX+ 	for (cn = 0; cn < 2; cn++) {
XX+ 		if (sl[cn] > '9') sl[cn] += 7;
XX+ 		if (sl[cn] > 'Z') sl[cn] += 6;
XX+ 	}
XX+ 	strcpy(password, crypt(password, sl));
XX+ 	break;
XX+ 
XX+       case CHFN:
XX+       case CHSH:
XX+ 	argn = argv[argc - 1];
XX+ 
XX+ 	if (strlen(argn) > (action == CHFN ? 80 : 60) || !goodchars(argn) ) {
XX+ 		std_err(bad);
XX+ 		exit(1);
XX+ 	}
XX+   }
XX+ 
XX    signal(SIGHUP, SIG_IGN);
XX    signal(SIGINT, SIG_IGN);
XX    signal(SIGQUIT, SIG_IGN);
XX    signal(SIGTERM, SIG_IGN);
XX! 
XX!   umask(0);
XX!   n = 10;
XX!   while ((fd_tmp = open(pw_tmp, O_RDWR | O_CREAT | O_EXCL, 0400)) < 0) {
XX! 	if (errno != EEXIST) fatal("Can't create temporary file");
XX! 
XX! 	if (n-- > 0) {
XX! 		sleep(2);
XX! 	} else {
XX! 		fprintf(stderr, "Password file busy, try again later.\n");
XX  		exit(1);
XX  	}
XX    }
XX! 
XX!   if ((fp_tmp = fdopen(fd_tmp, "w+")) == NULL) fatal(pw_tmp);
XX! 
XX    setpwent();
XX    while ((pwd = getpwent()) != 0) {
XX! 	if (strcmp(name, pwd->pw_name) == 0) {
XX! 		switch (action) {
XX! 		    case PASSWD:
XX! 			pwd->pw_passwd = password;
XX! 			break;
XX! 		    case CHFN:
XX! 			pwd->pw_gecos = argn;
XX! 			break;
XX! 		    case CHSH:	pwd->pw_shell = argn;
XX! 		}
XX! 	}
XX! 	if (strcmp(pwd->pw_shell, "/bin/sh") == 0
XX! 			    || strcmp(pwd->pw_shell, "/usr/bin/sh") == 0)
XX! 		pwd->pw_shell = "";
XX! 
XX! 	fprintf(fp_tmp, "%s:%s:%s:",
XX! 		pwd->pw_name,
XX! 		pwd->pw_passwd,
XX! 		itoa(pwd->pw_uid)
XX! 		);
XX! 	if (ferror(fp_tmp)) fatal(pw_tmp);
XX! 
XX! 	fprintf(fp_tmp, "%s:%s:%s:%s\n", itoa(pwd->pw_gid), pwd->pw_gecos,
XX! 			  		 pwd->pw_dir, pwd->pw_shell);
XX! 	if (ferror(fp_tmp)) fatal(pw_tmp);
XX    }
XX    endpwent();
XX!   if (fflush(fp_tmp) == EOF) fatal(pw_tmp);
XX  
XX!   if (lseek(fd_tmp, (off_t) 0, SEEK_SET) != 0)
XX! 	fatal("Can't reread temp file");
XX! 
XX!   if ((fd_pwd = creat(pw_file, 0644)) < 0)
XX! 	fatal("Can't recreate password file");
XX! 
XX!   while ((n = read(fd_tmp, buf, sizeof(buf))) != 0) {
XX! 	if (n < 0 || write(fd_pwd, buf, n) != n) {
XX! 		report("Error rewriting password file, tell root!");
XX! 		exit(1);
XX! 	}
XX!   }
XX!   close(fd_tmp);
XX!   close(fd_pwd);
XX!   quit(0);
XX  }
X/
Xecho x - paste.c.d
Xsed '/^X/s///' > paste.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/paste.c  crc=40905  11531	Sun Apr 25 21:35:11 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/paste.c  crc=50702  12595	Wed Nov  4 04:19:16 1992
XX***************
XX*** 2,62 ****
XX  
XX  /* Paste - a recreation of the Unix(Tm) paste(1) command.
XX   *
XX!  * syntax:	paste file1 file2 ...
XX!  *		paste -dLIST file1 file2 ...
XX!  *		paste -s [-dLIST] file1 file2 ...
XX   *
XX!  *	Copyright (C) 1984 by David M. Ihnat
XX   *
XX!  * This program is a total rewrite of the Bell Laboratories Unix(Tm)
XX!  * command of the same name, as of System V.  It contains no proprietary
XX!  * code, and therefore may be used without violation of any proprietary
XX!  * agreements whatsoever.  However, you will notice that the program is
XX!  * copyrighted by me.  This is to assure the program does *not* fall
XX!  * into the public domain.  Thus, I may specify just what I am now:
XX!  * This program may be freely copied and distributed, provided this notice
XX!  * remains; it may not be sold for profit without express written consent of
XX!  * the author.
XX!  * Please note that I recreated the behavior of the Unix(Tm) 'paste' command
XX!  * as faithfully as possible, with minor exceptions (noted below); however,
XX!  * I haven't run a full set of regression * tests.  Thus, the user of
XX!  * this program accepts full responsibility for any effects or loss;
XX!  * in particular, the author is not responsible for any losses,
XX!  * explicit or incidental, that may be incurred through use of this program.
XX   *
XX!  * The changes to the program, with one exception, are transparent to
XX!  * a user familiar with the Unix command of the same name.  These changes
XX!  * are:
XX   *
XX   * 1) The '-s' option had a bug in the Unix version when used with multiple
XX!  *    files.  (It would repeat each file in a list, i.e., for
XX!  *    'paste -s file1 file2 file3', it would list
XX!  *    <file1\n><file1\n><file2\n><file1\n><file2\n><file3\n>
XX!  *    I fixed this, and reported the bug to the providers of the command in
XX!  *    Unix.
XX   *
XX!  * 2) The list of valid escape sequences has been expanded to include
XX!  *    \b,\f, and \r.  (Just because *I* can't imagine why you'd want
XX!  *    to use them doesn't mean I should keep them from you.)
XX   *
XX   * 3) There is no longer any restriction on line length.
XX   *
XX   * I ask that any bugs (and, if possible, fixes) be reported to me when
XX   * possible.  -David Ihnat (312) 784-4544 ihuxx!ignatz
XX   */
XX  
XX! /* Modified to run under MINIX 1.1
XX!  * by David O. Tinker  (416) 978-3636 (utgpu!dtinker)
XX!  * Sept. 19, 1987
XX   */
XX  
XX  #include <errno.h>
XX  #include <ctype.h>
XX  #include <stdio.h>
XX  
XX- extern int errno;
XX- 
XX- 
XX  /* I'd love to use enums, but not everyone has them.  Portability, y'know. */
XX  #define NODELIM		1
XX  #define USAGE		2
XX--- 2,68 ----
XX  
XX  /* Paste - a recreation of the Unix(Tm) paste(1) command.
XX   *
XX!  * syntax: paste file1 file2 ... paste -dLIST file1 file2 ... paste -s [-dLIST]
XX!  * file1 file2 ...
XX   *
XX!  * Copyright (C) 1984 by David M. Ihnat
XX   *
XX!  * This program is a total rewrite of the Bell Laboratories Unix(Tm) command of
XX!  * the same name, as of System V.  It contains no proprietary code, and
XX!  * therefore may be used without violation of any proprietary agreements
XX!  * whatsoever.  However, you will notice that the program is copyrighted by
XX!  * me.  This is to assure the program does *not* fall into the public domain.
XX!  * Thus, I may specify just what I am now: This program may be freely copied
XX!  * and distributed, provided this notice remains; it may not be sold for
XX!  * profit without express written consent of the author. Please note that I
XX!  * recreated the behavior of the Unix(Tm) 'paste' command as faithfully as
XX!  * possible, with minor exceptions (noted below); however, I haven't run a
XX!  * full set of regression * tests.  Thus, the user of this program accepts
XX!  * full responsibility for any effects or loss; in particular, the author is
XX!  * not responsible for any losses, explicit or incidental, that may be
XX!  * incurred through use of this program.
XX   *
XX!  * The changes to the program, with one exception, are transparent to a user
XX!  * familiar with the Unix command of the same name.  These changes are:
XX   *
XX   * 1) The '-s' option had a bug in the Unix version when used with multiple
XX!  *    files.  (It would repeat each file in a list, i.e., for 
XX   *
XX!  *		paste -s file1 file2 file3
XX   *
XX+  * it would list
XX+  *
XX+  *	 <file1\n><file1\n><file2\n><file1\n><file2\n><file3\n>
XX+  *
XX+  * I fixed this, and reported the bug to the providers of the command in Unix.
XX+  *
XX+  * 2) The list of valid escape sequences has been expanded to include \b,\f, 
XX+  *    and \r.  (Just because *I* can't imagine why you'd want to use them 
XX+  *    doesn't mean I should keep them from you.)
XX+  *
XX   * 3) There is no longer any restriction on line length.
XX   *
XX   * I ask that any bugs (and, if possible, fixes) be reported to me when
XX   * possible.  -David Ihnat (312) 784-4544 ihuxx!ignatz
XX   */
XX  
XX! /* Modified to run under MINIX 1.1 by David O. Tinker  (416) 978-3636
XX!  * (utgpu!dtinker) Sept. 19, 1987
XX   */
XX  
XX+ /* Modified to conform to POSIX 1003.2/Draft10 standard 23rd Sept. 1990
XX+  * Changes:
XX+  * 	- the arguments can be in any order
XX+  *	- removed the ToUpper function
XX+  * by Thomas Brupbacher (tobr@mw.lpc.ethz.ch)
XX+  */
XX+ 
XX  #include <errno.h>
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  /* I'd love to use enums, but not everyone has them.  Portability, y'know. */
XX  #define NODELIM		1
XX  #define USAGE		2
XX***************
XX*** 69,94 ****
XX  #define	FF		'\f'
XX  #define	CR		'\r'
XX  #define DEL             '\177'
XX  
XX  #define	_MAXSZ		512
XX  #define _MAXFILES	12
XX  #define	CLOSED		((FILE *)-1)
XX  #define ENDLIST		((FILE *)-2)
XX  
XX! char *cmdnam, ToUpper();
XX  
XX  
XX! short int dflag, sflag;
XX! char delims[] = {TAB};
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   char *strcpy();
XX  
XX-   dflag = sflag = 0;
XX- 
XX    cmdnam = *argv;
XX  
XX    if (argc >= 2) {
XX--- 75,110 ----
XX  #define	FF		'\f'
XX  #define	CR		'\r'
XX  #define DEL             '\177'
XX+ #define SPACE		' '
XX+ #define BACKSLASH	'\\'
XX  
XX  #define	_MAXSZ		512
XX  #define _MAXFILES	12
XX  #define	CLOSED		((FILE *)-1)
XX  #define ENDLIST		((FILE *)-2)
XX  
XX! char *cmdnam;
XX  
XX+ short int sflag;
XX+ static char default_delims[] = {TAB};	/* default delimiter string	 */
XX+ char *delims;			/* the pointer to the delimiters        */
XX+ int number_of_delims = 1;	/* number of delimiters to use	 	 */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void docol, (int nfiles, char **fnamptr));
XX! _PROTOTYPE(void doserial, (int nfiles, char **fnamptr));
XX! _PROTOTYPE(void delimbuild, (char *strptr));
XX! _PROTOTYPE(void prerr, (int etype, char *estring));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   char **arg_ptr;		/* used to save argv, needed for docol() etc */
XX!   int num_files = 0;		/* Number of filenames specified on cmd line */
XX!   sflag = 0;
XX!   delims = default_delims;	/* use default delimiters */
XX  
XX    cmdnam = *argv;
XX  
XX    if (argc >= 2) {
XX***************
XX*** 97,138 ****
XX  	argv++;
XX  	argc--;
XX  
XX  	/* First, parse input options */
XX  
XX! 	while (argv[0][0] == '-' && argv[0][1] != '\0') {
XX! 		switch (ToUpper(argv[0][1])) {
XX! 		    case 'D':
XX! 			/* Delimiter character(s) */
XX! 			strcpy(delims, &argv[0][2]);
XX! 			if (*delims == '\0')
XX! 				prerr(NODELIM, "");
XX! 			else
XX! 				delimbuild(delims);
XX  
XX! 			break;
XX  
XX! 		    case 'S':	sflag++;	break;
XX! 
XX! 		    default:	prerr(USAGE, "");
XX  		}
XX- 		argv++;
XX- 		argc--;
XX  	}
XX-   } else
XX- 	prerr(USAGE, "");
XX  
XX!   /* If no files specified, simply exit.  Otherwise, if not the old
XX!    * '-s' option, process all files. If '-s', then process files
XX!    * one-at-a-time. */
XX!   if (!sflag)
XX! 	docol(argc, argv);	/* Column paste */
XX!   else
XX! 	doserial(argc, argv);	/* Serial paste */
XX  
XX!   exit(0);
XX  }
XX  
XX! docol(nfiles, fnamptr)
XX  int nfiles;
XX  char **fnamptr;
XX  {
XX--- 113,165 ----
XX  	argv++;
XX  	argc--;
XX  
XX+ 	/* Save argv */
XX+ 	arg_ptr = argv;
XX  	/* First, parse input options */
XX  
XX! 	while (argc-- > 0) {
XX! 		if (argv[0][0] == '-' && argv[0][1] != '\0') {
XX! 			switch (argv[0][1]) {
XX! 			    case 'd':
XX! 				/* Delimiter character(s) */
XX! 				if (*(++argv) == '\0')
XX! 					prerr(NODELIM, "");
XX! 				else
XX! 					delimbuild(*(argv));
XX! 				argc--;
XX! 				break;
XX  
XX! 			    case 's':	sflag++;	break;
XX  
XX! 			    default:	prerr(USAGE, "");
XX! 			}
XX! 			argv++;
XX! 		} else {
XX! 			num_files++;
XX! 			argv++;
XX  		}
XX  	}
XX  
XX! 	/* If there are more than MAX_FILES files on the command
XX! 	 * line, exit with error message.						 */
XX! 	if (num_files > _MAXFILES) prerr(TOOMANY, "");
XX  
XX! 	/* If no files specified, simply exit.  Otherwise, if not the
XX! 	 * old '-s' option, process all files. If '-s', then process
XX! 	 * files one-at-a-time. */
XX! 
XX! 	if (!sflag)
XX! 		docol(num_files, arg_ptr);	/* Column paste */
XX! 	else
XX! 		doserial(num_files, arg_ptr);	/* Serial paste */
XX! 
XX! 	exit(0);
XX!   } else
XX! 	prerr(USAGE, "");
XX!   return(0);
XX  }
XX  
XX! void docol(nfiles, fnamptr)
XX  int nfiles;
XX  char **fnamptr;
XX  {
XX***************
XX*** 143,156 ****
XX     * closed, or will on this round.  In that case, the string of
XX     * delimiters must be preserved.  delbuf[1] ->delbuf[MAXFILES+1]
XX     * provides intermediate storage for closed files, if needed;
XX!    * delbuf[0] is the current index. */
XX    char delbuf[_MAXFILES + 2];
XX  
XX    FILE *fileptr[_MAXFILES + 1];
XX-   FILE *fopen();
XX  
XX-   char *fgets();
XX- 
XX    int filecnt;			/* Set to number of files to process */
XX    register char *delimptr;	/* Cycling delimiter pointer */
XX    int index;			/* Working variable */
XX--- 170,181 ----
XX     * closed, or will on this round.  In that case, the string of
XX     * delimiters must be preserved.  delbuf[1] ->delbuf[MAXFILES+1]
XX     * provides intermediate storage for closed files, if needed;
XX!    * delbuf[0] is the current index.
XX!    */
XX    char delbuf[_MAXFILES + 2];
XX  
XX    FILE *fileptr[_MAXFILES + 1];
XX  
XX    int filecnt;			/* Set to number of files to process */
XX    register char *delimptr;	/* Cycling delimiter pointer */
XX    int index;			/* Working variable */
XX***************
XX*** 160,185 ****
XX     * could be expanded to an infinite number of files, but at the
XX     * (considerable) expense of remembering the file and its current
XX     * offset, then opening/reading/closing.  The commands' utility
XX!    * doesn't warrant the effort; at least, to me...) */
XX  
XX!   for (filecnt = 0; (nfiles > 0) && (filecnt < _MAXFILES); filecnt++, nfiles--, fnamptr++) {
XX! 	if (fnamptr[0][0] == '-')
XX! 		fileptr[filecnt] = stdin;
XX! 	else {
XX! 		fileptr[filecnt] = fopen(*fnamptr, "r");
XX! 		if (fileptr[filecnt] == NULL) prerr(BADFILE, *fnamptr);
XX  	}
XX    }
XX  
XX    fileptr[filecnt] = ENDLIST;	/* End of list. */
XX  
XX-   if (nfiles) prerr(TOOMANY, "");
XX- 
XX    /* Have all files.  Now, read a line from each file, and output to
XX     * stdout.  Notice that the old 511 character limitation on the line
XX     * length no longer applies, since this program doesn't do the
XX     * buffering.  Do this until you go through the loop and don't
XX!    * successfully read from any of the files. */
XX    for (; filecnt;) {
XX  	somedone = 0;		/* Blank field handling flag */
XX  	delimptr = delims;	/* Start at beginning of delim list */
XX--- 185,216 ----
XX     * could be expanded to an infinite number of files, but at the
XX     * (considerable) expense of remembering the file and its current
XX     * offset, then opening/reading/closing.  The commands' utility
XX!    * doesn't warrant the effort; at least, to me...) 
XX!    */
XX  
XX!   for (filecnt = 0; (nfiles > 0); fnamptr++) {
XX! 	if ((fnamptr[0][0] == '-') && (fnamptr[0][1] != '\0')) {
XX! 		if (fnamptr[0][1] == 'd') fnamptr++;
XX! 	} else {
XX! 		nfiles--;
XX! 		if (fnamptr[0][0] == '-') {
XX! 			fileptr[filecnt++] = stdin;
XX! 		} else {
XX! 			fileptr[filecnt] = fopen(fnamptr[0], "r");
XX! 			if (fileptr[filecnt++] == NULL)
XX! 				prerr(BADFILE, *fnamptr);
XX! 		}
XX  	}
XX    }
XX  
XX    fileptr[filecnt] = ENDLIST;	/* End of list. */
XX  
XX    /* Have all files.  Now, read a line from each file, and output to
XX     * stdout.  Notice that the old 511 character limitation on the line
XX     * length no longer applies, since this program doesn't do the
XX     * buffering.  Do this until you go through the loop and don't
XX!    * successfully read from any of the files.
XX!    */
XX    for (; filecnt;) {
XX  	somedone = 0;		/* Blank field handling flag */
XX  	delimptr = delims;	/* Start at beginning of delim list */
XX***************
XX*** 192,204 ****
XX  		 * 
XX  		 * Otherwise, if it is from the last file, then leave
XX  		 * the carriage return in place; if not, replace with
XX! 		 * a delimiter (if any) */
XX  
XX  		strend = 0;	/* Set so can easily detect EOF */
XX  
XX  		if (fileptr[index] != CLOSED)
XX! 			while (fgets(iobuff, (_MAXSZ - 1), fileptr[index]) != (char *) NULL) {
XX! 				strend = strlen(iobuff);	/* Did the buffer fill? */
XX  
XX  				if (strend == (_MAXSZ - 1)) {
XX  					/* Gosh, what a long line. */
XX--- 223,237 ----
XX  		 * 
XX  		 * Otherwise, if it is from the last file, then leave
XX  		 * the carriage return in place; if not, replace with
XX! 		 * a delimiter (if any) 
XX!  		 */
XX  
XX  		strend = 0;	/* Set so can easily detect EOF */
XX  
XX  		if (fileptr[index] != CLOSED)
XX! 			while (fgets(iobuff, (_MAXSZ - 1), 
XX! 					fileptr[index]) != NULL) {
XX! 				strend = strlen(iobuff);/* Did the buf fill? */
XX  
XX  				if (strend == (_MAXSZ - 1)) {
XX  					/* Gosh, what a long line. */
XX***************
XX*** 219,225 ****
XX  		 * wrong, so I'm going to be very Unix-like and
XX  		 * ignore it!), or a closed file, or a received line.
XX  		 * If an EOF, close the file and mark it in the list.
XX! 		 * In any case, output the delimiter of choice. */
XX  
XX  		if (!strend) {
XX  			if (fileptr[index] != CLOSED) {
XX--- 252,259 ----
XX  		 * wrong, so I'm going to be very Unix-like and
XX  		 * ignore it!), or a closed file, or a received line.
XX  		 * If an EOF, close the file and mark it in the list.
XX! 		 * In any case, output the delimiter of choice. 
XX! 		 */
XX  
XX  		if (!strend) {
XX  			if (fileptr[index] != CLOSED) {
XX***************
XX*** 266,272 ****
XX  			if (fileptr[index + 1] != ENDLIST) {
XX  				if (*delimptr == DEL) {
XX  					delimptr++;
XX! 					iobuff[strend - 1] = '\0';	/* No delim */
XX  				} else
XX  					iobuff[strend - 1] = *delimptr++;
XX  			}
XX--- 300,306 ----
XX  			if (fileptr[index + 1] != ENDLIST) {
XX  				if (*delimptr == DEL) {
XX  					delimptr++;
XX! 					iobuff[strend - 1] = '\0';/* No delim*/
XX  				} else
XX  					iobuff[strend - 1] = *delimptr++;
XX  			}
XX***************
XX*** 280,346 ****
XX    }
XX  }
XX  
XX! doserial(nfiles, fnamptr)
XX  int nfiles;
XX  char **fnamptr;
XX  {
XX    /* Do serial paste.  Simply scarf characters, performing
XX!    * one-character buffering to facilitate delim processing. */
XX  
XX    register int charnew, charold;
XX    register char *delimptr;
XX  
XX    register FILE *fileptr;
XX-   FILE *fopen();
XX  
XX!   for (; nfiles; nfiles--, fnamptr++) {
XX! 	if (fnamptr[0][0] == '-')
XX! 		fileptr = stdin;
XX! 	else {
XX! 		fileptr = fopen(*fnamptr, "r");
XX  
XX! 		if (fileptr == NULL) prerr(BADFILE, *fnamptr);
XX! 	}
XX  
XX! 	/* The file is open; just keep taking characters, stashing
XX! 	 * them in charnew; output charold, converting to the
XX! 	 * appropriate delimiter character if needful.  After the
XX! 	 * EOF, simply output 'charold' if it's a newline; otherwise,
XX! 	 * output it and then a newline. */
XX  
XX! 	delimptr = delims;	/* Set up for delimiter string */
XX  
XX! 	if ((charold = getc(fileptr)) == EOF) {
XX! 		/* Empty file! */
XX! 		putc(NL, stdout);
XX! 		fflush(stdout);
XX! 		continue;	/* Go on to the next file */
XX! 	}
XX  
XX! 	/* Ok, 'charold' is set up.  Hit it! */
XX  
XX! 	while ((charnew = getc(fileptr)) != EOF) {
XX! 		/* Ok, process the old character */
XX! 		if (charold == NL) {
XX! 			if (*delimptr != DEL) putc(*delimptr++, stdout);
XX  
XX! 			/* Reset pointer at end of delimiter string */
XX! 			if (*delimptr == '\0') delimptr = delims;
XX! 		} else
XX! 			putc((char) charold, stdout);
XX  
XX! 		charold = charnew;
XX! 	}
XX  
XX! 	/* Ok, hit EOF.  Process that last character */
XX  
XX! 	putc((char) charold, stdout);
XX! 	if ((char) charold != NL) putc(NL, stdout);
XX! 	fflush(stdout);
XX    }
XX  }
XX  
XX! delimbuild(strptr)
XX  char *strptr;
XX  {
XX    /* Process the delimiter string into something that can be used by
XX--- 314,388 ----
XX    }
XX  }
XX  
XX! void doserial(nfiles, fnamptr)
XX  int nfiles;
XX  char **fnamptr;
XX  {
XX    /* Do serial paste.  Simply scarf characters, performing
XX!    * one-character buffering to facilitate delim processing. 
XX!    */
XX  
XX    register int charnew, charold;
XX    register char *delimptr;
XX  
XX    register FILE *fileptr;
XX  
XX!   for (; nfiles != 0; fnamptr++) {
XX! 	if ((fnamptr[0][0] == '-') && (fnamptr[0][1] != '\0')) {
XX! 		if (fnamptr[0][1] == 'd') fnamptr++;
XX! 	} else {
XX! 		if (fnamptr[0][0] == '-') {
XX! 			fileptr = stdin;
XX! 		} else {
XX! 			fileptr = fopen(*fnamptr, "r");
XX  
XX! 			if (fileptr == NULL) prerr(BADFILE, *fnamptr);
XX! 		}
XX  
XX! 		/* The file is open; just keep taking characters,
XX! 		 * stashing them in charnew; output charold,
XX! 		 * converting to the appropriate delimiter character
XX! 		 * if needful.  After the EOF, simply output
XX! 		 * 'charold' if it's a newline; otherwise, output it
XX! 		 * and then a newline. 
XX! 		 */
XX  
XX! 		delimptr = delims;	/* Set up for delimiter string */
XX  
XX! 		if ((charold = getc(fileptr)) == EOF) {
XX! 			/* Empty file! */
XX! 			putc(NL, stdout);
XX! 			fflush(stdout);
XX! 			continue;	/* Go on to the next file */
XX! 		}
XX  
XX! 		/* Ok, 'charold' is set up.  Hit it! */
XX  
XX! 		while ((charnew = getc(fileptr)) != EOF) {
XX! 			/* Ok, process the old character */
XX! 			if (charold == NL) {
XX! 				if (*delimptr != DEL)
XX! 					putc((int) *delimptr++, stdout);
XX  
XX! 				/* Reset pointer at end of delimiter string */
XX! 				if (*delimptr == '\0') delimptr = delims;
XX! 			} else
XX! 				putc(charold, stdout);
XX  
XX! 			charold = charnew;
XX! 		}
XX  
XX! 		/* Ok, hit EOF.  Process that last character */
XX  
XX! 		putc(charold, stdout);
XX! 		if ((char) charold != NL) putc(NL, stdout);
XX! 		fflush(stdout);
XX! 		nfiles--;
XX! 	}
XX    }
XX  }
XX  
XX! void delimbuild(strptr)
XX  char *strptr;
XX  {
XX    /* Process the delimiter string into something that can be used by
XX***************
XX*** 348,357 ****
XX     * representations of special characters into their actual values,
XX     * and terminating the string in a manner that the routines can
XX     * recognize.  The set of possible backslash characters has been
XX!    * expanded beyond that recognized by the vanilla Unix(Tm) version. */
XX  
XX    register char *strout;
XX  
XX    strout = strptr;		/* Start at the same place, anyway */
XX  
XX    while (*strptr) {
XX--- 390,401 ----
XX     * representations of special characters into their actual values,
XX     * and terminating the string in a manner that the routines can
XX     * recognize.  The set of possible backslash characters has been
XX!    * expanded beyond that recognized by the vanilla Unix(Tm) version. 
XX!    */
XX  
XX    register char *strout;
XX  
XX+   delims = strptr;		/* delims now points to argv[...]	 */
XX    strout = strptr;		/* Start at the same place, anyway */
XX  
XX    while (*strptr) {
XX***************
XX*** 360,378 ****
XX  	else {
XX  		strptr++;	/* Get past escape character */
XX  
XX! 		switch (ToUpper(*strptr)) {
XX  		    case '0':	*strout++ = DEL;	break;
XX  
XX! 		    case 'T':	*strout++ = TAB;	break;
XX  
XX! 		    case 'N':	*strout++ = NL;	break;
XX  
XX! 		    case 'B':	*strout++ = BS;	break;
XX  
XX! 		    case 'F':	*strout++ = FF;	break;
XX  
XX! 		    case 'R':	*strout++ = CR;	break;
XX  
XX  		    default:	*strout++ = *strptr;
XX  		}
XX  
XX--- 404,426 ----
XX  	else {
XX  		strptr++;	/* Get past escape character */
XX  
XX! 		switch (*strptr) {
XX  		    case '0':	*strout++ = DEL;	break;
XX  
XX! 		    case 't':	*strout++ = TAB;	break;
XX  
XX! 		    case 'n':	*strout++ = NL;	break;
XX  
XX! 		    case 'b':	*strout++ = BS;	break;
XX  
XX! 		    case 'f':	*strout++ = FF;	break;
XX  
XX! 		    case 'r':	*strout++ = CR;	break;
XX  
XX+ 		    case '\\':
XX+ 			*strout++ = BACKSLASH;
XX+ 			break;
XX+ 
XX  		    default:	*strout++ = *strptr;
XX  		}
XX  
XX***************
XX*** 383,395 ****
XX    *strout = '\0';		/* Heaven forfend that we forget this! */
XX  }
XX  
XX! prerr(etype, estring)
XX  int etype;
XX  char *estring;
XX  {
XX    switch (etype) {
XX        case USAGE:
XX! 	fprintf(stderr, "%s : Usage: %s [-s] [-d<delimiter>] file1 file2 ...\n", cmdnam, cmdnam);
XX  	break;
XX  
XX        case NODELIM:
XX--- 431,443 ----
XX    *strout = '\0';		/* Heaven forfend that we forget this! */
XX  }
XX  
XX! void prerr(etype, estring)
XX  int etype;
XX  char *estring;
XX  {
XX    switch (etype) {
XX        case USAGE:
XX! 	fprintf(stderr, "%s : Usage: %s [-s] [-d <delimiters>] file1 file2 ...\n", cmdnam, cmdnam);
XX  	break;
XX  
XX        case NODELIM:
XX***************
XX*** 405,429 ****
XX  	break;
XX    }
XX    exit(1);
XX- }
XX- 
XX- char ToUpper(c)			/* This is non-standard, but it works */
XX- char c;
XX- {
XX-   char x;
XX- 
XX-   if (isalpha(c)) {
XX- 	if (c > 'Z')
XX- 		x = (c - ' ');
XX- 	else
XX- 		x = c;
XX-   } else {
XX- 	if (isdigit(c))
XX- 		x = c;
XX- 	else
XX- 		x = '\0';	/* this will terminate a string at
XX- 				 * any character other than a letter
XX- 				 * or numeral.            */
XX-   }
XX-   return(x);
XX  }
XX--- 453,456 ----
X/
Xecho x - pr.c.d
Xsed '/^X/s///' > pr.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/pr.c  crc=40424  12218	Sun Apr 25 21:35:11 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/pr.c  crc=12214  12261	Wed Nov  4 07:51:30 1992
XX***************
XX*** 1,6 ****
XX  /* pr - print files			Author: Michiel Huisjes */
XX  
XX- 
XX  /* Pr - print files
XX   *
XX   * Author: Michiel Huisjes.
XX--- 1,5 ----
XX***************
XX*** 33,49 ****
XX   *        -h header: Take next argument as page header.
XX   *        -w width  : Take the width of the page to be n instead of default 79
XX   *	  -f : do not fold lines.
XX   * Modified: Lars Fredriksen		(Jan 19, 1990)
XX!  *	fixed the program so that 
XX   *		pr -n *.c
XX   *	would work. The clobal variable 'width' was decremented
XX   *	by NUM_WIDTH, for each file, resulting in width finally
XX   *	being so small that nothing was printed. Used the local
XX   *	variable 'w' for the width adjustment (in print())
XX   */
XX  
XX  #include <stdio.h>
XX  
XX  #define DEF_LENGTH	66
XX  #define DEF_WIDTH	79
XX  #define NUM_WIDTH	8
XX--- 32,62 ----
XX   *        -h header: Take next argument as page header.
XX   *        -w width  : Take the width of the page to be n instead of default 79
XX   *	  -f : do not fold lines.
XX+  *
XX   * Modified: Lars Fredriksen		(Jan 19, 1990)
XX!  *	fixed the program so that
XX   *		pr -n *.c
XX   *	would work. The clobal variable 'width' was decremented
XX   *	by NUM_WIDTH, for each file, resulting in width finally
XX   *	being so small that nothing was printed. Used the local
XX   *	variable 'w' for the width adjustment (in print())
XX+  *
XX+  * Modified: Kenneth J. Hendrickson	(10 April 1991)
XX+  *	date in header should be last modification date for files,
XX+  *	and the current time for stdin.
XX+  *
XX+  * Modified: Kees J. Bot		(5 October 1992)
XX+  *	Use localtime(3) to get the date, it knows TZ.
XX   */
XX  
XX+ #include <sys/types.h>
XX+ #include <sys/stat.h>
XX+ #include <string.h>
XX+ #include <time.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX+ 
XX  #define DEF_LENGTH	66
XX  #define DEF_WIDTH	79
XX  #define NUM_WIDTH	8
XX***************
XX*** 57,64 ****
XX  #define FALSE		0
XX  #define TRUE		1
XX  
XX- #define NIL_PTR		((char *) 0)
XX- 
XX  /* EAT:	eat rest of input line */
XX  #define EAT(fp)		while((c=getc(fp))!='\n' && c!=EOF)
XX  
XX--- 70,75 ----
XX***************
XX*** 71,77 ****
XX  BOOL minix_number = FALSE;
XX  BOOL ext_header_set = FALSE;	/* external header given */
XX  BOOL back_space = TRUE;		/* back space correction in line width */
XX! BOOL dont_fold = FALSE;		/* original. If the line does not fit eat it.*/
XX  short columns;
XX  short cwidth;
XX  short start_page = 1;
XX--- 82,88 ----
XX  BOOL minix_number = FALSE;
XX  BOOL ext_header_set = FALSE;	/* external header given */
XX  BOOL back_space = TRUE;		/* back space correction in line width */
XX! BOOL dont_fold = FALSE;		/* original. If the line does not fit eat it. */
XX  short columns;
XX  short cwidth;
XX  short start_page = 1;
XX***************
XX*** 81,90 ****
XX  char *line_buf;			/* used in format for multi-column output */
XX  
XX  char output[1024];
XX- FILE *fopen();
XX- static char *myalloc();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 92,108 ----
XX  char *line_buf;			/* used in format for multi-column output */
XX  
XX  char output[1024];
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(static char *myalloc, (size_t size));
XX! _PROTOTYPE(char skip_page, (int lines, int width, FILE * filep));
XX! _PROTOTYPE(void format, (FILE * filep));
XX! _PROTOTYPE(void print_page, (int pagenr, int maxcol));
XX! _PROTOTYPE(void print, (FILE * filep));
XX! _PROTOTYPE(void out_header, (int page));
XX! _PROTOTYPE(void print_time, (time_t t));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 165,171 ****
XX  	}
XX  	for (line = 0; line < length; line++)
XX  		for (col = 0; col < columns; col++)
XX! 			L_BUF(line, col) = NIL_PTR;
XX  
XX  	if (length <= 0) {
XX  		fprintf(stderr, "Minimal length should be %d\n", no_header ?
XX--- 183,189 ----
XX  	}
XX  	for (line = 0; line < length; line++)
XX  		for (col = 0; col < columns; col++)
XX! 			L_BUF(line, col) = NULL;
XX  
XX  	if (length <= 0) {
XX  		fprintf(stderr, "Minimal length should be %d\n", no_header ?
XX***************
XX*** 205,211 ****
XX    } while (index <= argc);	/* "pr -l60" should work too */
XX  
XX    (void) fflush(stdout);
XX!   exit(0);
XX  }
XX  
XX  char skip_page(lines, width, filep)
XX--- 223,229 ----
XX    } while (index <= argc);	/* "pr -l60" should work too */
XX  
XX    (void) fflush(stdout);
XX!   return(0);
XX  }
XX  
XX  char skip_page(lines, width, filep)
XX***************
XX*** 242,248 ****
XX    return c;			/* last char read */
XX  }
XX  
XX! format(filep)
XX  FILE *filep;
XX  {
XX    char buf[512];
XX--- 260,266 ----
XX    return c;			/* last char read */
XX  }
XX  
XX! void format(filep)
XX  FILE *filep;
XX  {
XX    char buf[512];
XX***************
XX*** 266,274 ****
XX  	lines = columns * length;
XX  	for (line = 0; line < length; line++)
XX  		for (col = 0; col < columns; col++) {
XX! 			if (L_BUF(line, col) != NIL_PTR)
XX  				free(L_BUF(line, col));
XX! 			L_BUF(line, col) = (char *) NIL_PTR;
XX  		}
XX  	line = 0;
XX  	col = 0;
XX--- 284,292 ----
XX  	lines = columns * length;
XX  	for (line = 0; line < length; line++)
XX  		for (col = 0; col < columns; col++) {
XX! 			if (L_BUF(line, col) != NULL)
XX  				free(L_BUF(line, col));
XX! 			L_BUF(line, col) = (char *) NULL;
XX  		}
XX  	line = 0;
XX  	col = 0;
XX***************
XX*** 327,336 ****
XX    } while (c != EOF);
XX  }
XX  
XX! print_page(pagenr, maxcol)
XX  short pagenr, maxcol;
XX  {
XX!   short pad, i, j, start;
XX    short width;
XX    char *p;
XX  
XX--- 345,354 ----
XX    } while (c != EOF);
XX  }
XX  
XX! void print_page(pagenr, maxcol)
XX  short pagenr, maxcol;
XX  {
XX!   short pad, i, j;
XX    short width;
XX    char *p;
XX  
XX***************
XX*** 359,371 ****
XX    if (!no_header) printf("\n\n\n\n\n");
XX  }
XX  
XX! print(filep)
XX  FILE *filep;
XX  {
XX    short c = '\0';
XX    short page_number = 0;
XX    short lines;
XX!   short cnt, i, max;
XX    short w = width;
XX    BOOL pr_number = TRUE;	/* only real lines are numbered, not folded
XX  			 * parts */
XX--- 377,389 ----
XX    if (!no_header) printf("\n\n\n\n\n");
XX  }
XX  
XX! void print(filep)
XX  FILE *filep;
XX  {
XX    short c = '\0';
XX    short page_number = 0;
XX    short lines;
XX!   short cnt;
XX    short w = width;
XX    BOOL pr_number = TRUE;	/* only real lines are numbered, not folded
XX  			 * parts */
XX***************
XX*** 436,510 ****
XX  }
XX  
XX  static char *myalloc(size)
XX! int size;			/* How many bytes */
XX  {
XX!   char *ptr, *malloc();
XX  
XX!   ptr = malloc((unsigned) size);
XX!   if (ptr == (char *) 0) {
XX! 	fprintf(stderr, "malloc returned %d\n", ptr);
XX  	exit(1);
XX    }
XX    return(char *) ptr;
XX  }
XX  
XX! out_header(page)
XX  short page;
XX  {
XX!   extern long time();
XX!   long t;
XX  
XX!   (void) time(&t);
XX    print_time(t);
XX    printf("  %s   Page %d\n\n\n", header, page);
XX  }
XX  
XX- #define MINUTE	60L
XX- #define HOUR	(60L * MINUTE)
XX- #define DAY	(24L * HOUR)
XX- #define YEAR	(365L * DAY)
XX- #define LYEAR	(366L * DAY)
XX- 
XX- int mo[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
XX- 
XX  char *moname[] = {
XX  	  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
XX  	  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
XX  };
XX  
XX! /* Print the date.  This only works from 1970 to 2099. */
XX! print_time(t)
XX! long t;
XX  {
XX!   int i, year, day, month, hour, minute;
XX!   long length, time(), original;
XX  
XX!   year = 1970;
XX!   original = t;
XX!   while (t > 0) {
XX! 	length = (year % 4 == 0 ? LYEAR : YEAR);
XX! 	if (t < length) break;
XX! 	t -= length;
XX! 	year++;
XX!   }
XX  
XX!   /* Year has now been determined.  Now the rest. */
XX!   day = (int) (t / DAY);
XX!   t -= (long) day *DAY;
XX!   hour = (int) (t / HOUR);
XX!   t -= (long) hour *HOUR;
XX!   minute = (int) (t / MINUTE);
XX! 
XX!   /* Determine the month and day of the month. */
XX!   mo[1] = (year % 4 == 0 ? 29 : 28);
XX!   month = 0;
XX!   i = 0;
XX!   while (day >= mo[i]) {
XX! 	month++;
XX! 	day -= mo[i];
XX! 	i++;
XX!   }
XX! 
XX!   /* At this point, 'year', 'month', 'day', 'hour', 'minute'  ok */
XX!   printf("\n\n%s %2d %2d:%02d %d", moname[month], day+1, hour, minute, year);
XX  }
XX--- 454,504 ----
XX  }
XX  
XX  static char *myalloc(size)
XX! size_t size;			/* How many bytes */
XX  {
XX!   void *ptr;
XX  
XX!   ptr = malloc(size);
XX!   if (ptr == NULL) {
XX! 	fprintf(stderr, "malloc returned NULL\n");
XX  	exit(1);
XX    }
XX    return(char *) ptr;
XX  }
XX  
XX! void out_header(page)
XX  short page;
XX  {
XX!   time_t t;
XX!   struct stat buf;
XX  
XX!   if (strlen(header)) {
XX! 	stat(header, &buf);	/* use last modify time for file */
XX! 	t = buf.st_mtime;
XX!   } else
XX! 	(void) time(&t);	/* use current time for stdin */
XX    print_time(t);
XX    printf("  %s   Page %d\n\n\n", header, page);
XX  }
XX  
XX  char *moname[] = {
XX  	  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
XX  	  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
XX  };
XX  
XX! /* Print the date. */
XX! void print_time(t)
XX! time_t t;
XX  {
XX!   struct tm *tm;
XX  
XX!   tm = localtime(&t);
XX  
XX!   printf("\n\n%s %2d %2d:%02d %d",
XX!          moname[tm->tm_mon],
XX!          tm->tm_mday,
XX!          tm->tm_hour,
XX!          tm->tm_min,
XX!          1900 + tm->tm_year
XX! 	);
XX  }
X/
Xecho x - prep.c.d
Xsed '/^X/s///' > prep.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/prep.c  crc=61375   2057	Sun Apr 25 21:35:12 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/prep.c  crc=25185   2308	Wed Nov  4 04:19:17 1992
XX***************
XX*** 1,6 ****
XX--- 1,7 ----
XX  /* prep - prepare file for statistics 	Author: Andy Tanenbaum */
XX  
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define TROFF_CHAR	'.'	/* troff commands begin with this char */
XX***************
XX*** 9,23 ****
XX  #define BACKSLASH       '\\'	/* troff code */
XX  
XX  int lfread;			/* set when last char read was lf */
XX! int lfwritten;			/* set when last char written was lf */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  
XX!   int c, backslash();
XX!   FILE *freopen();
XX  
XX    if (argc > 2) usage();
XX    if (argc == 2) {
XX--- 10,28 ----
XX  #define BACKSLASH       '\\'	/* troff code */
XX  
XX  int lfread;			/* set when last char read was lf */
XX! int lfwritten = 1;		/* set when last char written was lf */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void skipline, (void));
XX! _PROTOTYPE(int backslash, (void));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  
XX!   int c;
XX  
XX    if (argc > 2) usage();
XX    if (argc == 2) {
XX***************
XX*** 57,67 ****
XX  	putchar(EOL);
XX  	lfwritten = 1;
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX! skipline()
XX  {
XX    char c;
XX  
XX--- 62,72 ----
XX  	putchar(EOL);
XX  	lfwritten = 1;
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX! void skipline()
XX  {
XX    char c;
XX  
XX***************
XX*** 73,79 ****
XX  {
XX  /* A backslash has been seen.  Eat troff stuff. */
XX  
XX!   int c;
XX  
XX    c = getchar();
XX    switch (c) {
XX--- 78,84 ----
XX  {
XX  /* A backslash has been seen.  Eat troff stuff. */
XX  
XX!   int c, c1, c2;
XX  
XX    c = getchar();
XX    switch (c) {
XX***************
XX*** 106,114 ****
XX  		return(c);
XX  	}
XX        case '(':			/* troff 4-character escape sequence */
XX  	c = getchar();
XX- 	c = getchar();
XX- 	c = getchar();
XX  	return(c);
XX  
XX        default:
XX--- 111,121 ----
XX  		return(c);
XX  	}
XX        case '(':			/* troff 4-character escape sequence */
XX+ 	c1 = getchar();
XX+ 	c2 = getchar();
XX+ 	if (c1 == 'e' && c2 == 'm') return(' ');
XX+ 	if (c1 == 'e' && c2 == 'n') return(' ');
XX  	c = getchar();
XX  	return(c);
XX  
XX        default:
XX***************
XX*** 117,123 ****
XX    }
XX  }
XX  
XX! usage()
XX  {
XX    printf("Usage: prep [file]\n");
XX    exit(1);
XX--- 124,130 ----
XX    }
XX  }
XX  
XX! void usage()
XX  {
XX    printf("Usage: prep [file]\n");
XX    exit(1);
X/
Xecho x - pretty.c.d
Xsed '/^X/s///' > pretty.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/pretty.c  crc=60480  10783	Sun Apr 25 21:35:12 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/pretty.c  crc=40556  11750	Wed Nov  4 04:19:17 1992
XX***************
XX*** 13,18 ****
XX--- 13,22 ----
XX   * To use pretty, install "indent" in /bin or /usr/bin.
XX   */
XX  
XX+ #include <sys/types.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define NAME_SIZE          14
XX***************
XX*** 29,35 ****
XX  char buf3[BUF_SIZE];
XX  int loops;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 33,57 ----
XX  char buf3[BUF_SIZE];
XX  int loops;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void indent, (char *s, char *intermediate));
XX! _PROTOTYPE(void process, (char *s, char *intermediate));
XX! _PROTOTYPE(int join, (void));
XX! _PROTOTYPE(void shift_left, (char *p));
XX! _PROTOTYPE(void shift_right, (char *p));
XX! _PROTOTYPE(int line_length, (char *p));
XX! _PROTOTYPE(void place_comment, (char *buf));
XX! _PROTOTYPE(void ifwhilefor, (FILE *in, FILE *out));
XX! _PROTOTYPE(void do_return, (char *b));
XX! _PROTOTYPE(void splice_comment, (FILE *in));
XX! _PROTOTYPE(void add_blank, (void));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(void do_case, (FILE *in));
XX! _PROTOTYPE(void capitalize, (void));
XX! _PROTOTYPE(void scrunch, (FILE *in));
XX! _PROTOTYPE(void three_liner, (FILE *in));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 45,51 ****
XX  	p = name + strlen(name) - 1;
XX  	while (p >= name && *p != '/') p--;
XX  	p++;			/* p points to last component */
XX! 	strncpy(intermediate, p, NAME_SIZE);
XX  	if (strlen(intermediate) < NAME_SIZE) {
XX  		/* Name is less than 14 chars.  Just add "+" to name. */
XX  		strcat(intermediate, "+");
XX--- 67,73 ----
XX  	p = name + strlen(name) - 1;
XX  	while (p >= name && *p != '/') p--;
XX  	p++;			/* p points to last component */
XX! 	strncpy(intermediate, p, (size_t)NAME_SIZE);
XX  	if (strlen(intermediate) < NAME_SIZE) {
XX  		/* Name is less than 14 chars.  Just add "+" to name. */
XX  		strcat(intermediate, "+");
XX***************
XX*** 59,67 ****
XX  	process(name, intermediate);
XX  	unlink(intermediate);
XX    }
XX  }
XX  
XX! indent(s, intermediate)
XX  char *s;			/* name of file to prettyprint */
XX  char *intermediate;		/* name of intermediate file */
XX  {
XX--- 81,90 ----
XX  	process(name, intermediate);
XX  	unlink(intermediate);
XX    }
XX+   return(0);
XX  }
XX  
XX! void indent(s, intermediate)
XX  char *s;			/* name of file to prettyprint */
XX  char *intermediate;		/* name of intermediate file */
XX  {
XX***************
XX*** 91,103 ****
XX    }
XX  }
XX  
XX! process(s, intermediate)
XX  char *s;			/* name of file to prettyprint */
XX  char *intermediate;		/* name of intermediate file */
XX  {
XX  /* File is now indented.  Post process it. */
XX  
XX-   int t, m, tabcol;
XX    FILE *in, *out;
XX    char *p;
XX  
XX--- 114,125 ----
XX    }
XX  }
XX  
XX! void process(s, intermediate)
XX  char *s;			/* name of file to prettyprint */
XX  char *intermediate;		/* name of intermediate file */
XX  {
XX  /* File is now indented.  Post process it. */
XX  
XX    FILE *in, *out;
XX    char *p;
XX  
XX***************
XX*** 168,187 ****
XX  }
XX  
XX  
XX! join()
XX  {
XX    char *p, *q;
XX!   int col, line_length();
XX  
XX    /* Don't join two if statements. */
XX    p = buf2;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "if ", 3) == 0) return(MAX_LINE + 100);
XX  
XX    /* Don't join if the third line is 'else'. */
XX    p = buf3;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "else", 4) == 0) return(MAX_LINE + 100);
XX  
XX    /* Determine how long the joined statements will be. */
XX    q = buf2;
XX--- 190,209 ----
XX  }
XX  
XX  
XX! int join()
XX  {
XX    char *p, *q;
XX!   int col;
XX  
XX    /* Don't join two if statements. */
XX    p = buf2;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "if ", (size_t)3) == 0) return(MAX_LINE + 100);
XX  
XX    /* Don't join if the third line is 'else'. */
XX    p = buf3;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "else", (size_t)4) == 0) return(MAX_LINE + 100);
XX  
XX    /* Determine how long the joined statements will be. */
XX    q = buf2;
XX***************
XX*** 191,197 ****
XX  }
XX  
XX  
XX! shift_left(p)
XX  register char *p;
XX  {
XX  /* Copy a string to the left 1 line_length. */
XX--- 213,219 ----
XX  }
XX  
XX  
XX! void shift_left(p)
XX  register char *p;
XX  {
XX  /* Copy a string to the left 1 line_length. */
XX***************
XX*** 202,208 ****
XX    } while (*p != 0);
XX  }
XX  
XX! shift_right(p)
XX  register char *p;
XX  {
XX  /* Copy a string to the right 1 line_length. */
XX--- 224,230 ----
XX    } while (*p != 0);
XX  }
XX  
XX! void shift_right(p)
XX  register char *p;
XX  {
XX  /* Copy a string to the right 1 line_length. */
XX***************
XX*** 234,240 ****
XX    return(col - 1);
XX  }
XX  
XX! place_comment(buf)
XX  char *buf;
XX  {
XX  /* See if there is a comment that has to be readjusted to get it right. */
XX--- 256,262 ----
XX    return(col - 1);
XX  }
XX  
XX! void place_comment(buf)
XX  char *buf;
XX  {
XX  /* See if there is a comment that has to be readjusted to get it right. */
XX***************
XX*** 311,317 ****
XX  }
XX  
XX  
XX! ifwhilefor(in, out)
XX  FILE *in, *out;
XX  {
XX  /* Check for 'if' or 'while' split over two lines. */
XX--- 333,339 ----
XX  }
XX  
XX  
XX! void ifwhilefor(in, out)
XX  FILE *in, *out;
XX  {
XX  /* Check for 'if' or 'while' split over two lines. */
XX***************
XX*** 326,334 ****
XX    while (first2 > &buf[0] && (*first2 == ' ' || *first2 == '\t')) first2--;
XX  
XX    /* First1 and first2 now point to first/last nonblank chars. */
XX!   is_if = (strncmp(first1, "if ", 3) == 0 ? 1 : 0);
XX!   is_for = (strncmp(first1, "for ", 4) == 0 ? 1 : 0);
XX!   is_while = (strncmp(first1, "while ", 6) == 0 ? 1 : 0);
XX  
XX    if ((is_if || is_for || is_while) && *first2 == ')') {
XX  	/* This is an 'if' or 'while' statement ending with ')'. */
XX--- 348,356 ----
XX    while (first2 > &buf[0] && (*first2 == ' ' || *first2 == '\t')) first2--;
XX  
XX    /* First1 and first2 now point to first/last nonblank chars. */
XX!   is_if = (strncmp(first1, "if ", (size_t)3) == 0 ? 1 : 0);
XX!   is_for = (strncmp(first1, "for ", (size_t)4) == 0 ? 1 : 0);
XX!   is_while = (strncmp(first1, "while ", (size_t)6) == 0 ? 1 : 0);
XX  
XX    if ((is_if || is_for || is_while) && *first2 == ')') {
XX  	/* This is an 'if' or 'while' statement ending with ')'. */
XX***************
XX*** 343,349 ****
XX    }
XX  }
XX  
XX! do_return(b)
XX  char *b;
XX  {
XX  /* Remove the space after return, i.e., return (0) ==> return(0). */
XX--- 365,371 ----
XX    }
XX  }
XX  
XX! void do_return(b)
XX  char *b;
XX  {
XX  /* Remove the space after return, i.e., return (0) ==> return(0). */
XX***************
XX*** 352,363 ****
XX  
XX    p = b;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "return (", 8) != 0) return;
XX    shift_left(p + 6);
XX  }
XX  
XX  
XX! splice_comment(in)
XX  FILE *in;
XX  {
XX  /* Indent has the problem that it sometimes breaks one line comments over two
XX--- 374,385 ----
XX  
XX    p = b;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "return (", (size_t)8) != 0) return;
XX    shift_left(p + 6);
XX  }
XX  
XX  
XX! void splice_comment(in)
XX  FILE *in;
XX  {
XX  /* Indent has the problem that it sometimes breaks one line comments over two
XX***************
XX*** 389,395 ****
XX  }
XX  
XX  
XX! add_blank()
XX  {
XX  /* Add a blank line between closing bracket and comment. */
XX  
XX--- 411,417 ----
XX  }
XX  
XX  
XX! void add_blank()
XX  {
XX  /* Add a blank line between closing bracket and comment. */
XX  
XX***************
XX*** 398,415 ****
XX    skip_whitespace(p);
XX    q = buf2;
XX    skip_whitespace(q);
XX!   if (strcmp(p, "}\n") == 0 && strncmp(q, "/*", 2) == 0) {
XX  	strcat(buf, "\n");
XX    }
XX  }
XX  
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: pretty file ...\n");
XX  }
XX  
XX! do_case(in)
XX  FILE *in;
XX  {
XX  /* Try to get short cases all on 1 line. */
XX--- 420,437 ----
XX    skip_whitespace(p);
XX    q = buf2;
XX    skip_whitespace(q);
XX!   if (strcmp(p, "}\n") == 0 && strncmp(q, "/*", (size_t)2) == 0) {
XX  	strcat(buf, "\n");
XX    }
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: pretty file ...\n");
XX  }
XX  
XX! void do_case(in)
XX  FILE *in;
XX  {
XX  /* Try to get short cases all on 1 line. */
XX***************
XX*** 418,424 ****
XX  
XX    p = buf;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "case ", 5) != 0 && strncmp(p, "default", 7) != 0) return;
XX    shift_right(p);
XX    *p++ = ' ';
XX    shift_right(p);
XX--- 440,446 ----
XX  
XX    p = buf;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "case ", (size_t)5) != 0 && strncmp(p, "default", (size_t)7) != 0) return;
XX    shift_right(p);
XX    *p++ = ' ';
XX    shift_right(p);
XX***************
XX*** 433,439 ****
XX  
XX    r = buf3;
XX    skip_whitespace(r);
XX!   if (strncmp(r, "break;", 6) != 0 && strcmp(r, "}\n") != 0) return;
XX  
XX    /* This is a case statement and the case is only 1 line long (+ break). */
XX    if (line_length(buf) + 3 * TAB + line_length(q) + line_length(r) > MAX_LINE)
XX--- 455,461 ----
XX  
XX    r = buf3;
XX    skip_whitespace(r);
XX!   if (strncmp(r, "break;", (size_t)6) != 0 && strcmp(r, "}\n") != 0) return;
XX  
XX    /* This is a case statement and the case is only 1 line long (+ break). */
XX    if (line_length(buf) + 3 * TAB + line_length(q) + line_length(r) > MAX_LINE)
XX***************
XX*** 444,455 ****
XX    strcat(buf, q);
XX    p = buf + strlen(buf) - 1;
XX    *p = 0;
XX!   if (strncmp(r, "break;", 6) == 0) {
XX  	strcat(buf, "\t");	/* 'break' case */
XX    } else {
XX  	strcat(buf, "\n");	/* 'default' case */
XX    }
XX!   if (strncmp(r, "}", 1) == 0) {
XX  	/* The "}' at the end of the switch has to be fudged. */
XX  	p = buf;
XX  	while (*p++ == '\t') strcat(buf, "\t");
XX--- 466,477 ----
XX    strcat(buf, q);
XX    p = buf + strlen(buf) - 1;
XX    *p = 0;
XX!   if (strncmp(r, "break;", (size_t)6) == 0) {
XX  	strcat(buf, "\t");	/* 'break' case */
XX    } else {
XX  	strcat(buf, "\n");	/* 'default' case */
XX    }
XX!   if (strncmp(r, "}", (size_t)1) == 0) {
XX  	/* The "}' at the end of the switch has to be fudged. */
XX  	p = buf;
XX  	while (*p++ == '\t') strcat(buf, "\t");
XX***************
XX*** 460,466 ****
XX  }
XX  
XX  
XX! capitalize()
XX  {
XX  /* Capitalize the first word of comments that begin a section. */
XX  
XX--- 482,488 ----
XX  }
XX  
XX  
XX! void capitalize()
XX  {
XX  /* Capitalize the first word of comments that begin a section. */
XX  
XX***************
XX*** 469,480 ****
XX    if (loops == 0) return;
XX    p = buf;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "/* ", 3) != 0) return;
XX    q = p + 3;
XX    if (*q >= 'a' && *q <= 'z') *q = *q - 'a' + 'A';
XX  }
XX  
XX! scrunch(in)
XX  FILE *in;
XX  {
XX  /* Move buf3 to buf2 and reload buf3. */
XX--- 491,502 ----
XX    if (loops == 0) return;
XX    p = buf;
XX    skip_whitespace(p);
XX!   if (strncmp(p, "/* ", (size_t)3) != 0) return;
XX    q = p + 3;
XX    if (*q >= 'a' && *q <= 'z') *q = *q - 'a' + 'A';
XX  }
XX  
XX! void scrunch(in)
XX  FILE *in;
XX  {
XX  /* Move buf3 to buf2 and reload buf3. */
XX***************
XX*** 483,489 ****
XX    if (fgets(buf3, BUF_SIZE, in) == NULL) buf3[0] = '\0';
XX  }
XX  
XX! three_liner(in)
XX  FILE *in;
XX  {
XX  /* Handle three line comments that get munged. */
XX--- 505,511 ----
XX    if (fgets(buf3, BUF_SIZE, in) == NULL) buf3[0] = '\0';
XX  }
XX  
XX! void three_liner(in)
XX  FILE *in;
XX  {
XX  /* Handle three line comments that get munged. */
X/
Xecho x - printenv.c.d
Xsed '/^X/s///' > printenv.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/printenv.c  crc=26966    188	Sun Apr 25 21:35:12 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/printenv.c  crc=44677    278	Wed Nov  4 04:19:17 1992
XX***************
XX*** 1,10 ****
XX  /* printenv - print the current environment	Author: Richard Todd */
XX  
XX! main()
XX  {
XX-   extern char **environ;
XX    char **sptr;
XX    for (sptr = environ; *sptr; ++sptr) {
XX! 	prints("%s\n", *sptr);
XX    }
XX  }
XX--- 1,17 ----
XX  /* printenv - print the current environment	Author: Richard Todd */
XX  
XX! #include <sys/types.h>
XX! #include <stdio.h>
XX! 
XX! extern char **environ;
XX! 
XX! _PROTOTYPE(int main, (void));
XX! 
XX! int main()
XX  {
XX    char **sptr;
XX    for (sptr = environ; *sptr; ++sptr) {
XX! 	printf("%s\n", *sptr);
XX    }
XX+   return(0);
XX  }
X/
Xecho x - printroot.c.d
Xsed '/^X/s///' > printroot.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/printroot.c  crc=52023   1951	Sun Apr 25 21:35:12 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/printroot.c  crc=53538   2097	Mon Dec 21 18:55:49 1992
XX***************
XX*** 12,55 ****
XX   *		   - sizeof "foo" is 2 (from wrong type char *) instead of 4
XX   *		   - char foo[10] = "bar"; allocates 4 bytes instead of 10
XX   *  1 October 1989 - Minor changes by Andy Tanenbaum
XX   */
XX  
XX  #include <sys/types.h>
XX- #include <sys/dir.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <stdlib.h>
XX  #include <string.h>
XX  #include <unistd.h>
XX  
XX  static char DEV_PATH[] = "/dev/";	/* #define would step on sizeof bug */
XX! static char MESSAGE[] =	" is root device\n";	/* ditto */
XX  #define UNKNOWN_DEV	"/dev/unknown"
XX  #define ROOT		"/"
XX  
XX! #ifdef __STDC__
XX! static void done(char *name, int status);
XX! #else
XX! static void done();
XX! #endif
XX  
XX  int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   struct direct dir;
XX!   int fd;
XX    struct stat filestat, rootstat;
XX    static char namebuf[sizeof DEV_PATH + NAME_MAX];
XX  
XX!   if (stat(ROOT, &rootstat) == 0 && (fd = open(DEV_PATH, O_RDONLY)) >= 0) {
XX! 	while (read(fd, (char *) &dir, sizeof dir) == sizeof dir) {
XX! 		if (dir.d_ino == 0) continue;
XX  		strcpy(namebuf, DEV_PATH);
XX! 
XX! 		/* If next does not null-terminate, last in buf does it. */
XX! 		strncat(namebuf, dir.d_name, NAME_MAX);
XX  		if (stat(namebuf, &filestat) != 0) continue;
XX  		if ((filestat.st_mode & S_IFMT) != S_IFBLK) continue;
XX  		if (filestat.st_rdev != rootstat.st_dev) continue;
XX--- 12,51 ----
XX   *		   - sizeof "foo" is 2 (from wrong type char *) instead of 4
XX   *		   - char foo[10] = "bar"; allocates 4 bytes instead of 10
XX   *  1 October 1989 - Minor changes by Andy Tanenbaum
XX+  *  5 October 1992 - Use readdir (kjb)
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <stdlib.h>
XX  #include <string.h>
XX  #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <dirent.h>
XX  
XX  static char DEV_PATH[] = "/dev/";	/* #define would step on sizeof bug */
XX! static char MESSAGE[] = " / ";	/* ditto */
XX  #define UNKNOWN_DEV	"/dev/unknown"
XX  #define ROOT		"/"
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void done, (char *name, int status));
XX  
XX  int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX!   DIR *dp;
XX!   struct dirent *entry;
XX    struct stat filestat, rootstat;
XX    static char namebuf[sizeof DEV_PATH + NAME_MAX];
XX  
XX!   if (stat(ROOT, &rootstat) == 0 && (dp = opendir(DEV_PATH)) != (DIR *) NULL) {
XX! 	while ((entry = readdir(dp)) != (struct dirent *) NULL) {
XX  		strcpy(namebuf, DEV_PATH);
XX! 		strcat(namebuf, entry->d_name);
XX  		if (stat(namebuf, &filestat) != 0) continue;
XX  		if ((filestat.st_mode & S_IFMT) != S_IFBLK) continue;
XX  		if (filestat.st_rdev != rootstat.st_dev) continue;
XX***************
XX*** 57,70 ****
XX  	}
XX    }
XX    done(UNKNOWN_DEV, 1);
XX!   return 0;			/* not reached */
XX  }
XX  
XX! static void done(name, status)
XX  char *name;
XX  int status;
XX  {
XX    write(1, name, strlen(name));
XX    write(1, MESSAGE, sizeof MESSAGE - 1);
XX    exit(status);
XX  }
XX--- 53,75 ----
XX  	}
XX    }
XX    done(UNKNOWN_DEV, 1);
XX!   return(0);			/* not reached */
XX  }
XX  
XX! void done(name, status)
XX  char *name;
XX  int status;
XX  {
XX+   int v;
XX+ 
XX+   v = fsversion(name, "printroot");	/* determine file system version */
XX    write(1, name, strlen(name));
XX    write(1, MESSAGE, sizeof MESSAGE - 1);
XX+   if (v == 1)
XX+ 	write(1, "1 rw\n", 5);
XX+   else if (v == 2)
XX+ 	write(1, "2 rw\n", 5);
XX+   else
XX+ 	write(1, "0 rw\n", 5);
XX    exit(status);
XX  }
X/
Xecho x - ps.c.d
Xsed '/^X/s///' > ps.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ps.c  crc=04124  19024	Sun Apr 25 21:35:13 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ps.c  crc=30672  25223	Fri Mar 12 19:24:36 1993
XX***************
XX*** 1,627 ****
XX! /* ps - print status			Author: Peter Valkenburg */
XX  
XX! /* ps.c, Peter Valkenburg (valke@psy.vu.nl), january 1990.
XX   *
XX!  * This is a V7 ps(1) look-alike for MINIX 1.5.0.  It can use a database with
XX!  * information on system addresses as an extra, and has some additional fields.
XX   * It does not support the 'k' option (i.e. cannot read memory from core file).
XX   * If you want to compile this for non-IBM PC architectures, the header files
XX   * require that you have your CHIP, MACHINE etc. defined.
XX   *
XX   * VERY IMPORTANT NOTE:
XX!  *	To use ps, kernel/kernel, fs/fs, and mm/mm must be in the /usr/src
XX!  *	(or the #includes below must be changed).  Furthermore, all of
XX!  *	must contain symbol tables.  This can be arranged using the -s flag
XX!  *	and the ast program.  For example in fs, one would have
XX   *
XX   *	asld -s -i -o fs $l/head.s $(obj) $l/libc.a $l/end.s >symbol.out
XX   *	ast -X fs		# include symbol.out in fs
XX   *
XX   */
XX  
XX! /*
XX   * Most fields are similar to V7 ps(1), except for CPU, NICE, PRI which are
XX!  * absent, RECV which replaces WCHAN, and RUID and PGRP that are extras.
XX   * The info is obtained from the following fields of proc, mproc and fproc:
XX   * F	- kernel status field, p_flags
XX   * S	- kernel status field, p_flags; mm status field, mp_flags (R if p_flags
XX   * 	  is 0; Z if mp_flags == HANGING; T if mp_flags == STOPPED; else W).
XX   * UID	- mm eff uid field, mp_effuid
XX-  * RUID	- mm real uid field, mp_realuid
XX   * PID	- mm pid field, mp_pid
XX   * PPID	- mm parent process index field, mp_parent (used as index in proc).
XX!  * PGRP - mm process group id mp_procgrp
XX   * ADDR	- kernel physical text address, p_map[T].mem_phys
XX!  * SZ	- kernel physical stack address + stack size - physical text address,
XX!  * 	  p_map[S].mem_phys + p_map[S].mem_len - p_map[T].mem_phys
XX   * RECV	- kernel process index field for message receiving, p_getfrom
XX   *	  If sleeping, mm's mp_flags, or fs's fp_task are used for more info.
XX   * TTY	- fs controlling tty device field, fs_tty.
XX   * TIME	- kernel user + system times fields, user_time + sys_time
XX   * CMD	- system process index (converted to mnemonic name obtained by reading
XX   *	  tasktab array from kmem), or user process argument list (obtained by
XX!  *	  reading reading stack frame; the resulting address is used to get
XX   *	  the argument vector from user space and converted into a concatenated
XX   *	  argument list).
XX!  */  	  
XX!  
XX  #include <minix/config.h>
XX  #include <limits.h>
XX  #include <sys/types.h>
XX  
XX  #include <minix/const.h>
XX! #undef EXTERN				/* <minix/const.h> defined this */
XX! #define EXTERN				/* so we get proc, mproc and fproc */
XX  #include <minix/type.h>
XX  
XX! #include "../kernel/const.h"
XX! #include "../kernel/type.h"
XX! #include "../kernel/proc.h"
XX! #undef printf				/* kernel's const.h defined this */
XX  
XX! #include "../mm/mproc.h"
XX! #include "../fs/fproc.h"
XX! #include "../fs/const.h"
XX! #undef printf				/* fs's const.h defined this */
XX  
XX  
XX  /*----- ps's local stuff below this line ------*/
XX  
XX- #include <minix/com.h>
XX- #include <fcntl.h>
XX- #include <a.out.h>
XX- #include <stdio.h>
XX  
XX  #define mindev(dev)	(((dev)>>MINOR) & 0377)	/* yield minor device */
XX  #define majdev(dev)	(((dev)>>MAJOR) & 0377)	/* yield major device */
XX  
XX! #define	TTY_MAJ		4			/* fixed tty major device */
XX  
XX! /* macro to convert memory offsets to rounded kilo-units */
XX  #define	off_to_k(off)	((unsigned) (((off) + 512) / 1024))
XX  
XX! /* what we think the relevant identifiers in the namelists are */
XX! #define	ID_PROC		"_proc"		/* from kernel namelist */
XX! #define	ID_MPROC	"_mproc"	/* from mm namelist */
XX! #define	ID_FPROC	"_fproc"	/* from fs namelist */
XX  #define	ID_TASKTAB	"_tasktab"	/* from kernel namelist */
XX  
XX! /*
XX!  * Structure for system address info (also layout of ps's database).
XX!  */
XX  typedef struct {
XX! 	struct nlist ke_proc[2], ke_tasktab[2];
XX! 	struct nlist mm_mproc[2];
XX! 	struct nlist fs_fproc[2];
XX  } sysinfo_t;
XX  
XX! sysinfo_t sysinfo;			/* sysinfo holds actual system info */
XX  
XX  #define	NAME_SIZ	(sizeof(sysinfo.ke_proc[0].n_name))	/* 8 chars */
XX  
XX! /* what we think the identfiers of the imported variables in this program are */
XX  #define	PROC	proc
XX  #define	MPROC	mproc
XX  #define	FPROC	fproc
XX  #define	TASKTAB	tasktab
XX  
XX! /* default paths for system binaries */
XX! #if (CHIP == M68000)
XX! #define KERNEL_PATH	"/usr/src/kernel/kernel.mix"
XX! #define MM_PATH		"/usr/src/mm/mm.mix"
XX! #define FS_PATH		"/usr/src/fs/fs.mix"
XX! #else
XX  #define KERNEL_PATH	"/usr/src/kernel/kernel"
XX  #define MM_PATH		"/usr/src/mm/mm"
XX  #define FS_PATH		"/usr/src/fs/fs"
XX- # endif
XX  
XX  #define	KMEM_PATH	"/dev/kmem"	/* opened for kernel proc table */
XX  #define	MEM_PATH	"/dev/mem"	/* opened for mm/fs + user processes */
XX  
XX! int kmemfd, memfd;			/* file descriptors of [k]mem */
XX  
XX  #define DBASE_PATH	"/etc/psdatabase"	/* path of ps's database */
XX! #define DBASE_MODE	0644			/* mode for ps's database */
XX  
XX- /* paths for system binaries (not relevant if database is used) */
XX- char *kpath = KERNEL_PATH;
XX- char *mpath = MM_PATH;
XX- char *fpath = FS_PATH;
XX- 
XX  struct tasktab tasktab[NR_TASKS + INIT_PROC_NR + 1];	/* task table */
XX  
XX! /*
XX!  * Short and long listing formats:
XX   *
XX   *   PID TTY  TIME CMD
XX!  * ppppp  ttmmm:ss ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
XX!  * 
XX!  *   F S UID   PID  PPID  PGRP ADDR  SZ        RECV TTY  TIME CMD
XX!  * fff s uuu ppppp ppppp ppppp aaaa sss rrrrrrrrrrr  ttmmm:ss cccccccccccccccccccc
XX!  * (RAMDSK) FS
XX!  * or
XX!  * (PAUSE) MM
XX   */
XX  #define S_HEADER "  PID TTY  TIME CMD\n"
XX! #define S_FORMAT "%5d  %3s%3ld:%02ld %.62s\n"
XX! #define L_HEADER "  F S UID   PID  PPID  PGRP ADDR  SZ        RECV TTY  TIME CMD\n"
XX! #define L_FORMAT "%3o %c %3d %5d %5d %5d %4d %3d %11s  %3s%3ld:%02ld %.19s\n"
XX  
XX! struct pstat {				/* structure filled by pstat() */
XX! 	dev_t ps_dev;			/* major/minor of controlling tty */
XX! 	uid_t ps_ruid;			/* real uid */
XX! 	uid_t ps_euid;			/* effective uid */
XX! 	pid_t ps_pid;			/* process id */
XX! 	pid_t ps_ppid;			/* parent process id */
XX! 	int ps_pgrp;			/* parent process id */
XX! 	int ps_flags;			/* kernel flags */
XX! 	int ps_mflags;			/* mm flags */
XX! 	int ps_ftask;			/* (possibly pseudo) fs suspend task */
XX! 	char ps_state;			/* process state */
XX! 	size_t ps_tsize;		/* text size (in bytes) */
XX! 	size_t ps_dsize;		/* data size (in bytes) */
XX! 	size_t ps_ssize;		/* stack size (in bytes) */
XX! 	off_t ps_text;			/* physical text offset */
XX! 	off_t ps_data;			/* physical data offset */
XX! 	off_t ps_stack;			/* physical stack offset */
XX! 	int ps_recv;			/* process number to receive from */
XX! 	time_t ps_utime;		/* accumulated user time */
XX! 	time_t ps_stime;		/* accumulated system time */
XX! 	char *ps_args;			/* concatenated argument string */
XX  };
XX  
XX! /* ps_state field values in pstat struct above */
XX! #define	Z_STATE		'Z'		/* Zombie */
XX! #define	W_STATE		'W'		/* Waiting */
XX! #define	S_STATE		'S'		/* Sleeping */
XX! #define	R_STATE		'R'		/* Runnable */
XX! #define	T_STATE		'T'		/* stopped (Trace) */
XX  
XX  /*
XX!  * Tname returns mnemonic string for dev_nr.  This is "?" for unknown maj/min
XX!  * pairs.  It is utterly rigid in this implementation...
XX   */
XX  char *tname(dev_nr)
XX  {
XX! 	static char buf[4];
XX! 	
XX! 	if (majdev(dev_nr) != TTY_MAJ ||	/* yuchhh! */
XX! 	    mindev(dev_nr) < 0 || mindev(dev_nr) >= 100)
XX! 		return "?  ";
XX! 	if (mindev(dev_nr) == 0)
XX! 		return "co ";
XX  
XX! 	sprintf(buf, "t%-2d", mindev(dev_nr));
XX! 	return buf;
XX  }
XX  
XX! /* return canonical task name of task p_nr; overwritten on each call */
XX  char *taskname(p_nr)
XX  {
XX! 	char *cp;
XX! 	
XX! 	if (p_nr < -NR_TASKS || p_nr > INIT_PROC_NR)
XX! 		return "?";
XX! 	
XX! 	/* strip trailing blanks for right-adjusted output */
XX! 	for (cp = tasktab[p_nr + NR_TASKS].name; *cp != '\0'; cp++)
XX! 		if (*cp == ' ')
XX! 			break;
XX! 	*cp = '\0';		
XX! 	
XX! 	return tasktab[p_nr + NR_TASKS].name;
XX  }
XX  
XX! /*
XX!  * Prrecv prints the RECV field for process with pstat buffer pointer bufp.
XX   * This is either "ANY", "taskname", or "(blockreason) taskname".
XX   */
XX  char *prrecv(bufp)
XX  struct pstat *bufp;
XX  {
XX! 	char *blkstr, *task;		/* reason for blocking and task */
XX! 	static char recvstr[20];
XX  
XX! 	if (bufp->ps_recv == ANY)
XX! 		return "ANY";
XX  
XX! 	task = taskname(bufp->ps_recv);
XX! 	if (bufp->ps_state != S_STATE)
XX! 		return task;
XX! 	
XX! 	blkstr = "?";
XX! 	if (bufp->ps_recv == MM_PROC_NR) {
XX! 		if (bufp->ps_mflags & PAUSED)
XX! 			blkstr = "pause";
XX! 		else if (bufp->ps_mflags & WAITING)
XX! 			blkstr = "wait";
XX! 	}
XX! 	else if (bufp->ps_recv == FS_PROC_NR) {
XX! 		if (-bufp->ps_ftask == XOPEN)
XX! 			blkstr = "xopen";
XX! 		else if (-bufp->ps_ftask == XPIPE)
XX! 			blkstr = "xpipe";
XX! 		else
XX! 			blkstr = taskname(-bufp->ps_ftask);	
XX! 	}
XX! 	
XX! 	(void) sprintf(recvstr, "(%s) %s", blkstr, task);
XX! 	return recvstr;
XX  }
XX  
XX! /*
XX!  * Main interprets arguments, gets system addresses, opens [k]mem, reads in
XX   * process tables from kernel/mm/fs and calls pstat() for relevant entries.
XX   */
XX! main(argc, argv)
XX  char *argv[];
XX  {
XX! 	int i;
XX! 	struct pstat buf;
XX! 	int db_fd;
XX! 	int uid = getuid();		/* real uid of caller */
XX! 	int opt_all = FALSE;		/* -a */
XX! 	int opt_long = FALSE;		/* -l */
XX! 	int opt_notty = FALSE;		/* -x */
XX! 	int opt_update = FALSE;		/* -U */
XX  
XX! 	/* parse arguments; a '-' need not be present (V7/BSD compatability) */
XX! 	switch (argc) {
XX! 	case 1:		/* plain ps */
XX! 		break;
XX! 	case 2:		/* ps <[-][alxU]> */
XX! 	case 5:		/* ps <[-][alxU]> <kernel mm fs> */
XX! 		for (i = (argv[1][0] == '-' ? 1 : 0); argv[1][i] != '\0'; i++)
XX! 			switch (argv[1][i]) {
XX! 			case 'a':
XX! 				opt_all = TRUE;
XX! 				break;
XX! 			case 'l':
XX! 				opt_long = TRUE;
XX! 				break;
XX! 			case 'x':
XX! 				opt_notty = TRUE;
XX! 				break;
XX! 			case 'U':
XX! 				opt_update = TRUE;
XX! 				break;
XX! 			default:
XX! 				usage(argv[0]);
XX! 			}	
XX! 		break;
XX! 	case 4:		/* ps <kernel mm fs> */
XX! 		if (argv[1][0] != '-')
XX! 			break;
XX! 	default:
XX! 		usage(argv[0]);
XX! 	}
XX! 	
XX! 	if (argc >= 4) {	/* ps [-][alxU] <kernel mm fs> */
XX! 		kpath = argv[argc - 3];
XX! 		mpath = argv[argc - 2];
XX! 		fpath = argv[argc - 1];
XX! 	}
XX! 	
XX! 	/* fill the sysinfo struct with system address information */
XX! 	if (opt_update || (db_fd = open(DBASE_PATH, O_RDONLY)) == -1) {
XX! 		strncpy(sysinfo.ke_proc[0].n_name, ID_PROC, NAME_SIZ);
XX! 		strncpy(sysinfo.ke_tasktab[0].n_name, ID_TASKTAB, NAME_SIZ);
XX! 		if (nlist(kpath, sysinfo.ke_proc) != 0 ||
XX! 		    nlist(kpath, sysinfo.ke_tasktab) != 0)
XX! 			err("Can't read kernel namelist");
XX! 		strncpy(sysinfo.mm_mproc[0].n_name, ID_MPROC, NAME_SIZ);
XX! 		if (nlist(mpath, sysinfo.mm_mproc) != 0)
XX! 			err("Can't read mm namelist");
XX! 		strncpy(sysinfo.fs_fproc[0].n_name, ID_FPROC, NAME_SIZ);
XX! 		if (nlist(fpath, sysinfo.fs_fproc) != 0)
XX! 			err("Can't read fs namelist");
XX! 		if (opt_update) {
XX! 			if ((db_fd = creat(DBASE_PATH, DBASE_MODE)) == -1)
XX! 				err("Can't creat psdatabase");
XX! 			if (write(db_fd, (char *) &sysinfo,
XX! 				  sizeof(sysinfo_t)) != sizeof(sysinfo_t))
XX! 				err("Can't write psdatabase");
XX! 		}		
XX! 	}
XX! 	else {
XX  		if (read(db_fd, (char *) &sysinfo,
XX! 			 sizeof(sysinfo_t)) != sizeof(sysinfo_t))
XX! 			err("Can't read psdatabase");	 
XX  	}
XX! 	(void) close (db_fd);
XX! 	    	
XX! 	/* get kernel tables */    	
XX! 	if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1)
XX! 		err(KMEM_PATH);
XX! 	if (addrread(kmemfd, (phys_clicks) 0,
XX! 		     (vir_bytes) sysinfo.ke_proc[0].n_value,
XX! 		     (char *) PROC, sizeof(PROC)) != sizeof(PROC))
XX! 		err("Can't get kernel proc table from /dev/kmem");
XX! 	if (addrread(kmemfd, (phys_clicks) 0,
XX! 		     (vir_bytes) sysinfo.ke_tasktab[0].n_value,
XX! 		     (char *) TASKTAB, sizeof(TASKTAB)) != sizeof(TASKTAB))
XX! 		err("Can't get kernel task table from /dev/kmem");
XX  
XX! 	/* get mm/fs tables */
XX! 	if ((memfd = open(MEM_PATH, O_RDONLY)) == -1)
XX! 		err(MEM_PATH);
XX! 	if (addrread(memfd, PROC[NR_TASKS + MM_PROC_NR].p_map[D].mem_phys,
XX! 		     (vir_bytes) sysinfo.mm_mproc[0].n_value,
XX! 		     (char *) MPROC, sizeof(MPROC)) != sizeof(MPROC))
XX! 		err("Can't get mm proc table from /dev/mem");
XX! 	if (addrread(memfd, PROC[NR_TASKS + FS_PROC_NR].p_map[D].mem_phys,
XX! 		     (vir_bytes) sysinfo.fs_fproc[0].n_value,
XX! 		     (char *) FPROC, sizeof(FPROC)) != sizeof(FPROC))
XX! 		err("Can't get fs proc table from /dev/mem");
XX! 		
XX! 	/* now loop through process table and handle each entry */
XX! 	printf("%s", opt_long ? L_HEADER : S_HEADER);
XX! 	for (i = -NR_TASKS; i < NR_PROCS; i++) {
XX! 		if (pstat(i, &buf) != -1 &&
XX! 		    (opt_all || buf.ps_euid == uid || buf.ps_ruid == uid) &&
XX! 		    (opt_notty || majdev(buf.ps_dev) == TTY_MAJ))
XX! 			if (opt_long)
XX! 				printf(L_FORMAT,
XX! 				       buf.ps_flags, buf.ps_state,
XX! 				       buf.ps_euid, buf.ps_pid, buf.ps_ppid,
XX! 				       buf.ps_pgrp,
XX! 				       off_to_k(buf.ps_text),
XX! 				       off_to_k((buf.ps_stack + buf.ps_ssize
XX! 				       			- buf.ps_text)),
XX! 				       (buf.ps_flags & RECEIVING ?
XX! 						prrecv(&buf) :
XX! 				       		""),
XX! 				       tname(buf.ps_dev),
XX! 				       (buf.ps_utime + buf.ps_stime) / HZ / 60,
XX! 				       (buf.ps_utime + buf.ps_stime) / HZ % 60,
XX! 				       i <= INIT_PROC_NR ? taskname(i) :
XX! 						(buf.ps_args == NULL ? "" :
XX! 					   		buf.ps_args));
XX! 			else
XX! 				printf(S_FORMAT,
XX! 				       buf.ps_pid, tname(buf.ps_dev),
XX! 				       (buf.ps_utime + buf.ps_stime) / HZ / 60,
XX! 				       (buf.ps_utime + buf.ps_stime) / HZ % 60,
XX! 				       i <= INIT_PROC_NR ? taskname(i) :
XX! 						(buf.ps_args == NULL ? "" :
XX! 					   		buf.ps_args));
XX  	}
XX  }
XX  
XX! /*
XX!  * Get_args inspects /dev/mem, using bufp, and tries to locate the initial
XX!  * stack frame pointer, i.e. the place where the stack started at exec time.
XX!  * It is assumed that the end of the stack frame looks as follows:
XX!  *	argc	<-- initial stack frame starts here
XX!  *	argv[0]
XX!  *	...
XX!  *	NULL	(*)
XX!  *	envp[0]
XX!  *	...
XX!  *	NULL	(**)
XX!  *	argv[0][0] ... '\0'
XX!  *	...
XX!  *	argv[argc - 1][0] ... '\0'
XX!  *	envp[0][0] ... '\0'
XX!  *	...
XX!  *	[trailing '\0']
XX!  * Where the total space occupied by this original stack frame <= ARG_MAX.
XX!  * Get_args reads in the last ARG_MAX bytes of the process' data, and
XX!  * searches back for two NULL ptrs (hopefully the (*) & (**) above).
XX!  * If it finds such a portion, it continues backwards, counting ptrs until:
XX!  * a) either a word is found that has as its value the count (supposedly argc),
XX!  * b) another NULL word is found, in which case the algorithm is reiterated, or
XX!  * c) we wind up before the start of the buffer and fail.
XX!  * Upon success, get_args returns a pointer to the conactenated arg list.
XX!  * Warning: this routine is inherently unreliable and probably doesn't work if
XX!  * ptrs and ints have different sizes.
XX!  */
XX! char *get_args(bufp)
XX! struct pstat *bufp;
XX! {
XX! 	union {
XX  #if (CHIP == M68000)
XX! 		long stk_i;
XX  #else
XX! 		int stk_i;
XX  #endif
XX! 		char *stk_cp;
XX! 		char stk_c;
XX! 	} stk[ARG_MAX / sizeof(char *)], *sp;
XX! 	enum {INITIAL, DONE, FAIL, NULL1, NULL2} state;
XX! 	int nargv;		/* guessed # of (non-NULL) argv pointers seen */
XX! 	int cnt;		/* # of bytes read from stack frame */
XX! 	int neos;		/* # of '\0's seen in argv string space */
XX! 	off_t l;
XX! 	char *cp, *args;
XX! 	
XX! 	
XX! 	if (bufp->ps_ssize < ARG_MAX)
XX! 		cnt = bufp->ps_ssize;
XX! 	else
XX! 		cnt = ARG_MAX;
XX! 	/* get last cnt bytes from user stack */
XX! 	if (addrread(memfd, (phys_clicks) (bufp->ps_stack >> CLICK_SHIFT),
XX! 		     (vir_bytes) (bufp->ps_ssize - cnt),
XX! 		     (char *) stk, cnt) != cnt)
XX! 		return NULL;
XX! 	
XX! 	state = INITIAL;
XX! 	sp = &stk[cnt / sizeof(char *)];
XX! 	while (state != DONE && state != FAIL) {
XX! 		if (--sp < &stk[0])
XX! 			state = FAIL;	/* wound up before start of buffer */
XX! 		switch(state) {
XX! 		case INITIAL:	/* no NULL seen yet */
XX! 			if (sp[0].stk_cp == NULL)
XX! 				state = NULL1;
XX  			break;
XX! 		case NULL1:	/* one NULL seen */	
XX! 			if (sp[0].stk_cp == NULL) {
XX! 				nargv = 0;	/* start counting argv ptrs */
XX! 				state = NULL2;
XX! 			}	
XX! 			/*
XX! 			 * What follows is a dirty patch to recognize sh's 
XX! 			 * stack frame when it has assigned argv[0] to argv[1],
XX! 			 * and has thus blown away its NULL pointer there.
XX! 			 */
XX! 			else if (sp > &stk[0] && sp[0].stk_cp == sp[-1].stk_cp){
XX! 				nargv = 0;
XX! 				state = NULL2;
XX! 			}
XX! 			break;
XX! 		case NULL2:	/* two NULLs seen */
XX! 			if (sp[0].stk_cp == NULL)
XX! 				nargv = 0;	/* restart counting */
XX! 			else if (sp[0].stk_i == nargv)
XX! 				state = DONE;	/* think i got it */
XX! 			/* next is same ugly patch as above */	
XX! 			else if (sp > &stk[0] && sp[0].stk_cp == sp[-1].stk_cp)
XX! 				nargv = 0;
XX! 			else
XX! 				nargv++;	/* ? some argv pointer ? */
XX! 			break;
XX! 		default:	/* FAIL or DONE */
XX! 			break;
XX! 		}	
XX! 	}
XX! 	
XX! 	if (state != DONE)
XX! 		return NULL;
XX  
XX! 	/* get a local version of argv[0]; l is offset back from end of stack */
XX! 	l = bufp->ps_stack + bufp->ps_ssize -
XX! #if (CHIP == INTEL)
XX! 		bufp->ps_data - 
XX! #endif
XX! 		(vir_bytes) sp[1].stk_cp;
XX! 	if (l < 0 || l > cnt)
XX! 		return NULL;
XX! 	args = &((char *) stk)[cnt - (int) l];
XX! 	neos = 0;
XX! 	for (cp = args; cp < &((char *) stk)[cnt]; cp++)
XX! 		if (*cp == '\0')
XX! 			if (++neos >= sp[0].stk_i)
XX! 				break;
XX! 			else
XX! 				*cp = ' ';	
XX! 	if (neos != sp[0].stk_i)
XX! 		return NULL;			
XX  
XX- 	return args;
XX  }
XX  
XX! /*
XX!  * Pstat collects info on process number p_nr and returns it in buf.
XX   * It is assumed that tasks do not have entries in fproc/mproc.
XX   */
XX  int pstat(p_nr, bufp)
XX  struct pstat *bufp;
XX  {
XX! 	int p_ki = p_nr + NR_TASKS;	/* kernel proc index */
XX! 	
XX! 	if (p_nr < -NR_TASKS || p_nr >= NR_PROCS)
XX! 		return -1;
XX! 	
XX! 	if ((PROC[p_ki].p_flags & P_SLOT_FREE) &&
XX! 	    !(MPROC[p_nr].mp_flags & IN_USE))
XX! 		return -1;
XX  
XX! 	bufp->ps_flags = PROC[p_ki].p_flags;
XX! 	
XX! 	if (p_nr >= 0) {
XX! 		bufp->ps_dev = FPROC[p_nr].fs_tty;
XX! 		bufp->ps_ftask = FPROC[p_nr].fp_task;
XX! 	}	
XX! 	else {
XX! 		bufp->ps_dev = 0;
XX! 		bufp->ps_ftask = 0;
XX! 	}
XX  
XX! 	if (p_nr >= 0) {
XX! 		bufp->ps_ruid = MPROC[p_nr].mp_realuid;	
XX! 		bufp->ps_euid = MPROC[p_nr].mp_effuid;	
XX! 		bufp->ps_pid = MPROC[p_nr].mp_pid;
XX! 		bufp->ps_ppid = MPROC[MPROC[p_nr].mp_parent].mp_pid;
XX! 		bufp->ps_pgrp = MPROC[p_nr].mp_procgrp;
XX! 		bufp->ps_mflags = MPROC[p_nr].mp_flags;
XX! 	}
XX! 	else {
XX! 		bufp->ps_pid = bufp->ps_ppid = 0;
XX! 		bufp->ps_ruid = bufp->ps_euid = 0;
XX! 		bufp->ps_pgrp = 0;
XX! 		bufp->ps_mflags = 0;
XX! 	}	
XX! 	
XX! 	/* state is interpretation of combined kernel/mm flags for non-tasks */
XX! 	if (p_nr >= 0) {				/* non-tasks */
XX! 		if (MPROC[p_nr].mp_flags & HANGING)
XX! 			bufp->ps_state = Z_STATE;	/* zombie */
XX! 		else if (MPROC[p_nr].mp_flags & STOPPED)
XX! 			bufp->ps_state = T_STATE;	/* stopped (traced) */
XX! 		else if (PROC[p_ki].p_flags == 0)
XX! 			bufp->ps_state = R_STATE;	/* in run-queue */
XX! 		else if (MPROC[p_nr].mp_flags & (WAITING | PAUSED) ||
XX! 			 FPROC[p_nr].fp_suspended == SUSPENDED)
XX! 			bufp->ps_state = S_STATE;	/* sleeping */
XX! 		else	
XX! 			bufp->ps_state = W_STATE;	/* a short wait */
XX! 	}
XX! 	else {						/* tasks are simple */
XX! 		if (PROC[p_ki].p_flags == 0)
XX! 			bufp->ps_state = R_STATE;	/* in run-queue */
XX! 		else
XX! 			bufp->ps_state = W_STATE;	/* other i.e. waiting */
XX! 	}		
XX! 		
XX! 	bufp->ps_tsize = (size_t) PROC[p_ki].p_map[T].mem_len << CLICK_SHIFT;
XX! 	bufp->ps_dsize = (size_t) PROC[p_ki].p_map[D].mem_len << CLICK_SHIFT;
XX! 	bufp->ps_ssize = (size_t) PROC[p_ki].p_map[S].mem_len << CLICK_SHIFT;
XX! 	bufp->ps_text = (off_t) PROC[p_ki].p_map[T].mem_phys << CLICK_SHIFT;
XX! 	bufp->ps_data = (off_t) PROC[p_ki].p_map[D].mem_phys << CLICK_SHIFT;
XX! 	bufp->ps_stack = (off_t) PROC[p_ki].p_map[S].mem_phys << CLICK_SHIFT;
XX! 	
XX! 	bufp->ps_recv = PROC[p_ki].p_getfrom;
XX! 	
XX! 	bufp->ps_utime = PROC[p_ki].user_time;
XX! 	bufp->ps_stime = PROC[p_ki].sys_time;
XX! 	
XX! 	if (bufp->ps_state == Z_STATE)
XX! 		bufp->ps_args = "<defunct>";
XX! 	else if (p_nr > INIT_PROC_NR)
XX! 		bufp->ps_args = get_args(bufp);
XX! 	
XX! 	return 0;
XX  }
XX  
XX! /*
XX!  * Addrread reads nbytes from offset addr to click base of fd into buf.
XX!  */
XX  int addrread(fd, base, addr, buf, nbytes)
XX  phys_clicks base;
XX  vir_bytes addr;
XX  char *buf;
XX  {
XX! 	extern long lseek();
XX!     
XX! 	if (lseek(fd, ((long) base << CLICK_SHIFT) + (long) addr, 0) < 0)
XX! 		return -1;
XX  
XX! 	return read(fd, buf, nbytes);
XX  }
XX  
XX! usage(pname)
XX  char *pname;
XX  {
XX! 	fprintf(stderr, "Usage: %s [-][alxU] [kernel mm fs]\n", pname);
XX! 	exit(1);
XX  }
XX  
XX! err(s)
XX  char *s;
XX  {
XX  	perror(s);
XX! 	exit(2);
XX! }	
XX--- 1,750 ----
XX! /* ps - print status 			Author: Peter Valkenburg */
XX  
XX! /* Ps.c, Peter Valkenburg (valke@psy.vu.nl), january 1990.
XX   *
XX!  * This is a V7 ps(1) look-alike for MINIX >= 1.5.0.  It can use a database
XX!  * with information on system addresses and terminal names as an extra, and
XX!  * has some additional fields.
XX   * It does not support the 'k' option (i.e. cannot read memory from core file).
XX   * If you want to compile this for non-IBM PC architectures, the header files
XX   * require that you have your CHIP, MACHINE etc. defined.
XX+  * Full syntax:
XX+  *	ps [-][alxU] [kernel mm fs]
XX+  * Option `a' gives all processes, `l' for detailed info, `x' includes even
XX+  * processes without a terminal, `U' updates /etc/psdatabase where ps keeps
XX+  * system information and terminal names.  Additional arguments are the paths
XX+  * of system binaries from which system addresses are taken.
XX+  * The database update with the `U' option uses paths kept in the old
XX+  * /etc/psdatabase, unless the additional kernel/mm/fs arguments were given.
XX+  * It defaults to /usr/src/{kernel/kernel,mm/mm,fs/fs} if the latter is not
XX+  * the case and psdatabase is non-existent.  Ps warns if the database appears
XX+  * older than the system executables.
XX   *
XX   * VERY IMPORTANT NOTE:
XX!  *	To compile ps, the kernel/, fs/ and mm/ source directories must be in
XX!  *	../ relative to the directory where ps is compiled (normally the
XX!  *	command source directory).
XX!  *	To run ps the kernel, mm and fs executables must contain symbol tables.
XX!  *	This can be arranged using the -s flag and the ast program.  For
XX!  *	example in fs, one would have
XX   *
XX   *	asld -s -i -o fs $l/head.s $(obj) $l/libc.a $l/end.s >symbol.out
XX   *	ast -X fs		# include symbol.out in fs
XX   *
XX+  *	Ps does *NOT* need the boot image to contain symbol tables.  Nor does
XX+  *	it need kernel, fs or mm binaries after a `ps -U'.  The paths of these
XX+  *	executables can be changed by passing them in the command line, e.g.,
XX+  *	a "ps /kernel /mm /fs" runs ps with namelists extracted from the
XX+  *	system executables found in /.  This also works for `-U'.
XX+  *	If you want your ps to be useable by anyone, yet disallow modification
XX+  *	of the database by anyone other than root and bin, you can arrange the
XX+  *	following access permissions (note the protected memory files and set
XX+  *	*group* id on ps):
XX+  *	-rwxr-sr-x  1 bin         11916 Jul  4 15:31 /bin/ps
XX+  *	-rw-r--r--  1 bin           848 Jul  4 15:39 /etc/psdatabase
XX+  *	crw-r-----  1 bin        1,   1 Jan  1  1970 /dev/mem
XX+  *	crw-r-----  1 bin        1,   2 Jan  1  1970 /dev/kmem
XX+  *
XX+  *	Finally, this is what you have to do if you have amoeba in your kernel:
XX+  *	  1) compile ps including -DAM_KERNEL as an argument to cc and
XX+  *	  2) pass the amoeba kernel, mm and fs binaries to a ps U, as in:
XX+  *		ps -U /amoeba/kernel/kernel /amoeba/mm/mm /amoeba/fs/fs
XX   */
XX  
XX! /* Some technical comments on this implementation:
XX!  *
XX   * Most fields are similar to V7 ps(1), except for CPU, NICE, PRI which are
XX!  * absent, RECV which replaces WCHAN, and PGRP that is an extra.
XX   * The info is obtained from the following fields of proc, mproc and fproc:
XX   * F	- kernel status field, p_flags
XX   * S	- kernel status field, p_flags; mm status field, mp_flags (R if p_flags
XX   * 	  is 0; Z if mp_flags == HANGING; T if mp_flags == STOPPED; else W).
XX   * UID	- mm eff uid field, mp_effuid
XX   * PID	- mm pid field, mp_pid
XX   * PPID	- mm parent process index field, mp_parent (used as index in proc).
XX!  * PGRP - mm process group field, mp_procgrp
XX   * ADDR	- kernel physical text address, p_map[T].mem_phys
XX!  * SZ	- kernel text size + physical stack address - physical data address
XX!  *			   + stack size
XX!  * 	  p_map[T].mem_len + p_map[S].mem_phys - p_map[D].mem_phys
XX!  * 	  		   + p_map[S].mem_len
XX   * RECV	- kernel process index field for message receiving, p_getfrom
XX   *	  If sleeping, mm's mp_flags, or fs's fp_task are used for more info.
XX   * TTY	- fs controlling tty device field, fs_tty.
XX   * TIME	- kernel user + system times fields, user_time + sys_time
XX   * CMD	- system process index (converted to mnemonic name obtained by reading
XX   *	  tasktab array from kmem), or user process argument list (obtained by
XX!  *	  reading the stack frame; the resulting address is used to get
XX   *	  the argument vector from user space and converted into a concatenated
XX   *	  argument list).
XX!  */
XX! 
XX!  /* #define NO_CLICKS  *//* new kernel doesn't use clicks */
XX! 
XX  #include <minix/config.h>
XX  #include <limits.h>
XX  #include <sys/types.h>
XX  
XX  #include <minix/const.h>
XX! #undef EXTERN			/* <minix/const.h> defined this */
XX! #define EXTERN			/* so we get proc, mproc and fproc */
XX  #include <minix/type.h>
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  
XX! #include <minix/com.h>
XX! #include <fcntl.h>
XX! #include <a.out.h>
XX! #include <dirent.h>
XX! #include <sys/stat.h>
XX! #include <signal.h>
XX! #include <stdio.h>
XX  
XX! #include "../../kernel/const.h"
XX! #include "../../kernel/type.h"
XX! #include "../../kernel/proc.h"
XX! #undef printf			/* kernel's const.h defined this */
XX  
XX+ #include "../../mm/mproc.h"
XX+ #include "../../fs/fproc.h"
XX+ #include "../../fs/const.h"
XX+ #undef printf			/* fs's const.h defined this */
XX  
XX+ #ifdef NO_CLICKS
XX+ #undef CLICK_SHIFT
XX+ #define CLICK_SHIFT 0
XX+ #define phys_clicks phys_bytes
XX+ 
XX+ /* Fix: many off_t's and one long should be phys_bytes' and a couple of longs
XX+  * should be off_t's. Also, phys_bytes should be unsigned as well as long.
XX+  * There will be a problem lseeking if the 386 kernel is every mapped high.
XX+  */
XX+ #endif
XX+ 
XX  /*----- ps's local stuff below this line ------*/
XX  
XX  
XX  #define mindev(dev)	(((dev)>>MINOR) & 0377)	/* yield minor device */
XX  #define majdev(dev)	(((dev)>>MAJOR) & 0377)	/* yield major device */
XX  
XX! #define	TTY_MAJ		4	/* major device of console */
XX  
XX! /* Macro to convert memory offsets to rounded kilo-units */
XX  #define	off_to_k(off)	((unsigned) (((off) + 512) / 1024))
XX  
XX! /* What we think the relevant identifiers in the namelists are */
XX! #define	ID_PROC		"_proc"	/* from kernel namelist */
XX! #define	ID_MPROC	"_mproc"/* from mm namelist */
XX! #define	ID_FPROC	"_fproc"/* from fs namelist */
XX  #define	ID_TASKTAB	"_tasktab"	/* from kernel namelist */
XX  
XX! /* Structure for system address info (also part of ps's database). */
XX  typedef struct {
XX!   struct nlist ke_proc[2], ke_tasktab[2];
XX!   struct nlist mm_mproc[2];
XX!   struct nlist fs_fproc[2];
XX  } sysinfo_t;
XX  
XX! sysinfo_t sysinfo;		/* sysinfo holds actual system info */
XX  
XX+ /* Structure for tty name info (also part of ps's database). */
XX+ typedef struct {
XX+   char tty_name[NAME_MAX + 1];	/* file name in /dev */
XX+   dev_t tty_dev;		/* major/minor pair */
XX+ } ttyinfo_t;
XX+ 
XX+ /* Structure for system path info (part of ps's database). */
XX+ typedef struct {
XX+   char ke_path[PATH_MAX + 1];	/* paths of kernel, */
XX+   char mm_path[PATH_MAX + 1];	/* mm, */
XX+   char fs_path[PATH_MAX + 1];	/* and fs used in last ps -U */
XX+ } pathinfo_t;
XX+ 
XX+ pathinfo_t pathinfo;		/* pathinfo holds actual path info */
XX+ 
XX+ /* N_TTYINFO is # of ttyinfo_t structs - should be >= # of entries in /dev. */
XX+ #define	N_TTYINFO	100
XX+ 
XX+ ttyinfo_t ttyinfo[N_TTYINFO];	/* ttyinfo holds actual tty info */
XX+ 
XX  #define	NAME_SIZ	(sizeof(sysinfo.ke_proc[0].n_name))	/* 8 chars */
XX  
XX! /* What we think the identfiers of the imported variables in this program are */
XX  #define	PROC	proc
XX  #define	MPROC	mproc
XX  #define	FPROC	fproc
XX  #define	TASKTAB	tasktab
XX  
XX! /* Default paths for system binaries */
XX  #define KERNEL_PATH	"/usr/src/kernel/kernel"
XX  #define MM_PATH		"/usr/src/mm/mm"
XX  #define FS_PATH		"/usr/src/fs/fs"
XX  
XX  #define	KMEM_PATH	"/dev/kmem"	/* opened for kernel proc table */
XX  #define	MEM_PATH	"/dev/mem"	/* opened for mm/fs + user processes */
XX  
XX! int kmemfd, memfd;		/* file descriptors of [k]mem */
XX  
XX  #define DBASE_PATH	"/etc/psdatabase"	/* path of ps's database */
XX! #define DBASE_MODE	0644	/* mode for ps's database */
XX  
XX  struct tasktab tasktab[NR_TASKS + INIT_PROC_NR + 1];	/* task table */
XX  
XX! /* Short and long listing formats:
XX   *
XX   *   PID TTY  TIME CMD
XX!  * ppppp tttmmm:ss ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
XX!  *
XX!  *   F S UID   PID  PPID  PGRP ADDR  SZ       RECV TTY  TIME CMD
XX!  * fff s uuu ppppp ppppp ppppp aaaa sss rrrrrrrrrr tttmmm:ss ccccccccccccccccccccc
XX   */
XX  #define S_HEADER "  PID TTY  TIME CMD\n"
XX! #define S_FORMAT "%5d %3s%3ld:%02ld %.63s\n"
XX! #define L_HEADER "  F S UID   PID  PPID  PGRP ADDR  SZ       RECV TTY  TIME CMD\n"
XX! #define L_FORMAT "%3o %c %3d %5d %5d %5d %4d %3d %10s %3s%3ld:%02ld %.21s\n"
XX  
XX! struct pstat {			/* structure filled by pstat() */
XX!   dev_t ps_dev;			/* major/minor of controlling tty */
XX!   uid_t ps_ruid;		/* real uid */
XX!   uid_t ps_euid;		/* effective uid */
XX!   pid_t ps_pid;			/* process id */
XX!   pid_t ps_ppid;		/* parent process id */
XX!   int ps_pgrp;			/* process group id */
XX!   int ps_flags;			/* kernel flags */
XX!   int ps_mflags;		/* mm flags */
XX!   int ps_ftask;			/* (possibly pseudo) fs suspend task */
XX!   char ps_state;		/* process state */
XX!   size_t ps_tsize;		/* text size (in bytes) */
XX!   size_t ps_dsize;		/* data size (in bytes) */
XX!   size_t ps_ssize;		/* stack size (in bytes) */
XX!   off_t ps_vtext;		/* physical text offset */
XX!   off_t ps_vdata;		/* physical data offset */
XX!   off_t ps_vstack;		/* physical stack offset */
XX!   off_t ps_text;		/* physical text offset */
XX!   off_t ps_data;		/* physical data offset */
XX!   off_t ps_stack;		/* physical stack offset */
XX!   int ps_recv;			/* process number to receive from */
XX!   time_t ps_utime;		/* accumulated user time */
XX!   time_t ps_stime;		/* accumulated system time */
XX!   char *ps_args;		/* concatenated argument string */
XX!   char *ps_istackframe;          /* initial stack frame from MM */
XX  };
XX  
XX! /* Ps_state field values in pstat struct above */
XX! #define	Z_STATE		'Z'	/* Zombie */
XX! #define	W_STATE		'W'	/* Waiting */
XX! #define	S_STATE		'S'	/* Sleeping */
XX! #define	R_STATE		'R'	/* Runnable */
XX! #define	T_STATE		'T'	/* stopped (Trace) */
XX  
XX+ _PROTOTYPE(char *tname, (Dev_t dev_nr ));
XX+ _PROTOTYPE(char *taskname, (int p_nr ));
XX+ _PROTOTYPE(char *prrecv, (struct pstat *bufp ));
XX+ _PROTOTYPE(void disaster, (int sig ));
XX+ _PROTOTYPE(int main, (int argc, char *argv []));
XX+ _PROTOTYPE(char *get_args, (struct pstat *bufp ));
XX+ _PROTOTYPE(int pstat, (int p_nr, struct pstat *bufp ));
XX+ _PROTOTYPE(int addrread, (int fd, phys_clicks base, vir_bytes addr, 
XX+ 						    char *buf, int nbytes ));
XX+ _PROTOTYPE(void usage, (char *pname ));
XX+ _PROTOTYPE(void err, (char *s ));
XX+ _PROTOTYPE(int gettynames, (ttyinfo_t ttyinfo []));
XX+ _PROTOTYPE(int outdates, (char *file, time_t tm ));
XX+ 
XX+ 
XX  /*
XX!  * Tname returns mnemonic string for dev_nr. This is "?" for maj/min pairs that
XX!  * are not found.  It uses the ttyinfo array (prepared by gettynames).
XX!  * Tname assumes that the first three letters of the tty's name can be omitted
XX!  * and returns the rest (except for the console, which yields "co").
XX!  * Thus, tname normally returns "co" for tty0, "1" for tty1, "01" for tty01,
XX!  * "p0" for ptyp0, "i00" for ttyi00, etc.
XX!  * One snag: If some non-standard name appears in /dev before the regular one,
XX!  * ps will print the non-standard's suffix.
XX   */
XX  char *tname(dev_nr)
XX+ Dev_t dev_nr;
XX  {
XX!   int i;
XX  
XX!   if (majdev(dev_nr) == TTY_MAJ && mindev(dev_nr) == 0) return "co";
XX! 
XX!   for (i = 0; i < N_TTYINFO && ttyinfo[i].tty_name[0] != '\0'; i++)
XX! 	if (ttyinfo[i].tty_dev == dev_nr)
XX! 		if (strlen(ttyinfo[i].tty_name) <= 3)
XX! 			return ttyinfo[i].tty_name;
XX! 		else
XX! 			return &(ttyinfo[i].tty_name[3]);
XX! 
XX!   return "?";
XX  }
XX  
XX! /* Return canonical task name of task p_nr; overwritten on each call (yucch) */
XX  char *taskname(p_nr)
XX+ int p_nr;
XX  {
XX!   char *cp;
XX! 
XX!   if (p_nr < -NR_TASKS || p_nr > INIT_PROC_NR) return "?";
XX! 
XX!   /* Strip trailing blanks for right-adjusted output */
XX!   for (cp = tasktab[p_nr + NR_TASKS].name; *cp != '\0'; cp++)
XX! 	if (*cp == ' ') break;
XX!   *cp = '\0';
XX! 
XX!   return tasktab[p_nr + NR_TASKS].name;
XX  }
XX  
XX! /* Prrecv prints the RECV field for process with pstat buffer pointer bufp.
XX   * This is either "ANY", "taskname", or "(blockreason) taskname".
XX   */
XX  char *prrecv(bufp)
XX  struct pstat *bufp;
XX  {
XX!   char *blkstr, *task;		/* reason for blocking and task */
XX!   static char recvstr[20];
XX  
XX!   if (bufp->ps_recv == ANY) return "ANY";
XX  
XX!   task = taskname(bufp->ps_recv);
XX!   if (bufp->ps_state != S_STATE) return task;
XX! 
XX!   blkstr = "?";
XX!   if (bufp->ps_recv == MM_PROC_NR) {
XX! 	if (bufp->ps_mflags & PAUSED)
XX! 		blkstr = "pause";
XX! 	else if (bufp->ps_mflags & WAITING)
XX! 		blkstr = "wait";
XX!   } else if (bufp->ps_recv == FS_PROC_NR) {
XX! 	if (-bufp->ps_ftask == XOPEN)
XX! 		blkstr = "xopen";
XX! 	else if (-bufp->ps_ftask == XPIPE)
XX! 		blkstr = "xpipe";
XX! 	else
XX! 		blkstr = taskname(-bufp->ps_ftask);
XX!   }
XX!   (void) sprintf(recvstr, "(%s) %s", blkstr, task);
XX!   return recvstr;
XX  }
XX  
XX! /* If disaster is called some of the system parameters imported into ps are
XX!  * probably wrong.  This tends to result in memory faults.
XX!  */
XX! void disaster(sig)
XX! int sig;
XX! {
XX!   fprintf(stderr, "Ooops, got signal %d: ", sig);
XX!   fprintf(stderr, "Make sure up-to-date system executables are used and\n");
XX!   fprintf(stderr, "correct system parameters are compiled into ps.\n");
XX!   exit(3);
XX! }
XX! 
XX! /* Main interprets arguments, gets system addresses, opens [k]mem, reads in
XX   * process tables from kernel/mm/fs and calls pstat() for relevant entries.
XX   */
XX! int main(argc, argv)
XX! int argc;
XX  char *argv[];
XX  {
XX!   int i;
XX!   struct pstat buf;
XX!   int db_fd;
XX!   int uid = getuid();		/* real uid of caller */
XX!   int opt_all = FALSE;		/* -a */
XX!   int opt_long = FALSE;		/* -l */
XX!   int opt_notty = FALSE;	/* -x */
XX!   int opt_update = FALSE;	/* -U */
XX!   int opt_path = FALSE;		/* alternative system executables */
XX  
XX!   (void) signal(SIGSEGV, disaster);	/* catch a common crash */
XX! 
XX!   /* Parse arguments; a '-' need not be present (V7/BSD compatability) */
XX!   switch (argc) {
XX!       case 1:			/* plain ps */
XX! 	break;
XX!       case 2:			/* ps <[-][alxU]> */
XX!       case 5:			/* ps <[-][alxU]> <kernel mm fs> */
XX! 	for (i = (argv[1][0] == '-' ? 1 : 0); argv[1][i] != '\0'; i++)
XX! 		switch (argv[1][i]) {
XX! 		    case 'a':	opt_all = TRUE;	break;
XX! 		    case 'l':	opt_long = TRUE;	break;
XX! 		    case 'x':	opt_notty = TRUE;	break;
XX! 		    case 'U':	opt_update = TRUE;	break;
XX! 		    default:	usage(argv[0]);
XX! 		}
XX! 	break;
XX!       case 4:			/* ps <kernel mm fs> */
XX! 	if (argv[1][0] != '-') break;
XX!       default:	usage(argv[0]);
XX! }
XX! 
XX!   if (argc >= 4) {		/* ps [-][alxU] <kernel mm fs> */
XX! 	opt_path = TRUE;
XX! 	strncpy(pathinfo.ke_path, argv[argc - 3], (size_t)PATH_MAX);
XX! 	strncpy(pathinfo.mm_path, argv[argc - 2], (size_t)PATH_MAX);
XX! 	strncpy(pathinfo.fs_path, argv[argc - 1], (size_t)PATH_MAX);
XX!   } else {
XX! 	strcpy(pathinfo.ke_path, KERNEL_PATH);
XX! 	strcpy(pathinfo.mm_path, MM_PATH);
XX! 	strcpy(pathinfo.fs_path, FS_PATH);
XX!   }
XX! 
XX!   /* Fill the sysinfo and ttyinfo structs */
XX!   if (opt_update || opt_path ||
XX!       (db_fd = open(DBASE_PATH, O_RDONLY)) == -1) {
XX! 
XX! 	/* Try to use old database's paths for this update */
XX! 	if (opt_update && !opt_path &&
XX! 	    (db_fd = open(DBASE_PATH, O_RDONLY)) != -1) {
XX  		if (read(db_fd, (char *) &sysinfo,
XX! 			 sizeof(sysinfo_t)) == sizeof(sysinfo_t) &&
XX! 		    read(db_fd, (char *) ttyinfo,
XX! 			 sizeof(ttyinfo)) == sizeof(ttyinfo) &&
XX! 		    read(db_fd, (char *) &pathinfo,
XX! 			 sizeof(pathinfo_t)) == sizeof(pathinfo_t))
XX! 			fprintf(stderr, "Using old pathnames found in %s.\n",
XX! 				DBASE_PATH);
XX! 		(void) close(db_fd);
XX  	}
XX! 	strncpy(sysinfo.ke_proc[0].n_name, ID_PROC, (size_t)NAME_SIZ);
XX! 	strncpy(sysinfo.ke_tasktab[0].n_name, ID_TASKTAB, (size_t)NAME_SIZ);
XX! 	if (nlist(pathinfo.ke_path, sysinfo.ke_proc) != 0 ||
XX! 	    nlist(pathinfo.ke_path, sysinfo.ke_tasktab) != 0)
XX! 		err("Can't read kernel namelist");
XX! 	strncpy(sysinfo.mm_mproc[0].n_name, ID_MPROC, (size_t)NAME_SIZ);
XX! 	if (nlist(pathinfo.mm_path, sysinfo.mm_mproc) != 0)
XX! 		err("Can't read mm namelist");
XX! 	strncpy(sysinfo.fs_fproc[0].n_name, ID_FPROC, (size_t)NAME_SIZ);
XX! 	if (nlist(pathinfo.fs_path, sysinfo.fs_fproc) != 0)
XX! 		err("Can't read fs namelist");
XX  
XX! 	if (gettynames(ttyinfo) == -1) err("Can't get tty names");
XX! 
XX! 	if (opt_update) {
XX! 		if ((db_fd = creat(DBASE_PATH, DBASE_MODE)) == -1)
XX! 			err("Can't creat psdatabase");
XX! 		if (write(db_fd, (char *) &sysinfo,
XX! 			  sizeof(sysinfo_t)) != sizeof(sysinfo_t) ||
XX! 		    write(db_fd, (char *) ttyinfo,
XX! 			  sizeof(ttyinfo)) != sizeof(ttyinfo) ||
XX! 		    write(db_fd, (char *) &pathinfo,
XX! 			  sizeof(pathinfo_t)) != sizeof(pathinfo_t))
XX! 			err("Can't write psdatabase");
XX! 		fprintf(stderr, "Updated terminal names and system addresses in %s using:\n",
XX! 			DBASE_PATH);
XX! 		fprintf(stderr, "%s, %s, %s.\n",
XX! 			pathinfo.ke_path, pathinfo.mm_path,
XX! 			pathinfo.fs_path);
XX! 		exit(0);	/* don't attempt to do further output */
XX  	}
XX+   } else {			/* get info from database */
XX+ 	struct stat db_stat;
XX+ 
XX+ 	if (read(db_fd, (char *) &sysinfo,
XX+ 		 sizeof(sysinfo_t)) != sizeof(sysinfo_t) ||
XX+ 	    read(db_fd, (char *) ttyinfo,
XX+ 		 sizeof(ttyinfo)) != sizeof(ttyinfo) ||
XX+ 	    read(db_fd, (char *) &pathinfo,
XX+ 		 sizeof(pathinfo_t)) != sizeof(pathinfo_t))
XX+ 		err("Can't read info from psdatabase");
XX+ 
XX+ 	/* Compare modification time of database with kernel/mm/fs
XX+ 	 * and warn user if the database appears to be outdated.
XX+ 	 * Times are ignored if the system executables have no
XX+ 	 * namelist.
XX+ 	 */
XX+ 	(void) fstat(db_fd, &db_stat);
XX+ 	if (outdates(pathinfo.ke_path, db_stat.st_mtime))
XX+ 		fprintf(stderr, "Warning: %s is older than %s\n",
XX+ 			DBASE_PATH, pathinfo.ke_path);
XX+ 	if (outdates(pathinfo.mm_path, db_stat.st_mtime))
XX+ 		fprintf(stderr, "Warning: %s is older than %s\n",
XX+ 			DBASE_PATH, pathinfo.mm_path);
XX+ 	if (outdates(pathinfo.fs_path, db_stat.st_mtime))
XX+ 		fprintf(stderr, "Warning: %s is older than %s\n",
XX+ 			DBASE_PATH, pathinfo.fs_path);
XX+   }
XX+   (void) close(db_fd);
XX+ 
XX+   /* Get kernel tables */
XX+   if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1) err(KMEM_PATH);
XX+   if (addrread(kmemfd, (phys_clicks) 0,
XX+ 	     (vir_bytes) sysinfo.ke_proc[0].n_value,
XX+ 	     (char *) PROC, sizeof(PROC)) != sizeof(PROC))
XX+ 	err("Can't get kernel proc table from /dev/kmem");
XX+   if (addrread(kmemfd, (phys_clicks) 0,
XX+ 	     (vir_bytes) sysinfo.ke_tasktab[0].n_value,
XX+ 	     (char *) TASKTAB, sizeof(TASKTAB)) != sizeof(TASKTAB))
XX+ 	err("Can't get kernel task table from /dev/kmem");
XX+ 
XX+   /* Get mm/fs tables */
XX+   if ((memfd = open(MEM_PATH, O_RDONLY)) == -1) err(MEM_PATH);
XX+   if (addrread(memfd, PROC[NR_TASKS + MM_PROC_NR].p_map[D].mem_phys,
XX+ 	     (vir_bytes) sysinfo.mm_mproc[0].n_value,
XX+ 	     (char *) MPROC, sizeof(MPROC)) != sizeof(MPROC))
XX+ 	err("Can't get mm proc table from /dev/mem");
XX+   if (addrread(memfd, PROC[NR_TASKS + FS_PROC_NR].p_map[D].mem_phys,
XX+ 	     (vir_bytes) sysinfo.fs_fproc[0].n_value,
XX+ 	     (char *) FPROC, sizeof(FPROC)) != sizeof(FPROC))
XX+ 	err("Can't get fs proc table from /dev/mem");
XX+ 
XX+   /* Now loop through process table and handle each entry */
XX+   printf("%s", opt_long ? L_HEADER : S_HEADER);
XX+   for (i = -NR_TASKS; i < NR_PROCS; i++) {
XX+ 	if (pstat(i, &buf) != -1 &&
XX+ 	    (opt_all || buf.ps_euid == uid || buf.ps_ruid == uid) &&
XX+ 	    (opt_notty || majdev(buf.ps_dev) == TTY_MAJ))
XX+ 		if (opt_long) printf(L_FORMAT,
XX+ 			       buf.ps_flags, buf.ps_state,
XX+ 			       buf.ps_euid, buf.ps_pid, buf.ps_ppid,
XX+ 			       buf.ps_pgrp,
XX+ 			       off_to_k(buf.ps_text),
XX+ 			       off_to_k((buf.ps_tsize
XX+ 					 + buf.ps_stack - buf.ps_data
XX+ 					 + buf.ps_ssize)),
XX+ 			       (buf.ps_flags & RECEIVING ?
XX+ 				prrecv(&buf) :
XX+ 				""),
XX+ 			       tname((Dev_t) buf.ps_dev),
XX+ 			    (buf.ps_utime + buf.ps_stime) / HZ / 60,
XX+ 			    (buf.ps_utime + buf.ps_stime) / HZ % 60,
XX+ 			       i <= INIT_PROC_NR ? taskname(i) :
XX+ 			       (buf.ps_args == NULL ? "" :
XX+ 				buf.ps_args));
XX+ 		else
XX+ 			printf(S_FORMAT,
XX+ 			       buf.ps_pid, tname((Dev_t) buf.ps_dev),
XX+ 			    (buf.ps_utime + buf.ps_stime) / HZ / 60,
XX+ 			    (buf.ps_utime + buf.ps_stime) / HZ % 60,
XX+ 			       i <= INIT_PROC_NR ? taskname(i) :
XX+ 			       (buf.ps_args == NULL ? "" :
XX+ 				buf.ps_args));
XX+   }
XX+   return(0);
XX  }
XX  
XX!   union {
XX  #if (CHIP == M68000)
XX! 	long stk_i;
XX  #else
XX! 	int stk_i;
XX  #endif
XX! 	char *stk_cp;
XX! 	char stk_c;
XX!   } stk[ARG_MAX / sizeof(char *)], *sp;
XX! 
XX! char *get_args(bufp)
XX! struct pstat *bufp;
XX! {
XX!   int nargv;
XX!   int cnt;			/* # of bytes read from stack frame */
XX!   int neos;			/* # of '\0's seen in argv string space */
XX!   long l;
XX!   char *cp, *args;
XX! 
XX!   /* Calculate the number of bytes to read from user stack */
XX!   cnt = bufp->ps_ssize - ( (long)bufp->ps_istackframe - (long)bufp->ps_stack );
XX!   if (cnt > ARG_MAX) cnt = ARG_MAX;
XX! 
XX!   /* Get cnt bytes from user initial stack to local stack buffer */
XX!   if (lseek(memfd, ((long) bufp->ps_istackframe), 0) < 0)
XX! 	return NULL; 
XX! 
XX!   if ( read(memfd, (char *)stk, cnt) != cnt ) 
XX! 	return NULL;
XX! 
XX!   sp = stk;
XX!   nargv = (int) sp[0].stk_i;  /* number of argv arguments */
XX! 
XX!   /* See if argv[0] is with the bytes we read in */
XX!   l = (long) sp[1].stk_cp - (long) bufp->ps_istackframe + (long)bufp->ps_stack -
XX! 	(long)bufp->ps_vstack;
XX!   if ( ( l < 0 ) || ( l > cnt ) )  
XX! 	return NULL;
XX! 
XX!   /* l is the offset of the argv[0] argument */
XX!   /* change for concatenation the '\0' to space, for nargv elements */
XX! 
XX!   args = &((char *) stk)[(int)l]; 
XX!   neos = 0;
XX!   for (cp = args; cp < &((char *) stk)[cnt]; cp++)
XX! 	if (*cp == '\0')
XX! 		if (++neos >= nargv)
XX  			break;
XX! 		else
XX! 			*cp = ' ';
XX!   if (neos != nargv) return NULL;
XX  
XX!   return args;
XX  
XX  }
XX  
XX! /* Pstat collects info on process number p_nr and returns it in buf.
XX   * It is assumed that tasks do not have entries in fproc/mproc.
XX   */
XX  int pstat(p_nr, bufp)
XX+ int p_nr;
XX  struct pstat *bufp;
XX  {
XX!   int p_ki = p_nr + NR_TASKS;	/* kernel proc index */
XX  
XX!   if (p_nr < -NR_TASKS || p_nr >= NR_PROCS) return -1;
XX  
XX!   if ((PROC[p_ki].p_flags & P_SLOT_FREE) && !(MPROC[p_nr].mp_flags & IN_USE))
XX! 	return -1;
XX! 
XX!   bufp->ps_flags = PROC[p_ki].p_flags;
XX! 
XX!   if (p_nr >= LOW_USER) {
XX! 	bufp->ps_dev = FPROC[p_nr].fs_tty;
XX! 	bufp->ps_ftask = FPROC[p_nr].fp_task;
XX!   } else {
XX! 	bufp->ps_dev = 0;
XX! 	bufp->ps_ftask = 0;
XX!   }
XX! 
XX!   if (p_nr >= LOW_USER) {
XX! 	bufp->ps_ruid = MPROC[p_nr].mp_realuid;
XX! 	bufp->ps_euid = MPROC[p_nr].mp_effuid;
XX! 	bufp->ps_pid = MPROC[p_nr].mp_pid;
XX! 	bufp->ps_ppid = MPROC[MPROC[p_nr].mp_parent].mp_pid;
XX! 	bufp->ps_pgrp = MPROC[p_nr].mp_procgrp;
XX! 	bufp->ps_mflags = MPROC[p_nr].mp_flags;
XX!   } else {
XX! 	bufp->ps_pid = bufp->ps_ppid = 0;
XX! 	bufp->ps_ruid = bufp->ps_euid = 0;
XX! 	bufp->ps_pgrp = 0;
XX! 	bufp->ps_mflags = 0;
XX!   }
XX! 
XX!   /* State is interpretation of combined kernel/mm flags for non-tasks */
XX!   if (p_nr >= LOW_USER) {		/* non-tasks */
XX! 	if (MPROC[p_nr].mp_flags & HANGING)
XX! 		bufp->ps_state = Z_STATE;	/* zombie */
XX! 	else if (MPROC[p_nr].mp_flags & STOPPED)
XX! 		bufp->ps_state = T_STATE;	/* stopped (traced) */
XX! 	else if (PROC[p_ki].p_flags == 0)
XX! 		bufp->ps_state = R_STATE;	/* in run-queue */
XX! 	else if (MPROC[p_nr].mp_flags & (WAITING | PAUSED) ||
XX! 		 FPROC[p_nr].fp_suspended == SUSPENDED)
XX! 		bufp->ps_state = S_STATE;	/* sleeping */
XX! 	else
XX! 		bufp->ps_state = W_STATE;	/* a short wait */
XX!   } else {			/* tasks are simple */
XX! 	if (PROC[p_ki].p_flags == 0)
XX! 		bufp->ps_state = R_STATE;	/* in run-queue */
XX! 	else
XX! 		bufp->ps_state = W_STATE;	/* other i.e. waiting */
XX!   }
XX! 
XX!   bufp->ps_tsize = (size_t) PROC[p_ki].p_map[T].mem_len << CLICK_SHIFT;
XX!   bufp->ps_dsize = (size_t) PROC[p_ki].p_map[D].mem_len << CLICK_SHIFT;
XX!   bufp->ps_ssize = (size_t) PROC[p_ki].p_map[S].mem_len << CLICK_SHIFT;
XX!   bufp->ps_vtext = (off_t) PROC[p_ki].p_map[T].mem_vir << CLICK_SHIFT;
XX!   bufp->ps_vdata = (off_t) PROC[p_ki].p_map[D].mem_vir << CLICK_SHIFT;
XX!   bufp->ps_vstack = (off_t) PROC[p_ki].p_map[S].mem_vir << CLICK_SHIFT;
XX!   bufp->ps_text = (off_t) PROC[p_ki].p_map[T].mem_phys << CLICK_SHIFT;
XX!   bufp->ps_data = (off_t) PROC[p_ki].p_map[D].mem_phys << CLICK_SHIFT;
XX!   bufp->ps_stack = (off_t) PROC[p_ki].p_map[S].mem_phys << CLICK_SHIFT;
XX! 
XX!   bufp->ps_recv = PROC[p_ki].p_getfrom;
XX! 
XX!   bufp->ps_utime = PROC[p_ki].user_time;
XX!   bufp->ps_stime = PROC[p_ki].sys_time;
XX! 
XX!   bufp->ps_istackframe = (char *)(MPROC[p_nr].mp_procargs 
XX! 			    - (PROC[p_ki].p_map[S].mem_vir << CLICK_SHIFT)
XX! 			    + (PROC[p_ki].p_map[S].mem_phys << CLICK_SHIFT));
XX! 
XX!   if (bufp->ps_state == Z_STATE)
XX! 	bufp->ps_args = "<defunct>";
XX!   else if (p_nr > INIT_PROC_NR)
XX! 	bufp->ps_args = get_args(bufp);
XX! 
XX!   return 0;
XX  }
XX  
XX! /* Addrread reads nbytes from offset addr to click base of fd into buf. */
XX  int addrread(fd, base, addr, buf, nbytes)
XX+ int fd;
XX  phys_clicks base;
XX  vir_bytes addr;
XX  char *buf;
XX+ int nbytes;
XX  {
XX!   if (lseek(fd, ((long) base << CLICK_SHIFT) + (long) addr, 0) < 0)
XX! 	return -1;
XX  
XX!   return read(fd, buf, nbytes);
XX  }
XX  
XX! void usage(pname)
XX  char *pname;
XX  {
XX!   fprintf(stderr, "Usage: %s [-][alxU] [kernel mm fs]\n", pname);
XX!   exit(1);
XX  }
XX  
XX! void err(s)
XX  char *s;
XX  {
XX+   extern int errno;
XX+ 
XX+   if (errno == 0)
XX+ 	fprintf(stderr, "%s\n", s);
XX+   else
XX  	perror(s);
XX! 
XX!   exit(2);
XX! }
XX! 
XX! /* Fill ttyinfo by fstatting character specials in /dev. */
XX! int gettynames(ttyinfo)
XX! ttyinfo_t ttyinfo[];
XX! {
XX!   static char dev_path[] = "/dev/";
XX!   DIR *dev_dir;
XX!   struct dirent *ent;
XX!   struct stat statbuf;
XX!   static char path[sizeof(dev_path) + NAME_MAX];
XX!   int index;
XX! 
XX!   if ((dev_dir = opendir(dev_path)) == NULL) return -1;
XX! 
XX!   index = 0;
XX!   while ((ent = readdir(dev_dir)) != NULL) {
XX! 	strcpy(path, dev_path);
XX! 	strcat(path, ent->d_name);
XX! 	if (stat(path, &statbuf) == -1 || !S_ISCHR(statbuf.st_mode))
XX! 		continue;
XX! 	if (index >= N_TTYINFO) err("Can't keep info on all ttys in /dev");
XX! 	ttyinfo[index].tty_dev = statbuf.st_rdev;
XX! 	strcpy(ttyinfo[index].tty_name, ent->d_name);
XX! 	index++;
XX!   }
XX! 
XX!   return 0;
XX! }
XX! 
XX! /* Outdates returns true iff non-stripped file was modified later than time. */
XX! int outdates(file, tm)
XX! char *file;
XX! time_t tm;
XX! {
XX!   int fd;
XX!   struct exec hd;
XX!   struct stat buf;
XX! 
XX!   if ((fd = open(file, O_RDONLY)) == -1) return 0;
XX! 
XX!   if (read(fd, (char *) &hd,
XX! 	 sizeof(struct exec)) != sizeof(struct exec) ||
XX!       fstat(fd, &buf) == -1) {
XX! 	(void) close(fd);
XX! 	return 0;
XX!   }
XX!   (void) close(fd);
XX! 
XX!   return !BADMAG(hd) && hd.a_syms != 0 && buf.st_mtime > tm;
XX! }
X/
Xecho x - pwd.c.d
Xsed '/^X/s///' > pwd.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/pwd.c  crc=09609    341	Sun Apr 25 21:35:13 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/pwd.c  crc=56553   1163	Mon Dec 21 00:08:30 1992
XX***************
XX*** 1,23 ****
XX  /*
XX!  * Print Working Directory (pwd)
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <limits.h>
XX  #include <unistd.h>
XX  
XX! char dir[PATH_MAX+1];
XX  
XX! main()
XX  {
XX    char *p;
XX  
XX    p = getcwd(dir, PATH_MAX);
XX!   if (p == (char *) NULL) {
XX! 	std_err("pwd: cannot search some directory on the path\n");
XX! 	exit(1);
XX    }
XX!   write(1, p, strlen(p));
XX!   write(1, "\n", 1);
XX!   exit(0);
XX  }
XX--- 1,49 ----
XX+ /* pwd - print working directory	Author: Norbert Schlenker */
XX+ 
XX  /*
XX!  * pwd - print working directory
XX!  *   Syntax:	pwd
XX!  *   Flags:	None.
XX!  *   Author:	Norbert Schlenker
XX!  *   Copyright:	None.  Released to the public domain.
XX!  *   Reference:	IEEE P1003.2 Section 4.50 (draft 10)
XX!  *   Bugs:	No internationalization support; all messages are in English.
XX   */
XX  
XX+ /* Force visible Posix names */
XX+ #ifndef _POSIX_SOURCE
XX+ #define _POSIX_SOURCE 1
XX+ #endif
XX+ 
XX+ /* External interfaces */
XX  #include <sys/types.h>
XX  #include <limits.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! /* Magic numbers suggested or required by Posix specification */
XX! #define SUCCESS	0		/* exit code in case of success */
XX! #define FAILURE 1		/*                   or failure */
XX  
XX! _PROTOTYPE(int main, (void));
XX! 
XX! static char dir[PATH_MAX + 1];
XX! static char *errmsg = "pwd: cannot search some directory on the path\n";
XX! 
XX! int main()
XX  {
XX    char *p;
XX+   size_t n;
XX  
XX    p = getcwd(dir, PATH_MAX);
XX!   if (p == NULL) {
XX! 	write(STDERR_FILENO, errmsg, strlen(errmsg));
XX! 	exit(FAILURE);
XX    }
XX!   n = strlen(p);
XX!   p[n] = '\n';
XX!   if (write(STDOUT_FILENO, p, n + 1) != n + 1) 	exit(FAILURE);
XX!   return(SUCCESS);
XX  }
X/
Xecho x - readall.c.d
Xsed '/^X/s///' > readall.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/readall.c  crc=05605   3285	Sun Apr 25 21:35:13 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/readall.c  crc=00746   3535	Wed Nov  4 07:51:29 1992
XX***************
XX*** 19,24 ****
XX--- 19,26 ----
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX  #include <blocksize.h>
XX+ #include <stdlib.h>
XX+ #include <stdio.h>
XX  
XX  #define CHUNK    25		/* max number of blocks read at once */
XX  #define RESUME  200		/* # good reads before going back to CHUNK */
XX***************
XX*** 35,41 ****
XX  char a[CHUNK * BLOCK_SIZE];	/* read buffer */
XX  long rotten[STORE];		/* list of bad blocks */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 37,46 ----
XX  char a[CHUNK * BLOCK_SIZE];	/* read buffer */
XX  long rotten[STORE];		/* list of bad blocks */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! static _PROTOTYPE(void output, (long blocks_read));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 44,77 ****
XX    char *p;
XX  
XX    if (argc != 2 && argc != 3) {
XX! 	printf("Usage: readall [-b | -t] file\n");
XX  	exit(1);
XX    }
XX- 
XX    i = 1;
XX  
XX    p = argv[1];
XX!   if (*p == '-' && *(p+1) == 'b' && *(p+2) == '\0') {
XX  	normal = 0;
XX  	i++;
XX  	name = argv[i];
XX    }
XX!   if (*p == '-' && *(p+1) == 't' && *(p+2) == '\0') {
XX  	normal = 0;
XX  	total = 1;
XX  	i++;
XX  	name = argv[i];
XX    }
XX- 
XX    fd = open(argv[i], O_RDONLY);
XX    if (fd < 0) {
XX! 	printf("%s is not readable\n", argv[i]);
XX  	exit(1);
XX    }
XX  
XX!   /* Read the entire file. Try it in large chunks, but if an error occurs,
XX!    * go to single reads for a while.
XX!    */
XX    while (1) {
XX  	lseek(fd, BLOCK_SIZE * b, SEEK_SET);
XX  	s = read(fd, a, BLOCK_SIZE * chunk);
XX--- 49,79 ----
XX    char *p;
XX  
XX    if (argc != 2 && argc != 3) {
XX! 	fprintf(stderr, "Usage: readall [-b | -t] file\n");
XX  	exit(1);
XX    }
XX    i = 1;
XX  
XX    p = argv[1];
XX!   if (*p == '-' && *(p + 1) == 'b' && *(p + 2) == '\0') {
XX  	normal = 0;
XX  	i++;
XX  	name = argv[i];
XX    }
XX!   if (*p == '-' && *(p + 1) == 't' && *(p + 2) == '\0') {
XX  	normal = 0;
XX  	total = 1;
XX  	i++;
XX  	name = argv[i];
XX    }
XX    fd = open(argv[i], O_RDONLY);
XX    if (fd < 0) {
XX! 	fprintf(stderr, "%s is not readable\n", argv[i]);
XX  	exit(1);
XX    }
XX  
XX!   /* Read the entire file. Try it in large chunks, but if an error
XX!    * occurs, go to single reads for a while. */
XX    while (1) {
XX  	lseek(fd, BLOCK_SIZE * b, SEEK_SET);
XX  	s = read(fd, a, BLOCK_SIZE * chunk);
XX***************
XX*** 80,86 ****
XX  		b += chunk;
XX  		goodies++;
XX  		if (chunk == 1) {
XX! 			if(goodies >= RESUME && b % DIVISOR == 0)chunk = CHUNK;
XX  		}
XX  	} else if (s < 0) {
XX  		/* I/O error. */
XX--- 82,89 ----
XX  		b += chunk;
XX  		goodies++;
XX  		if (chunk == 1) {
XX! 			if (goodies >= RESUME && b % DIVISOR == 0)
XX! 				chunk = CHUNK;
XX  		}
XX  	} else if (s < 0) {
XX  		/* I/O error. */
XX***************
XX*** 89,113 ****
XX  			continue;
XX  		}
XX  		if (errors == STORE) {
XX! 		     printf("\n%ld Bad blocks is too many.  Exiting\n",errors);
XX! 		     exit(1);
XX  		}
XX! 		rotten[(int)errors] = b;	/* log the error */
XX  		b += chunk;
XX  		errors++;
XX  	} else {
XX  		/* End of file. */
XX! 		b += s/BLOCK_SIZE;
XX  		if (normal) {
XX  			output(b);
XX! 			printf("\n");
XX  		}
XX  		if (total) printf("%8ld\n", b);
XX  		if ((errors == 0) || total) exit(0);
XX! 		if (normal) 
XX! 			printf("Summary of bad blocks\n");
XX! 		else
XX! 			badprinted = 0;
XX  
XX  		/* Print summary of bad blocks, possibly as shell script. */
XX  		for (i = 0; i < errors; i++) {
XX--- 92,116 ----
XX  			continue;
XX  		}
XX  		if (errors == STORE) {
XX! 			fprintf(stderr,
XX! 			 "\n%ld Bad blocks is too many.  Exiting\n",
XX! 				errors);
XX! 			exit(1);
XX  		}
XX! 		rotten[(int) errors] = b;	/* log the error */
XX  		b += chunk;
XX  		errors++;
XX  	} else {
XX  		/* End of file. */
XX! 		b += s / BLOCK_SIZE;
XX  		if (normal) {
XX  			output(b);
XX! 			fprintf(stderr, "\n");
XX  		}
XX  		if (total) printf("%8ld\n", b);
XX  		if ((errors == 0) || total) exit(0);
XX! 		badprinted = 0;
XX! 		if (normal) printf("Summary of bad blocks\n");
XX  
XX  		/* Print summary of bad blocks, possibly as shell script. */
XX  		for (i = 0; i < errors; i++) {
XX***************
XX*** 116,122 ****
XX  				badprinted = 1;
XX  			}
XX  			printf("%6ld ", rotten[i]);
XX! 			if ( (i+1) % 7 == 0) {
XX  				printf("\n");
XX  				badprinted = 0;
XX  			}
XX--- 119,125 ----
XX  				badprinted = 1;
XX  			}
XX  			printf("%6ld ", rotten[i]);
XX! 			if ((i + 1) % 7 == 0) {
XX  				printf("\n");
XX  				badprinted = 0;
XX  			}
XX***************
XX*** 128,135 ****
XX    }
XX  }
XX  
XX! output(b)
XX! long b;
XX  {
XX!   printf("%8ld blocks read, %5ld errors\r", b, errors);
XX  }
XX--- 131,139 ----
XX    }
XX  }
XX  
XX! static void output(blocks_read)
XX! long blocks_read;
XX  {
XX!   fprintf(stderr, "%8ld blocks read, %5ld errors\r", blocks_read, errors);
XX!   fflush(stderr);
XX  }
X/
Xecho x - readfs.c.d
Xsed '/^X/s///' > readfs.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/readfs.c  crc=61092  14782	Sun Apr 25 21:35:14 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/readfs.c  crc=43983  16178	Mon Dec 21 21:38:40 1992
XX***************
XX*** 6,11 ****
XX--- 6,12 ----
XX   *
XX   * Flags: -l:	Extract files and dirs and produce a mkfs-listing on stdout
XX   * 	  -i:	Information only: give the listing, but do not extract files.
XX+  *	  -d:	Don't extract regular files, just the skeleton please.
XX   *
XX   * Examples: readfs /dev/fd1		# extract all files from /dev/fd1.
XX   * 	     readfs -i /dev/hd2		# see what's on /dev/hd2.
XX***************
XX*** 24,33 ****
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <unistd.h>
XX! #include <stdio.h>
XX  
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX--- 25,39 ----
XX   */
XX  
XX  #include <sys/types.h>
XX+ #include <sys/dir.h>
XX+ #include <sys/stat.h>
XX+ #include <sys/wait.h>
XX  #include <fcntl.h>
XX  #include <limits.h>
XX  #include <unistd.h>
XX! #include <stdlib.h>
XX! #include <string.h>
XX! #include <utime.h>
XX  
XX  #include <minix/config.h>
XX  #include <minix/const.h>
XX***************
XX*** 37,49 ****
XX  #include "../fs/buf.h"
XX  #include "../fs/super.h"
XX  
XX- 
XX  #undef printf			/* Definition used only in the kernel */
XX  
XX- #define block_nr long		/* To allow big filesystems even if FS
XX- 			 * doesn't. */
XX- 
XX- 
XX  /* Compile with -I/user0/ast/minix
XX   * (i.e. the directory containing the MINIX system sources)
XX   *
XX--- 43,51 ----
XX  #include "../fs/buf.h"
XX  #include "../fs/super.h"
XX  
XX  #undef printf			/* Definition used only in the kernel */
XX+ #include <stdio.h>
XX  
XX  /* Compile with -I/user0/ast/minix
XX   * (i.e. the directory containing the MINIX system sources)
XX   *
XX***************
XX*** 54,64 ****
XX   /* And extracts its contents. */
XX  char noaction = 0;		/* just give a mkfs-listing, do not extract
XX  			 * files. */
XX  
XX  struct super_block sb;
XX  char pathname[1024];
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 56,82 ----
XX   /* And extracts its contents. */
XX  char noaction = 0;		/* just give a mkfs-listing, do not extract
XX  			 * files. */
XX+ char nofiles = 0;		/* only extract the skeleton FS structure */
XX  
XX  struct super_block sb;
XX  char pathname[1024];
XX+ int inodes_per_block;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void get_flags, (char *flags));
XX! _PROTOTYPE(void readfs, (char *special_file, char *directory));
XX! _PROTOTYPE(int get_inode, (int fd, Ino_t inum, d1_inode * ip));
XX! _PROTOTYPE(void dump_dir, (int special, d1_inode * ip, char *directory));
XX! _PROTOTYPE(int dump_file, (int special, d1_inode * ip, char *filename));
XX! _PROTOTYPE(int get_fileblock, (int special, d1_inode * ip, block_t b, struct buf * bp));
XX! _PROTOTYPE(int get_block, (int fd, block_t block, struct buf * bp, int type));
XX! _PROTOTYPE(int get_rawblock, (int special, block_t blockno, char *bufp));
XX! _PROTOTYPE(void restore, (char *name, d1_inode * ip));
XX! _PROTOTYPE(void show_info, (char *name, d1_inode * ip, char *path));
XX! _PROTOTYPE(void do_indent, (int i));
XX! _PROTOTYPE(int Mkdir, (char *directory));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 88,97 ****
XX  	fprintf(stderr, "Usage: %s [-li] <special> [dirname]\n", argv[0]);
XX  	exit(1);
XX    }
XX!   exit(0);
XX  }
XX  
XX! get_flags(flags)
XX  register char *flags;
XX  {
XX    while (*flags) {
XX--- 106,115 ----
XX  	fprintf(stderr, "Usage: %s [-li] <special> [dirname]\n", argv[0]);
XX  	exit(1);
XX    }
XX!   return(0);
XX  }
XX  
XX! void get_flags(flags)
XX  register char *flags;
XX  {
XX    while (*flags) {
XX***************
XX*** 103,108 ****
XX--- 121,128 ----
XX  		noaction = 1;
XX  		verbose = 1;
XX  		break;
XX+ 	    case 'D':
XX+ 	    case 'd':	nofiles = 1;	break;
XX  	    default:
XX  		fprintf(stderr, "Bad flag: %c\n", *flags);
XX  		break;
XX***************
XX*** 113,126 ****
XX  
XX  #define	zone_shift	(sb.s_log_zone_size)	/* zone to block ratio */
XX  
XX! readfs(special_file, directory)
XX  char *special_file, *directory;
XX  /* Readfs: opens the given special file (with MINIX filesystem),
XX   * and extracts its contents into the given directory.
XX   */
XX  {
XX!   d_inode root_inode;
XX!   int special;
XX    off_t super_b;
XX  
XX    umask(0);
XX--- 133,146 ----
XX  
XX  #define	zone_shift	(sb.s_log_zone_size)	/* zone to block ratio */
XX  
XX! void readfs(special_file, directory)
XX  char *special_file, *directory;
XX  /* Readfs: opens the given special file (with MINIX filesystem),
XX   * and extracts its contents into the given directory.
XX   */
XX  {
XX!   d1_inode root_inode;
XX!   int special, magic;
XX    off_t super_b;
XX  
XX    umask(0);
XX***************
XX*** 143,152 ****
XX  	return;
XX    }
XX  
XX    /* Is it really a MINIX filesystem ? */
XX!   if (sb.s_magic != SUPER_MAGIC) {
XX! 	fprintf(stderr, "%s is not a valid MINIX filesystem\n",
XX! 		special_file);
XX  	return;
XX    }
XX  
XX--- 163,179 ----
XX  	return;
XX    }
XX  
XX+   /* The number of inodes in a block differs in V1 and V2. */
XX+   magic = sb.s_magic;
XX+   if (magic == SUPER_MAGIC || magic == SUPER_REV) {
XX+ 	inodes_per_block = V1_INODES_PER_BLOCK;
XX+   } else {
XX+ 	inodes_per_block = V2_INODES_PER_BLOCK;
XX+   }
XX+ 
XX    /* Is it really a MINIX filesystem ? */
XX!   if (magic != SUPER_MAGIC && magic != SUPER_V2) {
XX! 	fprintf(stderr, "%s is not a valid MINIX filesystem\n", special_file);
XX  	return;
XX    }
XX  
XX***************
XX*** 158,164 ****
XX  
XX    /* Print number of blocks and inodes */
XX    if (verbose) printf("boot\n%ld %d\n",
XX! 	       (block_nr) sb.s_nzones << zone_shift, sb.s_ninodes);
XX  
XX    /* Extract (recursively) the root directory */
XX    dump_dir(special, &root_inode, directory);
XX--- 185,191 ----
XX  
XX    /* Print number of blocks and inodes */
XX    if (verbose) printf("boot\n%ld %d\n",
XX! 	       (block_t) sb.s_nzones << zone_shift, sb.s_ninodes);
XX  
XX    /* Extract (recursively) the root directory */
XX    dump_dir(special, &root_inode, directory);
XX***************
XX*** 173,199 ****
XX  int get_inode(fd, inum, ip)
XX  int fd;
XX  ino_t inum;
XX! d_inode *ip;
XX  
XX  /* Get inode `inum' from the MINIX filesystem. (Uses the inode-cache) */
XX  {
XX    struct buf bp;
XX!   block_nr block;
XX!   block_nr ino_block;
XX!   unshort ino_offset;
XX!   int r;
XX  
XX    /* Calculate start of i-list */
XX    block = SUPER_BLOCK + 1 + sb.s_imap_blocks + sb.s_zmap_blocks;
XX  
XX    /* Calculate block with inode inum */
XX!   ino_block = ((inum - 1) / INODES_PER_BLOCK);
XX!   ino_offset = ((inum - 1) % INODES_PER_BLOCK);
XX    block += ino_block;
XX  
XX    /* Fetch the block */
XX    if (get_block(fd, block, &bp, B_INODE) == 0) {
XX! 	bcopy(&bp.b_inode[ino_offset], ip, sizeof(d_inode));
XX  	return(0);
XX    }
XX  
XX--- 200,225 ----
XX  int get_inode(fd, inum, ip)
XX  int fd;
XX  ino_t inum;
XX! d1_inode *ip;
XX  
XX  /* Get inode `inum' from the MINIX filesystem. (Uses the inode-cache) */
XX  {
XX    struct buf bp;
XX!   block_t block;
XX!   block_t ino_block;
XX!   unsigned short ino_offset;
XX  
XX    /* Calculate start of i-list */
XX    block = SUPER_BLOCK + 1 + sb.s_imap_blocks + sb.s_zmap_blocks;
XX  
XX    /* Calculate block with inode inum */
XX!   ino_block = ((inum - 1) / inodes_per_block);
XX!   ino_offset = ((inum - 1) % inodes_per_block);
XX    block += ino_block;
XX  
XX    /* Fetch the block */
XX    if (get_block(fd, block, &bp, B_INODE) == 0) {
XX! 	memcpy((void *) ip, (void *) &bp.b_v1_ino[ino_offset], sizeof(d1_inode));
XX  	return(0);
XX    }
XX  
XX***************
XX*** 204,223 ****
XX  
XX  static int indent = 0;		/* current indent (used for mkfs-listing) */
XX  
XX! dump_dir(special, ip, directory)
XX  int special;
XX! d_inode *ip;
XX! 
XX  char *directory;
XX  /* Make the given directory (if non-NULL),
XX   * and recursively extract its contents.
XX   */
XX  {
XX!   register dir_struct *dp;
XX    register int n_entries;
XX    register char *name;
XX!   block_nr b = 0;
XX!   d_inode dip;
XX    struct buf bp;
XX  
XX    if (verbose) {
XX--- 230,248 ----
XX  
XX  static int indent = 0;		/* current indent (used for mkfs-listing) */
XX  
XX! void dump_dir(special, ip, directory)
XX  int special;
XX! d1_inode *ip;
XX  char *directory;
XX  /* Make the given directory (if non-NULL),
XX   * and recursively extract its contents.
XX   */
XX  {
XX!   register struct direct *dp;
XX    register int n_entries;
XX    register char *name;
XX!   block_t b = 0;
XX!   d1_inode dip;
XX    struct buf bp;
XX  
XX    if (verbose) {
XX***************
XX*** 226,233 ****
XX    }
XX    if (!noaction && *directory) {
XX  	/* Try to make the directory if not already there */
XX! 	if (mkdir(directory) != 0 || chdir(directory) < 0) {
XX! 		fprintf(stderr, "mkdir %s failed\n", directory);
XX  		return;
XX  	}
XX    }
XX--- 251,258 ----
XX    }
XX    if (!noaction && *directory) {
XX  	/* Try to make the directory if not already there */
XX! 	if (Mkdir(directory) != 0 || chdir(directory) < 0) {
XX! 		fprintf(stderr, "Mkdir %s failed\n", directory);
XX  		return;
XX  	}
XX    }
XX***************
XX*** 235,266 ****
XX  	;
XX    *name++ = '/';		/* Add trailing slash */
XX  
XX!   n_entries = (int) (ip->i_size / (off_t) sizeof(dir_struct));
XX    while (n_entries > 0) {
XX  
XX  	/* Read next block of the directory */
XX  	if (get_fileblock(special, ip, b, &bp) < 0) return;
XX  	dp = &bp.b_dir[0];
XX! 	if (b++ == (block_nr) 0) {
XX  		dp += 2;	/* Skip "." and ".." */
XX  		n_entries -= 2;
XX  	}
XX  
XX  	/* Extract the files/directories listed in the block */
XX  	while (n_entries-- > 0 && dp < &bp.b_dir[NR_DIR_ENTRIES]) {
XX! 		if (dp->d_inum != (ino_t) 0) {
XX! 			if (get_inode(special, dp->d_inum, &dip) < 0) {
XX  				/* Bad luck */
XX  				dp++;
XX  				continue;
XX  			}
XX  
XX  			/* Add new pathname-component to `pathname'. */
XX! 			strncpy(name, dp->d_name, NAME_MAX);
XX  			name[NAME_MAX] = '\0';
XX  
XX  			/* Call the right routine */
XX! 			if ((dip.i_mode & I_TYPE) == I_DIRECTORY)
XX  				dump_dir(special, &dip, name);
XX  			else
XX  				dump_file(special, &dip, name);
XX--- 260,291 ----
XX  	;
XX    *name++ = '/';		/* Add trailing slash */
XX  
XX!   n_entries = (int) (ip->d1_size / (off_t) sizeof(struct direct));
XX    while (n_entries > 0) {
XX  
XX  	/* Read next block of the directory */
XX  	if (get_fileblock(special, ip, b, &bp) < 0) return;
XX  	dp = &bp.b_dir[0];
XX! 	if (b++ == (block_t) 0) {
XX  		dp += 2;	/* Skip "." and ".." */
XX  		n_entries -= 2;
XX  	}
XX  
XX  	/* Extract the files/directories listed in the block */
XX  	while (n_entries-- > 0 && dp < &bp.b_dir[NR_DIR_ENTRIES]) {
XX! 		if (dp->d_ino != (ino_t) 0) {
XX! 			if (get_inode(special, dp->d_ino, &dip) < 0) {
XX  				/* Bad luck */
XX  				dp++;
XX  				continue;
XX  			}
XX  
XX  			/* Add new pathname-component to `pathname'. */
XX! 			strncpy(name, dp->d_name, (size_t) NAME_MAX);
XX  			name[NAME_MAX] = '\0';
XX  
XX  			/* Call the right routine */
XX! 			if ((dip.d1_mode & I_TYPE) == I_DIRECTORY)
XX  				dump_dir(special, &dip, name);
XX  			else
XX  				dump_file(special, &dip, name);
XX***************
XX*** 279,298 ****
XX    }
XX  }
XX  
XX! dump_file(special, ip, filename)
XX  int special;
XX! d_inode *ip;
XX  char *filename;
XX  /* Extract given filename from the MINIX-filesystem,
XX   * and store it on the local filesystem.
XX   */
XX  {
XX-   dir_struct *dp;
XX    int file;
XX!   block_nr b = 0;
XX    struct buf bp;
XX    off_t size;
XX  
XX    if (verbose) show_info(filename, ip, pathname);
XX  
XX    if (noaction) return(0);
XX--- 304,324 ----
XX    }
XX  }
XX  
XX! int dump_file(special, ip, filename)
XX  int special;
XX! d1_inode *ip;
XX  char *filename;
XX  /* Extract given filename from the MINIX-filesystem,
XX   * and store it on the local filesystem.
XX   */
XX  {
XX    int file;
XX!   block_t b = 0;
XX    struct buf bp;
XX    off_t size;
XX  
XX+   if (nofiles && (ip->d1_mode & I_TYPE) == I_REGULAR) return(0);
XX+ 
XX    if (verbose) show_info(filename, ip, pathname);
XX  
XX    if (noaction) return(0);
XX***************
XX*** 302,315 ****
XX  	fprintf(stderr, "Will not create %s: file exists\n", filename);
XX  	return(-1);
XX    }
XX!   if ((file = creat(filename, (ip->i_mode & ALL_MODES))) < 0) {
XX  	fprintf(stderr, "cannot create %s\n", filename);
XX  	return(-1);
XX    }
XX  
XX    /* Don't try to extract /dev/hd0 */
XX!   if ((ip->i_mode & I_TYPE) == I_REGULAR) {
XX! 	size = ip->i_size;
XX  	while (size > (off_t) 0) {
XX  		/* Get next block of file */
XX  		if (get_fileblock(special, ip, b++, &bp) < 0) {
XX--- 328,341 ----
XX  	fprintf(stderr, "Will not create %s: file exists\n", filename);
XX  	return(-1);
XX    }
XX!   if ((file = creat(filename, (ip->d1_mode & ALL_MODES))) < 0) {
XX  	fprintf(stderr, "cannot create %s\n", filename);
XX  	return(-1);
XX    }
XX  
XX    /* Don't try to extract /dev/hd0 */
XX!   if ((ip->d1_mode & I_TYPE) == I_REGULAR) {
XX! 	size = ip->d1_size;
XX  	while (size > (off_t) 0) {
XX  		/* Get next block of file */
XX  		if (get_fileblock(special, ip, b++, &bp) < 0) {
XX***************
XX*** 333,388 ****
XX  
XX  int get_fileblock(special, ip, b, bp)
XX  int special;
XX! d_inode *ip;
XX! block_nr b;
XX  struct buf *bp;
XX  /* Read the `b'-th block from the file whose inode is `ip'. */
XX  {
XX!   zone_nr zone, ind_zone;
XX!   block_nr z, zone_index;
XX    int r;
XX  
XX    /* Calculate zone in which the datablock number is contained */
XX!   zone = (zone_nr) (b >> zone_shift);
XX  
XX    /* Calculate index of the block number in the zone */
XX!   zone_index = b - ((block_nr) zone << zone_shift);
XX  
XX    /* Go get the zone */
XX!   if (zone < (zone_nr) NR_DZONE_NUM) {	/* direct block */
XX! 	zone = ip->i_zone[zone];
XX! 	z = ((block_nr) zone << zone_shift) + zone_index;
XX  	r = get_block(special, z, bp, B_DATA);
XX  	return(r);
XX    }
XX  
XX    /* The zone is not a direct one */
XX!   zone -= (zone_nr) NR_DZONE_NUM;
XX  
XX    /* Is it single indirect ? */
XX!   if (zone < (zone_nr) NR_INDIRECTS) {	/* single indirect block */
XX! 	ind_zone = ip->i_zone[NR_DZONE_NUM];
XX    } else {			/* double indirect block */
XX  	/* Fetch the double indirect block */
XX! 	ind_zone = ip->i_zone[NR_DZONE_NUM + 1];
XX! 	z = (block_nr) ind_zone << zone_shift;
XX  	r = get_block(special, z, bp, B_INDIRECT);
XX  	if (r < 0) return(r);
XX  
XX  	/* Extract the indirect zone number from it */
XX! 	zone -= (zone_nr) NR_INDIRECTS;
XX! 	ind_zone = bp->b_ind[zone / (zone_nr) NR_INDIRECTS];
XX! 	zone %= (zone_nr) NR_INDIRECTS;
XX    }
XX  
XX    /* Extract the datablock number from the indirect zone */
XX!   z = (block_nr) ind_zone << zone_shift;
XX    r = get_block(special, z, bp, B_INDIRECT);
XX    if (r < 0) return(r);
XX-   zone = bp->b_ind[zone];
XX  
XX    /* Calculate datablock number to be fetched */
XX!   z = ((block_nr) zone << zone_shift) + zone_index;
XX    r = get_block(special, z, bp, B_DATA);
XX    return(r);
XX  }
XX--- 359,418 ----
XX  
XX  int get_fileblock(special, ip, b, bp)
XX  int special;
XX! d1_inode *ip;
XX! block_t b;
XX  struct buf *bp;
XX  /* Read the `b'-th block from the file whose inode is `ip'. */
XX  {
XX!   zone_t zone, ind_zone;
XX!   block_t z, zone_index;
XX    int r;
XX  
XX    /* Calculate zone in which the datablock number is contained */
XX!   zone = (zone_t) (b >> zone_shift);
XX  
XX    /* Calculate index of the block number in the zone */
XX!   zone_index = b - ((block_t) zone << zone_shift);
XX  
XX    /* Go get the zone */
XX!   if (zone < (zone_t) V1_NR_DZONES) {	/* direct block */
XX! 	zone = ip->d1_zone[(int) zone];
XX! 	z = ((block_t) zone << zone_shift) + zone_index;
XX  	r = get_block(special, z, bp, B_DATA);
XX  	return(r);
XX    }
XX  
XX    /* The zone is not a direct one */
XX!   zone -= (zone_t) V1_NR_DZONES;
XX  
XX    /* Is it single indirect ? */
XX!   if (zone < (zone_t) V1_INDIRECTS) {	/* single indirect block */
XX! 	ind_zone = ip->d1_zone[V1_NR_DZONES];
XX    } else {			/* double indirect block */
XX  	/* Fetch the double indirect block */
XX! 	ind_zone = ip->d1_zone[V1_NR_DZONES + 1];
XX! 	z = (block_t) ind_zone << zone_shift;
XX  	r = get_block(special, z, bp, B_INDIRECT);
XX  	if (r < 0) return(r);
XX  
XX  	/* Extract the indirect zone number from it */
XX! 	zone -= (zone_t) V1_INDIRECTS;
XX! 
XX! 	/* The next line assumes a V1 file system only! */
XX! 	ind_zone = bp->b_v1_ind[(int) (zone / V1_INDIRECTS)];
XX! 	zone %= (zone_t) V1_INDIRECTS;
XX    }
XX  
XX    /* Extract the datablock number from the indirect zone */
XX!   z = (block_t) ind_zone << zone_shift;
XX    r = get_block(special, z, bp, B_INDIRECT);
XX    if (r < 0) return(r);
XX  
XX+   /* The next line assumes a V1 file system only! */
XX+   zone = bp->b_v1_ind[(int) zone];
XX+ 
XX    /* Calculate datablock number to be fetched */
XX!   z = ((block_t) zone << zone_shift) + zone_index;
XX    r = get_block(special, z, bp, B_DATA);
XX    return(r);
XX  }
XX***************
XX*** 393,399 ****
XX   */
XX  
XX  struct cache_block {
XX!   block_nr b_block;		/* block number of block */
XX    long b_access;		/* counter value of last access */
XX    char b_buf[BLOCK_SIZE];	/* buffer for block */
XX  };
XX--- 423,429 ----
XX   */
XX  
XX  struct cache_block {
XX!   block_t b_block;		/* block number of block */
XX    long b_access;		/* counter value of last access */
XX    char b_buf[BLOCK_SIZE];	/* buffer for block */
XX  };
XX***************
XX*** 405,413 ****
XX  static long counter = 0L;	/* Counter used as a sense of time. */
XX   /* Incremented after each cache operation. */
XX  
XX! get_block(fd, block, bp, type)
XX  int fd;
XX! block_nr block;
XX  struct buf *bp;
XX  int type;
XX  /* Get the requested block from the device with filedescriptor fd.
XX--- 435,443 ----
XX  static long counter = 0L;	/* Counter used as a sense of time. */
XX   /* Incremented after each cache operation. */
XX  
XX! int get_block(fd, block, bp, type)
XX  int fd;
XX! block_t block;
XX  struct buf *bp;
XX  int type;
XX  /* Get the requested block from the device with filedescriptor fd.
XX***************
XX*** 418,430 ****
XX    register int i;
XX    register struct cache_block *cache_p, *cp;
XX  
XX!   if (block == (block_nr) NO_ZONE) {
XX  	/* Should never happen in a good filesystem. */
XX  	fprintf(stderr, "get_block: NO_ZONE requested !\n");
XX  	return(-1);
XX    }
XX    if (type < 0 || type >= NR_CACHES)	/* No cache for this type */
XX! 	return(get_rawblock(fd, block, bp));
XX  
XX    cache_p = cache[type];
XX    cp = (struct cache_block *) 0;
XX--- 448,460 ----
XX    register int i;
XX    register struct cache_block *cache_p, *cp;
XX  
XX!   if (block == (block_t) NO_ZONE) {
XX  	/* Should never happen in a good filesystem. */
XX  	fprintf(stderr, "get_block: NO_ZONE requested !\n");
XX  	return(-1);
XX    }
XX    if (type < 0 || type >= NR_CACHES)	/* No cache for this type */
XX! 	return(get_rawblock(fd, block, (char *) bp));
XX  
XX    cache_p = cache[type];
XX    cp = (struct cache_block *) 0;
XX***************
XX*** 450,466 ****
XX    /* Update/store last access counter */
XX    cp->b_access = ++counter;
XX    cp->b_block = block;
XX!   bcopy(cp->b_buf, bp, BLOCK_SIZE);
XX    return(0);
XX  }
XX  
XX  int get_rawblock(special, blockno, bufp)
XX  int special;
XX! block_nr blockno;
XX  char *bufp;
XX  /* Read a block from the disk. */
XX  {
XX-   int r;
XX    off_t pos;
XX  
XX    /* Calculate the position of the block on the disk */
XX--- 480,495 ----
XX    /* Update/store last access counter */
XX    cp->b_access = ++counter;
XX    cp->b_block = block;
XX!   memcpy((void *) bp, (void *) cp->b_buf, BLOCK_SIZE);
XX    return(0);
XX  }
XX  
XX  int get_rawblock(special, blockno, bufp)
XX  int special;
XX! block_t blockno;
XX  char *bufp;
XX  /* Read a block from the disk. */
XX  {
XX    off_t pos;
XX  
XX    /* Calculate the position of the block on the disk */
XX***************
XX*** 476,484 ****
XX    return(-1);
XX  }
XX  
XX! restore(name, ip)
XX  char *name;
XX! d_inode *ip;
XX  /* Restores given file's attributes.
XX   * `ip' contains the attributes of the file on the MINIX filesystem,
XX   * `name' is the filename of the extracted file on the local filesystem.
XX--- 505,513 ----
XX    return(-1);
XX  }
XX  
XX! void restore(name, ip)
XX  char *name;
XX! d1_inode *ip;
XX  /* Restores given file's attributes.
XX   * `ip' contains the attributes of the file on the MINIX filesystem,
XX   * `name' is the filename of the extracted file on the local filesystem.
XX***************
XX*** 486,495 ****
XX  {
XX    long ttime[2];
XX  
XX!   chown(name, ip->i_uid, ip->i_gid);	/* Fails if not superuser */
XX!   chmod(name, (ip->i_mode & ALL_MODES));
XX!   ttime[0] = ttime[1] = ip->i_mtime;
XX!   utime(name, ttime);
XX  }
XX  
XX  /* Characters to use as prefix to `mkfs' mode field */
XX--- 515,524 ----
XX  {
XX    long ttime[2];
XX  
XX!   chown(name, ip->d1_uid, ip->d1_gid);	/* Fails if not superuser */
XX!   chmod(name, (ip->d1_mode & ALL_MODES));
XX!   ttime[0] = ttime[1] = ip->d1_mtime;
XX!   utime(name, (struct utimbuf *) ttime);
XX  }
XX  
XX  /* Characters to use as prefix to `mkfs' mode field */
XX***************
XX*** 501,537 ****
XX  		       'b'	/* I_BLOCK_SPECIAL */
XX  };
XX  
XX! show_info(name, ip, path)
XX  char *name;
XX! d_inode *ip;
XX  char *path;
XX  /* Show information about the given file/dir in `mkfs'-format */
XX  {
XX    char c1, c2, c3;
XX  
XX!   c1 = special_chars[(ip->i_mode >> 13) & 03];
XX!   c2 = ((ip->i_mode & ALL_MODES & ~RWX_MODES) == I_SET_UID_BIT) ? 'u' : '-';
XX!   c3 = ((ip->i_mode & ALL_MODES & ~RWX_MODES) == I_SET_GID_BIT) ? 'g' : '-';
XX  
XX    if (*name) {
XX  	do_indent(indent);
XX  	printf("%-14s ", name);
XX    }
XX    printf("%c%c%c%03o %d %d", c1, c2, c3,
XX!          (ip->i_mode & RWX_MODES), ip->i_uid, ip->i_gid);
XX  
XX!   switch (ip->i_mode & I_TYPE) {
XX        case I_DIRECTORY:
XX  	break;
XX        case I_CHAR_SPECIAL:	/* Print major and minor dev numbers */
XX! 	printf(" %d %d", (ip->i_zone[0] >> MAJOR) & 0377,
XX! 	       (ip->i_zone[0] >> MINOR) & 0377);
XX  	break;
XX        case I_BLOCK_SPECIAL:	/* Print major and minor dev numbers */
XX! 	printf(" %d %d", (ip->i_zone[0] >> MAJOR) & 0377,
XX! 	       (ip->i_zone[0] >> MINOR) & 0377);
XX  	/* Also print the number of blocks on the device */
XX! 	printf(" %ld", (ip->i_size / (off_t) BLOCK_SIZE));
XX  	break;
XX        default:			/* Just print the pathname */
XX  	printf(" %s", path);
XX--- 530,566 ----
XX  		       'b'	/* I_BLOCK_SPECIAL */
XX  };
XX  
XX! void show_info(name, ip, path)
XX  char *name;
XX! d1_inode *ip;
XX  char *path;
XX  /* Show information about the given file/dir in `mkfs'-format */
XX  {
XX    char c1, c2, c3;
XX  
XX!   c1 = special_chars[(ip->d1_mode >> 13) & 03];
XX!   c2 = ((ip->d1_mode & ALL_MODES & ~RWX_MODES) == I_SET_UID_BIT) ? 'u' : '-';
XX!   c3 = ((ip->d1_mode & ALL_MODES & ~RWX_MODES) == I_SET_GID_BIT) ? 'g' : '-';
XX  
XX    if (*name) {
XX  	do_indent(indent);
XX  	printf("%-14s ", name);
XX    }
XX    printf("%c%c%c%03o %d %d", c1, c2, c3,
XX!          (ip->d1_mode & RWX_MODES), ip->d1_uid, ip->d1_gid);
XX  
XX!   switch (ip->d1_mode & I_TYPE) {
XX        case I_DIRECTORY:
XX  	break;
XX        case I_CHAR_SPECIAL:	/* Print major and minor dev numbers */
XX! 	printf(" %d %d", (ip->d1_zone[0] >> MAJOR) & 0377,
XX! 	       (ip->d1_zone[0] >> MINOR) & 0377);
XX  	break;
XX        case I_BLOCK_SPECIAL:	/* Print major and minor dev numbers */
XX! 	printf(" %d %d", (ip->d1_zone[0] >> MAJOR) & 0377,
XX! 	       (ip->d1_zone[0] >> MINOR) & 0377);
XX  	/* Also print the number of blocks on the device */
XX! 	printf(" %ld", (ip->d1_size / (off_t) BLOCK_SIZE));
XX  	break;
XX        default:			/* Just print the pathname */
XX  	printf(" %s", path);
XX***************
XX*** 542,555 ****
XX  
XX  #define	INDENT_SIZE	4
XX  
XX! do_indent(i)
XX  int i;
XX  {
XX    i *= INDENT_SIZE;
XX    while (i-- > 0) putchar(' ');
XX  }
XX  
XX! int mkdir(directory)
XX  char *directory;
XX  /* Make a directory, return exit status.
XX   * This routine is not necessary on systems that
XX--- 571,584 ----
XX  
XX  #define	INDENT_SIZE	4
XX  
XX! void do_indent(i)
XX  int i;
XX  {
XX    i *= INDENT_SIZE;
XX    while (i-- > 0) putchar(' ');
XX  }
XX  
XX! int Mkdir(directory)
XX  char *directory;
XX  /* Make a directory, return exit status.
XX   * This routine is not necessary on systems that
XX***************
XX*** 559,579 ****
XX    int pid, status;
XX  
XX    if ((pid = fork()) == 0) {
XX! 	execl("/bin/mkdir", "mkdir", directory, (char *) 0);
XX! 	execl("/usr/bin/mkdir", "mkdir", directory, (char *) 0);
XX  	exit(1);
XX    } else if (pid < 0)
XX  	return(-1);
XX    while (wait(&status) != pid);
XX    return(status);
XX- }
XX- 
XX- bcopy(src, dest, bytes)
XX- register char *src, *dest;
XX- register int bytes;
XX- /* Copy bytes from src to dest.
XX-  * May also be in the standard libc.a on some systems.
XX-  */
XX- {
XX-   while (bytes--) *dest++ = *src++;
XX  }
XX--- 588,598 ----
XX    int pid, status;
XX  
XX    if ((pid = fork()) == 0) {
XX! 	execl("/bin/Mkdir", "Mkdir", directory, (char *) 0);
XX! 	execl("/usr/bin/Mkdir", "Mkdir", directory, (char *) 0);
XX  	exit(1);
XX    } else if (pid < 0)
XX  	return(-1);
XX    while (wait(&status) != pid);
XX    return(status);
XX  }
X/
Xecho x - recover.c.d
Xsed '/^X/s///' > recover.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/recover.c  crc=20724   1170	Sun Apr 25 21:35:14 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/recover.c  crc=18393   1339	Wed Nov  4 04:19:19 1992
XX***************
XX*** 17,23 ****
XX   * last two characters, in fact, play no role in locating the file.
XX   */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 17,30 ----
XX   * last two characters, in fact, play no role in locating the file.
XX   */
XX  
XX! #include <stdlib.h>
XX! #include <string.h>
XX! #include <minix/minlib.h>
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 31,40 ****
XX  	strcat(buf, argv[i]);
XX  	system(buf);
XX    }
XX  }
XX  
XX  
XX! usage()
XX  {
XX    std_err("Usage: recover file ...\n");
XX    exit(1);
XX--- 38,48 ----
XX  	strcat(buf, argv[i]);
XX  	system(buf);
XX    }
XX+   return(0);
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    std_err("Usage: recover file ...\n");
XX    exit(1);
X/
Xecho x - rev.c.d
Xsed '/^X/s///' > rev.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/rev.c  crc=57113   1420	Sun Apr 25 21:35:14 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/rev.c  crc=04530   1611	Wed Nov  4 04:19:19 1992
XX***************
XX*** 3,17 ****
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <blocksize.h>
XX  
XX  #ifndef EOF
XX  #define	EOF	((char) -1)
XX  #endif
XX  
XX  
XX  int fd;				/* File descriptor from file being read */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 3,23 ----
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <blocksize.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX  
XX  #ifndef EOF
XX  #define	EOF	((char) -1)
XX  #endif
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void rev, (void));
XX+ _PROTOTYPE(int nextchar, (void));
XX  
XX  int fd;				/* File descriptor from file being read */
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 32,44 ****
XX  	rev();
XX  	close(fd);
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX  
XX  
XX! rev()
XX  {
XX    char output[BLOCK_SIZE];	/* Contains a reversed line */
XX    register unsigned short i;	/* Index in output array */
XX--- 38,50 ----
XX  	rev();
XX  	close(fd);
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX  
XX  
XX! void rev()
XX  {
XX    char output[BLOCK_SIZE];	/* Contains a reversed line */
XX    register unsigned short i;	/* Index in output array */
XX***************
XX*** 53,62 ****
XX  }
XX  
XX  
XX- 
XX- 
XX  char buf[BLOCK_SIZE];
XX! nextchar()
XX  {				/* Does a sort of buffered I/O */
XX    static int n = 0;		/* Read count */
XX    static int i;			/* Index in input buffer to next character */
XX--- 59,67 ----
XX  }
XX  
XX  
XX  char buf[BLOCK_SIZE];
XX! 
XX! int nextchar()
XX  {				/* Does a sort of buffered I/O */
XX    static int n = 0;		/* Read count */
XX    static int i;			/* Index in input buffer to next character */
X/
Xecho x - rm.c.d
Xsed '/^X/s///' > rm.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/rm.c  crc=63523   2625	Sun Apr 25 21:35:15 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/rm.c  crc=49450   5331	Wed Nov  4 04:19:19 1992
XX***************
XX*** 1,152 ****
XX! /* rm - remove files			Author: Adri Koppes */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX! #include <sys/dir.h>
XX  
XX  int errors = 0;
XX  int fflag = 0;
XX  int iflag = 0;
XX  int rflag = 0;
XX! int exstatus;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   char *opt;
XX  
XX!   if (argc < 2) usage();
XX!   *++argv;
XX!   --argc;
XX!   while (**argv == '-') {
XX! 	opt = *argv;
XX! 	while (*++opt != '\0') switch (*opt) {
XX! 		    case 'f':	fflag++;	break;
XX! 		    case 'i':	iflag++;	break;
XX! 		    case 'r':	rflag++;	break;
XX! 		    default:
XX! 			std_err("rm: unknown option\n");
XX! 			usage();
XX! 			break;
XX! 		}
XX! 	argc--;
XX! 	*++argv;
XX!   }
XX!   if (argc < 1) usage();
XX!   while (argc--) remove(*argv++);
XX!   exstatus = (errors == 0 ? 0 : 1);
XX!   if (fflag) exstatus = 0;
XX!   exit(exstatus);
XX  }
XX  
XX! usage()
XX  {
XX!   std_err("Usage: rm [-fir] file\n");
XX    exit(1);
XX  }
XX  
XX! remove(name)
XX  char *name;
XX  {
XX!   struct stat s;
XX!   struct direct d;
XX!   char rname[128], *strcpy(), *strcat();
XX!   int fd;
XX  
XX!   if (stat(name, &s)) {
XX! 	if (!fflag) stderr3("rm: ", name, " non-existent\n");
XX! 	errors++;
XX  	return;
XX    }
XX!   if (iflag) {
XX! 	stderr3("rm: remove ", name, "? ");
XX! 	if (!confirm()) return;
XX    }
XX!   if ((s.st_mode & S_IFMT) == S_IFDIR) {
XX! 	if (rflag) {
XX! 		if ((fd = open(name, 0)) < 0) {
XX! 			if (!fflag) stderr3("rm: can't open ", name, "\n");
XX! 			errors++;
XX  			return;
XX  		}
XX! 		while (read(fd, (char *) &d, sizeof(struct direct)) > 0) {
XX! 			if (d.d_ino && strcmp("..", d.d_name) && strcmp(".", d.d_name)) {
XX! 				strcpy(rname, name);
XX! 				strcat(rname, "/");
XX! 				strncat(rname, d.d_name, DIRSIZ);
XX! 				remove(rname);
XX! 			}
XX! 		}
XX! 		close(fd);
XX! 		rem_dir(name);
XX! 	} else {
XX! 		if (!fflag) stderr3("rm: ", name, " is a directory\n");
XX! 		errors++;
XX  		return;
XX  	}
XX!   } else {
XX! 	if (access(name, 2) && !fflag) {
XX! 		stderr3("rm: remove ", name, " (mode = ");
XX! 		octal(s.st_mode & 0777);
XX! 		std_err(") ? ");
XX! 		if (!confirm()) return;
XX  	}
XX  	if (unlink(name)) {
XX! 		if (!fflag) stderr3("rm: ", name, " not removed\n");
XX! 		errors++;
XX  	}
XX    }
XX  }
XX  
XX- rem_dir(name)
XX- char *name;
XX- {
XX-   int status;
XX  
XX!   switch (fork()) {
XX!       case -1:
XX! 	std_err("rm: can't fork\n");
XX! 	errors++;
XX! 	return;
XX!       case 0:
XX! 	execl("/bin/rmdir", "rmdir", name, (char *) 0);
XX! 	execl("/usr/bin/rmdir", "rmdir", name, (char *) 0);
XX! 	std_err("rm: can't exec rmdir\n");
XX! 	exit(1);
XX!       default:
XX! 	wait(&status);
XX! 	errors += status;
XX!   }
XX! }
XX! 
XX! confirm()
XX  {
XX!   char c, t;
XX!   read(0, &c, 1);
XX!   t = c;
XX!   do
XX! 	read(0, &t, 1);
XX!   while (t != '\n' && t != -1);
XX!   return(c == 'y' || c == 'Y');
XX  }
XX  
XX- octal(num)
XX- unsigned int num;
XX- {
XX-   char a[4];
XX  
XX!   a[0] = (((num >> 6) & 7) + '0');
XX!   a[1] = (((num >> 3) & 7) + '0');
XX!   a[2] = ((num & 7) + '0');
XX!   a[3] = 0;
XX!   std_err(a);
XX! }
XX! 
XX! stderr3(s1, s2, s3)
XX! char *s1, *s2, *s3;
XX  {
XX!   std_err(s1);
XX!   std_err(s2);
XX!   std_err(s3);
XX  }
XX--- 1,274 ----
XX! /* rm - remove directory entries	Author: V. Archer */
XX  
XX+ /* Copyright 1991 by Vincent Archer
XX+  *	You may freely redistribute this software, in source or binary
XX+  *	form, provided that you do not alter this copyright mention in any
XX+  *	way.
XX+  */
XX+ 
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX! #include <sys/wait.h>
XX! #include <minix/minlib.h>
XX! #include <dirent.h>
XX! #include <limits.h>
XX! #include <errno.h>
XX! #include <stdlib.h>
XX! #include <string.h>
XX! #include <unistd.h>
XX! #include <stdio.h>
XX  
XX+ 
XX+ /* Global variables. */
XX  int errors = 0;
XX  int fflag = 0;
XX  int iflag = 0;
XX  int rflag = 0;
XX! int tflag = -1;
XX! char *pgm;
XX! char path[PATH_MAX + 1];
XX! struct stat st;
XX  
XX! extern int optind, opterr;
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int negative, (void));
XX! _PROTOTYPE(char *octal, (Mode_t num));
XX! _PROTOTYPE(void rm_fork, (char *dir));
XX! _PROTOTYPE(void removal, (char *name));
XX! _PROTOTYPE(void stdprot, (char *name, char *prompt, Mode_t mode));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! /* Main module. The internal '-t' flag is set if the file descriptor 0 is a
XX!  * tty, rather than from the command line options. It is not used when '-f'
XX!  * is specified.
XX!  */
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int c;
XX  
XX!   if (argc == 2 && *(argv[1]) == '-')
XX! 	usage();		/* file name required */
XX!   pgm = argv[0];
XX!   opterr = 0;
XX!   while ((c = getopt(argc, argv, "Rfir")) != EOF) switch (c) {
XX! 	    case 'f':
XX! 		fflag = 1;
XX! 		iflag = 0;
XX! 		break;
XX! 	    case 'i':
XX! 		iflag = 1;
XX! 		fflag = 0;
XX! 		break;
XX! 	    case 'R':
XX! 	    case 'r':	rflag = 1;	break;
XX! 	    default:	usage();
XX! 	}
XX!   if (optind >= argc) usage();
XX! 
XX!   tflag = isatty(0);
XX!   while (optind < argc) removal(argv[optind++]);
XX! 
XX!   return(errors);
XX  }
XX  
XX! 
XX! /* Wait for a user answer from the stdin stream (but do not use stdio which
XX!  * is bulky and unneeded in most tools). An error (or end of file) on file
XX!  * descriptor 0 is assumed to mean a NEGATIVE answer. LC_* locale could be
XX!  * handled here.
XX!  */
XX! int negative()
XX  {
XX!   char c, t;
XX! 
XX!   if (read(0, &c, 1) != 1) return(1);
XX!   t = c;
XX!   while (t != '\n')
XX! 	if (read(0, &t, 1) != 1) break;
XX!   return(c != 'y' && c != 'Y');
XX! }
XX! 
XX! 
XX! /* Quick transformation of a mode_t in 3-digits octal form. */
XX! char *octal(num)
XX! mode_t num;
XX! {
XX!   static char a[4];
XX! 
XX!   a[0] = (((num >> 6) & 7) + '0');
XX!   a[1] = (((num >> 3) & 7) + '0');
XX!   a[2] = ((num & 7) + '0');
XX!   a[3] = 0;
XX!   return(a);
XX! }
XX! 
XX! 
XX! /* P1003.2 requires "rm -r directory" to be able to descend to arbitrary
XX!  *	depth if a file hierarchy, and not to fail due to file descriptors
XX!  *	loss or path length limitations (except PATH_MAX). (4.53.2)
XX!  */
XX! void rm_fork(dir)
XX! char *dir;
XX! {
XX!   pid_t pid, pid2;
XX!   int status;
XX!   int i;
XX!   char options[4];
XX! 
XX!   if (pid = fork()) {
XX! 	if (pid < 0) {
XX! 		perror("fork()");
XX! 		errors = 1;
XX! 		return;
XX! 	}
XX! 	while ((pid2 = wait(&status)) != pid)
XX! 		if (pid2 < 0) {
XX! 			errors = 1;
XX! 			return;
XX! 		}
XX! 	if (!WIFEXITED(status) || WEXITSTATUS(status)) errors = 1;
XX! 	return;
XX!   }
XX!   for (i = 3; i < OPEN_MAX; i++) close(i);
XX!   options[0] = '-';
XX!   options[1] = 'R';
XX!   options[3] = '\0';
XX!   if (fflag)
XX! 	options[2] = 'f';
XX!   else if (iflag)
XX! 	options[2] = 'i';
XX!   else
XX! 	options[2] = '\0';
XX!   execlp(pgm, pgm, options, dir, (char *) 0);
XX! 
XX!   std_err(dir);
XX!   std_err(": ");
XX!   perror(pgm);
XX    exit(1);
XX  }
XX  
XX! 
XX! /* Remove a single argument, as prescribed in P1003.2 (4.53.2) */
XX! void removal(name)
XX  char *name;
XX  {
XX!   DIR *dirp;
XX!   struct dirent *entp;
XX!   char *namp;
XX  
XX!   if (
XX! #ifdef S_IFLNK
XX!       lstat(name, &st)
XX! #else
XX!       stat(name, &st)
XX! #endif
XX! 	) {
XX! 	if (!fflag) {
XX! 		perror(name);
XX! 		errors = 1;
XX! 	}
XX  	return;
XX    }
XX!   if (namp = strrchr(name, '/'))
XX! 	namp++;
XX!   else
XX! 	namp = name;
XX!   if (namp[0] == '.' &&
XX!       (!namp[1] || (namp[1] == '.' && !namp[2]))) {
XX! 	std_err(name);
XX! 	std_err(": cannot remove\n");
XX! 	errors = 1;
XX! 	return;
XX    }
XX!   if (S_ISDIR(st.st_mode)) {
XX! 	if (!rflag) {
XX! 		errno = EISDIR;
XX! 		perror(name);
XX! 		errors = 1;
XX! 		return;
XX! 	}
XX! 	if (!fflag)
XX! 		if (access(name, 2) && tflag) {
XX! 			stdprot(name, ": remove contents", st.st_mode);
XX! 			if (negative()) return;
XX! 		} else if (iflag) {
XX! 			std_err(name);
XX! 			std_err(": remove contents ? ");
XX! 			if (negative()) return;
XX! 		}
XX! 	if (!(dirp = opendir(name))) {
XX! 		if (errno != EMFILE) {
XX! 			perror(name);
XX! 			errors = 1;
XX  			return;
XX  		}
XX! 		rm_fork(name);
XX  		return;
XX+ 	} else {
XX+ 		if (name != path) strcpy(path, name);
XX+ 		namp = path + strlen(path);
XX+ 		*namp++ = '/';
XX+ 		while (entp = readdir(dirp))
XX+ 			if (entp->d_name[0] != '.' ||
XX+ 			    (entp->d_name[1] &&
XX+ 			     (entp->d_name[1] != '.' || entp->d_name[2]))) {
XX+ 				strcpy(namp, entp->d_name);
XX+ 				removal(path);
XX+ 			}
XX+ 		closedir(dirp);
XX+ 		*--namp = '\0';
XX  	}
XX! 	if (iflag) {
XX! 		std_err(name);
XX! 		std_err(": remove directory ? ");
XX! 		if (negative()) return;
XX  	}
XX+ 	if (rmdir(name)) {
XX+ 		perror(name);
XX+ 		errors = 1;
XX+ 	}
XX+   } else {
XX+ 	if (!fflag)
XX+ 		if (
XX+ #ifdef S_IFLNK
XX+ 		    !S_ISLNK(st.st_mode) &&
XX+ #endif
XX+ 		    access(name, 2) && tflag) {
XX+ 			stdprot(name, ": remove", st.st_mode);
XX+ 			if (negative()) return;
XX+ 		} else if (iflag) {
XX+ 			std_err(name);
XX+ 			std_err(": remove ? ");
XX+ 			if (negative()) return;
XX+ 		}
XX  	if (unlink(name)) {
XX! 		perror(name);
XX! 		errors = 1;
XX! 		return;
XX  	}
XX    }
XX  }
XX  
XX  
XX! /* Standard prompt when mode does not allow writing to something. */
XX! void stdprot(name, prompt, mode)
XX! char *name, *prompt;
XX! mode_t mode;
XX  {
XX!   std_err(name);
XX!   std_err(prompt);
XX!   std_err(" (mode = ");
XX!   std_err(octal(mode));
XX!   std_err(") ? ");
XX  }
XX  
XX  
XX! /* Posix command prototype. */
XX! void usage()
XX  {
XX!   std_err("Usage: rm [-fiRr] file...\n");
XX!   exit(1);
XX  }
X/
Xecho x - rmdir.c.d
Xsed '/^X/s///' > rmdir.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/rmdir.c  crc=12445   4923	Sun Apr 25 21:35:15 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/rmdir.c  crc=01190   5423	Wed Nov  4 04:19:19 1992
XX***************
XX*** 1,4 ****
XX! /* rmdir - remove a directory		Author: Adri Koppes
XX  
XX  /* (modified by Paul Polderman)
XX   * (modified by Bjarne Steinsbo)	Fixed "rmdir ../anything"
XX--- 1,4 ----
XX! /* rmdir - remove a directory		Author: Adri Koppes */
XX  
XX  /* (modified by Paul Polderman)
XX   * (modified by Bjarne Steinsbo)	Fixed "rmdir ../anything"
XX***************
XX*** 13,39 ****
XX  #include <sys/dir.h>
XX  #include <limits.h>
XX  #include <string.h>
XX  
XX  int error = 0;
XX  
XX! main(argc, argv)
XX  register int argc;
XX  register char **argv;
XX  {
XX    if (argc < 2) {
XX! 	prints("Usage: rmdir dir ...\n");
XX  	exit(1);
XX    }
XX    signal(SIGHUP, SIG_IGN);
XX    signal(SIGINT, SIG_IGN);
XX    signal(SIGQUIT, SIG_IGN);
XX    signal(SIGTERM, SIG_IGN);
XX!   while (--argc) remove(*++argv);
XX    if (error) exit(1);
XX  }
XX  
XX  
XX! remove(dirname)
XX  char *dirname;
XX  {
XX    struct direct d;		/* buffer for reading directory */
XX--- 13,56 ----
XX  #include <sys/dir.h>
XX  #include <limits.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX+ #ifdef S_IFLNK
XX+ #define LSTAT lstat
XX+ #else
XX+ #define LSTAT stat
XX+ #endif
XX+ 
XX  int error = 0;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void Remove, (char *dirname));
XX! _PROTOTYPE(void stderr2, (char *s1, char *s2));
XX! _PROTOTYPE(void patch_path, (char *dir));
XX! _PROTOTYPE(void StrCpy, (char *s, char *t));
XX! 
XX! int main(argc, argv)
XX  register int argc;
XX  register char **argv;
XX  {
XX    if (argc < 2) {
XX! 	printf("Usage: rmdir dir ...\n");
XX  	exit(1);
XX    }
XX    signal(SIGHUP, SIG_IGN);
XX    signal(SIGINT, SIG_IGN);
XX    signal(SIGQUIT, SIG_IGN);
XX    signal(SIGTERM, SIG_IGN);
XX!   while (--argc) Remove(*++argv);
XX    if (error) exit(1);
XX+   return(0);
XX  }
XX  
XX  
XX! void Remove(dirname)
XX  char *dirname;
XX  {
XX    struct direct d;		/* buffer for reading directory */
XX***************
XX*** 53,59 ****
XX    }
XX  
XX    /* Does the file exist ? */
XX!   if (stat(dirname, &s)) {
XX  	stderr2(dirname, " doesn't exist\n");
XX  	error++;
XX  	return;
XX--- 70,76 ----
XX    }
XX  
XX    /* Does the file exist ? */
XX!   if (LSTAT(dirname, &s)) {
XX  	stderr2(dirname, " doesn't exist\n");
XX  	error++;
XX  	return;
XX***************
XX*** 99,105 ****
XX    }
XX  
XX    /* Are we trying to remove current directory ? */
XX!   stat(".", &cwd);
XX    if ((s.st_ino == cwd.st_ino) && (s.st_dev == cwd.st_dev)) {
XX  	std_err("rmdir: can't remove current directory\n");
XX  	error++;
XX--- 116,126 ----
XX    }
XX  
XX    /* Are we trying to remove current directory ? */
XX!   if (LSTAT(".", &cwd)) {
XX! 	std_err("rmdir: can't stat current directory\n");
XX! 	error++;
XX! 	return;
XX!   }
XX    if ((s.st_ino == cwd.st_ino) && (s.st_dev == cwd.st_dev)) {
XX  	std_err("rmdir: can't remove current directory\n");
XX  	error++;
XX***************
XX*** 141,147 ****
XX    }
XX  }
XX  
XX! stderr2(s1, s2)
XX  char *s1, *s2;
XX  {
XX    std_err("rmdir: ");
XX--- 162,168 ----
XX    }
XX  }
XX  
XX! void stderr2(s1, s2)
XX  char *s1, *s2;
XX  {
XX    std_err("rmdir: ");
XX***************
XX*** 156,162 ****
XX  #define IS_DOT(s)    (*(s) == '.' && *((s)+1) == '/')
XX  #define IS_DOTDOT(s) (*(s) == '.' && *((s)+1) == '.' && *((s)+2) == '/')
XX  
XX! patch_path(dir)
XX  char *dir;
XX  {
XX  /* Check if the path name will be invalidated when `dirname/..' and
XX--- 177,183 ----
XX  #define IS_DOT(s)    (*(s) == '.' && *((s)+1) == '/')
XX  #define IS_DOTDOT(s) (*(s) == '.' && *((s)+1) == '.' && *((s)+2) == '/')
XX  
XX! void patch_path(dir)
XX  char *dir;
XX  {
XX  /* Check if the path name will be invalidated when `dirname/..' and
XX***************
XX*** 206,212 ****
XX    }
XX  }
XX  
XX! StrCpy(s, t)
XX  register char *s, *t;
XX  {
XX  /* Overlapping copies are implemetation-dependent in strcpy, so we'll
XX--- 227,233 ----
XX    }
XX  }
XX  
XX! void StrCpy(s, t)
XX  register char *s, *t;
XX  {
XX  /* Overlapping copies are implemetation-dependent in strcpy, so we'll
X/
Xecho x - roff.c.d
Xsed '/^X/s///' > roff.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/roff.c  crc=14271  21541	Sun Apr 25 21:35:15 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/roff.c  crc=65332  23269	Mon Jan 18 18:56:09 1993
XX***************
XX*** 19,24 ****
XX--- 19,27 ----
XX  #include <sys/stat.h>
XX  #include <sgtty.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define SUFTAB	"/usr/lib/suftab"
XX***************
XX*** 67,75 ****
XX  int n_outwords;
XX  FILE *File, *Macread, *Macwrite;
XX  FILE *Save;
XX! long int teller[MAXDEPTH], ftell();
XX! char *strcat(), *strcpy(), *strend(), *strhas();
XX! char *sprintf();
XX  char *request[] = {
XX  	   "ad", "ar", "bl", "bp", "br", "cc", "ce", "de",
XX  	 "ds", "ef", "eh", "fi", "fo", "hc", "he", "hx", "hy", "ig",
XX--- 70,76 ----
XX  int n_outwords;
XX  FILE *File, *Macread, *Macwrite;
XX  FILE *Save;
XX! long int teller[MAXDEPTH];
XX  char *request[] = {
XX  	   "ad", "ar", "bl", "bp", "br", "cc", "ce", "de",
XX  	 "ds", "ef", "eh", "fi", "fo", "hc", "he", "hx", "hy", "ig",
XX***************
XX*** 77,88 ****
XX  	 "n1", "n2", "na", "ne", "nf", "ni", "nn", "nx", "of", "oh",
XX  	 "pa", "pl", "po", "ro", "sk", "sp", "ss", "ta", "tc", "ti",
XX  	   "tr", "ul", 0};
XX! char *mktemp(), *mfilnam = "/tmp/rtmXXXXXX";
XX  int c;				/* LAST CHAR READ */
XX  struct sgttyb tty;
XX- FILE *fopen();
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 78,136 ----
XX  	 "n1", "n2", "na", "ne", "nf", "ni", "nn", "nx", "of", "oh",
XX  	 "pa", "pl", "po", "ro", "sk", "sp", "ss", "ta", "tc", "ti",
XX  	   "tr", "ul", 0};
XX! char *mfilnam = "/tmp/rtmXXXXXX";
XX  int c;				/* LAST CHAR READ */
XX  struct sgttyb tty;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void mesg, (int f));
XX! _PROTOTYPE(void readfile, (void));
XX! _PROTOTYPE(int readline, (void));
XX! _PROTOTYPE(void bumpword, (void));
XX! _PROTOTYPE(void dehyph, (char *s));
XX! _PROTOTYPE(int reallen, (char *s));
XX! _PROTOTYPE(void tabulate, (void));
XX! _PROTOTYPE(int readreq, (void));
XX! _PROTOTYPE(void snset, (int *par));
XX! _PROTOTYPE(int tread, (char *s));
XX! _PROTOTYPE(void nread, (int *i));
XX! _PROTOTYPE(int snread, (int *i, int *s, int sdef));
XX! _PROTOTYPE(int cread, (int *k));
XX! _PROTOTYPE(void defmac, (void));
XX! _PROTOTYPE(void openmac, (void));
XX! _PROTOTYPE(int copyline, (void));
XX! _PROTOTYPE(void submac, (int r));
XX! _PROTOTYPE(void endmac, (void));
XX! _PROTOTYPE(void do_ta, (void));
XX! _PROTOTYPE(void do_tr, (void));
XX! _PROTOTYPE(void do_nx, (void));
XX! _PROTOTYPE(int skipsp, (void));
XX! _PROTOTYPE(void writebreak, (void));
XX! _PROTOTYPE(void blankline, (void));
XX! _PROTOTYPE(void writeline, (int adflag, int flushflag));
XX! _PROTOTYPE(void fillline, (void));
XX! _PROTOTYPE(void insrt, (int p));
XX! _PROTOTYPE(void newpage, (void));
XX! _PROTOTYPE(void beginpage, (void));
XX! _PROTOTYPE(void endpage, (void));
XX! _PROTOTYPE(void blankpage, (void));
XX! _PROTOTYPE(void waitawhile, (void));
XX! _PROTOTYPE(void nix, (int sig));
XX! _PROTOTYPE(void writetitle, (char *t));
XX! _PROTOTYPE(char *pgform, (void));
XX! _PROTOTYPE(int titlen, (char *t, int c, int k));
XX! _PROTOTYPE(void spits, (char *s));
XX! _PROTOTYPE(void spit, (int c));
XX! _PROTOTYPE(int suck, (void));
XX! _PROTOTYPE(char *strhas, (char *p, int c));
XX! _PROTOTYPE(char *strend, (char *p));
XX! _PROTOTYPE(int isspace, (int c));
XX! _PROTOTYPE(int isalnum, (int c));
XX! _PROTOTYPE(int isdigit, (int c));
XX! _PROTOTYPE(int islegal, (int c));
XX! _PROTOTYPE(void bomb, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 127,142 ****
XX    endpage();
XX    for (; o_sk; o_sk--) blankpage();
XX    mesg(1);			/* ALLOW MESSAGES */
XX!   exit(0);
XX  }
XX  
XX! mesg(f)
XX  int f;
XX  {
XX    static int mode;
XX    struct stat cbuf;
XX- /* This routine is not needed.
XX-   char *ttyname();
XX  
XX    if (!isatty(1)) return;
XX    if (!f) {
XX--- 175,188 ----
XX    endpage();
XX    for (; o_sk; o_sk--) blankpage();
XX    mesg(1);			/* ALLOW MESSAGES */
XX!   return(0);
XX  }
XX  
XX! void mesg(f)
XX  int f;
XX  {
XX    static int mode;
XX    struct stat cbuf;
XX  
XX    if (!isatty(1)) return;
XX    if (!f) {
XX***************
XX*** 145,154 ****
XX  	chmod(ttyname(1),mode & ~022);
XX    }
XX    else chmod(ttyname(1),mode);
XX! * ------- end of mesg */
XX  }
XX  
XX! readfile()
XX  {
XX    while (readline()) {
XX  	if (isrequest) continue;
XX--- 191,200 ----
XX  	chmod(ttyname(1),mode & ~022);
XX    }
XX    else chmod(ttyname(1),mode);
XX! /* ------- end of mesg */
XX  }
XX  
XX! void readfile()
XX  {
XX    while (readline()) {
XX  	if (isrequest) continue;
XX***************
XX*** 162,168 ****
XX    }
XX  }
XX  
XX! readline()
XX  {
XX    int startline, doingword;
XX    isrequest = 0;
XX--- 208,214 ----
XX    }
XX  }
XX  
XX! int readline()
XX  {
XX    int startline, doingword;
XX    isrequest = 0;
XX***************
XX*** 230,236 ****
XX   *	bumpword - add word to current line.
XX   */
XX  
XX! bumpword()
XX  {
XX    char *hc;
XX    *holdp = '\0';
XX--- 276,282 ----
XX   *	bumpword - add word to current line.
XX   */
XX  
XX! void bumpword()
XX  {
XX    char *hc;
XX    *holdp = '\0';
XX***************
XX*** 303,309 ****
XX   *	dehyph - remove hyphenation marks.
XX   */
XX  
XX! dehyph(s)
XX  char *s;
XX  {
XX    char *t;
XX--- 349,355 ----
XX   *	dehyph - remove hyphenation marks.
XX   */
XX  
XX! void dehyph(s)
XX  char *s;
XX  {
XX    char *t;
XX***************
XX*** 325,331 ****
XX    return n;
XX  }
XX  
XX! tabulate()
XX  {
XX    int j;
XX    for (j = 0; j < n_ta; j++)
XX--- 371,377 ----
XX    return n;
XX  }
XX  
XX! void tabulate()
XX  {
XX    int j;
XX    for (j = 0; j < n_ta; j++)
XX***************
XX*** 527,533 ****
XX    return c != EOF;
XX  }
XX  
XX! snset(par)
XX  int *par;
XX  {
XX    int r, s;
XX--- 573,579 ----
XX    return c != EOF;
XX  }
XX  
XX! void snset(par)
XX  int *par;
XX  {
XX    int r, s;
XX***************
XX*** 540,546 ****
XX  	*par = r;
XX  }
XX  
XX! tread(s)
XX  char *s;
XX  {
XX    int leadbl;
XX--- 586,592 ----
XX  	*par = r;
XX  }
XX  
XX! int tread(s)
XX  char *s;
XX  {
XX    int leadbl;
XX***************
XX*** 557,563 ****
XX    }
XX  }
XX  
XX! nread(i)
XX  int *i;
XX  {
XX    int f;
XX--- 603,609 ----
XX    }
XX  }
XX  
XX! void nread(i)
XX  int *i;
XX  {
XX    int f;
XX***************
XX*** 620,626 ****
XX    }
XX  }
XX  
XX! defmac()
XX  {
XX    int i;
XX    char newmac[3], *nm;
XX--- 666,672 ----
XX    }
XX  }
XX  
XX! void defmac()
XX  {
XX    int i;
XX    char newmac[3], *nm;
XX***************
XX*** 644,650 ****
XX    fflush(Macwrite);
XX  }
XX  
XX! openmac()
XX  {
XX    if (NULL == (Macwrite = fopen(mktemp(mfilnam), "w"))) {
XX  	fprintf(stderr, "roff: cannot open temp file\n");
XX--- 690,696 ----
XX    fflush(Macwrite);
XX  }
XX  
XX! void openmac()
XX  {
XX    if (NULL == (Macwrite = fopen(mktemp(mfilnam), "w"))) {
XX  	fprintf(stderr, "roff: cannot open temp file\n");
XX***************
XX*** 684,690 ****
XX    }
XX  }
XX  
XX! submac(r)
XX  int r;
XX  {
XX    while (c != EOF && c != '\n') c = suck();
XX--- 730,736 ----
XX    }
XX  }
XX  
XX! void submac(r)
XX  int r;
XX  {
XX    while (c != EOF && c != '\n') c = suck();
XX***************
XX*** 698,704 ****
XX    fseek(Macread, macro[r].moff, 0);
XX  }
XX  
XX! endmac()
XX  {
XX    depth--;
XX    if (depth)
XX--- 744,750 ----
XX    fseek(Macread, macro[r].moff, 0);
XX  }
XX  
XX! void endmac()
XX  {
XX    depth--;
XX    if (depth)
XX***************
XX*** 708,714 ****
XX    c = '\n';
XX  }
XX  
XX! do_ta()
XX  {
XX    int v;
XX    n_ta = 0;
XX--- 754,760 ----
XX    c = '\n';
XX  }
XX  
XX! void do_ta()
XX  {
XX    int v;
XX    n_ta = 0;
XX***************
XX*** 722,728 ****
XX    }
XX  }
XX  
XX! do_tr()
XX  {
XX    char *t;
XX    t = &o_tr[0][0];
XX--- 768,774 ----
XX    }
XX  }
XX  
XX! void do_tr()
XX  {
XX    char *t;
XX    t = &o_tr[0][0];
XX***************
XX*** 736,742 ****
XX    *t = '\0';
XX  }
XX  
XX! do_nx()
XX  {
XX    char fname[100], *f;
XX    f = fname;
XX--- 782,788 ----
XX    *t = '\0';
XX  }
XX  
XX! void do_nx()
XX  {
XX    char fname[100], *f;
XX    f = fname;
XX***************
XX*** 774,780 ****
XX  	}
XX  }
XX  
XX! writebreak()
XX  {
XX    int q;
XX    if (assylen) writeline(0, 1);
XX--- 820,826 ----
XX  	}
XX  }
XX  
XX! void writebreak()
XX  {
XX    int q;
XX    if (assylen) writeline(0, 1);
XX***************
XX*** 793,799 ****
XX    }
XX  }
XX  
XX! blankline()
XX  {
XX    if (line_no >= TXTLEN) newpage();
XX    if (o_n2) o_n2++;
XX--- 839,845 ----
XX    }
XX  }
XX  
XX! void blankline()
XX  {
XX    if (line_no >= TXTLEN) newpage();
XX    if (o_n2) o_n2++;
XX***************
XX*** 801,807 ****
XX    line_no++;
XX  }
XX  
XX! writeline(adflag, flushflag)
XX  int adflag, flushflag;
XX  {
XX    int j, q;
XX--- 847,853 ----
XX    line_no++;
XX  }
XX  
XX! void writeline(adflag, flushflag)
XX  int adflag, flushflag;
XX  {
XX    int j, q;
XX***************
XX*** 857,863 ****
XX    o_ix = o_ti = -1;
XX  }
XX  
XX! fillline()
XX  {
XX    int excess, j, s, inc, spaces;
XX    adjtoggle ^= 1;
XX--- 903,909 ----
XX    o_ix = o_ti = -1;
XX  }
XX  
XX! void fillline()
XX  {
XX    int excess, j, s, inc, spaces;
XX    adjtoggle ^= 1;
XX***************
XX*** 891,897 ****
XX    }
XX  }
XX  
XX! insrt(p)
XX  int p;
XX  {
XX    int i;
XX--- 937,943 ----
XX    }
XX  }
XX  
XX! void insrt(p)
XX  int p;
XX  {
XX    int i;
XX***************
XX*** 899,905 ****
XX    assylen++;
XX  }
XX  
XX! newpage()
XX  {
XX    if (page_no >= 0)
XX  	endpage();
XX--- 945,951 ----
XX    assylen++;
XX  }
XX  
XX! void newpage()
XX  {
XX    if (page_no >= 0)
XX  	endpage();
XX***************
XX*** 909,915 ****
XX    beginpage();
XX  }
XX  
XX! beginpage()
XX  {
XX    int i;
XX    if (sflag) waitawhile();
XX--- 955,961 ----
XX    beginpage();
XX  }
XX  
XX! void beginpage()
XX  {
XX    int i;
XX    if (sflag) waitawhile();
XX***************
XX*** 919,925 ****
XX    line_no = 0;
XX  }
XX  
XX! endpage()
XX  {
XX    int i;
XX    for (i = line_no; i < TXTLEN; i++) blankline();
XX--- 965,971 ----
XX    line_no = 0;
XX  }
XX  
XX! void endpage()
XX  {
XX    int i;
XX    for (i = line_no; i < TXTLEN; i++) blankline();
XX***************
XX*** 934,940 ****
XX    }
XX  }
XX  
XX! blankpage()
XX  {
XX    int i;
XX    if (sflag) waitawhile();
XX--- 980,986 ----
XX    }
XX  }
XX  
XX! void blankpage()
XX  {
XX    int i;
XX    if (sflag) waitawhile();
XX***************
XX*** 949,958 ****
XX    line_no = 0;
XX  }
XX  
XX! waitawhile()
XX  {
XX    int oldflags; 
XX-   void nix();
XX    if (isatty(0)) {
XX  	oldflags = tty.sg_flags;
XX  	tty.sg_flags &= ~ECHO;	/* DON'T ECHO THE RUBOUT */
XX--- 995,1003 ----
XX    line_no = 0;
XX  }
XX  
XX! void waitawhile()
XX  {
XX    int oldflags; 
XX    if (isatty(0)) {
XX  	oldflags = tty.sg_flags;
XX  	tty.sg_flags &= ~ECHO;	/* DON'T ECHO THE RUBOUT */
XX***************
XX*** 971,980 ****
XX  {
XX  }
XX  
XX! writetitle(t)
XX  char *t;
XX  {
XX!   char d, *pst, *pgform();
XX    int j, l, m, n;
XX    d = *t;
XX    if (o_hx || !d) {
XX--- 1016,1025 ----
XX  {
XX  }
XX  
XX! void writetitle(t)
XX  char *t;
XX  {
XX!   char d, *pst;
XX    int j, l, m, n;
XX    d = *t;
XX    if (o_hx || !d) {
XX***************
XX*** 1084,1096 ****
XX    return q;
XX  }
XX  
XX! spits(s)
XX  char *s;
XX  {
XX    while (*s) spit(*s++);
XX  }
XX  
XX! spit(c)
XX  char c;
XX  {
XX    static int col_no, n_blanks;
XX--- 1129,1141 ----
XX    return q;
XX  }
XX  
XX! void spits(s)
XX  char *s;
XX  {
XX    while (*s) spit(*s++);
XX  }
XX  
XX! void spit(c)
XX  char c;
XX  {
XX    static int col_no, n_blanks;
XX***************
XX*** 1112,1118 ****
XX  		while (col_no / 8 < (col_no + n_blanks) / 8) {
XX  			putc('\t', stdout);
XX  			n_blanks -= 8 - (col_no & 07);
XX! 			col_no = 8 + col_no & ~07;
XX  		}
XX  	for (; n_blanks; n_blanks--) {
XX  		putc(' ', stdout);
XX--- 1157,1163 ----
XX  		while (col_no / 8 < (col_no + n_blanks) / 8) {
XX  			putc('\t', stdout);
XX  			n_blanks -= 8 - (col_no & 07);
XX! 			col_no = (8 + col_no) & ~07;
XX  		}
XX  	for (; n_blanks; n_blanks--) {
XX  		putc(' ', stdout);
XX***************
XX*** 1197,1206 ****
XX  int islegal(c)
XX  int c;
XX  {
XX!   return c >= ' ' && c <= '~' || isspace(c) || c == '\n' || c == EOF;
XX  }
XX  
XX! bomb()
XX  {
XX    fprintf(stderr, "Usage: roff [+00] [-00] [-s] [-h] file ...\n");
XX    exit(1);
XX--- 1242,1251 ----
XX  int islegal(c)
XX  int c;
XX  {
XX!   return (c >= ' ' && c <= '~') || isspace(c) || c == '\n' || c == EOF;
XX  }
XX  
XX! void bomb()
XX  {
XX    fprintf(stderr, "Usage: roff [+00] [-00] [-s] [-h] file ...\n");
XX    exit(1);
X/
Xecho x - sed.c.d
Xsed '/^X/s///' > sed.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/sed.c  crc=51644  45276	Sun Apr 25 21:35:17 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/sed.c  crc=47299  45955	Wed Nov  4 04:19:19 1992
XX***************
XX*** 19,24 ****
XX--- 19,28 ----
XX   */
XX  
XX  #include <ctype.h>
XX+ #include <sys/types.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  /*+++++++++++++++*/
XX***************
XX*** 122,134 ****
XX     The operation of execute() is described in its source module.
XX  */
XX  
XX! /* #include <stdio.h>		/* uses getc, fprintf, fopen, fclose */
XX! extern FILE *fopen();		/* should this be in stdio.h? */
XX! /* #include "sed.h"		/* command type struct and name defines */
XX  
XX  /* Imported functions */
XX- extern int strcmp();		/* test strings for equality */
XX- extern void execute();		/* execute compiled command */
XX  
XX  /***** public stuff ******/
XX  
XX--- 126,135 ----
XX     The operation of execute() is described in its source module.
XX  */
XX  
XX! /* #include <stdio.h> */
XX! /* #include "sed.h"   */
XX  
XX  /* Imported functions */
XX  
XX  /***** public stuff ******/
XX  
XX***************
XX*** 210,223 ****
XX  static int eflag;		/* -e option flag */
XX  static int gflag;		/* -g option flag */
XX  
XX  
XX! main(argc, argv)
XX  /* Main sequence of the stream editor */
XX  int argc;
XX  char *argv[];
XX  {
XX-   void compile(), resolve();
XX- 
XX    eargc = argc;			/* set local copy of argument count */
XX    eargv = argv;			/* set local copy of argument list */
XX    cmdp->addr1 = pool;		/* 1st addr expand will be at pool start */
XX--- 211,250 ----
XX  static int eflag;		/* -e option flag */
XX  static int gflag;		/* -g option flag */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(static void compile, (void));
XX+ _PROTOTYPE(static int cmdcomp, (int cchar));
XX+ _PROTOTYPE(static char *rhscomp, (char *rhsp, int delim));
XX+ _PROTOTYPE(static char *recomp, (char *expbuf, int redelim));
XX+ _PROTOTYPE(static int cmdline, (char *cbuf));
XX+ _PROTOTYPE(static char *address, (char *expbuf));
XX+ _PROTOTYPE(static char *gettext, (char *txp));
XX+ _PROTOTYPE(static label *search, (label *ptr));
XX+ _PROTOTYPE(static void resolve, (void));
XX+ _PROTOTYPE(static char *ycomp, (char *ep, int delim));
XX+ _PROTOTYPE(void quit, (int n));
XX+ _PROTOTYPE(void execute, (void));
XX+ _PROTOTYPE(static int selected, (sedcmd *ipc));
XX+ _PROTOTYPE(static int match, (char *expbuf, int gf));
XX+ _PROTOTYPE(static int advance, (char *lp, char *ep));
XX+ _PROTOTYPE(static int substitute, (sedcmd *ipc));
XX+ _PROTOTYPE(static void dosub, (char *rhsbuf));
XX+ _PROTOTYPE(static char *place, (char *asp, char *al1, char *al2));
XX+ _PROTOTYPE(static void listto, (char *p1, FILE *fp));
XX+ _PROTOTYPE(static void truncated, (int h));
XX+ _PROTOTYPE(static void command, (sedcmd *ipc));
XX+ _PROTOTYPE(static void openfile, (char *file));
XX+ _PROTOTYPE(static void get, (void));
XX+ _PROTOTYPE(static void initget, (void));
XX+ _PROTOTYPE(static char *getline, (char *buf));
XX+ _PROTOTYPE(static int Memcmp, (char *a, char *b, int count));
XX+ _PROTOTYPE(static void readout, (void));
XX  
XX! int main(argc, argv)
XX  /* Main sequence of the stream editor */
XX  int argc;
XX  char *argv[];
XX  {
XX    eargc = argc;			/* set local copy of argument count */
XX    eargv = argv;			/* set local copy of argument list */
XX    cmdp->addr1 = pool;		/* 1st addr expand will be at pool start */
XX***************
XX*** 267,272 ****
XX--- 294,300 ----
XX    resolve();			/* resolve label table indirections */
XX    execute();			/* execute commands */
XX    quit(0);			/* everything was O.K. if we got here */
XX+   return(0);
XX  }
XX  
XX  
XX***************
XX*** 291,302 ****
XX  static void compile()
XX  /* Precompile sed commands out of a file */
XX  {
XX!   char ccode, *address();
XX  
XX  
XX    for (;;) {			/* main compilation loop */
XX! 	if (*cp == '\0')	/* get a new command line */
XX  		if (cmdline(cp = linebuf) < 0) break;
XX  	SKIPWS(cp);
XX  	if (*cp == '\0')	/* empty */
XX  		continue;
XX--- 319,332 ----
XX  static void compile()
XX  /* Precompile sed commands out of a file */
XX  {
XX!   char ccode;
XX  
XX  
XX    for (;;) {			/* main compilation loop */
XX! 	if (*cp == '\0') {	/* get a new command line */
XX! 		*linebuf = '\0';	/* K.H */
XX  		if (cmdline(cp = linebuf) < 0) break;
XX+ 	}
XX  	SKIPWS(cp);
XX  	if (*cp == '\0')	/* empty */
XX  		continue;
XX***************
XX*** 364,377 ****
XX  /* Compile a single command */
XX  register char cchar;		/* character name of command */
XX  {
XX-   char *gettext(), *rhscomp(), *recomp(), *ycomp();
XX    static sedcmd **cmpstk[MAXDEPTH];	/* current cmd stack for {} */
XX    static char *fname[WFILES];	/* w file name pointers */
XX    static FILE *fout[WFILES];	/* w file file ptrs */
XX    static int nwfiles = 1;	/* count of open w files */
XX    int i;			/* indexing dummy used in w */
XX    sedcmd *sp1, *sp2;		/* temps for label searches */
XX!   label *lpt, *search();	/* ditto, and the searcher */
XX    char redelim;			/* current RE delimiter */
XX  
XX    fout[0] = stdout;
XX--- 394,406 ----
XX  /* Compile a single command */
XX  register char cchar;		/* character name of command */
XX  {
XX    static sedcmd **cmpstk[MAXDEPTH];	/* current cmd stack for {} */
XX    static char *fname[WFILES];	/* w file name pointers */
XX    static FILE *fout[WFILES];	/* w file file ptrs */
XX    static int nwfiles = 1;	/* count of open w files */
XX    int i;			/* indexing dummy used in w */
XX    sedcmd *sp1, *sp2;		/* temps for label searches */
XX!   label *lpt;
XX    char redelim;			/* current RE delimiter */
XX  
XX    fout[0] = stdout;
XX***************
XX*** 534,540 ****
XX    char *svclass;		/* start of current char class */
XX    char brnest[MAXTAGS];		/* bracket-nesting array */
XX    char *brnestp;		/* ptr to current bracket-nest */
XX-   char *pp;			/* scratch pointer */
XX    int classct;			/* class element count */
XX    int tags;			/* # of closed tags */
XX  
XX--- 563,568 ----
XX***************
XX*** 663,669 ****
XX  {
XX    register int inc;		/* not char because must hold EOF */
XX  
XX!   cbuf--;			/* so pre-increment points us at cbuf */
XX  
XX    /* E command flag is on */
XX    if (eflag) {
XX--- 691,697 ----
XX  {
XX    register int inc;		/* not char because must hold EOF */
XX  
XX!   *cbuf-- = 0;			/* so pre-increment points us at cbuf */
XX  
XX    /* E command flag is on */
XX    if (eflag) {
XX***************
XX*** 842,848 ****
XX    return(ep + 0x80);		/* return first free location past table end */
XX  }
XX  
XX! quit(n)
XX  int n;
XX  {
XX  /* Flush buffers and exit.  Now a historical relic.  Rely on exit to flush
XX--- 870,876 ----
XX    return(ep + 0x80);		/* return first free location past table end */
XX  }
XX  
XX! void quit(n)
XX  int n;
XX  {
XX  /* Flush buffers and exit.  Now a historical relic.  Rely on exit to flush
XX***************
XX*** 864,879 ****
XX     The function command() does most of the work. Match() and advance()
XX     are used for matching text against precompiled regular expressions and
XX     dosub() does right-hand-side substitution.  Getline() does text input;
XX!    readout() and memcmp() are output and string-comparison utilities.
XX  */
XX  
XX! /* #include <stdio.h>	/* {f}puts, {f}printf, getc/putc, f{re}open, fclose */
XX! extern FILE *fopen();
XX! /* #include <ctype.h>	/* for isprint(), isdigit(), toascii() macros */
XX! /* #include "sed.h"	/* command type structures & miscellaneous constants */
XX  
XX- extern char *strcpy();		/* used in dosub */
XX- 
XX  /***** shared variables imported from the main ******/
XX  
XX  /* Main data areas */
XX--- 892,904 ----
XX     The function command() does most of the work. Match() and advance()
XX     are used for matching text against precompiled regular expressions and
XX     dosub() does right-hand-side substitution.  Getline() does text input;
XX!    readout() and Memcmp() are output and string-comparison utilities.
XX  */
XX  
XX! /* #include <stdio.h>	*/
XX! /* #include <ctype.h>	*/
XX! /* #include "sed.h"	*/
XX  
XX  /***** shared variables imported from the main ******/
XX  
XX  /* Main data areas */
XX***************
XX*** 928,935 ****
XX    register char *p1;		/* dummy copy ptrs */
XX    register sedcmd *ipc;		/* ptr to current command */
XX    char *execp;			/* ptr to source */
XX-   char *getline();		/* input-getting functions */
XX-   void command(), readout(), initget();
XX  
XX  
XX    initget();
XX--- 953,958 ----
XX***************
XX*** 1018,1023 ****
XX--- 1041,1047 ----
XX  static int match(expbuf, gf)	/* uses genbuf */
XX   /* Match RE at expbuf against linebuf; if gf set, copy linebuf from genbuf */
XX  char *expbuf;
XX+ int gf;
XX  {
XX    register char *p1, *p2, c;
XX  
XX***************
XX*** 1113,1119 ****
XX  		bbeg = brastart[*ep];
XX  		ct = bracend[*ep++] - bbeg;
XX  
XX! 		if (memcmp(bbeg, lp, ct)) {
XX  			lp += ct;
XX  			continue;
XX  		}
XX--- 1137,1143 ----
XX  		bbeg = brastart[*ep];
XX  		ct = bracend[*ep++] - bbeg;
XX  
XX! 		if (Memcmp(bbeg, lp, ct)) {
XX  			lp += ct;
XX  			continue;
XX  		}
XX***************
XX*** 1123,1129 ****
XX  		bbeg = brastart[*ep];
XX  		ct = bracend[*ep++] - bbeg;
XX  		curlp = lp;
XX! 		while (memcmp(bbeg, lp, ct)) lp += ct;
XX  
XX  		while (lp >= curlp) {
XX  			if (advance(lp, ep)) return(TRUE);
XX--- 1147,1153 ----
XX  		bbeg = brastart[*ep];
XX  		ct = bracend[*ep++] - bbeg;
XX  		curlp = lp;
XX! 		while (Memcmp(bbeg, lp, ct)) lp += ct;
XX  
XX  		while (lp >= curlp) {
XX  			if (advance(lp, ep)) return(TRUE);
XX***************
XX*** 1190,1197 ****
XX  /* Perform s command */
XX  sedcmd *ipc;			/* ptr to s command struct */
XX  {
XX-   void dosub();			/* for if we find a match */
XX- 
XX    if (match(ipc->u.lhs, 0))	/* if no match */
XX  	dosub(ipc->rhs);	/* perform it once */
XX    else
XX--- 1214,1219 ----
XX***************
XX*** 1212,1218 ****
XX  {
XX    register char *lp, *sp, *rp;
XX    int c;
XX-   char *place();
XX  
XX    /* Copy linebuf to genbuf up to location  1 */
XX    lp = linebuf;
XX--- 1234,1239 ----
XX***************
XX*** 1307,1313 ****
XX    register char *p1, *p2;
XX    char *execp;
XX    int didsub;			/* true if last s succeeded */
XX-   char *getline();		/* input-getting functions */
XX  
XX    switch (ipc->command) {
XX        case ACMD:		/* append */
XX--- 1328,1333 ----
XX***************
XX*** 1354,1360 ****
XX  	p2 = holdsp;
XX  	do
XX  		if (p1 > linebuf + MAXBUF) {
XX! 			truncated();
XX  			p1[-1] = 0;
XX  			break;
XX  		}
XX--- 1374,1380 ----
XX  	p2 = holdsp;
XX  	do
XX  		if (p1 > linebuf + MAXBUF) {
XX! 			truncated(0);
XX  			p1[-1] = 0;
XX  			break;
XX  		}
XX***************
XX*** 1376,1382 ****
XX  	p2 = linebuf;
XX  	do
XX  		if (p1 > holdsp + MAXBUF) {
XX! 			truncated();
XX  			p1[-1] = 0;
XX  			break;
XX  		}
XX--- 1396,1402 ----
XX  	p2 = linebuf;
XX  	do
XX  		if (p1 > holdsp + MAXBUF) {
XX! 			truncated(1);
XX  			p1[-1] = 0;
XX  			break;
XX  		}
XX***************
XX*** 1540,1555 ****
XX    if (c == EOF) lastline = TRUE;
XX  
XX    if (buf > linebuf + MAXBUF) {
XX! 	truncated();
XX  	--buf;
XX    }
XX    *buf = 0;
XX    return buf;
XX  }
XX  
XX! static int memcmp(a, b, count)
XX  /* Return TRUE if *a... == *b... for count chars, FALSE otherwise */
XX  register char *a, *b;
XX  {
XX    while (count--)		/* look at count characters */
XX  	if (*a++ != *b++)	/* if any are nonequal	 */
XX--- 1560,1576 ----
XX    if (c == EOF) lastline = TRUE;
XX  
XX    if (buf > linebuf + MAXBUF) {
XX! 	truncated(0);
XX  	--buf;
XX    }
XX    *buf = 0;
XX    return buf;
XX  }
XX  
XX! static int Memcmp(a, b, count)
XX  /* Return TRUE if *a... == *b... for count chars, FALSE otherwise */
XX  register char *a, *b;
XX+ int count;
XX  {
XX    while (count--)		/* look at count characters */
XX  	if (*a++ != *b++)	/* if any are nonequal	 */
X/
Xecho x - shar.c.d
Xsed '/^X/s///' > shar.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/shar.c  crc=53724   1135	Sun Apr 25 21:35:17 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/shar.c  crc=37758   1532	Mon Dec 21 00:10:49 1992
XX***************
XX*** 1,65 ****
XX  /* shar - make a shell archive		Author: Michiel Husijes */
XX  
XX! #include <sys/types.h>
XX! #include <fcntl.h>
XX! #include <blocksize.h>
XX  #include <stdio.h>
XX  
XX! #define IO_SIZE		(10 * BLOCK_SIZE)
XX  
XX! char input[IO_SIZE];
XX! char output[IO_SIZE];
XX! int ind = 0;
XX! 
XX! main(argc, argv)
XX  int argc;
XX! register char *argv[];
XX  {
XX!   register int i;
XX!   int fd;
XX  
XX!   for (i = 1; i < argc; i++) {
XX! 	if ((fd = open(argv[i], O_RDONLY)) < 0) {
XX! 		write(2, "Cannot open ", 12);
XX! 		write(2, argv[i], strlen(argv[i]));
XX! 		write(2, ".\n", 2);
XX  	} else {
XX! 		print("echo x - ");
XX! 		print(argv[i]);
XX! 		print("\nsed '/^X/s///' > ");
XX! 		print(argv[i]);
XX! 		print(" << '/'\n");
XX! 		cat(fd);
XX  	}
XX    }
XX!   if (ind) write(1, output, ind);
XX!   exit(0);
XX! }
XX! 
XX! cat(fd)
XX! int fd;
XX! {
XX!   static char *current, *last;
XX!   register int r = 0;
XX!   register char *cur_pos = current;
XX! 
XX!   putchar('X');
XX!   for (;;) {
XX! 	if (cur_pos == last) {
XX! 		if ((r = read(fd, input, IO_SIZE)) <= 0) break;
XX! 		last = &input[r];
XX! 		cur_pos = input;
XX! 	}
XX! 	putchar(*cur_pos);
XX! 	if (*cur_pos++ == '\n' && cur_pos != last) putchar('X');
XX    }
XX!   print("/\n");
XX!   (void) close(fd);
XX!   current = cur_pos;
XX  }
XX  
XX! print(str)
XX! register char *str;
XX  {
XX!   while (*str) putchar(*str++);
XX  }
XX--- 1,71 ----
XX  /* shar - make a shell archive		Author: Michiel Husijes */
XX  
XX! #include <stdlib.h>		/* for the nonstd :-( _PROTOTYPE */
XX  #include <stdio.h>
XX  
XX! static _PROTOTYPE( void error, (char *progname, char *operation,
XX! 				char *filename) );
XX! _PROTOTYPE( int main, (int argc, char **argv) );
XX  
XX! int main(argc, argv)
XX  int argc;
XX! char *argv[];
XX  {
XX!   int argn;
XX!   register int ch;
XX!   register FILE *fp;
XX!   int exitstatus;
XX!   char *filename;
XX  
XX!   exitstatus = 0;
XX!   for (argn = 1; argn < argc; argn++) {
XX! 	filename = argv[argn];
XX! 	if ((fp = fopen(filename, "r")) == NULL) {
XX! 		error(argv[0], "opening ", filename);
XX! 		exitstatus = 1;
XX  	} else {
XX! 		fputs("echo x - ", stdout);
XX! 		fputs(filename, stdout);
XX! 		fputs("\nsed '/^X/s///' > ", stdout);
XX! 		fputs(filename, stdout);
XX! 		fputs(" << '/'\n", stdout);
XX! 		while ((ch = getc(fp)) != EOF) {
XX! 			putchar('X');
XX! 			putchar(ch);
XX! 			while (ch != '\n') {
XX! 				ch = getc(fp);
XX! 				if (ch == EOF) break;
XX! 				putchar(ch);
XX! 			}
XX! 			if (ch == EOF) break;
XX! 		}
XX! 		fputs("/\n", stdout);
XX! 		if (ferror(fp)) {
XX! 			error(argv[0], "reading ", filename);
XX! 			exitstatus = 1;
XX! 		}
XX! 		if (fclose(fp) != 0) {
XX! 			error(argv[0], "closing ", filename);
XX! 			exitstatus = 1;
XX! 		}
XX! 		if (ferror(stdout)) break;	/* lost already */
XX  	}
XX    }
XX!   fflush(stdout);
XX!   if (ferror(stdout)) {
XX! 	error(argv[0], "writing ", "stdout");
XX! 	exitstatus = 1;
XX    }
XX!   return(exitstatus);
XX  }
XX  
XX! static void error(progname, operation, filename)
XX! char *progname;
XX! char *operation;
XX! char *filename;
XX  {
XX!   fputs(progname, stderr);
XX!   fputs(": error ", stderr);
XX!   fputs(operation, stderr);
XX!   perror(filename);
XX  }
X/
Xecho x - size.c.d
Xsed '/^X/s///' > size.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/size.c  crc=19126   1573	Sun Apr 25 21:35:17 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/size.c  crc=46795   1420	Wed Nov  4 04:19:20 1992
XX***************
XX*** 2,20 ****
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  
XX- #define HLONG            8	/* # longs in the header */
XX- #define TEXT             2
XX- #define DATA             3
XX- #define BSS              4
XX- #define CHMEM            6
XX- #define MAGIC       0x0301	/* magic number for an object file */
XX- #define SEPBIT  0x00200000	/* this bit is set for separate I/D */
XX- 
XX  int heading;			/* set when heading printed */
XX  int error;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 2,19 ----
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX+ #include <a.out.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX  int heading;			/* set when heading printed */
XX  int error;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void size, (char *name));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 25,71 ****
XX  	exit(error);
XX    }
XX    for (i = 1; i < argc; i++) size(argv[i]);
XX!   exit(error);
XX  }
XX  
XX  
XX  
XX! size(name)
XX  char *name;
XX  {
XX    int fd, separate;
XX!   long head[HLONG], dynam, allmem;
XX  
XX    if ((fd = open(name, O_RDONLY)) < 0) {
XX! 	stderr3("size: can't open ", name, "\n");
XX  	return;
XX    }
XX!   if (read(fd, head, sizeof(head)) != sizeof(head)) {
XX! 	stderr3("size: ", name, ": header too short\n");
XX  	error = 1;
XX  	close(fd);
XX  	return;
XX    }
XX!   if ((head[0] & 0xFFFFL) != MAGIC) {
XX! 	stderr3("size: ", name, " not an object file\n");
XX  	close(fd);
XX  	return;
XX    }
XX!   separate = (head[0] & SEPBIT ? 1 : 0);
XX!   dynam = head[CHMEM] - head[TEXT] - head[DATA] - head[BSS];
XX!   if (separate) dynam += head[TEXT];
XX!   allmem = (separate ? head[CHMEM] + head[TEXT] : head[CHMEM]);
XX!   if (heading++ == 0) prints("  text\t  data\t   bss\t stack\tmemory\n");
XX    printf("%6ld\t%6ld\t%6ld\t%6ld\t%6ld\t%s\n",
XX!          head[TEXT], head[DATA], head[BSS], dynam, allmem, name);
XX    close(fd);
XX- }
XX- 
XX- stderr3(s1, s2, s3)
XX- char *s1, *s2, *s3;
XX- {
XX-   std_err(s1);
XX-   std_err(s2);
XX-   std_err(s3);
XX-   error = 1;
XX  }
XX--- 24,64 ----
XX  	exit(error);
XX    }
XX    for (i = 1; i < argc; i++) size(argv[i]);
XX!   return(error);
XX  }
XX  
XX  
XX  
XX! void size(name)
XX  char *name;
XX  {
XX    int fd, separate;
XX!   long dynam, allmem;
XX!   struct exec exec;
XX  
XX    if ((fd = open(name, O_RDONLY)) < 0) {
XX! 	fprintf(stderr, "size: can't open %s\n", name);
XX! 	error = 1;
XX  	return;
XX    }
XX!   if (read(fd, (char *)&exec, sizeof(struct exec)) != sizeof(struct exec)) {
XX! 	fprintf(stderr, "size: %s: header too short\n", name);
XX  	error = 1;
XX  	close(fd);
XX  	return;
XX    }
XX!   if (BADMAG(exec)) {
XX! 	fprintf(stderr, "size: %s not an object file\n", name);
XX! 	error = 1;
XX  	close(fd);
XX  	return;
XX    }
XX!   separate = (exec.a_flags & A_SEP ? 1 : 0);
XX!   dynam = exec.a_total - exec.a_text - exec.a_data - exec.a_bss;
XX!   if (separate) dynam += exec.a_text;
XX!   allmem = (separate ? exec.a_total + exec.a_text : exec.a_total);
XX!   if (heading++ == 0) printf("  text\t  data\t   bss\t stack\tmemory\n");
XX    printf("%6ld\t%6ld\t%6ld\t%6ld\t%6ld\t%s\n",
XX!          exec.a_text, exec.a_data, exec.a_bss, dynam, allmem, name);
XX    close(fd);
XX  }
X/
Xecho x - sleep.c.d
Xsed '/^X/s///' > sleep.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/sleep.c  crc=30888    425	Sun Apr 25 21:35:18 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/sleep.c  crc=62351    569	Wed Nov  4 04:19:20 1992
XX***************
XX*** 1,6 ****
XX  /* sleep - suspend a process for x sec		Author: Andy Tanenbaum */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 1,13 ----
XX  /* sleep - suspend a process for x sec		Author: Andy Tanenbaum */
XX  
XX! #include <sys/types.h>
XX! #include <stdlib.h>
XX! #include <unistd.h>
XX! #include <minix/minlib.h>
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 23,27 ****
XX  
XX    /* Now sleep. */
XX    sleep(seconds);
XX!   exit(0);
XX  }
XX--- 30,34 ----
XX  
XX    /* Now sleep. */
XX    sleep(seconds);
XX!   return(0);
XX  }
X/
Xecho x - sort.c.d
Xsed '/^X/s///' > sort.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/sort.c  crc=04405  31334	Sun Apr 25 21:35:18 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/sort.c  crc=47481  33016	Mon Jan 18 18:56:10 1993
XX***************
XX*** 36,44 ****
XX  #include <fcntl.h>
XX  #include <signal.h>
XX  #include <unistd.h>
XX  
XX! #define OPEN_FILES	16	/* Nr of open files per process */
XX! 
XX  #define MEMORY_SIZE	(20 * 1024)	/* Total mem_size */
XX  #define LINE_SIZE	(1024 >> 1)	/* Max length of a line */
XX  #define IO_SIZE		(2 * 1024)	/* Size of buffered output */
XX--- 36,47 ----
XX  #include <fcntl.h>
XX  #include <signal.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <stdio.h>
XX+ #include <limits.h>
XX  
XX! #define OPEN_FILES	(OPEN_MAX-4)	/* Nr of open files per process */
XX  #define MEMORY_SIZE	(20 * 1024)	/* Total mem_size */
XX  #define LINE_SIZE	(1024 >> 1)	/* Max length of a line */
XX  #define IO_SIZE		(2 * 1024)	/* Size of buffered output */
XX***************
XX*** 123,132 ****
XX  char USAGE[] = "Usage: sort [-funbirdcmt'x'] [+beg_pos [-end_pos]] [-o outfile] [file] ..";
XX  
XX  /* Forward declarations */
XX! void catch();
XX! char *file_name(), *skip_fields();
XX! MERGE *skip_lines(), *print();
XX! extern char *msbrk(), *mbrk();
XX  
XX  /* Table of all chars. 0 means no special meaning. */
XX  char table[256] = {
XX--- 126,165 ----
XX  char USAGE[] = "Usage: sort [-funbirdcmt'x'] [+beg_pos [-end_pos]] [-o outfile] [file] ..";
XX  
XX  /* Forward declarations */
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void get_opts, (char *ptr, FIELD * field));
XX! _PROTOTYPE(void new_field, (FIELD * field, int *offset, BOOL beg_fl));
XX! _PROTOTYPE(void adjust_options, (FIELD * field));
XX! _PROTOTYPE(void error, (BOOL quit, char *message, char *arg));
XX! _PROTOTYPE(void open_outfile, (void));
XX! _PROTOTYPE(void get_file, (int fd, off_t size));
XX! _PROTOTYPE(int last_line, (void));
XX! _PROTOTYPE(void print_table, (int fd));
XX! _PROTOTYPE(char *file_name, (int nr));
XX! _PROTOTYPE(void mread, (int fd, char *address, int bytes));
XX! _PROTOTYPE(void mwrite, (int fd, char *address, int bytes));
XX! _PROTOTYPE(void sort, (void));
XX! _PROTOTYPE(void sort_table, (int nel));
XX! _PROTOTYPE(void incr, (int si, int ei));
XX! _PROTOTYPE(int cmp_fields, (char *el1, char *el2));
XX! _PROTOTYPE(void build_field, (char *dest, FIELD * field, char *src));
XX! _PROTOTYPE(char *skip_fields, (char *str, int nf));
XX! _PROTOTYPE(int compare, (char *el1, char *el2));
XX! _PROTOTYPE(int cmp, (unsigned char *el1, unsigned char *el2, FIELD * field));
XX! _PROTOTYPE(int digits, (char *str1, char *str2, BOOL check_sign));
XX! _PROTOTYPE(void files_merge, (int file_cnt));
XX! _PROTOTYPE(void merge, (int start_file, int limit_file));
XX! _PROTOTYPE(void put_line, (char *line));
XX! _PROTOTYPE(MERGE * print, (MERGE * merg, int file_cnt));
XX! _PROTOTYPE(int read_line, (MERGE * merg));
XX! _PROTOTYPE(MERGE * skip_lines, (MERGE * smallest, int file_cnt));
XX! _PROTOTYPE(void uniq_lines, (MERGE * merg));
XX! _PROTOTYPE(void check_file, (int fd, char *file));
XX! _PROTOTYPE(int length, (char *line));
XX! _PROTOTYPE(void copy, (char *dest, char *src));
XX! _PROTOTYPE(char *msbrk, (int size));
XX! _PROTOTYPE(void mbrk, (char *address));
XX! _PROTOTYPE(void catch, (int dummy));
XX  
XX  /* Table of all chars. 0 means no special meaning. */
XX  char table[256] = {
XX***************
XX*** 188,198 ****
XX  	   0, 0, 0, 0, 0, 0, 0
XX  };
XX  
XX  /*
XX   * Get_opts () assigns the options into the field structure as described in ptr.
XX   * This field structure could be the GLOBAL one.
XX   */
XX! get_opts(ptr, field)
XX  register char *ptr;
XX  register FIELD *field;
XX  {
XX--- 221,232 ----
XX  	   0, 0, 0, 0, 0, 0, 0
XX  };
XX  
XX+ 
XX  /*
XX   * Get_opts () assigns the options into the field structure as described in ptr.
XX   * This field structure could be the GLOBAL one.
XX   */
XX! void get_opts(ptr, field)
XX  register char *ptr;
XX  register FIELD *field;
XX  {
XX***************
XX*** 221,243 ****
XX    }
XX  }
XX  
XX- /* Atoi() converts a string to an int. */
XX- atoi(ptr)
XX- register char *ptr;
XX- {
XX-   register int num = 0;		/* Accumulator */
XX- 
XX-   while (table[*ptr] & DIGIT) num = num * 10 + *ptr++ - '0';
XX- 
XX-   return num;
XX- }
XX- 
XX  /* New_field () assigns a new field as described by the arguments.
XX   * A field description is of the form: +a.b[opts] -c.d, where b and d, as well
XX   * as -c.d and [opts] are optional. Nr before digit is field nr. Nr after digit
XX   * is offset from field.
XX   */
XX! new_field(field, offset, beg_fl)
XX  register FIELD *field;		/* Field to assign */
XX  int *offset;			/* Offset in argv structure */
XX  BOOL beg_fl;			/* Assign beg or end of field */
XX--- 255,266 ----
XX    }
XX  }
XX  
XX  /* New_field () assigns a new field as described by the arguments.
XX   * A field description is of the form: +a.b[opts] -c.d, where b and d, as well
XX   * as -c.d and [opts] are optional. Nr before digit is field nr. Nr after digit
XX   * is offset from field.
XX   */
XX! void new_field(field, offset, beg_fl)
XX  register FIELD *field;		/* Field to assign */
XX  int *offset;			/* Offset in argv structure */
XX  BOOL beg_fl;			/* Assign beg or end of field */
XX***************
XX*** 280,286 ****
XX    }
XX  }
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 303,309 ----
XX    }
XX  }
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 353,359 ****
XX  	if (check)
XX  		check_file(0, NIL_PTR);
XX  	else
XX! 		get_file(0, 0L);
XX    } else
XX  	while (arg_count < argc) {	/* Sort or check args */
XX  		if (strcmp(argv[arg_count], "-") == 0)
XX--- 376,382 ----
XX  	if (check)
XX  		check_file(0, NIL_PTR);
XX  	else
XX! 		get_file(0, (off_t) 0);
XX    } else
XX  	while (arg_count < argc) {	/* Sort or check args */
XX  		if (strcmp(argv[arg_count], "-") == 0)
XX***************
XX*** 363,369 ****
XX  			continue;
XX  		}
XX  
XX! 		 /* Open files */ 
XX  		else if ((fd = open(argv[arg_count], O_RDONLY)) < 0) {
XX  			error(FALSE, "Cannot open ", argv[arg_count++]);
XX  			continue;
XX--- 386,392 ----
XX  			continue;
XX  		}
XX  
XX! 		/* Open files */
XX  		else if ((fd = open(argv[arg_count], O_RDONLY)) < 0) {
XX  			error(FALSE, "Cannot open ", argv[arg_count++]);
XX  			continue;
XX***************
XX*** 383,395 ****
XX  	exit(0);
XX  
XX    files_merge(nr_of_files);
XX!   exit(0);
XX  }
XX  
XX  /* Adjust_options() assigns all global variables set also in the fields
XX   * assigned.
XX   */
XX! adjust_options(field)
XX  register FIELD *field;
XX  {
XX    register FIELD *gfield = &fields[GLOBAL];
XX--- 406,418 ----
XX  	exit(0);
XX  
XX    files_merge(nr_of_files);
XX!   return(0);
XX  }
XX  
XX  /* Adjust_options() assigns all global variables set also in the fields
XX   * assigned.
XX   */
XX! void adjust_options(field)
XX  register FIELD *field;
XX  {
XX    register FIELD *gfield = &fields[GLOBAL];
XX***************
XX*** 403,422 ****
XX  }
XX  
XX  /* Error () prints the error message on stderr and exits if quit == TRUE. */
XX! error(quit, message, arg)
XX  register BOOL quit;
XX  register char *message, *arg;
XX  {
XX    write(2, message, strlen(message));
XX    if (arg != NIL_PTR) write(2, arg, strlen(arg));
XX!   write(2, ".\n", 2);
XX    if (quit) exit(1);
XX  }
XX  
XX  /* Open_outfile () assigns to out_fd the fd where the output must go when all
XX   * the sorting is done.
XX   */
XX! open_outfile()
XX  {
XX    if (output_file == NIL_PTR)
XX  	out_fd = STD_OUT;
XX--- 426,445 ----
XX  }
XX  
XX  /* Error () prints the error message on stderr and exits if quit == TRUE. */
XX! void error(quit, message, arg)
XX  register BOOL quit;
XX  register char *message, *arg;
XX  {
XX    write(2, message, strlen(message));
XX    if (arg != NIL_PTR) write(2, arg, strlen(arg));
XX!   perror(" ");
XX    if (quit) exit(1);
XX  }
XX  
XX  /* Open_outfile () assigns to out_fd the fd where the output must go when all
XX   * the sorting is done.
XX   */
XX! void open_outfile()
XX  {
XX    if (output_file == NIL_PTR)
XX  	out_fd = STD_OUT;
XX***************
XX*** 427,435 ****
XX  /* Get_file reads the whole file of filedescriptor fd. If the file is too big
XX   * to keep in core, a partial sort is done, and the output is stashed somewhere.
XX   */
XX! get_file(fd, size)
XX  int fd;				/* Fd of file to read */
XX! register long size;		/* Size of file */
XX  {
XX    register int i;
XX    int rest;			/* Rest in memory */
XX--- 450,458 ----
XX  /* Get_file reads the whole file of filedescriptor fd. If the file is too big
XX   * to keep in core, a partial sort is done, and the output is stashed somewhere.
XX   */
XX! void get_file(fd, size)
XX  int fd;				/* Fd of file to read */
XX! register off_t size;		/* Size of file */
XX  {
XX    register int i;
XX    int rest;			/* Rest in memory */
XX***************
XX*** 460,472 ****
XX  	}
XX    }
XX  
XX!    /* Reading file. Check size */ 
XX    else if (size > rest) {	/* Won't fit */
XX  	mread(fd, cur_pos, rest);
XX  	in_core = FALSE;
XX  	i = last_line();	/* Get pos. of last line */
XX  	mem_top[i] = '\0';	/* Truncate */
XX! 	(void) lseek(fd, (long) (i - MEMORY_SIZE), SEEK_CUR);	/* Do this next time */
XX  	size = size - rest - i + MEMORY_SIZE;	/* Calculate rest */
XX  	cur_pos = mem_top;	/* Reset mem */
XX  	sort();			/* Sort core */
XX--- 483,495 ----
XX  	}
XX    }
XX  
XX!   /* Reading file. Check size */
XX    else if (size > rest) {	/* Won't fit */
XX  	mread(fd, cur_pos, rest);
XX  	in_core = FALSE;
XX  	i = last_line();	/* Get pos. of last line */
XX  	mem_top[i] = '\0';	/* Truncate */
XX! 	(void) lseek(fd, (off_t) (i - MEMORY_SIZE), SEEK_CUR);	/* Do this next time */
XX  	size = size - rest - i + MEMORY_SIZE;	/* Calculate rest */
XX  	cur_pos = mem_top;	/* Reset mem */
XX  	sort();			/* Sort core */
XX***************
XX*** 483,493 ****
XX  /* Last_line () find the last line in core and retuns the offset from the top
XX   * of the memory.
XX   */
XX! last_line()
XX  {
XX    register int i;
XX  
XX!   for (i = MEMORY_SIZE - 1; i > 0; i--)
XX  	if (mem_top[i] == '\n') break;
XX    return i + 1;
XX  }
XX--- 506,516 ----
XX  /* Last_line () find the last line in core and retuns the offset from the top
XX   * of the memory.
XX   */
XX! int last_line()
XX  {
XX    register int i;
XX  
XX!   for (i = MEMORY_SIZE - 2; i > 0; i--)
XX  	if (mem_top[i] == '\n') break;
XX    return i + 1;
XX  }
XX***************
XX*** 495,501 ****
XX  /* Print_table prints the line table in the given file_descriptor. If the fd
XX   * equals ERROR, it opens a temp_file itself.
XX   */
XX! print_table(fd)
XX  int fd;
XX  {
XX    register char **line_ptr;	/* Ptr in line_table */
XX--- 518,524 ----
XX  /* Print_table prints the line table in the given file_descriptor. If the fd
XX   * equals ERROR, it opens a temp_file itself.
XX   */
XX! void print_table(fd)
XX  int fd;
XX  {
XX    register char **line_ptr;	/* Ptr in line_table */
XX***************
XX*** 541,547 ****
XX  }
XX  
XX  /* Mread () performs a normal read (), but checks the return value. */
XX! mread(fd, address, bytes)
XX  int fd;
XX  char *address;
XX  register int bytes;
XX--- 564,570 ----
XX  }
XX  
XX  /* Mread () performs a normal read (), but checks the return value. */
XX! void mread(fd, address, bytes)
XX  int fd;
XX  char *address;
XX  register int bytes;
XX***************
XX*** 551,557 ****
XX  }
XX  
XX  /* Mwrite () performs a normal write (), but checks the return value. */
XX! mwrite(fd, address, bytes)
XX  int fd;
XX  char *address;
XX  register int bytes;
XX--- 574,580 ----
XX  }
XX  
XX  /* Mwrite () performs a normal write (), but checks the return value. */
XX! void mwrite(fd, address, bytes)
XX  int fd;
XX  char *address;
XX  register int bytes;
XX***************
XX*** 561,567 ****
XX  }
XX  
XX  /* Sort () sorts the input in memory starting at mem_top. */
XX! sort()
XX  {
XX    register char *ptr = mem_top;
XX    register int count = 0;
XX--- 584,590 ----
XX  }
XX  
XX  /* Sort () sorts the input in memory starting at mem_top. */
XX! void sort()
XX  {
XX    register char *ptr = mem_top;
XX    register int count = 0;
XX***************
XX*** 593,603 ****
XX  	print_table(ERROR);
XX  
XX  /* Free line table */
XX!   mbrk(line_table);
XX  }
XX  
XX  /* Sort_table () sorts the line table consisting of nel elements. */
XX! sort_table(nel)
XX  register int nel;
XX  {
XX    char *tmp;
XX--- 616,626 ----
XX  	print_table(ERROR);
XX  
XX  /* Free line table */
XX!   mbrk((char *) line_table);
XX  }
XX  
XX  /* Sort_table () sorts the line table consisting of nel elements. */
XX! void sort_table(nel)
XX  register int nel;
XX  {
XX    char *tmp;
XX***************
XX*** 616,622 ****
XX  }
XX  
XX  /* Incr () increments the heap. */
XX! incr(si, ei)
XX  register int si, ei;
XX  {
XX    char *tmp;
XX--- 639,645 ----
XX  }
XX  
XX  /* Incr () increments the heap. */
XX! void incr(si, ei)
XX  register int si, ei;
XX  {
XX    char *tmp;
XX***************
XX*** 637,643 ****
XX   * puts it into the line1 and line2 arrays. It then calls the cmp () routine
XX   * with the field describing the arguments.
XX   */
XX! cmp_fields(el1, el2)
XX  register char *el1, *el2;
XX  {
XX    int i, ret;
XX--- 660,666 ----
XX   * puts it into the line1 and line2 arrays. It then calls the cmp () routine
XX   * with the field describing the arguments.
XX   */
XX! int cmp_fields(el1, el2)
XX  register char *el1, *el2;
XX  {
XX    int i, ret;
XX***************
XX*** 646,652 ****
XX    for (i = 0; i < field_cnt; i++) {	/* Setup line parts */
XX  	build_field(line1, &fields[i + 1], el1);
XX  	build_field(line2, &fields[i + 1], el2);
XX! 	if ((ret = cmp(line1, line2, &fields[i + 1])) != SAME)
XX  		break;		/* If equal, try next field */
XX    }
XX  
XX--- 669,676 ----
XX    for (i = 0; i < field_cnt; i++) {	/* Setup line parts */
XX  	build_field(line1, &fields[i + 1], el1);
XX  	build_field(line2, &fields[i + 1], el2);
XX! 	if ((ret = cmp((unsigned char *) line1, (unsigned char *) line2,
XX! 		       &fields[i + 1])) != SAME)
XX  		break;		/* If equal, try next field */
XX    }
XX  
XX***************
XX*** 660,666 ****
XX  /* Build_field builds a new line from the src as described by the field.
XX   * The result is put in dest.
XX   */
XX! build_field(dest, field, src)
XX  char *dest;			/* Holds result */
XX  register FIELD *field;		/* Field description */
XX  register char *src;		/* Source line */
XX--- 684,690 ----
XX  /* Build_field builds a new line from the src as described by the field.
XX   * The result is put in dest.
XX   */
XX! void build_field(dest, field, src)
XX  char *dest;			/* Holds result */
XX  register FIELD *field;		/* Field description */
XX  register char *src;		/* Source line */
XX***************
XX*** 708,729 ****
XX   * has been made. if so, it calls cmp_fields (). If not, it calls cmp () and
XX   * reversed the return value if the (global) reverse flag is set.
XX   */
XX! compare(el1, el2)
XX  register char *el1, *el2;
XX  {
XX    int ret;
XX  
XX    if (field_cnt > GLOBAL) return cmp_fields(el1, el2);
XX  
XX!   ret = cmp(el1, el2, &fields[GLOBAL]);
XX    return(fields[GLOBAL].reverse) ? -ret : ret;
XX  }
XX  
XX  /* Cmp () is the actual compare routine. It compares according to the
XX   * description given in the field pointer.
XX   */
XX! cmp(el1, el2, field)
XX! register char *el1, *el2;
XX  FIELD *field;
XX  {
XX    int c1, c2;
XX--- 732,753 ----
XX   * has been made. if so, it calls cmp_fields (). If not, it calls cmp () and
XX   * reversed the return value if the (global) reverse flag is set.
XX   */
XX! int compare(el1, el2)
XX  register char *el1, *el2;
XX  {
XX    int ret;
XX  
XX    if (field_cnt > GLOBAL) return cmp_fields(el1, el2);
XX  
XX!   ret = cmp((unsigned char *) el1, (unsigned char *) el2, &fields[GLOBAL]);
XX    return(fields[GLOBAL].reverse) ? -ret : ret;
XX  }
XX  
XX  /* Cmp () is the actual compare routine. It compares according to the
XX   * description given in the field pointer.
XX   */
XX! int cmp(el1, el2, field)
XX! register unsigned char *el1, *el2;
XX  FIELD *field;
XX  {
XX    int c1, c2;
XX***************
XX*** 733,739 ****
XX  	while (table[*el2] & BLANK) el2++;
XX    }
XX    if (field->numeric)		/* Compare numeric */
XX! 	return digits(el1, el2, TRUE);
XX  
XX    for (;;) {
XX  	while (*el1 == *el2) {
XX--- 757,763 ----
XX  	while (table[*el2] & BLANK) el2++;
XX    }
XX    if (field->numeric)		/* Compare numeric */
XX! 	return digits((char *) el1, (char *) el2, TRUE);
XX  
XX    for (;;) {
XX  	while (*el1 == *el2) {
XX***************
XX*** 788,794 ****
XX   * Digits compares () the two strings that point to a number of digits followed
XX   * by an optional decimal point.
XX   */
XX! digits(str1, str2, check_sign)
XX  register char *str1, *str2;
XX  BOOL check_sign;		/* True if sign must be checked */
XX  {
XX--- 812,818 ----
XX   * Digits compares () the two strings that point to a number of digits followed
XX   * by an optional decimal point.
XX   */
XX! int digits(str1, str2, check_sign)
XX  register char *str1, *str2;
XX  BOOL check_sign;		/* True if sign must be checked */
XX  {
XX***************
XX*** 854,860 ****
XX  /* Files_merge () merges all files as indicated by nr_of_files. Merging goes
XX   * in numbers of files that can be opened at the same time. (OPEN_FILES)
XX   */
XX! files_merge(file_cnt)
XX  register int file_cnt;		/* Nr_of_files to merge */
XX  {
XX    register int i;
XX--- 878,884 ----
XX  /* Files_merge () merges all files as indicated by nr_of_files. Merging goes
XX   * in numbers of files that can be opened at the same time. (OPEN_FILES)
XX   */
XX! void files_merge(file_cnt)
XX  register int file_cnt;		/* Nr_of_files to merge */
XX  {
XX    register int i;
XX***************
XX*** 882,888 ****
XX  }
XX  
XX  /* Merge () merges the files between start_file and limit_file. */
XX! merge(start_file, limit_file)
XX  int start_file, limit_file;
XX  {
XX    register MERGE *smallest;	/* Keeps track of smallest line */
XX--- 906,912 ----
XX  }
XX  
XX  /* Merge () merges the files between start_file and limit_file. */
XX! void merge(start_file, limit_file)
XX  int start_file, limit_file;
XX  {
XX    register MERGE *smallest;	/* Keeps track of smallest line */
XX***************
XX*** 951,957 ****
XX  /* Put_line () prints the line into the out_fd filedescriptor. If line equals
XX   * NIL_PTR, the out_fd is flushed and closed.
XX   */
XX! put_line(line)
XX  register char *line;
XX  {
XX    static int index = 0;		/* Index in out_buffer */
XX--- 975,981 ----
XX  /* Put_line () prints the line into the out_fd filedescriptor. If line equals
XX   * NIL_PTR, the out_fd is flushed and closed.
XX   */
XX! void put_line(line)
XX  register char *line;
XX  {
XX    static int index = 0;		/* Index in out_buffer */
XX***************
XX*** 1002,1008 ****
XX   * done in buf_size bytes.
XX   * Lines longer than LINE_SIZE are silently truncated.
XX   */
XX! read_line(merg)
XX  register MERGE *merg;
XX  {
XX    register char *ptr = merg->line - 1;	/* Ptr buf that will hold line */
XX--- 1026,1032 ----
XX   * done in buf_size bytes.
XX   * Lines longer than LINE_SIZE are silently truncated.
XX   */
XX! int read_line(merg)
XX  register MERGE *merg;
XX  {
XX    register char *ptr = merg->line - 1;	/* Ptr buf that will hold line */
XX***************
XX*** 1056,1062 ****
XX  }
XX  
XX  /* Uniq_lines () prints only the uniq lines out of the fd of the merg struct. */
XX! uniq_lines(merg)
XX  register MERGE *merg;
XX  {
XX    char lastline[LINE_SIZE];	/* Buffer to hold last line */
XX--- 1080,1086 ----
XX  }
XX  
XX  /* Uniq_lines () prints only the uniq lines out of the fd of the merg struct. */
XX! void uniq_lines(merg)
XX  register MERGE *merg;
XX  {
XX    char lastline[LINE_SIZE];	/* Buffer to hold last line */
XX***************
XX*** 1078,1084 ****
XX   * Check_file () checks if a file is sorted in order according to the arguments
XX   * given in main ().
XX   */
XX! check_file(fd, file)
XX  int fd;
XX  char *file;
XX  {
XX--- 1102,1108 ----
XX   * Check_file () checks if a file is sorted in order according to the arguments
XX   * given in main ().
XX   */
XX! void check_file(fd, file)
XX  int fd;
XX  char *file;
XX  {
XX***************
XX*** 1118,1124 ****
XX  }
XX  
XX  /* Length () returns the length of the argument line including the linefeed. */
XX! length(line)
XX  register char *line;
XX  {
XX    register int i = 1;		/* Add linefeed */
XX--- 1142,1148 ----
XX  }
XX  
XX  /* Length () returns the length of the argument line including the linefeed. */
XX! int length(line)
XX  register char *line;
XX  {
XX    register int i = 1;		/* Add linefeed */
XX***************
XX*** 1128,1134 ****
XX  }
XX  
XX  /* Copy () copies the src line into the dest line including linefeed. */
XX! copy(dest, src)
XX  register char *dest, *src;
XX  {
XX    while ((*dest++ = *src++) != '\n');
XX--- 1152,1158 ----
XX  }
XX  
XX  /* Copy () copies the src line into the dest line including linefeed. */
XX! void copy(dest, src)
XX  register char *dest, *src;
XX  {
XX    while ((*dest++ = *src++) != '\n');
XX***************
XX*** 1136,1144 ****
XX  
XX  /* Msbrk() does a sbrk() and checks the return value. */
XX  char *msbrk(size)
XX! register size;
XX  {
XX-   extern char *sbrk();
XX    register char *address;
XX  
XX    if ((address = sbrk(size)) == (char *) -1)
XX--- 1160,1167 ----
XX  
XX  /* Msbrk() does a sbrk() and checks the return value. */
XX  char *msbrk(size)
XX! register int size;
XX  {
XX    register char *address;
XX  
XX    if ((address = sbrk(size)) == (char *) -1)
XX***************
XX*** 1147,1169 ****
XX  }
XX  
XX  /* Mbrk() does a brk() and checks the return value. */
XX! char *mbrk(address)
XX  char *address;
XX  {
XX!   extern char *brk();
XX! 
XX!   if ((address = brk(address)) == (char *) -1)
XX! 	error(TRUE, "Cannot reset memory", NIL_PTR);
XX!   return address;
XX  }
XX  
XX! void catch()
XX  {
XX!   register short i;
XX  
XX    signal(SIGINT, SIG_IGN);
XX    only_merge = FALSE;
XX    for (i = 0; i < 26; i++) (void) unlink(file_name(i));
XX    exit(2);
XX  }
XX- 
XX--- 1170,1188 ----
XX  }
XX  
XX  /* Mbrk() does a brk() and checks the return value. */
XX! void mbrk(address)
XX  char *address;
XX  {
XX!   if (brk(address) < 0) error(TRUE, "Cannot reset memory", NIL_PTR);
XX  }
XX  
XX! void catch(dummy)
XX! int dummy;			/* to satisfy the prototype */
XX  {
XX!   register int i;
XX  
XX    signal(SIGINT, SIG_IGN);
XX    only_merge = FALSE;
XX    for (i = 0; i < 26; i++) (void) unlink(file_name(i));
XX    exit(2);
XX  }
X/
Xecho x - split.c.d
Xsed '/^X/s///' > split.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/split.c  crc=26163   2032	Sun Apr 25 21:35:18 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/split.c  crc=31814   2319	Wed Nov  4 04:19:20 1992
XX***************
XX*** 2,15 ****
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <blocksize.h>
XX  
XX  int cut_line = 1000;
XX  int infile;
XX  char out_file[100];
XX  char *suffix;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 2,25 ----
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX  #include <blocksize.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX  
XX  int cut_line = 1000;
XX  int infile;
XX  char out_file[100];
XX  char *suffix;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void split, (void));
XX! _PROTOTYPE(int newfile, (void));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(void quit, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 44,53 ****
XX  /* Appendix now points to last `a' of "aa". We have to decrement it by one */
XX    *suffix = 'a' - 1;
XX    split();
XX!   exit(0);
XX  }
XX  
XX! split()
XX  {
XX    char buf[BLOCK_SIZE];
XX    register char *index, *base;
XX--- 54,63 ----
XX  /* Appendix now points to last `a' of "aa". We have to decrement it by one */
XX    *suffix = 'a' - 1;
XX    split();
XX!   return(0);
XX  }
XX  
XX! void split()
XX  {
XX    char buf[BLOCK_SIZE];
XX    register char *index, *base;
XX***************
XX*** 76,82 ****
XX    }
XX  }
XX  
XX! newfile()
XX  {
XX    int fd;
XX  
XX--- 86,92 ----
XX    }
XX  }
XX  
XX! int newfile()
XX  {
XX    int fd;
XX  
XX***************
XX*** 93,105 ****
XX    return fd;
XX  }
XX  
XX! usage()
XX  {
XX    std_err("Usage: split [-n] [file [name]].\n");
XX    exit(1);
XX  }
XX  
XX! quit()
XX  {
XX    std_err("split: write error\n");
XX    exit(1);
XX--- 103,115 ----
XX    return fd;
XX  }
XX  
XX! void usage()
XX  {
XX    std_err("Usage: split [-n] [file [name]].\n");
XX    exit(1);
XX  }
XX  
XX! void quit()
XX  {
XX    std_err("split: write error\n");
XX    exit(1);
X/
Xecho x - strings.c.d
Xsed '/^X/s///' > strings.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/strings.c  crc=26719   3878	Sun Apr 25 21:35:19 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/strings.c  crc=16504   4030	Wed Nov  4 04:19:20 1992
XX***************
XX*** 33,38 ****
XX--- 33,40 ----
XX  
XX  
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  /* Minix (8086 version) dependant definitions */
XX***************
XX*** 52,58 ****
XX  #define	STRLEN		4	/* default minimum string length */
XX  #define STRBUF		512	/* buffer length for strings */
XX  
XX! void strings(), usage();
XX  
XX  int strmin = STRLEN;		/* minimum string length */
XX  int printoff = 0;		/* print octal offset of each str */
XX--- 54,62 ----
XX  #define	STRLEN		4	/* default minimum string length */
XX  #define STRBUF		512	/* buffer length for strings */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void strings, (char *filename));
XX! _PROTOTYPE(void usage, (void));
XX  
XX  int strmin = STRLEN;		/* minimum string length */
XX  int printoff = 0;		/* print octal offset of each str */
XX***************
XX*** 60,66 ****
XX  
XX  /* Just initialized data segment */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 64,70 ----
XX  
XX  /* Just initialized data segment */
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 77,83 ****
XX  
XX    if (0 == argc) usage();
XX    while (argc--) strings(*argv++);
XX!   exit(0);
XX  }
XX  
XX  void strings(filename)
XX--- 81,87 ----
XX  
XX    if (0 == argc) usage();
XX    while (argc--) strings(*argv++);
XX!   return(0);
XX  }
XX  
XX  void strings(filename)
XX***************
XX*** 96,102 ****
XX  	perror(filename);
XX  	exit(1);
XX    }
XX!   if (HDR_LEN == fread(header, sizeof(long), HDR_LEN, input)
XX        && (SMALLMAGIC == header[HDR_MAGIC]
XX  	||SEPARATEMAGIC == header[HDR_MAGIC]) && !objall) {
XX  	offset = header[HDR_HSIZE] + header[HDR_TSIZE];	/* object file */
XX--- 100,106 ----
XX  	perror(filename);
XX  	exit(1);
XX    }
XX!   if (HDR_LEN == fread(header, sizeof(long), (size_t)HDR_LEN, input)
XX        && (SMALLMAGIC == header[HDR_MAGIC]
XX  	||SEPARATEMAGIC == header[HDR_MAGIC]) && !objall) {
XX  	offset = header[HDR_HSIZE] + header[HDR_TSIZE];	/* object file */
X/
Xecho x - strip.c.d
Xsed '/^X/s///' > strip.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/strip.c  crc=10548   3319	Sun Apr 25 21:35:19 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/strip.c  crc=06067   3637	Wed Nov  4 04:19:20 1992
XX***************
XX*** 6,11 ****
XX--- 6,12 ----
XX  #include <a.out.h>
XX  #include <unistd.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  /* Strip [file] ...
XX***************
XX*** 21,27 ****
XX  char new_file[NAME_LENGTH];	/* contains name of temporary */
XX  struct exec header;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 22,35 ----
XX  char new_file[NAME_LENGTH];	/* contains name of temporary */
XX  struct exec header;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void strip, (char *file));
XX! _PROTOTYPE(int read_header, (int fd));
XX! _PROTOTYPE(int write_header, (int fd));
XX! _PROTOTYPE(int make_tmp, (char *new_name, char *name));
XX! _PROTOTYPE(int copy_file, (int fd1, int fd2, long size));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 33,42 ****
XX  		strip(*argv);
XX  		argv++;
XX  	}
XX!   exit(0);
XX  }
XX  
XX! strip(file)
XX  char *file;
XX  {
XX    int fd, new_fd;
XX--- 41,50 ----
XX  		strip(*argv);
XX  		argv++;
XX  	}
XX!   return(0);
XX  }
XX  
XX! void strip(file)
XX  char *file;
XX  {
XX    int fd, new_fd;
XX***************
XX*** 69,75 ****
XX  	return;
XX    }
XX    if (write_header(new_fd)) {
XX! 	fprintf(stderr, "%s: can't write temporary file\n");
XX  	unlink(new_file);
XX  	close(fd);
XX  	close(new_fd);
XX--- 77,83 ----
XX  	return;
XX    }
XX    if (write_header(new_fd)) {
XX! 	fprintf(stderr, "can't write temporary file\n");
XX  	unlink(new_file);
XX  	close(fd);
XX  	close(new_fd);
XX***************
XX*** 104,110 ****
XX    chmod(file, buf.st_mode);
XX  }
XX  
XX! read_header(fd)
XX  int fd;
XX  {
XX    if (read(fd, (char *) &header, A_MINHDR) != A_MINHDR) return(1);
XX--- 112,118 ----
XX    chmod(file, buf.st_mode);
XX  }
XX  
XX! int read_header(fd)
XX  int fd;
XX  {
XX    if (read(fd, (char *) &header, A_MINHDR) != A_MINHDR) return(1);
XX***************
XX*** 116,122 ****
XX    return(0);
XX  }
XX  
XX! write_header(fd)
XX  int fd;
XX  {
XX    lseek(fd, 0L, SEEK_SET);
XX--- 124,130 ----
XX    return(0);
XX  }
XX  
XX! int write_header(fd)
XX  int fd;
XX  {
XX    lseek(fd, 0L, SEEK_SET);
XX***************
XX*** 142,148 ****
XX    return(creat(new_name, 0777));
XX  }
XX  
XX! copy_file(fd1, fd2, size)
XX  int fd1, fd2;
XX  long size;
XX  {
XX--- 150,156 ----
XX    return(creat(new_name, 0777));
XX  }
XX  
XX! int copy_file(fd1, fd2, size)
XX  int fd1, fd2;
XX  long size;
XX  {
X/
Xecho x - stty.c.d
Xsed '/^X/s///' > stty.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/stty.c  crc=38154   5511	Sun Apr 25 21:35:19 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/stty.c  crc=35437   6235	Mon Jan 18 18:56:10 1993
XX***************
XX*** 1,6 ****
XX--- 1,10 ----
XX  /* stty - set terminal mode	  	Author: Andy Tanenbaum */
XX  
XX  #include <sgtty.h>
XX+ #include <stdlib.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX+ 
XX  char *on[] = {"tabs", "cbreak", "raw", "-nl", "echo", "odd", "even"};
XX  char *off[] = {"-tabs", "", "", "nl", "-echo", "", ""};
XX  int k;
XX***************
XX*** 20,33 ****
XX  #define clr1 args.sg_flags &= ~(BITS5 | BITS6 | BITS7 | BITS8)
XX  #define clr2 args.sg_flags &= ~(EVENP | ODDP)
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  
XX    /* Stty with no arguments just reports on current status. */
XX    if (ioctl(FD,TIOCGETP,&args)<0 || ioctl(FD,TIOCGETC,(struct sgttyb*)&tch)<0){
XX! 	prints("%s: can't read ioctl parameters from stdin\n", argv[0]);
XX  	exit(1);
XX    }
XX    if (argc == 1) {
XX--- 24,44 ----
XX  #define clr1 args.sg_flags &= ~(BITS5 | BITS6 | BITS7 | BITS8)
XX  #define clr2 args.sg_flags &= ~(EVENP | ODDP)
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void report, (void));
XX! _PROTOTYPE(void pr, (int f, int n));
XX! _PROTOTYPE(void option, (char *opt, char *next));
XX! _PROTOTYPE(int match, (char *s1, char *s2));
XX! _PROTOTYPE(void prctl, (int c));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  
XX    /* Stty with no arguments just reports on current status. */
XX    if (ioctl(FD,TIOCGETP,&args)<0 || ioctl(FD,TIOCGETC,(struct sgttyb*)&tch)<0){
XX! 	printf("%s: can't read ioctl parameters from stdin\n", argv[0]);
XX  	exit(1);
XX    }
XX    if (argc == 1) {
XX***************
XX*** 42,56 ****
XX  	k++;
XX    }
XX    if (ioctl(FD,TIOCSETP,&args)<0 || ioctl(FD,TIOCSETC,(struct sgttyb*)&tch)<0){
XX! 	prints("%s: can't write ioctl parameters to stdin\n", argv[0]);
XX  	exit(2);
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX  
XX! report()
XX  {
XX    int mode, ispeed, ospeed;
XX  
XX--- 53,67 ----
XX  	k++;
XX    }
XX    if (ioctl(FD,TIOCSETP,&args)<0 || ioctl(FD,TIOCSETC,(struct sgttyb*)&tch)<0){
XX! 	printf("%s: can't write ioctl parameters to stdin\n", argv[0]);
XX  	exit(2);
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX  
XX! void report()
XX  {
XX    int mode, ispeed, ospeed;
XX  
XX***************
XX*** 65,115 ****
XX  
XX    ispeed = 100 * ((int) args.sg_ispeed & BYTE);
XX    ospeed = 100 * ((int) args.sg_ospeed & BYTE);
XX!   prints("\nkill = ");
XX    prctl(args.sg_kill);
XX!   prints("\nerase = ");
XX    prctl(args.sg_erase);
XX!   prints("\nint = ");
XX    prctl(tch.t_intrc);
XX!   prints("\nquit = ");
XX    prctl(tch.t_quitc);
XX    if (ispeed > 0) {
XX! 	prints("\nspeed = ");
XX  	switch (ispeed) {
XX! 	    case 100:	prints("110");	break;
XX! 	    case 200:	prints("200");	break;
XX! 	    case 300:	prints("300");	break;
XX! 	    case 600:	prints("600");	break;
XX! 	    case 1200:	prints("1200");	break;
XX! 	    case 1800:	prints("1800");	break;
XX! 	    case 2400:	prints("2400");	break;
XX! 	    case 3600:	prints("3600");	break;
XX! 	    case 4800:	prints("4800");	break;
XX! 	    case 7200:	prints("7200");	break;
XX! 	    case 9600:	prints("9600");	break;
XX! 	    case 19200:	prints("19200");	break;
XX! 	    default:	prints("unknown");
XX  	}
XX  	switch (mode & BITS8) {
XX! 	    case BITS5:	prints("\nbits = 5");	break;
XX! 	    case BITS6:	prints("\nbits = 6");	break;
XX! 	    case BITS7:	prints("\nbits = 7");	break;
XX! 	    case BITS8:	prints("\nbits = 8");	break;
XX  	}
XX    }
XX!   prints("\n");
XX  }
XX  
XX! pr(f, n)
XX  int f, n;
XX  {
XX    if (f)
XX! 	prints("%s ", on[n]);
XX    else
XX! 	prints("%s ", off[n]);
XX  }
XX  
XX! option(opt, next)
XX  char *opt, *next;
XX  {
XX    if (match(opt, "-tabs")) {
XX--- 76,130 ----
XX  
XX    ispeed = 100 * ((int) args.sg_ispeed & BYTE);
XX    ospeed = 100 * ((int) args.sg_ospeed & BYTE);
XX!   printf("\nkill = ");
XX    prctl(args.sg_kill);
XX!   printf("\nerase = ");
XX    prctl(args.sg_erase);
XX!   printf("\nint = ");
XX    prctl(tch.t_intrc);
XX!   printf("\nquit = ");
XX    prctl(tch.t_quitc);
XX    if (ispeed > 0) {
XX! 	printf("\nspeed = ");
XX  	switch (ispeed) {
XX! 	    case 100:	printf("110");	break;
XX! 	    case 200:	printf("200");	break;
XX! 	    case 300:	printf("300");	break;
XX! 	    case 600:	printf("600");	break;
XX! 	    case 1200:	printf("1200");	break;
XX! 	    case 1800:	printf("1800");	break;
XX! 	    case 2400:	printf("2400");	break;
XX! 	    case 3600:	printf("3600");	break;
XX! 	    case 4800:	printf("4800");	break;
XX! 	    case 7200:	printf("7200");	break;
XX! 	    case 9600:	printf("9600");	break;
XX! 	    case 19200:	printf("19200");	break;
XX! 	    case 19300:	printf("115200");	break;
XX! 	    case 19400:	printf("57600");	break;
XX! 	    case 19500:	printf("38400");	break;
XX! 	    case 19600:	printf("28800");	break;
XX! 	    default:	printf("unknown");
XX  	}
XX  	switch (mode & BITS8) {
XX! 	    case BITS5:	printf("\nbits = 5");	break;
XX! 	    case BITS6:	printf("\nbits = 6");	break;
XX! 	    case BITS7:	printf("\nbits = 7");	break;
XX! 	    case BITS8:	printf("\nbits = 8");	break;
XX  	}
XX    }
XX!   printf("\n");
XX  }
XX  
XX! void pr(f, n)
XX  int f, n;
XX  {
XX    if (f)
XX! 	printf("%s ", on[n]);
XX    else
XX! 	printf("%s ", off[n]);
XX  }
XX  
XX! void option(opt, next)
XX  char *opt, *next;
XX  {
XX    if (match(opt, "-tabs")) {
XX***************
XX*** 258,263 ****
XX--- 273,294 ----
XX  	speed(192);
XX  	return;
XX    }
XX+   if (match(opt, "115200")) {
XX+ 	speed(193);
XX+ 	return;
XX+   }
XX+   if (match(opt, "57600")) {
XX+ 	speed(194);
XX+ 	return;
XX+   }
XX+   if (match(opt, "38400")) {
XX+ 	speed(195);
XX+ 	return;
XX+   }
XX+   if (match(opt, "28800")) {
XX+ 	speed(196);
XX+ 	return;
XX+   }
XX    if (match(opt, "default")) {
XX  	args.sg_flags = ECHO | CRMOD | XTABS | BITS8;
XX  	args.sg_ispeed = B1200;
XX***************
XX*** 290,302 ****
XX    }
XX  }
XX  
XX! prctl(c)
XX  char c;
XX  {
XX    if (c < ' ')
XX! 	prints("^%c", 'A' + c - 1);
XX    else if (c == 0177)
XX! 	prints("DEL");
XX    else
XX! 	prints("%c", c);
XX  }
XX--- 321,333 ----
XX    }
XX  }
XX  
XX! void prctl(c)
XX  char c;
XX  {
XX    if (c < ' ')
XX! 	printf("^%c", 'A' + c - 1);
XX    else if (c == 0177)
XX! 	printf("DEL");
XX    else
XX! 	printf("%c", c);
XX  }
X/
Xecho x - su.c.d
Xsed '/^X/s///' > su.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/su.c  crc=02381   1188	Sun Apr 25 21:35:20 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/su.c  crc=14819   1826	Wed Nov  4 07:51:31 1992
XX***************
XX*** 1,26 ****
XX  /* su - become super-user		Author: Patrick van Kleef */
XX  
XX  #include <sys/types.h>
XX- #include <sgtty.h>
XX  #include <pwd.h>
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   register char *name;
XX!   char *crypt();
XX    char *shell = "/bin/sh";
XX    char *shell2 = "/usr/bin/sh";
XX    int nr;
XX-   char password[14];
XX-   struct sgttyb args;
XX    register struct passwd *pwd;
XX!   struct passwd *getpwnam();
XX  
XX!   if (argc > 1)
XX  	name = argv[1];
XX!   else
XX  	name = "root";
XX  
XX    if ((pwd = getpwnam(name)) == 0) {
XX--- 1,46 ----
XX  /* su - become super-user		Author: Patrick van Kleef */
XX  
XX  #include <sys/types.h>
XX  #include <pwd.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX  
XX! #ifdef SUPERGROUP
XX! /* If this flag is set then su allows members of group 0 to become each other
XX!  * without a password.  See passwd(1) for more.  (kjb)
XX!  */
XX! #define getid()	getgid()
XX! #else
XX! #define getid()	getuid()
XX! #endif
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int putenv, (char *env));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   register char *name, *password;
XX    char *shell = "/bin/sh";
XX    char *shell2 = "/usr/bin/sh";
XX    int nr;
XX    register struct passwd *pwd;
XX!   static char USER[20], LOGNAME[25], HOME[100], SHELL[100];
XX  
XX!   if (argc > 1 && strcmp(argv[1], "-") == 0) {
XX! 	if (argv[0][0] != 0) argv[0][0] = '-';	/* Read .profile */
XX! 	argv[1] = argv[0];
XX! 	argv++;
XX! 	argc--;
XX!   }
XX!   if (argc > 1) {
XX  	name = argv[1];
XX! 	argv[1] = argv[0];
XX! 	argv++;
XX!   } else
XX  	name = "root";
XX  
XX    if ((pwd = getpwnam(name)) == 0) {
XX***************
XX*** 29,44 ****
XX  	std_err("\n");
XX  	exit(1);
XX    }
XX!   if (pwd->pw_passwd[0] != '\0' && getuid() != 0) {
XX! 	std_err("Password: ");
XX! 	ioctl(0, TIOCGETP, &args);	/* get parameters */
XX! 	args.sg_flags = args.sg_flags & (~ECHO);
XX! 	ioctl(0, TIOCSETP, &args);
XX! 	nr = read(0, password, 14);
XX! 	password[nr - 1] = 0;
XX! 	std_err("\n");
XX! 	args.sg_flags = args.sg_flags | ECHO;
XX! 	ioctl(0, TIOCSETP, &args);
XX  	if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))) {
XX  		std_err("Sorry\n");
XX  		exit(2);
XX--- 49,56 ----
XX  	std_err("\n");
XX  	exit(1);
XX    }
XX!   if (pwd->pw_passwd[0] != '\0' && getid() != 0) {
XX! 	password = getpass("Password:");
XX  	if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))) {
XX  		std_err("Sorry\n");
XX  		exit(2);
XX***************
XX*** 46,54 ****
XX    }
XX    setgid(pwd->pw_gid);
XX    setuid(pwd->pw_uid);
XX!   if (pwd->pw_shell[0]) shell = pwd->pw_shell;
XX!   execl(shell, shell, "-i", (char *) 0);
XX!   execl(shell2, shell2, "-i", (char *) 0);
XX    std_err("No shell\n");
XX!   exit(3);
XX  }
XX--- 58,84 ----
XX    }
XX    setgid(pwd->pw_gid);
XX    setuid(pwd->pw_uid);
XX!   if (pwd->pw_shell[0] != '\0')
XX! 	shell = pwd->pw_shell;
XX!   else {
XX! 	if (access(shell, 0) < 0) shell = shell2;
XX!   }
XX!   if (argv[0][0] == '-') {
XX! 	strcpy(USER, "USER=");
XX! 	strcpy(USER + 5, name);
XX! 	putenv(USER);
XX! 	strcpy(LOGNAME, "LOGNAME=");
XX! 	strcpy(LOGNAME + 8, name);
XX! 	putenv(LOGNAME);
XX! 	strcpy(SHELL, "SHELL=");
XX! 	strcpy(SHELL + 6, shell);
XX! 	putenv(SHELL);
XX! 	strcpy(HOME, "HOME=");
XX! 	strcpy(HOME + 5, pwd->pw_dir);
XX! 	putenv(HOME);
XX! 	(void) chdir(pwd->pw_dir);
XX!   }
XX!   execv(shell, argv);
XX    std_err("No shell\n");
XX!   return(3);
XX  }
X/
Xecho x - sum.c.d
Xsed '/^X/s///' > sum.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/sum.c  crc=28429   1861	Sun Apr 25 21:35:20 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/sum.c  crc=46598   2185	Wed Nov  4 04:19:21 1992
XX***************
XX*** 13,26 ****
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  
XX! #define BUFSIZ (512)
XX  
XX  int rc = 0;
XX  
XX  char *defargv[] = {"-", 0};
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 13,35 ----
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX! #define BUFFER_SIZE (512)
XX  
XX  int rc = 0;
XX  
XX  char *defargv[] = {"-", 0};
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void error, (char *s, char *f));
XX! _PROTOTYPE(void sum, (int fd, char *fname));
XX! _PROTOTYPE(void putd, (int number, int fw, int zeros));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 41,50 ****
XX  	sum(fd, (argc > 2) ? *argv : (char *) 0);
XX  	if (fd != 0) close(fd);
XX    }
XX!   exit(rc);
XX  }
XX  
XX! error(s, f)
XX  char *s, *f;
XX  {
XX  
XX--- 50,59 ----
XX  	sum(fd, (argc > 2) ? *argv : (char *) 0);
XX  	if (fd != 0) close(fd);
XX    }
XX!   return(rc);
XX  }
XX  
XX! void error(s, f)
XX  char *s, *f;
XX  {
XX  
XX***************
XX*** 55,71 ****
XX    std_err("\n");
XX  }
XX  
XX! sum(fd, fname)
XX  int fd;
XX  char *fname;
XX  {
XX!   char buf[BUFSIZ];
XX    register int i, n;
XX    long size = 0;
XX    unsigned crc = 0;
XX    unsigned tmp, blks;
XX  
XX!   while ((n = read(fd, buf, BUFSIZ)) > 0) {
XX  	for (i = 0; i < n; i++) {
XX  		crc = (crc >> 1) + ((crc & 1) ? 0x8000 : 0);
XX  		tmp = buf[i] & 0377;
XX--- 64,80 ----
XX    std_err("\n");
XX  }
XX  
XX! void sum(fd, fname)
XX  int fd;
XX  char *fname;
XX  {
XX!   char buf[BUFFER_SIZE];
XX    register int i, n;
XX    long size = 0;
XX    unsigned crc = 0;
XX    unsigned tmp, blks;
XX  
XX!   while ((n = read(fd, buf, BUFFER_SIZE)) > 0) {
XX  	for (i = 0; i < n; i++) {
XX  		crc = (crc >> 1) + ((crc & 1) ? 0x8000 : 0);
XX  		tmp = buf[i] & 0377;
XX***************
XX*** 84,96 ****
XX  	return;
XX    }
XX    putd(crc, 5, 1);
XX!   blks = (size + (long) BUFSIZ - 1L) / (long) BUFSIZ;
XX    putd(blks, 6, 0);
XX!   if (fname) prints(" %s", fname);
XX!   prints("\n");
XX  }
XX  
XX! putd(number, fw, zeros)
XX  int number, fw, zeros;
XX  {
XX  /* Put a decimal number, in a field width, to stdout. */
XX--- 93,105 ----
XX  	return;
XX    }
XX    putd(crc, 5, 1);
XX!   blks = (size + (long) BUFFER_SIZE - 1L) / (long) BUFFER_SIZE;
XX    putd(blks, 6, 0);
XX!   if (fname) printf(" %s", fname);
XX!   printf("\n");
XX  }
XX  
XX! void putd(number, fw, zeros)
XX  int number, fw, zeros;
XX  {
XX  /* Put a decimal number, in a field width, to stdout. */
XX***************
XX*** 108,112 ****
XX  		buf[fw - n - 1] = zeros ? '0' : ' ';
XX    }
XX    buf[fw] = 0;
XX!   prints("%s", buf);
XX  }
XX--- 117,121 ----
XX  		buf[fw - n - 1] = zeros ? '0' : ' ';
XX    }
XX    buf[fw] = 0;
XX!   printf("%s", buf);
XX  }
X/
Xecho x - sync.c.d
Xsed '/^X/s///' > sync.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/sync.c  crc=57085    144	Sun Apr 25 21:35:20 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/sync.c  crc=59668    269	Wed Nov  4 04:19:21 1992
XX***************
XX*** 1,7 ****
XX  /* sync - flush the file system buffers.  Author: Andy Tanenbaum */
XX  
XX! main()
XX  {
XX  /* First prize in shortest useful program contest. */
XX    sync();
XX  }
XX--- 1,14 ----
XX  /* sync - flush the file system buffers.  Author: Andy Tanenbaum */
XX  
XX! #include <sys/types.h>
XX! #include <unistd.h>
XX! 
XX! _PROTOTYPE(int main, (void));
XX! 
XX! int main()
XX  {
XX  /* First prize in shortest useful program contest. */
XX+ /* Highest comment/code ratio */
XX    sync();
XX+   return(0);
XX  }
X/
Xecho x - tail.c.d
Xsed '/^X/s///' > tail.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tail.c  crc=07378   2421	Sun Apr 25 21:35:21 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tail.c  crc=01807  10188	Wed Nov  4 04:19:21 1992
XX***************
XX*** 1,145 ****
XX! /* tail - print the end of a file */
XX  
XX  #include <stdio.h>
XX  
XX! #define TRUE 1
XX  #define FALSE 0
XX! #define BLANK ' '
XX! #define TAB '\t'
XX! #define NEWL '\n'
XX  
XX! int lines, chars;
XX! char buff[BUFSIZ];
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   char *s;
XX!   FILE *input, *fopen();
XX!   int count;
XX  
XX!   setbuf(stdout, buff);
XX!   argc--;
XX!   argv++;
XX!   lines = TRUE;
XX!   chars = FALSE;
XX!   count = -10;
XX! 
XX!   if (argc == 0) {
XX! 	tail(stdin, count);
XX! 	exit(0);
XX    }
XX!   s = *argv;
XX!   if (*s == '-' || *s == '+') {
XX! 	s++;
XX! 	if (*s >= '0' && *s <= '9') {
XX! 		count = stoi(*argv);
XX! 		s++;
XX! 		while (*s >= '0' && *s <= '9') s++;
XX  	}
XX! 	if (*s == 'c') {
XX! 		chars = TRUE;
XX! 		lines = FALSE;
XX! 	} else if (*s != 'l' && *s != '\0') {
XX! 		fprintf(stderr, "tail: unknown option %c\n", *s);
XX! 		argc = 0;
XX  	}
XX! 	argc--;
XX! 	argv++;
XX    }
XX!   if (argc < 0) {
XX! 	fprintf(stderr, "Usage: tail [+/-[number][lc]] [files]\n");
XX! 	exit(1);
XX    }
XX-   if (argc == 0) tail(stdin, count);
XX  
XX!   else if ((input = fopen(*argv, "r")) == NULL) {
XX! 	fprintf(stderr, "tail: can't open %s\n", *argv);
XX! 	exit(1);
XX    } else {
XX! 	tail(input, count);
XX! 	fclose(input);
XX    }
XX! 
XX!   exit(0);
XX  }
XX  
XX! /* Stoi - convert string to integer */
XX! stoi(s)
XX! char *s;
XX  {
XX!   int n, sign;
XX  
XX!   while (*s == BLANK || *s == NEWL || *s == TAB) s++;
XX  
XX!   sign = 1;
XX!   if (*s == '+')
XX! 	s++;
XX!   else if (*s == '-') {
XX! 	sign = -1;
XX! 	s++;
XX    }
XX-   for (n = 0; *s >= '0' && *s <= '9'; s++) n = 10 * n + *s - '0';
XX-   return(sign * n);
XX- }
XX  
XX! /* Tail - print 'count' lines/chars */
XX  
XX! #define INCR(p)  if (p >= end) p=cbuf ; else p++
XX! #define BUF_SIZE 4098
XX  
XX! char cbuf[BUF_SIZE];
XX  
XX! tail(in, goal)
XX! FILE *in;
XX! int goal;
XX  {
XX!   int c, count;
XX!   char *start, *finish, *end;
XX  
XX!   count = 0;
XX! 
XX!   if (goal > 0) {		/* skip */
XX! 	count++;		/* start counting at 1 */
XX! 	if (lines)		/* lines */
XX! 		while ((c = getc(in)) != EOF) {
XX! 			if (c == NEWL) count++;
XX! 			if (count >= goal) break;
XX! 		}
XX! 	else			/* chars */
XX! 		while (getc(in) != EOF) {
XX! 			count++;
XX! 			if (count >= goal) break;
XX! 		}
XX! 	if (count >= goal) while ((c = getc(in)) != EOF)
XX! 			putc(c, stdout);
XX!   } else {			/* tail */
XX! 
XX! 	goal = -goal;
XX! 	start = finish = cbuf;
XX! 	end = &cbuf[BUF_SIZE - 1];
XX! 
XX! 	while ((c = getc(in)) != EOF) {
XX! 		*finish = c;
XX! 		INCR(finish);
XX! 
XX! 		if (start == finish) INCR(start);
XX! 		if (!lines || c == NEWL) count++;
XX! 
XX! 		if (count > goal) {
XX! 			count = goal;
XX! 			if (lines) while (*start != NEWL)
XX! 					INCR(start);
XX! 			INCR(start);
XX! 		}
XX! 	}			/* end while */
XX! 
XX! 	while (start != finish) {
XX! 		putc(*start, stdout);
XX! 		INCR(start);
XX  	}
XX  
XX!   }				/* end else */
XX! 
XX! }				/* end tail */
XX--- 1,347 ----
XX! /* tail - copy the end of a file	Author: Norbert Schlenker */
XX  
XX+ /*   Syntax:	tail [-f] [-c number | -n number] [file]
XX+  *		tail -[number][c|l][f] [file]		(obsolescent)
XX+  *		tail +[number][c|l][f] [file]		(obsolescent)
XX+  *   Flags:
XX+  *	-c number	Measure starting point in bytes.  If number begins
XX+  *			with '+', the starting point is relative to the
XX+  *			the file's beginning.  If number begins with '-'
XX+  *			or has no sign, the starting point is relative to
XX+  *			the end of the file.
XX+  *	-f		Keep trying to read after EOF on files and FIFOs.
XX+  *	-n number	Measure starting point in lines.  The number
XX+  *			following the flag has significance similar to
XX+  *			that described for the -c flag.
XX+  *
XX+  *   If neither -c nor -n are specified, the default is tail -n 10.
XX+  *
XX+  *   In the obsolescent syntax, an argument with a 'c' following the
XX+  *   (optional) number is equivalent to "-c number" in the standard
XX+  *   syntax, with number including the leading sign ('+' or '-') of the
XX+  *   argument.  An argument with 'l' following the number is equivalent
XX+  *   to "-n number" in the standard syntax.  If the number is not
XX+  *   specified, 10 is used as the default.  If neither 'c' nor 'l' are
XX+  *   specified, 'l' is assumed.  The character 'f' may be suffixed to
XX+  *   the argument and is equivalent to specifying "-f" in the standard
XX+  *   syntax.  Look for lines marked "OBSOLESCENT".
XX+  *
XX+  *   If no file is specified, standard input is assumed. 
XX+  *
XX+  *   P1003.2 does not specify tail's behavior when a count of 0 is given.
XX+  *   It also does not specify clearly whether the first byte (line) of a
XX+  *   file should be numbered 0 or 1.  Historical behavior is that the
XX+  *   first byte is actually number 1 (contrary to all Unix standards).
XX+  *   Historically, a count of 0 (or -0) results in no output whatsoever,
XX+  *   while a count of +0 results in the entire file being copied (just like
XX+  *   +1).  The implementor does not agree with these behaviors, but has
XX+  *   copied them slavishly.  Look for lines marked "HISTORICAL".
XX+  *   
XX+  *   Author:    Norbert Schlenker
XX+  *   Copyright: None.  Released to the public domain.
XX+  *   Reference: P1003.2 section 4.59 (draft 10)
XX+  *   Notes:	Under Minix, this program requires chmem =30000.
XX+  *   Bugs:	No internationalization support; all messages are in English.
XX+  */
XX+ 
XX+ /* Force visible Posix names */
XX+ #ifndef _POSIX_SOURCE
XX+ #define _POSIX_SOURCE 1
XX+ #endif
XX+ 
XX+ /* External interfaces */
XX+ #include <sys/types.h>
XX+ #include <sys/stat.h>
XX+ #include <unistd.h>
XX+ #include <ctype.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX! /* External interfaces that should have been standardized into <getopt.h> */
XX! #ifdef _MINIX
XX! _PROTOTYPE(int getopt, (int argc, char **argv, char *options));
XX! #else
XX! extern int getopt();
XX! #endif
XX! extern char *optarg;
XX! extern int optind;
XX! 
XX! /* We expect this constant to be defined in <limits.h> in a Posix program,
XX!  * but we'll specify it here just in case it's been left out.
XX!  */
XX! #ifndef LINE_MAX
XX! #define LINE_MAX 2048		/* minimum acceptable lower bound */
XX! #endif
XX! 
XX! /* Magic numbers suggested or required by Posix specification */
XX! #define SUCCESS	0		/* exit code in case of success */
XX! #define FAILURE 1		/*                   or failure */
XX! #define DEFAULT_COUNT 10	/* default number of lines or bytes */
XX! #define MIN_BUFSIZE (LINE_MAX * DEFAULT_COUNT)
XX! #define SLEEP_INTERVAL	1	/* sleep for one second intervals with -f */
XX! 
XX  #define FALSE 0
XX! #define TRUE 1
XX  
XX! /* Internal functions - prototyped under Minix */
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int tail, (int count, int bytes, int read_until_killed));
XX! _PROTOTYPE(int keep_reading, (void));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX!   int cflag = FALSE;
XX!   int nflag = FALSE;
XX!   int fflag = FALSE;
XX!   int number = -DEFAULT_COUNT;
XX!   char *suffix;
XX!   int opt;
XX!   struct stat stat_buf;
XX  
XX! /* Determining whether this invocation is via the standard syntax or
XX!  * via an obsolescent one is a nasty kludge.  Here it is, but there is
XX!  * no pretense at elegance.
XX!  */
XX!   if (argc == 1) {		/* simple:  default read of a pipe */
XX! 	exit(tail(-DEFAULT_COUNT, 0, fflag));
XX    }
XX!   if ((argv[1][0] == '+') ||	/* OBSOLESCENT */
XX!       (argv[1][0] == '-' && ((isdigit(argv[1][1])) ||
XX! 			     (argv[1][1] == 'l') ||
XX! 			     (argv[1][1] == 'c' && argv[1][2] == 'f')))) {
XX! 	--argc; ++argv;
XX! 	if (isdigit(argv[0][1])) {
XX! 		number = (int)strtol(argv[0], &suffix, 10);
XX! 		if (number == 0) {		/* HISTORICAL */
XX! 			if (argv[0][0] == '+')
XX! 				number = 1;
XX! 			else
XX! 				exit(SUCCESS);
XX! 		}
XX! 	} else {
XX! 		number = (argv[0][0] == '+') ? DEFAULT_COUNT : -DEFAULT_COUNT;
XX! 		suffix = &(argv[0][1]);
XX  	}
XX! 	if (*suffix != '\0') {
XX! 		if (*suffix == 'c') {
XX! 			cflag = TRUE;
XX! 			++suffix;
XX! 		}
XX! 		else
XX! 		if (*suffix == 'l') {
XX! 			nflag = TRUE;
XX! 			++suffix;
XX! 		}
XX  	}
XX! 	if (*suffix != '\0') {
XX! 		if (*suffix == 'f') {
XX! 			fflag = TRUE;
XX! 			++suffix;
XX! 		}
XX! 	}
XX! 	if (*suffix != '\0') {	/* bad form: assume to be a file name */
XX! 		number = -DEFAULT_COUNT;
XX! 		cflag = nflag = FALSE;
XX! 		fflag = FALSE;
XX! 	} else {
XX! 		--argc; ++argv;
XX! 	}
XX!   } else {			/* new standard syntax */
XX! 	while ((opt = getopt(argc, argv, "c:fn:")) != EOF) {
XX! 		switch (opt) {
XX! 		      case 'c':
XX! 			cflag = TRUE;
XX! 			if (*optarg == '+' || *optarg == '-')
XX! 				number = atoi(optarg);
XX! 			else
XX! 			if (isdigit(*optarg))
XX! 				number = -atoi(optarg);
XX! 			else
XX! 				usage();
XX! 			if (number == 0) {		/* HISTORICAL */
XX! 				if (*optarg == '+')
XX! 					number = 1;
XX! 				else
XX! 					exit(SUCCESS);
XX! 			}
XX! 			break;
XX! 		      case 'f':
XX! 			fflag = TRUE;
XX! 			break;
XX! 		      case 'n':
XX! 			nflag = TRUE;
XX! 			if (*optarg == '+' || *optarg == '-')
XX! 				number = atoi(optarg);
XX! 			else
XX! 			if (isdigit(*optarg))
XX! 				number = -atoi(optarg);
XX! 			else
XX! 				usage();
XX! 			if (number == 0) {		/* HISTORICAL */
XX! 				if (*optarg == '+')
XX! 					number = 1;
XX! 				else
XX! 					exit(SUCCESS);
XX! 			}
XX! 			break;
XX! 		      default:
XX! 			usage();
XX! 			/* NOTREACHED */
XX! 		}
XX! 	}
XX! 	argc -= optind;
XX! 	argv += optind;
XX    }
XX! 
XX!   if (argc > 1 ||		/* too many arguments */
XX!       (cflag && nflag)) {	/* both bytes and lines specified */
XX! 	usage();
XX    }
XX  
XX!   if (argc > 0) {		/* an actual file */
XX! 	if (freopen(argv[0], "r", stdin) != stdin) {
XX! 		fputs("tail: could not open ", stderr);
XX! 		fputs(argv[0], stderr);
XX! 		fputs("\n", stderr);
XX! 		exit(FAILURE);
XX! 	}
XX! 	/* There is an optimization possibility here.  If a file is being
XX! 	 * read, we need not look at the front of it.  If we seek backwards
XX!          * from the end, we can (potentially) avoid looking at most of the
XX! 	 * file.  Some systems fail when asked to seek backwards to a point
XX! 	 * before the start of the file, so we avoid that possibility.
XX! 	 */
XX! 	if (number < 0 && fstat(fileno(stdin), &stat_buf) == 0) {
XX! 		long offset = cflag ? (long)number : (long)number * LINE_MAX;
XX! 
XX! 		if (-offset < stat_buf.st_size)
XX! 			fseek(stdin, offset, SEEK_END);
XX! 	}
XX    } else {
XX! 	fflag = FALSE;		/* force -f off when reading a pipe */
XX    }
XX!   exit(tail(number, cflag, fflag));
XX!   /* NOTREACHED */
XX  }
XX  
XX! int tail(count, bytes, read_until_killed)
XX! int count;			/* lines or bytes desired */
XX! int bytes;			/* TRUE if we want bytes */
XX! int read_until_killed;		/* keep reading at EOF */
XX  {
XX!   int c;
XX!   char *buf;			/* pointer to input buffer */
XX!   char *buf_end;		/* and one past its end */
XX!   char *start;			/* pointer to first desired character in buf */
XX!   char *finish;			/* pointer past last desired character */
XX!   int wrapped_once = FALSE;	/* TRUE after buf has been filled once */
XX  
XX! /* This is magic.  If count is positive, it means start at the count'th
XX!  * line or byte, with the first line or byte considered number 1.  Thus,
XX!  * we want to SKIP one less line or byte than the number specified.  In
XX!  * the negative case, we look backward from the end of the file for the
XX!  * (count + 1)'th newline or byte, so we really want the count to be one
XX!  * LARGER than was specified (in absolute value).  In either case, the
XX!  * right thing to do is:
XX!  */
XX!   --count;
XX  
XX! /* Count is positive:  skip the desired lines or bytes and then copy. */
XX!   if (count >= 0) {
XX! 	while (count > 0 && (c = getchar()) != EOF) {
XX! 		if (bytes || c == '\n')
XX! 			--count;
XX! 	}
XX! 	while ((c = getchar()) != EOF) {
XX! 		if (putchar(c) == EOF)
XX! 			return FAILURE;
XX! 	}
XX! 	if (read_until_killed)
XX! 		return keep_reading();
XX! 	return ferror(stdin) ? FAILURE : SUCCESS;
XX    }
XX  
XX! /* Count is negative:  allocate a reasonably large buffer. */
XX!   if ((buf = (char *)malloc(MIN_BUFSIZE + 1)) == (char *)NULL) {
XX! 	fputs("tail: out of memory\n", stderr);
XX! 	return FAILURE;
XX!   }
XX!   buf_end = buf + (MIN_BUFSIZE + 1);
XX  
XX! /* Read the entire file into the buffer. */
XX!   finish = buf;
XX!   while ((c = getchar()) != EOF) {
XX! 	*finish++ = c;
XX! 	if (finish == buf_end) {
XX! 		finish = buf;
XX! 		wrapped_once = TRUE;
XX! 	}
XX!   }
XX!   if (ferror(stdin))
XX! 	return FAILURE;
XX  
XX! /* Back up inside the buffer.  The count has already been adjusted to
XX!  * back up exactly one character too far, so we will bump the buffer
XX!  * pointer once after we're done.
XX!  * 
XX!  * BUG: For large line counts, the buffer may not be large enough to
XX!  *	hold all the lines.  The specification allows the program to
XX!  *	fail in such a case - this program will simply dump the entire
XX!  *	buffer's contents as its best attempt at the desired behavior.
XX!  */
XX!   if (finish != buf || wrapped_once) {		/* file was not empty */
XX! 	start = (finish == buf) ? buf_end - 1 : finish - 1;
XX! 	while (start != finish) {
XX! 		if ((bytes || *start == '\n') && ++count == 0)
XX! 			break;
XX! 		if (start == buf) {
XX! 			start = buf_end - 1;
XX! 			if (!wrapped_once)	/* never wrapped: stop now */
XX! 				break;
XX! 		} else {
XX! 			--start;
XX! 		}
XX! 	}
XX! 	if (++start == buf_end) {		/* bump after going too far */
XX! 		start = buf;
XX! 	}
XX! 	if (finish > start) {
XX! 		fwrite(start, 1, finish - start, stdout);
XX! 	} else {
XX! 		fwrite(start, 1, buf_end - start, stdout);
XX! 		fwrite(buf, 1, finish - buf, stdout);
XX! 	}
XX!   }
XX!   if (read_until_killed)
XX! 	return keep_reading();
XX!   return ferror(stdout) ? FAILURE : SUCCESS;
XX! }
XX  
XX! /* Wake at intervals to reread standard input.  Copy anything read to
XX!  * standard output and then go to sleep again.
XX!  */
XX! int keep_reading()
XX  {
XX!   int c;
XX  
XX!   for (;;) {
XX! 	sleep(SLEEP_INTERVAL);
XX! 	clearerr(stdin);
XX! 	while ((c = getchar()) != EOF) {
XX! 		if (putchar(c) == EOF)
XX! 			return FAILURE;
XX  	}
XX+ 	if (ferror(stdin))
XX+ 		return FAILURE;
XX+   }
XX+ }
XX  
XX! /* Tell the user the standard syntax. */
XX! void usage()
XX! {
XX!   fputs("Usage: tail [-f] [-c number | -n number] [file]\n", stderr);
XX!   exit(FAILURE);
XX! }
X/
Xecho x - tar.c.d
Xsed '/^X/s///' > tar.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tar.c  crc=18790  22092	Sun Apr 25 21:35:21 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tar.c  crc=18817  27547	Mon Mar  1 12:39:54 1993
XX***************
XX*** 14,31 ****
XX   *
XX   *
XX   * 1)	tar will back itself up, should check archive inode num(&dev) and
XX! 	then check the target inode number. In verbose mode, issue
XX! 	warning, in all cases ignore target.
XX! 	marks@mgse		Mon Sep 25 10:38:58 CDT 1989
XX    	added global varaibles, made changes to main() and add_file();
XX! 	maks@mgse Mon Sep 25 12:09:20 CDT 1989
XX  
XX     2)	tar will not notice that a file has changed size while it was being
XX! 	backed up. should issue warning.
XX! 	marks@mgse		Mon Sep 25 10:38:58 CDT 1989
XX  
XX     3)	the 'f' option was not documented in usage[].
XX! 	marks@mgse		Mon Sep 25 12:03:20 CDT 1989
XX    	changed both usage[] defines. Why are there two (one is commented out)?
XX    	( deleted by me (was done twice) -- KS, 2/10/89 )
XX   *
XX--- 14,31 ----
XX   *
XX   *
XX   * 1)	tar will back itself up, should check archive inode num(&dev) and
XX!   then check the target inode number. In verbose mode, issue
XX!   warning, in all cases ignore target.
XX!   marks@mgse		Mon Sep 25 10:38:58 CDT 1989
XX    	added global varaibles, made changes to main() and add_file();
XX!   maks@mgse Mon Sep 25 12:09:20 CDT 1989
XX  
XX     2)	tar will not notice that a file has changed size while it was being
XX!   backed up. should issue warning.
XX!   marks@mgse		Mon Sep 25 10:38:58 CDT 1989
XX  
XX     3)	the 'f' option was not documented in usage[].
XX!   marks@mgse		Mon Sep 25 12:03:20 CDT 1989
XX    	changed both usage[] defines. Why are there two (one is commented out)?
XX    	( deleted by me (was done twice) -- KS, 2/10/89 )
XX   *
XX***************
XX*** 42,47 ****
XX--- 42,51 ----
XX   *  made lint complains less (On a BSD 4.3 system)		KS 3/10/89
XX   *  use of directory(3) routines				KS 3/10/89
XX   *  deleted use of d_namlen selector of struct dirent		KS 18/10/89
XX+  *  support mknod4(2)						EC 7/7/90
XX+  *  forget inodes when link count expires			EC 6/4/91
XX+  *  don't remember directories *twice*!
XX+  *  added 'p' flag to ignore umask for normal user		KJB 6/10/92
XX   *
XX   * Bugs:
XX   *  verbose mode is not reporting consistent
XX***************
XX*** 58,68 ****
XX--- 62,85 ----
XX  #include <pwd.h>
XX  #include <grp.h>
XX  #include <tar.h>
XX+ #include <stdarg.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <utime.h>
XX+ #include <sys/wait.h>
XX  #include <stdio.h>		/* need NULL */
XX  
XX  #define	POSIX_COMP		/* POSIX compatible */
XX  #define DIRECT_3		/* use directory(3) routines */
XX  
XX+ #ifdef _MINIX
XX+ #include <blocksize.h>
XX+ #define MKNOD(p,M,m,s) mknod4(p,M,m, (long)s)
XX+ #else
XX+ #define MKNOD(p,M,m,s) mknod(p,M,m)
XX+ #endif
XX+ 
XX  #ifdef DIRECT_3
XX  #ifndef BSD
XX  /* To all minix users: i am sorry, developed this piece of code on a
XX***************
XX*** 78,88 ****
XX--- 95,109 ----
XX  #ifdef S_IFIFO
XX  #define	HAVE_FIFO		/* have incorporated Simon Pooles' changes */
XX  #endif
XX+ #ifdef S_IFLNK
XX+ #define HAVE_SYMLINK
XX+ #endif
XX  
XX  typedef char BOOL;
XX  #define TRUE	1
XX  #define FALSE	0
XX  
XX+ #define STRING_SIZE	256	/* string buffer size */
XX  #define HEADER_SIZE	TBLOCK
XX  #define NAME_SIZE	NAMSIZ
XX  /* #define BLOCK_BOUNDARY	 20 -- not in POSIX ! */
XX***************
XX*** 126,133 ****
XX  struct link {
XX    ino_t ino;
XX    dev_t dev;
XX!   char name[NAMSIZ];
XX    struct link *next;
XX  } *link_top = NULL;
XX  
XX  HEADER header;
XX--- 147,155 ----
XX  struct link {
XX    ino_t ino;
XX    dev_t dev;
XX!   nlink_t nlink;
XX    struct link *next;
XX+   char name[1];
XX  } *link_top = NULL;
XX  
XX  HEADER header;
XX***************
XX*** 135,145 ****
XX  #define INT_TYPE	(sizeof(header.member.m_uid))
XX  #define LONG_TYPE	(sizeof(header.member.m_size))
XX  
XX! #define MKDIR		"/bin/mkdir"
XX  
XX  #define NIL_HEADER	((HEADER *) 0)
XX  #define NIL_PTR		((char *) 0)
XX! #define BLOCK_SIZE	TBLOCK
XX  
XX  #define flush()		print(NIL_PTR)
XX  
XX--- 157,168 ----
XX  #define INT_TYPE	(sizeof(header.member.m_uid))
XX  #define LONG_TYPE	(sizeof(header.member.m_size))
XX  
XX! #define MKDIR1		"/bin/mkdir"
XX! #define MKDIR2		"/usr/bin/mkdir"
XX  
XX  #define NIL_HEADER	((HEADER *) 0)
XX  #define NIL_PTR		((char *) 0)
XX! #define TBLOCK_SIZE	TBLOCK
XX  
XX  #define flush()		print(NIL_PTR)
XX  
XX***************
XX*** 148,154 ****
XX  int tar_fd;
XX  /* Char usage[] = "Usage: tar [cxt] tarfile [files]."; */
XX  char usage[] = "Usage: tar [cxt][vo][F][f] tarfile [files].";
XX! char io_buffer[BLOCK_SIZE];
XX  char path[NAME_SIZE];
XX  char pathname[NAME_SIZE];
XX  int force_flag = 0;
XX--- 171,177 ----
XX  int tar_fd;
XX  /* Char usage[] = "Usage: tar [cxt] tarfile [files]."; */
XX  char usage[] = "Usage: tar [cxt][vo][F][f] tarfile [files].";
XX! char io_buffer[TBLOCK_SIZE];
XX  char path[NAME_SIZE];
XX  char pathname[NAME_SIZE];
XX  int force_flag = 0;
XX***************
XX*** 167,178 ****
XX  int total_blocks;
XX  int u_mask;			/* one's complement of current umask */
XX  
XX- long convert();
XX- 
XX  #define block_size()	(int) ((convert(header.member.m_size, LONG_TYPE) \
XX! 	+ (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE)
XX  
XX! error(s1, s2)
XX  char *s1, *s2;
XX  {
XX    string_print(NIL_PTR, "%s %s\n", s1, s2 ? s2 : "");
XX--- 190,230 ----
XX  int total_blocks;
XX  int u_mask;			/* one's complement of current umask */
XX  
XX  #define block_size()	(int) ((convert(header.member.m_size, LONG_TYPE) \
XX!   + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE)
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void error, (char *s1, char *s2));
XX! _PROTOTYPE(BOOL get_header, (void));
XX! _PROTOTYPE(void tarfile, (void));
XX! _PROTOTYPE(void skip_entry, (void));
XX! _PROTOTYPE(void extract, (char *file));
XX! _PROTOTYPE(void do_chown, (char *file));
XX! _PROTOTYPE(void timestamp, (char *file));
XX! _PROTOTYPE(void copy, (char *file, int from, int to, long bytes));
XX! _PROTOTYPE(long convert, (char str[], int type));
XX! _PROTOTYPE(int make_dir, (char *dir_name));
XX! _PROTOTYPE(int checksum, (void));
XX! _PROTOTYPE(int is_dir, (char *file));
XX! _PROTOTYPE(char *path_name, (char *file));
XX! _PROTOTYPE(void add_path, (char *name));
XX! _PROTOTYPE(void add_file, (char *file));
XX! _PROTOTYPE(void verb_print, (char *s1, char *s2));
XX! _PROTOTYPE(void add_close, (int fd));
XX! _PROTOTYPE(int add_open, (char *file, struct stat * st));
XX! _PROTOTYPE(void make_header, (char *file, struct stat * st));
XX! _PROTOTYPE(void is_added, (struct stat * st, char *file));
XX! _PROTOTYPE(void is_deleted, (struct stat * st));
XX! _PROTOTYPE(char *is_linked, (struct stat * st));
XX! _PROTOTYPE(void clear_header, (void));
XX! _PROTOTYPE(void adjust_boundary, (void));
XX! _PROTOTYPE(void mread, (int fd, char *address, int bytes));
XX! _PROTOTYPE(void mwrite, (int fd, char *address, int bytes));
XX! _PROTOTYPE(void print, (char *str));
XX! _PROTOTYPE(char *num_out, (long number));
XX! _PROTOTYPE(void string_print, (char *buffer, char *fmt,...));
XX! 
XX! void error(s1, s2)
XX  char *s1, *s2;
XX  {
XX    string_print(NIL_PTR, "%s %s\n", s1, s2 ? s2 : "");
XX***************
XX*** 180,188 ****
XX    exit(1);
XX  }
XX  
XX! BOOL get_header();
XX! 
XX! main(argc, argv)
XX  int argc;
XX  register char *argv[];
XX  {
XX--- 232,238 ----
XX    exit(1);
XX  }
XX  
XX! int main(argc, argv)
XX  int argc;
XX  register char *argv[];
XX  {
XX***************
XX*** 209,214 ****
XX--- 259,267 ----
XX  		break;
XX  	    case 'f':		/* standard U*IX usage -KS */
XX  		break;
XX+ 	    case 'p':		/* restore file modes right, ignore umask. */
XX+ 		(void) umask(0);
XX+ 		break;
XX  	    default:	error(usage, NIL_PTR);
XX  	}
XX    }
XX***************
XX*** 230,236 ****
XX  	umask(save_umask);
XX  	chown_flag = TRUE;	/* normal user can't chown */
XX    } else
XX! 	u_mask = 0777;		/* don't restrict if 'privileged utiliy' */
XX  
XX    ar_dev = -1;			/* impossible device nr */
XX    if (creat_fl) {
XX--- 283,289 ----
XX  	umask(save_umask);
XX  	chown_flag = TRUE;	/* normal user can't chown */
XX    } else
XX! 	u_mask = ~0;		/* don't restrict if 'privileged utility' */
XX  
XX    ar_dev = -1;			/* impossible device nr */
XX    if (creat_fl) {
XX***************
XX*** 248,254 ****
XX  	}
XX  	adjust_boundary();
XX    } else if (ext_fl) {
XX! 	/* extraction code moved here from tarfile() MSP */
XX  	while (get_header()) {
XX  		mem_name = header.member.m_name;
XX  		if (is_dir(mem_name)) {
XX--- 301,307 ----
XX  	}
XX  	adjust_boundary();
XX    } else if (ext_fl) {
XX! 	/* Extraction code moved here from tarfile() MSP */
XX  	while (get_header()) {
XX  		mem_name = header.member.m_name;
XX  		if (is_dir(mem_name)) {
XX***************
XX*** 261,278 ****
XX  				break;
XX  		if (argc == 3 || (i < argc)) {
XX  			extract(mem_name);
XX! 		} else
XX! 			if (header.dbuf.typeflag == '0' ||
XX! 			    header.dbuf.typeflag == 0 ||
XX! 			    header.dbuf.typeflag == ' ')
XX! 				skip_entry();
XX  		flush();
XX!   	}
XX    } else
XX! 	tarfile();	/* tarfile() justs prints info. now MSP */
XX  
XX    flush();
XX!   exit(0);
XX  }
XX  
XX  BOOL get_header()
XX--- 314,330 ----
XX  				break;
XX  		if (argc == 3 || (i < argc)) {
XX  			extract(mem_name);
XX! 		} else if (header.dbuf.typeflag == '0' ||
XX! 			   header.dbuf.typeflag == 0 ||
XX! 			   header.dbuf.typeflag == ' ')
XX! 			skip_entry();
XX  		flush();
XX! 	}
XX    } else
XX! 	tarfile();		/* tarfile() justs prints info. now MSP */
XX  
XX    flush();
XX!   return(0);
XX  }
XX  
XX  BOOL get_header()
XX***************
XX*** 292,303 ****
XX    return TRUE;
XX  }
XX  
XX! /* tarfile() just lists info about archive now; as of the t flag. */
XX  /* Extraction has been moved into main() as that needs access to argv[] */
XX  
XX! tarfile()
XX  {
XX-   register char *ptr;
XX    register char *mem_name;
XX  
XX    while (get_header()) {
XX--- 344,354 ----
XX    return TRUE;
XX  }
XX  
XX! /* Tarfile() just lists info about archive now; as of the t flag. */
XX  /* Extraction has been moved into main() as that needs access to argv[] */
XX  
XX! void tarfile()
XX  {
XX    register char *mem_name;
XX  
XX    while (get_header()) {
XX***************
XX*** 308,334 ****
XX  	    case '1':
XX  		verb_print("linked to", header.dbuf.linkname);
XX  		break;
XX! 	    case '6':
XX! 		verb_print("", "fifo");
XX  		break;
XX  	    case '3':
XX  	    case '4':
XX! 		if (verbose_flag) string_print(NIL_PTR,
XX! 				     "%s special file major %s minor %s\n",
XX! 			      (header.dbuf.typeflag == '3' ?
XX! 			       "character" : "block"),
XX! 				     header.dbuf.devmajor, header.dbuf.devminor);
XX  		break;
XX! 	    case '0':	/* official POSIX */
XX! 	    case 0:	/* also mentioned in POSIX */
XX! 	    case ' ':	/* ofetn used */
XX  		if (!is_dir(mem_name)) {
XX  			if (verbose_flag)
XX  				string_print(NIL_PTR, "%d tape blocks\n",
XX  					     block_size());
XX  			skip_entry();
XX  			break;
XX! 		} else	/* FALL TROUGH */
XX  	    case '5':
XX  			verb_print("", "directory");
XX  		break;
XX--- 359,398 ----
XX  	    case '1':
XX  		verb_print("linked to", header.dbuf.linkname);
XX  		break;
XX! 	    case '2':
XX! 		verb_print("symbolic link to", header.dbuf.linkname);
XX  		break;
XX+ 	    case '6':	verb_print("", "fifo");	break;
XX  	    case '3':
XX  	    case '4':
XX! 		if (verbose_flag) {
XX! 			char sizebuf[TSIZLEN + 1];
XX! 
XX! 			strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
XX! 			sizebuf[TSIZLEN] = 0;
XX! 			string_print(NIL_PTR,
XX! #ifdef _MINIX
XX! 				     "%s special file major %s minor %s size %s\n",
XX! #else
XX! 			      "%s special file major %s minor %s\n",
XX! #endif
XX! 				     (header.dbuf.typeflag == '3' ?
XX! 				      "character" : "block"),
XX! 				     header.dbuf.devmajor,
XX! 				     header.dbuf.devminor,
XX! 				     sizebuf);
XX! 		}
XX  		break;
XX! 	    case '0':		/* official POSIX */
XX! 	    case 0:		/* also mentioned in POSIX */
XX! 	    case ' ':		/* ofetn used */
XX  		if (!is_dir(mem_name)) {
XX  			if (verbose_flag)
XX  				string_print(NIL_PTR, "%d tape blocks\n",
XX  					     block_size());
XX  			skip_entry();
XX  			break;
XX! 		} else		/* FALL TROUGH */
XX  	    case '5':
XX  			verb_print("", "directory");
XX  		break;
XX***************
XX*** 340,356 ****
XX    }
XX  }
XX  
XX! skip_entry()
XX  {
XX    register int blocks = block_size();
XX  
XX!   while (blocks--) (void) read(tar_fd, io_buffer, BLOCK_SIZE);
XX  }
XX  
XX! extract(file)
XX  register char *file;
XX  {
XX    register int fd;
XX  
XX    switch (header.dbuf.typeflag) {
XX        case '1':			/* Link */
XX--- 404,421 ----
XX    }
XX  }
XX  
XX! void skip_entry()
XX  {
XX    register int blocks = block_size();
XX  
XX!   while (blocks--) (void) read(tar_fd, io_buffer, TBLOCK_SIZE);
XX  }
XX  
XX! void extract(file)
XX  register char *file;
XX  {
XX    register int fd;
XX+   char *pd1, *pd2;		/* walk thru failed directory path */
XX  
XX    switch (header.dbuf.typeflag) {
XX        case '1':			/* Link */
XX***************
XX*** 371,392 ****
XX        case '3':			/* character special */
XX        case '4':			/* block special */
XX  	{
XX! 		int dmajor, dminor, mode;
XX  
XX  		dmajor = (int) convert(header.dbuf.devmajor, INT_TYPE);
XX  		dminor = (int) convert(header.dbuf.devminor, INT_TYPE);
XX  		mode = (header.dbuf.typeflag == '3' ? S_IFCHR : S_IFBLK);
XX! 		if (mknod(file, mode, (dmajor << 8 | dminor), 0) == 0) {
XX  			if (verbose_flag) string_print(NIL_PTR,
XX  					     "made %s special file major %s minor %s\n",
XX  				      (header.dbuf.typeflag == '3' ?
XX  				       "character" : "block"),
XX! 					     header.dbuf.devmajor, header.dbuf.devminor);
XX  			do_chown(file);
XX  		}
XX  		return;
XX  	}
XX        case '2':			/* symbolic link */
XX        case '7':			/* contiguous file -- what is this (KS) */
XX  	print("Not implemented file type\n");
XX  	return;			/* not implemented, but break out */
XX--- 436,494 ----
XX        case '3':			/* character special */
XX        case '4':			/* block special */
XX  	{
XX! 		int dmajor, dminor, mode, size;
XX! 		char sizebuf[TSIZLEN + 1];
XX  
XX  		dmajor = (int) convert(header.dbuf.devmajor, INT_TYPE);
XX  		dminor = (int) convert(header.dbuf.devminor, INT_TYPE);
XX  		mode = (header.dbuf.typeflag == '3' ? S_IFCHR : S_IFBLK);
XX! 		strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
XX! 		sizebuf[TSIZLEN] = 0;
XX! 		if (convert(header.dbuf.size, LONG_TYPE) % BLOCK_SIZE != 0)
XX! 			string_print(NIL_PTR,
XX! 			"Warning: %s not a multiple of BLOCK_SIZE\n",
XX! 				     sizebuf);
XX! 		size = (int) (convert(header.dbuf.size, LONG_TYPE) / BLOCK_SIZE);
XX! 		if (MKNOD(file, mode, (dmajor << 8 | dminor), size) == 0) {
XX  			if (verbose_flag) string_print(NIL_PTR,
XX+ #ifdef _MINIX
XX+ 					     "made %s special file major %s minor %s size %s\n",
XX+ #else
XX  					     "made %s special file major %s minor %s\n",
XX+ #endif
XX  				      (header.dbuf.typeflag == '3' ?
XX  				       "character" : "block"),
XX! 					     header.dbuf.devmajor,
XX! 					     header.dbuf.devminor,
XX! 					     sizebuf);
XX  			do_chown(file);
XX  		}
XX+ 		else 
XX+ 		{
XX+ 			string_print(NIL_PTR,
XX+ #ifdef _MINIX
XX+ 					     "cannot make %s special file major %s minor %s size %s\n",
XX+ #else
XX+ 					     "cannot make %s special file major %s minor %s\n",
XX+ #endif
XX+ 				      (header.dbuf.typeflag == '3' ?
XX+ 				       "character" : "block"),
XX+ 					     header.dbuf.devmajor,
XX+ 					     header.dbuf.devminor,
XX+ 					     sizebuf);
XX+ 		}
XX  		return;
XX  	}
XX        case '2':			/* symbolic link */
XX+ #ifdef HAVE_SYMLINK
XX+ 	if (symlink(header.member.m_link, file) < 0)
XX+ 		string_print(NIL_PTR, "Cannot make symbolic link %s to %s\n",
XX+ 			     header.member.m_link, file);
XX+ 	else if (verbose_flag)
XX+ 		string_print(NIL_PTR, "Symbolic link %s to %s\n",
XX+ 			     header.member.m_link, file);
XX+ 	return;
XX+ #endif
XX        case '7':			/* contiguous file -- what is this (KS) */
XX  	print("Not implemented file type\n");
XX  	return;			/* not implemented, but break out */
XX***************
XX*** 401,410 ****
XX  #endif
XX    }
XX  
XX!   /* Security change: creat with mode 0600, chown and then chmod -- KS */
XX    if ((fd = creat(file, 0600)) < 0) {
XX! 	string_print(NIL_PTR, "Cannot create %s\n", file);
XX! 	return;
XX    }
XX    copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
XX    (void) close(fd);
XX--- 503,526 ----
XX  #endif
XX    }
XX  
XX!   /* Create regular file.  If failure, try to make missing directories. */
XX    if ((fd = creat(file, 0600)) < 0) {
XX! 	pd1 = file;
XX! 	while ((pd2 = index(pd1, '/')) > (char *) 0) {
XX! 		*pd2 = '\0';
XX! 		if (access(file, 1) < 0)
XX! 			if (mkdir(file, 0777) < 0) {
XX! 				string_print(NIL_PTR, "Cannot mkdir %s\n", file);
XX! 				return;
XX! 			} else
XX! 				string_print(NIL_PTR, "Made directory %s\n", file);
XX! 		*pd2 = '/';
XX! 		pd1 = ++pd2;
XX! 	}
XX! 	if ((fd = creat(file, 0600)) < 0) {
XX! 		string_print(NIL_PTR, "Cannot create %s\n", file);
XX! 		return;
XX! 	}
XX    }
XX    copy(file, tar_fd, fd, convert(header.member.m_size, LONG_TYPE));
XX    (void) close(fd);
XX***************
XX*** 412,429 ****
XX    do_chown(file);
XX  }
XX  
XX! do_chown(file)
XX  char *file;
XX  {
XX    int uid = -1, gid = -1;	/* these are illegal ??? -- KS */
XX  
XX    if (!chown_flag) {		/* set correct owner and group  -Dal */
XX  	if (header.dbuf.magic[TMAGLEN] == ' ')
XX! 		header.dbuf.magic[TMAGLEN] == '\0';	/* some tars out there
XX  							 * ... */
XX! 	if (strncmp(TMAGIC, header.dbuf.magic, TMAGLEN)) {
XX! 		struct passwd *pwd, *getpwnam();
XX! 		struct group *grp, *getgrnam();
XX  
XX  		pwd = getpwnam(header.dbuf.uname);
XX  		if (pwd != NULL) uid = pwd->pw_uid;
XX--- 528,545 ----
XX    do_chown(file);
XX  }
XX  
XX! void do_chown(file)
XX  char *file;
XX  {
XX    int uid = -1, gid = -1;	/* these are illegal ??? -- KS */
XX  
XX    if (!chown_flag) {		/* set correct owner and group  -Dal */
XX  	if (header.dbuf.magic[TMAGLEN] == ' ')
XX! 		header.dbuf.magic[TMAGLEN] = '\0';	/* some tars out there
XX  							 * ... */
XX! 	if (strncmp(TMAGIC, header.dbuf.magic, (size_t) TMAGLEN)) {
XX! 		struct passwd *pwd;
XX! 		struct group *grp;
XX  
XX  		pwd = getpwnam(header.dbuf.uname);
XX  		if (pwd != NULL) uid = pwd->pw_uid;
XX***************
XX*** 441,470 ****
XX  
XX  }
XX  
XX! timestamp(file)
XX  char *file;
XX  {
XX!   time_t times[2];
XX  
XX!   times[0] = times[1] = (long) convert(header.dbuf.mtime, LONG_TYPE);
XX!   utime(file, times);
XX  }
XX  
XX! copy(file, from, to, bytes)
XX  char *file;
XX  int from, to;
XX  register long bytes;
XX  {
XX    register int rest;
XX!   int blocks = (int) ((bytes + (long) BLOCK_SIZE - 1) / (long) BLOCK_SIZE);
XX  
XX    if (verbose_flag)
XX  	string_print(NIL_PTR, "%s, %d tape blocks\n", file, blocks);
XX  
XX    while (blocks--) {
XX! 	(void) read(from, io_buffer, BLOCK_SIZE);
XX! 	rest = (bytes > (long) BLOCK_SIZE) ? BLOCK_SIZE : (int) bytes;
XX! 	mwrite(to, io_buffer, (to == tar_fd) ? BLOCK_SIZE : rest);
XX  	bytes -= (long) rest;
XX    }
XX  }
XX--- 557,586 ----
XX  
XX  }
XX  
XX! void timestamp(file)
XX  char *file;
XX  {
XX!   struct utimbuf buf;
XX  
XX!   buf.modtime = buf.actime = convert(header.dbuf.mtime, LONG_TYPE);
XX!   utime(file, &buf);
XX  }
XX  
XX! void copy(file, from, to, bytes)
XX  char *file;
XX  int from, to;
XX  register long bytes;
XX  {
XX    register int rest;
XX!   int blocks = (int) ((bytes + (long) TBLOCK_SIZE - 1) / (long) TBLOCK_SIZE);
XX  
XX    if (verbose_flag)
XX  	string_print(NIL_PTR, "%s, %d tape blocks\n", file, blocks);
XX  
XX    while (blocks--) {
XX! 	(void) read(from, io_buffer, TBLOCK_SIZE);
XX! 	rest = (bytes > (long) TBLOCK_SIZE) ? TBLOCK_SIZE : (int) bytes;
XX! 	mwrite(to, io_buffer, (to == tar_fd) ? TBLOCK_SIZE : rest);
XX  	bytes -= (long) rest;
XX    }
XX  }
XX***************
XX*** 486,492 ****
XX    return ac;
XX  }
XX  
XX! make_dir(dir_name)
XX  char *dir_name;
XX  {
XX    register int pid, w;
XX--- 602,608 ----
XX    return ac;
XX  }
XX  
XX! int make_dir(dir_name)
XX  char *dir_name;
XX  {
XX    register int pid, w;
XX***************
XX*** 498,504 ****
XX    if ((pid = fork()) < 0) error("Cannot fork().", NIL_PTR);
XX  
XX    if (pid == 0) {
XX! 	execl(MKDIR, "mkdir", dir_name, (char *) 0);
XX  	error("Cannot execute mkdir.", NIL_PTR);
XX    }
XX    do {
XX--- 614,621 ----
XX    if ((pid = fork()) < 0) error("Cannot fork().", NIL_PTR);
XX  
XX    if (pid == 0) {
XX! 	execl(MKDIR1, "mkdir", dir_name, (char *) 0);
XX! 	execl(MKDIR2, "mkdir", dir_name, (char *) 0);
XX  	error("Cannot execute mkdir.", NIL_PTR);
XX    }
XX    do {
XX***************
XX*** 508,514 ****
XX    return ret;
XX  }
XX  
XX! checksum()
XX  {
XX    register char *ptr = header.member.m_checksum;
XX    register int ac = 0;
XX--- 625,631 ----
XX    return ret;
XX  }
XX  
XX! int checksum()
XX  {
XX    register char *ptr = header.member.m_checksum;
XX    register int ac = 0;
XX***************
XX*** 516,527 ****
XX    while (ptr < &header.member.m_checksum[INT_TYPE]) *ptr++ = ' ';
XX  
XX    ptr = header.hdr_block;
XX!   while (ptr < &header.hdr_block[BLOCK_SIZE]) ac += *ptr++;
XX  
XX    return ac;
XX  }
XX  
XX! is_dir(file)
XX  register char *file;
XX  {
XX    while (*file++ != '\0');
XX--- 633,644 ----
XX    while (ptr < &header.member.m_checksum[INT_TYPE]) *ptr++ = ' ';
XX  
XX    ptr = header.hdr_block;
XX!   while (ptr < &header.hdr_block[TBLOCK_SIZE]) ac += *ptr++;
XX  
XX    return ac;
XX  }
XX  
XX! int is_dir(file)
XX  register char *file;
XX  {
XX    while (*file++ != '\0');
XX***************
XX*** 538,544 ****
XX    return pathname;
XX  }
XX  
XX! add_path(name)
XX  register char *name;
XX  {
XX    register char *path_ptr = path;
XX--- 655,661 ----
XX    return pathname;
XX  }
XX  
XX! void add_path(name)
XX  register char *name;
XX  {
XX    register char *path_ptr = path;
XX***************
XX*** 564,582 ****
XX  /*
XX   *	add a file to the archive
XX  */
XX! add_file(file)
XX  register char *file;
XX  {
XX    struct stat st;
XX! #ifdef DIRECT_3
XX!   struct direct dir;
XX! #endif
XX    register int fd = -1;
XX    char namebuf[16];		/* -Dal */
XX    char cwd[129];		/* -KS */
XX-   char *getcwd();		/* marks@mgse Mon Sep 25 10:06:08 CDT 1989 */
XX  
XX    if (stat(file, &st) < 0) {
XX  	string_print(NIL_PTR, "Cannot find %s\n", file);
XX  	return;
XX    }
XX--- 681,700 ----
XX  /*
XX   *	add a file to the archive
XX  */
XX! void add_file(file)
XX  register char *file;
XX  {
XX    struct stat st;
XX!   char *linkname;
XX    register int fd = -1;
XX    char namebuf[16];		/* -Dal */
XX    char cwd[129];		/* -KS */
XX  
XX+ #ifdef HAVE_SYMLINK
XX+   if (lstat(file, &st) < 0) {
XX+ #else
XX    if (stat(file, &st) < 0) {
XX+ #endif
XX  	string_print(NIL_PTR, "Cannot find %s\n", file);
XX  	return;
XX    }
XX***************
XX*** 589,692 ****
XX  	return;
XX    }
XX    make_header(path_name(file), &st);
XX!   switch (st.st_mode & S_IFMT) {
XX!       case S_IFREG:
XX! 	header.dbuf.typeflag = '0';
XX  	string_print(header.member.m_checksum, "%I ", checksum());
XX  	mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 	copy(path_name(file), fd, tar_fd, (long) st.st_size);
XX! 	break;
XX!       case S_IFDIR:
XX! 	header.dbuf.typeflag = '5';
XX! 	string_print(header.member.m_checksum, "%I ", checksum());
XX! 	mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 	if (NULL == getcwd(cwd, 129))
XX! 		string_print(NIL_PTR, "Error: cannot getcwd()\n");
XX! 	else if (chdir(file) < 0)
XX! 		string_print(NIL_PTR, "Cannot chdir to %s\n", file);
XX! 	else {
XX! 		is_added(&st, file);
XX! 		verb_print("read directory", file);
XX! 		add_path(file);
XX  #ifdef	DIRECT_3
XX! 		{
XX! 			DIR *dirp;
XX! 			struct direct *dp;
XX  
XX! 			dirp = opendir(".");
XX! 			while (NULL != (dp = readdir(dirp)))
XX! 				if ((strcmp(dp->d_name, ".") == 0) ||
XX! 				    (strcmp(dp->d_name, "..") == 0))
XX! 					continue;
XX! 				else {
XX! 					strcpy(namebuf, dp->d_name);
XX! 					add_file(namebuf);
XX  				}
XX! 			closedir(dirp);
XX  		}
XX! #else
XX! 		mread(fd, &dir, sizeof(dir));	/* "." */
XX! 		mread(fd, &dir, sizeof(dir));	/* ".." */
XX! 		while (read(fd, &dir, sizeof(dir)) == sizeof(dir))
XX! 			if (dir.d_ino) {
XX! 				strncpy(namebuf, dir.d_name, 14);
XX! 				namebuf[14] = '\0';
XX! 				add_file(namebuf);
XX  			}
XX  #endif
XX- 		chdir(cwd);
XX- 		add_path(NIL_PTR);
XX- 		*file = 0;
XX- 	}
XX- 	break;
XX  #ifdef HAVE_FIFO
XX!       case S_IFIFO:
XX! 	header.dbuf.typeflag = '6';
XX! 	verb_print("read fifo", file);
XX! 	string_print(header.member.m_checksum, "%I ", checksum());
XX! 	mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 	break;
XX  #endif
XX!       case S_IFBLK:
XX! 	header.dbuf.typeflag = '4';
XX! 	if (verbose_flag) string_print(NIL_PTR,
XX  			 "read block device %s major %s minor %s\n",
XX! 		  file, header.dbuf.devmajor, header.dbuf.devminor);
XX! 	string_print(header.member.m_checksum, "%I ", checksum());
XX! 	mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 	break;
XX!       case S_IFCHR:
XX! 	header.dbuf.typeflag = '3';
XX! 	if (verbose_flag) string_print(NIL_PTR,
XX! 		     "read character device %s major %s minor %s\n",
XX! 		  file, header.dbuf.devmajor, header.dbuf.devminor);
XX! 	string_print(header.member.m_checksum, "%I ", checksum());
XX! 	mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 	break;
XX!       case -1 & S_IFMT:
XX! 	header.dbuf.typeflag = '1';
XX! 	if (verbose_flag) string_print(NIL_PTR, "linked %s to %s\n",
XX! 			     header.dbuf.linkname, file);
XX! 	string_print(header.member.m_checksum, "%I ", checksum());
XX! 	mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 	break;
XX!       default:
XX! 	string_print(NIL_PTR, "Tar: %s unknown file type. Not added.\n", file);
XX! 	*file = 0;
XX    }
XX  
XX    flush();
XX-   is_added(&st, file);
XX    add_close(fd);
XX  }
XX  
XX! verb_print(s1, s2)
XX  char *s1, *s2;
XX  {
XX    if (verbose_flag) string_print(NIL_PTR, "%s: %s\n", s1, s2);
XX  }
XX  
XX! add_close(fd)
XX  int fd;
XX  {
XX    if (fd != 0) close(fd);
XX--- 707,861 ----
XX  	return;
XX    }
XX    make_header(path_name(file), &st);
XX!   if ((linkname = is_linked(&st)) != NULL) {
XX! 	strncpy(header.dbuf.linkname, linkname, (size_t) NAMSIZ);
XX! 	header.dbuf.typeflag = '1';
XX! 	if (verbose_flag) string_print(NIL_PTR, "linked %s to %s\n",
XX! 			     header.dbuf.linkname, file);
XX  	string_print(header.member.m_checksum, "%I ", checksum());
XX  	mwrite(tar_fd, (char *) &header, sizeof(header));
XX!   } else {
XX! 	is_added(&st, file);
XX! 	switch (st.st_mode & S_IFMT) {
XX! 	    case S_IFREG:
XX! 		header.dbuf.typeflag = '0';
XX! 		string_print(header.member.m_checksum, "%I ", checksum());
XX! 		mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 		copy(path_name(file), fd, tar_fd, (long) st.st_size);
XX! 		break;
XX! 	    case S_IFDIR:
XX! 		header.dbuf.typeflag = '5';
XX! 		string_print(header.member.m_checksum, "%I ", checksum());
XX! 		mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 		if (NULL == getcwd(cwd, (int) sizeof cwd))
XX! 			string_print(NIL_PTR, "Error: cannot getcwd()\n");
XX! 		else if (chdir(file) < 0)
XX! 			string_print(NIL_PTR, "Cannot chdir to %s\n", file);
XX! 		else {
XX! 			verb_print("read directory", file);
XX! 			add_path(file);
XX  #ifdef	DIRECT_3
XX! 			{
XX! 				DIR *dirp;
XX! 				struct direct *dp;
XX! 				struct stat dst;
XX  
XX! 				dirp = opendir(".");
XX! 				while (NULL != (dp = readdir(dirp)))
XX! 					if (strcmp(dp->d_name, ".") == 0)
XX! 						is_linked(&st);
XX! 					else if (strcmp(dp->d_name, "..") == 0) {
XX! 						if (stat("..", &dst) == 0)
XX! 							is_linked(&dst);
XX! 					} else {
XX! 						strcpy(namebuf, dp->d_name);
XX! 						add_file(namebuf);
XX! 					}
XX! 				closedir(dirp);
XX! 			}
XX! #else
XX! 			{
XX! 				int i;
XX! 				struct direct dir;
XX! 				struct stat dst;
XX! 
XX! 				for (i = 0; i < 2; i++) {	/* . and .. */
XX! 					mread(fd, &dir, sizeof(dir));
XX! 					if (strcmp(dir.d_name, ".") == 0)
XX! 						is_linked(&st);
XX! 					else if (strcmp(dir.d_name, "..") == 0) {
XX! 						if (stat("..", &dst) == 0)
XX! 							is_linked(&dst);
XX! 					} else
XX! 						break;
XX  				}
XX! 				while (read(fd, &dir, sizeof(dir)) == sizeof(dir))
XX! 					if (dir.d_ino) {
XX! 						strncpy(namebuf, dir.d_name,
XX! 						   (size_t) DIRSIZ);
XX! 						namebuf[DIRSIZ] = '\0';
XX! 						add_file(namebuf);
XX! 					}
XX! 			}
XX! #endif
XX! 			chdir(cwd);
XX! 			add_path(NIL_PTR);
XX! 			*file = 0;
XX  		}
XX! 		break;
XX! #ifdef HAVE_SYMLINK
XX! 	    case S_IFLNK:
XX! 		{
XX! 			int i;
XX! 
XX! 			header.dbuf.typeflag = '2';
XX! 			verb_print("read symlink", file);
XX! 			i = readlink(file,
XX! 				     header.dbuf.linkname,
XX! 				  sizeof(header.dbuf.linkname) - 1);
XX! 			if (i < 0) {
XX! 				string_print(NIL_PTR,
XX! 					     "Cannot read symbolic link %s\n", file);
XX! 				return;
XX  			}
XX+ 			header.dbuf.linkname[i] = 0;
XX+ 			string_print(header.member.m_checksum, "%I ", checksum());
XX+ 			mwrite(tar_fd, (char *) &header, sizeof(header));
XX+ 			break;
XX+ 		}
XX  #endif
XX  #ifdef HAVE_FIFO
XX! 	    case S_IFIFO:
XX! 		header.dbuf.typeflag = '6';
XX! 		verb_print("read fifo", file);
XX! 		string_print(header.member.m_checksum, "%I ", checksum());
XX! 		mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 		break;
XX  #endif
XX! 	    case S_IFBLK:
XX! 		header.dbuf.typeflag = '4';
XX! 		if (verbose_flag) {
XX! 			char sizebuf[TSIZLEN + 1];
XX! 
XX! 			strncpy(sizebuf, header.dbuf.size, (size_t) TSIZLEN);
XX! 			sizebuf[TSIZLEN] = 0;
XX! 			string_print(NIL_PTR,
XX! #ifdef _MINIX
XX! 				     "read block device %s major %s minor %s size %s\n",
XX! #else
XX  			 "read block device %s major %s minor %s\n",
XX! #endif
XX! 				     file, header.dbuf.devmajor, header.dbuf.devminor, sizebuf);
XX! 		}
XX! 		string_print(header.member.m_checksum, "%I ", checksum());
XX! 		mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 		break;
XX! 	    case S_IFCHR:
XX! 		header.dbuf.typeflag = '3';
XX! 		if (verbose_flag) string_print(NIL_PTR,
XX! 				     "read character device %s major %s minor %s\n",
XX! 				     file, header.dbuf.devmajor, header.dbuf.devminor);
XX! 		string_print(header.member.m_checksum, "%I ", checksum());
XX! 		mwrite(tar_fd, (char *) &header, sizeof(header));
XX! 		break;
XX! 	    default:
XX! 		is_deleted(&st);
XX! 		string_print(NIL_PTR, "Tar: %s unknown file type. Not added.\n", file);
XX! 		*file = 0;
XX! 	}
XX    }
XX  
XX    flush();
XX    add_close(fd);
XX  }
XX  
XX! void verb_print(s1, s2)
XX  char *s1, *s2;
XX  {
XX    if (verbose_flag) string_print(NIL_PTR, "%s: %s\n", s1, s2);
XX  }
XX  
XX! void add_close(fd)
XX  int fd;
XX  {
XX    if (fd != 0) close(fd);
XX***************
XX*** 695,701 ****
XX  /*
XX   *	open file 'file' to be added to archive, return file descriptor
XX  */
XX! add_open(file, st)
XX  char *file;
XX  struct stat *st;
XX  {
XX--- 864,870 ----
XX  /*
XX   *	open file 'file' to be added to archive, return file descriptor
XX  */
XX! int add_open(file, st)
XX  char *file;
XX  struct stat *st;
XX  {
XX***************
XX*** 707,720 ****
XX    return fd;
XX  }
XX  
XX! make_header(file, st)
XX  char *file;
XX  register struct stat *st;
XX  {
XX    register char *ptr = header.member.m_name;
XX!   char *is_linked();
XX!   struct passwd *pwd, *getpwuid();
XX!   struct group *grp, *getgrgid();
XX  
XX    clear_header();
XX  
XX--- 876,888 ----
XX    return fd;
XX  }
XX  
XX! void make_header(file, st)
XX  char *file;
XX  register struct stat *st;
XX  {
XX    register char *ptr = header.member.m_name;
XX!   struct passwd *pwd;
XX!   struct group *grp;
XX  
XX    clear_header();
XX  
XX***************
XX*** 726,748 ****
XX    string_print(header.member.m_mode, "%I ", st->st_mode & 07777);
XX    string_print(header.member.m_uid, "%I ", st->st_uid);
XX    string_print(header.member.m_gid, "%I ", st->st_gid);
XX!   if ((st->st_mode & S_IFMT) == S_IFREG)
XX  	string_print(header.member.m_size, "%L ", st->st_size);
XX    else
XX! 	strncpy(header.dbuf.size, "0", TSIZLEN);
XX    string_print(header.member.m_time, "%L ", st->st_mtime);
XX!   /* Header.member.m_linked = ''; */
XX!   if ((ptr = is_linked(st)) != NULL) {
XX! 	strncpy(header.dbuf.linkname, ptr, NAMSIZ);
XX! 	st->st_mode = -1;	/* invalid value */
XX!   }
XX!   strncpy(header.dbuf.magic, TMAGIC, TMAGLEN);
XX    header.dbuf.version[0] = 0;
XX    header.dbuf.version[1] = 0;
XX    pwd = getpwuid(st->st_uid);
XX!   strncpy(header.dbuf.uname, (pwd != NULL ? pwd->pw_name : "nobody"), TUNMLEN);
XX    grp = getgrgid(st->st_gid);
XX!   strncpy(header.dbuf.gname, (grp != NULL ? grp->gr_name : "nobody"), TGNMLEN);
XX    if (st->st_mode & (S_IFBLK | S_IFCHR)) {
XX  	string_print(header.dbuf.devmajor, "%I ", (st->st_rdev >> 8));
XX  	string_print(header.dbuf.devminor, "%I ", (st->st_rdev & 0xFF));
XX--- 894,917 ----
XX    string_print(header.member.m_mode, "%I ", st->st_mode & 07777);
XX    string_print(header.member.m_uid, "%I ", st->st_uid);
XX    string_print(header.member.m_gid, "%I ", st->st_gid);
XX!   if (
XX! #ifdef _MINIX
XX!       (st->st_mode & S_IFMT) == S_IFBLK ||
XX! #endif
XX!       (st->st_mode & S_IFMT) == S_IFREG)
XX  	string_print(header.member.m_size, "%L ", st->st_size);
XX    else
XX! 	strncpy(header.dbuf.size, "0", (size_t) TSIZLEN);
XX    string_print(header.member.m_time, "%L ", st->st_mtime);
XX!   strncpy(header.dbuf.magic, TMAGIC, (size_t) TMAGLEN);
XX    header.dbuf.version[0] = 0;
XX    header.dbuf.version[1] = 0;
XX    pwd = getpwuid(st->st_uid);
XX!   strncpy(header.dbuf.uname,
XX! 	(pwd != NULL ? pwd->pw_name : "nobody"), TUNMLEN);
XX    grp = getgrgid(st->st_gid);
XX!   strncpy(header.dbuf.gname,
XX! 	(grp != NULL ? grp->gr_name : "nobody"), TGNMLEN);
XX    if (st->st_mode & (S_IFBLK | S_IFCHR)) {
XX  	string_print(header.dbuf.devmajor, "%I ", (st->st_rdev >> 8));
XX  	string_print(header.dbuf.devminor, "%I ", (st->st_rdev & 0xFF));
XX***************
XX*** 750,764 ****
XX    header.dbuf.prefix[0] = 0;
XX  }
XX  
XX! is_added(st, file)
XX  struct stat *st;
XX  char *file;
XX  {
XX    struct link *new;
XX!   char *malloc();
XX  
XX    if ((*file == 0) || (st->st_nlink == 1)) return;
XX!   new = (struct link *) malloc(sizeof(struct link));
XX    if (new == NULL) {
XX  	print("Out of memory\n");
XX  	return;
XX--- 919,934 ----
XX    header.dbuf.prefix[0] = 0;
XX  }
XX  
XX! void is_added(st, file)
XX  struct stat *st;
XX  char *file;
XX  {
XX    struct link *new;
XX!   char *name;
XX  
XX    if ((*file == 0) || (st->st_nlink == 1)) return;
XX!   name = path_name(file);
XX!   new = (struct link *) malloc(sizeof(struct link) + strlen(name));
XX    if (new == NULL) {
XX  	print("Out of memory\n");
XX  	return;
XX***************
XX*** 766,796 ****
XX    new->next = link_top;
XX    new->dev = st->st_dev;
XX    new->ino = st->st_ino;
XX!   strncpy(new->name, path_name(file), NAMSIZ);
XX    link_top = new;
XX  }
XX  
XX  char *is_linked(st)
XX  struct stat *st;
XX  {
XX    struct link *cur = link_top;
XX  
XX    while (cur != NULL)
XX! 	if ((cur->dev == st->st_dev) && (cur->ino == st->st_ino))
XX! 		return cur->name;
XX! 	else
XX  		cur = cur->next;
XX    return NULL;
XX  }
XX  
XX! clear_header()
XX  {
XX    register char *ptr = header.hdr_block;
XX  
XX!   while (ptr < &header.hdr_block[BLOCK_SIZE]) *ptr++ = '\0';
XX  }
XX  
XX! adjust_boundary()
XX  {
XX    clear_header();
XX    mwrite(tar_fd, (char *) &header, sizeof(header));
XX--- 936,987 ----
XX    new->next = link_top;
XX    new->dev = st->st_dev;
XX    new->ino = st->st_ino;
XX!   new->nlink = st->st_nlink - 1;
XX!   strcpy(new->name, name);
XX    link_top = new;
XX  }
XX  
XX+ void is_deleted(st)
XX+ struct stat *st;
XX+ {
XX+   struct link *old;
XX+ 
XX+   if ((old = link_top) != NULL) {
XX+ 	link_top = old->next;
XX+ 	free(old);
XX+   }
XX+ }
XX+ 
XX  char *is_linked(st)
XX  struct stat *st;
XX  {
XX    struct link *cur = link_top;
XX+   struct link **pre = &link_top;
XX+   static char name[NAMSIZ];
XX  
XX    while (cur != NULL)
XX! 	if ((cur->dev != st->st_dev) || (cur->ino != st->st_ino)) {
XX! 		pre = &cur->next;
XX  		cur = cur->next;
XX+ 	} else {
XX+ 		if (--cur->nlink == 0) {
XX+ 			*pre = cur->next;
XX+ 			strncpy(name, cur->name, NAMSIZ);
XX+ 			return name;
XX+ 		}
XX+ 		return cur->name;
XX+ 	}
XX    return NULL;
XX  }
XX  
XX! void clear_header()
XX  {
XX    register char *ptr = header.hdr_block;
XX  
XX!   while (ptr < &header.hdr_block[TBLOCK_SIZE]) *ptr++ = '\0';
XX  }
XX  
XX! void adjust_boundary()
XX  {
XX    clear_header();
XX    mwrite(tar_fd, (char *) &header, sizeof(header));
XX***************
XX*** 803,816 ****
XX    (void) close(tar_fd);
XX  }
XX  
XX! mread(fd, address, bytes)
XX  int fd, bytes;
XX  char *address;
XX  {
XX    if (read(fd, address, bytes) != bytes) error("Tar: read error.", NIL_PTR);
XX  }
XX  
XX! mwrite(fd, address, bytes)
XX  int fd, bytes;
XX  char *address;
XX  {
XX--- 994,1007 ----
XX    (void) close(tar_fd);
XX  }
XX  
XX! void mread(fd, address, bytes)
XX  int fd, bytes;
XX  char *address;
XX  {
XX    if (read(fd, address, bytes) != bytes) error("Tar: read error.", NIL_PTR);
XX  }
XX  
XX! void mwrite(fd, address, bytes)
XX  int fd, bytes;
XX  char *address;
XX  {
XX***************
XX*** 820,842 ****
XX    total_blocks++;
XX  }
XX  
XX! char output[BLOCK_SIZE];
XX! print(str)			/* changed to use stderr rather than stdout
XX  			 * -Dal */
XX  register char *str;
XX  {
XX!   static int index = 0;
XX  
XX    if (str == NIL_PTR) {
XX! 	write(2, output, index);
XX! 	index = 0;
XX  	return;
XX    }
XX    while (*str) {
XX! 	output[index++] = *str++;
XX! 	if (index == BLOCK_SIZE) {
XX! 		write(2, output, BLOCK_SIZE);
XX! 		index = 0;
XX  	}
XX    }
XX  }
XX--- 1011,1033 ----
XX    total_blocks++;
XX  }
XX  
XX! char output[TBLOCK_SIZE];
XX! void print(str)			/* changed to use stderr rather than stdout
XX  			 * -Dal */
XX  register char *str;
XX  {
XX!   static int indx = 0;
XX  
XX    if (str == NIL_PTR) {
XX! 	write(2, output, indx);
XX! 	indx = 0;
XX  	return;
XX    }
XX    while (*str) {
XX! 	output[indx++] = *str++;
XX! 	if (indx == TBLOCK_SIZE) {
XX! 		write(2, output, TBLOCK_SIZE);
XX! 		indx = 0;
XX  	}
XX    }
XX  }
XX***************
XX*** 856,895 ****
XX  }
XX  
XX  /*VARARGS2*/
XX! string_print(buffer, fmt, args)
XX  char *buffer;
XX! register char *fmt;
XX! int args;
XX  {
XX    register char *buf_ptr;
XX    char *scan_ptr;
XX!   char buf[NAME_SIZE];
XX!   char *argptr = (char *) &args;
XX    BOOL pr_fl, i;
XX  
XX    if (pr_fl = (buffer == NIL_PTR)) buffer = buf;
XX  
XX    buf_ptr = buffer;
XX    while (*fmt) {
XX  	if (*fmt == '%') {
XX  		fmt++;
XX  		switch (*fmt++) {
XX  		    case 's':
XX! 			scan_ptr = *((char **) argptr);
XX! 			argptr += sizeof(char *);
XX  			break;
XX  		    case 'I':
XX! 			scan_ptr = num_out((long) *((int *) argptr));
XX! 			argptr += sizeof(int);
XX  			for (i = 0; i < 5; i++) scan_ptr++;
XX  			break;
XX  		    case 'L':
XX! 			scan_ptr = num_out(*((long *) argptr));
XX! 			argptr += sizeof(long);
XX  			break;
XX  		    case 'd':
XX! 			scan_ptr = num_out((long) *((int *) argptr));
XX! 			argptr += sizeof(int);
XX  			while (*scan_ptr == '0') scan_ptr++;
XX  			scan_ptr--;
XX  			break;
XX--- 1047,1086 ----
XX  }
XX  
XX  /*VARARGS2*/
XX! #if __STDC__
XX! void string_print(char *buffer, char *fmt,...)
XX! #else
XX! void string_print(buffer, fmt)
XX  char *buffer;
XX! char *fmt;
XX! #endif
XX  {
XX+   va_list args;
XX    register char *buf_ptr;
XX    char *scan_ptr;
XX!   char buf[STRING_SIZE];
XX    BOOL pr_fl, i;
XX  
XX    if (pr_fl = (buffer == NIL_PTR)) buffer = buf;
XX  
XX+   va_start(args, fmt);
XX    buf_ptr = buffer;
XX    while (*fmt) {
XX  	if (*fmt == '%') {
XX  		fmt++;
XX  		switch (*fmt++) {
XX  		    case 's':
XX! 			scan_ptr = (char *) (va_arg(args, char *));
XX  			break;
XX  		    case 'I':
XX! 			scan_ptr = num_out((long) (va_arg(args, int)));
XX  			for (i = 0; i < 5; i++) scan_ptr++;
XX  			break;
XX  		    case 'L':
XX! 			scan_ptr = num_out((long) va_arg(args, long));
XX  			break;
XX  		    case 'd':
XX! 			scan_ptr = num_out((long) va_arg(args, int));
XX  			while (*scan_ptr == '0') scan_ptr++;
XX  			scan_ptr--;
XX  			break;
XX***************
XX*** 903,906 ****
XX--- 1094,1098 ----
XX    *buf_ptr = '\0';
XX  
XX    if (pr_fl) print(buffer);
XX+   va_end(args);
XX  }
X/
Xecho x - tee.c.d
Xsed '/^X/s///' > tee.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tee.c  crc=02530   1213	Sun Apr 25 21:35:22 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tee.c  crc=39242   1313	Wed Nov  4 04:19:21 1992
XX***************
XX*** 5,16 ****
XX  #include <blocksize.h>
XX  #include <signal.h>
XX  #include <unistd.h>
XX  
XX  #define	MAXFD	18
XX  
XX  int fd[MAXFD];
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 5,20 ----
XX  #include <blocksize.h>
XX  #include <signal.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX+ #include <minix/minlib.h>
XX  
XX  #define	MAXFD	18
XX  
XX  int fd[MAXFD];
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 58,62 ****
XX  
XX    for (i = 0; i < s; i++)	/* Close all fd's */
XX  	close(fd[i]);
XX!   exit(0);
XX  }
XX--- 62,66 ----
XX  
XX    for (i = 0; i < s; i++)	/* Close all fd's */
XX  	close(fd[i]);
XX!   return(0);
XX  }
X/
Xecho x - termcap.c.d
Xsed '/^X/s///' > termcap.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/termcap.c  crc=14056   3832	Sun Apr 25 21:35:22 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/termcap.c  crc=56233   3999	Wed Nov  4 04:19:21 1992
XX***************
XX*** 1,12 ****
XX  /* termcap - print termcap settings	Author: Terrence Holm */
XX  
XX  #include <stdio.h>
XX  
XX  #define  TC_BUFFER  1024	/* Size of termcap(3) buffer	*/
XX  
XX- char *getenv();
XX- char *tgetstr();
XX- 
XX  /****************************************************************/
XX  /*								*/
XX  /*    termcap  [ type ]						*/
XX--- 1,11 ----
XX  /* termcap - print termcap settings	Author: Terrence Holm */
XX  
XX+ #include <stdlib.h>
XX+ #include <termcap.h>
XX  #include <stdio.h>
XX  
XX  #define  TC_BUFFER  1024	/* Size of termcap(3) buffer	*/
XX  
XX  /****************************************************************/
XX  /*								*/
XX  /*    termcap  [ type ]						*/
XX***************
XX*** 17,26 ****
XX  /*								*/
XX  /****************************************************************/
XX  
XX  
XX! main( argc, argv )
XX!   int   argc;
XX!   char *argv[];
XX  
XX    {
XX    char *term;
XX--- 16,28 ----
XX  /*								*/
XX  /****************************************************************/
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void Print, (char *comment, char *name));
XX+ _PROTOTYPE(void Error, (char *message, char *arg));
XX  
XX! int main(argc, argv)
XX! int argc;
XX! char *argv[];
XX  
XX    {
XX    char *term;
XX***************
XX*** 94,100 ****
XX    Print( "Generated by numeric \"-\"",	  "k4" );
XX    Print( "Generated by numeric \"5\"",	  "k5" );
XX  
XX!   exit( 0 );
XX    }
XX  
XX  
XX--- 96,102 ----
XX    Print( "Generated by numeric \"-\"",	  "k4" );
XX    Print( "Generated by numeric \"5\"",	  "k5" );
XX  
XX!   return( 0 );
XX    }
XX  
XX  
XX***************
XX*** 113,119 ****
XX  /****************************************************************/
XX  
XX  
XX! Print( comment, name )
XX    char *comment;
XX    char *name;
XX  
XX--- 115,121 ----
XX  /****************************************************************/
XX  
XX  
XX! void Print( comment, name )
XX    char *comment;
XX    char *name;
XX  
XX***************
XX*** 151,157 ****
XX  /****************************************************************/
XX  
XX  
XX! Error( message, arg )
XX    char *message;
XX    char *arg;
XX  
XX--- 153,159 ----
XX  /****************************************************************/
XX  
XX  
XX! void Error( message, arg )
XX    char *message;
XX    char *arg;
XX  
X/
Xecho x - test.c.d
Xsed '/^X/s///' > test.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/test.c  crc=17805   5308	Sun Apr 25 21:35:22 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/test.c  crc=58579   6328	Mon Jan 18 18:56:10 1993
XX***************
XX*** 10,16 ****
XX   *			| "(" expr ")"
XX   *			| "!" expr
XX   *			;
XX!  *		unary-operator ::= "-r"|"-w"|"-f"|"-d"|"-s"|"-t"|"-z"|"-n";
XX   *		binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt";
XX   *		operand ::= <any legal UNIX file name>
XX   *
XX--- 10,16 ----
XX   *			| "(" expr ")"
XX   *			| "!" expr
XX   *			;
XX!  *		unary-operator ::= "-r"|"-w"|"-f"|"-d"|"-s"|"-t"|"-z"|"-n"|"-x";
XX   *		binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt";
XX   *		operand ::= <any legal UNIX file name>
XX   *
XX***************
XX*** 31,41 ****
XX--- 31,50 ----
XX   *		Mod Bruce Evans 09/27/89 evans@ditsyda.oz.au
XX   *		    Allow whitespace in numbers.
XX   *		    Deleted bloat from single use of stdio (fprintf).
XX+  *
XX+  *		Mod Paul Wood 10/10/91 paul@max.uk.mugnet.org
XX+  *		    Added support for -x option.
XX+  *
XX+  *		Add Kees J. Bot 02/19/92 kjb@cs.vu.nl
XX+  *		    Binary operator 'f1 -newer f2'.
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <sgtty.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  
XX  #define EOI	0
XX  #define FILRD	1
XX***************
XX*** 60,65 ****
XX--- 69,76 ----
XX  #define LPAREN	20
XX  #define RPAREN	21
XX  #define OPERAND	22
XX+ #define FILXQ	23
XX+ #define FILNW	24
XX  
XX  #define UNOP	1
XX  #define BINOP	2
XX***************
XX*** 136,141 ****
XX--- 147,158 ----
XX  	")", RPAREN, PAREN
XX    },
XX    {
XX+ 	"-x", FILXQ, UNOP
XX+   },
XX+   {
XX+ 	"-newer", FILNW, BINOP
XX+   },
XX+   {
XX  	0, 0, 0
XX    }
XX  };
XX***************
XX*** 145,150 ****
XX--- 162,176 ----
XX  char *prog;
XX  struct op *ip_op;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void syntax, (void));
XX+ _PROTOTYPE(long num, (char *s));
XX+ _PROTOTYPE(int filstat, (char *nm, int mode));
XX+ _PROTOTYPE(int newer, (char *fil1, char *fil2));
XX+ _PROTOTYPE(int lex, (char *s));
XX+ _PROTOTYPE(int primary, (int n));
XX+ _PROTOTYPE(int bexpr, (int n));
XX+ _PROTOTYPE(int expr, (int n));
XX  
XX  void syntax()
XX  {
XX***************
XX*** 193,202 ****
XX--- 219,243 ----
XX  	return(stat(nm, &s) == 0 && (s.st_size > 0L));
XX        case FILTT:
XX  	return(ioctl((int) num(nm), TIOCGETP, &t) == 0);
XX+       case FILXQ:
XX+ 	return(access(nm, 1) == 0);
XX    }
XX+   return(0);
XX  }
XX  
XX  
XX+ int newer(fil1, fil2)
XX+ char *fil1, *fil2;
XX+ /* True iff fil1 is not older (!) then fil2. */
XX+ {
XX+   struct stat s1, s2;
XX+ 
XX+   if (stat(fil1, &s1) != 0) return 0;
XX+   if (stat(fil2, &s2) != 0) return 1;
XX+   return s1.st_mtime >= s2.st_mtime;
XX+ }
XX+ 
XX+ 
XX  int lex(s)
XX  register char *s;
XX  {
XX***************
XX*** 253,258 ****
XX--- 294,301 ----
XX  			return(num(opnd1) <= num(opnd2));
XX  		    case INTLT:
XX  			return(num(opnd1) < num(opnd2));
XX+ 		    case FILNW:
XX+ 			return(newer(opnd1, opnd2));
XX  		}
XX  	}
XX  	ip--;
XX***************
XX*** 293,299 ****
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 336,342 ----
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 306,310 ****
XX    if (argc == 1) exit(1);
XX    prog = argv[0];
XX    ip = &argv[1];
XX!   exit(!expr(lex(*ip)));
XX  }
XX--- 349,353 ----
XX    if (argc == 1) exit(1);
XX    prog = argv[0];
XX    ip = &argv[1];
XX!   return(!expr(lex(*ip)));
XX  }
X/
Xecho x - time.c.d
Xsed '/^X/s///' > time.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/time.c  crc=09564   2381	Sun Apr 25 21:35:22 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/time.c  crc=28321   2999	Mon Jan 18 18:56:11 1993
XX***************
XX*** 5,27 ****
XX  #include <limits.h>
XX  #include <time.h>
XX  #include <signal.h>
XX  
XX- #define HZ CLOCKS_PER_SEC
XX- 
XX  char **args;
XX  char *name;
XX  
XX  int digit_seen;
XX! char a[] = "        .  \n";
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  
XX    struct tms pre_buf, post_buf;
XX    int status, pid;
XX!   long start_time, end_time;
XX  
XX    if (argc == 1) exit(0);
XX  
XX--- 5,35 ----
XX  #include <limits.h>
XX  #include <time.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <sys/wait.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdio.h>
XX  
XX  char **args;
XX  char *name;
XX  
XX  int digit_seen;
XX! char a[] = "        . \0";
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void print_time, (clock_t t));
XX! _PROTOTYPE(void twin, (int n, char *p));
XX! _PROTOTYPE(void execute, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX  
XX    struct tms pre_buf, post_buf;
XX    int status, pid;
XX!   time_t start_time, end_time;
XX  
XX    if (argc == 1) exit(0);
XX  
XX***************
XX*** 50,81 ****
XX    if ((status & 0377) != 0) std_err("Command terminated abnormally.\n");
XX    times(&post_buf);
XX  
XX!   /* Print results. */
XX!   print_time("real ", (end_time - start_time) * HZ);
XX!   print_time("user ", post_buf.tms_cutime - pre_buf.tms_cutime);
XX!   print_time("sys  ", post_buf.tms_cstime - pre_buf.tms_cstime);
XX!   exit(status >> 8);
XX  }
XX  
XX! print_time(mess, t)
XX! char *mess;
XX! register long t;
XX  {
XX  /* Print the time 't' in hours: minutes: seconds.  't' is in ticks. */
XX    int hours, minutes, seconds, hundredths, i;
XX  
XX    digit_seen = 0;
XX    for (i = 0; i < 8; i++) a[i] = ' ';
XX!   hours = (int) (t / (3600L * (long) HZ));
XX!   t -= (long) hours * 3600L * (long) HZ;
XX!   minutes = (int) (t / (60L * (long) HZ));
XX!   t -= (long) minutes * 60L * (long) HZ;
XX!   seconds = (int) (t / (long) HZ);
XX!   t -= (long) seconds * (long) HZ;
XX!   hundredths = (int) (t * 100L / (long) HZ);
XX  
XX-   std_err(mess);
XX- 
XX    if (hours) {
XX  	twin(hours, &a[0]);
XX  	a[2] = ':';
XX--- 58,100 ----
XX    if ((status & 0377) != 0) std_err("Command terminated abnormally.\n");
XX    times(&post_buf);
XX  
XX!   /* Print results.  -DNEW_TIME_FORMAT enables time on one line to 0.01 sec. */
XX! #ifndef NEW_TIME_FORMAT
XX!   std_err("real ");
XX!   print_time((clock_t) (end_time - start_time) * CLOCKS_PER_SEC);
XX!   std_err("\nuser ");
XX!   print_time(post_buf.tms_cutime - pre_buf.tms_cutime);
XX!   std_err("\nsys  ");
XX!   print_time(post_buf.tms_cstime - pre_buf.tms_cstime);
XX!   std_err("\n");
XX! #else
XX!   print_time((clock_t) (end_time - start_time) * CLOCKS_PER_SEC);
XX!   std_err(" real");
XX!   print_time(post_buf.tms_cutime - pre_buf.tms_cutime);
XX!   std_err(" user");
XX!   print_time(post_buf.tms_cstime - pre_buf.tms_cstime);
XX!   std_err(" sys\n");
XX! #endif
XX!   return(status >> 8);
XX  }
XX  
XX! void print_time(t)
XX! register clock_t t;
XX  {
XX  /* Print the time 't' in hours: minutes: seconds.  't' is in ticks. */
XX+ 
XX    int hours, minutes, seconds, hundredths, i;
XX  
XX    digit_seen = 0;
XX    for (i = 0; i < 8; i++) a[i] = ' ';
XX!   hours = (int) (t / ((clock_t) 3600 * CLOCKS_PER_SEC));
XX!   t -= (clock_t) hours * 3600 * CLOCKS_PER_SEC;
XX!   minutes = (int) (t / ((clock_t) 60 * CLOCKS_PER_SEC));
XX!   t -= (clock_t) minutes * 60 * CLOCKS_PER_SEC;
XX!   seconds = (int) (t / CLOCKS_PER_SEC);
XX!   t -= (clock_t) seconds * CLOCKS_PER_SEC;
XX!   hundredths = (int) (t * 100 / CLOCKS_PER_SEC);
XX  
XX    if (hours) {
XX  	twin(hours, &a[0]);
XX  	a[2] = ':';
XX***************
XX*** 90,102 ****
XX  	a[7] = '0';
XX    a[9] = hundredths / 10 + '0';
XX    a[10] = hundredths % 10 + '0';
XX- #ifndef HUNDREDTHS		/* tenths used to be enough */
XX-   a[10] = '\n'; a[11] = 0;
XX- #endif
XX    std_err(a);
XX  }
XX  
XX! twin(n, p)
XX  int n;
XX  char *p;
XX  {
XX--- 109,118 ----
XX  	a[7] = '0';
XX    a[9] = hundredths / 10 + '0';
XX    a[10] = hundredths % 10 + '0';
XX    std_err(a);
XX  }
XX  
XX! void twin(n, p)
XX  int n;
XX  char *p;
XX  {
XX***************
XX*** 109,115 ****
XX    if (n > 0) digit_seen = 1;
XX  }
XX  
XX! execute()
XX  {
XX    execvp(name, args);
XX    std_err("Cannot execute ");
XX--- 125,131 ----
XX    if (n > 0) digit_seen = 1;
XX  }
XX  
XX! void execute()
XX  {
XX    execvp(name, args);
XX    std_err("Cannot execute ");
X/
Xecho x - touch.c.d
Xsed '/^X/s///' > touch.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/touch.c  crc=02393   1194	Sun Apr 25 21:35:23 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/touch.c  crc=43426   1436	Wed Nov  4 04:19:21 1992
XX***************
XX*** 3,11 ****
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <errno.h>
XX  int no_creat = 0;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 3,22 ----
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <errno.h>
XX+ #include <stdlib.h>
XX+ #include <time.h>
XX+ #include <fcntl.h>
XX+ #include <unistd.h>
XX+ #include <utime.h>
XX+ #include <minix/minlib.h>
XX+ 
XX  int no_creat = 0;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int doit, (char *name));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 33,51 ****
XX  		}
XX  	}
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX! doit(name)
XX  char *name;
XX  {
XX    int fd;
XX!   long *t, tim;
XX    struct stat buf;
XX!   unsigned short tmp;
XX!   long tvp[2];
XX!   extern long time();
XX  
XX    if (!access(name, 0)) {	/* change date if possible */
XX  	stat(name, &buf);
XX--- 44,61 ----
XX  		}
XX  	}
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX! int doit(name)
XX  char *name;
XX  {
XX    int fd;
XX!   time_t tim;
XX    struct stat buf;
XX!   mode_t tmp;
XX!   time_t tvp[2];
XX  
XX    if (!access(name, 0)) {	/* change date if possible */
XX  	stat(name, &buf);
XX***************
XX*** 55,61 ****
XX  	tim = time((long *) 0);
XX  	tvp[0] = tim;
XX  	tvp[1] = tim;
XX! 	if (!utime(name, tvp))
XX  		return(0);
XX  	else
XX  		return(1);
XX--- 65,71 ----
XX  	tim = time((long *) 0);
XX  	tvp[0] = tim;
XX  	tvp[1] = tim;
XX! 	if (!utime(name, (struct utimbuf *)tvp))
XX  		return(0);
XX  	else
XX  		return(1);
XX***************
XX*** 74,80 ****
XX  }
XX  
XX  
XX! usage()
XX  {
XX    std_err("Usage: touch [-c] file...\n");
XX    exit(1);
XX--- 84,90 ----
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    std_err("Usage: touch [-c] file...\n");
XX    exit(1);
X/
Xecho x - tr.c.d
Xsed '/^X/s///' > tr.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tr.c  crc=42541   3221	Sun Apr 25 21:35:23 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tr.c  crc=07333   3651	Wed Nov  4 04:19:21 1992
XX***************
XX*** 22,28 ****
XX  
XX  short in_index, out_index;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 22,39 ----
XX  
XX  short in_index, out_index;
XX  
XX! #include <sys/types.h>
XX! #include <string.h>
XX! #include <stdlib.h>
XX! #include <unistd.h>
XX! 
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void convert, (void));
XX! _PROTOTYPE(void map, (unsigned char *string1, unsigned char *string2));
XX! _PROTOTYPE(void expand, (char *arg, unsigned char *buffer));
XX! _PROTOTYPE(void complement, (unsigned char *buffer));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 57,65 ****
XX  	for (ptr = output; *ptr; ptr++) outvec[*ptr] = TRUE;
XX    }
XX    convert();
XX  }
XX  
XX! convert()
XX  {
XX    short read_chars = 0;
XX    short c, coded;
XX--- 68,77 ----
XX  	for (ptr = output; *ptr; ptr++) outvec[*ptr] = TRUE;
XX    }
XX    convert();
XX+   return(0);
XX  }
XX  
XX! void convert()
XX  {
XX    short read_chars = 0;
XX    short c, coded;
XX***************
XX*** 67,74 ****
XX  
XX    for (;;) {
XX  	if (in_index == read_chars) {
XX! 		if ((read_chars = read(0, input, BUFFER_SIZE)) <= 0) {
XX! 			if (write(1, output, out_index) != out_index)
XX  				write(2, "Bad write\n", 10);
XX  			exit(0);
XX  		}
XX--- 79,86 ----
XX  
XX    for (;;) {
XX  	if (in_index == read_chars) {
XX! 		if ((read_chars = read(0, (char *)input, BUFFER_SIZE)) <= 0) {
XX! 			if (write(1, (char *)output, out_index) != out_index)
XX  				write(2, "Bad write\n", 10);
XX  			exit(0);
XX  		}
XX***************
XX*** 80,86 ****
XX  	if (sq_fl && last == coded && outvec[coded]) continue;
XX  	output[out_index++] = last = coded;
XX  	if (out_index == BUFFER_SIZE) {
XX! 		if (write(1, output, out_index) != out_index) {
XX  			write(2, "Bad write\n", 10);
XX  			exit(1);
XX  		}
XX--- 92,98 ----
XX  	if (sq_fl && last == coded && outvec[coded]) continue;
XX  	output[out_index++] = last = coded;
XX  	if (out_index == BUFFER_SIZE) {
XX! 		if (write(1, (char *)output, out_index) != out_index) {
XX  			write(2, "Bad write\n", 10);
XX  			exit(1);
XX  		}
XX***************
XX*** 91,97 ****
XX    /* NOTREACHED */
XX  }
XX  
XX! map(string1, string2)
XX  register unsigned char *string1, *string2;
XX  {
XX    unsigned char last;
XX--- 103,109 ----
XX    /* NOTREACHED */
XX  }
XX  
XX! void map(string1, string2)
XX  register unsigned char *string1, *string2;
XX  {
XX    unsigned char last;
XX***************
XX*** 105,111 ****
XX    }
XX  }
XX  
XX! expand(arg, buffer)
XX  register char *arg;
XX  register unsigned char *buffer;
XX  {
XX--- 117,123 ----
XX    }
XX  }
XX  
XX! void expand(arg, buffer)
XX  register char *arg;
XX  register unsigned char *buffer;
XX  {
XX***************
XX*** 139,145 ****
XX    }
XX  }
XX  
XX! complement(buffer)
XX  unsigned char *buffer;
XX  {
XX    register unsigned char *ptr;
XX--- 151,157 ----
XX    }
XX  }
XX  
XX! void complement(buffer)
XX  unsigned char *buffer;
XX  {
XX    register unsigned char *ptr;
XX***************
XX*** 153,157 ****
XX  	if (*ptr == '\0') conv[index++] = i & ASCII;
XX    }
XX    conv[index] = '\0';
XX!   strcpy(buffer, conv);
XX  }
XX--- 165,169 ----
XX  	if (*ptr == '\0') conv[index++] = i & ASCII;
XX    }
XX    conv[index] = '\0';
XX!   strcpy((char *)buffer, (char *)conv);
XX  }
X/
Xecho x - traverse.c.d
Xsed '/^X/s///' > traverse.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/traverse.c  crc=26744   1708	Sun Apr 25 21:35:23 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/traverse.c  crc=01982   2227	Wed Nov  4 04:19:21 1992
XX***************
XX*** 2,44 ****
XX  
XX  #include <sys/types.h>
XX  #include <sys/dir.h>
XX  #include <stdio.h>
XX  
XX  #define STANDALONE
XX  
XX  #define	DIR	FILE
XX! #define	MAXNAME (DIRSIZ+2)
XX  #define	opendir(path) fopen (path, "r")
XX  #define closedir(dirp) fclose (dirp)
XX  
XX  struct direct *readdir(dirp)
XX  DIR *dirp;
XX  {
XX    static struct direct entry;
XX!   if (dirp == NULL) return((struct direct *) NULL);
XX    for (;;) {
XX! 	if (fread(&entry, sizeof(struct direct), 1, dirp) == 0)
XX! 		return((struct direct *) NULL);
XX  	if (entry.d_ino) return(&entry);
XX    }
XX  }
XX  
XX- char *strncpy();
XX- 
XX  char *namedir(entry)
XX  struct direct *entry;
XX  {
XX    static char name[MAXNAME];
XX!   return(strncpy(name, entry->d_name, DIRSIZ));
XX  }
XX  
XX  
XX  #include <sys/stat.h>
XX  #define	isdir(path) (stat(path, &buf) ? 0 : (buf.st_mode&S_IFMT)==S_IFDIR)
XX  
XX! traverse(path, func)
XX  char *path;
XX! int (*func) ();
XX  {
XX    DIR *dirp;
XX    struct direct *entry;
XX--- 2,57 ----
XX  
XX  #include <sys/types.h>
XX  #include <sys/dir.h>
XX+ #include <string.h>
XX+ #include <limits.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define STANDALONE
XX  
XX  #define	DIR	FILE
XX! #define	MAXNAME (NAME_MAX+2)
XX  #define	opendir(path) fopen (path, "r")
XX  #define closedir(dirp) fclose (dirp)
XX+ #define readdir myreaddir	/* someday this should use the library
XX+ 				 * dirent routines, and report errors */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(struct direct *readdir, (DIR *dirp));
XX+ _PROTOTYPE(char *namedir, (struct direct *entry));
XX+ _PROTOTYPE(void traverse, (char *path, void (*func)(char *, int, int)));
XX+ _PROTOTYPE(void tryverse, (char *file, int type, int pos));
XX+ 
XX  struct direct *readdir(dirp)
XX  DIR *dirp;
XX  {
XX    static struct direct entry;
XX!   if (dirp == NULL) return(NULL);
XX    for (;;) {
XX! 	if (fread(&entry, sizeof(struct direct), (size_t)1, dirp) == 0)
XX! 		return(NULL);
XX  	if (entry.d_ino) return(&entry);
XX    }
XX  }
XX  
XX  char *namedir(entry)
XX  struct direct *entry;
XX  {
XX    static char name[MAXNAME];
XX!   return(strncpy(name, entry->d_name, (size_t)NAME_MAX));
XX  }
XX  
XX  
XX  #include <sys/stat.h>
XX  #define	isdir(path) (stat(path, &buf) ? 0 : (buf.st_mode&S_IFMT)==S_IFDIR)
XX  
XX! void traverse(path, func)
XX  char *path;
XX! #ifdef __STDC__
XX! void (*func) (char *, int, int);
XX! #else
XX! void (*func) ();
XX! #endif
XX  {
XX    DIR *dirp;
XX    struct direct *entry;
XX***************
XX*** 65,72 ****
XX  #ifdef STANDALONE
XX  
XX  static Indent = 0;
XX! tryverse(file, type, pos)
XX  char *file;
XX  {
XX    int in;
XX    if (pos == 0) {
XX--- 78,88 ----
XX  #ifdef STANDALONE
XX  
XX  static Indent = 0;
XX! 
XX! void tryverse(file, type, pos)
XX  char *file;
XX+ int type;
XX+ int pos;
XX  {
XX    int in;
XX    if (pos == 0) {
XX***************
XX*** 80,91 ****
XX  	Indent--;
XX  }
XX  
XX! main(argc, argv)
XX  char **argv;
XX  {
XX-   int tryverse();
XX    char *root = argc > 1 ? argv[1] : ".";
XX    traverse(root, tryverse);
XX  }
XX  
XX  #endif
XX--- 96,108 ----
XX  	Indent--;
XX  }
XX  
XX! int main(argc, argv)
XX! int argc;
XX  char **argv;
XX  {
XX    char *root = argc > 1 ? argv[1] : ".";
XX    traverse(root, tryverse);
XX+   return(0);
XX  }
XX  
XX  #endif
X/
Xecho x - treecmp.c.d
Xsed '/^X/s///' > treecmp.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/treecmp.c  crc=63088   7773	Sun Apr 25 21:35:24 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/treecmp.c  crc=35703   8263	Sun Dec 20 15:36:55 1992
XX***************
XX*** 21,26 ****
XX--- 21,27 ----
XX  #include <fcntl.h>
XX  #include <string.h>
XX  #include <unistd.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define BUFSIZE 4096		/* size of file buffers */
XX***************
XX*** 40,46 ****
XX  int changes;			/* set on -c flag */
XX  int verbose;			/* set on -v flag */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 41,54 ----
XX  int changes;			/* set on -c flag */
XX  int verbose;			/* set on -v flag */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void compare, (char *old, char *new));
XX! _PROTOTYPE(void regular, (char *old, char *new));
XX! _PROTOTYPE(void directory, (char *old, char *new));
XX! _PROTOTYPE(void check, (char *s, struct dirstruct *dp1, int ent1, char *new));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 49,55 ****
XX    if (argc < 3 || argc > 4) usage();
XX    p = argv[1];
XX    if (argc == 4) {
XX! 	if (*p != '-') usage;
XX  	p++;
XX  	if (*p == '\0') usage();
XX  	while (*p) {
XX--- 57,63 ----
XX    if (argc < 3 || argc > 4) usage();
XX    p = argv[1];
XX    if (argc == 4) {
XX! 	if (*p != '-') usage();
XX  	p++;
XX  	if (*p == '\0') usage();
XX  	while (*p) {
XX***************
XX*** 64,73 ****
XX    else
XX  	compare(argv[2], argv[3]);
XX  
XX!   exit(0);
XX  }
XX  
XX! compare(old, new)
XX  char *old, *new;
XX  {
XX  /* This is the main comparision routine.  It gets two path names as arguments
XX--- 72,81 ----
XX    else
XX  	compare(argv[2], argv[3]);
XX  
XX!   return(0);
XX  }
XX  
XX! void compare(old, new)
XX  char *old, *new;
XX  {
XX  /* This is the main comparision routine.  It gets two path names as arguments
XX***************
XX*** 113,119 ****
XX    return;
XX  }
XX  
XX! regular(old, new)
XX  char *old, *new;
XX  {
XX  /* Compare to regular files.  If they are different, complain. */
XX--- 121,127 ----
XX    return;
XX  }
XX  
XX! void regular(old, new)
XX  char *old, *new;
XX  {
XX  /* Compare to regular files.  If they are different, complain. */
XX***************
XX*** 172,178 ****
XX    close(fd2);
XX  }
XX  
XX! directory(old, new)
XX  char *old, *new;
XX  {
XX  /* Recursively compare two directories by reading them and comparing their
XX--- 180,186 ----
XX    close(fd2);
XX  }
XX  
XX! void directory(old, new)
XX  char *old, *new;
XX  {
XX  /* Recursively compare two directories by reading them and comparing their
XX***************
XX*** 184,200 ****
XX    char name1buf[MAXPATH], name2buf[MAXPATH];
XX    struct dirstruct *dp1, *dp2;
XX    unsigned dir1bytes, dir2bytes;
XX-   extern char *malloc();
XX  
XX    /* Allocate space to read in the directories */
XX    dir1bytes = (unsigned) stat1.st_size;
XX!   dir1buf = malloc(dir1bytes);
XX    if (dir1buf == 0) {
XX  	fprintf(stderr, "Cannot process directory %s: out of memory\n", new);
XX  	return;
XX    }
XX    dir2bytes = (unsigned) stat2.st_size;
XX!   dir2buf = malloc(dir2bytes);
XX    if (dir2buf == 0) {
XX  	fprintf(stderr, "Cannot process directory %s: out of memory\n", old);
XX  	free(dir1buf);
XX--- 192,207 ----
XX    char name1buf[MAXPATH], name2buf[MAXPATH];
XX    struct dirstruct *dp1, *dp2;
XX    unsigned dir1bytes, dir2bytes;
XX  
XX    /* Allocate space to read in the directories */
XX    dir1bytes = (unsigned) stat1.st_size;
XX!   dir1buf = (char *)malloc((size_t)dir1bytes);
XX    if (dir1buf == 0) {
XX  	fprintf(stderr, "Cannot process directory %s: out of memory\n", new);
XX  	return;
XX    }
XX    dir2bytes = (unsigned) stat2.st_size;
XX!   dir2buf = (char *)malloc((size_t)dir2bytes);
XX    if (dir2buf == 0) {
XX  	fprintf(stderr, "Cannot process directory %s: out of memory\n", old);
XX  	free(dir1buf);
XX***************
XX*** 247,253 ****
XX    dp2 = (struct dirstruct *) dir2buf;
XX    for (i = 0; i < ent2; i++) {
XX  	if (dp2->inum == 0 || strcmp(dp2->fname, ".") == 0 ||
XX! 	    strcmp(dp2->fname, "..") == 0) {
XX  		dp2++;
XX  		continue;
XX  	}
XX--- 254,260 ----
XX    dp2 = (struct dirstruct *) dir2buf;
XX    for (i = 0; i < ent2; i++) {
XX  	if (dp2->inum == 0 || strcmp(dp2->fname, ".") == 0 ||
XX! 					    strcmp(dp2->fname, "..") == 0) {
XX  		dp2++;
XX  		continue;
XX  	}
XX***************
XX*** 277,286 ****
XX  	}
XX  	strcpy(name1buf, old);
XX  	strcat(name1buf, "/");
XX! 	strncat(name1buf, dp1->fname, DIRENTLEN);
XX  	strcpy(name2buf, new);
XX  	strcat(name2buf, "/");
XX! 	strncat(name2buf, dp1->fname, DIRENTLEN);
XX  
XX  	/* Here is the recursive call to process an entry. */
XX  	compare(name1buf, name2buf);	/* recursive call */
XX--- 284,293 ----
XX  	}
XX  	strcpy(name1buf, old);
XX  	strcat(name1buf, "/");
XX! 	strncat(name1buf, dp1->fname, (size_t)DIRENTLEN);
XX  	strcpy(name2buf, new);
XX  	strcat(name2buf, "/");
XX! 	strncat(name2buf, dp1->fname, (size_t)DIRENTLEN);
XX  
XX  	/* Here is the recursive call to process an entry. */
XX  	compare(name1buf, name2buf);	/* recursive call */
XX***************
XX*** 291,297 ****
XX    free(dir2buf);
XX  }
XX  
XX! check(s, dp1, ent1, new)
XX  char *s;
XX  struct dirstruct *dp1;
XX  int ent1;
XX--- 298,304 ----
XX    free(dir2buf);
XX  }
XX  
XX! void check(s, dp1, ent1, new)
XX  char *s;
XX  struct dirstruct *dp1;
XX  int ent1;
XX***************
XX*** 299,314 ****
XX  {
XX  /* See if the file name 's' is present in the directory 'dirbuf'. */
XX    int i;
XX  
XX    for (i = 0; i < ent1; i++) {
XX! 	if (strncmp(dp1->fname, s, DIRENTLEN) == 0) return;
XX  	dp1++;
XX    }
XX!   if (changes == 0) printf("Missing file: %s/%s\n", new, s);
XX  	
XX  }
XX  
XX! usage()
XX  {
XX    printf("Usage: treecmp [-cv] old_dir new_dir\n");
XX    exit(1);
XX--- 306,326 ----
XX  {
XX  /* See if the file name 's' is present in the directory 'dirbuf'. */
XX    int i;
XX+   char file[DIRENTLEN+1];
XX  
XX    for (i = 0; i < ent1; i++) {
XX! 	if (strncmp(dp1->fname, s, (size_t)DIRENTLEN) == 0) return;
XX  	dp1++;
XX    }
XX!   if (changes == 0) {
XX! 	strncpy(file, s, DIRENTLEN);
XX! 	file[DIRENTLEN] = '\0';
XX! 	printf("Missing file: %s/%s\n", new, file);
XX!   }
XX  	
XX  }
XX  
XX! void usage()
XX  {
XX    printf("Usage: treecmp [-cv] old_dir new_dir\n");
XX    exit(1);
X/
Xecho x - tset.c.d
Xsed '/^X/s///' > tset.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tset.c  crc=18877   2319	Sun Apr 25 21:35:24 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tset.c  crc=16808   2454	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,6 ****
XX--- 1,7 ----
XX  /* tset - set the TERM variable		Author: Terrence Holm */
XX  
XX  #include <sys/types.h>
XX+ #include <stdlib.h>
XX  #include <string.h>
XX  #include <termcap.h>
XX  #include <unistd.h>
XX***************
XX*** 9,16 ****
XX  #define  LINE_LENGTH  40	/* Max length in /etc/ttytype	 */
XX  #define  TC_BUFFER  1024	/* Size of termcap(3) buffer	 */
XX  
XX- char *ttyname();
XX- 
XX  /****************************************************************/
XX  /*								*/
XX  /*	eval `tset  [ device_type ]`				*/
XX--- 10,15 ----
XX***************
XX*** 36,44 ****
XX  /*								*/
XX  /****************************************************************/
XX  
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 35,46 ----
XX  /*								*/
XX  /****************************************************************/
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void Find_Termcap, (char *terminal));
XX+ _PROTOTYPE(void Error, (char *msg));
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 58,74 ****
XX  
XX    /* No terminal name supplied, so use the current device	 */
XX  
XX!   if ((name = ttyname(0)) == (char *) NULL)
XX  	Error("Can not determine the user's terminal");
XX  
XX    name += 5;			/* Chop off "/dev/" part	 */
XX  
XX    /* Look up the default terminal type in /etc/ttytype		 */
XX  
XX!   if ((f = fopen("/etc/ttytype", "r")) == (FILE *) NULL)
XX  	Error("Can not open /etc/ttytype");
XX  
XX!   while (fgets(line, LINE_LENGTH, f) != (char *) NULL) {
XX  	char *space = strchr(line, ' ');
XX  
XX  	line[strlen(line) - 1] = '\0';	/* Remove '\n'		 */
XX--- 60,76 ----
XX  
XX    /* No terminal name supplied, so use the current device	 */
XX  
XX!   if ((name = ttyname(0)) == NULL)
XX  	Error("Can not determine the user's terminal");
XX  
XX    name += 5;			/* Chop off "/dev/" part	 */
XX  
XX    /* Look up the default terminal type in /etc/ttytype		 */
XX  
XX!   if ((f = fopen("/etc/ttytype", "r")) == NULL)
XX  	Error("Can not open /etc/ttytype");
XX  
XX!   while (fgets(line, LINE_LENGTH, f) != NULL) {
XX  	char *space = strchr(line, ' ');
XX  
XX  	line[strlen(line) - 1] = '\0';	/* Remove '\n'		 */
XX***************
XX*** 81,89 ****
XX    }
XX  
XX    Error("Can not find your terminal in /etc/ttytype");
XX  }
XX  
XX! Find_Termcap(terminal)
XX  char *terminal;
XX  {
XX    char termcap[TC_BUFFER];
XX--- 83,92 ----
XX    }
XX  
XX    Error("Can not find your terminal in /etc/ttytype");
XX+   return(0);
XX  }
XX  
XX! void Find_Termcap(terminal)
XX  char *terminal;
XX  {
XX    char termcap[TC_BUFFER];
XX***************
XX*** 95,101 ****
XX    printf("TERM=%s;\n", terminal);
XX  }
XX  
XX! Error(msg)
XX  char *msg;
XX  {
XX    fprintf(stderr, "tset: %s\n", msg);
XX--- 98,104 ----
XX    printf("TERM=%s;\n", terminal);
XX  }
XX  
XX! void Error(msg)
XX  char *msg;
XX  {
XX    fprintf(stderr, "tset: %s\n", msg);
X/
Xecho x - tsort.c.d
Xsed '/^X/s///' > tsort.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tsort.c  crc=11978   7621	Sun Apr 25 21:35:24 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tsort.c  crc=53037   8184	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,3 ****
XX--- 1,5 ----
XX+ /* topo - topological sort		Author: Kent Williams */
XX+ 
XX  /*
XX  ** topo - perform a topological sort of the output of lorder.
XX  **
XX***************
XX*** 6,22 ****
XX  ** Author: Kent Williams (williams@umaxc.weeg.uiowa.edu)
XX  */
XX  
XX- #include <stdio.h>
XX  #include <ctype.h>
XX  
XX- /*
XX- ** for the benefit of the zortech runtime
XX- */
XX- int _okbigbuf = 0;
XX- 
XX- extern char *malloc();
XX- extern char *gets();
XX- 
XX  typedef struct __v {
XX      struct __v *next;   /* link list node                   */
XX      int indegree,       /* number of edges into this vertex */
XX--- 8,18 ----
XX  ** Author: Kent Williams (williams@umaxc.weeg.uiowa.edu)
XX  */
XX  
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <stdio.h>
XX  
XX  typedef struct __v {
XX      struct __v *next;   /* link list node                   */
XX      int indegree,       /* number of edges into this vertex */
XX***************
XX*** 32,50 ****
XX      vertex *v;          /* vertex to which this edge goes   */
XX  } edge;
XX  
XX  /*
XX  ** xmalloc -- standard do or die malloc front end.
XX  */
XX  void *
XX  xmalloc(siz)
XX! unsigned siz;
XX  {
XX      void *rval = (void *)malloc(siz);
XX      if(rval == NULL) {
XX          fputs("Out of memory.\n",stderr);
XX          exit(1);
XX      }
XX!     return(rval);
XX  }
XX  
XX  /*
XX--- 28,60 ----
XX      vertex *v;          /* vertex to which this edge goes   */
XX  } edge;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void *xmalloc, (size_t siz));
XX+ _PROTOTYPE(edge *new_edge, (vertex *v));
XX+ _PROTOTYPE(char *copyupto, (char *name, char *buf, int stop));
XX+ _PROTOTYPE(int child_of, (vertex *parent, vertex *child));
XX+ _PROTOTYPE(vertex *add_v, (char *s));
XX+ _PROTOTYPE(void readin, (void));
XX+ _PROTOTYPE(void pushname, (char *s));
XX+ _PROTOTYPE(char *popname, (void));
XX+ _PROTOTYPE(void topo, (void));
XX+ _PROTOTYPE(void print_cycle, (vertex *parent, vertex *child));
XX+ _PROTOTYPE(void dfs, (vertex *v));
XX+ _PROTOTYPE(void check_cycles, (void));
XX+ 
XX  /*
XX  ** xmalloc -- standard do or die malloc front end.
XX  */
XX  void *
XX  xmalloc(siz)
XX! size_t siz;
XX  {
XX      void *rval = (void *)malloc(siz);
XX      if(rval == NULL) {
XX          fputs("Out of memory.\n",stderr);
XX          exit(1);
XX      }
XX!     return rval;
XX  }
XX  
XX  /*
XX***************
XX*** 118,124 ****
XX          return v;
XX      }
XX  
XX!     v = (vertex *)xmalloc(sizeof(vertex)+strlen(s));
XX  
XX      v->out = NULL;
XX      strcpy(v->key,s);
XX--- 128,134 ----
XX          return v;
XX      }
XX  
XX!     v = (vertex *)xmalloc(sizeof(vertex) + strlen(s));
XX  
XX      v->out = NULL;
XX      strcpy(v->key,s);
XX***************
XX*** 189,196 ****
XX  /*
XX  ** topo - do a topological sort of the dependency graph.
XX  */
XX! topo() {
XX!     vertex *x;
XX      edge *e;
XX      vertex *outq = NULL,*tmp;
XX  #define insq(x) ((x->next = outq),(outq = x))
XX--- 199,206 ----
XX  /*
XX  ** topo - do a topological sort of the dependency graph.
XX  */
XX! void topo() {
XX!     vertex *x = vset,*n;
XX      edge *e;
XX      vertex *outq = NULL,*tmp;
XX  #define insq(x) ((x->next = outq),(outq = x))
XX***************
XX*** 198,211 ****
XX  
XX      /*
XX      ** find all vertices that don't depend on any other vertices
XX!     ** Since it break the next links to insert x into the queue,
XX      ** x->next is saved before insq, to resume the list traversal.
XX      */
XX!     for(x = vset; x != NULL; x = x->next)
XX          if(x->indegree == 0) {
XX              insq(x);
XX              pushname(x->key);       
XX          }
XX  
XX      /*
XX      ** for each vertex V with indegree of zero,
XX--- 208,224 ----
XX  
XX      /*
XX      ** find all vertices that don't depend on any other vertices
XX!     ** Since it breaks the "next" links to insert x into the queue,
XX      ** x->next is saved before insq, to resume the list traversal.
XX      */
XX!     while (x != NULL) {
XX! 	n = x->next;
XX          if(x->indegree == 0) {
XX              insq(x);
XX              pushname(x->key);       
XX          }
XX+ 	x = n;
XX+     }
XX  
XX      /*
XX      ** for each vertex V with indegree of zero,
XX***************
XX*** 315,321 ****
XX  check_cycles()
XX  {
XX      vertex *v;
XX-     struct _vpair *vp;
XX      for(v = vset; v != NULL; v = v->next)
XX          dfs(v);
XX  }
XX--- 328,333 ----
XX***************
XX*** 323,330 ****
XX  /*
XX  ** main program.
XX  */
XX! int
XX! main(argc,argv)
XX  int argc;
XX  char **argv;
XX  {
XX--- 335,341 ----
XX  /*
XX  ** main program.
XX  */
XX! int main(argc,argv)
XX  int argc;
XX  char **argv;
XX  {
XX***************
XX*** 339,343 ****
XX      readin();
XX      check_cycles();
XX      topo();
XX  }
XX- 
XX--- 350,354 ----
XX      readin();
XX      check_cycles();
XX      topo();
XX+     return(0);
XX  }
X/
Xecho x - ttt.c.d
Xsed '/^X/s///' > ttt.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/ttt.c  crc=30131   6307	Sun Apr 25 21:35:24 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/ttt.c  crc=12370   6927	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,18 ****
XX  /* tic tac toe (noughts and crosses)		Author: Warren Toomey */
XX  
XX! /* Copyright (C) 1988 Warren Toomey.
XX!   You may use, copy, modify, or give this away provided you
XX!   1. make the source available with every copy.
XX!   2. include this notice.
XX!   3. don't use this for military purposes.
XX!   (but you can take credit for improvements, etc.)
XX! */
XX  
XX  /* Compile with cc -o tic tic.c -lcurses -ltermcap */
XX  
XX! #define CURSES
XX  #ifdef CURSES
XX! /*  #include <curses.h> 		Used by the real curses  */
XX  #endif
XX  
XX  #ifndef CURSES
XX--- 1,25 ----
XX  /* tic tac toe (noughts and crosses)		Author: Warren Toomey */
XX  
XX! /* Copyright 1988 by Warren Toomey	wkt@cs.adfa.oz.au[@uunet.uu.net]
XX!  *
XX!  * You may freely copy or distribute this code as long as this notice
XX!  * remains intact.
XX!  *
XX!  * You may modify this code, as long as this notice remains intact, and
XX!  * you add another notice indicating that the code has been modified.
XX!  *
XX!  * You may NOT sell this code or in any way profit from this code without
XX!  * prior agreement from the author.
XX!  */
XX  
XX  /* Compile with cc -o tic tic.c -lcurses -ltermcap */
XX  
XX! #include <stdlib.h>
XX! #include <time.h>
XX! #include <stdio.h>
XX! 
XX  #ifdef CURSES
XX! #include <curses.h>
XX  #endif
XX  
XX  #ifndef CURSES
XX***************
XX*** 25,30 ****
XX--- 32,44 ----
XX    int path;			/* alphabeta consists of a value */
XX  } MOVE;				/* and an actual move (path)   */
XX  
XX+ _PROTOTYPE(int main, (void));
XX+ _PROTOTYPE(int stateval, (int board [], int whosemove));
XX+ _PROTOTYPE(MOVE alphabeta, (int board [], int whosemove, int alpha, int beta));
XX+ _PROTOTYPE(void draw, (int board []));
XX+ _PROTOTYPE(void getmove, (int board []));
XX+ _PROTOTYPE(int endofgame, (int board []));
XX+ _PROTOTYPE(int randommove, (void));
XX  
XX   /* Static evaluator. Returns 100 if we have 3 in a row -100 if they have 3
XX    * in a row
XX***************
XX*** 36,42 ****
XX  
XX  int stateval(board, whosemove)
XX  int board[];
XX! 
XX  {
XX    static int row[8][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8},	/* Indices of 3in-a-rows */
XX  			{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
XX--- 50,56 ----
XX  
XX  int stateval(board, whosemove)
XX  int board[];
XX! int whosemove;
XX  {
XX    static int row[8][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8},	/* Indices of 3in-a-rows */
XX  			{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
XX***************
XX*** 109,115 ****
XX  }
XX  
XX  
XX! draw(board)			/* Draw the board */
XX  int board[];
XX  {
XX    int i, j, row;
XX--- 123,129 ----
XX  }
XX  
XX  
XX! void draw(board)			/* Draw the board */
XX  int board[];
XX  {
XX    int i, j, row;
XX***************
XX*** 147,156 ****
XX  }
XX  
XX  
XX! getmove(board)			/* Get a player's move */
XX  int board[];
XX  {
XX    int Move;
XX  
XX    do {
XX  	do {
XX--- 161,172 ----
XX  }
XX  
XX  
XX! void getmove(board)			/* Get a player's move */
XX  int board[];
XX  {
XX    int Move;
XX+   int ItemsRead;
XX+   char dumc;
XX  
XX    do {
XX  	do {
XX***************
XX*** 161,168 ****
XX  #else
XX  		printw("Your move: ");	/* Prompt for move */
XX  #endif
XX  	}
XX! 	while (scanf("%d", &Move) != 1);	/* Input the move */
XX    }
XX    while (board[Move]);
XX    board[Move] = 4;		/* If legal, add to board */
XX--- 177,186 ----
XX  #else
XX  		printw("Your move: ");	/* Prompt for move */
XX  #endif
XX+ 		ItemsRead = scanf("%d", &Move);	/* Input the move */
XX+ 		if (ItemsRead == 0) scanf("%c", &dumc);	/* Remove the offending character */
XX  	}
XX! 	while (ItemsRead != 1);
XX    }
XX    while (board[Move]);
XX    board[Move] = 4;		/* If legal, add to board */
XX***************
XX*** 204,210 ****
XX  
XX  int randommove()
XX  {				/* Make an initial random move */
XX-   long time();			/* based on current time */
XX    int i;
XX  
XX    i = abs((int) time((long *) 0));
XX--- 222,227 ----
XX***************
XX*** 212,218 ****
XX  }
XX  
XX  
XX! main()
XX  {				/* The actual game */
XX    int i, board[9];
XX    char ch;
XX--- 229,235 ----
XX  }
XX  
XX  
XX! int main()
XX  {				/* The actual game */
XX    int i, board[9];
XX    char ch;
XX***************
XX*** 277,280 ****
XX--- 294,298 ----
XX  #ifdef CURSES
XX    endwin();
XX  #endif
XX+   return(0);
XX  }
X/
Xecho x - tty.c.d
Xsed '/^X/s///' > tty.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/tty.c  crc=34586    443	Sun Apr 25 21:35:25 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/tty.c  crc=08336    646	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,23 ****
XX  /* tty.c - Return tty name		Author: Freeman P. Pascal IV */
XX  
XX  #include <sys/types.h>
XX  #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    char *tty_name;
XX  
XX!   tty_name = ttyname(0);
XX    if ((argc == 2) && (!strcmp(argv[1], "-s")))
XX  	 /* Do nothing - shhh! we're in silent mode */ ;
XX    else
XX! 	puts((tty_name != (char *) NULL) ? tty_name : "Not a tty");
XX  
XX!   if (tty_name == (char *) NULL)
XX! 	exit(1);
XX    else
XX! 	exit(0);
XX  }
XX--- 1,30 ----
XX  /* tty.c - Return tty name		Author: Freeman P. Pascal IV */
XX  
XX+ /* Minor changes to make tty conform to POSIX1003.2 Draft10
XX+    Thomas Brupbacher (tobr@mw.lpc.ethz.ch)			*/
XX+ 
XX  #include <sys/types.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <unistd.h>
XX  #include <stdio.h>
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ 
XX  int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    char *tty_name;
XX  
XX!   tty_name = ttyname(STDIN_FILENO);
XX    if ((argc == 2) && (!strcmp(argv[1], "-s")))
XX  	 /* Do nothing - shhh! we're in silent mode */ ;
XX    else
XX! 	puts((tty_name != NULL) ? tty_name : "not a tty");
XX  
XX!   if (isatty(STDIN_FILENO) == 0)
XX! 	return(1);
XX    else
XX! 	return(0);
XX  }
X/
Xecho x - umount.c.d
Xsed '/^X/s///' > umount.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/umount.c  crc=00291   1160	Sun Apr 25 21:35:25 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/umount.c  crc=14176   1408	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,16 ****
XX  /* umount - unmount a file system		Author: Andy Tanenbaum */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <errno.h>
XX  
XX! #define BUFSIZE 1024
XX  
XX! extern int errno;
XX! char *mounttable = "/etc/mtab";
XX! char buffer[BUFSIZE], *p = &buffer[0], *q;
XX! 
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 1,23 ----
XX  /* umount - unmount a file system		Author: Andy Tanenbaum */
XX  
XX+ #define _MINIX 1		/* for proto of the non-POSIX umount() */
XX+ #define _POSIX_SOURCE 1		/* for PATH_MAX from limits.h */
XX+ 
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <errno.h>
XX+ #include <limits.h>
XX+ #include <minix/minlib.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void update_mtab, (char *devname));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 25,73 ****
XX    }
XX    std_err(argv[1]);
XX    std_err(" unmounted\n");
XX!   do_mtab(argv[1]);
XX!   exit(0);
XX  }
XX  
XX! do_mtab(devname)
XX  char *devname;
XX  {
XX! /* Remove an entry from mtab. */
XX!   int n, fd;
XX!   char line[256];
XX  
XX!   /* Read in the mount table and then overwrite the file. */
XX!   fd = open(mounttable, O_RDWR);
XX!   n = read(fd, buffer, BUFSIZE);
XX!   close(fd);
XX!   q = &buffer[n];
XX!   fd = creat(mounttable, 0554);
XX! 
XX!   n = strlen(devname);
XX!   while (getline(line) != 0) {
XX! 	if (strncmp(line, devname, n) == 0) continue;
XX! 	write(fd, line, strlen(line));
XX    }
XX! }
XX! 
XX! int getline(ptr)
XX! char *ptr;
XX! {
XX!   char c;
XX! 
XX!   while (p < q) {
XX! 	c = *p++;
XX! 	*ptr++ = c;
XX! 	if (c == '\n') {
XX! 		*ptr++ = 0;
XX! 		return(1);
XX! 	}
XX    }
XX!   return(0);
XX  }
XX  
XX! 
XX! usage()
XX  {
XX    std_err("Usage: umount special\n");
XX    exit(1);
XX--- 32,66 ----
XX    }
XX    std_err(argv[1]);
XX    std_err(" unmounted\n");
XX!   update_mtab(argv[1]);
XX!   return(0);
XX  }
XX  
XX! void update_mtab(devname)
XX  char *devname;
XX  {
XX! /* Remove an entry from /etc/mtab. */
XX!   int n;
XX!   char special[PATH_MAX+1], mounted_on[PATH_MAX+1], version[10], rw_flag[10];
XX  
XX!   if (load_mtab("umount") < 0) {
XX! 	std_err("/etc/mtab not updated.\n");
XX! 	exit(1);
XX    }
XX!   while (1) {
XX! 	n = get_mtab_entry(special, mounted_on, version, rw_flag);
XX! 	if (n < 0) break;
XX! 	if (strcmp(devname, special) == 0) continue;
XX! 	(void) put_mtab_entry(special, mounted_on, version, rw_flag);
XX    }
XX!   n = rewrite_mtab("umount");
XX!   if (n < 0) {
XX! 	std_err("/etc/mtab not updated.\n");
XX! 	exit(1);
XX!   }
XX  }
XX  
XX! void usage()
XX  {
XX    std_err("Usage: umount special\n");
XX    exit(1);
X/
Xecho x - unexpand.c.d
Xsed '/^X/s///' > unexpand.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/unexpand.c  crc=03292   2102	Sun Apr 25 21:35:25 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/unexpand.c  crc=47878   2247	Wed Nov  4 04:19:22 1992
XX***************
XX*** 2,7 ****
XX--- 2,9 ----
XX  
XX  /*  Usage:  unexpand  [ -a ]  [ file ... ]  */
XX  
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  #define  TAB   8
XX***************
XX*** 12,18 ****
XX  int leading_blank = 1;		/* Only unexpand leading blanks,	    */
XX  /* Overruled by -a option	            */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  
XX--- 14,23 ----
XX  int leading_blank = 1;		/* Only unexpand leading blanks,	    */
XX  /* Overruled by -a option	            */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void Unexpand, (FILE *f, int all));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  
XX***************
XX*** 52,62 ****
XX  	--spaces;
XX    }
XX  
XX!   exit(0);
XX  }
XX  
XX! 
XX! Unexpand(f, all)
XX  FILE *f;
XX  int all;
XX  
XX--- 57,66 ----
XX  	--spaces;
XX    }
XX  
XX!   return(0);
XX  }
XX  
XX! void Unexpand(f, all)
XX  FILE *f;
XX  int all;
XX  
X/
Xecho x - uniq.c.d
Xsed '/^X/s///' > uniq.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/uniq.c  crc=48468   3250	Sun Apr 25 21:35:26 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/uniq.c  crc=30516   3586	Wed Nov  4 04:19:22 1992
XX***************
XX*** 11,21 ****
XX   */
XX  
XX  #define WRITE_ERROR 1
XX! #define isdigit(c) (c >= '0' && c <= '9')
XX  #include <errno.h>
XX  #include <stdio.h>
XX  
XX- FILE *fopen();
XX  char buffer[BUFSIZ];
XX  int uflag = 1;			/* default is union of -d and -u outputs */
XX  int dflag = 1;			/* flags are mutually exclusive */
XX--- 11,22 ----
XX   */
XX  
XX  #define WRITE_ERROR 1
XX! #include <ctype.h>
XX  #include <errno.h>
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  char buffer[BUFSIZ];
XX  int uflag = 1;			/* default is union of -d and -u outputs */
XX  int dflag = 1;			/* flags are mutually exclusive */
XX***************
XX*** 23,34 ****
XX  int fields = 0;
XX  int chars = 0;
XX  
XX  FILE *xfopen(fn, mode)
XX  char *fn, *mode;
XX  {
XX    FILE *p;
XX-   extern int errno;
XX-   extern char *sys_errlist[];
XX  
XX    if ((p = fopen(fn, mode)) == NULL) {
XX  	perror("uniq");
XX--- 24,42 ----
XX  int fields = 0;
XX  int chars = 0;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(FILE *xfopen, (char *fn, char *mode));
XX+ _PROTOTYPE(char *skip, (char *s));
XX+ _PROTOTYPE(int equal, (char *s1, char *s2));
XX+ _PROTOTYPE(void show, (char *line, int count));
XX+ _PROTOTYPE(int uniq, (void));
XX+ _PROTOTYPE(void usage, (void));
XX+ _PROTOTYPE(int getline, (char *buf, int count));
XX+ 
XX  FILE *xfopen(fn, mode)
XX  char *fn, *mode;
XX  {
XX    FILE *p;
XX  
XX    if ((p = fopen(fn, mode)) == NULL) {
XX  	perror("uniq");
XX***************
XX*** 38,44 ****
XX    return(p);
XX  }
XX  
XX! main(argc, argv)
XX  char *argv[];
XX  {
XX    char *p;
XX--- 46,53 ----
XX    return(p);
XX  }
XX  
XX! int main(argc, argv)
XX! int argc;
XX  char *argv[];
XX  {
XX    char *p;
XX***************
XX*** 88,94 ****
XX  
XX    uniq();
XX    fflush(stdout);
XX!   exit(0);
XX  }
XX  
XX  char *skip(s)
XX--- 97,103 ----
XX  
XX    uniq();
XX    fflush(stdout);
XX!   return(0);
XX  }
XX  
XX  char *skip(s)
XX***************
XX*** 119,127 ****
XX    return !strcmp(skip(s1), skip(s2));
XX  }
XX  
XX! 
XX! show(line, count)
XX  char *line;
XX  {
XX    if (cflag)
XX  	printf("%4d %s", count, line);
XX--- 128,136 ----
XX    return !strcmp(skip(s1), skip(s2));
XX  }
XX  
XX! void show(line, count)
XX  char *line;
XX+ int count;
XX  {
XX    if (cflag)
XX  	printf("%4d %s", count, line);
XX***************
XX*** 134,140 ****
XX  /* The meat of the whole affair */
XX  char *nowline, *prevline, buf1[1024], buf2[1024];
XX  
XX! uniq()
XX  {
XX    char *p;
XX    int seen;
XX--- 143,149 ----
XX  /* The meat of the whole affair */
XX  char *nowline, *prevline, buf1[1024], buf2[1024];
XX  
XX! int uniq()
XX  {
XX    char *p;
XX    int seen;
XX***************
XX*** 161,171 ****
XX    return 0;
XX  }
XX  
XX! usage()
XX  {
XX!   std_err("Usage: uniq [-udc] [+n] [-n] [input [output]]\n");
XX  }
XX- 
XX  
XX  int getline(buf, count)
XX  char *buf;
XX--- 170,179 ----
XX    return 0;
XX  }
XX  
XX! void usage()
XX  {
XX!   fprintf(stderr, "Usage: uniq [-udc] [+n] [-n] [input [output]]\n");
XX  }
XX  
XX  int getline(buf, count)
XX  char *buf;
X/
Xecho x - unshar.c.d
Xsed '/^X/s///' > unshar.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/unshar.c  crc=19518   7468	Sun Apr 25 21:35:26 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/unshar.c  crc=50877   8264	Fri Jan  8 22:11:17 1993
XX***************
XX*** 1,16 ****
XX  /* unshar - extract files from a shell archive	Author: Warren Toomey */
XX  
XX! 
XX! /* Unshar - extract files from shell archive
XX   *
XX!  * Written by Warren Toomey [wkt@csadfa.oz.au@munnari.oz@uunet.uu.net] You may
XX!  * freely copy or give away this source as long as this notice remains
XX!  * intact.
XX   *
XX!  * Definitions used by unshar
XX   */
XX  
XX! 
XX  #include <stdio.h>
XX  
XX  /* Methods of unsharing */
XX--- 1,22 ----
XX  /* unshar - extract files from a shell archive	Author: Warren Toomey */
XX  
XX! /* Copyright 1989 by Warren Toomey	wkt@cs.adfa.oz.au[@uunet.uu.net]
XX   *
XX!  * You may freely copy or distribute this code as long as this notice
XX!  * remains intact.
XX   *
XX!  * You may modify this code, as long as this notice remains intact, and
XX!  * you add another notice indicating that the code has been modified.
XX!  *
XX!  * You may NOT sell this code or in any way profit from this code without
XX!  * prior agreement from the author.
XX!  *
XX!  * Modified by Andy Tanenbaum, Nov. 1992
XX!  * Modified by Bruce Evans, Jan. 1993
XX   */
XX  
XX! #include <stdlib.h>
XX! #include <string.h>
XX  #include <stdio.h>
XX  
XX  /* Methods of unsharing */
XX***************
XX*** 25,103 ****
XX  #define NOX	0
XX  #define YESX	1
XX  
XX! /* Emulation types available */
XX  
XX! #define NUMTOKS    4		/* Must change NUMTOKS to equal the */
XX!  /* Define UNKNOWN  0 *//* number of emulation types */
XX  #define SED	   1
XX  #define GRES 	   2
XX  #define CAT	   3
XX  
XX  /* The list of emulation types. */
XX! static char *token[NUMTOKS]=
XX! {
XX!   "",
XX!   "sed",
XX!   "gres",
XX!   "cat"
XX! };
XX  
XX- 
XX- /* Misc. constants */
XX- #define BUFSIZE	512		/* Size of line buffer */
XX- 
XX  /* Global variables */
XX  int table;			/* Generate a table, or extract */
XX- int verbose;			/* Unshar verbosely - debugging */
XX  int numext;			/* Number of files to extract */
XX! int binfile;			/* Binary file - err indicator */
XX  char *exfile[100];		/* Files to extract */
XX  
XX  
XX! #define getline(x,y)	fgetline(stdin,x,y)
XX  
XX! int fgetline(zin, how, buf)	/* Get a line from a file */
XX  FILE *zin;
XX! int how;			/* Ignore leading whitespace if */
XX! char *buf;			/* how == NOWHITE */
XX  {
XX    int ch = 0;
XX  
XX    *buf = 0;			/* Null the buffer */
XX    if (how == NOWHITE) {		/* If skip any whitespace */
XX! 	while (((ch = fgetc(zin)) == ' ') || (ch == '\t'));
XX  	if (ch == EOF) return(EOF);	/* Returning EOF or 0 */
XX  	if (ch == '\n') return (0);
XX  	*buf++ = ch;		/* Put char in buffer */
XX    }
XX!   while ((ch = fgetc(zin)) != '\n') {	/* Now get the line */
XX  	if (ch == EOF) {
XX  		*buf = 0;
XX  		return(EOF);
XX  	}
XX! 	if (ch > 127) {
XX! 		binfile = 1;
XX! 		return(0);
XX  	}
XX! 	*buf++ = ch;
XX    }
XX  
XX    *buf = 0;			/* Finally null-terminate the buffer */
XX    return(0);			/* and return */
XX  }
XX  
XX! 
XX! 
XX! char *getstring(buf)		/* Get the next string from the buffer */
XX! char *buf;			/* ignoring any quotes */
XX  {
XX    char out[BUFSIZE];
XX    char *temp = out;
XX    char inquotes = 0, ok = 1;
XX    while ((*buf == ' ') || (*buf == '\t'))
XX  	buf++;			/* Skip whitespace */
XX  
XX-   if (verbose) printf("In getstring...\n");
XX    *temp = 0;
XX    while (ok) {			/* Parse line */
XX  	switch (*buf) {
XX--- 31,177 ----
XX  #define NOX	0
XX  #define YESX	1
XX  
XX! /* Misc. constants */
XX! #define BUFSIZE	512		/* Size of line buffer */
XX  
XX! /* Emulation types available */
XX! #define NUMTOKS    4		/* NUMTOKS must equal # of emulation types */
XX  #define SED	   1
XX  #define GRES 	   2
XX  #define CAT	   3
XX  
XX  /* The list of emulation types. */
XX! static char *token[NUMTOKS] = {"", "sed", "gres", "cat"};
XX  
XX  /* Global variables */
XX  int table;			/* Generate a table, or extract */
XX  int numext;			/* Number of files to extract */
XX! unsigned long nulchars;		/* # Nuls discarded from input */
XX! unsigned long overrunchars;	/* # Chars overruning line buffers */
XX  char *exfile[100];		/* Files to extract */
XX  
XX+ extern char *optarg;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(int fgetline, (FILE * zin, int how, char *buf, size_t max));
XX! _PROTOTYPE(char *getstring, (char *buf));
XX! _PROTOTYPE(int firstword, (char *buf));
XX! _PROTOTYPE(int mustget, (char *s1));
XX! _PROTOTYPE(void extract, (int how, char *file, char *end, char *lead));
XX! _PROTOTYPE(void getnames, (char *buf, char *file, char *word));
XX! _PROTOTYPE(void disembowel, (void));
XX! _PROTOTYPE(void usage, (void));
XX  
XX! int main(argc, argv)
XX! int argc;
XX! char *argv[];
XX! {
XX!   int i, c, first;
XX!   int method;			/* Method of unsharing */
XX! 
XX!   method = BRUTAL;		/* Only BRUTAL currently available */
XX!   table = 0;			/* Don't generate a table */
XX!   numext = 0;			/* Initially no files to extract */
XX! 
XX!   while ((c = getopt(argc, argv, "x:tbv")) != EOF) switch (c) {
XX! 	    case 't':
XX! 		table = 1;	/* Get the various options */
XX! 		break;
XX! 
XX! 	    case 'b':	method = BRUTAL;	break;
XX! 	    case 'x':
XX! 		exfile[numext] = (char *) malloc(strlen(optarg) + 1);
XX! 		strcpy(exfile[numext++], optarg);
XX! 		break;
XX! 
XX! 	    default:	usage();
XX! 	}
XX! 
XX!   if (argc == 1) {
XX! 	first = argc;		/* Find first file argument */
XX!   } else {
XX! 	for (first = 1; first < argc; first++)
XX! 		if (argv[first][0] != '-') break;
XX!   }
XX! 
XX!   if (first == argc) {		/* If no file argument use stdin only */
XX! 	switch (method) {
XX! 	    case BRUTAL:
XX! 		disembowel();	/* Unshar brutally! */
XX! 		break;
XX! 
XX! 	    default:
XX! 		fprintf(stderr, "unshar: Unknown method of unsharing\n");
XX! 		exit(1);
XX! 	}
XX!   } else {
XX! 	for (i = first; i < argc; i++) {	/* open stdio with every
XX! 						 * file */
XX! 		if (table) printf("%s:\n", argv[i]);
XX! 		if (freopen(argv[i], "r", stdin) != stdin) {
XX! 			perror("unshar");
XX! 			exit(1);
XX! 		}
XX! 		switch (method) {
XX! 		    case BRUTAL:
XX! 			disembowel();	/* Unshar brutally! */
XX! 			break;
XX! 
XX! 		    default:
XX! 			fprintf(stderr,"unshar: Unknown method of unsharing\n");
XX! 			exit(1);
XX! 		}
XX! 	}
XX!   }
XX!   return(0);
XX! }
XX! 
XX! int fgetline(zin, how, buf, max)
XX  FILE *zin;
XX! int how;			/* Ignore leading whitespace if how=NOWHITE */
XX! char *buf;
XX! size_t max;			/* Buffer size, must be >= 2 */
XX  {
XX+ /* Get a line from a file */
XX    int ch = 0;
XX+   char *limit = buf + max - 1;
XX  
XX    *buf = 0;			/* Null the buffer */
XX    if (how == NOWHITE) {		/* If skip any whitespace */
XX! 	while (((ch = getc(zin)) == ' ') || (ch == '\t'));
XX  	if (ch == EOF) return(EOF);	/* Returning EOF or 0 */
XX  	if (ch == '\n') return (0);
XX  	*buf++ = ch;		/* Put char in buffer */
XX    }
XX!   while ((ch = getc(zin)) != '\n') {	/* Now get the line */
XX  	if (ch == EOF) {
XX  		*buf = 0;
XX  		return(EOF);
XX  	}
XX! 	if (ch == 0) {
XX! 		nulchars++;
XX! 		continue;
XX  	}
XX! 	if (buf == limit)
XX! 		overrunchars++;
XX! 	else
XX! 		*buf++ = ch;
XX    }
XX  
XX    *buf = 0;			/* Finally null-terminate the buffer */
XX    return(0);			/* and return */
XX  }
XX  
XX! char *getstring(buf)
XX! char *buf;
XX  {
XX+ /* Get the next string from the buffer ignoring any quotes. */
XX    char out[BUFSIZE];
XX    char *temp = out;
XX    char inquotes = 0, ok = 1;
XX    while ((*buf == ' ') || (*buf == '\t'))
XX  	buf++;			/* Skip whitespace */
XX  
XX    *temp = 0;
XX    while (ok) {			/* Parse line */
XX  	switch (*buf) {
XX***************
XX*** 106,115 ****
XX  		buf++;
XX  		inquotes = !inquotes;	/* Toggle inquotes */
XX  		break;
XX  	    case 0:
XX  	    case '\n':		/* Stop on <, >, NULL */
XX  	    case '>':		/* \n, and sometimes */
XX! 	        case '<':	ok = 0;	break;	/* space & tab */
XX  	    case '\t':
XX  	    case ' ':
XX  		if (!inquotes) ok = 0;
XX--- 180,190 ----
XX  		buf++;
XX  		inquotes = !inquotes;	/* Toggle inquotes */
XX  		break;
XX+ 
XX  	    case 0:
XX  	    case '\n':		/* Stop on <, >, NULL */
XX  	    case '>':		/* \n, and sometimes */
XX! 	    case '<':	ok = 0;	break;	/* space & tab */
XX  	    case '\t':
XX  	    case ' ':
XX  		if (!inquotes) ok = 0;
XX***************
XX*** 118,136 ****
XX  			buf++;
XX  			break;
XX  		}
XX  	    default:
XX  		*temp++ = *buf++;	/* Copy chars :-) */
XX  	}
XX    }
XX    *temp = 0;
XX-   if (verbose) printf("Returning *%s*\n", out);
XX    return(out);
XX  }
XX  
XX! 
XX! int firstword(buf)			/* Return token value of first word */
XX! char *buf;			/* in the buffer. Assume no leading */
XX! {				/* whitespace in the buffer */
XX    int i;
XX  
XX    for (i = 1; i < NUMTOKS; i++)
XX--- 193,213 ----
XX  			buf++;
XX  			break;
XX  		}
XX+ 
XX  	    default:
XX  		*temp++ = *buf++;	/* Copy chars :-) */
XX  	}
XX    }
XX    *temp = 0;
XX    return(out);
XX  }
XX  
XX! int firstword(buf)
XX! char *buf;
XX! {
XX! /* Return token value of the first word in the buffer.  Assume no leading
XX!  * white space in the buffer.
XX!  */
XX    int i;
XX  
XX    for (i = 1; i < NUMTOKS; i++)
XX***************
XX*** 139,148 ****
XX    return(UNKNOWN);
XX  }
XX  
XX! 
XX! int mustget(s1)			/* Return 1 if s1 is in the list of  */
XX! char *s1;			/* files to extract. Return 0 if not */
XX  {
XX    int i;
XX  
XX    if (numext == 0) return(0);
XX--- 216,225 ----
XX    return(UNKNOWN);
XX  }
XX  
XX! int mustget(s1)
XX! char *s1;
XX  {
XX+ /* Return 1 if s1 is in he list of files to extract.  Else return 0. */
XX    int i;
XX  
XX    if (numext == 0) return(0);
XX***************
XX*** 151,200 ****
XX    return(0);
XX  }
XX  
XX! 
XX! void extract(how, file, end, lead)	/* Extract file, up until end word */
XX! int how;			/* If how==YESX, then ignore lead   */
XX! char *file;			/* character on every line */
XX  char *end;
XX! int lead;
XX  {
XX    FILE *zout;
XX    char line[BUFSIZE];
XX    char *temp;
XX!   int ch;
XX  
XX    zout = fopen(file, "w");	/* Open output file */
XX    if (zout == NULL) {
XX! 	perror("unshar1");
XX  	return;
XX    }
XX    while (1) {
XX! 	binfile = 0;
XX! 	ch = getline(WHITE, line);	/* Get a line of file */
XX  	temp = line;
XX! 	if (binfile || (ch == EOF)) {
XX  		fprintf(zout, "%s\n", line);
XX  		fclose(zout);
XX  		return;
XX  	}
XX- 	if ((how == YESX) && (*temp == lead)) temp++;	/* Skip any lead */
XX- 
XX  	if (strcmp(temp, end) == 0) {	/* If end word */
XX  		fclose(zout);	/* close the file */
XX  		return;
XX  	}
XX  	fprintf(zout, "%s\n", temp);
XX    }
XX  }
XX  
XX- 
XX  void getnames(buf, file, word)	/* Get the file & end word */
XX  char *buf, *file, *word;	/* from the buffer */
XX  {
XX    char *temp;
XX  
XX    temp = buf;
XX-   if (verbose) printf("Getnames: buf is %s\n", buf);
XX  
XX    while (*temp != 0) {		/* Scan along buffer */
XX  	switch (*temp) {	/* Get file or end word */
XX--- 228,277 ----
XX    return(0);
XX  }
XX  
XX! void extract(how, file, end, lead)
XX! int how;		/* If how==YESX, ignore 1st char on each line */
XX! char *file;
XX  char *end;
XX! char *lead;
XX  {
XX+ /* Extract file, up until end word */
XX    FILE *zout;
XX    char line[BUFSIZE];
XX    char *temp;
XX!   int ch, match;
XX!   size_t n;
XX  
XX+   n = strlen(lead);
XX    zout = fopen(file, "w");	/* Open output file */
XX    if (zout == NULL) {
XX! 	perror("unshar");
XX  	return;
XX    }
XX    while (1) {
XX! 	ch = fgetline(stdin, WHITE, line, sizeof line);
XX  	temp = line;
XX! 	if (ch == EOF) {
XX  		fprintf(zout, "%s\n", line);
XX  		fclose(zout);
XX  		return;
XX  	}
XX  	if (strcmp(temp, end) == 0) {	/* If end word */
XX  		fclose(zout);	/* close the file */
XX  		return;
XX  	}
XX+ 	match = strncmp(temp, lead, n);
XX+ 	if ((how == YESX) && (match == 0))
XX+ 		temp += n;	/* Skip any lead */
XX  	fprintf(zout, "%s\n", temp);
XX    }
XX  }
XX  
XX  void getnames(buf, file, word)	/* Get the file & end word */
XX  char *buf, *file, *word;	/* from the buffer */
XX  {
XX    char *temp;
XX  
XX    temp = buf;
XX  
XX    while (*temp != 0) {		/* Scan along buffer */
XX  	switch (*temp) {	/* Get file or end word */
XX***************
XX*** 205,339 ****
XX  		if (*(++temp) == '<') ++temp;	/* Skip 2nd < */
XX  		strcpy(word, getstring(temp));	/* Get next word */
XX  		break;
XX! 	    default:
XX! 		temp++;
XX  	}
XX    }
XX  }
XX  
XX- 
XX- 
XX  void disembowel()
XX  {				/* Unshar brutally! */
XX    char buf[BUFSIZE];		/* Line buffer */
XX    char file[BUFSIZE];		/* File name */
XX    char word[BUFSIZE];		/* Word buffer */
XX!   int ch, x;
XX  
XX!   if (verbose) printf("Entering disembowel\n");
XX!   x = 'X';			/* Leading X character */
XX    while (1) {
XX! 	binfile = 0;
XX! 	ch = getline(NOWHITE, buf);	/* Get a line from file */
XX! 	if (ch == EOF) return;
XX! 	if (binfile) continue;
XX! 
XX  	switch (firstword(buf)) {	/* Extract, depending on first word */
XX  	    case CAT:
XX- 		if (verbose) printf("About to do getnames\n");
XX  		getnames(buf, file, word);
XX  		if (table == 0) {
XX  			if ((numext == 0) || (mustget(file))) {
XX  				printf("unshar: Extracting  %s\n", file);
XX! 				if (verbose)
XX! 					printf("        stopping at %s\n", word);
XX! 				extract(NOX, file, word, x);
XX  			}
XX! 		} else
XX  			printf("  %s\n", file);
XX  		break;
XX  	    case GRES:
XX  	    case SED:
XX- 		if (verbose) printf("About to do getnames\n");
XX  		getnames(buf, file, word);
XX  		if (table == 0) {
XX  			if ((numext == 0) || (mustget(file))) {
XX  				printf("unshar: Extracting  %s\n", file);
XX! 				if (verbose)
XX! 					printf("        stopping at %s\n", word);
XX! 				extract(YESX, file, word, x);
XX  			}
XX! 		} else
XX  			printf("  %s\n", file);
XX  		break;
XX! 	    default:
XX! 		break;
XX  	}
XX    }
XX  }
XX  
XX! 
XX! 
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
XX-   exit(0);
XX- }
XX- 
XX- 
XX- main(argc, argv)
XX- int argc;
XX- char *argv[];
XX- {
XX-   extern int optind;
XX-   extern char *optarg;
XX-   int i, c, first;
XX- 
XX-   FILE *zin;			/* Dummy file descriptor */
XX-   int method;			/* Method of unsharing */
XX- 
XX-   method = BRUTAL;		/* Only BRUTAL currently available */
XX-   table = 0;			/* Don't generate a table */
XX-   verbose = 0;			/* Nor be very verbose */
XX-   numext = 0;			/* Initially no files to extract */
XX- 
XX- 
XX-   while ((c = getopt(argc, argv, "x:tbv")) != EOF) switch (c) {
XX- 	    case 't':
XX- 		table = 1;	/* Get the various options */
XX- 		break;
XX- 	        case 'b':	method = BRUTAL;	break;
XX- 	        case 'v':	verbose = 1;	break;
XX- 	    case 'x':
XX- 		exfile[numext] = (char *) malloc(strlen(optarg) + 1);
XX- 		strcpy(exfile[numext++], optarg);
XX- 		break;
XX- 	    default:
XX- 		usage();
XX- 	}
XX- 
XX-   if (argc == 1)
XX- 	first = argc;		/* Find first file argument */
XX-   else
XX- 	for (first = 1; first < argc; first++)
XX- 		if (argv[first][0] != '-') break;
XX- 
XX-   if (first == argc) {		/* If no file argument *//* use stdin only */
XX- 	switch (method) {
XX- 	    case BRUTAL:
XX- 		disembowel();	/* Unshar brutally! */
XX- 		break;
XX- 	    default:
XX- 		fprintf(stderr, "unshar: Unknown method of unsharing\n");
XX- 		exit(1);
XX- 	}
XX-   } else
XX- 	for (i = first; i < argc; i++) {	/* open stdio with every
XX- 						 * file */
XX- 		if (table) printf("%s:\n", argv[i]);
XX- 		fclose(stdin);
XX- 		if ((zin = fopen(argv[i], "r")) == NULL) {
XX- 			perror("unshar2");
XX- 			exit(1);
XX- 		}
XX- 		switch (method) {
XX- 		    case BRUTAL:
XX- 			disembowel();	/* Unshar brutally! */
XX- 			break;
XX- 		    default:
XX- 			fprintf(stderr, "unshar: Unknown method of unsharing\n");
XX- 			exit(1);
XX- 		}
XX- 	}
XX    exit(0);
XX  }
XX--- 282,362 ----
XX  		if (*(++temp) == '<') ++temp;	/* Skip 2nd < */
XX  		strcpy(word, getstring(temp));	/* Get next word */
XX  		break;
XX! 	    default:	temp++;
XX  	}
XX    }
XX  }
XX  
XX  void disembowel()
XX  {				/* Unshar brutally! */
XX    char buf[BUFSIZE];		/* Line buffer */
XX    char file[BUFSIZE];		/* File name */
XX    char word[BUFSIZE];		/* Word buffer */
XX!   char lead_string[BUFSIZE];	/* lead string */
XX!   char *p, *p1;
XX!   int ch;
XX  
XX!   overrunchars = nulchars = 0;
XX    while (1) {
XX! 	ch = fgetline(stdin, NOWHITE, buf, sizeof buf);
XX! 	if (ch == EOF) {
XX! 		if (nulchars + overrunchars != 0) fprintf(stderr,
XX! 				"unshar: Discarded %lu characters from input.  Output may be garbled\n",
XX! 				nulchars + overrunchars);
XX! 		return;
XX! 	}
XX  	switch (firstword(buf)) {	/* Extract, depending on first word */
XX  	    case CAT:
XX  		getnames(buf, file, word);
XX+ 
XX+ 		/* Find the leading string. */
XX+ 		p = buf;
XX+ 		while (*p != '/') p++;
XX+ 		p++;
XX+ 		if (*p == '^') p++;	/* ^ has no width */
XX+ 		p1 = p;
XX+ 		while (*p1 != '/') p1++;
XX+ 		strncpy(lead_string, p, (size_t) (p1 - p));
XX+ 
XX  		if (table == 0) {
XX  			if ((numext == 0) || (mustget(file))) {
XX  				printf("unshar: Extracting  %s\n", file);
XX! 				extract(NOX, file, word, lead_string);
XX  			}
XX! 		} else {
XX  			printf("  %s\n", file);
XX+ 		}
XX  		break;
XX+ 
XX  	    case GRES:
XX  	    case SED:
XX  		getnames(buf, file, word);
XX+ 
XX+ 		/* Find the leading string. */
XX+ 		p = buf;
XX+ 		while (*p != '/') p++;
XX+ 		p++;
XX+ 		if (*p == '^') p++;	/* ^ has no width */
XX+ 		p1 = p;
XX+ 		while (*p1 != '/') p1++;
XX+ 		strncpy(lead_string, p, (size_t) (p1 - p));
XX+ 
XX  		if (table == 0) {
XX  			if ((numext == 0) || (mustget(file))) {
XX  				printf("unshar: Extracting  %s\n", file);
XX! 				extract(YESX, file, word, lead_string);
XX  			}
XX! 		} else {
XX  			printf("  %s\n", file);
XX+ 		}
XX  		break;
XX! 	    default:	break;
XX  	}
XX    }
XX  }
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
XX    exit(0);
XX  }
X/
Xecho x - update.c.d
Xsed '/^X/s///' > update.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/update.c  crc=58561    576	Sun Apr 25 21:35:26 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/update.c  crc=15202    812	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,13 ****
XX  /* update - do sync periodically		Author: Andy Tanenbaum */
XX  
XX  #include <sys/types.h>
XX  #include <signal.h>
XX  
XX! main()
XX! {
XX!   int fd, buf[2];
XX  
XX! 
XX    /* Disable SIGTERM */
XX    signal(SIGTERM, SIG_IGN);
XX  
XX--- 1,16 ----
XX  /* update - do sync periodically		Author: Andy Tanenbaum */
XX  
XX+ #define _MINIX 1		/* for proto of the non-POSIX sync() */
XX+ 
XX  #include <sys/types.h>
XX+ #include <fcntl.h>
XX  #include <signal.h>
XX+ #include <unistd.h>
XX  
XX! _PROTOTYPE(int main, (void));
XX  
XX! int main()
XX! {
XX    /* Disable SIGTERM */
XX    signal(SIGTERM, SIG_IGN);
XX  
XX***************
XX*** 20,30 ****
XX    chdir("/");
XX  
XX    /* Open some files to hold their inodes in core. */
XX! /*open("/bin", 0);*/
XX! /*open("/lib", 0);*/
XX! /*open("/etc", 0);*/
XX! /*open("/tmp", 0);*/
XX! 
XX  
XX    /* Flush the cache every 30 seconds. */
XX    while (1) {
XX--- 23,35 ----
XX    chdir("/");
XX  
XX    /* Open some files to hold their inodes in core. */
XX! #if 0	/* No, don't open them since we often want to mount on them. */
XX!   open("/bin", O_RDONLY);
XX!   open("/etc", O_RDONLY);
XX!   open("/tmp", O_RDONLY);
XX!   open("/usr", O_RDONLY);
XX!   open("/user", O_RDONLY);
XX! #endif
XX  
XX    /* Flush the cache every 30 seconds. */
XX    while (1) {
X/
Xecho x - users.c.d
Xsed '/^X/s///' > users.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/users.c  crc=46970   2261	Sun Apr 25 21:35:26 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/users.c  crc=33933   2472	Wed Nov  4 04:19:22 1992
XX***************
XX*** 10,15 ****
XX--- 10,17 ----
XX  
XX  #include <sys/types.h>
XX  #include <utmp.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  #ifndef  WTMP
XX***************
XX*** 23,30 ****
XX  
XX  struct utmp wtmp_buffer[MAX_WTMP_COUNT];
XX  
XX  
XX! main()
XX  {
XX    FILE *f;
XX    long size;			/* Number of wtmp records in the file	 */
XX--- 25,35 ----
XX  
XX  struct utmp wtmp_buffer[MAX_WTMP_COUNT];
XX  
XX+ _PROTOTYPE(int main, (void));
XX+ _PROTOTYPE(int Strncmp, (const void *str1,const void *str2));
XX+ _PROTOTYPE(void Print_Users, (int user_count, char users[10][8]));
XX  
XX! int main()
XX  {
XX    FILE *f;
XX    long size;			/* Number of wtmp records in the file	 */
XX***************
XX*** 48,54 ****
XX  	wtmp_count = (int) min(size, MAX_WTMP_COUNT);
XX  	size -= (long) wtmp_count;
XX  	fseek(f, size * sizeof(struct utmp), 0);
XX! 	if (fread(&wtmp_buffer[0], sizeof(struct utmp), wtmp_count, f) !=
XX  	    wtmp_count) {
XX  		fprintf(stderr, "users: read error on wtmp file\n");
XX  		exit(1);
XX--- 53,59 ----
XX  	wtmp_count = (int) min(size, MAX_WTMP_COUNT);
XX  	size -= (long) wtmp_count;
XX  	fseek(f, size * sizeof(struct utmp), 0);
XX! 	if (fread(&wtmp_buffer[0], sizeof(struct utmp), (size_t)wtmp_count, f) !=
XX  	    wtmp_count) {
XX  		fprintf(stderr, "users: read error on wtmp file\n");
XX  		exit(1);
XX***************
XX*** 68,74 ****
XX  		}
XX  		if (!(used & (1 << tty))) {
XX  			used |= 1 << tty;
XX! 			memcpy(users[user_count], wtmp_buffer[wtmp_count].ut_name, 8);
XX  
XX  			if (users[user_count][0] != '\0') ++user_count;
XX  		}
XX--- 73,79 ----
XX  		}
XX  		if (!(used & (1 << tty))) {
XX  			used |= 1 << tty;
XX! 			memcpy(users[user_count], wtmp_buffer[wtmp_count].ut_name, (size_t)8);
XX  
XX  			if (users[user_count][0] != '\0') ++user_count;
XX  		}
XX***************
XX*** 78,111 ****
XX  
XX    Print_Users(user_count, users);
XX  
XX!   exit(0);
XX  }
XX  
XX  
XX  
XX! Strncmp(str1, str2)
XX! char *str1;
XX! char *str2;
XX  
XX  {
XX!   return(strncmp(str1, str2, 8));
XX  }
XX  
XX  
XX  
XX! Print_Users(user_count, users)
XX  int user_count;
XX! char *users;
XX! 
XX  {
XX    int i;
XX  
XX!   qsort(users, user_count, 8, Strncmp);
XX  
XX!   for (i = 0; i < user_count - 1; ++i) {
XX! 	printf("%.8s ", users);
XX! 	users += 8;
XX    }
XX- 
XX-   if (user_count > 0) printf("%.8s\n", users);
XX  }
XX--- 83,112 ----
XX  
XX    Print_Users(user_count, users);
XX  
XX!   return(0);
XX  }
XX  
XX  
XX  
XX! int Strncmp(str1, str2)
XX! _CONST void *str1;
XX! _CONST void *str2;
XX  
XX  {
XX!   return(strncmp(str1, str2, (size_t)8));
XX  }
XX  
XX  
XX  
XX! void Print_Users(user_count, users)
XX  int user_count;
XX! char users[10][8];
XX  {
XX    int i;
XX  
XX!   qsort(users, (size_t)user_count, (size_t)8, Strncmp);
XX  
XX!   for (i = 0; i < user_count; i++) {
XX! 	printf("%.8s ", users[i]);
XX    }
XX  }
X/
Xecho x - uud.c.d
Xsed '/^X/s///' > uud.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/uud.c  crc=09916  11317	Sun Apr 25 21:35:27 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/uud.c  crc=07606  11991	Wed Nov  4 04:19:22 1992
XX***************
XX*** 26,31 ****
XX--- 26,37 ----
XX  #define SYSNAME "unix"
XX  #endif
XX  
XX+ #include <sys/types.h>
XX+ #include <stdarg.h>
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <sys/stat.h>
XX  #include <stdio.h>
XX  
XX  #ifdef GEMDOS
XX***************
XX*** 42,53 ****
XX  
XX  #define loop	while (1)
XX  
XX- extern FILE *fopen();
XX- extern char *strcpy();
XX- extern char *strcat();
XX- 
XX- char *getnword();
XX- 
XX  #define NCHARS  256
XX  #define LINELEN 256
XX  #define FILELEN 64
XX--- 48,53 ----
XX***************
XX*** 67,73 ****
XX  int debug = 0, nochk = 0, onedone = 0;
XX  int chtbl[NCHARS], cdlen[NORMLEN + 3];
XX  
XX! main(argc, argv) int argc; char *argv[];
XX  {
XX  	int mode;
XX  	register int i, j;
XX--- 67,83 ----
XX  int debug = 0, nochk = 0, onedone = 0;
XX  int chtbl[NCHARS], cdlen[NORMLEN + 3];
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(char *getnword, (char *str, int n));
XX! _PROTOTYPE(void gettable, (void));
XX! _PROTOTYPE(void decode, (void));
XX! _PROTOTYPE(void getfile, (char *buf));
XX! _PROTOTYPE(void format, (char *fp, ...));
XX! _PROTOTYPE(void doprnt, (char *fp, char *ap));
XX! _PROTOTYPE(void puti, (unsigned int i, unsigned int r));
XX! _PROTOTYPE(void outc, (int c));
XX! 
XX! int main(argc, argv) int argc; char *argv[];
XX  {
XX  	int mode;
XX  	register int i, j;
XX***************
XX*** 171,181 ****
XX  				}
XX  			}
XX  			numl++;
XX! 			if (strncmp(buf, "table", 5) == 0) {
XX  				gettable();
XX  				continue;
XX  			}
XX! 			if (strncmp(buf, "begin", 5) == 0) {
XX  				break;
XX  			}
XX  		}
XX--- 181,191 ----
XX  				}
XX  			}
XX  			numl++;
XX! 			if (strncmp(buf, "table", (size_t)5) == 0) {
XX  				gettable();
XX  				continue;
XX  			}
XX! 			if (strncmp(buf, "begin", (size_t)5) == 0) {
XX  				break;
XX  			}
XX  		}
XX***************
XX*** 237,243 ****
XX  /*
XX   * Install the table in memory for later use.
XX   */
XX! gettable()
XX  {
XX  	char buf[LINELEN];
XX  	register int c, n = 0;
XX--- 247,253 ----
XX  /*
XX   * Install the table in memory for later use.
XX   */
XX! void gettable()
XX  {
XX  	char buf[LINELEN];
XX  	register int c, n = 0;
XX***************
XX*** 250,256 ****
XX  		Error(5);
XX  	}
XX  	numl++;
XX! 	if (strncmp(buf, "begin", 5) == 0) {
XX  		format("uud: Incomplete translation table.\n");
XX  		Error(6);
XX  	}
XX--- 260,266 ----
XX  		Error(5);
XX  	}
XX  	numl++;
XX! 	if (strncmp(buf, "begin", (size_t)5) == 0) {
XX  		format("uud: Incomplete translation table.\n");
XX  		Error(6);
XX  	}
XX***************
XX*** 278,284 ****
XX   * copy from in to out, decoding as you go along.
XX   */
XX  
XX! decode()
XX  {
XX  	char buf[LINELEN], outl[LINELEN];
XX  	register char *bp, *ut;
XX--- 288,294 ----
XX   * copy from in to out, decoding as you go along.
XX   */
XX  
XX! void decode()
XX  {
XX  	char buf[LINELEN], outl[LINELEN];
XX  	register char *bp, *ut;
XX***************
XX*** 307,317 ****
XX  /*
XX   * end of uuencoded file ?
XX   */
XX! 		if (strncmp(buf, "end", 3) == 0) return;
XX  /*
XX   * end of current file ? : get next one.
XX   */
XX! 		if (strncmp(buf, "include", 7) == 0) {
XX  			getfile(buf);
XX  			continue;
XX  		}
XX--- 317,327 ----
XX  /*
XX   * end of uuencoded file ?
XX   */
XX! 		if (strncmp(buf, "end", (size_t)3) == 0) return;
XX  /*
XX   * end of current file ? : get next one.
XX   */
XX! 		if (strncmp(buf, "include", (size_t)7) == 0) {
XX  			getfile(buf);
XX  			continue;
XX  		}
XX***************
XX*** 402,408 ****
XX  			}
XX  			bp += 4;
XX  		}
XX! 		if ((n = fwrite(outl, 1, len, out)) <= 0) {
XX  			format("uud: Error on writing decoded file.\n");
XX  			Error(18);
XX  		}
XX--- 412,418 ----
XX  			}
XX  			bp += 4;
XX  		}
XX! 		if ((n = fwrite(outl, (size_t)1, (size_t)len, out)) <= 0) {
XX  			format("uud: Error on writing decoded file.\n");
XX  			Error(18);
XX  		}
XX***************
XX*** 413,419 ****
XX   * Find the next needed file, if existing, otherwise try further
XX   * on next file.
XX   */
XX! getfile(buf) register char *buf;
XX  {
XX  	if ((pos = getnword(buf, 2)) == NULL) {
XX  		format("uud: Missing include file name.\n");
XX--- 423,429 ----
XX   * Find the next needed file, if existing, otherwise try further
XX   * on next file.
XX   */
XX! void getfile(buf) register char *buf;
XX  {
XX  	if ((pos = getnword(buf, 2)) == NULL) {
XX  		format("uud: Missing include file name.\n");
XX***************
XX*** 451,461 ****
XX  			Error(12);
XX  		}
XX  		numl++;
XX! 		if (strncmp(buf, "table", 5) == 0) {
XX  			gettable();
XX  			continue;
XX  		}
XX! 		if (strncmp(buf, "begin", 5) == 0) break;
XX  	}
XX  	lens = strlen(buf);
XX  	if (lens) buf[--lens] = '\0';
XX--- 461,471 ----
XX  			Error(12);
XX  		}
XX  		numl++;
XX! 		if (strncmp(buf, "table", (size_t)5) == 0) {
XX  			gettable();
XX  			continue;
XX  		}
XX! 		if (strncmp(buf, "begin", (size_t)5) == 0) break;
XX  	}
XX  	lens = strlen(buf);
XX  	if (lens) buf[--lens] = '\0';
XX***************
XX*** 482,494 ****
XX   * Printf style formatting. (Borrowed from MicroEmacs by Dave Conroy.) 
XX   * A lot smaller than the full fledged printf.
XX   */
XX  /* VARARGS1 */
XX! format(fp, args) char *fp;
XX  {
XX  	doprnt(fp, (char *)&args);
XX  }
XX  
XX! doprnt(fp, ap)
XX  register char	*fp;
XX  register char	*ap;
XX  {
XX--- 492,515 ----
XX   * Printf style formatting. (Borrowed from MicroEmacs by Dave Conroy.) 
XX   * A lot smaller than the full fledged printf.
XX   */
XX+ #ifdef __STDC__
XX+ void format(char *fp, ...)
XX+ {
XX+   va_list args;
XX+ 
XX+   va_start (args, fp);
XX+   doprnt(fp, (char *)&args);
XX+   va_end(args);
XX+ }
XX+ #else
XX  /* VARARGS1 */
XX! void format(fp, args) char *fp;
XX  {
XX  	doprnt(fp, (char *)&args);
XX  }
XX+ #endif
XX  
XX! void doprnt(fp, ap)
XX  register char	*fp;
XX  register char	*ap;
XX  {
XX***************
XX*** 528,534 ****
XX  /*
XX   * Put integer, in radix "r".
XX   */
XX! puti(i, r)
XX  register unsigned int	i;
XX  register unsigned int	r;
XX  {
XX--- 549,555 ----
XX  /*
XX   * Put integer, in radix "r".
XX   */
XX! void puti(i, r)
XX  register unsigned int	i;
XX  register unsigned int	r;
XX  {
XX***************
XX*** 542,548 ****
XX  	else
XX  		outc(s - 10 + 'A');
XX  }
XX! outc(c) register char c;
XX  {
XX  #ifdef GEMDOS
XX  	if (c == '\n') Bconout(2, '\r');
XX--- 563,569 ----
XX  	else
XX  		outc(s - 10 + 'A');
XX  }
XX! void outc(c) register char c;
XX  {
XX  #ifdef GEMDOS
XX  	if (c == '\n') Bconout(2, '\r');
X/
Xecho x - uue.c.d
Xsed '/^X/s///' > uue.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/uue.c  crc=61630   4216	Sun Apr 25 21:35:27 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/uue.c  crc=35725   4499	Wed Nov  4 04:19:22 1992
XX***************
XX*** 20,25 ****
XX--- 20,27 ----
XX  
XX  
XX  #include <ctype.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX  #include <stdio.h>
XX  
XX  #define USAGE
XX***************
XX*** 28,34 ****
XX  /* ENC is the basic 1 character encoding function to make a char printing */
XX  #define ENC(c) (((c) & 077) + ' ')
XX  
XX- extern FILE *fopen();
XX  FILE *fp, *outp;
XX  char ofname[80];
XX  int lenofname;
XX--- 30,35 ----
XX***************
XX*** 48,54 ****
XX  int split = 0;
XX  int fileln = 32000;
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 49,62 ----
XX  int split = 0;
XX  int fileln = 32000;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void maketable, (void));
XX! _PROTOTYPE(void makename, (void));
XX! _PROTOTYPE(void encode, (void));
XX! _PROTOTYPE(void outdec, (char *p));
XX! _PROTOTYPE(int fr, (char *buf, int cnt));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 62,68 ****
XX  	fileln = -atoi(argv[1]);
XX  	if (fileln <= 0) {
XX  		fprintf(stderr, "Wrong file length arg.\n");
XX! 		exit();
XX  	}
XX  	split = 1;
XX  	argv++;
XX--- 70,76 ----
XX  	fileln = -atoi(argv[1]);
XX  	if (fileln <= 0) {
XX  		fprintf(stderr, "Wrong file length arg.\n");
XX! 		exit(3);
XX  	}
XX  	split = 1;
XX  	argv++;
XX***************
XX*** 97,109 ****
XX    encode();
XX    fprintf(outp, "end\n");
XX    fclose(outp);
XX!   exit(0);
XX  }
XX  
XX  /* Create ASCII table so a mailer can screw it up and the decode
XX   * program can restore the error.
XX   */
XX! maketable()
XX  {
XX    register int i, j;
XX  
XX--- 105,117 ----
XX    encode();
XX    fprintf(outp, "end\n");
XX    fclose(outp);
XX!   return(0);
XX  }
XX  
XX  /* Create ASCII table so a mailer can screw it up and the decode
XX   * program can restore the error.
XX   */
XX! void maketable()
XX  {
XX    register int i, j;
XX  
XX***************
XX*** 116,122 ****
XX  }
XX  
XX  /* Generate the names needed for single and multiple part encoding.  */
XX! makename()
XX  {
XX    if (split) {
XX  	ofname[lenofname - 1] = part;
XX--- 124,130 ----
XX  }
XX  
XX  /* Generate the names needed for single and multiple part encoding.  */
XX! void makename()
XX  {
XX    if (split) {
XX  	ofname[lenofname - 1] = part;
XX***************
XX*** 125,131 ****
XX  }
XX  
XX  /* Copy from in to out, encoding as you go along.  */
XX! encode()
XX  {
XX    char buf[80];
XX    register int i, n;
XX--- 133,139 ----
XX  }
XX  
XX  /* Copy from in to out, encoding as you go along.  */
XX! void encode()
XX  {
XX    char buf[80];
XX    register int i, n;
XX***************
XX*** 166,179 ****
XX  }
XX  
XX  /* Output one group of 3 bytes, pointed at by p, on file f.  */
XX! outdec(p)
XX  register char *p;
XX  {
XX    register int c1, c2, c3, c4;
XX  
XX    c1 = *p >> 2;
XX!   c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
XX!   c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
XX    c4 = p[2] & 077;
XX    putc(ENC(c1), outp);
XX    putc(ENC(c2), outp);
XX--- 174,187 ----
XX  }
XX  
XX  /* Output one group of 3 bytes, pointed at by p, on file f.  */
XX! void outdec(p)
XX  register char *p;
XX  {
XX    register int c1, c2, c3, c4;
XX  
XX    c1 = *p >> 2;
XX!   c2 = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
XX!   c3 = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
XX    c4 = p[2] & 077;
XX    putc(ENC(c1), outp);
XX    putc(ENC(c2), outp);
X/
Xecho x - vol.c.d
Xsed '/^X/s///' > vol.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/vol.c  crc=40098   3025	Sun Apr 25 21:35:27 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/vol.c  crc=04684   3044	Wed Nov  4 04:19:22 1992
XX***************
XX*** 18,30 ****
XX  #include <blocksize.h>
XX  #include <signal.h>
XX  #include <errno.h>
XX  
XX- extern int errno;
XX- extern char *itoa();
XX- 
XX  char buffer[BLOCK_SIZE];
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 18,35 ----
XX  #include <blocksize.h>
XX  #include <signal.h>
XX  #include <errno.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX  char buffer[BLOCK_SIZE];
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void diskio, (int size, int fd1, int fd2, char *errstr1,
XX! 			 char *errstr2));
XX! _PROTOTYPE(void message, (char *s1, char *s2));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 54,62 ****
XX  	fd = open(name, 1 - reading);
XX  	if (fd < 0) message("vol: cannot open %s\n", name);
XX  
XX! 	std_err("Please insert volume ");
XX! 	num(volume);
XX! 	std_err(" and hit return\n");
XX  	read(tty, buffer, BLOCK_SIZE);
XX  	volume++;
XX  
XX--- 59,65 ----
XX  	fd = open(name, 1 - reading);
XX  	if (fd < 0) message("vol: cannot open %s\n", name);
XX  
XX! 	fprintf(stderr, "\007Please insert volume %d and hit return\n",volume);
XX  	read(tty, buffer, BLOCK_SIZE);
XX  	volume++;
XX  
XX***************
XX*** 70,76 ****
XX    }
XX  }
XX  
XX! diskio(size, fd1, fd2, errstr1, errstr2)
XX  int size, fd1, fd2;
XX  char *errstr1, *errstr2;
XX  {
XX--- 73,79 ----
XX    }
XX  }
XX  
XX! void diskio(size, fd1, fd2, errstr1, errstr2)
XX  int size, fd1, fd2;
XX  char *errstr1, *errstr2;
XX  {
XX***************
XX*** 95,122 ****
XX    }
XX  }
XX  
XX! 
XX! 
XX! message(s1, s2)
XX  char *s1, *s2;
XX  {
XX    printf(s1, s2);
XX    exit(1);
XX- }
XX- 
XX- num(n)
XX- int n;
XX- {
XX-   char out[3];
XX- 
XX-   out[0] = ' ';
XX-   out[1] = '0';
XX-   out[2] = 0;
XX-   if (n < 10) {
XX- 	out[1] += n;
XX-   } else {
XX- 	out[1] += (n % 10);
XX- 	out[0] = '0' + (n / 10);
XX-   }
XX-   std_err(out);
XX  }
XX--- 98,106 ----
XX    }
XX  }
XX  
XX! void message(s1, s2)
XX  char *s1, *s2;
XX  {
XX    printf(s1, s2);
XX    exit(1);
XX  }
X/
Xecho x - wc.c.d
Xsed '/^X/s///' > wc.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/wc.c  crc=25702   2857	Sun Apr 25 21:35:28 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/wc.c  crc=10174   2945	Wed Nov  4 04:19:22 1992
XX***************
XX*** 1,7 ****
XX  /* wc - count lines, words and characters	Author: David Messer */
XX  
XX  #include <stdio.h>
XX- #define isspace(c) (c==' ' || c=='\t' || c=='\n' || c=='\f' || c=='\r')
XX  
XX  /*
XX   *
XX--- 1,8 ----
XX  /* wc - count lines, words and characters	Author: David Messer */
XX  
XX+ #include <ctype.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  /*
XX   *
XX***************
XX*** 38,51 ****
XX  long wtotal;			/* Total count of words */
XX  long ctotal;			/* Total count of characters */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int k;
XX    char *cp;
XX    int tflag, files;
XX-   int i;
XX  
XX    /* Get flags. */
XX    files = argc - 1;
XX--- 39,55 ----
XX  long wtotal;			/* Total count of words */
XX  long ctotal;			/* Total count of characters */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void count, (FILE *f));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX    int k;
XX    char *cp;
XX    int tflag, files;
XX  
XX    /* Get flags. */
XX    files = argc - 1;
XX***************
XX*** 90,96 ****
XX    while (k < argc) {
XX  	FILE *f;
XX  
XX! 	if ((f = fopen(argv[k], "r")) == (FILE *) NULL) {
XX  		fprintf(stderr, "wc: cannot open %s\n", argv[k]);
XX  	} else {
XX  		count(f);
XX--- 94,100 ----
XX    while (k < argc) {
XX  	FILE *f;
XX  
XX! 	if ((f = fopen(argv[k], "r")) == NULL) {
XX  		fprintf(stderr, "wc: cannot open %s\n", argv[k]);
XX  	} else {
XX  		count(f);
XX***************
XX*** 110,119 ****
XX  	printf(" total\n");
XX    }
XX    fflush(stdout);
XX!   exit(0);
XX  }
XX  
XX! count(f)
XX  FILE *f;
XX  {
XX    register int c;
XX--- 114,123 ----
XX  	printf(" total\n");
XX    }
XX    fflush(stdout);
XX!   return(0);
XX  }
XX  
XX! void count(f)
XX  FILE *f;
XX  {
XX    register int c;
XX***************
XX*** 140,147 ****
XX    ctotal += ccount;
XX  }
XX  
XX! usage()
XX  {
XX!   std_err("Usage: wc [-lwc] [name ...]\n");
XX    exit(1);
XX  }
XX--- 144,151 ----
XX    ctotal += ccount;
XX  }
XX  
XX! void usage()
XX  {
XX!   fprintf(stderr, "Usage: wc [-lwc] [name ...]\n");
XX    exit(1);
XX  }
X/
Xecho x - whatsnew.c.d
Xsed '/^X/s///' > whatsnew.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/whatsnew.c  crc=51566   6163	Sun Apr 25 21:35:28 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/whatsnew.c  crc=49569   6686	Wed Nov  4 04:19:22 1992
XX***************
XX*** 19,24 ****
XX--- 19,26 ----
XX   * ! or +.  Tabs are converted to spaces in the process.
XX   */
XX  
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define MAX_WIDTH       256	/* max line length */
XX***************
XX*** 29,41 ****
XX  #define DEF_WIDTH        80	/* default width */
XX  
XX  int cdif_found = 0;		/* set to 1 if cdif entry found */
XX! char *index[HEAP_LINES];	/* pointers into the heap */
XX  char heap[HEAP_BYTES];		/* the + and ! lines are saved here. */
XX  int lines_used;			/* number of index slots used */
XX  char *hp = heap;		/* pointer to end of the heap */
XX  int width = DEF_WIDTH;		/* how wide to print the listing */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 31,52 ----
XX  #define DEF_WIDTH        80	/* default width */
XX  
XX  int cdif_found = 0;		/* set to 1 if cdif entry found */
XX! char *indices[HEAP_LINES];	/* pointers into the heap */
XX  char heap[HEAP_BYTES];		/* the + and ! lines are saved here. */
XX  int lines_used;			/* number of index slots used */
XX  char *hp = heap;		/* pointer to end of the heap */
XX  int width = DEF_WIDTH;		/* how wide to print the listing */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void eat_cdif, (FILE *cdif, char *name));
XX! _PROTOTYPE(void read_and_print, (FILE *newf));
XX! _PROTOTYPE(int present, (char *line, char *name));
XX! _PROTOTYPE(void enter_line, (char *line));
XX! _PROTOTYPE(int hash, (char *p));
XX! _PROTOTYPE(void print_line, (char *line, int c));
XX! _PROTOTYPE(void usage, (void));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 76,96 ****
XX    eat_cdif(cdif, argv[k]);
XX  
XX    /* Read and print the new file. */
XX!   read_and_print(newf, width);
XX  
XX!   exit(0);
XX  }
XX  
XX! eat_cdif(cdif, name)
XX  FILE *cdif;
XX  char *name;
XX  {
XX!   int n;
XX!   char line[MAX_WIDTH], *p;
XX  
XX    /* First find the start of the relevant cdif stuff. */
XX    while (fgets(line, MAX_WIDTH, cdif) != NULL) {
XX! 	if (strncmp(line, "*** ", 4) != 0) continue;
XX  	if (present(line, name) && present(line, ":")) {
XX  		cdif_found = 1;
XX  		break;
XX--- 87,106 ----
XX    eat_cdif(cdif, argv[k]);
XX  
XX    /* Read and print the new file. */
XX!   read_and_print(newf);
XX  
XX!   return(0);
XX  }
XX  
XX! void eat_cdif(cdif, name)
XX  FILE *cdif;
XX  char *name;
XX  {
XX!   char line[MAX_WIDTH];
XX  
XX    /* First find the start of the relevant cdif stuff. */
XX    while (fgets(line, MAX_WIDTH, cdif) != NULL) {
XX! 	if (strncmp(line, "*** ", (size_t)4) != 0) continue;
XX  	if (present(line, name) && present(line, ":")) {
XX  		cdif_found = 1;
XX  		break;
XX***************
XX*** 103,109 ****
XX  
XX    /* We found it. Save all the ! and + lines in the hash table. */
XX    while (fgets(line, MAX_WIDTH, cdif) != NULL) {
XX! 	if (strcmp(line, "*** ", 4) == 0 && present(line, ":")) break;
XX  	if (line[0] != '+' && line[0] != '!') continue;
XX  	if (line[1] != ' ') continue;
XX  	enter_line(line);
XX--- 113,119 ----
XX  
XX    /* We found it. Save all the ! and + lines in the hash table. */
XX    while (fgets(line, MAX_WIDTH, cdif) != NULL) {
XX! 	if (strncmp(line, "*** ", (size_t)4) == 0 && present(line, ":")) break;
XX  	if (line[0] != '+' && line[0] != '!') continue;
XX  	if (line[1] != ' ') continue;
XX  	enter_line(line);
XX***************
XX*** 111,135 ****
XX  }
XX  
XX  
XX! read_and_print(newf)
XX  FILE *newf;
XX  {
XX    int h, hit;
XX!   char line[MAX_WIDTH], *p, c;
XX  
XX    /* Examine each line in the patched file. */
XX    while (fgets(line, MAX_WIDTH, newf) != NULL) {
XX  	/* Hash the line and see if it is in the table. */
XX  	hit = -1;
XX  	h = hash(line);
XX! 	while (index[h] != 0) {
XX! 		if (strcmp(line, index[h] + 2) == 0) {
XX  			hit = h;
XX  			break;
XX  		}
XX  		h = (h + 1) % HEAP_LINES;
XX  	}
XX! 	c = (hit >= 0 ? *(index[h]) : ' ');
XX  	print_line(line, c);
XX    }
XX  }
XX--- 121,145 ----
XX  }
XX  
XX  
XX! void read_and_print(newf)
XX  FILE *newf;
XX  {
XX    int h, hit;
XX!   char line[MAX_WIDTH], c;
XX  
XX    /* Examine each line in the patched file. */
XX    while (fgets(line, MAX_WIDTH, newf) != NULL) {
XX  	/* Hash the line and see if it is in the table. */
XX  	hit = -1;
XX  	h = hash(line);
XX! 	while (indices[h] != 0) {
XX! 		if (strcmp(line, indices[h] + 2) == 0) {
XX  			hit = h;
XX  			break;
XX  		}
XX  		h = (h + 1) % HEAP_LINES;
XX  	}
XX! 	c = (hit >= 0 ? *(indices[h]) : ' ');
XX  	print_line(line, c);
XX    }
XX  }
XX***************
XX*** 148,161 ****
XX    p = line;
XX    n = strlen(name);
XX    while (*p != 0) {
XX! 	if (strncmp(p, name, n) == 0) return(1);
XX  	p++;
XX    }
XX    return(0);
XX  }
XX  
XX  
XX! enter_line(line)
XX  char *line;
XX  {
XX  /* Enter a line in the hash table.  Note that the first two characters
XX--- 158,171 ----
XX    p = line;
XX    n = strlen(name);
XX    while (*p != 0) {
XX! 	if (strncmp(p, name, (size_t)n) == 0) return(1);
XX  	p++;
XX    }
XX    return(0);
XX  }
XX  
XX  
XX! void enter_line(line)
XX  char *line;
XX  {
XX  /* Enter a line in the hash table.  Note that the first two characters
XX***************
XX*** 167,182 ****
XX    /* Certain lines should not be entered as they occur often. */
XX    n = strlen(line) - 2;
XX    if (n == 1) return;		/* don't enter null lines */
XX!   if (strncmp(line, "+ /*==", 6) == 0) return;
XX!   if (strncmp(line, "+  *==", 6) == 0) return;
XX!   if (strncmp(line, "+   {", 5) == 0) return;
XX!   if (strncmp(line, "+   }", 5) == 0) return;
XX!   if (strncmp(line, "+ {", 3) == 0) return;
XX!   if (strncmp(line, "+ }", 3) == 0) return;
XX!   if (strncmp(line, "+ \t{", 4) == 0) return;
XX!   if (strncmp(line, "+ \t}", 4) == 0) return;
XX!   if (strncmp(line, "+ else", 6) == 0) return;
XX!   if (strncmp(line, "+ #end", 6) == 0) return;
XX  
XX    if (lines_used == HEAP_LINES) {
XX  	fprintf(stderr, "cdif listing has too many lines\n");
XX--- 177,192 ----
XX    /* Certain lines should not be entered as they occur often. */
XX    n = strlen(line) - 2;
XX    if (n == 1) return;		/* don't enter null lines */
XX!   if (strncmp(line, "+ /*==", (size_t)6) == 0) return;
XX!   if (strncmp(line, "+  *==", (size_t)6) == 0) return;
XX!   if (strncmp(line, "+   {", (size_t)5) == 0) return;
XX!   if (strncmp(line, "+   }", (size_t)5) == 0) return;
XX!   if (strncmp(line, "+ {", (size_t)3) == 0) return;
XX!   if (strncmp(line, "+ }", (size_t)3) == 0) return;
XX!   if (strncmp(line, "+ \t{", (size_t)4) == 0) return;
XX!   if (strncmp(line, "+ \t}", (size_t)4) == 0) return;
XX!   if (strncmp(line, "+ else", (size_t)6) == 0) return;
XX!   if (strncmp(line, "+ #end", (size_t)6) == 0) return;
XX  
XX    if (lines_used == HEAP_LINES) {
XX  	fprintf(stderr, "cdif listing has too many lines\n");
XX***************
XX*** 189,196 ****
XX  
XX    /* Make the heap entry. */
XX    h = hash(line + 2);
XX!   while (index[h] != 0) h = (h + 1) % HEAP_LINES;
XX!   index[h] = hp;		/* index table points to the lines */
XX    strcpy(hp, line);		/* first two chars also copied */
XX    lines_used++;			/* count # table slots used */
XX    hp += n + 3;			/* 0 byte counts also */
XX--- 199,206 ----
XX  
XX    /* Make the heap entry. */
XX    h = hash(line + 2);
XX!   while (indices[h] != 0) h = (h + 1) % HEAP_LINES;
XX!   indices[h] = hp;		/* indices table points to the lines */
XX    strcpy(hp, line);		/* first two chars also copied */
XX    lines_used++;			/* count # table slots used */
XX    hp += n + 3;			/* 0 byte counts also */
XX***************
XX*** 217,223 ****
XX  }
XX  
XX  
XX! print_line(line, c)
XX  char *line, c;
XX  {
XX  /* Print the line. */
XX--- 227,233 ----
XX  }
XX  
XX  
XX! void print_line(line, c)
XX  char *line, c;
XX  {
XX  /* Print the line. */
XX***************
XX*** 252,258 ****
XX  }
XX  
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: whatsnew [-<width>] file file.cdif\n");
XX    exit(1);
XX--- 262,268 ----
XX  }
XX  
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: whatsnew [-<width>] file file.cdif\n");
XX    exit(1);
X/
Xecho x - which.c.d
Xsed '/^X/s///' > which.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/which.c  crc=30706   1346	Sun Apr 25 21:35:28 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/which.c  crc=47484   1447	Wed Nov  4 04:19:22 1992
XX***************
XX*** 2,12 ****
XX--- 2,17 ----
XX  
XX  #define DELIMITER ':'
XX  
XX+ #include <sys/types.h>
XX  #include <stdlib.h>
XX  #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ 
XX  int main(ac, av)
XX+ int ac;
XX  char **av;
XX  {
XX    char *path, *cp;
XX***************
XX*** 74,78 ****
XX  		}
XX  	}
XX    }
XX!   exit(0);
XX  }
XX--- 79,83 ----
XX  		}
XX  	}
XX    }
XX!   return(0);
XX  }
X/
Xecho x - who.c.d
Xsed '/^X/s///' > who.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/who.c  crc=07289   2034	Sun Apr 25 21:35:28 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/who.c  crc=23404   2221	Wed Nov  4 04:19:23 1992
XX***************
XX*** 10,16 ****
XX   *		who <DEVICE>
XX   *		who am i
XX   *
XX!  * Version:	1.5	01/09/90
XX   *
XX   * Author:	Terrence W. Holm	June 1988
XX   *		revised for UTMP use	Feb 1989
XX--- 10,16 ----
XX   *		who <DEVICE>
XX   *		who am i
XX   *
XX!  * Version:	1.6	01/08/91
XX   *
XX   * Author:	Terrence W. Holm	June 1988
XX   *		revised for UTMP use	Feb 1989
XX***************
XX*** 18,34 ****
XX   *		Fred van Kempen, October 1989
XX   *		Fred van Kempen, December 1989
XX   *		Fred van Kempen, January 1990
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <time.h>
XX  #include <utmp.h>
XX  #include <stdio.h>
XX  
XX  static char *Version = "@(#) WHO 1.5 (01/09/90)";
XX  
XX! extern char *ttyname();
XX  
XX  void usage()
XX  {
XX--- 18,39 ----
XX   *		Fred van Kempen, October 1989
XX   *		Fred van Kempen, December 1989
XX   *		Fred van Kempen, January 1990
XX+  *		Sean A Goggin, 	January 1991 	Fixed "ACTIVE" time when TZ set
XX   */
XX  
XX  #include <sys/types.h>
XX  #include <fcntl.h>
XX  #include <time.h>
XX  #include <utmp.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  static char *Version = "@(#) WHO 1.5 (01/09/90)";
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void usage, (void));
XX  
XX  void usage()
XX  {
XX***************
XX*** 37,43 ****
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 42,48 ----
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 45,51 ****
XX    struct tm *tm;
XX    char *fmt = "%02.2d:%02.2d:%02.2d";
XX    char logstr[16], actstr[16];
XX!   char *arg, *sp;
XX    long login, active;
XX    int fd, size, found;
XX  
XX--- 50,56 ----
XX    struct tm *tm;
XX    char *fmt = "%02.2d:%02.2d:%02.2d";
XX    char logstr[16], actstr[16];
XX!   char *arg;
XX    long login, active;
XX    int fd, size, found;
XX  
XX***************
XX*** 71,77 ****
XX  	fprintf(stderr, "%s: user-accouting is not active.\n", argv[0]);
XX  	exit(0);
XX    }
XX!   while (read(fd, &entry, size) == size) {
XX  	if (entry.ut_type == USER_PROCESS) {
XX  		if (found == 0) {
XX  			found++;
XX--- 76,82 ----
XX  	fprintf(stderr, "%s: user-accouting is not active.\n", argv[0]);
XX  	exit(0);
XX    }
XX!   while (read(fd, (char *)&entry, size) == size) {
XX  	if (entry.ut_type == USER_PROCESS) {
XX  		if (found == 0) {
XX  			found++;
XX***************
XX*** 82,88 ****
XX  		sprintf(logstr, fmt, tm->tm_hour, tm->tm_min, tm->tm_sec);
XX  		time(&active);
XX  		active -= login;
XX! 		tm = localtime(&active);
XX  		sprintf(actstr, fmt, tm->tm_hour, tm->tm_min, tm->tm_sec);
XX  		printf("%-8.8s %-8.8s %-8.8s  %-8.8s  %d\n",
XX  		       entry.ut_name, entry.ut_line, logstr,
XX--- 87,93 ----
XX  		sprintf(logstr, fmt, tm->tm_hour, tm->tm_min, tm->tm_sec);
XX  		time(&active);
XX  		active -= login;
XX! 		tm = gmtime(&active);
XX  		sprintf(actstr, fmt, tm->tm_hour, tm->tm_min, tm->tm_sec);
XX  		printf("%-8.8s %-8.8s %-8.8s  %-8.8s  %d\n",
XX  		       entry.ut_name, entry.ut_line, logstr,
XX***************
XX*** 92,96 ****
XX    close(fd);
XX    if (found == 0) printf("No active users.\n");
XX  
XX!   exit(0);
XX  }
XX--- 97,101 ----
XX    close(fd);
XX    if (found == 0) printf("No active users.\n");
XX  
XX!   return(0);
XX  }
X/
Xecho x - whoami.c.d
Xsed '/^X/s///' > whoami.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/whoami.c  crc=38008    302	Sun Apr 25 21:35:29 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/whoami.c  crc=48748    351	Wed Nov  4 04:19:23 1992
XX***************
XX*** 2,17 ****
XX  
XX  #include <sys/types.h>
XX  #include <pwd.h>
XX  #include <stdio.h>
XX  
XX! struct passwd *getpwuid();
XX  
XX! main()
XX  {
XX    struct passwd *pw_entry;
XX  
XX    pw_entry = getpwuid(geteuid());
XX    if (pw_entry == NULL) exit(1);
XX    puts(pw_entry->pw_name);
XX!   exit(0);
XX  }
XX--- 2,19 ----
XX  
XX  #include <sys/types.h>
XX  #include <pwd.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX! _PROTOTYPE(int main, (void));
XX  
XX! int main()
XX  {
XX    struct passwd *pw_entry;
XX  
XX    pw_entry = getpwuid(geteuid());
XX    if (pw_entry == NULL) exit(1);
XX    puts(pw_entry->pw_name);
XX!   return(0);
XX  }
X/
Xecho x - width.c.d
Xsed '/^X/s///' > width.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/width.c  crc=11508   2766	Sun Apr 25 21:35:29 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/width.c  crc=21235   2971	Wed Nov  4 04:19:23 1992
XX***************
XX*** 12,23 ****
XX   *		width -20	# copy stdin to stdout and force to 20 cols
XX   */
XX  
XX  #include <stdio.h>
XX  
XX  #define MAX_WIDTH	1024	/* longest acceptable line */
XX  #define TAB_WIDTH          8	/* spacing between tab stops */
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 12,29 ----
XX   *		width -20	# copy stdin to stdout and force to 20 cols
XX   */
XX  
XX+ #include <stdlib.h>
XX  #include <stdio.h>
XX  
XX  #define MAX_WIDTH	1024	/* longest acceptable line */
XX  #define TAB_WIDTH          8	/* spacing between tab stops */
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv));
XX! _PROTOTYPE(void process, (FILE *in, FILE *out, int width));
XX! _PROTOTYPE(void cant_open, (char *program, char *file));
XX! _PROTOTYPE(void usage, (char *s));
XX! 
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 40,63 ****
XX  	process(stdin, stdout, width);
XX    } else if (argc == k + 1) {
XX  	/* For example: width file   or   width -30 file */
XX! 	if ((in = fopen(argv[k], "r")) == (FILE *) NULL)
XX  		cant_open(argv[0], argv[k]);
XX  	process(in, stdout, width);
XX    } else if (argc == k + 2) {
XX  	/* For example, width inf outf  or   width -30 inf outf */
XX! 	if ((in = fopen(argv[k], "r")) == (FILE *) NULL)
XX  		cant_open(argv[0], argv[k]);
XX! 	if ((out = fopen(argv[k + 1], "w")) == (FILE *) NULL)
XX  		cant_open(argv[0], argv[k]);
XX  	process(in, out, width);
XX    } else {
XX  	usage(argv[0]);
XX    }
XX!   exit(0);
XX  }
XX  
XX  
XX! process(in, out, width)
XX  FILE *in, *out;
XX  int width;
XX  {
XX--- 46,69 ----
XX  	process(stdin, stdout, width);
XX    } else if (argc == k + 1) {
XX  	/* For example: width file   or   width -30 file */
XX! 	if ((in = fopen(argv[k], "r")) == NULL)
XX  		cant_open(argv[0], argv[k]);
XX  	process(in, stdout, width);
XX    } else if (argc == k + 2) {
XX  	/* For example, width inf outf  or   width -30 inf outf */
XX! 	if ((in = fopen(argv[k], "r")) == NULL)
XX  		cant_open(argv[0], argv[k]);
XX! 	if ((out = fopen(argv[k + 1], "w")) == NULL)
XX  		cant_open(argv[0], argv[k]);
XX  	process(in, out, width);
XX    } else {
XX  	usage(argv[0]);
XX    }
XX!   return(0);
XX  }
XX  
XX  
XX! void process(in, out, width)
XX  FILE *in, *out;
XX  int width;
XX  {
XX***************
XX*** 67,73 ****
XX    register char *p, *q;
XX    char in_buf[MAX_WIDTH + 1], out_buf[MAX_WIDTH + 1];
XX  
XX!   while (fgets(in_buf, MAX_WIDTH, in) != (char *) NULL) {
XX  	/* This loop executed once for each line in the input file. */
XX  	p = in_buf;
XX  	q = out_buf;
XX--- 73,79 ----
XX    register char *p, *q;
XX    char in_buf[MAX_WIDTH + 1], out_buf[MAX_WIDTH + 1];
XX  
XX!   while (fgets(in_buf, MAX_WIDTH, in) != NULL) {
XX  	/* This loop executed once for each line in the input file. */
XX  	p = in_buf;
XX  	q = out_buf;
XX***************
XX*** 95,101 ****
XX  }
XX  
XX  
XX! cant_open(program, file)
XX  char *program;
XX  char *file;
XX  {
XX--- 101,107 ----
XX  }
XX  
XX  
XX! void cant_open(program, file)
XX  char *program;
XX  char *file;
XX  {
XX***************
XX*** 107,113 ****
XX  }
XX  
XX  
XX! usage(s)
XX  char *s;
XX  {
XX    fputs("Usage: ", stderr);
XX--- 113,119 ----
XX  }
XX  
XX  
XX! void usage(s)
XX  char *s;
XX  {
XX    fputs("Usage: ", stderr);
X/
Xecho x - write.c.d
Xsed '/^X/s///' > write.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/simple/write.c  crc=53747   5581	Sun Apr 25 21:35:29 1993
XX--- /home/top/ast/minix/1.6.25/commands/simple/write.c  crc=24238   5881	Wed Nov  4 07:51:32 1992
XX***************
XX*** 5,11 ****
XX   *  			-c Read & write one character at a time (cbreak mode)
XX   *			-v Verbose
XX   *
XX!  * Version:	1.5	01/09/90
XX   *
XX   * NOTES:	Write requires 1.4a (or higher) libraries,
XX   *		for getopt(), strchr().
XX--- 5,11 ----
XX   *  			-c Read & write one character at a time (cbreak mode)
XX   *			-v Verbose
XX   *
XX!  * Version:	1.6	10/24/92
XX   *
XX   * NOTES:	Write requires 1.4a (or higher) libraries,
XX   *		for getopt(), strchr().
XX***************
XX*** 19,45 ****
XX  #include <pwd.h>
XX  #include <sgtty.h>
XX  #include <signal.h>
XX  #include <string.h>
XX- #include <time.h>
XX- #include <utmp.h>
XX  #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  
XX- static char *Version = "@(#) WRITE 1.5 (01/09/90)";
XX- 
XX  int otty;			/* file desc of callee's terminal */
XX  short int cbreak = 0;		/* are we in CBREAK (-c) mode? */
XX  short int verbose = 0;		/* are we in VERBOSE (-v) mode? */
XX  short int writing = 0;		/* is there a connection? */
XX! char *user = NULL;		/* callee's user name */
XX! char *tty = NULL;		/* callee's terminal if given */
XX! char *ourtty = NULL;		/* our terminal name */
XX  struct sgttyb ttyold, ttynew;	/* our tty controlling structs */
XX  
XX! extern int getopt(), optind;	/* from getopt(3) */
XX! void intr();
XX  
XX  char *finduser()
XX  {
XX  /* Search the UTMP database for the user we want. */
XX--- 19,53 ----
XX  #include <pwd.h>
XX  #include <sgtty.h>
XX  #include <signal.h>
XX+ #include <stdlib.h>
XX  #include <string.h>
XX  #include <unistd.h>
XX+ #include <utmp.h>
XX+ #include <time.h>
XX  #include <stdio.h>
XX  
XX+ static char *Version = "@(#) WRITE 1.6 (10/24/92)";
XX  
XX  int otty;			/* file desc of callee's terminal */
XX  short int cbreak = 0;		/* are we in CBREAK (-c) mode? */
XX  short int verbose = 0;		/* are we in VERBOSE (-v) mode? */
XX  short int writing = 0;		/* is there a connection? */
XX! char *user = NULL;	/* callee's user name */
XX! char *tty = NULL;	/* callee's terminal if given */
XX! char *ourtty = NULL;	/* our terminal name */
XX  struct sgttyb ttyold, ttynew;	/* our tty controlling structs */
XX  
XX! extern int optind;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(char *finduser, (void));
XX+ _PROTOTYPE(void settty, (char *utty));
XX+ _PROTOTYPE(void sayhello, (void));
XX+ _PROTOTYPE(void escape, (char *cmd));
XX+ _PROTOTYPE(void writetty, (void));
XX+ _PROTOTYPE(void usage, (void));
XX+ _PROTOTYPE(void intr, (int dummy));
XX+ 
XX  char *finduser()
XX  {
XX  /* Search the UTMP database for the user we want. */
XX***************
XX*** 47,53 ****
XX    static char utmptty[16];
XX    struct utmp utmp;
XX    struct passwd *userptr;
XX-   char ourname[9];
XX    int utmpfd;
XX  
XX    ourtty = ttyname(0);
XX--- 55,60 ----
XX***************
XX*** 63,69 ****
XX  
XX    if ((utmpfd = open(UTMP, O_RDONLY)) < 0) {
XX  	fprintf(stderr, "Cannot open utmp file\n");
XX! 	return((char *) NULL);
XX    }
XX    utmptty[0] = '\0';
XX  
XX--- 70,76 ----
XX  
XX    if ((utmpfd = open(UTMP, O_RDONLY)) < 0) {
XX  	fprintf(stderr, "Cannot open utmp file\n");
XX! 	return(NULL);
XX    }
XX    utmptty[0] = '\0';
XX  
XX***************
XX*** 72,93 ****
XX     * caller specified, return that tty name. */
XX    while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
XX  	/* is this the user we are looking for? */
XX! 	if (strcmp(utmp.ut_name, user)) continue;
XX  
XX  	/* is he on the terminal we want to write to? */
XX! 	if (tty == NULL || strcmp(utmptty, tty)) {
XX! 		strcpy(utmptty, utmp.ut_line);
XX  		break;
XX  	}
XX    }
XX  
XX    if (utmptty[0] == '\0') {
XX  	fprintf(stderr, "%s is not logged on\n", user);
XX! 	return( (char *) NULL);
XX    }
XX    if (tty != NULL && strcmp(utmptty, tty)) {
XX  	fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
XX! 	return( (char *) NULL);
XX    }
XX    close(utmpfd);
XX  
XX--- 79,100 ----
XX     * caller specified, return that tty name. */
XX    while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
XX  	/* is this the user we are looking for? */
XX! 	if (strncmp(utmp.ut_name, user, sizeof(utmp.ut_name))) continue;
XX  
XX+ 	strcpy(utmptty, utmp.ut_line);
XX  	/* is he on the terminal we want to write to? */
XX! 	if (tty == NULL || !strcmp(utmptty, tty)) {
XX  		break;
XX  	}
XX    }
XX  
XX    if (utmptty[0] == '\0') {
XX  	fprintf(stderr, "%s is not logged on\n", user);
XX! 	return( NULL);
XX    }
XX    if (tty != NULL && strcmp(utmptty, tty)) {
XX  	fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
XX! 	return( NULL);
XX    }
XX    close(utmpfd);
XX  
XX***************
XX*** 204,210 ****
XX  }
XX  
XX  
XX! main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX--- 211,217 ----
XX  }
XX  
XX  
XX! int main(argc, argv)
XX  int argc;
XX  char *argv[];
XX  {
XX***************
XX*** 236,252 ****
XX  	usage();
XX  
XX    sp = finduser();		/* find which tty to write onto */
XX!   if (sp != NULL) {		/* did we find one? */
XX  	settty(sp);		/* setup our terminal */
XX  	sayhello();		/* print the initial message */
XX  	writetty();		/* the write loop */
XX  	ioctl(0, TIOCSETP, &ttyold);
XX  	exit(0);
XX    }
XX!   exit(-1);
XX  }
XX  
XX! void intr()
XX  {
XX  /* The interrupt key has been hit. exit cleanly. */
XX  
XX--- 243,260 ----
XX  	usage();
XX  
XX    sp = finduser();		/* find which tty to write onto */
XX!   if (sp != NULL) {	/* did we find one? */
XX  	settty(sp);		/* setup our terminal */
XX  	sayhello();		/* print the initial message */
XX  	writetty();		/* the write loop */
XX  	ioctl(0, TIOCSETP, &ttyold);
XX  	exit(0);
XX    }
XX!   return(-1);
XX  }
XX  
XX! void intr(dummy)
XX! int dummy;			/* to satisfy the prototype */
XX  {
XX  /* The interrupt key has been hit. exit cleanly. */
XX  
XX***************
XX*** 256,260 ****
XX    if (writing) write(otty, "\nEOT\n", 5);
XX    exit(0);
XX  }
XX- 
XX- 
XX--- 264,266 ----
X/
/
