Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

zpty



Hi,

I'm new to this mailing list.  I've been using zsh for a while.
Recently I found out that zpty actually does not work on my Linux
system.

$ zmodload zsh/zpty
$ zpty date date
zpty: can't open pseudo terminal: bad file descriptor
$

As I digged into the code, I saw those old-style /dev/ptyxx heuristics
which may not work on some modern Linux systems because the location is
changed to /dev/pts/xx.  Meanwhile there's an API in glibc for dealing
with pseudo terminals.  So I reworked that code a bit.

Now it works fine for me.  Of course it's not portable, it works with
glibc only.  But glibc is one of the most popular libc implementation,
and it works not on Linux systems only.  So please consider whether this
can be useful somehow.

Thanks,
Alexey Tourbin
ALT Linux Team
--- zsh-4.1.1~/Src/Modules/zpty.c	2003-02-13 14:07:02 +0300
+++ zsh-4.1.1/Src/Modules/zpty.c	2003-08-23 16:21:50 +0400
@@ -27,8 +27,14 @@
  *
  */
 
+/* getpt(3) requires _GNU_SOURCE */
+#define _GNU_SOURCE
 #include "zpty.mdh"
 #include "zpty.pro"
+#include <stdlib.h>
+#include <stropts.h>
+#include <errno.h>
+#include <error.h>
 
 /* The number of bytes we normally read when given no pattern and the
  * upper bound on the number of bytes we read (even if we are give a
@@ -154,6 +160,7 @@ getptycmd(char *name)
     return NULL;
 }
 
+#if 0
 /**** maybe we should use configure here */
 /**** and we certainly need more/better #if tests */
 
@@ -265,9 +272,11 @@ get_pty(int master, int *retfd)
     close(mfd);
 
     return 1;
+
 }
 
 #endif /* __SVR4 */
+#endif /* 0 */
 
 static int
 newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
@@ -282,10 +291,20 @@ newptycmd(char *nam, char *pname, char *
 	return 1;
     }
 
-    if (get_pty(1, &master)) {
-	zwarnnam(nam, "can't open pseudo terminal: %e", NULL, errno);
-	return 1;
+    master = getpt();
+    if (master < 0) {
+	    zwarnnam(nam, "can't open pseudo terminal: %e", NULL, errno);
+	    return 1;
     }
+    if (grantpt(master) < 0) {
+	    zwarnnam(nam, "grantpt: %e", NULL, errno);
+	    return 1;
+    }
+    if (unlockpt(master) < 0) {
+	    zwarnnam(nam, "unlockpt: %e", NULL, errno);
+	    return 1;
+    }
+
     if ((pid = fork()) == -1) {
 	zwarnnam(nam, "can't create pty command %s: %e", pname, errno);
 	close(master);
@@ -310,8 +329,21 @@ newptycmd(char *nam, char *pname, char *
 	}
 #endif
 
-	if (get_pty(0, &slave))
-	    exit(1);
+	{
+		const char *name = ptsname(master);
+		if (!name)
+			exit(1);
+		slave = open(name, O_RDWR|O_NOCTTY);
+		if (slave < 0)
+			exit(1);
+		if (isastream(slave))
+		{
+			if (ioctl(slave, I_PUSH, "ptem") < 0
+			|| ioctl(slave, I_PUSH, "ldterm") < 0)
+				exit(1);
+		}
+	}
+		
 #ifdef TIOCGWINSZ
 	/* Set the window size before associating with the terminal *
 	 * so that we don't get hit with a SIGWINCH.  I'm paranoid. */
@@ -347,10 +379,6 @@ newptycmd(char *nam, char *pname, char *
 	ioctl(slave, TIOCSCTTY, 0);
 #endif
 
-	close(0);
-	close(1);
-	close(2);
-
 	dup2(slave, 0);
 	dup2(slave, 1);
 	dup2(slave, 2);

Attachment: pgpgU6lmYwHTp.pgp
Description: PGP signature



Messages sorted by: Reverse Date, Date, Thread, Author