#!/usr/bin/env python

# dput - debian package upload tool
# (c) 2000 Christian Kurz <shorty@debian.org>
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import os, sys, string, re, glob, getopt, signal
import pwd, stat, md5, sha, rfc822

# Now import out modules
import ConfigParser

dput_version = "dput 0.9.2.2"

config = None
upload_methods = {}
files_to_upload = []
simulate = unsigned_upload = 0
debug = dinstall = check_only = 0
config_file = ''

dput_modules = ('')

# Function to import files from the /usr/share/dput and make them available
# to this script
def import_upload_functions():
    files_to_import = glob.glob('/usr/share/dput/*.py')
    for file in files_to_import:
        if debug: print "D: File: %s" % file
        base = os.path.basename(file)
        if len(dput_modules) != 0:
            if base not in dput_modules:
                base = os.path.splitext(base)[0]
        else:
            base = os.path.splitext(base)[0]
        if debug: print "D: Base: %s" % base
        d = {}
        try:
            exec open(file) in d
            if debug: print "Imported: %s" % file
        except IOError:
            print "Couldn't import %s" % file
            continue
        register_upload_function(base, d['upload'])

# add function to upload_methods dictionary using key of name
def register_upload_function(name, function):
    global upload_methods

    upload_methods[name] = function

# parse the changes file
def parse_changes(chg_fd):
    check = chg_fd.read(5)
    if check != '-----':
        chg_fd.seek(0)
    else: # found a PGP header, gonna ditch the next 3 lines
        chg_fd.readline() # eat the rest of the line
        chg_fd.readline() # Hash: SHA1
        chg_fd.readline() # empty line
    if not string.find(chg_fd.readline(), 'Format') != -1:
        chg_fd.readline()
    changes = rfc822.Message(chg_fd)
    return changes
        
# read configs in this order:
#   if specified on the command line, only read extra_config
#   otherwise, read /etc/dput.cf then ~/.dput.cf
# the config parser will layer values
def read_configs(extra_config, debug):
    global config

    config = ConfigParser.ConfigParser()

    config.set('DEFAULT', 'login', 'username')
    config.set('DEFAULT', 'method', 'scp')
    config.set('DEFAULT', 'hash', 'md5')
    config.set('DEFAULT', 'allow_unsigned_uploads', '0')
    config.set('DEFAULT', 'run_lintian', '0')
    config.set('DEFAULT', 'run_dinstall', '0')
    config.set('DEFAULT', 'check_version', '0')
    config.set('DEFAULT', 'scp_compress', '0')
    config.set('DEFAULT', 'default_host_main', '')
    config.set('DEFAULT', 'default_host_non-us', '')
    config.set('DEFAULT', 'post_upload_command', '')
    config.set('DEFAULT', 'pre_upload_command', '')
    config.set('DEFAULT', 'passive_ftp', '0')

    if extra_config:
        try:
            fd = open(extra_config)
        except IOError, e:
            print e
            sys.exit(1)
        if debug: print "D: Parsing Configuration File"
        config.readfp(fd)
        fd.close()
    else:
        user_config_file = os.path.join(os.environ['HOME'], ".dput.cf")
        global_config_file = '/etc/dput.cf'
        fd = None
        for config_file in (global_config_file, user_config_file):
            try:
                fd = open(config_file)
            except IOError, e:
                if debug:
                    print '%s: %s, skipping' % (e[1], config_file)
                continue
            if debug: print "D: Parsing Configuration File %s" % config_file
            config.readfp(fd)
            fd.close()
        if fd == None:
            print 'Could not open %s or %s, exiting' % \
                (user_config_file, global_config_file)
            sys.exit(1)
    # only check for fqdn and incoming dir, rest have reasonable defaults
    # use a sentinel so we can report all errors instead of just the
    # first one
    error = 0
    for section in config.sections():
        if not config.has_option(section, 'fqdn'):
            print 'Config error: %s must have a fqdn set' % section
            error = 1
        if not config.has_option(section, 'incoming'):
            print 'Config error: %s must have an incoming directory set' % \
                section
            error = 1
    if error:
        sys.exit(1)
    
