aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-10-11 23:08:31 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-10-11 23:08:31 +0200
commitf4fcd74a6e3d5cd2ec44cd6ce90be8a0ed108467 (patch)
treed79b1828fa7f42bda6f0c3e3d8ad5d73da2e3e0a
parent6ba1f2d0bcdddb96c43ff9fec34758a4e2b4a467 (diff)
downloadbusybox-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.c73
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
139static 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. */
143struct lineedit_statics { 139struct 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 */
240static 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
252static 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
260static 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
238static size_t load_string(const char *src) 269static 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]);