1/*-
2 * Copyright (c) 1985, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35__attribute__((__used__))
36static const char copyright[] =
37"@(#) Copyright (c) 1985, 1993\n\
38	The Regents of the University of California.  All rights reserved.\n";
39#endif /* not lint */
40
41#ifndef lint
42#if 0
43static char sccsid[] = "@(#)timedc.c	8.1 (Berkeley) 6/6/93";
44#endif
45__attribute__((__used__))
46static const char rcsid[] =
47  "$FreeBSD: src/usr.sbin/timed/timedc/timedc.c,v 1.6 2007/11/07 10:53:41 kevlo Exp $";
48#endif /* not lint */
49#include <sys/cdefs.h>
50
51#include "timedc.h"
52#include <ctype.h>
53#include <err.h>
54#include <setjmp.h>
55#include <signal.h>
56#include <stdlib.h>
57#include <string.h>
58#include <syslog.h>
59#include <unistd.h>
60
61int trace = 0;
62FILE *fd = 0;
63int	margc;
64int	fromatty;
65#define	MAX_MARGV	20
66char	*margv[MAX_MARGV];
67char	cmdline[200];
68jmp_buf	toplevel;
69static struct cmd *getcmd(char *);
70
71int
72main(argc, argv)
73	int argc;
74	char *argv[];
75{
76	register struct cmd *c;
77
78	openlog("timedc", LOG_ODELAY, LOG_AUTH);
79
80	/*
81	 * security dictates!
82	 */
83	if (priv_resources() < 0)
84		errx(1, "could not get privileged resources");
85	(void) setuid(getuid());
86
87	if (--argc > 0) {
88		c = getcmd(*++argv);
89		if (c == (struct cmd *)-1) {
90			printf("?Ambiguous command\n");
91			exit(1);
92		}
93		if (c == 0) {
94			printf("?Invalid command\n");
95			exit(1);
96		}
97		if (c->c_priv && getuid()) {
98			printf("?Privileged command\n");
99			exit(1);
100		}
101		(*c->c_handler)(argc, argv);
102		exit(0);
103	}
104
105	fromatty = isatty(fileno(stdin));
106	if (setjmp(toplevel))
107		putchar('\n');
108	(void) signal(SIGINT, intr);
109	for (;;) {
110		if (fromatty) {
111			printf("timedc> ");
112			(void) fflush(stdout);
113		}
114		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
115			quit();
116		if (cmdline[0] == 0)
117			break;
118		makeargv();
119		if (margv[0] == 0)
120			continue;
121		c = getcmd(margv[0]);
122		if (c == (struct cmd *)-1) {
123			printf("?Ambiguous command\n");
124			continue;
125		}
126		if (c == 0) {
127			printf("?Invalid command\n");
128			continue;
129		}
130		if (c->c_priv && getuid()) {
131			printf("?Privileged command\n");
132			continue;
133		}
134		(*c->c_handler)(margc, margv);
135	}
136	return 0;
137}
138
139void
140intr(signo)
141	int signo;
142{
143	if (!fromatty)
144		exit(0);
145	longjmp(toplevel, 1);
146}
147
148
149static struct cmd *
150getcmd(name)
151	char *name;
152{
153	register char *p, *q;
154	register struct cmd *c, *found;
155	register int nmatches, longest;
156	extern int NCMDS;
157
158	longest = 0;
159	nmatches = 0;
160	found = 0;
161	for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
162		p = c->c_name;
163		for (q = name; *q == *p++; q++)
164			if (*q == 0)		/* exact match? */
165				return(c);
166		if (!*q) {			/* the name was a prefix */
167			if (q - name > longest) {
168				longest = q - name;
169				nmatches = 1;
170				found = c;
171			} else if (q - name == longest)
172				nmatches++;
173		}
174	}
175	if (nmatches > 1)
176		return((struct cmd *)-1);
177	return(found);
178}
179
180/*
181 * Slice a string up into argc/argv.
182 */
183void
184makeargv()
185{
186	register char *cp;
187	register char **argp = margv;
188
189	margc = 0;
190	for (cp = cmdline; margc < MAX_MARGV - 1 && *cp; ) {
191		while (isspace(*cp))
192			cp++;
193		if (*cp == '\0')
194			break;
195		*argp++ = cp;
196		margc += 1;
197		while (*cp != '\0' && !isspace(*cp))
198			cp++;
199		if (*cp == '\0')
200			break;
201		*cp++ = '\0';
202	}
203	*argp++ = 0;
204}
205
206#define HELPINDENT (sizeof ("directory"))
207
208/*
209 * Help command.
210 */
211void
212help(argc, argv)
213	int argc;
214	char *argv[];
215{
216	register struct cmd *c;
217
218	if (argc == 1) {
219		register int i, j, w;
220		int columns, width = 0, lines;
221		extern int NCMDS;
222
223		printf("Commands may be abbreviated.  Commands are:\n\n");
224		for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
225			int len = strlen(c->c_name);
226
227			if (len > width)
228				width = len;
229		}
230		width = (width + 8) &~ 7;
231		columns = 80 / width;
232		if (columns == 0)
233			columns = 1;
234		lines = (NCMDS + columns - 1) / columns;
235		for (i = 0; i < lines; i++) {
236			for (j = 0; j < columns; j++) {
237				c = cmdtab + j * lines + i;
238				printf("%s", c->c_name);
239				if (c + lines >= &cmdtab[NCMDS]) {
240					printf("\n");
241					break;
242				}
243				w = strlen(c->c_name);
244				while (w < width) {
245					w = (w + 8) &~ 7;
246					putchar('\t');
247				}
248			}
249		}
250		return;
251	}
252	while (--argc > 0) {
253		register char *arg;
254		arg = *++argv;
255		c = getcmd(arg);
256		if (c == (struct cmd *)-1)
257			printf("?Ambiguous help command %s\n", arg);
258		else if (c == (struct cmd *)0)
259			printf("?Invalid help command %s\n", arg);
260		else
261			printf("%-*s\t%s\n", (int)HELPINDENT,
262				c->c_name, c->c_help);
263	}
264}
265