--------------------------------------------------------------------------------
 cmd/admin.c    |  762 ++++++++-==========================================
 cmd/alloc.c    |   13 
 cmd/bdiff.c    |  374 ========================
 cmd/cmt.c      |  353 ++++++++++++++++++++++
 cmd/comb.c     |  251 ================
 cmd/delta.c    |  670 +++========================================
 cmd/get.c      |  701 ++==========================================
 cmd/help.c     |  154 ==========
 cmd/prs.c      |  797 +++++++++++++++++++++++++++++++++++++++++++++++++++
 cmd/prt.c      |  425 ===========================
 cmd/rmchg.c    |  392 +++++++++++++++++++++++++
 cmd/sccsdiff   |   41 !!
 cmd/scv.c      |  877 !!!!!===================================================
 cmd/snull.c    |  581 +++++++++++++++++++++++++++++++++++++
 cmd/stree.c    |  293 +++++++++++++++++++
 cmd/val.c      |  688 ++++++++++++++++++++++++++++++++++++++++++++
 cmd/vc.c       |  658 ++++++++++++++++++++++++++++++++++++++++++
 cmd/what.c     |   63 ====
 com/auxf.c     |   39 ==
 com/chkid.c    |   19 =
 com/chksid.c   |   14 
 com/date_ab.c  |  102 =====
 com/date_ba.c  |   22 =
 com/del_ab.c   |   38 ==
 com/del_ba.c   |   41 ==
 com/dodelt.c   |  131 =======
 com/dofile.c   |   59 ===
 com/dohist.c   |  162 ==========
 com/doie.c     |   21 =
 com/dolist.c   |   80 ====
 com/eqsid.c    |   15 
 com/flushto.c  |   19 =
 com/fmterr.c   |   10 
 com/getline.c  |   45 ==
 com/newstats.c |   14 
 com/permiss.c  |   76 ====
 com/pf_ab.c    |   57 ===
 com/putline.c  |   92 =====
 com/rdmod.c    |  163 ==========
 com/setup.c    |   81 ====
 com/sid_ab.c   |   18 =
 com/sid_ba.c   |   20 =
 com/sidtoser.c |   21 =
 com/sinit.c    |   38 ==
 com/stats_ab.c |   19 =
 hdr/defines.h  |  210 +============
 hdr/had.h      |   26 =
 46 files changed, 4046 insertions(+), 21 deletions(-), 247 modifications(!), 5431 unchanged lines(=)
--------------------------------------------------------------------------------
# Please remove the following files before applying this patch.
# (You can feed this patch to 'sh' to do so.)
 
rm -f cmd/rmdel.c
rm -f install
rm -f makefile
exit
 
Index:  cmd/admin.c
--- UNSW-87-record0:sccs4/cmd/admin.c   1978-09-07 19:22:08.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/admin.c      1981-01-15 00:16:23.000000000 -0500
@@ -1,7 +1,7 @@
 # include "../hdr/defines.h"
 # include "../hdr/had.h"
 
