1 /* $NetBSD: recvjob.c,v 1.21 2008/07/21 13:36:58 lukem Exp $ */
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
36 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
37 The Regents of the University of California. All rights reserved.");
42 static char sccsid
[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95";
44 __RCSID("$NetBSD: recvjob.c,v 1.21 2008/07/21 13:36:58 lukem Exp $");
49 * Receive printer jobs from the network, queue them and
50 * start the printer daemon.
52 #include <sys/param.h>
53 #include <sys/mount.h>
67 #include "pathnames.h"
69 #define ack() (void)write(STDOUT_FILENO, sp, 1);
71 static char dfname
[NAME_MAX
]; /* data files */
72 static int minfree
; /* keep at least minfree blocks available */
73 static const char *sp
= "";
74 static char tfname
[NAME_MAX
]; /* tmp copy of cf before linking */
76 static int chksize(int);
77 static void frecverr(const char *, ...)
78 __attribute__((__format__(__printf__
, 1, 2)));
79 static int noresponse(void);
80 static void rcleanup(int);
81 static int read_number(const char *);
82 static int readfile(char *, int);
83 static int readjob(void);
93 /* Set up the log file. */
94 if ((fd
= open(LF
, O_WRONLY
|O_APPEND
, 0664)) < 0) {
95 syslog(LOG_ERR
, "%s: %m", LF
);
96 fd
= open(_PATH_DEVNULL
, O_WRONLY
);
99 (void) dup2(fd
, STDERR_FILENO
);
102 (void) close(STDERR_FILENO
);
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 */
112 } else if (stat(SD
, &stb
) < 0)
113 frecverr("%s: %s: %m", printer
, SD
);
114 minfree
= 2 * read_number("minfree"); /* scale KB to 512 blocks */
115 signal(SIGTERM
, rcleanup
);
116 signal(SIGPIPE
, rcleanup
);
123 * Read printer jobs sent by lpd and copy them to the spooling directory.
124 * Return the number of jobs successfully transfered.
136 * Read a command to tell us what to do
140 if ((size
= read(STDOUT_FILENO
, cp
, 1)) != 1) {
142 frecverr("%s: Lost connection",
146 } while (*cp
++ != '\n' && (size_t)(cp
- line
+ 1) < sizeof(line
));
147 if ((size_t)(cp
- line
+ 1) >= sizeof(line
))
148 frecverr("readjob overflow");
152 case '\1': /* cleanup because data sent was bad */
156 case '\2': /* read cf file */
158 while (*cp
>= '0' && *cp
<= '9')
159 size
= size
* 10 + (*cp
++ - '0');
163 * host name has been authenticated, we use our
164 * view of the host name since we may be passed
165 * something different than what gethostbyaddr()
168 (void)strlcpy(cp
+ 6, from
,
169 sizeof(line
) + line
- cp
- 6);
171 frecverr("readjob: %s: illegal path name", cp
);
172 (void)strlcpy(tfname
, cp
, sizeof(tfname
));
174 if (!chksize(size
)) {
175 (void)write(STDOUT_FILENO
, "\2", 1);
178 if (!readfile(tfname
, size
)) {
182 if (link(tfname
, cp
) < 0)
183 frecverr("%s: %m", tfname
);
184 (void)unlink(tfname
);
189 case '\3': /* read df file */
191 while (*cp
>= '0' && *cp
<= '9')
192 size
= size
* 10 + (*cp
++ - '0');
195 if (!chksize(size
)) {
196 (void)write(STDOUT_FILENO
, "\2", 1);
200 frecverr("readjob: %s: illegal path name", cp
);
201 (void)strlcpy(dfname
, cp
, sizeof(dfname
));
202 (void)readfile(dfname
, size
);
205 frecverr("protocol screwup: %s", line
);
210 * Read files send by lpd and copy them to the spooling directory.
213 readfile(char *file
, int size
)
220 fd
= open(file
, O_CREAT
|O_EXCL
|O_WRONLY
, FILMOD
);
222 frecverr("readfile: %s: illegal path name: %m", file
);
225 for (i
= 0; i
< size
; i
+= BUFSIZ
) {
231 j
= read(STDOUT_FILENO
, cp
, amt
);
233 frecverr("Lost connection");
240 if (write(fd
, buf
, amt
) != amt
) {
247 frecverr("%s: write error", file
);
248 if (noresponse()) { /* file sent had bad data in it */
261 if (read(STDOUT_FILENO
, &resp
, 1) != 1)
262 frecverr("Lost connection");
269 * Check to see if there is enough space on the disk for size bytes.
270 * 1 == OK, 0 == Not OK.
278 if (statvfs(".", &sfb
) < 0) {
279 syslog(LOG_ERR
, "%s: %m", "statfs(\".\")");
282 spacefree
= sfb
.f_bavail
* (sfb
.f_frsize
/ 512);
283 size
= (size
+ 511) / 512;
284 if (minfree
+ size
> spacefree
)
290 read_number(const char *fn
)
295 if ((fp
= fopen(fn
, "r")) == NULL
)
297 if (fgets(lin
, 80, fp
) == NULL
) {
306 * Remove all the files associated with the current job being transfered.
312 (void)unlink(tfname
);
316 if (strchr(dfname
, '/') == 0)
317 (void)unlink(dfname
);
318 } while (dfname
[2]-- != 'A');
320 } while (dfname
[0]-- != 'd');
327 frecverr(const char *msg
, ...)
334 syslog(LOG_ERR
, "%s", fromb
);
335 vsyslog(LOG_ERR
, msg
, ap
);
337 putchar('\1'); /* return error code */