1996-05-04 07:50:46 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1996-05-04 07:50:46 +00:00
printcap parsing
1998-01-22 13:27:43 +00:00
Copyright ( C ) Karl Auer 1993 - 1998
1996-05-04 07:50:46 +00:00
Re - working by Martin Kiff , 1994
Re - written again by Andrew Tridgell
1997-12-03 05:08:07 +00:00
Modified for SVID support by Norm Jacobs , 1997
1999-12-13 13:27:58 +00:00
Modified for CUPS support by Michael Sweet , 1999
1996-05-04 07:50:46 +00:00
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
2007-07-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 07:50:46 +00:00
( 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
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 07:50:46 +00:00
*/
/*
2005-01-05 16:20:35 +00:00
* This module contains code to parse and cache printcap data , possibly
* in concert with the CUPS / SYSV / AIX - specific code found elsewhere .
1996-05-04 07:50:46 +00:00
*
* 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 .
1997-12-03 05:08:07 +00:00
*
* Modified to call SVID / XPG4 support if printcap name is set to " lpstat "
* in smb . conf under Solaris .
1999-12-13 13:27:58 +00:00
*
* Modified to call CUPS support if printcap name is set to " cups "
* in smb . conf .
2005-09-20 23:28:22 +00:00
*
* Modified to call iPrint support if printcap name is set to " iprint "
* in smb . conf .
1996-05-04 07:50:46 +00:00
*/
# include "includes.h"
2005-01-05 16:20:35 +00:00
2008-10-10 11:55:14 -07:00
struct pcap_cache {
2005-01-05 16:20:35 +00:00
char * name ;
char * comment ;
struct pcap_cache * next ;
2008-10-10 11:55:14 -07:00
} ;
2005-01-05 16:20:35 +00:00
2008-10-10 11:55:14 -07:00
/* The systemwide printcap cache. */
static struct pcap_cache * pcap_cache = NULL ;
2005-01-05 16:20:35 +00:00
2008-10-10 11:55:14 -07:00
bool pcap_cache_add_specific ( struct pcap_cache * * ppcache , const char * name , const char * comment )
1996-05-04 07:50:46 +00:00
{
2008-10-10 11:55:14 -07:00
struct pcap_cache * p ;
2005-01-05 16:20:35 +00:00
2008-10-10 11:55:14 -07:00
if ( name = = NULL | | ( ( p = SMB_MALLOC_P ( struct pcap_cache ) ) = = NULL ) )
return false ;
2005-01-05 16:20:35 +00:00
p - > name = SMB_STRDUP ( name ) ;
p - > comment = ( comment & & * comment ) ? SMB_STRDUP ( comment ) : NULL ;
2008-10-10 11:55:14 -07:00
DEBUG ( 11 , ( " pcap_cache_add_specific: Adding name %s info %s \n " ,
p - > name , p - > comment ? p - > comment : " " ) ) ;
p - > next = * ppcache ;
* ppcache = p ;
2005-01-05 16:20:35 +00:00
2008-10-10 11:55:14 -07:00
return true ;
1996-05-04 07:50:46 +00:00
}
2005-01-05 16:20:35 +00:00
2008-10-10 11:55:14 -07:00
void pcap_cache_destroy_specific ( struct pcap_cache * * pp_cache )
1996-05-04 07:50:46 +00:00
{
2008-10-10 11:55:14 -07:00
struct pcap_cache * p , * next ;
1996-05-04 07:50:46 +00:00
2008-10-10 11:55:14 -07:00
for ( p = * pp_cache ; p ! = NULL ; p = next ) {
2005-01-05 16:20:35 +00:00
next = p - > next ;
SAFE_FREE ( p - > name ) ;
SAFE_FREE ( p - > comment ) ;
SAFE_FREE ( p ) ;
1996-05-04 07:50:46 +00:00
}
2008-10-10 11:55:14 -07:00
* pp_cache = NULL ;
}
bool pcap_cache_add ( const char * name , const char * comment )
{
return pcap_cache_add_specific ( & pcap_cache , name , comment ) ;
1996-05-04 07:50:46 +00:00
}
2007-10-18 17:40:25 -07:00
bool pcap_cache_loaded ( void )
1996-05-04 07:50:46 +00:00
{
2005-01-05 16:20:35 +00:00
return ( pcap_cache ! = NULL ) ;
1996-05-04 07:50:46 +00:00
}
1998-07-29 03:08:05 +00:00
2008-10-10 11:55:14 -07:00
void pcap_cache_replace ( const struct pcap_cache * pcache )
{
const struct pcap_cache * p ;
pcap_cache_destroy_specific ( & pcap_cache ) ;
for ( p = pcache ; p ; p = p - > next ) {
pcap_cache_add ( p - > name , p - > comment ) ;
}
}
2005-01-05 16:20:35 +00:00
void pcap_cache_reload ( void )
1996-05-04 07:50:46 +00:00
{
2005-01-05 16:20:35 +00:00
const char * pcap_name = lp_printcapname ( ) ;
2007-10-18 17:40:25 -07:00
bool pcap_reloaded = False ;
2008-10-10 11:55:14 -07:00
struct pcap_cache * tmp_cache = NULL ;
2005-01-05 16:20:35 +00:00
XFILE * pcap_file ;
char * pcap_line ;
DEBUG ( 3 , ( " reloading printcap cache \n " ) ) ;
/* only go looking if no printcap name supplied */
if ( pcap_name = = NULL | | * pcap_name = = 0 ) {
DEBUG ( 0 , ( " No printcap file name configured! \n " ) ) ;
return ;
}
tmp_cache = pcap_cache ;
pcap_cache = NULL ;
1997-12-03 05:08:07 +00:00
2001-08-23 19:06:20 +00:00
# ifdef HAVE_CUPS
2005-01-05 16:20:35 +00:00
if ( strequal ( pcap_name , " cups " ) ) {
pcap_reloaded = cups_cache_reload ( ) ;
goto done ;
}
# endif
1999-12-13 13:27:58 +00:00
2005-09-20 23:28:22 +00:00
# ifdef HAVE_IPRINT
if ( strequal ( pcap_name , " iprint " ) ) {
pcap_reloaded = iprint_cache_reload ( ) ;
goto done ;
}
# endif
2005-03-07 22:10:27 +00:00
# if defined(SYSV) || defined(HPUX)
2005-01-05 16:20:35 +00:00
if ( strequal ( pcap_name , " lpstat " ) ) {
pcap_reloaded = sysv_cache_reload ( ) ;
goto done ;
}
1997-12-03 05:08:07 +00:00
# endif
1996-05-04 07:50:46 +00:00
# ifdef AIX
2005-01-05 16:20:35 +00:00
if ( strstr_m ( pcap_name , " /qconfig " ) ! = NULL ) {
pcap_reloaded = aix_cache_reload ( ) ;
goto done ;
}
1996-05-04 07:50:46 +00:00
# endif
1997-12-03 05:08:07 +00:00
2005-01-05 16:20:35 +00:00
/* handle standard printcap - moved from pcap_printer_fn() */
if ( ( pcap_file = x_fopen ( pcap_name , O_RDONLY , 0 ) ) = = NULL ) {
DEBUG ( 0 , ( " Unable to open printcap file %s for read! \n " , pcap_name ) ) ;
goto done ;
}
2008-10-19 13:06:14 +02:00
for ( ; ( pcap_line = fgets_slash ( NULL , 1024 , pcap_file ) ) ! = NULL ; free ( pcap_line ) ) {
2007-11-21 13:56:36 -08:00
char name [ MAXPRINTERLEN + 1 ] ;
char comment [ 62 ] ;
2005-01-05 16:20:35 +00:00
char * p , * q ;
1996-05-04 07:50:46 +00:00
2005-01-05 16:20:35 +00:00
if ( * pcap_line = = ' # ' | | * pcap_line = = 0 )
continue ;
1996-05-04 07:50:46 +00:00
2005-01-05 16:20:35 +00:00
/* now we have a real printer line - cut at the first : */
if ( ( p = strchr_m ( pcap_line , ' : ' ) ) ! = NULL )
* p = 0 ;
1996-05-04 07:50:46 +00:00
2005-01-05 16:20:35 +00:00
/*
* now find the most likely printer name and comment
* this is pure guesswork , but it ' s better than nothing
*/
for ( * name = * comment = 0 , p = pcap_line ; p ! = NULL ; p = q ) {
2007-10-18 17:40:25 -07:00
bool has_punctuation ;
2005-01-05 16:20:35 +00:00
if ( ( q = strchr_m ( p , ' | ' ) ) ! = NULL )
* q + + = 0 ;
has_punctuation = ( strchr_m ( p , ' ' ) | |
strchr_m ( p , ' \t ' ) | |
strchr_m ( p , ' ( ' ) | |
strchr_m ( p , ' ) ' ) ) ;
if ( strlen ( p ) > strlen ( comment ) & & has_punctuation ) {
2007-11-21 13:56:36 -08:00
strlcpy ( comment , p , sizeof ( comment ) ) ;
2005-01-05 16:20:35 +00:00
continue ;
}
if ( strlen ( p ) < = MAXPRINTERLEN & &
strlen ( p ) > strlen ( name ) & & ! has_punctuation ) {
2007-11-21 13:56:36 -08:00
if ( ! * comment ) {
strlcpy ( comment , name , sizeof ( comment ) ) ;
}
strlcpy ( name , p , sizeof ( name ) ) ;
2005-01-05 16:20:35 +00:00
continue ;
}
if ( ! strchr_m ( comment , ' ' ) & &
strlen ( p ) > strlen ( comment ) ) {
2007-11-21 13:56:36 -08:00
strlcpy ( comment , p , sizeof ( comment ) ) ;
2005-01-05 16:20:35 +00:00
continue ;
}
}
comment [ 60 ] = 0 ;
name [ MAXPRINTERLEN ] = 0 ;
if ( * name & & ! pcap_cache_add ( name , comment ) ) {
x_fclose ( pcap_file ) ;
goto done ;
}
1996-05-04 07:50:46 +00:00
}
2005-01-05 16:20:35 +00:00
x_fclose ( pcap_file ) ;
pcap_reloaded = True ;
done :
DEBUG ( 3 , ( " reload status: %s \n " , ( pcap_reloaded ) ? " ok " : " error " ) ) ;
if ( pcap_reloaded )
2008-10-10 11:55:14 -07:00
pcap_cache_destroy_specific ( & tmp_cache ) ;
2005-01-05 16:20:35 +00:00
else {
2008-10-10 11:55:14 -07:00
pcap_cache_destroy_specific ( & pcap_cache ) ;
2005-01-05 16:20:35 +00:00
pcap_cache = tmp_cache ;
}
return ;
1996-05-04 07:50:46 +00:00
}
2007-10-18 17:40:25 -07:00
bool pcap_printername_ok ( const char * printername )
2005-01-05 16:20:35 +00:00
{
2008-10-10 11:55:14 -07:00
struct pcap_cache * p ;
2005-01-05 16:20:35 +00:00
for ( p = pcap_cache ; p ! = NULL ; p = p - > next )
if ( strequal ( p - > name , printername ) )
return True ;
return False ;
}
1996-05-04 07:50:46 +00:00
/***************************************************************************
2008-10-10 11:55:14 -07:00
run a function on each printer name in the printcap file .
1996-05-04 07:50:46 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-10 11:55:14 -07:00
void pcap_printer_fn_specific ( const struct pcap_cache * pc ,
void ( * fn ) ( const char * , const char * , void * ) ,
void * pdata )
1996-05-04 07:50:46 +00:00
{
2008-10-10 11:55:14 -07:00
const struct pcap_cache * p ;
1996-05-04 07:50:46 +00:00
2008-10-10 11:55:14 -07:00
for ( p = pc ; p ! = NULL ; p = p - > next )
fn ( p - > name , p - > comment , pdata ) ;
1996-05-04 07:50:46 +00:00
2005-01-05 16:20:35 +00:00
return ;
1996-05-04 07:50:46 +00:00
}
2008-10-10 11:55:14 -07:00
void pcap_printer_fn ( void ( * fn ) ( const char * , const char * , void * ) , void * pdata )
{
2008-10-12 10:38:55 +02:00
pcap_printer_fn_specific ( pcap_cache , fn , pdata ) ;
2008-10-10 11:55:14 -07:00
}