113639Ssam #ifndef lint 2*33559Srick static char sccsid[] = "@(#)cico.c 5.15 (Berkeley) 02/24/88"; 313639Ssam #endif 413639Ssam 523590Sbloom #include <signal.h> 613639Ssam #include "uucp.h" 713639Ssam #include <setjmp.h> 817767Sralph #ifdef USG 913639Ssam #include <termio.h> 10*33559Srick #include <fcntl.h> 1113639Ssam #endif 1217767Sralph #ifndef USG 1313639Ssam #include <sgtty.h> 1413639Ssam #endif 1517767Sralph #ifdef BSDTCP 1617767Sralph #include <netdb.h> 1717767Sralph #include <netinet/in.h> 1817767Sralph #include <sys/socket.h> 1917767Sralph #endif BSDTCP 2017767Sralph #include <sys/stat.h> 21*33559Srick #ifdef BSD4_2 22*33559Srick #include <sys/time.h> 23*33559Srick #include <fcntl.h> 24*33559Srick #else 25*33559Srick #include <time.h> 26*33559Srick #endif 2717767Sralph #include "uust.h" 2817767Sralph #include "uusub.h" 2913639Ssam 3023590Sbloom #if defined(VMS) && defined(BSDTCP) 3123590Sbloom #define NOGETPEER 3223590Sbloom #endif 3323590Sbloom 3423590Sbloom #ifdef BSD2_9 3523590Sbloom #define NOGETPEER 3623590Sbloom #endif 3723590Sbloom 3817767Sralph jmp_buf Sjbuf; 3917767Sralph jmp_buf Pipebuf; 4013639Ssam 4117767Sralph /* call fail text */ 4213639Ssam char *Stattext[] = { 4313639Ssam "", 4413639Ssam "BAD SYSTEM", 4517767Sralph "WRONG TIME TO CALL", 4613639Ssam "SYSTEM LOCKED", 4713639Ssam "NO DEVICE", 4825703Sbloom "CALL FAILED", 4913639Ssam "LOGIN FAILED", 5013639Ssam "BAD SEQUENCE" 5117767Sralph }; 5213639Ssam 5317767Sralph /* call fail codes */ 5417767Sralph int Stattype[] = { 5517767Sralph 0, 5617767Sralph 0, 5717767Sralph SS_WRONGTIME, 5817767Sralph 0, 5917767Sralph SS_NODEVICE, 6017767Sralph SS_FAIL, 6117767Sralph SS_FAIL, 6217767Sralph SS_BADSEQ 6317767Sralph }; 6413639Ssam 6525703Sbloom /* Arguments to setdebug(): */ 6625703Sbloom #define DBG_TEMP 0 /* Create a temporary audit file */ 6725703Sbloom #define DBG_PERM 1 /* Create a permanent audit file */ 6825703Sbloom #define DBG_CLEAN 2 /* Cleanup, discard temp file */ 6913639Ssam 7017767Sralph int ReverseRole = 0; 7117767Sralph int Role = SLAVE; 72*33559Srick int InitialRole = SLAVE; 73*33559Srick long StartTime; 7417767Sralph int onesys = 0; 7518616Sralph int turntime = 30 * 60; /* 30 minutes expressed in seconds */ 7625703Sbloom char *ttyn = NULL; 7717767Sralph extern int LocalOnly; 7825703Sbloom extern int errno; 7918616Sralph extern char MaxGrade, DefMaxGrade; 8018616Sralph extern char Myfullname[]; 8117767Sralph 82*33559Srick long Bytes_Sent, Bytes_Received; 83*33559Srick 8417767Sralph #ifdef USG 8513639Ssam struct termio Savettyb; 8613639Ssam #endif 8717767Sralph #ifndef USG 8813639Ssam struct sgttyb Savettyb; 8913639Ssam #endif 9013639Ssam 9125703Sbloom /* 9225703Sbloom * this program is used to place a call to a 9313639Ssam * remote machine, login, and copy files between the two machines. 9413639Ssam */ 9513639Ssam main(argc, argv) 9625703Sbloom int argc; 9713639Ssam register char *argv[]; 9813639Ssam { 9913639Ssam register int ret; 10013639Ssam int seq; 10113639Ssam char wkpre[NAMESIZE], file[NAMESIZE]; 10225703Sbloom char msg[MAXFULLNAME], *q; 10313639Ssam register char *p; 10425703Sbloom extern onintr(), timeout(), dbg_signal(); 10513639Ssam extern char *pskip(); 10623725Sbloom char rflags[MAXFULLNAME]; 10723590Sbloom #ifdef NOGETPEER 10817767Sralph u_long Hostnumber = 0; 10923590Sbloom #endif NOGETPEER 11013639Ssam 11113639Ssam strcpy(Progname, "uucico"); 11213639Ssam 11326149Sbloom #ifdef BSD4_2 11426149Sbloom sigsetmask(0); /* in case we inherit blocked signals */ 11526149Sbloom #endif BSD4_2 11613639Ssam signal(SIGINT, onintr); 11713639Ssam signal(SIGHUP, onintr); 11813639Ssam signal(SIGQUIT, onintr); 11913639Ssam signal(SIGTERM, onintr); 12013639Ssam signal(SIGPIPE, onintr); /* 4.1a tcp-ip stupidity */ 12125703Sbloom signal(SIGFPE, dbg_signal); 12213639Ssam ret = guinfo(getuid(), User, msg); 12313639Ssam strcpy(Loginuser, User); 12423590Sbloom uucpname(Myname); 12517767Sralph ASSERT(ret == 0, "BAD UID", CNULL, ret); 12613639Ssam 12725703Sbloom setbuf (stderr, CNULL); 12825703Sbloom 12925703Sbloom rflags[0] = '\0'; 13013639Ssam umask(WFMASK); 13113639Ssam strcpy(Rmtname, Myname); 13213639Ssam Ifn = Ofn = -1; 13313639Ssam while(argc>1 && argv[1][0] == '-'){ 13413639Ssam switch(argv[1][1]){ 13513639Ssam case 'd': 13613639Ssam Spool = &argv[1][2]; 13713639Ssam break; 13813639Ssam case 'g': 13918616Sralph case 'p': 14018616Sralph MaxGrade = DefMaxGrade = argv[1][2]; 14113639Ssam break; 14213639Ssam case 'r': 14313639Ssam Role = atoi(&argv[1][2]); 14413639Ssam break; 14517767Sralph case 'R': 14617767Sralph ReverseRole++; 14717767Sralph Role = MASTER; 14817767Sralph break; 14913639Ssam case 's': 15023590Sbloom strncpy(Rmtname, &argv[1][2], MAXBASENAME); 15123590Sbloom Rmtname[MAXBASENAME] = '\0'; 15213639Ssam if (Rmtname[0] != '\0') 15313639Ssam onesys = 1; 15413639Ssam break; 15513639Ssam case 'x': 15613639Ssam Debug = atoi(&argv[1][2]); 15713639Ssam if (Debug <= 0) 15813639Ssam Debug = 1; 15925703Sbloom strcat(rflags, argv[1]); 16013639Ssam break; 16118616Sralph case 't': 16218616Sralph turntime = atoi(&argv[1][2])*60;/* minutes to seconds */ 16318616Sralph break; 16417767Sralph case 'L': /* local calls only */ 16517767Sralph LocalOnly++; 16617767Sralph break; 16723590Sbloom #ifdef NOGETPEER 16817767Sralph case 'h': 16917767Sralph Hostnumber = inet_addr(&argv[1][2]); 17017767Sralph break; 17123590Sbloom #endif NOGETPEER 17213639Ssam default: 17317767Sralph printf("unknown flag %s (ignored)\n", argv[1]); 17413639Ssam break; 17513639Ssam } 17613639Ssam --argc; argv++; 17713639Ssam } 17813639Ssam 17917767Sralph while (argc > 1) { 18025703Sbloom fprintf(stderr, "unknown argument %s (ignored)\n", argv[1]); 18117767Sralph --argc; argv++; 18217767Sralph } 18317767Sralph 18427069Sbloom if (Debug && Role == MASTER) 18527069Sbloom chkdebug(); 18627069Sbloom 18725124Sbloom /* Try to run as uucp */ 18817767Sralph setgid(getegid()); 18917767Sralph setuid(geteuid()); 19017767Sralph #ifdef TIOCNOTTY 19117767Sralph /* 19217767Sralph * detach uucico from controlling terminal 19317767Sralph * to defend against rlogind sending us a SIGKILL (!!!) 19417767Sralph */ 19517767Sralph if (Role == MASTER && (ret = open("/dev/tty", 2)) >= 0) { 19617767Sralph ioctl(ret, TIOCNOTTY, STBNULL); 19717767Sralph close(ret); 19817767Sralph } 19917767Sralph #endif TIOCNOTTY 20017767Sralph #ifdef BSD4_2 20125517Stef if (getpgrp(0) == 0) { /* We have no controlling terminal */ 20217767Sralph setpgrp(0, getpid()); 20317767Sralph } 20417767Sralph #endif BSD4_2 20517767Sralph 20617767Sralph ret = subchdir(Spool); 20717767Sralph ASSERT(ret >= 0, "CHDIR FAILED", Spool, ret); 20813639Ssam strcpy(Wrkdir, Spool); 20913639Ssam 21025703Sbloom if (Debug) { 21125703Sbloom setdebug ((Role == SLAVE) ? DBG_TEMP : DBG_PERM); 21225703Sbloom if (Debug > 0) 21325703Sbloom logent ("Local Enabled", "DEBUG"); 21425703Sbloom } 21525703Sbloom 21625703Sbloom /* 21725703Sbloom * First time through: If we're the slave, do initial checking. 21825703Sbloom */ 21913639Ssam if (Role == SLAVE) { 22017767Sralph /* check for /etc/nologin */ 22125124Sbloom if (access(NOLOGIN, 0) == 0) { 22217767Sralph logent(NOLOGIN, "UUCICO SHUTDOWN"); 22323590Sbloom if (Debug > 4) 22417767Sralph logent("DEBUGGING", "continuing anyway"); 22517767Sralph else 22617767Sralph cleanup(1); 22717767Sralph } 22825703Sbloom Ifn = 0; 22925703Sbloom Ofn = 1; 23017767Sralph #ifdef TCPIP 23117767Sralph /* 23217767Sralph * Determine if we are on TCPIP 23317767Sralph */ 234*33559Srick if (isatty(Ifn) == 0) { 23517767Sralph IsTcpIp = 1; 23617767Sralph DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); 23723590Sbloom } else 23823590Sbloom IsTcpIp = 0; 23917767Sralph #endif TCPIP 24013639Ssam /* initial handshake */ 24113639Ssam onesys = 1; 24217767Sralph if (!IsTcpIp) { 24317767Sralph #ifdef USG 24425703Sbloom ret = ioctl(Ifn, TCGETA, &Savettyb); 24513639Ssam Savettyb.c_cflag = (Savettyb.c_cflag & ~CS8) | CS7; 24613639Ssam Savettyb.c_oflag |= OPOST; 24713639Ssam Savettyb.c_lflag |= (ISIG|ICANON|ECHO); 24817767Sralph #else !USG 24925703Sbloom ret = ioctl(Ifn, TIOCGETP, &Savettyb); 25013639Ssam Savettyb.sg_flags |= ECHO; 25113639Ssam Savettyb.sg_flags &= ~RAW; 25217767Sralph #endif !USG 25325703Sbloom ttyn = ttyname(Ifn); 25413639Ssam } 25513639Ssam fixmode(Ifn); 25625703Sbloom 25725703Sbloom /* 25825703Sbloom * Initial Message -- tell them we're here, and who we are. 25925703Sbloom */ 26018616Sralph sprintf(msg, "here=%s", Myfullname); 26117767Sralph omsg('S', msg, Ofn); 26213639Ssam signal(SIGALRM, timeout); 263*33559Srick alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); 26413639Ssam if (setjmp(Sjbuf)) { 26513639Ssam /* timed out */ 26617767Sralph if (!IsTcpIp) { 26717767Sralph #ifdef USG 26825703Sbloom ret = ioctl(Ifn, TCSETA, &Savettyb); 26925703Sbloom 27023590Sbloom #else !USG 27125703Sbloom ret = ioctl(Ifn, TIOCSETP, &Savettyb); 27223590Sbloom #endif !USG 27313639Ssam } 27417767Sralph cleanup(0); 27513639Ssam } 27613639Ssam for (;;) { 27713639Ssam ret = imsg(msg, Ifn); 27825703Sbloom if (ret != SUCCESS) { 27913639Ssam alarm(0); 28017767Sralph if (!IsTcpIp) { 28117767Sralph #ifdef USG 28225703Sbloom ret = ioctl(Ifn, TCSETA, &Savettyb); 28323590Sbloom #else !USG 28425703Sbloom ret = ioctl(Ifn, TIOCSETP, &Savettyb); 28523590Sbloom #endif !USG 28613639Ssam } 28717767Sralph cleanup(0); 28813639Ssam } 28913639Ssam if (msg[0] == 'S') 29013639Ssam break; 29113639Ssam } 29213639Ssam alarm(0); 29313639Ssam q = &msg[1]; 29413639Ssam p = pskip(q); 29523590Sbloom strncpy(Rmtname, q, MAXBASENAME); 29623590Sbloom Rmtname[MAXBASENAME] = '\0'; 29725703Sbloom 29825703Sbloom /* 29925703Sbloom * Now that we know who they are, give the audit file the right 30025703Sbloom * name. 30125703Sbloom */ 30225703Sbloom setdebug (DBG_PERM); 30313639Ssam DEBUG(4, "sys-%s\n", Rmtname); 30423725Sbloom /* The versys will also do an alias on the incoming name */ 30523725Sbloom if (versys(&Rmtname)) { 306*33559Srick #ifdef NOSTRANGERS 30723725Sbloom /* If we don't know them, we won't talk to them... */ 308*33559Srick assert("Unknown host:", Rmtname, 0); 30923590Sbloom omsg('R', "You are unknown to me", Ofn); 31023590Sbloom cleanup(0); 31123725Sbloom #endif NOSTRANGERS 31223590Sbloom } 31317767Sralph #ifdef BSDTCP 31417767Sralph /* we must make sure they are really who they say they 31517767Sralph * are. We compare the hostnumber with the number in the hosts 31617767Sralph * table for the site they claim to be. 31717767Sralph */ 31817767Sralph if (IsTcpIp) { 31917767Sralph struct hostent *hp; 32017767Sralph char *cpnt, *inet_ntoa(); 32125703Sbloom int fromlen; 32217767Sralph struct sockaddr_in from; 32325124Sbloom extern char PhoneNumber[]; 32417767Sralph 32523590Sbloom #ifdef NOGETPEER 32623590Sbloom from.sin_addr.s_addr = Hostnumber; 32723590Sbloom from.sin_family = AF_INET; 32823590Sbloom #else !NOGETPEER 32925703Sbloom fromlen = sizeof(from); 33025703Sbloom if (getpeername(Ifn, &from, &fromlen) < 0) { 33117767Sralph logent(Rmtname, "NOT A TCP CONNECTION"); 33217767Sralph omsg('R', "NOT TCP", Ofn); 33317767Sralph cleanup(0); 33417767Sralph } 33523590Sbloom #endif !NOGETPEER 33617767Sralph hp = gethostbyaddr(&from.sin_addr, 33717767Sralph sizeof (struct in_addr), from.sin_family); 33825703Sbloom if (hp == NULL) { 33917767Sralph /* security break or just old host table? */ 34017767Sralph logent(Rmtname, "UNKNOWN IP-HOST Name ="); 34117767Sralph cpnt = inet_ntoa(from.sin_addr), 34217767Sralph logent(cpnt, "UNKNOWN IP-HOST Number ="); 34317767Sralph sprintf(wkpre, "%s/%s isn't in my host table", 34417767Sralph Rmtname, cpnt); 34517767Sralph omsg('R' ,wkpre ,Ofn); 34617767Sralph cleanup(0); 34717767Sralph } 34825703Sbloom if (Debug > 99) 34917767Sralph logent(Rmtname,"Request from IP-Host name ="); 35025124Sbloom /* 35125124Sbloom * The following is to determine if the name given us by 35225124Sbloom * the Remote uucico matches any of the names 35317767Sralph * given its network number (remote machine) in our 35417767Sralph * host table. 35525124Sbloom * We could check the aliases, but that won't work in 35625124Sbloom * all cases (like if you are running the domain 35725124Sbloom * server, where you don't get any aliases). The only 35825124Sbloom * reliable way I can think of that works in ALL cases 35925124Sbloom * is too look up the site in L.sys and see if the 36025124Sbloom * sitename matches what we would call him if we 36125124Sbloom * originated the call. 36217767Sralph */ 36325124Sbloom /* PhoneNumber contains the official network name of the host we are checking. (set in versys.c) */ 36425124Sbloom if (sncncmp(PhoneNumber, hp->h_name, SYSNSIZE) == 0) { 36517767Sralph if (Debug > 99) 36617767Sralph logent(q,"Found in host Tables"); 36725124Sbloom } else { 36825124Sbloom logent(hp->h_name, "FORGED HOSTNAME"); 36925124Sbloom logent(inet_ntoa(from.sin_addr), "ORIGINATED AT"); 37025124Sbloom logent(PhoneNumber, "SHOULD BE"); 37125124Sbloom sprintf(wkpre, "You're not who you claim to be: %s != %s", hp->h_name, PhoneNumber); 37225124Sbloom omsg('R', wkpre, Ofn); 37325124Sbloom cleanup(0); 37417767Sralph } 37517767Sralph } 37617767Sralph #endif BSDTCP 37717767Sralph 37825703Sbloom if (mlock(Rmtname)) { 37913639Ssam omsg('R', "LCK", Ofn); 38013639Ssam cleanup(0); 38113639Ssam } 38213639Ssam else if (callback(Loginuser)) { 38313639Ssam signal(SIGINT, SIG_IGN); 38413639Ssam signal(SIGHUP, SIG_IGN); 38513639Ssam omsg('R', "CB", Ofn); 38613639Ssam logent("CALLBACK", "REQUIRED"); 38713639Ssam /* set up for call back */ 38817767Sralph systat(Rmtname, SS_CALLBACK, "CALLING BACK"); 38913639Ssam gename(CMDPRE, Rmtname, 'C', file); 39013639Ssam close(creat(subfile(file), 0666)); 39113639Ssam xuucico(Rmtname); 39213639Ssam cleanup(0); 39313639Ssam } 39413639Ssam seq = 0; 39513639Ssam while (*p == '-') { 39613639Ssam q = pskip(p); 39713639Ssam switch(*(++p)) { 39813639Ssam case 'x': 39925703Sbloom if (Debug == 0) { 40025703Sbloom Debug = atoi(++p); 40125703Sbloom if (Debug <= 0) 40225703Sbloom Debug = 1; 40325703Sbloom setdebug(DBG_PERM); 40425703Sbloom if (Debug > 0) 40525703Sbloom logent("Remote Enabled", "DEBUG"); 40625703Sbloom } else { 40725703Sbloom DEBUG(1, "Remote debug request ignored\n", 40825703Sbloom CNULL); 40925703Sbloom } 41013639Ssam break; 41113639Ssam case 'Q': 41213639Ssam seq = atoi(++p); 41313639Ssam break; 41418616Sralph case 'p': 41518616Sralph MaxGrade = DefMaxGrade = *++p; 41618616Sralph DEBUG(4, "MaxGrade set to %c\n", MaxGrade); 41718616Sralph break; 41823590Sbloom case 'v': 41923590Sbloom if (strncmp(p, "grade", 5) == 0) { 42023590Sbloom p += 6; 42123590Sbloom MaxGrade = DefMaxGrade = *p++; 42223590Sbloom DEBUG(4, "MaxGrade set to %c\n", MaxGrade); 42323590Sbloom } 42423590Sbloom break; 42513639Ssam default: 42613639Ssam break; 42713639Ssam } 42813639Ssam p = q; 42913639Ssam } 43013639Ssam if (callok(Rmtname) == SS_BADSEQ) { 43113639Ssam logent("BADSEQ", "PREVIOUS"); 43213639Ssam omsg('R', "BADSEQ", Ofn); 43313639Ssam cleanup(0); 43413639Ssam } 43517767Sralph #ifdef GNXSEQ 43613639Ssam if ((ret = gnxseq(Rmtname)) == seq) { 43713639Ssam omsg('R', "OK", Ofn); 43813639Ssam cmtseq(); 43917767Sralph } else { 44017767Sralph #else !GNXSEQ 44117767Sralph if (seq == 0) 44217767Sralph omsg('R', "OK", Ofn); 44313639Ssam else { 44417767Sralph #endif !GNXSEQ 44513639Ssam systat(Rmtname, Stattype[7], Stattext[7]); 44623590Sbloom logent("BAD SEQ", "FAILED HANDSHAKE"); 44717767Sralph #ifdef GNXSEQ 44813639Ssam ulkseq(); 44917767Sralph #endif GNXSEQ 45013639Ssam omsg('R', "BADSEQ", Ofn); 45113639Ssam cleanup(0); 45213639Ssam } 45313639Ssam if (ttyn != NULL) 45413639Ssam chmod(ttyn, 0600); 45513639Ssam } 45617767Sralph 45713639Ssam loop: 45817767Sralph if(setjmp(Pipebuf)) { /* come here on SIGPIPE */ 45917767Sralph clsacu(); 46017767Sralph close(Ofn); 46117767Sralph close(Ifn); 46217767Sralph Ifn = Ofn = -1; 46317767Sralph rmlock(CNULL); 46417767Sralph sleep(3); 46517767Sralph } 46613639Ssam if (!onesys) { 467*33559Srick do_connect_accounting(); 468*33559Srick StartTime = 0; 46913639Ssam ret = gnsys(Rmtname, Spool, CMDPRE); 47025703Sbloom setdebug(DBG_PERM); 47113639Ssam if (ret == FAIL) 47213639Ssam cleanup(100); 473*33559Srick else if (ret == SUCCESS) 47413639Ssam cleanup(0); 47517767Sralph } else if (Role == MASTER && callok(Rmtname) != 0) { 47613639Ssam logent("SYSTEM STATUS", "CAN NOT CALL"); 47713639Ssam cleanup(0); 47813639Ssam } 47913639Ssam 48023590Sbloom sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname); 481*33559Srick StartTime = 0; 482*33559Srick Bytes_Sent = Bytes_Received = 0L; 48313639Ssam 48417767Sralph signal(SIGINT, SIG_IGN); 48517767Sralph signal(SIGQUIT, SIG_IGN); 48613639Ssam if (Role == MASTER) { 487*33559Srick extern char LineType[]; 48817767Sralph /* check for /etc/nologin */ 48925124Sbloom if (access(NOLOGIN, 0) == 0) { 49017767Sralph logent(NOLOGIN, "UUCICO SHUTDOWN"); 49123590Sbloom if (Debug > 4) 49217767Sralph logent("DEBUGGING", "continuing anyway"); 49317767Sralph else 49417767Sralph cleanup(1); 49517767Sralph } 49613639Ssam /* master part */ 49713639Ssam signal(SIGHUP, SIG_IGN); 49813639Ssam if (Ifn != -1 && Role == MASTER) { 49913639Ssam write(Ofn, EOTMSG, strlen(EOTMSG)); 50013639Ssam clsacu(); 50113639Ssam close(Ofn); 50213639Ssam close(Ifn); 50313639Ssam Ifn = Ofn = -1; 50413639Ssam rmlock(CNULL); 50513639Ssam sleep(3); 50613639Ssam } 50725124Sbloom if (mlock(Rmtname) != SUCCESS) { 508*33559Srick DEBUG(1, "LOCKED: call to %s\n", Rmtname); 50917767Sralph US_SST(us_s_lock); 51013639Ssam goto next; 51113639Ssam } 51213639Ssam Ofn = Ifn = conn(Rmtname); 513*33559Srick sprintf(msg, "call to %s via %s", Rmtname, LineType); 51413639Ssam if (Ofn < 0) { 51517767Sralph if (Ofn != CF_TIME) 51617767Sralph logent(msg, _FAILED); 51717767Sralph /* avoid excessive 'wrong time' info */ 51823590Sbloom if (Stattype[-Ofn] != SS_WRONGTIME){ 51917767Sralph systat(Rmtname, Stattype[-Ofn], Stattext[-Ofn]); 52017767Sralph US_SST(-Ofn); 52117767Sralph UB_SST(-Ofn); 52217767Sralph } 52313639Ssam goto next; 52417767Sralph } else { 52513639Ssam logent(msg, "SUCCEEDED"); 52617767Sralph US_SST(us_s_cok); 52717767Sralph UB_SST(ub_ok); 52813639Ssam } 529*33559Srick InitialRole = MASTER; 53017767Sralph #ifdef TCPIP 53117767Sralph /* 53217767Sralph * Determine if we are on TCPIP 53317767Sralph */ 53425703Sbloom if (isatty(Ifn) == 0) { 53517767Sralph IsTcpIp = 1; 53617767Sralph DEBUG(4, "TCPIP connection -- ioctl-s disabled\n", CNULL); 53723590Sbloom } else 53823590Sbloom IsTcpIp = 0; 53917767Sralph #endif 54017767Sralph 54113639Ssam if (setjmp(Sjbuf)) 54213639Ssam goto next; 54313639Ssam signal(SIGALRM, timeout); 544*33559Srick alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME*2); 54513639Ssam for (;;) { 54613639Ssam ret = imsg(msg, Ifn); 547*33559Srick if (ret != SUCCESS) { 54813639Ssam alarm(0); 549*33559Srick DEBUG(4,"\nimsg failed: errno %d\n", errno); 55017767Sralph logent("imsg 1", _FAILED); 55117767Sralph goto Failure; 55213639Ssam } 55313639Ssam if (msg[0] == 'S') 55413639Ssam break; 55513639Ssam } 556*33559Srick alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); 55717767Sralph #ifdef GNXSEQ 55813639Ssam seq = gnxseq(Rmtname); 55917767Sralph #else !GNXSEQ 56017767Sralph seq = 0; 56117767Sralph #endif !GNXSEQ 56218616Sralph if (MaxGrade != '\177') { 56323590Sbloom DEBUG(2, "Max Grade this transfer is %c\n", MaxGrade); 56425963Sbloom sprintf(msg, "%s -Q%d -p%c -vgrade=%c %s", 56525963Sbloom Myname, seq, MaxGrade, MaxGrade, rflags); 56625963Sbloom } else 56725963Sbloom sprintf(msg, "%s -Q%d %s", Myname, seq, rflags); 56813639Ssam omsg('S', msg, Ofn); 56913639Ssam for (;;) { 57013639Ssam ret = imsg(msg, Ifn); 57113639Ssam DEBUG(4, "msg-%s\n", msg); 57217767Sralph if (ret != SUCCESS) { 57313639Ssam alarm(0); 57417767Sralph #ifdef GNXSEQ 57513639Ssam ulkseq(); 57617767Sralph #endif GNXSEQ 57717767Sralph logent("imsg 2", _FAILED); 57817767Sralph goto Failure; 57913639Ssam } 58013639Ssam if (msg[0] == 'R') 58113639Ssam break; 58213639Ssam } 58313639Ssam alarm(0); 58413639Ssam if (msg[1] == 'B') { 58513639Ssam /* bad sequence */ 58623590Sbloom logent("BAD SEQ", "FAILED HANDSHAKE"); 58717767Sralph US_SST(us_s_hand); 58817767Sralph systat(Rmtname, SS_BADSEQ, Stattext[SS_BADSEQ]); 58917767Sralph #ifdef GNXSEQ 59013639Ssam ulkseq(); 59117767Sralph #endif GNXSEQ 59213639Ssam goto next; 59313639Ssam } 59413639Ssam if (strcmp(&msg[1], "OK") != SAME) { 59523590Sbloom logent(&msg[1], "FAILED HANDSHAKE"); 59617767Sralph US_SST(us_s_hand); 59717767Sralph #ifdef GNXSEQ 59813639Ssam ulkseq(); 59917767Sralph #endif GNXSEQ 60017767Sralph systat(Rmtname, SS_INPROGRESS, 60117767Sralph strcmp(&msg[1], "CB") == SAME? 60223590Sbloom "AWAITING CALLBACK": "FAILED HANDSHAKE"); 60313639Ssam goto next; 60413639Ssam } 60517767Sralph #ifdef GNXSEQ 60613639Ssam cmtseq(); 60717767Sralph #endif GNXSEQ 60813639Ssam } 60917767Sralph DEBUG(1, "Rmtname %s, ", Rmtname); 61013639Ssam DEBUG(1, "Role %s, ", Role ? "MASTER" : "SLAVE"); 61113639Ssam DEBUG(1, "Ifn - %d, ", Ifn); 61213639Ssam DEBUG(1, "Loginuser - %s\n", Loginuser); 61313639Ssam 61425703Sbloom ttyn = ttyname(Ifn); 61525703Sbloom 616*33559Srick alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); 61718616Sralph if (ret=setjmp(Sjbuf)) 61813639Ssam goto Failure; 61913639Ssam ret = startup(Role); 62013639Ssam alarm(0); 62113639Ssam if (ret != SUCCESS) { 62217767Sralph logent("startup", _FAILED); 62313639Ssam Failure: 62417767Sralph US_SST(us_s_start); 62518616Sralph systat(Rmtname, SS_FAIL, ret > 0 ? "CONVERSATION FAILED" : 62618616Sralph "STARTUP FAILED"); 62713639Ssam goto next; 62817767Sralph } else { 629*33559Srick char smsg[BUFSIZ], gmsg[10], pmsg[20], bpsmsg[20]; 630*33559Srick extern char UsingProtocol; 631*33559Srick extern int linebaudrate; 632*33559Srick if (ttyn != NULL) 633*33559Srick sprintf(bpsmsg, " %s %d bps", &ttyn[5], linebaudrate); 634*33559Srick else 635*33559Srick bpsmsg[0] = '\0'; 636*33559Srick if (UsingProtocol != 'g') 637*33559Srick sprintf(pmsg, " %c protocol", UsingProtocol); 638*33559Srick else 639*33559Srick pmsg[0] = '\0'; 640*33559Srick if (MaxGrade != '\177') 641*33559Srick sprintf(gmsg, " grade %c", MaxGrade); 642*33559Srick else 643*33559Srick gmsg[0] = '\0'; 644*33559Srick sprintf(smsg, "startup%s%s%s", bpsmsg, pmsg, gmsg); 645*33559Srick logent(smsg, "OK"); 64617767Sralph US_SST(us_s_gress); 647*33559Srick StartTime = Now.time; 64813639Ssam systat(Rmtname, SS_INPROGRESS, "TALKING"); 64913639Ssam ret = cntrl(Role, wkpre); 65013639Ssam DEBUG(1, "cntrl - %d\n", ret); 65113639Ssam signal(SIGINT, SIG_IGN); 65213639Ssam signal(SIGHUP, SIG_IGN); 65313639Ssam signal(SIGALRM, timeout); 654*33559Srick sprintf(smsg, "conversation complete %ld sent %ld received", 655*33559Srick Bytes_Sent, Bytes_Received); 65617767Sralph if (ret == SUCCESS) { 657*33559Srick logent(smsg, "OK"); 65817767Sralph US_SST(us_s_ok); 65913639Ssam rmstat(Rmtname); 66013639Ssam 66117767Sralph } else { 662*33559Srick logent(smsg, _FAILED); 66317767Sralph US_SST(us_s_cf); 66417767Sralph systat(Rmtname, SS_FAIL, "CONVERSATION FAILED"); 66513639Ssam } 666*33559Srick alarm(IsTcpIp?MAXMSGTIME*4:MAXMSGTIME); 66713639Ssam DEBUG(4, "send OO %d,", ret); 66813639Ssam if (!setjmp(Sjbuf)) { 66913639Ssam for (;;) { 67013639Ssam omsg('O', "OOOOO", Ofn); 67113639Ssam ret = imsg(msg, Ifn); 67213639Ssam if (ret != 0) 67313639Ssam break; 67413639Ssam if (msg[0] == 'O') 67513639Ssam break; 67613639Ssam } 67713639Ssam } 67813639Ssam alarm(0); 67917767Sralph clsacu(); 68017767Sralph rmlock(CNULL); 681*33559Srick 68213639Ssam } 68313639Ssam next: 68413639Ssam if (!onesys) { 68513639Ssam goto loop; 68613639Ssam } 68713639Ssam cleanup(0); 68813639Ssam } 68913639Ssam 69017767Sralph #ifndef USG 69113639Ssam struct sgttyb Hupvec; 69213639Ssam #endif 69313639Ssam 69425703Sbloom /* 69525703Sbloom * cleanup and exit with "code" status 69613639Ssam */ 69713639Ssam cleanup(code) 69813639Ssam register int code; 69913639Ssam { 70013639Ssam signal(SIGINT, SIG_IGN); 70113639Ssam signal(SIGHUP, SIG_IGN); 70213639Ssam rmlock(CNULL); 70325703Sbloom sleep(5); /* Wait for any pending output */ 70413639Ssam clsacu(); 70513639Ssam logcls(); 70613639Ssam if (Role == SLAVE) { 70717767Sralph if (!IsTcpIp) { 70817767Sralph #ifdef USG 70913639Ssam Savettyb.c_cflag |= HUPCL; 71023590Sbloom (void) ioctl(0, TCSETA, &Savettyb); 71117767Sralph #else !USG 71223590Sbloom (void) ioctl(0, TIOCHPCL, STBNULL); 71318616Sralph #ifdef TIOCSDTR 71423590Sbloom (void) ioctl(0, TIOCCDTR, STBNULL); 71518616Sralph sleep(2); 71623590Sbloom (void) ioctl(0, TIOCSDTR, STBNULL); 71718616Sralph #else !TIOCSDTR 71823590Sbloom (void) ioctl(0, TIOCGETP, &Hupvec); 71913639Ssam Hupvec.sg_ispeed = B0; 72013639Ssam Hupvec.sg_ospeed = B0; 72123590Sbloom (void) ioctl(0, TIOCSETP, &Hupvec); 72225703Sbloom #endif !TIOCSDTR 72313639Ssam sleep(2); 72423590Sbloom (void) ioctl(0, TIOCSETP, &Savettyb); 72517767Sralph /* make *sure* exclusive access is off */ 72623590Sbloom (void) ioctl(0, TIOCNXCL, STBNULL); 72717767Sralph #endif !USG 72813639Ssam } 72913639Ssam if (ttyn != NULL) 73013639Ssam chmod(ttyn, 0600); 73113639Ssam } 73213639Ssam if (Ofn != -1) { 73313639Ssam if (Role == MASTER) 73413639Ssam write(Ofn, EOTMSG, strlen(EOTMSG)); 73513639Ssam close(Ifn); 73613639Ssam close(Ofn); 73713639Ssam } 73818616Sralph #ifdef DIALINOUT 73918616Sralph /* reenable logins on dialout */ 74018616Sralph reenable(); 74118616Sralph #endif DIALINOUT 74213639Ssam if (code == 0) 74313639Ssam xuuxqt(); 74417767Sralph else 74517767Sralph DEBUG(1, "exit code %d\n", code); 74625703Sbloom setdebug (DBG_CLEAN); 747*33559Srick do_connect_accounting(); 74813639Ssam exit(code); 74913639Ssam } 75013639Ssam 751*33559Srick do_connect_accounting() 752*33559Srick { 753*33559Srick register FILE *fp; 754*33559Srick struct tm *localtime(); 755*33559Srick register struct tm *tm; 756*33559Srick int flags; 757*33559Srick 758*33559Srick if (StartTime == 0) 759*33559Srick return; 760*33559Srick 761*33559Srick #ifdef DO_CONNECT_ACCOUNTING 762*33559Srick fp = fopen("/usr/spool/uucp/CONNECT", "a"); 763*33559Srick ASSERT(fp != NULL, "Can't open CONNECT file", Rmtname, errno); 764*33559Srick 765*33559Srick tm = localtime(&StartTime); 766*33559Srick #ifdef F_SETFL 767*33559Srick flags = fcntl(fileno(fp), F_GETFL, 0); 768*33559Srick fcntl(fileno(fp), F_SETFL, flags|O_APPEND); 769*33559Srick #endif 770*33559Srick #ifdef USG 771*33559Srick fprintf(fp,"%s %d %d%.2d%.2d %.2d%.2d %d %ld %s %ld %ld\n", 772*33559Srick #else /* V7 */ 773*33559Srick fprintf(fp,"%s %d %d%02d%02d %02d%02d %d %ld %s %ld %ld\n", 774*33559Srick #endif /* V7 */ 775*33559Srick Rmtname, InitialRole, tm->tm_year, tm->tm_mon + 1, 776*33559Srick tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_wday, 777*33559Srick (Now.time - StartTime + 59) / 60, 778*33559Srick ttyn == NULL ? "ttyp0" : &ttyn[5], 779*33559Srick Bytes_Sent, Bytes_Received); 780*33559Srick fclose(fp); 781*33559Srick #endif /* DO_CONNECT_ACCOUNTING */ 782*33559Srick } 783*33559Srick 78425703Sbloom /* 78525703Sbloom * on interrupt - remove locks and exit 78613639Ssam */ 78713639Ssam 78813639Ssam onintr(inter) 78913639Ssam register int inter; 79013639Ssam { 791*33559Srick char str[BUFSIZ]; 79213639Ssam signal(inter, SIG_IGN); 79313639Ssam sprintf(str, "SIGNAL %d", inter); 79413639Ssam logent(str, "CAUGHT"); 79517767Sralph US_SST(us_s_intr); 79623590Sbloom if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) 79717767Sralph systat(Rmtname, SS_FAIL, str); 798*33559Srick sprintf(str, "conversation complete %ld sent %ld received", 799*33559Srick Bytes_Sent, Bytes_Received); 800*33559Srick logent(str, _FAILED); 80117767Sralph if (inter == SIGPIPE && !onesys) 80217767Sralph longjmp(Pipebuf, 1); 80313639Ssam cleanup(inter); 80413639Ssam } 80513639Ssam 80613639Ssam /* 80713639Ssam * Catch a special signal 80813639Ssam * (SIGFPE, ugh), and toggle debugging between 0 and 30. 80913639Ssam * Handy for looking in on long running uucicos. 81013639Ssam */ 81125703Sbloom dbg_signal() 81213639Ssam { 81325703Sbloom Debug = (Debug == 0) ? 30 : 0; 81425703Sbloom setdebug(DBG_PERM); 81525703Sbloom if (Debug > 0) 81625703Sbloom logent("Signal Enabled", "DEBUG"); 81725703Sbloom } 81817767Sralph 81925703Sbloom 82025703Sbloom /* 82125703Sbloom * Check debugging requests, and open RMTDEBUG audit file if necessary. If an 82225703Sbloom * audit file is needed, the parm argument indicates how to create the file: 82325703Sbloom * 82425703Sbloom * DBG_TEMP - Open a temporary file, with filename = RMTDEBUG/pid. 82525703Sbloom * DBG_PERM - Open a permanent audit file, filename = RMTDEBUG/Rmtname. 82625703Sbloom * If a temp file already exists, it is mv'ed to be permanent. 82725703Sbloom * DBG_CLEAN - Cleanup; unlink temp files. 82825703Sbloom * 82925703Sbloom * Restrictions - this code can only cope with one open debug file at a time. 83025703Sbloom * Each call creates a new file; if an old one of the same name exists it will 83125703Sbloom * be overwritten. 83225703Sbloom */ 83325703Sbloom setdebug(parm) 83425703Sbloom int parm; 83525703Sbloom { 83625703Sbloom char buf[BUFSIZ]; /* Buffer for building filenames */ 83725703Sbloom static char *temp = NULL; /* Ptr to temporary file name */ 83825703Sbloom static int auditopen = 0; /* Set to 1 when we open a file */ 83925703Sbloom struct stat stbuf; /* File status buffer */ 84025703Sbloom 84125703Sbloom /* 84225703Sbloom * If movement or cleanup of a temp file is indicated, we do it no 84325703Sbloom * matter what. 84425703Sbloom */ 84525703Sbloom if (temp != CNULL && parm == DBG_PERM) { 84625703Sbloom sprintf(buf, "%s/%s", RMTDEBUG, Rmtname); 84725703Sbloom unlink(buf); 84825703Sbloom if (link(temp, buf) != 0) { 84923590Sbloom Debug = 0; 85025703Sbloom assert("RMTDEBUG LINK FAIL", temp, errno); 85125703Sbloom cleanup(1); 85225703Sbloom } 85325703Sbloom parm = DBG_CLEAN; 85423590Sbloom } 85525703Sbloom if (parm == DBG_CLEAN) { 85625703Sbloom if (temp != CNULL) { 85725703Sbloom unlink(temp); 85825703Sbloom free(temp); 85925703Sbloom temp = CNULL; 86025703Sbloom } 86125703Sbloom return; 86225703Sbloom } 86325703Sbloom 86425703Sbloom if (Debug == 0) 86525703Sbloom return; /* Gotta be in debug to come here. */ 86625703Sbloom 86725703Sbloom /* 86825703Sbloom * If we haven't opened a file already, we can just return if it's 86925703Sbloom * alright to use the stderr we came in with. We can if: 87025703Sbloom * 87125703Sbloom * Role == MASTER, and Stderr is a regular file, a TTY or a pipe. 87225703Sbloom * 87325703Sbloom * Caution: Detecting when stderr is a pipe is tricky, because the 4.2 87425703Sbloom * man page for fstat(2) disagrees with reality, and System V leaves it 87525703Sbloom * undefined, which means different implementations act differently. 87625703Sbloom */ 87725703Sbloom if (!auditopen && Role == MASTER) { 87825703Sbloom if (isatty(fileno(stderr))) 87925703Sbloom return; 88025703Sbloom else if (fstat(fileno(stderr), &stbuf) == 0) { 88125703Sbloom #ifdef USG 88225703Sbloom /* Is Regular File or Fifo */ 88325703Sbloom if ((stbuf.st_mode & 0060000) == 0) 88425703Sbloom return; 88525703Sbloom #else !USG 88617767Sralph #ifdef BSD4_2 88725703Sbloom /* Is Regular File */ 88825703Sbloom if ((stbuf.st_mode & S_IFMT) == S_IFREG || 88925703Sbloom stbuf.st_mode == 0) /* Is a pipe */ 89025703Sbloom return; 89125703Sbloom #else !BSD4_2 89225703Sbloom /* Is Regular File or Pipe */ 89325703Sbloom if ((stbuf.st_mode & S_IFMT) == S_IFREG) 89425703Sbloom return; 89525703Sbloom #endif BSD4_2 89625703Sbloom #endif USG 89725703Sbloom } 89817767Sralph } 89913639Ssam 90025703Sbloom /* 90125703Sbloom * We need RMTDEBUG directory to do auditing. If the file doesn't exist, 90225703Sbloom * then we forget about debugging; if it exists but has improper owner- 90325703Sbloom * ship or modes, we gripe about it in ERRLOG. 90425703Sbloom */ 90525703Sbloom if (stat(RMTDEBUG, &stbuf) != SUCCESS) { 90625703Sbloom Debug = 0; 90725703Sbloom return; 90825703Sbloom } 90925703Sbloom if ((geteuid() != stbuf.st_uid) || /* We must own it */ 91025703Sbloom ((stbuf.st_mode & 0170700) != 040700)) { /* Directory, rwx */ 91125703Sbloom Debug = 0; 91225703Sbloom assert("INVALID RMTDEBUG DIRECTORY:", RMTDEBUG, stbuf.st_mode); 91325703Sbloom return; 91425703Sbloom } 91513639Ssam 91625703Sbloom if (parm == DBG_TEMP) { 91725703Sbloom sprintf(buf, "%s/%d", RMTDEBUG, getpid()); 91825703Sbloom temp = malloc(strlen (buf) + 1); 91925703Sbloom if (temp == CNULL) { 92025703Sbloom Debug = 0; 92125703Sbloom assert("RMTDEBUG MALLOC ERROR:", temp, errno); 92225703Sbloom cleanup(1); 92325703Sbloom } 92425703Sbloom strcpy(temp, buf); 92525703Sbloom } else 92625703Sbloom sprintf(buf, "%s/%s", RMTDEBUG, Rmtname); 92713639Ssam 92825703Sbloom unlink(buf); 92925703Sbloom if (freopen(buf, "w", stderr) != stderr) { 93025703Sbloom Debug = 0; 93125703Sbloom assert("FAILED RMTDEBUG FILE OPEN:", buf, errno); 93225703Sbloom cleanup(1); 93325703Sbloom } 93425703Sbloom setbuf(stderr, CNULL); 93525703Sbloom auditopen = 1; 93613639Ssam } 93713639Ssam 93823590Sbloom /* 93925703Sbloom * catch SIGALRM routine 94013639Ssam */ 94113639Ssam timeout() 94213639Ssam { 94323590Sbloom extern int HaveSentHup; 94423590Sbloom if (!HaveSentHup) { 94523590Sbloom logent(Rmtname, "TIMEOUT"); 94623590Sbloom if (*Rmtname && strncmp(Rmtname, Myname, MAXBASENAME)) { 94723590Sbloom US_SST(us_s_tmot); 94823590Sbloom systat(Rmtname, SS_FAIL, "TIMEOUT"); 94923590Sbloom } 95017767Sralph } 95113639Ssam longjmp(Sjbuf, 1); 95213639Ssam } 95313639Ssam 95413639Ssam static char * 95513639Ssam pskip(p) 95613639Ssam register char *p; 95713639Ssam { 95817767Sralph while(*p && *p != ' ') 95913639Ssam ++p; 96023590Sbloom while(*p && *p == ' ') 96117767Sralph *p++ = 0; 96217767Sralph return p; 96313639Ssam } 964