[Top][All Lists]
[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 */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r3068 - GNUnet/src/util/os,
moon <=