lpc.c revision 62294
11553Srgrimes/* 21553Srgrimes * Copyright (c) 1983, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * 61553Srgrimes * Redistribution and use in source and binary forms, with or without 71553Srgrimes * modification, are permitted provided that the following conditions 81553Srgrimes * are met: 91553Srgrimes * 1. Redistributions of source code must retain the above copyright 101553Srgrimes * notice, this list of conditions and the following disclaimer. 111553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121553Srgrimes * notice, this list of conditions and the following disclaimer in the 131553Srgrimes * documentation and/or other materials provided with the distribution. 141553Srgrimes * 3. All advertising materials mentioning features or use of this software 151553Srgrimes * must display the following acknowledgement: 161553Srgrimes * This product includes software developed by the University of 171553Srgrimes * California, Berkeley and its contributors. 181553Srgrimes * 4. Neither the name of the University nor the names of its contributors 191553Srgrimes * may be used to endorse or promote products derived from this software 201553Srgrimes * without specific prior written permission. 211553Srgrimes * 221553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321553Srgrimes * SUCH DAMAGE. 331553Srgrimes */ 341553Srgrimes 351553Srgrimes#ifndef lint 3629780Scharnierstatic const char copyright[] = 371553Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 381553Srgrimes The Regents of the University of California. All rights reserved.\n"; 391553Srgrimes#endif /* not lint */ 401553Srgrimes 411553Srgrimes#ifndef lint 4229780Scharnier#if 0 4315637Sjoergstatic char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95"; 4429780Scharnier#endif 4529780Scharnierstatic const char rcsid[] = 4650479Speter "$FreeBSD: head/usr.sbin/lpr/lpc/lpc.c 62294 2000-06-30 20:05:21Z mph $"; 471553Srgrimes#endif /* not lint */ 481553Srgrimes 491553Srgrimes#include <sys/param.h> 501553Srgrimes 5129780Scharnier#include <ctype.h> 521553Srgrimes#include <dirent.h> 5331492Swollman#include <err.h> 5429780Scharnier#include <grp.h> 5529780Scharnier#include <setjmp.h> 561553Srgrimes#include <signal.h> 5729780Scharnier#include <stdio.h> 5829780Scharnier#include <stdlib.h> 591553Srgrimes#include <syslog.h> 6029780Scharnier#include <string.h> 611553Srgrimes#include <unistd.h> 6250039Smdodd#include <histedit.h> 6331492Swollman 641553Srgrimes#include "lp.h" 651553Srgrimes#include "lpc.h" 661553Srgrimes#include "extern.h" 671553Srgrimes 6815637Sjoerg#ifndef LPR_OPER 6915637Sjoerg#define LPR_OPER "operator" /* group name of lpr operators */ 7015637Sjoerg#endif 7115637Sjoerg 721553Srgrimes/* 731553Srgrimes * lpc -- line printer control program 741553Srgrimes */ 751553Srgrimes 7627618Simp#define MAX_CMDLINE 200 7727618Simp#define MAX_MARGV 20 7839084Swollmanstatic int fromatty; 791553Srgrimes 8039084Swollmanstatic char cmdline[MAX_CMDLINE]; 8139084Swollmanstatic int margc; 8239084Swollmanstatic char *margv[MAX_MARGV]; 8339084Swollmanuid_t uid, euid; 841553Srgrimes 8539084Swollmanint main __P((int, char *[])); 8650039Smdoddstatic void cmdscanner __P((void)); 871553Srgrimesstatic struct cmd *getcmd __P((char *)); 881553Srgrimesstatic void intr __P((int)); 891553Srgrimesstatic void makeargv __P((void)); 9015637Sjoergstatic int ingroup __P((char *)); 911553Srgrimes 921553Srgrimesint 931553Srgrimesmain(argc, argv) 941553Srgrimes int argc; 951553Srgrimes char *argv[]; 961553Srgrimes{ 971553Srgrimes register struct cmd *c; 981553Srgrimes 9927618Simp euid = geteuid(); 10027618Simp uid = getuid(); 10127618Simp seteuid(uid); 1021553Srgrimes name = argv[0]; 1031553Srgrimes openlog("lpd", 0, LOG_LPR); 1041553Srgrimes 1051553Srgrimes if (--argc > 0) { 1061553Srgrimes c = getcmd(*++argv); 1071553Srgrimes if (c == (struct cmd *)-1) { 1081553Srgrimes printf("?Ambiguous command\n"); 1091553Srgrimes exit(1); 1101553Srgrimes } 1111553Srgrimes if (c == 0) { 1121553Srgrimes printf("?Invalid command\n"); 1131553Srgrimes exit(1); 1141553Srgrimes } 11515637Sjoerg if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 1161553Srgrimes printf("?Privileged command\n"); 1171553Srgrimes exit(1); 1181553Srgrimes } 11931492Swollman if (c->c_generic != 0) 12031492Swollman generic(c->c_generic, argc, argv); 12131492Swollman else 12231492Swollman (*c->c_handler)(argc, argv); 1231553Srgrimes exit(0); 1241553Srgrimes } 1251553Srgrimes fromatty = isatty(fileno(stdin)); 12650039Smdodd if (!fromatty) 1271553Srgrimes signal(SIGINT, intr); 1281553Srgrimes for (;;) { 12950039Smdodd cmdscanner(); 1301553Srgrimes } 1311553Srgrimes} 1321553Srgrimes 1331553Srgrimesstatic void 1341553Srgrimesintr(signo) 1351553Srgrimes int signo; 1361553Srgrimes{ 13750039Smdodd exit(0); 1381553Srgrimes} 1391553Srgrimes 14050039Smdoddstatic char * 14150039Smdoddlpc_prompt() 14250039Smdodd{ 14350039Smdodd return("lpc> "); 14450039Smdodd} 14550039Smdodd 1461553Srgrimes/* 1471553Srgrimes * Command parser. 1481553Srgrimes */ 1491553Srgrimesstatic void 15050039Smdoddcmdscanner() 1511553Srgrimes{ 1521553Srgrimes register struct cmd *c; 15350039Smdodd static EditLine *el = NULL; 15450039Smdodd static History *hist = NULL; 15550039Smdodd int num = 0; 15650071Smdodd int len; 15750039Smdodd const char *bp = NULL; 1581553Srgrimes 1591553Srgrimes for (;;) { 1601553Srgrimes if (fromatty) { 16150039Smdodd if (!el) { 16250039Smdodd el = el_init("lpc", stdin, stdout); 16350039Smdodd hist = history_init(); 16450039Smdodd history(hist, H_EVENT, 100); 16550039Smdodd el_set(el, EL_HIST, history, hist); 16650039Smdodd el_set(el, EL_EDITOR, "emacs"); 16750039Smdodd el_set(el, EL_PROMPT, lpc_prompt); 16850039Smdodd el_set(el, EL_SIGNAL, 1); 16950042Smdodd el_source(el, NULL); 17050039Smdodd } 17150039Smdodd if ((bp = el_gets(el, &num)) == NULL || num == 0) 17262294Smph quit(0, NULL); 17350039Smdodd 17450077Smdodd len = (num > MAX_CMDLINE) ? MAX_CMDLINE : num; 17550071Smdodd memcpy(cmdline, bp, len); 17650071Smdodd cmdline[len] = 0; 17750039Smdodd history(hist, H_ENTER, bp); 17850039Smdodd 17950039Smdodd } else { 18050039Smdodd if (fgets(cmdline, MAX_CMDLINE, stdin) == 0) 18150039Smdodd quit(0, NULL); 18250039Smdodd if (cmdline[0] == 0 || cmdline[0] == '\n') 18350039Smdodd break; 1841553Srgrimes } 18550039Smdodd 1861553Srgrimes makeargv(); 18750039Smdodd if (margc == 0) 18850039Smdodd continue; 18950039Smdodd if (el_parse(el, margc, margv) != -1) 19050039Smdodd continue; 19150039Smdodd 1921553Srgrimes c = getcmd(margv[0]); 1931553Srgrimes if (c == (struct cmd *)-1) { 1941553Srgrimes printf("?Ambiguous command\n"); 1951553Srgrimes continue; 1961553Srgrimes } 1971553Srgrimes if (c == 0) { 1981553Srgrimes printf("?Invalid command\n"); 1991553Srgrimes continue; 2001553Srgrimes } 20115637Sjoerg if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) { 2021553Srgrimes printf("?Privileged command\n"); 2031553Srgrimes continue; 2041553Srgrimes } 20531492Swollman if (c->c_generic != 0) 20631492Swollman generic(c->c_generic, margc, margv); 20731492Swollman else 20831492Swollman (*c->c_handler)(margc, margv); 2091553Srgrimes } 2101553Srgrimes} 2111553Srgrimes 21215637Sjoergstatic struct cmd * 2131553Srgrimesgetcmd(name) 2141553Srgrimes register char *name; 2151553Srgrimes{ 2161553Srgrimes register char *p, *q; 2171553Srgrimes register struct cmd *c, *found; 2181553Srgrimes register int nmatches, longest; 2191553Srgrimes 2201553Srgrimes longest = 0; 2211553Srgrimes nmatches = 0; 2221553Srgrimes found = 0; 22319202Simp for (c = cmdtab; (p = c->c_name); c++) { 2241553Srgrimes for (q = name; *q == *p++; q++) 2251553Srgrimes if (*q == 0) /* exact match? */ 2261553Srgrimes return(c); 2271553Srgrimes if (!*q) { /* the name was a prefix */ 2281553Srgrimes if (q - name > longest) { 2291553Srgrimes longest = q - name; 2301553Srgrimes nmatches = 1; 2311553Srgrimes found = c; 2321553Srgrimes } else if (q - name == longest) 2331553Srgrimes nmatches++; 2341553Srgrimes } 2351553Srgrimes } 2361553Srgrimes if (nmatches > 1) 2371553Srgrimes return((struct cmd *)-1); 2381553Srgrimes return(found); 2391553Srgrimes} 2401553Srgrimes 2411553Srgrimes/* 2421553Srgrimes * Slice a string up into argc/argv. 2431553Srgrimes */ 2441553Srgrimesstatic void 2451553Srgrimesmakeargv() 2461553Srgrimes{ 2471553Srgrimes register char *cp; 2481553Srgrimes register char **argp = margv; 24927618Simp register int n = 0; 2501553Srgrimes 2511553Srgrimes margc = 0; 25227618Simp for (cp = cmdline; *cp && (cp - cmdline) < sizeof(cmdline) && 25327618Simp n < MAX_MARGV; n++) { 2541553Srgrimes while (isspace(*cp)) 2551553Srgrimes cp++; 2561553Srgrimes if (*cp == '\0') 2571553Srgrimes break; 2581553Srgrimes *argp++ = cp; 2591553Srgrimes margc += 1; 2601553Srgrimes while (*cp != '\0' && !isspace(*cp)) 2611553Srgrimes cp++; 2621553Srgrimes if (*cp == '\0') 2631553Srgrimes break; 2641553Srgrimes *cp++ = '\0'; 2651553Srgrimes } 2661553Srgrimes *argp++ = 0; 2671553Srgrimes} 2681553Srgrimes 2691553Srgrimes#define HELPINDENT (sizeof ("directory")) 2701553Srgrimes 2711553Srgrimes/* 2721553Srgrimes * Help command. 2731553Srgrimes */ 2741553Srgrimesvoid 2751553Srgrimeshelp(argc, argv) 2761553Srgrimes int argc; 2771553Srgrimes char *argv[]; 2781553Srgrimes{ 2791553Srgrimes register struct cmd *c; 2801553Srgrimes 2811553Srgrimes if (argc == 1) { 2821553Srgrimes register int i, j, w; 2831553Srgrimes int columns, width = 0, lines; 2841553Srgrimes 2851553Srgrimes printf("Commands may be abbreviated. Commands are:\n\n"); 2861553Srgrimes for (c = cmdtab; c->c_name; c++) { 2871553Srgrimes int len = strlen(c->c_name); 2881553Srgrimes 2891553Srgrimes if (len > width) 2901553Srgrimes width = len; 2911553Srgrimes } 2921553Srgrimes width = (width + 8) &~ 7; 2931553Srgrimes columns = 80 / width; 2941553Srgrimes if (columns == 0) 2951553Srgrimes columns = 1; 2961553Srgrimes lines = (NCMDS + columns - 1) / columns; 2971553Srgrimes for (i = 0; i < lines; i++) { 2981553Srgrimes for (j = 0; j < columns; j++) { 2991553Srgrimes c = cmdtab + j * lines + i; 3001553Srgrimes if (c->c_name) 3011553Srgrimes printf("%s", c->c_name); 3021553Srgrimes if (c + lines >= &cmdtab[NCMDS]) { 3031553Srgrimes printf("\n"); 3041553Srgrimes break; 3051553Srgrimes } 3061553Srgrimes w = strlen(c->c_name); 3071553Srgrimes while (w < width) { 3081553Srgrimes w = (w + 8) &~ 7; 3091553Srgrimes putchar('\t'); 3101553Srgrimes } 3111553Srgrimes } 3121553Srgrimes } 3131553Srgrimes return; 3141553Srgrimes } 3151553Srgrimes while (--argc > 0) { 3161553Srgrimes register char *arg; 3171553Srgrimes arg = *++argv; 3181553Srgrimes c = getcmd(arg); 3191553Srgrimes if (c == (struct cmd *)-1) 3201553Srgrimes printf("?Ambiguous help command %s\n", arg); 3211553Srgrimes else if (c == (struct cmd *)0) 3221553Srgrimes printf("?Invalid help command %s\n", arg); 3231553Srgrimes else 32434784Sjb printf("%-*s\t%s\n", (int) HELPINDENT, 3251553Srgrimes c->c_name, c->c_help); 3261553Srgrimes } 3271553Srgrimes} 32815637Sjoerg 32915637Sjoerg/* 33015637Sjoerg * return non-zero if the user is a member of the given group 33115637Sjoerg */ 33215637Sjoergstatic int 33315637Sjoergingroup(grname) 33415637Sjoerg char *grname; 33515637Sjoerg{ 33615637Sjoerg static struct group *gptr=NULL; 33715637Sjoerg static gid_t groups[NGROUPS]; 33815637Sjoerg register gid_t gid; 33915637Sjoerg register int i; 34015637Sjoerg 34115637Sjoerg if (gptr == NULL) { 34215637Sjoerg if ((gptr = getgrnam(grname)) == NULL) { 34329780Scharnier warnx("warning: unknown group '%s'", grname); 34415637Sjoerg return(0); 34515637Sjoerg } 34629780Scharnier if (getgroups(NGROUPS, groups) < 0) 34729780Scharnier err(1, "getgroups"); 34815637Sjoerg } 34915637Sjoerg gid = gptr->gr_gid; 35015637Sjoerg for (i = 0; i < NGROUPS; i++) 35115637Sjoerg if (gid == groups[i]) 35215637Sjoerg return(1); 35315637Sjoerg return(0); 35415637Sjoerg} 355