16 04 | 2012

“Everything is a file” rocks

Written by Tanguy

Classified in : Homepage, Debian, Command line, Miscellaneous

Licence plate with “UNIX” written, subtitle “live free or die”

Unix rocks, or at least one of its design feature does: everything is a file.

Here is one funny use of that feature. I consider that programs that manipulate text should basically take it on their standard input, and write it to their standard output, while specifying the name of an input or output file should be an optional refinement.

Well, at least one program was designed the other way: when used to import a foreign key, ssh-keygen -i has no option to read it on its standard input. No problem, this can be worked around:

# ssh-keygen -if /dev/stdin
[paste the foreign key here]

Unfortunately, that does not work with every action of ssh-keygen since not all of them were written to be able to handle streams, which cannot be rewound.


monday 16 april 2012 à 21:35 Adam Skutt said : #1

Except everything isn't a file. You can't seek pipes or sockets. You can't do select/poll based non-blocking I/O on actual files on disk. The only common operation supported by everything is close(2).

And while most applications should probably support I/O operations from stdin to stdout, it's just not feasible for all operating modes of several key UNIX applications like sort(1) and join(1).

Windows NT does the "Everything is a handle" thing much better since it has actual support for polymorphic handles, though it still has a considerable number of warts.

tuesday 17 april 2012 à 02:05 Stan Schwertly said : #2

I love this! Saving the idea for later for when a second dash on the parameter won't switch to STDIN!

tuesday 17 april 2012 à 12:30 Eddi said : #3

But, as it seems, this handling of /dev/stdin is a Bash feature! Maybe other shells (Zsh comes to mind) support that too.

tuesday 17 april 2012 à 13:03 Tanguy said : #4

@Eddi : No it is not. /dev/std* do exist and they are symlinks to /proc/self/sd*, where /proc/self is itself a symlink to the current process. So in fact, /dev/stdin points to /proc/PID/fd/0. When that process was launched without a redirection, this is a symlink to the corresponding terminal device, for instance /dev/tty1 or /dev/pts/1. When it was launched with a file redirection it is a symlink to that file, and when it was launched in a pipeline it is a symlink to some kind of pipe identifier.

tuesday 17 april 2012 à 21:10 9fan said : #5

"Everything is a file" is the biggest lie of Unix. Take a closer look at Plan 9.

tuesday 17 april 2012 à 22:39 Tranxene50 said : #6

> "Everything is a file" is the biggest lie of Unix.

Please, could you explain, more precisely?

Everything can be opened, read and written so, IMHO, yes, everything is a file.


tuesday 17 april 2012 à 22:47 Jakob said : #7

I am using “dd of=/dev/stdout if=/dev/zero foo=bar” all the time! ;)

wednesday 18 april 2012 à 00:41 Adam Skutt said : #8

Nope, there are plenty of things that you cannot open(2): sockets, certain types of pipes, certain types of devices. Some interfaces have specific and unusual semantics for open(2), such as named sockets.

Some devices don't support read/write. Some socket drivers don't support them either under certain conditions.

Many things don't support mmap(2).

As I said originally, the only thing that's universally supported is close(2). Only the most basic I/O code can be written without considering what I/O interfaces will be involved.

Write a comment

What is the second letter of the word ovxd? :