xref: /dflybsd-src/contrib/gdb-7/readline/tilde.c (revision 16003dcfd2baa152f5dd24794ec9f36e139eaeb8)
1*6b445a62SJohn Marino /* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
2*6b445a62SJohn Marino 
3*6b445a62SJohn Marino /* Copyright (C) 1988-2009 Free Software Foundation, Inc.
4*6b445a62SJohn Marino 
5*6b445a62SJohn Marino    This file is part of the GNU Readline Library (Readline), a library
6*6b445a62SJohn Marino    for reading lines of text with interactive input and history editing.
7*6b445a62SJohn Marino 
8*6b445a62SJohn Marino    Readline is free software: you can redistribute it and/or modify
9*6b445a62SJohn Marino    it under the terms of the GNU General Public License as published by
10*6b445a62SJohn Marino    the Free Software Foundation, either version 3 of the License, or
11*6b445a62SJohn Marino    (at your option) any later version.
12*6b445a62SJohn Marino 
13*6b445a62SJohn Marino    Readline is distributed in the hope that it will be useful,
14*6b445a62SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*6b445a62SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*6b445a62SJohn Marino    GNU General Public License for more details.
17*6b445a62SJohn Marino 
18*6b445a62SJohn Marino    You should have received a copy of the GNU General Public License
19*6b445a62SJohn Marino    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
20*6b445a62SJohn Marino */
21*6b445a62SJohn Marino 
22*6b445a62SJohn Marino #if defined (HAVE_CONFIG_H)
23*6b445a62SJohn Marino #  include <config.h>
24*6b445a62SJohn Marino #endif
25*6b445a62SJohn Marino 
26*6b445a62SJohn Marino #if defined (HAVE_UNISTD_H)
27*6b445a62SJohn Marino #  ifdef _MINIX
28*6b445a62SJohn Marino #    include <sys/types.h>
29*6b445a62SJohn Marino #  endif
30*6b445a62SJohn Marino #  include <unistd.h>
31*6b445a62SJohn Marino #endif
32*6b445a62SJohn Marino 
33*6b445a62SJohn Marino #if defined (HAVE_STRING_H)
34*6b445a62SJohn Marino #  include <string.h>
35*6b445a62SJohn Marino #else /* !HAVE_STRING_H */
36*6b445a62SJohn Marino #  include <strings.h>
37*6b445a62SJohn Marino #endif /* !HAVE_STRING_H */
38*6b445a62SJohn Marino 
39*6b445a62SJohn Marino #if defined (HAVE_STDLIB_H)
40*6b445a62SJohn Marino #  include <stdlib.h>
41*6b445a62SJohn Marino #else
42*6b445a62SJohn Marino #  include "ansi_stdlib.h"
43*6b445a62SJohn Marino #endif /* HAVE_STDLIB_H */
44*6b445a62SJohn Marino 
45*6b445a62SJohn Marino #include <sys/types.h>
46*6b445a62SJohn Marino #if defined (HAVE_PWD_H)
47*6b445a62SJohn Marino #include <pwd.h>
48*6b445a62SJohn Marino #endif
49*6b445a62SJohn Marino 
50*6b445a62SJohn Marino #include "tilde.h"
51*6b445a62SJohn Marino 
52*6b445a62SJohn Marino #if defined (TEST) || defined (STATIC_MALLOC)
53*6b445a62SJohn Marino static void *xmalloc (), *xrealloc ();
54*6b445a62SJohn Marino #else
55*6b445a62SJohn Marino #  include "xmalloc.h"
56*6b445a62SJohn Marino #endif /* TEST || STATIC_MALLOC */
57*6b445a62SJohn Marino 
58*6b445a62SJohn Marino #if !defined (HAVE_GETPW_DECLS)
59*6b445a62SJohn Marino #  if defined (HAVE_GETPWUID)
60*6b445a62SJohn Marino extern struct passwd *getpwuid PARAMS((uid_t));
61*6b445a62SJohn Marino #  endif
62*6b445a62SJohn Marino #  if defined (HAVE_GETPWNAM)
63*6b445a62SJohn Marino extern struct passwd *getpwnam PARAMS((const char *));
64*6b445a62SJohn Marino #  endif
65*6b445a62SJohn Marino #endif /* !HAVE_GETPW_DECLS */
66*6b445a62SJohn Marino 
67*6b445a62SJohn Marino #if !defined (savestring)
68*6b445a62SJohn Marino #define savestring(x) strcpy ((char *)xmalloc (1 + strlen (x)), (x))
69*6b445a62SJohn Marino #endif /* !savestring */
70*6b445a62SJohn Marino 
71*6b445a62SJohn Marino #if !defined (NULL)
72*6b445a62SJohn Marino #  if defined (__STDC__)
73*6b445a62SJohn Marino #    define NULL ((void *) 0)
74*6b445a62SJohn Marino #  else
75*6b445a62SJohn Marino #    define NULL 0x0
76*6b445a62SJohn Marino #  endif /* !__STDC__ */
77*6b445a62SJohn Marino #endif /* !NULL */
78*6b445a62SJohn Marino 
79*6b445a62SJohn Marino /* If being compiled as part of bash, these will be satisfied from
80*6b445a62SJohn Marino    variables.o.  If being compiled as part of readline, they will
81*6b445a62SJohn Marino    be satisfied from shell.o. */
82*6b445a62SJohn Marino extern char *sh_get_home_dir PARAMS((void));
83*6b445a62SJohn Marino extern char *sh_get_env_value PARAMS((const char *));
84*6b445a62SJohn Marino 
85*6b445a62SJohn Marino /* The default value of tilde_additional_prefixes.  This is set to
86*6b445a62SJohn Marino    whitespace preceding a tilde so that simple programs which do not
87*6b445a62SJohn Marino    perform any word separation get desired behaviour. */
88*6b445a62SJohn Marino static const char *default_prefixes[] =
89*6b445a62SJohn Marino   { " ~", "\t~", (const char *)NULL };
90*6b445a62SJohn Marino 
91*6b445a62SJohn Marino /* The default value of tilde_additional_suffixes.  This is set to
92*6b445a62SJohn Marino    whitespace or newline so that simple programs which do not
93*6b445a62SJohn Marino    perform any word separation get desired behaviour. */
94*6b445a62SJohn Marino static const char *default_suffixes[] =
95*6b445a62SJohn Marino   { " ", "\n", (const char *)NULL };
96*6b445a62SJohn Marino 
97*6b445a62SJohn Marino /* If non-null, this contains the address of a function that the application
98*6b445a62SJohn Marino    wants called before trying the standard tilde expansions.  The function
99*6b445a62SJohn Marino    is called with the text sans tilde, and returns a malloc()'ed string
100*6b445a62SJohn Marino    which is the expansion, or a NULL pointer if the expansion fails. */
101*6b445a62SJohn Marino tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL;
102*6b445a62SJohn Marino 
103*6b445a62SJohn Marino /* If non-null, this contains the address of a function to call if the
104*6b445a62SJohn Marino    standard meaning for expanding a tilde fails.  The function is called
105*6b445a62SJohn Marino    with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
106*6b445a62SJohn Marino    which is the expansion, or a NULL pointer if there is no expansion. */
107*6b445a62SJohn Marino tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL;
108*6b445a62SJohn Marino 
109*6b445a62SJohn Marino /* When non-null, this is a NULL terminated array of strings which
110*6b445a62SJohn Marino    are duplicates for a tilde prefix.  Bash uses this to expand
111*6b445a62SJohn Marino    `=~' and `:~'. */
112*6b445a62SJohn Marino char **tilde_additional_prefixes = (char **)default_prefixes;
113*6b445a62SJohn Marino 
114*6b445a62SJohn Marino /* When non-null, this is a NULL terminated array of strings which match
115*6b445a62SJohn Marino    the end of a username, instead of just "/".  Bash sets this to
116*6b445a62SJohn Marino    `:' and `=~'. */
117*6b445a62SJohn Marino char **tilde_additional_suffixes = (char **)default_suffixes;
118*6b445a62SJohn Marino 
119*6b445a62SJohn Marino static int tilde_find_prefix PARAMS((const char *, int *));
120*6b445a62SJohn Marino static int tilde_find_suffix PARAMS((const char *));
121*6b445a62SJohn Marino static char *isolate_tilde_prefix PARAMS((const char *, int *));
122*6b445a62SJohn Marino static char *glue_prefix_and_suffix PARAMS((char *, const char *, int));
123*6b445a62SJohn Marino 
124*6b445a62SJohn Marino /* Find the start of a tilde expansion in STRING, and return the index of
125*6b445a62SJohn Marino    the tilde which starts the expansion.  Place the length of the text
126*6b445a62SJohn Marino    which identified this tilde starter in LEN, excluding the tilde itself. */
127*6b445a62SJohn Marino static int
tilde_find_prefix(string,len)128*6b445a62SJohn Marino tilde_find_prefix (string, len)
129*6b445a62SJohn Marino      const char *string;
130*6b445a62SJohn Marino      int *len;
131*6b445a62SJohn Marino {
132*6b445a62SJohn Marino   register int i, j, string_len;
133*6b445a62SJohn Marino   register char **prefixes;
134*6b445a62SJohn Marino 
135*6b445a62SJohn Marino   prefixes = tilde_additional_prefixes;
136*6b445a62SJohn Marino 
137*6b445a62SJohn Marino   string_len = strlen (string);
138*6b445a62SJohn Marino   *len = 0;
139*6b445a62SJohn Marino 
140*6b445a62SJohn Marino   if (*string == '\0' || *string == '~')
141*6b445a62SJohn Marino     return (0);
142*6b445a62SJohn Marino 
143*6b445a62SJohn Marino   if (prefixes)
144*6b445a62SJohn Marino     {
145*6b445a62SJohn Marino       for (i = 0; i < string_len; i++)
146*6b445a62SJohn Marino 	{
147*6b445a62SJohn Marino 	  for (j = 0; prefixes[j]; j++)
148*6b445a62SJohn Marino 	    {
149*6b445a62SJohn Marino 	      if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
150*6b445a62SJohn Marino 		{
151*6b445a62SJohn Marino 		  *len = strlen (prefixes[j]) - 1;
152*6b445a62SJohn Marino 		  return (i + *len);
153*6b445a62SJohn Marino 		}
154*6b445a62SJohn Marino 	    }
155*6b445a62SJohn Marino 	}
156*6b445a62SJohn Marino     }
157*6b445a62SJohn Marino   return (string_len);
158*6b445a62SJohn Marino }
159*6b445a62SJohn Marino 
160*6b445a62SJohn Marino /* Find the end of a tilde expansion in STRING, and return the index of
161*6b445a62SJohn Marino    the character which ends the tilde definition.  */
162*6b445a62SJohn Marino static int
tilde_find_suffix(string)163*6b445a62SJohn Marino tilde_find_suffix (string)
164*6b445a62SJohn Marino      const char *string;
165*6b445a62SJohn Marino {
166*6b445a62SJohn Marino   register int i, j, string_len;
167*6b445a62SJohn Marino   register char **suffixes;
168*6b445a62SJohn Marino 
169*6b445a62SJohn Marino   suffixes = tilde_additional_suffixes;
170*6b445a62SJohn Marino   string_len = strlen (string);
171*6b445a62SJohn Marino 
172*6b445a62SJohn Marino   for (i = 0; i < string_len; i++)
173*6b445a62SJohn Marino     {
174*6b445a62SJohn Marino #if defined (__MSDOS__)
175*6b445a62SJohn Marino       if (string[i] == '/' || string[i] == '\\' /* || !string[i] */)
176*6b445a62SJohn Marino #else
177*6b445a62SJohn Marino       if (string[i] == '/' /* || !string[i] */)
178*6b445a62SJohn Marino #endif
179*6b445a62SJohn Marino 	break;
180*6b445a62SJohn Marino 
181*6b445a62SJohn Marino       for (j = 0; suffixes && suffixes[j]; j++)
182*6b445a62SJohn Marino 	{
183*6b445a62SJohn Marino 	  if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
184*6b445a62SJohn Marino 	    return (i);
185*6b445a62SJohn Marino 	}
186*6b445a62SJohn Marino     }
187*6b445a62SJohn Marino   return (i);
188*6b445a62SJohn Marino }
189*6b445a62SJohn Marino 
190*6b445a62SJohn Marino /* Return a new string which is the result of tilde expanding STRING. */
191*6b445a62SJohn Marino char *
tilde_expand(string)192*6b445a62SJohn Marino tilde_expand (string)
193*6b445a62SJohn Marino      const char *string;
194*6b445a62SJohn Marino {
195*6b445a62SJohn Marino   char *result;
196*6b445a62SJohn Marino   int result_size, result_index;
197*6b445a62SJohn Marino 
198*6b445a62SJohn Marino   result_index = result_size = 0;
199*6b445a62SJohn Marino   if (result = strchr (string, '~'))
200*6b445a62SJohn Marino     result = (char *)xmalloc (result_size = (strlen (string) + 16));
201*6b445a62SJohn Marino   else
202*6b445a62SJohn Marino     result = (char *)xmalloc (result_size = (strlen (string) + 1));
203*6b445a62SJohn Marino 
204*6b445a62SJohn Marino   /* Scan through STRING expanding tildes as we come to them. */
205*6b445a62SJohn Marino   while (1)
206*6b445a62SJohn Marino     {
207*6b445a62SJohn Marino       register int start, end;
208*6b445a62SJohn Marino       char *tilde_word, *expansion;
209*6b445a62SJohn Marino       int len;
210*6b445a62SJohn Marino 
211*6b445a62SJohn Marino       /* Make START point to the tilde which starts the expansion. */
212*6b445a62SJohn Marino       start = tilde_find_prefix (string, &len);
213*6b445a62SJohn Marino 
214*6b445a62SJohn Marino       /* Copy the skipped text into the result. */
215*6b445a62SJohn Marino       if ((result_index + start + 1) > result_size)
216*6b445a62SJohn Marino 	result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
217*6b445a62SJohn Marino 
218*6b445a62SJohn Marino       strncpy (result + result_index, string, start);
219*6b445a62SJohn Marino       result_index += start;
220*6b445a62SJohn Marino 
221*6b445a62SJohn Marino       /* Advance STRING to the starting tilde. */
222*6b445a62SJohn Marino       string += start;
223*6b445a62SJohn Marino 
224*6b445a62SJohn Marino       /* Make END be the index of one after the last character of the
225*6b445a62SJohn Marino 	 username. */
226*6b445a62SJohn Marino       end = tilde_find_suffix (string);
227*6b445a62SJohn Marino 
228*6b445a62SJohn Marino       /* If both START and END are zero, we are all done. */
229*6b445a62SJohn Marino       if (!start && !end)
230*6b445a62SJohn Marino 	break;
231*6b445a62SJohn Marino 
232*6b445a62SJohn Marino       /* Expand the entire tilde word, and copy it into RESULT. */
233*6b445a62SJohn Marino       tilde_word = (char *)xmalloc (1 + end);
234*6b445a62SJohn Marino       strncpy (tilde_word, string, end);
235*6b445a62SJohn Marino       tilde_word[end] = '\0';
236*6b445a62SJohn Marino       string += end;
237*6b445a62SJohn Marino 
238*6b445a62SJohn Marino       expansion = tilde_expand_word (tilde_word);
239*6b445a62SJohn Marino       xfree (tilde_word);
240*6b445a62SJohn Marino 
241*6b445a62SJohn Marino       len = strlen (expansion);
242*6b445a62SJohn Marino #ifdef __CYGWIN__
243*6b445a62SJohn Marino       /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
244*6b445a62SJohn Marino 	 $HOME for `user' is /.  On cygwin, // denotes a network drive. */
245*6b445a62SJohn Marino       if (len > 1 || *expansion != '/' || *string != '/')
246*6b445a62SJohn Marino #endif
247*6b445a62SJohn Marino 	{
248*6b445a62SJohn Marino 	  if ((result_index + len + 1) > result_size)
249*6b445a62SJohn Marino 	    result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
250*6b445a62SJohn Marino 
251*6b445a62SJohn Marino 	  strcpy (result + result_index, expansion);
252*6b445a62SJohn Marino 	  result_index += len;
253*6b445a62SJohn Marino 	}
254*6b445a62SJohn Marino       xfree (expansion);
255*6b445a62SJohn Marino     }
256*6b445a62SJohn Marino 
257*6b445a62SJohn Marino   result[result_index] = '\0';
258*6b445a62SJohn Marino 
259*6b445a62SJohn Marino   return (result);
260*6b445a62SJohn Marino }
261*6b445a62SJohn Marino 
262*6b445a62SJohn Marino /* Take FNAME and return the tilde prefix we want expanded.  If LENP is
263*6b445a62SJohn Marino    non-null, the index of the end of the prefix into FNAME is returned in
264*6b445a62SJohn Marino    the location it points to. */
265*6b445a62SJohn Marino static char *
isolate_tilde_prefix(fname,lenp)266*6b445a62SJohn Marino isolate_tilde_prefix (fname, lenp)
267*6b445a62SJohn Marino      const char *fname;
268*6b445a62SJohn Marino      int *lenp;
269*6b445a62SJohn Marino {
270*6b445a62SJohn Marino   char *ret;
271*6b445a62SJohn Marino   int i;
272*6b445a62SJohn Marino 
273*6b445a62SJohn Marino   ret = (char *)xmalloc (strlen (fname));
274*6b445a62SJohn Marino #if defined (__MSDOS__)
275*6b445a62SJohn Marino   for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
276*6b445a62SJohn Marino #else
277*6b445a62SJohn Marino   for (i = 1; fname[i] && fname[i] != '/'; i++)
278*6b445a62SJohn Marino #endif
279*6b445a62SJohn Marino     ret[i - 1] = fname[i];
280*6b445a62SJohn Marino   ret[i - 1] = '\0';
281*6b445a62SJohn Marino   if (lenp)
282*6b445a62SJohn Marino     *lenp = i;
283*6b445a62SJohn Marino   return ret;
284*6b445a62SJohn Marino }
285*6b445a62SJohn Marino 
286*6b445a62SJohn Marino #if 0
287*6b445a62SJohn Marino /* Public function to scan a string (FNAME) beginning with a tilde and find
288*6b445a62SJohn Marino    the portion of the string that should be passed to the tilde expansion
289*6b445a62SJohn Marino    function.  Right now, it just calls tilde_find_suffix and allocates new
290*6b445a62SJohn Marino    memory, but it can be expanded to do different things later. */
291*6b445a62SJohn Marino char *
292*6b445a62SJohn Marino tilde_find_word (fname, flags, lenp)
293*6b445a62SJohn Marino      const char *fname;
294*6b445a62SJohn Marino      int flags, *lenp;
295*6b445a62SJohn Marino {
296*6b445a62SJohn Marino   int x;
297*6b445a62SJohn Marino   char *r;
298*6b445a62SJohn Marino 
299*6b445a62SJohn Marino   x = tilde_find_suffix (fname);
300*6b445a62SJohn Marino   if (x == 0)
301*6b445a62SJohn Marino     {
302*6b445a62SJohn Marino       r = savestring (fname);
303*6b445a62SJohn Marino       if (lenp)
304*6b445a62SJohn Marino 	*lenp = 0;
305*6b445a62SJohn Marino     }
306*6b445a62SJohn Marino   else
307*6b445a62SJohn Marino     {
308*6b445a62SJohn Marino       r = (char *)xmalloc (1 + x);
309*6b445a62SJohn Marino       strncpy (r, fname, x);
310*6b445a62SJohn Marino       r[x] = '\0';
311*6b445a62SJohn Marino       if (lenp)
312*6b445a62SJohn Marino 	*lenp = x;
313*6b445a62SJohn Marino     }
314*6b445a62SJohn Marino 
315*6b445a62SJohn Marino   return r;
316*6b445a62SJohn Marino }
317*6b445a62SJohn Marino #endif
318*6b445a62SJohn Marino 
319*6b445a62SJohn Marino /* Return a string that is PREFIX concatenated with SUFFIX starting at
320*6b445a62SJohn Marino    SUFFIND. */
321*6b445a62SJohn Marino static char *
glue_prefix_and_suffix(prefix,suffix,suffind)322*6b445a62SJohn Marino glue_prefix_and_suffix (prefix, suffix, suffind)
323*6b445a62SJohn Marino      char *prefix;
324*6b445a62SJohn Marino      const char *suffix;
325*6b445a62SJohn Marino      int suffind;
326*6b445a62SJohn Marino {
327*6b445a62SJohn Marino   char *ret;
328*6b445a62SJohn Marino   int plen, slen;
329*6b445a62SJohn Marino 
330*6b445a62SJohn Marino   plen = (prefix && *prefix) ? strlen (prefix) : 0;
331*6b445a62SJohn Marino   slen = strlen (suffix + suffind);
332*6b445a62SJohn Marino   ret = (char *)xmalloc (plen + slen + 1);
333*6b445a62SJohn Marino   if (plen)
334*6b445a62SJohn Marino     strcpy (ret, prefix);
335*6b445a62SJohn Marino   strcpy (ret + plen, suffix + suffind);
336*6b445a62SJohn Marino   return ret;
337*6b445a62SJohn Marino }
338*6b445a62SJohn Marino 
339*6b445a62SJohn Marino /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
340*6b445a62SJohn Marino    tilde.  If there is no expansion, call tilde_expansion_failure_hook.
341*6b445a62SJohn Marino    This always returns a newly-allocated string, never static storage. */
342*6b445a62SJohn Marino char *
tilde_expand_word(filename)343*6b445a62SJohn Marino tilde_expand_word (filename)
344*6b445a62SJohn Marino      const char *filename;
345*6b445a62SJohn Marino {
346*6b445a62SJohn Marino   char *dirname, *expansion, *username;
347*6b445a62SJohn Marino   int user_len;
348*6b445a62SJohn Marino   struct passwd *user_entry;
349*6b445a62SJohn Marino 
350*6b445a62SJohn Marino   if (filename == 0)
351*6b445a62SJohn Marino     return ((char *)NULL);
352*6b445a62SJohn Marino 
353*6b445a62SJohn Marino   if (*filename != '~')
354*6b445a62SJohn Marino     return (savestring (filename));
355*6b445a62SJohn Marino 
356*6b445a62SJohn Marino   /* A leading `~/' or a bare `~' is *always* translated to the value of
357*6b445a62SJohn Marino      $HOME or the home directory of the current user, regardless of any
358*6b445a62SJohn Marino      preexpansion hook. */
359*6b445a62SJohn Marino   if (filename[1] == '\0' || filename[1] == '/')
360*6b445a62SJohn Marino     {
361*6b445a62SJohn Marino       /* Prefix $HOME to the rest of the string. */
362*6b445a62SJohn Marino       expansion = sh_get_env_value ("HOME");
363*6b445a62SJohn Marino 
364*6b445a62SJohn Marino       /* If there is no HOME variable, look up the directory in
365*6b445a62SJohn Marino 	 the password database. */
366*6b445a62SJohn Marino       if (expansion == 0)
367*6b445a62SJohn Marino 	expansion = sh_get_home_dir ();
368*6b445a62SJohn Marino 
369*6b445a62SJohn Marino       return (glue_prefix_and_suffix (expansion, filename, 1));
370*6b445a62SJohn Marino     }
371*6b445a62SJohn Marino 
372*6b445a62SJohn Marino   username = isolate_tilde_prefix (filename, &user_len);
373*6b445a62SJohn Marino 
374*6b445a62SJohn Marino   if (tilde_expansion_preexpansion_hook)
375*6b445a62SJohn Marino     {
376*6b445a62SJohn Marino       expansion = (*tilde_expansion_preexpansion_hook) (username);
377*6b445a62SJohn Marino       if (expansion)
378*6b445a62SJohn Marino 	{
379*6b445a62SJohn Marino 	  dirname = glue_prefix_and_suffix (expansion, filename, user_len);
380*6b445a62SJohn Marino 	  xfree (username);
381*6b445a62SJohn Marino 	  xfree (expansion);
382*6b445a62SJohn Marino 	  return (dirname);
383*6b445a62SJohn Marino 	}
384*6b445a62SJohn Marino     }
385*6b445a62SJohn Marino 
386*6b445a62SJohn Marino   /* No preexpansion hook, or the preexpansion hook failed.  Look in the
387*6b445a62SJohn Marino      password database. */
388*6b445a62SJohn Marino   dirname = (char *)NULL;
389*6b445a62SJohn Marino #if defined (HAVE_GETPWNAM)
390*6b445a62SJohn Marino   user_entry = getpwnam (username);
391*6b445a62SJohn Marino #else
392*6b445a62SJohn Marino   user_entry = 0;
393*6b445a62SJohn Marino #endif
394*6b445a62SJohn Marino   if (user_entry == 0)
395*6b445a62SJohn Marino     {
396*6b445a62SJohn Marino       /* If the calling program has a special syntax for expanding tildes,
397*6b445a62SJohn Marino 	 and we couldn't find a standard expansion, then let them try. */
398*6b445a62SJohn Marino       if (tilde_expansion_failure_hook)
399*6b445a62SJohn Marino 	{
400*6b445a62SJohn Marino 	  expansion = (*tilde_expansion_failure_hook) (username);
401*6b445a62SJohn Marino 	  if (expansion)
402*6b445a62SJohn Marino 	    {
403*6b445a62SJohn Marino 	      dirname = glue_prefix_and_suffix (expansion, filename, user_len);
404*6b445a62SJohn Marino 	      xfree (expansion);
405*6b445a62SJohn Marino 	    }
406*6b445a62SJohn Marino 	}
407*6b445a62SJohn Marino       /* If we don't have a failure hook, or if the failure hook did not
408*6b445a62SJohn Marino 	 expand the tilde, return a copy of what we were passed. */
409*6b445a62SJohn Marino       if (dirname == 0)
410*6b445a62SJohn Marino 	dirname = savestring (filename);
411*6b445a62SJohn Marino     }
412*6b445a62SJohn Marino #if defined (HAVE_GETPWENT)
413*6b445a62SJohn Marino   else
414*6b445a62SJohn Marino     dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
415*6b445a62SJohn Marino #endif
416*6b445a62SJohn Marino 
417*6b445a62SJohn Marino   xfree (username);
418*6b445a62SJohn Marino #if defined (HAVE_GETPWENT)
419*6b445a62SJohn Marino   endpwent ();
420*6b445a62SJohn Marino #endif
421*6b445a62SJohn Marino   return (dirname);
422*6b445a62SJohn Marino }
423*6b445a62SJohn Marino 
424*6b445a62SJohn Marino 
425*6b445a62SJohn Marino #if defined (TEST)
426*6b445a62SJohn Marino #undef NULL
427*6b445a62SJohn Marino #include <stdio.h>
428*6b445a62SJohn Marino 
main(argc,argv)429*6b445a62SJohn Marino main (argc, argv)
430*6b445a62SJohn Marino      int argc;
431*6b445a62SJohn Marino      char **argv;
432*6b445a62SJohn Marino {
433*6b445a62SJohn Marino   char *result, line[512];
434*6b445a62SJohn Marino   int done = 0;
435*6b445a62SJohn Marino 
436*6b445a62SJohn Marino   while (!done)
437*6b445a62SJohn Marino     {
438*6b445a62SJohn Marino       printf ("~expand: ");
439*6b445a62SJohn Marino       fflush (stdout);
440*6b445a62SJohn Marino 
441*6b445a62SJohn Marino       if (!gets (line))
442*6b445a62SJohn Marino 	strcpy (line, "done");
443*6b445a62SJohn Marino 
444*6b445a62SJohn Marino       if ((strcmp (line, "done") == 0) ||
445*6b445a62SJohn Marino 	  (strcmp (line, "quit") == 0) ||
446*6b445a62SJohn Marino 	  (strcmp (line, "exit") == 0))
447*6b445a62SJohn Marino 	{
448*6b445a62SJohn Marino 	  done = 1;
449*6b445a62SJohn Marino 	  break;
450*6b445a62SJohn Marino 	}
451*6b445a62SJohn Marino 
452*6b445a62SJohn Marino       result = tilde_expand (line);
453*6b445a62SJohn Marino       printf ("  --> %s\n", result);
454*6b445a62SJohn Marino       free (result);
455*6b445a62SJohn Marino     }
456*6b445a62SJohn Marino   exit (0);
457*6b445a62SJohn Marino }
458*6b445a62SJohn Marino 
459*6b445a62SJohn Marino static void memory_error_and_abort ();
460*6b445a62SJohn Marino 
461*6b445a62SJohn Marino static void *
xmalloc(bytes)462*6b445a62SJohn Marino xmalloc (bytes)
463*6b445a62SJohn Marino      size_t bytes;
464*6b445a62SJohn Marino {
465*6b445a62SJohn Marino   void *temp = (char *)malloc (bytes);
466*6b445a62SJohn Marino 
467*6b445a62SJohn Marino   if (!temp)
468*6b445a62SJohn Marino     memory_error_and_abort ();
469*6b445a62SJohn Marino   return (temp);
470*6b445a62SJohn Marino }
471*6b445a62SJohn Marino 
472*6b445a62SJohn Marino static void *
xrealloc(pointer,bytes)473*6b445a62SJohn Marino xrealloc (pointer, bytes)
474*6b445a62SJohn Marino      void *pointer;
475*6b445a62SJohn Marino      int bytes;
476*6b445a62SJohn Marino {
477*6b445a62SJohn Marino   void *temp;
478*6b445a62SJohn Marino 
479*6b445a62SJohn Marino   if (!pointer)
480*6b445a62SJohn Marino     temp = malloc (bytes);
481*6b445a62SJohn Marino   else
482*6b445a62SJohn Marino     temp = realloc (pointer, bytes);
483*6b445a62SJohn Marino 
484*6b445a62SJohn Marino   if (!temp)
485*6b445a62SJohn Marino     memory_error_and_abort ();
486*6b445a62SJohn Marino 
487*6b445a62SJohn Marino   return (temp);
488*6b445a62SJohn Marino }
489*6b445a62SJohn Marino 
490*6b445a62SJohn Marino static void
memory_error_and_abort()491*6b445a62SJohn Marino memory_error_and_abort ()
492*6b445a62SJohn Marino {
493*6b445a62SJohn Marino   fprintf (stderr, "readline: out of virtual memory\n");
494*6b445a62SJohn Marino   abort ();
495*6b445a62SJohn Marino }
496*6b445a62SJohn Marino 
497*6b445a62SJohn Marino /*
498*6b445a62SJohn Marino  * Local variables:
499*6b445a62SJohn Marino  * compile-command: "gcc -g -DTEST -o tilde tilde.c"
500*6b445a62SJohn Marino  * end:
501*6b445a62SJohn Marino  */
502*6b445a62SJohn Marino #endif /* TEST */
503