mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-24 17:00:32 +02:00
18980: new zsh/system module
This commit is contained in:
parent
c016b2dcdc
commit
c9c5f9da93
11 changed files with 680 additions and 3 deletions
|
|
@ -1,5 +1,12 @@
|
||||||
2003-08-30 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
|
2003-08-30 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
|
||||||
|
|
||||||
|
* 18980: zshconfig.ac, Doc/.cvsignore, Doc/Makefile.in,
|
||||||
|
Doc/Zsh/mod_system.yo, Doc/Zsh/params.yo, Src/params.c,
|
||||||
|
Src/Modules/.cvsignore, Src/Modules/errnames1.awk,
|
||||||
|
Src/Modules/errnames2.awk, Src/Modules/system.c,
|
||||||
|
Src/Modules/system.mdd: zsh/system module provides interface
|
||||||
|
to read, write and system errors.
|
||||||
|
|
||||||
* 18982: Src/subst.c: Comments/rant for paramsubst().
|
* 18982: Src/subst.c: Comments/rant for paramsubst().
|
||||||
|
|
||||||
* 18981: Doc/Zsh/tcpsys.yo: General tidy up.
|
* 18981: Doc/Zsh/tcpsys.yo: General tidy up.
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,4 @@ zsh.tp zsh.tps
|
||||||
zsh_*.ps
|
zsh_*.ps
|
||||||
infodir
|
infodir
|
||||||
*.swp
|
*.swp
|
||||||
|
zsh.pdf zsh_a4.pdf zsh_us.pdf
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,11 @@ 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_pcre.yo \
|
Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_parameter.yo Zsh/mod_pcre.yo \
|
||||||
Zsh/mod_sched.yo Zsh/mod_socket.yo \
|
Zsh/mod_sched.yo Zsh/mod_socket.yo \
|
||||||
Zsh/mod_stat.yo Zsh/mod_termcap.yo Zsh/mod_terminfo.yo \
|
Zsh/mod_stat.yo Zsh/mod_system.yo Zsh/mod_tcp.yo \
|
||||||
|
Zsh/mod_termcap.yo Zsh/mod_terminfo.yo \
|
||||||
Zsh/mod_zftp.yo Zsh/mod_zle.yo Zsh/mod_zleparameter.yo \
|
Zsh/mod_zftp.yo Zsh/mod_zle.yo Zsh/mod_zleparameter.yo \
|
||||||
Zsh/mod_zprof.yo Zsh/mod_zpty.yo Zsh/mod_zselect.yo \
|
Zsh/mod_zprof.yo Zsh/mod_zpty.yo Zsh/mod_zselect.yo \
|
||||||
Zsh/mod_zutil.yo Zsh/mod_tcp.yo
|
Zsh/mod_zutil.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 \
|
||||||
|
|
|
||||||
128
Doc/Zsh/mod_system.yo
Normal file
128
Doc/Zsh/mod_system.yo
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
COMMENT(!MOD!zsh/system
|
||||||
|
A builtin interface to various low-level system features.
|
||||||
|
!MOD!)
|
||||||
|
The tt(zsh/system) module makes available three builtin commands and
|
||||||
|
a parameter.
|
||||||
|
|
||||||
|
sect(Builtins)
|
||||||
|
|
||||||
|
startitem()
|
||||||
|
findex(syserror)
|
||||||
|
item(tt(syserror) tt([ -e) var(errvar) tt(] [ -p) var(prefix) tt(] [) var(errno) tt(|) var(errname ]))(
|
||||||
|
This command prints out the error message associated with var(errno), a
|
||||||
|
system error number, followed by a newline to standard error.
|
||||||
|
|
||||||
|
Instead of the error number, a name var(errname), for example
|
||||||
|
tt(ENOENT), may be used. The set of names is the same as the contents
|
||||||
|
of the array tt(errnos), see below.
|
||||||
|
|
||||||
|
If the string var(prefix) is given, it is printed in front of the error
|
||||||
|
message, with no intervening space.
|
||||||
|
|
||||||
|
If var(errvar) is supplied, the entire message, without a newline, is
|
||||||
|
assigned to the parameter names var(errvar) and nothing is output.
|
||||||
|
|
||||||
|
A return value of 0 indicates the message was successfully printed
|
||||||
|
(although it may not be useful if the error number was out of the
|
||||||
|
system's range), a return value of 1 indicates an error in the
|
||||||
|
parameters, and a return value of 2 indicates the error name was
|
||||||
|
not recognised (no message is printed for this).
|
||||||
|
)
|
||||||
|
findex(sysread)
|
||||||
|
xitem(tt(sysread [ -c) var(countvar) tt(] [ -i) var(infd) tt(] [ -o) var(outfd) tt(]))
|
||||||
|
item( tt([ -s) var(bufsize) tt(] [ -t) var(timeout) tt(] [) var(param) tt(]))(
|
||||||
|
Perform a single system read from file descriptor var(infd), or zero if
|
||||||
|
that is not given. The result of the read is stored in var(param) or
|
||||||
|
var(REPLY) if that is not given. If var(countvar) is given, the number
|
||||||
|
of bytes read is assigned to the parameter named by var(countvar).
|
||||||
|
|
||||||
|
The maximum number of bytes read is var(bufsize) or 8192 if that is not
|
||||||
|
given, however the command returns as soon as any number of bytes was
|
||||||
|
successfully read.
|
||||||
|
|
||||||
|
If var(timeout) is given, it specifies a timeout in seconds, which may
|
||||||
|
be zero to poll the file descriptor. This is handled by the tt(poll)
|
||||||
|
system call if available, otherwise the tt(select) system call if
|
||||||
|
available.
|
||||||
|
|
||||||
|
If var(outfd) is given, an attempt is made to write all the bytes just
|
||||||
|
read to the file descriptor var(outfd). If this fails, because of a
|
||||||
|
system error other than tt(EINTR) or because of an internal zsh error
|
||||||
|
during an interrupt, the bytes read but not written are stored in the
|
||||||
|
parameter named by var(param) if supplied (no default is used in this
|
||||||
|
case), and the number of bytes read but not written is stored in the
|
||||||
|
parameter named by var(countvar) if that is supplied. If it was
|
||||||
|
successful, var(countvar) contains the full number of bytes transferred,
|
||||||
|
as usual, and var(param) is not set.
|
||||||
|
|
||||||
|
The error tt(EINTR) (interrupted system call) is handled internally so
|
||||||
|
that shell interrupts are transparent to the caller. Any other error
|
||||||
|
causes a return.
|
||||||
|
|
||||||
|
The possible return values are
|
||||||
|
startitem()
|
||||||
|
item(0)(
|
||||||
|
At least one byte of data was successfully read and, if appropriate,
|
||||||
|
written.
|
||||||
|
)
|
||||||
|
item(1)(
|
||||||
|
There was an error in the parameters to the command. This is the only
|
||||||
|
error for which a message is printed to standard error.
|
||||||
|
)
|
||||||
|
item(2)(
|
||||||
|
There was an error on the read, or on polling the input file descriptor
|
||||||
|
for a timeout. The parameter tt(ERRNO) gives the error.
|
||||||
|
)
|
||||||
|
item(3)(
|
||||||
|
Data were successfully read, but there was an error writing them
|
||||||
|
to var(outfd). The parameter tt(ERRNO) gives the error.
|
||||||
|
)
|
||||||
|
item(4)(
|
||||||
|
The attempt to read timed out. Note this does not set tt(ERRNO) as this
|
||||||
|
is not a system error.
|
||||||
|
)
|
||||||
|
item(5)(
|
||||||
|
No system error occurred, but zero bytes were read. This usually
|
||||||
|
indicates end of file. The parameters are set according to the
|
||||||
|
usual rules; no write to var(outfd) is attempted.
|
||||||
|
)
|
||||||
|
enditem()
|
||||||
|
)
|
||||||
|
item(tt(syswrite [ -c) var(countvar) tt(] [ -o) var(outfd) tt(]) var(data))(
|
||||||
|
The data (a single string of bytes) are written to the file descriptor
|
||||||
|
var(outfd), or 1 if that is not given, using the tt(write) system call.
|
||||||
|
Multiple write operations may be used if the first does not write all
|
||||||
|
the data.
|
||||||
|
|
||||||
|
If var(countvar) is given, the number of byte written is stored in the
|
||||||
|
parameter named by var(countvar); this may not be the full length of
|
||||||
|
var(data) if an error occurred.
|
||||||
|
|
||||||
|
The error tt(EINTR) (interrupted system call) is handled internally by
|
||||||
|
retrying; otherwise an error causes the command to return. For example,
|
||||||
|
if the file descriptor is set to non-blocking output, an error
|
||||||
|
tt(EAGAIN) (on some systems, tt(EWOULDBLOCK)) may result in the command
|
||||||
|
returning early.
|
||||||
|
|
||||||
|
The return status may be 0 for success, 1 for an error in the parameters
|
||||||
|
to the command, or 2 for an error on the write; no error message is
|
||||||
|
printed in the last case, but the parameter tt(ERRNO) will reflect
|
||||||
|
the error that occurred.
|
||||||
|
)
|
||||||
|
enditem()
|
||||||
|
|
||||||
|
sect(Parameters)
|
||||||
|
|
||||||
|
startitem()
|
||||||
|
item(tt(errnos))(
|
||||||
|
A readonly array of the names of errors defined on the system. These
|
||||||
|
are typically macros defined in C by including the system header file
|
||||||
|
tt(errno.h). The index of each name (assuming the option tt(KSH_ARRAYS)
|
||||||
|
is unset) corresponds to the error number. Error numbers var(num)
|
||||||
|
before the last known error which have no name are given the name
|
||||||
|
tt(E)var(num) in the array.
|
||||||
|
|
||||||
|
Note that aliases for errors are not handled; only the canonical name is
|
||||||
|
used.
|
||||||
|
)
|
||||||
|
enditem()
|
||||||
|
|
@ -520,7 +520,8 @@ item(tt(ERRNO) <S>)(
|
||||||
The value of errno (see manref(errno)(3))
|
The value of errno (see manref(errno)(3))
|
||||||
as set by the most recently failed system call.
|
as set by the most recently failed system call.
|
||||||
This value is system dependent and is intended for debugging
|
This value is system dependent and is intended for debugging
|
||||||
purposes.
|
purposes. It is also useful with the tt(zsh/system) module which
|
||||||
|
allows the number to be turned into a name or message.
|
||||||
)
|
)
|
||||||
vindex(GID)
|
vindex(GID)
|
||||||
item(tt(GID) <S>)(
|
item(tt(GID) <S>)(
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,4 @@ so_locations
|
||||||
*.mdhs
|
*.mdhs
|
||||||
*.mdh.tmp
|
*.mdh.tmp
|
||||||
*.swp
|
*.swp
|
||||||
|
ernames.c errcount.h
|
||||||
|
|
|
||||||
18
Src/Modules/errnames1.awk
Normal file
18
Src/Modules/errnames1.awk
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Edited version of Src/signames1.awk.
|
||||||
|
#
|
||||||
|
# This is an awk script which finds out what the possibilities for
|
||||||
|
# the error names are, and dumps them out so that cpp can turn them
|
||||||
|
# into numbers. Since we don't need to decide here what the
|
||||||
|
# real signals are, we can afford to be generous about definitions,
|
||||||
|
# in case the definitions are in terms of other definitions.
|
||||||
|
# However, we need to avoid definitions with parentheses, which will
|
||||||
|
# mess up the syntax.
|
||||||
|
BEGIN { printf "#include <errno.h>\n\n" }
|
||||||
|
|
||||||
|
/^[\t ]*#[\t ]*define[\t ]*E[A-Z0-9]*[\t ][\t ]*[^(\t ]/ {
|
||||||
|
eindex = index($0, "E")
|
||||||
|
etail = substr($0, eindex, 80)
|
||||||
|
split(etail, tmp)
|
||||||
|
enam = substr(tmp[1], 2, 20)
|
||||||
|
printf("XXNAMES XXE%s E%s\n", enam, enam)
|
||||||
|
}
|
||||||
42
Src/Modules/errnames2.awk
Normal file
42
Src/Modules/errnames2.awk
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Edited version of Src/signames2.awk.
|
||||||
|
#
|
||||||
|
# {g,n}awk script to generate errnames.c
|
||||||
|
# This version relies on the previous output of the preprocessor
|
||||||
|
# on sigtmp.c, sigtmp.out, which is in turn generated by errnames1.awk.
|
||||||
|
#
|
||||||
|
# NB: On SunOS 4.1.3 - user-functions don\'t work properly, also \" problems
|
||||||
|
# Without 0 + hacks some nawks compare numbers as strings
|
||||||
|
#
|
||||||
|
/^XXNAMES XXE[A-Z0-9]*[\t ][\t ]*[1-9][0-9]*/ {
|
||||||
|
eindex = index($0, "E")
|
||||||
|
etail = substr($0, 11, 80)
|
||||||
|
split(etail, tmp)
|
||||||
|
enam = tmp[1]
|
||||||
|
enum = tmp[2]
|
||||||
|
if (errname[enum] == "") {
|
||||||
|
errname[enum] = enam
|
||||||
|
if (0 + max < 0 + enum && enum < 1024)
|
||||||
|
max = enum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
ps = "%s"
|
||||||
|
printf "/** errnames.c **/\n"
|
||||||
|
printf "/** architecture-customized errnames.c for zsh **/\n"
|
||||||
|
printf "\n"
|
||||||
|
printf "#define ERRCOUNT\t%d\n", max
|
||||||
|
printf "\n"
|
||||||
|
printf "#include %csystem.mdh%c\n", 34, 34
|
||||||
|
printf "\n"
|
||||||
|
printf "/**/\n"
|
||||||
|
printf "const char *sys_errnames[ERRCOUNT+1] = {\n"
|
||||||
|
|
||||||
|
for (i = 1; i <= 0 + max; i++)
|
||||||
|
if (errname[i] == "")
|
||||||
|
printf("\t%cE%d%c,\n", 34, i, 34)
|
||||||
|
else
|
||||||
|
printf("\t%c%s%c,\n", 34, errname[i], 34)
|
||||||
|
print "\tNULL"
|
||||||
|
print "};"
|
||||||
|
}
|
||||||
418
Src/Modules/system.c
Normal file
418
Src/Modules/system.c
Normal file
|
|
@ -0,0 +1,418 @@
|
||||||
|
/*
|
||||||
|
* sysread.c - interface to system read/write
|
||||||
|
*
|
||||||
|
* This file is part of zsh, the Z shell.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1998-2003 Peter Stephenson
|
||||||
|
* 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 Peter Stephenson 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 Peter Stephenson, and the Zsh
|
||||||
|
* Development Group have been advised of the possibility of such damage.
|
||||||
|
*
|
||||||
|
* Peter Stephenson 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 Peter Stephenson
|
||||||
|
* and the Zsh Development Group have no obligation to provide maintenance,
|
||||||
|
* support, updates, enhancements, or modifications.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "system.mdh"
|
||||||
|
#include "system.pro"
|
||||||
|
|
||||||
|
#ifdef HAVE_POLL_H
|
||||||
|
# include <poll.h>
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_POLL) && !defined(POLLIN)
|
||||||
|
# undef HAVE_POLL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SYSREAD_BUFSIZE 8192
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
getposint(char *instr, char *nam)
|
||||||
|
{
|
||||||
|
char *eptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = (int)zstrtol(instr, &eptr, 10);
|
||||||
|
if (*eptr || ret < 0) {
|
||||||
|
zwarnnam(nam, "integer expected: %s", instr, 0);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return values of bin_sysread:
|
||||||
|
* 0 Successfully read (and written if appropriate)
|
||||||
|
* 1 Error in parameters to command
|
||||||
|
* 2 Error on read, or polling read fd ) ERRNO set by
|
||||||
|
* 3 Error on write ) system
|
||||||
|
* 4 Timeout on read
|
||||||
|
* 5 Zero bytes read, end of file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
bin_sysread(char *nam, char **args, Options ops, int func)
|
||||||
|
{
|
||||||
|
int infd = 0, outfd = -1, bufsize = SYSREAD_BUFSIZE, count;
|
||||||
|
char *outvar = NULL, *countvar = NULL, *inbuf;
|
||||||
|
|
||||||
|
/* -i: input file descriptor if not stdin */
|
||||||
|
if (OPT_ISSET(ops, 'i')) {
|
||||||
|
infd = getposint(OPT_ARG(ops, 'i'), nam);
|
||||||
|
if (infd < 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -o: output file descriptor, else store in REPLY */
|
||||||
|
if (OPT_ISSET(ops, 'o')) {
|
||||||
|
if (*args) {
|
||||||
|
zwarnnam(nam, "no argument allowed with -o", NULL, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
outfd = getposint(OPT_ARG(ops, 'o'), nam);
|
||||||
|
if (outfd < 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -s: buffer size if not default SYSREAD_BUFSIZE */
|
||||||
|
if (OPT_ISSET(ops, 's')) {
|
||||||
|
bufsize = getposint(OPT_ARG(ops, 's'), nam);
|
||||||
|
if (bufsize < 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -c: name of variable to store count of transferred bytes */
|
||||||
|
if (OPT_ISSET(ops, 'c')) {
|
||||||
|
countvar = OPT_ARG(ops, 'c');
|
||||||
|
if (!isident(countvar)) {
|
||||||
|
zwarnnam(nam, "not an identifier: %s", countvar, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*args) {
|
||||||
|
/*
|
||||||
|
* Variable in which to store result if doing a plain read.
|
||||||
|
* Default variable if not specified is REPLY.
|
||||||
|
* If writing, only stuff we couldn't write is stored here,
|
||||||
|
* no default in that case (we just discard it if no variable).
|
||||||
|
*/
|
||||||
|
outvar = *args;
|
||||||
|
if (!isident(outvar)) {
|
||||||
|
zwarnnam(nam, "not an identifier: %s", outvar, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inbuf = zhalloc(bufsize);
|
||||||
|
|
||||||
|
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
|
||||||
|
/* -t: timeout */
|
||||||
|
if (OPT_ISSET(ops, 't'))
|
||||||
|
{
|
||||||
|
# ifdef HAVE_POLL
|
||||||
|
struct pollfd poll_fd;
|
||||||
|
mnumber to_mn;
|
||||||
|
int to_int, ret;
|
||||||
|
|
||||||
|
poll_fd.fd = infd;
|
||||||
|
poll_fd.events = POLLIN;
|
||||||
|
|
||||||
|
to_mn = matheval(OPT_ARG(ops, 't'));
|
||||||
|
if (errflag)
|
||||||
|
return 1;
|
||||||
|
if (to_mn.type == MN_FLOAT)
|
||||||
|
to_int = (int) (1000 * to_mn.u.d);
|
||||||
|
else
|
||||||
|
to_int = 1000 * (int)to_mn.u.l;
|
||||||
|
|
||||||
|
while ((ret = poll(&poll_fd, 1, to_int)) < 0) {
|
||||||
|
if (errno != EINTR || errflag || retflag || breaks || contflag)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret <= 0) {
|
||||||
|
/* treat non-timeout error as error on read */
|
||||||
|
return ret ? 2 : 4;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
/* using select */
|
||||||
|
struct timeval select_tv;
|
||||||
|
fd_set fds;
|
||||||
|
mnumber to_mn;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(infd, &fds);
|
||||||
|
to_mn = matheval(OPT_ARG(ops, 't'));
|
||||||
|
if (errflag)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (to_mn.type == MN_FLOAT) {
|
||||||
|
select_tv.tv_sec = (int) to_mn.u.d;
|
||||||
|
select_tv.tv_usec =
|
||||||
|
(int) ((to_mn.u.d - select_tv.tv_sec) * 1e6);
|
||||||
|
} else {
|
||||||
|
select_tv.tv_sec = (int) to_mn.u.l;
|
||||||
|
select_tv.tv_usec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ret = select(infd+1, (SELECT_ARG_2_T) &fds,
|
||||||
|
NULL, NULL,&select_tv)) < 1) {
|
||||||
|
if (errno != EINTR || errflag || retflag || breaks || contflag)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret <= 0) {
|
||||||
|
/* treat non-timeout error as error on read */
|
||||||
|
return ret ? 2 : 4;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while ((count = read(infd, inbuf, bufsize)) < 0) {
|
||||||
|
if (errno != EINTR || errflag || retflag || breaks || contflag)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (countvar)
|
||||||
|
setiparam(countvar, count);
|
||||||
|
if (count < 0)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (outfd >= 0) {
|
||||||
|
if (!count)
|
||||||
|
return 5;
|
||||||
|
while (count > 0) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = write(outfd, inbuf, count);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR && !errflag &&
|
||||||
|
!retflag && !breaks && !contflag)
|
||||||
|
continue;
|
||||||
|
if (outvar)
|
||||||
|
setsparam(outvar, metafy(inbuf, count, META_DUP));
|
||||||
|
if (countvar)
|
||||||
|
setiparam(countvar, count);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
inbuf += ret;
|
||||||
|
count -= ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outvar)
|
||||||
|
outvar = "REPLY";
|
||||||
|
/* do this even if we read zero bytes */
|
||||||
|
setsparam(outvar, metafy(inbuf, count, META_DUP));
|
||||||
|
|
||||||
|
return count ? 0 : 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return values of bin_syswrite:
|
||||||
|
* 0 Successfully written
|
||||||
|
* 1 Error in parameters to command
|
||||||
|
* 2 Error on write, ERRNO set by system
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
bin_syswrite(char *nam, char **args, Options ops, int func)
|
||||||
|
{
|
||||||
|
int outfd = 1, len, count, totcount;
|
||||||
|
char *countvar = NULL;
|
||||||
|
|
||||||
|
/* -o: output file descriptor if not stdout */
|
||||||
|
if (OPT_ISSET(ops, 'o')) {
|
||||||
|
outfd = getposint(OPT_ARG(ops, 'o'), nam);
|
||||||
|
if (outfd < 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -c: variable in which to store count of bytes written */
|
||||||
|
if (OPT_ISSET(ops, 'c')) {
|
||||||
|
countvar = OPT_ARG(ops, 'c');
|
||||||
|
if (!isident(countvar)) {
|
||||||
|
zwarnnam(nam, "not an identifier: %s", countvar, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
totcount = 0;
|
||||||
|
unmetafy(*args, &len);
|
||||||
|
while (len) {
|
||||||
|
while ((count = write(outfd, *args, len)) < 0) {
|
||||||
|
if (errno != EINTR || errflag || retflag || breaks || contflag)
|
||||||
|
{
|
||||||
|
if (countvar)
|
||||||
|
setiparam(countvar, totcount);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*args += count;
|
||||||
|
totcount += count;
|
||||||
|
len -= count;
|
||||||
|
}
|
||||||
|
if (countvar)
|
||||||
|
setiparam(countvar, totcount);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return values of bin_syserror:
|
||||||
|
* 0 Successfully processed error
|
||||||
|
* (although if the number was invalid the string
|
||||||
|
* may not be useful)
|
||||||
|
* 1 Error in parameters
|
||||||
|
* 2 Name of error not recognised.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static int
|
||||||
|
bin_syserror(char *nam, char **args, Options ops, int func)
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
char *errvar = NULL, *msg, *pfx = "", *str;
|
||||||
|
|
||||||
|
/* variable in which to write error message */
|
||||||
|
if (OPT_ISSET(ops, 'e')) {
|
||||||
|
errvar = OPT_ARG(ops, 'e');
|
||||||
|
if (!isident(errvar)) {
|
||||||
|
zwarnnam(nam, "not an identifier: %s", errvar, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* prefix for error message */
|
||||||
|
if (OPT_ISSET(ops, 'p'))
|
||||||
|
pfx = OPT_ARG(ops, 'p');
|
||||||
|
|
||||||
|
if (!*args)
|
||||||
|
num = errno;
|
||||||
|
else {
|
||||||
|
char *ptr = *args;
|
||||||
|
while (*ptr && idigit(*ptr))
|
||||||
|
ptr++;
|
||||||
|
if (!*ptr && ptr > *args)
|
||||||
|
num = atoi(*args);
|
||||||
|
else {
|
||||||
|
const char **eptr;
|
||||||
|
for (eptr = sys_errnames; *eptr; eptr++) {
|
||||||
|
if (!strcmp(*eptr, *args)) {
|
||||||
|
num = (eptr - sys_errnames) + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!*eptr)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = strerror(num);
|
||||||
|
if (errvar) {
|
||||||
|
str = (char *)zalloc(strlen(msg) + strlen(pfx) + 1);
|
||||||
|
sprintf(str, "%s%s", pfx, msg);
|
||||||
|
setsparam(errvar, str);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s%s\n", pfx, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Functions for the errnos special parameter. */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static char **
|
||||||
|
errnosgetfn(Param pm)
|
||||||
|
{
|
||||||
|
/* arrdup etc. should really take const pointers as arguments */
|
||||||
|
return arrdup((char **)sys_errnames);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct builtin bintab[] = {
|
||||||
|
BUILTIN("syserror", 0, bin_syserror, 0, 1, 0, "e:p:", NULL),
|
||||||
|
BUILTIN("sysread", 0, bin_sysread, 0, 1, 0, "c:i:o:s:t:", NULL),
|
||||||
|
BUILTIN("syswrite", 0, bin_syswrite, 1, 1, 0, "c:o:", NULL),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* The load/unload routines required by the zsh library interface */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
setup_(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
static void
|
||||||
|
tidyparam(Param pm)
|
||||||
|
{
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
pm->flags &= ~PM_READONLY;
|
||||||
|
unsetparam_pm(pm, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_(Module m)
|
||||||
|
{
|
||||||
|
Param pm_nos;
|
||||||
|
|
||||||
|
/* this takes care of an autoload on errnos */
|
||||||
|
unsetparam("errnos");
|
||||||
|
if (!(pm_nos = createparam("errnos", PM_ARRAY|PM_SPECIAL|PM_READONLY|
|
||||||
|
PM_HIDE|PM_HIDEVAL|PM_REMOVABLE)))
|
||||||
|
return 1;
|
||||||
|
pm_nos->gets.afn = errnosgetfn;
|
||||||
|
|
||||||
|
if (!addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab))) {
|
||||||
|
tidyparam(pm_nos);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
cleanup_(Module m)
|
||||||
|
{
|
||||||
|
tidyparam((Param)paramtab->getnode(paramtab, "errnos"));
|
||||||
|
|
||||||
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
27
Src/Modules/system.mdd
Normal file
27
Src/Modules/system.mdd
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
name=zsh/system
|
||||||
|
link=dynamic
|
||||||
|
load=no
|
||||||
|
|
||||||
|
autobins="sysread syswrite syserror"
|
||||||
|
|
||||||
|
autoparams="errnos"
|
||||||
|
|
||||||
|
objects="system.o errnames.o"
|
||||||
|
|
||||||
|
headers="errcount.h"
|
||||||
|
|
||||||
|
:<<\Make
|
||||||
|
errnames.c: errnames1.awk errnames2.awk $(dir_top)/config.h @ERRNO_H@
|
||||||
|
if [ x@ERRNO_H@ = x ]; then \
|
||||||
|
touch errtmp.out; \
|
||||||
|
else \
|
||||||
|
$(AWK) -f $(sdir)/errnames1.awk @ERRNO_H@ >errtmp.c; \
|
||||||
|
$(CPP) errtmp.c >errtmp.out; \
|
||||||
|
fi
|
||||||
|
$(AWK) -f $(sdir)/errnames2.awk errtmp.out > $@
|
||||||
|
rm -f errtmp.c errtmp.out
|
||||||
|
|
||||||
|
errcount.h: errnames.c
|
||||||
|
grep 'define.*ERRCOUNT' errnames.c > $@
|
||||||
|
Make
|
||||||
|
|
||||||
33
zshconfig.ac
33
zshconfig.ac
|
|
@ -1117,6 +1117,39 @@ zsh_cv_path_signal_h=$SIGNAL_H
|
||||||
SIGNAL_H=$zsh_cv_path_signal_h
|
SIGNAL_H=$zsh_cv_path_signal_h
|
||||||
AC_SUBST(SIGNAL_H)dnl
|
AC_SUBST(SIGNAL_H)dnl
|
||||||
|
|
||||||
|
dnl Where are error names located? Needed as input for errnames1.awk
|
||||||
|
AC_CACHE_CHECK(where error names are located, zsh_cv_path_errno_h,
|
||||||
|
[dnl Look at the output from the preprocessor.
|
||||||
|
dnl We should get lines of the form `# 1 "/usr/include/errno.h"'
|
||||||
|
dnl The following assumes the real definitions are in a file which
|
||||||
|
dnl contains the name `err'; we could relax this if necessary,
|
||||||
|
dnl but then you can get a rather long list of files to test.
|
||||||
|
dnl The backslash substitution is to persuade cygwin to cough up
|
||||||
|
dnl slashes rather than doubled backslashes in the path.
|
||||||
|
echo "#include <errno.h>" > nametmp.c
|
||||||
|
errfile_list="`$CPP nametmp.c |
|
||||||
|
sed -n 's/^#[ ].*\"\(.*\)\"/\1/p' |
|
||||||
|
sed 's/\\\\\\\\/\//g' |
|
||||||
|
$AWK '{ if (\$1 ~ \"err\") files[[\$1]] = \$1 }
|
||||||
|
END { for (var in files) print var }'`"
|
||||||
|
rm -f nametmp.c
|
||||||
|
for ERRNO_H in $errfile_list /dev/null
|
||||||
|
do
|
||||||
|
dnl Try to make sure it doesn't get confused by files that don't
|
||||||
|
dnl have real error definitions in. Count definitions to make sure.
|
||||||
|
nerrs=`test -f $ERRNO_H && \
|
||||||
|
grep '#[ ]*define[ ][ ]*E[0-9A-Z]*[ ]*[0-9][0-9]*' $ERRNO_H | \
|
||||||
|
wc -l | sed 's/[ ]//g'`
|
||||||
|
test "x$nerrs" != x && test "$nerrs" -ge 7 && break
|
||||||
|
done
|
||||||
|
if test $ERRNO_H = "/dev/null"; then
|
||||||
|
AC_MSG_ERROR(ERROR MACROS NOT FOUND: please report to developers)
|
||||||
|
fi
|
||||||
|
zsh_cv_path_errno_h=$ERRNO_H
|
||||||
|
])
|
||||||
|
ERRNO_H=$zsh_cv_path_errno_h
|
||||||
|
AC_SUBST(ERRNO_H)dnl
|
||||||
|
|
||||||
dnl -----------------------------------------------------
|
dnl -----------------------------------------------------
|
||||||
dnl Look for the file containing the RLIMIT_* definitions
|
dnl Look for the file containing the RLIMIT_* definitions
|
||||||
dnl -----------------------------------------------------
|
dnl -----------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue