17 #define LP unsharp("#9/bin/lp")
18 #define TMPDIR "/var/tmp"
19 #define LPDAEMONLOG unsharp("#9/lp/log/lpdaemonl")
24 unsigned char argvstr[ARGSIZ]; /* arguments after parsing */
25 unsigned char *argvals[ARGSIZ/2+1]; /* pointers to arguments after parsing */
26 int ascnt = 0, argcnt = 0; /* number of arguments parsed */
27 /* for 'stuff' gleened from lpr cntrl file */
33 #define MIN(a,b) ((a<b)?a:b)
35 #define CPYFIELD(src, dst) { while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; }
37 #define ACK() write(1, "", 1)
38 #define NAK() write(1, "\001", 1)
41 unsigned char lnbuf[LNBFSZ];
44 unsigned char jobbuf[RDSIZE];
46 int datafd[400], cntrlfd = -1;
49 char *dbgstrings[] = {
68 if((fp=fopen(LPDAEMONLOG, "a"))==NULL) {
69 fprintf(stderr, "cannot open %s in append mode\n", LPDAEMONLOG);
73 chartime = ctime(&thetime);
74 fprintf(fp, "%.15s [%5.5d] ", &(chartime[4]), getpid());
76 while((args[argno++] = va_arg(ap, char*)) && argno<8);
78 fprintf(fp, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
88 unsigned char *bp, *cp;
89 unsigned char logent[LNBFSZ];
91 /* log this call to lp */
93 for (i=1; i<argcnt; i++) {
95 if (cp+strlen((const char *)bp)+1 < logent+LNBFSZ-1) {
102 error((char *)logent);
103 switch((cpid=fork())){
105 error("fork error\n");
112 execvp(LP, (char **)argvals);
113 error("exec failed\n");
116 while((i=wait((int *)0)) != cpid){
117 if(i == -1 && errno == ECHILD)
119 printf("%d %d\n", i, errno);
122 error("wait got %d\n", cpid);
129 static int tindx = 0;
130 char tmpf[sizeof(TMPDIR)+64];
133 sprintf(tmpf, "%s/lp%d.%d", TMPDIR, getpid(), tindx++);
134 if((crtfd=creat(tmpf, 0666)) < 0) {
135 error("cannot create temp file %s\n", tmpf);
139 if((tmpfd=open(tmpf, 2)) < 0) {
140 error("cannot open temp file %s\n", tmpf);
145 /* unlink(tmpf); /* comment out for debugging */
150 readfile(int outfd, int bsize)
158 for(; bsize > 0; bsize -= rv) {
160 if((rv=read(0, jobbuf, MIN(bsize,RDSIZE))) < 0) {
161 error("error reading input, %d unread\n", bsize);
163 } else if (rv == 0) {
164 error("connection closed prematurely\n");
166 } else if((write(outfd, jobbuf, rv)) != rv) {
167 error("error writing temp file, %d unread\n", bsize);
173 if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) {
181 error("received bad status <%d> from sender\n", *jobbuf);
182 error("rv=%d\n", rv);
187 /* reads a line from the input into lnbuf
188 * if there is no error, it returns
189 * the number of characters in the buffer
190 * if there is an error and there where characters
191 * read, it returns the negative value of the
192 * number of characters read
193 * if there is an error and no characters were read,
194 * it returns the negative value of 1 greater than
195 * the size of the line buffer
208 rv = read(inpfd, ap, 1);
209 } while (rv==1 && ++i && *ap != '\n' && ap++ && (i < LNBFSZ - 2));
211 if (i != 0 && *ap != '\n') {
217 error("read error; lost connection\n");
218 if (i==0) i = -(LNBFSZ+1);
228 int filecnt, bsize, rv;
231 /* get a line, hopefully containing a ctrl char, size, and name */
234 if ((rv=readline(0)) < 0) NAK();
239 case '\1': /* cleanup - data sent was bad (whatever that means) */
241 case '\2': /* read control file */
242 bsize = atoi((const char *)ap);
243 cntrlfd = tempfile();
244 if (readfile(cntrlfd, bsize) < 0) {
250 case '\3': /* read data file */
251 bsize = atoi((const char *)ap);
252 datafd[filecnt] = tempfile();
253 if (readfile(datafd[filecnt], bsize) < 0) {
254 close(datafd[filecnt]);
261 error("protocol error <%d>\n", *(ap-1));
273 static struct jobinfo info;
275 if (fd < 0) error("getjobinfo: bad file descriptor\n");
276 if (lseek(fd, 0L, 0) < 0) {
277 error("error seeking in temp file\n");
280 /* the following strings should be < NAMELEN or else they will not
281 * be null terminated.
283 strncpy(info.user, "daemon", NAMELEN);
284 strncpy(info.host, "nowhere", NAMELEN);
285 /* there may be a space after the name and host. It will be filtered out
288 while ((rv=readline(fd)) > 0) {
290 ap[rv-1] = '\0'; /* remove newline from string */
294 strncpy(info.host, "unknown", NAMELEN);
296 strncpy(info.host, (const char *)&ap[1], NAMELEN);
297 info.host[strlen(info.host)] = '\0';
301 strncpy(info.user, "unknown", NAMELEN);
303 strncpy(info.user, (const char *)&ap[1], NAMELEN);
304 info.user[strlen(info.user)] = '\0';
312 alarmhandler(int sig) {
313 signal(sig, alarmhandler);
314 error("alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
326 unsigned char *ap, *bp, *cp, *savbufpnt;
327 int i, blen, rv, saveflg, savargcnt;
328 struct jobinfo *jinfop;
330 signal(SIGHUP, SIG_IGN); /* SIGHUP not in lcc */
331 signal(SIGALRM, alarmhandler); /* SIGALRM not in lcc */
332 signal(SIGCHLD, nop); /* so that wait will get us something */
334 /* setup argv[0] for exec */
335 argvals[argcnt++] = cp;
336 for (bp = (unsigned char *)LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++);
338 /* get the first line sent and parse it as arguments for lp */
339 if ((rv=readline(0)) < 0)
342 /* setup the remaining arguments */
343 /* check for BSD style request */
344 /* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */
349 bp++; /* drop the ctrl character from the input */
350 argvals[argcnt++] = cp;
351 *cp++ = '-'; *cp++ = 'q'; *cp++ = '\0'; /* -q */
352 argvals[argcnt++] = cp;
353 *cp++ = '-'; *cp++ = 'd'; /* -d */
354 CPYFIELD(bp, cp); /* printer */
358 bp++; /* drop the ctrl character from the input */
359 argvals[argcnt++] = cp;
360 *cp++ = '-'; *cp++ = 'd'; /* -d */
361 CPYFIELD(bp, cp); /* printer */
366 while ((rv=getfiles())) {
367 jinfop = getjobinfo(cntrlfd);
371 argvals[argcnt++] = cp;
372 *cp++ = '-'; *cp++ = 'M'; /* -M */
373 bp = (unsigned char *)jinfop->host;
374 CPYFIELD(bp, cp); /* host name */
376 argvals[argcnt++] = cp;
377 *cp++ = '-'; *cp++ = 'u'; /* -u */
378 bp = (unsigned char *)jinfop->user;
379 CPYFIELD(bp, cp); /* user name */
386 bp++; /* drop the ctrl character from the input */
387 argvals[argcnt++] = cp;
388 *cp++ = '-'; *cp++ = 'k'; *cp++ = '\0'; /* -k */
389 argvals[argcnt++] = cp;
390 *cp++ = '-'; *cp++ = 'd'; /* -d */
391 CPYFIELD(bp, cp); /* printer */
393 argvals[argcnt++] = cp;
394 *cp++ = '-'; ap = cp; *cp++ = 'u'; /* -u */
395 CPYFIELD(bp, cp); /* username */
397 /* deal with bug in lprng where the username is not supplied
400 ap = (unsigned char *)"none";
405 datafd[0] = tempfile();
406 blen = strlen((const char *)bp);
407 if (write(datafd[0], bp, blen) != blen) {
408 error("write error\n");
411 if (write(datafd[0], "\n", 1) != 1) {
412 error("write error\n");
417 /* otherwise get my lp arguments */
419 /* move to next non-white space */
420 while (*bp==' '||*bp=='\t')
422 if (*bp=='\n') continue;
423 /* only accept arguments beginning with -
424 * this is done to prevent the printing of
425 * local files from the destination host
428 argvals[argcnt++] = cp;
432 /* move to next white space copying text to argument buffer */
433 while (*bp!=' ' && *bp!='\t' && *bp!='\n'
440 } while (*bp!='\n' && *bp!='\0');
441 if (readline(0) < 0) exit(7);
442 datafd[0] = tempfile();
443 if(readfile(datafd[0], atoi((const char *)lnbuf)) < 0) {
444 error("readfile failed\n");