r8384: merging clutter fixes from release branch
[sfrench/samba-autobuild/.git] / examples / logon / ntlogon / ntlogon.py
diff --git a/examples/logon/ntlogon/ntlogon.py b/examples/logon/ntlogon/ntlogon.py
new file mode 100755 (executable)
index 0000000..ba46ba8
--- /dev/null
@@ -0,0 +1,376 @@
+#!/usr/bin/env python
+"""
+ntlogon.py written by Timothy (rhacer) Grant
+
+Copyright 1999 - 2002 by Timothy Grant 
+
+is distributed under the terms of the GNU Public License.
+
+The format for the configuration file is as follows:
+
+While there is some room for confusion, we attempt to process things in
+order of specificity: Global first, Group second, User third, OS Type
+forth. This order can be debated forever, but it seems to make the most
+sense.
+
+# Everything in the Global section applies to all users logging on to the
+# network
+[Global]
+@ECHO "Welcome to our network!!!"
+NET TIME \\\\servername /SET /YES
+NET USE F: \\\\servername\\globalshare /YES
+
+# Map the private user area in the global section so we don't have to
+# create individual user entries for each user!
+NET USE U: \\\\servername\\%U /YES
+
+# Group entries, User entries and OS entries each start with the
+# keyword followed by a dash followed by--appropriately enough the Group
+# name, the User name, or the OS name.
+[Group-admin]
+@ECHO "Welcome administrators!"
+NET USE G: \\\\servername\\adminshare1 /YES
+NET USE I: \\\\servername\\adminshare2 /YES
+
+[Group-peons]
+@ECHO "Be grateful we let you use computers!"
+NET USE G: \\\\servername\\peonshare1 /YES
+
+[Group-hackers]
+@ECHO "What can I do for you today great one?"
+NET USE G: \\\\servername\\hackershare1 /YES
+NET USE I: \\\\servername\\adminshare2 /YES
+
+[User-fred]
+@ECHO "Hello there Fred!"
+NET USE F: \\\\servername\\fredsspecialshare /YES
+
+[OS-WfWg]
+@ECHO "Time to upgrade it?"
+
+# End configuration file
+
+usage: ntlogon [-g | --group=groupname] 
+               [-u | --user=username]
+               [-o | --os=osname]
+               [-m | --machine=netbiosname]
+               [-f | --templatefile=filename]
+               [-d | --dir=netlogon directory]
+               [-v | --version]
+               [-h | --help]
+               [--pause]
+               [--debug]
+""" 
+#   
+#" This quote mark is an artifact of the inability of my editor to
+#  correctly colour code anything after the triple-quoted docstring.
+#  if your editor does not have this flaw, feel free to remove it.
+
+
+import sys
+import getopt
+import re
+import string
+import os
+
+version = "ntlogon.py v0.8"
+
+def buildScript(buf, sections, group, user, ostype, machine, debug, pause):
+    """
+    buildScript() Takes the contents of the template file and builds
+    a DOS batch file to be executed as an NT logon script. It does this
+    by determining which sections of the configuration file should be included
+    and creating a list object that contains each line contained in each
+    included section.  The list object is then returned to the calling 
+    routine.
+
+    All comments (#) are removed. A REM is inserted to show
+    which section of the configuration file each line comes from.
+    We leave blanklines as they are sometimes useful for debugging
+
+    We also replace all of the Samba macros (e.g., %U, %G, %a, %m) with their
+    expanded versions which have been passed to us by smbd
+    """
+    hdrstring   = ''
+    script = []
+
+    #
+    # These are the Samba macros that we currently know about.
+    # any user defined macros will also be added to this dictionary.
+    # We do not store the % sign as part of the macro name.
+    # The replace routine will prepend the % sign to all possible
+    # replacements.
+    # 
+    macros = {
+                       'U': user,
+                'G': group,
+                'a': ostype,
+                'm': machine
+             }
+
+    #
+    # Process each section defined in the list sections
+    #
+    for s in sections:
+        # print 'searching for: ' + s
+
+        idx = 0
+
+        while idx < len(buf):
+            ln = buf[idx]
+
+            #
+            # We need to set up a regex for each possible section we
+            # know about. This is slightly complicated due to the fact
+            # that section headers contain user defined text.
+            #
+            if s == 'Global':
+                hdrstring = '\[ *' + s + ' *\]'
+            elif s == 'Group':
+                hdrstring = '\[ *' + s + ' *- *' + group + ' *\]'
+            elif s == 'User':
+                hdrstring = '\[ *' + s + ' *- *' + user + ' *\]'
+            elif s == 'OS':
+                hdrstring = '\[ *' + s + ' *- *' + ostype + ' *\]'
+            elif s == 'Machine':
+               hdrstring = '\[ *' + s + ' *- *' + machine + ' *\]'
+
+            #
+            # See if we have found a section header
+            #
+            if re.search(r'(?i)' + hdrstring, ln):
+                idx = idx + 1   # increment the counter to move to the next
+                                # line.
+
+                x = re.match(r'([^#\r\n]*)', ln)    # Determine the section
+                                                    # name and strip out CR/LF
+                                                    # and comment information
+
+                if debug:
+                    print 'rem ' + x.group(1) + ' commands'
+                else:
+                    # create the rem at the beginning of each section of the
+                    # logon script.
+                    script.append('rem ' + x.group(1) + ' commands') 
+
+                #
+                # process each line until we have found another section
+                # header
+                #
+                while not re.search(r'.*\[.*\].*', buf[idx]):
+
+                    #
+                    # strip comments and line endings
+                    #
+                    x = re.match(r'([^#\r\n]*)', buf[idx])
+
+                    if string.strip(x.group(1)) != '' :
+                        # if there is still content  after stripping comments and
+                        # line endings then this is a line to process
+
+                        line = x.group(1)
+
+                        #
+                        # Check to see if this is a macro definition line
+                        #
+                        vardef = re.match(r'(.*)=(.*)', line)
+
+                        if vardef:
+                            varname = string.strip(vardef.group(1))            # Strip leading and
+                            varsub  = string.strip(vardef.group(2))            # and trailing spaces
+
+                            if varname == '':
+                                print "Error: No substition name specified line: %d" % idx
+                                sys.exit(1)
+
+                            if varsub == '':
+                                print "Error: No substitution text provided line: %d" % idx
+                                sys.exit(1)
+
+                            if macros.has_key(varname):
+                                print "Warning: macro %s redefined line: %d" % (varname, idx)
+
+                            macros[varname] = varsub
+                            idx = idx + 1
+                            continue
+
+                        #
+                        # Replace all the  macros that we currently
+                        # know about.
+                        #
+                        # Iterate over the dictionary that contains all known
+                        # macro substitutions.
+                        #
+                        # We test for a macro name by prepending % to each dictionary
+                        # key.
+                        #
+                        for varname in macros.keys():
+                            line = re.sub(r'%' + varname + r'(\W)',
+                                          macros[varname] + r'\1', line)
+
+                        if debug:
+                            print line
+                            if pause:
+                                print 'pause'
+                        else:
+                            script.append(line)
+
+                    idx = idx + 1
+
+                    if idx == len(buf):
+                        break   # if we have reached the end of the file
+                                # stop processing.
+
+            idx = idx + 1   # increment the line counter
+
+        if debug:
+            print ''
+        else:
+            script.append('')
+
+    return script
+
+# End buildScript()
+
+def run():
+    """
+    run() everything starts here. The main routine reads the command line
+    arguments, opens and reads the configuration file.
+    """
+    configfile  = '/etc/ntlogon.conf'   # Default configuration file
+    group       = ''                    # Default group
+    user        = ''                    # Default user
+    ostype      = ''                    # Default os
+    machine     = ''                   # Default machine type
+    outfile     = 'logon.bat'           # Default batch file name
+                                        #   this file name WILL take on the form
+                                        #   username.bat if a username is specified
+    debug       = 0                     # Default debugging mode
+    pause              = 0                                             # Default pause mode
+    outdir      = '/usr/local/samba/netlogon/'   # Default netlogon directory
+
+    sections    = ['Global', 'Machine', 'OS', 'Group', 'User'] # Currently supported
+                                                    # configuration file 
+                                                    # sections
+
+    options, args = getopt.getopt(sys.argv[1:], 'd:f:g:ho:u:m:v', 
+                                 ['templatefile=', 
+                                  'group=',
+                                  'help',
+                                  'os=',
+                                  'user=',
+                                  'machine=',
+                                  'dir=',
+                                  'version',
+                                  'pause',
+                                  'debug'])
+
+    #
+    # Process the command line arguments
+    #
+    for i in options:
+        # template file to process
+        if (i[0] == '-f') or (i[0] == '--templatefile'):
+            configfile = i[1]
+            # print 'configfile = ' + configfile
+
+        # define the group to be used
+        elif (i[0] == '-g') or (i[0] == '--group'):
+            group = i[1]
+            # print 'group = ' + group
+
+        # define the os type
+        elif (i[0] == '-o') or (i[0] == '--os'):
+            ostype = i[1]
+            # print 'os = ' + os
+
+        # define the user
+        elif (i[0] == '-u') or (i[0] == '--user'):
+            user = i[1]
+            outfile = user + '.bat' # Setup the output file name
+            # print 'user = ' + user
+
+        # define the machine
+        elif (i[0] == '-m') or (i[0] == '--machine'):
+            machine = i[1]
+
+        # define the netlogon directory
+        elif (i[0] == '-d') or (i[0] == '--dir'):
+            outdir = i[1]
+            # print 'outdir = ' + outdir
+
+        # if we are asked to turn on debug info, do so.
+        elif (i[0] == '--debug'):
+            debug = 1
+            # print 'debug = ' + debug
+
+        # if we are asked to turn on the automatic pause functionality, do so
+        elif (i[0] == '--pause'):
+            pause = 1
+            # print 'pause = ' + pause
+
+        # if we are asked for the version number, print it.
+        elif (i[0] == '-v') or (i[0] == '--version'):
+            print version
+            sys.exit(0)
+
+        # if we are asked for help print the docstring.
+        elif (i[0] == '-h') or (i[0] == '--help'):
+            print __doc__
+            sys.exit(0)
+
+    #
+    # open the configuration file
+    #    
+    try:
+        iFile = open(configfile, 'r')
+    except IOError:
+        print 'Unable to open configuration file: ' + configfile
+        sys.exit(1)
+
+
+    #
+    # open the output file
+    #    
+    if not debug:
+        try:
+            oFile = open(outdir + outfile, 'w')
+        except IOError:
+            print 'Unable to open logon script file: ' + outdir + outfile
+            sys.exit(1)
+
+    buf = iFile.readlines() # read in the entire configuration file
+
+    #
+    # call the script building routine
+    #
+    script = buildScript(buf, sections, group, user, ostype, machine, debug, pause)
+
+    #
+    # write out the script file
+    #
+    if not debug:
+        for ln in script:
+            oFile.write(ln + '\r\n')
+            if pause:
+                if string.strip(ln) != '':                     # Because whitespace
+                    oFile.write('pause' + '\r\n')      # is a useful tool, we
+                                                                               # don't put pauses after
+                                                    # an empty line.
+
+
+# End run()
+
+#
+# immediate-mode commands, for drag-and-drop or execfile() execution
+#
+if __name__ == '__main__':
+    run()
+else:
+    print "Module ntlogon.py imported."
+    print "To run, type: ntlogon.run()"
+    print "To reload after changes to the source, type: reload(ntlogon)"
+
+#
+# End NTLogon.py
+#