YAP 7.1.0
sys.c
1/*************************************************************************
2 * *
3 * YAP Prolog *
4 * *
5 * Yap Prolog was developed at NCCUP - Universidade do Porto *
6 * *
7 * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8 * *
9 **************************************************************************
10 * *
11 *
12 * comments: regular expression interpreter *
13 * *
14 *************************************************************************/
15
16#include "YapInterface.h"
17
18#include <stdlib.h>
19
20#if __ANDROID__
21#include <android/asset_manager.h>
22#include <android/asset_manager_jni.h>
23#include <android/log.h>
24#include <jni.h>
25#endif
26#include "YapStreams.h"
27
28#include "VFS.h"
29
30#include "crypto/md5.h"
31#if HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34#include <stdio.h>
35#if HAVE_TIME_H
36#include <time.h>
37#endif
38#if HAVE_SYS_TYPES_H
39#include <sys/types.h>
40#endif
41#if HAVE_SYS_STAT_H
42#include <sys/stat.h>
43#endif
44#if HAVE_FCNTL_H
45#include <fcntl.h>
46#endif
47#if HAVE_MATH_H
48#include <math.h>
49#endif
50#if HAVE_UNISTD_H
51#include <unistd.h>
52#endif
53#if HAVE_ERRNO_H
54#include <errno.h>
55#endif
56#if HAVE_STRING_H
57#include <string.h>
58#endif
59#if HAVE_SIGNAL_H
60#include <signal.h>
61#endif
62#if HAVE_SYS_WAIT_H
63#include <sys/wait.h>
64#endif
65#if HAVE_DIRENT_H
66#include <dirent.h>
67#endif
68#if HAVE_DIRECT_H
69#include <direct.h>
70#endif
71#if defined(__MINGW32__) || _MSC_VER
72#include <io.h>
73#include <process.h>
74#include <windows.h>
75#endif
76#ifdef __MINGW32__
77#ifdef HAVE_ENVIRON
78#undef HAVE_ENVIRON
79#endif
80#endif
81#if __ANDROID__
82#include <android/asset_manager.h>
83#include <android/asset_manager_jni.h>
84#include <android/log.h>
85#endif
86
87X_API void init_sys(void);
88
89#if defined(__MINGW32__) || _MSC_VER
90static YAP_Term WinError(void) {
91 char msg[256];
92 /* Error, we could not read time */
93 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
94 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
95 msg, 256, NULL);
96 return (YAP_MkAtomTerm(YAP_LookupAtom(msg)));
97}
98#endif
99
100/* Return time in a structure */
101static YAP_Bool sysmktime(void) {
102
103#if defined(__MINGW32__) || _MSC_VER
104 SYSTEMTIME stime, stime0;
105 FILETIME ftime, ftime0;
106
107 stime.wYear = YAP_IntOfTerm(YAP_ARG1);
108 stime.wMonth = YAP_IntOfTerm(YAP_ARG2);
109 stime.wDay = YAP_IntOfTerm(YAP_ARG3);
110 stime.wHour = YAP_IntOfTerm(YAP_ARG4);
111 stime.wMinute = YAP_IntOfTerm(YAP_ARG5);
112 stime.wSecond = YAP_IntOfTerm(YAP_ARG6);
113 stime.wMilliseconds = 0;
114 stime0.wYear = 1970;
115 stime0.wMonth = 1;
116 stime0.wDay = 1;
117 stime0.wHour = 12;
118 stime0.wMinute = 0;
119 stime0.wSecond = 0;
120 stime0.wMilliseconds = 0;
121 if (!SystemTimeToFileTime(&stime, &ftime)) {
122 return YAP_Unify(YAP_ARG8, YAP_MkIntTerm(errno));
123 }
124 if (!SystemTimeToFileTime(&stime0, &ftime0)) {
125 return YAP_Unify(YAP_ARG8, YAP_MkIntTerm(errno));
126 }
127#if __GNUC__
128 {
129 unsigned long long f1 = (((unsigned long long)ftime.dwHighDateTime) << 32) +
130 (unsigned long long)ftime.dwLowDateTime;
131 unsigned long long f0 =
132 (((unsigned long long)ftime0.dwHighDateTime) << 32) +
133 (unsigned long long)ftime0.dwLowDateTime;
134 return YAP_Unify(YAP_ARG7, YAP_MkIntTerm((long int)((f1 - f0) / 10000000)));
135 }
136#else
137 return FALSE;
138#endif
139#else
140#ifdef HAVE_MKTIME
141 struct tm loc;
142 time_t tim;
143
144 loc.tm_year = YAP_IntOfTerm(YAP_ARG1) - 1900;
145 loc.tm_mon = YAP_IntOfTerm(YAP_ARG2) - 1;
146 loc.tm_mday = YAP_IntOfTerm(YAP_ARG3);
147 loc.tm_hour = YAP_IntOfTerm(YAP_ARG4);
148 loc.tm_min = YAP_IntOfTerm(YAP_ARG5);
149 loc.tm_sec = YAP_IntOfTerm(YAP_ARG6);
150 loc.tm_isdst = -1;
151
152 if ((tim = mktime(&loc)) == (time_t)-1) {
153 return YAP_Unify(YAP_ARG8, YAP_MkIntTerm(errno));
154 }
155 return YAP_Unify(YAP_ARG7, YAP_MkIntTerm(tim));
156#else
157 oops
158#endif /* HAVE_MKTIME */
159#endif /* WINDOWS */
160}
161
162/* Return time in a structure */
163static YAP_Bool datime(void) {
164 YAP_Term tf, out[6];
165#if defined(__MINGW32__) || _MSC_VER
166 SYSTEMTIME stime;
167 GetLocalTime(&stime);
168 out[0] = YAP_MkIntTerm(stime.wYear);
169 out[1] = YAP_MkIntTerm(stime.wMonth);
170 out[2] = YAP_MkIntTerm(stime.wDay);
171 out[3] = YAP_MkIntTerm(stime.wHour);
172 out[4] = YAP_MkIntTerm(stime.wMinute);
173 out[5] = YAP_MkIntTerm(stime.wSecond);
174#elif HAVE_TIME
175 time_t tp;
176
177 if ((tp = time(NULL)) == -1) {
178 return (YAP_Unify(YAP_ARG2, YAP_MkIntTerm(errno)));
179 }
180#ifdef HAVE_LOCALTIME
181 {
182 struct tm *loc = localtime(&tp);
183 if (loc == NULL) {
184 return (YAP_Unify(YAP_ARG2, YAP_MkIntTerm(errno)));
185 }
186 out[0] = YAP_MkIntTerm(1900 + loc->tm_year);
187 out[1] = YAP_MkIntTerm(1 + loc->tm_mon);
188 out[2] = YAP_MkIntTerm(loc->tm_mday);
189 out[3] = YAP_MkIntTerm(loc->tm_hour);
190 out[4] = YAP_MkIntTerm(loc->tm_min);
191 out[5] = YAP_MkIntTerm(loc->tm_sec);
192 }
193#else
194 oops
195#endif /* HAVE_LOCALTIME */
196#else
197 oops
198#endif /* HAVE_TIME */
199 tf = YAP_MkApplTerm(YAP_MkFunctor(YAP_LookupAtom("datime"), 6), 6, out);
200 return YAP_Unify(YAP_ARG1, tf);
201}
202
203#define BUF_SIZE 1024
204
205
206static YAP_Bool p_unlink(void) {
207 char *fd = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
208#if defined(__MINGW32__) || _MSC_VER
209 if (_unlink(fd) == -1)
210#else
211 if (unlink(fd) == -1)
212#endif
213 {
214 /* return an error number */
215 return (YAP_Unify(YAP_ARG2, YAP_MkIntTerm(errno)));
216 }
217 return (TRUE);
218}
219
220static YAP_Bool p_rmdir(void) {
221 char *fd = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
222#if defined(__MINGW32__) || _MSC_VER
223 if (_rmdir(fd) == -1) {
224#else
225 if (rmdir(fd) == -1) {
226#endif
227 /* return an error number */
228 return (YAP_Unify(YAP_ARG2, YAP_MkIntTerm(errno)));
229 }
230 return (TRUE);
231}
232
233static YAP_Bool rename_file(void) {
234 char *s1 = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
235 char *s2 = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG2));
236#if HAVE_RENAME
237 if (rename(s1, s2) == -1) {
238 /* return an error number */
239 return (YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno)));
240 }
241#endif
242 return (TRUE);
243}
244
245static YAP_Bool read_link(void) {
246#if HAVE_READLINK
247 char *s1 = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
248 char buf[MAXPATHLEN + 1];
249
250 if (readlink(s1, buf, MAXPATHLEN) < 0)
251 return false;
252
253 /* return an error number */
254 if (!YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom(buf)))) {
255 return false;
256 }
257#endif
258#if _WIN32
259 return false;
260#endif
261 return true;
262}
263
264static YAP_Bool dir_separator(void) {
265 return (YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom("/"))));
266}
267
268static YAP_Bool file_property(void) {
269 const char *fd;
270#if HAVE_LSTAT
271 struct stat buf;
272
273 fd = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
274 if (lstat(fd, &buf) == -1) {
275 /* return an error number */
276 return (YAP_Unify(YAP_ARG7, YAP_MkIntTerm(errno)));
277 }
278 if (S_ISREG(buf.st_mode)) {
279 if (!(YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("regular"))) &&
280 YAP_Unify(YAP_ARG6, YAP_MkIntTerm(0))))
281 return (FALSE);
282 } else if (S_ISDIR(buf.st_mode)) {
283 if (!(YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("directory"))) &&
284 YAP_Unify(YAP_ARG6, YAP_MkIntTerm(0))))
285 return (FALSE);
286 } else if (S_ISFIFO(buf.st_mode)) {
287 if (!(YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("fifo"))) &&
288 YAP_Unify(YAP_ARG6, YAP_MkIntTerm(0))))
289 return (FALSE);
290 } else if (S_ISLNK(buf.st_mode)) {
291 if (!YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("symlink"))))
292 return (FALSE);
293#if HAVE_READLINK
294 {
295 char tmp[256];
296 int n;
297 if ((n = readlink(fd, tmp, 256)) == -1) {
298 return (YAP_Unify(YAP_ARG7, YAP_MkIntTerm(errno)));
299 }
300 tmp[n] = '\0';
301 if (!YAP_Unify(YAP_ARG6, YAP_MkAtomTerm(YAP_LookupAtom(tmp)))) {
302 return (FALSE);
303 }
304 }
305#else
306 if (!YAP_Unify(YAP_ARG6, YAP_MkIntTerm(0)))
307 return (FALSE);
308#endif
309 } else if (S_ISSOCK(buf.st_mode)) {
310 if (!(YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("socket"))) &&
311 YAP_Unify(YAP_ARG6, YAP_MkIntTerm(0))))
312 return (FALSE);
313 } else {
314 if (!(YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("unknown"))) &&
315 YAP_Unify(YAP_ARG6, YAP_MkIntTerm(0))))
316 return (FALSE);
317 }
318#elif defined(__MINGW32__) || _MSC_VER
319 /* for some weird reason _stat did not work with mingw32 */
320 struct _stat buf;
321
322 fd = YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
323 if (_stat(fd, &buf) != 0) {
324 /* return an error number */
325 return (YAP_Unify(YAP_ARG7, YAP_MkIntTerm(errno)));
326 }
327 if (buf.st_mode & S_IFREG) {
328 if (!YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("regular"))))
329 return (FALSE);
330 } else if (buf.st_mode & S_IFDIR) {
331 if (!YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("directory"))))
332 return (FALSE);
333 } else {
334 if (!YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom("unknown"))))
335 return (FALSE);
336 }
337#endif
338 return (YAP_Unify(YAP_ARG3, YAP_MkIntTerm(buf.st_size)) &&
339 YAP_Unify(YAP_ARG4, YAP_MkIntTerm(buf.st_mtime)) &&
340 YAP_Unify(YAP_ARG5, YAP_MkIntTerm(buf.st_mode)));
341}
342
343/* temporary files */
344
345static YAP_Bool p_mktemp(void) {
346#if HAVE_MKSTEMP || HAVE_MKTEMP || defined(__MINGW32__) || _MSC_VER
347 char *s, tmp[BUF_SIZE];
348 s = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
349#if HAVE_STRNCPY
350 strncpy(tmp, s, BUF_SIZE);
351#else
352 strcpy(tmp, s);
353#endif
354#if defined(__MINGW32__) || _MSC_VER
355 if ((s = _mktemp(tmp)) == NULL) {
356 /* return an error number */
357 return (YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno)));
358 }
359 return (YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom(s))));
360#elif HAVE_MKSTEMP
361 strcpy(tmp, "/tmp/YAP_tmpXXXXXXXX");
362 if (mkstemp(tmp) == -1) {
363 /* return an error number */
364 return (YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno)));
365 }
366 return YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom(tmp)));
367#else
368 if ((s = mktemp(tmp)) == NULL) {
369 /* return an error number */
370 return (YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno)));
371 }
372 return YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom(s)));
373#endif
374#else
375 return FALSE;
376#endif
377 return (TRUE);
378}
379
380static YAP_Bool p_tmpnam(void) {
381#if HAVE_MKSTEMP
382 char s[21];
383 strcpy(s, "/tmp/YAP_tmpXXXXXXXX");
384 if (mkstemp(s) == -1)
385 return FALSE;
386 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(s)));
387#elif HAVE_MKTEMP
388 char *s;
389 if (!(s = mktemp("/tmp/YAP_tmpXXXXXXXX")))
390 return FALSE;
391 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(s)));
392#elif HAVE_TMPNAM
393 char buf[L_tmpnam], *s;
394 if (!(s = tmpnam(buf)))
395 return FALSE;
396 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(s)));
397#else
398 return FALSE;
399#endif
400}
401
402static YAP_Bool p_tmpdir(void) {
403#if defined(__MINGW32__) || _MSC_VER
404 char buf[512];
405 DWORD out = GetTempPath(512, buf);
406 if (!out) {
407 return (YAP_Unify(YAP_ARG2, WinError()));
408 }
409 if (out > 511) {
410 char *nbuf = malloc(out + 1);
411 if (!nbuf)
412 return YAP_Unify(YAP_ARG2,
413 YAP_MkAtomTerm(YAP_LookupAtom("no malloc memory")));
414 out = GetTempPath(512, nbuf);
415 if (!out) {
416 return YAP_Unify(YAP_ARG2, WinError());
417 }
418 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(nbuf)));
419 }
420 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(buf)));
421#else
422 char *s;
423 if ((s = getenv("TMPDIR")))
424 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(s)));
425#ifdef P_tmpdir
426 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(P_tmpdir)));
427#endif
428 return YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom("/tmp")));
429#endif
430}
431
432/* return YAP's environment */
433static YAP_Bool p_environ(void) {
434#if HAVE_ENVIRON && 0
435#if HAVE__NSGETENVIRON
436 char **ptr = _NSGetEnviron();
437#elif defined(__MINGW32__) || _MSC_VER
438 extern char **_environ;
439 char **ptr = _environ;
440#else
441 extern char **environ;
442 char **ptr = environ;
443#endif
444 YAP_Term t1 = YAP_ARG1;
445 long int i;
446
447 i = YAP_IntOfTerm(t1);
448 if (ptr[i] == NULL)
449 return (FALSE);
450 else {
451 YAP_Term t = YAP_BufferToString(ptr[i]);
452 return (YAP_Unify(t, YAP_ARG2));
453 }
454#else
455 YAP_Error(0, 0L, "environ not available in this configuration");
456 return (FALSE);
457#endif
458}
459
460#if defined(__MINGW32__) || _MSC_VER
461static HANDLE get_handle(YAP_Term ti, DWORD fd) {
462 if (YAP_IsAtomTerm(ti)) {
463 HANDLE out;
464 SECURITY_ATTRIBUTES satt;
465
466 satt.nLength = sizeof(satt);
467 satt.lpSecurityDescriptor = NULL;
468 satt.bInheritHandle = TRUE;
469 out = CreateFile("NUL", GENERIC_READ | GENERIC_WRITE,
470 FILE_SHARE_READ | FILE_SHARE_WRITE, &satt, OPEN_EXISTING,
471 0, NULL);
472 return (out);
473 } else {
474 if (YAP_IsIntTerm(ti)) {
475 return (GetStdHandle(fd));
476 } else
477 return ((HANDLE)_get_osfhandle(YAP_StreamToFileNo(ti)));
478 }
479}
480
481static void close_handle(YAP_Term ti, HANDLE h) {
482 if (YAP_IsAtomTerm(ti)) {
483 CloseHandle(h);
484 }
485}
486
487#endif
488
489/* execute a command as a detached process */
490static YAP_Bool execute_command(void) {
491 YAP_Term ti = YAP_ARG2, to = YAP_ARG3, te = YAP_ARG4;
492 int res;
493
494#if defined(__MINGW32__) || _MSC_VER
495 HANDLE inpf, outf, errf;
496 DWORD CreationFlags = 0;
497 STARTUPINFO StartupInfo;
498 PROCESS_INFORMATION ProcessInformation;
499 inpf = get_handle(ti, STD_INPUT_HANDLE);
500 if (inpf == INVALID_HANDLE_VALUE) {
501 return (YAP_Unify(YAP_ARG6, WinError()));
502 }
503 outf = get_handle(to, STD_OUTPUT_HANDLE);
504 if (outf == INVALID_HANDLE_VALUE) {
505 close_handle(ti, inpf);
506 return (YAP_Unify(YAP_ARG6, WinError()));
507 }
508 errf = get_handle(te, STD_OUTPUT_HANDLE);
509 if (errf == INVALID_HANDLE_VALUE) {
510 close_handle(ti, inpf);
511 close_handle(to, outf);
512 return (YAP_Unify(YAP_ARG6, WinError()));
513 }
514 if (!YAP_IsIntTerm(ti) && !YAP_IsIntTerm(to) && !YAP_IsIntTerm(te)) {
515 /* we do not keep a current stream */
516 CreationFlags = DETACHED_PROCESS;
517 }
518 StartupInfo.cb = sizeof(STARTUPINFO);
519 StartupInfo.lpReserved = NULL;
520 StartupInfo.lpDesktop = NULL; /* inherit */
521 StartupInfo.lpTitle = NULL; /* we do not create a new console window */
522 StartupInfo.dwFlags = STARTF_USESTDHANDLES;
523 StartupInfo.cbReserved2 = 0;
524 StartupInfo.lpReserved2 = NULL;
525 StartupInfo.hStdInput = inpf;
526 StartupInfo.hStdOutput = outf;
527 StartupInfo.hStdError = errf;
528 /* got stdin, stdout and error as I like it */
529 if (CreateProcess(NULL, (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1)), NULL,
530 NULL, TRUE, CreationFlags, NULL, NULL, &StartupInfo,
531 &ProcessInformation) == FALSE) {
532 close_handle(ti, inpf);
533 close_handle(to, outf);
534 close_handle(te, errf);
535 return (YAP_Unify(YAP_ARG6, WinError()));
536 }
537 close_handle(ti, inpf);
538 close_handle(to, outf);
539 close_handle(te, errf);
540 res = ProcessInformation.dwProcessId;
541 return (YAP_Unify(YAP_ARG5, YAP_MkIntTerm(res)));
542#else /* UNIX CODE */
543 YAP_Term AtomNull = YAP_MkAtomTerm(YAP_LookupAtom("null"));
544 int inpf, outf, errf;
545 /* process input first */
546 if (ti == AtomNull) {
547 inpf = open("/dev/null", O_RDONLY);
548 } else {
549 int sd;
550 if (YAP_IsIntTerm(ti))
551 sd = YAP_IntOfTerm(ti);
552 else
553 sd = YAP_StreamToFileNo(ti);
554 if (sd == 0)
555 inpf = 0;
556 else
557 inpf = dup(sd);
558 }
559 if (inpf < 0) {
560 /* return an error number */
561 return (YAP_Unify(YAP_ARG6, YAP_MkIntTerm(errno)));
562 }
563 /* then output stream */
564 if (to == AtomNull) {
565 outf = open("/dev/zero", O_WRONLY);
566 } else {
567 int sd;
568 if (YAP_IsIntTerm(to))
569 sd = YAP_IntOfTerm(to);
570 else
571 sd = YAP_StreamToFileNo(to);
572 if (sd == 1)
573 outf = 1;
574 else
575 outf = dup(sd);
576 }
577 if (outf < 0) {
578 /* return an error number */
579 if (inpf != 0)
580 close(inpf);
581 return (YAP_Unify(YAP_ARG6, YAP_MkIntTerm(errno)));
582 }
583 /* then error stream */
584 if (te == AtomNull) {
585 errf = open("/dev/zero", O_WRONLY);
586 } else {
587 int sd;
588 if (YAP_IsIntTerm(te))
589 sd = YAP_IntOfTerm(te);
590 else
591 sd = YAP_StreamToFileNo(te);
592 if (sd == 2)
593 errf = 2;
594 else
595 errf = dup(sd);
596 }
597 if (errf < 0) {
598 /* return an error number */
599 if (inpf != 0)
600 close(inpf);
601 if (outf != 1)
602 close(outf);
603 return (YAP_Unify(YAP_ARG6, YAP_MkIntTerm(errno)));
604 }
605 YAP_FlushAllStreams();
606 /* we are now ready to fork */
607 if ((res = fork()) < 0) {
608 /* close streams we don't need */
609 if (inpf != 0)
610 close(inpf);
611 if (outf != 1)
612 close(outf);
613 if (errf != 2)
614 close(errf);
615 /* return an error number */
616 return (YAP_Unify(YAP_ARG6, YAP_MkIntTerm(errno)));
617 } else if (res == 0) {
618 char *argv[4];
619
620 /* child */
621 /* close current streams, but not std streams */
622 YAP_CloseAllOpenStreams();
623 if (inpf != 0) {
624 close(0);
625 if (dup(inpf) != 0)
626 exit(1);
627 close(inpf);
628 }
629 if (outf != 1) {
630 close(1);
631 if (dup(outf) != 1)
632 exit(1);
633 close(outf);
634 }
635 if (errf != 2) {
636 close(2);
637 if (dup(errf) != 2)
638 exit(2);
639 close(errf);
640 }
641 argv[0] = "sh";
642 argv[1] = "-c";
643 argv[2] = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
644 argv[3] = NULL;
645 execv("/bin/sh", argv);
646 exit(127);
647 /* we have the streams where we want them, just want to execute now */
648 } else {
649 if (inpf != 0)
650 close(inpf);
651 if (outf != 1)
652 close(outf);
653 if (errf != 2)
654 close(errf);
655 return (YAP_Unify(YAP_ARG5, YAP_MkIntTerm(res)));
656 }
657#endif /* UNIX code */
658}
659
669static YAP_Bool do_system(void) {
670 char *command = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
671#if HAVE_SYSTEM
672 int sys = system(command);
673 if (sys < 0) {
674 return YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno));
675 }
676 return YAP_Unify(YAP_ARG2, YAP_MkIntTerm(sys));
677#else
678 YAP_Error(0, 0L, "system not available in this configuration, trying %s",
679 command);
680 return FALSE;
681#endif
682}
683
684/* execute a command as a detached process */
685static YAP_Bool do_shell(void) {
686#if defined(__MINGW32__) || _MSC_VER
687 YAP_Error(0, 0L, "system not available in this configuration");
688 return (FALSE);
689#elif HAVE_SYSTEM
690 char *buf = YAP_AllocSpaceFromYap(BUF_SIZE);
691 int sys;
692
693 if (buf == NULL) {
694 YAP_Error(0, 0L, "No Temporary Space for Shell");
695 return (FALSE);
696 }
697#if HAVE_STRNCPY
698 strncpy(buf, YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1)), BUF_SIZE);
699 strncpy(buf, " ", BUF_SIZE);
700 strncpy(buf, YAP_AtomName(YAP_AtomOfTerm(YAP_ARG2)), BUF_SIZE);
701 strncpy(buf, " ", BUF_SIZE);
702 strncpy(buf, YAP_AtomName(YAP_AtomOfTerm(YAP_ARG3)), BUF_SIZE);
703#else
704 strcpy(buf, YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1)));
705 strcpy(buf, YAP_AtomName(YAP_AtomOfTerm(YAP_ARG2)));
706 strcpy(buf, " ");
707 strcpy(buf, YAP_AtomName(YAP_AtomOfTerm(YAP_ARG3)));
708#endif
709 sys = system(buf);
710 YAP_FreeSpaceFromYap(buf);
711 if (sys < 0) {
712 return YAP_Unify(YAP_ARG5, YAP_MkIntTerm(errno));
713 }
714 return YAP_Unify(YAP_ARG4, YAP_MkIntTerm(sys));
715#else
716 char *cptr[4];
717 int t;
718 int sys;
719
720 cptr[0] = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG1));
721 cptr[1] = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG2));
722 cptr[2] = (char *)YAP_AtomName(YAP_AtomOfTerm(YAP_ARG3));
723 cptr[3] = NULL;
724 t = fork();
725 if (t < 0) {
726 return YAP_Unify(YAP_ARG5, YAP_MkIntTerm(errno));
727 } else if (t == 0) {
728 t = execvp(cptr[0], cptr);
729 return t;
730 } else {
731 t = wait(&sys);
732 if (t < 0) {
733 return YAP_Unify(YAP_ARG5, YAP_MkIntTerm(errno));
734 }
735 }
736 return YAP_Unify(YAP_ARG4, YAP_MkIntTerm(sys));
737#endif
738}
739
740/* execute a command as a detached process */
741static YAP_Bool plwait(void) {
742 long int pid = YAP_IntOfTerm(YAP_ARG1);
743#if defined(__MINGW32__) || _MSC_VER
744 HANDLE proc = OpenProcess(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE, FALSE, pid);
745 DWORD ExitCode;
746 if (proc == NULL) {
747 return (YAP_Unify(YAP_ARG3, WinError()));
748 }
749 if (WaitForSingleObject(proc, INFINITE) == WAIT_FAILED) {
750 return (YAP_Unify(YAP_ARG3, WinError()));
751 }
752 if (GetExitCodeProcess(proc, &ExitCode) == 0) {
753 return (YAP_Unify(YAP_ARG4, WinError()));
754 }
755 CloseHandle(proc);
756 return (YAP_Unify(YAP_ARG2, YAP_MkIntTerm(ExitCode)));
757#else
758 do {
759 int status;
760
761 /* check for interruptions */
762 if (waitpid(pid, &status, 0) == -1) {
763 if (errno) {
764 if (errno == EINTR) {
765 continue;
766 }
767 return YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno));
768 }
769 }
770 if (WIFEXITED(status)) {
771 return YAP_Unify(YAP_ARG2, YAP_MkIntTerm(WEXITSTATUS(status)));
772 } else if (WIFSIGNALED(status)) {
773 return YAP_Unify(YAP_ARG3, YAP_MkAtomTerm(YAP_LookupAtom("signalled"))) &&
774 YAP_Unify(YAP_ARG4, YAP_MkIntTerm(WTERMSIG(status)));
775 } else /* WIFSTOPPED(status) */ {
776 return YAP_Unify(YAP_ARG3, YAP_MkAtomTerm(YAP_LookupAtom("stopped"))) &&
777 YAP_Unify(YAP_ARG4, YAP_MkIntTerm(WSTOPSIG(status)));
778 }
779 } while (TRUE);
780#endif
781}
782
783/* host info */
784
785static YAP_Bool host_name(void) {
786#if defined(__MINGW32__) || _MSC_VER
787 char name[MAX_COMPUTERNAME_LENGTH + 1];
788 DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
789 if (GetComputerName(name, &nSize) == 0) {
790 return (YAP_Unify(YAP_ARG2, WinError()));
791 }
792#else
793#if HAVE_GETHOSTNAME
794 char name[256];
795 if (gethostname(name, 256) == -1) {
796 /* return an error number */
797 return (YAP_Unify(YAP_ARG2, YAP_MkIntTerm(errno)));
798 }
799#endif
800#endif /* defined(__MINGW32__) || _MSC_VER */
801 return (YAP_Unify(YAP_ARG1, YAP_MkAtomTerm(YAP_LookupAtom(name))));
802}
803
804static YAP_Bool host_id(void) {
805#if HAVE_GETHOSTID
806 return (YAP_Unify(YAP_ARG1, YAP_MkIntTerm(gethostid())));
807#else
808 return (YAP_Unify(YAP_ARG1, YAP_MkIntTerm(0)));
809#endif
810}
811
812static YAP_Bool pid(void) {
813#if defined(__MINGW32__) || _MSC_VER
814 return (YAP_Unify(YAP_ARG1, YAP_MkIntTerm(_getpid())));
815#else
816 return (YAP_Unify(YAP_ARG1, YAP_MkIntTerm(getpid())));
817#endif
818}
819
820static YAP_Bool win(void) {
821#if defined(__MINGW32__) || _MSC_VER
822 return (TRUE);
823#else
824 return (FALSE);
825#endif
826}
827
828static YAP_Bool p_kill(void) {
829#if defined(__MINGW32__) || _MSC_VER
830 /* Windows does not support cross-process signals, so we shall do the
831 SICStus thing and assume that a signal to a process will
832 always kill it */
833 HANDLE proc = OpenProcess(STANDARD_RIGHTS_REQUIRED | PROCESS_TERMINATE, FALSE,
834 YAP_IntOfTerm(YAP_ARG1));
835 if (proc == NULL) {
836 return (YAP_Unify(YAP_ARG3, WinError()));
837 }
838 if (TerminateProcess(proc, -1) == 0) {
839 return (YAP_Unify(YAP_ARG3, WinError()));
840 }
841 CloseHandle(proc);
842#else
843 if (kill(YAP_IntOfTerm(YAP_ARG1), YAP_IntOfTerm(YAP_ARG2)) < 0) {
844 /* return an error number */
845 return (YAP_Unify(YAP_ARG3, YAP_MkIntTerm(errno)));
846 }
847#endif /* defined(__MINGW32__) || _MSC_VER */
848 return (TRUE);
849}
850
851#if HAVE_OPENSSL_RIPEMD_H
852#include <openssl/ripemd.h>
853#endif
854
864static YAP_Bool md5(void) {
865 unsigned char buf[64];
866 md5_state_t pms;
867 const char *s;
868 size_t len = -1;
869
870 if (!(s = YAP_StringToBuffer(YAP_ARG1, NULL, len)) || s[0] == 0)
871 return false;
872
873 md5_init(&pms);
874 md5_append(&pms, (const unsigned char *)s, strlen(s));
875 md5_finish(&pms, buf);
876 // free((void *)s);
877 YAP_Term t = YAP_ARG3;
878 int i = 16;
879 while (i > 0) {
880 int top, bop;
881 i--;
882 top = buf[i] >> 4;
883 if (top > 9)
884 top = (top - 10) + 'a';
885 else
886 top = top + '0';
887 bop = buf[i] & 15;
888 if (bop > 9)
889 bop = (bop - 10) + 'a';
890 else
891 bop = bop + '0';
892 t = YAP_MkPairTerm(YAP_MkIntTerm(top),
893 YAP_MkPairTerm(YAP_MkIntTerm(bop), t));
894 }
895 return YAP_Unify(YAP_ARG2, t);
896}
897
898static YAP_Bool error_message(void) {
899#if HAVE_STRERROR
900 return YAP_Unify(YAP_ARG2, YAP_MkAtomTerm(YAP_LookupAtom(
901 strerror(YAP_IntOfTerm(YAP_ARG1)))));
902#else
903 return YAP_Unify(YAP_ARG2, YAP_ARG1);
904#endif
905}
906X_API void init_sys(void) {
907#if HAVE_MKTIME
908 tzset();
909#endif
910 YAP_UserCPredicate("datime", datime, 2);
911 YAP_UserCPredicate("mktime", sysmktime, 8);
912 YAP_UserCPredicate("file_property", file_property, 7);
913 YAP_UserCPredicate("unlink", p_unlink, 2);
914 YAP_UserCPredicate("rmdir", p_rmdir, 2);
915 YAP_UserCPredicate("dir_separator", dir_separator, 1);
916 YAP_UserCPredicate("p_environ", p_environ, 2);
917 YAP_UserCPredicate("exec_command", execute_command, 6);
918 YAP_UserCPredicate("do_shell", do_shell, 5);
919 YAP_UserCPredicate("do_system", do_system, 3);
920 YAP_UserCPredicate("plwait", plwait, 4);
921 YAP_UserCPredicate("host_name", host_name, 2);
922 YAP_UserCPredicate("host_id", host_id, 2);
923 YAP_UserCPredicate("pid", pid, 2);
924 YAP_UserCPredicate("kill", p_kill, 3);
925 YAP_UserCPredicate("mktemp", p_mktemp, 3);
926 YAP_UserCPredicate("tmpnam", p_tmpnam, 2);
927 YAP_UserCPredicate("tmpdir", p_tmpdir, 2);
928 YAP_UserCPredicate("rename_file", rename_file, 3);
929 YAP_UserCPredicate("read_link", read_link, 2);
930 YAP_UserCPredicate("error_message", error_message, 2);
931 YAP_UserCPredicate("win", win, 0);
932 YAP_UserCPredicate("md5", md5, 3);
933}
934
935#ifdef _WIN32
936
937#include <windows.h>
938
939int WINAPI win_sys(HANDLE, DWORD, LPVOID);
940
941int WINAPI win_sys(HANDLE hinst, DWORD reason, LPVOID reserved) {
942 switch (reason) {
943 case DLL_PROCESS_ATTACH:
944 break;
945 case DLL_PROCESS_DETACH:
946 break;
947 case DLL_THREAD_ATTACH:
948 break;
949 case DLL_THREAD_DETACH:
950 break;
951 }
952 return 1;
953}
954#endif
@ argv
read-only atom, it describes the list with all arguments received by YAP at boot
Definition: YapGFlagInfo.h:89
X_API char * YAP_StringToBuffer(Term t, char *buf, unsigned int bufsize)
copy a string to a buffer, the buffer must have been malloced
Definition: c_interface.c:1362