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