# To unbundle, run this file echo Install sed 's/.//' >Install <<'//GO.SYSIN DD Install' -# this version is intended for use with the Second Edition CDROM -# (the public distribition) -# unpack the shell archive, then run this script -# it assumes you've got the Postscript software in /sys/lib/postscript -for(a in kill stat spooler) { - cp /sys/lib/lp/$a/generic bsdlp.$a - {cat $a.diffs; echo 'w'} | ed - bsdlp.$a -} -for(a in kill stat spooler) - mv bsdlp.$a /sys/lib/lp/$a/bsdlp && chmod a+rx /sys/lib/lp/$a/bsdlp -mk installall -if(! test -d /sys/lib/lp/bsdjob) - mkdir /sys/lib/lp/bsdjob && chmod 777 /sys/lib/lp/bsdjob -# then look at sample.devices for examples of what to put in /sys/lib/lp/devices //GO.SYSIN DD Install echo kill.diffs sed 's/.//' >kill.diffs <<'//GO.SYSIN DD kill.diffs' -21c -case *; lpbsd rm $DEST_HOST $LPDEST $KILLARGS -. //GO.SYSIN DD kill.diffs echo spooler.diffs sed 's/.//' >spooler.diffs <<'//GO.SYSIN DD spooler.diffs' -36,42c - rv=$status - if(status=$rv) - lpbsd -H$LPMACHID -P$LPUSERID send $DEST_HOST $LPDEST $tmpf - rv=$status - ENDTIME=`{date} - if (status=$rv) echo $LPMACHID' '$LPUSERID' '0' + 'unknown' '$STARTIME(4)' '$ENDTIME(4) >> $LPLOG - if not echo $LPMACHID' '$LPUSERID' '0' - 'unknown' '$STARTIME(4)' '$ENDTIME(4) >> $LPLOG -. -22,34c - STARTIME=`{date} - switch ($j) { - case ''; @{bind -b $LPLIB/process /bin; $LPPROC} | aux/download -f -H/sys/lib/postscript/font -mfontmap -plw+ >$tmpf - case *; @{bind -b $LPLIB/process /bin; $LPPROC} <$j | aux/download -f -H/sys/lib/postscript/font -mfontmap -plw+ >$tmpf -. -19a - tmpf=/tmp/lp$pid - fn sigexit {rm -f $tmpf} -. -5,10d //GO.SYSIN DD spooler.diffs echo stat.diffs sed 's/.//' >stat.diffs <<'//GO.SYSIN DD stat.diffs' -25c - lpbsd stat $DEST_HOST $LPDEST -. //GO.SYSIN DD stat.diffs echo mkfile sed 's/.//' >mkfile <<'//GO.SYSIN DD mkfile' -sample.devices <<'//GO.SYSIN DD sample.devices' -#device_name loc dest_host phys_dev_name speed class def_proc spooler stat kill daemon sched -imagen X/D014 SoftEng - - post300+duplex+nohead generic bsdlp bsdlp bsdlp - FIFO -hp7 X/D104 Dcpu1 - - post300+duplex+nohead generic bsdlp bsdlp bsdlp - FIFO //GO.SYSIN DD sample.devices echo lpbsd.c sed 's/.//' >lpbsd.c <<'//GO.SYSIN DD lpbsd.c' -/* - * rfc1179 network printing protocol - * bugs to forsyth@plan9.cs.york.ac.uk - */ - -#include -#include - -typedef struct Printop Printop; -struct Printop { - char *name; - void (*act)(char*, char**); -}; - -#define TIMEOUT (240*1000) /* msec */ - -static int dfd; -static char *remote; -static char cmd[1024], *cmdp = cmd; -static char ctl[4096], *ctlp = ctl; - -static int filetype = 'o'; /* default is PostScript */ -static char *opts[128]; /* arguments for option letters */ -static int nobanner = 0; - -static void appcmd(char*, ...); -static void appctl(char*, ...); -static void sendcmd(void); -static int timeout(void*, char*); -static void prod(char*, char**); -static void qstat(char*, char**); -static void send(char*, char**); -static void rm(char*, char**); - -static Printop ops[] = { - {"stat", qstat}, - {"prod", prod}, - {"send", send}, - {"rm", rm}, - {0}, -}; - -void -main(int argc, char **argv) -{ - int i; - char *p; - - ARGBEGIN{ - case 'h': /* no header */ - nobanner = 1; - break; - case 'C': /* class for banner page */ - case 'H': /* host name */ - case 'I': /* indent */ - case 'J': /* job name */ - case 'L': /* banner page */ - case 'M': /* send mail to user when done */ - case 'N': /* name of source file */ - case 'P': /* user name */ - case 'T': /* title for pr */ - case 'W': /* width of output */ - opts[_argc] = ARGF(); - break; - case 't': /* file type; most of these are obsolete */ - if((p = ARGF()) != 0) - switch(*p) { - case 'c': /* CIF */ - case 'd': /* DVI */ - case 'f': /* `formatted' file */ - case 'g': /* old Unix plot format */ - case 'k': /* reserved for kerberos */ - case 'l': /* print leaving control characters */ - case 'n': /* ditroff */ - case 'o': /* PostScript */ - case 'p': /* pr format */ - case 'r': /* Fortran carriage control */ - case 't': /* ancient C/A/T troff */ - case 'v': /* Sun raster file */ - case 'z': /* reserved for Palladium */ - filetype = *p; - break; - } - break; - }ARGEND - atnotify(timeout, 1); - if(argc < 3) { - fprint(2, "Usage: lpbsd [-t type] [-h] [-M user] [-W width] [-[CHIJLNPT] arg] op dialstring queue [arg ...]\n"); - exits("usage"); - } - for(i=0; ops[i].name; i++) - if(strcmp(ops[i].name, *argv) == 0) { - remote = argv[1]; - dfd = dial(netmkaddr(remote, 0, "printer"), 0, 0, 0); - if(dfd < 0) { - fprint(2, "lpbsd: can't dial %s (printer): %r\n", remote); - exits("dial"); - } - (*ops[i].act)(argv[2], argv+3); - exits(0); - } - fprint(2, "lpbsd: unknown op: %s\n", *argv); - exits("usage"); -} - -static int -Read(int fd, void *buf, unsigned nb, int required) -{ - int nr; - - alarm(TIMEOUT); - nr = read(fd, buf, nb); - if(nr < 0) { - fprint(2, "lpbsd: lost connection to %s: %r\n", remote); - exits("Retry lost link"); - } - if(required && nb == 0) { - fprint(2, "lpbsd: lost connection to %s\n", remote); - exits("Retry lost link"); - } - alarm(0); - return nr; -} - -static void -Write(int fd, void *buf, unsigned nb) -{ - int nw; - - alarm(TIMEOUT); - nw = write(fd, buf, nb); - if(nw < 0) { - fprint(2, "lpbsd: error writing to %s: %r\n", remote); - exits("Retry lost link"); - } - if(nb != nw) { - fprint(2, "lpbsd: failed to write to %s\n", remote); - exits("Retry remote write"); - } - alarm(0); -} - -static void -appcmd(char *fmt, ...) -{ - cmdp = doprint(cmdp, cmd+sizeof(cmd), fmt, &fmt+1); -} - -static void -sendcmd(void) -{ - Write(dfd, cmd, cmdp-cmd); - cmdp = cmd; -} - -static void -appctl(char *fmt, ...) -{ - ctlp = doprint(ctlp, ctl+sizeof(ctl), fmt, &fmt+1); -} - -static void -printreply(void) -{ - char buf[4096]; - int nb; - - while((nb = Read(dfd, buf, sizeof(buf), 0)) > 0) - write(1, buf, nb); -} - -static int -nak(void) -{ - uchar c; - - return Read(dfd, &c, 1, 1) == 1? c: -1; -} - -static void -mustack(char *what) -{ - int i; - - i = nak(); - if(i == 2) { - fprint(2, "lpbsd: remote host %s rejected %s: no space\n", remote, what); - exits("Retry no space"); - } else if(i) { - fprint(2, "lpbsd: remote host %s rejected %s\n", remote, what); - exits("rejected"); - } -} - -static void -prod(char *queue, char **av) -{ - USED(av); - appcmd("\1%s\n", queue); - sendcmd(); - mustack("start printing"); - /* not clear if ack/nak should be expected */ -} - -static void -qstat(char *queue, char **av) -{ - USED(av); - appcmd("\3%s", queue); - for(; *av; av++) - appcmd(" %s", *av); - appcmd("\n"); - sendcmd(); - printreply(); -} - -static void -rm(char *queue, char **av) -{ - if(*av == 0) - exits(0); - appcmd("\5%s %s", queue, getuser()); - for(; *av; av++) - appcmd(" %s", *av); - appcmd("\n"); - sendcmd(); - /* not clear if ack/nak should be expected */ - mustack("remove request"); -} - -static int -jobno(char *host) -{ - char name[100], buf[10]; - int fd; - long n; - - snprint(name, sizeof(name), "/sys/lib/lp/bsdjob/%s", host); - fd = open(name, ORDWR); - if(fd < 0) { - fd = create(name, ORDWR, CHEXCL|0666); - if(fd < 0) { - fprint(2, "lpbsd: can't create %s: %r\n", name); - exits("no job file"); - } - } - n = read(fd, buf, sizeof(buf)-1); - if(n > 0) { - buf[n] = 0; - n = strtoul(buf, 0, 10); - } else - n = 0; - snprint(buf, sizeof(buf), "%3d\n", (n+1)%1000); - seek(fd, 0, 0); - if(write(fd, buf, 4) != 4) { - fprint(2, "lpbsd: can't update %s: %r\n", name); - exits("bad job file"); - } - close(fd); - return n; -} - -static void -send(char *queue, char **av) -{ - char *myname; - Dir dir; - int fd, n; - char buf[8192]; - long nb, job; - - if(*av == 0) { - fprint(2, "lpbsd: missing data file name\n"); - exits("usage"); - } - myname = getenv("sysname"); - if(myname == 0) - myname = "kremvax"; - appcmd("\2%s\n", queue); - sendcmd(); - if(nak()) { - fprint(2, "lpbsd: %s refused print request for %s in %s queue\n", remote, *av, queue); - exits("refused"); - } - - job = jobno(myname); - - /* - * start control file - */ - appctl("H%s\n", myname); - if(nobanner) - opts['L'] = 0; - else if(opts['L'] == 0) - opts['L'] = getuser(); - if(opts['P'] == 0) - opts['P'] = getuser(); - appctl("P%s\n", opts['P']); - opts['P'] = 0; - for(n = 'A'; n <= 'Z'; n++) - if(opts[n]) - appctl("%c%s\n", n, opts[n]); - - /* - * send data file - */ - fd = open(*av, OREAD); - if(fd < 0) { - fprint(2, "lpbsd: can't open %s: %r\n", *av); - exits("cannot open"); - } - if(dirfstat(fd, &dir) < 0) { - fprint(2, "lpbsd: can't stat %s: %r\n", *av); - exits("bad file"); - } - appctl("%cdfA%.3d%s\n", filetype, job, myname); - appctl("UdfA%.3d%s\n", job, myname); - appcmd("\3%ld dfA%.3d%s\n", dir.length, job, myname); - sendcmd(); - mustack("data file command"); - for(; dir.length != 0; dir.length -= nb) { - nb = read(fd, buf, sizeof(buf)); - if(nb < 0) { - fprint(2, "lpbsd: error reading %s: %r\n", *av); - exits("i/o error"); - } - if(nb == 0) { - fprint(2, "lpbsd: unexpected end-of-file on %s\n", *av); - exits("eof"); - } - Write(dfd, buf, nb); - } - Write(dfd, "", 1); /* strange rfc1179 convention */ - mustack("data file's contents"); - - /* - * send control file - */ - appcmd("\2%ld cfA%.3d%s\n", (long)(ctlp-ctl), job, myname); - sendcmd(); - mustack("control file command"); - *ctlp++ = 0; /* strange rfc1179 convention */ - Write(dfd, ctl, ctlp-ctl); - mustack("control file's contents"); -} - -static int -timeout(void *a, char *why) -{ - USED(a); - return strcmp(why, "alarm") == 0; -} //GO.SYSIN DD lpbsd.c