These patches add new functions setEnvPath and os::path_separator and uses
setEnvPath to add the directory containing the LyX executable to the PATH
on MacOSX and on Windows.

The 14x patch also resurrects PutEnv that was removed 22 months ago by
André. Looking at it, I have a question: if ::putenv is so evil (and I see
that it is) why do we use it in preference to ::setenv? Ie, why

#if HAVE_PUTENV
#else
# ifdef HAVE_SETENV
# else
# endif
#endif

rather than

#if defined (HAVE_SETENV)
#elif defined (HAVE_PUTENV)
#else
#endif

-- 
Angus
Index: src/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v
retrieving revision 1.1021.2.58
diff -u -p -r1.1021.2.58 ChangeLog
--- src/ChangeLog	10 Jan 2005 19:17:22 -0000	1.1021.2.58
+++ src/ChangeLog	12 Jan 2005 15:49:21 -0000
@@ -1,3 +1,8 @@
+2005-01-12  Angus Leeming  <[EMAIL PROTECTED]>
+
+	* lyx_main.C (init): set the PATH variable to include the
+	directory containing the LyX binary when running on Mac or Windows.
+
 2005-01-10  Angus Leeming  <[EMAIL PROTECTED]>
 
 	* Makefile.am: remove the lyx_main.C special casing.
Index: src/lyx_main.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyx_main.C,v
retrieving revision 1.134.2.9
diff -u -p -r1.134.2.9 lyx_main.C
--- src/lyx_main.C	10 Jan 2005 19:17:25 -0000	1.134.2.9
+++ src/lyx_main.C	12 Jan 2005 15:49:22 -0000
@@ -87,6 +87,16 @@ LyX::LyX(int & argc, char * argv[])
 
 	lyx::init_package(argv[0], cl_system_support, cl_user_support);
 
+	// Set the locale_dir.
+	string locale_dir = lyx::package().locale_dir();
+	FileInfo fi(locale_dir);
+	if (fi.isOK() && fi.isDir()) {
+		lyxerr[Debug::INIT]
+			<< "Setting locale directory to "
+			<< locale_dir << endl;
+		gettext_init(locale_dir);
+	}
+
 	// Global bindings (this must be done as early as possible.) (Lgb)
 	toplevel_keymap.reset(new kb_keymap);
 	defaultKeyBindings(toplevel_keymap.get());
@@ -224,39 +234,26 @@ void LyX::init(bool gui)
 	signal(SIGINT, error_handler);
 	signal(SIGTERM, error_handler);
 
-	//
-	// Determine path of binary
-	//
-
 	lyx::Package const & package = lyx::package();
 
+#if !defined (USE_POSIX_PACKAGING)
+	// Add the directory containing the LyX executable to the path
+	// so that LyX can find things like reLyX.
+	if (package.build_support().empty()) {
+		vector<string> path = getEnvPath("PATH");
+		path.insert(path.begin(), package.binary_dir());
+		setEnvPath("PATH", path);
+	}
+#endif
 #if defined (USE_MACOSX_PACKAGING)
-	// Set PATH for LyX/Mac 
-	//
-	// LyX/Mac is a relocatable application bundle; here we add to
-	// the PATH so it can find binaries like reLyX inside its own
-	// application bundle, and also append PATH elements that it
-	// needs to run latex, previewers, etc.
-
-	string oldpath = GetEnv("PATH");
-	string newpath = "PATH=" + oldpath + ":" +
-		lyx::package().binary_dir() + ":";
-	newpath += "/sw/bin:/usr/local/bin:"
-		"/usr/local/teTeX/bin/powerpc-apple-darwin-current";
-	PutEnv(newpath);
-	lyxerr[Debug::INIT] << "Running from LyX/Mac bundle. " 
+	// This hard-coded nastiness should be moved into a LyXRC variable.
+	vector<string> path = getEnvPath("PATH");
+	path.insert(path.begin(), "/usr/local/teTeX/bin/powerpc-apple-darwin-current");
+	path.insert(path.begin(), "/usr/local/bin");
+	path.insert(path.begin(), "/sw/bin");
+	lyxerr[Debug::INIT]  << "Running from LyX/Mac bundle. "
 		"Setting PATH to: " << GetEnv("PATH") << endl;
 #endif
