Back to index

tetex-bin  3.0
tilde.c
Go to the documentation of this file.
00001 /* tilde.c: Expand user's home directories.
00002 
00003 Copyright (C) 1993, 95, 96, 97 Karl Berry.
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Library General Public
00007 License as published by the Free Software Foundation; either
00008 version 2 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Library General Public License for more details.
00014 
00015 You should have received a copy of the GNU Library General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #include <kpathsea/config.h>
00020 
00021 #include <kpathsea/c-pathch.h>
00022 #include <kpathsea/tilde.h>
00023 
00024 #ifdef HAVE_PWD_H
00025 #include <pwd.h>
00026 #endif
00027 
00028 
00029 /* If NAME has a leading ~ or ~user, Unix-style, expand it to the user's
00030    home directory, and return a new malloced string.  If no ~, or no
00031    <pwd.h>, just return NAME.  */
00032 
00033 string
00034 kpse_tilde_expand P1C(const_string, name)
00035 {
00036   const_string expansion;
00037   const_string home;
00038   
00039   assert (name);
00040   
00041   /* If no leading tilde, do nothing.  */
00042   if (*name != '~') {
00043     expansion = name;
00044   
00045   /* If a bare tilde, return the home directory or `.'.  (Very unlikely
00046      that the directory name will do anyone any good, but ...  */
00047   } else if (name[1] == 0) {
00048     home = getenv ("HOME");
00049     if (!home) {
00050       home = ".";
00051     }
00052     expansion = xstrdup (home);
00053   
00054   /* If `~/', remove any trailing / or replace leading // in $HOME.
00055      Should really check for doubled intermediate slashes, too.  */
00056   } else if (IS_DIR_SEP (name[1])) {
00057     unsigned c = 1;
00058     home = getenv ("HOME");
00059     if (!home) {
00060       home = ".";
00061     }
00062     if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) {  /* handle leading // */
00063       home++;
00064     }
00065     if (IS_DIR_SEP (home[strlen (home) - 1])) {        /* omit / after ~ */
00066       c++;
00067     }
00068     expansion = concat (home, name + c);
00069   
00070   /* If `~user' or `~user/', look up user in the passwd database (but
00071      OS/2 doesn't have this concept.  */
00072   } else
00073 #ifdef HAVE_PWD_H
00074     {
00075       struct passwd *p;
00076       string user;
00077       unsigned c = 2;
00078       while (!IS_DIR_SEP (name[c]) && name[c] != 0) /* find user name */
00079         c++;
00080       
00081       user = (string) xmalloc (c);
00082       strncpy (user, name + 1, c - 1);
00083       user[c - 1] = 0;
00084       
00085       /* We only need the cast here for (deficient) systems
00086          which do not declare `getpwnam' in <pwd.h>.  */
00087       p = (struct passwd *) getpwnam (user);
00088       free (user);
00089 
00090       /* If no such user, just use `.'.  */
00091       home = p ? p->pw_dir : ".";
00092       if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) { /* handle leading // */
00093         home++;
00094       }
00095       if (IS_DIR_SEP (home[strlen (home) - 1]) && name[c] != 0)
00096         c++; /* If HOME ends in /, omit the / after ~user. */
00097 
00098       expansion = name[c] == 0 ? xstrdup (home) : concat (home, name + c);
00099     }
00100 #else /* not HAVE_PWD_H */
00101     expansion = name;
00102 #endif /* not HAVE_PWD_H */
00103 
00104   /* We may return the same thing as the original, and then we might not
00105      be returning a malloc-ed string.  Callers beware.  Sorry.  */
00106   return (string) expansion;
00107 }
00108 
00109 #ifdef TEST
00110 
00111 void
00112 test_expand_tilde (const_string filename)
00113 {
00114   string answer;
00115   
00116   printf ("Tilde expansion of `%s':\t", filename ? filename : "(nil)");
00117   answer = kpse_tilde_expand (filename);
00118   puts (answer);
00119 }
00120 
00121 int
00122 main ()
00123 {
00124   string tilde_path = "tilde";
00125 
00126   test_expand_tilde ("");
00127   test_expand_tilde ("none");
00128   test_expand_tilde ("~root");
00129   test_expand_tilde ("~");
00130   test_expand_tilde ("foo~bar");
00131   
00132   return 0;
00133 }
00134 
00135 #endif /* TEST */
00136 
00137 
00138 /*
00139 Local variables:
00140 standalone-compile-command: "gcc -g -I. -I.. -DTEST tilde.c kpathsea.a"
00141 End:
00142 */