ftp.nice.ch/pub/next/unix/disk/SambaManager.1.0.NIHS.s.tar.gz#/SambaManager/samba-1.9.17p4/source/pcap.c

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.