lib: Add close_low_fd
authorVolker Lendecke <vl@samba.org>
Tue, 29 Jul 2014 18:35:10 +0000 (20:35 +0200)
committerJeremy Allison <jra@samba.org>
Fri, 1 Aug 2014 20:11:46 +0000 (22:11 +0200)
This factors out the essential code from close_low_fds for one file
descriptor: Redirect a fd to /dev/null

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
lib/util/become_daemon.c
lib/util/samba_util.h

index 0671a1ef8ed541a75daecf218b1450ed54d825e8..eba0cae579e9580e6ffd22b3baa0352484b0e1eb 100644 (file)
  Close the low 3 fd's and open dev/null in their place.
 ********************************************************************/
 
+_PUBLIC_ int close_low_fd(int fd)
+{
+#ifndef VALGRIND
+       int ret, dev_null;
+
+       dev_null = open("/dev/null", O_RDWR, 0);
+
+       if ((dev_null == -1) && (errno = ENFILE)) {
+               /*
+                * Try to free up an fd
+                */
+               ret = close(fd);
+               if (ret != 0) {
+                       return errno;
+               }
+       }
+
+       dev_null = open("/dev/null", O_RDWR, 0);
+       if (dev_null == -1) {
+               dev_null = open("/dev/null", O_WRONLY, 0);
+       }
+       if (dev_null == -1) {
+               return errno;
+       }
+
+       if (dev_null == fd) {
+               /*
+                * This can happen in the ENFILE case above
+                */
+               return 0;
+       }
+
+       ret = dup2(dev_null, fd);
+       if (ret == -1) {
+               int err = errno;
+               close(dev_null);
+               return err;
+       }
+       close(dev_null);
+#endif
+       return 0;
+}
+
 _PUBLIC_ void close_low_fds(bool stdin_too, bool stdout_too, bool stderr_too)
 {
 #ifndef VALGRIND
index 2ffe028959b445c21a9ad4a89eb626c5f3df5b81..b31ee1f8f0a24c4164093db23cce3bdfe3cf5cc9 100644 (file)
@@ -838,6 +838,11 @@ _PUBLIC_ int idr_remove(struct idr_context *idp, int id);
 
 /* The following definitions come from lib/util/become_daemon.c  */
 
+/**
+ Close a fd and open dev/null in its place
+**/
+_PUBLIC_ int close_low_fd(int fd);
+
 /**
  Close the low 3 fd's and open dev/null in their place
 **/