#!/usr/bin/python -u
#
# Copyright (c) 1999 Red Hat, Inc.
# $Id: main.py,v 1.14 1999/09/26 21:49:43 pbrown Exp $

import sys
import os
sys.path.append("/usr/share/up2date")
import urllib, string
from threading import Thread

def passPackageList(pkgListFile):
    # okay, noe the client simply read the contents of the
    # pkgListFile and tries to throw it into the Unix domain
    # socket where something else should be waiting for it
    from socket import *
    import time
    
    # Probably these should be config options later, but for now we'd better
    # not let the users play with these
    sock_path = "/var/run/up2date.sock"
    sock_timeout = 15

    sock = socket(AF_UNIX, SOCK_STREAM)
    if sock < 0:
        print "up2date client: Error processing data"
        print "Could not create a socket for sending data to the parent process"
        return -1

    while sock.connect_ex(sock_path) != 0:
        # wait on the parent to create that socket for us
        time.sleep(1)
        sock_timeout = sock_timeout - 1
        if sock_timeout <= 0:
            return -1
        
    # we're connected okay
    if not os.access(pkgListFile, os.R_OK):
        print "Cannot open package file \"%s\" for "
        "reading.\n  Do you have sufficient "
        "permissions?" % pkgListFile
        return -1
        
    # you gotta love python
    dataStr = open(pkgListFile, 'r').read()

    need_write = len(dataStr)
    while 1:
        try:
            w = os.write(sock.fileno(), dataStr)
        except:
            print "Could not write data to the parent socket"
            break
        if w >= 0:
            need_write = need_write - w
        else:
            # some weird error
            print "Could not write %d bytes to parent's socket" % (need_write,)
        if need_write <= 0:
            # we're done
            break
    if need_write > 0:
        # could not write the whole thing
        return -1
    sock.close()
    return 0

if __name__ == "__main__":
    import getopt
    
    batch = 0
    authStr = ""
    pkgListFile = ""

    
    if os.geteuid() != 0:
	print "You must run Update Agent as root."
	sys.exit(-1)

    try:
	optlist, args = getopt.getopt(sys.argv[1:], 
			       'bhp:a:', [ 'batch', 'help',
					   'auth=', 'packagelist=' ])

    except getopt.error, msg:
	print("Error parsing command line arguments: %s" % msg)
	sys.exit()

    if args:
	print "Available command line options:"
	print "-a <auth>, --auth=<auth>        - override authorization information"
	print "-b, --batch                     - batch mode (no GUI, email results)"
	print "-p <list>, --packagelist=<list> - a list of packages to retrieve"
	print "-h, --help                      - this help"
	sys.exit()
	
    for opt in optlist:
	if opt[0] == '-b' or opt[0] == 'batch':
	    batch = 1
	elif opt[0] == '-a' or opt[0] == 'auth=':
	    authStr = opt[1]
	elif opt[0] == '-p' or opt[0] == 'packagelist=':
	    pkgListFile = opt[1]
	elif opt[0] == '-h' or opt[0] == 'help':
	    print "Available command line options:"
	    print "-a <auth>, --auth=<auth> - override default authorization information"
	    print "-b, --batch - run in batch mode (no GUI, email results)"
	    print "-p <list>, --packagelist=<list> - a list of packages to retrieve"
	    print "-h, --help - this help"
	    sys.exit()

    # stop gnome from stealing argument processing
    for arg in sys.argv[1:]:
	sys.argv.remove(arg)
    sys.argc = 1

    if not batch:
	from gui import Gui
	from os import environ
	import re
	from gtk import mainloop, threads_enter, threads_leave

	# first thing we need to do is check for proper mime types
	# in this user's .mailcap
	try:
	    f = open("%s/.mailcap" % environ['HOME'], "r")
	except:
            # XXX: what if we don't have write permission? --gafton
	    f = open("%s/.mailcap" % environ['HOME'], "w")
	    f.close()
	    f = open("%s/.mailcap" % environ['HOME'], "r")

	found = 0
	for line in f.readlines():
	    if re.match("application/redhat-package-list", line):
		found = 1
		break
	f.close()
	if not found:
	    f = open("%s/.mailcap" % environ['HOME'], "w+")
	    f.write("#mailcap entry added by Red Hat Update Agent\n")
	    f.write("application/redhat-package-list;/usr/sbin/up2date -p %s\n")
	    f.close()

	class GtkMainThread (Thread):
	    def run (self):
		self.setName ("gtk_main")
		threads_enter ()
		mainloop ()
		threads_leave ()

	if pkgListFile != "":
            if passPackageList(pkgListFile) != 0:
                sys.exit(-1)
            sys.exit(0)
            
	# in gui mode, we let the Gui handle all interactions
	# (including creation) with the Client class.
	g = Gui(authStr)
        m = GtkMainThread ()
	m.start ()
    else:
	from client import Client
	# in batch mode, the client does nothing but
	# follow orders from outside.
	c = Client(authStr)
    
	if pkgListFile == "":
	    c.getPackageList()
	    c.removeSkipPackages(c.pkgList)
	    c.removeInstalledPackages(c.pkgList, 
				      c.cfg.readEntry("retrieveNew"))
	    if len(c.pkgList) == 0:
		c.addReply("No packages to install, quitting.")
		c.finishUp()

        else:
	    f = open(pkgListFile, 'r')
	    stateData = f.readline()
	    stateData = urllib.unquote_plus(stateData)
	    c.state = stateData
	    f.readline() # throw away blank separator line
	    for line in f.readlines():
		name, epoch, version, release = string.split(line)
		c.pkgList.append("%s %s %s %s" % (name, epoch, version, release))
	    f.close()

	c.retrieveHeaders(c.pkgList)
	c.removeSkipFiles(c.pkgList)

	if len(c.pkgList) == 0:
	    c.addReply("No packages to install, quitting.")
	    c.finishUp()

	c.dryRun()

	c.checkFreeDiskSpace()

	c.retrievePackages()

	if not c.cfg.readEntry("retrieveOnly"):
	    c.installPackages()

	if (not c.cfg.readEntry("retrieveOnly") and 
	    not c.cfg.readEntry("keepAfterInstall")):
	    c.deletePackageFiles()

	c.addReply("Done.")
	c.finishUp()
