echo x - Makefile.ansi
sed '/^X/s///' > Makefile.ansi << '/'
X# Makefile for IBM specific files
X
Xl=/usr/lib
XCC=exec cc
X
XCFLAGS= -s -m -O -D_MINIX -D_POSIX_SOURCE 
XSMALL= -Dprintf=printk -Dfprintf=fprintk
XO=s
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=cc libpack libupack lorder readclock sdump ncc
XOBJ2=ar ast dosread fdisk postmort
X
X
Xall:	$(OBJ1) $(OBJ2)
X
X$(OBJ1):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
X$(OBJ2):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) $(SMALL) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
Xclean:	
X	@rm -f *.o *.s core *.bak
/
echo x - Makefile.kr
sed '/^X/s///' > Makefile.kr << '/'
X# Makefile for IBM specific files
X
Xl=/usr/lib
XCC=exec cc
X
XCFLAGS= -O -D_MINIX -D_POSIX_SOURCE 
XSMALL= -Dprintf=printk -Dfprintf=fprintk
XO=s
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=cc libpack libupack lorder readclock sdump ncc
XOBJ2=ar ast dosread fdisk postmort
X
X
Xall:	$(OBJ1) $(OBJ2)
X
X$(OBJ1):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
X$(OBJ2):
X	@echo ----------------------------- $@ -------------------------------
X	@$(CC) $(CFLAGS) $(SMALL) -o bin/$@ $@.c
X	@chmem =8192 bin/$@ >/dev/null 2>&1
X
Xclean:	
X	@rm -f *.o *.s core *.bak
/
echo x - format.c
sed '/^X/s///' > format.c << '/'
X/* format -  floppy disk format (PC-MINIX)          Author: D. Chapman */
X
X/* Author: Donald E. Chapman.      Copyright 1991 by Donald E. Chapman
X *
X * Usage: format [-q][-a][special [kbsize]][-v [dosvollabel]]
X *
X * Flags: -q: quiet will skip the "are you sure" prompt.
X *	  -v: volume label added along with structures Dos needs.
X *	      If no label is given format will prompt for it.
X *	  -a: sort interactive list alphabetically rather than by size.
X *
X *	     Format allows super user to format disks.  If it is suid
X *	  then it allows others to format if they are at the console.
X *	     Format will format all seven of the non-automatic
X *	  disk/media combinations that PC-Minix supports.  It will
X *	  also try to format automatics (minor 0 through 3) if a device
X *	  size was given when the node was made.  Format usually expects
X *	  special devices to have sizes.
X *	     Format will optionally add the structures Dos needs,
X *	  including a "non-bootable" message, if either the device
X *	  name is a dos device, like dosA, or if the -v flag is used.
X *	     If a special device is specified in the command line then
X *	  a size may also be specified there.  If a size is specified
X *	  in the command line the size must agree with the capability
X *	  of the special device.
X *	     If no special device is specified in the command line
X *	  format will interactively help you to determine which of
X *	  your drives you wish to format on.  It actually allows
X *	  the automatic devices to be formatted that way even if
X *	  they were made with a size of zero.
X *
X * Warning:  Some disk drives are media sensitive and on them you
X *	  should use DD or HD media as appropriate for the density
X *	  you are formatting.  For some media sensitive drives if
X *	  you try to format media of the wrong density the disk
X *	  can not be formatted correctly.
X *
X * Examples:	format /dev/at0			format disk in /dev/at0.
X *		format /dev/at0 360		format disk to size 360.
X *		format /dev/dosA		format for Dos.
X *		format /dev/fd1 -v DOS_DISK	format labeled Dos disk.
X *		format				interactive mode formatting.
X *
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <minix/config.h>
X#include <minix/const.h>
X#ifndef _V15_
X#include <minix/minlib.h>
X#endif
X#include <dirent.h>
X#include <ctype.h>
X#include <signal.h>
X#include <stdlib.h>
X#include <time.h>
X#include <unistd.h>
X#include <fcntl.h>
X#include <string.h>
X#include <stdio.h>
X
X/* Kludges */
X#ifdef _V15_
X#define mknod4 mknod
X#endif
X
X/* Macros */
X#define maj(d)  ( ((d) >> MAJOR) & BYTE)
X#define min(d)  ( ((d) >> MINOR) & 0x7F)	/* ignore format bit */
X#define illegal(s) ((s)!=360 && (s)!=720 && (s)!=1200 && (s)!=1440)
X
X/* For the list of existing drives */
Xstruct drive {
X  dev_t device;
X  int dos_type;
X  int is_auto;
X  off_t msize;
X  char *name;
X  struct drive *next;
X};
X
Xstruct param_struct {		/* Must align with diskparm.h */
X  unsigned char s1;
X  unsigned char s2;
X  unsigned char motor_off;
X  unsigned char sec_size_code;	/* Needed */
X  unsigned char sec_per_cyl;	/* Needed */
X  unsigned char gap;
X  unsigned char data_len;
X  unsigned char gap_fmt;	/* Needed */
X  unsigned char fill_byte;	/* Needed */
X  unsigned char head_settle;
X  unsigned char motor_start;
X};
X
Xstruct table_entry {
X  unsigned char cyl;
X  unsigned char head;
X  unsigned char sector;
X  unsigned char sec_size_code;
X};
X
X/* Some constants */
X#define NULL_L		(struct drive *)NULL
X#define NULL_D		(struct dirent *)NULL
X#define SEC_SIZE	 512
X#define NR_HEADS	   2
X#define F_MAJOR		   2
X#define F_DRIVE_BITS	0x03
X#define F_BIT		0x80
X#define UNLINK		TRUE
X#define OMIT		FALSE
X#define NAME_MAX	  14	/* was in limit.h strangely */
X#define PATH_MAX	 255
X#define FAIL_MOUNTED	TRUE
X#define NOT_MOUNTED	FALSE
X
X#define FAIL_OPEN	   1
X#define FAIL_SEEK	   2
X#define FAIL_WRITE	   4
X#define MAX_TRIES	  10
X
X#ifndef CONSOLE
X#define CONSOLE         "/dev/tty0"
X#endif
X
X/* Constants for DOS */
X#define BOOT_SIZE	sizeof(non_boot)
X#define VE_SIZE		sizeof(vol_entry)
X#define VEL_SIZE	sizeof(vol_entry.label)
X#define BLANKS		"           "	/* max 11 */
X#define SMALL_DIR	0x70
X#define LARGE_DIR	0xE0
X#define DIRENT_SIZE	  32
X#define VOL_ARC		0x28
X#define Y_SHIFT		   9
X#define MON_SHIFT	   5
X#define H_SHIFT		  11
X#define MIN_SHIFT	   5
X#define SEC_DIV		   2
X#define DOS_BASE_YEAR	  80
X#define FAT_SIZE	   3
X#define MAGIC_SIZE	   5
X#define MAGIC_LOC	 510
X#define NO_FAILURE	   0
X#define FAIL_D0		   1
X#define FAIL_DCLEAR	   2
X#define FAIL_DFAT2	   4
X#define FAIL_DVOL	   8
X#define FAIL_DFAT1	  16
X
Xstatic char version[] = {"format V1.2, Copyright 1991 by Donald E. Chapman"};
X
X/* Globals */
Xstruct param_struct param;
X
Xunsigned char non_boot[113] = {	/* hand constructed with loving care */
X	 0xEB, 0x50, 0x90, 0x4D, 0x49, 0x4E, 0x49, 0x58, 0x66, 0x31,
X	 0x31, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0xE0, 0x00, 0x60,
X	 0x09, 0xF9, 0x07, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00,
X	 0x00, 0x00, 0x0D, 0x0A, 0x4E, 0x6F, 0x74, 0x20, 0x61, 0x20,
X	 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x64, 0x69, 0x73,
X	 0x6B, 0x2E, 0x20, 0x52, 0x65, 0x70, 0x6C, 0x61, 0x63, 0x65,
X	 0x20, 0x61, 0x6E, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73,
X	 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x2E, 0x0D,
X	 0x0A, 0x00, 0xFA, 0x33, 0xC0, 0x8E, 0xD0, 0x8E, 0xD8, 0xBC,
X	 0x00, 0x7C, 0xBE, 0x20, 0x7C, 0xFC, 0xAC, 0x3C, 0x00, 0x74,
X	 0x06, 0xB4, 0x0E, 0xCD, 0x10, 0xEB, 0xF5, 0x33, 0xC0, 0xCD,
X		       0x16, 0xCD, 0x19
X};
X
X/* Magic number for DOS and fat bytes */
Xstatic unsigned char f_bytes[5] = {0x55, 0xAA, 0xF9, 0xFF, 0xFF};
X
X/* Volume label and date */
Xstruct vol_entry {
X  char label[11];
X  unsigned char attrib;
X  char reserv[10];
X  short time;
X  short date;
X} vol_entry;
Xstatic char vol_temp[20] = {'\0'};
X
X/* Formatting work area */
Xstatic union u {
X  char buffer[BLOCK_SIZE];
X  struct p {
X	struct table_entry	/* max 128 */
X	 table[BLOCK_SIZE / 2 / sizeof(struct table_entry)];
X	struct param_struct param;
X  } p;
X} u;
X
X/* MINIX Drive/media combinations (automatics are mapped.)
X * minor 0-3 4-7  8-11 12-15  12-15  16-19  16-19 20-23  24-27  28-31
X * dtype  0   1    2     3      3      4      4     5      6      7
X * drv.  au. 360 1.2M   720   1.44M  720   1.44M   1.2M   1.2M  1.44M
X * med.  au. 360 1.2M   360    360   720    720    360    720   1.44M
X */
X
Xint dsize[] = {0, 360, 1200, 720, 720, 1200, 1200, 1440};
Xunsigned char cyl_table[] = {0, 39, 79, 39, 79, 39, 79, 79};
Xunsigned char gap_fmt_table[] = {0, 0x50, 0x54, 0x50, 0x50, 0x50, 0x50, 0x54};
Xunsigned char media_id[] = {0, 0xFD, 0xF9, 0xFD, 0xF9, 0xFD, 0xF9, 0xF0};
Xunsigned char sector_table[] = {0, 9, 15, 9, 9, 9, 9, 18};
Xunsigned char sec_cluster[] = {0, 2, 1, 2, 2, 2, 2, 1};
Xunsigned char sec_fat[] = {0, 2, 7, 2, 3, 2, 3, 9};
Xunsigned char dir_size[] = {0, SMALL_DIR, LARGE_DIR, SMALL_DIR,
X		    SMALL_DIR, SMALL_DIR, SMALL_DIR, LARGE_DIR};
X
X/* Chart of dtype mapping. 3.5 inch 1440's serve as 720's too.
X *                   dsize
X * map[u][m]    360 720 1200 1440
X * usize  360    1   3    5    3
X * usize  720    .   4    6    4
X * usize 1200    .   .    2    .
X * usize 1440    .   .    .    7
X */
Xint dtype_map[4][4] = {1, 3, 5, 3, -1, 4, 6, 4, -1, -1, 2, -1, -1, -1, -1, 7};
X
Xchar *progname, *nname;
Xint interrupt = FALSE;		/* If sigint or sigquit occurs	 */
Xint a_flag = FALSE;		/* Don't sort alphabetically */
Xint v_flag = 0;			/* Can be -1, 0 or +n */
Xint dos_type = FALSE;
Xint interactive = TRUE;
Xint max_cyl;
Xint max_len;			/* Length of longest special name */
Xint msize = 0;			/* usually holds media size in Kb */
Xint usize = 0;			/* User specified size in Kb */
Xoff_t dir_start;
Xoff_t dir_max;
Xoff_t second_fat;
X
X_PROTOTYPE(void usage, (void));
X_PROTOTYPE(void quit, (char *mess, char *more, int linked));
X_PROTOTYPE(void add_to_list, (struct drive ** h, struct drive * f));
X_PROTOTYPE(void make_list, (struct drive ** drive_list));
X_PROTOTYPE(struct drive * make_selection, (struct drive * list_head));
X_PROTOTYPE(struct drive * command_line_check, (struct drive * dp));
X_PROTOTYPE(void set_parameters, (int dtype));
X_PROTOTYPE(void adjust_bootblock, (int dtype, int msize));
X_PROTOTYPE(int mounted, (char *dname));
X_PROTOTYPE(void Sigint, (int s));
X_PROTOTYPE(void Sigquit, (int s));
X_PROTOTYPE(void prepare_node, (Dev_t device));
X_PROTOTYPE(int format_track, (int cyl, int head, int logical));
X_PROTOTYPE(int full_format, (void));
X_PROTOTYPE(int add_vol_label, (int fd));
X_PROTOTYPE(int add_structures, (char *dname, Dev_t device));
X_PROTOTYPE(int test_error, (char *dname));
X_PROTOTYPE(int main, (int argc, char *argv[]));
X
X
Xvoid usage()
X{
X  fprintf(stderr,
X	"\nUsage: %s [-q][-a][special [kbsize]][-v [dosvollabel]]\n",
X	progname);
X  exit(EXIT_FAILURE);
X}
X
Xvoid quit(mess, more, linked)
Xchar *mess;
Xchar *more;
Xint linked;
X{
X  if (linked) unlink(nname);	/* remove temporary */
X  fprintf(stderr, "\n%s: %s%s.\n", progname, mess, more);
X  exit(EXIT_FAILURE);
X}
X
Xvoid add_to_list(h, f)		/* by sizes or alphabetic */
Xstruct drive **h, *f;
X{
X  /* At the tail */
X  if ((*h) == NULL_L) {
X	f->next = (*h);
X	(*h) = f;
X  } else if ((a_flag && strcmp((*h)->name, f->name) > 0) ||
X	     (!a_flag && ((*h)->msize > f->msize) ||
X		       ((*h)->msize == f->msize && (
X					 (*h)->device > f->device ||
X					((*h)->device == f->device &&
X				       (*h)->dos_type > f->dos_type)))
X		       )
X	) {
X	/* Amid the list */
X	f->next = *h;
X	(*h) = f;
X  } else			/* Recursion */
X	add_to_list(&((*h)->next), f);
X}
X
X/* Make a list of existing floppy drives found in /dev */
Xvoid make_list(drive_list)
Xstruct drive **drive_list;
X{
X  struct drive *dp;
X  DIR *dd1;
X  struct stat dstat;
X  struct dirent *dentry;
X  char *dname;
X  int sres, nlen;
X
X  max_len = 0;
X  dd1 = opendir("/dev");
X  while ((dentry = readdir(dd1)) != NULL_D) {
X	if (dentry->d_name[0] != '.') {
X		dname = (char *) malloc(strlen(dentry->d_name) + 6);
X		strcpy(dname, "/dev/");
X		strcat(dname, dentry->d_name);
X		sres = stat(dname, &dstat);
X		if (sres >= 0
X		    && S_ISBLK(dstat.st_mode)
X		    && maj(dstat.st_rdev) == F_MAJOR) {
X			dp = (struct drive *) malloc(sizeof(struct drive));
X			dp->device = dstat.st_rdev;
X			dp->msize = dstat.st_size / BLOCK_SIZE;
X			dp->name = dname;
X			nlen = strlen(dp->name);
X			if (nlen > max_len) max_len = nlen;
X			dp->dos_type = !strncmp(dentry->d_name, "dos", 3);
X			if (!((dstat.st_rdev >> 2) & 0x1F))
X				dp->is_auto = TRUE;
X			else
X				dp->is_auto = FALSE;
X			add_to_list(drive_list, dp);
X		} else
X			free(dname);	/* no leaks */
X	}
X  }
X  closedir(dd1);
X}				/* make list */
X
X/* Interactive query routine */
Xstruct drive
X*make_selection(list_head)
Xstruct drive *list_head;
X{
X  static char insize[10] = {'\0'};
X  static char choice[5] = {'\0'};
X  struct drive *dp;
X  int i, m, n, minor, drnr, dtype, fbit;
X  dev_t device;
X
X  if (list_head == NULL_L)
X	quit("Use mknod with specific minor devices first", "", OMIT);
X  printf("\nYour floppy drives:\n\n");
X  for (dp = list_head, i = 1;
X       dp != NULL_L;
X       dp = dp->next, i++) {
X	device = dp->device;
X	fbit = device & F_BIT;
X	minor = min(device);
X	drnr = minor & F_DRIVE_BITS;
X	dtype = minor >> 2;
X	msize = dp->msize;
X	if (dp->is_auto) printf(
X		       "Number %2d  %-*s     ? Kb on %4s KB drive %d%s Auto.%s\n",
X		    i, max_len, dp->name, msize ? itoa(msize) : "?",
X		       drnr, dp->dos_type ? " Dos" : "    ",
X		       fbit ? " Fbit" : "");
X	else
X		printf("Number %2d  %-*s  %4d Kb on %4d KB drive %d%s      %s\n",
X		       i, max_len, dp->name, msize, dsize[dtype],
X		       drnr, dp->dos_type ? " Dos" : "    ",
X		       fbit ? " Fbit" : "");
X  }
X  m = i - 1;
X  printf("\nWhich do you wish to format (number)? ");
X  fflush(stdout);
X  fgets(choice, 4, stdin);
X  n = atoi(choice);
X  if (n < 1 || n > m) exit(EXIT_FAILURE);
X  for (dp = list_head, i = 1; i != n && dp != NULL_L; dp = dp->next, i++);
X  msize = dp->msize;
X  if (dp->is_auto) {
X	/* Try to determine the drive type */
X	printf("This is an automatic drive.\n");
X	printf("Format how many Kb (360 720 1200 1440) ? ");
X	fflush(stdout);
X	fgets(insize, 7, stdin);
X	usize = atoi(insize);
X	if (illegal(msize)) {
X		printf("What is the drive size (360 720 1200 1440) ? ");
X		fflush(stdout);
X		fgets(insize, 7, stdin);
X		msize = atoi(insize);
X	}
X  }
X  return(dp);
X}				/* make selection */
X
X/* Check the name and size from the command line */
Xstruct drive
X*command_line_check(dp)
Xstruct drive *dp;
X{
X  struct stat dstat;
X  char *ptr;
X  int fd;
X  int dtype;
X
X  if (dp == NULL_L) usage();	/* at least special */
X
X  /* Check spelling of name for DOS */
X  ptr = (char *) (dp->name + strlen(dp->name));
X  while (*ptr != '/' && ptr > dp->name) ptr--;
X  if (*ptr == '/') ptr++;
X
X  /* Also perhaps there was -v after special name */
X  dp->dos_type = dos_type || !strncmp(ptr, "dos", 3);
X  fd = open(dp->name, O_RDONLY);
X  if (fd < 0) quit("Can't open ", dp->name, OMIT);
X  if (fstat(fd, &dstat) != 0) quit("Can't stat ", dp->name, OMIT);
X  close(fd);
X  if (!S_ISBLK(dstat.st_mode) || maj(dstat.st_rdev) != F_MAJOR)
X	quit("Not a floppy ", dp->name, OMIT);
X  dp->device = dstat.st_rdev;
X  dtype = min(dp->device) >> 2;
X  msize = dp->msize = dstat.st_size / BLOCK_SIZE;
X  if (!usize) usize = msize;
X
X  /* Auto will set device as determined by usize and msize */
X  if (!dtype) {
X	if (!msize) quit("Device size unknown. Mknod with size, ",
X		     dp->name, OMIT);
X	dp->is_auto = TRUE;
X  } else {
X	dp->is_auto = FALSE;
X	if (!msize || msize != usize)
X		quit("Size error, drive is ", itoa(msize), OMIT);
X  }
X  return(dp);
X}				/* command_line_check */
X
X/* Set the values for formatting parameters */
Xvoid set_parameters(dtype)
Xint dtype;
X{
X  param.sec_size_code = (unsigned char) 2;
X  param.sec_per_cyl = sector_table[dtype];	/* sec/cyl */
X  param.gap_fmt = gap_fmt_table[dtype];
X  param.fill_byte = (unsigned char) 0xF6;	/* traditional */
X}
X
X/* Put proper values into the boot block header */
Xvoid adjust_bootblock(dtype, msize)
Xint dtype;
Xint msize;
X{
X  non_boot[0x0D] = sec_cluster[dtype];	/* sec/cluster */
X  non_boot[0x11] = dir_size[dtype];
X  non_boot[0x13] =
X	(unsigned char) ((msize * (BLOCK_SIZE / SEC_SIZE)) % 256);
X  non_boot[0x14] =
X	(unsigned char) ((msize * (BLOCK_SIZE / SEC_SIZE)) / 256);
X  non_boot[0x15] = media_id[dtype];	/* media id. */
X  non_boot[0x16] = sec_fat[dtype];	/* sec/fat */
X  non_boot[0x18] = sector_table[dtype];	/* sec/cyl */
X}
X
X/* See if drive is already mounted by any name. */
Xint mounted(dname)
Xchar *dname;
X{
X  int n, ddrive, mdrive;
X  struct stat dstat, mstat;
X#ifdef _V15_
X  FILE *fp;
X  char line[60],mname[20];
X#else
X  char mdevice[PATH_MAX + 1], mounted[PATH_MAX + 1], vers[5], flag[15];
X#endif
X  /* Device may be mounted under a pseudonym */
X  stat(dname, &dstat);
X  ddrive = dstat.st_rdev & F_DRIVE_BITS;
X#ifdef _V15_
X  if((fp = fopen("/etc/mtab","r")) == (FILE *) NULL) return(FAIL_MOUNTED);
X  while (TRUE) {
X      fgets(line,59,fp);
X      if(feof(fp)) break;
X      sscanf(line,"%s",mname);
X      stat(mname,&mstat);
X	if (maj(mstat.st_rdev) != F_MAJOR) continue;
X	mdrive = mstat.st_rdev & F_DRIVE_BITS;
X	if (ddrive == mdrive)
X		quit("Won't format, drive is mounted as ", mname, OMIT);
X  }
X  fclose(fp);
X  return(NOT_MOUNTED);
X#else
X  if (load_mtab(progname) < 0) return(FAIL_MOUNTED);
X  while (TRUE) {
X	n = get_mtab_entry(mdevice, mounted, vers, flag);
X	if (n < 0) return(NOT_MOUNTED);
X	stat(mdevice, &mstat);
X	if (maj(mstat.st_rdev) != F_MAJOR) continue;
X	mdrive = mstat.st_rdev & F_DRIVE_BITS;
X	if (ddrive == mdrive)
X		quit("Won't format, drive is mounted as ", mdevice, OMIT);
X  }
X#endif
X}
X
Xvoid Sigint(s)
Xint s;
X{
X  interrupt = SIGINT;
X}
X
X
Xvoid Sigquit(s)
Xint s;
X{
X  interrupt = SIGQUIT;
X}
X
X
X/* Make a temporary formatting node.  It will be deleted after use. */
Xvoid prepare_node(device)
Xdev_t device;
X{
X  int fd, mres;
X  struct stat dstat;
X  char *ptr;
X
X  /* Make a temporary name. Chop progname of excessive renaming. */
X  ptr = (char *) progname + strlen(progname);
X  while (*ptr != '/' && ptr > progname) ptr--;
X  if (*ptr == '/') ptr++;	/* Elide path */
X  nname = (char *) malloc(strlen(ptr) < 8 ? strlen(ptr) + 12 : 20);
X  strcpy(nname, "/tmp/");
X  strncat(nname, ptr, 8);
X  strcat(nname, "XXXXXX");
X  mktemp(nname);
X  mres = mknod4(nname, S_IFBLK|S_IWUSR|S_IRUSR, device | F_BIT, (long) msize);
X  if (mres) quit("Can't make temporary node ", nname, OMIT);
X
X  /* As a pre-check open and stat the node */
X  fd = open(nname, O_WRONLY | O_EXCL);
X  if (fd < 0) quit("Can't open temporary node ", nname, UNLINK);
X  if (fstat(fd, &dstat) != 0) {
X	close(fd);
X	quit("Can't stat temporary node ", nname, UNLINK);
X  }
X  close(fd);
X}				/* prepare_node */
X
X/* Format one track */
Xint format_track(cyl, head, logical)
Xint cyl, head, logical;
X{
X  int errnum = 0;
X  int physical;
X  off_t cyl_start;
X  int fd;
X
X  /* Setup to do one head */
X  memset(u.buffer, 0, BLOCK_SIZE);
X  u.p.param = param;
X  for (physical = 0; physical <= param.sec_per_cyl; ++physical) {
X	u.p.table[physical].cyl = (unsigned char) cyl;
X	u.p.table[physical].head = (unsigned char) head;
X	u.p.table[physical].sector = (unsigned char) (physical + 1);
X	u.p.table[physical].sec_size_code = param.sec_size_code;
X  }
X
X  /* Need to set only the cylinder and head for the drive with a seek.
X   * Close enough: */
X  cyl_start = (((off_t) logical) / 2) * 2 * SEC_SIZE;
X  if ((fd = open(nname, O_WRONLY)) < 0) errnum |= FAIL_OPEN;
X  if (lseek(fd, cyl_start, SEEK_SET) != cyl_start) {
X	printf("Seek error: cyl %d head %d.\n", cyl, head);
X	errnum |= FAIL_SEEK;
X  }
X  if (write(fd, u.buffer, (unsigned) BLOCK_SIZE) != BLOCK_SIZE) {
X	printf("Write error: cyl %d head %d.\n", cyl, head);
X	errnum |= FAIL_WRITE;
X  }
X  close(fd);			/* Don't need sync. This will do. */
X  return(errnum);
X}				/* format_track */
X
X/* Format all of the tracks on the disk */
Xint full_format()
X{
X  int cyl;
X  int head;
X  int logical;
X  int errnum = 0;
X  int tries;
X
X  for (cyl = 0, logical = 1; cyl <= max_cyl && !errnum; cyl++) {
X	/* Check for interrupt */
X	if (interrupt) quit("Interrupted..", "", UNLINK);
X
X	/* Go ahead and do both heads  */
X	for (head = 0; head < NR_HEADS && !errnum; ++head) {
X		printf("\r%s: Cyl. %2d, Head %1d.  ", progname, cyl, head);
X		fflush(stdout);
X		tries = 0;
X		errnum = format_track(cyl, head, logical);
X
X		/* Were FS slots busy for other processes? */
X		while (errnum & FAIL_OPEN && tries++ < MAX_TRIES) {
X			printf("Retry: cyl %d head %d.\n", cyl, head);
X			fflush(stdout);
X			if (interrupt) quit("Interrupted..", "", UNLINK);
X			sleep(1);
X			errnum = format_track(cyl, head, logical);
X		}
X		logical += param.sec_per_cyl;
X	}			/* for head */
X  }				/* for  cyl */
X  return(errnum);
X}				/* full_format */
X
X/* Put label and date in directory for Dos */
Xint add_vol_label(fd)
Xint fd;
X{
X  char *c;
X  time_t now;
X  struct tm *local;
X
X  /* Use a different label next time */
X  if (v_flag) v_flag = -1;
X
X  /* Massage and pad the volume label */
X  vol_temp[11] = '\0';		/* Guard */
X  c = vol_temp;
X  while (*c != '\0') {
X	if (*c == '\n' || *c == '\r') {
X		*c = '\0';
X		break;
X	} else if (!isalpha(*c) && !isdigit(*c) && *c != '.')
X		*c = '_';
X	else if (islower(*c))
X		*c = toupper(*c);
X	c++;
X  }
X  if (strlen(vol_temp) < VEL_SIZE)
X	strncat(vol_temp, BLANKS, VEL_SIZE - strlen(vol_temp));
X  strncpy(vol_entry.label, vol_temp, sizeof(vol_entry.label));
X  vol_entry.attrib = VOL_ARC;
X  time(&now);
X  local = localtime(&now);
X  vol_entry.date = (local->tm_year - DOS_BASE_YEAR) << Y_SHIFT;
X  vol_entry.date += (local->tm_mon + 1) << MON_SHIFT;
X  vol_entry.date += local->tm_mday;
X  vol_entry.time = (local->tm_hour) << H_SHIFT;
X  vol_entry.time += (local->tm_min) << MIN_SHIFT;
X  vol_entry.time += local->tm_sec / SEC_DIV;
X  if (lseek(fd, dir_start, SEEK_SET) != dir_start) return(FAIL_DVOL);
X  if (write(fd, (char *) &vol_entry, VE_SIZE) != VE_SIZE) return (FAIL_DVOL);
X  return(0);			/* No errors, errnum == 0  */
X}				/* add_vol_label */
X
X/* Add the structures Dos needs to the disk. */
Xint add_structures(dname, device)
Xchar *dname;
Xdev_t device;
X{
X  int fd;
X  int errnum;
X  off_t dos_position;
X  off_t to_do;
X  int written;
X  int do_label;
X
X  /* If special has format bit set it can't write normally */
X  if (device & F_BIT)
X	quit("Format Bit Set, Can't add structures Dos needs, rm ",
X	     dname, UNLINK);
X  printf("\nAdding structures Dos needs.  ");
X  if (interactive || v_flag < 0) {
X	printf("\nEnter Volume Label (11 or less) : ");
X	fflush(stdout);
X	fgets(vol_temp, 19, stdin);
X	if (vol_temp[0] == '\n')
X		do_label = FALSE;
X	else
X		do_label = TRUE;
X	printf("\n");
X  }
X  if ((fd = open(dname, O_WRONLY)) < 0)
X	quit("Can't open to write structures Dos needs ",
X	     dname, UNLINK);
X
X  /* Write the boot block */
X  if (lseek(fd, (off_t) 0, SEEK_SET) != (off_t) 0) return(FAIL_D0);
X  dos_position = write(fd, (char *) non_boot, BOOT_SIZE);
X  if (dos_position != (off_t) BOOT_SIZE) return(FAIL_D0);
X
X  /* Round out the first block, then zero enough of them */
X  memset(u.buffer, 0, BLOCK_SIZE);
X  to_do = (off_t) BLOCK_SIZE - dos_position;
X  while (to_do > (off_t) 0) {
X	if (interrupt) quit("Interrupted..", "", UNLINK);
X	written = write(fd, u.buffer, (int) to_do);
X	if (written != (int) to_do) return(FAIL_DCLEAR);
X	dos_position += written;
X	/* Do whole blocks */
X	to_do = dir_max - dos_position;
X	if (to_do > (off_t) BLOCK_SIZE) to_do = (off_t) BLOCK_SIZE;
X  }
X
X  /* Add volume label and date */
X  if (do_label || v_flag > 0) {
X	errnum = add_vol_label(fd);
X	if (errnum) return(errnum);
X  }
X  if (second_fat) {
X	dos_position = lseek(fd, second_fat, SEEK_SET);
X	if (dos_position != second_fat) return(FAIL_DFAT2);
X	written = write(fd, (char *) &f_bytes[2], FAT_SIZE);
X	if (written != FAT_SIZE) return(FAIL_DFAT2);
X  }
X
X  /* Do DOS magic number and first fat */
X  dos_position = lseek(fd, (off_t) MAGIC_LOC, SEEK_SET);
X  if (dos_position != (off_t) MAGIC_LOC) return(FAIL_DFAT1);
X  written = write(fd, (char *) f_bytes, MAGIC_SIZE);
X  if (written != MAGIC_SIZE) return(FAIL_DFAT1);
X  close(fd);			/* close dos structure device */
X  return(NO_FAILURE);
X}				/* add_structures */
X
X/* Try to read block 0 from the disk */
Xint test_error(dname)
Xchar *dname;
X{
X  int fd;
X  if ((fd = open(dname, O_RDONLY)) < 0) return(TRUE);
X  if (lseek(fd, (off_t) 0, SEEK_SET) != (off_t) 0) {
X	close(fd);
X	return(TRUE);
X  }
X  if (read(fd, u.buffer, BLOCK_SIZE) != BLOCK_SIZE) {
X	close(fd);
X	return(TRUE);
X  }
X  close(fd);
X  return(FALSE);
X}
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[]; {
X
X  int q_flag = FALSE;
X  char *dname;
X  static char answer[4] = {'n'};
X  struct drive *dp = NULL_L;
X  struct drive *drive_list = NULL_L;
X  int is_auto = FALSE;
X  dev_t device;
X  int minor, dtype, drnr;
X  int i, errnum;
X
X  progname = argv[0];		/* this became a variable */
X
X/* Su should decide who is allowed to format. Normally only su should format.
X * Plucky su's could suid it however...
X */
X  if (geteuid() != 0) quit("Must be su to format", "", OMIT);
X
X  /* Normally only from the console. */
X  if (strcmp(ttyname(0), CONSOLE)) {
X	/* Suid'ed user must be at console. */
X	if (getuid() != 0) quit("Only from the console", "", OMIT);
X	/* Su can make big mistakes. :-) */
X  }
X
X  /* Get command line parameters if there are some. */
X  for (i = 1; i < argc; i++) {
X	if (argv[i][0] == '-') {
X		if (argv[i][1] == 'v') {
X			dos_type = TRUE;
X			if (argc - 1 - i > 0) {
X				v_flag = i + 1;
X				strncpy(vol_temp, argv[v_flag], 11);
X				i++;
X			} else
X				v_flag = -1;
X		}
X		if (argv[i][1] == 'q') q_flag = TRUE;
X		if (argv[i][1] == 'a') a_flag = TRUE;
X	} else if (isdigit(argv[i][0])) {
X		interactive = FALSE;
X		msize = usize = atoi(argv[i]);
X	} else if (isalpha(argv[i][0]) ||
X		   argv[i][0] == '/' ||
X		   argv[i][0] == '.') {
X		/* Name or path */
X		interactive = FALSE;
X		if (dp != NULL_L) free(dp);
X		dp = (struct drive *) malloc(sizeof(struct drive));
X		dp->name = (char *) malloc(strlen(argv[i]) + 1);
X		strcpy(dp->name, argv[i]);
X	} else
X		usage();
X  }
X
X  if (interactive) {
X	make_list(&drive_list);
X	dp = make_selection(drive_list);
X  } else
X	dp = command_line_check(dp);
X
X  if (illegal(msize)) quit("Can't do drive size ", itoa(msize), OMIT);
X
X  if (dp->is_auto) {
X	is_auto = TRUE;
X	if (illegal(usize)) quit("Can't do size ", itoa(usize), OMIT);
X	dtype = dtype_map[usize / 360 - 1][msize / 360 - 1];
X	if (dtype == -1) quit("Invalid size for drive ", dp->name, OMIT);
X	dp->device |= (dtype << 2);
X	msize = dp->msize = usize;
X  }
X  device = dp->device;
X  minor = min(device);
X  drnr = minor & F_DRIVE_BITS;
X  dtype = minor >> 2;
X  dos_type = dp->dos_type || v_flag;
X  dname = dp->name;
X
X  set_parameters(dtype);
X
X  max_cyl = cyl_table[dtype];
X
X  if (dos_type) {
X	adjust_bootblock(dtype, msize);
X	f_bytes[2] = non_boot[0x15];	/* media id. for fat */
X	second_fat = SEC_SIZE *
X		(unsigned int) non_boot[0x16] + SEC_SIZE;
X	dir_start = (off_t) non_boot[0x16] * SEC_SIZE + second_fat;
X	dir_max = (off_t) non_boot[0x11] * DIRENT_SIZE + dir_start;
X  }
X
X  /* Check /etc/mtab */
X  if (mounted(dname)) exit(EXIT_FAILURE);
X
X  /* Trap interrupts to allow cleanup of temporary node */
X  if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
X	signal(SIGINT, Sigint);
X	signal(SIGQUIT, Sigquit);
X  }
X  prepare_node(device);
X
X  if (interactive)
X	printf("%s  %s%4d Kb on %4d Kb %sdrive %d (cyl 0-%d, sec 1-%d)\n",
X	       dname, dos_type ? "Dos " : "", msize,
X	       dsize[dtype], is_auto ? "Auto. " : "", drnr,
X	       max_cyl, param.sec_per_cyl);
X
X  if (interactive || !q_flag) {
X	printf("Are you sure (y/n) ? ");
X	fflush(stdout);
X	fgets(answer, 3, stdin);
X	if (answer[0] != 'y') {
X		unlink(nname);
X		exit(EXIT_FAILURE);
X	}
X	printf("\n");
X  }
X  do {				/* While answer == 'y' */
X
X	errnum = full_format();
X	if (errnum) quit("Format errors on ", dname, UNLINK);
X
X	if (test_error(dname))
X		quit("Wrong media? Format failed on ", dname, UNLINK);
X
X	if (dos_type) {
X		errnum = add_structures(dname, device);
X		if (errnum) quit("Failed to add structures Dos needs, ",
X			     itoa(errnum), UNLINK);
X	}
X	if (interactive || !q_flag) {
X		printf("\nAnother %s%d Kb on drive %d (y/n) ? ",
X		       dos_type ? "Dos Disk " : "", msize, drnr);
X		fflush(stdout);
X		fgets(answer, 3, stdin);
X	} else {
X		printf("\n");
X		answer[0] = 'n';
X	}
X  } while (answer[0] == 'y');
X  unlink(nname);
X  exit(EXIT_SUCCESS);
X}
/
echo x - ncc.c
sed '/^X/s///' > ncc.c << '/'
X/*	Driver for Minix compilers.
X	Written june 1987 by Ceriel J.H. Jacobs, partly derived from old
X	cc-driver, written by Erik Baalbergen.
X	This driver is mostly table-driven, the table being in the form of
X	some global initialized structures.
X*/
X/* $Header: cc.c,v 1.35 91/04/12 15:33:50 ceriel Exp $ */
X
X#include <sys/types.h>
X#include <sys/wait.h>
X#include <errno.h>
X#include <signal.h>
X#include <string.h>
X#include <stdlib.h>
X#include <fcntl.h>
X#include <unistd.h>
X
X#ifdef RAMDISK
X/* Everything is located in /lib instead of /usr/lib. */
X#define SHELL		"/bin/sh"
X#define PP		"/lib/ncpp"
X#define IRREL		"/lib/irrel"
X#define CEM		"/lib/ncem"
X#define M2EM		"/lib/nm2em"
X#define OPT		"/lib/nopt"
X#define CG		"/lib/ncg"
X#define AS		"/bin/as"
X#define LD		"/lib/ld"
X#define CV		"/lib/cv"
X#define LIBDIR		"/lib"
X#define CRT		"/lib/ncrtso.o"
X#define PEM		"/usr/lib/npem"
X#define PRT		"/usr/lib/nprtso.o"
X#define M2RT		"/usr/lib/nm2rtso.o"
X#define LIBC            "/lib/libd.A", "/usr/lib/libc.A"
X#define LIBP		"/usr/lib/libp.A", "/usr/lib/libc.A"
X#define LIBM2		"/usr/lib/libm2.A", "/usr/lib/libc.A"
X#define END             "/lib/libe.A", "/usr/lib/end.A"
X#define M2DEF		"-I/usr/lib/m2"
X#else 
X/* Use /usr/lib */
X#define SHELL		"/bin/sh"
X#define PP		"/usr/lib/ncpp"
X#define IRREL		"/usr/lib/irrel"
X#define CEM		"/usr/lib/ncem"
X#define M2EM		"/usr/lib/nm2em"
X#define OPT		"/usr/lib/nopt"
X#define CG		"/usr/lib/ncg"
X#define AS		"/usr/bin/as"
X#define LD		"/usr/lib/ld"
X#define CV		"/usr/lib/cv"
X#define LIBDIR		"/usr/lib"
X#define CRT		"/usr/lib/ncrtso.o"
X#define PEM		"/usr/lib/npem"
X#define PRT		"/usr/lib/nprtso.o"
X#define M2RT		"/usr/lib/nm2rtso.o"
X#define LIBC            "/usr/lib/libd.A", "/usr/lib/libc.A"
X#define LIBP		"/usr/lib/libp.A", "/usr/lib/libc.A"
X#define LIBM2		"/usr/lib/libm2.A", "/usr/lib/libc.A"
X#define END             "/usr/lib/libe.A", "/usr/lib/end.A"
X#define M2DEF		"-I/usr/lib/m2"
X#endif
X
X
X/*	every pass that this program knows about has associated with it
X	a structure, containing such information as its name, where it
X	resides, the flags it accepts, and the like.
X*/
Xstruct passinfo {
X	char *p_name;		/* name of this pass */
X	char *p_path;		/* where is it */
X	char *p_from;		/* suffix of source (comma-separated list) */
X	char *p_to;		/* suffix of destination */
X	char *p_acceptflags;	/* comma separated list; format:
X			   		flag
X			   		flag*
X			   		flag=xxx
X					flag*=xxx[*]
X				   where a star matches a, possibly empty, 
X				   string
X				*/
X	int  p_flags;
X#define INPUT	01		/* needs input file as argument */
X#define OUTPUT	02		/* needs output file as argument */
X#define LOADER	04		/* this pass is the loader */
X#define STDIN	010		/* reads from standard input */
X#define STDOUT	020		/* writes on standard output */
X#define NOCLEAN	040		/* do not remove target if this pass fails */
X#define O_OUTPUT 0100		/* -o outputfile, hack for as */
X#define PREPALWAYS	0200	/* always to be preprocessed */
X#define PREPCOND	0400	/* preprocessed when starting with '#' */
X};
X
X#define MAXHEAD	6
X#define MAXTAIL	6
X#define MAXPASS	7
X
X/*	Every language handled by this program has a "compile" structure
X	associated with it, describing the start-suffix, how the driver for
X	this language is called, which passes must be called, which flags
X	and arguments must be passed to these passes, etc.
X	The language is determined by the suffix of the argument program.
X	However, if this suffix does not determine a language (DEFLANG),
X	the callname is used.
X	Notice that the 's' suffix does not determine a language, because
X	the input file could have been derived from f.i. a C-program.
X	So, if you use "cc x.s", the C-runtime system will be used, but if
X	you use "as x.s", it will not.
X*/
Xstruct compile {
X	char *c_suffix;		/* starting suffix of this list of passes */
X	char *c_callname;	/* affects runtime system loaded with program */
X	struct pass {
X		char *pp_name;		/* name of the pass */
X		char *pp_head[MAXHEAD];	/* args in front of filename */
X		char *pp_tail[MAXTAIL];	/* args after filename */
X	} c_passes[MAXPASS];
X	int  c_flags;
X#define DEFLANG		010	/* this suffix determines a language */
X};
X
Xstruct passinfo passinfo[] = {
X	{ "cpp", PP, 0, "i", "wo=o,I*,D*,U*", INPUT|STDOUT },
X	{ "irrel", IRREL, "i", "i", "", INPUT},
X	{ "cem", CEM, "i,c", "k", "m,p,wa=a,wo=o,ws=s,w,T*", INPUT|OUTPUT|PREPALWAYS },
X	{ "pc", PEM, "i,p", "k", "n=L,w,a,A,R", INPUT|OUTPUT|PREPCOND },
X	{ "m2", M2EM, "i,mod", "k", "n=L,w*,A,R,W*,3,I*", INPUT|OUTPUT|PREPCOND },
X	{ "opt", OPT, "k", "m", "", STDIN|STDOUT },
X	{ "cg", CG, "m", "s", "O=p4", INPUT|OUTPUT },
X	{ "as", AS, "i,s", "o", "T*", INPUT|O_OUTPUT|PREPCOND },
X	{ "ld", LD, "o", "out", "i,s", INPUT|LOADER },	/* changed */
X	{ "cv", CV, "out", 0, "", INPUT|OUTPUT|NOCLEAN },	/* must come after loader */
X	{ 0}
X};
X
X#define	PREP_FLAGS	"-D_EM_WSIZE=2", "-D_EM_PSIZE=2", "-D_EM_LSIZE=4" \
X			, "-D__ACK__"
X
Xstruct pass preprocessor = { "cpp",
X			    { PREP_FLAGS }
X			    , {0}
X			    };
X
Xstruct pass irrel = { "irrel",
X			    {0}
X			};
X
X/* The "*" in the arguments for the loader indicates the place where the
X * fp-emulation library should come.
X */
Xstruct compile passes[] = {
X{	"c", "cc", 
X	{	{ "cem", {"-L"}, {0} },	/* changed */
X		{ "opt", {0}, {0} },
X		{ "cg", {0}, {0} },
X		{ "as", {"-"}, {0} },
X		{ "ld", {CRT}, /* changed */
X			  {LIBC, "*",  END}},
X		{ "cv", {0}, {0} }
X	},
X	DEFLANG
X},
X{	"p", "pc",
X	{	{ "pc", {0}, {0} },
X		{ "opt", {0}, {0} },
X		{ "cg", {0}, {0} },
X		{ "as", {"-"}, {0} },
X		{ "ld", {PRT}, 
X			  {LIBP,
X			    "*", END}},
X		{ "cv", {0}, {0} }
X	},
X	DEFLANG
X},
X{	"mod", "m2",
X	{	{ "m2", {M2DEF}, {0} },
X		{ "opt", {0}, {0} },
X		{ "cg", {0}, {0} },
X		{ "as", {"-"}, {0} },
X		{ "ld", {M2RT}, 
X			  {LIBM2,
X			    "*", END}},
X		{ "cv", {0}, {0} }
X	},
X	DEFLANG
X},
X{	"s", "as",
X	{	{ "as", {0}, {0}}}, 0 },
X{	0}
X};
X
X#define MAXARGC	150	/* maximum number of arguments allowed in a list */
X#define USTR_SIZE	64	/* maximum length of string variable */
X
Xtypedef char USTRING[USTR_SIZE];
X
Xstruct arglist {
X	int al_argc;
X	char *al_argv[MAXARGC];
X};
X
Xstruct arglist CALLVEC;
X
Xint kids = -1;
X
Xchar *o_FILE = "a.out"; /* default name for executable file */
X
X#define init(a)		((a)->al_argc = 1)
X#define cleanup(str)		(str && remove(str))
X
Xchar *ProgCall = 0;
X
Xint RET_CODE = 0;
X
Xchar *stopsuffix;
Xint m_flag = 0;
Xint v_flag = 0;
Xint t_flag = 0;
Xint noexec = 0;
Xint fp_lib = 0;
X
X
XUSTRING curfil;
XUSTRING newfil;
Xstruct arglist SRCFILES;
Xstruct arglist LDIRS;
Xstruct arglist LDFILES;
Xstruct arglist GEN_LDFILES;
Xstruct arglist FLAGS;
X
Xchar *tmpdir = "/tmp";
Xchar tmpname[64];
X
Xstruct compile *compbase;
Xstruct pass *loader;
Xstruct passinfo *loaderinfo;
Xchar *source;
Xint maxLlen;
X
X_PROTOTYPE(char *library, (char *nm ));
X_PROTOTYPE(void trapcc, (int sig ));
X_PROTOTYPE(int main, (int argc, char *argv []));
X_PROTOTYPE(int remove, (char *str ));
X_PROTOTYPE(char *alloc, (unsigned u ));
X_PROTOTYPE(int append, (struct arglist *al, char *arg ));
X_PROTOTYPE(int concat, (struct arglist *al1, struct arglist *al2 ));
X_PROTOTYPE(char *mkstr, (char *dst, char *arg1, char *arg2, char *arg3 ));
X_PROTOTYPE(int basename, (char *str, char *dst ));
X_PROTOTYPE(char *extension, (char *fln ));
X_PROTOTYPE(int runvec, (struct arglist *vec, struct passinfo *pass, char *in, char *out ));
X_PROTOTYPE(int prnum, (unsigned x ));
X_PROTOTYPE(int prs, (char *str ));
X_PROTOTYPE(int panic, (char *str ));
X_PROTOTYPE(int pr_vec, (struct arglist *vec ));
X_PROTOTYPE(int ex_vec, (struct arglist *vec ));
X_PROTOTYPE(int mktempname, (char *nm ));
X_PROTOTYPE(int mkbase, (void));
X_PROTOTYPE(int mkloader, (void));
X_PROTOTYPE(int needsprep, (char *name ));
X_PROTOTYPE(int cfile, (char *name ));
X_PROTOTYPE(char *apply, (struct passinfo *pinf, struct compile *cp, char *name, int passindex, int noremove, int first, char *resultname ));
X_PROTOTYPE(int applicable, (struct passinfo *pinf, char *suffix ));
X_PROTOTYPE(char *process, (char *name, int noremove ));
X_PROTOTYPE(int mkvec, (struct arglist *call, char *in, char *out, struct pass *pass, struct passinfo *pinf ));
X_PROTOTYPE(int callld, (struct arglist *in, char *out, struct pass *pass, struct passinfo *pinf ));
X_PROTOTYPE(int clean, (struct arglist *c ));
X_PROTOTYPE(int scanflags, (struct arglist *call, struct passinfo *pinf ));
X
X
X
Xchar *
Xlibrary(nm)
X	char	*nm;
X{
X	static char	f[512];
X	int	Lcount;
X
X	for (Lcount = 0; Lcount < LDIRS.al_argc; Lcount++) {
X		mkstr(f, LDIRS.al_argv[Lcount], "/lib", nm);
X		strcat(f, ".A");
X		if (access(f, 0) != 0) {
X			f[strlen(f)-1] = 'a';
X			if (access(f, 0) != 0) continue;
X		}
X		return f;
X	}
X	mkstr(f, LIBDIR, "/lib", nm);
X	strcat(f, ".A");
X	if (access(f, 0) != 0) {
X		int i = strlen(f) - 1;
X		f[i] = 'a';
X		if (access(f, 0) != 0) f[i] = 'A';
X	}
X	return f;
X}
X
Xvoid trapcc(sig)
X	int sig;
X{
X	signal(sig, SIG_IGN);
X	if (kids != -1) kill(kids, sig);
X	cleanup(newfil);
X	cleanup(curfil);
X	exit(1);
X}
X
Xmain(argc, argv)
X	char *argv[];
X{
X	char *str;
X	char **argvec;
X	int count;
X	char *file;
X
X	maxLlen = strlen(LIBDIR);
X	ProgCall = *argv++;
X
X	mkbase();
X
X	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
X		signal(SIGHUP, trapcc);
X	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
X		signal(SIGINT, trapcc);
X	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
X		signal(SIGQUIT, trapcc);
X	while (--argc > 0) {
X		if (*(str = *argv++) != '-') {
X			append(&SRCFILES, str);
X			continue;
X		}
X
X		switch (str[1]) {
X
X		case 'c':
X			stopsuffix = "o";
X			break;
X		case 'f':
X			fp_lib = 1;
X			break;
X		case 'F':
X			break;
X		case 'L':
X			append(&LDIRS, &str[2]);
X			count = strlen(&str[2]);
X			if (count > maxLlen) maxLlen = count;
X			break;
X		case 'l':
X			append(&SRCFILES, library(&str[2]));
X			break;
X		case 'm':
X			m_flag++;
X			break;
X		case 'o':
X			if (argc-- >= 0)
X				o_FILE = *argv++;
X			break;
X		case 'S':
X			stopsuffix = "s";
X			break;
X		case 'v':
X			v_flag++;
X			if (str[2] == 'n')
X				noexec = 1;
X			break;
X		case 't':
X			/* save temporaries */
X			t_flag++;
X			break;
X		case 'r':
X			/* no runtime start-off */
X			loader->pp_head[0] = 0;
X			break;
X		case 'T':
X			tmpdir = &str[2];
X			/*FALLTHROUGH*/
X		default:
X			append(&FLAGS, str);
X
X		}
X	}
X
X	mktempname(tmpname);
X
X	count = SRCFILES.al_argc;
X	argvec = &(SRCFILES.al_argv[0]);
X
X	while (count-- > 0) {
X
X		file = *argvec++;
X		source = file;
X
X		if (SRCFILES.al_argc > 1) {
X			write(1, file, strlen(file));
X			write(1, ":\n", 2);
X		}
X
X		file = process(file, 1);
X	
X		if (file && ! stopsuffix) append(&LDFILES, file);
X	}
X
X	clean(&SRCFILES);
X
X	/* loader ... */
X	if (RET_CODE == 0 && LDFILES.al_argc > 0) {
X		register struct passinfo *pp = passinfo;
X
X		while (!(pp->p_flags & LOADER)) pp++;
X		mkstr(newfil, tmpname, pp->p_to, "");
X		callld(&LDFILES, !((pp+1)->p_name) ? o_FILE : newfil, loader, pp);
X		if (RET_CODE == 0) {
X			register int i = GEN_LDFILES.al_argc;
X
X			while (i-- > 0) {
X				remove(GEN_LDFILES.al_argv[i]);
X				free(GEN_LDFILES.al_argv[i]);
X			}
X			if ((++pp)->p_name) {
X				process(newfil, 0);
X			}
X		}
X	}
X	exit(RET_CODE);
X}
X
Xremove(str)
X	char *str;
X{
X	if (t_flag)
X		return;
X	if (v_flag) {
X		prs("rm ");
X		prs(str);
X		prs("\n");
X	}
X	if (noexec)
X		return;
X	unlink(str);
X}
X
Xchar *
Xalloc(u)
X	unsigned u;
X{
X	register char *p = malloc(u);
X
X	if (p == 0) panic("no space\n");
X	return p;
X}
X
Xappend(al, arg)
X	struct arglist *al;
X	char *arg;
X{
X	char *a = alloc((unsigned) (strlen(arg) + 1));
X
X	strcpy(a, arg);
X	if (al->al_argc >= MAXARGC)
X		panic("argument list overflow\n");
X	al->al_argv[(al->al_argc)++] = a;
X}
X
Xconcat(al1, al2)
X	struct arglist *al1, *al2;
X{
X	register i = al2->al_argc;
X	register char **p = &(al1->al_argv[al1->al_argc]);
X	register char **q = &(al2->al_argv[0]);
X
X	if ((al1->al_argc += i) >= MAXARGC)
X		panic("argument list overflow\n");
X	while (i-- > 0)
X		*p++ = *q++;
X}
X
Xchar *
Xmkstr(dst, arg1, arg2, arg3)
X	char *dst, *arg1, *arg2, *arg3;
X{
X	register char *p;
X	register char *q = dst;
X
X	p = arg1;
X	while (*q++ = *p++);
X	q--;
X	p = arg2;
X	while (*q++ = *p++);
X	q--;
X	p = arg3;
X	while (*q++ = *p++);
X	q--;
X	return dst;
X}
X
Xbasename(str, dst)
X	char *str;
X	register char *dst;
X{
X	register char *p1 = str;
X	register char *p2 = p1;
X
X	while (*p1)
X		if (*p1++ == '/')
X			p2 = p1;
X	p1--;
X	while (*p1 != '.' && p1 > p2) p1--;
X	if (*p1 == '.') {
X		*p1 = '\0';
X		while (*dst++ = *p2++);
X		*p1 = '.';
X	}
X	else
X		while (*dst++ = *p2++);
X}
X
Xchar *
Xextension(fln)
X	char *fln;
X{
X	register char *fn = fln;
X
X	while (*fn) fn++;
X	while (fn > fln && *fn != '.') fn--;
X	if (fn != fln) return fn+1;
X	return (char *)0;
X}
X
Xrunvec(vec, pass, in, out)
X	struct arglist *vec;
X	struct passinfo *pass;
X	char *in, *out;
X{
X	int pid, status;
X
X#ifndef MYDEBUG
X	int shifted = 0;
X	if (
X		strncmp(vec->al_argv[1], "/usr/", 5) == 0
X		&&
X		access(vec->al_argv[1] + 4, 1) == 0
X	) {
X		vec->al_argv[1] += 4;
X		shifted = 1;
X	}
X#endif
X	if (v_flag) {
X		pr_vec(vec);
X		if (pass->p_flags & STDIN) {
X			prs(" <");
X			prs(in);
X		}
X		if (pass->p_flags & STDOUT) {
X			prs(" >");
X			prs(out);
X		}
X		prs("\n");
X	}
X	if (noexec) {
X#ifndef MYDEBUG
X		if (shifted) vec->al_argv[1] -= 4;
X#endif
X		clean(vec);
X		return 1;
X	}
X	if ((pid = fork()) == 0) {	/* start up the process */
X		if (pass->p_flags & STDIN) { /* redirect standard input */
X			close(0);
X			if (open(in, 0) != 0)
X				panic("cannot open input file\n");
X		}
X		if (pass->p_flags & STDOUT) { /* redirect standard output */
X			close(1);
X			if (creat(out, 0666) != 1)
X				panic("cannot create output file\n");
X		}
X		ex_vec(vec);
X	}
X	if (pid == -1)
X		panic("no more processes\n");
X	kids = pid;
X	wait(&status);
X	if (status) switch(status & 0177) {
X	case SIGHUP:
X	case SIGINT:
X	case SIGQUIT:
X	case SIGTERM:
X	case 0:
X		break;
X	default:
X		prs(vec->al_argv[1]);
X		prs(" died with signal ");
X		prnum(status & 0177);
X		prs("\n");
X	}
X#ifndef MYDEBUG
X	if (shifted) vec->al_argv[1] -= 4;
X#endif
X	clean(vec);
X	kids = -1;
X	return status ? ((RET_CODE = 1), 0) : 1;
X}
X
Xprnum(x)
X	register unsigned x;
X{
X	static char numbuf[8];			/* though it prints at most 3 characters */
X	register char *cp = numbuf + sizeof(numbuf) - 1;
X
X	*cp = '\0';
X	while (x >= 10) {
X		*--cp = (x % 10) + '0';
X		x /= 10;
X	}
X	*--cp = x + '0';
X	prs(cp);
X
X}
X
Xprs(str)
X	char *str;
X{
X	if (str && *str)
X		write(2, str, strlen(str));
X}
X
Xpanic(str)
X	char *str;
X{
X	prs(str);
X	trapcc(SIGINT);
X}
X
Xpr_vec(vec)
X	register struct arglist *vec;
X{
X	register char **ap = &vec->al_argv[1];
X	
X	vec->al_argv[vec->al_argc] = 0;
X	prs(*ap);
X	while (*++ap) {
X		prs(" ");
X		if (strlen(*ap))
X			prs(*ap);
X		else
X			prs("(empty)");
X	}
X}
X
Xex_vec(vec)
X	register struct arglist *vec;
X{
X	extern int errno;
X
X	vec->al_argv[vec->al_argc] = 0;
X	execv(vec->al_argv[1], &(vec->al_argv[1]));
X	if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
X		vec->al_argv[0] = SHELL;
X		execv(SHELL, &(vec->al_argv[0]));
X	}
X	if (access(vec->al_argv[1], 1) == 0) {
X		/* File is executable. */
X		prs("Cannot execute ");
X		prs(vec->al_argv[1]);
X		prs(". Not enough memory.\n");
X		prs("Use chmem to reduce its stack allocation\n");
X	} else {
X		prs(vec->al_argv[1]);
X		prs(" is not executable\n");
X	}
X	exit(1);
X}
X
Xmktempname(nm)
X	register char *nm;
X{
X	register int i;
X	register int pid = getpid();
X
X	mkstr(nm, tmpdir, "/", compbase->c_callname);
X	while (*nm) nm++;
X
X	for (i = 9; i > 3; i--) {
X		*nm++ = (pid % 10) + '0';
X		pid /= 10;
X	}
X	*nm++ = '.';
X	*nm++ = '\0'; /* null termination */
X}
X
Xmkbase()
X{
X	register struct compile *p = passes;
X	USTRING callname;
X	register int len;
X
X	basename(ProgCall, callname);
X	len = strlen(callname);
X	while (p->c_suffix) {
X		if (strcmp(p->c_callname, callname+len-strlen(p->c_callname)) == 0) {
X			compbase = p;
X			mkloader();
X			return;
X		}
X		p++;
X	}
X	/* we should not get here */
X	panic("internal error\n");
X}
X
Xmkloader()
X{
X	register struct passinfo *p = passinfo;
X	register struct pass *pass;
X
X	while (!(p->p_flags & LOADER)) p++;
X	loaderinfo = p;
X	pass = &(compbase->c_passes[0]);
X	while (strcmp(pass->pp_name, p->p_name)) pass++;
X	loader = pass;
X}
X
Xneedsprep(name)
X	char *name;
X{
X	int file;
X	char fc;
X
X	file = open(name,0);
X	if (file <0) return 0;
X	if (read(file, &fc, 1) != 1) fc = 0;
X	close(file);
X	return fc == '#';
X}
X
Xcfile(name)
X	char *name;
X{
X	while (*name != '\0' && *name != '.')
X		name++;
X
X	if (*name == '\0') return 0;
X	return (*++name == 'c' && *++name == '\0');
X}
X
Xchar *
Xapply(pinf, cp, name, passindex, noremove, first, resultname)
X	register struct passinfo *pinf;
X	register struct compile *cp;
X	char *name, *resultname;
X{
X	/*	Apply a pass, indicated by "pinf", with args in 
X		cp->c_passes[passindex], to name "name", leaving the result
X		in a file with name "resultname", concatenated with result
X		suffix.
X		When neccessary, the preprocessor is run first.
X		If "noremove" is NOT set, the file "name" is removed.
X	*/
X
X	struct arglist *call = &CALLVEC;
X	struct pass *pass = &(cp->c_passes[passindex]);
X	char *outname;
X
X	if ( /* this pass is the first pass */
X	     first
X	   &&
X	     ( /* preprocessor always needed */
X	       (pinf->p_flags & PREPALWAYS)
X	     ||/* or only when "needsprep" says so */
X	       ( (pinf->p_flags & PREPCOND) && needsprep(name))
X	     )
X	   ) {
X		mkstr(newfil, tmpname, passinfo[0].p_to, "");
X		mkvec(call, name, newfil, &preprocessor, &passinfo[0]);
X		if (! runvec(call, &passinfo[0], name, newfil)) {
X			cleanup(newfil);
X			return 0;
X		}
X		/*
X		 * When -m is specified and we have a .c file, then we
X		 * should run irrel.
X		 */
X		if (m_flag && cfile(name)) {
X			/* newfil is OK */
X			mkvec(call, newfil, newfil, &irrel, &passinfo[1]);
X			if (! runvec(call, &passinfo[1], newfil, newfil)) {
X				cleanup(newfil);
X				return 0;
X			}
X		}
X		strcpy(curfil, newfil);
X		newfil[0] = '\0';
X		name = curfil;
X		noremove = 0;
X	}
X	if (pinf->p_to) outname = mkstr(newfil, resultname, pinf->p_to, "");
X	else outname = o_FILE;
X	mkvec(call, name, outname, pass, pinf);
X	if (! runvec(call, pinf, name, outname)) {
X		if (! (pinf->p_flags & NOCLEAN)) cleanup(outname);
X		if (! noremove) cleanup(name);
X		return 0;
X	}
X	if (! noremove) cleanup(name);
X	strcpy(curfil, newfil);
X	newfil[0] = '\0';
X	return curfil;
X}
X
Xint
Xapplicable(pinf, suffix)
X	struct passinfo *pinf;
X	char *suffix;
X{
X	/*	Return one if the pass indicated by "pinfo" is applicable to
X		a file with suffix "suffix".
X	*/
X	register char *sfx = pinf->p_from;
X	int l;
X
X	if (! suffix) return 0;
X	l = strlen(suffix);
X	while (*sfx) {
X		register char *p = sfx;
X
X		while (*p && *p != ',') p++;
X		if (l == p - sfx && strncmp(sfx, suffix, l) == 0) {
X			return 1;
X		}
X		if (*p == ',') sfx = p+1;
X		else sfx = p;
X	}
X	return 0;
X}
X		
Xchar *
Xprocess(name, noremove)
X	char *name;
X{
X	register struct compile *cp = passes;
X	char *suffix = extension(name);
X	USTRING base;
X	register struct pass *pass;
X	register struct passinfo *pinf;
X
X	if (! suffix) return name;
X
X	basename(name, base);
X
X	while (cp->c_suffix) {
X		if ((cp->c_flags & DEFLANG) &&
X		    strcmp(cp->c_suffix, suffix) == 0)
X			break;
X		cp++;
X	}
X	if (! cp->c_suffix) cp = compbase;
X	pass = cp->c_passes;
X	while (pass->pp_name) {
X		int first = 1;
X
X		for (pinf=passinfo; strcmp(pass->pp_name,pinf->p_name);pinf++)
X			;
X		if (! (pinf->p_flags & LOADER) && applicable(pinf, suffix)) {
X			int cont = ! stopsuffix || ! pinf->p_to ||
X					strcmp(stopsuffix, pinf->p_to) != 0;
X			name = apply(pinf,
X				     cp,
X				     name,
X				     (int) (pass - cp->c_passes),
X				     noremove,
X				     first,
X				     applicable(loaderinfo, pinf->p_to) ||
X				      !cont ?
X					strcat(base, ".") :
X					tmpname);
X			first = noremove = 0;
X			suffix = pinf->p_to;
X			if (!cont || !name) break;
X		}
X		pass++;
X	}
X	if (!noremove && name)
X		append(&GEN_LDFILES, name);
X	return name;
X}
X
Xmkvec(call, in, out, pass, pinf)
X	struct arglist *call;
X	char *in, *out;
X	struct pass *pass;
X	register struct passinfo *pinf;
X{
X	register int i;
X
X	init(call);
X	append(call, pinf->p_path);
X	scanflags(call, pinf);
X	if (pass) for (i = 0; i < MAXHEAD; i++)
X		if (pass->pp_head[i])
X			append(call, pass->pp_head[i]);
X		else	break;
X	if (pinf->p_flags & INPUT)
X		append(call, in);
X	if (pinf->p_flags & OUTPUT)
X		append(call, out);
X	if (pinf->p_flags & O_OUTPUT) {
X		append(call, "-o");
X		append(call, out);
X	}
X	if (pass) for (i = 0; i < MAXTAIL; i++)
X		if (pass->pp_tail[i])
X			append(call, pass->pp_tail[i]);
X		else	break;
X}
X
Xcallld(in, out, pass, pinf)
X	struct arglist *in;
X	char *out;
X	struct pass *pass;
X	register struct passinfo *pinf;
X{
X	struct arglist *call = &CALLVEC;
X	register int i;
X
X	init(call);
X	append(call, pinf->p_path);
X	scanflags(call, pinf);
X	append(call, "-o");
X	append(call, out);
X	for (i = 0; i < MAXHEAD; i++)
X		if (pass->pp_head[i])
X			append(call, pass->pp_head[i]);
X		else	break;
X	if (pinf->p_flags & INPUT)
X		concat(call, in);
X	if (pinf->p_flags & OUTPUT)
X		append(call, out);
X	for (i = 0; i < MAXTAIL; i++) {
X		if (pass->pp_tail[i]) {
X			if (pass->pp_tail[i][0] == '-' &&
X			    pass->pp_tail[i][1] == 'l') {
X				append(call, library(&(pass->pp_tail[i][2])));
X			}
X			else if (*(pass->pp_tail[i]) != '*')
X				append(call, pass->pp_tail[i]);
X			else if (fp_lib)
X				append(call, library("fp"));
X		} else	break;
X	}
X	if (! runvec(call, pinf, (char *) 0, out)) {
X		cleanup(out);
X		RET_CODE = 1;
X	}
X}
X
Xclean(c)
X	register struct arglist *c;
X{
X	register int i;
X
X	for (i = 1; i < c->al_argc; i++) {
X		free(c->al_argv[i]);
X		c->al_argv[i] = 0;
X	}
X	c->al_argc = 0;
X}
X
Xscanflags(call, pinf)
X	struct arglist *call;
X	struct passinfo *pinf;
X{
X	/*	Find out which flags from FLAGS must be passed to pass "pinf",
X		and how. 
X		Append them to "call"
X	*/
X	register int i;
X	USTRING flg;
X
X	for (i = 0; i < FLAGS.al_argc; i++) {
X		register char *q = pinf->p_acceptflags;
X
X		while (*q)  {
X			register char *p = FLAGS.al_argv[i] + 1;
X
X			while (*q && *q == *p) {
X				q++; p++;
X			}
X			if (*q == ',' || !*q) {
X				if (! *p) {
X					/* append literally */
X					append(call, FLAGS.al_argv[i]);
X				}
X				break;
X			}
X			if (*q == '*') {
X				register char *s = flg;
X
X				if (*++q != '=') {
X					/* append literally */
X					append(call, FLAGS.al_argv[i]);
X					break;
X				}
X				*s++ = '-';
X				if (*q) q++;	/* skip ',' */
X				while (*q && *q != ',' && *q != '*') {
X					/* copy replacement flag */
X					*s++ = *q++;
X				}
X				if (*q == '*') {
X					/* copy rest */
X					while (*p) *s++ = *p++;
X				}
X				*s = 0;
X				append(call, flg);
X				break;
X			}
X			if (*q == '=') {
X				/* copy replacement */
X				register char *s = flg;
X
X				*s++ = '-';
X				q++;
X				while (*q && *q != ',') *s++ = *q++;
X				*s = 0;
X				append(call, flg);
X				break;
X			}
X			while (*q && *q++ != ',')
X				;
X		}
X	}
X}
/
echo x - postmort.c
sed '/^X/s///' > postmort.c << '/'
X/* postmort - post mortem dump		Author: C. W. Rose */
X
X/* Postmort: perform post-mortem on PC Minix 1.5 core files.
X *
X * $Id: postmort.c,v 1.1 1992/03/26 08:05:56 cwr Rel $
X */
X
X /* The 1.5 core file structure is a struct mem_map, the segment memory map,
X  * followed by a struct proc, the process table, followed by a dump of the
X  * text, data, and stack segments.
X  * 
X  * This is the 8086/Intel version; 386 and 68K will differ.  It defaults to
X  * using the name 'core' for the core file, and 'a.out' for the symbol file.
X  * If there is no 'a.out', it will try and read the symbol table from
X  * 'symbol.out', then give up.  A non-existant symbol table is not a fatal
X  * error unless the -s option was used.
X  * 
X  * The PC 1.5 kernel dump routines are odd - they dump the memory maps twice,
X  * the second time as part of the kernel process table, and the kernel
X  * process table size must be a multiple of 4.  Should a core file have a
X  * header with a magic number in future?
X  * 
X  * The kernel include file paths need to be edited for each machine. */
X
X#include <sys/types.h>
X#include <minix/config.h>
X#include <minix/const.h>
X#include <minix/type.h>
X#include <limits.h>
X#include <signal.h>
X#include <stdlib.h>
X
X#undef EXTERN			/* <minix/const.h> defined this */
X#define EXTERN			/* so we get proc & mproc */
X#include "../../kernel/const.h"
X#include "../../kernel/type.h"
X#include "../../kernel/proc.h"
X#undef printf			/* kernel's const.h defined this */
X#include "../../mm/mproc.h"
X
X#include <a.out.h>
X#include <ctype.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <stdio.h>
X#undef NULL
X#include <string.h>
X#include <unistd.h>
X
X#define FALSE		0
X#undef TRUE
X#define TRUE		~FALSE
X#define OK		1
X#define FAILED		-1
X
X#define CORE		"core"
X#define AOUT		"a.out"
X#define SYMB		"symbol.out"
X#define LINE_LEN	16
X#define MAXSYM		200
X#define SYMLEN		8
X
X/* Global variables */
Xint opt_c = FALSE;		/* name of core file */
Xint opt_d = FALSE;		/* dump raw data and stack segments */
Xint opt_p = FALSE;		/* dump the kernel process table */
Xint opt_s = FALSE;		/* name of symbol file */
Xint opt_t = FALSE;		/* trace back the stack */
Xint opt_x = FALSE;		/* debugging flag */
X
Xchar progname[20];		/* program name */
Xchar *segment_name[] = {	/* array of segment names */
X  "Text",
X  "Data",
X  "Stack"
X};
X
Xint dbglvl = 0;			/* debugging level */
Xint maxsym;			/* maximum symbol number */
Xunsigned int baseptr;		/* reference copy of stack base pointer */
Xunsigned int stackptr;		/* reference copy of stack pointer */
Xlong int lengths[NR_SEGS];	/* segment lengths */
Xlong int bases[NR_SEGS];	/* segment base addresses */
X
Xstruct sym {			/* symbol table addresses and labels */
X  unsigned int addr;
X  char label[SYMLEN + 1];
X} symtab[MAXSYM];
X
X/* Used by getopt(3) package */
Xextern int optind, opterr, optopt;
Xextern char *optarg;
X
X_PROTOTYPE(int binary, (int uc, char *sp));
X_PROTOTYPE(void dump_all_segs, (int fd));
X_PROTOTYPE(void dump_maps, (struct mem_map * mp));
X_PROTOTYPE(void dump_one_seg, (int fd, int segindex));
X_PROTOTYPE(void dump_proc_table, (struct proc * pt));
X_PROTOTYPE(void dump_registers, (struct proc * pt));
X_PROTOTYPE(void dump_stack, (struct stackframe_s * sp));
X_PROTOTYPE(int main, (int argc, char *argv[]));
X_PROTOTYPE(int parse_line, (char *ps));
X_PROTOTYPE(int read_symbol, (int fd));
X_PROTOTYPE(void stack_trace, (int fd));
X_PROTOTYPE(void usage, (void));
X
X
X/* B i n a r y
X *
X * Produce a binary representation of an 8-bit number.
X */
Xint binary(ucc, sp)
Xint ucc;
Xchar *sp;
X{
X  int j;
X  unsigned char k, uc;
X
X  uc = (unsigned char) ucc;
X  for (k = 0x80, j = 0; j < 8; j++) {
X	if ((uc & k) == 0)
X		*sp++ = '0';
X	else
X		*sp++ = '1';
X	if (j == 3) *sp++ = '$';
X	k >>= 1;
X  }
X  *sp = '\0';
X
X  return(0);
X}
X
X
X/* D u m p _ a l l _ s e g s
X *
X * Dump all the segments except for text
X */
Xvoid dump_all_segs(fd)
Xint fd;
X{
X  int j;
X  long int start;
X
X  start = (long) (NR_SEGS * sizeof(struct mem_map)) + sizeof(struct proc);
X  for (j = 1; j < NR_SEGS; j++) {
X	start += lengths[j - 1];
X	(void) lseek(fd, start, 0);
X	printf("\n");
X	dump_one_seg(fd, j);
X  }
X}
X
X
X/* D u m p _ m a p s
X *
X * Dump the memory maps
X */
Xvoid dump_maps(mp)
Xstruct mem_map *mp;
X{
X  int j;
X  long int vir, phy, len;
X
X  printf("\t  Virtual\t  Physical\tLength\n");
X  printf("\t  address\t  address\n");
X  for (j = 0; j < NR_SEGS; j++) {
X	vir = (long) mp[j].mem_vir << CLICK_SHIFT;
X	phy = (long) mp[j].mem_phys << CLICK_SHIFT;
X	len = (long) mp[j].mem_len << CLICK_SHIFT;
X	printf("%s:\t0x%08.8lx\t0x%08.8lx\t%8ld (0x%08.8lx)\n",
X	       segment_name[j], vir, phy, len, len);
X	lengths[j] = len;
X	bases[j] = vir;
X  }
X}
X
X
X/* D u m p _ o n e _ s e g
X *
X * Dump a single segment
X */
Xvoid dump_one_seg(fd, segindex)
Xint fd, segindex;
X{
X  unsigned char dlen[LINE_LEN];
X  int i, amt, amt_read;
X  long int len, offset;
X
X  printf("%s segment\n\n", segment_name[segindex]);
X  len = lengths[segindex];
X  amt = LINE_LEN;
X  for (offset = 0; offset < len; offset += amt) {
X	if ((len - offset) < LINE_LEN) amt = (int) (len - offset);
X	if (dbglvl > 0)
X		printf("Length %ld, offset %ld, amt %d\n", len, offset, amt);
X	if ((amt_read = read(fd, (char *) dlen, (unsigned int) amt)) == -1) {
X		printf("Unexpected end of file\n");
X		exit(1);
X	}
X	printf("%08.8lx: ", bases[segindex] + offset);
X	for (i = 0; i < amt_read; i++) {
X		if (i == LINE_LEN / 2) printf("- ");
X		printf("%02.2x ", dlen[i]);
X	}
X	printf("  ");
X	for (i = 0; i < amt_read; i++) {
X		if (isprint(dlen[i]))
X			(void) putchar((char) dlen[i]);
X		else
X			(void) putchar('.');
X	}
X	(void) putchar('\n');
X	if (dbglvl > 0 && amt_read != amt)
X		printf("wanted = %d, got = %d, offset = %ld\n",
X		       amt, amt_read, offset);
X  }
X}
X
X
X/* D u m p _ p r o c _ t a b l e
X *
X * Dump the entire kernel proc table
X */
Xvoid dump_proc_table(pt)
Xstruct proc *pt;
X{
X  printf("Kernel process table entries:\n\n");
X#if 0
X  printf("Process' registers:			0x%04.4x\n", pt->p_reg);	/* struct stackframe_s */
X  printf("Selector in gdt:			0x%04.4x\n", pt->p_ldt_sel);	/* reg_t */
X  printf("Descriptors for code and data:	0x%04.4x\n", pt->p_ldt[2]);	/* struct segdesc_s */
X#endif
X  printf("Lowest legal stack value:		0x%04.4x\n", pt->p_splimit);	/* reg_t */
X  printf("Number of this process:			0x%04.4x\n", pt->p_nr);	/* int */
X  printf("Nonzero if blocked by busy task:	0x%04.4x\n", pt->p_int_blocked);	/* int */
X  printf("Nonzero if held by busy syscall:	0x%04.4x\n", pt->p_int_held);	/* int */
X#if 0
X  printf("Next in chain of held-up processes:	0x%04.4x\n", pt->p_nextheld);	/* struct proc * */
X#endif
X  printf("P_SLOT_FREE SENDING, RECEIVING, etc.:	0x%04.4x\n", pt->p_flags);	/* int */
X#if 0
X  printf("Memory map:				0x%04.4x\n", pt->p_map[NR_SEGS]);	/* struct mem_map */
X#endif
X  printf("Process id passed in from MM:		0x%04.4x\n", pt->p_pid);	/* int */
X  printf("User time in ticks:			%ld\n", pt->user_time);	/* time_t */
X  printf("Sys time in ticks:			%ld\n", pt->sys_time);	/* time_t */
X  printf("Cumulative user time of children:	%ld\n", pt->child_utime);	/* time_t */
X  printf("Cumulative sys time of children:	%ld\n", pt->child_stime);	/* time_t */
X  printf("Time of next alarm in ticks or 0:	%ld\n", pt->p_alarm);	/* time_t */
X#if 0
X  printf("Ticks used in current quantum:	%d\n", pt->quantum_time);	/* int */
X  printf("Ticks used in last quantum:		%d\n", pt->quantum_last);	/* int */
X  printf("Current priority of the process:	%d\n", pt->curr_prio);	/* int */
X  printf("Base priority of the process:		%d\n", pt->base_prio);	/* int */
X  printf("Scale for profiling, 0 = none:	%u\n", pt->p_pscale);	/* unsigned */
X  printf("Profiling pc lower boundary:		%d\n", pt->p_plow);	/* vir_bytes */
X  printf("Profiling pc upper boundary:		%d\n", pt->p_phigh);	/* vir_bytes */
X  printf("Profiling buffer:			%d\n", pt->p_pbuf);	/* vir_bytes */
X  printf("Profiling buffer size:		%d\n", pt->p_psiz);	/* vir_bytes */
X#endif
X#if 0
X  printf("First proc wishing to send:		0x%04.4x\n", pt->p_callerq);	/* struct proc * */
X  printf("Link to next proc wishing to send:	0x%04.4x\n", pt->p_sendlink);	/* struct proc * */
X  printf("Pointer to message buffer:		0x%04.4x\n", pt->p_messbuf);	/* message * */
X#endif
X  printf("Expecting message from:			0x%04.4x\n", pt->p_getfrom);	/* int */
X#if 0
X  printf("Pointer to next ready process:	0x%04.4x\n", pt->p_nextready);	/* struct proc * */
X#endif
X  printf("Bit map for pending signals 1-16:	0x%04.4x\n", pt->p_pending);	/* int */
X  printf("Count of pending/unfinished signals:	0x%04.4x\n", pt->p_pendcount);	/* unsigned */
X}
X
X
X/* D u m p _ r e g i s t e r s
X *
X * Dump the registers from the proc table
X */
Xvoid dump_registers(pt)
Xstruct proc *pt;
X{
X  char buff[32];
X  unsigned char uc;
X
X  /* Print the registers */
X  dump_stack(&pt->p_reg);
X
X  /* Print some miscellaneous information */
X  printf("\nLowest legal stack value = %04.4x\n", pt->p_splimit);
X
X  /* Build up a binary representation of the signal flags */
X  uc = (pt->p_pending >> 8) & 0xff;
X  (void) binary((int) uc, buff);
X  buff[9] = '$';
X  uc = pt->p_pending & 0xff;
X  (void) binary((int) uc, buff + 10);
X  printf("Pending signals = %s\n", buff);
X}
X
X
X/* D u m p _ s t a c k
X *
X * Dump the stack frame
X */
Xvoid dump_stack(sp)
Xstruct stackframe_s *sp;
X{
X  char buff[32];
X  unsigned char uc;
X
X  /* Build up the binary PSW representation */
X  uc = (sp->psw >> 8) & 0xff;
X  (void) binary((int) uc, buff);
X  uc = sp->psw & 0xff;
X  buff[9] = '$';
X  (void) binary((int) uc, buff + 10);
X
X  /* Print all the information */
X  printf("Stack Frame:\tPC = %04.4x\t\t   PSW = %s\n",
X         sp->pc, buff);
X  printf("\t\t\t\t\tStatus = ____ ODIT SZ_A _P_C\n");
X
X  printf("  ax	bx	cx	dx	di	si\n");
X  printf("  %04.4x\t%04.4x\t%04.4x\t%04.4x\t%04.4x\t%04.4x\n",
X         sp->retreg, sp->bx, sp->cx, sp->dx, sp->di, sp->si);
X  printf("  sp	bp	ss\n");
X  printf("  %04.4x\t%04.4x\t%04.4x\n",
X         sp->sp, sp->fp, sp->ss);
X  printf("  cs	ds	es\n");
X  printf("  %04.4x\t%04.4x\t%04.4x\n",
X         sp->cs, sp->ds, sp->es);
X
X  /* Store for future reference */
X  stackptr = sp->sp;
X  baseptr = sp->fp;
X  if (dbglvl > 0)
X	printf("\nStack pointer 0x%x, Base pointer 0x%x\n", stackptr, baseptr);
X}
X
X
X/* M a i n
X *
X * Main program
X */
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  int j, fdc, fds;
X  char *cp, corefile[132], symbfile[132];
X  struct proc proc_entry;
X  struct mem_map mp_segs[NR_SEGS];
X
X  /* Initial set up */
X  if ((cp = strrchr(argv[0], '/')) == (char *) NULL)
X	cp = argv[0];
X  else
X	cp++;
X  strncpy(progname, cp, 19);
X  strncpy(corefile, CORE, 131);
X  strncpy(symbfile, AOUT, 131);
X
X  /* Parse arguments */
X  opterr = 0;
X  while ((j = getopt(argc, argv, "c:dps:tx:")) != EOF) {
X	switch (j & 0177) {
X	    case 'c':
X		opt_c = TRUE;
X		strncpy(corefile, optarg, 131);
X		break;
X	    case 'd':	opt_d = TRUE;	break;
X	    case 'p':	opt_p = TRUE;	break;
X	    case 's':
X		opt_s = TRUE;
X		strncpy(symbfile, optarg, 131);
X		break;
X	    case 't':	opt_t = TRUE;	break;
X	    case 'x':
X		dbglvl = atoi(optarg);
X		opt_x = TRUE;
X		break;
X	    case '?':
X	    default:
X		usage();
X		exit(1);
X		break;
X	}
X  }
X
X  /* We must have a core file */
X  if ((fdc = open(corefile, O_RDONLY)) == -1) {
X	fprintf(stderr, "Cannot open %s\n", corefile);
X	exit(1);
X  }
X
X  /* We'd like an a.out file or a symbol table */
X  if ((fds = open(symbfile, O_RDONLY)) == -1) {
X	if (opt_s)
X		j = FAILED;
X	else {
X		strncpy(symbfile, AOUT, 131);
X		if ((fds = open(symbfile, O_RDONLY)) == -1)
X			j = FAILED;
X		else
X			j = read_symbol(fds);
X	}
X  } else
X	j = read_symbol(fds);
X
X  /* Only fatal if we insisted */
X  if (opt_s && j == FAILED) {
X	fprintf(stderr, "Cannot find symbols in %s\n", symbfile);
X	exit(1);
X  }
X
X  /* Read the process table */
X  if (dbglvl > 0) {
X	printf("\n");
X	printf("Size of mproc entry %d\n", NR_SEGS * sizeof(struct mem_map));
X	printf("Size of process table %d\n", sizeof(proc_entry));
X  }
X  if (read(fdc, (char *) mp_segs, sizeof(mp_segs)) != sizeof(mp_segs) ||
X      read(fdc, (char *) &proc_entry,
X	 sizeof(struct proc)) != sizeof(struct proc)) {
X	fprintf(stderr, "Cannot open %s\n", corefile);
X	exit(1);
X  }
X
X  /* Do the work */
X#if 0
X  dump_maps(mp_segs);		/* duplicated in the kernel */
X  printf("\n");
X#endif
X  dump_maps(proc_entry.p_map);
X  printf("\n");
X  dump_registers(&proc_entry);
X  if (opt_t) {
X	printf("\n");
X	stack_trace(fdc);
X  }
X  if (opt_p) {
X	printf("\n");
X	dump_proc_table(&proc_entry);
X  }
X  if (opt_d) {
X	printf("\n");
X	dump_all_segs(fdc);
X  }
X
X  /* Wrap up */
X  (void) close(fdc);
X  if (fds != -1) (void) close(fds);
X
X  exit(0);
X  /* NOTREACHED */
X}
X
X
X/* P a r s e _ l i n e
X *
X * Parse a line of the symbol table
X */
Xint parse_line(ps)
Xchar *ps;
X{
X  char c, s[80];
X  int j, k;
X  unsigned int u;
X
X  /* We must have space in the table */
X  if (maxsym == MAXSYM) return(FAILED);
X
X  /* Lines must be a minimum length to contain information */
X  if (strlen(ps) < 8) return(FAILED);
X
X  /* Lines must have a definite structure */
X  if (ps[1] != ' ' || ps[6] != ' ') return(FAILED);
X  for (j = 2; j < 6; j++)
X	if (!isxdigit(ps[j])) return(FAILED);
X  if (sscanf(ps, "%c %x %s", &c, &u, s) != 3) return (FAILED);
X
X  if (dbglvl > 0) printf("Address 0x%04.4x, label %s\n", u, s);
X
X  /* Load the symbol table in sorted order */
X  for (j = 0; j < maxsym; j++) {
X	if (u < symtab[j].addr) {
X		for (k = maxsym; k > j; k--) symtab[k] = symtab[k - 1];
X		break;
X	}
X  }
X  symtab[j].addr = u;
X  strncpy(symtab[j].label, s, SYMLEN);
X  maxsym++;
X
X  return(OK);
X}
X
X
X/* R e a d _ s y m b o l
X *
X * Read the symbol table
X */
Xint read_symbol(fd)
Xint fd;
X{
X  char sym[80], buff[BUFSIZ];
X  int j, k, m;
X  long int offset;
X  struct exec *ep;
X  struct nlist *np;
X
X  /* We collect only text symbols, since that's all that's needed here */
X
X  /* Initialise the buffer */
X  if ((j = read(fd, buff, BUFSIZ)) == 0 || j == -1) return(FAILED);
X
X  k = maxsym = 0;
X
X  /* Find out what we've got */
X  ep = (struct exec *) buff;
X  np = (struct nlist *) buff;
X  if (BADMAG(*ep)) {
X	/* Must be a separate symbol table */
X	while (TRUE) {
X		if (buff[k] == 'T') {
X			for (m = 0; m < 78; m++) {
X				sym[m] = buff[k];
X				if (++k == j) {
X					if ((j = read(fd, buff, BUFSIZ)) == 0 || j == -1)
X						break;
X					k = 0;
X				}
X				if (buff[k] == '\n') break;
X			}
X			sym[m + 1] = '\0';
X			(void) parse_line(sym);
X		}
X		if (++k == j) {
X			if ((j = read(fd, buff, BUFSIZ)) == 0 || j == -1)
X				break;
X			k = 0;
X		}
X	}
X  } else if (ep->a_syms != 0L) {
X	/* There's symbols in them thar hills */
X	offset = 8 * sizeof(long) + ep->a_text + ep->a_data;
X	if (lseek(fd, offset, 0) == -1L) return(FAILED);
X	/* Symbols are in an unsorted list */
X	while (read(fd, buff, sizeof(struct nlist)) == sizeof(struct nlist)) {
X		if (np->n_sclass == (N_TEXT + C_EXT)) {	/* external text symbols */
X			for (j = 0; j < maxsym; j++) {
X				if (np->n_value < symtab[j].addr) {
X					for (k = maxsym; k > j; k--)
X						symtab[k] = symtab[k - 1];
X					break;
X				}
X			}
X			symtab[j].addr = np->n_value;
X			strncpy(symtab[j].label, np->n_name, SYMLEN);
X			if (maxsym++ == MAXSYM) break;
X		}
X	}
X  } else if (opt_s)
X	return(FAILED);
X
X  if (dbglvl > 0) {
X	for (m = 0; m < maxsym; m++) printf("Addr 0x%04.4x, label %s\n",
X		       symtab[m].addr, symtab[m].label);
X	printf("Maxsym %d\n", maxsym);
X  }
X  return(OK);
X}
X
X
X/* S t a c k _ t r a c e
X *
X * Trace back down the stack frames.
X *
X * WARNING: very, very, non-portable code
X */
Xvoid stack_trace(fd)
Xint fd;
X{
X  int j;
X  unsigned int framepointer, lastpointer, returnvalue, end;
X  long int offset, bp;
X
X  /* Bp actually gives the offset from the base of the data segment */
X  bp = (long) (NR_SEGS * sizeof(struct mem_map)) + sizeof(struct proc)
X	+ lengths[0] + lengths[1] - bases[2];
X  if ((offset = lseek(fd, bp + (long int) baseptr, 0)) == -1L) return;
X  end = (bases[2] + lengths[2] - 1) & 0xffff;
X
X  if (dbglvl > 0)
X	printf("Baseptr %x, End %x, Bp %ld, Offset %ld\n", baseptr, end, bp, offset);
X
X  /* Print the header, then try to backtrace  */
X  printf("Stack back trace:\n\n");
X  printf("Frame address.  Contents.  Return address.");
X  if (maxsym != 0) printf("  Previous label.");
X  printf("\n");
X
X  lastpointer = baseptr;
X  while (TRUE) {
X	/* Read the frame pointer and return address values */
X	if (read(fd, (char *) &framepointer, sizeof(int)) == -1 ||
X	    read(fd, (char *) &returnvalue, sizeof(int)) == -1)
X		break;
X
X	/* Look up the return address - ignored if maxsym == 0 */
X	for (j = 0; j < maxsym; j++) {
X		if (symtab[j].addr >= returnvalue) break;
X	}
X	if (j > 0) j--;
X	printf("    0x%04.4x        0x%04.4x      0x%04.4x          %s\n",
X	       lastpointer, framepointer, returnvalue,
X	       (maxsym == 0) ? "" : symtab[j].label);
X
X	/* If the result is clearly invalid, quit */
X	if (framepointer == 0 || framepointer >= end || framepointer <= lastpointer)
X		break;
X
X	/* Otherwise try to move to the next frame base */
X	lastpointer = framepointer;
X	if ((offset = lseek(fd, bp + (long int) framepointer, 0)) == -1L || offset == 0L)
X		break;
X  }
X}
X
X
X/* U s a g e
X *
X * Usage message
X */
Xvoid usage()
X{
X  fprintf(stderr, "Usage: %s [-dpt] [-c corefile] [-s symbfile]\n", progname);
X}
/
echo x - sdump.c
sed '/^X/s///' > sdump.c << '/'
X/* sdump - dump memory */
X
X#include <minix/config.h>
X#include <sys/types.h>
X#include <minix/const.h>
X#include <minix/type.h>
X#include <signal.h>
X
X#undef EXTERN
X#define EXTERN
X#include "/usr/src/mm/const.h"
X#include "/usr/src/mm/type.h"
X#include "/usr/src/mm/mproc.h"
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/proc.h"
X#undef printf			/* printf was misdefined by the sys headers */
X
X#include <ctype.h>
X#include <fcntl.h>
X#include <limits.h>
X#include <stdarg.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X#include <stdio.h>
X
X#define STACK_BYTES 30000
X
Xchar *default_core = "core";
Xint stack[STACK_BYTES / sizeof (int)];
X
X_PROTOTYPE(int main, (int argc, char **argv));
X_PROTOTYPE(void read_segmap, (int fd, struct mproc *mp, long *seg_size));
X_PROTOTYPE(void read_registers, (int fd, struct proc *p));
X_PROTOTYPE(void dump_stack, (int fd, struct mproc *mp, long *seg_size));
X_PROTOTYPE(void error, (char *s1, char *s2));
X
Xint main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  int fd;
X  long seg_size[NR_SEGS];	/* segment sizes in bytes */
X  struct mproc *mp;
X  struct proc *p;
X  char *file;
X
X  if (argc > 2) error("Usage: rdump [core_file]\n", "");
X
X  if (argc == 1)
X	file = default_core;
X  else
X	file = argv[1];
X
X  if ( (fd = open(file, O_RDONLY)) < 0) error("Cannot open", file);
X
X  mp = &mproc[0];
X  p = &proc[0];
X  read_segmap(fd, mp, seg_size);
X  read_registers(fd, p);
X  dump_stack(fd, mp, seg_size);
X  return(0);
X}
X
Xvoid read_segmap(fd, mp, seg_size)
Xint fd;
Xstruct mproc *mp;
Xlong seg_size[NR_SEGS];
X{
X  int i, segmap_size;
X
X  /* Read in the segment map. */
X  segmap_size = sizeof mp->mp_seg;
X  if (read(fd, (char *) mp, segmap_size) != segmap_size)
X	error("Cannot read segmap map from core image file", "");
X
X  for (i = 0; i < NR_SEGS; i++)
X	seg_size[i] = (long) mp->mp_seg[i].mem_len << CLICK_SHIFT;
X  printf("Seg sizes in bytes:  Text: %ld  Data: %ld, Stack: %ld\n",
X	 seg_size[T], seg_size[D], seg_size[S]);
X}
X
Xvoid read_registers(fd, p)
Xint fd;
Xstruct proc *p;
X{
X  int proctblsize;
X  struct stackframe_s r;
X
X  proctblsize = sizeof (struct proc);
X  if (read(fd, (char *) p, proctblsize) != proctblsize)
X	error("Cannot read process table from core image file", "");
X  r = p->p_reg;
X
X  /* Print proc table. */
X  printf("\n");
X#if (CHIP == INTEL)
X#if INTEL_32BITS
X  printf("eax=%8lX   ebx=%8lX   ecx=%8lX   edx=%8lX\n",
X	 r.retreg, r.bx, r.cx, r.dx);
X  printf("esi=%8lX   edi=%8lX   ebp=%8lX   esp=%8lX   eip=%8lX\n",
X	 r.si, r.di, r.fp, r.sp, r.pc);
X  printf(" ds=%8lX    es=%8lX                   ss=%8lX    cs=%8lX\n",
X	 r.ds, r.es, r.ss, r.cs);
X  printf(" fs=%8lX    gs=%8lX                                  ef=%8lX\n",
X         r.fs, r.gs, r.psw);
X#else
X  printf(
X"ax=%4X  bx=%4X  cx=%4X  dx=%4X  si=%4X  di=%4X  bp=%4X  sp=%4X  ip=%4X\n",
X	 r.retreg, r.bx, r.cx, r.dx, r.si, r.di, r.fp, r.sp, r.pc);
X  printf(
X" f=%4X                             ds=%4X  es=%4X           ss=%4X  cs=%4X\n",
X	 r.psw, r.ds, r.es, r.ss, r.cs);
X#endif
X#endif /* (CHIP == INTEL) */
X#if (CHIP == M68000)
X  printf("pc=%8lx   psw=%4x\n", r.pc, r.psw);
X  printf("d0=%8lx   d1=%8lx   d2=%8lx   d3=%8lx\n", r.retreg, r.d1, r.d2, r.d3);
X  printf("d4=%8lx   d5=%8lx   d6=%8lx   d7=%8lx\n", r.d4, r.d5, r.d6, r.d7);
X  printf("a0=%8lx   a1=%8lx   a2=%8lx   a3=%8lx\n", r.a0, r.a1, r.a2, r.a3);
X  printf("a4=%8lx   a5=%8lx   a6=%8lx   a7=%8lx\n", r.a4, r.a5, r.a6, r.sp);
X#endif
X  printf("\n");
X}
X
Xvoid dump_stack(fd, mp, seg_size)
Xint fd;
Xstruct mproc *mp;
Xlong seg_size[NR_SEGS];
X{
X  unsigned char ch;
X  char format[32];
X  int word, i, stack_size, j;
X  vir_bytes v, vi;
X
X  /* Seek past text and data segments. */
X  lseek(fd, seg_size[T] + seg_size[D], SEEK_CUR);
X  v = mp->mp_seg[S].mem_vir << CLICK_SHIFT;
X
X  stack_size = (int) seg_size[S];
X  if (stack_size != seg_size[S] || stack_size < 0 || stack_size > STACK_BYTES)
X	error("Stack too large", "");
X
X  /* Dump the stack. */
X  if (read(fd, (char *) stack, stack_size) != stack_size)
X	error("Error reading stack from core file", "");
X
X#define BYTES(num)      ((unsigned) sizeof (num))
X#define DEC_DIGITS(num) (sizeof (num) <= 2 ? 6 : 11)	/* for 16/32 bit num */
X#define HEX_DIGITS(num) (((unsigned) sizeof (num) * CHAR_BIT + 3) / 4)
X
X  printf("%*s   %*s  %*s  %*s\n",
X	 HEX_DIGITS(vi), "Addr",
X	 HEX_DIGITS(word), "Hex",
X	 DEC_DIGITS(word), "Dec",
X	 BYTES(word), "Char");
X
X  /* The format string depends messily on the size of various things. */
X  strcpy(format, "%*");
X  if (sizeof v > sizeof (int)) strcat(format, "l");
X  strcat(format, "X:  %*");
X  if (sizeof word > sizeof (int)) strcat(format, "l");
X  strcat(format, "X  %*");
X  if (sizeof word > sizeof (int)) strcat(format, "l");
X  strcat(format, "d  ");
X  
X  for (i = stack_size / sizeof (int) - 1, vi = v + stack_size - sizeof (int);
X       i >= 0; --i, vi -= sizeof (int)) {
X	word = stack[i];
X	printf(format,
X	       HEX_DIGITS(vi), vi,
X	       HEX_DIGITS(word), word,
X	       DEC_DIGITS(word), word);
X	for (j = 0; j < BYTES(word); ++j, word >>= CHAR_BIT) {
X		ch = (unsigned char) word;
X		if (!isprint(ch)) ch = '.';
X		putchar(ch);
X	}
X	putchar('\n');
X  }
X}
X
Xvoid error(s1, s2)
Xchar *s1, *s2;
X{
X  printf("%s %s\n", s1, s2);
X  exit(1);
X}
/
echo x - ibm.cd
sed '/^X/s///' > ibm.cd << '/'
Xecho x - ar.c.d
Xsed '/^X/s///' > ar.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/ar.c  crc=54380  20538	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/ar.c  crc=34758  22716	Sun Mar 28 23:19:15 1993
XX***************
XX*** 1,5 ****
XX--- 1,6 ----
XX  /* ar - archiver		Author: Michiel Huisjes */
XX  /* V7 upgrade			Author:	Monty Walls */
XX+ /* ASCII upgrade		Author:	Bruce Evans */
XX  
XX  /* Usage: ar 'key' [posname] archive [file] ...
XX   *
XX***************
XX*** 38,69 ****
XX   *	forgot that ar_size is a long for printing - 2/14/88 - mrw
XX   *	got the mode bit maps mirrored - 2/19/88 - mrw
XX   *	print & extract member logic fixed - 2/19/88 - mrw
XX   */
XX  
XX  /* Include files */
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX! #include <signal.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX! #include <ar.h>
XX  #include <stdio.h>
XX  
XX  struct i_ar_hdr {		/* local version, maybe different padding */
XX!   char ar_name[14];
XX!   long ar_date;
XX!   char ar_uid;
XX!   char ar_gid;
XX!   int ar_mode;
XX!   long ar_size;
XX  };
XX  
XX- 
XX  /* Macro functions */
XX- #define FOREVER		(32766)
XX  #define odd(nr)		(nr & 1)
XX  #define even(nr)	(odd(nr) ? nr + 1 : nr)
XX- #define quit(pid,sig)	(kill(pid,sig),sleep(FOREVER))
XX  #ifndef tell
XX  #	define tell(f)	(lseek(f, 0l, SEEK_CUR))
XX  #endif
XX--- 39,82 ----
XX   *	forgot that ar_size is a long for printing - 2/14/88 - mrw
XX   *	got the mode bit maps mirrored - 2/19/88 - mrw
XX   *	print & extract member logic fixed - 2/19/88 - mrw
XX+  *
XX+  *	On Aug 13 1991 - bde:
XX+  *	handle ASCII headers.
XX+  *	fix printing of times.
XX+  *	remove magic 14's (work mostly with null-terminated strings).
XX+  *	declare all functions and fix warnings from gcc.
XX+  *	clean up printing of error messages; use strerror.
XX   */
XX  
XX+ 
XX  /* Include files */
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX! #include <ar.h>
XX  #include <fcntl.h>
XX  #include <unistd.h>
XX! 
XX! #include <errno.h>
XX! #include <stdlib.h>
XX! #include <signal.h>
XX! #include <string.h>
XX! #include <time.h>
XX  #include <stdio.h>
XX  
XX+ struct ar_hdr dummy_hdr;
XX+ 
XX  struct i_ar_hdr {		/* local version, maybe different padding */
XX!   char ar_name[sizeof dummy_hdr.ar_name + 1];
XX!   time_t ar_date;
XX!   uid_t ar_uid;
XX!   gid_t ar_gid;
XX!   mode_t ar_mode;
XX!   off_t ar_size;
XX  };
XX  
XX  /* Macro functions */
XX  #define odd(nr)		(nr & 1)
XX  #define even(nr)	(odd(nr) ? nr + 1 : nr)
XX  #ifndef tell
XX  #	define tell(f)	(lseek(f, 0l, SEEK_CUR))
XX  #endif
XX***************
XX*** 103,110 ****
XX--- 116,128 ----
XX  #define BUFFERSIZE	4096
XX  #define WRITE		2	/* both read & write */
XX  #define READ		0
XX+ #ifdef SARMAG
XX+ #define MAGICSIZE	SARMAG
XX+ #define SIZEOF_AR_HDR	(sizeof (struct ar_hdr))
XX+ #else				/* sizeof (struct ar_hdr) wrong after pad */
XX  #define MAGICSIZE	sizeof(short)	/* size of magic number in file */
XX  #define SIZEOF_AR_HDR	((size_t) 26)
XX+ #endif
XX  
XX  /* Option switches */
XX  char verbose = 0;
XX***************
XX*** 117,128 ****
XX  /* Global variables */
XX  char *tmp1;
XX  char *tmp2;
XX  char *progname;
XX  char *posname = NULL;
XX  char *afile;
XX  char buffer[BUFFERSIZE];
XX  long pos_offset = -1;
XX- int mypid;
XX  
XX  /* Keep track of member moves using this struct */
XX  struct mov_list {
XX--- 135,146 ----
XX  /* Global variables */
XX  char *tmp1;
XX  char *tmp2;
XX+ char *outname;
XX  char *progname;
XX  char *posname = NULL;
XX  char *afile;
XX  char buffer[BUFFERSIZE];
XX  long pos_offset = -1;
XX  
XX  /* Keep track of member moves using this struct */
XX  struct mov_list {
XX***************
XX*** 130,142 ****
XX    struct mov_list *next;
XX  } *moves = NULL;
XX  
XX! /* Forward declarations and external references */
XX! extern char *malloc();
XX! extern char *mktemp(), *rindex();
XX! extern int strncmp();
XX! extern print_date();
XX! extern user_abort(), usage();
XX! extern char *basename();
XX  
XX  int main(argc, argv)
XX  int argc;
XX--- 148,178 ----
XX    struct mov_list *next;
XX  } *moves = NULL;
XX  
XX! _PROTOTYPE(int main, (int argc, char **argv ));
XX! _PROTOTYPE(void usage, (void));
XX! _PROTOTYPE(void user_abort, (int s ));
XX! _PROTOTYPE(void insert_abort, (int s ));
XX! _PROTOTYPE(void mwrite, (int fd, char *address, int bytes ));
XX! _PROTOTYPE(void int_to_p2, (char *cp, int n ));
XX! _PROTOTYPE(void long_to_p4, (char *cp, long n ));
XX! _PROTOTYPE(int p2_to_int, (unsigned char *cp ));
XX! _PROTOTYPE(long p4_to_long, (unsigned char *cp ));
XX! _PROTOTYPE(void addmove, (long pos ));
XX! _PROTOTYPE(struct i_ar_hdr *get_member, (int fd ));
XX! _PROTOTYPE(int open_archive, (char *filename, int opt, int to_create ));
XX! _PROTOTYPE(int rebuild, (int fd, int tempfd ));
XX! _PROTOTYPE(void print_Mode, (int mode ));
XX! _PROTOTYPE(void print_header, (struct i_ar_hdr *member ));
XX! _PROTOTYPE(void print_member, (int fd, struct i_ar_hdr *member ));
XX! _PROTOTYPE(void copy_member, (int infd, int outfd, struct i_ar_hdr *member ));
XX! _PROTOTYPE(int insert,(int fd,char *name,char *mess,struct i_ar_hdr *oldmem ));
XX! _PROTOTYPE(int ar_move, (int oldfd, int arfd, struct mov_list *mov ));
XX! _PROTOTYPE(int ar_insert, (int oldfd, int ac, int argc, char **argv ));
XX! _PROTOTYPE(void ar_common, (int ac, int argc, char **argv ));
XX! _PROTOTYPE(void ar_members, (int ac, int argc, char **argv ));
XX! _PROTOTYPE(void append_members, (int ac, int argc, char **argv ));
XX! _PROTOTYPE(char *basename, (char *path ));
XX! _PROTOTYPE(void error, (char *str1, char *str2 ));
XX  
XX  int main(argc, argv)
XX  int argc;
XX***************
XX*** 215,223 ****
XX  	ac = 3;
XX    }
XX  
XX-   /* Exit logic consists of doing a kill on my pid to insure that we */
XX-   /* Get the current clean up and exit logic */
XX-   mypid = getpid();
XX    signal(SIGINT, user_abort);
XX  
XX    switch (Major) {
XX--- 251,256 ----
XX***************
XX*** 241,282 ****
XX  	}
XX    }
XX    fflush(stdout);
XX!   exit(rc);
XX  }
XX  
XX! usage()
XX  {
XX    fprintf(stderr, "Usage: %s [qrxdpmt][abivulc] [posname] afile name ... \n", progname);
XX!   exit(1);
XX  }
XX  
XX! user_abort()
XX  {
XX    unlink(tmp1);
XX!   exit(1);
XX  }
XX  
XX! insert_abort()
XX  {
XX    unlink(tmp1);
XX    unlink(tmp2);
XX!   exit(1);
XX  }
XX  
XX! mwrite(fd, address, bytes)
XX  int fd;
XX! register char *address;
XX! register int bytes;
XX  {
XX!   if (write(fd, address, bytes) != bytes) {
XX! 	fprintf(stderr, " Error: %s - Write error\n", progname);
XX! 	quit(mypid, SIGINT);
XX!   }
XX  }
XX  
XX  /* Convert int to pdp-11 order char array */
XX  
XX! int_to_p2(cp, n)
XX  char *cp;
XX  int n;
XX  {
XX--- 274,316 ----
XX  	}
XX    }
XX    fflush(stdout);
XX!   return(rc);
XX  }
XX  
XX! void usage()
XX  {
XX    fprintf(stderr, "Usage: %s [qrxdpmt][abivulc] [posname] afile name ... \n", progname);
XX!   exit(EXIT_FAILURE);
XX  }
XX  
XX! void user_abort(s)
XX! int s;				/* ANSI requires this */
XX  {
XX    unlink(tmp1);
XX!   exit(EXIT_FAILURE);
XX  }
XX  
XX! void insert_abort(s)
XX! int s;				/* ANSI requires this */
XX  {
XX    unlink(tmp1);
XX    unlink(tmp2);
XX!   exit(EXIT_FAILURE);
XX  }
XX  
XX! void mwrite(fd, address, bytes)
XX  int fd;
XX! char *address;
XX! int bytes;
XX  {
XX!   if (write(fd, address, bytes) != bytes) error("write error on", outname);
XX  }
XX  
XX+ #ifndef SARMAG
XX+ 
XX  /* Convert int to pdp-11 order char array */
XX  
XX! void int_to_p2(cp, n)
XX  char *cp;
XX  int n;
XX  {
XX***************
XX*** 286,292 ****
XX  
XX  /* Convert long to pdp-11 order char array */
XX  
XX! long_to_p4(cp, n)
XX  char *cp;
XX  long n;
XX  {
XX--- 320,326 ----
XX  
XX  /* Convert long to pdp-11 order char array */
XX  
XX! void long_to_p4(cp, n)
XX  char *cp;
XX  long n;
XX  {
XX***************
XX*** 313,319 ****
XX  	0x10000L * cp[0] + 0x1000000L * cp[1]);
XX  }
XX  
XX! addmove(pos)
XX  long pos;
XX  {
XX    struct mov_list *newmove;
XX--- 347,355 ----
XX  	0x10000L * cp[0] + 0x1000000L * cp[1]);
XX  }
XX  
XX! #endif /* not SARMAG */
XX! 
XX! void addmove(pos)
XX  long pos;
XX  {
XX    struct mov_list *newmove;
XX***************
XX*** 324,331 ****
XX    moves = newmove;
XX  }
XX  
XX! struct i_ar_hdr *
XX!  get_member(fd)
XX  int fd;
XX  {
XX    int ret;
XX--- 360,366 ----
XX    moves = newmove;
XX  }
XX  
XX! struct i_ar_hdr *get_member(fd)
XX  int fd;
XX  {
XX    int ret;
XX***************
XX*** 334,361 ****
XX  
XX    if ((ret = read(fd, (char *) &xmember, (unsigned) SIZEOF_AR_HDR)) <= 0)
XX  	return((struct i_ar_hdr *) NULL);
XX!   if (ret != SIZEOF_AR_HDR) {
XX! 	fprintf(stderr, "Error: ar corrupted archive %s\n", afile);
XX! 	quit(mypid, SIGINT);
XX!   }
XX  
XX    /* The archive long format is pdp11 not intel therefore we must
XX     * reformat them for our internal use */
XX  
XX    strncpy(member.ar_name, xmember.ar_name, sizeof member.ar_name);
XX    member.ar_date = p4_to_long(xmember.ar_date);
XX    member.ar_uid = xmember.ar_uid;
XX    member.ar_gid = xmember.ar_gid;
XX    member.ar_mode = p2_to_int(xmember.ar_mode);
XX    member.ar_size = p4_to_long(xmember.ar_size);
XX    return(&member);
XX  }
XX  
XX  int open_archive(filename, opt, to_create)
XX  char *filename;
XX  int opt;
XX  {
XX!   static unsigned short magic;
XX    int fd, omode;
XX  
XX    /* To_create can have values of 0,1,2 */
XX--- 369,411 ----
XX  
XX    if ((ret = read(fd, (char *) &xmember, (unsigned) SIZEOF_AR_HDR)) <= 0)
XX  	return((struct i_ar_hdr *) NULL);
XX!   errno = 0;
XX!   if (ret != SIZEOF_AR_HDR) error("corrupted archive", afile);
XX  
XX    /* The archive long format is pdp11 not intel therefore we must
XX     * reformat them for our internal use */
XX  
XX    strncpy(member.ar_name, xmember.ar_name, sizeof member.ar_name);
XX+   member.ar_name[sizeof member.ar_name - 1] = '\0';
XX+ #ifdef SARMAG
XX+   /* XXX - It is possible for fields to be joined.  Another stupid format.
XX+    * The bounds checking could be improved.
XX+    */
XX+   member.ar_date = (time_t) strtol(xmember.ar_date, (char **) NULL, 10);
XX+   member.ar_uid = (uid_t) strtol(xmember.ar_uid, (char **) NULL, 10);
XX+   member.ar_gid = (gid_t) strtol(xmember.ar_gid, (char **) NULL, 10);
XX+   member.ar_mode = (mode_t) strtol(xmember.ar_mode, (char **) NULL, 8);
XX+   member.ar_size = (off_t) strtol(xmember.ar_size, (char **) NULL, 10);
XX+ #else
XX    member.ar_date = p4_to_long(xmember.ar_date);
XX    member.ar_uid = xmember.ar_uid;
XX    member.ar_gid = xmember.ar_gid;
XX    member.ar_mode = p2_to_int(xmember.ar_mode);
XX    member.ar_size = p4_to_long(xmember.ar_size);
XX+ #endif
XX    return(&member);
XX  }
XX  
XX  int open_archive(filename, opt, to_create)
XX  char *filename;
XX  int opt;
XX+ int to_create;
XX  {
XX! #ifdef SARMAG
XX!   char magic[SARMAG];
XX! #else
XX!   unsigned short magic;
XX! #endif
XX    int fd, omode;
XX  
XX    /* To_create can have values of 0,1,2 */
XX***************
XX*** 364,396 ****
XX    /* 2 - create file but don't talk about it */
XX  
XX    if (to_create) {
XX! 	if ((fd = creat(filename, 0644)) < 0) {
XX! 		fprintf(stderr, "Error: %s can not create %s\n", progname, filename);
XX! 		quit(mypid, SIGINT);
XX! 	}
XX  	if (!create && to_create == 1)
XX  		fprintf(stderr, "%s:%s created\n", progname, filename);
XX  	magic = ARMAG;
XX  	mwrite(fd, &magic, MAGICSIZE);
XX  	return(fd);
XX    } else {
XX  	omode = (opt == READ ? O_RDONLY : O_RDWR);
XX  	if ((fd = open(filename, omode)) < 0) {
XX  		if (opt == WRITE)
XX  			return(open_archive(filename, opt, 1));
XX! 		else {
XX! 			fprintf(stderr, "Error: %s can not open %s\n", progname, filename);
XX! 			quit(mypid, SIGINT);
XX! 		}
XX  	}
XX  
XX! 	/* Now check the magic number for ar V7 file */
XX  	lseek(fd, 0l, SEEK_SET);
XX! 	read(fd, (char *) &magic, MAGICSIZE);
XX! 	if (magic != ARMAG) {
XX! 		fprintf(stderr, "Error: not %s V7 format - %s\n", progname, filename);
XX! 		quit(mypid, SIGINT);
XX! 	}
XX  	if (Major & APPEND)
XX  		lseek(fd, 0l, SEEK_END);	/* seek eof position */
XX  
XX--- 414,452 ----
XX    /* 2 - create file but don't talk about it */
XX  
XX    if (to_create) {
XX! 	if ((fd = creat(filename, 0644)) < 0)
XX! 		error("can not create archive", filename);
XX  	if (!create && to_create == 1)
XX  		fprintf(stderr, "%s:%s created\n", progname, filename);
XX+ 	outname = filename;
XX+ #ifdef SARMAG
XX+ 	mwrite(fd, ARMAG, MAGICSIZE);
XX+ #else
XX  	magic = ARMAG;
XX  	mwrite(fd, &magic, MAGICSIZE);
XX+ #endif
XX  	return(fd);
XX    } else {
XX  	omode = (opt == READ ? O_RDONLY : O_RDWR);
XX  	if ((fd = open(filename, omode)) < 0) {
XX  		if (opt == WRITE)
XX  			return(open_archive(filename, opt, 1));
XX! 		else
XX! 			error("can not open archive", filename);
XX  	}
XX  
XX! 	/* Check the magic number */
XX! 	errno = 0;
XX  	lseek(fd, 0l, SEEK_SET);
XX! #ifdef SARMAG
XX! 	if (read(fd, magic, MAGICSIZE) != MAGICSIZE
XX! 	    || strncmp(magic, ARMAG, MAGICSIZE) != 0)
XX! 		error(filename, "not in ASCII format");
XX! #else
XX! 	if (read(fd, (char *) &magic, MAGICSIZE) != MAGICSIZE
XX! 	    || magic != ARMAG)
XX! 		error(filename, "not in V7 format");
XX! #endif
XX  	if (Major & APPEND)
XX  		lseek(fd, 0l, SEEK_END);	/* seek eof position */
XX  
XX***************
XX*** 413,431 ****
XX    close(tempfd);
XX    fd = open_archive(afile, WRITE, 2);
XX    tempfd = open_archive(tmp1, WRITE, 0);
XX    while ((n = read(tempfd, buffer, BUFFERSIZE)) > 0) mwrite(fd, buffer, n);
XX    close(tempfd);
XX    unlink(tmp1);
XX    return(fd);
XX  }
XX  
XX! print_mode(mode)
XX! short mode;
XX  {
XX    char g_ex, o_ex, all_ex;
XX    char g_rd, o_rd, all_rd;
XX    char g_wr, o_wr, all_wr;
XX  
XX    g_ex = EXEC_GROUP & mode ? 'x' : '-';
XX    o_ex = EXEC_OWNER & mode ? 'x' : '-';
XX    all_ex = EXEC_ALL & mode ? 'x' : '-';
XX--- 469,490 ----
XX    close(tempfd);
XX    fd = open_archive(afile, WRITE, 2);
XX    tempfd = open_archive(tmp1, WRITE, 0);
XX+   outname = afile;
XX    while ((n = read(tempfd, buffer, BUFFERSIZE)) > 0) mwrite(fd, buffer, n);
XX    close(tempfd);
XX    unlink(tmp1);
XX    return(fd);
XX  }
XX  
XX! void print_Mode(mowed)
XX! int mowed;
XX  {
XX+   mode_t mode; 		      /* avoid promotion problems by using int param */
XX    char g_ex, o_ex, all_ex;
XX    char g_rd, o_rd, all_rd;
XX    char g_wr, o_wr, all_wr;
XX  
XX+   mode = mowed;
XX    g_ex = EXEC_GROUP & mode ? 'x' : '-';
XX    o_ex = EXEC_OWNER & mode ? 'x' : '-';
XX    all_ex = EXEC_ALL & mode ? 'x' : '-';
XX***************
XX*** 441,485 ****
XX    o_wr = WRITE_OWNER & mode ? 'w' : '-';
XX    all_wr = WRITE_ALL & mode ? 'w' : '-';
XX  
XX!   fprintf(stdout, "%c%c%c", o_rd, o_wr, o_ex);
XX!   fprintf(stdout, "%c%c%c", g_rd, g_wr, g_ex);
XX!   fprintf(stdout, "%c%c%c", all_rd, all_wr, all_ex);
XX  }
XX  
XX! print_header(member)
XX  struct i_ar_hdr *member;
XX  {
XX    if (verbose) {
XX! 	print_mode(member->ar_mode);
XX! 	fprintf(stdout, "%3.3d", member->ar_uid);
XX! 	fprintf(stdout, "/%-3.3d ", member->ar_gid);
XX! 	fprintf(stdout, "%5.5D", member->ar_size);	/* oops is long - mrw */
XX! 	print_date(member->ar_date);
XX    }
XX!   fprintf(stdout, "%-14.14s\n", member->ar_name);
XX  }
XX  
XX! print(fd, member)
XX  int fd;
XX  struct i_ar_hdr *member;
XX  {
XX    int outfd;
XX    long size;
XX    register int cnt, ret;
XX-   int do_align;
XX  
XX    if (Major & EXTRACT) {
XX! 	if ((outfd = creat(member->ar_name, 0666)) < 0) {
XX! 		fprintf(stderr, "Error: %s could not creat %-14.14s\n", progname, member->ar_name);
XX! 		quit(mypid, SIGINT);
XX! 	}
XX! 	if (verbose) fprintf(stdout, "x - %-14.14s\n", member->ar_name);
XX    } else {
XX  	if (verbose) {
XX! 		fprintf(stdout, "p - %-14.14s\n", member->ar_name);
XX  		fflush(stdout);
XX  	}
XX  	outfd = fileno(stdout);
XX    }
XX  
XX    /* Changed loop to use long size for correct extracts */
XX--- 500,545 ----
XX    o_wr = WRITE_OWNER & mode ? 'w' : '-';
XX    all_wr = WRITE_ALL & mode ? 'w' : '-';
XX  
XX!   printf("%c%c%c", o_rd, o_wr, o_ex);
XX!   printf("%c%c%c", g_rd, g_wr, g_ex);
XX!   printf("%c%c%c", all_rd, all_wr, all_ex);
XX  }
XX  
XX! void print_header(member)
XX  struct i_ar_hdr *member;
XX  {
XX+   char *ctime_string;
XX+ 
XX    if (verbose) {
XX! 	print_Mode((int) member->ar_mode);
XX! 	ctime_string = ctime(&member->ar_date);
XX! 	printf(" %3u/%-3u %6ld %12.12s %4.4s ",
XX! 	       member->ar_uid, member->ar_gid, member->ar_size,
XX! 	       ctime_string + 4, ctime_string + 20);
XX    }
XX!   puts(member->ar_name);
XX  }
XX  
XX! void print_member(fd, member)
XX  int fd;
XX  struct i_ar_hdr *member;
XX  {
XX    int outfd;
XX    long size;
XX    register int cnt, ret;
XX  
XX    if (Major & EXTRACT) {
XX! 	if ((outfd = creat(member->ar_name, 0666)) < 0)
XX! 		error("can not create file", member->ar_name);
XX! 	if (verbose) printf("x - %s\n", member->ar_name);
XX! 	outname = member->ar_name;
XX    } else {
XX  	if (verbose) {
XX! 		printf("p - %s\n", member->ar_name);
XX  		fflush(stdout);
XX  	}
XX  	outfd = fileno(stdout);
XX+ 	outname = "stdout";
XX    }
XX  
XX    /* Changed loop to use long size for correct extracts */
XX***************
XX*** 497,503 ****
XX  }
XX  
XX  /* Copy a given member from fd1 to fd2 */
XX! copy_member(infd, outfd, member)
XX  int infd, outfd;
XX  struct i_ar_hdr *member;
XX  {
XX--- 557,563 ----
XX  }
XX  
XX  /* Copy a given member from fd1 to fd2 */
XX! void copy_member(infd, outfd, member)
XX  int infd, outfd;
XX  struct i_ar_hdr *member;
XX  {
XX***************
XX*** 510,528 ****
XX  
XX    /* Format for disk usage */
XX    strncpy(xmember.ar_name, member->ar_name, sizeof xmember.ar_name);
XX    long_to_p4(xmember.ar_date, member->ar_date);
XX    xmember.ar_uid = member->ar_uid;
XX    xmember.ar_gid = member->ar_gid;
XX    int_to_p2(xmember.ar_mode, member->ar_mode);
XX    long_to_p4(xmember.ar_size, member->ar_size);
XX  
XX    mwrite(outfd, (char *) &xmember, (int) SIZEOF_AR_HDR);
XX    for (; m > 0; m -= n) {
XX  	cnt = (m < BUFFERSIZE ? m : BUFFERSIZE);
XX! 	if ((n = read(infd, buffer, cnt)) != cnt) {
XX! 		fprintf(stderr, "Error: %s - read error on %-14.14s\n", progname, member->ar_name);
XX! 		quit(mypid, SIGINT);
XX! 	}
XX  	mwrite(outfd, buffer, n);
XX    }
XX    if (odd(size)) {		/* pad to word boundary */
XX--- 570,610 ----
XX  
XX    /* Format for disk usage */
XX    strncpy(xmember.ar_name, member->ar_name, sizeof xmember.ar_name);
XX+ #ifdef SARMAG
XX+   /* The following won't overrun the the arrays, because assuming ar.h has
XX+    * been designed to match the scalar types being printed, and that the
XX+    * size is reasonable (LONG_MIN won't fit).  However, spaces between the
XX+    * fields are not guaranteed.
XX+    */
XX+   sprintf(xmember.ar_date, "%d", member->ar_date);
XX+   sprintf(xmember.ar_uid, "%d", member->ar_uid);
XX+   sprintf(xmember.ar_gid, "%d", member->ar_gid);
XX+   sprintf(xmember.ar_mode, "%o", member->ar_mode);
XX+   sprintf(xmember.ar_size, "%d", member->ar_size);
XX+   strncpy(xmember.ar_fmag, ARFMAG, sizeof xmember.ar_fmag);
XX+ 
XX+   /* Change any nulls in the header to spaces. */
XX+   {
XX+ 	char *endpad;
XX+ 	register char *pad;
XX+ 
XX+ 	for (pad = (char *) &xmember, endpad = (char *) (&xmember + 1);
XX+ 	     pad < endpad; ++pad)
XX+ 		if (*pad == '\0') *pad = ' ';
XX+   }
XX+ #else
XX    long_to_p4(xmember.ar_date, member->ar_date);
XX    xmember.ar_uid = member->ar_uid;
XX    xmember.ar_gid = member->ar_gid;
XX    int_to_p2(xmember.ar_mode, member->ar_mode);
XX    long_to_p4(xmember.ar_size, member->ar_size);
XX+ #endif
XX  
XX    mwrite(outfd, (char *) &xmember, (int) SIZEOF_AR_HDR);
XX    for (; m > 0; m -= n) {
XX  	cnt = (m < BUFFERSIZE ? m : BUFFERSIZE);
XX! 	if ((n = read(infd, buffer, cnt)) != cnt)
XX! 		error("read error on file", member->ar_name);
XX  	mwrite(outfd, buffer, n);
XX    }
XX    if (odd(size)) {		/* pad to word boundary */
XX***************
XX*** 532,538 ****
XX  }
XX  
XX  /* Insert at current offset - name file */
XX! insert(fd, name, mess, oldmember)
XX  int fd;
XX  char *name, *mess;
XX  struct i_ar_hdr *oldmember;
XX--- 614,620 ----
XX  }
XX  
XX  /* Insert at current offset - name file */
XX! int insert(fd, name, mess, oldmember)
XX  int fd;
XX  char *name, *mess;
XX  struct i_ar_hdr *oldmember;
XX***************
XX*** 541,554 ****
XX    static struct stat status;
XX    int in_fd;
XX  
XX!   if (stat(name, &status) < 0) {
XX! 	fprintf(stderr, "Error: %s cannot find file %s\n", progname, name);
XX! 	quit(mypid, SIGINT);
XX!   } else if ((in_fd = open(name, O_RDONLY)) < 0) {
XX! 	fprintf(stderr, "Error: %s cannot open file %s\n", progname, name);
XX! 	quit(mypid, SIGINT);
XX!   }
XX!   strncpy(member.ar_name, basename(name), 14);
XX    member.ar_uid = status.st_uid;
XX    member.ar_gid = status.st_gid;
XX    member.ar_mode = status.st_mode & 07777;
XX--- 623,634 ----
XX    static struct stat status;
XX    int in_fd;
XX  
XX!   if (stat(name, &status) < 0)
XX! 	error("can not find file", name);
XX!   else if ((in_fd = open(name, O_RDONLY)) < 0)
XX! 	error("can not open file", name);
XX!   strncpy(member.ar_name, basename(name), sizeof member.ar_name - 1);
XX!   member.ar_name[sizeof member.ar_name - 1] = '\0';
XX    member.ar_uid = status.st_uid;
XX    member.ar_gid = status.st_gid;
XX    member.ar_mode = status.st_mode & 07777;
XX***************
XX*** 559,569 ****
XX  		if (member.ar_date <= oldmember->ar_date) {
XX  			close(in_fd);
XX  			if (verbose)
XX! 				fprintf(stdout, "not %-14.14s - %-14.14s\n", mess, name);
XX  			return(-1);
XX  		}
XX    copy_member(in_fd, fd, &member);
XX!   if (verbose) fprintf(stdout, "%s - %-14.14s\n", mess, name);
XX    close(in_fd);
XX    return(1);
XX  }
XX--- 639,649 ----
XX  		if (member.ar_date <= oldmember->ar_date) {
XX  			close(in_fd);
XX  			if (verbose)
XX! 				printf("not %s - %s\n", mess, name);
XX  			return(-1);
XX  		}
XX    copy_member(in_fd, fd, &member);
XX!   if (verbose) printf("%s - %s\n", mess, name);
XX    close(in_fd);
XX    return(1);
XX  }
XX***************
XX*** 573,579 ****
XX  struct mov_list *mov;
XX  {
XX    long pos;
XX!   int cnt, want, a, newfd;
XX    struct i_ar_hdr *member;
XX  
XX    if (local)
XX--- 653,659 ----
XX  struct mov_list *mov;
XX  {
XX    long pos;
XX!   int cnt, want, newfd;
XX    struct i_ar_hdr *member;
XX  
XX    if (local)
XX***************
XX*** 605,611 ****
XX  	if ((member = get_member(arfd)) != NULL)
XX  		copy_member(arfd, newfd, member);
XX  	mov = mov->next;
XX! 	if (verbose) fprintf(stdout, "m - %-14.14s\n", member->ar_name);
XX    }
XX  
XX    /* Copy rest of library into new tmp file */
XX--- 685,691 ----
XX  	if ((member = get_member(arfd)) != NULL)
XX  		copy_member(arfd, newfd, member);
XX  	mov = mov->next;
XX! 	if (verbose) printf("m - %s\n", member->ar_name);
XX    }
XX  
XX    /* Copy rest of library into new tmp file */
XX***************
XX*** 673,679 ****
XX    return(newfd);
XX  }
XX  
XX! ar_common(ac, argc, argv)
XX  int ac, argc;
XX  char **argv;
XX  {
XX--- 753,759 ----
XX    return(newfd);
XX  }
XX  
XX! void ar_common(ac, argc, argv)
XX  int ac, argc;
XX  char **argv;
XX  {
XX***************
XX*** 685,695 ****
XX  	did_print = 0;
XX  	if (ac < argc) {
XX  		for (a = ac + 1; a <= argc; ++a) {
XX! 			if (strncmp(basename(argv[a - 1]), member->ar_name, 14) == 0) {
XX  				if (Major & TABLE)
XX  					print_header(member);
XX  				else if (Major & (PRINT | EXTRACT)) {
XX! 					print(fd, member);
XX  					did_print = 1;
XX  				}
XX  				*argv[a - 1] = '\0';
XX--- 765,775 ----
XX  	did_print = 0;
XX  	if (ac < argc) {
XX  		for (a = ac + 1; a <= argc; ++a) {
XX! 			if (strcmp(basename(argv[a - 1]), member->ar_name) == 0) {
XX  				if (Major & TABLE)
XX  					print_header(member);
XX  				else if (Major & (PRINT | EXTRACT)) {
XX! 					print_member(fd, member);
XX  					did_print = 1;
XX  				}
XX  				*argv[a - 1] = '\0';
XX***************
XX*** 700,706 ****
XX  		if (Major & TABLE)
XX  			print_header(member);
XX  		else if (Major & (PRINT | EXTRACT)) {
XX! 			print(fd, member);
XX  			did_print = 1;
XX  		}
XX  	}
XX--- 780,786 ----
XX  		if (Major & TABLE)
XX  			print_header(member);
XX  		else if (Major & (PRINT | EXTRACT)) {
XX! 			print_member(fd, member);
XX  			did_print = 1;
XX  		}
XX  	}
XX***************
XX*** 711,723 ****
XX    }
XX  }
XX  
XX! ar_members(ac, argc, argv)
XX  int ac, argc;
XX  char **argv;
XX  {
XX!   int a, fd, tempfd, rc;
XX    struct i_ar_hdr *member;
XX-   long *lpos;
XX  
XX    fd = open_archive(afile, WRITE, 0);
XX    tempfd = open_archive(tmp1, WRITE, 2);
XX--- 791,802 ----
XX    }
XX  }
XX  
XX! void ar_members(ac, argc, argv)
XX  int ac, argc;
XX  char **argv;
XX  {
XX!   int a, fd, tempfd;
XX    struct i_ar_hdr *member;
XX  
XX    fd = open_archive(afile, WRITE, 0);
XX    tempfd = open_archive(tmp1, WRITE, 2);
XX***************
XX*** 725,736 ****
XX  
XX  	/* If posname specified check for our member */
XX  	/* If our member save his starting pos in our working file */
XX! 	if (posname && strncmp(posname, member->ar_name, 14) == 0)
XX  		pos_offset = tell(tempfd) - MAGICSIZE;
XX  
XX  	if (ac < argc) {	/* we have a list of members to check */
XX  		for (a = ac + 1; a <= argc; ++a)
XX! 			if (strncmp(basename(argv[a - 1]), member->ar_name, 14) == 0) {
XX  				if (Major & REPLACE) {
XX  					if (insert(tempfd, argv[a - 1], "r", member) < 0)
XX  						copy_member(fd, tempfd, member);
XX--- 804,815 ----
XX  
XX  	/* If posname specified check for our member */
XX  	/* If our member save his starting pos in our working file */
XX! 	if (posname && strcmp(posname, member->ar_name) == 0)
XX  		pos_offset = tell(tempfd) - MAGICSIZE;
XX  
XX  	if (ac < argc) {	/* we have a list of members to check */
XX  		for (a = ac + 1; a <= argc; ++a)
XX! 			if (strcmp(basename(argv[a - 1]), member->ar_name) == 0) {
XX  				if (Major & REPLACE) {
XX  					if (insert(tempfd, argv[a - 1], "r", member) < 0)
XX  						copy_member(fd, tempfd, member);
XX***************
XX*** 749,765 ****
XX  		copy_member(fd, tempfd, member);
XX  	else if (Major & DELETE) {
XX  		if (verbose)
XX! 			fprintf(stdout, "d - %-14.14s\n", member->ar_name);
XX  		lseek(fd, (long) even(member->ar_size), SEEK_CUR);
XX  	}
XX    }
XX    if (Major & MOVE) {
XX  	if (posname == NULL)
XX  		pos_offset = lseek(fd, 0l, SEEK_END);
XX! 	else if (pos_offset == (-1)) {
XX! 		fprintf(stderr, "Error: %s cannot find file %-14.14s\n", progname, posname);
XX! 		quit(mypid, SIGINT);
XX! 	}
XX  	tempfd = ar_move(tempfd, fd, moves);
XX    } else if (Major & REPLACE) {
XX  	/* Take care to add left overs */
XX--- 828,842 ----
XX  		copy_member(fd, tempfd, member);
XX  	else if (Major & DELETE) {
XX  		if (verbose)
XX! 			printf("d - %s\n", member->ar_name);
XX  		lseek(fd, (long) even(member->ar_size), SEEK_CUR);
XX  	}
XX    }
XX    if (Major & MOVE) {
XX  	if (posname == NULL)
XX  		pos_offset = lseek(fd, 0l, SEEK_END);
XX! 	else if (pos_offset == (-1))
XX! 		error("can not find file", posname);
XX  	tempfd = ar_move(tempfd, fd, moves);
XX    } else if (Major & REPLACE) {
XX  	/* Take care to add left overs */
XX***************
XX*** 778,789 ****
XX    close(fd);
XX  }
XX  
XX! append_members(ac, argc, argv)
XX  int ac, argc;
XX  char **argv;
XX  {
XX    int a, fd;
XX-   struct i_ar_hdr *member;
XX  
XX    /* Quickly append members don't worry about dups in ar */
XX    fd = open_archive(afile, WRITE, 0);
XX--- 855,865 ----
XX    close(fd);
XX  }
XX  
XX! void append_members(ac, argc, argv)
XX  int ac, argc;
XX  char **argv;
XX  {
XX    int a, fd;
XX  
XX    /* Quickly append members don't worry about dups in ar */
XX    fd = open_archive(afile, WRITE, 0);
XX***************
XX*** 817,875 ****
XX    return last + 1;
XX  }
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[] = {
XX!       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
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.  This only works from 1970 to 2099. */
XX! print_date(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!   fprintf(stdout, "%s%2.2d ", moname[month], ++day);
XX!   if (time((long *) NULL) - original >= YEAR / 2L)
XX! 	fprintf(stdout, "%4.4D ", (long) year);
XX!   else
XX! 	fprintf(stdout, "%02.2d:%02.2d ", hour, minute);
XX  }
XX--- 893,915 ----
XX    return last + 1;
XX  }
XX  
XX! void error(str1, str2)
XX! char *str1;
XX! char *str2;
XX  {
XX! /* Print a message about the error.
XX!  * Kill the current process to to insure that we get the current cleanup and
XX!  * exit logic.  Sleep a while to allow the cleanup.  The exit should normally
XX!  * be done by the signal handler and not here.
XX!  */
XX  
XX!   int old_errno;
XX  
XX!   old_errno = errno;
XX!   fprintf(stderr, "%s: %s %s", progname, str1, str2);
XX!   if (old_errno != 0) fprintf(stderr, ": %s", strerror(old_errno));
XX!   fprintf(stderr, "\n");
XX!   kill(getpid(), SIGINT);
XX!   sleep(20);
XX!   exit(EXIT_FAILURE);
XX  }
X/
Xecho x - ast.c.d
Xsed '/^X/s///' > ast.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/ast.c  crc=48518   5955	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/ast.c  crc=08750   6419	Thu Jul 16 12:21:31 1992
XX***************
XX*** 1,8 ****
XX  /* ast - add symbol table.		Author: Dick van Veen */
XX  
XX  #include <sys/types.h>
XX- #include <fcntl.h>
XX  #include <a.out.h>
XX  #include <stdio.h>
XX  
XX  /* Since the a.out file in MINIX does not contain any symbol table,
XX--- 1,10 ----
XX  /* ast - add symbol table.		Author: Dick van Veen */
XX  
XX  #include <sys/types.h>
XX  #include <a.out.h>
XX+ #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  /* Since the a.out file in MINIX does not contain any symbol table,
XX***************
XX*** 49,62 ****
XX  char buffer[LINE_LENGTH];	/* contains line of symbol file */
XX  
XX  char io_buf[BUFSIZ];		/* for buffered output on stderr */
XX- unsigned int get_value();	/* forward definition */
XX  
XX  main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX-   extern FILE *fopen();
XX- 
XX    argv++;
XX    if (*argv != NULL && **argv == '-') {
XX  	*argv += 1;
XX--- 51,72 ----
XX  char buffer[LINE_LENGTH];	/* contains line of symbol file */
XX  
XX  char io_buf[BUFSIZ];		/* for buffered output on stderr */
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(int ast, (FILE *s_fd, FILE *o_fd));
XX+ _PROTOTYPE(int read_line, (FILE *fd, char *buffer));
XX+ _PROTOTYPE(int transform_line, (char *buffer, struct nlist *symbol));
XX+ _PROTOTYPE(int save_line, (FILE *fd, struct nlist *symbol));
XX+ _PROTOTYPE(unsigned get_value, (char *string));
XX+ _PROTOTYPE(int get_bits, (int ch));
XX+ _PROTOTYPE(int get_name, (char *str1, char *str2));
XX+ _PROTOTYPE(int do_header, (void));
XX+ _PROTOTYPE(int redo_header, (FILE *fd));
XX+ 
XX  main(argc, argv)
XX  int argc;
XX  char **argv;
XX  {
XX    argv++;
XX    if (*argv != NULL && **argv == '-') {
XX  	*argv += 1;
XX***************
XX*** 251,257 ****
XX    int fd;
XX  
XX    fd = open(o_file, O_RDONLY);
XX!   if (read(fd, &header, sizeof(struct exec)) != sizeof(struct exec)) {
XX  	fprintf(stderr, "%s: no executable file\n", o_file);
XX  	exit(-1);
XX    }
XX--- 261,267 ----
XX    int fd;
XX  
XX    fd = open(o_file, O_RDONLY);
XX!   if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec)) {
XX  	fprintf(stderr, "%s: no executable file\n", o_file);
XX  	exit(-1);
XX    }
X/
Xecho x - cc.c.d
Xsed '/^X/s///' > cc.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/cc.c  crc=12611  10047	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/cc.c  crc=12484  11308	Mon Nov 16 19:33:55 1992
XX***************
XX*** 1,7 ****
XX--- 1,13 ----
XX  /* cc - call the C compiler		Author: Erik Baalbergen */
XX  
XX+ #include <sys/types.h>
XX+ #include <sys/wait.h>
XX  #include <errno.h>
XX+ #include <fcntl.h>
XX  #include <signal.h>
XX+ #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  
XX  #define SYMBOL_FILE	"symbol.out"		/* symbol table for prof */
XX  
XX***************
XX*** 10,15 ****
XX--- 16,39 ----
XX  
XX  typedef char USTRING[USTR_SIZE];
XX  
XX+ struct arglist;
XX+ _PROTOTYPE(void trapcc, (int sig ));
XX+ _PROTOTYPE(int main, (int argc, char *argv []));
XX+ _PROTOTYPE(char *alloc, (unsigned u ));
XX+ _PROTOTYPE(int append, (struct arglist *al, char *arg ));
XX+ _PROTOTYPE(int concat, (struct arglist *al1, struct arglist *al2 ));
XX+ char *mkstr();
XX+ _PROTOTYPE(int basename, (char *str, char *dst ));
XX+ _PROTOTYPE(int extension, (char *fn ));
XX+ _PROTOTYPE(int runvec, (struct arglist *vec, char *outp ));
XX+ _PROTOTYPE(int runvec2, (struct arglist *vec0, struct arglist *vec1 ));
XX+ _PROTOTYPE(int panic, (char *str ));
XX+ _PROTOTYPE(char *cindex, (char *s, int c ));
XX+ _PROTOTYPE(int pr_vec, (struct arglist *vec ));
XX+ _PROTOTYPE(int ex_vec, (struct arglist *vec ));
XX+ _PROTOTYPE(int mktempname, (char nm []));
XX+ 
XX+ 
XX  struct arglist {
XX  	int al_argc;
XX  	char *al_argv[MAXARGC];
XX***************
XX*** 17,22 ****
XX--- 41,59 ----
XX  
XX  
XX  /* MINIX paths */
XX+ #ifdef RAMDSK
XX+ char *PP     = "/lib/cpp";
XX+ char *CEM    = "/lib/cem";
XX+ char *OPT    = "/lib/opt";
XX+ char *CG     = "/lib/cg";
XX+ char *ASLD   = "/bin/asld";
XX+ char *AST    = "/bin/ast";
XX+ char *SHELL  = "/bin/sh";
XX+ char *LIBDIR = "/lib";
XX+ struct arglist LD_HEAD =    {1, { "/lib/crtso.s" } };
XX+ struct arglist M_LD_HEAD =  {1, { "/lib/mrtso.s" } };
XX+ struct arglist LD_TAIL =    {2, { "/lib/libc.a", "/lib/end.s" } };
XX+ #else
XX  char *PP     = "/usr/lib/cpp";
XX  char *CEM    = "/usr/lib/cem";
XX  char *OPT    = "/usr/lib/opt";
XX***************
XX*** 25,34 ****
XX  char *AST    = "/usr/bin/ast";
XX  char *SHELL  = "/bin/sh";
XX  char *LIBDIR = "/usr/lib";
XX- 
XX  struct arglist LD_HEAD =    {1, { "/usr/lib/crtso.s" } };
XX  struct arglist M_LD_HEAD =  {1, { "/usr/lib/mrtso.s" } };
XX  struct arglist LD_TAIL =    {2, { "/usr/lib/libc.a", "/usr/lib/end.s" } };
XX  
XX  char *o_FILE = "a.out"; /* default name for executable file */
XX  
XX--- 62,71 ----
XX  char *AST    = "/usr/bin/ast";
XX  char *SHELL  = "/bin/sh";
XX  char *LIBDIR = "/usr/lib";
XX  struct arglist LD_HEAD =    {1, { "/usr/lib/crtso.s" } };
XX  struct arglist M_LD_HEAD =  {1, { "/usr/lib/mrtso.s" } };
XX  struct arglist LD_TAIL =    {2, { "/usr/lib/libc.a", "/usr/lib/end.s" } };
XX+ #endif
XX  
XX  char *o_FILE = "a.out"; /* default name for executable file */
XX  
XX***************
XX*** 67,82 ****
XX  int s_flag = 0;
XX  int p_flag = 0;	/* profil flag */
XX  
XX- char *mkstr();
XX- char *alloc();
XX- 
XX  USTRING ifile, kfile, sfile, mfile, ofile;
XX  USTRING BASE;
XX  
XX  char *tmpdir = "/tmp";
XX  char tmpname[15];
XX  
XX! trapcc(sig)
XX  	int sig;
XX  {
XX  	signal(sig, SIG_IGN);
XX--- 104,116 ----
XX  int s_flag = 0;
XX  int p_flag = 0;	/* profil flag */
XX  
XX  USTRING ifile, kfile, sfile, mfile, ofile;
XX  USTRING BASE;
XX  
XX  char *tmpdir = "/tmp";
XX  char tmpname[15];
XX  
XX! void trapcc(sig)
XX  	int sig;
XX  {
XX  	signal(sig, SIG_IGN);
XX***************
XX*** 261,267 ****
XX  			append(call, CG);
XX  			concat(call, &CG_FLAGS);
XX  			append(call, file);
XX! 			f = mkstr(ldfile, BASE, ".s", 0);
XX  			append(call, f);
XX  			if (runvec(call, (char *)0) == 0)
XX  				continue;
XX--- 295,301 ----
XX  			append(call, CG);
XX  			concat(call, &CG_FLAGS);
XX  			append(call, file);
XX! 			f = mkstr(ldfile, BASE, ".s", "", 0);
XX  			append(call, f);
XX  			if (runvec(call, (char *)0) == 0)
XX  				continue;
XX***************
XX*** 355,362 ****
XX  
XX  /*VARARGS1*/
XX  char *
XX! mkstr(dst, arg)
XX  	char *dst, *arg;
XX  {
XX  	char **vec = (char **) &arg;
XX  	register char *p;
XX--- 389,398 ----
XX  
XX  /*VARARGS1*/
XX  char *
XX! mkstr(dst, arg, s1, s2, n)
XX  	char *dst, *arg;
XX+ 	char *s1, *s2;
XX+ 	int n;
XX  {
XX  	char **vec = (char **) &arg;
XX  	register char *p;
XX***************
XX*** 467,475 ****
XX  }
XX  
XX  /*VARARGS1*/
XX! panic(str, argv)
XX  	char *str;
XX- 	int argv;
XX  {
XX  	write(2, str, strlen(str));
XX  	exit(1);
XX--- 503,510 ----
XX  }
XX  
XX  /*VARARGS1*/
XX! panic(str)
XX  	char *str;
XX  {
XX  	write(2, str, strlen(str));
XX  	exit(1);
X/
Xecho x - dosread.c.d
Xsed '/^X/s///' > dosread.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/dosread.c  crc=01097  23331	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/dosread.c  crc=52006  25440	Thu Oct  8 00:09:20 1992
XX***************
XX*** 11,19 ****
XX--- 11,23 ----
XX   *	  a: Set ASCII bit.
XX   */
XX  
XX+ #include <ctype.h>
XX  #include <sys/types.h>
XX  #include <sys/stat.h>
XX  #include <fcntl.h>
XX+ #include <stdlib.h>
XX+ #include <string.h>
XX+ #include <time.h>
XX  #include <unistd.h>
XX  
XX  #define DRIVE		"/dev/dosX"
XX***************
XX*** 22,28 ****
XX  #define MAX_CLUSTER_SIZE	4096
XX  #define MAX_ROOT_ENTRIES	512
XX  #define FAT_START		512L	/* After bootsector */
XX! #define ROOTADDR		(FAT_START + 2L * (long) fat_size)
XX  #define clus_add(cl_no)		((long) (((long) cl_no - 2L) \
XX  				* (long) cluster_size \
XX  				+ data_start \
XX--- 26,32 ----
XX  #define MAX_CLUSTER_SIZE	4096
XX  #define MAX_ROOT_ENTRIES	512
XX  #define FAT_START		512L	/* After bootsector */
XX! #define ROOTADDR		(FAT_START + 2L * fat_size)
XX  #define clus_add(cl_no)		((long) (((long) cl_no - 2L) \
XX  				* (long) cluster_size \
XX  				+ data_start \
XX***************
XX*** 54,60 ****
XX  #define BAD		0xFF0
XX  #define BAD16		0xFFF0
XX  
XX! typedef char BOOL;
XX  
XX  #define TRUE	1
XX  #define FALSE	0
XX--- 58,64 ----
XX  #define BAD		0xFF0
XX  #define BAD16		0xFFF0
XX  
XX! typedef int BOOL;
XX  
XX  #define TRUE	1
XX  #define FALSE	0
XX***************
XX*** 64,72 ****
XX  
XX  #define READ			0
XX  #define WRITE			1
XX- #define disk_read(s, a, b)	disk_io(READ, s, a, b)
XX- #define disk_write(s, a, b)	disk_io(WRITE, s, a, b)
XX- 
XX  #define get_fat(f, b)		buf_read(FAT_START + f, b, 1)
XX  
XX  #define put_fat(f, b)		{ disk_io(WRITE, FAT_START + f, b, 1); \
XX--- 68,73 ----
XX***************
XX*** 96,115 ****
XX  unsigned char fat_info;
XX  DIRECTORY root[MAX_ROOT_ENTRIES];
XX  DIRECTORY save_entry;
XX! char null[MAX_CLUSTER_SIZE], device[] = DRIVE, path[128];
XX  long data_start, mark;
XX! unsigned short total_clusters, cluster_size, fat_size, root_entries, sub_entries;
XX  
XX  BOOL Rflag, Lflag, Aflag, dos_read, dos_write, dos_dir, fat_16 = 0;
XX  
XX  char disk_written = 1, buf_buf[1025];
XX  long buf_addr = 0;
XX  
XX! DIRECTORY *directory(), *read_cluster();
XX! unsigned short free_cluster(), next_cluster();
XX! char *make_name(), *num_out(), *slash(), *brk();
XX! long time();
XX  
XX  leave(nr)
XX  short nr;
XX  {
XX--- 97,147 ----
XX  unsigned char fat_info;
XX  DIRECTORY root[MAX_ROOT_ENTRIES];
XX  DIRECTORY save_entry;
XX! char null[MAX_CLUSTER_SIZE], *device = DRIVE, path[128];
XX  long data_start, mark;
XX! unsigned short total_clusters, cluster_size, root_entries, sub_entries;
XX! unsigned long fat_size;
XX  
XX  BOOL Rflag, Lflag, Aflag, dos_read, dos_write, dos_dir, fat_16 = 0;
XX  
XX  char disk_written = 1, buf_buf[1025];
XX  long buf_addr = 0;
XX  
XX! /* Prototypes. */
XX! void print_string();		/* HACK.  Should be varargs */
XX! _PROTOTYPE(int leave, (int nr) );
XX! _PROTOTYPE(int usage, (char *prog_name) );
XX! _PROTOTYPE(unsigned c2u2, (unsigned char *ucarray) );
XX! _PROTOTYPE(unsigned long c4u4, (unsigned char *ucarray) );
XX! _PROTOTYPE(int determine, (void));
XX! _PROTOTYPE(int main, (int argc, char *argv []));
XX! _PROTOTYPE(DIRECTORY *directory, (DIRECTORY *dir, int entries, BOOL function, char *pathname) );
XX! _PROTOTYPE(int extract, (DIRECTORY *entry) );
XX! _PROTOTYPE(int print, (int fd, char *buffer, int bytes) );
XX! _PROTOTYPE(int make_file, (DIRECTORY *dir_ptr, int entries, char *name) );
XX! _PROTOTYPE(int fill_date, (DIRECTORY *entry) );
XX! _PROTOTYPE(char *make_name, (DIRECTORY *dir_ptr, int dir_fl) );
XX! _PROTOTYPE(int fill, (char *buffer) );
XX! _PROTOTYPE(int get_char, (void));
XX! _PROTOTYPE(int xmodes, (int mode) );
XX! _PROTOTYPE(int show, (DIRECTORY *dir_ptr, char *name) );
XX! _PROTOTYPE(int free_blocks, (void));
XX! _PROTOTYPE(char *num_out, (long number) );
XX! /* _PROTOTYPE(void print_string, (BOOL err_fl, char *fmt, int args) ); */
XX! _PROTOTYPE(DIRECTORY *read_cluster, (unsigned int cluster) );
XX! _PROTOTYPE(unsigned short free_cluster, (BOOL leave_fl) );
XX! _PROTOTYPE(int link_fat, (unsigned int cl_1, unsigned int cl_2) );
XX! _PROTOTYPE(unsigned short next_cluster, (unsigned int cl_no) );
XX! _PROTOTYPE(char *slash, (char *str) );
XX! _PROTOTYPE(void add_path, (char *file, BOOL slash_fl) );
XX! _PROTOTYPE(int b_copy, (char *src, char *dest, int bytes) );
XX! _PROTOTYPE(int disk_io, (BOOL op, unsigned long seek, void *address, unsigned bytes) );
XX! _PROTOTYPE(int bad, (void));
XX! _PROTOTYPE(int buf_read, (long seek, char *b, int c) );
XX  
XX+ _PROTOTYPE( void perror, (const char *_s)				);
XX+ 
XX+ 
XX  leave(nr)
XX  short nr;
XX  {
XX***************
XX*** 121,127 ****
XX  register char *prog_name;
XX  {
XX    print_string(TRUE, "Usage: %s [%s\n", prog_name,
XX! 	     dos_dir ? "-lr] drive [dir]" : "-a] drive file");
XX    exit(1);
XX  }
XX  
XX--- 153,159 ----
XX  register char *prog_name;
XX  {
XX    print_string(TRUE, "Usage: %s [%s\n", prog_name,
XX! 	     (int) (dos_dir ? "-lr] drive [dir]" : "-a] drive file"));
XX    exit(1);
XX  }
XX  
XX***************
XX*** 131,136 ****
XX--- 163,176 ----
XX    return ucarray[0] + (ucarray[1] << 8);	/* parens vital */
XX  }
XX  
XX+ unsigned long c4u4(ucarray)
XX+ unsigned char *ucarray;
XX+ {
XX+   return ucarray[0] + ((unsigned long) ucarray[1] << 8) +
XX+ 		      ((unsigned long) ucarray[2] << 16) +
XX+ 		      ((unsigned long) ucarray[3] << 24);
XX+ }
XX+ 
XX  determine()
XX  {
XX    struct dosboot {
XX***************
XX*** 148,180 ****
XX  	unsigned char csecptrack[2];
XX  	unsigned char cheads[2];
XX  	unsigned char chiddensec[2];
XX! 	/* Char    fill[482]; */
XX    } boot;
XX    unsigned short boot_magic;	/* last of boot block */
XX!   unsigned bytepers, reservsec, dirents, totsec;
XX    unsigned secpfat, secptrack, heads, hiddensec;
XX  
XX    int errcount = 0;
XX  
XX    /* Read Bios-Parameterblock */
XX!   disk_read(0L, &boot, sizeof boot);
XX!   disk_read(0x1FEL, &boot_magic, sizeof boot_magic);
XX  
XX    /* Convert some arrays */
XX    bytepers = c2u2(boot.cbytepers);
XX    reservsec = c2u2(boot.creservsec);
XX    dirents = c2u2(boot.cdirents);
XX    totsec = c2u2(boot.ctotsec);
XX    secpfat = c2u2(boot.csecpfat);
XX    secptrack = c2u2(boot.csecptrack);
XX    heads = c2u2(boot.cheads);
XX    hiddensec = c2u2(boot.chiddensec);
XX  
XX    /* Calculate everything. */
XX!   total_clusters = totsec / (boot.secpclus == 0 ? 1 : boot.secpclus);
XX    cluster_size = bytepers * boot.secpclus;
XX!   fat_size = secpfat * bytepers;
XX!   data_start = (long) bytepers + (long) boot.fats * (long) fat_size
XX  	+ (long) dirents *32L;
XX    root_entries = dirents;
XX    sub_entries = boot.secpclus * bytepers / 32;
XX--- 188,225 ----
XX  	unsigned char csecptrack[2];
XX  	unsigned char cheads[2];
XX  	unsigned char chiddensec[2];
XX! 	unsigned char dos4hidd2[2];
XX! 	unsigned char dos4totsec[4];
XX! 	/* Char    fill[476]; */
XX    } boot;
XX    unsigned short boot_magic;	/* last of boot block */
XX!   unsigned bytepers, reservsec, dirents;
XX    unsigned secpfat, secptrack, heads, hiddensec;
XX+   unsigned long totsec;
XX  
XX    int errcount = 0;
XX  
XX    /* Read Bios-Parameterblock */
XX!   disk_io(READ, 0L, &boot, sizeof boot);
XX!   disk_io(READ, 0x1FEL, &boot_magic, sizeof boot_magic);
XX  
XX    /* Convert some arrays */
XX    bytepers = c2u2(boot.cbytepers);
XX    reservsec = c2u2(boot.creservsec);
XX    dirents = c2u2(boot.cdirents);
XX    totsec = c2u2(boot.ctotsec);
XX+   if (totsec == 0) totsec = c4u4(boot.dos4totsec);
XX    secpfat = c2u2(boot.csecpfat);
XX    secptrack = c2u2(boot.csecptrack);
XX    heads = c2u2(boot.cheads);
XX    hiddensec = c2u2(boot.chiddensec);
XX  
XX    /* Calculate everything. */
XX!   total_clusters = (unsigned short)
XX! 	(totsec / (boot.secpclus == 0 ? 1 : boot.secpclus));
XX    cluster_size = bytepers * boot.secpclus;
XX!   fat_size = (unsigned long) secpfat * (unsigned long) bytepers;
XX!   data_start = (long) bytepers + (long) boot.fats * fat_size
XX  	+ (long) dirents *32L;
XX    root_entries = dirents;
XX    sub_entries = boot.secpclus * bytepers / 32;
XX***************
XX*** 182,188 ****
XX  
XX    /* Safety checking */
XX    if (boot_magic != 0xAA55) {
XX! 	print_string(TRUE, "magic != 0xAA55\n");
XX  	++errcount;
XX    }
XX  
XX--- 227,233 ----
XX  
XX    /* Safety checking */
XX    if (boot_magic != 0xAA55) {
XX! 	print_string(TRUE, "magic != 0xAA55\n", 0);
XX  	++errcount;
XX    }
XX  
XX***************
XX*** 195,221 ****
XX        secptrack != 8 &&
XX  #endif
XX        secptrack != 9) {
XX! 	print_string(TRUE, "sectors per track not supported\n");
XX  	++errcount;
XX    }
XX    if (boot.secpclus == 0) {
XX! 	print_string(TRUE, "sectors per cluster == 0\n");
XX  	++errcount;
XX    }
XX    if (boot.fats != 2 && dos_write) {
XX! 	print_string(TRUE, "fats != 2\n");
XX  	++errcount;
XX    }
XX    if (reservsec != 1) {
XX! 	print_string(TRUE, "reserved != 1\n");
XX  	++errcount;
XX    }
XX    if (cluster_size > MAX_CLUSTER_SIZE) {
XX! 	print_string(TRUE, "cluster size too big\n");
XX  	++errcount;
XX    }
XX    if (errcount != 0) {
XX! 	print_string(TRUE, "Can't handle disk\n");
XX  	leave(2);
XX    }
XX  }
XX--- 240,266 ----
XX        secptrack != 8 &&
XX  #endif
XX        secptrack != 9) {
XX! 	print_string(TRUE, "sectors per track not supported\n", 0);
XX  	++errcount;
XX    }
XX    if (boot.secpclus == 0) {
XX! 	print_string(TRUE, "sectors per cluster == 0\n", 0);
XX  	++errcount;
XX    }
XX    if (boot.fats != 2 && dos_write) {
XX! 	print_string(TRUE, "fats != 2\n", 0);
XX  	++errcount;
XX    }
XX    if (reservsec != 1) {
XX! 	print_string(TRUE, "reserved != 1\n", 0);
XX  	++errcount;
XX    }
XX    if (cluster_size > MAX_CLUSTER_SIZE) {
XX! 	print_string(TRUE, "cluster size too big\n", 0);
XX  	++errcount;
XX    }
XX    if (errcount != 0) {
XX! 	print_string(TRUE, "Can't handle disk\n", 0);
XX  	leave(2);
XX    }
XX  }
XX***************
XX*** 237,243 ****
XX    else if (!strcmp(arg_ptr, "doswrite"))
XX  	dos_write = TRUE;
XX    else {
XX! 	print_string(TRUE, "Program should be named dosread, doswrite or dosdir.\n");
XX  	exit(1);
XX    }
XX  
XX--- 282,288 ----
XX    else if (!strcmp(arg_ptr, "doswrite"))
XX  	dos_write = TRUE;
XX    else {
XX! 	print_string(TRUE, "Program should be named dosread, doswrite or dosdir.\n", 0);
XX  	exit(1);
XX    }
XX  
XX***************
XX*** 258,281 ****
XX    }
XX    if (index == argc) usage(argv[0]);
XX  
XX!   if ((dev_nr = (0x5f & *argv[index++])) < 'A' || dev_nr > 'Z')
XX! 	usage(argv[0]);
XX  
XX!   device[DRIVE_NR] = dev_nr;
XX  
XX    if ((disk = open(device, dos_write ? O_RDWR : O_RDONLY)) < 0) {
XX  	print_string(TRUE, "Cannot open %s\n", device);
XX  	exit(1);
XX    }
XX!   disk_read(FAT_START, &fat_info, 1);
XX    determine();
XX!   disk_read(FAT_START + (long) fat_size, &fat_check, sizeof(fat_check));
XX  
XX    if (fat_check != fat_info) {
XX! 	print_string(TRUE, "Disk type in FAT copy differs from disk type in FAT original.\n");
XX  	leave(1);
XX    }
XX!   disk_read(ROOTADDR, root, DIR_SIZE * root_entries);
XX  
XX    if (dos_dir && Lflag) {
XX  	entry = label();
XX--- 303,330 ----
XX    }
XX    if (index == argc) usage(argv[0]);
XX  
XX!   if (strncmp(argv[index], "/dev/", 5) == 0)
XX! 	device = argv[index++];
XX!   else {
XX! 	if ((dev_nr = toupper (*argv[index++])) < 'A' || dev_nr > 'Z')
XX! 		usage(argv[0]);
XX  
XX! 	device[DRIVE_NR] = dev_nr;
XX!   }
XX  
XX    if ((disk = open(device, dos_write ? O_RDWR : O_RDONLY)) < 0) {
XX  	print_string(TRUE, "Cannot open %s\n", device);
XX  	exit(1);
XX    }
XX!   disk_io(READ, FAT_START, &fat_info, 1);
XX    determine();
XX!   disk_io(READ, FAT_START + fat_size, &fat_check, sizeof(fat_check));
XX  
XX    if (fat_check != fat_info) {
XX! 	print_string(TRUE, "Disk type in FAT copy differs from disk type in FAT original.\n", 0);
XX  	leave(1);
XX    }
XX!   disk_io(READ, ROOTADDR, root, DIR_SIZE * root_entries);
XX  
XX    if (dos_dir && Lflag) {
XX  	entry = label();
XX***************
XX*** 336,342 ****
XX  
XX  DIRECTORY *directory(dir, entries, function, pathname)
XX  DIRECTORY *dir;
XX! short entries;
XX  BOOL function;
XX  register char *pathname;
XX  {
XX--- 385,391 ----
XX  
XX  DIRECTORY *directory(dir, entries, function, pathname)
XX  DIRECTORY *dir;
XX! int entries;
XX  BOOL function;
XX  register char *pathname;
XX  {
XX***************
XX*** 401,407 ****
XX  			}
XX  			if (mem) {
XX  				if (dir_ptr) {
XX! 					bcopy(dir_ptr, &save_entry, DIR_SIZE);
XX  					dir_ptr = &save_entry;
XX  				}
XX  				(void) brk( (char *) mem);
XX--- 450,456 ----
XX  			}
XX  			if (mem) {
XX  				if (dir_ptr) {
XX! 					b_copy((char *)dir_ptr, (char *)&save_entry, DIR_SIZE);
XX  					dir_ptr = &save_entry;
XX  				}
XX  				(void) brk( (char *) mem);
XX***************
XX*** 432,444 ****
XX        case ENTRY:
XX  	if (!mem) {
XX  		flush();
XX! 		print_string(TRUE, "No entries left in root directory.\n");
XX  		leave(1);
XX  	}
XX  	cl_no = free_cluster(TRUE);
XX  	link_fat(last, cl_no);
XX  	link_fat(cl_no, LAST_CLUSTER);
XX! 	disk_write(clus_add(cl_no), null, cluster_size);
XX  
XX  	return new_entry(dir, entries);
XX        case FALSE:
XX--- 481,493 ----
XX        case ENTRY:
XX  	if (!mem) {
XX  		flush();
XX! 		print_string(TRUE, "No entries left in root directory.\n", 0);
XX  		leave(1);
XX  	}
XX  	cl_no = free_cluster(TRUE);
XX  	link_fat(last, cl_no);
XX  	link_fat(cl_no, LAST_CLUSTER);
XX! 	disk_io(WRITE, clus_add(cl_no), null, cluster_size);
XX  
XX  	return new_entry(dir, entries);
XX        case FALSE:
XX***************
XX*** 460,479 ****
XX  	return;
XX  
XX    do {
XX! 	disk_read(clus_add(cl_no), buffer, cluster_size);
XX  	rest = (entry->d_size > (long) cluster_size) ? cluster_size : (short) entry->d_size;
XX  	print(STD_OUT, buffer, rest);
XX  	entry->d_size -= (long) rest;
XX  	cl_no = next_cluster(cl_no);
XX  	if (cl_no == (fat_16 ? BAD16 : BAD)) {
XX  		flush();
XX! 		print_string(TRUE, "Reserved cluster value encountered.\n");
XX  		leave(1);
XX  	}
XX    } while (entry->d_size && cl_no != LAST_CLUSTER);
XX  
XX    if (cl_no != LAST_CLUSTER)
XX! 	print_string(TRUE, "Too many clusters allocated for file.\n");
XX    else if (entry->d_size != 0)
XX  	print_string(TRUE, "Premature EOF: %L bytes left.\n",
XX  		     entry->d_size);
XX--- 509,528 ----
XX  	return;
XX  
XX    do {
XX! 	disk_io(READ, clus_add(cl_no), buffer, cluster_size);
XX  	rest = (entry->d_size > (long) cluster_size) ? cluster_size : (short) entry->d_size;
XX  	print(STD_OUT, buffer, rest);
XX  	entry->d_size -= (long) rest;
XX  	cl_no = next_cluster(cl_no);
XX  	if (cl_no == (fat_16 ? BAD16 : BAD)) {
XX  		flush();
XX! 		print_string(TRUE, "Reserved cluster value encountered.\n", 0);
XX  		leave(1);
XX  	}
XX    } while (entry->d_size && cl_no != LAST_CLUSTER);
XX  
XX    if (cl_no != LAST_CLUSTER)
XX! 	print_string(TRUE, "Too many clusters allocated for file.\n", 0);
XX    else if (entry->d_size != 0)
XX  	print_string(TRUE, "Premature EOF: %L bytes left.\n",
XX  		     entry->d_size);
XX***************
XX*** 544,550 ****
XX    short i, r;
XX    long size = 0L;
XX  
XX!   bcopy("           ", &entry->d_name[0], 11);	/* clear entry */
XX    for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++)
XX  	entry->d_name[i] = *ptr++;
XX    while (*ptr != '.' && *ptr) ptr++;
XX--- 593,599 ----
XX    short i, r;
XX    long size = 0L;
XX  
XX!   b_copy("           ", (char *) &entry->d_name[0], 11);    /* clear entry */
XX    for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++)
XX  	entry->d_name[i] = *ptr++;
XX    while (*ptr != '.' && *ptr) ptr++;
XX***************
XX*** 558,567 ****
XX  
XX    while ((r = fill(buffer)) > 0) {
XX  	if ((next = free_cluster(FALSE)) > total_clusters) {
XX! 		print_string(TRUE, "Diskette full. File truncated.\n");
XX  		break;
XX  	}
XX! 	disk_write(clus_add(next), buffer, r);
XX  
XX  	if (entry->d_cluster == 0)
XX  		cl_no = entry->d_cluster = next;
XX--- 607,616 ----
XX  
XX    while ((r = fill(buffer)) > 0) {
XX  	if ((next = free_cluster(FALSE)) > total_clusters) {
XX! 		print_string(TRUE, "Diskette full. File truncated.\n", 0);
XX  		break;
XX  	}
XX! 	disk_io(WRITE, clus_add(next), buffer, r);
XX  
XX  	if (entry->d_cluster == 0)
XX  		cl_no = entry->d_cluster = next;
XX***************
XX*** 577,583 ****
XX  
XX    entry->d_size = Aflag ? (size - 1) : size;	/* Strip added ^Z */
XX    fill_date(entry);
XX!   disk_write(mark, entry, DIR_SIZE);
XX  }
XX  
XX  
XX--- 626,632 ----
XX  
XX    entry->d_size = Aflag ? (size - 1) : size;	/* Strip added ^Z */
XX    fill_date(entry);
XX!   disk_io(WRITE, mark, entry, DIR_SIZE);
XX  }
XX  
XX  
XX***************
XX*** 709,716 ****
XX  	 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
XX  };
XX  
XX! modes(mode)
XX! register unsigned char mode;
XX  {
XX    print_string(FALSE, "\t%c%c%c%c%c", (mode & SUB_DIR) ? 'd' : '-',
XX  	     (mode & 02) ? 'h' : '-', (mode & 04) ? 's' : '-',
XX--- 758,765 ----
XX  	 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
XX  };
XX  
XX! xmodes(mode)
XX! int mode;
XX  {
XX    print_string(FALSE, "\t%c%c%c%c%c", (mode & SUB_DIR) ? 'd' : '-',
XX  	     (mode & 02) ? 'h' : '-', (mode & 04) ? 's' : '-',
XX***************
XX*** 733,739 ****
XX  	print_string(FALSE, "%s\n", bname);
XX  	return;
XX    }
XX!   modes(dir_ptr->d_attribute);
XX    print_string(FALSE, "\t%s%s", bname, strlen(bname) < 8 ? "\t\t" : "\t");
XX    i = 1;
XX    if (is_dir(dir_ptr)) {
XX--- 782,788 ----
XX  	print_string(FALSE, "%s\n", bname);
XX  	return;
XX    }
XX!   xmodes( (int) dir_ptr->d_attribute);
XX    print_string(FALSE, "\t%s%s", bname, strlen(bname) < 8 ? "\t\t" : "\t");
XX    i = 1;
XX    if (is_dir(dir_ptr)) {
XX***************
XX*** 789,795 ****
XX  }
XX  
XX  /* VARARGS */
XX! print_string(err_fl, fmt, args)
XX  BOOL err_fl;
XX  char *fmt;
XX  int args;
XX--- 838,844 ----
XX  }
XX  
XX  /* VARARGS */
XX! void print_string(err_fl, fmt, args)
XX  BOOL err_fl;
XX  char *fmt;
XX  int args;
XX***************
XX*** 847,859 ****
XX  register unsigned short cluster;
XX  {
XX    register DIRECTORY *sub_dir;
XX-   extern char *sbrk();
XX  
XX    if ((sub_dir = (DIRECTORY *) sbrk(cluster_size)) == (DIRECTORY *) -1) {
XX! 	print_string(TRUE, "Cannot set break!\n");
XX  	leave(1);
XX    }
XX!   disk_read(clus_add(cluster), sub_dir, cluster_size);
XX  
XX    return sub_dir;
XX  }
XX--- 896,907 ----
XX  register unsigned short cluster;
XX  {
XX    register DIRECTORY *sub_dir;
XX  
XX    if ((sub_dir = (DIRECTORY *) sbrk(cluster_size)) == (DIRECTORY *) -1) {
XX! 	print_string(TRUE, "Cannot set break!\n", 0);
XX  	leave(1);
XX    }
XX!   disk_io(READ, clus_add(cluster), sub_dir, cluster_size);
XX  
XX    return sub_dir;
XX  }
XX***************
XX*** 868,874 ****
XX  
XX    if (leave_fl && cl_index > total_clusters) {
XX  	flush();
XX! 	print_string(TRUE, "Diskette full. File not added.\n");
XX  	leave(1);
XX    }
XX    return cl_index++;
XX--- 916,922 ----
XX  
XX    if (leave_fl && cl_index > total_clusters) {
XX  	flush();
XX! 	print_string(TRUE, "Diskette full. File not added.\n", 0);
XX  	leave(1);
XX    }
XX    return cl_index++;
XX***************
XX*** 891,903 ****
XX    if (cl_1 & 0x01) {
XX  	pad = cl_2 >> 4;
XX  	put_fat((long) (fat_index + 1), &pad);
XX! 	get_fat((long) fat_index, &pad);
XX  	pad = (pad & 0x0F) | ((cl_2 & 0x0F) << 4);
XX  	put_fat((long) fat_index, &pad);
XX    } else {
XX  	pad = cl_2;
XX  	put_fat((long) (fat_index - 1), &pad);
XX! 	get_fat((long) fat_index, &pad);
XX  	pad = (pad & 0xF0) | (0xf & (cl_2 >> 8));
XX  	put_fat((long) fat_index, &pad);
XX    }
XX--- 939,951 ----
XX    if (cl_1 & 0x01) {
XX  	pad = cl_2 >> 4;
XX  	put_fat((long) (fat_index + 1), &pad);
XX! 	get_fat((long) fat_index, (char *) &pad);
XX  	pad = (pad & 0x0F) | ((cl_2 & 0x0F) << 4);
XX  	put_fat((long) fat_index, &pad);
XX    } else {
XX  	pad = cl_2;
XX  	put_fat((long) (fat_index - 1), &pad);
XX! 	get_fat((long) fat_index, (char *) &pad);
XX  	pad = (pad & 0xF0) | (0xf & (cl_2 >> 8));
XX  	put_fat((long) fat_index, &pad);
XX    }
XX***************
XX*** 914,933 ****
XX  
XX    if (!fat_16) {
XX  	fat_index = (cl_no >> 1) * 3 + 1;
XX! 	get_fat((long) fat_index, &pad);
XX  	if (cl_no & 0x01) {
XX  		pad16 = 0x0f & (pad >> 4);
XX! 		get_fat((long) (fat_index + 1), &pad);
XX  		cl_no = (((short) pad) << 4) | pad16;
XX  	} else {
XX  		pad16 = (0x0f & pad) << 8;
XX! 		get_fat((long) (fat_index - 1), &pad);
XX  		cl_no = (short) pad | pad16;
XX  	}
XX  	mask = MASK;
XX  	bad = BAD;
XX    } else {
XX! 	get_fat16((long) (cl_no << 1), &pad16);
XX  	cl_no = pad16;
XX    }
XX  
XX--- 962,981 ----
XX  
XX    if (!fat_16) {
XX  	fat_index = (cl_no >> 1) * 3 + 1;
XX! 	get_fat((long) fat_index, (char *) &pad);
XX  	if (cl_no & 0x01) {
XX  		pad16 = 0x0f & (pad >> 4);
XX! 		get_fat((long) (fat_index + 1), (char *) &pad);
XX  		cl_no = (((short) pad) << 4) | pad16;
XX  	} else {
XX  		pad16 = (0x0f & pad) << 8;
XX! 		get_fat((long) (fat_index - 1), (char *) &pad);
XX  		cl_no = (short) pad | pad16;
XX  	}
XX  	mask = MASK;
XX  	bad = BAD;
XX    } else {
XX! 	get_fat16((long) (cl_no << 1), (char *) &pad16);
XX  	cl_no = pad16;
XX    }
XX  
XX***************
XX*** 950,957 ****
XX    return result;
XX  }
XX  
XX! add_path(file, slash_fl)
XX! register char *file;
XX  BOOL slash_fl;
XX  {
XX    register char *ptr = path;
XX--- 998,1005 ----
XX    return result;
XX  }
XX  
XX! void add_path(file, slash_fl)
XX! char *file;
XX  BOOL slash_fl;
XX  {
XX    register char *ptr = path;
XX***************
XX*** 969,975 ****
XX  	while (*ptr++ = *file++);
XX  }
XX  
XX! bcopy(src, dest, bytes)
XX  register char *src, *dest;
XX  short bytes;
XX  {
XX--- 1017,1023 ----
XX  	while (*ptr++ = *file++);
XX  }
XX  
XX! b_copy(src, dest, bytes)
XX  register char *src, *dest;
XX  short bytes;
XX  {
XX***************
XX*** 979,992 ****
XX  disk_io(op, seek, address, bytes)
XX  register BOOL op;
XX  unsigned long seek;
XX! DIRECTORY *address;
XX  register unsigned bytes;
XX  {
XX    unsigned int r;
XX  
XX    if (lseek(disk, seek, SEEK_SET) < 0L) {
XX  	flush();
XX! 	print_string(TRUE, "Bad lseek\n");
XX  	leave(1);
XX    }
XX    if (op == READ)
XX--- 1027,1040 ----
XX  disk_io(op, seek, address, bytes)
XX  register BOOL op;
XX  unsigned long seek;
XX! void *address;
XX  register unsigned bytes;
XX  {
XX    unsigned int r;
XX  
XX    if (lseek(disk, seek, SEEK_SET) < 0L) {
XX  	flush();
XX! 	print_string(TRUE, "Bad lseek\n", 0);
XX  	leave(1);
XX    }
XX    if (op == READ)
X/
Xecho x - fdisk.c.d
Xsed '/^X/s///' > fdisk.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/fdisk.c  crc=04647  22000	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/fdisk.c  crc=58765  22901	Thu Jul 16 12:21:32 1992
XX***************
XX*** 27,34 ****
XX--- 27,38 ----
XX   * (everyone should convert to use fcntl.h).
XX   */
XX  
XX+ #include <sys/types.h>
XX  #include <minix/partition.h>
XX+ #include <fcntl.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #ifdef DOS
XX***************
XX*** 65,82 ****
XX  int nsec;
XX  int readonly;
XX  
XX! static void adj_base();
XX! static void adj_size();
XX! static struct part_entry *ask_partition();
XX! static int chk_table();
XX! static void footnotes();
XX! static int get_an_int();
XX! static void list_part_types();
XX! static void mark_npartition();
XX! static int mygets();
XX! static char *systype();
XX! static void toggle_active();
XX! static void usage();
XX  
XX  main(argc, argv)
XX  int argc;
XX--- 69,100 ----
XX  int nsec;
XX  int readonly;
XX  
XX! _PROTOTYPE(int main, (int argc, char *argv []));
XX! _PROTOTYPE(int getboot, (char *buffer));
XX! _PROTOTYPE(int putboot, (char *buffer));
XX! _PROTOTYPE(int load_from_file, (void));
XX! _PROTOTYPE(int save_to_file, (void));
XX! _PROTOTYPE(int dpl_partitions, (int rawflag));
XX! _PROTOTYPE(int chk_table, (void));
XX! _PROTOTYPE(int sec_to_hst, (long logsec, unsigned char *hd, unsigned char *sec,
XX! 							 unsigned char *cyl));
XX! _PROTOTYPE(int mark_partition, (struct part_entry *pe));
XX! _PROTOTYPE(int change_partition, (struct part_entry *entry));
XX! _PROTOTYPE(int get_a_char, (void));
XX! _PROTOTYPE(int print_menu, (void));
XX! _PROTOTYPE(int getboot, (char *buffer));
XX! _PROTOTYPE(int putboot, (char *buffer));
XX! _PROTOTYPE(void adj_base, (struct part_entry *pe));
XX! _PROTOTYPE(void adj_size, (struct part_entry *pe));
XX! _PROTOTYPE(struct part_entry *ask_partition, (void));
XX! _PROTOTYPE(void footnotes, (void));
XX! _PROTOTYPE(int get_an_int, (char *prompt, int *intptr));
XX! _PROTOTYPE(void list_part_types, (void));
XX! _PROTOTYPE(void mark_npartition, (struct part_entry *pe));
XX! _PROTOTYPE(int mygets, (char *buf, int length));
XX! _PROTOTYPE(char *systype, (int type));
XX! _PROTOTYPE(void toggle_active, (struct part_entry *pe));
XX! _PROTOTYPE(void usage, (void));
XX  
XX  main(argc, argv)
XX  int argc;
XX***************
XX*** 350,356 ****
XX  }
XX  
XX  
XX! static int chk_table()
XX  {
XX  /* Check partition table */
XX  
XX--- 368,374 ----
XX  }
XX  
XX  
XX! int chk_table()
XX  {
XX  /* Check partition table */
XX  
XX***************
XX*** 552,558 ****
XX  		printf("Leaving partition inactive\n");
XX  		break;
XX  	} else if (ch == 'y') {
XX! 		toggle_active();
XX  		break;
XX  	}
XX    }
XX--- 570,576 ----
XX  		printf("Leaving partition inactive\n");
XX  		break;
XX  	} else if (ch == 'y') {
XX! 		toggle_active((struct part_entry *)0);
XX  		break;
XX  	}
XX    }
XX***************
XX*** 655,661 ****
XX  
XX  #endif
XX  
XX! static void adj_base(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Adjust base sector of partition, usually to make it even. */
XX--- 673,679 ----
XX  
XX  #endif
XX  
XX! void adj_base(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Adjust base sector of partition, usually to make it even. */
XX***************
XX*** 683,689 ****
XX  	 pe->lowsec, pe->size);
XX  }
XX  
XX! static void adj_size(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Adjust size of partition by reducing high sector. */
XX--- 701,707 ----
XX  	 pe->lowsec, pe->size);
XX  }
XX  
XX! void adj_size(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Adjust size of partition by reducing high sector. */
XX***************
XX*** 704,710 ****
XX    printf("Size of partition adjusted to %ld\n", pe->size);
XX  }
XX  
XX! static struct part_entry *ask_partition()
XX  {
XX  /* Ask for a valid partition number and return its entry. */
XX  
XX--- 722,728 ----
XX    printf("Size of partition adjusted to %ld\n", pe->size);
XX  }
XX  
XX! struct part_entry *ask_partition()
XX  {
XX  /* Ask for a valid partition number and return its entry. */
XX  
XX***************
XX*** 721,727 ****
XX    return((struct part_entry *) &secbuf[PART_TABLE_OFF] + (num - 1));
XX  }
XX  
XX! static void footnotes()
XX  {
XX  /* Explain the footnotes. */
XX  
XX--- 739,745 ----
XX    return((struct part_entry *) &secbuf[PART_TABLE_OFF] + (num - 1));
XX  }
XX  
XX! void footnotes()
XX  {
XX  /* Explain the footnotes. */
XX  
XX***************
XX*** 763,769 ****
XX    }
XX  }
XX  
XX! static int get_an_int(prompt, intptr)
XX  char *prompt;
XX  int *intptr;
XX  {
XX--- 781,787 ----
XX    }
XX  }
XX  
XX! int get_an_int(prompt, intptr)
XX  char *prompt;
XX  int *intptr;
XX  {
XX***************
XX*** 779,785 ****
XX    }
XX  }
XX  
XX! static void list_part_types()
XX  {
XX  /* Print all known partition types. */
XX  
XX--- 797,803 ----
XX    }
XX  }
XX  
XX! void list_part_types()
XX  {
XX  /* Print all known partition types. */
XX  
XX***************
XX*** 800,806 ****
XX    if (column != 0) putchar('\n');
XX  }
XX  
XX! static void mark_npartition(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Mark a partition with arbitrary type. */
XX--- 818,824 ----
XX    if (column != 0) putchar('\n');
XX  }
XX  
XX! void mark_npartition(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Mark a partition with arbitrary type. */
XX***************
XX*** 825,831 ****
XX    printf("Partition type changed to 0x%02x (%s)\n", type, systype(type));
XX  }
XX  
XX! static int mygets(buf, length)
XX  char *buf;
XX  int length;			/* as for fgets(), but must be >= 2 */
XX  {
XX--- 843,849 ----
XX    printf("Partition type changed to 0x%02x (%s)\n", type, systype(type));
XX  }
XX  
XX! int mygets(buf, length)
XX  char *buf;
XX  int length;			/* as for fgets(), but must be >= 2 */
XX  {
XX***************
XX*** 844,850 ****
XX    }
XX  }
XX  
XX! static char *systype(type)
XX  int type;
XX  {
XX  /* Convert system indicator into system name. */
XX--- 862,868 ----
XX    }
XX  }
XX  
XX! char *systype(type)
XX  int type;
XX  {
XX  /* Convert system indicator into system name. */
XX***************
XX*** 872,878 ****
XX    }
XX  }
XX  
XX! static void toggle_active(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Toggle active flag of a partition. */
XX--- 890,896 ----
XX    }
XX  }
XX  
XX! void toggle_active(pe)
XX  struct part_entry *pe;
XX  {
XX  /* Toggle active flag of a partition. */
XX***************
XX*** 882,888 ****
XX    printf("Partition changed to %sactive\n", pe->bootind ? "" : "in");
XX  }
XX  
XX! static void usage()
XX  {
XX  /* Print usage message and exit. */
XX  
XX--- 900,906 ----
XX    printf("Partition changed to %sactive\n", pe->bootind ? "" : "in");
XX  }
XX  
XX! void usage()
XX  {
XX  /* Print usage message and exit. */
XX  
X/
Xecho x - libpack.c.d
Xsed '/^X/s///' > libpack.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/libpack.c  crc=38299   4564	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/libpack.c  crc=60928   4602	Thu Jul 16 12:21:33 1992
XX***************
XX*** 5,13 ****
XX--- 5,16 ----
XX  /* Do not alter the order of the entries in "table"; asld depends on it.*/
XX  
XX  /* External interfaces */
XX+ #include <sys/types.h>
XX  #include <ctype.h>
XX  #include <errno.h>
XX  #include <string.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  /* Constants */
XX***************
XX*** 23,33 ****
XX  };
XX  typedef unsigned short TWOBYTES;	/* CHEAT - used to return two bytes */
XX  
XX- /* Local interfaces */
XX- static void error_exit(/* int rc, char *msg */);
XX- static void hash_init(/* void */);		/* initializes hash table */
XX- static void pack_line(/* char *line */);	/* packs an input line */
XX- static TWOBYTES abbreviate_string(/* char *s */); /* abbreviates a string */
XX  
XX  /* Macros */
XX  #define HASH(word) ((*(word) + *((word) + 1)) & 0x7f)
XX--- 26,31 ----
XX***************
XX*** 160,169 ****
XX  };
XX  
XX  /* This table is used to look up strings.  */
XX- 
XX  struct node node[ABBREVS];
XX- 
XX  struct node *hash[ABBREVS];		/* hash table */
XX  
XX  /* Code */
XX  int main(argc, argv)
XX--- 158,171 ----
XX  };
XX  
XX  /* This table is used to look up strings.  */
XX  struct node node[ABBREVS];
XX  struct node *hash[ABBREVS];		/* hash table */
XX+ 
XX+ _PROTOTYPE(int main, (int argc, char *argv []));
XX+ _PROTOTYPE(static void error_exit, (int rc, char *msg));
XX+ _PROTOTYPE(static void hash_init, (void));
XX+ _PROTOTYPE(static void pack_line, (char *line));
XX+ _PROTOTYPE(static TWOBYTES abbreviate_string, (char *ip));
XX  
XX  /* Code */
XX  int main(argc, argv)
X/
Xecho x - libupack.c.d
Xsed '/^X/s///' > libupack.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/libupack.c  crc=19139   2323	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/libupack.c  crc=51651   2469	Thu Jul 16 12:21:33 1992
XX***************
XX*** 1,5 ****
XX--- 1,9 ----
XX  /* libupack - unpack a packed .s file		Author: Andy Tanenbaum */
XX  
XX+ #include <sys/types.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ 
XX  char *table[] = {
XX  	 "push ax",
XX  	 "ret",
XX***************
XX*** 127,132 ****
XX--- 131,139 ----
XX  #define OUTMAX (7*1024)
XX  
XX  char input[IBUFSIZE + 1], output[OBUFSIZE + 1];
XX+ 
XX+ _PROTOTYPE(int main, (void));
XX+ _PROTOTYPE(int unpack88, (char *inp, char *outp));
XX  
XX  main()
XX  {
X/
Xecho x - lorder.c.d
Xsed '/^X/s///' > lorder.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/lorder.c  crc=10306   7657	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/lorder.c  crc=41161   8167	Mon Dec 21 18:55:49 1992
XX***************
XX*** 23,31 ****
XX   *		progname = argv[0] - should be first. 5/25/88 - mbeck
XX   */
XX  
XX  #include <ctype.h>
XX  #include <signal.h>
XX! #include <ar.h>
XX  #include <stdio.h>
XX  
XX  #define MAXLINE		256
XX--- 23,36 ----
XX   *		progname = argv[0] - should be first. 5/25/88 - mbeck
XX   */
XX  
XX+ #include <minix/config.h>
XX+ #include <sys/types.h>
XX+ #include <ar.h>
XX  #include <ctype.h>
XX  #include <signal.h>
XX! #include <stdlib.h>
XX! #include <string.h>
XX! #include <unistd.h>
XX  #include <stdio.h>
XX  
XX  #define MAXLINE		256
XX***************
XX*** 50,60 ****
XX  
XX  struct filelist *list;
XX  struct node *tree, *lastnode;
XX- extern char *malloc(), *mktemp();
XX- extern FILE *popen(), *fopen();
XX- extern char *addfile();
XX- extern void user_abort();
XX  
XX  main(argc, argv)
XX  int argc;
XX  char **argv;
XX--- 55,75 ----
XX  
XX  struct filelist *list;
XX  struct node *tree, *lastnode;
XX  
XX+ _PROTOTYPE(int main, (int argc, char **argv));
XX+ _PROTOTYPE(void user_abort, (int s));
XX+ _PROTOTYPE(char *xalloc, (int n));
XX+ _PROTOTYPE(int is_liba, (char *s));
XX+ _PROTOTYPE(char *strsave, (char *s));
XX+ _PROTOTYPE(char *addfile, (char *s));
XX+ _PROTOTYPE(int printtree, (struct node *t));
XX+ _PROTOTYPE(struct node *finddef, (char *s));
XX+ _PROTOTYPE(struct node *makedef, (char *s));
XX+ _PROTOTYPE(void dodef, (char *s));
XX+ _PROTOTYPE(void usedef, (char *s));
XX+ _PROTOTYPE(int yylex, (void));
XX+ 
XX+ 
XX  main(argc, argv)
XX  int argc;
XX  char **argv;
XX***************
XX*** 97,105 ****
XX  	fprintf(stderr, "Usage: %s file ....\n", progname);
XX  	exit(1);
XX    }
XX  }
XX  
XX! void user_abort()
XX  {
XX    unlink(tempfile);
XX    exit(1);
XX--- 112,122 ----
XX  	fprintf(stderr, "Usage: %s file ....\n", progname);
XX  	exit(1);
XX    }
XX+   exit(0);
XX  }
XX  
XX! void user_abort(s)
XX! int s;				/* for ANSI */
XX  {
XX    unlink(tempfile);
XX    exit(1);
XX***************
XX*** 110,116 ****
XX  {
XX    char *p;
XX  
XX!   if ((p = malloc(n)) == (char *) NULL) {
XX  	fprintf(stderr, "Error %s - out of memory\n", progname);
XX  	exit(1);
XX    }
XX--- 127,133 ----
XX  {
XX    char *p;
XX  
XX!   if ((p = (char *) malloc(n)) == (char *) NULL) {
XX  	fprintf(stderr, "Error %s - out of memory\n", progname);
XX  	exit(1);
XX    }
X/
Xecho x - readclock.c.d
Xsed '/^X/s///' > readclock.c.d << '/'
XX*** /home/top/ast/minix/1.5/commands/ibm/readclock.c  crc=63713   3998	Sat Apr 21 22:27:18 1990
XX--- /home/top/ast/minix/1.6.25/commands/ibm/readclock.c  crc=61832   7408	Mon Dec 21 18:55:49 1992
XX***************
XX*** 1,50 ****
XX! /* readclock - read the AT real time clock	Authors: T. Holm & E. Froese */
XX  
XX  /************************************************************************/
XX  /*									*/
XX  /*   readclock.c							*/
XX  /*									*/
XX! /*		Read the AT real time clock, write the time to		*/
XX! /*		standard output in a form usable by date(1).		*/
XX! /*		If the system is an AT then the time is read		*/
XX! /*		from the built-in clock, and written to standard	*/
XX! /*		output in the form:					*/
XX  /*									*/
XX  /*			mmddyyhhmmss					*/
XX  /*									*/
XX! /*		If the system is not an AT then ``-q'' is written 	*/
XX! /*		to standard output. This is useful for placement in	*/
XX  /*		the ``/etc/rc'' script:					*/
XX  /*									*/
XX  /*	 	  /usr/bin/date `/usr/bin/readclock` </dev/tty  	*/
XX  /*									*/
XX  /************************************************************************/
XX  /*    origination          1987-Dec-29              efth                */
XX  /************************************************************************/
XX  
XX  
XX  
XX! #define CPU_TYPE_SEGMENT   0xFFFF	/* BIOS segment for CPU type 	 */
XX! #define CPU_TYPE_OFFSET    0x000E	/* BIOS offset for CPU type 	 */
XX! #define PC_AT              0xFC	/* IBM code for PC-AT (0xFFFFE) */
XX! #define PS_386		0xF8 /* IBM code for 386 PS/2's */	
XX  
XX  
XX! #define CLK_ELE 0x70		/* ptr corresponding to element of time to be*/
XX! #define CLK_IO 0x71		/* read or written is written to port clk_ele*/
XX! /* The element can then be read or written by */
XX! /* Reading or writing port clk_io.            */
XX  
XX! #define  YEAR             9	/* Clock register addresses	 */
XX  #define  MONTH            8
XX  #define  DAY              7
XX  #define  HOUR             4
XX  #define  MINUTE           2
XX  #define  SECOND           0
XX! #define  STATUS           0x0b
XX  
XX! #define  BCD_TO_DEC(x)	  ( (x>>4) * 10 + (x & 0x0f) )
XX  
XX  
XX  struct time {
XX    unsigned year;
XX--- 1,111 ----
XX! /* readclock - read the real time clock		Authors: T. Holm & E. Froese */
XX  
XX  /************************************************************************/
XX  /*									*/
XX  /*   readclock.c							*/
XX  /*									*/
XX! /*		Read from the 64 byte CMOS RAM area, then write		*/
XX! /*		the time to standard output in a form usable by		*/
XX! /*		date(1).						*/
XX  /*									*/
XX+ /*		If the machine ID byte is 0xFC or 0xF8, the device	*/
XX+ /*		/dev/port exists and is a character special file,	*/
XX+ /*		and no errors in the CMOS RAM are reported by the	*/
XX+ /*		RTC, then the time is read from the clock RAM		*/
XX+ /*		area maintained by the RTC.				*/
XX+ /*									*/
XX+ /*		The clock RAM values are decoded and written to		*/
XX+ /*		standard output in the form:				*/
XX+ /*									*/
XX  /*			mmddyyhhmmss					*/
XX  /*									*/
XX! /*		If the machine ID does not match 0xFC or 0xF8,		*/
XX! /*		then ``-q'' is written to standard output.		*/
XX! /*									*/
XX! /*		If the machine ID is 0xFC or 0xF8 and /dev/port		*/
XX! /*		is missing, or is not a character special file,		*/
XX! /*		then an error message is written to stderr,		*/
XX! /*		and ``-q'' is written to stdout.			*/
XX! /*									*/
XX! /*		If the RTC reports errors in the CMOS RAM,		*/
XX! /*		then an error message is written to stderr,		*/
XX! /*		and ``-q'' is written to stdout.			*/
XX! /*									*/
XX! /*		Readclock is used as follows when placed		*/
XX  /*		the ``/etc/rc'' script:					*/
XX  /*									*/
XX  /*	 	  /usr/bin/date `/usr/bin/readclock` </dev/tty  	*/
XX  /*									*/
XX+ /*		It is best if this program is owned by bin and NOT	*/
XX+ /*		SUID because of the peculiar method of reading from	*/
XX+ /*		RTC.  When someone makes a /dev/clock driver, this	*/
XX+ /*		warning may be removed.					*/
XX+ /*									*/
XX  /************************************************************************/
XX  /*    origination          1987-Dec-29              efth                */
XX+ /*    robustness	   1990-Oct-06		    C. Sylvain		*/
XX+ /* incorp. B. Evans ideas  1991-Jul-06		    C. Sylvain		*/
XX  /************************************************************************/
XX  
XX  
XX+ #include <sys/types.h>
XX+ #include <sys/stat.h>
XX+ #include <stdlib.h>
XX+ #include <unistd.h>
XX+ #include <stdio.h>
XX  
XX! #define CPU_TYPE_SEGMENT   0xFFFF	/* Segment for Machine ID in BIOS */
XX! #define CPU_TYPE_OFFSET    0x000E	/* Offset for Machine ID	  */
XX  
XX+ #define PC_AT		   0xFC		/* Machine ID byte for PC/AT,
XX+ 					   PC/XT286, and PS/2 Models 50, 60 */
XX+ #define PS_386		   0xF8		/* Machine ID byte for PS/2 Model 80 */
XX  
XX! /* Manufacturers usually use the ID value of the IBM model they emulate.
XX!  * However some manufacturers, notably HP and COMPAQ, have had different
XX!  * ideas in the past.
XX!  *
XX!  * Machine ID byte information source:
XX!  *	_The Programmer's PC Sourcebook_ by Thom Hogan,
XX!  *	published by Microsoft Press
XX!  */
XX  
XX! #define CLK_ELE		0x70	/* CMOS RAM address register port (write only)
XX! 				 * Bit 7 = 1  NMI disable
XX! 				 *	   0  NMI enable
XX! 				 * Bits 6-0 = RAM address
XX! 				 */
XX! 
XX! #define CLK_IO		0x71	/* CMOS RAM data register port (read/write) */
XX! 
XX! #define  YEAR             9	/* Clock register addresses in CMOS RAM	*/
XX  #define  MONTH            8
XX  #define  DAY              7
XX  #define  HOUR             4
XX  #define  MINUTE           2
XX  #define  SECOND           0
XX! #define  STATUS        0x0B	/* Status register B: RTC configuration	*/
XX! #define  HEALTH	       0x0E	/* Diagnostic status: (should be set by Power
XX! 				 * On Self-Test [POST])
XX! 				 * Bit  7 = RTC lost power
XX! 				 *	6 = Checksum (for addr 0x10-0x2d) bad
XX! 				 *	5 = Config. Info. bad at POST
XX! 				 *	4 = Mem. size error at POST
XX! 				 *	3 = I/O board failed initialization
XX! 				 *	2 = CMOS time invalid
XX! 				 *    1-0 =    reserved
XX! 				 */
XX! #define  DIAG_BADBATT       0x80
XX! #define  DIAG_MEMDIRT       0x40
XX! #define  DIAG_BADTIME       0x04
XX  
XX! /* CMOS RAM and RTC information source:
XX!  *	_System BIOS for PC/XT/AT Computers and Compatibles_
XX!  *	by Phoenix Technologies Ltd., published by Addison-Wesley
XX!  */
XX  
XX+ #define  BCD_TO_DEC(x)      ( (x >> 4) * 10 + (x & 0x0f) )
XX+ #define  errmsg(s)          fputs( s, stderr )
XX  
XX  struct time {
XX    unsigned year;
XX***************
XX*** 55,74 ****
XX    unsigned second;
XX  };
XX  
XX  
XX  
XX! main()
XX  {
XX    struct time time1;
XX    struct time time2;
XX    int i;
XX!   int cpu_type;	
XX  
XX    cpu_type = peek(CPU_TYPE_SEGMENT, CPU_TYPE_OFFSET);
XX    if (cpu_type != PS_386 && cpu_type != PC_AT) {
XX  	printf("-q\n");
XX  	exit(1);
XX    }
XX    for (i = 0; i < 10; i++) {
XX  	get_time(&time1);
XX  	get_time(&time2);
XX--- 116,174 ----
XX    unsigned second;
XX  };
XX  
XX+ _PROTOTYPE(int main, (void));
XX+ _PROTOTYPE(void get_time, (struct time *t));
XX+ _PROTOTYPE(int read_register, (int reg_addr));
XX  
XX+ /* These little fellers are written in assembler :-(  */
XX+ _PROTOTYPE(int port_out, (int port, int value));
XX+ _PROTOTYPE(int port_in, (int port, int *value));
XX+ _PROTOTYPE(int peek, (int a, int b));
XX  
XX! int main()
XX  {
XX+   struct stat pdev;
XX    struct time time1;
XX    struct time time2;
XX    int i;
XX!   int cpu_type, cmos_state;
XX  
XX    cpu_type = peek(CPU_TYPE_SEGMENT, CPU_TYPE_OFFSET);
XX    if (cpu_type != PS_386 && cpu_type != PC_AT) {
XX+ 	errmsg( "Machine ID unknown.\n" );
XX+ 	fprintf( stderr, "Machine ID byte = %x\n", cpu_type );
XX+ 
XX  	printf("-q\n");
XX  	exit(1);
XX    }
XX+   if (stat( "/dev/port", &pdev ) != 0) {
XX+ 	errmsg( "/dev/port not found.\n" );
XX+ 
XX+ 	printf("-q\n");
XX+ 	exit(1);
XX+   }
XX+   if (!S_ISCHR(pdev.st_mode)) {
XX+ 	errmsg( "/dev/port not a character special file.\n" );
XX+ 
XX+ 	printf("-q\n");
XX+ 	exit(1);
XX+   }
XX+   cmos_state = read_register(HEALTH);
XX+   if (cmos_state & (DIAG_BADBATT | DIAG_MEMDIRT | DIAG_BADTIME)) {
XX+ 	errmsg( "\nCMOS RAM error(s) found...   " );
XX+ 	fprintf( stderr, "CMOS state = 0x%02x\n", cmos_state );
XX+ 
XX+ 	if (cmos_state & DIAG_BADBATT)
XX+ 	    errmsg( "RTC lost power. Reset CMOS RAM with SETUP.\n" );
XX+ 	if (cmos_state & DIAG_MEMDIRT)
XX+ 	    errmsg( "CMOS RAM checksum is bad. Run SETUP.\n" );
XX+ 	if (cmos_state & DIAG_BADTIME)
XX+ 	    errmsg( "Time invalid in CMOS RAM. Reset clock with setclock.\n" );
XX+ 	errmsg( "\n" );
XX+ 
XX+ 	printf("-q\n");
XX+ 	exit(1);
XX+   }
XX    for (i = 0; i < 10; i++) {
XX  	get_time(&time1);
XX  	get_time(&time2);
XX***************
XX*** 97,109 ****
XX  /*    get_time( time )                                                 */
XX  /*                                                                     */
XX  /*    Update the structure pointed to by time with the current time    */
XX! /*    as read from the hardware real-time clock of the AT.             */
XX  /*    If necessary, the time is converted into a binary format before  */
XX  /*    being stored in the structure.                                   */
XX  /*                                                                     */
XX  /***********************************************************************/
XX  
XX! get_time(t)
XX  struct time *t;
XX  {
XX    t->year = read_register(YEAR);
XX--- 197,209 ----
XX  /*    get_time( time )                                                 */
XX  /*                                                                     */
XX  /*    Update the structure pointed to by time with the current time    */
XX! /*    as read from CMOS RAM of the RTC.				       */
XX  /*    If necessary, the time is converted into a binary format before  */
XX  /*    being stored in the structure.                                   */
XX  /*                                                                     */
XX  /***********************************************************************/
XX  
XX! void get_time(t)
XX  struct time *t;
XX  {
XX    t->year = read_register(YEAR);
XX***************
XX*** 116,122 ****
XX  
XX  
XX    if ((read_register(STATUS) & 0x04) == 0) {
XX! 	/* Convert BCD to binary if necessary */
XX  	t->year = BCD_TO_DEC(t->year);
XX  	t->month = BCD_TO_DEC(t->month);
XX  	t->day = BCD_TO_DEC(t->day);
XX--- 216,222 ----
XX  
XX  
XX    if ((read_register(STATUS) & 0x04) == 0) {
XX! 	/* Convert BCD to binary (default RTC mode) */
XX  	t->year = BCD_TO_DEC(t->year);
XX  	t->month = BCD_TO_DEC(t->month);
XX  	t->day = BCD_TO_DEC(t->day);
XX***************
XX*** 127,133 ****
XX  }
XX  
XX  
XX! read_register(reg_addr)
XX  char reg_addr;
XX  {
XX    int val;
XX--- 227,233 ----
XX  }
XX  
XX  
XX! int read_register(reg_addr)
XX  char reg_addr;
XX  {
XX    int val;
X/
/
