X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=fish%2Ftilde.c;h=ee87ce1b29ce13d188a6378fe06f8ba3bc61a9ab;hp=13e6cd8ff2410e98421ee92b7cdc5e2b2f8ae75d;hb=eb209a3664906257b3dc87b6f7b04ff54e0d1288;hpb=9449b0fce4145a56df9d43169d61e8b2c4e41b09 diff --git a/fish/tilde.c b/fish/tilde.c index 13e6cd8..ee87ce1 100644 --- a/fish/tilde.c +++ b/fish/tilde.c @@ -22,15 +22,15 @@ #include #include #include -#include #include #include #include #include "fish.h" -static char *expand_home (const char *); -static const char *find_home_for_username (const char *, int); +static char *expand_home (char *orig, const char *append); +static const char *find_home_for_username (const char *, size_t); +static const char *find_home_for_current_user (void); /* This is called from the script loop if we find a candidate for * ~username (tilde-expansion). @@ -40,32 +40,28 @@ try_tilde_expansion (char *str) { assert (str[0] == '~'); - /* Expand current user's home directory. By simple experimentation - * I found out that bash always uses $HOME. - */ + /* Expand "~" to current user's home directory. */ if (str[1] == '\0') /* ~ */ - return expand_home (NULL); + return expand_home (str, NULL); else if (str[1] == '/') /* ~/... */ - return expand_home (&str[1]); + return expand_home (str, &str[1]); /* Try expanding the part up to the following '\0' or '/' as a * username from the password file. */ else { - int len; const char *home, *rest; - - len = strcspn (&str[1], "/"); + size_t len = strcspn (&str[1], "/"); rest = &str[1+len]; home = find_home_for_username (&str[1], len); if (home) { - len = strlen (home) + strlen (rest); + len = strlen (home) + strlen (rest) + 1; str = malloc (len); if (str == NULL) { - perror ("malloc"); - exit (1); + perror ("malloc"); + exit (EXIT_FAILURE); } strcpy (str, home); strcat (str, rest); @@ -79,20 +75,27 @@ try_tilde_expansion (char *str) /* Return $HOME + append string. */ static char * -expand_home (const char *append) +expand_home (char *orig, const char *append) { const char *home; int len; char *str; home = getenv ("HOME"); - if (!home) home = "~"; + if (!home) { + /* $HOME not set, bash can look up the current user in the + * password file and find their home that way. (RHBZ#617440). + */ + home = find_home_for_current_user (); + if (!home) + return orig; + } - len = strlen (home) + (append ? strlen (append) : 0); + len = strlen (home) + (append ? strlen (append) : 0) + 1; str = malloc (len); if (str == NULL) { perror ("malloc"); - exit (1); + exit (EXIT_FAILURE); } strcpy (str, home); @@ -106,14 +109,29 @@ expand_home (const char *append) * or NULL if not found. */ static const char * -find_home_for_username (const char *username, int ulen) +find_home_for_username (const char *username, size_t ulen) { struct passwd *pw; setpwent (); while ((pw = getpwent ()) != NULL) { if (strlen (pw->pw_name) == ulen && - strncmp (username, pw->pw_name, ulen) == 0) + STREQLEN (username, pw->pw_name, ulen)) + return pw->pw_dir; + } + + return NULL; +} + +static const char * +find_home_for_current_user (void) +{ + struct passwd *pw; + uid_t euid = geteuid (); + + setpwent (); + while ((pw = getpwent ()) != NULL) { + if (pw->pw_uid == euid) return pw->pw_dir; }