diff options
author | Andy Fiddaman <omnios@citrus-it.co.uk> | 2021-03-10 15:37:50 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2021-03-16 19:20:39 +0000 |
commit | d6f391ef39bc41c64e16ac5d7b10c1c8d5b1761e (patch) | |
tree | 03ba0359a58496a978969da5a16c31afa70e550c | |
parent | aa15372140b6b509a26742fd85fe78dd77d9a642 (diff) | |
download | illumos-joyent-d6f391ef39bc41c64e16ac5d7b10c1c8d5b1761e.tar.gz |
4149 ksh head builtin does not like newlines
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/cmd/ast/libshell/Makefile.demo | 1 | ||||
-rw-r--r-- | usr/src/cmd/ast/libshell/common/tests/illumos_4149_builtin_head.sh | 125 | ||||
-rw-r--r-- | usr/src/contrib/ast/src/lib/libast/sfio/sfmove.c | 14 | ||||
-rw-r--r-- | usr/src/contrib/ast/src/lib/libcmd/head.c | 20 | ||||
-rw-r--r-- | usr/src/contrib/ast/src/lib/libcmd/tail.c | 34 | ||||
-rw-r--r-- | usr/src/pkg/manifests/source-demo-system.mf | 1 |
6 files changed, 175 insertions, 20 deletions
diff --git a/usr/src/cmd/ast/libshell/Makefile.demo b/usr/src/cmd/ast/libshell/Makefile.demo index e1a81f07c2..ebddf0e6cc 100644 --- a/usr/src/cmd/ast/libshell/Makefile.demo +++ b/usr/src/cmd/ast/libshell/Makefile.demo @@ -116,6 +116,7 @@ DF_TESTS= \ DF_XTESTS= \ tests/README.tests \ + tests/illumos_4149_builtin_head.sh \ tests/illumos_13434_chunked_heredoc.sh \ tests/sun_solaris_array_default_datatype.sh \ tests/sun_solaris_builtin_poll.sh \ diff --git a/usr/src/cmd/ast/libshell/common/tests/illumos_4149_builtin_head.sh b/usr/src/cmd/ast/libshell/common/tests/illumos_4149_builtin_head.sh new file mode 100644 index 0000000000..a146d3fb2e --- /dev/null +++ b/usr/src/cmd/ast/libshell/common/tests/illumos_4149_builtin_head.sh @@ -0,0 +1,125 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2021 OmniOS Community Edition (OmniOSce) Association. +# + +# +# Test whether the builtin head command properly handles files which do +# not have a trailing newline. +# + +# test setup +function err_exit +{ + print -u2 -n "\t" + print -u2 -r ${Command}[$1]: "${@:2}" + (( Errors++ )) +} +alias err_exit='err_exit $LINENO' + +set -o nounset +Command=${0##*/} +integer Errors=0 + +builtin head tail + +t1=`mktemp` +t2=`mktemp` +t3=`mktemp` +if [[ ! -f "$t1" || ! -f "$t2" || ! -f "$t3" ]]; then + # Don't use the global err _ exit function as the test harness uses + # calls to that to compute the number of tests present in this file. + echo "Could not create temporary files" + rm -f "$t1" "$t2" "$t3" + exit 1 +fi + +for f in test{0..4%02d}; do + echo $f +done | tee $t1 > $t2 +printf "nonewline" >> $t2 +printf "nonewline" >> $t3 + +# Standard file, five lines, with trailing newline + +[[ $(head -1 $t1) == 'test00' ]] || \ + err_exit "Shell head -1 standard file" + +[[ $(head -2 $t1) == $'test00\ntest01' ]] || \ + err_exit "Shell head -2 standard file" + +[[ $(head -s 2 -n2 $t1) == $'test02\ntest03' ]] || \ + err_exit "Shell head -s 2 -n 2 standard file" + +[[ $(head -5 $t1) == $'test00\ntest01\ntest02\ntest03\ntest04' ]] || \ + err_exit "Shell head -5 standard file" + +[[ $(head -10 $t1) == $'test00\ntest01\ntest02\ntest03\ntest04' ]] || \ + err_exit "Shell head -10 standard file" + +[[ $(tail -1 $t1) == 'test04' ]] || \ + err_exit "Shell tail -1 standard file" + +[[ $(tail -2 $t1) == $'test03\ntest04' ]] || \ + err_exit "Shell tail -2 standard file" + +[[ $(tail -10 $t1) == $'test00\ntest01\ntest02\ntest03\ntest04' ]] || \ + err_exit "Shell tail -10 standard file" + +# File with a single line, no trailing newline + +[[ $(head -1 $t3) == 'nonewline' ]] || \ + err_exit "Shell head -1 one-line file" + +[[ $(head -2 $t3) == 'nonewline' ]] || \ + err_exit "Shell head -2 one-line file" + +[[ $(tail -1 $t3) == 'nonewline' ]] || \ + err_exit "Shell tail -1 one-line file" + +[[ $(tail -2 $t3) == 'nonewline' ]] || \ + err_exit "Shell tail -2 one-line file" + +# File with six lines, no trailing newline + +[[ $(head -1 $t2) == "test00" ]] || \ + err_exit "Shell head -1 six-line file" + +[[ $(head -2 $t2) == $'test00\ntest01' ]] || \ + err_exit "Shell head -2 six-line file" + +[[ $(head -s 2 -n2 $t2) == $'test02\ntest03' ]] || \ + err_exit "Shell head -s 2 -n 2 six-line file" + +[[ $(head -5 $t2) == $'test00\ntest01\ntest02\ntest03\ntest04' ]] || \ + err_exit "Shell head -5 six-line file" + +[[ $(head -6 $t2) == $'test00\ntest01\ntest02\ntest03\ntest04\nnonewline' ]] \ + || err_exit "Shell head -6 six-line file" + +[[ $(head -10 $t2) == $'test00\ntest01\ntest02\ntest03\ntest04\nnonewline' ]] \ + || err_exit "Shell head -10 six-line file" + +[[ $(tail -1 $t2) == 'nonewline' ]] || \ + err_exit "Shell tail -1 six-line file" + +[[ $(tail -2 $t2) == $'test04\nnonewline' ]] || \ + err_exit "Shell tail -2 six-line file" + +[[ $(tail -10 $t2) == $'test00\ntest01\ntest02\ntest03\ntest04\nnonewline' ]] \ + || err_exit "Shell tail -10 six-line file" + +rm -f "$t1" "$t2" "$t3" + +# tests done +exit $Errors diff --git a/usr/src/contrib/ast/src/lib/libast/sfio/sfmove.c b/usr/src/contrib/ast/src/lib/libast/sfio/sfmove.c index 9e3965750a..413a977c5c 100644 --- a/usr/src/contrib/ast/src/lib/libast/sfio/sfmove.c +++ b/usr/src/contrib/ast/src/lib/libast/sfio/sfmove.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2011 AT&T Intellectual Property * +* Copyright (c) 1985-2013 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler <gsf@research.att.com> * -* David Korn <dgk@research.att.com> * -* Phong Vo <kpv@research.att.com> * +* Glenn Fowler <glenn.s.fowler@gmail.com> * +* David Korn <dgkorn@gmail.com> * +* Phong Vo <phongvo@gmail.com> * * * ***********************************************************************/ #include "sfhdr.h" @@ -113,7 +113,11 @@ reg int rc; /* record separator */ /* try reading a block of data */ direct = 0; - if((r = fr->endb - (next = fr->next)) <= 0) + if(fr->rsrv && (r = -fr->rsrv->slen) > 0) + { fr->rsrv->slen = 0; + next = fr->rsrv->data; + } + else if((r = fr->endb - (next = fr->next)) <= 0) { /* amount of data remained to be read */ if((w = n > MAX_SSIZE ? MAX_SSIZE : (ssize_t)n) < 0) { if(fr->extent < 0) diff --git a/usr/src/contrib/ast/src/lib/libcmd/head.c b/usr/src/contrib/ast/src/lib/libcmd/head.c index 426e7db80f..7f39aef72b 100644 --- a/usr/src/contrib/ast/src/lib/libcmd/head.c +++ b/usr/src/contrib/ast/src/lib/libcmd/head.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1992-2012 AT&T Intellectual Property * +* Copyright (c) 1992-2013 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,8 +14,8 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler <gsf@research.att.com> * -* David Korn <dgk@research.att.com> * +* Glenn Fowler <glenn.s.fowler@gmail.com> * +* David Korn <dgkorn@gmail.com> * * * ***********************************************************************/ #pragma prototyped @@ -27,7 +27,7 @@ */ static const char usage[] = -"[-n?\n@(#)$Id: head (AT&T Research) 2012-05-31 $\n]" +"[-n?\n@(#)$Id: head (AT&T Research) 2013-09-19 $\n]" USAGE_LICENSE "[+NAME?head - output beginning portion of one or more files ]" "[+DESCRIPTION?\bhead\b copies one or more input files to standard " @@ -77,6 +77,7 @@ b_head(int argc, register char** argv, Shbltin_t* context) register off_t keep = 10; register off_t skip = 0; register int delim = '\n'; + off_t moved; int header = 1; char* format = (char*)header_fmt+1; @@ -138,9 +139,16 @@ b_head(int argc, register char** argv, Shbltin_t* context) sfprintf(sfstdout, format, cp); format = (char*)header_fmt; if (skip > 0) - sfmove(fp, NiL, skip, delim); - if (sfmove(fp, sfstdout, keep, delim) < 0 && !ERROR_PIPE(errno) && errno != EINTR) + { + if ((moved = sfmove(fp, NiL, skip, delim)) < 0 && !ERROR_PIPE(errno) && errno != EINTR) + error(ERROR_system(0), "%s: skip error", cp); + if (delim >= 0 && moved < skip) + goto next; + } + if ((moved = sfmove(fp, sfstdout, keep, delim)) < 0 && !ERROR_PIPE(errno) && errno != EINTR || + delim >= 0 && moved < keep && sfmove(fp, sfstdout, SF_UNBOUND, -1) < 0 && !ERROR_PIPE(errno) && errno != EINTR) error(ERROR_system(0), "%s: read error", cp); + next: if (fp != sfstdin) sfclose(fp); } while (cp = *argv++); diff --git a/usr/src/contrib/ast/src/lib/libcmd/tail.c b/usr/src/contrib/ast/src/lib/libcmd/tail.c index ce52f9f3d6..4f078a7709 100644 --- a/usr/src/contrib/ast/src/lib/libcmd/tail.c +++ b/usr/src/contrib/ast/src/lib/libcmd/tail.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1992-2012 AT&T Intellectual Property * +* Copyright (c) 1992-2013 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,8 +14,8 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler <gsf@research.att.com> * -* David Korn <dgk@research.att.com> * +* Glenn Fowler <glenn.s.fowler@gmail.com> * +* David Korn <dgkorn@gmail.com> * * * ***********************************************************************/ #pragma prototyped @@ -28,7 +28,7 @@ */ static const char usage[] = -"+[-?\n@(#)$Id: tail (AT&T Research) 2012-06-19 $\n]" +"+[-?\n@(#)$Id: tail (AT&T Research) 2013-09-19 $\n]" USAGE_LICENSE "[+NAME?tail - output trailing portion of one or more files ]" "[+DESCRIPTION?\btail\b copies one or more input files to standard output " @@ -159,8 +159,10 @@ tailpos(register Sfio_t* fp, register Sfoff_t number, int delim) register Sfoff_t last; register char* s; register char* t; + int incomplete; struct stat st; + error(-1, "AHA#%d tail number=%I*d", __LINE__, sizeof(number), number); last = sfsize(fp); if ((first = sfseek(fp, (Sfoff_t)0, SEEK_CUR)) < 0) return last || fstat(sffileno(fp), &st) || st.st_size || FIFO(st.st_mode) ? -1 : 0; @@ -170,6 +172,7 @@ tailpos(register Sfio_t* fp, register Sfoff_t number, int delim) return first; return offset; } + incomplete = 1; for (;;) { if ((offset = last - SF_BUFSIZE) < first) @@ -179,6 +182,15 @@ tailpos(register Sfio_t* fp, register Sfoff_t number, int delim) if (!(s = sfreserve(fp, n, SF_LOCKR))) return -1; t = s + n; + if (incomplete) + { + if (t > s && *(t - 1) != delim && number-- <= 0) + { + sfread(fp, s, 0); + return offset + (t - s); + } + incomplete = 0; + } while (t > s) if (*--t == delim && number-- <= 0) { @@ -280,6 +292,7 @@ init(Tail_t* tp, Sfoff_t number, int delim, int flags, const char** format) return -1; } sfset(tp->sp, SF_SHARE, 0); + error(-1, "AHA#%d offset=%I*d number=%I*d", __LINE__, sizeof(offset), offset, sizeof(number), number); if (offset) { if (number < 0 || !number && (flags & POSITIVE)) @@ -410,6 +423,7 @@ b_tail(int argc, char** argv, Shbltin_t* context) char* t; char* r; char* file; + Sfoff_t moved; Sfoff_t offset; Sfoff_t number = DEFAULT; unsigned long timeout = 0; @@ -424,7 +438,7 @@ b_tail(int argc, char** argv, Shbltin_t* context) Tail_t* files; Tv_t tv; - cmdinit(argc, argv, context, ERROR_CATALOG, 0); + cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY); for (;;) { switch (n = optget(argv, usage)) @@ -639,7 +653,7 @@ b_tail(int argc, char** argv, Shbltin_t* context) { if (n) n = 0; - else if (sh_checksig(context) || tvsleep(&tv, NiL)) + else if (sh_checksig(context) || tvsleep(&tv, NiL) && sh_checksig(context)) { error_info.errors++; break; @@ -686,11 +700,13 @@ b_tail(int argc, char** argv, Shbltin_t* context) { i = 3; while (--i && stat(fp->name, &st)) - if (sh_checksig(context) || tvsleep(&tv, NiL)) + if (sh_checksig(context)) { error_info.errors++; goto done; } + else + tvsleep(&tv, NiL); if (i && (fp->dev != st.st_dev || fp->ino != st.st_ino) && !init(fp, 0, 0, flags, &format)) { if (!(flags & SILENT)) @@ -746,8 +762,8 @@ b_tail(int argc, char** argv, Shbltin_t* context) if (number < 0 || !number && (flags & POSITIVE)) { sfset(ip, SF_SHARE, 1); - if (number < -1) - sfmove(ip, NiL, -number - 1, delim); + if (number < -1 && (moved = sfmove(ip, NiL, -(number + 1), delim)) >= 0 && delim >= 0 && moved < -(number + 1)) + (void)sfgetr(ip, delim, SF_LASTR); if (flags & REVERSE) rev_line(ip, sfstdout, sfseek(ip, (Sfoff_t)0, SEEK_CUR)); else diff --git a/usr/src/pkg/manifests/source-demo-system.mf b/usr/src/pkg/manifests/source-demo-system.mf index b2aaf94cbf..e3415901dc 100644 --- a/usr/src/pkg/manifests/source-demo-system.mf +++ b/usr/src/pkg/manifests/source-demo-system.mf @@ -130,6 +130,7 @@ file path=usr/demo/ksh/tests/glob.sh file path=usr/demo/ksh/tests/grep.sh file path=usr/demo/ksh/tests/heredoc.sh file path=usr/demo/ksh/tests/illumos_13434_chunked_heredoc.sh +file path=usr/demo/ksh/tests/illumos_4149_builtin_head.sh file path=usr/demo/ksh/tests/io.sh file path=usr/demo/ksh/tests/leaks.sh file path=usr/demo/ksh/tests/locale.sh |