pass flags selectively to things like "delget"
[unix-history] / usr / src / usr.bin / sccs / sccs.c
index b55043f..a72026c 100644 (file)
 **             UIDUSER -- determine who the user is by looking at the
 **                     uid rather than the login name -- for machines
 **                     where SCCS gets the user in this way.
 **             UIDUSER -- determine who the user is by looking at the
 **                     uid rather than the login name -- for machines
 **                     where SCCS gets the user in this way.
-**             SRCDIR -- if defined, forces the -d flag to take on
+**             SCCSDIR -- if defined, forces the -d flag to take on
 **                     this value.  This is so that the setuid
 **                     aspects of this program cannot be abused.
 **                     this value.  This is so that the setuid
 **                     aspects of this program cannot be abused.
+**                     This flag also disables the -p flag.
+**             SCCSPATH -- the default for the -p flag.
 **
 **     Compilation Instructions:
 **             cc -O -n -s sccs.c
 **
 **     Author:
 **             Eric Allman, UCB/INGRES
 **
 **     Compilation Instructions:
 **             cc -O -n -s sccs.c
 **
 **     Author:
 **             Eric Allman, UCB/INGRES
+**             Copyright 1980 Regents of the University of California
 */
 
 */
 
+/*******************  Configuration Information  ********************/
+
 # ifdef CSVAX
 # define UIDUSER
 # ifdef CSVAX
 # define UIDUSER
-# endif
+# define PROGPATH(name)        "/usr/local/name"
+# endif CSVAX
+
+# define SCCSPATH      "SCCS"
+/* put #define SCCSDIR here */
+
+char   MyName[] = "sccs";      /* name used in messages */
 
 
-static char SccsId[] = "@(#)sccs.c     1.28 %G%";
+/****************  End of Configuration Information  ****************/
+
+static char SccsId[] = "@(#)sccs.c     1.32 %G%";
 
 # define bitset(bit, word)     ((bit) & (word))
 
 
 # define bitset(bit, word)     ((bit) & (word))
 
@@ -99,13 +112,12 @@ typedef char       bool;
 # include <pwd.h>
 # endif UIDUSER
 
 # include <pwd.h>
 # endif UIDUSER
 
-char   MyName[] = "sccs";
-
 struct sccsprog
 {
        char    *sccsname;      /* name of SCCS routine */
        short   sccsoper;       /* opcode, see below */
        short   sccsflags;      /* flags, see below */
 struct sccsprog
 {
        char    *sccsname;      /* name of SCCS routine */
        short   sccsoper;       /* opcode, see below */
        short   sccsflags;      /* flags, see below */
+       char    *sccsklets;     /* valid key-letters on macros */
        char    *sccspath;      /* pathname of binary implementing */
 };
 
        char    *sccspath;      /* pathname of binary implementing */
 };
 
@@ -125,34 +137,30 @@ struct sccsprog
 # define INFOC         1       /* info command */
 # define CHECKC                2       /* check command */
 
 # define INFOC         1       /* info command */
 # define CHECKC                2       /* check command */
 
