Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / samba / source / printing / pcap.c
blob62010706bb3abe30139050f00df44eb435bb6296
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 printcap parsing
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 Modified for CUPS support by Michael Sweet, 1999
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 * Parse printcap file.
33 * This module does exactly one thing - it looks into the printcap file
34 * and tells callers if a specified string appears as a printer name.
36 * The way this module looks at the printcap file is very simplistic.
37 * Only the local printcap file is inspected (no searching of NIS
38 * databases etc).
40 * There are assumed to be one or more printer names per record, held
41 * as a set of sub-fields separated by vertical bar symbols ('|') in the
42 * first field of the record. The field separator is assumed to be a colon
43 * ':' and the record separator a newline.
45 * Lines ending with a backspace '\' are assumed to flag that the following
46 * line is a continuation line so that a set of lines can be read as one
47 * printcap entry.
49 * A line stating with a hash '#' is assumed to be a comment and is ignored
50 * Comments are discarded before the record is strung together from the
51 * set of continuation lines.
53 * Opening a pipe for "lpc status" and reading that would probably
54 * be pretty effective. Code to do this already exists in the freely
55 * distributable PCNFS server code.
57 * Modified to call SVID/XPG4 support if printcap name is set to "lpstat"
58 * in smb.conf under Solaris.
60 * Modified to call CUPS support if printcap name is set to "cups"
61 * in smb.conf.
64 #include "includes.h"
66 #include "smb.h"
68 extern int DEBUGLEVEL;
70 #ifdef AIX
71 /* ******************************************
72 Extend for AIX system and qconfig file
73 from 'boulard@univ-rennes1.fr
74 ****************************************** */
75 static int strlocate(char *xpLine,char *xpS)
77 int iS,iL,iRet;
78 char *p;
79 iS = strlen(xpS);
80 iL = strlen(xpLine);
82 iRet = 0;
83 p = xpLine;
84 while (iL >= iS)
86 if (strncmp(p,xpS,iS) == 0) {iRet =1;break;};
87 p++;
88 iL--;
90 /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/
92 return(iRet);
96 /* ******************************************************************* */
97 /* * Scan qconfig and search all virtual printer (device printer) * */
98 /* ******************************************************************* */
99 static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *))
101 int iEtat;
102 FILE *pfile;
103 char *line,*p;
104 pstring name,comment;
105 line = NULL;
106 *name = 0;
107 *comment = 0;
109 if ((pfile = sys_fopen(psz, "r")) == NULL)
111 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
112 return;
115 iEtat = 0;
116 /* scan qconfig file for searching <printername>: */
117 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
119 if (*line == '*' || *line == 0)
120 continue;
121 switch (iEtat)
123 case 0: /* locate an entry */
124 if (*line == '\t' || *line == ' ') continue;
125 if ((p=strchr(line,':')))
127 *p = '\0';
128 p = strtok(line,":");
129 if (strcmp(p,"bsh")!=0)
131 pstrcpy(name,p);
132 iEtat = 1;
133 continue;
136 break;
137 case 1: /* scanning device stanza */
138 if (*line == '*' || *line == 0) continue;
139 if (*line != '\t' && *line != ' ')
141 /* name is found without stanza device */
142 /* probably a good printer ??? */
143 fn(name,comment);
144 iEtat = 0;
145 continue;
148 if (strlocate(line,"backend"))
150 /* it's a device, not a virtual printer*/
151 iEtat = 0;
153 else if (strlocate(line,"device"))
155 /* it's a good virtual printer */
156 fn(name,comment);
157 iEtat = 0;
158 continue;
160 break;
163 fclose(pfile);
166 /* Scan qconfig file and locate de printername */
168 static BOOL ScanQconfig(char *psz,char *pszPrintername)
170 int iLg,iEtat;
171 FILE *pfile;
172 char *pName;
173 char *line;
175 pName = NULL;
176 line = NULL;
177 if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0))
178 pName = malloc(iLg+10);
179 if (pName == NULL)
181 DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername));
182 return(False);
184 if ((pfile = sys_fopen(psz, "r")) == NULL)
186 DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz));
187 free(pName);
188 return(False);
190 slprintf(pName, iLg + 9, "%s:",pszPrintername);
191 iLg = strlen(pName);
192 /*DEBUG(3,( " Looking for entry %s\n",pName));*/
193 iEtat = 0;
194 /* scan qconfig file for searching <printername>: */
195 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
197 if (*line == '*' || *line == 0)
198 continue;
199 switch (iEtat)
201 case 0: /* scanning entry */
202 if (strncmp(line,pName,iLg) == 0)
204 iEtat = 1;
205 continue;
207 break;
208 case 1: /* scanning device stanza */
209 if (*line == '*' || *line == 0) continue;
210 if (*line != '\t' && *line != ' ')
212 /* name is found without stanza device */
213 /* probably a good printer ??? */
214 free (line);
215 free(pName);
216 fclose(pfile);
217 return(True);
220 if (strlocate(line,"backend"))
222 /* it's a device, not a virtual printer*/
223 iEtat = 0;
225 else if (strlocate(line,"device"))
227 /* it's a good virtual printer */
228 free (line);
229 free(pName);
230 fclose(pfile);
231 return(True);
233 break;
236 free (pName);
237 fclose(pfile);
238 return(False);
240 #endif /* AIX */
243 /***************************************************************************
244 Scan printcap file pszPrintcapname for a printer called pszPrintername.
245 Return True if found, else False. Returns False on error, too, after logging
246 the error at level 0. For generality, the printcap name may be passed - if
247 passed as NULL, the configuration will be queried for the name.
248 ***************************************************************************/
249 BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
251 char *line=NULL;
252 char *psz;
253 char *p,*q;
254 FILE *pfile;
256 if (pszPrintername == NULL || pszPrintername[0] == '\0')
258 DEBUG(0,( "Attempt to locate null printername! Internal error?\n"));
259 return(False);
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"));
267 return(False);
270 #ifdef HAVE_LIBCUPS
271 if (strequal(psz, "cups"))
272 return (cups_printername_ok(pszPrintername));
273 #endif /* HAVE_LIBCUPS */
275 #ifdef SYSV
276 if (strequal(psz, "lpstat"))
277 return (sysv_printername_ok(pszPrintername));
278 #endif
280 #ifdef AIX
281 if (strlocate(psz,"/qconfig"))
282 return(ScanQconfig(psz,pszPrintername));
283 #endif
285 if ((pfile = sys_fopen(psz, "r")) == NULL)
287 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
288 return(False);
291 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
293 if (*line == '#' || *line == 0)
294 continue;
296 /* now we have a real printer line - cut it off at the first : */
297 p = strchr(line,':');
298 if (p) *p = 0;
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 */
302 for (p=line; p; p=q)
304 if ((q = strchr(p,'|'))) *q++ = 0;
306 if (strequal(p,pszPrintername))
308 /* normalise the case */
309 pstrcpy(pszPrintername,p);
310 free(line);
311 fclose(pfile);
312 return(True);
314 p = q;
318 fclose(pfile);
319 return(False);
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)
326 ***************************************************************************/
327 void pcap_printer_fn(void (*fn)(char *, char *))
329 pstring name,comment;
330 char *line;
331 char *psz;
332 char *p,*q;
333 FILE *pfile;
335 /* only go looking if no printcap name supplied */
336 if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0'))
338 DEBUG(0,( "No printcap file name configured!\n"));
339 return;
342 #ifdef HAVE_LIBCUPS
343 if (strequal(psz, "cups")) {
344 cups_printer_fn(fn);
345 return;
347 #endif /* HAVE_LIBCUPS */
349 #ifdef SYSV
350 if (strequal(psz, "lpstat")) {
351 sysv_printer_fn(fn);
352 return;
354 #endif
356 #ifdef AIX
357 if (strlocate(psz,"/qconfig"))
359 ScanQconfig_fn(psz,fn);
360 return;
362 #endif
364 if ((pfile = sys_fopen(psz, "r")) == NULL)
366 DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
367 return;
370 for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line))
372 if (*line == '#' || *line == 0)
373 continue;
375 /* now we have a real printer line - cut it off at the first : */
376 p = strchr(line,':');
377 if (p) *p = 0;
379 /* now find the most likely printer name and comment
380 this is pure guesswork, but it's better than nothing */
381 *name = 0;
382 *comment = 0;
383 for (p=line; p; p=q)
385 BOOL has_punctuation;
386 if ((q = strchr(p,'|'))) *q++ = 0;
388 has_punctuation = (strchr(p,' ') || strchr(p,'(') || strchr(p,')'));
390 if (strlen(p)>strlen(comment) && has_punctuation)
392 StrnCpy(comment,p,sizeof(comment)-1);
393 continue;
396 if (strlen(p) <= MAXPRINTERLEN && strlen(p)>strlen(name) && !has_punctuation)
398 if (!*comment) pstrcpy(comment,name);
399 pstrcpy(name,p);
400 continue;
403 if (!strchr(comment,' ') &&
404 strlen(p) > strlen(comment))
406 StrnCpy(comment,p,sizeof(comment)-1);
407 continue;
411 comment[60] = 0;
412 name[MAXPRINTERLEN] = 0;
414 if (*name)
415 fn(name,comment);
417 fclose(pfile);