aboutsummaryrefslogtreecommitdiffstats
path: root/src/callproc.c
diff options
context:
space:
mode:
authorJim Porter2022-07-17 20:25:00 -0700
committerJim Porter2022-08-05 17:58:54 -0700
commitd7b89ea4077d4fe677ba0577245328819ee79cdc (patch)
treed4e499042bdf2f301be7f2d7ec05f0d1bfd8d44b /src/callproc.c
parentb70369c557efed3dcd86dc64a2e73e3480dea6af (diff)
downloademacs-d7b89ea4077d4fe677ba0577245328819ee79cdc.tar.gz
emacs-d7b89ea4077d4fe677ba0577245328819ee79cdc.zip
Allow creating processes where only one of stdin or stdout is a PTY
* src/lisp.h (emacs_spawn): * src/callproc.c (emacs_spawn): Add PTY_IN and PTY_OUT arguments to specify which streams should be set up as a PTY. (call_process): Adjust call to 'emacs_spawn'. * src/process.h (Lisp_Process): Replace 'pty_flag' with 'pty_in' and 'pty_out'. * src/process.c (is_pty_from_symbol): New function. (make-process): Allow :connection-type to be a cons cell, and allow using a stderr process with a PTY for stdin/stdout. (create_process): Handle creating a process where only one of stdin or stdout is a PTY. * lisp/eshell/esh-proc.el (eshell-needs-pipe, eshell-needs-pipe-p): Remove. (eshell-gather-process-output): Use 'make-process' and set ':connection-type' as needed by the value of 'eshell-in-pipeline-p'. * lisp/net/tramp.el (tramp-handle-make-process): * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't signal an error when ':connection-type' is a cons cell. * test/src/process-tests.el (process-test-sentinel-wait-function-working-p): Allow passing PROC in, and rework into... (process-test-wait-for-sentinel): ... this. (process-test-sentinel-accept-process-output) (process-test-sentinel-sit-for, process-test-quoted-batfile) (process-test-stderr-filter): Use 'process-test-wait-for-sentinel'. (make/process/test-connection-type): New function. (make-process/connection-type/pty, make-process/connection-type/pty-2) (make-process/connection-type/pipe) (make-process/connection-type/pipe-2) (make-process/connection-type/in-pty) (make-process/connection-type/out-pty) (make-process/connection-type/pty-with-stderr-buffer) (make-process/connection-type/out-pty-with-stderr-buffer): New tests. * test/lisp/eshell/esh-proc-tests.el (esh-proc-test--detect-pty-cmd): New variable. (esh-proc-test/pipeline-connection-type/no-pipeline) (esh-proc-test/pipeline-connection-type/first) (esh-proc-test/pipeline-connection-type/middle) (esh-proc-test/pipeline-connection-type/last): New tests. * doc/lispref/processes.texi (Asynchronous Processes): Document new ':connection-type' behavior. (Output from Processes): Remove caveat about ':stderr' forcing 'make-process' to use pipes. * etc/NEWS: Announce this change (bug#56025).
Diffstat (limited to 'src/callproc.c')
-rw-r--r--src/callproc.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/src/callproc.c b/src/callproc.c
index dd162f36a6c..aec0a2f5a58 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -650,7 +650,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
650 650
651 child_errno 651 child_errno
652 = emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env, 652 = emacs_spawn (&pid, filefd, fd_output, fd_error, new_argv, env,
653 SSDATA (current_dir), NULL, &oldset); 653 SSDATA (current_dir), NULL, false, false, &oldset);
654 eassert ((child_errno == 0) == (0 < pid)); 654 eassert ((child_errno == 0) == (0 < pid));
655 655
656 if (pid > 0) 656 if (pid > 0)
@@ -1412,14 +1412,15 @@ emacs_posix_spawn_init_attributes (posix_spawnattr_t *attributes,
1412int 1412int
1413emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err, 1413emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1414 char **argv, char **envp, const char *cwd, 1414 char **argv, char **envp, const char *cwd,
1415 const char *pty, const sigset_t *oldset) 1415 const char *pty_name, bool pty_in, bool pty_out,
1416 const sigset_t *oldset)
1416{ 1417{
1417#if USABLE_POSIX_SPAWN 1418#if USABLE_POSIX_SPAWN
1418 /* Prefer the simpler `posix_spawn' if available. `posix_spawn' 1419 /* Prefer the simpler `posix_spawn' if available. `posix_spawn'
1419 doesn't yet support setting up pseudoterminals, so we fall back 1420 doesn't yet support setting up pseudoterminals, so we fall back
1420 to `vfork' if we're supposed to use a pseudoterminal. */ 1421 to `vfork' if we're supposed to use a pseudoterminal. */
1421 1422
1422 bool use_posix_spawn = pty == NULL; 1423 bool use_posix_spawn = pty_name == NULL;
1423 1424
1424 posix_spawn_file_actions_t actions; 1425 posix_spawn_file_actions_t actions;
1425 posix_spawnattr_t attributes; 1426 posix_spawnattr_t attributes;
@@ -1473,7 +1474,9 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1473 /* vfork, and prevent local vars from being clobbered by the vfork. */ 1474 /* vfork, and prevent local vars from being clobbered by the vfork. */
1474 pid_t *volatile newpid_volatile = newpid; 1475 pid_t *volatile newpid_volatile = newpid;
1475 const char *volatile cwd_volatile = cwd; 1476 const char *volatile cwd_volatile = cwd;
1476 const char *volatile pty_volatile = pty; 1477 const char *volatile ptyname_volatile = pty_name;
1478 bool volatile ptyin_volatile = pty_in;
1479 bool volatile ptyout_volatile = pty_out;
1477 char **volatile argv_volatile = argv; 1480 char **volatile argv_volatile = argv;
1478 int volatile stdin_volatile = std_in; 1481 int volatile stdin_volatile = std_in;
1479 int volatile stdout_volatile = std_out; 1482 int volatile stdout_volatile = std_out;
@@ -1495,7 +1498,9 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1495 1498
1496 newpid = newpid_volatile; 1499 newpid = newpid_volatile;
1497 cwd = cwd_volatile; 1500 cwd = cwd_volatile;
1498 pty = pty_volatile; 1501 pty_name = ptyname_volatile;
1502 pty_in = ptyin_volatile;
1503 pty_out = ptyout_volatile;
1499 argv = argv_volatile; 1504 argv = argv_volatile;
1500 std_in = stdin_volatile; 1505 std_in = stdin_volatile;
1501 std_out = stdout_volatile; 1506 std_out = stdout_volatile;
@@ -1506,13 +1511,12 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1506 if (pid == 0) 1511 if (pid == 0)
1507#endif /* not WINDOWSNT */ 1512#endif /* not WINDOWSNT */
1508 { 1513 {
1509 bool pty_flag = pty != NULL;
1510 /* Make the pty be the controlling terminal of the process. */ 1514 /* Make the pty be the controlling terminal of the process. */
1511#ifdef HAVE_PTYS 1515#ifdef HAVE_PTYS
1512 dissociate_controlling_tty (); 1516 dissociate_controlling_tty ();
1513 1517
1514 /* Make the pty's terminal the controlling terminal. */ 1518 /* Make the pty's terminal the controlling terminal. */
1515 if (pty_flag && std_in >= 0) 1519 if (pty_in && std_in >= 0)
1516 { 1520 {
1517#ifdef TIOCSCTTY 1521#ifdef TIOCSCTTY
1518 /* We ignore the return value 1522 /* We ignore the return value
@@ -1521,7 +1525,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1521#endif 1525#endif
1522 } 1526 }
1523#if defined (LDISC1) 1527#if defined (LDISC1)
1524 if (pty_flag && std_in >= 0) 1528 if (pty_in && std_in >= 0)
1525 { 1529 {
1526 struct termios t; 1530 struct termios t;
1527 tcgetattr (std_in, &t); 1531 tcgetattr (std_in, &t);
@@ -1531,7 +1535,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1531 } 1535 }
1532#else 1536#else
1533#if defined (NTTYDISC) && defined (TIOCSETD) 1537#if defined (NTTYDISC) && defined (TIOCSETD)
1534 if (pty_flag && std_in >= 0) 1538 if (pty_in && std_in >= 0)
1535 { 1539 {
1536 /* Use new line discipline. */ 1540 /* Use new line discipline. */
1537 int ldisc = NTTYDISC; 1541 int ldisc = NTTYDISC;
@@ -1548,18 +1552,21 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1548 both TIOCSCTTY is defined. */ 1552 both TIOCSCTTY is defined. */
1549 /* Now close the pty (if we had it open) and reopen it. 1553 /* Now close the pty (if we had it open) and reopen it.
1550 This makes the pty the controlling terminal of the subprocess. */ 1554 This makes the pty the controlling terminal of the subprocess. */
1551 if (pty_flag) 1555 if (pty_name)
1552 { 1556 {
1553 1557
1554 /* I wonder if emacs_close (emacs_open (pty, ...)) 1558 /* I wonder if emacs_close (emacs_open (pty, ...))
1555 would work? */ 1559 would work? */
1556 if (std_in >= 0) 1560 if (pty_in && std_in >= 0)
1557 emacs_close (std_in); 1561 emacs_close (std_in);
1558 std_out = std_in = emacs_open_noquit (pty, O_RDWR, 0); 1562 int ptyfd = emacs_open_noquit (pty_name, O_RDWR, 0);
1559 1563 if (pty_in)
1564 std_in = ptyfd;
1565 if (pty_out)
1566 std_out = ptyfd;
1560 if (std_in < 0) 1567 if (std_in < 0)
1561 { 1568 {
1562 emacs_perror (pty); 1569 emacs_perror (pty_name);
1563 _exit (EXIT_CANCELED); 1570 _exit (EXIT_CANCELED);
1564 } 1571 }
1565 1572
@@ -1599,7 +1606,7 @@ emacs_spawn (pid_t *newpid, int std_in, int std_out, int std_err,
1599 /* Stop blocking SIGCHLD in the child. */ 1606 /* Stop blocking SIGCHLD in the child. */
1600 unblock_child_signal (oldset); 1607 unblock_child_signal (oldset);
1601 1608
1602 if (pty_flag) 1609 if (pty_out)
1603 child_setup_tty (std_out); 1610 child_setup_tty (std_out);
1604#endif 1611#endif
1605 1612