busybox/libbb/xfuncs.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Utility routines.
   4 *
   5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
   6 * Copyright (C) 2006 Rob Landley
   7 * Copyright (C) 2006 Denys Vlasenko
   8 *
   9 * Licensed under GPLv2, see file LICENSE in this source tree.
  10 */
  11
  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
  25#include "libbb.h"
  26
  27/* Turn on nonblocking I/O on a fd */
  28void FAST_FUNC ndelay_on(int fd)
  29{
  30        int flags = fcntl(fd, F_GETFL);
  31        if (flags & O_NONBLOCK)
  32                return;
  33        fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  34}
  35
  36void FAST_FUNC ndelay_off(int fd)
  37{
  38        int flags = fcntl(fd, F_GETFL);
  39        if (!(flags & O_NONBLOCK))
  40                return;
  41        fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
  42}
  43
  44void FAST_FUNC close_on_exec_on(int fd)
  45{
  46        fcntl(fd, F_SETFD, FD_CLOEXEC);
  47}
  48
  49char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src)
  50{
  51#ifndef IFNAMSIZ
  52        enum { IFNAMSIZ = 16 };
  53#endif
  54        return strncpy(dst, src, IFNAMSIZ);
  55}
  56
  57
  58/* Convert unsigned integer to ascii, writing into supplied buffer.
  59 * A truncated result contains the first few digits of the result ala strncpy.
  60 * Returns a pointer past last generated digit, does _not_ store NUL.
  61 */
  62void BUG_sizeof(void);
  63char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
  64{
  65        unsigned i, out, res;
  66
  67        if (buflen) {
  68                out = 0;
  69                if (sizeof(n) == 4)
  70                // 2^32-1 = 4294967295
  71                        i = 1000000000;
  72#if UINT_MAX > 4294967295 /* prevents warning about "const too large" */
  73                else
  74                if (sizeof(n) == 8)
  75                // 2^64-1 = 18446744073709551615
  76                        i = 10000000000000000000;
  77#endif
  78                else
  79                        BUG_sizeof();
  80                for (; i; i /= 10) {
  81                        res = n / i;
  82                        n = n % i;
  83                        if (res || out || i == 1) {
  84                                if (--buflen == 0)
  85                                        break;
  86                                out++;
  87                                *buf++ = '0' + res;
  88                        }
  89                }
  90        }
  91        return buf;
  92}
  93
  94/* Convert signed integer to ascii, like utoa_to_buf() */
  95char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
  96{
  97        if (!buflen)
  98                return buf;
  99        if (n < 0) {
 100                n = -n;
 101                *buf++ = '-';
 102                buflen--;
 103        }
 104        return utoa_to_buf((unsigned)n, buf, buflen);
 105}
 106
 107// The following two functions use a static buffer, so calling either one a
 108// second time will overwrite previous results.
 109//
 110// The largest 32 bit integer is -2 billion plus NUL, or 1+10+1=12 bytes.
 111// It so happens that sizeof(int) * 3 is enough for 32+ bit ints.
 112// (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
 113
 114static char local_buf[sizeof(int) * 3];
 115
 116/* Convert unsigned integer to ascii using a static buffer (returned). */
 117char* FAST_FUNC utoa(unsigned n)
 118{
 119        *(utoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
 120
 121        return local_buf;
 122}
 123
 124/* Convert signed integer to ascii using a static buffer (returned). */
 125char* FAST_FUNC itoa(int n)
 126{
 127        *(itoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
 128
 129        return local_buf;
 130}
 131
 132/* Emit a string of hex representation of bytes */
 133char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
 134{
 135        while (count) {
 136                unsigned char c = *cp++;
 137                /* put lowercase hex digits */
 138                *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
 139                *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
 140                count--;
 141        }
 142        return p;
 143}
 144
 145/* Convert "[x]x[:][x]x[:][x]x[:][x]x" hex string to binary, no more than COUNT bytes */
 146char* FAST_FUNC hex2bin(char *dst, const char *str, int count)
 147{
 148        errno = EINVAL;
 149        while (*str && count) {
 150                uint8_t val;
 151                uint8_t c = *str++;
 152                if (isdigit(c))
 153                        val = c - '0';
 154                else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
 155                        val = (c|0x20) - ('a' - 10);
 156                else
 157                        return NULL;
 158                val <<= 4;
 159                c = *str;
 160                if (isdigit(c))
 161                        val |= c - '0';
 162                else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
 163                        val |= (c|0x20) - ('a' - 10);
 164                else if (c == ':' || c == '\0')
 165                        val >>= 4;
 166                else
 167                        return NULL;
 168
 169                *dst++ = val;
 170                if (c != '\0')
 171                        str++;
 172                if (*str == ':')
 173                        str++;
 174                count--;
 175        }
 176        errno = (*str ? ERANGE : 0);
 177        return dst;
 178}
 179
 180/* Return how long the file at fd is, if there's any way to determine it. */
 181#ifdef UNUSED
 182off_t FAST_FUNC fdlength(int fd)
 183{
 184        off_t bottom = 0, top = 0, pos;
 185        long size;
 186
 187        // If the ioctl works for this, return it.
 188
 189        if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
 190
 191        // FIXME: explain why lseek(SEEK_END) is not used here!
 192
 193        // If not, do a binary search for the last location we can read.  (Some
 194        // block devices don't do BLKGETSIZE right.)
 195
 196        do {
 197                char temp;
 198
 199                pos = bottom + (top - bottom) / 2;
 200
 201                // If we can read from the current location, it's bigger.
 202
 203                if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
 204                        if (bottom == top) bottom = top = (top+1) * 2;
 205                        else bottom = pos;
 206
 207                // If we can't, it's smaller.
 208
 209                } else {
 210                        if (bottom == top) {
 211                                if (!top) return 0;
 212                                bottom = top/2;
 213                        }
 214                        else top = pos;
 215                }
 216        } while (bottom + 1 != top);
 217
 218        return pos + 1;
 219}
 220#endif
 221
 222int FAST_FUNC bb_putchar_stderr(char ch)
 223{
 224        return write(STDERR_FILENO, &ch, 1);
 225}
 226
 227ssize_t FAST_FUNC full_write1_str(const char *str)
 228{
 229        return full_write(STDOUT_FILENO, str, strlen(str));
 230}
 231
 232ssize_t FAST_FUNC full_write2_str(const char *str)
 233{
 234        return full_write(STDERR_FILENO, str, strlen(str));
 235}
 236
 237static int wh_helper(int value, int def_val, const char *env_name, int *err)
 238{
 239        if (value == 0) {
 240                char *s = getenv(env_name);
 241                if (s) {
 242                        value = atoi(s);
 243                        /* If LINES/COLUMNS are set, pretend that there is
 244                         * no error getting w/h, this prevents some ugly
 245                         * cursor tricks by our callers */
 246                        *err = 0;
 247                }
 248        }
 249        if (value <= 1 || value >= 30000)
 250                value = def_val;
 251        return value;
 252}
 253
 254/* It is perfectly ok to pass in a NULL for either width or for
 255 * height, in which case that value will not be set.  */
 256int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
 257{
 258        struct winsize win;
 259        int err;
 260
 261        win.ws_row = 0;
 262        win.ws_col = 0;
 263        /* I've seen ioctl returning 0, but row/col is (still?) 0.
 264         * We treat that as an error too.  */
 265        err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0;
 266        if (height)
 267                *height = wh_helper(win.ws_row, 24, "LINES", &err);
 268        if (width)
 269                *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
 270        return err;
 271}
 272
 273int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
 274{
 275        return tcsetattr(STDIN_FILENO, TCSANOW, tp);
 276}
 277
 278pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
 279{
 280        pid_t r;
 281
 282        do
 283                r = waitpid(pid, wstat, options);
 284        while ((r == -1) && (errno == EINTR));
 285        return r;
 286}
 287
 288pid_t FAST_FUNC wait_any_nohang(int *wstat)
 289{
 290        return safe_waitpid(-1, wstat, WNOHANG);
 291}
 292
 293// Wait for the specified child PID to exit, returning child's error return.
 294int FAST_FUNC wait4pid(pid_t pid)
 295{
 296        int status;
 297
 298        if (pid <= 0) {
 299                /*errno = ECHILD; -- wrong. */
 300                /* we expect errno to be already set from failed [v]fork/exec */
 301                return -1;
 302        }
 303        if (safe_waitpid(pid, &status, 0) == -1)
 304                return -1;
 305        if (WIFEXITED(status))
 306                return WEXITSTATUS(status);
 307        if (WIFSIGNALED(status))
 308                return WTERMSIG(status) + 0x180;
 309        return 0;
 310}
 311