Bash-4.3 distribution sources and documentation

This commit is contained in:
Chet Ramey 2014-02-26 09:36:43 -05:00
commit ac50fbac37
497 changed files with 129395 additions and 87598 deletions

View file

@ -92,7 +92,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.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 shmbchar.c
strchrnul.c unicode.c wcswidth.c wcsnwidth.c shmbchar.c strdup.c
# The header files for this library.
HSOURCES =
@ -106,7 +106,8 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
strtrans.o snprintf.o mailstat.o fmtulong.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 ${LIBOBJS}
input_avail.o mbscasecmp.o fnxform.o unicode.o shmbchar.o \
wcsnwidth.o ${LIBOBJS}
SUPPORT = Makefile
@ -197,6 +198,7 @@ uconvert.o: uconvert.c
ufuncs.o: ufuncs.c
vprint.o: vprint.c
wcsdup.o: wcsdup.c
wcsnwidth.o: wcsnwidth.c
wcswidth.o: wcswidth.c
mbschr.o: mbschr.c
zcatfd.o: zcatfd.c
@ -269,6 +271,7 @@ uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
vprint.o: ${BUILD_DIR}/config.h
wcsdup.o: ${BUILD_DIR}/config.h
wcsnwidth.o: ${BUILD_DIR}/config.h
wcswidth.o: ${BUILD_DIR}/config.h
mbschr.o: ${BUILD_DIR}/config.h
zcatfd.o: ${BUILD_DIR}/config.h
@ -291,7 +294,7 @@ getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
getenv.o: ${BUILD_DIR}/version.h
#getenv.o: ${BUILD_DIR}/version.h
inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
inet_aton.o: ${BASHINCDIR}/stdc.h
@ -303,7 +306,8 @@ itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir
itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#itos.o: ${BUILD_DIR}/version.h
makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@ -312,7 +316,8 @@ makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#makepath.o: ${BUILD_DIR}/version.h
netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
netconn.o: ${topdir}/bashtypes.h
@ -324,8 +329,9 @@ netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
#netopen.o: ${BUILD_DIR}/version.h
oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@ -334,9 +340,10 @@ oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdi
oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#oslib.o: ${BUILD_DIR}/version.h
pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@ -345,9 +352,10 @@ pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#pathcanon.o: ${BUILD_DIR}/version.h
pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@ -356,9 +364,10 @@ pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
#pathphys.o: ${BUILD_DIR}/version.h
rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
rename.o: ${BASHINCDIR}/posixstat.h
@ -377,7 +386,8 @@ eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${top
eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#eaccess.o: ${BUILD_DIR}/version.h
shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
@ -403,7 +413,8 @@ strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#strerror.o: ${BUILD_DIR}/version.h
strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
@ -415,7 +426,8 @@ stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${
stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#stringlist.o: ${BUILD_DIR}/version.h
stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
@ -424,7 +436,8 @@ stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${t
stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#stringvec.o: ${BUILD_DIR}/version.h
strnlen.o: ${BASHINCDIR}/stdc.h
@ -461,7 +474,8 @@ strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${to
strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
#strtrans.o: ${BUILD_DIR}/version.h
times.o: ${BASHINCDIR}/systimes.h
times.o: ${BASHINCDIR}/posixtime.h
@ -510,6 +524,9 @@ wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsdup.o: ${BASHINCDIR}/stdc.h
wcsdup.o: ${topdir}/xmalloc.h
wcsnwidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsnwidth.o: ${BASHINCDIR}/stdc.h
wcswidth.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcswidth.o: ${BASHINCDIR}/stdc.h

View file

@ -36,8 +36,10 @@
#include <ctype.h>
#include <xmalloc.h>
#include <shmbchar.h>
#include <shmbutil.h>
#include <chartypes.h>
#include <typemax.h>
#include <glob/strmatch.h>
@ -67,6 +69,10 @@
extern char *substring __P((char *, int, int));
#ifndef UCHAR_MAX
# define UCHAR_MAX TYPE_MAXIMUM(unsigned char)
#endif
#if defined (HANDLE_MULTIBYTE)
static wchar_t
cval (s, i)
@ -78,7 +84,7 @@ cval (s, i)
int l;
mbstate_t mps;
if (MB_CUR_MAX == 1)
if (MB_CUR_MAX == 1 || is_basic (s[i]))
return ((wchar_t)s[i]);
l = strlen (s);
if (i >= (l - 1))
@ -140,8 +146,10 @@ sh_modcase (string, pat, flags)
if (iswalnum (wc) == 0)
{
inword = 0;
#if 0
ADVANCE_CHAR (ret, end, start);
continue;
#endif
}
if (pat)
@ -202,8 +210,11 @@ sh_modcase (string, pat, flags)
else
nop = flags;
if (MB_CUR_MAX == 1 || isascii (wc))
/* Need to check UCHAR_MAX since wc may have already been converted to a
wide character by cval() */
if (MB_CUR_MAX == 1 || (wc <= UCHAR_MAX && is_basic ((int)wc)))
{
singlebyte:
switch (nop)
{
default:
@ -220,15 +231,18 @@ sh_modcase (string, pat, flags)
{
m = mbrtowc (&wc, string + start, end - start, &state);
if (MB_INVALIDCH (m))
wc = (wchar_t)string[start];
{
wc = (unsigned char)string[start];
goto singlebyte;
}
else if (MB_NULLWCH (m))
wc = L'\0';
switch (nop)
{
default:
case CASE_NOOP: nwc = wc; break;
case CASE_UPPER: nwc = TOUPPER (wc); break;
case CASE_LOWER: nwc = TOLOWER (wc); break;
case CASE_UPPER: nwc = _to_wupper (wc); break;
case CASE_LOWER: nwc = _to_wlower (wc); break;
case CASE_TOGGLEALL:
case CASE_TOGGLE: nwc = TOGGLE (wc); break;
}

View file

@ -21,7 +21,9 @@
#include <config.h>
#include <bashtypes.h>
#include <sys/param.h>
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>

View file

@ -205,14 +205,16 @@ sh_eaccess (path, mode)
if (path_is_devfd (path))
return (sh_stataccess (path, mode));
#if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
return (faccessat (AT_FDCWD, path, mode, AT_EACCESS));
#elif defined (HAVE_EACCESS) /* FreeBSD */
#if (defined (HAVE_FACCESSAT) && defined (AT_EACCESS)) || defined (HAVE_EACCESS)
# if defined (HAVE_FACCESSAT) && defined (AT_EACCESS)
ret = faccessat (AT_FDCWD, path, mode, AT_EACCESS);
# else /* HAVE_EACCESS */ /* FreeBSD */
ret = eaccess (path, mode); /* XXX -- not always correct for X_OK */
# if defined (__FreeBSD__)
# endif /* HAVE_EACCESS */
# if defined (__FreeBSD__) || defined (SOLARIS)
if (ret == 0 && current_user.euid == 0 && mode == X_OK)
return (sh_stataccess (path, mode));
# endif
# endif /* __FreeBSD__ || SOLARIS */
return ret;
#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
return access (path, mode|EFF_ONLY_OK);
@ -233,7 +235,6 @@ sh_eaccess (path, mode)
return (sh_stataccess (path, mode));
#endif
return ret;
}
return (sh_stataccess (path, mode));

View file

@ -1,6 +1,6 @@
/* fmtulong.c -- Convert unsigned long int to string. */
/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
/* Copyright (C) 1998-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -98,8 +98,9 @@ fmtulong (ui, base, buf, len, flags)
if (base < 2 || base > 64)
{
#if 1
/* XXX - truncation possible with long translation */
strncpy (buf, _("invalid base"), len - 1);
buf[len] = '\0';
buf[len-1] = '\0';
errno = EINVAL;
return (p = buf);
#else

View file

@ -48,7 +48,7 @@
#include <bashansi.h>
#if defined (BROKEN_DIRENT_D_INO)
#if !defined (D_FILENO_AVAILABLE)
# include "command.h"
# include "general.h"
# include "externs.h"
@ -71,7 +71,7 @@ extern int errno;
/* If the d_fileno member of a struct dirent doesn't return anything useful,
we need to check inode number equivalence the hard way. Return 1 if
the inode corresponding to PATH/DIR is identical to THISINO. */
#if defined (BROKEN_DIRENT_D_INO)
#if !defined (D_FILENO_AVAILABLE)
static int
_path_checkino (dotp, name, thisino)
char *dotp;
@ -206,7 +206,7 @@ getcwd (buf, size)
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
#if !defined (BROKEN_DIRENT_D_INO)
#if defined (D_FILENO_AVAILABLE)
if (mount_point || d->d_fileno == thisino)
#else
if (mount_point || _path_checkino (dotp, d->d_name, thisino))

View file

@ -67,7 +67,9 @@ static char rcsid[] = "$Id: inet_addr.c,v 1.5 1996/08/14 03:48:37 drepper Exp $"
#if !defined (HAVE_INET_ATON) && defined (HAVE_NETWORK) && defined (HAVE_NETINET_IN_H) && defined (HAVE_ARPA_INET_H)
#include <sys/types.h>
#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>

View file

@ -50,6 +50,18 @@ itos (i)
return (savestring (p));
}
/* Integer to string conversion. This conses the string using strdup;
caller should free it and be prepared to deal with NULL return. */
char *
mitos (i)
intmax_t i;
{
char *p, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
p = fmtumax (i, 10, lbuf, sizeof(lbuf), 0);
return (strdup (p));
}
char *
uinttostr (i, buf, len)
uintmax_t i;

View file

@ -28,7 +28,7 @@
#include <posixdir.h>
#include <bashansi.h>
#ifndef _MINIX
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif

View file

@ -94,7 +94,7 @@ sh_makepath (path, dir, flags)
MAKEDOT();
}
else if ((flags & MP_IGNDOT) && path[0] == '.' && (path[1] == '\0' ||
path[1] == '/' && path[2] == '\0'))
(path[1] == '/' && path[2] == '\0')))
{
xpath = nullpath;
pathlen = 0;

View file

@ -27,6 +27,8 @@
#include "bashansi.h"
#include "shmbutil.h"
extern int locale_mb_cur_max;
#undef mbschr
/* In some locales, the non-first byte of some multibyte characters have
@ -51,7 +53,7 @@ mbschr (s, c)
GBK, GB18030, SHIFT_JIS, and JOHAB. They exhibit the problem only
when c >= 0x30. We can therefore use the faster bytewise search if
c <= 0x30. */
if ((unsigned char)c >= '0' && MB_CUR_MAX > 1)
if ((unsigned char)c >= '0' && locale_mb_cur_max > 1)
{
pos = (char *)s;
memset (&state, '\0', sizeof(mbstate_t));
@ -59,9 +61,14 @@ mbschr (s, c)
while (strlength > 0)
{
mblength = mbrlen (pos, strlength, &state);
if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
if (is_basic (*pos))
mblength = 1;
else
{
mblength = mbrlen (pos, strlength, &state);
if (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == (size_t)0)
mblength = 1;
}
if (mblength == 1 && c == (unsigned char)*pos)
return pos;

View file

@ -41,8 +41,6 @@
#ifndef VMS
#include <sys/types.h> /* Some systems define `time_t' here. */
#else
#include <stddef.h>
#endif
#include <time.h>

View file

@ -21,7 +21,7 @@
#include <config.h>
#include <bashtypes.h>
#ifndef _MINIX
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
@ -124,7 +124,7 @@ dup2 (fd1, fd2)
/*
* Return the total number of available file descriptors.
*
* On some systems, like 4.2BSD and its descendents, there is a system call
* On some systems, like 4.2BSD and its descendants, there is a system call
* that returns the size of the descriptor table: getdtablesize(). There are
* lots of ways to emulate this on non-BSD systems.
*

View file

@ -21,7 +21,7 @@
#include <config.h>
#include <bashtypes.h>
#ifndef _MINIX
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <posixstat.h>

View file

@ -21,7 +21,7 @@
#include <config.h>
#include <bashtypes.h>
#ifndef _MINIX
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif
#include <posixstat.h>
@ -269,7 +269,7 @@ sh_realpath (pathname, resolved)
wd = get_working_directory ("sh_realpath");
if (wd == 0)
return ((char *)NULL);
tdir = sh_makepath ((char *)pathname, wd, 0);
tdir = sh_makepath (wd, (char *)pathname, 0);
free (wd);
}
else

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
/* Copyright (C) 2001, 2006, 2009, 2010, 2012 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
@ -89,4 +89,25 @@ mbsmbchar (s)
}
return 0;
}
int
sh_mbsnlen(src, srclen, maxlen)
const char *src;
size_t srclen;
int maxlen;
{
int count;
int sind;
DECLARE_MBSTATE;
for (sind = count = 0; src[sind]; )
{
count++; /* number of multibyte characters */
ADVANCE_CHAR (src, srclen, sind);
if (sind > maxlen)
break;
}
return count;
}
#endif

View file

@ -32,6 +32,50 @@
#include "syntax.h"
#include <xmalloc.h>
/* Default set of characters that should be backslash-quoted in strings */
static const char bstab[256] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, /* TAB, NL */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 1, 1, /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
1, 1, 1, 0, 1, 0, 0, 0, /* LPAR, RPAR, STAR, COMMA */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 1, 1, /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 0, /* LBRACK, BS, RBRACK, CARAT */
1, 0, 0, 0, 0, 0, 0, 0, /* BACKQ */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, /* LBRACE, BAR, RBRACE */
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
/* **************************************************************** */
/* */
/* Functions for quoting strings to be re-read as input */
@ -50,6 +94,15 @@ sh_single_quote (string)
result = (char *)xmalloc (3 + (4 * strlen (string)));
r = result;
if (string[0] == '\'' && string[1] == 0)
{
*r++ = '\\';
*r++ = '\'';
*r++ = 0;
return result;
}
*r++ = '\'';
for (s = string; s && (c = *s); s++)
@ -163,53 +216,33 @@ sh_un_double_quote (string)
way to protect the CTLESC and CTLNUL characters. As I write this,
the current callers will never cause the string to be expanded without
going through the shell parser, which will protect the internal
quoting characters. */
quoting characters. TABLE, if set, points to a map of the ascii code
set with char needing to be backslash-quoted if table[char]==1. FLAGS,
if 1, causes tildes to be quoted as well. */
char *
sh_backslash_quote (string)
sh_backslash_quote (string, table, flags)
char *string;
char *table;
int flags;
{
int c;
char *result, *r, *s;
char *result, *r, *s, *backslash_table;
result = (char *)xmalloc (2 * strlen (string) + 1);
backslash_table = table ? table : (char *)bstab;
for (r = result, s = string; s && (c = *s); s++)
{
switch (c)
{
case ' ': case '\t': case '\n': /* IFS white space */
case '\'': case '"': case '\\': /* quoting chars */
case '|': case '&': case ';': /* shell metacharacters */
case '(': case ')': case '<': case '>':
case '!': case '{': case '}': /* reserved words */
case '*': case '[': case '?': case ']': /* globbing chars */
case '^':
case '$': case '`': /* expansion chars */
case ',': /* brace expansion */
*r++ = '\\';
*r++ = c;
break;
#if 0
case '~': /* tilde expansion */
if (s == string || s[-1] == '=' || s[-1] == ':')
*r++ = '\\';
*r++ = c;
break;
case CTLESC: case CTLNUL: /* internal quoting characters */
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
break;
#endif
case '#': /* comment char */
if (s == string)
*r++ = '\\';
/* FALLTHROUGH */
default:
*r++ = c;
break;
}
if (backslash_table[c] == 1)
*r++ = '\\';
else if (c == '#' && s == string) /* comment char */
*r++ = '\\';
else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
/* Tildes are special at the start of a word or after a `:' or `='
(technically unquoted, but it doesn't make a difference in practice) */
*r++ = '\\';
*r++ = c;
}
*r = '\0';

View file

@ -9,7 +9,7 @@
Unix snprintf implementation.
derived from inetutils/libinetutils/snprintf.c Version 1.1
Copyright (C) 2001,2006,2010 Free Software Foundation, Inc.
Copyright (C) 2001,2006,2010,2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -26,7 +26,7 @@
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
Revision History:
Original (pre-bash) Revision History:
1.1:
* added changes from Miles Bader
@ -50,7 +50,6 @@
* Currently doesn't handle (and bash/readline doesn't use):
* * *M$ width, precision specifications
* * %N$ numbered argument conversions
* * inf, nan floating values imperfect (if isinf(), isnan() not in libc)
* * support for `F' is imperfect with ldfallback(), since underlying
* printf may not handle it -- should ideally have another autoconf test
*/
@ -303,11 +302,30 @@ static void dfallback __P((struct DATA *, const char *, const char *, double));
static char *groupnum __P((char *));
#ifndef HAVE_ISINF_IN_LIBC
static int isinf __P((double));
#if defined (HAVE_LONG_DOUBLE)
# define LONGDOUBLE long double
#else
# define LONGDOUBLE double
#endif
#ifndef HAVE_ISNAN_IN_LIBC
static int isnan __P((double));
#ifndef isnan
static inline int isnan_f (float x) { return x != x; }
static inline int isnan_d (double x) { return x != x; }
static inline int isnan_ld (LONGDOUBLE x) { return x != x; }
# define isnan(x) \
(sizeof (x) == sizeof (LONGDOUBLE) ? isnan_ld (x) \
: sizeof (x) == sizeof (double) ? isnan_d (x) \
: isnan_f (x))
#endif
#ifndef isinf
static inline int isinf_f (float x) { return !isnan (x) && isnan (x - x); }
static inline int isinf_d (double x) { return !isnan (x) && isnan (x - x); }
static inline int isinf_ld (LONGDOUBLE x) { return !isnan (x) && isnan (x - x); }
# define isinf(x) \
(sizeof (x) == sizeof (LONGDOUBLE) ? isinf_ld (x) \
: sizeof (x) == sizeof (double) ? isinf_d (x) \
: isinf_f (x))
#endif
#ifdef DRIVER
@ -371,7 +389,7 @@ static void xfree __P((void *));
while (0)
#define PUT_PLUS(d, p, zero) \
if ((d) > zero && (p)->justify == RIGHT) \
if (((p)->flags & PF_PLUS) && (d) > zero) \
PUT_CHAR('+', p)
#define PUT_SPACE(d, p, zero) \
@ -431,9 +449,9 @@ static void xfree __P((void *));
if (lv) \
{ \
if (lv->decimal_point && lv->decimal_point[0]) \
(d) = lv->decimal_point[0]; \
(d) = lv->decimal_point[0]; \
if (lv->thousands_sep && lv->thousands_sep[0]) \
(t) = lv->thousands_sep[0]; \
(t) = lv->thousands_sep[0]; \
(g) = lv->grouping ? lv->grouping : ""; \
if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
} \
@ -574,7 +592,7 @@ integral(real, ip)
/*
* return an ascii representation of the integral part of the number
* and set fract to be an ascii representation of the fraction part
* the container for the fraction and the integral part or staticly
* the container for the fraction and the integral part or statically
* declare with fix size
*/
static char *
@ -586,10 +604,9 @@ numtoa(number, base, precision, fract)
register int i, j;
double ip, fp; /* integer and fraction part */
double fraction;
int digits = MAX_INT - 1;
int digits, sign;
static char integral_part[MAX_INT];
static char fraction_part[MAX_FRACT];
double sign;
int ch;
/* taking care of the obvious case: 0.0 */
@ -607,8 +624,12 @@ numtoa(number, base, precision, fract)
return integral_part;
}
/* -0 is tricky */
sign = (number == -0.) ? '-' : ((number < 0.) ? '-' : '+');
digits = MAX_INT - 1;
/* for negative numbers */
if ((sign = number) < 0.)
if (sign == '-')
{
number = -number;
digits--; /* sign consume one digit */
@ -643,7 +664,7 @@ numtoa(number, base, precision, fract)
integral_part[i] = '9';
/* put the sign ? */
if (sign < 0.)
if (sign == '-')
integral_part[i++] = '-';
integral_part[i] = '\0';
@ -682,9 +703,13 @@ number(p, d, base)
long sd;
int flags;
/* An explicit precision turns off the zero-padding flag. */
/* An explicit precision turns off the zero-padding flag and sets the
pad character back to space. */
if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
p->flags &= ~PF_ZEROPAD;
{
p->flags &= ~PF_ZEROPAD;
p->pad = ' ';
}
sd = d; /* signed for ' ' padding in base 10 */
flags = 0;
@ -698,10 +723,11 @@ number(p, d, base)
{
GETLOCALEDATA(decpoint, thoussep, grouping);
if (grouping && (t = groupnum (tmp)))
tmp = t;
tmp = t;
}
p->width -= strlen(tmp);
/* need to add one for any `+', but we only add one in base 10 */
p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
PAD_RIGHT(p);
if ((p->flags & PF_DOT) && p->precision > 0)
@ -753,9 +779,13 @@ lnumber(p, d, base)
long long sd;
int flags;
/* An explicit precision turns off the zero-padding flag. */
/* An explicit precision turns off the zero-padding flag and sets the
pad character back to space. */
if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
p->flags &= ~PF_ZEROPAD;
{
p->flags &= ~PF_ZEROPAD;
p->pad = ' ';
}
sd = d; /* signed for ' ' padding in base 10 */
flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
@ -768,10 +798,11 @@ lnumber(p, d, base)
{
GETLOCALEDATA(decpoint, thoussep, grouping);
if (grouping && (t = groupnum (tmp)))
tmp = t;
tmp = t;
}
p->width -= strlen(tmp);
/* need to add one for any `+', but we only add one in base 10 */
p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
PAD_RIGHT(p);
if ((p->flags & PF_DOT) && p->precision > 0)
@ -875,11 +906,11 @@ wstrings(p, tmp)
{
len = wcsrtombs (NULL, &ws, 0, &mbs);
if (len != (size_t)-1)
{
{
memset (&mbs, '\0', sizeof (mbstate_t));
os = (char *)xmalloc (len + 1);
(void)wcsrtombs (os, &ws, len + 1, &mbs);
}
}
}
if (len == (size_t)-1)
{
@ -919,32 +950,6 @@ wchars (p, wc)
#ifdef FLOATING_POINT
#ifndef HAVE_ISINF_IN_LIBC
/* Half-assed versions, since we don't want to link with libm. */
static int
isinf(d)
double d;
{
#ifdef DBL_MAX
if (d < DBL_MIN)
return -1;
else if (d > DBL_MAX)
return 1;
else
#endif
return 0;
}
#endif
#ifndef HAVE_ISNAN_IN_LIBC
static int
isnan(d)
double d;
{
return 0;
}
#endif
/* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
(mode == 2) we check for NaN. This does the necessary printing. Returns
1 if Inf or Nan, 0 if not. */
@ -1002,19 +1007,35 @@ floating(p, d)
{
/* smash the trailing zeros unless altform */
for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
tmp2[i] = '\0';
tmp2[i] = '\0';
if (tmp2[0] == '\0')
p->precision = 0;
}
/* calculate the padding. 1 for the dot */
p->width = p->width -
/* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
#if 0
((d > 0. && p->justify == RIGHT) ? 1:0) -
#else
((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
#endif
((p->flags & PF_SPACE) ? 1:0) -
strlen(tmp) - p->precision -
((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */
PAD_RIGHT(p);
PUT_PLUS(d, p, 0.);
if (p->pad == ' ')
{
PAD_RIGHT(p);
PUT_PLUS(d, p, 0.);
}
else
{
if (*tmp == '-')
PUT_CHAR(*tmp++, p);
PUT_PLUS(d, p, 0.);
PAD_RIGHT(p);
}
PUT_SPACE(d, p, 0.);
while (*tmp)
@ -1058,14 +1079,30 @@ exponent(p, d)
tmp = dtoa(d, p->precision, &tmp2);
/* 1 for unit, 1 for the '.', 1 for 'e|E',
* 1 for '+|-', 2 for 'exp' */
* 1 for '+|-', 2 for 'exp' (but no `.' if precision == 0 */
/* calculate how much padding need */
p->width = p->width -
/* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
#if 0
((d > 0. && p->justify == RIGHT) ? 1:0) -
((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
#else
((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
#endif
(p->precision != 0 || (p->flags & PF_ALTFORM)) -
((p->flags & PF_SPACE) ? 1:0) - p->precision - 5;
PAD_RIGHT(p);
PUT_PLUS(d, p, 0.);
if (p->pad == ' ')
{
PAD_RIGHT(p);
PUT_PLUS(d, p, 0.);
}
else
{
if (*tmp == '-')
PUT_CHAR(*tmp++, p);
PUT_PLUS(d, p, 0.);
PAD_RIGHT(p);
}
PUT_SPACE(d, p, 0.);
while (*tmp)
@ -1163,7 +1200,7 @@ groupnum (s)
else if (*g == CHAR_MAX)
{
do
*--re = *--se;
*--re = *--se;
while (se > s);
break;
}
@ -1295,10 +1332,6 @@ vsnprintf_internal(data, string, length, format, args)
case '#':
data->flags |= PF_ALTFORM;
continue;
case '0':
data->flags |= PF_ZEROPAD;
data->pad = '0';
continue;
case '*':
if (data->flags & PF_DOT)
data->flags |= PF_STAR_P;
@ -1322,13 +1355,25 @@ vsnprintf_internal(data, string, length, format, args)
if ((data->flags & PF_DOT) == 0)
{
data->flags |= PF_PLUS;
data->justify = RIGHT;
if ((data->flags & PF_LADJUST) == 0)
data->justify = RIGHT;
}
continue;
case '\'':
data->flags |= PF_THOUSANDS;
continue;
case '0':
/* If we're not specifying precision (in which case we've seen
a `.') and we're not performing left-adjustment (in which
case the `0' is ignored), a `0' is taken as the zero-padding
flag. */
if ((data->flags & (PF_DOT|PF_LADJUST)) == 0)
{
data->flags |= PF_ZEROPAD;
data->pad = '0';
continue;
}
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
@ -1410,8 +1455,9 @@ conv_break:
else
{
/* reduce precision by 1 because of leading digit before
decimal point in e format. */
data->precision--;
decimal point in e format, unless specified as 0. */
if (data->precision > 0)
data->precision--;
exponent(data, d);
}
state = 0;

View file

@ -30,7 +30,7 @@
#include <bashtypes.h>
#include <posixdir.h>
#include <posixstat.h>
#ifndef _MINIX
#if defined (HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif

View file

@ -1,5 +1,5 @@
/* Searching in a string.
Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Copyright (C) 2012 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
@ -15,130 +15,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <stdio.h>
/* Specification. */
#include <string.h>
/* On 32-bit hardware, choosing longword to be a 32-bit unsigned
long instead of a 64-bit uintmax_t tends to give better
performance. On 64-bit hardware, unsigned long is generally 64
bits already. Change this typedef to experiment with
performance. */
typedef unsigned long int longword;
/* Find the first occurrence of C in S or the final NUL byte. */
char *
strchrnul (s, c_in)
const char *s;
int c_in;
{
const unsigned char *char_ptr;
const longword *longword_ptr;
longword repeated_one;
longword repeated_c;
unsigned char c;
char c;
register char *s1;
c = (unsigned char) c_in;
if (c == 0) /* find final null byte */
return (char *)(s ? (s + strlen (s)) : s);
/* Handle the first few bytes by reading one byte at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
for (char_ptr = (const unsigned char *) s;
(size_t) char_ptr % sizeof (longword) != 0;
++char_ptr)
if (!*char_ptr || *char_ptr == c)
return (char *) char_ptr;
longword_ptr = (const longword *) char_ptr;
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to any size longwords. */
/* Compute auxiliary longword values:
repeated_one is a value which has a 1 in every byte.
repeated_c has c in every byte. */
repeated_one = 0x01010101;
repeated_c = c | (c << 8);
repeated_c |= repeated_c << 16;
if (0xffffffffU < (longword) -1)
{
repeated_one |= repeated_one << 31 << 1;
repeated_c |= repeated_c << 31 << 1;
if (8 < sizeof (longword))
{
size_t i;
for (i = 64; i < sizeof (longword) * 8; i *= 2)
{
repeated_one |= repeated_one << i;
repeated_c |= repeated_c << i;
}
}
}
/* Instead of the traditional loop which tests each byte, we will
test a longword at a time. The tricky part is testing if *any of
the four* bytes in the longword in question are equal to NUL or
c. We first use an xor with repeated_c. This reduces the task
to testing whether *any of the four* bytes in longword1 or
longword2 is zero.
Let's consider longword1. We compute tmp =
((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
That is, we perform the following operations:
1. Subtract repeated_one.
2. & ~longword1.
3. & a mask consisting of 0x80 in every byte.
Consider what happens in each byte:
- If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
and step 3 transforms it into 0x80. A carry can also be propagated
to more significant bytes.
- If a byte of longword1 is nonzero, let its lowest 1 bit be at
position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
the byte ends in a single bit of value 0 and k bits of value 1.
After step 2, the result is just k bits of value 1: 2^k - 1. After
step 3, the result is 0. And no carry is produced.
So, if longword1 has only non-zero bytes, tmp is zero.
Whereas if longword1 has a zero byte, call j the position of the least
significant zero byte. Then the result has a zero at positions 0, ...,
j-1 and a 0x80 at position j. We cannot predict the result at the more
significant bytes (positions j+1..3), but it does not matter since we
already have a non-zero bit at position 8*j+7.
The test whether any byte in longword1 or longword2 is zero is equivalent
to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine
this into a single test, whether (tmp1 | tmp2) is nonzero.
This test can read more than one byte beyond the end of a string,
depending on where the terminating NUL is encountered. However,
this is considered safe since the initialization phase ensured
that the read will be aligned, therefore, the read will not cross
page boundaries and will not cause a fault. */
while (1)
{
longword longword1 = *longword_ptr ^ repeated_c;
longword longword2 = *longword_ptr;
if (((((longword1 - repeated_one) & ~longword1)
| ((longword2 - repeated_one) & ~longword2))
& (repeated_one << 7)) != 0)
break;
longword_ptr++;
}
char_ptr = (const unsigned char *) longword_ptr;
/* At this point, we know that one of the sizeof (longword) bytes
starting at char_ptr is == 0 or == c. On little-endian machines,
we could determine the first such byte without any further memory
accesses, just by looking at the tmp result from the last loop
iteration. But this does not work on big-endian machines.
Choose code that works in both cases. */
char_ptr = (unsigned char *) longword_ptr;
while (*char_ptr && (*char_ptr != c))
char_ptr++;
return (char *) char_ptr;
for (c = c_in, s1 = (char *)s; s1 && *s1 && *s1 != c; s1++)
;
return (s1);
}

42
lib/sh/strdup.c Normal file
View file

@ -0,0 +1,42 @@
/* strdup - return a copy of a string in newly-allocated memory. */
/* Copyright (C) 2013 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>
/* Get specification. */
#include <string.h>
#include <stdlib.h>
/* Duplicate S, returning an identical malloc'd string. */
char *
strdup (s)
const char *s;
{
size_t len;
void *new;
len = strlen (s) + 1;
if ((new = malloc (len)) == NULL)
return NULL;
memcpy (new, s, len);
return ((char *)new);
}

View file

@ -23,7 +23,7 @@
#if !defined (HAVE_STRERROR)
#include <bashtypes.h>
#ifndef _MINIX
#if defined (HAVE_SYS_PARAM_H)
# include <sys/param.h>
#endif

View file

@ -38,6 +38,7 @@
* Updated September, 2000
* Updated December, 2001
* Updated January, 2011
* Updated April, 2012
*
* Fixes from ado@elsie.nci.nih.gov,
* February 1991, May 1992
@ -75,6 +76,7 @@
#define VMS_EXT 1 /* include %v for VMS date format */
#define HPUX_EXT 1 /* non-conflicting stuff in HP-UX date */
#define POSIX_SEMANTICS 1 /* call tzset() if TZ changes */
#define POSIX_2008 1 /* flag and fw for C, F, G, Y formats */
#undef strchr /* avoid AIX weirdness */
@ -96,27 +98,25 @@ static int iso8601wknum(const struct tm *timeptr);
#define range(low, item, hi) max(low, min(item, hi))
#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
/* Whew! This stuff is a mess. */
#if !defined(OS2) && !defined(MSDOS) && !defined(__CYGWIN__) && defined(HAVE_TZNAME)
extern char *tzname[2];
extern int daylight;
#if defined(SOLARIS) || defined(mips) || defined (M_UNIX)
extern long int timezone, altzone;
#else
# if defined (HPUX)
# if defined (HPUX) || defined(__hpux)
extern long int timezone;
# else
# if !defined(__CYGWIN__)
extern int timezone, altzone;
# endif /* !HPUX */
#endif /* !SOLARIS && !mips && !M_UNIX */
# endif
# endif
#endif
#endif
#undef min /* just in case */
/* format for %+ -- currently unused */
#ifndef NATIONAL_FORMAT
#define NATIONAL_FORMAT "%a %b %e %H:%M:%S %Z %Y"
#endif
/* min --- return minimum of two numbers */
static inline int
@ -135,6 +135,34 @@ max(int a, int b)
return (a > b ? a : b);
}
#ifdef POSIX_2008
/* iso_8601_2000_year --- format a year per ISO 8601:2000 as in 1003.1 */
static void
iso_8601_2000_year(char *buf, int year, size_t fw)
{
int extra;
char sign = '\0';
if (year >= -9999 && year <= 9999) {
sprintf(buf, "%0*d", (int) fw, year);
return;
}
/* now things get weird */
if (year > 9999) {
sign = '+';
} else {
sign = '-';
year = -year;
}
extra = year / 10000;
year %= 10000;
sprintf(buf, "%c_%04d_%d", sign, extra, year);
}
#endif /* POSIX_2008 */
/* strftime --- produce formatted time */
size_t
@ -155,12 +183,19 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#ifndef HAVE_TM_ZONE
#ifndef HAVE_TM_NAME
#ifndef HAVE_TZNAME
#ifndef __CYGWIN__
extern char *timezone();
struct timeval tv;
struct timezone zone;
#endif /* __CYGWIN__ */
#endif /* HAVE_TZNAME */
#endif /* HAVE_TM_NAME */
#endif /* HAVE_TM_ZONE */
#ifdef POSIX_2008
int pad;
size_t fw;
char flag;
#endif /* POSIX_2008 */
/* various tables, useful in North America */
static const char *days_a[] = {
@ -234,6 +269,40 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
*s++ = *format;
continue;
}
#ifdef POSIX_2008
pad = '\0';
fw = 0;
flag = '\0';
switch (*++format) {
case '+':
flag = '+';
/* fall through */
case '0':
pad = '0';
format++;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
break;
default:
format--;
goto again;
}
for (; isdigit(*format); format++) {
fw = fw * 10 + (*format - '0');
}
format--;
#endif /* POSIX_2008 */
again:
switch (*++format) {
case '\0':
@ -285,8 +354,19 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
break;
case 'C':
#ifdef POSIX_2008
if (pad != '\0' && fw > 0) {
size_t min_fw = (flag ? 3 : 2);
fw = max(fw, min_fw);
sprintf(tbuf, flag
? "%+0*ld"
: "%0*ld", (int) fw,
(timeptr->tm_year + 1900L) / 100);
} else
#endif /* POSIX_2008 */
century:
sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
sprintf(tbuf, "%02ld", (timeptr->tm_year + 1900L) / 100);
break;
case 'd': /* day of the month, 01 - 31 */
@ -307,7 +387,30 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
goto again;
case 'F': /* ISO 8601 date representation */
{
#ifdef POSIX_2008
/*
* Field width for %F is for the whole thing.
* It must be at least 10.
*/
char m_d[10];
strftime(m_d, sizeof m_d, "-%m-%d", timeptr);
size_t min_fw = 10;
if (pad != '\0' && fw > 0) {
fw = max(fw, min_fw);
} else {
fw = min_fw;
}
fw -= 6; /* -XX-XX at end are invariant */
iso_8601_2000_year(tbuf, timeptr->tm_year + 1900, fw);
strcat(tbuf, m_d);
#else
strftime(tbuf, sizeof tbuf, "%Y-%m-%d", timeptr);
#endif /* POSIX_2008 */
}
break;
case 'g':
@ -329,8 +432,20 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
else
y = 1900L + timeptr->tm_year;
if (*format == 'G')
sprintf(tbuf, "%ld", y);
if (*format == 'G') {
#ifdef POSIX_2008
if (pad != '\0' && fw > 0) {
size_t min_fw = 4;
fw = max(fw, min_fw);
sprintf(tbuf, flag
? "%+0*ld"
: "%0*ld", (int) fw,
y);
} else
#endif /* POSIX_2008 */
sprintf(tbuf, "%ld", y);
}
else
sprintf(tbuf, "%02ld", y % 100);
break;
@ -455,7 +570,17 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
break;
case 'Y': /* year with century */
fullyear:
#ifdef POSIX_2008
if (pad != '\0' && fw > 0) {
size_t min_fw = 4;
fw = max(fw, min_fw);
sprintf(tbuf, flag
? "%+0*ld"
: "%0*ld", (int) fw,
1900L + timeptr->tm_year);
} else
#endif /* POSIX_2008 */
sprintf(tbuf, "%ld", 1900L + timeptr->tm_year);
break;
@ -496,12 +621,12 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
* Systems with tzname[] probably have timezone as
* secs west of GMT. Convert to mins east of GMT.
*/
# ifdef HPUX
# if defined(__hpux) || defined (HPUX) || defined(__CYGWIN__)
off = -timezone / 60;
# else
/* ADR: 4 August 2001, fixed this per gazelle@interaccess.com */
off = -(daylight ? altzone : timezone) / 60;
# endif /* !HPUX */
# endif
#else /* !HAVE_TZNAME */
gettimeofday(& tv, & zone);
off = -zone.tz_minuteswest;

View file

@ -40,6 +40,14 @@ strvec_create (n)
return ((char **)xmalloc ((n) * sizeof (char *)));
}
/* Allocate an array of strings with room for N members. */
char **
strvec_mcreate (n)
int n;
{
return ((char **)malloc ((n) * sizeof (char *)));
}
char **
strvec_resize (array, nsize)
char **array;
@ -48,6 +56,14 @@ strvec_resize (array, nsize)
return ((char **)xrealloc (array, nsize * sizeof (char *)));
}
char **
strvec_mresize (array, nsize)
char **array;
int nsize;
{
return ((char **)realloc (array, nsize * sizeof (char *)));
}
/* Return the length of ARRAY, a NULL terminated array of char *. */
int
strvec_len (array)

View file

@ -29,7 +29,7 @@
#include <stdc.h>
/* Find the first ocurrence in S of any character in ACCEPT. */
/* Find the first occurrence in S of any character in ACCEPT. */
char *
strpbrk (s, accept)
register const char *s;

View file

@ -1,6 +1,6 @@
/* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */
/* Copyright (C) 2000-2010 Free Software Foundation, Inc.
/* Copyright (C) 2000-2011 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -30,6 +30,9 @@
#include "shell.h"
#include "shmbchar.h"
#include "shmbutil.h"
#ifdef ESC
#undef ESC
#endif
@ -74,7 +77,7 @@ ansicstr (string, len, flags, sawc, rlen)
case 'a': c = '\a'; break;
case 'v': c = '\v'; break;
#else
case 'a': c = '\007'; break;
case 'a': c = (int) 0x07; break;
case 'v': c = (int) 0x0B; break;
#endif
case 'b': c = '\b'; break;
@ -144,7 +147,7 @@ ansicstr (string, len, flags, sawc, rlen)
*r++ = '\\'; /* c remains unchanged */
break;
}
else if (v <= UCHAR_MAX)
else if (v <= 0x7f) /* <= 0x7f translates directly */
{
c = v;
break;
@ -208,6 +211,11 @@ ansic_quote (str, flags, rlen)
char *r, *ret, *s;
int l, rsize;
unsigned char c;
size_t clen;
int b;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
#endif
if (str == 0 || *str == 0)
return ((char *)0);
@ -219,10 +227,13 @@ ansic_quote (str, flags, rlen)
*r++ = '$';
*r++ = '\'';
for (s = str, l = 0; *s; s++)
s = str;
for (s = str; c = *s; s++)
{
c = *s;
l = 1; /* 1 == add backslash; 0 == no backslash */
b = l = 1; /* 1 == add backslash; 0 == no backslash */
clen = 1;
switch (c)
{
case ESC: c = 'E'; break;
@ -230,7 +241,7 @@ ansic_quote (str, flags, rlen)
case '\a': c = 'a'; break;
case '\v': c = 'v'; break;
#else
case '\007': c = 'a'; break;
case 0x07: c = 'a'; break;
case 0x0b: c = 'v'; break;
#endif
@ -243,7 +254,14 @@ ansic_quote (str, flags, rlen)
case '\'':
break;
default:
#if defined (HANDLE_MULTIBYTE)
b = is_basic (c);
/* XXX - clen comparison to 0 is dicey */
if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || MB_INVALIDCH (clen) || iswprint (wc) == 0)) ||
(b == 1 && ISPRINT (c) == 0))
#else
if (ISPRINT (c) == 0)
#endif
{
*r++ = '\\';
*r++ = TOCHAR ((c >> 6) & 07);
@ -254,9 +272,20 @@ ansic_quote (str, flags, rlen)
l = 0;
break;
}
if (b == 0 && clen == 0)
break;
if (l)
*r++ = '\\';
*r++ = c;
if (clen == 1)
*r++ = c;
else
{
for (b = 0; b < (int)clen; b++)
*r++ = (unsigned char)s[b];
s += clen - 1; /* -1 because of the increment above */
}
}
*r++ = '\'';
@ -266,6 +295,37 @@ ansic_quote (str, flags, rlen)
return ret;
}
#if defined (HANDLE_MULTIBYTE)
int
ansic_wshouldquote (string)
const char *string;
{
const wchar_t *wcs;
wchar_t wcc;
wchar_t *wcstr = NULL;
size_t slen;
slen = mbstowcs (wcstr, string, 0);
if (slen == -1)
slen = 0;
wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
mbstowcs (wcstr, string, slen + 1);
for (wcs = wcstr; wcc = *wcs; wcs++)
if (iswprint(wcc) == 0)
{
free (wcstr);
return 1;
}
free (wcstr);
return 0;
}
#endif
/* return 1 if we need to quote with $'...' because of non-printing chars. */
int
ansic_shouldquote (string)
@ -278,8 +338,14 @@ ansic_shouldquote (string)
return 0;
for (s = string; c = *s; s++)
if (ISPRINT (c) == 0)
return 1;
{
#if defined (HANDLE_MULTIBYTE)
if (is_basic (c) == 0)
return (ansic_wshouldquote (s));
#endif
if (ISPRINT (c) == 0)
return 1;
}
return 0;
}

