/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* tcpip720 src/tcpip/usr/samples/tcpip/onhost/onhost0.c 1.9 */ /* */ /* 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[] = "@(#)08 1.9 src/tcpip/usr/samples/tcpip/onhost/onhost0.c, tcpip_samples, tcpip720 3/8/94 19:18:49"; /* * COMPONENT_NAME: TCPIP onhost0.c * * FUNCTIONS: checkline, doem3278, dopath, getcmd, getem3278, getinp, * getinput, Getline, getsocknm, immedinp, initialize, * intrsig, NextItem, openhostsocket, OpenLastAlias, openmsg, * readhost, scanmsg, setecho, usage, writehost, 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. */ /* Talk to hostconnect. */ char version [] = "1.1"; /* static char AIXwhatC[] = "onhost0.c 1.18 PASC 1.18"; */ #include #include #include #include #include #include #ifdef BSD42LIB extern errno; #include #include struct sgttyb ttyb; #include #endif BSD42LIB #include #include #ifdef SYSVLIB #define u_short ushort #define u_long ulong #ifndef AIXV4 #define index strchr #define rindex strrchr #endif #include #include struct termio ttyb; #endif SYSVLIB /* sigvec is available on all IBM systems. It may not be available on older System V where signal will be used instead */ #ifdef SIGVEC /* select the enhanced signal capability if possible */ struct sigvec oldvec, newvec; #endif SIGVEC #ifdef LONGJMP /* a long jump is needed to break a slow read */ int sigjmpok; jmp_buf sigjmp; #endif #include "onhost0.h" nl_catd catd; #define byte(x) ((x)&0377) #define SMALL 32 #define ESC '\033' int argc; char *argp, **argv; char *iam; int cmsretcode = 0; int cmsstate = 0; int dtype = CScmscmd; int hostsocket = -1; char sockfile[80]; FILE *stddbg = NULL; int datatype; int debugvar = 0; int ndata = 0; int gotcmsretcode = 0; int gotint = 0; int gotsigint = 0; FILE *outstream; char sockp0[] = "noalias"; char sockpath[SMALL]; int newsockpath = 0; int xpertuser = 1; int fstest = 0; int fsmode = 0; int prompt = 0; int loud = 0; int nonstop = 0; int bury = 0; int printcmsstatus = 0; #define BFSIZE 4096 char rdbuf[BFSIZE]; char WRbuf[BFSIZE]; #define wrbuf (WRbuf+CShlen) #define bfSIZE (BFSIZE-CShlen) char aliasfile[] = "onhost.alias"; char last_alias[] = "onhost.last"; FILE *fds; char InetAddr[SMALL]; char LPort[SMALL]; char Auth[SMALL]; char em3278[SMALL]; #ifdef BSD42LIB char emdefault[] = "tn3270"; #else char emdefault[] = "tn"; #endif BSD42LIB /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> checkline checks for the onhost end of command flag and, if * * found, extracts the host return code. The result points to * * the beginning of the flag line. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * checkline(q,r) char *q, *r; { #define distinct0 "RetCode:" #define distinct1 "; OnHost End of Command Flag" #define len0 8 #define len1 28 #define lenr 8 #define len 44 int j, k, n; char *p, *pd; if (1 < debugvar) { fprintf(stddbg,"checkline: %d long==>",1+(r-q)); (void) fwrite(q,1,1+(r-q),stddbg); fprintf(stddbg,"<==\n"); } n = len; /* tso hack - skip leading and trailing blank */ if ( ( *q == ' ') && ( *( r - 1) == ' ')) { p = q + 1; n += 2; } else p = q; if ( n != ( r - q)) return ( NULL); if ( ( *p == distinct0[0]) && ( strncmp( distinct0,p,len0) == 0)) { pd = p + len0; if ( strncmp( distinct1,pd+lenr,len1) == 0) { n = 0; for ( j = 0; j < lenr; pd++, j++) { if (*pd >= 'A') k = 10 + *pd - 'A'; else k = *pd - '0'; n = ( n << 4) | k; } cmsretcode = n; gotcmsretcode++; if (debugvar) fprintf(stddbg,"checkline: retcode %d is %d\n",gotcmsretcode,n); return ( q); } } return ( NULL); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> doem3278 tells hostconnect to expect a full-screen emulator, * * then onhost replaces itself with the emulator. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int doem3278() { int n; getem3278(); /* get the IBM-3278-2 full-screen emulator name */ WRbuf[0] = CSem3278; /* tell hostconnect full-screen emulator mode */ WRbuf[1] = '\000'; /* negotiation style. 0 standard */ if (fstest) WRbuf[1] = fstest - 1; n = writehost(2); if (debugvar) fprintf(stddbg,"doem3278: sends CSem3278 %x\n",WRbuf[1]); close(hostsocket); /* close socket so emulator can connect */ if (debugvar) fprintf(stddbg,"doem3278: starting %s for %s:%s\n", em3278,InetAddr,LPort); if (fstest) { fprintf(stdout,catgets(catd,ONHOST_ERR,OH_EMUL_WAIT, "hostconnect is waiting for a full-screen emulator\n to call host %s port %s as an IBM-3278-2 emulator\n"), InetAddr,LPort); exit(0); } if (debugvar) (void) fflush(stddbg); if ( strcmp( em3278,"tn.old") == 0) /* AIX/RT pre 2.2.1 */ n = execlp(em3278,em3278,"-p",LPort,InetAddr,0); else if ( strcmp( em3278,"tn.new") == 0) /* AIX merged tn */ n = execlp(em3278,em3278,"-e3270",InetAddr,LPort,0); else if ( strcmp( em3278,"tn") == 0) #ifdef TNOLD n = execlp(em3278,em3278,"-p",LPort,InetAddr,0); #else n = execlp(em3278,em3278,"-e3270",InetAddr,LPort,0); #endif else n = execlp(em3278,em3278,InetAddr,LPort,0); if (n<0) { fprintf(stderr,catgets(catd,ONHOST_ERR,OH_EXECLP_FAIL, "execlp failed for full-screen emulator ")); perror(em3278); if ( 1 < debugvar) fprintf(stddbg,"doem3278 %s failed errno=%d\n",em3278,errno); return(-1); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> dopath gets current working directory and default user for ftp * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int dopath(line) char *line; { char cwdenv[1024], *cwd; if ( (NULL != (cwd = getenv("LOGNAME"))) || (NULL != (cwd = getenv("USER"))) ) { if (strlen(cwd)) (void) strcpy(line,cwd); else (void) strcpy(line,"?"); (void) strcat(line," "); } else (void) strcpy(line,"? "); if ( (NULL != (cwd = getenv("CWD"))) || #ifdef SYSVLIB (NULL != (cwd = getcwd(cwdenv, 1024))) ) #else !SYSVLIB (NULL != (cwd = getwd(cwdenv))) ) #endif SYSVLIB { if ( (strlen(line) + strlen(cwd)) < 80 ) (void) strcat(line,cwd); else { (void) strcat(line,"??"); /* cwd too long */ } } else { (void) strcat(line,"?"); /* cwd not found */ } return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> getcmd gets a command from argv and puts it in cmdbuf where it * * will be processed and sent to the host. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int getcmd(cmdbuf,szcmdbuf) char *cmdbuf; int szcmdbuf; { int nc; register char *p, *q, *qlast; /* return nc > 0: valid string and cmdbuf[nc] == \n */ /* nc= -1: end of file or read error */ /* nc= -2: cmdbuf too small to hold valid string */ if (! *argv ) return(-1); nc = 0; q = cmdbuf; qlast = q + szcmdbuf -2; p = argp; do { while ((*p) && (q <= qlast)) *q++ = *p++; if (q>qlast) nc = -2; else { if (*argv) { p = *++argv; if (!p) { *q++ = '\n'; nc = q-cmdbuf; *q++ = '\0'; } else *q++ = ' '; } else nc--; } } while (!nc); argp = p; return(nc); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> getem3278 sets the IBM-3278-2 full-screen emulator name * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void getem3278() { static char buf[80]; char *b, *s, *s1, *s2; strcpy (em3278,emdefault); /* set default emulator */ (void) strcpy(sockfile,aliasfile); if ((fds=fopen(sockfile,"r"))==NULL) { /* try to find default */ if ( (s = getenv ("HOME")) != 0) (void) strcpy(sockfile,s); else (void) strcpy(sockfile,"."); (void) strcat(sockfile,"/"); (void) strcat(sockfile,aliasfile); if ((fds=fopen(sockfile,"r"))==NULL) if (debugvar) fprintf(stddbg,"%s not found in current or home directory.\n", aliasfile); } if (fds != NULL) { GetLine (fds,buf); b = buf; /* 1st line of onhost.alias is [user [pass]] emulator */ if (0 != (s1 = NextItem(&b))) if (0 != (s2 = NextItem(&b))) if (0 != (s = NextItem(&b))) strcpy (em3278,s); else strcpy (em3278,s2); else strcpy (em3278,s1); else {} /* use default emulator */ fclose(fds); } if (debugvar) fprintf(stddbg,"getem3278 sets emulator name to %s\n",em3278); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> getinp reads a line from stdin. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int getinp() { int nc; register char *p; if ( gotint) { gotint = 0; return ( immedinp()); } if ( fgets(wrbuf,bfSIZE,stdin) == NULL) wrbuf[0] = '\0'; if ( (p=index(wrbuf,'\n')) != 0) nc = p+1-wrbuf; else { nc = -1; /* e.g., end of file or control-D */ printf("\n"); } if (debugvar) fprintf(stddbg,"getinp: line read from stdin, %d long\n",nc); return(nc); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> getinput reads a line in display or non-display mode * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int getinput() { int n; if (cmsstate & needNDread) { setecho(0); n = getinp(); setecho(1); } else n = getinp(); return(n); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> Getline is used to read the first line of onhost.profil * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int GetLine (fds,line) FILE *fds; char *line; { int n; char *p; int t; p = line; do { *p++ = t = fgetc (fds); } while ( (t!=EOF) && (t!='\n')); *--p = '\0'; n = p - line; if (t==EOF) return(EOF); else return(n); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> getsocknm makes name of file containing hostconnect socket * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void getsocknm() { char *p; if (sockpath[0] != '/') { if ( (p = getenv("HOME")) != 0) (void) strcpy(sockfile,p); else (void) strcpy(sockfile,"."); (void) strcat(sockfile,"/hostcon."); #ifdef SHORT sockpath[6] = '\0'; /* limit file name (hostcon.xxxxxx) to 14 chars */ #endif SHORT (void) strcat(sockfile,sockpath); } else (void) strcpy(sockfile,sockpath); if (debugvar) fprintf(stddbg,"getsocknm: %s contains hostconnect socket\n",sockfile); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> immedinp prompts for stdin line after user sent an interrupt * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int immedinp() { int n; printf(catgets(catd,ONHOST_ERR,OH_FULL_SCREEN, " (Press enter for full-screen or enter a host line.)\n")); if ( (n = getinp() ) < 1 ) return(n); if (n==1) /* full-screen request */ if (doem3278()) exit(1); /* problem */ return( n); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> initialize scans the opts and args * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void initialize() { register char *p; while ( (--argc > 0) && ((*++argv)[0] == '-') ) { p = *argv; while (p && *++p) { if (*p == '?') /* query usage of onhost */ usage(1); else if (*p == 'a') { /* alias option */ if (!--argc) /* request alias */ if (!OpenLastAlias("r")) { (void) fscanf(fds,"%s\n",sockpath); fclose(fds); fprintf(stderr,catgets(catd,ONHOST_ERR, OH_CURR_ALIAS,"current alias is %s\n"),sockpath); exit(0); } else { fprintf(stderr,catgets(catd,ONHOST_ERR, OH_NO_ALIAS,"no current alias\n")); exit(0); } else { /* set new alias */ (void) strcpy(sockpath,*++argv); ++newsockpath; } } else if (*p == 'b') /* bury all host output */ bury++; else if (*p == 'c') /* continue until end of file */ nonstop++; else if (*p == 'd') { /* debug option */ char c; debugvar = 1; c = *(p+1); if ( (c >= '0') && (c <= '9') ) { /* optional debug digit */ debugvar += c - '0'; p++; } } else if (*p == 'f') /* full-screen option */ fsmode++; else if (*p == 'i') /* ipl if cp read */ xpertuser = 0; else if (*p == 'l') /* loud display of all communication */ loud++; else if (*p == 'n') /* normal host line - no processing */ dtype = CScmsinp; else if (*p == 'o') /* one onhost command only */ nonstop = 0; else if (*p == 'p') /* prompt for input */ prompt++; else if (*p == 'q') /* quiet prompt option */ prompt = 0; else if (*p == 'r') /* repress return code display */ printcmsstatus = 0; else if (*p == 's') /* show return code option */ printcmsstatus++; else if (*p == 't') /* full-screen test option */ fstest++; else if (*p == 'x') /* expert cp user */ xpertuser++; else { fprintf(stderr,catgets(catd,ONHOST_ERR,OH_BAD_OPTION, "unrecognized option: %c\n"),*p); usage(0); } } } /* end while doing options */ if ( 1 == debugvar) { /* debug print on stderr */ stddbg = stderr; } else if (debugvar) { if ( (stddbg = fopen("onhost.debug","w")) == NULL) { stddbg = stderr; fprintf(stderr,catgets(catd,ONHOST_ERR,OH_CANT_DEBUG, "can not open onhost.debug\n")); } else (void) chmod("onhost.debug",0600); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> intrsig handles interrupt signals * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifdef SIGVEC /* select the enhanced signal capability if possible */ #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 { /* got a SIGINT */ gotsigint++; #ifdef LONGJMP /* use long jump to break read - bsd 4.2 only */ if (sigjmpok) /* if longjmp is required to break read, do it */ longjmp( (jmp_buf *) sigjmp, -1); #endif LONGJMP } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> NextItem is used to get tokens from a profile line * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * NextItem (line) char **line; { char *p, *start; int something; something = 0; p = start = *line; for (;;) { if (*p=='\0') break; if ((*p==' ') || (*p=='\t')) if (something) break; else start++; something = 1; p++; } if ( *p != '\0') { *p = '\0'; *line = ++p; } else *line = p; if (something) return(start); else return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> openhostsocket opens connection to hostconnect. If successful * * hostsocket is the fileno of connection, else -1 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void openhostsocket() { int af = AF_INET; u_short LocalPort; struct sockaddr_in sname; FILE *cmsfds; char *hs; if ( (cmsfds = fopen(sockfile,"r")) == 0) { if (strcmp(sockp0,sockpath)) hs = ""; else hs = " hostname"; fprintf(stderr,catgets(catd,ONHOST_ERR,OH_NOT_CONN, "The host with alias %s is probably not connected.\n"),sockpath); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_ENTER_CMD, "Enter hostconnect -a %s%s to make a connection\n or retry onhost with the alias of an active connection.\n"), sockpath,hs); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_ACTIVE_ALIAS, "(ls hostcon.* in your home directory to find an active alias.)\n")); return; } (void) fscanf(cmsfds,"%s %s %s\n", InetAddr, LPort, Auth); (void) fclose(cmsfds); if ( (hostsocket = socket(af,SOCK_STREAM,0)) < 0) { perror("socket call failed"); return; } LocalPort = (u_short) atoi(LPort); sname.sin_family = AF_INET; sname.sin_port = htons(LocalPort); sname.sin_addr.s_addr = inet_addr(InetAddr); if ( 1 < debugvar) fprintf(stddbg,"InetAddr =%s LocalPort =%d\n",InetAddr,LocalPort); if ( connect(hostsocket,(struct sockaddr*) &sname,sizeof(sname)) == 0 ) openmsg(); else { perror("connect call failed"); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_BACKGROUND, "\n Hostconnect should be running as a background process at %s.\n\t If it is not, remove hostcon.%s from your home directory and try again.\n\t Otherwise you can kill hostconnect (do not use kill -9) and try again.\n"), InetAddr,sockpath); (void) close(hostsocket); hostsocket = -1; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> OpenLastAlias is used to open file containing alias last used * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int OpenLastAlias(open_type) char *open_type; { char *s; if ( (s=getenv("HOME")) != 0) (void) strcpy(sockfile,s); else (void) strcpy(sockfile,"."); (void) strcat(sockfile,"/"); (void) strcat(sockfile,last_alias); if ((fds=fopen(sockfile,open_type))==NULL) return(-1); return(0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> openmsg sends the initial message to hostconnect which * * includes the current working directory. hostconnect expands * * the onhost special commands so that onhost.profil needs to * * be read once per connection, not once per command. But the * * cwd is needed so hostconnect can send it to FTP. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void openmsg() { int n, m; WRbuf[0] = CSopen; /* open and authenticate connection */ (void) strncpy(&WRbuf[1],Auth,6); WRbuf[7] = '\0'; n = 8; (void) dopath(&WRbuf[n+4]); /* store current working directory */ m = 1 + strlen(&WRbuf[n+4]); WRbuf[n++] = CSdata; WRbuf[n++] = m / 256; WRbuf[n++] = m % 256; WRbuf[n++] = CScwd; n += m; n = writehost(n); if (n < 0) exit(-1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> readhost reads from hostconnect, scans the data, loops until * * scanmsg sets cmsstate * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int readhost(i0) int i0; { int nr; while ( !cmsstate) { nr = 0; if ( i0) break; if (debugvar) fprintf(stddbg,"readhost: waiting for line from host\n"); #ifdef LONGJMP /* use long jump to break read - bsd 4.2 only */ if (setjmp(sigjmp) == 0) { sigjmpok = 1; if (debugvar) fprintf(stddbg,"readhost: long jump set\n"); nr = read(hostsocket,&rdbuf[i0],bfSIZE - i0); } else { nr = -1; /* return -1 as would the other systems */ if (debugvar) fprintf(stddbg,"readhost: long jump taken\n"); } sigjmpok = 0; #else !LONGJMP nr = read(hostsocket,&rdbuf[i0],bfSIZE - i0); #endif LONGJMP if (debugvar) fprintf(stddbg,"readhost: line read from host, %d long\n",nr); if (gotsigint) { gotsigint = 0; #ifndef SIGVEC /* enhanced signal not available, use signal */ signal(SIGINT, intrsig); /* tell system we still want signal */ #endif SIGVEC (void) fputs("\n",stdout); gotint++; cmsstate |= needCMScmd; return( i0); } if (nr <= 0) { if (debugvar) fprintf(stddbg,"onhost lost connection nr=%d i0=%d errno=%d\n", nr,i0,errno); exit(3); } nr += i0; i0 = scanmsg(rdbuf,nr); if (debugvar) fprintf(stddbg,"readhost: state of host is %d\n",cmsstate); } /* end while (!cmsstate) */ return ( i0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> scanmsg scans data from hostconnect for hostconnect messages. * * Output from the host is sent to stdout or buried. * * Unprocessed characters are shifted to front of buffer. * * Error messages from host go to stderr. * * (Messages may not be complete this time through code.) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int scanmsg(rbuf,nr0) char *rbuf; int nr0; { char *p, *q, *r, *s, *q1; int nr, k; nr = nr0; p = rbuf; if (debugvar) fprintf(stddbg,"scanmsg: looking at data, %d long (ndata: %d)\n", nr0,ndata); while ( nr) { if (ndata == 0) switch( byte(*p) ) { case CSstate: if (nr < 2) goto out; p++; cmsstate = *p++; nr -= 2; break; case CSdata: if (nr < 4) goto out; p++; ndata = byte(*p++); ndata = 256 * ndata + byte(*p++); datatype = byte(*p++); if ( datatype == CSerrmsg) fprintf(stderr,"onhost: "); nr -= 4; if ( 1 < debugvar) fprintf(stddbg,"scanmsg: ndata=%d type=%d\n",ndata,datatype); break; default: printf(catgets(catd,ONHOST_ERR,OH_OUT_PHASE, "scanmsg: out of phase nr=%d c=0x%x\n"),nr,*p); exit(-1); } /* end if (!ndata) */ if ( ndata) { if ( nr < ndata) k = nr; else k = ndata; if ( datatype == CSerrmsg) { (void) fwrite(p,1,k,stderr); } else { /* Scan data for the onhost end of command flag line and, if found, * extract the host return code. Write the characters up to the * flag line, set print suppression if required, and write remaining * complete lines. * * This code assumes that the flag line is not split across * a CSdata block although the block may be split across TCP packets. * * p points to the beginning of the output characters * q points to the beginning of a line; r points to the end * q1 points to first flag line found */ r = q = p; s = k + r; q1 = NULL; while ( r < s) { while ( ( q < s) && ( *q == '\n')) q++; r = q; while ( ( r < s) && ( *r != '\n')) r++; if ( q1) (void) checkline(q,r); else q1 = checkline(q,r); q = r; } if ( nr < ndata) { s = q; k -= ( r - s); } if ( q1) q = q1; if ( ( outstream) && ( p != q)) if ( !bury) (void) fwrite(p,1,(q-p),outstream); if ( ( gotcmsretcode) && ( !loud)) outstream = NULL; if ( ( outstream) && ( q != s)) if ( !bury) (void) fwrite(p,1,(s-q),outstream); } nr -= k; ndata -= k; p += k; if ( ndata) goto out; } } /* move remaining nr characters to front of buffer */ out: for (k=0; k setecho turns local echo on and off to protect password entry * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void setecho(echoon) int echoon; { #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 } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> usage prints a bit of information about the onhost options * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void usage(zip) int zip; { fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP1, "(%s) usage: "),version); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP2, "%s [-?abcd[n]lnpqst] [alias] [command]\n"),iam); if (zip == 0) exit(1); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP3, "where \ta \t= use alias if present or display current alias\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP4, "\tb \t= bury all host output\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP5, "\tc \t= continue after one onhost command until input end of file\n\t or interrupt (see note 1) ends onhost\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP6, "\td, d0 \t= debug output to stddbg\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP7, "\td1 \t= debug output to onhost.debug\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP8, "\tl \t= loud display of all host output\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP9, "\tn \t= normal line for host, no special treatment (see note 2)\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP10, "\tp \t= prompt for host input - prompt will show\n\t\t>> for onhost command, > for normal line\n\t\t if no prompt appears, a line can be forced (see note 1)\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP11, "\tq \t= quiet host input prompt\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP12, "\ts \t= show host return code\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP13, "\tt \t= test mode for full-screen emulator\n")); getem3278(); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP14, "will send command to the host identified by alias or to the\n\tlast used host. If no command is present, then a full-screen\n\tsession is started using the IBM-3278-2 emulator named %s\n"),em3278); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP15, "note 1: an interrupt (ctrl-c) will terminate onhost if onhost is waiting\n\tfor your input, otherwise onhost will force a line to the host\n")); fprintf(stderr,catgets(catd,ONHOST_ERR,OH_HELP16, "note 2: a normal line of hat(^) followed by a character produces a\n\tpf1..pf12(1234567890-=), pa1..pa2(ab), enter(e), or clear(z) at the host\n")); exit(1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> writehost writes a buffer load to hostconnect * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int writehost(n) int n; { int m; if ( ( m = write(hostsocket,WRbuf,n)) <= 0 ) { if ( 1 < debugvar) fprintf(stddbg,"writehost: m=%d, errno= %d\n",m,errno); return(-1); } return(m); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ====> main opens a connection to hostconnect, runs the connection * * between host and user, and then exits with a return code. * * * * Characters are sent to hostconnect in response to status data * * about the host. If the command flag is on, then hostconnect * * will process the next group of characters using onhost.profil * * to generate data for the host. Otherwise, the next group of * * characters will be passed straight to the host. * * * * When the host status shows that input is required, onhost will * * try to get some characters to send. Otherwise, onhost will * * listen to hostconnect for any host output or status. * * * * Either read is broken by a user interrupt. Termination of the * * local read terminates onhost. Termination of the hostconnect * * read produces a prompt for immediate input. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int main(argc0,argv0) int argc0; char *argv0[]; { int i0 = 0; int n, triedpwd; /* set the locale to the default */ setlocale(LC_ALL, ""); /* open the message catalog */ catd = catopen("onhost.cat",NL_CAT_LOCALE); gotcmsretcode = triedpwd = 0; argv = argv0; iam = argv0[0]; argc = argc0; initialize(); if (debugvar) fprintf(stddbg,"%s (onhost version %s) completed initialize()\n", iam,version); if (!newsockpath) /* get the current alias */ if (!OpenLastAlias("r")) { (void) fscanf(fds,"%s\n",sockpath); fclose(fds); } else (void) strcpy (sockpath,sockp0); /* no current alias, use default */ getsocknm(); hostsocket = -1; openhostsocket(); /* check this alias */ if (hostsocket < 0) { /* no good */ if (debugvar) fprintf(stddbg,"main: can't connect to hostconnect\n"); exit(2); } if (debugvar) fprintf(stddbg,"main: connected to hostconnect\n"); if (newsockpath) if (!OpenLastAlias("w")) { /* save alias */ (void) fprintf(fds,"%s\n",sockpath); fclose(fds); } else /* can't save current alias - no big deal (system told user) */ if (debugvar) fprintf(stddbg,"main: current alias not saved\n"); if ( fsmode || ( argc == 0)) /* no command means full-screen */ if (doem3278()) exit(1); /* problem */ argp = *argv; outstream = stdout; gotsigint = 0; #ifdef SIGVEC /* select the enhanced signal capability if possible */ newvec.sv_onstack = 0; /* signal.h may define sv_onstack to sv_flags */ #endif SIGVEC #ifdef LONGJMP sigjmpok = 0; #else !LONGJMP #ifdef BSD42LIB /* BSD system */ newvec.sv_flags |= SV_INTERRUPT; /* tell BSD 4.3 to break slow read */ #endif BSD42LIB #endif LONGJMP #ifdef SIGVEC /* select the enhanced signal capability if possible */ newvec.sv_mask = 0; newvec.sv_handler = intrsig; sigvec(SIGINT, &newvec, &oldvec); #else !SIGVEC /* otherwise use signal */ signal(SIGINT, intrsig); #endif SIGVEC WRbuf[0] = CSgetstate; n = writehost(1); if (debugvar) fprintf(stddbg,"main: requesting host state from hostconnect\n"); /* This is the main loop of onhost */ while ( 0 <= n) { cmsstate = n = 0; i0 = readhost(i0); /* read hostconnect until cmsstate <> 0 */ if (printcmsstatus) if (gotcmsretcode) printf("host rc=%d\n",cmsretcode); if (cmsstate & FullScreen ) cmsstate &= ~(needCPcmd); if (cmsstate & lostconnection ) break; if ( gotcmsretcode && nonstop) { gotcmsretcode = 0; dtype = CScmscmd; } if ( cmsstate & ( needCMScmd | needCMSinp)) { if ( gotcmsretcode) break; outstream = stdout; triedpwd = 0; } if ( cmsstate & needCPcmd) { if (triedpwd) { if (xpertuser) { /* give expert more than one CP read */ if ( loud || prompt) printf("CP>"); n = getinput(); } else { printf(catgets(catd,ONHOST_ERR,OH_CP_READ, "CP read without expert option - onhost requesting ipl\n")); WRbuf[0] = CSipl; if ( 0 < (n = writehost(1)) ) n = 0; outstream = stdout; /* NULL to bury ipl output, stdout to show */ } } else { /* treat first CP read as a password request */ /* triedpwd++; suspend for the nonce so *all* CP reads are okay */ if ( loud || prompt) printf("CP>"); n = getinput(); if (n == 1) n = strlen(strcpy(wrbuf,"b")); /* feed begin (also dummy pwd) */ } } if (cmsstate & (needCMScmd | needCMSinp)) { if ( loud || prompt) { printf(">"); if (dtype == CScmscmd) printf(">"); } if ( (n = getcmd(wrbuf,bfSIZE) ) < 0) /* use command line first */ n = getinput(); else if ( loud || prompt) printf(wrbuf); gotint = 0; } if (debugvar) fprintf(stddbg,"main: line for host, %d long\n",n); if (0 < n) { wrbuf[n] = '\0'; if (debugvar) { fprintf(stddbg,"main: line sent to host, %d long: %s\n", n,wrbuf); } if (loud && !(cmsstate & needNDread)) printf(wrbuf); WRbuf[0] = CSdata; /* these four bytes prefix wrbuf */ WRbuf[1] = n / 256; WRbuf[2] = n % 256; WRbuf[3] = dtype; n += CShlen; n = writehost(n); dtype = CScmsinp; } } /* end while */ if (debugvar) { fprintf(stddbg,"main: exit with n= %d and cmsretcode= %d\n", n,cmsretcode); if (4 < n) fprintf(stddbg,"main: string (less 4 byte header) = %s\n", wrbuf[0]); } #ifdef AIXV3 /* close the message catalog */ catclose(catd); #endif AIXV3 if (gotcmsretcode) return(cmsretcode); else return(-1); }