![]() |
Home
| Calendar
| Mail Lists
| List Archives
| Desktop SIG
| Hardware Hacking SIG
Wiki | Flickr | PicasaWeb | Video | Maps & Directions | Installfests | Keysignings Linux Cafe | Meeting Notes | Linux Links | Bling | About BLU |
I use this filter for the HP4000, equipped with a duplex unit. It senses the file type (text, Postscript, PCL), and sends the commands appropriate the modes. I compile two editions, one for normal use, and one with -DDUPLEX to turn on the duplexer, and then use a flag to use the filter that turns the duplexer on. The printcap entry on our Sparc 5 is: lz0|lps0|corridor_hp: \ :lp=/dev/bpp0:sh:ff=/f:sd=/var/spool/lz0:ms=-opost,crtscts:pl#60:mx#0\ :lf=/var/spool/lz0/errs:\ :if=/usr/local/bin/hplaser:df=/usr/local/bin/hplaser2sides: so lpr -Plz0 -d <filename> will be printed with the duplexer on. There's also a compile time mode that will invoke another filter 'hpps' that uses Ghostscript to generate PCL code for non-Postscript printers. It has only one line in it: /usr/local/bin/gs -q -dNOPAUSE -sDEVICE=laserjet -sOutputFile=- - Referencing it as a separate command allows changes, e.g., device driver, without re-compilation. -------------- next part -------------- /* @(#)hplaser.c 1.9 4/14/99 Taste the file to determine file type: PCL, text, Postscript. For text files, expand tabs and put a CR before each LF. For reasons unknown, executing 'write' with 0 bytes will hang the Aurora parallel port - avoid it... */ #include <stdio.h> #include <signal.h> #include <errno.h> enum FILETYPE { text, PCL, Postscript }; static enum FILETYPE mode; static int psDup_off; static int gs_pid; void duplex_off(void) { #ifdef DUPLEX char cmd[80]; if (mode == Postscript) { if (!psDup_off) { strcpy(cmd, "<< /Duplex false >> setpagedevice\n"); write(1, cmd, strlen(cmd)); psDup_off = 1; } } else write(1, "\033&l0S", 5); /* duplex off */ #endif } /* when 'lprm' is executed, clean up the job before terminating. */ void sigint(int s) { #ifdef GHOSTSCRIPT /* If postscript, we've started a subprocess to run gs which may have gone away when a job is removed - just exit in this case, so we don't hang on the write. */ if (mode == Postscript) { if (gs_pid) kill(gs_pid, SIGINT); exit(0); } #else duplex_off(); write(1, "\033E", 2); /* reset */ #endif exit(0); } void gs_sig(int s) { int n; wait(&n); /* pick up gs subprocess exit status */ if ((n & 0xff) != 0) exit(-1); else exit((n >> 8) & 0xff); } int main(int ac, char **av) { int nbytes, col, i, nb, n, sd[2]; char buff[307], *p, *s, *eob; char cmd[80]; signal(SIGINT, sigint); /* Get some characters, and determine its type */ nbytes = read(0, buff, sizeof(buff)); p = s = buff; if ((nbytes > 0) && (buff[0] == '\033')) { mode = PCL; write(1, "\033E", 2); /* Scan for initial \033E reset sequence at beginning of buffer. This can turn off other modes (e.g., duplex) if sent later.. */ if (buff[1] == 'E') s = &buff[2]; } else if ((nbytes >= 10) && !strncmp(buff, "%!PS-Adobe", 10)) { mode = Postscript; } else { mode = text; /* Check for first character ^L; omit since we're already at top of form. */ if (*p == '\f') { p++; s = p; } write(1, "\033E", 2); #ifdef LAND132 strcpy(cmd, "\033&l2A\033(s13H\033&l1O"); write(1, cmd, strlen(cmd)); #endif } #ifdef GHOSTSCRIPT if (mode == Postscript) { /* fork subprocess, make pipe, run 'hpps' script */ pipe(sd); if (!(gs_pid = fork())) { /* subprocess */ close(sd[1]); dup2(sd[0], 0); /* pick up stdin */ if (execl("/usr/local/bin/hpps", "hpps", 0) < 0) perror("can't exec /usr/local/bin/hpps"); exit(0); } else { dup2(sd[1], 1); /* pick up stdout */ /* we want to be notified of abnormal terminations, so we can quit.... */ signal(SIGCHLD, gs_sig); } } #endif #ifdef DUPLEX if (mode == Postscript) { /* Scan to end of first line; insert duplex command */ eob = &buff[nbytes]; while (p < eob) { if (*p == '\n') { p++; write(1, buff, p - buff); s = p; strcpy(cmd, "<< /Duplex true >> setpagedevice\n"); write(1, cmd, strlen(cmd)); break; } else p++; } } else { write(1, "\033&l1S", 5); /* duplex, long edge binding */ } #endif col = 0; do { if (mode == text) { /* expand tabs and add CR to LF */ for (eob = &buff[nbytes]; p < eob; i++, p++) { switch (*p) { /* Line feeds expand to CR LF */ case '\n': n = p - s; if (n > 0) write(1, s, n); write(1, "\r\n", 2); s = p + 1; col = 0; continue; case '\r': col = 0; break; /* Tabs expand by 8 012345678901234567890 x x */ case '\t': n = p - s; if (n > 0) write(1, s, n); nb = 8 - (col % 8); write(1, " ", nb); col += nb; s = p + 1; continue; default: col++; break; } } #ifdef DUPLEX } else if (mode == Postscript) { /* Scan for %%EOF; put in end of duplex if found. Note that if not found, p will equal &buff[nbytes], and entire buffer will be written out, below. */ eob = &buff[nbytes]; for (p=buff; p<eob; p++) { if (*p == '%') { /* Check for enough chars to compare; get more if need more */ if (eob - p < 5) { n = p - s; if (n > 0) write(1, s, n); nbytes = eob - p; memcpy(s, p, nbytes); n = read(0, &buff[nbytes], sizeof(buff)-nbytes); if (n < 0) break; nbytes += n; eob = &buff[nbytes]; p = buff; } if (eob - p >= 5 && !strncmp(p, "%%EOF", 5)) { n = p - s; if (n) write(1, s, n); duplex_off(); s = p; p = eob; break; } } } #endif } else { /* PCL and non-Duplex Postscript modes are just pass thru */ p = &buff[nbytes]; } /* Flush buffer */ n = p - s; if (n > 0) write(1, s, n); nbytes = read(0, buff, sizeof(buff)); p = s = buff; } while (nbytes > 0); duplex_off(); if (mode != Postscript) write(1, "\033E", 2); #ifdef GHOSTSCRIPT close(sd[1]); close(1); if (mode == Postscript) { /* wait for Ghostscript subprocess to terminate */ signal(SIGCHLD, SIG_DFL); wait(&n); if ((n & 0xff) != 0) return -1; else return (n >> 8) & 0xff; } else { return 0; } #else close(1); return 0; #endif }
![]() |
|
BLU is a member of BostonUserGroups | |
We also thank MIT for the use of their facilities. |