home *** CD-ROM | disk | FTP | other *** search
- /* FINGERD.CMD ver 1.0 (8/14/1993)
- REXX Program to Service FINGER Requests (FINGER Server)
- by R L Samuell (samuell@cis.uab.edu)
-
- NOTE: -- FINGERD.CMD requires OS/2 2.0 GA or later, TCPIP 1.2.1
- with April 1993 CSDs or later, and the latest version of
- the RxSock IBM EWS Freeware package.
-
- NOTICE -- COPYRIGHT 1993 by Robert L. Samuell, III
- -- All Rights Reserved. Publication of this document in
- whole or in part in any form, electronic or printed,
- in any forum, public or private, is expressly prohibited
- without the explicit permission of the author.
- -- The latest version of documentation for FINGERD may
- obtained by Anonymous FTP at 138.26.65.78.
-
- LICENSE -- TERMS and CONDITIONS
- -- You are not allowed to modify any portion of this program
- other than the values of variables defined in the section
- entitled 'Parameterize.'
- -- This program is available for you to use free of charge.
- -- Any distribution of this program must include both program
- and documentation, in the latest versions, unchanged.
- -- Commercial sale or re-sale of this program is allowed only
- with the approval of the author.
- -- DISCLAIMER: No warranties or guarantees are expressed or
- implied. And the author assumes no liability for ANY damage
- or loss whatsoever arising from the use of this program.
- Furthermore, the author is under no obligation to provide
- support of any kind. This disclaimer applies to any support
- that is provided.
- -- ACCEPTANCE: By using or distributing this program, you
- agree to these terms.
- */
-
- PARSE ARG switches
-
- SAY 'FINGERD: A FINGER Server for OS/2'
- SAY 'NOTICE -- COPYRIGHT 1993 by Robert L. Samuell, III'
-
- /* Parameterize -- ATTENTION:
- Only values of the following code variables may be modified by the user. */
-
- fpath = 'C:\FINGER\'
- password = '' /* NOTE: must be 0 or 6 characters & alphas must be upper */
-
- /* Initialize */
-
- allow = 0
- bheading = 0 /* is heading bulletin OFF */
- bhfile = fpath'HEADING.BUL'
- blank = D2C(32)
- bonly = 0 /* is only bulletin OFF */
- bofile = fpath'ONLY.BUL'
- btrailing = 0 /* is trailing bulletin OFF */
- btfile = fpath'TRAILING.BUL'
- disallow = 0
- endline = D2C(13) || D2C(10)
- executing = 0 /* is OFF */
- fver = '1.0'
- hostfile = fpath'FINGERD.HST'
- lastclient = ''
- logfile = fpath'FINGERD.LOG'
- logging = 0 /* is OFF */
- notify = 0 /* is OFF */
- port = 79
- rcontrol = 0 /* is OFF */
- restricted = 0 /* is NO */
- tab = D2C(9)
- tcount = 0
- verbose = 0 /* is OFF */
-
- /* Load Socket Functions */
-
- IF RxFuncQuery('SockLoadFuncs') THEN DO
- rc = RxFuncAdd('SockLoadFuncs','RxSock','SockLoadFuncs')
- rc = SockLoadFuncs()
- END
-
- /* Set Options */
-
- IF switches <> '' THEN DO
-
- DO i = 1 TO WORDS(switches)
-
- option = TRANSLATE(WORD(switches, i))
-
- SELECT
-
- WHEN ABBREV('/BHEADING',option) THEN
- bheading = 1 /* is heading bulletin ON */
-
- WHEN ABBREV('/BONLY',option) THEN
- bonly = 1 /* is only bulletin ON */
-
- WHEN ABBREV('/BTRAILING',option) THEN
- btrailing = 1 /* is trailing bulletin ON */
-
- WHEN (option = '/C') & (password <> '') THEN
- rcontrol = 1 /* is remote control ON */
-
- WHEN option = '/L' THEN
- logging = 1 /* is ON */
-
- WHEN option = '/N' THEN
- notify = 1 /* is YES */
-
- WHEN ABBREV('/RDISALLOW', option) THEN DO
- restricted = 1 /* is YES */
- disallow = 1 /* and listed are not allowed */
- allow = 0
- END
-
- WHEN ABBREV('/RALLOW', option) THEN DO
- restricted = 1 /* is YES */
- allow = 1 /* is listed are allowed */
- disallow = 0
- END
-
- WHEN option = '/V' THEN
- verbose = 1 /* is ON */
-
- WHEN option = '/X' THEN
- executing = 1 /* is ON */
-
- OTHERWISE
- SAY '"'option'" option is not recognized by FINGERD and has been ignored !'
- END
-
- END
-
- END
-
- /* Set up Restriction List if Needed */
-
- IF restricted THEN DO
-
- IF verbose THEN
- IF allow THEN
- SAY 'Only the following hosts allowed...'
- ELSE
- SAY 'The following hosts not allowed...'
-
- rlist = ''
-
- DO WHILE LINES(hostfile) > 0
- rline = TRANSLATE(LINEIN(hostfile), blank, tab)
- PARSE VAR rline rid (blank) rest
- IF verbose THEN
- SAY rid
- rlist = rlist || rid || blank
- END
-
- rlist = rlist || 'RHE'
-
- CALL LINEOUT hostfile
-
- END
-
- /* Get a Socket */
-
- s = SockSocket('AF_INET','SOCK_STREAM',0)
- IF (s = -1) THEN DO
- SAY 'SockSocket error: 'errno' !'
- endcode = 1
- SIGNAL halt2;
- END
-
- /* Handle a Break */
-
- SIGNAL ON halt;
-
- /* Bind Socket to Port */
-
- server.!family = 'AF_INET'
- server.!port = port
- server.!addr = 'INADDR_ANY'
-
- rc = SockBind(s,'server.!')
- IF (rc = -1) THEN DO
- SAY 'SockBind error: 'errno' !'
- endcode = 2
- SIGNAL halt2;
- END
-
- /* Set Queue Size and Listen */
-
- rc = SockListen(s,10)
- IF (rc = -1) THEN DO
- SAY 'SockListen error: 'errno' !'
- endcode = 3
- SIGNAL halt2;
- END
-
- SAY 'FINGERD has started...'
-
- IF logging THEN DO
- logentry = DATE('S') TIME('N') 'S' switches
- CALL LINEOUT logfile, logentry
- END
-
- /* Handle FINGER Requests */
-
- DO FOREVER
-
- ordered = 0
-
- IF verbose THEN SAY 'FINGERD is waiting for a client.'
-
- /* Accept a Connection */
-
- ns = SockAccept(s,'client.!')
- IF (ns = -1) THEN DO
- SAY 'SockAccept error: 'errno' !'
- endcode = 4
- SIGNAL halt2;
- END
-
- tcount = tcount + 1
- order = 0
-
- /* Get Client's Host Name */
-
- IF SockGetHostByAddr(client.!addr,'host.!') THEN
- clientName = host.!name
- ELSE
- clientName = 'Unknown'
-
- cinfo = client.!addr clientName
-
- IF verbose THEN SAY 'Accepted client: 'cinfo
-
- /* Get Peer Host Name */
-
- rc = SockGetPeerName(ns,'peer.!')
- IF (rc = -1) THEN DO
- SAY 'SockGetPeerName error: 'errno' !'
- endcode = 5
- SIGNAL halt2;
- END
-
- IF verbose THEN SAY 'PeerName: 'peer.!addr
-
- /* Get Socket Host Name */
-
- rc = SockGetSockName(ns,'sock.!')
- IF (rc = -1) THEN DO
- SAY 'SockGetSockName error: 'errno' !'
- endcode = 6
- SIGNAL halt2;
- END
-
- IF verbose THEN SAY 'SockName: 'sock.!addr
-
- /* Receive Request from Client */
-
- rc = SockRecv(ns,'data',1000)
- IF (rc = -1) THEN DO
- SAY 'SockRecv error: 'errno' !'
- endcode = 7
- SIGNAL halt2;
- END
-
- IF verbose THEN SAY 'Received: 'data
-
- /* Identify Request */
-
- id = ''
-
- /* Test for a NULL Query */
-
- IF data = endline | LENGTH(data) < 3 THEN DO
- replyfile = fpath'NULL.FNG'
- IF executing & (LINES(fpath'NULL.CMD') > 0) THEN DO
- CALL LINEOUT fpath'NULL.CMD'
- ADDRESS CMD
- '@CALL 'fpath'NULL.CMD >FING'tcount
- replyfile = 'FING'tcount
- END
- code = 'N' /* indicates that no user ID provided */
- lastclient = cinfo
- END
-
- ELSE DO
-
- i = 1
-
- DO WHILE (i <= 8) & (i <= LENGTH(data)) & (SUBSTR(data,i,1) <> D2C(13))
- id = id || SUBSTR(data,i,1)
- i = i + 1
- END
-
- id = TRANSLATE(id)
-
- /* Test for a KNOWN User */
-
- IF LINES(fpath''id'.FNG') > 0 THEN DO
- replyfile = fpath''id'.FNG'
- code = 'I' /* indicates that a known user ID provided */
- lastclient = cinfo
- END
-
- /* Test for an RPC */
-
- ELSE IF executing & (id <> 'FINGERD') & (LINES(fpath''id'.CMD') > 0) THEN DO
- CALL LINEOUT fpath''id'.CMD'
- ADDRESS CMD
- 'CALL 'fpath''id'.CMD >FING'tcount
- replyfile = 'FING'tcount
- code = 'X' /* indicates that an executable user ID provided */
- END
-
- /* Test for a Control Toggle/Query */
-
- ELSE IF rcontrol & (LENGTH(id) > 6) & (SUBSTR(id,1,6) = password) THEN DO
-
- ordered = 1
- report = ''
- order = SUBSTR(id,7,1)
-
- SELECT
-
- WHEN SUBSTR(id,7,2) = 'BH' THEN
- bheading = \bheading
- WHEN SUBSTR(id,7,2) = 'BO' THEN
- bonly = \bonly
- WHEN SUBSTR(id,7,2) = 'BT' THEN
- btrailing = \btrailing
- WHEN order = 'C' THEN
- rcontrol = \rcontrol
- WHEN order = 'L' THEN
- logging = \logging
- WHEN order = 'N' THEN
- notify = \notify
- WHEN order = 'R' THEN DO
- IF allow <> disallow THEN
- restricted = \restricted
- END
- WHEN order = 'V' THEN
- verbose = \verbose
- WHEN order = 'X' THEN
- executing = \executing
- WHEN order = '1' THEN
- report = tcount
- WHEN order = '2' THEN
- report = lastclient
- WHEN order = '9' THEN
- report = tcount
-
- OTHERWISE
-
- END
-
- replyfile = ''
- code = 'C' || order
- END
-
- /* Test for an UNKNOWN User */
-
- ELSE DO
- replyfile = fpath'UNKNOWN.FNG'
- IF executing & (LINES(fpath'UNKNOWN.CMD') > 0) THEN DO
- CALL LINEOUT fpath'UNKNOWN.CMD'
- ADDRESS CMD
- 'CALL 'fpath'UNKNOWN.CMD >FING'tcount
- replyfile = 'FING'tcount
- END
- code = 'U' /* indicates that no known user ID provided */
- END
-
- END
-
- /* Build Reply */
-
- reply = ''
-
- IF \ordered & (replyfile <> '') THEN DO
-
- IF bheading THEN
-
- CALL readin bhfile
-
- CALL readin replyfile
-
- IF replyfile = 'FING'tcount THEN
- '@ERASE FING'tcount' 2>nul'
-
- IF btrailing THEN
-
- CALL readin btfile
-
- END
-
- ELSE
- reply = '/Bh =' bheading || endline,
- '/Bo =' bonly || endline,
- '/Bt =' btrailing || endline,
- '/C =' rcontrol || endline,
- '/L =' logging || endline,
- '/N =' notify || endline,
- '/R =' restricted allow disallow || endline,
- '/V =' verbose || endline,
- '/X =' executing || endline,
- 'report'order' = 'report
-
- /* Reject Request if Client is Restricted */
-
- IF restricted THEN DO
-
- rhost = ''
- h = 1
-
- DO WHILE rhost <> 'RHE'
-
- rhost = WORD(rlist, h)
-
- IF client.!addr = rhost THEN
-
- IF disallow & \ordered THEN DO
- reply = 'FINGER not allowed by FINGERD!'
- code = code || '+'
- LEAVE
- END
- ELSE
- LEAVE
-
- h = h+1
-
- END
-
- IF (rhost = 'RHE') & allow & \ordered THEN DO
- reply = 'FINGER not allowed by FINGERD!!'
- code = code || '-'
- END
-
- END
-
- /* Force Only a Bulletin if Indicated */
-
- IF bonly & \ordered THEN DO
- reply = ''
- CALL readin bofile
- code = code || '!'
- END
-
- /* Display Notice */
-
- IF id = 'FINGERD' THEN DO
- reply = 'FINGERD' fver': A FINGER Server for OS/2' || endline
- reply = reply || 'NOTICE -- COPYRIGHT 1993 by Robert L. Samuell, III' || endline
- END
-
- /* Log Request */
-
- IF logging THEN DO
- IF rcontrol & (SUBSTR(id,1,6) = password) THEN
- data = ''
- logentry = DATE('S') TIME('N') code cinfo data
- CALL LINEOUT logfile, logentry
- END
-
- /* Notify if Selected */
-
- IF notify THEN
- SAY BEEP(600, 200) BEEP(300, 400)
-
- /* Send Reply Back */
-
- rc = SockSend(ns,reply)
- IF (rc = -1) THEN DO
- SAY 'SockSend error: 'errno' !'
- endcode = 8
- SIGNAL halt2;
- END
-
- /* Shutdown if Ordered */
-
- IF ordered & (order = 9) THEN DO
- endcode = 9
- SIGNAL halt2;
- END
-
- /* Close Socket from Client */
-
- rc = SockSoClose(ns)
- ns = ''
- IF (rc = -1) THEN DO
- SAY 'SockSoClose error: 'errno' !'
- endcode = 10
- SIGNAL halt2;
- END
-
- IF verbose THEN DO
- SAY 'Closing connection.'
- SAY
- END
-
- END
-
- /* Subroutine to Read Input File into Reply */
-
- readin:
-
- PARSE ARG infile
-
- IF LINES(infile) < 1 THEN DO
- reply = 'FINGERD! No information is available !!!'
- RETURN
- END
-
- DO WHILE LINES(infile) > 0
- sdata = LINEIN(infile)
- reply = reply || sdata || endline
- END
-
- CALL LINEOUT infile
-
- RETURN
-
- /* Handle a Break by Closing Sockets */
-
- halt:
-
- endcode = 0
-
- halt2:
-
- SAY
- SAY 'FINGERD is quitting ...'
-
- rc = SockSoClose(s)
-
- IF DATATYPE(ns,'W') THEN
- rc = SockSoClose(ns)
-
- IF logging THEN DO
- logentry = DATE('S') TIME('N') 'E' endcode
- CALL LINEOUT logfile, logentry
- CALL LINEOUT logfile
- END
-
- EXIT endcode