Unix (/ˈjuːnɪks/; trademarked as UNIX) is a family of multitasking, multiuser computer operating systems that derive from the original AT&T Unix, whose development started in 1969 at the Bell Labs research center by Ken Thompson, Dennis Ritchie, and others.



UNIX was an operating systems experiment started when Bell Labs started to leave the Multics project because most of their community felt Multics hadn't delivered what it promised, its titular multiplexed information and computing service. The Bell Labs engineers working on Multics at the time (Ken Thompson, Dennis Ritchie, Malcolm Douglas McIlroy, and Joseph Frank Ossanna) had realized Multics' goal as a system but at an unsustainable cost, so, reading the writing on the wall, they began working on a new operating system and unsuccessfully lobbying Bell Labs for their own computer on which to work. Thompson, Rudd H. Canaday, and Ritchie developed a heirarchical file system and Thompson simulated it on Multics. Thompson also developed Space Travel, first for Multics, then for another operating system where it ran poorly. Hoping to be able to continue to work on Space Travel, which simulated the movements of the major cellestial bodies of the Solar System and allowed the player to roam in a starship among them, past Multics' demise at Bell Labs, Thompson rewrote the game to run on a spare PDP-7 at Bell. Having written so much code already to get the PDP-7 to work, Thompson started to work on other things for it; a file system, some utilities for it, a command interpreter, and an assembler. Then, mid-1970, Brian Kernighan named the non-multiplexing Multics workalike Unics, which was somehow (see Interview with Brian Kernighan) bastardized into Unix.

1971; First Edition; It had a assembler for a PDP-11/20, file system, fork(), roff and ed. It was used for text processing of patent documents.
(History and Timeline)


1973; Fourth Edition; It was rewritten in C. This made it portable and changed the history of OS's.
(History and Timeline)


There had been a highly regarded ACM SIGOPS sponsored conference on operating systems at Gatlinburg, Tennessee in 1967. The fourth of these conferences was held in Yorktown Heights, NY in 1973, and Ken and Dennis gave a talk there, presenting Unix. Several of us Multicians went to the conference, and sat with the Bell Labs ex-Multicians, and applauded the paper, which was and remains one of the best and clearest pieces of writing in the computer field. There were some other great papers at that conference, but as I remember, the Unix paper won the best paper award.

I was working for MIT in those days, and one thing I did was to organize an MIT PDP-11 users' group and encourage them to look into Unix. The idea of a free, non-vendor-supported operating system was new to them. I invited Dennis Ritchie to come up and talk to them.

We went to lunch afterward, and I remarked to Dennis that easily half the code I was writing in Multics was error recovery code. He said, "We left all that stuff out. If there's an error, we have this routine called panic(), and when it is called, the machine crashes, and you holler down the hall, 'Hey, reboot it.'"

(Unix and Multics)







cat(1) is a program that exists to catenate files; to "join" one file at its end to another at its start.

cat(1) was introduced in UNIX's first edition to succeed pr(1), which prints the contents of a single file to the screen. Most use of cat(1) is similar; it's often introduced to beginners as a means to print the contents of a file to the screen, which is why many implementations include options that modify output to make it easier to read on a display. POSIX requires only -u to be implemented, which guarantees output is unbuffered - on some systems output is buffered in 512-byte blocks, which is also the default of dd(1), though most current implementations (busybox, GNU coreutils) don't buffer output regardless. Various implementations include -s to strip duplicate blank lines (cat "$@" | sed '/^\s*$/d' would also work), -n to number lines (to which Pike and Kernighan offered awk '{ print NR "\t" $0 }' "$@" as a replacement) and -b to number non-blank lines (both cases for which nl(1) was later made), and -v to mark invisible characters.

Additions to man(1) are controversial; Rob Pike and Brian Kernighan explain this in Program Design in the UNIX Environment, the paper that accompanied Rob Pike's presentation UNIX Style, or cat -v Considered Harmful at the 1983 USENIX Summer Conference.

