Commit | Line | Data |
---|---|---|
48688564 | 1 | #ifndef lint |
46b15d8a | 2 | static char sccsid[] = "@(#)cntrl.c 5.4 (Berkeley) %G%"; |
48688564 SL |
3 | #endif |
4 | ||
5 | #include "uucp.h" | |
6 | #include <sys/types.h> | |
7 | #include <sys/stat.h> | |
46b15d8a | 8 | #include "uust.h" |
48688564 | 9 | |
46b15d8a | 10 | extern int errno; |
48688564 SL |
11 | |
12 | struct Proto { | |
13 | char P_id; | |
14 | int (*P_turnon)(); | |
15 | int (*P_rdmsg)(); | |
16 | int (*P_wrmsg)(); | |
17 | int (*P_rddata)(); | |
18 | int (*P_wrdata)(); | |
19 | int (*P_turnoff)(); | |
20 | }; | |
21 | ||
48688564 SL |
22 | extern int gturnon(), gturnoff(); |
23 | extern int grdmsg(), grddata(); | |
24 | extern int gwrmsg(), gwrdata(); | |
25 | extern int imsg(), omsg(); | |
46b15d8a RC |
26 | #ifdef BSDTCP |
27 | extern int tnullf(); | |
28 | extern int twrmsg(), trdmsg(); | |
29 | extern int twrdata(), trddata(); | |
30 | #endif BSDTCP | |
31 | #ifdef PAD | |
32 | extern int fturnon(), fturnoff(); | |
33 | extern int frdmsg(), frddata(); | |
34 | extern int fwrmsg(), fwrdata(); | |
35 | #endif PAD | |
48688564 SL |
36 | |
37 | struct Proto Ptbl[]={ | |
46b15d8a RC |
38 | #ifdef BSDTCP |
39 | 't', tnullf, trdmsg, twrmsg, trddata, twrdata, tnullf, | |
40 | #endif BSDTCP | |
41 | #ifdef PAD | |
42 | 'f', fturnon, frdmsg, fwrmsg, frddata, fwrdata, fturnoff, | |
43 | #endif PAD | |
48688564 SL |
44 | 'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff, |
45 | '\0' | |
46 | }; | |
47 | ||
46b15d8a | 48 | int (*Imsg)() = imsg, (*Omsg)() = omsg; |
48688564 SL |
49 | |
50 | int (*Rdmsg)()=imsg, (*Rddata)(); | |
51 | int (*Wrmsg)()=omsg, (*Wrdata)(); | |
52 | int (*Turnon)(), (*Turnoff)(); | |
53 | ||
54 | ||
46b15d8a RC |
55 | static char *YES = "Y"; |
56 | static char *NO = "N"; | |
48688564 SL |
57 | |
58 | /* failure messages */ | |
59 | #define EM_MAX 6 | |
60 | #define EM_LOCACC "N1" /* local access to file denied */ | |
61 | #define EM_RMTACC "N2" /* remote access to file/path denied */ | |
62 | #define EM_BADUUCP "N3" /* a bad uucp command was generated */ | |
63 | #define EM_NOTMP "N4" /* remote error - can't create temp */ | |
64 | #define EM_RMTCP "N5" /* can't copy to remote directory - file in public */ | |
65 | #define EM_LOCCP "N6" /* can't copy on local system */ | |
66 | ||
67 | char *Em_msg[] = { | |
68 | "COPY FAILED (reason not given by remote)", | |
69 | "local access to file denied", | |
70 | "remote access to path/file denied", | |
71 | "system error - bad uucp command generated", | |
72 | "remote system can't create temp file", | |
73 | "can't copy to file/directory - file left in PUBDIR/user/file", | |
46b15d8a | 74 | "can't copy to file/directory on local system - file left in PUBDIR/user/file" |
48688564 SL |
75 | }; |
76 | ||
48688564 SL |
77 | |
78 | #define XUUCP 'X' /* execute uucp (string) */ | |
79 | #define SLTPTCL 'P' /* select protocol (string) */ | |
80 | #define USEPTCL 'U' /* use protocol (character) */ | |
81 | #define RCVFILE 'R' /* receive file (string) */ | |
82 | #define SNDFILE 'S' /* send file (string) */ | |
83 | #define RQSTCMPT 'C' /* request complete (string - yes | no) */ | |
84 | #define HUP 'H' /* ready to hangup (string - yes | no) */ | |
85 | #define RESET 'X' /* reset line modes */ | |
86 | ||
48688564 SL |
87 | #define W_TYPE wrkvec[0] |
88 | #define W_FILE1 wrkvec[1] | |
89 | #define W_FILE2 wrkvec[2] | |
90 | #define W_USER wrkvec[3] | |
91 | #define W_OPTNS wrkvec[4] | |
92 | #define W_DFILE wrkvec[5] | |
93 | #define W_MODE wrkvec[6] | |
94 | #define W_NUSER wrkvec[7] | |
95 | ||
46b15d8a RC |
96 | #define XFRRATE 35000L |
97 | #define RMESG(m, s, n) if (rmesg(m, s, n) != 0) {(*Turnoff)(); return FAIL;} else | |
98 | #define RAMESG(s, n) if (rmesg('\0', s, n) != 0) {(*Turnoff)(); return FAIL;} else | |
99 | #define WMESG(m, s) if(wmesg(m, s) != 0) {(*Turnoff)(); return FAIL;} else | |
48688564 SL |
100 | |
101 | char Wfile[MAXFULLNAME] = {'\0'}; | |
102 | char Dfile[MAXFULLNAME]; | |
103 | ||
104 | /* | |
105 | * To avoid a huge backlog of X. files, start uuxqt every so often. | |
48688564 SL |
106 | */ |
107 | static int nXfiles = 0; /* number of X files since last uuxqt start */ | |
108 | static int nXQTs = 0; /* number of uuxqts started */ | |
46b15d8a RC |
109 | static char send_or_receive; |
110 | struct stat stbuf; | |
48688564 | 111 | |
46b15d8a | 112 | /* |
48688564 SL |
113 | * cntrl - this routine will execute the conversation |
114 | * between the two machines after both programs are | |
115 | * running. | |
116 | * | |
117 | * return codes | |
118 | * SUCCESS - ok | |
119 | * FAIL - failed | |
120 | */ | |
121 | ||
122 | cntrl(role, wkpre) | |
123 | int role; | |
124 | char *wkpre; | |
125 | { | |
126 | char msg[BUFSIZ], rqstr[BUFSIZ]; | |
127 | register FILE *fp; | |
128 | int filemode; | |
48688564 SL |
129 | char filename[MAXFULLNAME], wrktype, *wrkvec[20]; |
130 | extern (*Rdmsg)(), (*Wrmsg)(); | |
131 | extern char *index(), *lastpart(); | |
132 | int status = 1; | |
133 | register int i, narg; | |
134 | int mailopt, ntfyopt; | |
135 | int ret; | |
136 | static int pnum, tmpnum = 0; | |
46b15d8a | 137 | extern int ReverseRole; |
48688564 SL |
138 | |
139 | pnum = getpid(); | |
48688564 SL |
140 | Wfile[0] = '\0'; |
141 | top: | |
142 | for (i = 0; i < sizeof wrkvec / sizeof wrkvec[0]; i++) | |
143 | wrkvec[i] = 0; | |
46b15d8a | 144 | DEBUG(4, "*** TOP *** - role=%s\n", role ? "MASTER" : "SLAVE"); |
48688564 | 145 | setline(RESET); |
46b15d8a | 146 | send_or_receive = RESET; |
48688564 SL |
147 | if (role == MASTER) { |
148 | /* get work */ | |
46b15d8a RC |
149 | if (ReverseRole || (narg = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) { |
150 | ReverseRole = 0; | |
48688564 SL |
151 | WMESG(HUP, ""); |
152 | RMESG(HUP, msg, 1); | |
153 | goto process; | |
154 | } | |
155 | wrktype = W_TYPE[0]; | |
48688564 SL |
156 | |
157 | msg[0] = '\0'; | |
158 | for (i = 1; i < narg; i++) { | |
159 | strcat(msg, " "); | |
160 | strcat(msg, wrkvec[i]); | |
161 | } | |
162 | ||
163 | if (wrktype == XUUCP) { | |
164 | sprintf(rqstr, "X %s", msg); | |
165 | logent(rqstr, "REQUEST"); | |
166 | goto sendmsg; | |
167 | } | |
46b15d8a RC |
168 | mailopt = index(W_OPTNS, 'm') != NULL; |
169 | ntfyopt = index(W_OPTNS, 'n') != NULL; | |
48688564 | 170 | |
46b15d8a RC |
171 | if (narg < 5) { |
172 | char *bnp; | |
173 | bnp = rindex(Wfile, '/'); | |
174 | sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); | |
175 | xmv(Wfile, rqstr); | |
176 | logent(Wfile, "CMD FILE CORRUPTED"); | |
177 | Wfile[0] = '\0'; | |
178 | goto top; | |
179 | } | |
48688564 SL |
180 | sprintf(User, "%.9s", W_USER); |
181 | sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, | |
182 | W_FILE2, W_USER); | |
183 | logent(rqstr, "REQUEST"); | |
184 | if (wrktype == SNDFILE ) { | |
185 | strcpy(filename, W_FILE1); | |
186 | i = expfile(filename); | |
46b15d8a | 187 | DEBUG(4, "expfile type - %d, ", i); |
48688564 SL |
188 | if (i != 0 && chkpth(User, "", filename)) |
189 | goto e_access; | |
190 | strcpy(Dfile, W_DFILE); | |
191 | fp = NULL; | |
192 | if (index(W_OPTNS, 'c') == NULL) { | |
193 | fp = fopen(subfile(Dfile), "r"); | |
194 | if (fp != NULL) | |
195 | i = 0; | |
196 | } | |
197 | if (fp == NULL && | |
198 | (fp = fopen(subfile(filename), "r")) == NULL) { | |
199 | /* can not read data file */ | |
46b15d8a RC |
200 | logent("CAN'T READ DATA", _FAILED); |
201 | USRF(USR_LOCACC); | |
48688564 SL |
202 | unlinkdf(Dfile); |
203 | lnotify(User, filename, "can't access"); | |
204 | goto top; | |
205 | } | |
206 | /* if file exists but is not generally readable... */ | |
207 | if (i != 0 && fstat(fileno(fp), &stbuf) == 0 | |
208 | && (stbuf.st_mode & ANYREAD) == 0) { | |
209 | e_access:; | |
210 | /* access denied */ | |
211 | fclose(fp); | |
212 | fp = NULL; | |
213 | logent("DENIED", "ACCESS"); | |
46b15d8a | 214 | USRF(USR_LOCACC); |
48688564 SL |
215 | unlinkdf(W_DFILE); |
216 | lnotify(User, filename, "access denied"); | |
217 | goto top; | |
218 | } | |
219 | ||
220 | setline(SNDFILE); | |
221 | } | |
222 | ||
223 | if (wrktype == RCVFILE) { | |
224 | strcpy(filename, W_FILE2); | |
225 | expfile(filename); | |
226 | if (chkpth(User, "", filename) | |
227 | || chkperm(filename, index(W_OPTNS, 'd'))) { | |
228 | /* access denied */ | |
229 | logent("DENIED", "ACCESS"); | |
46b15d8a | 230 | USRF(USR_LOCACC); |
48688564 SL |
231 | lnotify(User, filename, "access denied"); |
232 | goto top; | |
233 | } | |
234 | sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); | |
235 | if ((fp = fopen(subfile(Dfile), "w")) == NULL) { | |
236 | /* can not create temp */ | |
46b15d8a RC |
237 | logent("CAN'T CREATE TM", _FAILED); |
238 | USRF(USR_LNOTMP); | |
48688564 SL |
239 | unlinkdf(Dfile); |
240 | goto top; | |
241 | } | |
242 | setline(RCVFILE); | |
243 | } | |
244 | sendmsg: | |
46b15d8a | 245 | DEBUG(4, "wrktype - %c\n", wrktype); |
48688564 SL |
246 | WMESG(wrktype, msg); |
247 | RMESG(wrktype, msg, 1); | |
248 | goto process; | |
249 | } | |
250 | ||
251 | /* role is slave */ | |
252 | RAMESG(msg, 1); | |
253 | goto process; | |
254 | ||
255 | process: | |
46b15d8a | 256 | DEBUG(4, "PROCESS: msg - %s\n", msg); |
48688564 SL |
257 | switch (msg[0]) { |
258 | ||
259 | case RQSTCMPT: | |
46b15d8a | 260 | DEBUG(4, "RQSTCMPT:\n", CNULL); |
48688564 SL |
261 | if (msg[1] == 'N') { |
262 | i = atoi(&msg[2]); | |
263 | if (i<0 || i>EM_MAX) i=0; | |
46b15d8a RC |
264 | USRF( 1 << i ); |
265 | i = 0; | |
266 | logent(Em_msg[i], "REQUEST FAILED"); | |
267 | if (strcmp(&msg[1], EM_NOTMP) == 0) { | |
268 | /* dont send him files he can't save */ | |
269 | WMESG(HUP, ""); | |
270 | RMESG(HUP, msg, 1); | |
271 | goto process; | |
272 | } | |
48688564 | 273 | } |
46b15d8a RC |
274 | if (msg[1] == 'Y') |
275 | USRF(USR_COK); | |
48688564 SL |
276 | if (role == MASTER) { |
277 | notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); | |
278 | } | |
279 | goto top; | |
280 | ||
281 | case HUP: | |
46b15d8a | 282 | DEBUG(4, "HUP:\n", CNULL); |
48688564 | 283 | if (msg[1] == 'Y') { |
46b15d8a RC |
284 | if (role == MASTER) |
285 | WMESG(HUP, YES); | |
48688564 SL |
286 | (*Turnoff)(); |
287 | Rdmsg = Imsg; | |
288 | Wrmsg = Omsg; | |
46b15d8a | 289 | return SUCCESS; |
48688564 SL |
290 | } |
291 | ||
292 | if (msg[1] == 'N') { | |
46b15d8a | 293 | ASSERT(role == MASTER, "WRONG ROLE - HUP", CNULL, role); |
48688564 SL |
294 | role = SLAVE; |
295 | goto top; | |
296 | } | |
297 | ||
298 | /* get work */ | |
299 | if (!iswrk(Wfile, "chk", Spool, wkpre)) { | |
300 | WMESG(HUP, YES); | |
301 | RMESG(HUP, msg, 1); | |
302 | goto process; | |
303 | } | |
304 | ||
305 | WMESG(HUP, NO); | |
306 | role = MASTER; | |
307 | goto top; | |
308 | ||
309 | case XUUCP: | |
310 | if (role == MASTER) { | |
311 | goto top; | |
312 | } | |
313 | ||
314 | /* slave part */ | |
46b15d8a | 315 | i = getargs(msg, wrkvec, 20); |
48688564 | 316 | strcpy(filename, W_FILE1); |
46b15d8a RC |
317 | if (index(filename, ';') != NULL || index(W_FILE2, ';') != NULL |
318 | || i < 3) { | |
48688564 SL |
319 | WMESG(XUUCP, NO); |
320 | goto top; | |
321 | } | |
322 | expfile(filename); | |
323 | if (chkpth("", Rmtname, filename)) { | |
324 | WMESG(XUUCP, NO); | |
325 | logent("XUUCP DENIED", filename); | |
46b15d8a | 326 | USRF(USR_XUUCP); |
48688564 SL |
327 | goto top; |
328 | } | |
329 | sprintf(rqstr, "%s %s", filename, W_FILE2); | |
330 | xuucp(rqstr); | |
331 | WMESG(XUUCP, YES); | |
332 | goto top; | |
333 | ||
334 | case SNDFILE: | |
335 | /* MASTER section of SNDFILE */ | |
336 | ||
337 | DEBUG(4, "%s\n", "SNDFILE:"); | |
338 | if (msg[1] == 'N') { | |
339 | i = atoi(&msg[2]); | |
340 | if (i < 0 || i > EM_MAX) | |
341 | i = 0; | |
46b15d8a RC |
342 | logent(Em_msg[i], "REQUEST FAILED"); |
343 | USRF( 1 << i ); | |
48688564 SL |
344 | fclose(fp); |
345 | fp = NULL; | |
46b15d8a RC |
346 | if (strcmp(&msg[1], EM_NOTMP) == 0) { |
347 | /* dont send him files he can't save */ | |
348 | WMESG(HUP, ""); | |
349 | RMESG(HUP, msg, 1); | |
350 | goto process; | |
351 | } | |
352 | notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); | |
353 | ASSERT(role == MASTER, "WRONG ROLE - SN", CNULL, role); | |
48688564 SL |
354 | if (msg[1] != '4') |
355 | unlinkdf(W_DFILE); | |
356 | goto top; | |
357 | } | |
358 | ||
359 | if (msg[1] == 'Y') { | |
360 | /* send file */ | |
46b15d8a | 361 | ASSERT(role == MASTER, "WRONG ROLE - SY", CNULL, role); |
48688564 SL |
362 | ret = fstat(fileno(fp), &stbuf); |
363 | ASSERT(ret != -1, "STAT FAILED", filename, 0); | |
364 | i = 1 + (int)(stbuf.st_size / XFRRATE); | |
46b15d8a RC |
365 | if (send_or_receive != SNDFILE) { |
366 | send_or_receive = SNDFILE; | |
367 | systat(Rmtname, SS_INPROGRESS, "SENDING"); | |
368 | } | |
48688564 SL |
369 | ret = (*Wrdata)(fp, Ofn); |
370 | fclose(fp); | |
371 | fp = NULL; | |
46b15d8a | 372 | if (ret != SUCCESS) { |
48688564 | 373 | (*Turnoff)(); |
46b15d8a RC |
374 | USRF(USR_CFAIL); |
375 | return FAIL; | |
48688564 SL |
376 | } |
377 | RMESG(RQSTCMPT, msg, i); | |
48688564 SL |
378 | unlinkdf(W_DFILE); |
379 | goto process; | |
380 | } | |
381 | ||
382 | /* SLAVE section of SNDFILE */ | |
46b15d8a | 383 | ASSERT(role == SLAVE, "WRONG ROLE - SLAVE", CNULL, role); |
48688564 SL |
384 | |
385 | /* request to receive file */ | |
386 | /* check permissions */ | |
46b15d8a RC |
387 | i = getargs(msg, wrkvec, 20); |
388 | if (i < 5) { | |
389 | char *bnp; | |
390 | bnp = rindex(Wfile, '/'); | |
391 | sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); | |
392 | xmv(Wfile, rqstr); | |
393 | logent(Wfile, "CMD FILE CORRUPTED"); | |
394 | Wfile[0] = '\0'; | |
395 | goto top; | |
396 | } | |
397 | sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1, W_FILE2, W_USER); | |
48688564 SL |
398 | logent(rqstr, "REQUESTED"); |
399 | DEBUG(4, "msg - %s\n", msg); | |
400 | strcpy(filename, W_FILE2); | |
401 | /* Run uuxqt occasionally */ | |
402 | if (filename[0] == XQTPRE) { | |
403 | if (++nXfiles > 10) { | |
404 | nXfiles = 0; | |
46b15d8a RC |
405 | /* |
406 | * want to create an orphan uuxqt, | |
407 | * so a double-fork is needed. | |
48688564 | 408 | */ |
46b15d8a RC |
409 | if (fork() == 0) { |
410 | xuuxqt(); | |
411 | _exit(0); | |
412 | } | |
413 | wait((int *)0); | |
48688564 SL |
414 | } |
415 | } | |
46b15d8a | 416 | /* expand filename, i is set to 0 if this is |
48688564 SL |
417 | * is a vanilla spool file, so no stat(II)s are needed */ |
418 | i = expfile(filename); | |
419 | DEBUG(4, "expfile type - %d\n", i); | |
420 | if (i != 0) { | |
421 | if (chkpth("", Rmtname, filename) | |
422 | || chkperm(filename, index(W_OPTNS, 'd'))) { | |
423 | WMESG(SNDFILE, EM_RMTACC); | |
424 | logent("DENIED", "PERMISSION"); | |
425 | goto top; | |
426 | } | |
427 | if (isdir(filename)) { | |
428 | strcat(filename, "/"); | |
429 | strcat(filename, lastpart(W_FILE1)); | |
430 | } | |
431 | } | |
432 | sprintf(User, "%.9s", W_USER); | |
433 | ||
434 | DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); | |
46b15d8a RC |
435 | /* speed things up by OKing file before |
436 | * creating TM file. If the TM file cannot be created, | |
437 | * then the conversation bombs, but that seems reasonable, | |
438 | * as there are probably serious problems then. | |
439 | */ | |
440 | WMESG(SNDFILE, YES); | |
48688564 SL |
441 | sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++); |
442 | if((fp = fopen(subfile(Dfile), "w")) == NULL) { | |
46b15d8a RC |
443 | /* WMESG(SNDFILE, EM_NOTMP);*/ |
444 | logent("CAN'T OPEN", "TM FILE"); | |
48688564 | 445 | unlinkdf(Dfile); |
46b15d8a RC |
446 | (*Turnoff)(); |
447 | return FAIL; | |
48688564 SL |
448 | } |
449 | ||
46b15d8a RC |
450 | if (send_or_receive != RCVFILE) { |
451 | send_or_receive = RCVFILE; | |
452 | systat(Rmtname, SS_INPROGRESS, "RECEIVING"); | |
453 | } | |
48688564 | 454 | ret = (*Rddata)(Ifn, fp); |
48688564 SL |
455 | fflush(fp); |
456 | if (ferror(fp) || fclose(fp)) | |
457 | ret = FAIL; | |
46b15d8a RC |
458 | if (ret != SUCCESS) { |
459 | (void) unlinkdf(Dfile); | |
48688564 | 460 | (*Turnoff)(); |
46b15d8a | 461 | return FAIL; |
48688564 SL |
462 | } |
463 | /* copy to user directory */ | |
464 | ntfyopt = index(W_OPTNS, 'n') != NULL; | |
465 | status = xmv(Dfile, filename); | |
466 | WMESG(RQSTCMPT, status ? EM_RMTCP : YES); | |
46b15d8a RC |
467 | if (i == 0) |
468 | ; /* vanilla file, nothing to do */ | |
469 | else if (status == 0) { | |
470 | if (W_MODE == 0 || sscanf(W_MODE, "%o", &filemode) != 1) | |
48688564 | 471 | filemode = BASEMODE; |
46b15d8a | 472 | chmod(subfile(filename), (filemode|BASEMODE)&0777); |
48688564 | 473 | arrived(ntfyopt, filename, W_NUSER, Rmtname, User); |
46b15d8a RC |
474 | } else { |
475 | logent(_FAILED, "COPY"); | |
48688564 SL |
476 | status = putinpub(filename, Dfile, W_USER); |
477 | DEBUG(4, "->PUBDIR %d\n", status); | |
478 | if (status == 0) | |
46b15d8a | 479 | arrived(ntfyopt, filename, W_NUSER, Rmtname, User); |
48688564 SL |
480 | } |
481 | ||
482 | goto top; | |
483 | ||
484 | case RCVFILE: | |
485 | /* MASTER section of RCVFILE */ | |
486 | ||
487 | DEBUG(4, "%s\n", "RCVFILE:"); | |
488 | if (msg[1] == 'N') { | |
489 | i = atoi(&msg[2]); | |
490 | if (i < 0 || i > EM_MAX) | |
491 | i = 0; | |
46b15d8a RC |
492 | logent(Em_msg[i], "REQUEST FAILED"); |
493 | USRF( 1 << i ); | |
48688564 | 494 | fclose(fp); |
46b15d8a RC |
495 | fp = NULL; |
496 | if (strcmp(&msg[1], EM_NOTMP) == 0) { | |
497 | /* dont send him files he can't save */ | |
498 | WMESG(HUP, ""); | |
499 | RMESG(HUP, msg, 1); | |
500 | goto process; | |
501 | } | |
502 | notify(mailopt, W_USER, W_FILE1, Rmtname, &msg[1]); | |
503 | ASSERT(role == MASTER, "WRONG ROLE - RN", CNULL, role); | |
48688564 SL |
504 | unlinkdf(Dfile); |
505 | goto top; | |
506 | } | |
507 | ||
508 | if (msg[1] == 'Y') { | |
509 | /* receive file */ | |
46b15d8a RC |
510 | ASSERT(role == MASTER, "WRONG ROLE - RY", CNULL, role); |
511 | if (send_or_receive != RCVFILE) { | |
512 | send_or_receive = RCVFILE; | |
513 | systat(Rmtname, SS_INPROGRESS, "RECEIVING"); | |
514 | } | |
48688564 | 515 | ret = (*Rddata)(Ifn, fp); |
48688564 SL |
516 | fflush(fp); |
517 | if (ferror(fp) || fclose(fp)) | |
518 | ret = FAIL; | |
46b15d8a RC |
519 | if (ret != SUCCESS) { |
520 | unlinkdf(Dfile); | |
48688564 | 521 | (*Turnoff)(); |
46b15d8a RC |
522 | USRF(USR_CFAIL); |
523 | return FAIL; | |
48688564 SL |
524 | } |
525 | /* copy to user directory */ | |
526 | if (isdir(filename)) { | |
527 | strcat(filename, "/"); | |
528 | strcat(filename, lastpart(W_FILE1)); | |
529 | } | |
530 | status = xmv(Dfile, filename); | |
531 | WMESG(RQSTCMPT, status ? EM_RMTCP : YES); | |
532 | notify(mailopt, W_USER, filename, Rmtname, | |
533 | status ? EM_LOCCP : YES); | |
534 | if (status == 0) { | |
535 | sscanf(&msg[2], "%o", &filemode); | |
536 | if (filemode <= 0) | |
537 | filemode = BASEMODE; | |
46b15d8a RC |
538 | chmod(subfile(filename), (filemode|BASEMODE)&0777); |
539 | USRF(USR_COK); | |
48688564 SL |
540 | } |
541 | else { | |
46b15d8a | 542 | logent(_FAILED, "COPY"); |
48688564 | 543 | putinpub(filename, Dfile, W_USER); |
46b15d8a | 544 | USRF(USR_LOCCP); |
48688564 SL |
545 | } |
546 | goto top; | |
547 | } | |
548 | ||
549 | /* SLAVE section of RCVFILE */ | |
46b15d8a | 550 | ASSERT(role == SLAVE, "WRONG ROLE - SLAVE RCV", CNULL, role); |
48688564 SL |
551 | |
552 | /* request to send file */ | |
553 | strcpy(rqstr, msg); | |
554 | logent(rqstr, "REQUESTED"); | |
555 | ||
556 | /* check permissions */ | |
46b15d8a RC |
557 | i = getargs(msg, wrkvec, 20); |
558 | if (i < 4) { | |
559 | char *bnp; | |
560 | bnp = rindex(Wfile, '/'); | |
561 | sprintf(rqstr, "%s/%s", CORRUPT, bnp ? bnp + 1 : Wfile); | |
562 | xmv(Wfile, rqstr); | |
563 | logent(Wfile, "CMD FILE CORRUPTED"); | |
564 | Wfile[0] = '\0'; | |
565 | goto top; | |
566 | } | |
48688564 SL |
567 | DEBUG(4, "msg - %s\n", msg); |
568 | DEBUG(4, "W_FILE1 - %s\n", W_FILE1); | |
569 | strcpy(filename, W_FILE1); | |
570 | expfile(filename); | |
571 | if (isdir(filename)) { | |
572 | strcat(filename, "/"); | |
573 | strcat(filename, lastpart(W_FILE2)); | |
574 | } | |
575 | sprintf(User, "%.9s", W_USER); | |
576 | if (chkpth("", Rmtname, filename) || anyread(filename)) { | |
577 | WMESG(RCVFILE, EM_RMTACC); | |
578 | logent("DENIED", "PERMISSION"); | |
579 | goto top; | |
580 | } | |
581 | DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname); | |
582 | ||
583 | if ((fp = fopen(subfile(filename), "r")) == NULL) { | |
584 | WMESG(RCVFILE, EM_RMTACC); | |
585 | logent("CAN'T OPEN", "DENIED"); | |
586 | goto top; | |
587 | } | |
588 | ||
589 | /* ok to send file */ | |
590 | ret = fstat(fileno(fp), &stbuf); | |
591 | ASSERT(ret != -1, "STAT FAILED", filename, 0); | |
592 | i = 1 + (int)(stbuf.st_size / XFRRATE); | |
593 | sprintf(msg, "%s %o", YES, stbuf.st_mode & 0777); | |
594 | WMESG(RCVFILE, msg); | |
46b15d8a RC |
595 | if (send_or_receive != SNDFILE) { |
596 | send_or_receive = SNDFILE; | |
597 | systat(Rmtname, SS_INPROGRESS, "SENDING"); | |
598 | } | |
48688564 SL |
599 | ret = (*Wrdata)(fp, Ofn); |
600 | fclose(fp); | |
46b15d8a | 601 | if (ret != SUCCESS) { |
48688564 | 602 | (*Turnoff)(); |
46b15d8a | 603 | return FAIL; |
48688564 SL |
604 | } |
605 | RMESG(RQSTCMPT, msg, i); | |
606 | goto process; | |
607 | } | |
608 | (*Turnoff)(); | |
46b15d8a | 609 | return FAIL; |
48688564 SL |
610 | } |
611 | ||
612 | ||
613 | /*** | |
614 | * rmesg(c, msg, n) read message 'c' | |
615 | * try 'n' times | |
616 | * char *msg, c; | |
617 | * | |
618 | * return code: 0 | FAIL | |
619 | */ | |
620 | ||
621 | rmesg(c, msg, n) | |
622 | register char *msg, c; | |
623 | register int n; | |
624 | { | |
46b15d8a | 625 | char str[128]; |
48688564 SL |
626 | |
627 | DEBUG(4, "rmesg - '%c' ", c); | |
46b15d8a RC |
628 | while ((*Rdmsg)(msg, Ifn) != SUCCESS) { |
629 | if (--n > 0) { | |
630 | sprintf(str, "%d", n); | |
631 | logent(str, "PATIENCE"); | |
48688564 | 632 | continue; |
46b15d8a RC |
633 | } |
634 | DEBUG(4, "got FAIL\n", CNULL); | |
635 | if (c != '\0') | |
636 | sprintf(str, "expected '%c' got FAIL (%d)", c, errno); | |
637 | else | |
638 | sprintf(str, "expected ANY got FAIL (%d)", errno); | |
48688564 | 639 | logent(str, "BAD READ"); |
46b15d8a | 640 | return FAIL; |
48688564 SL |
641 | } |
642 | if (c != '\0' && msg[0] != c) { | |
643 | DEBUG(4, "got %s\n", msg); | |
46b15d8a | 644 | sprintf(str, "expected '%c' got %s", c, msg); |
48688564 | 645 | logent(str, "BAD READ"); |
46b15d8a | 646 | return FAIL; |
48688564 | 647 | } |
46b15d8a RC |
648 | DEBUG(4, "got %s\n", msg); |
649 | return SUCCESS; | |
48688564 SL |
650 | } |
651 | ||
652 | ||
653 | /*** | |
654 | * wmesg(m, s) write a message (type m) | |
655 | * char *s, m; | |
656 | * | |
657 | * return codes: 0 - ok | FAIL - ng | |
658 | */ | |
659 | ||
660 | wmesg(m, s) | |
661 | register char *s, m; | |
662 | { | |
46b15d8a RC |
663 | DEBUG(4, "wmesg '%c' ", m); |
664 | DEBUG(4, "%s\n", s); | |
665 | return (*Wrmsg)(m, s, Ofn); | |
48688564 SL |
666 | } |
667 | ||
668 | ||
669 | /*** | |
670 | * notify mail results of command | |
671 | * | |
672 | * return codes: none | |
673 | */ | |
674 | ||
675 | notify(mailopt, user, file, sys, msgcode) | |
676 | char *user, *file, *sys, *msgcode; | |
677 | { | |
678 | char str[200]; | |
679 | int i; | |
680 | char *msg; | |
681 | ||
682 | if (!mailopt && *msgcode == 'Y') | |
683 | return; | |
684 | if (*msgcode == 'Y') | |
685 | msg = "copy succeeded"; | |
686 | else { | |
687 | i = atoi(msgcode + 1); | |
688 | if (i < 1 || i > EM_MAX) | |
689 | i = 0; | |
690 | msg = Em_msg[i]; | |
691 | } | |
46b15d8a RC |
692 | sprintf(str, "file %s!%s -- %s\n", |
693 | sys,file, msg); | |
694 | mailst(user, str, CNULL); | |
48688564 SL |
695 | return; |
696 | } | |
697 | ||
698 | /*** | |
699 | * lnotify(user, file, mesg) - local notify | |
700 | * | |
701 | * return code - none | |
702 | */ | |
703 | ||
704 | lnotify(user, file, mesg) | |
705 | char *user, *file, *mesg; | |
706 | { | |
707 | char mbuf[200]; | |
46b15d8a RC |
708 | sprintf(mbuf, "file %s!%s -- %s\n", Myname, file, mesg); |
709 | mailst(user, mbuf, CNULL); | |
48688564 SL |
710 | return; |
711 | } | |
712 | ||
713 | ||
714 | /*** | |
715 | * startup(role) | |
716 | * int role; | |
717 | * | |
718 | * startup - this routine will converse with the remote | |
719 | * machine, agree upon a protocol (if possible) and start the | |
720 | * protocol. | |
721 | * | |
722 | * return codes: | |
723 | * SUCCESS - successful protocol selection | |
724 | * FAIL - can't find common or open failed | |
725 | */ | |
726 | ||
727 | startup(role) | |
728 | int role; | |
729 | { | |
730 | extern (*Rdmsg)(), (*Wrmsg)(); | |
731 | extern char *blptcl(), fptcl(); | |
46b15d8a | 732 | char msg[BUFSIZ], str[MAXFULLNAME]; |
48688564 SL |
733 | |
734 | Rdmsg = Imsg; | |
735 | Wrmsg = Omsg; | |
736 | if (role == MASTER) { | |
737 | RMESG(SLTPTCL, msg, 1); | |
738 | if ((str[0] = fptcl(&msg[1])) == NULL) { | |
739 | /* no protocol match */ | |
740 | WMESG(USEPTCL, NO); | |
46b15d8a | 741 | return FAIL; |
48688564 SL |
742 | } |
743 | str[1] = '\0'; | |
744 | WMESG(USEPTCL, str); | |
745 | if (stptcl(str) != 0) | |
46b15d8a | 746 | return FAIL; |
48688564 | 747 | DEBUG(4, "protocol %s\n", str); |
46b15d8a | 748 | return SUCCESS; |
48688564 SL |
749 | } |
750 | else { | |
751 | WMESG(SLTPTCL, blptcl(str)); | |
752 | RMESG(USEPTCL, msg, 1); | |
753 | if (msg[1] == 'N') { | |
46b15d8a | 754 | return FAIL; |
48688564 SL |
755 | } |
756 | ||
757 | if (stptcl(&msg[1]) != 0) | |
46b15d8a | 758 | return FAIL; |
48688564 | 759 | DEBUG(4, "Protocol %s\n", msg); |
46b15d8a | 760 | return SUCCESS; |
48688564 SL |
761 | } |
762 | } | |
763 | ||
764 | ||
765 | /******* | |
766 | * char | |
767 | * fptcl(str) | |
768 | * char *str; | |
769 | * | |
770 | * fptcl - this routine will choose a protocol from | |
771 | * the input string (str) and return the found letter. | |
772 | * | |
773 | * return codes: | |
774 | * '\0' - no acceptable protocol | |
775 | * any character - the chosen protocol | |
776 | */ | |
777 | ||
778 | char | |
779 | fptcl(str) | |
780 | register char *str; | |
781 | { | |
782 | register struct Proto *p; | |
46b15d8a | 783 | extern char *Flds[]; |
48688564 SL |
784 | |
785 | for (p = Ptbl; p->P_id != '\0'; p++) { | |
46b15d8a RC |
786 | #ifdef BSDTCP |
787 | if (!IsTcpIp && p->P_id == 't') /* Only use 't' on TCP/IP */ | |
788 | continue; | |
789 | #endif BSDTCP | |
790 | /* only use 'f' protocol on PAD */ | |
791 | if (strcmp("PAD", Flds[F_LINE]) && p->P_id == 'f') | |
0385e946 | 792 | continue; |
48688564 | 793 | if (index(str, p->P_id) != NULL) { |
46b15d8a | 794 | return p->P_id; |
48688564 SL |
795 | } |
796 | } | |
797 | ||
46b15d8a | 798 | return '\0'; |
48688564 SL |
799 | } |
800 | ||
801 | ||
802 | /*** | |
803 | * char * | |
804 | * blptcl(str) | |
805 | * char *str; | |
806 | * | |
807 | * blptcl - this will build a string of the | |
808 | * letters of the available protocols and return | |
809 | * the string (str). | |
810 | * | |
811 | * return: | |
812 | * a pointer to string (str) | |
813 | */ | |
814 | ||
815 | char * | |
816 | blptcl(str) | |
817 | register char *str; | |
818 | { | |
819 | register struct Proto *p; | |
820 | register char *s; | |
821 | ||
46b15d8a RC |
822 | for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++) |
823 | ; | |
824 | *s = '\0'; | |
825 | return str; | |
48688564 SL |
826 | } |
827 | ||
828 | /*** | |
829 | * stptcl(c) | |
830 | * char *c; | |
831 | * | |
832 | * stptcl - this routine will set up the six routines | |
833 | * (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the | |
834 | * desired protocol. | |
835 | * | |
836 | * return codes: | |
837 | * SUCCESS - ok | |
838 | * FAIL - no find or failed to open | |
839 | * | |
840 | */ | |
841 | ||
842 | stptcl(c) | |
843 | register char *c; | |
844 | { | |
845 | register struct Proto *p; | |
846 | ||
847 | for (p = Ptbl; p->P_id != '\0'; p++) { | |
848 | if (*c == p->P_id) { | |
849 | /* found protocol - set routines */ | |
850 | Rdmsg = p->P_rdmsg; | |
851 | Wrmsg = p->P_wrmsg; | |
852 | Rddata = p->P_rddata; | |
853 | Wrdata = p->P_wrdata; | |
854 | Turnon = p->P_turnon; | |
855 | Turnoff = p->P_turnoff; | |
46b15d8a RC |
856 | if ((*Turnon)() != SUCCESS) |
857 | return FAIL; | |
48688564 | 858 | DEBUG(4, "Proto started %c\n", *c); |
46b15d8a | 859 | return SUCCESS; |
48688564 SL |
860 | } |
861 | } | |
862 | DEBUG(4, "Proto start-fail %c\n", *c); | |
46b15d8a | 863 | return FAIL; |
48688564 SL |
864 | } |
865 | ||
866 | /*** | |
867 | * putinpub put file in public place | |
868 | * if successful, filename is modified | |
869 | * | |
870 | * return code 0 | FAIL | |
871 | */ | |
872 | ||
873 | putinpub(file, tmp, user) | |
874 | register char *file, *user, *tmp; | |
875 | { | |
876 | char fullname[MAXFULLNAME]; | |
877 | char *lastpart(); | |
878 | int status; | |
879 | ||
880 | sprintf(fullname, "%s/%s/", PUBDIR, user); | |
881 | if (mkdirs(fullname) != 0) { | |
882 | /* can not make directories */ | |
46b15d8a | 883 | return FAIL; |
48688564 SL |
884 | } |
885 | strcat(fullname, lastpart(file)); | |
886 | status = xmv(tmp, fullname); | |
887 | if (status == 0) { | |
888 | strcpy(file, fullname); | |
889 | chmod(subfile(fullname), BASEMODE); | |
890 | } | |
46b15d8a | 891 | return status; |
48688564 SL |
892 | } |
893 | ||
894 | /*** | |
895 | * unlinkdf(file) - unlink D. file | |
896 | * | |
897 | * return code - none | |
898 | */ | |
899 | ||
900 | unlinkdf(file) | |
901 | register char *file; | |
902 | { | |
903 | if (strlen(file) > 6) | |
904 | unlink(subfile(file)); | |
905 | return; | |
906 | } | |
907 | ||
908 | /*** | |
909 | * arrived - notify receiver of arrived file | |
910 | * | |
911 | * return code - none | |
912 | */ | |
913 | ||
914 | arrived(opt, file, nuser, rmtsys, rmtuser) | |
915 | char *file, *nuser, *rmtsys, *rmtuser; | |
916 | { | |
917 | char mbuf[200]; | |
918 | ||
919 | if (!opt) | |
920 | return; | |
921 | sprintf(mbuf, "%s from %s!%s arrived\n", file, rmtsys, rmtuser); | |
46b15d8a | 922 | mailst(nuser, mbuf, CNULL); |
48688564 SL |
923 | return; |
924 | } |