summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-06-11 15:16:09 +0000
committerLennart Poettering <lennart@poettering.net>2007-06-11 15:16:09 +0000
commitb45cd330549c234d0c061602d6239b083ddb9978 (patch)
tree019ed7655be9ce4a62f718f1d55490e00277b569
parente64d682f16b36ca16c6e8b2dada36520243a3d1c (diff)
add daemon_logv()
git-svn-id: file:///home/lennart/svn/public/libdaemon/trunk@116 153bfa13-eec0-0310-be40-b0cb6a0e1b4b
-rw-r--r--libdaemon/dexec.c17
-rw-r--r--libdaemon/dexec.h8
-rw-r--r--libdaemon/dfork.c142
-rw-r--r--libdaemon/dfork.h9
-rw-r--r--libdaemon/dlog.c12
-rw-r--r--libdaemon/dlog.h7
6 files changed, 173 insertions, 22 deletions
diff --git a/libdaemon/dexec.c b/libdaemon/dexec.c
index 3726565..10c757c 100644
--- a/libdaemon/dexec.c
+++ b/libdaemon/dexec.c
@@ -44,14 +44,13 @@
#define MAX_ARGS 100
-int daemon_exec(const char *dir, int *ret, const char *prog, ...) {
+int daemon_execv(const char *dir, int *ret, const char *prog, va_list ap) {
pid_t pid;
int p[2];
unsigned n = 0;
static char buf[256];
int sigfd, r;
fd_set fds;
- va_list ap;
assert(daemon_signal_fd() >= 0);
@@ -93,12 +92,10 @@ int daemon_exec(const char *dir, int *ret, const char *prog, ...) {
chdir("/");
}
- va_start(ap, prog);
for (i = 0; i < MAX_ARGS-1; i++)
if (!(args[i] = va_arg(ap, char*)))
break;
args[i] = NULL;
- va_end(ap);
execv(prog, args);
@@ -128,7 +125,6 @@ int daemon_exec(const char *dir, int *ret, const char *prog, ...) {
return -1;
}
-
if (FD_ISSET(p[0], &qfds)) {
char c;
@@ -190,3 +186,14 @@ int daemon_exec(const char *dir, int *ret, const char *prog, ...) {
}
}
}
+
+int daemon_exec(const char *dir, int *ret, const char *prog, ...) {
+ va_list ap;
+ int r;
+
+ va_start(ap, prog);
+ r = daemon_execv(dir, ret, prog, ap);
+ va_end(ap);
+
+ return r;
+}
diff --git a/libdaemon/dexec.h b/libdaemon/dexec.h
index 03fea2b..4b74f5e 100644
--- a/libdaemon/dexec.h
+++ b/libdaemon/dexec.h
@@ -22,6 +22,8 @@
* 02110-1301 USA
*/
+#include <stdarg.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,6 +52,12 @@ extern "C" {
*/
int daemon_exec(const char *dir, int *ret, const char *prog, ...);
+/** This variable is defined to 1 iff daemon_execv() is supported.*/
+#define DAEMON_EXECV_AVAILABLE 1
+
+/** The same as daemon_exec, but without variadic arguments */
+int daemon_execv(const char *dir, int *ret, const char *prog, va_list ap);
+
#ifdef __cplusplus
}
#endif
diff --git a/libdaemon/dfork.c b/libdaemon/dfork.c
index 86acaee..ad7a77f 100644
--- a/libdaemon/dfork.c
+++ b/libdaemon/dfork.c
@@ -36,6 +36,8 @@
#include <sys/ioctl.h>
#include <signal.h>
#include <sys/time.h>
+#include <sys/resource.h>
+#include <dirent.h>
#include "dfork.h"
#include "dnonblock.h"
@@ -199,30 +201,29 @@ pid_t daemon_fork(void) {
goto fail;
} else if (pid == 0) {
- int tty_fd;
+ int tty_fd;
/* Second child */
if (daemon_log_use & DAEMON_LOG_AUTO)
daemon_log_use = DAEMON_LOG_SYSLOG;
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTSTP, SIG_IGN);
-
- setsid();
- setpgid(0,0);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+
+ setsid();
+ setpgid(0,0);
#ifdef TIOCNOTTY
- if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
- ioctl(tty_fd, TIOCNOTTY, NULL);
- close(tty_fd);
- }
+ if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
+ ioctl(tty_fd, TIOCNOTTY, NULL);
+ close(tty_fd);
+ }
#endif
dpid = getpid();
if (atomic_write(pipe_fds[1], &dpid, sizeof(dpid)) != sizeof(dpid))
goto fail;
close(pipe_fds[1]);
-
return 0;
} else {
@@ -279,6 +280,9 @@ void daemon_retval_done(void) {
int daemon_retval_send(int i) {
ssize_t r;
+ if (_daemon_retval_pipe[1] < 0)
+ return -1;
+
r = atomic_write(_daemon_retval_pipe[1], &i, sizeof(i));
daemon_retval_done();
@@ -339,3 +343,117 @@ int daemon_retval_wait(int timeout) {
return i;
}
+int daemon_close_all(int except_fd, ...) {
+ va_list original_ap, ap;
+ int n, i, r;
+ int *p;
+
+ va_start(original_ap, except_fd);
+ va_copy(ap, original_ap);
+
+ for (n = 0; va_arg(ap, int) >= 0; n++)
+ ;
+
+ va_end(ap);
+
+ if (!(p = malloc(sizeof(int) * (n+1)))) {
+ va_end(original_ap);
+ return -1;
+ }
+
+ i = 0;
+ while ((p[i++] = va_arg(original_ap, int)) >= 0)
+ ;
+
+ p[i] = -1;
+
+ r = daemon_close_allv(p);
+ free(p);
+
+ return r;
+}
+
+/** Same as daemon_close_all but takes an array of fds, terminated by -1 */
+int daemon_close_allv(const int except_fds[]) {
+ struct rlimit rl;
+ int fd;
+
+#ifdef xxx__linux__
+
+ DIR *d;
+
+ if ((d = opendir("/proc/self/fd"))) {
+
+ struct dirent *de;
+
+ while ((de = readdir(d))) {
+ long l;
+ char *e = NULL;
+ int i, fd;
+
+ if (de->d_name[0] == '.')
+ continue;
+
+ errno = 0;
+ l = strtol(de->d_name, &e, 10);
+ if (errno != 0 || !e || *e) {
+ closedir(d);
+ errno = EINVAL;
+ return -1;
+ }
+
+ fd = (int) l;
+
+ if ((long) fd != l) {
+ closedir(d);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (fd <= 3)
+ continue;
+
+ if (fd == dirfd(d))
+ continue;
+
+ if (fd == _daemon_retval_pipe[1])
+ continue;
+
+ for (i = 0; except_fds[i] >= 0; i++)
+ if (except_fds[i] == fd)
+ continue;
+
+ if (close(fd) < 0) {
+ closedir(d);
+ return -1;
+ }
+ }
+
+ closedir(d);
+ return 0;
+ }
+
+#endif
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
+ return -1;
+
+ for (fd = 0; fd < (int) rl.rlim_max; fd++) {
+ int i;
+
+ if (fd <= 3)
+ continue;
+
+ if (fd == _daemon_retval_pipe[1])
+ continue;
+
+ for (i = 0; except_fds[i] >= 0; i++)
+ if (except_fds[i] == fd)
+ continue;
+
+ if (close(fd) < 0 && errno != EBADF)
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/libdaemon/dfork.h b/libdaemon/dfork.h
index b7effa1..fcb32c3 100644
--- a/libdaemon/dfork.h
+++ b/libdaemon/dfork.h
@@ -27,7 +27,7 @@
#ifdef __cplusplus
extern "C" {
#endif
-
+
/** \mainpage libdaemon
*
* libdaemon
@@ -100,6 +100,13 @@ int daemon_retval_wait(int timeout);
*/
int daemon_retval_send(int s);
+/** Close all file descriptors except those passed. List needs to be
+ * terminated by -1. FDs 0, 1, 2 will be kept open anyway. */
+int daemon_close_all(int except_fd, ...);
+
+/** Same as daemon_close_all but takes an array of fds, terminated by -1 */
+int daemon_close_allv(const int except_fds[]);
+
#ifdef __cplusplus
}
#endif
diff --git a/libdaemon/dlog.c b/libdaemon/dlog.c
index a50123c..3748cf8 100644
--- a/libdaemon/dlog.c
+++ b/libdaemon/dlog.c
@@ -32,10 +32,8 @@
enum daemon_log_flags daemon_log_use = DAEMON_LOG_AUTO|DAEMON_LOG_STDERR;
const char* daemon_log_ident = NULL;
-void daemon_log(int prio, const char* template, ...) {
- va_list arglist;
- va_start(arglist, template);
-
+void daemon_logv(int prio, const char* template, va_list arglist) {
+
if (daemon_log_use & DAEMON_LOG_SYSLOG) {
openlog(daemon_log_ident ? daemon_log_ident : "UNKNOWN", LOG_PID, LOG_DAEMON);
vsyslog(prio | LOG_DAEMON, template, arglist);
@@ -50,8 +48,14 @@ void daemon_log(int prio, const char* template, ...) {
vfprintf(stdout, template, arglist);
fprintf(stdout, "\n");
}
+
+}
+void daemon_log(int prio, const char* template, ...) {
+ va_list arglist;
+ va_start(arglist, template);
+ daemon_logv(prio, template, arglist);
va_end(arglist);
}
diff --git a/libdaemon/dlog.h b/libdaemon/dlog.h
index f0d5d41..ff66060 100644
--- a/libdaemon/dlog.h
+++ b/libdaemon/dlog.h
@@ -23,6 +23,7 @@
*/
#include <syslog.h>
+#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
@@ -64,6 +65,12 @@ extern const char* daemon_log_ident;
*/
void daemon_log(int prio, const char* t, ...) DAEMON_GCC_PRINTF_ATTR(2,3);
+/** This variable is defined to 1 iff daemon_logv() is supported.*/
+#define DAEMON_LOGV_AVAILABLE 1
+
+/** Same as daemon_logv, but without variadic arguments */
+void daemon_logv(int prio, const char* t, va_list ap);
+
/** Return a sensible syslog identification for daemon_log_ident
* generated from argv[0]. This will return a pointer to the file name
* of argv[0], i.e. strrchr(argv[0], '\')+1