LRN: Fix automake deps to allow -j* builds again
[oweals/gnunet.git] / src / util / os_installation.c
index 39b5174e360394c61f415c7036989d848b59585f..36627a8d8834ddbf621f37bbfef18bed1ca978a6 100644 (file)
  * @brief get paths used by the program
  * @author Milan
  */
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0                           /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
@@ -42,7 +33,7 @@ extern "C"
 #include "gnunet_configuration_lib.h"
 #include "gnunet_disk_lib.h"
 #include "gnunet_os_lib.h"
-#if OSX
+#if DARWIN
 #include <mach-o/ldsyms.h>
 #include <mach-o/dyld.h>
 #endif
@@ -55,32 +46,31 @@ static char *
 get_path_from_proc_maps ()
 {
   char fn[64];
-  char *line;
-  char *dir;
+  char line[1024];
+  char dir[1024];
   FILE *f;
+  char *lgu;
 
-  GNUNET_snprintf (fn, 64, "/proc/%u/maps", getpid ());
-  line = GNUNET_malloc (1024);
-  dir = GNUNET_malloc (1024);
+  GNUNET_snprintf (fn,
+                  sizeof(fn), 
+                  "/proc/%u/maps", 
+                  getpid ());
   f = fopen (fn, "r");
-  if (f != NULL)
+  if (f == NULL)
+    return NULL;
+  while (NULL != fgets (line, sizeof(line), f))
     {
-      while (NULL != fgets (line, 1024, f))
-        {
-          if ((1 == sscanf (line,
-                            "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%s",
-                            dir)) && (NULL != strstr (dir, "libgnunetutil")))
-            {
-              strstr (dir, "libgnunetutil")[0] = '\0';
-              fclose (f);
-              GNUNET_free (line);
-              return dir;
-            }
-        }
-      fclose (f);
+      if ((1 == sscanf (line,
+                       "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%s",
+                       dir)) &&
+         (NULL != (lgu = strstr (dir, "libgnunetutil"))))
+       {
+         lgu[0] = '\0';
+         fclose (f);
+         return GNUNET_strdup (dir);
+       }
     }
-  GNUNET_free (dir);
-  GNUNET_free (line);
+  fclose (f);
   return NULL;
 }
 
@@ -91,29 +81,28 @@ static char *
 get_path_from_proc_exe ()
 {
   char fn[64];
-  char *lnk;
-  size_t size;
+  char lnk[1024];
+  ssize_t size;
 
-  GNUNET_snprintf (fn, 64, "/proc/%u/exe", getpid ());
-  lnk = GNUNET_malloc (1024);
-  size = readlink (fn, lnk, 1023);
-  if ((size == 0) || (size >= 1024))
+  GNUNET_snprintf (fn, 
+                  sizeof(fn), "/proc/%u/exe", getpid ());
+  size = readlink (fn, lnk, sizeof (lnk)-1);
+  if (size <= 0)
     {
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "readlink", fn);
-      GNUNET_free (lnk);
       return NULL;
     }
+  GNUNET_assert (size < sizeof (lnk));
   lnk[size] = '\0';
   while ((lnk[size] != '/') && (size > 0))
     size--;
   if ((size < 4) || (lnk[size - 4] != '/'))
     {
       /* not installed in "/bin/" -- binary path probably useless */
-      GNUNET_free (lnk);
       return NULL;
     }
   lnk[size] = '\0';
-  return lnk;
+  return GNUNET_strdup (lnk);
 }
 #endif
 
@@ -124,20 +113,19 @@ get_path_from_proc_exe ()
 static char *
 get_path_from_module_filename ()
 {
-  char *path;
+  char path[4097];
   char *idx;
 
-  path = GNUNET_malloc (4097);
-  GetModuleFileName (NULL, path, 4096);
+  GetModuleFileName (NULL, path, sizeof(path)-1);
   idx = path + strlen (path);
   while ((idx > path) && (*idx != '\\') && (*idx != '/'))
     idx--;
   *idx = '\0';
-  return path;
+  return GNUNET_strdup (path);
 }
 #endif
 
-#if OSX
+#if DARWIN
 typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize);
 
 static char *
@@ -205,8 +193,15 @@ get_path_from_dyld_image ()
 }
 #endif
 
+/**
+ * Return the actual path to a file found in the current
+ * PATH environment variable.
+ *
+ * @param binary the name of the file to find
+ * @return path to binary, NULL if not found
+ */
 static char *
