123670Sgusella /* 223670Sgusella * Copyright (c) 1983 Regents of the University of California. 333123Sbostic * All rights reserved. 433123Sbostic * 5*42829Sbostic * %sccs.include.redist.c% 623670Sgusella */ 723670Sgusella 823670Sgusella #ifndef lint 923670Sgusella char copyright[] = 1023670Sgusella "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1123670Sgusella All rights reserved.\n"; 1233123Sbostic #endif /* not lint */ 1323670Sgusella 1423670Sgusella #ifndef lint 15*42829Sbostic static char sccsid[] = "@(#)timedc.c 2.9 (Berkeley) 06/01/90"; 1633123Sbostic #endif /* not lint */ 1723670Sgusella 1823670Sgusella #include "timedc.h" 1923670Sgusella #include <signal.h> 2023670Sgusella #include <ctype.h> 2123670Sgusella #include <setjmp.h> 2224908Sbloom #include <syslog.h> 2323670Sgusella 2423670Sgusella int top; 2523670Sgusella int margc; 2623670Sgusella int fromatty; 2723670Sgusella char *margv[20]; 2823670Sgusella char cmdline[200]; 2923670Sgusella jmp_buf toplevel; 3023670Sgusella int intr(); 3123670Sgusella int priv_resources(); 3223670Sgusella struct cmd *getcmd(); 3323670Sgusella 3423670Sgusella 3523670Sgusella main(argc, argv) 3623670Sgusella char *argv[]; 3723670Sgusella { 3823670Sgusella register struct cmd *c; 3923670Sgusella 4024872Seric openlog("timedc", LOG_ODELAY, LOG_AUTH); 4124872Seric 4223670Sgusella /* 4323670Sgusella * security dictates! 4423670Sgusella */ 4523670Sgusella if (priv_resources() < 0) { 4639719Sbostic fprintf(stderr, "Could not get privileged resources\n"); 4723670Sgusella exit(1); 4823670Sgusella } 4923670Sgusella (void) setuid(getuid()); 5023670Sgusella 5123670Sgusella if (--argc > 0) { 5223670Sgusella c = getcmd(*++argv); 5323670Sgusella if (c == (struct cmd *)-1) { 5423670Sgusella printf("?Ambiguous command\n"); 5523670Sgusella exit(1); 5623670Sgusella } 5723670Sgusella if (c == 0) { 5823670Sgusella printf("?Invalid command\n"); 5923670Sgusella exit(1); 6023670Sgusella } 6129348Sbloom if (c->c_priv && getuid()) { 6229348Sbloom printf("?Privileged command\n"); 6329348Sbloom exit(1); 6429348Sbloom } 6523670Sgusella (*c->c_handler)(argc, argv); 6623670Sgusella exit(0); 6723670Sgusella } 6823670Sgusella fromatty = isatty(fileno(stdin)); 6923670Sgusella top = setjmp(toplevel) == 0; 7023670Sgusella if (top) 7123670Sgusella (void) signal(SIGINT, intr); 7223670Sgusella for (;;) { 7323670Sgusella cmdscanner(top); 7423670Sgusella top = 1; 7523670Sgusella } 7623670Sgusella } 7723670Sgusella 7823670Sgusella intr() 7923670Sgusella { 8023670Sgusella if (!fromatty) 8123670Sgusella exit(0); 8223670Sgusella longjmp(toplevel, 1); 8323670Sgusella } 8423670Sgusella 8523670Sgusella /* 8623670Sgusella * Command parser. 8723670Sgusella */ 8823670Sgusella cmdscanner(top) 8923670Sgusella int top; 9023670Sgusella { 9123670Sgusella register struct cmd *c; 9223670Sgusella extern int help(); 9323670Sgusella 9423670Sgusella if (!top) 9523670Sgusella putchar('\n'); 9623670Sgusella for (;;) { 9723670Sgusella if (fromatty) { 9823670Sgusella printf("timedc> "); 9923670Sgusella (void) fflush(stdout); 10023670Sgusella } 10136246Sbostic if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 10223670Sgusella quit(); 10323670Sgusella if (cmdline[0] == 0) 10423670Sgusella break; 10523670Sgusella makeargv(); 10623670Sgusella c = getcmd(margv[0]); 10723670Sgusella if (c == (struct cmd *)-1) { 10823670Sgusella printf("?Ambiguous command\n"); 10923670Sgusella continue; 11023670Sgusella } 11123670Sgusella if (c == 0) { 11223670Sgusella printf("?Invalid command\n"); 11323670Sgusella continue; 11423670Sgusella } 11523670Sgusella if (c->c_priv && getuid()) { 11623670Sgusella printf("?Privileged command\n"); 11723670Sgusella continue; 11823670Sgusella } 11923670Sgusella (*c->c_handler)(margc, margv); 12023670Sgusella } 12123670Sgusella longjmp(toplevel, 0); 12223670Sgusella } 12323670Sgusella 12423670Sgusella struct cmd * 12523670Sgusella getcmd(name) 12623670Sgusella register char *name; 12723670Sgusella { 12823670Sgusella register char *p, *q; 12923670Sgusella register struct cmd *c, *found; 13023670Sgusella register int nmatches, longest; 13133158Sbostic extern struct cmd cmdtab[]; 13225961Sbloom extern int NCMDS; 13323670Sgusella 13423670Sgusella longest = 0; 13523670Sgusella nmatches = 0; 13623670Sgusella found = 0; 13725961Sbloom for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 13825961Sbloom p = c->c_name; 13923670Sgusella for (q = name; *q == *p++; q++) 14023670Sgusella if (*q == 0) /* exact match? */ 14123670Sgusella return(c); 14223670Sgusella if (!*q) { /* the name was a prefix */ 14323670Sgusella if (q - name > longest) { 14423670Sgusella longest = q - name; 14523670Sgusella nmatches = 1; 14623670Sgusella found = c; 14723670Sgusella } else if (q - name == longest) 14823670Sgusella nmatches++; 14923670Sgusella } 15023670Sgusella } 15123670Sgusella if (nmatches > 1) 15223670Sgusella return((struct cmd *)-1); 15323670Sgusella return(found); 15423670Sgusella } 15523670Sgusella 15623670Sgusella /* 15723670Sgusella * Slice a string up into argc/argv. 15823670Sgusella */ 15923670Sgusella makeargv() 16023670Sgusella { 16123670Sgusella register char *cp; 16223670Sgusella register char **argp = margv; 16323670Sgusella 16423670Sgusella margc = 0; 16523670Sgusella for (cp = cmdline; *cp;) { 16623670Sgusella while (isspace(*cp)) 16723670Sgusella cp++; 16823670Sgusella if (*cp == '\0') 16923670Sgusella break; 17023670Sgusella *argp++ = cp; 17123670Sgusella margc += 1; 17223670Sgusella while (*cp != '\0' && !isspace(*cp)) 17323670Sgusella cp++; 17423670Sgusella if (*cp == '\0') 17523670Sgusella break; 17623670Sgusella *cp++ = '\0'; 17723670Sgusella } 17823670Sgusella *argp++ = 0; 17923670Sgusella } 18023670Sgusella 18123670Sgusella #define HELPINDENT (sizeof ("directory")) 18223670Sgusella 18323670Sgusella /* 18423670Sgusella * Help command. 18523670Sgusella */ 18623670Sgusella help(argc, argv) 18723670Sgusella int argc; 18823670Sgusella char *argv[]; 18923670Sgusella { 19023670Sgusella register struct cmd *c; 19133158Sbostic extern struct cmd cmdtab[]; 19223670Sgusella 19323670Sgusella if (argc == 1) { 19423670Sgusella register int i, j, w; 19523670Sgusella int columns, width = 0, lines; 19623670Sgusella extern int NCMDS; 19723670Sgusella 19823670Sgusella printf("Commands may be abbreviated. Commands are:\n\n"); 19923670Sgusella for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 20023670Sgusella int len = strlen(c->c_name); 20123670Sgusella 20223670Sgusella if (len > width) 20323670Sgusella width = len; 20423670Sgusella } 20523670Sgusella width = (width + 8) &~ 7; 20623670Sgusella columns = 80 / width; 20723670Sgusella if (columns == 0) 20823670Sgusella columns = 1; 20923670Sgusella lines = (NCMDS + columns - 1) / columns; 21023670Sgusella for (i = 0; i < lines; i++) { 21123670Sgusella for (j = 0; j < columns; j++) { 21223670Sgusella c = cmdtab + j * lines + i; 21323670Sgusella printf("%s", c->c_name); 21423670Sgusella if (c + lines >= &cmdtab[NCMDS]) { 21523670Sgusella printf("\n"); 21623670Sgusella break; 21723670Sgusella } 21823670Sgusella w = strlen(c->c_name); 21923670Sgusella while (w < width) { 22023670Sgusella w = (w + 8) &~ 7; 22123670Sgusella putchar('\t'); 22223670Sgusella } 22323670Sgusella } 22423670Sgusella } 22523670Sgusella return; 22623670Sgusella } 22723670Sgusella while (--argc > 0) { 22823670Sgusella register char *arg; 22923670Sgusella arg = *++argv; 23023670Sgusella c = getcmd(arg); 23123670Sgusella if (c == (struct cmd *)-1) 23223670Sgusella printf("?Ambiguous help command %s\n", arg); 23323670Sgusella else if (c == (struct cmd *)0) 23423670Sgusella printf("?Invalid help command %s\n", arg); 23523670Sgusella else 23623670Sgusella printf("%-*s\t%s\n", HELPINDENT, 23723670Sgusella c->c_name, c->c_help); 23823670Sgusella } 23923670Sgusella } 240