1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2016-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 may be provided by gnulib. We don't include gnulib
27 // headers directly in Octave's C++ source files to avoid problems that
28 // may be caused by the way that gnulib overrides standard library
29 // functions.
30
31 #if defined (HAVE_CONFIG_H)
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36
37 #include <sys/types.h>
38 #include <unistd.h>
39
40 #if defined (__WIN32__) && ! defined (__CYGWIN__)
41 # include <process.h>
42 #endif
43
44 #if defined (OCTAVE_USE_WINDOWS_API)
45 # include <windows.h>
46 # include <wchar.h>
47 #endif
48
49 #include "uniconv-wrappers.h"
50 #include "unistd-wrappers.h"
51
52 int
octave_access_f_ok(void)53 octave_access_f_ok (void)
54 {
55 return F_OK;
56 }
57
58 int
octave_access_r_ok(void)59 octave_access_r_ok (void)
60 {
61 return R_OK;
62 }
63
64 int
octave_access_w_ok(void)65 octave_access_w_ok (void)
66 {
67 return W_OK;
68 }
69
70 int
octave_access_x_ok(void)71 octave_access_x_ok (void)
72 {
73 return X_OK;
74 }
75
76 int
octave_access_wrapper(const char * nm,int mode)77 octave_access_wrapper (const char *nm, int mode)
78 {
79 return access (nm, mode);
80 }
81
82 int
octave_chdir_wrapper(const char * nm)83 octave_chdir_wrapper (const char *nm)
84 {
85 #if defined (OCTAVE_USE_WINDOWS_API)
86 wchar_t *wnm = u8_to_wchar (nm);
87 int status = _wchdir (wnm);
88 free ((void *) wnm);
89 return status;
90 #else
91 return chdir (nm);
92 #endif
93 }
94
95 int
octave_close_wrapper(int fd)96 octave_close_wrapper (int fd)
97 {
98 return close (fd);
99 }
100
101 const char *
octave_ctermid_wrapper(void)102 octave_ctermid_wrapper (void)
103 {
104 #if defined (HAVE_CTERMID)
105 return ctermid (0);
106 #else
107 return "/dev/tty";
108 #endif
109 }
110
111 int
octave_dup2_wrapper(int fd1,int fd2)112 octave_dup2_wrapper (int fd1, int fd2)
113 {
114 return dup2 (fd1, fd2);
115 }
116
117 #if defined (__WIN32__) && ! defined (__CYGWIN__)
118
119 // Adapted from libtool wrapper.
120
121 /* Prepares an argument vector before calling spawn().
122
123 Note that spawn() does not by itself call the command interpreter
124 (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
125 ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
126 GetVersionEx(&v);
127 v.dwPlatformId == VER_PLATFORM_WIN32_NT;
128 }) ? "cmd.exe" : "command.com").
129
130 Instead it simply concatenates the arguments, separated by ' ', and calls
131 CreateProcess(). We must quote the arguments since Win32 CreateProcess()
132 interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
133 special way:
134
135 - Space and tab are interpreted as delimiters. They are not treated as
136 delimiters if they are surrounded by double quotes: "...".
137
138 - Unescaped double quotes are removed from the input. Their only effect is
139 that within double quotes, space and tab are treated like normal
140 characters.
141
142 - Backslashes not followed by double quotes are not special.
143
144 - But 2*n+1 backslashes followed by a double quote become
145 n backslashes followed by a double quote (n >= 0):
146 \" -> "
147 \\\" -> \"
148 \\\\\" -> \\"
149 */
150
151 #define SHELL_SPECIAL_CHARS \
152 "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
153
154 #define SHELL_SPACE_CHARS \
155 " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
156
157 static char **
prepare_spawn(char * const * argv)158 prepare_spawn (char *const *argv)
159 {
160 size_t argc;
161 char **new_argv;
162 size_t i;
163
164 /* Count number of arguments. */
165 for (argc = 0; argv[argc] != NULL; argc++)
166 ;
167
168 /* Allocate new argument vector. */
169 new_argv = (char **) malloc ((argc + 1) * sizeof (char *));
170
171 /* Put quoted arguments into the new argument vector. */
172 for (i = 0; i < argc; i++)
173 {
174 const char *string = argv[i];
175
176 if (string[0] == '\0')
177 new_argv[i] = strdup ("\"\"");
178 else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
179 {
180 int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
181 size_t length;
182 unsigned int backslashes;
183 const char *s;
184 char *quoted_string;
185 char *p;
186
187 length = 0;
188 backslashes = 0;
189 if (quote_around)
190 length++;
191 for (s = string; *s != '\0'; s++)
192 {
193 char c = *s;
194 if (c == '"')
195 length += backslashes + 1;
196 length++;
197 if (c == '\\')
198 backslashes++;
199 else
200 backslashes = 0;
201 }
202 if (quote_around)
203 length += backslashes + 1;
204
205 quoted_string = (char *) malloc (length + 1);
206
207 p = quoted_string;
208 backslashes = 0;
209 if (quote_around)
210 *p++ = '"';
211 for (s = string; *s != '\0'; s++)
212 {
213 char c = *s;
214 if (c == '"')
215 {
216 unsigned int j;
217 for (j = backslashes + 1; j > 0; j--)
218 *p++ = '\\';
219 }
220 *p++ = c;
221 if (c == '\\')
222 backslashes++;
223 else
224 backslashes = 0;
225 }
226 if (quote_around)
227 {
228 unsigned int j;
229 for (j = backslashes; j > 0; j--)
230 *p++ = '\\';
231 *p++ = '"';
232 }
233 *p = '\0';
234
235 new_argv[i] = quoted_string;
236 }
237 else
238 new_argv[i] = strdup (string);
239 }
240
241 new_argv[argc] = NULL;
242
243 return new_argv;
244 }
245
246 #endif
247
248 int
octave_execv_wrapper(const char * file,char * const * argv)249 octave_execv_wrapper (const char *file, char *const *argv)
250 {
251 #if defined (__WIN32__) && ! defined (__CYGWIN__)
252
253 char **sanitized_argv = prepare_spawn (argv);
254
255 int status = spawnv (P_OVERLAY, file, sanitized_argv);
256
257 // This only happens if spawnv fails.
258
259 char **p = sanitized_argv;
260 while (*p)
261 free (*p++);
262 free (sanitized_argv);
263
264 return status;
265
266 #else
267
268 return execv (file, argv);
269
270 #endif
271 }
272
273 int
octave_execvp_wrapper(const char * file,char * const * argv)274 octave_execvp_wrapper (const char *file, char *const *argv)
275 {
276 return execvp (file, argv);
277 }
278
279 pid_t
octave_fork_wrapper(void)280 octave_fork_wrapper (void)
281 {
282 #if defined (HAVE_FORK)
283 return fork ();
284 #else
285 return -1;
286 #endif
287 }
288
289 int
octave_ftruncate_wrapper(int fd,off_t sz)290 octave_ftruncate_wrapper (int fd, off_t sz)
291 {
292 return ftruncate (fd, sz);
293 }
294
295 char *
octave_getcwd_wrapper(char * nm,size_t len)296 octave_getcwd_wrapper (char *nm, size_t len)
297 {
298 #if defined (OCTAVE_USE_WINDOWS_API)
299 wchar_t *tmp = _wgetcwd (NULL, 0);
300 char *retval = NULL;
301
302 if (! tmp)
303 return retval;
304
305 retval = u8_from_wchar (tmp);
306 if (! nm)
307 return retval;
308 else
309 {
310 if (strlen (retval) > len)
311 return NULL;
312
313 memcpy (nm, retval, len);
314 free (retval);
315 return nm;
316 }
317 #else
318 return getcwd (nm, len);
319 #endif
320 }
321
322 gid_t
octave_getegid_wrapper(void)323 octave_getegid_wrapper (void)
324 {
325 #if defined (HAVE_GETEGID)
326 return getegid ();
327 #else
328 return -1;
329 #endif
330 }
331
332 uid_t
octave_geteuid_wrapper(void)333 octave_geteuid_wrapper (void)
334 {
335 #if defined (HAVE_GETEUID)
336 return geteuid ();
337 #else
338 return -1;
339 #endif
340 }
341
342 gid_t
octave_getgid_wrapper(void)343 octave_getgid_wrapper (void)
344 {
345 #if defined (HAVE_GETGID)
346 return getgid ();
347 #else
348 return -1;
349 #endif
350 }
351
352 int
octave_gethostname_wrapper(char * nm,size_t len)353 octave_gethostname_wrapper (char *nm, size_t len)
354 {
355 return gethostname (nm, len);
356 }
357
358 pid_t
octave_getpgrp_wrapper(void)359 octave_getpgrp_wrapper (void)
360 {
361 #if defined (HAVE_GETPGRP)
362 return getpgrp ();
363 #else
364 return -1;
365 #endif
366 }
367
368 pid_t
octave_getpid_wrapper(void)369 octave_getpid_wrapper (void)
370 {
371 #if defined (HAVE_GETPID)
372 return getpid ();
373 #else
374 return -1;
375 #endif
376 }
377
378 pid_t
octave_getppid_wrapper(void)379 octave_getppid_wrapper (void)
380 {
381 #if defined (HAVE_GETPPID)
382 return getppid ();
383 #else
384 return -1;
385 #endif
386 }
387
388 uid_t
octave_getuid_wrapper(void)389 octave_getuid_wrapper (void)
390 {
391 #if defined (HAVE_GETUID)
392 return getuid ();
393 #else
394 return -1;
395 #endif
396 }
397
398 int
octave_isatty_wrapper(int fd)399 octave_isatty_wrapper (int fd)
400 {
401 return isatty (fd);
402 }
403
404 int
octave_link_wrapper(const char * nm1,const char * nm2)405 octave_link_wrapper (const char *nm1, const char *nm2)
406 {
407 return link (nm1, nm2);
408 }
409
410 int
octave_pipe_wrapper(int * fd)411 octave_pipe_wrapper (int *fd)
412 {
413 return pipe (fd);
414 }
415
416 int
octave_rmdir_wrapper(const char * nm)417 octave_rmdir_wrapper (const char *nm)
418 {
419 #if defined (OCTAVE_USE_WINDOWS_API)
420 wchar_t *wnm = u8_to_wchar (nm);
421 int status = _wrmdir (wnm);
422 free ((void *) wnm);
423 return status;
424 #else
425 return rmdir (nm);
426 #endif
427 }
428
429 pid_t
octave_setsid_wrapper(void)430 octave_setsid_wrapper (void)
431 {
432 #if defined (HAVE_SETSID)
433 return setsid ();
434 #else
435 return -1;
436 #endif
437 }
438
439 int
octave_stdin_fileno(void)440 octave_stdin_fileno (void)
441 {
442 return STDIN_FILENO;
443 }
444
445 int
octave_stdout_fileno(void)446 octave_stdout_fileno (void)
447 {
448 return STDOUT_FILENO;
449 }
450
451 int
octave_symlink_wrapper(const char * nm1,const char * nm2)452 octave_symlink_wrapper (const char *nm1, const char *nm2)
453 {
454 return symlink (nm1, nm2);
455 }
456
457 int
octave_unlink_wrapper(const char * nm)458 octave_unlink_wrapper (const char *nm)
459 {
460 #if defined (OCTAVE_USE_WINDOWS_API)
461 wchar_t *wnm = u8_to_wchar (nm);
462 int status = _wunlink (wnm);
463 free ((void *) wnm);
464 return status;
465 #else
466 return unlink (nm);
467 #endif
468 }
469
470 pid_t
octave_vfork_wrapper(void)471 octave_vfork_wrapper (void)
472 {
473 #if defined (HAVE_VFORK)
474 return vfork ();
475 #else
476 return -1;
477 #endif
478 }
479
480 bool
octave_have_fork(void)481 octave_have_fork (void)
482 {
483 #if defined (HAVE_FORK)
484 return true;
485 #else
486 return false;
487 #endif
488 }
489
490 bool
octave_have_vfork(void)491 octave_have_vfork (void)
492 {
493 #if defined (HAVE_VFORK)
494 return true;
495 #else
496 return false;
497 #endif
498 }
499