diff options
| author | Paul Eggert | 2018-11-13 09:29:14 -0800 |
|---|---|---|
| committer | Paul Eggert | 2018-11-13 09:32:50 -0800 |
| commit | 900276502fbb4dcabdabc5d7d24b4bc5645f2cf3 (patch) | |
| tree | 4d6c17f5b3cea0f4d5dfbc7243eb6495269a7e56 /src/fileio.c | |
| parent | ce1fb157e840fd292c3db4632831c4514a663890 (diff) | |
| download | emacs-900276502fbb4dcabdabc5d7d24b4bc5645f2cf3.tar.gz emacs-900276502fbb4dcabdabc5d7d24b4bc5645f2cf3.zip | |
Act like POSIX sh if $HOME is relative
POSIX says sh ~/foo should act like $HOME/foo even if $HOME is
relative, so be consistent with that (Bug#33255).
* admin/merge-gnulib (GNULIB_MODULES): Add dosname.
* src/buffer.c (init_buffer): Use emacs_wd to get
initial working directory with slash appended if needed.
(default-directory): Say it must be absolute.
* src/emacs.c (emacs_wd): New global variable.
(init_cmdargs): Dir arg is now char const *.
(main): Set emacs_wd.
* src/emacs.c (main) [NS_IMPL_COCOA]:
* src/fileio.c (Fexpand_file_name):
Use get_homedir instead of egetenv ("HOME").
* src/fileio.c: Include dosname.h, for IS_ABSOLUTE_FILE_NAME.
(splice_dir_file, get_homedir): New functions.
* src/xrdb.c (gethomedir): Remove. All callers changed
to use get_homedir and splice_dir_file.
* test/src/fileio-tests.el (fileio-tests--relative-HOME): New test.
Diffstat (limited to 'src/fileio.c')
| -rw-r--r-- | src/fileio.c | 62 |
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. */ | ||
| 1641 | static bool | 1640 | static bool |
| 1642 | file_name_absolute_p (const char *filename) | 1641 | file_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. */ | ||
| 1655 | char * | ||
| 1656 | splice_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. */ | ||
| 1668 | char const * | ||
| 1669 | get_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. */ | ||
| 1653 | static char * | 1707 | static char * |
| 1654 | search_embedded_absfilename (char *nm, char *endp) | 1708 | search_embedded_absfilename (char *nm, char *endp) |
| 1655 | { | 1709 | { |