casaroli opened a new pull request, #21107: URL: https://github.com/apache/nuttx/pull/21107
## Summary Four functions that NuttX did not have, one commit each (setpgrp() also marks itself in the documentation). Nothing that exists changes. ### setpgrp `setpgrp()` is the XSI function without arguments that makes the caller the leader of its own process group, as `setpgid(0, 0)` does, and returns the process group ID. glibc and musl have it, and programs call it (`login` of util-linux, for example). NuttX had `setpgid()` and `getpgrp()` but not `setpgrp()`. The first commit adds `setpgrp()` to libc over `setpgid()` and `getpgrp()` and declares it in `<unistd.h>`. The second commit marks it as supported in the XSI Multiple Process table of `Documentation/standards/posix.rst`. ### getusershell Programs that check a login shell (`chsh`, for example) read the list of the valid shells with `getusershell()`, `setusershell()` and `endusershell()`. glibc, musl and the BSDs have them in `<unistd.h>`; NuttX did not, and such programs did not compile. `getusershell()` reads `_PATH_SHELLS` (`/etc/shells`, already in `<paths.h>`): on each line, the word that starts at the first `/`; `#` starts a comment, and a line without `/` is skipped. This is what glibc does. If the file cannot be read, the shells are `/bin/sh` and `/bin/csh`, as on other systems. `setusershell()` starts the list again; `endusershell()` closes the file and frees the memory. The functions need stdio streams (`CONFIG_FILE_STREAM`). ### forkpty Terminal programs (`tmux`, for example) start the program of a pseudo terminal with `forkpty()`, which glibc, musl and the BSDs have in `<pty.h>`. NuttX had only `openpty()`. `forkpty()` opens the pair with `openpty()` and forks. The child starts a new session (`setsid()`), makes the slave its controlling terminal (`TIOCSCTTY`) and its standard input, output and error, and closes the master. The parent closes the slave and gets the master. Without `CONFIG_TTY_SIGINT` and `CONFIG_TTY_SIGTSTP` the pty driver has no `TIOCSCTTY`; the child then still gets the slave as its standard streams. `forkpty()` needs `fork()`, so it is declared and built with `CONFIG_PSEUDOTERM` and `CONFIG_ARCH_HAVE_FORK` (kernel builds with address environments on armv7-a, arm64, risc-v, x86_64 and xtensa). Flat and protected builds do not get it. ### getloadavg `getloadavg()` of the BSDs, Linux and macOS was missing, so programs that use it did not link (GNU coreutils `uptime`, for example). NuttX does not keep the load averages, so `getloadavg()` returns -1: the load average is not available. The BSD and glibc functions return the same value when they cannot get the load average (for example a Linux system without `/proc/loadavg`), and programs take it as "unknown". The function is in `libs/libc/stdlib/lib_getloadavg.c` (Make.defs and CMakeLists.txt), declared in `stdlib.h` and listed in `libs/libc/libc.csv`, all under `CONFIG_HAVE_DOUBLE`. ## Impact - setpgrp: A new libc function, the same in flat, protected and kernel builds; nothing per architecture. No Kconfig option (a few bytes, and only when a program calls it). nuttx-apps' `testing/ltp` skips the LTP tests that use `setpgrp`; they can compile now (a later apps change). - getusershell: Three new functions in libc (and in `libc.csv`), in all build modes with `CONFIG_FILE_STREAM`. The functions are not in POSIX, so `Documentation/standards/posix.rst` does not change. A file whose last line has no newline loses that line on master, because `getline()` drops it. A separate PR fixes `getdelim()`. - forkpty: One new function in libc, in kernel builds. No change for other builds. `forkpty()` is not in POSIX, so `Documentation/standards/posix.rst` does not change. - getloadavg: One new function in libc, in all build modes. It always returns -1. A real load average can come later behind the same function. `getloadavg()` is not in POSIX, so `Documentation/standards/posix.rst` does not change. ## Testing The branches were first tested one by one (below). Then all commits of this PR together, on master b79dc18e015: setpgrp.c, usershell.c, forkpty.c (PSEUDOTERM, TTY_SIGINT, TTY_SIGTSTP), loadavg.c on `qemu-armv8a:knsh` (QEMU with HVF) all PASS, and ostest exits with status 0 on `qemu-armv8a:knsh` and `qemu-armv8a:nsh`. ### setpgrp Test program `setpgrp.c` (`self`: `setpgrp()` returns `getpgrp()`, which is `getpid()`; `child`: with `fork()`, a child's `setpgrp()` returns the child's pid), compiled against the export of qemu-armv8a:knsh (kernel build) and run under QEMU (HVF): | | master aeab6fbf989 | this PR | |---|---|---| | `setpgrp` | does not compile (no declaration) | self PASS (5 = 5 = 5), child PASS | ostest exits with status 0 on qemu-armv8a:knsh (kernel) and qemu-armv8a:nsh (flat). Builds, each without new warnings: stm32f4discovery:nsh (flat, Cortex-M4), lm3s6965-ek:qemu-protected (protected, Cortex-M3) and rv-virt:nsh64 (flat, RISC-V). ### getusershell Test program `usershell.c`: - default: without `/etc/shells`: `/bin/sh`, `/bin/csh`, then NULL; `setusershell()` starts again. - file: an `/etc/shells` with comments, blank lines, spaces and a line without `/` (it needs a writable `/etc`). - ends: `endusershell()`, then `getusershell()` gives the first shell again. | Build | Config | master (aeab6fbf989) | this PR | |---|---|---|---| | kernel, arm64 | `qemu-armv8a:knsh` (QEMU, HVF) | does not compile (implicit declarations) | default, ends: PASS; file: SKIP (no writable `/etc`); ostest 0 | | flat, arm64 | `qemu-armv8a:nsh` (QEMU, HVF; the test as a builtin app; a tmpfs mounted on `/etc`) | | default, file, ends: PASS (1); ostest 0 | (1) With a test file whose last line ends with a newline. With the last line `\t/bin/zsh` without a newline, the file case fails: `getline()` on master drops that line (see Impact). Builds (make): `mps2-an500:knsh` (protected, armv7-m), `rv-virt:knsh64` (kernel, risc-v), `nucleo-f072rb:nsh` (flat, armv6-m, without `CONFIG_FILE_STREAM`: the file is not built): OK. CMake: `qemu-armv8a:nsh` builds the new file: OK. ### forkpty Test program `forkpty.c` (needs `CONFIG_PSEUDOTERM` and `fork()`): - name: the parent gets a master and the name of the slave. - child: in the child the slave is stdin, stdout and stderr, and the child leads a new session. - winsize: the slave has the window size given. - output: what the child writes comes out of the master. - wait: the child exits with 0 (`waitpid()`). The pty driver on master has no `TIOCGWINSZ`/`TIOCSWINSZ`, so `openpty()` cannot give the slave a window size, and the test skips the winsize case. | Build | Config | master (aeab6fbf989) | this PR | |---|---|---|---| | kernel, arm64 | `qemu-armv8a:knsh` + `PSEUDOTERM`, `PSEUDOTERM_SUSV1`, `TTY_SIGINT`, `TTY_SIGTSTP` (QEMU, HVF) | does not compile (no `forkpty()`) | name, child, output, wait: PASS; winsize: SKIP; ostest 0 (knsh and nsh) | | kernel, arm64 | `qemu-armv8a:knsh` + `PSEUDOTERM`, without `TTY_SIGINT` and `TTY_SIGTSTP` | | name, child, output, wait: PASS; winsize: SKIP; ostest 0 (knsh and nsh) | Builds with `PSEUDOTERM` (make): `rv-virt:knsh64` (kernel, risc-v) and `qemu-armv7a:knsh` (kernel, armv7-a) build `lib_forkpty.c`; `mps2-an500:knsh` (protected) and `qemu-armv8a:nsh` (flat) build without it: OK. CMake: `qemu-armv8a:knsh` + `PSEUDOTERM` builds the new file: OK. ### getloadavg Test program `loadavg.c`: `getloadavg(a, 3)` returns -1 or 1 to 3 values that are not negative; `getloadavg(a, 0)` does not write `a[]`. | Build | Config | master (aeab6fbf989) | this PR | |---|---|---|---| | kernel, arm64 | `qemu-armv8a:knsh` (QEMU, HVF) | does not compile (no `getloadavg()`) | load (-1), load0: PASS; ostest 0 | | flat, arm64 | `qemu-armv8a:nsh` (QEMU, HVF; the test as a builtin app) | | load (-1), load0: PASS; ostest 0 | Builds (make): `mps2-an500:knsh` (protected, armv7-m), `rv-virt:knsh64` (kernel, risc-v), `nucleo-f072rb:nsh` (flat, armv6-m): OK. CMake: `qemu-armv8a:nsh` builds the new file: OK. `tools/checkpatch.sh -c -u -m -g` passes. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
