|
|
1.1 root 1: #include <stddef.h>
2: #include <stdarg.h>
3: #include <signal.h>
4: #include <fio.h>
5: #include <errno.h>
6: #include <time.h>
7:
8: /* for Tenth Edition systems */
9: #define LP "/usr/bin/lp"
10: /* for System V or BSD systems */
11: /* #define LP "/v/bin/lp" */
12:
13: #define LPDAEMONLOG "/tmp/lpdaemonl"
14:
15: #define ARGSIZ 4096
16: #define NAMELEN 11
17:
18: char argvstr[ARGSIZ]; /* arguments after parsing */
19: char *argvals[ARGSIZ/2+1]; /* pointers to arguments after parsing */
20: int ascnt = 0, argcnt = 0; /* number of arguments parsed */
21: /* for 'stuff' gleened from lpr cntrl file */
22: struct jobinfo {
23: char user[NAMELEN+1];
24: char host[NAMELEN+1];
25: } *getjobinfo();
26:
27: #define MIN(a,b) ((a<b)?a:b)
28:
29: #define CPYFIELD(src, dst) { while (*(src)!=' ' && *(src)!='\t' && *(src)!='\r' && *(src)!='\n' && *(src)!='\0') *(dst)++ = *(src)++; }
30:
31: #define ACK() write(1, "", 1)
32: #define NAK() write(1, "\001", 1)
33:
34: #define LNBFSZ 4096
35: char lnbuf[LNBFSZ];
36: int readline();
37:
38: #define RDSIZE 512
39: char jobbuf[RDSIZE];
40:
41: int datafd[400], cntrlfd;
42:
43: void
44: error(int level, char *s1, ...)
45: {
46: int fd;
47: long thetime;
48: char *chartime;
49: va_list ap;
50: char *args[8];
51: int argno = 0;
52:
53: if((fd=open(LPDAEMONLOG, 1))<0) {
54: if(errno==ENOENT) {
55: if((fd=creat(LPDAEMONLOG, 0664))<0) {
56: return; /* hopeless, just go away mad */
57: }
58: } else return;
59: }
60:
61: lseek(fd, 0, 2);
62: if (level == 0) {
63: time(&thetime);
64: chartime = ctime(&thetime);
65: fprint(fd, "%.15s ", &(chartime[4]));
66: }
67: va_start(ap, s1);
68: while(args[argno++] = va_arg(ap, char*));
69: va_end(ap);
70: fprint(fd, s1, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
71: close(fd);
72: return;
73: }
74:
75: void
76: forklp(int inputfd)
77: {
78: int i, cpid;
79: char *bp, *cp;
80: char logent[LNBFSZ];
81:
82: /* log this call to lp */
83: cp = logent;
84: for (i=1; i<argcnt; i++) {
85: bp = argvals[i];
86: if (cp+strlen(bp)+1 < logent+LNBFSZ-1) {
87: CPYFIELD(bp, cp);
88: *cp++ = ' ';
89: }
90: }
91: *--cp = '\n';
92: *++cp = '\0';
93: error(0, logent);
94: switch((cpid=fork())){
95: case -1:
96: error(0, "fork error\n");
97: exit(2);
98: case 0:
99: if (inputfd != 0)
100: dup2(inputfd, 0);
101: dup2(1, 2);
102: lseek(0, 0L, 0);
103: execvp(LP, argvals);
104: error(0, "exec failed\n");
105: exit(3);
106: default:
107: while(wait((int *)0) != cpid);
108: }
109: }
110:
111: int
112: getfiles(void)
113: {
114: char *ap;
115: int filecnt, bsize, rv;
116:
117: filecnt = 0;
118: /* get a line, hopefully containing a ctrl char, size, and name */
119: for(;;) {
120: ap = lnbuf;
121: do {
122: if ((rv = read(1, ap, 1)) != 1) {
123: if (rv < 0) {
124: error(0, "Lost connection\n");
125: NAK();
126: }
127: return(filecnt);
128: }
129: } while (*ap != '\n' && (ap++ - lnbuf < LNBFSZ - 1));
130: *ap = '\0';
131: ap = lnbuf;
132: switch(*ap++) {
133: case '\1': /* cleanup - data sent was bad (whatever that means) */
134: break;
135: case '\2': /* read control file */
136: bsize = atoi(ap);
137: cntrlfd = tmpfile();
138: if (readfile(cntrlfd, bsize) < 0) {
139: close(cntrlfd);
140: NAK();
141: return(0);
142: }
143: return(filecnt);
144: case '\3': /* read data file */
145: bsize = atoi(ap);
146: datafd[filecnt] = tmpfile();
147: readfile(datafd[filecnt++], bsize);
148: break;
149: default:
150: error(0, "protocol error <%d>\n", *(ap-1));
151: NAK();
152: }
153: }
154: }
155:
156: int
157: readfile(int outfd, int bsize)
158: {
159: int bcnt, rv;
160:
161: ACK();
162: for(bcnt=bsize ; bcnt > 0; bcnt -= rv) {
163: if((rv=read(0, jobbuf, MIN(bcnt,RDSIZE))) < 0) {
164: error(0, "error reading input\n");
165: exit(4);
166: } else if((write(outfd, jobbuf, rv)) != rv) {
167: error(0, "error writing temp file\n");
168: exit(5);
169: }
170: }
171: if (((rv=read(0, jobbuf, 1))==1) && (*jobbuf=='\0')) {
172: ACK();
173: return(outfd);
174: }
175: error(0, "received bad status <%d> from sender ", *jobbuf);
176: error(1, "rv=%d\n", rv);
177: NAK();
178: return(-1);
179: }
180:
181: struct jobinfo *
182: getjobinfo(int fd)
183: {
184: register char *ap;
185: int rv;
186: static struct jobinfo info;
187:
188: if (lseek(fd, 0L, 0) < 0) {
189: error(0, "error seeking in temp file\n");
190: exit(7);
191: }
192: /* the following strings should be < NAMELEN or else they will not
193: * be null terminated.
194: */
195: strncpy(info.user, "daemon", NAMELEN);
196: strncpy(info.host, "nowhere", NAMELEN);
197: /* there may be a space after the name and host. It will be filtered out
198: * by CPYFIELD.
199: */
200: while ((rv=readline(fd)) != 0) {
201: ap = lnbuf;
202: ap[rv-1] = '\0'; /* remove newline from string */
203: switch (*ap) {
204: case 'H':
205: strncpy(info.host, &ap[1], NAMELEN);
206: break;
207: case 'P':
208: strncpy(info.user, &ap[1], NAMELEN);
209: break;
210: }
211: }
212: return(&info);
213: }
214:
215: int
216: tmpfile(void)
217: {
218: static tindx = 0;
219: char tmpf[20];
220: int crtfd, tmpfd;
221:
222: sprint(tmpf, "/tmp/lp%d.%d", getpid(), tindx++);
223: if((crtfd=creat(tmpf, 0666)) < 0) {
224: error(0, "cannot create temp file %s\n", tmpf);
225: NAK();
226: exit(3);
227: }
228: if((tmpfd=open(tmpf, 2)) < 0) {
229: error(0, "cannot open temp file %s\n", tmpf);
230: NAK();
231: exit(3);
232: }
233: close(crtfd);
234: /* unlink(tmpf); /* comment out for debugging */
235: return(tmpfd);
236: }
237:
238: int
239: readline(int inpfd)
240: {
241: register char *ap;
242: register int i;
243:
244: ap = lnbuf;
245: i = 0;
246: do {
247: if (read(inpfd, ap, 1) != 1) {
248: error(0, "read error\n");
249: break;
250: }
251: i++;
252: } while (*ap++ != '\n' && (i < LNBFSZ - 2));
253: if (*(ap-1) != '\n') {
254: *(ap-1) = '\n';
255: i++;
256: }
257: *ap = '\0';
258: return(i);
259: }
260:
261: main()
262: {
263: char *ap, *bp, *cp, *savbufpnt;
264: int i, rv, saveflg, savargcnt;
265: struct jobinfo *jinfop;
266:
267: signal(1, SIG_IGN);
268: cp = argvstr;
269: /* setup argv[0] for exec */
270: argvals[argcnt++] = cp;
271: for (bp = LP, i = 0; (*bp != '\0') && (i < ARGSIZ-1); *cp++ = *bp++, i++);
272: *cp++ = '\0';
273: /* get the first line sent and parse it as arguments for lp */
274: ap = lnbuf;
275: i = 0;
276: do {
277: if ((rv = read(0, ap, 1)) != 1) {
278: if (rv < 0) {
279: error(0, "Lost connection\n");
280: }
281: exit(1);
282: }
283: i++;
284: } while (*ap++ != '\n' && (i < LNBFSZ - 2));
285: if (*(ap-1) != '\n') {
286: *(ap-1) = '\n';
287: i++;
288: }
289: *ap = '\0';
290: ap = lnbuf;
291: if (ap == (char *)0) {
292: error(0, "cannot read arg line\n");
293: NAK();
294: exit(1);
295: }
296: bp = ap;
297: /* setup the remaining arguments */
298: /* check for BSD style request */
299: /* ^A, ^B, ^C, ^D, ^E (for BSD lpr) */
300: switch (*bp) {
301: case '\001':
302: case '\003':
303: case '\004':
304: bp++; /* drop the ctrl character from the input */
305: argvals[argcnt++] = cp;
306: *cp++ = '-'; *cp++ = 'q'; *cp++ = '\0'; /* -q */
307: argvals[argcnt++] = cp;
308: *cp++ = '-'; *cp++ = 'd'; /* -d */
309: CPYFIELD(bp, cp); /* printer */
310: *cp++ = '\0';
311: break;
312: case '\002':
313: bp++; /* drop the ctrl character from the input */
314: argvals[argcnt++] = cp;
315: *cp++ = '-'; *cp++ = 'd'; /* -d */
316: CPYFIELD(bp, cp); /* printer */
317: *cp++ = '\0';
318: ACK();
319: savargcnt = argcnt;
320: savbufpnt = cp;
321: while ((rv=getfiles())) {
322: jinfop = getjobinfo(cntrlfd);
323: close(cntrlfd);
324: argcnt = savargcnt;
325: cp = savbufpnt;
326: argvals[argcnt++] = cp;
327: *cp++ = '-'; *cp++ = 'M'; /* -M */
328: bp = jinfop->host;
329: CPYFIELD(bp, cp); /* host name */
330: *cp++ = '\0';
331: argvals[argcnt++] = cp;
332: *cp++ = '-'; *cp++ = 'u'; /* -u */
333: bp = jinfop->user;
334: CPYFIELD(bp, cp); /* user name */
335: *cp++ = '\0';
336: for(i=0;i<rv;i++)
337: forklp(datafd[i]);
338: }
339: exit(0);
340: case '\005':
341: bp++; /* drop the ctrl character from the input */
342: argvals[argcnt++] = cp;
343: *cp++ = '-'; *cp++ = 'k'; *cp++ = '\0'; /* -k */
344: argvals[argcnt++] = cp;
345: *cp++ = '-'; *cp++ = 'd'; /* -d */
346: CPYFIELD(bp, cp); /* printer */
347: *cp++ = '\0';
348: argvals[argcnt++] = cp;
349: *cp++ = '-'; *cp++ = 'u'; /* -u */
350: CPYFIELD(bp, cp); /* username */
351: *cp++ = '\0';
352: datafd[0] = tmpfile();
353: fprint(datafd[0], "%s\n", bp);
354: break;
355: default:
356: /* otherwise get my lp arguments */
357: do {
358: /* move to next non-white space */
359: while (*bp==' '||*bp=='\t')
360: ++bp;
361: if (*bp=='\n') continue;
362: /* only accept arguments beginning with -
363: * this is done to prevent the printing of
364: * local files from the destination host
365: */
366: if (*bp=='-') {
367: argvals[argcnt++] = cp;
368: saveflg = 1;
369: } else
370: saveflg = 0;
371: /* move to next white space copying text to argument buffer */
372: while (*bp!=' ' && *bp!='\t' && *bp!='\n'
373: && *bp!='\0') {
374: *cp = *bp++;
375: cp += saveflg;
376: }
377: *cp = '\0';
378: cp += saveflg;
379: } while (*bp!='\n');
380: readline(0);
381: datafd[0] = tmpfile();
382: error(0, "reading in %d bytes <%s>\n", atoi(lnbuf), lnbuf);
383: if(readfile(datafd[0], atoi(lnbuf)) < 0) {
384: error(0, "readfile failed\n");
385: exit(7);
386: }
387: }
388: forklp(datafd[0]);
389: exit(0);
390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.