1 262ecfed 2005-08-31 devnull #ifdef plan9
3 262ecfed 2005-08-31 devnull #include <u.h>
4 262ecfed 2005-08-31 devnull #include <libc.h>
5 262ecfed 2005-08-31 devnull #define stderr 2
7 262ecfed 2005-08-31 devnull #define RDNETIMEOUT 60000
8 262ecfed 2005-08-31 devnull #define WRNETIMEOUT 60000
12 262ecfed 2005-08-31 devnull /* not for plan 9 */
13 262ecfed 2005-08-31 devnull #include <stdio.h>
14 262ecfed 2005-08-31 devnull #include <errno.h>
15 262ecfed 2005-08-31 devnull #include <time.h>
16 262ecfed 2005-08-31 devnull #include <fcntl.h>
17 262ecfed 2005-08-31 devnull #include <signal.h>
19 262ecfed 2005-08-31 devnull #define create creat
20 262ecfed 2005-08-31 devnull #define seek lseek
21 262ecfed 2005-08-31 devnull #define fprint fprintf
22 262ecfed 2005-08-31 devnull #define sprint sprintf
23 262ecfed 2005-08-31 devnull #define exits exit
25 262ecfed 2005-08-31 devnull #define ORDWR O_RDWR
26 262ecfed 2005-08-31 devnull #define OTRUNC O_TRUNC
27 262ecfed 2005-08-31 devnull #define ORCLOSE 0
29 262ecfed 2005-08-31 devnull #define RDNETIMEOUT 60
30 262ecfed 2005-08-31 devnull #define WRNETIMEOUT 60
34 262ecfed 2005-08-31 devnull #define MIN(a,b) ((a<b)?a:b)
36 262ecfed 2005-08-31 devnull #define ACK(a) write(a, "", 1)
37 262ecfed 2005-08-31 devnull #define NAK(a) write(a, "\001", 1)
39 262ecfed 2005-08-31 devnull #define LPDAEMONLOG "/tmp/lpdaemonl"
41 262ecfed 2005-08-31 devnull #define LNBFSZ 4096
42 262ecfed 2005-08-31 devnull char lnbuf[LNBFSZ];
43 262ecfed 2005-08-31 devnull int dbgstate = 0;
44 262ecfed 2005-08-31 devnull char *dbgstrings[] = {
46 262ecfed 2005-08-31 devnull "rcvack1",
48 262ecfed 2005-08-31 devnull "rcvack2",
49 262ecfed 2005-08-31 devnull "response",
53 262ecfed 2005-08-31 devnull #ifdef plan9
56 262ecfed 2005-08-31 devnull error(int level, char *s1, ...)
58 262ecfed 2005-08-31 devnull va_list ap;
59 262ecfed 2005-08-31 devnull long thetime;
60 262ecfed 2005-08-31 devnull char *chartime;
61 262ecfed 2005-08-31 devnull char *args[8];
62 262ecfed 2005-08-31 devnull int argno = 0;
64 262ecfed 2005-08-31 devnull if (level == 0) {
65 262ecfed 2005-08-31 devnull time(&thetime);
66 262ecfed 2005-08-31 devnull chartime = ctime(thetime);
67 262ecfed 2005-08-31 devnull fprint(stderr, "%.15s ", &(chartime[4]));
69 262ecfed 2005-08-31 devnull va_start(ap, s1);
70 262ecfed 2005-08-31 devnull while(args[argno++] = va_arg(ap, char*));
71 262ecfed 2005-08-31 devnull va_end(ap);
72 262ecfed 2005-08-31 devnull fprint(stderr, s1, *args);
77 262ecfed 2005-08-31 devnull alarmhandler(void *foo, char *note) {
78 262ecfed 2005-08-31 devnull USED(foo);
79 262ecfed 2005-08-31 devnull if(strcmp(note, "alarm")==0) {
80 262ecfed 2005-08-31 devnull fprint(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
81 262ecfed 2005-08-31 devnull return(1);
82 262ecfed 2005-08-31 devnull } else return(0);
88 262ecfed 2005-08-31 devnull error(int level, char *s1, ...)
90 262ecfed 2005-08-31 devnull time_t thetime;
91 262ecfed 2005-08-31 devnull char *chartime;
93 262ecfed 2005-08-31 devnull if (level == 0) {
94 262ecfed 2005-08-31 devnull time(&thetime);
95 262ecfed 2005-08-31 devnull chartime = ctime(&thetime);
96 262ecfed 2005-08-31 devnull fprintf(stderr, "%.15s ", &(chartime[4]));
98 262ecfed 2005-08-31 devnull fprintf(stderr, s1, (&s1+1));
103 262ecfed 2005-08-31 devnull alarmhandler() {
104 262ecfed 2005-08-31 devnull fprintf(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
109 262ecfed 2005-08-31 devnull /* get a line from inpfd using nonbuffered input. The line is truncated if it is too
110 262ecfed 2005-08-31 devnull * long for the buffer. The result is left in lnbuf and the number of characters
111 262ecfed 2005-08-31 devnull * read in is returned.
114 262ecfed 2005-08-31 devnull readline(int inpfd)
116 262ecfed 2005-08-31 devnull register char *ap;
117 262ecfed 2005-08-31 devnull register int i;
119 262ecfed 2005-08-31 devnull ap = lnbuf;
122 262ecfed 2005-08-31 devnull if (read(inpfd, ap, 1) != 1) {
123 262ecfed 2005-08-31 devnull error(0, "read error in readline, fd=%d\n", inpfd);
126 262ecfed 2005-08-31 devnull } while ((++i < LNBFSZ - 2) && *ap++ != '\n');
127 262ecfed 2005-08-31 devnull if (i == LNBFSZ - 2) {
128 262ecfed 2005-08-31 devnull *ap = '\n';
131 262ecfed 2005-08-31 devnull *ap = '\0';
132 262ecfed 2005-08-31 devnull return(i);
135 262ecfed 2005-08-31 devnull #define RDSIZE 512
136 262ecfed 2005-08-31 devnull char jobbuf[RDSIZE];
139 262ecfed 2005-08-31 devnull pass(int inpfd, int outfd, int bsize)
141 262ecfed 2005-08-31 devnull int bcnt = 0;
142 262ecfed 2005-08-31 devnull int rv = 0;
144 262ecfed 2005-08-31 devnull for(bcnt=bsize; bcnt > 0; bcnt -= rv) {
145 262ecfed 2005-08-31 devnull alarm(WRNETIMEOUT); /* to break hanging */
146 262ecfed 2005-08-31 devnull if((rv=read(inpfd, jobbuf, MIN(bcnt,RDSIZE))) < 0) {
147 262ecfed 2005-08-31 devnull error(0, "read error during pass, %d remaining\n", bcnt);
149 262ecfed 2005-08-31 devnull } else if((write(outfd, jobbuf, rv)) != rv) {
150 262ecfed 2005-08-31 devnull error(0, "write error during pass, %d remaining\n", bcnt);
154 262ecfed 2005-08-31 devnull alarm(0);
155 262ecfed 2005-08-31 devnull return(bcnt);
158 262ecfed 2005-08-31 devnull /* get whatever stdin has and put it into the temporary file.
159 262ecfed 2005-08-31 devnull * return the file size.
162 262ecfed 2005-08-31 devnull prereadfile(int inpfd)
164 262ecfed 2005-08-31 devnull int rv, bsize;
166 262ecfed 2005-08-31 devnull bsize = 0;
168 262ecfed 2005-08-31 devnull if((rv=read(0, jobbuf, RDSIZE))<0) {
169 262ecfed 2005-08-31 devnull error(0, "read error while making temp file\n");
170 262ecfed 2005-08-31 devnull exits("read error while making temp file");
171 262ecfed 2005-08-31 devnull } else if((write(inpfd, jobbuf, rv)) != rv) {
172 262ecfed 2005-08-31 devnull error(0, "write error while making temp file\n");
173 262ecfed 2005-08-31 devnull exits("write error while making temp file");
175 262ecfed 2005-08-31 devnull bsize += rv;
176 262ecfed 2005-08-31 devnull } while (rv!=0);
177 262ecfed 2005-08-31 devnull return(bsize);
181 262ecfed 2005-08-31 devnull tempfile(void)
183 262ecfed 2005-08-31 devnull static int tindx = 0;
184 262ecfed 2005-08-31 devnull char tmpf[20];
185 262ecfed 2005-08-31 devnull int tmpfd;
187 262ecfed 2005-08-31 devnull sprint(tmpf, "/var/tmp/lp%d.%d", getpid(), tindx++);
188 262ecfed 2005-08-31 devnull if((tmpfd=create(tmpf,
190 262ecfed 2005-08-31 devnull #ifdef plan9
192 262ecfed 2005-08-31 devnull ORDWR|OTRUNC,
196 262ecfed 2005-08-31 devnull 0666)) < 0) {
197 262ecfed 2005-08-31 devnull error(0, "cannot create temp file %s\n", tmpf);
198 262ecfed 2005-08-31 devnull exits("cannot create temp file");
200 262ecfed 2005-08-31 devnull close(tmpfd);
201 262ecfed 2005-08-31 devnull if((tmpfd=open(tmpf, ORDWR
203 262ecfed 2005-08-31 devnull #ifdef plan9
205 262ecfed 2005-08-31 devnull |ORCLOSE|OTRUNC
209 262ecfed 2005-08-31 devnull )) < 0) {
210 262ecfed 2005-08-31 devnull error(0, "cannot open temp file %s\n", tmpf);
211 262ecfed 2005-08-31 devnull exits("cannot open temp file");
213 262ecfed 2005-08-31 devnull return(tmpfd);
217 262ecfed 2005-08-31 devnull recvACK(int netfd)
221 262ecfed 2005-08-31 devnull *jobbuf = '\0';
222 262ecfed 2005-08-31 devnull alarm(RDNETIMEOUT);
223 262ecfed 2005-08-31 devnull if (read(netfd, jobbuf, 1)!=1 || *jobbuf!='\0') {
224 262ecfed 2005-08-31 devnull error(0, "failed to receive ACK, ");
225 262ecfed 2005-08-31 devnull if (*jobbuf == '\0')
226 262ecfed 2005-08-31 devnull error(1, "read failed\n");
228 262ecfed 2005-08-31 devnull error(1, "received <0x%x> instead\n", *jobbuf);
230 262ecfed 2005-08-31 devnull } else rv = 1;
231 262ecfed 2005-08-31 devnull alarm(0);
232 262ecfed 2005-08-31 devnull return(rv);
236 262ecfed 2005-08-31 devnull main(int argc, char *argv[])
238 262ecfed 2005-08-31 devnull char *devdir;
239 262ecfed 2005-08-31 devnull int i, rv, netfd, bsize;
240 262ecfed 2005-08-31 devnull int datafd;
242 262ecfed 2005-08-31 devnull #ifndef plan9
244 262ecfed 2005-08-31 devnull void (*oldhandler)();
248 262ecfed 2005-08-31 devnull devdir = nil;
249 262ecfed 2005-08-31 devnull /* make connection */
250 262ecfed 2005-08-31 devnull if (argc != 2) {
251 262ecfed 2005-08-31 devnull fprint(stderr, "usage: %s network!destination!service\n", argv[0]);
252 262ecfed 2005-08-31 devnull exits("incorrect number of arguments");
255 262ecfed 2005-08-31 devnull /* read options line from stdin into lnbuf */
256 262ecfed 2005-08-31 devnull i = readline(0);
258 262ecfed 2005-08-31 devnull /* read stdin into tempfile to get size */
259 262ecfed 2005-08-31 devnull datafd = tempfile();
260 262ecfed 2005-08-31 devnull bsize = prereadfile(datafd);
262 262ecfed 2005-08-31 devnull /* network connection is opened after data is in to avoid timeout */
263 262ecfed 2005-08-31 devnull if ((netfd=dial(argv[1], 0, 0, 0)) < 0) {
264 262ecfed 2005-08-31 devnull fprint(stderr, "dialing %s\n", devdir);
265 262ecfed 2005-08-31 devnull perror("dial");
266 262ecfed 2005-08-31 devnull exits("can't dial");
269 262ecfed 2005-08-31 devnull /* write out the options we read above */
270 262ecfed 2005-08-31 devnull if (write(netfd, lnbuf, i) != i) {
271 262ecfed 2005-08-31 devnull error(0, "write error while sending options\n");
272 262ecfed 2005-08-31 devnull exits("write error while sending options");
275 262ecfed 2005-08-31 devnull /* send the size of the file to be sent */
276 262ecfed 2005-08-31 devnull sprint(lnbuf, "%d\n", bsize);
277 262ecfed 2005-08-31 devnull i = strlen(lnbuf);
278 262ecfed 2005-08-31 devnull if ((rv=write(netfd, lnbuf, i)) != i) {
279 262ecfed 2005-08-31 devnull perror("write error while sending size");
280 262ecfed 2005-08-31 devnull error(0, "write returned %d\n", rv);
281 262ecfed 2005-08-31 devnull exits("write error while sending size");
284 262ecfed 2005-08-31 devnull if (seek(datafd, 0L, 0) < 0) {
285 262ecfed 2005-08-31 devnull error(0, "error seeking temp file\n");
286 262ecfed 2005-08-31 devnull exits("seek error");
288 262ecfed 2005-08-31 devnull /* mirror performance in readfile() in lpdaemon */
290 262ecfed 2005-08-31 devnull #ifdef plan9
292 262ecfed 2005-08-31 devnull atnotify(alarmhandler, 1);
296 262ecfed 2005-08-31 devnull oldhandler = signal(SIGALRM, alarmhandler);
300 262ecfed 2005-08-31 devnull dbgstate = 1;
301 262ecfed 2005-08-31 devnull if(!recvACK(netfd)) {
302 262ecfed 2005-08-31 devnull error(0, "failed to receive ACK before sending data\n");
303 262ecfed 2005-08-31 devnull exits("recv ack1 failed");
305 262ecfed 2005-08-31 devnull dbgstate = 2;
306 262ecfed 2005-08-31 devnull if ((i=pass(datafd, netfd, bsize)) != 0) {
307 262ecfed 2005-08-31 devnull NAK(netfd);
308 262ecfed 2005-08-31 devnull error(0, "failed to send %d bytes\n", i);
309 262ecfed 2005-08-31 devnull exits("send data failed");
311 262ecfed 2005-08-31 devnull ACK(netfd);
312 262ecfed 2005-08-31 devnull dbgstate = 3;
313 262ecfed 2005-08-31 devnull if(!recvACK(netfd)) {
314 262ecfed 2005-08-31 devnull error(0, "failed to receive ACK after sending data\n");
315 262ecfed 2005-08-31 devnull exits("recv ack2 failed");
318 262ecfed 2005-08-31 devnull /* get response, as from lp -q */
319 262ecfed 2005-08-31 devnull dbgstate = 4;
320 262ecfed 2005-08-31 devnull while((rv=read(netfd, jobbuf, RDSIZE)) > 0) {
321 262ecfed 2005-08-31 devnull if((write(1, jobbuf, rv)) != rv) {
322 262ecfed 2005-08-31 devnull error(0, "write error while sending to stdout\n");
323 262ecfed 2005-08-31 devnull exits("write error while sending to stdout");
326 262ecfed 2005-08-31 devnull dbgstate = 5;
328 262ecfed 2005-08-31 devnull #ifdef plan9
330 262ecfed 2005-08-31 devnull atnotify(alarmhandler, 0);
331 262ecfed 2005-08-31 devnull /* close down network connections and go away */
332 262ecfed 2005-08-31 devnull exits("");
336 262ecfed 2005-08-31 devnull signal(SIGALRM, oldhandler);
337 262ecfed 2005-08-31 devnull exit(0);