# Convert a hex string into readable characters.
hexStr = string.hexdigits
def hexify_string(string):
    char = ''
    for c in string:
        char = char + hexStr[(ord(c) >> 4) & 0xF] + hexStr[ord(c) & 0xF]
    return char

# Function to generatea checksum for a file.
# Currently supports md5, sha1. ripemd may come in the future.
def checksum_test(filename,hash):
    try:
        file_to_test = open(filename, 'r')
    except IOError:
        print "Can't open %s" % filename
        sys.exit(1)

    if hash == 'md5':
        hash_type = md5
    else:
        hash_type = sha

    check_obj = hash_type.new()

    for line in file_to_test.readlines():
        check_obj.update(line)

    file_to_test.close()
    checksum = hexify_string(check_obj.digest())

    return checksum

# Verify the GnuPG signature on a file.
def check_signature(filename):
    if os.access(filename, os.R_OK):
        if os.access("/usr/bin/gpg", os.R_OK):
            stream = os.popen("/usr/bin/gpg --status-fd 1 --verify --batch %s" % filename).read()
            if stream.count('[GNUPG:] GOODSIG'):
                print "Good signature on %s." % filename
            elif stream.count('[GNUPG:] BADSIG'):
                print "Bad signature on %s." % filename
                sys.exit(1)
            elif stream.count('[GNUPG:] ERRSIG'):
                print "Error verifying signature on %s." % filename
                sys.exit(1)
            else:
                print "Error finding status of signature verification."
        else:
            print "Can't verify signature on %s" % filename
            print "If you are still using PGP, please read this:"
            print "http://www.gnupg.org/gph/en/pgp2x.html"
            sys.exit(1)
    else:
        print "Can't read %s" % filename
        sys.exit(1)

# Check if this is a binary_upload only or not.
def check_upload_variant(changes, debug):
    binary_upload = 0
    if changes.dict.has_key('architecture'):
        arch = changes.dict['architecture']
        if debug: print "D: Architecture: %s" % arch
        if string.find(arch, 'source') < 0:
            if debug:
                print "D: Doing a binary upload only."
            binary_upload = 1
    return binary_upload

# Check the signature on the two files given via function call.
def verify_signature(host, changes_file, dsc_file, check_only, debug,\
    unsigned_upload, binary_upload):

    if debug:
        print "D: .changes-File: %s" % changes_file
        print "D: .dsc-File: %s" % dsc_file
    if check_only or (config.getboolean(host, 'allow_unsigned_uploads') == 0 \
        and unsigned_upload == 0):
        print "Checking Signature on .changes"
        check_signature(changes_file)
        if not binary_upload:
            print "Checking Signature on .dsc"
            check_signature(dsc_file)

# Check if an orig.tar.gz or tar.gz has to be included in the package or not.
def source_check(changes, debug):
    include_orig = include_tar = 0
    if changes.dict.has_key('version'):
        version = changes.dict['version']
        if debug: print "D: Package Version: %s" % version
        # versions with a dash in them are for non-native only
        if string.find(version, '-') == -1: # debian native
            include_tar = 1
        else:
            if string.find(version, ':') > 0:
                if debug: print "D: Epoch found"
                version = version[2:]
            pos = string.rfind(version, '-')
            upstream_version = version[0:pos]
            debian_version = version[pos+1:]
            if debug:
                print "D: Upstream Version: %s" % upstream_version
                print "D: Debian Version: %s" % debian_version
            if debian_version == '0.1' or debian_version == '1' \
               or debian_version == '1.1':
                include_orig = 1
            else:
                include_tar = 1
    return (include_orig, include_tar)

