lpc.c revision 50071
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 const 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#if 0 43static char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95"; 44#endif 45static const char rcsid[] = 46 "$Id: lpc.c,v 1.10 1999/08/19 04:10:32 mdodd Exp $"; 47#endif /* not lint */ 48 49#include <sys/param.h> 50 51#include <ctype.h> 52#include <dirent.h> 53#include <err.h> 54#include <grp.h> 55#include <setjmp.h> 56#include <signal.h> 57#include <stdio.h> 58#include <stdlib.h> 59#include <syslog.h> 60#include <string.h> 61#include <unistd.h> 62#include <histedit.h> 63 64#include "lp.h" 65#include "lpc.h" 66#include "extern.h" 67 68#ifndef LPR_OPER 69#define LPR_OPER "operator" /* group name of lpr operators */ 70#endif 71 72/* 73 * lpc -- line printer control program 74 */ 75 76#define MAX_CMDLINE 200 77#define MAX_MARGV 20 78static int fromatty; 79 80static char cmdline[MAX_CMDLINE]; 81static int margc; 82static char *margv[MAX_MARGV]; 83uid_t uid, euid; 84 85int main __P((int, char *[])); 86static void cmdscanner __P((void)); 87static struct cmd *getcmd __P((char *)); 88static void intr __P((int)); 89static void makeargv __P((void)); 90static int ingroup __P((char *)); 91 92int 93main(argc, argv) 94 int argc; 95 char *argv[]; 96{ 97 register struct cmd *c; 98 99 euid = geteuid(); 100 uid = getuid(); 101 seteuid(uid); 102 name = argv[0]; 103 openlog("lpd", 0, LOG_LPR); 104 105 if (--argc > 0) { 106 c = getcmd(*++argv); 107 if (c == (struct cmd *)-1) { 108 printf("?Ambiguous command\n"); 109 exit(1); 110 } 111 if (c == 0) { 112 printf("?Invalid command\n"); 113 exit(1); 114 } 115 if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 116 printf("?Privileged command\n"); 117 exit(1); 118 } 119 if (c->c_generic != 0) 120 generic(c->c_generic, argc, argv); 121 else 122 (*c->c_handler)(argc, argv); 123 exit(0); 124 } 125 fromatty = isatty(fileno(stdin)); 126 if (!fromatty) 127 signal(SIGINT, intr); 128 for (;;) { 129 cmdscanner(); 130 } 131} 132 133static void 134intr(signo) 135 int signo; 136{ 137 exit(0); 138} 139 140static char * 141lpc_prompt() 142{ 143 return("lpc> "); 144} 145 146/* 147 * Command parser. 148 */ 149static void 150cmdscanner() 151{ 152 register struct cmd *c; 153 static EditLine *el = NULL; 154 static History *hist = NULL; 155 int num = 0; 156 int len; 157 const char *bp = NULL; 158 159 for (;;) { 160 if (fromatty) { 161 if (!el) { 162 el = el_init("lpc", stdin, stdout); 163 hist = history_init(); 164 history(hist, H_EVENT, 100); 165 el_set(el, EL_HIST, history, hist); 166 el_set(el, EL_EDITOR, "emacs"); 167 el_set(el, EL_PROMPT, lpc_prompt); 168 el_set(el, EL_SIGNAL, 1); 169 el_source(el, NULL); 170 } 171 if ((bp = el_gets(el, &num)) == NULL || num == 0) 172 return; 173 174 len = (num > MAX_CMDLINE) ? MAX_CMDLINE : num); 175 memcpy(cmdline, bp, len); 176 cmdline[len] = 0; 177 history(hist, H_ENTER, bp); 178 179 } else { 180 if (fgets(cmdline, MAX_CMDLINE, stdin) == 0) 181 quit(0, NULL); 182 if (cmdline[0] == 0 || cmdline[0] == '\n') 183 break; 184 } 185 186 makeargv(); 187 if (margc == 0) 188 continue; 189 if (el_parse(el, margc, margv) != -1) 190 continue; 191 192 c = getcmd(margv[0]); 193 if (c == (struct cmd *)-1) { 194 printf("?Ambiguous command\n"); 195 continue; 196 } 197 if (c == 0) { 198 printf("?Invalid command\n"); 199 continue; 200 } 201 if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 202 printf("?Privileged command\n"); 203 continue; 204 } 205 if (c->c_generic != 0) 206 generic(c->c_generic, margc, margv); 207 else 208 (*c->c_handler)(margc, margv); 209 } 210} 211 212static struct cmd * 213getcmd(name) 214 register char *name; 215{ 216 register char *p, *q; 217 register struct cmd *c, *found; 218 register int nmatches, longest; 219 220 longest = 0; 221 nmatches = 0; 222 found = 0; 223 for (c = cmdtab; (p = c->c_name); c++) { 224 for (q = name; *q == *p++; q++) 225 if (*q == 0) /* exact match? */ 226 return(c); 227 if (!*q) { /* the name was a prefix */ 228 if (q - name > longest) { 229 longest = q - name; 230 nmatches = 1; 231 found = c; 232 } else if (q - name == longest) 233 nmatches++; 234 } 235 } 236 if (nmatches > 1) 237 return((struct cmd *)-1); 238 return(found); 239} 240 241/* 242 * Slice a string up into argc/argv. 243 */ 244static void 245makeargv() 246{ 247 register char *cp; 248 register char **argp = margv; 249 register int n = 0; 250 251 margc = 0; 252 for (cp = cmdline; *cp && (cp - cmdline) < sizeof(cmdline) && 253 n < MAX_MARGV; n++) { 254 while (isspace(*cp)) 255 cp++; 256 if (*cp == '\0') 257 break; 258 *argp++ = cp; 259 margc += 1; 260 while (*cp != '\0' && !isspace(*cp)) 261 cp++; 262 if (*cp == '\0') 263 break; 264 *cp++ = '\0'; 265 } 266 *argp++ = 0; 267} 268 269#define HELPINDENT (sizeof ("directory")) 270 271/* 272 * Help command. 273 */ 274void 275help(argc, argv) 276 int argc; 277 char *argv[]; 278{ 279 register struct cmd *c; 280 281 if (argc == 1) { 282 register int i, j, w; 283 int columns, width = 0, lines; 284 285 printf("Commands may be abbreviated. Commands are:\n\n"); 286 for (c = cmdtab; c->c_name; c++) { 287 int len = strlen(c->c_name); 288 289 if (len > width) 290 width = len; 291 } 292 width = (width + 8) &~ 7; 293 columns = 80 / width; 294 if (columns == 0) 295 columns = 1; 296 lines = (NCMDS + columns - 1) / columns; 297 for (i = 0; i < lines; i++) { 298 for (j = 0; j < columns; j++) { 299 c = cmdtab + j * lines + i; 300 if (c->c_name) 301 printf("%s", c->c_name); 302 if (c + lines >= &cmdtab[NCMDS]) { 303 printf("\n"); 304 break; 305 } 306 w = strlen(c->c_name); 307 while (w < width) { 308 w = (w + 8) &~ 7; 309 putchar('\t'); 310 } 311 } 312 } 313 return; 314 } 315 while (--argc > 0) { 316 register char *arg; 317 arg = *++argv; 318 c = getcmd(arg); 319 if (c == (struct cmd *)-1) 320 printf("?Ambiguous help command %s\n", arg); 321 else if (c == (struct cmd *)0) 322 printf("?Invalid help command %s\n", arg); 323 else 324 printf("%-*s\t%s\n", (int) HELPINDENT, 325 c->c_name, c->c_help); 326 } 327} 328 329/* 330 * return non-zero if the user is a member of the given group 331 */ 332static int 333ingroup(grname) 334 char *grname; 335{ 336 static struct group *gptr=NULL; 337 static gid_t groups[NGROUPS]; 338 register gid_t gid; 339 register int i; 340 341 if (gptr == NULL) { 342 if ((gptr = getgrnam(grname)) == NULL) { 343 warnx("warning: unknown group '%s'", grname); 344 return(0); 345 } 346 if (getgroups(NGROUPS, groups) < 0) 347 err(1, "getgroups"); 348 } 349 gid = gptr->gr_gid; 350 for (i = 0; i < NGROUPS; i++) 351 if (gid == groups[i]) 352 return(1); 353 return(0); 354} 355