[comp.os.minix] Turbo C diff's for Minix 1.2; here they are ! Part 6 of 9

evas@euraiv1.UUCP (Eelco van Asperen) (10/02/87)

Here is part 6 of 9:						Eelco van Asperen.

# This is a shar archive.  Extract with sh, not csh.
# This archive ends with exit, so do not worry about trailing junk.
# --------------------------- cut here --------------------------
PATH=/bin:/usr/bin
echo Extracting commands/ar.dif
sed 's/^X//' > commands/ar.dif << '+ END-OF-FILE 'commands/ar.dif
X244c244
X<   ar_fd = open_archive(argv[2], (show_fl || pr_fl) ? READ : APPEND);
X---
X>   ar_fd = open_archive(argv[2], (show_fl || pr_fl || ex_fl) ? READ : APPEND);
+ END-OF-FILE commands/ar.dif
chmod u=rw,g=r,o=r commands/ar.dif
set `sum commands/ar.dif`
sum=$1
case $sum in
12600)	:;;
*)	echo 'Bad sum in 'commands/ar.dif >&2
esac
echo Extracting commands/basename.dif
sed 's/^X//' > commands/basename.dif << '+ END-OF-FILE 'commands/basename.dif
X21,23c21,23
X<   if (d == NULL) 
X< 	d = argv[1]; 
X<   else        
X---
X>   if (d == NULL)
X> 	d = argv[1];
X>   else
X27c27
X< 	prints("%s \n",d);
X---
X> 	prints("%s\n",d);
X35,36c35
X<   prints("%s \n",c);
X< } 
X---
X> }
+ END-OF-FILE commands/basename.dif
chmod u=rw,g=r,o=r commands/basename.dif
set `sum commands/basename.dif`
sum=$1
case $sum in
12694)	:;;
*)	echo 'Bad sum in 'commands/basename.dif >&2
esac
echo Extracting commands/cal.c
sed 's/^X//' > commands/cal.c << '+ END-OF-FILE 'commands/cal.c
X/* cal - print a calendar		Author: Maritn Minow */
X
X#include "../include/stdio.h"
X
X#define do3months	domonth
X#define	IO_SUCCESS	0		/* Unix definitions		*/
X#define	IO_ERROR	1
X#define	EOS	0
X
X#define	ENTRY_SIZE	3		/* 3 bytes per value		*/
X#define DAYS_PER_WEEK	7		/* Sunday, etc.			*/
X#define	WEEKS_PER_MONTH	6		/* Max. weeks in a month	*/
X#define	MONTHS_PER_LINE	3		/* Three months across		*/
X#define	MONTH_SPACE	3		/* Between each month		*/
X
Xchar *badarg = {"Bad argument\n"};
Xchar *how = {"Usage: cal [month] year\n"};
X
X/*
X * calendar() stuffs data into layout[],
X * output() copies from layout[] to outline[], (then trims blanks).
X */
Xchar layout[MONTHS_PER_LINE][WEEKS_PER_MONTH][DAYS_PER_WEEK][ENTRY_SIZE];
Xchar outline[(MONTHS_PER_LINE * DAYS_PER_WEEK * ENTRY_SIZE)
X      + (MONTHS_PER_LINE * MONTH_SPACE)
X      + 1];
X
Xchar *weekday = " S  M Tu  W Th  F  S";
Xchar *monthname[] = {
X  "???",						/* No month 0	*/
X  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X};
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  register int month;
X  register int year;
X
X  register int arg1val;
X  int arg1len;
X  int arg2val;
X
X  if (argc <= 1) {
X  	usage(how);
X  } else {
X      arg1val = atoi(argv[1]);
X      arg1len = strlen(argv[1]);
X      if (argc == 2) {
X	/*
X	 * Only one argument, if small, it's a month.  If
X	 * large, it's a year.  Note:
X	 *	cal	0082	Year 0082
X	 *	cal	82	Year 0082
X	 */
X	if (arg1len <= 2 && arg1val <= 12)
X		do3months(year, arg1val);
X	else
X		doyear(arg1val);
X      } else {
X	/*
X	 * Two arguments, allow 1980 12 or 12 1980
X	 */
X	arg2val = atoi(argv[2]);
X	if (arg1len > 2)
X	    do3months(arg1val, arg2val);
X	else
X	    do3months(arg2val, arg1val);
X      }
X  }
X  exit(IO_SUCCESS);
X}
X
Xdoyear(year)
Xint year;
X/*
X * Print the calendar for an entire year.
X */
X{
X  register int month;
X
X  if (year < 1 || year > 9999) usage(badarg);
X  if (year < 100)
X	printf("\n\n\n                                 00%2d\n\n", year);
X  else
X	printf("\n\n\n%35d\n\n", year);
X  for (month = 1; month <= 12; month += MONTHS_PER_LINE) {
X      printf("%12s%23s%23s\n",
X	    monthname[month],
X	    monthname[month+1],
X	    monthname[month+2]);
X      printf("%s   %s   %s\n", weekday, weekday, weekday);
X      calendar(year, month+0, 0);
X      calendar(year, month+1, 1);
X      calendar(year, month+2, 2);
X      output(3);
X#if MONTHS_PER_LINE != 3
X      error, the above won't work  ' /* this last quote is to fool Turbo C's
X                                     *  simple builtin preprocessor
X                                     */
X#endif
X  }
X  printf("\n\n\n");
X}
X
Xdomonth(year, month)
Xint year;
Xint month;
X/*
X * Do one specific month -- note: no longer used
X */
X{
X  if (year < 1 || year > 9999) usage(badarg);
X  if (month <= 0 || month > 12) usage(badarg);
X  printf("%9s%5d\n\n%s\n", monthname[month], year, weekday);
X  calendar(year, month, 0);
X  output(1);
X  printf("\n\n");
X}
X
Xoutput(nmonths)
Xint nmonths;		/* Number of months to do	*/
X/*
X * Clean up and output the text.
X */
X{
X  register int week;
X  register int month;
X  register char *outp;
X  int i;
X  char tmpbuf[21], *p;
X
X  for (week = 0; week < WEEKS_PER_MONTH; week++) {
X      outp = outline;
X      for (month = 0; month < nmonths; month++) {
X	/*
X	 * The -1 in the following removes
X	 * the unwanted leading blank from
X	 * the entry for Sunday.
X	 */
X	p = &layout[month][week][0][1];
X	for (i=0; i<20; i++) tmpbuf[i] = *p++;
X	tmpbuf[20] = 0;
X	sprintf(outp, "%s   ", tmpbuf);
X	outp += (DAYS_PER_WEEK * ENTRY_SIZE) + MONTH_SPACE - 1;
X      }
X      while (outp > outline && outp[-1] == ' ')	outp--;
X      *outp = EOS;
X      puts(outline);
X  }
X}
X
Xcalendar(year, month, index)
Xint year;
Xint month;
Xint index;		/* Which of the three months		*/
X/*
X * Actually build the calendar for this month.
X */
X{
X  register char *tp;
X  int week;
X  register int wday;
X  register int today;
X
X  setmonth(year, month);
X  for (week = 0; week < WEEKS_PER_MONTH; week++) {
X      for (wday = 0; wday < DAYS_PER_WEEK; wday++) {
X	tp = &layout[index][week][wday][0];
X	*tp++ = ' ';
X	today = getdate(week, wday);
X	if (today <= 0) {
X	    *tp++ = ' ';
X	    *tp++ = ' ';
X	}
X	else if (today < 10) {
X	    *tp++ = ' ';
X	    *tp   = (today + '0');
X	}
X	else {
X	    *tp++ = (today / 10) + '0';
X	    *tp   = (today % 10) + '0';
X	}
X      }
X  }
X}
X
Xusage(s)
Xchar *s;
X{
X/* Fatal parameter error. */
X
X  fprintf(stderr, "%s", s);
X  exit(IO_ERROR);
X}
X
X/*
X * Calendar routines, intended for eventual porting to TeX
X *
X * date(year, month, week, wday)
X *	Returns the date on this week (0 is first, 5 last possible)
X *	and day of the week (Sunday == 0)
X *	Note: January is month 1.
X *
X * setmonth(year, month)
X *	Parameters are as above, sets getdate() for this month.
X *
X * int
X * getdate(week, wday)
X *	Parameters are as above, uses the data set by setmonth()
X */
X
X/*
X * This structure is used to pass data between setmonth() and getdate().
X * It needs considerable expansion if the Julian->Gregorian change is
X * to be extended to other countries.
X */
X
Xstatic struct {
X    int this_month;	/* month number used in 1752 checking	*/
X    int feb;		/* Days in February for this month	*/
X    int sept;		/* Days in September for this month	*/
X    int days_in_month;	/* Number of days in this month		*/
X    int dow_first;	/* Day of week of the 1st day in month	*/
X} info;
X
Xstatic int day_month[] = {	/* 30 days hath September...		*/
X  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X};
X
Xint
Xdate(year, month, week, wday)
Xint year;		/* Calendar date being computed		*/
Xint month;		/* January == 1				*/
Xint week;		/* Week in the month 0..5 inclusive	*/
Xint wday;		/* Weekday, Sunday == 0			*/
X/*
X * Return the date of the month that fell on this week and weekday.
X * Return zero if it's out of range.
X */
X{
X  setmonth(year, month);
X  return (getdate(week, wday));
X}
X
Xsetmonth(year, month)
Xint year;			/* Year to compute		*/
Xint month;			/* Month, January is month 1	*/
X/*
X * Setup the parameters needed to compute this month
X * (stored in the info structure).
X */
X{
X  register int i;
X
X  if (month < 1 || month > 12) {	/* Verify caller's parameters	*/
X      info.days_in_month = 0;	/* Garbage flag			*/
X      return;
X  }
X  info.this_month = month;	/* used in 1752	checking	*/
X  info.dow_first = Jan1(year);	/* Day of January 1st for now	*/
X  info.feb = 29;			/* Assume leap year		*/
X  info.sept = 30;			/* Assume normal year		*/
X  /*
X   * Determine whether it's an ordinary year, a leap year
X   * or the magical calendar switch year of 1752.
X   */
X  switch ((Jan1(year + 1) + 7 - info.dow_first) % 7) {
X  case 1:				/* Not a leap year		*/
X      info.feb = 28;
X  case 2:				/* Ordinary leap year		*/
X      break;
X
X  default:			/* The magical moment arrives	*/
X      info.sept = 19;		/* 19 days hath September	*/
X      break;
X  }
X  info.days_in_month =
X        (month == 2) ? info.feb
X      : (month == 9) ? info.sept
X      : day_month[month];
X  for (i = 1; i < month; i++) {
X      switch (i) {		/* Special months?		*/
X      case 2:			/* February			*/
X	info.dow_first += info.feb;
X	break;
X
X      case 9:
X	info.dow_first += info.sept;
X	break;
X
X      default:
X	info.dow_first += day_month[i];
X	break;
X      }
X  }
X  info.dow_first %= 7;		/* Now it's Sunday to Saturday	*/
X}
X
Xint getdate(week, wday)
Xint week;
Xint wday;
X{
X  register int today;
X
X  /*
X   * Get a first guess at today's date and make sure it's in range.
X   */
X  today = (week * 7) + wday - info.dow_first + 1;
X  if (today <= 0 || today > info.days_in_month)
X      return (0);
X  else if (info.sept == 19 && info.this_month == 9
X	&& today >= 3)		/* The magical month?	*/
X      return (today + 11);	/* If so, some dates changed	*/
X  else				/* Otherwise,			*/
X      return (today);		/* Return the date		*/
X}
X
Xstatic int Jan1(year)
Xint year;
X/*
X * Return day of the week for Jan 1 of the specified year.
X */
X{
X  register int day;
X
X  day = year + 4 + ((year + 3) / 4);	/* Julian Calendar	*/
X  if (year > 1800) {			/* If it's recent, do	*/
X      day -= ((year - 1701) / 100);	/* Clavian correction	*/
X      day += ((year - 1601) / 400);	/* Gregorian correction	*/
X  }
X  if (year > 1752)			/* Adjust for Gregorian	*/
X      day += 3;				/* calendar		*/
X  return (day % 7);
X}
X
+ END-OF-FILE commands/cal.c
chmod u=rw,g=r,o=r commands/cal.c
set `sum commands/cal.c`
sum=$1
case $sum in
16624)	:;;
*)	echo 'Bad sum in 'commands/cal.c >&2
esac
echo Extracting commands/cat.dif
sed 's/^X//' > commands/cat.dif << '+ END-OF-FILE 'commands/cat.dif
X86c86
X< 	if (write(1, buffer, next - buffer) <= 0) quit();
X---
X> 	if (write(1, buffer, (int) (next - buffer)) <= 0) quit();
+ END-OF-FILE commands/cat.dif
chmod u=rw,g=r,o=r commands/cat.dif
set `sum commands/cat.dif`
sum=$1
case $sum in
8897)	:;;
*)	echo 'Bad sum in 'commands/cat.dif >&2
esac
echo Extracting commands/chmem.dif
sed 's/^X//' > commands/chmem.dif << '+ END-OF-FILE 'commands/chmem.dif
X1c1,18
X< /* chmem - set total memory size for execution	Author: Andy Tanenbaum */
X---
X> /* chmem - set total memory size for execution	   Author: Andy Tanenbaum */
X> 
X> /* modified for use with Turbo C under DOS by Eelco van Asperen, 87/08/26
X> *
X> * Changes made involve the use of unsigned long's rather than long's and
X> * unsigned int's; and the mode-parameter for open() has to include O_BINARY
X> * for Turbo C.
X> */
X> 
X> #ifdef DOS
X> # include <fcntl.h>
X> # include <stdlib.h>
X> 
X> # define  RWMODE   (O_RDWR|O_BINARY)	
X> #else
X> # define  RWMODE   (2)
X> #endif
X> 
X9c26,34
X< #define SEPBIT   0x00200000	/* this bit is set for separate I/D */
X---
X> 
X> #ifdef DOS
X> # define SEPBIT 0x00200000L	  /* this bit is set for separate I/D */
X> # define MAXPARAM   65520lu   /* maximum for parameter */
X> #else
X> # define SEPBIT  0x00200000	  /* this bit is set for separate I/D */
X> # define MAXPARAM     65520   /* maximum for parameter */
X> #endif
X> 
X28,32c53,60
X< 
X<   char *p;
X<   unsigned int n;
X<   int fd, separate;
X<   long lsize, olddynam, newdynam, newtot, overflow, header[HLONG];
X---
X>   char *p;
X>   int fd, separate;
X> #ifdef DOS
X>   unsigned long lsize, olddynam, newdynam, newtot, overflow, header[HLONG];
X> #else
X>   unsigned int n;
X>   long lsize, olddynam, newdynam, newtot, overflow, header[HLONG];
X> #endif
X37,41c65,73
X<   n = atoi(p+1);
X<   lsize = n;
X<   if (n > 65520) stderr3("chmem: ", p+1, " too large\n");
X< 
X<   fd = open(argv[2], 2);
X---
X> #ifdef DOS
X>   lsize = (unsigned long) atol(p+1);
X> #else
X>   n = atoi(p+1);
X>   lsize = n;
X> #endif
X>   if (lsize > MAXPARAM) stderr3("chmem: ", p+1, " too large\n");
X> 
X>   fd = open(argv[2], RWMODE);
X63,64c95,103
X<   printf("%s: Stack+malloc area changed from %D to %D bytes.\n",
X< 			 argv[2],  olddynam, newdynam);
X---
X> 
X> #ifdef DOS
X>   printf("%s: Stack+malloc area changed from %lu to %lu bytes.\n",
X> 			 argv[2],  olddynam, newdynam);
X> #else
X>   printf("%s: Stack+malloc area changed from %D to %D bytes.\n",
X> 			 argv[2],  olddynam, newdynam);
X> #endif
X> 
X70c109
X<   std_err("chmem {=+-} amount file\n");
X---
X>   std_err("usage:\tchmem {=+-} amount file\n");
X81a121,133
X> 
X> #ifdef DOS
X> 
X> std_err(s)
X> char *s;
X> {
X>   char *p = s;
X> 
X>   while(*p != 0) p++;
X>   write(2, s, p - s);
X> }
X> 
X> #endif
+ END-OF-FILE commands/chmem.dif
chmod u=rw,g=r,o=r commands/chmem.dif
set `sum commands/chmem.dif`
sum=$1
case $sum in
40156)	:;;
*)	echo 'Bad sum in 'commands/chmem.dif >&2
esac
echo Extracting commands/cp.dif
sed 's/^X//' > commands/cp.dif << '+ END-OF-FILE 'commands/cp.dif
X47a48
X>   exit(0);
+ END-OF-FILE commands/cp.dif
chmod u=rw,g=r,o=r commands/cp.dif
set `sum commands/cp.dif`
sum=$1
case $sum in
1120)	:;;
*)	echo 'Bad sum in 'commands/cp.dif >&2
esac
echo Extracting commands/cpdir.c
sed 's/^X//' > commands/cpdir.c << '+ END-OF-FILE 'commands/cpdir.c
X/* cpdir - copy directory  	 	Author: Erik Baalbergen */
X
X/* Use "cpdir [-v] src dst" to make a copy dst of directory src.
X   Cpdir should behave like the UNIX shell command
X	(cd src; tar cf - .) | (mkdir dst; cd dst; tar xf -)
X   but the linking structure of the tree, and the owner and time
X   information of files are not yet preserved. (See the work-yet-to-be-done list
X   below.)
X   The -v "verbose" flag enables you to see what's going on when running cpdir.
X
X   Work yet to be done:
X  - preserve link structure, times, etc...
X  - 'stat' optimization (stat() is invoked twice for normal files)
X  - link checks, i.e. am I not overwriting a file/directory by itself?
X	* has been solved by letting 'cpdir' create the target directory
X  - handle character and block special files
X	* they're simply not copied
X
X  Please report bugs and suggestions to erikb@cs.vu.nl
X*/
X
X#include "stdio.h"
X
X#define MKDIR1 "/bin/mkdir"
X#define MKDIR2 "/usr/bin/mkdir"
X#ifdef UNIX
X#include <sys/types.h>
X#include <sys/stat.h>
X#else !UNIX
X#include "stat.h"
X#endif
X
X#define BUFSIZE 1024
X#define PLEN	256
X#define DIRSIZ	16
X
Xchar *prog;
Xint vflag = 0;	/* verbose */
Xchar *strcpy();
X
Xmain(argc, argv)
X	char *argv[];
X{
X	int rc = 0;
X	char *p, *s;
X
X	prog = *argv++;
X	if ((p = *argv) && *p == '-') {
X		argv++;
X		argc--;
X		while (*++p) {
X			switch (*p) {
X			case 'v':
X				vflag = 1;
X				break;
X			default:
X				fatal("illegal flag %s", p);
X			}
X		}
X	}
X	if (argc != 3)
X		fatal("Usage: cpdir [-v] source destination");
X	if (ftype(s = *argv++) != S_IFDIR)
X		fatal("%s is not a directory", s);
X	cpdir(s, *argv);
X	exit(0);
X}
X
Xcpdir(s, d)
X	char *s, *d;
X{
X	char spath[PLEN], dpath[PLEN];
X	char ent[DIRSIZ + 1];
X	register char *send = spath, *dend = dpath;
X	int fd, n;
X
X	while (*send++ = *s++) {}
X	send--;
X	while (*dend++ = *d++) {}
X	if ((fd = open(spath, 0)) < 0) {
X		nonfatal("can't read directory %s", spath);
X		return;
X	}
X	*send++ = '/';
X	ent[DIRSIZ] = '\0';
X	mkdir(dpath);
X	dend[-1] = '/';
X	while ((n = read(fd, ent, DIRSIZ)) == DIRSIZ) {
X		if (!((ent[0] == '\0' && ent[1] == '\0')
X		|| (ent[2] == '.') &&
X			(ent[3] == '\0' || (ent[3] == '.' && ent[4] == '\0'))
X		)) {
X			strcpy(send, ent + 2);
X			strcpy(dend, ent + 2);
X			switch (ftype(spath)) {
X			case S_IFDIR:
X				cpdir(spath, dpath);
X				break;
X			case S_IFREG:
X				cp(spath, dpath);
X				break;
X			default:
X				nonfatal("can't copy special file %s", spath);
X			}
X		}
X	}
X	close(fd);
X	if (n)
X		fatal("error in reading directory %s", spath);
X}
X
Xmkdir(s)
X	char *s;
X{
X	int pid, status;
X
X	if (vflag)
X		printf("mkdir %s\n", s);
X	if ((pid = fork()) == 0) {
X		execl(MKDIR1, "mkdir", s, (char *)0);
X		execl(MKDIR2, "mkdir", s, (char *)0);
X		fatal("can't execute %s or %s", MKDIR1, MKDIR2);
X	}
X	if (pid == -1)
X		fatal("can't fork", prog);
X	wait(&status);
X	if (status)
X		fatal("can't create %s", s);
X}
X
Xcp(s, d)
X	char *s, *d;
X{
X	struct stat st;
X	char buf[BUFSIZE];
X	int sfd, dfd, n;
X
X	if (vflag)
X		printf("cp %s %s\n", s, d);
X	if ((sfd = open(s, 0)) < 0)
X		nonfatal("can't read %s", s);
X	else {
X		if (fstat(sfd, &st) < 0)
X			fatal("can't get file status of %s", s);
X		if ((dfd = creat(d, st.st_mode & 0777)) < 0)
X			fatal("can't create %s", d);
X		while ((n = read(sfd, buf, BUFSIZE)) > 0)
X			write(dfd, buf, n);
X		close(sfd);
X		close(dfd);
X		if (n)
X			fatal("error in reading file %s", s);
X	}
X}
X
Xftype(s)
X	char *s;
X{
X	struct stat st;
X
X	if (stat(s, &st) < 0)
X		fatal("can't get file status of %s", s);
X	return st.st_mode & S_IFMT;
X}
X
Xnonfatal(s, a)
X	char *s, *a;
X{
X	fprintf(stderr, "%s: ", prog);
X	fprintf(stderr, s, a);
X	fprintf(stderr, "\n");
X}
X
Xfatal(s, a)
X	char *s, *a;
X{
X	nonfatal(s, a);
X	exit(1);
X}
X
X
+ END-OF-FILE commands/cpdir.c
chmod u=rw,g=r,o=r commands/cpdir.c
set `sum commands/cpdir.c`
sum=$1
case $sum in
8282)	:;;
*)	echo 'Bad sum in 'commands/cpdir.c >&2
esac
echo Extracting commands/df.dif
sed 's/^X//' > commands/df.dif << '+ END-OF-FILE 'commands/df.dif
X37d36
X<   extern char *itoa();
X133a133
X>   return(0);
X146a147,149
X>   extern char *itoa();
X>   extern char *itoa(int);
X> 
+ END-OF-FILE commands/df.dif
chmod u=rw,g=r,o=r commands/df.dif
set `sum commands/df.dif`
sum=$1
case $sum in
8568)	:;;
*)	echo 'Bad sum in 'commands/df.dif >&2
esac
echo Extracting commands/diff.c
sed 's/^X//' > commands/diff.c << '+ END-OF-FILE 'commands/diff.c
X/* diff  - print differences between 2 files	  Author: Erik Baalbergen */
X
X/* Poor man's implementation of diff(1)
X - no options available
X - may give more output than other diffs, due to the straight-forward algorithm
X - runs out of memory if the differing chunks become too large
X - input line length should not exceed LINELEN; longer lines are truncated,
X   while only the first LINELEN characters are compared
X 
X Please report bugs and suggestions to erikb@cs.vu.nl
X*/
X#include "stdio.h"
XFILE *fopen();
X
X#define LINELEN 128
X
Xchar *prog;
Xint diffs = 0;
X
Xmain(argc, argv)
X	char **argv;
X{
X	FILE *fp1 = NULL, *fp2 = NULL;
X
X	prog = *argv++;
X	if (argc != 3)
X		fatal("use: %s file1 file2", prog);
X	if (strcmp(argv[0], "-") == 0)
X		fp1 = stdin;
X	else
X	if (strcmp(argv[1], "-") == 0)
X		fp2 = stdin;
X	if (fp1 == NULL && (fp1 = fopen(argv[0], "r")) == NULL)
X		fatal("can't read %s", argv[0]);
X	if (fp2 == NULL && (fp2 = fopen(argv[1], "r")) == NULL)
X		fatal("can't read %s", argv[1]);
X	diff(fp1, fp2);
X	exit(diffs > 0);
X}
X
Xfatal(fmt, s)
X	char *fmt, *s;
X{
X	fprintf(stderr, "%s: ", prog);
X	fprintf(stderr, fmt, s);
X	fprintf(stderr, "\n");
X	exit(2);
X}
X
X/* the line module */
Xchar *malloc();
Xchar *fgets();
X
Xstruct line {
X	struct line *l_next;
X	char l_text[LINELEN + 2];
X};
X
Xstruct line *freelist = 0;
X
Xstruct line *
Xnew_line()
X{
X	register struct line *l;
X
X	if (l = freelist)
X		freelist = freelist->l_next;
X	else
X	if ((l = (struct line *)malloc(sizeof(struct line))) == 0)
X		fatal("out of memory");
X	return l;
X}
X
Xfree_line(l)
X	register struct line *l;
X{
X	l->l_next = freelist;
X	freelist = l;
X}
X
X#define equal_line(l1, l2) (strcmp((l1)->l_text, (l2)->l_text) == 0)
X
Xint equal_3(l1, l2)
X	struct line *l1, *l2;
X{
X	register int i;
X
X	for (i=0; i<3 && l1 && l2; ++i, l1=l1->l_next, l2=l2->l_next) {
X		if (!equal_line(l1, l2))
X			return 0;
X	}
X	return (i==3);
X}
X
Xstruct line *
Xread_line(fp)
X	FILE *fp;
X{
X	register struct line *l = new_line();
X	register char *p;
X	register int c;
X
X	(p = &(l->l_text[LINELEN]))[1] = '\377';
X	if (fgets(l->l_text, LINELEN + 2, fp) == NULL) {
X		free_line(l);
X		return 0;
X	}
X	if ((p[1] & 0377) != '\377' && *p != '\n') {
X		while ((c = fgetc(fp)) != '\n' && c != EOF) {}
X		*p++ = '\n';
X		*p = '\0';
X	}
X	l->l_next = 0;
X	return l;
X}
X
X/* file window handler */
Xstruct f {
X	struct line *f_bwin, *f_ewin;
X	struct line *f_aside;
X	int f_linecnt;	/* line number in file of last advanced line */
X	FILE *f_fp;
X};
X
Xadvance(f)
X	register struct f *f;
X{
X	register struct line *l;
X	
X	if (l = f->f_bwin) {
X		if (f->f_ewin == l)
X			f->f_bwin = f->f_ewin = 0;
X		else
X			f->f_bwin = l->l_next;
X		free_line(l);
X		(f->f_linecnt)++;
X	}
X}
X
Xaside(f, l)
X	struct f *f;
X	struct line *l;
X{
X	register struct line *ll;
X
X	if (ll = l->l_next) {
X		while (ll->l_next)
X			ll = ll->l_next;
X		ll->l_next = f->f_aside;
X		f->f_aside = l->l_next;
X		l->l_next = 0;
X		f->f_ewin = l;
X	}
X}
X
Xstruct line *
Xnext(f)
X	register struct f *f;
X{
X	register struct line *l;
X
X	if (l = f->f_aside) {
X		f->f_aside = l->l_next;
X		l->l_next = 0;
X	}
X	else
X		l = read_line(f->f_fp);
X	if (l) {
X		if (f->f_bwin == 0)
X			f->f_bwin = f->f_ewin = l;
X		else {
X			f->f_ewin->l_next = l;
X			f->f_ewin = l;
X		}
X	}
X	return l;
X}
X
Xinit_f(f, fp)
X	register struct f *f;
X	FILE *fp;
X{
X	f->f_bwin = f->f_ewin =  f->f_aside = 0;
X	f->f_linecnt = 0;
X	f->f_fp = fp;
X}
X
Xupdate(f, s)
X	register struct f *f;
X	char *s;
X{
X	while (f->f_bwin && f->f_bwin != f->f_ewin) {
X		printf("%s%s", s, f->f_bwin->l_text);
X		advance(f);
X	}
X}
X	
X/* diff procedure */
Xdiff(fp1, fp2)
X	FILE *fp1, *fp2;
X{
X	struct f f1, f2;
X	struct line *l1, *s1, *b1, *l2, *s2, *b2;
X	register struct line *ll;
X
X	init_f(&f1, fp1);
X	init_f(&f2, fp2);
X	l1 = next(&f1);
X	l2 = next(&f2);
X	while (l1 && l2) {
X		if (equal_line(l1, l2)) {
Xequal:
X			advance(&f1);
X			advance(&f2);
X			l1 = next(&f1);
X			l2 = next(&f2);
X			continue;
X		}
X		s1 = b1 = l1;
X		s2 = b2 = l2;
X		/* read several more lines */
X		next(&f1); next(&f1);
X		next(&f2); next(&f2);
X		/* start searching */
Xsearch:
X		if ((l2 = next(&f2)) == 0)
X			continue;
X		ll = s1;
X		b2 = b2->l_next;
X		do {
X			if (equal_3(ll, b2)) {
X				aside(&f1, ll);
X				aside(&f2, b2);
X				differ(&f1, &f2);
X				goto equal;
X			}
X		} while (ll = ll->l_next);
X		if ((l1 = next(&f1)) == 0)
X			continue;
X		ll = s2;
X		b1 = b1->l_next;
X		do {
X			if (equal_3(ll, b1)) {
X				aside(&f2, ll);
X				aside(&f1, b1);
X				differ(&f1, &f2);
X				goto equal;
X			}
X		} while (ll = ll->l_next);
X		goto search;
X	}
X	/* one of the files reached EOF */
X	if (l1) /* eof on 2 */
X		while (next(&f1)) {}
X	if (l2)
X		while (next(&f2)) {}
X	f1.f_ewin = 0;
X	f2.f_ewin = 0;
X	differ(&f1, &f2);
X}
X
Xdiffer(f1, f2)
X	register struct f *f1, *f2;
X{
X	int cnt1 = f1->f_linecnt, len1 = wlen(f1), cnt2 = f2->f_linecnt,
X		len2 = wlen(f2);
X
X	if ((len1 = wlen(f1)) || (len2 = wlen(f2))) {
X		if (len1 == 0) {
X			printf("%da", cnt1);
X			range(cnt2 + 1, cnt2 + len2);
X		}
X		else
X		if (len2 == 0) {
X			range(cnt1 + 1, cnt1 + len1);
X			printf("d%d", cnt2);
X		}
X		else {
X			range(cnt1 + 1, cnt1 + len1);
X			putchar('c');
X			range(cnt2 + 1, cnt2 + len2);
X		}
X		putchar('\n');
X		if (len1)
X			update(f1, "< ");
X		if (len1 && len2)
X			printf("---\n");
X		if (len2)
X			update(f2, "> ");
X		diffs++;
X	}
X}
X
Xwlen(f)
X	struct f *f;
X{
X	register cnt = 0;
X	register struct line *l = f->f_bwin, *e = f->f_ewin;
X
X	while (l && l != e) {
X		cnt++;
X		l = l->l_next;
X	}
X	return cnt;
X}
X
Xrange(a, b)
X{
X	printf(((a == b) ? "%d" : "%d,%d"), a, b);
X}
+ END-OF-FILE commands/diff.c
chmod u=rw,g=r,o=r commands/diff.c
set `sum commands/diff.c`
sum=$1
case $sum in
64242)	:;;
*)	echo 'Bad sum in 'commands/diff.c >&2
esac
echo Extracting commands/dosread.dif
sed 's/^X//' > commands/dosread.dif << '+ END-OF-FILE 'commands/dosread.dif
X16c16
X< #define DRIVE		"/dev/fdX"
X---
X> #define DRIVE		"/dev/atX"
X186c186
X< 		print_string(TRUE, "Diskette is neither 360K nor 1.2M\n");
X---
X> 		print_string(TRUE, "Diskette is not DOS 2.0 360K or 1.2M\n");
X279c279
X< 		while (*pathname != '/' && *pathname && i < 11)
X---
X> 		while (*pathname != '/' && *pathname && i < 12)
X494,506c494,502
X< 	for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++)
X< 		entry->d_name[i] = *ptr++;
X< 	while (i < 8)
X< 		entry->d_name[i++] = ' ';
X< 	r = strlen(name);
X< 	while (r && name[r - 1] != '.')
X< 		r--;
X< 
X< 	i = 0;
X< 	while (r && i < 3 && name[r])
X< 		entry->d_ext[i++] = name[r++];
X< 	while (i < 3)
X< 		entry->d_ext[i++] = ' ';
X---
X> 	bcopy("           ",&entry->d_name[0],11);	/* clear entry */
X> 	for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++)
X> 		entry->d_name[i] = *ptr++;
X> 	while (*ptr != '.' && *ptr)
X> 		ptr++;
X> 	if (*ptr == '.')
X> 		ptr++;
X> 	for (i=0;i < 3 && *ptr; i++)
X> 		entry->d_ext[i] = *ptr++;
X584c580
X< 		day -= mon_len[i];
X---
X> 		day -= mon_len[i++];
X641c637
X< 	return (buffer - begin);
X---
X> 	return (int) (buffer - begin);
X819c815
X< 		write(2, buf, buf_ptr - buf);
X---
X> 		write(2, buf, (int) (buf_ptr - buf));
+ END-OF-FILE commands/dosread.dif
chmod u=rw,g=r,o=r commands/dosread.dif
set `sum commands/dosread.dif`
sum=$1
case $sum in
14054)	:;;
*)	echo 'Bad sum in 'commands/dosread.dif >&2
esac
echo Extracting commands/fdisk.c
sed 's/^X//' > commands/fdisk.c << '+ END-OF-FILE 'commands/fdisk.c
X/* fdisk - partition a hard disk	Author: Jakob Schripsema */
X
X/*
X * First run the DOS utilities FDISK and FORMAT. FDISK
X * puts the boot code in sector 0.
X * Then run fdisk
X *
X *	fdisk /dev/hdx	(MINIX)
X *	fdisk x:		(DOS)
X *
X * Compiling
X *
X *	cc -o fdisk -DUNIX fdisk.c	(MINIX)
X *	cl -DDOS fdisk.c			(DOS with MS C compiler)
X */
X 
X#include "stdio.h"
X#define UNIX		/* for MINIX */
X
X#ifdef DOS
X#include <dos.h>
X#endif
X
X/*
X * Constants
X */
X
X#define	NHEAD		4		/* # heads		*/
X#define	NSEC		17		/* sectors / track	*/
X#define SECSIZE		512		/* sector size		*/
X#define	OK		0
X#define	ERR		1
X#define	TABLEOFFSET	0x1be		/* offset in boot sector*/
X/*
X * Description of entry in partition table
X */
X
Xstruct part_entry {
X	char	bootind;	/* boot indicator 0/0x80	*/
X	char	start_head;	/* head value for first sector	*/
X	char	start_sec;	/* sector value for first sector*/
X	char	start_cyl;	/* track value for first sector	*/
X	char	sysind;		/* system indicator 00=?? 01=DOS*/
X	char	last_head;	/* head value for last sector	*/
X	char	last_sec;	/* sector value for last sector	*/
X	char	last_cyl;	/* track value for last sector	*/
X	long	lowsec;		/* logical first sector		*/
X	long	size;		/* size of partion in sectors	*/
X};
X	
X/*
X * Globals
X */
X
Xchar	secbuf[SECSIZE];
Xchar	*devname;
Xchar	*dosstr  = "  DOS  ";
Xchar	*ndosstr = "Non-DOS";
X
X#ifdef DOS
Xunion	REGS	regs;
Xstruct	SREGS	sregs;
Xint	drivenum;
X#endif
X
X#ifdef UNIX
Xint	devfd;
X#endif
X
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	char	ch;
X
X	/* init */
X
X	if (argc != 2) {
X		printf("Usage: fdisk /dev/hdx\n");
X		exit(1);
X	}
X
X	devname = argv[1];
X	getboot(secbuf);	/* get boot sector	*/
X
X	do {
X		dpl_partitions();
X		print_menu();
X		ch = get_a_char();
X		putchar('\n');
X		switch (ch) {
X			case 'c' :
X				change_table();
X				break;
X			case 'w' :
X				if (chk_table() == OK) {
X					putboot(secbuf);
X					exit(0);
X				}
X				break;
X			case 'l' :
X				load_from_file();
X				break;
X			case 's' :
X				save_to_file();
X				break;
X			case 'p' :
X				dump_table();
X				break;
X			case 'q' :
X				exit(0);
X			default :
X				printf(" %c ????\n",ch);
X		}
X	}
X	while (1);
X}
X
X/*
X * Read boot sector
X */
X
X#ifdef DOS
X
Xgetboot(buffer)
Xchar	*buffer;
X{
X	segread(&sregs);	/* get ds */
X
X	if (devname[1] != ':') {
X		printf("Invalid drive %s\n",devname);
X		exit(1);
X	}
X
X	if (*devname >= 'a')
X		*devname += 'A' - 'a';
X	drivenum = (*devname - 'C') & 0xff;
X	if (drivenum < 0 || drivenum > 7) {
X		printf("Funny drive number %d\n",drivenum);
X		exit(1);
X	}
X	regs.x.ax = 0x201;	/* read 1 sectors	*/
X	regs.h.ch = 0;		/* track		*/
X	regs.h.cl = 1;		/* first sector = 1	*/
X	regs.h.dh = 0;		/* head = 0		*/
X	regs.h.dl = 0x80+drivenum;/* drive = 0		*/
X	sregs.es = sregs.ds;	/* buffer address	*/
X	regs.x.bx = (int)secbuf;
X
X	int86x(0x13,&regs,&regs,&sregs);
X	if (regs.x.cflag)
X	{
X		printf("Cannot read boot sector\n");
X		exit(1);
X	}
X}
X#endif
X
X#ifdef UNIX
X
Xgetboot(buffer)
Xchar	*buffer;
X{
X	devfd = open(devname,2);
X	if (devfd < 0) {
X		printf("Cannot open device %s\n",devname);
X		exit(1);
X	}
X	if (read(devfd,buffer,SECSIZE) != SECSIZE) {
X		printf("Cannot read boot sector\n");
X		exit(2);
X	}
X}
X#endif
X
X/*
X * Write boot sector
X */
X
X#ifdef DOS
X
Xputboot(buffer)
Xchar	*buffer;
X{
X	regs.x.ax = 0x301;	/* read 1 sectors	*/
X	regs.h.ch = 0;		/* track		*/
X	regs.h.cl = 1;		/* first sector = 1	*/
X	regs.h.dh = 0;		/* head = 0		*/
X	regs.h.dl = 0x80+drivenum;/* drive = 0		*/
X	sregs.es = sregs.ds;	/* buffer address	*/
X	regs.x.bx = (int)secbuf;
X
X	int86x(0x13,&regs,&regs,&sregs);
X	if (regs.x.cflag)
X	{
X		printf("Cannot write boot sector\n");
X		exit(1);
X	}
X}
X#endif
X
X#ifdef UNIX
X
Xputboot(buffer)
Xchar	*buffer;
X{
X	int r;
X
X	if (lseek(devfd,0L,0) < 0) {
X		printf("Seek error during write\n");
X		exit(1);
X	}
X	if (write(devfd,buffer,SECSIZE) != SECSIZE) {
X		printf("Write error\n");
X		exit(1);
X	}
X	sync();
X}
X#endif
X
X/*
X * Load buffer from file
X */
X
Xload_from_file()
X{
X	char	file[80];
X	int	fd;
X
X	printf("Enter file name: ");
X	gets(file);
X#ifdef UNIX
X	fd = open(file,0);
X#endif
X#ifdef DOS
X	fd = open(file,0x8000);
X#endif
X	if (fd < 0) {
X		fprintf(stderr,"Cannot load from %s\n",file);
X		exit(1);
X	}
X	if (read(fd,secbuf,SECSIZE) != SECSIZE) {
X		fprintf(stderr,"Read error\n");
X		exit(1);
X	}
X	close(fd);
X}
X
X/*
X * Save to file
X */
X
Xsave_to_file()
X{
X	char	file[80];
X	int	fd;
X
X	printf("Enter file name: ");
X	gets(file);
X#ifdef UNIX
X	fd = creat(file,0644);
X#endif
X#ifdef DOS
X	fd = creat(file,0644);
X	if (fd < 0) {
X		fprintf(stderr,"Cannot creat %s\n",file);
X		exit(1);
X	}
X	close(fd);
X	fd = open(file,0x8001);
X#endif
X	if (fd < 0) {
X		fprintf(stderr,"Cannot save to %s\n",file);
X		exit(1);
X	}
X	if (write(fd,secbuf,SECSIZE) != SECSIZE) {
X		fprintf(stderr,"Write error\n");
X		exit(1);
X	}
X	close(fd);
X}
X
X/*
X * Dump partition table
X */
X
Xdump_table()
X{
X	struct	part_entry	*pe;
X	int	i;
X
X	pe = (struct part_entry *)&secbuf[TABLEOFFSET];
X	printf("\n       --first---     ---last---\n");
X	printf("Prt ac hd sec cyl sys hd sec cyl    low      size\n");
X	for (i = 1 ; i < 5 ; i++) {
X		printf(" %x  %2x  %x  %2x  %2x  %2x  %x  %2x  %2x %6D %9D\n",
X			i,
X			pe->bootind & 0xff,
X			pe->start_head & 0xff,
X			pe->start_sec & 0xff,
X			pe->start_cyl & 0xff,
X			pe->sysind & 0xff,
X			pe->last_head & 0xff,
X			pe->last_sec & 0xff,
X			pe->last_cyl & 0xff,
X			pe->lowsec,
X			pe->size);
X		pe++;
X	}
X}
X/*
X * Display partition table
X */
X
Xdpl_partitions()
X{
X	struct	part_entry	*pe;
X	int	i;
X
X	printf("\nPartition      Type     Begin End  Active\n");
X	pe = (struct part_entry *)&secbuf[TABLEOFFSET];
X	for (i = 1 ; i <= 4 ; i++) {
X		dpl_entry(i,pe);
X		pe++;
X	}
X}
X
X/*
X * Display an entry
X */
X
Xdpl_entry(number,entry)
Xint	number;
Xstruct	part_entry	*entry;
X{
X	int	low_cyl,high_cyl,temp;
X	char	*typestring;
X	char	active;
X
X	if (entry->sysind == 0x01)
X		typestring = dosstr;
X	else
X		typestring = ndosstr;
X	printf("%5d         %s  ",number,typestring);
X	temp = entry->start_sec & 0xc0;
X	low_cyl = (entry->start_cyl & 0xff) + (temp << 2);
X	temp = entry->last_sec & 0xc0;
X	high_cyl = (entry->last_cyl & 0xff) + (temp << 2);
X	printf("%4d  %4d",low_cyl,high_cyl);
X	if ((entry->bootind & 0xff) == 0x80)
X		active = 'A';
X	else
X		active = 'N';
X	printf("     %c\n",active);
X}
X
X/*
X * Check partition table
X */
X
Xchk_table()
X{
X	struct part_entry *pe;
X	int i;
X	int active;
X	long limit;
X
X	pe = (struct part_entry *)&secbuf[TABLEOFFSET];
X	limit = 0L;
X	active = 0;
X	for (i = 1 ; i < 5 ; i++) {
X		if (pe->size == 0L)
X			return(OK);
X		if (pe->lowsec <= limit) {
X			printf("Overlap between part. %d and %d\n",i,i-1);
X			return(ERR);
X		}
X		limit = pe->lowsec + pe->size - 1L;
X		if (pe->bootind == 0x80)
X			active++;
X		pe++;
X	}
X	if (active > 1) {
X		printf("%d active partitions\n",active);
X		return(ERR);
X	}
X	return(OK);
X}
X/*
X * Check entry
X * head/sector/track info must match logical sector number
X * Used to check 'foreign' partition table during debugging
X */
X
Xchk_entry(entry)
Xstruct	part_entry	*entry;
X{
X	char	head;
X	char	sector;
X	char	track;
X
X	sec_to_hst(entry->lowsec,&head,&sector,&track);
X	if (	(head != entry->start_head) ||
X		(sector != entry->start_sec) ||
X		(track != entry->start_cyl))
X		return(ERR);
X	sec_to_hst(entry->lowsec + entry->size - 1L,&head,&sector,&track);
X	if (	(head != entry->last_head) ||
X		(sector != entry->last_sec) ||
X		(track != entry->last_cyl))
X		return(ERR);
X	return(OK);
X}
X
X/*
X * Convert a logical sector number to
X * head / sector / track
X */
X
Xsec_to_hst(logsec,hd,sec,cyl)
Xlong	logsec;
Xchar	*hd,*sec,*cyl;
X{
X	int	bigcyl;
X
X	bigcyl = logsec / (NHEAD * NSEC);
X	*sec = (logsec % NSEC) + 1 + ((bigcyl >> 2) & 0xc0);
X	*cyl = bigcyl & 0xff;
X	*hd = (logsec % (NHEAD * NSEC)) / NSEC;
X}
X
X/*
X * change partition table
X */
X
Xchange_table()
X{
X	struct	part_entry	*pe;
X	int	i,temp,low_cyl,high_cyl;
X	char	ch;
X
X	pe = (struct part_entry *)&secbuf[TABLEOFFSET];
X	for (i = 1 ; i <= 4 ; i++) {
X		temp = pe->start_sec & 0xc0;
X		low_cyl = (pe->start_cyl & 0xff) + (temp << 2);
X		temp = pe->last_sec & 0xc0;
X		high_cyl = (pe->last_cyl & 0xff) + (temp << 2);
X		printf("Partition %d from %d to %d. Change? (y/n) ",
X			i,low_cyl,high_cyl);
X		ch = get_a_char();
X		if (ch == 'y' || ch == 'Y')
X			get_partition(pe);
X		pe++;
X	}
X	putchar('\n');
X}
X
X/*
X * Get partition info : first & last cylinder
X */
X
Xget_partition(entry)
Xstruct part_entry *entry;
X{
X	char	buf[80];
X	int	first,last;
X	long	low,high;
X	char	ch;
X
X	printf("	Enter first cylinder: ");
X	gets(buf);
X	sscanf(buf,"%d",&first);
X	printf("	Enter last cylinder: ");
X	gets(buf);
X	sscanf(buf,"%d",&last);;
X	if (first == 0 && last == 0) {
X		entry->bootind = 0;
X		entry->start_head = 0;
X		entry->start_sec = 0;
X		entry->start_cyl = 0;
X		entry->sysind = 0;
X		entry->last_head = 0;
X		entry->last_sec  = 0;
X		entry->last_cyl = 0;
X		entry->lowsec = 0L;
X		entry->size = 0L ;
X		return;
X	}
X	low = first & 0xffff;
X	low = low * NSEC * NHEAD;
X	if (low == 0)
X		low = 1; /* sec0 is master boot record */
X	high = last & 0xffff;
X	high = (high + 1)*NSEC*NHEAD - 1;
X	entry->lowsec = low;
X	entry->size = high - low + 1;
X	sec_to_hst(low,
X		&entry->start_head,
X		&entry->start_sec,
X		&entry->start_cyl);
X	sec_to_hst(high,
X		&entry->last_head,
X		&entry->last_sec,
X		&entry->last_cyl);
X	printf("	DOS partition? (y/n) ");
X	ch = get_a_char();
X	if (ch == 'y' || ch == 'Y')
X		entry->sysind = 1;
X	else
X		entry->sysind = 0;
X	printf("	Active partition? (y/n) ");
X	ch = get_a_char();
X	if (ch == 'y' || ch == 'Y')
X		entry->bootind = 0x80;
X	else
X		entry->bootind = 0;
X}
X
X/*
X * Read 1 character and discard rest of line
X */
X
Xget_a_char()
X{
X	char	ch;
X
X	ch = getchar();
X	if (ch != '\n')
X		while (getchar() != '\n');
X	return(ch);
X}
X
Xprint_menu()
X{
X  printf("\nType a command letter, then a carriage return:\n");
X  printf("   c - change a partition\n");
X  printf("   w - write changed partition table back to disk and exit\n");
X  printf("   q - quit without making any changes\n");
X  printf("   s - save boot block (including partition table) on a file\n");
X  printf("   l - load boot block (including partition table) from a file\n");
X  printf("   p - print partition table\n\n");
X}
+ END-OF-FILE commands/fdisk.c
chmod u=rw,g=r,o=r commands/fdisk.c
set `sum commands/fdisk.c`
sum=$1
case $sum in
25274)	:;;
*)	echo 'Bad sum in 'commands/fdisk.c >&2
esac
exit 0