-# ifdef CSVAX
-# define PROGPATH(name)        "/usr/local/name"
-# endif CSVAX
-
 # ifndef PROGPATH
 # define PROGPATH(name)        "/usr/sccs/name"
 # endif PROGPATH
 
 struct sccsprog SccsProg[] =
 {
 # ifndef PROGPATH
 # define PROGPATH(name)        "/usr/sccs/name"
 # endif PROGPATH
 
 struct sccsprog SccsProg[] =
 {
-       "admin",        PROG,   REALUSER,               PROGPATH(admin),
-       "chghist",      PROG,   0,                      PROGPATH(rmdel),
-       "comb",         PROG,   0,                      PROGPATH(comb),
-       "delta",        PROG,   0,                      PROGPATH(delta),
-       "get",          PROG,   0,                      PROGPATH(get),
-       "help",         PROG,   NO_SDOT,                PROGPATH(help),
-       "prt",          PROG,   0,                      PROGPATH(prt),
-       "rmdel",        PROG,   REALUSER,               PROGPATH(rmdel),
-       "what",         PROG,   NO_SDOT,                PROGPATH(what),
-       "edit",         CMACRO, 0,                      "get -e",
-       "delget",       CMACRO, 0,                      "delta/get",
-       "deledit",      CMACRO, 0,                      "delta/get -e",
-       "fix",          FIX,    0,                      NULL,
-       "clean",        CLEAN,  REALUSER,               (char *) CLEANC,
-       "info",         CLEAN,  REALUSER,               (char *) INFOC,
-       "check",        CLEAN,  REALUSER,               (char *) CHECKC,
-       "unedit",       UNEDIT, 0,                      NULL,
-       NULL,           -1,     0,                      NULL
+       "admin",        PROG,   REALUSER,       "",             PROGPATH(admin),
+       "chghist",      PROG,   0,              "",             PROGPATH(rmdel),
+       "comb",         PROG,   0,              "",             PROGPATH(comb),
+       "delta",        PROG,   0,              "mysrp",        PROGPATH(delta),
+       "get",          PROG,   0,              "ixbeskc",      PROGPATH(get),
+       "help",         PROG,   NO_SDOT,        "",             PROGPATH(help),
+       "prt",          PROG,   0,              "",             PROGPATH(prt),
+       "rmdel",        PROG,   REALUSER,       "",             PROGPATH(rmdel),
+       "what",         PROG,   NO_SDOT,        "",             PROGPATH(what),
+       "edit",         CMACRO, NO_SDOT,        "ixbsc",        "get -e",
+       "delget",       CMACRO, NO_SDOT,        "",             "delta/get -t",
+       "deledit",      CMACRO, NO_SDOT,        "",             "delta/get -e -t",
+       "fix",          FIX,    NO_SDOT,        "",             NULL,
+       "clean",        CLEAN,  REALUSER,       "",             (char *) CLEANC,
+       "info",         CLEAN,  REALUSER,       "",             (char *) INFOC,
+       "check",        CLEAN,  REALUSER,       "",             (char *) CHECKC,
+       "unedit",       UNEDIT, NO_SDOT,        "",             NULL,
+       NULL,           -1,     0,              "",             NULL
 };
 
 struct pfile
 };
 
 struct pfile
@@ -164,11 +172,11 @@ struct pfile
        char    *p_time;        /* time of get */
 };
 
        char    *p_time;        /* time of get */
 };
 
-char   *SccsPath = "SCCS";     /* pathname of SCCS files */
-# ifdef SRCDIR
-char   *SccsDir = SRCDIR;      /* directory to begin search from */
+char   *SccsPath = SCCSPATH;   /* pathname of SCCS files */
+# ifdef SCCSDIR
+char   *SccsDir = SCCSDIR;     /* directory to begin search from */
 # else
 # else
-char   *SccsDir = "";          /* directory to begin search from */
+char   *SccsDir = "";
 # endif
 bool   RealUser;               /* if set, running as real user */
 # ifdef DEBUG
 # endif
 bool   RealUser;               /* if set, running as real user */
 # ifdef DEBUG
@@ -181,6 +189,7 @@ main(argc, argv)
 {
        register char *p;
        extern struct sccsprog *lookup();
 {
        register char *p;
        extern struct sccsprog *lookup();
+       register int i;
 
        /*
        **  Detect and decode flags intended for this program.
 
        /*
        **  Detect and decode flags intended for this program.
@@ -206,7 +215,7 @@ main(argc, argv)
                                RealUser++;
                                break;
 
                                RealUser++;
                                break;
 
-# ifndef SRCDIR
+# ifndef SCCSDIR
                          case 'p':             /* path of sccs files */
                                SccsPath = ++p;
                                break;
                          case 'p':             /* path of sccs files */
                                SccsPath = ++p;
                                break;
@@ -231,44 +240,114 @@ main(argc, argv)
                        SccsPath = ".";
        }
 
                        SccsPath = ".";
        }
 
