summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2008-03-18 09:11:45 +0000
committerdeva <deva>2008-03-18 09:11:45 +0000
commit42f978a143b3bf2b2f8696ef70ccf712ed147350 (patch)
treeae6bec6b941106aadc5c0e1cd57390e2d387ead2
parent6cbd8761972281325956d6bc2c34850fe09acf91 (diff)
A lot of changes to the daemon code.
-rw-r--r--server/src/Makefile.am2
-rw-r--r--server/src/daemon.cc158
-rw-r--r--server/src/daemon.h45
-rw-r--r--server/src/pracrod.cc73
4 files changed, 222 insertions, 56 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index 4cee6cf..672b8e7 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -7,6 +7,7 @@ pracrod_CXXFLAGS = $(PQXX_CXXFLAGS) $(CONFIG_CXXFLAGS)
pracrod_SOURCES = \
pracrod.cc \
+ daemon.cc \
database.cc \
configuration.cc \
exception.cc \
@@ -21,6 +22,7 @@ pracrod_SOURCES = \
EXTRA_DIST = \
configuration.h \
+ daemon.h \
database.h \
debug.h \
exception.h \
diff --git a/server/src/daemon.cc b/server/src/daemon.cc
new file mode 100644
index 0000000..a88fa39
--- /dev/null
+++ b/server/src/daemon.cc
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * daemon.cc
+ *
+ * Thu Jun 9 10:27:59 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "daemon.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+// For getgrent and getgrent
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+
+// For strcmp
+#include <string.h>
+
+/* Resolve a group's name or id into a numeric gid */
+static gid_t get_gid(const char *grp)
+{
+ char *eptr;
+ gid_t xid = strtoul(grp, &eptr, 10);
+ struct group *gr;
+ errno = 0; /* Per getgrnam(3) and getgrgid(3) manual page */
+ if(!*eptr)
+ gr = getgrgid(xid);
+ else
+ gr = getgrnam(grp);
+ return !gr ? 0 : gr->gr_gid;
+}
+
+/* Resolve a user's name or id into a numeric uid with associated gid */
+static uid_t get_uid(const char *usr, gid_t *gid)
+{
+ char *eptr;
+ uid_t xid = strtoul(usr, &eptr, 10);
+ struct passwd *pw;
+ errno = 0; /* Per getpwnam(3) and getpwuid(3) manual page */
+ if(!*eptr)
+ pw = getpwuid(xid);
+ else
+ pw = getpwnam(usr);
+ if(!pw)
+ return 0;
+ if(!gid)
+ *gid = pw->pw_gid;
+ return pw->pw_uid;
+}
+
+Daemon::Daemon()
+{}
+
+Daemon::~Daemon()
+{}
+
+int Daemon::run(const char *user, const char* group, bool detach)
+{
+ int f;
+ int fd;
+
+ // Fetch user and group IDs
+ gid_t gid = 0;
+ uid_t uid = 0;
+ if(user && *user) {
+ uid = get_uid(user, &gid);
+ if(errno) {
+ fprintf(stderr, "Could resolve user \"%s\"", user);
+ perror("");
+ }
+ }
+
+ if(group && *group) {
+ gid = get_gid(group);
+ if(errno) {
+ fprintf(stderr, "Could not resolve group \"%s\"", group);
+ perror("");
+ }
+ }
+
+ chdir("/");
+ umask(0);
+
+ if(detach) {
+ switch(fork()) {
+ case -1: // Fork error
+ perror("Fork in daemon.cc");
+ return 1;
+
+ case 0: // Forked child
+ break; // Break out of switch
+
+ default: // Parent
+ // exit(0);
+ return 0;
+ }
+ }
+
+ if(gid) {
+ // Switch to given group
+ if(setgid(gid) != 0) {
+ fprintf(stderr, "Failed to change to group \"%s\" (gid: %d), quitting.\n", group, gid);
+ perror("");
+ fprintf(stderr, "Runnning daemon as current group\n");
+ }
+ }
+
+ if(uid) {
+ // Switch to given user
+ if(setuid(uid) != 0) {
+ fprintf(stderr, "Failed to change to user \"%s\" (uid: %d), quitting.\n", user, uid);
+ perror("");
+ fprintf(stderr, "Runnning daemon as current user\n");
+ }
+ }
+
+ // Redirect stdin, stdout and stderr to /dev/null
+ fd = open("/dev/null", O_NOCTTY | O_RDWR, 0666);
+
+ dup2(0, fd);
+ dup2(1, fd);
+ dup2(2, fd);
+
+ close(fd);
+
+ setsid();
+
+ signal (SIGTERM, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+ if(detach) signal (SIGINT, SIG_IGN); // Don't disable Ctrl+c when running in foreground.
+
+ return daemon_main();
+}
diff --git a/server/src/daemon.h b/server/src/daemon.h
new file mode 100644
index 0000000..89c3f1c
--- /dev/null
+++ b/server/src/daemon.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * daemon.h
+ *
+ * Thu Jun 9 10:27:59 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This program 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DAEMON_H__
+#define __DAEMON_H__
+
+#include <sys/types.h>
+
+class Daemon {
+public:
+ Daemon();
+ virtual ~Daemon();
+
+ /**
+ * Use NOBODY_GROUP and NOBODY_USER if no privileges are needed to run.
+ */
+ int run(const char* user, const char* group, bool detach = true);
+
+private:
+ virtual int daemon_main() = 0;
+};
+
+#endif/*__DAEMON_H__*/
diff --git a/server/src/pracrod.cc b/server/src/pracrod.cc
index cd5bfe7..134b212 100644
--- a/server/src/pracrod.cc
+++ b/server/src/pracrod.cc
@@ -27,6 +27,8 @@
// For ETC
#include <config.h>
+#include "daemon.h"
+
// For setuid and setgid
#include <sys/types.h>
#include <unistd.h>
@@ -93,6 +95,19 @@ void reload(int fisk)
}
}
+class PracroDaemon : public Daemon {
+private:
+ int daemon_main();
+};
+
+int PracroDaemon::daemon_main()
+{
+ // Activate the server main loop.
+ server();
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
int c;
@@ -152,9 +167,6 @@ int main(int argc, char *argv[])
}
}
- //std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
- //std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
-
char *cfname = NULL;
if(!configfile) cfname = ETC"/pracrod.conf";
else cfname = configfile;
@@ -170,24 +182,6 @@ int main(int argc, char *argv[])
}
}
- if(user) {
- // Fetch user id
- int uid = -1;
- struct passwd *p = getpwent();
- while(p) {
- if(strcmp(p->pw_name, user) == 0) uid = p->pw_uid;
- p = getpwent();
- }
- if(uid == -1) {
- fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user);
- return 1;
- }
-
- if(setuid(uid) == -1) {
- fprintf(stderr, "Could not switch to user %s: %s\n", user, strerror(errno));
- return 1;
- }
- }
if(!group) {
std::string groupstr;
@@ -199,41 +193,8 @@ int main(int argc, char *argv[])
}
- if(group) {
- // Fetch group id
- int gid = -1;
- struct group *g = getgrent();
- while(g) {
- if(strcmp(g->gr_name, group) == 0) gid = g->gr_gid;
- g = getgrent();
- }
- if(gid == -1) {
- fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group);
- return 1;
- }
-
- if(setgid(gid) == -1) {
- fprintf(stderr, "Could not switch to group %s: %s\n", group, strerror(errno));
- return 1;
- }
- }
-
- if(!foreground) {
- daemon(0,0);
- signal (SIGTERM, SIG_IGN);
- signal (SIGINT, SIG_IGN);
- } else {
- printf("Running in foreground mode.\n");
- }
-
- // Create callback to reload conf files.
- signal (SIGHUP, reload);
-
- signal(SIGCLD, SIG_IGN); // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes
- // (ellers kommer der kernel-brok)
-
- // Activate the server main loop.
- server();
+ PracroDaemon daemon;
+ daemon.run(user, group, !foreground);
// Clean up
if(configfile) free(configfile);