Path: utzoo!utgpu!water!watmath!clyde!att!pacbell!ames!ncar!mailrus!cornell!rochester!udel!mmdf
From: Postmaster%EBRUPC51.BITNET@cunyvm.cuny.edu (PMDF Mail Server)
Newsgroups: comp.os.minix
Subject: Undeliverable mail
Message-ID: <4319@louie.udel.EDU>
Date: 29 Sep 88 02:10:05 GMT
Sender: mmdf@udel.EDU
Lines: 2273

The message could not be delivered to:

Addressee: EAMATEO
Reason:
  %MAIL-E-NOSUCHUSR, no such user EAMATEO at node GAUDI

----------------------------------------

Received: from JNET-DAEMON by EBRUPC51; Thu, 29 Sep 88 02:56 N
Received: From EB0UB011(MAILER) by EBRUPC51 with Jnet id 5780 for
 EAMATEO@EBRUPC51; Thu, 29 Sep 88 02:56 N
Received: by EB0UB011 (Mailer X1.25) id 1513; Thu, 29 Sep 88 02:50:26 HOE
Date: Tue, 27 Sep 88 20:52:29 GMT
From: Andy Tanenbaum 
Subject: V1.3c posting #4 - commands (2 of 3)
Sender: Minix operating system 
To: NACHO NAVARRO 
Reply-to: INFO-MINIX@UDEL.EDU
Comments:     Warning -- original Sender: tag was info-minix-request@UDEL.EDU
Comments: To: info-minix@UDEL.EDU

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'date.c'
sed 's/^X//' > 'date.c' << '+ END-OF-FILE ''date.c'
X/* date - print or set time and date        Author: Jan Looyen */
X
X#include 
X#include 
X
X#define    MIN    60L        /* # seconds in a minute */
X#define    HOUR    (60 * MIN)    /* # seconds in an hour */
X#define    DAY    (24 * HOUR)    /* # seconds in a day */
X#define    YEAR    (365 * DAY)    /* # seconds in a year */
X
Xchar *ctime();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X  int qflag;
X  long t, time();
X  char time_buf[15];
X
X  if (argc  > 2) usage();
X  if (argc == 2) {
X    if (*argv[1] == '-' && (argv[1][1] | 0x60) == 'q') {
X        freopen(stdin, "/dev/tty0", "r");
X        printf("\nPlease enter date: MMDDYYhhmmss. Then hit RETURN.\n");
X        gets(time_buf);
X        set_time(time_buf);
X    }
X    else
X        set_time(argv[1]);
X  }
X  time(&t);
X  printf("%s", ctime(&t));
X  exit(0);
X}
X
X
Xset_time(t)
Xchar *t;
X{
X  char *tp;
X  long ct, time();
X  int len;
X  static int days_per_month[] = {
X      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X  };
X  struct tm *p, *localtime();
X
X  time(&ct);
X  p = localtime(&ct);
X  p->tm_year -= 1970;
X  p->tm_mon++;
X  len = strlen(t);
X  if (len != 12 && len != 10 && len != 6 && len != 4) usage();
X  tp = t;
X  while (*tp)
X    if (!isdigit(*tp++))
X        bad();
X  if (len == 6 || len == 12)
X      p->tm_sec = conv(&tp, 59);
X  p->tm_min = conv(&tp, 59);
X  p->tm_hour = conv(&tp, 23);
X  if (len == 12 || len == 10) {
X      p->tm_year = conv(&tp, 99);
X      p->tm_mday = conv(&tp, 31);
X      p->tm_mon = conv(&tp, 12);
X      p->tm_year -= 70;
X    if (p->tm_year < 0)
X        p->tm_year += 100;
X  }
X  ct = p->tm_year * YEAR;
X  ct += ((p->tm_year + 1) / 4) * DAY;
X  days_per_month[1] = 28;
X  if (((p->tm_year + 2) % 4) == 0)
X    days_per_month[1]++;
X  len = 0;
X  p->tm_mon--;
X  while (len < p->tm_mon)
X    ct += days_per_month[len++] * DAY;
X  ct += --p->tm_mday * DAY;
X  ct += p->tm_hour * HOUR;
X  ct += p->tm_min * MIN;
X  ct += p->tm_sec;
X  if (stime(&ct))
X    fprintf(stderr, "Set date not allowed\n");
X}
X
Xconv(ptr, max)
Xchar **ptr;
Xint max;
X{
X  int buf;
X
X  *ptr -=2;
X  buf = atoi(*ptr);
X  **ptr = 0;
X  if (buf < 0 || buf > max)
X    bad();
X  return(buf);
X}
X
Xbad()
X{
X  fprintf(stderr, "Date: bad conversion\n");
X  exit(1);
X}
X
Xusage()
X{
X  fprintf(stderr, "Usage: date [-q] [[MMDDYY]hhmm[ss]]\n");
X  exit(1);
X}
X
Xisdigit(c)
Xchar c;
X{
X  if (c >= '0' && c <= '9')
X    return(1);
X  else
X    return(0);
X}
+ END-OF-FILE date.c
chmod 'u=rw,g=r,o=r' 'date.c'
set `wc -c 'date.c'`
count=$1
case $count in
2223)    :;;
*)    echo 'Bad character count in ''date.c' >&2
        echo 'Count should be 2223' >&2
esac
echo Extracting 'df.c.cdif'
sed 's/^X//' > 'df.c.cdif' << '+ END-OF-FILE ''df.c.cdif'
X*** /local/ast/minix/tape3b/commands/df.c    Wed Jul 13 13:10:51 1988
X--- df.c    Sun Sep 25 15:24:55 1988
X***************
X*** 178,187 ****
X  char *p;
X  {
X    char c;
X
X    while (1) {
X!     c = getchar();
X!     if (c < 0) exit(0);
X      if (c == ' ') c = 0;
X      *p++ = c;
X      if (c == '\n') return;
X--- 178,189 ----
X  char *p;
X  {
X    char c;
X+   char ch;
X
X    while (1) {
X!     ch = getchar();
X!     if (ch == EOF) exit(0);
X!     c = (char) ch;
X      if (c == ' ') c = 0;
X      *p++ = c;
X      if (c == '\n') return;
+ END-OF-FILE df.c.cdif
chmod 'u=rw,g=r,o=r' 'df.c.cdif'
set `wc -c 'df.c.cdif'`
count=$1
case $count in
487)    :;;
*)    echo 'Bad character count in ''df.c.cdif' >&2
        echo 'Count should be 487' >&2
esac
echo Extracting 'diskcheck.c.cdif'
sed 's/^X//' > 'diskcheck.c.cdif' << '+ END-OF-FILE ''diskcheck.c.cdif'
X*** /local/ast/minix/tape3b/commands/diskcheck.c    Wed Jul 13 13:10:51 1988
X--- diskcheck.c    Sun Sep 25 15:24:55 1988
X***************
X*** 15,20 ****
X--- 15,21 ----
X  int pfd;            /* file descriptor for purging */
X  int fd;                /* file descriptor for data I/O */
X  unsigned initblock;        /* first block to test */
X+ unsigned curblock;        /* current block */
X  unsigned limit;            /* first block beyond test zone */
X  unsigned errors;        /* # errors so far */
X  unsigned ct;            /* # blocks read so far */
X***************
X*** 62,67 ****
X--- 63,69 ----
X              write(fd, buf, BLOCK_SIZE);
X          }
X      }
X+     curblock = b;
X      ct++;
X      if (ct % PRINTFREQ == 0) status();
X    }
X***************
X*** 120,126 ****
X
X  status()
X  {
X!   printf("%5u blocks tested, %u errors detected\n",ct,errors);
X  }
X
X  nonfatal(s, b)
X--- 122,129 ----
X
X  status()
X  {
X!   printf("%5u blocks tested, %u errors detected (last block tested = %5u)\n",
X!                         ct,errors,curblock);
X  }
X
X  nonfatal(s, b)
+ END-OF-FILE diskcheck.c.cdif
chmod 'u=rw,g=r,o=r' 'diskcheck.c.cdif'
set `wc -c 'diskcheck.c.cdif'`
count=$1
case $count in
956)    :;;
*)    echo 'Bad character count in ''diskcheck.c.cdif' >&2
        echo 'Count should be 956' >&2
