1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "libbb.h"
24
25
26int FAST_FUNC ndelay_on(int fd)
27{
28 int flags = fcntl(fd, F_GETFL);
29 if (flags & O_NONBLOCK)
30 return flags;
31 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
32 return flags;
33}
34
35int FAST_FUNC ndelay_off(int fd)
36{
37 int flags = fcntl(fd, F_GETFL);
38 if (!(flags & O_NONBLOCK))
39 return flags;
40 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
41 return flags;
42}
43
44void FAST_FUNC close_on_exec_on(int fd)
45{
46 fcntl(fd, F_SETFD, FD_CLOEXEC);
47}
48
49char* 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
59
60
61
62char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
63{
64 unsigned i, out, res;
65
66 if (buflen) {
67 out = 0;
68
69 BUILD_BUG_ON(sizeof(n) != 4 && sizeof(n) != 8);
70 if (sizeof(n) == 4)
71
72 i = 1000000000;
73#if UINT_MAX > 0xffffffff
74 else
75 if (sizeof(n) == 8)
76
77 i = 10000000000000000000;
78#endif
79 for (; i; i /= 10) {
80 res = n / i;
81 n = n % i;
82 if (res || out || i == 1) {
83 if (--buflen == 0)
84 break;
85 out++;
86 *buf++ = '0' + res;
87 }
88 }
89 }
90 return buf;
91}
92
93
94char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
95{
96 if (!buflen)
97 return buf;
98 if (n < 0) {
99 n = -n;
100 *buf++ = '-';
101 buflen--;
102 }
103 return utoa_to_buf((unsigned)n, buf, buflen);
104}
105
106
107
108
109
110
111
112
113static char local_buf[sizeof(int) * 3];
114
115
116char* FAST_FUNC utoa(unsigned n)
117{
118 *(utoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
119
120 return local_buf;
121}
122
123
124char* FAST_FUNC itoa(int n)
125{
126 *(itoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0';
127
128 return local_buf;
129}
130
131
132char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
133{
134 while (count) {
135 unsigned char c = *cp++;
136
137 *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
138 *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
139 count--;
140 }
141 return p;
142}
143
144
145char* FAST_FUNC hex2bin(char *dst, const char *str, int count)
146{
147 errno = EINVAL;
148 while (*str && count) {
149 uint8_t val;
150 uint8_t c = *str++;
151 if (isdigit(c))
152 val = c - '0';
153 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
154 val = (c|0x20) - ('a' - 10);
155 else
156 return NULL;
157 val <<= 4;
158 c = *str;
159 if (isdigit(c))
160 val |= c - '0';
161 else if ((c|0x20) >= 'a' && (c|0x20) <= 'f')
162 val |= (c|0x20) - ('a' - 10);
163 else if (c == ':' || c == '\0')
164 val >>= 4;
165 else
166 return NULL;
167
168 *dst++ = val;
169 if (c != '\0')
170 str++;
171 if (*str == ':')
172 str++;
173 count--;
174 }
175 errno = (*str ? ERANGE : 0);
176 return dst;
177}
178
179
180#ifdef UNUSED
181off_t FAST_FUNC fdlength(int fd)
182{
183 off_t bottom = 0, top = 0, pos;
184 long size;
185
186
187
188 if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
189
190
191
192
193
194
195 do {
196 char temp;
197
198 pos = bottom + (top - bottom) / 2;
199
200
201
202 if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
203 if (bottom == top) bottom = top = (top+1) * 2;
204 else bottom = pos;
205
206
207 } else {
208 if (bottom == top) {
209 if (!top) return 0;
210 bottom = top/2;
211 }
212 else top = pos;
213 }
214 } while (bottom + 1 != top);
215
216 return pos + 1;
217}
218#endif
219
220int FAST_FUNC bb_putchar_stderr(char ch)
221{
222 return write(STDERR_FILENO, &ch, 1);
223}
224
225ssize_t FAST_FUNC full_write1_str(const char *str)
226{
227 return full_write(STDOUT_FILENO, str, strlen(str));
228}
229
230ssize_t FAST_FUNC full_write2_str(const char *str)
231{
232 return full_write(STDERR_FILENO, str, strlen(str));
233}
234
235static int wh_helper(int value, int def_val, const char *env_name, int *err)
236{
237
238
239
240
241
242
243
244
245
246
247
248
249 char *s = getenv(env_name);
250 if (s) {
251 value = atoi(s);
252
253
254
255 *err = 0;
256 }
257
258 if (value <= 1 || value >= 30000)
259 value = def_val;
260 return value;
261}
262
263
264
265int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
266{
267 struct winsize win;
268 int err;
269 int close_me = -1;
270
271 if (fd == -1) {
272 if (isatty(STDOUT_FILENO))
273 fd = STDOUT_FILENO;
274 else
275 if (isatty(STDERR_FILENO))
276 fd = STDERR_FILENO;
277 else
278 if (isatty(STDIN_FILENO))
279 fd = STDIN_FILENO;
280 else
281 close_me = fd = open("/dev/tty", O_RDONLY);
282 }
283
284 win.ws_row = 0;
285 win.ws_col = 0;
286
287
288 err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0;
289 if (height)
290 *height = wh_helper(win.ws_row, 24, "LINES", &err);
291 if (width)
292 *width = wh_helper(win.ws_col, 80, "COLUMNS", &err);
293
294 if (close_me >= 0)
295 close(close_me);
296
297 return err;
298}
299int FAST_FUNC get_terminal_width(int fd)
300{
301 unsigned width;
302 get_terminal_width_height(fd, &width, NULL);
303 return width;
304}
305
306int FAST_FUNC is_TERM_dumb(void)
307{
308 char *term = getenv("TERM");
309 return term && strcmp(term, "dumb") == 0;
310}
311
312int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
313{
314 return tcsetattr(STDIN_FILENO, TCSANOW, tp);
315}
316
317int FAST_FUNC get_termios_and_make_raw(int fd, struct termios *newterm, struct termios *oldterm, int flags)
318{
319
320 int r;
321
322 memset(oldterm, 0, sizeof(*oldterm));
323 r = tcgetattr(fd, oldterm);
324 *newterm = *oldterm;
325
326
327
328
329
330 newterm->c_lflag &= ~(ICANON | ECHO | ECHONL);
331 if (flags & TERMIOS_CLEAR_ISIG) {
332
333 newterm->c_lflag &= ~ISIG;
334 }
335
336 newterm->c_cc[VMIN] = 1;
337
338 newterm->c_cc[VTIME] = 0;
339
340
341
342
343
344
345
346
347
348 if (flags & TERMIOS_RAW_CRNL_INPUT) {
349
350
351 newterm->c_iflag &= ~(IXON | ICRNL);
352 }
353 if (flags & TERMIOS_RAW_CRNL_OUTPUT) {
354
355 newterm->c_oflag &= ~(ONLCR);
356
357
358
359
360
361
362
363 }
364 if (flags & TERMIOS_RAW_INPUT) {
365#ifndef IMAXBEL
366# define IMAXBEL 0
367#endif
368#ifndef IUCLC
369# define IUCLC 0
370#endif
371#ifndef IXANY
372# define IXANY 0
373#endif
374
375
376
377
378
379
380 newterm->c_iflag &= ~(IXOFF|IXON|IXANY|BRKINT|INLCR|ICRNL|IUCLC|IMAXBEL);
381 }
382 return r;
383}
384
385int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags)
386{
387 struct termios newterm;
388
389 get_termios_and_make_raw(fd, &newterm, oldterm, flags);
390 return tcsetattr(fd, TCSANOW, &newterm);
391}
392
393pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
394{
395 pid_t r;
396
397 do
398 r = waitpid(pid, wstat, options);
399 while ((r == -1) && (errno == EINTR));
400 return r;
401}
402
403pid_t FAST_FUNC wait_any_nohang(int *wstat)
404{
405 return safe_waitpid(-1, wstat, WNOHANG);
406}
407
408
409int FAST_FUNC wait4pid(pid_t pid)
410{
411 int status;
412
413 if (pid <= 0) {
414
415
416 return -1;
417 }
418 if (safe_waitpid(pid, &status, 0) == -1)
419 return -1;
420 if (WIFEXITED(status))
421 return WEXITSTATUS(status);
422 if (WIFSIGNALED(status))
423 return WTERMSIG(status) + 0x180;
424 return 0;
425}
426