add hostname to recvjob screwup message, print out messed up line
[unix-history] / usr / src / usr.sbin / lpr / lpd / recvjob.c
CommitLineData
d0aeaf5a 1/*
c13032d6 2 * Copyright (c) 1983 The Regents of the University of California.
9d85c861
KB
3 * All rights reserved.
4 *
c61e0514 5 *
c13032d6 6 * %sccs.include.redist.c%
d0aeaf5a
DF
7 */
8
5f84f8f0 9#ifndef lint
2e709bb2 10static char copyright[] =
c13032d6
EA
11"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
12 All rights reserved.\n";
13#endif /* not lint */
14
15#ifndef lint
1d3cf5d3 16static char sccsid[] = "@(#)recvjob.c 5.21 (Berkeley) %G%";
9d85c861 17#endif /* not lint */
5f84f8f0 18
e3127271
RC
19/*
20 * Receive printer jobs from the network, queue them and
21 * start the printer daemon.
22 */
34c0890f
KB
23#include <sys/param.h>
24#include <sys/mount.h>
25#include <sys/stat.h>
e3127271 26
c61e0514 27#include <unistd.h>
34c0890f
KB
28#include <signal.h>
29#include <fcntl.h>
30#include <dirent.h>
31#include <syslog.h>
32#include <stdio.h>
c61e0514
EA
33#include <stdlib.h>
34#include <string.h>
e3127271 35#include "lp.h"
34c0890f
KB
36#include "lp.local.h"
37#include "extern.h"
7abf8d65 38#include "pathnames.h"
e3127271 39
47f0387b
RC
40#define ack() (void) write(1, sp, 1);
41
c61e0514
EA
42static char dfname[40]; /* data files */
43static int minfree; /* keep at least minfree blocks available */
44static char *sp = "";
45static char tfname[40]; /* tmp copy of cf before linking */
47f0387b 46
34c0890f
KB
47static int chksize __P((int));
48static void frecverr __P((const char *, ...));
c61e0514 49static int noresponse __P((void));
34c0890f 50static void rcleanup __P((int));
c61e0514
EA
51static int read_number __P((char *));
52static int readfile __P((char *, int));
53static int readjob __P((void));
34c0890f 54
e3127271 55
c61e0514 56void
e3127271
RC
57recvjob()
58{
88f026f7 59 struct stat stb;
b681f416 60 int status;
e3127271 61
e3127271
RC
62 /*
63 * Perform lookup for printer name or abbreviation
64 */
c61e0514 65 if ((status = cgetent(&bp, printcapdb, printer)) == -2)
47f0387b 66 frecverr("cannot open printer description file");
c61e0514 67 else if (status == -1)
47f0387b 68 frecverr("unknown printer %s", printer);
c61e0514
EA
69 else if (status == -3)
70 fatal("potential reference loop detected in printcap file");
71
72 if (cgetstr(bp, "lf", &LF) == -1)
7abf8d65 73 LF = _PATH_CONSOLE;
c61e0514 74 if (cgetstr(bp, "sd", &SD) == -1)
7abf8d65 75 SD = _PATH_DEFSPOOL;
c61e0514 76 if (cgetstr(bp, "lo", &LO) == -1)
88f026f7 77 LO = DEFLOCK;
e3127271 78
4e7bc1ec
EA
79 (void) close(2); /* set up log file */
80 if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
81 syslog(LOG_ERR, "%s: %m", LF);
7abf8d65 82 (void) open(_PATH_DEVNULL, O_WRONLY);
4e7bc1ec
EA
83 }
84
e3127271 85 if (chdir(SD) < 0)
47f0387b
RC
86 frecverr("%s: %s: %m", printer, SD);
87 if (stat(LO, &stb) == 0) {
88 if (stb.st_mode & 010) {
89 /* queue is disabled */
90 putchar('\1'); /* return error code */
91 exit(1);
92 }
93 } else if (stat(SD, &stb) < 0)
94 frecverr("%s: %s: %m", printer, SD);
40192b67 95 minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */
47f0387b
RC
96 signal(SIGTERM, rcleanup);
97 signal(SIGPIPE, rcleanup);
e3127271
RC
98
99 if (readjob())
100 printjob();
101}
102
e3127271
RC
103/*
104 * Read printer jobs sent by lpd and copy them to the spooling directory.
105 * Return the number of jobs successfully transfered.
106 */
34c0890f 107static int
47f0387b 108readjob()
e3127271
RC
109{
110 register int size, nfiles;
111 register char *cp;
112
113 ack();
114 nfiles = 0;
115 for (;;) {
116 /*
117 * Read a command to tell us what to do
118 */
119 cp = line;
120 do {
121 if ((size = read(1, cp, 1)) != 1) {
122 if (size < 0)
47f0387b 123 frecverr("%s: Lost connection",printer);
e3127271
RC
124 return(nfiles);
125 }
126 } while (*cp++ != '\n');
127 *--cp = '\0';
128 cp = line;
129 switch (*cp++) {
130 case '\1': /* cleanup because data sent was bad */
34c0890f 131 rcleanup(0);
e3127271
RC
132 continue;
133
134 case '\2': /* read cf file */
135 size = 0;
136 while (*cp >= '0' && *cp <= '9')
137 size = size * 10 + (*cp++ - '0');
138 if (*cp++ != ' ')
139 break;
dda5ffcd
JB
140 /*
141 * host name has been authenticated, we use our
142 * view of the host name since we may be passed
143 * something different than what gethostbyaddr()
144 * returns
145 */
146 strcpy(cp + 6, from);
e3127271
RC
147 strcpy(tfname, cp);
148 tfname[0] = 't';
47f0387b
RC
149 if (!chksize(size)) {
150 (void) write(1, "\2", 1);
151 continue;
152 }
e3127271 153 if (!readfile(tfname, size)) {
34c0890f 154 rcleanup(0);
e3127271
RC
155 continue;
156 }
157 if (link(tfname, cp) < 0)
47f0387b 158 frecverr("%s: %m", tfname);
e3127271
RC
159 (void) unlink(tfname);
160 tfname[0] = '\0';
161 nfiles++;
162 continue;
163
164 case '\3': /* read df file */
165 size = 0;
166 while (*cp >= '0' && *cp <= '9')
167 size = size * 10 + (*cp++ - '0');
168 if (*cp++ != ' ')
169 break;
47f0387b
RC
170 if (!chksize(size)) {
171 (void) write(1, "\2", 1);
172 continue;
173 }
3066c9a6
KB
174 (void) strcpy(dfname, cp);
175 if (index(dfname, '/'))
c3c382e9
KM
176 frecverr("readjob: %s: illegal path name",
177 dfname);
666561d4 178 (void) readfile(dfname, size);
e3127271
RC
179 continue;
180 }
1d3cf5d3 181 frecverr("protocol screwup: %s", line);
e3127271
RC
182 }
183}
184
185/*
186 * Read files send by lpd and copy them to the spooling directory.
187 */
34c0890f 188static int
e3127271
RC
189readfile(file, size)
190 char *file;
191 int size;
192{
193 register char *cp;
194 char buf[BUFSIZ];
195 register int i, j, amt;
196 int fd, err;
197
40192b67 198 fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD);
e3127271 199 if (fd < 0)
c3c382e9 200 frecverr("readfile: %s: illegal path name: %m", file);
e3127271
RC
201 ack();
202 err = 0;
203 for (i = 0; i < size; i += BUFSIZ) {
204 amt = BUFSIZ;
205 cp = buf;
206 if (i + amt > size)
207 amt = size - i;
208 do {
209 j = read(1, cp, amt);
210 if (j <= 0)
47f0387b 211 frecverr("Lost connection");
e3127271
RC
212 amt -= j;
213 cp += j;
214 } while (amt > 0);
215 amt = BUFSIZ;
216 if (i + amt > size)
217 amt = size - i;
c6d1c018 218 if (write(fd, buf, amt) != amt) {
e3127271 219 err++;
c6d1c018
RC
220 break;
221 }
e3127271
RC
222 }
223 (void) close(fd);
224 if (err)
47f0387b 225 frecverr("%s: write error", file);
e3127271
RC
226 if (noresponse()) { /* file sent had bad data in it */
227 (void) unlink(file);
228 return(0);
229 }
230 ack();
231 return(1);
232}
233
34c0890f 234static int
e3127271
RC
235noresponse()
236{
237 char resp;
238
239 if (read(1, &resp, 1) != 1)
47f0387b 240 frecverr("Lost connection");
e3127271
RC
241 if (resp == '\0')
242 return(0);
243 return(1);
244}
245
47f0387b
RC
246/*
247 * Check to see if there is enough space on the disk for size bytes.
248 * 1 == OK, 0 == Not OK.
249 */
34c0890f 250static int
47f0387b
RC
251chksize(size)
252 int size;
253{
47f0387b 254 int spacefree;
40192b67 255 struct statfs sfb;
47f0387b 256
40192b67
KM
257 if (statfs(".", &sfb) < 0) {
258 syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
259 return (1);
260 }
78c3ee49 261 spacefree = sfb.f_bavail * (sfb.f_bsize / 512);
40192b67 262 size = (size + 511) / 512;
47f0387b
RC
263 if (minfree + size > spacefree)
264 return(0);
265 return(1);
266}
267
34c0890f 268static int
47f0387b
RC
269read_number(fn)
270 char *fn;
271{
272 char lin[80];
273 register FILE *fp;
274
275 if ((fp = fopen(fn, "r")) == NULL)
276 return (0);
277 if (fgets(lin, 80, fp) == NULL) {
278 fclose(fp);
279 return (0);
280 }
281 fclose(fp);
282 return (atoi(lin));
283}
284
e3127271
RC
285/*
286 * Remove all the files associated with the current job being transfered.
287 */
34c0890f
KB
288static void
289rcleanup(signo)
290 int signo;
e3127271 291{
e3127271
RC
292 if (tfname[0])
293 (void) unlink(tfname);
666561d4 294 if (dfname[0])
e3127271
RC
295 do {
296 do
297 (void) unlink(dfname);
0b551c43
RC
298 while (dfname[2]-- != 'A');
299 dfname[2] = 'z';
300 } while (dfname[0]-- != 'd');
666561d4 301 dfname[0] = '\0';
e3127271
RC
302}
303
34c0890f
KB
304#if __STDC__
305#include <stdarg.h>
306#else
307#include <varargs.h>
308#endif
309
310static void
311#if __STDC__
312frecverr(const char *msg, ...)
313#else
314frecverr(msg, va_alist)
e3127271 315 char *msg;
34c0890f
KB
316 va_dcl
317#endif
e3127271 318{
1d3cf5d3 319 extern char *fromb;
34c0890f
KB
320 va_list ap;
321#if __STDC__
322 va_start(ap, msg);
323#else
324 va_start(ap);
325#endif
326 rcleanup(0);
1d3cf5d3 327 syslog(LOG_ERR, "%s", fromb);
34c0890f
KB
328 vsyslog(LOG_ERR, msg, ap);
329 va_end(ap);
e3127271
RC
330 putchar('\1'); /* return error code */
331 exit(1);
332}