Commit | Line | Data |
---|---|---|
5f84f8f0 SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)recvjob.c 4.6 (Berkeley) %G%"; | |
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" | |
11 | ||
54266d1f RC |
12 | static char tfname[40]; /* tmp copy of cf before linking */ |
13 | static char *dfname; /* data files */ | |
e3127271 RC |
14 | |
15 | recvjob() | |
16 | { | |
88f026f7 | 17 | struct stat stb; |
e3127271 RC |
18 | char *bp = pbuf; |
19 | int status; | |
20 | ||
e3127271 RC |
21 | /* |
22 | * Perform lookup for printer name or abbreviation | |
23 | */ | |
24 | if ((status = pgetent(line, printer)) < 0) | |
25 | fatal("cannot open printer description file"); | |
26 | else if (status == 0) | |
27 | fatal("unknown printer"); | |
28 | if ((LF = pgetstr("lf", &bp)) == NULL) | |
29 | LF = DEFLOGF; | |
30 | if ((SD = pgetstr("sd", &bp)) == NULL) | |
31 | SD = DEFSPOOL; | |
88f026f7 RC |
32 | if ((LO = pgetstr("lo", &bp)) == NULL) |
33 | LO = DEFLOCK; | |
e3127271 RC |
34 | |
35 | (void) close(2); | |
adec4d9e | 36 | (void) open(LF, O_WRONLY|O_APPEND); |
e3127271 RC |
37 | if (chdir(SD) < 0) |
38 | fatal("cannot chdir to %s", SD); | |
88f026f7 RC |
39 | if (stat(LO, &stb) == 0 && (stb.st_mode & 010)) { |
40 | /* queue is disabled */ | |
41 | putchar('\1'); /* return error code */ | |
42 | exit(1); | |
43 | } | |
e3127271 RC |
44 | |
45 | if (readjob()) | |
46 | printjob(); | |
47 | } | |
48 | ||
49 | char *sp = ""; | |
50 | #define ack() (void) write(1, sp, 1); | |
51 | ||
52 | /* | |
53 | * Read printer jobs sent by lpd and copy them to the spooling directory. | |
54 | * Return the number of jobs successfully transfered. | |
55 | */ | |
54266d1f | 56 | static |
e3127271 RC |
57 | readjob(printer) |
58 | char *printer; | |
59 | { | |
60 | register int size, nfiles; | |
61 | register char *cp; | |
62 | ||
63 | ack(); | |
64 | nfiles = 0; | |
65 | for (;;) { | |
66 | /* | |
67 | * Read a command to tell us what to do | |
68 | */ | |
69 | cp = line; | |
70 | do { | |
71 | if ((size = read(1, cp, 1)) != 1) { | |
72 | if (size < 0) | |
73 | fatal("Lost connection"); | |
74 | return(nfiles); | |
75 | } | |
76 | } while (*cp++ != '\n'); | |
77 | *--cp = '\0'; | |
78 | cp = line; | |
79 | switch (*cp++) { | |
80 | case '\1': /* cleanup because data sent was bad */ | |
81 | cleanup(); | |
82 | continue; | |
83 | ||
84 | case '\2': /* read cf file */ | |
85 | size = 0; | |
86 | while (*cp >= '0' && *cp <= '9') | |
87 | size = size * 10 + (*cp++ - '0'); | |
88 | if (*cp++ != ' ') | |
89 | break; | |
90 | strcpy(tfname, cp); | |
91 | tfname[0] = 't'; | |
92 | if (!readfile(tfname, size)) { | |
93 | cleanup(); | |
94 | continue; | |
95 | } | |
96 | if (link(tfname, cp) < 0) | |
97 | fatal("cannot rename %s", tfname); | |
98 | (void) unlink(tfname); | |
99 | tfname[0] = '\0'; | |
100 | nfiles++; | |
101 | continue; | |
102 | ||
103 | case '\3': /* read df file */ | |
104 | size = 0; | |
105 | while (*cp >= '0' && *cp <= '9') | |
106 | size = size * 10 + (*cp++ - '0'); | |
107 | if (*cp++ != ' ') | |
108 | break; | |
109 | (void) readfile(dfname = cp, size); | |
110 | continue; | |
111 | } | |
112 | fatal("protocol screwup"); | |
113 | } | |
114 | } | |
115 | ||
116 | /* | |
117 | * Read files send by lpd and copy them to the spooling directory. | |
118 | */ | |
54266d1f | 119 | static |
e3127271 RC |
120 | readfile(file, size) |
121 | char *file; | |
122 | int size; | |
123 | { | |
124 | register char *cp; | |
125 | char buf[BUFSIZ]; | |
126 | register int i, j, amt; | |
127 | int fd, err; | |
128 | ||
adec4d9e | 129 | fd = open(file, O_WRONLY|O_CREAT, FILMOD); |
e3127271 RC |
130 | if (fd < 0) |
131 | fatal("cannot create %s", file); | |
132 | ack(); | |
133 | err = 0; | |
134 | for (i = 0; i < size; i += BUFSIZ) { | |
135 | amt = BUFSIZ; | |
136 | cp = buf; | |
137 | if (i + amt > size) | |
138 | amt = size - i; | |
139 | do { | |
140 | j = read(1, cp, amt); | |
141 | if (j <= 0) | |
142 | fatal("Lost connection"); | |
143 | amt -= j; | |
144 | cp += j; | |
145 | } while (amt > 0); | |
146 | amt = BUFSIZ; | |
147 | if (i + amt > size) | |
148 | amt = size - i; | |
c6d1c018 | 149 | if (write(fd, buf, amt) != amt) { |
e3127271 | 150 | err++; |
c6d1c018 RC |
151 | break; |
152 | } | |
e3127271 RC |
153 | } |
154 | (void) close(fd); | |
155 | if (err) | |
156 | fatal("%s: write error", file); | |
157 | if (noresponse()) { /* file sent had bad data in it */ | |
158 | (void) unlink(file); | |
159 | return(0); | |
160 | } | |
161 | ack(); | |
162 | return(1); | |
163 | } | |
164 | ||
165 | static | |
166 | noresponse() | |
167 | { | |
168 | char resp; | |
169 | ||
170 | if (read(1, &resp, 1) != 1) | |
171 | fatal("Lost connection"); | |
172 | if (resp == '\0') | |
173 | return(0); | |
174 | return(1); | |
175 | } | |
176 | ||
177 | /* | |
178 | * Remove all the files associated with the current job being transfered. | |
179 | */ | |
180 | static | |
181 | cleanup() | |
182 | { | |
183 | register int i; | |
184 | ||
185 | if (tfname[0]) | |
186 | (void) unlink(tfname); | |
187 | if (dfname) | |
188 | do { | |
189 | do | |
190 | (void) unlink(dfname); | |
191 | while (dfname[i]-- != 'A'); | |
192 | dfname[i] = 'z'; | |
193 | } while (dfname[i-2]-- != 'd'); | |
194 | } | |
195 | ||
196 | static | |
197 | fatal(msg, a1) | |
198 | char *msg; | |
199 | { | |
200 | cleanup(); | |
201 | log(msg, a1); | |
202 | putchar('\1'); /* return error code */ | |
203 | exit(1); | |
204 | } |