| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Copyright (C) 1988,1989 Free Software Foundation, Inc.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    This file is part of GNU Readline, a library for reading lines | 
					
						
							|  |  |  |  |    of text with interactive input and history editing. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    Readline 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 1, or (at your option) any | 
					
						
							|  |  |  |  |    later version. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |    Readline 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 Readline; see the file COPYING.  If not, write to the Free | 
					
						
							|  |  |  |  |    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #if defined (HAVE_CONFIG_H)
 | 
					
						
							|  |  |  |  | #  include <config.h>
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |  | #  ifdef _MINIX
 | 
					
						
							|  |  |  |  | #    include <sys/types.h>
 | 
					
						
							|  |  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | #if defined (HAVE_STRING_H)
 | 
					
						
							|  |  |  |  | #  include <string.h>
 | 
					
						
							|  |  |  |  | #else /* !HAVE_STRING_H */
 | 
					
						
							|  |  |  |  | #  include <strings.h>
 | 
					
						
							|  |  |  |  | #endif /* !HAVE_STRING_H */  
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if defined (HAVE_STDLIB_H)
 | 
					
						
							|  |  |  |  | #  include <stdlib.h>
 | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | #  include "ansi_stdlib.h"
 | 
					
						
							|  |  |  |  | #endif /* HAVE_STDLIB_H */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  |  | #include <pwd.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #include "tilde.h"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | #ifdef SHELL
 | 
					
						
							|  |  |  |  | #include "shell.h"
 | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #if !defined (HAVE_GETPW_DECLS)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | extern struct passwd *getpwuid (), *getpwnam (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | #endif /* !HAVE_GETPW_DECLS */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | #if !defined (savestring)
 | 
					
						
							|  |  |  |  | extern char *xmalloc (); | 
					
						
							|  |  |  |  | #  ifndef strcpy
 | 
					
						
							|  |  |  |  | extern char *strcpy (); | 
					
						
							|  |  |  |  | #  endif
 | 
					
						
							|  |  |  |  | #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
 | 
					
						
							|  |  |  |  | #endif /* !savestring */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if !defined (NULL)
 | 
					
						
							|  |  |  |  | #  if defined (__STDC__)
 | 
					
						
							|  |  |  |  | #    define NULL ((void *) 0)
 | 
					
						
							|  |  |  |  | #  else
 | 
					
						
							|  |  |  |  | #    define NULL 0x0
 | 
					
						
							|  |  |  |  | #  endif /* !__STDC__ */
 | 
					
						
							|  |  |  |  | #endif /* !NULL */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | #if defined (TEST) || defined (STATIC_MALLOC)
 | 
					
						
							|  |  |  |  | static char *xmalloc (), *xrealloc (); | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | extern char *xmalloc (), *xrealloc (); | 
					
						
							|  |  |  |  | #endif /* TEST || STATIC_MALLOC */
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* The default value of tilde_additional_prefixes.  This is set to
 | 
					
						
							|  |  |  |  |    whitespace preceding a tilde so that simple programs which do not | 
					
						
							|  |  |  |  |    perform any word separation get desired behaviour. */ | 
					
						
							|  |  |  |  | static char *default_prefixes[] = | 
					
						
							|  |  |  |  |   { " ~", "\t~", (char *)NULL }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* The default value of tilde_additional_suffixes.  This is set to
 | 
					
						
							|  |  |  |  |    whitespace or newline so that simple programs which do not | 
					
						
							|  |  |  |  |    perform any word separation get desired behaviour. */ | 
					
						
							|  |  |  |  | static char *default_suffixes[] = | 
					
						
							|  |  |  |  |   { " ", "\n", (char *)NULL }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | /* 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; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* 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 | 
					
						
							|  |  |  |  |    which is the expansion, or a NULL pointer if there is no expansion. */ | 
					
						
							|  |  |  |  | CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* When non-null, this is a NULL terminated array of strings which
 | 
					
						
							|  |  |  |  |    are duplicates for a tilde prefix.  Bash uses this to expand | 
					
						
							|  |  |  |  |    `=~' and `:~'. */ | 
					
						
							|  |  |  |  | char **tilde_additional_prefixes = default_prefixes; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* When non-null, this is a NULL terminated array of strings which match
 | 
					
						
							|  |  |  |  |    the end of a username, instead of just "/".  Bash sets this to | 
					
						
							|  |  |  |  |    `:' and `=~'. */ | 
					
						
							|  |  |  |  | char **tilde_additional_suffixes = default_suffixes; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Find the start of a tilde expansion in STRING, and return the index of
 | 
					
						
							|  |  |  |  |    the tilde which starts the expansion.  Place the length of the text | 
					
						
							|  |  |  |  |    which identified this tilde starter in LEN, excluding the tilde itself. */ | 
					
						
							|  |  |  |  | static int | 
					
						
							|  |  |  |  | tilde_find_prefix (string, len) | 
					
						
							|  |  |  |  |      char *string; | 
					
						
							|  |  |  |  |      int *len; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   register int i, j, string_len; | 
					
						
							|  |  |  |  |   register char **prefixes = tilde_additional_prefixes; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   string_len = strlen (string); | 
					
						
							|  |  |  |  |   *len = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   if (*string == '\0' || *string == '~') | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     return (0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (prefixes) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       for (i = 0; i < string_len; i++) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  for (j = 0; prefixes[j]; j++) | 
					
						
							|  |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		  *len = strlen (prefixes[j]) - 1; | 
					
						
							|  |  |  |  | 		  return (i + *len); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	    } | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   return (string_len); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* Find the end of a tilde expansion in STRING, and return the index of
 | 
					
						
							|  |  |  |  |    the character which ends the tilde definition.  */ | 
					
						
							|  |  |  |  | static int | 
					
						
							|  |  |  |  | tilde_find_suffix (string) | 
					
						
							|  |  |  |  |      char *string; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   register int i, j, string_len; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   register char **suffixes; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   suffixes = tilde_additional_suffixes; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   string_len = strlen (string); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   for (i = 0; i < string_len; i++) | 
					
						
							|  |  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |       if (string[i] == '/' /* || !string[i] */) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       for (j = 0; suffixes && suffixes[j]; j++) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0) | 
					
						
							|  |  |  |  | 	    return (i); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   return (i); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | #if !defined (SHELL)
 | 
					
						
							|  |  |  |  | static char * | 
					
						
							|  |  |  |  | get_string_value (varname) | 
					
						
							|  |  |  |  |      char *varname; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   return ((char *)getenv (varname)); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | #endif
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* Return a new string which is the result of tilde expanding STRING. */ | 
					
						
							|  |  |  |  | char * | 
					
						
							|  |  |  |  | tilde_expand (string) | 
					
						
							|  |  |  |  |      char *string; | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   char *result; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   int result_size, result_index; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   result_index = result_size = 0; | 
					
						
							|  |  |  |  |   if (result = strchr (string, '~')) | 
					
						
							|  |  |  |  |     result = xmalloc (result_size = (strlen (string) + 16)); | 
					
						
							|  |  |  |  |   else | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  |  |     result = xmalloc (result_size = (strlen (string) + 1)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Scan through STRING expanding tildes as we come to them. */ | 
					
						
							|  |  |  |  |   while (1) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       register int start, end; | 
					
						
							|  |  |  |  |       char *tilde_word, *expansion; | 
					
						
							|  |  |  |  |       int len; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Make START point to the tilde which starts the expansion. */ | 
					
						
							|  |  |  |  |       start = tilde_find_prefix (string, &len); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Copy the skipped text into the result. */ | 
					
						
							|  |  |  |  |       if ((result_index + start + 1) > result_size) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 	result = xrealloc (result, 1 + (result_size += (start + 20))); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       strncpy (result + result_index, string, start); | 
					
						
							|  |  |  |  |       result_index += start; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Advance STRING to the starting tilde. */ | 
					
						
							|  |  |  |  |       string += start; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Make END be the index of one after the last character of the
 | 
					
						
							|  |  |  |  | 	 username. */ | 
					
						
							|  |  |  |  |       end = tilde_find_suffix (string); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* If both START and END are zero, we are all done. */ | 
					
						
							|  |  |  |  |       if (!start && !end) | 
					
						
							|  |  |  |  | 	break; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* Expand the entire tilde word, and copy it into RESULT. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |       tilde_word = xmalloc (1 + end); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |       strncpy (tilde_word, string, end); | 
					
						
							|  |  |  |  |       tilde_word[end] = '\0'; | 
					
						
							|  |  |  |  |       string += end; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       expansion = tilde_expand_word (tilde_word); | 
					
						
							|  |  |  |  |       free (tilde_word); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       len = strlen (expansion); | 
					
						
							|  |  |  |  |       if ((result_index + len + 1) > result_size) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 	result = xrealloc (result, 1 + (result_size += (len + 20))); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       strcpy (result + result_index, expansion); | 
					
						
							|  |  |  |  |       result_index += len; | 
					
						
							|  |  |  |  |       free (expansion); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   result[result_index] = '\0'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return (result); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | /* 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); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |    tilde.  If there is no expansion, call tilde_expansion_failure_hook. | 
					
						
							|  |  |  |  |    This always returns a newly-allocated string, never static storage. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | char * | 
					
						
							|  |  |  |  | tilde_expand_word (filename) | 
					
						
							|  |  |  |  |      char *filename; | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   char *dirname, *expansion, *username; | 
					
						
							|  |  |  |  |   int user_len; | 
					
						
							|  |  |  |  |   struct passwd *user_entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   if (filename == 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |     return ((char *)NULL); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   if (*filename != '~') | 
					
						
							|  |  |  |  |     return (savestring (filename)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   /* 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] == '/') | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |       /* Prefix $HOME to the rest of the string. */ | 
					
						
							|  |  |  |  |       expansion = get_string_value ("HOME"); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |       /* If there is no HOME variable, look up the directory in
 | 
					
						
							|  |  |  |  | 	 the password database. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |       if (expansion == 0) | 
					
						
							|  |  |  |  | 	expansion = get_home_dir (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |       return (glue_prefix_and_suffix (expansion, filename, 1)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   username = isolate_tilde_prefix (filename, &user_len); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   if (tilde_expansion_preexpansion_hook) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       expansion = (*tilde_expansion_preexpansion_hook) (username); | 
					
						
							|  |  |  |  |       if (expansion) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | 	  dirname = glue_prefix_and_suffix (expansion, filename, user_len); | 
					
						
							|  |  |  |  | 	  free (username); | 
					
						
							|  |  |  |  | 	  free (expansion); | 
					
						
							|  |  |  |  | 	  return (dirname); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* 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) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  | 	  expansion = (*tilde_expansion_failure_hook) (username); | 
					
						
							|  |  |  |  | 	  if (expansion) | 
					
						
							|  |  |  |  | 	    { | 
					
						
							|  |  |  |  | 	      dirname = glue_prefix_and_suffix (expansion, filename, user_len); | 
					
						
							|  |  |  |  | 	      free (expansion); | 
					
						
							|  |  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  |       free (username); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |       /* 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); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |  |   endpwent (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   return (dirname); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  | 
					
						
							|  |  |  |  | #if defined (TEST)
 | 
					
						
							|  |  |  |  | #undef NULL
 | 
					
						
							|  |  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | main (argc, argv) | 
					
						
							|  |  |  |  |      int argc; | 
					
						
							|  |  |  |  |      char **argv; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   char *result, line[512]; | 
					
						
							|  |  |  |  |   int done = 0; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   while (!done) | 
					
						
							|  |  |  |  |     { | 
					
						
							|  |  |  |  |       printf ("~expand: "); | 
					
						
							|  |  |  |  |       fflush (stdout); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if (!gets (line)) | 
					
						
							|  |  |  |  | 	strcpy (line, "done"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       if ((strcmp (line, "done") == 0) || | 
					
						
							|  |  |  |  | 	  (strcmp (line, "quit") == 0) || | 
					
						
							|  |  |  |  | 	  (strcmp (line, "exit") == 0)) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	  done = 1; | 
					
						
							|  |  |  |  | 	  break; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |       result = tilde_expand (line); | 
					
						
							|  |  |  |  |       printf ("  --> %s\n", result); | 
					
						
							|  |  |  |  |       free (result); | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  |   exit (0); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void memory_error_and_abort (); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static char * | 
					
						
							|  |  |  |  | xmalloc (bytes) | 
					
						
							|  |  |  |  |      int bytes; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   char *temp = (char *)malloc (bytes); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!temp) | 
					
						
							|  |  |  |  |     memory_error_and_abort (); | 
					
						
							|  |  |  |  |   return (temp); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static char * | 
					
						
							|  |  |  |  | xrealloc (pointer, bytes) | 
					
						
							|  |  |  |  |      char *pointer; | 
					
						
							|  |  |  |  |      int bytes; | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |   char *temp; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!pointer) | 
					
						
							|  |  |  |  |     temp = (char *)malloc (bytes); | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     temp = (char *)realloc (pointer, bytes); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (!temp) | 
					
						
							|  |  |  |  |     memory_error_and_abort (); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   return (temp); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | static void | 
					
						
							|  |  |  |  | memory_error_and_abort () | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |  |   fprintf (stderr, "readline: out of virtual memory\n"); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |  |   abort (); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /*
 | 
					
						
							|  |  |  |  |  * Local variables: | 
					
						
							|  |  |  |  |  * compile-command: "gcc -g -DTEST -o tilde tilde.c" | 
					
						
							|  |  |  |  |  * end: | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | #endif /* TEST */
 |