home *** CD-ROM | disk | FTP | other *** search
- /* 00010000
- * Name: GOPCLISX REXX 00020000
- * CMS Gopher client TCP/IP (sockets; "sox") function 00030000
- * Author: Rick Troth, Rice University, Information Systems 00040000
- * Date: 1992-Dec-23 00050000
- * 00060000
- * Input: one or more gopher menu lines 00070000
- * Output 0: zero or more blocks of raw (may be ASCII) data 00080000
- * Output 1: status messages and/or error messages 00090000
- * 00100000
- * Note: input is "plain text" (EBCDIC), while output 00110000
- * may be anything. If output is "plain text" (ASCII), 00120000
- * the following stage must handle translation. 00130000
- */ 00140000
- 00150000
- /* 00160000
- * Copyright 1992 Richard M. Troth. This software was developed 00170000
- * with resources provided by Rice University and is intended 00180000
- * to serve Rice's user community. Rice has benefitted greatly 00190000
- * from the free distribution of software, therefore distribution 00200000
- * of unmodified copies of this material is not restricted. 00210000
- * You may change your own copy as needed. Neither Rice 00220000
- * University nor any of its employees or students shall be held 00230000
- * liable for damages resulting from the use of this software. 00240000
- */ 00250000
- 00260000
- Trace "OFF" 00270000
- 00280000
- /* sync with input so that 'CALLPIPE COMMAND' will work */ 00290000
- 'PEEKTO' 00300000
- 00310000
- 'CALLPIPE COMMAND GLOBALV SELECT GOPHER GET GOPHER' 00320000
- If gopher = "" Then gopher = "Gopher" 00330000
- quit = 0 00340000
- 00350000
- Parse Arg . '(' opts ')' . 00360000
- 00370000
- trans = 0 00380000
- Do While opts ^= "" 00390000
- Parse Var opts op opts 00400000
- Upper op 00410000
- Select /* op */ 00420000
- When Abbrev("TRANSLATE",op,4) Then trans = 1 00430000
- When Abbrev("NOTRANSLATE",op,6) Then trans = 0 00440000
- Otherwise Address "COMMAND" 'XMITMSG 3 OP (ERRMSG' 00450000
- End /* Select op */ 00460000
- End /* Do While */ 00470000
- 00480000
- If trans Then crlf = '0D25'x 00490000
- Else crlf = '0D0A'x 00500000
- 00510000
- /* 00520000
- * Initialize RXSOCKET 00530000
- */ 00540000
- maxdesc = Socket('Initialize', gopher) 00550000
- If maxdesc = "-1" Then Do 00560000
- If errno ^= "ESUBTASKALREADYACTIVE" Then Do 00570000
- /* Call STATUS tcperror() */ 00580000
- Exit -1 00590000
- End /* If .. Do */ 00600000
- rc = Socket('Terminate') 00610000
- maxdesc = Socket('Initialize', gopher) 00620000
- If maxdesc = "-1" Then Do 00630000
- Call STATUS tcperror() 00640000
- Exit -1 00650000
- End /* If .. Do */ 00660000
- End /* If .. Do */ 00670000
- 00680000
- /* L O O P */ 00690000
- 00700000
- Do Forever 00710000
- 00720000
- 'PEEKTO ITEM' 00730000
- If rc ^= 0 Then Leave 00740000
- 00750000
- Parse Var item 1 type 2 name '05'x path '05'x host , 00760000
- '05'x port '05'x xtra 00770000
- port = Strip(port) /* for robustness */ 00780000
- If type = '7' Then path = path || '05'x || xtra 00790000
- 00800000
- /* Call STATUS "Connecting ... press ENTER twice to abort" */ 00810000
- /* Call STATUS "Connecting to" host "port" port */ 00820000
- Call STATUS 22 '"' || host || '"' '"' || port || '"' 00830000
- 00840000
- /* 00850000
- * Request a new socket descriptor (TCP protocol) 00860000
- */ 00870000
- socket = Socket('Socket', 'AF_INET', 'Sock_Stream') 00880000
- If socket = "-1" Then Do 00890000
- Call STATUS tcperror() 00900000
- Exit -1 00910000
- End /* If .. Do */ 00920000
- 00930000
- If trans Then Do 00940000
- /* 00950000
- * Enable ASCII<->EBCDIC Translation Option 00960000
- */ 00970000
- rc = Socket('SetSockOpt', socket, 'SOL_SOCKET', 'SO_EBCDIC', 1) 00980000
- If rc = "-1" Then Do 00990000
- Call STATUS tcperror() 01000000
- Exit -1 01010000
- End /* If .. Do */ 01020000
- End /* If .. Do */ 01030000
- 01040000
- /* 01050000
- * Connect to the server 01060000
- */ 01070000
- Parse Var host h1 '.' h2 '.' h3 '.' h4 '.' . 01080000
- If Datatype(h1,'N') &, 01090000
- Datatype(h2,'N') &, 01100000
- Datatype(h3,'N') &, 01110000
- Datatype(h4,'N') Then 01120000
- hisaddr = d2c(h1) || d2c(h2) || d2c(h3) || d2c(h4) 01130000
- Else Do 01140000
- hisaddr = Socket('GetHostByName', host) 01150000
- If hisaddr = "-1" Then Do 01160000
- Call STATUS tcperror() 01170000
- Exit -1 01180000
- End /* If .. Do */ 01190000
- End /* Else Do */ 01200000
- 01210000
- /* Parse Var hisaddr h1 +1 h2 +1 h3 +1 h4 +1 . */ 01220000
- 01230000
- name = AF_INET || Htons(port) || hisaddr 01240000
- 01250000
- /* 01260000
- * Set this socket to non-blocking mode 01270000
- */ 01280000
- rc = Socket('Ioctl', socket, 'FIONBIO', 1) 01290000
- If rc="-1" Then Do 01300000
- Call STATUS tcperror() 01310000
- Exit -1 01320000
- End /* If .. Do */ 01330000
- 01340000
- /* 01350000
- * Connect to the host 01360000
- */ 01370000
- rc = Socket('Connect', socket, name) 01380000
- If rc = "-1" Then , 01390000
- If errno ^= "EINPROGRESS" Then Do 01400000
- Call STATUS tcperror() 01410000
- If errno = "ECONNREFUSED" Then , 01420000
- Call STATUS 23 '"' || host || '"' '"' || port || '"' 01430000
- Exit -1 01440000
- End /* If .. Do */ 01450000
- 01460000
- rc = FD_ZERO('readmask') 01470000
- rc = FD_ZERO('writemask') 01480000
- rc = FD_SET(socket,'writemask') 01490000
- rc = FD_SET('0', 'readmask') 01500000
- 01510000
- rc = Socket('Select', socket+1, 'readmask', 'writemask', 0, 20) 01520000
- If rc="-1" Then Do 01530000
- Call STATUS tcperror() 01540000
- Exit -1 01550000
- End /* If .. Do */ 01560000
- 01570000
- If FD_ISSET('0', 'readmask')<>0 Then Do 01580000
- rc = Socket('Close', socket) 01590000
- /* Call STATUS "Connection canceled by user request" */ 01600000
- Call STATUS 28 01610000
- Exit -1 01620000
- End 01630000
- 01640000
- If FD_ISSET(socket, 'writemask')=0 Then Do 01650000
- rc = Socket('Close', socket) 01660000
- /* Call STATUS "Connection canceled by TIMEOUT" */ 01670000
- Call STATUS 29 01680000
- Exit -1 01690000
- end 01700000
- 01710000
- /* Return to standard mode 01720000
- rc = Socket('Ioctl', socket, 'FIONBIO', 0) 01730000
- */ 01740000
- 01750000
- /* TRANSlate option will affect both writing to, as well as * 01760000
- * reading from, the socket. So if the socket is set for * 01770000
- * TRANSLATE, then we need not translate the path from EBCDIC * 01780000
- * to ASCII. But if not, then we must do so as follows: */01790000
- If ^trans Then 01800000
- 'CALLPIPE VAR PATH | TCPE2A' gopher '| VAR PATH' 01810000
- 01820000
- /* 01830000
- * Send the "query" to the server 01840000
- */ 01850000
- bytes_out = Socket('Write', socket, path || crlf) 01860000
- If bytes_out = "-1" Then Do 01870000
- If errno = 'EPIPE' Then , 01880000
- 'OUTPUT' "ECONNREFUSED" 01890000
- If errno = 'EPIPE' Then , 01900000
- Call STATUS 23 '"' || host || '"' '"' || port || '"' 01910000
- Else Call STATUS tcperror() 01920000
- Exit -1 01930000
- End /* If .. Do */ 01940000
- 01950000
- /* Call STATUS "Reading ... press ENTER twice to abort" */ 01960000
- /* Call STATUS "Reading ... " */ 01970000
- /* Call STATUS 24 */ 01980000
- 01990000
- totbytes = 0 02000000
- prevtot = 0 02010000
- /* 02020000
- * Loop, reading response and sending to the next pipeline stage 02030000
- */ 02040000
- Do Forever 02050000
- /* Set up to trap console ENTER key */ 02060000
- rc = FD_ZERO('readmask') 02070000
- rc = FD_SET('0','readmask') 02080000
- rc = FD_SET(socket,'readmask') 02090000
- 02100000
- /* Wait for something to happen */ 02110000
- rc = Socket('Select',socket+1,'readmask',0,0) 02120000
- /* If console input, clear 'socket' and return */ 02130000
- If FD_ISSET('0','readmask')<>0 Then Do 02140000
- /* Call STATUS "Request ABORTED" */ 02150000
- Call STATUS 27 02160000
- rc = Socket('Close', socket) 02170000
- Leave 02180000
- End 02190000
- 02200000
- bytes_in = Socket('Read', socket, 'pack') 02210000
- If bytes_in = "-1" Then 02220000
- Call STATUS tcperror() 02230000
- If bytes_in < 1 Then Leave 02240000
- 02250000
- totbytes = totbytes + bytes_in 02260000
- If prevtot/totbytes < 0.9 Then /* adjust the 0.9 factor to taste */ 02270000
- Do 02280000
- Call STATUS 26 '"' || totbytes || '"' 02290000
- prevtot = totbytes 02300000
- End 02310000
- 'OUTPUT' pack 02320000
- If rc ^= 0 Then Leave 02330000
- 02340000
- End /* Do Forever */ 02350000
- 02360000
- If rc ^= 0 Then Leave 02370000
- 02380000
- /* 02390000
- * All done, relinquish our socket descriptor 02400000
- */ 02410000
- rc = Socket('Close', socket) 02420000
- If rc = "-1" Then Do 02430000
- Call STATUS tcperror() 02440000
- Leave 02450000
- End /* If .. Do */ 02460000
- 02470000
- 'READTO' 02480000
- 02490000
- End /* Do Forever */ 02500000
- 02510000
- /* 02520000
- * Tell RXSOCKET that we are done with this IUCV path 02530000
- */ 02540000
- rc = Socket('Terminate') 02550000
- If rc = "-1" Then Do 02560000
- Call STATUS tcperror() 02570000
- Exit -1 02580000
- End 02590000
- 02600000
- /* an empty line as last in status stream indicates success */ 02610000
- /* Call STATUS " " */ 02620000
- 02630000
- Exit 02640000
- 02650000
- 02660000
- 02670000
- /* -------------------------------------------------------------- STATUS02680000
- * Write "status messages" to the secondary stream, if connected. 02690000
- * This routine saves & restores the current stream selection. 02700000
- * (though there are presently no other streams used besides 1 and 0) 02710000
- */ 02720000
- STATUS: Procedure 02730000
- Parse Arg string 02740000
- 02750000
- /* note the current stream (should be zero) */ 02760000
- 'STREAMNO OUTPUT' 02770000
- If rc < 0 Then Return 02780000
- stream = rc 02790000
- 02800000
- /* select secondary stream and output the string */ 02810000
- 'SELECT OUTPUT 1' 02820000
- If rc ^= 0 Then Return 02830000
- If Datatype(Word(string,1),'N') Then 02840000
- 'CALLPIPE COMMAND XMITMSG' string '(APPLID GOP CALLER TCP ERRMSG | *:' 02850000
- Else 'OUTPUT' string 02860000
- 'SELECT OUTPUT' stream 02870000
- 02880000
- Return 02890000
- 02900000
-