xref: /original-bsd/usr.sbin/timed/timedc/timedc.c (revision 2bd07fe6)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)timedc.c	2.8 (Berkeley) 12/14/89";
26 #endif /* not lint */
27 
28 #include "timedc.h"
29 #include <signal.h>
30 #include <ctype.h>
31 #include <setjmp.h>
32 #include <syslog.h>
33 
34 int	top;
35 int	margc;
36 int	fromatty;
37 char	*margv[20];
38 char	cmdline[200];
39 jmp_buf	toplevel;
40 int	intr();
41 int priv_resources();
42 struct	cmd *getcmd();
43 
44 
45 main(argc, argv)
46 	char *argv[];
47 {
48 	register struct cmd *c;
49 
50 	openlog("timedc", LOG_ODELAY, LOG_AUTH);
51 
52 	/*
53 	 * security dictates!
54 	 */
55 	if (priv_resources() < 0) {
56 		fprintf(stderr, "Could not get privileged resources\n");
57 		exit(1);
58 	}
59 	(void) setuid(getuid());
60 
61 	if (--argc > 0) {
62 		c = getcmd(*++argv);
63 		if (c == (struct cmd *)-1) {
64 			printf("?Ambiguous command\n");
65 			exit(1);
66 		}
67 		if (c == 0) {
68 			printf("?Invalid command\n");
69 			exit(1);
70 		}
71 		if (c->c_priv && getuid()) {
72 			printf("?Privileged command\n");
73 			exit(1);
74 		}
75 		(*c->c_handler)(argc, argv);
76 		exit(0);
77 	}
78 	fromatty = isatty(fileno(stdin));
79 	top = setjmp(toplevel) == 0;
80 	if (top)
81 		(void) signal(SIGINT, intr);
82 	for (;;) {
83 		cmdscanner(top);
84 		top = 1;
85 	}
86 }
87 
88 intr()
89 {
90 	if (!fromatty)
91 		exit(0);
92 	longjmp(toplevel, 1);
93 }
94 
95 /*
96  * Command parser.
97  */
98 cmdscanner(top)
99 	int top;
100 {
101 	register struct cmd *c;
102 	extern int help();
103 
104 	if (!top)
105 		putchar('\n');
106 	for (;;) {
107 		if (fromatty) {
108 			printf("timedc> ");
109 			(void) fflush(stdout);
110 		}
111 		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
112 			quit();
113 		if (cmdline[0] == 0)
114 			break;
115 		makeargv();
116 		c = getcmd(margv[0]);
117 		if (c == (struct cmd *)-1) {
118 			printf("?Ambiguous command\n");
119 			continue;
120 		}
121 		if (c == 0) {
122 			printf("?Invalid command\n");
123 			continue;
124 		}
125 		if (c->c_priv && getuid()) {
126 			printf("?Privileged command\n");
127 			continue;
128 		}
129 		(*c->c_handler)(margc, margv);
130 	}
131 	longjmp(toplevel, 0);
132 }
133 
134 struct cmd *
135 getcmd(name)
136 	register char *name;
137 {
138 	register char *p, *q;
139 	register struct cmd *c, *found;
140 	register int nmatches, longest;
141 	extern struct cmd cmdtab[];
142 	extern int NCMDS;
143 
144 	longest = 0;
145 	nmatches = 0;
146 	found = 0;
147 	for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
148 		p = c->c_name;
149 		for (q = name; *q == *p++; q++)
150 			if (*q == 0)		/* exact match? */
151 				return(c);
152 		if (!*q) {			/* the name was a prefix */
153 			if (q - name > longest) {
154 				longest = q - name;
155 				nmatches = 1;
156 				found = c;
157 			} else if (q - name == longest)
158 				nmatches++;
159 		}
160 	}
161 	if (nmatches > 1)
162 		return((struct cmd *)-1);
163 	return(found);
164 }
165 
166 /*
167  * Slice a string up into argc/argv.
168  */
169 makeargv()
170 {
171 	register char *cp;
172 	register char **argp = margv;
173 
174 	margc = 0;
175 	for (cp = cmdline; *cp;) {
176 		while (isspace(*cp))
177 			cp++;
178 		if (*cp == '\0')
179 			break;
180 		*argp++ = cp;
181 		margc += 1;
182 		while (*cp != '\0' && !isspace(*cp))
183 			cp++;
184 		if (*cp == '\0')
185 			break;
186 		*cp++ = '\0';
187 	}
188 	*argp++ = 0;
189 }
190 
191 #define HELPINDENT (sizeof ("directory"))
192 
193 /*
194  * Help command.
195  */
196 help(argc, argv)
197 	int argc;
198 	char *argv[];
199 {
200 	register struct cmd *c;
201 	extern struct cmd cmdtab[];
202 
203 	if (argc == 1) {
204 		register int i, j, w;
205 		int columns, width = 0, lines;
206 		extern int NCMDS;
207 
208 		printf("Commands may be abbreviated.  Commands are:\n\n");
209 		for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
210 			int len = strlen(c->c_name);
211 
212 			if (len > width)
213 				width = len;
214 		}
215 		width = (width + 8) &~ 7;
216 		columns = 80 / width;
217 		if (columns == 0)
218 			columns = 1;
219 		lines = (NCMDS + columns - 1) / columns;
220 		for (i = 0; i < lines; i++) {
221 			for (j = 0; j < columns; j++) {
222 				c = cmdtab + j * lines + i;
223 				printf("%s", c->c_name);
224 				if (c + lines >= &cmdtab[NCMDS]) {
225 					printf("\n");
226 					break;
227 				}
228 				w = strlen(c->c_name);
229 				while (w < width) {
230 					w = (w + 8) &~ 7;
231 					putchar('\t');
232 				}
233 			}
234 		}
235 		return;
236 	}
237 	while (--argc > 0) {
238 		register char *arg;
239 		arg = *++argv;
240 		c = getcmd(arg);
241 		if (c == (struct cmd *)-1)
242 			printf("?Ambiguous help command %s\n", arg);
243 		else if (c == (struct cmd *)0)
244 			printf("?Invalid help command %s\n", arg);
245 		else
246 			printf("%-*s\t%s\n", HELPINDENT,
247 				c->c_name, c->c_help);
248 	}
249 }
250