1 /* vi: set sw=4 ts=4: */
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 * Copyright (C) 2006 Rob Landley
7 * Copyright (C) 2006 Denys Vlasenko
9 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
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.
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.
22 * TODO: move xmalloc() and xatonum() here.
27 /* Turn on nonblocking I/O on a fd */
28 int FAST_FUNC
ndelay_on(int fd
)
30 return fcntl(fd
, F_SETFL
, fcntl(fd
,F_GETFL
) | O_NONBLOCK
);
33 int FAST_FUNC
ndelay_off(int fd
)
35 return fcntl(fd
, F_SETFL
, fcntl(fd
,F_GETFL
) & ~O_NONBLOCK
);
38 int FAST_FUNC
close_on_exec_on(int fd
)
40 return fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
43 char* FAST_FUNC
strncpy_IFNAMSIZ(char *dst
, const char *src
)
46 enum { IFNAMSIZ
= 16 };
48 return strncpy(dst
, src
, IFNAMSIZ
);
51 /* Convert unsigned long long value into compact 4-char
52 * representation. Examples: "1234", "1.2k", " 27M", "123T"
53 * String is not terminated (buf[4] is untouched) */
54 void FAST_FUNC
smart_ulltoa4(unsigned long long ul
, char buf
[5], const char *scale
)
58 unsigned v
, u
, idx
= 0;
60 if (ul
> 9999) { // do not scale if 9999 or less
65 } while (ul
>= 10000);
67 v
= ul
; // ullong divisions are expensive, avoid them
73 // 9999 or less: use "1234" format
74 // u is value/10, v is last digit
75 c
= buf
[0] = " 123456789"[u
/100];
76 if (c
!= ' ') fmt
= "0123456789";
77 c
= buf
[1] = fmt
[u
/10%10];
78 if (c
!= ' ') fmt
= "0123456789";
80 buf
[3] = "0123456789"[v
];
82 // u is value, v is 1/10ths (allows for 9.2M format)
84 // value is >= 10: use "123M', " 12M" formats
85 c
= buf
[0] = " 123456789"[u
/100];
86 if (c
!= ' ') fmt
= "0123456789";
91 // value is < 10: use "9.2M" format
92 buf
[0] = "0123456789"[u
];
95 buf
[2] = "0123456789"[v
];
96 buf
[3] = scale
[idx
]; /* typically scale = " kmgt..." */
100 /* Convert unsigned long long value into compact 5-char representation.
101 * String is not terminated (buf[5] is untouched) */
102 void FAST_FUNC
smart_ulltoa5(unsigned long long ul
, char buf
[6], const char *scale
)
106 unsigned v
, u
, idx
= 0;
108 if (ul
> 99999) { // do not scale if 99999 or less
113 } while (ul
>= 100000);
115 v
= ul
; // ullong divisions are expensive, avoid them
121 // 99999 or less: use "12345" format
122 // u is value/10, v is last digit
123 c
= buf
[0] = " 123456789"[u
/1000];
124 if (c
!= ' ') fmt
= "0123456789";
125 c
= buf
[1] = fmt
[u
/100%10];
126 if (c
!= ' ') fmt
= "0123456789";
127 c
= buf
[2] = fmt
[u
/10%10];
128 if (c
!= ' ') fmt
= "0123456789";
130 buf
[4] = "0123456789"[v
];
132 // value has been scaled into 0..9999.9 range
133 // u is value, v is 1/10ths (allows for 92.1M format)
135 // value is >= 100: use "1234M', " 123M" formats
136 c
= buf
[0] = " 123456789"[u
/1000];
137 if (c
!= ' ') fmt
= "0123456789";
138 c
= buf
[1] = fmt
[u
/100%10];
139 if (c
!= ' ') fmt
= "0123456789";
144 // value is < 100: use "92.1M" format
145 c
= buf
[0] = " 123456789"[u
/10];
146 if (c
!= ' ') fmt
= "0123456789";
150 buf
[3] = "0123456789"[v
];
151 buf
[4] = scale
[idx
]; /* typically scale = " kmgt..." */
156 // Convert unsigned integer to ascii, writing into supplied buffer.
157 // A truncated result contains the first few digits of the result ala strncpy.
158 // Returns a pointer past last generated digit, does _not_ store NUL.
159 void BUG_sizeof_unsigned_not_4(void);
160 char* FAST_FUNC
utoa_to_buf(unsigned n
, char *buf
, unsigned buflen
)
162 unsigned i
, out
, res
;
163 if (sizeof(unsigned) != 4)
164 BUG_sizeof_unsigned_not_4();
167 for (i
= 1000000000; i
; i
/= 10) {
169 if (res
|| out
|| i
== 1) {
170 if (!--buflen
) break;
180 /* Convert signed integer to ascii, like utoa_to_buf() */
181 char* FAST_FUNC
itoa_to_buf(int n
, char *buf
, unsigned buflen
)
183 if (buflen
&& n
< 0) {
188 return utoa_to_buf((unsigned)n
, buf
, buflen
);
191 // The following two functions use a static buffer, so calling either one a
192 // second time will overwrite previous results.
194 // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
195 // It so happens that sizeof(int) * 3 is enough for 32+ bits.
196 // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
198 static char local_buf
[sizeof(int) * 3];
200 // Convert unsigned integer to ascii using a static buffer (returned).
201 char* FAST_FUNC
utoa(unsigned n
)
203 *(utoa_to_buf(n
, local_buf
, sizeof(local_buf
))) = '\0';
208 /* Convert signed integer to ascii using a static buffer (returned). */
209 char* FAST_FUNC
itoa(int n
)
211 *(itoa_to_buf(n
, local_buf
, sizeof(local_buf
))) = '\0';
216 /* Emit a string of hex representation of bytes */
217 char* FAST_FUNC
bin2hex(char *p
, const char *cp
, int count
)
220 unsigned char c
= *cp
++;
221 /* put lowercase hex digits */
222 *p
++ = 0x20 | bb_hexdigits_upcase
[c
>> 4];
223 *p
++ = 0x20 | bb_hexdigits_upcase
[c
& 0xf];
229 /* Return how long the file at fd is, if there's any way to determine it. */
231 off_t FAST_FUNC
fdlength(int fd
)
233 off_t bottom
= 0, top
= 0, pos
;
236 // If the ioctl works for this, return it.
238 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) return size
*512;
240 // FIXME: explain why lseek(SEEK_END) is not used here!
242 // If not, do a binary search for the last location we can read. (Some
243 // block devices don't do BLKGETSIZE right.)
248 pos
= bottom
+ (top
- bottom
) / 2;
250 // If we can read from the current location, it's bigger.
252 if (lseek(fd
, pos
, SEEK_SET
)>=0 && safe_read(fd
, &temp
, 1)==1) {
253 if (bottom
== top
) bottom
= top
= (top
+1) * 2;
256 // If we can't, it's smaller.
265 } while (bottom
+ 1 != top
);
271 char* FAST_FUNC
xmalloc_ttyname(int fd
)
273 char *buf
= xzalloc(128);
274 int r
= ttyname_r(fd
, buf
, 127);
282 /* It is perfectly ok to pass in a NULL for either width or for
283 * height, in which case that value will not be set. */
284 int FAST_FUNC
get_terminal_width_height(int fd
, unsigned *width
, unsigned *height
)
286 struct winsize win
= { 0, 0, 0, 0 };
287 int ret
= ioctl(fd
, TIOCGWINSZ
, &win
);
291 char *s
= getenv("LINES");
292 if (s
) win
.ws_row
= atoi(s
);
294 if (win
.ws_row
<= 1 || win
.ws_row
>= 30000)
296 *height
= (int) win
.ws_row
;
301 char *s
= getenv("COLUMNS");
302 if (s
) win
.ws_col
= atoi(s
);
304 if (win
.ws_col
<= 1 || win
.ws_col
>= 30000)
306 *width
= (int) win
.ws_col
;
312 int FAST_FUNC
tcsetattr_stdin_TCSANOW(const struct termios
*tp
)
314 return tcsetattr(STDIN_FILENO
, TCSANOW
, tp
);