blob: 78e500b1f85e21bddb45a243e6110561b03541dc [file] [log] [blame]
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -05001/* 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
Rob Landley99332732015-07-03 15:17:25 -05009// 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
Rob Landley50fc9ed2014-12-04 21:46:59 -060023pid_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
Elliott Hughes6a29bb12014-11-21 21:49:05 -060033#if defined(__APPLE__)
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050034ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream)
35{
Rob Landley7aa651a2012-11-13 17:14:08 -060036 int ch;
37 size_t new_len;
38 ssize_t i = 0;
39 char *line, *new_line;
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050040
Rob Landley7aa651a2012-11-13 17:14:08 -060041 // Invalid input
42 if (!linep || !np) {
43 errno = EINVAL;
44 return -1;
45 }
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050046
Rob Landley7aa651a2012-11-13 17:14:08 -060047 if (*linep == NULL || *np == 0) {
48 *np = 1024;
49 *linep = calloc(1, *np);
50 if (*linep == NULL) return -1;
51 }
52 line = *linep;
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050053
Rob Landley7aa651a2012-11-13 17:14:08 -060054 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;
Rob Landleycff8e132015-03-21 15:29:21 -050061 line = *linep = new_line;
Rob Landley7aa651a2012-11-13 17:14:08 -060062 }
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050063
Rob Landley7aa651a2012-11-13 17:14:08 -060064 line[i] = ch;
65 if (ch == delim) break;
66 i += 1;
67 }
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050068
Rob Landley7aa651a2012-11-13 17:14:08 -060069 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;
Rob Landleycff8e132015-03-21 15:29:21 -050075 line = *linep = new_line;
Rob Landley7aa651a2012-11-13 17:14:08 -060076 }
77 line[i + 1] = '\0';
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050078
Rob Landley7aa651a2012-11-13 17:14:08 -060079 return i > 0 ? i : -1;
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050080}
81
Rob Landley7aa651a2012-11-13 17:14:08 -060082ssize_t getline(char **linep, size_t *np, FILE *stream)
83{
84 return getdelim(linep, np, '\n', stream);
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050085}
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050086
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050087extern char **environ;
88
Rob Landley7aa651a2012-11-13 17:14:08 -060089int clearenv(void)
90{
91 *environ = NULL;
92 return 0;
Georgi Chorbadzhiyski522d9062012-03-16 06:42:08 -050093}
94#endif