esac
echo Extracting 'dosread.c'
sed 's/^X//' > 'dosread.c' << '+ END-OF-FILE ''dosread.c'
X/* dos{read|write|dir} - handle DOS disks    Author: Michiel Huisjes */
X
X/* dosdir - list MS-DOS directories.
X * doswrite - write stdin to DOS-file
X * dosread - read DOS-file to stdout
X *
X * Author: Michiel Huisjes.
X *
X * Usage: dos... [-lra] drive [file/dir]
X *      l: Give long listing.
X *      r: List recursively.
X *      a: Set ASCII bit.
X *
X *    Modified by Tim Kachel 4-88
X *        drive can be 0,1, a, b, c, d, e, f
X *        program will automatically configure to different hard disks
X *          and the partitions for such (could change drive name for
X *          a second hard disk if you have one)
X *            (has been tested on a 16 bit FAT AT drive)
X *            (High density AT diskettes and regular 360K)
X *        compile with cc -O -i
X *        hard disk is named /dev/hd0 to avoid accidents
X *          To test FAT sizes on your hard disk first try dir -lr c
X *            (or what ever your dos partition is)  if this works
X *            properly then all the rest should be okay.
X *        If there are any problems there is debugging information
X *          in fdinit() -- please let me know of any problems
X */
X
X#include 
X
X#define DRIVE0        "/dev/at0"
X#define DRIVE1        "/dev/at1"
X#define FDRIVE        "/dev/hd0"
X
X#define DDDD    0xFD
X#define DDHD    0xF9
X#define DDFD    0xF8
X
X#define    MAX_CLUSTER_SIZE    4096
X#define MAX_FAT_SIZE        23552    /* 46 sectoren */
X#define HMASK        0xFF00
X#define LMASK        0x00FF
X
X#define MAX_ROOT_ENTRIES    512    /* 32 sectoren */
X#define FAT_START        512L    /* After bootsector */
X#define clus_add(cl_no)        ((long) (((long) cl_no - 2L) \
X                    * (long) cluster_size \
X                    + (long) data_start \
X                       ))
Xstruct dir_entry {
X    unsigned char d_name[8];
X    unsigned char d_ext[3];
X    unsigned char d_attribute;
X    unsigned char d_reserved[10];
X    unsigned short d_time;
X    unsigned short d_date;
X    unsigned short d_cluster;
X    unsigned long d_size;
X};
X
Xtypedef struct dir_entry DIRECTORY;
X
X#define NOT_USED    0x00
X#define ERASED        0xE5
X#define DIR        0x2E
X#define DIR_SIZE    (sizeof (struct dir_entry))
X#define SUB_DIR        0x10
X#define NIL_DIR        ((DIRECTORY *) 0)
X
X#define LAST_CLUSTER    0x0FFF
X#define MASK        0xFF8        /* FF8 - FFF are last cluster */
X#define FREE        0x000
X#define BAD        0xFF0        /* Includes reserved */
X
X#define LAST_16        0xFFFF
X#define MASK_16        0xFFF8
X#define FREE_16        0x0000
X#define BAD_16        0xFFF0        /* Includes reserved */
X
Xtypedef char BOOL;
X
X#define TRUE    1
X#define FALSE    0
X#define NIL_PTR    ((char *) 0)
X
X#define DOS_TIME    315532800L     /* 1970 - 1980 */
X
X#define READ            0
X#define WRITE            1
X#define disk_read(s, a, b)    disk_io(READ, s, a, b)
X#define disk_write(s, a, b)    disk_io(WRITE, s, a, b)
X
X#define FIND    3
X#define LABEL    4
X#define ENTRY    5
X#define find_entry(d, e, p)    directory(d, e, FIND, p)
X#define list_dir(d, e, f)    (void) directory(d, e, f, NIL_PTR)
X#define label()            directory(root, root_entries, LABEL, NIL_PTR)
X#define new_entry(d, e)        directory(d, e, ENTRY, NIL_PTR)
X
X#define is_dir(d)        ((d)->d_attribute & SUB_DIR)
X
X#define EOF            0400
X#define EOF_MARK        '\032'
X#define STD_OUT            1
X#define flush()            print(STD_OUT, NIL_PTR, 0)
X
Xshort disk;
Xunion tbl
X{
X    unsigned char  twelve[4096];
X    unsigned short sixteen[MAX_FAT_SIZE / 2 ];
X} fat;
X
XDIRECTORY root[MAX_ROOT_ENTRIES], save_entry, *directory(), *read_cluster();
Xchar null[MAX_CLUSTER_SIZE], *device, path[128];
Xshort total_clusters, cluster_size, fat_size, root_entries, sub_entries;
X
XBOOL Rflag, Lflag, Aflag, dos_read, dos_write, dos_dir, Tfat = TRUE;
X
Xunsigned short free_cluster(), next_cluster();
Xchar *make_name(), *num_out(), *slash(), *brk();
Xlong mark, data_start, lseek(), time(), f_start;
X
Xleave(nr)
Xshort nr;
X{
X    (void) umount(device);
X    exit(nr);
X}
X
Xusage(prog_name)
Xregister char *prog_name;
X{
X    print_string(TRUE, "Usage: %s [%s\n", prog_name,
X             dos_dir ? "-lr] drive [dir]" : "-a] drive file");
X    exit(1);
X}
X
Xmain(argc, argv)
Xint argc;
Xregister char *argv[];
X{
X    register char *arg_ptr = slash(argv[0]);
X    DIRECTORY *entry;
X    short index = 1;
X    char dev_nr;
X    unsigned char fat_type, fat_check;
X    BOOL fdisk = FALSE;
X    int i;
X
X    if (!strcmp(arg_ptr, "dosdir"))
X        dos_dir = TRUE;
X    else if (!strcmp(arg_ptr, "dosread"))
X        dos_read = TRUE;
X    else if (!strcmp(arg_ptr, "doswrite"))
X        dos_write = TRUE;
X    else {
X        print_string(TRUE, "Program should be named dosread, doswrite or
 dosdir.\n");
X        exit(1);
X    }
X
X    if (argc == 1)
X        usage(argv[0]);
X
X    if (argv[1][0] == '-') {
X        for (arg_ptr = &argv[1][1]; *arg_ptr; arg_ptr++) {
X            if (*arg_ptr == 'l' && dos_dir)
X                Lflag = TRUE;
X            else if (*arg_ptr == 'r' && dos_dir)
X                Rflag = TRUE;
X            else if (*arg_ptr == 'a' && !dos_dir)
X                Aflag = TRUE;
X            else
X                usage(argv[0]);
X        }
X        index++;
X    }
X
X    if (index == argc)
X        usage(argv[0]);
X
X    switch (dev_nr = *argv[index++])
X    {
X        case '0':
X        case 'a':    device = DRIVE0; break;
X        case '1':
X        case 'b':    device = DRIVE1; break;
X        case 'c':
X        case 'd':
X        case 'e':
X        case 'f':    fdisk = TRUE; device = FDRIVE; break;
X        default :    usage(argv[0]);
X    }
X
X    if ((disk = open(device, 2)) < 0) {
X        print_string(TRUE, "Cannot open %s\n", device);
X        exit(1);
X    }
X
X    if (fdisk) {        /* fixed disk */
X        fdinit(dev_nr);
X        disk_read(f_start, &fat_type, sizeof(fat_type));
X        if (fat_type != DDFD) {
X            print_string(TRUE, "Fixed disk is not DOS\n");
X            leave(1);
X        }
X    }
X    else {        /* use standard start for floppies */
X        f_start = FAT_START;
X        disk_read(f_start, &fat_type, sizeof(fat_type));
X        if (fat_type == DDDD) {        /* Double-sided double-density 9 s/t */
X            total_clusters = 355;    /* 720 - 7 - 2 - 2 - 1 */
X            cluster_size = 1024;    /* 2 sectors per cluster */
X            fat_size = 1024;    /* 2 sectors */
X            data_start = 6144L;    /* Starts on sector #12 */
X            root_entries = 112;
X            sub_entries = 32;    /* 1024 / 32 */
X        }
X        else if (fat_type == DDHD) {    /* Double-sided high-density 15 s/t */
X            total_clusters = 2372;    /* 2400 - 14 - 7 - 7 - 1 */
X            cluster_size = 512;    /* 1 sector per cluster */
X            fat_size = 3584;    /* 7 sectors */
X            data_start = 14848L;    /* Starts on sector #29 */
X            root_entries = 224;
X            sub_entries = 16;    /* 512 / 32 */
X        }
X        else {
X                print_string(TRUE, "Diskette is not DOS 2.0 360K or 1.2M\n");
X            leave(1);
X        }
X    }
X
X    disk_read(f_start + (long) fat_size, &fat_check, sizeof(fat_check));
X    if (fat_check != fat_type) {
X        print_string(TRUE, "Disk type in FAT copy differs from disk type in FAT
 original.\n");
X        leave(1);
X    }
X
X    if (Tfat)    /* twelve bit FAT entries */
X        disk_read(f_start, fat.twelve, fat_size);
X    else        /* sixteen bit */
X        disk_read(f_start, fat.sixteen, fat_size);
X/*******
X    for (i=0; i<= 30; i++){
X        printf("%x\t%c", fat.sixteen[i], (i % 10) ? ' ':'\n');
X    }
X    leave(1);
X/*******/
X    disk_read(f_start + 2L * (long) fat_size, root, DIR_SIZE * root_entries);
X/*******
X    for (i=0; i<2; i++){
X        printf("%s d_name\n", root[i].d_name);
X        printf("%s d_ext\n",  root[i].d_ext);
X        printf("%d d_attr\n",  root[i].d_attribute);
X        printf("%s d_reserved\n",  root[i].d_reserved);
X        printf("%d d_time\n",  root[i].d_time);
X        printf("%d d_date\n",  root[i].d_date);
X        printf("%d d_cluster\n",  root[i].d_cluster);
X        printf("%D d_size\n",  root[i].d_size);
X    }
X
X
X/*********/
X    if (dos_dir) {
X        entry = label();
X        print_string(FALSE, "Volume in drive %c ", dev_nr);
X        if (entry == NIL_DIR)
X            print(STD_OUT, "has no label.\n\n", 0);
X        else
X            print_string(FALSE, "is %S\n\n", entry->d_name);
X    }
X
X    if (argv[index] == NIL_PTR) {
X        if (!dos_dir)
X            usage(argv[0]);
X        print(STD_OUT, "Root directory:\n", 0);
X        list_dir(root, root_entries, FALSE);
X        free_blocks();
X        flush();
X        leave(0);
X    }
X
X    for (arg_ptr = argv[index]; *arg_ptr; arg_ptr++)
X        if (*arg_ptr == '\\')
X            *arg_ptr = '/';
X        else if (*arg_ptr >= 'a' && *arg_ptr <= 'z')
X            *arg_ptr += ('A' - 'a');
X    if (*--arg_ptr == '/')
X        *arg_ptr = '\0';       /* skip trailing '/' */
X
X    add_path(argv[index], FALSE);
X    add_path("/", FALSE);
X
X    if (dos_dir)
X        print_string(FALSE, "Directory %s:\n", path);
X
X    entry = find_entry(root, root_entries, argv[index]);
X
X    if (dos_dir) {
X        list_dir(entry, sub_entries, FALSE);
X        free_blocks();
X    }
X    else if (dos_read)
X        extract(entry);
X    else {
X        if (entry != NIL_DIR) {
X            flush();
X            if (is_dir(entry))
X                print_string(TRUE, "%s is a directory.\n", path);
X            else
X                print_string(TRUE, "%s already exists.\n", argv[index]);
X            leave(1);
X        }
X
X        add_path(NIL_PTR, TRUE);
X
X        if (*path)
X            make_file(find_entry(root, root_entries, path),
X                  sub_entries, slash(argv[index]));
X        else
X            make_file(root, root_entries, argv[index]);
X    }
X
X    (void) close(disk);
X    flush();
X    leave(0);
X}
X
Xfdinit(part_nr)        /* Fixed Disk Initializations */
Xchar part_nr;
X{
X
X#define    SECSIZE        512        /* sector size        */
X#define TABLEOFFSET    0x1be      /* offset in boot sector*/
X
X    /*
X     * Description of entry in partition table
X     */
X    struct part_entry {
X        char    bootind;    /* boot indicator 0/0x80    */
X        char    start_head;    /* head value for first sector    */
X        char    start_sec;    /* sector value for first sector*/
X        char    start_cyl;    /* track value for first sector    */
X        char    sysind;        /* system indicator 00=?? 01=DOS*/
X        char    last_head;    /* head value for last sector    */
X        char    last_sec;    /* sector value for last sector    */
X        char    last_cyl;    /* track value for last sector    */
X        long    lowsec;        /* logical first sector        */
X        long    size;        /* size of partion in sectors    */
X    } *pe;
X
X    char    secbuf[SECSIZE];
X
X    /*
X     *    Description of the boot block
X     */
X    struct {
X        unsigned char jump[3];
X        unsigned char oem[8];
X        unsigned char bytes_sector[2];
X        unsigned char cluster_size;
X        unsigned char res_sectors[2];
X        unsigned char num_fats;
X        unsigned char root_entries[2];
X        unsigned char logical_sectors[2];
X        unsigned char media_type;
X        unsigned char fat_sectors[2];
X        unsigned char track_sectors[2];
X        unsigned char num_heads[2];
X        unsigned char hidden_sectors[2];
X    } boot;
X
X    short block_size, reserved;    long boot_loc;
X
X    disk_read(0L, secbuf, SECSIZE);    /* get boot sector */
X        /* offset into boot sector for the partition table */
X    pe = (struct part_entry *)&secbuf[TABLEOFFSET];
X        /* get the proper partition */
X    switch(part_nr) {
X        case 'f': pe++;
X        case 'e': pe++;
X        case 'd': pe++;
X        case 'c': boot_loc = pe->lowsec * 512L; break;
X            default:  printf("Error: unknown partition\n"); leave();
X    }
X        /* now read the boot block for the partition needed */
X    disk_read(boot_loc, &boot, sizeof(boot));
X
X    /* this section can be used to print drive information */
X/**************
X    printf("OEM = %s\n", boot.oem);
X    printf("Bytes/sector = %d\n",
X        (boot.bytes_sector[1] << 8 & HMASK) + (boot.bytes_sector[0] & LMASK));
X    printf("Sectors/cluster = %d\n", boot.cluster_size);
X    printf("Number of Reserved Clusters = %d\n",
X        (boot.res_sectors[1] << 8 & HMASK) + (boot.res_sectors[0] & LMASK));
X    printf("Number of FAT's = %d\n", boot.num_fats);
X    printf("Number of root-directory entries = %d\n",
X        (boot.root_entries[1] << 8 & HMASK) + (boot.root_entries[0] & LMASK));
X    printf("Total sectors in logical volume = %D\n",
X        (long) (boot.logical_sectors[1] << 8 & HMASK) +
(boot.logical_sectors[0] & LMASK));
X    printf("Media Descriptor = %x\n", boot.media_type);
X    printf("Number of sectors/FAT = %d\n",
X        (boot.fat_sectors[1] << 8 & HMASK) + (boot.fat_sectors[0] & LMASK));
X    printf("Sectors/track = %d\n",
X        (boot.track_sectors[1] << 8 & HMASK) + (boot.track_sectors[0] &
 LMASK));
X    printf("Number of Heads = %d\n",
X        (boot.num_heads[1] << 8 & HMASK) + (boot.num_heads[0] & LMASK));
X    printf("Number of hidden sectors = %d\n",
X        (boot.hidden_sectors[1]  << 8 & HMASK) + (boot.hidden_sectors[0] &
 LMASK));
X    leave(1);
X/**************/
X    if (boot.media_type != DDFD) {
X        printf("DISK is not DOS Format.\n");
X        leave(1);
X    }
X    if (boot.num_fats != 2) {
X        printf("Disk does not have two FAT Tables!\n");
X        leave(1);
X    }
X    block_size = (boot.bytes_sector[1] << 8 & HMASK) +
X             (boot.bytes_sector[0] & LMASK);
X    if ((cluster_size = block_size * boot.cluster_size)
X                    > MAX_CLUSTER_SIZE) {
X        printf("Cluster size is larger than MAX_CLUSTER_SIZE.\n");
X        leave(1);
X    }
X    reserved =  ((boot.res_sectors[1] << 8 & HMASK) +
X            (boot.res_sectors[0] & LMASK));
X    f_start = boot_loc + (long) block_size * (long) reserved;
X    root_entries = (boot.root_entries[1] << 8 & HMASK) +
X            (boot.root_entries[0] & LMASK);
X    fat_size = (boot.fat_sectors[1] << 8 & HMASK) +
X             (boot.fat_sectors[0] & LMASK);
X        /* (sectors - rootdir - fats - reserved) / blocks/cluster */
X    total_clusters = (int) ((long) ((boot.logical_sectors[1] << 8 & HMASK) +
X                   (boot.logical_sectors[0] & LMASK)) -
X          (root_entries * 32 / block_size) -
X          (fat_size * 2) - reserved) / boot.cluster_size;
X    if (total_clusters > 4096)
X        Tfat = FALSE;        /* sixteen bit fat entries */
X    if ( (fat_size *= block_size) > MAX_FAT_SIZE) {
X        printf("Disk FAT is larger than MAX_FAT_SIZE.\n");
X        leave(1);
X    }
X    sub_entries = cluster_size / 32;
X    data_start = f_start + (long) (fat_size * 2L) +
X            (long) (root_entries * 32L);
X/**********
X    printf("f_start = %D\n", f_start);
X    printf("total_clusters = %d\n", total_clusters);
X    printf("cluster_size = %d\n", cluster_size);
X    printf("fat_size = %d\n", fat_size);
X    printf("data_start = %D\n", data_start);
X    printf("root_entries = %d\n", root_entries);
X    printf("sub_entries = %d\n", sub_entries);
X    printf("Tfat = %d\n", Tfat);
X    leave(1);
X/*********/
X}
X
XDIRECTORY *directory(dir, entries, function, pathname)
XDIRECTORY *dir;
Xshort entries;
XBOOL function;
Xregister char *pathname;
X{
X    register DIRECTORY *dir_ptr = dir;
X    DIRECTORY *mem = NIL_DIR;
X    unsigned short cl_no = dir->d_cluster;
X    unsigned short type, last;
X    char file_name[14];
X    char *name;
X    int i = 0;
X
X    if (function == FIND) {
X        while (*pathname != '/' && *pathname && i < 12)
X            file_name[i++] = *pathname++;
X        while (*pathname != '/' && *pathname)
X            pathname++;
X        file_name[i] = '\0';
X    }
X
X    do {
X        if (entries != root_entries) {
X            mem = dir_ptr = read_cluster(cl_no);
X            last = cl_no;
X            cl_no = next_cluster(cl_no);
X        }
X
X        for (i = 0; i < entries; i++, dir_ptr++) {
X            type = dir_ptr->d_name[0] & 0x0FF;
X            if (function == ENTRY) {
X                if (type == NOT_USED || type == ERASED) {
X                    mark = lseek(disk, 0L, 1) -
X                        (long) cluster_size +
X                        (long) i * (long) DIR_SIZE;
X                    if (!mem)
X                        mark += (long) cluster_size - (long) (root_entries *
 sizeof (DIRECTORY));
X                    return dir_ptr;
X                }
X                continue;
X            }
X            if (type == NOT_USED)
X                break;
X            if (dir_ptr->d_attribute & 0x08) {
X                if (function == LABEL)
X                    return dir_ptr;
X                continue;
X            }
X            if (type == DIR || type == ERASED || function == LABEL)
X                continue;
X            type = is_dir(dir_ptr);
X            name = make_name(dir_ptr, (function == FIND) ?
X                     FALSE : type);
X            if (function == FIND) {
X                if (strcmp(file_name, name) != 0)
X                    continue;
X                if (!type) {
X                    if (dos_dir || *pathname) {
X                        flush();
X                        print_string(TRUE, "Not a directory: %s\n", file_name);
X                        leave(1);
X                    }
X                }
X                else if (*pathname == '\0' && dos_read) {
X                    flush();
X                    print_string(TRUE, "%s is a directory.\n", path);
X                    leave(1);
X                }
X                if (*pathname) {
X                    dir_ptr = find_entry(dir_ptr,
X                           sub_entries, pathname + 1);
X                }
X                if (mem) {
X                    if (dir_ptr) {
X                        bcopy(dir_ptr, &save_entry, DIR_SIZE);
X                        dir_ptr = &save_entry;
X                    }
X                    (void) brk(mem);
X                }
X                return dir_ptr;
X            }
X            else {
X                if (function == FALSE)
X                    show(dir_ptr, name);
X                else if (type) {    /* Recursive */
X                    print_string(FALSE, "Directory %s%s:\n", path, name);
X                    add_path(name, FALSE);
X                    list_dir(dir_ptr, sub_entries, FALSE);
X                    add_path(NIL_PTR, FALSE);
X                }
X            }
X        }
X        if (mem)
X            (void) brk(mem);
X    } while ((Tfat && cl_no != LAST_CLUSTER && mem) ||
X         (!Tfat && cl_no != LAST_16 && mem));
X
X    switch (function) {
X        case FIND:
X            if (dos_write && *pathname == '\0')
X                return NIL_DIR;
X            flush();
X            print_string(TRUE, "Cannot find `%s'.\n", file_name);
X            leave(1);
X        case LABEL:
X            return NIL_DIR;
X        case ENTRY:
X            if (!mem) {
X                flush();
X                print_string(TRUE, "No entries left in root directory.\n");
X                leave(1);
X            }
X
X            cl_no = free_cluster(TRUE);
X            link_fat(last, cl_no);
X            if (Tfat)
X                link_fat(cl_no, LAST_CLUSTER);
X            else
X                link_fat(cl_no, LAST_16);
X            disk_write(clus_add(cl_no), null, cluster_size);
X
X            return new_entry(dir, entries);
X        case FALSE:
X            if (Rflag) {
X                print(STD_OUT, "\n", 0);
X                list_dir(dir, entries, TRUE);
X            }
X    }
X}
X
Xextract(entry)
Xregister DIRECTORY *entry;
X{
X    register unsigned short cl_no = entry->d_cluster;
X    char buffer[MAX_CLUSTER_SIZE];
X    short rest;
X
X    if (entry->d_size == 0)           /* Empty file */
X        return;
X
X    do {
X        disk_read(clus_add(cl_no), buffer, cluster_size);
X        rest = (entry->d_size > (long) cluster_size) ? cluster_size : (short)
 entry->d_size;
X        print(STD_OUT, buffer, rest);
X        entry->d_size -= (long) rest;
X        cl_no = next_cluster(cl_no);
X        if ((Tfat && cl_no == BAD) || (!Tfat && cl_no == BAD_16)){
X            flush();
X            print_string(TRUE, "Reserved cluster value encountered.\n");
X            leave(1);
X        }
X    } while ((Tfat && entry->d_size && cl_no != LAST_CLUSTER) ||
X         (!Tfat && entry->d_size && cl_no != LAST_16));
X
X    if ((Tfat && cl_no != LAST_CLUSTER) || (!Tfat && cl_no != LAST_16))
X        print_string(TRUE, "Too many clusters allocated for file.\n");
X    else if (entry->d_size != 0)
X        print_string(TRUE, "Premature EOF: %L bytes left.\n",
X                 entry->d_size);
X}
X
Xprint(fd, buffer, bytes)
Xshort fd;
Xregister char *buffer;
Xregister short bytes;
X{
X    static short index;
X    static BOOL lf_pending = FALSE;
X    static char output[MAX_CLUSTER_SIZE + 1];
X
X    if (buffer == NIL_PTR) {
X        if (dos_read && Aflag && lf_pending) {
X            output[index++] = '\r';
X            lf_pending = FALSE;
X        }
X        if (write(fd, output, index) != index)
X            bad();
X        index = 0;
X        return;
X    }
X
X    if (bytes == 0)
X        bytes = strlen(buffer);
X
X    while (bytes--) {
X        if (index >= MAX_CLUSTER_SIZE) {
X            if (write(fd, output, index) != index)
X                bad ();
X            index = 0;
X        }
X        if (dos_read && Aflag) {
X            if (*buffer == '\r') {
X                if (lf_pending)
X                    output[index++] = *buffer++;
X                else {
X                    lf_pending = TRUE;
X                    buffer++;
X                }
X            }
X            else if (*buffer == '\n') {
X                output[index++] = *buffer++;
X                lf_pending = FALSE;
X            }
X            else if (lf_pending) {
X                output[index++] = '\r';
X                output[index++] = *buffer++;
X            }
X            else if ((output[index++] = *buffer++) == EOF_MARK) {
X                if (lf_pending) {
X                    output[index - 1] = '\r';
X                    index++;
X                    lf_pending = FALSE;
X                }
X                index--;
X                return;
X            }
X        }
X        else
X            output[index++] = *buffer++;
X    }
X}
X
Xmake_file(dir_ptr, entries, name)
XDIRECTORY *dir_ptr;
Xint entries;
Xchar *name;
X{
X    register DIRECTORY *entry = new_entry(dir_ptr, entries);
X    register char *ptr;
X    char buffer[MAX_CLUSTER_SIZE];
X    unsigned short cl_no, next;
X    short i, r;
X    long size = 0L;
X
X    bcopy("           ",&entry->d_name[0],11);    /* clear entry */
X    for (i = 0, ptr = name; i < 8 && *ptr != '.' && *ptr; i++)
X        entry->d_name[i] = *ptr++;
X    while (*ptr != '.' && *ptr)
X        ptr++;
X    if (*ptr == '.')
X        ptr++;
X    for (i=0;i < 3 && *ptr; i++)
X        entry->d_ext[i] = *ptr++;
X
X    for (i = 0; i < 10; i++)
X        entry->d_reserved[i] = '\0';
X    entry->d_attribute = '\0';
X
X    entry->d_cluster = 0;
X
X    while ((r = fill(buffer)) > 0) {
X        if ((next = free_cluster(FALSE)) > total_clusters) {
X            print_string(TRUE, "Disk full. File truncated.\n");
X            break;
X        }
X
X        disk_write(clus_add(next), buffer, r);
X
X        if (entry->d_cluster == 0)
X            cl_no = entry->d_cluster = next;
X        else {
X            link_fat(cl_no, next);
X            cl_no = next;
X        }
X
X        size += r;
X    }
X
X    if (entry->d_cluster != 0) {
X        if (Tfat)
X            link_fat(cl_no, LAST_CLUSTER);
X        else
X            link_fat(cl_no, LAST_16);
X    }
X
X    entry->d_size = Aflag ? (size - 1) : size;    /* Strip added ^Z */
X    fill_date(entry);
X    disk_write(mark, entry, DIR_SIZE);
X    if (Tfat) {
X        disk_write(f_start, fat.twelve, fat_size);
X        disk_write(f_start + (long) fat_size, fat.twelve, fat_size);
X    } else {
X        disk_write(f_start, fat.sixteen, fat_size);
X        disk_write(f_start + (long) fat_size, fat.sixteen, fat_size);
X    }
X}
X
X
X#define SEC_MIN    60L
X#define SEC_HOUR    (60L * SEC_MIN)
X#define SEC_DAY    (24L * SEC_HOUR)
X#define SEC_YEAR    (365L * SEC_DAY)
X#define SEC_LYEAR    (366L * SEC_DAY)
X
Xshort mon_len[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
X
Xfill_date(entry)
XDIRECTORY *entry;
X{
X    register long cur_time = time((long *) 0) - DOS_TIME;
X    unsigned short year = 0, month = 1, day, hour, minutes, seconds;
X    int i;
X    long tmp;
X
X    if (cur_time < 0)           /* Date not set on booting ... */
X        cur_time = 0;
X    for (;;) {
X        tmp = (year % 4 == 0) ? SEC_LYEAR : SEC_YEAR;
X        if (cur_time < tmp)
X            break;
X        cur_time -= tmp;
X        year++;
X    }
X
X    day = (unsigned short) (cur_time / SEC_DAY);
X    cur_time -= (long) day *SEC_DAY;
X
X    hour = (unsigned short) (cur_time / SEC_HOUR);
X    cur_time -= (long) hour *SEC_HOUR;
X
X    minutes = (unsigned short) (cur_time / SEC_MIN);
X    cur_time -= (long) minutes *SEC_MIN;
X
X    seconds = (unsigned short) cur_time;
X
X    mon_len[1] = (year % 4 == 0) ? 29 : 28;
X    i = 0;
X    while (day >= mon_len[i]) {
X        month++;
X        day -= mon_len[i++];
X    }
X    day++;
X
X    entry->d_date = (year << 9) | (month << 5) | day;
X    entry->d_time = (hour << 11) | (minutes << 5) | seconds;
X}
X
Xchar *make_name(dir_ptr, dir_fl)
Xregister DIRECTORY *dir_ptr;
Xshort dir_fl;
X{
X    static char name_buf[14];
X    register char *ptr = name_buf;
X    short i;
X
X    for (i = 0; i < 8; i++)
X        *ptr++ = dir_ptr->d_name[i];
X
X    while (*--ptr == ' ');
X
X    ptr++;
X    if (dir_ptr->d_ext[0] != ' ') {
X        *ptr++ = '.';
X        for (i = 0; i < 3; i++)
X            *ptr++ = dir_ptr->d_ext[i];
X        while (*--ptr == ' ');
X        ptr++;
X    }
X    if (dir_fl)
X        *ptr++ = '/';
X    *ptr = '\0';
X
X    return name_buf;
X}
X
Xfill(buffer)
Xregister char *buffer;
X{
X    static BOOL eof_mark = FALSE;
X    char *last = &buffer[cluster_size];
X    char *begin = buffer;
X    register short c;
X
X    if (eof_mark)
X        return 0;
X
X    while (buffer < last) {
X        if ((c = get_char()) == EOF) {
X            eof_mark = TRUE;
X            if (Aflag)
X                *buffer++ = EOF_MARK;
X            break;
X        }
X        *buffer++ = c;
X    }
X
X    return (int) (buffer - begin);
X}
X
Xget_char()
X{
X    static short read_chars, index;
X    static char input[MAX_CLUSTER_SIZE];
X    static BOOL new_line = FALSE;
X
X    if (new_line == TRUE) {
X        new_line = FALSE;
X        return '\n';
X    }
X
X    if (index == read_chars) {
X        if ((read_chars = read(0, input, cluster_size)) == 0)
X            return EOF;
X        index = 0;
X    }
X
X    if (Aflag && input[index] == '\n') {
X        new_line = TRUE;
X        index++;
X        return '\r';
X    }
X
X    return input[index++];
X}
X
X#define HOUR    0xF800               /* Upper 5 bits */
X#define MIN    0x07E0               /* Middle 6 bits */
X#define YEAR    0xFE00               /* Upper 7 bits */
X#define MONTH    0x01E0               /* Mid 4 bits */
X#define DAY    0x01F               /* Lowest 5 bits */
X
Xchar *month[] = {
X         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X};
X
Xmodes(mode)
Xregister unsigned char mode;
X{
X    print_string(FALSE, "\t%c%c%c%c%c", (mode & SUB_DIR) ? 'd' : '-',
X             (mode & 02) ? 'h' : '-', (mode & 04) ? 's' : '-',
X             (mode & 01) ? '-' : 'w', (mode & 0x20) ? 'a' : '-');
X}
X
Xshow(dir_ptr, name)
XDIRECTORY *dir_ptr;
Xchar *name;
X{
X    register unsigned short e_date = dir_ptr->d_date;
X    register unsigned short e_time = dir_ptr->d_time;
X    unsigned short next;
X    char bname[20];
X    short i = 0;
X
X    while (*name && *name != '/')
X        bname[i++] = *name++;
X    bname[i] = '\0';
X    if (!Lflag) {
X        print_string(FALSE, "%s\n", bname);
X        return;
X    }
X    modes(dir_ptr->d_attribute);
X    print_string(FALSE, "\t%s%s", bname, strlen(bname) < 8 ? "\t\t" : "\t");
X    i = 1;
X    if (is_dir(dir_ptr)) {
X        next = dir_ptr->d_cluster;
X        while (((next = next_cluster(next)) != LAST_CLUSTER && Tfat) ||
X            (!Tfat && next != LAST_16))
X            i++;
X        print_string(FALSE, "%L", (long) i * (long) cluster_size);
X    }
X    else
X        print_string(FALSE, "%L", dir_ptr->d_size);
X    print_string(FALSE, "\t%N:%N %P %s %d\n", ((e_time & HOUR) >> 11),
X             ((e_time & MIN) >> 5), (e_date & DAY),
X       month[((e_date & MONTH) >> 5) - 1], ((e_date & YEAR) >> 9) + 1980);
X}
X
Xfree_blocks()
X{
X    register unsigned short cl_no;
X    register short free = 0;
X    short bad = 0;
X    if (Tfat)
X        for (cl_no = 2; cl_no <= total_clusters; cl_no++) {
X            switch (next_cluster(cl_no)) {
X                case FREE:
X                    free++;
X                    break;
X                case BAD:
X                    bad++;
X            }
X        }
X    else
X        for (cl_no = 2; cl_no <= total_clusters; cl_no++) {
X            switch (next_cluster(cl_no)) {
X                case FREE_16:
X                    free++;
X                    break;
X                case BAD_16:
X                    bad++;
X            }
X        }
X
X    print_string(FALSE, "Free space: %L bytes.\n", (long) free * (long)
 cluster_size);
X    if (bad)
X        print_string(FALSE, "Bad sectors: %L bytes.\n", (long) bad * (long)
 cluster_size);
X}
X
Xchar *num_out(number)
Xregister long number;
X{
X    static char num_buf[13];
X    char temp[13];
X    register short i = 0;
X    short j;
X
X    if (number == 0)
X        temp[i++] = '0';
X
X    while (number) {
X        temp[i++] = (char) (number % 10L + '0');
X        number /= 10L;
X    }
X
X    for (j = 0; j < 11; j++)
X        num_buf[j] = temp[i - j - 1];
X
X    num_buf[i] = '\0';
X    return num_buf;
X}
X
X/* VARARGS */
Xprint_string(err_fl, fmt, args)
XBOOL err_fl;
Xchar *fmt;
Xint args;
X{
X    char buf[200];
X    register char *buf_ptr = buf;
X    char *scan_ptr;
X    register int *arg_ptr = &args;
X    short i;
X
X    while (*fmt) {
X        if (*fmt == '%') {
X            fmt++;
X            if (*fmt == 'c') {
X                *buf_ptr++ = (char) *arg_ptr++;
X                fmt++;
X                continue;
X            }
X            if (*fmt == 'S') {
X                scan_ptr = (char *) *arg_ptr;
X                for (i = 0; i < 11; i++)
X                    *buf_ptr++ = *scan_ptr++;
X                fmt++;
X                continue;
X            }
X            if (*fmt == 's')
X                scan_ptr = (char *) *arg_ptr;
X            else if (*fmt == 'L') {
X                scan_ptr = num_out(*((long *) arg_ptr));
X                arg_ptr++;
X            }
X            else {
X                scan_ptr = num_out((long) *arg_ptr);
X                if (*fmt == 'P' && *arg_ptr < 10)
X                    *buf_ptr++ = ' ';
X                else if (*fmt == 'N' && *arg_ptr < 10)
X                    *buf_ptr++ = '0';
X            }
X            while (*buf_ptr++ = *scan_ptr++);
X            buf_ptr--;
X            arg_ptr++;
X            fmt++;
X        }
X        else
X            *buf_ptr++ = *fmt++;
X    }
X
X    *buf_ptr = '\0';
X
X    if (err_fl) {
X        flush();
X        write(2, buf, (int) (buf_ptr - buf));
X    }
X    else
X        print(STD_OUT, buf, 0);
Xflush();
X}
X
XDIRECTORY *read_cluster(cluster)
Xregister unsigned short cluster;
X{
X    register DIRECTORY *sub_dir;
X    extern char *sbrk();
X
X    if ((sub_dir = (DIRECTORY *) sbrk(cluster_size)) < 0) {
X        print_string(TRUE, "Cannot set break!\n");
X        leave(1);
X    }
X    disk_read(clus_add(cluster), sub_dir, cluster_size);
X
X    return sub_dir;
X}
X
Xunsigned short free_cluster(leave_fl)
XBOOL leave_fl;
X{
X    static unsigned short cl_index = 2;
X
X    if (Tfat)
X        while (cl_index <= total_clusters && next_cluster(cl_index) != FREE)
X            cl_index++;
X    else        /* Sixteen bit */
X        while (cl_index <= total_clusters && next_cluster(cl_index) != FREE_16)
X            cl_index++;
X
X    if (leave_fl && cl_index > total_clusters) {
X        flush();
X        print_string(TRUE, "Disk full. File not added.\n");
X        leave(1);
X    }
X
X    return cl_index++;
X}
X
X/* ****************FIX FOR SIXTEEN BIT ***************** */
Xlink_fat(cl_1, cl_2)
Xunsigned short cl_1;
Xregister unsigned short cl_2;
X{
X    if (Tfat) {
X        register unsigned char *fat_index = &fat.twelve[(cl_1 >> 1) * 3 + 1];
X        if (cl_1 & 0x01) {
X            *(fat_index + 1) = cl_2 >> 4;
X            *fat_index = (*fat_index & 0x0F) | ((cl_2 & 0x0F) << 4);
X        }
X        else {
X            *(fat_index - 1) = cl_2 & 0x0FF;
X            *fat_index = (*fat_index & 0xF0) | (cl_2 >> 8);
X        }
X    }
X    else {
X        fat.sixteen[cl_1] = cl_2;
X    }
X}
X
X
Xunsigned short next_cluster(cl_no)
Xregister unsigned short cl_no;
X{
X    if (Tfat) {
X        register unsigned char *fat_index = &fat.twelve[(cl_no >> 1) * 3 + 1];
X
X        if (cl_no & 0x01)
X            cl_no = (*(fat_index + 1) << 4) | (*fat_index >> 4);
X        else
X            cl_no = ((*fat_index & 0x0F) << 8) | *(fat_index - 1);
X
X        if ((cl_no & MASK) == MASK)
X            cl_no = LAST_CLUSTER;
X        else if ((cl_no & BAD) == BAD)
X            cl_no = BAD;
X    }
X    else {
X        /*cl_no = fat.sixteen[cl_no << 1];*/
X        cl_no = fat.sixteen[cl_no];
X        if ((cl_no & MASK_16) == MASK_16)
X            cl_no = LAST_16;
X        else if ((cl_no & BAD_16) == BAD_16)
X            cl_no = BAD_16;
X    }
X
X    return cl_no;
X}
X
Xchar *slash(str)
Xregister char *str;
X{
X    register char *result = str;
X
X    while (*str)
X        if (*str++ == '/')
X            result = str;
X
X    return result;
X}
X
Xadd_path(file, slash_fl)
Xregister char *file;
XBOOL slash_fl;
X{
X    register char *ptr = path;
X
X    while (*ptr)
X        ptr++;
X
X    if (file == NIL_PTR) {
X        ptr--;
X        do {
X            ptr--;
X        } while (*ptr != '/' && ptr != path);
X        if (ptr != path && !slash_fl)
X            ptr++;
X        *ptr = '\0';
X    }
X    else
X        while (*ptr++ = *file++);
X}
X
Xbcopy(src, dest, bytes)
Xregister char *src, *dest;
Xshort bytes;
X{
X    while (bytes--)
X        *dest++ = *src++;
X}
X
Xdisk_io(op, seek, address, bytes)
Xregister BOOL op;
Xunsigned long seek;
XDIRECTORY *address;
Xregister unsigned bytes;
X{
X    unsigned int r;
X
X    if (lseek(disk, seek, 0) < 0L) {
X        flush();
X        print_string(TRUE, "Bad lseek\n");
X        leave(1);
X    }
X
X    if (op == READ)
X        r = read(disk, address, bytes);
X    else
X        r = write(disk, address, bytes);
X
X    if (r != bytes)
X        bad();
X}
X
Xbad()
X{
X    flush();
X    perror("I/O error");
X    leave(1);
X}
+ END-OF-FILE dosread.c
chmod 'u=rw,g=r,o=r' 'dosread.c'
set `wc -c 'dosread.c'`
count=$1
case $count in
28473)    :;;
*)    echo 'Bad character count in ''dosread.c' >&2
        echo 'Count should be 28473' >&2
esac
echo Extracting 'factor.c.cdif'
sed 's/^X//' > 'factor.c.cdif' << '+ END-OF-FILE ''factor.c.cdif'
X*** /local/ast/minix/tape3b/commands/factor.c    Wed Jul 13 13:10:54 1988
X--- factor.c    Sun Sep 25 15:24:59 1988
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* factor - print the prime factors of a number      Author: Andy Tanenbaum
 */
X+
X  main(argc, argv)
X  int argc;
X  char *argv[];
+ END-OF-FILE factor.c.cdif
chmod 'u=rw,g=r,o=r' 'factor.c.cdif'
set `wc -c 'factor.c.cdif'`
count=$1
case $count in
282)    :;;
*)    echo 'Bad character count in ''factor.c.cdif' >&2
        echo 'Count should be 282' >&2
