gnunet-svn
[Top][All Lists]
Advanced

[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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]