mrrl-logincaps

MRRL version of logincaps
git clone https://ccx.te2000.cz/git/mrrl-logincaps
Log | Files | Refs

portability.c (2550B)


      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 void xgetrandom(void *buf, unsigned buflen, unsigned flags)
     34 {
     35   int fd;
     36 
     37 #if CFG_TOYBOX_GETRANDOM
     38   if (buflen == getrandom(buf, buflen, flags)) return;
     39   if (!CFG_TOYBOX_ON_ANDROID || errno!=ENOSYS) perror_exit("getrandom");
     40 #endif
     41 
     42   fd = xopen(flags ? "/dev/random" : "/dev/urandom", O_RDONLY);
     43   xreadall(fd, buf, buflen);
     44   close(fd);
     45 }
     46 
     47 #if defined(__APPLE__)
     48 ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream)
     49 {
     50   int ch;
     51   size_t new_len;
     52   ssize_t i = 0;
     53   char *line, *new_line;
     54 
     55   // Invalid input
     56   if (!linep || !np) {
     57     errno = EINVAL;
     58     return -1;
     59   }
     60 
     61   if (*linep == NULL || *np == 0) {
     62     *np = 1024;
     63     *linep = calloc(1, *np);
     64     if (*linep == NULL) return -1;
     65   }
     66   line = *linep;
     67 
     68   while ((ch = getc(stream)) != EOF) {
     69     if (i > *np) {
     70       // Need more space
     71       new_len = *np + 1024;
     72       new_line = realloc(*linep, new_len);
     73       if (!new_line) return -1;
     74       *np = new_len;
     75       line = *linep = new_line;
     76     }
     77 
     78     line[i++] = ch;
     79     if (ch == delim) break;
     80   }
     81 
     82   if (i > *np) {
     83     // Need more space
     84     new_len  = i + 2;
     85     new_line = realloc(*linep, new_len);
     86     if (!new_line) return -1;
     87     *np = new_len;
     88     line = *linep = new_line;
     89   }
     90   line[i] = '\0';
     91 
     92   return i > 0 ? i : -1;
     93 }
     94 
     95 ssize_t getline(char **linep, size_t *np, FILE *stream)
     96 {
     97   return getdelim(linep, np, '\n', stream);
     98 }
     99 
    100 extern char **environ;
    101 
    102 int clearenv(void)
    103 {
    104   *environ = NULL;
    105   return 0;
    106 }
    107 #endif