xfuncs.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src)
  38. {
  39. #ifndef IFNAMSIZ
  40. enum { IFNAMSIZ = 16 };
  41. #endif
  42. return strncpy(dst, src, IFNAMSIZ);
  43. }
  44. // Convert unsigned integer to ascii, writing into supplied buffer.
  45. // A truncated result contains the first few digits of the result ala strncpy.
  46. // Returns a pointer past last generated digit, does _not_ store NUL.
  47. void BUG_sizeof_unsigned_not_4(void);
  48. char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
  49. {
  50. unsigned i, out, res;
  51. if (sizeof(unsigned) != 4)
  52. BUG_sizeof_unsigned_not_4();
  53. if (buflen) {
  54. out = 0;
  55. for (i = 1000000000; i; i /= 10) {
  56. res = n / i;
  57. if (res || out || i == 1) {
  58. if (!--buflen) break;
  59. out++;
  60. n -= res*i;
  61. *buf++ = '0' + res;
  62. }
  63. }
  64. }
  65. return buf;
  66. }
  67. /* Convert signed integer to ascii, like utoa_to_buf() */
  68. char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
  69. {
  70. if (buflen && n < 0) {
  71. n = -n;
  72. *buf++ = '-';
  73. buflen--;
  74. }
  75. return utoa_to_buf((unsigned)n, buf, buflen);
  76. }
  77. // The following two functions use a static buffer, so calling either one a
  78. // second time will overwrite previous results.
  79. //
  80. // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
  81. // It so happens that sizeof(int) * 3 is enough for 32+ bits.
  82. // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
  83. static char local_buf[sizeof(int) * 3];
  84. // Convert unsigned integer to ascii using a static buffer (returned).
  85. char* FAST_FUNC utoa(unsigned n)
  86. {
  87. *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
  88. return local_buf;
  89. }
  90. /* Convert signed integer to ascii using a static buffer (returned). */
  91. char* FAST_FUNC itoa(int n)
  92. {
  93. *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
  94. return local_buf;
  95. }
  96. /* Emit a string of hex representation of bytes */
  97. char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
  98. {
  99. while (count) {
  100. unsigned char c = *cp++;
  101. /* put lowercase hex digits */
  102. *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
  103. *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
  104. count--;
  105. }
  106. return p;
  107. }
  108. /* Convert "[x]x[:][x]x[:][x]x[:][x]x" hex string to binary, no more than COUNT bytes */
  109. char* FAST_FUNC hex2bin(char *dst, const char *str, int count)
  110. {
  111. errno = EINVAL;
  112. while (*str && count) {
  113. uint8_t val;
  114. uint8_t c = *str++;
  115. if (isdigit(c))
  116. val = c - '0';
  117. else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
  118. val = (c|0x20) - ('a' - 10);
  119. else
  120. return NULL;
  121. val <<= 4;
  122. c = *str;
  123. if (isdigit(c))
  124. val |= c - '0';
  125. else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
  126. val |= (c|0x20) - ('a' - 10);
  127. else if (c == ':' || c == '\0')
  128. val >>= 4;
  129. else
  130. return NULL;
  131. *dst++ = val;
  132. if (c != '\0')
  133. str++;
  134. if (*str == ':')
  135. str++;
  136. count--;
  137. }
  138. errno = (*str ? ERANGE : 0);
  139. return dst;
  140. }
  141. /* Return how long the file at fd is, if there's any way to determine it. */
  142. #ifdef UNUSED
  143. off_t FAST_FUNC fdlength(int fd)
  144. {
  145. off_t bottom = 0, top = 0, pos;
  146. long size;
  147. // If the ioctl works for this, return it.
  148. if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
  149. // FIXME: explain why lseek(SEEK_END) is not used here!
  150. // If not, do a binary search for the last location we can read. (Some
  151. // block devices don't do BLKGETSIZE right.)
  152. do {
  153. char temp;
  154. pos = bottom + (top - bottom) / 2;
  155. // If we can read from the current location, it's bigger.
  156. if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
  157. if (bottom == top) bottom = top = (top+1) * 2;
  158. else bottom = pos;
  159. // If we can't, it's smaller.
  160. } else {
  161. if (bottom == top) {
  162. if (!top) return 0;
  163. bottom = top/2;
  164. }
  165. else top = pos;
  166. }
  167. } while (bottom + 1 != top);
  168. return pos + 1;
  169. }
  170. #endif
  171. char* FAST_FUNC xmalloc_ttyname(int fd)
  172. {
  173. char *buf = xzalloc(128);
  174. int r = ttyname_r(fd, buf, 127);
  175. if (r) {
  176. free(buf);
  177. buf = NULL;
  178. }
  179. return buf;
  180. }
  181. static int wh_helper(int value, int def_val, const char *env_name, int *err)
  182. {
  183. if (value == 0) {
  184. char *s = getenv(env_name);
  185. if (s) {
  186. value = atoi(s);
  187. /* If LINES/COLUMNS are set, pretent that there is
  188. * no error getting w/h, this prevents some ugly
  189. * cursor tricks by our callers */
  190. *err = 0;
  191. }
  192. }
  193. if (value <= 1 || value >= 30000)
  194. value = def_val;
  195. return value;
  196. }
  197. /* It is perfectly ok to pass in a NULL for either width or for
  198. * height, in which case that value will not be set. */
  199. int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
  200. {
  201. struct winsize win;
  202. int err;
  203. win.ws_row = 0;
  204. win.ws_col = 0;
  205. /* I've seen ioctl returning 0, but row/col is (still?) 0.
  206. * We treat that as an error too. */
  207. err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0;
  208. if (height)
  209. *height = wh_helper(win.ws_row, 24, "LINES", &err);
  210. if (width)
  211. *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
  212. return err;
  213. }
  214. int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
  215. {
  216. return tcsetattr(STDIN_FILENO, TCSANOW, tp);
  217. }
  218. void FAST_FUNC generate_uuid(uint8_t *buf)
  219. {
  220. /* http://www.ietf.org/rfc/rfc4122.txt
  221. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  222. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  223. * | time_low |
  224. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  225. * | time_mid | time_hi_and_version |
  226. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  227. * |clk_seq_and_variant | node (0-1) |
  228. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  229. * | node (2-5) |
  230. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  231. * IOW, uuid has this layout:
  232. * uint32_t time_low (big endian)
  233. * uint16_t time_mid (big endian)
  234. * uint16_t time_hi_and_version (big endian)
  235. * version is a 4-bit field:
  236. * 1 Time-based
  237. * 2 DCE Security, with embedded POSIX UIDs
  238. * 3 Name-based (MD5)
  239. * 4 Randomly generated
  240. * 5 Name-based (SHA-1)
  241. * uint16_t clk_seq_and_variant (big endian)
  242. * variant is a 3-bit field:
  243. * 0xx Reserved, NCS backward compatibility
  244. * 10x The variant specified in rfc4122
  245. * 110 Reserved, Microsoft backward compatibility
  246. * 111 Reserved for future definition
  247. * uint8_t node[6]
  248. *
  249. * For version 4, these bits are set/cleared:
  250. * time_hi_and_version & 0x0fff | 0x4000
  251. * clk_seq_and_variant & 0x3fff | 0x8000
  252. */
  253. pid_t pid;
  254. int i;
  255. i = open("/dev/urandom", O_RDONLY);
  256. if (i >= 0) {
  257. read(i, buf, 16);
  258. close(i);
  259. }
  260. /* Paranoia. /dev/urandom may be missing.
  261. * rand() is guaranteed to generate at least [0, 2^15) range,
  262. * but lowest bits in some libc are not so "random". */
  263. srand(monotonic_us());
  264. pid = getpid();
  265. while (1) {
  266. for (i = 0; i < 16; i++)
  267. buf[i] ^= rand() >> 5;
  268. if (pid == 0)
  269. break;
  270. srand(pid);
  271. pid = 0;
  272. }
  273. /* version = 4 */
  274. buf[4 + 2 ] = (buf[4 + 2 ] & 0x0f) | 0x40;
  275. /* variant = 10x */
  276. buf[4 + 2 + 2] = (buf[4 + 2 + 2] & 0x3f) | 0x80;
  277. }