mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-10-31 06:00:54 +01:00 
			
		
		
		
	Assorted read_poll() and zpty cleanup.
This commit is contained in:
		
							parent
							
								
									ab99c6d8b6
								
							
						
					
					
						commit
						dbc0aebcd4
					
				
					 5 changed files with 146 additions and 73 deletions
				
			
		|  | @ -1,3 +1,12 @@ | |||
| 2000-11-05  Bart Schaefer  <schaefer@zsh.org> | ||||
| 
 | ||||
| 	* 13120: Doc/Zsh/mod_zpty.yo, Functions/Misc/nslookup, | ||||
| 	Src/utils.c, Src/Modules/zpty.c: Merge Sven's uncommitted patch | ||||
| 	from 13061 with 13116.  WARNING: This reverses the meaning of | ||||
| 	`zpty -b'; the default is now blocking, -b selects non-blocking. | ||||
| 	Fix nslookup accordingly.  Clean up read_poll() somewhat. | ||||
| 	Document that `zpty -w' and `zpty -r' can stream to/from the pty. | ||||
| 
 | ||||
| 2000-11-04  Bart Schaefer  <schaefer@zsh.org> | ||||
| 
 | ||||
| 	* 13118: Completion/Core/compinit: Add `bareglobqual' to the | ||||
|  |  | |||
|  | @ -5,42 +5,73 @@ 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) ] ]) | ||||
| xitem(tt(zpty) tt(-t) var(name)) | ||||
| item(tt(zpty) [ tt(-L) ])( | ||||
| item(tt(zpty) [ tt(-e) ] [ tt(-b) ] var(name) var(command) [ var(args ...) ])( | ||||
| In the first form, the var(command) is started with the var(args) as | ||||
| arguments.  The command runs under a newly assigned pseudo-terminal; this | ||||
| is useful for running commands non-interactively which expect an | ||||
| interactive environment.  The var(name) given is used to refer to this | ||||
| command in later calls to tt(pty).  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. | ||||
| interactive environment.  The var(name) is used to refer to this command | ||||
| in later calls to tt(zpty). | ||||
| 
 | ||||
| The second form with the tt(-d) option is used to delete commands | ||||
| previously started by supplying a list of their var(name)s.  If no | ||||
| With the tt(-e) option, the pseudo-terminal is set up so that input | ||||
| characters are echoed. | ||||
| 
 | ||||
| With the tt(-b) option, input to and output from the pseudo-terminal are | ||||
| made non-blocking. | ||||
| ) | ||||
| item(tt(zpty) tt(-d) [ var(names) ... ])( | ||||
| The second form, with the tt(-d) option, is used to delete commands | ||||
| previously started, by supplying a list of their var(name)s.  If no | ||||
| var(names) are given, all commands are deleted.  Deleting a command causes | ||||
| the HUP signal to be sent to the corresponding process. | ||||
| 
 | ||||
| The tt(-w) option can be used to send the command var(name) the given | ||||
| ) | ||||
| item(tt(zpty) tt(-w) [ tt(-n) ] var(name) [ var(strings ...) ])( | ||||
| The tt(-w) option can be used to send the to command var(name) the given | ||||
| var(strings) as input (separated by spaces).  If the tt(-n) option is | ||||
| not given, a newline will be added at the end. | ||||
| em(not) given, a newline is added at the end. | ||||
| 
 | ||||
| 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). | ||||
| If no var(strings) are provided, the standard input is copied to the | ||||
| pseudo-terminal; this may stop before copying the full input if the | ||||
| pseudo-terminal is non-blocking. | ||||
| 
 | ||||
| The tt(-t) option can be used to test whether the command var(name) is  | ||||
| still running.  It returns a zero value if the command is running and | ||||
| a non-zero value otherwise. | ||||
| Note that the command under the pseudo-terminal sees this input as if it | ||||
| were typed, so beware when sending special tty driver characters such as | ||||
| word-erase, line-kill, and end-of-file. | ||||
| ) | ||||
| item(tt(zpty) tt(-r) [ tt(-t) ] var(name) [ var(param) [ var(pattern) ] ])( | ||||
| The tt(-r) option can be used to read the output of the command var(name). | ||||
| With only a var(name) argument, the output read is copied to the standard | ||||
| output.  Unless the pseudo-terminal is non-blocking, copying continues | ||||
| until the command under the pseudo-terminal exits; when non-blocking, only | ||||
| as much output as is immediately available is copied.  The return value is | ||||
| zero if any output is copied. | ||||
| 
 | ||||
| The last form without any arguments is used to list the commands | ||||
| When also given a var(param) argument, at most one line is read and stored | ||||
| in the parameter named var(param).  Less than a full line may be read if | ||||
| the pseudo-terminal is non-blocking.  The return value is zero if at least | ||||
| one character is stored in var(param). | ||||
| 
 | ||||
| If a var(pattern) is given as well, output is read until the whole string | ||||
| read matches the var(pattern), even in the non-blocking case.  The return | ||||
| value is zero if the string read matches the pattern, or if the command | ||||
| has exited but at least one character could still be read.  As of this | ||||
| writing, a maximum of one megabyte of output can be consumed this way; if | ||||
| a full megabyte is read without matching the pattern, the return value is | ||||
| non-zero. | ||||
| 
 | ||||
| In all cases, the return value is non-zero if nothing could be read, and | ||||
| is tt(2) if this is because the command has finished. | ||||
| 
 | ||||
| If the tt(-r) option is combined with the tt(-t) option, tt(zpty) tests | ||||
| whether output is available before trying to read.  If no output is | ||||
| available, tt(zpty) immediately returns the value tt(1). | ||||
| ) | ||||
| item(tt(zpty) tt(-t) var(name))( | ||||
| The tt(-t) option without the tt(-r) option can be used to test | ||||
| whether the command var(name) is still running.  It returns a zero | ||||
| value if the command is running and a non-zero value otherwise. | ||||
| ) | ||||
| item(tt(zpty) [ tt(-L) ])( | ||||
| 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. | ||||
| ) | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ zstyle -s ':nslookup' pager tmp && | |||
|     [[ -z "$pager" ]] && pager="${opager:-more}" | ||||
| (( $#pmpt )) || pmpt=(-p '> ') | ||||
| 
 | ||||
| zpty -b nslookup nslookup "$@" | ||||
| zpty nslookup nslookup "$@" | ||||
| 
 | ||||
| zpty -r nslookup line '* | ||||
| > ' | ||||
|  |  | |||
|  | @ -34,7 +34,6 @@ | |||
|  * upper bound on the number of bytes we read (even if we are give a | ||||
|  * pattern). */ | ||||
| 
 | ||||
| #define READ_LEN 1024 | ||||
| #define READ_MAX (1024 * 1024) | ||||
| 
 | ||||
| typedef struct ptycmd *Ptycmd; | ||||
|  | @ -46,9 +45,10 @@ struct ptycmd { | |||
|     int fd; | ||||
|     int pid; | ||||
|     int echo; | ||||
|     int block; | ||||
|     int nblock; | ||||
|     int fin; | ||||
|     int read; | ||||
|     char *old; | ||||
| }; | ||||
| 
 | ||||
| static Ptycmd ptycmds; | ||||
|  | @ -264,7 +264,7 @@ get_pty(int master, int *retfd) | |||
| #endif /* __SVR4 */ | ||||
| 
 | ||||
| static int | ||||
| newptycmd(char *nam, char *pname, char **args, int echo, int block) | ||||
| newptycmd(char *nam, char *pname, char **args, int echo, int nblock) | ||||
| { | ||||
|     Ptycmd p; | ||||
|     int master, slave, pid; | ||||
|  | @ -380,14 +380,15 @@ newptycmd(char *nam, char *pname, char **args, int echo, int block) | |||
|     p->fd = master; | ||||
|     p->pid = pid; | ||||
|     p->echo = echo; | ||||
|     p->block = block; | ||||
|     p->nblock = nblock; | ||||
|     p->fin = 0; | ||||
|     p->read = -1; | ||||
|     p->old = NULL; | ||||
| 
 | ||||
|     p->next = ptycmds; | ||||
|     ptycmds = p; | ||||
| 
 | ||||
|     if (!block) | ||||
|     if (nblock) | ||||
| 	ptynonblock(master); | ||||
| 
 | ||||
|     return 0; | ||||
|  | @ -411,12 +412,12 @@ deleteptycmd(Ptycmd cmd) | |||
|     zsfree(p->name); | ||||
|     freearray(p->args); | ||||
| 
 | ||||
|     zclose(cmd->fd); | ||||
| 
 | ||||
|     /* We kill the process group the command put itself in. */ | ||||
| 
 | ||||
|     kill(-(p->pid), SIGHUP); | ||||
| 
 | ||||
|     zclose(cmd->fd); | ||||
| 
 | ||||
|     zfree(p, sizeof(*p)); | ||||
| } | ||||
| 
 | ||||
|  | @ -438,7 +439,7 @@ checkptycmd(Ptycmd cmd) | |||
| { | ||||
|     if (cmd->read != -1) | ||||
| 	return; | ||||
|     if (!read_poll(cmd->fd, &cmd->read, !cmd->block) && | ||||
|     if (!read_poll(cmd->fd, &cmd->read, 0) && | ||||
| 	kill(cmd->pid, 0) < 0) { | ||||
| 	cmd->fin = 1; | ||||
| 	zclose(cmd->fd); | ||||
|  | @ -448,8 +449,8 @@ checkptycmd(Ptycmd cmd) | |||
| static int | ||||
| ptyread(char *nam, Ptycmd cmd, char **args) | ||||
| { | ||||
|     int blen = 256, used = 0, seen = 0, ret = 1; | ||||
|     char *buf = (char *) zhalloc((blen = 256) + 1); | ||||
|     int blen, used, seen = 0, ret = 0; | ||||
|     char *buf; | ||||
|     Patprog prog = NULL; | ||||
| 
 | ||||
|     if (*args && args[1]) { | ||||
|  | @ -469,10 +470,20 @@ ptyread(char *nam, Ptycmd cmd, char **args) | |||
|     } else | ||||
| 	fflush(stdout); | ||||
| 
 | ||||
|     if (cmd->old) { | ||||
| 	used = strlen(cmd->old); | ||||
| 	buf = (char *) zhalloc((blen = 256 + used) + 1); | ||||
| 	strcpy(buf, cmd->old); | ||||
| 	zsfree(cmd->old); | ||||
| 	cmd->old = NULL; | ||||
|     } else { | ||||
| 	used = 0; | ||||
| 	buf = (char *) zhalloc((blen = 256) + 1); | ||||
|     } | ||||
|     if (cmd->read != -1) { | ||||
| 	buf[0] = (char) cmd->read; | ||||
| 	buf[1] = '\0'; | ||||
| 	used = 1; | ||||
| 	buf[used] = (char) cmd->read; | ||||
| 	buf[used + 1] = '\0'; | ||||
| 	seen = used = 1; | ||||
| 	cmd->read = -1; | ||||
|     } | ||||
|     do { | ||||
|  | @ -495,36 +506,60 @@ ptyread(char *nam, Ptycmd cmd, char **args) | |||
| 	} | ||||
| 	buf[used] = '\0'; | ||||
| 
 | ||||
| 	if (!prog && ret <= 0) | ||||
| 	if (!prog && (ret <= 0 || (*args && buf[used - 1] == '\n'))) | ||||
| 	    break; | ||||
|     } while (!errflag && !breaks && !retflag && !contflag && | ||||
| 	     (prog ? (used < READ_MAX && (!ret || !pattry(prog, buf))) : | ||||
| 	      (used < READ_LEN))); | ||||
|     } while (!(errflag || breaks || retflag || contflag) && | ||||
| 	     used < READ_MAX && !(prog && ret && pattry(prog, buf))); | ||||
| 
 | ||||
|     if (prog && ret < 0 && | ||||
| #ifdef EWOULDBLOCK | ||||
| 	errno == EWOULDBLOCK | ||||
| #else | ||||
| #ifdef EAGAIN | ||||
| 	errno == EAGAIN | ||||
| #endif | ||||
| #endif | ||||
| 	) { | ||||
| 	cmd->old = ztrdup(buf); | ||||
| 	used = 0; | ||||
| 
 | ||||
| 	return 1; | ||||
|     } | ||||
|     if (*args) | ||||
| 	setsparam(*args, ztrdup(metafy(buf, used, META_HREALLOC))); | ||||
|     else | ||||
|     else if (used) | ||||
| 	write(1, buf, used); | ||||
| 
 | ||||
|     return !seen; | ||||
|     return (seen ? 0 : cmd->fin + 1); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| ptywritestr(Ptycmd cmd, char *s, int len) | ||||
| { | ||||
|     int written; | ||||
|     int written, all = 0; | ||||
| 
 | ||||
|     for (; len; len -= written, s += written) { | ||||
| 	if ((written = write(cmd->fd, s, len)) < 0) | ||||
| 	    return 1; | ||||
|     for (; !errflag && !breaks && !retflag && !contflag && len; | ||||
| 	 len -= written, s += written) { | ||||
| 	if ((written = write(cmd->fd, s, len)) < 0 && cmd->nblock && | ||||
| #ifdef EWOULDBLOCK | ||||
| 	    errno == EWOULDBLOCK | ||||
| #else | ||||
| #ifdef EAGAIN | ||||
| 	    errno == EAGAIN | ||||
| #endif | ||||
| #endif | ||||
| 	    ) | ||||
| 	    return !all; | ||||
| 	if (written < 0) { | ||||
| 	    checkptycmd(cmd); | ||||
| 	    if (cmd->fin) | ||||
| 		break; | ||||
| 	    written = 0; | ||||
| 	} | ||||
| 	if (written > 0) | ||||
| 	    all += written; | ||||
|     } | ||||
|     return 0; | ||||
|     return (all ? 0 : cmd->fin + 1); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
|  | @ -559,8 +594,9 @@ 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['t'] || | ||||
| 	((ops['r'] || ops['w']) && (ops['d'] || ops['e'] || | ||||
| 				    ops['b'] || ops['L'])) || | ||||
| 	(ops['w'] && ops['t']) || | ||||
| 	(ops['n'] && (ops['b'] || ops['e'] || ops['r'] || ops['t'] || | ||||
| 		      ops['d'] || ops['L'])) || | ||||
| 	(ops['d'] && (ops['b'] || ops['e'] || ops['L'] || ops['t'])) || | ||||
|  | @ -579,7 +615,10 @@ bin_zpty(char *nam, char **args, char *ops, int func) | |||
| 	    return 1; | ||||
| 	} | ||||
| 	if (p->fin) | ||||
| 	    return 2; | ||||
| 	if (ops['t'] && p->read == -1 && !read_poll(p->fd, &p->read, 0)) | ||||
| 	    return 1; | ||||
| 
 | ||||
| 	return (ops['r'] ? | ||||
| 		ptyread(nam, p, args + 1) : | ||||
| 		ptywrite(p, args + 1, ops['n'])); | ||||
|  | @ -629,7 +668,7 @@ bin_zpty(char *nam, char **args, char *ops, int func) | |||
| 	    checkptycmd(p); | ||||
| 	    if (ops['L']) | ||||
| 		printf("%s %s%s%s ", nam, (p->echo ? "-e " : ""), | ||||
| 		       (p->block ? "-b " : ""), p->name); | ||||
| 		       (p->nblock ? "-b " : ""), p->name); | ||||
| 	    else if (p->fin) | ||||
| 		printf("(finished) %s: ", p->name); | ||||
| 	    else | ||||
|  |  | |||
							
								
								
									
										34
									
								
								Src/utils.c
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								Src/utils.c
									
										
									
									
									
								
							|  | @ -1315,7 +1315,7 @@ setblock_stdin(void) | |||
| mod_export int | ||||
| read_poll(int fd, int *readchar, int polltty) | ||||
| { | ||||
|     int ret = 0; | ||||
|     int ret = -1; | ||||
|     long mode = -1; | ||||
|     char c; | ||||
| #ifdef HAVE_SELECT | ||||
|  | @ -1353,38 +1353,32 @@ read_poll(int fd, int *readchar, int polltty) | |||
|      */ | ||||
|     if (polltty) { | ||||
| 	gettyinfo(&ti); | ||||
| 	ti.tio.c_cc[VMIN] = 0; | ||||
| 	settyinfo(&ti); | ||||
| 	if ((polltty = ti.tio.c_cc[VMIN])) { | ||||
| 	    ti.tio.c_cc[VMIN] = 0; | ||||
| 	    settyinfo(&ti); | ||||
| 	} | ||||
|     } | ||||
| #else | ||||
|     polltty = 0; | ||||
| #endif | ||||
| #ifdef HAVE_SELECT | ||||
|     if (!ret) { | ||||
| 	expire_tv.tv_sec = expire_tv.tv_usec = 0; | ||||
| 	FD_ZERO(&foofd); | ||||
| 	FD_SET(fd, &foofd); | ||||
| 	if (select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv) | ||||
| 	    > 1) | ||||
| 	    ret = 1; | ||||
|     } | ||||
|     expire_tv.tv_sec = expire_tv.tv_usec = 0; | ||||
|     FD_ZERO(&foofd); | ||||
|     FD_SET(fd, &foofd); | ||||
|     ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv); | ||||
| #else | ||||
| #ifdef FIONREAD | ||||
|     if (!ret) { | ||||
| 	ioctl(fd, FIONREAD, (char *)&val); | ||||
| 	if (val) | ||||
| 	    ret = 1; | ||||
|     } | ||||
|     if (ioctl(fd, FIONREAD, (char *) &val) == 0) | ||||
| 	ret = (val > 0); | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
|     if (!ret) { | ||||
|     if (ret <= 0) { | ||||
| 	/*
 | ||||
| 	 * Final attempt: set non-blocking read and try to read a character. | ||||
| 	 * Praise Bill, this works under Cygwin (nothing else seems to). | ||||
| 	 */ | ||||
| 	if ((polltty || setblock_fd(0, fd, &mode)) | ||||
| 	    && read(fd, &c, 1) > 0) { | ||||
| 	if ((polltty || setblock_fd(0, fd, &mode)) && read(fd, &c, 1) > 0) { | ||||
| 	    *readchar = STOUC(c); | ||||
| 	    ret = 1; | ||||
| 	} | ||||
|  | @ -1397,7 +1391,7 @@ read_poll(int fd, int *readchar, int polltty) | |||
| 	settyinfo(&ti); | ||||
|     } | ||||
| #endif | ||||
|     return ret; | ||||
|     return (ret > 0); | ||||
| } | ||||
| 
 | ||||
| /**/ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue