|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)recvjob.c 5.11 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Receive printer jobs from the network, queue them and
26: * start the printer daemon.
27: */
28:
29: #include "lp.h"
30: #include <ufs/fs.h>
31: #include "pathnames.h"
32:
33: char *sp = "";
34: #define ack() (void) write(1, sp, 1);
35:
36: char tfname[40]; /* tmp copy of cf before linking */
37: char dfname[40]; /* data files */
38: int minfree; /* keep at least minfree blocks available */
39: char *ddev; /* disk device (for checking free space) */
40: int dfd; /* file system device descriptor */
41:
42: char *find_dev();
43:
44: recvjob()
45: {
46: struct stat stb;
47: char *bp = pbuf;
48: int status, rcleanup();
49:
50: /*
51: * Perform lookup for printer name or abbreviation
52: */
53: if ((status = pgetent(line, printer)) < 0)
54: frecverr("cannot open printer description file");
55: else if (status == 0)
56: frecverr("unknown printer %s", printer);
57: if ((LF = pgetstr("lf", &bp)) == NULL)
58: LF = _PATH_CONSOLE;
59: if ((SD = pgetstr("sd", &bp)) == NULL)
60: SD = _PATH_DEFSPOOL;
61: if ((LO = pgetstr("lo", &bp)) == NULL)
62: LO = DEFLOCK;
63:
64: (void) close(2); /* set up log file */
65: if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
66: syslog(LOG_ERR, "%s: %m", LF);
67: (void) open(_PATH_DEVNULL, O_WRONLY);
68: }
69:
70: if (chdir(SD) < 0)
71: frecverr("%s: %s: %m", printer, SD);
72: if (stat(LO, &stb) == 0) {
73: if (stb.st_mode & 010) {
74: /* queue is disabled */
75: putchar('\1'); /* return error code */
76: exit(1);
77: }
78: } else if (stat(SD, &stb) < 0)
79: frecverr("%s: %s: %m", printer, SD);
80: minfree = read_number("minfree");
81: ddev = find_dev(stb.st_dev, S_IFBLK);
82: if ((dfd = open(ddev, O_RDONLY)) < 0)
83: syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
84: signal(SIGTERM, rcleanup);
85: signal(SIGPIPE, rcleanup);
86:
87: if (readjob())
88: printjob();
89: }
90:
91: char *
92: find_dev(dev, type)
93: register dev_t dev;
94: register int type;
95: {
96: register DIR *dfd = opendir(_PATH_DEV);
97: struct direct *dir;
98: struct stat stb;
99: char devname[MAXNAMLEN+6];
100: char *dp;
101:
102: strcpy(devname, _PATH_DEV);
103: while ((dir = readdir(dfd))) {
104: strcpy(devname + 5, dir->d_name);
105: if (stat(devname, &stb))
106: continue;
107: if ((stb.st_mode & S_IFMT) != type)
108: continue;
109: if (dev == stb.st_rdev) {
110: closedir(dfd);
111: dp = (char *)malloc(strlen(devname)+1);
112: strcpy(dp, devname);
113: return(dp);
114: }
115: }
116: closedir(dfd);
117: frecverr("cannot find device %d, %d", major(dev), minor(dev));
118: /*NOTREACHED*/
119: }
120:
121: /*
122: * Read printer jobs sent by lpd and copy them to the spooling directory.
123: * Return the number of jobs successfully transfered.
124: */
125: readjob()
126: {
127: register int size, nfiles;
128: register char *cp;
129:
130: ack();
131: nfiles = 0;
132: for (;;) {
133: /*
134: * Read a command to tell us what to do
135: */
136: cp = line;
137: do {
138: if ((size = read(1, cp, 1)) != 1) {
139: if (size < 0)
140: frecverr("%s: Lost connection",printer);
141: return(nfiles);
142: }
143: } while (*cp++ != '\n');
144: *--cp = '\0';
145: cp = line;
146: switch (*cp++) {
147: case '\1': /* cleanup because data sent was bad */
148: rcleanup();
149: continue;
150:
151: case '\2': /* read cf file */
152: size = 0;
153: while (*cp >= '0' && *cp <= '9')
154: size = size * 10 + (*cp++ - '0');
155: if (*cp++ != ' ')
156: break;
157: /*
158: * host name has been authenticated, we use our
159: * view of the host name since we may be passed
160: * something different than what gethostbyaddr()
161: * returns
162: */
163: strcpy(cp + 6, from);
164: strcpy(tfname, cp);
165: tfname[0] = 't';
166: if (!chksize(size)) {
167: (void) write(1, "\2", 1);
168: continue;
169: }
170: if (!readfile(tfname, size)) {
171: rcleanup();
172: continue;
173: }
174: if (link(tfname, cp) < 0)
175: frecverr("%s: %m", tfname);
176: (void) unlink(tfname);
177: tfname[0] = '\0';
178: nfiles++;
179: continue;
180:
181: case '\3': /* read df file */
182: size = 0;
183: while (*cp >= '0' && *cp <= '9')
184: size = size * 10 + (*cp++ - '0');
185: if (*cp++ != ' ')
186: break;
187: if (!chksize(size)) {
188: (void) write(1, "\2", 1);
189: continue;
190: }
191: (void) strcpy(dfname, cp);
192: if (index(dfname, '/'))
193: frecverr("illegal path name");
194: (void) readfile(dfname, size);
195: continue;
196: }
197: frecverr("protocol screwup");
198: }
199: }
200:
201: /*
202: * Read files send by lpd and copy them to the spooling directory.
203: */
204: readfile(file, size)
205: char *file;
206: int size;
207: {
208: register char *cp;
209: char buf[BUFSIZ];
210: register int i, j, amt;
211: int fd, err;
212:
213: fd = open(file, O_WRONLY|O_CREAT, FILMOD);
214: if (fd < 0)
215: frecverr("%s: %m", file);
216: ack();
217: err = 0;
218: for (i = 0; i < size; i += BUFSIZ) {
219: amt = BUFSIZ;
220: cp = buf;
221: if (i + amt > size)
222: amt = size - i;
223: do {
224: j = read(1, cp, amt);
225: if (j <= 0)
226: frecverr("Lost connection");
227: amt -= j;
228: cp += j;
229: } while (amt > 0);
230: amt = BUFSIZ;
231: if (i + amt > size)
232: amt = size - i;
233: if (write(fd, buf, amt) != amt) {
234: err++;
235: break;
236: }
237: }
238: (void) close(fd);
239: if (err)
240: frecverr("%s: write error", file);
241: if (noresponse()) { /* file sent had bad data in it */
242: (void) unlink(file);
243: return(0);
244: }
245: ack();
246: return(1);
247: }
248:
249: noresponse()
250: {
251: char resp;
252:
253: if (read(1, &resp, 1) != 1)
254: frecverr("Lost connection");
255: if (resp == '\0')
256: return(0);
257: return(1);
258: }
259:
260: /*
261: * Check to see if there is enough space on the disk for size bytes.
262: * 1 == OK, 0 == Not OK.
263: */
264: chksize(size)
265: int size;
266: {
267: int spacefree;
268: struct fs fs;
269:
270: if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0)
271: return(1);
272: if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
273: return(1);
274: spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
275: size = (size + 1023) / 1024;
276: if (minfree + size > spacefree)
277: return(0);
278: return(1);
279: }
280:
281: read_number(fn)
282: char *fn;
283: {
284: char lin[80];
285: register FILE *fp;
286:
287: if ((fp = fopen(fn, "r")) == NULL)
288: return (0);
289: if (fgets(lin, 80, fp) == NULL) {
290: fclose(fp);
291: return (0);
292: }
293: fclose(fp);
294: return (atoi(lin));
295: }
296:
297: /*
298: * Remove all the files associated with the current job being transfered.
299: */
300: rcleanup()
301: {
302:
303: if (tfname[0])
304: (void) unlink(tfname);
305: if (dfname[0])
306: do {
307: do
308: (void) unlink(dfname);
309: while (dfname[2]-- != 'A');
310: dfname[2] = 'z';
311: } while (dfname[0]-- != 'd');
312: dfname[0] = '\0';
313: }
314:
315: frecverr(msg, a1, a2)
316: char *msg;
317: {
318: rcleanup();
319: syslog(LOG_ERR, msg, a1, a2);
320: putchar('\1'); /* return error code */
321: exit(1);
322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.