syscons util remove use kbdcontrol & vidcontrol instead
[unix-history] / usr.sbin / lpr / lpd / recvjob.c
CommitLineData
15637ed4
RG
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, 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.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)recvjob.c 5.15 (Berkeley) 5/4/91";
36#endif /* not lint */
37
38/*
39 * Receive printer jobs from the network, queue them and
40 * start the printer daemon.
41 */
42
43#include "lp.h"
44#include "pathnames.h"
45#include <sys/mount.h>
46
47char *sp = "";
48#define ack() (void) write(1, sp, 1);
49
50char tfname[40]; /* tmp copy of cf before linking */
51char dfname[40]; /* data files */
52int minfree; /* keep at least minfree blocks available */
53
54void rcleanup();
55
56recvjob()
57{
58 struct stat stb;
59 char *bp = pbuf;
60 int status;
61
62 /*
63 * Perform lookup for printer name or abbreviation
64 */
65 if ((status = pgetent(line, printer)) < 0)
66 frecverr("cannot open printer description file");
67 else if (status == 0)
68 frecverr("unknown printer %s", printer);
69 if ((LF = pgetstr("lf", &bp)) == NULL)
70 LF = _PATH_CONSOLE;
71 if ((SD = pgetstr("sd", &bp)) == NULL)
72 SD = _PATH_DEFSPOOL;
73 if ((LO = pgetstr("lo", &bp)) == NULL)
74 LO = DEFLOCK;
75
76 (void) close(2); /* set up log file */
77 if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
78 syslog(LOG_ERR, "%s: %m", LF);
79 (void) open(_PATH_DEVNULL, O_WRONLY);
80 }
81
82 if (chdir(SD) < 0)
83 frecverr("%s: %s: %m", printer, SD);
84 if (stat(LO, &stb) == 0) {
85 if (stb.st_mode & 010) {
86 /* queue is disabled */
87 putchar('\1'); /* return error code */
88 exit(1);
89 }
90 } else if (stat(SD, &stb) < 0)
91 frecverr("%s: %s: %m", printer, SD);
92 minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
93 signal(SIGTERM, rcleanup);
94 signal(SIGPIPE, rcleanup);
95
96 if (readjob())
97 printjob();
98}
99
100/*
101 * Read printer jobs sent by lpd and copy them to the spooling directory.
102 * Return the number of jobs successfully transfered.
103 */
104readjob()
105{
106 register int size, nfiles;
107 register char *cp;
108
109 ack();
110 nfiles = 0;
111 for (;;) {
112 /*
113 * Read a command to tell us what to do
114 */
115 cp = line;
116 do {
117 if ((size = read(1, cp, 1)) != 1) {
118 if (size < 0)
119 frecverr("%s: Lost connection",printer);
120 return(nfiles);
121 }
122 } while (*cp++ != '\n');
123 *--cp = '\0';
124 cp = line;
125 switch (*cp++) {
126 case '\1': /* cleanup because data sent was bad */
127 rcleanup();
128 continue;
129
130 case '\2': /* read cf file */
131 size = 0;
132 while (*cp >= '0' && *cp <= '9')
133 size = size * 10 + (*cp++ - '0');
134 if (*cp++ != ' ')
135 break;
136 /*
137 * host name has been authenticated, we use our
138 * view of the host name since we may be passed
139 * something different than what gethostbyaddr()
140 * returns
141 */
142 strcpy(cp + 6, from);
143 strcpy(tfname, cp);
144 tfname[0] = 't';
145 if (!chksize(size)) {
146 (void) write(1, "\2", 1);
147 continue;
148 }
149 if (!readfile(tfname, size)) {
150 rcleanup();
151 continue;
152 }
153 if (link(tfname, cp) < 0)
154 frecverr("%s: %m", tfname);
155 (void) unlink(tfname);
156 tfname[0] = '\0';
157 nfiles++;
158 continue;
159
160 case '\3': /* read df file */
161 size = 0;
162 while (*cp >= '0' && *cp <= '9')
163 size = size * 10 + (*cp++ - '0');
164 if (*cp++ != ' ')
165 break;
166 if (!chksize(size)) {
167 (void) write(1, "\2", 1);
168 continue;
169 }
170 (void) strcpy(dfname, cp);
171 if (index(dfname, '/'))
172 frecverr("readjob: %s: illegal path name",
173 dfname);
174 (void) readfile(dfname, size);
175 continue;
176 }
177 frecverr("protocol screwup");
178 }
179}
180
181/*
182 * Read files send by lpd and copy them to the spooling directory.
183 */
184readfile(file, size)
185 char *file;
186 int size;
187{
188 register char *cp;
189 char buf[BUFSIZ];
190 register int i, j, amt;
191 int fd, err;
192
193 fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
194 if (fd < 0)
195 frecverr("readfile: %s: illegal path name: %m", file);
196 ack();
197 err = 0;
198 for (i = 0; i < size; i += BUFSIZ) {
199 amt = BUFSIZ;
200 cp = buf;
201 if (i + amt > size)
202 amt = size - i;
203 do {
204 j = read(1, cp, amt);
205 if (j <= 0)
206 frecverr("Lost connection");
207 amt -= j;
208 cp += j;
209 } while (amt > 0);
210 amt = BUFSIZ;
211 if (i + amt > size)
212 amt = size - i;
213 if (write(fd, buf, amt) != amt) {
214 err++;
215 break;
216 }
217 }
218 (void) close(fd);
219 if (err)
220 frecverr("%s: write error", file);
221 if (noresponse()) { /* file sent had bad data in it */
222 (void) unlink(file);
223 return(0);
224 }
225 ack();
226 return(1);
227}
228
229noresponse()
230{
231 char resp;
232
233 if (read(1, &resp, 1) != 1)
234 frecverr("Lost connection");
235 if (resp == '\0')
236 return(0);
237 return(1);
238}
239
240/*
241 * Check to see if there is enough space on the disk for size bytes.
242 * 1 == OK, 0 == Not OK.
243 */
244chksize(size)
245 int size;
246{
247 int spacefree;
248 struct statfs sfb;
249
250 if (statfs(".", &sfb) < 0) {
251 syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
252 return (1);
253 }
254 spacefree = sfb.f_bavail * (sfb.f_fsize / 512);
255 size = (size + 511) / 512;
256 if (minfree + size > spacefree)
257 return(0);
258 return(1);
259}
260
261read_number(fn)
262 char *fn;
263{
264 char lin[80];
265 register FILE *fp;
266
267 if ((fp = fopen(fn, "r")) == NULL)
268 return (0);
269 if (fgets(lin, 80, fp) == NULL) {
270 fclose(fp);
271 return (0);
272 }
273 fclose(fp);
274 return (atoi(lin));
275}
276
277/*
278 * Remove all the files associated with the current job being transfered.
279 */
280void
281rcleanup()
282{
283
284 if (tfname[0])
285 (void) unlink(tfname);
286 if (dfname[0])
287 do {
288 do
289 (void) unlink(dfname);
290 while (dfname[2]-- != 'A');
291 dfname[2] = 'z';
292 } while (dfname[0]-- != 'd');
293 dfname[0] = '\0';
294}
295
296frecverr(msg, a1, a2)
297 char *msg;
298{
299 rcleanup();
300 syslog(LOG_ERR, msg, a1, a2);
301 putchar('\1'); /* return error code */
302 exit(1);
303}