| /* tilde.c -- tilde expansion code (~/foo := $HOME/foo). |
| |
| Copyright 1988-2026 Free Software Foundation, Inc. |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <https://www.gnu.org/licenses/>. |
| |
| Originally written by Brian Fox. */ |
| |
| #include "info.h" |
| #include "tilde.h" |
| |
| #ifdef HAVE_PWD_H |
| #include <pwd.h> |
| #endif |
| /* Some systems don't declare this function in pwd.h. */ |
| struct passwd *getpwnam (const char *name); |
| |
| |
| /* Do the work of tilde expansion on FILENAME. FILENAME starts with a |
| tilde. */ |
| char * |
| tilde_expand_word (const char *filename) |
| { |
| char *dirname = filename ? xstrdup (filename) : NULL; |
| |
| if (dirname && *dirname == '~') |
| { |
| char *temp_name; |
| if (!dirname[1] || IS_SLASH (dirname[1])) |
| { |
| /* Prepend $HOME to the rest of the string. */ |
| char *temp_home = getenv ("HOME"); |
| |
| /* If there is no HOME variable, look up the directory in |
| the password database. */ |
| if (!temp_home) |
| { |
| #ifndef __MINGW32__ |
| struct passwd *entry; |
| |
| entry = (struct passwd *) getpwuid (getuid ()); |
| if (entry) |
| temp_home = entry->pw_dir; |
| #else |
| temp_home = "."; |
| #endif |
| } |
| |
| temp_name = xmalloc (1 + strlen (&dirname[1]) |
| + (temp_home ? strlen (temp_home) : 0)); |
| if (temp_home) |
| strcpy (temp_name, temp_home); |
| else |
| temp_name[0] = 0; |
| strcat (temp_name, &dirname[1]); |
| free (dirname); |
| dirname = xstrdup (temp_name); |
| free (temp_name); |
| } |
| else |
| { |
| #ifndef __MINGW32__ |
| struct passwd *user_entry; |
| #endif |
| char *username = xmalloc (257); |
| int i, c; |
| |
| for (i = 1; (c = dirname[i]); i++) |
| { |
| if (IS_SLASH (c)) |
| break; |
| else |
| username[i - 1] = c; |
| } |
| username[i - 1] = 0; |
| |
| #ifndef __MINGW32__ |
| user_entry = (struct passwd *) getpwnam (username); |
| if (user_entry) |
| { |
| temp_name = xmalloc (1 + strlen (user_entry->pw_dir) |
| + strlen (&dirname[i])); |
| strcpy (temp_name, user_entry->pw_dir); |
| strcat (temp_name, &dirname[i]); |
| |
| free (dirname); |
| dirname = xstrdup (temp_name); |
| free (temp_name); |
| } |
| |
| endpwent (); |
| free (username); |
| #else |
| free (dirname); |
| dirname = xstrdup (temp_name); |
| free (temp_name); |
| #endif |
| } |
| } |
| return dirname; |
| } |