'''
    This module is used to fork the current process into a daemon.
    Almost none of this is necessary (or advisable) if your daemon 
    is being started by inetd. In that case, stdin, stdout and stderr are 
    all set up for you to refer to the network connection, and the fork()s 
    and session manipulation should not be done (to avoid confusing inetd). 
    Only the chdir() and umask() steps remain as useful.
'''
    
import sys, os, time, logging
from signal import SIGTERM

class Daemon:
    def __init__(self, appName = 'default', logfile='/dev/null', pidfile=None, startmsg = 'started with pid %s' ):
        self.__logfile   = logfile
        self.__pidfile   = pidfile
        self.__startmsg  = startmsg
	self.__appName   = appName
	self.__logger    = None
	''' 
    		initialize the logger
    	'''
	newfile = None
	self.__logger = logging.getLogger(self.__appName)
        if not (os.path.exists(os.path.dirname(self.__logfile))):
		os.makedirs(os.path.dirname(self.__logfile))
        	newFile = open(self.__logfile, "w")
	else:
		newFile = open(self.__logfile, "a")
        newFile.close()
                
	hdlr = logging.FileHandler(self.__logfile)
	formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
	hdlr.setFormatter(formatter)
	self.__logger.addHandler(hdlr) 
	self.__logger.setLevel(logging.INFO)
    
    def __deamonize(self):
        # Do first fork.
        try: 
            pid = os.fork() 
	    # Exit first parent.
            if pid > 0: sys.exit(0)
        except OSError, e: 
            self.__logger.error("fork #1 failed: (%d) %s" % (e.errno, e.strerror))
            sys.exit(1)
        
        # Decouple from parent environment.
        os.chdir("/") 
        os.umask(0) 
        os.setsid() 
    
        # Do second fork.
        try: 
            pid = os.fork()
	    # Exit second parent.
            if pid > 0: sys.exit(0)
        except OSError, e: 
            self.__logger.error("fork #2 failed: (%d) %s" % (e.errno, e.strerror))
            sys.exit(1)
    
        pid = str(os.getpid())
        self.__logger.info("\n%s\n" % self.__startmsg % pid)
        if self.__pidfile: file(self.__pidfile,'w+').write("%s\n" % pid)
    

    def execCmd(self, cmd):
        action = cmd
        try:
            pf  = file(self.__pidfile,'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = None
	
	if 'status' == action:
	    if not pid:
                self.__logger.info('Status: Stopped\n')

            else: self.__logger.info('Status: Running\n')
            sys.exit(0)

        if 'stop' == action or 'restart' == action:
            if not pid:
                self.__logger.error('Could not stop, pid file %s missing.', self.__pidfile)
                if 'stop' == action:
                    sys.exit(0)
                action = 'start'
                pid = None
            else:
               try:
                  while 1:
                      os.kill(pid,SIGTERM)
		      time.sleep(1)
               except OSError, err:
                  err = str(err)
                  if err.find("No such process") > 0:
                      os.remove(self.__pidfile)
                      if 'stop' == action:
			  self.__logger.info('Correctly stopped')
                          sys.exit(0)
                      action = 'start'
                      pid = None
                  else:
                      print str(err)
                      sys.exit(1)

        if 'start' == action:
            if pid:
                self.__logger.error('Start aborted because pidfile %s already exists.', self.__pidfile)
		print 'Start aborted because pidfile ' + self.__pidfile +' already exists. Stop it then start it again.'
                sys.exit(1)
            self.__deamonize()

    def getLogger(self):
	return self.__logger

