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