This is the mail archive of the sid@sources.redhat.com mailing list for the SID project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

patch for location-independence



The attached patch causes SID to look at argv[0] to determine its
location, so that the installed sid tree can be moved anywhere and
there is no need to set SID_EXEC_PREFIX (to run the sid executable,
at least).

OK to commit?

-- 
Geoff Keating <geoffk@redhat.com>

===File ~/patches/sid-relocate.patch========================
Index: sid/include/ChangeLog
2001-11-19  Geoffrey Keating  <geoffk@redhat.com>

	* sidmiscutil.h (argv0): New variable.
	(make_relative_prefix): New function.
	(sid_file_search_path): Determine default SID_EXEC_PREFIX from
	argv[0].
	* configure.in: Define SID_PREFIX as $prefix.
	* configure: Regenerate.
	* sidconfutil.in: Dummy SID_PREFIX declaration.

Index: sid/main/dynamic/ChangeLog
2001-11-19  Geoffrey Keating  <geoffk@redhat.com>

	* mainDynamic.cxx (sidutil::argv0): Define.

Index: sid/include/configure.in
===================================================================
RCS file: /cvs/cvsfiles/devo/sid/include/configure.in,v
retrieving revision 1.10
diff -p -u -p -r1.10 configure.in
--- configure.in	2001/03/26 19:18:38	1.10
+++ configure.in	2001/11/20 05:26:27
@@ -66,5 +66,7 @@ else
 fi
 AC_DEFINE_UNQUOTED(SID_EXEC_PREFIX,"$sid_exec_prefix",[Define to build-time exec-prefix])
 
+AC_DEFINE_UNQUOTED(SID_PREFIX,"$prefix",[Define to build-time prefix])
+
 dnl Outputs
 AC_OUTPUT(Makefile)
Index: sid/include/sidconfutil.in
===================================================================
RCS file: /cvs/cvsfiles/devo/sid/include/sidconfutil.in,v
retrieving revision 1.4
diff -p -u -p -r1.4 sidconfutil.in
--- sidconfutil.in	2001/03/26 19:18:38	1.4
+++ sidconfutil.in	2001/11/20 05:26:27
@@ -36,3 +36,6 @@
 /* Define to build-time exec-prefix */
 #undef SID_EXEC_PREFIX
 
+/* Define to build-time prefix */
+#undef SID_PREFIX
+
Index: sid/include/sidmiscutil.h
===================================================================
RCS file: /cvs/cvsfiles/devo/sid/include/sidmiscutil.h,v
retrieving revision 1.19
diff -p -u -p -r1.19 sidmiscutil.h
--- sidmiscutil.h	2001/05/25 15:12:54	1.19
+++ sidmiscutil.h	2001/11/20 05:26:27
@@ -20,10 +20,14 @@
 #ifdef __CYGWIN__
 #include <sys/cygwin.h>
 #endif
+#include <unistd.h>
 
 
 namespace sidutil
 {
+  // argv[0] passed to the main program.
+  extern char *argv0;
+
   // Instances of this class template function as bidirectional lookup
   // tables (bijections) for mapping objects to each other by value.
   template <class Obj1, class Obj2>
@@ -310,6 +314,111 @@ namespace sidutil
     }
 
 
