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