INSTALLDIR changes from /usr/new to /usr/ucb
[unix-history] / usr / src / usr.bin / sccs / sccs.c
index 1ff099a..cade273 100644 (file)
@@ -5,7 +5,86 @@
 # include <sysexits.h>
 # include <whoami.h>
 
 # include <sysexits.h>
 # include <whoami.h>
 
-static char SccsId[] = "@(#)sccs.c     1.24 %G%";
+/*
+**  SCCS.C -- human-oriented front end to the SCCS system.
+**
+**     Without trying to add any functionality to speak of, this
+**     program tries to make SCCS a little more accessible to human
+**     types.  The main thing it does is automatically put the
+**     string "SCCS/s." on the front of names.  Also, it has a
+**     couple of things that are designed to shorten frequent
+**     combinations, e.g., "delget" which expands to a "delta"
+**     and a "get".
+**
+**     This program can also function as a setuid front end.
+**     To do this, you should copy the source, renaming it to
+**     whatever you want, e.g., "syssccs".  Change any defaults
+**     in the program (e.g., syssccs might default -d to
+**     "/usr/src/sys").  Then recompile and put the result
+**     as setuid to whomever you want.  In this mode, sccs
+**     knows to not run setuid for certain programs in order
+**     to preserve security, and so forth.
+**
+**     Usage:
+**             sccs [flags] command [args]
+**
+**     Flags:
+**             -d<dir>         <dir> represents a directory to search
+**                             out of.  It should be a full pathname
+**                             for general usage.  E.g., if <dir> is
+**                             "/usr/src/sys", then a reference to the
+**                             file "dev/bio.c" becomes a reference to
+**                             "/usr/src/sys/dev/bio.c".
+**             -p<path>        prepends <path> to the final component
+**                             of the pathname.  By default, this is
+**                             "SCCS".  For example, in the -d example
+**                             above, the path then gets modified to
+**                             "/usr/src/sys/dev/SCCS/s.bio.c".  In
+**                             more common usage (without the -d flag),
+**                             "prog.c" would get modified to
+**                             "SCCS/s.prog.c".  In both cases, the
+**                             "s." gets automatically prepended.
+**             -r              run as the real user.
+**
+**     Commands:
+**             admin,
+**             get,
+**             delta,
+**             rmdel,
+**             chghist,
+**             etc.            Straight out of SCCS; only difference
+**                             is that pathnames get modified as
+**                             described above.
+**             edit            Macro for "get -e".
+**             unedit          Removes a file being edited, knowing
+**                             about p-files, etc.
+**             delget          Macro for "delta" followed by "get".
+**             deledit         Macro for "delta" followed by "get -e".
+**             info            Tell what files being edited.
+**             clean           Remove all files that can be
+**                             regenerated from SCCS files.
+**             status          Like info, but return exit status, for
+**                             use in makefiles.
+**             fix             Remove a top delta & reedit, but save
+**                             the previous changes in that delta.
+**
+**     Compilation Flags:
+**             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.
+**
+**     Compilation Instructions:
+**             cc -O -n -s sccs.c
+**
+**     Author:
+**             Eric Allman, UCB/INGRES
+*/
+
+# ifdef CSVAX
+# define UIDUSER
+# endif
+
+static char SccsId[] = "@(#)sccs.c     1.26 %G%";
 
 # define bitset(bit, word)     ((bit) & (word))
 
 
 # define bitset(bit, word)     ((bit) & (word))
 
@@ -13,6 +92,10 @@ typedef char bool;
 # define TRUE  1
 # define FALSE 0
 
 # define TRUE  1
 # define FALSE 0
 
