1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
31
32 #include "stdio.h"
33 #include "string.h"
34 #include "errno.h"
35 #include "sys/types.h"
36 #include "stdlib.h"
37 #include <syslog.h>
38
39 #include "lp.h"
40 #include "printers.h"
41
42 extern struct {
43 char *v;
44 short len,
45 okremote;
46 } prtrheadings[];
47
48 /**
49 ** getprinter() - EXTRACT PRINTER STRUCTURE FROM DISK FILE
50 **/
51
52 PRINTER *
getprinter(char * name)53 getprinter(char *name)
54 {
55 static long lastdir = -1;
56
57 PRINTER *prp;
58
59 char buf[BUFSIZ];
60
61 short daisy;
62
63 int fld;
64
65 int fd;
66
67 FALERT *pa;
68
69 register char * p;
70 register char ** pp;
71 register char *** ppp;
72 register char * path;
73 int isNameAll;
74
75
76
77 if (!name || !*name) {
78 errno = EINVAL;
79 return (0);
80 }
81
82 syslog(LOG_DEBUG, "getprinter(%s)", name ? name : "");
83 /*
84 * Getting ``all''? If so, jump into the directory
85 * wherever we left off.
86 */
87 isNameAll = STREQU(NAME_ALL, name);
88 for (; ; ) {
89 /* fix for bug 1117241
90 * occasionally when a printer is removed, a printer directory
91 * is left behind, but the CONFIGFILE is removed. In this
92 * case this directory terminates the search for additional
93 * printers as we have been returning 0 in this case.
94 * Now, we loop back and try the next directory until
95 * we have no more directories or we find a directory with
96 * a CONFIGFILE
97 */
98 if (isNameAll) {
99 if (!(name = next_dir(Lp_A_Printers, &lastdir)))
100 return (0);
101 } else
102 lastdir = -1;
103
104 /*
105 * Get the printer configuration information.
106 */
107
108 path = getprinterfile(name, CONFIGFILE);
109 if (!path) {
110 if (isNameAll)
111 Free(name);
112 return (0);
113 }
114
115 if ((fd = open_locked(path, "r", 0)) < 0) {
116 Free(path); /*
117 * go around to loop again for
118 * NAME_ALL case
119 */
120
121 if (!isNameAll) /* fix for bug 1117241 */
122 return(0);
123 else
124 Free(name);
125 }
126 else
127 break;
128 }
129 Free (path);
130
131 /*
132 * Initialize the entire structure, to ensure no random
133 * values get in it. However, make sure some values won't
134 * be null or empty. Do the latter here as opposed to
135 * after reading the file, because sometimes the file
136 * contains an empty header to FORCE a null/empty value.
137 */
138 prp = calloc(sizeof (*prp), 1);
139 prp->name = Strdup(name);
140 if (isNameAll)
141 Free(name);
142 prp->printer_types = getlist(NAME_UNKNOWN, LP_WS, LP_SEP);
143 prp->input_types = getlist(NAME_SIMPLE, LP_WS, LP_SEP);
144 #if defined(CAN_DO_MODULES)
145 prp->modules = getlist(NAME_DEFAULT, LP_WS, LP_SEP);
146 #endif
147
148 /*
149 * Read the file.
150 */
151 errno = 0;
152 while (fdgets(buf, BUFSIZ, fd) != NULL) {
153
154 buf[strlen(buf) - 1] = 0;
155
156 for (fld = 0; fld < PR_MAX; fld++)
157 if (
158 prtrheadings[fld].v
159 && prtrheadings[fld].len
160 && STRNEQU(
161 buf,
162 prtrheadings[fld].v,
163 prtrheadings[fld].len
164 )
165 ) {
166 p = buf + prtrheadings[fld].len;
167 while (*p && *p == ' ')
168 p++;
169 break;
170 }
171
172 /*
173 * To allow future extensions to not impact applications
174 * using old versions of this routine, ignore strange
175 * fields.
176 */
177 if (fld >= PR_MAX)
178 continue;
179
180 switch (fld) {
181
182 case PR_BAN:
183 if ((pp = getlist(p, LP_WS, ":"))) {
184 if (pp[0] != NULL) {
185 if (strcmp(pp[0], NAME_OPTIONAL) == 0)
186 prp->banner = BAN_OPTIONAL;
187 else if (strcmp(pp[0], NAME_OFF) == 0)
188 prp->banner = BAN_NEVER;
189 else if (strcmp(pp[0], NAME_ON) == 0)
190 prp->banner = BAN_ALWAYS;
191 else /* default to the LP default */
192 prp->banner = BAN_ALWAYS;
193 }
194 if (pp[1] && CS_STREQU(pp[1], NAME_ALWAYS))
195 prp->banner |= BAN_ALWAYS;
196 freelist (pp);
197 }
198 break;
199
200 case PR_LOGIN:
201 prp->login = LOG_IN;
202 break;
203
204 case PR_CPI:
205 prp->cpi = getcpi(p);
206 break;
207
208 case PR_LPI:
209 prp->lpi = getsdn(p);
210 break;
211
212 case PR_LEN:
213 prp->plen = getsdn(p);
214 break;
215
216 case PR_WIDTH:
217 prp->pwid = getsdn(p);
218 break;
219
220 case PR_CS:
221 ppp = &(prp->char_sets);
222 goto CharStarStar;
223
224 case PR_ITYPES:
225 ppp = &(prp->input_types);
226 CharStarStar: if (*ppp)
227 freelist (*ppp);
228 *ppp = getlist(p, LP_WS, LP_SEP);
229 break;
230
231 case PR_DEV:
232 pp = &(prp->device);
233 goto CharStar;
234
235 case PR_DIAL:
236 pp = &(prp->dial_info);
237 goto CharStar;
238
239 case PR_RECOV:
240 pp = &(prp->fault_rec);
241 goto CharStar;
242
243 case PR_INTFC:
244 pp = &(prp->interface);
245 goto CharStar;
246
247 case PR_PTYPE:
248 ppp = &(prp->printer_types);
249 goto CharStarStar;
250
251 case PR_REMOTE:
252 pp = &(prp->remote);
253 goto CharStar;
254
255 case PR_SPEED:
256 pp = &(prp->speed);
257 goto CharStar;
258
259 case PR_STTY:
260 pp = &(prp->stty);
261 CharStar: if (*pp)
262 Free (*pp);
263 *pp = Strdup(p);
264 break;
265
266 #if defined(CAN_DO_MODULES)
267 case PR_MODULES:
268 ppp = &(prp->modules);
269 goto CharStarStar;
270 #endif
271
272 case PR_OPTIONS:
273 ppp = &(prp->options);
274 goto CharStarStar;
275 break;
276
277 case PR_PPD:
278 {
279 pp = &(prp->ppd);
280 goto CharStar;
281 }
282 }
283
284 }
285 if (errno != 0) {
286 int save_errno = errno;
287
288 freeprinter (prp);
289 close(fd);
290 errno = save_errno;
291 return (0);
292 }
293 close(fd);
294
295 /*
296 * Get the printer description (if it exists).
297 */
298 if (!(path = getprinterfile(prp->name, COMMENTFILE)))
299 return (0);
300 if (!(prp->description = loadstring(path)) && errno != ENOENT) {
301 Free (path);
302 freeprinter (prp);
303 return (0);
304 }
305 Free (path);
306
307 /*
308 * Get the information for the alert. Don't fail if we can't
309 * read it because of access permission UNLESS we're "root"
310 * or "lp"
311 */
312 if (!(pa = getalert(Lp_A_Printers, prp->name))) {
313 if (
314 errno != ENOENT
315 && (
316 errno != EACCES
317 || !getpid() /* we be root */
318 || STREQU(getname(), LPUSER) /* we be lp */
319 )
320 ) {
321 freeprinter (prp);
322 return (0);
323 }
324 } else
325 prp->fault_alert = *pa;
326
327 /*
328 * Now go through the structure and see if we have
329 * anything strange.
330 */
331 if (!okprinter(prp->name, prp, 0)) {
332 freeprinter (prp);
333 errno = EBADF;
334 return (0);
335 }
336
337 /*
338 * Just in case somebody tried to pull a fast one
339 * by giving a printer type header by itself....
340 */
341 if (!prp->printer_types)
342 prp->printer_types = getlist(NAME_UNKNOWN, LP_WS, LP_SEP);
343
344 /*
345 * If there are more than one printer type, then we can't
346 * have any input types, except perhaps ``simple''.
347 */
348 if (
349 lenlist(prp->printer_types) > 1
350 && prp->input_types
351 && (
352 lenlist(prp->input_types) > 1
353 || !STREQU(NAME_SIMPLE, *prp->input_types)
354 )
355 ) {
356 freeprinter (prp);
357 badprinter = BAD_ITYPES;
358 errno = EBADF;
359 return (0);
360 }
361
362 /*
363 * If there are more than one printer types, none can
364 * be ``unknown''.
365 */
366 if (
367 lenlist(prp->printer_types) > 1
368 && searchlist(NAME_UNKNOWN, prp->printer_types)
369 ) {
370 freeprinter (prp);
371 badprinter = BAD_PTYPES;
372 errno = EBADF;
373 return (0);
374 }
375
376 /*
377 * All the printer types had better agree on whether the
378 * printer takes print wheels!
379 */
380 prp->daisy = -1;
381 for (pp = prp->printer_types; *pp; pp++) {
382 tidbit (*pp, "daisy", &daisy);
383 if (daisy == -1)
384 daisy = 0;
385 if (prp->daisy == -1)
386 prp->daisy = daisy;
387 else if (prp->daisy != daisy) {
388 freeprinter (prp);
389 badprinter = BAD_DAISY;
390 errno = EBADF;
391 return (0);
392 }
393 }
394
395 /*
396 * Help out those who are still using the obsolete
397 * "printer_type" member.
398 */
399 prp->printer_type = Strdup(*prp->printer_types);
400
401 return (prp);
402 }
403