Subject: [bug#57050] [PATCH v2 04/13] gnu: Add Zuo.

From: "Philip McGrath" <[email-masked]>
Date: Mon, 22 Aug 2022 21:40:29 -0400

Hi,

On Tue, Aug 16, 2022, at 10:47 AM, Maxime Devos wrote:
> On 11-08-2022 16:00, Philip McGrath wrote:
>>>> +        #~`(,(string-append "CPPFLAGS=-DGUIX_RKTIO_BIN_SH="
>>>> +                            #$(file-append (this-package-input
>>>> "bash-minimal")
>>>> +                                           "/bin/sh"))
>>>> 
>>> As with chez-scheme, I do think using a Racket-agnostic macro name is
>>> helpful here.
>>> 
>> I'm planning to respond in the other thread about the possibility of a truly generic macro name, but I hope it doesn't need to become an issue blocking this patch series. For now, I'm not entirely sure what "Racket-agnostic" means; the bottom line for my is I think it would be absurdly awful to have to write, e.g. if cross-compiling using `distro-build` with the top-level Makefile:
>> 
>>     ./configure CPPFLAGS="GUIX_RKTIO_BIN_SH=/input/bin/sh GUIX_ZUO_BIN_SH=/input/bin/sh GUIX_CHEZ_BIN_SH=/input/bin/sh" CPPFLAGS_FOR_BUILD="GUIX_RKTIO_BIN_SH=/native-input/bin/sh GUIX_ZUO_BIN_SH=/native-input/bin/sh GUIX_CHEZ_BIN_SH=/native-input/bin/sh"
>
> Example: GUIX_SH=/inputs/bin/sh.
> 

I will use GUIX_SH in v3 of this series.

My concern with it originally was that it's generic enough that it might be used in other ways elsewhere in Guix, but, since I'm hoping it's only going to be a medium-term solution, it seems good enough, and I haven't heard any objections to it.

> I haven't been following the discussion on the other patches, but didn't I give an example of something independent of the Racket component in use and even independent of Racket itself? See the suggestion of using the already existing _PATH_BSHELL from <paths.h>. It's even not Guix-specific, apparently it's a BSD-ism!
> 

