37 Commits

Author SHA1 Message Date
f0eac562b3 tests: bonsai/npc.mk: fixed copyright header 2025-02-24 23:08:28 -07:00
008c0624f6 tests: bonsai/npc.mk: removed test that is broken with GNU and BusyBox 2025-02-24 22:57:42 -07:00
07a2f1efc2 Merge branch 'man-fixes' 2024-09-11 15:42:58 -06:00
accec33301 Makefile: fixes abuse of relative paths 2024-09-05 17:12:39 -06:00
444e682f02 Merge branch 'rdme' 2024-09-05 17:02:31 -06:00
fde682a10e Makefile: fixes manpage installation location 2024-09-05 12:57:55 -06:00
DTB
87c9e29932 tests: bonsai/peek.mk 2024-09-01 08:51:33 -06:00
DTB
1037e32e6e peek(1): fix erroring on stdin/stdout redirection 2024-09-01 08:50:13 -06:00
DTB
5c70852890 peek.1: replace parens with square brackets 2024-09-01 08:50:12 -06:00
DTB
8ec18ccf75 peek(1): use stdbool.h 2024-09-01 08:50:12 -06:00
DTB
3bfdc62035 peek(1): better error on piping 2024-09-01 08:50:12 -06:00
DTB
7d174c1f7c peek(1): warn on pledge(2) or unveil(2) errors 2024-09-01 08:50:12 -06:00
DTB
3f41110617 peek(1): pledge(2) and unveil(2) on OpenBSD 2024-09-01 08:50:11 -06:00
DTB
7a69e1d516 peek.1: correct references to use the 1p section, add reference to stty(1p) 2024-09-01 08:50:11 -06:00
DTB
64e943f64a peek(1): fix ioerr typos 2024-09-01 08:50:11 -06:00
DTB
16dcd4da37 peek(1): more style fixes 2024-09-01 08:50:11 -06:00
DTB
d892fa1cac peek(1): update style 2024-09-01 08:50:11 -06:00
DTB
3862a95151 peek.1: s/inputted/input/ 2024-09-01 08:48:26 -06:00
DTB
264ae2e82c peek.1: fix version string 2024-09-01 08:48:26 -06:00
DTB
1634761593 peek.1: fix wording on -i 2024-09-01 08:48:26 -06:00
DTB
0b40360e7e Makefile: all: add peek 2024-09-01 08:48:26 -06:00
590d98d7f7 peek.1: updates to be more consistent with current documentation 2024-09-01 08:48:26 -06:00
DTB
07aa9a9abc peek(1): remove unused variables, clean up some typos 2024-09-01 08:48:25 -06:00
DTB
fce49bed85 peek(1): correct grammar 2024-09-01 08:46:56 -06:00
DTB
62b38a6765 peek(1): strip down to bare essentials, rewrite man page to match 2024-09-01 08:46:56 -06:00
DTB
23521bade5 peek(1): remove -p 2024-09-01 08:46:56 -06:00
DTB
3b774cab27 Import peek(1) from trinity/src 2024-09-01 08:46:52 -06:00
e889159619 CONTRIBUTING: made better 2024-08-30 21:22:53 -06:00
fbacfecce8 Merge branch 'linux-fix' (closes #158) 2024-08-21 22:43:29 -06:00
DTB
579ff65b67 tests: bonsai/npc.mk: drop redundant tab removal 2024-08-21 21:59:22 -06:00
DTB
334433536b tests: bonsai/npc.mk: fix harrowing ordeal of a Linux error 2024-08-21 21:57:10 -06:00
e9058803d3 mm(1): fixes to pledge(2) now; tests: bonsai/mm.mk: adds test for regression 2024-08-17 14:58:56 -06:00
71d4d6ba05 tests: bonsai/dj.mk, bonsai/rpn.mk: fixes testing on linux 2024-08-17 01:57:16 -06:00
821f5d09e9 fop(1), hru(1), intcmp(1), mm(1), rpn(1), swab(1): fixes conditional compilation 2024-08-17 01:51:25 -06:00
a4a556a5b6 mm(1): fixes extra file arguments not being unveil(2)ed 2024-08-16 18:43:51 -06:00
d2f8fb8106 README: improvements, community links 2024-08-12 17:53:43 -06:00
DTB
cd875df547 README: attempt to clarify intent 2024-07-18 09:32:58 -06:00
16 changed files with 429 additions and 72 deletions

View File

@@ -1,26 +1,29 @@
Make sure to read our code of conduct in the CONDUCT file.
When contributing a pull request to the main branch, please sign your commits
with a PGP key and add your name and the year to the bottom of the list of
copyright holders for the file. For example, an existing copyright header might
read:
Copyright Information
=====================
When editing a file, create a copyright statement correlated to your
identity so that it is easier to keep track of who has touched what file.
Pseudonymous contributions are welcome (and encouraged). Place new copyright
information below existing copyright information. If there is an existing
copyright statement:
* Copyright (c) 20222023 Emma Tebibyte <emma@tebibyte.media>
You would add your name below it like this:
you would add your name below it like this:
* Copyright (c) 20222023 Emma Tebibyte <emma@tebibyte.media>
* Copyright (c) 20XX Your Name <your e-mail address or website>
We accept contributions from people using aliases.
Only list years in which you modified the source file. For example:
* Copyright (c) 20202021, 2023 Your Name <your-address@example.com>
This header shows that “Your Name” worked on this source file in 2020, 2021, and
2023. Please use the en dash (“–”) to separate the years in the copyright
notice.
2023. Please use the en dash (“–”, U+2013) to separate consecutive years in the
copyright notice.
If you are contributing a new file, please prepend the following license header
text to it, replacing the proper text on the copyright line:
@@ -92,6 +95,10 @@ notice:
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
Style
=====
Make sure lines never exceed 80 columns in width when using four-character
indentation steps. This helps contributors with smaller screens, those using
side-by-side editor windows or panes, and those who have no text wrapping in
@@ -104,8 +111,13 @@ style guide for the usage texts output format [0].
If committing a new utility, please include tests and documentation (see
tests/ and docs/) for the new tool.
If committing a new source file, format the commit message following these
guidelines:
Committing
==========
When contributing to Bonsai, please sign your commit with a PGP key and create
the commit with an identity which can be easily contacted.
Format commit messages following these guidelines:
$ git commit -m 'tool(1): add feature x'
@@ -131,7 +143,13 @@ $ git commit -m 'tool(1): fix #42 & add feature x'
Commit messages should be written in the present tense.
References
==========
[0] <http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/share/misc/style>
--
This work © 20232024 by Emma Tebibyte is licensed under CC BY-SA 4.0. To view a
copy of this license, visit <http://creativecommons.org/licenses/by-sa/4.0/>

View File

@@ -22,9 +22,9 @@ OS_INCLUDE != test -e include/$(OS).mk && printf 'include/$(OS).mk\n' \
|| printf '/dev/null\n'
# normalized prefix
PREFIX_N != dirname $(PREFIX)/.
PREFIX_N != realpath $(PREFIX)
MANDIR != test $(PREFIX_N) = / && printf '/usr/share/man\n' \
|| printf '/share/man\n'
|| printf '$(PREFIX_N)/man\n'
SYSEXITS != printf '\043include <sysexits.h>\n' | cpp -M - | tr ' ' '\n' \
| sed -n 's/sysexits\.h//p' || printf 'include\n'
@@ -42,7 +42,7 @@ BIN = build/bin
default: all test
.PHONY: all
all: dj false fop hru intcmp mm npc rpn scrut str strcmp swab true
all: dj false fop hru intcmp mm npc peek rpn scrut str strcmp swab true
# keep build/include until bindgen(1) has stdin support
# https://github.com/rust-lang/rust-bindgen/issues/2703
@@ -54,9 +54,9 @@ clean:
rm -rf build dist
dist: all docs
mkdir -p $(DESTDIR)/$(PREFIX)/bin $(DESTDIR)/$(PREFIX)/$(MANDIR)/man1
cp build/bin/* $(DESTDIR)/$(PREFIX)/bin
cp build/docs/*.1 $(DESTDIR)/$(PREFIX)/$(MANDIR)/man1
mkdir -p $(DESTDIR)/$(PREFIX_N)/bin $(DESTDIR)/$(MANDIR)/man1
cp build/bin/* $(DESTDIR)/$(PREFIX_N)/bin
cp build/docs/*.1 $(DESTDIR)/$(MANDIR)/man1
.PHONY: install
install: dist
@@ -137,6 +137,11 @@ npc: build/bin/npc
build/bin/npc: src/npc.c build
$(CC) $(CFLAGS) -o $@ src/npc.c
.PHONY: peek
peek: build/bin/peek
build/bin/peek: src/peek.c build
$(CC) $(CFLAGS) -o $@ src/peek.c
.PHONY: rpn
rpn: build/bin/rpn
build/bin/rpn: src/rpn.rs build rustlibs

49
README
View File

@@ -1,24 +1,28 @@
“Seek not to walk the path of the masters; seek what they sought.”
Matsuo Basho
The Bonsai harakit utilities are a replacement for standard POSIX utilities
which aim to fill its niche while expanding on their capabilities. These new
tools are the result of the careful examination of the current state of POSIX
and Unix utilies. The Unix Philosophy of “do one thing and do it well” are their
core but they avoid clinging to the past.
Bonsais Harakit is an alternative to the standard POSIX utilities that aims to
be simpler, easier, and more powerful. These tools are the result of careful
examination of the current state common Unix utilities, POSIX-compliant and
otherwise, following frustrations with design decisions and implementation
details. They represent a vision of accomplishing everyday use cases with tools
that follow the Unix philosophy of “do one thing and do it well” without
clinging to the past.
The era of the original Unix tools has been long and fruitful, but they have
their flaws. This project originated from frustrations with the way certain
tools work and how other projects that extend POSIX dont make anything better.
This project will not follow in the footsteps of GNU; extensions of POSIX will
not be found here. GNU extensions are a gateway to the misuse of the shell. The
harakit utilities will intentionally discourage use of the shell for purposes
beyond its scope.
The intent of Harakit is not to conform to or extend POSIX, like the GNU or BSD
utilities do, but to invent new utilities to perform the same tasks in more
intuitive ways. GNU and BSD extensions are convenient but often unhealthy,
forgetting the purposes of the tools they extend, or building into existing
utilities features that would be more useful as their own tools to be used
anywhere. Other utility sets aim to provide a number of fully-featured
programs to be used individually, Harakit utilities are meant to be easily
composable and work together in pipelines.
See docs/ for more on the specific utilities currently implemented.
Building
========
Harakit utilities require a POSIX-compliant environment to compile, including a
C compiler and preprocessor (cc(1) and cpp(1) by default), an edition 2023 Rust
@@ -43,7 +47,22 @@ To remove all build and distributable files:
$ make clean
Contributing
============
See the CONTRIBUTING file for contribution guidelines.
Community
=========
xmpp://bonsai@covenant.murderu.us
irc://feeling.murderu.us/#bonsai
Read More
=========
An Introduction to the Unix Shell
<https://porkmail.org/era/unix/shell>
@@ -57,6 +76,10 @@ Master Foo Discourses on the Unix-Nature
Shell Programming!
<https://tldp.org/LDP/abs/html/why-shell.html>
UNIX Style, or cat -v Considered Harmful
<http://harmful.cat-v.org/cat-v/>
--
Copyright © 20232024 Emma Tebibyte <emma@tebibyte.media>
Copyright © 2024 DTB <trinity@trinity.moe>

111
docs/peek.1 Normal file
View File

@@ -0,0 +1,111 @@
.\" Copyright (c) 2023-2024 DTB <trinity@trinity.moe>
.\" Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
.\"
.\" This work is licensed under CC BY-SA 4.0. To see a copy of this license,
.\" visit <http://creativecommons.org/licenses/by-sa/4.0/>.
.\"
.TH PEEK 1 2024-08-14 "Harakit X.X.X"
.SH NAME
peek \(en read from the standard input, furtively
.\"
.SH SYNOPSIS
peek
.RB [ -i ]
.\"
.SH DESCRIPTION
Read input from the standard input with terminal echo disabled.
.\"
.SH OPTIONS
.IP \fB-i\fP
Allows input to come from sources other than terminals (pipes).
.\"
.SH DIAGNOSTICS
In the event of an error, a debug message will be printed and the program will
exit with the appropriate
.BR sysexits.h (3)
error code.
In order to ensure the user\(cqs terminal is still usable after premature
termination, the program attempts to handle the SIGINT signal; if it cannot,
an error message is printed and execution continues. If the program is
interrupted, it exits unsuccessfully without an error message.
.\"
.SH RATIONALE
This tool was originally written to accept passwords in shell scripts as an
extremely simple alternative to the GNU Privacy Guard project\(cqs
.BR pinentry (1)
utility.
Accepting input without showing what is being typed is useful when keying in
secrets in public settings or in places where surveillance cameras are
installed.
.\"
.SH CAVEATS
This program does nothing to prevent others from seeing the key presses input to
a keyboard. It also does not protect against the sound of typing being analyzed
to determine what was input without needing to see screen or keyboard.
Accepting secrets in shell scripts is probably not advisable.
On systems that support it, the
.BR ioctl (2)
command TIOCSTI can be used to insert characters into the standard input. This
doesn't allow snooping but can be used for general mischief.
.\"
.SH EXAMPLES
This is an
.BR sh (1p)
command line that hashes a given password. It uses
.BR head (1p)
to only accept one line of input,
.BR xargs (1p)
and
.BR printf (1p)
to strip the trailing newline,
.BR htpasswd (1)
from Apache\(cqs utilities to hash the input with the bcrypt algorithm, and
.BR cut (1p)
to print only the resulting hash:
.RS
$ peek | head -n 1 | xargs printf '%s' | htpasswd -nBi _ | cut -d : -f 2
.RE
This is an
.BR sh (1p)
command line that allows a user to write blindly into a text file but displaying
only written lines. Some writers have the habit of prematurely revising their
work and use tools with functionality similar to this to prevent it.
It uses
.BR mm (1)
to pipe the output of the program to both the standard error and the regular
file writing.txt:
.RS
$ echo Input ^D to quit. && peek | mm -eo - >writing.txt
.RE
.\"
.SH AUTHOR
Written by DTB
.MT trinity@trinity.moe
.ME .
.\"
.SH COPYRIGHT
Copyright \(co 2023-2024 DTB. License AGPLv3+: GNU AGPL version 3 or later
<https://gnu.org/licenses/gpl.html>.
.\"
.SH SEE ALSO
.BR ioctl (2),
.BR ioctl_tty (2),
.BR read (1p),
.BR sh (1p),
.BR stty (1p)

View File

@@ -39,7 +39,7 @@ fn main() {
let mut d = '\u{1E}'.to_string(); /* ASCII record separator */
let mut optind = 1;
if cfg!(target_os="openbsd") {
#[cfg(target_os="openbsd")] {
let promises = Promises::new("stdio proc exec");
if let Err(e) = pledge(Some(promises), None) {
eprintln!("{}: {}", argv[0], e.strerror());

View File

@@ -86,7 +86,7 @@ fn main() -> ExitCode {
return ExitCode::from(EX_USAGE as u8);
}
if cfg!(target_os="openbsd") {
#[cfg(target_os="openbsd")] {
let promises = Promises::new("stdio");
if let Err(e) = pledge(Some(promises), None) {
eprintln!("{}: {}", argv[0], e.strerror());

View File

@@ -42,7 +42,7 @@ fn usage(s: &str) -> ExitCode {
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
if cfg!(target_os="openbsd") {
#[cfg(target_os="openbsd")] {
let promises = Promises::new("stdio");
if let Err(e) = pledge(Some(promises), None) {
eprintln!("{}: {}", argv[0], e.strerror());

View File

@@ -51,8 +51,8 @@ fn main() -> ExitCode {
let argv = args().collect::<Vec<_>>();
let usage = format!("Usage: {} [-aetu] [-i input] [-o output]", argv[0]);
if cfg!(target_os="openbsd") {
let promises = Promises::new("rpath stdio unveil");
#[cfg(target_os="openbsd")] {
let promises = Promises::new("cpath rpath stdio unveil wpath");
if let Err(e) = pledge(Some(promises), None) {
eprintln!("{}: {}", argv[0], e.strerror());
return ExitCode::from(EX_OSERR as u8);
@@ -76,29 +76,11 @@ fn main() -> ExitCode {
Ok("t") => t = false,
Ok("i") => { /* add inputs */
let input = opt.arg().unwrap();
if cfg!(target_os="openbsd") {
let perms = UnveilPerms::new(vec!['r']);
if let Err(e) = unveil(Some(&input), Some(perms)) {
eprintln!("{}: {}", argv[0], e.strerror());
return ExitCode::from(EX_OSERR as u8);
}
}
ins.push(input);
mode = Some(In); /* latest argument == -i */
},
Ok("o") => { /* add output */
let output = opt.arg().unwrap();
if cfg!(target_os="openbsd") {
let perms = UnveilPerms::new(vec!['w', 'c']);
if let Err(e) = unveil(Some(&output), Some(perms)) {
eprintln!("{}: {}", argv[0], e.strerror());
return ExitCode::from(EX_OSERR as u8);
}
}
let output = opt.arg().unwrap();
outs.push(output);
mode = Some(Out); /* latest argument == -o */
},
@@ -124,7 +106,25 @@ fn main() -> ExitCode {
}
}
if cfg!(target_os="openbsd") {
#[cfg(target_os="openbsd")] {
for input in &ins {
let perms = UnveilPerms::new(vec!['r']);
if let Err(e) = unveil(Some(&input), Some(perms)) {
eprintln!("{}: {}", argv[0], e.strerror());
return ExitCode::from(EX_OSERR as u8);
}
}
for output in &outs {
let perms = UnveilPerms::new(vec!['c', 'w']);
if let Err(e) = unveil(Some(&output), Some(perms)) {
eprintln!("{}: {}", argv[0], e.strerror());
return ExitCode::from(EX_OSERR as u8);
}
}
if let Err(e) = unveil(None, None) {
eprintln!("{}: {}", argv[0], e.strerror());
return ExitCode::from(EX_OSERR as u8);

147
src/peek.c Normal file
View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 20232024 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program 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 Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <signal.h> /* sigaction(2), signal(2), struct sigaction, SIGINT */
#include <stdbool.h> /* bool */
#include <stdio.h> /* fprintf(3), fgetc(3), perror(3), fputc(3), stderr, stdin,
* stdout, EOF, NULL */
#include <stdlib.h> /* exit(3), EXIT_FAILURE */
#include <sysexits.h> /* EX_IOERR, EX_OK, EX_USAGE */
#include <termios.h> /* tcgetattr(3), tcsetattr(3), struct termios, ECHO */
#include <unistd.h> /* getopt(3), isatty(3), pledge(2), unveil(2),
* STDIN_FILENO */
char *program_name = "peek";
/* Restores terminal echo; otherwise when a user ^Cs the terminal would
* continue to not display typed text. If sig isn't zero, this will terminate
* the program. */
static void
restore_echo(int sig) {
static struct termios t;
/* Failure isn't reported because this is the termination routine anyway;
* errors will be obvious. */
if (tcgetattr(STDIN_FILENO, &t) == 0) {
t.c_lflag |= ECHO;
(void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &t);
}
if (sig != 0) { exit(EXIT_FAILURE); } /* Terminated by signal. */
return;
}
static int
ioerr(char *argv0) {
perror(argv0);
restore_echo(0);
return EX_IOERR;
}
static int
usage(char *argv0) {
(void)fprintf(stderr, "Usage: %s [-i]\n", argv0);
return EX_USAGE;
}
int main(int argc, char *argv[]){
bool is_term; /* Is stdin a terminal? */
bool must_be_term = 1; /* Must it be? */
#ifdef __OpenBSD__
if (pledge("stdio tty unveil", "") != 0 || unveil(NULL, NULL) != 0) {
/* This isn't fatal; these return values could be cast to void just as
* easily. */
(void)perror(argv[0] == NULL ? argv[0] : program_name);
}
#endif
is_term = isatty(STDIN_FILENO);
if (argc > 0) { /* option parsing */
int c;
program_name = argv[0];
while ((c = getopt(argc, argv, "i")) != -1) {
switch (c) {
case 'i': must_be_term = 0; break;
default: return usage(argv[0]);
}
}
if (argc > optind) { return usage(argv[0]); }
}
if (!is_term && must_be_term) {
(void)fprintf(
stderr,
"%s: Must be run in a terminal (specify -i to skip this check)\n",
argv[0]
);
return EX_USAGE;
}
if (is_term) {
{ /* Install signal handler */
/* There isn't a difference in functionality between the signal(2)
* and sigaction(2) methods. sigaction(2) is vastly preferred for
* portability but some older systems only have signal(2). */
/* Errors aren't terminating because the worst that happens is some
* terminal phooeyness if things go awry. */
#if defined _POSIX_C_SOURCE
struct sigaction act = { 0 };
act.sa_handler = restore_echo;
if (sigaction(SIGINT, &act, NULL) != 0) { perror(program_name); }
#else
if (signal(SIGINT, restore_echo) == SIG_ERR) {
perror(program_name);
}
#endif
}
{ /* Banish terminal echo */
/* This terminates when it fails because it's the whole point of
* the program. */
struct termios t;
if (tcgetattr(STDIN_FILENO, &t) != 0) {
return ioerr(program_name);
}
t.c_lflag ^= ECHO;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) != 0) {
return ioerr(program_name);
}
}
}
{ /* Input loop */
int c;
while ((c = fgetc(stdin)) != EOF) {
if (fputc(c, stdout) == EOF) { return ioerr(program_name); }
}
}
if (is_term) { restore_echo(0); }
return EX_OK;
}

View File

@@ -198,7 +198,7 @@ fn round_precise(value: &f64, precision: usize) -> f64 {
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
if cfg!(target_os="openbsd") {
#[cfg(target_os="openbsd")] {
let promises = Promises::new("stdio");
if let Err(e) = pledge(Some(promises), None) {
eprintln!("{}: {}", argv[0], e.strerror());

View File

@@ -54,7 +54,7 @@ fn usage(s: &str) -> ExitCode {
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
if cfg!(target_os="openbsd") {
#[cfg(target_os="openbsd")] {
let promises = Promises::new("stdio");
if let Err(e) = pledge(Some(promises), None) {
return oserr(&argv[0], e);

View File

@@ -19,7 +19,7 @@ dj_tests: dj_help dj_full dj_null # dj_skip_stdin
dj_full: $(BIN)/dj /dev/full
case "$$(uname)" in \
Linux) \
$(BIN)/dj -Hi /dev/zero -o /dev/full 2>&1 \
! $(BIN)/dj -Hi /dev/zero -o /dev/full 2>&1 \
| tee /dev/stderr \
| xargs -I out test '1+0 > 0+0; 1024 > 0' = out \
;; \

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2024 E$(NAME)a Tebibyte <e$(NAME)a@tebibyte.media>
# Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
# SPDX-License-Identifier: FSFAP
#
# Copying and distribution of this file, with or without modification, are
@@ -6,7 +6,7 @@
# notice are preserved. This file is offered as-is, without any warranty.
.PHONY: mm_tests
mm_tests: mm_args mm_help mm_stderr
mm_tests: mm_args mm_help mm_stderr mm_remaining
.PHONY: mm_none
mm_none: $(BIN)/mm
@@ -25,3 +25,10 @@ mm_help: $(BIN)/mm
# check if stderr is empty upon specifying -e
mm_stderr: $(BIN)/mm
test "$$(printf 'test\n' | $(BIN)/mm -e 2>&1 >/dev/null )" = "test"
.PHONY: mm_remaining
# check to make sure remaining arguments are used
mm_remaining: $(BIN)/mm
test "$$($(BIN)/mm -i README COPYING)" = "$$(cat README COPYING)"
$(BIN)/mm -i README -o /tmp/mm_test0 /tmp/mm_test1
diff /tmp/mm_test0 /tmp/mm_test1

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# Copyright (c) 2024 DTB <trinity@trinity.moe>
# Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
# Copyright (c) 20242025 Emma Tebibyte <emma@tebibyte.media>
# SPDX-License-Identifier: FSFAP
#
# Copying and distribution of this file, with or without modification, are
@@ -26,17 +26,35 @@ npc_args:
.PHONY: npc_ascii
# Test 0x00 to 0x7f in input; in other words, the full 7b ASCII range.
npc_ascii: npc_ascii_controls npc_ascii_symbols npc_ascii_uppers # \
npc_ascii: npc_ascii_controls npc_ascii_uppers # npc_ascii_symbols \
# npc_ascii_lowers
.PHONY: npc_ascii_controls
# (control characters)
npc_ascii_controls:
# The following test prints the bytes 0x00 (inclusive) through 0x20
# (exclusive) and pipes them through npc(1). npc(1) should then replace all
# non-printing, non-space (in the isspace(3p) sense) characters with their
# graphical carat-char counterparts (see the npc(1) man page). The head(1p)
# invocation then strips off everything past the first line (or past the
# first newline byte, 0x0A) and xargs(1p) is used to test(1p) the output
# against the known good answer.
# Immediately before that newline, 0x09 is printed - in ASCII, the
# horizontal tab. If xargs' -I option is used, tr(1p) should used to delete
# that tab. If the tab is left as part of input, OpenBSD's xargs(1)
# implementation has been observed to strip it along with the other
# trailing whitespace (the newline), but Busybox's and GNU's xargs(1)
# implementations have been observed to leave the tab in. All three
# implementations strip off the trailing tab if `-I` is not used. The POSIX
# specification for `-I` is ambiguous as to which behavior is correct.
# This comment is the result of much bewilderment and debugging.
# ASCII 0x00 to 0x0a (before the newline, due to xargs(1p) issues)
awk 'BEGIN{ for (i = 0; i < 32; ++i) printf("%c", i); }' \
| $(BIN)/npc \
| head -n 1 \
| xargs -I out test "^@^A^B^C^D^E^F^G^H" = out
| xargs test "^@^A^B^C^D^E^F^G^H" =
# ASCII 0x0a (otherwise the head|tail sequence won't work) to 0x1f
awk 'BEGIN{ for (i = 0; i < 32; ++i) printf("%c", i); print }' \
@@ -45,14 +63,18 @@ npc_ascii_controls:
| tail -n 1 \
| xargs -I out test "^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_"
.PHONY: npc_ascii_symbols
# ASCII 0x1f to 0x3f (^_ and symbols)
npc_ascii_symbols:
# shell quoting olympics
awk 'BEGIN{ for (i = 31; i < 64; ++i) printf("%c", i); print }' \
| $(BIN)/npc \
| sed -e s"/\'/\\\'/g" -e 's/"/\\"/g' \
| xargs -I out test "^_ !\"#$$%&'()*+,-./0123456789:;<=>?" = out
# This test is broken on Linux and will need closer inspection along with GNU
# xargs(1).
# .PHONY: npc_ascii_symbols
# # ASCII 0x1f to 0x3f (^_ and symbols)
# npc_ascii_symbols:
# # shell quoting olympics
# c="$(awk 'BEGIN{ for (i = 31; i < 64; ++i) printf("%c", i); print }')"
#
# printf '%s\n' "$c" | $(BIN)/npc \
# | sed -e s"/\'/\\\'/g" -e 's/"/\\"/g' \
# | tr -d '\n' \
# | xargs -I out test "^_ !\"#$$%&\'()*+,-./0123456789:;<=>?" = out
.PHONY: npc_ascii_uppers
# ASCII 0x40 to 0x5f (uppercases)

24
tests/bonsai/peek.mk Executable file
View File

@@ -0,0 +1,24 @@
# Copyright (c) 2024 DTB <trinity@trinity.moe>
# SPDX-License-Identifier: FSFAP
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice and this
# notice are preserved. This file is offered as-is, without any warranty.
# Testing peek is hard as it requires visual confirmation that text isn't being
# echoed. These tests don't go that far but are a start, and have already
# caught a bug in -i behavior.
.PHONY: peek_tests
peek_tests: peek_help peek_stdio
.PHONY: peek_help
peek_help: $(BIN)/peek
! $(BIN)/peek -h
.PHONY: peek_stdio
# Test peek -i
peek_stdio: $(BIN)/peek
printf 'Test.\n' \
| $(BIN)/peek -i \
| xargs test 'Test.' =

View File

@@ -30,7 +30,7 @@ rpn_mul: $(BIN)/rpn
.PHONY: rpn_div
rpn_div: $(BIN)/rpn
test "$$($(BIN)/rpn 12 5 /)" = 2.4
test "$$($(BIN)/rpn 3 0 /)" -eq inf
test "$$($(BIN)/rpn 3 0 /)" = inf
.PHONY: rpn_mod
rpn_mod: $(BIN)/rpn