Bump to version 1.22.1
[platform/upstream/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 GPLv2, see file LICENSE in this source tree.
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 void FAST_FUNC ndelay_on(int fd)
29 {
30         int flags = fcntl(fd, F_GETFL);
31         if (flags & O_NONBLOCK)
32                 return;
33         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
34 }
35
36 void FAST_FUNC ndelay_off(int fd)
37 {
38         int flags = fcntl(fd, F_GETFL);
39         if (!(flags & O_NONBLOCK))
40                 return;
41         fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
42 }
43
44 void FAST_FUNC close_on_exec_on(int fd)
45 {
46         fcntl(fd, F_SETFD, FD_CLOEXEC);
47 }
48
49 char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src)
50 {
51 #ifndef IFNAMSIZ
52         enum { IFNAMSIZ = 16 };
53 #endif
54         return strncpy(dst, src, IFNAMSIZ);
55 }
56
57
58 /* Convert unsigned integer to ascii, writing into supplied buffer.
59  * A truncated result contains the first few digits of the result ala strncpy.
60  * Returns a pointer past last generated digit, does _not_ store NUL.
61  */
62 void BUG_sizeof(void);
63 char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
64 {
65         unsigned i, out, res;
66
67         if (buflen) {
68                 out = 0;
69                 if (sizeof(n) == 4)
70                 // 2^32-1 = 4294967295
71                         i = 1000000000;
72 #if UINT_MAX > 4294967295 /* prevents warning about "const too large" */
73                 else
74                 if (sizeof(n) == 8)
75                 // 2^64-1 = 18446744073709551615
76                         i = 10000000000000000000;
77 #endif
78                 else
79                         BUG_sizeof();
80                 for (; i; i /= 10) {
81                         res = n / i;
82                         n = n % i;
83                         if (res || out || i == 1) {
84                                 if (--buflen == 0)
85                                         break;
86                                 out++;
87                                 *buf++ = '0' + res;
88                         }
89                 }
90         }
91         return buf;
92 }
93
94 /* Convert signed integer to ascii, like utoa_to_buf() */
95 char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
96 {
97         if (!buflen)
98                 return buf;
99         if (n < 0) {
100                 n = -n;
101                 *buf++ = '-';
102                 buflen--;
103         }
104         return utoa_to_buf((unsigned)n, buf, buflen);
105 }
106
107 // The following two functions use a static buffer, so calling either one a
108 // second time will overwrite previous results.
109 //
110 // The largest 32 bit integer is -2 billion plus NUL, or 1+10+1=12 bytes.
111 // It so happens that sizeof(int) * 3 is enough for 32+ bit ints.
112 // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
113
114 static char local_buf[sizeof(int) * 3];
115
116 /* Convert unsigned integer to ascii using a static buffer (returned). */
117 char* FAST_FUNC utoa(unsigned n)
118 {
119         *(utoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
120
121         return local_buf;
122 }
123
124 /* Convert signed integer to ascii using a static buffer (returned). */
125 char* FAST_FUNC itoa(int n)
126 {
127         *(itoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
128
129         return local_buf;
130 }
131
132 /* Emit a string of hex representation of bytes */
133 char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
134 {
135         while (count) {
136                 unsigned char c = *cp++;
137                 /* put lowercase hex digits */
138                 *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
139                 *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
140                 count--;
141         }
142         return p;
143 }
144
145 /* Convert "[x]x[:][x]x[:][x]x[:][x]x" hex string to binary, no more than COUNT bytes */
146 char* FAST_FUNC hex2bin(char *dst, const char *str, int count)
147 {
148         errno = EINVAL;
149         while (*str && count) {
150                 uint8_t val;
151                 uint8_t c = *str++;
152                 if (isdigit(c))
153                         val = c - '0';
154                 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
155                         val = (c|0x20) - ('a' - 10);
156                 else
157                         return NULL;
158                 val <<= 4;
159                 c = *str;
160                 if (isdigit(c))
161                         val |= c - '0';
162                 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
163                         val |= (c|0x20) - ('a' - 10);
164                 else if (c == ':' || c == '\0')
165                         val >>= 4;
166                 else
167                         return NULL;
168
169                 *dst++ = val;
170                 if (c != '\0')
171                         str++;
172                 if (*str == ':')
173                         str++;
174                 count--;
175         }
176         errno = (*str ? ERANGE : 0);
177         return dst;
178 }
179
180 /* Return how long the file at fd is, if there's any way to determine it. */
181 #ifdef UNUSED
182 off_t FAST_FUNC fdlength(int fd)
183 {
184         off_t bottom = 0, top = 0, pos;
185         long size;
186
187         // If the ioctl works for this, return it.
188
189         if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
190
191         // FIXME: explain why lseek(SEEK_END) is not used here!
192
193         // If not, do a binary search for the last location we can read.  (Some
194         // block devices don't do BLKGETSIZE right.)
195
196         do {
197                 char temp;
198
199                 pos = bottom + (top - bottom) / 2;
200
201                 // If we can read from the current location, it's bigger.
202
203                 if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
204                         if (bottom == top) bottom = top = (top+1) * 2;
205                         else bottom = pos;
206
207                 // If we can't, it's smaller.
208
209                 } else {
210                         if (bottom == top) {
211                                 if (!top) return 0;
212                                 bottom = top/2;
213                         }
214                         else top = pos;
215                 }
216         } while (bottom + 1 != top);
217
218         return pos + 1;
219 }
220 #endif
221
222 int FAST_FUNC bb_putchar_stderr(char ch)
223 {
224         return write(STDERR_FILENO, &ch, 1);
225 }
226
227 ssize_t FAST_FUNC full_write1_str(const char *str)
228 {
229         return full_write(STDOUT_FILENO, str, strlen(str));
230 }
231
232 ssize_t FAST_FUNC full_write2_str(const char *str)
233 {
234         return full_write(STDERR_FILENO, str, strlen(str));
235 }
236
237 static int wh_helper(int value, int def_val, const char *env_name, int *err)
238 {
239         if (value == 0) {
240                 char *s = getenv(env_name);
241                 if (s) {
242                         value = atoi(s);
243                         /* If LINES/COLUMNS are set, pretend that there is
244                          * no error getting w/h, this prevents some ugly
245                          * cursor tricks by our callers */
246                         *err = 0;
247                 }
248         }
249         if (value <= 1 || value >= 30000)
250                 value = def_val;
251         return value;
252 }
253
254 /* It is perfectly ok to pass in a NULL for either width or for
255  * height, in which case that value will not be set.  */
256 int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
257 {
258         struct winsize win;
259         int err;
260
261         win.ws_row = 0;
262         win.ws_col = 0;
263         /* I've seen ioctl returning 0, but row/col is (still?) 0.
264          * We treat that as an error too.  */
265         err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0;
266         if (height)
267                 *height = wh_helper(win.ws_row, 24, "LINES", &err);
268         if (width)
269                 *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
270         return err;
271 }
272
273 int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
274 {
275         return tcsetattr(STDIN_FILENO, TCSANOW, tp);
276 }
277
278 pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
279 {
280         pid_t r;
281
282         do
283                 r = waitpid(pid, wstat, options);
284         while ((r == -1) && (errno == EINTR));
285         return r;
286 }
287
288 pid_t FAST_FUNC wait_any_nohang(int *wstat)
289 {
290         return safe_waitpid(-1, wstat, WNOHANG);
291 }
292
293 // Wait for the specified child PID to exit, returning child's error return.
294 int FAST_FUNC wait4pid(pid_t pid)
295 {
296         int status;
297
298         if (pid <= 0) {
299                 /*errno = ECHILD; -- wrong. */
300                 /* we expect errno to be already set from failed [v]fork/exec */
301                 return -1;
302         }
303         if (safe_waitpid(pid, &status, 0) == -1)
304                 return -1;
305         if (WIFEXITED(status))
306                 return WEXITSTATUS(status);
307         if (WIFSIGNALED(status))
308                 return WTERMSIG(status) + 0x180;
309         return 0;
310 }