+  /* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string
+     that gets to PREFIX starting with the directory portion of
+     PROGNAME and a relative pathname of the difference between
+     BIN_PREFIX and PREFIX.
+     
+     For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX
+     is /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc,
+     then this function will return /red/green/blue/../omega.
+     
+     If no relative prefix can be found, return NULL.  */
+
+  inline std::string *
+  make_relative_prefix (const std::string &progname, 
+			const std::string &bin_prefix, 
+			const std::string &prefix)
+  {
+    std::vector<std::string> prog_dirs = tokenize (progname, "/");
+
+    /* If there is no full pathname, try to find the program by
+       checking in each of the directories specified in the PATH
+       environment variable.  */
+    if (prog_dirs.size() == 1)
+      {
+	char *path = getenv ("PATH");
+	
+	if (path)
+	  {
+	    std::vector<std::string> paths = tokenize (path, ":");
+	    std::vector<std::string>::iterator i;
+	    
+	    for (i = paths.begin();
+		 i != paths.end();
+		 i++)
+	      {
+		std::string s = *i;
+		if (s == "")
+		  s = '.';
+		if (s[s.length()-1] != '/')
+		  s += '/';
+		s += progname;
+		if (! access (s.c_str (), X_OK))
+		  break;
+#ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+		s += HOST_EXECUTABLE_SUFFIX;
+		if (! access (s.c_str (), X_OK))
+		  break;
+#endif
+	      }
+	  
+	    if (i == paths.end())
+	      return NULL;
+	  
+	    prog_dirs = tokenize (*i, "/");
+	  }
+      } else {
+	/* Remove the program name from comparison of directory names.  */
+	prog_dirs.pop_back ();
+      }
+    
+    std::vector<std::string> bin_dirs = tokenize (bin_prefix, "/");
+
+    /* Determine if the program is installed in the standard location, and if
+       so, we don't need to specify relative directories.  */
+    if (prog_dirs == bin_dirs)
+      return new std::string (prefix);
+
+    std::vector<std::string> prefix_dirs = tokenize (prefix, "/");
+
+    /* Find how many directories are in common between bin_prefix & prefix.  */
+    std::vector<std::string>::iterator bin_common, pfx_common;
+    for (bin_common = bin_dirs.begin(), pfx_common = prefix_dirs.begin();
+	 bin_common != bin_dirs.end() && pfx_common != prefix_dirs.end();
+	 bin_common++, pfx_common++)
+      if (*bin_common != *pfx_common)
+	break;
+    
+    /* If there are no common directories, there can be no relative prefix.  */
+    if (bin_common == bin_dirs.begin ())
+      return NULL;
+  
+    std::string result = "";
+
+    /* Build up the pathnames in argv[0].  */
+    for (std::vector<std::string>::iterator i = prog_dirs.begin ();
+	 i != prog_dirs.end ();
+	 i++)
+      {
+	result += *i;
+	result += '/';
+      }
+
+    /* Now build up the ..'s.  */
+    for (; bin_common != bin_dirs.end (); bin_common++)
+      result += "../";
+  
+    /* Put in directories to move over to prefix.  */
+    for (; pfx_common != prefix_dirs.end (); pfx_common++)
+      {
+	result += *pfx_common;
+	result += '/';
+      }
+    
+    return new std::string(result);
+  }
+
   // Return a vector of directory names, where the SID_LIBRARY_PATH
   // and SID_EXEC_PREFIX environment variables are pointing.  Convert
   // all paths to POSIX form on Cygwin.
@@ -337,14 +446,31 @@ namespace sidutil
 	  sep = conv_fn;
       }
 #endif
-    if (!sep) sep = SID_EXEC_PREFIX; // build-time configuration
-    // We really just want to get to pkgdatadir, which is $prefix/share
-    // Guess exec-prefix == prefix
-    std::string pkglibdir1 = std::string(sep) + std::string("/share");
-    search_directories.push_back (pkglibdir1);
-    // Guess exec-prefix == prefix/H-HOST
-    std::string pkglibdir2 = std::string(sep) + std::string("/../share");
-    search_directories.push_back (pkglibdir2);
+    if (sep)
+      {
+	// We really just want to get to pkgdatadir, which is $prefix/share
+	// Guess exec-prefix == prefix
+	std::string pkglibdir1 = std::string(sep) + std::string("/share");
+	search_directories.push_back (pkglibdir1);
+	// Guess exec-prefix == prefix/H-HOST
+	std::string pkglibdir2 = std::string(sep) + std::string("/../share");
+	search_directories.push_back (pkglibdir2);
+      }
+    else
+      {
+	// Guess from argv[0].
+	std::string *path;
+	path = make_relative_prefix (argv0, SID_EXEC_PREFIX "/bin",
+				     SID_PREFIX "/share");
+	if (path)
+	  {
+	    search_directories.push_back (*path);
+	    delete path;
+	  }
+	else
+	  // Fall back to build-time configuration.
+	  search_directories.push_back (SID_PREFIX "/share");
+      }
 
     return search_directories;
   }
Index: sid/main/dynamic/mainDynamic.cxx
===================================================================
RCS file: /cvs/cvsfiles/devo/sid/main/dynamic/mainDynamic.cxx,v
retrieving revision 1.23
diff -p -u -p -r1.23 mainDynamic.cxx
--- mainDynamic.cxx	2001/10/05 19:57:06	1.23
+++ mainDynamic.cxx	2001/11/20 05:26:27
@@ -35,6 +35,9 @@ static void sid_pre_run () {}
 static void sid_post_run () {}
 
 
+namespace sidutil {
+  char *argv0;
+}
 
 void
 version ()
@@ -68,6 +71,8 @@ main(int argc, char* argv[])
   vector< pair<bool,string> > config_items;
   bool dry_run_p = false;
   string config_file;
+
+  argv0 = argv[0];
 
   if (argc == 1)
     {
============================================================


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]