Home | History | Annotate | Download | only in lib
      1 /* portability.c - code to workaround the deficiencies of various platforms.
      2  *
      3  * Copyright 2012 Rob Landley <rob (at) landley.net>
      4  * Copyright 2012 Georgi Chorbadzhiyski <gf (at) 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   }
     67 
     68   if (i > *np) {
     69     // Need more space
     70     new_len  = i + 2;
     71     new_line = realloc(*linep, new_len);
     72     if (!new_line) return -1;
     73     *np = new_len;
     74     line = *linep = new_line;
     75   }
     76   line[i] = '\0';
     77 
     78   return i > 0 ? i : -1;
     79 }
     80 
     81 ssize_t getline(char **linep, size_t *np, FILE *stream)
     82 {
     83   return getdelim(linep, np, '\n', stream);
     84 }
     85 
     86 extern char **environ;
     87 
     88 int clearenv(void)
     89 {
     90   *environ = NULL;
     91   return 0;
     92 }
     93 #endif
     94