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.13 (Berkeley) 8/6/92"; 42 #endif /* not lint */ 43 44 #include <sys/param.h> 45 46 #include <dirent.h> 47 #include <signal.h> 48 #include <setjmp.h> 49 #include <syslog.h> 50 #include <unistd.h> 51 #include <stdlib.h> 52 #include <stdio.h> 53 #include <ctype.h> 54 #include <string.h> 55 #include "lp.h" 56 #include "lpc.h" 57 #include "extern.h" 58 59 /* 60 * lpc -- line printer control program 61 */ 62 63 int fromatty; 64 65 char cmdline[200]; 66 int margc; 67 char *margv[20]; 68 int top; 69 70 jmp_buf toplevel; 71 72 static void cmdscanner __P((int)); 73 static struct cmd *getcmd __P((char *)); 74 static void intr __P((int)); 75 static void makeargv __P((void)); 76 77 int 78 main(argc, argv) 79 int argc; 80 char *argv[]; 81 { 82 register struct cmd *c; 83 84 name = argv[0]; 85 openlog("lpd", 0, LOG_LPR); 86 87 if (--argc > 0) { 88 c = getcmd(*++argv); 89 if (c == (struct cmd *)-1) { 90 printf("?Ambiguous command\n"); 91 exit(1); 92 } 93 if (c == 0) { 94 printf("?Invalid command\n"); 95 exit(1); 96 } 97 if (c->c_priv && getuid()) { 98 printf("?Privileged command\n"); 99 exit(1); 100 } 101 (*c->c_handler)(argc, argv); 102 exit(0); 103 } 104 fromatty = isatty(fileno(stdin)); 105 top = setjmp(toplevel) == 0; 106 if (top) 107 signal(SIGINT, intr); 108 for (;;) { 109 cmdscanner(top); 110 top = 1; 111 } 112 } 113 114 static void 115 intr(signo) 116 int signo; 117 { 118 if (!fromatty) 119 exit(0); 120 longjmp(toplevel, 1); 121 } 122 123 /* 124 * Command parser. 125 */ 126 static void 127 cmdscanner(top) 128 int top; 129 { 130 register struct cmd *c; 131 132 if (!top) 133 putchar('\n'); 134 for (;;) { 135 if (fromatty) { 136 printf("lpc> "); 137 fflush(stdout); 138 } 139 if (fgets(cmdline, sizeof(cmdline), stdin) == 0) 140 quit(0, NULL); 141 if (cmdline[0] == 0 || cmdline[0] == '\n') 142 break; 143 makeargv(); 144 c = getcmd(margv[0]); 145 if (c == (struct cmd *)-1) { 146 printf("?Ambiguous command\n"); 147 continue; 148 } 149 if (c == 0) { 150 printf("?Invalid command\n"); 151 continue; 152 } 153 if (c->c_priv && getuid()) { 154 printf("?Privileged command\n"); 155 continue; 156 } 157 (*c->c_handler)(margc, margv); 158 } 159 longjmp(toplevel, 0); 160 } 161 162 struct cmd * 163 getcmd(name) 164 register char *name; 165 { 166 register char *p, *q; 167 register struct cmd *c, *found; 168 register int nmatches, longest; 169 170 longest = 0; 171 nmatches = 0; 172 found = 0; 173 for (c = cmdtab; p = c->c_name; c++) { 174 for (q = name; *q == *p++; q++) 175 if (*q == 0) /* exact match? */ 176 return(c); 177 if (!*q) { /* the name was a prefix */ 178 if (q - name > longest) { 179 longest = q - name; 180 nmatches = 1; 181 found = c; 182 } else if (q - name == longest) 183 nmatches++; 184 } 185 } 186 if (nmatches > 1) 187 return((struct cmd *)-1); 188 return(found); 189 } 190 191 /* 192 * Slice a string up into argc/argv. 193 */ 194 static void 195 makeargv() 196 { 197 register char *cp; 198 register char **argp = margv; 199 200 margc = 0; 201 for (cp = cmdline; *cp;) { 202 while (isspace(*cp)) 203 cp++; 204 if (*cp == '\0') 205 break; 206 *argp++ = cp; 207 margc += 1; 208 while (*cp != '\0' && !isspace(*cp)) 209 cp++; 210 if (*cp == '\0') 211 break; 212 *cp++ = '\0'; 213 } 214 *argp++ = 0; 215 } 216 217 #define HELPINDENT (sizeof ("directory")) 218 219 /* 220 * Help command. 221 */ 222 void 223 help(argc, argv) 224 int argc; 225 char *argv[]; 226 { 227 register struct cmd *c; 228 229 if (argc == 1) { 230 register int i, j, w; 231 int columns, width = 0, lines; 232 extern int NCMDS; 233 234 printf("Commands may be abbreviated. Commands are:\n\n"); 235 for (c = cmdtab; c->c_name; c++) { 236 int len = strlen(c->c_name); 237 238 if (len > width) 239 width = len; 240 } 241 width = (width + 8) &~ 7; 242 columns = 80 / width; 243 if (columns == 0) 244 columns = 1; 245 lines = (NCMDS + columns - 1) / columns; 246 for (i = 0; i < lines; i++) { 247 for (j = 0; j < columns; j++) { 248 c = cmdtab + j * lines + i; 249 if (c->c_name) 250 printf("%s", c->c_name); 251 if (c + lines >= &cmdtab[NCMDS]) { 252 printf("\n"); 253 break; 254 } 255 w = strlen(c->c_name); 256 while (w < width) { 257 w = (w + 8) &~ 7; 258 putchar('\t'); 259 } 260 } 261 } 262 return; 263 } 264 while (--argc > 0) { 265 register char *arg; 266 arg = *++argv; 267 c = getcmd(arg); 268 if (c == (struct cmd *)-1) 269 printf("?Ambiguous help command %s\n", arg); 270 else if (c == (struct cmd *)0) 271 printf("?Invalid help command %s\n", arg); 272 else 273 printf("%-*s\t%s\n", HELPINDENT, 274 c->c_name, c->c_help); 275 } 276 } 277