mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-26 16:40:29 +01:00
zsh-workers/9390
This commit is contained in:
parent
74be4d9a37
commit
e7de8c77d4
9 changed files with 642 additions and 25 deletions
|
|
@ -60,7 +60,7 @@ Zsh/mod_computil.yo \
|
||||||
Zsh/mod_deltochar.yo Zsh/mod_example.yo Zsh/mod_files.yo \
|
Zsh/mod_deltochar.yo Zsh/mod_example.yo Zsh/mod_files.yo \
|
||||||
Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_parameter.yo Zsh/mod_sched.yo \
|
Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_parameter.yo Zsh/mod_sched.yo \
|
||||||
Zsh/mod_stat.yo Zsh/mod_zftp.yo Zsh/mod_zle.yo Zsh/mod_zleparameter.yo \
|
Zsh/mod_stat.yo Zsh/mod_zftp.yo Zsh/mod_zle.yo Zsh/mod_zleparameter.yo \
|
||||||
Zsh/mod_zutil.yo Zsh/mod_zprof.yo
|
Zsh/mod_zutil.yo Zsh/mod_zprof.yo Zsh/mod_zpty.yo
|
||||||
|
|
||||||
YODLSRC = zmacros.yo zman.yo ztexi.yo Zsh/arith.yo Zsh/builtins.yo \
|
YODLSRC = zmacros.yo zman.yo ztexi.yo Zsh/arith.yo Zsh/builtins.yo \
|
||||||
Zsh/compat.yo Zsh/compctl.yo Zsh/compsys.yo Zsh/compwid.yo Zsh/cond.yo \
|
Zsh/compat.yo Zsh/compctl.yo Zsh/compsys.yo Zsh/compwid.yo Zsh/cond.yo \
|
||||||
|
|
|
||||||
40
Doc/Zsh/mod_zpty.yo
Normal file
40
Doc/Zsh/mod_zpty.yo
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
COMMENT(!MOD!zsh/zpty
|
||||||
|
A builtin for starting a command in a pseudo-terminal.
|
||||||
|
!MOD!)
|
||||||
|
The tt(zsh/zpty) module offers one builtin:
|
||||||
|
|
||||||
|
startitem()
|
||||||
|
findex(zpty)
|
||||||
|
xitem(tt(zpty) [ tt(-e) ] [ tt(-b) ] var(name) var(command) [ var(args ...) ])
|
||||||
|
xitem(tt(zpty) tt(-d) [ var(names) ... ])
|
||||||
|
xitem(tt(zpty) tt(-w) [ tt(-n) ] var(name) var(strings ...))
|
||||||
|
xitem(tt(zpty) tt(-r) var(name) [ var(param) [ var(pattern) ] ])
|
||||||
|
item(tt(zpty) [ tt(-L) ])(
|
||||||
|
In the first form, the var(command) is started with the var(args) as
|
||||||
|
arguments. After this, the var(name) can be used in further calls to
|
||||||
|
tt(zpty) to refer to this command. With the tt(-e) option given, the
|
||||||
|
pseudo-terminal will be set up so that input characters are echoed and
|
||||||
|
with the tt(-b) option given, input and output from and to the
|
||||||
|
pseudo-terminal will be blocking.
|
||||||
|
|
||||||
|
The second form with the tt(-d) option is used to delete commands
|
||||||
|
started before by giving their var(names). If no var(names) are given,
|
||||||
|
all commands are deleted. Deleting a command makes the HUP signal be
|
||||||
|
sent to the process started for it.
|
||||||
|
|
||||||
|
The tt(-w) option can be used to sent the command var(name) the given
|
||||||
|
var(strings) as input (separated by spaces). If the tt(-n) option is
|
||||||
|
not given, a newline will be sent after the last var(string).
|
||||||
|
|
||||||
|
The tt(-r) option can be used to read the output of the command
|
||||||
|
var(name). Without a var(param) argument, the string read will be
|
||||||
|
printed to standard output. With a var(param) argument, the string
|
||||||
|
read will be put in the parameter named var(param). If the
|
||||||
|
var(pattern) is also given, output will be read until the whole string
|
||||||
|
read matches the var(pattern).
|
||||||
|
|
||||||
|
The last form without any arguments is used to list the commands
|
||||||
|
currently defined. If the tt(-L) option is given, this is done in the
|
||||||
|
form of calls to the tt(zpty) builtin.
|
||||||
|
)
|
||||||
|
enditem()
|
||||||
|
|
@ -1,34 +1,27 @@
|
||||||
# Simple wrapper function for `nslookup'. With completion if you are using
|
# Simple wrapper function for `nslookup'. With completion if you are using
|
||||||
# the function based completion system.
|
# the function based completion system.
|
||||||
|
|
||||||
setopt localoptions completealiases
|
setopt localoptions localtraps completealiases
|
||||||
|
|
||||||
local char line compcontext=nslookup pid
|
local tmp line compcontext=nslookup curcontext=':nslookup' pmpt
|
||||||
|
|
||||||
trap 'print -p exit;return' INT
|
trap 'return 130' INT
|
||||||
|
trap 'zpty -d nslookup' EXIT
|
||||||
|
|
||||||
coproc command nslookup
|
zstyle -s ':nslookup' prompt pmpt || pmpt='> '
|
||||||
pid=$!
|
|
||||||
|
|
||||||
while read -pk 1 char; do
|
zpty nslookup nslookup
|
||||||
line="$line$char"
|
|
||||||
[[ "$line" = *'
|
|
||||||
> ' ]] && break
|
|
||||||
done
|
|
||||||
print -nr - "$line"
|
|
||||||
|
|
||||||
line=''
|
zpty -r nslookup line '*> '
|
||||||
while vared -p '> ' line; do
|
print -nr "$line"
|
||||||
print -p "$line"
|
|
||||||
line=''
|
while line=''; vared -p "$pmpt" line; do
|
||||||
while read -pk 1 char; do
|
[[ "$line" = exit ]] && break
|
||||||
line="$line$char"
|
|
||||||
[[ "$line" = *'
|
zpty -w nslookup "$line"
|
||||||
> ' ]] && break
|
|
||||||
done
|
zpty -r nslookup line '*> '
|
||||||
print -nr - "$line"
|
print -nr "$line"
|
||||||
line=''
|
|
||||||
done
|
done
|
||||||
|
|
||||||
print -p exit
|
zpty -w nslookup 'exit'
|
||||||
wait $pid
|
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@ DISTFILES_SRC='
|
||||||
stat.mdd stat.c
|
stat.mdd stat.c
|
||||||
zftp.mdd zftp.c
|
zftp.mdd zftp.c
|
||||||
zutil.mdd zutil.c
|
zutil.mdd zutil.c
|
||||||
|
zpty.mdd zpty.c
|
||||||
'
|
'
|
||||||
|
|
|
||||||
564
Src/Modules/zpty.c
Normal file
564
Src/Modules/zpty.c
Normal file
|
|
@ -0,0 +1,564 @@
|
||||||
|
/*
|
||||||
|
* zpty.c - sub-processes with pseudo terminals
|
||||||
|
*
|
||||||
|
* This file is part of zsh, the Z shell.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2000 Sven Wischnowsky
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and to distribute modified versions of this software for any
|
||||||
|
* purpose, provided that the above copyright notice and the following
|
||||||
|
* two paragraphs appear in all copies of this software.
|
||||||
|
*
|
||||||
|
* In no event shall Sven Wischnowsky or the Zsh Development Group be liable
|
||||||
|
* to any party for direct, indirect, special, incidental, or consequential
|
||||||
|
* damages arising out of the use of this software and its documentation,
|
||||||
|
* even if Sven Wischnowsky and the Zsh Development Group have been advised of
|
||||||
|
* the possibility of such damage.
|
||||||
|
*
|
||||||
|
* Sven Wischnowsky and the Zsh Development Group specifically disclaim any
|
||||||
|
* warranties, including, but not limited to, the implied warranties of
|
||||||
|
* merchantability and fitness for a particular purpose. The software
|
||||||
|
* provided hereunder is on an "as is" basis, and Sven Wischnowsky and the
|
||||||
|
* Zsh Development Group have no obligation to provide maintenance,
|
||||||
|
* support, updates, enhancements, or modifications.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zpty.mdh"
|
||||||
|
#include "zpty.pro"
|
||||||
|
|
||||||
|
typedef struct ptycmd *Ptycmd;
|
||||||
|
|
||||||
|
struct ptycmd {
|
||||||
|
Ptycmd next;
|
||||||
|
char *name;
|
||||||
|
char **args;
|
||||||
|
int fd;
|
||||||
|
int pid;
|
||||||
|
int echo;
|
||||||
|
int block;
|
||||||
|
int fin;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Ptycmd ptycmds;
|
||||||
|
|
||||||
|
static int
|
||||||
|
ptynonblock(int fd)
|
||||||
|
{
|
||||||
|
#ifdef O_NDELAY
|
||||||
|
# ifdef O_NONBLOCK
|
||||||
|
# define NONBLOCK (O_NDELAY|O_NONBLOCK)
|
||||||
|
# else /* !O_NONBLOCK */
|
||||||
|
# define NONBLOCK O_NDELAY
|
||||||
|
# endif /* !O_NONBLOCK */
|
||||||
|
#else /* !O_NDELAY */
|
||||||
|
# ifdef O_NONBLOCK
|
||||||
|
# define NONBLOCK O_NONBLOCK
|
||||||
|
# else /* !O_NONBLOCK */
|
||||||
|
# define NONBLOCK 0
|
||||||
|
# endif /* !O_NONBLOCK */
|
||||||
|
#endif /* !O_NDELAY */
|
||||||
|
|
||||||
|
#if NONBLOCK
|
||||||
|
long mode;
|
||||||
|
|
||||||
|
mode = fcntl(fd, F_GETFL, 0);
|
||||||
|
if (mode != -1 && !(mode & NONBLOCK) &&
|
||||||
|
!fcntl(fd, F_SETFL, mode | NONBLOCK))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#endif /* NONBLOCK */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#undef NONBLOCK
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
ptygettyinfo(int fd, struct ttyinfo *ti)
|
||||||
|
{
|
||||||
|
if (fd != -1) {
|
||||||
|
#ifdef HAVE_TERMIOS_H
|
||||||
|
# ifdef HAVE_TCGETATTR
|
||||||
|
if (tcgetattr(fd, &ti->tio) == -1)
|
||||||
|
# else
|
||||||
|
if (ioctl(fd, TCGETS, &ti->tio) == -1)
|
||||||
|
# endif
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_TERMIO_H
|
||||||
|
ioctl(fd, TCGETA, &ti->tio);
|
||||||
|
# else
|
||||||
|
ioctl(fd, TIOCGETP, &ti->sgttyb);
|
||||||
|
ioctl(fd, TIOCLGET, &ti->lmodes);
|
||||||
|
ioctl(fd, TIOCGETC, &ti->tchars);
|
||||||
|
ioctl(fd, TIOCGLTC, &ti->ltchars);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static void
|
||||||
|
ptysettyinfo(int fd, struct ttyinfo *ti)
|
||||||
|
{
|
||||||
|
if (fd != -1) {
|
||||||
|
#ifdef HAVE_TERMIOS_H
|
||||||
|
# ifdef HAVE_TCGETATTR
|
||||||
|
# ifndef TCSADRAIN
|
||||||
|
# define TCSADRAIN 1 /* XXX Princeton's include files are screwed up */
|
||||||
|
# endif
|
||||||
|
tcsetattr(fd, TCSADRAIN, &ti->tio);
|
||||||
|
/* if (tcsetattr(SHTTY, TCSADRAIN, &ti->tio) == -1) */
|
||||||
|
# else
|
||||||
|
ioctl(fd, TCSETS, &ti->tio);
|
||||||
|
/* if (ioctl(SHTTY, TCSETS, &ti->tio) == -1) */
|
||||||
|
# endif
|
||||||
|
/* zerr("settyinfo: %e",NULL,errno)*/ ;
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_TERMIO_H
|
||||||
|
ioctl(fd, TCSETA, &ti->tio);
|
||||||
|
# else
|
||||||
|
ioctl(fd, TIOCSETN, &ti->sgttyb);
|
||||||
|
ioctl(fd, TIOCLSET, &ti->lmodes);
|
||||||
|
ioctl(fd, TIOCSETC, &ti->tchars);
|
||||||
|
ioctl(fd, TIOCSLTC, &ti->ltchars);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Ptycmd
|
||||||
|
getptycmd(char *name)
|
||||||
|
{
|
||||||
|
Ptycmd p;
|
||||||
|
|
||||||
|
for (p = ptycmds; p; p = p->next)
|
||||||
|
if (!strcmp(p->name, name))
|
||||||
|
return p;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** maybe we should use configure here */
|
||||||
|
/**** and we certainly need more/better #if tests */
|
||||||
|
|
||||||
|
#ifdef __osf__
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_pty(int *master, int *slave)
|
||||||
|
{
|
||||||
|
return openpty(master, slave, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ! __osf__ */
|
||||||
|
|
||||||
|
#if __SVR4
|
||||||
|
|
||||||
|
#include <sys/stropts.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_pty(int *master, int *slave)
|
||||||
|
{
|
||||||
|
int mfd, sfd;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
if ((mfd = open("/dev/ptmx", O_RDWR)) < 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!(name = ptsname(mfd)) || grantpt(mfd) || unlockpt(mfd)) {
|
||||||
|
close(mfd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((sfd = open(name, O_RDWR)) < 0) {
|
||||||
|
close(mfd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ioctl(sfd, I_PUSH, "ptem") ||
|
||||||
|
ioctl(sfd, I_PUSH, "ldterm") ||
|
||||||
|
ioctl(sfd, I_PUSH, "ttcompat")) {
|
||||||
|
close(mfd);
|
||||||
|
close(sfd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*master = mfd;
|
||||||
|
*slave = sfd;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* ! __SVR4 */
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_pty(int *master, int *slave)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
static char char1[] = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
static char char2[] = "0123456789abcdef";
|
||||||
|
#else /* ! __linux */
|
||||||
|
static char char1[] = "pq";
|
||||||
|
static char char2[] = "0123456789abcdef";
|
||||||
|
#endif /* __linux */
|
||||||
|
|
||||||
|
char name[11], *p1, *p2;
|
||||||
|
int mfd, sfd;
|
||||||
|
|
||||||
|
strcpy(name, "/dev/ptyxx");
|
||||||
|
|
||||||
|
for (p1 = char1; *p1; p1++) {
|
||||||
|
name[8] = *p1;
|
||||||
|
for (p2 = char2; *p2; p2++) {
|
||||||
|
name[9] = *p2;
|
||||||
|
if ((mfd = open(name, O_RDWR)) >= 0) {
|
||||||
|
name[5] = 't';
|
||||||
|
if ((sfd = open(name, O_RDWR)) >= 0) {
|
||||||
|
*master = mfd;
|
||||||
|
*slave = sfd;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
name[5] = 'p';
|
||||||
|
close(mfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __SVR4 */
|
||||||
|
#endif /* __osf__ */
|
||||||
|
|
||||||
|
static int
|
||||||
|
newptycmd(char *nam, char *pname, char **args, int echo, int block)
|
||||||
|
{
|
||||||
|
Ptycmd p;
|
||||||
|
int master, slave, pid;
|
||||||
|
char *cmd;
|
||||||
|
|
||||||
|
if (!(cmd = findcmd(*args, 1))) {
|
||||||
|
zerrnam(nam, "unknown command: %s", *args, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (get_pty(&master, &slave)) {
|
||||||
|
zerrnam(nam, "can't open pseudo terminal", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((pid = fork()) == -1) {
|
||||||
|
close(master);
|
||||||
|
close(slave);
|
||||||
|
zerrnam(nam, "couldn't create pty command: %s", pname, 0);
|
||||||
|
return 1;
|
||||||
|
} else if (!pid) {
|
||||||
|
if (!echo) {
|
||||||
|
struct ttyinfo info;
|
||||||
|
|
||||||
|
if (!ptygettyinfo(slave, &info)) {
|
||||||
|
#ifdef HAVE_TERMIOS_H
|
||||||
|
info.tio.c_lflag &= ~ECHO;
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_TERMIO_H
|
||||||
|
info.tio.c_lflag &= ~ECHO;
|
||||||
|
#else
|
||||||
|
info.tio.lmodes &= ~ECHO; /**** dunno if this is right */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
ptysettyinfo(slave, &info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TIOCGWINSZ
|
||||||
|
if (interact) {
|
||||||
|
struct ttyinfo info;
|
||||||
|
|
||||||
|
if (ioctl(slave, TIOCGWINSZ, (char *) &info.winsize) == 0) {
|
||||||
|
info.winsize.ws_row = lines;
|
||||||
|
info.winsize.ws_col = columns;
|
||||||
|
ioctl(slave, TIOCSWINSZ, (char *) &info.winsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* TIOCGWINSZ */
|
||||||
|
|
||||||
|
signal_default(SIGTERM);
|
||||||
|
signal_default(SIGINT);
|
||||||
|
signal_default(SIGQUIT);
|
||||||
|
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
|
||||||
|
dup2(slave, 0);
|
||||||
|
dup2(slave, 1);
|
||||||
|
dup2(slave, 2);
|
||||||
|
|
||||||
|
close(slave);
|
||||||
|
|
||||||
|
execve(cmd, args, environ);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
master = movefd(master);
|
||||||
|
close(slave);
|
||||||
|
|
||||||
|
p = (Ptycmd) zalloc(sizeof(*p));
|
||||||
|
|
||||||
|
p->name = ztrdup(pname);
|
||||||
|
PERMALLOC {
|
||||||
|
p->args = arrdup(args);
|
||||||
|
} LASTALLOC;
|
||||||
|
p->fd = master;
|
||||||
|
p->pid = pid;
|
||||||
|
p->echo = echo;
|
||||||
|
p->block = block;
|
||||||
|
p->fin = 0;
|
||||||
|
|
||||||
|
p->next = ptycmds;
|
||||||
|
ptycmds = p;
|
||||||
|
|
||||||
|
if (!block)
|
||||||
|
ptynonblock(master);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
deleteptycmd(Ptycmd cmd)
|
||||||
|
{
|
||||||
|
Ptycmd p, q;
|
||||||
|
|
||||||
|
for (q = NULL, p = ptycmds; p != cmd; q = p, p = p->next);
|
||||||
|
|
||||||
|
if (p != cmd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (q)
|
||||||
|
q->next = p->next;
|
||||||
|
else
|
||||||
|
ptycmds = p->next;
|
||||||
|
|
||||||
|
zsfree(p->name);
|
||||||
|
freearray(p->args);
|
||||||
|
|
||||||
|
kill(p->pid, SIGHUP);
|
||||||
|
|
||||||
|
zclose(cmd->fd);
|
||||||
|
|
||||||
|
zfree(p, sizeof(*p));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
deleteallptycmds(void)
|
||||||
|
{
|
||||||
|
Ptycmd p, n;
|
||||||
|
|
||||||
|
for (p = ptycmds; p; p = n) {
|
||||||
|
n = p->next;
|
||||||
|
deleteptycmd(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** a better process handling would be nice */
|
||||||
|
|
||||||
|
static void
|
||||||
|
checkptycmd(Ptycmd cmd)
|
||||||
|
{
|
||||||
|
if (kill(cmd->pid, 0) < 0) {
|
||||||
|
cmd->fin = 1;
|
||||||
|
zclose(cmd->fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ptyread(char *nam, Ptycmd cmd, char **args)
|
||||||
|
{
|
||||||
|
int blen = 256, used = 0, ret;
|
||||||
|
char *buf = (char *) zhalloc(blen + 1);
|
||||||
|
Patprog prog = NULL;
|
||||||
|
|
||||||
|
if (*args && args[1]) {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (args[2]) {
|
||||||
|
zerrnam(nam, "too many arguments", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p = dupstring(args[1]);
|
||||||
|
tokenize(p);
|
||||||
|
remnulargs(p);
|
||||||
|
if (!(prog = patcompile(p, PAT_STATIC, NULL))) {
|
||||||
|
zerrnam(nam, "bad pattern: %s", args[1], 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
while ((ret = read(cmd->fd, buf + used, 1)) == 1) {
|
||||||
|
if (++used == blen) {
|
||||||
|
buf = hrealloc(buf, blen, blen << 1);
|
||||||
|
blen <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf[used] = '\0';
|
||||||
|
} while (prog && !pattry(prog, buf));
|
||||||
|
|
||||||
|
if (*args)
|
||||||
|
setsparam(*args, ztrdup(buf));
|
||||||
|
else
|
||||||
|
printf("%s", buf);
|
||||||
|
|
||||||
|
return !used;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ptywrite(Ptycmd cmd, char **args, int nonl)
|
||||||
|
{
|
||||||
|
if (*args) {
|
||||||
|
char sp = ' ';
|
||||||
|
|
||||||
|
while (*args) {
|
||||||
|
write(cmd->fd, *args, strlen(*args));
|
||||||
|
|
||||||
|
if (*++args)
|
||||||
|
write(cmd->fd, &sp, 1);
|
||||||
|
}
|
||||||
|
if (!nonl) {
|
||||||
|
sp = '\n';
|
||||||
|
write(cmd->fd, &sp, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int n;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
while ((n = read(0, buf, BUFSIZ)) > 0)
|
||||||
|
write(cmd->fd, buf, n);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
bin_zpty(char *nam, char **args, char *ops, int func)
|
||||||
|
{
|
||||||
|
if ((ops['r'] && ops['w']) ||
|
||||||
|
((ops['r'] || ops['w']) && (ops['d'] || ops['e'] ||
|
||||||
|
ops['b'] || ops['L'])) ||
|
||||||
|
(ops['n'] && (ops['b'] || ops['e'] || ops['r'] ||
|
||||||
|
ops['d'] || ops['L'])) ||
|
||||||
|
(ops['d'] && (ops['b'] || ops['e'] || ops['L'])) ||
|
||||||
|
(ops['L'] && (ops['b'] || ops['e']))) {
|
||||||
|
zerrnam(nam, "illegal option combination", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ops['r'] || ops['w']) {
|
||||||
|
Ptycmd p;
|
||||||
|
|
||||||
|
if (!*args) {
|
||||||
|
zerrnam(nam, "missing pty command name", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
} else if (!(p = getptycmd(*args))) {
|
||||||
|
zerrnam(nam, "no such pty command: %s", *args, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
checkptycmd(p);
|
||||||
|
if (p->fin)
|
||||||
|
return 1;
|
||||||
|
return (ops['r'] ?
|
||||||
|
ptyread(nam, p, args + 1) :
|
||||||
|
ptywrite(p, args + 1, ops['n']));
|
||||||
|
} else if (ops['d']) {
|
||||||
|
Ptycmd p;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (*args) {
|
||||||
|
while (*args)
|
||||||
|
if ((p = getptycmd(*args++)))
|
||||||
|
deleteptycmd(p);
|
||||||
|
else {
|
||||||
|
zwarnnam(nam, "no such pty command: %s", args[-1], 0);
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
deleteallptycmds();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
} else if (*args) {
|
||||||
|
if (!args[1]) {
|
||||||
|
zerrnam(nam, "missing command", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (getptycmd(*args)) {
|
||||||
|
zerrnam(nam, "pty command name already used: %s", *args, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return newptycmd(nam, *args, args + 1, ops['e'], ops['b']);
|
||||||
|
} else {
|
||||||
|
Ptycmd p;
|
||||||
|
char **a;
|
||||||
|
|
||||||
|
for (p = ptycmds; p; p = p->next) {
|
||||||
|
checkptycmd(p);
|
||||||
|
if (ops['L'])
|
||||||
|
printf("%s %s%s%s ", nam, (p->echo ? "-e " : ""),
|
||||||
|
(p->block ? "-b " : ""), p->name);
|
||||||
|
else if (p->fin)
|
||||||
|
printf("(finished) %s: ", p->name);
|
||||||
|
else
|
||||||
|
printf("(%d) %s: ", p->pid, p->name);
|
||||||
|
for (a = p->args; *a; ) {
|
||||||
|
quotedzputs(*a++, stdout);
|
||||||
|
if (*a)
|
||||||
|
putchar(' ');
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ptyhook(Hookdef d, void *dummy)
|
||||||
|
{
|
||||||
|
deleteallptycmds();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct builtin bintab[] = {
|
||||||
|
BUILTIN("zpty", 0, bin_zpty, 0, -1, 0, "ebdrwLn", NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_(Module m)
|
||||||
|
{
|
||||||
|
ptycmds = NULL;
|
||||||
|
|
||||||
|
addhookfunc("exit", ptyhook);
|
||||||
|
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
cleanup_(Module m)
|
||||||
|
{
|
||||||
|
deletehookfunc("exit", ptyhook);
|
||||||
|
deleteallptycmds();
|
||||||
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
5
Src/Modules/zpty.mdd
Normal file
5
Src/Modules/zpty.mdd
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
name=zsh/zpty
|
||||||
|
|
||||||
|
autobins="zpty"
|
||||||
|
|
||||||
|
objects="zpty.o"
|
||||||
|
|
@ -3219,6 +3219,7 @@ zexit(int val, int from_signal)
|
||||||
}
|
}
|
||||||
if (sigtrapped[SIGEXIT])
|
if (sigtrapped[SIGEXIT])
|
||||||
dotrap(SIGEXIT);
|
dotrap(SIGEXIT);
|
||||||
|
runhookdef(EXITHOOK, NULL);
|
||||||
if (mypid != getpid())
|
if (mypid != getpid())
|
||||||
_exit(val);
|
_exit(val);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,11 @@ mod_export int (*getkeyptr) _((int));
|
||||||
mod_export int alloc_stackp;
|
mod_export int alloc_stackp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**/
|
||||||
|
mod_export struct hookdef zshhooks[] = {
|
||||||
|
HOOKDEF("exit", NULL, HOOKF_ALL),
|
||||||
|
};
|
||||||
|
|
||||||
/* keep executing lists until EOF found */
|
/* keep executing lists until EOF found */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
|
@ -560,6 +565,8 @@ setupvals(void)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
addhookdefs(argzero, zshhooks, sizeof(zshhooks)/sizeof(*zshhooks));
|
||||||
|
|
||||||
init_eprog();
|
init_eprog();
|
||||||
|
|
||||||
getkeyptr = NULL;
|
getkeyptr = NULL;
|
||||||
|
|
|
||||||
|
|
@ -1641,3 +1641,9 @@ typedef unsigned char * (*ZleReadFn) _((char *, char *, int));
|
||||||
/***************************************/
|
/***************************************/
|
||||||
|
|
||||||
#define mod_export
|
#define mod_export
|
||||||
|
|
||||||
|
/***************************************/
|
||||||
|
/* Hooks in core. */
|
||||||
|
/***************************************/
|
||||||
|
|
||||||
|
#define EXITHOOK (zshhooks + 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue