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