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