xref: /csrg-svn/usr.sbin/lpr/lpc/lpc.c (revision 56121)
122428Sdist /*
222428Sdist  * Copyright (c) 1983 Regents of the University of California.
334203Sbostic  * All rights reserved.
434203Sbostic  *
5*56121Selan  * Redistribution and use in source and binary forms, with or without
6*56121Selan  * modification, are permitted provided that the following conditions
7*56121Selan  * are met:
8*56121Selan  * 1. Redistributions of source code must retain the above copyright
9*56121Selan  *    notice, this list of conditions and the following disclaimer.
10*56121Selan  * 2. Redistributions in binary form must reproduce the above copyright
11*56121Selan  *    notice, this list of conditions and the following disclaimer in the
12*56121Selan  *    documentation and/or other materials provided with the distribution.
13*56121Selan  * 3. All advertising materials mentioning features or use of this software
14*56121Selan  *    must display the following acknowledgement:
15*56121Selan  *	This product includes software developed by the University of
16*56121Selan  *	California, Berkeley and its contributors.
17*56121Selan  * 4. Neither the name of the University nor the names of its contributors
18*56121Selan  *    may be used to endorse or promote products derived from this software
19*56121Selan  *    without specific prior written permission.
20*56121Selan  *
21*56121Selan  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22*56121Selan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*56121Selan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*56121Selan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25*56121Selan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*56121Selan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*56121Selan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*56121Selan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*56121Selan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*56121Selan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*56121Selan  * SUCH DAMAGE.
3222428Sdist  */
3322428Sdist 
3412380Sralph #ifndef lint
3522428Sdist char copyright[] =
3622428Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
3722428Sdist  All rights reserved.\n";
3834203Sbostic #endif /* not lint */
3912380Sralph 
4022428Sdist #ifndef lint
41*56121Selan static char sccsid[] = "@(#)lpc.c	5.13 (Berkeley) 8/6/92";
4234203Sbostic #endif /* not lint */
4322428Sdist 
4455472Sbostic #include <sys/param.h>
4555472Sbostic 
4655472Sbostic #include <dirent.h>
4712380Sralph #include <signal.h>
4812380Sralph #include <setjmp.h>
4925494Seric #include <syslog.h>
5055472Sbostic #include <unistd.h>
5155472Sbostic #include <stdlib.h>
5255472Sbostic #include <stdio.h>
5355472Sbostic #include <ctype.h>
5455472Sbostic #include <string.h>
5555472Sbostic #include "lp.h"
5612380Sralph #include "lpc.h"
5755472Sbostic #include "extern.h"
5812380Sralph 
5955472Sbostic /*
6055472Sbostic  * lpc -- line printer control program
6155472Sbostic  */
6255472Sbostic 
6312380Sralph int	fromatty;
6412380Sralph 
6512380Sralph char	cmdline[200];
6612380Sralph int	margc;
6712380Sralph char	*margv[20];
6812380Sralph int	top;
6912380Sralph 
7012380Sralph jmp_buf	toplevel;
7112380Sralph 
7255472Sbostic static void		 cmdscanner __P((int));
7355472Sbostic static struct cmd	*getcmd __P((char *));
7455472Sbostic static void		 intr __P((int));
7555472Sbostic static void		 makeargv __P((void));
7655472Sbostic 
7755472Sbostic int
7812380Sralph main(argc, argv)
7955472Sbostic 	int argc;
8012380Sralph 	char *argv[];
8112380Sralph {
8212380Sralph 	register struct cmd *c;
8312380Sralph 
8412744Sralph 	name = argv[0];
8525494Seric 	openlog("lpd", 0, LOG_LPR);
8612744Sralph 
8712380Sralph 	if (--argc > 0) {
8812380Sralph 		c = getcmd(*++argv);
8912380Sralph 		if (c == (struct cmd *)-1) {
9012380Sralph 			printf("?Ambiguous command\n");
9112380Sralph 			exit(1);
9212380Sralph 		}
9312380Sralph 		if (c == 0) {
9412380Sralph 			printf("?Invalid command\n");
9512380Sralph 			exit(1);
9612380Sralph 		}
9712380Sralph 		if (c->c_priv && getuid()) {
9812380Sralph 			printf("?Privileged command\n");
9912380Sralph 			exit(1);
10012380Sralph 		}
10112380Sralph 		(*c->c_handler)(argc, argv);
10212380Sralph 		exit(0);
10312380Sralph 	}
10412380Sralph 	fromatty = isatty(fileno(stdin));
10512380Sralph 	top = setjmp(toplevel) == 0;
10612380Sralph 	if (top)
10713147Ssam 		signal(SIGINT, intr);
10812380Sralph 	for (;;) {
10912380Sralph 		cmdscanner(top);
11012380Sralph 		top = 1;
11112380Sralph 	}
11212380Sralph }
11312380Sralph 
11455472Sbostic static void
11555472Sbostic intr(signo)
11655472Sbostic 	int signo;
11712380Sralph {
11812380Sralph 	if (!fromatty)
11912380Sralph 		exit(0);
12012380Sralph 	longjmp(toplevel, 1);
12112380Sralph }
12212380Sralph 
12312380Sralph /*
12412380Sralph  * Command parser.
12512380Sralph  */
12655472Sbostic static void
12712380Sralph cmdscanner(top)
12812380Sralph 	int top;
12912380Sralph {
13012380Sralph 	register struct cmd *c;
13112380Sralph 
13212380Sralph 	if (!top)
13312380Sralph 		putchar('\n');
13412380Sralph 	for (;;) {
13512380Sralph 		if (fromatty) {
13612380Sralph 			printf("lpc> ");
13712380Sralph 			fflush(stdout);
13812380Sralph 		}
13936247Sbostic 		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
14055472Sbostic 			quit(0, NULL);
14140549Stef 		if (cmdline[0] == 0 || cmdline[0] == '\n')
14212380Sralph 			break;
14312380Sralph 		makeargv();
14412380Sralph 		c = getcmd(margv[0]);
14512380Sralph 		if (c == (struct cmd *)-1) {
14612380Sralph 			printf("?Ambiguous command\n");
14712380Sralph 			continue;
14812380Sralph 		}
14912380Sralph 		if (c == 0) {
15012380Sralph 			printf("?Invalid command\n");
15112380Sralph 			continue;
15212380Sralph 		}
15312380Sralph 		if (c->c_priv && getuid()) {
15412380Sralph 			printf("?Privileged command\n");
15512380Sralph 			continue;
15612380Sralph 		}
15712380Sralph 		(*c->c_handler)(margc, margv);
15812380Sralph 	}
15912380Sralph 	longjmp(toplevel, 0);
16012380Sralph }
16112380Sralph 
16212380Sralph struct cmd *
16312380Sralph getcmd(name)
16412380Sralph 	register char *name;
16512380Sralph {
16612380Sralph 	register char *p, *q;
16712380Sralph 	register struct cmd *c, *found;
16812380Sralph 	register int nmatches, longest;
16912380Sralph 
17012380Sralph 	longest = 0;
17112380Sralph 	nmatches = 0;
17212380Sralph 	found = 0;
17312380Sralph 	for (c = cmdtab; p = c->c_name; c++) {
17412380Sralph 		for (q = name; *q == *p++; q++)
17512380Sralph 			if (*q == 0)		/* exact match? */
17612380Sralph 				return(c);
17712380Sralph 		if (!*q) {			/* the name was a prefix */
17812380Sralph 			if (q - name > longest) {
17912380Sralph 				longest = q - name;
18012380Sralph 				nmatches = 1;
18112380Sralph 				found = c;
18212380Sralph 			} else if (q - name == longest)
18312380Sralph 				nmatches++;
18412380Sralph 		}
18512380Sralph 	}
18612380Sralph 	if (nmatches > 1)
18712380Sralph 		return((struct cmd *)-1);
18812380Sralph 	return(found);
18912380Sralph }
19012380Sralph 
19112380Sralph /*
19212380Sralph  * Slice a string up into argc/argv.
19312380Sralph  */
19455472Sbostic static void
19512380Sralph makeargv()
19612380Sralph {
19712380Sralph 	register char *cp;
19812380Sralph 	register char **argp = margv;
19912380Sralph 
20012380Sralph 	margc = 0;
20112380Sralph 	for (cp = cmdline; *cp;) {
20212380Sralph 		while (isspace(*cp))
20312380Sralph 			cp++;
20412380Sralph 		if (*cp == '\0')
20512380Sralph 			break;
20612380Sralph 		*argp++ = cp;
20712380Sralph 		margc += 1;
20812380Sralph 		while (*cp != '\0' && !isspace(*cp))
20912380Sralph 			cp++;
21012380Sralph 		if (*cp == '\0')
21112380Sralph 			break;
21212380Sralph 		*cp++ = '\0';
21312380Sralph 	}
21412380Sralph 	*argp++ = 0;
21512380Sralph }
21612380Sralph 
21712380Sralph #define HELPINDENT (sizeof ("directory"))
21812380Sralph 
21912380Sralph /*
22012380Sralph  * Help command.
22112380Sralph  */
22255472Sbostic void
22312380Sralph help(argc, argv)
22412380Sralph 	int argc;
22512380Sralph 	char *argv[];
22612380Sralph {
22712380Sralph 	register struct cmd *c;
22812380Sralph 
22912380Sralph 	if (argc == 1) {
23012380Sralph 		register int i, j, w;
23112380Sralph 		int columns, width = 0, lines;
23212380Sralph 		extern int NCMDS;
23312380Sralph 
23412380Sralph 		printf("Commands may be abbreviated.  Commands are:\n\n");
23539727Sbostic 		for (c = cmdtab; c->c_name; c++) {
23612380Sralph 			int len = strlen(c->c_name);
23712380Sralph 
23812380Sralph 			if (len > width)
23912380Sralph 				width = len;
24012380Sralph 		}
24112380Sralph 		width = (width + 8) &~ 7;
24212380Sralph 		columns = 80 / width;
24312380Sralph 		if (columns == 0)
24412380Sralph 			columns = 1;
24512380Sralph 		lines = (NCMDS + columns - 1) / columns;
24612380Sralph 		for (i = 0; i < lines; i++) {
24712380Sralph 			for (j = 0; j < columns; j++) {
24812380Sralph 				c = cmdtab + j * lines + i;
24939727Sbostic 				if (c->c_name)
25039727Sbostic 					printf("%s", c->c_name);
25112380Sralph 				if (c + lines >= &cmdtab[NCMDS]) {
25212380Sralph 					printf("\n");
25312380Sralph 					break;
25412380Sralph 				}
25512380Sralph 				w = strlen(c->c_name);
25612380Sralph 				while (w < width) {
25712380Sralph 					w = (w + 8) &~ 7;
25812380Sralph 					putchar('\t');
25912380Sralph 				}
26012380Sralph 			}
26112380Sralph 		}
26212380Sralph 		return;
26312380Sralph 	}
26412380Sralph 	while (--argc > 0) {
26512380Sralph 		register char *arg;
26612380Sralph 		arg = *++argv;
26712380Sralph 		c = getcmd(arg);
26812380Sralph 		if (c == (struct cmd *)-1)
26912380Sralph 			printf("?Ambiguous help command %s\n", arg);
27012380Sralph 		else if (c == (struct cmd *)0)
27112380Sralph 			printf("?Invalid help command %s\n", arg);
27212380Sralph 		else
27312380Sralph 			printf("%-*s\t%s\n", HELPINDENT,
27412380Sralph 				c->c_name, c->c_help);
27512380Sralph 	}
27612380Sralph }
277