Rust port of Apple's shell_cmds
Port Apple's shell commands from C to Rust.
-
Want to help? Jump right in! If you would rather talk first then contact me by creating an issue
-
Code to port: shell_cmds version 198
-
Commands need a file in
src/bin/
with afn main()
. For exampleecho
hassrc/bin/echo.rs
-
To compile+run your new command (for example)
echo arg1 arg2
you would docargo run --bin echo -- arg1 arg2
-
Use
std::env::args()
directly for the dirt-simple utilities. Use getopts for the fancier ones. -
Put the man pages (files ending in
.1
) in theman/
directory. -
Put the companion shell scripts in the
sh/
directory. -
When there's a license header, copy it over verbatim into the
.rs
file for the binary. (Lawyer repellent.)
- alias - Just a man page pointer to
builtin.1
, which iscsh
's manpage. - apply - Some serious pointer-loop reverse engineering on this one.
- basename - Ancient utilities are frustrating because their behavior with
arguments makes no blasted sense.
basename
is one of these. If it has exactly two arguments, then it acts completely differently. - chroot - Many calls to libc. Seems to have matched behavior exactly, except for the buffer overflow vulnerability.
- date
- dirname - Shares a man page with basename.
- echo - Got an education in rust Strings.
- env
- expr
- false - Simple.
- find
- getopt
- hexdump
- hostname
- id
- jot
- kill
- killall
- lastcomm
- locate
- logname
- mktemp
- nice
- nohup
- path_helper
- printenv - Done. Did you know printenv silently ignores any extra arguments?
- pwd
- renice
- script
- seq
- sh
- shlock
- sleep - Instead of treating invalid input as 0 silently, we spit out the usage and die.
- su
- systime
- tee - Done. Good practice with
Vec
,zip()
,stdin/stdout/stderr
, and files. - test
- time
- true - Simple.
- uname
- users
- w
- what
- whereis
- which
- who
- xargs
- yes - Did you know that
yes
takes an optional argument?
Below is a partial list of bugs discovered in C code of Apple's shell_cmds version 198 -- which ships on macOS Sierra.
- Buffer Overflow: If more than 16 valid groups are provided to the
-G
option, then thegidlist
buffer overflows and starts overwriting later data in the stack frame with resolved group ids. That is not difficult to do since macOS ships with over 100 valid groups by default. In Rust, we use aVec
to store the resolved group ids.Vec
is dynamically sized, so it won't overflow.