gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r4745 - in GNUnet: contrib src/include src/server src/util/


From: gnunet
Subject: [GNUnet-SVN] r4745 - in GNUnet: contrib src/include src/server src/util/os
Date: Sun, 15 Apr 2007 15:35:13 -0600 (MDT)

Author: grothoff
Date: 2007-04-15 15:35:13 -0600 (Sun, 15 Apr 2007)
New Revision: 4745

Modified:
   GNUnet/contrib/config-daemon.scm
   GNUnet/src/include/gnunet_util_os.h
   GNUnet/src/server/gnunetd.c
   GNUnet/src/server/startup.c
   GNUnet/src/server/startup.h
   GNUnet/src/util/os/console.c
   GNUnet/src/util/os/user.c
Log:
fixing Mantis bug #1192

Modified: GNUnet/contrib/config-daemon.scm
===================================================================
--- GNUnet/contrib/config-daemon.scm    2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/contrib/config-daemon.scm    2007-04-15 21:35:13 UTC (rev 4745)
@@ -153,7 +153,7 @@
   (nohelp) 
   '()
   #t
-  "$GNUNET_HOME/data/shared"
+  "$GNUNETD_HOME/data/shared"
   '()
   'always) )
 
@@ -291,11 +291,10 @@
   "GNUNETD"
   "PIDFILE"
   (_ "Where should gnunetd write the PID?")
