123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- #ifdef plan9
- #include <u.h>
- #include <libc.h>
- enum {
- stderr = 2,
- RDNETIMEOUT = 30*60*1000,
- WRNETIMEOUT = RDNETIMEOUT,
- };
- #else
- /* not for plan 9 */
- #include <stdio.h>
- #include <errno.h>
- #include <time.h>
- #include <fcntl.h>
- #include <signal.h>
- #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<b)?a:b)
- #define ACK(a) write(a, "", 1)
- #define NAK(a) write(a, "\001", 1)
- #define LPDAEMONLOG "/tmp/lpdaemonl"
- #define LNBFSZ 4096
- char lnbuf[LNBFSZ];
- int dbgstate = 0;
- char *dbgstrings[] = {
- "",
- "rcvack1",
- "send",
- "rcvack2",
- "response",
- "done"
- };
- #ifdef plan9
- void
- error(int level, char *s1, ...)
- {
- va_list ap;
- long thetime;
- char *chartime;
- char *args[8];
- int argno = 0;
- if (level == 0) {
- time(&thetime);
- chartime = ctime(thetime);
- fprint(stderr, "%.15s ", &(chartime[4]));
- }
- va_start(ap, s1);
- while(args[argno++] = va_arg(ap, char*))
- ;
- va_end(ap);
- fprint(stderr, s1, *args);
- }
- int
- alarmhandler(void *foo, char *note) {
- USED(foo);
- if(strcmp(note, "alarm")==0) {
- fprint(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
- return(1);
- } else return(0);
- }
- #else
- void
- error(int level, char *s1, ...)
- {
- time_t thetime;
- char *chartime;
- if (level == 0) {
- time(&thetime);
- chartime = ctime(&thetime);
- fprintf(stderr, "%.15s ", &(chartime[4]));
- }
- fprintf(stderr, s1, &s1 + 1);
- }
- void
- alarmhandler() {
- fprintf(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
- }
- #endif
- /* get a line from inpfd using nonbuffered input. The line is truncated if it is too
- * long for the buffer. The result is left in lnbuf and the number of characters
- * read in is returned.
- */
- int
- readline(int inpfd)
- {
- register char *ap;
- register int i;
- ap = lnbuf;
- i = 0;
- do {
- if (read(inpfd, ap, 1) != 1) {
- error(0, "read error in readline, fd=%d\n", inpfd);
- break;
- }
- } while ((++i < LNBFSZ - 2) && *ap++ != '\n');
- if (i == LNBFSZ - 2) {
- *ap = '\n';
- i++;
- }
- *ap = '\0';
- return(i);
- }
- #define RDSIZE 512
- char jobbuf[RDSIZE];
- int
- pass(int inpfd, int outfd, int bsize)
- {
- int rv, bcnt;
- for(bcnt=bsize; bcnt > 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 tindx = 0;
- char tmpf[20];
- int tmpfd;
- sprint(tmpf, "/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 <%#x> instead\n", (uchar)*jobbuf);
- rv = 0;
- } else rv = 1;
- alarm(0);
- return(rv);
- }
- void
- main(int argc, char *argv[])
- {
- int i, rv, netfd, bsize, datafd;
- #ifndef plan9
- void (*oldhandler)();
- #endif
- /* make connection */
- if (argc != 2) {
- fprint(stderr, "usage: %s network!destination!service\n",
- argv[0]);
- exits("usage");
- }
- /* 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 ");
- perror(argv[1]);
- 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 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 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
- }
|