2 Unix SMB/CIFS implementation.
4 Copyright (C) Karl Auer 1993-1998
6 Re-working by Martin Kiff, 1994
8 Re-written again by Andrew Tridgell
10 Modified for SVID support by Norm Jacobs, 1997
12 Modified for CUPS support by Michael Sweet, 1999
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 3 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 * This module contains code to parse and cache printcap data, possibly
30 * in concert with the CUPS/SYSV/AIX-specific code found elsewhere.
32 * The way this module looks at the printcap file is very simplistic.
33 * Only the local printcap file is inspected (no searching of NIS
36 * There are assumed to be one or more printer names per record, held
37 * as a set of sub-fields separated by vertical bar symbols ('|') in the
38 * first field of the record. The field separator is assumed to be a colon
39 * ':' and the record separator a newline.
41 * Lines ending with a backspace '\' are assumed to flag that the following
42 * line is a continuation line so that a set of lines can be read as one
45 * A line stating with a hash '#' is assumed to be a comment and is ignored
46 * Comments are discarded before the record is strung together from the
47 * set of continuation lines.
49 * Opening a pipe for "lpc status" and reading that would probably
50 * be pretty effective. Code to do this already exists in the freely
51 * distributable PCNFS server code.
53 * Modified to call SVID/XPG4 support if printcap name is set to "lpstat"
54 * in smb.conf under Solaris.
56 * Modified to call CUPS support if printcap name is set to "cups"
59 * Modified to call iPrint support if printcap name is set to "iprint"
69 struct pcap_cache
*next
;
72 /* The systemwide printcap cache. */
73 static struct pcap_cache
*pcap_cache
= NULL
;
75 bool pcap_cache_add_specific(struct pcap_cache
**ppcache
, const char *name
, const char *comment
)
79 if (name
== NULL
|| ((p
= SMB_MALLOC_P(struct pcap_cache
)) == NULL
))
82 p
->name
= SMB_STRDUP(name
);
83 p
->comment
= (comment
&& *comment
) ? SMB_STRDUP(comment
) : NULL
;
85 DEBUG(11,("pcap_cache_add_specific: Adding name %s info %s\n",
86 p
->name
, p
->comment
? p
->comment
: ""));
94 void pcap_cache_destroy_specific(struct pcap_cache
**pp_cache
)
96 struct pcap_cache
*p
, *next
;
98 for (p
= *pp_cache
; p
!= NULL
; p
= next
) {
102 SAFE_FREE(p
->comment
);
108 bool pcap_cache_add(const char *name
, const char *comment
)
110 return pcap_cache_add_specific(&pcap_cache
, name
, comment
);
113 bool pcap_cache_loaded(void)
115 return (pcap_cache
!= NULL
);
118 void pcap_cache_replace(const struct pcap_cache
*pcache
)
120 const struct pcap_cache
*p
;
122 pcap_cache_destroy_specific(&pcap_cache
);
123 for (p
= pcache
; p
; p
= p
->next
) {
124 pcap_cache_add(p
->name
, p
->comment
);
128 void pcap_cache_reload(void (*post_cache_fill_fn
)(void))
130 const char *pcap_name
= lp_printcapname();
131 bool pcap_reloaded
= False
;
132 struct pcap_cache
*tmp_cache
= NULL
;
135 bool post_cache_fill_fn_handled
= false;
137 DEBUG(3, ("reloading printcap cache\n"));
139 /* only go looking if no printcap name supplied */
140 if (pcap_name
== NULL
|| *pcap_name
== 0) {
141 DEBUG(0, ("No printcap file name configured!\n"));
145 tmp_cache
= pcap_cache
;
149 if (strequal(pcap_name
, "cups")) {
150 pcap_reloaded
= cups_cache_reload(post_cache_fill_fn
);
152 * cups_cache_reload() is async and calls post_cache_fill_fn()
153 * on successful completion
155 post_cache_fill_fn_handled
= true;
161 if (strequal(pcap_name
, "iprint")) {
162 pcap_reloaded
= iprint_cache_reload();
167 #if defined(SYSV) || defined(HPUX)
168 if (strequal(pcap_name
, "lpstat")) {
169 pcap_reloaded
= sysv_cache_reload();
175 if (strstr_m(pcap_name
, "/qconfig") != NULL
) {
176 pcap_reloaded
= aix_cache_reload();
181 /* handle standard printcap - moved from pcap_printer_fn() */
183 if ((pcap_file
= x_fopen(pcap_name
, O_RDONLY
, 0)) == NULL
) {
184 DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name
));
188 for (; (pcap_line
= fgets_slash(NULL
, 1024, pcap_file
)) != NULL
; free(pcap_line
)) {
189 char name
[MAXPRINTERLEN
+1];
193 if (*pcap_line
== '#' || *pcap_line
== 0)
196 /* now we have a real printer line - cut at the first : */
197 if ((p
= strchr_m(pcap_line
, ':')) != NULL
)
201 * now find the most likely printer name and comment
202 * this is pure guesswork, but it's better than nothing
204 for (*name
= *comment
= 0, p
= pcap_line
; p
!= NULL
; p
= q
) {
205 bool has_punctuation
;
207 if ((q
= strchr_m(p
, '|')) != NULL
)
210 has_punctuation
= (strchr_m(p
, ' ') ||
219 if (strlen(p
) > strlen(comment
) && has_punctuation
) {
220 strlcpy(comment
, p
, sizeof(comment
));
224 if (strlen(p
) <= MAXPRINTERLEN
&& *name
== '\0' && !has_punctuation
) {
226 strlcpy(comment
, name
, sizeof(comment
));
228 strlcpy(name
, p
, sizeof(name
));
232 if (!strchr_m(comment
, ' ') &&
233 strlen(p
) > strlen(comment
)) {
234 strlcpy(comment
, p
, sizeof(comment
));
239 if (*name
&& !pcap_cache_add(name
, comment
)) {
246 pcap_reloaded
= True
;
249 DEBUG(3, ("reload status: %s\n", (pcap_reloaded
) ? "ok" : "error"));
252 pcap_cache_destroy_specific(&tmp_cache
);
253 if ((post_cache_fill_fn_handled
== false)
254 && (post_cache_fill_fn
!= NULL
)) {
255 post_cache_fill_fn();
258 pcap_cache_destroy_specific(&pcap_cache
);
259 pcap_cache
= tmp_cache
;
266 bool pcap_printername_ok(const char *printername
)
268 struct pcap_cache
*p
;
270 for (p
= pcap_cache
; p
!= NULL
; p
= p
->next
)
271 if (strequal(p
->name
, printername
))
277 /***************************************************************************
278 run a function on each printer name in the printcap file.
279 ***************************************************************************/
281 void pcap_printer_fn_specific(const struct pcap_cache
*pc
,
282 void (*fn
)(const char *, const char *, void *),
285 const struct pcap_cache
*p
;
287 for (p
= pc
; p
!= NULL
; p
= p
->next
)
288 fn(p
->name
, p
->comment
, pdata
);
293 void pcap_printer_fn(void (*fn
)(const char *, const char *, void *), void *pdata
)
295 pcap_printer_fn_specific(pcap_cache
, fn
, pdata
);