emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 4e59830bc0 2/2: Add STREAM argument to 'process-tty-name'


From: Jim Porter
Subject: master 4e59830bc0 2/2: Add STREAM argument to 'process-tty-name'
Date: Fri, 5 Aug 2022 21:06:07 -0400 (EDT)

branch: master
commit 4e59830bc0ab17cdbd85748b133c97837bed99e3
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>

    Add STREAM argument to 'process-tty-name'
    
    * src/process.c (process-tty-name): Add STREAM argument.
    
    * lisp/eshell/esh-io.el (eshell-close-target): Only call
    'process-send-eof' once if the process's stdin is a pipe.
    
    * test/src/process-tests.el (make-process/test-connection-type): Check
    behavior of 'process-tty-name'.
    
    * doc/lispref/processes.texi (Process Information): Document the new
    argument.
    
    * etc/NEWS: Announce this change.
---
 doc/lispref/processes.texi | 21 +++++++++++++++------
 etc/NEWS                   |  5 ++++-
 lisp/eshell/esh-io.el      | 27 +++++++++++++++------------
 src/process.c              | 25 +++++++++++++++++++++----
 test/src/process-tests.el  |  3 +++
 5 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index e253ab9de0..382053ab24 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -1243,15 +1243,24 @@ that are already closed, the value is either 0 or 256, 
depending on
 whether the connection was closed normally or abnormally.
 @end defun
 
-@defun process-tty-name process
+@defun process-tty-name process &optional stream
 This function returns the terminal name that @var{process} is using for
 its communication with Emacs---or @code{nil} if it is using pipes
 instead of a pty (see @code{process-connection-type} in
-@ref{Asynchronous Processes}).  If @var{process} represents a program
-running on a remote host, the terminal name used by that program on
-the remote host is provided as process property @code{remote-tty}.  If
-@var{process} represents a network, serial, or pipe connection, the
-value is @code{nil}.
+@ref{Asynchronous Processes}).  By default, this function returns the
+terminal name if any of @var{process}'s standard streams use a
+terminal.  If @var{stream} is one of @code{stdin}, @code{stdout}, or
+@code{stderr}, this function returns the terminal name (or @code{nil},
+as above) that @var{process} uses for that stream specifically.  You
+can use this to determine whether a particular stream uses a pipe or a
+pty.
+
+If @var{process} represents a program running on a remote host, this
+function returns the @emph{local} terminal name that communicates with
+@var{process}; you can get the terminal name used by that program on
+the remote host with the process property @code{remote-tty}.  If
+@var{process} represents a network, serial, or pipe connection, this
+function always returns @code{nil}.
 @end defun
 
 @defun process-coding-system process
diff --git a/etc/NEWS b/etc/NEWS
index 8a9744ab3e..bca3c4da78 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3333,7 +3333,10 @@ invocation.  Such shells are POSIX conformant by default.
 ** 'make-process' can set connection type independently for input and output.
 When calling 'make-process', communication via pty can be enabled
 selectively for just input or output by passing a cons cell for
