Welcome to little lamb

Code » limb » commit bc15470

Add term_ensurefg() to ensure current process is..

author Olivier Brunel
2023-04-23 08:46:29 UTC
committer Olivier Brunel
2023-05-20 18:06:37 UTC
parent a688eae8f3121d037b522d25f579b0bd7892be5f

Add term_ensurefg() to ensure current process is..

..in the foreground job of ctty.

Also call term_ensurefg() in ask_password(), that way before asking for
the password we make sure we can actually read it.

src/doc/term.h.0.md +3 -0
src/doc/term.h/ask_password.3.md +9 -6
src/doc/term.h/term_ensurefg.3.md +36 -0
src/liblimb/include/limb/term.h +1 -0
src/liblimb/term.h/ask_password.c +3 -0
src/liblimb/term.h/term_ensurefg.c +20 -0

diff --git a/src/doc/term.h.0.md b/src/doc/term.h.0.md
index 7e3e94e..0ed77f8 100644
--- a/src/doc/term.h.0.md
+++ b/src/doc/term.h.0.md
@@ -24,3 +24,6 @@ The following functions are defined :
 
 : [term_echo](3)
 :: To enable/disable echoing of input characters from a terminal.
+
+: [term_ensurefg](3)
+:: To ensure current process is in the foreground job if needed.
diff --git a/src/doc/term.h/ask_password.3.md b/src/doc/term.h/ask_password.3.md
index 0bbeb3f..e7718c4 100644
--- a/src/doc/term.h/ask_password.3.md
+++ b/src/doc/term.h/ask_password.3.md
@@ -18,8 +18,11 @@ ssize_t ask_password(char *<em>dst</em>, size_t <em>dlen</em>, const char *<em>p
 The `ask_password`() function will read data from *stdin* up to a newline (`\n`)
 and store it into the memory area pointed by `dst`, up to `dlen` bytes.
 
-First, it will ensure input character echoing is disabled for *stdin*, then drop
-any data that might remain in `buffer_0`.
+First, it will ensure that the current process is in the foreground process
+group of its controlling terminal /if/ said terminal is referred to by *stdin*,
+then make sure input character echoing is disabled for *stdin* for the duration
+on the password input, and finally drop any data that might remain in
+`buffer_0`.
 
 If `prompt` is not NULL, it will be written to *stderr* before attempting to
 read from *stdin*, unless it begins with `>` in which case it is written (past
@@ -54,15 +57,15 @@ Otherwise it returns -1 and sets `errno` to indicate the error.
 # ERRORS
 
 The `ask_password`() function may fail and set `errno` for any of the errors
-described for [term_echo](3) and [buffer_getuptoc](3), with the following
-exceptions :
+described for [term_ensurefg](3), [term_echo](3) and [buffer_getuptoc](3), with
+the following exceptions :
 
 : *EINVAL*
 :: The argument for [buffer_getuptoc](3) cannot be invalid.
 
 : *ENOTTY*
-:: If [term_echo](3) fails with *ENOTTY* when disabling input character echoing,
-:: `ask_password`() simply ignores it and attempts to proceed as normal.
+:: If [term_ensurefg](3) or [term_echo](3) fails with *ENOTTY* `ask_password`()
+:: simply ignores it and attempts to proceed as normal.
 
 : *EPIPE*
 :: If [buffer_getuptoc](3) fails with *EPIPE* it means end of file was reached,
diff --git a/src/doc/term.h/term_ensurefg.3.md b/src/doc/term.h/term_ensurefg.3.md
new file mode 100644
index 0000000..4cb0160
--- /dev/null
+++ b/src/doc/term.h/term_ensurefg.3.md
@@ -0,0 +1,36 @@
+% limb manual
+% term_ensurefg(3)
+
+# NAME
+
+term\_ensurefg - ensure current process is in the foreground job if needed
+
+# SYNOPSIS
+
+    #include <limb/term.h>
+
+```pre hl
+int term_ensurefg(int <em>fd</em>)
+```
+
+# DESCRIPTION
+
+The `term_ensurefg`() function will make sure the current process is in the
+foreground process group of its controlling terminal, which must be referred to
+by `fd`.
+
+! NOTE:
+! To do so, the *SIGTTOU* signal will be ignored during the execution of the
+! function (so it doesn't get send and blocks the process whilst setting the
+! terminal foreground process group) then restored to its original handling
+! state.
+
+# RETURN VALUE
+
+The `term_ensurefg`() function returns 1 on success, otherwise it returns 0 and
+sets `errno` to indicate the error.
+
+# ERRORS
+
+The `term_ensurefg`() function may fail and set `errno` for any of the errors
+described for [tcsetpgrp](3) except *EINVAL* and *EPERM*.
diff --git a/src/liblimb/include/limb/term.h b/src/liblimb/include/limb/term.h
index f948d93..4b1be45 100644
--- a/src/liblimb/include/limb/term.h
+++ b/src/liblimb/include/limb/term.h
@@ -6,6 +6,7 @@
 
 #include <sys/types.h> /* {,s}size_t */
 
+extern int term_ensurefg(int fd);
 extern int term_echo(int fd, int want);
 extern ssize_t ask_password(char *dst, size_t dlen, const char *prompt);
 
diff --git a/src/liblimb/term.h/ask_password.c b/src/liblimb/term.h/ask_password.c
index 8a2afe6..fa2fbd2 100644
--- a/src/liblimb/term.h/ask_password.c
+++ b/src/liblimb/term.h/ask_password.c
@@ -9,6 +9,9 @@
 ssize_t
 ask_password(char *dst, size_t dlen, const char *prompt)
 {
+    if (!term_ensurefg(buffer_fd(buffer_0)) && errno != ENOTTY)
+        return -1;
+
     int echo = term_echo(buffer_fd(buffer_0), 0);
     if (echo < 0) {
         if (errno != ENOTTY) return -1;
diff --git a/src/liblimb/term.h/term_ensurefg.c b/src/liblimb/term.h/term_ensurefg.c
new file mode 100644
index 0000000..b59dca8
--- /dev/null
+++ b/src/liblimb/term.h/term_ensurefg.c
@@ -0,0 +1,20 @@
+/* This file is part of limb                           https://lila.oss/limb
+ * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <signal.h>
+#include <unistd.h>
+#include <limb/term.h>
+
+int
+term_ensurefg(int fd)
+{
+    struct sigaction oact;
+    struct sigaction act = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART };
+    int r;
+
+    sigaction(SIGTTOU, &act, &oact);
+    r = tcsetpgrp(fd, getpgid(0));
+    sigaction(SIGTTOU, &oact, NULL);
+
+    return !r;
+}