# Check if a non-US package will be uploaded and if the
# upload will be done to non-US.debian.org
def check_upload_host(changes, host, debug):
    if changes.dict.has_key('section'):
        section = changes.dict['section']
        if debug: print "D: Section: %s" % section
        if string.find(section, 'non-us') and \
            (config.get(host, 'fqdn') != 'non-US.debian.org' or \
             config.getboolean(host, 'allow_non-us_software') != 1):
                print "Refusing upload."
                print "Tried uploading non-US software to a server != " +\
                    "non-US.debian.org"
                sys.exit(1)

# Run some tests on the files before uploading them to 
# verify that they are in good shape.
def verify_files(path, filename, host, check_only, check_version, \
        unsigned_upload, debug):
    file_seen = include_orig_tar_gz = include_tar_gz = binary_only = 0

    name_of_file = filename
   
    change_file = os.path.join(path, name_of_file)

    print "D: %s" % change_file
    try:
        chg_fd = open(change_file, 'r')
    except IOError:
        print "Can't open %s" % change_file
        sys.exit(1)
    changes = parse_changes(chg_fd)
    chg_fd.close

    # Find out if it's a binary only upload or not
    binary_upload = check_upload_variant(changes, debug)

    if binary_upload:
        dsc_file = ''
    else:
        for file in string.split(changes.dict['files'], '\n'):
            filename = string.split(file)[4] # filename only
            if string.find(filename, '.dsc') != -1:
                if debug:
                    print "D: dsc-File: %s" % filename
                dsc_file = os.path.join(path, filename)

    # Run the check to verify that the package has been tested.
    if config.getboolean(host, 'check_version') == 1 or check_version:
        version_check (changes, debug)

    # Verify the signature of the maintainer
    verify_signature(host, change_file, dsc_file, check_only, debug,\
        unsigned_upload, binary_upload)

    # Check the sources
    (include_orig_tar_gz, include_tar_gz) = source_check(changes, debug)

    # Check the upload host
    check_upload_host(changes, host, debug)

    # Check md5sum and the size
    file_list = string.split(changes.dict['files'], '\n')
    hash_to_use = config.get('DEFAULT','hash')
    for line in file_list:
        (check_sum, size, section, priority, file) = string.split(line)
        file_to_upload = os.path.join(path, file)
        if debug:
            print "D: File to upload: %s" % file_to_upload
        if checksum_test(file_to_upload,hash_to_use) != check_sum:
            if debug:
                print "D: checksum from .changes: %s" % check_sum
                print "D: generated checksum: %s" % \
                      checksum_test(file_to_upload,hash_to_use)
            print "checksum doesn't match for %s" % file_to_upload
            sys.exit(1)
        else:
            if debug: print "D: checksum for %s is fine" % file_to_upload
        if os.lstat(file_to_upload)[stat.ST_SIZE] != int(size):
            if debug:
                print "D: size from .changes: %s" % size
                print "D: calculated size: %s" % \
                    os.lstat(file_to_upload)[stat.ST_SIZE]
            print "size doesn't match for %s" % file_to_upload
        
        files_to_upload.append(file_to_upload)
    
    # Check filenames
    for file in files_to_upload:
        if file[-12:] == '.orig.tar.gz' and not include_orig_tar_gz:
            if debug:
                print "D: Filename: %s" % file
                print "D: Suffix: %s" % file[-12:]
            print "Package includes an .orig.tar.gz file although it's not"
            print "needed and the package may be rejected because of this."
        elif file[-7:] == '.tar.gz' and not include_tar_gz \
            and not include_orig_tar_gz:
            if debug:
                print "D: Filename: %s" % file
                print "D: Suffix: %s" % file[-7:]
            print "Package includes a .tar.gz file although it's not"
            print "needed and the package may be rejected because of this."

    if debug:
        print "D: File to upload: %s" % change_file
    files_to_upload.append(change_file)

# Print the configuration and exit.
def print_config(config, debug):
    print
    config.write(sys.stdout)
    print

