diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-22 14:11:12 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 14:11:12 +0000 |
commit | 67758035a4fe040c6ac69b39d61bcd6bddd7b827 (patch) | |
tree | a4a1db7f54c16d12fabe2626b8f1e235cd694e9e /libbb/lineedit.c | |
parent | 811c449748d5bd0505f8510e5582892f94ac0cda (diff) | |
parent | b83c9704128dd106071184e4b00335a3b8486857 (diff) | |
download | busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.gz busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.tar.bz2 busybox-w32-67758035a4fe040c6ac69b39d61bcd6bddd7b827.zip |
Merge commit 'b83c9704128dd106071184e4b00335a3b8486857' into merge
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r-- | libbb/lineedit.c | 152 |
1 files changed, 92 insertions, 60 deletions
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 |
205 | static size_t load_string(const char *src, int maxsize) | 205 | static 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 | } |
213 | static unsigned save_string(char *dst, unsigned maxsize) | 220 | static 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... */ |
256 | static void BB_PUTCHAR(wchar_t c) | 270 | static 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 | ||
1261 | unsigned 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 | |||
1243 | static void save_command_ps_at_cur_history(void) | 1274 | static 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 |