xref: /original-bsd/usr.sbin/lpr/lpc/lpc.c (revision 27393bdf)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char copyright[] =
11 "@(#) Copyright (c) 1983, 1993\n\
12 	The Regents of the University of California.  All rights reserved.\n";
13 #endif /* not lint */
14 
15 #ifndef lint
16 static char sccsid[] = "@(#)lpc.c	8.3 (Berkeley) 04/28/95";
17 #endif /* not lint */
18 
19 #include <sys/param.h>
20 
21 #include <dirent.h>
22 #include <signal.h>
23 #include <setjmp.h>
24 #include <syslog.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <grp.h>
31 #include <sys/param.h>
32 #include "lp.h"
33 #include "lpc.h"
34 #include "extern.h"
35 
36 #ifndef LPR_OPER
37 #define LPR_OPER	"operator"	/* group name of lpr operators */
38 #endif
39 
40 /*
41  * lpc -- line printer control program
42  */
43 
44 int	fromatty;
45 
46 char	cmdline[200];
47 int	margc;
48 char	*margv[20];
49 int	top;
50 
51 jmp_buf	toplevel;
52 
53 static void		 cmdscanner __P((int));
54 static struct cmd	*getcmd __P((char *));
55 static void		 intr __P((int));
56 static void		 makeargv __P((void));
57 static int		 ingroup __P((char *));
58 
59 int
60 main(argc, argv)
61 	int argc;
62 	char *argv[];
63 {
64 	register struct cmd *c;
65 
66 	name = argv[0];
67 	openlog("lpd", 0, LOG_LPR);
68 
69 	if (--argc > 0) {
70 		c = getcmd(*++argv);
71 		if (c == (struct cmd *)-1) {
72 			printf("?Ambiguous command\n");
73 			exit(1);
74 		}
75 		if (c == 0) {
76 			printf("?Invalid command\n");
77 			exit(1);
78 		}
79 		if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
80 			printf("?Privileged command\n");
81 			exit(1);
82 		}
83 		(*c->c_handler)(argc, argv);
84 		exit(0);
85 	}
86 	fromatty = isatty(fileno(stdin));
87 	top = setjmp(toplevel) == 0;
88 	if (top)
89 		signal(SIGINT, intr);
90 	for (;;) {
91 		cmdscanner(top);
92 		top = 1;
93 	}
94 }
95 
96 static void
97 intr(signo)
98 	int signo;
99 {
100 	if (!fromatty)
101 		exit(0);
102 	longjmp(toplevel, 1);
103 }
104 
105 /*
106  * Command parser.
107  */
108 static void
109 cmdscanner(top)
110 	int top;
111 {
112 	register struct cmd *c;
113 
114 	if (!top)
115 		putchar('\n');
116 	for (;;) {
117 		if (fromatty) {
118 			printf("lpc> ");
119 			fflush(stdout);
120 		}
121 		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
122 			quit(0, NULL);
123 		if (cmdline[0] == 0 || cmdline[0] == '\n')
124 			break;
125 		makeargv();
126 		c = getcmd(margv[0]);
127 		if (c == (struct cmd *)-1) {
128 			printf("?Ambiguous command\n");
129 			continue;
130 		}
131 		if (c == 0) {
132 			printf("?Invalid command\n");
133 			continue;
134 		}
135 		if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
136 			printf("?Privileged command\n");
137 			continue;
138 		}
139 		(*c->c_handler)(margc, margv);
140 	}
141 	longjmp(toplevel, 0);
142 }
143 
144 static struct cmd *
145 getcmd(name)
146 	register char *name;
147 {
148 	register char *p, *q;
149 	register struct cmd *c, *found;
150 	register int nmatches, longest;
151 
152 	longest = 0;
153 	nmatches = 0;
154 	found = 0;
155 	for (c = cmdtab; p = c->c_name; c++) {
156 		for (q = name; *q == *p++; q++)
157 			if (*q == 0)		/* exact match? */
158 				return(c);
159 		if (!*q) {			/* the name was a prefix */
160 			if (q - name > longest) {
161 				longest = q - name;
162 				nmatches = 1;
163 				found = c;
164 			} else if (q - name == longest)
165 				nmatches++;
166 		}
167 	}
168 	if (nmatches > 1)
169 		return((struct cmd *)-1);
170 	return(found);
171 }
172 
173 /*
174  * Slice a string up into argc/argv.
175  */
176 static void
177 makeargv()
178 {
179 	register char *cp;
180 	register char **argp = margv;
181 
182 	margc = 0;
183 	for (cp = cmdline; *cp;) {
184 		while (isspace(*cp))
185 			cp++;
186 		if (*cp == '\0')
187 			break;
188 		*argp++ = cp;
189 		margc += 1;
190 		while (*cp != '\0' && !isspace(*cp))
191 			cp++;
192 		if (*cp == '\0')
193 			break;
194 		*cp++ = '\0';
195 	}
196 	*argp++ = 0;
197 }
198 
199 #define HELPINDENT (sizeof ("directory"))
200 
201 /*
202  * Help command.
203  */
204 void
205 help(argc, argv)
206 	int argc;
207 	char *argv[];
208 {
209 	register struct cmd *c;
210 
211 	if (argc == 1) {
212 		register int i, j, w;
213 		int columns, width = 0, lines;
214 		extern int NCMDS;
215 
216 		printf("Commands may be abbreviated.  Commands are:\n\n");
217 		for (c = cmdtab; c->c_name; c++) {
218 			int len = strlen(c->c_name);
219 
220 			if (len > width)
221 				width = len;
222 		}
223 		width = (width + 8) &~ 7;
224 		columns = 80 / width;
225 		if (columns == 0)
226 			columns = 1;
227 		lines = (NCMDS + columns - 1) / columns;
228 		for (i = 0; i < lines; i++) {
229 			for (j = 0; j < columns; j++) {
230 				c = cmdtab + j * lines + i;
231 				if (c->c_name)
232 					printf("%s", c->c_name);
233 				if (c + lines >= &cmdtab[NCMDS]) {
234 					printf("\n");
235 					break;
236 				}
237 				w = strlen(c->c_name);
238 				while (w < width) {
239 					w = (w + 8) &~ 7;
240 					putchar('\t');
241 				}
242 			}
243 		}
244 		return;
245 	}
246 	while (--argc > 0) {
247 		register char *arg;
248 		arg = *++argv;
249 		c = getcmd(arg);
250 		if (c == (struct cmd *)-1)
251 			printf("?Ambiguous help command %s\n", arg);
252 		else if (c == (struct cmd *)0)
253 			printf("?Invalid help command %s\n", arg);
254 		else
255 			printf("%-*s\t%s\n", HELPINDENT,
256 				c->c_name, c->c_help);
257 	}
258 }
259 
260 /*
261  * return non-zero if the user is a member of the given group
262  */
263 static int
264 ingroup(grname)
265 	char *grname;
266 {
267 	static struct group *gptr=NULL;
268 	static gid_t groups[NGROUPS];
269 	register gid_t gid;
270 	register int i;
271 
272 	if (gptr == NULL) {
273 		if ((gptr = getgrnam(grname)) == NULL) {
274 			fprintf(stderr, "Warning: unknown group '%s'\n",
275 				grname);
276 			return(0);
277 		}
278 		if (getgroups(NGROUPS, groups) < 0) {
279 			perror("getgroups");
280 			exit(1);
281 		}
282 	}
283 	gid = gptr->gr_gid;
284 	for (i = 0; i < NGROUPS; i++)
285 		if (gid == groups[i])
286 			return(1);
287 	return(0);
288 }
289