diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-11 23:08:31 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-11 23:08:31 +0200 |
commit | f4fcd74a6e3d5cd2ec44cd6ce90be8a0ed108467 (patch) | |
tree | d79b1828fa7f42bda6f0c3e3d8ad5d73da2e3e0a | |
parent | 6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467 (diff) | |
download | busybox-w32-f4fcd74a6e3d5cd2ec44cd6ce90be8a0ed108467.tar.gz busybox-w32-f4fcd74a6e3d5cd2ec44cd6ce90be8a0ed108467.tar.bz2 busybox-w32-f4fcd74a6e3d5cd2ec44cd6ce90be8a0ed108467.zip |
shell: do not read user database for every prompt - only for those which need it
function old new delta
get_user_strings - 52 +52
get_homedir_or_NULL - 23 +23
parse_and_put_prompt 823 838 +15
null_str 1 - -1
complete_cmd_dir_file 814 812 -2
deinit_S 51 42 -9
read_line_input 3059 3015 -44
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 1/3 up/down: 90/-56) Total: 34 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/lineedit.c | 73 |
1 files changed, 46 insertions, 27 deletions
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 9960448ec..e14c78707 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 |
@@ -207,8 +204,9 @@ extern struct lineedit_statics *BB_GLOBAL_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 ) |
@@ -226,14 +224,47 @@ static void deinit_S(void) | |||
226 | #endif | 224 | #endif |
227 | #if ENABLE_USERNAME_OR_HOMEDIR | 225 | #if ENABLE_USERNAME_OR_HOMEDIR |
228 | free(user_buf); | 226 | free(user_buf); |
229 | if (home_pwd_buf != null_str) | 227 | free(home_pwd_buf); |
230 | free(home_pwd_buf); | ||
231 | #endif | 228 | #endif |
232 | free(lineedit_ptr_to_statics); | 229 | free(lineedit_ptr_to_statics); |
233 | } | 230 | } |
234 | #define DEINIT_S() deinit_S() | 231 | #define DEINIT_S() deinit_S() |
235 | 232 | ||
236 | 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 | |||
237 | #if ENABLE_UNICODE_SUPPORT | 268 | #if ENABLE_UNICODE_SUPPORT |
238 | static size_t load_string(const char *src) | 269 | static size_t load_string(const char *src) |
239 | { | 270 | { |
@@ -691,11 +722,11 @@ static char *username_path_completion(char *ud) | |||
691 | { | 722 | { |
692 | struct passwd *entry; | 723 | struct passwd *entry; |
693 | char *tilde_name = ud; | 724 | char *tilde_name = ud; |
694 | char *home = NULL; | 725 | const char *home = NULL; |
695 | 726 | ||
696 | ud++; /* skip ~ */ | 727 | ud++; /* skip ~ */ |
697 | if (*ud == '/') { /* "~/..." */ | 728 | if (*ud == '/') { /* "~/..." */ |
698 | home = home_pwd_buf; | 729 | home = get_homedir_or_NULL(); |
699 | } else { | 730 | } else { |
700 | /* "~user/..." */ | 731 | /* "~user/..." */ |
701 | ud = strchr(ud, '/'); | 732 | ud = strchr(ud, '/'); |
@@ -1971,7 +2002,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1971 | 2002 | ||
1972 | switch (c) { | 2003 | switch (c) { |
1973 | case 'u': | 2004 | case 'u': |
1974 | pbuf = user_buf ? user_buf : (char*)""; | 2005 | pbuf = (char*)get_username_str(); |
1975 | break; | 2006 | break; |
1976 | case 'H': | 2007 | case 'H': |
1977 | case 'h': | 2008 | case 'h': |
@@ -1993,14 +2024,15 @@ static void parse_and_put_prompt(const char *prmt_ptr) | |||
1993 | case 'w': /* current dir */ | 2024 | case 'w': /* current dir */ |
1994 | case 'W': /* basename of cur dir */ | 2025 | case 'W': /* basename of cur dir */ |
1995 | if (!cwd_buf) { | 2026 | if (!cwd_buf) { |
2027 | const char *home; | ||
1996 | cwd_buf = xrealloc_getcwd_or_warn(NULL); | 2028 | cwd_buf = xrealloc_getcwd_or_warn(NULL); |
1997 | if (!cwd_buf) | 2029 | if (!cwd_buf) |
1998 | cwd_buf = (char *)bb_msg_unknown; | 2030 | cwd_buf = (char *)bb_msg_unknown; |
1999 | else if (home_pwd_buf[0]) { | 2031 | else if ((home = get_homedir_or_NULL()) != NULL && home[0]) { |
2000 | char *after_home_user; | 2032 | char *after_home_user; |
2001 | 2033 | ||
2002 | /* /home/user[/something] -> ~[/something] */ | 2034 | /* /home/user[/something] -> ~[/something] */ |
2003 | after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); | 2035 | after_home_user = is_prefixed_with(cwd_buf, home); |
2004 | if (after_home_user | 2036 | if (after_home_user |
2005 | && (*after_home_user == '/' || *after_home_user == '\0') | 2037 | && (*after_home_user == '/' || *after_home_user == '\0') |
2006 | ) { | 2038 | ) { |
@@ -2399,7 +2431,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2399 | //command_len = 0; - done by INIT_S() | 2431 | //command_len = 0; - done by INIT_S() |
2400 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ | 2432 | //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ |
2401 | cmdedit_termw = 80; | 2433 | cmdedit_termw = 80; |
2402 | IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;) | ||
2403 | IF_FEATURE_EDITING_VI(delptr = delbuf;) | 2434 | IF_FEATURE_EDITING_VI(delptr = delbuf;) |
2404 | 2435 | ||
2405 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 | 2436 | n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 |
@@ -2459,18 +2490,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman | |||
2459 | 2490 | ||
2460 | tcsetattr_stdin_TCSANOW(&new_settings); | 2491 | tcsetattr_stdin_TCSANOW(&new_settings); |
2461 | 2492 | ||
2462 | #if ENABLE_USERNAME_OR_HOMEDIR | ||
2463 | { | ||
2464 | struct passwd *entry; | ||
2465 | |||
2466 | entry = getpwuid(geteuid()); | ||
2467 | if (entry) { | ||
2468 | user_buf = xstrdup(entry->pw_name); | ||
2469 | home_pwd_buf = xstrdup(entry->pw_dir); | ||
2470 | } | ||
2471 | } | ||
2472 | #endif | ||
2473 | |||
2474 | #if 0 | 2493 | #if 0 |
2475 | for (i = 0; i <= state->max_history; i++) | 2494 | for (i = 0; i <= state->max_history; i++) |
2476 | bb_error_msg("history[%d]:'%s'", i, state->history[i]); | 2495 | bb_error_msg("history[%d]:'%s'", i, state->history[i]); |