View file

@ -31,6 +31,8 @@
# include <unistd.h>
#endif
#include <bashansi.h>
#include <stdio.h>
#include <errno.h>
@ -135,7 +137,7 @@ sh_mktmpname (nameroot, flags)
filenum = (filenum << 1) ^
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
(unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
(unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32)
filename[tdlen + 1 + tmpnamelen] = '\0';
@ -184,7 +186,7 @@ sh_mktmpfd (nameroot, flags, namep)
filenum = (filenum << 1) ^
(unsigned long) time ((time_t *)0) ^
(unsigned long) dollar_dollar_pid ^
(unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
(unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++);
sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
if (tmpnamelen > 0 && tmpnamelen < 32)
filename[tdlen + 1 + tmpnamelen] = '\0';

View file

@ -1,6 +1,6 @@
/* unicode.c - functions to convert unicode characters */
/* Copyright (C) 2010 Free Software Foundation, Inc.
/* Copyright (C) 2010-2012 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@ -28,6 +28,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#include <limits.h>
#if HAVE_ICONV
@ -61,6 +62,8 @@ static iconv_t localconv;
#endif
#ifndef HAVE_LOCALE_CHARSET
static char charsetbuf[40];
static char *
stub_charset ()
{
@ -68,32 +71,46 @@ stub_charset ()
locale = get_locale_var ("LC_CTYPE");
if (locale == 0 || *locale == 0)
return "ASCII";
{
strcpy (charsetbuf, "ASCII");
return charsetbuf;
}
s = strrchr (locale, '.');
if (s)
{
t = strchr (s, '@');
strcpy (charsetbuf, s+1);
t = strchr (charsetbuf, '@');
if (t)
*t = 0;
return ++s;
return charsetbuf;
}
else if (STREQ (locale, "UTF-8"))
return "UTF-8";
else
return "ASCII";
strcpy (charsetbuf, locale);
return charsetbuf;
}
#endif
void
u32reset ()
{
#if defined (HAVE_ICONV)
if (u32init && localconv != (iconv_t)-1)
{
iconv_close (localconv);
localconv = (iconv_t)-1;
}
#endif
u32init = 0;
utf8locale = 0;
}
/* u32toascii ? */
int
u32tochar (wc, s)
wchar_t wc;
u32tochar (x, s)
unsigned long x;
char *s;
{
unsigned long x;
int l;
x = wc;
l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
if (x <= UCHAR_MAX)
@ -115,31 +132,107 @@ u32tochar (wc, s)
}
int
u32toutf8 (wc, s)
wchar_t wc;
u32tocesc (wc, s)
u_bits32_t wc;
char *s;
{
int l;
l = (wc < 0x0080) ? 1 : ((wc < 0x0800) ? 2 : 3);
if (wc < 0x10000)
l = sprintf (s, "\\u%04X", wc);
else
l = sprintf (s, "\\u%08X", wc);
return l;
}
/* Convert unsigned 32-bit int to utf-8 character string */
int
u32toutf8 (wc, s)
u_bits32_t wc;
char *s;
{
int l;
if (wc < 0x0080)
s[0] = (unsigned char)wc;
{
s[0] = (char)wc;
l = 1;
}
else if (wc < 0x0800)
{
s[0] = (wc >> 6) | 0xc0;
s[1] = (wc & 0x3f) | 0x80;
l = 2;
}
else
else if (wc < 0x10000)
{
/* Technically, we could return 0 here if 0xd800 <= wc <= 0x0dfff */
s[0] = (wc >> 12) | 0xe0;
s[1] = ((wc >> 6) & 0x3f) | 0x80;
s[2] = (wc & 0x3f) | 0x80;
l = 3;
}
else if (wc < 0x200000)
{
s[0] = (wc >> 18) | 0xf0;
s[1] = ((wc >> 12) & 0x3f) | 0x80;
s[2] = ((wc >> 6) & 0x3f) | 0x80;
s[3] = (wc & 0x3f) | 0x80;
l = 4;
}
/* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
else if (wc < 0x04000000)
{
s[0] = (wc >> 24) | 0xf8;
s[1] = ((wc >> 18) & 0x3f) | 0x80;
s[2] = ((wc >> 12) & 0x3f) | 0x80;
s[3] = ((wc >> 6) & 0x3f) | 0x80;
s[4] = (wc & 0x3f) | 0x80;
l = 5;
}
else if (wc < 0x080000000)
{
s[0] = (wc >> 30) | 0xf8;
s[1] = ((wc >> 24) & 0x3f) | 0x80;
s[2] = ((wc >> 18) & 0x3f) | 0x80;
s[3] = ((wc >> 12) & 0x3f) | 0x80;
s[4] = ((wc >> 6) & 0x3f) | 0x80;
s[5] = (wc & 0x3f) | 0x80;
l = 6;
}
else
l = 0;
s[l] = '\0';
return l;
}
/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
only if sizeof(wchar_t) == 2. */
int
u32toutf16 (c, s)
u_bits32_t c;
unsigned short *s;
{
int l;
l = 0;
if (c < 0x0d800)
{
s[0] = (unsigned short) (c & 0xFFFF);
l = 1;
}
else if (c >= 0x0e000 && c <= 0x010ffff)
{
c -= 0x010000;
s[0] = (unsigned short)((c >> 10) + 0xd800);
s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
l = 2;
}
s[l] = 0;
return l;
}
/* convert a single unicode-32 character into a multibyte string and put the
result in S, which must be large enough (at least MB_LEN_MAX bytes) */
int
@ -148,6 +241,7 @@ u32cconv (c, s)
char *s;
{
wchar_t wc;
wchar_t ws[3];
int n;
#if HAVE_ICONV
const char *charset;
@ -157,21 +251,23 @@ u32cconv (c, s)
size_t sn;
#endif
wc = c;
#if __STDC_ISO_10646__
if (sizeof (wchar_t) == 4)
{
n = wctomb (s, wc);
return n;
}
wc = c;
if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
n = wctomb (s, wc);
else if (sizeof (wchar_t) == 2 && c <= 0x10ffff && u32toutf16 (c, ws))
n = wcstombs (s, ws, MB_LEN_MAX);
else
n = -1;
if (n != -1)
return n;
#endif
#if HAVE_NL_LANGINFO
codeset = nl_langinfo (CODESET);
if (STREQ (codeset, "UTF-8"))
{
n = u32toutf8 (wc, s);
n = u32toutf8 (c, s);
return n;
}
#endif
@ -191,25 +287,23 @@ u32cconv (c, s)
{
localconv = iconv_open (charset, "UTF-8");
if (localconv == (iconv_t)-1)
localconv = iconv_open (charset, "ASCII");
/* We assume ASCII when presented with an unknown encoding. */
localconv = iconv_open ("ASCII", "UTF-8");
}
u32init = 1;
}
/* If we have a UTF-8 locale, convert to UTF-8 and return converted value. */
n = u32toutf8 (c, s);
if (utf8locale)
{
n = u32toutf8 (wc, s);
return n;
}
return n;
/* If the conversion is not supported, even the ASCII requested above, we
bail now. Currently we return the UTF-8 conversion. We could return
u32tocesc(). */
if (localconv == (iconv_t)-1)
{
n = u32tochar (wc, s);
return n;
}
n = u32toutf8 (wc, s);
return n;
optr = obuf;
obytesleft = sizeof (obuf);
iptr = s;
@ -218,7 +312,15 @@ u32cconv (c, s)
iconv (localconv, NULL, NULL, NULL, NULL);
if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
return n; /* You get utf-8 if iconv fails */
{
#if 1
/* You get ISO C99 escape sequences if iconv fails */
n = u32tocesc (c, s);
#else
/* You get UTF-8 if iconv fails */
#endif
return n;
}
*optr = '\0';
@ -226,10 +328,14 @@ u32cconv (c, s)
checking */
strcpy (s, obuf);
return (optr - obuf);
#endif
#endif /* HAVE_ICONV */
n = u32tochar (wc, s); /* fallback */
n = u32tocesc (c, s); /* fallback is ISO C99 escape sequences */
return n;
}
#else
void
u32reset ()
{
}
#endif /* HANDLE_MULTIBYTE */

56
lib/sh/wcsnwidth.c Normal file
View file

@ -0,0 +1,56 @@
/* wcsnwidth.c - compute display width of wide character string, up to max
specified width, return length. */
/* Copyright (C) 2012 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 (HANDLE_MULTIBYTE)
#include <stdc.h>
#include <wchar.h>
#include <bashansi.h>
/* Return the number of wide characters that will be displayed from wide string
PWCS. If the display width exceeds MAX, return the number of wide chars
from PWCS required to display MAX characters on the screen. */
int
wcsnwidth(pwcs, n, max)
const wchar_t *pwcs;
size_t n, max;
{
wchar_t wc, *ws;
int len, l;
len = 0;
ws = (wchar_t *)pwcs;
while (n-- > 0 && (wc = *ws++) != L'\0')
{
l = wcwidth (wc);
if (l < 0)
return (-1);
else if (l == max - len)
return (ws - pwcs);
else if (l > max - len)
return (--ws - pwcs);
len += l;
}
return (ws - pwcs);
}
#endif

View file

@ -50,7 +50,7 @@ typedef ssize_t creadfunc_t __P((int, char *));
The differences are
(1) using file descriptor instead of FILE *,
(2) the order of arguments; the file descriptor comes the first, and
(3) the addtion of thired argument, UNBUFFERED_READ; this argument
(3) the addition of third argument, UNBUFFERED_READ; this argument
controls whether get_line uses buffering or not to get a byte data
from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and
uses zread if UNBUFFERED_READ is non-zero.

View file

@ -66,11 +66,10 @@ zmapfd (fd, ostr, fn)
}
else if (nr < 0)
{
rval = -1;
free (result);
if (ostr)
*ostr = (char *)NULL;
break;
return -1;
}
RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, 128);

