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)
130 const char *pcap_name
= lp_printcapname();
131 bool pcap_reloaded
= False
;
132 struct pcap_cache
*tmp_cache
= NULL
;
136 DEBUG(3, ("reloading printcap cache\n"));
138 /* only go looking if no printcap name supplied */
139 if (pcap_name
== NULL
|| *pcap_name
== 0) {
140 DEBUG(0, ("No printcap file name configured!\n"));
144 tmp_cache
= pcap_cache
;
148 if (strequal(pcap_name
, "cups")) {
149 pcap_reloaded
= cups_cache_reload();
155 if (strequal(pcap_name
, "iprint")) {
156 pcap_reloaded
= iprint_cache_reload();
161 #if defined(SYSV) || defined(HPUX)
162 if (strequal(pcap_name
, "lpstat")) {
163 pcap_reloaded
= sysv_cache_reload();
169 if (strstr_m(pcap_name
, "/qconfig") != NULL
) {
170 pcap_reloaded
= aix_cache_reload();
175 /* handle standard printcap - moved from pcap_printer_fn() */
177 if ((pcap_file
= x_fopen(pcap_name
, O_RDONLY
, 0)) == NULL
) {
178 DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name
));
182 for (; (pcap_line
= fgets_slash(NULL
, 1024, pcap_file
)) != NULL
; safe_free(pcap_line
)) {
183 char name
[MAXPRINTERLEN
+1];
187 if (*pcap_line
== '#' || *pcap_line
== 0)
190 /* now we have a real printer line - cut at the first : */
191 if ((p
= strchr_m(pcap_line
, ':')) != NULL
)
195 * now find the most likely printer name and comment
196 * this is pure guesswork, but it's better than nothing
198 for (*name
= *comment
= 0, p
= pcap_line
; p
!= NULL
; p
= q
) {
199 bool has_punctuation
;
201 if ((q
= strchr_m(p
, '|')) != NULL
)
204 has_punctuation
= (strchr_m(p
, ' ') ||
209 if (strlen(p
) > strlen(comment
) && has_punctuation
) {
210 strlcpy(comment
, p
, sizeof(comment
));
214 if (strlen(p
) <= MAXPRINTERLEN
&&
215 strlen(p
) > strlen(name
) && !has_punctuation
) {
217 strlcpy(comment
, name
, sizeof(comment
));
219 strlcpy(name
, p
, sizeof(name
));
223 if (!strchr_m(comment
, ' ') &&
224 strlen(p
) > strlen(comment
)) {
225 strlcpy(comment
, p
, sizeof(comment
));
231 name
[MAXPRINTERLEN
] = 0;
233 if (*name
&& !pcap_cache_add(name
, comment
)) {
240 pcap_reloaded
= True
;
243 DEBUG(3, ("reload status: %s\n", (pcap_reloaded
) ? "ok" : "error"));
246 pcap_cache_destroy_specific(&tmp_cache
);
248 pcap_cache_destroy_specific(&pcap_cache
);
249 pcap_cache
= tmp_cache
;
256 bool pcap_printername_ok(const char *printername
)
258 struct pcap_cache
*p
;
260 for (p
= pcap_cache
; p
!= NULL
; p
= p
->next
)
261 if (strequal(p
->name
, printername
))
267 /***************************************************************************
268 run a function on each printer name in the printcap file.
269 ***************************************************************************/
271 void pcap_printer_fn_specific(const struct pcap_cache
*pc
,
272 void (*fn
)(const char *, const char *, void *),
275 const struct pcap_cache
*p
;
277 for (p
= pc
; p
!= NULL
; p
= p
->next
)
278 fn(p
->name
, p
->comment
, pdata
);
283 void pcap_printer_fn(void (*fn
)(const char *, const char *, void *), void *pdata
)
285 pcap_printer_fn_specific(pcap_cache
, fn
, pdata
);