1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2008-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25
26 // These functions are also defined in liboctave or libinterp. They
27 // are repeated here to avoid having to link the main Octave program
28 // with the Octave libraries.
29
30 #if ! defined (octave_shared_fcns_h)
31 #define octave_shared_fcns_h 1
32
33 #include <cctype>
34
35 #if defined (OCTAVE_USE_WINDOWS_API)
36
37 #include <windows.h>
38 #include <tlhelp32.h>
39
40 #if defined (_MSC_VER)
41 # define popen _popen
42 # define pclose _pclose
43 #endif
44
45 static std::string
w32_get_octave_home(void)46 w32_get_octave_home (void)
47 {
48 std::string retval;
49
50 std::string bin_dir;
51
52 char namebuf[MAX_PATH+1];
53 if (GetModuleFileName (GetModuleHandle (nullptr), namebuf, MAX_PATH))
54 {
55 namebuf[MAX_PATH] = '\0';
56
57 std::string exe_name = namebuf;
58 std::size_t pos = exe_name.rfind ('\\');
59
60 if (pos != std::string::npos)
61 bin_dir = exe_name.substr (0, pos + 1);
62 }
63
64 if (! bin_dir.empty ())
65 {
66 std::size_t pos = bin_dir.rfind (R"(\bin\)");
67
68 if (pos != std::string::npos)
69 retval = bin_dir.substr (0, pos);
70 }
71
72 return retval;
73 }
74
75 #endif
76
77 // Find the directory where the octave binary is supposed to be
78 // installed.
79
80 #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \
81 && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM))
82 static const char dir_sep_char = '\\';
83 #else
84 static const char dir_sep_char = '/';
85 #endif
86
87 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
88 static std::string dir_sep_chars = R"(/\)";
89 #else
90 static std::string dir_sep_chars = "/";
91 #endif
92
93 static std::string
octave_getenv(const std::string & name)94 octave_getenv (const std::string& name)
95 {
96 char *value = ::getenv (name.c_str ());
97
98 return value ? value : "";
99 }
100
101 static std::string Voctave_home;
102 static std::string Voctave_exec_home;
103
104 static void
set_octave_home(void)105 set_octave_home (void)
106 {
107 std::string op = OCTAVE_PREFIX;
108 std::string oep = OCTAVE_EXEC_PREFIX;
109
110 std::string oh = octave_getenv ("OCTAVE_HOME");
111 std::string oeh = octave_getenv ("OCTAVE_EXEC_HOME");
112
113 #if defined (OCTAVE_USE_WINDOWS_API)
114 if (oh.empty ())
115 oh = w32_get_octave_home ();
116 #endif
117
118 // If OCTAVE_HOME is set in the environment, use that. Otherwise,
119 // default to ${prefix} from configure.
120
121 Voctave_home = (oh.empty () ? op : oh);
122
123 // If OCTAVE_EXEC_HOME is set in the environment, use that.
124 // Otherwise, if ${prefix} and ${exec_prefix} from configure are set
125 // to the same value, use OCTAVE_HOME from the environment if it is set.
126 // Otherwise, default to ${exec_prefix} from configure.
127
128 if (! oeh.empty ())
129 Voctave_exec_home = oeh;
130 else if (op == oep && ! oh.empty ())
131 Voctave_exec_home = oh;
132 else
133 Voctave_exec_home = oep;
134 }
135
is_dir_sep(char c)136 static bool is_dir_sep (char c)
137 {
138 return dir_sep_chars.find (c) != std::string::npos;
139 }
140
141 static bool
absolute_pathname(const std::string & s)142 absolute_pathname (const std::string& s)
143 {
144 std::size_t len = s.length ();
145
146 if (len == 0)
147 return false;
148
149 if (is_dir_sep (s[0]))
150 return true;
151
152 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
153 if ((len == 2 && isalpha (s[0]) && s[1] == ':')
154 || (len > 2 && isalpha (s[0]) && s[1] == ':'
155 && is_dir_sep (s[2])))
156 return true;
157 #endif
158
159 return false;
160 }
161
162 static std::string
prepend_home_dir(const std::string & hd,const std::string & s)163 prepend_home_dir (const std::string& hd, const std::string& s)
164 {
165 std::string retval = s;
166
167 if (! absolute_pathname (retval))
168 retval = hd + dir_sep_char + s;
169
170 if (dir_sep_char != '/')
171 std::replace (retval.begin (), retval.end (), '/', dir_sep_char);
172
173 return retval;
174 }
175
176 // prepend_octave_home is used in mkoctfile.in.cc and
177 // octave-config.in.cc but not in main.in.cc. Tagging it as unused
178 // avoids warnings from GCC about an unused function but should not
179 // cause trouble in the event that it actually is used.
180
181 OCTAVE_UNUSED
182 static std::string
prepend_octave_home(const std::string & s)183 prepend_octave_home (const std::string& s)
184 {
185 return prepend_home_dir (Voctave_home, s);
186 }
187
188 static std::string
prepend_octave_exec_home(const std::string & s)189 prepend_octave_exec_home (const std::string& s)
190 {
191 return prepend_home_dir (Voctave_exec_home, s);
192 }
193
194 #endif
195