busybox: do not print help to fd 2, print it to fd 1
[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 ndelay_on(int fd)
29 {
30         return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);
31 }
32
33 int ndelay_off(int fd)
34 {
35         return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK);
36 }
37
38 int close_on_exec_on(int fd)
39 {
40         return fcntl(fd, F_SETFD, FD_CLOEXEC);
41 }
42
43 /* Convert unsigned long long value into compact 4-char
44  * representation. Examples: "1234", "1.2k", " 27M", "123T"
45  * String is not terminated (buf[4] is untouched) */
46 void smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale)
47 {
48         const char *fmt;
49         char c;
50         unsigned v, u, idx = 0;
51
52         if (ul > 9999) { // do not scale if 9999 or less
53                 ul *= 10;
54                 do {
55                         ul /= 1024;
56                         idx++;
57                 } while (ul >= 10000);
58         }
59         v = ul; // ullong divisions are expensive, avoid them
60
61         fmt = " 123456789";
62         u = v / 10;
63         v = v % 10;
64         if (!idx) {
65                 // 9999 or less: use "1234" format
66                 // u is value/10, v is last digit
67                 c = buf[0] = " 123456789"[u/100];
68                 if (c != ' ') fmt = "0123456789";
69                 c = buf[1] = fmt[u/10%10];
70                 if (c != ' ') fmt = "0123456789";
71                 buf[2] = fmt[u%10];
72                 buf[3] = "0123456789"[v];
73         } else {
74                 // u is value, v is 1/10ths (allows for 9.2M format)
75                 if (u >= 10) {
76                         // value is >= 10: use "123M', " 12M" formats
77                         c = buf[0] = " 123456789"[u/100];
78                         if (c != ' ') fmt = "0123456789";
79                         v = u % 10;
80                         u = u / 10;
81                         buf[1] = fmt[u%10];
82                 } else {
83                         // value is < 10: use "9.2M" format
84                         buf[0] = "0123456789"[u];
85                         buf[1] = '.';
86                 }
87                 buf[2] = "0123456789"[v];
88                 buf[3] = scale[idx]; /* typically scale = " kmgt..." */
89         }
90 }
91
92 /* Convert unsigned long long value into compact 5-char representation.
93  * String is not terminated (buf[5] is untouched) */
94 void smart_ulltoa5(unsigned long long ul, char buf[6], const char *scale)
95 {
96         const char *fmt;
97         char c;
98         unsigned v, u, idx = 0;
99
100         if (ul > 99999) { // do not scale if 99999 or less
101                 ul *= 10;
102                 do {
103                         ul /= 1024;
104                         idx++;
105                 } while (ul >= 100000);
106         }
107         v = ul; // ullong divisions are expensive, avoid them
108
109         fmt = " 123456789";
110         u = v / 10;
111         v = v % 10;
112         if (!idx) {
113                 // 99999 or less: use "12345" format
114                 // u is value/10, v is last digit
115                 c = buf[0] = " 123456789"[u/1000];
116                 if (c != ' ') fmt = "0123456789";
117                 c = buf[1] = fmt[u/100%10];
118                 if (c != ' ') fmt = "0123456789";
119                 c = buf[2] = fmt[u/10%10];
120                 if (c != ' ') fmt = "0123456789";
121                 buf[3] = fmt[u%10];
122                 buf[4] = "0123456789"[v];
123         } else {
124                 // value has been scaled into 0..9999.9 range
125                 // u is value, v is 1/10ths (allows for 92.1M format)
126                 if (u >= 100) {
127                         // value is >= 100: use "1234M', " 123M" formats
128                         c = buf[0] = " 123456789"[u/1000];
129                         if (c != ' ') fmt = "0123456789";
130                         c = buf[1] = fmt[u/100%10];
131                         if (c != ' ') fmt = "0123456789";
132                         v = u % 10;
133                         u = u / 10;
134                         buf[2] = fmt[u%10];
135                 } else {
136                         // value is < 100: use "92.1M" format
137                         c = buf[0] = " 123456789"[u/10];
138                         if (c != ' ') fmt = "0123456789";
139                         buf[1] = fmt[u%10];
140                         buf[2] = '.';
141                 }
142                 buf[3] = "0123456789"[v];
143                 buf[4] = scale[idx]; /* typically scale = " kmgt..." */
144         }
145 }
146
147
148 // Convert unsigned integer to ascii, writing into supplied buffer.
149 // A truncated result contains the first few digits of the result ala strncpy.
150 // Returns a pointer past last generated digit, does _not_ store NUL.
151 void BUG_sizeof_unsigned_not_4(void);
152 char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
153 {
154         unsigned i, out, res;
155         if (sizeof(unsigned) != 4)
156                 BUG_sizeof_unsigned_not_4();
157         if (buflen) {
158                 out = 0;
159                 for (i = 1000000000; i; i /= 10) {
160                         res = n / i;
161                         if (res || out || i == 1) {
162                                 if (!--buflen) break;
163                                 out++;
164                                 n -= res*i;
165                                 *buf++ = '0' + res;
166                         }
167                 }
168         }
169         return buf;
170 }
171
172 /* Convert signed integer to ascii, like utoa_to_buf() */
173 char *itoa_to_buf(int n, char *buf, unsigned buflen)
174 {
175         if (buflen && n < 0) {
176                 n = -n;
177                 *buf++ = '-';
178                 buflen--;
179         }
180         return utoa_to_buf((unsigned)n, buf, buflen);
181 }
182
183 // The following two functions use a static buffer, so calling either one a
184 // second time will overwrite previous results.
185 //
186 // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
187 // It so happens that sizeof(int) * 3 is enough for 32+ bits.
188 // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
189
190 static char local_buf[sizeof(int) * 3];
191
192 // Convert unsigned integer to ascii using a static buffer (returned).
193 char *utoa(unsigned n)
194 {
195         *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
196
197         return local_buf;
198 }
199
200 /* Convert signed integer to ascii using a static buffer (returned). */
201 char *itoa(int n)
202 {
203         *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
204
205         return local_buf;
206 }
207
208 /* Emit a string of hex representation of bytes */
209 char *bin2hex(char *p, const char *cp, int count)
210 {
211         while (count) {
212                 unsigned char c = *cp++;
213                 /* put lowercase hex digits */
214                 *p++ = 0x20 | bb_hexdigits_upcase[c >> 4];
215                 *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf];
216                 count--;
217         }
218         return p;
219 }
220
221 /* Return how long the file at fd is, if there's any way to determine it. */
222 #ifdef UNUSED
223 off_t fdlength(int fd)
224 {
225         off_t bottom = 0, top = 0, pos;
226         long size;
227
228         // If the ioctl works for this, return it.
229
230         if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512;
231
232         // FIXME: explain why lseek(SEEK_END) is not used here!
233
234         // If not, do a binary search for the last location we can read.  (Some
235         // block devices don't do BLKGETSIZE right.)
236
237         do {
238                 char temp;
239
240                 pos = bottom + (top - bottom) / 2;
241
242                 // If we can read from the current location, it's bigger.
243
244                 if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) {
245                         if (bottom == top) bottom = top = (top+1) * 2;
246                         else bottom = pos;
247
248                 // If we can't, it's smaller.
249
250                 } else {
251                         if (bottom == top) {
252                                 if (!top) return 0;
253                                 bottom = top/2;
254                         }
255                         else top = pos;
256                 }
257         } while (bottom + 1 != top);
258
259         return pos + 1;
260 }
261 #endif
262
263 /* It is perfectly ok to pass in a NULL for either width or for
264  * height, in which case that value will not be set.  */
265 int get_terminal_width_height(int fd, unsigned *width, unsigned *height)
266 {
267         struct winsize win = { 0, 0, 0, 0 };
268         int ret = ioctl(fd, TIOCGWINSZ, &win);
269
270         if (height) {
271                 if (!win.ws_row) {
272                         char *s = getenv("LINES");
273                         if (s) win.ws_row = atoi(s);
274                 }
275                 if (win.ws_row <= 1 || win.ws_row >= 30000)
276                         win.ws_row = 24;
277                 *height = (int) win.ws_row;
278         }
279
280         if (width) {
281                 if (!win.ws_col) {
282                         char *s = getenv("COLUMNS");
283                         if (s) win.ws_col = atoi(s);
284                 }
285                 if (win.ws_col <= 1 || win.ws_col >= 30000)
286                         win.ws_col = 80;
287                 *width = (int) win.ws_col;
288         }
289
290         return ret;
291 }