xfuncs.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  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. #include "libbb.h"
  12. /* All the functions starting with "x" call bb_error_msg_and_die() if they
  13. * fail, so callers never need to check for errors. If it returned, it
  14. * succeeded. */
  15. #ifndef DMALLOC
  16. /* dmalloc provides variants of these that do abort() on failure.
  17. * Since dmalloc's prototypes overwrite the impls here as they are
  18. * included after these prototypes in libbb.h, all is well.
  19. */
  20. // Warn if we can't allocate size bytes of memory.
  21. void *malloc_or_warn(size_t size)
  22. {
  23. void *ptr = malloc(size);
  24. if (ptr == NULL && size != 0)
  25. bb_error_msg(bb_msg_memory_exhausted);
  26. return ptr;
  27. }
  28. // Die if we can't allocate size bytes of memory.
  29. void *xmalloc(size_t size)
  30. {
  31. void *ptr = malloc(size);
  32. if (ptr == NULL && size != 0)
  33. bb_error_msg_and_die(bb_msg_memory_exhausted);
  34. return ptr;
  35. }
  36. // Die if we can't resize previously allocated memory. (This returns a pointer
  37. // to the new memory, which may or may not be the same as the old memory.
  38. // It'll copy the contents to a new chunk and free the old one if necessary.)
  39. void *xrealloc(void *ptr, size_t size)
  40. {
  41. ptr = realloc(ptr, size);
  42. if (ptr == NULL && size != 0)
  43. bb_error_msg_and_die(bb_msg_memory_exhausted);
  44. return ptr;
  45. }
  46. #endif /* DMALLOC */
  47. // Die if we can't allocate and zero size bytes of memory.
  48. void *xzalloc(size_t size)
  49. {
  50. void *ptr = xmalloc(size);
  51. memset(ptr, 0, size);
  52. return ptr;
  53. }
  54. // Die if we can't copy a string to freshly allocated memory.
  55. char * xstrdup(const char *s)
  56. {
  57. char *t;
  58. if (s == NULL)
  59. return NULL;
  60. t = strdup(s);
  61. if (t == NULL)
  62. bb_error_msg_and_die(bb_msg_memory_exhausted);
  63. return t;
  64. }
  65. // Die if we can't allocate n+1 bytes (space for the null terminator) and copy
  66. // the (possibly truncated to length n) string into it.
  67. char *xstrndup(const char *s, int n)
  68. {
  69. int m;
  70. char *t;
  71. if (ENABLE_DEBUG && s == NULL)
  72. bb_error_msg_and_die("xstrndup bug");
  73. /* We can just xmalloc(n+1) and strncpy into it, */
  74. /* but think about xstrndup("abc", 10000) wastage! */
  75. m = n;
  76. t = (char*) s;
  77. while (m) {
  78. if (!*t) break;
  79. m--;
  80. t++;
  81. }
  82. n -= m;
  83. t = xmalloc(n + 1);
  84. t[n] = '\0';
  85. return memcpy(t, s, n);
  86. }
  87. // Die if we can't open a file and return a FILE * to it.
  88. // Notice we haven't got xfread(), This is for use with fscanf() and friends.
  89. FILE *xfopen(const char *path, const char *mode)
  90. {
  91. FILE *fp = fopen(path, mode);
  92. if (fp == NULL)
  93. bb_perror_msg_and_die("can't open '%s'", path);
  94. return fp;
  95. }
  96. // Die if we can't open a file and return a fd.
  97. int xopen3(const char *pathname, int flags, int mode)
  98. {
  99. int ret;
  100. ret = open(pathname, flags, mode);
  101. if (ret < 0) {
  102. bb_perror_msg_and_die("can't open '%s'", pathname);
  103. }
  104. return ret;
  105. }
  106. // Die if we can't open an existing file and return a fd.
  107. int xopen(const char *pathname, int flags)
  108. {
  109. return xopen3(pathname, flags, 0666);
  110. }
  111. // Warn if we can't open a file and return a fd.
  112. int open3_or_warn(const char *pathname, int flags, int mode)
  113. {
  114. int ret;
  115. ret = open(pathname, flags, mode);
  116. if (ret < 0) {
  117. bb_perror_msg("can't open '%s'", pathname);
  118. }
  119. return ret;
  120. }
  121. // Warn if we can't open a file and return a fd.
  122. int open_or_warn(const char *pathname, int flags)
  123. {
  124. return open3_or_warn(pathname, flags, 0666);
  125. }
  126. void xunlink(const char *pathname)
  127. {
  128. if (unlink(pathname))
  129. bb_perror_msg_and_die("can't remove file '%s'", pathname);
  130. }
  131. void xrename(const char *oldpath, const char *newpath)
  132. {
  133. if (rename(oldpath, newpath))
  134. bb_perror_msg_and_die("can't move '%s' to '%s'", oldpath, newpath);
  135. }
  136. int rename_or_warn(const char *oldpath, const char *newpath)
  137. {
  138. int n = rename(oldpath, newpath);
  139. if (n)
  140. bb_perror_msg("can't move '%s' to '%s'", oldpath, newpath);
  141. return n;
  142. }
  143. void xpipe(int filedes[2])
  144. {
  145. if (pipe(filedes))
  146. bb_perror_msg_and_die("can't create pipe");
  147. }
  148. // Turn on nonblocking I/O on a fd
  149. int ndelay_on(int fd)
  150. {
  151. return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);
  152. }
  153. int close_on_exec_on(int fd)
  154. {
  155. return fcntl(fd, F_SETFD, FD_CLOEXEC);
  156. }
  157. int ndelay_off(int fd)
  158. {
  159. return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK);
  160. }
  161. void xdup2(int from, int to)
  162. {
  163. if (dup2(from, to) != to)
  164. bb_perror_msg_and_die("can't duplicate file descriptor");
  165. }
  166. // "Renumber" opened fd
  167. void xmove_fd(int from, int to)
  168. {
  169. if (from == to)
  170. return;
  171. xdup2(from, to);
  172. close(from);
  173. }
  174. // Die with an error message if we can't write the entire buffer.
  175. void xwrite(int fd, const void *buf, size_t count)
  176. {
  177. if (count) {
  178. ssize_t size = full_write(fd, buf, count);
  179. if (size != count)
  180. bb_error_msg_and_die("short write");
  181. }
  182. }
  183. // Die with an error message if we can't lseek to the right spot.
  184. off_t xlseek(int fd, off_t offset, int whence)
  185. {
  186. off_t off = lseek(fd, offset, whence);
  187. if (off == (off_t)-1) {
  188. if (whence == SEEK_SET)
  189. bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);
  190. bb_perror_msg_and_die("lseek");
  191. }
  192. return off;
  193. }
  194. // Die with supplied filename if this FILE * has ferror set.
  195. void die_if_ferror(FILE *fp, const char *fn)
  196. {
  197. if (ferror(fp)) {
  198. /* ferror doesn't set useful errno */
  199. bb_error_msg_and_die("%s: I/O error", fn);
  200. }
  201. }
  202. // Die with an error message if stdout has ferror set.
  203. void die_if_ferror_stdout(void)
  204. {
  205. die_if_ferror(stdout, bb_msg_standard_output);
  206. }
  207. // Die with an error message if we have trouble flushing stdout.
  208. void xfflush_stdout(void)
  209. {
  210. if (fflush(stdout)) {
  211. bb_perror_msg_and_die(bb_msg_standard_output);
  212. }
  213. }
  214. void xsetenv(const char *key, const char *value)
  215. {
  216. if (setenv(key, value, 1))
  217. bb_error_msg_and_die(bb_msg_memory_exhausted);
  218. }
  219. /* Converts unsigned long long value into compact 4-char
  220. * representation. Examples: "1234", "1.2k", " 27M", "123T"
  221. * String is not terminated (buf[4] is untouched) */
  222. void smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale)
  223. {
  224. const char *fmt;
  225. char c;
  226. unsigned v, u, idx = 0;
  227. if (ul > 9999) { // do not scale if 9999 or less
  228. ul *= 10;
  229. do {
  230. ul /= 1024;
  231. idx++;
  232. } while (ul >= 10000);
  233. }
  234. v = ul; // ullong divisions are expensive, avoid them
  235. fmt = " 123456789";
  236. u = v / 10;
  237. v = v % 10;
  238. if (!idx) {
  239. // 9999 or less: use "1234" format
  240. // u is value/10, v is last digit
  241. c = buf[0] = " 123456789"[u/100];
  242. if (c != ' ') fmt = "0123456789";
  243. c = buf[1] = fmt[u/10%10];
  244. if (c != ' ') fmt = "0123456789";
  245. buf[2] = fmt[u%10];
  246. buf[3] = "0123456789"[v];
  247. } else {
  248. // u is value, v is 1/10ths (allows for 9.2M format)
  249. if (u >= 10) {
  250. // value is >= 10: use "123M', " 12M" formats
  251. c = buf[0] = " 123456789"[u/100];
  252. if (c != ' ') fmt = "0123456789";
  253. v = u % 10;
  254. u = u / 10;
  255. buf[1] = fmt[u%10];
  256. } else {
  257. // value is < 10: use "9.2M" format
  258. buf[0] = "0123456789"[u];
  259. buf[1] = '.';
  260. }
  261. buf[2] = "0123456789"[v];
  262. buf[3] = scale[idx]; /* typically scale = " kmgt..." */
  263. }
  264. }
  265. /* Converts unsigned long long value into compact 5-char representation.
  266. * String is not terminated (buf[5] is untouched) */
  267. void smart_ulltoa5(unsigned long long ul, char buf[6], const char *scale)
  268. {
  269. const char *fmt;
  270. char c;
  271. unsigned v, u, idx = 0;
  272. if (ul > 99999) { // do not scale if 99999 or less
  273. ul *= 10;
  274. do {
  275. ul /= 1024;
  276. idx++;
  277. } while (ul >= 100000);
  278. }
  279. v = ul; // ullong divisions are expensive, avoid them
  280. fmt = " 123456789";
  281. u = v / 10;
  282. v = v % 10;
  283. if (!idx) {
  284. // 99999 or less: use "12345" format
  285. // u is value/10, v is last digit
  286. c = buf[0] = " 123456789"[u/1000];
  287. if (c != ' ') fmt = "0123456789";
  288. c = buf[1] = fmt[u/100%10];
  289. if (c != ' ') fmt = "0123456789";
  290. c = buf[2] = fmt[u/10%10];
  291. if (c != ' ') fmt = "0123456789";
  292. buf[3] = fmt[u%10];
  293. buf[4] = "0123456789"[v];
  294. } else {
  295. // value has been scaled into 0..9999.9 range
  296. // u is value, v is 1/10ths (allows for 92.1M format)
  297. if (u >= 100) {
  298. // value is >= 100: use "1234M', " 123M" formats
  299. c = buf[0] = " 123456789"[u/1000];
  300. if (c != ' ') fmt = "0123456789";
  301. c = buf[1] = fmt[u/100%10];
  302. if (c != ' ') fmt = "0123456789";
  303. v = u % 10;
  304. u = u / 10;
  305. buf[2] = fmt[u%10];
  306. } else {
  307. // value is < 100: use "92.1M" format
  308. c = buf[0] = " 123456789"[u/10];
  309. if (c != ' ') fmt = "0123456789";
  310. buf[1] = fmt[u%10];
  311. buf[2] = '.';
  312. }
  313. buf[3] = "0123456789"[v];
  314. buf[4] = scale[idx]; /* typically scale = " kmgt..." */
  315. }
  316. }
  317. // Convert unsigned integer to ascii, writing into supplied buffer.
  318. // A truncated result contains the first few digits of the result ala strncpy.
  319. // Returns a pointer past last generated digit, does _not_ store NUL.
  320. void BUG_sizeof_unsigned_not_4(void);
  321. char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
  322. {
  323. unsigned i, out, res;
  324. if (sizeof(unsigned) != 4)
  325. BUG_sizeof_unsigned_not_4();
  326. if (buflen) {
  327. out = 0;
  328. for (i = 1000000000; i; i /= 10) {
  329. res = n / i;
  330. if (res || out || i == 1) {
  331. if (!--buflen) break;
  332. out++;
  333. n -= res*i;
  334. *buf++ = '0' + res;
  335. }
  336. }
  337. }
  338. return buf;
  339. }
  340. // Convert signed integer to ascii, like utoa_to_buf()
  341. char *itoa_to_buf(int n, char *buf, unsigned buflen)
  342. {
  343. if (buflen && n<0) {
  344. n = -n;
  345. *buf++ = '-';
  346. buflen--;
  347. }
  348. return utoa_to_buf((unsigned)n, buf, buflen);
  349. }
  350. // The following two functions use a static buffer, so calling either one a
  351. // second time will overwrite previous results.
  352. //
  353. // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
  354. // Int should always be 32 bits on any remotely Unix-like system, see
  355. // http://www.unix.org/whitepapers/64bit.html for the reasons why.
  356. static char local_buf[12];
  357. // Convert unsigned integer to ascii using a static buffer (returned).
  358. char *utoa(unsigned n)
  359. {
  360. *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
  361. return local_buf;
  362. }
  363. // Convert signed integer to ascii using a static buffer (returned).
  364. char *itoa(int n)
  365. {
  366. *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
  367. return local_buf;
  368. }
  369. // Emit a string of hex representation of bytes
  370. char *bin2hex(char *p, const char *cp, int count)
  371. {
  372. while (count) {
  373. unsigned char c = *cp++;
  374. /* put lowercase hex digits */
  375. *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
  376. *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
  377. count--;
  378. }
  379. return p;
  380. }
  381. // Die with an error message if we can't set gid. (Because resource limits may
  382. // limit this user to a given number of processes, and if that fills up the
  383. // setgid() will fail and we'll _still_be_root_, which is bad.)
  384. void xsetgid(gid_t gid)
  385. {
  386. if (setgid(gid)) bb_perror_msg_and_die("setgid");
  387. }
  388. // Die with an error message if we can't set uid. (See xsetgid() for why.)
  389. void xsetuid(uid_t uid)
  390. {
  391. if (setuid(uid)) bb_perror_msg_and_die("setuid");
  392. }
  393. // Return how long the file at fd is, if there's any way to determine it.
  394. #ifdef UNUSED
  395. off_t fdlength(int fd)
  396. {
  397. off_t bottom = 0, top = 0, pos;
  398. long size;
  399. // If the ioctl works for this, return it.
  400. if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
  401. // FIXME: explain why lseek(SEEK_END) is not used here!
  402. // If not, do a binary search for the last location we can read. (Some
  403. // block devices don't do BLKGETSIZE right.)
  404. do {
  405. char temp;
  406. pos = bottom + (top - bottom) / 2;
  407. // If we can read from the current location, it's bigger.
  408. if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
  409. if (bottom == top) bottom = top = (top+1) * 2;
  410. else bottom = pos;
  411. // If we can't, it's smaller.
  412. } else {
  413. if (bottom == top) {
  414. if (!top) return 0;
  415. bottom = top/2;
  416. }
  417. else top = pos;
  418. }
  419. } while (bottom + 1 != top);
  420. return pos + 1;
  421. }
  422. #endif
  423. int bb_putchar(int ch)
  424. {
  425. /* time.c needs putc(ch, stdout), not putchar(ch).
  426. * it does "stdout = stderr;", but then glibc's putchar()
  427. * doesn't work as expected. bad glibc, bad */
  428. return putc(ch, stdout);
  429. }
  430. // Die with an error message if we can't malloc() enough space and do an
  431. // sprintf() into that space.
  432. char *xasprintf(const char *format, ...)
  433. {
  434. va_list p;
  435. int r;
  436. char *string_ptr;
  437. #if 1
  438. // GNU extension
  439. va_start(p, format);
  440. r = vasprintf(&string_ptr, format, p);
  441. va_end(p);
  442. #else
  443. // Bloat for systems that haven't got the GNU extension.
  444. va_start(p, format);
  445. r = vsnprintf(NULL, 0, format, p);
  446. va_end(p);
  447. string_ptr = xmalloc(r+1);
  448. va_start(p, format);
  449. r = vsnprintf(string_ptr, r+1, format, p);
  450. va_end(p);
  451. #endif
  452. if (r < 0)
  453. bb_error_msg_and_die(bb_msg_memory_exhausted);
  454. return string_ptr;
  455. }
  456. #if 0 /* If we will ever meet a libc which hasn't [f]dprintf... */
  457. int fdprintf(int fd, const char *format, ...)
  458. {
  459. va_list p;
  460. int r;
  461. char *string_ptr;
  462. #if 1
  463. // GNU extension
  464. va_start(p, format);
  465. r = vasprintf(&string_ptr, format, p);
  466. va_end(p);
  467. #else
  468. // Bloat for systems that haven't got the GNU extension.
  469. va_start(p, format);
  470. r = vsnprintf(NULL, 0, format, p) + 1;
  471. va_end(p);
  472. string_ptr = malloc(r);
  473. if (string_ptr) {
  474. va_start(p, format);
  475. r = vsnprintf(string_ptr, r, format, p);
  476. va_end(p);
  477. }
  478. #endif
  479. if (r >= 0) {
  480. full_write(fd, string_ptr, r);
  481. free(string_ptr);
  482. }
  483. return r;
  484. }
  485. #endif
  486. // Die with an error message if we can't copy an entire FILE * to stdout, then
  487. // close that file.
  488. void xprint_and_close_file(FILE *file)
  489. {
  490. fflush(stdout);
  491. // copyfd outputs error messages for us.
  492. if (bb_copyfd_eof(fileno(file), 1) == -1)
  493. xfunc_die();
  494. fclose(file);
  495. }
  496. // Die if we can't chdir to a new path.
  497. void xchdir(const char *path)
  498. {
  499. if (chdir(path))
  500. bb_perror_msg_and_die("chdir(%s)", path);
  501. }
  502. void xchroot(const char *path)
  503. {
  504. if (chroot(path))
  505. bb_perror_msg_and_die("can't change root directory to %s", path);
  506. }
  507. // Print a warning message if opendir() fails, but don't die.
  508. DIR *warn_opendir(const char *path)
  509. {
  510. DIR *dp;
  511. dp = opendir(path);
  512. if (!dp)
  513. bb_perror_msg("can't open '%s'", path);
  514. return dp;
  515. }
  516. // Die with an error message if opendir() fails.
  517. DIR *xopendir(const char *path)
  518. {
  519. DIR *dp;
  520. dp = opendir(path);
  521. if (!dp)
  522. bb_perror_msg_and_die("can't open '%s'", path);
  523. return dp;
  524. }
  525. // Die with an error message if we can't open a new socket.
  526. int xsocket(int domain, int type, int protocol)
  527. {
  528. int r = socket(domain, type, protocol);
  529. if (r < 0) {
  530. /* Hijack vaguely related config option */
  531. #if ENABLE_VERBOSE_RESOLUTION_ERRORS
  532. const char *s = "INET";
  533. if (domain == AF_PACKET) s = "PACKET";
  534. if (domain == AF_NETLINK) s = "NETLINK";
  535. USE_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";)
  536. bb_perror_msg_and_die("socket(AF_%s)", s);
  537. #else
  538. bb_perror_msg_and_die("socket");
  539. #endif
  540. }
  541. return r;
  542. }
  543. // Die with an error message if we can't bind a socket to an address.
  544. void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
  545. {
  546. if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");
  547. }
  548. // Die with an error message if we can't listen for connections on a socket.
  549. void xlisten(int s, int backlog)
  550. {
  551. if (listen(s, backlog)) bb_perror_msg_and_die("listen");
  552. }
  553. /* Die with an error message if sendto failed.
  554. * Return bytes sent otherwise */
  555. ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
  556. socklen_t tolen)
  557. {
  558. ssize_t ret = sendto(s, buf, len, 0, to, tolen);
  559. if (ret < 0) {
  560. if (ENABLE_FEATURE_CLEAN_UP)
  561. close(s);
  562. bb_perror_msg_and_die("sendto");
  563. }
  564. return ret;
  565. }
  566. // xstat() - a stat() which dies on failure with meaningful error message
  567. void xstat(const char *name, struct stat *stat_buf)
  568. {
  569. if (stat(name, stat_buf))
  570. bb_perror_msg_and_die("can't stat '%s'", name);
  571. }
  572. // selinux_or_die() - die if SELinux is disabled.
  573. void selinux_or_die(void)
  574. {
  575. #if ENABLE_SELINUX
  576. int rc = is_selinux_enabled();
  577. if (rc == 0) {
  578. bb_error_msg_and_die("SELinux is disabled");
  579. } else if (rc < 0) {
  580. bb_error_msg_and_die("is_selinux_enabled() failed");
  581. }
  582. #else
  583. bb_error_msg_and_die("SELinux support is disabled");
  584. #endif
  585. }
  586. /* It is perfectly ok to pass in a NULL for either width or for
  587. * height, in which case that value will not be set. */
  588. int get_terminal_width_height(int fd, int *width, int *height)
  589. {
  590. struct winsize win = { 0, 0, 0, 0 };
  591. int ret = ioctl(fd, TIOCGWINSZ, &win);
  592. if (height) {
  593. if (!win.ws_row) {
  594. char *s = getenv("LINES");
  595. if (s) win.ws_row = atoi(s);
  596. }
  597. if (win.ws_row <= 1 || win.ws_row >= 30000)
  598. win.ws_row = 24;
  599. *height = (int) win.ws_row;
  600. }
  601. if (width) {
  602. if (!win.ws_col) {
  603. char *s = getenv("COLUMNS");
  604. if (s) win.ws_col = atoi(s);
  605. }
  606. if (win.ws_col <= 1 || win.ws_col >= 30000)
  607. win.ws_col = 80;
  608. *width = (int) win.ws_col;
  609. }
  610. return ret;
  611. }
  612. void ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...)
  613. {
  614. va_list p;
  615. if (ioctl(fd, request, argp) < 0) {
  616. va_start(p, fmt);
  617. bb_verror_msg(fmt, p, strerror(errno));
  618. /* xfunc_die can actually longjmp, so be nice */
  619. va_end(p);
  620. xfunc_die();
  621. }
  622. }
  623. int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...)
  624. {
  625. va_list p;
  626. int ret = ioctl(fd, request, argp);
  627. if (ret < 0) {
  628. va_start(p, fmt);
  629. bb_verror_msg(fmt, p, strerror(errno));
  630. va_end(p);
  631. }
  632. return ret;
  633. }
  634. #if ENABLE_IOCTL_HEX2STR_ERROR
  635. int bb_ioctl_or_warn(int fd, unsigned request, void *argp, const char *ioctl_name)
  636. {
  637. int ret;
  638. ret = ioctl(fd, request, argp);
  639. if (ret < 0)
  640. bb_simple_perror_msg(ioctl_name);
  641. return ret;
  642. }
  643. void bb_xioctl(int fd, unsigned request, void *argp, const char *ioctl_name)
  644. {
  645. if (ioctl(fd, request, argp) < 0)
  646. bb_simple_perror_msg_and_die(ioctl_name);
  647. }
  648. #else
  649. int bb_ioctl_or_warn(int fd, unsigned request, void *argp)
  650. {
  651. int ret;
  652. ret = ioctl(fd, request, argp);
  653. if (ret < 0)
  654. bb_perror_msg("ioctl %#x failed", request);
  655. return ret;
  656. }
  657. void bb_xioctl(int fd, unsigned request, void *argp)
  658. {
  659. if (ioctl(fd, request, argp) < 0)
  660. bb_perror_msg_and_die("ioctl %#x failed", request);
  661. }
  662. #endif