e0b04778c7a30dd8a92f9ebe1a2a89616bf62a1f
[busybox-power] / debian / patches / ash-history-buffer.patch
1 --- a/shell/ash.c
2 +++ b/shell/ash.c
3 @@ -182,6 +182,24 @@
4  //config:        This option recreates the prompt string from the environment
5  //config:        variable each time it is displayed.
6  //config:
7 +//config:config ASH_HIST_BUFFER
8 +//config:      bool "History buffer"
9 +//config:      default n
10 +//config:      depends on ASH && FEATURE_EDITING_SAVEHISTORY
11 +//config:      help
12 +//config:        Allows you to set a temporary location for .ash_history.
13 +//config:        History is saved to this custom location, and written out to
14 +//config:        its default location (~/.ash_history) upon shell exit.
15 +//config:        Useful to prevent wear on flash-based storage devices.
16 +//config:
17 +//config:config ASH_HIST_BUFFER_PATH
18 +//config:      string "History buffer location"
19 +//config:      default "/tmp"
20 +//config:      depends on ASH && ASH_HIST_BUFFER
21 +//config:      help
22 +//config:        Directory which will be used to save the shell history until
23 +//config:        ash is exited.
24 +//config:
25  
26  //usage:#define ash_trivial_usage NOUSAGE_STR
27  //usage:#define ash_full_usage ""
28 @@ -12810,6 +12828,14 @@ exitshell(void)
29         char *p;
30         int status;
31  
32 +#if ENABLE_ASH_HIST_BUFFER
33 +       const char *tmphistory = lookupvar("HISTFILE");
34 +       const char *storedhistory = lookupvar("STOREDHISTFILE");
35 +
36 +       if (storedhistory) /* is NULL when setting up the history buffer failed; check for this before copying */
37 +               copy_file(tmphistory, storedhistory, FILEUTILS_FORCE | FILEUTILS_DEREFERENCE | FILEUTILS_PRESERVE_STATUS);
38 +#endif
39 +
40         status = exitstatus;
41         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
42         if (setjmp(loc.loc)) {
43 @@ -13056,9 +13082,59 @@ int ash_main(int argc UNUSED_PARAM, char
44                 if (hp == NULL) {
45                         hp = lookupvar("HOME");
46                         if (hp != NULL) {
47 +#if ENABLE_ASH_HIST_BUFFER
48 +                               char *tmppath;
49 +                               char *tmphistory;
50 +                               char *storedhistory;
51 +                               const char *user = lookupvar("USER");
52 +
53 +                               tmppath = concat_path_file(CONFIG_ASH_HIST_BUFFER_PATH, user);
54 +                               tmphistory = concat_path_file(tmppath, ".ash_history");
55 +                               storedhistory = concat_path_file(hp, ".ash_history");
56 +
57 +                               if (access(CONFIG_ASH_HIST_BUFFER_PATH, R_OK == -1)) {
58 +                                       bb_simple_perror_msg("could not access history buffer path");
59 +                                       goto bail;
60 +                               }
61 +
62 +                               if (bb_make_directory(tmppath, S_IRWXU, FILEUTILS_RECUR)) {
63 +                                       /* bb_make_directory is noisy, no need for an additional error message */
64 +                                       goto bail;
65 +                               } else {
66 +                                       struct stat stat_tmppath;
67 +                                       stat(tmppath, &stat_tmppath);
68 +                                       if (stat_tmppath.st_uid != geteuid() || stat_tmppath.st_mode & (S_IRWXG | S_IRWXO)) {
69 +                                               errno = 0;
70 +                                               bb_simple_perror_msg("history buffer is not exclusive to the shell user");   
71 +                                               goto bail;
72 +                                       }
73 +                               }
74 +
75 +                               if (access(tmphistory, R_OK | W_OK) == -1) {
76 +                                       if (access(storedhistory, R_OK) != -1) {
77 +                                               if (copy_file(storedhistory, tmphistory, FILEUTILS_FORCE | FILEUTILS_DEREFERENCE | FILEUTILS_PRESERVE_STATUS) == -1) {
78 +                                                       /* copy_file is noisy too, no need for an additional error message */
79 +                                                       goto bail;
80 +                                               }
81 +                                       }
82 +                               }
83 +                               setvar("STOREDHISTFILE", storedhistory, 0);
84 +                               goto out;
85 +
86 + bail:
87 +                               errno = 0;
88 +                               bb_simple_perror_msg("shell history will not be saved");
89 +                               tmphistory = xasprintf("/dev/null");
90 + out:
91 +                               setvar("HISTFILE", tmphistory, 0);
92 +                               free(storedhistory);
93 +                               free(tmphistory);
94 +                               free(tmppath);
95 +#else
96                                 char *defhp = concat_path_file(hp, ".ash_history");
97                                 setvar("HISTFILE", defhp, 0);
98                                 free(defhp);
99 +#endif
100                         }
101                 }
102         }