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