import sys, string, SambaParm
from smbparm import parm_table
######################################################################
##
## smb.conf parser class
##
## Copyright (C) Gerald Carter 2004.
##
## 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 3 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, see .
##
######################################################################
#####################################################################
## multi line Samba comment
class SambaComment:
def __init__( self, comment ):
self.comment = comment
def Dump( self, stream, whitespace=None ):
if not self.comment:
return
for line in self.comment:
if whitespace:
stream.write( whitespace )
stream.write( line )
stream.write( "\n" )
#####################################################################
## string smb.conf parms
class SambaParameter :
## indexs into the parm table tuples
DisplayName = 0
ObjectType = 1
DefaultValue = 2
Scope = 3
## Stores a key into the parm_table and creates an
## SambaParmXXX object to store the value
def __init__( self, name, value, comment=None ):
self.key = string.upper(string.strip(name))
self.comment = None
assert parm_table.has_key( self.key ), "Bad parameter name! [%s]" % name
self.parm = parm_table[self.key][self.ObjectType]( value )
if comment :
self.comment = SambaComment( comment )
#if not self.parm.valid:
# self.parm.SetValue( parm_table[self.key][self.DefaultValue] )
## simple test for global or service parameter scope
def isGlobalParm( self ) :
return parm_table[self.key][Scope]
## dump 1` character so setup the result
if not result:
result = ""
## Check for comments -- terminated by \n -- no continuation
if input_str[0] == '#' or input_str[0] == ';' :
result = input_str
break
## check for line continuation
if input_str[-1] == "\\" :
result += input_str[0:-1]
contine
## otherwise we have a complete line
result += input_str
break
return result
## convert the parameter name to a form suitable as a dictionary key
def NormalizeParamName( self, param ):
return string.upper( string.join(string.split(param), "") )
## Open the file and parse it into a services dictionary
## if possible
def ReadConfig( self, filename ):
self.filename = filename
try:
fconfig = open( filename, "r" )
except IOError:
self.valid = False
return
section_name = None
## the most recent seen comment is stored as an array
current_comment = []
while True:
str = self.ReadLine( fconfig )
if not str:
break
## Check for comments
if str[0] == '#' or str[0] == ';' :
current_comment.append( str )
continue
## look for a next section name
if str[0]=='[' and str[-1]==']' :
section_name = str[1:-1]
self.AddService( section_name, current_comment )
current_comment = []
continue
str_list = string.split( str, "=" )
if len(str_list) != 2 :
continue
if not section_name :
print "parameter given without section name!"
break
param = self.NormalizeParamName( str_list[0] )
value = string.strip(str_list[1])
self.SetServiceOption( section_name, param, value, current_comment )
self.dirty = False
## reset the comment strinf if we have one
current_comment = []
fconfig.close()
## Add a parameter to the global section
def SetGlobalOption( self, param, value, comment=None ) :
self.SetServiceOption( "GLOBAL", param, value, comment )
## Add a parameter to a specific service
def SetServiceOption( self, servicename, param, value, comment=None ) :
service = string.upper(servicename)
parm = self.NormalizeParamName(param)
self.services[service]['_order_'].append( parm )
self.services[service][parm] = SambaParameter( parm, value, comment )
self.dirty = True
## remove a service from the config file
def DelService( self, servicename ) :
service = string.upper(servicename)
self.services[service] = None
self.dirty = True
## remove a service from the config file
def AddService( self, servicename, comment=None ) :
service = string.upper(servicename)
self.services[service] = {}
self.services[service]['_order_'] = []
if ( comment ):
self.services[service]['_comment_'] = SambaComment( comment )
self.services_order.append( service )
self.dirty = True
def isService( self, servicename ):
service = string.upper(servicename)
return self.services.has_key( service )
## dump a single service to stream
def DumpService( self, stream, servicename ):
## comments first
if self.services[servicename].has_key( '_comment_' ):
self.services[servicename]['_comment_'].Dump( stream )
## section header
stream.write( "[%s]\n" % (servicename) )
## parameter = value
for parm in self.services[servicename]['_order_']:
self.services[servicename][parm].Dump(stream)
## dump the config to stream
def Dump( self, stream ):
self.DumpService( stream, "GLOBAL" )
stream.write("\n")
for section in self.services_order:
## already handled the global section
if section == "GLOBAL":
continue
## check for deleted sections ##
if not self.services[section]:
continue
self.DumpService( stream, section )
stream.write( "\n" )
## write out any changes to disk
def Flush( self ):
if not self.dirty:
return
try:
fconfig = open( self.filename, "w" )
except IOError:
sys.stderr.write( "ERROR!\n" )
return 1
self.Dump( fconfig )
fconfig.close()
return 0
def Services( self ):
service_list = []
for section in self.services.keys():
service_list.append( section )
return service_list
def NumServices( self ):
return len(self.Services())
def Write( self, filename ):
self.filename = filename
self.valid = True
if not self.dirty:
return
self.Flush()
######################################################################
## Unit tests
######################################################################
if __name__ == "__main__" :
x = SambaConf( )
x.ReadConfig( sys.argv[1] )
if not x.valid :
print "Bad file!"
sys.exit(1)
x.Dump( sys.stdout )
## end of SambaConfig.py ######################################################
###############################################################################