xref: /csrg-svn/usr.sbin/lpr/lpc/lpc.c (revision 39727)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)lpc.c	5.8 (Berkeley) 12/18/89";
26 #endif /* not lint */
27 
28 /*
29  * lpc -- line printer control program
30  */
31 #include <stdio.h>
32 #include <signal.h>
33 #include <ctype.h>
34 #include <setjmp.h>
35 #include <syslog.h>
36 
37 #include "lpc.h"
38 
39 int	fromatty;
40 
41 char	cmdline[200];
42 int	margc;
43 char	*margv[20];
44 int	top;
45 int	intr();
46 struct	cmd *getcmd();
47 
48 jmp_buf	toplevel;
49 
50 main(argc, argv)
51 	char *argv[];
52 {
53 	register struct cmd *c;
54 	extern char *name;
55 
56 	name = argv[0];
57 	openlog("lpd", 0, LOG_LPR);
58 
59 	if (--argc > 0) {
60 		c = getcmd(*++argv);
61 		if (c == (struct cmd *)-1) {
62 			printf("?Ambiguous command\n");
63 			exit(1);
64 		}
65 		if (c == 0) {
66 			printf("?Invalid command\n");
67 			exit(1);
68 		}
69 		if (c->c_priv && getuid()) {
70 			printf("?Privileged command\n");
71 			exit(1);
72 		}
73 		(*c->c_handler)(argc, argv);
74 		exit(0);
75 	}
76 	fromatty = isatty(fileno(stdin));
77 	top = setjmp(toplevel) == 0;
78 	if (top)
79 		signal(SIGINT, intr);
80 	for (;;) {
81 		cmdscanner(top);
82 		top = 1;
83 	}
84 }
85 
86 intr()
87 {
88 	if (!fromatty)
89 		exit(0);
90 	longjmp(toplevel, 1);
91 }
92 
93 /*
94  * Command parser.
95  */
96 cmdscanner(top)
97 	int top;
98 {
99 	register struct cmd *c;
100 
101 	if (!top)
102 		putchar('\n');
103 	for (;;) {
104 		if (fromatty) {
105 			printf("lpc> ");
106 			fflush(stdout);
107 		}
108 		if (fgets(cmdline, sizeof(cmdline), stdin) == 0)
109 			quit();
110 		if (cmdline[0] == 0)
111 			break;
112 		makeargv();
113 		c = getcmd(margv[0]);
114 		if (c == (struct cmd *)-1) {
115 			printf("?Ambiguous command\n");
116 			continue;
117 		}
118 		if (c == 0) {
119 			printf("?Invalid command\n");
120 			continue;
121 		}
122 		if (c->c_priv && getuid()) {
123 			printf("?Privileged command\n");
124 			continue;
125 		}
126 		(*c->c_handler)(margc, margv);
127 	}
128 	longjmp(toplevel, 0);
129 }
130 
131 extern struct cmd cmdtab[];
132 
133 struct cmd *
134 getcmd(name)
135 	register char *name;
136 {
137 	register char *p, *q;
138 	register struct cmd *c, *found;
139 	register int nmatches, longest;
140 
141 	longest = 0;
142 	nmatches = 0;
143 	found = 0;
144 	for (c = cmdtab; p = c->c_name; c++) {
145 		for (q = name; *q == *p++; q++)
146 			if (*q == 0)		/* exact match? */
147 				return(c);
148 		if (!*q) {			/* the name was a prefix */
149 			if (q - name > longest) {
150 				longest = q - name;
151 				nmatches = 1;
152 				found = c;
153 			} else if (q - name == longest)
154 				nmatches++;
155 		}
156 	}
157 	if (nmatches > 1)
158 		return((struct cmd *)-1);
159 	return(found);
160 }
161 
162 /*
163  * Slice a string up into argc/argv.
164  */
165 makeargv()
166 {
167 	register char *cp;
168 	register char **argp = margv;
169 
170 	margc = 0;
171 	for (cp = cmdline; *cp;) {
172 		while (isspace(*cp))
173 			cp++;
174 		if (*cp == '\0')
175 			break;
176 		*argp++ = cp;
177 		margc += 1;
178 		while (*cp != '\0' && !isspace(*cp))
179 			cp++;
180 		if (*cp == '\0')
181 			break;
182 		*cp++ = '\0';
183 	}
184 	*argp++ = 0;
185 }
186 
187 #define HELPINDENT (sizeof ("directory"))
188 
189 /*
190  * Help command.
191  */
192 help(argc, argv)
193 	int argc;
194 	char *argv[];
195 {
196 	register struct cmd *c;
197 
198 	if (argc == 1) {
199 		register int i, j, w;
200 		int columns, width = 0, lines;
201 		extern int NCMDS;
202 
203 		printf("Commands may be abbreviated.  Commands are:\n\n");
204 		for (c = cmdtab; c->c_name; c++) {
205 			int len = strlen(c->c_name);
206 
207 			if (len > width)
208 				width = len;
209 		}
210 		width = (width + 8) &~ 7;
211 		columns = 80 / width;
212 		if (columns == 0)
213 			columns = 1;
214 		lines = (NCMDS + columns - 1) / columns;
215 		for (i = 0; i < lines; i++) {
216 			for (j = 0; j < columns; j++) {
217 				c = cmdtab + j * lines + i;
218 				if (c->c_name)
219 					printf("%s", c->c_name);
220 				if (c + lines >= &cmdtab[NCMDS]) {
221 					printf("\n");
222 					break;
223 				}
224 				w = strlen(c->c_name);
225 				while (w < width) {
226 					w = (w + 8) &~ 7;
227 					putchar('\t');
228 				}
229 			}
230 		}
231 		return;
232 	}
233 	while (--argc > 0) {
234 		register char *arg;
235 		arg = *++argv;
236 		c = getcmd(arg);
237 		if (c == (struct cmd *)-1)
238 			printf("?Ambiguous help command %s\n", arg);
239 		else if (c == (struct cmd *)0)
240 			printf("?Invalid help command %s\n", arg);
241 		else
242 			printf("%-*s\t%s\n", HELPINDENT,
243 				c->c_name, c->c_help);
244 	}
245 }
246