sccs.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,630 行 · 第 1/3 页
C
1,630 行
#ifndef lintstatic char *sccsid = "@(#)sccs.c 4.1 ULTRIX 7/17/90";#endif lint/************************************************************************ * * * Copyright (c) 1984 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************/ /* sccs.c from 3BSD or 4.0BSD via circuitous routes. */ /******************************************************************* * * Modification History: * * 8Jul83 -- jmcg * New directory paths: /usr/sccs * * 1Nov83 -- rjl * New directory paths: /usr/local * * 27Nov84 -- depp * 1. Moved path macros to new header file: ../hdr/paths.h * 2. Fixed "g" file deletion bug in "unedit" routine. * The "g" file was not being deleted due to ownership conflict. * To fix, the UID is set to the "real" UID temporarily while * the file deletion takes place, then reset to the "effective" * UID. * 3. Fixed same type of bug in "command" routine, CLEAN case. * UID was not being set to "real". * 4. Provided limited chghist, it will now permit a comment to * be inserted into a delta using "cdc" command. * * 06Dec84 -- depp * Modified the setting of the "real" UID in unedit, so that it doesn't * have to be temporary (see #2 of modification 27Nov84), as the system * will not permit the UID to be reset to the effective UID. * * 14Dec84 -- depp * clean up of old code that was eliminate do to modification (06Dec84). * * 24 Oct 85 -- depp * Insured that the command "prt" call the utility "prs" (not "prt" * which doesn't exist). * * 17 Jul 86 -- metsky * Made it impossible to do a fix to a version 1.1 file. This was * creating files that couldn't be delta'ed. Created a new error * message, (sc24) "cannot use fix command on version 1.1". * * 04 Dec 86 -- metsky * Fixed previous 'fix'. Now the fix cmmand works correctly. * ******************************************************************/# include <stdio.h># include <sys/param.h># include <sys/stat.h># include <sys/dir.h># include <sys/file.h># include <errno.h># include <signal.h># include <sysexits.h># include <pwd.h># include "paths.h"/*** 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.** check 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.** 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 flag also disables the -p flag.** SCCSPATH -- the default for the -p flag.** MYNAME -- the title this program should print when it** gives error messages.**** Compilation Instructions:** cc -O -n -s sccs.c** The flags listed above can be -D defined to simplify** recompilation for variant versions.**** Author:** Eric Allman, UCB/INGRES** Copyright 1980 Regents of the University of California*/static char SccsId[] = "@(#)sccs.c 1.69 1/13/83";typedef char bool;# define TRUE 1# define FALSE 0# define bitset(bit, word) ((bool) ((bit) & (word)))struct sccsprog{ char *sccsname; /* name of SCCS routine */ short sccsoper; /* opcode, see below */ short sccsflags; /* flags, see below */ char *sccspath; /* pathname of binary implementing */};/* values for sccsoper */# define PROG 0 /* call a program */# define CMACRO 1 /* command substitution macro */# define FIX 2 /* fix a delta */# define CLEAN 3 /* clean out recreatable files */# define UNEDIT 4 /* unedit a file */# define SHELL 5 /* call a shell file (like PROG) */# define DIFFS 6 /* diff between sccs & file out */# define DODIFF 7 /* internal call to diff program */# define ENTER 8 /* enter new files *//* bits for sccsflags */# 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 */# define TELLC 3 /* give list of files being edited *//*** Description of commands known to this program.** First argument puts the command into a class. Second arg is** info regarding treatment of this command. Third arg is a** list of flags this command accepts from macros, etc. Fourth** arg is the pathname of the implementing program, or the** macro definition, or the arg to a sub-algorithm.*/struct sccsprog SccsProg[] ={ "admin", PROG, 0, PROGPATH(admin), "chghist", CMACRO, 0, "cdc:r", "comb", PROG, 0, PROGPATH(comb), "delta", PROG, 0, PROGPATH(delta), "get", PROG, 0, PROGPATH(get), "help", PROG, NO_SDOT, PROGPATH(sccshelp), "prs", PROG, 0, PROGPATH(prs), "prt", PROG, 0, PROGPATH(prs), "cdc", PROG, 0, PROGPATH(cdc), "rmdel", PROG, 0, PROGPATH(rmdel), "val", PROG, 0, PROGPATH(val), "what", PROG, NO_SDOT, PROGPATH(what), "sccsdiff", SHELL, REALUSER, PROGPATH(sccsdiff), "edit", CMACRO, NO_SDOT, "get -e", "delget", CMACRO, NO_SDOT, "delta:mysrp/get:ixbeskcl -t", "deledit", CMACRO, NO_SDOT, "delta:mysrp -n/get:ixbskcl -e -t -g", "fix", FIX, NO_SDOT, NULL, "clean", CLEAN, REALUSER|NO_SDOT, (char *) CLEANC, "info", CLEAN, REALUSER|NO_SDOT, (char *) INFOC, "check", CLEAN, REALUSER|NO_SDOT, (char *) CHECKC, "tell", CLEAN, REALUSER|NO_SDOT, (char *) TELLC, "unedit", UNEDIT, NO_SDOT, NULL, "diffs", DIFFS, NO_SDOT|REALUSER, NULL, "-diff", DODIFF, NO_SDOT|REALUSER, PROGPATH(bdiff), "print", CMACRO, 0, "prs -e/get -p -m -s", "branch", CMACRO, NO_SDOT, "get:ixrc -e -b/delta: -s -n -ybranch-place-holder/get:pl -e -t -g", "enter", ENTER, NO_SDOT, NULL, "create", CMACRO, NO_SDOT, "enter/get:ixbeskcl -t", NULL, -1, 0, NULL};/* one line from a p-file */struct pfile{ char *p_osid; /* old SID */ char *p_nsid; /* new SID */ char *p_user; /* user who did edit */ char *p_date; /* date of get */ char *p_time; /* time of get */ char *p_aux; /* extra info at end */};char *SccsPath = SCCSPATH; /* pathname of SCCS files */# ifdef SCCSDIRchar *SccsDir = SCCSDIR; /* directory to begin search from */# elsechar *SccsDir = "";# endifchar MyName[] = MYNAME; /* name used in messages */int OutFile = -1; /* override output file for commands */bool RealUser; /* if set, running as real user */# ifdef DEBUGbool Debug; /* turn on tracing */# endif# ifndef V6extern char *getenv();# endif V6char *gstrcat(), *strcat();char *gstrncat(), *strncat();char *gstrcpy(), *strcpy();#define FBUFSIZ BUFSIZ#define PFILELG 120main(argc, argv) int argc; char **argv;{ register char *p; extern struct sccsprog *lookup(); register int i;# ifndef V6# ifndef SCCSDIR register struct passwd *pw; extern struct passwd *getpwnam(); char buf[FBUFSIZ]; /* pull "SccsDir" out of the environment (possibly) */ p = getenv("PROJECTDIR"); if (p != NULL && p[0] != '\0') { if (p[0] == '/') SccsDir = p; else { pw = getpwnam(p); if (pw == NULL) { usrerr("user %s does not exist (sc1)", p); exit(EX_USAGE); } gstrcpy(buf, pw->pw_dir, sizeof(buf)); gstrcat(buf, "/src", sizeof(buf)); if (access(buf, 0) < 0) { gstrcpy(buf, pw->pw_dir, sizeof(buf)); gstrcat(buf, "/source", sizeof(buf)); if (access(buf, 0) < 0) { usrerr("project %s has no source! (sc2)" , p); exit(EX_USAGE); } } SccsDir = buf; } }# endif SCCSDIR# endif V6 /* ** Detect and decode flags intended for this program. */ if (argc < 2) { fprintf(stderr, "Usage: %s [flags] command [flags]\n", MyName); exit(EX_USAGE); } argv[argc] = NULL; if (lookup(argv[0]) == NULL) { while ((p = *++argv) != NULL) { if (*p != '-') break; switch (*++p) { case 'r': /* run as real user */ setuid(getuid()); RealUser++; break;# ifndef SCCSDIR case 'p': /* path of sccs files */ SccsPath = ++p; if (SccsPath[0] == '\0' && argv[1] != NULL) SccsPath = *++argv; break; case 'd': /* directory to search from */ SccsDir = ++p; if (SccsDir[0] == '\0' && argv[1] != NULL) SccsDir = *++argv; break;# endif# ifdef DEBUG case 'T': /* trace */ Debug++; break;# endif default: usrerr("unknown option -%s (sc3)", p); break; } } if (SccsPath[0] == '\0') SccsPath = "."; } i = command(argv, FALSE, ""); exit(i);}/*** 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, arg0) char **argv; bool forkflag; char *arg0;{ register struct sccsprog *cmd; register char *p; char buf[FBUFSIZ]; extern struct sccsprog *lookup(); char *nav[1000]; char **np; register char **ap; register int i; register char *q; extern bool unedit(); int rval = 0; extern char *index(); extern char *makefile(); char *editchs; extern char *tail();# ifdef DEBUG if (Debug) { printf("command:\n\t\"%s\"\n", arg0); for (np = argv; *np != NULL; np++) printf("\t\"%s\"\n", *np); }# endif /* ** Copy arguments. ** Copy from arg0 & if necessary at most one arg ** from argv[0]. */ np = ap = &nav[1]; editchs = NULL; for (p = arg0, q = buf; *p != '\0' && *p != '/'; ) { *np++ = q; while (*p == ' ') p++; while (*p != ' ' && *p != '\0' && *p != '/' && *p != ':') *q++ = *p++; *q++ = '\0'; if (*p == ':') { editchs = q; while (*++p != '\0' && *p != '/' && *p != ' ') *q++ = *p; *q++ = '\0'; } } *np = NULL; if (*ap == NULL) *np++ = *argv++; /* ** Look up command. ** At this point, *ap is the command name. */ cmd = lookup(*ap); if (cmd == NULL) { usrerr("Unknown command \"%s\" (sc4)", *ap); return (EX_USAGE); } /* ** Copy remaining arguments doing editing as appropriate. */ for (; *argv != NULL; argv++) { p = *argv; if (*p == '-') { if (p[1] == '\0' || editchs == NULL || index(editchs, 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. */ switch (cmd->sccsoper) { case SHELL: /* call a shell file */ *ap = cmd->sccspath; *--ap = "sh"; rval = callprog("/bin/sh", cmd->sccsflags, ap, forkflag); break; case PROG: /* call an sccs prog */ rval = callprog(cmd->sccspath, cmd->sccsflags, ap, forkflag); break; case CMACRO: /* command macro */ /* step through & execute each part of the macro */ for (p = cmd->sccspath; *p != '\0'; p++) { q = p; while (*p != '\0' && *p != '/') p++; rval = command(&ap[1], *p != '\0', q); if (rval != 0) break; } break; case FIX: /* fix a delta */ if (strncmp(ap[1], "-r", 2) != 0) { usrerr("-r flag needed for fix command (sc5)"); rval = EX_USAGE; break; } if (strcmp(ap[1], "-r1.1") == 0) /* metsky 7/17/86 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?