source: MondoRescue/branches/3.3/mindi-busybox/libbb/xfuncs.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

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