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