Is the decision to put all termios manipulation in a single SRFI correct?
I think so, at least for now.
Are there any modern needs for exposed stty(1) functionality besides serial-line manipulation for communication with other systems? (This SRFI does not propose to support retrocomputing with real serial-line terminals.)
No.
Exactly which stty(1) arguments are needed for modern serial-line use, such as with embedded computing?
Here's my best shot at what should be settable (disallows 110 baud and non-8-bit characters):
from c_iflag: IGNBRK (ignore breaks), BRKINT (signal interrupt / throw error on break), PARMRK (prefix parity/framing errors with #xFF #x00, and change #xFF to #xFF #xFF), INPCK (enable parity check), ISTRIP (strip parity bit), IXON (^S/^Q on output), IXOFF (^S/^Q on input).
from c_oflag: none
baud rates for input and output: all
from c_cflag: CREAD (enable reader), PARENB (enable parity), PARODD (odd parity), HUPCL (hang up modem lines on close), CLOCAL (ignore modem status).
from c_lflag: none
I think there is no need for blocks here: it's set and forget.
with-cooked-mode exists to "shell out" from a program that's already executing the thunk handed to with-rare-mode or with-raw-mode. Does it need arguments in addition to the standard triplet of input, output, and error ports to do this safely and securely?
Terminal settings belong to the device, not the port/fd, so it suffices to open "/dev/tty". Therefore no port arguments are needed for these procedures, unless you want to support them on terminals other than the controlling terminal, which I doubt. Even in that case, one port would suffice.
Is there any way to enforce, rather than prescribe, safe use of with-cooked-mode? If so, should that be done for the good of users?
Not sure what "safe" means.
What are the best recommended stty(1) settings for with-cooked-mode?
All of the three original procedures should, I think, work the same way. On entry to the block, the termios structure is read and a copy saved in a local variable. Then the relevant bits are changed in the original and the struct is written back. After the block runs, the copy is written back. This guarantees that on block exit the settings at block entry are restored exactly.
The bits to clear for raw and rare modes are well-documented. The question then is which bits to set for cooked mode. We shouldn't just blindly set all the ones that were cleared. So the answer is that when we enter a raw or rare block for the first time, we read the current termios structure and save it in a global place. That becomes the basis of cooked-mode, on the (safe) assumption that a terminal application always starts up in cooked mode.
So in cooked mode, instead of "the relevant bits are changed and the struct is written back", it should be "the global cooked mode struct is written to the terminal".