summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2021-03-10 15:37:50 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2021-03-16 19:20:39 +0000
commitd6f391ef39bc41c64e16ac5d7b10c1c8d5b1761e (patch)
tree03ba0359a58496a978969da5a16c31afa70e550c
parentaa15372140b6b509a26742fd85fe78dd77d9a642 (diff)
downloadillumos-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.demo1
-rw-r--r--usr/src/cmd/ast/libshell/common/tests/illumos_4149_builtin_head.sh125
-rw-r--r--usr/src/contrib/ast/src/lib/libast/sfio/sfmove.c14
-rw-r--r--usr/src/contrib/ast/src/lib/libcmd/head.c20
-rw-r--r--usr/src/contrib/ast/src/lib/libcmd/tail.c34
-rw-r--r--usr/src/pkg/manifests/source-demo-system.mf1
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