Path: utzoo!attcan!uunet!husc6!osf!dbrooks From: dbrooks@osf.OSF.ORG (David Brooks) Newsgroups: comp.lang.postscript Subject: Re: ^D embedded in PS files Message-ID: <1005@osf.OSF.ORG> Date: 26 May 89 19:33:17 GMT References: <864@adobe.UUCP> Reply-To: dbrooks@osf.org (David Brooks) Organization: Open Software Foundation Lines: 107 As the one who wrote the Prime PostScript despooler, my problem (once I had finished) was precisely with the non-standard nature of the implementation. I interpreted Appendix D of the Red Book, and the implementations on machines that came after the LaserWriter (QMS1200/2400, QMS800, Data Products LZRsomething) to mean: "This isn't actually the PostScript standard, but we're establishing it as a de facto expectation." This I took to mean things like the serverloop execution, ^D, ^C, ^T, most of statusdict, and so on. I kind of came to rely on these, although I was nervous because I knew Adobe didn't regard them as standard (and I didn't want to go playing with printer description files). Everything went well until... Bong! the DEC LNO3 standard password wasn't 6 digits, but a string whose initial value was LN03R. And, since the software read the password out of a (protected) environment file, and assumed it was only 6 characters long, and we now had to write (LN03R) (7 characters) to get the semantics right... you fill in the rest. We found a disgusting hack to work around it. You don't want to know. I'm not at Prime any more, and I did all this without benefit of prior art. In particular, what I'm about to describe may be familiar to users of other despoolers, or not. I worried particularly about races and timeouts. That's not easy to do on a timeshared computer without multi-event wait, and some of the code is gross. Also, I don't like "unattended" software that just goes quiet or dies without telling anyone how, especially if it's because of external misbehaving hardware. It does behave sensibly if it finds a ^D embedded in the file! In case anyone is interested, here's a summary of the less obvious features: 1. Establishing contact with the printer didn't assume a printer that was alive, or even one that was quiescent. First I hit it with ^T and looked for a properly formatted reply among potential junk that could be streaming back from yesterday's job. Then ^D (wait for ^D), and if no ^D returned, ^C, ^D again (wait for ^D). This covers a printer that's quiescent, or busy, or in interactive mode. 2. A hack like Apple used: check the printer for a flag and, if it's not there, download some standard dictionaries in separate jobs. This is repeated before each user job, in case the printer was turned off and on again. 3. Print the header page with "large" characters printed in dark gray (so they don't wash out) and 84-point -- except that if the line would get too long the point size is shrunk to fit (the printer itself does these calculations). 4. Read pagecount if possible (and parseable), and start the job, offering host-based text emulation for non-PostScript files. Field all returned messages. 5. If the returned message is %%[ Flushing..., drop the job (yes, it's possible for a program to fake that, but why bother?). 6. Do the ^D negotiation. (Send one, wait for one). As I said, we stripped out embedded ^Ds, but if we hadn't it would, I think, still be OK, except you might attach messages from this job onto the next job. 7. Print in text any uplinked data, as a separate job. That way the user sees error messages and anything else he cared to "print", on sheets after the job's proper output. Any messages that are clearly meant for the operator/administrator get put in a log file (who watches system consoles these days?). Get pagecount again. 8. During jobs, execute a timeout. How do you distinguish between a user who submits "{}loop" and one who submits <8Mb of data imaged> showpage? We judged that a printer that hasn't ^D-ed about 20 minutes after the last character sent is almost certainly wedged, so we ^C after 30 minutes it and do end-of-job. If no ^D is still sent back (after 15 seconds) we declare the printer seriously dead. 9. Exception to the above: If you get a %%[ PrinterError during the timeout, the clock must be halted until the printer is well again, as determined by a healthy response to ^T. The problem is caused by paper out on last sheet of job, probably. Care is needed not to get stuck if the printer decides to croak at this point. 10. General robustness was built in. For example, I've seen a QMS1200 return a %%[ status line with no trailing newline, so we won't hang waiting for a complete line. As I said, the problem with coding like this is relying on the nonstandard semantics, and for the most part Adobe has kept things standard (even if not always sensible...want to talk about suppressing bare CR characters?). I do rely on: ^C, ^D, ^T semantics, and the text returned by ^T; exitserver semantics including password; and for convenience sake the statusdict entries pagecount, printername, product, revision, jobname and username (it won't actually break if statusdict is absent). So, Adobe, the point of all this is to ask: are you ever going to change these expectations and make Prime unhappy (since I don't think they have anyone there who understands all this stuff)? -- David Brooks dbrooks@osf.org Open Software Foundation uunet!osf.org!dbrooks 11 Cambridge Center Personal views, not necessarily those Cambridge, MA 02142, USA of OSF, its sponsors or members.