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