xref: /original-bsd/usr.sbin/lpr/lpc/lpc.c (revision d919d844)
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.6 (Berkeley) 06/30/88";
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 (gets(cmdline) == 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 < &cmdtab[NCMDS - 1]; 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 				printf("%s", c->c_name);
219 				if (c + lines >= &cmdtab[NCMDS]) {
220 					printf("\n");
221 					break;
222 				}
223 				w = strlen(c->c_name);
224 				while (w < width) {
225 					w = (w + 8) &~ 7;
226 					putchar('\t');
227 				}
228 			}
229 		}
230 		return;
231 	}
232 	while (--argc > 0) {
233 		register char *arg;
234 		arg = *++argv;
235 		c = getcmd(arg);
236 		if (c == (struct cmd *)-1)
237 			printf("?Ambiguous help command %s\n", arg);
238 		else if (c == (struct cmd *)0)
239 			printf("?Invalid help command %s\n", arg);
240 		else
241 			printf("%-*s\t%s\n", HELPINDENT,
242 				c->c_name, c->c_help);
243 	}
244 }
245