-       command(argv, FALSE);
-       exit(EX_OK);
+       i = command(argv, FALSE, FALSE, "");
+       exit(i);
 }
 }
+\f/*
+**  COMMAND -- look up and perform a command
+**
+**     This routine is the guts of this program.  Given an
+**     argument vector, it looks up the "command" (argv[0])
+**     in the configuration table and does the necessary stuff.
+**
+**     Parameters:
+**             argv -- an argument vector to process.
+**             forkflag -- if set, fork before executing the command.
+**             editflag -- if set, only include flags listed in the
+**                     sccsklets field of the command descriptor.
+**             arg0 -- a space-seperated list of arguments to insert
+**                     before argv.
+**
+**     Returns:
+**             zero -- command executed ok.
+**             else -- error status.
+**
+**     Side Effects:
+**             none.
+*/
 
 
-command(argv, forkflag)
+command(argv, forkflag, editflag, arg0)
        char **argv;
        bool forkflag;
        char **argv;
        bool forkflag;
+       bool editflag;
+       char *arg0;
 {
        register struct sccsprog *cmd;
        register char *p;
        register char *q;
        char buf[40];
        extern struct sccsprog *lookup();
 {
        register struct sccsprog *cmd;
        register char *p;
        register char *q;
        char buf[40];
        extern struct sccsprog *lookup();
-       char *nav[200];
-       char **avp;
+       char *nav[1000];
+       char **np;
+       char **ap;
        register int i;
        extern bool unedit();
        register int i;
        extern bool unedit();
+       int rval = 0;
+       extern char *index();
+       extern char *makefile();
 
 # ifdef DEBUG
        if (Debug)
        {
 
 # ifdef DEBUG
        if (Debug)
        {
-               printf("command:\n");
-               for (avp = argv; *avp != NULL; avp++)
-                       printf("    \"%s\"\n", *avp);
+               printf("command:\n\t\"%s\"\n", arg0);
+               for (np = argv; *np != NULL; np++)
+                       printf("\t\"%s\"\n", *np);
        }
 # endif
 
        }
 # endif
 
+       /*
+       **  Copy arguments.
+       **      Phase one -- from arg0 & if necessary argv[0].
+       */
+
+       np = nav;
+       for (p = arg0, q = buf; *p != '\0' && *p != '/'; )
+       {
+               *np++ = q;
+               while (*p == ' ')
+                       p++;
+               while (*p != ' ' && *p != '\0' && *p != '/')
+                       *q++ = *p++;
+               *q++ = '\0';
+       }
+       *np = NULL;
+       if (nav[0] == NULL)
+               *np++ = *argv++;
+
        /*
        **  Look up command.
        /*
        **  Look up command.
-       **      At this point, argv points to the command name.
+       **      At this point, nav[0] is the command name.
        */
 
        */
 
-       cmd = lookup(argv[0]);
+       cmd = lookup(nav[0]);
        if (cmd == NULL)
        {
                usrerr("Unknown command \"%s\"", argv[0]);
        if (cmd == NULL)
        {
                usrerr("Unknown command \"%s\"", argv[0]);
-               exit(EX_USAGE);
+               return (EX_USAGE);
+       }
+
+       /*
+       **  Copy remaining arguments doing editing as appropriate.
+       */
+
+       for (; *argv != NULL; argv++)
+       {
+               p = *argv;
+               if (*p == '-')
+               {
+                       if (p[1] == '\0' || !editflag || cmd->sccsklets == NULL ||
+                           index(cmd->sccsklets, p[1]) != NULL)
+                               *np++ = p;
+               }
+               else
+               {
+                       if (!bitset(NO_SDOT, cmd->sccsflags))
+                               p = makefile(p);
+                       if (p != NULL)
+                               *np++ = p;
+               }
        }
        }
+       *np = NULL;
 
        /*
        **  Interpret operation associated with this command.
 
        /*
        **  Interpret operation associated with this command.
@@ -277,64 +356,59 @@ command(argv, forkflag)
        switch (cmd->sccsoper)
        {
          case PROG:            /* call an sccs prog */
        switch (cmd->sccsoper)
        {
          case PROG:            /* call an sccs prog */
-               callprog(cmd->sccspath, cmd->sccsflags, argv, forkflag);
+               rval = callprog(cmd->sccspath, cmd->sccsflags, nav, forkflag);
                break;
 
          case CMACRO:          /* command macro */
                for (p = cmd->sccspath; *p != '\0'; p++)
                {
                break;
 
          case CMACRO:          /* command macro */
                for (p = cmd->sccspath; *p != '\0'; p++)
                {
-                       avp = nav;
-                       *avp++ = buf;
-                       for (q = buf; *p != '/' && *p != '\0'; p++, q++)
-                       {
-                               if (*p == ' ')
-                               {
-                                       *q = '\0';
-                                       *avp++ = &q[1];
-                               }
-                               else
-                                       *q = *p;
-                       }
-                       *q = '\0';
-                       *avp = NULL;
-                       xcommand(&argv[1], *p != '\0', nav[0], nav[1], nav[2],
-                                nav[3], nav[4], nav[5], nav[6]);
+                       q = p;
+                       while (*p != '\0' && *p != '/')
+                               p++;
+                       rval = command(&nav[1], *p != '\0', TRUE, q);
+                       if (rval != 0)
+                               break;
                }
                }
-               syserr("internal error: CMACRO");
-               exit(EX_SOFTWARE);
+               break;
 
          case FIX:             /* fix a delta */
 
          case FIX:             /* fix a delta */
-               if (strncmp(argv[1], "-r", 2) != 0)
+               if (strncmp(nav[1], "-r", 2) != 0)
                {
                        usrerr("-r flag needed for fix command");
                {
                        usrerr("-r flag needed for fix command");
+                       rval = EX_USAGE;
                        break;
                }
                        break;
                }
-               xcommand(&argv[1], TRUE, "get", "-k", NULL);
-               xcommand(&argv[1], TRUE, "rmdel", NULL);
-               xcommand(&argv[2], FALSE, "get", "-e", "-g", NULL);
-               syserr("FIX");
-               exit(EX_SOFTWARE);
+               rval = command(&nav[1], TRUE, TRUE, "get -k");
+               if (rval == 0)
+                       rval = command(&nav[1], TRUE, TRUE, "rmdel");
+               if (rval == 0)
+                       rval = command(&nav[2], FALSE, TRUE, "get -e -g");
+               break;
 
          case CLEAN:
 
          case CLEAN:
-               clean((int) cmd->sccspath);
+               rval = clean((int) cmd->sccspath);
                break;
 
          case UNEDIT:
                break;
 
          case UNEDIT:
-               i = 0;
-               for (avp = &argv[1]; *avp != NULL; avp++)
+               for (argv = np = &nav[1]; *argv != NULL; argv++)
                {
                {
-                       if (unedit(*avp))
-                               nav[i++] = *avp;
+                       if (unedit(*argv))
+                               *np++ = *argv;
                }
                }
-               nav[i] = NULL;
+               *np = NULL;
                if (i > 0)
                if (i > 0)
-                       xcommand(nav, FALSE, "get", NULL);
+                       rval = command(&nav[1], FALSE, FALSE, "get");
                break;
 
          default:
                syserr("oper %d", cmd->sccsoper);
                exit(EX_SOFTWARE);
        }
                break;
 
          default:
                syserr("oper %d", cmd->sccsoper);
                exit(EX_SOFTWARE);
        }
+# ifdef DEBUG
+       if (Debug)
+               printf("command: rval=%d\n", rval);
+# endif
+       return (rval);
 }
 \f/*
 **  LOOKUP -- look up an SCCS command name.
 }
 \f/*
 **  LOOKUP -- look up an SCCS command name.
@@ -363,25 +437,25 @@ lookup(name)
        }
        return (NULL);
 }
        }
        return (NULL);
 }
-
-
-xcommand(argv, forkflag, arg0)
-       char **argv;
-       bool forkflag;
-       char *arg0;
-{
-       register char **av;
-       char *newargv[1000];
-       register char **np;
-
-       np = newargv;
-       for (av = &arg0; *av != NULL; av++)
-               *np++ = *av;
-       for (av = argv; *av != NULL; av++)
-               *np++ = *av;
-       *np = NULL;
-       command(newargv, forkflag);
-}
+\f/*
+**  CALLPROG -- call a program
+**
+**     Used to call the SCCS programs.
+**
+**     Parameters:
+**             progpath -- pathname of the program to call.
+**             flags -- status flags from the command descriptors.
+**             argv -- an argument vector to pass to the program.
+**             forkflag -- if true, fork before calling, else just
+**                     exec.
+**
+**     Returns:
+**             The exit status of the program.
+**             Nothing if forkflag == FALSE.
+**
+**     Side Effects:
+**             Can exit if forkflag == FALSE.
+*/
 
 callprog(progpath, flags, argv, forkflag)
        char *progpath;
 
 callprog(progpath, flags, argv, forkflag)
        char *progpath;