-get_path_from_PATH ()
+get_path_from_PATH (const char *binary)
 {
   char *path;
   char *pos;
@@ -219,12 +214,11 @@ get_path_from_PATH ()
     return NULL;
   path = GNUNET_strdup (p);     /* because we write on it */
   buf = GNUNET_malloc (strlen (path) + 20);
-  pos = path;
-
-  while (NULL != (end = strchr (pos, ':')))
+  pos = path;  
+  while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
     {
       *end = '\0';
-      sprintf (buf, "%s/%s", pos, "gnunetd");
+      sprintf (buf, "%s/%s", pos, binary);
       if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
         {
           pos = GNUNET_strdup (pos);
@@ -234,7 +228,7 @@ get_path_from_PATH ()
         }
       pos = end + 1;
     }
-  sprintf (buf, "%s/%s", pos, "gnunetd");
+  sprintf (buf, "%s/%s", pos, binary);
   if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
     {
       pos = GNUNET_strdup (pos);
@@ -285,7 +279,7 @@ os_get_gnunet_path ()
   if (ret != NULL)
     return ret;
 #endif
-#if OSX
+#if DARWIN
   ret = get_path_from_dyld_image ();
   if (ret != NULL)
     return ret;
@@ -293,13 +287,15 @@ os_get_gnunet_path ()
   if (ret != NULL)
     return ret;
 #endif
-  ret = get_path_from_PATH ();
+  ret = get_path_from_PATH ("gnunet-arm");
   if (ret != NULL)
     return ret;
   /* other attempts here */
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-             _("Could not determine installation path for GNUnet.  Set `%s' environment variable.\n"),
-             "GNUNET_PREFIX");
+              _
+              ("Could not determine installation path for %s.  Set `%s' environment variable.\n"),
+             "GNUnet",
+              "GNUNET_PREFIX");
   return NULL;
 }
 
@@ -314,6 +310,7 @@ os_get_exec_path ()
 {
   char *ret;
 
+  ret = NULL;
 #if LINUX
   ret = get_path_from_proc_exe ();
   if (ret != NULL)
@@ -324,13 +321,13 @@ os_get_exec_path ()
   if (ret != NULL)
     return ret;
 #endif
-#if OSX
+#if DARWIN
   ret = get_path_from_NSGetExecutablePath ();
   if (ret != NULL)
     return ret;
 #endif
   /* other attempts here */
-  return NULL;
+  return ret;
 }
 
 
@@ -425,6 +422,10 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
         DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale"
         DIR_SEPARATOR_STR;
       break;
+    case GNUNET_OS_IPK_ICONDIR:
+      dirname =
+        DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR;
+      break;
     default:
       GNUNET_free (execpath);
       return NULL;
@@ -435,10 +436,90 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind)
   return tmp;
 }
 
-#if 0                           /* keep Emacsens' auto-indent happy */
+
+/**
+ * Check whether an executable exists and possibly
+ * if the suid bit is set on the file.
+ * Attempts to find the file using the current
+ * PATH environment variable as a search path.
+ *
+ * @param binary the name of the file to check
+ * @return GNUNET_YES if the file is SUID, 
+ *         GNUNET_NO if not SUID (but binary exists)
+ *         GNUNET_SYSERR on error (no such binary or not executable)
+ */
+int
+GNUNET_OS_check_helper_binary (const char *binary)
 {
+  struct stat statbuf;
+  char *p;
+  char *pf;
+#ifdef MINGW
+  SOCKET rawsock;
+  char *binaryexe;
+
+  GNUNET_asprintf (&binaryexe, "%s.exe", binary);
+  p = get_path_from_PATH (binaryexe);
+  if (p != NULL)
+    {
+      GNUNET_asprintf (&pf, "%s/%s", p, binaryexe);
+      GNUNET_free (p);
+      p = pf;
+    }
+  free (binaryexe);
+#else
+  p = get_path_from_PATH (binary);
+  if (p != NULL)
+    {
+      GNUNET_asprintf (&pf, "%s/%s", p, binary);
+      GNUNET_free (p);
+      p = pf;
+    }
 #endif
-#ifdef __cplusplus
-}
+  if (p == NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                 _("Could not find binary `%s' in PATH!\n"),
+                 binary);
+      return GNUNET_SYSERR;
+    }
+  if (0 != STAT (p, &statbuf))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 
+                 _("stat (%s) failed: %s\n"), 
+                 p,
+                 STRERROR (errno));
+      GNUNET_free (p);
+      return GNUNET_SYSERR;
+    }
+#ifndef MINGW
+  if ( (0 != (statbuf.st_mode & S_ISUID)) &&
+       (statbuf.st_uid == 0) )
+    {
+      GNUNET_free (p);
+      return GNUNET_YES;
+    }
+  if (0 == ACCESS (p, X_OK))
+    {
+      GNUNET_free (p);
+      return GNUNET_NO;
+    }
+  GNUNET_free (p);
+  return GNUNET_SYSERR;
+#else
+  GNUNET_free (p);
+  rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
+  if (INVALID_SOCKET == rawsock)
+    {
+      DWORD err = GetLastError ();
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
+                 "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) failed! GLE = %d\n", err);
+      return GNUNET_NO; /* not running as administrator */
+    }
+  closesocket (rawsock);
+  return GNUNET_YES;
 #endif
-/* end of installpath.c */
+}
+
+
+/* end of os_installation.c */