Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: ksh compatibility: initial value of $_
> 2023/04/09 1:22、Oliver Kiddle <opk@xxxxxxx>のメール:
>
> dana wrote:
>> Maybe ZSH_EXECUTABLE? That kind of matches ZSH_SCRIPT too
>
> That sounds good. Unless we want to take advantage of Bart's recent
> changes and put it in a namespace.
In the path below I used ZSH_EXEPATH to make it (somewhat) easier to
guess that it is a full pathname, but ZSH_EXECUTABLE (or any other
name) is OK for me.
If it will be put in a namespace, is it available only in the namespace,
or also in the toplevel namespace?
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 2db4210eb..08b3e79f6 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -1112,6 +1112,10 @@ item(tt(ZSH_EXECUTION_STRING))(
If the shell was started with the option tt(-c), this contains
the argument passed to the option. Otherwise it is not set.
)
+vindex(ZSH_EXEPATH)
+item(tt(ZSH_EXEPATH))(
+Full pathname of the executable file of current zsh process.
+)
vindex(ZSH_NAME)
item(tt(ZSH_NAME))(
Expands to the basename of the command used to invoke this instance
diff --git a/Src/init.c b/Src/init.c
index 7e98af44c..f8acf2ff1 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -246,6 +246,9 @@ loop(int toplevel, int justonce)
static int restricted;
+/* original argv[0] for initialization of $_. this is already metafied */
+static char *argv0;
+
/**/
static void
parseargs(char *zsh_name, char **argv, char **runscript, char **cmdptr,
@@ -257,7 +260,7 @@ parseargs(char *zsh_name, char **argv, char **runscript, char **cmdptr,
if (**argv == '-')
flags |= PARSEARGS_LOGIN;
- argzero = posixzero = *argv++;
+ argv0 = argzero = posixzero = *argv++;
SHIN = 0;
/*
@@ -893,6 +896,106 @@ init_term(void)
return 1;
}
+/*
+ * Get (or guess) the absolute pathname of the current zsh exeutable.
+ * Try OS-specific method, and if it fails, guess the absolute pathname
+ * from argv0, pwd, and PATH. 'name' and 'cwd' are unmetefied versions of
+ * argv0 and pwd.
+ * Returns a zalloc()ed string (not metafied), or NULL if failed.
+ */
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
+/**/
+static char *
+getmypath(const char *name, const char *cwd)
+{
+ char *buf;
+ int namelen;
+
+ if (!name)
+ return NULL;
+ if (*name == '-')
+ ++name;
+ if ((namelen = strlen(name) == 0))
+ return NULL;
+#if defined(__APPLE__)
+ {
+ uint32_t n = PATH_MAX;
+ int ret;
+ buf = (char *)zalloc(PATH_MAX);
+ if ((ret = _NSGetExecutablePath(buf, &n)) < 0) {
+ /* try again with increased buffer size */
+ buf = (char *)zrealloc(buf, n);
+ ret = _NSGetExecutablePath(buf, &n);
+ }
+ if (ret == 0 && strlen(buf) > 0)
+ return buf;
+ else
+ free(buf);
+ }
+#elif defined(PROC_SELF_EXE)
+ {
+ ssize_t n;
+ buf = (char *)zalloc(PATH_MAX);
+ n = readlink(PROC_SELF_EXE, buf, PATH_MAX);
+ if (n > 0 && n < PATH_MAX) {
+ buf[n] = '\0';
+ return buf;
+ }
+ else
+ free(buf);
+ }
+#endif
+ /* guess the absolute pathname of 'name' */
+ if (name[namelen-1] == '/') /* name should not end with '/' */
+ return NULL;
+ else if (name[0] == '/') {
+ /* name is already an absolute pathname */
+ return ztrdup(name);
+ }
+ else if (strchr(name, '/')) {
+ /* relative path */
+ if (!cwd)
+ return NULL;
+ buf = (char *)zalloc(strlen(cwd) + namelen + 2);
+ sprintf(buf, "%s/%s", cwd, name);
+ return buf;
+ }
+#ifdef HAVE_REALPATH
+ else {
+ /* search each dir in PARH */
+ const char *path, *sep;
+ char *real, *try;
+ int pathlen, dirlen;
+
+ path = getenv("PATH");
+ if (!path || (pathlen = strlen(path)) == 0)
+ return NULL;
+ /* for simplicity, allocate buf even if REALPATH_ACCEPTS_NULL is on */
+ buf = (char *)zalloc(PATH_MAX);
+ try = (char *)zalloc(pathlen + namelen + 2);
+ do {
+ sep = strchr(path, ':');
+ dirlen = sep ? sep - path : strlen(path);
+ strncpy(try, path, dirlen);
+ try[dirlen] = '/';
+ try[dirlen+1] = '\0';
+ strcat(try, name);
+ real = realpath(try, buf);
+ if (sep)
+ path = sep + 1;
+ } while (!real && sep);
+ free(try);
+ if (!real)
+ free(buf);
+ return real; /* this may be NULL */
+ }
+#endif
+ return NULL;
+}
+
/* Initialize lots of global variables and hash tables */
/**/
@@ -1195,6 +1298,18 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
/* Colour sequences for outputting colours in prompts and zle */
set_default_colour_sequences();
+ /* ZSH_EXEPATH */
+ {
+ char *mypath, *exename, *cwd;
+ exename = unmetafy(ztrdup(argv0), NULL);
+ cwd = pwd ? unmetafy(ztrdup(pwd), NULL) : NULL;
+ mypath = getmypath(exename, cwd);
+ free(exename);
+ free(cwd);
+ if (mypath) {
+ setsparam("ZSH_EXEPATH", metafy(mypath, -1, META_REALLOC));
+ }
+ }
if (cmd)
setsparam("ZSH_EXECUTION_STRING", ztrdup(cmd));
if (runscript)
diff --git a/configure.ac b/configure.ac
index e6ced85d9..d8a17791a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2011,6 +2011,25 @@ if test x$zsh_cv_sys_path_dev_fd != xno; then
AC_DEFINE_UNQUOTED(PATH_DEV_FD, "$zsh_cv_sys_path_dev_fd")
fi
+dnl ----------------------------------------------------
+dnl CHECK FOR SYMLINK TO THE CURRENT EXECUTABLE IN /proc
+dnl ----------------------------------------------------
+dnl Linux: /proc/self/exe
+dnl NetBSD: /proc/curproc/exe (or /proc/self/exe, but not /proc/curproc/file)
+dnl DragonFly: /proc/curproc/file
+dnl Solaris: /proc/self/path/a.out
+AH_TEMPLATE([PROC_SELF_EXE],
+[Define to the path of the symlink to the current executable file.])
+AC_CACHE_CHECK(for symlink to the current executable in /proc,
+zsh_cv_proc_self_exe,
+[for zsh_cv_proc_self_exe in /proc/self/exe /proc/curproc/exe \
+ /proc/curproc/file /proc/self/path/a.out no; do
+ test -L $zsh_cv_proc_self_exe && break
+done])
+if test x$zsh_cv_proc_self_exe != xno; then
+ AC_DEFINE_UNQUOTED(PROC_SELF_EXE, "$zsh_cv_proc_self_exe")
+fi
+
dnl ---------------------------------
dnl CHECK FOR RFS SUPERROOT DIRECTORY
dnl ---------------------------------
Messages sorted by:
Reverse Date,
Date,
Thread,
Author