@@ -389,12 +463,17 @@ callprog(progpath, flags, argv, forkflag)
        char **argv;
        bool forkflag;
 {
        char **argv;
        bool forkflag;
 {
-       register char *p;
-       register char **av;
-       extern char *makefile();
        register int i;
        auto int st;
        register int i;
        auto int st;
-       register char **nav;
+
+# ifdef DEBUG
+       if (Debug)
+       {
+               printf("callprog:\n");
+               for (i = 0; argv[i] != NULL; i++)
+                       printf("\t\"%s\"\n", argv[i]);
+       }
+# endif
 
        if (*argv == NULL)
                return (-1);
 
        if (*argv == NULL)
                return (-1);
@@ -418,28 +497,12 @@ callprog(progpath, flags, argv, forkflag)
                else if (i > 0)
                {
                        wait(&st);
                else if (i > 0)
                {
                        wait(&st);
+                       if ((st & 0377) == 0)
+                               st = (st >> 8) & 0377;
                        return (st);
                }
        }
 
                        return (st);
                }
        }
 
-       /*
-       **  Build new argument vector.
-       */
-
-       /* copy program filename arguments and flags */
-       nav = &argv[1];
-       av = argv;
-       while ((p = *++av) != NULL)
-       {
-               if (!bitset(NO_SDOT, flags) && *p != '-')
-                       *nav = makefile(p);
-               else
-                       *nav = p;
-               if (*nav != NULL)
-                       nav++;
-       }
-       *nav = NULL;
-
        /*
        **  Set protection as appropriate.
        */
        /*
        **  Set protection as appropriate.
        */
@@ -635,7 +698,7 @@ clean(mode)
        if (dirfd == NULL)
        {
                usrerr("cannot open %s", buf);
        if (dirfd == NULL)
        {
                usrerr("cannot open %s", buf);
-               return;
+               return (EX_NOINPUT);
        }
 
        /*
        }
 
        /*
@@ -681,6 +744,7 @@ clean(mode)
                printf("Nothing being edited\n");
        if (mode == CHECKC)
                exit(gotedit);
                printf("Nothing being edited\n");
        if (mode == CHECKC)
                exit(gotedit);
+       return (EX_OK);
 }
 \f/*
 **  UNEDIT -- unedit a file
 }
 \f/*
 **  UNEDIT -- unedit a file
@@ -718,6 +782,7 @@ unedit(fn)
        struct pfile *pent;
        extern struct pfile *getpfile();
        char buf[120];
        struct pfile *pent;
        extern struct pfile *getpfile();
        char buf[120];
+       extern char *makefile();
 # ifdef UIDUSER
        struct passwd *pw;
        extern struct passwd *getpwuid();
 # ifdef UIDUSER
        struct passwd *pw;
        extern struct passwd *getpwuid();