Subject: Re: bug#75688: Replace wrapper scripts with search path value files in search-paths.d

From: Maxim Cournoyer <[email-masked]>
Date: Tue, 28 Jan 2025 13:55:00 +0900

Hi,

[email-masked] writes:

> From: 宋文武 <[email-masked]>
>
> This is used by 'g_build_guix_search_path_dirs' in our patched GLIB.
>
> * gnu/packages/patches/python-3-set-GUIX_INTERPRETER_PATH.patch: New patch.
> * gnu/local.mk (dist_patch_DATA): Register it.
> * gnu/packages/python.scm (python-3.10)[source]<patches>: Add it.

[...]

> diff --git a/gnu/packages/patches/python-3-set-GUIX_INTERPRETER_PATH.patch b/gnu/packages/patches/python-3-set-GUIX_INTERPRETER_PATH.patch
> new file mode 100644
> index 0000000000..2f173c68c8
> --- /dev/null
> +++ b/gnu/packages/patches/python-3-set-GUIX_INTERPRETER_PATH.patch
> @@ -0,0 +1,28 @@
> +The 'g_build_guix_search_path_dirs' function in our patched GLIB requires

s/function/procedure/, s/GLIB/GLib/

> +2 environment variables (GUIX_INTERPRETER_PATH and
> GUIX_MAIN_SCRIPT_PATH) to

I'd reword this to 'the GUIX_INTERPRETER_FILE and GUIX_MAIN_SCRIPT_FILE
environment variables to'

> +check if the current executable is a script launched by an interpreter, and
> +find the script path if it is.

I'd replace 'path' by 'file name' everywhere except perhaps in
environment variables where I'd use just '_FILE' for brevitiy, as path
conventionally implies multiple entries, and the GNU project prefers to
call the path of files 'file names' (see info '(Standards) GNU Manuals',
a manual from the autoconf package):

--8<---------------cut here---------------start------------->8---
   Please do not use the term "pathname" that is used in Unix
documentation; use "file name" (two words) instead.  We use the term
"path" only for search paths, which are lists of directory names.
--8<---------------cut here---------------end--------------->8---

> +---
> +diff --git a/Modules/main.c b/Modules/main.c
> +index 5bb1de2..83ada3d 100644
> +--- a/Modules/main.c
> ++++ b/Modules/main.c
> +@@ -636,6 +636,18 @@ pymain_run_python(int *exitcode)
> +            prepended to sys.path.
> +
> +            Otherwise, main_importer_path is left unchanged. */
> ++
> ++        /* Set environment variables to support 'search-paths.d'. */
> ++        char *exe_path = realpath("/proc/self/exe", NULL);
> ++        PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1);
> ++        const char *main_script_path = PyUnicode_AsUTF8(filename);
> ++        if (exe_path != NULL && main_script_path != NULL) {

I assume the != NULL guards to avoid the condition where allocating memory
failed?  Perhaps prefer to do something like:

if (!(exe_path && main_script_path)) {
    printf("memory allocation failure, aborting\n");
    exit(1);
}

> ++            setenv("GUIX_INTERPRETER_PATH", exe_path, 1);
> ++            setenv("GUIX_MAIN_SCRIPT_PATH", main_script_path, 1);
> ++        }
> ++        free(exe_path);
> ++        Py_DECREF(filename);
> ++

I was wondering, if instead of having to patch every interpreter out
there, would it be possible to infer this inside glib by having a list
of interpreter base names?  e.g. python, guile, etc., and when we find
these in /proc/self/exe, we look at the /proc/self/comm and extract arg1
from there, which hopefully would be the script?  But that'd be fragile
given the script argument position is not guaranteed to come as arg1, it
could come later, e.g. for some scripts launched via '#/usr/bin/env -S
python3 --some-option ...'.  Your solution should be more reliable for
that reason, so perhaps it's necessary.

-- 
Thanks,
Maxim