xfuncs.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. /* We need to have separate xfuncs.c and xfuncs_printf.c because
  12. * with current linkers, even with section garbage collection,
  13. * if *.o module references any of XXXprintf functions, you pull in
  14. * entire printf machinery. Even if you do not use the function
  15. * which uses XXXprintf.
  16. *
  17. * xfuncs.c contains functions (not necessarily xfuncs)
  18. * which do not pull in printf, directly or indirectly.
  19. * xfunc_printf.c contains those which do.
  20. *
  21. * TODO: move xmalloc() and xatonum() here.
  22. */
  23. #include "libbb.h"
  24. /* Turn on nonblocking I/O on a fd */
  25. int FAST_FUNC ndelay_on(int fd)
  26. {
  27. return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);
  28. }
  29. int FAST_FUNC ndelay_off(int fd)
  30. {
  31. return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK);
  32. }
  33. int FAST_FUNC close_on_exec_on(int fd)
  34. {
  35. return fcntl(fd, F_SETFD, FD_CLOEXEC);
  36. }
  37. /* Convert unsigned long long value into compact 4-char
  38. * representation. Examples: "1234", "1.2k", " 27M", "123T"
  39. * String is not terminated (buf[4] is untouched) */
  40. void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale)
  41. {
  42. const char *fmt;
  43. char c;
  44. unsigned v, u, idx = 0;
  45. if (ul > 9999) { // do not scale if 9999 or less
  46. ul *= 10;
  47. do {
  48. ul /= 1024;
  49. idx++;
  50. } while (ul >= 10000);
  51. }
  52. v = ul; // ullong divisions are expensive, avoid them
  53. fmt = " 123456789";
  54. u = v / 10;
  55. v = v % 10;
  56. if (!idx) {
  57. // 9999 or less: use "1234" format
  58. // u is value/10, v is last digit
  59. c = buf[0] = " 123456789"[u/100];
  60. if (c != ' ') fmt = "0123456789";
  61. c = buf[1] = fmt[u/10%10];
  62. if (c != ' ') fmt = "0123456789";
  63. buf[2] = fmt[u%10];
  64. buf[3] = "0123456789"[v];
  65. } else {
  66. // u is value, v is 1/10ths (allows for 9.2M format)
  67. if (u >= 10) {
  68. // value is >= 10: use "123M', " 12M" formats
  69. c = buf[0] = " 123456789"[u/100];
  70. if (c != ' ') fmt = "0123456789";
  71. v = u % 10;
  72. u = u / 10;
  73. buf[1] = fmt[u%10];
  74. } else {
  75. // value is < 10: use "9.2M" format
  76. buf[0] = "0123456789"[u];
  77. buf[1] = '.';
  78. }
  79. buf[2] = "0123456789"[v];
  80. buf[3] = scale[idx]; /* typically scale = " kmgt..." */
  81. }
  82. }
  83. /* Convert unsigned long long value into compact 5-char representation.
  84. * String is not terminated (buf[5] is untouched) */
  85. void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[6], const char *scale)
  86. {
  87. const char *fmt;
  88. char c;
  89. unsigned v, u, idx = 0;
  90. if (ul > 99999) { // do not scale if 99999 or less
  91. ul *= 10;
  92. do {
  93. ul /= 1024;
  94. idx++;
  95. } while (ul >= 100000);
  96. }
  97. v = ul; // ullong divisions are expensive, avoid them
  98. fmt = " 123456789";
  99. u = v / 10;
  100. v = v % 10;
  101. if (!idx) {
  102. // 99999 or less: use "12345" format
  103. // u is value/10, v is last digit
  104. c = buf[0] = " 123456789"[u/1000];
  105. if (c != ' ') fmt = "0123456789";
  106. c = buf[1] = fmt[u/100%10];
  107. if (c != ' ') fmt = "0123456789";
  108. c = buf[2] = fmt[u/10%10];
  109. if (c != ' ') fmt = "0123456789";
  110. buf[3] = fmt[u%10];
  111. buf[4] = "0123456789"[v];
  112. } else {
  113. // value has been scaled into 0..9999.9 range
  114. // u is value, v is 1/10ths (allows for 92.1M format)
  115. if (u >= 100) {
  116. // value is >= 100: use "1234M', " 123M" formats
  117. c = buf[0] = " 123456789"[u/1000];
  118. if (c != ' ') fmt = "0123456789";
  119. c = buf[1] = fmt[u/100%10];
  120. if (c != ' ') fmt = "0123456789";
  121. v = u % 10;
  122. u = u / 10;
  123. buf[2] = fmt[u%10];
  124. } else {
  125. // value is < 100: use "92.1M" format
  126. c = buf[0] = " 123456789"[u/10];
  127. if (c != ' ') fmt = "0123456789";
  128. buf[1] = fmt[u%10];
  129. buf[2] = '.';
  130. }
  131. buf[3] = "0123456789"[v];
  132. buf[4] = scale[idx]; /* typically scale = " kmgt..." */
  133. }
  134. }
  135. // Convert unsigned integer to ascii, writing into supplied buffer.
  136. // A truncated result contains the first few digits of the result ala strncpy.
  137. // Returns a pointer past last generated digit, does _not_ store NUL.
  138. void BUG_sizeof_unsigned_not_4(void);
  139. char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
  140. {
  141. unsigned i, out, res;
  142. if (sizeof(unsigned) != 4)
  143. BUG_sizeof_unsigned_not_4();
  144. if (buflen) {
  145. out = 0;
  146. for (i = 1000000000; i; i /= 10) {
  147. res = n / i;
  148. if (res || out || i == 1) {
  149. if (!--buflen) break;
  150. out++;
  151. n -= res*i;
  152. *buf++ = '0' + res;
  153. }
  154. }
  155. }
  156. return buf;
  157. }
  158. /* Convert signed integer to ascii, like utoa_to_buf() */
  159. char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
  160. {
  161. if (buflen && n < 0) {
  162. n = -n;
  163. *buf++ = '-';
  164. buflen--;
  165. }
  166. return utoa_to_buf((unsigned)n, buf, buflen);
  167. }
  168. // The following two functions use a static buffer, so calling either one a
  169. // second time will overwrite previous results.
  170. //
  171. // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
  172. // It so happens that sizeof(int) * 3 is enough for 32+ bits.
  173. // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
  174. static char local_buf[sizeof(int) * 3];
  175. // Convert unsigned integer to ascii using a static buffer (returned).
  176. char* FAST_FUNC utoa(unsigned n)
  177. {
  178. *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
  179. return local_buf;
  180. }
  181. /* Convert signed integer to ascii using a static buffer (returned). */
  182. char* FAST_FUNC itoa(int n)
  183. {
  184. *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
  185. return local_buf;
  186. }
  187. /* Emit a string of hex representation of bytes */
  188. char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
  189. {
  190. while (count) {
  191. unsigned char c = *cp++;
  192. /* put lowercase hex digits */
  193. *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
  194. *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
  195. count--;
  196. }
  197. return p;
  198. }
  199. /* Return how long the file at fd is, if there's any way to determine it. */
  200. #ifdef UNUSED
  201. off_t FAST_FUNC fdlength(int fd)
  202. {
  203. off_t bottom = 0, top = 0, pos;
  204. long size;
  205. // If the ioctl works for this, return it.
  206. if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
  207. // FIXME: explain why lseek(SEEK_END) is not used here!
  208. // If not, do a binary search for the last location we can read. (Some
  209. // block devices don't do BLKGETSIZE right.)
  210. do {
  211. char temp;
  212. pos = bottom + (top - bottom) / 2;
  213. // If we can read from the current location, it's bigger.
  214. if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
  215. if (bottom == top) bottom = top = (top+1) * 2;
  216. else bottom = pos;
  217. // If we can't, it's smaller.
  218. } else {
  219. if (bottom == top) {
  220. if (!top) return 0;
  221. bottom = top/2;
  222. }
  223. else top = pos;
  224. }
  225. } while (bottom + 1 != top);
  226. return pos + 1;
  227. }
  228. #endif
  229. /* It is perfectly ok to pass in a NULL for either width or for
  230. * height, in which case that value will not be set. */
  231. int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
  232. {
  233. struct winsize win = { 0, 0, 0, 0 };
  234. int ret = ioctl(fd, TIOCGWINSZ, &win);
  235. if (height) {
  236. if (!win.ws_row) {
  237. char *s = getenv("LINES");
  238. if (s) win.ws_row = atoi(s);
  239. }
  240. if (win.ws_row <= 1 || win.ws_row >= 30000)
  241. win.ws_row = 24;
  242. *height = (int) win.ws_row;
  243. }
  244. if (width) {
  245. if (!win.ws_col) {
  246. char *s = getenv("COLUMNS");
  247. if (s) win.ws_col = atoi(s);
  248. }
  249. if (win.ws_col <= 1 || win.ws_col >= 30000)
  250. win.ws_col = 80;
  251. *width = (int) win.ws_col;
  252. }
  253. return ret;
  254. }