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