bug fixes and changes from Rick Adams
[unix-history] / usr / src / usr.bin / uucp / uucico / cntrl.c
CommitLineData
48688564 1#ifndef lint
46b15d8a 2static 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 10extern int errno;
48688564
SL
11
12struct 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
22extern int gturnon(), gturnoff();
23extern int grdmsg(), grddata();
24extern int gwrmsg(), gwrdata();
25extern int imsg(), omsg();
46b15d8a
RC
26#ifdef BSDTCP
27extern int tnullf();
28extern int twrmsg(), trdmsg();
29extern int twrdata(), trddata();
30#endif BSDTCP
31#ifdef PAD
32extern int fturnon(), fturnoff();
33extern int frdmsg(), frddata();
34extern int fwrmsg(), fwrdata();
35#endif PAD
48688564
SL
36
37struct 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 48int (*Imsg)() = imsg, (*Omsg)() = omsg;
48688564
SL
49
50int (*Rdmsg)()=imsg, (*Rddata)();
51int (*Wrmsg)()=omsg, (*Wrdata)();
52int (*Turnon)(), (*Turnoff)();
53
54
46b15d8a
RC
55static char *YES = "Y";
56static 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
67char *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
101char Wfile[MAXFULLNAME] = {'\0'};
102char Dfile[MAXFULLNAME];
103
104/*
105 * To avoid a huge backlog of X. files, start uuxqt every so often.
48688564
SL
106 */
107static int nXfiles = 0; /* number of X files since last uuxqt start */
108static int nXQTs = 0; /* number of uuxqts started */
46b15d8a
RC
109static char send_or_receive;
110struct 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
122cntrl(role, wkpre)
123int role;
124char *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';
141top:
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 }
244sendmsg:
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
255process:
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
621rmesg(c, msg, n)
622register char *msg, c;
623register 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
660wmesg(m, s)
661register 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
675notify(mailopt, user, file, sys, msgcode)
676char *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
704lnotify(user, file, mesg)
705char *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
727startup(role)
728int 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
778char
779fptcl(str)
780register 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
815char *
816blptcl(str)
817register 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
842stptcl(c)
843register 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
873putinpub(file, tmp, user)
874register 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
900unlinkdf(file)
901register 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
914arrived(opt, file, nuser, rmtsys, rmtuser)
915char *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}