From 262ecfed9f7e39811f34517d82e848b8ec20f863 Mon Sep 17 00:00:00 2001 From: rsc Date: Wed, 31 Aug 2005 02:18:29 +0000 Subject: Initial lp. --- src/cmd/lp/lpdaemon.c | 457 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 src/cmd/lp/lpdaemon.c (limited to 'src/cmd/lp/lpdaemon.c') diff --git a/src/cmd/lp/lpdaemon.c b/src/cmd/lp/lpdaemon.c new file mode 100644 index 00000000..10b0aa3d --- /dev/null +++ b/src/cmd/lp/lpdaemon.c @@ -0,0 +1,457 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ctime +#undef wait + +/* for Plan 9 */ +#ifdef PLAN9 +#define LP "/bin/lp" +#define TMPDIR "/var/tmp" +#define LPDAEMONLOG unsharp("#9/lp/log/lpdaemonl") +#endif +/* for Tenth Edition systems */ +#ifdef V10 +#define LP "/usr/bin/lp" +#define TMPDIR "/tmp" +#define LPDAEMONLOG "/tmp/lpdaemonl" +#endif +/* for System V or BSD systems */ +#if defined(SYSV) || defined(BSD) +#define LP "/v/bin/lp" +#define TMPDIR "/tmp" +#define LPDAEMONLOG "/tmp/lpdaemonl" +#endif + +#define ARGSIZ 4096 +#define NAMELEN 30 + +unsigned char argvstr[ARGSIZ]; /* arguments after parsing */ +unsigned char *argvals[ARGSIZ/2+1]; /* pointers to arguments after parsing */ +int ascnt = 0, argcnt = 0; /* number of arguments parsed */ +/* for 'stuff' gleened from lpr cntrl file */ +struct jobinfo { + char user[NAMELEN+1]; + char host[NAMELEN+1]; +} *getjobinfo(); + +#define MIN(a,b) ((a 0; bsize -= rv) { + alarm(60); + if((rv=read(0, jobbuf, MIN(bsize,RDSIZE))) < 0) { + error("error reading input, %d unread\n", bsize); + exit(4); + } else if (rv == 0) { + error("connection closed prematurely\n"); + exit(4); + } else if((write(outfd, jobbuf, rv)) != rv) { + error("error writing temp file, %d unread\n", bsize); + exit(5); + } + } + dbgstate = 3; + alarm(60); + if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) { + alarm(60); + ACK(); + dbgstate = 4; + alarm(0); + return(outfd); + } + alarm(0); + error("received bad status <%d> from sender\n", *jobbuf); + error("rv=%d\n", rv); + NAK(); + return(-1); +} + +/* reads a line from the input into lnbuf + * if there is no error, it returns + * the number of characters in the buffer + * if there is an error and there where characters + * read, it returns the negative value of the + * number of characters read + * if there is an error and no characters were read, + * it returns the negative value of 1 greater than + * the size of the line buffer + */ +int +readline(int inpfd) +{ + unsigned char *ap; + int i, rv; + + ap = lnbuf; + lnbuf[0] = '\0'; + i = 0; + alarm(60); + do { + rv = read(inpfd, ap, 1); + } while (rv==1 && ++i && *ap != '\n' && ap++ && (i < LNBFSZ - 2)); + alarm(0); + if (i != 0 && *ap != '\n') { + *++ap = '\n'; + i++; + } + *++ap = '\0'; + if (rv < 0) { + error("read error; lost connection\n"); + if (i==0) i = -(LNBFSZ+1); + else i = -i; + } + return(i); +} + +int +getfiles(void) +{ + unsigned char *ap; + int filecnt, bsize, rv; + + filecnt = 0; + /* get a line, hopefully containing a ctrl char, size, and name */ + for(;;) { + ap = lnbuf; + if ((rv=readline(0)) < 0) NAK(); + if (rv <= 0) { + return(filecnt); + } + switch(*ap++) { + case '\1': /* cleanup - data sent was bad (whatever that means) */ + break; + case '\2': /* read control file */ + bsize = atoi(ap); + cntrlfd = tempfile(); + if (readfile(cntrlfd, bsize) < 0) { + close(cntrlfd); + NAK(); + return(0); + } + break; + case '\3': /* read data file */ + bsize = atoi(ap); + datafd[filecnt] = tempfile(); + if (readfile(datafd[filecnt], bsize) < 0) { + close(datafd[filecnt]); + NAK(); + return(0); + } + filecnt++; + break; + default: + error("protocol error <%d>\n", *(ap-1)); + NAK(); + } + } + return(filecnt); +} + +struct jobinfo * +getjobinfo(int fd) +{ + unsigned char *ap; + int rv; + static struct jobinfo info; + + if (fd < 0) error("getjobinfo: bad file descriptor\n"); + if (lseek(fd, 0L, 0) < 0) { + error("error seeking in temp file\n"); + exit(7); + } + /* the following strings should be < NAMELEN or else they will not + * be null terminated. + */ + strncpy(info.user, "daemon", NAMELEN); + strncpy(info.host, "nowhere", NAMELEN); + /* there may be a space after the name and host. It will be filtered out + * by CPYFIELD. + */ + while ((rv=readline(fd)) > 0) { + ap = lnbuf; + ap[rv-1] = '\0'; /* remove newline from string */ + switch (*ap) { + case 'H': + if (ap[1] == '\0') + strncpy(info.host, "unknown", NAMELEN); + else + strncpy(info.host, (const char *)&ap[1], NAMELEN); + info.host[strlen(info.host)] = '\0'; + break; + case 'P': + if (ap[1] == '\0') + strncpy(info.user, "unknown", NAMELEN); + else + strncpy(info.user, (const char *)&ap[1], NAMELEN); + info.user[strlen(info.user)] = '\0'; + break; + } + } + return(&info); +} + +void +alarmhandler(int sig) { + signal(sig, alarmhandler); + error("alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]); +} + +void +main(int argc, char **argv) +{ + unsigned char *ap, *bp, *cp, *savbufpnt; + int i, blen, rv, saveflg, savargcnt; + struct jobinfo *jinfop; + + USED(argc); + USED(argv); + + signal(SIGHUP, SIG_IGN); + signal(SIGALRM, alarmhandler); + cp = argvstr; + /* setup argv[0] for exec */ + argvals[argcnt++] = cp; + for (bp = (unsigned char *)LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++); + *cp++ = '\0'; + /* get the first line sent and parse it as arguments for lp */ + if ((rv=readline(0)) < 0) + exit(1); + bp = lnbuf; + /* setup the remaining arguments */ + /* check for BSD style request */ + /* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */ + switch (*bp) { + case '\001': + case '\003': + case '\004': + bp++; /* drop the ctrl character from the input */ + argvals[argcnt++] = cp; + *cp++ = '-'; *cp++ = 'q'; *cp++ = '\0'; /* -q */ + argvals[argcnt++] = cp; + *cp++ = '-'; *cp++ = 'd'; /* -d */ + CPYFIELD(bp, cp); /* printer */ + *cp++ = '\0'; + break; + case '\002': + bp++; /* drop the ctrl character from the input */ + argvals[argcnt++] = cp; + *cp++ = '-'; *cp++ = 'd'; /* -d */ + CPYFIELD(bp, cp); /* printer */ + *cp++ = '\0'; + ACK(); + savargcnt = argcnt; + savbufpnt = cp; + while ((rv=getfiles())) { + jinfop = getjobinfo(cntrlfd); + close(cntrlfd); + argcnt = savargcnt; + cp = savbufpnt; + argvals[argcnt++] = cp; + *cp++ = '-'; *cp++ = 'M'; /* -M */ + bp = (unsigned char *)jinfop->host; + CPYFIELD(bp, cp); /* host name */ + *cp++ = '\0'; + argvals[argcnt++] = cp; + *cp++ = '-'; *cp++ = 'u'; /* -u */ + bp = (unsigned char *)jinfop->user; + CPYFIELD(bp, cp); /* user name */ + *cp++ = '\0'; + for(i=0;i