aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-09-04 16:12:33 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-09-04 16:12:33 +0200
commitbede215cf105377a1127532d2d710924cb58cc39 (patch)
treed0227961b7eb002cb03653f2e69211e6cf13d598
parent4840ae8a06298e987374fa3cc6d7e4969fd19344 (diff)
downloadbusybox-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.h9
-rw-r--r--libbb/Config.src7
-rw-r--r--libbb/lineedit.c68
-rw-r--r--shell/ash.c4
-rw-r--r--shell/hush.c4
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 */
1448int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; 1454int 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
1456void save_history(line_input_t *st);
1457# endif
1449#else 1458#else
1450#define MAX_HISTORY 0 1459#define MAX_HISTORY 0
1451int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; 1460int 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
97config 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
97config FEATURE_REVERSE_SEARCH 104config 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
1401void 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
1396static void save_history(char *str) 1445static 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)
1541static void hush_exit(int exitcode) NORETURN; 1541static void hush_exit(int exitcode) NORETURN;
1542static void hush_exit(int exitcode) 1542static 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];