Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/libbb/xfuncs.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/libbb/xfuncs.c
r1765 r2725 5 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * Copyright (C) 2006 Rob Landley 7 * Copyright (C) 2006 Den is Vlasenko7 * Copyright (C) 2006 Denys Vlasenko 8 8 * 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. 10 10 */ 11 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 12 25 #include "libbb.h" 13 26 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 */ 28 int FAST_FUNC ndelay_on(int fd) 29 { 30 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 31 } 32 33 int FAST_FUNC ndelay_off(int fd) 34 { 35 return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); 36 } 37 38 int FAST_FUNC close_on_exec_on(int fd) 39 { 40 return fcntl(fd, F_SETFD, FD_CLOEXEC); 41 } 42 43 char* 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. 22 55 */ 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) 56 void BUG_sizeof(void); 57 char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen) 327 58 { 328 59 unsigned i, out, res; 329 if (sizeof(unsigned) != 4) 330 BUG_sizeof_unsigned_not_4(); 60 331 61 if (buflen) { 332 62 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) { 334 75 res = n / i; 76 n = n % i; 335 77 if (res || out || i == 1) { 336 if (!--buflen) break; 78 if (--buflen == 0) 79 break; 337 80 out++; 338 n -= res*i;339 81 *buf++ = '0' + res; 340 82 } … … 344 86 } 345 87 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() */ 89 char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen) 90 { 91 if (!buflen) 92 return buf; 93 if (n < 0) { 350 94 n = -n; 351 95 *buf++ = '-'; … … 358 102 // second time will overwrite previous results. 359 103 // 360 // The largest 32 bit integer is -2 billion plus null terminator, or12 bytes.361 // I nt should always be 32 bits on any remotely Unix-like system, see362 // 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 108 static char local_buf[sizeof(int) * 3]; 109 110 /* Convert unsigned integer to ascii using a static buffer (returned). */ 111 char* FAST_FUNC utoa(unsigned n) 112 { 113 *(utoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0'; 370 114 371 115 return local_buf; 372 116 } 373 117 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). */ 119 char* FAST_FUNC itoa(int n) 120 { 121 *(itoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0'; 378 122 379 123 return local_buf; 380 124 } 381 125 382 / / Emit a string of hex representation of bytes383 char *bin2hex(char *p, const char *cp, int count)126 /* Emit a string of hex representation of bytes */ 127 char* FAST_FUNC bin2hex(char *p, const char *cp, int count) 384 128 { 385 129 while (count) { … … 393 137 } 394 138 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 */ 140 char* 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 176 off_t FAST_FUNC fdlength(int fd) 411 177 { 412 178 off_t bottom = 0, top = 0, pos; … … 446 212 return pos + 1; 447 213 } 448 449 // Die with an error message if we can't malloc() enough space and do an450 // 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 1458 // GNU extension459 va_start(p, format);460 r = vasprintf(&string_ptr, format, p);461 va_end(p);462 #else463 // 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);471 214 #endif 472 215 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 216 int FAST_FUNC bb_putchar_stderr(char ch) 217 { 218 return write(STDERR_FILENO, &ch, 1); 219 } 220 221 ssize_t FAST_FUNC full_write1_str(const char *str) 222 { 223 return full_write(STDOUT_FILENO, str, strlen(str)); 224 } 225 226 ssize_t FAST_FUNC full_write2_str(const char *str) 227 { 228 return full_write(STDERR_FILENO, str, strlen(str)); 229 } 230 231 static 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; 618 246 } 619 247 620 248 /* It is perfectly ok to pass in a NULL for either width or for 621 249 * 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 250 int 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 267 int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) 268 { 269 return tcsetattr(STDIN_FILENO, TCSANOW, tp); 270 } 271 272 pid_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 282 pid_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. 288 int 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.