import os, sys, time
import pwd, grp
import signal


# Set to desired naming prefix
PREFIX = 'daemonSkeleton'

# Change these as seen fit
PID = PREFIX + '.pid'
PIDPATH = '/var/run/' + PREFIX
PIDFILE = PIDPATH + '/' + PID
LOGDIR = '/var/log/' + PREFIX
UID = 0
GID = 0
USER = 'daemon'                 # Set to desired user
GROUP = 'nogroup'               # Set to desired group
UMASK = 022                     # Set to desired umask


# Shutdown signal handler
def shutdown(sig, frame):
    # Remove PID file
    if (os.path.exists(PIDFILE)):
        os.unlink(PIDFILE)

    sys.exit(0)
    
   

def startDaemonMode():
    # Ignore child signal. This prevents child processes
    # from going zombie when they quit.
    signal.signal(signal.SIGCHLD, signal.SIG_IGN)

    # Quick sanity check
    if (os.path.exists(PIDFILE)):
        print "Found PID file"
        print "Checking if I'm already running"

        fp = open(PIDFILE, 'r')
        pid = fp.readline()
        fp.close()

        # Make sure we're not already running
        if (os.path.exists('/proc/' + pid)):
            print "Error: already running. Abort!"
            os._exit(0)
        
        print "PID file found, but process not running."
        print "Unclean shutdown???"

    # Initial Fork
    if (os.fork()):
        time.sleep(0.5)

        # This is used instead of sys.exit(), because
        # this function doesn't call atexit stuff.
        os._exit(0)
    else:
        os.setsid()                 # Become session leader
        os.chdir('/')               # cd /
        os.umask(UMASK)             # So we don't inherit users' umask

        # Find UID and GID for USER/GROUP variables
        # These will be used when we drop privleges,
        # and to set desired permissions
        UID = int(pwd.getpwnam(USER)[2])
        GID = int(grp.getgrnam(GROUP)[2])

        # Make log dir
        if (not os.path.exists(LOGDIR)):
            os.mkdir(LOGDIR)
            os.chown(LOGDIR, UID, GID)

        # Make run dir, that we can write to
        # after dropping privleges
        if (not os.path.exists(PIDPATH)):
            os.mkdir(PIDPATH)
            os.chown(PIDPATH, UID, GID)

        # Fork again, to detach from terminal
        pid = os.fork()

        if (pid): # Parent
            # Write PID file
            f = open(PIDFILE, 'w')
            f.write(str(pid))

            # This forces disk sync.
            # MUST be done in this order.
            f.flush()
            os.fsync(f.fileno())

            # Close
            f.close()

            # Set permissions, so child can delete PID file on exit
            os.chown(PIDFILE, UID, GID)

            # Exit.
            os._exit(0)
        else: # Child
            # Drop privleges
            os.setgid(GID)
            os.setuid(UID)

            # Redirect stdin to /dev/null
            nstdin = open('/dev/null', 'r')

            # Redirect stdout / stderr to files
            nstdout = open(LOGDIR + '/' + 'stdout.log', 'a')
            nstderr = open(LOGDIR + '/' + 'stderr.log', 'a')

            # This just duplicates the file descriptors
            os.dup2(nstdin.fileno(), sys.stdin.fileno())
            os.dup2(nstdout.fileno(), sys.stdout.fileno())
            os.dup2(nstderr.fileno(), sys.stderr.fileno())

            # Call main
            main()
            

# Main Loop
def main():
    # Install desired signals
    signal.signal(signal.SIGQUIT, shutdown)
    signal.signal(signal.SIGTERM, shutdown)

    # Put your code here
    time.sleep(10)
    
    # Suicide
    os.kill(os.getpid(), signal.SIGQUIT)


if __name__ == "__main__":
    startDaemonMode()

