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/lpsend.c | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 341 insertions(+) create mode 100644 src/cmd/lp/lpsend.c (limited to 'src/cmd/lp/lpsend.c') diff --git a/src/cmd/lp/lpsend.c b/src/cmd/lp/lpsend.c new file mode 100644 index 00000000..4893f452 --- /dev/null +++ b/src/cmd/lp/lpsend.c @@ -0,0 +1,341 @@ +#ifdef plan9 + +#include +#include +#define stderr 2 + +#define RDNETIMEOUT 60000 +#define WRNETIMEOUT 60000 + +#else + +/* not for plan 9 */ +#include +#include +#include +#include +#include + +#define create creat +#define seek lseek +#define fprint fprintf +#define sprint sprintf +#define exits exit + +#define ORDWR O_RDWR +#define OTRUNC O_TRUNC +#define ORCLOSE 0 + +#define RDNETIMEOUT 60 +#define WRNETIMEOUT 60 + +#endif + +#define MIN(a,b) ((a 0; bcnt -= rv) { + alarm(WRNETIMEOUT); /* to break hanging */ + if((rv=read(inpfd, jobbuf, MIN(bcnt,RDSIZE))) < 0) { + error(0, "read error during pass, %d remaining\n", bcnt); + break; + } else if((write(outfd, jobbuf, rv)) != rv) { + error(0, "write error during pass, %d remaining\n", bcnt); + break; + } + } + alarm(0); + return(bcnt); +} + +/* get whatever stdin has and put it into the temporary file. + * return the file size. + */ +int +prereadfile(int inpfd) +{ + int rv, bsize; + + bsize = 0; + do { + if((rv=read(0, jobbuf, RDSIZE))<0) { + error(0, "read error while making temp file\n"); + exits("read error while making temp file"); + } else if((write(inpfd, jobbuf, rv)) != rv) { + error(0, "write error while making temp file\n"); + exits("write error while making temp file"); + } + bsize += rv; + } while (rv!=0); + return(bsize); +} + +int +tempfile(void) +{ + static int tindx = 0; + char tmpf[20]; + int tmpfd; + + sprint(tmpf, "/var/tmp/lp%d.%d", getpid(), tindx++); + if((tmpfd=create(tmpf, + +#ifdef plan9 + + ORDWR|OTRUNC, + +#endif + + 0666)) < 0) { + error(0, "cannot create temp file %s\n", tmpf); + exits("cannot create temp file"); + } + close(tmpfd); + if((tmpfd=open(tmpf, ORDWR + +#ifdef plan9 + + |ORCLOSE|OTRUNC + +#endif + + )) < 0) { + error(0, "cannot open temp file %s\n", tmpf); + exits("cannot open temp file"); + } + return(tmpfd); +} + +int +recvACK(int netfd) +{ + int rv; + + *jobbuf = '\0'; + alarm(RDNETIMEOUT); + if (read(netfd, jobbuf, 1)!=1 || *jobbuf!='\0') { + error(0, "failed to receive ACK, "); + if (*jobbuf == '\0') + error(1, "read failed\n"); + else + error(1, "received <0x%x> instead\n", *jobbuf); + rv = 0; + } else rv = 1; + alarm(0); + return(rv); +} + +void +main(int argc, char *argv[]) +{ + char *devdir; + int i, rv, netfd, bsize; + int datafd; + +#ifndef plan9 + + void (*oldhandler)(); + +#endif + + devdir = nil; + /* make connection */ + if (argc != 2) { + fprint(stderr, "usage: %s network!destination!service\n", argv[0]); + exits("incorrect number of arguments"); + } + + /* read options line from stdin into lnbuf */ + i = readline(0); + + /* read stdin into tempfile to get size */ + datafd = tempfile(); + bsize = prereadfile(datafd); + + /* network connection is opened after data is in to avoid timeout */ + if ((netfd=dial(argv[1], 0, 0, 0)) < 0) { + fprint(stderr, "dialing %s\n", devdir); + perror("dial"); + exits("can't dial"); + } + + /* write out the options we read above */ + if (write(netfd, lnbuf, i) != i) { + error(0, "write error while sending options\n"); + exits("write error while sending options"); + } + + /* send the size of the file to be sent */ + sprint(lnbuf, "%d\n", bsize); + i = strlen(lnbuf); + if ((rv=write(netfd, lnbuf, i)) != i) { + perror("write error while sending size"); + error(0, "write returned %d\n", rv); + exits("write error while sending size"); + } + + if (seek(datafd, 0L, 0) < 0) { + error(0, "error seeking temp file\n"); + exits("seek error"); + } + /* mirror performance in readfile() in lpdaemon */ + +#ifdef plan9 + + atnotify(alarmhandler, 1); + +#else + + oldhandler = signal(SIGALRM, alarmhandler); + +#endif + + dbgstate = 1; + if(!recvACK(netfd)) { + error(0, "failed to receive ACK before sending data\n"); + exits("recv ack1 failed"); + } + dbgstate = 2; + if ((i=pass(datafd, netfd, bsize)) != 0) { + NAK(netfd); + error(0, "failed to send %d bytes\n", i); + exits("send data failed"); + } + ACK(netfd); + dbgstate = 3; + if(!recvACK(netfd)) { + error(0, "failed to receive ACK after sending data\n"); + exits("recv ack2 failed"); + } + + /* get response, as from lp -q */ + dbgstate = 4; + while((rv=read(netfd, jobbuf, RDSIZE)) > 0) { + if((write(1, jobbuf, rv)) != rv) { + error(0, "write error while sending to stdout\n"); + exits("write error while sending to stdout"); + } + } + dbgstate = 5; + +#ifdef plan9 + + atnotify(alarmhandler, 0); + /* close down network connections and go away */ + exits(""); + +#else + + signal(SIGALRM, oldhandler); + exit(0); + +#endif + +} -- cgit v1.2.3