        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        ':::                                                                 :::
        ':::                                                                 :::
        ':::    PROGRAM:        ULIST.BAS                                    :::
        ':::    AUTHOR:         Mike Shaffer                                 :::
        ':::    DATE:           Feb 2, 1991                                  :::
        ':::    VERSION:        2.1                                          :::
        ':::    PURPOSE:        Shows a userlist on Novell with total        :::
        ':::                    elapsed time logged-in.                      :::
        ':::    REVISIONS:      Feb 6, 1991: Improved structure of source    :::
        ':::                                 for general release (V2.0-2.1)  :::
        ':::                                                                 :::
        ':::                                                                 :::
        ':::    NOTES:          This program assumes you're using PDQ from   :::
        ':::                    Crescent Software. If not (shame on you!)    :::
        ':::                    than you can modify the interrupt call to    :::
        ':::                    use INT86 as provided with QuickBASIC, and   :::
        ':::                    take out the reference to PDQDECL.BAS.       :::
        ':::                    Also change: PDQVALx() references to VAL()   :::
        ':::                                 PDQCPRINT references to PRINT   :::
        ':::                                                                 :::
        ':::                    Compile using:                               :::
        ':::                                                                 :::
        ':::                         BC ulist/o/s;                           :::
        ':::                         LINK /NOD/NOE ulist,,,pdq[386].lib      :::
        ':::                                                                 :::
        ':::                    or similar...                                :::
        ':::                                                                 :::
        ':::                                                                 :::
        ':::                                                                 :::
        ':::                                                                 :::
        ':::  Author  is not responsible for any damages resulting from use  :::
        ':::  or  inability to use this program.  The entire responsibility  :::
        ':::  for use of this program is with the user.                      :::
        ':::                                                                 :::
        ':::                                                                 :::
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        '
        '                                               '   PDQ declarations
        '                                               '   PDQ declarations
        '$include: 'pdqdecl.bas'                        ' Crescent Software's
        '                                               '   PDQ declarations
        '                                               '
        dim shared regs as regtype                      ' Define a struct for
        '                                               '   interrupt usage
        '                                               '
        common shared year%,month$,day$,_               ' Share vars
                      hours$,mins$,reply$               '
        '                                               '
        declare SUB SINFO(node%,result%)                ' SUB to get node info
        '                                               '
        '                                               '
        def fnCALCDATE&(year,month,days)=_              ' Function to obtain
              ((month-1)*28)+_                          '   the 3-digit day
              pdqvall&(MID$("000303060811131619212426",_'   of year value (from
              (month - 1) * 2 + 1, 2))-_                '   1 to 365/366 if leap
              ((month>2) AND ((year AND NOT -4)=0))+_   '   year) given mm, dd,
              days                                      '   and 4-digit yy.
        '                                               '
        today& = fncalcdate&(pdqvall&(mid$(date$,7,4)),_' Get today's day number
                             pdqvall&(mid$(date$,1,2)),_'   from 1-365 (or 366
                             pdqvall&(mid$(date$,4,2))) '   if a leap year!)
        '                                               '
        now& = (today&*86400)+_                         '
               (pdqvall&(left$(time$,2))*3600)+_        '
               (pdqvall&(mid$(time$,4,2))*60)           ' Calculate current time
        '                                               '   from the beginning
        '                                               '   of year in seconds.
        '                                               '   ñ59 seconds
        '                                               '
        '                                               '
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        ':::       Display the welcome and some titles for the table         :::
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        '                                               '
        '                                               '
        '                                               '
        color 7,0                                       '   set 'normal'
        print "þ ULIST þ Version 2.1 þ Copyright *c* 1991, Mike Shaffer"
        color 14,0:pdqcprint "þ",csrlin-1,1             ' Jazz it up with a 
        pdqcprint "þ",csrlin-1,9                        '   bit of color!
        pdqcprint "þ",csrlin-1,23                       '
        color 7,0 : pdqcprint " ",csrlin,2              '
        '                                               '
        '                                               '
        '                                               '
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        ':::                Now we really get down to business!              :::
        ':::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        '                                               '
        '                                               '
        '                                               '
        pse% = 0                                        ' Clear PAUSE flag
        if instr(ucase$(command$),"/P") then            ' Did user want a pause?
           pse% = -1                                    '   YES: Set PAUSE flag
           lct%   =  0                                  '   clear line count
        end if                                          '
        '                                               '
        '                                               '
        if instr(ucase$(command$), "?") or_             ' Did user want help?
           instr(ucase$(command$),"/H") then            ' Did user want help?
              goto HELP                                 '   YES: So give it
        end if                                          '
        '                                               '
        '                                               '
        '                                               '
        regs.ax = &h7A00                                ' Check to see if we
        '                                               '   are running Novell!
        interrupt &h2F,regs                             ' Do interrupt
        if (regs.ax AND &hFF) <> &hFF then              ' Whoops! We're not!
           color 12,0                                   '   Error indication
           print : print                                '
           pdqcprint "Not running Novell Netware.",_    '
                     csrlin,1                           '   Show error
           color 7,0                                    '   back to 'normal'
           goto HELP                                    '   Show help screen!
        end if                                          '
        '                                               '
        regs.ax = &hDC00                                ' Function to get this
        interrupt &h21,regs                             '   node's address
        lcal% = regs.ax and &hFF                        ' Contained in AL
        '                                               ' INTERESTING NOTE:
        '                                               '   I tried to name
        '                                               '   this variable
        '                                               '   LOCAL%, but was
        '                                               '   informed by QB that
        '                                               '   it was an advanced
        '                                               '   feature (a reserved
        '                                               '   word).
        '                                               '
        '                                               '
        SINFO lcal%,result%                             ' Get port info
        '                                               ' OK, we're on a Novell
        '                                               '   network (IPX is 
        '                                               '   loaded) but are we
        '                                               '   logged in?
        if not result% then                             ' Whoops! Not logged in!
           color 12,0                                   '   Error indication
           print : print                                '
           pdqcprint "Not logged-in to any server.",_   '
                     csrlin,1                           '   Show error
           color 7,0                                    '   back to 'normal'
           goto HELP                                    '   Show help screen!
        end if                                          '
        '                                               '
        '                                               '
        '                                               '
        '                                               '
        print "Station  User-ID      Time/Date Logged In     Elapsed time on system"
        print "-------------------------------------------------------------------------"
        for x% = 1 to 255                               ' Display <= 255 nodes
           '                                            '
           SINFO x%,result%                             '
           if result% then                              '
           '                                            '
              print right$("000"+str$(x%),3);space$(7); ' Print station #
              if x% = lcal% then                        ' Is it me?
                 color 14,0                             '   YES, so:
                 pdqcprint "-->",csrlin,5               '     display a color
                 color 7,0                              '     identifier
              end if                                    '
              print mid$(reply$,9,12);                  ' Show ID name
              print " ";hours$":"mins$"  ";             ' Show time logged in
              print month$"/"day$"/"year%;"   ";        ' Show date logged in
              '                                         ' Now we determine how
              '                                         '   long this node has
              '                                         '   been 'logged-in'
              ldate& = fncalcdate&(year%,_              ' Calculate 'logged-in'
                                   pdqvall&(month$),_   '    date's 3-digit day
                                   pdqvall&(day$))      '    of year value
              ltime& = (pdqvall&(hours$)*3600)+_        ' Calculate elapsed time
                       (pdqvall&(mins$)*60)             '   in seconds (today)
              lthen& = (ldate&*86400) + ltime&          ' Calculate elapsed time
              '                                         '   in seconds from log-
              '                                         '   in date
              diff&  = now& - lthen&                    ' Get difference
              '                                         '
              '                                         ' Now we can get the time
              '                                         '   in human readable form
              '                                         '   (hh:mm:ss) by using 
              '                                         '   integer math only...
              hrs& = diff&\3600:diff& = diff& mod 3600  ' Get hours
              mns& = diff&\60:diff& = diff& mod 60      ' Get minutes
              dys& = hrs&\24:hrs& = hrs& mod 24         ' Get days, modify hours
              '                                         '
              if dys& = 0 then                          ' Print # of days this
                 print "           ";                   '   node has been online
              elseif dys& = 1 then                      '    .
                 print "   1 day,  ";                   '    .
              else                                      '    .
                 print right$(space$(4)+_               '    .
                       str$(dys&),4)" days, ";          '    .
              end if                                    '    .
              if hrs& = 0 then                          ' Print # of hours this
                 print "        ";                      '   node has been online
              elseif hrs& = 1 then                      '    .
                 print " 1 hr,  ";                      '    .
              else                                      '    .
                 print right$(space$(2)+_               '    .
                       str$(hrs&),2)" hrs, ";           '    .
              end if                                    '    .
              print right$(space$(2)+str$(mns&),2)" min"' Print # of minutes
              '                                         '   this node online
              '                                         '
              '                                         '
              if pse% then                              ' Is PAUSE flag on?
                 lct% = lct% + 1                        '   INC line count
                 if lct% = 20 then                      '   at limit?
                    print "(Press a key for more)";     '   YES: show prompt
                    an$ = input$(1)                     '        wait for key
                    lct% = 0                            '        clear count
                    locate csrlin,1                     '        go to BOL
                    print space$(20);                   '        clear prompt
                    locate csrlin,1                     '        go to BOL
                 end if                                 '   done
              end if                                    '
              '                                         '
              '                                         '
           else                                         ' OTHERWISE (null)
              mt% = mt% + 1                             '   Increment null count
              if mt% = 20 then x% = 255                 '   if over 20 nulls
              '                                         '     have been seen,
              '                                         '     assume we're done!
           end if                                       '
        next                                            ' Continue until done
        '                                               '
        '                                               '
        end                                             '
        '                                               '
        '                                               '
        '                                               '
