|
|
1.1 root 1: /* %W%
2:
3: * uucp file transfer program:
4: * to place a call to a remote machine, login, and
5: * copy files between the two machines.
6:
7: */
8: #include "uucp.h"
9: VERSION(%W%);
10:
11: #ifndef V7
12: #include <sys/sysmacros.h>
13: #endif
14:
15: jmp_buf Sjbuf;
16: extern int Errorrate;
17: char uuxqtarg[MAXBASENAME] = {'\0'};
18:
19: #define USAGE "[-xNUM] [-r[0|1]] -sSYSTEM"
20:
21: extern void closedem();
22:
23: main(argc, argv, envp)
24: char *argv[];
25: char **envp;
26: {
27: extern onintr(), timeout();
28: extern intrEXIT();
29: extern char *pskip();
30: int ret, seq, exitcode;
31: char file[NAMESIZE];
32: char msg[BUFSIZ], *p, *q;
33: char xflag[6]; /* -xN N is single digit */
34: char *ttyn;
35: char cb[128];
36: time_t ts, tconv;
37: #ifndef V7
38: long minulimit, dummy;
39: #endif V7
40:
41: Uid = getuid();
42: Euid = geteuid(); /* this should be UUCPUID */
43: if (Uid == 0)
44: setuid(UUCPUID); /* fails in ATTSV, but so what? */
45: Env = envp;
46: Role = SLAVE;
47: strcpy(Logfile, LOGCICO);
48: *Rmtname = NULLCHAR;
49:
50: closedem();
51: time(&Nstat.t_qtime);
52: tconv = Nstat.t_start = Nstat.t_qtime;
53: strcpy(Progname, "uucico");
54: Pchar = 'C';
55: (void) signal(SIGILL, intrEXIT);
56: (void) signal(SIGTRAP, intrEXIT);
57: (void) signal(SIGIOT, intrEXIT);
58: (void) signal(SIGEMT, intrEXIT);
59: (void) signal(SIGFPE, intrEXIT);
60: (void) signal(SIGBUS, intrEXIT);
61: (void) signal(SIGSEGV, intrEXIT);
62: (void) signal(SIGSYS, intrEXIT);
63: (void) signal(SIGPIPE, SIG_IGN);
64: (void) signal(SIGINT, onintr);
65: (void) signal(SIGHUP, onintr);
66: (void) signal(SIGQUIT, onintr);
67: (void) signal(SIGTERM, onintr);
68: #ifdef ATTSV
69: (void) signal(SIGUSR1, SIG_IGN);
70: (void) signal(SIGUSR2, SIG_IGN);
71: #endif
72: ret = guinfo(Euid, User);
73: ASSERT(ret == 0, "BAD UID ", "", ret);
74: strncpy(Uucp, User, NAMESIZE);
75:
76: setuucp(User);
77: ret = guinfo(Uid, Loginuser);
78: ASSERT(ret == 0, "BAD LOGIN_UID ", "", ret);
79:
80: *xflag = NULLCHAR;
81: Ifn = Ofn = -1;
82: while ((ret = getopt(argc, argv, "d:r:s:x:")) != EOF) {
83: switch (ret) {
84: case 'd':
85: Spool = optarg;
86: break;
87: case 'r':
88: Role = atoi(optarg);
89: break;
90: case 's':
91: /* avoid 2 searches of the systems file
92: if (versys(optarg, 0)) {
93: DEBUG(4, "%s not in Systems file\n", optarg);
94: cleanup(101);
95: }
96: */
97: strncpy(Rmtname, optarg, MAXBASENAME);
98: Rmtname[MAXBASENAME] = '\0';
99: /* set args for possible xuuxqt call */
100: strcpy(uuxqtarg, Rmtname);
101: break;
102: case 'x':
103: Debug = atoi(optarg);
104: if (Debug <= 0)
105: Debug = 1;
106: if (Debug > 9)
107: Debug = 9;
108: (void) sprintf(xflag, "-x%d", Debug);
109: break;
110: default:
111: (void) fprintf(stderr, "\tusage: %s %s\n",
112: Progname, USAGE);
113: exit(1);
114: }
115: }
116:
117: if (Role == MASTER) {
118: if (*Rmtname == NULLCHAR) {
119: DEBUG(5, "No -s specified\n" , "");
120: cleanup(101);
121: }
122: /* get Myname - it depends on who I'm calling--Rmtname */
123: (void) mchFind(Rmtname);
124: myName(Myname);
125: if (EQUALSN(Rmtname, Myname, SYSNSIZE)) {
126: DEBUG(5, "This system specified: -sMyname: %s, ", Myname);
127: cleanup(101);
128: }
129: }
130:
131: ASSERT(chdir(Spool) == 0, Ct_CHDIR, Spool, errno);
132: strcpy(Wrkdir, Spool);
133:
134: if (Role == SLAVE) {
135:
136: /*
137: * initial handshake
138: */
139: ret = savline();
140: Ifn = 0;
141: Ofn = 1;
142: fixline(Ifn, 0, D_ACU);
143: freopen(RMTDEBUG, "a", stderr);
144: setbuf(stderr, (char *)NULL);
145: /* get MyName - use logFind to check PERMISSIONS file */
146: (void) logFind(Loginuser, "");
147: myName(Myname);
148:
149: DEBUG(4,"cico.c: Myname - %s\n",Myname);
150: DEBUG(4,"cico.c: Loginuser - %s\n",Loginuser);
151: Nstat.t_scall = times(&Nstat.t_tga);
152: (void) sprintf(msg, "here=%s", Myname);
153: omsg('S', msg, Ofn);
154: (void) signal(SIGALRM, timeout);
155: (void) alarm(2 * MAXMSGTIME); /* give slow machines a second chance */
156: if (setjmp(Sjbuf)) {
157:
158: /*
159: * timed out
160: */
161: ret = restline();
162: rmlock(CNULL);
163: exit(0);
164: }
165: for (;;) {
166: ret = imsg(msg, Ifn);
167: if (ret != 0) {
168: (void) alarm(0);
169: ret = restline();
170: rmlock(CNULL);
171: exit(0);
172: }
173: if (msg[0] == 'S')
174: break;
175: }
176: Nstat.t_ecall = times(&Nstat.t_tga);
177: (void) alarm(0);
178: q = &msg[1];
179: p = pskip(q);
180: strncpy(Rmtname, q, MAXBASENAME);
181: Rmtname[MAXBASENAME] = '\0';
182:
183: seq = 0;
184: while (*p == '-') {
185: q = pskip(p);
186: switch(*(++p)) {
187: case 'x':
188: Debug = atoi(++p);
189: if (Debug <= 0)
190: Debug = 1;
191: break;
192: case 'Q':
193: seq = atoi(++p);
194: break;
195: default:
196: break;
197: }
198: p = q;
199: }
200: DEBUG(4, "sys-%s\n", Rmtname);
201:
202: #ifdef NOSTRANGERS
203: /* here's the place to look the remote system up in the Systems file.
204: * If the command NOSTRANGERS is executable and
205: /* If they're not in my file then hang up */
206: if ( (access(NOSTRANGERS, 1) == 0) && versys(Rmtname, 1)) {
207: char unkcmd[64];
208: register char *p;
209:
210: omsg('R', "You are unknown to me", Ofn);
211: for (p = Rmtname; *p; p++)
212: if (*p == '\'')
213: *p = ' '; /* cheap hack. who cares. */
214: (void) sprintf(unkcmd, "%s '%s'", NOSTRANGERS, Rmtname);
215: system(unkcmd);
216: cleanup(101);
217: }
218: #endif NOSTRANGERS
219:
220: if (mlock(Rmtname)) {
221: omsg('R', "LCK", Ofn);
222: cleanup(101);
223: }
224:
225: /* validate login using PERMISSIONS file */
226: if (logFind(Loginuser, Rmtname) == FAIL) {
227: Uerror = SS_BAD_LOG_MCH;
228: logent(UERRORTEXT, "FAILED");
229: systat(Rmtname, SS_BAD_LOG_MCH, UERRORTEXT,
230: Retrytime);
231: omsg('R', "LOGIN", Ofn);
232: cleanup(101);
233: }
234:
235: ret = callBack();
236: DEBUG(4,"return from callcheck: %s",ret ? "TRUE" : "FALSE");
237: if (ret==TRUE) {
238: (void) signal(SIGINT, SIG_IGN);
239: (void) signal(SIGHUP, SIG_IGN);
240: omsg('R', "CB", Ofn);
241: logent("CALLBACK", "REQUIRED");
242:
243: /*
244: * set up for call back
245: */
246: systat(Rmtname, SS_CALLBACK, "CALL BACK", Retrytime);
247: gename(CMDPRE, Rmtname, 'C', file);
248: (void) close(creat(file, CFILEMODE));
249: xuucico(Rmtname);
250: cleanup(101);
251: }
252:
253: if (callok(Rmtname) == SS_SEQBAD) {
254: Uerror = SS_SEQBAD;
255: logent(UERRORTEXT, "PREVIOUS");
256: omsg('R', "BADSEQ", Ofn);
257: cleanup(101);
258: }
259:
260: if ((ret = gnxseq(Rmtname)) == seq) {
261: omsg('R', "OK", Ofn);
262: cmtseq();
263: } else {
264: Uerror = SS_SEQBAD;
265: systat(Rmtname, SS_SEQBAD, UERRORTEXT, Retrytime);
266: logent(UERRORTEXT, "HANDSHAKE FAILED");
267: ulkseq();
268: omsg('R', "BADSEQ", Ofn);
269: cleanup(101);
270: }
271: if ((ttyn = ttyname(Ifn)) != NULL)
272: strcpy(Dc, BASENAME(ttyn, '/'));
273: else
274: strcpy(Dc, "notty");
275: /* set args for possible xuuxqt call */
276: strcpy(uuxqtarg, Rmtname);
277: }
278:
279: strcpy(User, Uucp);
280: /*
281: * Ensure reasonable ulimit (MINULIMIT)
282: */
283:
284: #ifndef V7
285: minulimit = ulimit(1,dummy);
286: ASSERT(minulimit >= MINULIMIT, "ULIMIT TOO SMALL",
287: Loginuser, minulimit);
288: #endif
289: if (Role == MASTER && callok(Rmtname) != 0) {
290: logent("SYSTEM STATUS", "CAN NOT CALL");
291: cleanup(101);
292: }
293:
294: chremdir(Rmtname);
295:
296: (void) strcpy(Wrkdir, RemSpool);
297: if (Role == MASTER) {
298:
299: /*
300: * master part
301: */
302: (void) signal(SIGINT, SIG_IGN);
303: (void) signal(SIGHUP, SIG_IGN);
304: (void) signal(SIGQUIT, SIG_IGN);
305: if (Ifn != -1 && Role == MASTER) {
306: (void) write(Ofn, EOTMSG, strlen(EOTMSG));
307: (void) close(Ofn);
308: (void) close(Ifn);
309: Ifn = Ofn = -1;
310: rmlock(CNULL);
311: sleep(3);
312: }
313: (void) sprintf(msg, "call to %s ", Rmtname);
314: if (mlock(Rmtname) != 0) {
315: logent(msg, "LOCKED");
316: CDEBUG(1, "Currently Talking With %s\n",
317: Rmtname);
318: cleanup(100);
319: }
320: Nstat.t_scall = times(&Nstat.t_tga);
321: Ofn = Ifn = conn(Rmtname);
322: Nstat.t_ecall = times(&Nstat.t_tga);
323: if (Ofn < 0) {
324: delock(Rmtname);
325: logent(UERRORTEXT, "CONN FAILED");
326: systat(Rmtname, Uerror, UERRORTEXT, Retrytime);
327: cleanup(101);
328: } else {
329: logent(msg, "SUCCEEDED");
330: ttyn = ttyname(Ifn);
331: }
332:
333: if (setjmp(Sjbuf)) {
334: delock(Rmtname);
335: Uerror = SS_LOGIN_FAILED;
336: logent(Rmtname, UERRORTEXT);
337: systat(Rmtname, SS_LOGIN_FAILED,
338: UERRORTEXT, Retrytime);
339: DEBUG(4, "%s - failed\n", UERRORTEXT);
340: cleanup(101);
341: }
342: (void) signal(SIGALRM, timeout);
343: /* give slow guys lots of time to thrash */
344: (void) alarm(3 * MAXMSGTIME);
345: for (;;) {
346: ret = imsg(msg, Ifn);
347: if (ret != 0) {
348: continue; /* try again */
349: }
350: if (msg[0] == 'S')
351: break;
352: }
353: (void) alarm(0);
354: if(EQUALSN("here=", &msg[1], 5)){
355: /*
356: /* this is a problem. We'd like to compare with an
357: * untruncated Rmtname but we fear incompatability.
358: * So we'll look at most 6 chars (at most).
359: */
360: if(!EQUALSN(&msg[6], Rmtname, (strlen(Rmtname)< 7 ?
361: strlen(Rmtname) : 6))){
362: delock(Rmtname);
363: Uerror = SS_WRONG_MCH;
364: logent(&msg[6], UERRORTEXT);
365: systat(Rmtname, SS_WRONG_MCH, UERRORTEXT,
366: Retrytime);
367: DEBUG(4, "%s - failed\n", UERRORTEXT);
368: cleanup(101);
369: }
370: }
371: CDEBUG(1,"Login Successful: System=%s\n",&msg[6]);
372: seq = gnxseq(Rmtname);
373: (void) sprintf(msg, "%s -Q%d %s", Myname, seq, xflag);
374: omsg('S', msg, Ofn);
375: (void) alarm(2 * MAXMSGTIME); /* give slow guys some thrash time */
376: for (;;) {
377: ret = imsg(msg, Ifn);
378: DEBUG(3, "msg-%s\n", msg);
379: if (ret != 0) {
380: (void) alarm(0);
381: delock(Rmtname);
382: ulkseq();
383: cleanup(101);
384: }
385: if (msg[0] == 'R')
386: break;
387: }
388: (void) alarm(0);
389:
390: /* check for rejects from remote */
391: Uerror = 0;
392: if (EQUALS(&msg[1], "LCK"))
393: Uerror = SS_RLOCKED;
394: else if (EQUALS(&msg[1], "LOGIN"))
395: Uerror = SS_RLOGIN;
396: else if (EQUALS(&msg[1], "CB"))
397: Uerror = SS_CALLBACK;
398: else if (EQUALS(&msg[1], "You are unknown to me"))
399: Uerror = SS_RUNKNOWN;
400: else if (EQUALS(&msg[1], "BADSEQ"))
401: Uerror = SS_SEQBAD;
402: else if (!EQUALS(&msg[1], "OK"))
403: Uerror = SS_UNKNOWN_RESPONSE;
404: if (Uerror) {
405: delock(Rmtname);
406: systat(Rmtname, Uerror, UERRORTEXT, Retrytime);
407: logent(UERRORTEXT, "HANDSHAKE FAILED");
408: CDEBUG(1, "HANDSHAKE FAILED: %s\n", UERRORTEXT);
409: ulkseq();
410: cleanup(101);
411: }
412: cmtseq();
413: }
414: DEBUG(4, " Rmtname %s, ", Rmtname);
415: DEBUG(4, "Role %s, ", Role ? "MASTER" : "SLAVE");
416: DEBUG(4, "Ifn - %d, ", Ifn);
417: DEBUG(4, "Loginuser - %s\n", Loginuser);
418:
419: /* alarm/setjmp added here due to experience with uucico
420: * hanging for hours in imsg().
421: */
422: if (setjmp(Sjbuf)) {
423: delock(Rmtname);
424: logent("startup", "TIMEOUT");
425: DEBUG(4, "%s - timeout\n", "startup");
426: cleanup(101);
427: }
428: (void) alarm(MAXSTART);
429: ret = startup(Role);
430: (void) alarm(0);
431:
432: if (ret != SUCCESS) {
433: delock(Rmtname);
434: logent("startup", "FAILED");
435: Uerror = SS_STARTUP;
436: CDEBUG(1, "%s\n", UERRORTEXT);
437: systat(Rmtname, Uerror, UERRORTEXT, Retrytime);
438: exitcode = 101;
439: } else {
440: logent("startup", "OK");
441: systat(Rmtname, SS_INPROGRESS, UTEXT(SS_INPROGRESS),Retrytime);
442: Nstat.t_sftp = times(&Nstat.t_tga);
443:
444: exitcode = cntrl(Role);
445: Nstat.t_eftp = times(&Nstat.t_tga);
446: DEBUG(4, "cntrl - %d\n", exitcode);
447: (void) signal(SIGINT, SIG_IGN);
448: (void) signal(SIGHUP, SIG_IGN);
449: (void) signal(SIGALRM, timeout);
450:
451: if (exitcode == 0) {
452: (void) time(&ts);
453: (void) sprintf(cb, "conversation complete %s %ld",
454: Dc, ts - tconv);
455: logent(cb, "OK");
456: systat(Rmtname, SS_OK, UTEXT(SS_OK), Retrytime);
457:
458: } else {
459: logent("conversation complete", "FAILED");
460: systat(Rmtname, SS_CONVERSATION,
461: UTEXT(SS_CONVERSATION), 0);
462: }
463: (void) alarm(2 * MAXMSGTIME); /* give slow guys some thrash time */
464: omsg('O', "OOOOO", Ofn);
465: CDEBUG(4, "send OO %d,", ret);
466: if (!setjmp(Sjbuf)) {
467: for (;;) {
468: omsg('O', "OOOOO", Ofn);
469: ret = imsg(msg, Ifn);
470: if (ret != 0)
471: break;
472: if (msg[0] == 'O')
473: break;
474: }
475: }
476: (void) alarm(0);
477: }
478: cleanup(exitcode);
479: }
480:
481: /*
482: * clean and exit with "code" status
483: */
484: cleanup(code)
485: register int code;
486: {
487: int ret;
488:
489: (void) signal(SIGINT, SIG_IGN);
490: (void) signal(SIGHUP, SIG_IGN);
491: rmlock(CNULL);
492: closedem();
493: if (Role == SLAVE) {
494: ret = restline();
495: DEBUG(4, "ret restline - %d\n", ret);
496: sethup(0);
497: }
498: if (Ofn != -1) {
499: if (Role == MASTER)
500: (void) write(Ofn, EOTMSG, strlen(EOTMSG));
501: (void) close(Ifn);
502: (void) close(Ofn);
503: }
504: DEBUG(4, "exit code %d\n", code);
505: CDEBUG(1, "Conversation Complete: Status %s\n\n",
506: code ? "FAILED" : "SUCCEEDED");
507:
508: cleanTM();
509: if (code == 0)
510: xuuxqt(uuxqtarg);
511: exit(code);
512: }
513:
514: short TM_cnt = 0;
515: char TM_name[MAXNAMESIZE];
516:
517: cleanTM()
518: {
519: register int i;
520: char tm_name[MAXNAMESIZE];
521:
522: DEBUG(7,"TM_cnt: %d\n",TM_cnt);
523: for(i=0; i < TM_cnt; i++) {
524: (void) sprintf(tm_name, "%s.%3.3d", TM_name, i);
525: DEBUG(7, "tm_name: %s\n", tm_name);
526: unlink(tm_name);
527: }
528: }
529:
530: TMname(file, pnum)
531: char *file;
532: {
533:
534: (void) sprintf(file, "%s/TM.%.5d.%.3d", RemSpool, pnum, TM_cnt);
535: if (TM_cnt == 0)
536: (void) sprintf(TM_name, "%s/TM.%.5d", RemSpool, pnum);
537: DEBUG(7, "TMname(%s)\n", file);
538: TM_cnt++;
539: }
540:
541: /*
542: * intrrupt - remove locks and exit
543: */
544: onintr(inter)
545: register int inter;
546: {
547: char str[30];
548: /* I'm putting a test for zero here because I saw it happen
549: * and don't know how or why, but it seemed to then loop
550: * here for ever?
551: */
552: if (inter == 0)
553: exit(99);
554: (void) signal(inter, SIG_IGN);
555: (void) sprintf(str, "SIGNAL %d", inter);
556: logent(str, "CAUGHT");
557: cleanup(inter);
558: }
559:
560: /*ARGSUSED*/
561: intrEXIT(inter)
562: {
563: char cb[10];
564: extern int errno;
565:
566: (void) sprintf(cb, "%d", errno);
567: logent("INTREXIT", cb);
568: (void) signal(SIGIOT, SIG_DFL);
569: (void) signal(SIGILL, SIG_DFL);
570: rmlock(CNULL);
571: closedem();
572: (void) setuid(Uid);
573: abort();
574: }
575:
576: /*
577: * catch SIGALRM routine
578: */
579: timeout()
580: {
581: longjmp(Sjbuf, 1);
582: }
583:
584: static char *
585: pskip(p)
586: register char *p;
587: {
588: while( *p && *p != ' ' )
589: ++p;
590: if( *p ) *p++ = 0;
591: return(p);
592: }
593:
594: void
595: closedem()
596: {
597: register i;
598:
599: for(i=3;i<_NFILE;i++)
600: (void) close(i);
601: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.