Home / Alt manpages / pic(1)

  • pic(1)
  • User command
  • linux

Draw Reproducible Diagrams in roff with pic

By the end of this guide, you will have a small roff document containing a box, an arrow and a label, and you will be able to render it as terminal output with GNU pic and groff. The examples use GNU groff 1.23.0, supplied here by the groff-base package. Allow about 15 minutes if you are new to roff. No elevated privileges are needed.

What pic does

pic is a preprocessor. It copies ordinary input to standard output, but interprets a picture between .PS and .PE, .PF or .PY. The result is drawing language understood by troff, or TeX when you select TeX mode. In normal use, groff invokes pic for you with its -p option; calling pic directly is useful when you want to inspect or pipeline its output.

The gpic command is the GNU name for the same installed implementation on this system. The two commands report GNU pic (groff) version 1.23.0, and their installed manual pages are identical here.

1. Check the local version

Run this as your ordinary user:

$ pic --version
GNU pic (groff) version 1.23.0

Also check the available option summary if you are working on another machine:

$ pic --help
usage: pic [-CnSU] [file ...]
usage: pic -t [-cCSUz] [file ...]
usage: pic {-v | --version}
usage: pic --help

Do not assume that a different groff release has exactly the same extensions. This guide describes the GNU implementation documented by the local pic(1) and gpic(1) pages.

2. Write the smallest useful picture

Create a temporary input file in a directory you control. The file has roff requests outside the picture and pic objects inside it:

$ mkdir -p /tmp/pic-example
$ cat > /tmp/pic-example/diagram.roff <<'EOF'
.PS
box "input"
arrow
box "output"
.PE
EOF

The first box is placed at the current drawing position. arrow then joins the next object, so the second box follows it. The quoted strings become labels. The here-document is only creating disposable input under /tmp; it does not install anything or change system configuration.

3. Render it through groff

Use groff's -p option to run pic, -m pic to load simple centring macros, and the utf8 terminal device for a readable result:

$ groff -Tutf8 -mpic -p /tmp/pic-example/diagram.roff
┌─────────┐      ┌──────────┐
│ input   │ ───> │ output   │
└─────────┘      └──────────┘

The exact box width and terminal glyphs depend on the device and font, so treat the layout above as representative. A successful command prints the rendered picture and exits with status zero.

Checkpoint

If you see the literal .PS and box lines, pic was not run. Check that the command contains -p, and that the picture delimiters are spelled exactly as shown.

4. Inspect pic output when debugging

Run pic directly when you need to see what it passes to troff:

$ pic /tmp/pic-example/diagram.roff | sed -n '1,12p'
.do if !dPS .ds PS
.do if !dPE .ds PE
.do if !dPF .ds PF
.do if !dPY .ds PY
...

This output is intermediate roff, not a finished page. It is useful for confirming that a picture was recognised. For TeX-compatible output, add -t:

$ pic -t /tmp/pic-example/diagram.roff | sed -n '1,8p'
\expandafter\ifx\csname graph\endcsname\relax
   \csname newbox\expandafter\endcsname\csname graph\endcsname
...

TeX mode requires a driver that supports tpic version 2 specials. The generated picture is placed in a TeX box named graph by default, and the document must print that box itself. Do not send this output to a terminal and expect a diagram.

5. Keep untrusted input in safer mode

GNU pic recognises a sh command that can pass text to a shell. Safer mode, selected by -S, is enabled by default and ignores these commands. This is the correct default for roff files obtained from elsewhere:

$ printf '.PS\nsh "printf BAD >&2"\nbox\n.PE\n' | pic -S
$

The command produces no BAD output because the shell request is ignored. Never use -U merely to make a third-party document render. Unsafe mode interprets shell commands with the permissions of the user running pic. If you deliberately need a trusted build step that uses sh, review the complete input first, run it as an unprivileged account, and keep its output directory separate from important files.

Warning

-U is a security boundary, not a compatibility switch. The following harmless test shows the distinction, but do not replace the command text with input you have not audited:

$ printf '.PS\nsh "printf PIC_TEST >&2"\nbox\n.PE\n' | pic -U
PIC_TEST

Useful boundaries and common traps

  • -S and -U are opposites for shell commands. Safer mode is the default; unsafe mode permits execution.
  • -t selects TeX output. It is not needed for ordinary troff or terminal rendering.
  • -C makes pic recognise .PS, .PE, .PF and .PY even when followed by a character other than a space or newline. Use it only when an existing document needs that compatibility.
  • -n avoids GNU troff drawing extensions. Use it when a downstream postprocessor cannot accept those extensions; it also changes how dots are drawn in troff mode.
  • .PF and .PY leave the drawing position at the top of the picture, while .PE leaves it at the bottom. GNU pic supports .PY as a workaround for a macro-name collision with the mm package.

If the picture is not centred, check the surrounding macro setup. The pic program expects suitable definitions for the PS, PE and, where used, PF or PY macros. The groff -mpic option supplies simple definitions that centre each picture.

Done means

  • pic --version identifies the installed GNU groff version.
  • Your input has one complete picture between recognised delimiters.
  • groff -Tutf8 -mpic -p renders the diagram and exits successfully.
  • You know whether you need troff output or TeX output from -t.
  • Untrusted documents are processed with the default safer mode, and you have not enabled -U without auditing every shell-capable command.