This is pcap.c in view mode; [Download] [Up]
/* Unix SMB/Netbios implementation. Version 1.9. printcap parsing Copyright (C) Karl Auer 1993-1997 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" 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. ***************************************************************************/ #ifdef USE_NETINFO BOOL pcap_file_printername_ok(char *pszPrintername, char *pszPrintcapname); BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname) { /* * The code to use when accesssing netinfo on NEXTSTEP/OPENSTEP * This file is included in ../pcap.c. */ ni_status status; ni_name name; ni_id ndir; ni_idlist ndirs; void *handle; ni_proplist props; int i,j,k; DEBUG(10, ("get_smbpwnam: opening netinfo for samba printers.\n")); /* * Scan the NetInfo hierarchy, starting from the local level, * until either an entry is found or we are past the top level. */ handle = NULL; status = ni_search_for_dir(S_PRINTERDIR, ".", &handle, &ndir, 5, 0, 1); while (status == NI_OK) { /* Read the directory and all its subdirectories. */ status = ni_children(handle, &ndir, &ndirs); if (status != NI_OK) { ni_free(handle); DEBUG(0, ("Unable to get netinfo entries for printers.\n")); return; } /* * For each subdirectory, scan the properties for the S_PRINTERNBNAME property. * If any is present, compare to the name passed. */ for (k = 0; k < ndirs.ni_idlist_len; k++) { /* Read the directory and all its properties, set the indexes. */ ndir.nii_object = ndirs.ni_idlist_val[k]; status = ni_read(handle, &ndir, &props); if (status != NI_OK) { DEBUG(0, ("Unable to get netinfo entries for printer with ID %d.\n", ndirs.ni_idlist_val[i])); continue; } name = NULL; for (i = 0; i < props.ni_proplist_len; i++) { if (!strcmp(PWENTNAME(i), S_PRINTERNBNAME)) name = PWENTVALU(i); } if ((name != NULL) && (strequal(name, pszPrintername))) { /* return the name! */ strcpy(pszPrintername, name); ni_proplist_free(&props); ni_idlist_free(&ndirs); ni_free(handle); return(True); } ni_proplist_free(&props); } ni_idlist_free(&ndirs); status = ni_search_for_dir(S_PRINTERDIR, "..", &handle, &ndir, 5, 0, 1); } if (strcmp("netinfo", pszPrintcapname)) { DEBUG(0, ("No Entry found in NetInfo. Trying flatfile %s.\n", pszPrintcapname)); return pcap_file_printername_ok(pszPrintername, pszPrintcapname); } return(False); } #define pcap_printername_ok pcap_file_printername_ok #endif /* USE_NETINFO */ 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 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) ***************************************************************************/ #ifdef USE_NETINFO void pcap_file_printer_fn(void (*fn)()); void pcap_printer_fn(void (*fn)()) { ni_status status; ni_name name, nbname, comment, driver, printcom, lprmcom, lpqcom, lpresumecom, lppausecom; ni_id ndir; ni_idlist ndirs; void *handle; ni_proplist props; int i,j,k; DEBUG(10, ("get_smbpwnam: opening netinfo for samba printers.\n")); /* * Scan the NetInfo hierarchy, starting from the local level, * until either an entry is found or we are past the top level. */ handle = NULL; status = ni_search_for_dir(S_PRINTERDIR, ".", &handle, &ndir, 5, 0, 1); while (status == NI_OK) { /* Read the directory and all its subdirectories. */ status = ni_children(handle, &ndir, &ndirs); if (status != NI_OK) { ni_free(handle); DEBUG(0, ("Unable to get netinfo entries for printers.\n")); return; } /* * For each subdirectory, scan the properties for the S_PRINTERNBNAME property. * If any is present, compare to the name passed. */ for (k = 0; k < ndirs.ni_idlist_len; k++) { /* Read the directory and all its properties, set the indexes. */ ndir.nii_object = ndirs.ni_idlist_val[k]; status = ni_read(handle, &ndir, &props); if (status != NI_OK) { DEBUG(0, ("Unable to get netinfo entries for printer with ID %d.\n", ndirs.ni_idlist_val[i])); continue; } name = NULL; nbname = NULL; comment = "From NetInfo"; driver = NULL; printcom = NULL; lprmcom = NULL; lpqcom = NULL; lpresumecom = NULL; lppausecom = NULL; for (i = 0; i < props.ni_proplist_len; i++) { if (!strcmp(PWENTNAME(i), S_PRINTERRNAME)) name = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_PRINTERNBNAME)) nbname = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_PRINTERCOMMENT)) comment = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_PRINTERDRIVER)) driver = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_PRINTCOMMAND)) printcom = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_LPRMCOMMAND)) lprmcom = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_LPQCOMMAND)) lpqcom = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_LPRESUMECOMMAND)) lpresumecom = PWENTVALU(i); else if (!strcmp(PWENTNAME(i), S_LPPAUSECOMMAND)) lppausecom = PWENTVALU(i); } if (nbname != NULL) fn(nbname, name, comment, driver, printcom, lprmcom, lpqcom, lpresumecom, lppausecom); ni_proplist_free(&props); } ni_idlist_free(&ndirs); status = ni_search_for_dir(S_PRINTERDIR, "..", &handle, &ndir, 5, 0, 1); } if (strcmp("netinfo", lp_printcapname())) pcap_file_printer_fn(fn); } #define pcap_printer_fn pcap_file_printer_fn #endif void pcap_printer_fn(void (*fn)()) { pstring name,comment; char *line; char *psz; char *p,*q; FILE *pfile; /* only go looking if 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) pstrcpy(comment,name); pstrcpy(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, name, comment, NULL, NULL, NULL, NULL, NULL, NULL); } fclose(pfile); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.