xref: /csrg-svn/usr.bin/sccs/sccs.c (revision 200)
1148Seric # include <stdio.h>
2148Seric # include <sys/types.h>
3148Seric # include <sys/stat.h>
4148Seric # include <sysexits.h>
5148Seric 
6*200Seric static char SccsId[] = "@(#)sccs.c 1.7 delta 05/22/80 20:24:38 get 10/14/12 16:33:34";
7155Seric 
8157Seric # define bitset(bit, word)	((bit) & (word))
9157Seric 
10157Seric typedef char	bool;
11*200Seric # define TRUE	1
12*200Seric # define FALSE	0
13157Seric 
14148Seric struct sccsprog
15148Seric {
16148Seric 	char	*sccsname;	/* name of SCCS routine */
17*200Seric 	short	sccsoper;	/* opcode, see below */
18*200Seric 	short	sccsflags;	/* flags, see below */
19148Seric 	char	*sccspath;	/* pathname of binary implementing */
20148Seric };
21148Seric 
22*200Seric /* values for sccsoper */
23*200Seric # define PROG		0	/* call a program */
24*200Seric 
25157Seric /* bits for sccsflags */
26*200Seric # define NO_SDOT	0001	/* no s. on front of args */
27*200Seric # define REALUSER	0002	/* protected (e.g., admin) */
28148Seric 
29148Seric struct sccsprog SccsProg[] =
30148Seric {
31*200Seric 	"admin",	PROG,	REALUSER,		"/usr/sccs/admin",
32*200Seric 	"chghist",	PROG,	0,			"/usr/sccs/rmdel",
33*200Seric 	"comb",		PROG,	0,			"/usr/sccs/comb",
34*200Seric 	"delta",	PROG,	0,			"/usr/sccs/delta",
35*200Seric 	"get",		PROG,	0,			"/usr/sccs/get",
36*200Seric 	"help",		PROG,	NO_SDOT,		"/usr/sccs/help",
37*200Seric 	"prt",		PROG,	0,			"/usr/sccs/prt",
38*200Seric 	"rmdel",	PROG,	REALUSER,		"/usr/sccs/rmdel",
39*200Seric 	"what",		PROG,	NO_SDOT,		"/usr/sccs/what",
40*200Seric 	NULL,		-1,	0,			NULL
41148Seric };
42148Seric 
43157Seric char	*SccsPath = "SCCS";	/* pathname of SCCS files */
44157Seric bool	RealUser;		/* if set, running as real user */
45148Seric 
46148Seric main(argc, argv)
47148Seric 	int argc;
48148Seric 	char **argv;
49148Seric {
50148Seric 	register char *p;
51148Seric 
52148Seric 	/*
53148Seric 	**  Detect and decode flags intended for this program.
54148Seric 	*/
55148Seric 
56*200Seric 	if (argc < 2)
57148Seric 	{
58*200Seric 		fprintf(stderr, "Usage: sccs [flags] command [flags]\n");
59*200Seric 		exit(EX_USAGE);
60*200Seric 	}
61*200Seric 	argv[argc] = NULL;
62*200Seric 
63*200Seric 	while ((p = *++argv) != NULL)
64*200Seric 	{
65148Seric 		if (*p != '-')
66148Seric 			break;
67148Seric 		switch (*++p)
68148Seric 		{
69148Seric 		  case 'r':		/* run as real user */
70148Seric 			setuid(getuid());
71157Seric 			RealUser++;
72148Seric 			break;
73148Seric 
74148Seric 		  case 'p':		/* path of sccs files */
75148Seric 			SccsPath = ++p;
76148Seric 			break;
77148Seric 
78148Seric 		  default:
79148Seric 			fprintf(stderr, "Sccs: unknown option -%s\n", p);
80148Seric 			break;
81148Seric 		}
82148Seric 	}
83158Seric 	if (SccsPath[0] == '\0')
84158Seric 		SccsPath = ".";
85148Seric 
86*200Seric 	command(argv);
87*200Seric 	exit(EX_OK);
88*200Seric }
89157Seric 
90*200Seric command(argv)
91*200Seric 	char **argv;
92*200Seric {
93*200Seric 	register struct sccsprog *cmd;
94*200Seric 	register char *p;
95*200Seric 
96157Seric 	/*
97148Seric 	**  Look up command.
98*200Seric 	**	At this point, argv points to the command name.
99148Seric 	*/
100148Seric 
101*200Seric 	p = *argv;
102148Seric 	for (cmd = SccsProg; cmd->sccsname != NULL; cmd++)
103148Seric 	{
104148Seric 		if (strcmp(cmd->sccsname, p) == 0)
105148Seric 			break;
106148Seric 	}
107148Seric 	if (cmd->sccsname == NULL)
108148Seric 	{
109148Seric 		fprintf(stderr, "Sccs: Unknown command \"%s\"\n", p);
110148Seric 		exit(EX_USAGE);
111148Seric 	}
112148Seric 
113148Seric 	/*
114*200Seric 	**  Interpret operation associated with this command.
115157Seric 	*/
116157Seric 
117*200Seric 	switch (cmd->sccsoper)
118*200Seric 	{
119*200Seric 	  case PROG:		/* call an sccs prog */
120*200Seric 		callprog(cmd->sccspath, cmd->sccsflags, argv, FALSE);
121*200Seric 		fprintf(stderr, "Sccs internal error: callprog\n");
122*200Seric 		exit(EX_SOFTWARE);
123157Seric 
124*200Seric 	  default:
125*200Seric 		fprintf(stderr, "Sccs internal error: oper %d\n", cmd->sccsoper);
126*200Seric 		exit(EX_SOFTWARE);
127*200Seric 	}
128*200Seric }
129*200Seric 
130*200Seric callprog(progpath, flags, argv, forkflag)
131*200Seric 	char *progpath;
132*200Seric 	short flags;
133*200Seric 	char **argv;
134*200Seric 	bool forkflag;
135*200Seric {
136*200Seric 	register char *p;
137*200Seric 	register char **av;
138*200Seric 	char *newargv[1000];
139*200Seric 	extern char *makefile();
140*200Seric 	register int i;
141*200Seric 
142*200Seric 	if (*argv == NULL)
143*200Seric 		return (-1);
144*200Seric 
145157Seric 	/*
146148Seric 	**  Build new argument vector.
147148Seric 	*/
148148Seric 
149148Seric 	av = newargv;
150*200Seric 	*av++ = *argv;
151148Seric 
152153Seric 	/* copy program filename arguments and flags */
153*200Seric 	while ((p = *++argv) != NULL)
154148Seric 	{
155*200Seric 		if (!bitset(NO_SDOT, flags) && *p != '-')
156153Seric 			*av++ = makefile(p);
157148Seric 		else
158153Seric 			*av++ = p;
159148Seric 	}
160148Seric 
161148Seric 	/* terminate argument vector */
162148Seric 	*av = NULL;
163148Seric 
164148Seric 	/*
165148Seric 	**  Call real SCCS program.
166148Seric 	*/
167148Seric 
168*200Seric 	if (forkflag)
169*200Seric 	{
170*200Seric 		i = fork();
171*200Seric 		if (i < 0)
172*200Seric 		{
173*200Seric 			fprintf(stderr, "Sccs: cannot fork");
174*200Seric 			exit(EX_OSERR);
175*200Seric 		}
176*200Seric 		else if (i > 0)
177*200Seric 			return (i);
178*200Seric 	}
179*200Seric 
180*200Seric 	/*
181*200Seric 	**  Set protection as appropriate.
182*200Seric 	*/
183*200Seric 
184*200Seric 	if (bitset(REALUSER, flags))
185*200Seric 		setuid(getuid());
186*200Seric 
187*200Seric 	/*
188*200Seric 	**  Call the program.
189*200Seric 	*/
190*200Seric 
191*200Seric 	execv(progpath, newargv);
192148Seric 	fprintf(stderr, "Sccs: cannot execute ");
193*200Seric 	perror(progpath);
194148Seric 	exit(EX_UNAVAILABLE);
195148Seric }
196148Seric 
197148Seric 
198148Seric char *
199148Seric makefile(name)
200148Seric 	char *name;
201148Seric {
202148Seric 	register char *p;
203148Seric 	register char c;
204148Seric 	char buf[512];
205148Seric 	struct stat stbuf;
206148Seric 	extern char *malloc();
207148Seric 
208148Seric 	/*
209148Seric 	**  See if this filename should be used as-is.
210148Seric 	**	There are three conditions where this can occur.
211148Seric 	**	1. The name already begins with "s.".
212148Seric 	**	2. The name has a "/" in it somewhere.
213148Seric 	**	3. The name references a directory.
214148Seric 	*/
215148Seric 
216148Seric 	if (strncmp(name, "s.", 2) == 0)
217148Seric 		return (name);
218148Seric 	for (p = name; (c = *p) != '\0'; p++)
219148Seric 	{
220148Seric 		if (c == '/')
221148Seric 			return (name);
222148Seric 	}
223148Seric 	if (stat(name, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR)
224148Seric 		return (name);
225148Seric 
226148Seric 	/*
227148Seric 	**  Prepend the path of the sccs file.
228148Seric 	*/
229148Seric 
230148Seric 	strcpy(buf, SccsPath);
231157Seric 	strcat(buf, "/s.");
232148Seric 	strcat(buf, name);
233148Seric 	p = malloc(strlen(buf) + 1);
234148Seric 	if (p == NULL)
235148Seric 	{
236148Seric 		perror("Sccs: no mem");
237148Seric 		exit(EX_OSERR);
238148Seric 	}
239148Seric 	strcpy(p, buf);
240148Seric 	return (p);
241148Seric }
242