X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Freadline%2Ftilde.c;h=1d38d9d461f349b6f9f211d9c5032cba426cec0f;hb=d166f048818e10cf3799aa24a174fb22835f1acc;hp=69f57688489e8535ce25d69117d7950136709a2b;hpb=ccc6cda312fea9f0468ee65b8f368e9653e1380b;p=platform%2Fupstream%2Fbash.git diff --git a/lib/readline/tilde.c b/lib/readline/tilde.c index 69f5768..1d38d9d 100644 --- a/lib/readline/tilde.c +++ b/lib/readline/tilde.c @@ -23,6 +23,10 @@ # include #endif +#if defined (HAVE_UNISTD_H) +# include +#endif + #if defined (HAVE_STRING_H) # include #else /* !HAVE_STRING_H */ @@ -40,6 +44,10 @@ #include "tilde.h" +#ifdef SHELL +#include "shell.h" +#endif + #if !defined (HAVE_GETPW_DECLS) extern struct passwd *getpwuid (), *getpwnam (); #endif /* !HAVE_GETPW_DECLS */ @@ -78,6 +86,12 @@ static char *default_prefixes[] = static char *default_suffixes[] = { " ", "\n", (char *)NULL }; +/* If non-null, this contains the address of a function that the application + wants called before trying the standard tilde expansions. The function + is called with the text sans tilde, and returns a malloc()'ed string + which is the expansion, or a NULL pointer if the expansion fails. */ +CPFunction *tilde_expansion_preexpansion_hook = (CPFunction *)NULL; + /* If non-null, this contains the address of a function to call if the standard meaning for expanding a tilde fails. The function is called with the text (sans tilde, as in "foo"), and returns a malloc()'ed string @@ -108,7 +122,7 @@ tilde_find_prefix (string, len) string_len = strlen (string); *len = 0; - if (!*string || *string == '~') + if (*string == '\0' || *string == '~') return (0); if (prefixes) @@ -135,13 +149,14 @@ tilde_find_suffix (string) char *string; { register int i, j, string_len; - register char **suffixes = tilde_additional_suffixes; + register char **suffixes; + suffixes = tilde_additional_suffixes; string_len = strlen (string); for (i = 0; i < string_len; i++) { - if (string[i] == '/' || !string[i]) + if (string[i] == '/' /* || !string[i] */) break; for (j = 0; suffixes && suffixes[j]; j++) @@ -153,16 +168,28 @@ tilde_find_suffix (string) return (i); } +#if !defined (SHELL) +static char * +get_string_value (varname) + char *varname; +{ + return ((char *)getenv (varname)); +} +#endif + /* Return a new string which is the result of tilde expanding STRING. */ char * tilde_expand (string) char *string; { - char *result, *tilde_expand_word (); + char *result; int result_size, result_index; - result_size = result_index = 0; - result = (char *)NULL; + result_index = result_size = 0; + if (result = strchr (string, '~')) + result = xmalloc (result_size = (strlen (string) + 16)); + else + result = xmalloc (result_size = strlen (string)); /* Scan through STRING expanding tildes as we come to them. */ while (1) @@ -215,97 +242,143 @@ tilde_expand (string) return (result); } +/* Take FNAME and return the tilde prefix we want expanded. If LENP is + non-null, the index of the end of the prefix into FNAME is returned in + the location it points to. */ +static char * +isolate_tilde_prefix (fname, lenp) + char *fname; + int *lenp; +{ + char *ret; + int i; + + ret = xmalloc (strlen (fname)); + for (i = 1; fname[i] && fname[i] != '/'; i++) + ret[i - 1] = fname[i]; + ret[i - 1] = '\0'; + if (lenp) + *lenp = i; + return ret; +} + +/* Return a string that is PREFIX concatenated with SUFFIX starting at + SUFFIND. */ +static char * +glue_prefix_and_suffix (prefix, suffix, suffind) + char *prefix, *suffix; + int suffind; +{ + char *ret; + int plen, slen; + + plen = (prefix && *prefix) ? strlen (prefix) : 0; + slen = strlen (suffix + suffind); + ret = xmalloc (plen + slen + 1); + if (prefix && *prefix) + strcpy (ret, prefix); + strcpy (ret + plen, suffix + suffind); + return ret; +} + +static char * +get_home_dir () +{ + char *home_dir; + +#ifdef SHELL + home_dir = (char *)NULL; + if (current_user.home_dir == 0) + get_current_user_info (); + home_dir = current_user.home_dir; +#else + struct passwd *entry; + + home_dir = (char *)NULL; + entry = getpwuid (getuid ()); + if (entry) + home_dir = entry->pw_dir; +#endif + return (home_dir); +} + /* Do the work of tilde expansion on FILENAME. FILENAME starts with a - tilde. If there is no expansion, call tilde_expansion_failure_hook. */ + tilde. If there is no expansion, call tilde_expansion_failure_hook. + This always returns a newly-allocated string, never static storage. */ char * tilde_expand_word (filename) char *filename; { - char *dirname; - char *temp_name; + char *dirname, *expansion, *username; + int user_len; + struct passwd *user_entry; - if (filename == (char *)0) + if (filename == 0) return ((char *)NULL); - dirname = savestring (filename); - - if (*dirname != '~') - return (dirname); + if (*filename != '~') + return (savestring (filename)); - if (!dirname[1] || dirname[1] == '/') + /* A leading `~/' or a bare `~' is *always* translated to the value of + $HOME or the home directory of the current user, regardless of any + preexpansion hook. */ + if (filename[1] == '\0' || filename[1] == '/') { - /* Prepend $HOME to the rest of the string. */ - char *temp_home = (char *)getenv ("HOME"); - int home_len; + /* Prefix $HOME to the rest of the string. */ + expansion = get_string_value ("HOME"); /* If there is no HOME variable, look up the directory in the password database. */ - if (!temp_home) - { - struct passwd *entry; - - entry = getpwuid (getuid ()); - if (entry) - temp_home = entry->pw_dir; - } + if (expansion == 0) + expansion = get_home_dir (); - home_len = temp_home ? strlen (temp_home) : 0; - temp_name = xmalloc (1 + strlen (dirname + 1) + home_len); - - if (temp_home) - strcpy (temp_name, temp_home); - strcpy (temp_name + home_len, dirname + 1); - free (dirname); - dirname = temp_name; + return (glue_prefix_and_suffix (expansion, filename, 1)); } - else - { - char *username; - struct passwd *user_entry; - int i, len; - username = xmalloc (strlen (dirname)); - for (i = 1; dirname[i] && dirname[i] != '/'; i++) - username[i - 1] = dirname[i]; - username[i - 1] = '\0'; + username = isolate_tilde_prefix (filename, &user_len); - if ((user_entry = getpwnam (username)) == (struct passwd *)0) + if (tilde_expansion_preexpansion_hook) + { + expansion = (*tilde_expansion_preexpansion_hook) (username); + if (expansion) { - /* If the calling program has a special syntax for - expanding tildes, and we couldn't find a standard - expansion, then let them try. */ - if (tilde_expansion_failure_hook) - { - char *expansion; - - expansion = (*tilde_expansion_failure_hook) (username); - - if (expansion) - { - len = strlen (expansion); - temp_name = xmalloc (1 + len + strlen (dirname + i)); - strcpy (temp_name, expansion); - strcpy (temp_name + len, dirname + i); - free (expansion); - free (dirname); - dirname = temp_name; - } - } - /* We shouldn't report errors. */ + dirname = glue_prefix_and_suffix (expansion, filename, user_len); + free (username); + free (expansion); + return (dirname); } - else + } + + /* No preexpansion hook, or the preexpansion hook failed. Look in the + password database. */ + dirname = (char *)NULL; + user_entry = getpwnam (username); + if (user_entry == 0) + { + /* If the calling program has a special syntax for expanding tildes, + and we couldn't find a standard expansion, then let them try. */ + if (tilde_expansion_failure_hook) { - len = strlen (user_entry->pw_dir); - temp_name = xmalloc (1 + len + strlen (dirname + i)); - strcpy (temp_name, user_entry->pw_dir); - strcpy (temp_name + len, dirname + i); - free (dirname); - dirname = temp_name; + expansion = (*tilde_expansion_failure_hook) (username); + if (expansion) + { + dirname = glue_prefix_and_suffix (expansion, filename, user_len); + free (expansion); + } } - endpwent (); free (username); + /* If we don't have a failure hook, or if the failure hook did not + expand the tilde, return a copy of what we were passed. */ + if (dirname == 0) + dirname = savestring (filename); + } + else + { + free (username); + dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len); } + endpwent (); return (dirname); }