Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH] make clone try to acquire a controlling tty
- X-seq: zsh-workers 18888
- From: Philippe Troin <phil@xxxxxxxx>
- To: zsh-workers@xxxxxxxxxx
- Subject: [PATCH] make clone try to acquire a controlling tty
- Date: 22 Jul 2003 18:12:10 -0700
- Mail-copies-to: nobody
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
- Sender: Philippe Troin <phil@xxxxxxxx>
The enclosed patch makes clone try to acquire a controlling tty. This
makes clone more useful because it enables job control in cloned
sessions.
The patch applies on current cvs head.
Notes about the patch:
- We don't call TIOCNOTTY if HAVE_SETSID: setsid() automatically
detaches from the current controlling tty.
- The logic for dup'ing the newly opened tty is changed for a better
one.
- Once the dup'ing of the newly opened tty is done, we try to acquire
the newly opened tty as a controlling tty. We print a message if
this fails.
- We have to reset mypgrp to zero so that init_io() can get its job
done correctly.
Notes about controlling ttys:
- Due to the way job control works, it is impossible for a process to
acquire a controlling tty if another process already acquired it
since:
* POSIX mandates that if a session leader dies, all the processes
in the session loose their controlling tty.
* Most terminal emulator programs (including screen, but see note
about screen) acquire a controlling tty before exec'ing their
target process.
- This means that the following won't work (the cloned zsh will run,
but will not have a controlling tty (-> no job control)):
* Open a new xterm.
* Run tty in xterm.
* Run in the xterm:
exec zsh -c 'trap "" INT QUIT TSTP; while :; do sleep 100000; done'
* Do a clone in the xterm's tty.
- However this will work (the cloned zsh will have a controlling tty
and job control will work):
* clone /dev/tty<n> or clone /dev/vc/<n> on linux
* zsh will be able to open cloned shells with job control in a
screen session as long as the screen "setsid off" command is in
effect in the screen:
+ Run screen. You're now in screen #0.
+ Enter "setsid off": this is done by typing in:
^A : setsid off <RETURN>
+ Create a new screen. You're now in screen #1.
+ The shell in screen 1 has job control disabled (it has no
controlling tty).
+ In screen #1, run:
tty && exec sleep 1000000
+ Switch back to screen #0: ^A 0
+ Run clone on the tty that was printed in screen #1.
+ Switch back to screen #1: ^A 1
+ You now have a cloned zsh with job control active.
Tested to work OK on Linux (with TIOCNOTTY/TIOCSCTTY controlling tty
acquiring method) and Solaris (with SvR4's O_NOCTTY controlling tty
acquiring method).
Phil.
Changelog entry:
2003-07-22 Philippe Troin <phil@xxxxxxxx>
* Src/Modules/clone.c (bin_clone): Try to acquire a controlling
tty when possible. Report failures. Cleanup.
Index: clone.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/clone.c,v
retrieving revision 1.3
diff -b -u -r1.3 clone.c
--- clone.c 27 Aug 2002 21:10:34 -0000 1.3
+++ clone.c 23 Jul 2003 01:07:48 -0000
@@ -43,7 +43,7 @@
static int
bin_clone(char *nam, char **args, Options ops, int func)
{
- int ttyfd, pid;
+ int ttyfd, pid, cttyfd;
unmetafy(*args, NULL);
ttyfd = open(*args, O_RDWR|O_NOCTTY);
@@ -57,29 +57,42 @@
ppid = getppid();
mypid = getpid();
#ifdef HAVE_SETSID
- if (setsid() != mypid) {
+ if (setsid() != mypid)
zwarnnam(nam, "failed to create new session: %e", NULL, errno);
-#endif
-#ifdef TIOCNOTTY
+#elif defined(TIOCNOTTY)
if (ioctl(SHTTY, TIOCNOTTY, 0))
- zwarnnam(nam, "%e", NULL, errno);
+ zwarnnam(*args, "%e", NULL, errno);
setpgrp(0L, mypid);
#endif
-#ifdef HAVE_SETSID
- }
-#endif
- if (ttyfd) {
- close(0);
- dup(ttyfd);
- } else
- ttyfd = -1;
- close(1);
- close(2);
- dup(0);
- dup(0);
+ dup2(ttyfd,0);
+ dup2(ttyfd,1);
+ dup2(ttyfd,2);
+ if (ttyfd > 2)
+ close(ttyfd);
closem(0);
close(coprocin);
close(coprocout);
+ /* Acquire a controlling terminal */
+ cttyfd = open(*args, O_RDWR);
+ if (cttyfd == -1)
+ zwarnnam(nam, "%e", NULL, errno);
+ else {
+#ifdef TIOCSCTTY
+ ioctl(cttyfd, TIOCSCTTY, 0);
+#endif
+ close(cttyfd);
+ }
+ /* check if we acquired the tty successfully */
+ cttyfd = open("/dev/tty", O_RDWR);
+ if (cttyfd == -1)
+ zwarnnam(nam, "could not make %s my controlling tty, job control "
+ "disabled", *args, 0);
+ else
+ close(cttyfd);
+
+ /* Clear mygrp so that acquire_pgrp() gets the new process group.
+ * (acquire_pgrp() is called from init_io()) */
+ mypgrp = 0;
init_io();
setsparam("TTY", ztrdup(ttystrname));
}
Messages sorted by:
Reverse Date,
Date,
Thread,
Author