#!/usr/bin/python3
# Display Engine Client - Copyright 2019 Lucid Networks - Stephen Loeckle

import os
import traceback
import inspect
import sys
import logging
import configparser
import argparse
import json
import socketserver
import pickle
import struct
import sqlite3
import subprocess
import shlex
import netifaces
import tkinter
from time import time, sleep
from datetime import datetime, timedelta
from declientlib import api, browserrestart, cloudcmd, displaysize, emailscreenshot, getcurrenturl, getmac, jobs, hotkeywatcher, maintenance, sendemail, sendlog, stats, systemanalysis, updatedict, uptime
from multiprocessing import Process

database = ('/var/lib/declient/declient.db')

class LogRecordStreamHandler(socketserver.StreamRequestHandler):
    def handle(self):
        while True:
            chunk = self.connection.recv(4)
            if len(chunk) < 4:
                break
            slen = struct.unpack('>L', chunk)[0]
            chunk = self.connection.recv(slen)
            while len(chunk) < slen:
                chunk = chunk + self.connection.recv(slen - len(chunk))
            obj = self.unPickle(chunk)
            record = logging.makeLogRecord(obj)
            self.handleLogRecord(record)

    def unPickle(self, data):
#        sortedresults = collections.OrderedDict(sorted(pickle.loads(data).items()))
#        for key,val in sortedresults.items():
#            print("{0} = {1}".format(key,val))
        return pickle.loads(data)

    def handleLogRecord(self, record):
        # if a name is specified, we use the named logger rather than the one
        # implied by the record.
        if self.server.logname is not None:
            name = self.server.logname
        else:
            name = record.name
        logger = logging.getLogger(name)
        # N.B. EVERY record gets logged. This is because Logger.handle
        # is normally called AFTER logger-level filtering. If you want
        # to do filtering, do it at the client end to save wasting
        # cycles and network bandwidth!
        logger.handle(record)

class LogRecordSocketReceiver(socketserver.ThreadingTCPServer):
    allow_reuse_address = True
    declientloggingport = 9022
    def __init__(self, host='localhost',
                 port=declientloggingport,
                 handler=LogRecordStreamHandler):
        socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
        self.abort = 0
        self.timeout = 1
        self.logname = None

    def serve_until_stopped(self):
        import select
        abort = 0
        while not abort:
            rd, wr, ex = select.select([self.socket.fileno()],
                                       [], [],
                                       self.timeout)
            if rd:
                self.handle_request()
            abort = self.abort
            
def engines(sysinfo):
    gotthefunc = inspect.stack()[0][3]
    if os.path.exists(database):
        conn = sqlite3.connect(database)
        c = conn.cursor()
    else:
        msg = ('Database not found! Halting!')
        sendlog(gotthefunc, msg, 50)
        sys.exit()
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'shutdown'))
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'apishutdowncomplete'))
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'cloudcmdshutdowncomplete'))
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'systemanalysisshutdowncomplete'))
    c.execute('SELECT value from system WHERE tags = ?', ('maintenance',))
    row = c.fetchone()
    if row[0] == 1:
        c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'maintenance'))
    if row[0] == 2:
        subject = 'Permenant Maintenance Mode Notification'
        message = 'Reminder: this box is in permenant maintenance mode.'
        sendemail(sysinfo,subject,message)
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'urlerrors'))
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'checkfundamentalsruns'))
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'screenanalysisruns'))
    c.execute('UPDATE system SET value = ? WHERE tags = ?', (0, 'activeproblemcount'))
    c.execute('UPDATE system SET strvalue = ? WHERE tags = ?', ('', 'activeproblem'))
    c.execute('UPDATE system SET strvalue = ? WHERE tags = ?', ('' ,'remediation'))
    datenow = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    c.execute('UPDATE system SET strvalue = ? WHERE tags = ?', (datenow, 'startuptime'))
    conn.commit()

    logworker = Process(target=logserver)
    logworker.start()
    
    sleep(1)
   
