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 GPL version 2, see file LICENSE in this tarball for details.
  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 */
  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/* Convert unsigned long long value into compact 4-char
  52 * representation. Examples: "1234", "1.2k", " 27M", "123T"
  53 * String is not terminated (buf[4] is untouched) */
  54void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale)
  55{
  56        const char *fmt;
  57        char c;
  58        unsigned v, u, idx = 0;
  59
  60        if (ul > 9999) { // do not scale if 9999 or less
  61                ul *= 10;
  62                do {
  63                        ul /= 1024;
  64                        idx++;
  65                } while (ul >= 10000);
  66        }
  67        v = ul; // ullong divisions are expensive, avoid them
  68
  69        fmt = " 123456789";
  70        u = v / 10;
  71        v = v % 10;
  72        if (!idx) {
  73                // 9999 or less: use "1234" format
  74                // u is value/10, v is last digit
  75                c = buf[0] = " 123456789"[u/100];
  76                if (c != ' ') fmt = "0123456789";
  77                c = buf[1] = fmt[u/10%10];
  78                if (c != ' ') fmt = "0123456789";
  79                buf[2] = fmt[u%10];
  80                buf[3] = "0123456789"[v];
  81        } else {
  82                // u is value, v is 1/10ths (allows for 9.2M format)
  83                if (u >= 10) {
  84                        // value is >= 10: use "123M', " 12M" formats
  85                        c = buf[0] = " 123456789"[u/100];
  86                        if (c != ' ') fmt = "0123456789";
  87                        v = u % 10;
  88                        u = u / 10;
  89                        buf[1] = fmt[u%10];
  90                } else {
  91                        // value is < 10: use "9.2M" format
  92                        buf[0] = "0123456789"[u];
  93                        buf[1] = '.';
  94                }
  95                buf[2] = "0123456789"[v];
  96                buf[3] = scale[idx]; /* typically scale = " kmgt..." */
  97        }
  98}
  99
 100/* Convert unsigned long long value into compact 5-char representation.
 101 * String is not terminated (buf[5] is untouched) */
 102void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[6], const char *scale)
 103{
 104        const char *fmt;
 105        char c;
 106        unsigned v, u, idx = 0;
 107
 108        if (ul > 99999) { // do not scale if 99999 or less
 109                ul *= 10;
 110                do {
 111                        ul /= 1024;
 112                        idx++;
 113                } while (ul >= 100000);
 114        }
 115        v = ul; // ullong divisions are expensive, avoid them
 116
 117        fmt = " 123456789";
 118        u = v / 10;
 119        v = v % 10;
 120        if (!idx) {
 121                // 99999 or less: use "12345" format
 122                // u is value/10, v is last digit
 123                c = buf[0] = " 123456789"[u/1000];
 124                if (c != ' ') fmt = "0123456789";
 125                c = buf[1] = fmt[u/100%10];
 126                if (c != ' ') fmt = "0123456789";
 127                c = buf[2] = fmt[u/10%10];
 128                if (c != ' ') fmt = "0123456789";
 129                buf[3] = fmt[u%10];
 130                buf[4] = "0123456789"[v];
 131        } else {
 132                // value has been scaled into 0..9999.9 range
 133                // u is value, v is 1/10ths (allows for 92.1M format)
 134                if (u >= 100) {
 135                        // value is >= 100: use "1234M', " 123M" formats
 136                        c = buf[0] = " 123456789"[u/1000];
 137                        if (c != ' ') fmt = "0123456789";
 138                        c = buf[1] = fmt[u/100%10];
 139                        if (c != ' ') fmt = "0123456789";
 140                        v = u % 10;
 141                        u = u / 10;
 142                        buf[2] = fmt[u%10];
 143                } else {
 144                        // value is < 100: use "92.1M" format
 145                        c = buf[0] = " 123456789"[u/10];
 146                        if (c != ' ') fmt = "0123456789";
 147                        buf[1] = fmt[u%10];
 148                        buf[2] = '.';
 149                }
 150                buf[3] = "0123456789"[v];
 151                buf[4] = scale[idx]; /* typically scale = " kmgt..." */
 152        }
 153}
 154
 155
 156// Convert unsigned integer to ascii, writing into supplied buffer.
 157// A truncated result contains the first few digits of the result ala strncpy.
 158// Returns a pointer past last generated digit, does _not_ store NUL.
 159void BUG_sizeof_unsigned_not_4(void);
 160char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
 161{
 162        unsigned i, out, res;
 163        if (sizeof(unsigned) != 4)
 164                BUG_sizeof_unsigned_not_4();
 165        if (buflen) {
 166                out = 0;
 167                for (i = 1000000000; i; i /= 10) {
 168                        res = n / i;
 169                        if (res || out || i == 1) {
 170                                if (!--buflen) break;
 171                                out++;
 172                                n -= res*i;
 173                                *buf++ = '0' + res;
 174                        }
 175                }
 176        }
 177        return buf;
 178}
 179
 180/* Convert signed integer to ascii, like utoa_to_buf() */
 181char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
 182{
 183        if (buflen && n < 0) {
 184                n = -n;
 185                *buf++ = '-';
 186                buflen--;
 187        }
 188        return utoa_to_buf((unsigned)n, buf, buflen);
 189}
 190
 191// The following two functions use a static buffer, so calling either one a
 192// second time will overwrite previous results.
 193//
 194// The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
 195// It so happens that sizeof(int) * 3 is enough for 32+ bits.
 196// (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
 197
 198static char local_buf[sizeof(int) * 3];
 199
 200// Convert unsigned integer to ascii using a static buffer (returned).
 201char* FAST_FUNC utoa(unsigned n)
 202{
 203        *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
 204
 205        return local_buf;
 206}
 207
 208/* Convert signed integer to ascii using a static buffer (returned). */
 209char* FAST_FUNC itoa(int n)
 210{
 211        *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
 212
 213        return local_buf;
 214}
 215
 216/* Emit a string of hex representation of bytes */
 217char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
 218{
 219        while (count) {
 220                unsigned char c = *cp++;
 221                /* put lowercase hex digits */
 222                *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
 223                *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
 224                count--;
 225        }
 226        return p;
 227}
 228
 229/* Return how long the file at fd is, if there's any way to determine it. */
 230#ifdef UNUSED
 231off_t FAST_FUNC fdlength(int fd)
 232{
 233        off_t bottom = 0, top = 0, pos;
 234        long size;
 235
 236        // If the ioctl works for this, return it.
 237
 238        if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
 239
 240        // FIXME: explain why lseek(SEEK_END) is not used here!
 241
 242        // If not, do a binary search for the last location we can read.  (Some
 243        // block devices don't do BLKGETSIZE right.)
 244
 245        do {
 246                char temp;
 247
 248                pos = bottom + (top - bottom) / 2;
 249
 250                // If we can read from the current location, it's bigger.
 251
 252                if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
 253                        if (bottom == top) bottom = top = (top+1) * 2;
 254                        else bottom = pos;
 255
 256                // If we can't, it's smaller.
 257
 258                } else {
 259                        if (bottom == top) {
 260                                if (!top) return 0;
 261                                bottom = top/2;
 262                        }
 263                        else top = pos;
 264                }
 265        } while (bottom + 1 != top);
 266
 267        return pos + 1;
 268}
 269#endif
 270
 271char* FAST_FUNC xmalloc_ttyname(int fd)
 272{
 273        char *buf = xzalloc(128);
 274        int r = ttyname_r(fd, buf, 127);
 275        if (r) {
 276                free(buf);
 277                buf = NULL;
 278        }
 279        return buf;
 280}
 281
 282/* It is perfectly ok to pass in a NULL for either width or for
 283 * height, in which case that value will not be set.  */
 284int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
 285{
 286        struct winsize win = { 0, 0, 0, 0 };
 287        int ret = ioctl(fd, TIOCGWINSZ, &win);
 288
 289        if (height) {
 290                if (!win.ws_row) {
 291                        char *s = getenv("LINES");
 292                        if (s) win.ws_row = atoi(s);
 293                }
 294                if (win.ws_row <= 1 || win.ws_row >= 30000)
 295                        win.ws_row = 24;
 296                *height = (int) win.ws_row;
 297        }
 298
 299        if (width) {
 300                if (!win.ws_col) {
 301                        char *s = getenv("COLUMNS");
 302                        if (s) win.ws_col = atoi(s);
 303                }
 304                if (win.ws_col <= 1 || win.ws_col >= 30000)
 305                        win.ws_col = 80;
 306                *width = (int) win.ws_col;
 307        }
 308
 309        return ret;
 310}
 311
 312int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
 313{
 314        return tcsetattr(STDIN_FILENO, TCSANOW, tp);
 315}
 316