-  (_ 
-"In which file should gnunetd write the process-id of the server?  If you run 
gnunetd as root, you may want to choose /var/run/gnunetd.pid. It's not the 
default since gnunetd may not have write rights at that location." )
+  (_ "The default is no longer /var/run/gnunetd.pid since we could not delete 
the file on shutdown at that location." )
   '()
   #f
-  "/var/run/gnunetd.pid"
+  "/var/run/gnunetd/pid"
   '()
   'rare) )
 

Modified: GNUnet/src/include/gnunet_util_os.h
===================================================================
--- GNUnet/src/include/gnunet_util_os.h 2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/src/include/gnunet_util_os.h 2007-04-15 21:35:13 UTC (rev 4745)
@@ -244,6 +244,13 @@
                   const char * user);
 
 /**
+ * @brief Change owner of a file
+ */
+int os_change_owner(struct GE_Context * ectx,
+                   const char * filename,
+                   const char * user);
+
+/**
  * Get the current CPU load.
  * @param ectx for error reporting
  * @param cfg to determine acceptable load level (LOAD::MAXCPULOAD)
@@ -312,16 +319,35 @@
  */
 char * os_get_installation_path(enum InstallPathKind dirkind);
 
+/**
+ * Write our process ID to the pid file.  Use only
+ * if you are not calling os_terminal_detach, since
+ * os_terminal_detach will already write the pid file.
+ *
+ * @return OK on success, SYSERR on error
+ */
+int os_write_pid_file(struct GE_Context * ectx,
+                     struct GC_Configuration * cfg,
+                     unsigned int pid);
 
+/**
+ * Delete the PID file (to be called when the daemon
+ * shuts down)
+ */
+int os_delete_pid_file(struct GE_Context * ectx,
+                      struct GC_Configuration * cfg);
 
+
 /**
  * Fork and start a new session to go into the background
- * in the way a good deamon should.
+ * in the way a good deamon should.  Also writes the PID
+ * file.
  *
  * @param filedes pointer to an array of 2 file descriptors
  *        to complete the detachment protocol (handshake)
  */
 int os_terminal_detach(struct GE_Context * ectx,
+                      struct GC_Configuration * cfg,
                       int * filedes);
 
 /**

Modified: GNUnet/src/server/gnunetd.c
===================================================================
--- GNUnet/src/server/gnunetd.c 2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/src/server/gnunetd.c 2007-04-15 21:35:13 UTC (rev 4745)
@@ -44,6 +44,7 @@
 static struct GE_Context * ectx = NULL;
 
 static struct CronManager * cron;
+static struct LoadMonitor * mon;
 
 static char * cfgFilename = DEFAULT_DAEMON_CONFIG_FILE;
 
@@ -89,38 +90,57 @@
         "gnunetd");
 }
 
+
+static int post_detach() {
+  if (OK != changeUser(ectx, cfg)) 
+    return SYSERR; 
+  if (OK != checkPermissions(ectx, cfg)) 
+    return SYSERR;  
+  mon = os_network_monitor_create(ectx,
+                                 cfg);
+  if (mon == NULL) 
+    return SYSERR;  
+  return OK;
+}
+
 /**
  * The main method of gnunetd.
  */
 int gnunet_main() {
-  struct LoadMonitor * mon;
   struct SignalHandlerContext * shc_hup;
   int filedes[2]; /* pipe between client and parent */
 
   if ( (NO == debug_flag) &&
        (OK != os_terminal_detach(ectx,
+                                cfg,
                                 filedes)) )
     return SYSERR;
-  mon = os_network_monitor_create(ectx,
-                                 cfg);
-  if (mon == NULL) {
-   if (NO == debug_flag)
-     os_terminal_detach_complete(ectx,
-                               filedes,
-                                NO);
-   return SYSERR;
+  if (NO != debug_flag) 
+    os_write_pid_file(ectx,
+                     cfg,
+                     (unsigned int)getpid());
+  if (OK != post_detach()) {
+    if (NO == debug_flag)
+      os_terminal_detach_complete(ectx,
+                                 filedes,
+                                 NO);
+    else
+      os_delete_pid_file(ectx, cfg);
+    return SYSERR;
   }
   cron = cron_create(ectx);
   GE_ASSERT(ectx,
            cron != NULL);
 #ifndef WINDOWS
-  shc_hup = signal_handler_install(SIGHUP, &reread_config);
+  shc_hup = signal_handler_install(SIGHUP, 
+                                  &reread_config);
 #endif
   if (OK != initCore(ectx,
                     cfg,
                     cron,
                     mon)) {
-       GE_LOG(ectx, GE_FATAL | GE_USER | GE_IMMEDIATE,
+       GE_LOG(ectx, 
+              GE_FATAL | GE_USER | GE_IMMEDIATE,
                _("Core initialization failed.\n"));
                
     cron_destroy(cron);
@@ -142,7 +162,6 @@
   
   initConnection(ectx, cfg, mon, cron);
   loadApplicationModules();
-  writePIDFile(ectx, cfg);
   if (NO == debug_flag)
     os_terminal_detach_complete(ectx,
                                filedes,
@@ -152,7 +171,7 @@
   waitForSignalHandler(ectx);
   disableCoreProcessing();
   cron_stop(cron);
-  deletePIDFile(ectx, cfg);
+  os_delete_pid_file(ectx, cfg);
   stopTCPServer();
   unloadApplicationModules();
   doneConnection();
@@ -240,10 +259,6 @@
                                                                    
GE_IMMEDIATE));
     }
   }
-  if (OK != changeUser(ectx, cfg)) {
-    GNUNET_fini(ectx, cfg);
-    return 1;
-  }
   setFdLimit(ectx, cfg);
   if (OK != checkUpToDate(ectx,
                          cfg)) {
@@ -256,13 +271,16 @@
   }
   
 #ifdef MINGW
-  if (GC_get_configuration_value_yesno(cfg, "GNUNETD", "WINSERVICE", NO) == 
YES) {
+  if (GC_get_configuration_value_yesno(cfg, 
+                                      "GNUNETD",
+                                      "WINSERVICE", 
+                                      NO) == YES) {
     SERVICE_TABLE_ENTRY DispatchTable[] =
       {{"GNUnet", ServiceMain}, {NULL, NULL}};
     ret = (GNStartServiceCtrlDispatcher(DispatchTable) != 0);
   } else
 #endif
-  ret = gnunet_main();
+    ret = gnunet_main();
   GNUNET_fini(ectx, cfg);
   if (ret != OK)
     return 1;

Modified: GNUnet/src/server/startup.c
===================================================================
--- GNUnet/src/server/startup.c 2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/src/server/startup.c 2007-04-15 21:35:13 UTC (rev 4745)
@@ -250,67 +250,80 @@
 #endif
 }
 
-static char * getPIDFile(struct GC_Configuration * cfg) {
-  char * pif;
-
-  if (0 != GC_get_configuration_value_filename(cfg,
-                                              "GNUNETD",
-                                              "PIDFILE",
-                                              VAR_DAEMON_DIRECTORY 
"/gnunetd.pid",
-                                              &pif))
-    return NULL;
-  return pif;
+int checkPermission(struct GE_Context * ectx,
+                   struct GC_Configuration * cfg,
+                   const char * section,
+                   const char * option,
+                   const char * def,
+                   int is_directory,
+                   int mode) {
+  char * fn;
+  int i;
+  
+  GC_get_configuration_value_filename(cfg,
+                                     section,
+                                     option,
+                                     def,
+                                     &fn);
+  if (is_directory)
+    disk_directory_create(ectx, fn);
+  else
+    disk_directory_create_for_file(ectx, fn);
+  if ( (0 != ACCESS(fn, F_OK)) &&
+       (mode == W_OK) ) {
+    /* adjust check to see if directory is writable */
+    i = strlen(fn);
+    while ( (i > 1) &&
+           (fn[i] != DIR_SEPARATOR) )
+      i--;
+    fn[i] = '\0';    
+    mode = X_OK | W_OK;
+  }
+  if (0 != ACCESS(fn, mode)) {
+    GE_LOG(ectx,
+          GE_FATAL | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+          _("Insufficient access permissions for `%s': %s"),
+          fn,
+          STRERROR(errno));
+    FREE(fn);
+    return SYSERR;
+  }
+  FREE(fn);
+  return OK;
 }
 
-/**
- * Write our process ID to the pid file.
- */
-void writePIDFile(struct GE_Context * ectx,
-                 struct GC_Configuration * cfg) {
-  FILE * pidfd;
-  char * pif;
+#define CHECK(a,b,c,d,e) if (OK != checkPermission(ectx, cfg, a, b, c, d, e)) 
return SYSERR;   
 
-  pif = getPIDFile(cfg);
-  if (pif == NULL)
-    return; /* no PID file */
-  pidfd = FOPEN(pif, "w");
-  if (pidfd == NULL) {
-    GE_LOG_STRERROR_FILE(ectx,
-                        GE_WARNING | GE_ADMIN | GE_BULK,
-                        "fopen",
-                        pif);
-    FREE(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);
+int checkPermissions(struct GE_Context * ectx,
+                    struct GC_Configuration * cfg) {
+  CHECK("PATHS",
+       "GNUNETD_HOME",
+       "/var/lib/gnunet",
+       YES,
+       W_OK | X_OK);  
+  CHECK("GNUNETD",
+       "LOGFILE",
+       "$GNUNETD_HOME/daemon-logs",
+       NO,
+       W_OK);
+  /* these should only be checked if "fs" is actually
+     loaded; we clearly should not check everything here
+     that just might be used (MYSQL-CONFIG, F2F-FRIENDS),
+     OTOH, late messages in the startup sequence are also
+     not great.  Would be nice if we could find a way to
+     keep things decentralized and still do a nice job
+     with reporting errors... */
+  CHECK("FS",
+       "DIR",
+       "$GNUNETD_HOME/data/fs",
+       YES,
+       W_OK | X_OK);
+  CHECK("FS",
+       "INDEX-DIRECTORY",
+       "$GNUNETD_HOME/data/shared",
+       YES,
+       W_OK | X_OK);
+  return OK;
 }
 
-void deletePIDFile(struct GE_Context * ectx,
-                  struct GC_Configuration * cfg) {
-  char * pif = getPIDFile(cfg);
-  if (pif == NULL)
-    return; /* no PID file */
-  if (YES == disk_file_test(ectx,
-                           pif)) {
-    if (0 != UNLINK(pif))
-      GE_LOG_STRERROR_FILE(ectx,
-                          GE_WARNING | GE_ADMIN | GE_BULK,
-                          "unlink",
-                          pif);
-  }
-  FREE(pif);
-}
-
 /* end of startup.c */

Modified: GNUnet/src/server/startup.h
===================================================================
--- GNUnet/src/server/startup.h 2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/src/server/startup.h 2007-04-15 21:35:13 UTC (rev 4745)
@@ -37,19 +37,10 @@
 int setFdLimit(struct GE_Context * ectx,
               struct GC_Configuration * cfg);
 
-/**
- * Write our process ID to the pid file.
- */
-void writePIDFile(struct GE_Context * ectx,
-                 struct GC_Configuration * cfg);
+int checkPermissions(struct GE_Context * ectx,
+                    struct GC_Configuration * cfg);
 
 /**
- * Delete the pid file.
- */
-void deletePIDFile(struct GE_Context * ectx,
-                  struct GC_Configuration * cfg);
-
-/**
  * @brief Cap datastore limit to the filesystem's capabilities
  * @notice FAT does not support files larger than 2/4 GB
  * @param ectx error handler

Modified: GNUnet/src/util/os/console.c
===================================================================
--- GNUnet/src/util/os/console.c        2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/src/util/os/console.c        2007-04-15 21:35:13 UTC (rev 4745)
@@ -27,13 +27,128 @@
  * receives a SIGTERM/SIGHUP etc.
  */
 
+#include "gnunet_directories.h"
 #include "gnunet_util_os.h"
 #include "gnunet_util_error.h"
 #include "gnunet_util_string.h"
 #include "gnunet_util_disk.h"
 #include "platform.h"
 
+
+static char * 
+getPIDFile(struct GC_Configuration * cfg) {
+  char * pif;
+  
+  if (0 != GC_get_configuration_value_filename(cfg,
+                                              "GNUNETD",
+                                              "PIDFILE",
+                                              VAR_DAEMON_DIRECTORY 
"/gnunetd/pid",
+                                              &pif))
+    return NULL;
+  return pif;
+}
+
+
 /**
+ * Write our process ID to the pid file.
+ *
+ * @return OK on success, SYSERR on error
+ */
+int os_write_pid_file(struct GE_Context * ectx,
+                     struct GC_Configuration * cfg,
+                     unsigned int pid) {
+  FILE * pidfd;
+  char * pif;
+  char * user;
+  char * rdir;
+  int len;
+
+  pif = getPIDFile(cfg);
+  if (pif == NULL)
+    return OK; /* no PID file */
+  GC_get_configuration_value_string(cfg,
+                                   "GNUNETD",
+                                   "USER",
+                                   "",
+                                   &user);
+  rdir = STRDUP(pif);
+  len = strlen(rdir);
+  while ( (len > 0) &&
+         (rdir[len] != DIR_SEPARATOR) )
+    len--;
+  rdir[len] = '\0';
+  if (0 != ACCESS(rdir, F_OK)) {
+    /* we get to create a directory -- and claim it
+       as ours! */
+    disk_directory_create(ectx, rdir);
+    if (strlen(user)) 
+      os_change_owner(ectx,
+                     rdir, 
+                     user);
+  }
+  if (0 != ACCESS(rdir, W_OK | X_OK)) {
+    GE_LOG_STRERROR_FILE(ectx,
+                        GE_ERROR | GE_ADMIN | GE_USER | GE_BULK,
+                        "access",
+                        rdir);
+    FREE(rdir);
+    FREE(user);
+    return SYSERR;
+  }
+  FREE(rdir);
+  pidfd = FOPEN(pif, "w");
+  if (pidfd == NULL) {
+    GE_LOG_STRERROR_FILE(ectx,
+                        GE_WARNING | GE_ADMIN | GE_BULK,
+                        "fopen",
+                        pif);
+    FREE(pif);
+    FREE(user);
+    return SYSERR;
+  }
+  if (0 > FPRINTF(pidfd,
+                 "%u",
+                 pid)) 
+    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);
+  if (strlen(user)) 
+    os_change_owner(ectx,
+                   pif, 
+                   user);
+  FREE(user);  
+  FREE(pif);
+  return OK;
+}
+
+int os_delete_pid_file(struct GE_Context * ectx,
+                      struct GC_Configuration * cfg) {
+  char * pif = getPIDFile(cfg);
+  if (pif == NULL)
+    return OK; /* no PID file */
+  if (YES == disk_file_test(ectx,
+                           pif)) {
+    if (0 != UNLINK(pif)) {
+      GE_LOG_STRERROR_FILE(ectx,
+                          GE_WARNING | GE_ADMIN | GE_BULK,
+                          "unlink",
+                          pif);
+      FREE(pif);
+      return SYSERR;
+    }
+  }
+  FREE(pif);
+  return OK;
+}
+
+
+/**
  * Fork and start a new session to go into the background
  * in the way a good deamon should.
  *
@@ -41,6 +156,7 @@
  *        to complete the detachment protocol (handshake)
  */
 int os_terminal_detach(struct GE_Context * ectx,
+                      struct GC_Configuration * cfg,
                       int * filedes) {
   pid_t pid;
   int nullfd;
@@ -78,10 +194,14 @@
        ok = OK;
     }
     fflush(stdout);
-    if (ok == OK)
+    if (ok == OK) {
+      os_write_pid_file(ectx, 
+                       cfg,
+                       pid);
       exit(0);
-    else
+    } else {
       exit(1); /* child reported error */
+    }
   }
   if (0 != CLOSE(filedes[0]))
     GE_LOG_STRERROR(ectx,

Modified: GNUnet/src/util/os/user.c
===================================================================
--- GNUnet/src/util/os/user.c   2007-04-14 22:41:44 UTC (rev 4744)
+++ GNUnet/src/util/os/user.c   2007-04-15 21:35:13 UTC (rev 4745)
@@ -109,6 +109,7 @@
 }
 
 
+
 /**
  * @brief Change user ID
  */
@@ -120,9 +121,10 @@
   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);
+          GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+          _("Cannot obtain information about user `%s': %s\n"),
+          user,
+          STRERROR(errno));
     return SYSERR;
   }
   if((0 != setgid(pws->pw_gid)) ||
@@ -147,3 +149,34 @@
 }
 
 
+
+/**
+ * @brief Change owner of a file
+ */
+int os_change_owner(struct GE_Context * ectx,
+                   const char * filename,
+                   const char * user) {
+#ifndef MINGW
+  struct passwd * pws;
+
+  pws = getpwnam(user);
+  if (pws == NULL) {
+    GE_LOG(ectx,
+          GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+          _("Cannot obtain information about user `%s': %s\n"),
+          user,
+          STRERROR(errno));
+    return SYSERR;
+  }
+  if (0 != chown(filename,
+                pws->pw_uid,
+                pws->pw_gid))
+    GE_LOG_STRERROR_FILE(ectx,
+                        GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+                        "chown",
+                        filename);
+#endif
+  return OK;
+}
+
+





reply via email to

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