diff options
author | Ron Yorston <rmy@pobox.com> | 2021-10-13 14:37:51 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-10-13 14:37:51 +0100 |
commit | 0ecf1aea459571b48dc68ddc2b7b9265740fa960 (patch) | |
tree | 491d6184a44b8b525a4ca35759d622aecd7f6344 /libbb/lineedit.c | |
parent | 4859ddcb20616718efbea12c6bf8b27c469b68de (diff) | |
parent | aaf3d5ba74c5da97ff80b61f30cb8dd225d39096 (diff) | |
download | busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.gz busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.bz2 busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb/lineedit.c')
-rw-r--r-- | libbb/lineedit.c | 94 |
1 files changed, 56 insertions, 38 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 7c46fa5db..8abc87976 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -135,10 +135,6 @@ enum { | |||
135 | : 0x7ff0 | 135 | : 0x7ff0 |
136 | }; | 136 | }; |
137 | 137 | ||
138 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
139 | static const char null_str[] ALIGN1 = ""; | ||
140 | #endif | ||
141 | |||
142 | /* We try to minimize both static and stack usage. */ | 138 | /* We try to minimize both static and stack usage. */ |
143 | struct lineedit_statics { | 139 | struct lineedit_statics { |
144 | line_input_t *state; | 140 | line_input_t *state; |
@@ -161,12 +157,13 @@ struct lineedit_statics { | |||
161 | 157 | ||
162 | #if ENABLE_USERNAME_OR_HOMEDIR | 158 | #if ENABLE_USERNAME_OR_HOMEDIR |
163 | char *user_buf; | 159 | char *user_buf; |
164 | char *home_pwd_buf; /* = (char*)null_str; */ | 160 | char *home_pwd_buf; |
161 | smallint got_user_strings; | ||
165 | #endif | 162 | #endif |
166 | 163 | ||
167 | #if ENABLE_FEATURE_TAB_COMPLETION | 164 | #if ENABLE_FEATURE_TAB_COMPLETION |
168 | char **matches; | ||
169 | unsigned num_matches; | 165 | unsigned num_matches; |
166 | char **matches; | ||
170 | #endif | 167 | #endif |
171 | 168 | ||
172 | #if ENABLE_FEATURE_EDITING_WINCH | 169 | #if ENABLE_FEATURE_EDITING_WINCH |
@@ -192,7 +189,7 @@ struct lineedit_statics { | |||
192 | }; | 189 | }; |
193 | 190 | ||
194 | /* See lineedit_ptr_hack.c */ | 191 | /* See lineedit_ptr_hack.c */ |
195 | extern struct lineedit_statics *const lineedit_ptr_to_statics; | 192 | extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics; |
196 | 193 | ||
197 | #define S (*lineedit_ptr_to_statics) | 194 | #define S (*lineedit_ptr_to_statics) |
198 | #define state (S.state ) | 195 | #define state (S.state ) |
@@ -207,15 +204,15 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics; | |||
207 | #define prompt_last_line (S.prompt_last_line) | 204 | #define prompt_last_line (S.prompt_last_line) |
208 | #define user_buf (S.user_buf ) | 205 | #define user_buf (S.user_buf ) |
209 | #define home_pwd_buf (S.home_pwd_buf ) | 206 | #define home_pwd_buf (S.home_pwd_buf ) |
210 | #define matches (S.matches ) | 207 | #define got_user_strings (S.got_user_strings) |
211 | #define num_matches (S.num_matches ) | 208 | #define num_matches (S.num_matches ) |
209 | #define matches (S.matches ) | ||
212 | #define delptr (S.delptr ) | 210 | #define delptr (S.delptr ) |
213 | #define newdelflag (S.newdelflag ) | 211 | #define newdelflag (S.newdelflag ) |
214 | #define delbuf (S.delbuf ) | 212 | #define delbuf (S.delbuf ) |
215 | 213 | ||
216 | #define INIT_S() do { \ | 214 | #define INIT_S() do { \ |
217 | (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ | 215 | XZALLOC_CONST_PTR(&lineedit_ptr_to_statics, sizeof(S)); \ |
218 | barrier(); \ | ||
219 | } while (0) | 216 | } while (0) |
220 | 217 | ||
221 | static void deinit_S(void) | 218 | static void deinit_S(void) |
@@ -227,14 +224,47 @@ static void deinit_S(void) | |||
227 | #endif | 224 | #endif |
228 | #if ENABLE_USERNAME_OR_HOMEDIR | 225 | #if ENABLE_USERNAME_OR_HOMEDIR |
229 | free(user_buf); | 226 | free(user_buf); |
230 | if (home_pwd_buf != null_str) | 227 | free(home_pwd_buf); |
231 | free(home_pwd_buf); | ||
232 | #endif | 228 | #endif |
233 | free(lineedit_ptr_to_statics); | 229 | free(lineedit_ptr_to_statics); |
234 | } | 230 | } |
235 | #define DEINIT_S() deinit_S() | 231 | #define DEINIT_S() deinit_S() |
236 | 232 | ||
237 | 233 | ||
234 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
235 | /* Call getpwuid() only if necessary. | ||
236 | * E.g. if PS1=':', no user database reading is needed to generate prompt. | ||
237 | * (Unfortunately, default PS1='\w \$' needs it, \w abbreviates homedir | ||
238 | * as ~/... - for that it needs to *know* the homedir...) | ||
239 | */ | ||
240 | static void get_user_strings(void) | ||
241 | { | ||
242 | struct passwd *entry; | ||
243 | |||
244 | got_user_strings = 1; | ||
245 | entry = getpwuid(geteuid()); | ||
246 | if (entry) { | ||
247 | user_buf = xstrdup(entry->pw_name); | ||
248 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | static const char *get_username_str(void) | ||
253 | { | ||
254 | if (!got_user_strings) | ||
255 | get_user_strings(); | ||
256 | return user_buf ? user_buf : ""; | ||
257 | /* btw, bash uses "I have no name!" string if uid has no entry */ | ||
258 | } | ||
259 | |||
260 | static NOINLINE const char *get_homedir_or_NULL(void) | ||
261 | { | ||
262 | if (!got_user_strings) | ||
263 | get_user_strings(); | ||
264 | return home_pwd_buf; | ||
265 | } | ||
266 | #endif | ||
267 | |||
238 | #if ENABLE_UNICODE_SUPPORT | 268 | #if ENABLE_UNICODE_SUPPORT |
239 | static size_t load_string(const char *src) | 269 | static size_t load_string(const char *src) |
240 | { | 270 | { |
@@ -748,11 +778,11 @@ static char *username_path_completion(char *ud) | |||
748 | struct passwd *entry; | 778 | struct passwd *entry; |
749 | #endif | 779 | #endif |
750 | char *tilde_name = ud; | 780 | char *tilde_name = ud; |
751 | char *home = NULL; | 781 | const char *home = NULL; |
752 | 782 | ||
753 | ud++; /* skip ~ */ | 783 | ud++; /* skip ~ */ |
754 | if (*ud == '/') { /* "~/..." */ | 784 | if (*ud == '/') { /* "~/..." */ |
755 | home = home_pwd_buf; | 785 | home = get_homedir_or_NULL(); |
756 | # if !ENABLE_PLATFORM_MINGW32 | 786 | # if !ENABLE_PLATFORM_MINGW32 |
757 | } else { | 787 | } else { |
758 | /* "~user/..." */ | 788 | /* "~user/..." */ |
@@ -1881,7 +1911,7 @@ vi_back_motion(void) | |||
1881 | input_backward(1); | 1911 | input_backward(1); |
1882 | } | 1912 | } |
1883 | } | 1913 | } |
1884 | #endif | 1914 | #endif /* ENABLE_FEATURE_EDITING_VI */ |
1885 | 1915 | ||
1886 | /* Modelled after bash 4.0 behavior of Ctrl-<arrow> */ | 1916 | /* Modelled after bash 4.0 behavior of Ctrl-<arrow> */ |
1887 | static void ctrl_left(void) | 1917 | static void ctrl_left(void) |
@@ -1982,7 +2012,7 @@ static void ask_terminal(void) | |||
1982 | } | 2012 | } |
1983 | } | 2013 | } |
1984 | #else | 2014 | #else |
1985 | #define ask_terminal() ((void)0) | 2015 | # define ask_terminal() ((void)0) |
1986 | #endif | 2016 | #endif |
1987 | 2017 | ||
1988 | /* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing: | 2018 | /* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing: |
@@ -2091,7 +2121,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2091 | 2121 | ||
2092 | switch (c) { | 2122 | switch (c) { |
2093 | case 'u': | 2123 | case 'u': |
2094 | pbuf = user_buf ? user_buf : (char*)""; | 2124 | pbuf = (char*)get_username_str(); |
2095 | break; | 2125 | break; |
2096 | case 'H': | 2126 | case 'H': |
2097 | case 'h': | 2127 | case 'h': |
@@ -2113,14 +2143,15 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2113 | case 'w': /* current dir */ | 2143 | case 'w': /* current dir */ |
2114 | case 'W': /* basename of cur dir */ | 2144 | case 'W': /* basename of cur dir */ |
2115 | if (!cwd_buf) { | 2145 | if (!cwd_buf) { |
2146 | const char *home; | ||
2116 | cwd_buf = xrealloc_getcwd_or_warn(NULL); | 2147 | cwd_buf = xrealloc_getcwd_or_warn(NULL); |
2117 | if (!cwd_buf) | 2148 | if (!cwd_buf) |
2118 | cwd_buf = (char *)bb_msg_unknown; | 2149 | cwd_buf = (char *)bb_msg_unknown; |
2119 | else if (home_pwd_buf[0]) { | 2150 | else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { |
2120 | char *after_home_user; | 2151 | char *after_home_user; |
2121 | 2152 | ||
2122 | /* /home/user[/something] -> ~[/something] */ | 2153 | /* /home/user[/something] -> ~[/something] */ |
2123 | after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); | 2154 | after_home_user = is_prefixed_with(cwd_buf, home); |
2124 | if (after_home_user | 2155 | if (after_home_user |
2125 | && (*after_home_user == '/' || *after_home_user == '\0') | 2156 | && (*after_home_user == '/' || *after_home_user == '\0') |
2126 | ) { | 2157 | ) { |
@@ -2176,7 +2207,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2176 | if (c == '\n') | 2207 | if (c == '\n') |
2177 | cmdedit_prmt_len = 0; | 2208 | cmdedit_prmt_len = 0; |
2178 | else if (flg_not_length != ']') { | 2209 | else if (flg_not_length != ']') { |
2179 | #if ENABLE_UNICODE_SUPPORT | 2210 | # if ENABLE_UNICODE_SUPPORT |
2180 | if (n == 1) { | 2211 | if (n == 1) { |
2181 | /* Only count single-byte characters and the first of multi-byte characters */ | 2212 | /* Only count single-byte characters and the first of multi-byte characters */ |
2182 | if ((unsigned char)*pbuf < 0x80 /* single byte character */ | 2213 | if ((unsigned char)*pbuf < 0x80 /* single byte character */ |
@@ -2187,9 +2218,9 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
2187 | } else { | 2218 | } else { |
2188 | cmdedit_prmt_len += unicode_strwidth(pbuf); | 2219 | cmdedit_prmt_len += unicode_strwidth(pbuf); |
2189 | } | 2220 | } |
2190 | #else | 2221 | # else |
2191 | cmdedit_prmt_len += n; | 2222 | cmdedit_prmt_len += n; |
2192 | #endif | 2223 | # endif |
2193 | } | 2224 | } |
2194 | } | 2225 | } |
2195 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); | 2226 | prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); |
@@ -2416,7 +2447,7 @@ static int32_t reverse_i_search(int timeout) | |||
2416 | } | 2447 | } |
2417 | 2448 | ||
2418 | /* Append this char */ | 2449 | /* Append this char */ |
2419 | #if ENABLE_UNICODE_SUPPORT | 2450 | # if ENABLE_UNICODE_SUPPORT |
2420 | if (unicode_status == UNICODE_ON) { | 2451 | if (unicode_status == UNICODE_ON) { |
2421 | mbstate_t mbstate = { 0 }; | 2452 | mbstate_t mbstate = { 0 }; |
2422 | char buf[MB_CUR_MAX + 1]; | 2453 | char buf[MB_CUR_MAX + 1]; |
@@ -2427,7 +2458,7 @@ static int32_t reverse_i_search(int timeout) | |||
2427 | strcpy(match_buf + match_buf_len, buf); | 2458 | strcpy(match_buf + match_buf_len, buf); |
2428 | } | 2459 | } |
2429 | } else | 2460 | } else |
2430 | #endif | 2461 | # endif |
2431 | if (match_buf_len < sizeof(match_buf) - 1) { | 2462 | if (match_buf_len < sizeof(match_buf) - 1) { |
2432 | match_buf[match_buf_len] = ic; | 2463 | match_buf[match_buf_len] = ic; |
2433 | match_buf[match_buf_len + 1] = '\0'; | 2464 | match_buf[match_buf_len + 1] = '\0'; |
@@ -2479,7 +2510,7 @@ static int32_t reverse_i_search(int timeout) | |||
2479 | 2510 | ||
2480 | return ic; | 2511 | return ic; |
2481 | } | 2512 | } |
2482 | #endif | 2513 | #endif /* ENABLE_FEATURE_REVERSE_SEARCH */ |
2483 | 2514 | ||
2484 | #if ENABLE_FEATURE_EDITING_WINCH | 2515 | #if ENABLE_FEATURE_EDITING_WINCH |
2485 | static void sigaction2(int sig, struct sigaction *act) | 2516 | static void sigaction2(int sig, struct sigaction *act) |
@@ -2521,7 +2552,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2521 | //command_len = 0; - done by INIT_S() | 2552 | //command_len = 0; - done by INIT_S() |
2522 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | 2553 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ |
2523 | cmdedit_termw = 80; | 2554 | cmdedit_termw = 80; |
2524 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) | ||
2525 | IF_FEATURE_EDITING_VI(delptr = delbuf;) | 2555 | IF_FEATURE_EDITING_VI(delptr = delbuf;) |
2526 | 2556 | ||
2527 | #if !ENABLE_PLATFORM_MINGW32 | 2557 | #if !ENABLE_PLATFORM_MINGW32 |
@@ -2589,18 +2619,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2589 | tcsetattr_stdin_TCSANOW(&new_settings); | 2619 | tcsetattr_stdin_TCSANOW(&new_settings); |
2590 | #endif | 2620 | #endif |
2591 | 2621 | ||
2592 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
2593 | { | ||
2594 | struct passwd *entry; | ||
2595 | |||
2596 | entry = getpwuid(geteuid()); | ||
2597 | if (entry) { | ||
2598 | user_buf = xstrdup(entry->pw_name); | ||
2599 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
2600 | } | ||
2601 | } | ||
2602 | #endif | ||
2603 | |||
2604 | #if 0 | 2622 | #if 0 |
2605 | for (i = 0; i <= state->max_history; i++) | 2623 | for (i = 0; i <= state->max_history; i++) |
2606 | bb_error_msg("history[%d]:'%s'", i, state->history[i]); | 2624 | bb_error_msg("history[%d]:'%s'", i, state->history[i]); |