gopherd

## Name

gopherd — UCSPI-TCP GOPHER server for static content

## Synopsis

`gopherd` {`root`}

## Description

gopherd prints requested public files from the `root` directory hierarchy. The Bernstein convention is for `root` to be `/public/file`, but it can use other conventional locations such as `/home/publicfile/public` or `/var/www`.

gopherd accepts requests on standard input in GOPHER and GOPHER+ formats. It supports three types of GOPHER+ request: "!" (information), "$" (directory), and "+" (view).

To each request it responds on standard output.

- For GOPHER and information ("!") GOPHER+ requests it just prints the response and exits. (Information responses are printed in GOPHER format. This avoids a bug in some GOPHER+ clients that cannot accept information responses in GOPHER+ format.)

- For directory ("$") and view ("+") GOPHER+ requests it permits multiple transactions over a single connection. It prints the response, in explicitly-length-counted format, and attempts to accept another request on standard input.

If gopherd does not like the request, it prints an error response and exits. If gopherd runs out of memory, encounters an I/O error, or does not receive an input packet within 60 seconds, it exits silently. gopherd also prints local log information on standard error.

Normally gopherd is run under a UCSPI-TCP server program (tcp-socket-accept, s6-tcpserver, or tcpserver spawning a server program per connection) to handle GOPHER connections from hosts around the Internet. It can also be run under a UCSPI-SSL server program.

### File handling

gopherd determines its local host name `v` as explained in the section on "gophermap"s. It uses this in conjunction with the selector provided in the request by the client.

### Note

The GOPHER protocol does not support virtual hosting as the GEMINI and HTTP protocols do.

A request for selector ``f`` not ending in a slash refers to the file named `./`v`/`f`` inside the `root` directory hierarchy.

- GOPHER and view ("+") GOPHER+ requests obtain the file contents as they stand. (Note that a direct request for selector ``f`/index.gopher` will thus retrieve the raw "gophermap".)

- Information ("!") GOPHER+ requests obtain the file metadata.

- Directory ("$") GOPHER+ requests are an error for this kind of selector and generate an error response.

A request for selector ``f`/` ending in a slash refers to the file named `./`v`/`f`/index.gopher` inside the `root` directory hierarchy. gopherd does not generate its own directory listings.

- GOPHER and view ("+") GOPHER+ requests obtain the file contents treated as a "gophermap". The "gophermap" is converted into a TAB-delimited multiple-record gopher menu.

- Information ("!") GOPHER+ requests obtain the file metadata. (The metadata of a directory's "gophermap" is thus seen as the directory's medatadata.)

- Directory ("$") GOPHER+ requests obtain the file contents treated as a "gophermap". The "gophermap" is converted into a series of information responses.

If the file does not exist or is unopenable, gopher prints an error response and exits.

### Gophermaps

A gophermap is a slightly modified form of an ordinary TAB-delimited GOPHER menu. The modifications aim to enable "gophermap"s to be position independent, and are twofold:

- The second field of every record may be zero-length or not begin with a slash, in which case gopherd prepends the selector `f` used to obtain the "gophermap" itself and a slash. This allows the selectors in the second field to be relative pathnames.

- The third and fourth fields of every record may be zero-length, in which case gopherd substitutes its own local host name and port number. The local host name and port number are taken from UCSPI-TCP or UCSPI-SSL environment variables, in particular the `PROTO`, `SSLLOCALHOST`/`TCPLOCALHOST`, `SSLLOCALIP`/`TCPLOCALIP`, and `SSLLOCALPORT`/`TCPLOCALPORT` environment variables. The fallback local host name in the event of none of this information being provided is `0`. The fallback local port number in the event of none of this information being provided is `70`.

### Unsupported features

gopherd does not support modification requests such as (non-zero-length) GOPHER+ request data.

gopherd does not have a search engine. It ignores information item selection in "!" and "$" GOPHER+ requests, and view selection in "+" GOPHER+ requests.

## Security

gopherd chroots to `root` when it starts. It then sets its group id and user id to the numbers given in environment variables `GID` and `UID`, as set by envuidgid (or equivalent). gopherd does not allow dots immediately after slashes in file names. It changes these dots to colons before attempting to open the file.

### Note

Earlier versions of gopherd required the `/etc/leapsecs.dat` to be copied under `root` . This file is now read before the chroot.

gopherd will refuse to read a file if the file

- is unreadable to user;

- is unreadable to group;

- is unreadable to world;

- is world-executable without being user-executable; or

- is anything other than a regular file: a directory, socket, device, etc.

## History

gopherd was added to the djbwares toolset in 2017.

## Author

Documentation by Jonathan de Boyne Pollard.