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

Last change on this file since 21461 was 21461, checked in by ak19, 14 years ago

Error messages are sent to stderr, since there are linking errors in generating oaiserver and library.cgi when the graphical Messagebox method is called. We can use the Messagebox for debugging the local library server (server.exe) instead.

  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
RevLine 
[1076]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"
[16895]27#include "fileutil.h"
[18880]28#include "stdlib.h"
[1076]29
[16949]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
[1678]41#if defined(__WIN32__)
42#include <windows.h>
43#include <process.h>
44#endif
45
[16895]46#if !defined (__WIN32__)
47#include <sys/utsname.h>
48#include <unistd.h>
49#endif
50
51
[1076]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
[1146]61text_t dm_safe (const text_t &instring) {
[1076]62
[1146]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);
[9593]69 ++here;
[1146]70 }
71 return outstring;
72}
73
[8727]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
[17545]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
[1817]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();
[1176]119
120#if defined (__WIN32__)
[1817]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)
[1176]124 STARTUPINFO ps = {sizeof(STARTUPINFO), NULL, NULL, NULL,
125 0, 0, 0, 0, 0, 0,
[1817]126 0, STARTF_USESHOWWINDOW,
127 SW_HIDE, 0, NULL,
[2298]128 NULL, NULL, NULL};
[1176]129 PROCESS_INFORMATION pi;
130 BOOL res = CreateProcess(NULL,
[1817]131 cmd_c,
[1176]132 NULL,
133 NULL,
134 FALSE,
[2298]135#if defined (GSDL_LOCAL_LIBRARY)
[1817]136 NULL,
[2298]137#else
[17698]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
[2298]141#endif
[1176]142 NULL,
143 NULL,
144 &ps,
145 &pi);
[17698]146
[1176]147 if (!res) {
[1817]148 logout << "gsdl_system failed to start " << cmd_c
[17698]149 << " process, error code " << GetLastError() << endl;
[8727]150 delete []cmd_c;
[1817]151 return -1;
[1176]152 }
153
[1817]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
[1176]162 CloseHandle(pi.hProcess);
163 CloseHandle(pi.hThread);
164
[1456]165#else
[1817]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
[17698]172 << " process, command interpreter not found" << endl;
[8727]173 delete []cmd_c;
[1817]174 return -1;
175 }
176 ret = system (cmd_c);
[1456]177
[1817]178 } else { // asynchronous system call
179 int pid = fork();
180 if (pid == -1) {
[8727]181 delete []cmd_c;
[1817]182 return -1;
183 }
184 if (pid == 0) {
185 // child process
186 char *argv[4];
187 argv[0] = "sh";
188 argv[1] = "-c";
[1818]189 argv[2] = cmd_c;
[1817]190 argv[3] = 0;
191 execv("/bin/sh", argv);
192 }
[1456]193 }
[1678]194#endif
[1456]195
[8727]196 delete []cmd_c;
[1817]197 return ret;
[1678]198}
[1783]199
[16895]200
201static bool gsdl_setenv_done = false;
[16909]202static char* retain_gsdlosc = NULL;
203static char* retain_gsdlhomec = NULL;
204static char* retain_pathc = NULL;
[16895]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
[16909]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();
[16949]249 retain_pathc = putpath.getcstr();
[16895]250
[16909]251 if ((putenv(retain_gsdlosc)!=0) || (putenv(retain_gsdlhomec)!=0)
252 || (putenv(retain_pathc)!=0))
[16895]253 {
[16949]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
[16895]257 return false;
258 }
259
[16909]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.
[16895]263
264 gsdl_setenv_done = true;
265
266 return true;
267}
268
269
270
[1783]271// attempts to work out if perl is functional
[1817]272bool perl_ok (ostream &logout) {
[1793]273#if defined(__WIN32__)
[1818]274 text_t cmd = "perl -e \"exit 0\"";
[1817]275#else
[1818]276 text_t cmd = "perl -e 'exit 0'";
[2937]277#endif
[1817]278 int i = gsdl_system (cmd, true, logout);
[1818]279 return (i == 0);
[1783]280}
[21454]281
282
283#if defined(__WIN32__)
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
[21461]311 cerr << message << endl;
312
313 // When debugging w32server having the messages appear in a popup
314 // window can be more convenient
315 //MessageBox (NULL, message, title, MB_OK);
[21454]316}
317
318#endif
Note: See TracBrowser for help on using the repository browser.