lpc.c revision 15703
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 36static 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 42static char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95"; 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 <grp.h> 57#include <sys/param.h> 58#include "lp.h" 59#include "lpc.h" 60#include "extern.h" 61 62#ifndef LPR_OPER 63#define LPR_OPER "operator" /* group name of lpr operators */ 64#endif 65 66/* 67 * lpc -- line printer control program 68 */ 69 70int fromatty; 71 72char cmdline[200]; 73int margc; 74char *margv[20]; 75int top; 76 77jmp_buf toplevel; 78 79static void cmdscanner __P((int)); 80static struct cmd *getcmd __P((char *)); 81static void intr __P((int)); 82static void makeargv __P((void)); 83static int ingroup __P((char *)); 84 85int 86main(argc, argv) 87 int argc; 88 char *argv[]; 89{ 90 register struct cmd *c; 91 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() && ingroup(LPR_OPER) == 0) { 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 122static void 123intr(signo) 124 int signo; 125{ 126 if (!fromatty) 127 exit(0); 128 longjmp(toplevel, 1); 129} 130 131/* 132 * Command parser. 133 */ 134static void 135cmdscanner(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, sizeof(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() && ingroup(LPR_OPER) == 0) { 162 printf("?Privileged command\n"); 163 continue; 164 } 165 (*c->c_handler)(margc, margv); 166 } 167 longjmp(toplevel, 0); 168} 169 170static struct cmd * 171getcmd(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 */ 202static void 203makeargv() 204{ 205 register char *cp; 206 register char **argp = margv; 207 208 margc = 0; 209 for (cp = cmdline; *cp;) { 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 */ 230void 231help(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 241 printf("Commands may be abbreviated. Commands are:\n\n"); 242 for (c = cmdtab; c->c_name; c++) { 243 int len = strlen(c->c_name); 244 245 if (len > width) 246 width = len; 247 } 248 width = (width + 8) &~ 7; 249 columns = 80 / width; 250 if (columns == 0) 251 columns = 1; 252 lines = (NCMDS + columns - 1) / columns; 253 for (i = 0; i < lines; i++) { 254 for (j = 0; j < columns; j++) { 255 c = cmdtab + j * lines + i; 256 if (c->c_name) 257 printf("%s", c->c_name); 258 if (c + lines >= &cmdtab[NCMDS]) { 259 printf("\n"); 260 break; 261 } 262 w = strlen(c->c_name); 263 while (w < width) { 264 w = (w + 8) &~ 7; 265 putchar('\t'); 266 } 267 } 268 } 269 return; 270 } 271 while (--argc > 0) { 272 register char *arg; 273 arg = *++argv; 274 c = getcmd(arg); 275 if (c == (struct cmd *)-1) 276 printf("?Ambiguous help command %s\n", arg); 277 else if (c == (struct cmd *)0) 278 printf("?Invalid help command %s\n", arg); 279 else 280 printf("%-*s\t%s\n", HELPINDENT, 281 c->c_name, c->c_help); 282 } 283} 284 285/* 286 * return non-zero if the user is a member of the given group 287 */ 288static int 289ingroup(grname) 290 char *grname; 291{ 292 static struct group *gptr=NULL; 293 static gid_t groups[NGROUPS]; 294 register gid_t gid; 295 register int i; 296 297 if (gptr == NULL) { 298 if ((gptr = getgrnam(grname)) == NULL) { 299 fprintf(stderr, "Warning: unknown group '%s'\n", 300 grname); 301 return(0); 302 } 303 if (getgroups(NGROUPS, groups) < 0) { 304 perror("getgroups"); 305 exit(1); 306 } 307 } 308 gid = gptr->gr_gid; 309 for (i = 0; i < NGROUPS; i++) 310 if (gid == groups[i]) 311 return(1); 312 return(0); 313} 314