esac
echo Extracting 'fgrep.c.cdif'
sed 's/^X//' > 'fgrep.c.cdif' << '+ END-OF-FILE ''fgrep.c.cdif'
X*** /local/ast/minix/tape3b/commands/fgrep.c    Wed Jul 13 13:10:55 1988
X--- fgrep.c    Sun Sep 25 15:24:59 1988
X***************
X*** 25,31 ****
X    int find();
X    void exparg();
X    void getargs();
X-   void maktbl();
X    void gotone();
X
X    argc=oargc;
X--- 25,30 ----
X***************
X*** 72,77 ****
X--- 71,77 ----
X  void getargs()
X  {
X    int tmp;
X+   void maktbl();
X    for (i=1; i< argc && argv[i][0]=='-'; i++) {
X      switch (argv[i][1]) {
X      case 'e':
+ END-OF-FILE fgrep.c.cdif
chmod 'u=rw,g=r,o=r' 'fgrep.c.cdif'
set `wc -c 'fgrep.c.cdif'`
count=$1
case $count in
457)    :;;
*)    echo 'Bad character count in ''fgrep.c.cdif' >&2
        echo 'Count should be 457' >&2
esac
echo Extracting 'file.c.cdif'
sed 's/^X//' > 'file.c.cdif' << '+ END-OF-FILE ''file.c.cdif'
X*** /local/ast/minix/tape3b/commands/file.c    Wed Jul 13 13:10:55 1988
X--- file.c    Sun Sep 25 15:25:00 1988
X***************
X*** 28,33 ****
X--- 28,34 ----
X  char *name;
X  {
X    int i, fd, n, magic, second, mode, nonascii, special, funnypct, etaoins;
X+   int symbols;
X    long engpct;
X    char c;
X    struct stat st_buf;
X***************
X*** 86,97 ****
X    /* Check to see if file is an executable binary. */
X    if (magic == A_OUT) {
X      /* File is executable.  Check for split I/D. */
X!     printf("executable ");
X      second = (buf[3]<<8) | (buf[2]&0377);
X      if (second == SPLIT)
X!         printf(" separate I & D space\n");
X      else
X!         printf(" combined I & D space\n");
X      close(fd);
X       return;
X    }
X--- 87,103 ----
X    /* Check to see if file is an executable binary. */
X    if (magic == A_OUT) {
X      /* File is executable.  Check for split I/D. */
X!     printf("executable");
X      second = (buf[3]<<8) | (buf[2]&0377);
X      if (second == SPLIT)
X!         printf("   separate I & D space");
X      else
X!         printf("   combined I & D space");
X!     symbols = buf[28] | buf[29] | buf[30] | buf[31];
X!     if (symbols != 0)
X!         printf("   not stripped\n");
X!     else
X!         printf("   stripped\n");
X      close(fd);
X       return;
X    }
+ END-OF-FILE file.c.cdif
chmod 'u=rw,g=r,o=r' 'file.c.cdif'
set `wc -c 'file.c.cdif'`
count=$1
case $count in
1189)    :;;
*)    echo 'Bad character count in ''file.c.cdif' >&2
        echo 'Count should be 1189' >&2
