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