xref: /csrg-svn/usr.bin/sccs/sccs.c (revision 202)
1148Seric # include <stdio.h>
2148Seric # include <sys/types.h>
3148Seric # include <sys/stat.h>
4148Seric # include <sysexits.h>
5*202Seric # include <whoami.h>
6148Seric 
7*202Seric static char SccsId[] = "@(#)sccs.c 1.9 delta 05/23/80 12:31:38 get 10/14/12 16:33:34";
8155Seric 
9157Seric # define bitset(bit, word)	((bit) & (word))
10157Seric 
11157Seric typedef char	bool;
12200Seric # define TRUE	1
13200Seric # define FALSE	0
14157Seric 
15148Seric struct sccsprog
16148Seric {
17148Seric 	char	*sccsname;	/* name of SCCS routine */
18200Seric 	short	sccsoper;	/* opcode, see below */
19200Seric 	short	sccsflags;	/* flags, see below */
20148Seric 	char	*sccspath;	/* pathname of binary implementing */
21148Seric };
22148Seric 
23200Seric /* values for sccsoper */
24200Seric # define PROG		0	/* call a program */
25201Seric # define CMACRO		1	/* command substitution macro */
26200Seric 
27157Seric /* bits for sccsflags */
28200Seric # define NO_SDOT	0001	/* no s. on front of args */
29200Seric # define REALUSER	0002	/* protected (e.g., admin) */
30148Seric 
31*202Seric # ifdef CSVAX
32*202Seric # define PROGPATH(name)	"/usr/local/name"
33*202Seric # endif CSVAX
34*202Seric 
35*202Seric # ifndef PROGPATH
36*202Seric # define PROGPATH(name)	"/usr/sccs/name"
37*202Seric # endif PROGPATH
38*202Seric 
39148Seric struct sccsprog SccsProg[] =
40148Seric {
41*202Seric 	"admin",	PROG,	REALUSER,		PROGPATH(admin),
42*202Seric 	"chghist",	PROG,	0,			PROGPATH(rmdel),
43*202Seric 	"comb",		PROG,	0,			PROGPATH(comb),
44*202Seric 	"delta",	PROG,	0,			PROGPATH(delta),
45*202Seric 	"get",		PROG,	0,			PROGPATH(get),
46*202Seric 	"help",		PROG,	NO_SDOT,		PROGPATH(help),
47*202Seric 	"prt",		PROG,	0,			PROGPATH(prt),
48*202Seric 	"rmdel",	PROG,	REALUSER,		PROGPATH(rmdel),
49*202Seric 	"what",		PROG,	NO_SDOT,		PROGPATH(what),
50201Seric 	"del",		CMACRO,	0,			"delta/get",
51200Seric 	NULL,		-1,	0,			NULL
52148Seric };
53148Seric 
54157Seric char	*SccsPath = "SCCS";	/* pathname of SCCS files */
55157Seric bool	RealUser;		/* if set, running as real user */
56148Seric 
57148Seric main(argc, argv)
58148Seric 	int argc;
59148Seric 	char **argv;
60148Seric {
61148Seric 	register char *p;
62148Seric 
63148Seric 	/*
64148Seric 	**  Detect and decode flags intended for this program.
65148Seric 	*/
66148Seric 
67200Seric 	if (argc < 2)
68148Seric 	{
69200Seric 		fprintf(stderr, "Usage: sccs [flags] command [flags]\n");
70200Seric 		exit(EX_USAGE);
71200Seric 	}
72200Seric 	argv[argc] = NULL;
73200Seric 
74200Seric 	while ((p = *++argv) != NULL)
75200Seric 	{
76148Seric 		if (*p != '-')
77148Seric 			break;
78148Seric 		switch (*++p)
79148Seric 		{
80148Seric 		  case 'r':		/* run as real user */
81148Seric 			setuid(getuid());
82157Seric 			RealUser++;
83148Seric 			break;
84148Seric 
85148Seric 		  case 'p':		/* path of sccs files */
86148Seric 			SccsPath = ++p;
87148Seric 			break;
88148Seric 
89148Seric 		  default:
90148Seric 			fprintf(stderr, "Sccs: unknown option -%s\n", p);
91148Seric 			break;
92148Seric 		}
93148Seric 	}
94158Seric 	if (SccsPath[0] == '\0')
95158Seric 		SccsPath = ".";
96148Seric 
97201Seric 	command(argv, FALSE);
98200Seric 	exit(EX_OK);
99200Seric }
100157Seric 
101201Seric command(argv, forkflag)
102200Seric 	char **argv;
103201Seric 	bool forkflag;
104200Seric {
105200Seric 	register struct sccsprog *cmd;
106200Seric 	register char *p;
107201Seric 	register char *q;
108201Seric 	char buf[40];
109200Seric 
110157Seric 	/*
111148Seric 	**  Look up command.
112200Seric 	**	At this point, argv points to the command name.
113148Seric 	*/
114148Seric 
115200Seric 	p = *argv;
116148Seric 	for (cmd = SccsProg; cmd->sccsname != NULL; cmd++)
117148Seric 	{
118148Seric 		if (strcmp(cmd->sccsname, p) == 0)
119148Seric 			break;
120148Seric 	}
121148Seric 	if (cmd->sccsname == NULL)
122148Seric 	{
123148Seric 		fprintf(stderr, "Sccs: Unknown command \"%s\"\n", p);
124148Seric 		exit(EX_USAGE);
125148Seric 	}
126148Seric 
127148Seric 	/*
128200Seric 	**  Interpret operation associated with this command.
129157Seric 	*/
130157Seric 
131200Seric 	switch (cmd->sccsoper)
132200Seric 	{
133200Seric 	  case PROG:		/* call an sccs prog */
134201Seric 		callprog(cmd->sccspath, cmd->sccsflags, argv, forkflag);
135201Seric 		break;
136201Seric 
137201Seric 	  case CMACRO:		/* command macro */
138201Seric 		for (p = cmd->sccspath; *p != '\0'; p++)
139201Seric 		{
140201Seric 			for (q = buf; *p != '/' && *p != '\0'; p++, q++)
141201Seric 				*q = *p;
142201Seric 			*q = '\0';
143201Seric 			argv[0] = buf;
144201Seric 			command(argv, *p != '\0');
145201Seric 		}
146201Seric 		fprintf(stderr, "Sccs internal error: CMACRO\n");
147200Seric 		exit(EX_SOFTWARE);
148157Seric 
149200Seric 	  default:
150200Seric 		fprintf(stderr, "Sccs internal error: oper %d\n", cmd->sccsoper);
151200Seric 		exit(EX_SOFTWARE);
152200Seric 	}
153200Seric }
154200Seric 
155200Seric callprog(progpath, flags, argv, forkflag)
156200Seric 	char *progpath;
157200Seric 	short flags;
158200Seric 	char **argv;
159200Seric 	bool forkflag;
160200Seric {
161200Seric 	register char *p;
162200Seric 	register char **av;
163200Seric 	char *newargv[1000];
164200Seric 	extern char *makefile();
165200Seric 	register int i;
166201Seric 	auto int st;
167200Seric 
168200Seric 	if (*argv == NULL)
169200Seric 		return (-1);
170200Seric 
171157Seric 	/*
172148Seric 	**  Build new argument vector.
173148Seric 	*/
174148Seric 
175148Seric 	av = newargv;
176200Seric 	*av++ = *argv;
177148Seric 
178153Seric 	/* copy program filename arguments and flags */
179200Seric 	while ((p = *++argv) != NULL)
180148Seric 	{
181200Seric 		if (!bitset(NO_SDOT, flags) && *p != '-')
182153Seric 			*av++ = makefile(p);
183148Seric 		else
184153Seric 			*av++ = p;
185148Seric 	}
186148Seric 
187148Seric 	/* terminate argument vector */
188148Seric 	*av = NULL;
189148Seric 
190148Seric 	/*
191148Seric 	**  Call real SCCS program.
192148Seric 	*/
193148Seric 
194200Seric 	if (forkflag)
195200Seric 	{
196200Seric 		i = fork();
197200Seric 		if (i < 0)
198200Seric 		{
199200Seric 			fprintf(stderr, "Sccs: cannot fork");
200200Seric 			exit(EX_OSERR);
201200Seric 		}
202200Seric 		else if (i > 0)
203201Seric 		{
204201Seric 			wait(&st);
205201Seric 			return (st);
206201Seric 		}
207200Seric 	}
208200Seric 
209200Seric 	/*
210200Seric 	**  Set protection as appropriate.
211200Seric 	*/
212200Seric 
213200Seric 	if (bitset(REALUSER, flags))
214200Seric 		setuid(getuid());
215200Seric 
216200Seric 	/*
217200Seric 	**  Call the program.
218200Seric 	*/
219200Seric 
220200Seric 	execv(progpath, newargv);
221148Seric 	fprintf(stderr, "Sccs: cannot execute ");
222200Seric 	perror(progpath);
223148Seric 	exit(EX_UNAVAILABLE);
224148Seric }
225148Seric 
226148Seric 
227148Seric char *
228148Seric makefile(name)
229148Seric 	char *name;
230148Seric {
231148Seric 	register char *p;
232148Seric 	register char c;
233148Seric 	char buf[512];
234148Seric 	struct stat stbuf;
235148Seric 	extern char *malloc();
236148Seric 
237148Seric 	/*
238148Seric 	**  See if this filename should be used as-is.
239148Seric 	**	There are three conditions where this can occur.
240148Seric 	**	1. The name already begins with "s.".
241148Seric 	**	2. The name has a "/" in it somewhere.
242148Seric 	**	3. The name references a directory.
243148Seric 	*/
244148Seric 
245148Seric 	if (strncmp(name, "s.", 2) == 0)
246148Seric 		return (name);
247148Seric 	for (p = name; (c = *p) != '\0'; p++)
248148Seric 	{
249148Seric 		if (c == '/')
250148Seric 			return (name);
251148Seric 	}
252148Seric 	if (stat(name, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR)
253148Seric 		return (name);
254148Seric 
255148Seric 	/*
256148Seric 	**  Prepend the path of the sccs file.
257148Seric 	*/
258148Seric 
259148Seric 	strcpy(buf, SccsPath);
260157Seric 	strcat(buf, "/s.");
261148Seric 	strcat(buf, name);
262148Seric 	p = malloc(strlen(buf) + 1);
263148Seric 	if (p == NULL)
264148Seric 	{
265148Seric 		perror("Sccs: no mem");
266148Seric 		exit(EX_OSERR);
267148Seric 	}
268148Seric 	strcpy(p, buf);
269148Seric 	return (p);
270148Seric }
271