SOS, PM, APC Start of String, Privacy Message, Application Program Command
Open a control string whose content the terminal itself does not act on.
SOS Start of String
ESC X Pt ST
- ECMA-48
- §8.3.128 SOS – Start of String, p. 66
- DEC STD 070
- §3.5.4.3 Character Strings, p. 3-29
- VT510
- 4.2 Control Characters
Three control strings carry content meant for someone other than the terminal. Each is closed by ST:
| Opener | 7-bit form | Carries |
|---|---|---|
| SOS, start of string | ESC X | a character string for an application to interpret |
| PM, privacy message | ESC ^ | a privacy message, under some privacy discipline |
| APC, application program command | ESC _ | commands for an application program |
PM is ECMA-48 §8.3.94, p. 53 and APC §8.3.2, p. 33. ECMA-48 lets an SOS string hold any characters but SOS and ST, where PM’s and APC’s, like DCS’s, may hold only printable characters and the format effectors BS to CR. DEC STD 070 reserves SOS for future use, and recommends a terminal treat it as “the start of an unimplemented control string” (§3.5.4.3, p. 3-29). The VT510 manual says that after PM or APC it “ignores all following characters until it receives a SUB, ST, or any other C1 control character”, but lists SOS itself as simply “Ignored”. libghostty-vt treats all three alike, as DEC STD 070 recommends.
None of them is displayed: a string the terminal does not act on is thrown away whole. CAN, SUB, ESC or a C1 control ends one early, as for any control string, so an ESC [ inside an SOS ends the string and starts a control sequence, though ECMA-48 would have it be part of the string.
Terminal emulators have since found uses for APC: kitty’s graphics protocol travels in ESC _ G … ST, and the proposed Glyph Protocol in ESC _ 25a1 ; … ST, both of which libghostty-vt reads. A terminal that does not know the protocol throws the same bytes away as an APC it does not implement.
All three are C1 controls, with single-byte forms 98, 9E and 9F that libghostty-vt, decoding its input as UTF-8, does not accept.
Support
| Terminal | Version | Support | Notes |
|---|---|---|---|
| VT220 | manual, 2nd ed., 1984 | No | not in §4.2 Control Characters, which says unlisted C1 controls are ignored |
| VT510 | manual, 1st ed., 1993 | Partly | Table 4–2: PM and APC strings are ignored to their end, but SOS itself is just “Ignored” |
| xterm | patch 412, xterm-411a | Yes | SOS, PM and APC strings are discarded |
| libghostty-vt | 0f171f6 | Yes | reads kitty graphics APC strings |
| kitty | 0.49.1, run in a VM | No | fails the 2 cases that show it working |
| foot | 1.28.0, run in a VM | Yes | passes the case that shows it working |
| pyte | 0.8.2, run as a library | No | fails the 2 cases that show it working |
| xterm.js headless | 6.0.0, run as a library | Yes | passes the 2 cases that show it working |
| alacritty_terminal | 0.26.0, run as a library | Yes | passes the 2 cases that show it working |
| ConEmu | build 230724, its documentation | No | not in ConEmu’s ANSI escape codes |
| rxvt-unicode | 9.31, run in a VM | No | fails the 2 cases that show it working |
| VTE | 0.84.1, run as a library | Yes | passes the 2 cases that show it working |
Validation
SOS-1: None is displayed
A
\eXstart of string\e\\
B
\e^privacy message\e\\
C
\e_application command\e\\
D
|ABCD__|
cursor 1,5
reply none
SOS-2: BEL does not end them
A
\e_hi\a # BEL is part of the string
B # and so is this
\e\\
C
|AC____|
bell 0
SOS-3: ESC ends one early
A
\eXa # an SOS
\e[2;2H # the ESC ends it, and this is a CUP
b
\e\\ # an ST with nothing to end
B
|A_____|
|_bB___|