1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 char copyright[] = 15 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif /* not lint */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)timedc.c 2.4 (Berkeley) 12/23/87"; 21 #endif /* not lint */ 22 23 #include "timedc.h" 24 #include <signal.h> 25 #include <ctype.h> 26 #include <setjmp.h> 27 #include <syslog.h> 28 29 int top; 30 int margc; 31 int fromatty; 32 char *margv[20]; 33 char cmdline[200]; 34 jmp_buf toplevel; 35 int intr(); 36 int priv_resources(); 37 struct cmd *getcmd(); 38 39 40 main(argc, argv) 41 char *argv[]; 42 { 43 register struct cmd *c; 44 45 openlog("timedc", LOG_ODELAY, LOG_AUTH); 46 47 /* 48 * security dictates! 49 */ 50 if (priv_resources() < 0) { 51 fprintf(stderr, "Could not get priviledged resources\n"); 52 exit(1); 53 } 54 (void) setuid(getuid()); 55 56 if (--argc > 0) { 57 c = getcmd(*++argv); 58 if (c == (struct cmd *)-1) { 59 printf("?Ambiguous command\n"); 60 exit(1); 61 } 62 if (c == 0) { 63 printf("?Invalid command\n"); 64 exit(1); 65 } 66 if (c->c_priv && getuid()) { 67 printf("?Privileged command\n"); 68 exit(1); 69 } 70 (*c->c_handler)(argc, argv); 71 exit(0); 72 } 73 fromatty = isatty(fileno(stdin)); 74 top = setjmp(toplevel) == 0; 75 if (top) 76 (void) signal(SIGINT, intr); 77 for (;;) { 78 cmdscanner(top); 79 top = 1; 80 } 81 } 82 83 intr() 84 { 85 if (!fromatty) 86 exit(0); 87 longjmp(toplevel, 1); 88 } 89 90 /* 91 * Command parser. 92 */ 93 cmdscanner(top) 94 int top; 95 { 96 register struct cmd *c; 97 extern struct cmd cmdtab[]; 98 extern int help(); 99 100 if (!top) 101 putchar('\n'); 102 for (;;) { 103 if (fromatty) { 104 printf("timedc> "); 105 (void) fflush(stdout); 106 } 107 if (gets(cmdline) == 0) 108 quit(); 109 if (cmdline[0] == 0) 110 break; 111 makeargv(); 112 c = getcmd(margv[0]); 113 if (c == (struct cmd *)-1) { 114 printf("?Ambiguous command\n"); 115 continue; 116 } 117 if (c == 0) { 118 printf("?Invalid command\n"); 119 continue; 120 } 121 if (c->c_priv && getuid()) { 122 printf("?Privileged command\n"); 123 continue; 124 } 125 (*c->c_handler)(margc, margv); 126 } 127 longjmp(toplevel, 0); 128 } 129 130 struct cmd * 131 getcmd(name) 132 register char *name; 133 { 134 register char *p, *q; 135 register struct cmd *c, *found; 136 register int nmatches, longest; 137 extern int NCMDS; 138 139 longest = 0; 140 nmatches = 0; 141 found = 0; 142 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 143 p = c->c_name; 144 for (q = name; *q == *p++; q++) 145 if (*q == 0) /* exact match? */ 146 return(c); 147 if (!*q) { /* the name was a prefix */ 148 if (q - name > longest) { 149 longest = q - name; 150 nmatches = 1; 151 found = c; 152 } else if (q - name == longest) 153 nmatches++; 154 } 155 } 156 if (nmatches > 1) 157 return((struct cmd *)-1); 158 return(found); 159 } 160 161 /* 162 * Slice a string up into argc/argv. 163 */ 164 makeargv() 165 { 166 register char *cp; 167 register char **argp = margv; 168 169 margc = 0; 170 for (cp = cmdline; *cp;) { 171 while (isspace(*cp)) 172 cp++; 173 if (*cp == '\0') 174 break; 175 *argp++ = cp; 176 margc += 1; 177 while (*cp != '\0' && !isspace(*cp)) 178 cp++; 179 if (*cp == '\0') 180 break; 181 *cp++ = '\0'; 182 } 183 *argp++ = 0; 184 } 185 186 #define HELPINDENT (sizeof ("directory")) 187 188 /* 189 * Help command. 190 */ 191 help(argc, argv) 192 int argc; 193 char *argv[]; 194 { 195 register struct cmd *c; 196 197 if (argc == 1) { 198 register int i, j, w; 199 int columns, width = 0, lines; 200 extern int NCMDS; 201 202 printf("Commands may be abbreviated. Commands are:\n\n"); 203 for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { 204 int len = strlen(c->c_name); 205 206 if (len > width) 207 width = len; 208 } 209 width = (width + 8) &~ 7; 210 columns = 80 / width; 211 if (columns == 0) 212 columns = 1; 213 lines = (NCMDS + columns - 1) / columns; 214 for (i = 0; i < lines; i++) { 215 for (j = 0; j < columns; j++) { 216 c = cmdtab + j * lines + i; 217 printf("%s", c->c_name); 218 if (c + lines >= &cmdtab[NCMDS]) { 219 printf("\n"); 220 break; 221 } 222 w = strlen(c->c_name); 223 while (w < width) { 224 w = (w + 8) &~ 7; 225 putchar('\t'); 226 } 227 } 228 } 229 return; 230 } 231 while (--argc > 0) { 232 register char *arg; 233 arg = *++argv; 234 c = getcmd(arg); 235 if (c == (struct cmd *)-1) 236 printf("?Ambiguous help command %s\n", arg); 237 else if (c == (struct cmd *)0) 238 printf("?Invalid help command %s\n", arg); 239 else 240 printf("%-*s\t%s\n", HELPINDENT, 241 c->c_name, c->c_help); 242 } 243 } 244