ast@cs.vu.nl (Andy Tanenbaum) (09/28/88)
: 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 <stdio.h>
X#include <time.h>
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 <sys/stat.h>
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 <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
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 <signal.h>
X#include <sgtty.h>
X#include <pwd.h>
X#include <sys/stat.h>
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 <stdio.h>
X #include <sys/types.h>
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