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]

Reply via email to