initialize loop variable
[unix-history] / usr / src / usr.sbin / lpr / lpd / recvjob.c
CommitLineData
5f84f8f0 1#ifndef lint
84f9c0d8 2static char sccsid[] = "@(#)recvjob.c 4.8 (Berkeley) %G%";
5f84f8f0
SL
3#endif
4
e3127271
RC
5/*
6 * Receive printer jobs from the network, queue them and
7 * start the printer daemon.
8 */
9
10#include "lp.h"
47f0387b 11#include <sys/fs.h>
e3127271 12
47f0387b
RC
13char *sp = "";
14#define ack() (void) write(1, sp, 1);
15
16char tfname[40]; /* tmp copy of cf before linking */
17char *dfname; /* data files */
18int minfree; /* keep at least minfree blocks available */
19char *ddev; /* disk device (for checking free space) */
20int dfd; /* file system device descriptor */
21
22char *find_dev();
e3127271
RC
23
24recvjob()
25{
88f026f7 26 struct stat stb;
e3127271 27 char *bp = pbuf;
47f0387b 28 int status, rcleanup();
e3127271 29
e3127271
RC
30 /*
31 * Perform lookup for printer name or abbreviation
32 */
33 if ((status = pgetent(line, printer)) < 0)
47f0387b 34 frecverr("cannot open printer description file");
e3127271 35 else if (status == 0)
47f0387b 36 frecverr("unknown printer %s", printer);
e3127271
RC
37 if ((LF = pgetstr("lf", &bp)) == NULL)
38 LF = DEFLOGF;
39 if ((SD = pgetstr("sd", &bp)) == NULL)
40 SD = DEFSPOOL;
88f026f7
RC
41 if ((LO = pgetstr("lo", &bp)) == NULL)
42 LO = DEFLOCK;
e3127271 43
e3127271 44 if (chdir(SD) < 0)
47f0387b
RC
45 frecverr("%s: %s: %m", printer, SD);
46 if (stat(LO, &stb) == 0) {
47 if (stb.st_mode & 010) {
48 /* queue is disabled */
49 putchar('\1'); /* return error code */
50 exit(1);
51 }
52 } else if (stat(SD, &stb) < 0)
53 frecverr("%s: %s: %m", printer, SD);
54 minfree = read_number("minfree");
55 ddev = find_dev(stb.st_dev, S_IFBLK);
56 if ((dfd = open(ddev, O_RDONLY)) < 0)
57 syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
58 signal(SIGTERM, rcleanup);
59 signal(SIGPIPE, rcleanup);
e3127271
RC
60
61 if (readjob())
62 printjob();
63}
64
47f0387b
RC
65char *
66find_dev(dev, type)
67 register dev_t dev;
68 register int type;
69{
70 register DIR *dfd = opendir("/dev");
71 struct direct *dir;
72 struct stat stb;
73 char devname[MAXNAMLEN+6];
74 char *dp;
75
76 strcpy(devname, "/dev/");
77 while ((dir = readdir(dfd))) {
78 strcpy(devname + 5, dir->d_name);
79 if (stat(devname, &stb))
80 continue;
81 if ((stb.st_mode & S_IFMT) != type)
82 continue;
83 if (dev == stb.st_rdev) {
84 closedir(dfd);
85 dp = (char *)malloc(strlen(devname)+1);
86 strcpy(dp, devname);
87 return(dp);
88 }
89 }
90 closedir(dfd);
91 frecverr("cannot find device %d, %d", major(dev), minor(dev));
92 /*NOTREACHED*/
93}
e3127271
RC
94
95/*
96 * Read printer jobs sent by lpd and copy them to the spooling directory.
97 * Return the number of jobs successfully transfered.
98 */
47f0387b 99readjob()
e3127271
RC
100{
101 register int size, nfiles;
102 register char *cp;
103
104 ack();
105 nfiles = 0;
106 for (;;) {
107 /*
108 * Read a command to tell us what to do
109 */
110 cp = line;
111 do {
112 if ((size = read(1, cp, 1)) != 1) {
113 if (size < 0)
47f0387b 114 frecverr("%s: Lost connection",printer);
e3127271
RC
115 return(nfiles);
116 }
117 } while (*cp++ != '\n');
118 *--cp = '\0';
119 cp = line;
120 switch (*cp++) {
121 case '\1': /* cleanup because data sent was bad */
47f0387b 122 rcleanup();
e3127271
RC
123 continue;
124
125 case '\2': /* read cf file */
126 size = 0;
127 while (*cp >= '0' && *cp <= '9')
128 size = size * 10 + (*cp++ - '0');
129 if (*cp++ != ' ')
130 break;
131 strcpy(tfname, cp);
132 tfname[0] = 't';
47f0387b
RC
133 if (!chksize(size)) {
134 (void) write(1, "\2", 1);
135 continue;
136 }
e3127271 137 if (!readfile(tfname, size)) {
47f0387b 138 rcleanup();
e3127271
RC
139 continue;
140 }
141 if (link(tfname, cp) < 0)
47f0387b 142 frecverr("%s: %m", tfname);
e3127271
RC
143 (void) unlink(tfname);
144 tfname[0] = '\0';
145 nfiles++;
146 continue;
147
148 case '\3': /* read df file */
149 size = 0;
150 while (*cp >= '0' && *cp <= '9')
151 size = size * 10 + (*cp++ - '0');
152 if (*cp++ != ' ')
153 break;
47f0387b
RC
154 if (!chksize(size)) {
155 (void) write(1, "\2", 1);
156 continue;
157 }
e3127271
RC
158 (void) readfile(dfname = cp, size);
159 continue;
160 }
47f0387b 161 frecverr("protocol screwup");
e3127271
RC
162 }
163}
164
165/*
166 * Read files send by lpd and copy them to the spooling directory.
167 */
168readfile(file, size)
169 char *file;
170 int size;
171{
172 register char *cp;
173 char buf[BUFSIZ];
174 register int i, j, amt;
175 int fd, err;
176
adec4d9e 177 fd = open(file, O_WRONLY|O_CREAT, FILMOD);
e3127271 178 if (fd < 0)
47f0387b 179 frecverr("%s: %m", file);
e3127271
RC
180 ack();
181 err = 0;
182 for (i = 0; i < size; i += BUFSIZ) {
183 amt = BUFSIZ;
184 cp = buf;
185 if (i + amt > size)
186 amt = size - i;
187 do {
188 j = read(1, cp, amt);
189 if (j <= 0)
47f0387b 190 frecverr("Lost connection");
e3127271
RC
191 amt -= j;
192 cp += j;
193 } while (amt > 0);
194 amt = BUFSIZ;
195 if (i + amt > size)
196 amt = size - i;
c6d1c018 197 if (write(fd, buf, amt) != amt) {
e3127271 198 err++;
c6d1c018
RC
199 break;
200 }
e3127271
RC
201 }
202 (void) close(fd);
203 if (err)
47f0387b 204 frecverr("%s: write error", file);
e3127271
RC
205 if (noresponse()) { /* file sent had bad data in it */
206 (void) unlink(file);
207 return(0);
208 }
209 ack();
210 return(1);
211}
212
e3127271
RC
213noresponse()
214{
215 char resp;
216
217 if (read(1, &resp, 1) != 1)
47f0387b 218 frecverr("Lost connection");
e3127271
RC
219 if (resp == '\0')
220 return(0);
221 return(1);
222}
223
47f0387b
RC
224/*
225 * Check to see if there is enough space on the disk for size bytes.
226 * 1 == OK, 0 == Not OK.
227 */
228chksize(size)
229 int size;
230{
231 struct stat stb;
232 register char *ddev;
233 int spacefree;
234 struct fs fs;
235
236 if (dfd < 0 || lseek(dfd, (long)(SBLOCK * DEV_BSIZE), 0) < 0)
237 return(1);
238 if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs)
239 return(1);
240 spacefree = (fs.fs_cstotal.cs_nbfree * fs.fs_frag +
241 fs.fs_cstotal.cs_nffree - fs.fs_dsize * fs.fs_minfree / 100) *
242 fs.fs_fsize / 1024;
243 size = (size + 1023) / 1024;
244 if (minfree + size > spacefree)
245 return(0);
246 return(1);
247}
248
249read_number(fn)
250 char *fn;
251{
252 char lin[80];
253 register FILE *fp;
254
255 if ((fp = fopen(fn, "r")) == NULL)
256 return (0);
257 if (fgets(lin, 80, fp) == NULL) {
258 fclose(fp);
259 return (0);
260 }
261 fclose(fp);
262 return (atoi(lin));
263}
264
e3127271
RC
265/*
266 * Remove all the files associated with the current job being transfered.
267 */
47f0387b 268rcleanup()
e3127271
RC
269{
270 register int i;
271
272 if (tfname[0])
273 (void) unlink(tfname);
274 if (dfname)
275 do {
276 do
277 (void) unlink(dfname);
278 while (dfname[i]-- != 'A');
279 dfname[i] = 'z';
280 } while (dfname[i-2]-- != 'd');
281}
282
47f0387b 283frecverr(msg, a1, a2)
e3127271
RC
284 char *msg;
285{
47f0387b
RC
286 rcleanup();
287 syslog(LOG_ERR, msg, a1, a2);
e3127271
RC
288 putchar('\1'); /* return error code */
289 exit(1);
290}