esac
echo Extracting 'getlf.c.cdif'
sed 's/^X//' > 'getlf.c.cdif' << '+ END-OF-FILE ''getlf.c.cdif'
X*** /local/ast/minix/tape3b/commands/getlf.c    Wed Jul 13 13:10:56 1988
X--- getlf.c    Sun Sep 25 15:25:01 1988
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* getlf - get a line feed        Author: Andy Tanenbaum */
X+
X  main(argc, argv)
X  int argc;
X  char *argv[];
+ END-OF-FILE getlf.c.cdif
chmod 'u=rw,g=r,o=r' 'getlf.c.cdif'
set `wc -c 'getlf.c.cdif'`
count=$1
case $count in
255)    :;;
*)    echo 'Bad character count in ''getlf.c.cdif' >&2
        echo 'Count should be 255' >&2
esac
echo Extracting 'help.c.new'
sed 's/^X//' > 'help.c.new' << '+ END-OF-FILE ''help.c.new'
X/* help - provide assistance about keywords    Author: Wolf N. Paul */
X
X#include 
X#include 
X#include 
X#include 
X
X#define MAXLINE    134
X#define HELPDIR    "/usr/lib"      /* Added by John Plocher */
X#define HELPFILE   "helpfile"      /* .. */
X#define INDEX      ".idx"          /* .. */
X
Xchar *helpfilename = "/usr/lib/helpfile";
Xchar *helpidxname  = "/usr/lib/helpfile.idx";
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X   struct
X   {
X       char name[15];
X       long offset;
X   } entry;                /* helpindex entries for each command */
X
X   struct stat sbuf1, sbuf2;   /* stat buffers for helpfile & helpindex */
X   char *command, *line, Line[MAXLINE];
X   register char   *cp;        /* John Plocher */
X   extern char *getenv();      /* .. */
X   int status;
X   FILE *ifp, *hfp;        /* file pointers for helpfile and helpindex */
X
X   if (argc > 2) {
X    fprintf(stderr, "Usage: help subject\n");
X    exit(1);
X   }
X
X   if ( argc == 1 )        /* If no arguments, ... */
X       command = "help";   /* ... default to "help help" */
X   else
X       command = argv[1];  /* else look for command in argv[1] */
X
X   stat(helpfilename, &sbuf1); /* get mtime for helpfile */
X   status=access(helpidxname, 0);
X   if ( status == 0 )  /* if helpindex exists ... */
X   {
X       stat(helpidxname, &sbuf2);  /* get mtime for helpindex */
X   }
X   if ( (status != 0) ||           /* if there is no helpindex ... */
X       (sbuf1.st_mtime > sbuf2.st_mtime) )
X                                   /* or if it is older than helpfile */
X   {
X       buildindex();       /* build a new helpindex */
X   }
X
X   system("clr");        /* clear the screen */
X
X   if ( (ifp=fopen(helpidxname, "r")) == NULL )
X   {
X       fprintf(stderr, "Can't read %s\n", helpidxname);
X       exit(-1);
X   }
X
X   while ( 1 )     /* look for index entry for "command" */
X   {
X       status=fread(&entry, sizeof(entry), 1, ifp);
X       if ( status==0 ) /* quit at end of index file */
X       {
X           fprintf(stderr, "No help for %s\n", command);
X           fclose(ifp);
X           exit(1);        }
X       if ( strcmp(entry.name, command) == 0 ) /* quit when we find it */
X       {
X           fclose(ifp);
X           break;
X       }
X   }
X
X   if ((hfp=fopen(helpfilename, "r")) == NULL )
X   {
X       fprintf(stderr, "Can't open %s\n", helpfilename);
X       exit(-1);
X   }
X
X   fseek(hfp, entry.offset, 0);    /* go to the help entry */
X
X   while ( 1 )         /* just copy lines to stdout */
X   {
X       line = fgets(Line, MAXLINE, hfp);
X       if ( line == (char *) NULL || line[0] == '#' )
X                       /* until another entry starts */
X           break;
X       fputs(line,stdout);
X   }
X
X   fclose(hfp);
X}
X
Xbuildindex()
X{
X   FILE *hfp, *ifp;
X   struct {
X       char name[15];
X       long offset;
X   } entry;
X   char Line[MAXLINE];
X   char *line;
X   int i,j;
X
X
X   unlink(helpidxname); /* remove old index file */
X   if ( (hfp=fopen(helpfilename, "r")) == NULL )
X   {
X       fprintf(stderr,"buildindex: Can't read %s\n", helpfilename);
X       exit(-1);
X   }
X   if ( (ifp=fopen(helpidxname, "w")) == NULL )
X   {
X       fprintf(stderr, "buildindex: Can't write %s\n", helpidxname);
X       exit(-1);
X   }
X
X   while (1)   /* Read thru helpfile ... */
X   {
X       entry.offset=(long) 0;
X       line = fgets(Line, MAXLINE, hfp);
X       if ( line == (char *) NULL ) break;
X       if ( line[0] == '#' )   /* and for each help entry ... */
X       {
X           line++;
X           while ( isspace(line[0]) ) line++;
X           i=j=0;
X           while ( line[i] != '\0' )
X           {
X               if ( line[i] == '\n' ) break;
X               while ( line[i] == ' ' || line[i] == ',' ) i++;
X               while ( !isspace(line[i] ) &&
X                       line[i] != ',') /* save its name ... */
X               {
X                   entry.name[j] = line[i];
X                   i++; j++;
X               }
X               while ( j < 15 )
X                   entry.name[j++] = '\0';
X               j = 0;
X               entry.offset=ftell(hfp);    /* and its offset ... */
X               fwrite(&entry, sizeof(entry), 1, ifp);
X                                       /* and write it to indexfile */
X           }
X       }
X   }
X   fclose(hfp);
X   fclose(ifp);
X}
+ END-OF-FILE help.c.new
chmod 'u=rw,g=r,o=r' 'help.c.new'
set `wc -c 'help.c.new'`
count=$1
case $count in
4249)    :;;
*)    echo 'Bad character count in ''help.c.new' >&2
        echo 'Count should be 4249' >&2
