--------------------------------------------------------------------------------
   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