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 2 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, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * Parse printcap file.
32 * This module does exactly one thing - it looks into the printcap file
33 * and tells callers if a specified string appears as a printer name.
35 * The way this module looks at the printcap file is very simplistic.
36 * Only the local printcap file is inspected (no searching of NIS
39 * There are assumed to be one or more printer names per record, held
40 * as a set of sub-fields separated by vertical bar symbols ('|') in the
41 * first field of the record. The field separator is assumed to be a colon
42 * ':' and the record separator a newline.
44 * Lines ending with a backspace '\' are assumed to flag that the following
45 * line is a continuation line so that a set of lines can be read as one
48 * A line stating with a hash '#' is assumed to be a comment and is ignored
49 * Comments are discarded before the record is strung together from the
50 * set of continuation lines.
52 * Opening a pipe for "lpc status" and reading that would probably
53 * be pretty effective. Code to do this already exists in the freely
54 * distributable PCNFS server code.
56 * Modified to call SVID/XPG4 support if printcap name is set to "lpstat"
57 * in smb.conf under Solaris.
59 * Modified to call CUPS support if printcap name is set to "cups"
66 /* ******************************************
67 Extend for AIX system and qconfig file
68 from 'boulard@univ-rennes1.fr
69 ****************************************** */
70 static int strlocate(char *xpLine
,char *xpS
)
81 if (strncmp(p
,xpS
,iS
) == 0) {iRet
=1;break;};
85 /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/
91 /* ******************************************************************* */
92 /* * Scan qconfig and search all virtual printer (device printer) * */
93 /* ******************************************************************* */
94 static void ScanQconfig_fn(char *psz
,void (*fn
)(char *, char *))
104 if ((pfile
= x_fopen(psz
, O_RDONLY
, 0)) == NULL
)
106 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz
));
111 /* scan qconfig file for searching <printername>: */
112 for (;(line
= fgets_slash(NULL
,sizeof(pstring
),pfile
)); safe_free(line
))
114 if (*line
== '*' || *line
== 0)
118 case 0: /* locate an entry */
119 if (*line
== '\t' || *line
== ' ') continue;
120 if ((p
=strchr_m(line
,':')))
123 p
= strtok(line
,":");
124 if (strcmp(p
,"bsh")!=0)
132 case 1: /* scanning device stanza */
133 if (*line
== '*' || *line
== 0) continue;
134 if (*line
!= '\t' && *line
!= ' ')
136 /* name is found without stanza device */
137 /* probably a good printer ??? */
143 if (strlocate(line
,"backend"))
145 /* it's a device, not a virtual printer*/
148 else if (strlocate(line
,"device"))
150 /* it's a good virtual printer */
161 /* Scan qconfig file and locate de printername */
163 static BOOL
ScanQconfig(char *psz
,char *pszPrintername
)
172 if ((pszPrintername
!= NULL
) && ((iLg
= strlen(pszPrintername
)) > 0))
173 pName
= malloc(iLg
+10);
176 DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername
));
179 if ((pfile
= x_fopen(psz
, O_RDONLY
, 0)) == NULL
)
181 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz
));
185 slprintf(pName
, iLg
+ 9, "%s:",pszPrintername
);
187 /*DEBUG(3,( " Looking for entry %s\n",pName));*/
189 /* scan qconfig file for searching <printername>: */
190 for (;(line
= fgets_slash(NULL
,sizeof(pstring
),pfile
)); safe_free(line
))
192 if (*line
== '*' || *line
== 0)
196 case 0: /* scanning entry */
197 if (strncmp(line
,pName
,iLg
) == 0)
203 case 1: /* scanning device stanza */
204 if (*line
== '*' || *line
== 0) continue;
205 if (*line
!= '\t' && *line
!= ' ')
207 /* name is found without stanza device */
208 /* probably a good printer ??? */
215 if (strlocate(line
,"backend"))
217 /* it's a device, not a virtual printer*/
220 else if (strlocate(line
,"device"))
222 /* it's a good virtual printer */
238 /***************************************************************************
239 Scan printcap file pszPrintcapname for a printer called pszPrintername.
240 Return True if found, else False. Returns False on error, too, after logging
241 the error at level 0. For generality, the printcap name may be passed - if
242 passed as NULL, the configuration will be queried for the name.
243 ***************************************************************************/
244 BOOL
pcap_printername_ok(const char *pszPrintername
, const char *pszPrintcapname
)
251 if (pszPrintername
== NULL
|| pszPrintername
[0] == '\0')
253 DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
257 /* only go looking if no printcap name supplied */
258 if ((psz
= pszPrintcapname
) == NULL
|| psz
[0] == '\0')
259 if (((psz
= lp_printcapname()) == NULL
) || (psz
[0] == '\0'))
261 DEBUG(0,( "No printcap file name configured!\n"));
266 if (strequal(psz
, "cups"))
267 return (cups_printername_ok(pszPrintername
));
268 #endif /* HAVE_CUPS */
271 if (strequal(psz
, "lpstat"))
272 return (sysv_printername_ok(pszPrintername
));
276 if (strlocate(psz
,"/qconfig"))
277 return(ScanQconfig(psz
,pszPrintername
));
280 if ((pfile
= x_fopen(psz
, O_RDONLY
, 0)) == NULL
)
282 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz
));
286 for (;(line
= fgets_slash(NULL
,sizeof(pstring
),pfile
)); safe_free(line
))
288 if (*line
== '#' || *line
== 0)
291 /* now we have a real printer line - cut it off at the first : */
292 p
= strchr_m(line
,':');
295 /* now just check if the name is in the list */
296 /* NOTE: I avoid strtok as the fn calling this one may be using it */
299 if ((q
= strchr_m(p
,'|'))) *q
++ = 0;
301 if (strequal(p
,pszPrintername
))
316 /***************************************************************************
317 run a function on each printer name in the printcap file. The function is
318 passed the primary name and the comment (if possible). Note the fn() takes
319 strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed
320 to return DOS codepage. FIXME !! JRA.
321 ***************************************************************************/
322 void pcap_printer_fn(void (*fn
)(char *, char *))
324 pstring name
,comment
;
330 /* only go looking if no printcap name supplied */
331 if (((psz
= lp_printcapname()) == NULL
) || (psz
[0] == '\0'))
333 DEBUG(0,( "No printcap file name configured!\n"));
338 if (strequal(psz
, "cups")) {
342 #endif /* HAVE_CUPS */
345 if (strequal(psz
, "lpstat")) {
352 if (strlocate(psz
,"/qconfig"))
354 ScanQconfig_fn(psz
,fn
);
359 if ((pfile
= x_fopen(psz
, O_RDONLY
, 0)) == NULL
)
361 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz
));
365 for (;(line
= fgets_slash(NULL
,sizeof(pstring
),pfile
)); safe_free(line
))
367 if (*line
== '#' || *line
== 0)
370 /* now we have a real printer line - cut it off at the first : */
371 p
= strchr_m(line
,':');
374 /* now find the most likely printer name and comment
375 this is pure guesswork, but it's better than nothing */
380 BOOL has_punctuation
;
381 if ((q
= strchr_m(p
,'|'))) *q
++ = 0;
383 has_punctuation
= (strchr_m(p
,' ') || strchr_m(p
,'\t') || strchr_m(p
,'(') || strchr_m(p
,')'));
385 if (strlen(p
)>strlen(comment
) && has_punctuation
)
391 if (strlen(p
) <= MAXPRINTERLEN
&& strlen(p
)>strlen(name
) && !has_punctuation
)
393 if (!*comment
) pstrcpy(comment
,name
);
398 if (!strchr_m(comment
,' ') &&
399 strlen(p
) > strlen(comment
))
407 name
[MAXPRINTERLEN
] = 0;