/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* tcpip720 src/tcpip/usr/samples/tcpip/onhost/hostcon0.c 1.10 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1986,1989 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ static char sccsid[] = "@(#)99 1.10 src/tcpip/usr/samples/tcpip/onhost/hostcon0.c, tcpip_samples, tcpip720 3/8/94 19:17:54"; /* * COMPONENT_NAME: TCPIP hostcon0.c * * FUNCTIONS: intrsig, pass3270, anyio, closeit, datafromhost, * dbgprint, filterhostcmd, readonhost, running, bailout, * scanmsg, gettn, puttn, selecttn, init_tn3270, selectio, * setecho, useduser, writetohost, writetouser, main * * ORIGINS: 27 * * (C) COPYRIGHT International Business Machines Corp. 1986, 1988, 1989 * All Rights Reserved * Licensed Materials - Property of IBM * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* NOTICE TO USERS OF THE SOURCE CODE EXAMPLES INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, IS WITH YOU. SHOULD ANY PART OF THE SOURCE CODE EXAMPLES PROVE DEFECTIVE, YOU (AND NOT IBM OR AN AUTHORIZED RISC System/6000* WORKSTATION DEALER) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. * RISC System/6000 is a trademark of International Business Machines Corporation. */ /* Set up a connection to an IBM host. */ char version [] = "1.1"; /* static char AIXwhatC[] = "hostcon0.c 1.20 PASC 1.20"; */ /* * hostconnect nnn where nnn is the name of the remote machine * will connect to the remote machine and send messages until * it sees the login prompt. It asks user for a userid and password, * sends the login and password messages, sets up the host, and if all * goes well, it will then put itself into the background and * wait for onhost action. */ #include #include #include #include #include #include #ifdef BSD42LIB #include #include struct sgttyb ttyb; #include #include #define memcpy(x,y,n) bcopy(y,x,n) #endif BSD42LIB #ifdef SYSVLIB #ifndef AIXV4 #define index strchr #define rindex strrchr #endif #include #include struct termio ttyb; #include #ifdef AIXV3 #include #else #include #endif AIXV3 #include #endif SYSVLIB /* has BSD sigvec operations */ #ifdef SIGVEC struct sigvec oldvec, newvec; #endif SIGVEC #include #include #include struct sockaddr_in sin; int ibits ,obits; int rdnil; /* i/o deadman */ struct timeval time5 = {5, 0 }; struct timeval time2 = {2, 0 }; /* DOINIT causes values to initialized in hostcon0.h */ #define DOINIT /* EXTERN is initialized to null in hostcon0.c, extern in hostcon*.c */ #define EXTERN #include "hostcon0.h" #include "onhost0.h" nl_catd catd; #define touserbuf (TOuserbuf+CShlen) int cmscc; int cmsstate; int cmsretcode; int spclcmd = 0; extern int echoed; extern char Auth[]; extern int authen; extern char alias[]; int cmsreadok, cmswriteok, localreadok, localwriteok; jmp_buf ExitOne; hosttype hostsys = hostunk; int kbd = 0; int pidmain; int tsomore = 0; int NDflag = 0; int spmsgn; char spmsg[512]; int timedout; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * =====>intrsig called by system when certain signals are received * * see sigvec calls in main() * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifdef SIGVEC #ifdef __SIGVOID /* la1 AIX/370 twitch - see /usr/include/sys/signal.h */ __SIGVOID #endif intrsig(sig,code,scp) int sig, code; struct sigcontext *scp; #else ~SIGVEC intrsig(sig) int sig; #endif ~SIGVEC { if ( sig == SIGALRM ) { return; } if ( ( sig == SIGINT ) || ( sig == SIGTERM ) ) longjmp( (jmp_buf *) ExitOne, -1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> pass3270 passes data between the sockets. The host data in * * fromcmsbuf goes to the application (em3278, for example) and * * application data in fromuserbuf goes to the host. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int pass3270() { int n; if (cmsreadok && !ntouser) { ntouser = read(remotesock, fromcmsbuf,sizeof(fromcmsbuf)); debug2((stddbg,"tn3270 CMSread ntouser=%d errno=%d\n",ntouser,errno)); if (debugvar>3) dbgprcms(fromcmsbuf,ntouser,"remoteread datastream %d bytes:\n"); if (ntouser==0) if ( 3 < rdnil) { UserStage = LostHost; if (!automaticlogin) quitanyio++; return(-1); } else rdnil++; else rdnil = 0; if (ntouser < 0) { if (errno==ENODEV) { /* connection closed */ UserStage = LostHost; return(-1); } ntouser = 0; } nnltouser = ntouser; } if (ntouser && localwriteok) { n = write(localwrite,fromcmsbuf,ntouser); debug2((stddbg,"tn3270 localwrite n=%d errno=%d\n",n,errno)); if (debugvar>3) dbgprcms(fromcmsbuf,n,"localwrite datastream %d bytes:\n"); ntouser -= n; nnltouser = ntouser; } if (localreadok && !ntocms) { ntocms = read(localread,fromuserbuf,sizeof(fromcmsbuf)); debug2((stddbg,"tn3270 localread ntocms=%d errno=%d\n",ntocms,errno)); if (debugvar>3) dbgprcms(fromuserbuf,ntocms,"localread datastream %d bytes:\n"); if (ntocms <= 0) return(-1); #ifdef LDSF if (isldsf) { /* strip IAC EOR */ n = ntocms - 1; if (byte(fromuserbuf[n])==EOR) n--; if (byte(fromuserbuf[n])==IAC) n--; if (n == (ntocms - 3)) ntocms -= 2; } #endif LDSF } if (ntocms && cmswriteok) { n = write(remotesock,fromuserbuf,ntocms); ntocms -= n; debug2((stddbg,"tn3270 CMSwrite n=%d errno=%d\n",n,errno)); if (debugvar>3) dbgprcms(fromuserbuf,n,"remotewrite datastream %d bytes:\n"); } return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> anyio contains the select loop for read or write to host and * * read or write to onhost - exits if quitarg. anyio is called * * from main for login and from running (in main). quitarg is * * set if connection lost to host, connection lost to onhost, * * login completes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ anyio() { int usercc = 0; int settimeout; struct timeval *timeptr; timeptr = (struct timeval *) 0; debug2((stddbg,"anyio: read=%d write=%d remote=%d \n", localread,localwrite,remotesock)); timedout = settimeout = quitanyio = 0; while (1) { timedout = selectio(timeptr); if (tn3270 == 2) { if ( pass3270()) return; } else { if (cmsreadok) if ( datafromhost()) /* reads from host, increment cmscc */ break; /* filter fromcmsbuf into touserbuf * increment ntouser, possibly print some data * note touserbuf will not be sent to user until * next iteration of anyio */ if ( 0 < cmscc) { cmscc = cmstouserbuf(cmscc); debug2((stddbg,"anyio: cmstouserbuf processed\n")); } if (localwriteok) writetouser(); if (localreadok) { if (Running) if ( (usercc = readonhost()) < 0) return; /* local read broke - exit from anyio */ } if (iplrequested) { iplrequested = 0; (void) strcpy(fromuserbuf,iplcmd); usercc = strlen(fromuserbuf); fromuserbuf[usercc++] = '\n'; cmsstate &= ~(needNDread | needCMSinp | needCMScmd | needCPcmd); telluser = 0; } if (automaticlogin) { if (ntocms == 0 ) usercc = StartupCommands(fromuserbuf,timedout, &settimeout); timedout = 0; if (settimeout) timeptr = &time2; else timeptr = (struct timeval *) 0; } if (quitanyio) return; if ( usercc) /* fromuserbuf --> fromuserbuf */ usercc = filterhostcmd(usercc); if (0 < usercc) /* fromuserbuf --> tocmsbuf */ usercc = usertocmsbuf(usercc); if ( cmswriteok && ntocms ) { writetohost(); /* tocmsbuf --> host */ } } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> closeit close all sockets and files * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ closeit() { if (remotesock>0) { #ifdef LDSF if (isldsf == 0) #endif LDSF (void) shutdown(remotesock,2); (void) close(remotesock); remotesock = -1; } (void) docmssock(oncmsUnmake); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> datafromhost called by anyio to read data from host * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int datafromhost() { int n; /* read data from host into fromcmsbuf */ errno = 0; n = read(remotesock, &fromcmsbuf[cmscc],sizeof(fromcmsbuf)-(cmscc+1)); if (n <= 0 ) { debug2((stddbg,"hostcon0:datafromhost: read returns %d (errno %d)\n", n,errno)); if (errno == EWOULDBLOCK) n = 0; else if (errno==ENODEV) { /* connection closed */ debug2((stddbg,"datafromhost: connection closed\n")); UserStage = LostHost; if (automaticlogin) return(0); return(1); } else { if (tn3270 && ConnectOnly) { debug2((stddbg,"No datafromhost connectonly errno=%d\n",errno)); return(0); } debug((stddbg,"datafromhost got n=%d errno=%d \n",n,errno)); UserStage = LostHost; if (automaticlogin) return(0); return(1); } } if (n && (debugvar > 2) ) if (debugvar>3) dbgprcms(&fromcmsbuf[cmscc],n,"<===From CMS n=%d\n"); if ( n > sizeof(fromcmsbuf) ) { printf(catgets(catd,HOSTCON0_ERR,HC_BAD_VALUE, "weird value on read fd=%d n=%d max=%d\n"), remotesock,n,sizeof(fromcmsbuf)); n = 0; } cmscc += n; debug2((stddbg,"datafromhost n=%d cmscc=%d errno=%d \n",n, cmscc, errno)); return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> dbgprint writes hex characters to stddbg * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ dbgprint(a,n,msg) char a[], *msg; int n; { /* write a[0..n-1] to stddbg in hex */ int j, k; debug((stddbg,"dbgprint: %d %s\n",n,msg)); for(k=1, j = 0; (j filterhostcmd looks for commands arriving from onhost * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int filterhostcmd(n0) int n0; { /* got command for VM but see if it is special * return n1 = number of characters in result */ register int n1; n1 = n0; fromuserbuf[n1] = '\0'; n1 = srch(fromuserbuf,spclcmd); if (n1) { spclcmd = 0; cmsstate &= ~(needNDread | needCMSinp | needCMScmd | needCPcmd); telluser = 0; if ((fromuserbuf[0] == AsciiEsc) || (fromuserbuf[0] == '^')) { if (dokeys(fromuserbuf) == 0) { /* immed pf produces host state change, otherwise input area change */ n1 = 0; echoed = 0; } } } else /* returns a message in spmsg */ GotNucxRetCode = 1; return(n1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> readonhost data from onhost and put it in fromuserbuf. * * localread is a socket to onhost. if return is < 0, then * * anyio will return to its caller. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int readonhost() { int n; int m; errno = 0; for(n=0; n >=0;) { m = read(localread,fromuserbuf+n,sizeof(fromuserbuf)-n); if (m < 0 && errno == EWOULDBLOCK) m = 0; else if (m <= 0) n = -1; if ( m > 0) { n += m; if ( scanmsg(&n) ) /* will have set n if non-zero return */ break; } } debug2((stddbg,"readonhost: errno=%d, m=%d, n=%d\n",errno,m,n)); return(n); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> running is called by main when login is complete. here is the * * main loop to create local socket, wait for onhost to open * * the socket, then call anyio and on return close socket and * * loop while userstage is GotNucx. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int running() { int rc; /* now we are running - ignore all signals except SIGTERM */ #ifdef SIGVEC newvec.sv_handler = SIG_IGN; for (rc=1; rc <= 32; rc++) { /* sigvec will ignore some values of rc such as 9 */ if (rc != SIGTERM) sigvec(rc, &newvec, &oldvec); } #else ~SIGVEC for (rc=1; rc <= 32; rc++) { /* signal will ignore some values of rc such as 9 */ if (rc != SIGTERM) (void) signal(rc, SIG_IGN); } #endif SIGVEC GotNucxRetCode = 0; pendofmsg = NULL; cmsstate = 0; Running = 1; /* If localread or localwrite breaks then onhost has terminated * but we can close then open to wait for a next onhost interaction * If hostread or hostwrite breaks then the host connection has been * lost so we close everything and exit. */ while (UserStage == GotNucx) { errno = 0; /* if 4.2, oncmsOpen will wait until onhost does an open */ if (docmssock(oncmsOpen) ) break; if ( tn3270 == 1) { tn3270++; if (init_tn3270()) { fprintf(stderr,catgets(catd,HOSTCON0_ERR,HC_EMUL_FAIL, "Expected full-screen emulator negotiation has failed.\n")); (void) docmssock(oncmsClose); tn3270 = 0; continue; } } anyio(); (void) docmssock(oncmsClose); cmscc = ntocms = ntouser = nnltouser = 0; if ( tn3270 == 2) { tn3270 = 0; havecursor = kbd = 0; ScreenStatus = UndefinedScreen; putiacbuf(ClearKey,IAC,EOR); debug2((stddbg,"Send ClearKey after em3278\n")); writetohost(); } } /* end while */ return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> bailout of host connection because we have not authenticated * * the onhost connection. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int bailout() { printf(catgets(catd,HOSTCON0_ERR,HC_UN_AUTH, "\nYour host connection to the alias named %s has been closed\nbecause of an unauthenticated attempt to use it.\n"),alias); closeit(); exit(1); return(1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> scanmsg to pickup any messages between onhost and hostconnect * * from the data flowing between the user and the host. Once * * one host data message is processed the rest is trashed! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int scanmsg(pn) int *pn; { /* Look for msgs from onhost, when first data msg is found, move * data to front of buffer, zap number of characters, trash remainder. * Msg may not be complete within one packet so return 0 and expect * the caller to come back after (append) reading more data. */ register char *p, *q; register int nr, ndata, datatype ; nr = *pn; *pn = 0; p = fromuserbuf; ndata = datatype = 0; if (debugvar > 2) dbgprint(p,nr,"scammsg (hostcon0):"); again: /* debug2((stddbg,"scanmsg: p=%d, nr=%d, byte(*p)=%d\n",p,nr,byte(*p))); */ if ((!authen) && (byte(*p) != CSopen)) bailout(); switch( byte(*p) ) { case CSclose: debug2((stddbg,"scanmsg: CSclose message\n")); *pn = -1; return(1); case CSopen: if (nr < 8) return(0); p++; debug((stddbg,"authentication received %s, expected %s.\n",p,Auth)); if ( 0 != strcmp( p, Auth) ) bailout(); authen++; p += 7; nr -= 8; debug2((stddbg,"scanmsg: CSopen message\n")); telluser = 0; if (nr) goto again; break; case CSipl: p++; nr--; iplrequested++; debug2((stddbg,"scanmsg: CSipl message\n")); if (nr) goto again; break; case CSgetstate: p++; nr--; debug2((stddbg,"scanmsg: CSgetstate message\n")); telluser = 1; if (nr) goto again; break; case CSem3278: p++; nr--; debug2((stddbg,"scanmsg: CSem3270 message\n")); tn3270 = 1; /* next connection is 3270 full-screen emulator */ tn3270n = byte(*p++); /* 0 standard binary eor 3278 negotiation */ if (--nr) goto again; break; case CSdata: if (nr < 4) return(0); p++; ndata = byte(*p++); ndata = 256 * ndata + byte(*p++); datatype = byte(*p++); nr -= 4; debug2((stddbg,"scanmsg: CSdata message\n")); break; default: debug2((stddbg,"scanmsg: switch default\n")); printf(catgets(catd,HOSTCON0_ERR,HC_UNEXPECTED, "hostconnect received unexpected data.\n")); *pn = -1; return(1); } if (ndata) { if (ndata > nr) return(0); switch(datatype) { case CScwd: (void) strcpy(wwdir," "); if (0 != strlen(p)) (void) strcat(wwdir,p); else (void) strcat(wwdir,"? ?"); nr -= ndata; p += ndata; ndata = 0; if (nr) goto again; break; case CScmscmd: spclcmd = 1; default: /* normal input or host command */ *pn = ndata; /* move everything to front of buffer * nr should be equal to ndata */ if (nr != ndata) debug((stddbg,"scanmsg: possible problem, nr=%d != ndata=%d bytes\n", nr,ndata)); q = fromuserbuf; for (nr = 0; nr < ndata; nr++) *q++ = *p++; debug2((stddbg,"hostcon0:scanmsg: gets %d bytes, state=%d\n",ndata,cmsstate)); ndata = 0; } } return(1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> gettn reads from the full-screen terminal emulator * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int gettn (item) int item; { int ctr, i, limit, n; struct timeval *timeptr; timeptr = (struct timeval *) 0; ctr = 0; for (limit=0;limit<10;limit++) { (void) selecttn(timeptr); if (!localreadok) continue; n = read(localread,&fromuserbuf[ctr],sizeof(fromuserbuf)-ctr); debug2((stddbg,"gettn read n=%d,errno=%d\n",n,errno)); if (n<0) { debug2((stddbg,"gettn errno=%d\n",errno)); n = 0; } for (i=ctr;i puttn writes to the full-screen terminal emulator * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int puttn () { int n, limit; struct timeval *timeptr; timeptr = (struct timeval *) 0; for (limit=0;limit<10;limit++) { (void) selecttn(timeptr); if (!localwriteok) continue; n = write(localwrite,TOuserbuf,ntouser); ntouser -= n; return(n); } debug2((stddbg,"puttn limit\n")); return(-1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> selecttn waits for full-screen terminal emulator read or write * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int selecttn(timeptr) struct timeval *timeptr; { int selret; if (ntouser) { ibits = 0; obits = (1 << localwrite); } else { ibits = (1 << localread); obits = 0; } again: errno = 0; /* debug2((stddbg,"selecttn0 user=%d,%d tell=%d timep=%x\n", ibits, obits, telluser, timeptr)); */ selret = select(16, &ibits, &obits, (int *) 0,timeptr); localreadok = ibits & (1 << localread); localwriteok = obits & (1 << localwrite); if (errno == EINTR) goto again; return(!selret); /* return 1 if timer expired */ } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> init_tn3270 negotiates binary telnet with the full-screen * * terminal emulator after onhost has given it our socket * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int init_tn3270() { int n, ni; #define TTLEN 11 char lasttt[TTLEN], wanttt[TTLEN]; lasttt[0] = IAC; (void) strcpy(wanttt,"IBM-3278-2"); wanttt[TTLEN-1] = IAC; debug2((stddbg,"init_tn3270\n")); ntouser = 0; putiactn(IAC,DO,Terminal_type); n = puttn(); debug2((stddbg,"write (iac) do termtype = %d\n",n)); n = gettn(Terminal_type); if (n<=0) return(-1); ni = 0; if (!(byte(fromuserbuf[ni++])==IAC)) return(-1); if (!(byte(fromuserbuf[ni++])==WILL)) return(-1); if (!(byte(fromuserbuf[ni++])==Terminal_type)) return(-1); debug2((stddbg,"read (iac) will termtype = %d\n",n)); /* repeat until terminal type is IBM-3278-2 (pass) or repeats (fail) */ /* this code accepts any repeated terminal type */ do { putiactn(IAC,SB,Terminal_type); putiactn(1,IAC,SE); n = puttn(); debug2((stddbg,"write sb termtype 1 iac se = %d\n",n)); n = gettn(SE); if (n<=0) return(-1); ni = 0; if (!(byte(fromuserbuf[ni++])==IAC)) return(-1); if (!(byte(fromuserbuf[ni++])==SB)) return(-1); if (!(byte(fromuserbuf[ni++])==Terminal_type)) return(-1); if (!(byte(fromuserbuf[ni++])==0)) return(-1); debug2((stddbg,"read sb termtype .. 16 se = %d\n",n)); } while ( strncmp(wanttt,&fromuserbuf[ni],TTLEN) && strncmp(lasttt,&fromuserbuf[ni],TTLEN) && strlen(strncpy(lasttt,&fromuserbuf[ni],TTLEN)) ); if ( tn3270n == 0) { putiactn(IAC,DO,End_of_record); n = puttn(); debug2((stddbg,"write do eor = %d\n",n)); n = gettn(End_of_record); if (n<=0) return(-1); ni = 0; if (!(byte(fromuserbuf[ni++])==IAC)) return(-1); if (!(byte(fromuserbuf[ni++])==WILL)) return(-1); if (!(byte(fromuserbuf[ni++])==End_of_record)) return(-1); debug2((stddbg,"read will eor = %d\n",n)); putiactn(IAC,WILL,End_of_record); n = puttn(); debug2((stddbg,"write will eor = %d\n",n)); n = gettn(End_of_record); if (n<=0) return(-1); ni = 0; if (!(byte(fromuserbuf[ni++])==IAC)) return(-1); if (!(byte(fromuserbuf[ni++])==DO)) return(-1); if (!(byte(fromuserbuf[ni++])==End_of_record)) return(-1); debug2((stddbg,"read do eor = %d\n",n)); } putiactn(IAC,DO,Transmit_binary); n = puttn(); debug2((stddbg,"write do binary = %d\n",n)); n = gettn(Transmit_binary); if (n<=0) return(-1); ni = 0; if (!(byte(fromuserbuf[ni++])==IAC)) return(-1); if (!(byte(fromuserbuf[ni])==WILL) && !(byte(fromuserbuf[ni])==DO)) return(-1); ni++; if (!(byte(fromuserbuf[ni++])==Transmit_binary)) return(-1); debug2((stddbg,"read will/do binary = %d\n",n)); putiactn(IAC,WILL,Transmit_binary); n = puttn(); debug2((stddbg,"write will binary = %d\n",n)); n = gettn(Transmit_binary); if (n<=0) return(-1); ni = 0; if (!(byte(fromuserbuf[ni++])==IAC)) return(-1); if (!(byte(fromuserbuf[ni])==DO) && !(byte(fromuserbuf[ni])==WILL)) return(-1); ni++; if (!(byte(fromuserbuf[ni++])==Transmit_binary)) return(-1); debug2((stddbg,"read do/will binary = %d\n",n)); putiacbuf(ClearKey,IAC,EOR); debug2((stddbg,"Send ClearKey befor em3278\n")); writetohost(); return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> selectio is called from anyio to select and wait for data * * to send or receive between user and host * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int selectio(timeptr) struct timeval *timeptr; { int selret; /* when running == 0 * localread = fileno(stdin) if userdoes login else - 1 * localwrite = fileno(stdout) * when running == 1 * localread = socket number of active onhost socket * localwrite = ditto */ ibits = obits = 0; /*if something to send to host, send it else read user */ if (ntocms ) obits |= (1 << remotesock); else if (localread >= 0) ibits |= (1 << localread); /*if something to send to user, send it else read host*/ if ( nnltouser > 0 ) obits |= (1 << localwrite); else ibits |= (1 << remotesock); /* this creates output if screen has VMREAD or CPREAD */ if (telluser ) obits |= (1 << localwrite); /* we usually have timeptr == 0 except for initial login * when some systems suppress the VM read */ again: errno = 0; debug2((stddbg,"selectio0 cms=%d,%d user=%d,%d tell=%d timep=%x\n", ( ibits & (1 << remotesock) ), ( obits & (1 << remotesock) ), ( ibits & (1 << localread) ), ( obits & (1 << localwrite) ), telluser, timeptr)); selret = select(16, &ibits, &obits, (int *) 0,timeptr); cmsreadok = ibits & (1 << remotesock); cmswriteok = obits & (1 << remotesock); localreadok = ibits & (1 << localread); localwriteok = obits & (1 << localwrite); debug2((stddbg,"selectio1 cms=%d,%d user=%d,%d errno=%d timeout=%d ntouser=%d\n", cmsreadok, cmswriteok, localreadok, localwriteok, errno,!selret, ntouser)); if (errno == EINTR) goto again; if (automaticlogin) localwriteok = 1; /* because write command is suppressed */ return(!selret); /* return 1 if timer expired */ } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> setecho turns local echo on and off to protect password entry * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int oldechoon = 1; void setecho(echoon) int echoon; { if (echoon == oldechoon) return; #ifdef BSD42LIB ioctl(0,TIOCGETP,&ttyb); if (echoon) ttyb.sg_flags |= ECHO; else ttyb.sg_flags &= ~ECHO; ioctl(0,TIOCSETP,&ttyb); #else SYSVLIB ioctl(0,TCGETA,&ttyb); if (echoon) ttyb.c_lflag |= ECHO; else ttyb.c_lflag &= ~ECHO; ioctl(0,TCSETA,&ttyb); #endif SYSVLIB oldechoon = echoon; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> useduser cleans up touserbuf after nwbytes have been used up * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ useduser(nw) int nw; { /* we used nw bytes in buffer. There are ntouser in buffer */ register char *p, *q, *pmax; if (ntouser - nw) { debug2((stddbg,"useduser leave %d-%d\n",ntouser,nw)); if (nw) { q = touserbuf + nw; /* first unused byte */ pmax = touserbuf + ntouser-1-nw; for( p = touserbuf; p <= pmax;) *p++ = *q++; q = pmax; while ((q>=touserbuf) && ( byte(*q) != '\n')) q--; nnltouser = q - touserbuf; ntouser -= nw; } } else nnltouser = ntouser = 0; debug2((stddbg,"useduser n= %d %d %d\n",ntouser,nnltouser,nw)); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> writetohost writes ntocms characters from tocmsbuf to the host * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ writetohost() { int n; register char *p, *q, *pmax; errno = 0; n = write(remotesock, tocmsbuf, ntocms); debug2((stddbg,"writetohost %d n=%d errno=%d\n",ntocms,n,errno)); if (n <= 0) { if (errno == ENOBUFS || errno == EWOULDBLOCK) n = 0; else { debug((stddbg,"write to remote errno=%d\n",errno)); UserStage = LostHost; if (!automaticlogin) quitanyio++; n = 0; } } if (n && (debugvar > 3)) dbgprcms(tocmsbuf,n,"===>To CMS n=%d\n"); if (ntocms-n) { q = tocmsbuf+n; ntocms -= n; for(p = tocmsbuf, pmax = p+ntocms; p < pmax;) *p++ = *q++; } else { ntocms = 0; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> writetouser scan touserbuf for keywords during login, write * * nnltouser characters from touserbuf to onhost * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ writetouser() { /* nnltouser characters in touserbuf ready to write */ register int j, nw, nb, na; char c; debug2((stddbg, "writetouser errno=%d n=%d %d run=%d %d\n", errno,nnltouser,ntouser,Running,telluser)); if (debugvar>3) dbgprint(touserbuf,ntouser,"write to user"); j = nw = na = 0; nb = 0; if (Running ) goto part2; if ( nnltouser > 0) { nb = nnltouser + CShlen; /* StartupCommands uses keyword search */ if (keywordi < 0) findkeyword(touserbuf,nnltouser); if (automaticlogin) { /* do not write */ nw = nnltouser; c = touserbuf[nw]; touserbuf[nw] = '\0'; debug((stddbg,"autologin buried these %d bytes from CMS\n%s\n",nw,touserbuf)); touserbuf[nw] = c; } else nw = write(localwrite, touserbuf, nw); } goto out; part2: /* nb = number of bytes to use from buffer * na = number of additional bytes to write */ na = 0; if (pendofmsg) { debug2((stddbg,"pendof %d %d %d\n", GotNucxRetCode,nnltouser,pendofmsg-touserbuf)); if ( nnltouser > (pendofmsg - touserbuf) ) nnltouser = pendofmsg - touserbuf; pendofmsg = NULL; } if (nnltouser) { nb = nnltouser + CShlen; TOuserbuf[0] = CSdata; TOuserbuf[1] = nnltouser / 256; TOuserbuf[2] = nnltouser % 256; TOuserbuf[3] = CSoutput; } if (spmsgn) { debug2((stddbg,"writeuser: copy %d bytes at %d\n",spmsgn,nb)); (void) memcpy(&TOuserbuf[nb],spmsg,spmsgn); debug2((stddbg,"writeuser: copy T=%s= s=%s=\n",&TOuserbuf[nb],spmsg+CShlen)); na += spmsgn; spmsgn = 0; } /* if host wants to read then inform onhost */ telluser = ( telluser || ( ScreenStatus == VMread) || ( ScreenStatus == CPread) || ( ( ScreenStatus == UndefinedScreen) && kbd && havecursor) ); if ( telluser) { if (ScreenStatus == CPread) { cmsstate |= needCPcmd; } else if (ScreenStatus == VMread) { cmsstate |= needCMSinp; } else if (ScreenStatus == UndefinedScreen) { if ( kbd && havecursor && !tsomore ) { cmsstate |= needCMScmd; kbd = havecursor = 0; } } if (NDflag && (cmsstate & (needCMSinp | needCMScmd | needCPcmd)) ) { NDflag = 0; cmsstate |= needNDread; } if(ntouser != nnltouser ) { debug2((stddbg,"writetouser: possible error, flushed %d after nl\n", ntouser-nnltouser)); ntouser = nnltouser; } TOuserbuf[nb+(na++)] = CSstate; TOuserbuf[nb+(na++)] = cmsstate; debug2((stddbg,"writetouser cmsstate=%d SpecialRc=%d\n",cmsstate, SpecialRc)); GotNucxRetCode = 0; } telluser = 0; j = na+nb; if ( j > 0 ) { nw = write(localwrite, TOuserbuf, j); out: if (nw == 0) nb = 0; else if ( nw < 0){ if (errno == EMSGSIZE) { debug2((stddbg,"write to local errno=EMSGSIZE j=%d\n",j)); errno = nw = nb = 0; #ifndef SIGVEC (void) signal(SIGALRM, intrsig); #endif ~SIGVEC (void) alarm( (unsigned int) 2); pause(); (void) alarm( (unsigned int) 0); } else { debug2((stddbg,"write to local errno=%d\n",errno)); quitanyio++; return; } } if (debugvar > 3) { char *p; p = TOuserbuf; fprintf(stddbg,"writetouser errno=%d wrote nw=%d na=%d nb=%d c=",errno, nw, na, nb); if (nw > 20) nw = 20; for (j=0; j main gets args, reads onhost.profil, opens a socket to the * * host, forks a child, and exits on signal from child. * * Child connects to host and does login, then calls running * * to handle onhost interaction * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ main(argc,argv) int argc; char *argv[]; { int rand(), srand(); long time(); int rc; /* set the locale to the default */ setlocale(LC_ALL, ""); /* open the message catalog */ catd = catopen("hostconn.cat",NL_CAT_LOCALE); rc = 0; stddbg = stderr; ScreenStatus = UndefinedScreen; localread = remotesock = -1; localwrite = fileno(stdout); automaticlogin = 1; iplrequested = ConnectOnly = 0; forkid = -1; if ( getargs(argc, argv) ) exit(1); if ( hostsys == hostunk) ConnectOnly = 1; /* do not try automatic login for unknown */ if ( ConnectOnly ) { printf(catgets(catd,HOSTCON0_ERR,HC_CONN_ONLY, "Connection only - use onhost to login to the host and execute onhostld.\n")); } if (findprofile() ) exit(1); if (opensockfile() ) exit(1); init3270(); if (setjmp(ExitOne) != 0) { if (forkid == 0) { if (Running) { printf(catgets(catd,HOSTCON0_ERR,HC_INTER, "%s got interrupt and closes\n"),argv[0]); (void) strcpy(fromuserbuf,"logoff\n"); ntocms = 0; (void) usertocmsbuf( strlen(fromuserbuf) ); writetohost(); closeit(); exit(1); } exit(0); } exit(0); } #ifdef SIGVEC newvec.sv_mask = 1; newvec.sv_onstack = 0; newvec.sv_handler = intrsig; sigvec(SIGTERM, &newvec, &oldvec); sigvec(SIGALRM, &newvec, &oldvec); #else ~SIGVEC (void) signal(SIGTERM, intrsig); #endif ~SIGVEC if (debugvar) (void) fflush(stddbg); pidmain = getpid(); if (0 != (forkid = fork())) { for(;;) { /* parent waits for child * child does a kill(pidmain,SIGTERM) and * we exit via longjmp in intrsig */ if (debugvar) (void) fclose(stddbg); pause(); } } #ifdef SIGVEC sigvec(SIGINT, &newvec, &oldvec); #else ~SIGVEC (void) signal(SIGINT, intrsig); (void) signal(SIGPIPE, SIG_IGN); #endif ~SIGVEC makeconnection(phost); if ( 0 != (rc = docmssock(oncmsMake)) ) connected = 0; if (connected) { keywordset(GotNothing); anyio(); /* connecting to host */ printf("\n"); kill(pidmain,SIGTERM); /* kill the main process */ automaticlogin = 0; if (UserStage == GotNucx) { rc = running(); } else rc = 4; } else { kill(pidmain,SIGTERM); /* kill the main process */ if (0 == rc) rc = 3; } closeit(); #ifdef AIXV3 /* close the message catalog */ catclose(catd); #endif AIXV3 exit(rc); }