source: main/trunk/greenstone2/common-src/src/lib/gsdltools.cpp@ 26677

Last change on this file since 26677 was 26677, checked in by davidb, 11 years ago

Mixed up over precise name to use for Microsoft Visualstudio Compile. Correct value is _MSC_VER. Files now fixed.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/**********************************************************************
2 *
3 * gsdltools.cpp --
4 * A component of the Greenstone digital library software
5 * from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Copyright (C) 1999 The New Zealand Digital Library Project
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but 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 this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "gsdltools.h"
27#include "fileutil.h"
28#include "stdlib.h"
29
30
31#if defined(GSDL_USE_OBJECTSPACE)
32# include <ospace/std/iostream>
33#elif defined(GSDL_USE_IOS_H)
34# include <iostream.h>
35#else
36# include <iostream>
37using namespace std;
38#endif
39
40
41#if defined(__WIN32__)
42#include <windows.h>
43#include <process.h>
44#endif
45
46#if !defined (__WIN32__)
47#include <sys/utsname.h>
48#include <unistd.h>
49#endif
50
51
52bool littleEndian() {
53 char s[2] = {'\xFE', '\xEF'};
54
55 if (sizeof(unsigned short) == 2)
56 return *(unsigned short*)s == 0xEFFE;
57 else if (sizeof(unsigned int) == 2)
58 return *(unsigned int*)s == 0xEFFE;
59}
60
61text_t dm_safe (const text_t &instring) {
62
63 text_t outstring;
64 text_t::const_iterator here = instring.begin();
65 text_t::const_iterator end = instring.end();
66 while (here != end) {
67 if (*here == '_' || *here == '\\') outstring.push_back('\\');
68 outstring.push_back(*here);
69 ++here;
70 }
71 return outstring;
72}
73
74void dm_js_safe(const text_t &instring, text_t &outstring)
75{
76 text_t::const_iterator here = instring.begin();
77 text_t::const_iterator end = instring.end();
78 while (here != end) {
79 if (*here == '_') outstring.push_back('\\');
80 else if (*here == '\\' || *here == '\'') {
81 outstring.push_back('\\');
82 outstring.push_back('\\');
83 }
84 outstring.push_back(*here);
85 ++here;
86 }
87}
88
89text_t xml_safe(const text_t &text_string)
90{
91 text_t text_string_safe;
92 text_t::const_iterator here = text_string.begin();
93 text_t::const_iterator end = text_string.end();
94 while (here != end) {
95 if (*here == '&') text_string_safe += "&amp;";
96 else if (*here == '<') text_string_safe += "&lt;";
97 else if (*here == '>') text_string_safe += "&gt;";
98 else text_string_safe.push_back(*here);
99 ++here;
100 }
101 return text_string_safe;
102}
103
104
105// gsdl_system creates a new process for the cmd command (which
106// may contain arguments).
107// cmd should contain the full path of the program to run.
108// The child process inherits the environment of the calling
109// process.
110// If sync is true a synchronous call will be made, otherwise
111// an asyncronous call.
112// If sync is true the return value will be the exit code of
113// the child process or -1 if the child process wasn't started.
114// If sync is false the return value will be 0 if the process
115// was started ok or -1 if it failed.
116int gsdl_system (const text_t &cmd, bool sync, ostream &logout) {
117 if (cmd.empty()) return -1;
118 char *cmd_c = cmd.getcstr();
119
120#if defined (__WIN32__)
121 // the windows version - this is implemented this way
122 // to prevent windows popping up all over the place when
123 // we call a console application (like perl)
124 STARTUPINFO ps = {sizeof(STARTUPINFO), NULL, NULL, NULL,
125 0, 0, 0, 0, 0, 0,
126 0, STARTF_USESHOWWINDOW,
127 SW_HIDE, 0, NULL,
128 NULL, NULL, NULL};
129 PROCESS_INFORMATION pi;
130 BOOL res = CreateProcess(NULL,
131 cmd_c,
132 NULL,
133 NULL,
134 FALSE,
135#if defined (GSDL_LOCAL_LIBRARY)
136 NULL,
137#else
138 CREATE_NO_WINDOW, // previously this was: DETACHED_PROCESS,
139 // see http://msdn.microsoft.com/en-us/library/ms682425.aspx
140 // and http://msdn.microsoft.com/en-us/library/ms684863(VS.85).aspx
141#endif
142 NULL,
143 NULL,
144 &ps,
145 &pi);
146
147 if (!res) {
148 logout << "gsdl_system failed to start " << cmd_c
149 << " process, error code " << GetLastError() << endl;
150 delete []cmd_c;
151 return -1;
152 }
153
154 DWORD ret = 0;
155 if (sync) { // synchronous system call
156 // wait until child process exits.
157 WaitForSingleObject(pi.hProcess, INFINITE);
158 // set ret to exit code of child process
159 GetExitCodeProcess(pi.hProcess, &ret);
160 }
161
162 CloseHandle(pi.hProcess);
163 CloseHandle(pi.hThread);
164
165#else
166 // the unix version
167 int ret = 0;
168 if (sync) { // synchronous system call
169 // make sure the command interpreter is found
170 if (system (NULL) == 0) {
171 logout << "gsdl_system failed to start " << cmd_c
172 << " process, command interpreter not found" << endl;
173 delete []cmd_c;
174 return -1;
175 }
176 ret = system (cmd_c);
177
178 } else { // asynchronous system call
179 int pid = fork();
180 if (pid == -1) {
181 delete []cmd_c;
182 return -1;
183 }
184 if (pid == 0) {
185 // child process
186 char *argv[4];
187 argv[0] = "sh";
188 argv[1] = "-c";
189 argv[2] = cmd_c;
190 argv[3] = 0;
191 execv("/bin/sh", argv);
192 }
193 }
194#endif
195
196 delete []cmd_c;
197 return ret;
198}
199
200
201static bool gsdl_setenv_done = false;
202static char* retain_gsdlosc = NULL;
203static char* retain_gsdlhomec = NULL;
204static char* retain_pathc = NULL;
205
206bool set_gsdl_env_vars (const text_t& gsdlhome)
207{
208 if (gsdl_setenv_done) { return true; }
209
210 // set up GSDLOS, GSDLHOME and PATH environment variables
211
212 text_t gsdlos, path;
213 unsigned int path_separator = ':';
214
215#if defined (__WIN32__)
216 gsdlos = "windows";
217 path_separator = ';';
218
219 path = filename_cat (gsdlhome, "bin", "windows", "perl", "bin;");
220
221#else
222 struct utsname *buf = new struct utsname();
223 int i = uname (buf);
224 if (i == -1) gsdlos = "linux"; // uname failed, default to linux
225 else gsdlos.setcstr (buf->sysname);
226 delete buf;
227 lc (gsdlos);
228#endif
229
230 // according to getenv documentation (after a bit of digging), *getenv*
231 // is responsible for the char* pointer returned, so no need for us
232 // to free it (in fact that would be a mistake!)
233
234 char* orig_pathc = getenv ("PATH");
235 path += filename_cat (gsdlhome, "bin", gsdlos);
236 path.push_back (path_separator);
237 path += filename_cat (gsdlhome, "bin", "script");
238 if (orig_pathc != NULL) {
239 path.push_back (path_separator);
240 path += orig_pathc;
241 }
242
243 text_t putpath = "PATH=" + path;
244 text_t putgsdlos = "GSDLOS=" + gsdlos;
245 text_t putgsdlhome = "GSDLHOME=" + gsdlhome;
246
247 retain_gsdlosc = putgsdlos.getcstr();
248 retain_gsdlhomec = putgsdlhome.getcstr();
249 retain_pathc = putpath.getcstr();
250
251 if ((putenv(retain_gsdlosc)!=0) || (putenv(retain_gsdlhomec)!=0)
252 || (putenv(retain_pathc)!=0))
253 {
254 // Would be better if the ostream& logout was used here.
255 cerr << "Error setting Greenstone environment variables with putenv()" << endl;
256 // perror("putenv(...): "); // This didn't yield any noticable output under Windows running local library server
257 return false;
258 }
259
260 // Need to keep memory allocated setgsdlosc, setgsdlhomec or pathc around
261 // (i.e. can't delete them). This is because putenv() doesn't take
262 // a copy, but places them in the actual environment.
263
264 gsdl_setenv_done = true;
265
266 return true;
267}
268
269
270
271// attempts to work out if perl is functional
272bool perl_ok (ostream &logout) {
273#if defined(__WIN32__)
274 text_t cmd = "perl -e \"exit 0\"";
275#else
276 text_t cmd = "perl -e 'exit 0'";
277#endif
278 int i = gsdl_system (cmd, true, logout);
279 return (i == 0);
280}
281
282
283#if defined(_MSC_VER)
284// A very useful function to call to debug mysterious heap memory errors when
285// their cause isn't clear in the Vis Studio debugger. Call it from various
286// places of the code and narrow down the point at which the heap memory becomes
287// corrupted. The title param can be the method this function is called from.
288void check_system_heap(char* title)
289{
290 int heapstatus = _heapchk();
291
292 char message[1024];
293
294 switch (heapstatus) {
295 case _HEAPOK:
296 sprintf(message,"%s","OK - heap is fine");
297 break;
298 case _HEAPEMPTY:
299 sprintf(message,"%s","OK - heap is empty");
300 break;
301 case _HEAPBADBEGIN:
302 sprintf(message,"%s","ERROR - bad start of heap");
303 break;
304 case _HEAPBADNODE:
305 sprintf(message,"%s","Error - bad node in heap");
306 break;
307 default:
308 sprintf(message,"%s: %d","Unrecognized heap status",heapstatus);
309 }
310
311 cerr << message << endl;
312
313 // When debugging w32server, having the messages appear in a popup
314 // window can be more convenient
315 // If you put this line in, make just server.exe (LOCAL_LIBRARY=1)
316 //MessageBox (NULL, message, title, MB_OK);
317}
318
319#endif
Note: See TracBrowser for help on using the repository browser.