diff --git a/Makefile b/Makefile index f181e20..cb6bca6 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,11 @@ PREFIX=/usr/local -CC=cc -RUSTC=rustc +CC != command -v "$$CC" || printf 'cc\n' +RUSTC != command -v "$$RUSTC" || printf 'rustc\n' +RUSTLIBS=--extern getopt=build/o/libgetopt.rlib \ + --extern sysexits=build/o/libsysexits.rlib \ + --extern strerror=build/o/libstrerror.rlib .PHONY: all all: dj false fop hru intcmp rpn scrut str strcmp true @@ -43,6 +46,18 @@ test: build tests/posix-compat.sh $(RUSTC) --test src/getopt-rs/lib.rs -o build/test/getopt +.PHONY: rustlibs +rustlibs: build/o/libsysexits.rlib build/o/libgetopt.rlib \ + build/o/libstrerror.rlib + +build/o/libgetopt.rlib: build src/getopt-rs/lib.rs + $(RUSTC) $(RUSTFLAGS) --crate-type=lib --crate-name=getopt \ + -o $@ src/getopt-rs/lib.rs + +build/o/libstrerror.rlib: build src/strerror.rs + $(RUSTC) $(RUSTFLAGS) --crate-type=lib -o $@ \ + src/strerror.rs + build/o/libsysexits.rlib: build # bandage solution until bindgen(1) gets stdin support printf '#define EXIT_FAILURE 1\n' | cat - include/sysexits.h \ @@ -51,11 +66,7 @@ build/o/libsysexits.rlib: build "$$(printf '#include \n' \ | cpp -M -idirafter "build/include" - \ | sed 's/ /\n/g' | grep sysexits.h)" \ - | $(RUSTC) $(RUSTFLAGS) --crate-type lib -o build/o/libsysexits.rlib - - -build/o/libgetopt.rlib: src/getopt-rs/lib.rs - $(RUSTC) $(RUSTFLAGS) --crate-type=lib --crate-name=getopt \ - -o build/o/libgetopt.rlib src/getopt-rs/lib.rs + | $(RUSTC) $(RUSTFLAGS) --crate-type lib -o $@ - .PHONY: dj dj: build/bin/dj @@ -69,17 +80,13 @@ build/bin/false: src/false.c build .PHONY: fop fop: build/bin/fop -build/bin/fop: src/fop.rs build build/o/libgetopt.rlib build/o/libsysexits.rlib - $(RUSTC) $(RUSTFLAGS) --extern getopt=build/o/libgetopt.rlib \ - --extern sysexits=build/o/libsysexits.rlib \ - -o $@ src/fop.rs +build/bin/fop: src/fop.rs build rustlibs + $(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/fop.rs .PHONY: hru hru: build/bin/hru -build/bin/hru: src/hru.rs build build/o/libgetopt.rlib build/o/libsysexits.rlib - $(RUSTC) $(RUSTFLAGS) --extern getopt=build/o/libgetopt.rlib \ - --extern sysexits=build/o/libsysexits.rlib \ - -o $@ src/hru.rs +build/bin/hru: src/hru.rs build rustlibs + $(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/hru.rs .PHONY: intcmp intcmp: build/bin/intcmp @@ -88,10 +95,8 @@ build/bin/intcmp: src/intcmp.c build .PHONY: rpn rpn: build/bin/rpn -build/bin/rpn: src/rpn.rs build build/o/libsysexits.rlib - $(RUSTC) $(RUSTFLAGS) \ - --extern sysexits=build/o/libsysexits.rlib \ - -o $@ src/rpn.rs +build/bin/rpn: src/rpn.rs build rustlibs + $(RUSTC) $(RUSTFLAGS) $(RUSTLIBS) -o $@ src/rpn.rs .PHONY: scrut scrut: build/bin/scrut diff --git a/src/strerror.rs b/src/strerror.rs new file mode 100644 index 0000000..0939df9 --- /dev/null +++ b/src/strerror.rs @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Emma Tebibyte + * 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. + */ + +use std::ffi::{ c_int, c_char, CStr }; + +/* binding to strerror(3p) */ +extern "C" { fn strerror(errnum: c_int) -> *mut c_char; } + +/* wrapper function for use in Rust */ +pub fn c_error(err: std::io::Error) -> String { + /* Get the raw OS error. If it’s None, what the hell is going on‽ */ + let error = err.raw_os_error().unwrap_or_else(|| { panic!() }) as c_int; + + /* Get a CStr from the error message so that it’s referenced and then + * convert it to an owned value. If the string is not valid UTF-8, return + * that error instead. */ + match unsafe { CStr::from_ptr(strerror(error)) }.to_str() { + Ok(s) => s.to_owned(), // yay!! :D + Err(e) => e.to_string(), // awww :( + } +}