First round of merging various UUID structures.
[Samba/gebeck_regimport.git] / source3 / printing / pcap.c
bloba5fb53a320dca01f7f180d3a93b95f9f4d873f85
1 /*
2 Unix SMB/CIFS implementation.
3 printcap parsing
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
37 * databases etc).
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
46 * printcap entry.
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"
60 * in smb.conf.
63 #include "includes.h"
65 #ifdef AIX
66 /* ******************************************
67 Extend for AIX system and qconfig file
68 from 'boulard@univ-rennes1.fr
69 ****************************************** */
70 static int strlocate(char *xpLine,char *xpS)
72 int iS,iL,iRet;
73 char *p;
74 iS = strlen(xpS);
75 iL = strlen(xpLine);
77 iRet = 0;
78 p = xpLine;
79 while (iL >= iS)
81 if (strncmp(p,xpS,iS) == 0) {iRet =1;break;};
82 p++;
83 iL--;
85 /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/
87 return(iRet);
91 /* ******************************************************************* */
92 /* * Scan qconfig and search all virtual printer (device printer) * */
93 /* ******************************************************************* */
94 static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *))
96 int iEtat;
97 XFILE *pfile;
98 char *line,*p;
99 pstring name,comment;
100 line = NULL;
101 *name = 0;
102 *comment = 0;
104 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
106 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
107 return;
110 iEtat = 0;
111 /* scan qconfig file for searching <printername>: */
112 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
114 if (*line == '*' || *line == 0)
115 continue;
116 switch (iEtat)
118 case 0: /* locate an entry */
119 if (*line == '\t' || *line == ' ') continue;
120 if ((p=strchr_m(line,':')))
122 *p = '\0';
123 p = strtok(line,":");
124 if (strcmp(p,"bsh")!=0)
126 pstrcpy(name,p);
127 iEtat = 1;
128 continue;
131 break;
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 ??? */
138 fn(name,comment);
139 iEtat = 0;
140 continue;
143 if (strlocate(line,"backend"))
145 /* it's a device, not a virtual printer*/
146 iEtat = 0;
148 else if (strlocate(line,"device"))
150 /* it's a good virtual printer */
151 fn(name,comment);
152 iEtat = 0;
153 continue;
155 break;
158 x_fclose(pfile);
161 /* Scan qconfig file and locate de printername */
163 static BOOL ScanQconfig(char *psz,char *pszPrintername)
165 int iLg,iEtat;
166 XFILE *pfile;
167 char *pName;
168 char *line;
170 pName = NULL;
171 line = NULL;
172 if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0))
173 pName = malloc(iLg+10);
174 if (pName == NULL)
176 DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername));
177 return(False);
179 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
181 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
182 SAFE_FREE(pName);
183 return(False);
185 slprintf(pName, iLg + 9, "%s:",pszPrintername);
186 iLg = strlen(pName);
187 /*DEBUG(3,( " Looking for entry %s\n",pName));*/
188 iEtat = 0;
189 /* scan qconfig file for searching <printername>: */
190 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
192 if (*line == '*' || *line == 0)
193 continue;
194 switch (iEtat)
196 case 0: /* scanning entry */
197 if (strncmp(line,pName,iLg) == 0)
199 iEtat = 1;
200 continue;
202 break;
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 ??? */
209 free (line);
210 SAFE_FREE(pName);
211 x_fclose(pfile);
212 return(True);
215 if (strlocate(line,"backend"))
217 /* it's a device, not a virtual printer*/
218 iEtat = 0;
220 else if (strlocate(line,"device"))
222 /* it's a good virtual printer */
223 free (line);
224 SAFE_FREE(pName);
225 x_fclose(pfile);
226 return(True);
228 break;
231 free (pName);
232 x_fclose(pfile);
233 return(False);
235 #endif /* AIX */
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)
246 char *line=NULL;
247 const char *psz;
248 char *p,*q;
249 XFILE *pfile;
251 if (pszPrintername == NULL || pszPrintername[0] == '\0')
253 DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
254 return(False);
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"));
262 return(False);
265 #ifdef HAVE_CUPS
266 if (strequal(psz, "cups"))
267 return (cups_printername_ok(pszPrintername));
268 #endif /* HAVE_CUPS */
270 #ifdef SYSV
271 if (strequal(psz, "lpstat"))
272 return (sysv_printername_ok(pszPrintername));
273 #endif
275 #ifdef AIX
276 if (strlocate(psz,"/qconfig"))
277 return(ScanQconfig(psz,pszPrintername));
278 #endif
280 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
282 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
283 return(False);
286 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
288 if (*line == '#' || *line == 0)
289 continue;
291 /* now we have a real printer line - cut it off at the first : */
292 p = strchr_m(line,':');
293 if (p) *p = 0;
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 */
297 for (p=line; p; p=q)
299 if ((q = strchr_m(p,'|'))) *q++ = 0;
301 if (strequal(p,pszPrintername))
303 SAFE_FREE(line);
304 x_fclose(pfile);
305 return(True);
307 p = q;
311 x_fclose(pfile);
312 return(False);
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;
325 char *line;
326 char *psz;
327 char *p,*q;
328 XFILE *pfile;
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"));
334 return;
337 #ifdef HAVE_CUPS
338 if (strequal(psz, "cups")) {
339 cups_printer_fn(fn);
340 return;
342 #endif /* HAVE_CUPS */
344 #ifdef SYSV
345 if (strequal(psz, "lpstat")) {
346 sysv_printer_fn(fn);
347 return;
349 #endif
351 #ifdef AIX
352 if (strlocate(psz,"/qconfig"))
354 ScanQconfig_fn(psz,fn);
355 return;
357 #endif
359 if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)
361 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
362 return;
365 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); safe_free(line))
367 if (*line == '#' || *line == 0)
368 continue;
370 /* now we have a real printer line - cut it off at the first : */
371 p = strchr_m(line,':');
372 if (p) *p = 0;
374 /* now find the most likely printer name and comment
375 this is pure guesswork, but it's better than nothing */
376 *name = 0;
377 *comment = 0;
378 for (p=line; p; p=q)
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)
387 pstrcpy(comment,p);
388 continue;
391 if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation)
393 if (!*comment) pstrcpy(comment,name);
394 pstrcpy(name,p);
395 continue;
398 if (!strchr_m(comment,' ') &&
399 strlen(p) > strlen(comment))
401 pstrcpy(comment,p);
402 continue;
406 comment[60] = 0;
407 name[MAXPRINTERLEN] = 0;
409 if (*name)
410 fn(name,comment);
412 x_fclose(pfile);