diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-09-04 16:12:33 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-09-04 16:12:33 +0200 |
commit | bede215cf105377a1127532d2d710924cb58cc39 (patch) | |
tree | d0227961b7eb002cb03653f2e69211e6cf13d598 | |
parent | 4840ae8a06298e987374fa3cc6d7e4969fd19344 (diff) | |
download | busybox-w32-bede215cf105377a1127532d2d710924cb58cc39.tar.gz busybox-w32-bede215cf105377a1127532d2d710924cb58cc39.tar.bz2 busybox-w32-bede215cf105377a1127532d2d710924cb58cc39.zip |
lineedit: add support for history saving on exit
Based on the patch by Dennis Groenen <tj.groenen@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/libbb.h | 9 | ||||
-rw-r--r-- | libbb/Config.src | 7 | ||||
-rw-r--r-- | libbb/lineedit.c | 68 | ||||
-rw-r--r-- | shell/ash.c | 4 | ||||
-rw-r--r-- | shell/hush.c | 4 |
5 files changed, 86 insertions, 6 deletions
diff --git a/include/libbb.h b/include/libbb.h index 63d041957..91343a95e 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1421,6 +1421,12 @@ typedef struct line_input_t { | |||
1421 | int cur_history; | 1421 | int cur_history; |
1422 | int max_history; /* must never be <= 0 */ | 1422 | int max_history; /* must never be <= 0 */ |
1423 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1423 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY |
1424 | /* meaning of this field depends on FEATURE_EDITING_SAVE_ON_EXIT: | ||
1425 | * if !FEATURE_EDITING_SAVE_ON_EXIT: "how many lines are | ||
1426 | * in on-disk history" | ||
1427 | * if FEATURE_EDITING_SAVE_ON_EXIT: "how many in-memory lines are | ||
1428 | * also in on-disk history (and thus need to be skipped on save)" | ||
1429 | */ | ||
1424 | unsigned cnt_history_in_file; | 1430 | unsigned cnt_history_in_file; |
1425 | const char *hist_file; | 1431 | const char *hist_file; |
1426 | # endif | 1432 | # endif |
@@ -1446,6 +1452,9 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; | |||
1446 | * >0 length of input string, including terminating '\n' | 1452 | * >0 length of input string, including terminating '\n' |
1447 | */ | 1453 | */ |
1448 | int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; | 1454 | int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; |
1455 | # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | ||
1456 | void save_history(line_input_t *st); | ||
1457 | # endif | ||
1449 | #else | 1458 | #else |
1450 | #define MAX_HISTORY 0 | 1459 | #define MAX_HISTORY 0 |
1451 | int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; | 1460 | int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; |
diff --git a/libbb/Config.src b/libbb/Config.src index aa442365a..f6f88b9ce 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -94,6 +94,13 @@ config FEATURE_EDITING_SAVEHISTORY | |||
94 | help | 94 | help |
95 | Enable history saving in shells. | 95 | Enable history saving in shells. |
96 | 96 | ||
97 | config FEATURE_EDITING_SAVE_ON_EXIT | ||
98 | bool "Save history on shell exit, not after every command" | ||
99 | default n | ||
100 | depends on FEATURE_EDITING_SAVEHISTORY | ||
101 | help | ||
102 | Save history on shell exit, not after every command. | ||
103 | |||
97 | config FEATURE_REVERSE_SEARCH | 104 | config FEATURE_REVERSE_SEARCH |
98 | bool "Reverse history search" | 105 | bool "Reverse history search" |
99 | default y | 106 | default y |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5d139043a..0786f9ae6 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -1351,7 +1351,9 @@ static void load_history(line_input_t *st_parm) | |||
1351 | 1351 | ||
1352 | /* fill temp_h[], retaining only last MAX_HISTORY lines */ | 1352 | /* fill temp_h[], retaining only last MAX_HISTORY lines */ |
1353 | memset(temp_h, 0, sizeof(temp_h)); | 1353 | memset(temp_h, 0, sizeof(temp_h)); |
1354 | st_parm->cnt_history_in_file = idx = 0; | 1354 | idx = 0; |
1355 | if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) | ||
1356 | st_parm->cnt_history_in_file = 0; | ||
1355 | while ((line = xmalloc_fgetline(fp)) != NULL) { | 1357 | while ((line = xmalloc_fgetline(fp)) != NULL) { |
1356 | if (line[0] == '\0') { | 1358 | if (line[0] == '\0') { |
1357 | free(line); | 1359 | free(line); |
@@ -1359,7 +1361,8 @@ static void load_history(line_input_t *st_parm) | |||
1359 | } | 1361 | } |
1360 | free(temp_h[idx]); | 1362 | free(temp_h[idx]); |
1361 | temp_h[idx] = line; | 1363 | temp_h[idx] = line; |
1362 | st_parm->cnt_history_in_file++; | 1364 | if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) |
1365 | st_parm->cnt_history_in_file++; | ||
1363 | idx++; | 1366 | idx++; |
1364 | if (idx == st_parm->max_history) | 1367 | if (idx == st_parm->max_history) |
1365 | idx = 0; | 1368 | idx = 0; |
@@ -1389,15 +1392,66 @@ static void load_history(line_input_t *st_parm) | |||
1389 | st_parm->history[i++] = line; | 1392 | st_parm->history[i++] = line; |
1390 | } | 1393 | } |
1391 | st_parm->cnt_history = i; | 1394 | st_parm->cnt_history = i; |
1395 | if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT) | ||
1396 | st_parm->cnt_history_in_file = i; | ||
1392 | } | 1397 | } |
1393 | } | 1398 | } |
1394 | 1399 | ||
1395 | /* state->flags is already checked to be nonzero */ | 1400 | # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
1401 | void save_history(line_input_t *st) | ||
1402 | { | ||
1403 | FILE *fp; | ||
1404 | |||
1405 | if (!(st->flags & SAVE_HISTORY)) | ||
1406 | return; | ||
1407 | if (!st->hist_file) | ||
1408 | return; | ||
1409 | if (st->cnt_history <= st->cnt_history_in_file) | ||
1410 | return; | ||
1411 | |||
1412 | fp = fopen(st->hist_file, "a"); | ||
1413 | if (fp) { | ||
1414 | int i, fd; | ||
1415 | char *new_name; | ||
1416 | line_input_t *st_temp; | ||
1417 | |||
1418 | for (i = st->cnt_history_in_file; i < st->cnt_history; i++) | ||
1419 | fprintf(fp, "%s\n", st->history[i]); | ||
1420 | fclose(fp); | ||
1421 | |||
1422 | /* we may have concurrently written entries from others. | ||
1423 | * load them */ | ||
1424 | st_temp = new_line_input_t(st->flags); | ||
1425 | st_temp->hist_file = st->hist_file; | ||
1426 | st_temp->max_history = st->max_history; | ||
1427 | load_history(st_temp); | ||
1428 | |||
1429 | /* write out temp file and replace hist_file atomically */ | ||
1430 | new_name = xasprintf("%s.%u.new", st->hist_file, (int) getpid()); | ||
1431 | fd = open(new_name, O_WRONLY | O_CREAT | O_TRUNC, 0600); | ||
1432 | if (fd >= 0) { | ||
1433 | fp = xfdopen_for_write(fd); | ||
1434 | for (i = 0; i < st_temp->cnt_history; i++) | ||
1435 | fprintf(fp, "%s\n", st_temp->history[i]); | ||
1436 | fclose(fp); | ||
1437 | if (rename(new_name, st->hist_file) == 0) | ||
1438 | st->cnt_history_in_file = st_temp->cnt_history; | ||
1439 | } | ||
1440 | free(new_name); | ||
1441 | free_line_input_t(st_temp); | ||
1442 | } | ||
1443 | } | ||
1444 | # else | ||
1396 | static void save_history(char *str) | 1445 | static void save_history(char *str) |
1397 | { | 1446 | { |
1398 | int fd; | 1447 | int fd; |
1399 | int len, len2; | 1448 | int len, len2; |
1400 | 1449 | ||
1450 | if (!(state->flags & SAVE_HISTORY)) | ||
1451 | return; | ||
1452 | if (!state->hist_file) | ||
1453 | return; | ||
1454 | |||
1401 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600); | 1455 | fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0600); |
1402 | if (fd < 0) | 1456 | if (fd < 0) |
1403 | return; | 1457 | return; |
@@ -1441,6 +1495,7 @@ static void save_history(char *str) | |||
1441 | free_line_input_t(st_temp); | 1495 | free_line_input_t(st_temp); |
1442 | } | 1496 | } |
1443 | } | 1497 | } |
1498 | # endif | ||
1444 | # else | 1499 | # else |
1445 | # define load_history(a) ((void)0) | 1500 | # define load_history(a) ((void)0) |
1446 | # define save_history(a) ((void)0) | 1501 | # define save_history(a) ((void)0) |
@@ -1469,15 +1524,16 @@ static void remember_in_history(char *str) | |||
1469 | for (i = 0; i < state->max_history-1; i++) | 1524 | for (i = 0; i < state->max_history-1; i++) |
1470 | state->history[i] = state->history[i+1]; | 1525 | state->history[i] = state->history[i+1]; |
1471 | /* i == state->max_history-1 */ | 1526 | /* i == state->max_history-1 */ |
1527 | if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT && state->cnt_history_in_file) | ||
1528 | state->cnt_history_in_file--; | ||
1472 | } | 1529 | } |
1473 | /* i <= state->max_history-1 */ | 1530 | /* i <= state->max_history-1 */ |
1474 | state->history[i++] = xstrdup(str); | 1531 | state->history[i++] = xstrdup(str); |
1475 | /* i <= state->max_history */ | 1532 | /* i <= state->max_history */ |
1476 | state->cur_history = i; | 1533 | state->cur_history = i; |
1477 | state->cnt_history = i; | 1534 | state->cnt_history = i; |
1478 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY | 1535 | # if ENABLE_FEATURE_EDITING_SAVEHISTORY && !ENABLE_FEATURE_EDITING_SAVE_ON_EXIT |
1479 | if ((state->flags & SAVE_HISTORY) && state->hist_file) | 1536 | save_history(str); |
1480 | save_history(str); | ||
1481 | # endif | 1537 | # endif |
1482 | IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;) | 1538 | IF_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;) |
1483 | } | 1539 | } |
diff --git a/shell/ash.c b/shell/ash.c index bf376bd0d..14472cb61 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -12888,6 +12888,10 @@ exitshell(void) | |||
12888 | char *p; | 12888 | char *p; |
12889 | int status; | 12889 | int status; |
12890 | 12890 | ||
12891 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | ||
12892 | save_history(line_input_state); | ||
12893 | #endif | ||
12894 | |||
12891 | status = exitstatus; | 12895 | status = exitstatus; |
12892 | TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); | 12896 | TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); |
12893 | if (setjmp(loc.loc)) { | 12897 | if (setjmp(loc.loc)) { |
diff --git a/shell/hush.c b/shell/hush.c index 42143fd9e..a9e2dd311 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1541,6 +1541,10 @@ static sighandler_t pick_sighandler(unsigned sig) | |||
1541 | static void hush_exit(int exitcode) NORETURN; | 1541 | static void hush_exit(int exitcode) NORETURN; |
1542 | static void hush_exit(int exitcode) | 1542 | static void hush_exit(int exitcode) |
1543 | { | 1543 | { |
1544 | #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT | ||
1545 | save_history(G.line_input_state); | ||
1546 | #endif | ||
1547 | |||
1544 | fflush_all(); | 1548 | fflush_all(); |
1545 | if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { | 1549 | if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { |
1546 | char *argv[3]; | 1550 | char *argv[3]; |