This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[kai/samba.git] / examples / ntlogon / ntlogon.py
1 #!/usr/bin/env python
2 """
3 ntlogon.py written by Timothy (rhacer) Grant
4
5 Copyright 1999 - 2002 by Timothy Grant 
6
7 is distributed under the terms of the GNU Public License.
8
9 The format for the configuration file is as follows:
10
11 While there is some room for confusion, we attempt to process things in
12 order of specificity: Global first, Group second, User third, OS Type
13 forth. This order can be debated forever, but it seems to make the most
14 sense.
15
16 # Everything in the Global section applies to all users logging on to the
17 # network
18 [Global]
19 @ECHO "Welcome to our network!!!"
20 NET TIME \\\\servername /SET /YES
21 NET USE F: \\\\servername\\globalshare /YES
22
23 # Map the private user area in the global section so we don't have to
24 # create individual user entries for each user!
25 NET USE U: \\\\servername\\%U /YES
26
27 # Group entries, User entries and OS entries each start with the
28 # keyword followed by a dash followed by--appropriately enough the Group
29 # name, the User name, or the OS name.
30 [Group-admin]
31 @ECHO "Welcome administrators!"
32 NET USE G: \\\\servername\\adminshare1 /YES
33 NET USE I: \\\\servername\\adminshare2 /YES
34
35 [Group-peons]
36 @ECHO "Be grateful we let you use computers!"
37 NET USE G: \\\\servername\\peonshare1 /YES
38
39 [Group-hackers]
40 @ECHO "What can I do for you today great one?"
41 NET USE G: \\\\servername\\hackershare1 /YES
42 NET USE I: \\\\servername\\adminshare2 /YES
43
44 [User-fred]
45 @ECHO "Hello there Fred!"
46 NET USE F: \\\\servername\\fredsspecialshare /YES
47
48 [OS-WfWg]
49 @ECHO "Time to upgrade it?"
50
51 # End configuration file
52
53 usage: ntlogon [-g | --group=groupname] 
54                [-u | --user=username]
55                [-o | --os=osname]
56                [-m | --machine=netbiosname]
57                [-f | --templatefile=filename]
58                [-d | --dir=netlogon directory]
59                [-v | --version]
60                [-h | --help]
61                [--pause]
62                [--debug]
63 """ 
64 #   
65 #" This quote mark is an artifact of the inability of my editor to
66 #  correctly colour code anything after the triple-quoted docstring.
67 #  if your editor does not have this flaw, feel free to remove it.
68
69
70 import sys
71 import getopt
72 import re
73 import string
74 import os
75
76 version = "ntlogon.py v0.8"
77
78 def buildScript(buf, sections, group, user, ostype, machine, debug, pause):
79     """
80     buildScript() Takes the contents of the template file and builds
81     a DOS batch file to be executed as an NT logon script. It does this
82     by determining which sections of the configuration file should be included
83     and creating a list object that contains each line contained in each
84     included section.  The list object is then returned to the calling 
85     routine.
86
87     All comments (#) are removed. A REM is inserted to show
88     which section of the configuration file each line comes from.
89     We leave blanklines as they are sometimes useful for debugging
90
91     We also replace all of the Samba macros (e.g., %U, %G, %a, %m) with their
92     expanded versions which have been passed to us by smbd
93     """
94     hdrstring   = ''
95     script = []
96
97     #
98     # These are the Samba macros that we currently know about.
99     # any user defined macros will also be added to this dictionary.
100     # We do not store the % sign as part of the macro name.
101     # The replace routine will prepend the % sign to all possible
102     # replacements.
103     # 
104     macros = {
105                         'U': user,
106                 'G': group,
107                 'a': ostype,
108                 'm': machine
109              }
110
111     #
112     # Process each section defined in the list sections
113     #
114     for s in sections:
115         # print 'searching for: ' + s
116
117         idx = 0
118
119         while idx < len(buf):
120             ln = buf[idx]
121
122             #
123             # We need to set up a regex for each possible section we
124             # know about. This is slightly complicated due to the fact
125             # that section headers contain user defined text.
126             #
127             if s == 'Global':
128                 hdrstring = '\[ *' + s + ' *\]'
129             elif s == 'Group':
130                 hdrstring = '\[ *' + s + ' *- *' + group + ' *\]'
131             elif s == 'User':
132                 hdrstring = '\[ *' + s + ' *- *' + user + ' *\]'
133             elif s == 'OS':
134                 hdrstring = '\[ *' + s + ' *- *' + ostype + ' *\]'
135             elif s == 'Machine':
136                 hdrstring = '\[ *' + s + ' *- *' + machine + ' *\]'
137
138             #
139             # See if we have found a section header
140             #
141             if re.search(r'(?i)' + hdrstring, ln):
142                 idx = idx + 1   # increment the counter to move to the next
143                                 # line.
144
145                 x = re.match(r'([^#\r\n]*)', ln)    # Determine the section
146                                                     # name and strip out CR/LF
147                                                     # and comment information
148
149                 if debug:
150                     print 'rem ' + x.group(1) + ' commands'
151                 else:
152                     # create the rem at the beginning of each section of the
153                     # logon script.
154                     script.append('rem ' + x.group(1) + ' commands') 
155
156                 #
157                 # process each line until we have found another section
158                 # header
159                 #
160                 while not re.search(r'.*\[.*\].*', buf[idx]):
161
162                     #
163                     # strip comments and line endings
164                     #
165                     x = re.match(r'([^#\r\n]*)', buf[idx])
166
167                     if string.strip(x.group(1)) != '' :
168                         # if there is still content  after stripping comments and
169                         # line endings then this is a line to process
170
171                         line = x.group(1)
172
173                         #
174                         # Check to see if this is a macro definition line
175                         #
176                         vardef = re.match(r'(.*)=(.*)', line)
177
178                         if vardef:
179                             varname = string.strip(vardef.group(1))             # Strip leading and
180                             varsub  = string.strip(vardef.group(2))             # and trailing spaces
181
182                             if varname == '':
183                                 print "Error: No substition name specified line: %d" % idx
184                                 sys.exit(1)
185
186                             if varsub == '':
187                                 print "Error: No substitution text provided line: %d" % idx
188                                 sys.exit(1)
189
190                             if macros.has_key(varname):
191                                 print "Warning: macro %s redefined line: %d" % (varname, idx)
192
193                             macros[varname] = varsub
194                             idx = idx + 1
195                             continue
196
197                         #
198                         # Replace all the  macros that we currently
199                         # know about.
200                         #
201                         # Iterate over the dictionary that contains all known
202                         # macro substitutions.
203                         #
204                         # We test for a macro name by prepending % to each dictionary
205                         # key.
206                         #
207                         for varname in macros.keys():
208                             line = re.sub(r'%' + varname + r'(\W)',
209                                           macros[varname] + r'\1', line)
210
211                         if debug:
212                             print line
213                             if pause:
214                                 print 'pause'
215                         else:
216                             script.append(line)
217
218                     idx = idx + 1
219
220                     if idx == len(buf):
221                         break   # if we have reached the end of the file
222                                 # stop processing.
223
224             idx = idx + 1   # increment the line counter
225
226         if debug:
227             print ''
228         else:
229             script.append('')
230
231     return script
232
233 # End buildScript()
234
235 def run():
236     """
237     run() everything starts here. The main routine reads the command line
238     arguments, opens and reads the configuration file.
239     """
240     configfile  = '/etc/ntlogon.conf'   # Default configuration file
241     group       = ''                    # Default group
242     user        = ''                    # Default user
243     ostype      = ''                    # Default os
244     machine     = ''                    # Default machine type
245     outfile     = 'logon.bat'           # Default batch file name
246                                         #   this file name WILL take on the form
247                                         #   username.bat if a username is specified
248     debug       = 0                     # Default debugging mode
249     pause               = 0                                             # Default pause mode
250     outdir      = '/usr/local/samba/netlogon/'   # Default netlogon directory
251
252     sections    = ['Global', 'Machine', 'OS', 'Group', 'User'] # Currently supported
253                                                     # configuration file 
254                                                     # sections
255
256     options, args = getopt.getopt(sys.argv[1:], 'd:f:g:ho:u:m:v', 
257                                  ['templatefile=', 
258                                   'group=',
259                                   'help',
260                                   'os=',
261                                   'user=',
262                                   'machine=',
263                                   'dir=',
264                                   'version',
265                                   'pause',
266                                   'debug'])
267
268     #
269     # Process the command line arguments
270     #
271     for i in options:
272         # template file to process
273         if (i[0] == '-f') or (i[0] == '--templatefile'):
274             configfile = i[1]
275             # print 'configfile = ' + configfile
276
277         # define the group to be used
278         elif (i[0] == '-g') or (i[0] == '--group'):
279             group = i[1]
280             # print 'group = ' + group
281
282         # define the os type
283         elif (i[0] == '-o') or (i[0] == '--os'):
284             ostype = i[1]
285             # print 'os = ' + os
286
287         # define the user
288         elif (i[0] == '-u') or (i[0] == '--user'):
289             user = i[1]
290             outfile = user + '.bat' # Setup the output file name
291             # print 'user = ' + user
292
293         # define the machine
294         elif (i[0] == '-m') or (i[0] == '--machine'):
295             machine = i[1]
296
297         # define the netlogon directory
298         elif (i[0] == '-d') or (i[0] == '--dir'):
299             outdir = i[1]
300             # print 'outdir = ' + outdir
301
302         # if we are asked to turn on debug info, do so.
303         elif (i[0] == '--debug'):
304             debug = 1
305             # print 'debug = ' + debug
306
307         # if we are asked to turn on the automatic pause functionality, do so
308         elif (i[0] == '--pause'):
309             pause = 1
310             # print 'pause = ' + pause
311
312         # if we are asked for the version number, print it.
313         elif (i[0] == '-v') or (i[0] == '--version'):
314             print version
315             sys.exit(0)
316
317         # if we are asked for help print the docstring.
318         elif (i[0] == '-h') or (i[0] == '--help'):
319             print __doc__
320             sys.exit(0)
321
322     #
323     # open the configuration file
324     #    
325     try:
326         iFile = open(configfile, 'r')
327     except IOError:
328         print 'Unable to open configuration file: ' + configfile
329         sys.exit(1)
330
331
332     #
333     # open the output file
334     #    
335     if not debug:
336         try:
337             oFile = open(outdir + outfile, 'w')
338         except IOError:
339             print 'Unable to open logon script file: ' + outdir + outfile
340             sys.exit(1)
341
342     buf = iFile.readlines() # read in the entire configuration file
343
344     #
345     # call the script building routine
346     #
347     script = buildScript(buf, sections, group, user, ostype, machine, debug, pause)
348
349     #
350     # write out the script file
351     #
352     if not debug:
353         for ln in script:
354             oFile.write(ln + '\r\n')
355             if pause:
356                 if string.strip(ln) != '':                      # Because whitespace
357                     oFile.write('pause' + '\r\n')       # is a useful tool, we
358                                                                                 # don't put pauses after
359                                                     # an empty line.
360
361
362 # End run()
363
364 #
365 # immediate-mode commands, for drag-and-drop or execfile() execution
366 #
367 if __name__ == '__main__':
368     run()
369 else:
370     print "Module ntlogon.py imported."
371     print "To run, type: ntlogon.run()"
372     print "To reload after changes to the source, type: reload(ntlogon)"
373
374 #
375 # End NTLogon.py
376 #