Bell 32V development
[unix-history] / usr / src / cmd / uucp / cntrl.c
CommitLineData
1d38f7f7
TL
1#include "uucp.h"
2#include <sys/types.h>
3#include <sys/stat.h>
4
5
6struct Proto {
7 char P_id;
8 int (*P_turnon)();
9 int (*P_rdmsg)();
10 int (*P_wrmsg)();
11 int (*P_rddata)();
12 int (*P_wrdata)();
13 int (*P_turnoff)();
14};
15
16
17extern int gturnon(), gturnoff();
18extern int grdmsg(), grddata();
19extern int gwrmsg(), gwrdata();
20extern int imsg();
21extern int omsg();
22
23struct Proto Ptbl[]={
24 'g', gturnon, grdmsg, gwrmsg, grddata, gwrdata, gturnoff,
25 '\0'
26};
27
28int (*Rdmsg)()=imsg, (*Rddata)();
29int (*Wrmsg)()=omsg, (*Wrdata)();
30int (*Turnon)(), (*Turnoff)();
31
32
33#define YES "Y"
34#define NO "N"
35#define Y 'Y'
36#define N 'N'
37
38
39#define XUUCP 'X' /* execute uucp (string) */
40#define SLTPTCL 'P' /* select protocol (string) */
41#define USEPTCL 'U' /* use protocol (character) */
42#define RCVFILE 'R' /* receive file (string) */
43#define SNDFILE 'S' /* send file (string) */
44#define RQSTCMPT 'C' /* request complete (string - yes | no) */
45#define HUP 'H' /* ready to hangup (string - yes | no) */
46
47
48#define W_TYPE wrkvec[0]
49#define W_FILE1 wrkvec[1]
50#define W_FILE2 wrkvec[2]
51#define W_USER wrkvec[3]
52#define W_OPTNS wrkvec[4]
53#define W_DFILE wrkvec[5]
54#define W_MODE wrkvec[6]
55
56#define RMESG(m, s) if (rmesg(m, s) != 0) return(FAIL);
57#define RAMESG(s) if (rmesg('\0', s) != 0) return(FAIL)
58#define WMESG(m, s) if(wmesg(m, s) != 0) return(FAIL)
59
60char Wfile[MAXFULLNAME] = {'\0'};
61char Dfile[MAXFULLNAME];
62
63/*******
64 * cntrl(role, wkpre)
65 * int role;
66 * char *wkpre;
67 *
68 * cntrl - this routine will execute the conversation
69 * between the two machines after both programs are
70 * running.
71 *
72 * return codes
73 * SUCCESS - ok
74 * FAIL - failed
75 */
76
77cntrl(role, wkpre)
78int role;
79char *wkpre;
80{
81 char msg[BUFSIZ], rqstr[BUFSIZ];
82 FILE *fp;
83 int filemode;
84 struct stat stbuf;
85 char filename[MAXFULLNAME], wrktype, *wrkvec[20];
86 extern (*Rdmsg)(), (*Wrmsg)();
87 extern char *index(), *lastpart();
88 int status = 1, i;
89 int ret;
90 static int pnum, tmpnum = 0;
91
92 pnum = getpid();
93top:
94 DEBUG(4, "*** TOP *** - role=%d, ", role);
95 if (role == MASTER) {
96 /* get work */
97 if ((i = gtwvec(Wfile, Spool, wkpre, wrkvec)) == 0) {
98 WMESG(HUP, "");
99 RMESG(HUP, msg);
100 goto process;
101 }
102 wrktype = W_TYPE[0];
103
104 DEBUG(4, "wrktype %c, ", wrktype);
105 if (wrktype == XUUCP) {
106 int n;
107 msg[0] = '\0';
108 for (n = 1; n < i; n++) {
109 strcat(msg, " ");
110 strcat(msg, wrkvec[n]);
111 }
112 sprintf(rqstr, "X %s", msg);
113 logent(rqstr, "REQUEST");
114 goto sendmsg;
115 }
116
117 ASSERT(i > 4, "ARG COUNT - %d\n", i);
118 sprintf(msg, " %s %s %s %s %s %s",
119 W_FILE1, W_FILE2, W_USER,
120 W_OPTNS, W_DFILE, W_MODE);
121 strcpy(User, W_USER);
122 ASSERT(strlen(User) <= 10, "User - %s\n", User);
123 sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1,
124 W_FILE2, W_USER);
125 logent(rqstr, "REQUEST");
126 DEBUG(4, "User - %s\n", User);
127 if (wrktype == SNDFILE ) {
128 strcpy(filename, W_FILE1);
129 expfile(filename);
130 if (chkpth(User, "", filename)) {
131 /* access denied */
132 logent("DENIED", "ACCESS");
133 unlink(W_DFILE);
134 unlink(Wfile);
135 goto top;
136 }
137
138 strcpy(Dfile, W_DFILE);
139 if ((fp = fopen(Dfile, "r")) == NULL
140 && (fp = fopen(filename, "r")) == NULL) {
141 /* can not read data file */
142 logent("CAN'T READ DATA", "FAILED");
143 unlink(Wfile);
144 unlink(Dfile);
145 goto top;
146 }
147 }
148
149 if (wrktype == RCVFILE) {
150 strcpy(filename, W_FILE2);
151 expfile(filename);
152 if (chkpth(User, "", filename)
153 || chkperm(filename, User, index(W_OPTNS, 'd'))) {
154 /* access denied */
155 logent("DENIED", "ACCESS");
156 unlink(Wfile);
157 goto top;
158 }
159 sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
160 if ((fp = fopen(Dfile, "w")) == NULL) {
161 /* can not create temp */
162 logent("CAN'T CREATE TM", "FAILED");
163 unlink(Wfile);
164 unlink(Dfile);
165 goto top;
166 }
167 chmod(Dfile, 0666);
168 }
169sendmsg:
170 DEBUG(4, "wrktype - %c, ", wrktype);
171 DEBUG(4, " fileno - %d\n", fileno(fp));
172 WMESG(wrktype, msg);
173 RMESG(wrktype, msg);
174 goto process;
175 }
176
177 /* role is slave */
178 RAMESG(msg);
179 goto process;
180
181process:
182 DEBUG(4, " PROCESS: msg - %s\n", msg);
183 switch (msg[0]) {
184
185 case RQSTCMPT:
186 DEBUG(4, "%s\n", "RQSTCMPT:");
187 logent((msg[1] == 'N') ? "FAILED" : "SUCCEEDED", "REQUEST");
188 if (role == MASTER) {
189 notify(W_OPTNS, W_USER, W_FILE1, Rmtname,
190 (msg[1] == N) ? "failed" : "succeeded");
191 }
192 goto top;
193
194 case HUP:
195 DEBUG(4, "%s\n", "HUP:");
196 if (msg[1] == Y) {
197 WMESG(HUP, YES);
198 (*Turnoff)();
199 Rdmsg = imsg;
200 Wrmsg = omsg;
201 return(0);
202 }
203
204 if (msg[1] == N) {
205 ASSERT(role == MASTER,
206 "role - %d", role);
207 role = SLAVE;
208 goto top;
209 }
210
211 /* get work */
212 if (!iswrk(Wfile, "chk", Spool, wkpre)) {
213 WMESG(HUP, YES);
214 RMESG(HUP, msg);
215 goto process;
216 }
217
218 WMESG(HUP, NO);
219 role = MASTER;
220 goto top;
221
222 case XUUCP:
223 if (role == MASTER) {
224 unlink(Wfile);
225 goto top;
226 }
227
228 /* slave part */
229 i = getargs(msg, wrkvec);
230 strcpy(filename, W_FILE1);
231 if (index(filename, ';') != NULL
232 || index(W_FILE2, ';') != NULL
233 || i < 3) {
234 WMESG(XUUCP, NO);
235 goto top;
236 }
237 expfile(filename);
238 if (chkpth("", Rmtname, filename)) {
239 WMESG(XUUCP, NO);
240 logent("XUUCP DENIED", filename);
241 goto top;
242 }
243 sprintf(rqstr, "%s %s", filename, W_FILE2);
244 xuucp(rqstr);
245 WMESG(XUUCP, YES);
246 goto top;
247
248 case SNDFILE:
249 /* MASTER section of SNDFILE */
250
251 DEBUG(4, "%s\n", "SNDFILE:");
252 if (msg[1] == N) {
253 logent("DENIED", "REQUEST");
254 ASSERT(role == MASTER,
255 "role - %d", role);
256 fclose(fp);
257 unlink(W_DFILE);
258 unlink(Wfile);
259 goto top;
260 }
261
262 if (msg[1] == Y) {
263 /* send file */
264 ASSERT(role == MASTER,
265 "role - %d", role);
266 ret = (*Wrdata)(fp, Ofn);
267 fclose(fp);
268 if (ret != 0)
269 return(FAIL);
270 unlink(W_DFILE);
271 RMESG(RQSTCMPT, msg);
272 goto process;
273 }
274
275 /* SLAVE section of SNDFILE */
276 ASSERT(role == SLAVE,
277 "role - %d", role);
278
279 /* request to receive file */
280 /* check permissions */
281 i = getargs(msg, wrkvec);
282 ASSERT(i > 4, "ARG COUNT - %d\n", i);
283 sprintf(rqstr, "%s %s %s %s", W_TYPE, W_FILE1,
284 W_FILE2, W_USER);
285 logent(rqstr, "REQUESTED");
286 DEBUG(4, "msg - %s\n", msg);
287 DEBUG(4, "W_FILE2 - %s\n", W_FILE2);
288 strcpy(filename, W_FILE2);
289 expfile(filename);
290 if (chkpth("", Rmtname, filename)
291 || chkperm(filename, Loginuser, index(W_OPTNS, 'd'))) {
292 WMESG(SNDFILE, NO);
293 logent("DENIED", "PERMISSION");
294 goto top;
295 }
296 if (isdir(filename)) {
297 strcat(filename, "/");
298 strcat(filename, lastpart(W_FILE1));
299 }
300 strcpy(User, W_USER);
301 ASSERT(strlen(User) <= 10, "User - %s\n", User);
302
303 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
304 sprintf(Dfile, "%s/TM.%05d.%03d", Spool, pnum, tmpnum++);
305 if((fp = fopen(Dfile, "w")) == NULL) {
306 WMESG(SNDFILE, NO);
307 logent("CAN'T OPEN", "DENIED");
308 unlink(Dfile);
309 goto top;
310 }
311 chmod(Dfile, 0666);
312
313 WMESG(SNDFILE, YES);
314 ret = (*Rddata)(Ifn, fp);
315 fclose(fp);
316 if (ret != 0)
317 return(FAIL);
318 /* copy to user directory */
319 status = xmv(Dfile, filename);
320 WMESG(RQSTCMPT, status ? NO : YES);
321 logent(status ? "FAILED" : "SUCCEEDED", "COPY");
322 sscanf(W_MODE, "%o", &filemode);
323 DEBUG(4, "mode - %o\n", filemode);
324 if (filemode <= 0)
325 filemode = 0666;
326 if (status == 0) {
327 filemode |= 0666;
328 chmod(filename, filemode | 0666);
329 }
330 goto top;
331
332 case RCVFILE:
333 /* MASTER section of RCVFILE */
334
335 DEBUG(4, "%s\n", "RCVFILE:");
336 if (msg[1] == N) {
337 logent("REQUEST", "DENIED");
338 ASSERT(role == MASTER,
339 "role - %d", role);
340 unlink(Wfile);
341 fclose(fp);
342 goto top;
343 }
344
345 if (msg[1] == Y) {
346 /* receive file */
347 ASSERT(role == MASTER,
348 "role - %d", role);
349 ret = (*Rddata)(Ifn, fp);
350 fclose(fp);
351 if (ret != 0)
352 return(FAIL);
353 /* copy to user directory */
354 if (isdir(filename)) {
355 strcat(filename, "/");
356 strcat(filename, lastpart(W_FILE1));
357 }
358 status = xmv(Dfile, filename);
359 WMESG(RQSTCMPT, status ? NO : YES);
360 logent(status ? "FAILED" : "SUCCEEDED", "COPY");
361 notify(W_OPTNS, W_USER, filename, Rmtname,
362 status ? "failed" : "succeeded");
363 sscanf(&msg[2], "%o", &filemode);
364 DEBUG(4, "mode - %o\n", filemode);
365 if (filemode <= 0)
366 filemode = 0666;
367 if (status == 0) {
368 unlink(Dfile);
369 filemode |= 0666;
370 chmod(filename, filemode | 0666);
371 }
372 goto top;
373 }
374
375 /* SLAVE section of RCVFILE */
376 ASSERT(role == SLAVE,
377 "role - %d", role);
378
379 /* request to send file */
380 strcpy(rqstr, msg);
381 logent(rqstr, "REQUESTED");
382
383 /* check permissions */
384 i = getargs(msg, wrkvec);
385 ASSERT(i > 3, "ARG COUNT - %d\n", i);
386 DEBUG(4, "msg - %s\n", msg);
387 DEBUG(4, "W_FILE1 - %s\n", W_FILE1);
388 strcpy(filename, W_FILE1);
389 expfile(filename);
390 if (isdir(filename)) {
391 strcat(filename, "/");
392 strcat(filename, lastpart(W_FILE2));
393 }
394 strcpy(User, W_USER);
395 ASSERT(strlen(User) <= 10, "User - %s\n", User);
396 if (chkpth("", Rmtname, filename) != 0) {
397 WMESG(RCVFILE, NO);
398 logent("DENIED", "PERMISSION");
399 goto top;
400 }
401 DEBUG(4, "chkpth ok Rmtname - %s\n", Rmtname);
402
403 if ((fp = fopen(filename, "r")) == NULL) {
404 WMESG(RCVFILE, NO);
405 logent("CAN'T OPEN", "DENIED");
406 goto top;
407 }
408
409 /* ok to send file */
410 ret = stat(filename, &stbuf);
411 ASSERT(ret != -1, "STAT FAILED %s", filename);
412 sprintf(msg, "%s %o", YES, stbuf.st_mode & 0777);
413 WMESG(RCVFILE, msg);
414 ret = (*Wrdata)(fp, Ofn);
415 fclose(fp);
416 if (ret != 0)
417 return(FAIL);
418 RMESG(RQSTCMPT, msg);
419 goto process;
420 }
421 return(FAIL);
422}
423
424
425/***
426 * rmesg(c, msg) read message 'c'
427 * char *msg, c;
428 *
429 * return code: 0 | FAIL
430 */
431
432rmesg(c, msg)
433char *msg, c;
434{
435 char str[50];
436
437 DEBUG(4, "rmesg - '%c' ", c);
438 if ((*Rdmsg)(msg, Ifn) != 0) {
439 DEBUG(4, "got %s\n", "FAIL");
440 sprintf(str, "expected '%c' got FAIL", c);
441 logent(str, "BAD READ");
442 return(FAIL);
443 }
444 if (c != '\0' && msg[0] != c) {
445 DEBUG(4, "got %s\n", msg);
446 sprintf(str, "expected '%c' got %.25s", c, msg);
447 logent(str, "BAD READ");
448 return(FAIL);
449 }
450 DEBUG(4, "got %.25s\n", msg);
451 return(0);
452}
453
454
455/***
456 * wmesg(m, s) write a message (type m)
457 * char *s, m;
458 *
459 * return codes: 0 - ok | FAIL - ng
460 */
461
462wmesg(m, s)
463char *s, m;
464{
465 DEBUG(4, "wmesg '%c'", m);
466 DEBUG(4, "%.25s\n", s);
467 return((*Wrmsg)(m, s, Ofn));
468}
469
470
471/***
472 * notify(options, user, file, sys, stwork) mail results of copy
473 * char *options, *user, *file, *sys, *stword);
474 *
475 * return codes: none
476 */
477
478notify(options, user, file, sys, stword)
479char *options, *user, *file, *sys, *stword;
480{
481 char str[200];
482 if (index(options, 'm') == NULL)
483 return;
484 sprintf(str, "file %s, system %s, copy %s\n", file, sys, stword);
485 mailst(user, str);
486 return;
487}
488
489
490/***
491 * startup(role)
492 * int role;
493 *
494 * startup - this routine will converse with the remote
495 * machine, agree upon a protocol (if possible) and start the
496 * protocol.
497 *
498 * return codes:
499 * SUCCESS - successful protocol selection
500 * FAIL - can't find common or open failed
501 */
502
503startup(role)
504int role;
505{
506 extern (*Rdmsg)(), (*Wrmsg)();
507 extern imsg(), omsg();
508 extern char *blptcl(), fptcl();
509 char msg[BUFSIZ], str[BUFSIZ];
510
511 Rdmsg = imsg;
512 Wrmsg = omsg;
513 if (role == MASTER) {
514 RMESG(SLTPTCL, msg);
515 if ((str[0] = fptcl(&msg[1])) == NULL) {
516 /* no protocol match */
517 WMESG(USEPTCL, NO);
518 return(FAIL);
519 }
520 str[1] = '\0';
521 WMESG(USEPTCL, str);
522 if (stptcl(str) != 0)
523 return(FAIL);
524 DEBUG(4, "protocol %s\n", str);
525 return(SUCCESS);
526 }
527 else {
528 WMESG(SLTPTCL, blptcl(str));
529 RMESG(USEPTCL, msg);
530 if (msg[1] == N) {
531 return(FAIL);
532 }
533
534 if (stptcl(&msg[1]) != 0)
535 return(FAIL);
536 DEBUG(4, "Protocol %s\n", msg);
537 return(SUCCESS);
538 }
539}
540
541
542/*******
543 * char
544 * fptcl(str)
545 * char *str;
546 *
547 * fptcl - this routine will choose a protocol from
548 * the input string (str) and return the found letter.
549 *
550 * return codes:
551 * '\0' - no acceptable protocol
552 * any character - the chosen protocol
553 */
554
555char
556fptcl(str)
557char *str;
558{
559 struct Proto *p;
560 extern char *index();
561
562 for (p = Ptbl; p->P_id != '\0'; p++) {
563 if (index(str, p->P_id) != NULL) {
564 return(p->P_id);
565 }
566 }
567
568 return('\0');
569}
570
571
572/***
573 * char *
574 * blptcl(str)
575 * char *str;
576 *
577 * blptcl - this will build a string of the
578 * letters of the available protocols and return
579 * the string (str).
580 *
581 * return:
582 * a pointer to string (str)
583 */
584
585char *
586blptcl(str)
587char *str;
588{
589 struct Proto *p;
590 char *s;
591
592 for (p = Ptbl, s = str; (*s++ = p->P_id) != '\0'; p++);
593 return(str);
594}
595
596/***
597 * stptcl(c)
598 * char *c;
599 *
600 * stptcl - this routine will set up the six routines
601 * (Rdmsg, Wrmsg, Rddata, Wrdata, Turnon, Turnoff) for the
602 * desired protocol.
603 *
604 * return codes:
605 * SUCCESS - ok
606 * FAIL - no find or failed to open
607 *
608 */
609
610stptcl(c)
611char *c;
612{
613 struct Proto *p;
614
615 for (p = Ptbl; p->P_id != '\0'; p++) {
616 if (*c == p->P_id) {
617 /* found protocol - set routines */
618 Rdmsg = p->P_rdmsg;
619 Wrmsg = p->P_wrmsg;
620 Rddata = p->P_rddata;
621 Wrdata = p->P_wrdata;
622 Turnon = p->P_turnon;
623 Turnoff = p->P_turnoff;
624 if ((*Turnon)() != 0)
625 return(FAIL);
626 DEBUG(4, "Proto started %c\n", *c);
627 return(SUCCESS);
628 }
629 }
630 DEBUG(4, "Proto start-fail %c\n", *c);
631 return(FAIL);
632}