10 #include <sys/types.h>
16 #define TMPDIR "/sys/lib/lp/tmp"
17 #define LPDAEMONLOG "/sys/lib/lp/log/lpdaemonl"
19 /* for Tenth Edition systems */
21 #define LP "/usr/bin/lp"
23 #define LPDAEMONLOG "/tmp/lpdaemonl"
25 /* for System V or BSD systems */
26 #if defined(SYSV) || defined(BSD)
27 #define LP "/v/bin/lp"
29 #define LPDAEMONLOG "/tmp/lpdaemonl"
35 unsigned char argvstr[ARGSIZ]; /* arguments after parsing */
36 unsigned char *argvals[ARGSIZ/2+1]; /* pointers to arguments after parsing */
37 int ascnt = 0, argcnt = 0; /* number of arguments parsed */
38 /* for 'stuff' gleened from lpr cntrl file */
44 #define MIN(a,b) ((a<b)?a:b)
46 #define CPYFIELD(src, dst) { while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; }
48 #define ACK() write(1, "", 1)
49 #define NAK() write(1, "\001", 1)
52 unsigned char lnbuf[LNBFSZ];
55 unsigned char jobbuf[RDSIZE];
57 int datafd[400], cntrlfd = -1;
60 char *dbgstrings[] = {
79 if((fp=fopen(LPDAEMONLOG, "a"))==NULL) {
80 fprintf(stderr, "cannot open %s in append mode\n", LPDAEMONLOG);
84 chartime = ctime(&thetime);
85 fprintf(fp, "%.15s [%5.5d] ", &(chartime[4]), getpid());
87 while((args[argno++] = va_arg(ap, char*)) && argno<8)
90 fprintf(fp, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
98 unsigned char *bp, *cp;
99 unsigned char logent[LNBFSZ];
101 /* log this call to lp */
103 for (i=1; i<argcnt; i++) {
105 if (cp+strlen((const char *)bp)+1 < logent+LNBFSZ-1) {
112 error((const char *)logent);
113 switch((cpid=fork())){
115 error("fork error\n");
122 execvp(LP, (const char **)argvals);
123 error("exec failed\n");
126 while(wait((int *)0) != cpid)
135 char tmpf[sizeof(TMPDIR)+64];
138 sprintf(tmpf, "%s/lp%d.%d", TMPDIR, getpid(), tindx++);
139 if((crtfd=creat(tmpf, 0666)) < 0) {
140 error("cannot create temp file %s\n", tmpf);
144 if((tmpfd=open(tmpf, 2)) < 0) {
145 error("cannot open temp file %s\n", tmpf);
150 unlink(tmpf); /* comment out for debugging */
155 readfile(int outfd, int bsize)
163 for(; bsize > 0; bsize -= rv) {
165 if((rv=read(0, jobbuf, MIN(bsize,RDSIZE))) < 0) {
166 error("error reading input, %d unread\n", bsize);
168 } else if (rv == 0) {
169 error("connection closed prematurely\n");
171 } else if((write(outfd, jobbuf, rv)) != rv) {
172 error("error writing temp file, %d unread\n", bsize);
178 if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) {
186 error("received bad status <%d> from sender\n", *jobbuf);
187 error("rv=%d\n", rv);
192 /* reads a line from the input into lnbuf
193 * if there is no error, it returns
194 * the number of characters in the buffer
195 * if there is an error and there where characters
196 * read, it returns the negative value of the
197 * number of characters read
198 * if there is an error and no characters were read,
199 * it returns the negative value of 1 greater than
200 * the size of the line buffer
213 rv = read(inpfd, ap, 1);
214 } while (rv==1 && ++i && *ap != '\n' && ap++ && (i < LNBFSZ - 2));
216 if (i != 0 && *ap != '\n') {
222 error("read error; lost connection\n");
223 if (i==0) i = -(LNBFSZ+1);
233 int filecnt, bsize, rv;
236 /* get a line, hopefully containing a ctrl char, size, and name */
239 if ((rv=readline(0)) < 0) NAK();
244 case '\1': /* cleanup - data sent was bad (whatever that means) */
246 case '\2': /* read control file */
247 bsize = atoi((const char *)ap);
248 cntrlfd = tempfile();
249 if (readfile(cntrlfd, bsize) < 0) {
255 case '\3': /* read data file */
256 bsize = atoi((const char *)ap);
257 datafd[filecnt] = tempfile();
258 if (readfile(datafd[filecnt], bsize) < 0) {
259 close(datafd[filecnt]);
266 error("protocol error <%d>\n", *(ap-1));
278 static struct jobinfo info;
280 if (fd < 0) error("getjobinfo: bad file descriptor\n");
281 if (lseek(fd, 0L, 0) < 0) {
282 error("error seeking in temp file\n");
285 /* the following strings should be < NAMELEN or else they will not
286 * be null terminated.
288 strncpy(info.user, "daemon", NAMELEN);
289 strncpy(info.host, "nowhere", NAMELEN);
290 /* there may be a space after the name and host. It will be filtered out
293 while ((rv=readline(fd)) > 0) {
295 ap[rv-1] = '\0'; /* remove newline from string */
299 strncpy(info.host, "unknown", NAMELEN);
301 strncpy(info.host, (const char *)&ap[1], NAMELEN);
302 info.host[NAMELEN] = '\0';
306 strncpy(info.user, "unknown", NAMELEN);
308 strncpy(info.user, (const char *)&ap[1], NAMELEN);
309 info.user[NAMELEN] = '\0';
317 alarmhandler(int sig) {
318 signal(sig, alarmhandler);
319 error("alarm at %d - %s\n", dbgstate, dbgstrings[dbgstate]);
325 unsigned char *ap, *bp, *cp, *savbufpnt;
326 int i, blen, rv, saveflg, savargcnt;
327 struct jobinfo *jinfop;
329 signal(SIGHUP, SIG_IGN);
330 signal(SIGALRM, alarmhandler);
332 /* setup argv[0] for exec */
333 argvals[argcnt++] = cp;
334 for (bp = (unsigned char *)LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++);
336 /* get the first line sent and parse it as arguments for lp */
337 if ((rv=readline(0)) < 0)
340 /* setup the remaining arguments */
341 /* check for BSD style request */
342 /* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */
347 bp++; /* drop the ctrl character from the input */
348 argvals[argcnt++] = cp;
349 *cp++ = '-'; *cp++ = 'q'; *cp++ = '\0'; /* -q */
350 argvals[argcnt++] = cp;
351 *cp++ = '-'; *cp++ = 'd'; /* -d */
352 CPYFIELD(bp, cp); /* printer */
356 bp++; /* drop the ctrl character from the input */
357 argvals[argcnt++] = cp;
358 *cp++ = '-'; *cp++ = 'd'; /* -d */
359 CPYFIELD(bp, cp); /* printer */
364 while ((rv=getfiles())) {
365 jinfop = getjobinfo(cntrlfd);
369 argvals[argcnt++] = cp;
370 *cp++ = '-'; *cp++ = 'M'; /* -M */
371 bp = (unsigned char *)jinfop->host;
372 CPYFIELD(bp, cp); /* host name */
374 argvals[argcnt++] = cp;
375 *cp++ = '-'; *cp++ = 'u'; /* -u */
376 bp = (unsigned char *)jinfop->user;
377 CPYFIELD(bp, cp); /* user name */
384 bp++; /* drop the ctrl character from the input */
385 argvals[argcnt++] = cp;
386 *cp++ = '-'; *cp++ = 'k'; *cp++ = '\0'; /* -k */
387 argvals[argcnt++] = cp;
388 *cp++ = '-'; *cp++ = 'd'; /* -d */
389 CPYFIELD(bp, cp); /* printer */
391 argvals[argcnt++] = cp;
392 *cp++ = '-'; ap = cp; *cp++ = 'u'; /* -u */
393 CPYFIELD(bp, cp); /* username */
395 /* deal with bug in lprng where the username is not supplied
398 ap = (unsigned char *)"none";
403 datafd[0] = tempfile();
404 blen = strlen((const char *)bp);
405 if (write(datafd[0], bp, blen) != blen) {
406 error("write error\n");
409 if (write(datafd[0], "\n", 1) != 1) {
410 error("write error\n");
415 /* otherwise get my lp arguments */
417 /* move to next non-white space */
418 while (*bp==' '||*bp=='\t')
420 if (*bp=='\n') continue;
421 /* only accept arguments beginning with -
422 * this is done to prevent the printing of
423 * local files from the destination host
426 argvals[argcnt++] = cp;
430 /* move to next white space copying text to argument buffer */
431 while (*bp!=' ' && *bp!='\t' && *bp!='\n'
438 } while (*bp!='\n' && *bp!='\0');
439 if (readline(0) < 0) exit(7);
440 datafd[0] = tempfile();
441 if(readfile(datafd[0], atoi((const char *)lnbuf)) < 0) {
442 error("readfile failed\n");