/* tilde.c -- tilde expansion code (~/foo := $HOME/foo).

   Copyright 1988-2023 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 <http://www.gnu.org/licenses/>.

   Originally written by Brian Fox. */

#include "info.h"
#include "tilde.h"

/* 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;
}
