/********************************************************************/ /* */ /* QSH_CLIENT : QSHELL セッション・クライアント */ /* */ /* [ 原典 ] QZSHSH IN IBM INFOMATION CENTER */ /* */ /* [ 記述 ] このプラグラムは SBMJOB された QSH_SERVER の */ /* クライアントとして最初は動作します。 */ /* 次に QSH_SERVER でユーザー認証を受けると */ /* QSH_SERVER は QZSHSH を SBMJOB します。 */ /* その後はこのプログラムは QZSHSH と対話して */ /* QZSHSH に SHELL コマンドを実行させて */ /* その結果を受け取ります。 */ /* */ /* [ パラメータ ] 1. Host running the qsh server (either host */ /* name or IP address) */ /* */ /* [ オプション ] 1. -N to force prompt for user name and */ /* password. */ /* 2. -P to specify port of qsh server. */ /* */ /* [ 注記 ] 1. IBM インフォーメーション・センターに公開されて */ /* いるサンプルは ASCII 用ですが、このプログラムは */ /* System i 上でコンパイル & 実行できるように */ /* 書き変えています。 */ /* 2. IBM インフォーメーション・センターに公開されて */ /* いるサンプルは */ /* extern int optind; */ /* extern char* optarg; */ /* が漏れているためにコンパイルはエラーとなりますが */ /* このプログラムでは補正しています。 */ /* 3. コンパイルは CRTBNDC でコンパイルしてください。 */ /* 4. 実行は CALL QSH_CLIENT PATM('-N' '-P 6042 ' 'HOST')*/ /* の形式で HOST には SYSTEM 名を指定してください。 */ /* */ /********************************************************************/ /* Remove the comments from the following line to use iconv() */ #define USE_ICONV 1 #include #include #include #include /* socket(), bind(), ... */ #include /* sockaddr_in */ #include /* inet_addr() */ #include /* ioctl() */ #include /* close(), read(), write() */ #include #include /* gethostbyname() */ #include /* getpwuid() */ #include /* sigaction() */ #include /* select() */ #include #ifdef AIX #include /* select() */ #include /* bzero() for FD_ZERO */ #endif #include /* iconv() */ /*************************************************************/ /* 固 定 定 数 */ /*************************************************************/ #define TRUE 0 #define FALSE -1 #define QSH_PORT 6042 #define DEFAULT_BUF 4096 typedef unsigned char unchar; /*************************************************************/ /* グ ロ ー バ ル 変 数 */ /*************************************************************/ char *sysname; /* Long host name of server system */ iconv_t ecd; /* Conversion descriptor for ASCII to EBCDIC */ iconv_t acd; /* Conversion descriptor for EBCDIC to ASCII */ /*************************************************************/ /* 内 部 使 用  関  数 */ /*************************************************************/ int GetPassword(char *, char *, char *); void MySignalHandler(int); void usage(void); /********************************************************************/ /* m a i n --- main module of this pgm */ /* */ /* 1. ACCLOG */ /* */ /********************************************************************/ int main(int argc, char *argv[]){ struct sigaction sigact; /* Signal action */ int c; /* Option Letter */ int nflag=0; /* True when -n option is specified */ int port=QSH_PORT; /* Port to connect to on server */ int sd; /* Sockwet to server */ fd_set read_set; /* For select() */ int rc; /* Return code */ struct sockaddr_in svr_addr;/* AF_INET socket address */ long ip_addr; /* IP address of server system */ struct in_addr host_addr; /* Host address for gethostbyaddr() */ char* hostname; /* Short host name of server system */ size_t len; /* Length of input string */ char* ascii_user; /* Username in ASCII */ char* ebcdic_user; /* USername in EBCDIC */ char* ascii_pwd; /* Password in ASCII */ char* ebcdic_pwd; /* Password in EBCDIC */ struct hostent *host_p; /* Pointer to hostent structure returned by gethostbyname() */ char* ascii_buf; /* Buffer of ASCII text */ char* ebcdic_buf; /* Buffer of EBCDIC text */ int buf_size; /* Amount of data read from server */ extern int optind; extern char* optarg; /*************************************************************/ /* Initialization */ /*************************************************************/ printf("**** QSH_CLIENT: SHELL クライアントの開始 ****\n"); /* Set up signal handler for SIGINT. the signal is sent to the process when the user presses c. */ sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigact.sa_handler = MySignalHandler; if(sigaction(SIGINT, &sigact, NULL) != 0){ perror("QSH_CLIENT:sogaction(SIGINT) faied."); exit(1); } /*************************************************************/ /* Process the input parameters */ /*************************************************************/ if(argc < 2){ usage(); } /* Process the options */ while((c = getopt(argc, argv, "HNP:")) != EOF){/* while */ switch(c){/*switch*/ case 'N': nflag = 1; break; case 'P': port = atoi(optarg); break; case 'H': default: usage(); break; }/*switch*/ }/* while */ /* Convert a dotted decimal address to a 32-bit IP address */ hostname = argv[optind]; ip_addr = inet_addr(hostname); /* When inet_addr() returns -1 assume the user specified a host name */ if(ip_addr == -1){/* HOSTBYNAME */ /* Try to find the host by name */ host_p = gethostbyname(hostname); if(host_p){/* HOST_P */ memcpy(&ip_addr, host_p->h_addr, host_p->h_length); sysname = host_p->h_name; }/* HOST_P */ else{/* ERR */ fprintf(stderr, "QSH_CLIENT: Could not find host %s\n", hostname); exit(1); }/* ERR */ }/* HOSTBYNAME */ /* The user specified a IP address */ else{/* HOSTBYADDR */ /* Try to find the host by address */ host_addr.s_addr = ip_addr; host_p = gethostbyaddr((char*)&host_addr.s_addr, sizeof(host_addr), AF_INET); if(host_p){/* HOST_P */ sysname = host_p->h_name; }/* HOST_P */ else{/* ERR */ fprintf(stderr, "QSH_CLIENT:Could not find host %s\n", hostname); exit(1); }/* ERR */ }/* HOSTBYADDR */ /*************************************************************/ /* Connect to the QSH_SERVER on the specified system */ /*************************************************************/ /* Create Socket */ if((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0){ perror("QSH_CLIENT:socket() failed."); exit(1); } /* Connect to the QSH_SERVER on specified system */ memset(&svr_addr, '\0', sizeof(svr_addr)); svr_addr.sin_family = AF_INET; svr_addr.sin_port = htons(port); svr_addr.sin_addr.s_addr = ip_addr; if(connect(sd, (struct sockaddr *)&svr_addr, sizeof(svr_addr)) != 0){ perror("QSH_CLIENT:connect() failed."); exit(1); } printf("QSH_CLIENT: connect OK to QSH_SERVER.\n"); /*************************************************************/ /* Send the user name and password to the server */ /*************************************************************/ printf("QSH_CLIENT: ユーザー名とパスワードの送信 \n"); /* Allocate buffers for translating input and output */ ascii_buf = (char*)malloc(DEFAULT_BUF); memset(ascii_buf, '\0', DEFAULT_BUF); ebcdic_buf = (char*)malloc(DEFAULT_BUF); memset(ebcdic_buf, '\0', DEFAULT_BUF); ascii_user = ascii_buf; ascii_pwd = ascii_buf + 100; ebcdic_user = ebcdic_buf; ebcdic_pwd = ebcdic_buf + 100; /* Prompt the user for the user name and password */ if(nflag){ printf(" ユーザー名を入れてください。 \n"); gets(ascii_user); printf(" パスワードを入れてください。 \n"); gets(ascii_pwd); printf(" \n"); } /* Convert the user name and password to EBCDIC */ strcpy(ebcdic_user, ascii_user); strcpy(ebcdic_pwd, ascii_pwd); /* Send the user name and password to the QSH_SEEVER. Note the the user name and password are sent as plain text. */ if((rc = write(sd, (void*)ebcdic_user, strlen(ebcdic_user)+1)) < 0){ perror("QSH_CLIENT:write() fained sending username\n"); close(sd); exit(1); } if((rc = write(sd, (void*)ebcdic_pwd, strlen(ebcdic_pwd)+1)) < 0){ perror("QSH_CLIENT:write() fained sending password\n"); close(sd); exit(1); } printf("QSH_CLIENT: Started qsh session on %s\n", sysname); /********************************************************************/ /* Process input and output between the user and the remote shell */ /********************************************************************/ printf(" QSHELL コマンド入力 \n"); /* Loopp forever */ while(1){/*while*/ /* Select on stdin and the socket connected to the remote shell */ FD_ZERO(&read_set); FD_SET(0, &read_set); FD_SET(sd, &read_set); rc = select(sd+1, &read_set, NULL, NULL, NULL); if((rc < 0) && (errno != EINTR)){ perror("QSH_CLIENT: select() failed."); exit(1); } if(rc == 0) continue; /* Process data enterd by the terminal user */ if(FD_ISSET(0, &read_set)){/* 端末からの読み取り */ /* Read the data from the terminal */ printf("Entry SHELL Cmd (END=QUIT)>\n"); gets(ascii_buf); if(strncmp(ascii_buf, "QUIT", 4) == 0) break; /* Convert the string to EBCIDC */ len = strlen(ascii_buf); memcpy(ebcdic_buf, ascii_buf, len); /* Put a newline on the end of the string */ *(ebcdic_buf+len) = 0x25; /* Send the data to the remote shell */ if(write(sd, ebcdic_buf, len+1) < 0){/* ERR */ perror("QSH_CLIENT:write() failed sending input."); }/* ERR */ }/* 端末からの読み取り */ /* Process data from the remote shell */ if(FD_ISSET(sd, &read_set)){/* リモート SHELL */ /* Read the data from the remote shell */ buf_size = read(sd, ebcdic_buf, DEFAULT_BUF-1); /* There was a failure reading from the remote shell */ if(buf_size < 0){/* ERR */ perror("\nQSH_CLIENT: error reading from remote shell"); printf("%s のセッションが終了した。 \n", sysname); exit(0); }/* ERR */ /* The remote shell process ended */ else if(buf_size == 0){/* ゼロ */ printf("%s のセッションが終了した。 \n", sysname); exit(0); }/* ゼロ */ /* Process the data from the remote shell */ else{/* 正 */ /* Convert to ASCII */ *(ebcdic_buf+buf_size) = '\0'; if((int)buf_size >= 0){/* サイズ */ memcpy(ascii_buf, ebcdic_buf, (int)buf_size); /* write(1, ascii_buf, buf_size); 標準出力 */ printf("%s\n", ascii_buf); }/* サイズ */ }/* 正 */ }/* リモート SHELL */ }/*while*/ exit(0); } /*************************************************************/ int GetPassword(char *sysname, char *logname, char *password) /*************************************************************/ { #define BUFSIZE 256 char buffer[BUFSIZE]; char *systag, *logtag; int logflag = 0, pwdflag = 0; FILE *netrc; struct passwd *pwdbuf; int rc = 0; /* Get user's home directory */ pwdbuf = getpwuid(getuid()); /* Does user have a netrc file in their home directory ? */ strcat(strcpy(buffer, pwdbuf->pw_dir), "/.netrc"); if((netrc = fopen(buffer, "r")) == NULL){ perror("QSH_CLIENT: open() failed."); return FALSE; } while(!(logflag || pwdflag) && fgets(buffer, BUFSIZE, netrc)!= NULL){/*while*/ /* Find system name in =/.netrc */ if((systag = (char*)strtok(buffer, " \t\n")) != NULL && !strncmp(systag, "machine", 7)){ systag = (char*)strtok(NULL, " \t\n"); if(!strcmp(systag, sysname)){ /* Find login and password */ while(!logtag || !pwdflag){/*while-2*/ if((logtag = (char*)strtok(NULL, " \t\n")) == NULL){ while(!logtag){/*while-3*/ fgets(buffer, BUFSIZE, netrc); logtag = (char*)strtok(buffer, " \t\n"); }/*while-3*/ } if(!strncmp(logtag, "login", 5)){/* not login */ strcpy(logname, strtok(NULL, " \n\t")); ++ logflag; }/* not login */ else if(!strncmp(logtag, "password", 8)){ strcpy(password, strtok(NULL, " \n\t")); ++ pwdflag; } else ; }/*while-2*/ } } }/*while*/ fclose(netrc); /* Login and password not found for system */ if(!(logflag && pwdflag)){ rc = FALSE; } return rc; } /******************************/ void MySignalHandler(int signo) /******************************/ { switch(signo){/*switch*/ case SIGINT: printf("\nQSG_CLIENT: c=ends this program\n"); printf("Ended qsh session on %s\n", sysname); exit(0); break; default: exit(1); break; }/*switch*/ return; } /***************/ void usage(void) /***************/ { fprintf(stderr, " 呼び出しは CALL QSH_CLIENT PARM('-N' '-P 6042' HOSTNAME\n"); exit(-1); }