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, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 char copyright[] = 36 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 static char sccsid[] = "@(#)lpc.c 5.11 (Berkeley) 3/2/91"; 42 #endif /* not lint */ 43 44 /* 45 * lpc -- line printer control program 46 */ 47 #include <stdio.h> 48 #include <signal.h> 49 #include <ctype.h> 50 #include <setjmp.h> 51 #include <syslog.h> 52 53 #include "lpc.h" 54 55 int fromatty; 56 57 char cmdline[200]; 58 int margc; 59 char *margv[20]; 60 int top; 61 void intr(); 62 struct cmd *getcmd(); 63 64 jmp_buf toplevel; 65 66 main(argc, argv) 67 char *argv[]; 68 { 69 register struct cmd *c; 70 extern char *name; 71 72 name = argv[0]; 73 openlog("lpd", 0, LOG_LPR); 74 75 if (--argc > 0) { 76 c = getcmd(*++argv); 77 if (c == (struct cmd *)-1) { 78 printf("?Ambiguous command\n"); 79 exit(1); 80 } 81 if (c == 0) { 82 printf("?Invalid command\n"); 83 exit(1); 84 } 85 if (c->c_priv && getuid()) { 86 printf("?Privileged command\n"); 87 exit(1); 88 } 89 (*c->c_handler)(argc, argv); 90 exit(0); 91 } 92 fromatty = isatty(fileno(stdin)); 93 top = setjmp(toplevel) == 0; 94 if (top) 95 signal(SIGINT, intr); 96 for (;;) { 97 cmdscanner(top); 98 top = 1; 99 } 100 } 101 102 void 103 intr() 104 { 105 if (!fromatty) 106 exit(0); 107 longjmp(toplevel, 1); 108 } 109 110 /* 111 * Command parser. 112 */ 113 cmdscanner(top) 114 int top; 115 { 116 register struct cmd *c; 117 118 if (!top) 119 putchar('\n'); 120 for (;;) { 121 if (fromatty) { 122 printf("lpc> "); 123 fflush(stdout); 124 } 125 if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 126 quit(); 127 if (cmdline[0] == 0 || cmdline[0] == '\n') 128 break; 129 makeargv(); 130 c = getcmd(margv[0]); 131 if (c == (struct cmd *)-1) { 132 printf("?Ambiguous command\n"); 133 continue; 134 } 135 if (c == 0) { 136 printf("?Invalid command\n"); 137 continue; 138 } 139 if (c->c_priv && getuid()) { 140 printf("?Privileged command\n"); 141 continue; 142 } 143 (*c->c_handler)(margc, margv); 144 } 145 longjmp(toplevel, 0); 146 } 147 148 extern struct cmd cmdtab[]; 149 150 struct cmd * 151 getcmd(name) 152 register char *name; 153 { 154 register char *p, *q; 155 register struct cmd *c, *found; 156 register int nmatches, longest; 157 158 longest = 0; 159 nmatches = 0; 160 found = 0; 161 for (c = cmdtab; p = c->c_name; c++) { 162 for (q = name; *q == *p++; q++) 163 if (*q == 0) /* exact match? */ 164 return(c); 165 if (!*q) { /* the name was a prefix */ 166 if (q - name > longest) { 167 longest = q - name; 168 nmatches = 1; 169 found = c; 170 } else if (q - name == longest) 171 nmatches++; 172 } 173 } 174 if (nmatches > 1) 175 return((struct cmd *)-1); 176 return(found); 177 } 178 179 /* 180 * Slice a string up into argc/argv. 181 */ 182 makeargv() 183 { 184 register char *cp; 185 register char **argp = margv; 186 187 margc = 0; 188 for (cp = cmdline; *cp;) { 189 while (isspace(*cp)) 190 cp++; 191 if (*cp == '\0') 192 break; 193 *argp++ = cp; 194 margc += 1; 195 while (*cp != '\0' && !isspace(*cp)) 196 cp++; 197 if (*cp == '\0') 198 break; 199 *cp++ = '\0'; 200 } 201 *argp++ = 0; 202 } 203 204 #define HELPINDENT (sizeof ("directory")) 205 206 /* 207 * Help command. 208 */ 209 help(argc, argv) 210 int argc; 211 char *argv[]; 212 { 213 register struct cmd *c; 214 215 if (argc == 1) { 216 register int i, j, w; 217 int columns, width = 0, lines; 218 extern int NCMDS; 219 220 printf("Commands may be abbreviated. Commands are:\n\n"); 221 for (c = cmdtab; c->c_name; c++) { 222 int len = strlen(c->c_name); 223 224 if (len > width) 225 width = len; 226 } 227 width = (width + 8) &~ 7; 228 columns = 80 / width; 229 if (columns == 0) 230 columns = 1; 231 lines = (NCMDS + columns - 1) / columns; 232 for (i = 0; i < lines; i++) { 233 for (j = 0; j < columns; j++) { 234 c = cmdtab + j * lines + i; 235 if (c->c_name) 236 printf("%s", c->c_name); 237 if (c + lines >= &cmdtab[NCMDS]) { 238 printf("\n"); 239 break; 240 } 241 w = strlen(c->c_name); 242 while (w < width) { 243 w = (w + 8) &~ 7; 244 putchar('\t'); 245 } 246 } 247 } 248 return; 249 } 250 while (--argc > 0) { 251 register char *arg; 252 arg = *++argv; 253 c = getcmd(arg); 254 if (c == (struct cmd *)-1) 255 printf("?Ambiguous help command %s\n", arg); 256 else if (c == (struct cmd *)0) 257 printf("?Invalid help command %s\n", arg); 258 else 259 printf("%-*s\t%s\n", HELPINDENT, 260 c->c_name, c->c_help); 261 } 262 } 263