~nabijaczleweli/voreutils

fdd72eea19e5bb85844e8ea95316d0d91a897803 — наб 6 days ago 8252842
Add uname (and arch). Centralise spaced print
M .builds/sid.yml => .builds/sid.yml +1 -0
@@ 7,6 7,7 @@ packages:
  - llvm-dev
  - mandoc
  - curl
  - bc
tasks:
  - build-gcc: |
      cd voreutils

M README.md => README.md +2 -2
@@ 30,10 30,10 @@ GNU coreutils provide the following 105 binaries, according to `dpkg -L coreutil
  [x] /bin/sync
  [ ] /bin/touch
  [x] /bin/true
  [ ] /bin/uname
  [x] /bin/uname
  [ ] /bin/vdir
  [ ] /usr/bin/[
  [ ] /usr/bin/arch
  [x] /usr/bin/arch
  [ ] /usr/bin/b2sum
  [ ] /usr/bin/base32
  [ ] /usr/bin/base64

M cmd/aliases => cmd/aliases +3 -1
@@ 1,1 1,3 @@
true  false
true   false

uname  arch

M cmd/echo.cpp => cmd/echo.cpp +3 -18
@@ 6,12 6,13 @@
#include <errno.h>
#include <string_view>
#include <vore-optarg>
#include <vore-print>

using namespace std::literals;


int main(int, const char * const * argv) {
	const char * argv0 = argv[0];
	const char * self = argv[0];
	if(*argv)
		++argv;



@@ 21,21 22,5 @@ int main(int, const char * const * argv) {
		newline = false;
	}

	bool first = true;
	for(const char * arg : vore::opt::args{argv}) {
		if(first)
			first = false;
		else
			std::fputc(' ', stdout);

		std::fputs(arg, stdout);
	}

	if(newline)
		std::fputc('\n', stdout);

	if(std::fflush(stdout)) {
		std::fprintf(stderr, "%s: %s\n", argv0, std::strerror(errno));
		return 1;
	}
	return vore::print_spaced(self, vore::opt::args{argv}, newline);
}

M cmd/sleep.cpp => cmd/sleep.cpp +4 -0
@@ 25,12 25,16 @@ int main(int, char * const * argv) {
					mult *= 365.25 / 7.;
				case 'w':
					mult *= 7;
					[[fallthrough]];
				case 'd':
					mult *= 24;
					[[fallthrough]];
				case 'h':
					mult *= 60;
					[[fallthrough]];
				case 'm':
					mult *= 60;
					[[fallthrough]];
				case 's':
					break;
				default:

M cmd/sync.cpp => cmd/sync.cpp +2 -2
@@ 8,8 8,8 @@
#include <vore-optarg>


static int usage(const char * argv0) {
	std::fprintf(stderr, "usage: %s [-d|-f] [file]...\n", argv0);
static int usage(const char * self) {
	std::fprintf(stderr, "usage: %s [-d|-f] [file]...\n", self);
	return 1;
}


A cmd/uname.cpp => cmd/uname.cpp +146 -0
@@ 0,0 1,146 @@
// SPDX-License-Identifier: 0BSD


#include <climits>
#include <cstdio>
#include <string_view>
#include <sys/utsname.h>
#include <unistd.h>
#include <vore-getopt>
#include <vore-path>
#include <vore-print>
#if __OpenBSD__
#include <sys/param.h>
#elif __NetBSD__ || __FreeBSD__ || __DragonFly__
#include <sys/param.h>
#include <sys/sysctl.h>
#endif

using namespace std::literals;


#define UNAME_USAGE "usage: %s [-asnrvmpio]\n"
#define ARCH_USAGE "usage: %s\n"

#define SETFLAG(whichc, which, where)                       \
	case whichc:                                              \
		where.which = static_cast<decltype(where.which)>(true); \
		break;


enum class defaultable : std::uint8_t { no, yes, ifknown };

struct fields {
	bool s;
	bool n;
	bool r;
	bool v;
	bool m;
	defaultable p;
	defaultable i;
	bool o;

	constexpr bool operator==(const fields & rhs) const noexcept {
		return this->s == rhs.s && this->n == rhs.n && this->r == rhs.r && this->v == rhs.v && this->m == rhs.m && this->p == rhs.p && this->i == rhs.i &&
		       this->o == rhs.o;
	}
};


int main(int argc, char * const * argv) {
	fields def{}, sel{};

	auto self = vore::basename(argv[0] ?: "(?)");
	if(self == "arch") {  // 4.3BSD-Reno calls this "machine"
		if(argv[1]) {
			std::fprintf(stderr, ARCH_USAGE, argv[0]);
			return 1;
		}

		def.m = true;
	} else if(self == "uname") {
		def.s = true;

		for(auto && [arg, _] : vore::opt::get{argc,
		                                      argv,
		                                      "asnrvmpio",
		                                      {{"all", no_argument, nullptr, 'a'},
		                                       {"kernel-name", no_argument, nullptr, 's'},
		                                       {"nodename", no_argument, nullptr, 'n'},
		                                       {"kernel-release", no_argument, nullptr, 'r'},
		                                       {"kernel-version", no_argument, nullptr, 'v'},
		                                       {"machine", no_argument, nullptr, 'm'},
		                                       {"processor", no_argument, nullptr, 'p'},
		                                       {"hardware-platform", no_argument, nullptr, 'i'},
		                                       {"operating-system", no_argument, nullptr, 'o'}}})
			switch(arg) {
				SETFLAG('s', s, sel);
				SETFLAG('n', n, sel);
				SETFLAG('r', r, sel);
				SETFLAG('v', v, sel);
				SETFLAG('m', m, sel);
				SETFLAG('p', p, sel);
				SETFLAG('i', i, sel);
				SETFLAG('o', o, sel);
				case 'a':
					// sel = {true, true, true, true, true, defaultable::no, defaultable::no, false};
					sel = {true, true, true, true, true, defaultable::ifknown, defaultable::ifknown, true};
					break;
				default:
					std::fprintf(stderr, UNAME_USAGE, argv[0]);
					return 1;
			}

		if(argv[optind]) {
			std::fprintf(stderr, UNAME_USAGE, argv[0]);
			return 1;
		}
	} else {
		std::fprintf(stderr, UNAME_USAGE, "uname");
		std::fprintf(stderr, ARCH_USAGE, "arch");
		return 2;
	}

	fields flds = (sel == fields{}) ? def : sel;


	struct utsname ut {};
	if(flds.s || flds.n || flds.r || flds.v || flds.m || flds.o)
		(void)uname(&ut);

	const char * processor{};
	char proc[SYS_NMLN] __attribute__((unused));
	if(flds.p != defaultable::no) {
#if __OpenBSD__
		processor = MACHINE_ARCH;
#elif __NetBSD__ || __FreeBSD__ || __DragonFly__
		int mib[]    = {CTL_HW, HW_MACHINE_ARCH};
		size_t procl = sizeof(proc);
		if(sysctl(mib, sizeof(mib) / sizeof(*mib), proc, &procl, nullptr, 0) == -1)
			std::fprintf(stderr, "%s: sysctl(hw.machine_arch): %s", argv[0], std::strerror(errno));
		processor = proc;
#else
		processor = "unknown";
#endif
	}

	const char * platform{};
	if(flds.i != defaultable::no)
		platform = "unknown";

	if(flds.p == defaultable::ifknown && processor == "unknown"sv)
		processor = nullptr;
	if(flds.i == defaultable::ifknown && platform == "unknown"sv)
		platform = nullptr;

	return vore::print_spaced(argv[0], std::initializer_list<const char *>{
	                                       flds.s ? ut.sysname : nullptr,
	                                       flds.n ? ut.nodename : nullptr,
	                                       flds.r ? ut.release : nullptr,
	                                       flds.v ? ut.version : nullptr,
	                                       flds.m ? ut.machine : nullptr,
	                                       processor,
	                                       platform,
	                                       flds.o ? ut.sysname : nullptr,
	                                   });
}

A include/vore-print => include/vore-print +43 -0
@@ 0,0 1,43 @@
// SPDX-License-Identifier: 0BSD


#pragma once

#include <cstdio>
#include <cstring>
#include <errno.h>


namespace vore {
	template <class I>
	int print_spaced(const char * self, I begin, I end, bool newline = true) {
		bool first = true;
		for(; begin != end; ++begin) {
			const char * str = *begin;

			if(!str)
				continue;

			if(first)
				first = false;
			else
				std::fputc(' ', stdout);

			std::fputs(str, stdout);
		}

		if(newline)
			std::fputc('\n', stdout);

		if(std::fflush(stdout)) {
			std::fprintf(stderr, "%s: %s\n", self, std::strerror(errno));
			return 1;
		} else
			return 0;
	}

	template <class C>
	int print_spaced(const char * self, const C & cont, bool newline = true) {
		return print_spaced(self, std::begin(cont), std::end(cont), newline);
	}
}

A man/uname.1 => man/uname.1 +82 -0
@@ 0,0 1,82 @@
.\" SPDX-License-Identifier: 0BSD
.\"
.Dd
.Dt UNAME 1
.Os
.
.Sh NAME
.Nm uname
.Nd print system information
.Sh SYNOPSIS
.Nm uname
.Op Fl asnrvmpio
.Nm arch
.
.Sh DESCRIPTION
Writes some system information to the standard output stream in the order listed below, separated by spaces.
Except where otherwise specified, information is obtained using
.Xr uname 3 ,
and is beholden to drawbacks thereof.
.Pp
.No If called as Nm uname , No the default is Fl s .
.No If called as Nm arch , No behaves like Nm uname Fl m .
.
.Sh OPTIONS
.Bl -tag -compact -width "-i, --hardware-platform"
.It Fl a , -all
.No Print all fields , Em but No only print Fl pi No if not Qq unknown .
.
.It Fl s , -kernel-name
Name of the kernel
.Pq Fa sysname .
.
.It Fl n , -nodename
Name of system on some communcation network, which usually means the configured hostname
.Pq Fa nodename .
.
.It Fl r , -kernel-release
Version number of the kernel
.Pq Fa release .
.
.It Fl v , -kernel-version
Human-readable version of the kernel
.Pq Fa version .
.
.It Fl m , -machine
Machine class the kernel is built for
.Pq Fa machine .
.
.It Fl p , -processor
Machine class the kernel is running on
.Po
this is non-portable: it corresponds to the
.Va hw.machine_arch No sysctl on Nx , Fx , and Dx , the
.Dv MACHINE_ARCH No macro on Ox , and
.Qq unknown
elsewhere
.Pc .
.
.It Fl i , -hardware-platform
.Qq unknown
.
.It Fl o , -operating-system
.No Same as Fl s .
.El
.
.Sh SEE ALSO
.Xr uname 3 ,
.Xr sysctl 7
.
.Sh STANDARDS
Conforms to
.St -p1003.2-92 .
.Pp
.No The Bx No calls Nm arch Nm machine .
.Nm arch No is also available on Solaris, but is deprecated and does something different .
.Pp
.Fl pio No are extensions :
.Fl p No is available on the Bx ,
.Fl io No are only available on the GNU system .
.No On the Bx , Fl a No is strictly equivalent to Fl snrvm .
.No Under Linux, on the GNU system , Fl o No is Qq GNU/Linux .
.Nm No from the GNU system handles Fl a No together with Fl io No differently .

M tests/tac/test => tests/tac/test +45 -40
@@ 25,87 25,92 @@ cp -r "${tmpdir}singlef/" "${tmpdir}nothing/"

cd "${tmpdir}singlef/" && for f in $files; do
  mkdir "$f.d"
  "$tac"     "$f" > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
  "$tac" -b  "$f" > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
  "$tac" -r  "$f" > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
  "$tac" -br "$f" > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
  "$tac"     "$f" > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
  "$tac" -b  "$f" > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
  "$tac" -r  "$f" > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
  "$tac" -br "$f" > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  for s in '' ' ' '  ' 'a ' ' ' '\s' '.' '..' 'a $'; do
    pat="$s"
    [ "$pat" = '\s' ] && pat='[[:space:]]'
    "$tac" -s   "$pat" "$f" > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
    "$tac" -bs  "$pat" "$f" > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
    "$tac" -rs  "$pat" "$f" > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
    "$tac" -brs "$pat" "$f" > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
    "$tac" -s   "$pat" "$f" > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
    "$tac" -bs  "$pat" "$f" > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
    "$tac" -rs  "$pat" "$f" > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
    "$tac" -brs "$pat" "$f" > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  done
done
wait
diff -r -u "$data" "${tmpdir}singlef/" >&3 2>&1 && echo "Single-file ok"

cd "${tmpdir}withnull/" && for f in $files; do
  mkdir "$f.d"
  "$tac"     /dev/null "$f" /dev/null > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
  "$tac" -b  /dev/null "$f" /dev/null > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
  "$tac" -r  /dev/null "$f" /dev/null > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
  "$tac" -br /dev/null "$f" /dev/null > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
  "$tac"     /dev/null "$f" /dev/null > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
  "$tac" -b  /dev/null "$f" /dev/null > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
  "$tac" -r  /dev/null "$f" /dev/null > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
  "$tac" -br /dev/null "$f" /dev/null > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  for s in '' ' ' '  ' 'a ' ' ' '\s' '.' '..' 'a $'; do
    pat="$s"
    [ "$pat" = '\s' ] && pat='[[:space:]]'
    "$tac" -s   "$pat" /dev/null "$f" /dev/null > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
    "$tac" -bs  "$pat" /dev/null "$f" /dev/null > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
    "$tac" -rs  "$pat" /dev/null "$f" /dev/null > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
    "$tac" -brs "$pat" /dev/null "$f" /dev/null > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
    "$tac" -s   "$pat" /dev/null "$f" /dev/null > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
    "$tac" -bs  "$pat" /dev/null "$f" /dev/null > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
    "$tac" -rs  "$pat" /dev/null "$f" /dev/null > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
    "$tac" -brs "$pat" /dev/null "$f" /dev/null > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  done
done
wait
diff -r -u "$data" "${tmpdir}withnull/" >&3 2>&1 && echo "Interposed null ok"

cd "${tmpdir}with-/" && for f in $files; do
  mkdir "$f.d"
  printf "" | "$tac"     - "$f" - > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
  printf "" | "$tac" -b  - "$f" - > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
  printf "" | "$tac" -r  - "$f" - > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
  printf "" | "$tac" -br - "$f" - > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
  printf "" | "$tac"     - "$f" - > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
  printf "" | "$tac" -b  - "$f" - > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
  printf "" | "$tac" -r  - "$f" - > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
  printf "" | "$tac" -br - "$f" - > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  for s in '' ' ' '  ' 'a ' ' ' '\s' '.' '..' 'a $'; do
    pat="$s"
    [ "$pat" = '\s' ] && pat='[[:space:]]'
    printf "" | "$tac" -s   "$pat" - "$f" - > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
    printf "" | "$tac" -bs  "$pat" - "$f" - > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
    printf "" | "$tac" -rs  "$pat" - "$f" - > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
    printf "" | "$tac" -brs "$pat" - "$f" - > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
    printf "" | "$tac" -s   "$pat" - "$f" - > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
    printf "" | "$tac" -bs  "$pat" - "$f" - > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
    printf "" | "$tac" -rs  "$pat" - "$f" - > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
    printf "" | "$tac" -brs "$pat" - "$f" - > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  done
done
wait
diff -r -u "$data" "${tmpdir}with-/" >&3 2>&1 && echo "Interposed - ok"

cd "${tmpdir}just-/" && for f in $files; do
  mkdir "$f.d"
  "$tac"     - < "$f" > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
  "$tac" -b  - < "$f" > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
  "$tac" -r  - < "$f" > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
  "$tac" -br - < "$f" > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
  "$tac"     - < "$f" > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
  "$tac" -b  - < "$f" > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
  "$tac" -r  - < "$f" > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
  "$tac" -br - < "$f" > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  for s in '' ' ' '  ' 'a ' ' ' '\s' '.' '..' 'a $'; do
    pat="$s"
    [ "$pat" = '\s' ] && pat='[[:space:]]'
    "$tac" -s   "$pat" - < "$f" > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
    "$tac" -bs  "$pat" - < "$f" > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
    "$tac" -rs  "$pat" - < "$f" > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
    "$tac" -brs "$pat" - < "$f" > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
    "$tac" -s   "$pat" - < "$f" > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
    "$tac" -bs  "$pat" - < "$f" > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
    "$tac" -rs  "$pat" - < "$f" > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
    "$tac" -brs "$pat" - < "$f" > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  done
done
wait
diff -r -u "$data" "${tmpdir}just-/" >&3 2>&1 && echo "stdin ok"

cd "${tmpdir}nothing/" && for f in $files; do
  mkdir "$f.d"
  "$tac"     < "$f" > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
  "$tac" -b  < "$f" > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
  "$tac" -r  < "$f" > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
  "$tac" -br < "$f" > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
  "$tac"     < "$f" > "$f.d/$f"    2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
  "$tac" -b  < "$f" > "$f.d/$f-b"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
  "$tac" -r  < "$f" > "$f.d/$f-r"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
  "$tac" -br < "$f" > "$f.d/$f-br" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  for s in '' ' ' '  ' 'a ' ' ' '\s' '.' '..' 'a $'; do
    pat="$s"
    [ "$pat" = '\s' ] && pat='[[:space:]]'
    "$tac" -s   "$pat" < "$f" > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error"
    "$tac" -bs  "$pat" < "$f" > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error"
    "$tac" -rs  "$pat" < "$f" > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error"
    "$tac" -brs "$pat" < "$f" > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error"
    "$tac" -s   "$pat" < "$f" > "$f.d/$f-s'$s'"   2>/dev/null || echo yes > "$f.d/$f-s'$s'.error" &
    "$tac" -bs  "$pat" < "$f" > "$f.d/$f-bs'$s'"  2>/dev/null || echo yes > "$f.d/$f-bs'$s'.error" &
    "$tac" -rs  "$pat" < "$f" > "$f.d/$f-rs'$s'"  2>/dev/null || echo yes > "$f.d/$f-rs'$s'.error" &
    "$tac" -brs "$pat" < "$f" > "$f.d/$f-brs'$s'" 2>/dev/null || echo yes > "$f.d/$f-brs'$s'.error" &
  done
done
wait
diff -r -u "$data" "${tmpdir}nothing/" >&3 2>&1 && echo "Default ok"

rm -rf "$tmpdir" >&3

A tests/uname => tests/uname +46 -0
@@ 0,0 1,46 @@
#!/bin/sh
# SPDX-License-Identifier: 0BSD

tmpdir="$(mktemp -dt "uname.XXXXXXXXXX")/"
uname="${CMDDIR}uname"

altname="${tmpdir%/}"
altname="${altname##*/}"

ln -fs "$uname" "${tmpdir}uname"
ln -fs "$uname" "${tmpdir}arch"
ln -fs "$uname" "${tmpdir}something-else"
ln -fs "$uname" "${tmpdir}$altname"

"${tmpdir}uname" > /dev/null; err=$?
[ $err -eq 0 ] || echo "uname: got $err instead of 0 for uname" >&3
"${tmpdir}arch" > /dev/null; err=$?
[ $err -eq 0 ] || echo "uname: got $err instead of 1 for arch" >&3
errstr="$("${tmpdir}something-else" 2>&1 > /dev/null)"; err=$?
[ $err -eq 2 ]   || echo "uname: got $err instead of 2 for something-else" >&3
[ -n "$errstr" ] || echo "uname: stderr empty for something-else" >&3
errstr="$("${tmpdir}$altname" 2>&1 > /dev/null)"; err=$?
[ $err -eq 2 ]   || echo "uname: got $err instead of 2 for $altname" >&3
[ -n "$errstr" ] || echo "uname: stderr empty for $altname" >&3

"${tmpdir}uname" -m > "${tmpdir}uname--m"
"${tmpdir}arch" | cmp "${tmpdir}uname--m" || echo "uname: arch doesn't match uname -m" >&3

"${tmpdir}uname" > "${tmpdir}uname-"
"${tmpdir}uname" -s | cmp "${tmpdir}uname-" || echo "uname: default doesn't match -s" >&3

"${tmpdir}uname" -s > "${tmpdir}uname--s"
"${tmpdir}uname" -o | cmp "${tmpdir}uname--s" || echo "uname: -o doesn't match -s" >&3

for s in '' '-s'; do for n in '' '-n'; do for r in '' '-r'; do for v in '' '-v'; do for m in '' '-m'; do for p in '' '-p'; do
	uname $s $n $r $v $m $p > "${tmpdir}uname $s $n $r $v $m $p"
	"${tmpdir}uname" $s $n $r $v $m $p | cmp "${tmpdir}uname $s $n $r $v $m $p" || echo "uname: $s $n $r $v $m $p doesn't match system" >&3
done; done; done; done; done; done

if uname -i > "${tmpdir}uname -i" 2>/dev/null; then
	"${tmpdir}uname" -i | cmp "${tmpdir}uname -i" || echo "uname: -s doesn't match system" >&3
else
	echo "uname: skipping -i, no system support" >&2
fi

rm -rf "$tmpdir" >&3