+# ifdef UIDUSER
+# include <pwd.h>
+# endif UIDUSER
+
 struct sccsprog
 {
        char    *sccsname;      /* name of SCCS routine */
 struct sccsprog
 {
        char    *sccsname;      /* name of SCCS routine */
@@ -32,6 +115,11 @@ struct sccsprog
 # define NO_SDOT       0001    /* no s. on front of args */
 # define REALUSER      0002    /* protected (e.g., admin) */
 
 # define NO_SDOT       0001    /* no s. on front of args */
 # define REALUSER      0002    /* protected (e.g., admin) */
 
+/* modes for the "clean", "info", "check" ops */
+# define CLEANC                0       /* clean command */
+# define INFOC         1       /* info command */
+# define CHECKC                2       /* check command */
+
 # ifdef CSVAX
 # define PROGPATH(name)        "/usr/local/name"
 # endif CSVAX
 # ifdef CSVAX
 # define PROGPATH(name)        "/usr/local/name"
 # endif CSVAX
@@ -54,11 +142,10 @@ struct sccsprog SccsProg[] =
        "edit",         CMACRO, 0,                      "get -e",
        "delget",       CMACRO, 0,                      "delta/get",
        "deledit",      CMACRO, 0,                      "delta/get -e",
        "edit",         CMACRO, 0,                      "get -e",
        "delget",       CMACRO, 0,                      "delta/get",
        "deledit",      CMACRO, 0,                      "delta/get -e",
-       "del",          CMACRO, 0,                      "delta/get",
-       "delt",         CMACRO, 0,                      "delta/get",
        "fix",          FIX,    0,                      NULL,
        "fix",          FIX,    0,                      NULL,
-       "clean",        CLEAN,  REALUSER,               (char *) TRUE,
-       "info",         CLEAN,  REALUSER,               (char *) FALSE,
+       "clean",        CLEAN,  REALUSER,               (char *) CLEANC,
+       "info",         CLEAN,  REALUSER,               (char *) INFOC,
+       "check",        CLEAN,  REALUSER,               (char *) CHECKC,
        "unedit",       UNEDIT, 0,                      NULL,
        NULL,           -1,     0,                      NULL
 };
        "unedit",       UNEDIT, 0,                      NULL,
        NULL,           -1,     0,                      NULL
 };
@@ -218,7 +305,7 @@ command(argv, forkflag)
                exit(EX_SOFTWARE);
 
          case CLEAN:
                exit(EX_SOFTWARE);
 
          case CLEAN:
-               clean((bool) cmd->sccspath);
+               clean((int) cmd->sccspath);
                break;
 
          case UNEDIT:
                break;
 
          case UNEDIT:
@@ -506,18 +593,20 @@ safepath(p)
 **     exists in the current directory is purged.
 **
 **     Parameters:
 **     exists in the current directory is purged.
 **
 **     Parameters:
-**             really -- if TRUE, remove everything.
-**                     else, just report status.
+**             tells whether this came from a "clean", "info", or
+**             "check" command.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
-**             removes files in the current directory.
+**             Removes files in the current directory.
+**             Prints information regarding files being edited.
+**             Exits if a "check" command.
 */
 
 */
 
-clean(really)
-       bool really;
+clean(mode)
+       int mode;
 {
        struct direct dir;
        struct stat stbuf;
 {
        struct direct dir;
        struct stat stbuf;
@@ -562,7 +651,7 @@ clean(really)
                }
                
                /* the s. file exists and no p. file exists -- unlink the g-file */
                }
                
                /* the s. file exists and no p. file exists -- unlink the g-file */
-               if (really)
+               if (mode == CLEANC)
                {
                        strncpy(buf, &dir.d_name[2], sizeof dir.d_name - 2);
                        buf[sizeof dir.d_name - 2] = '\0';
                {
                        strncpy(buf, &dir.d_name[2], sizeof dir.d_name - 2);
                        buf[sizeof dir.d_name - 2] = '\0';
@@ -571,8 +660,10 @@ clean(really)
        }
 
        fclose(dirfd);
        }
 
        fclose(dirfd);
-       if (!gotedit && !really)
+       if (!gotedit && mode == INFOC)
                printf("Nothing being edited\n");
                printf("Nothing being edited\n");
+       if (mode == CHECKC)
+               exit(gotedit);
 }
 \f/*
 **  UNEDIT -- unedit a file
 }
 \f/*
 **  UNEDIT -- unedit a file
@@ -610,6 +701,10 @@ unedit(fn)
        struct pfile *pent;
        extern struct pfile *getpfile();
        char buf[120];
        struct pfile *pent;
        extern struct pfile *getpfile();
        char buf[120];
+# ifdef UIDUSER
+       struct passwd *pw;
+       extern struct passwd *getpwuid();
+# endif UIDUSER
 
        /* make "s." filename & find the trailing component */
        pfn = makefile(fn);
 
        /* make "s." filename & find the trailing component */
        pfn = makefile(fn);
@@ -646,7 +741,17 @@ unedit(fn)
                exit(EX_OSERR);
        }
 
                exit(EX_OSERR);
        }
 
+# ifdef UIDUSER
+       pw = getpwuid(getuid());
+       if (pw == NULL)
+       {
+               fprintf(stderr, "Sccs: who are you?\n");
+               exit(EX_OSERR);
+       }
+       myname = pw->pw_name;
+# else
        myname = getlogin();
        myname = getlogin();
+# endif UIDUSER
        while ((pent = getpfile(pfp)) != NULL)
        {
                if (strcmp(pent->p_user, myname) == 0)
        while ((pent = getpfile(pfp)) != NULL)
        {
                if (strcmp(pent->p_user, myname) == 0)