# Write a logfile of the upload and call it .upload
def create_upload_file(package, host, path, files_to_upload, debug):
    base = os.path.splitext(package)[0] # only need first part
    logfile_name = os.path.join(path, base + '.upload')
    if debug:
        print "D: Writing logfile: %s" % logfile_name
    if os.access(logfile_name, os.R_OK):
        logfile_fd = open(logfile_name, 'a')
    else:
        logfile_fd = open(logfile_name, 'w')
    for file in files_to_upload:
        entry_for_logfile = 'Successfully uploaded ' + file + \
            ' to ' + config.get(host, 'fqdn') + '.\n'
        logfile_fd.write(entry_for_logfile)
    logfile_fd.close()
        
# Run lintian on the changes file and stop if it finds errors.
def run_lintian_test(changes_file):
    if os.access(changes_file, os.R_OK):
        if os.access("/usr/bin/lintian", os.R_OK):
            old_signal = signal.signal(signal.SIGPIPE, signal.SIG_DFL)
            print "Package is now being checked with lintian."
            if os.spawnv(os.P_WAIT, "/usr/bin/lintian",
                  ['lintian', '-i', changes_file]):
                print 
                print "Lintian says this package is not compliant" +\
                    "with the current policy."
                print "Please check the current policy and your package."
                print "Also see lintian documentation about overrides."
                sys.exit(1)
            else:
                signal.signal(signal.SIGPIPE, old_signal)
                return 0
        else:
            print "lintian is not installed, skipping package test."
    else:
        print "Can't read %s" % changes_file
        sys.exit(1)
    
# Guess the host where the package should be uploaded to. This is based
# on information from the changes file.
def guess_upload_host(path, filename):
    non_us = 0

    name_of_file = filename
    changes_file = os.path.join(path, name_of_file)
    
    try:
        changes_file_fd = open(changes_file, 'r')
    except IOError:
        print "Can't open %s" % changes_file
        sys.exit(1)
    lines = changes_file_fd.readlines()
    for line in lines:
        if ((string.find(line, 'non-US') != -1) or (string.find(line, 'non-us') != -1)):
            non_us = 1
            break

    if non_us:
        if len(config.get('DEFAULT', 'default_host_non-us')) != 0:
            print "Upload package to host %s" % config.get('DEFAULT', \
                'default_host_non-us') 
            return config.get('DEFAULT', 'default_host_non-us')
        else:            
            print "Uploading package to host non-us.debian.org"
            if config.get('DEFAULT', 'method') == 'scp' or \
                config.get('DEFAULT', 'method') == 'rsync':
                return "non-us-secure"
            else:
                return "non-us"
                
    else:
        if len(config.get('DEFAULT', 'default_host_main')) != 0:
            print "Upload package to host %s" % config.get('DEFAULT', \
                'default_host_main')
            return config.get('DEFAULT', 'default_host_main')
        else:
            print "Uploading package to host ftp-master.debian.org"
            if config.get('DEFAULT', 'method') == 'scp' or \
                config.get('DEFAULT', 'method') == 'rsync':
                return "ftp-master-secure"
            else:
                return "ftp-master"

# Run dinstall in test-mode and present the output to the user so that
# he can see if his package would be installed or not.
def dinstall_caller(filename, host, login, debug):
    command = ['ssh', '%s@%s' % (login, config.get(host, 'fqdn')),
           'cd', '%s' % config.get(host, 'incoming'),
           ';', 'dinstall', '-n', '%s' % filename]
    if debug:
        print "D: Logging into %s@%s:%s" % (login, \
            config.get(host, 'fqdn'), config.get(host, 'incoming'))
        print "D: dinstall -n %s" % filename
    if config.getboolean(host, 'run_dinstall') == 1 or dinstall:
        if os.spawnv(os.P_WAIT, '/usr/bin/ssh', command):
            print "Error occured while trying to connect, or while " +\
			    "attempting to run dinstall."
            sys.exit(1)

