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