bash-5.2-alpha release

This commit is contained in:
Chet Ramey
2022-01-20 15:06:05 -05:00
parent 9439ce094c
commit 4491c03014
409 changed files with 63491 additions and 54851 deletions
+8 -3
View File
@@ -58,6 +58,7 @@ host_os = @host_os@
host_cpu = @host_cpu@
host_vendor = @host_vendor@
STYLE_CFLAGS = @STYLE_CFLAGS@
CFLAGS = @CFLAGS@
LOCAL_CFLAGS = @LOCAL_CFLAGS@
DEFS = @DEFS@
@@ -76,7 +77,7 @@ INTL_BUILDDIR = ${LIBBUILD}/intl
INTL_INC = @INTL_INC@
LIBINTL_H = @LIBINTL_H@
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(CFLAGS)
CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(CFLAGS) $(STYLE_CFLAGS)
#
# These values are generated for configure by ${topdir}/support/shobj-conf.
@@ -103,8 +104,8 @@ INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins -I${srcdir} \
ALLPROG = print truefalse sleep finfo logname basename dirname fdflags \
tty pathchk tee head mkdir rmdir mkfifo mktemp printenv id whoami \
uname sync push ln unlink realpath strftime mypid setpgid seq rm \
accept csv cut
OTHERPROG = necho hello cat pushd stat asort
accept csv cut stat getconf
OTHERPROG = necho hello cat pushd asort
all: $(SHOBJ_STATUS)
@@ -191,6 +192,9 @@ head: head.o
printenv: printenv.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
getconf: getconf.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
id: id.o
$(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
@@ -294,6 +298,7 @@ truefalse.o: truefalse.c
accept.o: accept.c
sleep.o: sleep.c
finfo.o: finfo.c
getconf.o: getconf.c getconf.h
logname.o: logname.c
basename.o: basename.c
dirname.o: dirname.c
+10 -4
View File
@@ -1,11 +1,13 @@
Some examples of ready-to-dynamic-load builtins. Most of the
examples given are reimplementations of standard commands whose
execution time is dominated by process startup time. The
execution time is dominated by process startup time. Some
exceptions are sleep, which allows you to sleep for fractions
of a second, finfo, which provides access to the rest of the
elements of the `stat' structure that `test' doesn't let you
see, and pushd/popd/dirs, which allows you to compile them out
of the shell.
see, csv, which allows you to manipulate data from comma-separated
values files, fdflags, which lets you change the flags associated
with one of the shell's file descriptors, and pushd/popd/dirs, which
allows you to compile them out of the shell.
All of the new builtins in ksh93 that bash didn't already have
are included here, as is the ksh `print' builtin.
@@ -40,6 +42,8 @@ without having to search for the right CFLAGS and LDFLAGS.
basename.c Return non-directory portion of pathname.
cat.c cat(1) replacement with no options - the way cat was intended.
csv.c Process a line of csv data and store it in an indexed array.
cut.c Cut out selected portions of each line of a file.
dirname.c Return directory portion of pathname.
fdflags.c Change the flag associated with one of bash's open file descriptors.
finfo.c Print file info.
@@ -52,7 +56,9 @@ logname.c Print login name of current user.
Makefile.in Simple makefile for the sample loadable builtins.
Makefile.inc.in Sample makefile to use for loadable builtin development.
mkdir.c Make directories.
mypid.c Add $MYPID variable, demonstrate use of unload hook functio.n
mkfifo.c Create named pipes.
mktemp.c Make unique temporary file name.
mypid.c Add $MYPID variable, demonstrate use of unload hook function.
necho.c echo without options or argument interpretation.
pathchk.c Check pathnames for validity and portability.
print.c Loadable ksh-93 style print builtin.
+27 -16
View File
@@ -30,6 +30,7 @@
#include "bashtypes.h"
#include <errno.h>
#include <time.h>
#include <limits.h>
#include "typemax.h"
#include <sys/socket.h>
@@ -44,11 +45,10 @@ int
accept_builtin (list)
WORD_LIST *list;
{
WORD_LIST *l;
SHELL_VAR *v;
intmax_t iport;
int opt;
char *tmoutarg, *fdvar, *rhostvar, *rhost;
char *tmoutarg, *fdvar, *rhostvar, *rhost, *bindaddr;
unsigned short uport;
int servsock, clisock;
struct sockaddr_in server, client;
@@ -56,13 +56,16 @@ accept_builtin (list)
struct timeval timeval;
struct linger linger = { 0, 0 };
rhostvar = tmoutarg = fdvar = rhost = (char *)NULL;
rhostvar = tmoutarg = fdvar = rhost = bindaddr = (char *)NULL;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "r:t:v:")) != -1)
while ((opt = internal_getopt (list, "b:r:t:v:")) != -1)
{
switch (opt)
{
case 'b':
bindaddr = list_optarg;
break;
case 'r':
rhostvar = list_optarg;
break;
@@ -125,7 +128,17 @@ accept_builtin (list)
memset ((char *)&server, 0, sizeof (server));
server.sin_family = AF_INET;
server.sin_port = htons(uport);
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_addr.s_addr = bindaddr ? inet_addr (bindaddr) : htonl(INADDR_ANY);
if (server.sin_addr.s_addr == INADDR_NONE)
{
builtin_error ("invalid address: %s", strerror (errno));
return (EXECUTION_FAILURE);
}
opt = 1;
setsockopt (servsock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt));
setsockopt (servsock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof (linger));
if (bind (servsock, (struct sockaddr *)&server, sizeof (server)) < 0)
{
@@ -134,10 +147,6 @@ accept_builtin (list)
return (EXECUTION_FAILURE);
}
opt = 1;
setsockopt (servsock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof (opt));
setsockopt (servsock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof (linger));
if (listen (servsock, 1) < 0)
{
builtin_error ("listen failure: %s", strerror (errno));
@@ -154,12 +163,12 @@ accept_builtin (list)
opt = select (servsock+1, &iofds, 0, 0, &timeval);
if (opt < 0)
builtin_error ("select failure: %s", strerror (errno));
builtin_error ("select failure: %s", strerror (errno));
if (opt <= 0)
{
close (servsock);
return (EXECUTION_FAILURE);
}
{
close (servsock);
return (EXECUTION_FAILURE);
}
}
clientlen = sizeof (client);
@@ -193,7 +202,7 @@ accept_bind_variable (varname, intval)
char ibuf[INT_STRLEN_BOUND (int) + 1], *p;
p = fmtulong (intval, 10, ibuf, sizeof (ibuf), 0);
v = builtin_bind_variable (varname, p, 0);
v = builtin_bind_variable (varname, p, 0); /* XXX */
if (v == 0 || readonly_p (v) || noassign_p (v))
builtin_error ("%s: cannot set variable", varname);
return (v != 0);
@@ -205,6 +214,8 @@ char *accept_doc[] = {
"This builtin allows a bash script to act as a TCP/IP server.",
"",
"Options, if supplied, have the following meanings:",
" -b address use ADDRESS as the IP address to listen on; the",
" default is INADDR_ANY",
" -t timeout wait TIMEOUT seconds for a connection. TIMEOUT may",
" be a decimal number including a fractional portion",
" -v varname store the numeric file descriptor of the connected",
@@ -229,6 +240,6 @@ struct builtin accept_struct = {
accept_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
accept_doc, /* array of long documentation strings. */
"accept [-t timeout] [-v varname] [-r addrvar ] port", /* usage synopsis; becomes short_doc */
"accept [-b address] [-t timeout] [-v varname] [-r addrvar ] port", /* usage synopsis; becomes short_doc */
0 /* reserved for internal use */
};
+19 -3
View File
@@ -36,13 +36,25 @@ extern char *strerror ();
extern char **make_builtin_argv ();
static int
fcopy(fd)
fcopy(fd, fn)
int fd;
char *fn;
{
char buf[1024], *s;
int n, w, e;
while (n = read(fd, buf, sizeof (buf))) {
if (n < 0) {
e = errno;
write(2, "cat: read error: ", 18);
write(2, fn, strlen(fn));
write(2, ": ", 2);
s = strerror(e);
write(2, s, strlen(s));
write(2, "\n", 1);
return 1;
}
QUIT;
w = write(1, buf, n);
if (w != n) {
e = errno;
@@ -52,6 +64,7 @@ int fd;
write(2, "\n", 1);
return 1;
}
QUIT;
}
return 0;
}
@@ -65,9 +78,10 @@ char **argv;
char *s;
if (argc == 1)
return (fcopy(0));
return (fcopy(0, "standard input"));
for (i = r = 1; i < argc; i++) {
QUIT;
if (argv[i][0] == '-' && argv[i][1] == '\0')
fd = 0;
else {
@@ -82,10 +96,11 @@ char **argv;
continue;
}
}
r = fcopy(fd);
r = fcopy(fd, argv[i]);
if (fd != 0)
close(fd);
}
QUIT;
return (r);
}
@@ -97,6 +112,7 @@ WORD_LIST *list;
int c, r;
v = make_builtin_argv(list, &c);
QUIT;
r = cat_main(c, v);
free(v);
+4
View File
@@ -415,10 +415,14 @@ cutfile (v, list, ops)
#endif
while ((n = zgetline (fd, &line, &llen, '\n', unbuffered_read)) != -1)
{
QUIT;
cutline (v, line, ops); /* can modify line */
}
if (fd > 0)
close (fd);
QUIT;
if (l)
l = l->next;
}
File diff suppressed because it is too large Load Diff
+136
View File
@@ -0,0 +1,136 @@
/*
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* getconf.h -- replacement definitions for ones the system doesn't provide
and don't appear in <typemax.h> */
#ifndef _GETCONF_H
#define _GETCONF_H
/* Some systems do not define these; use POSIX.2 minimum recommended values. */
#ifndef _POSIX2_COLL_WEIGHTS_MAX
# define _POSIX2_COLL_WEIGHTS_MAX 2
#endif
/* If we're on a posix system, but the system doesn't define the necessary
constants, use posix.1 minimum values. */
#if defined (_POSIX_VERSION)
#ifndef _POSIX_ARG_MAX
# define _POSIX_ARG_MAX 4096
#endif
#ifndef _POSIX_CHILD_MAX
# define _POSIX_CHILD_MAX 6
#endif
#ifndef _POSIX_LINK_MAX
# define _POSIX_LINK_MAX 8
#endif
#ifndef _POSIX_MAX_CANON
# define _POSIX_MAX_CANON 255
#endif
#ifndef _POSIX_MAX_INPUT
# define _POSIX_MAX_INPUT 255
#endif
#ifndef _POSIX_NAME_MAX
# define _POSIX_NAME_MAX 14
#endif
#ifndef _POSIX_NGROUPS_MAX
# define _POSIX_NGROUPS_MAX 0
#endif
#ifndef _POSIX_OPEN_MAX
# define _POSIX_OPEN_MAX 16
#endif
#ifndef _POSIX_PATH_MAX
# define _POSIX_PATH_MAX 255
#endif
#ifndef _POSIX_PIPE_BUF
# define _POSIX_PIPE_BUF 512
#endif
#ifndef _POSIX_SSIZE_MAX
# define _POSIX_SSIZE_MAX 32767
#endif
#ifndef _POSIX_STREAM_MAX
# define _POSIX_STREAM_MAX 8
#endif
#ifndef _POSIX_TZNAME_MAX
# define _POSIX_TZNAME_MAX 3
#endif
#ifndef _POSIX2_BC_BASE_MAX
# define _POSIX2_BC_BASE_MAX 99
#endif
#ifndef _POSIX2_BC_DIM_MAX
# define _POSIX2_BC_DIM_MAX 2048
#endif
#ifndef _POSIX2_BC_SCALE_MAX
# define _POSIX2_BC_SCALE_MAX 99
#endif
#ifndef _POSIX2_BC_STRING_MAX
# define _POSIX2_BC_STRING_MAX 1000
#endif
#ifndef _POSIX2_EQUIV_CLASS_MAX
# define _POSIX2_EQUIV_CLASS_MAX 2
#endif
#ifndef _POSIX2_EXPR_NEST_MAX
# define _POSIX2_EXPR_NEST_MAX 32
#endif
#ifndef _POSIX2_LINE_MAX
# define _POSIX2_LINE_MAX 2048
#endif
#ifndef _POSIX2_RE_DUP_MAX
# define _POSIX2_RE_DUP_MAX 255
#endif
#endif /* _POSIX_VERSION */
/* ANSI/ISO C, POSIX.1-200x, XPG 4.2, and C language type limits.
Defined only if the system include files and <typemax.h> don't. */
#ifndef CHAR_MAX
# define CHAR_MAX 127
#endif
#ifndef CHAR_MIN
# define CHAR_MIN -128
#endif
#ifndef SCHAR_MAX
# define SCHAR_MAX 127
#endif
#ifndef SCHAR_MIN
# define SCHAR_MIN -128
#endif
#ifndef INT_BIT
# define INT_BIT (sizeof (int) * CHAR_BIT)
#endif
#ifndef LONG_BIT
# define LONG_BIT (sizeof (long int) * CHAR_BIT)
#endif
#ifndef WORD_BIT
# define WORD_BIT (sizeof (int) * CHAR_BIT)
#endif
#if !defined (PRIdMAX)
# if HAVE_LONG_LONG
# define PRIdMAX "lld"
# else
# define PRIdMAX "ld"
# endif
#endif
#endif /* _GETCONF_H */
+3
View File
@@ -79,11 +79,13 @@ file_head (fp, cnt)
{
while ((ch = getc (fp)) != EOF)
{
QUIT;
if (putchar (ch) == EOF)
{
builtin_error ("write error: %s", strerror (errno));
return EXECUTION_FAILURE;
}
QUIT;
if (ch == '\n')
break;
}
@@ -141,6 +143,7 @@ head_builtin (list)
printf ("%s==> %s <==\n", opt ? "" : "\n", l->word->word);
opt = 0;
}
QUIT;
rval = file_head (fp, nline);
fclose (fp);
}
+80 -19
View File
@@ -1,10 +1,13 @@
/*
* realpath -- canonicalize pathnames, resolving symlinks
*
* usage: realpath [-csv] pathname [pathname...]
* usage: realpath [-csv] [-a name] pathname [pathname...]
*
* options: -c check whether or not each resolved path exists
* options: -a name assign each canonicalized pathname to indexed array
* variable NAME
* -c check whether or not each resolved path exists
* -s no output, exit status determines whether path is valid
* -S strip . and .. from the pathname only, no symlink resolution
* -v produce verbose output
*
*
@@ -19,7 +22,7 @@
*/
/*
Copyright (C) 1999-2009 Free Software Foundation, Inc.
Copyright (C) 1999-2009,2021 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
@@ -61,28 +64,46 @@ extern int errno;
extern char *sh_realpath();
int
realpath_builtin(list)
WORD_LIST *list;
realpath_builtin(WORD_LIST *list)
{
int opt, cflag, vflag, sflag, es;
char *r, realbuf[PATH_MAX], *p;
int opt, cflag, vflag, sflag, Sflag, aflag, es;
char *r, realbuf[PATH_MAX], *p, *newpath;
struct stat sb;
#if defined (ARRAY_VARS)
arrayind_t ind;
char *aname;
SHELL_VAR *v;
#endif
if (list == 0) {
builtin_usage();
return (EX_USAGE);
}
vflag = cflag = sflag = 0;
vflag = cflag = sflag = aflag = Sflag = 0;
#if defined (ARRAY_VARS)
aname = NULL;
v = NULL;
ind = 0;
#endif
reset_internal_getopt();
while ((opt = internal_getopt (list, "csv")) != -1) {
while ((opt = internal_getopt (list, "a:Scsv")) != -1) {
switch (opt) {
#if defined (ARRAY_VARS)
case 'a':
aflag = 1;
aname = list_optarg;
break;
#endif
case 'c':
cflag = 1;
break;
case 's':
sflag = 1;
break;
case 'S':
Sflag = 1;
break;
case 'v':
vflag = 1;
break;
@@ -100,26 +121,62 @@ WORD_LIST *list;
return (EX_USAGE);
}
#if defined (ARRAY_VARS)
if (aflag && legal_identifier (aname) == 0) {
sh_invalidid(aname);
return (EXECUTION_FAILURE);
}
if (aname && builtin_unbind_variable (aname) == -2)
return (EXECUTION_FAILURE);
if (aname) {
v = find_or_make_array_variable (aname, 1);
if (v == 0 || readonly_p (v) || noassign_p (v)) {
if (v && readonly_p (v))
err_readonly (aname);
return (EXECUTION_FAILURE);
} else if (array_p (v) == 0) {
builtin_error ("%s: not an indexed array", aname);
return (EXECUTION_FAILURE);
}
if (invisible_p (v))
VUNSETATTR (v, att_invisible);
array_flush (array_cell (v));
}
#endif
for (es = EXECUTION_SUCCESS; list; list = list->next) {
p = list->word->word;
r = sh_realpath(p, realbuf);
if (Sflag) {
/* sh_canonpath doesn't convert to absolute pathnames */
newpath = make_absolute(p, get_string_value("PWD"));
r = sh_canonpath(newpath, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
free(newpath);
} else
r = sh_realpath(p, realbuf);
if (r == 0) {
es = EXECUTION_FAILURE;
if (sflag == 0)
builtin_error("%s: cannot resolve: %s", p, strerror(errno));
continue;
}
if (cflag && (stat(realbuf, &sb) < 0)) {
if (cflag && (stat(r, &sb) < 0)) {
es = EXECUTION_FAILURE;
if (sflag == 0)
builtin_error("%s: %s", p, strerror(errno));
continue;
}
if (sflag == 0) {
if (vflag)
printf ("%s -> ", p);
printf("%s\n", realbuf);
if (aflag) {
bind_array_element (v, ind, r, 0);
ind++;
} else {
if (vflag)
printf ("%s -> ", p);
printf("%s\n", r);
}
}
if (Sflag)
free (r);
}
return es;
}
@@ -128,10 +185,14 @@ char *realpath_doc[] = {
"Display pathname in canonical form.",
"",
"Display the canonicalized version of each PATHNAME argument, resolving",
"symbolic links. The -c option checks whether or not each resolved name",
"exists. The -s option produces no output; the exit status determines the",
"validity of each PATHNAME. The -v option produces verbose output. The",
"exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
"symbolic links.",
"If the -S option is supplied, canonicalize . and .. pathname components",
"without resolving symbolic links.",
"The -c option checks whether or not each resolved name exists.",
"The -s option produces no output; the exit status determines the",
"validity of each PATHNAME.",
"The -v option produces verbose output.",
"The exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
(char *)NULL
};
@@ -140,6 +201,6 @@ struct builtin realpath_struct = {
realpath_builtin, /* function implementing the builtin */
BUILTIN_ENABLED, /* initial flags for builtin */
realpath_doc, /* array of long documentation strings */
"realpath [-csv] pathname [pathname...]", /* usage synopsis */
"realpath [-Scsv] pathname [pathname...]", /* usage synopsis */
0 /* reserved for internal use */
};
+5 -1
View File
@@ -59,7 +59,8 @@ _remove_directory(const char *dirname)
char *fname;
int fnsize;
#endif
QUIT;
if (*dp->d_name == '.' && (dp->d_name[1] == 0 || (dp->d_name[1] == '.' && dp->d_name[2] == 0)))
continue;
@@ -76,6 +77,7 @@ _remove_directory(const char *dirname)
#ifndef __GNUC__
free (fname);
#endif
QUIT;
}
closedir(dir);
@@ -98,6 +100,7 @@ rm_file(const char *fname)
if (unlink (fname) == 0)
return 0;
QUIT;
/* If FNAME is a directory glibc returns EISDIR but correct POSIX value
would be EPERM. If we get that error and FNAME is a directory and -r
was supplied, recursively remove the directory and its contents */
@@ -155,6 +158,7 @@ rm_builtin (list)
for (l = list; l; l = l->next)
{
QUIT;
if (rm_file(l->word->word) && force == 0)
rval = EXECUTION_FAILURE;
}
+88 -10
View File
@@ -2,10 +2,12 @@
* sleep -- sleep for fractions of a second
*
* usage: sleep seconds[.fraction]
*
* as an extension, we support the GNU time interval format (2m20s)
*/
/*
Copyright (C) 1999-2020 Free Software Foundation, Inc.
Copyright (C) 1999-2021 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
@@ -44,13 +46,80 @@
#include <stdio.h>
#include "chartypes.h"
#include "shell.h"
#include "builtins.h"
#include "common.h"
#include "loadables.h"
#define S_SEC 1
#define S_MIN (60*S_SEC)
#define S_HOUR (60*S_MIN)
#define S_DAY (24*S_HOUR)
static int
parse_gnutimefmt (char *string, long *sp, long *up)
{
int c, r;
char *s, *ep;
long tsec, tusec, accumsec, accumusec, t;
int mult;
tsec = tusec = 0;
accumsec = accumusec = 0;
mult = 1;
for (s = string; s && *s; s++) {
r = uconvert(s, &accumsec, &accumusec, &ep);
if (r == 0 && *ep == 0)
return r;
c = *ep;
mult = 1;
switch (c) {
case '\0':
case 's':
mult = S_SEC;
break;
case 'm':
mult = S_MIN;
break;
case 'h':
mult = S_HOUR;
break;
case 'd':
mult = S_DAY;
break;
default:
return 0;
}
/* multiply the accumulated value by the multiplier */
t = accumusec * mult;
accumsec = accumsec * mult + (t / 1000000);
accumusec = t % 1000000;
/* add to running total */
tsec += accumsec;
tusec += accumusec;
if (tusec >= 1000000) {
tsec++;
tusec -= 1000000;
}
/* reset and continue */
accumsec = accumusec = 0;
mult = 1;
if (c == 0)
break;
s = ep;
}
if (sp)
*sp = tsec;
if (up)
*up = tusec;
return 1;
}
int
sleep_builtin (list)
WORD_LIST *list;
sleep_builtin (WORD_LIST *list)
{
long sec, usec;
char *ep;
@@ -72,14 +141,22 @@ WORD_LIST *list;
}
r = uconvert(list->word->word, &sec, &usec, &ep);
/* Maybe postprocess conversion failures here based on EP */
/*
* Maybe postprocess conversion failures here based on EP
*
* A heuristic: if the conversion failed, but the argument appears to
* contain a GNU-like interval specifier (e.g. "1m30s"), try to parse
* it. If we can't, return the right exit code to tell
* execute_builtin to try and execute a disk command instead.
*/
if (r == 0 && (strchr ("dhms", *ep) || strpbrk (list->word->word, "dhms")))
r = parse_gnutimefmt (list->word->word, &sec, &usec);
if (r) {
if (r) {
fsleep(sec, usec);
QUIT;
return(EXECUTION_SUCCESS);
}
}
builtin_error("%s: bad sleep interval", list->word->word);
return (EXECUTION_FAILURE);
}
@@ -88,6 +165,7 @@ static char *sleep_doc[] = {
"Suspend execution for specified period.",
""
"sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.",
"As an extension, sleep accepts GNU-style time intervals (e.g., 2m30s).",
(char *)NULL
};
+40 -16
View File
@@ -72,6 +72,13 @@ static char *arraysubs[] =
0
};
#define DEFTIMEFMT "%a %b %e %k:%M:%S %Z %Y"
#ifndef TIMELEN_MAX
# define TIMELEN_MAX 128
#endif
static char *stattime (time_t, const char *);
static int
getstat (fname, flags, sp)
const char *fname;
@@ -253,24 +260,33 @@ statmode(mode)
}
static char *
stattime (t)
stattime (t, timefmt)
time_t t;
const char *timefmt;
{
char *tbuf, *ret;
const char *fmt;
size_t tlen;
struct tm *tm;
fmt = timefmt ? timefmt : DEFTIMEFMT;
tm = localtime (&t);
ret = xmalloc (TIMELEN_MAX);
tlen = strftime (ret, TIMELEN_MAX, fmt, tm);
if (tlen == 0)
tlen = strftime (ret, TIMELEN_MAX, DEFTIMEFMT, tm);
tbuf = ctime (&t);
tlen = strlen (tbuf);
ret = savestring (tbuf);
ret[tlen-1] = '\0';
return ret;
}
static char *
statval (which, fname, flags, sp)
statval (which, fname, flags, fmt, sp)
int which;
char *fname;
int flags;
char *fmt;
struct stat *sp;
{
int temp;
@@ -296,11 +312,11 @@ statval (which, fname, flags, sp)
case ST_SIZE:
return itos (sp->st_size);
case ST_ATIME:
return ((flags & 2) ? stattime (sp->st_atime) : itos (sp->st_atime));
return ((flags & 2) ? stattime (sp->st_atime, fmt) : itos (sp->st_atime));
case ST_MTIME:
return ((flags & 2) ? stattime (sp->st_mtime) : itos (sp->st_mtime));
return ((flags & 2) ? stattime (sp->st_mtime, fmt) : itos (sp->st_mtime));
case ST_CTIME:
return ((flags & 2) ? stattime (sp->st_ctime) : itos (sp->st_ctime));
return ((flags & 2) ? stattime (sp->st_ctime, fmt) : itos (sp->st_ctime));
case ST_BLKSIZE:
return itos (sp->st_blksize);
case ST_BLOCKS:
@@ -316,11 +332,12 @@ statval (which, fname, flags, sp)
}
static int
loadstat (vname, var, fname, flags, sp)
loadstat (vname, var, fname, flags, fmt, sp)
char *vname;
SHELL_VAR *var;
char *fname;
int flags;
char *fmt;
struct stat *sp;
{
int i;
@@ -330,7 +347,7 @@ loadstat (vname, var, fname, flags, sp)
for (i = 0; arraysubs[i]; i++)
{
key = savestring (arraysubs[i]);
value = statval (i, fname, flags, sp);
value = statval (i, fname, flags, fmt, sp);
v = bind_assoc_variable (var, vname, key, value, ASS_FORCE);
}
return 0;
@@ -341,15 +358,16 @@ stat_builtin (list)
WORD_LIST *list;
{
int opt, flags;
char *aname, *fname;
char *aname, *fname, *timefmt;
struct stat st;
SHELL_VAR *v;
aname = "STAT";
flags = 0;
timefmt = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "A:Ll")) != -1)
while ((opt = internal_getopt (list, "A:F:Ll")) != -1)
{
switch (opt)
{
@@ -362,6 +380,9 @@ stat_builtin (list)
case 'l':
flags |= 2;
break;
case 'F':
timefmt = list_optarg;
break;
CASE_HELPOPT;
default:
builtin_usage ();
@@ -391,7 +412,7 @@ stat_builtin (list)
builtin_error ("%s: cannot create variable", aname);
return (EXECUTION_FAILURE);
}
if (loadstat (aname, v, fname, flags, &st) < 0)
if (loadstat (aname, v, fname, flags, timefmt, &st) < 0)
{
builtin_error ("%s: cannot assign file status information", aname);
unbind_variable (aname);
@@ -412,8 +433,11 @@ char *stat_doc[] = {
"by the -A option. The default array name is STAT. If the -L",
"option is supplied, stat does not resolve symbolic links and",
"reports information about the link itself. The -l option results",
"in longer-form listings for some of the fields. The exit status is 0",
"unless the stat fails or assigning the array is unsuccessful.",
"in longer-form listings for some of the fields. When -l is used,",
"the -F option supplies a format string passed to strftime(3) to",
"display the file time information.",
"The exit status is 0 unless the stat fails or assigning the array",
"is unsuccessful.",
(char *)NULL
};
+5 -2
View File
@@ -3,7 +3,7 @@
/* See Makefile for compilation details. */
/*
Copyright (C) 1999-2009 Free Software Foundation, Inc.
Copyright (C) 1999-2021 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
@@ -121,6 +121,7 @@ tee_builtin (list)
fl = fl->next;
fl->next = (FLIST *)NULL;
}
QUIT;
}
while ((nr = read(0, buf, TEE_BUFSIZE)) > 0)
@@ -137,6 +138,7 @@ tee_builtin (list)
break;
}
bp += nw;
QUIT;
}
while (n -= nw);
}
@@ -156,7 +158,8 @@ tee_builtin (list)
tee_flist = tee_flist->next;
free (fl);
}
QUIT;
return (rval);
}
+2 -1
View File
@@ -3,7 +3,7 @@
/* See Makefile for compilation details. */
/*
Copyright (C) 1999-2009 Free Software Foundation, Inc.
Copyright (C) 1999-2021 Free Software Foundation, Inc.
This file is part of GNU Bash.
Bash is free software: you can redistribute it and/or modify
@@ -55,6 +55,7 @@ tty_builtin (list)
list = loptend;
t = ttyname (0);
QUIT;
if (sflag == 0)
puts (t ? t : "not a tty");
return (t ? EXECUTION_SUCCESS : EXECUTION_FAILURE);