-
-	// Set the locale_dir.
-	string locale_dir = package.locale_dir();
-	FileInfo fi(locale_dir);
-	if (fi.isOK() && fi.isDir()) {
-		lyxerr[Debug::INIT] 
-			<< "Setting locale directory to "
-			<< locale_dir << endl;
-		gettext_init(locale_dir);
-	}
 
 	// Check that user LyX directory is ok. We don't do that if
 	// running in batch mode.
Index: src/support/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/ChangeLog,v
retrieving revision 1.149.2.26
diff -u -p -r1.149.2.26 ChangeLog
--- src/support/ChangeLog	10 Jan 2005 19:17:31 -0000	1.149.2.26
+++ src/support/ChangeLog	12 Jan 2005 15:49:26 -0000
@@ -1,3 +1,13 @@
+2005-01-12  Angus Leeming  <[EMAIL PROTECTED]>
+
+	* filetools.[Ch] (setEnvPath): new function to create a PATH-style
+	string from a vector of paths and to use it to set an environment
+	variable.
+
+	* os.h, os_os2.C, os_unix.C, os_win32.C (path_separator): new
+	function returning the character used to separate paths returned
+	by the PATH environment variable.
+
 2005-01-10  Angus Leeming  <[EMAIL PROTECTED]>
 
 	* os.h:
