add ufs_check_export
[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 *
c61e0514
EA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
d0aeaf5a
DF
32 */
33
5f84f8f0 34#ifndef lint
c61e0514 35static char sccsid[] = "@(#)recvjob.c 5.18 (Berkeley) 8/6/92";
9d85c861 36#endif /* not lint */
5f84f8f0 37
e3127271
RC
38/*
39 * Receive printer jobs from the network, queue them and
40 * start the printer daemon.
41 */
34c0890f
KB
42#include <sys/param.h>
43#include <sys/mount.h>
44#include <sys/stat.h>
e3127271 45
c61e0514 46#include <unistd.h>
34c0890f
KB
47#include <signal.h>
48#include <fcntl.h>
49#include <dirent.h>
50#include <syslog.h>
51#include <stdio.h>
c61e0514
EA
52#include <stdlib.h>
53#include <string.h>
e3127271 54#include "lp.h"
34c0890f
KB
55#include "lp.local.h"
56#include "extern.h"
7abf8d65 57#include "pathnames.h"
e3127271 58
47f0387b
RC
59#define ack() (void) write(1, sp, 1);
60
c61e0514
EA
61static char dfname[40]; /* data files */
62static int minfree; /* keep at least minfree blocks available */
63static char *sp = "";
64static char tfname[40]; /* tmp copy of cf before linking */
47f0387b 65
34c0890f
KB
66static int chksize __P((int));
67static void frecverr __P((const char *, ...));
c61e0514 68static int noresponse __P((void));
34c0890f 69static void rcleanup __P((int));
c61e0514
EA
70static int read_number __P((char *));
71static int readfile __P((char *, int));
72static int readjob __P((void));
34c0890f 73
e3127271 74
c61e0514 75void
e3127271
RC
76recvjob()
77{
88f026f7 78 struct stat stb;
b681f416 79 int status;
e3127271 80
e3127271
RC
81 /*
82 * Perform lookup for printer name or abbreviation
83 */
c61e0514 84 if ((status = cgetent(&bp, printcapdb, printer)) == -2)
47f0387b 85 frecverr("cannot open printer description file");
c61e0514 86 else if (status == -1)
47f0387b 87 frecverr("unknown printer %s", printer);
c61e0514
EA
88 else if (status == -3)
89 fatal("potential reference loop detected in printcap file");
90
91 if (cgetstr(bp, "lf", &LF) == -1)
7abf8d65 92 LF = _PATH_CONSOLE;
c61e0514 93 if (cgetstr(bp, "sd", &SD) == -1)
7abf8d65 94 SD = _PATH_DEFSPOOL;
c61e0514 95 if (cgetstr(bp, "lo", &LO) == -1)
88f026f7 96 LO = DEFLOCK;
e3127271 97
4e7bc1ec
EA
98 (void) close(2); /* set up log file */
99 if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
100 syslog(LOG_ERR, "%s: %m", LF);
7abf8d65 101 (void) open(_PATH_DEVNULL, O_WRONLY);
4e7bc1ec
EA
102 }
103
e3127271 104 if (chdir(SD) < 0)
47f0387b
RC
105 frecverr("%s: %s: %m", printer, SD);
106 if (stat(LO, &stb) == 0) {
107 if (stb.st_mode & 010) {
108 /* queue is disabled */
109 putchar('\1'); /* return error code */
110 exit(1);
111 }
112 } else if (stat(SD, &stb) < 0)
113 frecverr("%s: %s: %m", printer, SD);
40192b67 114 minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
47f0387b
RC
115 signal(SIGTERM, rcleanup);
116 signal(SIGPIPE, rcleanup);
e3127271
RC
117
118 if (readjob())
119 printjob();
120}
121
e3127271
RC
122/*
123 * Read printer jobs sent by lpd and copy them to the spooling directory.
124 * Return the number of jobs successfully transfered.
125 */
34c0890f 126static int
47f0387b 127readjob()
e3127271
RC
128{
129 register int size, nfiles;
130 register char *cp;
131
132 ack();
133 nfiles = 0;
134 for (;;) {
135 /*
136 * Read a command to tell us what to do
137 */
138 cp = line;
139 do {
140 if ((size = read(1, cp, 1)) != 1) {
141 if (size < 0)
47f0387b 142 frecverr("%s: Lost connection",printer);
e3127271
RC
143 return(nfiles);
144 }
145 } while (*cp++ != '\n');
146 *--cp = '\0';
147 cp = line;
148 switch (*cp++) {
149 case '\1': /* cleanup because data sent was bad */
34c0890f 150 rcleanup(0);
e3127271
RC
151 continue;
152
153 case '\2': /* read cf file */
154 size = 0;
155 while (*cp >= '0' && *cp <= '9')
156 size = size * 10 + (*cp++ - '0');
157 if (*cp++ != ' ')
158 break;
dda5ffcd
JB
159 /*
160 * host name has been authenticated, we use our
161 * view of the host name since we may be passed
162 * something different than what gethostbyaddr()
163 * returns
164 */
165 strcpy(cp + 6, from);
e3127271
RC
166 strcpy(tfname, cp);
167 tfname[0] = 't';
47f0387b
RC
168 if (!chksize(size)) {
169 (void) write(1, "\2", 1);
170 continue;
171 }
e3127271 172 if (!readfile(tfname, size)) {
34c0890f 173 rcleanup(0);
e3127271
RC
174 continue;
175 }
176 if (link(tfname, cp) < 0)
47f0387b 177 frecverr("%s: %m", tfname);
e3127271
RC
178 (void) unlink(tfname);
179 tfname[0] = '\0';
180 nfiles++;
181 continue;
182
183 case '\3': /* read df file */
184 size = 0;
185 while (*cp >= '0' && *cp <= '9')
186 size = size * 10 + (*cp++ - '0');
187 if (*cp++ != ' ')
188 break;
47f0387b
RC
189 if (!chksize(size)) {
190 (void) write(1, "\2", 1);
191 continue;
192 }
3066c9a6
KB
193 (void) strcpy(dfname, cp);
194 if (index(dfname, '/'))
c3c382e9
KM
195 frecverr("readjob: %s: illegal path name",
196 dfname);
666561d4 197 (void) readfile(dfname, size);
e3127271
RC
198 continue;
199 }
47f0387b 200 frecverr("protocol screwup");
e3127271
RC
201 }
202}
203
204/*
205 * Read files send by lpd and copy them to the spooling directory.
206 */
34c0890f 207static int
e3127271
RC
208readfile(file, size)
209 char *file;
210 int size;
211{
212 register char *cp;
213 char buf[BUFSIZ];
214 register int i, j, amt;
215 int fd, err;
216
40192b67 217 fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
e3127271 218 if (fd < 0)
c3c382e9 219 frecverr("readfile: %s: illegal path name: %m", file);
e3127271
RC
220 ack();
221 err = 0;
222 for (i = 0; i < size; i += BUFSIZ) {
223 amt = BUFSIZ;
224 cp = buf;
225 if (i + amt > size)
226 amt = size - i;
227 do {
228 j = read(1, cp, amt);
229 if (j <= 0)
47f0387b 230 frecverr("Lost connection");
e3127271
RC
231 amt -= j;
232 cp += j;
233 } while (amt > 0);
234 amt = BUFSIZ;
235 if (i + amt > size)
236 amt = size - i;
c6d1c018 237 if (write(fd, buf, amt) != amt) {
e3127271 238 err++;
c6d1c018
RC
239 break;
240 }
e3127271
RC
241 }
242 (void) close(fd);
243 if (err)
47f0387b 244 frecverr("%s: write error", file);
e3127271
RC
245 if (noresponse()) { /* file sent had bad data in it */
246 (void) unlink(file);
247 return(0);
248 }
249 ack();
250 return(1);
251}
252
34c0890f 253static int
e3127271
RC
254noresponse()
255{
256 char resp;
257
258 if (read(1, &resp, 1) != 1)
47f0387b 259 frecverr("Lost connection");
e3127271
RC
260 if (resp == '\0')
261 return(0);
262 return(1);
263}
264
47f0387b
RC
265/*
266 * Check to see if there is enough space on the disk for size bytes.
267 * 1 == OK, 0 == Not OK.
268 */
34c0890f 269static int
47f0387b
RC
270chksize(size)
271 int size;
272{
47f0387b 273 int spacefree;
40192b67 274 struct statfs sfb;
47f0387b 275
40192b67
KM
276 if (statfs(".", &sfb) < 0) {
277 syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
278 return (1);
279 }
78c3ee49 280 spacefree = sfb.f_bavail * (sfb.f_bsize / 512);
40192b67 281 size = (size + 511) / 512;
47f0387b
RC
282 if (minfree + size > spacefree)
283 return(0);
284 return(1);
285}
286
34c0890f 287static int
47f0387b
RC
288read_number(fn)
289 char *fn;
290{
291 char lin[80];
292 register FILE *fp;
293
294 if ((fp = fopen(fn, "r")) == NULL)
295 return (0);
296 if (fgets(lin, 80, fp) == NULL) {
297 fclose(fp);
298 return (0);
299 }
300 fclose(fp);
301 return (atoi(lin));
302}
303
e3127271
RC
304/*
305 * Remove all the files associated with the current job being transfered.
306 */
34c0890f
KB
307static void
308rcleanup(signo)
309 int signo;
e3127271 310{
e3127271
RC
311 if (tfname[0])
312 (void) unlink(tfname);
666561d4 313 if (dfname[0])
e3127271
RC
314 do {
315 do
316 (void) unlink(dfname);
0b551c43
RC
317 while (dfname[2]-- != 'A');
318 dfname[2] = 'z';
319 } while (dfname[0]-- != 'd');
666561d4 320 dfname[0] = '\0';
e3127271
RC
321}
322
34c0890f
KB
323#if __STDC__
324#include <stdarg.h>
325#else
326#include <varargs.h>
327#endif
328
329static void
330#if __STDC__
331frecverr(const char *msg, ...)
332#else
333frecverr(msg, va_alist)
e3127271 334 char *msg;
34c0890f
KB
335 va_dcl
336#endif
e3127271 337{
34c0890f
KB
338 va_list ap;
339#if __STDC__
340 va_start(ap, msg);
341#else
342 va_start(ap);
343#endif
344 rcleanup(0);
345 vsyslog(LOG_ERR, msg, ap);
346 va_end(ap);
e3127271
RC
347 putchar('\1'); /* return error code */
348 exit(1);
349}