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 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. 55 */ 56void BUG_sizeof(void); 57char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen) 58{ 59 unsigned i, out, res; 60 61 if (buflen) { 62 out = 0; 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) { 75 res = n / i; 76 n = n % i; 77 if (res || out || i == 1) { 78 if (--buflen == 0) 79 break; 80 out++; 81 *buf++ = '0' + res; 82 } 83 } 84 } 85 return buf; 86} 87 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) { 94 n = -n; 95 *buf++ = '-'; 96 buflen--; 97 } 98 return utoa_to_buf((unsigned)n, buf, buflen); 99} 100 101// The following two functions use a static buffer, so calling either one a 102// second time will overwrite previous results. 103// 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'; 114 115 return local_buf; 116} 117 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'; 122 123 return local_buf; 124} 125 126/* Emit a string of hex representation of bytes */ 127char* FAST_FUNC bin2hex(char *p, const char *cp, int count) 128{ 129 while (count) { 130 unsigned char c = *cp++; 131 /* put lowercase hex digits */ 132 *p++ = 0x20 | bb_hexdigits_upcase[c >> 4]; 133 *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf]; 134 count--; 135 } 136 return p; 137} 138 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) 177{ 178 off_t bottom = 0, top = 0, pos; 179 long size; 180 181 // If the ioctl works for this, return it. 182 183 if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512; 184 185 // FIXME: explain why lseek(SEEK_END) is not used here! 186 187 // If not, do a binary search for the last location we can read. (Some 188 // block devices don't do BLKGETSIZE right.) 189 190 do { 191 char temp; 192 193 pos = bottom + (top - bottom) / 2; 194 195 // If we can read from the current location, it's bigger. 196 197 if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) { 198 if (bottom == top) bottom = top = (top+1) * 2; 199 else bottom = pos; 200 201 // If we can't, it's smaller. 202 203 } else { 204 if (bottom == top) { 205 if (!top) return 0; 206 bottom = top/2; 207 } 208 else top = pos; 209 } 210 } while (bottom + 1 != top); 211 212 return pos + 1; 213} 214#endif 215 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; 246} 247 248/* It is perfectly ok to pass in a NULL for either width or for 249 * height, in which case that value will not be set. */ 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} 305 306char * FAST_FUNC unparse_uuid(const uint8_t *uu, char *out) 307{ 308 char uuid_string[32]; 309 310 bin2hex(uuid_string, (char *)uu, 16); 311 /* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */ 312 sprintf(out, "%.8s-%.4s-%.4s-%.4s-%.12s", 313 uuid_string, 314 uuid_string+8, 315 uuid_string+8+4, 316 uuid_string+8+4+4, 317 uuid_string+8+4+4+4 318 ); 319 return out; 320} 321 322static unsigned char fromhex(char c) 323{ 324 if (isdigit(c)) 325 return (c - '0'); 326 return ((c|0x20) - 'a' + 10); 327} 328 329/* Parse & verify UUID string */ 330int FAST_FUNC parse_uuid(const char *s, uint8_t *uuid) 331{ 332 int i; 333 334 if (strlen(s) != 36 || s[8] != '-' || s[13] != '-' 335 || s[18] != '-' || s[23] != '-' 336 ) { 337 return -1; 338 } 339 for (i = 0; i < 16; i++) { 340 if (*s == '-') 341 s++; 342 if (!isxdigit(s[0]) || !isxdigit(s[1])) 343 return -2; 344 uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1])); 345 s += 2; 346 } 347 348 return 0; 349} 350 351