diff options
Diffstat (limited to 'lib/sh')
37 files changed, 797 insertions, 184 deletions
diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in index 06917ba4..98064de5 100644 --- a/lib/sh/Makefile.in +++ b/lib/sh/Makefile.in @@ -2,7 +2,7 @@ # Makefile for the Bash library # # -# Copyright (C) 1998-2010 Free Software Foundation, Inc. +# Copyright (C) 1998-2020 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -93,7 +93,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \ wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \ casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c \ strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c \ - utf8.c + utf8.c random.c gettimeofday.c # The header files for this library. HSOURCES = @@ -108,7 +108,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \ fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \ fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \ input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o \ - utf8.o wcsnwidth.o ${LIBOBJS} + utf8.o random.o gettimeofday.o wcsnwidth.o ${LIBOBJS} SUPPORT = Makefile @@ -155,6 +155,7 @@ fnxform.o: fnxform.c fpurge.o: fpurge.c getcwd.o: getcwd.c getenv.o: getenv.c +gettimeofday.o: gettimeofday.c inet_aton.o: inet_aton.c input_avail.o: input_avail.c itos.o: itos.c @@ -170,6 +171,7 @@ netopen.o: netopen.c oslib.o: oslib.c pathcanon.o: pathcanon.c pathphys.o: pathphys.c +random.o: random.c rename.o: rename.c setlinebuf.o: setlinebuf.c shmatch.o: shmatch.c @@ -233,6 +235,7 @@ fnxform.o: ${BUILD_DIR}/config.h fpurge.o: ${BUILD_DIR}/config.h getcwd.o: ${BUILD_DIR}/config.h getenv.o: ${BUILD_DIR}/config.h +gettimeofday.o: ${BUILD_DIR}/config.h inet_aton.o: ${BUILD_DIR}/config.h input_avail.o: ${BUILD_DIR}/config.h itos.o: ${BUILD_DIR}/config.h @@ -248,6 +251,7 @@ netopen.o: ${BUILD_DIR}/config.h oslib.o: ${BUILD_DIR}/config.h pathcanon.o: ${BUILD_DIR}/config.h pathphys.o: ${BUILD_DIR}/config.h +random.o: ${BUILD_DIR}/config.h rename.o: ${BUILD_DIR}/config.h setlinebuf.o: ${BUILD_DIR}/config.h shmatch.o: ${BUILD_DIR}/config.h @@ -275,7 +279,7 @@ strtoumax.o: ${BUILD_DIR}/config.h strtrans.o: ${BUILD_DIR}/config.h times.o: ${BUILD_DIR}/config.h timeval.o: ${BUILD_DIR}/config.h -tmpfile.o: ${BUILD_DIR}/config.h +tmpfile.o: ${BUILD_DIR}/config.h ${topdir}/config-top.h uconvert.o: ${BUILD_DIR}/config.h ufuncs.o: ${BUILD_DIR}/config.h unicode.o: ${BUILD_DIR}/config.h @@ -380,6 +384,10 @@ pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h #pathphys.o: ${BUILD_DIR}/version.h +random.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h +random.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h +random.o: ${BASHINCDIR}/filecntl.h + rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h rename.o: ${BASHINCDIR}/posixstat.h @@ -505,6 +513,7 @@ times.o: ${BASHINCDIR}/systimes.h times.o: ${BASHINCDIR}/posixtime.h timeval.o: ${BASHINCDIR}/posixtime.h +gettimeofday.o: ${BASHINCDIR}/posixtime.h tmpfile.o: ${topdir}/bashtypes.h tmpfile.o: ${BASHINCDIR}/chartypes.h diff --git a/lib/sh/casemod.c b/lib/sh/casemod.c index 7cdd4178..bdd96f84 100644 --- a/lib/sh/casemod.c +++ b/lib/sh/casemod.c @@ -1,6 +1,6 @@ /* casemod.c -- functions to change case of strings */ -/* Copyright (C) 2008,2009,2015 Free Software Foundation, Inc. +/* Copyright (C) 2008-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -67,7 +67,7 @@ #define CASE_USEWORDS 0x1000 /* modify behavior to act on words in passed string */ -extern char *substring __P((char *, int, int)); +extern char *substring PARAMS((char *, int, int)); #ifndef UCHAR_MAX # define UCHAR_MAX TYPE_MAXIMUM(unsigned char) diff --git a/lib/sh/eaccess.c b/lib/sh/eaccess.c index 3d8ae4e8..c3043ec1 100644 --- a/lib/sh/eaccess.c +++ b/lib/sh/eaccess.c @@ -1,6 +1,6 @@ /* eaccess.c - eaccess replacement for the shell, plus other access functions. */ -/* Copyright (C) 2006-2010 Free Software Foundation, Inc. +/* Copyright (C) 2006-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -52,10 +52,10 @@ extern int errno; #define F_OK 0 #endif /* R_OK */ -static int path_is_devfd __P((const char *)); -static int sh_stataccess __P((const char *, int)); +static int path_is_devfd PARAMS((const char *)); +static int sh_stataccess PARAMS((const char *, int)); #if HAVE_DECL_SETREGID -static int sh_euidaccess __P((const char *, int)); +static int sh_euidaccess PARAMS((const char *, int)); #endif static int @@ -213,10 +213,10 @@ sh_eaccess (path, mode) # else /* HAVE_EACCESS */ /* FreeBSD */ ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */ # endif /* HAVE_EACCESS */ -# if defined (__FreeBSD__) || defined (SOLARIS) +# if defined (__FreeBSD__) || defined (SOLARIS) || defined (_AIX) if (ret == 0 && current_user.euid == 0 && mode == X_OK) return (sh_stataccess (path, mode)); -# endif /* __FreeBSD__ || SOLARIS */ +# endif /* __FreeBSD__ || SOLARIS || _AIX */ return ret; #elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */ return access (path, mode|EFF_ONLY_OK); diff --git a/lib/sh/fnxform.c b/lib/sh/fnxform.c index d7e1b5ad..35d7e737 100644 --- a/lib/sh/fnxform.c +++ b/lib/sh/fnxform.c @@ -1,6 +1,6 @@ /* fnxform - use iconv(3) to transform strings to and from "filename" format */ -/* Copyright (C) 2009-2010 Free Software Foundation, Inc. +/* Copyright (C) 2009-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -35,9 +35,9 @@ #endif #if defined (HAVE_LOCALE_CHARSET) -extern const char *locale_charset __P((void)); +extern const char *locale_charset PARAMS((void)); #else -extern char *get_locale_var __P((char *)); +extern char *get_locale_var PARAMS((char *)); #endif #if defined (HAVE_ICONV) @@ -49,9 +49,9 @@ static iconv_t conv_tofs = (iconv_t)-1; static char *outbuf = 0; static size_t outlen = 0; -static char *curencoding __P((void)); -static void init_tofs __P((void)); -static void init_fromfs __P((void)); +static char *curencoding PARAMS((void)); +static void init_tofs PARAMS((void)); +static void init_fromfs PARAMS((void)); static char * curencoding () diff --git a/lib/sh/fpurge.c b/lib/sh/fpurge.c index 13e8c78e..8cd4e368 100644 --- a/lib/sh/fpurge.c +++ b/lib/sh/fpurge.c @@ -1,6 +1,6 @@ /* fpurge - Flushing buffers of a FILE stream. */ -/* Copyright (C) 2007-2010 Free Software Foundation, Inc. +/* Copyright (C) 2007-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -29,7 +29,7 @@ #if HAVE_FPURGE # define fpurge _bash_fpurge #endif -extern int fpurge __P((FILE *stream)); +extern int fpurge PARAMS((FILE *stream)); #if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */ # include <stdio_ext.h> diff --git a/lib/sh/gettimeofday.c b/lib/sh/gettimeofday.c new file mode 100644 index 00000000..b654c154 --- /dev/null +++ b/lib/sh/gettimeofday.c @@ -0,0 +1,35 @@ +/* gettimeofday.c - gettimeofday replacement using time() */ + +/* Copyright (C) 2020 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + 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/>. +*/ + +#include "config.h" + +#if !defined (HAVE_GETTIMEOFDAY) + +#include "posixtime.h" + +/* A version of gettimeofday that just sets tv_sec from time(3) */ +int +gettimeofday (struct timeval *tv, void *tz) +{ + tv->tv_sec = (time_t) time ((time_t *)0); + tv->tv_usec = 0; + return 0; +} +#endif diff --git a/lib/sh/input_avail.c b/lib/sh/input_avail.c index ac157a9f..695165fd 100644 --- a/lib/sh/input_avail.c +++ b/lib/sh/input_avail.c @@ -1,7 +1,7 @@ /* input_avail.c -- check whether or not data is available for reading on a specified file descriptor. */ -/* Copyright (C) 2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 2008,2009-2019 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -33,6 +33,10 @@ # include <sys/file.h> #endif /* HAVE_SYS_FILE_H */ +#if defined (HAVE_PSELECT) +# include <signal.h> +#endif + #if defined (HAVE_UNISTD_H) # include <unistd.h> #endif /* HAVE_UNISTD_H */ @@ -82,10 +86,8 @@ input_avail (fd) timeout.tv_usec = 0; result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout); return ((result <= 0) ? 0 : 1); - #endif - result = -1; #if defined (FIONREAD) errno = 0; result = ioctl (fd, FIONREAD, &chars_avail); @@ -96,3 +98,68 @@ input_avail (fd) return 0; } + +/* Wait until NCHARS are available for reading on file descriptor FD. + This can wait indefinitely. Return -1 on error. */ +int +nchars_avail (fd, nchars) + int fd; + int nchars; +{ + int result, chars_avail; +#if defined(HAVE_SELECT) + fd_set readfds, exceptfds; +#endif +#if defined (HAVE_PSELECT) + sigset_t set, oset; +#endif + + if (fd < 0 || nchars < 0) + return -1; + if (nchars == 0) + return (input_avail (fd)); + + chars_avail = 0; + +#if defined (HAVE_SELECT) + FD_ZERO (&readfds); + FD_ZERO (&exceptfds); + FD_SET (fd, &readfds); + FD_SET (fd, &exceptfds); +#endif +#if defined (HAVE_SELECT) || defined (HAVE_PSELECT) + sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); +# ifdef SIGCHLD + sigaddset (&set, SIGCHLD); +# endif + sigemptyset (&oset); +#endif + + while (1) + { + result = 0; +#if defined (HAVE_PSELECT) + /* XXX - use pselect(2) to block SIGCHLD atomically */ + result = pselect (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, (struct timespec *)NULL, &set); +#elif defined (HAVE_SELECT) + sigprocmask (SIG_BLOCK, &set, &oset); + result = select (fd + 1, &readfds, (fd_set *)NULL, &exceptfds, (struct timeval *)NULL); + sigprocmask (SIG_BLOCK, &oset, (sigset_t *)NULL); +#endif + if (result < 0) + return -1; + +#if defined (FIONREAD) + errno = 0; + result = ioctl (fd, FIONREAD, &chars_avail); + if (result == -1 && errno == EIO) + return -1; + if (chars_avail >= nchars) + break; +#else + break; +#endif + } + + return 0; +} diff --git a/lib/sh/mailstat.c b/lib/sh/mailstat.c index 79b431ae..bd5c25fb 100644 --- a/lib/sh/mailstat.c +++ b/lib/sh/mailstat.c @@ -60,7 +60,7 @@ mailstat(path, st) struct stat st_ret, st_tmp; DIR *dd; struct dirent *fn; - char dir[PATH_MAX * 2], file[PATH_MAX * 2]; + char dir[PATH_MAX * 2], file[PATH_MAX * 2 + 1]; int i, l; time_t atime, mtime; diff --git a/lib/sh/makepath.c b/lib/sh/makepath.c index ef01718b..ab46c967 100644 --- a/lib/sh/makepath.c +++ b/lib/sh/makepath.c @@ -1,6 +1,6 @@ /* makepath.c - glue PATH and DIR together into a full pathname. */ -/* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc. +/* Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -45,7 +45,7 @@ # define MP_IGNDOT 0x08 #endif -extern char *get_working_directory __P((char *)); +extern char *get_working_directory PARAMS((char *)); static char *nullpath = ""; diff --git a/lib/sh/mktime.c b/lib/sh/mktime.c index b2b0d3f2..9ee675be 100644 --- a/lib/sh/mktime.c +++ b/lib/sh/mktime.c @@ -1,6 +1,6 @@ /* mktime - convert struct tm to a time_t value */ -/* Copyright (C) 1993-2002 Free Software Foundation, Inc. +/* Copyright (C) 1993-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. Contributed by Paul Eggert (eggert@twinsun.com). @@ -56,13 +56,13 @@ #define mktime my_mktime #endif /* DEBUG_MKTIME */ -#ifndef __P +#ifndef PARAMS #if defined (__GNUC__) || (defined (__STDC__) && __STDC__) -#define __P(args) args +#define PARAMS(args) args #else -#define __P(args) () +#define PARAMS(args) () #endif /* GCC. */ -#endif /* Not __P. */ +#endif /* Not PARAMS. */ #ifndef CHAR_BIT #define CHAR_BIT 8 @@ -117,13 +117,13 @@ const unsigned short int __mon_yday[2][13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; -static time_t ydhms_tm_diff __P ((int, int, int, int, int, const struct tm *)); -time_t __mktime_internal __P ((struct tm *, +static time_t ydhms_tm_diff PARAMS ((int, int, int, int, int, const struct tm *)); +time_t __mktime_internal PARAMS ((struct tm *, struct tm *(*) (const time_t *, struct tm *), time_t *)); -static struct tm *my_localtime_r __P ((const time_t *, struct tm *)); +static struct tm *my_localtime_r PARAMS ((const time_t *, struct tm *)); static struct tm * my_localtime_r (t, tp) const time_t *t; @@ -193,7 +193,7 @@ mktime (tp) time_t __mktime_internal (tp, convert, offset) struct tm *tp; - struct tm *(*convert) __P ((const time_t *, struct tm *)); + struct tm *(*convert) PARAMS ((const time_t *, struct tm *)); time_t *offset; { time_t t, dt, t0; diff --git a/lib/sh/netopen.c b/lib/sh/netopen.c index bc3d8f8a..ee0baf66 100644 --- a/lib/sh/netopen.c +++ b/lib/sh/netopen.c @@ -5,7 +5,7 @@ * chet@ins.CWRU.Edu */ -/* Copyright (C) 1987-2016 Free Software Foundation, Inc. +/* Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -63,18 +63,18 @@ extern int errno; #endif #if !defined (HAVE_INET_ATON) -extern int inet_aton __P((const char *, struct in_addr *)); +extern int inet_aton PARAMS((const char *, struct in_addr *)); #endif #ifndef HAVE_GETADDRINFO -static int _getaddr __P((char *, struct in_addr *)); -static int _getserv __P((char *, int, unsigned short *)); -static int _netopen4 __P((char *, char *, int)); +static int _getaddr PARAMS((char *, struct in_addr *)); +static int _getserv PARAMS((char *, int, unsigned short *)); +static int _netopen4 PARAMS((char *, char *, int)); #else /* HAVE_GETADDRINFO */ -static int _netopen6 __P((char *, char *, int)); +static int _netopen6 PARAMS((char *, char *, int)); #endif -static int _netopen __P((char *, char *, int)); +static int _netopen PARAMS((char *, char *, int)); #ifndef HAVE_GETADDRINFO /* Stuff the internet address corresponding to HOST into AP, in network diff --git a/lib/sh/pathcanon.c b/lib/sh/pathcanon.c index f9506dff..7d0df9f9 100644 --- a/lib/sh/pathcanon.c +++ b/lib/sh/pathcanon.c @@ -90,7 +90,7 @@ _path_isdir (path) /* Canonicalize PATH, and return a new path. The new path differs from PATH in that: - Multple `/'s are collapsed to a single `/'. + Multiple `/'s are collapsed to a single `/'. Leading `./'s and trailing `/.'s are removed. Trailing `/'s are removed. Non-leading `../'s and trailing `..'s are handled by removing diff --git a/lib/sh/pathphys.c b/lib/sh/pathphys.c index 99390cef..95b72f19 100644 --- a/lib/sh/pathphys.c +++ b/lib/sh/pathphys.c @@ -1,6 +1,6 @@ /* pathphys.c -- return pathname with all symlinks expanded. */ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 2000-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -46,7 +46,7 @@ extern int errno; #endif /* !errno */ -extern char *get_working_directory __P((char *)); +extern char *get_working_directory PARAMS((char *)); static int _path_readlink (path, buf, bufsiz) diff --git a/lib/sh/random.c b/lib/sh/random.c new file mode 100644 index 00000000..1eaa71aa --- /dev/null +++ b/lib/sh/random.c @@ -0,0 +1,240 @@ +/* random.c -- Functions for managing 16-bit and 32-bit random numbers. */ + +/* Copyright (C) 2020 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + 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/>. +*/ + +#include "config.h" + +#include "bashtypes.h" + +#if defined (HAVE_SYS_RANDOM_H) +# include <sys/random.h> +#endif + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif +#include "filecntl.h" + +#include <stdio.h> +#include "bashansi.h" + +#include "shell.h" + +extern time_t shell_start_time; + +extern int last_random_value; + +static u_bits32_t intrand32 PARAMS((u_bits32_t)); +static u_bits32_t genseed PARAMS((void)); + +static u_bits32_t brand32 PARAMS((void)); +static void sbrand32 PARAMS((u_bits32_t)); +static void perturb_rand32 PARAMS((void)); + +/* The random number seed. You can change this by setting RANDOM. */ +static u_bits32_t rseed = 1; + +/* Returns a 32-bit pseudo-random number. */ +static u_bits32_t +intrand32 (last) + u_bits32_t last; +{ + /* Minimal Standard generator from + "Random number generators: good ones are hard to find", + Park and Miller, Communications of the ACM, vol. 31, no. 10, + October 1988, p. 1195. Filtered through FreeBSD. + + x(n+1) = 16807 * x(n) mod (m). + + We split up the calculations to avoid overflow. + + h = last / q; l = x - h * q; t = a * l - h * r + m = 2147483647, a = 16807, q = 127773, r = 2836 + + There are lots of other combinations of constants to use; look at + https://www.gnu.org/software/gsl/manual/html_node/Other-random-number-generators.html#Other-random-number-generators */ + + bits32_t h, l, t; + u_bits32_t ret; + + /* Can't seed with 0. */ + ret = (last == 0) ? 123459876 : last; + h = ret / 127773; + l = ret - (127773 * h); + t = 16807 * l - 2836 * h; + ret = (t < 0) ? t + 0x7fffffff : t; + + return (ret); +} + +static u_bits32_t +genseed () +{ + struct timeval tv; + u_bits32_t iv; + + gettimeofday (&tv, NULL); + iv = (u_bits32_t)seedrand; /* let the compiler truncate */ + iv = tv.tv_sec ^ tv.tv_usec ^ getpid () ^ getppid () ^ current_user.uid ^ iv; + return (iv); +} + +#define BASH_RAND_MAX 32767 /* 0x7fff - 16 bits */ + +/* Returns a pseudo-random number between 0 and 32767. */ +int +brand () +{ + unsigned int ret; + + rseed = intrand32 (rseed); + if (shell_compatibility_level > 50) + ret = (rseed >> 16) ^ (rseed & 65535); + else + ret = rseed; + return (ret & BASH_RAND_MAX); +} + +/* Set the random number generator seed to SEED. */ +void +sbrand (seed) + unsigned long seed; +{ + rseed = seed; + last_random_value = 0; +} + +void +seedrand () +{ + u_bits32_t iv; + + iv = genseed (); + sbrand (iv); +} + +static u_bits32_t rseed32 = 1073741823; +static int last_rand32; + +static int urandfd = -1; + +#define BASH_RAND32_MAX 0x7fffffff /* 32 bits */ + +/* Returns a 32-bit pseudo-random number between 0 and 4294967295. */ +static u_bits32_t +brand32 () +{ + u_bits32_t ret; + + rseed32 = intrand32 (rseed32); + return (rseed32 & BASH_RAND32_MAX); +} + +static void +sbrand32 (seed) + u_bits32_t seed; +{ + last_rand32 = rseed32 = seed; +} + +void +seedrand32 () +{ + u_bits32_t iv; + + iv = genseed (); + sbrand32 (iv); +} + +static void +perturb_rand32 () +{ + rseed32 ^= genseed (); +} + +/* Force another attempt to open /dev/urandom on the next call to get_urandom32 */ +void +urandom_close () +{ + if (urandfd >= 0) + close (urandfd); + urandfd = -1; +} + +#if !defined (HAVE_GETRANDOM) +/* Imperfect emulation of getrandom(2). */ +#ifndef GRND_NONBLOCK +# define GRND_NONBLOCK 1 +# define GRND_RANDOM 2 +#endif + +static ssize_t +getrandom (buf, len, flags) + void *buf; + size_t len; + unsigned int flags; +{ + int oflags; + ssize_t r; + static int urand_unavail = 0; + +#if HAVE_GETENTROPY + r = getentropy (buf, len); + return (r == 0) ? len : -1; +#endif + + if (urandfd == -1 && urand_unavail == 0) + { + oflags = O_RDONLY; + if (flags & GRND_NONBLOCK) + oflags |= O_NONBLOCK; + urandfd = open ("/dev/urandom", oflags, 0); + if (urandfd >= 0) + SET_CLOSE_ON_EXEC (urandfd); + else + { + urand_unavail = 1; + return -1; + } + } + if (urandfd >= 0 && (r = read (urandfd, buf, len)) == len) + return (r); + return -1; +} +#endif + +u_bits32_t +get_urandom32 () +{ + u_bits32_t ret; + + if (getrandom ((void *)&ret, sizeof (ret), GRND_NONBLOCK) == sizeof (ret)) + return (last_rand32 = ret); + +#if defined (HAVE_ARC4RANDOM) + ret = arc4random (); +#else + if (subshell_environment) + perturb_rand32 (); + do + ret = brand32 (); + while (ret == last_rand32); +#endif + return (last_rand32 = ret); +} diff --git a/lib/sh/shmatch.c b/lib/sh/shmatch.c index da05211e..d6e7f904 100644 --- a/lib/sh/shmatch.c +++ b/lib/sh/shmatch.c @@ -64,7 +64,7 @@ sh_regmatch (string, pattern, flags) #endif rflags = REG_EXTENDED; - if (glob_ignore_case || match_ignore_case) + if (match_ignore_case) rflags |= REG_ICASE; #if !defined (ARRAY_VARS) rflags |= REG_NOSUB; @@ -107,7 +107,9 @@ sh_regmatch (string, pattern, flags) } } +#if 0 VSETATTR (rematch, att_readonly); +#endif free (subexp_str); free (matches); diff --git a/lib/sh/shquote.c b/lib/sh/shquote.c index 97e2bc53..680f84ed 100644 --- a/lib/sh/shquote.c +++ b/lib/sh/shquote.c @@ -1,6 +1,6 @@ /* shquote - functions to quote and dequote strings */ -/* Copyright (C) 1999-2015 Free Software Foundation, Inc. +/* Copyright (C) 1999-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -36,8 +36,8 @@ #include "shmbchar.h" #include "shmbutil.h" -extern char *ansic_quote __P((char *, int, int *)); -extern int ansic_shouldquote __P((const char *)); +extern char *ansic_quote PARAMS((char *, int, int *)); +extern int ansic_shouldquote PARAMS((const char *)); /* Default set of characters that should be backslash-quoted in strings */ static const char bstab[256] = @@ -136,8 +136,15 @@ sh_double_quote (string) const char *string; { register unsigned char c; + int mb_cur_max; char *result, *r; - const char *s; + size_t slen; + const char *s, *send; + DECLARE_MBSTATE; + + slen = strlen (string); + send = string + slen; + mb_cur_max = MB_CUR_MAX; result = (char *)xmalloc (3 + (2 * strlen (string))); r = result; @@ -148,12 +155,19 @@ sh_double_quote (string) /* Backslash-newline disappears within double quotes, so don't add one. */ if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n') *r++ = '\\'; -#if 0 - /* Assume that the string will not be further expanded. */ - else if (c == CTLESC || c == CTLNUL) - *r++ = CTLESC; /* could be '\\'? */ + +#if defined (HANDLE_MULTIBYTE) + if ((locale_utf8locale && (c & 0x80)) || + (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0)) + { + COPY_CHAR_P (r, s, send); + s--; /* compensate for auto-increment in loop above */ + continue; + } #endif + /* Assume that the string will not be further expanded, so no need to + add CTLESC to protect CTLESC or CTLNUL. */ *r++ = c; } @@ -171,16 +185,29 @@ sh_mkdoublequoted (s, slen, flags) int slen, flags; { char *r, *ret; - int rlen; + const char *send; + int rlen, mb_cur_max; + DECLARE_MBSTATE; + send = s + slen; + mb_cur_max = flags ? MB_CUR_MAX : 1; rlen = (flags == 0) ? slen + 3 : (2 * slen) + 1; ret = r = (char *)xmalloc (rlen); - + *r++ = '"'; while (*s) { if (flags && *s == '"') *r++ = '\\'; + +#if defined (HANDLE_MULTIBYTE) + if (flags && ((locale_utf8locale && (*s & 0x80)) || + (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (*s) == 0))) + { + COPY_CHAR_P (r, s, send); + continue; + } +#endif *r++ = *s++; } *r++ = '"'; @@ -259,7 +286,8 @@ sh_backslash_quote (string, table, flags) *r++ = c; continue; } - if (mb_cur_max > 1 && is_basic (c) == 0) + if ((locale_utf8locale && (c & 0x80)) || + (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0)) { COPY_CHAR_P (r, s, send); s--; /* compensate for auto-increment in loop above */ @@ -291,18 +319,35 @@ sh_backslash_quote_for_double_quotes (string) char *string; { unsigned char c; - char *result, *r, *s; - - result = (char *)xmalloc (2 * strlen (string) + 1); + char *result, *r, *s, *send; + size_t slen; + int mb_cur_max; + DECLARE_MBSTATE; + + slen = strlen (string); + send = string + slen; + mb_cur_max = MB_CUR_MAX; + result = (char *)xmalloc (2 * slen + 1); for (r = result, s = string; s && (c = *s); s++) { - if (sh_syntaxtab[c] & CBSDQUOTE) + /* Backslash-newline disappears within double quotes, so don't add one. */ + if ((sh_syntaxtab[c] & CBSDQUOTE) && c != '\n') *r++ = '\\'; - /* I should probably add flags for these to sh_syntaxtab[] */ + /* I should probably use the CSPECL flag for these in sh_syntaxtab[] */ else if (c == CTLESC || c == CTLNUL) *r++ = CTLESC; /* could be '\\'? */ +#if defined (HANDLE_MULTIBYTE) + if ((locale_utf8locale && (c & 0x80)) || + (locale_utf8locale == 0 && mb_cur_max > 1 && is_basic (c) == 0)) + { + COPY_CHAR_P (r, s, send); + s--; /* compensate for auto-increment in loop above */ + continue; + } +#endif + *r++ = c; } diff --git a/lib/sh/snprintf.c b/lib/sh/snprintf.c index 6e5892ee..406a3a50 100644 --- a/lib/sh/snprintf.c +++ b/lib/sh/snprintf.c @@ -9,7 +9,7 @@ Unix snprintf implementation. derived from inetutils/libinetutils/snprintf.c Version 1.1 - Copyright (C) 2001,2006,2010,2012 Free Software Foundation, Inc. + Copyright (C) 2001-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -129,8 +129,8 @@ # define FL_ADDBASE 0x02 /* add base# prefix to converted value */ # define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */ # define FL_UNSIGNED 0x08 /* don't add any sign */ -extern char *fmtulong __P((unsigned long int, int, char *, size_t, int)); -extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int)); +extern char *fmtulong PARAMS((unsigned long int, int, char *, size_t, int)); +extern char *fmtullong PARAMS((unsigned long long int, int, char *, size_t, int)); #endif #ifndef FREE @@ -271,38 +271,38 @@ struct DATA /* the floating point stuff */ #ifdef FLOATING_POINT -static double pow_10 __P((int)); -static int log_10 __P((double)); -static double integral __P((double, double *)); -static char *numtoa __P((double, int, int, char **)); +static double pow_10 PARAMS((int)); +static int log_10 PARAMS((double)); +static double integral PARAMS((double, double *)); +static char *numtoa PARAMS((double, int, int, char **)); #endif -static void init_data __P((struct DATA *, char *, size_t, const char *, int)); -static void init_conv_flag __P((struct DATA *)); +static void init_data PARAMS((struct DATA *, char *, size_t, const char *, int)); +static void init_conv_flag PARAMS((struct DATA *)); /* for the format */ #ifdef FLOATING_POINT -static void floating __P((struct DATA *, double)); -static void exponent __P((struct DATA *, double)); +static void floating PARAMS((struct DATA *, double)); +static void exponent PARAMS((struct DATA *, double)); #endif -static void number __P((struct DATA *, unsigned long, int)); +static void number PARAMS((struct DATA *, unsigned long, int)); #ifdef HAVE_LONG_LONG -static void lnumber __P((struct DATA *, unsigned long long, int)); +static void lnumber PARAMS((struct DATA *, unsigned long long, int)); #endif -static void pointer __P((struct DATA *, unsigned long)); -static void strings __P((struct DATA *, char *)); +static void pointer PARAMS((struct DATA *, unsigned long)); +static void strings PARAMS((struct DATA *, char *)); #ifdef FLOATING_POINT # define FALLBACK_FMTSIZE 32 # define FALLBACK_BASE 4096 # define LFALLBACK_BASE 5120 # ifdef HAVE_LONG_DOUBLE -static void ldfallback __P((struct DATA *, const char *, const char *, long double)); +static void ldfallback PARAMS((struct DATA *, const char *, const char *, long double)); # endif -static void dfallback __P((struct DATA *, const char *, const char *, double)); +static void dfallback PARAMS((struct DATA *, const char *, const char *, double)); #endif -static char *groupnum __P((char *)); +static char *groupnum PARAMS((char *)); #if defined (HAVE_LONG_DOUBLE) # define LONGDOUBLE long double @@ -332,9 +332,9 @@ static char *groupnum __P((char *)); #ifdef DRIVER static void memory_error_and_abort (); -static void *xmalloc __P((size_t)); -static void *xrealloc __P((void *, size_t)); -static void xfree __P((void *)); +static void *xmalloc PARAMS((size_t)); +static void *xrealloc PARAMS((void *, size_t)); +static void xfree PARAMS((void *)); #else # include <xmalloc.h> #endif diff --git a/lib/sh/spell.c b/lib/sh/spell.c index da78690c..cdf465b2 100644 --- a/lib/sh/spell.c +++ b/lib/sh/spell.c @@ -1,6 +1,6 @@ /* spell.c -- spelling correction for pathnames. */ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 2000-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -40,8 +40,8 @@ #include <maxpath.h> #include <stdc.h> -static int mindist __P((char *, char *, char *)); -static int spdist __P((char *, char *)); +static int mindist PARAMS((char *, char *, char *)); +static int spdist PARAMS((char *, char *)); /* * `spname' and its helpers are inspired by the code in "The UNIX diff --git a/lib/sh/strftime.c b/lib/sh/strftime.c index 0ababc14..08ccb9a3 100644 --- a/lib/sh/strftime.c +++ b/lib/sh/strftime.c @@ -62,6 +62,7 @@ #include <stdio.h> #include <ctype.h> #include <time.h> +#include <errno.h> #if defined(TM_IN_SYS_TIME) #include <sys/types.h> @@ -80,6 +81,10 @@ #undef strchr /* avoid AIX weirdness */ +#if !defined (errno) +extern int errno; +#endif + #if defined (SHELL) extern char *get_string_value (const char *); #endif @@ -172,7 +177,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr) char *start = s; auto char tbuf[100]; long off; - int i, w; + int i, w, oerrno; long y; static short first = 1; #ifdef POSIX_SEMANTICS @@ -217,6 +222,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr) }; static const char *ampm[] = { "AM", "PM", }; + oerrno = errno; + if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0) return 0; @@ -642,7 +649,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr) sprintf(tbuf+1, "%02ld%02ld", off/60, off%60); break; - case 'Z': /* time zone name or abbrevation */ + case 'Z': /* time zone name or abbreviation */ #ifdef HAVE_TZNAME i = (daylight && timeptr->tm_isdst > 0); /* 0 or 1 */ strcpy(tbuf, tzname[i]); @@ -716,6 +723,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr) out: if (s < endp && *format == '\0') { *s = '\0'; + if (s == start) + errno = oerrno; return (s - start); } else return 0; @@ -939,7 +948,7 @@ static char *array[] = "(%%H) hour (24-hour clock, 00..23) %H", "(%%I) hour (12-hour clock, 01..12) %I", "(%%M) minute (00..59) %M", - "(%%N) Emporer/Era Name %N", + "(%%N) Emperor/Era Name %N", "(%%O) Locale extensions (ignored) %O", "(%%R) time, 24-hour (%%H:%%M) %R", "(%%S) second (00..60) %S", @@ -960,7 +969,7 @@ static char *array[] = "(%%k) hour, 24-hour clock, blank pad ( 0..23) %k", "(%%l) hour, 12-hour clock, blank pad ( 0..12) %l", "(%%m) month (01..12) %m", - "(%%o) Emporer/Era Year %o", + "(%%o) Emperor/Era Year %o", "(%%p) locale's AM or PM based on 12-hour clock %p", "(%%r) time, 12-hour (same as %%I:%%M:%%S %%p) %r", "(%%u) ISO 8601: Weekday as decimal number [1 (Monday) - 7] %u", diff --git a/lib/sh/stringlist.c b/lib/sh/stringlist.c index b0c272ae..3f28b631 100644 --- a/lib/sh/stringlist.c +++ b/lib/sh/stringlist.c @@ -1,6 +1,6 @@ /* stringlist.c - functions to handle a generic `list of strings' structure */ -/* Copyright (C) 2000-2002 Free Software Foundation, Inc. +/* Copyright (C) 2000-2019 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -255,7 +255,7 @@ strlist_sort (sl) { if (sl == 0 || sl->list_len == 0 || sl->list == 0) return; - strvec_sort (sl->list); + strvec_sort (sl->list, 0); } STRINGLIST * diff --git a/lib/sh/stringvec.c b/lib/sh/stringvec.c index 3bb4ab70..86000429 100644 --- a/lib/sh/stringvec.c +++ b/lib/sh/stringvec.c @@ -122,7 +122,6 @@ strvec_remove (array, name) return 0; } -#ifdef INCLUDE_UNUSED /* Find NAME in ARRAY. Return the index of NAME, or -1 if not present. ARRAY should be NULL terminated. */ int @@ -137,7 +136,6 @@ strvec_search (array, name) return (-1); } -#endif /* Allocate and return a new copy of ARRAY and its contents. */ char ** @@ -158,6 +156,28 @@ strvec_copy (array) return (ret); } +/* Comparison routine for use by qsort that conforms to the new Posix + requirements (http://austingroupbugs.net/view.php?id=1070). + + Perform a bytewise comparison if *S1 and *S2 collate equally. */ +int +strvec_posixcmp (s1, s2) + register char **s1, **s2; +{ + int result; + +#if defined (HAVE_STRCOLL) + result = strcoll (*s1, *s2); + if (result != 0) + return result; +#endif + + if ((result = **s1 - **s2) == 0) + result = strcmp (*s1, *s2); + + return (result); +} + /* Comparison routine for use with qsort() on arrays of strings. Uses strcoll(3) if available, otherwise it uses strcmp(3). */ int @@ -178,10 +198,14 @@ strvec_strcmp (s1, s2) /* Sort ARRAY, a null terminated array of pointers to strings. */ void -strvec_sort (array) +strvec_sort (array, posix) char **array; + int posix; { - qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_strcmp); + if (posix) + qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_posixcmp); + else + qsort (array, strvec_len (array), sizeof (char *), (QSFUNC *)strvec_strcmp); } /* Cons up a new array of words. The words are taken from LIST, diff --git a/lib/sh/strtod.c b/lib/sh/strtod.c index 851d99b9..55e11540 100644 --- a/lib/sh/strtod.c +++ b/lib/sh/strtod.c @@ -49,6 +49,10 @@ extern int errno; # define HUGE_VAL HUGE #endif +#ifndef locale_decpoint +extern int locale_decpoint PARAMS((void)); +#endif + /* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the character after the last one used in the number is put in *ENDPTR. */ double @@ -62,6 +66,7 @@ strtod (nptr, endptr) /* The number so far. */ double num; + int radixchar; int got_dot; /* Found a decimal point. */ int got_digit; /* Seen any digits. */ @@ -85,6 +90,7 @@ strtod (nptr, endptr) if (*s == '-' || *s == '+') ++s; + radixchar = locale_decpoint (); num = 0.0; got_dot = 0; got_digit = 0; @@ -113,7 +119,7 @@ strtod (nptr, endptr) if (got_dot) --exponent; } - else if (!got_dot && *s == '.') + else if (!got_dot && *s == radixchar) /* Record that we have found the decimal point. */ got_dot = 1; else diff --git a/lib/sh/strtoimax.c b/lib/sh/strtoimax.c index a4170f06..676e02ef 100644 --- a/lib/sh/strtoimax.c +++ b/lib/sh/strtoimax.c @@ -1,6 +1,6 @@ /* strtoimax - convert string representation of a number into an intmax_t value. */ -/* Copyright 1999-2009 Free Software Foundation, Inc. +/* Copyright 1999-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -45,14 +45,14 @@ "this configure-time declaration test was not run" #endif #if !HAVE_DECL_STRTOL -extern long strtol __P((const char *, char **, int)); +extern long strtol PARAMS((const char *, char **, int)); #endif #ifndef HAVE_DECL_STRTOLL "this configure-time declaration test was not run" #endif #if !HAVE_DECL_STRTOLL && HAVE_LONG_LONG -extern long long strtoll __P((const char *, char **, int)); +extern long long strtoll PARAMS((const char *, char **, int)); #endif #ifdef strtoimax diff --git a/lib/sh/strtoumax.c b/lib/sh/strtoumax.c index 09423add..0247e57b 100644 --- a/lib/sh/strtoumax.c +++ b/lib/sh/strtoumax.c @@ -1,6 +1,6 @@ /* strtoumax - convert string representation of a number into an uintmax_t value. */ -/* Copyright 1999-2009 Free Software Foundation, Inc. +/* Copyright 1999-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -45,14 +45,14 @@ "this configure-time declaration test was not run" #endif #if !HAVE_DECL_STRTOUL -extern unsigned long strtoul __P((const char *, char **, int)); +extern unsigned long strtoul PARAMS((const char *, char **, int)); #endif #ifndef HAVE_DECL_STRTOULL "this configure-time declaration test was not run" #endif #if !HAVE_DECL_STRTOULL && HAVE_UNSIGNED_LONG_LONG -extern unsigned long long strtoull __P((const char *, char **, int)); +extern unsigned long long strtoull PARAMS((const char *, char **, int)); #endif #ifdef strtoumax diff --git a/lib/sh/strtrans.c b/lib/sh/strtrans.c index 48f255f5..b2b1acca 100644 --- a/lib/sh/strtrans.c +++ b/lib/sh/strtrans.c @@ -55,12 +55,18 @@ ansicstr (string, len, flags, sawc, rlen) int c, temp; char *ret, *r, *s; unsigned long v; + size_t clen; + int b, mb_cur_max; +#if defined (HANDLE_MULTIBYTE) + wchar_t wc; +#endif if (string == 0 || *string == '\0') return ((char *)NULL); + mb_cur_max = MB_CUR_MAX; #if defined (HANDLE_MULTIBYTE) - temp = 4*len + 1; + temp = 4*len + 4; if (temp < 12) temp = 12; /* ensure enough for eventual u32cesc */ ret = (char *)xmalloc (temp); @@ -71,7 +77,21 @@ ansicstr (string, len, flags, sawc, rlen) { c = *s++; if (c != '\\' || *s == '\0') - *r++ = c; + { + clen = 1; +#if defined (HANDLE_MULTIBYTE) + if ((locale_utf8locale && (c & 0x80)) || + (locale_utf8locale == 0 && mb_cur_max > 0 && is_basic (c) == 0)) + { + clen = mbrtowc (&wc, s - 1, mb_cur_max, 0); + if (MB_INVALIDCH (clen)) + clen = 1; + } +#endif + *r++ = c; + for (--clen; clen > 0; clen--) + *r++ = *s++; + } else { switch (c = *s++) diff --git a/lib/sh/times.c b/lib/sh/times.c index 47ddf577..2423078a 100644 --- a/lib/sh/times.c +++ b/lib/sh/times.c @@ -1,6 +1,6 @@ /* times.c - times(3) library function */ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -30,7 +30,7 @@ # include <sys/resource.h> #endif /* HAVE_SYS_RESOURCE_H && HAVE_GETRUSAGE */ -extern long get_clk_tck __P((void)); +extern long get_clk_tck PARAMS((void)); #define CONVTCK(r) (r.tv_sec * clk_tck + r.tv_usec / (1000000 / clk_tck)) @@ -58,7 +58,7 @@ times(tms) tms->tms_cutime = CONVTCK(ru.ru_utime); tms->tms_cstime = CONVTCK(ru.ru_stime); - if (gettimeofday(&tv, (struct timezone *) 0) < 0) + if (gettimeofday(&tv, NULL) < 0) return ((clock_t)-1); rv = (clock_t)(CONVTCK(tv)); #else /* !HAVE_GETRUSAGE */ diff --git a/lib/sh/timeval.c b/lib/sh/timeval.c index c4b61dc8..f2ca7624 100644 --- a/lib/sh/timeval.c +++ b/lib/sh/timeval.c @@ -67,6 +67,32 @@ addtimeval (d, t1, t2) return d; } +struct timeval * +multimeval (d, m) + struct timeval *d; + int m; +{ + time_t t; + + t = d->tv_usec * m; + d->tv_sec = d->tv_sec * m + t / 1000000; + d->tv_usec = t % 1000000; + return d; +} + +struct timeval * +divtimeval (d, m) + struct timeval *d; + int m; +{ + time_t t; + + t = d->tv_sec; + d->tv_sec = t / m; + d->tv_usec = (d->tv_usec + 1000000 * (t % m)) / m; + return d; +} + /* Do "cpu = ((user + sys) * 10000) / real;" with timevals. Barely-tested code from Deven T. Corzine <deven@ties.org>. */ int @@ -149,4 +175,5 @@ print_timeval (fp, tvp) fprintf (fp, "%ldm%d%c%03ds", minutes, seconds, locale_decpoint (), seconds_fraction); } + #endif /* HAVE_TIMEVAL */ diff --git a/lib/sh/tmpfile.c b/lib/sh/tmpfile.c index e41e45bd..ef8b067b 100644 --- a/lib/sh/tmpfile.c +++ b/lib/sh/tmpfile.c @@ -2,7 +2,7 @@ * tmpfile.c - functions to create and safely open temp files for the shell. */ -/* Copyright (C) 2000-2015 Free Software Foundation, Inc. +/* Copyright (C) 2000-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -54,8 +54,8 @@ extern int errno; extern pid_t dollar_dollar_pid; -static char *get_sys_tmpdir __P((void)); -static char *get_tmpdir __P((int)); +static char *get_sys_tmpdir PARAMS((void)); +static char *get_tmpdir PARAMS((int)); static char *sys_tmpdir = (char *)NULL; static int ntmpfiles; @@ -146,9 +146,17 @@ sh_mktmpname (nameroot, flags) tdlen = strlen (tdir); lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; + if (nameroot == 0) + flags &= ~MT_TEMPLATE; + + if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX) + flags &= ~MT_TEMPLATE; #ifdef USE_MKTEMP - sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + if (flags & MT_TEMPLATE) + strcpy (filename, nameroot); + else + sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); if (mktemp (filename) == 0) { free (filename); @@ -192,9 +200,17 @@ sh_mktmpfd (nameroot, flags, namep) tdlen = strlen (tdir); lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; + if (nameroot == 0) + flags &= ~MT_TEMPLATE; + + if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX) + flags &= ~MT_TEMPLATE; #ifdef USE_MKSTEMP - sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + if (flags & MT_TEMPLATE) + strcpy (filename, nameroot); + else + sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); fd = mkstemp (filename); if (fd < 0 || namep == 0) { @@ -245,3 +261,51 @@ sh_mktmpfp (nameroot, flags, namep) close (fd); return fp; } + +char * +sh_mktmpdir (nameroot, flags) + char *nameroot; + int flags; +{ + char *filename, *tdir, *lroot, *dirname; + int fd, tdlen; + +#ifdef USE_MKDTEMP + filename = (char *)xmalloc (PATH_MAX + 1); + tdir = get_tmpdir (flags); + tdlen = strlen (tdir); + + lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; + if (nameroot == 0) + flags &= ~MT_TEMPLATE; + + if ((flags & MT_TEMPLATE) && strlen (nameroot) > PATH_MAX) + flags &= ~MT_TEMPLATE; + + if (flags & MT_TEMPLATE) + strcpy (filename, nameroot); + else + sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + dirname = mkdtemp (filename); + if (dirname == 0) + { + free (filename); + filename = NULL; + } + return dirname; +#else /* !USE_MKDTEMP */ + filename = (char *)NULL; + do + { + filename = sh_mktmpname (nameroot, flags); + fd = mkdir (filename, 0700); + if (fd == 0) + break; + free (filename); + filename = (char *)NULL; + } + while (fd < 0 && errno == EEXIST); + + return (filename); +#endif /* !USE_MKDTEMP */ +} diff --git a/lib/sh/uconvert.c b/lib/sh/uconvert.c index 3d656df0..457552eb 100644 --- a/lib/sh/uconvert.c +++ b/lib/sh/uconvert.c @@ -1,7 +1,7 @@ /* uconvert - convert string representations of decimal numbers into whole number/fractional value pairs. */ -/* Copyright (C) 2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 2008,2009,2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -23,16 +23,7 @@ #include "bashtypes.h" -#if defined (TIME_WITH_SYS_TIME) -# include <sys/time.h> -# include <time.h> -#else -# if defined (HAVE_SYS_TIME_H) -# include <sys/time.h> -# else -# include <time.h> -# endif -#endif +#include "posixtime.h" #if defined (HAVE_UNISTD_H) #include <unistd.h> @@ -50,6 +41,7 @@ do { \ if (ip) *ip = ipart * mult; \ if (up) *up = upart; \ + if (ep) *ep = p; \ return (x); \ } while (0) @@ -61,12 +53,14 @@ static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 }; /* Take a decimal number int-part[.[micro-part]] and convert it to the whole and fractional portions. The fractional portion is returned in millionths (micro); callers are responsible for multiplying appropriately. + EP, if non-null, gets the address of the character where conversion stops. Return 1 if value converted; 0 if invalid integer for either whole or fractional parts. */ int -uconvert(s, ip, up) +uconvert(s, ip, up, ep) char *s; long *ip, *up; + char **ep; { int n, mult; long ipart, upart; @@ -102,7 +96,14 @@ uconvert(s, ip, up) for (n = 0; n < 6 && p[n]; n++) { if (DIGIT(p[n]) == 0) - RETURN(0); + { + if (ep) + { + upart *= multiplier[n]; + p += n; /* To set EP */ + } + RETURN(0); + } upart = (upart * 10) + (p[n] - '0'); } @@ -112,5 +113,12 @@ uconvert(s, ip, up) if (n == 6 && p[6] >= '5' && p[6] <= '9') upart++; /* round up 1 */ + if (ep) + { + p += n; + while (DIGIT(*p)) + p++; + } + RETURN(1); } diff --git a/lib/sh/ufuncs.c b/lib/sh/ufuncs.c index ad9284cc..4dc4853b 100644 --- a/lib/sh/ufuncs.c +++ b/lib/sh/ufuncs.c @@ -1,6 +1,6 @@ /* ufuncs - sleep and alarm functions that understand fractional values */ -/* Copyright (C) 2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 2008,2009-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -22,16 +22,7 @@ #include "bashtypes.h" -#if defined (TIME_WITH_SYS_TIME) -# include <sys/time.h> -# include <time.h> -#else -# if defined (HAVE_SYS_TIME_H) -# include <sys/time.h> -# else -# include <time.h> -# endif -#endif +#include "posixtime.h" #if defined (HAVE_UNISTD_H) #include <unistd.h> @@ -130,7 +121,7 @@ fsleep(sec, usec) #endif e = errno; if (r < 0 && errno == EINTR) - QUIT; /* just signals, no traps */ + return -1; /* caller will handle */ errno = e; } while (r < 0 && errno == EINTR); diff --git a/lib/sh/unicode.c b/lib/sh/unicode.c index fe13c4a0..d95d1e25 100644 --- a/lib/sh/unicode.c +++ b/lib/sh/unicode.c @@ -1,6 +1,6 @@ /* unicode.c - functions to convert unicode characters */ -/* Copyright (C) 2010-2016 Free Software Foundation, Inc. +/* Copyright (C) 2010-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -50,9 +50,9 @@ #endif /* !STREQ */ #if defined (HAVE_LOCALE_CHARSET) -extern const char *locale_charset __P((void)); +extern const char *locale_charset PARAMS((void)); #else -extern char *get_locale_var __P((char *)); +extern char *get_locale_var PARAMS((char *)); #endif extern int locale_utf8locale; @@ -196,7 +196,7 @@ u32toutf8 (wc, s) } else if (wc < 0x080000000) { - s[0] = (wc >> 30) | 0xf8; + s[0] = (wc >> 30) | 0xfc; s[1] = ((wc >> 24) & 0x3f) | 0x80; s[2] = ((wc >> 18) & 0x3f) | 0x80; s[3] = ((wc >> 12) & 0x3f) | 0x80; @@ -216,21 +216,21 @@ u32toutf8 (wc, s) int u32toutf16 (c, s) u_bits32_t c; - unsigned short *s; + wchar_t *s; { int l; l = 0; if (c < 0x0d800 || (c >= 0x0e000 && c <= 0x0ffff)) { - s[0] = (unsigned short) (c & 0xFFFF); + s[0] = (wchar_t) (c & 0xFFFF); l = 1; } else if (c >= 0x10000 && c <= 0x010ffff) { c -= 0x010000; - s[0] = (unsigned short)((c >> 10) + 0xd800); - s[1] = (unsigned short)((c & 0x3ff) + 0xdc00); + s[0] = (wchar_t)((c >> 10) + 0xd800); + s[1] = (wchar_t)((c & 0x3ff) + 0xdc00); l = 2; } s[l] = 0; diff --git a/lib/sh/utf8.c b/lib/sh/utf8.c index d27fcf54..fed25226 100644 --- a/lib/sh/utf8.c +++ b/lib/sh/utf8.c @@ -76,13 +76,13 @@ utf8_mbsnlen(src, srclen, maxlen) return (count); } -/* Adapted from GNU gnulib */ +/* Adapted from GNU gnulib. Handles UTF-8 characters up to 4 bytes long */ int utf8_mblen (s, n) const char *s; size_t n; { - unsigned char c, c1; + unsigned char c, c1, c2, c3; if (s == 0) return (0); /* no shift states */ @@ -97,25 +97,74 @@ utf8_mblen (s, n) c1 = (unsigned char)s[1]; if (c < 0xe0) { - if (n >= 2 && (s[1] ^ 0x80) < 0x40) + if (n == 1) + return -2; + + /* + * c c1 + * + * U+0080..U+07FF C2..DF 80..BF + */ + + if (n >= 2 && (c1 ^ 0x80) < 0x40) /* 0x80..0xbf */ return 2; } else if (c < 0xf0) { - if (n >= 3 - && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 + if (n == 1) + return -2; + + /* + * c c1 c2 + * + * U+0800..U+0FFF E0 A0..BF 80..BF + * U+1000..U+CFFF E1..EC 80..BF 80..BF + * U+D000..U+D7FF ED 80..9F 80..BF + * U+E000..U+FFFF EE..EF 80..BF 80..BF + */ + + if ((c1 ^ 0x80) < 0x40 && (c >= 0xe1 || c1 >= 0xa0) && (c != 0xed || c1 < 0xa0)) - return 3; + { + if (n == 2) + return -2; /* incomplete */ + + c2 = (unsigned char)s[2]; + if ((c2 ^ 0x80) < 0x40) + return 3; + } } - else if (c < 0xf8) + else if (c <= 0xf4) { - if (n >= 4 - && (s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 - && (s[3] ^ 0x80) < 0x40 + if (n == 1) + return -2; + + /* + * c c1 c2 c3 + * + * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + */ + if (((c1 ^ 0x80) < 0x40) && (c >= 0xf1 || c1 >= 0x90) && (c < 0xf4 || (c == 0xf4 && c1 < 0x90))) - return 4; + { + if (n == 2) + return -2; /* incomplete */ + + c2 = (unsigned char)s[2]; + if ((c2 ^ 0x80) < 0x40) + { + if (n == 3) + return -2; + + c3 = (unsigned char)s[3]; + if ((c3 ^ 0x80) < 0x40) + return 4; + } + } } } /* invalid or incomplete multibyte character */ diff --git a/lib/sh/winsize.c b/lib/sh/winsize.c index ab83433a..861c7c89 100644 --- a/lib/sh/winsize.c +++ b/lib/sh/winsize.c @@ -1,6 +1,6 @@ /* winsize.c - handle window size changes and information. */ -/* Copyright (C) 2005-2015 Free Software Foundation, Inc. +/* Copyright (C) 2005-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -68,9 +68,9 @@ extern int errno; extern int shell_tty; #if defined (READLINE) -extern void rl_set_screen_size __P((int, int)); +extern void rl_set_screen_size PARAMS((int, int)); #endif -extern void sh_set_lines_and_columns __P((int, int)); +extern void sh_set_lines_and_columns PARAMS((int, int)); void get_new_window_size (from_sig, rp, cp) diff --git a/lib/sh/zcatfd.c b/lib/sh/zcatfd.c index bdbcd910..aa8199fd 100644 --- a/lib/sh/zcatfd.c +++ b/lib/sh/zcatfd.c @@ -1,6 +1,6 @@ /* zcatfd - copy contents of file descriptor to another */ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -34,8 +34,12 @@ extern int errno; #endif -extern ssize_t zread __P((int, char *, size_t)); -extern int zwrite __P((int, char *, ssize_t)); +#ifndef ZBUFSIZ +# define ZBUFSIZ 4096 +#endif + +extern ssize_t zread PARAMS((int, char *, size_t)); +extern int zwrite PARAMS((int, char *, ssize_t)); /* Dump contents of file descriptor FD to OFD. FN is the filename for error messages (not used right now). */ @@ -46,7 +50,7 @@ zcatfd (fd, ofd, fn) { ssize_t nr; int rval; - char lbuf[128]; + char lbuf[ZBUFSIZ]; rval = 0; while (1) diff --git a/lib/sh/zgetline.c b/lib/sh/zgetline.c index a686ba3d..8ded1442 100644 --- a/lib/sh/zgetline.c +++ b/lib/sh/zgetline.c @@ -1,7 +1,7 @@ /* zgetline - read a line of input from a specified file descriptor and return a pointer to a newly-allocated buffer containing the data. */ -/* Copyright (C) 2008,2009 Free Software Foundation, Inc. +/* Copyright (C) 2008-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -34,13 +34,13 @@ extern int errno; #endif -extern ssize_t zread __P((int, char *, size_t)); -extern ssize_t zreadc __P((int, char *)); -extern ssize_t zreadintr __P((int, char *, size_t)); -extern ssize_t zreadcintr __P((int, char *)); +extern ssize_t zread PARAMS((int, char *, size_t)); +extern ssize_t zreadc PARAMS((int, char *)); +extern ssize_t zreadintr PARAMS((int, char *, size_t)); +extern ssize_t zreadcintr PARAMS((int, char *)); -typedef ssize_t breadfunc_t __P((int, char *, size_t)); -typedef ssize_t creadfunc_t __P((int, char *)); +typedef ssize_t breadfunc_t PARAMS((int, char *, size_t)); +typedef ssize_t creadfunc_t PARAMS((int, char *)); /* Initial memory allocation for automatic growing buffer in zreadlinec */ #define GET_LINE_INITIAL_ALLOCATION 16 diff --git a/lib/sh/zmapfd.c b/lib/sh/zmapfd.c index e7208921..f9e9ed71 100644 --- a/lib/sh/zmapfd.c +++ b/lib/sh/zmapfd.c @@ -1,6 +1,6 @@ /* zmapfd - read contents of file descriptor into a newly-allocated buffer */ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -36,7 +36,11 @@ extern int errno; #endif -extern ssize_t zread __P((int, char *, size_t)); +#ifndef ZBUFSIZ +# define ZBUFSIZ 4096 +#endif + +extern ssize_t zread PARAMS((int, char *, size_t)); /* Dump contents of file descriptor FD to *OSTR. FN is the filename for error messages (not used right now). */ @@ -48,12 +52,12 @@ zmapfd (fd, ostr, fn) { ssize_t nr; int rval; - char lbuf[128]; + char lbuf[ZBUFSIZ]; char *result; int rsize, rind; rval = 0; - result = (char *)xmalloc (rsize = 64); + result = (char *)xmalloc (rsize = ZBUFSIZ); rind = 0; while (1) @@ -72,7 +76,7 @@ zmapfd (fd, ostr, fn) return -1; } - RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, 128); + RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, ZBUFSIZ); memcpy (result+rind, lbuf, nr); rind += nr; } diff --git a/lib/sh/zread.c b/lib/sh/zread.c index 8b7ecedf..71a06a76 100644 --- a/lib/sh/zread.c +++ b/lib/sh/zread.c @@ -1,6 +1,6 @@ /* zread - read data from file descriptor into buffer with retries */ -/* Copyright (C) 1999-2017 Free Software Foundation, Inc. +/* Copyright (C) 1999-2020 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -37,6 +37,10 @@ extern int errno; # define SEEK_CUR 1 #endif +#ifndef ZBUFSIZ +# define ZBUFSIZ 4096 +#endif + extern int executing_builtin; extern void check_signals_and_traps (void); @@ -55,12 +59,17 @@ zread (fd, buf, len) check_signals (); /* check for signals before a blocking read */ while ((r = read (fd, buf, len)) < 0 && errno == EINTR) - /* XXX - bash-5.0 */ - /* We check executing_builtin and run traps here for backwards compatibility */ - if (executing_builtin) - check_signals_and_traps (); /* XXX - should it be check_signals()? */ - else - check_signals (); + { + int t; + t = errno; + /* XXX - bash-5.0 */ + /* We check executing_builtin and run traps here for backwards compatibility */ + if (executing_builtin) + check_signals_and_traps (); /* XXX - should it be check_signals()? */ + else + check_signals (); + errno = t; + } return r; } @@ -112,7 +121,7 @@ zreadintr (fd, buf, len) in read(2). This does some local buffering to avoid many one-character calls to read(2), like those the `read' builtin performs. */ -static char lbuf[128]; +static char lbuf[ZBUFSIZ]; static size_t lind, lused; ssize_t |