diff options
Diffstat (limited to 'source3/printing/pcap.c')
-rw-r--r-- | source3/printing/pcap.c | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c new file mode 100644 index 0000000000..8973b1627f --- /dev/null +++ b/source3/printing/pcap.c @@ -0,0 +1,383 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + printcap parsing + Copyright (C) Karl Auer 1993,1994 + + Re-working by Martin Kiff, 1994 + + Re-written again by Andrew Tridgell + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * Parse printcap file. + * + * This module does exactly one thing - it looks into the printcap file + * and tells callers if a specified string appears as a printer name. + * + * The way this module looks at the printcap file is very simplistic. + * Only the local printcap file is inspected (no searching of NIS + * databases etc). + * + * There are assumed to be one or more printer names per record, held + * as a set of sub-fields separated by vertical bar symbols ('|') in the + * first field of the record. The field separator is assumed to be a colon + * ':' and the record separator a newline. + * + * Lines ending with a backspace '\' are assumed to flag that the following + * line is a continuation line so that a set of lines can be read as one + * printcap entry. + * + * A line stating with a hash '#' is assumed to be a comment and is ignored + * Comments are discarded before the record is strung together from the + * set of continuation lines. + * + * Opening a pipe for "lpc status" and reading that would probably + * be pretty effective. Code to do this already exists in the freely + * distributable PCNFS server code. + */ + +#include "includes.h" + +#include "smb.h" +#include "loadparm.h" +#include "pcap.h" + +extern int DEBUGLEVEL; + +#ifdef AIX +/* ****************************************** + Extend for AIX system and qconfig file + from 'boulard@univ-rennes1.fr + ****************************************** */ +static int strlocate(char *xpLine,char *xpS) +{ + int iS,iL,i,iRet; + char *p; + iS = strlen(xpS); + iL = strlen(xpLine); + + iRet = 0; + p = xpLine; + while (iL >= iS) + { + if (strncmp(p,xpS,iS) == 0) {iRet =1;break;}; + p++; + iL--; + } + /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/ + + return(iRet); +} + + +/* ******************************************************************* */ +/* * Scan qconfig and search all virtual printer (device printer) * */ +/* ******************************************************************* */ +static void ScanQconfig_fn(char *psz,void (*fn)()) +{ + int iLg,iEtat; + FILE *pfile; + char *line,*p; + pstring name,comment; + line = NULL; + *name = 0; + *comment = 0; + + if ((pfile = fopen(psz, "r")) == NULL) + { + DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); + return; + } + + iEtat = 0; + /* scan qconfig file for searching <printername>: */ + for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) + { + if (*line == '*' || *line == 0) + continue; + switch (iEtat) + { + case 0: /* locate an entry */ + if (*line == '\t' || *line == ' ') continue; + if ((p=strchr(line,':'))) + { + *p = '\0'; + p = strtok(line,":"); + if (strcmp(p,"bsh")!=0) + { + strcpy(name,p); + iEtat = 1; + continue; + } + } + break; + case 1: /* scanning device stanza */ + if (*line == '*' || *line == 0) continue; + if (*line != '\t' && *line != ' ') + { + /* name is found without stanza device */ + /* probably a good printer ??? */ + fn(name,comment); + iEtat = 0; + continue; + } + + if (strlocate(line,"backend")) + { + /* it's a device, not a virtual printer*/ + iEtat = 0; + } + else if (strlocate(line,"device")) + { + /* it's a good virtual printer */ + fn(name,comment); + iEtat = 0; + continue; + } + break; + } + } + fclose(pfile); +} + +/* Scan qconfig file and locate de printername */ + +static BOOL ScanQconfig(char *psz,char *pszPrintername) +{ + int iLg,iEtat; + FILE *pfile; + char *pName; + char *line; + + pName = NULL; + line = NULL; + if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0)) + pName = malloc(iLg+10); + if (pName == NULL) + { + DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername)); + return(False); + } + if ((pfile = fopen(psz, "r")) == NULL) + { + DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); + free(pName); + return(False); + } + sprintf(pName,"%s:",pszPrintername); + iLg = strlen(pName); + /*DEBUG(3,( " Looking for entry %s\n",pName));*/ + iEtat = 0; + /* scan qconfig file for searching <printername>: */ + for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) + { + if (*line == '*' || *line == 0) + continue; + switch (iEtat) + { + case 0: /* scanning entry */ + if (strncmp(line,pName,iLg) == 0) + { + iEtat = 1; + continue; + } + break; + case 1: /* scanning device stanza */ + if (*line == '*' || *line == 0) continue; + if (*line != '\t' && *line != ' ') + { + /* name is found without stanza device */ + /* probably a good printer ??? */ + free (line); + free(pName); + fclose(pfile); + return(True); + } + + if (strlocate(line,"backend")) + { + /* it's a device, not a virtual printer*/ + iEtat = 0; + } + else if (strlocate(line,"device")) + { + /* it's a good virtual printer */ + free (line); + free(pName); + fclose(pfile); + return(True); + } + break; + } + } + free (pName); + fclose(pfile); + return(False); +} + +#endif +/*************************************************************************** +Scan printcap file pszPrintcapname for a printer called pszPrintername. +Return True if found, else False. Returns False on error, too, after logging +the error at level 0. For generality, the printcap name may be passed - if +passed as NULL, the configuration will be queried for the name. +***************************************************************************/ +BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname) +{ + char *line=NULL; + char *psz; + char *p,*q; + FILE *pfile; + + if (pszPrintername == NULL || pszPrintername[0] == '\0') + { + DEBUG(0,( "Attempt to locate null printername! Internal error?\n")); + return(False); + } + + /* only go looking if no printcap name supplied */ + if ((psz = pszPrintcapname) == NULL || psz[0] == '\0') + if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) + { + DEBUG(0,( "No printcap file name configured!\n")); + return(False); + } +#ifdef AIX + if (strlocate(psz,"/qconfig") != NULL) + return(ScanQconfig(psz,pszPrintername)); +#endif + if ((pfile = fopen(psz, "r")) == NULL) + { + DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); + return(False); + } + + for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) + { + if (*line == '#' || *line == 0) + continue; + + /* now we have a real printer line - cut it off at the first : */ + p = strchr(line,':'); + if (p) *p = 0; + + /* now just check if the name is in the list */ + /* NOTE: I avoid strtok as the fn calling this one may be using it */ + for (p=line; p; p=q) + { + if ((q = strchr(p,'|'))) *q++ = 0; + + if (strequal(p,pszPrintername)) + { + /* normalise the case */ + strcpy(pszPrintername,p); + free(line); + fclose(pfile); + return(True); + } + p = q; + } + } + + + fclose(pfile); + return(False); +} + + +/*************************************************************************** +run a function on each printer name in the printcap file. The function is +passed the primary name and the comment (if possible) +***************************************************************************/ +void pcap_printer_fn(void (*fn)()) +{ + pstring name,comment; + char *line; + char *psz; + char *p,*q; + FILE *pfile; + + /* only go looking if no printcap name supplied */ + if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) + { + DEBUG(0,( "No printcap file name configured!\n")); + return; + } + +#ifdef AIX + if (strlocate(psz,"/qconfig") != NULL) + { + ScanQconfig_fn(psz,fn); + return; + } +#endif + if ((pfile = fopen(psz, "r")) == NULL) + { + DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); + return; + } + + for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) + { + if (*line == '#' || *line == 0) + continue; + + /* now we have a real printer line - cut it off at the first : */ + p = strchr(line,':'); + if (p) *p = 0; + + /* now find the most likely printer name and comment + this is pure guesswork, but it's better than nothing */ + *name = 0; + *comment = 0; + for (p=line; p; p=q) + { + BOOL has_punctuation; + if ((q = strchr(p,'|'))) *q++ = 0; + + has_punctuation = (strchr(p,' ') || strchr(p,'(') || strchr(p,')')); + + if (strlen(p)>strlen(comment) && has_punctuation) + { + StrnCpy(comment,p,sizeof(comment)-1); + continue; + } + + if (strlen(p) <= 8 && strlen(p)>strlen(name) && !has_punctuation) + { + if (!*comment) strcpy(comment,name); + strcpy(name,p); + continue; + } + + if (!strchr(comment,' ') && + strlen(p) > strlen(comment)) + { + StrnCpy(comment,p,sizeof(comment)-1); + continue; + } + } + + comment[60] = 0; + name[8] = 0; + + if (*name) + fn(name,comment); + } + fclose(pfile); +} |