# Check if the caller has installed the package also on his system
# for testing purposes before uploading it. If not, we reject the upload.
def version_check(changes, debug):
    files_to_check = []
    version_to_check = []
    
    # Get filenames of deb files:
    for file in string.split(changes.dict['files'], '\n'):
        filename = string.split(file)[4] # filename only
        if string.find(filename, '.deb') != -1:
            if debug:
                print "D: Debian Package: %s" % filename
            pos1 = string.find(filename, '_')
            pos2 = string.rfind(filename, '_')
            package_name = filename[0:pos1]
            version_numer = filename[pos1+1:pos2]
            if debug: print "D: Package to Check: %s" % package_name
            if debug: print "D: Version to Check: %s" % version_numer
            files_to_check.append(package_name)
            version_to_check.append(version_numer)
    
    for file in files_to_check:
        if debug: print "D: Name of Package: %s" % file
    dpkg_output = rfc822.Message(os.popen('dpkg -s %s' % file))
    if dpkg_output.has_key('version'):
        installed_version = dpkg_output.dict['version']
        if debug: print "D: Installed-Version: %s" % installed_version
        position = files_to_check.index(file)
        if debug: print "D: Check-Version: %s" % \
            version_to_check[position]
        if installed_version != version_to_check[position]:
            print "Package to upload is not installed, but it appears " +\
            "you have an older version installed."    
    else:
        print "Uninstalled Package. Test it before uploading it."
        sys.exit(1)

# Run a command that the user-defined in the config_file.
def execute_command(host, debug, type):
    lookup_command = type + '_upload_command'
    if debug: print "D: Command: %s" % config.get(host, lookup_command)
    if os.system(config.get(host, lookup_command)):
        print "Error while executing command."
        print "Continuing..."

# Open a Logfile and check if the user already put
# this package on the specified host or not:
def check_upload_logfile(changes_file, host, check_only,\
    call_lintian, force_upload, debug):
    uploaded = 0
    upload_logfile = changes_file[:-8] + '.upload'
    if not check_only and not force_upload:
        if not os.path.exists(upload_logfile):
            return
        try:
            fd_logfile = open(upload_logfile)
        except IOError:
            print "Couldn't open %s" % upload_logfile
            sys.exit(1)
        for line in fd_logfile.readlines():
            if string.find(line, config.get(host, 'fqdn')) != -1:
                uploaded = 1
        if uploaded:
            print "Already uploaded to %s" % config.get(host, 'fqdn')
            print "Doing nothing for %s" % changes_file
            sys.exit(0)

# Help Message to print
USAGE = """Usage: dput [host] <package(s).changes>
 Supported options (see man page for long forms):
   -c: Config file to parse.
   -d: Activate debugging.
   -D: Run dinstall after upload.
   -f: Force an upload.
   -h: Display this help message.
   -H: Display a list of hosts from the config file.
   -l: Run lintian before upload.
   -o: Only check the package.
   -p: Print the configuration.
   -s: Simulate the upload only.
   -u: Don't check GnuPG signature.
   -v: Display version information.
   -V: Check the package version and then upload it.
"""

