1 /* tilde.c -- tilde expansion code (~/foo := $HOME/foo).
2
3 Copyright 1988-2023 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 Originally written by Brian Fox. */
19
20 #include "info.h"
21 #include "tilde.h"
22
23 /* Do the work of tilde expansion on FILENAME. FILENAME starts with a
24 tilde. */
25 char *
26 tilde_expand_word (const char *filename)
27 {
28 char *dirname = filename ? xstrdup (filename) : NULL;
29
30 if (dirname && *dirname == '~')
31 {
32 char *temp_name;
33 if (!dirname[1] || IS_SLASH (dirname[1]))
34 {
35 /* Prepend $HOME to the rest of the string. */
36 char *temp_home = getenv ("HOME");
37
38 /* If there is no HOME variable, look up the directory in
39 the password database. */
40 if (!temp_home)
41 {
42 #ifndef __MINGW32__
43 struct passwd *entry;
44
45 entry = (struct passwd *) getpwuid (getuid ());
46 if (entry)
47 temp_home = entry->pw_dir;
48 #else
49 temp_home = ".";
50 #endif
51 }
52
53 temp_name = xmalloc (1 + strlen (&dirname[1])
54 + (temp_home ? strlen (temp_home) : 0));
55 if (temp_home)
56 strcpy (temp_name, temp_home);
57 else
58 temp_name[0] = 0;
59 strcat (temp_name, &dirname[1]);
60 free (dirname);
61 dirname = xstrdup (temp_name);
62 free (temp_name);
63 }
64 else
65 {
66 #ifndef __MINGW32__
67 struct passwd *user_entry;
68 #endif
69 char *username = xmalloc (257);
70 int i, c;
71
72 for (i = 1; (c = dirname[i]); i++)
73 {
74 if (IS_SLASH (c))
75 break;
76 else
77 username[i - 1] = c;
78 }
79 username[i - 1] = 0;
80
81 #ifndef __MINGW32__
82 user_entry = (struct passwd *) getpwnam (username);
83 if (user_entry)
84 {
85 temp_name = xmalloc (1 + strlen (user_entry->pw_dir)
86 + strlen (&dirname[i]));
87 strcpy (temp_name, user_entry->pw_dir);
88 strcat (temp_name, &dirname[i]);
89
90 free (dirname);
91 dirname = xstrdup (temp_name);
92 free (temp_name);
93 }
94
95 endpwent ();
96 free (username);
97 #else
98 free (dirname);
99 dirname = xstrdup (temp_name);
100 free (temp_name);
101 #endif
102 }
103 }
104 return dirname;
105 }