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