lpc.c revision 50039
1160383Snetchild/* 2160383Snetchild * Copyright (c) 1983, 1993 3172150Sariff * The Regents of the University of California. All rights reserved. 4160383Snetchild * 5160383Snetchild * 6160383Snetchild * Redistribution and use in source and binary forms, with or without 7160383Snetchild * modification, are permitted provided that the following conditions 8160383Snetchild * are met: 9160383Snetchild * 1. Redistributions of source code must retain the above copyright 10160383Snetchild * notice, this list of conditions and the following disclaimer. 11160383Snetchild * 2. Redistributions in binary form must reproduce the above copyright 12160383Snetchild * notice, this list of conditions and the following disclaimer in the 13160383Snetchild * documentation and/or other materials provided with the distribution. 14160383Snetchild * 3. All advertising materials mentioning features or use of this software 15160383Snetchild * must display the following acknowledgement: 16160383Snetchild * This product includes software developed by the University of 17160383Snetchild * California, Berkeley and its contributors. 18160383Snetchild * 4. Neither the name of the University nor the names of its contributors 19160383Snetchild * may be used to endorse or promote products derived from this software 20160383Snetchild * without specific prior written permission. 21160383Snetchild * 22160383Snetchild * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23160383Snetchild * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24160383Snetchild * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25160383Snetchild * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26160383Snetchild * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27160383Snetchild * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28160383Snetchild * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29160383Snetchild * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30160383Snetchild * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31160383Snetchild * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32160383Snetchild * SUCH DAMAGE. 33160383Snetchild */ 34160383Snetchild 35160383Snetchild#ifndef lint 36160383Snetchildstatic const char copyright[] = 37160383Snetchild"@(#) Copyright (c) 1983, 1993\n\ 38160383Snetchild The Regents of the University of California. All rights reserved.\n"; 39160383Snetchild#endif /* not lint */ 40160383Snetchild 41172150Sariff#ifndef lint 42160383Snetchild#if 0 43160383Snetchildstatic char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95"; 44160383Snetchild#endif 45160383Snetchildstatic const char rcsid[] = 46160383Snetchild "$Id: lpc.c,v 1.8 1998/09/11 18:49:31 wollman Exp $"; 47160383Snetchild#endif /* not lint */ 48193640Sariff 49193640Sariff#include <sys/param.h> 50193640Sariff 51193640Sariff#include <ctype.h> 52160383Snetchild#include <dirent.h> 53160383Snetchild#include <err.h> 54160383Snetchild#include <grp.h> 55160383Snetchild#include <setjmp.h> 56229981Spfg#include <signal.h> 57160383Snetchild#include <stdio.h> 58160383Snetchild#include <stdlib.h> 59160383Snetchild#include <syslog.h> 60160383Snetchild#include <string.h> 61160383Snetchild#include <unistd.h> 62160383Snetchild#include <histedit.h> 63160383Snetchild 64160383Snetchild#include "lp.h" 65160383Snetchild#include "lpc.h" 66160383Snetchild#include "extern.h" 67160383Snetchild 68160383Snetchild#ifndef LPR_OPER 69160383Snetchild#define LPR_OPER "operator" /* group name of lpr operators */ 70160383Snetchild#endif 71160383Snetchild 72160383Snetchild/* 73160383Snetchild * lpc -- line printer control program 74160383Snetchild */ 75160383Snetchild 76160383Snetchild#define MAX_CMDLINE 200 77160383Snetchild#define MAX_MARGV 20 78160383Snetchildstatic int fromatty; 79160383Snetchild 80160383Snetchildstatic char cmdline[MAX_CMDLINE]; 81160383Snetchildstatic int margc; 82160383Snetchildstatic char *margv[MAX_MARGV]; 83160383Snetchilduid_t uid, euid; 84160383Snetchild 85160383Snetchildint main __P((int, char *[])); 86160383Snetchildstatic void cmdscanner __P((void)); 87160383Snetchildstatic struct cmd *getcmd __P((char *)); 88160383Snetchildstatic void intr __P((int)); 89160383Snetchildstatic void makeargv __P((void)); 90160383Snetchildstatic int ingroup __P((char *)); 91160383Snetchild 92160383Snetchildint 93160383Snetchildmain(argc, argv) 94160383Snetchild int argc; 95160383Snetchild char *argv[]; 96160383Snetchild{ 97160383Snetchild register struct cmd *c; 98160383Snetchild 99160383Snetchild euid = geteuid(); 100160383Snetchild uid = getuid(); 101160383Snetchild seteuid(uid); 102160383Snetchild name = argv[0]; 103160383Snetchild openlog("lpd", 0, LOG_LPR); 104160383Snetchild 105160383Snetchild if (--argc > 0) { 106160383Snetchild c = getcmd(*++argv); 107160383Snetchild if (c == (struct cmd *)-1) { 108160383Snetchild printf("?Ambiguous command\n"); 109160383Snetchild exit(1); 110160383Snetchild } 111160383Snetchild if (c == 0) { 112172150Sariff printf("?Invalid command\n"); 113172150Sariff exit(1); 114172150Sariff } 115160383Snetchild if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 116160383Snetchild printf("?Privileged command\n"); 117160383Snetchild exit(1); 118160383Snetchild } 119160383Snetchild if (c->c_generic != 0) 120160383Snetchild generic(c->c_generic, argc, argv); 121160383Snetchild else 122160383Snetchild (*c->c_handler)(argc, argv); 123160383Snetchild exit(0); 124160383Snetchild } 125160383Snetchild fromatty = isatty(fileno(stdin)); 126160383Snetchild if (!fromatty) 127160383Snetchild signal(SIGINT, intr); 128160383Snetchild for (;;) { 129160383Snetchild cmdscanner(); 130160383Snetchild } 131160383Snetchild} 132160383Snetchild 133160383Snetchildstatic void 134160383Snetchildintr(signo) 135160383Snetchild int signo; 136160383Snetchild{ 137160383Snetchild exit(0); 138160383Snetchild} 139160383Snetchild 140160383Snetchildstatic char * 141160383Snetchildlpc_prompt() 142160383Snetchild{ 143160383Snetchild return("lpc> "); 144160383Snetchild} 145160383Snetchild 146160383Snetchild/* 147160383Snetchild * Command parser. 148160383Snetchild */ 149160383Snetchildstatic void 150160383Snetchildcmdscanner() 151160383Snetchild{ 152160383Snetchild register struct cmd *c; 153160383Snetchild static EditLine *el = NULL; 154160383Snetchild static History *hist = NULL; 155160383Snetchild int num = 0; 156160383Snetchild const char *bp = NULL; 157160383Snetchild 158160383Snetchild for (;;) { 159160383Snetchild if (fromatty) { 160165833Snetchild if (!el) { 161230137Sjoel el = el_init("lpc", stdin, stdout); 162160383Snetchild hist = history_init(); 163160383Snetchild history(hist, H_EVENT, 100); 164160383Snetchild el_set(el, EL_HIST, history, hist); 165160383Snetchild el_set(el, EL_EDITOR, "emacs"); 166160383Snetchild el_set(el, EL_PROMPT, lpc_prompt); 167160383Snetchild el_set(el, EL_SIGNAL, 1); 168160383Snetchild } 169160383Snetchild if ((bp = el_gets(el, &num)) == NULL || num == 0) 170160383Snetchild return; 171160383Snetchild 172160383Snetchild memcpy(cmdline, bp, (MAX_CMDLINE > num ? MAX_CMDLINE : num)); 173160383Snetchild cmdline[num] = 0; 174160383Snetchild history(hist, H_ENTER, bp); 175160383Snetchild 176160383Snetchild } else { 177160383Snetchild if (fgets(cmdline, MAX_CMDLINE, stdin) == 0) 178160383Snetchild quit(0, NULL); 179160383Snetchild if (cmdline[0] == 0 || cmdline[0] == '\n') 180160383Snetchild break; 181160383Snetchild } 182160383Snetchild 183160383Snetchild makeargv(); 184160383Snetchild if (margc == 0) 185229981Spfg continue; 186160383Snetchild if (el_parse(el, margc, margv) != -1) 187160383Snetchild continue; 188160383Snetchild 189160383Snetchild c = getcmd(margv[0]); 190160383Snetchild if (c == (struct cmd *)-1) { 191160383Snetchild printf("?Ambiguous command\n"); 192160383Snetchild continue; 193160383Snetchild } 194160383Snetchild if (c == 0) { 195160383Snetchild printf("?Invalid command\n"); 196160383Snetchild continue; 197160383Snetchild } 198160383Snetchild if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 199160383Snetchild printf("?Privileged command\n"); 200160383Snetchild continue; 201160383Snetchild } 202160383Snetchild if (c->c_generic != 0) 203160383Snetchild generic(c->c_generic, margc, margv); 204160383Snetchild else 205160383Snetchild (*c->c_handler)(margc, margv); 206160383Snetchild } 207160383Snetchild} 208160383Snetchild 209160383Snetchildstatic struct cmd * 210160383Snetchildgetcmd(name) 211160383Snetchild register char *name; 212160383Snetchild{ 213160383Snetchild register char *p, *q; 214160383Snetchild register struct cmd *c, *found; 215160383Snetchild register int nmatches, longest; 216160383Snetchild 217160383Snetchild longest = 0; 218160383Snetchild nmatches = 0; 219160383Snetchild found = 0; 220160383Snetchild for (c = cmdtab; (p = c->c_name); c++) { 221229981Spfg for (q = name; *q == *p++; q++) 222229981Spfg if (*q == 0) /* exact match? */ 223229981Spfg return(c); 224229981Spfg if (!*q) { /* the name was a prefix */ 225229981Spfg if (q - name > longest) { 226160383Snetchild longest = q - name; 227229981Spfg nmatches = 1; 228229981Spfg found = c; 229229981Spfg } else if (q - name == longest) 230229981Spfg nmatches++; 231229981Spfg } 232229981Spfg } 233229981Spfg if (nmatches > 1) 234229981Spfg return((struct cmd *)-1); 235160383Snetchild return(found); 236160383Snetchild} 237160383Snetchild 238160383Snetchild/* 239160383Snetchild * Slice a string up into argc/argv. 240160383Snetchild */ 241160383Snetchildstatic void 242160383Snetchildmakeargv() 243160383Snetchild{ 244160383Snetchild register char *cp; 245160383Snetchild register char **argp = margv; 246160383Snetchild register int n = 0; 247172150Sariff 248172150Sariff margc = 0; 249172150Sariff for (cp = cmdline; *cp && (cp - cmdline) < sizeof(cmdline) && 250165833Snetchild n < MAX_MARGV; n++) { 251160383Snetchild while (isspace(*cp)) 252160383Snetchild cp++; 253160383Snetchild if (*cp == '\0') 254160383Snetchild break; 255160383Snetchild *argp++ = cp; 256161055Snetchild margc += 1; 257160383Snetchild while (*cp != '\0' && !isspace(*cp)) 258160383Snetchild cp++; 259160383Snetchild if (*cp == '\0') 260160383Snetchild break; 261160383Snetchild *cp++ = '\0'; 262160383Snetchild } 263160383Snetchild *argp++ = 0; 264160383Snetchild} 265160383Snetchild 266172150Sariff#define HELPINDENT (sizeof ("directory")) 267172150Sariff 268160383Snetchild/* 269160383Snetchild * Help command. 270160383Snetchild */ 271160383Snetchildvoid 272160383Snetchildhelp(argc, argv) 273160383Snetchild int argc; 274160383Snetchild char *argv[]; 275160383Snetchild{ 276160383Snetchild register struct cmd *c; 277160383Snetchild 278160383Snetchild if (argc == 1) { 279161054Snetchild register int i, j, w; 280160383Snetchild int columns, width = 0, lines; 281160383Snetchild 282160383Snetchild printf("Commands may be abbreviated. Commands are:\n\n"); 283160383Snetchild for (c = cmdtab; c->c_name; c++) { 284160383Snetchild int len = strlen(c->c_name); 285172150Sariff 286160383Snetchild if (len > width) 287160383Snetchild width = len; 288160383Snetchild } 289160383Snetchild width = (width + 8) &~ 7; 290160383Snetchild columns = 80 / width; 291160383Snetchild if (columns == 0) 292160383Snetchild columns = 1; 293160383Snetchild lines = (NCMDS + columns - 1) / columns; 294160383Snetchild for (i = 0; i < lines; i++) { 295160383Snetchild for (j = 0; j < columns; j++) { 296160383Snetchild c = cmdtab + j * lines + i; 297160383Snetchild if (c->c_name) 298160383Snetchild printf("%s", c->c_name); 299160383Snetchild if (c + lines >= &cmdtab[NCMDS]) { 300160383Snetchild printf("\n"); 301160383Snetchild break; 302160383Snetchild } 303160383Snetchild w = strlen(c->c_name); 304160383Snetchild while (w < width) { 305160383Snetchild w = (w + 8) &~ 7; 306160383Snetchild putchar('\t'); 307160383Snetchild } 308160383Snetchild } 309160383Snetchild } 310160383Snetchild return; 311160383Snetchild } 312165833Snetchild while (--argc > 0) { 313160383Snetchild register char *arg; 314160383Snetchild arg = *++argv; 315160383Snetchild c = getcmd(arg); 316160383Snetchild if (c == (struct cmd *)-1) 317160383Snetchild printf("?Ambiguous help command %s\n", arg); 318160383Snetchild else if (c == (struct cmd *)0) 319160383Snetchild printf("?Invalid help command %s\n", arg); 320160383Snetchild else 321160383Snetchild printf("%-*s\t%s\n", (int) HELPINDENT, 322160383Snetchild c->c_name, c->c_help); 323160383Snetchild } 324160383Snetchild} 325160383Snetchild 326160383Snetchild/* 327160383Snetchild * return non-zero if the user is a member of the given group 328160383Snetchild */ 329160383Snetchildstatic int 330160383Snetchildingroup(grname) 331160383Snetchild char *grname; 332160383Snetchild{ 333160383Snetchild static struct group *gptr=NULL; 334160383Snetchild static gid_t groups[NGROUPS]; 335160383Snetchild register gid_t gid; 336172150Sariff register int i; 337160383Snetchild 338160383Snetchild if (gptr == NULL) { 339160383Snetchild if ((gptr = getgrnam(grname)) == NULL) { 340160383Snetchild warnx("warning: unknown group '%s'", grname); 341160383Snetchild return(0); 342160383Snetchild } 343160383Snetchild if (getgroups(NGROUPS, groups) < 0) 344160383Snetchild err(1, "getgroups"); 345160383Snetchild } 346160383Snetchild gid = gptr->gr_gid; 347160383Snetchild for (i = 0; i < NGROUPS; i++) 348160383Snetchild if (gid == groups[i]) 349160383Snetchild return(1); 350160383Snetchild return(0); 351172150Sariff} 352160383Snetchild