You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.2 KiB
94 lines
2.2 KiB
/* portability.c - code to workaround the deficiencies of various platforms. |
|
* |
|
* Copyright 2012 Rob Landley <rob@landley.net> |
|
* Copyright 2012 Georgi Chorbadzhiyski <gf@unixsol.org> |
|
*/ |
|
|
|
#include "toys.h" |
|
|
|
// We can't fork() on nommu systems, and vfork() requires an exec() or exit() |
|
// before resuming the parent (because they share a heap until then). And no, |
|
// we can't implement our own clone() call that does the equivalent of fork() |
|
// because nommu heaps use physical addresses so if we copy the heap all our |
|
// pointers are wrong. (You need an mmu in order to map two heaps to the same |
|
// address range without interfering with each other.) In the absence of |
|
// a portable way to tell malloc() to start a new heap without freeing the old |
|
// one, you pretty much need the exec().) |
|
|
|
// So we exec ourselves (via /proc/self/exe, if anybody knows a way to |
|
// re-exec self without depending on the filesystem, I'm all ears), |
|
// and use the arguments to signal reentry. |
|
|
|
#if CFG_TOYBOX_FORK |
|
pid_t xfork(void) |
|
{ |
|
pid_t pid = fork(); |
|
|
|
if (pid < 0) perror_exit("fork"); |
|
|
|
return pid; |
|
} |
|
#endif |
|
|
|
#if defined(__APPLE__) |
|
ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) |
|
{ |
|
int ch; |
|
size_t new_len; |
|
ssize_t i = 0; |
|
char *line, *new_line; |
|
|
|
// Invalid input |
|
if (!linep || !np) { |
|
errno = EINVAL; |
|
return -1; |
|
} |
|
|
|
if (*linep == NULL || *np == 0) { |
|
*np = 1024; |
|
*linep = calloc(1, *np); |
|
if (*linep == NULL) return -1; |
|
} |
|
line = *linep; |
|
|
|
while ((ch = getc(stream)) != EOF) { |
|
if (i > *np) { |
|
// Need more space |
|
new_len = *np + 1024; |
|
new_line = realloc(*linep, new_len); |
|
if (!new_line) return -1; |
|
*np = new_len; |
|
line = *linep = new_line; |
|
} |
|
|
|
line[i] = ch; |
|
if (ch == delim) break; |
|
i += 1; |
|
} |
|
|
|
if (i > *np) { |
|
// Need more space |
|
new_len = i + 2; |
|
new_line = realloc(*linep, new_len); |
|
if (!new_line) return -1; |
|
*np = new_len; |
|
line = *linep = new_line; |
|
} |
|
line[i + 1] = '\0'; |
|
|
|
return i > 0 ? i : -1; |
|
} |
|
|
|
ssize_t getline(char **linep, size_t *np, FILE *stream) |
|
{ |
|
return getdelim(linep, np, '\n', stream); |
|
} |
|
|
|
extern char **environ; |
|
|
|
int clearenv(void) |
|
{ |
|
*environ = NULL; |
|
return 0; |
|
} |
|
#endif
|
|
|