usage: qscanq-stdin [PROG] [ARG] ...
qscanq-stdin is invoked by qscanq. It ensures that the message on stdin is seekable, extracts its MIME components to the current directory, and runs the virus scanner on them.
Like qscanq and qmail-queue, qscanq-stdin needs no arguments. If arguments are supplied, they are used as the command to run instead of qmail-queue. In this way, further qmail-queue wrappers--such as spam filters--can be chained with qscanq.
qscanq-stdin expects an email message on file descriptor 1, its envelope on file descriptor 0, and writes nothing to descriptor 2. It returns an exit code which is interpreted by the caller (usually qmail-smtpd or qmail-inject).
The first thing qscanq-stdin does is to copy stdin to a file in the current directory using a unique filename. It then closes and reopens the file read-only on file descriptor 0, and unlinks the file. This presents the same interface to downstream programs while ensuring that the file is seekable, read-only, and not directly accessible to other programs.
After making stdin seekable, qscanq-stdin may create a second copy of the message in a file also named "msg". Some viruses are only detected by looking at the raw message, so they need a copy in the working folder. This step is enabled and disabled by the setting in conf-scan-stdin.
Once stdin is seekable, qscanq-stdin runs the command specified in conf-ripmime to extract the MIME components of stdin into files in the current directory. RipMIME is run with descriptors 1 and 2 closed, so it can't read the message envelope or print any output. If RipMIME fails, qscanq-stdin returns temporary error code 71, resulting in message deferral. After RipMIME exits, stdin is rewound to the start of the file. This step is disabled by setting conf-ripmime to "/bin/true", which is now the default.
After RipMIME completes, qscanq-stdin runs the scanner selected at compile time to scan the message for viruses. File descriptors 1 and 2 are closed before running the scanner. If it can't be run, or crashes, then qscanq-stdin returns code 71, causing the message to be deferred. If run-antivir returns code 2, indicating that a virus has been found, then run-antivir returns error code 31, permanently rejecting the message.
If the virus scanner returns success, then qscanq-stdin will run the command supplied on its command line, or if none is supplied will run qmail-queue. It also requests cleanup of its working directory by calling run-cleanq
Upon startup, qscanq-stdin sets an alarm for the time specified in conf-ageout (default: 1 hour). When the alarm fires, qscanq-stdin sends SIGKILL to RipMIME or to the virus scanner, whichever may be running, and exits with code 71 (or code 54 if ripmime is killed). Once qmail-queue has started, it sets its own alarm, independent of qscanq's alarm (default: 1 day). qscanq will wait forever if need be, so its longest runtime is equal to conf-ageout plus the timeout used by qmail-queue.
Environment Variables
qscanq-stdin sets no environment variables. It does pass its environment to qmail-queue (or PROG, if supplied instead). This means that any qmail-queue wrapper must be able to handle its environment safely.
If the DEBUG environment variable is set to any value whatsoever, then qscanq-stdin will print diagnostic messages to stderr whenever an error occurs. This is for use in debugging a new configuration, and should never be used to capture "extra log information" during runtime. If DEBUG is set for qscanq, then qscanq will set DEBUG=1 when calling qscanq-stdin.
It should be stressed that the value of DEBUG is ignored. Setting DEBUG to "1", "TRUE", "yes", etc., will turn on debug messages. Setting it to "0", "FALSE", "no", "N", etc., will also turn on debug messages. If you don't want debug messages, don't set DEBUG at all.
Return Codes
In addition to the return codes from qmail-queue, qscanq-stdin returns 53 (write error) if it can't create a seekable copy of stdin, and 54 (read error) if it can't reopen that file in read-only mode or if RipMIME fails. If run-antivir or qmail-queue fails, it returns code 71 (temporary rejection). If run-antivir returns exit code 2, then qscanq-stdin returns 31 (permanent rejection).
