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     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
     95