aboutsummaryrefslogtreecommitdiffstats
path: root/src/fileio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c62
1 files changed, 58 insertions, 4 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 7fb865809f5..e178c39fc18 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -96,6 +96,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
96#include <acl.h> 96#include <acl.h>
97#include <allocator.h> 97#include <allocator.h>
98#include <careadlinkat.h> 98#include <careadlinkat.h>
99#include <dosname.h>
99#include <fsusage.h> 100#include <fsusage.h>
100#include <stat-time.h> 101#include <stat-time.h>
101#include <tempname.h> 102#include <tempname.h>
@@ -1093,8 +1094,7 @@ the root directory. */)
1093 { 1094 {
1094 Lisp_Object tem; 1095 Lisp_Object tem;
1095 1096
1096 if (!(newdir = egetenv ("HOME"))) 1097 newdir = get_homedir ();
1097 newdir = newdirlim = "";
1098 nm++; 1098 nm++;
1099#ifdef WINDOWSNT 1099#ifdef WINDOWSNT
1100 if (newdir[0]) 1100 if (newdir[0])
@@ -1109,7 +1109,7 @@ the root directory. */)
1109#endif 1109#endif
1110 tem = build_string (newdir); 1110 tem = build_string (newdir);
1111 newdirlim = newdir + SBYTES (tem); 1111 newdirlim = newdir + SBYTES (tem);
1112 /* `egetenv' may return a unibyte string, which will bite us 1112 /* get_homedir may return a unibyte string, which will bite us
1113 if we expect the directory to be multibyte. */ 1113 if we expect the directory to be multibyte. */
1114 if (multibyte && !STRING_MULTIBYTE (tem)) 1114 if (multibyte && !STRING_MULTIBYTE (tem))
1115 { 1115 {
@@ -1637,7 +1637,6 @@ See also the function `substitute-in-file-name'.")
1637} 1637}
1638#endif 1638#endif
1639 1639
1640/* If /~ or // appears, discard everything through first slash. */
1641static bool 1640static bool
1642file_name_absolute_p (const char *filename) 1641file_name_absolute_p (const char *filename)
1643{ 1642{
@@ -1650,6 +1649,61 @@ file_name_absolute_p (const char *filename)
1650 ); 1649 );
1651} 1650}
1652 1651
1652/* Put into BUF the concatenation of DIR and FILE, with an intervening
1653 directory separator if needed. Return a pointer to the null byte
1654 at the end of the concatenated string. */
1655char *
1656splice_dir_file (char *buf, char const *dir, char const *file)
1657{
1658 char *e = stpcpy (buf, dir);
1659 *e = DIRECTORY_SEP;
1660 e += ! (buf < e && IS_DIRECTORY_SEP (e[-1]));
1661 return stpcpy (e, file);
1662}
1663
1664/* Get the home directory, an absolute file name. Return the empty
1665 string on failure. The returned value does not survive garbage
1666 collection, calls to this function, or calls to the getpwnam class
1667 of functions. */
1668char const *
1669get_homedir (void)
1670{
1671 char const *home = egetenv ("HOME");
1672 if (!home)
1673 {
1674 static char const *userenv[] = {"LOGNAME", "USER"};
1675 struct passwd *pw = NULL;
1676 for (int i = 0; i < ARRAYELTS (userenv); i++)
1677 {
1678 char *user = egetenv (userenv[i]);
1679 if (user)
1680 {
1681 pw = getpwnam (user);
1682 if (pw)
1683 break;
1684 }
1685 }
1686 if (!pw)
1687 pw = getpwuid (getuid ());
1688 if (pw)
1689 home = pw->pw_dir;
1690 if (!home)
1691 return "";
1692 }
1693 if (IS_ABSOLUTE_FILE_NAME (home))
1694 return home;
1695 if (!emacs_wd)
1696 error ("$HOME is relative to unknown directory");
1697 static char *ahome;
1698 static ptrdiff_t ahomesize;
1699 ptrdiff_t ahomelenbound = strlen (emacs_wd) + 1 + strlen (home) + 1;
1700 if (ahomesize <= ahomelenbound)
1701 ahome = xpalloc (ahome, &ahomesize, ahomelenbound + 1 - ahomesize, -1, 1);
1702 splice_dir_file (ahome, emacs_wd, home);
1703 return ahome;
1704}
1705
1706/* If /~ or // appears, discard everything through first slash. */
1653static char * 1707static char *
1654search_embedded_absfilename (char *nm, char *endp) 1708search_embedded_absfilename (char *nm, char *endp)
1655{ 1709{