-':connection-type', e.g. '(pipe . pty)'.
+':connection-type', e.g. '(pipe . pty)'.  When examining a process
+later, you can determine whether a particular stream for a process
+uses a pty by passing one of 'stdin', 'stdout', or 'stderr' as the
+second argument to 'process-tty-name'.
 
 +++
 ** 'signal-process' now consults the list 'signal-process-functions'.
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index c035890ddf..68e52a2c9c 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -276,18 +276,21 @@ STATUS should be non-nil on successful termination of the 
output."
    ;; If we're redirecting to a process (via a pipe, or process
    ;; redirection), send it EOF so that it knows we're finished.
    ((eshell-processp target)
-    ;; According to POSIX.1-2017, section 11.1.9, sending EOF causes
-    ;; all bytes waiting to be read to be sent to the process
-    ;; immediately.  Thus, if there are any bytes waiting, we need to
-    ;; send EOF twice: once to flush the buffer, and a second time to
-    ;; cause the next read() to return a size of 0, indicating
-    ;; end-of-file to the reading process.  However, some platforms
-    ;; (e.g. Solaris) actually require sending a *third* EOF.  Since
-    ;; sending extra EOFs while the process is running shouldn't break
-    ;; anything, we'll just send the maximum we'd ever need.  See
-    ;; bug#56025 for further details.
-    (let ((i 0))
-      (while (and (<= (cl-incf i) 3)
+    ;; According to POSIX.1-2017, section 11.1.9, when communicating
+    ;; via terminal, sending EOF causes all bytes waiting to be read
+    ;; to be sent to the process immediately.  Thus, if there are any
+    ;; bytes waiting, we need to send EOF twice: once to flush the
+    ;; buffer, and a second time to cause the next read() to return a
+    ;; size of 0, indicating end-of-file to the reading process.
+    ;; However, some platforms (e.g. Solaris) actually require sending
+    ;; a *third* EOF.  Since sending extra EOFs while the process is
+    ;; running are a no-op, we'll just send the maximum we'd ever
+    ;; need.  See bug#56025 for further details.
+    (let ((i 0)
+          ;; Only call `process-send-eof' once if communicating via a
+          ;; pipe (in truth, this just closes the pipe).
+          (max-attempts (if (process-tty-name target 'stdin) 3 1)))
+      (while (and (<= (cl-incf i) max-attempts)
                   (eq (process-status target) 'run))
         (process-send-eof target))))
 
diff --git a/src/process.c b/src/process.c
index 68dbd8b68b..23479c0619 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1243,14 +1243,31 @@ or t (process is stopped).  */)
   return XPROCESS (process)->command;
 }
 
-DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 1, 0,
+DEFUN ("process-tty-name", Fprocess_tty_name, Sprocess_tty_name, 1, 2, 0,
        doc: /* Return the name of the terminal PROCESS uses, or nil if none.
 This is the terminal that the process itself reads and writes on,
-not the name of the pty that Emacs uses to talk with that terminal.  */)
-  (register Lisp_Object process)
+not the name of the pty that Emacs uses to talk with that terminal.
+
+If STREAM is nil, return the terminal name if any of PROCESS's
+standard streams use a terminal for communication.  If STREAM is one
+of `stdin', `stdout', or `stderr', return the name of the terminal
+PROCESS uses for that stream specifically, or nil if that stream
+communicates via a pipe.  */)
+  (register Lisp_Object process, Lisp_Object stream)
 {
   CHECK_PROCESS (process);
-  return XPROCESS (process)->tty_name;
+  register struct Lisp_Process *p = XPROCESS (process);
+
+  if (NILP (stream))
+    return p->tty_name;
+  else if (EQ (stream, Qstdin))
+    return p->pty_in ? p->tty_name : Qnil;
+  else if (EQ (stream, Qstdout))
+    return p->pty_out ? p->tty_name : Qnil;
+  else if (EQ (stream, Qstderr))
+    return p->pty_out && NILP (p->stderrproc) ? p->tty_name : Qnil;
+  else
+    signal_error ("Unknown stream", stream);
 }
 
 static void
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index b801563feb..db8a504478 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -294,6 +294,9 @@ should be a TTY, respectively."
                                        "if [ -t 2 ]; then echo stderr; fi"))
                 :buffer stdout-buffer
                 args)))
+    (should (eq (and (process-tty-name proc 'stdin) t) (nth 0 ttys)))
+    (should (eq (and (process-tty-name proc 'stdout) t) (nth 1 ttys)))
+    (should (eq (and (process-tty-name proc 'stderr) t) (nth 2 ttys)))
     (process-test-wait-for-sentinel proc 0)
     (should (equal (with-current-buffer stdout-buffer (buffer-string))
                    expected-output))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]