On Wed, Aug 10, 2022, at 7:46 AM, Maxime Devos wrote:
> On 09-08-2022 23:58, Philip McGrath wrote:
>
>> On Tuesday, August 9, 2022 5:38:56 PM EDT ( wrote:
>>> On Tue Aug 9, 2022 at 10:24 PM BST, Maxime Devos wrote:
>>>> In the glibc headers, there's some (POSIX?) standard macro that points
>>>> at "/gnu/store/.../bin/sh" (I don't recall the name), any reason we
>>>> aren't using that macro?  That would be Guix-independent. I'm not sure
>>>> if a /gnu/store/... prefix is included, but if not, maybe we could try
>>>> overriding it with -D...="/gnu/store/...", or failing that, add a
>>>> post-unpack substitute* replacing [the macro name] ->
>>>> "/gnu/store/.../bin/sh".
>>> I believe you might be referring to <paths.h>, which defines _PATH_BSHELL.
>>>
>>> It's not standard C <https://en.cppreference.com/w/c/header> nor POSIX
>>> <https://pubs.opengroup.org/onlinepubs/9699919799/idx/head.html> though.
>>>
>>>      -- (
>
> Looking at the "paths.h" header, it appears to be a BSDism. Not really 
> standard but still better than a Guix-ism.
>
>> I'd love to be wrong, but I also can't find such a macro. In the glibc source
>> tree, "stdlib/system.c" defines a stub implementation that always fails with
>> ENOSYS, and "sysdeps/posix/system.c" contains:
>>
>>      #define	SHELL_PATH	"/bin/sh"	/* Path of the shell.  */
>>      #define	SHELL_NAME	"sh"	/* Name to give it.  */
>>
>> Concretely, I think Guix's glibc currently uses /bin/sh dynamically: in my
>> Chez example above, if you replace `process` with `system` (which uses libc's
>> `system`), the result is always "/bin/sh\n".
>
> If so, that's a bug.  I do not know what result you are referring to.

(Disregard this part; I think I was thinking about some other way I had tried things.)

>
> Anyway, the Guix package definition of glibc substitutes _PATH_BSHELL 
> and SHELL_PATH, so unless there's a bug, it doesn't depend on /bin/sh.
>

I have been looking further into options for addressing this upstream.

First of all, I have found that there *is* another Unix-like system where "/bin/sh" doesn't exist: on Android, the POSIX shell is usually at "/system/bin/sh". Also, at least on some versions, _PATH_BSHELL isn't a compile-time constant. It is:

    #define _PATH_BSHELL __bionic_get_shell_path()

(There are also systems where "/bin/sh" is some non-POSIX shell and the POSIX shell is at "/usr/xpg4/bin/sh". If changing this upstream, Racket may need to decide whether POSIX compatibility or historical compatibility is more important there.)

I've found that there does seem to be a POSIX recommendation for finding "sh". The POSIX spec for `system` <https://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html> says, under "Application Usage", "There is no defined way for an application to find the specific path for the shell. However, confstr() can provide a value for PATH that is guaranteed to find the sh utility." Similarly, <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html> says that "applications should note that the standard PATH to the shell cannot be assumed to be either /bin/sh or /usr/bin/sh, and should be determined by interrogation of the PATH returned by getconf PATH, ensuring that the returned pathname is an absolute pathname and not a shell built-in." Most emphatically, <https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html> says in the normative "Description":

>
> If the implementation supports the POSIX shell option, the string stored in buf after a call to:
>
>     confstr(_CS_PATH, buf, sizeof(buf))
>
> can be used as a value of the PATH environment variable that accesses all of the standard utilities of POSIX.1-2017, that are provided in a manner accessible via the exec family of functions, if the return value is less than or equal to sizeof(buf).
>

However, apparently using `confstr` with `_CS_PATH` does not give a useful result in Guix build environments. Try building the following package with `guix build -f`: I've put the interesting log output in the description. In particular, note that *both* bash-minimal and bash-static are present!

--8<---------------cut here---------------start------------->8---
(use-modules
 (guix build-system gnu)
 (guix gexp)
 ((guix licenses) #:prefix license:)
 (guix packages))
(define src
  (plain-file "demo.c"
              "#include <stdlib.h>
#include <stdio.h>
#include <paths.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
  puts(_PATH_BSHELL);
  size_t buf_len = confstr(_CS_PATH, NULL, 0);
  char* buf = malloc(buf_len);
  if (NULL == buf) {
    return 1;
  };
  confstr(_CS_PATH, buf, buf_len);
  puts(buf);
  fflush(stdout);
  int status = system(\"echo $BASH\");
  fflush(stdout);
  printf(\"status: %i\\n\", status);
  return 0;
}
"))
(package
  (name "libc-system-demo")
  (version "0")
  (source src)
  (build-system gnu-build-system)
  (arguments
   (list
    #:phases
    #~(modify-phases %standard-phases
        (delete 'configure)
        (replace 'build
          (lambda args
            (invoke "gcc" "-o" "demo" #$src)))
        (replace 'check
          (lambda args
            (invoke "./demo")))
        (replace 'install
          (lambda args
            (install-file "demo" (string-append #$output "/bin")))))))
  (home-page "https://issues.guix.gnu.org/57050")
  (synopsis "Some 'sh'-related values from glibc")
  (description "starting phase `check'
/gnu/store/720rj90bch716isd8z7lcwrnvz28ap4y-bash-static-5.1.8/bin/sh
/bin:/usr/bin
/gnu/store/4y5m9lb8k3qkb1y9m02sw9w9a6hacd16-bash-minimal-5.1.8/bin/sh
status: 0
phase `check' succeeded after 0.0 seconds")
  (license license:cc0))
--8<---------------cut here---------------end--------------->8---

AFAICT, Glibc's `confstr` implementation for `_CS_PATH` doesn't have any mechanism for configuring the search path; it simply uses the compile-time version, `CS_PATH`, which is:

    #define	CS_PATH	"/bin:/usr/bin"

More generally, it seems questionable for our glibc to retain a store reference to Bash (let alone two). Wouldn't that prevent creating containers or packs without a shell present?

After I've sent a v3 of this series, I plan to raise these questions on the guix-devel list. Then, once I have a sense of whether Guix would like to support `confstr` with  `_CS_PATH` as a way of finding the shell, I'll propose some changes to Racket upstream.

-Philip