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