HELP:                                                   '
        print                                           '
        print                                           '
        print "ULIST displays a list of users currently on your Novell Network."
        print "In addition to Novell's USERLIST command, ULIST also shows the total"
        print "elapsed time on the net by each user. The only options for ULIST are:"
        print                                           '
        print "        /H or /?  =  This help screen"
        print "        /P        =  Pause on full screens"
        print
        print                                           '
        print                                           '
        print "Ú"string$(77,"Ä")"¿"
        print "³ To report problems or submit suggestions for improvement, call Mike Shaffer ³"
        print "³          at (214) 855-5200 (voice) or (214) 340-6896 (SOS-BBS).             ³"
        print "À"string$(77,"Ä")"Ù"
        print                                           '
        print                                           '
        end                                             '
        '                                               '
        '                                               '
        '                                               '
        '                                               '
        sub SINFO(node%,result%) static                 '
           result%  = 0                                 ' Clear result
           request$ = mki$(61) + chr$(22) + chr$(node%) ' Set up interrupt req
           reply$   = ""                                ' Erase string (PDQ)
           reply$   = space$(63)                        ' Set up receiver
           regs.ax  = &hE300                            ' Define interrupt/func
           regs.si  = sadd(request$)                    ' Address of request
           regs.di  = sadd(reply$)                      ' Address for reply
           interrupt &h21,regs                          ' Do it!
           '                                            '
           if midchar%(reply$,9)<> 0 and_               ' Not null?
              midchar%(reply$,9)<>32 then               ' Not space?
              result% = -1                              ' Show good results!
              year%  = (1900 + (cvi(mid$(reply$,57,2)) and &hFF))
              Month$ = right$("00"+str$((cvi(mid$(reply$,58,2)) and &HFF)),2)
              Day$   = right$("00"+str$((cvi(mid$(reply$,59,2)) and &HFF)),2)
              Hours$ = right$("00"+str$((cvi(mid$(reply$,60,2)) and &HFF)),2)
              Mins$  = right$("00"+str$((cvi(mid$(reply$,61,2)) and &HFF)),2)
              '                                         '
           end if                                       '
        end sub                                         '

