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