[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r3152 - in GNUnet/src: include server util/os util/threads
From: |
grothoff |
Subject: |
[GNUnet-SVN] r3152 - in GNUnet/src: include server util/os util/threads |
Date: |
Sat, 29 Jul 2006 00:57:02 -0700 (PDT) |
Author: grothoff
Date: 2006-07-29 00:56:57 -0700 (Sat, 29 Jul 2006)
New Revision: 3152
Added:
GNUnet/src/util/os/console.c
GNUnet/src/util/os/user.c
GNUnet/src/util/threads/signal.c
Modified:
GNUnet/src/include/core.h
GNUnet/src/include/gnunet_util_getopt.h
GNUnet/src/include/gnunet_util_os.h
GNUnet/src/include/gnunet_util_threads.h
GNUnet/src/server/core.c
GNUnet/src/server/gnunetd.c
GNUnet/src/server/handler.c
GNUnet/src/server/handler.h
GNUnet/src/server/startup.c
GNUnet/src/server/startup.h
GNUnet/src/server/tcpserver.c
GNUnet/src/server/version.c
GNUnet/src/server/version.h
GNUnet/src/util/os/Makefile.am
GNUnet/src/util/os/osconfig.c
GNUnet/src/util/threads/Makefile.am
GNUnet/src/util/threads/shutdown.c
Log:
moving more code into util
Modified: GNUnet/src/include/core.h
===================================================================
--- GNUnet/src/include/core.h 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/include/core.h 2006-07-29 07:56:57 UTC (rev 3152)
@@ -38,21 +38,25 @@
/**
* Initialize the CORE's globals.
*/
-void initCore();
+int initCore(struct GE_Context * ectx,
+ struct GC_Configuration * cfg,
+ struct CronManager * cron,
+ struct LoadMonitor * monitor);
+
/**
* Shutdown the CORE modules (also shuts down all
* application modules).
*/
-void doneCore();
+void doneCore(void);
void * requestService(const char * pos);
int releaseService(void * service);
-void unloadApplicationModules();
+void unloadApplicationModules(void);
-void loadApplicationModules();
+void loadApplicationModules(void);
Modified: GNUnet/src/include/gnunet_util_getopt.h
===================================================================
--- GNUnet/src/include/gnunet_util_getopt.h 2006-07-29 01:13:50 UTC (rev
3151)
+++ GNUnet/src/include/gnunet_util_getopt.h 2006-07-29 07:56:57 UTC (rev
3152)
@@ -181,7 +181,7 @@
* Marker to end the list of options.
*/
#define COMMAND_LINE_OPTION_END \
- { '\0', NULL, NULL, 0, NULL, NULL }
+ { '\0', NULL, NULL, NULL, 0, NULL, NULL }
/**
* Parse the command line.
Modified: GNUnet/src/include/gnunet_util_os.h
===================================================================
--- GNUnet/src/include/gnunet_util_os.h 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/include/gnunet_util_os.h 2006-07-29 07:56:57 UTC (rev 3152)
@@ -213,6 +213,14 @@
const char * group);
/**
+ * Change current process to run as the given
+ * user
+ * @return OK on success, SYSERR on error
+ */
+int os_change_user(struct GE_Context * ectx,
+ const char * user);
+
+/**
* Get the current CPU load.
* @param ectx for error reporting
* @param cfg to determine acceptable load level (LOAD::MAXCPULOAD)
@@ -270,6 +278,27 @@
struct GC_Configuration * cfg,
enum InstallPathKind dirkind);
+
+
+/**
+ * Fork and start a new session to go into the background
+ * in the way a good deamon should.
+ *
+ * @param filedes pointer to an array of 2 file descriptors
+ * to complete the detachment protocol (handshake)
+ */
+int os_terminal_detach(struct GE_Context * ectx,
+ int * filedes);
+
+/**
+ * Complete the handshake of detaching from the terminal.
+ * @param success use NO for error, YES for successful start
+ */
+void os_terminal_detach_complete(struct GE_Context * ectx,
+ int * filedes,
+ int success);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: GNUnet/src/include/gnunet_util_threads.h
===================================================================
--- GNUnet/src/include/gnunet_util_threads.h 2006-07-29 01:13:50 UTC (rev
3151)
+++ GNUnet/src/include/gnunet_util_threads.h 2006-07-29 07:56:57 UTC (rev
3152)
@@ -187,6 +187,29 @@
*/
void GNUNET_SHUTDOWN_WAITFOR(void);
+struct SignalHandlerContext;
+
+/**
+ * A signal handler. Since different OSes have different signatures
+ * for their handlers, the API only gives the most restrictive
+ * signature -- no arguments, no return value. Note that this will
+ * work even if the OS expects a function with arguments. However,
+ * the implementation must guarantee that this handler is not called
+ * for signals other than the one that it has been registered for.
+ */
+typedef void (*SignalHandler)(void);
+
+/**
+ * Install a signal handler that will be run if the
+ * given signal is received.
+ */
+struct SignalHandlerContext * signal_handler_install(int signal,
+ SignalHandler handler);
+
+void signal_handler_uninstall(int signal,
+ SignalHandler handler,
+ struct SignalHandlerContext * ctx);
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: GNUnet/src/server/core.c
===================================================================
--- GNUnet/src/server/core.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/core.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -523,8 +523,21 @@
/**
* Initialize the CORE's globals.
*/
-void initCore() {
- initTCPServer();
+int initCore(struct GE_Context * ectx,
+ struct GC_Configuration * cfg,
+ struct CronManager * cron,
+ struct LoadMonitor * monitor) {
+ identity = requestService("identity");
+ if (identity == NULL)
+ return SYSERR;
+ identity->getPeerIdentity(identity->getPublicPrivateKey(),
+ &myIdentity);
+ initTCPServer(ectx,
+ cfg);
+ applicationCore.ectx = ectx;
+ applicationCore.cfg = cfg;
+ applicationCore.load_monitor = monitor;
+ applicationCore.cron = cron;
applicationCore.version = 0;
applicationCore.myIdentity = &myIdentity; /* core.c */
applicationCore.loadApplicationModule = &loadApplicationModule; /* core.c */
@@ -569,13 +582,8 @@
applicationCore.getSlotCount = &getSlotCount; /* connection.c */
applicationCore.isSlotUsed = &isSlotUsed; /* connection.c */
applicationCore.getLastActivityOf = &getLastActivityOf; /* connection.c */
-
- identity = requestService("identity");
- if (identity == NULL)
- errexit(_("FATAL: Identity plugin not found!\n"));
- identity->getPeerIdentity(identity->getPublicPrivateKey(),
- &myIdentity);
- initHandler();
+ initHandler(ectx);
+ return OK;
}
/**
Modified: GNUnet/src/server/gnunetd.c
===================================================================
--- GNUnet/src/server/gnunetd.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/gnunetd.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -30,7 +30,9 @@
#include "gnunet_util.h"
#include "gnunet_util_config_impl.h"
#include "gnunet_util_error_loggers.h"
+#include "gnunet_util_cron.h"
#include "gnunet_core.h"
+#include "gnunet_directories.h"
#include "core.h"
#include "connection.h"
#include "tcpserver.h"
@@ -38,104 +40,136 @@
#include "startup.h"
#include "version.h"
+static struct GC_Configuration * cfg;
+
+static struct CronManager * cron;
+
/**
- * The main method of gnunetd. And here is how it works:
- * <ol>
- * <li>detach from tty, initialize all coresystems
- * <li>a) start core-services
- * b) initialize application services and download hostlist
- * <li>wait for semaphore to signal shutdown
- * <li>shutdown all services (in roughly inverse order)
- * <li>exit
- * </ol>
+ * Cron job that triggers re-reading of the configuration.
*/
-void gnunet_main() {
- int filedes[2]; /* pipe between client and parent */
+static void reread_config_helper(void * unused) {
+ char * filename;
+
+ filename = NULL;
+ if (-1 == GC_get_configuration_value_string(cfg,
+ "GNUNET",
+ "CONFIGFILE",
+ DEFAULT_DAEMON_CONFIG_FILE,
+ &filename)) {
+ GE_BREAK(NULL, 0); /* should never happen */
+ return;
+ }
+ GE_ASSERT(NULL, filename != NULL);
+ GC_parse_configuration(cfg,
+ filename);
+ FREE(filename);
+}
- /* init 0: change user */
-#ifndef MINGW
- char *user = getConfigurationString("GNUNETD", "USER");
- if (user && strlen(user))
- changeUser(user);
- FREENONNULL(user);
-#endif
+/**
+ * Signal handler for SIGHUP.
+ * Re-reads the configuration file.
+ */
+static void reread_config() {
+ cron_add_job(cron,
+ &reread_config_helper,
+ 1 * cronSECONDS,
+ 0,
+ NULL);
+}
- /* init 1: version management for GNUnet core,
- essentially forces running gnunet-update
- whenever the version OR configuration changes. */
- if (OK != checkUpToDate())
- errexit(_("Configuration or GNUnet version changed. You need to run
`%s'!\n"),
- "gnunet-update");
-
- /* init 2: become deamon, initialize core subsystems */
- if (NO == debug_flag())
- detachFromTerminal(filedes);
-
+/**
+ * Park main thread until shutdown has been signaled.
+ */
+static void waitForSignalHandler(struct GE_Context * ectx) {
GE_LOG(ectx,
GE_INFO | GE_USER | GE_REQUEST,
- _("`%s' starting\n"),
- "gnunetd");
-
- initCore();
- initConnection(); /* requires core, starts transports! */
- loadApplicationModules(); /* still single-threaded! */
-
- /* initialize signal handler (CTRL-C / SIGTERM) */
- if (NO == debug_flag())
- detachFromTerminalComplete(filedes);
- writePIDFile();
-
- startCron();
- enableCoreProcessing();
-
- /* init 4: wait for shutdown */
- /* wait for SIGTERM, SIGTERM will set
- doShutdown to YES and send this thread
- a SIGUSR1 which will wake us up from the
- sleep */
- initSignalHandlers();
- GE_LOG(ectx,
- GE_INFO | GE_USER | GE_REQUEST,
_("`%s' startup complete.\n"),
- "gnunetd");
-
- waitForSignalHandler();
+ "gnunetd");
+ GNUNET_SHUTDOWN_WAITFOR();
GE_LOG(ectx,
GE_INFO | GE_USER | GE_REQUEST,
_("`%s' is shutting down.\n"),
"gnunetd");
-
- /* init 5: shutdown */
- disableCoreProcessing(); /* calls on applications! */
- stopCron(); /* avoid concurrency! */
- stopTCPServer(); /* calls on applications! */
- unloadApplicationModules(); /* requires connection+tcpserver+handler */
+}
- doneConnection(); /* requires core, stops transports! */
+/**
+ * The main method of gnunetd.
+ */
+int gnunet_main(struct GE_Context * ectx) {
+ struct LoadMonitor * mon;
+ struct SignalHandlerContext * shc_hup;
+ int filedes[2]; /* pipe between client and parent */
+
+ if (NO == debug_flag()) {
+ if (OK != detachFromTerminal(ectx,
+ filedes))
+ return SYSERR;
+ }
+ mon = os_network_monitor_create(ectx,
+ cfg);
+ cron = cron_create(ectx);
+ shc_hup = signal_handler_install(SIGHUP, &reread_config);
+ initCore(ectx,
+ cfg,
+ cron,
+ mon);
+ initConnection();
+ loadApplicationModules();
+ writePIDFile(ectx, cfg);
+ if (NO == debug_flag())
+ detachFromTerminalComplete(ectx,
+ filedes);
+ cron_start(cron);
+ enableCoreProcessing();
+ waitForSignalHandler(ectx);
+ disableCoreProcessing();
+ cron_stop(cron);
+ deletePIDFile(ectx, cfg);
+ stopTCPServer();
+ unloadApplicationModules();
+ doneConnection();
doneCore();
-
- /* init 6: goodbye */
- deletePIDFile();
- doneSignalHandlers();
+ os_network_monitor_destroy(mon);
+ signal_handler_uninstall(SIGHUP,
+ &reread_config,
+ shc_hup);
+ cron_destroy(cron);
+ return OK;
}
-#ifdef MINGW
/**
- * Main method of the windows service
+ * All gnunetd command line options
*/
-void WINAPI ServiceMain(DWORD argc, LPSTR *argv) {
- win_service_main(gnunet_main);
-}
+static struct CommandLineOption gnunetdOptions[] = {
+ COMMAND_LINE_OPTION_CFG_FILE, /* -c */
+ { '@', "win-service", NULL, gettext_noop(""), 0,
+ &gnunet_getopt_configure_set_option, "GNUNETD:WINSERVICE" },
+ { 'd', "debug", NULL,
+ gettext_noop("run in debug mode; gnunetd will "
+ "not daemonize and error messages will "
+ "be written to stderr instead of a logfile"),
+ 0, &gnunet_getopt_configure_set_option, "GNUNETD:DEBUG" },
+ COMMAND_LINE_OPTION_HELP(_("Starts the gnunetd daemon.")), /* -h */
+ COMMAND_LINE_OPTION_HOSTNAME, /* -H */
+ COMMAND_LINE_OPTION_LOGGING, /* -L */
+ { 'p', "padding", "PADDING", gettext_noop(""), 1,
+ &gnunet_getopt_configure_set_option, "GNUNETD-EXPERIMENTAL:PADDING" },
+#ifndef MINGW
+ { 'u', "user", "USERNAME", gettext_noop(""), 1,
+ &gnunet_getopt_configure_set_option, "GNUNETD:USERNAME" },
#endif
+ COMMAND_LINE_OPTION_VERSION(PACKAGE_VERSION), /* -v */
+ COMMAND_LINE_OPTION_END,
+};
/**
* Initialize util (parse command line, options) and
* call the main routine.
*/
int main(int argc,
- char * argv[]) {
+ const char * argv[]) {
+ char * user;
int ret;
- struct GC_Configuration * cfg;
struct GE_Context * ectx;
if ( (4 != sizeof(MESSAGE_HEADER)) ||
@@ -144,7 +178,6 @@
"Sorry, your C compiler did not properly align the C structs.
Aborting.\n");
return -1;
}
-
ectx = GE_create_context_stderr(NO,
GE_WARNING | GE_ERROR | GE_FATAL |
GE_USER | GE_ADMIN | GE_DEVELOPER |
@@ -152,31 +185,46 @@
GE_setDefaultContext(ectx);
cfg = GC_create_C_impl();
GE_ASSERT(ectx, cfg != NULL);
- /* init 1: get options and basic services up */
- ret = gnunet_parse_options("gnunetd",
- ectx,
- cfg,
- &gnunetdOptions,
- (unsigned int) argc,
- argv);
- if (ret == -1) {
+ if (-1 == gnunet_parse_options("gnunetd",
+ ectx,
+ cfg,
+ gnunetdOptions,
+ (unsigned int) argc,
+ argv)) {
GC_free(cfg);
GE_free_context(ectx);
return -1;
}
- /* now: patch up default context according to config! */
-
-#ifdef MINGW
- if (win_service()) {
- SERVICE_TABLE_ENTRY DispatchTable[] =
- {{"GNUnet", ServiceMain}, {NULL, NULL}};
- GNStartServiceCtrlDispatcher(DispatchTable);
-
- return 0;
- } else
-#endif
- gnunet_main();
-
+ user = NULL;
+ if (0 == GC_get_configuration_value_string(cfg,
+ "GNUNETD",
+ "USER",
+ NULL,
+ &user)) {
+ if (OK != os_change_user(ectx,
+ user)) {
+ GC_free(cfg);
+ GE_free_context(ectx);
+ FREE(user);
+ return 1;
+ }
+ FREE(user);
+ }
+ if (OK != checkUpToDate(ectx,
+ cfg)) {
+ GE_LOG(ectx,
+ GE_USER | GE_FATAL | GE_IMMEDIATE,
+ _("Configuration or GNUnet version changed. You need to run
`%s'!\n"),
+ "gnunet-update");
+ GC_free(cfg);
+ GE_free_context(ectx);
+ return 1;
+ }
+ ret = gnunet_main(ectx);
+ GC_free(cfg);
+ GE_free_context(ectx);
+ if (ret != OK)
+ return 1;
return 0;
}
Modified: GNUnet/src/server/handler.c
===================================================================
--- GNUnet/src/server/handler.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/handler.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -627,7 +627,8 @@
/**
* Initialize message handling module.
*/
-void initHandler() {
+void initHandler(struct GE_Context * e) {
+ ectx = e;
handlerLock = MUTEX_CREATE(NO);
transport = requestService("transport");
GE_ASSERT(ectx, transport != NULL);
Modified: GNUnet/src/server/handler.h
===================================================================
--- GNUnet/src/server/handler.h 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/handler.h 2006-07-29 07:56:57 UTC (rev 3152)
@@ -33,7 +33,7 @@
* Initialize message handling module (make ready to register
* handlers).
*/
-void initHandler();
+void initHandler(struct GE_Context * e);
/**
* Shutdown message handling module.
Modified: GNUnet/src/server/startup.c
===================================================================
--- GNUnet/src/server/startup.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/startup.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -23,11 +23,7 @@
* @brief insignificant gnunetd helper methods
*
* Helper methods for the startup of gnunetd:
- * - install signal handling
- * - system checks on startup
* - PID file handling
- * - detaching from terminal
- * - command line parsing
*
* @author Christian Grothoff
*/
@@ -40,545 +36,63 @@
#include "core.h"
#include "startup.h"
-
-/**
- * This flag is set if gnunetd is not (to be) detached from the
- * console.
- */
-static int debug_flag_ = NO;
-
-/**
- * This flag is set if gnunetd was started as windows service
- */
-static int win_service_ = NO;
-
-int debug_flag() {
- return debug_flag_;
+static char * getPIDFile(struct GC_Configuration * cfg) {
+ char * pif;
+
+ if (0 != GC_get_configuration_value_string(cfg,
+ "GNUNETD",
+ "PIDFILE",
+ NULL,
+ &pif))
+ return NULL;
+ return pif;
}
-int win_service() {
- return win_service_;
-}
-
-
-#ifdef MINGW
- /**
- * Windows service information
- */
- static SERVICE_STATUS theServiceStatus;
- static SERVICE_STATUS_HANDLE hService;
-#endif
-
/**
- * This flag is set if gnunetd is shutting down.
- */
-static struct SEMAPHORE * doShutdown;
-
-/* ************* SIGNAL HANDLING *********** */
-
-/**
- * Cron job that triggers re-reading of the configuration.
- */
-static void reread_config_helper(void * unused) {
- LOG(LOG_DEBUG,
- "Re-reading configuration file.\n");
- readConfiguration();
- triggerGlobalConfigurationRefresh();
- LOG(LOG_DEBUG,
- "New configuration active.\n");
-}
-
-/**
- * Signal handler for SIGHUP.
- * Re-reads the configuration file.
- */
-static void reread_config(int signum) {
- addCronJob(&reread_config_helper,
- 1 * cronSECONDS,
- 0,
- NULL);
-}
-
-#ifdef MINGW
-static void shutdown_gnunetd(int signum);
-
-BOOL WINAPI win_shutdown_gnunetd(DWORD dwCtrlType)
-{
- switch(dwCtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- case CTRL_LOGOFF_EVENT:
- case SERVICE_CONTROL_STOP:
- shutdown_gnunetd(dwCtrlType);
- }
-
- return TRUE;
-}
-
-/**
- * This function is called from the Windows Service Control Manager
- * when a service has to shutdown
- */
-void WINAPI ServiceCtrlHandler(DWORD dwOpcode) {
- if (dwOpcode == SERVICE_CONTROL_STOP)
- win_shutdown_gnunetd(SERVICE_CONTROL_STOP);
-}
-
-/**
- * called by gnunetd.c::ServiceMain()
- */
-void win_service_main(void (*gn_main)()) {
- memset(&theServiceStatus, 0, sizeof(theServiceStatus));
- theServiceStatus.dwServiceType = SERVICE_WIN32;
- theServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- theServiceStatus.dwCurrentState = SERVICE_RUNNING;
-
- hService = GNRegisterServiceCtrlHandler("GNUnet", ServiceCtrlHandler);
- if (! hService)
- return;
-
- GNSetServiceStatus(hService, &theServiceStatus);
-
- gn_main();
-
- theServiceStatus.dwCurrentState = SERVICE_STOPPED;
- GNSetServiceStatus(hService, &theServiceStatus);
-}
-#endif
-
-/**
- * Try a propper shutdown of gnunetd.
- */
-static void shutdown_gnunetd(int signum) {
-
-#ifdef MINGW
-if (win_service())
-{
- /* If GNUnet runs as service, only the
- Service Control Manager is allowed
- to kill us. */
- if (signum != SERVICE_CONTROL_STOP)
- {
- SERVICE_STATUS theStat;
-
- /* Init proper shutdown through the SCM */
- if (GNControlService(hService, SERVICE_CONTROL_STOP, &theStat))
- {
- /* Success */
-
- /* The Service Control Manager will call
- gnunetd.c::ServiceCtrlHandler(), which calls
- this function again. We then stop the gnunetd. */
- return;
- }
- /* We weren't able to tell the SCM to stop the service,
- but we don't care.
- Just shut the gnunetd process down. */
- }
-
- /* Acknowledge the shutdown request */
- theServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
- GNSetServiceStatus(hService, &theServiceStatus);
-}
-#endif
-
- SEMAPHORE_UP(doShutdown);
-}
-
-static int shutdownHandler(ClientHandle client,
- const CS_MESSAGE_HEADER * msg) {
- int ret;
-
- if (ntohs(msg->size) != sizeof(CS_MESSAGE_HEADER)) {
- LOG(LOG_WARNING,
- _("The `%s' request received from client is malformed.\n"),
- "shutdown");
- return SYSERR;
- }
- LOG(LOG_INFO,
- "shutdown request accepted from client\n");
-
- if (SYSERR == unregisterCSHandler(CS_PROTO_SHUTDOWN_REQUEST,
- &shutdownHandler))
- GNUNET_ASSERT(0);
- ret = sendTCPResultToClient(client,
- OK);
- shutdown_gnunetd(0);
- return ret;
-}
-
-/**
- * Initialize signal handlers
- */
-void initSignalHandlers() {
-#ifndef MINGW
- struct sigaction sig;
- struct sigaction oldsig;
-#endif
-
- doShutdown = SEMAPHORE_CREATE(0);
-
-#ifndef MINGW
- sig.sa_handler = &shutdown_gnunetd;
- sigemptyset(&sig.sa_mask);
-#ifdef SA_INTERRUPT
- sig.sa_flags = SA_INTERRUPT; /* SunOS */
-#else
- sig.sa_flags = SA_RESTART;
-#endif
- sigaction(SIGINT, &sig, &oldsig);
- sigaction(SIGTERM, &sig, &oldsig);
- sigaction(SIGQUIT, &sig, &oldsig);
-
- sig.sa_handler = &reread_config;
- sigaction(SIGHUP, &sig, &oldsig);
-#else
- SetConsoleCtrlHandler(&win_shutdown_gnunetd, TRUE);
-#endif
-
- if (SYSERR == registerCSHandler(CS_PROTO_SHUTDOWN_REQUEST,
- &shutdownHandler))
- GE_ASSERT(ectx, 0);
-}
-
-void doneSignalHandlers() {
-#ifndef MINGW
- struct sigaction sig;
- struct sigaction oldsig;
-
- sig.sa_handler = SIG_DFL;
- sigemptyset(&sig.sa_mask);
-#ifdef SA_INTERRUPT
- sig.sa_flags = SA_INTERRUPT; /* SunOS */
-#else
- sig.sa_flags = SA_RESTART;
-#endif
- sigaction(SIGINT, &sig, &oldsig);
- sigaction(SIGTERM, &sig, &oldsig);
- sigaction(SIGQUIT, &sig, &oldsig);
-#else
- SetConsoleCtrlHandler(&win_shutdown_gnunetd, TRUE);
-#endif
- SEMAPHORE_DESTROY(doShutdown);
- doShutdown = NULL;
-}
-
-/**
- * Cron job to timeout gnunetd.
- */
-static void semaphore_up(void * sem) {
- SEMAPHORE_UP((Semaphore*)sem);
-}
-
-void waitForSignalHandler() {
- int valgrind;
-
- /* mechanism to stop gnunetd after a certain
- time without a signal -- to debug with valgrind*/
- valgrind = getConfigurationInt("GNUNETD",
- "VALGRIND");
- if (valgrind > 0)
- addCronJob(&semaphore_up,
- valgrind * cronSECONDS,
- 0,
- doShutdown);
-#if 0
- /* If Valgrind is used to debug memory leaks, some sort of mechanism
- is needed to make gnunetd exit without using any signal -IW*/
- FILE *fp;
-
- while(1) {
- fp=FOPEN("/tmp/quitgn", "r");
- if(fp) {
- fprintf(stderr, "QUITTING...\n");
- fclose(fp);
- return;
- }
- sleep(1);
- }
-#endif
- SEMAPHORE_DOWN(doShutdown);
- if (valgrind > 0)
- delCronJob(&semaphore_up,
- 0,
- doShutdown);
-
-}
-
-static char * getPIDFile() {
- return getFileName("GNUNETD",
- "PIDFILE",
- _("You must specify a name for the PID file in section"
- " `%s' under `%s'.\n"));
-}
-
-/**
* Write our process ID to the pid file.
*/
-void writePIDFile() {
+void writePIDFile(struct GE_Context * ectx,
+ struct GC_Configuration * cfg) {
FILE * pidfd;
char * pif;
- pif = getPIDFile();
+ pif = getPIDFile(cfg);
+ if (pif == NULL)
+ return; /* no PID file */
pidfd = FOPEN(pif, "w");
if (pidfd == NULL) {
- LOG(LOG_WARNING,
- _("Could not write PID to file `%s': %s.\n"),
- pif,
- STRERROR(errno));
- } else {
- fprintf(pidfd, "%u", (unsigned int) getpid());
- fclose(pidfd);
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "fopen",
+ pif);
+ return;
}
+ if (0 > FPRINTF(pidfd,
+ "%u",
+ (unsigned int) getpid()))
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "fprintf",
+ pif);
+ if (0 != FCLOSE(pidfd))
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "fclose",
+ pif);
FREE(pif);
}
-void deletePIDFile() {
- char * pif = getPIDFile();
- UNLINK(pif);
+void deletePIDFile(struct GE_Context * ectx,
+ struct GC_Configuration * cfg) {
+ char * pif = getPIDFile(cfg);
+ if (pif == NULL)
+ return; /* no PID file */
+ if (0 != UNLINK(pif))
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "unlink",
+ pif);
FREE(pif);
}
-/* ************** DETACHING FROM TERMAINAL ************** */
-
-/**
- * Fork and start a new session to go into the background
- * in the way a good deamon should.
- *
- * @param filedes pointer to an array of 2 file descriptors
- * to complete the detachment protocol (handshake)
- */
-void detachFromTerminal(int * filedes) {
-#ifndef MINGW
- pid_t pid;
- int nullfd;
-#endif
-
- /* Don't hold the wrong FS mounted */
- if (CHDIR("/") < 0) {
- perror("chdir");
- exit(1);
- }
-
-#ifndef MINGW
- PIPE(filedes);
- pid = fork();
- if (pid < 0) {
- perror("fork");
- exit(1);
- }
- if (pid) { /* Parent */
- int ok;
- char c;
-
- closefile(filedes[1]); /* we only read */
- ok = SYSERR;
- while (0 < READ(filedes[0], &c, sizeof(char))) {
- if (c == '.')
- ok = OK;
- }
- fflush(stdout);
- if (ok == OK)
- exit(0);
- else
- exit(1); /* child reported error */
- }
- closefile(filedes[0]); /* we only write */
- nullfd = fileopen("/dev/null",
- O_CREAT | O_RDWR | O_APPEND);
- if (nullfd < 0) {
- perror("/dev/null");
- exit(1);
- }
- /* child - close fds linking to invoking terminal, but
- * close usual incoming fds, but redirect them somewhere
- * useful so the fds don't get reallocated elsewhere.
- */
- if (dup2(nullfd,0) < 0 ||
- dup2(nullfd,1) < 0 ||
- dup2(nullfd,2) < 0) {
- perror("dup2"); /* Should never happen */
- exit(1);
- }
- pid = setsid(); /* Detach from controlling terminal */
-#else
- FreeConsole();
-#endif
-}
-
-void detachFromTerminalComplete(int * filedes) {
-#ifndef MINGW
- char c = '.';
- WRITE(filedes[1], &c, sizeof(char)); /* signal success */
- closefile(filedes[1]);
-#endif
-}
-
-/* ****************** COMMAND LINE PARSING ********************* */
-
-static void printDot(void * unused) {
- LOG(LOG_DEBUG, ".");
-}
-
-/**
- * Print a list of the options we offer.
- */
-static void printhelp() {
- static Help help[] = {
- HELP_CONFIG,
- { 'd', "debug", NULL,
- gettext_noop("run in debug mode; gnunetd will "
- "not daemonize and error messages will "
- "be written to stderr instead of a logfile") },
- HELP_HELP,
- HELP_LOGLEVEL,
-#ifndef MINGW /* not supported */
- { 'u', "user", "LOGIN",
- gettext_noop("run as user LOGIN") },
-#endif
- HELP_VERSION,
- HELP_END,
- };
- formatHelp("gnunetd [OPTIONS]",
- _("Starts the gnunetd daemon."),
- help);
-}
-
-#ifndef MINGW
-/**
- * @brief Change user ID
- */
-void changeUser(const char *user) {
- struct passwd * pws;
-
- pws = getpwnam(user);
- if(pws == NULL) {
- LOG(LOG_WARNING,
- _("User `%s' not known, cannot change UID to it.\n"), user);
- return;
- }
- if((0 != setgid(pws->pw_gid)) ||
- (0 != setegid(pws->pw_gid)) ||
- (0 != setuid(pws->pw_uid)) || (0 != seteuid(pws->pw_uid))) {
- if((0 != setregid(pws->pw_gid, pws->pw_gid)) ||
- (0 != setreuid(pws->pw_uid, pws->pw_uid)))
- LOG(LOG_WARNING,
- _("Cannot change user/group to `%s': %s\n"),
- user, STRERROR(errno));
- }
-}
-#endif
-
-/**
- * Perform option parsing from the command line.
- */
-int parseGnunetdCommandLine(int argc,
- char * argv[]) {
- int cont = OK;
- int c;
-
- /* set the 'magic' code that indicates that
- this process is 'gnunetd' (and not any of
- the tools). This can be used by code
- that runs in both the tools and in gnunetd
- to distinguish between the two cases. */
- FREENONNULL(setConfigurationString("GNUNETD",
- "_MAGIC_",
- "YES"));
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "loglevel",1, 0, 'L' },
- { "config", 1, 0, 'c' },
- { "version", 0, 0, 'v' },
- { "help", 0, 0, 'h' },
- { "user", 1, 0, 'u' },
- { "debug", 0, 0, 'd' },
- { "livedot", 0, 0, 'l' },
- { "padding", 1, 0, 'p' },
- { "win-service", 0, 0, '@' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "vhdc:u:L:lp:@",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process */
-
- switch(c) {
- case 'p':
- FREENONNULL(setConfigurationString("GNUNETD-EXPERIMENTAL",
- "PADDING",
- GNoptarg));
- break;
- case 'l':
- addCronJob(&printDot,
- 1 * cronSECONDS,
- 1 * cronSECONDS,
- NULL);
- break;
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- case 'v':
- printf("GNUnet v%s\n",
- VERSION);
- cont = SYSERR;
- break;
- case 'h':
- printhelp();
- cont = SYSERR;
- break;
- case 'L':
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGLEVEL",
- GNoptarg));
- break;
- case 'd':
- debug_flag_ = YES;
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGFILE",
- NULL));
- break;
-#ifndef MINGW /* not supported */
- case 'u':
- changeUser(GNoptarg);
- break;
-#endif
-#ifdef MINGW
- case '@':
- win_service_ = YES;
- break;
-#endif
- default:
- LOG(LOG_FAILURE,
- _("Use --help to get a list of options.\n"));
- cont = SYSERR;
- } /* end of parsing commandline */
- }
- if (GNoptind < argc) {
- LOG(LOG_WARNING,
- _("Invalid command-line arguments:\n"));
- while (GNoptind < argc) {
- LOG(LOG_WARNING,
- _("Argument %d: `%s'\n"),
- GNoptind+1,
- argv[GNoptind]);
- GNoptind++;
- }
- LOG(LOG_FATAL,
- _("Invalid command-line arguments.\n"));
- return SYSERR;
- }
- return cont;
-}
-
/* end of startup.c */
Modified: GNUnet/src/server/startup.h
===================================================================
--- GNUnet/src/server/startup.h 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/startup.h 2006-07-29 07:56:57 UTC (rev 3152)
@@ -22,13 +22,8 @@
* @file server/startup.h
* @author Christian Grothoff
* @brief Helper methods for the startup of gnunetd:
- * - install signal handling
- * - system checks on startup
* - PID file handling
- * - detaching from terminal
- * - command line parsing
- *
- **/
+ */
#ifndef STARTUP_H
#define STARTUP_H
@@ -36,60 +31,17 @@
#include "gnunet_util.h"
#include "platform.h"
-int debug_flag(void);
-
-int win_service(void);
-
/**
- * Initialize signal handlers
- **/
-void initSignalHandlers(void);
-
-void doneSignalHandlers(void);
-
-void waitForSignalHandler(void);
-
-/**
- * Fork and start a new session to go into the background
- * in the way a good deamon should.
- *
- * @param filedes pointer to an array of 2 file descriptors
- * to complete the detachment protocol (handshake)
- **/
-void detachFromTerminal(int * filedes);
-
-/**
- * Detached process signals former parent success.
- **/
-void detachFromTerminalComplete(int * filedes);
-
-
-/**
* Write our process ID to the pid file.
**/
-void writePIDFile(void);
+void writePIDFile(struct GE_Context * ectx,
+ struct GC_Configuration * cfg);
/**
* Delete the pid file.
**/
-void deletePIDFile(void);
+void deletePIDFile(struct GE_Context * ectx,
+ struct GC_Configuration * cfg);
-/**
- * Load all of the user-specified application modules.
- */
-void loadApplicationModules(void);
-
-#ifndef MINGW
-/**
- * @brief Change user ID
- */
-void changeUser(const char *user);
#endif
-
-#ifdef MINGW
-BOOL WINAPI win_shutdown_gnunetd(DWORD dwCtrlType);
-void win_service_main(void (*gn_main)());
-#endif
-
-#endif
/* end of startup.h */
Modified: GNUnet/src/server/tcpserver.c
===================================================================
--- GNUnet/src/server/tcpserver.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/tcpserver.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -92,6 +92,26 @@
ip);
}
+static int shutdownHandler(ClientHandle client,
+ const MESSAGE_HEADER * msg) {
+ int ret;
+
+ if (ntohs(msg->size) != sizeof(MESSAGE_HEADER)) {
+ GE_LOG(NULL,
+ GE_WARNING | GE_USER | GE_BULK,
+ _("The `%s' request received from client is malformed.\n"),
+ "shutdown");
+ return SYSERR;
+ }
+ GE_LOG(NULL,
+ GE_INFO | GE_USER | GE_REQUEST,
+ "shutdown request accepted from client\n");
+ ret = sendTCPResultToClient(client,
+ OK);
+ GNUNET_SHUTDOWN_INITIATE();
+ return ret;
+}
+
int registerClientExitHandler(ClientExitHandler callback) {
MUTEX_LOCK(handlerlock);
GROW(exitHandlers,
Modified: GNUnet/src/server/version.c
===================================================================
--- GNUnet/src/server/version.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/version.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -110,7 +110,6 @@
* @return OK if we are
*/
int checkUpToDate(struct GE_Context * ectx,
- State_ServiceAPI * sapi,
struct GC_Configuration * cfg) {
char * version;
int len;
@@ -122,7 +121,6 @@
(void**)&version);
if (len == -1) {
upToDate(ectx,
- sapi,
cfg); /* first start */
return OK;
}
@@ -150,7 +148,6 @@
* Writes the version tag
*/
void upToDate(struct GE_Context * ectx,
- State_ServiceAPI * sapi,
struct GC_Configuration * cfg) {
char * version;
int len;
Modified: GNUnet/src/server/version.h
===================================================================
--- GNUnet/src/server/version.h 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/server/version.h 2006-07-29 07:56:57 UTC (rev 3152)
@@ -27,7 +27,6 @@
#define GNUNETD_VERSION_H
#include "gnunet_util.h"
-#include "gnunet_state_service.h"
/**
@@ -35,14 +34,12 @@
* @return OK if we are
*/
int checkUpToDate(struct GE_Context * ectx,
- State_ServiceAPI * sapi,
struct GC_Configuration * cfg);
/**
* We are up-to-date.
*/
void upToDate(struct GE_Context * ectx,
- State_ServiceAPI * sapi,
struct GC_Configuration * cfg);
#endif
Modified: GNUnet/src/util/os/Makefile.am
===================================================================
--- GNUnet/src/util/os/Makefile.am 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/os/Makefile.am 2006-07-29 07:56:57 UTC (rev 3152)
@@ -14,6 +14,7 @@
semaphore.c \
statuscalls.c \
time.c \
+ user.c \
installpath.c
check_PROGRAMS = \
Added: GNUnet/src/util/os/console.c
===================================================================
--- GNUnet/src/util/os/console.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/os/console.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -0,0 +1,131 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2006 Christian Grothoff (and other contributing authors)
+
+ GNUnet 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, or (at your
+ option) any later version.
+
+ GNUnet 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 GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/os/console.c
+ * @brief code to detach from console
+ * @author Christian Grothoff
+ *
+ * Helper code for writing proper termination code when an application
+ * receives a SIGTERM/SIGHUP etc.
+ */
+
+#include "gnunet_util_os.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+/**
+ * Fork and start a new session to go into the background
+ * in the way a good deamon should.
+ *
+ * @param filedes pointer to an array of 2 file descriptors
+ * to complete the detachment protocol (handshake)
+ */
+int os_terminal_detach(struct GE_Context * ectx,
+ int * filedes) {
+ pid_t pid;
+ int nullfd;
+
+ /* Don't hold the wrong FS mounted */
+ if (CHDIR("/") < 0) {
+ GE_LOG_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "chdir");
+ return SYSERR;
+ }
+
+ PIPE(filedes);
+ pid = fork();
+ if (pid < 0) {
+ GE_LOG_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "fork");
+ return SYSERR;
+ }
+ if (pid) { /* Parent */
+ int ok;
+ char c;
+
+ if (0 != CLOSE(filedes[1]))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "close");
+ ok = SYSERR;
+ while (0 < READ(filedes[0],
+ &c,
+ sizeof(char))) {
+ if (c == '.')
+ ok = OK;
+ }
+ fflush(stdout);
+ if (ok == OK)
+ exit(0);
+ else
+ exit(1); /* child reported error */
+ }
+ if (0 != CLOSE(filedes[0]))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "close");
+ nullfd = fileopen("/dev/null",
+ O_CREAT | O_RDWR | O_APPEND);
+ if (nullfd < 0) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "fork",
+ "/dev/null");
+ return SYSERR;
+ }
+ /* child - close fds linking to invoking terminal, but
+ * close usual incoming fds, but redirect them somewhere
+ * useful so the fds don't get reallocated elsewhere.
+ */
+ if (dup2(nullfd,0) < 0 ||
+ dup2(nullfd,1) < 0 ||
+ dup2(nullfd,2) < 0) {
+ GE_LOG_STRERROR(ectx,
+ GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "dup2");
+ return SYSERR;
+ }
+ pid = setsid(); /* Detach from controlling terminal */
+ if (pid == -1)
+ GE_LOG_STRERROR(ectx,
+ GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "setsid");
+}
+
+void os_terminal_detach_complete(struct GE_Context * ectx,
+ int * filedes,
+ int success) {
+ char c = '.';
+
+ if (! success)
+ c = '!';
+ WRITE(filedes[1],
+ &c,
+ sizeof(char)); /* signal success */
+ if (0 != CLOSE(filedes[1]))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ "close");
+}
+
Property changes on: GNUnet/src/util/os/console.c
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: GNUnet/src/util/os/osconfig.c
===================================================================
--- GNUnet/src/util/os/osconfig.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/os/osconfig.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -320,86 +320,5 @@
return SYSERR;
}
-int os_modify_user(struct GE_Context * ectx,
- int testCapability,
- int doAdd,
- const char *group_name,
- const char *user_name) {
- int haveGroup;
- if (testCapability) {
- /* TODO: actually check that group/user
- exists/does not yet exist */
-#ifdef WINDOWS
- return IsWinNT() ? OK : SYSERR;
-#endif
-#ifdef LINUX
- if (geteuid() != 0)
- return SYSERR;
- if (doAdd == YES) {
- if ( ( (ACCESS("/usr/sbin/adduser", X_OK) == 0) ||
- (ACCESS("/usr/sbin/useradd", X_OK) == 0) ) &&
- ( (ACCESS("/usr/sbin/addgroup", X_OK) == 0) ||
- (ACCESS("/usr/sbin/groupadd", X_OK) == 0) ) )
- return OK;
- return SYSERR;
- } else if (doAdd == NO) {
- if ( (ACCESS("/usr/sbin/deluser", X_OK) == 0) ||
- (ACCESS("/usr/sbin/userdel", X_OK) == 0) )
- return OK;
- return SYSERR;
- } else if (doAdd == SYSERR) {
- if ( ( (ACCESS("/usr/sbin/dleuser", X_OK) == 0) ||
- (ACCESS("/usr/sbin/userdel", X_OK) == 0) ) &&
- ( (ACCESS("/usr/sbin/delgroup", X_OK) == 0) ||
- (ACCESS("/usr/sbin/groupdel", X_OK) == 0) ) )
- return OK;
- return SYSERR;
- }
-#endif
- return SYSERR;
- }
- if ( (user_name == NULL) ||
- (0 == strlen(user_name)) )
- return 0;
-
-#ifdef WINDOWS
- if (IsWinNT())
- return CreateServiceAccount(user_name,
- "GNUnet service account");
-#else
- if (ACCESS("/usr/sbin/adduser",
- X_OK) == 0) {
- /* Debian */
- /* TODO: FreeBSD?
http://www.freebsd.org/cgi/man.cgi?query=adduser&sektion=8 */
- char * cmd;
-
- haveGroup = group_name && strlen(group_name) > 0;
- cmd = MALLOC(haveGroup ? strlen(group_name) : 0 + strlen(user_name) + 64);
-
- if (haveGroup) {
- sprintf(cmd,
- "/usr/sbin/addgroup --quiet --system %s",
- group_name);
- system(cmd);
- }
-
- sprintf(cmd,
- "/usr/sbin/adduser --quiet --system %s %s "
- "--no-create-home %s",
- haveGroup ? "--ingroup" : "",
- haveGroup ? group_name : "",
- user_name);
- system(cmd);
- FREE(cmd);
- return OK;
- }
- /* TODO: useradd */
- else
- return SYSERR;
-#endif
- return SYSERR;
-}
-
-
/* end of osconfig.c */
Added: GNUnet/src/util/os/user.c
===================================================================
--- GNUnet/src/util/os/user.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/os/user.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -0,0 +1,144 @@
+/*
+ This file is part of GNUnet.
+ (C) 2006 Christian Grothoff (and other contributing authors)
+
+ GNUnet 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, or (at your
+ option) any later version.
+
+ GNUnet 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 GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/os/user.c
+ * @brief wrappers for UID functions
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util_os.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+int os_modify_user(struct GE_Context * ectx,
+ int testCapability,
+ int doAdd,
+ const char *group_name,
+ const char *user_name) {
+ int haveGroup;
+
+ if (testCapability) {
+ /* TODO: actually check that group/user
+ exists/does not yet exist */
+#ifdef WINDOWS
+ return IsWinNT() ? OK : SYSERR;
+#endif
+#ifdef LINUX
+ if (geteuid() != 0)
+ return SYSERR;
+ if (doAdd == YES) {
+ if ( ( (ACCESS("/usr/sbin/adduser", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/useradd", X_OK) == 0) ) &&
+ ( (ACCESS("/usr/sbin/addgroup", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/groupadd", X_OK) == 0) ) )
+ return OK;
+ return SYSERR;
+ } else if (doAdd == NO) {
+ if ( (ACCESS("/usr/sbin/deluser", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/userdel", X_OK) == 0) )
+ return OK;
+ return SYSERR;
+ } else if (doAdd == SYSERR) {
+ if ( ( (ACCESS("/usr/sbin/dleuser", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/userdel", X_OK) == 0) ) &&
+ ( (ACCESS("/usr/sbin/delgroup", X_OK) == 0) ||
+ (ACCESS("/usr/sbin/groupdel", X_OK) == 0) ) )
+ return OK;
+ return SYSERR;
+ }
+#endif
+ return SYSERR;
+ }
+ if ( (user_name == NULL) ||
+ (0 == strlen(user_name)) )
+ return 0;
+
+#ifdef WINDOWS
+ if (IsWinNT())
+ return CreateServiceAccount(user_name,
+ "GNUnet service account");
+#else
+ if (ACCESS("/usr/sbin/adduser",
+ X_OK) == 0) {
+ /* Debian */
+ /* TODO: FreeBSD?
http://www.freebsd.org/cgi/man.cgi?query=adduser&sektion=8 */
+ char * cmd;
+
+ haveGroup = group_name && strlen(group_name) > 0;
+ cmd = MALLOC(haveGroup ? strlen(group_name) : 0 + strlen(user_name) + 64);
+
+ if (haveGroup) {
+ sprintf(cmd,
+ "/usr/sbin/addgroup --quiet --system %s",
+ group_name);
+ system(cmd);
+ }
+
+ sprintf(cmd,
+ "/usr/sbin/adduser --quiet --system %s %s "
+ "--no-create-home %s",
+ haveGroup ? "--ingroup" : "",
+ haveGroup ? group_name : "",
+ user_name);
+ system(cmd);
+ FREE(cmd);
+ return OK;
+ }
+ /* TODO: useradd */
+ else
+ return SYSERR;
+#endif
+ return SYSERR;
+}
+
+
+/**
+ * @brief Change user ID
+ */
+int os_change_user(struct GE_Context * ectx,
+ const char * user) {
+ struct passwd * pws;
+
+ pws = getpwnam(user);
+ if (pws == NULL) {
+ GE_LOG(ectx,
+ GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ _("User `%s' not known, cannot change UID to it.\n"),
+ user);
+ return SYSERR;
+ }
+ if((0 != setgid(pws->pw_gid)) ||
+ (0 != setegid(pws->pw_gid)) ||
+ (0 != setuid(pws->pw_uid)) || (0 != seteuid(pws->pw_uid))) {
+ if((0 != setregid(pws->pw_gid, pws->pw_gid)) ||
+ (0 != setreuid(pws->pw_uid, pws->pw_uid))) {
+ GE_LOG(ectx,
+ GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+ _("Cannot change user/group to `%s': %s\n"),
+ user,
+ STRERROR(errno));
+ return SYSERR;
+ }
+ }
+ return OK;
+}
+
+
Property changes on: GNUnet/src/util/os/user.c
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: GNUnet/src/util/threads/Makefile.am
===================================================================
--- GNUnet/src/util/threads/Makefile.am 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/threads/Makefile.am 2006-07-29 07:56:57 UTC (rev 3152)
@@ -10,6 +10,7 @@
pthread.c \
semaphore.c \
shutdown.c \
+ signal.c \
time.c
check_PROGRAMS = \
Modified: GNUnet/src/util/threads/shutdown.c
===================================================================
--- GNUnet/src/util/threads/shutdown.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/threads/shutdown.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -39,6 +39,12 @@
static int shutdown_active;
+static struct SignalHandlerContext * shc_int;
+
+static struct SignalHandlerContext * shc_term;
+
+static struct SignalHandlerContext * shc_quit;
+
void GNUNET_SHUTDOWN_INITIATE() {
GE_ASSERT(NULL, shutdown_signal != NULL);
shutdown_active = YES;
@@ -53,71 +59,31 @@
SEMAPHORE_DOWN(shutdown_signal, YES);
}
-#ifdef MINGW
-BOOL WINAPI run_shutdown_win(DWORD dwCtrlType) {
- switch(dwCtrlType) {
- case CTRL_C_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- case CTRL_LOGOFF_EVENT:
- GNUNET_SHUTDOWN_INITIATE();
- }
- return TRUE;
-}
-#else
-static void run_shutdown(int signum) {
+static void run_shutdown() {
GNUNET_SHUTDOWN_INITIATE();
}
-#endif
/**
* Initialize the signal handlers, etc.
*/
void __attribute__ ((constructor)) shutdown_handlers_ltdl_init() {
-#ifndef MINGW
- struct sigaction sig;
- struct sigaction oldsig;
-#endif
-
GE_ASSERT(NULL, shutdown_signal == NULL);
GE_ASSERT(NULL, shutdown_active == NO);
shutdown_signal = SEMAPHORE_CREATE(0);
-#ifndef MINGW
- sig.sa_handler = &run_shutdown;
- sigemptyset(&sig.sa_mask);
-#ifdef SA_INTERRUPT
- sig.sa_flags = SA_INTERRUPT; /* SunOS */
-#else
- sig.sa_flags = SA_RESTART;
-#endif
- sigaction(SIGINT, &sig, &oldsig);
- sigaction(SIGTERM, &sig, &oldsig);
- sigaction(SIGQUIT, &sig, &oldsig);
-#else
- SetConsoleCtrlHandler(&run_shutdown_win, TRUE);
-#endif
+ shc_int = signal_handler_install(SIGINT, &run_shutdown);
+ shc_term = signal_handler_install(SIGTERM, &run_shutdown);
+ shc_quit = signal_handler_install(SIGQUIT, &run_shutdown);
}
void __attribute__ ((destructor)) shutdown_handlers_ltdl_fini() {
-#ifndef MINGW
- struct sigaction sig;
- struct sigaction oldsig;
-
- sig.sa_handler = SIG_DFL;
- sigemptyset(&sig.sa_mask);
-#ifdef SA_INTERRUPT
- sig.sa_flags = SA_INTERRUPT; /* SunOS */
-#else
- sig.sa_flags = SA_RESTART;
-#endif
- sigaction(SIGINT, &sig, &oldsig);
- sigaction(SIGTERM, &sig, &oldsig);
- sigaction(SIGQUIT, &sig, &oldsig);
-#else
- SetConsoleCtrlHandler(&run_shutdown_win, FALSE);
-#endif
+ signal_handler_uninstall(SIGINT, &run_shutdown, shc_int);
+ signal_handler_uninstall(SIGTERM, &run_shutdown, shc_term);
+ signal_handler_uninstall(SIGQUIT, &run_shutdown, shc_quit);
SEMAPHORE_DESTROY(shutdown_signal);
shutdown_signal = NULL;
+ shc_int = NULL;
+ shc_term = NULL;
+ shc_quit = NULL;
}
/* end of shutdown.c */
Added: GNUnet/src/util/threads/signal.c
===================================================================
--- GNUnet/src/util/threads/signal.c 2006-07-29 01:13:50 UTC (rev 3151)
+++ GNUnet/src/util/threads/signal.c 2006-07-29 07:56:57 UTC (rev 3152)
@@ -0,0 +1,77 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2006 Christian Grothoff (and other contributing authors)
+
+ GNUnet 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, or (at your
+ option) any later version.
+
+ GNUnet 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 GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/threads/signal.c
+ * @brief code for installing and uninstalling signal handlers
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util_threads.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+typedef struct SignalHandlerContext {
+ int sig;
+
+ SignalHandler method;
+
+#ifndef MINGW
+ struct sigaction oldsig;
+#endif
+} SignalHandlerContext;
+
+struct SignalHandlerContext * signal_handler_install(int signal,
+ SignalHandler handler) {
+ struct SignalHandlerContext * ret;
+ struct sigaction sig;
+
+ ret = MALLOC(sizeof(struct SignalHandlerContext));
+ ret->sig = signal;
+ ret->method = handler;
+#ifndef MINGW
+ sig.sa_handler = (void*) handler;
+ sigemptyset(&sig.sa_mask);
+#ifdef SA_INTERRUPT
+ sig.sa_flags = SA_INTERRUPT; /* SunOS */
+#else
+ sig.sa_flags = SA_RESTART;
+#endif
+ sigaction(signal, &sig, &ret->oldsig);
+#else
+ /* FIXME: mingw! */
+#endif
+ return ret;
+}
+
+void signal_handler_uninstall(int signal,
+ SignalHandler handler,
+ struct SignalHandlerContext * ctx) {
+#ifndef MINGW
+ struct sigaction sig;
+
+ GE_ASSERT(NULL, (ctx->sig == signal) && (ctx->method == handler));
+ sigemptyset(&sig.sa_mask);
+ sigaction(signal, &ctx->oldsig, &sig);
+#else
+ /* FIXME: mingw! */
+#endif
+}
+
Property changes on: GNUnet/src/util/threads/signal.c
___________________________________________________________________
Name: svn:eol-style
+ native
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r3152 - in GNUnet/src: include server util/os util/threads,
grothoff <=