Hacker News new | ask | show | jobs
by theamk 698 days ago
If you are wondering how it handles C-only functions.. it does not.

open(..., O_RDWR | O_EXCL) -> runtime error, "echo "Unknow file mode" ; exit 1"

lseek(fd, 1, SEEK_HOLE); -> invalid code (uses undefined _lseek)

socket(AF_UNIX, SOCK_STREAM, 0); -> same (uses undefined _socket)

looking closer at "cp" and "cat" examples, write() call does not handle errors at all. Forget about partial writes, it does not even return -1 on failures.

"Compiler you can Trust", indeed... maybe you can trust it to get all the details wrong?

4 comments

There seems to be libc in the repo but many functions are TODO https://github.com/udem-dlteam/pnut/tree/main/portable_libc

Otherwise the builtins seems to be here https://github.com/udem-dlteam/pnut/blob/main/runtime.sh

FYI all your functions are not "C functions", but rather POSIX functions. I did not expect it to be complete, but it's still impressive for what it is.

There are Linux ports of the plan9 `syscall` binary, which is presumably necessary to implement parts of libc with shell scripts: https://stackoverflow.com/questions/10196395/os-system-calls...

I don't remember there being a way to keep a server listening on a /dev/tcp/$ip/$port port, for sockets from shell scripts with shellcheck at least

I suspect the “trust” is a reference to Ken Thompson’s Turing Award speech “Reflections on trusting trust” where he laid out the concern of a back door in a compiler that survives updates to the compiler. In other words, the compiler injects a back door into future versions of itself in addition into your programs that source level analysis of the code will never reveal.

I think the pitch here is that it can compile TCC which can then compile GCC which makes it much more difficult for a backdoor to survive potentially, especially if the shell code is easier to read and verify than the corresponding assembly.

Within that context, an incomplete libc is irrelevant.

Implementation issues aside, while technically it should be possible to seek a file descriptor from shell through a suitable helper program in C, I believe none of the POSIX utilities provide this facility
head, read, and sed can be used for seeking forward according to POSIX (see the INPUT FILES section here <https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V...>). I doubt non-GNU implementations support it though.
If it’s in POSIX, chances are the BSDs implement it, too.

I think seeking a specific number of bytes and then writing data there will be a problem, though.

For seeking n bytes, read nor sed will work; they work with lines.

sed is the only one of those that can write, and POSIX doesn’t appear to have the -i option for in-place editing (https://pubs.opengroup.org/onlinepubs/9699919799/utilities/s...)

So, I think head for seeking followed by sed (or ed or vi, but sed is the simpler tool, I think) for replacing the first n characters, redirecting to a temp file and then doing a mv is your only option.

Advantage will be that writes will be atomic; disadvantage that it will be slow

head was used for this purpose in the xz backdoor.
I think dd might be more reliable. (Is dd POSIX?)
maybe access to libc functions can be achieved through something like <https://github.com/taviso/ctypes.sh>. Although that very specific implementation seems to require explicitly bash and is not broadly POSIX Shell compatible as Pnut wants to be.