Occasionally a document wants to access the file system
or other services provided by the operating environment.
GNU
troff permits the reading of files into the input stream.
Enabling 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.
.so ["]file ¶.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.143
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.
.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.
.mso ["]file ¶.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;
see
GROFF_TMAC_PATH
in
Environment
and
-m
in
Options.
.trf ["]file ¶.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 device.
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 (see 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.
.nx [["]file] ¶Stop processing the input file. If file is specified, read it; otherwise, read the next pending input file, if any.
.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
.pi ["]command ¶Use GNU troff’s device-independent output as the input to the
commands specified in pipe and emit their output to the standard
output stream instead of GNU troff’s usual output.
Since that output is in a page description
language,144 using this request without
specifying the -Z option to groff is likely to
provoke fatal errors from an output driver.
The formatter reads the remainder of the input line into command
and passes it to popen(3). Output produced by the
command(s) is not captured by GNU troff.
Multiple pi requests construct a multi-stage pipeline in the same
order as the formatter encounters the requests.
pi must be invoked before GNU troff writes any nodes
to its output.145 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.
.pi foo .pi bar
is the same as ‘.pi foo | bar’.
.sy ["]command ¶\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 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.
The following code fragment introduces the current time into a document.
.sy perl -e 'printf ".nr H %d\\n.nr M %d\\n.nr S %d\\n",\
(localtime(time))[2,1,0]' > /tmp/x\n[$$]
.so /tmp/x\n[$$]
.sy rm /tmp/x\n[$$]
\nH:\nM:\nS
This works by having the Perl script (run by sy) write
nr requests that set the registers H, M, and
S to a temporary file. The roff document then reads the
temporary file using the so request.
The registers seconds, minutes, and hours,
initialized at startup of GNU troff, should satisfy most
requirements. Use the af request to format their values for
output.
.af hours 00
.af minutes 00
.af seconds 00
\n[hours]:\n[minutes]:\n[seconds]
⇒ 02:17:54
.open stream ["]file ¶.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 if
file
already exists,
appends to it 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 option to
enable unsafe mode.
The pstream request dumps the list of open streams to the
standard error stream; see Debugging.
.write stream ["]contents ¶.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.
.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.
The contents of
name are read in copy mode. That is, already formatted elements
(nodes) are ignored. Consequently, diversions must be unformatted with
the asciify request before calling writem. Usually, this
means a loss of information.
.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