esac
echo Extracting 'libupack.c.cdif'
sed 's/^X//' > 'libupack.c.cdif' << '+ END-OF-FILE ''libupack.c.cdif'
X*** /local/ast/minix/tape3b/commands/libupack.c    Wed Jul 13 13:10:58 1988
X--- libupack.c    Sun Sep 25 15:25:03 1988
X***************
X*** 1,3 ****
X--- 1,5 ----
X+ /* libupack - unpack a packed .s file        Author: Andy Tanenbaum */
X+
X  char *table[] = {
X  "push ax",
X  "ret",
+ END-OF-FILE libupack.c.cdif
chmod 'u=rw,g=r,o=r' 'libupack.c.cdif'
set `wc -c 'libupack.c.cdif'`
count=$1
case $count in
267)    :;;
*)    echo 'Bad character count in ''libupack.c.cdif' >&2
        echo 'Count should be 267' >&2
esac
echo Extracting 'login.c'
sed 's/^X//' > 'login.c' << '+ END-OF-FILE ''login.c'
X/* login - log into the system        Author: Patrick van Kleef */
X
X/* Peter S. Housel   Jan. 1988
X *  - Set up $USER, $HOME and $TERM.
X *  - Set signals to SIG_DFL.
X *
X * Terrence W. Holm   June 1988
X *  - Allow a username as an optional argument.
X *  - Time out if a password is not typed within 30 seconds.
X *  - Perform a dummy delay after a bad username is entered.
X *  - Don't allow a login if "/etc/nologin" exists.
X *  - Cause a failure on bad "pw_shell" fields.
X *  - Record the login in "/usr/adm/wtmp".
X */
X
X#include 
X#include 
X#include 
X#include 
X
X#define  NULL   (char *) 0
X#define WTMPSIZE           8
X#define DIGIT 3
X
Xextern char *crypt();
Xextern struct passwd *getpwnam();
Xextern long time();
Xextern long lseek();
Xint Time_out();
X
Xint  time_out;
X
Xchar user[ 32 ];
Xchar logname[ 35 ];
Xchar home[ 64 ];
Xchar shell[ 64 ];
X
Xchar *env[] = {
X          user,
X          logname,
X          home,
X          shell,
X          "TERM=minix",
X          NULL
X};
Xchar wtmpfile[] = {"/usr/adm/wtmp"};
Xchar ttyname[] = {"tty?"};
X
X
Xmain( argc, argv )
Xint   argc;
Xchar *argv[];
X{
X    char    name[30];
X    char    password[30];
X    int     bad;
X    int    n;
X    int     ttynr;
X    struct  sgttyb args;
X    struct  passwd *pwd;
X    struct stat statbuf;
X    char   *sh = "/bin/sh";
X
X    /* Reset some of the line parameters in case they have been mashed */
X    if ( ioctl(0, TIOCGETP, &args) < 0 ) exit( 1 );
X
X    args.sg_kill  = '@';
X    args.sg_erase = '\b';
X    args.sg_flags = (args.sg_flags & 01700) | XTABS | CRMOD | ECHO;
X    ioctl (0, TIOCSETP, &args);
X
X    /* Get login name and passwd. */
X    for (;;) {
X        bad = 0;
X
X        if ( argc > 1 ) {
X            strcpy( name, argv[1] );
X            argc = 1;
X        } else {
X            do {
X            write(1,"login: ",7);
X            n = read (0, name, 30);
X            } while (n < 2);
X            name[n - 1] = 0;
X        }
X
X        /* Look up login/passwd. */
X        if ((pwd = getpwnam (name)) == 0) bad++;
X
X        /* If login name wrong or password exists, ask for pw. */
X        if (bad || strlen (pwd->pw_passwd) != 0) {
X            args.sg_flags &= ~ECHO;
X            ioctl (0, TIOCSETP, &args);
X            write(1,"Password: ",10);
X
X            time_out = 0;
X            signal( SIGALRM, Time_out );
X            alarm( 30 );
X
X            n = read (0, password, 30);
X
X            alarm( 0 );
X            if ( time_out ) {
X                n = 1;
X                bad++;
X            }
X
X            password[n - 1] = 0;
X            write(1,"\n",1);
X            args.sg_flags |= ECHO;
X            ioctl (0, TIOCSETP, &args);
X
X            if (bad && crypt(password, "aaaa") ||
X             strcmp (pwd->pw_passwd, crypt(password, pwd->pw_passwd))) {
X                write (1,"Login incorrect\n",16);
X                continue;
X            }
X        }
X
X        /*  Check if the system is going down  */
X        if ( access( "/etc/nologin", 0 ) == 0  &&
X                        strcmp( name, "root" ) != 0 ) {
X            write( 1, "System going down\n\n", 19 );
X            continue;
X        }
X
X
X        /* Look up /dev/tty number. */
X        fstat(0, &statbuf);
X        ttynr = statbuf.st_rdev & 0377;
X        ttyname[DIGIT] = '0' + ttynr;
X
X        /*  Write login record to /usr/adm/wtmp  */
X        wtmp(ttyname, name);
X
X        setgid( pwd->pw_gid );
X        setuid( pwd->pw_uid );
X
X        if (pwd->pw_shell[0]) sh = pwd->pw_shell;
X
X        /*  Set the environment  */
X        strcpy( user,  "USER=" );
X        strcat( user,   name );
X        strcpy( logname, "LOGNAME=" );
X        strcat( logname, name );
X        strcpy( home,  "HOME=" );
X        strcat( home,  pwd->pw_dir );
X        strcpy( shell, "SHELL=" );
X        strcat( shell, sh );
X
X        chdir( pwd->pw_dir );
X
X        /* Reset signals to default values. */
X
X        for ( n = 1;  n <= NR_SIGS;  ++n )
X            signal( n, SIG_DFL );
X
X        execle( sh, "-", NULL, env );
X        write(1,"exec failure\n",13);
X        exit(1);
X    }
X}
X
X
X
XTime_out( )
X{
X  time_out = 1;
X}
X
Xwtmp(tty, name)
X{
X/* Make an entry in /usr/adm/wtmp. */
X
X  int i, fd;
X  long t, time();
X  char ttybuff[WTMPSIZE], namebuff[WTMPSIZE];
X
X  fd = open(wtmpfile, 2);
X  if (fd < 0) return;        /* if wtmp does not exist, no accounting */
X  lseek(fd, 0L, 2);        /* append to file */
X
X  for (i = 0; i < WTMPSIZE; i++) {
X    ttybuff[i] = 0;
X    namebuff[i] = 0;
X  }
X  strncpy(ttybuff, tty, 8);
X  strncpy(namebuff, name, 8);
X  time(&t);
X  write(fd, ttybuff, WTMPSIZE);
X  write(fd, namebuff, WTMPSIZE);
X  write(fd, &t, sizeof(t));
X  close(fd);
X}
+ END-OF-FILE login.c
chmod 'u=rw,g=r,o=r' 'login.c'
set `wc -c 'login.c'`
count=$1
case $count in
3973)    :;;
*)    echo 'Bad character count in ''login.c' >&2
        echo 'Count should be 3973' >&2
