Next: , Previous: , Up: GNU troff Reference   [Contents][Index]


5.34 Host System Service Access

Occasionally a document wants to access the system clock, file storage, or other services provided by the operating environment.

Register: \n[$$]

Process identifier (PID) of the GNU troff program in its operating environment.

Date- and time-related registers are set per the local time as determined by localtime(3) when the formatter launches. This initialization can be influenced by the environment variable TZ or overridden by SOURCE_DATE_EPOCH; see Environment.

\n[seconds]

Count of seconds elapsed in the minute (0–60).

\n[minutes]

Count of minutes elapsed in the hour (0–59).

\n[hours]

Count of hours elapsed since midnight (0–23).

\n[dw]

Day of the week (1–7; 1 is Sunday).

\n[dy]

Day of the month (1–31).

\n[mo]

Month of the year (1–12).

\n[year]

Gregorian year.

\n[yr]

Gregorian year minus 1900. This register is incorrectly documented in the AT&T troff manual as storing the last two digits of the current year. That claim stopped being true in 2000. Old troff input that looks like:

'\" The year number is a surprise after 1999.
This document was formatted in 19\n(yr.

can be corrected to:

This document was formatted in \n[year].

or, for portability across many roff programs, to the following.

.nr y4 1900+\n(yr
This document was formatted in \n(y4.

If you wish to embed the date and/or time of a document’s formatting into its output, interpolate these registers into its text. Use the af request to format their values for output.

.af year 0000
.af mo 00
.af dy 00
.af hours 00
.af minutes 00
.af seconds 00
ISO 8601 date stamp:
\n[year]-\n[mo]-\n[dy]T\n[hours]:\n[minutes]:\n[seconds]
    ⇒ ISO 8601 date stamp: 2025-12-07T02:17:54

roff formatters allow files to be read into the input stream. Enabling GNU troff’s unsafe mode at the command line permits the writing of files and execution of external commands, with or without inclusion of their output in the document.

Caution: The requests discussed below that accept a file name or system command as an argument treat the remainder of the input line as that argument, including any spaces, up to a newline or comment escape sequence. Suffixing the file name or command with a comment, even an empty one, prevents unwanted space from creeping into it during source document maintenance. GNU troff removes a leading neutral double quote ‘"’ from such an argument, permitting initial embedded spaces in it, and reads it to the end of the input line in copy mode. Recall Copy Mode.

Request: .so ["]file
Request: .soquiet ["]file

Replace the request’s control line with the contents of file, “sourcing” it. GNU troff searches for file in any directories specified by -I command-line options, followed by the current working directory. If file does not exist, the formatter ignores the request.176

so can be useful for large documents, allowing each chapter of a book, for example, to be maintained in a separate file. However, files interpolated with so are not preprocessed; to overcome this limitation, see gsoelim(1).

Caution: Since the formatter replaces the entire control line with the contents of a file, file must end with a newline, or the formatter will continue reading the next input line of the roff file as if it were part of the last line of the sourced file. Consider a file xxx containing only the word ‘foo’ without a trailing newline.

$ printf 'foo' > xxx
$ groff -T ascii <<EOF
The situation is
.so xxx
bar.
EOF
    ⇒ The situation is foobar.

soquiet works the same way, except that GNU troff issues no warning diagnostic if file does not exist.

Request: .pso ["]command

Read the standard output from the specified command when passed to popen(3) and include it in place of the pso request.

It is an error to use this request in safer mode, which is the default. Invoke GNU troff or a front end with the -U option to enable unsafe mode.

The cautionary note regarding a final newline in the stream read by the so request applies to pso as well.

Request: .mso ["]file
Request: .msoquiet ["]file

As the so and soquiet requests, respectively, except that GNU troff searches for the specified file in the same directories as macro files; recall GROFF_TMAC_PATH in Environment and -m in Groff Options.

Request: .trf ["]file
Request: .cf ["]file

Break and copy the contents of file as “throughput” to GNU troff’s output. Each line of file is output as if preceded by \!, but is not interpreted by the formatter. If file does not end with a newline, trf appends one. Both requests break the line before reading file, unless invoked with the no-break control character. If a diversion is in use, GNU troff performs the copy only when the diversion is emitted.

cf copies the contents of file completely unprocessed; it is therefore an error to use this request in safer mode, which is the default. Invoke GNU troff or a front end with the -U option to enable unsafe mode.

trf discards invalid input characters; recall Input Format.

For cf, within a diversion, “completely unprocessed” means that each line of a file to be inserted is handled as if it were preceded by \!\\!.

Caution: Use of these requests can put syntactically invalid content into the formatter’s output, which groff’s output drivers then fail to process. One application is to pass instructions to a postprocessor that interprets file’s contents and filters it out before sending it to the output driver.

To define a macro x containing the contents of file f, use

.ev 1
.di x
.trf f
.di
.ev

The calls to ev prevent the partially collected output line from becoming part of the diversion; recall Diversions.

In AT&T troff, cf copies the contents of file to the output immediately even if a diversion is active; this behavior is so anomalous that it must be considered a bug.

Request: .nx [["]file]

Stop processing the input file. If file is specified, read it; otherwise, read the next pending input file, if any.

Request: .rd [prompt [arg1 arg2 …]]

Read from standard input, and include what is read as though it were part of the input file. Text is read until a blank line is encountered.

If standard input is a TTY input device (keyboard), write prompt to standard error, followed by a colon (or send BEL for a beep if no argument is given).

Arguments after prompt are available for the input. For example, the line

.rd data foo bar

with the input ‘This is \$2. prints

This is bar.

Using the nx and rd requests, it is easy to set up form letters. The form letter template is constructed like this, putting the following lines into a file called repeat.let:

.ce
\*(td
.sp 2
.nf
.rd
.sp
.rd
.fi
Body of letter.
.bp
.nx repeat.let

When this is run, a file containing the following lines should be redirected in. Requests included in this file are executed as though they were part of the form letter. The last block of input is the ex request, which tells GNU troff to stop processing. If this were not there, troff would not know when to stop.

Trent A. Fisher
708 NW 19th Av., #202
Portland, OR  97209

Dear Trent,

Len Adollar
4315 Sierra Vista
San Diego, CA  92103

Dear Mr. Adollar,

.ex
Request: .pi ["]command

Use the formatter’s device-independent output as the input to the commands specified in pipe and emit their output to the standard output stream instead of the formatter’s usual output. The formatter reads the remainder of the input line into command and passes it to popen(3). The formatter does not capture output produced by the command(s).

Multiple pi requests construct a multi-stage pipeline in the same order as the formatter encounters the requests.

.pi foo
.pi bar

is the same as ‘.pi foo | bar.

pi must be invoked before GNU troff writes any nodes to its output.177 The formatter reports an error and ignores the request if pi is invoked “too late”. Roughly, this means you should set up your pi pipeline early in a document, before anything but register, string, and macro definitions (and/or sourcing of files that comprise these exclusively).

Use of this request in safer mode (GNU troff’s default) is erroneous. Invoke GNU troff or a front end with the -U option to enable unsafe mode.

Caution: Use of the pi request can put syntactically invalid content into the formatter’s output, which groff’s output drivers then fail to process. The pipeline you construct is responsible for maintaining the validity of the input to the output driver.

Request: .sy ["]command
Register: \n[systat]

Execute the specified shell command(s). The formatter reads the remainder of the input line into a buffer and passes it to system(3). The formatter does not capture the output produced by the command(s).

It is an error to use this request in safer mode; this is the default. Give GNU troff or a front end program the -U command-line option to enable unsafe mode.

The writable register systat contains the return value of the system(3) function executed by the most recent sy request.

Real-world (and non-malicious) applications of sy are esoteric; the request interpolates neither the standard output nor the standard error streams of command into the document—worse, AT&T troff afforded no means of verifying that command operated as expected. We therefore offer a silly example of its use, making a document refuse to format if the system user name running the formatter is ‘branden’.178

.ds user branden\"
.sy test "$(id -un)" = \*[user]
.if \n[systat]=0 .ab formatting refused for \*[user]
Hello, world!
Request: .open stream ["]file
Request: .opena stream ["]file

Open file for writing and associate a stream named ident with it, making it available for write requests.

The opena request is like open, but appends to file if it already exists instead of overwriting it.

It is an error to use these requests in safer mode; this is the default. Give GNU troff or a front end program the -U command-line option to enable unsafe mode.

The pstream request dumps the list of open streams to the standard error stream.179

Request: .write stream ["]contents
Request: .writec stream ["]contents

Write contents to stream, which must previously have been the subject of an open (or opena) request. GNU troff flushes the stream after writing to it.

The writec request is like write, but only write appends a newline to contents.

Request: .writem stream name

Write the contents of the macro or string name to stream, which must previously have been the subject of an open (or opena) request. GNU troff reads the contents of name in copy mode. That is, it ignores already formatted elements (nodes). Consequently, diversions must be unformatted with the asciify request before calling writem. Usually, this means a loss of information.

Request: .close stream

Close the specified stream; the stream is no longer an acceptable argument to the write request.

Here a simple macro to write an index entry.

.open idx test.idx
.
.de IX
.  write idx \\n[%] \\$*
..
.
.IX test entry
.
.close idx
Escape sequence: \Ve
Escape sequence: \V(ev
Escape sequence: \V[env]

Interpolate the contents of the system environment variable env (one-character name e, two-character name ev) as returned by getenv(3). \V is interpreted even in copy mode; recall Copy Mode.


Next: , Previous: , Up: GNU troff Reference   [Contents][Index]