In my work on be able to use RunCPM as a Github Action (because it transparently maps the underlying file system to CP/M disks) I found that the emulated command processor supported the standard CP/M '$$$.SUB' facility on the A drive and this could be used to inject commands even if the emulator did not support this from the command line, so I had a closer look.
'A0:$$$.SUB' is what the SUBMIT.COM command generates given an input batch file.
The format is simple: The list of commands is reversed, and converted to a set of 128-byte records. Each record contains first a byte stating the length of the command, the actual command and a trailing zero (not counted) plus padding up to 128 characters. The command processor then at each command prompt takes the last record, truncates the file to be one record shorter, and executes the command. If an error occurs the file is deleted.
I wrote this unoptimized Perl-snippet which may be useful:
perl -e 'print join("\n", reverse @ARGV)' "$@" | perl -ne 's/[\r\n]//g; printf "%-128s", chr(length($_)).$_.chr(0)' > 'A/0/$$$.SUB'
This mechanism was probably chosen for being short and simple in a period where every byte counted.
If you can inject such a file onto the disk or disk image that the emulator considers A:, it should be executed when the emulator starts.
$$$.SUB
exists. If so, it reads the last 128 bytes of the file into its line buffer, shrinks the file by 128 bytes (deleting it if the size would become zero), and executes the contents of the line buffer. If the first 128 bytes of$$$.SUB
contained a command that would$$$.SUB
, then unless the system lost power between the time that program was launched and the time it was able to rewrite the file, the system would on power-up process whatever the next action in$$$.SUB
would be.