gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r3068 - GNUnet/src/util/os


From: moon
Subject: [GNUnet-SVN] r3068 - GNUnet/src/util/os
Date: Mon, 26 Jun 2006 13:49:57 -0700 (PDT)

Author: moon
Date: 2006-06-26 13:49:53 -0700 (Mon, 26 Jun 2006)
New Revision: 3068

Added:
   GNUnet/src/util/os/installpath.c
Log:
get the install paths (DATADIR, BINDIR, LIBDIR on so on)
to adapt still...



Added: GNUnet/src/util/os/installpath.c
===================================================================
--- GNUnet/src/util/os/installpath.c    2006-06-26 20:35:08 UTC (rev 3067)
+++ GNUnet/src/util/os/installpath.c    2006-06-26 20:49:53 UTC (rev 3068)
@@ -0,0 +1,256 @@
+/*
+     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 src/util/os/prefix.c
+ * @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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "gnunet_util_config.h"
+
+#define PATH_TRY 96
+
+/*
+ * List of app dirs
+ * Used to find paths
+ */
+enum InstallPathKind {
+  PREFIX,
+  BINDIR,
+  LIBDIR,
+  DATADIR,
+  PACKAGEDATADIR,
+  LOCALEDIR };
+
+/*
+ * @brief get the path to the executable, including the binary itself
+ * @author Milan
+ * @param ectx the context to report the errors to
+ * @param cfg the context to get configuration values from
+ * @returns a pointer to the executable path, owned by the function (don't 
free it)
+ */
+static char *os_get_exec_path(struct GE_Context * ectx,
+                              struct GC_Configuration * cfg) {
+#ifdef WINDOWS
+/* FIXME: get the path
+ * set found and execpath so the end of the function is valid */
+
+#else /* Should work on all Unices, else we won't run */
+  static char *execpath = NULL; /* save it between calls */
+
+  /* FIXME: we assume PATH_MAX is the same for all used files */
+  const long path_max = pathconf(".", _PC_PATH_MAX);
+  const long name_max = pathconf(".", _PC_NAME_MAX);
+
+  char *tmp, *path1, *path2, *path3;
+  size_t size, size1, size2;
+  struct stat dummy_stat;
+  int found;
+
+  if(execpath) /* already got the path, don't work more */
+     return execpath;
+
+  /* I. get the path from /proc */
+  tmp = MALLOC(name_max+10);
+  SNPRINTF(tmp, 
+          name_max+10,
+          "/proc/%u/exe",
+          getpid());
+  path1 = MALLOC(PATH_TRY); /* let's try with a little buffer */
+  size = readlink(tmp, path1, PATH_TRY-1);
+  if(size == PATH_TRY) { /* buffer too small */
+    path1 = REALLOC(path1, path_max);
+    size = readlink(tmp, path1, path_max-1); }
+  FREE(tmp);
+  if (size > 0) { /* this method worked well */
+    path1[size] = '\0';
+
+    execpath = STRDUP(path1);
+    FREE(path1);
+    return execpath; }
+
+  FREE(path1);
+
+
+  /* II. reading /proc failed, trying with argv[0] */
+  found = 0;
+  GC_get_configuration_value_string(cfg, "ARGV", "0", "gnunetd", &path1);
+
+  /* 1. absolute path */
+  if(*path1 == '/') {
+    execpath = path1;
+    found = 1; }
+
+  /* 2. relative path */
+  else if(strchr(path1, '/')) {
+    tmp = MALLOC(PATH_TRY); /* let's try with a little buffer */
+    if( !getcwd(tmp, PATH_TRY-1) ) { /* buffer too small */
+      tmp = REALLOC(tmp, path_max);
+      size = getcwd(tmp, path_max-1); }
+
+    execpath = MALLOC(strlen(tmp)+strlen(path1)+2);
+    sprintf(execpath, "%s/%s", tmp, path1);
+    FREE(tmp);
+    FREE(path1);
+    found = 1; }
+
+  /* 3. program in PATH */
+  else {
+    path3 = MALLOC(PATH_TRY);
+    tmp = STRDUP(getenv("PATH")); /* because we write on it */
+    size = strlen(path1);
+    size1 = PATH_TRY;
+
+    while(strchr(tmp, ':')) {
+      path2 = (strrchr(tmp, ':')+1);
+      size2 = strlen(path2)+size+2);
+      if(size2 > size1) {
+        path3 = REALLOC(path3, size2); /* not nice, but best to do: */
+        size1 = size2; }               /* malloc PATH_MAX bytes is too much */
+
+      sprintf(path3, "%s/%s", path2, path1);
+      if(STAT(path3, &dummy_stat) == 0) {
+        found = 1;
+        break; }
+       *(path2-1) = '\0';
+    }
+
+    if(!found) { /* first dir in PATH */
+      path2 = tmp;
+      sprintf(path3, "%s/%s", path2, path1);
+      if(STAT(path3, &dummy_stat) == 0)
+        found = 1; }
+
+    execpath = STRDUP(path3);
+
+    FREE(path1);
+    FREE(path3);
+    FREE(tmp); }
+
+#endif
+  if(found) {
+      return execpath; }
+  else { /* we can do nothing to run normally */
+    GE_LOG(NULL, /* This error should not occur on standard Unices */
+          GE_ERROR | GE_USER | GE_ADMIN | GE_DEVELOPER | GE_IMMEDIATE,
+          _("Cannot determine the path to the executable, your system may be 
broken or not supported.\n"));
+     return NULL; }
+}
+
+
+/*
+ * @brief get the path to a specific app dir
+ * @author Milan
+ * @param ectx the context to report the errors to
+ * @param cfg the context to get configuration values from
+ * @returns a pointer to the dir path (to be freed by the caller)
+ */
+char * os_get_installation_path(struct GE_Context * ectx,
+                                struct GC_Configuration * cfg,
+                                enum InstallPathKind dirkind) {
+
+  static char *prefix = NULL; /*save it between calls */
+
+  unsigned int n;
+  char *dirname, *final_dir, *appname;
+  char *execpath, *tmp, *ptr;
+
+  if(!prefix) { /* if we already got the prefix once, don't work more */
+    if( !(execpath = os_get_exec_path(ectx, cfg)) )
+      return NULL;
+  
+    tmp = STRDUP(execpath);
+    ptr = strrchr(tmp, DIR_SEPARATOR); /* get prefix from prefix/bin/app */
+    *ptr = '\0';
+    n = 1;
+    while( *(ptr-n) == DIR_SEPARATOR ) { /* manage "//" in the path */
+      *(ptr-n) = '\0';
+      n++; }
+    ptr = strrchr(tmp, DIR_SEPARATOR);
+    while( *(ptr-n) == DIR_SEPARATOR ) { /* same, but keep the final '/' */
+      *(ptr-n+1) = '\0';
+      n++; }
+
+    if(*tmp == '\0') { /* no prefix at all */
+      GE_LOG(NULL,
+             GE_ERROR | GE_USER | GE_ADMIN | GE_DEVELOPER | GE_IMMEDIATE,
+             _("Cannot determine the installation prefix. Unknown error.\n"));
+     return NULL; }
+
+    prefix = STRDUP(tmp);
+    FREE(tmp); }
+
+
+  /* what do we have to return ? */
+  GC_get_configuration_value_string(cfg, "ARGV", "0", "gnunetd", &appname);
+
+  switch(dirkind) {
+    case PREFIX:
+      dirname = NULL;
+    case BINDIR:
+      dirname = STRDUP("bin/");
+    case LIBDIR:
+      dirname = STRDUP("lib/");
+    case DATADIR:
+      dirname = STRDUP("share/");
+    case PACKAGEDATADIR:
+      tmp = MALLOC(9+strlen(prefix)+strlen(appname));
+      sprintf(tmp, "share/%s/%s/", prefix, appname);
+      dirname = STRDUP(tmp);
+      FREE(tmp);
+    case LOCALEDIR:
+      dirname = STRDUP("share/locale/");
+    default:
+      return NULL; }
+
+  if( !(tmp = MALLOC(strlen(prefix)+strlen(dirname)+1)) ) {
+    GE_LOG(ectx,
+           GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE,
+          _("Cannot determine the application directories. Memory allocation 
error.\n"));
+    return NULL; }
+
+  sprintf(tmp, "%s%s", prefix, dirname);
+  final_dir = STRDUP(tmp);
+
+  FREE(tmp);
+  FREENONULL(dirname);
+  return final_dir;
+}
+
+#if 0 /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+/* end of prefix.c */





reply via email to

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