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>
This commit is contained in:
parent
6ba1f2d0bc
commit
f4fcd74a6e
@ -135,10 +135,6 @@ enum {
|
||||
: 0x7ff0
|
||||
};
|
||||
|
||||
#if ENABLE_USERNAME_OR_HOMEDIR
|
||||
static const char null_str[] ALIGN1 = "";
|
||||
#endif
|
||||
|
||||
/* We try to minimize both static and stack usage. */
|
||||
struct lineedit_statics {
|
||||
line_input_t *state;
|
||||
@ -161,12 +157,13 @@ struct lineedit_statics {
|
||||
|
||||
#if ENABLE_USERNAME_OR_HOMEDIR
|
||||
char *user_buf;
|
||||
char *home_pwd_buf; /* = (char*)null_str; */
|
||||
char *home_pwd_buf;
|
||||
smallint got_user_strings;
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_TAB_COMPLETION
|
||||
char **matches;
|
||||
unsigned num_matches;
|
||||
char **matches;
|
||||
#endif
|
||||
|
||||
#if ENABLE_FEATURE_EDITING_WINCH
|
||||
@ -207,8 +204,9 @@ extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics;
|
||||
#define prompt_last_line (S.prompt_last_line)
|
||||
#define user_buf (S.user_buf )
|
||||
#define home_pwd_buf (S.home_pwd_buf )
|
||||
#define matches (S.matches )
|
||||
#define got_user_strings (S.got_user_strings)
|
||||
#define num_matches (S.num_matches )
|
||||
#define matches (S.matches )
|
||||
#define delptr (S.delptr )
|
||||
#define newdelflag (S.newdelflag )
|
||||
#define delbuf (S.delbuf )
|
||||
@ -226,14 +224,47 @@ static void deinit_S(void)
|
||||
#endif
|
||||
#if ENABLE_USERNAME_OR_HOMEDIR
|
||||
free(user_buf);
|
||||
if (home_pwd_buf != null_str)
|
||||
free(home_pwd_buf);
|
||||
free(home_pwd_buf);
|
||||
#endif
|
||||
free(lineedit_ptr_to_statics);
|
||||
}
|
||||
#define DEINIT_S() deinit_S()
|
||||
|
||||
|
||||
#if ENABLE_USERNAME_OR_HOMEDIR
|
||||
/* Call getpwuid() only if necessary.
|
||||
* E.g. if PS1=':', no user database reading is needed to generate prompt.
|
||||
* (Unfortunately, default PS1='\w \$' needs it, \w abbreviates homedir
|
||||
* as ~/... - for that it needs to *know* the homedir...)
|
||||
*/
|
||||
static void get_user_strings(void)
|
||||
{
|
||||
struct passwd *entry;
|
||||
|
||||
got_user_strings = 1;
|
||||
entry = getpwuid(geteuid());
|
||||
if (entry) {
|
||||
user_buf = xstrdup(entry->pw_name);
|
||||
home_pwd_buf = xstrdup(entry->pw_dir);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_username_str(void)
|
||||
{
|
||||
if (!got_user_strings)
|
||||
get_user_strings();
|
||||
return user_buf ? user_buf : "";
|
||||
/* btw, bash uses "I have no name!" string if uid has no entry */
|
||||
}
|
||||
|
||||
static NOINLINE const char *get_homedir_or_NULL(void)
|
||||
{
|
||||
if (!got_user_strings)
|
||||
get_user_strings();
|
||||
return home_pwd_buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_UNICODE_SUPPORT
|
||||
static size_t load_string(const char *src)
|
||||
{
|
||||
@ -691,11 +722,11 @@ static char *username_path_completion(char *ud)
|
||||
{
|
||||
struct passwd *entry;
|
||||
char *tilde_name = ud;
|
||||
char *home = NULL;
|
||||
const char *home = NULL;
|
||||
|
||||
ud++; /* skip ~ */
|
||||
if (*ud == '/') { /* "~/..." */
|
||||
home = home_pwd_buf;
|
||||
home = get_homedir_or_NULL();
|
||||
} else {
|
||||
/* "~user/..." */
|
||||
ud = strchr(ud, '/');
|
||||
@ -1971,7 +2002,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
|
||||
|
||||
switch (c) {
|
||||
case 'u':
|
||||
pbuf = user_buf ? user_buf : (char*)"";
|
||||
pbuf = (char*)get_username_str();
|
||||
break;
|
||||
case 'H':
|
||||
case 'h':
|
||||
@ -1993,14 +2024,15 @@ static void parse_and_put_prompt(const char *prmt_ptr)
|
||||
case 'w': /* current dir */
|
||||
case 'W': /* basename of cur dir */
|
||||
if (!cwd_buf) {
|
||||
const char *home;
|
||||
cwd_buf = xrealloc_getcwd_or_warn(NULL);
|
||||
if (!cwd_buf)
|
||||
cwd_buf = (char *)bb_msg_unknown;
|
||||
else if (home_pwd_buf[0]) {
|
||||
else if ((home = get_homedir_or_NULL()) != NULL && home[0]) {
|
||||
char *after_home_user;
|
||||
|
||||
/* /home/user[/something] -> ~[/something] */
|
||||
after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf);
|
||||
after_home_user = is_prefixed_with(cwd_buf, home);
|
||||
if (after_home_user
|
||||
&& (*after_home_user == '/' || *after_home_user == '\0')
|
||||
) {
|
||||
@ -2399,7 +2431,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
|
||||
//command_len = 0; - done by INIT_S()
|
||||
//cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
|
||||
cmdedit_termw = 80;
|
||||
IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;)
|
||||
IF_FEATURE_EDITING_VI(delptr = delbuf;)
|
||||
|
||||
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
|
||||
|
||||
tcsetattr_stdin_TCSANOW(&new_settings);
|
||||
|
||||
#if ENABLE_USERNAME_OR_HOMEDIR
|
||||
{
|
||||
struct passwd *entry;
|
||||
|
||||
entry = getpwuid(geteuid());
|
||||
if (entry) {
|
||||
user_buf = xstrdup(entry->pw_name);
|
||||
home_pwd_buf = xstrdup(entry->pw_dir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (i = 0; i <= state->max_history; i++)
|
||||
bb_error_msg("history[%d]:'%s'", i, state->history[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user