113639Ssam #ifndef lint 2*25517Stef static char sccsid[] = "@(#)cico.c 5.10 (Berkeley) 11/22/85"; 313639Ssam #endif 413639Ssam 523590Sbloom #include <signal.h> 613639Ssam #include "uucp.h" 713639Ssam #include <setjmp.h> 817767Sralph #ifdef USG 913639Ssam #include <termio.h> 1013639Ssam #endif 1117767Sralph #ifndef USG 1213639Ssam #include <sgtty.h> 1313639Ssam #endif 1417767Sralph #ifdef BSDTCP 1517767Sralph #include <netdb.h> 1617767Sralph #include <netinet/in.h> 1717767Sralph #include <sys/socket.h> 1817767Sralph #endif BSDTCP 1917767Sralph #include <sys/stat.h> 2017767Sralph #include "uust.h" 2117767Sralph #include "uusub.h" 2213639Ssam 2323590Sbloom #if defined(VMS) && defined(BSDTCP) 2423590Sbloom #define NOGETPEER 2523590Sbloom #endif 2623590Sbloom 2723590Sbloom #ifdef BSD2_9 2823590Sbloom #define NOGETPEER 2923590Sbloom #endif 3023590Sbloom 3117767Sralph jmp_buf Sjbuf; 3217767Sralph jmp_buf Pipebuf; 3313639Ssam 3417767Sralph /* call fail text */ 3513639Ssam char *Stattext[] = { 3613639Ssam "", 3713639Ssam "BAD SYSTEM", 3817767Sralph "WRONG TIME TO CALL", 3913639Ssam "SYSTEM LOCKED", 4013639Ssam "NO DEVICE", 4113639Ssam "DIAL FAILED", 4213639Ssam "LOGIN FAILED", 4313639Ssam "BAD SEQUENCE" 4417767Sralph }; 4513639Ssam 4617767Sralph /* call fail codes */ 4717767Sralph int Stattype[] = { 4817767Sralph 0, 4917767Sralph 0, 5017767Sralph SS_WRONGTIME, 5117767Sralph 0, 5217767Sralph SS_NODEVICE, 5317767Sralph SS_FAIL, 5417767Sralph SS_FAIL, 5517767Sralph SS_BADSEQ 5617767Sralph }; 5713639Ssam 5813639Ssam 5917767Sralph int ReverseRole = 0; 6017767Sralph int StdErrIsTty = 0; 6117767Sralph int Role = SLAVE; 6217767Sralph int onesys = 0; 6318616Sralph int turntime = 30 * 60; /* 30 minutes expressed in seconds */ 6417767Sralph extern int LocalOnly; 6518616Sralph extern char MaxGrade, DefMaxGrade; 6618616Sralph extern char Myfullname[]; 6717767Sralph 6817767Sralph #ifdef USG 6913639Ssam struct termio Savettyb; 7013639Ssam #endif 7117767Sralph #ifndef USG 7213639Ssam struct sgttyb Savettyb; 7313639Ssam #endif 7413639Ssam 7513639Ssam /******* 7613639Ssam * cico - this program is used to place a call to a 7713639Ssam * remote machine, login, and copy files between the two machines. 7813639Ssam */ 7913639Ssam 8013639Ssam main(argc, argv) 8113639Ssam register char *argv[]; 8213639Ssam { 8313639Ssam register int ret; 8413639Ssam int seq; 8513639Ssam char wkpre[NAMESIZE], file[NAMESIZE]; 8617767Sralph char msg[MAXFULLNAME], *q, **alias; 8713639Ssam register char *p; 8813639Ssam extern onintr(), timeout(), setdebug(); 8913639Ssam extern char *pskip(); 9023725Sbloom char rflags[MAXFULLNAME]; 9113639Ssam char *ttyn; 9223590Sbloom #ifdef NOGETPEER 9317767Sralph u_long Hostnumber = 0; 9423590Sbloom #endif NOGETPEER 9513639Ssam 9613639Ssam strcpy(Progname, "uucico"); 9713639Ssam 9813639Ssam signal(SIGINT, onintr); 9913639Ssam signal(SIGHUP, onintr); 10013639Ssam signal(SIGQUIT, onintr); 10113639Ssam signal(SIGTERM, onintr); 10213639Ssam signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */ 10313639Ssam signal(SIGFPE, setdebug); 10413639Ssam ret = guinfo(getuid(), User, msg); 10513639Ssam strcpy(Loginuser, User); 10623590Sbloom uucpname(Myname); 10717767Sralph ASSERT(ret == 0, "BAD UID", CNULL, ret); 10813639Ssam 10917767Sralph #ifdef BSD4_2 11017767Sralph setlinebuf(stderr); 11117767Sralph #endif 11213639Ssam umask(WFMASK); 11313639Ssam strcpy(Rmtname, Myname); 11413639Ssam Ifn = Ofn = -1; 11513639Ssam while(argc>1 && argv[1][0] == '-'){ 11613639Ssam switch(argv[1][1]){ 11713639Ssam case 'd': 11813639Ssam Spool = &argv[1][2]; 11913639Ssam break; 12013639Ssam case 'g': 12118616Sralph case 'p': 12218616Sralph MaxGrade = DefMaxGrade = argv[1][2]; 12313639Ssam break; 12413639Ssam case 'r': 12513639Ssam Role = atoi(&argv[1][2]); 12613639Ssam break; 12717767Sralph case 'R': 12817767Sralph ReverseRole++; 12917767Sralph Role = MASTER; 13017767Sralph break; 13113639Ssam case 's': 13223590Sbloom strncpy(Rmtname, &argv[1][2], MAXBASENAME); 13323590Sbloom Rmtname[MAXBASENAME] = '\0'; 13413639Ssam if (Rmtname[0] != '\0') 13513639Ssam onesys = 1; 13613639Ssam break; 13713639Ssam case 'x': 13817767Sralph chkdebug(); 13913639Ssam Debug = atoi(&argv[1][2]); 14013639Ssam if (Debug <= 0) 14113639Ssam Debug = 1; 14213639Ssam logent("ENABLED", "DEBUG"); 14313639Ssam break; 14418616Sralph case 't': 14518616Sralph turntime = atoi(&argv[1][2])*60;/* minutes to seconds */ 14618616Sralph break; 14717767Sralph case 'L': /* local calls only */ 14817767Sralph LocalOnly++; 14917767Sralph break; 15023590Sbloom #ifdef NOGETPEER 15117767Sralph case 'h': 15217767Sralph Hostnumber = inet_addr(&argv[1][2]); 15317767Sralph break; 15423590Sbloom #endif NOGETPEER 15513639Ssam default: 15617767Sralph printf("unknown flag %s (ignored)\n", argv[1]); 15713639Ssam break; 15813639Ssam } 15913639Ssam --argc; argv++; 16013639Ssam } 16113639Ssam 16217767Sralph while (argc > 1) { 16317767Sralph printf("unknown argument %s (ignored)\n", argv[1]); 16417767Sralph --argc; argv++; 16517767Sralph } 16617767Sralph 16725124Sbloom /* Try to run as uucp */ 16817767Sralph setgid(getegid()); 16917767Sralph setuid(geteuid()); 17017767Sralph #ifdef TIOCNOTTY 17117767Sralph /* 17217767Sralph * detach uucico from controlling terminal 17317767Sralph * to defend against rlogind sending us a SIGKILL (!!!) 17417767Sralph */ 17517767Sralph if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) { 17617767Sralph ioctl(ret, TIOCNOTTY, STBNULL); 17717767Sralph close(ret); 17817767Sralph } 17917767Sralph #endif TIOCNOTTY 18017767Sralph #ifdef BSD4_2 181*25517Stef if (getpgrp(0) == 0) { /* We have no controlling terminal */ 18217767Sralph setpgrp(0, getpid()); 18317767Sralph } 18417767Sralph #endif BSD4_2 18517767Sralph 18617767Sralph ret = subchdir(Spool); 18717767Sralph ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret); 18813639Ssam strcpy(Wrkdir, Spool); 18913639Ssam 19013639Ssam if (Role == SLAVE) { 19117767Sralph /* check for /etc/nologin */ 19225124Sbloom if (access(NOLOGIN, 0) == 0) { 19317767Sralph logent(NOLOGIN, "UUCICO SHUTDOWN"); 19423590Sbloom if (Debug > 4) 19517767Sralph logent("DEBUGGING", "continuing anyway"); 19617767Sralph else 19717767Sralph cleanup(1); 19817767Sralph } 19917767Sralph #ifdef TCPIP 20017767Sralph /* 20117767Sralph * Determine if we are on TCPIP 20217767Sralph */ 20317767Sralph if (isatty(0) == 0) { 20417767Sralph IsTcpIp = 1; 20517767Sralph DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); 20623590Sbloom } else 20723590Sbloom IsTcpIp = 0; 20817767Sralph #endif TCPIP 20913639Ssam /* initial handshake */ 21013639Ssam onesys = 1; 21117767Sralph if (!IsTcpIp) { 21217767Sralph #ifdef USG 21313639Ssam ret = ioctl(0, TCGETA, &Savettyb); 21413639Ssam Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7; 21513639Ssam Savettyb.c_oflag |= OPOST; 21613639Ssam Savettyb.c_lflag |= (ISIG|ICANON|ECHO); 21717767Sralph #else !USG 21813639Ssam ret = ioctl(0, TIOCGETP, &Savettyb); 21913639Ssam Savettyb.sg_flags |= ECHO; 22013639Ssam Savettyb.sg_flags &= ~RAW; 22117767Sralph #endif !USG 22213639Ssam } 22313639Ssam Ifn = 0; 22413639Ssam Ofn = 1; 22513639Ssam fixmode(Ifn); 226*25517Stef getbaud(Ifn); 22717767Sralph sprintf(file,"%s/%d", RMTDEBUG, getpid()); 22817767Sralph #ifdef VMS 22917767Sralph /* hold the version number down */ 23017767Sralph unlink(file); 23123590Sbloom #endif VMS 23217767Sralph freopen(file, "w", stderr); 23317767Sralph #ifdef BSD4_2 23417767Sralph setlinebuf(stderr); 23517767Sralph #else !BSD4_2 23617767Sralph setbuf(stderr, NULL); 23717767Sralph #endif !BSD4_2 23818616Sralph sprintf(msg, "here=%s", Myfullname); 23917767Sralph omsg('S', msg, Ofn); 24013639Ssam signal(SIGALRM, timeout); 24113639Ssam alarm(MAXMSGTIME); 24213639Ssam if (setjmp(Sjbuf)) { 24313639Ssam /* timed out */ 24417767Sralph if (!IsTcpIp) { 24517767Sralph #ifdef USG 24613639Ssam ret = ioctl(0, TCSETA, &Savettyb); 24723590Sbloom #else !USG 24813639Ssam ret = ioctl(0, TIOCSETP, &Savettyb); 24923590Sbloom #endif !USG 25013639Ssam } 25117767Sralph cleanup(0); 25213639Ssam } 25313639Ssam for (;;) { 25413639Ssam ret = imsg(msg, Ifn); 25513639Ssam if (ret != 0) { 25613639Ssam alarm(0); 25717767Sralph if (!IsTcpIp) { 25817767Sralph #ifdef USG 25913639Ssam ret = ioctl(0, TCSETA, &Savettyb); 26023590Sbloom #else !USG 26113639Ssam ret = ioctl(0, TIOCSETP, &Savettyb); 26223590Sbloom #endif !USG 26313639Ssam } 26417767Sralph cleanup(0); 26513639Ssam } 26613639Ssam if (msg[0] == 'S') 26713639Ssam break; 26813639Ssam } 26913639Ssam alarm(0); 27013639Ssam q = &msg[1]; 27113639Ssam p = pskip(q); 27223590Sbloom strncpy(Rmtname, q, MAXBASENAME); 27323590Sbloom Rmtname[MAXBASENAME] = '\0'; 27417767Sralph sprintf(wkpre,"%s/%s", RMTDEBUG, Rmtname); 27517767Sralph unlink(wkpre); 27617767Sralph if (link(file, wkpre) == 0) 27717767Sralph unlink(file); 27813639Ssam DEBUG(4, "sys-%s\n", Rmtname); 27923725Sbloom /* The versys will also do an alias on the incoming name */ 28023725Sbloom if (versys(&Rmtname)) { 28123725Sbloom /* If we don't know them, we won't talk to them... */ 28223590Sbloom #ifdef NOSTRANGERS 28323590Sbloom logent(Rmtname, "UNKNOWN HOST"); 28423590Sbloom omsg('R', "You are unknown to me", Ofn); 28523590Sbloom cleanup(0); 28623725Sbloom #endif NOSTRANGERS 28723590Sbloom } 28817767Sralph #ifdef BSDTCP 28917767Sralph /* we must make sure they are really who they say they 29017767Sralph * are. We compare the hostnumber with the number in the hosts 29117767Sralph * table for the site they claim to be. 29217767Sralph */ 29317767Sralph if (IsTcpIp) { 29417767Sralph struct hostent *hp; 29517767Sralph char *cpnt, *inet_ntoa(); 29625124Sbloom int len; 29717767Sralph struct sockaddr_in from; 29825124Sbloom extern char PhoneNumber[]; 29917767Sralph 30023590Sbloom #ifdef NOGETPEER 30123590Sbloom from.sin_addr.s_addr = Hostnumber; 30223590Sbloom from.sin_family = AF_INET; 30323590Sbloom #else !NOGETPEER 30425124Sbloom len = sizeof(from); 30525124Sbloom if (getpeername(0, &from, &len) < 0) { 30617767Sralph logent(Rmtname, "NOT A TCP CONNECTION"); 30717767Sralph omsg('R', "NOT TCP", Ofn); 30817767Sralph cleanup(0); 30917767Sralph } 31023590Sbloom #endif !NOGETPEER 31117767Sralph hp = gethostbyaddr(&from.sin_addr, 31217767Sralph sizeof (struct in_addr), from.sin_family); 31317767Sralph if (hp == 0) { 31417767Sralph /* security break or just old host table? */ 31517767Sralph logent(Rmtname, "UNKNOWN IP-HOST Name ="); 31617767Sralph cpnt = inet_ntoa(from.sin_addr), 31717767Sralph logent(cpnt, "UNKNOWN IP-HOST Number ="); 31817767Sralph sprintf(wkpre, "%s/%s isn't in my host table", 31917767Sralph Rmtname, cpnt); 32017767Sralph omsg('R' ,wkpre ,Ofn); 32117767Sralph cleanup(0); 32217767Sralph } 32317767Sralph if (Debug>99) 32417767Sralph logent(Rmtname,"Request from IP-Host name ="); 32525124Sbloom /* 32625124Sbloom * The following is to determine if the name given us by 32725124Sbloom * the Remote uucico matches any of the names 32817767Sralph * given its network number (remote machine) in our 32917767Sralph * host table. 33025124Sbloom * We could check the aliases, but that won't work in 33125124Sbloom * all cases (like if you are running the domain 33225124Sbloom * server, where you don't get any aliases). The only 33325124Sbloom * reliable way I can think of that works in ALL cases 33425124Sbloom * is too look up the site in L.sys and see if the 33525124Sbloom * sitename matches what we would call him if we 33625124Sbloom * originated the call. 33717767Sralph */ 33825124Sbloom /* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */ 33925124Sbloom if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) { 34017767Sralph if (Debug > 99) 34117767Sralph logent(q,"Found in host Tables"); 34225124Sbloom } else { 34325124Sbloom logent(hp->h_name, "FORGED HOSTNAME"); 34425124Sbloom logent(inet_ntoa(from.sin_addr), "ORIGINATED AT"); 34525124Sbloom logent(PhoneNumber, "SHOULD BE"); 34625124Sbloom sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber); 34725124Sbloom omsg('R', wkpre, Ofn); 34825124Sbloom cleanup(0); 34917767Sralph } 35017767Sralph } 35117767Sralph #endif BSDTCP 35217767Sralph 35325124Sbloom if (mlock(Rmtname) == FAIL) { 35413639Ssam omsg('R', "LCK", Ofn); 35513639Ssam cleanup(0); 35613639Ssam } 35713639Ssam else if (callback(Loginuser)) { 35813639Ssam signal(SIGINT, SIG_IGN); 35913639Ssam signal(SIGHUP, SIG_IGN); 36013639Ssam omsg('R', "CB", Ofn); 36113639Ssam logent("CALLBACK", "REQUIRED"); 36213639Ssam /* set up for call back */ 36317767Sralph systat(Rmtname, SS_CALLBACK, "CALLING BACK"); 36413639Ssam gename(CMDPRE, Rmtname, 'C', file); 36513639Ssam close(creat(subfile(file), 0666)); 36613639Ssam xuucico(Rmtname); 36713639Ssam cleanup(0); 36813639Ssam } 36913639Ssam seq = 0; 37013639Ssam while (*p == '-') { 37113639Ssam q = pskip(p); 37213639Ssam switch(*(++p)) { 37313639Ssam case 'x': 37413639Ssam Debug = atoi(++p); 37513639Ssam if (Debug <= 0) 37613639Ssam Debug = 1; 37713639Ssam break; 37813639Ssam case 'Q': 37913639Ssam seq = atoi(++p); 38013639Ssam break; 38118616Sralph case 'p': 38218616Sralph MaxGrade = DefMaxGrade = *++p; 38318616Sralph DEBUG(4, "MaxGrade set to %c\n", MaxGrade); 38418616Sralph break; 38523590Sbloom case 'v': 38623590Sbloom if (strncmp(p, "grade", 5) == 0) { 38723590Sbloom p += 6; 38823590Sbloom MaxGrade = DefMaxGrade = *p++; 38923590Sbloom DEBUG(4, "MaxGrade set to %c\n", MaxGrade); 39023590Sbloom } 39123590Sbloom break; 39213639Ssam default: 39313639Ssam break; 39413639Ssam } 39513639Ssam p = q; 39613639Ssam } 39713639Ssam if (callok(Rmtname) == SS_BADSEQ) { 39813639Ssam logent("BADSEQ", "PREVIOUS"); 39913639Ssam omsg('R', "BADSEQ", Ofn); 40013639Ssam cleanup(0); 40113639Ssam } 40217767Sralph #ifdef GNXSEQ 40313639Ssam if ((ret = gnxseq(Rmtname)) == seq) { 40413639Ssam omsg('R', "OK", Ofn); 40513639Ssam cmtseq(); 40617767Sralph } else { 40717767Sralph #else !GNXSEQ 40817767Sralph if (seq == 0) 40917767Sralph omsg('R', "OK", Ofn); 41013639Ssam else { 41117767Sralph #endif !GNXSEQ 41213639Ssam systat(Rmtname, Stattype[7], Stattext[7]); 41323590Sbloom logent("BAD SEQ", "FAILED HANDSHAKE"); 41417767Sralph #ifdef GNXSEQ 41513639Ssam ulkseq(); 41617767Sralph #endif GNXSEQ 41713639Ssam omsg('R', "BADSEQ", Ofn); 41813639Ssam cleanup(0); 41913639Ssam } 42013639Ssam ttyn = ttyname(Ifn); 42113639Ssam if (ttyn != NULL) 42213639Ssam chmod(ttyn, 0600); 42317767Sralph } else { /* Role == MASTER */ 42417767Sralph struct stat stbuf; 42517767Sralph if (isatty(fileno(stderr)) || (fstat(fileno(stderr),&stbuf) == 0 42617767Sralph && stbuf.st_mode&S_IFREG) ) 42717767Sralph StdErrIsTty = 1; 42817767Sralph setdebug(0); 42913639Ssam } 43017767Sralph 43113639Ssam loop: 43217767Sralph if(setjmp(Pipebuf)) { /* come here on SIGPIPE */ 43317767Sralph clsacu(); 43417767Sralph close(Ofn); 43517767Sralph close(Ifn); 43617767Sralph Ifn = Ofn = -1; 43717767Sralph rmlock(CNULL); 43817767Sralph sleep(3); 43917767Sralph } 44013639Ssam if (!onesys) { 44117767Sralph struct stat sbuf; 44217767Sralph 44317767Sralph if (!StdErrIsTty) { 44417767Sralph sprintf(file, "%s/%s", RMTDEBUG, Rmtname); 44517767Sralph if (stat(file, &sbuf) == 0 && sbuf.st_size == 0) 44617767Sralph unlink(file); 44717767Sralph } 44813639Ssam ret = gnsys(Rmtname, Spool, CMDPRE); 44917767Sralph setdebug(0); 45013639Ssam if (ret == FAIL) 45113639Ssam cleanup(100); 45223590Sbloom if (ret == SUCCESS) 45313639Ssam cleanup(0); 45417767Sralph } else if (Role == MASTER && callok(Rmtname) != 0) { 45513639Ssam logent("SYSTEM STATUS", "CAN NOT CALL"); 45613639Ssam cleanup(0); 45713639Ssam } 45813639Ssam 45923590Sbloom sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); 46013639Ssam 46117767Sralph signal(SIGINT, SIG_IGN); 46217767Sralph signal(SIGQUIT, SIG_IGN); 46313639Ssam if (Role == MASTER) { 46417767Sralph /* check for /etc/nologin */ 46525124Sbloom if (access(NOLOGIN, 0) == 0) { 46617767Sralph logent(NOLOGIN, "UUCICO SHUTDOWN"); 46723590Sbloom if (Debug > 4) 46817767Sralph logent("DEBUGGING", "continuing anyway"); 46917767Sralph else 47017767Sralph cleanup(1); 47117767Sralph } 47213639Ssam /* master part */ 47313639Ssam signal(SIGHUP, SIG_IGN); 47413639Ssam if (Ifn != -1 && Role == MASTER) { 47513639Ssam write(Ofn, EOTMSG, strlen(EOTMSG)); 47613639Ssam clsacu(); 47713639Ssam close(Ofn); 47813639Ssam close(Ifn); 47913639Ssam Ifn = Ofn = -1; 48013639Ssam rmlock(CNULL); 48113639Ssam sleep(3); 48213639Ssam } 48313639Ssam sprintf(msg, "call to %s ", Rmtname); 48425124Sbloom if (mlock(Rmtname) != SUCCESS) { 48513639Ssam logent(msg, "LOCKED"); 48617767Sralph US_SST(us_s_lock); 48713639Ssam goto next; 48813639Ssam } 48913639Ssam Ofn = Ifn = conn(Rmtname); 49013639Ssam if (Ofn < 0) { 49117767Sralph if (Ofn != CF_TIME) 49217767Sralph logent(msg, _FAILED); 49317767Sralph /* avoid excessive 'wrong time' info */ 49423590Sbloom if (Stattype[-Ofn] != SS_WRONGTIME){ 49517767Sralph systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]); 49617767Sralph US_SST(-Ofn); 49717767Sralph UB_SST(-Ofn); 49817767Sralph } 49913639Ssam goto next; 50017767Sralph } else { 50113639Ssam logent(msg, "SUCCEEDED"); 50217767Sralph US_SST(us_s_cok); 50317767Sralph UB_SST(ub_ok); 50413639Ssam } 50517767Sralph #ifdef TCPIP 50617767Sralph /* 50717767Sralph * Determine if we are on TCPIP 50817767Sralph */ 50917767Sralph if (isatty(Ifn) == 0) { 51017767Sralph IsTcpIp = 1; 51117767Sralph DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); 51223590Sbloom } else 51323590Sbloom IsTcpIp = 0; 51417767Sralph #endif 51517767Sralph 51613639Ssam if (setjmp(Sjbuf)) 51713639Ssam goto next; 51813639Ssam signal(SIGALRM, timeout); 51913639Ssam alarm(2 * MAXMSGTIME); 52013639Ssam for (;;) { 52113639Ssam ret = imsg(msg, Ifn); 52213639Ssam if (ret != 0) { 52313639Ssam alarm(0); 52417767Sralph logent("imsg 1", _FAILED); 52517767Sralph goto Failure; 52613639Ssam } 52713639Ssam if (msg[0] == 'S') 52813639Ssam break; 52913639Ssam } 53013639Ssam alarm(MAXMSGTIME); 53117767Sralph #ifdef GNXSEQ 53213639Ssam seq = gnxseq(Rmtname); 53317767Sralph #else !GNXSEQ 53417767Sralph seq = 0; 53517767Sralph #endif !GNXSEQ 53625124Sbloom if (Debug) 53725124Sbloom sprintf(rflags, "-x%d", Debug); 53825124Sbloom else 53925124Sbloom rflags[0] = '\0'; 54025124Sbloom 54118616Sralph if (MaxGrade != '\177') { 54223725Sbloom char buf[MAXFULLNAME]; 54323590Sbloom sprintf(buf, " -p%c -vgrade=%c", MaxGrade, MaxGrade); 54418616Sralph strcat(rflags, buf); 54518616Sralph } 54618616Sralph 54723590Sbloom sprintf(msg, "%s -Q%d %s", Myname, seq, rflags); 54823590Sbloom if (MaxGrade != '\177') 54923590Sbloom DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade); 55013639Ssam omsg('S', msg, Ofn); 55113639Ssam for (;;) { 55213639Ssam ret = imsg(msg, Ifn); 55313639Ssam DEBUG(4, "msg-%s\n", msg); 55417767Sralph if (ret != SUCCESS) { 55513639Ssam alarm(0); 55617767Sralph #ifdef GNXSEQ 55713639Ssam ulkseq(); 55817767Sralph #endif GNXSEQ 55917767Sralph logent("imsg 2", _FAILED); 56017767Sralph goto Failure; 56113639Ssam } 56213639Ssam if (msg[0] == 'R') 56313639Ssam break; 56413639Ssam } 56513639Ssam alarm(0); 56613639Ssam if (msg[1] == 'B') { 56713639Ssam /* bad sequence */ 56823590Sbloom logent("BAD SEQ", "FAILED HANDSHAKE"); 56917767Sralph US_SST(us_s_hand); 57017767Sralph systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]); 57117767Sralph #ifdef GNXSEQ 57213639Ssam ulkseq(); 57317767Sralph #endif GNXSEQ 57413639Ssam goto next; 57513639Ssam } 57613639Ssam if (strcmp(&msg[1], "OK") != SAME) { 57723590Sbloom logent(&msg[1], "FAILED HANDSHAKE"); 57817767Sralph US_SST(us_s_hand); 57917767Sralph #ifdef GNXSEQ 58013639Ssam ulkseq(); 58117767Sralph #endif GNXSEQ 58217767Sralph systat(Rmtname, SS_INPROGRESS, 58317767Sralph strcmp(&msg[1], "CB") == SAME? 58423590Sbloom "AWAITING CALLBACK": "FAILED HANDSHAKE"); 58513639Ssam goto next; 58613639Ssam } 58717767Sralph #ifdef GNXSEQ 58813639Ssam cmtseq(); 58917767Sralph #endif GNXSEQ 59013639Ssam } 59117767Sralph DEBUG(1, "Rmtname %s, ", Rmtname); 59213639Ssam DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE"); 59313639Ssam DEBUG(1, "Ifn - %d, ", Ifn); 59413639Ssam DEBUG(1, "Loginuser - %s\n", Loginuser); 59513639Ssam 59613639Ssam alarm(MAXMSGTIME); 59718616Sralph if (ret=setjmp(Sjbuf)) 59813639Ssam goto Failure; 59913639Ssam ret = startup(Role); 60013639Ssam alarm(0); 60113639Ssam if (ret != SUCCESS) { 60217767Sralph logent("startup", _FAILED); 60313639Ssam Failure: 60417767Sralph US_SST(us_s_start); 60518616Sralph systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" : 60618616Sralph "STARTUP FAILED"); 60713639Ssam goto next; 60817767Sralph } else { 60913639Ssam logent("startup", "OK"); 61017767Sralph US_SST(us_s_gress); 61113639Ssam systat(Rmtname, SS_INPROGRESS, "TALKING"); 61213639Ssam ret = cntrl(Role, wkpre); 61313639Ssam DEBUG(1, "cntrl - %d\n", ret); 61413639Ssam signal(SIGINT, SIG_IGN); 61513639Ssam signal(SIGHUP, SIG_IGN); 61613639Ssam signal(SIGALRM, timeout); 61717767Sralph if (ret == SUCCESS) { 61813639Ssam logent("conversation complete", "OK"); 61917767Sralph US_SST(us_s_ok); 62013639Ssam rmstat(Rmtname); 62113639Ssam 62217767Sralph } else { 62317767Sralph logent("conversation complete", _FAILED); 62417767Sralph US_SST(us_s_cf); 62517767Sralph systat(Rmtname, SS_FAIL, "CONVERSATION FAILED"); 62613639Ssam } 62713639Ssam alarm(MAXMSGTIME); 62813639Ssam DEBUG(4, "send OO %d,", ret); 62913639Ssam if (!setjmp(Sjbuf)) { 63013639Ssam for (;;) { 63113639Ssam omsg('O', "OOOOO", Ofn); 63213639Ssam ret = imsg(msg, Ifn); 63313639Ssam if (ret != 0) 63413639Ssam break; 63513639Ssam if (msg[0] == 'O') 63613639Ssam break; 63713639Ssam } 63813639Ssam } 63913639Ssam alarm(0); 64017767Sralph clsacu(); 64117767Sralph rmlock(CNULL); 64213639Ssam } 64313639Ssam next: 64413639Ssam if (!onesys) { 64513639Ssam goto loop; 64613639Ssam } 64713639Ssam cleanup(0); 64813639Ssam } 64913639Ssam 65017767Sralph #ifndef USG 65113639Ssam struct sgttyb Hupvec; 65213639Ssam #endif 65313639Ssam 65413639Ssam /*** 65513639Ssam * cleanup(code) cleanup and exit with "code" status 65613639Ssam * int code; 65713639Ssam */ 65813639Ssam 65913639Ssam cleanup(code) 66013639Ssam register int code; 66113639Ssam { 66213639Ssam register char *ttyn; 66317767Sralph char bfr[BUFSIZ]; 66417767Sralph struct stat sbuf; 66513639Ssam 66613639Ssam signal(SIGINT, SIG_IGN); 66713639Ssam signal(SIGHUP, SIG_IGN); 66813639Ssam rmlock(CNULL); 66913639Ssam clsacu(); 67013639Ssam logcls(); 67113639Ssam if (Role == SLAVE) { 67217767Sralph if (!IsTcpIp) { 67317767Sralph #ifdef USG 67413639Ssam Savettyb.c_cflag |= HUPCL; 67523590Sbloom (void) ioctl(0, TCSETA, &Savettyb); 67617767Sralph #else !USG 67723590Sbloom (void) ioctl(0, TIOCHPCL, STBNULL); 67818616Sralph #ifdef TIOCSDTR 67923590Sbloom (void) ioctl(0, TIOCCDTR, STBNULL); 68018616Sralph sleep(2); 68123590Sbloom (void) ioctl(0, TIOCSDTR, STBNULL); 68218616Sralph #else !TIOCSDTR 68323590Sbloom (void) ioctl(0, TIOCGETP, &Hupvec); 68418616Sralph #endif !TIOCSDTR 68513639Ssam Hupvec.sg_ispeed = B0; 68613639Ssam Hupvec.sg_ospeed = B0; 68723590Sbloom (void) ioctl(0, TIOCSETP, &Hupvec); 68813639Ssam sleep(2); 68923590Sbloom (void) ioctl(0, TIOCSETP, &Savettyb); 69017767Sralph /* make *sure* exclusive access is off */ 69123590Sbloom (void) ioctl(0, TIOCNXCL, STBNULL); 69217767Sralph #endif !USG 69313639Ssam } 69413639Ssam ttyn = ttyname(Ifn); 69513639Ssam if (ttyn != NULL) 69613639Ssam chmod(ttyn, 0600); 69713639Ssam } 69813639Ssam if (Ofn != -1) { 69913639Ssam if (Role == MASTER) 70013639Ssam write(Ofn, EOTMSG, strlen(EOTMSG)); 70113639Ssam close(Ifn); 70213639Ssam close(Ofn); 70313639Ssam } 70418616Sralph #ifdef DIALINOUT 70518616Sralph /* reenable logins on dialout */ 70618616Sralph reenable(); 70718616Sralph #endif DIALINOUT 70813639Ssam if (code == 0) 70913639Ssam xuuxqt(); 71017767Sralph else 71117767Sralph DEBUG(1, "exit code %d\n", code); 71217767Sralph sprintf(bfr, "%s/%s", RMTDEBUG, Rmtname); 71317767Sralph if (stat(bfr, &sbuf) == 0 && sbuf.st_size == 0) 71417767Sralph unlink(bfr); 71517767Sralph sprintf(bfr, "%s/%d", RMTDEBUG, getpid()); 71617767Sralph unlink(bfr); 71713639Ssam exit(code); 71813639Ssam } 71913639Ssam 72013639Ssam /*** 72113639Ssam * onintr(inter) interrupt - remove locks and exit 72213639Ssam */ 72313639Ssam 72413639Ssam onintr(inter) 72513639Ssam register int inter; 72613639Ssam { 72713639Ssam char str[30]; 72813639Ssam signal(inter, SIG_IGN); 72913639Ssam sprintf(str, "SIGNAL %d", inter); 73013639Ssam logent(str, "CAUGHT"); 73117767Sralph US_SST(us_s_intr); 73223590Sbloom if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) 73317767Sralph systat(Rmtname, SS_FAIL, str); 73417767Sralph if (inter == SIGPIPE && !onesys) 73517767Sralph longjmp(Pipebuf, 1); 73613639Ssam cleanup(inter); 73713639Ssam } 73813639Ssam 73913639Ssam /* 74013639Ssam * Catch a special signal 74113639Ssam * (SIGFPE, ugh), and toggle debugging between 0 and 30. 74213639Ssam * Handy for looking in on long running uucicos. 74313639Ssam */ 74417767Sralph setdebug(code) 74517767Sralph int code; 74613639Ssam { 74717767Sralph char buf[BUFSIZ]; 74817767Sralph 74923590Sbloom if (code) { 75023590Sbloom if (Debug == 0) 75123590Sbloom Debug = 30; 75223590Sbloom else 75323590Sbloom Debug = 0; 75423590Sbloom } 75523590Sbloom if (Debug && !StdErrIsTty) { 75617767Sralph sprintf(buf,"%s/%s", RMTDEBUG, Rmtname); 75717767Sralph unlink(buf); 75817767Sralph freopen(buf, "w", stderr); 75917767Sralph #ifdef BSD4_2 76017767Sralph setlinebuf(stderr); 76117767Sralph #else !BSD4_2 76217767Sralph setbuf(stderr, NULL); 76317767Sralph #endif !BSD4_2 76417767Sralph } 76513639Ssam } 76613639Ssam 76713639Ssam 76813639Ssam /*** 76913639Ssam * fixmode(tty) fix kill/echo/raw on line 77013639Ssam * 77113639Ssam * return codes: none 77213639Ssam */ 77313639Ssam 77413639Ssam fixmode(tty) 77513639Ssam register int tty; 77613639Ssam { 77717767Sralph #ifdef USG 77813639Ssam struct termio ttbuf; 77913639Ssam #endif 78017767Sralph #ifndef USG 78113639Ssam struct sgttyb ttbuf; 78213639Ssam #endif 78313639Ssam 78417767Sralph if (IsTcpIp) 78513639Ssam return; 78617767Sralph #ifdef USG 78723590Sbloom ioctl(tty, TCGETA, &ttbuf); 78813639Ssam ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0; 78913639Ssam ttbuf.c_cflag &= (CBAUD); 79013639Ssam ttbuf.c_cflag |= (CS8|CREAD); 79113639Ssam ttbuf.c_cc[VMIN] = 6; 79213639Ssam ttbuf.c_cc[VTIME] = 1; 79323590Sbloom ioctl(tty, TCSETA, &ttbuf); 79413639Ssam #endif 79517767Sralph #ifndef USG 79613639Ssam ioctl(tty, TIOCGETP, &ttbuf); 79713639Ssam ttbuf.sg_flags = (ANYP | RAW); 79823590Sbloom ioctl(tty, TIOCSETP, &ttbuf); 79913639Ssam #endif 80017767Sralph #ifndef USG 80123590Sbloom ioctl(tty, TIOCEXCL, STBNULL); 80213639Ssam #endif 80313639Ssam } 80413639Ssam 80513639Ssam 80623590Sbloom /* 80713639Ssam * timeout() catch SIGALRM routine 80813639Ssam */ 80913639Ssam 81013639Ssam timeout() 81113639Ssam { 81223590Sbloom extern int HaveSentHup; 81323590Sbloom if (!HaveSentHup) { 81423590Sbloom logent(Rmtname, "TIMEOUT"); 81523590Sbloom if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) { 81623590Sbloom US_SST(us_s_tmot); 81723590Sbloom systat(Rmtname, SS_FAIL, "TIMEOUT"); 81823590Sbloom } 81917767Sralph } 82013639Ssam longjmp(Sjbuf, 1); 82113639Ssam } 82213639Ssam 82313639Ssam static char * 82413639Ssam pskip(p) 82513639Ssam register char *p; 82613639Ssam { 82717767Sralph while(*p && *p != ' ') 82813639Ssam ++p; 82923590Sbloom while(*p && *p == ' ') 83017767Sralph *p++ = 0; 83117767Sralph return p; 83213639Ssam } 833