|
@@ -0,0 +1,123 @@
|
|
|
+# 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 <http://www.gnu.org/licenses/>.
|
|
|
+
|
|
|
+# -*- 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
|