Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

open-axiom repository from github

24005 views
1
/*
2
Copyright (C) 1991-2002, The Numerical Algorithms Group Ltd.
3
All rights reserved.
4
5
Copyright (C) 2007-2013, Gabriel Dos Reis.
6
All rights reserved.
7
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions are
10
met:
11
12
- Redistributions of source code must retain the above copyright
13
notice, this list of conditions and the following disclaimer.
14
15
- Redistributions in binary form must reproduce the above copyright
16
notice, this list of conditions and the following disclaimer in
17
the documentation and/or other materials provided with the
18
distribution.
19
20
- Neither the name of The Numerical Algorithms Group Ltd. nor the
21
names of its contributors may be used to endorse or promote products
22
derived from this software without specific prior written permission.
23
24
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
*/
36
37
#include "openaxiom-c-macros.h"
38
39
#include <errno.h>
40
#include <limits.h>
41
#include <sys/types.h>
42
#include <sys/stat.h>
43
#include <stdlib.h>
44
#include <string.h>
45
#include <stdio.h>
46
#include <assert.h>
47
#include <math.h>
48
#include <unistd.h>
49
50
51
#ifdef OPENAXIOM_MS_WINDOWS_HOST
52
# include <windows.h>
53
#else
54
# include <dirent.h>
55
# include <fcntl.h>
56
#endif
57
58
#include "cfuns.h"
59
60
/* Most versions of Windows don't have the POSIX functions getuid(),
61
geteuid(), getgid(), and getegid(). The following definitions are
62
approximations, to patch for the deficiencies of Windows
63
POSIX interface. */
64
65
#if !HAVE_DECL_GETUID
66
# define getuid() 0
67
#endif
68
69
#if !HAVE_DECL_GETGID
70
# define getgid() 0
71
#endif
72
73
#if !HAVE_DECL_GETEUID
74
# define geteuid() getuid()
75
#endif
76
77
#if !HAVE_DECL_GETEGID
78
# define getegid() getgid()
79
#endif
80
81
namespace OpenAxiom {
82
// Make a copy of string data on free store.
83
static char*
84
copy_c_str(const std::string& s) {
85
return strdup(s.c_str());
86
}
87
88
OPENAXIOM_C_EXPORT int
89
addtopath(char *dir)
90
{
91
char *path, *newpath;
92
93
path = oa_getenv("PATH");
94
if (path == NULL)
95
return -1;
96
97
newpath = (char *) malloc(1 + strlen(path) + strlen(dir) + strlen("PATH=:"));
98
if (newpath == NULL)
99
return -1;
100
101
sprintf(newpath, "PATH=%s:%s", path, dir);
102
103
return putenv(newpath);
104
}
105
106
107
108
/* Returns 1 if `c' designates a path separator, 0 otherwise. */
109
static inline int
110
openaxiom_is_path_separator(char c)
111
{
112
#ifdef OPENAXIOM_MS_WINDOWS_HOST
113
return c == '\\' || c == '/';
114
#else
115
return c == '/';
116
#endif
117
}
118
119
/*
120
Returns a the dirname of `path'. If `path' has no separator, then
121
returns ".". The returned value if malloc-allocated. */
122
123
OPENAXIOM_C_EXPORT char*
124
oa_dirname(const char* path)
125
{
126
const int n = strlen(path);
127
const char* mark = path + n;
128
129
if (n == 0)
130
return strdup(".");
131
else if (n == 1 && openaxiom_is_path_separator(*path))
132
return strdup("/");
133
134
/* For "/banana/space/", we want "/banana". */
135
if (openaxiom_is_path_separator(*--mark))
136
--mark;
137
while (path < mark && !openaxiom_is_path_separator(*mark))
138
--mark;
139
140
if (path == mark)
141
return strdup(openaxiom_is_path_separator(*path) ? "/" : ".");
142
else {
143
const int l = mark - path;
144
char* dir = (char*) malloc(l + 1);
145
memcpy(dir, path, l);
146
dir[l] = '\0';
147
return dir;
148
}
149
}
150
151
/*
152
* Test whether the path is the name of a directory. Returns 1 if so, 0 if
153
* not, -1 if it doesn't exist.
154
*/
155
156
157
OPENAXIOM_C_EXPORT int
158
directoryp(char *path)
159
{
160
struct stat buf;
161
int code = stat(path, &buf);
162
163
return code == -1 ? -1 : S_ISDIR(buf.st_mode);
164
}
165
166
OPENAXIOM_C_EXPORT int
167
make_path_from_file(char *s, char *t)
168
{
169
char *pos = NULL;
170
char *c;
171
172
/** simply copies the path name from t into s **/
173
for (c = t + strlen(t); c != s; c--)
174
if (*c == '/') {
175
pos = c;
176
break;
177
}
178
/** Check to see if the path was actually present **/
179
if (c == t) { /** No Path, so return the pwd **/
180
return (-1);
181
}
182
/** now just do the copying **/
183
strncpy(s, t, pos - t);
184
return 1;
185
}
186
187
/* The functions writeablep() and readablep() determine write and
188
read access of a file designated by its name. The function
189
axiom_has_write_access is a sub-routine of writeablep.
190
191
The access is determined based on the POSIX semantics; see
192
"Advanced Programming in the UNIX Environement", section 4.5.
193
194
1. If the effective user ID of the process is 0 (the superuser),
195
access is allowed. This gives the superuser free rein throughout
196
the entire file system.
197
198
2. If the effective user ID of the process equals the owner ID of
199
the file (i.e., the process owns the file), access is allowed
200
if the appropriate user access permission bit is set. [...]
201
202
3. If the effective group ID of the process or one of the
203
supplementary group IDs of the process equals the group ID
204
of the file, access is allowed if the appropriate
205
group access permission bit is set. Otherwise, permission
206
is denied.
207
208
4. If the appropriate other access permission bit is set, access is
209
allowed. Otherwise, permission is defined. */
210
211
212
/* Return 1 if the process has write access of file as explained above.
213
Otherwise, return 0. */
214
215
static inline int
216
axiom_has_write_access(const struct stat* file_info)
217
{
218
uid_t effetive_uid = geteuid();
219
220
if (effetive_uid == 0)
221
return 1;
222
223
if (effetive_uid == file_info->st_uid)
224
return (file_info->st_mode & S_IWUSR) ? 1 : 0;
225
226
#ifdef S_IWGRP
227
if (getegid() == file_info->st_gid)
228
return (file_info->st_mode & S_IWGRP) ? 1 : 0;
229
#endif
230
231
#ifdef S_IWOTH
232
return (file_info->st_mode & S_IWOTH) ? 1 : 0;
233
#else
234
return 0;
235
#endif
236
}
237
238
239
/* Return
240
-1 if the file designated by PATH is inexistent.
241
0 if the file exists but write access is denied.
242
1 if the file exists and process has write access.
243
2 if the file does not exists but process has write
244
has write access to the dirname of path. */
245
246
OPENAXIOM_C_EXPORT int
247
writeablep(const char *path)
248
{
249
struct stat buf;
250
int code;
251
252
code = stat(path, &buf);
253
if (code == -1) {
254
/* The file does not exist, so check to see if the directory
255
is writable. */
256
char* dir = oa_dirname(path);
257
code = stat(dir, &buf);
258
/* FIXME: Work around MinGW/MSYS bug.
259
The string pointed to by `dir' was strdup'd. According to
260
the C standard, that means the the string was allocated
261
by `malloc', therefore can be disposed of by `free'. However,
262
the MinGW/MSYS port appears to use MS' StrDup as the real
263
worker. Consequently, the guarantee that the the string can
264
free'd no longer holds. We have to use MS's LocalFree. */
265
#ifdef OPENAXIOM_MS_WINDOWS_HOST
266
LocalFree(dir);
267
#else
268
free(dir);
269
#endif
270
return (code == 0) && axiom_has_write_access(&buf) ? 2 : -1;
271
}
272
273
return axiom_has_write_access(&buf);
274
}
275
276
277
/* Return
278
-1 if the file designated by PATH is inexistent.
279
0 if the file exists but process has no read access.
280
1 if the file exists and read access is granted. */
281
282
OPENAXIOM_C_EXPORT int
283
readablep(const char *path)
284
{
285
struct stat buf;
286
int code;
287
288
code = stat(path, &buf);
289
if (code == -1)
290
return -1;
291
292
if (geteuid() == buf.st_uid)
293
return ((buf.st_mode & S_IREAD) != 0);
294
295
#ifdef S_IRGRP
296
if (getegid() == buf.st_gid)
297
return ((buf.st_mode & S_IRGRP) != 0);
298
#endif
299
300
#ifdef S_IROTH
301
return ((buf.st_mode & S_IROTH) != 0);
302
#else
303
return 0;
304
#endif
305
}
306
307
308
309
OPENAXIOM_C_EXPORT long
310
findString(char *file, char *string)
311
{
312
int nstring, charpos;
313
FILE *fn;
314
char buffer[1024];
315
316
if ((fn = fopen(file, "r")) == NULL)
317
return -1;
318
319
for (charpos = 0, nstring = strlen(string);
320
fgets(buffer, sizeof buffer, fn) != NULL;
321
charpos += strlen(buffer)
322
)
323
if (!strncmp(buffer, string, nstring))
324
return charpos;
325
return -1;
326
327
}
328
329
OPENAXIOM_C_EXPORT int
330
copyEnvValue(char *varName, char *buffer)
331
{
332
char *s;
333
334
s = oa_getenv(varName);
335
if (s == NULL)
336
return 0;
337
strcpy(buffer, s);
338
return strlen(s);
339
}
340
341
/* Return 1 if the file descriptor FD, as viewed by the Core Executable,
342
is attached to a terminal. */
343
OPENAXIOM_C_EXPORT int
344
std_stream_is_terminal(int fd)
345
{
346
assert(fd > -1 && fd < 3);
347
#ifdef OPENAXIOM_MS_WINDOWS_HOST
348
DWORD handle;
349
switch (fd) {
350
case 0: handle = STD_INPUT_HANDLE; break;
351
case 1: handle = STD_OUTPUT_HANDLE; break;
352
case 2: handle = STD_ERROR_HANDLE; break;
353
/* Next code is never executed but it makes the compiler happy. */
354
default: return 0;
355
}
356
/* The MS documentation suggests `GetFileType' for determining
357
the nature of the file handle. The return value, in our case,
358
is an over approximation of what we are interested in: Are we
359
dealing with a stream connected to a terminal? The constant
360
FILE_TYPE_CHAR characterises character files; in particular
361
a console terminal, or a printer. There is an undocumented
362
function `VerifyConsoleIoHandle' to deal precisely with the case
363
we are interested in. However, while availale in Wine, it is
364
not available in the MinGW headers. Consequently, we cannot
365
rely on it for the moment.
366
So, we may still get garbage out of this function on MS platforms. */
367
return GetFileType(GetStdHandle(handle)) == FILE_TYPE_CHAR;
368
#else
369
return isatty(fd);
370
#endif
371
}
372
373
/* Change the process' curretnt directory. Return zero on success,
374
and -1 on failure. */
375
OPENAXIOM_C_EXPORT int
376
oa_chdir(const char* path)
377
{
378
#ifdef OPENAXIOM_MS_WINDOWS_HOST
379
return SetCurrentDirectory(path) ? 0 : -1;
380
#else
381
return chdir(path);
382
#endif /* OPENAXIOM_MS_WINDOWS_HOST */
383
}
384
385
386
/* return true if path is `.' or `..'. */
387
static inline int
388
is_dot_or_dotdot(const char* path)
389
{
390
return strcmp(path, ".") == 0 || strcmp(path, "..") == 0;
391
}
392
393
/* Remove a directory entry. Files are removed, directories are
394
recursively walked and removed.
395
Return 0 on success, and -1 on falure.
396
In practice, OpenAxiom does not remove directories with
397
non-trivial recursive structues. */
398
OPENAXIOM_C_EXPORT int
399
oa_unlink(const char* path)
400
{
401
const char* curdir;
402
int status = -1;
403
#ifdef OPENAXIOM_MS_WINDOWS_HOST
404
WIN32_FIND_DATA findData;
405
HANDLE walkHandle;
406
407
if (is_dot_or_dotdot(path))
408
return -1;
409
410
walkHandle = FindFirstFile(path, &findData);
411
if (walkHandle == INVALID_HANDLE_VALUE)
412
return -1;
413
414
/* Remember where we are so we can return back properly. */
415
curdir = oa_getcwd();
416
417
do {
418
if (is_dot_or_dotdot(findData.cFileName))
419
continue;
420
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
421
if ((status = oa_chdir(findData.cFileName)) < 0)
422
goto sortie;
423
if ((status = oa_unlink("*")) < 0)
424
goto sortie;
425
if ((status = oa_chdir("..")) < 0)
426
goto sortie;
427
if(!RemoveDirectory(findData.cFileName)) {
428
status = -1;
429
goto sortie;
430
}
431
}
432
else if (!DeleteFile(findData.cFileName)) {
433
status = -1;
434
goto sortie;
435
}
436
status = 0;
437
} while (FindNextFile(walkHandle, &findData));
438
if (!FindClose(walkHandle)) {
439
status = -1;
440
goto sortie;
441
}
442
#else
443
struct stat pathstat;
444
DIR* dir;
445
struct dirent* entry;
446
447
/* Don't ever try to remove `.' or `..'. */
448
if (is_dot_or_dotdot(path))
449
return -1;
450
451
if (stat(path, &pathstat) < 0)
452
return -1;
453
454
/* handle non directories first. */
455
if (!S_ISDIR(pathstat.st_mode))
456
return unlink(path);
457
458
/* change into the path so that we don't have to form full
459
pathnames. */
460
curdir = oa_getcwd();
461
if ((dir = opendir(path)) == NULL || oa_chdir(path) < 0)
462
goto sortie;
463
464
while (errno = 0, (entry = readdir(dir)) != NULL) {
465
struct stat s;
466
if (is_dot_or_dotdot(entry->d_name))
467
continue;
468
if ((status = stat(entry->d_name, &s)) < 0)
469
goto sortie;
470
if (S_ISDIR(s.st_mode)) {
471
if ((status = oa_unlink(entry->d_name)) < 0)
472
goto sortie;
473
}
474
else if ((status = unlink(entry->d_name)) < 0)
475
goto sortie;
476
}
477
if (errno != 0) {
478
status = -1;
479
goto sortie;
480
}
481
482
/* Now, get one level up, and remove the empty directory. */
483
if (oa_chdir("..") < 0 || closedir(dir) < 0 || rmdir(path) < 0)
484
status = -1;
485
else
486
status = 0;
487
#endif /* OPENAXIOM_MS_WINDOWS_HOST */
488
489
sortie:
490
oa_chdir(curdir);
491
free((char*) curdir);
492
return status;
493
}
494
495
OPENAXIOM_C_EXPORT const char*
496
oa_acquire_temporary_pathname() {
497
#if OPENAXIOM_MS_WINDOWS_HOST
498
char buf[MAX_PATH];
499
const char* tmpdir = oa_get_tmpdir();
500
auto n = GetTempFileName(tmpdir, "oa-", random() % SHRT_MAX, buf);
501
/* tmpdir was malloc()ed when OPENAXIOM_MS_WINDOWS_HOST. */
502
free(const_cast<char*>(tmpdir));
503
if (n == 0) {
504
perror("oa_acquire_temporary_pathname");
505
exit(1);
506
}
507
return strdup(buf);
508
#elif HAVE_DECL_MKTEMP
509
return mktemp(copy_c_str(std::string{ oa_get_tmpdir() } + "/oa-XXXXXX"));
510
#elif HAVE_DECL_TEMPNAM
511
return tempnam(oa_get_tmpdir(), "oa-");
512
#else
513
return copy_c_str("oa-" + std::to_string(random()));
514
#endif
515
}
516
517
OPENAXIOM_C_EXPORT void
518
oa_release_temporary_pathname(const char* s)
519
{
520
free(const_cast<char*>(s)); // yuck!
521
}
522
523
/* Rename a file or directory. */
524
OPENAXIOM_C_EXPORT int
525
oa_rename(const char* old_path, const char* new_path)
526
{
527
#ifdef OPENAXIOM_MS_WINDOWS_HOST
528
return MoveFile(old_path, new_path) ? 0 : -1;
529
#else
530
return rename(old_path, new_path);
531
#endif
532
}
533
534
/* Create a new directory named `path'. Return 0 on success,
535
and -1 on failure. */
536
OPENAXIOM_C_EXPORT int
537
oa_mkdir(const char* path)
538
{
539
#ifdef OPENAXIOM_MS_WINDOWS_HOST
540
return CreateDirectory(path, NULL) ? 0 : -1;
541
#else
542
# define DIRECTORY_PERM ((S_IRWXU|S_IRWXG|S_IRWXO) & ~(S_IWGRP|S_IWOTH))
543
return mkdir (path, DIRECTORY_PERM);
544
# undef DIRECTORY_PERM
545
#endif
546
}
547
548
/* Run a shell command. Effectively forward to C's system(). */
549
OPENAXIOM_C_EXPORT int
550
oa_system(const char* cmd)
551
{
552
return system(cmd);
553
}
554
555
OPENAXIOM_C_EXPORT int
556
oa_getpid(void)
557
{
558
#ifdef OPENAXIOM_MS_WINDOWS_HOST
559
return GetCurrentProcessId();
560
#else
561
return getpid();
562
#endif
563
}
564
565
/* Concatenate two strings and return a pointer to the
566
newly allocate resulting string. */
567
OPENAXIOM_C_EXPORT const char*
568
oa_concatenate_string(const char* lhs, const char* rhs)
569
{
570
if (lhs == NULL)
571
return rhs;
572
else if (rhs == NULL)
573
return lhs;
574
else {
575
const int lhs_length = strlen(lhs);
576
char* result = (char*) malloc(lhs_length + strlen(rhs) + 1);
577
strcpy(result, lhs);
578
strcpy(result + lhs_length, rhs);
579
return result;
580
}
581
}
582
583
/* Return a string object that is the result of catenating the strings
584
designated by `left' and `right'. */
585
OPENAXIOM_C_EXPORT const char*
586
oa_strcat(const char* left, const char* right)
587
{
588
int left_size = strlen(left);
589
int right_size = strlen(right);
590
int size = left_size + right_size;
591
char* buffer = (char*) malloc(size + 1);
592
593
memcpy(buffer, left, left_size);
594
memcpy(buffer + left_size, right, right_size);
595
buffer[size] = '\0';
596
return buffer;
597
}
598
599
/* Return the value of an environment variable. */
600
OPENAXIOM_C_EXPORT char*
601
oa_getenv(const char* var)
602
{
603
#ifdef OPENAXIOM_MS_WINDOWS_HOST
604
#define BUFSIZE 128
605
char* buf = (char*) malloc(BUFSIZE);
606
int len = GetEnvironmentVariable(var, buf, BUFSIZE);
607
if (len == 0) {
608
free(buf);
609
return NULL;
610
}
611
else if (len > BUFSIZE) {
612
buf = (char*) realloc(buf,len);
613
len = GetEnvironmentVariable(var, buf, len);
614
if (len == 0) {
615
free(buf);
616
return NULL;
617
}
618
}
619
return buf;
620
#else
621
return getenv(var);
622
#endif
623
}
624
625
/* Set the value of environment variable VAR to VAL.
626
Return 1 on success, and 0 otherwise. */
627
OPENAXIOM_C_EXPORT int
628
oa_setenv(const char* var, const char* val)
629
{
630
#ifdef OPENAXIOM_MS_WINDOWS_HOST
631
return SetEnvironmentVariable(var, val);
632
#elif HAVE_DECL_SETENV
633
return !setenv(var, val, true);
634
#else
635
const int var_length = strlen(var);
636
const int val_length = strlen(val);
637
char* str = (char*) malloc(var_length + 1 + val_length + 1);
638
strcpy(str, var);
639
str[var_length] = '=';
640
strcpy(str + var_length + 1, val);
641
str[var_length + 1 + val_length] = '\0';
642
return !putenv(str);
643
#endif
644
}
645
646
647
OPENAXIOM_C_EXPORT char*
648
oa_getcwd(void)
649
{
650
size_t bufsz = 256;
651
char* buf = (char*) malloc(bufsz);
652
#ifdef OPENAXIOM_MS_WINDOWS_HOST
653
DWORD n = GetCurrentDirectory(bufsz, buf);
654
if (n == 0) {
655
perror("oa_getcwd");
656
exit(-1);
657
}
658
else if (n > bufsz) {
659
buf = (char*) realloc(buf,n);
660
if (GetCurrentDirectory(n, buf) != n) {
661
perror("oa_getcwd");
662
exit(-1);
663
}
664
}
665
return buf;
666
#else /* OPENAXIOM_MS_WINDOWS_HOST */
667
errno = 0;
668
while (getcwd(buf,bufsz) == 0) {
669
if (errno == ERANGE) {
670
errno = 0;
671
bufsz *= 2;
672
buf = (char*) realloc(buf, bufsz);
673
}
674
else {
675
perror("oa_getcwd");
676
exit(-1);
677
}
678
}
679
return buf;
680
#endif
681
}
682
683
OPENAXIOM_C_EXPORT int
684
oa_access_file_for_read(const char* path)
685
{
686
#ifdef OPENAXIOM_MS_WINDOWS_HOST
687
return GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES ? -1 : 1;
688
#else
689
return access(path, R_OK);
690
#endif
691
}
692
693
694
OPENAXIOM_C_EXPORT const char*
695
oa_get_tmpdir(void)
696
{
697
#ifdef OPENAXIOM_MS_WINDOWS_HOST
698
char* buf;
699
/* First, probe. */
700
int bufsz = GetTempPath(0, NULL);
701
if (bufsz == 0) {
702
perror("oa_get_tmpdir");
703
exit(1);
704
}
705
else {
706
int new_size;
707
buf = (char*) malloc(bufsz + 1);
708
new_size = GetTempPath(bufsz, buf);
709
if(new_size == 0 || new_size >= bufsz) {
710
perror("oa_get_tmpdir");
711
free(buf);
712
exit(1);
713
}
714
buf[new_size] = '\0';
715
}
716
return buf;
717
#else
718
return "/tmp";
719
#endif
720
}
721
722
723
OPENAXIOM_C_EXPORT int
724
oa_copy_file(const char* src, const char* dst)
725
{
726
#ifdef OPENAXIOM_MS_WINDOWS_HOST
727
return CopyFile(src,dst, /* bFailIfExists = */ 0) ? 0 : -1;
728
#else
729
#define OA_BUFSZ 512
730
#define OA_DEFAULT_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
731
char buf[OA_BUFSZ];
732
int src_fd;
733
int dst_fd;
734
int count;
735
if((src_fd = open(src, O_RDONLY)) < 0)
736
return -1;
737
if ((dst_fd = creat(dst, OA_DEFAULT_MODE)) < 0) {
738
close(src_fd);
739
return -1;
740
}
741
742
while ((count = read(src_fd, buf, OA_BUFSZ)) > 0)
743
if (write(dst_fd, buf, count) != count)
744
break;
745
746
#undef OA_DEFAULT_MODE
747
#undef OA_BUFSZ
748
return (close(dst_fd) < 0 || close(src_fd) < 0 || count < 0) ? -1 : 0;
749
#endif
750
}
751
752
753
OPENAXIOM_C_EXPORT double
754
plus_infinity(void )
755
{
756
#ifdef INFINITY
757
return INFINITY;
758
#else
759
/* This must be a curious platform. */
760
volatile double zero = 0.0;
761
return 1.0 / zero; /* If it traps, well, it traps. */
762
#endif
763
}
764
765
OPENAXIOM_C_EXPORT double
766
minus_infinity(void)
767
{
768
return -plus_infinity();
769
}
770
771
OPENAXIOM_C_EXPORT double
772
quiet_double_NaN(void)
773
{
774
#ifdef NAN
775
return NAN;
776
#else
777
return sqrt(-1.0); /* Just pick one. */
778
#endif
779
}
780
781
782
OPENAXIOM_C_EXPORT Byteorder
783
oa_get_host_byteorder(void)
784
{
785
#ifdef WORDS_BIGENDIAN
786
return Byteorder::big;
787
#else
788
return Byteorder::little;
789
#endif
790
}
791
792
793
OPENAXIOM_C_EXPORT void
794
oa_allocate_process_argv(Process* proc, int argc)
795
{
796
proc->argc = argc;
797
proc->argv = (char**) malloc((1 + argc) * sizeof (char*));
798
proc->argv[argc] = NULL;
799
}
800
801
OPENAXIOM_C_EXPORT int
802
oa_spawn(Process* proc, SpawnFlags flags)
803
{
804
#ifdef OPENAXIOM_MS_WINDOWS_HOST
805
const char* path = NULL;
806
char* cmd_line = NULL;
807
int curpos = strlen(proc->argv[0]);
808
int cmd_line_length = curpos;
809
int i;
810
PROCESS_INFORMATION proc_info;
811
STARTUPINFO startup_info = { 0 };
812
DWORD status;
813
814
for (i = 0; i < proc->argc; ++i)
815
cmd_line_length += 1 + strlen(proc->argv[i]);
816
817
cmd_line = (char*) malloc(cmd_line_length + 1);
818
strcpy(cmd_line, proc->argv[0]);
819
for (i = 0; i < proc->argc; ++i) {
820
cmd_line[curpos++] = ' ';
821
strcpy(cmd_line + curpos, proc->argv[i]);
822
curpos += strlen(proc->argv[i]);
823
}
824
cmd_line[curpos] = '\0';
825
826
if ((flags & SpawnFlags::search_path) == 0)
827
path = proc->argv[0];
828
829
if(CreateProcess(/* lpApplicationName */ path,
830
/* lpCommandLine */ cmd_line,
831
/* lpProcessAttributes */ NULL,
832
/* lpThreadAttributes */ NULL,
833
/* bInheritHandles */ TRUE,
834
/* dwCreationFlags */ 0,
835
/* lpEnvironment */ NULL,
836
/* lpCurrentDirectory */ NULL,
837
/* lpstartupInfo */ &startup_info,
838
/* lpProcessInformation */ &proc_info) == 0) {
839
fprintf(stderr, "oa_spawn: error %lu\n", GetLastError());
840
return proc->id = -1;
841
}
842
proc->id = proc_info.dwProcessId;
843
if ((flags & SpawnFlags::replace) == 0)
844
return proc->id;
845
WaitForSingleObject(proc_info.hProcess, INFINITE);
846
GetExitCodeProcess(proc_info.hProcess, &status);
847
CloseHandle(proc_info.hThread);
848
CloseHandle(proc_info.hProcess);
849
return status;
850
851
#else
852
proc->id = 0;
853
if ((flags & SpawnFlags::replace) == 0)
854
proc->id = fork();
855
if (proc->id == 0) {
856
if (flags & SpawnFlags::search_path)
857
execvp(proc->argv[0], proc->argv);
858
else
859
execv(proc->argv[0], proc->argv);
860
perror(strerror(errno));
861
/* Don't keep useless clones around. */
862
if ((flags & SpawnFlags::replace) == 0)
863
exit(-1);
864
}
865
return proc->id;
866
#endif
867
}
868
869
OPENAXIOM_C_EXPORT char*
870
oa_substr(const char* str, const size_t begin, const size_t end)
871
{
872
char* substring;
873
int len;
874
875
if (str == NULL || strlen(str) == 0 ||
876
strlen(str) < begin || end >= strlen(str) || begin > end)
877
return NULL;
878
879
len = (end - begin) + 2;
880
substring = (char*) malloc(len * sizeof(char));
881
memset(substring,'\0',len);
882
memcpy(substring, str+begin, len-1);
883
884
return substring;
885
}
886
887
OPENAXIOM_C_EXPORT char**
888
oa_split(const char* sequence, const char* delimiter, int* size)
889
{
890
int sequence_length = 0, newsize = 0;
891
char* token;
892
char** tokens = NULL;
893
char* sequence_copy;
894
895
sequence_length = strlen(sequence);
896
sequence_copy = (char*) malloc((sequence_length + 1) * sizeof(char*));
897
strcpy(sequence_copy,sequence);
898
sequence_copy[sequence_length] = '\0';
899
900
token = strtok(sequence_copy, delimiter);
901
while (token != NULL) {
902
903
tokens = (char**) realloc(tokens,(newsize + 1) * sizeof(char*));
904
tokens[newsize] = token;
905
newsize++;
906
token = strtok (NULL, delimiter);
907
}
908
909
*size = newsize;
910
911
return tokens;
912
}
913
914
}
915
916