remove pathnames.h
[unix-history] / usr / src / usr.sbin / lpr / lpd / recvjob.c
CommitLineData
d0aeaf5a
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
9d85c861
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
a399f6c8
KB
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.
d0aeaf5a
DF
16 */
17
5f84f8f0 18#ifndef lint
a399f6c8 19static char sccsid[] = "@(#)recvjob.c 5.7 (Berkeley) %G%";
9d85c861 20#endif /* not lint */
5f84f8f0 21
e3127271
RC
22/*
23 * Receive printer jobs from the network, queue them and
24 * start the printer daemon.
25 */
26
27#include "lp.h"
47f0387b 28#include <sys/fs.h>
e3127271 29
47f0387b
RC
30char *sp = "";
31#define ack() (void) write(1, sp, 1);
32
33char tfname[40]; /* tmp copy of cf before linking */
666561d4 34char dfname[40]; /* data files */
47f0387b
RC
35int minfree; /* keep at least minfree blocks available */
36char *ddev; /* disk device (for checking free space) */
37int dfd; /* file system device descriptor */
38
39char *find_dev();
e3127271
RC
40
41recvjob()
42{
88f026f7 43 struct stat stb;
e3127271 44 char *bp = pbuf;
47f0387b 45 int status, rcleanup();
e3127271 46
e3127271
RC
47 /*
48 * Perform lookup for printer name or abbreviation
49 */
50 if ((status = pgetent(line, printer)) < 0)
47f0387b 51 frecverr("cannot open printer description file");
e3127271 52 else if (status == 0)
47f0387b 53 frecverr("unknown printer %s", printer);
e3127271
RC
54 if ((LF = pgetstr("lf", &bp)) == NULL)
55 LF = DEFLOGF;
56 if ((SD = pgetstr("sd", &bp)) == NULL)
57 SD = DEFSPOOL;
88f026f7
RC
58 if ((LO = pgetstr("lo", &bp)) == NULL)
59 LO = DEFLOCK;
e3127271 60
4e7bc1ec
EA
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
e3127271 67 if (chdir(SD) < 0)
47f0387b
RC
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);
e3127271
RC
83
84 if (readjob())
85 printjob();
86}
87
47f0387b
RC
88char *
89find_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}
e3127271
RC
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 */
47f0387b 122readjob()
e3127271
RC
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)
47f0387b 137 frecverr("%s: Lost connection",printer);
e3127271
RC
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 */
47f0387b 145 rcleanup();
e3127271
RC
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;
dda5ffcd
JB
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);
e3127271
RC
161 strcpy(tfname, cp);
162 tfname[0] = 't';
47f0387b
RC
163 if (!chksize(size)) {
164 (void) write(1, "\2", 1);
165 continue;
166 }
e3127271 167 if (!readfile(tfname, size)) {
47f0387b 168 rcleanup();
e3127271
RC
169 continue;
170 }
171 if (link(tfname, cp) < 0)
47f0387b 172 frecverr("%s: %m", tfname);
e3127271
RC
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;
47f0387b
RC
184 if (!chksize(size)) {
185 (void) write(1, "\2", 1);
186 continue;
187 }
666561d4
KM
188 strcpy(dfname, cp);
189 (void) readfile(dfname, size);
e3127271
RC
190 continue;
191 }
47f0387b 192 frecverr("protocol screwup");
e3127271
RC
193 }
194}
195
196/*
197 * Read files send by lpd and copy them to the spooling directory.
198 */
199readfile(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
adec4d9e 208 fd = open(file, O_WRONLY|O_CREAT, FILMOD);
e3127271 209 if (fd < 0)
47f0387b 210 frecverr("%s: %m", file);
e3127271
RC
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)
47f0387b 221 frecverr("Lost connection");
e3127271
RC
222 amt -= j;
223 cp += j;
224 } while (amt > 0);
225 amt = BUFSIZ;
226 if (i + amt > size)
227 amt = size - i;
c6d1c018 228 if (write(fd, buf, amt) != amt) {
e3127271 229 err++;
c6d1c018
RC
230 break;
231 }
e3127271
RC
232 }
233 (void) close(fd);
234 if (err)
47f0387b 235 frecverr("%s: write error", file);
e3127271
RC
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
e3127271
RC
244noresponse()
245{
246 char resp;
247
248 if (read(1, &resp, 1) != 1)
47f0387b 249 frecverr("Lost connection");
e3127271
RC
250 if (resp == '\0')
251 return(0);
252 return(1);
253}
254
47f0387b
RC
255/*
256 * Check to see if there is enough space on the disk for size bytes.
257 * 1 == OK, 0 == Not OK.
258 */
259chksize(size)
260 int size;
261{
262 struct stat stb;
263 register char *ddev;
264 int spacefree;
265 struct fs fs;
266
6d011afb 267 if (dfd < 0 || lseek(dfd, (long)(SBOFF), 0) < 0)
47f0387b
RC
268 return(1);
269 if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
270 return(1);
6d011afb 271 spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 1024;
47f0387b
RC
272 size = (size + 1023) / 1024;
273 if (minfree + size > spacefree)
274 return(0);
275 return(1);
276}
277
278read_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
e3127271
RC
294/*
295 * Remove all the files associated with the current job being transfered.
296 */
47f0387b 297rcleanup()
e3127271 298{
e3127271
RC
299
300 if (tfname[0])
301 (void) unlink(tfname);
666561d4 302 if (dfname[0])
e3127271
RC
303 do {
304 do
305 (void) unlink(dfname);
0b551c43
RC
306 while (dfname[2]-- != 'A');
307 dfname[2] = 'z';
308 } while (dfname[0]-- != 'd');
666561d4 309 dfname[0] = '\0';
e3127271
RC
310}
311
47f0387b 312frecverr(msg, a1, a2)
e3127271
RC
313 char *msg;
314{
47f0387b
RC
315 rcleanup();
316 syslog(LOG_ERR, msg, a1, a2);
e3127271
RC
317 putchar('\1'); /* return error code */
318 exit(1);
319}