-SCCSID(@(#)admin       1.12);
+SCCSID(@(#)admin.c     4.1);
 
 /*
        Program to create new SCCS files and change parameters
@@ -30,8 +30,14 @@
 # define NOCOPY 1
 
 char *ifile, *tfile;
+char *z;       /* for validation program name */
 char had[26], had_flag[26], rm_flag[26];
+char   *Comments, *Mrs;
+char Valpgm[]          "/usr/local/val";
 int irel, fexists, num_files;
+int    VFLAG   0;
+int    Domrs;
+char *Sflags[];
 char *anames[MAXNAMES], *enames[MAXNAMES];
 char *flag_p[26];
 int asub, esub;
@@ -75,6 +81,12 @@
                        case 't':       /* name of file of descriptive text */
                                tfile = p;
                                break;
+                       case 'm':       /* mr flag */
+                               Mrs = p;
+                               break;
+                       case 'y':       /* comments flag for entry */
+                               Comments = p;
+                               break;
 
                        case 'd':       /* flags to be deleted */
                                testklt = 0;
@@ -89,6 +101,7 @@
                                case VALFLAG:
                                case TYPEFLAG:
                                case MODFLAG:
+                               case NULLFLAG:
                                case FLORFLAG:
                                case CEILFLAG:
                                case DEFTFLAG:
@@ -115,12 +128,16 @@
 
                                case IDFLAG:    /* id-kwd message (err/warn) */
                                case BRCHFLAG:  /* branch */
+                               case NULLFLAG:  /* null deltas */
                                        if (*p)
                                                fatal(sprintf(Error,
                                                "value after %c flag (ad13)",f));
                                        break;
 
                                case VALFLAG:   /* mr validation */
+                                       VFLAG++;
+                                       if (*p)
+                                               z = p;
                                        break;
 
                                case FLORFLAG:  /* floor */
@@ -206,6 +223,9 @@
        if (num_files == 0)
                fatal("missing file arg (cm3)");
 
+       if (HADI && num_files > 1) /* only one file allowed with `i' */
+               fatal("more than one file (ad15)");
+
        setsig();
 
        /*
@@ -238,31 +258,44 @@
        and the old s-file is removed.
 */
 
-struct packet gpkt;    /* see file s.h */
+struct packet gpkt;    /* see file defines.h */
+char   Zhold[BUFSIZ];  /* temporary z-file name */
 
 USXALLOC();            /* defines alloc() and free() */
 
 admin(afile)
 char *afile;
 {
-       struct deltab dt;       /* see file s.h */
-       struct stats stats;     /* see file s.h */
+       struct deltab dt;       /* see file defines.h */
+       struct stats stats;     /* see file defines.h */
        FILE *iptr;
        register int k;
        register char *cp, *q;
+       char command[80];
        char line[512];
+       int i;                  /* used in forking procedure */
+       int status;
        extern nfiles;
+       extern had_dir;
 
        if (setjmp(Fjmp))       /* set up to return here from 'fatal' */
                return;         /* and return to caller of admin */
 
-       if (HADI && nfiles > 0) /* only one file allowed with 'i' keyletter */
-               fatal("more than one file (ad15)");
+       if (HADI && had_dir) /* directory not allowed with `i' keyletter */
+               fatal("directory named with `i' keyletter (ad26)");
 
        fexists = exists(afile);
 
        if (HADI)
                HADN = 1;
+       if (HADI || HADN) {
+               if (HADM && !VFLAG)
+                       fatal("MRs not allowed (de8)");
+
+               if (VFLAG && !HADM)
+                       fatal("MRs required (de10)");
+
+       }
 
        if (!HADI && HADR)
                fatal("r only allowed with i (ad16)");
@@ -278,12 +311,41 @@
 
        if (!HADN && !fexists)
                fatal(sprintf(Error,"file %s does not exist (ad20)",afile));
+       /*
+          Check for '-h' flag.  If set, create child process and
+          invoke 'get' to examine format of SCCS file.
+       */
+
+       if (HADH) {
+               /*
+                  fork here so 'admin' can execute 'val' to
+                  check for a corrupted file.
+               */
+               if ((i = fork()) < 0)
+                       fatal("cannot fork, try again");
+               if (i == 0) {           /* child */
+                       /*
+                          perform 'val' with appropriate keyletters
+                       */
+                       execl("/bin/sh","/bin/sh","-c",
+                               sprintf(command,
+                                       "/usr/local/val -s %s",
+                                               afile),0);
+                       fatal(sprintf(Error,"cannot execute '%s'",Valpgm));
+               }
+               else {
+                       wait(&status);     /* wait on status from 'execl' */
+                       if (status)
+                               fatal("corrupted file (co6)");
+                       return;         /* return to caller of 'admin' */
+               }
+       }
 
        /*
        Lock out any other user who may be trying to process
        the same file.
        */
-       if (!HADH && lockit(auxf(afile,'z'),2,getpid()))
+       if (!HADH && lockit(copy(auxf(afile,'z'),Zhold),2,getpid()))
                fatal("cannot create lock file (cm4)");
 
        if (fexists)
@@ -293,20 +355,17 @@
                sinit(&gpkt,afile,0);   /* and init pkt */
        }
 
-       /*
-       Flag for putline routine to tell it to open x-file
-       and allow writing on it.
-       */
-       if (HADH)
-               gpkt.p_upd = 0;
-       else
+       if (!HADH)
+               /*
+                  set the flag for 'putline' routine to open
+                  the 'x-file' and allow writing on it.
+               */
                gpkt.p_upd = 1;
 
-       if (fexists && !gpkt.p_ihash)   /* ignore checksum processing? */
-               HADZ = 1;
-
-       if (HADZ)
+       if (HADZ) {
+               gpkt.do_chksum = 0;     /* ignore checksum processing */
                gpkt.p_ihash = 0;
+       }
 
        /*
        Get statistics of latest delta in old file.
@@ -353,6 +412,33 @@
                putline(&gpkt,line);    /* delta-table entry */
 
                /*
+               If -m flag, enter MR numbers
+               */
+
+               if (Mrs) {
+                       mrfixup();
+                       if (z && valmrs(&gpkt,z))
+                               fatal("invalid MRs (de9)");
+                       putmrs(&gpkt);
+               }
+
+               /*
+               Enter comment line for `chghist'
+               */
+
+               if (HADY) {
+                       putline(&gpkt,sprintf(line,"%c%c ",CTLCHAR,COMMENTS));
+                       putline(&gpkt,Comments);
+                       putline(&gpkt,"\n");
+               }
+               else {
+                       /*
+                       insert date/time and pgmr into comment line
+                       */
+                       cmt_ba(&dt,line);
+                       putline(&gpkt,line);
+               }
+               /*
                End of delta-table.
                */
                putline(&gpkt,sprintf(line,CTLSTR,CTLCHAR,EDELTAB));
@@ -619,8 +705,55 @@
 clean_up()
 {
        xrm(&gpkt);
-       if (!HADH && gpkt.p_file[0])
-               unlockit(auxf(gpkt.p_file,'z'),getpid());
+       if (!HADH)
+               unlockit(Zhold,getpid());
        if (HADN)
                unlink(&gpkt);
 }
+
+
+cmt_ba(dt,str)
+register struct deltab *dt;
+char *str;
+{
+       register char *p;
+
+       p = str;
+       *p++ = CTLCHAR;
+       *p++ = COMMENTS;
+       *p++ = ' ';
+       copy("date and time created",p);
+       while (*p++)
+               ;
+       --p;
+       *p++ = ' ';
+       date_ba(&dt->d_datetime,p);
+       while (*p++)
+               ;
+       --p;
+       *p++ = ' ';
+       copy("by",p);
+       while (*p++)
+               ;
+       --p;
+       *p++ = ' ';
+       copy(dt->d_pgmr,p);
+       while (*p++)
+               ;
+       --p;
+       *p++ = '\n';
+       *p = 0;
+       return(str);
+}
+
+
+putmrs(pkt)
+struct packet *pkt;
+{
+       register char **argv;
+       char str[64];
+       extern char *Varg[];
+
+       for (argv = &Varg[VSTART]; *argv; argv++)
+               putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
+}
Index:  cmd/alloc.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/alloc.c      1981-01-15 00:17:47.000000000 -0500
@@ -0,0 +1,13 @@
+# include <sccs.h>
+
+SCCSID(@(#)alloc.c     4.1);
+
+alloc(i)
+       int i;
+{
+       register char *cp = malloc(i);
+
+       if (cp == 0)
+               return (-1);
+       return (cp);
+}
Index:  cmd/bdiff.c
--- UNSW-87-record0:sccs4/cmd/bdiff.c   1978-09-07 19:22:09.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/bdiff.c      1981-01-15 00:16:26.000000000 -0500
@@ -1,6 +1,6 @@
 # include "../hdr/defines.h"
 
-SCCSID(@(#)bdiff       1.8);
+SCCSID(@(#)bdiff.c     4.1);
 
 /*
        This program segments two files into pieces of <= seglim lines
@@ -223,7 +223,7 @@
                        EOF on pipe.
                        */
                        wait(&status);
-                       if (status)
+                       if (status&~0x100)
                                fatal(sprintf(Error,"'%s' failed (bd6)",diff));
                }
                linenum =+ seglim;
Index:  cmd/cmt.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/cmt.c        1981-01-15 00:16:27.000000000 -0500
@@ -0,0 +1,353 @@
+# include      "../hdr/defines.h"
+# include      "../hdr/had.h"
+
+SCCSID(@(#)cmt.c       4.1);
+
+struct packet gpkt;
+int    num_files, had_ffile;
+int    F_Opened, Opened, Domrs, First;
+char   *Comments, *Mrs, *ffile;
+char   Cstr[BUFSIZ], Mstr[BUFSIZ], Line[BUFSIZ], had[26];
+FILE   *iop, *Xiop;
+static char    ifde[]  "initial file does not exists";
+
+main(argc,argv)
+int argc;
+register char *argv[];
+{
+       register int i;
+       register char *p;
+       char c;
+       extern cmt();
+       extern int Fcnt;
+
+       /*
+       Flags for 'fatal'.
+       */
+       Fflags = FTLEXIT | FTLMSG | FTLCLN;
+
+       /*
+       Process arguments.
+       */
+       for (i = 1; i < argc; i++)
+               if (argv[i][0] == '-' && (c = argv[i][1])) {
+                       p = &argv[i][2];
+                       switch (c) {
+                       case 'f':
+                               if (*p) {
+                                       ffile = p;
+                                       ++had_ffile;
+                                       if (!exists(ffile))
+                                               fatal(ifde);
+                               }
+                               break;
+                       default:
+                               fatal("unknown key letter (cm1)");
+                       }
+                       if (had[c - 'a']++)
+                               fatal("key letter twice (cm2)");
+                       argv[i] = 0;
+               }
+               else num_files++;
+
+       if(num_files == 0)
+               fatal("missing file arg (cm3)");
+
+       setsig();
+       /*
+       Reset flags for 'fatal' so that it will return to 'main'
+       rather than exiting.
+       */
+       Fflags =& ~FTLEXIT;
+       Fflags =| FTLJMP;
+
+       /*
+       Invoke 'cmt' for each file argument. 
+       */
+       for (i = 1; i < argc; i++)
+               if (p = argv[i])
+                       do_file(p,cmt);
+
+       exit(Fcnt ? 1 : 0);
+}
+
+
+static char s_warn[] "WARNING: MR flag is set; `%s' should contain both MR line and comment line\n";
+
+static char ns_warn[] "WARNING: MR flag is not set; `%s' should only contain comment line\n";
+
+cmt(file)
+register char *file;
+{
+       extern char had_dir, had_standinp;
+       extern  char    *Sflags[];
+       extern  char    Pgmr[8];
+       char    line[BUFSIZ];
+       int     fowner, downer, user;
+
+       /*
+       Set up to return to caller ('main') from 'fatal'.
+       */
+       if (setjmp(Fjmp))
+               return;
+
+       sinit(&gpkt,file,1);    /* init packet and open file */
+
+       if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
+               fatal("cannot create lock file (cm4)");
+
+       if (num_files > 1 || had_dir || had_standinp)
+               printf("\n%s:\n",gpkt.p_file);
+
+       First = 1;
+       gpkt.p_reopen = 1;
+       do_delt(&gpkt);         /* read delta table for First time */
+       finduser(&gpkt);
+       doflags(&gpkt);         /* get flags (see if v flag is set) */
+       permiss(&gpkt);
+
+       /*
+       Check that user is either owner of file or
+       directory, or is one who made the initial delta
+       */
+
+       fstat(fileno(gpkt.p_iop),&Statbuf);
+       fowner = Statbuf.st_uid & 0377;
+       copy(gpkt.p_file,line);         /* temporary for dname() */
+       if (stat(dname(line),&Statbuf))
+               downer = -1;
+       else downer = Statbuf.st_uid & 0377;
+       user = getuid() & 0377;
+       if (user != fowner || user != downer)
+               if (!equal(Pgmr,logname()))
+                       fatal(sprintf(Error,
+                               "you are neither owner nor '%s' (rc4)",Pgmr));
+
+       if ((HADF && had_ffile)) {
+               if (Sflags[VALFLAG - 'a'])
+                       fprintf(stderr,s_warn,ffile);
+               else fprintf(stderr,ns_warn,ffile);
+               sleep(5);
+       }
+       flushto(&gpkt,EUSERTXT,1);
+       gpkt.p_chkeof = 1;      /* indicate that EOF is okay */
+       while (getline(&gpkt))  /* this will read body checking for cor */
+               ;
+
+       gpkt.p_upd = 1;         /* x-file is to be used */
+       gpkt.p_wrttn = 1;       /* prevent printing of header line */
+       getline(&gpkt);         /* skip over old header record */
+       gpkt.p_wrttn = 1;
+
+       /*
+       Write new header.
+       */
+       putline(&gpkt,sprintf(Line,"%c%c00000\n",CTLCHAR,HEAD));
+       do_delt(&gpkt);         /* read delta table second time */
+
+       flushto(&gpkt,EUSERNAM,0);
+       flushto(&gpkt,EUSERTXT,0);
+       while(getline(&gpkt))
+               ;
+
+       flushline(&gpkt,0);     /* flush buffer, fix header, and close */
+       rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
+       xrm(&gpkt);
+       unlockit(auxf(gpkt.p_file,'z'),getpid());
+       return;
+}
+
+
+static char    cle[]   "comment line for initial delta already exists";
+
+do_delt(pkt)
+register struct packet *pkt;
+{
+       int     n;
+       int     did_zero 0;
+       struct deltab dt;
+       struct stats stats;
+
+       while(getstats(pkt,&stats)) {
+               if(getadel(pkt,&dt) != BDELTAB)
+                       fmterr(pkt);
+               if(dt.d_type == 'D' && dt.d_pred == 0) {
+                       copy(dt.d_pgmr,Pgmr);
+                       if (First)
+                               did_zero++;
+                       else {
+                               putline(pkt,0);
+                               fixintdel();
+                       }
+               }
+               while((n = getline(pkt)) != NULL)
+                       if (pkt->p_line[0] != CTLCHAR)
+                               break;
+                       else {
+                               switch(pkt->p_line[1]) {
+                               case EDELTAB:
+                                       break;
+                               case INCLUDE:
+                               case EXCLUDE:
+                               case IGNORE:
+                               case MRNUM:
+                                       continue;
+                               case COMMENTS:
+                                       if (First)
+                                               if(did_zero)
+                                                       fatal(cle);
+                                       continue;
+                               default:
+                                       fmterr(pkt);
+                               }
+                               break;
+                       }
+               if (n ==NULL || pkt->p_line[0] != CTLCHAR)
+                       fmterr(pkt);
+       }
+       First = 0;
+}
+
+
+getadel(pkt,dt)
+register struct packet *pkt;
+register struct deltab *dt;
+{
+       if (getline(pkt) == NULL)
+               fmterr(pkt);
+       return(del_ab(pkt->p_line,dt,pkt));
+}
+
+
+getstats(pkt,statp)
+register struct packet *pkt;
+register struct stats *statp;
+{
+       register char *p;
+       extern  char    *satoi();
+
+       p = pkt->p_line;
+       if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
+               return(0);
+       NONBLANK(p);
+       p = satoi(p,&statp->s_ins);
+       p = satoi(++p,&statp->s_del);
+       satoi(++p,&statp->s_unc);
+       return(1);
+}
+
+clean_up(n)
+{
+       if (gpkt.p_file[0])
+               unlockit(auxf(gpkt.p_file,'z'),getpid());
+       if (gpkt.p_iop)
+               fclose(gpkt.p_iop);
+
+       xrm(&gpkt);
+       if (exists(auxf(gpkt.p_file,'x')))
+               remove(auxf(gpkt.p_file,'x'));  /* remove x-file */
+       Xiop = 0;
+       if (F_Opened)
+               fclose(iop);
+       iop = F_Opened = Opened = 0;
+       xfreeall();
+}
+
+
+fixintdel()
+{
+
+       register char   *p;
+       register int    doprmt;
+       int     tty[3];
+       char    str[128];
+
+       doprmt = 0;
+       if (gtty(0,tty) >= 0)
+               doprmt++;
+
+       if (!HADF && !had_ffile) {
+               Opened++;
+               iop = stdin;
+       }
+       else if (HADF && had_ffile) {
+               iop = xfopen(ffile,0);
+               doprmt = 0;
+               Opened++;
+               F_Opened++;
+       }
+       else if (HADF && !had_ffile)
+               doprmt = 0;
+
+       if ((p = Sflags[VALFLAG - 'a'])) {
+               if (doprmt)
+                       printf("MRs? ");
+               if (Opened) {
+                       Mrs = getinput(" ",Mstr);
+                       mrfixup();
+                       if (*p && valmrs(&gpkt,p))
+                               fatal("invalid MRs (de9)");
+                       putmrs(&gpkt);
+               }
+               else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,MRNUM));
+       }
+       if (doprmt)
+               printf("comments? ");
+       if (Opened) {
+               Comments = getinput(sprintf(Line,"\n%c%c ",CTLCHAR,COMMENTS),
+                          Cstr);
+               putline(&gpkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
+               putline(&gpkt,Comments);
+               putline(&gpkt,"\n");
+       }
+       else putline(&gpkt,sprintf(Line,CTLSTR,CTLCHAR,COMMENTS));
+
+       if (F_Opened)
+               fclose(iop);
+       F_Opened = Opened = 0;
+}
+
+
+getinput(repstr,result)
+char *repstr;
+char *result;
+{
+       char line[BUFSIZ];
+       register int done, sz;
+       register char *p;
+
+       result[0] = 0;
+       done = 0;
+       setbuf(iop,NULL);
+       sz = sizeof(line) - size(repstr);
+       while (!done && fgets(line,sz,iop) != NULL) {
+               p = strend(line);
+               if (*--p == '\n') {
+                       if (*--p == '\\') {
+                               copy(repstr,p);
+                       }
+                       else {
+                               *++p = 0;
+                               ++done;
+                       }
+               }
+               else
+                       fatal("line too long (co18)");
+               if ((size(line) + size(result)) > RESPSIZE)
+                       fatal("response too long (co19)");
+               strcat(result,line);
+       }
+       return(result);
+}
+
+
+putmrs(pkt)
+struct packet *pkt;
+{
+       register char **argv;
+       char str[64];
+       extern char *Varg[];
+
+       for (argv = &Varg[VSTART]; *argv; argv++)
+               putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
+}
Index:  cmd/comb.c
--- UNSW-87-record0:sccs4/cmd/comb.c    1978-09-07 19:22:10.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/comb.c       1981-01-15 00:16:29.000000000 -0500
@@ -1,7 +1,7 @@
 # include      "../hdr/defines.h"
 # include      "../hdr/had.h"
 
-SCCSID(@(#)comb        1.3);
+SCCSID(@(#)comb.c      4.1);
 USXALLOC();
 
 struct packet gpkt;
@@ -148,24 +148,25 @@
                prtget(rdp, Cvec[i], iop, gpkt.p_file);
                fprintf(iop, "delta -s '-yThis was COMBined' s.COMB\n");
        }
-       fprintf(iop, "sed -n '/^%c%c$/,/^%c%c$/p' %s >comb$$\n",
+       fprintf(iop, "sed -n '/^%c%c$/,/^%c%c$/p' %s >comb${pid}\n",
                CTLCHAR, BUSERTXT, CTLCHAR, EUSERTXT, gpkt.p_file);
-       fprintf(iop, "ed - comb$$\n");
+       fprintf(iop, "ed - comb${pid} <<\\!\n");
        fprintf(iop, "1d\n");
        fprintf(iop, "$c\n");
        fprintf(iop, " *** DELTA TABLE PRIOR TO COMBINE ***\n");
        fprintf(iop, ".\n");
        fprintf(iop, "w\n");
        fprintf(iop, "q\n");
-       fprintf(iop, "prt -a %s >>comb$$\n", gpkt.p_file);
-       fprintf(iop, "admin -tcomb$$ s.COMB\\\n");
+       fprintf(iop, "!\n");
+       fprintf(iop, "prt -a %s >>comb${pid}\n", gpkt.p_file);
+       fprintf(iop, "admin -tcomb${pid} s.COMB\\\n");
        for (i = 0; i < NFLAGS; i++)
                if (p = Sflags[i])
-                       fprintf(iop, "'-f%c%s'\\\n", i + 'a', p);
+                       fprintf(iop, " -f%c%s\\\n", i + 'a', p);
        fprintf(iop, "\n");
-       fprintf(iop, "sed -n '/^%c%c$/,/^%c%c$/p' %s >comb$$\n",
+       fprintf(iop, "sed -n '/^%c%c$/,/^%c%c$/p' %s >comb${pid}\n",
                CTLCHAR, BUSERNAM, CTLCHAR, EUSERNAM, gpkt.p_file);
-       fprintf(iop, "ed - comb$$\n");
+       fprintf(iop, "ed - comb${pid} <<\\!\n");
        fprintf(iop, "v/^%c/s/.*/-a& \\\\/\n", CTLCHAR);
        fprintf(iop, "1c\n");
        fprintf(iop, "admin s.COMB\\\n");
@@ -175,19 +176,18 @@
        fprintf(iop, ".\n");
        fprintf(iop, "w\n");
        fprintf(iop, "q\n");
-       fprintf(iop, "sh comb$$\n");
-       fprintf(iop, "rm comb$$\n");
+       fprintf(iop, "!\n");
+       fprintf(iop, "sh comb${pid}\n");
+       fprintf(iop, "rm comb${pid}\n");
        if (!HADS) {
                fprintf(iop, "rm -f %s\n", gpkt.p_file);
                fprintf(iop, "mv s.COMB %s\n", gpkt.p_file);
        }
        else {
-               fprintf(iop, "ls -s s.COMB | = a\n");
-               fprintf(iop, "= a $a\n");
-               fprintf(iop, "ls -s %s | = b\n", gpkt.p_file);
-               fprintf(iop, "= b $b\n");
-               fprintf(iop, "expr 100 - 100 '*' $a / $b | = c\n");
-               fprintf(iop, "echo '%s\t' $c'%%\t' $a/$b\n", gpkt.p_file);
+               fprintf(iop, "set a=`echo \\`ls -s s.COMB\\``\n");
+               fprintf(iop, "set b=`echo \\`ls -s %s\\``\n",gpkt.p_file);
+               fprintf(iop, "set c=`expr 100 - 100 '*' ${a} / ${b}`\n");
+               fprintf(iop, "echo '%s\t' ${c}'%%\t' ${a}/${b}\n", gpkt.p_file);
                fprintf(iop, "rm -f s.COMB\n");
        }
 }
@@ -213,7 +213,8 @@
        struct sid *sp;
 
        sid_ba(sp = &idp[ser].i_sid, buf);
-       fprintf(iop, "get -s -k -r%s -p %s >COMB\n", buf, file);
+       fprintf(iop, ":\t/bin/bsh\n");
+       fprintf(iop, "get -s -k -r%s -p %s > COMB\n", buf, file);
        return(sp);
 }
 
Index:  cmd/delta.c
--- UNSW-87-record0:sccs4/cmd/delta.c   1978-09-07 19:22:11.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/delta.c      1981-01-15 13:38:10.000000000 -0500
@@ -1,10 +1,10 @@
 # include      "../hdr/defines.h"
 # include      "../hdr/had.h"
 
-SCCSID(@(#)delta       1.13);
+SCCSID(@(#)delta.c     4.2);
 USXALLOC();
 
-char   Diffpgm[]       "/usr/bin/bdiff";
+char   Diffpgm[]       "/usr/local/bdiff";
 FILE   *Diffin;
 int    Debug   0;
 struct packet gpkt;
@@ -179,7 +179,8 @@
                gpkt.p_wrttn = 1;
                getline(&gpkt);
                gpkt.p_wrttn = 1;
-               newser = mkdelt(&gpkt,&pp->pf_nsid,&pp->pf_gsid,diffloop);
+               newser = mkdelt(&gpkt,&pp->pf_nsid,&pp->pf_gsid,
+                                               diffloop,orig);
                diffloop = 1;
                flushto(&gpkt,EUSERTXT,0);
                Diffin = dodiff(auxf(gpkt.p_file,'g'),dfilename,difflim);
@@ -257,16 +258,17 @@
        }
        clean_up(0);
        if (!HADN) {
-               setuid(getuid() & 0377);
+               setuid(getuid());
                unlink(gfilename);
        }
 }
 
 
-mkdelt(pkt,sp,osp,diffloop)
+mkdelt(pkt,sp,osp,diffloop,orig_nlines)
 struct packet *pkt;
 struct sid *sp, *osp;
 int diffloop;
+int orig_nlines;
 {
        extern long Timenow;
        struct deltab dt;
@@ -274,6 +276,7 @@
        int newser;
        extern char *Sflags[];
        register char *p;
+       int ser_inc, opred, nulldel;
 
        if (!diffloop && pkt->p_verbose) {
                sid_ba(sp,str);
@@ -282,8 +285,38 @@
        putline(pkt,sprintf(str,"%c%c00000\n",CTLCHAR,HEAD));
        newstats(pkt,str,"0");
        move(sp,&dt.d_sid,sizeof(dt.d_sid));
-       newser = dt.d_serial = maxser(pkt) + 1;
-       dt.d_pred = sidtoser(osp,pkt);
+
+       /*
+       Check if 'null' deltas should be inserted
+       (only if 'null' flag is in file and
+       releases are being skipped) and set
+       'nulldel' indicator appropriately.
+       */
+       if (Sflags[NULLFLAG - 'a'] && (sp->s_rel > osp->s_rel + 1) &&
+                       !sp->s_br && !sp->s_seq &&
+                       !osp->s_br && !osp->s_seq)
+               nulldel = 1;
+       else
+               nulldel = 0;
+       /*
+       Calculate how many serial numbers are needed.
+       */
+       if (nulldel)
+               ser_inc = sp->s_rel - osp->s_rel;
+       else
+               ser_inc = 1;
+       /*
+       Find serial number of the new delta.
+       */
+       newser = dt.d_serial = maxser(pkt) + ser_inc;
+       /*
+       Find old predecessor's serial number.
+       */
+       opred = sidtoser(osp,pkt);
+       if (nulldel)
+               dt.d_pred = newser - 1; /* set predecessor to 'null' delta */
+       else
+               dt.d_pred = opred;
        dt.d_datetime = Timenow;
        substr(logname(),dt.d_pgmr,0,7);
        dt.d_type = 'D';
@@ -308,6 +341,23 @@
        putline(pkt,Comments);
        putline(pkt,"\n");
        putline(pkt,sprintf(str,CTLSTR,CTLCHAR,EDELTAB));
+       if (nulldel)                    /* insert 'null' deltas */
+               while (--ser_inc) {
+                       putline(pkt,sprintf(str,"%c%c %s/%s/%05u\n",
+                               CTLCHAR, STATS,
+                               "00000", "00000", orig_nlines));
+                       dt.d_sid.s_rel =- 1;
+                       dt.d_serial =- 1;
+                       if (ser_inc != 1)
+                               dt.d_pred =- 1;
+                       else
+                               dt.d_pred = opred;      /* point to old pred */
+                       del_ba(&dt,str);
+                       putline(pkt,str);
+                       putline(pkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
+                       putline(pkt,"AUTO NULL DELTA\n");
+                       putline(pkt,sprintf(str,CTLSTR,CTLCHAR,EDELTAB));
+               }
        return(newser);
 }
 
@@ -381,7 +431,7 @@
        }
        fflush(out);
        fstat(fileno(out),&Statbuf);
-       Szqfile = lsize(Statbuf.i_size0,Statbuf.i_size1);
+       Szqfile = Statbuf.st_size;
        copy(auxf(pkt->p_file,'p'),Pfilename);
        fclose(out);
        fclose(in);
@@ -453,7 +503,7 @@
                case 'd':
                        num_lines = highline - lowline + 1;
                        *type = DEL;
-                       skipline(line,num_lines);
+                       skiplines(line,num_lines);
                        break;
 
                case 'a':
@@ -468,7 +518,7 @@
                        linerange(p,&lowline,&highline);
                        chg_num = highline - lowline + 1;
                        *type = DEL;
-                       skipline(line,num_lines);
+                       skiplines(line,num_lines);
                        break;
                }
        }
Index:  cmd/get.c
--- UNSW-87-record0:sccs4/cmd/get.c     1978-09-07 19:22:13.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/get.c        1981-01-15 00:16:33.000000000 -0500
@@ -1,7 +1,7 @@
 # include      "../hdr/defines.h"
 # include      "../hdr/had.h"
 
-SCCSID(@(#)get 1.11);
+SCCSID(@(#)get.c       4.1);
 USXALLOC();
 
 int    Debug   0;
@@ -126,6 +126,7 @@
        extern char had_dir, had_standinp;
        extern char *Sflags[];
        struct stats stats;
+       char    str[32];
 
        if (setjmp(Fjmp))
                return;
@@ -166,12 +167,19 @@
                Type = Null;
        if (!(HADP || HADG) && access(Gfile,2) == 0)
                fatal(sprintf(Error,"writable `%s' exists (ge4)",Gfile));
+       if (gpkt.p_verbose) {
+               sid_ba(&gpkt.p_gotsid,str);
+               fprintf(gpkt.p_stdout,"%s\n",str);
+       }
        if (HADE) {
+               if (!HADR)
+                       move(&gpkt.p_gotsid,&gpkt.p_reqsid,
+                            sizeof(gpkt.p_reqsid));
                newsid(&gpkt,Sflags[BRCHFLAG - 'a'] && HADB);
                permiss(&gpkt);
                wrtpfile(&gpkt,ilist,elist);
        }
-       setuid(getuid()&0377);
+       setuid(getuid());
        if (HADL)
                gen_lfile(&gpkt);
        if (HADG) {
@@ -370,6 +378,9 @@
 char   Gchgdate[9];
 char   Sid[32];
 char   Mod[16];
+char   Olddir[BUFSIZ];
+char   Pname[BUFSIZ];
+char   Dir[BUFSIZ];
 
 idsetup(pkt)
 register struct packet *pkt;
@@ -381,6 +392,16 @@
        date_ba(&Timenow,Curdate);
        Curtime = &Curdate[9];
        Curdate[8] = 0;
+       copy(pkt->p_file,Dir);
+       dname(Dir);
+       if(curdir(Olddir) != 0)
+               fatal("curdir failed (ge20)");
+       if(chdir(Dir) != 0)
+               fatal("cannot change directory (ge22)");
+       if(curdir(Pname) != 0)
+               fatal("curdir failed (ge21)");
+       if(chdir(Olddir) != 0)
+               fatal("cannot change directory (ge23)");
        makgdate(Curdate,Gdate);
        for (n = maxser(pkt); n; n--)
                if (pkt->p_apply[n].a_code == APPLY)
@@ -485,6 +506,11 @@
                        case 'I':
                                tp = trans(tp,Sid);
                                break;
+                       case 'P':
+                               tp = trans(tp,Pname);
+                               *tp++ = '/';
+                               tp = trans(tp,(sname(pkt->p_file)));
+                               break;
                        case 'F':
                                tp = trans(tp,pkt->p_file);
                                break;
@@ -545,6 +571,8 @@
 {
        if (gpkt.p_file[0])
                unlockit(auxf(gpkt.p_file,'z'),getpid());
+       if (gpkt.p_iop)
+               fclose(gpkt.p_iop);
        xfreeall();
 }
 
@@ -579,9 +607,11 @@
                                (pf.pf_nsid.s_rel == pkt->p_reqsid.s_rel &&
                                pf.pf_nsid.s_lev == pkt->p_reqsid.s_lev &&
                                pf.pf_nsid.s_br == pkt->p_reqsid.s_br &&
-                               pf.pf_nsid.s_seq == pkt->p_reqsid.s_seq))
+                               pf.pf_nsid.s_seq == pkt->p_reqsid.s_seq)) {
+                               fclose(in);
                                fatal(sprintf(Error,"being edited: `%s' (ge17)",
                                        line));
+                               }
                        if (!equal(pf.pf_user,user))
                                fprintf(stderr,"WARNING: being edited: `%s' (ge18)\n",line);
                }
@@ -601,6 +631,8 @@
                fprintf(out," -x%s",exc);
        fprintf(out,"\n");
        fclose(out);
+       if (pkt->p_verbose)
+               fprintf(pkt->p_stdout,"new delta %s\n",str2);
        unlockit(auxf(pkt->p_file,'z'),getpid());
 }
 
@@ -610,7 +642,6 @@
 {
        register struct idel *rdp;
        int n, ser, def;
-       char str[32];
        char *p;
        extern char *Sflags[];
 
@@ -652,10 +683,6 @@
                fatal("nonexistent sid (ge5)");
        rdp = &pkt->p_idel[ser];
        move(&rdp->i_sid, &pkt->p_gotsid, sizeof(pkt->p_gotsid));
-       if (pkt->p_verbose) {
-               sid_ba(&pkt->p_gotsid,str);
-               fprintf(pkt->p_stdout,"%s\n",str);
-       }
        if (def || (pkt->p_reqsid.s_lev == 0 && pkt->p_reqsid.s_rel == pkt->p_gotsid.s_rel))
                move(&pkt->p_gotsid, &pkt->p_reqsid, sizeof(pkt->p_gotsid));
        return(ser);
Index:  cmd/help.c
--- UNSW-87-record0:sccs4/cmd/help.c    1978-09-07 19:22:13.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/help.c       1981-01-15 00:16:36.000000000 -0500
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)help        1.5);
+SCCSID(@(#)help.c      4.1);
 
 /*
        Program to locate helpful info in an ascii file.
@@ -8,15 +8,15 @@
 
        The file to be searched is determined from the argument. If the
        argument does not contain numerics, the search
-       will be attempted on '/usr/lib/help/cmds', with the search key
+       will be attempted on '/usr/local/lib/help/cmds', with the search key
        being the whole argument.
        If the argument begins with non-numerics but contains
        numerics (e.g, zz32) the search will be attempted on
-       '/usr/lib/help/<non-numeric prefix>', (e.g,/usr/lib/help/zz),
+       '/usr/local/lib/help/<non-numeric prefix>', (e.g,/usr/lib/help/zz),
        with the search key being <remainder of arg>, (e.g., 32).
        If the argument is all numeric, or if the file as
        determined above does not exist, the search will be attempted on
-       '/usr/lib/sccs.hf', which is the old help file, with the
+       '/usr/local/lib/sccs.hf', which is the old help file, with the
        search key being the entire argument.
        In no case will more than one search per argument be performed.
 
@@ -39,8 +39,8 @@
 
        If the argument is omitted, the program requests it.
 */
-char   oldfile[]       "/usr/lib/sccs.hf";
-char   helpdir[]       "/usr/lib/help/";
+char   oldfile[]       "/usr/local/lib/sccs.hf";
+char   helpdir[]       "/usr/local/lib/help/";
 char   hfile[64];
 FILE   *iop;
 char   line [512];
Index:  cmd/prs.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/prs.c        1981-01-15 00:21:03.000000000 -0500
@@ -0,0 +1,797 @@
+/*************************************************************************/
+/*                                                                      */
+/*     prs [-d<dataspec>] [-r<sid>] [-c<cutoff>] [-a]                   */
+/*         [-y<reverse-cutoff>] file ...                                */
+/*                                                                      */
+/*************************************************************************/
+
+/*
+       Program to print parts or all of an SCCS file
+       in user supplied format.
+       Arguments to the program may appear in any order
+       and consist of keyletters, which begin with '-',
+       and named files.
+
+       If a direcory is given as an argument, each
+       SCCS file within the directory is processed as if
+       it had been specifically named. If a name of '-'
+       is given, the standard input is read for a list
+       of names of SCCS files to be processed.
+       Non-SCCS files are ignored.
+*/
+
+# include "../hdr/defines.h"
+# include "../hdr/had.h"
+
+SCCSID(@(#)prs.c       4.1);
+
+char   had[26];
+char   Getpgm[]        "/usr/local/get";
+char   Sid[32];
+char   Mod[16];
+char   *Type;
+char   Deltadate[18];
+char   *Deltatime;
+char   tempskel[]      "/tmp/prXXXXXX";        /* used to generate temp
+                                                  file names
+                                               */
+char   untmp[32], uttmp[32], cmtmp[32];
+char   mrtmp[32], bdtmp[32];
+FILE   *UNiop;
+FILE   *UTiop;
+FILE   *CMiop;
+FILE   *MRiop;
+FILE   *BDiop;
+char   line[BUFSIZ];
+int    num_files;
+long   cutoff;
+long   revcut;
+char   *dataspec;
+char   iline[BUFSIZ], xline[BUFSIZ], gline[BUFSIZ];
+char   *maket();
+struct packet  gpkt;
+struct sid     sid;
+struct tm      *Dtime;
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+       register int j;
+       register char *p;
+       char c;
+       extern prs();
+       extern int Fcnt;
+
+       /*
+       Set flags for 'fatal' to issue message, call clean-up
+       routine, and terminate processing.
+       */
+       Fflags = FTLMSG | FTLCLN | FTLEXIT;
+
+
+       /*
+       The following loop processes keyletters and arguments.
+       Note that these are processed only once for each
+       invocation of 'main'.
+       */
+       for (j = 1; j < argc; j++)
+               if (argv[j][0] == '-' && (c = argv[j][1])) {
+                       p = &argv[j][2];
+                       switch (c) {
+
+                       case 'r':       /* delta cutoff */
+                               if (*p) {
+                                       if (invalid(p))
+                                               fatal("invalid sid (co8)");
+                                       sid_ab(p,&sid);
+                               }
+                               break;
+
+                       case 'c':       /* time cutoff */
+                               if (*p && date_ab(p,&cutoff))
+                                       fatal("bad date/time (cm5)");
+                               break;
+
+                       case 'y':       /* reverse time cutoff */
+                               if (*p && date_ab(p,&revcut))
+                                       fatal ("bad date/time (cm5)");
+                               break;
+
+                       case 'a':
+                               if (*p)
+                                       fatal("value after a arg (cm7)");
+                               break;
+                       case 'd':       /* dataspec line */
+                               dataspec = p;
+                               break;
+                       default:
+                               fatal("unknown key letter (cm1)");
+                       }
+
+                       if (had[c - 'a']++)
+                               fatal("key letter twice (cm2)");
+                       argv[j] = 0;
+               }
+               else
+                       num_files++;
+
+       if (num_files == 0)
+               fatal("missing file arg (cm3)");
+
+       if (!HADD)
+               exit(0);
+       if (HADC && HADY)
+               fatal("both 'c' and 'y' keyletters specified (prs2)");
+
+       setsig();
+
+       /*
+       Change flags for 'fatal' so that it will return to this
+       routine (main) instead of terminating processing.
+       */
+       Fflags =& ~FTLEXIT;
+       Fflags =| FTLJMP;
+
+       /*
+       Call 'prs' routine for each file argument.
+       */
+       for (j = 1; j < argc; j++)
+               if (p = argv[j])
+                       do_file(p,prs);
+
+       exit(Fcnt ? 1 : 0);
+}
+
+
+prs(file)
+register       char    *file;
+{
+       int     n;
+       extern  char    had_dir, had_standinp;
+
+       if (setjmp(Fjmp))
+               return;
+       sinit(&gpkt,file,1);    /* init packet and open SCCS file */
+
+       gpkt.p_reqsid.s_rel = sid.s_rel;
+       gpkt.p_reqsid.s_lev = sid.s_lev;
+       gpkt.p_reqsid.s_br = sid.s_br;
+       gpkt.p_reqsid.s_seq = sid.s_seq;
+       gpkt.p_cutoff = cutoff;
+       gpkt.p_reopen = 1;
+
+       /*
+       read delta table entries checking only for format error
+       */
+       deltblchk(&gpkt);
+
+       /*
+       create auxiliary file for User Name Section
+       */
+
+       aux_create(UNiop,untmp,EUSERNAM);
+
+       doflags(&gpkt);
+
+       /*
+       create auxiliary file for the User Text section
+       */
+
+       aux_create(UTiop,uttmp,EUSERTXT);
+
+       /*
+       indicate to 'getline' that EOF is okay
+       */
+       gpkt.p_chkeof = 1;
+
+       /*
+       read body of SCCS file and create temp file for it
+       */
+       while(read_mod(&gpkt))
+               ;
+
+       if (num_files > 1 || had_dir || had_standinp)
+               printf("\n%s:\n",gpkt.p_file);
+       /*
+       Here, file has already been re-opened (by 'getline')
+       */
+       getline(&gpkt);         /* skip over header line */
+
+       /*
+       call dodeltbl to read delta table entries
+       */
+
+       dodeltbl(&gpkt);
+
+       clean_up();
+
+       return;
+}
+
+
+dodeltbl(pkt)
+register struct packet *pkt;
+{
+       int     n;
+       struct  deltab  dt;
+       struct  stats   stats;
+
+       /*
+       Read entire delta table.
+       */
+       while (getstats(pkt,&stats)) {
+               if (getadel(pkt,&dt) != BDELTAB)
+                       fmterr(pkt);
+
+               /*
+               Read rest of delta entry. 
+               */
+               while ((n = getline(pkt)) != NULL)
+                       if (pkt->p_line[0] != CTLCHAR)
+                               break;
+                       else {
+                               switch (pkt->p_line[1]) {
+                               case EDELTAB:
+                                       scanspec(dataspec,&dt,&stats);
+                                       break;
+                               case INCLUDE:
+                                       getit(iline,n);
+                                       continue;
+                               case EXCLUDE:
+                                       getit(xline,n);
+                                       continue;
+                               case IGNORE:
+                                       getit(gline,n);
+                                       continue;
+                               case MRNUM:
+                               case COMMENTS:
+                                       continue;
+                               default:
+                                       fmterr(pkt);
+                               }
+                               break;
+                       }
+               if (n == NULL || pkt->p_line[0] != CTLCHAR)
+                       fmterr(pkt);
+       }
+}
+
+
+/*
+ * The scanspec procedure scans the dataspec searching for ID keywords.
+ * When a keyword is found the value is replaced and printed on the
+ * standard output. Any character that is not an ID keyword is printed
+ * immediately.
+*/
+
+static char    Zkeywd[5]       "@(#)";
+scanspec(spec,dtp,statp)
+char spec[];
+struct deltab  *dtp;
+struct stats   *statp;
+{
+
+       extern  char    *Sflags[];
+       register char *lp;
+       register char   *k;
+       union {
+               char    str[2];
+               short   istr;
+       } u;
+       register        char    c;
+
+       idsetup(&dtp->d_sid,&gpkt,&dtp->d_datetime);
+       for(lp = spec; *lp != 0; lp++) {
+               if(lp[0] == ':' && lp[1] != 0 && lp[2] == ':') {
+                       c = *++lp;
+                       switch (c) {
+                       case 'I':       /* SID */
+                               printf("%s",Sid);
+                               break;
+                       case 'R':       /* Release number */
+                               printf("%u",dtp->d_sid.s_rel);
+                               break;
+                       case 'L':       /* Level number */
+                               printf("%u",dtp->d_sid.s_lev);
+                               break;
+                       case 'B':       /* Branch number */
+                               if (dtp->d_sid.s_br != 0)
+                                       printf("%u",dtp->d_sid.s_br);
+                               break;
+                       case 'S':       /* Sequence number */
+                               if (dtp->d_sid.s_seq != 0)
+                                       printf("%u",dtp->d_sid.s_seq);
+                               break;
+                       case 'D':       /* Date delta created */
+                               printf("%s",Deltadate);
+                               break;
+                       case 'T':       /* Time delta created */
+                               printf("%s",Deltatime);
+                               break;
+                       case 'P':       /* Programmer who created delta */
+                               printf("%s",dtp->d_pgmr);
+                               break;
+                       case 'C':       /* Comments */
+                               break;
+                       case 'Y':       /* Type flag */
+                               printf("%s",Type);
+                               break;
+                       case 'M':       /* Module name */
+                               printf("%s",Mod);
+                               break;
+                       case 'W':       /* Form of what string */
+                               printf("%s",Zkeywd);
+                               printf("%s",Mod);
+                               putchar('\t');
+                               printf("%s",Sid);
+                               break;
+                       case 'A':       /* Form of what string */
+                               printf("%s",Zkeywd);
+                               printf("%s ",Type);
+                               printf("%s ",Mod);
+                               printf("%s",Sid);
+                               printf("%s",Zkeywd);
+                               break;
+                       case 'Z':       /* what string constructor */
+                               printf("%s",Zkeywd);
+                               break;
+                       case 'F':       /* File name */
+                               printf("%s",sname(gpkt.p_file));
+                               break;
+                       default:
+                               putchar(':');
+                               putchar(c);
+                               putchar(':');
+                               break;
+                       }
+                       lp++;
+               }
+               else if(lp[0] == ':' && lp[1] != 0 && lp[2] !=0 && lp[3] == ':') {
+                       if (lp[1] == ':') {
+                               putchar(':');
+                               *lp =+ 2;
+                               continue;
+                       }
+                       u.str[1] = *++lp;
+                       u.str[0] = *++lp;
+                       switch (u.istr) {
+                       case 'Dl':      /* Delta line statistics */
+                               printf("%05d",statp->s_ins);
+                               putchar('/');
+                               printf("%05d",statp->s_del);
+                               putchar('/');
+                               printf("%05d",statp->s_unc);
+                               break;
+                       case 'Li':      /* Lines inserted by delta */
+                               printf("%05d",statp->s_ins);
+                               break;
+                       case 'Ld':      /* Lines deleted by delta */
+                               printf("%05d",statp->s_del);
+                               break;
+                       case 'Lu':      /* Lines unchanged by delta */
+                               printf("%05d",statp->s_unc);
+                               break;
+                       case 'DT':      /* Delta type */
+                               printf("%c",dtp->d_type);
+                               break;
+                       case 'Dy':      /* Year delta created */
+                               printf("%02d",Dtime->tm_year);
+                               break;
+                       case 'Dm':      /* Month delta created */
+                               printf("%02d",(Dtime->tm_mon + 1));
+                               break;
+                       case 'Dd':      /* Day delta created */
+                               printf("%02d",Dtime->tm_mday);
+                               break;
+                       case 'Th':      /* Hour delta created */
+                               printf("%02d",Dtime->tm_hour);
+                               break;
+                       case 'Tm':      /* Minutes delta created */
+                               printf("%02d",Dtime->tm_min);
+                               break;
+                       case 'Ts':      /* Seconds delta created */
+                               printf("%02d",Dtime->tm_sec);
+                               break;
+                       case 'DS':      /* Delta sequence number */
+                               printf("%d",dtp->d_serial);
+                               break;
+                       case 'DP':      /* Predecessor delta sequence number */
+                               printf("%d",dtp->d_pred);
+                               break;
+                       case 'DI':      /* Deltas included,excluded,ignored */
+                               printf("%s",iline);
+                               putchar('/');
+                               printf("%s",xline);
+                               putchar('/');
+                               printf("%s",gline);
+                               break;
+                       case 'Di':      /* Deltas included */
+                               printf("%s",iline);
+                               break;
+                       case 'Dx':      /* Deltas excluded */
+                               printf("%s",xline);
+                               break;
+                       case 'Dg':      /* Deltas ignored */
+                               printf("%s",gline);
+                               break;
+                       case 'MR':      /* MR numbers */
+                               break;
+                       case 'UN':      /* User names */
+                               printfile(untmp);
+                               break;
+                       case 'MF':      /* MR validation flag */
+                               if (Sflags[VALFLAG - 'a'])
+                                       printf("yes");
+                               else printf("no");
+                               break;
+                       case 'MP':      /* MR validation program */
+                               if (!(k = Sflags[VALFLAG - 'a']))
+                                       printf("none");
+                               else printf("%s",k);
+                               break;
+                       case 'KF':      /* Keyword err/warn flag */
+                               if (Sflags[IDFLAG - 'a'])
+                                       printf("yes");
+                               else printf("no");
+                               break;
+                       case 'BF':      /* Branch flag */
+                               if (Sflags[BRCHFLAG - 'a'])
+                                       printf("yes");
+                               else printf("no");
+                               break;
+                       case 'FB':      /* Floor Boundry */
+                               if (k = Sflags[FLORFLAG - 'a'])
+                                       printf("%s",k);
+                               else printf("none");
+                               break;
+                       case 'CB':      /* Ceiling Boundry */
+                               if (k = Sflags[CEILFLAG - 'a'])
+                                       printf("%s",k);
+                               else printf("none");
+                               break;
+                       case 'Ds':      /* Default SID */
+                               if (k = Sflags[DEFTFLAG - 'a'])
+                                       printf("%s",k);
+                               else printf("none");
+                               break;
+                       case 'ND':      /* Null delta */
+                               if (Sflags[NULLFLAG - 'a'])
+                                       printf("yes");
+                               else printf("no");
+                               break;
+                       case 'FD':      /* File descriptive text */
+                               printfile(uttmp);
+                               break;
+                       case 'BD':      /* Entire file body */
+                               printfile(bdtmp);
+                               break;
+                       case 'GB':      /* Gotten body from 'get' */
+                               getbody(&dtp->d_sid,&gpkt);
+                               break;
+                       default:
+                               putchar(':');
+                               printf("%c",u.istr);
+                               putchar(':');
+                               break;
+                       }
+                       lp++;
+               }
+               else {
+                       c = *lp;
+                       if (c == '\\') {
+                               switch(*++lp) {
+                               case 'n':       /* for newline */
+                                       putchar('\n');
+                                       break;
+                               case ':':       /* for wanted colon */
+                                       putchar(':');
+                                       break;
+                               case 't':       /* for tab */
+                                       putchar('\t');
+                                       break;
+                               case 'b':       /* for backspace */
+                                       putchar('\b');
+                                       break;
+                               case 'r':       /* for carriage return */
+                                       putchar('\r');
+                                       break;
+                               case 'f':       /* for form feed */
+                                       putchar('\f');
+                                       break;
+                               case '\\':      /* for backslash */
+                                       putchar('\\');
+                                       break;
+                               case '\'':      /* for single quote */
+                                       putchar('\'');
+                                       break;
+                               default:        /* unknown case */
+                                       putchar('\\');
+                                       putchar(*lp);
+                                       break;
+                               }
+                       }
+                       else putchar(*lp);
+               }
+       }
+       /*
+       zero out first char of global string lines in case
+       a value is not gotten in next delta table entry
+       */
+       iline[0] = xline[0] = gline[0] = 0;
+       putchar('\n');
+       return;
+}
+
+
+clean_up()
+{
+       unlink(untmp);
+       unlink(uttmp);
+       unlink(bdtmp);
+       if (gpkt.p_iop)
+               fclose(gpkt.p_iop);
+}
+
+
+/* This function takes as it's argument the SID inputed and determines
+ * whether or not it is valid (e. g. not ambiguous or illegal).
+*/
+invalid(i_sid)
+register char  *i_sid;
+{
+       register int count;
+       register int digits;
+       count = digits = 0;
+       if (*i_sid == '0' || *i_sid == '.')
+               return (1);
+       i_sid++;
+       digits++;
+       while (*i_sid != '\0') {
+               if (*i_sid++ == '.') {
+                       digits = 0;
+                       count++;
+                       if (*i_sid == '0' || *i_sid == '.')
+                               return (1);
+               }
+               digits++;
+               if (digits > 5)
+                       return (1);
+       }
+       if (*(--i_sid) == '.' )
+               return (1);
+       if (count == 1 || count == 3)
+               return (0);
+       return (1);
+}
+
+
+deltblchk(pkt)
+register struct packet *pkt;
+{
+       int     n;
+       struct  deltab  dt;
+       struct  stats   stats;
+
+       /*
+       Read entire delta table.
+       */
+       while (getstats(pkt,&stats)) {
+               if (getadel(pkt,&dt) != BDELTAB)
+                       fmterr(pkt);
+
+               /*
+               Read rest of delta entry. 
+               */
+               while ((n = getline(pkt)) != NULL)
+                       if (pkt->p_line[0] != CTLCHAR)
+                               break;
+                       else {
+                               switch (pkt->p_line[1]) {
+                               case EDELTAB:
+                                       break;
+                               case INCLUDE:
+                               case EXCLUDE:
+                               case IGNORE:
+                               case MRNUM:
+                               case COMMENTS:
+                                       continue;
+                               default:
+                                       fmterr(pkt);
+                               }
+                               break;
+                       }
+               if (n == NULL || pkt->p_line[0] != CTLCHAR)
+                       fmterr(pkt);
+       }
+       if (pkt->p_line[1] != BUSERNAM)
+               fmterr(pkt);
+}
+
+
+getstats(pkt,statp)
+register struct packet *pkt;
+register struct stats *statp;
+{
+       register char *p;
+
+       p = pkt->p_line;
+       if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
+               return(0);
+       NONBLANK(p);
+       p = satoi(p,&statp->s_ins);
+       p = satoi(++p,&statp->s_del);
+       satoi(++p,&statp->s_unc);
+       return(1);
+}
+
+
+getadel(pkt,dt)
+register struct packet *pkt;
+register struct deltab *dt;
+{
+       if (getline(pkt) == NULL)
+               fmterr(pkt);
+       return(del_ab(pkt->p_line,dt,pkt));
+}
+
+
+
+char   *maket(file)
+char   *file;
+{
+       FILE *iop;
+
+       copy(tempskel,file);
+       iop = xfcreat(mktemp(file),0644);
+
+       return(iop);
+}
+
+
+printfile(file)
+register       char    *file;
+{
+       register        char    *p;
+       FILE    *iop;
+
+       iop = xfopen(file,0);
+       while ((p = fgets(line,sizeof(line),iop)) != NULL)
+               printf("%s",p);
+       fclose(iop);
+}
+
+
+read_mod(pkt)
+register struct packet *pkt;
+{
+       register char *p;
+       int ser;
+       int iord;
+       register struct apply *ap;
+
+       BDiop = maket(bdtmp);
+       while (getline(pkt) != NULL) {
+               p = pkt->p_line;
+               fputs(p,BDiop);
+               if (*p++ != CTLCHAR)
+                       continue;
+               else {
+                       if (!((iord = *p++) == INS || iord == DEL || iord == END))
+                               fmterr(pkt);
+                       NONBLANK(p);
+                       satoi(p,&ser);
+                       if (iord == END)
+                               remq(pkt,ser);
+                       else if ((ap = &pkt->p_apply[ser])->a_code == APPLY)
+                               addq(pkt,ser,iord == INS ? YES : NO,iord,ap->a_reason & USER);
+                       else
+                               addq(pkt,ser,iord == INS ? NO : NULL,iord,ap->a_reason & USER);
+               }
+       }
+       fclose(BDiop);
+       if (pkt->p_q)
+               fatal("premature eof (co5)");
+       return(0);
+}
+
+
+getbody(gsid,pkt)
+struct sid     *gsid;
+struct packet *pkt;
+{
+       int     i;
+       int     status;
+       extern  char    Getpgm[];
+       char    str[128];
+       char    rarg[20];
+       char    filearg[80];
+
+       sid_ba(gsid,str);
+       sprintf(rarg,"%s",str);
+       sprintf(filearg,"%s",pkt->p_file);
+       /*
+       fork here so 'getbody' can execute 'get' to
+       print out gotten body :GB:
+       */
+       if ((i = fork()) < 0)
+               fatal("cannot fork, try again");
+       if (i = 0) {
+               /*
+               perform 'get' and redirect output
+               to standard output
+               */
+               execl(Getpgm,Getpgm,"-s","-p","-r",rarg,filearg,0);
+               fatal(sprintf(Error,"cannot execute '%s'",Getpgm));
+       }
+       else {
+               wait(&status);
+               return;
+       }
+}
+
+
+getit(str,cp)
+register       char    *str, *cp;
+{
+       cp =+ 2;
+       NONBLANK(cp);
+       cp[length(cp) - 1] = '\0';
+       sprintf(str,"%s",cp);
+}
+
+
+aux_create(iop,file,delchar)
+FILE   *iop;
+char   *file;
+char   delchar;
+{
+
+       int     n;
+       int     text;
+       /*
+       create auxiliary file for the named section
+       */
+
+       text = 0;
+       iop = maket(file);
+       while ((n = getline(&gpkt)) != NULL && gpkt.p_line[0] != CTLCHAR) {
+               text = 1;
+               fputs(n,iop);
+       }
+       /*
+       check to see that delimiter found is correct
+       */
+       if (n == NULL || gpkt.p_line[0] != CTLCHAR || gpkt.p_line[1] != delchar)
+               fmterr(&gpkt);
+       if (!text)
+               fprintf(iop,"No entries\n");
+       fclose(iop);
+}
+
+
+idsetup(gsid,pkt,bdate)
+struct sid     *gsid;
+struct packet  *pkt;
+long   *bdate;
+{
+
+       register        char    *p;
+       extern  struct  tm      *localtime();
+
+       date_ba(bdate,Deltadate);
+
+       Deltatime = &Deltadate[9];
+       Deltadate[8] = 0;
+
+       sid_ba(gsid,Sid);
+
+       Dtime = localtime(bdate);
+
+       if (p = Sflags[MODFLAG - 'a'])
+               copy(p,Mod);
+       else sprintf(Mod,"%s",sname(pkt->p_file));
+
+       if (!(Type = Sflags[TYPEFLAG - 'a']))
+               Type = "none";
+}
Index:  cmd/prt.c
--- UNSW-87-record0:sccs4/cmd/prt.c     1978-09-07 19:22:14.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/prt.c        1981-01-15 00:16:37.000000000 -0500
@@ -1,7 +1,7 @@
 # include "../hdr/defines.h"
 # include "../hdr/had.h"
 
-SCCSID(@(#)prt 1.9);
+SCCSID(@(#)prt.c       4.1);
 
 /*
        Program to print parts or all of an SCCS file.
@@ -18,7 +18,6 @@
 */
 
 # define NOEOF 0
-# define EOF   1
 # define BLANK(p)      while (!(*p == ' ' || *p == '\t')) p++;
 
 char had[26];
@@ -52,7 +51,7 @@
                        "",
                        "",
                        "module",
-                       "",
+                       "null delta",
                        "",
                        "",
                        "",
Index:  cmd/rmchg.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/rmchg.c      1981-01-15 00:16:39.000000000 -0500
@@ -0,0 +1,392 @@
+# include "../hdr/defines.h"
+# include "../hdr/had.h"
+
+SCCSID(@(#)rmchg.c     4.1);
+
+/*
+       Program to remove a specified delta from an SCCS file,
+       when invoked as 'rmdel',
+       or to change the MRs and/or comments of a specified delta,
+       when invoked as 'chghist'.
+       (The program has two links to it, one called 'rmdel', the
+       other 'chghist'.)
+
+       The delta to be removed (or whose MRs and/or comments
+       are to be changed) is specified via the
+       r argument, in the form of an SID.
+
+       If the delta is to be removed, it must be the most recent one
+       in its branch in the delta tree (a so-called 'leaf' delta).
+       For either function, the delta being processed must not
+       have any 'delivered' MRs, and the user must have basically
+       the same permissions as are required to make deltas.
+
+       If a directory is given as an argument, each SCCS file
+       within the directory will be processed as if it had been
+       specifically named. If a name of '-' is given, the standard
+       input will be read for a list of names of SCCS files to be
+       processed. Non SCCS files are ignored.
+*/
+
+# define COPY 0
+# define NOCOPY 1
+
+struct sid sid;
+int num_files;
+char had[26];
+char D_type;
+int D_serial;
+
+main(argc,argv)
+int argc;
+char *argv[];
+{
+       register int i;
+       register char *p;
+       char c;
+       extern rmchg();
+       extern int Fcnt;
+
+       /*
+       Set flags for 'fatal' to issue message, call clean-up
+       routine, and terminate processing.
+       */
+       Fflags = FTLMSG | FTLCLN | FTLEXIT;
+
+       for(i=1; i<argc; i++)
+               if(argv[i][0] == '-' && (c = argv[i][1])) {
+                       p = &argv[i][2];
+                       switch (c) {
+
+                       case 'r':
+                               if (!(*p))
+                                       fatal("r has no sid (rc11)");
+                               chksid(sid_ab(p,&sid),&sid);
+                               break;
+                       default:
+                               fatal("unknown key letter (cm1)");
+                       }
+
+                       if (had[c - 'a']++)
+                               fatal("key letter twice (cm2)");
+                       argv[i] = 0;
+               }
+               else
+                       num_files++;
+
+       if(num_files == 0)
+               fatal("missing file arg (cm3)");
+
+       if (*(p = sname(argv[0])) == 'n')
+               p++;
+       if (equal(p,"rmdel"))
+               D_type = 'R';           /* invoked as 'rmdel' */
+       else if (equal(p,"chghist"))
+               D_type = 'D';           /* invoked as 'chghist' */
+       else
+               fatal("bad invocation (rc10)");
+
+       setsig();
+
+       /*
+       Change flags for 'fatal' so that it will return to this
+       routine (main) instead of terminating processing.
+       */
+       Fflags =& ~FTLEXIT;
+       Fflags =| FTLJMP;
+
+       /*
+       Call 'rmchg' routine for each file argument.
+       */
+       for (i=1; i<argc; i++)
+               if (p = argv[i])
+                       do_file(p,rmchg);
+
+       exit(Fcnt ? 1 : 0);
+}
+
+
+/*
+       Routine that actually causes processing of the delta.
+       Processing on the file takes place on a
+       temporary copy of the SCCS file (the x-file).
+       The name of the x-file is the same as that of the
+       s-file (SCCS file) with the 's.' replaced by 'x.'.
+       At end of processing, the s-file is removed
+       and the x-file is renamed with the name of the old s-file.
+
+       This routine makes use of the z-file to lock out simultaneous
+       updates to the SCCS file by more than one user.
+*/
+
+struct packet gpkt;    /* see file s.h */
+char line[BUFSIZ];
+char *Mrs;
+char *Comments;
+int Domrs;
+
+USXALLOC();            /* defines alloc() and free() */
+
+rmchg(file)
+char *file;
+{
+       static int first_time 1;
+       struct deltab dt;       /* see file s.defines.h */
+       struct stats stats;     /* see file s.defines.h */
+       extern char *Sflags[];
+       int n;
+       char *p, *cp;
+       int keep;
+       extern char Pgmr[8];
+       int fowner, downer, user;
+
+       if (setjmp(Fjmp))       /* set up to return here from 'fatal' */
+               return;         /* and return to caller of rmchg */
+
+       if (!HADR)
+               fatal("missing r (rc1)");
+
+       if (D_type == 'D' && first_time) {
+               first_time = 0;
+               dohist(file);
+       }
+
+       if (!exists(file))
+               fatal(sprintf(Error,"file %s does not exist (rc2)",file));
+
+       /*
+       Lock out any other user who may be trying to process
+       the same file.
+       */
+       if (lockit(auxf(file,'z'),2,getpid()))
+               fatal("cannot create lock file (cm4)");
+
+       sinit(&gpkt,file,1);    /* initialize packet and open s-file */
+
+       /*
+       Flag for 'putline' routine to tell it to open x-file
+       and allow writing on it.
+       */
+       gpkt.p_upd = 1;
+
+       /*
+       Save requested SID for later checking of
+       permissions (by 'permiss').
+       */
+       move(&sid,&gpkt.p_reqsid,sizeof(gpkt.p_reqsid));
+
+       /*
+       Now read-in delta table. The 'dodelt' routine
+       will read the table and change the delta entry of the
+       requested SID to be of type 'R' if this is
+       being executed as 'rmdel'; otherwise, for 'chghist', only
+       the MR and comments sections will be changed 
+       (by 'escdodelt', called by 'dodelt').
+       */
+       if (dodelt(&gpkt,&stats,&sid,D_type) == 0)
+               fmterr(&gpkt);
+
+       /*
+       Get serial number of requested SID from
+       delta table just processed.
+       */
+       D_serial = sidtoser(&gpkt.p_reqsid,&gpkt);
+
+       /*
+       If SID has not been zeroed (by 'dodelt'),
+       SID was not found in file.
+       */
+       if (sid.s_rel != 0)
+               fatal("nonexistent sid (rc3)");
+       /*
+       Replace 'sid' with original 'sid'
+       requested.
+       */
+       move(&gpkt.p_reqsid,&sid,sizeof(gpkt.p_reqsid));
+
+       /*
+       Now check permissions.
+       */
+       finduser(&gpkt);
+       doflags(&gpkt);
+       permiss(&gpkt);
+
+       /*
+       Check that user is either owner of file or
+       directory, or is one who made the delta.
+       */
+       fstat(fileno(gpkt.p_iop),&Statbuf);
+       fowner = Statbuf.st_uid & 0377;
+       copy(gpkt.p_file,line);         /* temporary for dname() */
+       if (stat(dname(line),&Statbuf))
+               downer = -1;
+       else
+               downer = Statbuf.st_uid & 0377;
+       user = getuid() & 0377;
+       if (user != fowner || user != downer)
+               if (!equal(Pgmr,logname()))
+                       fatal(sprintf(Error,
+                               "you are neither owner nor '%s' (rc4)",Pgmr));
+
+       /*
+       For 'rmdel', check that delta being removed is a
+       'leaf' delta, and if ok,
+       process the body.
+       */
+       if (D_type == 'R') {
+               for (n = maxser(&gpkt); n > D_serial; n--) {
+                       p = &gpkt.p_idel[n];
+                       if (p->i_pred == D_serial)
+                               fatal("not a 'leaf' delta (rc5)");
+               }
+
+               /*
+                  For 'rmdel' check that the sid requested is
+                  not contained in p-file, should a p-file
+                  exist.
+               */
+
+               if (exists(auxf(gpkt.p_file,'p')))
+                       rdpfile(&gpkt,&sid);
+
+               flushto(&gpkt,EUSERTXT,COPY);
+
+               keep = YES;
+               gpkt.p_chkeof = 1;              /* set EOF is ok */
+               while ((p = getline(&gpkt)) != NULL) {
+                       if (*p++ == CTLCHAR) {
+                               cp = p++;
+                               NONBLANK(p);
+                               /*
+                               Convert serial number to binary.
+                               */
+                               if (*(p = satoi(p,&n)) != '\n')
+                                       fmterr(&gpkt);
+                               if (n == D_serial) {
+                                       gpkt.p_wrttn = 1;
+                                       if (*cp == INS)
+                                               keep = NO;
+                                       else
+                                               keep = YES;
+                               }
+                       }
+                       else
+                               if (keep == NO)
+                                       gpkt.p_wrttn = 1;
+               }
+       }
+       else {
+               /*
+               This is for invocation as 'chghist'.
+               Check MRs.
+               */
+               if (Mrs) {
+                       if (!(p = Sflags[VALFLAG - 'a']))
+                               fatal("MRs not allowed (rc6)");
+                       if (*p && valmrs(&gpkt,p))
+                               fatal("inavlid MRs (rc7)");
+               }
+               else
+                       if (Sflags[VALFLAG - 'a'])
+                               fatal("MRs required (rc8)");
+
+               /*
+               Indicate that EOF at this point is ok, and
+               flush rest of s-file to x-file.
+               */
+               gpkt.p_chkeof = 1;
+               while (getline(&gpkt))
+                       ;
+       }
+
+       flushline(&gpkt,0);
+
+       /*
+       Delete old s-file, change x-file name to s-file.
+       */
+       rename(auxf(&gpkt,'x'),&gpkt);
+
+       clean_up();
+}
+
+
+escdodelt(pkt)
+struct packet *pkt;
+{
+       extern int First_esc;
+       char *p;
+       extern long Timenow;
+
+       if (D_type == 'D' && First_esc) {       /* chghist, first time */
+               First_esc = 0;
+               if (Mrs)
+                       putmrs(pkt);
+
+               putline(pkt,sprintf(line,"%c%c ",CTLCHAR,COMMENTS));
+               putline(pkt,Comments);
+               putline(pkt,"\n");
+               putline(pkt,sprintf(line,"%c%c ",CTLCHAR,COMMENTS));
+               putline(pkt,"*** CHANGED *** ");
+               date_ba(&Timenow,line);         /* get date and time */
+               putline(pkt,line);
+               putline(pkt,sprintf(line," %s\n",logname()));
+       }
+
+       if (pkt->p_line[1] == MRNUM) {
+               p = &pkt->p_line;
+               while (*p)
+                       p++;
+               if (*(p - 2) == DELIVER)
+                       fatal("delta specified has delivered MR (rc9)");
+
+               if (D_type == 'D')              /* turn MRs into comments */
+                       pkt->p_line[1] = COMMENTS;
+       }
+}
+
+
+putmrs(pkt)
+struct packet *pkt;
+{
+       register char **argv;
+       char str[64];
+       extern char *Varg[];
+
+       for (argv = &Varg[VSTART]; *argv; argv++)
+               putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
+}
+
+
+clean_up()
+{
+       xrm(&gpkt);
+       if (gpkt.p_file[0])
+               unlockit(auxf(gpkt.p_file,'z'),getpid());
+       if (exists(auxf(gpkt.p_file,'x')))
+               xunlink(auxf(gpkt.p_file,'x'));
+       xfreeall();
+}
+
+
+rdpfile(pkt,sp)
+register struct packet *pkt;
+struct sid *sp;
+{
+       struct pfile pf;
+       char line[BUFSIZ];
+       FILE *in;
+
+       in = xfopen(auxf(pkt->p_file,'p'),0);
+       while (fgets(line,sizeof(line),in) != NULL) {
+               pf_ab(line,&pf,1);
+               if (sp->s_rel == pf.pf_gsid.s_rel &&
+                       sp->s_lev == pf.pf_gsid.s_lev &&
+                       sp->s_br == pf.pf_gsid.s_br &&
+                       sp->s_seq == pf.pf_gsid.s_seq) {
+                               fclose(in);
+                               fatal("being edited -- sid is in p-file (rc12)");
+               }
+       }
+       fclose(in);
+       return;
+}
Index:  cmd/sccsdiff
--- UNSW-87-record0:sccs4/cmd/sccsdiff  1978-09-07 19:22:15.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/sccsdiff     1990-04-10 22:50:11.000000000 -0400
@@ -1,41 +1,36 @@
-: sccsdiff 1.2
-onintr intr
-goto start
-: intr
-rm -f /tmp/get$$ >/dev/null
-exit 1
-
-
-DESCRIPTION:
-       Run bdiff on two versions of a set of SCCS files
-       $1 and $2 are two (old/new) SCCS get specifiers (-r... or -c...)
-       if $3 begins with a "-" it is taken to be an argument for pr (e.g. -l84)
-       $3 $4 ... are SCCS files which are gotten.
-
-
-: start
-if $n -lt 3 then
+: sccsdiff 2.2
+: DESCRIPTION:
+:      Run bdiff on two versions of a set of SCCS files.  ${1}  and  ${2}
+:      are two "(" old/new ")" SCCS get specifiers "(" -r... or -c...")".
+:
+:      If ${3} begins with a "-" it is taken to be an  argument  for  pr
+:      "(" e.g. -l84 ")", ${3} ${4} ... are SCCS files which are gotten.
+:
+trap "rm -f /tmp/get$$  > /dev/null; exit 1" 0 1 2 3 13 14 15
+if [ ${#} -lt 3 ]
+then
        echo "Usage: sccsdiff -r<old> -r<new> [pr flags] sccsfile ..."
        exit 1
-endif
-= a "$1"
+fi
+a="${1}"
 shift
-= b "$1"
+b="${1}"
 shift
-
-expr substr "$1" 1 1 ^ = c
-if "x$c" = x- then
-       = c "$1"
+c="`expr substr "${1}" 1 1`"
+if [ "x${c}" = x- ]
+then
+       c="${1}"
        shift
 else
-       = c " "
-endif
-
-while $1
-       get -s -p -k $a $1 >/tmp/get$$
-       if $r -eq 0 then
-          get -s -p -k $b $1 ^ bdiff /tmp/get$$ - ^ pr $c -h "$1: $a vs. $b"
-       endif
+       c=" "
+fi
+while [ ${1} ]
+do
+       get -s -p -k ${a} ${1}  > /tmp/get$$
+       if [ ${?} -eq 0 ]
+       then
+       get -s -p -k ${b} ${1} ^ bdiff /tmp/get$$ - ^ pr ${c} -h "${1}: ${a} vs. ${b}"
+       fi
        shift
-end
+done
 rm /tmp/get$$
Index:  cmd/scv.c
--- UNSW-87-record0:sccs4/cmd/scv.c     1978-09-07 19:22:17.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/scv.c        1981-01-15 00:21:07.000000000 -0500
@@ -11,51 +11,57 @@
        directory "mysccsdir".
 */
 # include      "../hdr/defines.h"
-# include      <dir.h>
+# include      "dir.h"
+
+SCCSID(@(#)scv.c       4.2);
 
 
 /*
-       Release 3 SCCS File Structures  (1.8  77/06/13 13:44:39)
+       Release 3 SCCS File Structures  (2.1  78/06/05 17:31:17)
        See osccsfile(V).
 */
 
 struct Header {
-       int  Hmagicno;
+       short  Hmagicno;
        char Htype[10];
        char Hpers[14];
        char Hdesc[100];
-       int  Hfloor;
-       int  Hceil;
-       int  Hsw[5];
-       int  Hrdef;
+       short  Hfloor;
+       short  Hceil;
+       short  Hsw[5];
+       short  Hrdef;
        char Hulist[32];
        char Hexpand[50];
-       int  Hash;
+       short  Hash;
 };
 #define MAGICNO (7)
 #define HASHADDR (226)
 
 
 struct Reltab {
-       int  Rrel;
-       int  Rlevs;
+       short  Rrel;
+       short  Rlevs;
 };
 
 
 struct Deltab {
-       int  Drel;
-       int  Dlev;
+       short  Drel;
+       short  Dlev;
        char Dtype;     /*'D': delta,'P','U': non-prop,'I': incl,'E': excl */
        char Dfill;     /* Used to be option letter */
-       long  Ddatetime;
+/* compiler once forced unfortunate alignment here.
+/* also, fp-11c high/low long goof strikes again.
+/*     long  Ddatetime;
+*/
+       short Ddthi,Ddtlo;
        char Dpgmr[8];
        char Dhist[200];
 };
 
 
 struct Control {
-       int  Crel;
-       int  Clev;
+       short  Crel;
+       short  Clev;
        char Cctl;      /* -11: ins, -12: del, -13: end */
 };
 #define SIZEOFCONTROL (5)
@@ -74,16 +80,16 @@
        getl and getr.
 */
 struct Ibufr {
-       int  Ifildes;
+       short  Ifildes;
        char *Irecptr;
        char *Iend;
        char Ibuff1[256];
        char Ibuff2[512];
        char Ibuff3[2];
-       int  Ilen;
-       int  Ihflag;
-       int  Ihcnt;
-       int  Ihtot;
+       short  Ilen;
+       short  Ihflag;
+       short  Ihcnt;
+       short  Ihtot;
 };
 
 
@@ -92,18 +98,18 @@
        putr, flshr and buflsh.
 */
 struct Obufr {
-       int  Ofildes;
+       short  Ofildes;
        char *Orecptr;
        char *Oend;
        char Obuff1[512];
-       int  Ohflag;
-       int  Ohcnt;
+       short  Ohflag;
+       short  Ohcnt;
 };
 
 
 /*
  * structure to access an
- * integer in bytes
+ * shorteger in bytes
  */
 struct
 {
@@ -113,20 +119,20 @@
 
 
 /*
- * structure to access an integer
+ * structure to access an shorteger
  */
 struct
 {
-       int     integ;
+       short   shorteg;
 };
 
 
 /*
- * structure to access a long as integers
+ * structure to access a long as shortegers
  */
 struct {
-       int     hiword;
-       int     loword;
+       short   hiword;
+       short   loword;
 };
 
 
@@ -134,23 +140,23 @@
        Structure for referencing pieces of localtime().
 */
 struct Time {
-       int     Tseconds;
-       int     Tminutes;
-       int     Thours;
-       int     Tday_month;
-       int     Tmonth;
-       int     Tyear;
-       int     Tday_week;
-       int     Tday_year;
-       int     Tflag;
+       short   Tseconds;
+       short   Tminutes;
+       short   Thours;
+       short   Tday_month;
+       short   Tmonth;
+       short   Tyear;
+       short   Tday_week;
+       short   Tday_year;
+       short   Tflag;
 };
 /*
-       SCCS Internal Structures (used by get and delta).     (1.8)
+       SCCS Internal Structures (used by get and delta).     (2.1)
 */
 
 struct Apply {
-       int    Adt;             /* pseudo date-time */
-       int    Acode;           /* APPLY, NOAPPLY or EMPTY */
+       short    Adt;           /* pseudo date-time */
+       short    Acode;         /* APPLY, NOAPPLY or EMPTY */
 };
 #define APPLY    (1)
 #define NOAPPLY  (-1)
@@ -159,14 +165,13 @@
 
 struct Queue {
        struct Queue *Qnext;
-       int    Qrel;            /* release */
-       int    Qlev;            /* level */
-       int    Qdt;             /* pseudo date-time */
-       int    Qkeep;           /* keep switch setting */
+       short    Qrel;          /* release */
+       short    Qlev;          /* level */
+       short    Qdt;           /* pseudo date-time */
+       short    Qkeep;         /* keep switch setting */
 };
 #define YES     (1)
 #define NO     (-1)
-#define NULL    (0)
 
 #define SIZEOFPfile (50)
 
@@ -179,14 +184,14 @@
                        This is because the release and level together
                        are treated as a long.
 */
-       int     Prel;           /* specified release (-1 = not spec.) */
-       int     Plev;           /* specified level (-1 = not spec.)*/
+       short   Prel;           /* specified release (-1 = not spec.) */
+       short   Plev;           /* specified level (-1 = not spec.)*/
        char    Pverbose;       /* verbose flags (see #define's below) */
        char    Pupd;           /* update flag (!0 = update mode) */
        long    Pcutoff;        /* specified cutoff date-time */
        struct  Header  Phdr;   /* header from module */
-       int     Plnno;          /* line number of current line */
-       int     Precno;         /* record number of current rec */
+       short   Plnno;          /* line number of current line */
+       short   Precno;         /* record number of current rec */
        char    Pwrttn;         /* written flag (!0 = written) */
        char    Pkeep;          /* keep switch for readmod() */
        struct  Apply **Papply; /* ptr to apply array */
@@ -196,8 +201,8 @@
        char    *Plfile;        /* 0 = no l-file; else ptr to l arg */
        char    Punack;         /* !0 if unacknowledged non-prop deltas */
        char    Pnoprop;        /* !0 if new delta is to be non-prop */
-       int     Pirel;          /* rel which inserted current rec */
-       int     Pilev;          /* lev which inserted current rec */
+       short   Pirel;          /* rel which inserted current rec */
+       short   Pilev;          /* lev which inserted current rec */
 };
 /*
        Masks for Pverbose
@@ -213,7 +218,6 @@
 /*
        size of login name
 */
-# define SZLNAM        (7)
 
 
 USXALLOC();
@@ -221,10 +225,10 @@
 main(argc,argv)
 char **argv;
 {
-       register int i;
+       register short i;
        register char *p;
        extern conv();
-       extern int Fcnt;
+       extern short Fcnt;
 
        setsig();
        Fflags = FTLMSG | FTLCLN | FTLJMP;
@@ -243,11 +247,11 @@
        struct Packet opkt;
        struct deltab *dt;
        char **hists;
-       int **rlp;
+       short **rlp;
        char statstr[32];
-       int ndels;
+       short ndels;
        char *line;
-       register int n;
+       short n;
        char *p;
 
        if (setjmp(Fjmp))
@@ -306,12 +310,14 @@
                free(hists[n]);
        free(hists);
        free(dt);
+/* [compiler bug, ignore this for now ]
        if (rlp) {
-               for (n = *rlp; n; n--)
+               for (n = (short) (*rlp); n; n--)
                        if (rlp[n])
                                free(rlp[n]);
                free(rlp);
        }
+*/
        rename(auxf(npkt.p_file,'x'),npkt.p_file);
        xrm(&npkt);
 }
@@ -331,15 +337,15 @@
 
 fixup(dt,ndels,rlp)
 struct deltab *dt;
-int ndels;
-int **rlp;
+short ndels;
+short **rlp;
 {
-       int m, n;
-       int maxr;
-       int seqcnt;
-       int pred;
+       short m, n;
+       short maxr;
+       short seqcnt;
+       short pred;
        register struct deltab *p1, *p2;
-       register int *brp;
+       register short *brp;
 
        for (m = ndels; m; m--) {
                p1 = &dt[m];
@@ -398,7 +404,7 @@
 struct names {
        struct  names   *n_next;
        char    n_name[SZLNAM];
-       int     n_uid;
+       short   n_uid;
 };
 
 struct names *names;
@@ -407,7 +413,7 @@
 register char *up;
 struct packet *pkt;
 {
-       int i, j;
+       short i, j;
        register char mask, c;
        char *p;
        char str[16];
@@ -425,7 +431,7 @@
 
 
 getlnam(uid)
-int uid;
+short uid;
 {
        char str[128];
        register struct names *cur, *prev;
@@ -451,7 +457,7 @@
 
 /*
        Routine to process the module header. All that's necessary is
-       to slide it into the packet.
+       to slide it shorto the packet.
 */
 
 dohead(pkt)
@@ -468,10 +474,10 @@
 
 doreltab(pkt,rlp)
 register struct Packet *pkt;
-register int ***rlp;
+register short ***rlp;
 {
-       int n;
-       int sz;
+       short n;
+       short sz;
        register struct Reltab *rt;
 
        n = 0;
@@ -493,9 +499,9 @@
 struct Packet *pkt;
 register struct deltab *dt;
 char **hists;
-int ndels;
+short ndels;
 {
-       int n;
+       short n;
        register struct deltab *ndt;
        register struct Deltab *odt;
 
@@ -509,7 +515,7 @@
                ndt = &dt[ndels];
                ndt->d_type = odt->Dtype;
                move(odt->Dpgmr,ndt->d_pgmr,sizeof(ndt->d_pgmr));
-               ndt->d_datetime = odt->Ddatetime;
+               ndt->d_datetime = (odt->Ddthi<<16)+(unsigned)odt->Ddtlo;
                ndt->d_sid.s_rel = odt->Drel;
                ndt->d_sid.s_lev = odt->Dlev;
                ndt->d_sid.s_br = 0;
@@ -538,7 +544,7 @@
 dobod(opkt,npkt,rlp,line)
 struct Packet *opkt;
 struct packet *npkt;
-int **rlp;
+short **rlp;
 char *line;
 {
        register struct Control *octl;
@@ -561,9 +567,9 @@
 
 octlrec(ctl,len)
 register struct Control *ctl;
-int len;
+short len;
 {
-       register int ch;
+       register short ch;
 
        if (len==SIZEOFCONTROL &&
                ((ch=ctl->Cctl)==OINS || ch==ODEL || ch==OEND))
@@ -590,17 +596,17 @@
 
 
 
-SCCSID(@(#)scv 1.8);
+SCCSID(@(#)scv 2.1.1.2);
 
 # define CALL(p,func,cnt)      Ffile=p; (*func)(p); cnt++;
-int    nfiles;
+short  nfiles;
 char   had_dir;
 char   had_standinp;
 
 
 odo_file(p,func)
 register char *p;
-int (*func)();
+short (*func)();
 {
        extern char *Ffile;
        char str[FILESIZE];
@@ -608,7 +614,7 @@
        FILE *iop;
        struct dir dir[2];
        register char *s;
-       int fd;
+       short fd;
 
        if (p[0] == '-') {
                had_standinp = 1;
@@ -618,7 +624,7 @@
                        }
                }
        }
-       else if (exists(p) && (Statbuf.i_mode & IFMT) == IFDIR) {
+       else if (exists(p) && (Statbuf.st_mode & S_IFMT) == S_IFDIR) {
                had_dir = 1;
                Ffile = p;
                if((iop = fopen(p,"r")) == NULL)
@@ -644,8 +650,8 @@
 osccsfile(file)
 register char *file;
 {
-       register int ff, result;
-       int magic[2];
+       register short ff, result;
+       short magic[2];
 
        result = (ff=open(file,0)) > 0
          && read(ff,magic,4) == 4
@@ -663,10 +669,10 @@
        opened) if pkt->p_upd is non-zero.  When the current line from 
        the packet is written, pkt->p_wrttn is set non-zero, and
        further attempts to write it are ignored.  When a line is
-       read into the packet, pkt->p_wrttn must be turned off.
+       read shorto the packet, pkt->p_wrttn must be turned off.
 */
 
-int    Xcreate;
+short  Xcreate;
 FILE   *Xiop;
 
 
@@ -683,9 +689,9 @@
        if(!Xcreate) {
                stat(pkt->p_file,&Statbuf);
                xf = auxf(pkt->p_file,'x');
-               Xiop = xfcreat(xf,Statbuf.i_mode);
+               Xiop = xfcreat(xf,Statbuf.st_mode);
                setbuf(Xiop,obf);
-               chown(xf,(Statbuf.i_gid<<8)|Statbuf.i_uid);
+               chown(xf,(Statbuf.st_gid<<8)|Statbuf.st_uid);
        }
        if (newline)
                p = newline;
@@ -715,7 +721,7 @@
                return;
        putline(pkt,0);
        rewind(Xiop);
-       sprintf(hash,"%5u",pkt->p_nhash);
+       sprintf(hash,"%5u",pkt->p_nhash&0xFFFF);
        zeropad(hash);
        fprintf(Xiop,"%c%c%s\n",CTLCHAR,HEAD,hash);
        fclose(Xiop);
@@ -737,9 +743,9 @@
 
 rdpfile(f,rp,un)
 char f[], un[];
-int *rp;
+short *rp;
 {
-       register int fd, i;
+       register short fd, i;
        register char *p;
        char s[65], *name;
 
@@ -771,7 +777,7 @@
 ckpfile(file)
 register char *file;
 {
-       int r;
+       short r;
        char un[SZLNAM];
 
        if(exists(file)) {
@@ -816,8 +822,8 @@
 register struct Ibufr *buf;
 {
        register char *p, *q;
-       int *w;
-       int i, n;
+       short *w;
+       short i, n;
 
        buf->Irecptr =+ buf->Ilen + !(buf->Ilen & 1);
 
@@ -859,9 +865,9 @@
 
 
 sumr(from,to)
-register int *from, *to;
+register short *from, *to;
 {
-       register int sum;
+       register short sum;
 
        for (sum=0; from<=to; )
                sum =+ *from++;
Index:  cmd/snull.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/snull.c      1981-01-15 00:16:43.000000000 -0500
@@ -0,0 +1,581 @@
+# include      "../hdr/defines.h"
+# include      "../hdr/had.h"
+
+SCCSID(@(#)snull.c     4.1);
+USXALLOC();
+
+int    Debug   0;
+struct packet gpkt;
+struct sid sid;
+int    num_files;
+char   had[26];
+FILE   *Xiop;
+int    Xcreate;
+struct deltalist {
+       struct deltalist *ds_olderdel;
+       struct deltalist *ds_youngerdel;
+       struct sid ds_sid;
+       int ds_origser;
+       int ds_ser;
+       int ds_pred;
+       long ds_datetime;
+       char ds_pgmr[8];
+       char ds_type;
+       struct stats ds_stats;
+       int ds_insnull;
+};
+struct deltalist *Dhead;
+struct deltalist *Dtail;
+char line[512];
+int *New_ser_ptr;
+int Max_old_ser;
+
+main(argc,argv)
+int argc;
+register char *argv[];
+{
+       register int i;
+       register char *p;
+       char c;
+       extern snull();
+       extern int Fcnt;
+
+       /*
+       Flags for 'fatal'.
+       */
+       Fflags = FTLEXIT | FTLMSG | FTLCLN;
+
+       /*
+       Process arguments.
+       */
+       for (i = 1; i < argc; i++)
+               if (argv[i][0] == '-' && (c = argv[i][1])) {
+                       p = &argv[i][2];
+                       switch (c) {
+                       default:
+                               fatal("unknown key letter (cm1)");
+                       }
+                       if (had[c - 'a']++)
+                               fatal("key letter twice (cm2)");
+                       argv[i] = 0;
+               }
+               else num_files++;
+
+       if(num_files == 0)
+               fatal("missing file arg (cm3)");
+
+       setsig();
+       /*
+       Reset flags for 'fatal' so that it will return to 'main'
+       rather than exiting.
+       */
+       Fflags =& ~FTLEXIT;
+       Fflags =| FTLJMP;
+
+       /*
+       Invoke 'snull' for each file argument. 
+       */
+       for (i = 1; i < argc; i++)
+               if (p = argv[i])
+                       do_file(p,snull);
+
+       exit(Fcnt ? 1 : 0);
+}
+
+
+snull(file)
+{
+       register char *p;
+       register int ser;
+       extern char had_dir, had_standinp;
+       extern char *Sflags[];
+       struct stats stats;
+       int newser;
+
+       /*
+       Set up to return to caller ('main') from 'fatal'.
+       */
+       if (setjmp(Fjmp))
+               return;
+
+       sinit(&gpkt,file,1);    /* init packet and open file */
+
+       if (exists(auxf(gpkt.p_file,'p')))
+               fatal("p-file exists (sn3)");
+
+       if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
+               fatal("cannot create lock file (cm4)");
+
+       /*
+       Indicate that file is to be re-opened (from beginning)
+       after it reaches EOF.
+       The file is read once to get the delta table
+       (without copying to x-file) and then again to make
+       required modifications to it (using x-file).
+       */
+       gpkt.p_reopen = 1;
+
+       dodeltbl(&gpkt);        /* get delta table */
+       flushto(&gpkt,EUSERNAM,1);
+       doflags(&gpkt);         /* get flags */
+
+       /*
+       Indicate to 'getline' that EOF is allowable.
+       */
+       gpkt.p_chkeof = 1;
+
+       /*
+       Flush through rest of file.
+       This checks for corruptions.
+       */
+       while (getline(&gpkt))
+               ;
+
+       if (num_files > 1 || had_dir || had_standinp)
+               printf("\n%s:\n",gpkt.p_file);
+
+       /*
+       Here, file has already been re-opened (by 'getline').
+       Indicate that x-file is to be used.
+       */
+       gpkt.p_upd = 1;
+
+       gpkt.p_wrttn = 1;
+       getline(&gpkt);         /* skip over old */
+       gpkt.p_wrttn = 1;       /* header record */
+
+       /*
+       Write new header.
+       */
+       putline(&gpkt,sprintf(line,"%c%c00000\n",CTLCHAR,HEAD));
+       mkdelt();               /* insert 'null' deltas */
+       wrtdeltbl(&gpkt);       /* write out new delta table */
+
+       flushto(&gpkt,EUSERNAM,0);
+       /*
+       If file does not have the 'n' flag, put one in.
+       */
+       if (!Sflags[NULLFLAG - 'a'])
+               putline(&gpkt,sprintf(line,"%c%c %c\n",CTLCHAR,
+                                               FLAG,NULLFLAG));
+
+       flushto(&gpkt,EUSERTXT,0);
+
+       /*
+       Process body, changing control-line serial numbers
+       appropriately.
+       */
+       fixbody(&gpkt);
+
+       flushline(&gpkt,0);     /* flush buffer, fix header, and close */
+       rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
+       clean_up(0);
+}
+
+
+dodeltbl(pkt)
+register struct packet *pkt;
+{
+       struct deltab dt;
+       struct stats stats;
+       struct deltalist *newp;
+       int n;
+
+       Dhead = Dtail = newp = 0;
+
+       /*
+       Read entire delta table.
+       */
+       while (getstats(pkt,&stats)) {
+               if (getadel(pkt,&dt) != BDELTAB)
+                       fmterr(pkt);
+               newp = alloc(n = sizeof(*Dhead));
+               zero(newp,n);
+               if (!Dhead) {
+                       Dhead = newp;
+                       New_ser_ptr = alloc(n = 2 * (dt.d_serial + 1));
+                       zero(New_ser_ptr,n);
+                       Max_old_ser = dt.d_serial;
+               }
+               else {
+                       Dtail->ds_olderdel = newp;
+                       newp->ds_youngerdel = Dtail;
+               }
+               newp->ds_sid.s_rel = dt.d_sid.s_rel;
+               newp->ds_sid.s_lev = dt.d_sid.s_lev;
+               newp->ds_sid.s_br = dt.d_sid.s_br;
+               newp->ds_sid.s_seq = dt.d_sid.s_seq;
+               newp->ds_origser = dt.d_serial;
+               newp->ds_ser = dt.d_serial;
+               newp->ds_pred = dt.d_pred;
+               newp->ds_datetime = dt.d_datetime;
+               move(&dt.d_pgmr,newp->ds_pgmr,sizeof(dt.d_pgmr));
+               newp->ds_type = dt.d_type;
+               newp->ds_stats.s_ins = stats.s_ins;
+               newp->ds_stats.s_del = stats.s_del;
+               newp->ds_stats.s_unc = stats.s_unc;
+               Dtail = newp;
+
+               /*
+               Skip over rest of delta entry. 
+               */
+               while ((n = getline(pkt)) != NULL)
+                       if (pkt->p_line[0] != CTLCHAR)
+                               break;
+                       else {
+                               switch (pkt->p_line[1]) {
+                               case EDELTAB:
+                                       break;
+                               case INCLUDE:
+                               case EXCLUDE:
+                               case IGNORE:
+                               case MRNUM:
+                               case COMMENTS:
+                                       continue;
+                               default:
+                                       fmterr(pkt);
+                               }
+                               break;
+                       }
+               if (n == NULL || pkt->p_line[0] != CTLCHAR)
+                       fmterr(pkt);
+       }
+}
+
+
+getadel(pkt,dt)
+register struct packet *pkt;
+register struct deltab *dt;
+{
+       if (getline(pkt) == NULL)
+               fmterr(pkt);
+       return(del_ab(pkt->p_line,dt,pkt));
+}
+
+
+getstats(pkt,statp)
+register struct packet *pkt;
+register struct stats *statp;
+{
+       register char *p;
+
+       p = pkt->p_line;
+       if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
+               return(0);
+       NONBLANK(p);
+       p = satoi(p,&statp->s_ins);
+       p = satoi(++p,&statp->s_del);
+       satoi(++p,&statp->s_unc);
+       return(1);
+}
+
+
+mkdelt()
+{
+       struct deltalist *ptr;
+       struct deltalist *nulldel;
+       struct deltalist *oldp;
+       struct deltalist *ptrtemp;
+       int n;
+       int currel;
+       int reldiff, numnull;
+       int serhold;
+
+       /*
+       Set current release to that of oldest (first) delta.
+       */
+       currel = Dtail->ds_sid.s_rel;
+
+       /*
+       The following loop processes each delta, starting with the
+       oldest one in the file (the last one read).
+       */
+       ptr = Dtail;
+       while (ptr) {
+               reldiff = ptr->ds_sid.s_rel - currel;
+
+               /*
+               Skip removed deltas, branch deltas, or any delta whose
+               release number is the same as the current release number.
+               */
+               if (ptr->ds_type == 'R' || ptr->ds_sid.s_br ||
+                                ptr->ds_sid.s_seq || reldiff == 0) {
+                       ptr = ptr->ds_youngerdel;
+                       continue;
+               }
+
+               /*
+               Check if delta is the next trunk delta in sequence, and if so
+               bump up current release number and continue.
+               */
+               if (reldiff == 1) {
+                       currel++;
+                       ptr = ptr->ds_youngerdel;
+                       continue;
+               }
+
+               /*
+               Here, a trunk delta has been found, and its release
+               number is greater (by at least 2) than the current
+               release number.
+               This requires insertion of 'null' deltas.
+               First, check that this trunk delta's release
+               number is greater than currel.
+               (This catches deltas whose SIDs have been changed
+               by the user to make them look like trunk deltas.)
+               */
+               if (reldiff < 0)
+                       fatal("file has invalid trunk delta (sn1)");
+
+               currel =+ reldiff;      /* update currel */
+
+               /*
+               Find pointer to ancestor delta.
+               */
+               oldp = ser_to_ptr(ptr->ds_pred);
+
+               /*
+               Retain serial number for later use in fixing
+               other deltas' serial numbers.
+               */
+               serhold = ptr->ds_ser;
+
+               ptrtemp = ptr;
+               numnull = reldiff;      /* number of null deltas needed */
+               while (--numnull) {     /* insert null deltas */
+                       nulldel = alloc(n = sizeof(*Dhead));
+                       zero(nulldel,n);
+                       nulldel->ds_youngerdel = ptrtemp;
+                       nulldel->ds_olderdel = ptrtemp->ds_olderdel;
+                       ptrtemp->ds_olderdel = nulldel;
+                       (nulldel->ds_olderdel)->ds_youngerdel = nulldel;
+                       nulldel->ds_sid.s_rel = ptrtemp->ds_sid.s_rel - 1;
+                       nulldel->ds_sid.s_lev = 1;
+                       nulldel->ds_sid.s_br = 0;
+                       nulldel->ds_sid.s_seq = 0;
+                       nulldel->ds_ser = serhold + numnull - 1;
+                       if (numnull != 1)
+                               nulldel->ds_pred = nulldel->ds_ser - 1;
+                       else
+                               nulldel->ds_pred = oldp->ds_ser;
+                       nulldel->ds_datetime = ptr->ds_datetime;
+                       substr(logname(),nulldel->ds_pgmr,0,7);
+                       nulldel->ds_type = 'D';
+                       nulldel->ds_stats.s_ins = 0;
+                       nulldel->ds_stats.s_del = 0;
+                       nulldel->ds_stats.s_unc = oldp->ds_stats.s_unc +
+                                               oldp->ds_stats.s_ins;
+                       nulldel->ds_insnull = 1;     /* null delta indicator */
+                       ptrtemp = nulldel;
+               }
+
+               /*
+               Fix up sequence and predecessor numbers of those deltas
+               which are younger than the ones just processed.
+               */
+               ptrtemp = ptr;
+               reldiff--;
+               while (ptrtemp) {
+                       if (ptrtemp->ds_ser >= serhold)
+                               ptrtemp->ds_ser =+ reldiff;
+                       if (ptrtemp->ds_pred >= serhold)
+                               ptrtemp->ds_pred =+ reldiff;
+
+                       ptrtemp = ptrtemp->ds_youngerdel;
+               }
+
+               /*
+               Fix predecessor of current delta.
+               */
+               ptr->ds_pred = serhold + reldiff - 1;
+
+               /*
+               Point to next (non-null) delta.
+               */
+               ptr = ptr->ds_youngerdel;
+       }
+
+       /*
+       Create array of original values of serial numbers of
+       the original deltas.
+       */
+       ptr = Dtail;
+       while (ptr) {
+               if (ptr->ds_insnull != 1)
+                       New_ser_ptr[ptr->ds_origser] = ptr->ds_ser;
+               ptr = ptr->ds_youngerdel;
+       }
+}
+
+
+ser_to_ptr(ser)
+int ser;
+{
+       struct deltalist *ptr;
+
+       ptr = Dtail;
+       while (ptr) {
+               if (ptr->ds_ser == ser)
+                       return(ptr);
+               ptr = ptr->ds_youngerdel;
+       }
+       fatal("internal error -- ser_to_ptr (sn2)");
+}
+
+
+wrtdeltbl(pkt)
+register struct packet *pkt;
+{
+       struct deltalist *ptr;
+       char *p;
+       int ser;
+
+       /*
+       The following loop writes out the new delta table.
+       */
+       ptr = Dhead;
+       while (ptr) {
+               if (ptr->ds_insnull) {          /* 'null' delta */
+                       /*
+                       Write out statistics line.
+                       */
+                       putline(pkt,sprintf(line,"%c%c %05u/%05u/%05u\n",
+                               CTLCHAR,STATS,ptr->ds_stats.s_ins,
+                                               ptr->ds_stats.s_del,
+                                               ptr->ds_stats.s_unc));
+
+                       /*
+                       Write 'delta' line, taken from
+                       in-core list.
+                       */
+                       putdel(pkt,ptr);
+
+                       putline(pkt,sprintf(line,"%c%c %s\n",CTLCHAR,COMMENTS,
+                                       "INSERTED BY SNULL"));
+                       putline(pkt,sprintf(line,CTLSTR,CTLCHAR,EDELTAB));
+               }
+               else {
+                       getline(pkt);           /* statistics line */
+                       getline(pkt);           /* 'delta' line */
+
+                       /*
+                       Indicate not to output previously read line.
+                       */
+                       pkt->p_wrttn = 1;
+
+                       /*
+                       Write 'delta' line from in-core list.
+                       */
+                       putdel(pkt,ptr);
+
+                       /*
+                       Process rest of entry, changeing serial
+                       numbers of deltas included, excluded,
+                       or ignored.
+                       */
+                       while (getline(pkt))
+                               if (pkt->p_line[0] != CTLCHAR)
+                                       break;
+                               else {
+                                       switch (*(p = &pkt->p_line[1])) {
+                                       case EDELTAB:
+                                               putline(pkt,0);
+                                               break;
+                                       case INCLUDE:
+                                       case EXCLUDE:
+                                       case IGNORE:
+                                               pkt->p_wrttn = 1;
+                                               putline(pkt,sprintf(line,
+                                                       "%c%c",CTLCHAR,*p++));
+                                               NONBLANK(p);
+                                               while (numeric(*p)) {
+                                                       p = satoi(p,&ser);
+
+                                                       if (!(ser > 0 &&
+                                                       ser <= Max_old_ser))
+                                                               fmterr(pkt);
+
+                                                       putline(pkt,sprintf(
+                                                       line," %u",
+                                                       New_ser_ptr[ser]));
+
+                                                       NONBLANK(p);
+                                               }
+                                               putline(pkt,"\n");
+                                               continue;
+                                       default:
+                                               putline(pkt,0);
+                                               continue;
+                                       }
+                                       break;
+                               }
+               }
+
+               /*
+               Point to next delta to be output.
+               */
+               ptr = ptr->ds_olderdel;
+       }
+}
+
+
+putdel(pkt,ptr)
+struct packet *pkt;
+struct deltalist *ptr;
+{
+       struct deltab dt;
+
+       move(&ptr->ds_sid,&dt.d_sid,sizeof(dt.d_sid));
+       dt.d_serial = ptr->ds_ser;
+       dt.d_pred = ptr->ds_pred;
+       dt.d_datetime = ptr->ds_datetime;
+       move(ptr->ds_pgmr,&dt.d_pgmr,sizeof(dt.d_pgmr));
+       dt.d_type = ptr->ds_type;
+
+       del_ba(&dt,line);
+       putline(pkt,line);
+}
+
+
+fixbody(pkt)
+register struct packet *pkt;
+{
+       int ser;
+       char *p, type;
+
+       while (getline(pkt)) {
+               p = pkt->p_line;
+
+               if (*p++ == CTLCHAR) {
+                       if (!((type = *p++) == INS || type == DEL ||
+                                                       type == END))
+                               fmterr(pkt);
+                       NONBLANK(p);
+                       satoi(p,&ser);
+                       if (!(ser > 0 && ser <= Max_old_ser))
+                               fmterr(pkt);
+
+                       /*
+                       Indicate not to output line just read.
+                       */
+                       pkt->p_wrttn = 1;
+
+                       /*
+                       Output new value of sequence number.
+                       */
+                       putline(pkt,sprintf(line,"%c%c %u\n",CTLCHAR,type,
+                                               New_ser_ptr[ser]));
+               }
+       }
+}
+
+
+clean_up(n)
+{
+       if (gpkt.p_file[0])
+               unlockit(auxf(gpkt.p_file,'z'),getpid());
+       if (gpkt.p_iop)
+               fclose(gpkt.p_iop);
+       xrm(&gpkt);
+       xfreeall();
+}
Index:  cmd/stree.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/stree.c      1981-01-15 00:16:45.000000000 -0500
@@ -0,0 +1,293 @@
+# include      "../hdr/defines.h"
+# include      "../hdr/had.h"
+
+SCCSID(@(#)stree.c     4.1);
+USXALLOC();
+
+struct tree {
+       int     t_dsucc;                /* first successor (trunk) */
+       struct  list    *t_osucc;       /* other successors */
+       int     t_trunk;                /* != 0 is a trunk delta */
+};
+
+struct list {
+       struct  list    *l_next;
+       int     l_val;
+};
+
+struct position {
+       int     p_depth;
+       int     p_width;
+       int     p_node;
+};
+
+
+struct tree    *tree;
+struct position        *pos;
+int    dval;
+
+struct packet gpkt;
+struct sid sid;
+int    num_files;
+char   had[26];
+
+main(argc,argv)
+int argc;
+register char *argv[];
+{
+       register int i;
+       register char *p;
+       char c;
+       int testmore;
+       extern prttree();
+       extern int Fcnt;
+
+       Fflags = FTLEXIT | FTLMSG | FTLCLN;
+       for(i = 1; i < argc; i++)
+               if(argv[i][0] == '-' && (c=argv[i][1])) {
+                       p = &argv[i][2];
+                       testmore = 0;
+                       switch (c) {
+
+                       case 'p':
+                               testmore++;
+                               break;
+
+                       default:
+                               fatal("unknown key letter (cm1)");
+                       }
+
+                       if (testmore) {
+                               testmore = 0;
+                               if (*p)
+                                       fatal(sprintf(Error,
+                                         "value after %c arg (cm7)",c));
+                       }
+                       if (had[c - 'a']++)
+                               fatal("key letter twice (cm2)");
+                       argv[i] = 0;
+               }
+               else num_files++;
+
+       if(num_files == 0)
+               fatal("missing file arg (cm3)");
+       setsig();
+       Fflags =& ~FTLEXIT;
+       Fflags =| FTLJMP;
+       for (i = 1; i < argc; i++)
+               if (p=argv[i])
+                       do_file(p,prttree);
+       exit(Fcnt ? 1 : 0);
+}
+
+
+prttree(file)
+{
+       register struct idel *rdp;
+       register int n, i;
+       char str[32];
+       extern char had_dir, had_standinp;
+       struct stats stats;
+       extern poscomp();
+
+       if (setjmp(Fjmp))
+               return;
+       sinit(&gpkt, file, 1);
+       gpkt.p_verbose = -1;
+       gpkt.p_stdout = stderr;
+       if (gpkt.p_verbose && (num_files > 1 || had_dir || had_standinp))
+               fprintf(gpkt.p_stdout,"\n%s:\n",gpkt.p_file);
+
+       if (dodelt(&gpkt,&stats,0,0) == 0)
+               fmterr(&gpkt);
+       fclose(gpkt.p_iop);
+       gpkt.p_iop = 0;
+
+       tree = alloc(n = ((maxser(&gpkt) + 1) * sizeof(struct tree)));
+       zero(tree, n);
+       pos = alloc(n = ((maxser(&gpkt) + 1) * sizeof(struct position)));
+       zero(pos, n);
+       for (i = 1; i <= maxser(&gpkt); i++)
+               pos[i].p_node = i;
+       rdp = gpkt.p_idel;
+       for (i = 1; i <= maxser(&gpkt); i++) {
+               if (rdp[i].i_sid.s_br == 0)
+                       tree[i].t_trunk = 1;
+               else
+                       pos[i].p_width = pos[rdp[i].i_pred].p_width + 1;
+               for (n = i + 1; n <= maxser(&gpkt); n++)
+                       if (rdp[n].i_pred == i)
+                               addsucc(i, n, rdp[n].i_sid.s_br);
+       }
+       dval = 0;
+       traverse(1);
+       if (!HADP) {
+               qsort(&pos[1], maxser(&gpkt), sizeof(pos[1]), poscomp);
+               for (n = 1; n <= maxser(&gpkt); n++) {
+                       sid_ba(&rdp[pos[n].p_node].i_sid, str);
+                       printf("Node %d\tSid %s\tDepth %d\tWidth %d\n",
+                               pos[n].p_node, str, pos[n].p_depth, pos[n].p_width);
+               }
+       }
+       else
+               plot(rdp, maxser(&gpkt));
+       xfreeall();
+}
+
+
+addsucc(par, child, childbr)
+{
+       struct tree *tp;
+
+       tp = &tree[par];
+       if (tp->t_trunk && tp->t_dsucc == 0 && childbr == 0)
+               tp->t_dsucc = child;
+       else
+               addlist(&tp->t_osucc, child);
+}
+
+
+addlist(headp, val)
+struct list *headp;
+{
+       struct list *prev, *p;
+
+       for (p = headp; p = (prev = p)->l_next; )
+               ;
+       prev->l_next = p = alloc(sizeof(struct list));
+       p->l_next = 0;
+       p->l_val = val;
+}
+
+
+traverse(node)
+{
+       register struct list *lp;
+
+       pos[node].p_depth = dval;
+       if (lp = tree[node].t_osucc) {
+               traverse(lp->l_val);
+               while (lp = lp->l_next) {
+                       ++dval;
+                       traverse(lp->l_val);
+               }
+       }
+       if (tree[node].t_dsucc) {
+               ++dval;
+               traverse(tree[node].t_dsucc);
+       }
+}
+
+
+poscomp(p1, p2)
+register struct position *p1, *p2;
+{
+       register int diff;
+
+       if (diff = p1->p_depth - p2->p_depth)
+               return(diff);
+       else
+               return(p1->p_width - p2->p_width);
+}
+
+
+dmptree()
+{
+       register int n;
+       register struct tree *tp;
+       register struct list *lp;
+
+       for (n = maxser(&gpkt); n; n--) {
+               printf("Node %d", n);
+               tp = &tree[n];
+               if (tp->t_dsucc)
+                       printf("\t%d", tp->t_dsucc);
+               for (lp = tp->t_osucc; lp; lp = lp->l_next)
+                       printf("\t%d", lp->l_val);
+               printf("\n");
+       }
+}
+
+
+plot(rdp, n)
+register struct idel *rdp;
+{
+       char str[32];
+       int i, j, x, y, node;
+       struct tree *tp;
+       struct list *lp;
+
+       for (i = 1; i <= n; i++) {
+               node = pos[i].p_node;
+               x = pos[i].p_width;
+               y = pos[i].p_depth;
+               sid_ba(&rdp[node].i_sid, str);
+               pllabel(str, x, y);
+               tp = &tree[node];
+               if (j = tp->t_dsucc)
+                       plline(x, y, pos[j].p_width, pos[j].p_depth);
+               for (lp = tp->t_osucc; lp; lp = lp->l_next) {
+                       j = lp->l_val;
+                       plline(x, y, pos[j].p_width, pos[j].p_depth);
+               }
+       }
+       pllabel("", 0, 15);
+}
+
+
+pllabel(s, x, y)
+{
+       x = scx(x) + 64;
+       y = scy(y) + 64;
+       putchar('m');
+       putwd(x);
+       putwd(y);
+       printf("t%s\n", s);
+}
+
+
+plline(x0, y0, x1, y1)
+{
+       x0 = scx(x0);
+       x1 = scx(x1);
+       y0 = scy(y0);
+       y1 = scy(y1);
+       putchar('l');
+       putwd(x0);
+       putwd(y0);
+       putwd(x1);
+       putwd(y1);
+}
+
+
+putwd(w)
+{
+       register char *p;
+
+       p = &w;
+       putchar(*p++);
+       putchar(*p);
+}
+
+
+scx(xi)
+{
+       return(xi * 1024 - 2047);
+}
+
+
+scy(yi)
+{
+       return(2047 - (yi * 256));
+}
+
+
+clean_up(n)
+{
+       xfreeall();
+}
+
+
+escdodelt()    /* dummy for dodelt() */
+{
+}
Index:  cmd/val.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/val.c        1981-01-15 00:16:47.000000000 -0500
@@ -0,0 +1,688 @@
+/************************************************************************/
+/*                                                                     */
+/*  val -                                                               */
+/*  val [-mname] [-rSID] [-s] [-ytype] file ...                         */
+/*                                                                      */
+/************************************************************************/
+
+# include      "../hdr/defines.h"
+# include      "../hdr/had.h"
+
+# define       FILARG_ERR      0200    /* no file name given */
+# define       UNKDUP_ERR      0100    /* unknown or duplicate keyletter */
+# define       CORRUPT_ERR     040     /* corrupt file error code */
+# define       FILENAM_ERR     020     /* file name error code */
+# define       INVALSID_ERR    010     /* invalid or ambiguous SID error  */
+# define       NONEXSID_ERR    04      /* non-existent SID error code */
+# define       TYPE_ERR        02      /* type arg value error code */
+# define       NAME_ERR        01      /* name arg value error code */
+# define       TRUE            1
+# define       FALSE           0
+# define       BLANK(l)        while (!(*l == ' ' || *l == '\t')) l++;
+
+int    ret_code;       /* prime return code from 'main' program */
+int    inline_err;     /* input line error code (from 'process') */
+int    infile_err;     /* file error code (from 'validate') */
+int    inpstd;         /* TRUE = args from standard input */
+
+struct packet gpkt;
+
+char   had[26];        /* had flag used in 'process' function */
+char   path[50];       /* storage for file name value */
+char   sid[50];        /* storage for sid (-r) value */
+char   type[50];       /* storage for type (-y) value */
+char   name[50];       /* storage for name (-m) value */
+char   line[BUFSIZ];
+char   *get_line();    /* function returning ptr to line read */
+char   *getval();      /* function returning adjusted ptr to line */
+char   *alloc();       /* function returning ptr */
+char   *fgets();       /* function returning i/o ptr */
+
+struct delent {                /* structure for delta table entry */
+       char type;
+       char *osid;
+       char *datetime;
+       char *pgmr;
+       char *serial;
+       char *pred;
+} del;
+
+SCCSID(@(#)val.c       4.1);
+
+/* This is the main program that determines whether the command line
+ * comes from the standard input or read off the original command
+ * line.  See VAL(I) for more information.
+*/
+main(argc,argv)
+int argc;
+char   *argv[];
+{
+       FILE    *iop;
+       register int j;
+
+       ret_code = 0;
+       if (argc == 2 && argv[1][0] == '-' && !(argv[1][1])) {
+               inpstd = TRUE;
+               iop = stdin;            /* read from standard input */
+               while (fgets(line,BUFSIZ,iop) != NULL) {
+                       if (line[0] != '\n') {
+                               repl (line,'\n','\0');
+                               process(line);
+                               ret_code =| inline_err;
+                       }
+               }
+       }
+       else {
+               inpstd = FALSE;
+               for (j = 1; j < argc; j++)
+                       sprintf(&(line[strlen(line)]),"%s ",argv[j]);
+               j = strlen(line) - 1;
+               line[j > 0 ? j : 0] = NULL;
+               process(line);
+               ret_code = inline_err;
+       }
+       exit(ret_code);
+}
+
+
+/* This function processes the line sent by the main routine.  It
+ * determines which keyletter values are present on the command
+ * line and assigns the values to the correct storage place.  It
+ * then calls validate for each file name on the command line
+ * It will return to main if the input line contains an error,
+ * otherwise it returns any error code found by validate.
+*/
+process(p_line)
+char   *p_line;
+{
+       register int    j;
+       register int    testklt;
+       register int    line_sw;
+
+       int     silent;
+       int     num_files;
+
+       char    filelist[50][50];
+       char    *savelinep;
+       char    c;
+
+       silent = FALSE;
+       path[0] = sid[0] = type[0] = name[0] = 0;
+       num_files = inline_err = 0;
+
+       /*
+       make copy of 'line' for use later
+       */
+       savelinep = p_line;
+       /*
+       clear out had flags for each 'line' processed
+       */
+       for (j = 0; j < 27; j++)
+               had[j] = 0;
+       /*
+       execute loop until all characters in 'line' are checked.
+       */
+       while (*p_line) {
+               testklt = 1;
+               NONBLANK(p_line);
+               if (*p_line == '-') {
+                       p_line =+ 1;
+                       c = *p_line;
+                       p_line++;
+                       switch (c) {
+                               case 's':
+                                       testklt = 0;
+                                       /*
+                                       turn on 'silent' flag.
+                                       */
+                                       silent = TRUE;
+                                       break;
+                               case 'r':
+                                       p_line = getval(p_line,sid);
+                                       break;
+                               case 'y':
+                                       p_line = getval(p_line,type);
+                                       break;
+                               case 'm':
+                                       p_line = getval(p_line,name);
+                                       break;
+                               default:
+                                       inline_err =| UNKDUP_ERR;
+                       }
+                       /*
+                       use 'had' array and determine if the keyletter
+                       was given twice.
+                       */
+                       if (had[c - 'a']++ && testklt++)
+                               inline_err =| UNKDUP_ERR;
+               }
+               else {
+                       /*
+                       assume file name if no '-' preceeded argument
+                       */
+                       p_line = getval(p_line,filelist[num_files]);
+                       num_files++;
+               }
+       }
+       /*
+       check if any files were named as arguments
+       */
+       if (num_files == 0)
+               inline_err =| FILARG_ERR;
+       /*
+       check for error in command line.
+       */
+       if (inline_err && !silent) {
+               if (inpstd)
+                       report(inline_err,savelinep,"");
+               else report(inline_err,"","");
+               return;         /* return to 'main' routine */
+       }
+       line_sw = 1;            /* print command line flag */
+       /*
+       loop through 'validate' for each file on command line.
+       */
+       for (j = 0; j < num_files; j++) {
+               /*
+               read a file from 'filelist' and place into 'path'.
+               */
+               sprintf(path,"%s",filelist[j]);
+               validate(path,sid,type,name);
+               inline_err =| infile_err;
+               /*
+               check for error from 'validate' and call 'report'
+               depending on 'silent' flag.
+               */
+               if (infile_err && !silent) {
+                       if (line_sw && inpstd) {
+                               report(infile_err,savelinep,path);
+                               line_sw = 0;
+                       }
+                       else report(infile_err,"",path);
+               }
+       }
+       return;         /* return to 'main' routine */
+}
+
+
+/* This function actually does the validation on the named file.
+ * It determines whether the file is an SCCS-file or if the file
+ * exists.  It also determines if the values given for type, SID,
+ * and name match those in the named file.  An error code is returned
+ * if any mismatch occurs.  See VAL(I) for more information.
+*/
+validate(c_path,c_sid,c_type,c_name)
+char   *c_path;
+char   *c_sid;
+char   *c_type;
+char   *c_name;
+{
+       register char   *l;
+       int     goods,goodt,goodn,hadmflag;
+
+       infile_err = goods = goodt = goodn = hadmflag = 0;
+       sinit(&gpkt,c_path);
+       if (!sccsfile(c_path) || (gpkt.p_iop = fopen(c_path,"r")) == NULL)
+               infile_err =| FILENAM_ERR;
+       else {
+               l = get_line(&gpkt);            /* read first line in file */
+               /*
+               check that it is header line.
+               */
+               if (*l++ != CTLCHAR || *l++ != HEAD)
+                       infile_err =| CORRUPT_ERR;
+
+               else {
+                       /*
+                       get old file checksum count
+                       */
+                       satoi(l,&gpkt.p_ihash);
+                       gpkt.p_chash = 0;
+                       if (HADR)
+                               /*
+                               check for invalid or ambiguous SID.
+                               */
+                               if (invalid(c_sid))
+                                       infile_err =| INVALSID_ERR;
+                       /*
+                       read delta table checking for errors and/or
+                       SID.
+                       */
+                       if (do_delt(&gpkt,goods,c_sid)) {
+                               fclose(gpkt.p_iop);
+                               infile_err =| CORRUPT_ERR;
+                               return;
+                       }
+
+                       read_to(EUSERNAM,&gpkt);
+
+                       if (HADY || HADM) {
+                               /*
+                               read flag section of delta table.
+                               */
+                               while ((l = get_line(&gpkt)) &&
+                                       *l++ == CTLCHAR &&
+                                       *l++ == FLAG) {
+                                       NONBLANK(l);
+                                       repl(l,'\n','\0');
+                                       if (*l == TYPEFLAG) {
+                                               l =+ 2;
+                                               if (equal(c_type,l))
+                                                       goodt++;
+                                       }
+                                       else if (*l == MODFLAG) {
+                                               hadmflag++;
+                                               l =+ 2;
+                                               if (equal(c_name,l))
+                                                       goodn++;
+                                       }
+                               }
+                               if (*(--l) != BUSERTXT) {
+                                       fclose(gpkt.p_iop);
+                                       infile_err =| CORRUPT_ERR;
+                                       return;
+                               }
+                               /*
+                               check if 'y' flag matched '-y' arg value.
+                               */
+                               if (!goodt && HADY)
+                                       infile_err =| TYPE_ERR;
+                               /*
+                               check if 'm' flag matched '-m' arg value.
+                               */
+                               if (HADM && !hadmflag) {
+                                       if (!equal(auxf(sname(c_path),'g'),c_name))
+                                               infile_err =| NAME_ERR;
+                               }
+                               else if (HADM && hadmflag && !goodn)
+                                               infile_err =| NAME_ERR;
+                       }
+                       else read_to(BUSERTXT,&gpkt);
+                       read_to(EUSERTXT,&gpkt);
+                       gpkt.p_chkeof = 1;
+                       /*
+                       read remainder of file so 'read_mod'
+                       can check for corruptness.
+                       */
+                       while (read_mod(&gpkt))
+                               ;
+               }
+       fclose(gpkt.p_iop);     /* close file pointer */
+       }
+       return;         /* return to 'process' function */
+}
+
+
+/* This function reads the 'delta' line from the named file and stores
+ * the information into the structure 'del'.
+*/
+getdel(delp,lp)
+register struct delent *delp;
+register char *lp;
+{
+       NONBLANK(lp);
+       delp->type = *lp++;
+       NONBLANK(lp);
+       delp->osid = lp;
+       BLANK(lp);
+       *lp++ = '\0';
+       NONBLANK(lp);
+       delp->datetime = lp;
+       BLANK(lp);
+       NONBLANK(lp);
+       BLANK(lp);
+       *lp++ = '\0';
+       NONBLANK(lp);
+       delp->pgmr = lp;
+       BLANK(lp);
+       *lp++ = '\0';
+       NONBLANK(lp);
+       delp->serial = lp;
+       BLANK(lp);
+       *lp++ = '\0';
+       NONBLANK(lp);
+       delp->pred = lp;
+       repl(lp,'\n','\0');
+}
+
+
+/* This function does a read through the named file until it finds
+ * the character sent over as an argument.
+*/
+read_to(ch,pkt)
+register char ch;
+register struct packet *pkt;
+{
+       register char *n;
+       while ((n = get_line(pkt)) &&
+                       !(*n++ == CTLCHAR && *n == ch))
+               ;
+       return;
+}
+
+
+/* This function places into a specified destination characters  which
+ * are delimited by either a space, tab or 0.  It obtains the char-
+ * acters from a line of characters.
+*/
+char   *getval(sourcep,destp)
+register char  *sourcep;
+register char  *destp;
+{
+       while (*sourcep != ' ' && *sourcep != '\t' && *sourcep != '\0')
+               *destp++ = *sourcep++;
+       *destp = 0;
+       return(sourcep);
+}
+
+
+/* This function will report the error that occured on the command
+ * line.  It will print one diagnostic message for each error that
+ * was found in the named file.
+*/
+report(code,inp_line,file)
+register int   code;
+register char  *inp_line;
+register char  *file;
+{
+       char    percent;
+       percent = '%';          /* '%' for -m and/or -y messages */
+       if (*inp_line)
+               printf("%s\n\n",inp_line);
+       if (code & NAME_ERR)
+               printf("    %s: %cM%c, -m mismatch\n",file,percent,percent);
+       if (code & TYPE_ERR)
+               printf("    %s: %cY%c, -y mismatch\n",file,percent,percent);
+       if (code & NONEXSID_ERR)
+               printf("    %s: SID nonexistent\n",file);
+       if (code & INVALSID_ERR)
+               printf("    %s: SID invalid or ambiguous\n",file);
+       if (code & FILENAM_ERR)
+               printf("    %s: can't open file or file not SCCS\n",file);
+       if (code & CORRUPT_ERR)
+               printf("    %s: corrupted SCCS file\n",file);
+       if (code & UNKDUP_ERR)
+               printf("    %s: Unknown or dupilcate keyletter argument\n",file);
+       if (code & FILARG_ERR)
+               printf("    %s: missing file argument\n",file);
+       return;
+}
+
+
+/* This function takes as it's argument the SID inputed and determines
+ * whether or not it is valid (e. g. not ambiguous or illegal).
+*/
+invalid(i_sid)
+register char  *i_sid;
+{
+       register int count;
+       register int digits;
+       count = digits = 0;
+       if (*i_sid == '0' || *i_sid == '.')
+               return (1);
+       i_sid++;
+       digits++;
+       while (*i_sid != '\0') {
+               if (*i_sid++ == '.') {
+                       digits = 0;
+                       count++;
+                       if (*i_sid == '0' || *i_sid == '.')
+                               return (1);
+               }
+               digits++;
+               if (digits > 5)
+                       return (1);
+       }
+       if (*(--i_sid) == '.' )
+               return (1);
+       if (count == 1 || count == 3)
+               return (0);
+       return (1);
+}
+
+
+/*
+       Routine to read a line into the packet.  The main reason for
+       it is to make sure that pkt->p_wrttn gets turned off,
+       and to increment pkt->p_slnno.
+*/
+
+char   *get_line(pkt)
+register struct packet *pkt;
+{
+       register char *n;
+       register char *p;
+
+       if ((n = fgets(pkt->p_line,sizeof(pkt->p_line),pkt->p_iop)) != NULL) {
+               pkt->p_slnno++;
+               for (p = pkt->p_line; *p; )
+                       pkt->p_chash =+ *p++;
+       }
+       else {
+               if (!pkt->p_chkeof)
+                       infile_err =| CORRUPT_ERR;
+               if (pkt->do_chksum && (pkt->p_chash ^ pkt->p_ihash)&0xFFFF)
+                       infile_err =| CORRUPT_ERR;
+       }
+       return(n);
+}
+
+
+/*
+       Does initialization for sccs files and packet.
+*/
+
+sinit(pkt,file)
+register struct packet *pkt;
+register char *file;
+{
+
+       zero(pkt,sizeof(*pkt));
+       copy(file,pkt->p_file);
+       pkt->p_wrttn = 1;
+       pkt->do_chksum = 1;     /* turn on checksum check for getline */
+}
+
+
+read_mod(pkt)
+register struct packet *pkt;
+{
+       register char *p;
+       int ser;
+       int iord;
+       register struct apply *ap;
+
+       while (get_line(pkt) != NULL) {
+               p = pkt->p_line;
+               if (*p++ != CTLCHAR)
+                       continue;
+               else {
+                       if (!((iord = *p++) == INS || iord == DEL || iord == END)) {
+                               infile_err =| CORRUPT_ERR;
+                               return(0);
+                       }
+                       NONBLANK(p);
+                       satoi(p,&ser);
+                       if (iord == END)
+                               remq(pkt,ser);
+                       else if ((ap = &pkt->p_apply[ser])->a_code == APPLY)
+                               addq(pkt,ser,iord == INS ? YES : NO,iord,ap->a_reason & USER);
+                       else
+                               addq(pkt,ser,iord == INS ? NO : NULL,iord,ap->a_reason & USER);
+               }
+       }
+       if (pkt->p_q)
+               infile_err =| CORRUPT_ERR;
+       return(0);
+}
+
+
+addq(pkt,ser,keep,iord,user)
+struct packet *pkt;
+int ser;
+int keep;
+int iord;
+{
+       register struct queue *cur, *prev, *q;
+
+       for (cur = &pkt->p_q; cur = (prev = cur)->q_next; )
+               if (cur->q_sernum <= ser)
+                       break;
+       if (cur->q_sernum == ser)
+               infile_err =| CORRUPT_ERR;
+       prev->q_next = q = alloc(sizeof(*q));
+       q->q_next = cur;
+       q->q_sernum = ser;
+       q->q_keep = keep;
+       q->q_iord = iord;
+       q->q_user = user;
+       if (pkt->p_ixuser && (q->q_ixmsg = chkix(q,&pkt->p_q)))
+               ++(pkt->p_ixmsg);
+       else
+               q->q_ixmsg = 0;
+
+       setkeep(pkt);
+}
+
+
+remq(pkt,ser)
+register struct packet *pkt;
+int ser;
+{
+       register struct queue *cur, *prev;
+
+       for (cur = &pkt->p_q; cur = (prev = cur)->q_next; )
+               if (cur->q_sernum == ser)
+                       break;
+       if (cur) {
+               if (cur->q_ixmsg)
+                       --(pkt->p_ixmsg);
+               prev->q_next = cur->q_next;
+               free(cur);
+               setkeep(pkt);
+       }
+       else
+               infile_err =| CORRUPT_ERR;
+}
+
+
+setkeep(pkt)
+register struct packet *pkt;
+{
+       register struct queue *q;
+       register struct sid *sp;
+
+       for (q = &pkt->p_q; q = q->q_next; )
+               if (q->q_keep != NULL) {
+                       if ((pkt->p_keep = q->q_keep) == YES) {
+                               sp = &pkt->p_idel[q->q_sernum].i_sid;
+                               pkt->p_inssid.s_rel = sp->s_rel;
+                               pkt->p_inssid.s_lev = sp->s_lev;
+                               pkt->p_inssid.s_br = sp->s_br;
+                               pkt->p_inssid.s_seq = sp->s_seq;
+                       }
+                       return;
+               }
+       pkt->p_keep = NO;
+}
+
+
+# define apply(qp)     ((qp->q_iord == INS && qp->q_keep == YES) || (qp->q_iord == DEL && qp->q_keep == NO))
+
+chkix(new,head)
+register struct queue *new;
+struct queue *head;
+{
+       register int retval;
+       register struct queue *cur;
+       int firstins, lastdel;
+
+       if (!apply(new))
+               return(0);
+       for (cur = head; cur = cur->q_next; )
+               if (cur->q_user)
+                       break;
+       if (!cur)
+               return(0);
+       retval = 0;
+       firstins = 0;
+       lastdel = 0;
+       for (cur = head; cur = cur->q_next; ) {
+               if (apply(cur)) {
+                       if (cur->q_iord == DEL)
+                               lastdel = cur->q_sernum;
+                       else if (firstins == 0)
+                               firstins = cur->q_sernum;
+               }
+               else if (cur->q_iord == INS)
+                       retval++;
+       }
+       if (retval == 0) {
+               if (lastdel && (new->q_sernum > lastdel))
+                       retval++;
+               if (firstins && (new->q_sernum < firstins))
+                       retval++;
+       }
+       return(retval);
+}
+
+
+/* This function reads the delta table entries and checks for the format
+ * as specifed in sccsfile(V).  If the format is incorrect, a corrupt
+ * error will be issued by 'val'.  This function also checks
+ * if the sid requested is in the file (depending if '-r' was specified).
+*/
+do_delt(pkt,goods,d_sid)
+register struct packet *pkt;
+register int goods;
+register char *d_sid;
+{
+       char *l;
+
+       while(getstats(pkt)) {
+               if ((l = get_line(pkt)) && *l++ != CTLCHAR || *l++ != BDELTAB)
+                       return(1);
+               if (HADR && !(infile_err & INVALSID_ERR)) {
+                       getdel(&del,l);
+                       if (equal(d_sid,del.osid) && del.type == 'D')
+                               goods++;
+               }
+               while ((l = get_line(pkt)) != NULL)
+                       if (pkt->p_line[0] != CTLCHAR)
+                               break;
+                       else {
+                               switch(pkt->p_line[1]) {
+                               case EDELTAB:
+                                       break;
+                               case COMMENTS:
+                               case MRNUM:
+                               case INCLUDE:
+                               case EXCLUDE:
+                               case IGNORE:
+                                       continue;
+                               default:
+                                       return(1);
+                               }
+                               break;
+                       }
+               if (l == NULL || pkt->p_line[0] != CTLCHAR)
+                       return(1);
+       }
+       if (pkt->p_line[1] != BUSERNAM)
+               return(1);
+       if (HADR && !goods && !(infile_err & INVALSID_ERR))
+               infile_err =| NONEXSID_ERR;
+       return(0);
+}
+
+
+/* This function reads the stats line from the sccsfile */
+getstats(pkt)
+register struct packet *pkt;
+{
+       register char *p;
+       p = pkt->p_line;
+       if (get_line(pkt) == NULL || *p++ != CTLCHAR || *p != STATS)
+               return(0);
+       return(1);
+}
Index:  cmd/vc.c
--- /dev/null   2020-06-21 15:53:25.452000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/vc.c 1981-01-15 00:16:50.000000000 -0500
@@ -0,0 +1,658 @@
+# include      "stdio.h"
+# include      "seven/types.h"
+# include      "seven/macros.h"
+# include      "fatal.h"
+
+SCCSID(@(#)vc.c        4.1);
+USXALLOC();
+
+/*
+ * The symbol table size is set to a limit of forty keywords per input
+ * file.  Should this limit be changed it should also be changed in the
+ * Help file.
+ */
+
+# define SYMSIZE 40
+# define PARMSIZE 10
+# define NSLOTS 32
+
+# define USD  1
+# define DCL 2
+# define ASG 4
+
+# define EQ '='
+# define NEQ '!'
+# define GT '>'
+# define LT '<'
+# define DELIM " \t"
+# define TRUE 1
+# define FALSE 0
+
+char   Ctlchar ':';
+
+struct symtab  {
+       int     usage;
+       char    name[PARMSIZE];
+       char    *value;
+       int     lenval;
+};
+struct symtab  Sym[SYMSIZE];
+
+struct {
+       char    chr;
+};
+
+int    Skiptabs;
+int    Repall;
+
+/*
+ * Delflag is used to indicate when text is to be skipped.  It is decre-
+ * mented whenever an if condition is false, or when an if occurs
+ * within a false if/end statement.  It is decremented whenever an end is
+ * encountered and the Delflag is greater than zero.  Whenever Delflag
+ * is greater than zero text is skipped.
+ */
+
+int    Delflag;
+
+/*
+ * Ifcount keeps track of the number of ifs and ends.  Each time
+ * an if is encountered Ifcount is incremented and each time an end is
+ * encountered it is decremented.
+ */
+
+int    Ifcount;
+int    Lineno;
+
+char   *Repflag;
+char   *Linend;
+int    Silent;
+
+
+/*
+ * The main program reads a line of text and sends it to be processed
+ * if it is a version control statement. If it is a line of text and
+ * the Delflag is equal to zero, it is written to the standard output.
+ */
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register  char *lineptr, *p;
+       register int i;
+       char line[512];
+       extern int Fflags;
+
+       Fflags = FTLCLN | FTLMSG | FTLEXIT;
+       setsig();
+       for(i = 1; i< argc; i++) {
+               p = argv[i];
+               if (p[0] == '-')
+                       switch (p[1]) {
+                       case 's':
+                               Silent = 1;
+                               break;
+                       case 't':
+                               Skiptabs = 1;
+                               break;
+                       case 'a':
+                               Repall = 1;
+                               break;
+                       case 'c':
+                               Ctlchar = p[2];
+                               break;
+                       }
+               else {
+                       p[size(p) - 1] = '\n';
+                       asgfunc(p);
+               }
+       }
+       while (fgets(line,sizeof(line),stdin) != NULL) {
+               lineptr = line;
+               Lineno++;
+
+               if (Repflag != 0) {
+                       free(Repflag);
+                       Repflag = 0;
+               }
+
+               if (Skiptabs) {
+                       for (p = lineptr; *p; p++)
+                               if (*p == '\t')
+                                       break;
+                       if (*p++ == '\t')
+                               lineptr = p;
+               }
+
+               if (lineptr[0] != Ctlchar) {
+                       if (lineptr[0] == '\\' && lineptr[1] == Ctlchar)
+                               for (p = &lineptr[1]; *lineptr++ = *p++; )
+                                       ;
+                       if(Delflag == 0) {
+                               if (Repall)
+                                       repfunc(line);
+                               else
+                                       fputs(line,stdout);
+                       }
+                       continue;
+               }
+
+               lineptr++;
+
+               if (imatch("if ", lineptr))
+                       iffunc(&lineptr[3]);
+               else if (imatch("end", lineptr))
+                       endfunc();
+               else if (Delflag == 0) {
+                       if (imatch("asg ", lineptr))
+                               asgfunc(&lineptr[4]);
+                       else if (imatch("dcl ", lineptr))
+                               dclfunc(&lineptr[4]);
+                       else if (imatch("err", lineptr))
+                               errfunc(&lineptr[3]);
+                       else if (imatch("msg", lineptr))
+                               msgfunc(&lineptr[3]);
+                       else if (lineptr[0] == Ctlchar)
+                               repfunc(&lineptr[1]);
+                       else if (imatch("on", lineptr))
+                               Repall = 1;
+                       else if (imatch("off", lineptr))
+                               Repall = 0;
+                       else if (imatch("ctl ", lineptr))
+                               Ctlchar = lineptr[4];
+                       else error("unknown command on line %d (901)",Lineno);
+               }
+       }
+       for(i = 0; Sym[i].usage != 0 && i<SYMSIZE; i++) {
+               if ((Sym[i].usage&USD) == 0)
+                       warn("`%s' never used (902)\n",Sym[i].name);
+               if ((Sym[i].usage&DCL) == 0)
+                       warn("`%s' never declared (903)\n", Sym[i].name);
+               if ((Sym[i].usage&ASG) == 0)
+                       warn("`%s' never assigned a value (920)\n", Sym[i].name);
+       }
+       if (Ifcount > 0)
+               error("`if' with no matching `end' (904)");
+       exit(0);
+}
+
+
+/*
+ * Asgfunc accepts a pointer to a line picks up a keyword name, an
+ * equal sign and a value and calls putin to place it in the symbol table.
+ */
+
+asgfunc(aptr)
+register char *aptr;
+{
+       register char *end, *aname;
+       char *avalue;
+
+       aptr = replace(aptr);
+       NONBLANK(aptr);
+       aname = aptr;
+       end = Linend;
+       aptr = findstr(aptr,"= \t");
+       if (*aptr == ' ' || *aptr == '\t') {
+               *aptr++ = '\0';
+               aptr = findch(aptr,'=');
+       }
+       if (aptr == end)
+               error("syntax on line %d (917)",Lineno);
+       *aptr++ = '\0';
+       avalue = getid(aptr);
+       chksize(aname);
+       putin(aname, avalue);
+}
+
+
+/*
+ * Dclfunc accepts a pointer to a line and picks up keywords
+ * separated by commas.  It calls putin to put each keyword in the
+ * symbol table.  It returns when it sees a newline.
+ */
+
+dclfunc(dptr)
+register char *dptr;
+{
+       register char *end, *dname;
+       int i;
+
+       dptr = replace(dptr);
+       end = Linend;
+       NONBLANK(dptr);
+       while (dptr < end) {
+               dname = dptr;
+               dptr = findch(dptr,',');
+               *dptr++ = '\0';
+               chksize(dname);
+               if (Sym[i = lookup(dname)].usage&DCL)
+                       error("`%s' declared twice on line %d (905)", 
+                               dname, Lineno);
+               else
+                       Sym[i].usage =| DCL;
+               NONBLANK(dptr);
+       }
+}
+
+
+/*
+ * Errfunc calls fatal which stops the process.
+ */
+
+errfunc(eptr)
+char *eptr;
+{
+       warn("ERROR:%s\n",replace(eptr));
+       error("err statement on line %d (915)", Lineno);
+}
+
+
+/*
+ * Endfunc indicates an end has been found by decrementing the if count
+ * flag.  If because of a previous if statement, text was being skipped,
+ * Delflag is also decremented.
+ */
+
+endfunc()
+{
+       if (--Ifcount < 0)
+               error("`end' without matching `if' on line %d (910)",Lineno);
+       if (Delflag > 0)
+               Delflag--;
+       return;
+}
+
+
+/*
+ * Msgfunc accepts a pointer to a line and prints that line on the 
+ * diagnostic output.
+ */
+
+msgfunc(mptr)
+char *mptr;
+{
+       warn("Message(%d):%s\n", Lineno, replace(mptr));
+}
+
+
+repfunc(s)
+char *s;
+{
+       fprintf(stdout,"%s\n",replace(s));
+}
+
+
+/*
+ * Iffunc and the three functions following it, door, doand, and exp
+ * are responsible for parsing and interperting the condition in the
+ * if statement.  The BNF used is as follows:
+ *     <iffunc> ::=   [ "not" ] <door> EOL
+ *     <door> ::=     <doand> | <doand> "|" <door>
+ *     <doand>::=     <exp> | <exp> "&" <doand>
+ *     <exp>::=       "(" <door> ")" | <value> <operator> <value>
+ *     <operator>::=  "=" | "!=" | "<" | ">"
+ * And has precedence over or.  If the condition is false the Delflag
+ * is bumped to indicate that lines are to be skipped.
+ * An external variable, sptr is used for processing the line in
+ * iffunc, door, doand, exp, getid.
+ * Iffunc accepts a pointer to a line and sets sptr to that line.  The
+ * rest of iffunc, door, and doand follow the BNF exactly.
+ */
+
+char *sptr;
+
+iffunc(iptr)
+char *iptr;
+{
+       register int value, not;
+
+       Ifcount++;
+       if (Delflag > 0)
+               Delflag++;
+
+       else {
+               sptr = replace(iptr);
+               NONBLANK(sptr);
+               if (imatch("not ", sptr)) {
+                       not = FALSE;
+                       sptr =+ 4;
+               }
+               else not = TRUE;
+
+               value = door();
+               if( *sptr != 0)
+                       error("syntax on line %d (918)",Lineno);
+
+               if (value != not)
+                       Delflag++;
+       }
+
+       return;
+}
+
+
+door()
+{
+       int value;
+       value = doand();
+       NONBLANK(sptr);
+       while (*sptr=='|') {
+               sptr++;
+               value =| doand();
+               NONBLANK(sptr);
+       }
+       return(value);
+}
+
+
+doand()
+{
+       int value;
+       value = exp();
+       NONBLANK(sptr);
+       while (*sptr=='&') {
+               sptr++;
+               value =& exp();
+               NONBLANK(sptr);
+       }
+       return(value);
+}
+
+
+/*
+ * After exp checks for parentheses, it picks up a value by calling getid,
+ * picks up an operator and calls getid to pick up the second value.
+ * Then based on the operator it calls either numcomp or equal to see
+ * if the exp is true or false and returns the correct value.
+ */
+
+exp()
+{
+       register char op, save;
+       register int value;
+       char *id1, *id2, next;
+
+       NONBLANK(sptr);
+       if(*sptr == '(') {
+               sptr++;
+               value = door();
+               NONBLANK(sptr);
+               if (*sptr == ')') {
+                       sptr++;
+                       return(value);
+               }
+               else error("parenthesis error on line %d (911)",Lineno);
+       }
+
+       id1 = getid(sptr);
+       if (op = *sptr)
+               *sptr++ = '\0';
+       if (op == NEQ && (next = *sptr++) == '\0')
+               --sptr;
+       id2 = getid(sptr);
+       save = *sptr;
+       *sptr = '\0';
+
+       if(op ==LT || op == GT) {
+               value = numcomp(id1, id2);
+               if ((op == GT && value == 1) || (op == LT && value == -1))
+                       value = TRUE;
+               else value = FALSE;
+       }
+
+       else if (op==EQ || (op==NEQ && next==EQ)) {
+               value = equal(id1, id2);
+               if ( op == NEQ)
+                       value = !value;
+       }
+
+       else error("invalid operator on line %d (912)", Lineno);
+       *sptr = save;
+       return(value);
+}
+
+
+/*
+ * Getid picks up a value off a line and returns a pointer to the value.
+ */
+
+getid(gptr)
+register char *gptr;
+{
+       register char c, *id;
+
+       NONBLANK(gptr);
+       id = gptr;
+       gptr = findstr(gptr,DELIM);
+       if (*gptr)
+               *gptr++ = '\0';
+       NONBLANK(gptr);
+       sptr = gptr;
+       return(id);
+}
+
+
+/*
+ * Numcomp accepts two pointers to strings of digits and calls numck
+ * to see if the strings contain only digits.  It returns -1 if
+ * the first is less than the second, 1 if the first is greater than the
+ * second and 0 if the two are equal.
+ */
+
+numcomp(id1, id2)
+register char *id1, *id2;
+{
+       int k1, k2;
+
+       numck(id1);
+       numck(id2);
+       while (*id1 == '0')
+               id1++;
+       while (*id2 == '0')
+               id2++;
+       if ((k1 = size(id1)) > (k2 = size(id2)))
+               return(1);
+       else if (k1 < k2)
+               return(-1);
+       else while(*id1 != '\0') {
+               if(*id1 > *id2)
+                       return(1);
+               else if(*id1 < *id2)
+                       return(-1);
+               id1++;
+               id2++;
+       }
+       return(0);
+}
+
+
+/*
+ * Numck accepts a pointer to a string and checks to see if they are
+ * all digits.  If they're not it calls fatal, otherwise it returns.
+ */
+
+numck(nptr)
+register char *nptr;
+{
+       for (; *nptr != '\0'; nptr++)
+               if (!numeric(*nptr))
+                       error("non-numerical value on line %d (914)",Lineno);
+       return;
+}
+
+
+/*
+ * Replace accepts a pointer to a line and scans the line for a keyword
+ * enclosed in control characters.  If it doesn't find one it returns
+ * a pointer to the begining of the line.  Otherwise, it calls
+ * lookup to find the keyword.
+ * It rewrites the line substituting the value for the
+ * keyword enclosed in control characters.  It then continues scanning
+ * the line until no control characters are found and returns a pointer to
+ * the begining of the new line.
+ */
+
+# define INCR(int) if (++int==NSLOTS) error(subrng,Lineno)
+char *subrng "out of space [line %d] (916)";
+
+replace(ptr)
+char *ptr;
+{
+       char *slots[NSLOTS];
+       int i,j,newlen;
+       register char *s, *t, *p;
+
+       for (s=ptr; *s++!='\n';);
+       *(--s) = '\0';
+       Linend = s;
+       i = -1;
+       for (p=ptr; *(s=findch(p,Ctlchar)); p=t) {
+               *s++ = '\0';
+               INCR(i);
+               slots[i] = p;
+               if (*(t=findch(s,Ctlchar))==0)
+                       error("unmatched `%c' on line %d (907)",Ctlchar,Lineno);
+               *t++ = '\0';
+               INCR(i);
+               slots[i] = Sym[j = lookup(s)].value;
+               Sym[j].usage =| USD;
+       }
+       INCR(i);
+       slots[i] = p;
+       if (i==0) return(ptr);
+       newlen = 0;
+       for (j=0; j<=i; j++)
+               newlen =+ (size(slots[j])-1);
+       t = Repflag = alloc(++newlen);
+       for (j=0; j<=i; j++)
+               t = ecopy(slots[j],t);
+       Linend = t;
+       return(Repflag);
+}
+
+
+/*
+ * Lookup accepts a pointer to a keyword name and searches the symbol
+ * table for the keyword.  It returns its index in the table if its there,
+ * otherwise it puts the keyword in the table.
+ */
+
+lookup(lname)
+char *lname;
+{
+       register int i;
+       register char *t;
+       register struct symtab *s;
+
+       t = lname;
+       while ((i.chr = *t++) &&
+               ((i.chr>='A' && i.chr<='Z') || (i.chr>='a' && i.chr<='z') ||
+                       (i.chr!= *lname && i.chr>='0' && i.chr<='9')));
+       if (i.chr)
+               error("invalid keyword name on line %d (909)",Lineno);
+
+       for(i =0; Sym[i].usage != 0 && i<SYMSIZE; i++)
+               if (equal(lname, Sym[i].name)) return(i);
+       s = &Sym[i];
+       if (s->usage == 0) {
+               copy(lname,s->name);
+               copy("",(s->value = alloc(s->lenval = 1)));
+               return(i);
+       }
+       error("out of space (906)");
+}
+
+
+/*
+ * Putin accepts a pointer to a keyword name, and a pointer to a value.
+ * It puts this information in the symbol table by calling lookup.
+ * It returns the index of the name in the table.
+ */
+
+putin(pname, pvalue)
+char *pname;
+char *pvalue;
+{
+       register int i;
+       register struct symtab *s;
+
+       s = &Sym[i = lookup(pname)];
+       free(s->value);
+       s->lenval = size(pvalue);
+       copy(pvalue, (s->value = alloc(s->lenval)));
+       s->usage =| ASG;
+       return(i);
+}
+
+
+chksize(s)
+char *s;
+{
+       if (size(s) > PARMSIZE)
+               error("keyword name too long on line %d (908)",Lineno);
+}
+
+
+findch(astr,match)
+char *astr, match;
+{
+       register char *s, *t, c;
+       char *temp;
+
+       for (s=astr; (c = *s) && c!=match; s++)
+               if (c=='\\') {
+                       if (s[1]==0)
+                               error("syntax on line %d (919)",Lineno);
+                       else {
+                               for (t = (temp=s) + 1; *s++ = *t++;);
+                               s = temp;
+                       }
+               }
+       return(s);
+}
+
+
+ecopy(s1,s2)
+char *s1, *s2;
+{
+       register char *r1, *r2;
+
+       r1 = s1;
+       r2 = s2;
+       while (*r2++ = *r1++);
+       return(--r2);
+}
+
+
+error(arg)
+{
+       fatal(sprintf(Error,"%r",&arg));
+}
+
+
+findstr(astr,pat)
+char *astr, *pat;
+{
+       register char *s, *t, c;
+       char *temp;
+
+       for (s=astr; (c = *s) && any(c,pat)==0; s++)
+               if (c=='\\') {
+                       if (s[1]==0)
+                               error("syntax on line %d (919)",Lineno);
+                       else {
+                               for (t = (temp=s) + 1; *s++ = *t++;);
+                               s = temp;
+                       }
+               }
+       return(s);
+}
+
+
+warn(arg)
+{
+       if (!Silent)
+               fprintf(stderr,"%r",&arg);
+}
Index:  cmd/what.c
--- UNSW-87-record0:sccs4/cmd/what.c    1978-09-07 19:22:17.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/cmd/what.c       1981-01-15 00:16:52.000000000 -0500
@@ -1,7 +1,7 @@
-# include      <stdio.h>
-# include      <macros.h>
+# include      "stdio.h"
+# include      "../hdr/macros.h"
 
-SCCSID(@(#)what.c      4.4);
+SCCSID(@(#)what.c      4.1);
 
 char pattern[] "@(#)";
 char opattern[] "~|^`";
Index:  com/auxf.c
--- UNSW-87-record0:sccs4/com/auxf.c    1978-09-07 19:22:18.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/auxf.c       1990-04-10 22:49:35.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)auxf        1.2);
+SCCSID(@(#)auxf        2.1);
 
 /*
        Figures out names for g-file, l-file, x-file, etc.
Index:  com/chkid.c
--- UNSW-87-record0:sccs4/com/chkid.c   1978-09-07 19:22:18.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/chkid.c      1990-04-10 22:49:36.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)chkid       1.3);
+SCCSID(@(#)chkid       2.1);
 
 chkid(line)
 char *line;
Index:  com/chksid.c
--- UNSW-87-record0:sccs4/com/chksid.c  1978-09-07 19:22:18.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/chksid.c     1990-04-10 22:49:36.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)chksid      1.2);
+SCCSID(@(#)chksid      2.1);
 
 chksid(p,sp)
 char *p;
Index:  com/date_ab.c
--- UNSW-87-record0:sccs4/com/date_ab.c 1978-09-07 19:22:18.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/date_ab.c    1981-01-28 10:52:48.000000000 -0500
@@ -1,6 +1,7 @@
-# include      <macros.h>
+# include      "../hdr/macros.h"
+
+SCCSID(@(#)date_ab.c   4.2);
 
-SCCSID(@(#)date_ab     1.1);
 /*
        Function to convert date in the form "yymmddhhmmss" to
        standard UNIX time (seconds since Jan. 1, 1970 GMT).
@@ -21,8 +22,12 @@
 {
        int y, t, d, h, m, s, i;
        long tim;
-       extern int timezone, *localtime();
+       extern int *localtime();
+#define        time_t  long
+#include <sys/timeb.h>
+       struct timeb timeb;
 
+       ftime(&timeb);
        Datep = adt;
 
        if((y=g2()) == -2) y = 99;
@@ -54,10 +59,10 @@
        tim =+ h;
        tim =* 60;
        tim =+ m;
+       tim =+ timeb.timezone;                  /* GMT correction */
        tim =* 60;
        tim =+ s;
 
-       tim =+ timezone;                        /* GMT correction */
        if(localtime(&tim)[8])
                tim =+ -1*60*60;                /* daylight savings */
        *bdt = tim;
Index:  com/date_ba.c
--- UNSW-87-record0:sccs4/com/date_ba.c 1978-09-07 19:22:18.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/date_ba.c    1990-04-10 22:49:37.000000000 -0400
@@ -1,22 +1,22 @@
 # include      "../hdr/defines.h"
 # define DO2(p,n,c)    *p++ = n/10 + '0'; *p++ = n%10 + '0'; *p++ = c;
 
-SCCSID(@(#)date_ba     1.2);
+SCCSID(@(#)date_ba     2.1.1.1);
 
 date_ba(bdt,adt)
 long *bdt;
 char *adt;
 {
-       register struct time *lcltm;
+       register struct tm *lcltm;
        register char *p;
 
        lcltm = localtime(bdt);
        p = adt;
-       DO2(p,lcltm->t_year,'/');
-       DO2(p,(lcltm->t_month + 1),'/');
-       DO2(p,lcltm->t_day_month,' ');
-       DO2(p,lcltm->t_hours,':');
-       DO2(p,lcltm->t_minutes,':');
-       DO2(p,lcltm->t_seconds,0);
+       DO2(p,lcltm->tm_year,'/');
+       DO2(p,(lcltm->tm_mon + 1),'/');
+       DO2(p,lcltm->tm_mday,' ');
+       DO2(p,lcltm->tm_hour,':');
+       DO2(p,lcltm->tm_min,':');
+       DO2(p,lcltm->tm_sec,0);
        return(adt);
 }
Index:  com/del_ab.c
--- UNSW-87-record0:sccs4/com/del_ab.c  1978-09-07 19:22:19.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/del_ab.c     1982-05-10 14:06:29.000000000 -0400
@@ -1,12 +1,13 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)del_ab      1.2);
+SCCSID(@(#)del_ab      2.1);
 
 del_ab(p,dt,pkt)
 register char *p;
 register struct deltab *dt;
 struct packet *pkt;
 {
+       extern  char    *satoi();
        int n;
        extern char *Datep;
 
Index:  com/del_ba.c
--- UNSW-87-record0:sccs4/com/del_ba.c  1978-09-07 19:22:19.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/del_ba.c     1990-04-10 22:49:38.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)del_ba      1.2);
+SCCSID(@(#)del_ba      2.1);
 
 del_ba(dt,str)
 register struct deltab *dt;
Index:  com/dodelt.c
--- UNSW-87-record0:sccs4/com/dodelt.c  1978-09-07 19:22:19.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/dodelt.c     1981-04-13 16:26:15.000000000 -0500
@@ -2,7 +2,7 @@
 
 # define ONEYEAR 31536000L
 
-SCCSID(@(#)dodelt      1.8);
+SCCSID(@(#)dodelt      2.1);
 
 long   Timenow;
 
@@ -15,6 +15,7 @@
 struct sid *sidp;
 char type;
 {
+       extern  char    *satoi();
        struct deltab dt;
        register struct idel *rdp;
        int n, founddel;
@@ -29,7 +30,7 @@
        while (getadel(pkt,&dt) == BDELTAB) {
                if (pkt->p_idel == 0) {
                        if (Timenow < dt.d_datetime)
-                               fatal("clock set wrong!!! (co10)");
+                               fprintf(stderr,"Clock may be set wrong! (co11)");
                        timediff = Timenow - dt.d_datetime;
                        if (timediff > ONEYEAR && pkt->p_verbose)
                                fprintf(stderr,"Clock may be set wrong! (co11)\n");
@@ -68,10 +69,13 @@
                                switch (pkt->p_line[1]) {
                                case EDELTAB:
                                        break;
-                               default:
+                               case COMMENTS:
+                               case MRNUM:
                                        if (founddel)
                                                escdodelt(pkt);
                                        continue;
+                               default:
+                                       fmterr(pkt);
                                case INCLUDE:
                                case EXCLUDE:
                                case IGNORE:
Index:  com/dofile.c
--- UNSW-87-record0:sccs4/com/dofile.c  1978-09-07 19:22:19.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/dofile.c     1981-01-14 15:17:25.000000000 -0500
@@ -1,7 +1,7 @@
-# include      <dir.h>
 # include      "../hdr/defines.h"
+# include      "dir.h"
 
-SCCSID(@(#)dofile      1.3);
+SCCSID(@(#)dofile.c    1.1);
 
 int    nfiles;
 char   had_dir;
@@ -31,7 +31,7 @@
                        }
                }
        }
-       else if (exists(p) && (Statbuf.i_mode & IFMT) == IFDIR) {
+       else if (exists(p) && (Statbuf.st_mode & S_IFMT) == S_IFDIR) {
                had_dir = 1;
                Ffile = p;
                if((iop = fopen(p,"r")) == NULL)
Index:  com/dohist.c
--- UNSW-87-record0:sccs4/com/dohist.c  1978-09-07 19:22:19.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/dohist.c     1985-05-03 13:18:28.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)dohist      1.3);
+SCCSID(@(#)dohist      2.1);
 
 char   Cstr[RESPSIZE];
 char   Mstr[RESPSIZE];
@@ -8,7 +8,7 @@
 dohist(file)
 char *file;
 {
-       char line[512];
+       char line[BUFSIZ];
        int tty[3];
        int doprmt;
        register char *p;
@@ -54,7 +54,7 @@
 char *repstr;
 char *result;
 {
-       char line[512];
+       char line[BUFSIZ];
        register int done, sz;
        register char *p;
 
Index:  com/doie.c
--- UNSW-87-record0:sccs4/com/doie.c    1978-09-07 19:22:19.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/doie.c       1990-04-10 22:49:39.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)doie        1.2);
+SCCSID(@(#)doie        2.1);
 
 doie(pkt,ilist,elist,glist)
 struct packet *pkt;
Index:  com/dolist.c
--- UNSW-87-record0:sccs4/com/dolist.c  1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/dolist.c     1981-01-15 13:32:45.000000000 -0500
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)dolist      1.2);
+SCCSID(@(#)dolist.c    4.2);
 
 static char br[] "bad range (co12)";
 
@@ -27,7 +27,9 @@
                                sid.s_br = sid.s_seq = 0;
                                for (sid.s_rel = lowsid.s_rel; sid.s_rel <= highsid.s_rel; sid.s_rel++) {
                                        sid.s_lev = (sid.s_rel == lowsid.s_rel ? lowsid.s_lev : 1);
-                                       for ( ; n = sidtoser(&sid,pkt); sid.s_lev++)
+                                       for ( ; (sid.s_rel < highsid.s_rel ||
+                                                sid.s_lev <= highsid.s_lev) &&
+                                               (n = sidtoser(&sid,pkt)); sid.s_lev++)
                                                enter(pkt,ch,n,&sid);
                                }
                        }
Index:  com/eqsid.c
--- UNSW-87-record0:sccs4/com/eqsid.c   1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/eqsid.c      1990-04-10 22:49:39.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)eqsid       1.2);
+SCCSID(@(#)eqsid       2.1);
 
 eqsid(s1, s2)
 register struct sid *s1, *s2;
Index:  com/flushto.c
--- UNSW-87-record0:sccs4/com/flushto.c 1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/flushto.c    1990-04-10 22:49:40.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)flushto     1.2);
+SCCSID(@(#)flushto     2.1);
 
 flushto(pkt,ch,put)
 register struct packet *pkt;
Index:  com/fmterr.c
--- UNSW-87-record0:sccs4/com/fmterr.c  1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/fmterr.c     1988-02-02 15:42:30.000000000 -0500
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)fmterr      1.2);
+SCCSID(@(#)fmterr      2.1);
 
 fmterr(pkt)
 register struct packet *pkt;
Index:  com/getline.c
--- UNSW-87-record0:sccs4/com/getline.c 1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/getline.c    1987-02-15 16:36:03.000000000 -0500
@@ -1,6 +1,6 @@
 #include       "../hdr/defines.h"
 
-SCCSID(@(#)getline     1.3);
+SCCSID(@(#)getline     2.1.1.1);
 /*
        Routine to read a line into the packet.  The main reason for
        it is to make sure that pkt->p_wrttn gets turned off,
@@ -28,7 +28,7 @@
                }
                if (!pkt->p_chkeof)
                        fatal("premature eof (co5)");
-               if (pkt->p_ihash && pkt->p_chash != pkt->p_ihash)
+               if (pkt->do_chksum && (pkt->p_chash ^ pkt->p_ihash)&0xFFFF)
                        fatal("corrupted file (co6)");
                if (pkt->p_reopen) {
                        fseek(pkt->p_iop,0L,0);
@@ -38,6 +38,7 @@
                        pkt->p_chash = 0;
                        pkt->p_nhash = 0;
                        pkt->p_keep = 0;
+                       pkt->do_chksum = 0;
                }
        }
        return(n);
Index:  com/newstats.c
--- UNSW-87-record0:sccs4/com/newstats.c        1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/newstats.c   1988-02-02 15:43:40.000000000 -0500
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)newstats    1.2);
+SCCSID(@(#)newstats    2.1);
 
 newstats(pkt,strp,ch)
 register struct packet *pkt;
Index:  com/permiss.c
--- UNSW-87-record0:sccs4/com/permiss.c 1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/permiss.c    1983-11-11 15:53:14.000000000 -0500
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)permiss     1.4);
+SCCSID(@(#)permiss.c   1.1);
 
 finduser(pkt)
 register struct packet *pkt;
@@ -8,22 +8,20 @@
        register char *p;
        register int i;
        char *user;
+       char *strend();
+       char userid[6];
        int none;
 
        none = 1;
        user = logname();
+       sprintf(userid,"%d",getuid() & 0377);
        while ((p = getline(pkt)) != NULL && *p != CTLCHAR) {
                none = 0;
+               repl(p,'\n','\0');      /* this is done for equal test below */
                if (!pkt->p_user)
-                       for (i = 0; p[i]; i++) {
-                               if (p[i] == '\n') {
-                                       if (!user[i])
-                                               pkt->p_user = 1;
-                                       break;
-                               }
-                               if (p[i] != user[i])
-                                       break;
-                       }
+                       if (equal(user,p) || equal(userid,p))
+                               pkt->p_user = 1;
+               *(strend(p)) = '\n';    /* repl \0 end of line w/ \n again */
        }
        if (none)
                pkt->p_user = 1;
@@ -65,12 +63,12 @@
        if (!pkt->p_user)
                fatal("not authorized to make deltas (co14)");
        if (p = Sflags[FLORFLAG - 'a']) {
-               if (pkt->p_reqsid.s_rel.unsignd < (n = patoi(p)))
+               if (((unsigned)pkt->p_reqsid.s_rel) < (n = patoi(p)))
                        fatal(sprintf(Error,"release %u < %u (floor) (co15)",
                                pkt->p_reqsid.s_rel,n));
        }
        if (p = Sflags[CEILFLAG - 'a'])
-               if (pkt->p_reqsid.s_rel.unsignd > (n = patoi(p)))
+               if (((unsigned)pkt->p_reqsid.s_rel) > (n = patoi(p)))
                        fatal(sprintf(Error,"release %u > %u (ceiling) (co16)",
                                pkt->p_reqsid.s_rel,n));
 }
Index:  com/pf_ab.c
--- UNSW-87-record0:sccs4/com/pf_ab.c   1978-09-07 19:22:20.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/pf_ab.c      1981-04-13 16:06:51.000000000 -0500
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)pf_ab       1.4);
+SCCSID(@(#)pf_ab       2.1.1.1);
 
 pf_ab(s,pp,all)
 char *s;
@@ -26,7 +26,7 @@
        ++p;
        i = index(p," ");
        pp->pf_user[0] = 0;
-       if (i.unsignd < 8) {
+       if (((unsigned)i) < 8) {
                move(p,pp->pf_user,i);
                pp->pf_user[i] = 0;
        }
Index:  com/putline.c
--- UNSW-87-record0:sccs4/com/putline.c 1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/putline.c    1985-05-03 12:36:28.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)putline     1.4);
+SCCSID(@(#)putline     2.1.1.1);
 /*
        Routine to write out either the current line in the packet
        (if newline is zero) or the line specified by newline.
@@ -28,9 +28,9 @@
        if(!Xcreate) {
                stat(pkt->p_file,&Statbuf);
                xf = auxf(pkt->p_file,'x');
-               Xiop = xfcreat(xf,Statbuf.i_mode);
+               Xiop = xfcreat(xf,Statbuf.st_mode);
                setbuf(Xiop,obf);
-               chown(xf,(Statbuf.i_gid<<8)|Statbuf.i_uid);
+               chown(xf,Statbuf.st_uid,Statbuf.st_gid);
        }
        if (newline)
                p = newline;
@@ -74,7 +74,7 @@
                        pkt->p_nhash =+ (*p - '0');
        }
 
-       sprintf(hash,"%5u",pkt->p_nhash);
+       sprintf(hash,"%5u",pkt->p_nhash&0xFFFF);
        zeropad(hash);
        fprintf(Xiop,"%c%c%s\n",CTLCHAR,HEAD,hash);
        if (stats)
Index:  com/rdmod.c
--- UNSW-87-record0:sccs4/com/rdmod.c   1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/rdmod.c      1987-02-15 16:35:33.000000000 -0500
@@ -1,13 +1,14 @@
 # include      "../hdr/defines.h"
 # define msg(s,help)   fprintf(pkt->p_stdout,msgstr,s,pkt->p_glnno,help)
 
-SCCSID(@(#)rdmod       1.2);
+SCCSID(@(#)rdmod       2.1);
 
 static char msgstr[]   "Inex conflict %s at line %u (%s)\n";
 
 readmod(pkt)
 register struct packet *pkt;
 {
+       extern  char    *satoi();
        register char *p;
        int ser;
        int iord;
Index:  com/setup.c
--- UNSW-87-record0:sccs4/com/setup.c   1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/setup.c      1985-05-03 12:36:29.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)setup       1.2);
+SCCSID(@(#)setup       2.2);
 
 setup(pkt,serial)
 register struct packet *pkt;
@@ -8,16 +8,25 @@
 {
        register int n;
        register struct apply *rap;
+       int     first_app       1;
 
        pkt->p_apply[serial].a_inline = 1;
        for (n = maxser(pkt); n; n--) {
                rap = &pkt->p_apply[n];
                if (rap->a_inline) {
+                       if (n != 1 && pkt->p_idel[n].i_pred == 0)
+                               fmterr(pkt);
                        pkt->p_apply[pkt->p_idel[n].i_pred].a_inline = 1;
                        if (pkt->p_idel[n].i_datetime > pkt->p_cutoff)
                                condset(rap,NOAPPLY,CUTOFF);
-                       else
+                       else {
+                               if (first_app)
+                                       move(&pkt->p_idel[n].i_sid,
+                                            &pkt->p_gotsid,
+                                            sizeof(pkt->p_gotsid));
+                               first_app = 0;
                                condset(rap,APPLY,EMPTY);
+                       }
                }
                else
                        condset(rap,NOAPPLY,EMPTY);
Index:  com/sid_ab.c
--- UNSW-87-record0:sccs4/com/sid_ab.c  1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/sid_ab.c     1990-04-10 22:49:42.000000000 -0400
@@ -1,11 +1,12 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)sid_ab      1.2);
+SCCSID(@(#)sid_ab      2.1);
 
 sid_ab(p,sp)
 register char *p;
 register struct sid *sp;
 {
+       extern  char    *satoi();
        if (*(p = satoi(p,&sp->s_rel)) == '.')
                p++;
        if (*(p = satoi(p,&sp->s_lev)) == '.')
Index:  com/sid_ba.c
--- UNSW-87-record0:sccs4/com/sid_ba.c  1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/sid_ba.c     1990-04-10 22:49:43.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)sid_ba      1.2);
+SCCSID(@(#)sid_ba      2.1);
 
 sid_ba(sp,p)
 register struct sid *sp;
Index:  com/sidtoser.c
--- UNSW-87-record0:sccs4/com/sidtoser.c        1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/sidtoser.c   1990-04-10 22:49:43.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)sidtoser    1.2);
+SCCSID(@(#)sidtoser    2.1);
 
 sidtoser(sp,pkt)
 register struct sid *sp;
Index:  com/sinit.c
--- UNSW-87-record0:sccs4/com/sinit.c   1978-09-07 19:22:21.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/sinit.c      1985-05-03 12:36:31.000000000 -0400
@@ -1,6 +1,6 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)sinit       1.4);
+SCCSID(@(#)sinit       2.1);
 /*
        Does initialization for sccs files and packet.
 */
@@ -9,6 +9,7 @@
 register struct packet *pkt;
 register char *file;
 {
+       extern  char    *satoi();
        register char *p;
 
        zero(pkt,sizeof(*pkt));
@@ -18,11 +19,12 @@
                fatal("not an SCCS file (co1)");
        copy(file,pkt->p_file);
        pkt->p_wrttn = 1;
+       pkt->do_chksum = 1;     /* turn on checksum check for getline */
        if (openflag) {
                pkt->p_iop = xfopen(file,0);
                setbuf(pkt->p_iop,pkt->p_buf);
                fstat(fileno(pkt->p_iop),&Statbuf);
-               if (Statbuf.i_nlink > 1)
+               if (Statbuf.st_nlink > 1)
                        fatal("more than one link (co3)");
                if ((p = getline(pkt)) == NULL || *p++ != CTLCHAR || *p++ != HEAD) {
                        fclose(pkt->p_iop);
Index:  com/stats_ab.c
--- UNSW-87-record0:sccs4/com/stats_ab.c        1978-09-07 19:22:22.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/com/stats_ab.c   1990-04-10 22:49:43.000000000 -0400
@@ -1,11 +1,12 @@
 # include      "../hdr/defines.h"
 
-SCCSID(@(#)stats_ab    1.2);
+SCCSID(@(#)stats_ab    2.1);
 
 stats_ab(pkt,statp)
 register struct packet *pkt;
 register struct stats *statp;
 {
+       extern  char    *satoi();
        register char *p;
 
        p = pkt->p_line;
Index:  hdr/defines.h
--- UNSW-87-record0:sccs4/hdr/defines.h 1978-09-07 19:22:22.000000000 -0400
+++ CSRG-cd4-sccscmds-19810205/hdr/defines.h    1981-04-13 16:00:27.000000000 -0500
@@ -1,11 +1,10 @@
 # include      "stdio.h"
-# include      "macros.h"
-# include      "fatal.h"
+# include      "../hdr/macros.h"
+# include      "../hdr/fatal.h"
 # include      "time.h"
-# include      "misc.h"
 
 /*
- *     s.h 1.6 of 4/20/77
+ *     defines.h 2.3 of 5/18/78
  */
 
 # define CTLSTR                "%c%c\n"
@@ -29,6 +28,7 @@
 # define NFLAGS        26
 
 # define FLAG          'f'
+# define NULLFLAG      'n'
 # define DEFTFLAG      'd'
 # define TYPEFLAG      't'
 # define VALFLAG       'v'
@@ -45,10 +45,24 @@
 # define DEL           'D'
 # define END           'E'
 
-# define FILESIZE      50
+# define FILESIZE      510
 # define MAX           9999
 # define DELIVER       '*'
 
+/*
+       Declares for external subroutines and/or functions
+*/
+
+extern char    *sname();
+extern char    *cat();
+extern char    *dname();
+extern char    *repeat();
+extern char    *satoi();
+extern char    *strend();
+extern char    *substr();
+extern char    *trnslat();
+extern char    *zero();
+extern char    *zeropad();
 
 /*
        SCCS Internal Structures.
@@ -83,7 +97,6 @@
 };
 #define YES     (1)
 #define NO     (-1)
-#define NULL    (0)
 
 
 struct sid {
@@ -153,6 +166,7 @@
        int     p_ixmsg;        /* inex msg counter */
        int     p_reopen;       /* reopen flag used by getline on eof */
        int     p_ixuser;       /* HADI | HADX (in get) */
+       int     do_chksum;      /* for getline(), 1 = do check sum */
 };
 /*
        Masks for p_verbose