esac
echo Extracting 'ls.c.cdif'
sed 's/^X//' > 'ls.c.cdif' << '+ END-OF-FILE ''ls.c.cdif'
X*** /local/ast/minix/tape3b/commands/ls.c    Wed Jul 13 13:11:02 1988
X--- ls.c    Sun Sep 25 15:25:05 1988
X***************
X*** 1,4 ****
X--- 1,5 ----
X  /* ls - list files and directories     Author: Andy Tanenbaum */
X+ /* Version: Minix 1.3 */
X
X  #include 
X  #include 
X***************
X*** 23,28 ****
X--- 24,30 ----
X    long modtime;
X    long size;
X    short link;
X+   char is_path;            /* 1 => fp_name is null terminated */
X  } file[NFILE+1];
X
X  struct dir {
X***************
X*** 99,105 ****
X    statflag = (topfiles == 0 ? 0 : 1);
X    if (present('c') || present('t') || present('u')) statflag = 1;
X    if (present('s') || present('l')) statflag = 1;
X!   while (k < argc) fill_file("", argv[k++], statflag);
X  }
X
X
X--- 101,107 ----
X    statflag = (topfiles == 0 ? 0 : 1);
X    if (present('c') || present('t') || present('u')) statflag = 1;
X    if (present('s') || present('l')) statflag = 1;
X!   while (k < argc) fill_file("", argv[k++], statflag,1);
X  }
X
X
X***************
X*** 212,218 ****
X      fp = &file[sort_index[k]];
X      if (present('l') || present('s') || present('i'))
X          if (fp->size == -1L)    /* -1 means stat not done */
X!             if (stat_file(dirname, fp) < 0) continue;
X
X      m = fp->mode & I_TYPE;    /* 'm' may be junk if 'expand' = 0 */
X      if (present('f')) m = I_DIRECTORY;
X--- 214,220 ----
X      fp = &file[sort_index[k]];
X      if (present('l') || present('s') || present('i'))
X          if (fp->size == -1L)    /* -1 means stat not done */
X!             if (stat_file(dirname, fp, fp->is_path) < 0) continue;
X
X      m = fp->mode & I_TYPE;    /* 'm' may be junk if 'expand' = 0 */
X      if (present('f')) m = I_DIRECTORY;
X***************
X*** 223,229 ****
X          /* Expand and print directory. */
X          exp_dir(fp);
X          sort(nrf, nrfiles - nrf, 0);
X!         if (topfiles > 1) fprintf(stdout, "\n%s:\n", fp->name);
X          print_total(nrf, nrfiles - nrf);
X          print(nrf, nrfiles - nrf, 0, fp->name);    /* recursion ! */
X          nrfiles = nrf;
X--- 225,235 ----
X          /* Expand and print directory. */
X          exp_dir(fp);
X          sort(nrf, nrfiles - nrf, 0);
X!         if (topfiles > 1) {
X!             fprintf(stdout, "\n");
X!             pfname(fp->name,fp->is_path);
X!             fprintf(stdout, ":\n");
X!         }
X          print_total(nrf, nrfiles - nrf);
X          print(nrf, nrfiles - nrf, 0, fp->name);    /* recursion ! */
X          nrfiles = nrf;
X***************
X*** 270,276 ****
X              if (*p == '.' && *(p+1) == 0) continue;
X              if (*p == '.' && *(p+1) == '.' && *(p+2) == 0) continue;
X          }
X!         fill_file(fp->name, p, statflag);
X      }
X    }
X    close(fd);
X--- 276,282 ----
X              if (*p == '.' && *(p+1) == 0) continue;
X              if (*p == '.' && *(p+1) == '.' && *(p+2) == 0) continue;
X          }
X!         fill_file(fp->name, p, statflag,0);
X      }
X    }
X    close(fd);
X***************
X*** 280,288 ****
X
X
X
X! fill_file(prefix, postfix, statflag)
X  char *prefix, *postfix;
X! int statflag;
X  {
X  /* Fill the next 'file' struct entry with the file whose name is formed by
X   * concatenating 'prefix' and 'postfix'.  Stat only if needed.
X--- 286,294 ----
X
X
X
X! fill_file(prefix, postfix, statflag, pathflag)
X  char *prefix, *postfix;
X! int statflag, pathflag;
X  {
X  /* Fill the next 'file' struct entry with the file whose name is formed by
X   * concatenating 'prefix' and 'postfix'.  Stat only if needed.
X***************
X*** 297,304 ****
X    }
X    fp = &file[nrfiles++];
X    fp->name = postfix;
X    if(statflag) {
X!     if (stat_file(prefix, fp) < 0) nrfiles--;
X    } else {
X      fp->size = -1L;        /* mark file as not yet stat'ed */
X    }
X--- 303,311 ----
X    }
X    fp = &file[nrfiles++];
X    fp->name = postfix;
X+   fp->is_path = pathflag;
X    if(statflag) {
X!     if (stat_file(prefix, fp, pathflag) < 0) nrfiles--;
X    } else {
X      fp->size = -1L;        /* mark file as not yet stat'ed */
X    }
X***************
X*** 308,315 ****
X
X
X
X! print_line(fp)
X  struct file *fp;
X  {
X    int blks, m, prot, s;
X    char *p1, *p2, *p3, c;
X--- 315,323 ----
X
X
X
X! print_line(fp,is_path)
X  struct file *fp;
X+ int  is_path;
X  {
X    int blks, m, prot, s;
X    char *p1, *p2, *p3, c;
X***************
X*** 358,376 ****
X
X      /* Print file name. */
X      m = 0;
X!     p1 = fp->name;
X!     while (*p1 != 0 && (m < DIRNAMELEN || *p1 == '/') ) {
X!         fprintf(stdout, "%c", *p1);
X!         m = (*p1 == '/' ? 0 : m + 1);
X!         p1++;
X!     }
X      fprintf(stdout, "\n");
X  }
X
X
X
X
X-
X  owngrp(fp)
X  struct file *fp;
X  {
X--- 366,394 ----
X
X      /* Print file name. */
X      m = 0;
X!     pfname(fp->name,fp->is_path);
X      fprintf(stdout, "\n");
X  }
X
X+ pfname(ptr,pathflag)
X+ char *ptr;
X+ int  pathflag;
X+ {
X+     int  m;
X+     if (pathflag) {
X+         fprintf(stdout,"%s",ptr);
X+     } else {
X+         /* dirname entry is null terminated if length < 14 */
X+         m = 0;
X+         while (*ptr && m < DIRNAMELEN) {
X+             putc(*ptr++, stdout);
X+             ++m;
X+         }
X+     }
X+ }
X
X
X
X  owngrp(fp)
X  struct file *fp;
X  {
X***************
X*** 393,405 ****
X
X
X
X! int stat_file(prefix, fp)
X  char *prefix;
X  struct file *fp;
X  {
X  /* Stat a file and enter it in 'file'. */
X
X!   char namebuf[MAXPATHLEN], *p, *org, *q;
X    struct stat sbuf;
X    int m, ctr;
X
X--- 411,424 ----
X
X
X
X! int stat_file(prefix, fp, pathflag)
X  char *prefix;
X  struct file *fp;
X+ int pathflag;
X  {
X  /* Stat a file and enter it in 'file'. */
X
X!   char namebuf[MAXPATHLEN], *p, *q;
X    struct stat sbuf;
X    int m, ctr;
X
X***************
X*** 408,421 ****
X    q = prefix;
X    while (*q != 0 && p - namebuf < MAXPATHLEN) *p++ = *q++;
X    if (*prefix != 0) *p++ = '/';
X-   org = fp->name;
X    q = fp->name;
X    ctr = 0;
X!   while (*q != 0 && p - namebuf < MAXPATHLEN) {
X!     ctr++;
X!     if (*q == '/') ctr = 0;
X!     if (ctr > DIRNAMELEN) break;
X!     *p++ = *q++;
X    }
X    *p = 0;
X
X--- 427,445 ----
X    q = prefix;
X    while (*q != 0 && p - namebuf < MAXPATHLEN) *p++ = *q++;
X    if (*prefix != 0) *p++ = '/';
X    q = fp->name;
X    ctr = 0;
X!
X!   if (pathflag) {
X!     /* fp->name is null terminated */
X!     while (*q) *p++ = *q++;
X!   } else {
X!     /* fp->name is char[14] */
X!     while (*q != 0 && p - namebuf < MAXPATHLEN) {
X!         ctr++;
X!         if (ctr > DIRNAMELEN) break;
X!         *p++ = *q++;
X!     }
X    }
X    *p = 0;
X
+ END-OF-FILE ls.c.cdif
chmod 'u=rw,g=r,o=r' 'ls.c.cdif'
set `wc -c 'ls.c.cdif'`
count=$1
case $count in
5992)    :;;
*)    echo 'Bad character count in ''ls.c.cdif' >&2
        echo 'Count should be 5992' >&2
esac
exit 0