View file

@ -26,6 +26,7 @@
# include <unistd.h>
#endif
#include <signal.h>
#include <errno.h>
#if !defined (errno)
@ -36,6 +37,9 @@ extern int errno;
# define SEEK_CUR 1
#endif
extern void check_signals_and_traps (void);
extern int signal_is_trapped (int);
/* Read LEN bytes from FD into BUF. Retry the read on EINTR. Any other
error causes the loop to break. */
ssize_t
@ -46,8 +50,22 @@ zread (fd, buf, len)
{
ssize_t r;
#if 0
#if defined (HAVE_SIGINTERRUPT)
if (signal_is_trapped (SIGCHLD))
siginterrupt (SIGCHLD, 1);
#endif
#endif
while ((r = read (fd, buf, len)) < 0 && errno == EINTR)
;
check_signals_and_traps (); /* XXX - should it be check_signals()? */
#if 0
#if defined (HAVE_SIGINTERRUPT)
siginterrupt (SIGCHLD, 0);
#endif
#endif
return r;
}
@ -148,6 +166,34 @@ zreadcintr (fd, cp)
return 1;
}
/* Like zreadc, but read a specified number of characters at a time. Used
for `read -N'. */
ssize_t
zreadn (fd, cp, len)
int fd;
char *cp;
size_t len;
{
ssize_t nr;
if (lind == lused || lused == 0)
{
if (len > sizeof (lbuf))
len = sizeof (lbuf);
nr = zread (fd, lbuf, len);
lind = 0;
if (nr <= 0)
{
lused = 0;
return nr;
}
lused = nr;
}
if (cp)
*cp = lbuf[lind++];
return 1;
}
void
zreset ()
{