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"
68 /* ******************************************
69 Extend for AIX system and qconfig file
70 from 'boulard@univ-rennes1.fr
71 ****************************************** */
72 static int strlocate(char *xpLine,char *xpS)
83 if (strncmp(p,xpS,iS) == 0) {iRet =1;break;};
87 /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/
93 /* ******************************************************************* */
94 /* * Scan qconfig and search all virtual printer (device printer) * */
95 /* ******************************************************************* */
96 static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *))
101 pstring name,comment;
106 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
108 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
113 /* scan qconfig file for searching <printername>: */
114 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
116 if (*line == '*' || *line == 0)
120 case 0: /* locate an entry */
121 if (*line == '\t' || *line == ' ') continue;
122 if ((p=strchr_m(line,':')))
125 p = strtok(line,":");
126 if (strcmp(p,"bsh")!=0)
134 case 1: /* scanning device stanza */
135 if (*line == '*' || *line == 0) continue;
136 if (*line != '\t' && *line != ' ')
138 /* name is found without stanza device */
139 /* probably a good printer ??? */
145 if (strlocate(line,"backend"))
147 /* it's a device, not a virtual printer*/
150 else if (strlocate(line,"device"))
152 /* it's a good virtual printer */
163 /* Scan qconfig file and locate de printername */
165 static BOOL ScanQconfig(char *psz,char *pszPrintername)
174 if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0))
175 pName = malloc(iLg+10);
178 DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername));
181 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
183 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
187 slprintf(pName, iLg + 9, "%s:",pszPrintername);
189 /*DEBUG(3,( " Looking for entry %s\n",pName));*/
191 /* scan qconfig file for searching <printername>: */
192 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
194 if (*line == '*' || *line == 0)
198 case 0: /* scanning entry */
199 if (strncmp(line,pName,iLg) == 0)
205 case 1: /* scanning device stanza */
206 if (*line == '*' || *line == 0) continue;
207 if (*line != '\t' && *line != ' ')
209 /* name is found without stanza device */
210 /* probably a good printer ??? */
217 if (strlocate(line,"backend"))
219 /* it's a device, not a virtual printer*/
222 else if (strlocate(line,"device"))
224 /* it's a good virtual printer */
240 /***************************************************************************
241 Scan printcap file pszPrintcapname for a printer called pszPrintername.
242 Return True if found, else False. Returns False on error, too, after logging
243 the error at level 0. For generality, the printcap name may be passed - if
244 passed as NULL, the configuration will be queried for the name. pszPrintername
245 must be in DOS codepage.
246 The xxx_printername_ok functions need fixing to understand they are being
247 given a DOS codepage. FIXME !! JRA.
248 ***************************************************************************/
249 BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
256 if (pszPrintername == NULL || pszPrintername[0] == '\0')
258 DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
262 /* only go looking if no printcap name supplied */
263 if ((psz = pszPrintcapname) == NULL || psz[0] == '\0')
264 if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
266 DEBUG(0,( "No printcap file name configured!\n"));
271 if (strequal(psz, "cups"))
272 return (cups_printername_ok(pszPrintername));
273 #endif /* HAVE_CUPS */
276 if (strequal(psz, "lpstat"))
277 return (sysv_printername_ok(pszPrintername));
281 if (strlocate(psz,"/qconfig"))
282 return(ScanQconfig(psz,pszPrintername));
285 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
287 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
291 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
293 if (*line == '#' || *line == 0)
296 /* now we have a real printer line - cut it off at the first : */
297 p = strchr_m(line,':');
300 /* now just check if the name is in the list */
301 /* NOTE: I avoid strtok as the fn calling this one may be using it */
304 if ((q = strchr_m(p,'|'))) *q++ = 0;
306 if (strequal(p,pszPrintername))
308 /* normalise the case */
309 pstrcpy(pszPrintername,p);
323 /***************************************************************************
324 run a function on each printer name in the printcap file. The function is
325 passed the primary name and the comment (if possible). Note the fn() takes
326 strings in DOS codepage. This means the xxx_printer_fn() calls must be fixed
327 to return DOS codepage. FIXME !! JRA.
328 ***************************************************************************/
329 void pcap_printer_fn(void (*fn)(char *, char *))
331 pstring name,comment;
337 /* only go looking if no printcap name supplied */
338 if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
340 DEBUG(0,( "No printcap file name configured!\n"));
345 if (strequal(psz, "cups")) {
349 #endif /* HAVE_CUPS */
352 if (strequal(psz, "lpstat")) {
359 if (strlocate(psz,"/qconfig"))
361 ScanQconfig_fn(psz,fn);
366 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
368 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
372 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
374 if (*line == '#' || *line == 0)
377 /* now we have a real printer line - cut it off at the first : */
378 p = strchr_m(line,':');
381 /* now find the most likely printer name and comment
382 this is pure guesswork, but it's better than nothing */
387 BOOL has_punctuation;
388 if ((q = strchr_m(p,'|'))) *q++ = 0;
390 has_punctuation = (strchr_m(p,' ') || strchr_m(p,'\t') || strchr_m(p,'(') || strchr_m(p,')'));
392 if (strlen(p)>strlen(comment) && has_punctuation)
394 StrnCpy(comment,p,sizeof(comment)-1);
398 if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation)
400 if (!*comment) pstrcpy(comment,name);
405 if (!strchr_m(comment,' ') &&
406 strlen(p) > strlen(comment))
408 StrnCpy(comment,p,sizeof(comment)-1);
414 name[MAXPRINTERLEN] = 0;