ast@cs.vu.nl (Andy Tanenbaum) (08/11/87)
I have been informed that the sizes and checksums of a few files in 1.2 do not agree with the files posted earlier. To ensure that everyone has exactly the same files, here is a repeat of the files in question. These files are the definitive 1.2 versions. Andy Tanenbaum : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin echo Extracting \c\p\d\i\r\.\c sed 's/^X//' > \c\p\d\i\r\.\c << '+ END-OF-FILE '\c\p\d\i\r\.\c X/* cpdir - copy directory Author: Erik Baalbergen */ X X/* Use "cpdir [-v] src dst" to make a copy dst of directory src. X Cpdir should behave like the UNIX shell command X (cd src; tar cf - .) | (mkdir dst; cd dst; tar xf -) X but the linking structure of the tree, and the owner and time X information of files are not yet preserved. (See the work-yet-to-be-done list X below.) X The -v "verbose" flag enables you to see what's going on when running cpdir. X X Work yet to be done: X - preserve link structure, times, etc... X - 'stat' optimization (stat() is invoked twice for normal files) X - link checks, i.e. am I not overwriting a file/directory by itself? X * has been solved by letting 'cpdir' create the target directory X - handle character and block special files X * they're simply not copied X X Please report bugs and suggestions to erikb@cs.vu.nl X*/ X X#include "stdio.h" X X#define MKDIR1 "/bin/mkdir" X#define MKDIR2 "/usr/bin/mkdir" X#ifdef UNIX X#include <sys/types.h> X#include <sys/stat.h> X#else !UNIX X#include "stat.h" X#endif X X#define BUFSIZE 1024 X#define PLEN 256 X#define DIRSIZ 16 X Xchar *prog; Xint vflag = 0; /* verbose */ Xchar *strcpy(); X Xmain(argc, argv) X char *argv[]; X{ X int rc = 0; X char *p, *s; X X prog = *argv++; X if ((p = *argv) && *p == '-') { X argv++; X argc--; X while (*++p) { X switch (*p) { X case 'v': X vflag = 1; X break; X default: X fatal("illegal flag %s", p); X } X } X } X if (argc != 3) X fatal("Usage: cpdir [-v] source destination"); X if (ftype(s = *argv++) != S_IFDIR) X fatal("%s is not a directory", s); X cpdir(s, *argv); X exit(0); X} X Xcpdir(s, d) X char *s, *d; X{ X char spath[PLEN], dpath[PLEN]; X char ent[DIRSIZ + 1]; X register char *send = spath, *dend = dpath; X int fd, n; X X while (*send++ = *s++) {} X send--; X while (*dend++ = *d++) {} X if ((fd = open(spath, 0)) < 0) { X nonfatal("can't read directory %s", spath); X return; X } X *send++ = '/'; X ent[DIRSIZ] = '\0'; X mkdir(dpath); X dend[-1] = '/'; X while ((n = read(fd, ent, DIRSIZ)) == DIRSIZ) { X if (!((ent[0] == '\0' && ent[1] == '\0') X || (ent[2] == '.') && X (ent[3] == '\0' || (ent[3] == '.' && ent[4] == '\0')) X )) { X strcpy(send, ent + 2); X strcpy(dend, ent + 2); X switch (ftype(spath)) { X case S_IFDIR: X cpdir(spath, dpath); X break; X case S_IFREG: X cp(spath, dpath); X break; X default: X nonfatal("can't copy special file %s", spath); X } X } X } X close(fd); X if (n) X fatal("error in reading directory %s", spath); X} X Xmkdir(s) X char *s; X{ X int pid, status; X X if (vflag) X printf("mkdir %s\n", s); X if ((pid = fork()) == 0) { X execl(MKDIR1, "mkdir", s, (char *)0); X execl(MKDIR2, "mkdir", s, (char *)0); X fatal("can't execute %s or %s", MKDIR1, MKDIR2); X } X if (pid == -1) X fatal("can't fork", prog); X wait(&status); X if (status) X fatal("can't create %s", s); X} X Xcp(s, d) X char *s, *d; X{ X struct stat st; X char buf[BUFSIZE]; X int sfd, dfd, n; X X if (vflag) X printf("cp %s %s\n", s, d); X if ((sfd = open(s, 0)) < 0) X nonfatal("can't read %s", s); X else { X if (fstat(sfd, &st) < 0) X fatal("can't get file status of %s", s); X if ((dfd = creat(d, st.st_mode & 0777)) < 0) X fatal("can't create %s", d); X while ((n = read(sfd, buf, BUFSIZE)) > 0) X write(dfd, buf, n); X close(sfd); X close(dfd); X if (n) X fatal("error in reading file %s", s); X } X} X Xftype(s) X char *s; X{ X struct stat st; X X if (stat(s, &st) < 0) X fatal("can't get file status of %s", s); X return st.st_mode & S_IFMT; X} X Xnonfatal(s, a) X char *s, *a; X{ X fprintf(stderr, "%s: ", prog); X fprintf(stderr, s, a); X fprintf(stderr, "\n"); X} X Xfatal(s, a) X char *s, *a; X{ X nonfatal(s, a); X exit(1); X} X X + END-OF-FILE cpdir.c chmod 'u=rw,g=r,o=r' \c\p\d\i\r\.\c set `sum \c\p\d\i\r\.\c` sum=$1 case $sum in 42315) :;; *) echo 'Bad sum in '\c\p\d\i\r\.\c >&2 esac echo Extracting \c\t\i\m\e\.\c sed 's/^X//' > \c\t\i\m\e\.\c << '+ END-OF-FILE '\c\t\i\m\e\.\c Xstruct tm { X int tm_sec; X int tm_min; X int tm_hour; X int tm_mday; X int tm_mon; X int tm_year; X int tm_wday; X int tm_yday; X int tm_isdst; X}; X Xstruct timeb { X long time; X unsigned short millitm; X short timezone; X short dstflag; X}; X Xextern struct tm *localtime(); Xextern char *asctime(); X Xchar *ctime(clock) X long *clock; X{ X return asctime(localtime(clock)); X} X Xstatic int monthsize[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; X X#define SECS_DAY (24*60L*60L) X#define YEARSIZE(year) ((year) % 4 ? 365 : 366) X Xstruct tm * Xgmtime(clock) X long *clock; X{ X long cl = *clock; X long dayclock, dayno; X static struct tm tm_buf; X register struct tm *pbuf = &tm_buf; X register int *months = monthsize; X int year = 1970; X X dayclock = cl % SECS_DAY; X dayno = cl / SECS_DAY; X X pbuf->tm_sec = dayclock % 60; X pbuf->tm_min = (dayclock % 3600) / 60; X pbuf->tm_hour = dayclock / 3600; X pbuf->tm_wday = (dayno + 4) % 7; /* day 0 was a thursday */ X while (dayno >= YEARSIZE(year)) { X dayno -= YEARSIZE(year); X year++; X } X pbuf->tm_year = year - 1900; X pbuf->tm_yday = dayno; X pbuf->tm_isdst = 0; X if (YEARSIZE(year) == 366) monthsize[1] = 29; X while (dayno - *months >= 0) dayno -= *months++; X pbuf->tm_mday = dayno + 1; X pbuf->tm_mon = months - monthsize; X monthsize[1] = 28; X return pbuf; X} X X#define FIRSTSUNDAY(t) (((t)->tm_yday - (t)->tm_wday + 420) % 7) X#define SUNDAY(day, t) ((day) < 58 ? \ X ((day) < FIRSTSUNDAY(t) ? FIRSTSUNDAY(t) : Xstatic int Xlast_sunday(d, t) X register int d; X register struct tm *t; X{ X int first = FIRSTSUNDAY(t); X X if (d >= 58 && YEARSIZE(t->tm_year)) d++; X if (d < first) return first; X return d - (d - first) % 7; X} X Xextern struct tm *gmtime(); X Xstruct tm * Xlocaltime(clock) X long *clock; X{ X register struct tm *gmt; X long cl; X int begindst, enddst; X extern int __daylight; X extern long __timezone; X X tzset(); X cl = *clock - __timezone; X gmt = gmtime(&cl); X if (__daylight) { X /* daylight saving time. X Unfortunately, rules differ for different countries. X Implemented here are heuristics that got it right X in Holland, over the last couple of years. X Of course, there is no algorithm. It is all X politics ... X */ X begindst = last_sunday(89, gmt); /* last Sun before Apr */ X enddst = last_sunday(272, gmt); /* last Sun in Sep */ X if ((gmt->tm_yday>begindst || X (gmt->tm_yday==begindst && gmt->tm_hour>=2)) && X (gmt->tm_yday<enddst || X (gmt->tm_yday==enddst && gmt->tm_hour<3))) { X /* it all happens between 2 and 3 */ X cl += 1*60*60; X gmt = gmtime(&cl); X gmt->tm_isdst++; X } X } X return gmt; X} X#ifdef BSD4_2 X#else X#ifndef USG X#endif X#endif X X#ifdef USG Xlong timezone = -1 * 60; Xint daylight = 1; Xchar *tzname[] = {"MET", "MDT",}; X#endif X Xlong __timezone = -1 * 60; Xint __daylight = 1; Xchar *__tzname[] = {"MET", "MDT", }; X Xtzset() X{ X#ifdef BSD4_2 X struct timeval tval; X struct timezone tzon; X X gettimeofday(&tval, &tzon); X __timezone = tzon.tz_minuteswest * 60L; X __daylight = tzon.tz_dsttime; X#else X#ifndef USG X struct timeb time; X X ftime(&time); X __timezone = time.timezone*60L; X __daylight = time.dstflag; X#endif X#endif X X { X extern char *getenv(); X register char *p = getenv("TZ"); X X if (p && *p) { X register int n = 0; X int sign = 1; X X strncpy(__tzname[0], p, 3); X p += 3; X if (*(p += 3) == '-') { X sign = -1; X p++; X } X X while(*p >= '0' && *p <= '9') X n = 10 * n + (*p++ - '0'); X n *= sign; X __timezone = ((long)(n * 60)) * 60; X __daylight = (*p != '\0'); X strncpy(__tzname[1], p, 3); X } X } X#ifdef USG X timezone = __timezone; X daylight = __daylight; X tzname[0] = __tzname[0]; X tzname[1] = __tzname[1]; X#endif X} + END-OF-FILE ctime.c chmod 'u=rw,g=r,o=r' \c\t\i\m\e\.\c set `sum \c\t\i\m\e\.\c` sum=$1 case $sum in 38880) :;; *) echo 'Bad sum in '\c\t\i\m\e\.\c >&2 esac echo Extracting \d\i\f\f\.\c sed 's/^X//' > \d\i\f\f\.\c << '+ END-OF-FILE '\d\i\f\f\.\c X/* diff - print differences between 2 files Author: Erik Baalbergen */ X X/* Poor man's implementation of diff(1) X - no options available X - may give more output than other diffs, due to the straight-forward algorithm X - runs out of memory if the differing chunks become too large X - input line length should not exceed LINELEN; longer lines are truncated, X while only the first LINELEN characters are compared X X Please report bugs and suggestions to erikb@cs.vu.nl X*/ X#include "stdio.h" XFILE *fopen(); X X#define LINELEN 128 X Xchar *prog; Xint diffs = 0; X Xmain(argc, argv) X char **argv; X{ X FILE *fp1 = NULL, *fp2 = NULL; X X prog = *argv++; X if (argc != 3) X fatal("use: %s file1 file2", prog); X if (strcmp(argv[0], "-") == 0) X fp1 = stdin; X else X if (strcmp(argv[1], "-") == 0) X fp2 = stdin; X if (fp1 == NULL && (fp1 = fopen(argv[0], "r")) == NULL) X fatal("can't read %s", argv[0]); X if (fp2 == NULL && (fp2 = fopen(argv[1], "r")) == NULL) X fatal("can't read %s", argv[1]); X diff(fp1, fp2); X exit(diffs > 0); X} X Xfatal(fmt, s) X char *fmt, *s; X{ X fprintf(stderr, "%s: ", prog); X fprintf(stderr, fmt, s); X fprintf(stderr, "\n"); X exit(2); X} X X/* the line module */ Xchar *malloc(); Xchar *fgets(); X Xstruct line { X struct line *l_next; X char l_text[LINELEN + 2]; X}; X Xstruct line *freelist = 0; X Xstruct line * Xnew_line() X{ X register struct line *l; X X if (l = freelist) X freelist = freelist->l_next; X else X if ((l = (struct line *)malloc(sizeof(struct line))) == 0) X fatal("out of memory"); X return l; X} X Xfree_line(l) X register struct line *l; X{ X l->l_next = freelist; X freelist = l; X} X X#define equal_line(l1, l2) (strcmp((l1)->l_text, (l2)->l_text) == 0) X Xint equal_3(l1, l2) X struct line *l1, *l2; X{ X register int i; X X for (i=0; i<3 && l1 && l2; ++i, l1=l1->l_next, l2=l2->l_next) { X if (!equal_line(l1, l2)) X return 0; X } X return (i==3); X} X Xstruct line * Xread_line(fp) X FILE *fp; X{ X register struct line *l = new_line(); X register char *p; X register int c; X X (p = &(l->l_text[LINELEN]))[1] = '\377'; X if (fgets(l->l_text, LINELEN + 2, fp) == NULL) { X free_line(l); X return 0; X } X if ((p[1] & 0377) != '\377' && *p != '\n') { X while ((c = fgetc(fp)) != '\n' && c != EOF) {} X *p++ = '\n'; X *p = '\0'; X } X l->l_next = 0; X return l; X} X X/* file window handler */ Xstruct f { X struct line *f_bwin, *f_ewin; X struct line *f_aside; X int f_linecnt; /* line number in file of last advanced line */ X FILE *f_fp; X}; X Xadvance(f) X register struct f *f; X{ X register struct line *l; X X if (l = f->f_bwin) { X if (f->f_ewin == l) X f->f_bwin = f->f_ewin = 0; X else X f->f_bwin = l->l_next; X free_line(l); X (f->f_linecnt)++; X } X} X Xaside(f, l) X struct f *f; X struct line *l; X{ X register struct line *ll; X X if (ll = l->l_next) { X while (ll->l_next) X ll = ll->l_next; X ll->l_next = f->f_aside; X f->f_aside = l->l_next; X l->l_next = 0; X f->f_ewin = l; X } X} X Xstruct line * Xnext(f) X register struct f *f; X{ X register struct line *l; X X if (l = f->f_aside) { X f->f_aside = l->l_next; X l->l_next = 0; X } X else X l = read_line(f->f_fp); X if (l) { X if (f->f_bwin == 0) X f->f_bwin = f->f_ewin = l; X else { X f->f_ewin->l_next = l; X f->f_ewin = l; X } X } X return l; X} X Xinit_f(f, fp) X register struct f *f; X FILE *fp; X{ X f->f_bwin = f->f_ewin = f->f_aside = 0; X f->f_linecnt = 0; X f->f_fp = fp; X} X Xupdate(f, s) X register struct f *f; X char *s; X{ X while (f->f_bwin && f->f_bwin != f->f_ewin) { X printf("%s%s", s, f->f_bwin->l_text); X advance(f); X } X} X X/* diff procedure */ Xdiff(fp1, fp2) X FILE *fp1, *fp2; X{ X struct f f1, f2; X struct line *l1, *s1, *b1, *l2, *s2, *b2; X register struct line *ll; X X init_f(&f1, fp1); X init_f(&f2, fp2); X l1 = next(&f1); X l2 = next(&f2); X while (l1 && l2) { X if (equal_line(l1, l2)) { Xequal: X advance(&f1); X advance(&f2); X l1 = next(&f1); X l2 = next(&f2); X continue; X } X s1 = b1 = l1; X s2 = b2 = l2; X /* read several more lines */ X next(&f1); next(&f1); X next(&f2); next(&f2); X /* start searching */ Xsearch: X if ((l2 = next(&f2)) == 0) X continue; X ll = s1; X b2 = b2->l_next; X do { X if (equal_3(ll, b2)) { X aside(&f1, ll); X aside(&f2, b2); X differ(&f1, &f2); X goto equal; X } X } while (ll = ll->l_next); X if ((l1 = next(&f1)) == 0) X continue; X ll = s2; X b1 = b1->l_next; X do { X if (equal_3(ll, b1)) { X aside(&f2, ll); X aside(&f1, b1); X differ(&f1, &f2); X goto equal; X } X } while (ll = ll->l_next); X goto search; X } X /* one of the files reached EOF */ X if (l1) /* eof on 2 */ X while (next(&f1)) {} X if (l2) X while (next(&f2)) {} X f1.f_ewin = 0; X f2.f_ewin = 0; X differ(&f1, &f2); X} X Xdiffer(f1, f2) X register struct f *f1, *f2; X{ X int cnt1 = f1->f_linecnt, len1 = wlen(f1), cnt2 = f2->f_linecnt, X len2 = wlen(f2); X X if ((len1 = wlen(f1)) || (len2 = wlen(f2))) { X if (len1 == 0) { X printf("%da", cnt1); X range(cnt2 + 1, cnt2 + len2); X } X else X if (len2 == 0) { X range(cnt1 + 1, cnt1 + len1); X printf("d%d", cnt2); X } X else { X range(cnt1 + 1, cnt1 + len1); X putchar('c'); X range(cnt2 + 1, cnt2 + len2); X } X putchar('\n'); X if (len1) X update(f1, "< "); X if (len1 && len2) X printf("---\n"); X if (len2) X update(f2, "> "); X diffs++; X } X} X Xwlen(f) X struct f *f; X{ X register cnt = 0; X register struct line *l = f->f_bwin, *e = f->f_ewin; X X while (l && l != e) { X cnt++; X l = l->l_next; X } X return cnt; X} X Xrange(a, b) X{ X printf(((a == b) ? "%d" : "%d,%d"), a, b); X} + END-OF-FILE diff.c chmod 'u=rw,g=r,o=r' \d\i\f\f\.\c set `sum \d\i\f\f\.\c` sum=$1 case $sum in 55356) :;; *) echo 'Bad sum in '\d\i\f\f\.\c >&2 esac echo Extracting \f\d\i\s\k\.\c sed 's/^X//' > \f\d\i\s\k\.\c << '+ END-OF-FILE '\f\d\i\s\k\.\c X/* fdisk - partition a hard disk Author: Jakob Schripsema */ X X/* X * First run the DOS utilities FDISK and FORMAT. FDISK X * puts the boot code in sector 0. X * Then run fdisk X * X * fdisk /dev/hdx (MINIX) X * fdisk x: (DOS) X * X * Compiling X * X * cc -o fdisk -DUNIX fdisk.c (MINIX) X * cl -DDOS fdisk.c (DOS with MS C compiler) X */ X X#include "stdio.h" X#define UNIX /* for MINIX */ X X#ifdef DOS X#include <dos.h> X#endif X X/* X * Constants X */ X X#define NHEAD 4 /* # heads */ X#define NSEC 17 /* sectors / track */ X#define SECSIZE 512 /* sector size */ X#define OK 0 X#define ERR 1 X#define TABLEOFFSET 0x1be /* offset in boot sector*/ X/* X * Description of entry in partition table X */ X Xstruct part_entry { X char bootind; /* boot indicator 0/0x80 */ X char start_head; /* head value for first sector */ X char start_sec; /* sector value for first sector*/ X char start_cyl; /* track value for first sector */ X char sysind; /* system indicator 00=?? 01=DOS*/ X char last_head; /* head value for last sector */ X char last_sec; /* sector value for last sector */ X char last_cyl; /* track value for last sector */ X long lowsec; /* logical first sector */ X long size; /* size of partion in sectors */ X}; X X/* X * Globals X */ X Xchar secbuf[SECSIZE]; Xchar *devname; Xchar *dosstr = " DOS "; Xchar *ndosstr = "Non-DOS"; X X#ifdef DOS Xunion REGS regs; Xstruct SREGS sregs; Xint drivenum; X#endif X X#ifdef UNIX Xint devfd; X#endif X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X char ch; X X /* init */ X X if (argc != 2) { X printf("Usage: fdisk /dev/hdx\n"); X exit(1); X } X X devname = argv[1]; X getboot(secbuf); /* get boot sector */ X X do { X dpl_partitions(); X print_menu(); X ch = get_a_char(); X putchar('\n'); X switch (ch) { X case 'c' : X change_table(); X break; X case 'w' : X if (chk_table() == OK) { X putboot(secbuf); X exit(0); X } X break; X case 'l' : X load_from_file(); X break; X case 's' : X save_to_file(); X break; X case 'p' : X dump_table(); X break; X case 'q' : X exit(0); X default : X printf(" %c ????\n",ch); X } X } X while (1); X} X X/* X * Read boot sector X */ X X#ifdef DOS X Xgetboot(buffer) Xchar *buffer; X{ X segread(&sregs); /* get ds */ X X if (devname[1] != ':') { X printf("Invalid drive %s\n",devname); X exit(1); X } X X if (*devname >= 'a') X *devname += 'A' - 'a'; X drivenum = (*devname - 'C') & 0xff; X if (drivenum < 0 || drivenum > 7) { X printf("Funny drive number %d\n",drivenum); X exit(1); X } X regs.x.ax = 0x201; /* read 1 sectors */ X regs.h.ch = 0; /* track */ X regs.h.cl = 1; /* first sector = 1 */ X regs.h.dh = 0; /* head = 0 */ X regs.h.dl = 0x80+drivenum;/* drive = 0 */ X sregs.es = sregs.ds; /* buffer address */ X regs.x.bx = (int)secbuf; X X int86x(0x13,®s,®s,&sregs); X if (regs.x.cflag) X { X printf("Cannot read boot sector\n"); X exit(1); X } X} X#endif X X#ifdef UNIX X Xgetboot(buffer) Xchar *buffer; X{ X devfd = open(devname,2); X if (devfd < 0) { X printf("Cannot open device %s\n",devname); X exit(1); X } X if (read(devfd,buffer,SECSIZE) != SECSIZE) { X printf("Cannot read boot sector\n"); X exit(2); X } X} X#endif X X/* X * Write boot sector X */ X X#ifdef DOS X Xputboot(buffer) Xchar *buffer; X{ X regs.x.ax = 0x301; /* read 1 sectors */ X regs.h.ch = 0; /* track */ X regs.h.cl = 1; /* first sector = 1 */ X regs.h.dh = 0; /* head = 0 */ X regs.h.dl = 0x80+drivenum;/* drive = 0 */ X sregs.es = sregs.ds; /* buffer address */ X regs.x.bx = (int)secbuf; X X int86x(0x13,®s,®s,&sregs); X if (regs.x.cflag) X { X printf("Cannot write boot sector\n"); X exit(1); X } X} X#endif X X#ifdef UNIX X Xputboot(buffer) Xchar *buffer; X{ X int r; X X if (lseek(devfd,0L,0) < 0) { X printf("Seek error during write\n"); X exit(1); X } X if (write(devfd,buffer,SECSIZE) != SECSIZE) { X printf("Write error\n"); X exit(1); X } X sync(); X} X#endif X X/* X * Load buffer from file X */ X Xload_from_file() X{ X char file[80]; X int fd; X X printf("Enter file name: "); X gets(file); X#ifdef UNIX X fd = open(file,0); X#endif X#ifdef DOS X fd = open(file,0x8000); X#endif X if (fd < 0) { X fprintf(stderr,"Cannot load from %s\n",file); X exit(1); X } X if (read(fd,secbuf,SECSIZE) != SECSIZE) { X fprintf(stderr,"Read error\n"); X exit(1); X } X close(fd); X} X X/* X * Save to file X */ X Xsave_to_file() X{ X char file[80]; X int fd; X X printf("Enter file name: "); X gets(file); X#ifdef UNIX X fd = creat(file,0644); X#endif X#ifdef DOS X fd = creat(file,0644); X if (fd < 0) { X fprintf(stderr,"Cannot creat %s\n",file); X exit(1); X } X close(fd); X fd = open(file,0x8001); X#endif X if (fd < 0) { X fprintf(stderr,"Cannot save to %s\n",file); X exit(1); X } X if (write(fd,secbuf,SECSIZE) != SECSIZE) { X fprintf(stderr,"Write error\n"); X exit(1); X } X close(fd); X} X X/* X * Dump partition table X */ X Xdump_table() X{ X struct part_entry *pe; X int i; X X pe = (struct part_entry *)&secbuf[TABLEOFFSET]; X printf("\n --first--- ---last---\n"); X printf("Prt ac hd sec cyl sys hd sec cyl low size\n"); X for (i = 1 ; i < 5 ; i++) { X printf(" %x %2x %x %2x %2x %2x %x %2x %2x %6D %9D\n", X i, X pe->bootind & 0xff, X pe->start_head & 0xff, X pe->start_sec & 0xff, X pe->start_cyl & 0xff, X pe->sysind & 0xff, X pe->last_head & 0xff, X pe->last_sec & 0xff, X pe->last_cyl & 0xff, X pe->lowsec, X pe->size); X pe++; X } X} X/* X * Display partition table X */ X Xdpl_partitions() X{ X struct part_entry *pe; X int i; X X printf("\nPartition Type Begin End Active\n"); X pe = (struct part_entry *)&secbuf[TABLEOFFSET]; X for (i = 1 ; i <= 4 ; i++) { X dpl_entry(i,pe); X pe++; X } X} X X/* X * Display an entry X */ X Xdpl_entry(number,entry) Xint number; Xstruct part_entry *entry; X{ X int low_cyl,high_cyl,temp; X char *typestring; X char active; X X if (entry->sysind == 0x01) X typestring = dosstr; X else X typestring = ndosstr; X printf("%5d %s ",number,typestring); X temp = entry->start_sec & 0xc0; X low_cyl = (entry->start_cyl & 0xff) + (temp << 2); X temp = entry->last_sec & 0xc0; X high_cyl = (entry->last_cyl & 0xff) + (temp << 2); X printf("%4d %4d",low_cyl,high_cyl); X if ((entry->bootind & 0xff) == 0x80) X active = 'A'; X else X active = 'N'; X printf(" %c\n",active); X} X X/* X * Check partition table X */ X Xchk_table() X{ X struct part_entry *pe; X int i; X int active; X long limit; X X pe = (struct part_entry *)&secbuf[TABLEOFFSET]; X limit = 0L; X active = 0; X for (i = 1 ; i < 5 ; i++) { X if (pe->size == 0L) X return(OK); X if (pe->lowsec <= limit) { X printf("Overlap between part. %d and %d\n",i,i-1); X return(ERR); X } X limit = pe->lowsec + pe->size - 1L; X if (pe->bootind == 0x80) X active++; X pe++; X } X if (active > 1) { X printf("%d active partitions\n",active); X return(ERR); X } X return(OK); X} X/* X * Check entry X * head/sector/track info must match logical sector number X * Used to check 'foreign' partition table during debugging X */ X Xchk_entry(entry) Xstruct part_entry *entry; X{ X char head; X char sector; X char track; X X sec_to_hst(entry->lowsec,&head,§or,&track); X if ( (head != entry->start_head) || X (sector != entry->start_sec) || X (track != entry->start_cyl)) X return(ERR); X sec_to_hst(entry->lowsec + entry->size - 1L,&head,§or,&track); X if ( (head != entry->last_head) || X (sector != entry->last_sec) || X (track != entry->last_cyl)) X return(ERR); X return(OK); X} X X/* X * Convert a logical sector number to X * head / sector / track X */ X Xsec_to_hst(logsec,hd,sec,cyl) Xlong logsec; Xchar *hd,*sec,*cyl; X{ X int bigcyl; X X bigcyl = logsec / (NHEAD * NSEC); X *sec = (logsec % NSEC) + 1 + ((bigcyl >> 2) & 0xc0); X *cyl = bigcyl & 0xff; X *hd = (logsec % (NHEAD * NSEC)) / NSEC; X} X X/* X * change partition table X */ X Xchange_table() X{ X struct part_entry *pe; X int i,temp,low_cyl,high_cyl; X char ch; X X pe = (struct part_entry *)&secbuf[TABLEOFFSET]; X for (i = 1 ; i <= 4 ; i++) { X temp = pe->start_sec & 0xc0; X low_cyl = (pe->start_cyl & 0xff) + (temp << 2); X temp = pe->last_sec & 0xc0; X high_cyl = (pe->last_cyl & 0xff) + (temp << 2); X printf("Partition %d from %d to %d. Change? (y/n) ", X i,low_cyl,high_cyl); X ch = get_a_char(); X if (ch == 'y' || ch == 'Y') X get_partition(pe); X pe++; X } X putchar('\n'); X} X X/* X * Get partition info : first & last cylinder X */ X Xget_partition(entry) Xstruct part_entry *entry; X{ X char buf[80]; X int first,last; X long low,high; X char ch; X X printf(" Enter first cylinder: "); X gets(buf); X sscanf(buf,"%d",&first); X printf(" Enter last cylinder: "); X gets(buf); X sscanf(buf,"%d",&last);; X if (first == 0 && last == 0) { X entry->bootind = 0; X entry->start_head = 0; X entry->start_sec = 0; X entry->start_cyl = 0; X entry->sysind = 0; X entry->last_head = 0; X entry->last_sec = 0; X entry->last_cyl = 0; X entry->lowsec = 0L; X entry->size = 0L ; X return; X } X low = first & 0xffff; X low = low * NSEC * NHEAD; X if (low == 0) X low = 1; /* sec0 is master boot record */ X high = last & 0xffff; X high = (high + 1)*NSEC*NHEAD - 1; X entry->lowsec = low; X entry->size = high - low + 1; X sec_to_hst(low, X &entry->start_head, X &entry->start_sec, X &entry->start_cyl); X sec_to_hst(high, X &entry->last_head, X &entry->last_sec, X &entry->last_cyl); X printf(" DOS partition? (y/n) "); X ch = get_a_char(); X if (ch == 'y' || ch == 'Y') X entry->sysind = 1; X else X entry->sysind = 0; X printf(" Active partition? (y/n) "); X ch = get_a_char(); X if (ch == 'y' || ch == 'Y') X entry->bootind = 0x80; X else X entry->bootind = 0; X} X X/* X * Read 1 character and discard rest of line X */ X Xget_a_char() X{ X char ch; X X ch = getchar(); X if (ch != '\n') X while (getchar() != '\n'); X return(ch); X} X Xprint_menu() X{ X printf("\nType a command letter, then a carriage return:\n"); X printf(" c - change a partition\n"); X printf(" w - write changed partition table back to disk and exit\n"); X printf(" q - quit without making any changes\n"); X printf(" s - save boot block (including partition table) on a file\n"); X printf(" l - load boot block (including partition table) from a file\n"); X printf(" p - print partition table\n\n"); X} + END-OF-FILE fdisk.c chmod 'u=rw,g=r,o=r' \f\d\i\s\k\.\c set `sum \f\d\i\s\k\.\c` sum=$1 case $sum in 48175) :;; *) echo 'Bad sum in '\f\d\i\s\k\.\c >&2 esac echo Extracting \f\i\n\d\.\c sed 's/^X//' > \f\i\n\d\.\c << '+ END-OF-FILE '\f\i\n\d\.\c X/* find - look for files satisfying a predicat Author: Erik Baalbergen */ X X/* X *** Check the switches in the SWITCHES section below. *** X X Differences from UNIX version 7 find(1): X * -name: no name allowed; only uid X e.g. find all core files: "find . -name core -a -print" X X The "-atime" may not work well on Minix. X Please report bugs and suggestions to erikb@cs.vu.nl X*/ X X#include "stdio.h" X X/*######################## SWITCHES ##############################*/ X#include "stat.h" X#define SHELL "/usr/bin/sh" X X#define PLEN 256 /* maximum path length; overflows are not detected */ X#define DIRSIZ 16 /* size of a directory entry */ X#define MAXARG 256 /* maximum length for an argv */ X#define NPATHS 256 /* maximum number of paths in path-list */ X#define BSIZE 1024 /* bytes per block */ X X/*######################## DEFINITIONS ##############################*/ X#define SECS_PER_DAY (24L * 60L * 60L) /* check your planet */ X Xstruct exec { X int e_cnt; X char *e_vec[MAXARG]; X}; X X#define OP_NAME 1 X#define OP_PERM 2 X#define OP_TYPE 3 X#define OP_LINKS 4 X#define OP_USER 5 X#define OP_GROUP 6 X#define OP_SIZE 7 X#define OP_INUM 8 X#define OP_ATIME 9 X#define OP_MTIME 10 X#define OP_EXEC 11 X#define OP_OK 12 X#define OP_PRINT 13 X#define OP_NEWER 14 X#define OP_AND 15 X#define OP_OR 16 X Xstruct oper { X char *op_str; X int op_val; X} ops[] = { X {"name", OP_NAME}, X {"perm", OP_PERM}, X {"type", OP_TYPE}, X {"links", OP_LINKS}, X {"user", OP_USER}, X {"group", OP_GROUP}, X {"size", OP_SIZE}, X {"inum", OP_INUM}, X {"atime", OP_ATIME}, X {"mtime", OP_MTIME}, X {"exec", OP_EXEC}, X {"ok", OP_OK}, X {"print", OP_PRINT}, X {"newer", OP_NEWER}, X {"a", OP_AND}, X {"o", OP_OR}, X {0, 0} X}; X X#define EOI -1 X#define NONE 0 X#define LPAR 20 X#define RPAR 21 X#define NOT 22 X Xchar *prog, *strcpy(), *Malloc(), *find_bin(); X Xstruct node { X int n_type; /* any OP_ or NOT */ X union { X char *n_str; X struct { X long n_val; X int n_sign; X } n_int; X struct exec *n_exec; X struct { X struct node *n_left, *n_right; X } n_opnd; X } n_info; X}; Xstruct node *expr(); X Xchar **ipp; Xint tty; /* fd for /dev/tty when using -ok */ Xlong current_time; X Xchar * XMalloc(n) X{ X char *malloc(), *m; X X if ((m = malloc(n)) == 0) X fatal("out of memory", ""); X return m; X} X Xchar * XSalloc(s) X char *s; X{ X return strcpy(Malloc(strlen(s) + 1), s); X} X Xmain(argc, argv) X char *argv[]; X{ X char *pathlist[NPATHS]; X int pathcnt = 0; X register i; X struct node *pred; X X prog = *argv++; X while (--argc > 0 && lex(*argv) == NONE) X pathlist[pathcnt++] = *argv++; X if (pathcnt == 0 || argc == 0) X fatal("Usage: path-list predicate-list", ""); X ipp = argv; X time(¤t_time); X pred = expr(lex(*ipp)); X if (lex(*++ipp) != EOI) X fatal("syntax error: garbage at end of predicate", ""); X for (i = 0; i < pathcnt; i++) X find(pathlist[i], pred, ""); X exit(0); X} X Xfind(path, pred, last) X char *path, *last; X struct node *pred; X{ X char spath[PLEN], ent[DIRSIZ + 1]; X struct stat st; X register char *send = spath; X FILE *fp, *fopen(); X X if (path[1] == '\0' && *path == '/') { X *send++ = '/'; X *send = '\0'; X } X else X while (*send++ = *path++) {} X if (stat(spath, &st) == -1) X nonfatal("can't get status of ", spath); X else { X (void) check(spath, &st, pred, last); X if ((st.st_mode & S_IFMT) == S_IFDIR) { X if ((fp = fopen(spath, "r")) == NULL) { X nonfatal("can't read directory ", spath); X return; X } X send[-1] = '/'; X ent[DIRSIZ] = '\0'; X while (fread(ent, DIRSIZ, 1, fp) == 1) { X if (!((*ent == '\0' && ent[1] == '\0') X || (ent[2] == '.') && X (ent[3] == '\0' X || (ent[3] == '.' && ent[4] == '\0')) X )) { X strcpy(send, ent + 2); X find(spath, pred, ent + 2); X } X } X fclose(fp); X } X } X} X Xcheck(path, st, n, last) X char *path, *last; X register struct stat *st; X register struct node *n; X{ X switch (n->n_type) { X case OP_AND: X return check(path, st, n->n_info.n_opnd.n_left, last) && X check(path, st, n->n_info.n_opnd.n_right, last); X case OP_OR: X return check(path, st, n->n_info.n_opnd.n_left, last) || X check(path, st, n->n_info.n_opnd.n_right, last); X case NOT: X return !check(path, st, n->n_info.n_opnd.n_left, last); X case OP_NAME: X return smatch(last, n->n_info.n_str); X case OP_PERM: X if (n->n_info.n_int.n_sign < 0) X return st->st_mode == (int) n->n_info.n_int.n_val; X return (st->st_mode & 0777) == (int) n->n_info.n_int.n_val; X case OP_NEWER: X return st->st_mtime > n->n_info.n_int.n_val; X case OP_TYPE: X return (st->st_mode & S_IFMT) == n->n_info.n_int.n_val; X case OP_LINKS: X return ichk((long)(st->st_nlink), n); X case OP_USER: X return st->st_uid == n->n_info.n_int.n_val; X case OP_GROUP: X return st->st_gid == n->n_info.n_int.n_val; X case OP_SIZE: X return ichk((st->st_size == 0) ? 0L : X ((st->st_size - 1) / BSIZE + 1), n); X case OP_INUM: X return ichk((long)(st->st_ino), n); X case OP_ATIME: X return ichk(st->st_atime, n); X case OP_MTIME: X return ichk(st->st_mtime, n); X case OP_EXEC: X case OP_OK: X return execute(n->n_type, n->n_info.n_exec, path); X case OP_PRINT: X prints("%s\n", path); X return 1; X } X fatal("ILLEGAL NODE", ""); X} X Xichk(val, n) X long val; X struct node *n; X{ X switch (n->n_info.n_int.n_sign) { X case 0: X return val == n->n_info.n_int.n_val; X case 1: X return val > n->n_info.n_int.n_val; X case -1: X return val < n->n_info.n_int.n_val; X } X fatal("internal: bad n_sign", ""); X} X Xlex(str) X char *str; X{ X if (str == 0) X return EOI; X if (*str == '-') { X register struct oper *op; X X str++; X for (op = ops; op->op_str; op++) X if (strcmp(str, op->op_str) == 0) X break; X return op->op_val; X } X if (str[1] == 0) { X switch(*str) { X case '(': X return LPAR; X case ')': X return RPAR; X case '!': X return NOT; X } X } X return NONE; X} X Xstruct node * Xnewnode(t) X{ X struct node *n = (struct node*) Malloc(sizeof(struct node)); X X n->n_type = t; X return n; X} X X/*########################### PARSER ###################################*/ X/* grammar: X expr : primary | primary OR expr; X primary : secondary | secondary AND primary | secondary primary; X secondary : NOT secondary | LPAR expr RPAR | simple; X simple : -OP args... X*/ Xstruct node *expr(), *primary(), *secondary(), *simple(); X Xnumber(str, base, pl, ps) X char *str; X long *pl; X int *ps; X{ X int up = '0' + base - 1; X long val = 0; X X *ps = ((*str == '-' || *str == '+') ? ((*str++ == '-') ? -1 : 1) : 0); X while (*str >= '0' && *str <= up) X val = base * val + *str++ - '0'; X if (*str) X fatal("syntax error: illegal numeric value", ""); X *pl = val; X} X Xstruct node * Xexpr(t) X{ X struct node *nd, *p, *nd2; X X nd = primary(t); X if ((t = lex(*++ipp)) == OP_OR) { X nd2 = expr(lex(*++ipp)); X p = newnode(OP_OR); X p->n_info.n_opnd.n_left = nd; X p->n_info.n_opnd.n_right = nd2; X return p; X } X ipp--; X return nd; X} X Xstruct node * Xprimary(t) X{ X struct node *nd, *p, *nd2; X X nd = secondary(t); X if ((t = lex(*++ipp)) != OP_AND) { X ipp--; X if (t == EOI || t == RPAR || t == OP_OR) X return nd; X } X nd2 = primary(lex(*++ipp)); X p = newnode(OP_AND); X p->n_info.n_opnd.n_left = nd; X p->n_info.n_opnd.n_right = nd2; X return p; X} X Xstruct node * Xsecondary(t) X{ X struct node *n, *p; X X if (t == LPAR) { X n = expr(lex(*++ipp)); X if (lex(*++ipp) != RPAR) X fatal("syntax error, ) expected", ""); X return n; X } X if (t == NOT) { X n = secondary(lex(*++ipp)); X p = newnode(NOT); X p->n_info.n_opnd.n_left = n; X return p; X } X return simple(t); X} X Xcheckarg(arg) X char *arg; X{ X if (arg == 0) X fatal("syntax error, argument expected", ""); X} X Xstruct node * Xsimple(t) X{ X struct node *p = newnode(t); X struct exec *e; X struct stat est; X long l; X X switch (t) { X case OP_TYPE: X checkarg(*++ipp); X switch (**ipp) { X case 'b': X p->n_info.n_int.n_val = S_IFBLK; X break; X case 'c': X p->n_info.n_int.n_val = S_IFCHR; X break; X case 'd': X p->n_info.n_int.n_val = S_IFDIR; X break; X case 'f': X p->n_info.n_int.n_val = S_IFREG; X break; X default: X fatal("-type needs b, c, d or f", ""); X } X break; X case OP_LINKS: X case OP_USER: X case OP_GROUP: X case OP_SIZE: X case OP_INUM: X case OP_PERM: X checkarg(*++ipp); X number(*ipp, (t == OP_PERM) ? 8 : 10, &(p->n_info.n_int.n_val), X &(p->n_info.n_int.n_sign)); X break; X case OP_ATIME: X case OP_MTIME: X checkarg(*++ipp); X number(*ipp, 10, &l, &(p->n_info.n_int.n_sign)); X p->n_info.n_int.n_val = current_time - l * SECS_PER_DAY; X /* more than n days old means less than the absolute time */ X p->n_info.n_int.n_sign *= -1; X break; X case OP_EXEC: X case OP_OK: X checkarg(*++ipp); X e = (struct exec *)Malloc(sizeof(struct exec)); X e->e_cnt = 2; X e->e_vec[0] = SHELL; X p->n_info.n_exec = e; X while (*ipp) { X if (**ipp == ';' && (*ipp)[1] == '\0') { X e->e_vec[e->e_cnt] = 0; X break; X } X e->e_vec[(e->e_cnt)++] = X (**ipp == '{' && (*ipp)[1] == '}' X && (*ipp)[2] == '\0') ? (char *)(-1) : *ipp; X ipp++; X } X if (*ipp == 0) X fatal("-exec/-ok: ; missing", ""); X if ((e->e_vec[1] = find_bin(e->e_vec[2])) == 0) X fatal("can't find program ", e->e_vec[2]); X if (t == OP_OK) X if ((tty = open("/dev/tty", 2)) < 0) X fatal("can't open /dev/tty", ""); X break; X case OP_NEWER: X checkarg(*++ipp); X if (stat(*ipp, &est) == -1) X fatal("-newer: can't get status of ", *ipp); X p->n_info.n_int.n_val = est.st_mtime; X break; X case OP_NAME: X checkarg(*++ipp); X p->n_info.n_str = *ipp; X break; X case OP_PRINT: X break; X default: X fatal("syntax error, operator expected", ""); X } X return p; X} X X/*######################## DIAGNOSTICS ##############################*/ X Xnonfatal(s1, s2) X char *s1, *s2; X{ X std_err(prog); X std_err(": "); X std_err(s1); X std_err(s2); X std_err("\n"); X} X Xfatal(s1, s2) X char *s1, *s2; X{ X nonfatal(s1, s2); X exit(1); X} X X/*################### SMATCH #########################*/ X/* Don't try to understand the following one... */ Xsmatch(s, t) /* shell-like matching */ X char *s, *t; X{ X register n; X X if (*t == '\0') X return *s == '\0'; X if (*t == '*') { X ++t; X do X if (smatch(s,t)) X return 1; X while (*s++ != '\0'); X return 0; X } X if (*s == '\0') X return 0; X if (*t == '\\') X return (*s == *++t) ? smatch(++s, ++t) : 0; X if (*t == '?') X return smatch(++s, ++t); X if (*t == '[') { X while (*++t != ']') { X if (*t == '\\') X ++t; X if (*(t+1) != '-') X if (*t == *s) { X while (*++t != ']') X if (*t == '\\') X ++t; X return smatch(++s, ++t); X } X else X continue; X if (*(t+2) == ']') X return (*s == *t || *s == '-'); X n = (*(t+2) == '\\') ? 3 : 2; X if (*s >= *t && *s <= *(t+n)) { X while (*++t != ']') X if (*t == '\\') X ++t; X return smatch(++s, ++t); X } X t += n; X } X return 0; X } X return (*s == *t) ? smatch(++s, ++t) : 0; X} X X/*####################### EXECUTE ###########################*/ X/* do -exec or -ok */ X Xchar *epath = 0; X Xchar * Xgetpath() X{ X extern char **environ; X register char **e = environ; X X if (epath) /* retrieve PATH only once */ X return epath; X while (*e) { X if (strncmp("PATH=", *e, 5) == 0) { X return epath = *e + 5; X } X e++; X } X fatal("can't get PATH from environment", ""); X} X Xchar * Xfind_bin(s) X char *s; X{ X char *f, *l, buf[PLEN]; X X if (*s == '/') /* absolute path name */ X return (access(s, 1) == 0) ? s : 0; X l = f = getpath(); X for (;;) { X if (*l == ':' || *l == 0) { X if (l == f) { X if (access(s, 1) == 0) X return Salloc(s); X f++; X } X else { X register char *p = buf, *q = s; X X while (f != l) X *p++ = *f++; X f++; X *p++ = '/'; X while (*p++ = *q++) {} X if (access(buf, 1) == 0) X return Salloc(buf); X } X if (*l == 0) X break; X } X l++; X } X return 0; X} X Xexecute(op, e, path) X struct exec *e; X char *path; X{ X int s, pid; X char *argv[MAXARG]; X register char **p, **q; X X for (p = e->e_vec, q = argv; *p;) /* replace the {}s */ X if ((*q++ = *p++) == (char *)-1) X q[-1] = path; X *q = '\0'; X if (op == OP_OK) { X char answer[10]; X X for (p = &argv[2]; *p; p++) { X write(tty, *p, strlen(*p)); X write(tty, " ", 1); X } X write(tty, "? ", 2); X if (read(tty, answer, 10) < 2 || *answer != 'y') X return 0; X } X if ((pid = fork()) == -1) X fatal("can't fork", ""); X if (pid == 0) { X register i = 3; X X while (close(i++) == 0) {} /* wow!!! */ X execv(argv[1], &argv[2]); /* binary itself? */ X execv(argv[0], &argv[1]); /* shell command? */ X fatal("exec failure: ", argv[1]); /* none of them! */ X exit(127); X } X return wait(&s) == pid && s == 0; X} + END-OF-FILE find.c chmod 'u=rw,g=r,o=r' \f\i\n\d\.\c set `sum \f\i\n\d\.\c` sum=$1 case $sum in 24425) :;; *) echo 'Bad sum in '\f\i\n\d\.\c >&2 esac echo Extracting \m\o\r\e\.\c sed 's/^X//' > \m\o\r\e\.\c << '+ END-OF-FILE '\m\o\r\e\.\c X/* more - terminal pager Author: Brandon S. Allbery */ X X/* Pager commands: X * <space> display next page X * <return> scroll up 1 line X * q quit X*/ X X#define reverse() write(1, "\033z\160", 3) /* reverse video */ X#define normal() write(1, "\033z\7", 3) /* undo reverse() */ X#define clearln() write(1, "\r\033~0", 4) /* clear line */ X X#define LINES 23 /* lines/screen (- 1 to retain last line) */ X#define COLS 80 /* columns/line */ X#define TABSTOP 8 /* tabstop expansion */ X X#include <sgtty.h> X#include <signal.h> X Xextern int byebye(); Xextern char *index(); X Xint line = 0; /* current terminal line */ Xint col = 0; /* current terminal column */ Xint fd = -1; /* terminal file descriptor (/dev/tty) */ Xstruct sgttyb ttymode; /* and the terminal modes */ Xchar ibuf[1024]; /* input buffer */ Xchar obuf[1024]; /* output buffer */ Xint ibl = 0; /* chars in input buffer */ Xint ibc = 0; /* position in input buffer */ Xint obc = 0; /* position in output buffer (== chars in) */ Xint isrewind = 0; /* flag: ' command -- next input() rewind */ Xint isdone = 0; /* flag: return EOF next read even if not */ X Xmain(argc, argv) Xchar **argv; { X char ch; X int fd, arg; X X signal(SIGINT, byebye); X fd = 0; X cbreak(); X if (argc < 2) X while ((ch = input(fd)) != 0) X output(ch); X else X for (arg = 1; argv[arg] != (char *) 0; arg++) { X if ((fd = open(argv[arg], 0)) == -1) { X write(1, "more: cannot open ", 18); X write(1, argv[arg], strlen(argv[arg])); X write(1, "\n", 1); X nocbreak(); X exit(1); X } X while ((ch = input(fd)) != 0) X output(ch); X close(fd); X if (argv[arg + 1] != (char *) 0) { X oflush(); X if (isdone) { /* 'n' command */ X reverse(); X write(1, "*** Skipping to next file ***\n", 30); X normal(); X isdone = 0; X } X reverse(); X write(1, "--More-- (Next file: ", 21); X write(1, argv[arg + 1], strlen(argv[arg + 1])); X write(1, ")", 1); X normal(); X switch (wtch()) { X case ' ': X case '\'': X case 'n': X case 'N': X line = 0; X break; X case '\r': X case '\n': X line = LINES - 1; X break; X case 'q': X case 'Q': X clearln(); X byebye(); X } X clearln(); X } X } X oflush(); X byebye(); X} X Xinput(fd) { X if (isdone) { X ibl = 0; X ibc = 0; X return 0; X } X if (isrewind) { X lseek(fd, 0L, 0); X ibl = 0; X ibc = 0; X isrewind = 0; X } X if (ibc == ibl) { X ibc = 0; X if ((ibl = read(fd, ibuf, sizeof ibuf)) <= 0) X return 0; X } X return ibuf[ibc++]; X} X Xoutput(c) Xchar c; { X if (obc == sizeof obuf) { X lwrite(1, obuf, sizeof obuf); X obc = 0; X } X if (!isrewind) X obuf[obc++] = c; X} X Xoflush() { X if (!isdone) X lwrite(1, obuf, obc); X obc = 0; X} X Xlwrite(fd, buf, len) Xchar *buf; Xunsigned len; { X unsigned here, start; X char cmd; X X start = 0; X here = 0; X while (here != len) { X cmd = '\0'; X switch (buf[here++]) { X case '\n': X col = 0; X if (++line == LINES) { X write(fd, buf + start, here - start); X reverse(); X write(1, "--More--", 8); X normal(); X cmd = wtch(); X clearln(); X line = 0; X start = here; X } X break; X case '\r': X col = 0; X break; X case '\b': X if (col != 0) X col--; X else { X line--; X col = COLS - 1; X } X break; X case '\t': X do { X col++; X } while (col % TABSTOP != 0); X break; X default: X if (++col == COLS) { X col = 0; X if (++line == LINES) { X write(fd, buf + start, here - start); X reverse(); X write(1, "--More--", 8); X normal(); X cmd = wtch(); X clearln(); X line = 0; X start = here; X } X } X } X switch (cmd) { X case '\0': X break; X case ' ': X line = 0; X break; X case '\r': X case '\n': X line = LINES - 1; X break; X case 'q': X case 'Q': X byebye(); X case '\'': X isrewind = 1; X reverse(); X write(1, "*** Back ***\n", 13); X normal(); X return; X case 'n': X case 'N': X isdone = 1; X return; X default: X break; X } X } X if (here != start) X write(fd, buf + start, here - start); X} X Xwtch() { X char ch; X X do { X read(fd, &ch, 1); X } while (index(" \r\nqQ'nN", ch) == (char *) 0); X return ch; X} X Xcbreak() { X if (fd != -1) X return; X if ((fd = open("/dev/tty", 0)) == -1) { X write(2, "OOPS -- can't open /dev/tty\n", 28); X exit(1); X } X ioctl(fd, TIOCGETP, &ttymode); X ttymode.sg_flags |= CBREAK; X ttymode.sg_flags &= ~ECHO; X ioctl(fd, TIOCSETP, &ttymode); /* NB: add TIOCSETN! */ X} X Xnocbreak() { X if (fd == -1) X return; X ttymode.sg_flags &= ~CBREAK; X ttymode.sg_flags |= ECHO; X ioctl(fd, TIOCSETP, &ttymode); X close(fd); X fd = -1; X} X Xbyebye() { X nocbreak(); X exit(0); X} + END-OF-FILE more.c chmod 'u=rw,g=r,o=r' \m\o\r\e\.\c set `sum \m\o\r\e\.\c` sum=$1 case $sum in 58691) :;; *) echo 'Bad sum in '\m\o\r\e\.\c >&2 esac echo Extracting \p\o\p\e\n\.\c sed 's/^X//' > \p\o\p\e\n\.\c << '+ END-OF-FILE '\p\o\p\e\n\.\c X#include <stdio.h> X#include <signal.h> X Xstatic int pids[20]; X XFILE * Xpopen(command, type) X char *command, *type; X{ X int piped[2]; X int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2; X int pid; X X if (Xtype == 2 || X pipe(piped) < 0 || X (pid = fork()) < 0) return 0; X X if (pid == 0) { X /* child */ X register int *p; X X for (p = pids; p < &pids[20]; p++) { X if (*p) close(p - pids); X } X close(piped[Xtype]); X dup2(piped[!Xtype], !Xtype); X close(piped[!Xtype]); X execl("/bin/sh", "sh", "-c", command, (char *) 0); X _exit(127); /* like system() ??? */ X } X X pids[piped[Xtype]] = pid; X close(piped[!Xtype]); X return fdopen(piped[Xtype], type); X} X Xpclose(iop) X FILE *iop; X{ X int fd = fileno(iop); X int status, wret; X int (*intsave)() = signal(SIGINT, SIG_IGN); X int (*quitsave)() = signal(SIGQUIT, SIG_IGN); X X fclose(iop); X while ((wret = wait(&status)) != -1) { X if (wret == pids[fd]) break; X } X if (wret == -1) status = -1; X signal(SIGINT, intsave); X signal(SIGQUIT, quitsave); X pids[fd] = 0; X return status; X} + END-OF-FILE popen.c chmod 'u=rw,g=r,o=r' \p\o\p\e\n\.\c set `sum \p\o\p\e\n\.\c` sum=$1 case $sum in 19198) :;; *) echo 'Bad sum in '\p\o\p\e\n\.\c >&2 esac echo Extracting \p\r\i\n\t\e\n\v\.\c sed 's/^X//' > \p\r\i\n\t\e\n\v\.\c << '+ END-OF-FILE '\p\r\i\n\t\e\n\v\.\c X/* printenv - print the current environment Author: Richard Todd */ X Xmain () X{ X extern char **environ; X char **sptr; X for (sptr = environ ; *sptr ; ++sptr) { X prints("%s\n",*sptr); X } X} + END-OF-FILE printenv.c chmod 'u=rw,g=r,o=r' \p\r\i\n\t\e\n\v\.\c set `sum \p\r\i\n\t\e\n\v\.\c` sum=$1 case $sum in 25077) :;; *) echo 'Bad sum in '\p\r\i\n\t\e\n\v\.\c >&2 esac echo Extracting \p\u\t\s\.\c sed 's/^X//' > \p\u\t\s\.\c << '+ END-OF-FILE '\p\u\t\s\.\c X#include "stdio.h" X Xint puts(s) Xchar *s; X{ X char c; X X c = fputs(s,stdout); X putchar('\n'); X return(c); X} + END-OF-FILE puts.c chmod 'u=rw,g=r,o=r' \p\u\t\s\.\c set `sum \p\u\t\s\.\c` sum=$1 case $sum in 09591) :;; *) echo 'Bad sum in '\p\u\t\s\.\c >&2 esac echo Extracting \q\s\o\r\t\.\c sed 's/^X//' > \q\s\o\r\t\.\c << '+ END-OF-FILE '\q\s\o\r\t\.\c Xstatic qsort1(); Xstatic int (*qcompar)(); Xstatic qexchange(); Xstatic q3exchange(); X Xqsort(base, nel, width, compar) X char *base; X int (*compar)(); X{ X qcompar = compar; X qsort1(base, base + (nel - 1) * width, width); X} X Xstatic Xqsort1(a1, a2, width) X char *a1, *a2; X register int width; X{ X register char *left, *right; X register char *lefteq, *righteq; X int cmp; X X for (;;) { X if (a2 <= a1) return; X left = a1; X right = a2; X lefteq = righteq = a1 + width * (((a2-a1)+width)/(2*width)); X /* X Pick an element in the middle of the array. X We will collect the equals around it. X "lefteq" and "righteq" indicate the left and right X bounds of the equals respectively. X Smaller elements end up left of it, larger elements end X up right of it. X */ Xagain: X while (left < lefteq && (cmp = (*qcompar)(left, lefteq)) <= 0) { X if (cmp < 0) { X /* leave it where it is */ X left += width; X } X else { X /* equal, so exchange with the element to X the left of the "equal"-interval. X */ X lefteq -= width; X qexchange(left, lefteq, width); X } X } X while (right > righteq) { X if ((cmp = (*qcompar)(right, righteq)) < 0) { X /* smaller, should go to left part X */ X if (left < lefteq) { X /* yes, we had a larger one at the X left, so we can just exchange X */ X qexchange(left, right, width); X left += width; X right -= width; X goto again; X } X /* no more room at the left part, so we X move the "equal-interval" one place to the X right, and the smaller element to the X left of it. X This is best expressed as a three-way X exchange. X */ X righteq += width; X q3exchange(left, righteq, right, width); X lefteq += width; X left = lefteq; X } X else if (cmp == 0) { X /* equal, so exchange with the element to X the right of the "equal-interval" X */ X righteq += width; X qexchange(right, righteq, width); X } X else /* just leave it */ right -= width; X } X if (left < lefteq) { X /* larger element to the left, but no more room, X so move the "equal-interval" one place to the X left, and the larger element to the right X of it. X */ X lefteq -= width; X q3exchange(right, lefteq, left, width); X righteq -= width; X right = righteq; X goto again; X } X /* now sort the "smaller" part */ X qsort1(a1, lefteq - width, width); X /* and now the larger, saving a subroutine call X because of the for(;;) X */ X a1 = righteq + width; X } X /*NOTREACHED*/ X} X Xstatic Xqexchange(p, q, n) X register char *p, *q; X register int n; X{ X register int c; X X while (n-- > 0) { X c = *p; X *p++ = *q; X *q++ = c; X } X} X Xstatic Xq3exchange(p, q, r, n) X register char *p, *q, *r; X register int n; X{ X register int c; X X while (n-- > 0) { X c = *p; X *p++ = *r; X *r++ = *q; X *q++ = c; X } X} + END-OF-FILE qsort.c chmod 'u=rw,g=r,o=r' \q\s\o\r\t\.\c set `sum \q\s\o\r\t\.\c` sum=$1 case $sum in 12247) :;; *) echo 'Bad sum in '\q\s\o\r\t\.\c >&2 esac echo Extracting \s\y\s\t\e\m\.\c sed 's/^X//' > \s\y\s\t\e\m\.\c << '+ END-OF-FILE '\s\y\s\t\e\m\.\c X#include <stdio.h> X X#ifndef NIL X#define NIL 0 X#endif X X Xsystem( cmd ) Xchar *cmd; X{ X int retstat, procid, waitstat; X X if( (procid = fork()) == 0 ) X { X execl( "/bin/sh", "sh", "-c", cmd, NIL ); X exit( 127 ); X } X X while( (waitstat = wait(&retstat)) != procid && waitstat != -1 ) X ; X if (waitstat == -1) X retstat = -1; X X return( retstat ); X} + END-OF-FILE system.c chmod 'u=rw,g=r,o=r' \s\y\s\t\e\m\.\c set `sum \s\y\s\t\e\m\.\c` sum=$1 case $sum in 00456) :;; *) echo 'Bad sum in '\s\y\s\t\e\m\.\c >&2 esac exit 0