ast@cs.vu.nl (Andy Tanenbaum) (06/28/88)
Here are four important files: - commands/fix.c (slightly immune to Bitnet) - commands/stty.c (handles baudrate for RS232) - commands/cdiff.c (is included in 1.3) - lib/ioctl.c (needed by new stty.c) Please install all of these. Andy Tanenbaum (ast@cs.vu.nl) : This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'fix.c' sed 's/^X//' > 'fix.c' << '+ END-OF-FILE ''fix.c' X/* fix file difflist - update file from difflist Author: Erik Baalbergen */ X X X/* Notes: X * files old and old.patch are equal after the following commands X diff old new > difflist X patch old difflist > old.patch X * the diff output is assumed to be produced by my diff program. X * the difflist has the following form: X difflist ::= chunk* X chunk ::= append | delete | change ; X append ::= n1 'a' n2 [',' n3]? '\n' ['> ' line '\n'](n3 - n2 + 1) X delete ::= n1 [',' n2]? 'd' n3 '\n' ['< ' line '\n'](n2 - n1 + 1) X change ::= n1 [',' n2]? 'c' n3 [',' n4]? '\n' X ['< ' line '\n'](n2 - n1 + 1) X '---\n' X ['> ' line '\n'](n4 - n3 + 1) X where X - n[1234] is an unsigned integer X - "[pat](expr)" means "(expr) occurences of pat" X - "[pat]?" means "either pat or nothing" X * the information in the diff listing is checked against the file to which X it is applied; an error is printed if there is a conflict X*/ X X#include <stdio.h> X X#define IGNORE_WHITE_SPACE /* This makes it white space insensitive */ X X#ifdef IGNORE_WHITE_SPACE X#define strcmp strwcmp X#endif X Xextern char *fgets(); Xextern FILE *fopen(); X#define LINELEN 1024 X Xchar *prog = 0, X *processing=0; X Xchar * Xgetline(fp, b) X FILE *fp; X char *b; X{ X int slen; X if (fgets(b, LINELEN, fp) == NULL) X fatal("unexpected eof"); X X return b; X} X X#define copy(str) printf("%s", str) X Xmain(argc, argv) X char **argv; X{ X char cmd, *fl, *fd, obuf[LINELEN], nbuf[LINELEN]; X int o1, o2, n1, n2, here; X FILE *fpf, *fpd; X X prog = argv[0]; X processing = argv[1]; X if (argc != 3) X fatal("use: %s original-file diff-list-file", prog); X if ((fpf = fopen(argv[1], "r")) == NULL) X fatal("can't read %s", argv[1]); X if ((fpd = fopen(argv[2], "r")) == NULL) X fatal("can't read %s", argv[2]); X here = 0; X while (getcommand(fpd, &o1, &o2, &cmd, &n1, &n2)) { X while (here < o1 - 1) { X here++; X copy(getline(fpf, obuf)); X } X switch (cmd) { X case 'c': X case 'd': X if (cmd == 'd' && n1 != n2) X fatal("delete count conflict"); X while (o1 <= o2) { X fl = getline(fpf, obuf); X here++; X fd = getline(fpd, nbuf); X if (strncmp(fd, "<", 1)) X fatal("illegal delete line"); X if (strcmp(fl, fd + 2)) X fatal("delete line conflict"); X o1++; X } X if (cmd == 'd') X break; X if (strcmp(getline(fpd, nbuf), "---\n")) X fatal("illegal separator in chunk"); X /*FALLTHROUGH*/ X case 'a': X if (cmd == 'a') { X if (o1 != o2) X fatal("append count conflict"); X copy(getline(fpf, obuf)); X here++; X } X while (n1 <= n2) { X if (strncmp(getline(fpd, nbuf), ">", 1)) X fatal("illegal append line"); X copy(nbuf + 2); X n1++; X } X break; X } X } X while (fgets(obuf, LINELEN, fpf) != NULL) X copy(obuf); X exit(0); X} X Xisdigit(c) X char c; X{ X return c >= '0' && c <= '9'; X} X Xchar * Xrange(s, p1, p2) X char *s; X int *p1, *p2; X{ X register int v1 = 0, v2; X X while (isdigit(*s)) X v1 = 10 * v1 + *s++ - '0'; X v2 = v1; X if (*s == ',') { X s++; X v2 = 0; X while (isdigit(*s)) X v2 = 10 * v2 + *s++ - '0'; X } X if ( v1 > v2) X fatal("illegal range"); X *p1 = v1; X *p2 = v2; X return s; X} X Xgetcommand(fp, o1, o2, pcmd, n1, n2) X FILE *fp; X int *o1, *o2, *n1, *n2; X char *pcmd; X{ X char buf[LINELEN]; X register char *s; X char cmd; X X if ((s = fgets(buf, LINELEN, fp)) == NULL) X return 0; X s = range(s, o1, o2); X if ((cmd = *s++) != 'a' && cmd != 'c' && cmd != 'd') X fatal("illegal command"); X s = range(s, n1, n2); X if (*s != '\n' && s[1] != '\0') X fatal("extra characters at end of command: %s", s); X *pcmd = cmd; X return 1; X} X Xfatal(s, a) X char *s, *a; X{ X fprintf(stderr, "%s: processing: %s fatal: ", prog,processing); X fprintf(stderr, s, a); X fprintf(stderr, "\n"); X exit(1); X} X X#ifdef IGNORE_WHITE_SPACE X X/* This routine is a white space insensitive version of strcmp. X It is needed for testing things which might have undergone X tab conversion or trailing space removal X Bret Mckee June, 1988 */ X Xint strwcmp(s1,s2) Xchar *s1,*s2; X{ X char *x1=s1,*x2=s2; X X /* remove leading white space */ X while(whitespace(*s1)) X s1++; X while(whitespace(*s2)) X s2++; X do X { X while((*s1 == *s2) && *s1 && *s2) X { X s1++; X s2++; X } X ; /* consume identical characters */ X while(whitespace(*s1)) X s1++; X while(whitespace(*s2)) X s2++; X } while (*s1 && *s2 && (*s1 == *s2)); X if (*s1-*s2) X fprintf(stderr,"Failing for (%x)[%s]\n (%x)[%s]\n", X (int)*s1,x1,(int)*s2,x2); X return(*s1-*s2); X} X Xint whitespace(ch) Xchar ch; X{ X switch(ch) X { X case ' ': X case '\n': X case 0x0D: X case '\t': return(1); X default: return(0); X } X} X#endif + END-OF-FILE fix.c chmod 'u=rw,g=,o=' 'fix.c' set `wc -c 'fix.c'` count=$1 case $count in 4592) :;; *) echo 'Bad character count in ''fix.c' >&2 echo 'Count should be 4592' >&2 esac echo Extracting 'stty.c' sed 's/^X//' > 'stty.c' << '+ END-OF-FILE ''stty.c' X/* stty - set terminal mode Author: Andy Tanenbaum */ X X#include <sgtty.h> Xchar *on[] = {"tabs", "cbreak", "raw", "-nl", "echo"}; Xchar *off[]= {"-tabs", "", "", "nl", "-echo"}; Xint k; X Xstruct sgttyb args; Xstruct tchars tch; X X#define STARTC 021 /* CTRL-Q */ X#define STOPC 023 /* CTRL-S */ X#define QUITC 034 /* CTRL-\ */ X#define EOFC 004 /* CTRL-D */ X#define DELC 0177 /* DEL */ X X#define speed(s) args.sg_ispeed = s; args.sg_ospeed = s X#define clr1 args.sg_flags &= ~(BITS5 | BITS6 | BITS7 | BITS8) X#define clr2 args.sg_flags &= ~(EVENP | ODDP) X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X X /* stty with no arguments just reports on current status. */ X ioctl(0, TIOCGETP, &args); X ioctl(0, TIOCGETC, &tch); X if (argc == 1) { X report(); X exit(0); X } X X /* Process the options specified. */ X k = 1; X while (k < argc) { X option(argv[k], k+1 < argc ? argv[k+1] : ""); X k++; X } X ioctl(0, TIOCSETP, &args); X ioctl(0, TIOCSETC, &tch); X exit(0); X} X X X Xreport() X{ X int mode; X X X mode = args.sg_flags; X pr(mode&XTABS, 0); X pr(mode&CBREAK, 1); X pr(mode&RAW, 2); X pr(mode&CRMOD,3); X pr(mode&ECHO,4); X prints("\nkill = "); prctl(args.sg_kill); X prints("\nerase = "); prctl(args.sg_erase); X prints("\nint = "); prctl(tch.t_intrc); X prints("\nquit = "); prctl(tch.t_quitc); X prints("\n"); X} X Xpr(f, n) Xint f,n; X{ X if (f) X prints("%s ",on[n]); X else X prints("%s ",off[n]); X} X Xoption(opt, next) Xchar *opt, *next; X{ X if (match(opt, "-tabs")) {args.sg_flags &= ~XTABS; return;} X if (match(opt, "-odd")) {args.sg_flags &= ~ODDP; return;} X if (match(opt, "-even")) {args.sg_flags &= ~EVENP; return;} X if (match(opt, "-raw")) {args.sg_flags &= ~RAW; return;} X if (match(opt, "-cbreak")) {args.sg_flags &= ~CBREAK; return;} X if (match(opt, "-echo")) {args.sg_flags &= ~ECHO; return;} X if (match(opt, "-nl")) {args.sg_flags |= CRMOD; return;} X X if (match(opt, "tabs")) {args.sg_flags |= XTABS; return;} X if (match(opt, "even")) {clr2; args.sg_flags |= EVENP; return;} X if (match(opt, "odd")) {clr2; args.sg_flags |= ODDP; return;} X if (match(opt, "raw")) {args.sg_flags |= RAW; return;} X if (match(opt, "cbreak")) {args.sg_flags |= CBREAK; return;} X if (match(opt, "echo")) {args.sg_flags |= ECHO; return;} X if (match(opt, "nl")) {args.sg_flags &= ~CRMOD; return;} X X if (match(opt, "kill")) {args.sg_kill = *next; k++; return;} X if (match(opt, "erase")) {args.sg_erase = *next; k++; return;} X if (match(opt, "int")) {tch.t_intrc = *next; k++; return;} X if (match(opt, "quit")) {tch.t_quitc = *next; k++; return;} X X if (match(opt, "5")) {clr1; args.sg_flags |= BITS5; return;} X if (match(opt, "6")) {clr1; args.sg_flags |= BITS6; return;} X if (match(opt, "7")) {clr1; args.sg_flags |= BITS7; return;} X if (match(opt, "8")) {clr1; args.sg_flags |= BITS8; return;} X X if (match(opt, "110")) {speed(B110); return;} X if (match(opt, "300")) {speed(B300); return;} X if (match(opt, "1200")) {speed(B1200); return;} X if (match(opt, "2400")) {speed(B2400); return;} X if (match(opt, "4800")) {speed(B4800); return;} X if (match(opt, "9600")) {speed(B9600); return;} X X if (match(opt, "default")) { X args.sg_flags = ECHO | CRMOD | XTABS | BITS8; X args.sg_ispeed = B1200; X args.sg_ospeed = B1200; X args.sg_kill = '@'; X args.sg_erase = '\b'; X tch.t_intrc = DELC; X tch.t_quitc = QUITC; X tch.t_startc = STARTC; X tch.t_stopc = STOPC; X tch.t_eofc = EOFC; X return; X } X X std_err("unknown mode: "); X std_err(opt); X std_err("\n"); X X} X Xint match(s1, s2) Xchar *s1, *s2; X{ X X while (1) { X if (*s1 == 0 && *s2 == 0) return(1); X if (*s1 == 0 || *s2 == 0) return(0); X if (*s1 != *s2) return(0); X s1++; X s2++; X } X} X Xprctl(c) Xchar c; X{ X if (c < ' ') X prints("^%c", 'A' + c - 1); X else if (c == 0177) X prints("DEL"); X else X prints("%c", c); X} + END-OF-FILE stty.c chmod 'u=rw,g=r,o=r' 'stty.c' set `wc -c 'stty.c'` count=$1 case $count in 3780) :;; *) echo 'Bad character count in ''stty.c' >&2 echo 'Count should be 3780' >&2 esac echo Extracting 'cdiff.c' sed 's/^X//' > 'cdiff.c' << '+ END-OF-FILE ''cdiff.c' X/* cdiff - context diff Author: Larry Wall */ X X/* cdiff - turns a regular diff into a new-style context diff X * X * Usage: cdiff file1 file2 X * X * $Log: cdiff.c,v $ X * Revision 1.1.1.2 87/06/04 11:21:43 lwall X * Didn't do diffs with less than 3 lines of leading context. X * X * Revision 1.1.1.1 87/06/03 11:52:25 lwall X * Wasn't concatenating overlapping hunks right. X * X * Revision 1.1 87/06/01 16:05:57 lwall X * Initial revision X * X */ Xstatic char rcsid[] = "$Header: cdiff.c,v 1.1.1.2 87/06/04 11:21:43 lwall Exp $"; X X#define PATCHLEVEL 2 X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <ctype.h> X Xchar buff[512]; X XFILE *inputfp, *oldfp, *newfp; X Xint oldmin, oldmax, newmin, newmax; Xint oldbeg, oldend, newbeg, newend; Xint preoldmax, prenewmax; Xint preoldbeg, preoldend, prenewbeg, prenewend; Xint oldwanted, newwanted; X Xchar *oldhunk, *newhunk; Xunsigned oldsize, oldalloc, newsize, newalloc; X Xvoid dumphunk(); Xchar *getold(); Xchar *getnew(); Xchar *malloc(); Xchar *realloc(); Xchar *fgets(); XFILE *popen(); X X#define Nullfp (FILE*)0 X#define Nullch (char*)0 X Xmain(argc,argv) Xint argc; Xchar **argv; X{ X char *old, *new; X int context = 3; X struct stat statbuf; X register char *s; X char op; X char *newmark, *oldmark; X int len; X char *line; X int i; X X oldalloc = 512; X oldhunk = malloc(oldalloc); X newalloc = 512; X newhunk = malloc(newalloc); X X for (argc--,argv++; argc; argc--,argv++) { X if (argv[0][0] != '-') X break; X if (argv[0][1] == 'v') { X printf("%s\n Patch level: %d\n",rcsid,PATCHLEVEL); X exit(0); X } X if (argv[0][1] == 'c') X context = atoi(argv[0]+2); X } X X if (argc != 2) { X fprintf(stderr,"Usage: cdiff old new\n"); X exit(1); X } X X old = argv[0]; X new = argv[1]; X X sprintf(buff,"diff %s %s", old, new); X inputfp = popen(buff, "r"); X if (!inputfp) { X fprintf(stderr, "Can't execute diff %s %s\n", old, new); X exit(1); X } X X oldfp = fopen(old,"r"); X if (!oldfp) { X fprintf(stderr, "Can't open %s\n", old); X exit(1); X } X newfp = fopen(new,"r"); X if (!newfp) { X fprintf(stderr, "Can't open %s\n", new); X exit(1); X } X X fstat(fileno(oldfp),&statbuf); X printf("*** %s\t%s", old, ctime(&statbuf.st_mtime)); X fstat(fileno(newfp),&statbuf); X printf("--- %s\t%s", new, ctime(&statbuf.st_mtime)); X X preoldend = -1000; X X while (fgets(buff, sizeof buff, inputfp) != Nullch) { X if (isdigit(*buff)) { X oldmin = atoi(buff); X for (s = buff; isdigit(*s); s++) ; X if (*s == ',') { X s++; X oldmax = atoi(s); X for ( ; isdigit(*s); s++) ; X } X else { X oldmax = oldmin; X } X if (*s != 'a' && *s != 'd' && *s != 'c') { X fprintf(stderr, "Unparseable input: %s", s); X exit(1); X } X op = *s; X s++; X newmin = atoi(s); X for ( ; isdigit(*s); s++) ; X if (*s == ',') { X s++; X newmax = atoi(s); X for ( ; isdigit(*s); s++) ; X } X else { X newmax = newmin; X } X if (*s != '\n' && *s != ' ') { X fprintf(stderr, "Unparseable input: %s", s); X exit(1); X } X X newmark = oldmark = "! "; X if (op == 'a') { X oldmin++; X newmark = "+ "; X } X if (op == 'd') { X newmin++; X oldmark = "- "; X } X X oldbeg = oldmin - context; X oldend = oldmax + context; X if (oldbeg < 1) X oldbeg = 1; X newbeg = newmin - context; X newend = newmax + context; X if (newbeg < 1) X newbeg = 1; X X if (preoldend < oldbeg - 1) { X if (preoldend >= 0) { X dumphunk(); X } X preoldbeg = oldbeg; X prenewbeg = newbeg; X oldwanted = newwanted = 0; X oldsize = newsize = 0; X } else { /* we want to append to previous hunk */ X oldbeg = preoldmax + 1; X newbeg = prenewmax + 1; X } X X for (i = oldbeg; i <= oldmax; i++) { X line = getold(i); X if (!*line) { X oldend = oldmax = i - 1; X break; X } X len = strlen(line) + 2; X if (oldsize + len + 1 >= oldalloc) { X oldalloc *= 2; X oldhunk = realloc(oldhunk, oldalloc); X } X if (i >= oldmin) { X strcpy(oldhunk+oldsize, oldmark); X oldwanted++; X } X else { X strcpy(oldhunk+oldsize, " "); X } X strcpy(oldhunk+oldsize+2,line); X oldsize += len; X } X preoldmax = oldmax; X preoldend = oldend; X X for (i = newbeg; i <= newmax; i++) { X line = getnew(i); X if (!*line) { X newend = newmax = i - 1; X break; X } X len = strlen(line) + 2; X if (newsize + len + 1 >= newalloc) { X newalloc *= 2; X newhunk = realloc(newhunk, newalloc); X } X if (i >= newmin) { X strcpy(newhunk+newsize, newmark); X newwanted++; X } X else { X strcpy(newhunk+newsize, " "); X } X strcpy(newhunk+newsize+2,line); X newsize += len; X } X prenewmax = newmax; X prenewend = newend; X } X } X X if (preoldend >= 0) { X dumphunk(); X } X} X Xvoid Xdumphunk() X{ X int i; X char *line; X int len; X X for (i = preoldmax + 1; i <= preoldend; i++) { X line = getold(i); X if (!line) { X preoldend = i - 1; X break; X } X len = strlen(line) + 2; X if (oldsize + len + 1 >= oldalloc) { X oldalloc *= 2; X oldhunk = realloc(oldhunk, oldalloc); X } X strcpy(oldhunk+oldsize, " "); X strcpy(oldhunk+oldsize+2, line); X oldsize += len; X } X for (i = prenewmax + 1; i <= prenewend; i++) { X line = getnew(i); X if (!line) { X prenewend = i - 1; X break; X } X len = strlen(line) + 2; X if (newsize + len + 1 >= newalloc) { X newalloc *= 2; X newhunk = realloc(newhunk, newalloc); X } X strcpy(newhunk+newsize, " "); X strcpy(newhunk+newsize+2, line); X newsize += len; X } X fputs("***************\n",stdout); X if (preoldbeg >= preoldend) { X printf("*** %d ****\n", preoldend); X } else { X printf("*** %d,%d ****\n", preoldbeg, preoldend); X } X if (oldwanted) { X fputs(oldhunk,stdout); X } X oldsize = 0; X *oldhunk = '\0'; X if (prenewbeg >= prenewend) { X printf("--- %d ----\n", prenewend); X } else { X printf("--- %d,%d ----\n", prenewbeg, prenewend); X } X if (newwanted) { X fputs(newhunk,stdout); X } X newsize = 0; X *newhunk = '\0'; X} X Xchar * Xgetold(targ) Xint targ; X{ X static int oldline = 0; X X while (fgets(buff, sizeof buff, oldfp) != Nullch) { X oldline++; X if (oldline == targ) X return buff; X } X return Nullch; X} X Xchar * Xgetnew(targ) Xint targ; X{ X static int newline = 0; X X while (fgets(buff, sizeof buff, newfp) != Nullch) { X newline++; X if (newline == targ) X return buff; X } X return Nullch; X} + END-OF-FILE cdiff.c chmod 'u=rw,g=r,o=r' 'cdiff.c' set `wc -c 'cdiff.c'` count=$1 case $count in 6400) :;; *) echo 'Bad character count in ''cdiff.c' >&2 echo 'Count should be 6400' >&2 esac echo Extracting 'ioctl.c' sed 's/^X//' > 'ioctl.c' << '+ END-OF-FILE ''ioctl.c' X#include "lib.h" X#include <minix/com.h> X#include <sgtty.h> X XPUBLIC int ioctl(fd, request, u) Xint fd; Xint request; Xunion { X struct sgttyb *argp; X struct tchars *argt; X} u; X X{ X int n; X long erase, kill, intr, quit, xon, xoff, eof, brk; X X M.TTY_REQUEST = request; X M.TTY_LINE = fd; X X switch(request) { X case TIOCSETP: X erase = u.argp->sg_erase & 0377; X kill = u.argp->sg_kill & 0377; X M.TTY_SPEK = (erase << 8) | kill; X M.TTY_FLAGS = u.argp->sg_flags; X M.TTY_SPEED = (u.argp->sg_ospeed << 8) | u.argp->sg_ispeed; X n = callx(FS, IOCTL); X return(n); X X case TIOCSETC: X intr = u.argt->t_intrc & 0377; X quit = u.argt->t_quitc & 0377; X xon = u.argt->t_startc & 0377; X xoff = u.argt->t_stopc & 0377; X eof = u.argt->t_eofc & 0377; X brk = u.argt->t_brkc & 0377; /* not used at the moment */ X M.TTY_SPEK = (intr<<24) | (quit<<16) | (xon<<8) | (xoff<<0); X M.TTY_FLAGS = (eof<<8) | (brk<<0); X n = callx(FS, IOCTL); X return(n); X X case TIOCGETP: X n = callx(FS, IOCTL); X u.argp->sg_erase = (M.TTY_SPEK >> 8) & 0377; X u.argp->sg_kill = (M.TTY_SPEK >> 0) & 0377; X u.argp->sg_flags = M.TTY_FLAGS; X return(n); X X case TIOCGETC: X n = callx(FS, IOCTL); X u.argt->t_intrc = (M.TTY_SPEK >> 24) & 0377; X u.argt->t_quitc = (M.TTY_SPEK >> 16) & 0377; X u.argt->t_startc = (M.TTY_SPEK >> 8) & 0377; X u.argt->t_stopc = (M.TTY_SPEK >> 0) & 0377; X u.argt->t_eofc = (M.TTY_FLAGS >> 8) & 0377; X u.argt->t_brkc = (M.TTY_FLAGS >> 8) & 0377; X return(n); X X default: X n = -1; X errno = -(EINVAL); X return(n); X } X} X + END-OF-FILE ioctl.c chmod 'u=rw,g=r,o=r' 'ioctl.c' set `wc -c 'ioctl.c'` count=$1 case $count in 1561) :;; *) echo 'Bad character count in ''ioctl.c' >&2 echo 'Count should be 1561' >&2 esac exit 0