159906Sbostic /*-
2*61885Sbostic * Copyright (c) 1985, 1993
3*61885Sbostic * The Regents of the University of California. All rights reserved.
433123Sbostic *
542829Sbostic * %sccs.include.redist.c%
623670Sgusella */
723670Sgusella
823670Sgusella #ifndef lint
9*61885Sbostic static char copyright[] =
10*61885Sbostic "@(#) Copyright (c) 1985, 1993\n\
11*61885Sbostic The Regents of the University of California. All rights reserved.\n";
1233123Sbostic #endif /* not lint */
1323670Sgusella
1423670Sgusella #ifndef lint
15*61885Sbostic static char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 06/06/93";
1633123Sbostic #endif /* not lint */
1723670Sgusella
1859906Sbostic #ifdef sgi
1959906Sbostic #ident "$Revision: 1.6 $"
2059906Sbostic #endif
2159906Sbostic
2223670Sgusella #include "timedc.h"
2359906Sbostic #include <strings.h>
2423670Sgusella #include <signal.h>
2523670Sgusella #include <ctype.h>
2623670Sgusella #include <setjmp.h>
2759906Sbostic #include <unistd.h>
2859906Sbostic #include <stdlib.h>
2924908Sbloom #include <syslog.h>
3023670Sgusella
3159906Sbostic int trace = 0;
3259906Sbostic FILE *fd = 0;
3323670Sgusella int margc;
3423670Sgusella int fromatty;
3523670Sgusella char *margv[20];
3623670Sgusella char cmdline[200];
3723670Sgusella jmp_buf toplevel;
3859906Sbostic static struct cmd *getcmd __P((char *));
3923670Sgusella
4059906Sbostic int
main(argc,argv)4123670Sgusella main(argc, argv)
4259906Sbostic int argc;
4323670Sgusella char *argv[];
4423670Sgusella {
4523670Sgusella register struct cmd *c;
4623670Sgusella
4724872Seric openlog("timedc", LOG_ODELAY, LOG_AUTH);
4824872Seric
4923670Sgusella /*
5023670Sgusella * security dictates!
5123670Sgusella */
5223670Sgusella if (priv_resources() < 0) {
5339719Sbostic fprintf(stderr, "Could not get privileged resources\n");
5423670Sgusella exit(1);
5523670Sgusella }
5623670Sgusella (void) setuid(getuid());
5723670Sgusella
5823670Sgusella if (--argc > 0) {
5923670Sgusella c = getcmd(*++argv);
6023670Sgusella if (c == (struct cmd *)-1) {
6123670Sgusella printf("?Ambiguous command\n");
6223670Sgusella exit(1);
6323670Sgusella }
6423670Sgusella if (c == 0) {
6523670Sgusella printf("?Invalid command\n");
6623670Sgusella exit(1);
6723670Sgusella }
6829348Sbloom if (c->c_priv && getuid()) {
6929348Sbloom printf("?Privileged command\n");
7029348Sbloom exit(1);
7129348Sbloom }
7223670Sgusella (*c->c_handler)(argc, argv);
7323670Sgusella exit(0);
7423670Sgusella }
7559906Sbostic
7623670Sgusella fromatty = isatty(fileno(stdin));
7759906Sbostic if (setjmp(toplevel))
7823670Sgusella putchar('\n');
7959906Sbostic (void) signal(SIGINT, intr);
8023670Sgusella for (;;) {
8123670Sgusella if (fromatty) {
8223670Sgusella printf("timedc> ");
8323670Sgusella (void) fflush(stdout);
8423670Sgusella }
8536246Sbostic if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
8623670Sgusella quit();
8723670Sgusella if (cmdline[0] == 0)
8823670Sgusella break;
8923670Sgusella makeargv();
9059906Sbostic if (margv[0] == 0)
9159906Sbostic continue;
9223670Sgusella c = getcmd(margv[0]);
9323670Sgusella if (c == (struct cmd *)-1) {
9423670Sgusella printf("?Ambiguous command\n");
9523670Sgusella continue;
9623670Sgusella }
9723670Sgusella if (c == 0) {
9823670Sgusella printf("?Invalid command\n");
9923670Sgusella continue;
10023670Sgusella }
10123670Sgusella if (c->c_priv && getuid()) {
10223670Sgusella printf("?Privileged command\n");
10323670Sgusella continue;
10423670Sgusella }
10523670Sgusella (*c->c_handler)(margc, margv);
10623670Sgusella }
10759906Sbostic return 0;
10823670Sgusella }
10923670Sgusella
11059906Sbostic void
intr(signo)11159906Sbostic intr(signo)
11259906Sbostic int signo;
11359906Sbostic {
11459906Sbostic if (!fromatty)
11559906Sbostic exit(0);
11659906Sbostic longjmp(toplevel, 1);
11759906Sbostic }
11859906Sbostic
11959906Sbostic
12059906Sbostic static struct cmd *
getcmd(name)12123670Sgusella getcmd(name)
12259906Sbostic char *name;
12323670Sgusella {
12423670Sgusella register char *p, *q;
12523670Sgusella register struct cmd *c, *found;
12623670Sgusella register int nmatches, longest;
12725961Sbloom extern int NCMDS;
12823670Sgusella
12923670Sgusella longest = 0;
13023670Sgusella nmatches = 0;
13123670Sgusella found = 0;
13225961Sbloom for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
13325961Sbloom p = c->c_name;
13423670Sgusella for (q = name; *q == *p++; q++)
13523670Sgusella if (*q == 0) /* exact match? */
13623670Sgusella return(c);
13723670Sgusella if (!*q) { /* the name was a prefix */
13823670Sgusella if (q - name > longest) {
13923670Sgusella longest = q - name;
14023670Sgusella nmatches = 1;
14123670Sgusella found = c;
14223670Sgusella } else if (q - name == longest)
14323670Sgusella nmatches++;
14423670Sgusella }
14523670Sgusella }
14623670Sgusella if (nmatches > 1)
14723670Sgusella return((struct cmd *)-1);
14823670Sgusella return(found);
14923670Sgusella }
15023670Sgusella
15123670Sgusella /*
15223670Sgusella * Slice a string up into argc/argv.
15323670Sgusella */
15459906Sbostic void
makeargv()15523670Sgusella makeargv()
15623670Sgusella {
15723670Sgusella register char *cp;
15823670Sgusella register char **argp = margv;
15923670Sgusella
16023670Sgusella margc = 0;
16123670Sgusella for (cp = cmdline; *cp;) {
16223670Sgusella while (isspace(*cp))
16323670Sgusella cp++;
16423670Sgusella if (*cp == '\0')
16523670Sgusella break;
16623670Sgusella *argp++ = cp;
16723670Sgusella margc += 1;
16823670Sgusella while (*cp != '\0' && !isspace(*cp))
16923670Sgusella cp++;
17023670Sgusella if (*cp == '\0')
17123670Sgusella break;
17223670Sgusella *cp++ = '\0';
17323670Sgusella }
17423670Sgusella *argp++ = 0;
17523670Sgusella }
17623670Sgusella
17723670Sgusella #define HELPINDENT (sizeof ("directory"))
17823670Sgusella
17923670Sgusella /*
18023670Sgusella * Help command.
18123670Sgusella */
18259906Sbostic void
help(argc,argv)18323670Sgusella help(argc, argv)
18423670Sgusella int argc;
18523670Sgusella char *argv[];
18623670Sgusella {
18723670Sgusella register struct cmd *c;
18823670Sgusella
18923670Sgusella if (argc == 1) {
19023670Sgusella register int i, j, w;
19123670Sgusella int columns, width = 0, lines;
19223670Sgusella extern int NCMDS;
19323670Sgusella
19423670Sgusella printf("Commands may be abbreviated. Commands are:\n\n");
19523670Sgusella for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
19623670Sgusella int len = strlen(c->c_name);
19723670Sgusella
19823670Sgusella if (len > width)
19923670Sgusella width = len;
20023670Sgusella }
20123670Sgusella width = (width + 8) &~ 7;
20223670Sgusella columns = 80 / width;
20323670Sgusella if (columns == 0)
20423670Sgusella columns = 1;
20523670Sgusella lines = (NCMDS + columns - 1) / columns;
20623670Sgusella for (i = 0; i < lines; i++) {
20723670Sgusella for (j = 0; j < columns; j++) {
20823670Sgusella c = cmdtab + j * lines + i;
20923670Sgusella printf("%s", c->c_name);
21023670Sgusella if (c + lines >= &cmdtab[NCMDS]) {
21123670Sgusella printf("\n");
21223670Sgusella break;
21323670Sgusella }
21423670Sgusella w = strlen(c->c_name);
21523670Sgusella while (w < width) {
21623670Sgusella w = (w + 8) &~ 7;
21723670Sgusella putchar('\t');
21823670Sgusella }
21923670Sgusella }
22023670Sgusella }
22123670Sgusella return;
22223670Sgusella }
22323670Sgusella while (--argc > 0) {
22423670Sgusella register char *arg;
22523670Sgusella arg = *++argv;
22623670Sgusella c = getcmd(arg);
22723670Sgusella if (c == (struct cmd *)-1)
22823670Sgusella printf("?Ambiguous help command %s\n", arg);
22923670Sgusella else if (c == (struct cmd *)0)
23023670Sgusella printf("?Invalid help command %s\n", arg);
23123670Sgusella else
23259906Sbostic printf("%-*s\t%s\n", (int)HELPINDENT,
23323670Sgusella c->c_name, c->c_help);
23423670Sgusella }
23523670Sgusella }
236