[Zodb-checkins] CVS: ZODB3/zdaemon - zdaemon.py:1.19

Guido van Rossum guido@python.org
Tue, 19 Nov 2002 13:44:01 -0500


Update of /cvs-repository/ZODB3/zdaemon
In directory cvs.zope.org:/tmp/cvs-serv20621

Modified Files:
	zdaemon.py 
Log Message:
Add -u USER option to call setuid() and setgid() right at the start.

When run as __main__, append parent dir to sys.path.


=== ZODB3/zdaemon/zdaemon.py 1.18 => 1.19 ===
--- ZODB3/zdaemon/zdaemon.py:1.18	Thu Nov 14 17:03:46 2002
+++ ZODB3/zdaemon/zdaemon.py	Tue Nov 19 13:44:00 2002
@@ -13,6 +13,7 @@
   -f -- run forever (by default, exit when the backoff limit is exceeded)
   -h -- print usage message and exit
   -s SOCKET -- Unix socket name for client communication (default "zdsock")
+  -u USER -- run as this user (or numeric uid)
   -x LIST -- list of fatal exit codes (default "0,2"; use "" to disable)
   -z DIRECTORY -- directory to chdir into when using -d; default "/"
   program [program-arguments] -- an arbitrary application to run
@@ -77,6 +78,11 @@
 import signal
 from stat import ST_MODE
 
+if __name__ == "__main__":
+    # Add the parent of the script directory to the module search path
+    from os.path import dirname, abspath, normpath
+    sys.path.append(dirname(dirname(normpath(abspath(sys.argv[0])))))
+
 import zLOG
 
 class Options:
@@ -99,6 +105,7 @@
     forever = 0                         # -f
     sockname = "zdsock"                 # -s SOCKET
     exitcodes = [0, 2]                  # -x LIST
+    user = None                         # -u USER
     zdirectory = "/"                    # -z DIRECTORY
 
     args = []                           # Positional arguments
@@ -119,7 +126,7 @@
         if progname:
             self.progname = progname
         try:
-            self.opts, self.args = getopt.getopt(args, "b:cdfhs:x:z:")
+            self.opts, self.args = getopt.getopt(args, "b:cdfhs:u:x:z:")
         except getopt.error, msg:
             self.usage(str(msg))
         self._interpret_options()
@@ -149,6 +156,8 @@
                 sys.exit(0)
             if o == "-s":
                 self.sockname = a
+            if o == "-u":
+                self.user = a
             if o == "-x":
                 if a == "":
                     self.exitcodes = []
@@ -317,11 +326,37 @@
 
     def main(self, args=None):
         self.opts = Options(args)
+        self.set_uid()
         if self.opts.isclient:
             clt = Client(self.opts)
             clt.doit()
         else:
             self.run()
+
+    def set_uid(self):
+        if self.opts.user is None:
+            return
+        if os.name != "posix":
+            self.opts.usage("-u USER only supported on Unix")
+        if os.geteuid() != 0:
+            self.opts.usage("only root can use -u USER")
+        import pwd
+        try:
+            uid = int(self.opts.user)
+        except: # int() can raise all sorts of errors
+            try:
+                pwrec = pwd.getpwnam(self.opts.user)
+            except KeyError:
+                self.opts.usage("username %r not found" % self.opts.user)
+            uid = pwrec[2]
+        else:
+            try:
+                pwrec = pwd.getpwuid(uid)
+            except KeyError:
+                self.opts.usage("uid %r not found" % self.opts.user)
+        gid = pwrec[3]
+        os.setgid(gid)
+        os.setuid(uid)
 
     def run(self):
         self.proc = Subprocess(self.opts)