The following shell script is a POSIX-compliant implementation of cat(1):

set -e


# usage with 0 arguments - print standard input to standard output
if test -z "$1"; then
	dd 2>/dev/null
	exit $?

while test -n "$1"; do
	# Parse options

	if test -z "$DONT_PARSE_ARGS"
		then case "$1" in
			shift; continue; ;;
			DD="dd bs=1"
			shift; continue; ;;
			$DD </dev/stdin 2>/dev/null
			shift; continue; ;;

	# Print input to output.
	$DD <"$1" 2>/dev/null


exit 0


Don't use echo(1), use printf(1). printf(1) simulates the printf(3) function in the C standard I/O library which has no significant variations, whereas the functionality of echo(1) can vary between vendors.

printf "%s" "$*" does not work as echo(1) though it's been said to do so (including by this page).

The following is an implementation of echo(1) in the C programming language, using the standard library.

#include <stdio.h>
int main(int argc, char *argv[]) {
	int i;
	for(i = 1; ; ) {
		if(i >= argc)
		printf("%s", argv[i]);
		if(i == argc)
			putchar(' ');
	return 0;

The following is an implementation of echo(1) in shell.

while :; do
	if test -z "$1"
		then break
	printf "%s" "$1"
	if test -z "$1"; then
		printf "\n"
		printf " "


I'm pretty sure some later UNIX-based OSes doubled the ed(1) buffers, there's pretty much no downside to doing so in the modern era but it should be very easy to do yourself if it hasn't already been done (just double some of the array sizes in the beginning of ed.c).


/* vi: set sw=4 ts=4: */
 * Copyright (c) 2002 by David I. Bell
 * Permission is granted to use, distribute, or modify this source,
 * provided that this copyright notice remains intact.
 * The "ed" built-in command (much simplified)
//config:config ED
//config:	bool "ed (21 kb)"
//config:	default y
//config:	help
//config:	The original 1970s Unix text editor, from the days of teletypes.
//config:	Small, simple, evil. Part of SUSv3. If youre not already using
//config:	this, you dont need it.
(editors/ed.c, as of 2021-12-29)

busybox ed(1) exists as part of busybox as an afterthought; if on an embedded system, see if #posix#vi(1) has been included in the busybox configuration, which is much closer to traditional implementations of itself.


Pretty good in use, but if you're using plan9port consider checking out sam(1), a much more powerful line editor.




make(1) in modern times is fragmented into the GNU version gmake and the BSD version bmake. Complex Makefiles may not be useable in both. Usually Linux systems have GNU Make as make and BSD Make as bmake, and BSD systems to have BSD Make as make and GNU Make as gmake; the native Make is simply make and the external Make gets a name designating its source.



We stole a shell out of a MULTICS, the concept of a shell. We stole per process execution. You know create a process -execute the command. From a combination of the two, although, neither of them really did it, MULTICS wanted to do it. But, it was so expensive creating a process that it ended up creating a few processes and then using them and putting them back on the shelf, then picking them up and reinitializing them. So, they never really created a process for command because it was just too expensive. The ION direction and the stuff like that and later in fact streams came from um the IO switch, that we worked on in MULTICS. Having everything work the same and just directing, you know, changing what it really pointed to.

(Interview with Ken Thompson, 9-6-89)


On /linux/#alpine, the dash-binsh package configures DASH as the system's /bin/sh.


true(1) is a tool that only quits silently with an exit status of 0. Similarly, false(1) is a tool that only quits silently with an exit status of 1. Recognizing arguments, printing to standard output, reading from standard input, or otherwise exiting with any other status of 0, is a violation of the POSIX specification for true(1). These utilities find use in shell scripting, which, though extremely relevant to these utilities, is beyond the scope of this article.

Because true(1)'s required functionality is so simple a POSIX-compliant implementation is a one-liner in most languages, so long as you're willing to make an exception in your code styling. For example, in C:

int main(void) { return 0; }

Because executing an empty shellscript file will in most shells do nothing and return an exit status of 0, technically an empty shellscript file is a POSIX-compliant true(1) implementation in 0 bytes. This was the true(1) implementation on early versions of UNIX, including Research UNIX, System V, and Sun's Solaris, according to both Rob Pike and John Chambers. A more explicit implementation also exists in POSIX shell:

exit 0

This happens to be nearly identical in source to the implementation used by NetBSD.

Python has the same 0 byte true(1) implementation feature as most shells. Here's false(1) in Python rather than true(1) to demonstrate how exiting with an arbitrary exit status can be done:

import sys

In some shells, true(1) is a shell built-in command, so running true will run the shell author's implementation of true(1) rather than the system implementation.

GNU true(1), from the GNU coreutils, is well known for being a maximalist implementation - it's eighty lines long and directly includes four C header files. Their true.c is 2.3 kilobytes and parses the arguments --help and --version (only if either are the first argument to the program). The GNU coreutils implementation of true(1) is not POSIX compliant.


Unlike busybox's ed(1) implementation, its vi(1) is very useable. vim(1) is a popular re-implementation of vi(1).


Advanced Configuration and Power Interface

The Advanced Configuration and Power Interface, or ACPI, is the interface through which the operating system and client programs can control features in your computer's firmware. Usually this is used with an ACPI client or opaquely controlled by the operating environment.

On Linux, see #Linux#ACPI. On NetBSD, see acpi(4).





For compilation, tcc(1), gcc(1), and clang(1) are all reasonable choices depending on your needs.

On Alpine Linux, the standard library headers are in the musl-dev package.

Many Linux software distributions' system package managers have meta-packages that pull all necessities for C development as dependencies. Alpine has build-base and Debian has build-essential.

For linking to libraries, see #pkg-config.


The C programming language was first described to the public in The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie, published by Prentice Hall in 1978. The language evolved out of the former B programming language, which was a product of Ken Thompson:

Challenged by McIlroy's feat in reproducing TMG, Thompson decided that Unix—possibly it had not even been named yet—needed a system programming language. After a rapidly scuttled attempt at Fortran, he created instead a language of his own, which he called B. B can be thought of as C without types; more accurately, it is BCPL squeezed into 8K bytes of memory and filtered through Thompson's brain. Its name most probably represents a contraction of BCPL, though an alternate theory holds that it derives from Bon [Thompson 69], an unrelated language created by Thompson during the Multics days. Bon in turn was named either after his wife Bonnie, or (according to an encyclopedia quotation in its manual), after a religion whose rituals involve the murmuring of magic formulas.

(The Development of the C Language)

[Thompson 69] references K. Thompson, "Bon—an Interactive Language," undated AT&T Bell Laboratories internal memorandum (ca. 1969). This is possibly Bon User's Manual but it's not conclusive. Please get in touch if you have a hyperlink for this document as I can't find it indexed on any search engines.

This language described in The C Programming Language isn't the C programming language known by most. It was a pre-standardization, relatively prototypical C, and rather than being codified in ANSI its primary documentation was the book by Kernighan and Ritchie (this book would later be known colloquially as K&R). This was known as "pre-ANSI C" or "K&R C" and dubbed "C78" for the purposes of naming this page, in the same style as the later "C89", described in ANSI X3.159-1989, or "C11", described in ISO/IEC 9899:2011. "C78" was also the name given to historical C by the c78(7) manual page on FreeBSD 9.0.

8 and 9 as valid octal digits

		00, 01, 02, 03, 04, 05, 06, 07, 08, 09

The GNU C compiler emits the following errors (this omits warnings) for the preceding piece of code:

snippet.c:4:49: error: invalid digit "8" in octal constant
    4 |                 00, 01, 02, 03, 04, 05, 06, 07, 08, 09
      |                                                 ^~
snippet.c:4:53: error: invalid digit "9" in octal constant
    4 |                 00, 01, 02, 03, 04, 05, 06, 07, 08, 09
      |                                                     ^~

This is because in C (both pre-standardization and post-ANSI) integer constants with leading zeroes are parsed as octal (base 8) numbers. In pre-ANSI C, 8 and 9 were valid octal digits corresponding to 010(b8) and 011(b8). This is documented in The C Programming Language, Appendix A, subsection 2.4.1, and evidenced by the preceding code block. The following is output of the compiled program in UNIX V6 on an emulated PDP-11:


This behavior exists within /usr/source/c/c0t.s, which is a PDP-11 assembler file that parses integer constants (as far as I can tell). This file provides getnum, a function used in /usr/source/c/c00.c. My theory is that this behavior is a side-effect of a very efficient but imperfect method of parsing integer constants from a file stream.

This wouldn't be a significant or even noticeable error; most programmers wouldn't use 8 or 9 as octal digits anyway. If not for its documentation within The C Programming Language it might have totally faded into obscurity. This is also mentioned in The C Programming Language, 2nd ed. in Appendix C.


In 1987, Richard M. Stallman, then a former MIT hacker who was working full time on the GNU Project, a re-implementation of the Unix operating system, released the first beta release of GCC, then the GNU C Compiler and later re-named the GNU Compiler Collection.









doas(1) is a systems administration tool that performs a command as a different user. doas(1) is configured in doas.conf(5).

For a pretty typical configuration, where users in the wheel group are meant to be administrating the system, the set-up session usually looks something like this:

$ su
# ed /etc/doas.conf
/etc/doas.conf: No such file or directory
permit :wheel

doas.conf(5) is located in $PREFIX/etc/doas.conf, except on Alpine Linux, where it's located in $PREFIX/etc/doas.d/doas.conf.



Emacs ("editor macros") is a text editor with a very powerful Lisp interpreter included.


nano(1) is a text editor that's usually recommended for beginners because of its lack of edit modes and its similar controls to popular editors from outside of UNIX.


ne(1) is similar to nano(1) but has a different featureset.


Also see #x#fonts.

Century Schoolbook

Comic Mono


As of 2021-04, Noto has fonts for 54% of Unicode.

On /linux/#alpine, all Noto family fonts match the glob font-noto-*. In #pkgsrc, all Noto family fonts match the glob fonts/noto-*.


Pango is a font rendering library.

Pango is packaged for /linux/#alpine as pango-dev.

Vendor Fonts


Unscii is packaged as fonts/unscii on #pkgsrc.


jiskan is a family of fonts comprising jiskan16 and jiskan24.



postmarketOS requires that the localmount OpenRC service be enabled for the system to read fstab(5).

Arch and Artix have fstab generators at genfstab(8) and fstabgen(8) respectively in their installation scripts.


See /linux/.



envstat(1) can show the current battery status.

Mounting filesystems

  1. Connect the drive with the filesystem you want to access.
  2. Use dmesg(8) to determine the location in /dev/ of the disk.
  3. disklabel(8) the drive to determine which partition on the disk you want to access (disklabel /dev/disk)
  4. mount(8) the filesystem.
  5. umount(8) the filesystem when done using it.


Install filesystems/fuse and filesystems/fuse-ext2. disklabel(8) will list ext4 filesystems as of type "Linux Ext2". Use fuse-ext2(1) to mount the filesystem.

fuse-ext2(1) is spotty in places and may not work correctly.


Install filesystems/fuse and filesystems/fuse-exfat. Use mount.exfat to mount the filesystem (the manual page for which is mount.exfat-fuse(8)).

Fix SSL certificate problem: unable to get local issuer certificate

Install security/mozilla-rootcerts-openssl.

Do not use SSL workarounds like (in the case of git) GIT_SSL_NO_VERIFY. These leave your system open to man-in-the-middle attacks.


If using Mullvad, you have to change the shebang on update-resolv-conf(8) (a standalone Bash script included in the OpenVPN configurations from Mullvad, intended to be placed in /etc/openvpn/) from #!/bin/bash to #!/usr/pkg/bin/bash if using Bash from pkgsrc or another appropriate location if using a different package manager.


System logging

See syslogd(8) and syslog.conf(5), which pertain to system logging.

Setting DDB_ONPANIC (see options(4) and sysctl(8)) will save a crash dump at /var/crash on kernel panic.



One of UNIX's innovations was its inclusion of a detailed, useful manual accessible on-system, accessible via man(1).

Alpine by default uses mandoc.


Task management


htop(1) is a featureful alternative to top(1).


Busybox and NetBSD provide implementations of top(1), an interactive in-terminal task manager.

PCI Utilities

Available as sysutils/pciutils from pkgsrc. Supplies lspci(8), setpci(8), and update-pciids(8).

update-pciids(8) is not part of the pciutils package in Alpine Linux repositories.

NetBSD includes pcictl(8) which offers similar functionality. pcictl pci0 list outputs roughly the same information as lspci(8), though lspci(8) may offer slightly more detailed information.


pkg-config is the querying interface to the pc(5) file format, which stores metadata relating to the file locations of key files for a language compiler or interpreter. Its purpose is to facilitate library linking, particularly for C and C++, without knowledge of where exactly a library's files are stored, which can vary dramatically between system and package manager.

Another implementation of pkg-config, pkgconf(1), is the default on #netbsd. pkgconf(1) comes with pkg.m4(7), macros for GNU autoconf.



Secure SHell


SSH keys are typically stored in $HOME/.ssh.

Typically, the public key's filename will be suffixed with .pub, while the private key will not.

You can generate an SSH key with ssh-keygen(1). Currently the preferred implementation is openssh-keygen, part of the OpenSSH suite.

Microsoft GitHub documentation suggests a user create a key with ssh-keygen -t ed25519 -C "[e-mail address]". This generates an Ed25519 SSH key with an e-mail address in the key comment.



wvkbd (Wayland Virtual Keyboard) is a software keyboard implementation for environments without a physical keyboard, such as a smartphone or tablet. #x#sxmo uses wvkbd by default in its variant for Wayland.

wvkbd depends on #x#cairo, #fonts#pango, the Wayland client libraries, and xkb-common.

warning: implicit declaration of function zwp_virtual_keyboard_*

Due to how the Makefile and #posix#make(1) work, if compilation is attempted before wayland-scanner is installed, an empty proto/virtual-keyboard-unstable-v1-client-protocol.h will be generated. The preprocessor won't error for lack of the file but because the file will be empty the necessary prototypes and constants will be missing and compilation will fail.

make clean should fix this.



wpa_supplicant(1) is usually good enough for establishing WiFi connections.

Here's an example configuration for a simple WPA-2 PSK access point.

	ssid="My SSID"
	psk="My password"

See wpa_supplicant.conf(5).

Partitions and filesystems

Don't use partitioners included with OS media where the same job can be done by GParted (which has live media available) or another good general-purpose partitioner. BSDs and Plan 9 are exceptions to this rule due to their exotic partitioning systems. Using utilities from a shell or TUIs does not make you "cooler" than someone who needs a GUI for partitioning; in some cases, messing up partitioning can have serious consequences, so it's always nice to have some idiot-proofing. I always partition my disks with the GParted live media.

You should do your own research on how you should partition your disks. I personally use separate partitions for /boot, /home, /, and swap. Your needs will vary.

Please note that a separate boot partition is mandatory if you intend to boot via (U)EFI. Check out the linked pages in the "See also" section.

Use mkfs(8) for creating filesystems and mount(8) for mounting partitions' filesystems.


Available as sysutils/gpart in pkgsrc.

gpart(8) is a tool that scans a file (or block device presented as a file) for drive partitions regardless of any table present on the medium.


e2fsprogs is needed for the dm_mod kernel module used for LUKS partition decryption.

To format a partition to a LUKS volume, determine the physical block device location for that partition and run cryptsetup luksFormat [partition]. The passphrase used can be changed or removed after creation.

To open a LUKS volume, use cryptsetup luksOpen [partition] [name]. This name is the name the decrypted block device location will take in /dev/mapper/.

Before the decrypted block device has a filesystem it'll just be cleared space - format as normal but use the decrypted block device location.

To mount a partition in an opened LUKS volume, use mount(8) as normal, just with the decrypted block device location.

To close an open LUKS volume, umount(8) any mapped and mounted partitions from the volume and cryptsetup luksClose [name].

To make the LUKS partition openable via keyfile, first make a keyfile (dd if=/dev/urandom of=/root/keyfile bs=1024 count=4 seems to work), and optionally make it readable by root only (chmod 0400 [keyfile]). Then add the keyfile to the partition's LUKS header with cryptsetup luksAddKey [physical partition block device] [keyfile].


dm-crypt is a service that automatically mounts LUKS volumes at boot.

On most OpenRC-initialized distributions, the cryptsetup-openrc package provides dmcrypt. Make sure that service is added to runlevel boot.

Configuration is in /etc/conf.d/dmcrypt and further configuration should be done in fstab. dm-crypt will need the UUID of the physical block device while fstab (if being configured with UUIDs will need the UUID of the decrypted block device in the device mapper).



X is a graphical windowing system that can be used on /linux/, FreeBSD, OpenBSD, #netbsd, and some proprietary operating systems as well. X is not the only windowing system; twin(1) exists for windowed multitasking within a framebuffer and Wayland is another windowing system intended to replace X.


Anki is the de facto standard flashcards studying programming given its popularity and lack of competition. Anki uses spaced repetition to make sure the user remembers what they study for the long term.

ModuleNotFoundError: No module named aqt

The module aqt isn't findable in the environment variable PYTHONPATH. Check each directory in the pattern $PREFIX/lib/python*/site-packages for the directory aqt/, and if it's there, try setting PYTHONPATH to that corresponding site-packages directory.

This bug exists on postmarketOS 22.12 (aarch64, based on Alpine Linux 3.17; anki-2.1.49-r2); the PYTHONPATH fix works as PYTHONPATH=/usr/lib/python3.11/site-packages/ anki.


cairo is a graphics rendering library, originally for X but later made cross-platform.

cairo is available on /linux/#alpine as cairo-dev.



Both jiskan16 and jiskan24 are included in Xorg, in the source tree at font/jis-misc but usually packaged separately (font-jis-misc on /linux/#alpine).


The (formerly Mozilla) Thunderbird mail suite is a popular though maximal choice. Claws Mail is a nice mail reader with a somewhat similar interface to Thunderbird but, in my experience, easier to use.


mpv(1) and vlc(1) are good options.


The de-facto standard X server is NetBSD uses as the default system X server.

/linux/#arch's package repositories have xorg, xorg-apps, and xorg-drivers package groups. #pkgsrc has meta-pkgs/modular-xorg.

Failed to open /dev/input/event[number] (Permission denied)

You need to be a part of the input group to use

Failed to open /dev/tty[number] (Permission denied)

You need to be a part of the video group to use

Managing Clients

It's possible to make X exec(3) a window manager at the end of initialization to ease the creation, deletion, and manipulation of windows. Contrary to what is now popular belief, window managers are not necessary (thought they're extremely convenient compared to the lack of them).



Add an app

Copy /usr/share/sxmo/default_hooks/ to "$XDG_CONFIG_HOME"/sxmo/hooks/ and edit the script.


TOR Browser

TOR Browser is available through pkgsrc at security/tor-browser.


startx(1) is usually included with xinit(1).

On /linux/#alpine, xinit(1) is provided by xinit. On /linux/#arch, xinit(1) is provided by xorg-xinit.