# This file is part of jwmud, written by Helmut Pozimski in 2014. # # jwmud 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, version 2 of the License. # # jwmud 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 jwmud. If not, see . # -*- coding: utf8 -*- import os import sys class Daemon(object): """ Tries to implement a well behaving unix daemon in a generic way, so the code could be used in different projects. """ def __init__(self, pfile_path, pfile_name): """ Initializes the object. """ self.__pfile_path = pfile_path self.__pfile_name = pfile_name self.__daemon = False self.__pid = 0 self.__pidfile = "" def Daemonize(self): """ Turns the calling process into a daemon running on it's own """ try: # Fork for the first time self.__pid = os.fork() except OSError: sys.exit(os.EX_OSERR) else: if self.__pid > 0: sys.exit(os.EX_OK) # Become session and group leader # noinspection PyArgumentList os.setsid() try: #Fork for the second time self.__pid = os.fork() except OSError: sys.exit(os.EX_OSERR) else: if self.__pid > 0: sys.exit(os.EX_OK) # Change cwd to / to avoid interfering with other mounted file systems os.chdir("/") # Reset the umask os.umask(0) # Close possibly open file descriptors os.close(0) os.close(1) os.close(2) # And redirect them to /dev/null os.open("/dev/null", 0) os.open("/dev/null", 1) os.open("/dev/null", 2) self.__daemon = True def DropPriv(self, uid, gid): """ If the daemon is running as root user, drop privileges and continue running as the defined unprivileged user """ if os.getuid() == 0: os.setgid(gid) os.setuid(uid) def SetName(self, name, cmdline): """ Sets the name of the process shown visible in ps and top, this allows to make your daemon look more like a standalone program instead of a python script. """ try: # First check if prctl is available, otherwise this # function does nothing # noinspection PyUnresolvedReferences import prctl except ImportError: return False else: prctl.set_name(name) prctl.set_proctitle(cmdline) return True def Start(self): """ Performs the operations needed to "start" the daemon """ if self.__daemon is True: if os.access(self.__pfile_path, os.F_OK & os.W_OK): self.__pidfile = open(os.path.join(self.__pfile_path, self.__pfile_name), "w") self.__pidfile.write(str(os.getpid()) + "\n") self.__pidfile.close() return True else: return False else: return False def Stop(self): """ Performs the operations needed to stop the daemon """ if self.__daemon is True: try: os.remove(os.path.join(self.__pfile_path, self.__pfile_name)) except OSError: return False else: return True else: return True