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