I/O (The GNU Troff Manual)

### 5.33 I/O

`gtroff` has several requests for including files:

Request: `.so` file ¶
Request: `.soquiet` file ¶

  Replace the `so` request’s control line with the contents of the file named by the argument, “sourcing” it. file is sought in the directories specified by `-I` command-line option. If file does not exist, a warning in category ‘`file`’ is produced and the request has no further effect. See Warnings, for information about the enablement and suppression of warnings.

  `so` can be useful for large documents; e.g., allowing each chapter of a book to be kept in a separate file. However, files interpolated with `so` are not preprocessed; to overcome this limitation, see the gsoelim(1) man page.

  Since GNU `troff` replaces the entire control line with the contents of a file, it matters whether `file` is terminated with a newline or not. Assume that file `xxx` contains only the word ‘`foo`’ without a trailing newline.

      $ printf 'foo' > xxx

      The situation is
      .so xxx
      bar.
          ⇒ The situation is foobar.

  `soquiet` works the same way, except that no warning diagnostic is issued if file does not exist.

Request: `.pso` command ¶

  Read the standard output from the specified command 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 comment regarding a final newline for the `so` request is valid for `pso` also.

Request: `.mso` file ¶
Request: `.msoquiet` file ¶

  Identical to the `so` and `soquiet` requests, respectively, except that `gtroff` searches for the specified file in the same directories as macro files for the `-m` command-line option. If the file name to be included has the form `name.tmac` and it isn’t found, these requests try to include `tmac.name` and vice versa.

Request: `.trf` file ¶
Request: `.cf` file ¶

  Transparently output the contents of file. Each line is output as if it were preceded by `\!`; however, the lines are not subject to copy mode interpretation. If the file does not end with a newline, `trf` adds one. Both requests cause a break.

  When used in a diversion, these requests embed a node (see `gtroff` Internals) in it that, when reread, causes the contents of file to be transparently copied to the output. In AT&T `troff`, the contents of file are immediately copied to the output regardless of whether there is a current diversion; this behaviour is so anomalous that it must be considered a bug.

  While `cf` copies the contents of file completely unprocessed, `trf` disallows characters such as NUL that are not valid `gtroff` input characters (see Identifiers).

  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 `\!\\!`.

  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).

Request: `.nx` [file] ¶

  Force `gtroff` to continue processing of the file specified as an argument. If no argument is given, immediately jump to the end of file.

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` pipe ¶

  Pipe the output of `gtroff` to the shell command(s) specified by pipe. This request must occur before `gtroff` has a chance to print anything.

  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.

  Multiple calls to `pi` are allowed, acting as a chain. For example,

      .pi foo
      .pi bar
      ...

  is the same as ‘`.pi foo | bar`’.

  The intermediate output format of GNU `troff` is piped to the specified commands. Consequently, calling `groff` without the `-Z` option normally causes a fatal error.

Request: `.sy` cmds ¶
Register: `\n[systat]` ¶

  Execute the shell command(s) specified by cmds. The output is not saved anywhere, so it is up to the user to do so.

  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 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

  The writable register `systat` contains the return value of the `system()` function executed by the last `sy` request.

Request: `.open` stream file ¶
Request: `.opena` stream file ¶

  Open the specified file for writing and associates the specified stream with it.

  The `opena` request is like `open`, but if the file exists, append to it instead of truncating 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.

Request: `.write` stream data ¶
Request: `.writec` stream data ¶

  Write to the file associated with the specified stream. The stream must previously have been the subject of an open request. The remainder of the line is interpreted as the `ds` request reads its second argument: an initial neutral double quote in contents is stripped to allow embedding of leading spaces, and it is read in copy mode.

  The `writec` request is like `write`, but only `write` appends a newline to the data.

Request: `.writem` stream xx ¶

  Write the contents of the macro or string xx to the file associated with the specified stream.

  xx is read in copy mode, i.e., already formatted elements are ignored. 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: `\V`e`` ¶
Escape sequence: `\V(`ev`` ¶
Escape sequence: `\V[`env`]` ¶

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