8 RDNETIMEOUT = 30*60*1000,
9 WRNETIMEOUT = RDNETIMEOUT,
22 #define fprint fprintf
23 #define sprint sprintf
27 #define OTRUNC O_TRUNC
30 #define RDNETIMEOUT 60
31 #define WRNETIMEOUT 60
35 #define MIN(a,b) ((a<b)?a:b)
37 #define ACK(a) write(a, "", 1)
38 #define NAK(a) write(a, "\001", 1)
40 #define LPDAEMONLOG "/tmp/lpdaemonl"
45 char *dbgstrings[] = {
57 error(int level, char *s1, ...)
67 chartime = ctime(thetime);
68 fprint(stderr, "%.15s ", &(chartime[4]));
71 while(args[argno++] = va_arg(ap, char*))
74 fprint(stderr, s1, *args);
78 alarmhandler(void *foo, char *note) {
80 if(strcmp(note, "alarm")==0) {
81 fprint(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
89 error(int level, char *s1, ...)
96 chartime = ctime(&thetime);
97 fprintf(stderr, "%.15s ", &(chartime[4]));
99 fprintf(stderr, s1, &s1 + 1);
104 fprintf(stderr, "alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
109 /* get a line from inpfd using nonbuffered input. The line is truncated if it is too
110 * long for the buffer. The result is left in lnbuf and the number of characters
111 * read in is returned.
122 if (read(inpfd, ap, 1) != 1) {
123 error(0, "read error in readline, fd=%d\n", inpfd);
126 } while ((++i < LNBFSZ - 2) && *ap++ != '\n');
127 if (i == LNBFSZ - 2) {
139 pass(int inpfd, int outfd, int bsize)
144 for(bcnt=bsize; bcnt > 0; bcnt -= rv) {
145 alarm(WRNETIMEOUT); /* to break hanging */
146 if((rv=read(inpfd, jobbuf, MIN(bcnt,RDSIZE))) < 0) {
147 error(0, "read error during pass, %d remaining\n", bcnt);
149 } else if((write(outfd, jobbuf, rv)) != rv) {
150 error(0, "write error during pass, %d remaining\n", bcnt);
158 /* get whatever stdin has and put it into the temporary file.
159 * return the file size.
162 prereadfile(int inpfd)
168 if((rv=read(0, jobbuf, RDSIZE))<0) {
169 error(0, "read error while making temp file\n");
170 exits("read error while making temp file");
171 } else if((write(inpfd, jobbuf, rv)) != rv) {
172 error(0, "write error while making temp file\n");
173 exits("write error while making temp file");
187 sprint(tmpf, "/tmp/lp%d.%d", getpid(), tindx++);
188 if((tmpfd=create(tmpf,
193 error(0, "cannot create temp file %s\n", tmpf);
194 exits("cannot create temp file");
197 if((tmpfd=open(tmpf, ORDWR
202 error(0, "cannot open temp file %s\n", tmpf);
203 exits("cannot open temp file");
215 if (read(netfd, jobbuf, 1)!=1 || *jobbuf!='\0') {
216 error(0, "failed to receive ACK, ");
218 error(1, "read failed\n");
220 error(1, "received <0x%x> instead\n", *jobbuf);
228 main(int argc, char *argv[])
231 int i, rv, netfd, bsize, datafd;
233 void (*oldhandler)();
236 /* make connection */
238 fprint(stderr, "usage: %s network!destination!service\n",
243 /* read options line from stdin into lnbuf */
246 /* read stdin into tempfile to get size */
248 bsize = prereadfile(datafd);
250 /* network connection is opened after data is in to avoid timeout */
251 if ((netfd = dial(argv[1], 0, 0, 0)) < 0) {
252 fprint(stderr, "dialing ");
257 /* write out the options we read above */
258 if (write(netfd, lnbuf, i) != i) {
259 error(0, "write error while sending options\n");
260 exits("write error sending options");
263 /* send the size of the file to be sent */
264 sprint(lnbuf, "%d\n", bsize);
266 if ((rv=write(netfd, lnbuf, i)) != i) {
267 perror("write error while sending size");
268 error(0, "write returned %d\n", rv);
269 exits("write error sending size");
272 if (seek(datafd, 0L, 0) < 0) {
273 error(0, "error seeking temp file\n");
276 /* mirror performance in readfile() in lpdaemon */
279 atnotify(alarmhandler, 1);
281 oldhandler = signal(SIGALRM, alarmhandler);
285 if(!recvACK(netfd)) {
286 error(0, "failed to receive ACK before sending data\n");
287 exits("recv ack1 failed");
290 if ((i=pass(datafd, netfd, bsize)) != 0) {
292 error(0, "failed to send %d bytes\n", i);
293 exits("send data failed");
297 if(!recvACK(netfd)) {
298 error(0, "failed to receive ACK after sending data\n");
299 exits("recv ack2 failed");
302 /* get response, as from lp -q */
304 while((rv=read(netfd, jobbuf, RDSIZE)) > 0) {
305 if((write(1, jobbuf, rv)) != rv) {
306 error(0, "write error while sending to stdout\n");
307 exits("write error while sending to stdout");
313 atnotify(alarmhandler, 0);
314 /* close down network connections and go away */
317 signal(SIGALRM, oldhandler);