11553Srgrimes/*-
21553Srgrimes * Copyright (c) 1985, 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * Redistribution and use in source and binary forms, with or without
61553Srgrimes * modification, are permitted provided that the following conditions
71553Srgrimes * are met:
81553Srgrimes * 1. Redistributions of source code must retain the above copyright
91553Srgrimes *    notice, this list of conditions and the following disclaimer.
101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111553Srgrimes *    notice, this list of conditions and the following disclaimer in the
121553Srgrimes *    documentation and/or other materials provided with the distribution.
131553Srgrimes * 4. Neither the name of the University nor the names of its contributors
141553Srgrimes *    may be used to endorse or promote products derived from this software
151553Srgrimes *    without specific prior written permission.
161553Srgrimes *
171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271553Srgrimes * SUCH DAMAGE.
281553Srgrimes */
291553Srgrimes
301553Srgrimes#ifndef lint
3130642Scharnierstatic const char copyright[] =
321553Srgrimes"@(#) Copyright (c) 1985, 1993\n\
331553Srgrimes	The Regents of the University of California.  All rights reserved.\n";
341553Srgrimes#endif /* not lint */
351553Srgrimes
361553Srgrimes#ifndef lint
3730642Scharnier#if 0
381553Srgrimesstatic char sccsid[] = "@(#)timedc.c	8.1 (Berkeley) 6/6/93";
3930642Scharnier#endif
4030642Scharnierstatic const char rcsid[] =
4150479Speter  "$FreeBSD$";
421553Srgrimes#endif /* not lint */
431553Srgrimes
441553Srgrimes#include "timedc.h"
451553Srgrimes#include <ctype.h>
4630642Scharnier#include <err.h>
471553Srgrimes#include <setjmp.h>
4830642Scharnier#include <signal.h>
491553Srgrimes#include <stdlib.h>
50116078Simp#include <string.h>
511553Srgrimes#include <syslog.h>
5230642Scharnier#include <unistd.h>
531553Srgrimes
541553Srgrimesint trace = 0;
551553SrgrimesFILE *fd = 0;
561553Srgrimesint	margc;
571553Srgrimesint	fromatty;
58120995Stjr#define	MAX_MARGV	20
59120995Stjrchar	*margv[MAX_MARGV];
601553Srgrimeschar	cmdline[200];
611553Srgrimesjmp_buf	toplevel;
62173412Skevlostatic struct cmd *getcmd(char *);
631553Srgrimes
641553Srgrimesint
651553Srgrimesmain(argc, argv)
661553Srgrimes	int argc;
671553Srgrimes	char *argv[];
681553Srgrimes{
691553Srgrimes	register struct cmd *c;
701553Srgrimes
711553Srgrimes	openlog("timedc", LOG_ODELAY, LOG_AUTH);
721553Srgrimes
731553Srgrimes	/*
741553Srgrimes	 * security dictates!
751553Srgrimes	 */
7630642Scharnier	if (priv_resources() < 0)
7730642Scharnier		errx(1, "could not get privileged resources");
78220970Ssimon	if (setuid(getuid()) != 0)
79220970Ssimon		err(1, "setuid()");
801553Srgrimes
811553Srgrimes	if (--argc > 0) {
821553Srgrimes		c = getcmd(*++argv);
831553Srgrimes		if (c == (struct cmd *)-1) {
841553Srgrimes			printf("?Ambiguous command\n");
851553Srgrimes			exit(1);
861553Srgrimes		}
871553Srgrimes		if (c == 0) {
881553Srgrimes			printf("?Invalid command\n");
891553Srgrimes			exit(1);
901553Srgrimes		}
911553Srgrimes		if (c->c_priv && getuid()) {
921553Srgrimes			printf("?Privileged command\n");
931553Srgrimes			exit(1);
941553Srgrimes		}
951553Srgrimes		(*c->c_handler)(argc, argv);
961553Srgrimes		exit(0);
971553Srgrimes	}
981553Srgrimes
991553Srgrimes	fromatty = isatty(fileno(stdin));
1001553Srgrimes	if (setjmp(toplevel))
1011553Srgrimes		putchar('\n');
1021553Srgrimes	(void) signal(SIGINT, intr);
1031553Srgrimes	for (;;) {
1041553Srgrimes		if (fromatty) {
1051553Srgrimes			printf("timedc> ");
1061553Srgrimes			(void) fflush(stdout);
1071553Srgrimes		}
1081553Srgrimes		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
1091553Srgrimes			quit();
1101553Srgrimes		if (cmdline[0] == 0)
1111553Srgrimes			break;
1121553Srgrimes		makeargv();
1131553Srgrimes		if (margv[0] == 0)
1141553Srgrimes			continue;
1151553Srgrimes		c = getcmd(margv[0]);
1161553Srgrimes		if (c == (struct cmd *)-1) {
1171553Srgrimes			printf("?Ambiguous command\n");
1181553Srgrimes			continue;
1191553Srgrimes		}
1201553Srgrimes		if (c == 0) {
1211553Srgrimes			printf("?Invalid command\n");
1221553Srgrimes			continue;
1231553Srgrimes		}
1241553Srgrimes		if (c->c_priv && getuid()) {
1251553Srgrimes			printf("?Privileged command\n");
1261553Srgrimes			continue;
1271553Srgrimes		}
1281553Srgrimes		(*c->c_handler)(margc, margv);
1291553Srgrimes	}
1301553Srgrimes	return 0;
1311553Srgrimes}
1321553Srgrimes
1331553Srgrimesvoid
1341553Srgrimesintr(signo)
1351553Srgrimes	int signo;
1361553Srgrimes{
1371553Srgrimes	if (!fromatty)
1381553Srgrimes		exit(0);
1391553Srgrimes	longjmp(toplevel, 1);
1401553Srgrimes}
1411553Srgrimes
1421553Srgrimes
1431553Srgrimesstatic struct cmd *
1441553Srgrimesgetcmd(name)
1451553Srgrimes	char *name;
1461553Srgrimes{
1471553Srgrimes	register char *p, *q;
1481553Srgrimes	register struct cmd *c, *found;
1491553Srgrimes	register int nmatches, longest;
1501553Srgrimes	extern int NCMDS;
1511553Srgrimes
1521553Srgrimes	longest = 0;
1531553Srgrimes	nmatches = 0;
1541553Srgrimes	found = 0;
1551553Srgrimes	for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
1561553Srgrimes		p = c->c_name;
1571553Srgrimes		for (q = name; *q == *p++; q++)
1581553Srgrimes			if (*q == 0)		/* exact match? */
1591553Srgrimes				return(c);
1601553Srgrimes		if (!*q) {			/* the name was a prefix */
1611553Srgrimes			if (q - name > longest) {
1621553Srgrimes				longest = q - name;
1631553Srgrimes				nmatches = 1;
1641553Srgrimes				found = c;
1651553Srgrimes			} else if (q - name == longest)
1661553Srgrimes				nmatches++;
1671553Srgrimes		}
1681553Srgrimes	}
1691553Srgrimes	if (nmatches > 1)
1701553Srgrimes		return((struct cmd *)-1);
1711553Srgrimes	return(found);
1721553Srgrimes}
1731553Srgrimes
1741553Srgrimes/*
1751553Srgrimes * Slice a string up into argc/argv.
1761553Srgrimes */
1771553Srgrimesvoid
1781553Srgrimesmakeargv()
1791553Srgrimes{
1801553Srgrimes	register char *cp;
1811553Srgrimes	register char **argp = margv;
1821553Srgrimes
1831553Srgrimes	margc = 0;
184120995Stjr	for (cp = cmdline; margc < MAX_MARGV - 1 && *cp; ) {
1851553Srgrimes		while (isspace(*cp))
1861553Srgrimes			cp++;
1871553Srgrimes		if (*cp == '\0')
1881553Srgrimes			break;
1891553Srgrimes		*argp++ = cp;
1901553Srgrimes		margc += 1;
1911553Srgrimes		while (*cp != '\0' && !isspace(*cp))
1921553Srgrimes			cp++;
1931553Srgrimes		if (*cp == '\0')
1941553Srgrimes			break;
1951553Srgrimes		*cp++ = '\0';
1961553Srgrimes	}
1971553Srgrimes	*argp++ = 0;
1981553Srgrimes}
1991553Srgrimes
2001553Srgrimes#define HELPINDENT (sizeof ("directory"))
2011553Srgrimes
2021553Srgrimes/*
2031553Srgrimes * Help command.
2041553Srgrimes */
2051553Srgrimesvoid
2061553Srgrimeshelp(argc, argv)
2071553Srgrimes	int argc;
2081553Srgrimes	char *argv[];
2091553Srgrimes{
2101553Srgrimes	register struct cmd *c;
2111553Srgrimes
2121553Srgrimes	if (argc == 1) {
2131553Srgrimes		register int i, j, w;
2141553Srgrimes		int columns, width = 0, lines;
2151553Srgrimes		extern int NCMDS;
2161553Srgrimes
2171553Srgrimes		printf("Commands may be abbreviated.  Commands are:\n\n");
2181553Srgrimes		for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
2191553Srgrimes			int len = strlen(c->c_name);
2201553Srgrimes
2211553Srgrimes			if (len > width)
2221553Srgrimes				width = len;
2231553Srgrimes		}
2241553Srgrimes		width = (width + 8) &~ 7;
2251553Srgrimes		columns = 80 / width;
2261553Srgrimes		if (columns == 0)
2271553Srgrimes			columns = 1;
2281553Srgrimes		lines = (NCMDS + columns - 1) / columns;
2291553Srgrimes		for (i = 0; i < lines; i++) {
2301553Srgrimes			for (j = 0; j < columns; j++) {
2311553Srgrimes				c = cmdtab + j * lines + i;
2321553Srgrimes				printf("%s", c->c_name);
2331553Srgrimes				if (c + lines >= &cmdtab[NCMDS]) {
2341553Srgrimes					printf("\n");
2351553Srgrimes					break;
2361553Srgrimes				}
2371553Srgrimes				w = strlen(c->c_name);
2381553Srgrimes				while (w < width) {
2391553Srgrimes					w = (w + 8) &~ 7;
2401553Srgrimes					putchar('\t');
2411553Srgrimes				}
2421553Srgrimes			}
2431553Srgrimes		}
2441553Srgrimes		return;
2451553Srgrimes	}
2461553Srgrimes	while (--argc > 0) {
2471553Srgrimes		register char *arg;
2481553Srgrimes		arg = *++argv;
2491553Srgrimes		c = getcmd(arg);
2501553Srgrimes		if (c == (struct cmd *)-1)
2511553Srgrimes			printf("?Ambiguous help command %s\n", arg);
2521553Srgrimes		else if (c == (struct cmd *)0)
2531553Srgrimes			printf("?Invalid help command %s\n", arg);
2541553Srgrimes		else
2551553Srgrimes			printf("%-*s\t%s\n", (int)HELPINDENT,
2561553Srgrimes				c->c_name, c->c_help);
2571553Srgrimes	}
2581553Srgrimes}
259