Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/libbb/xfuncs.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/libbb/xfuncs.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 * Copyright (C) 2006 Rob Landley
    7  * Copyright (C) 2006 Denis Vlasenko
     7 * Copyright (C) 2006 Denys Vlasenko
    88 *
    9  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2, see file LICENSE in this source tree.
    1010 */
    1111
     12/* We need to have separate xfuncs.c and xfuncs_printf.c because
     13 * with current linkers, even with section garbage collection,
     14 * if *.o module references any of XXXprintf functions, you pull in
     15 * entire printf machinery. Even if you do not use the function
     16 * which uses XXXprintf.
     17 *
     18 * xfuncs.c contains functions (not necessarily xfuncs)
     19 * which do not pull in printf, directly or indirectly.
     20 * xfunc_printf.c contains those which do.
     21 *
     22 * TODO: move xmalloc() and xatonum() here.
     23 */
     24
    1225#include "libbb.h"
    1326
    14 /* All the functions starting with "x" call bb_error_msg_and_die() if they
    15  * fail, so callers never need to check for errors.  If it returned, it
    16  * succeeded. */
    17 
    18 #ifndef DMALLOC
    19 /* dmalloc provides variants of these that do abort() on failure.
    20  * Since dmalloc's prototypes overwrite the impls here as they are
    21  * included after these prototypes in libbb.h, all is well.
     27/* Turn on nonblocking I/O on a fd */
     28int FAST_FUNC ndelay_on(int fd)
     29{
     30    return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
     31}
     32
     33int FAST_FUNC ndelay_off(int fd)
     34{
     35    return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
     36}
     37
     38int FAST_FUNC close_on_exec_on(int fd)
     39{
     40    return fcntl(fd, F_SETFD, FD_CLOEXEC);
     41}
     42
     43char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src)
     44{
     45#ifndef IFNAMSIZ
     46    enum { IFNAMSIZ = 16 };
     47#endif
     48    return strncpy(dst, src, IFNAMSIZ);
     49}
     50
     51
     52/* Convert unsigned integer to ascii, writing into supplied buffer.
     53 * A truncated result contains the first few digits of the result ala strncpy.
     54 * Returns a pointer past last generated digit, does _not_ store NUL.
    2255 */
    23 // Warn if we can't allocate size bytes of memory.
    24 void *malloc_or_warn(size_t size)
    25 {
    26     void *ptr = malloc(size);
    27     if (ptr == NULL && size != 0)
    28         bb_error_msg(bb_msg_memory_exhausted);
    29     return ptr;
    30 }
    31 
    32 // Die if we can't allocate size bytes of memory.
    33 void *xmalloc(size_t size)
    34 {
    35     void *ptr = malloc(size);
    36     if (ptr == NULL && size != 0)
    37         bb_error_msg_and_die(bb_msg_memory_exhausted);
    38     return ptr;
    39 }
    40 
    41 // Die if we can't resize previously allocated memory.  (This returns a pointer
    42 // to the new memory, which may or may not be the same as the old memory.
    43 // It'll copy the contents to a new chunk and free the old one if necessary.)
    44 void *xrealloc(void *ptr, size_t size)
    45 {
    46     ptr = realloc(ptr, size);
    47     if (ptr == NULL && size != 0)
    48         bb_error_msg_and_die(bb_msg_memory_exhausted);
    49     return ptr;
    50 }
    51 #endif /* DMALLOC */
    52 
    53 // Die if we can't allocate and zero size bytes of memory.
    54 void *xzalloc(size_t size)
    55 {
    56     void *ptr = xmalloc(size);
    57     memset(ptr, 0, size);
    58     return ptr;
    59 }
    60 
    61 // Die if we can't copy a string to freshly allocated memory.
    62 char * xstrdup(const char *s)
    63 {
    64     char *t;
    65 
    66     if (s == NULL)
    67         return NULL;
    68 
    69     t = strdup(s);
    70 
    71     if (t == NULL)
    72         bb_error_msg_and_die(bb_msg_memory_exhausted);
    73 
    74     return t;
    75 }
    76 
    77 // Die if we can't allocate n+1 bytes (space for the null terminator) and copy
    78 // the (possibly truncated to length n) string into it.
    79 char * xstrndup(const char *s, int n)
    80 {
    81     int m;
    82     char *t;
    83 
    84     if (ENABLE_DEBUG && s == NULL)
    85         bb_error_msg_and_die("xstrndup bug");
    86 
    87     /* We can just xmalloc(n+1) and strncpy into it, */
    88     /* but think about xstrndup("abc", 10000) wastage! */
    89     m = n;
    90     t = (char*) s;
    91     while (m) {
    92         if (!*t) break;
    93         m--;
    94         t++;
    95     }
    96     n -= m;
    97     t = xmalloc(n + 1);
    98     t[n] = '\0';
    99 
    100     return memcpy(t, s, n);
    101 }
    102 
    103 // Die if we can't open a file and return a FILE * to it.
    104 // Notice we haven't got xfread(), This is for use with fscanf() and friends.
    105 FILE *xfopen(const char *path, const char *mode)
    106 {
    107     FILE *fp = fopen(path, mode);
    108     if (fp == NULL)
    109         bb_perror_msg_and_die("can't open '%s'", path);
    110     return fp;
    111 }
    112 
    113 // Die if we can't open a file and return a fd.
    114 int xopen3(const char *pathname, int flags, int mode)
    115 {
    116     int ret;
    117 
    118     ret = open(pathname, flags, mode);
    119     if (ret < 0) {
    120         bb_perror_msg_and_die("can't open '%s'", pathname);
    121     }
    122     return ret;
    123 }
    124 
    125 // Die if we can't open an existing file and return a fd.
    126 int xopen(const char *pathname, int flags)
    127 {
    128     return xopen3(pathname, flags, 0666);
    129 }
    130 
    131 // Warn if we can't open a file and return a fd.
    132 int open3_or_warn(const char *pathname, int flags, int mode)
    133 {
    134     int ret;
    135 
    136     ret = open(pathname, flags, mode);
    137     if (ret < 0) {
    138         bb_perror_msg("can't open '%s'", pathname);
    139     }
    140     return ret;
    141 }
    142 
    143 // Warn if we can't open a file and return a fd.
    144 int open_or_warn(const char *pathname, int flags)
    145 {
    146     return open3_or_warn(pathname, flags, 0666);
    147 }
    148 
    149 void xpipe(int filedes[2])
    150 {
    151     if (pipe(filedes))
    152         bb_perror_msg_and_die("can't create pipe");
    153 }
    154 
    155 void xunlink(const char *pathname)
    156 {
    157     if (unlink(pathname))
    158         bb_perror_msg_and_die("can't remove file '%s'", pathname);
    159 }
    160 
    161 // Turn on nonblocking I/O on a fd
    162 int ndelay_on(int fd)
    163 {
    164     return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);
    165 }
    166 
    167 int ndelay_off(int fd)
    168 {
    169     return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK);
    170 }
    171 
    172 void xdup2(int from, int to)
    173 {
    174     if (dup2(from, to) != to)
    175         bb_perror_msg_and_die("can't duplicate file descriptor");
    176 }
    177 
    178 // "Renumber" opened fd
    179 void xmove_fd(int from, int to)
    180 {
    181     if (from == to)
    182         return;
    183     xdup2(from, to);
    184     close(from);
    185 }
    186 
    187 // Die with an error message if we can't write the entire buffer.
    188 void xwrite(int fd, const void *buf, size_t count)
    189 {
    190     if (count) {
    191         ssize_t size = full_write(fd, buf, count);
    192         if (size != count)
    193             bb_error_msg_and_die("short write");
    194     }
    195 }
    196 
    197 // Die with an error message if we can't lseek to the right spot.
    198 off_t xlseek(int fd, off_t offset, int whence)
    199 {
    200     off_t off = lseek(fd, offset, whence);
    201     if (off == (off_t)-1) {
    202         if (whence == SEEK_SET)
    203             bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);
    204         bb_perror_msg_and_die("lseek");
    205     }
    206     return off;
    207 }
    208 
    209 // Die with supplied filename if this FILE * has ferror set.
    210 void die_if_ferror(FILE *fp, const char *fn)
    211 {
    212     if (ferror(fp)) {
    213         /* ferror doesn't set useful errno */
    214         bb_error_msg_and_die("%s: I/O error", fn);
    215     }
    216 }
    217 
    218 // Die with an error message if stdout has ferror set.
    219 void die_if_ferror_stdout(void)
    220 {
    221     die_if_ferror(stdout, bb_msg_standard_output);
    222 }
    223 
    224 // Die with an error message if we have trouble flushing stdout.
    225 void xfflush_stdout(void)
    226 {
    227     if (fflush(stdout)) {
    228         bb_perror_msg_and_die(bb_msg_standard_output);
    229     }
    230 }
    231 
    232 void sig_block(int sig)
    233 {
    234     sigset_t ss;
    235     sigemptyset(&ss);
    236     sigaddset(&ss, sig);
    237     sigprocmask(SIG_BLOCK, &ss, NULL);
    238 }
    239 
    240 void sig_unblock(int sig)
    241 {
    242     sigset_t ss;
    243     sigemptyset(&ss);
    244     sigaddset(&ss, sig);
    245     sigprocmask(SIG_UNBLOCK, &ss, NULL);
    246 }
    247 
    248 #if 0
    249 void sig_blocknone(void)
    250 {
    251     sigset_t ss;
    252     sigemptyset(&ss);
    253     sigprocmask(SIG_SETMASK, &ss, NULL);
    254 }
    255 #endif
    256 
    257 void sig_catch(int sig, void (*f)(int))
    258 {
    259     struct sigaction sa;
    260     sa.sa_handler = f;
    261     sa.sa_flags = 0;
    262     sigemptyset(&sa.sa_mask);
    263     sigaction(sig, &sa, NULL);
    264 }
    265 
    266 void sig_pause(void)
    267 {
    268     sigset_t ss;
    269     sigemptyset(&ss);
    270     sigsuspend(&ss);
    271 }
    272 
    273 
    274 void xsetenv(const char *key, const char *value)
    275 {
    276     if (setenv(key, value, 1))
    277         bb_error_msg_and_die(bb_msg_memory_exhausted);
    278 }
    279 
    280 // Converts unsigned long long value into compact 4-char
    281 // representation. Examples: "1234", "1.2k", " 27M", "123T"
    282 // Fifth char is always '\0'
    283 void smart_ulltoa5(unsigned long long ul, char buf[5])
    284 {
    285     const char *fmt;
    286     char c;
    287     unsigned v,idx = 0;
    288     ul *= 10;
    289     if (ul > 9999*10) { // do not scale if 9999 or less
    290         while (ul >= 10000) {
    291             ul /= 1024;
    292             idx++;
    293         }
    294     }
    295     v = ul; // ullong divisions are expensive, avoid them
    296 
    297     fmt = " 123456789";
    298     if (!idx) {     // 9999 or less: use 1234 format
    299         c = buf[0] = " 123456789"[v/10000];
    300         if (c != ' ') fmt = "0123456789";
    301         c = buf[1] = fmt[v/1000%10];
    302         if (c != ' ') fmt = "0123456789";
    303         buf[2] = fmt[v/100%10];
    304         buf[3] = "0123456789"[v/10%10];
    305     } else {
    306         if (v >= 10*10) {   // scaled value is >=10: use 123M format
    307             c = buf[0] = " 123456789"[v/1000];
    308             if (c != ' ') fmt = "0123456789";
    309             buf[1] = fmt[v/100%10];
    310             buf[2] = "0123456789"[v/10%10];
    311         } else {    // scaled value is <10: use 1.2M format
    312             buf[0] = "0123456789"[v/10];
    313             buf[1] = '.';
    314             buf[2] = "0123456789"[v%10];
    315         }
    316         // see http://en.wikipedia.org/wiki/Tera
    317         buf[3] = " kMGTPEZY"[idx];
    318     }
    319     buf[4] = '\0';
    320 }
    321 
    322 // Convert unsigned integer to ascii, writing into supplied buffer.
    323 // A truncated result contains the first few digits of the result ala strncpy.
    324 // Returns a pointer past last generated digit, does _not_ store NUL.
    325 void BUG_sizeof_unsigned_not_4(void);
    326 char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
     56void BUG_sizeof(void);
     57char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
    32758{
    32859    unsigned i, out, res;
    329     if (sizeof(unsigned) != 4)
    330         BUG_sizeof_unsigned_not_4();
     60
    33161    if (buflen) {
    33262        out = 0;
    333         for (i = 1000000000; i; i /= 10) {
     63        if (sizeof(n) == 4)
     64        // 2^32-1 = 4294967295
     65            i = 1000000000;
     66#if UINT_MAX > 4294967295 /* prevents warning about "const too large" */
     67        else
     68        if (sizeof(n) == 8)
     69        // 2^64-1 = 18446744073709551615
     70            i = 10000000000000000000;
     71#endif
     72        else
     73            BUG_sizeof();
     74        for (; i; i /= 10) {
    33475            res = n / i;
     76            n = n % i;
    33577            if (res || out || i == 1) {
    336                 if (!--buflen) break;
     78                if (--buflen == 0)
     79                    break;
    33780                out++;
    338                 n -= res*i;
    33981                *buf++ = '0' + res;
    34082            }
     
    34486}
    34587
    346 // Convert signed integer to ascii, like utoa_to_buf()
    347 char *itoa_to_buf(int n, char *buf, unsigned buflen)
    348 {
    349     if (buflen && n<0) {
     88/* Convert signed integer to ascii, like utoa_to_buf() */
     89char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
     90{
     91    if (!buflen)
     92        return buf;
     93    if (n < 0) {
    35094        n = -n;
    35195        *buf++ = '-';
     
    358102// second time will overwrite previous results.
    359103//
    360 // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
    361 // Int should always be 32 bits on any remotely Unix-like system, see
    362 // http://www.unix.org/whitepapers/64bit.html for the reasons why.
    363 
    364 static char local_buf[12];
    365 
    366 // Convert unsigned integer to ascii using a static buffer (returned).
    367 char *utoa(unsigned n)
    368 {
    369     *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
     104// The largest 32 bit integer is -2 billion plus NUL, or 1+10+1=12 bytes.
     105// It so happens that sizeof(int) * 3 is enough for 32+ bit ints.
     106// (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
     107
     108static char local_buf[sizeof(int) * 3];
     109
     110/* Convert unsigned integer to ascii using a static buffer (returned). */
     111char* FAST_FUNC utoa(unsigned n)
     112{
     113    *(utoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
    370114
    371115    return local_buf;
    372116}
    373117
    374 // Convert signed integer to ascii using a static buffer (returned).
    375 char *itoa(int n)
    376 {
    377     *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
     118/* Convert signed integer to ascii using a static buffer (returned). */
     119char* FAST_FUNC itoa(int n)
     120{
     121    *(itoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
    378122
    379123    return local_buf;
    380124}
    381125
    382 // Emit a string of hex representation of bytes
    383 char *bin2hex(char *p, const char *cp, int count)
     126/* Emit a string of hex representation of bytes */
     127char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
    384128{
    385129    while (count) {
     
    393137}
    394138
    395 // Die with an error message if we can't set gid.  (Because resource limits may
    396 // limit this user to a given number of processes, and if that fills up the
    397 // setgid() will fail and we'll _still_be_root_, which is bad.)
    398 void xsetgid(gid_t gid)
    399 {
    400     if (setgid(gid)) bb_perror_msg_and_die("setgid");
    401 }
    402 
    403 // Die with an error message if we can't set uid.  (See xsetgid() for why.)
    404 void xsetuid(uid_t uid)
    405 {
    406     if (setuid(uid)) bb_perror_msg_and_die("setuid");
    407 }
    408 
    409 // Return how long the file at fd is, if there's any way to determine it.
    410 off_t fdlength(int fd)
     139/* Convert "[x]x[:][x]x[:][x]x[:][x]x" hex string to binary, no more than COUNT bytes */
     140char* FAST_FUNC hex2bin(char *dst, const char *str, int count)
     141{
     142    errno = EINVAL;
     143    while (*str && count) {
     144        uint8_t val;
     145        uint8_t c = *str++;
     146        if (isdigit(c))
     147            val = c - '0';
     148        else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
     149            val = (c|0x20) - ('a' - 10);
     150        else
     151            return NULL;
     152        val <<= 4;
     153        c = *str;
     154        if (isdigit(c))
     155            val |= c - '0';
     156        else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
     157            val |= (c|0x20) - ('a' - 10);
     158        else if (c == ':' || c == '\0')
     159            val >>= 4;
     160        else
     161            return NULL;
     162
     163        *dst++ = val;
     164        if (c != '\0')
     165            str++;
     166        if (*str == ':')
     167            str++;
     168        count--;
     169    }
     170    errno = (*str ? ERANGE : 0);
     171    return dst;
     172}
     173
     174/* Return how long the file at fd is, if there's any way to determine it. */
     175#ifdef UNUSED
     176off_t FAST_FUNC fdlength(int fd)
    411177{
    412178    off_t bottom = 0, top = 0, pos;
     
    446212    return pos + 1;
    447213}
    448 
    449 // Die with an error message if we can't malloc() enough space and do an
    450 // sprintf() into that space.
    451 char *xasprintf(const char *format, ...)
    452 {
    453     va_list p;
    454     int r;
    455     char *string_ptr;
    456 
    457 #if 1
    458     // GNU extension
    459     va_start(p, format);
    460     r = vasprintf(&string_ptr, format, p);
    461     va_end(p);
    462 #else
    463     // Bloat for systems that haven't got the GNU extension.
    464     va_start(p, format);
    465     r = vsnprintf(NULL, 0, format, p);
    466     va_end(p);
    467     string_ptr = xmalloc(r+1);
    468     va_start(p, format);
    469     r = vsnprintf(string_ptr, r+1, format, p);
    470     va_end(p);
    471214#endif
    472215
    473     if (r < 0) bb_error_msg_and_die(bb_msg_memory_exhausted);
    474     return string_ptr;
    475 }
    476 
    477 #if 0 /* If we will ever meet a libc which hasn't [f]dprintf... */
    478 int fdprintf(int fd, const char *format, ...)
    479 {
    480     va_list p;
    481     int r;
    482     char *string_ptr;
    483 
    484 #if 1
    485     // GNU extension
    486     va_start(p, format);
    487     r = vasprintf(&string_ptr, format, p);
    488     va_end(p);
    489 #else
    490     // Bloat for systems that haven't got the GNU extension.
    491     va_start(p, format);
    492     r = vsnprintf(NULL, 0, format, p) + 1;
    493     va_end(p);
    494     string_ptr = malloc(r);
    495     if (string_ptr) {
    496         va_start(p, format);
    497         r = vsnprintf(string_ptr, r, format, p);
    498         va_end(p);
    499     }
    500 #endif
    501 
    502     if (r >= 0) {
    503         full_write(fd, string_ptr, r);
    504         free(string_ptr);
    505     }
    506     return r;
    507 }
    508 #endif
    509 
    510 // Die with an error message if we can't copy an entire FILE * to stdout, then
    511 // close that file.
    512 void xprint_and_close_file(FILE *file)
    513 {
    514     fflush(stdout);
    515     // copyfd outputs error messages for us.
    516     if (bb_copyfd_eof(fileno(file), 1) == -1)
    517         xfunc_die();
    518 
    519     fclose(file);
    520 }
    521 
    522 // Die if we can't chdir to a new path.
    523 void xchdir(const char *path)
    524 {
    525     if (chdir(path))
    526         bb_perror_msg_and_die("chdir(%s)", path);
    527 }
    528 
    529 // Print a warning message if opendir() fails, but don't die.
    530 DIR *warn_opendir(const char *path)
    531 {
    532     DIR *dp;
    533 
    534     dp = opendir(path);
    535     if (!dp)
    536         bb_perror_msg("can't open '%s'", path);
    537     return dp;
    538 }
    539 
    540 // Die with an error message if opendir() fails.
    541 DIR *xopendir(const char *path)
    542 {
    543     DIR *dp;
    544 
    545     dp = opendir(path);
    546     if (!dp)
    547         bb_perror_msg_and_die("can't open '%s'", path);
    548     return dp;
    549 }
    550 
    551 // Die with an error message if we can't open a new socket.
    552 int xsocket(int domain, int type, int protocol)
    553 {
    554     int r = socket(domain, type, protocol);
    555 
    556     if (r < 0) {
    557         /* Hijack vaguely related config option */
    558 #if ENABLE_VERBOSE_RESOLUTION_ERRORS
    559         const char *s = "INET";
    560         if (domain == AF_PACKET) s = "PACKET";
    561         if (domain == AF_NETLINK) s = "NETLINK";
    562 USE_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
    563         bb_perror_msg_and_die("socket(AF_%s)", s);
    564 #else
    565         bb_perror_msg_and_die("socket");
    566 #endif
    567     }
    568 
    569     return r;
    570 }
    571 
    572 // Die with an error message if we can't bind a socket to an address.
    573 void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
    574 {
    575     if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
    576 }
    577 
    578 // Die with an error message if we can't listen for connections on a socket.
    579 void xlisten(int s, int backlog)
    580 {
    581     if (listen(s, backlog)) bb_perror_msg_and_die("listen");
    582 }
    583 
    584 /* Die with an error message if sendto failed.
    585  * Return bytes sent otherwise  */
    586 ssize_t xsendto(int s, const  void *buf, size_t len, const struct sockaddr *to,
    587                 socklen_t tolen)
    588 {
    589     ssize_t ret = sendto(s, buf, len, 0, to, tolen);
    590     if (ret < 0) {
    591         if (ENABLE_FEATURE_CLEAN_UP)
    592             close(s);
    593         bb_perror_msg_and_die("sendto");
    594     }
    595     return ret;
    596 }
    597 
    598 // xstat() - a stat() which dies on failure with meaningful error message
    599 void xstat(const char *name, struct stat *stat_buf)
    600 {
    601     if (stat(name, stat_buf))
    602         bb_perror_msg_and_die("can't stat '%s'", name);
    603 }
    604 
    605 // selinux_or_die() - die if SELinux is disabled.
    606 void selinux_or_die(void)
    607 {
    608 #if ENABLE_SELINUX
    609     int rc = is_selinux_enabled();
    610     if (rc == 0) {
    611         bb_error_msg_and_die("SELinux is disabled");
    612     } else if (rc < 0) {
    613         bb_error_msg_and_die("is_selinux_enabled() failed");
    614     }
    615 #else
    616     bb_error_msg_and_die("SELinux support is disabled");
    617 #endif
     216int FAST_FUNC bb_putchar_stderr(char ch)
     217{
     218    return write(STDERR_FILENO, &ch, 1);
     219}
     220
     221ssize_t FAST_FUNC full_write1_str(const char *str)
     222{
     223    return full_write(STDOUT_FILENO, str, strlen(str));
     224}
     225
     226ssize_t FAST_FUNC full_write2_str(const char *str)
     227{
     228    return full_write(STDERR_FILENO, str, strlen(str));
     229}
     230
     231static int wh_helper(int value, int def_val, const char *env_name, int *err)
     232{
     233    if (value == 0) {
     234        char *s = getenv(env_name);
     235        if (s) {
     236            value = atoi(s);
     237            /* If LINES/COLUMNS are set, pretent that there is
     238             * no error getting w/h, this prevents some ugly
     239             * cursor tricks by our callers */
     240            *err = 0;
     241        }
     242    }
     243    if (value <= 1 || value >= 30000)
     244        value = def_val;
     245    return value;
    618246}
    619247
    620248/* It is perfectly ok to pass in a NULL for either width or for
    621249 * height, in which case that value will not be set.  */
    622 int get_terminal_width_height(int fd, int *width, int *height)
    623 {
    624     struct winsize win = { 0, 0, 0, 0 };
    625     int ret = ioctl(fd, TIOCGWINSZ, &win);
    626 
    627     if (height) {
    628         if (!win.ws_row) {
    629             char *s = getenv("LINES");
    630             if (s) win.ws_row = atoi(s);
    631         }
    632         if (win.ws_row <= 1 || win.ws_row >= 30000)
    633             win.ws_row = 24;
    634         *height = (int) win.ws_row;
    635     }
    636 
    637     if (width) {
    638         if (!win.ws_col) {
    639             char *s = getenv("COLUMNS");
    640             if (s) win.ws_col = atoi(s);
    641         }
    642         if (win.ws_col <= 1 || win.ws_col >= 30000)
    643             win.ws_col = 80;
    644         *width = (int) win.ws_col;
    645     }
    646 
    647     return ret;
    648 }
    649 
    650 void ioctl_or_perror_and_die(int fd, int request, void *argp, const char *fmt,...)
    651 {
    652     va_list p;
    653 
    654     if (ioctl(fd, request, argp) < 0) {
    655         va_start(p, fmt);
    656         bb_verror_msg(fmt, p, strerror(errno));
    657         /* xfunc_die can actually longjmp, so be nice */
    658         va_end(p);
    659         xfunc_die();
    660     }
    661 }
    662 
    663 int ioctl_or_perror(int fd, int request, void *argp, const char *fmt,...)
    664 {
    665     va_list p;
    666     int ret = ioctl(fd, request, argp);
    667 
    668     if (ret < 0) {
    669         va_start(p, fmt);
    670         bb_verror_msg(fmt, p, strerror(errno));
    671         va_end(p);
    672     }
    673     return ret;
    674 }
    675 
    676 #if ENABLE_IOCTL_HEX2STR_ERROR
    677 int bb_ioctl_or_warn(int fd, int request, void *argp, const char *ioctl_name)
    678 {
    679     int ret;
    680 
    681     ret = ioctl(fd, request, argp);
    682     if (ret < 0)
    683         bb_perror_msg("%s", ioctl_name);
    684     return ret;
    685 }
    686 void bb_xioctl(int fd, int request, void *argp, const char *ioctl_name)
    687 {
    688     if (ioctl(fd, request, argp) < 0)
    689         bb_perror_msg_and_die("%s", ioctl_name);
    690 }
    691 #else
    692 int bb_ioctl_or_warn(int fd, int request, void *argp)
    693 {
    694     int ret;
    695 
    696     ret = ioctl(fd, request, argp);
    697     if (ret < 0)
    698         bb_perror_msg("ioctl %#x failed", request);
    699     return ret;
    700 }
    701 void bb_xioctl(int fd, int request, void *argp)
    702 {
    703     if (ioctl(fd, request, argp) < 0)
    704         bb_perror_msg_and_die("ioctl %#x failed", request);
    705 }
    706 #endif
     250int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
     251{
     252    struct winsize win;
     253    int err;
     254
     255    win.ws_row = 0;
     256    win.ws_col = 0;
     257    /* I've seen ioctl returning 0, but row/col is (still?) 0.
     258     * We treat that as an error too.  */
     259    err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0;
     260    if (height)
     261        *height = wh_helper(win.ws_row, 24, "LINES", &err);
     262    if (width)
     263        *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
     264    return err;
     265}
     266
     267int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
     268{
     269    return tcsetattr(STDIN_FILENO, TCSANOW, tp);
     270}
     271
     272pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
     273{
     274    pid_t r;
     275
     276    do
     277        r = waitpid(pid, wstat, options);
     278    while ((r == -1) && (errno == EINTR));
     279    return r;
     280}
     281
     282pid_t FAST_FUNC wait_any_nohang(int *wstat)
     283{
     284    return safe_waitpid(-1, wstat, WNOHANG);
     285}
     286
     287// Wait for the specified child PID to exit, returning child's error return.
     288int FAST_FUNC wait4pid(pid_t pid)
     289{
     290    int status;
     291
     292    if (pid <= 0) {
     293        /*errno = ECHILD; -- wrong. */
     294        /* we expect errno to be already set from failed [v]fork/exec */
     295        return -1;
     296    }
     297    if (safe_waitpid(pid, &status, 0) == -1)
     298        return -1;
     299    if (WIFEXITED(status))
     300        return WEXITSTATUS(status);
     301    if (WIFSIGNALED(status))
     302        return WTERMSIG(status) + 0x180;
     303    return 0;
     304}
Note: See TracChangeset for help on using the changeset viewer.