2 Unix SMB/Netbios implementation.
5 Copyright (C) Karl Auer 1993-1997
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 = 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 = fopen(psz, "r")) == NULL)
181 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
185 sprintf(pName,"%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 */
237 /***************************************************************************
238 Scan printcap file pszPrintcapname for a printer called pszPrintername.
239 Return True if found, else False. Returns False on error, too, after logging
240 the error at level 0. For generality, the printcap name may be passed - if
241 passed as NULL, the configuration will be queried for the name.
242 ***************************************************************************/
243 BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
250 if (pszPrintername == NULL || pszPrintername[0] == '\0')
252 DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
256 /* only go looking if no printcap name supplied */
257 if ((psz = pszPrintcapname) == NULL || psz[0] == '\0')
258 if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
260 DEBUG(0,( "No printcap file name configured!\n"));
265 if (strequal(psz, "lpstat"))
266 return (sysv_printername_ok(pszPrintername));
270 if (strlocate(psz,"/qconfig"))
271 return(ScanQconfig(psz,pszPrintername));
274 if ((pfile = fopen(psz, "r")) == NULL)
276 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
280 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
282 if (*line == '#' || *line == 0)
285 /* now we have a real printer line - cut it off at the first : */
286 p = strchr(line,':');
289 /* now just check if the name is in the list */
290 /* NOTE: I avoid strtok as the fn calling this one may be using it */
293 if ((q = strchr(p,'|'))) *q++ = 0;
295 if (strequal(p,pszPrintername))
297 /* normalise the case */
298 strcpy(pszPrintername,p);
312 /***************************************************************************
313 run a function on each printer name in the printcap file. The function is
314 passed the primary name and the comment (if possible)
315 ***************************************************************************/
316 void pcap_printer_fn(void (*fn)())
318 pstring name,comment;
324 /* only go looking if no printcap name supplied */
325 if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
327 DEBUG(0,( "No printcap file name configured!\n"));
332 if (strequal(psz, "lpstat")) {
339 if (strlocate(psz,"/qconfig"))
341 ScanQconfig_fn(psz,fn);
346 if ((pfile = fopen(psz, "r")) == NULL)
348 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
352 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
354 if (*line == '#' || *line == 0)
357 /* now we have a real printer line - cut it off at the first : */
358 p = strchr(line,':');
361 /* now find the most likely printer name and comment
362 this is pure guesswork, but it's better than nothing */
367 BOOL has_punctuation;
368 if ((q = strchr(p,'|'))) *q++ = 0;
370 has_punctuation = (strchr(p,' ') || strchr(p,'(') || strchr(p,')'));
372 if (strlen(p)>strlen(comment) && has_punctuation)
374 StrnCpy(comment,p,sizeof(comment)-1);
378 if (strlen(p) <= 8 && strlen(p)>strlen(name) && !has_punctuation)
380 if (!*comment) pstrcpy(comment,name);
385 if (!strchr(comment,' ') &&
386 strlen(p) > strlen(comment))
388 StrnCpy(comment,p,sizeof(comment)-1);