# Setup system environment and variable defaults

    logger = logging.getLogger('main')
    if sysinfo['SYSTEM']['CONFIG']['LOGLEVEL'] == '10':
        logger.setLevel(logging.DEBUG)
    if sysinfo['SYSTEM']['CONFIG']['LOGLEVEL'] == '20':
        logger.setLevel(logging.INFO)
    if sysinfo['SYSTEM']['CONFIG']['LOGLEVEL'] == '30':
        logger.setLevel(logging.WARNING)
    if sysinfo['SYSTEM']['CONFIG']['LOGLEVEL'] == '40':
        logger.setLevel(logging.ERROR)
    if sysinfo['SYSTEM']['CONFIG']['LOGLEVEL'] == '50':
        logger.setLevel(logging.CRITICAL)

    sock = logging.handlers.SocketHandler('localhost', 9022)
    logger.addHandler(sock)

    msg = ('Debug test')
    sendlog(gotthefunc, msg, 10)
    msg = ('Info test')
    sendlog(gotthefunc, msg, 20)
    msg = ('Warning test')
    sendlog(gotthefunc, msg, 30)
    msg = ('Error test')
    sendlog(gotthefunc, msg, 40)
    msg = ('Critical test')
    sendlog(gotthefunc, msg, 50)
   
    try:
        sysinfo['SYSTEM']['MAC'] = getmac(sysinfo,'eth0')
    except:
        msg = ('Unknown Error in {0} Getting MAC Address! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        print(msg)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        sendlog(gotthefunc, msg, 10)
        print(msg)
        sys.exit()
    if sysinfo['SYSTEM']['CONFIG']['BOXTYPE'] != 'control':
        browserpid = browserrestart(sysinfo)
        c.execute('UPDATE system SET value = ? WHERE tags = ?', (browserpid,'browserpid'))
        conn.commit()
    
#    subject = 'Startup Email'
#    message = 'This is the startup email'
#    sendemail(sysinfo,subject,message)

    apiworker = Process(target=api, args=(sysinfo,))
    apiworker.start()
    sleep(1)
    cloudworker = Process(target=cloudcmd, args=(sysinfo,))
    cloudworker.start()
    sleep(1)
    systemanalysisworker = Process(target=systemanalysis, args=(sysinfo,))
    systemanalysisworker.start()
    sleep(3)
    jobworker = Process(target=jobs, args=(sysinfo,))
    jobworker.start()
    hotkeyworker = Process(target=hotkeywatcher, args=(sysinfo,))
    hotkeyworker.start()

    logworker.join()
    apiworker.join()
    cloudworker.join()
    systemanalysisworker.join()
    jobworker.join()
    hotkeyworker.join()

def logserver():
#    logging.basicConfig(format='%(asctime)s %(processName)-10s %(name)s %(levelname)-8s %(message)s',handlers=[logging.handlers.RotatingFileHandler('/var/log/declient/declient.log', mode='a', maxBytes=10*1024*1024, backupCount=0, encoding=None, delay=False)])
    logging.basicConfig(format='%(asctime)s %(processName)-10s %(name)s %(levelname)-8s %(message)s',handlers=[logging.handlers.RotatingFileHandler('/var/log/declient/declient.log', mode='a', maxBytes=10000*1024, backupCount=30, encoding=None, delay=False)])
#    logging.basicConfig(format='%(asctime)s %(processName)-10s %(name)s %(levelname)-8s %(message)s',filename='/var/log/declient/declient.log')
    tcpserver = LogRecordSocketReceiver()
    tcpserver.serve_until_stopped()

def main(sysinfo):
    gotthefunc = inspect.stack()[0][3]
    msg = ('Entered {} function'.format(gotthefunc))

    tmpdir = '/media/ramdisk/de'
    try:
        os.mkdir(tmpdir)
    except:
        pass
   
# Setup system defaults

    sysinfo['SYSTEM']['CONFIG'] = {}
    sysinfo['SYSTEM']['CONFIG']['BROWSER'] = {}
    sysinfo['SYSTEM']['CONFIG']['NETWORK'] = {}

# Read config file

    config = configparser.ConfigParser()
    try:
        config.read(['/etc/declient/declient.conf'])
    except configparser.Error as e:
        msg = ('Unable to read configuration file /etc/declient/declient.conf! Halting!')
        sendlog(gotthefunc, msg, 40)
        sys.exit()
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
#        sysinfo['SYSTEM']['CONFIG']['EMAIL'] = config.get('system', 'emailnotification')
        sysinfo['SYSTEM']['CONFIG']['EMAIL'] = [e.strip() for e in config.get('system', 'emailnotification').split(',')]
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No email(s) for notifications specified in configuration file. Continuing with no notifications.')
        sendlog(gotthefunc, msg, 40)
        sysinfo['SYSTEM']['CONFIG']['EMAIL'] = None
        pass
    except configparser.Error as e:
        msg = ('Config read entry system email notification error! Clearing entry.')
        sendlog(gotthefunc, msg, 40)
        sysinfo['SYSTEM']['CONFIG']['EMAIL'] = None
        pass
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
        sysinfo['SYSTEM']['CONFIG']['SMTPHOST'] = config.get('system', 'smtphost')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No smtp hosts for notifications specified in configuration file. Default to localhost.')
        sendlog(gotthefunc, msg, 40)
        sysinfo['SYSTEM']['CONFIG']['SMTPHOST'] = 'localhost'
        pass
    except configparser.Error as e:
        msg = ('Config read entry system email notification error! Clearing entry.')
        sendlog(gotthefunc, msg, 40)
        sysinfo['SYSTEM']['CONFIG']['SMTPHOST'] = 'localhost'
        pass
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    # Load license key
    try:
        sysinfo['SYSTEM']['CONFIG']['LICENSEKEY'] = config.get('system', 'licensekey')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sys.exit()
        
    if not sysinfo['SYSTEM']['CONFIG']['LICENSEKEY']:
        subject = 'No license key in configuration file!'
        msg = ('No license key in configuration file!')
        sendemail(sysinfo,subject,msg)
        
    try:
        sysinfo['SYSTEM']['CONFIG']['BOXTYPE'] = config.get('system', 'boxtype')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sys.exit()
        
    try:
        sysinfo['SYSTEM']['CONFIG']['INTERVAL'] = int(config.get('system', 'interval'))
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['INTERVAL'] = 1
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['INTERVAL'] = 1
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['INTERVAL'] = 1
        
    try:
        sysinfo['SYSTEM']['CONFIG']['DAILYREBOOTTIME'] = config.get('system', 'dailyreboottime')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        sysinfo['SYSTEM']['CONFIG']['DAILYREBOOTTIME'] = None
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['DAILYREBOOTTIME'] = None
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['DAILYREBOOTTIME'] = None
        
    try:
        sysinfo['SYSTEM']['CONFIG']['STARTUPSECS'] = int(config.get('system', 'startupsecs'))
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        sysinfo['SYSTEM']['CONFIG']['STARTUPSECS'] = 60
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['STARTUPSECS'] = 60
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['STARTUPSECS'] = 60

    try:
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISSECS'] = int(config.get('system', 'systemanalysissecs'))
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISSECS'] = 30
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISSECS'] = 30
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISSECS'] = 30
        
    try:
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISPROBLEMSECS'] = int(config.get('system', 'systemanalysisproblemsecs'))
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISPROBLEMSECS'] = 15
    except configparser.Error as e:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISPROBLEMSECS'] = 15
    except:
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sysinfo['SYSTEM']['CONFIG']['SYSTEMANALYSISPROBLEMSECS'] = 15

    try:
        sysinfo['SYSTEM']['CONFIG']['USER'] = config.get('system', 'user')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No run-as user defined in configuration file! Defaulting to kiosk!')
        sendlog(gotthefunc, msg, 40)
        sysinfo['SYSTEM']['CONFIG']['USER'] = 'kiosk'
    except configparser.Error as e:
        msg = ('Config read entry system license key error! Halting!')
        sendlog(gotthefunc, msg, 40)
        sys.exit()
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
        sysinfo['SYSTEM']['CONFIG']['LOGLEVEL'] = config.get('system', 'loglevel')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No logging type specified in configuration file. Defaulting to INFO!')
        sendlog(gotthefunc, msg, 40)
        sysinfo['SYSTEM']['LOGLEVEL'] = '10'
        pass
    except configparser.Error as e:
        msg = ('Config read entry system loglevel error! Halting!')
        sendlog(gotthefunc, msg, 40)
        sys.exit()
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
        sysinfo['SYSTEM']['CONFIG']['BROWSER']['NAME'] = config.get('browser', 'name')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No browser name specified. Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['BROWSER']['NAME']))
        sendlog(gotthefunc, msg, 40)
        pass
    except configparser.Error as e:
        msg = ('Config read entry browser name! Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['BROWSER']['NAME']))
        sendlog(gotthefunc, msg, 40)
        pass
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
        sysinfo['SYSTEM']['CONFIG']['BROWSER']['PATH'] = config.get('browser', 'path')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No browser path specified. Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['BROWSER']['PATH']))
        sendlog(gotthefunc, msg, 40)
        pass
    except configparser.Error as e:
        msg = ('Config read entry browser path! Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['BROWSER']['PATH']))
        sendlog(gotthefunc, msg, 40)
        pass
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
        sysinfo['SYSTEM']['CONFIG']['BROWSER']['OPTIONS'] = config.get('browser', 'options')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No browser options specified. Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['BROWSER']['OPTIONS']))
        sendlog(gotthefunc, msg, 40)
        pass
    except configparser.Error as e:
        msg = ('Config read entry browser options! Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['BROWSER']['OPTIONS']))
        sendlog(gotthefunc, msg, 40)
        pass
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
    try:
        sysinfo['SYSTEM']['CONFIG']['NETWORK']['HTTPPROXY'] = config.get('network', 'httpproxy')
    except (configparser.NoOptionError, configparser.InterpolationMissingOptionError):
        msg = ('No network http proxy specified. Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['NETWORK']['HTTPPROXY']))
        sendlog(gotthefunc, msg, 40)
        pass
    except configparser.Error as e:
        msg = ('Config read entry network options! Defaulting to {}.'.format(sysinfo['SYSTEM']['CONFIG']['NETWORK']['HTTPPROXY']))
        sendlog(gotthefunc, msg, 40)
        pass
    except:
        msg = ('Unknown Error in {0} Reading Config! Halting!'.format(gotthefunc))
        sendlog(gotthefunc, msg, 40)
        err = traceback.format_exc()
        msg = ('Unknown Error in {0} Detail: {1}'.format(gotthefunc,err))
        print(msg)
        sendlog(gotthefunc, msg, 10)
        sys.exit()
        
# Setup OS environment

    os.environ["DISPLAY"] = ":0"

    displayconnected = 0

    while displayconnected == 0:
        try:
            displayroot = tkinter.Tk()
        except tkinter.TclError as error:
            msg = ('No Diplay Connected. Waiting 30 Seconds.')
            sendlog(gotthefunc, msg, 40)
            pass
            sleep(30)
        except:
            err = traceback.format_exc()
            msg = ('Unknown Error: {}'.format(err))
            sendlog(gotthefunc, msg, 40)
            pass
            sleep(30)
        else:
            dh,dv = displaysize(displayroot)
            msg = ('Display Connected. Resolution: {} x {}'.format(dh,dv))
            sendlog(gotthefunc, msg, 10)
            displayconnected = 1
            displayroot.destroy()
        

#    xsetcmd = ('{} {} {} {}'.format('xset', 's', 'off', '-dpms'))
    xsetcmd = ('{} {} {} {} {}'.format('xset', 'dpms', '0', '0', '0'))
    subprocess.call(shlex.split(xsetcmd))
    xsetcmd = ('{} {} {} {} {} {} {} {}'.format('xset', '-dpms', 's', 'off', 's', 'noblank', 's', 'noexpose'))
    subprocess.call(shlex.split(xsetcmd))
    xsetcmd = ('{} {} {} {}'.format('xset', 's', '0', '0'))
    subprocess.call(shlex.split(xsetcmd))
    
        
    if sysinfo['SYSTEM']['CONFIG']['NETWORK']['HTTPPROXY']:
        os.environ["http_proxy"] = sysinfo['SYSTEM']['CONFIG']['NETWORK']['HTTPPROXY']
        os.environ["https_proxy"] = sysinfo['SYSTEM']['CONFIG']['NETWORK']['HTTPPROXY']
        
# Parse CLI options
        
    parser = argparse.ArgumentParser(description='Display Engine Client System')
    parser.add_argument('-e', '--engines', help = 'Run declient client engines', action="store_true")
    parser.add_argument('-s', '--stats', help = 'Show declient stats', action='store_true')
    parser.add_argument('-se', '--statsemail', metavar = 'EMAILADDRESS', help = 'Send stats to email address. Email address required. Multiple email addresses can be added, space delimited', nargs='+')
    parser.add_argument('-m', '--maint', help = 'Put system in maintenance mode. Restarts Chrome out of kiosk mode.', action='store_true')
    parser.add_argument('-mon', '--mainton', help = 'Put system in permenant maintenance mode until removed. Restarts Chrome out of kiosk mode.', action='store_true')
    parser.add_argument('-moff', '--maintoff', help = 'Take system out of permenant maintenance mode.', action='store_true')
    parser.add_argument('-es', '--emailscreenshot', metavar = 'EMAILADDRESS', help = 'Send screenshot to email address. Email address required. Multiple email addresses can be added, space delimited.', nargs='+')
    parser.add_argument('-sd', '--shutdown', help = 'Shutdown the system', action='store_true')
    parser.add_argument('-u', '--url', help = 'Get current URL from Chrome', action='store_true')
    
    
    args = parser.parse_args()
    if (not args.engines and not args.stats and not args.maint and not args.emailscreenshot and not args.mainton and not args.maintoff and not args.statsemail and not args.shutdown and not args.url):
        parser.print_help()
    if args.engines:
        ut, us = uptime()
        startupthreshold = 300
        startupwaittime = 15
        if ut < startupthreshold:
            msg = ('Uptime is less than {}. Pausing startup for {} seconds.'.format(startupthreshold, startupwaittime))
            sleep(startupwaittime)
        gateways = netifaces.gateways()
        sysinfo['SYSTEM']['DEFAULTGATEWAY'] = gateways['default'][netifaces.AF_INET][0]
        engines(sysinfo)       
    elif args.stats:
        stats(1)
    elif args.statsemail:
        subject = 'Stats Email'
        message = stats(2)
###### We aren't simply passing the config file email address to allow for a different recipient to receive stats. So, we're creating the variables required to run sendemail from CLI arguments and existing SMTP host data.
        statsemailinfo = {}
        statsemailinfo['SYSTEM'] = {}
        statsemailinfo['SYSTEM']['CONFIG'] = {}
        statsemailinfo['SYSTEM']['CONFIG']['EMAIL'] = args.statsemail
        statsemailinfo['SYSTEM']['CONFIG']['SMTPHOST'] = sysinfo['SYSTEM']['CONFIG']['SMTPHOST']
        sendemail(statsemailinfo,subject,message)
    elif args.maint:
        maintenance()
    elif args.mainton:
        maintenance(0,2)
    elif args.maintoff:
        maintenance(0,0)
    elif args.emailscreenshot:
        emailscreenshot(sysinfo, args.emailscreenshot)
    elif args.url:
        currenturl = getcurrenturl(sysinfo['SYSTEM']['CONFIG']['USER'])
        print(currenturl)
    elif args.shutdown:
        if os.path.exists(database):
            conn = sqlite3.connect(database)
            c = conn.cursor()
        else:
            msg = ('Database not found! Halting!')
            sendlog(gotthefunc, msg, 50)
            sys.exit()
        dbsuccess = 0
        while dbsuccess == 0:
            try:
                c.execute('UPDATE system SET strvalue = ?, notes = ? WHERE tags = ?', ('shutdown','Shutdown request from API','remediation'))
                conn.commit()
            except sqlite3.OperationalError:
                msg = ('API: Database locked. Trying again.')
                sendlog(gotthefunc, msg, 10)
                pass
                sleep(1)
            else:
                dbsuccess = 1
                conn.close()
    else:
        parser.print_help()

if __name__ == '__main__':
    sysinfo = {}
    sysinfo['SYSTEM'] = {}
    sysinfo['SYSTEM']['PID'] =  os.getpid()
    main(sysinfo)