Compare commits

..

6 Commits

Author SHA1 Message Date
DTB
2337cedd77
run.1: rename man page from simexec.1 2024-07-24 23:45:16 -06:00
DTB
e0f9641e93
run(1) works 2024-07-24 23:39:47 -06:00
DTB
f7e0cb5c14
simexec(1): rename to run(1) 2024-07-24 19:04:02 -06:00
DTB
653576b35d
simexec(1): Merge in pschdir(1) functionality 2024-07-24 19:02:23 -06:00
DTB
87845ba5bd
Merge branch 'pschdir' into simexec 2024-07-24 18:47:09 -06:00
DTB
427e1b9d36
simexec(1): non-functional Rust rewrite 2024-07-24 18:46:05 -06:00
9 changed files with 173 additions and 246 deletions

View File

@ -31,8 +31,8 @@ RUSTLIBS = --extern getopt=build/o/libgetopt.rlib \
--extern strerror=build/o/libstrerror.rlib --extern strerror=build/o/libstrerror.rlib
CFLAGS += -I$(SYSEXITS) CFLAGS += -I$(SYSEXITS)
all: argued dj false fop hru intcmp mm npc pschdir retval rpn scrut simexec \ .PHONY: all
str strcmp swab true all: dj false fop hru intcmp mm npc rpn run scrut str strcmp swab true
# keep build/include until bindgen(1) has stdin support # keep build/include until bindgen(1) has stdin support
# https://github.com/rust-lang/rust-bindgen/issues/2703 # https://github.com/rust-lang/rust-bindgen/issues/2703
@ -87,11 +87,6 @@ build/o/libsysexits.rlib: build/include/sysexits.h
build/include/sysexits.h: build $(SYSEXITS)sysexits.h build/include/sysexits.h: build $(SYSEXITS)sysexits.h
printf '\043define EXIT_FAILURE 1\n' | cat - $(SYSEXITS)sysexits.h > $@ printf '\043define EXIT_FAILURE 1\n' | cat - $(SYSEXITS)sysexits.h > $@
.PHONY: argued
argued: build/bin/argued
build/bin/argued: src/argued.rs build
$(RUSTC) $(RUSTFLAGS) -o $@ src/argued.rs
.PHONY: dj .PHONY: dj
dj: build/bin/dj dj: build/bin/dj
build/bin/dj: src/dj.c build build/bin/dj: src/dj.c build
@ -127,31 +122,21 @@ npc: build/bin/npc
build/bin/npc: src/npc.c build build/bin/npc: src/npc.c build
$(CC) $(CFLAGAS) -o $@ src/npc.c $(CC) $(CFLAGAS) -o $@ src/npc.c
.PHONY: pschdir
pschdir: build/bin/pschdir
build/bin/pschdir: src/pschdir.rs build
$(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/pschdir.rs
.PHONY: retval
retval: build/bin/retval
build/bin/retval: src/retval.rs build rustlibs
$(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/retval.rs
.PHONY: rpn .PHONY: rpn
rpn: build/bin/rpn rpn: build/bin/rpn
build/bin/rpn: src/rpn.rs build rustlibs build/bin/rpn: src/rpn.rs build rustlibs
$(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/rpn.rs $(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/rpn.rs
.PHONY: run
run: build/bin/run
build/bin/run: src/run.rs build
$(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/run.rs
.PHONY: scrut .PHONY: scrut
scrut: build/bin/scrut scrut: build/bin/scrut
build/bin/scrut: src/scrut.c build build/bin/scrut: src/scrut.c build
$(CC) $(CFLAGS) -o $@ src/scrut.c $(CC) $(CFLAGS) -o $@ src/scrut.c
.PHONY: simexec
simexec: build/bin/simexec
build/bin/simexec: src/simexec.c build
$(CC) $(CFLAGS) -o $@ src/simexec.c
.PHONY: str .PHONY: str
str: build/bin/str str: build/bin/str
build/bin/str: src/str.c build build/bin/str: src/str.c build

58
README
View File

@ -1,9 +1,61 @@
overgrown - trinity's harakit workshop “Seek not to walk the path of the masters; seek what they sought.”
Matsuo Basho
simple build, no dependencies except rust 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.
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.
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
compiler (rustc(1) by default), bindgen(1), and a POSIX-compliant make(1)
utility.
To build and install:
# pkg_add rust rust-bindgen
$ make $ make
$ make PREFIX="/your/preferred/location" install
To build with a different compiler than the default:
$ make CC=clang
$ make RUSTC=gccrs
To test the utilities:
$ make test
To remove all build and distributable files:
$ make clean
Read More
An Introduction to the Unix Shell
<https://porkmail.org/era/unix/shell>
Master Foo and the Ten Thousand Lines
<http://www.catb.org/~esr/writings/unix-koans/ten-thousand.html>
Master Foo Discourses on the Unix-Nature
<http://www.catb.org/~esr/writings/unix-koans/unix-nature.html>
Shell Programming!
<https://tldp.org/LDP/abs/html/why-shell.html>
-- --
Copyright © 20232024 Emma Tebibyte <emma@tebibyte.media> Copyright © 20232024 Emma Tebibyte <emma@tebibyte.media>

View File

@ -1,28 +0,0 @@
.\" Copyright (c) 20222024 DTB <trinity@trinity.moe>
.\"
.\" 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 ARGUED 1 2024-07-23 "Harakit-overgrown X.X.X"
.SH NAME
argued \(en check for arguments
.\"
.SH DESCRIPTION
.BR argued (1)
exits successfully if any arguments are provided, and unsuccessfully
otherwise.
.\"
.SH AUTHOR
Written by DTB
.MT trinity@trinity.moe
.ME .
.\"
.SH COPYRIGHT
This work is marked with CC0 1.0. To see a copy of this license, visit
<http://creativecommons.org/publicdomain/zero/1.0>.
.\"
.SH SEE ALSO
.BR test (1)

View File

@ -3,52 +3,31 @@
.\" This work is licensed under CC BY-SA 4.0. To see a copy of this license, .\" 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/>. .\" visit <http://creativecommons.org/licenses/by-sa/4.0/>.
.\" .\"
.TH SIMEXEC 1 2024-07-23 "Harakit-overgrown X.X.X" .TH SIMEXEC 1 2024-07-24 "Harakit-overgrown X.X.X"
.SH NAME .SH NAME
simexec \(en execute a program with argv run \(en execute a program
.\" .\"
.SH SYNOPSIS .SH SYNOPSIS
simexec run
.B binary argv... .B binary argument...
.\"
.SH DESCRIPTION .SH DESCRIPTION
Execute a binary with a certain argv. Execute a binary with arguments.
.\"
.SH CAVEATS .SH CAVEATS
Non-binary programs cannot be executed on their own. The PATH environment Non-binary programs cannot be executed on their own. The PATH environment
variable is not used and a valid pathname (relative or absolute) must be variable is not used and a valid pathname (relative or absolute) must be
specified. specified.
.BR simexec (1)
requires caution.
.B argv
are not just the operands for the binary but in fact the direct
.B argv
it will receive in runtime;
the first argv entry is the program\(cqs name, and omitting this, though valid
use of
.BR simexec (1),
can break false assumptions made by programmers.
for example, the
.BR true (1)
implementation in the GNU coreutils project suffers a segmentation fault it is
given no argv[0].
While POSIX.1-2017 doesn't mandate there being an argv[0] per se, a Strictly While POSIX.1-2017 doesn't mandate there being an argv[0] per se, a Strictly
Conforming POSIX Application must pass an argv[0]. It has also been said that Conforming POSIX Application must pass an argv[0]. It has also been said that
those who do not pass an argv[0] are mean and nasty and smell of elderberries. those who do not pass an argv[0] are mean and nasty and smell of elderberries.
.BR simexec (1)
directly uses the
.BR execv (3p)
library function. It cannot execute shell scripts intelligently (via shebang).
It is inadviseable to use
.BR simexec (1)
to simply execute a program when other methods would suffice.
.\" .\"
.SH DIAGNOSTICS .SH DIAGNOSTICS
.BR simexec (1) .BR run (1)
exits with the returned value of exits with the returned value of
.BR execv (3p), .BR execv (3p),
which will be 255 if an error occurs in execution, such as the binary not being which will be 255 if an error occurs in execution, such as the binary not being
@ -56,7 +35,8 @@ found.
This is indistinguishable from the executed binary exiting with the same This is indistinguishable from the executed binary exiting with the same
status. status.
Simexec will print a error message and return the proper .BR run (1)
will print a error message and return the proper
.BR sysexits.h (3) .BR sysexits.h (3)
value if invoked in an invalid manner. value if invoked in an invalid manner.
.\" .\"
@ -76,4 +56,5 @@ Copyright \(co 20222024 DTB. License AGPLv3+: GNU AGPL version 3 or later
The C89 standard's draft, section 2.1.2.2: "Hosted environment". The C89 standard's draft, section 2.1.2.2: "Hosted environment".
POSIX.1-2017 System Interfaces: execv. Particularly under the RATIONALE section header. POSIX.1-2017 System Interfaces: execv. Particularly under the RATIONALE section
header.

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2022_2024 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/.
*/
use std::{ env::args, process::ExitCode };
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
match argv.len() {
0 | 1 => ExitCode::FAILURE,
_ => ExitCode::SUCCESS
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2023_2024 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/.
*/
use std::{ env::args, io::Error, process::{ Command, ExitCode } };
extern crate strerror;
use strerror::StrError;
extern crate sysexits;
use sysexits::{ EX_UNAVAILABLE, EX_USAGE };
fn error(p: &str, n: &str, e: Error) -> ExitCode {
eprintln!("{}: {}: {}", p, n, e.strerror());
ExitCode::from(EX_UNAVAILABLE as u8)
}
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
if argv.len() < 3 {
eprintln!("Usage: {} directory command [argument]", argv[0]);
return ExitCode::from(EX_USAGE as u8);
}
let cmdargs = argv.iter().clone().skip(3).collect::<Vec<&String>>();
match Command::new(argv[2].clone())
.current_dir(argv[1].clone())
.args(cmdargs)
.spawn() {
Ok(mut child) => match child.wait() {
Ok(status) => {
match status.code() {
Some(code) => ExitCode::from(code as u8),
None => {
eprintln!("{}: {}: process terminated by signal",
argv[0], argv[2]);
ExitCode::FAILURE
}
}
},
Err(e) => error(&argv[0], &argv[2], e)
},
Err(e) => error(&argv[0], &argv[2], e)
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright (c) 2024 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/.
*/
use std::{ env::args, process::ExitCode };
extern crate sysexits;
use sysexits::EX_USAGE;
fn usage(s: &str) -> ExitCode {
eprintln!("Usage: {} status", s);
ExitCode::from(EX_USAGE)
}
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
match argv.len() {
2 => match argv[1].parse::<u8>() {
Ok(e) => ExitCode::from(e),
_ => usage(&argv[0])
},
_ => usage(&argv[0])
}
}

99
src/run.rs Normal file
View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 20222024 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/.
*/
use std::{
env::args,
io::Error,
os::unix::process::CommandExt,
process::{ Command, ExitCode }
};
extern crate getopt;
use getopt::GetOpt;
extern crate strerror;
use strerror::StrError;
extern crate sysexits;
use sysexits::{ EX_UNAVAILABLE, EX_USAGE };
fn error(p: &str, n: &str, e: Error) -> ExitCode {
eprintln!("{}: {}: {}", p, n, e.strerror());
ExitCode::from(EX_UNAVAILABLE as u8)
}
fn usage(s: &str) -> ExitCode {
eprintln!("Usage: {} command [argument...]", s);
ExitCode::from(EX_USAGE as u8)
}
fn main() -> ExitCode {
let argv = args().collect::<Vec<String>>();
let mut optind = 1;
/* arg0 is None if no argv[0] is meant to be given (argc will be 0),
* however I don't know how to do this in Rust, so the option is currently
* meaningless. -z will set this to None. */
let mut arg0: Option<String> = Some(String::default());
let mut dir = String::from("."); // $PWD for command
while let Some(opt) = argv.getopt("C:n:z") {
match opt.opt() {
// Consistent with precedent; git, make, tar, etc.
Ok("C") => dir = opt.arg().unwrap(),
Ok("n") => arg0 = Some(opt.arg().unwrap()),
// Ok("z") => arg0 = None,
_ => { return usage(&argv[0]); }
}
optind = opt.ind();
}
if argv.len() - optind < 1 { return usage(&argv[0]); }
let mut cmd = Command::new(argv[optind].clone());
cmd.current_dir(dir.clone());
match arg0 {
Some(a) if a != String::default() => { cmd.arg0(a); },
_ => () // TODO: argv[0]==NULL support
}
if argv.len() - optind > 1 { // there are arguments
let cmdargs = argv
.iter()
.clone()
.skip(optind + 1)
.collect::<Vec<&String>>();
cmd.args(cmdargs);
}
match cmd.spawn() {
Ok(mut child) => match child.wait() {
Ok(status) => match status.code() {
Some(code) => ExitCode::from(code as u8),
None => {
eprintln!("{}: {}: process terminated by signal",
argv[0], argv[2]);
ExitCode::FAILURE
}
},
Err(e) => error(&argv[0], &argv[optind], e)
},
Err(e) => error(&argv[0], &argv[optind], e)
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 20222024 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 <stdio.h> /* fprintf(3), NULL */
#include <unistd.h> /* execv(3), */
#include <sysexits.h> /* EX_USAGE */
char *program_name = "simexec";
int main(int argc, char *argv[]){
if (argc < 2) {
fprintf(stderr, "Usage: %s binary argv...\n",
argv[0] == NULL ? program_name : argv[0]
);
return EX_USAGE;
}
execv(argv[1], &argv[2]);
}