# Main function, no further comment needed. :)
def main():
    global simulate 
    global debug
    global check_only
    global dinstall
    global unsigned_upload
    global config_file

    check_version = config_print = force_upload = \
    call_lintian = config_host_list = 0
    ftp_passive_mode = 0
    preferred_host = ''

    # Parse Command Line Options.
    try:
        (opts, args) = getopt.getopt(sys.argv[1:],
                            'c:dDfhHlopsuvV',
                            ['debug', 'dinstall', 'check-only',
                            'check-version', 'config', 'force', 'help',
                            'host-list', 'lintian', 'print', 'simulate',
							'unchecked', 'version'])
    except getopt.error, msg:
        print msg
        sys.exit(1)

    for option, arg in opts:
        if option in ('-h', '--help'):
            print USAGE
            return
        elif option in ('-v', '--version'):
            print dput_version
            return
        elif option in ('-d', '--debug'):
            debug = 1
        elif option in ('-D', '--dinstall'):
            dinstall = 1
        elif option in ('-c', '--config'):
            config_file = arg   
        elif option in ('-f', '--force'):
            force_upload = 1
        elif option in ('-H', '--host-list'):
            config_host_list = 1
        elif option in ('-l', '--lintian'):
            call_lintian = 1
        elif option in ('-o', '--check-only'):
            check_only = 1
        elif option in ('-p', '--print'):
            config_print = 1
        elif option in ('P', '--passive'):
            ftp_passive_mode = 1
        elif option in ('-s', '--simulate'):
            simulate = 1
        elif option in ('-u', '--unchecked'):
            unsigned_upload = 1
        elif option in ('-V', '--check_version'):
            check_version = 1           
  
    # Always print the version number in the debug output
    # so that in case of bugreports, we know which version
    # the user has installed
    if debug: print "D: %s" % dput_version
    
    # Try to get the login from the enviroment
    if os.environ.has_key('USER'):
        login = os.environ['USER']
        if debug: print "D: Login: %s" % login
    else:
        print "$USER not set, will use login."
    
    # Else use the current username
    if login == '':
       print "D: Variable $USER not set."
       login = pwd.getpwuid(os.getuid( ))[0]
       if debug:
           print "D: User-ID: %s" % os.getuid()
           print "D: Login: %s" % login

    # Start Config File Parsing.
    read_configs(config_file, debug)

    if config_print:
        print_config(config, debug)
        sys.exit(0)

    if config_host_list:
        print
        print "Default Method: %s" % config.get('DEFAULT','method')
        print
        for section in config.sections():
            print "%s => %s  (Upload method: %s)" % (section, \
                config.get(section,'fqdn'), config.get(section,'method'))
        print
        sys.exit(0)

    # Process further command line options.
    if len(args) == 0:
        print "No package or host named."
        sys.exit(0)
    elif len(args) == 1 and not check_only:
        package_to_upload = args[0:]
    else:
        if not check_only:
            if debug:
                print "D: Checking if a host was named on the command line."
            if config.has_section(args[0]):
                if debug:
                    print "D: Host %s found in config" % args[0]
                # Host was also named, so only the rest will be a list
                # of packages to upload.
                preferred_host = args[0]
                package_to_upload = args[1:]
            elif not config.has_section(args[0]):
                print "NO host %s found in config" % args[0]
                sys.exit(1)
            else:
                if debug:
                    print "D: No host named on command line."
                # Only packages have been named on the command line.
                host = '' 
                package_to_upload = args[0:]

    # Now Import the Upload functions
    import_upload_functions()

    # Run the same checks for all packages that have been given on
    # the command line
    for package_name in package_to_upload:
        # Check that a .changes file was given on the command line 
        # and no matching .upload file exists.
        if package_name[-8:] != '.changes':
            print "Not a .changes file."
            print "Please select a .changes file to upload."
            print "Tried to upload: %s" % package_name
            sys.exit(1)
        files_to_upload[:] = []

        # Construct the package name for further usage.
        path, name_of_package = os.path.split(package_name)
        if path == '':
            path = os.getcwd()
    
        # Define the host to upload to.
        if preferred_host == '':
            host = guess_upload_host(path, name_of_package)
        else:
            host = preferred_host
        
        # Check if we already did this upload or not
        check_upload_logfile(package_name, host, check_only, \
            call_lintian, force_upload, debug)

        # Run the change file tests.
        verify_files(path, name_of_package, host, check_only, check_version, \
            unsigned_upload, debug)

        # Run the lintian test if the user asked us to do so.
        if call_lintian or check_only or \
            config.getboolean(host, 'run_lintian') == 1:
            run_lintian_test(os.path.join(path, name_of_package))

        # don't upload, skip to the next item
        if check_only:
            print "Package checked by dput."
            continue

        # Pre-Upload Commands
        if len(config.get(host, 'pre_upload_command')) !=0:
            type = 'pre'
            execute_command(host, debug, type)

        # Check the upload methods that we have as default and per host
        if debug: print "D: Default Method: %s" % \
            config.get('DEFAULT', 'method')
        if not upload_methods.has_key(config.get('DEFAULT', 'method')):
            print "Unknown upload method: %s" % \
                config.get('DEFAULT', 'method')
            sys.exit(1)
        if debug: print "D: Host Method: %s" % config.get(host, 'method') 
        if not upload_methods.has_key(config.get(host, 'method')):
            print "Unknown upload method: %s" % config.get(host, 'method')
            sys.exit(1)

        # Inspect the Config and set appropriate upload method
        if len(config.get(host, 'method')) != 0:
            if config.get('DEFAULT', 'method') != config.get(host, 'method'):
                if (config.get('DEFAULT', 'method') == 'ftp' and \
                  config.get(host, 'method') == 'scp'):
                    method = config.get(host, 'method')      
                else:
                    method = config.get('DEFAULT', 'method')
            else:
                method = config.get('DEFAULT', 'method')
        else:
            method = config.get('DEFAULT', 'method')

        # Check now the login and redefine it if needed
        if method == 'ftp':
            login = config.get(host, 'login')
        elif method == 'scp' or method == 'rsync':
            if config.get('DEFAULT', 'login') != login:
                if (len(config.get(host, 'login')) != 0 and \
                    config.get(host, 'login') != 'username'):
                    login = config.get(host, 'login')
                if debug: print "D: Different Logins, changing them."
                if debug: print "D: Enviroment Login: %s" % login
                if debug: print "D: Config Default Login: %s" % \
                    config.get('DEFAULT','login')
                if config.get('DEFAULT', 'login') != 'username':
                    if debug: print "D: Changing login to Default " + \
                        "Configuration Value."
                    login = config.get('DEFAULT', 'login')
                    
        if debug: print "D: Login to use: %s" % login
                
        fqdn = config.get(host, 'fqdn')
        incoming = config.get(host, 'incoming')
        
        # Do the actual upload
        if not simulate:
            if debug:
                print "D: FQDN: %s" % config.get(host, 'fqdn')
                print "D: Login: %s" % login
                print "D: Incoming: %s" % config.get(host, 'incoming')
            if method == 'ftp':
                ftp_mode = config.getboolean(host, 'passive_ftp')
                if ftp_passive_mode == 1: ftp_mode = 1
                if ftp_mode == 1:
                    if debug: 
                        print "D: Using passive ftp"
                    else:
                        print "D: Using active ftp"
                upload_methods[method](fqdn, login, incoming, \
                    files_to_upload, debug, ftp_mode)
            elif method == 'scp':
                if debug and config.getboolean(host, 'scp_compress'):
                    print "D: Setting compression for scp"
                scp_compress = config.getboolean(host, 'scp_compress')
                upload_methods[method](fqdn, login, incoming, \
                    files_to_upload, debug, scp_compress)
            else:
                upload_methods[method](fqdn, login, incoming, \
                    files_to_upload, debug)
        # Or just simulate it.
        else:
            for file in files_to_upload:
                print 'Uploading with %s: %s to %s:%s' % (method, \
                    file, fqdn, incoming)

        # Create the logfile after the package has 
        # been put into the archive.
        if not simulate:
            create_upload_file(name_of_package, host, path, \
                files_to_upload, debug)
            print "Successfully uploaded packages."
        else:
            print "Simulated upload."
    
        # Run dinstall if the user asked us to do so.
        if debug:
            print "D: dinstall: %s" % dinstall
            print "D: Host Config: %s" % config.getboolean(host, 'run_dinstall')
        if config.getboolean(host, 'run_dinstall') == 1 or dinstall:
            if not simulate:
                dinstall_caller(name_of_package, host, login, debug)
            else:
                print "Would run dinstall now."
        else:
            print "Not running dinstall."

        # Post-Upload Command
        if len(config.get(host, 'post_upload_command')) != 0:
            type = 'post'
            execute_command(host, debug, type)
            
    return

# Main
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print "exiting due to user interrupt."
# vim: set expandtab tabstop=4 :
