xref: /csrg-svn/usr.sbin/lpr/lpc/lpc.c (revision 69027)
122428Sdist /*
261843Sbostic  * Copyright (c) 1983, 1993
361843Sbostic  *	The Regents of the University of California.  All rights reserved.
434203Sbostic  *
556121Selan  *
656250Selan  * %sccs.include.redist.c%
722428Sdist  */
822428Sdist 
912380Sralph #ifndef lint
1056264Selan static char copyright[] =
1161843Sbostic "@(#) Copyright (c) 1983, 1993\n\
1261843Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1334203Sbostic #endif /* not lint */
1412380Sralph 
1522428Sdist #ifndef lint
16*69027Stef static char sccsid[] = "@(#)lpc.c	8.2 (Berkeley) 04/28/95";
1734203Sbostic #endif /* not lint */
1822428Sdist 
1955472Sbostic #include <sys/param.h>
2055472Sbostic 
2155472Sbostic #include <dirent.h>
2212380Sralph #include <signal.h>
2312380Sralph #include <setjmp.h>
2425494Seric #include <syslog.h>
2555472Sbostic #include <unistd.h>
2655472Sbostic #include <stdlib.h>
2755472Sbostic #include <stdio.h>
2855472Sbostic #include <ctype.h>
2955472Sbostic #include <string.h>
30*69027Stef #include "extern.h"
31*69027Stef #include <sys/param.h>
32*69027Stef #include <grp.h>
3355472Sbostic #include "lp.h"
3412380Sralph #include "lpc.h"
3555472Sbostic #include "extern.h"
3612380Sralph 
37*69027Stef #ifndef LPR_OPER
38*69027Stef #define LPR_OPER	"operator"	/* group name of lpr operators */
39*69027Stef #endif
40*69027Stef 
4155472Sbostic /*
4255472Sbostic  * lpc -- line printer control program
4355472Sbostic  */
4455472Sbostic 
4512380Sralph int	fromatty;
4612380Sralph 
4712380Sralph char	cmdline[200];
4812380Sralph int	margc;
4912380Sralph char	*margv[20];
5012380Sralph int	top;
5112380Sralph 
5212380Sralph jmp_buf	toplevel;
5312380Sralph 
5455472Sbostic static void		 cmdscanner __P((int));
5555472Sbostic static struct cmd	*getcmd __P((char *));
5655472Sbostic static void		 intr __P((int));
5755472Sbostic static void		 makeargv __P((void));
58*69027Stef static int		 ingroup __P((char *));
5955472Sbostic 
6055472Sbostic int
6112380Sralph main(argc, argv)
6255472Sbostic 	int argc;
6312380Sralph 	char *argv[];
6412380Sralph {
6512380Sralph 	register struct cmd *c;
6612380Sralph 
6712744Sralph 	name = argv[0];
6825494Seric 	openlog("lpd", 0, LOG_LPR);
6912744Sralph 
7012380Sralph 	if (--argc > 0) {
7112380Sralph 		c = getcmd(*++argv);
7212380Sralph 		if (c == (struct cmd *)-1) {
7312380Sralph 			printf("?Ambiguous command\n");
7412380Sralph 			exit(1);
7512380Sralph 		}
7612380Sralph 		if (c == 0) {
7712380Sralph 			printf("?Invalid command\n");
7812380Sralph 			exit(1);
7912380Sralph 		}
80*69027Stef 		if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
8112380Sralph 			printf("?Privileged command\n");
8212380Sralph 			exit(1);
8312380Sralph 		}
8412380Sralph 		(*c->c_handler)(argc, argv);
8512380Sralph 		exit(0);
8612380Sralph 	}
8712380Sralph 	fromatty = isatty(fileno(stdin));
8812380Sralph 	top = setjmp(toplevel) == 0;
8912380Sralph 	if (top)
9013147Ssam 		signal(SIGINT, intr);
9112380Sralph 	for (;;) {
9212380Sralph 		cmdscanner(top);
9312380Sralph 		top = 1;
9412380Sralph 	}
9512380Sralph }
9612380Sralph 
9755472Sbostic static void
9855472Sbostic intr(signo)
9955472Sbostic 	int signo;
10012380Sralph {
10112380Sralph 	if (!fromatty)
10212380Sralph 		exit(0);
10312380Sralph 	longjmp(toplevel, 1);
10412380Sralph }
10512380Sralph 
10612380Sralph /*
10712380Sralph  * Command parser.
10812380Sralph  */
10955472Sbostic static void
11012380Sralph cmdscanner(top)
11112380Sralph 	int top;
11212380Sralph {
11312380Sralph 	register struct cmd *c;
11412380Sralph 
11512380Sralph 	if (!top)
11612380Sralph 		putchar('\n');
11712380Sralph 	for (;;) {
11812380Sralph 		if (fromatty) {
11912380Sralph 			printf("lpc> ");
12012380Sralph 			fflush(stdout);
12112380Sralph 		}
12236247Sbostic 		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
12355472Sbostic 			quit(0, NULL);
12440549Stef 		if (cmdline[0] == 0 || cmdline[0] == '\n')
12512380Sralph 			break;
12612380Sralph 		makeargv();
12712380Sralph 		c = getcmd(margv[0]);
12812380Sralph 		if (c == (struct cmd *)-1) {
12912380Sralph 			printf("?Ambiguous command\n");
13012380Sralph 			continue;
13112380Sralph 		}
13212380Sralph 		if (c == 0) {
13312380Sralph 			printf("?Invalid command\n");
13412380Sralph 			continue;
13512380Sralph 		}
136*69027Stef 		if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
13712380Sralph 			printf("?Privileged command\n");
13812380Sralph 			continue;
13912380Sralph 		}
14012380Sralph 		(*c->c_handler)(margc, margv);
14112380Sralph 	}
14212380Sralph 	longjmp(toplevel, 0);
14312380Sralph }
14412380Sralph 
145*69027Stef static struct cmd *
14612380Sralph getcmd(name)
14712380Sralph 	register char *name;
14812380Sralph {
14912380Sralph 	register char *p, *q;
15012380Sralph 	register struct cmd *c, *found;
15112380Sralph 	register int nmatches, longest;
15212380Sralph 
15312380Sralph 	longest = 0;
15412380Sralph 	nmatches = 0;
15512380Sralph 	found = 0;
15612380Sralph 	for (c = cmdtab; p = c->c_name; c++) {
15712380Sralph 		for (q = name; *q == *p++; q++)
15812380Sralph 			if (*q == 0)		/* exact match? */
15912380Sralph 				return(c);
16012380Sralph 		if (!*q) {			/* the name was a prefix */
16112380Sralph 			if (q - name > longest) {
16212380Sralph 				longest = q - name;
16312380Sralph 				nmatches = 1;
16412380Sralph 				found = c;
16512380Sralph 			} else if (q - name == longest)
16612380Sralph 				nmatches++;
16712380Sralph 		}
16812380Sralph 	}
16912380Sralph 	if (nmatches > 1)
17012380Sralph 		return((struct cmd *)-1);
17112380Sralph 	return(found);
17212380Sralph }
17312380Sralph 
17412380Sralph /*
17512380Sralph  * Slice a string up into argc/argv.
17612380Sralph  */
17755472Sbostic static void
17812380Sralph makeargv()
17912380Sralph {
18012380Sralph 	register char *cp;
18112380Sralph 	register char **argp = margv;
18212380Sralph 
18312380Sralph 	margc = 0;
18412380Sralph 	for (cp = cmdline; *cp;) {
18512380Sralph 		while (isspace(*cp))
18612380Sralph 			cp++;
18712380Sralph 		if (*cp == '\0')
18812380Sralph 			break;
18912380Sralph 		*argp++ = cp;
19012380Sralph 		margc += 1;
19112380Sralph 		while (*cp != '\0' && !isspace(*cp))
19212380Sralph 			cp++;
19312380Sralph 		if (*cp == '\0')
19412380Sralph 			break;
19512380Sralph 		*cp++ = '\0';
19612380Sralph 	}
19712380Sralph 	*argp++ = 0;
19812380Sralph }
19912380Sralph 
20012380Sralph #define HELPINDENT (sizeof ("directory"))
20112380Sralph 
20212380Sralph /*
20312380Sralph  * Help command.
20412380Sralph  */
20555472Sbostic void
20612380Sralph help(argc, argv)
20712380Sralph 	int argc;
20812380Sralph 	char *argv[];
20912380Sralph {
21012380Sralph 	register struct cmd *c;
21112380Sralph 
21212380Sralph 	if (argc == 1) {
21312380Sralph 		register int i, j, w;
21412380Sralph 		int columns, width = 0, lines;
21512380Sralph 		extern int NCMDS;
21612380Sralph 
21712380Sralph 		printf("Commands may be abbreviated.  Commands are:\n\n");
21839727Sbostic 		for (c = cmdtab; c->c_name; c++) {
21912380Sralph 			int len = strlen(c->c_name);
22012380Sralph 
22112380Sralph 			if (len > width)
22212380Sralph 				width = len;
22312380Sralph 		}
22412380Sralph 		width = (width + 8) &~ 7;
22512380Sralph 		columns = 80 / width;
22612380Sralph 		if (columns == 0)
22712380Sralph 			columns = 1;
22812380Sralph 		lines = (NCMDS + columns - 1) / columns;
22912380Sralph 		for (i = 0; i < lines; i++) {
23012380Sralph 			for (j = 0; j < columns; j++) {
23112380Sralph 				c = cmdtab + j * lines + i;
23239727Sbostic 				if (c->c_name)
23339727Sbostic 					printf("%s", c->c_name);
23412380Sralph 				if (c + lines >= &cmdtab[NCMDS]) {
23512380Sralph 					printf("\n");
23612380Sralph 					break;
23712380Sralph 				}
23812380Sralph 				w = strlen(c->c_name);
23912380Sralph 				while (w < width) {
24012380Sralph 					w = (w + 8) &~ 7;
24112380Sralph 					putchar('\t');
24212380Sralph 				}
24312380Sralph 			}
24412380Sralph 		}
24512380Sralph 		return;
24612380Sralph 	}
24712380Sralph 	while (--argc > 0) {
24812380Sralph 		register char *arg;
24912380Sralph 		arg = *++argv;
25012380Sralph 		c = getcmd(arg);
25112380Sralph 		if (c == (struct cmd *)-1)
25212380Sralph 			printf("?Ambiguous help command %s\n", arg);
25312380Sralph 		else if (c == (struct cmd *)0)
25412380Sralph 			printf("?Invalid help command %s\n", arg);
25512380Sralph 		else
25612380Sralph 			printf("%-*s\t%s\n", HELPINDENT,
25712380Sralph 				c->c_name, c->c_help);
25812380Sralph 	}
25912380Sralph }
260*69027Stef 
261*69027Stef /*
262*69027Stef  * return non-zero if the user is a member of the given group
263*69027Stef  */
264*69027Stef static int
265*69027Stef ingroup(grname)
266*69027Stef 	char *grname;
267*69027Stef {
268*69027Stef 	static struct group *gptr=NULL;
269*69027Stef 	static gid_t groups[NGROUPS];
270*69027Stef 	register gid_t gid;
271*69027Stef 	register int i;
272*69027Stef 
273*69027Stef 	if (gptr == NULL) {
274*69027Stef 		if ((gptr = getgrnam(grname)) == NULL) {
275*69027Stef 			fprintf(stderr, "Warning: unknown group '%s'\n",
276*69027Stef 				grname);
277*69027Stef 			return(0);
278*69027Stef 		}
279*69027Stef 		if (getgroups(NGROUPS, groups) < 0) {
280*69027Stef 			perror("getgroups");
281*69027Stef 			exit(1);
282*69027Stef 		}
283*69027Stef 	}
284*69027Stef 	gid = gptr->gr_gid;
285*69027Stef 	for (i = 0; i < NGROUPS; i++)
286*69027Stef 		if (gid == groups[i])
287*69027Stef 			return(1);
288*69027Stef 	return(0);
289*69027Stef }
290