Index: src/support/filetools.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/filetools.C,v
retrieving revision 1.146.2.11
diff -u -p -r1.146.2.11 filetools.C
--- src/support/filetools.C	10 Jan 2005 19:17:31 -0000	1.146.2.11
+++ src/support/filetools.C	12 Jan 2005 15:49:27 -0000
@@ -378,13 +378,8 @@ vector<string> const getEnvPath(string c
 	typedef boost::char_separator<char> Separator;
 	typedef boost::tokenizer<Separator> Tokenizer;
 
-#if defined (__EMX__) || defined (_WIN32)
-	Separator const separator(";");
-#else
-	Separator const separator(":");
-#endif
-
 	string const env_var = GetEnv(name);
+	Separator const separator(string(1, os::path_separator()).c_str());
 	Tokenizer const tokens(env_var, separator);
 	Tokenizer::const_iterator it = tokens.begin();
 	Tokenizer::const_iterator const end = tokens.end();
@@ -394,6 +389,21 @@ vector<string> const getEnvPath(string c
 		vars.push_back(os::internal_path(*it));
 
 	return vars;
+}
+
+
+void setEnvPath(string const & name, vector<string> const & env)
+{
+	char const separator(os::path_separator());
+	std::ostringstream ss;
+	vector<string>::const_iterator it = env.begin();
+	vector<string>::const_iterator const end = env.end();
+	for (; it != end; ++it) {
+		if (ss.tellp() > 0)
+			ss << separator;
+		ss << os::external_path(*it);
+	}
+	PutEnv(name + "=" + ss.str());
 }
 
 
Index: src/support/filetools.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/filetools.h,v
retrieving revision 1.38.2.2
diff -u -p -r1.38.2.2 filetools.h
--- src/support/filetools.h	10 Jan 2005 19:17:31 -0000	1.38.2.2
+++ src/support/filetools.h	12 Jan 2005 15:49:28 -0000
@@ -113,6 +113,12 @@ string const GetEnv(string const & envna
  */
 std::vector<string> const getEnvPath(string const & name);
 
+/** Set the contents of the environment variable \c name
+ *  using the paths stored in the \c env vector.
+ *  Each element is passed through os::external_path.
+ */
+void setEnvPath(string const & name, std::vector<string> const & env);
+
 ///
 bool PutEnv(string const & envstr);
 
Index: src/support/os.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os.h,v
retrieving revision 1.7.2.6
diff -u -p -r1.7.2.6 os.h
--- src/support/os.h	10 Jan 2005 19:17:31 -0000	1.7.2.6
+++ src/support/os.h	12 Jan 2005 15:49:28 -0000
@@ -30,17 +30,25 @@ public:
 	static string::size_type common_path(string const &p1,
 					     string const &p2);
 
-	// Converts a unix style path to host OS style.
+	/// Converts a unix style path to host OS style.
 	static string external_path(string const &p);
-	// Converts a host OS style path to unix style.
+	/// Converts a host OS style path to unix style.
 	static string internal_path(string const &p);
-	// is path absolute?
+	/// Is the path absolute?
 	static bool is_absolute_path(string const & p);
-	// returns a string suitable to be passed to fopen when
-	// reading a file
+	/** Returns a string suitable to be passed to fopen when
+	 *  reading a file.
+	 */
 	static char const * read_mode();
-	// same for popen().
+	/** Returns a string suitable to be passed to popen when
+	 *  reading a file.
+	 */
 	static char const * popen_read_mode();
+
+	/** The character used to separate paths returned by the
+	 *  PATH environment variable.
+	 */
+	static char path_separator();
 private:
 	static string const nulldev_;
 	static os::shell_type shell_;
Index: src/support/os_os2.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os_os2.C,v
retrieving revision 1.5.2.5
diff -u -p -r1.5.2.5 os_os2.C
--- src/support/os_os2.C	10 Jan 2005 19:17:31 -0000	1.5.2.5
+++ src/support/os_os2.C	12 Jan 2005 15:49:28 -0000
@@ -166,3 +166,11 @@ char const * os::popen_read_mode()
 {
 	return "r";
 }
+
+
+// The character used to separate paths returned by the
+//  PATH environment variable.
+char os::path_separator()
+{
+	return ';';
+}
Index: src/support/os_unix.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os_unix.C,v
retrieving revision 1.6.2.4
diff -u -p -r1.6.2.4 os_unix.C
--- src/support/os_unix.C	10 Jan 2005 19:17:31 -0000	1.6.2.4
+++ src/support/os_unix.C	12 Jan 2005 15:49:28 -0000
@@ -66,3 +66,11 @@ char const * os::popen_read_mode()
 {
 	return "r";
 }
+
+
+// The character used to separate paths returned by the
+//  PATH environment variable.
+char os::path_separator()
+{
+	return ':';
+}
Index: src/support/os_win32.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os_win32.C,v
retrieving revision 1.8.2.8
diff -u -p -r1.8.2.8 os_win32.C
--- src/support/os_win32.C	10 Jan 2005 19:17:31 -0000	1.8.2.8
+++ src/support/os_win32.C	12 Jan 2005 15:49:28 -0000
@@ -133,3 +133,15 @@ char const * os::popen_read_mode()
 {
 	return "r";
 }
+
+
+// The character used to separate paths returned by the
+//  PATH environment variable.
+char os::path_separator()
+{
+#if defined (_WIN32)
+	return ';';
+#else // Cygwin
+	return ':';
+#endif
+}
Index: src/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/ChangeLog,v
retrieving revision 1.2081
diff -u -p -r1.2081 ChangeLog
--- src/ChangeLog	10 Jan 2005 19:17:38 -0000	1.2081
+++ src/ChangeLog	12 Jan 2005 16:07:40 -0000
@@ -1,3 +1,10 @@
+2005-01-12  Angus Leeming  <[EMAIL PROTECTED]>
+
+	* lyx_main.C (init): set the PATH variable to include the
+	directory containing the LyX binary when running on Mac or Windows.
+	Remove cruft that purports to set the locale dir. It doesn't and
+	is not needed anyway.
+
 2005-01-10  Angus Leeming  <[EMAIL PROTECTED]>
 
 	* Makefile.am: remove the lyx_main.C special casing.
Index: src/lyx_main.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyx_main.C,v
retrieving revision 1.192
diff -u -p -r1.192 lyx_main.C
--- src/lyx_main.C	12 Jan 2005 10:30:44 -0000	1.192
+++ src/lyx_main.C	12 Jan 2005 16:07:40 -0000
@@ -343,31 +343,24 @@ void LyX::init(bool gui)
 	signal(SIGTERM, error_handler);
 	// SIGPIPE can be safely ignored.
 
+#if !defined (USE_POSIX_PACKAGING)
+	// Add the directory containing the LyX executable to the path
+	// so that LyX can find things like reLyX.
+	if (package.build_support().empty()) {
+		vector<string> path = getEnvPath("PATH");
+		path.insert(path.begin(), package.binary_dir());
+		setEnvPath("PATH", path);
+	}
+#endif
 #if defined (USE_MACOSX_PACKAGING)
-	// Set PATH for LyX/Mac
- 	//
- 	// LyX/Mac is a relocatable application bundle; here we add to
- 	// the PATH so it can find binaries like reLyX inside its own
- 	// application bundle, and also append PATH elements that it
-	// needs to run latex, previewers, etc.
-	string oldpath = GetEnv("PATH");
-	string newpath = "PATH=" + oldpath + ":" + package().binary_dir() + ":";
-	newpath += "/sw/bin:/usr/local/bin:"
-		"/usr/local/teTeX/bin/powerpc-apple-darwin-current";
-	PutEnv(newpath);
-	lyxerr[Debug::INIT] << "Running from LyX/Mac bundle. "
+	// This hard-coded nastiness should be moved into a LyXRC variable.
+	vector<string> path = getEnvPath("PATH");
+	path.insert(path.begin(), "/usr/local/teTeX/bin/powerpc-apple-darwin-current");
+	path.insert(path.begin(), "/usr/local/bin");
+	path.insert(path.begin(), "/sw/bin");
+	lyxerr[Debug::INIT]  << "Running from LyX/Mac bundle. "
 		"Setting PATH to: " << GetEnv("PATH") << endl;
 #endif
-
-	// Set the locale_dir.
-	string const & locale_dir = package().locale_dir();
-	FileInfo fi(locale_dir);
-	if (fi.isOK() && fi.isDir()) {
-		lyxerr[Debug::INIT]
-			<< "Setting locale directory to "
-			<< locale_dir << endl;
-		//gettext_init(locale_dir);
- 	}
 
 	// Check that user LyX directory is ok. We don't do that if
 	// running in batch mode.
Index: src/support/ChangeLog
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/ChangeLog,v
retrieving revision 1.302
diff -u -p -r1.302 ChangeLog
--- src/support/ChangeLog	12 Jan 2005 12:25:30 -0000	1.302
+++ src/support/ChangeLog	12 Jan 2005 16:07:42 -0000
@@ -1,14 +1,21 @@
 2005-01-12  Angus Leeming  <[EMAIL PROTECTED]>
 
+	* filetools.[Ch] (setEnvPath): new function to create a PATH-style
+	string from a vector of paths and to use it to set an environment
+	variable.
+	(putEnv): resurrect this from the grave.
+
+	* os.h, os_os2.C, os_unix.C, os_win32.C (path_separator): new
+	function returning the character used to separate paths returned
+	by the PATH environment variable.
+
+	* os_win32.C: add #include "lstring.h" back in.
+
 	* package.C.in (package): comment out the ASSERT for now.
 	(check_env_var_dir): write one of the strings to be translated
 	(any one, doesn't matter) on a single line so that the
 	gettext search mechanism in po/Makefile.in.in will register
 	package.C.in as a file containing strings that need translation.
-
-2005-01-12  Angus Leeming  <[EMAIL PROTECTED]>
-
-	* os_win32.C: add #include "lstring.h" back in.
 
 2005-01-10  Angus Leeming  <[EMAIL PROTECTED]>
 
Index: src/support/filetools.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/filetools.C,v
retrieving revision 1.197
diff -u -p -r1.197 filetools.C
--- src/support/filetools.C	10 Jan 2005 19:17:43 -0000	1.197
+++ src/support/filetools.C	12 Jan 2005 16:07:43 -0000
@@ -399,13 +399,8 @@ vector<string> const getEnvPath(string c
 	typedef boost::char_separator<char> Separator;
 	typedef boost::tokenizer<Separator> Tokenizer;
 
-#if defined (__EMX__) || defined (_WIN32)
-	Separator const separator(";");
-#else
-	Separator const separator(":");
-#endif
-
 	string const env_var = GetEnv(name);
+	Separator const separator(string(1, os::path_separator()).c_str());
 	Tokenizer const tokens(env_var, separator);
 	Tokenizer::const_iterator it = tokens.begin();
 	Tokenizer::const_iterator const end = tokens.end();
@@ -418,14 +413,59 @@ vector<string> const getEnvPath(string c
 }
 
 
-string const GetEnvPath(string const & name)
+void setEnvPath(string const & name, vector<string> const & env)
 {
-#ifndef __EMX__
-	string const pathlist = subst(GetEnv(name), ':', ';');
+	char const separator(os::path_separator());
+	std::ostringstream ss;
+	vector<string>::const_iterator it = env.begin();
+	vector<string>::const_iterator const end = env.end();
+	for (; it != end; ++it) {
+		if (ss.tellp() > 0)
+			ss << separator;
+		ss << os::external_path(*it);
+	}
+	putEnv(name + "=" + ss.str());
+}
+
+
+bool putEnv(string const & envstr)
+{
+	// CHECK Look at and fix this.
+	// f.ex. what about error checking?
+
+#if HAVE_PUTENV
+	// this leaks, but what can we do about it?
+	//   Is doing a getenv() and a free() of the older value
+	//   a good idea? (JMarc)
+	// Actually we don't have to leak...calling putenv like this
+	// should be enough: ... and this is obviously not enough if putenv
+	// does not make a copy of the string. It is also not very wise to
+	// put a string on the free store. If we have to leak we should do it
+	// like this:
+	char * leaker = new char[envstr.length() + 1];
+	envstr.copy(leaker, envstr.length());
+	leaker[envstr.length()] = '\0';
+	int const retval = ::putenv(leaker);
+
+	// If putenv does not make a copy of the char const * this
+	// is very dangerous. OTOH if it does take a copy this is the
+	// best solution.
+	// The  only implementation of putenv that I have seen does not
+	// allocate memory. _And_ after testing the putenv in glibc it
+	// seems that we need to make a copy of the string contents.
+	// I will enable the above.
+	//int retval = lyx::putenv(envstr.c_str());
 #else
-	string const pathlist = os::internal_path(GetEnv(name));
+#ifdef HAVE_SETENV
+	string varname;
+	string const str = envstr.split(varname,'=');
+	int const retval = ::setenv(varname.c_str(), str.c_str(), true);
+#else
+	// No environment setting function. Can this happen?
+	int const retval = 1; //return an error condition.
+#endif
 #endif
-	return rtrim(pathlist, ";");
+	return retval == 0;
 }
 
 
Index: src/support/filetools.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/filetools.h,v
retrieving revision 1.57
diff -u -p -r1.57 filetools.h
--- src/support/filetools.h	10 Jan 2005 19:17:43 -0000	1.57
+++ src/support/filetools.h	12 Jan 2005 16:07:44 -0000
@@ -123,6 +123,15 @@ std::string const GetEnv(std::string con
  */
 std::vector<std::string> const getEnvPath(std::string const & name);
 
+/** Set the contents of the environment variable \c name
+ *  using the paths stored in the \c env vector.
+ *  Each element is passed through os::external_path.
+ */
+void setEnvPath(std::string const & name, std::vector<std::string> const & env);
+
+/// Set an environment variable using a string of the form "name=FOO".
+bool putEnv(std::string const & envstr);
+
 /// Substitutes active latex characters with underscores in filename
 std::string const MakeLatexName(std::string const & file);
 
Index: src/support/os.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os.h,v
retrieving revision 1.22
diff -u -p -r1.22 os.h
--- src/support/os.h	10 Jan 2005 19:17:43 -0000	1.22
+++ src/support/os.h	12 Jan 2005 16:07:44 -0000
@@ -21,32 +21,44 @@ namespace lyx {
 namespace support {
 namespace os {
 
-//
 enum shell_type {
 	UNIX,	// Do we have to distinguish sh and csh?
 	CMD_EXE
 };
 
-// do some work just once
+/// Do some work just once.
 void init(int argc, char * argv[]);
 
-// Returns the name of the NULL device (/dev/null, null).
+/// Returns the name of the NULL device (/dev/null, null).
 std::string const & nulldev();
-//
+
+/// Returns "/" on *nix, "C:/", etc on Windows.
 std::string current_root();
-//
+
+///
 shell_type shell();
-// DBCS aware!
+
+/// Extract the path common to both @c p1 and @c p2. DBCS aware!
 std::string::size_type common_path(std::string const & p1, std::string const & p2);
-// Converts a unix style path to host OS style.
+
+/// Converts a unix style path to host OS style.
 std::string external_path(std::string const & p);
-// Converts a host OS style path to unix style.
+
+/// Converts a host OS style path to unix style.
 std::string internal_path(std::string const & p);
-// is path absolute?
+
+/// Is the path absolute?
 bool is_absolute_path(std::string const & p);
-// returns a string suitable to be passed to popen when
-// same for popen().
-	char const * popen_read_mode();
+
+/** Returns a string suitable to be passed to popen when
+ *  reading a file.
+ */
+char const * popen_read_mode();
+
+/** The character used to separate paths returned by the
+ *  PATH environment variable.
+ */
+char path_separator();
 
 } // namespace os
 } // namespace support
Index: src/support/os_os2.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os_os2.C,v
retrieving revision 1.15
diff -u -p -r1.15 os_os2.C
--- src/support/os_os2.C	10 Jan 2005 19:17:43 -0000	1.15
+++ src/support/os_os2.C	12 Jan 2005 16:07:44 -0000
@@ -202,6 +202,12 @@ shell_type shell()
 	return shell_;
 }
 
+
+char path_separator()
+{
+	return ';';
+}
+
 } // namespace os
 } // namespace support
 } // namespace lyx
Index: src/support/os_unix.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os_unix.C,v
retrieving revision 1.16
diff -u -p -r1.16 os_unix.C
--- src/support/os_unix.C	10 Jan 2005 19:17:43 -0000	1.16
+++ src/support/os_unix.C	12 Jan 2005 16:07:44 -0000
@@ -87,6 +87,11 @@ shell_type shell()
 	return UNIX;
 }
 
+char path_separator()
+{
+	return ':';
+}
+
 } // namespace os
 } // namespace support
 } // namespace lyx
Index: src/support/os_win32.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/support/os_win32.C,v
retrieving revision 1.22
diff -u -p -r1.22 os_win32.C
--- src/support/os_win32.C	12 Jan 2005 08:27:14 -0000	1.22
+++ src/support/os_win32.C	12 Jan 2005 16:07:44 -0000
@@ -163,6 +163,15 @@ shell_type shell()
 #endif
 }
 
+char path_separator()
+{
+#if defined (_WIN32)
+	return ';';
+#else // Cygwin
+	return ':';
+#endif
+}
+
 } // namespace os
 } // namespace support
 } // namespace lyx

Reply via email to