home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / network / fingerd / fingerd.cmd next >
Encoding:
Text File  |  1993-10-12  |  12.5 KB  |  543 lines

  1. /*  FINGERD.CMD ver 1.0 (8/14/1993)
  2.       REXX Program to Service FINGER Requests (FINGER Server)
  3.         by R L Samuell  (samuell@cis.uab.edu)
  4.  
  5.       NOTE: -- FINGERD.CMD requires OS/2 2.0 GA or later, TCPIP 1.2.1
  6.                   with April 1993 CSDs or later, and the latest version of
  7.                   the RxSock IBM EWS Freeware package.
  8.  
  9.       NOTICE -- COPYRIGHT 1993 by Robert L. Samuell, III
  10.               -- All Rights Reserved.  Publication of this document in
  11.                     whole or in part in any form, electronic or printed,
  12.                     in any forum, public or private, is expressly prohibited
  13.                     without the explicit permission of the author.
  14.               -- The latest version of documentation for FINGERD may
  15.                     obtained by Anonymous FTP at 138.26.65.78.
  16.  
  17.       LICENSE -- TERMS and CONDITIONS
  18.               -- You are not allowed to modify any portion of this program
  19.                     other than the values of variables defined in the section
  20.                     entitled 'Parameterize.'
  21.               -- This program is available for you to use free of charge.
  22.               -- Any distribution of this program must include both program
  23.                     and documentation, in the latest versions, unchanged.
  24.               -- Commercial sale or re-sale of this program is allowed only
  25.                     with the approval of the author.
  26.               -- DISCLAIMER: No warranties or guarantees are expressed or 
  27.                     implied.  And the author assumes no liability for ANY damage
  28.                     or loss whatsoever arising from the use of this program.
  29.                     Furthermore, the author is under no obligation to provide
  30.                     support of any kind.  This disclaimer applies to any support
  31.                     that is provided.
  32.               -- ACCEPTANCE:  By using or distributing this program, you 
  33.                     agree to these terms.
  34. */
  35.  
  36. PARSE ARG switches
  37.  
  38. SAY 'FINGERD:  A FINGER Server for OS/2'
  39. SAY 'NOTICE -- COPYRIGHT 1993 by Robert L. Samuell, III'
  40.  
  41. /* Parameterize -- ATTENTION:  
  42.       Only values of the following code variables may be modified by the user. */
  43.  
  44. fpath = 'C:\FINGER\'
  45. password = ''  /* NOTE:  must be 0 or 6 characters & alphas must be upper */
  46.  
  47. /* Initialize */
  48.  
  49. allow = 0
  50. bheading = 0 /* is heading bulletin OFF */
  51. bhfile = fpath'HEADING.BUL'
  52. blank = D2C(32)
  53. bonly = 0 /* is only bulletin OFF */
  54. bofile = fpath'ONLY.BUL'
  55. btrailing = 0 /* is trailing bulletin OFF */
  56. btfile = fpath'TRAILING.BUL'
  57. disallow = 0
  58. endline = D2C(13) || D2C(10)
  59. executing = 0 /* is OFF */
  60. fver = '1.0'
  61. hostfile = fpath'FINGERD.HST'
  62. lastclient = ''
  63. logfile = fpath'FINGERD.LOG'
  64. logging = 0 /* is OFF */
  65. notify = 0 /* is OFF */
  66. port = 79
  67. rcontrol = 0 /* is OFF */
  68. restricted = 0 /* is NO */
  69. tab = D2C(9)
  70. tcount = 0
  71. verbose = 0 /* is OFF */
  72.  
  73. /*  Load Socket Functions */
  74.  
  75. IF RxFuncQuery('SockLoadFuncs') THEN DO
  76.    rc = RxFuncAdd('SockLoadFuncs','RxSock','SockLoadFuncs')
  77.    rc = SockLoadFuncs()
  78.    END
  79.  
  80. /* Set Options */
  81.  
  82. IF switches <> '' THEN DO
  83.  
  84.   DO i = 1 TO WORDS(switches)
  85.  
  86.     option = TRANSLATE(WORD(switches, i))
  87.  
  88.     SELECT
  89.  
  90.       WHEN ABBREV('/BHEADING',option) THEN
  91.         bheading = 1 /* is heading bulletin ON */
  92.  
  93.       WHEN ABBREV('/BONLY',option) THEN
  94.         bonly = 1 /* is only bulletin ON */
  95.  
  96.       WHEN ABBREV('/BTRAILING',option) THEN
  97.         btrailing = 1 /* is trailing bulletin ON */
  98.  
  99.       WHEN (option = '/C') & (password <> '')  THEN
  100.         rcontrol = 1 /* is remote control ON */
  101.  
  102.       WHEN option = '/L'  THEN
  103.         logging = 1 /* is ON */
  104.  
  105.       WHEN option = '/N' THEN 
  106.         notify = 1 /* is YES */
  107.  
  108.       WHEN ABBREV('/RDISALLOW', option) THEN DO
  109.         restricted = 1 /* is YES */
  110.         disallow = 1 /* and listed are not allowed */
  111.         allow = 0
  112.         END
  113.  
  114.       WHEN ABBREV('/RALLOW', option) THEN DO
  115.         restricted = 1 /* is YES */
  116.         allow = 1 /* is listed are allowed */
  117.         disallow = 0
  118.         END
  119.  
  120.       WHEN option = '/V' THEN 
  121.         verbose = 1 /* is ON */
  122.  
  123.       WHEN option = '/X' THEN
  124.         executing = 1 /* is ON */
  125.  
  126.       OTHERWISE
  127.         SAY '"'option'" option is not recognized by FINGERD and has been ignored !'
  128.       END
  129.  
  130.     END
  131.  
  132. END
  133.  
  134. /* Set up Restriction List if Needed */
  135.  
  136. IF restricted THEN DO
  137.  
  138.   IF verbose THEN
  139.     IF allow THEN
  140.       SAY 'Only the following hosts allowed...'
  141.     ELSE
  142.       SAY 'The following hosts not allowed...'
  143.  
  144.   rlist = ''
  145.  
  146.   DO WHILE LINES(hostfile) > 0
  147.     rline = TRANSLATE(LINEIN(hostfile), blank, tab)
  148.     PARSE VAR rline rid (blank) rest
  149.     IF verbose THEN
  150.       SAY rid 
  151.     rlist = rlist || rid || blank
  152.     END
  153.  
  154.   rlist = rlist || 'RHE'
  155.  
  156.   CALL LINEOUT hostfile
  157.  
  158.   END
  159.  
  160. /* Get a Socket */
  161.  
  162. s  = SockSocket('AF_INET','SOCK_STREAM',0)
  163. IF (s = -1) THEN DO
  164.   SAY 'SockSocket error: 'errno' !'
  165.   endcode = 1
  166.   SIGNAL halt2;
  167.   END
  168.  
  169. /* Handle a Break */
  170.  
  171. SIGNAL ON halt;
  172.  
  173. /* Bind Socket to Port */
  174.  
  175. server.!family = 'AF_INET'
  176. server.!port   = port
  177. server.!addr   = 'INADDR_ANY'
  178.  
  179. rc = SockBind(s,'server.!')
  180. IF (rc = -1) THEN DO
  181.   SAY 'SockBind error: 'errno' !'
  182.   endcode = 2
  183.   SIGNAL halt2;
  184.   END
  185.  
  186. /* Set Queue Size and Listen */
  187.  
  188. rc = SockListen(s,10)
  189. IF (rc = -1) THEN DO
  190.    SAY 'SockListen error: 'errno' !'
  191.    endcode = 3
  192.    SIGNAL halt2;
  193.    END
  194.  
  195. SAY 'FINGERD has started...'
  196.  
  197. IF logging THEN DO
  198.   logentry = DATE('S') TIME('N') 'S' switches 
  199.   CALL LINEOUT logfile, logentry
  200.   END
  201.  
  202. /* Handle FINGER Requests */
  203.  
  204. DO FOREVER
  205.  
  206.   ordered = 0
  207.  
  208.   IF verbose THEN SAY 'FINGERD is waiting for a client.'
  209.  
  210.   /* Accept a Connection */
  211.  
  212.   ns = SockAccept(s,'client.!')
  213.   IF (ns = -1) THEN DO
  214.     SAY 'SockAccept error: 'errno' !'
  215.     endcode = 4
  216.     SIGNAL halt2;
  217.     END
  218.  
  219.   tcount = tcount + 1
  220.   order = 0
  221.  
  222.   /* Get Client's Host Name */
  223.  
  224.   IF SockGetHostByAddr(client.!addr,'host.!') THEN
  225.     clientName = host.!name
  226.   ELSE
  227.     clientName = 'Unknown'
  228.  
  229.   cinfo = client.!addr clientName   
  230.  
  231.   IF verbose THEN SAY 'Accepted client: 'cinfo
  232.  
  233.   /* Get Peer Host Name */
  234.  
  235.   rc = SockGetPeerName(ns,'peer.!')
  236.   IF (rc = -1) THEN DO
  237.     SAY 'SockGetPeerName error: 'errno' !'
  238.     endcode = 5
  239.     SIGNAL halt2; 
  240.     END
  241.  
  242.   IF verbose THEN SAY 'PeerName: 'peer.!addr
  243.  
  244.   /* Get Socket Host Name */
  245.  
  246.   rc = SockGetSockName(ns,'sock.!')
  247.   IF (rc = -1) THEN DO
  248.     SAY 'SockGetSockName error: 'errno' !'
  249.     endcode = 6
  250.     SIGNAL halt2;
  251.     END
  252.  
  253.   IF verbose THEN SAY 'SockName: 'sock.!addr
  254.  
  255.   /* Receive Request from Client */
  256.  
  257.   rc = SockRecv(ns,'data',1000)
  258.   IF (rc = -1) THEN DO
  259.     SAY 'SockRecv error: 'errno' !'
  260.     endcode = 7
  261.     SIGNAL halt2;
  262.     END
  263.  
  264.   IF verbose THEN SAY 'Received: 'data
  265.  
  266.   /* Identify Request */
  267.  
  268.   id = ''
  269.  
  270.   /* Test for a NULL Query */
  271.  
  272.   IF data = endline | LENGTH(data) < 3 THEN DO
  273.     replyfile = fpath'NULL.FNG'
  274.     IF executing & (LINES(fpath'NULL.CMD') > 0) THEN DO
  275.       CALL LINEOUT fpath'NULL.CMD'
  276.       ADDRESS CMD
  277.       '@CALL 'fpath'NULL.CMD >FING'tcount
  278.       replyfile = 'FING'tcount
  279.       END
  280.     code = 'N' /* indicates that no user ID provided */
  281.     lastclient = cinfo
  282.     END
  283.    
  284.   ELSE DO
  285.      
  286.     i = 1
  287.      
  288.     DO WHILE (i <= 8) & (i <= LENGTH(data)) & (SUBSTR(data,i,1) <> D2C(13))    
  289.       id = id || SUBSTR(data,i,1)
  290.       i = i + 1
  291.       END
  292.  
  293.     id = TRANSLATE(id)
  294.  
  295.     /* Test for a KNOWN User */
  296.  
  297.     IF LINES(fpath''id'.FNG') > 0 THEN DO
  298.       replyfile = fpath''id'.FNG'
  299.       code = 'I' /* indicates that a known user ID provided */
  300.       lastclient = cinfo
  301.       END
  302.  
  303.     /* Test for an RPC */
  304.  
  305.     ELSE IF executing & (id <> 'FINGERD') & (LINES(fpath''id'.CMD') > 0) THEN DO
  306.       CALL LINEOUT fpath''id'.CMD'
  307.       ADDRESS CMD
  308.       'CALL 'fpath''id'.CMD >FING'tcount
  309.       replyfile = 'FING'tcount
  310.       code = 'X' /* indicates that an executable user ID provided */
  311.       END
  312.  
  313.     /*  Test for a Control Toggle/Query */
  314.  
  315.     ELSE IF rcontrol & (LENGTH(id) > 6) & (SUBSTR(id,1,6) = password) THEN DO
  316.  
  317.       ordered = 1
  318.       report = ''
  319.       order = SUBSTR(id,7,1)
  320.  
  321.       SELECT
  322.  
  323.         WHEN SUBSTR(id,7,2) = 'BH' THEN
  324.           bheading = \bheading
  325.         WHEN SUBSTR(id,7,2) = 'BO' THEN
  326.           bonly = \bonly
  327.         WHEN SUBSTR(id,7,2) = 'BT' THEN
  328.           btrailing = \btrailing
  329.         WHEN order = 'C' THEN
  330.           rcontrol = \rcontrol
  331.         WHEN order = 'L' THEN
  332.           logging = \logging
  333.         WHEN order = 'N' THEN
  334.           notify = \notify
  335.         WHEN order = 'R' THEN DO
  336.           IF allow <> disallow THEN
  337.             restricted = \restricted
  338.           END
  339.         WHEN order = 'V' THEN
  340.           verbose =  \verbose
  341.         WHEN order = 'X' THEN
  342.           executing = \executing
  343.         WHEN order = '1' THEN
  344.           report = tcount
  345.         WHEN order = '2' THEN
  346.           report = lastclient
  347.         WHEN order = '9' THEN
  348.           report = tcount
  349.           
  350.         OTHERWISE
  351.  
  352.         END
  353.  
  354.       replyfile = ''
  355.       code = 'C' || order
  356.       END
  357.  
  358.     /* Test for an UNKNOWN User */
  359.  
  360.     ELSE DO
  361.       replyfile = fpath'UNKNOWN.FNG'
  362.       IF executing & (LINES(fpath'UNKNOWN.CMD') > 0) THEN DO
  363.         CALL LINEOUT fpath'UNKNOWN.CMD'
  364.         ADDRESS CMD
  365.         'CALL 'fpath'UNKNOWN.CMD >FING'tcount
  366.         replyfile = 'FING'tcount
  367.         END
  368.       code = 'U' /* indicates that no known user ID provided */
  369.       END
  370.  
  371.     END
  372.  
  373.   /* Build Reply */
  374.  
  375.   reply = ''
  376.  
  377.   IF \ordered & (replyfile <> '') THEN DO
  378.  
  379.     IF bheading THEN
  380.  
  381.       CALL readin bhfile
  382.  
  383.     CALL readin replyfile
  384.  
  385.     IF replyfile = 'FING'tcount THEN
  386.       '@ERASE FING'tcount' 2>nul'
  387.  
  388.     IF btrailing THEN
  389.  
  390.       CALL readin btfile
  391.  
  392.     END
  393.  
  394.   ELSE
  395.     reply = '/Bh =' bheading || endline,
  396.             '/Bo =' bonly || endline,
  397.             '/Bt =' btrailing || endline,
  398.             '/C =' rcontrol || endline,
  399.             '/L =' logging || endline,
  400.             '/N =' notify || endline,
  401.             '/R =' restricted allow disallow || endline,
  402.             '/V =' verbose || endline,
  403.             '/X =' executing || endline,
  404.             'report'order' = 'report
  405.  
  406.   /* Reject Request if Client is Restricted */
  407.  
  408.   IF restricted THEN DO
  409.  
  410.     rhost = ''
  411.     h = 1
  412.  
  413.     DO WHILE rhost <> 'RHE'
  414.  
  415.       rhost = WORD(rlist, h)
  416.  
  417.       IF client.!addr = rhost THEN
  418.  
  419.         IF disallow & \ordered THEN DO
  420.           reply = 'FINGER not allowed by FINGERD!'
  421.           code = code || '+'
  422.           LEAVE
  423.           END
  424.         ELSE
  425.            LEAVE
  426.  
  427.       h = h+1
  428.  
  429.       END
  430.  
  431.     IF (rhost = 'RHE') & allow & \ordered THEN DO
  432.       reply = 'FINGER not allowed by FINGERD!!'
  433.       code = code || '-'
  434.       END
  435.  
  436.   END
  437.  
  438.   /* Force Only a Bulletin if Indicated */
  439.  
  440.   IF bonly & \ordered THEN DO
  441.     reply = ''
  442.     CALL readin bofile
  443.     code = code || '!'
  444.     END
  445.  
  446.   /* Display Notice */
  447.  
  448.   IF id = 'FINGERD' THEN DO
  449.     reply = 'FINGERD' fver':  A FINGER Server for OS/2' || endline
  450.     reply = reply || 'NOTICE -- COPYRIGHT 1993 by Robert L. Samuell, III' || endline
  451.     END
  452.  
  453.   /* Log Request */
  454.  
  455.   IF logging THEN DO
  456.     IF rcontrol & (SUBSTR(id,1,6) = password) THEN
  457.       data = ''
  458.     logentry = DATE('S') TIME('N') code cinfo data 
  459.     CALL LINEOUT logfile, logentry
  460.     END
  461.  
  462.   /* Notify if Selected */
  463.  
  464.   IF notify THEN
  465.     SAY BEEP(600, 200) BEEP(300, 400)
  466.  
  467.   /* Send Reply Back */
  468.  
  469.   rc = SockSend(ns,reply)
  470.   IF (rc = -1) THEN DO
  471.     SAY 'SockSend error: 'errno' !'
  472.     endcode = 8
  473.     SIGNAL halt2;
  474.     END
  475.  
  476.   /* Shutdown if Ordered */
  477.  
  478.   IF ordered & (order = 9) THEN DO
  479.     endcode = 9
  480.     SIGNAL halt2;
  481.     END 
  482.  
  483.   /* Close Socket from Client */
  484.  
  485.   rc = SockSoClose(ns)
  486.   ns = ''
  487.   IF (rc = -1) THEN DO
  488.     SAY 'SockSoClose error: 'errno' !'
  489.     endcode = 10
  490.     SIGNAL halt2;
  491.     END
  492.  
  493.   IF verbose THEN DO
  494.     SAY 'Closing connection.'
  495.     SAY
  496.     END
  497.  
  498. END
  499.  
  500. /* Subroutine to Read Input File into Reply */
  501.  
  502. readin:
  503.  
  504.   PARSE ARG infile
  505.  
  506.   IF LINES(infile) < 1 THEN DO
  507.     reply = 'FINGERD! No information is available !!!'
  508.     RETURN
  509.     END
  510.  
  511.   DO WHILE LINES(infile) > 0
  512.     sdata = LINEIN(infile)
  513.     reply = reply || sdata || endline
  514.     END
  515.  
  516.   CALL LINEOUT infile
  517.  
  518.   RETURN
  519.  
  520. /* Handle a Break by Closing Sockets */
  521.  
  522. halt:
  523.  
  524. endcode = 0
  525.  
  526. halt2:
  527.  
  528. SAY
  529. SAY 'FINGERD is quitting ...'
  530.  
  531. rc = SockSoClose(s)
  532.  
  533. IF DATATYPE(ns,'W') THEN
  534.   rc = SockSoClose(ns)
  535.  
  536. IF logging THEN DO
  537.   logentry = DATE('S') TIME('N') 'E' endcode 
  538.   CALL LINEOUT logfile, logentry
  539.   CALL LINEOUT logfile
  540.   END
  541.  
  542. EXIT endcode
  543.