aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 14:11:12 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 14:11:12 +0000
commit67758035a4fe040c6ac69b39d61bcd6bddd7b827 (patch)
treea4a1db7f54c16d12fabe2626b8f1e235cd694e9e /libbb
parent811c449748d5bd0505f8510e5582892f94ac0cda (diff)
parentb83c9704128dd106071184e4b00335a3b8486857 (diff)
downloadbusybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.gz
busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.bz2
busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.zip
Merge commit 'b83c9704128dd106071184e4b00335a3b8486857' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Config.src5
-rw-r--r--libbb/appletlib.c2
-rw-r--r--libbb/get_line_from_file.c6
-rw-r--r--libbb/lineedit.c152
-rw-r--r--libbb/parse_config.c6
-rw-r--r--libbb/platform.c6
-rw-r--r--libbb/single_argv.c2
-rw-r--r--libbb/unicode.c7
-rw-r--r--libbb/xconnect.c16
9 files changed, 125 insertions, 77 deletions
diff --git a/libbb/Config.src b/libbb/Config.src
index a25af23b4..0ea8f43ab 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -80,11 +80,12 @@ config FEATURE_EDITING_VI
80 80
81config FEATURE_EDITING_HISTORY 81config FEATURE_EDITING_HISTORY
82 int "History size" 82 int "History size"
83 range 0 99999 83 # Don't allow way too big values here, code uses fixed "char *history[N]" struct member
84 range 0 9999
84 default 255 85 default 255
85 depends on FEATURE_EDITING 86 depends on FEATURE_EDITING
86 help 87 help
87 Specify command history size. 88 Specify command history size (0 - disable).
88 89
89config FEATURE_EDITING_SAVEHISTORY 90config FEATURE_EDITING_SAVEHISTORY
90 bool "History saving" 91 bool "History saving"
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 50e53aa25..a934f11bb 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -442,7 +442,7 @@ static void parse_config_file(void)
442 sct->m_mode |= mode_mask[(q - mode_chars) - i]; 442 sct->m_mode |= mode_mask[(q - mode_chars) - i];
443 } 443 }
444 444
445 /* Now get the the user/group info. */ 445 /* Now get the user/group info. */
446 446
447 s = skip_whitespace(e); 447 s = skip_whitespace(e);
448 448
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index a0ed9193f..9be10687b 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -44,8 +44,12 @@ char* FAST_FUNC bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno
44 idx -= 2; 44 idx -= 2;
45 } 45 }
46 } 46 }
47 if (end) 47 if (end) {
48 *end = idx; 48 *end = idx;
49 /* handle corner case when the file is not ended with '\n' */
50 if (ch == EOF && lineno != NULL)
51 (*lineno)++;
52 }
49 if (linebuf) { 53 if (linebuf) {
50 // huh, does fgets discard prior data on error like this? 54 // huh, does fgets discard prior data on error like this?
51 // I don't think so.... 55 // I don't think so....
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 92ecc330a..67c5e0baa 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -204,65 +204,82 @@ static void deinit_S(void)
204#if ENABLE_UNICODE_SUPPORT 204#if ENABLE_UNICODE_SUPPORT
205static size_t load_string(const char *src, int maxsize) 205static size_t load_string(const char *src, int maxsize)
206{ 206{
207 ssize_t len = mbstowcs(command_ps, src, maxsize - 1); 207 if (unicode_status == UNICODE_ON) {
208 if (len < 0) 208 ssize_t len = mbstowcs(command_ps, src, maxsize - 1);
209 len = 0; 209 if (len < 0)
210 command_ps[len] = BB_NUL; 210 len = 0;
211 return len; 211 command_ps[len] = BB_NUL;
212 return len;
213 } else {
214 unsigned i = 0;
215 while ((command_ps[i] = src[i]) != 0)
216 i++;
217 return i;
218 }
212} 219}
213static unsigned save_string(char *dst, unsigned maxsize) 220static unsigned save_string(char *dst, unsigned maxsize)
214{ 221{
222 if (unicode_status == UNICODE_ON) {
215# if !ENABLE_UNICODE_PRESERVE_BROKEN 223# if !ENABLE_UNICODE_PRESERVE_BROKEN
216 ssize_t len = wcstombs(dst, command_ps, maxsize - 1); 224 ssize_t len = wcstombs(dst, command_ps, maxsize - 1);
217 if (len < 0) 225 if (len < 0)
218 len = 0; 226 len = 0;
219 dst[len] = '\0'; 227 dst[len] = '\0';
220 return len; 228 return len;
221# else 229# else
222 unsigned dstpos = 0; 230 unsigned dstpos = 0;
223 unsigned srcpos = 0; 231 unsigned srcpos = 0;
224 232
225 maxsize--; 233 maxsize--;
226 while (dstpos < maxsize) { 234 while (dstpos < maxsize) {
227 wchar_t wc; 235 wchar_t wc;
228 int n = srcpos; 236 int n = srcpos;
229 237
230 /* Convert up to 1st invalid byte (or up to end) */ 238 /* Convert up to 1st invalid byte (or up to end) */
231 while ((wc = command_ps[srcpos]) != BB_NUL 239 while ((wc = command_ps[srcpos]) != BB_NUL
232 && !unicode_is_raw_byte(wc) 240 && !unicode_is_raw_byte(wc)
233 ) { 241 ) {
242 srcpos++;
243 }
244 command_ps[srcpos] = BB_NUL;
245 n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos);
246 if (n < 0) /* should not happen */
247 break;
248 dstpos += n;
249 if (wc == BB_NUL) /* usually is */
250 break;
251
252 /* We do have invalid byte here! */
253 command_ps[srcpos] = wc; /* restore it */
234 srcpos++; 254 srcpos++;
255 if (dstpos == maxsize)
256 break;
257 dst[dstpos++] = (char) wc;
235 } 258 }
236 command_ps[srcpos] = BB_NUL; 259 dst[dstpos] = '\0';
237 n = wcstombs(dst + dstpos, command_ps + n, maxsize - dstpos); 260 return dstpos;
238 if (n < 0) /* should not happen */
239 break;
240 dstpos += n;
241 if (wc == BB_NUL) /* usually is */
242 break;
243
244 /* We do have invalid byte here! */
245 command_ps[srcpos] = wc; /* restore it */
246 srcpos++;
247 if (dstpos == maxsize)
248 break;
249 dst[dstpos++] = (char) wc;
250 }
251 dst[dstpos] = '\0';
252 return dstpos;
253# endif 261# endif
262 } else {
263 unsigned i = 0;
264 while ((dst[i] = command_ps[i]) != 0)
265 i++;
266 return i;
267 }
254} 268}
255/* I thought just fputwc(c, stdout) would work. But no... */ 269/* I thought just fputwc(c, stdout) would work. But no... */
256static void BB_PUTCHAR(wchar_t c) 270static void BB_PUTCHAR(wchar_t c)
257{ 271{
258 char buf[MB_CUR_MAX + 1]; 272 if (unicode_status == UNICODE_ON) {
259 mbstate_t mbst = { 0 }; 273 char buf[MB_CUR_MAX + 1];
260 ssize_t len; 274 mbstate_t mbst = { 0 };
261 275 ssize_t len = wcrtomb(buf, c, &mbst);
262 len = wcrtomb(buf, c, &mbst); 276 if (len > 0) {
263 if (len > 0) { 277 buf[len] = '\0';
264 buf[len] = '\0'; 278 fputs(buf, stdout);
265 fputs(buf, stdout); 279 }
280 } else {
281 /* In this case, c is always one byte */
282 putchar(c);
266 } 283 }
267} 284}
268# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS 285# if ENABLE_UNICODE_COMBINING_WCHARS || ENABLE_UNICODE_WIDE_WCHARS
@@ -1234,12 +1251,26 @@ line_input_t* FAST_FUNC new_line_input_t(int flags)
1234{ 1251{
1235 line_input_t *n = xzalloc(sizeof(*n)); 1252 line_input_t *n = xzalloc(sizeof(*n));
1236 n->flags = flags; 1253 n->flags = flags;
1254 n->max_history = MAX_HISTORY;
1237 return n; 1255 return n;
1238} 1256}
1239 1257
1240 1258
1241#if MAX_HISTORY > 0 1259#if MAX_HISTORY > 0
1242 1260
1261unsigned size_from_HISTFILESIZE(const char *hp)
1262{
1263 int size = MAX_HISTORY;
1264 if (hp) {
1265 size = atoi(hp);
1266 if (size <= 0)
1267 return 1;
1268 if (size > MAX_HISTORY)
1269 return MAX_HISTORY;
1270 }
1271 return size;
1272}
1273
1243static void save_command_ps_at_cur_history(void) 1274static void save_command_ps_at_cur_history(void)
1244{ 1275{
1245 if (command_ps[0] != BB_NUL) { 1276 if (command_ps[0] != BB_NUL) {
@@ -1330,7 +1361,7 @@ static void load_history(line_input_t *st_parm)
1330 temp_h[idx] = line; 1361 temp_h[idx] = line;
1331 st_parm->cnt_history_in_file++; 1362 st_parm->cnt_history_in_file++;
1332 idx++; 1363 idx++;
1333 if (idx == MAX_HISTORY) 1364 if (idx == st_parm->max_history)
1334 idx = 0; 1365 idx = 0;
1335 } 1366 }
1336 fclose(fp); 1367 fclose(fp);
@@ -1339,18 +1370,18 @@ static void load_history(line_input_t *st_parm)
1339 if (st_parm->cnt_history_in_file) { 1370 if (st_parm->cnt_history_in_file) {
1340 while (temp_h[idx] == NULL) { 1371 while (temp_h[idx] == NULL) {
1341 idx++; 1372 idx++;
1342 if (idx == MAX_HISTORY) 1373 if (idx == st_parm->max_history)
1343 idx = 0; 1374 idx = 0;
1344 } 1375 }
1345 } 1376 }
1346 1377
1347 /* copy temp_h[] to st_parm->history[] */ 1378 /* copy temp_h[] to st_parm->history[] */
1348 for (i = 0; i < MAX_HISTORY;) { 1379 for (i = 0; i < st_parm->max_history;) {
1349 line = temp_h[idx]; 1380 line = temp_h[idx];
1350 if (!line) 1381 if (!line)
1351 break; 1382 break;
1352 idx++; 1383 idx++;
1353 if (idx == MAX_HISTORY) 1384 if (idx == st_parm->max_history)
1354 idx = 0; 1385 idx = 0;
1355 line_len = strlen(line); 1386 line_len = strlen(line);
1356 if (line_len >= MAX_LINELEN) 1387 if (line_len >= MAX_LINELEN)
@@ -1381,7 +1412,7 @@ static void save_history(char *str)
1381 1412
1382 /* did we write so much that history file needs trimming? */ 1413 /* did we write so much that history file needs trimming? */
1383 state->cnt_history_in_file++; 1414 state->cnt_history_in_file++;
1384 if (state->cnt_history_in_file > MAX_HISTORY * 4) { 1415 if (state->cnt_history_in_file > state->max_history * 4) {
1385 char *new_name; 1416 char *new_name;
1386 line_input_t *st_temp; 1417 line_input_t *st_temp;
1387 1418
@@ -1389,6 +1420,7 @@ static void save_history(char *str)
1389 * load them */ 1420 * load them */
1390 st_temp = new_line_input_t(state->flags); 1421 st_temp = new_line_input_t(state->flags);
1391 st_temp->hist_file = state->hist_file; 1422 st_temp->hist_file = state->hist_file;
1423 st_temp->max_history = state->max_history;
1392 load_history(st_temp); 1424 load_history(st_temp);
1393 1425
1394 /* write out temp file and replace hist_file atomically */ 1426 /* write out temp file and replace hist_file atomically */
@@ -1427,20 +1459,20 @@ static void remember_in_history(char *str)
1427 if (i && strcmp(state->history[i-1], str) == 0) 1459 if (i && strcmp(state->history[i-1], str) == 0)
1428 return; 1460 return;
1429 1461
1430 free(state->history[MAX_HISTORY]); /* redundant, paranoia */ 1462 free(state->history[state->max_history]); /* redundant, paranoia */
1431 state->history[MAX_HISTORY] = NULL; /* redundant, paranoia */ 1463 state->history[state->max_history] = NULL; /* redundant, paranoia */
1432 1464
1433 /* If history[] is full, remove the oldest command */ 1465 /* If history[] is full, remove the oldest command */
1434 /* we need to keep history[MAX_HISTORY] empty, hence >=, not > */ 1466 /* we need to keep history[state->max_history] empty, hence >=, not > */
1435 if (i >= MAX_HISTORY) { 1467 if (i >= state->max_history) {
1436 free(state->history[0]); 1468 free(state->history[0]);
1437 for (i = 0; i < MAX_HISTORY-1; i++) 1469 for (i = 0; i < state->max_history-1; i++)
1438 state->history[i] = state->history[i+1]; 1470 state->history[i] = state->history[i+1];
1439 /* i == MAX_HISTORY-1 */ 1471 /* i == state->max_history-1 */
1440 } 1472 }
1441 /* i <= MAX_HISTORY-1 */ 1473 /* i <= state->max_history-1 */
1442 state->history[i++] = xstrdup(str); 1474 state->history[i++] = xstrdup(str);
1443 /* i <= MAX_HISTORY */ 1475 /* i <= state->max_history */
1444 state->cur_history = i; 1476 state->cur_history = i;
1445 state->cnt_history = i; 1477 state->cnt_history = i;
1446# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY 1478# if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -1968,7 +2000,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
1968 maxsize = MAX_LINELEN; 2000 maxsize = MAX_LINELEN;
1969 S.maxsize = maxsize; 2001 S.maxsize = maxsize;
1970 2002
1971 /* With null flags, no other fields are ever used */ 2003 /* With zero flags, no other fields are ever used */
1972 state = st ? st : (line_input_t*) &const_int_0; 2004 state = st ? st : (line_input_t*) &const_int_0;
1973#if MAX_HISTORY > 0 2005#if MAX_HISTORY > 0
1974# if ENABLE_FEATURE_EDITING_SAVEHISTORY 2006# if ENABLE_FEATURE_EDITING_SAVEHISTORY
@@ -2020,7 +2052,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2020#endif 2052#endif
2021 2053
2022#if 0 2054#if 0
2023 for (i = 0; i <= MAX_HISTORY; i++) 2055 for (i = 0; i <= state->max_history; i++)
2024 bb_error_msg("history[%d]:'%s'", i, state->history[i]); 2056 bb_error_msg("history[%d]:'%s'", i, state->history[i]);
2025 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history); 2057 bb_error_msg("cur_history:%d cnt_history:%d", state->cur_history, state->cnt_history);
2026#endif 2058#endif
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index d471edbee..4b0236028 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -8,6 +8,12 @@
8 * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later. 8 * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later.
9 */ 9 */
10 10
11/*
12//usage:#define parse_trivial_usage
13//usage: "[-n MAXTOKENS] [-m MINTOKENS] [-d DELIMS] [-f FLAGS] FILE..."
14//usage:#define parse_full_usage ""
15*/
16
11#include "libbb.h" 17#include "libbb.h"
12 18
13#if defined ENABLE_PARSE && ENABLE_PARSE 19#if defined ENABLE_PARSE && ENABLE_PARSE
diff --git a/libbb/platform.c b/libbb/platform.c
index 1441a84ac..c594dcb4a 100644
--- a/libbb/platform.c
+++ b/libbb/platform.c
@@ -42,9 +42,9 @@ int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p)
42} 42}
43#endif 43#endif
44 44
45#ifndef HAVE_FDPRINTF 45#ifndef HAVE_DPRINTF
46/* dprintf is now actually part of POSIX.1, but was only added in 2008 */ 46/* dprintf is now part of POSIX.1, but was only added in 2008 */
47int fdprintf(int fd, const char *format, ...) 47int dprintf(int fd, const char *format, ...)
48{ 48{
49 va_list p; 49 va_list p;
50 int r; 50 int r;
diff --git a/libbb/single_argv.c b/libbb/single_argv.c
index 85137b40f..64844ddf8 100644
--- a/libbb/single_argv.c
+++ b/libbb/single_argv.c
@@ -10,6 +10,8 @@
10 10
11char* FAST_FUNC single_argv(char **argv) 11char* FAST_FUNC single_argv(char **argv)
12{ 12{
13 if (argv[1] && strcmp(argv[1], "--") == 0)
14 argv++;
13 if (!argv[1] || argv[2]) 15 if (!argv[1] || argv[2])
14 bb_show_usage(); 16 bb_show_usage();
15 return argv[1]; 17 return argv[1];
diff --git a/libbb/unicode.c b/libbb/unicode.c
index d01efd9a2..99dc1dfa6 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -23,12 +23,13 @@ uint8_t unicode_status;
23 23
24/* Unicode support using libc locale support. */ 24/* Unicode support using libc locale support. */
25 25
26void FAST_FUNC reinit_unicode(const char *LANG UNUSED_PARAM) 26void FAST_FUNC reinit_unicode(const char *LANG)
27{ 27{
28 static const char unicode_0x394[] = { 0xce, 0x94, 0 }; 28 static const char unicode_0x394[] = { 0xce, 0x94, 0 };
29 size_t width; 29 size_t width;
30 30
31//TODO: call setlocale(LC_ALL, LANG) here? 31//TODO: avoid repeated calls by caching last string?
32 setlocale(LC_ALL, (LANG && LANG[0]) ? LANG : "C");
32 33
33 /* In unicode, this is a one character string */ 34 /* In unicode, this is a one character string */
34// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused 35// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused
@@ -39,7 +40,7 @@ void FAST_FUNC reinit_unicode(const char *LANG UNUSED_PARAM)
39void FAST_FUNC init_unicode(void) 40void FAST_FUNC init_unicode(void)
40{ 41{
41 if (unicode_status == UNICODE_UNKNOWN) 42 if (unicode_status == UNICODE_UNKNOWN)
42 reinit_unicode(NULL /*getenv("LANG")*/); 43 reinit_unicode(getenv("LANG"));
43} 44}
44 45
45#else 46#else
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 127e2a5fc..4b7c110d3 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -134,16 +134,18 @@ int FAST_FUNC get_nport(const struct sockaddr *sa)
134 return -1; 134 return -1;
135} 135}
136 136
137void FAST_FUNC set_nport(len_and_sockaddr *lsa, unsigned port) 137void FAST_FUNC set_nport(struct sockaddr *sa, unsigned port)
138{ 138{
139#if ENABLE_FEATURE_IPV6 139#if ENABLE_FEATURE_IPV6
140 if (lsa->u.sa.sa_family == AF_INET6) { 140 if (sa->sa_family == AF_INET6) {
141 lsa->u.sin6.sin6_port = port; 141 struct sockaddr_in6 *sin6 = (void*) sa;
142 sin6->sin6_port = port;
142 return; 143 return;
143 } 144 }
144#endif 145#endif
145 if (lsa->u.sa.sa_family == AF_INET) { 146 if (sa->sa_family == AF_INET) {
146 lsa->u.sin.sin_port = port; 147 struct sockaddr_in *sin = (void*) sa;
148 sin->sin_port = port;
147 return; 149 return;
148 } 150 }
149 /* What? UNIX socket? IPX?? :) */ 151 /* What? UNIX socket? IPX?? :) */
@@ -283,7 +285,7 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
283 memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen); 285 memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen);
284 286
285 set_port: 287 set_port:
286 set_nport(r, htons(port)); 288 set_nport(&r->u.sa, htons(port));
287 ret: 289 ret:
288 if (result) 290 if (result)
289 freeaddrinfo(result); 291 freeaddrinfo(result);
@@ -369,7 +371,7 @@ static int create_and_bind_or_die(const char *bindaddr, int port, int sock_type)
369 fd = xsocket(lsa->u.sa.sa_family, sock_type, 0); 371 fd = xsocket(lsa->u.sa.sa_family, sock_type, 0);
370 } else { 372 } else {
371 fd = xsocket_type(&lsa, IF_FEATURE_IPV6(AF_UNSPEC,) sock_type); 373 fd = xsocket_type(&lsa, IF_FEATURE_IPV6(AF_UNSPEC,) sock_type);
372 set_nport(lsa, htons(port)); 374 set_nport(&lsa->u.sa, htons(port));
373 } 375 }
374 setsockopt_reuseaddr(fd); 376 setsockopt_reuseaddr(fd);
375 xbind(fd, &lsa->u.sa, lsa->len); 377 xbind(fd, &lsa->u.sa, lsa->len);