OSDN Git Service

Merge remote-tracking branch 'toybox/master' into HEAD
[android-x86/external-toybox.git] / lib / portability.c
1 /* portability.c - code to workaround the deficiencies of various platforms.
2  *
3  * Copyright 2012 Rob Landley <rob@landley.net>
4  * Copyright 2012 Georgi Chorbadzhiyski <gf@unixsol.org>
5  */
6
7 #include "toys.h"
8
9 // We can't fork() on nommu systems, and vfork() requires an exec() or exit()
10 // before resuming the parent (because they share a heap until then). And no,
11 // we can't implement our own clone() call that does the equivalent of fork()
12 // because nommu heaps use physical addresses so if we copy the heap all our
13 // pointers are wrong. (You need an mmu in order to map two heaps to the same
14 // address range without interfering with each other.) In the absence of
15 // a portable way to tell malloc() to start a new heap without freeing the old
16 // one, you pretty much need the exec().)
17
18 // So we exec ourselves (via /proc/self/exe, if anybody knows a way to
19 // re-exec self without depending on the filesystem, I'm all ears),
20 // and use the arguments to signal reentry.
21
22 #if CFG_TOYBOX_FORK
23 pid_t xfork(void)
24 {
25   pid_t pid = fork();
26
27   if (pid < 0) perror_exit("fork");
28
29   return pid;
30 }
31 #endif
32
33 #if defined(__APPLE__)
34 ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream)
35 {
36   int ch;
37   size_t new_len;
38   ssize_t i = 0;
39   char *line, *new_line;
40
41   // Invalid input
42   if (!linep || !np) {
43     errno = EINVAL;
44     return -1;
45   }
46
47   if (*linep == NULL || *np == 0) {
48     *np = 1024;
49     *linep = calloc(1, *np);
50     if (*linep == NULL) return -1;
51   }
52   line = *linep;
53
54   while ((ch = getc(stream)) != EOF) {
55     if (i > *np) {
56       // Need more space
57       new_len = *np + 1024;
58       new_line = realloc(*linep, new_len);
59       if (!new_line) return -1;
60       *np = new_len;
61       line = *linep = new_line;
62     }
63
64     line[i] = ch;
65     if (ch == delim) break;
66     i += 1;
67   }
68
69   if (i > *np) {
70     // Need more space
71     new_len  = i + 2;
72     new_line = realloc(*linep, new_len);
73     if (!new_line) return -1;
74     *np = new_len;
75     line = *linep = new_line;
76   }
77   line[i + 1] = '\0';
78
79   return i > 0 ? i : -1;
80 }
81
82 ssize_t getline(char **linep, size_t *np, FILE *stream)
83 {
84   return getdelim(linep, np, '\n', stream);
85 }
86
87 extern char **environ;
88
89 int clearenv(void)
90 {
91   *environ = NULL;
92   return 0;
93 }
94 #endif