1148Seric # include <stdio.h> 2148Seric # include <sys/types.h> 3148Seric # include <sys/stat.h> 4148Seric # include <sysexits.h> 5148Seric 6*157Seric static char SccsId[] = "@(#)sccs.c 1.4 delta 05/13/80 11:18:42 get 10/14/12 16:33:33"; 7155Seric 8*157Seric # define bitset(bit, word) ((bit) & (word)) 9*157Seric 10*157Seric typedef char bool; 11*157Seric 12148Seric struct sccsprog 13148Seric { 14148Seric char *sccsname; /* name of SCCS routine */ 15148Seric short sccsflags; /* see below */ 16148Seric char *sccspath; /* pathname of binary implementing */ 17148Seric }; 18148Seric 19*157Seric /* bits for sccsflags */ 20148Seric # define F_NOSDOT 0001 /* no s. on front of args */ 21*157Seric # define F_PROT 0002 /* protected (e.g., admin) */ 22148Seric 23148Seric struct sccsprog SccsProg[] = 24148Seric { 25*157Seric "admin", F_PROT, "/usr/sccs/admin", 26153Seric "chghist", 0, "/usr/sccs/rmdel", 27148Seric "comb", 0, "/usr/sccs/comb", 28148Seric "delta", 0, "/usr/sccs/delta", 29148Seric "get", 0, "/usr/sccs/get", 30153Seric "help", F_NOSDOT, "/usr/sccs/help", 31148Seric "prt", 0, "/usr/sccs/prt", 32*157Seric "rmdel", F_PROT, "/usr/sccs/rmdel", 33148Seric "what", F_NOSDOT, "/usr/sccs/what", 34148Seric NULL, 0, NULL 35148Seric }; 36148Seric 37*157Seric char *SccsPath = "SCCS"; /* pathname of SCCS files */ 38*157Seric bool IsAdmin; /* if set, this person is an administrator */ 39*157Seric bool RealUser; /* if set, running as real user */ 40148Seric 41148Seric main(argc, argv) 42148Seric int argc; 43148Seric char **argv; 44148Seric { 45148Seric register char *p; 46148Seric register char **av; 47148Seric char *newargv[1000]; 48148Seric extern char *makefile(); 49148Seric register struct sccsprog *cmd; 50*157Seric char buf[200]; 51*157Seric int uid; 52*157Seric auto int xuid; 53*157Seric register FILE *fp; 54148Seric 55148Seric /* 56148Seric ** Detect and decode flags intended for this program. 57148Seric */ 58148Seric 59148Seric while (--argc > 0) 60148Seric { 61148Seric p = *++argv; 62148Seric if (*p != '-') 63148Seric break; 64148Seric switch (*++p) 65148Seric { 66148Seric case 'r': /* run as real user */ 67148Seric setuid(getuid()); 68*157Seric RealUser++; 69148Seric break; 70148Seric 71148Seric case 'p': /* path of sccs files */ 72148Seric SccsPath = ++p; 73148Seric break; 74148Seric 75148Seric default: 76148Seric fprintf(stderr, "Sccs: unknown option -%s\n", p); 77148Seric break; 78148Seric } 79148Seric } 80148Seric 81148Seric /* 82*157Seric ** See if this user is an administrator. 83*157Seric */ 84*157Seric 85*157Seric uid = getuid(); 86*157Seric # ifdef V6 87*157Seric uid &= 0377; 88*157Seric # endif V6 89*157Seric strcpy(buf, SccsPath); 90*157Seric strcat(buf, "/ADMINFILE"); 91*157Seric fp = fopen(buf, "r"); 92*157Seric if (fp != NULL) 93*157Seric { 94*157Seric while (fgets(buf, sizeof buf, fp) != NULL) 95*157Seric { 96*157Seric if (buf[0] == 'A') 97*157Seric { 98*157Seric if (sscanf(&buf[1], "%d", &xuid) > 0 && 99*157Seric xuid == uid) 100*157Seric IsAdmin++; 101*157Seric } 102*157Seric } 103*157Seric fclose(fp); 104*157Seric } 105*157Seric 106*157Seric /* 107148Seric ** Look up command. 108148Seric ** At this point, p and argv point to the command name. 109148Seric */ 110148Seric 111148Seric for (cmd = SccsProg; cmd->sccsname != NULL; cmd++) 112148Seric { 113148Seric if (strcmp(cmd->sccsname, p) == 0) 114148Seric break; 115148Seric } 116148Seric if (cmd->sccsname == NULL) 117148Seric { 118148Seric fprintf(stderr, "Sccs: Unknown command \"%s\"\n", p); 119148Seric exit(EX_USAGE); 120148Seric } 121148Seric 122148Seric /* 123*157Seric ** Set protection as appropriate. 124*157Seric */ 125*157Seric 126*157Seric if (bitset(F_PROT, cmd->sccsflags) && !IsAdmin && !RealUser) 127*157Seric { 128*157Seric fprintf(stderr, "Sccs: not authorized to use %s\n", p); 129*157Seric exit(EX_USAGE); 130*157Seric } 131*157Seric 132*157Seric /* 133148Seric ** Build new argument vector. 134148Seric */ 135148Seric 136148Seric av = newargv; 137148Seric *av++ = p; 138148Seric 139153Seric /* copy program filename arguments and flags */ 140153Seric while (--argc > 0) 141148Seric { 142153Seric p = *++argv; 143*157Seric if (!bitset(F_NOSDOT, cmd->sccsflags) && *p != '-') 144153Seric *av++ = makefile(p); 145148Seric else 146153Seric *av++ = p; 147148Seric } 148148Seric 149148Seric /* terminate argument vector */ 150148Seric *av = NULL; 151148Seric 152148Seric /* 153148Seric ** Call real SCCS program. 154148Seric */ 155148Seric 156148Seric execv(cmd->sccspath, newargv); 157148Seric fprintf(stderr, "Sccs: cannot execute "); 158148Seric perror(cmd->sccspath); 159148Seric exit(EX_UNAVAILABLE); 160148Seric } 161148Seric 162148Seric 163148Seric char * 164148Seric makefile(name) 165148Seric char *name; 166148Seric { 167148Seric register char *p; 168148Seric register char c; 169148Seric char buf[512]; 170148Seric struct stat stbuf; 171148Seric extern char *malloc(); 172148Seric 173148Seric /* 174148Seric ** See if this filename should be used as-is. 175148Seric ** There are three conditions where this can occur. 176148Seric ** 1. The name already begins with "s.". 177148Seric ** 2. The name has a "/" in it somewhere. 178148Seric ** 3. The name references a directory. 179148Seric */ 180148Seric 181148Seric if (strncmp(name, "s.", 2) == 0) 182148Seric return (name); 183148Seric for (p = name; (c = *p) != '\0'; p++) 184148Seric { 185148Seric if (c == '/') 186148Seric return (name); 187148Seric } 188148Seric if (stat(name, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR) 189148Seric return (name); 190148Seric 191148Seric /* 192148Seric ** Prepend the path of the sccs file. 193148Seric */ 194148Seric 195148Seric strcpy(buf, SccsPath); 196*157Seric strcat(buf, "/s."); 197148Seric strcat(buf, name); 198148Seric p = malloc(strlen(buf) + 1); 199148Seric if (p == NULL) 200148Seric { 201148Seric perror("Sccs: no mem"); 202148Seric exit(EX_OSERR); 203148Seric } 204148Seric strcpy(p, buf); 205148Seric return (p); 206148Seric } 207148Seric 208