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]); |
