123670Sgusella /* 223670Sgusella * Copyright (c) 1983 Regents of the University of California. 333123Sbostic * All rights reserved. 433123Sbostic * 533123Sbostic * Redistribution and use in source and binary forms are permitted 633123Sbostic * provided that this notice is preserved and that due credit is given 733123Sbostic * to the University of California at Berkeley. The name of the University 833123Sbostic * may not be used to endorse or promote products derived from this 933123Sbostic * software without specific prior written permission. This software 1033123Sbostic * is provided ``as is'' without express or implied warranty. 1123670Sgusella */ 1223670Sgusella 1323670Sgusella #ifndef lint 1423670Sgusella char copyright[] = 1523670Sgusella "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1623670Sgusella All rights reserved.\n"; 1733123Sbostic #endif /* not lint */ 1823670Sgusella 1923670Sgusella #ifndef lint 20*33158Sbostic static char sccsid[] = "@(#)timedc.c 2.5 (Berkeley) 12/26/87"; 2133123Sbostic #endif /* not lint */ 2223670Sgusella 2323670Sgusella #include "timedc.h" 2423670Sgusella #include <signal.h> 2523670Sgusella #include <ctype.h> 2623670Sgusella #include <setjmp.h> 2724908Sbloom #include <syslog.h> 2823670Sgusella 2923670Sgusella int top; 3023670Sgusella int margc; 3123670Sgusella int fromatty; 3223670Sgusella char *margv[20]; 3323670Sgusella char cmdline[200]; 3423670Sgusella jmp_buf toplevel; 3523670Sgusella int intr(); 3623670Sgusella int priv_resources(); 3723670Sgusella struct cmd *getcmd(); 3823670Sgusella 3923670Sgusella 4023670Sgusella main(argc, argv) 4123670Sgusella char *argv[]; 4223670Sgusella { 4323670Sgusella register struct cmd *c; 4423670Sgusella 4524872Seric openlog("timedc", LOG_ODELAY, LOG_AUTH); 4624872Seric 4723670Sgusella /* 4823670Sgusella * security dictates! 4923670Sgusella */ 5023670Sgusella if (priv_resources() < 0) { 5123670Sgusella fprintf(stderr, "Could not get priviledged resources\n"); 5223670Sgusella exit(1); 5323670Sgusella } 5423670Sgusella (void) setuid(getuid()); 5523670Sgusella 5623670Sgusella if (--argc > 0) { 5723670Sgusella c = getcmd(*++argv); 5823670Sgusella if (c == (struct cmd *)-1) { 5923670Sgusella printf("?Ambiguous command\n"); 6023670Sgusella exit(1); 6123670Sgusella } 6223670Sgusella if (c == 0) { 6323670Sgusella printf("?Invalid command\n"); 6423670Sgusella exit(1); 6523670Sgusella } 6629348Sbloom if (c->c_priv && getuid()) { 6729348Sbloom printf("?Privileged command\n"); 6829348Sbloom exit(1); 6929348Sbloom } 7023670Sgusella (*c->c_handler)(argc, argv); 7123670Sgusella exit(0); 7223670Sgusella } 7323670Sgusella fromatty = isatty(fileno(stdin)); 7423670Sgusella top = setjmp(toplevel) == 0; 7523670Sgusella if (top) 7623670Sgusella (void) signal(SIGINT, intr); 7723670Sgusella for (;;) { 7823670Sgusella cmdscanner(top); 7923670Sgusella top = 1; 8023670Sgusella } 8123670Sgusella } 8223670Sgusella 8323670Sgusella intr() 8423670Sgusella { 8523670Sgusella if (!fromatty) 8623670Sgusella exit(0); 8723670Sgusella longjmp(toplevel, 1); 8823670Sgusella } 8923670Sgusella 9023670Sgusella /* 9123670Sgusella * Command parser. 9223670Sgusella */ 9323670Sgusella cmdscanner(top) 9423670Sgusella int top; 9523670Sgusella { 9623670Sgusella register struct cmd *c; 9723670Sgusella extern int help(); 9823670Sgusella 9923670Sgusella if (!top) 10023670Sgusella putchar('\n'); 10123670Sgusella for (;;) { 10223670Sgusella if (fromatty) { 10323670Sgusella printf("timedc> "); 10423670Sgusella (void) fflush(stdout); 10523670Sgusella } 10623670Sgusella if (gets(cmdline) == 0) 10723670Sgusella quit(); 10823670Sgusella if (cmdline[0] == 0) 10923670Sgusella break; 11023670Sgusella makeargv(); 11123670Sgusella c = getcmd(margv[0]); 11223670Sgusella if (c == (struct cmd *)-1) { 11323670Sgusella printf("?Ambiguous command\n"); 11423670Sgusella continue; 11523670Sgusella } 11623670Sgusella if (c == 0) { 11723670Sgusella printf("?Invalid command\n"); 11823670Sgusella continue; 11923670Sgusella } 12023670Sgusella if (c->c_priv && getuid()) { 12123670Sgusella printf("?Privileged command\n"); 12223670Sgusella continue; 12323670Sgusella } 12423670Sgusella (*c->c_handler)(margc, margv); 12523670Sgusella } 12623670Sgusella longjmp(toplevel, 0); 12723670Sgusella } 12823670Sgusella 12923670Sgusella struct cmd * 13023670Sgusella getcmd(name) 13123670Sgusella register char *name; 13223670Sgusella { 13323670Sgusella register char *p, *q; 13423670Sgusella register struct cmd *c, *found; 13523670Sgusella register int nmatches, longest; 136*33158Sbostic extern struct cmd cmdtab[]; 13725961Sbloom extern int NCMDS; 13823670Sgusella 13923670Sgusella longest = 0; 14023670Sgusella nmatches = 0; 14123670Sgusella found = 0; 14225961Sbloom for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 14325961Sbloom p = c->c_name; 14423670Sgusella for (q = name; *q == *p++; q++) 14523670Sgusella if (*q == 0) /* exact match? */ 14623670Sgusella return(c); 14723670Sgusella if (!*q) { /* the name was a prefix */ 14823670Sgusella if (q - name > longest) { 14923670Sgusella longest = q - name; 15023670Sgusella nmatches = 1; 15123670Sgusella found = c; 15223670Sgusella } else if (q - name == longest) 15323670Sgusella nmatches++; 15423670Sgusella } 15523670Sgusella } 15623670Sgusella if (nmatches > 1) 15723670Sgusella return((struct cmd *)-1); 15823670Sgusella return(found); 15923670Sgusella } 16023670Sgusella 16123670Sgusella /* 16223670Sgusella * Slice a string up into argc/argv. 16323670Sgusella */ 16423670Sgusella makeargv() 16523670Sgusella { 16623670Sgusella register char *cp; 16723670Sgusella register char **argp = margv; 16823670Sgusella 16923670Sgusella margc = 0; 17023670Sgusella for (cp = cmdline; *cp;) { 17123670Sgusella while (isspace(*cp)) 17223670Sgusella cp++; 17323670Sgusella if (*cp == '\0') 17423670Sgusella break; 17523670Sgusella *argp++ = cp; 17623670Sgusella margc += 1; 17723670Sgusella while (*cp != '\0' && !isspace(*cp)) 17823670Sgusella cp++; 17923670Sgusella if (*cp == '\0') 18023670Sgusella break; 18123670Sgusella *cp++ = '\0'; 18223670Sgusella } 18323670Sgusella *argp++ = 0; 18423670Sgusella } 18523670Sgusella 18623670Sgusella #define HELPINDENT (sizeof ("directory")) 18723670Sgusella 18823670Sgusella /* 18923670Sgusella * Help command. 19023670Sgusella */ 19123670Sgusella help(argc, argv) 19223670Sgusella int argc; 19323670Sgusella char *argv[]; 19423670Sgusella { 19523670Sgusella register struct cmd *c; 196*33158Sbostic extern struct cmd cmdtab[]; 19723670Sgusella 19823670Sgusella if (argc == 1) { 19923670Sgusella register int i, j, w; 20023670Sgusella int columns, width = 0, lines; 20123670Sgusella extern int NCMDS; 20223670Sgusella 20323670Sgusella printf("Commands may be abbreviated. Commands are:\n\n"); 20423670Sgusella for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 20523670Sgusella int len = strlen(c->c_name); 20623670Sgusella 20723670Sgusella if (len > width) 20823670Sgusella width = len; 20923670Sgusella } 21023670Sgusella width = (width + 8) &~ 7; 21123670Sgusella columns = 80 / width; 21223670Sgusella if (columns == 0) 21323670Sgusella columns = 1; 21423670Sgusella lines = (NCMDS + columns - 1) / columns; 21523670Sgusella for (i = 0; i < lines; i++) { 21623670Sgusella for (j = 0; j < columns; j++) { 21723670Sgusella c = cmdtab + j * lines + i; 21823670Sgusella printf("%s", c->c_name); 21923670Sgusella if (c + lines >= &cmdtab[NCMDS]) { 22023670Sgusella printf("\n"); 22123670Sgusella break; 22223670Sgusella } 22323670Sgusella w = strlen(c->c_name); 22423670Sgusella while (w < width) { 22523670Sgusella w = (w + 8) &~ 7; 22623670Sgusella putchar('\t'); 22723670Sgusella } 22823670Sgusella } 22923670Sgusella } 23023670Sgusella return; 23123670Sgusella } 23223670Sgusella while (--argc > 0) { 23323670Sgusella register char *arg; 23423670Sgusella arg = *++argv; 23523670Sgusella c = getcmd(arg); 23623670Sgusella if (c == (struct cmd *)-1) 23723670Sgusella printf("?Ambiguous help command %s\n", arg); 23823670Sgusella else if (c == (struct cmd *)0) 23923670Sgusella printf("?Invalid help command %s\n", arg); 24023670Sgusella else 24123670Sgusella printf("%-*s\t%s\n", HELPINDENT, 24223670Sgusella c->c_name, c->c_help); 24323670Sgusella } 24423670Sgusella } 245