2 Unix SMB/Netbios implementation.
5 Copyright (C) Karl Auer 1993-1998
7 Re-working by Martin Kiff, 1994
9 Re-written again by Andrew Tridgell
11 Modified for SVID support by Norm Jacobs, 1997
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * Parse printcap file.
31 * This module does exactly one thing - it looks into the printcap file
32 * and tells callers if a specified string appears as a printer name.
34 * The way this module looks at the printcap file is very simplistic.
35 * Only the local printcap file is inspected (no searching of NIS
38 * There are assumed to be one or more printer names per record, held
39 * as a set of sub-fields separated by vertical bar symbols ('|') in the
40 * first field of the record. The field separator is assumed to be a colon
41 * ':' and the record separator a newline.
43 * Lines ending with a backspace '\' are assumed to flag that the following
44 * line is a continuation line so that a set of lines can be read as one
47 * A line stating with a hash '#' is assumed to be a comment and is ignored
48 * Comments are discarded before the record is strung together from the
49 * set of continuation lines.
51 * Opening a pipe for "lpc status" and reading that would probably
52 * be pretty effective. Code to do this already exists in the freely
53 * distributable PCNFS server code.
55 * Modified to call SVID/XPG4 support if printcap name is set to "lpstat"
56 * in smb.conf under Solaris.
63 extern int DEBUGLEVEL
;
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
)())
104 if ((pfile
= sys_fopen(psz
, "r")) == 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
)); free(line
))
114 if (*line
== '*' || *line
== 0)
118 case 0: /* locate an entry */
119 if (*line
== '\t' || *line
== ' ') continue;
120 if ((p
=strchr(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
= sys_fopen(psz
, "r")) == 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
)); 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(char *pszPrintername
, 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
, "lpstat"))
267 return (sysv_printername_ok(pszPrintername
));
271 if (strlocate(psz
,"/qconfig"))
272 return(ScanQconfig(psz
,pszPrintername
));
275 if ((pfile
= sys_fopen(psz
, "r")) == NULL
)
277 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz
));
281 for (;(line
= fgets_slash(NULL
,sizeof(pstring
),pfile
)); free(line
))
283 if (*line
== '#' || *line
== 0)
286 /* now we have a real printer line - cut it off at the first : */
287 p
= strchr(line
,':');
290 /* now just check if the name is in the list */
291 /* NOTE: I avoid strtok as the fn calling this one may be using it */
294 if ((q
= strchr(p
,'|'))) *q
++ = 0;
296 if (strequal(p
,pszPrintername
))
298 /* normalise the case */
299 pstrcpy(pszPrintername
,p
);
313 /***************************************************************************
314 run a function on each printer name in the printcap file. The function is
315 passed the primary name and the comment (if possible)
316 ***************************************************************************/
317 void pcap_printer_fn(void (*fn
)(char *, char *))
319 pstring name
,comment
;
325 /* only go looking if no printcap name supplied */
326 if (((psz
= lp_printcapname()) == NULL
) || (psz
[0] == '\0'))
328 DEBUG(0,( "No printcap file name configured!\n"));
333 if (strequal(psz
, "lpstat")) {
340 if (strlocate(psz
,"/qconfig"))
342 ScanQconfig_fn(psz
,fn
);
347 if ((pfile
= sys_fopen(psz
, "r")) == NULL
)
349 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz
));
353 for (;(line
= fgets_slash(NULL
,sizeof(pstring
),pfile
)); free(line
))
355 if (*line
== '#' || *line
== 0)
358 /* now we have a real printer line - cut it off at the first : */
359 p
= strchr(line
,':');
362 /* now find the most likely printer name and comment
363 this is pure guesswork, but it's better than nothing */
368 BOOL has_punctuation
;
369 if ((q
= strchr(p
,'|'))) *q
++ = 0;
371 has_punctuation
= (strchr(p
,' ') || strchr(p
,'(') || strchr(p
,')'));
373 if (strlen(p
)>strlen(comment
) && has_punctuation
)
375 StrnCpy(comment
,p
,sizeof(comment
)-1);
379 if (strlen(p
) <= MAXPRINTERLEN
&& strlen(p
)>strlen(name
) && !has_punctuation
)
381 if (!*comment
) pstrcpy(comment
,name
);
386 if (!strchr(comment
,' ') &&
387 strlen(p
) > strlen(comment
))
389 StrnCpy(comment
,p
,sizeof(comment
)-1);
395 name
[MAXPRINTERLEN
] = 0;