Subversion Repositories Kolibri OS

Rev

Rev 1323 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;
  3. ;    FTPS
  4. ;    FTP Server
  5. ;
  6. ;    Compile with FASM for Menuet
  7. ;
  8.  
  9. ; note: telnet == 23, ftp cmd == 21, data on 20
  10.  
  11. use32
  12.  
  13.     org     0x0
  14.  
  15.     db      'MENUET01'              ; 8 byte id
  16.     dd      1                       ; header version
  17.     dd      START                   ; program start
  18.     dd      I_END                   ; program image size
  19.     dd      0x170000                ; required amount of memory
  20.     dd      0x16FFF0                ; esp = 0x16FFF0
  21.     dd      0, 0                    ; no params, no path
  22.  
  23. include 'macros.inc'
  24. ; Various states of client connection
  25. USER_NONE       equ 0   ; Awaiting a connection
  26. USER_CONNECTED  equ 1   ; User just connected, prompt given
  27. USER_USERNAME   equ 2   ; User given username
  28. USER_LOGGED_IN  equ 3   ; User given password
  29.  
  30.  
  31.  
  32.  
  33.  
  34. START:                          ; start of execution
  35.     ; Clear the screen memory
  36.     mov     eax, '    '
  37.     mov     edi,text
  38.     mov     ecx,80*30 /4
  39.     cld
  40.     rep     stosd
  41.  
  42.     call    draw_window
  43.  
  44.     ; init the receive buffer pointer
  45.     mov     [buffptr], buff
  46.  
  47.     ; Init FTP server state machine
  48.     mov     [state], USER_NONE
  49.  
  50.     ; Open the listening socket
  51.     call    connect
  52.  
  53. still:
  54.     ; check connection status
  55.     mov     eax,53
  56.     mov     ebx,6               ; Get socket status
  57.     mov     ecx,[CmdSocket]
  58.     mcall
  59.  
  60.     mov     ebx, [CmdSocketStatus]
  61.     mov     [CmdSocketStatus], eax
  62.  
  63.     cmp     eax, ebx
  64.     je      waitev
  65.  
  66.     ; If the socket closed by remote host, open it again.
  67.     cmp     eax, 7
  68.     je      con
  69.  
  70.     ; If socket closed by Reset, open it again
  71.     cmp     eax, 11
  72.     je      con
  73.  
  74.     ; If a user has just connected, start by outputting welcome msg
  75.     cmp     eax, 4
  76.     jne     noc
  77.  
  78.     mov     esi, loginStr0
  79.     mov     edx, loginStr0_end - loginStr0
  80.     call    outputStr
  81.  
  82.     mov     [state], USER_CONNECTED
  83.     jmp     noc
  84.  
  85.  
  86. con:
  87.     ; Need to call disconnect, since a remote close does not fully
  88.     ; close the socket
  89.     call    disconnect
  90.     mov     eax,5
  91.     mov     ebx,10          ; Delay for 100ms
  92.     mcall
  93.     call    connect
  94.     jmp     noc
  95.  
  96. noc:
  97.     ; Display the changed connected status
  98.     call    draw_window
  99.  
  100. waitev:
  101.     mov     eax,23                 ; wait here for event
  102.     mov     ebx,1                 ; Delay for up to 1s
  103.     mcall
  104.  
  105.     cmp     eax,1                  ; redraw request ?
  106.     je      red
  107.     cmp     eax,2                  ; key in buffer ?
  108.     je      key
  109.     cmp     eax,3                  ; button in buffer ?
  110.     je      button
  111.  
  112.     ; any data from the socket?
  113.  
  114.     mov     eax, 53
  115.     mov     ebx, 2                  ; Get # of bytes in input queue
  116.     mov     ecx, [CmdSocket]
  117.     mcall
  118.     test    eax, eax
  119.     jz      still
  120.  
  121. read_input:
  122.     mov     eax, 53
  123.     mov     ebx, 3                  ; Get a byte from socket in bl
  124.     mov     ecx, [CmdSocket]
  125.     mcall
  126.  
  127.     call    ftpRxCmdData            ; process incoming ftp command
  128.  
  129.     ; Keep processing data until there is no more to process
  130.     mov     eax, 53
  131.     mov     ebx, 2                  ; Get # of bytes in input queue
  132.     mov     ecx, [CmdSocket]
  133.     mcall
  134.     cmp     eax, 0
  135.     jne     read_input
  136.  
  137.     ; Now redraw the text text field.
  138.     ; Probably not required, since ftp requires no
  139.     ; console i/o.
  140.     ; Leave in for now, for debugging.
  141. ; (fall through to "red:")
  142. ;    call    draw_text
  143. ;    jmp     still
  144.  
  145. red:                          ; REDRAW WINDOW
  146.     call    draw_window
  147.     jmp     still
  148.  
  149. key:                          ; KEY
  150.     mov     eax,2                  ; get but ignore
  151.     mcall
  152.     jmp     still
  153.  
  154. button:
  155.     mov     eax,17
  156.     mcall
  157.     cmp     ah,1
  158.     jne     still
  159.  
  160.     ; Exit button pressed, so close socket and quit
  161.     mov     eax,53
  162.     mov     ebx,8
  163.     mov     ecx,[CmdSocket]
  164.     mcall
  165.  
  166.     ; ... terminate program
  167.     or     eax,-1
  168.     mcall
  169.     jmp     still
  170.  
  171.  
  172.  
  173. ;   *********************************************
  174. ;   *******  WINDOW DEFINITIONS AND DRAW ********
  175. ;   *********************************************
  176. draw_window:
  177.     pusha
  178.  
  179.     mov  eax,12
  180.     mov  ebx,1
  181.     mcall
  182.  
  183.     xor  eax,eax                   ; DRAW WINDOW
  184.     mov  ebx,100*65536+491 + 8 +15
  185.     mov  ecx,100*65536+270 + 20     ; 20 for status bar
  186.     mov  edx,0x14000000
  187.     mov  edi,labelt
  188.     mcall
  189.  
  190.     ; draw status bar
  191.     mov     eax, 13
  192.     mov     ebx, 4*65536+484 + 8 +15
  193.     mov     ecx, 270*65536 + 3
  194.     mov     edx, 0x00557799
  195.     mcall
  196.  
  197.  
  198.     mov  esi,contlen-contt          ; display connected status
  199.     mov     edx, contt
  200.     cmp     [CmdSocketStatus], 4    ; 4 is connected
  201.     je      pcon
  202.     mov     esi,discontlen-discontt
  203.     mov     edx, discontt
  204. pcon:
  205.  
  206.     mov  eax,4                      ; status text
  207.     mov  ebx,380*65536+276
  208.     mov  ecx,0x00ffffff
  209.     mcall
  210.  
  211.     ; Draw the text on the screen, clearing it first
  212.     ; This can go when we loose debuggin info.
  213.     xor  eax,eax
  214.     mov  edi,text+80*30
  215.     mov  ecx,80*30 /4
  216.     cld
  217.     rep  stosd
  218.  
  219.     call draw_text
  220.  
  221.     mov  eax,12
  222.     mov  ebx,2
  223.     mcall
  224.  
  225.     popa
  226.  
  227.     ret
  228.  
  229.  
  230. ;***************************************************************************
  231. ;   Function
  232. ;      draw_text
  233. ;
  234. ;   Description
  235. ;       Updates the text on the screen. This is part of the debugging code
  236. ;
  237. ;   Inputs
  238. ;       Character to add in bl
  239. ;
  240. ;***************************************************************************
  241. draw_text:
  242.  
  243.     pusha
  244.  
  245.     mov  esi,text
  246.     mov  eax,0
  247.     mov  ebx,0
  248.   newletter:
  249.     mov  cl,[esi]
  250.     cmp  cl,[esi+30*80]
  251.     jz   noletter
  252.   yesletter:
  253.     mov  [esi+30*80],cl
  254.  
  255.     ; erase character
  256.  
  257.     pusha
  258.     mov     edx, 0                  ; bg colour
  259.     mov     ecx, ebx
  260.     add     ecx, 26
  261.     shl     ecx, 16
  262.     mov     cx, 9
  263.     mov     ebx, eax
  264.     add     ebx, 6
  265.     shl     ebx, 16
  266.     mov     bx, 6
  267.     mov     eax, 13
  268.     mcall
  269.     popa
  270.  
  271.     ; draw character
  272.  
  273.     pusha
  274.     mov     ecx, 0x00ffffff
  275.     push bx
  276.     mov  ebx,eax
  277.     add  ebx,6
  278.     shl  ebx,16
  279.     pop  bx
  280.     add  bx,26
  281.     mov  eax,4
  282.     mov  edx,esi
  283.     mov  esi,1
  284.     mcall
  285.     popa
  286.  
  287.   noletter:
  288.  
  289.     add  esi,1
  290.     add  eax,6
  291.     cmp  eax,80*6
  292.     jb   newletter
  293.     mov  eax,0
  294.     add  ebx,10
  295.     cmp  ebx,24*10
  296.     jb   newletter
  297.  
  298.     popa
  299.     ret
  300.  
  301.  
  302.  
  303. ;***************************************************************************
  304. ;   Function
  305. ;      ftpRxCmdData
  306. ;
  307. ;   Description
  308. ;       Prcoesses incoming command data, calling a handler for each command.
  309. ;       Commands are built up in buff before being processed.
  310. ;
  311. ;   Inputs
  312. ;       Character to add in bl
  313. ;
  314. ;***************************************************************************
  315. ftpRxCmdData:
  316.     ; Quit if we are not connected
  317.     ;( This case shouldn't be necessary, but be safe )
  318.     mov     al, [state]
  319.     cmp     al, USER_NONE
  320.     je      frcd_exit
  321.  
  322.     ; Store the incoming character
  323.     mov     esi, [buffptr]
  324.     mov     [esi], bl
  325.     inc     esi
  326.     mov     [buffptr], esi
  327.  
  328.     ; For debugging, show the data coming in
  329.     pusha
  330.     call    printChar
  331.     popa
  332.  
  333.     ; Do we have an end of line? (LF)
  334.     ; if not, just exit
  335.     cmp     bl, 0x0a
  336.     jne     frcd_exit
  337.  
  338.     ; OK we have a complete command.
  339.     ; Process, and send response
  340.  
  341.     ; There are a number of states involved in ftp,
  342.     ; to do with logging in.
  343.  
  344.     mov     al, [state]
  345.     cmp     al, USER_CONNECTED
  346.     jne     fs001
  347.  
  348.     ; This should be the username
  349.  
  350.     ; TODO validate username
  351.  
  352.     ; OK, username accepted - ask for password
  353.     mov     esi, loginStr1
  354.     mov     edx, loginStr1_end - loginStr1
  355.     call    outputStr
  356.  
  357.     mov     [state], USER_USERNAME
  358.  
  359.     ; init the receive buffer pointer
  360.     mov     [buffptr], buff
  361.  
  362.     jmp     frcd_exit
  363.  
  364. fs001:
  365.     cmp     al, USER_USERNAME
  366.     jne     fs002
  367.  
  368.     ; This should be the password
  369.  
  370.     ; TODO validate password
  371.  
  372.     ; OK, password accepted - show they are logged in
  373.     mov     esi, loginStr2
  374.     mov     edx, loginStr2_end - loginStr2
  375.     call    outputStr
  376.  
  377.     mov     [state], USER_LOGGED_IN
  378.  
  379.     ; init the receive buffer pointer
  380.     mov     [buffptr], buff
  381.  
  382.     jmp     frcd_exit
  383.  
  384. fs002:
  385.     cmp     al, USER_LOGGED_IN
  386.     jne     fs003
  387.  
  388.     ; This should be a cmd
  389.     call    findCmd
  390.     mov     eax, [cmdPtr]
  391.     cmp     eax, 0
  392.  
  393.     je      fs002b
  394.  
  395.     call    [cmdPtr]
  396.  
  397. fs002a:
  398.     ; init the receive buffer pointer
  399.     mov     [buffptr], buff
  400.  
  401.     jmp     frcd_exit
  402.  
  403. fs002b:
  404.     ; an unsupported command was entered.
  405.     ; Tell user that the command is not supported
  406.  
  407.     mov     esi, unsupStr
  408.     mov     edx, unsupStr_end - unsupStr
  409.     call    outputStr
  410.  
  411.     jmp     fs002a
  412.  
  413. fs003:
  414. frcd_exit:
  415.     ret
  416.  
  417.  
  418.  
  419. ;***************************************************************************
  420. ;   Function
  421. ;      outputStr
  422. ;
  423. ;   Description
  424. ;       Sends a string over the 'Command' socket
  425. ;
  426. ;   Inputs
  427. ;       String in esi
  428. ;       Length in edx
  429. ;
  430. ;***************************************************************************
  431. outputStr:
  432.     push    esi
  433.     push    edx
  434.     mov     eax,53
  435.     mov     ebx,7
  436.     mov     ecx,[CmdSocket]
  437.     mcall
  438.     pop     edx
  439.     pop     esi
  440.  
  441.     cmp     eax, 0
  442.     je      os_exit
  443.  
  444.     ; The TCP/IP transmit queue is full; Wait a bit, then retry
  445.     pusha
  446.     mov     eax,5
  447.     mov     ebx,1                 ; Delay for up 10ms
  448.     mcall
  449.     popa
  450.     jmp     outputStr
  451. os_exit:
  452.     ret
  453.  
  454.  
  455.  
  456. ;***************************************************************************
  457. ;   Function
  458. ;      outputDataStr
  459. ;
  460. ;   Description
  461. ;       Sends a string over the 'Data' socket
  462. ;
  463. ;   Inputs
  464. ;       String in esi
  465. ;       Length in edx
  466. ;
  467. ;***************************************************************************
  468. outputDataStr:
  469.     push    esi
  470.     push    edx
  471.     mov     eax,53
  472.     mov     ebx,7
  473.     mov     ecx,[DataSocket]
  474.     mcall
  475.     pop     edx
  476.     pop     esi
  477.  
  478.     cmp     eax, 0
  479.     je      ods_exit
  480.  
  481.     ; The TCP/IP transmit queue is full; Wait a bit, then retry
  482.     pusha
  483.     mov     eax,5
  484.     mov     ebx,1                 ; Delay for up 10ms
  485.     mcall
  486.     popa
  487.     jmp     outputDataStr
  488. ods_exit:
  489.     ret
  490.  
  491.  
  492.  
  493. ;***************************************************************************
  494. ;   Function
  495. ;      printChar
  496. ;
  497. ;   Description
  498. ;       Writes a character to the screen; Used to display the data coming
  499. ;       in from the user. Really only useful for debugging.
  500. ;
  501. ;   Inputs
  502. ;       Character in bl
  503. ;
  504. ;***************************************************************************
  505. printChar:
  506.     cmp     bl,13                          ; BEGINNING OF LINE
  507.     jne     nobol
  508.     mov     ecx,[pos]
  509.     add     ecx,1
  510. boll1:
  511.     sub     ecx,1
  512.     mov     eax,ecx
  513.     xor     edx,edx
  514.     mov     ebx,80
  515.     div     ebx
  516.     cmp     edx,0
  517.     jne     boll1
  518.     mov     [pos],ecx
  519.     jmp     newdata
  520. nobol:
  521.  
  522.     cmp     bl,10                            ; LINE DOWN
  523.     jne     nolf
  524. addx1:
  525.     add     [pos],dword 1
  526.     mov     eax,[pos]
  527.     xor     edx,edx
  528.     mov     ecx,80
  529.     div     ecx
  530.     cmp     edx,0
  531.     jnz     addx1
  532.     mov     eax,[pos]
  533.     jmp     cm1
  534. nolf:
  535.  
  536.     cmp     bl,8                            ; BACKSPACE
  537.     jne     nobasp
  538.     mov     eax,[pos]
  539.     dec     eax
  540.     mov     [pos],eax
  541.     mov     [eax+text],byte 32
  542.     mov     [eax+text+60*80],byte 0
  543.     jmp     newdata
  544. nobasp:
  545.  
  546.     cmp     bl,15                           ; CHARACTER
  547.     jbe     newdata
  548. putcha:
  549.     mov     eax,[pos]
  550.     mov     [eax+text],bl
  551.     mov     eax,[pos]
  552.     add     eax,1
  553. cm1:
  554.     mov     ebx,[scroll+4]
  555.     imul    ebx,80
  556.     cmp     eax,ebx
  557.     jb      noeaxz
  558.     mov     esi,text+80
  559.     mov     edi,text
  560.     mov     ecx,ebx
  561.     cld
  562.     rep     movsb
  563.     mov     eax,ebx
  564.     sub     eax,80
  565. noeaxz:
  566.     mov     [pos],eax
  567. newdata:
  568.     ret
  569.  
  570.  
  571. ;***************************************************************************
  572. ;   Function
  573. ;      disconnect
  574. ;
  575. ;   Description
  576. ;       Closes the command socket
  577. ;
  578. ;   Inputs
  579. ;       None
  580. ;
  581. ;***************************************************************************
  582. disconnect:
  583.     mov     eax, 53         ; Stack Interface
  584.     mov     ebx,8           ; Close TCP socket
  585.     mov     ecx,[CmdSocket]
  586.     mcall
  587.     ret
  588.  
  589.  
  590.  
  591. ;***************************************************************************
  592. ;   Function
  593. ;      disconnectData
  594. ;
  595. ;   Description
  596. ;       Closes the data socket
  597. ;
  598. ;   Inputs
  599. ;       None
  600. ;
  601. ;***************************************************************************
  602. disconnectData:
  603.     ; This delay would be better done by allowing the socket code
  604.     ; to wait for all data to pass through the stack before closing
  605.     pusha
  606.     mov     eax,5
  607.     mov     ebx,10          ; Delay for 100ms
  608.     mcall
  609.     popa
  610.  
  611.     mov     eax, 53         ; Stack Interface
  612.     mov     ebx,8           ; Close TCP socket
  613.     mov     ecx,[DataSocket]
  614.     mcall
  615.     ret
  616.  
  617.  
  618.  
  619.  
  620. ;***************************************************************************
  621. ;   Function
  622. ;      connect
  623. ;
  624. ;   Description
  625. ;       Opens the command socket
  626. ;
  627. ;   Inputs
  628. ;       None
  629. ;
  630. ;***************************************************************************
  631. connect:
  632.     pusha
  633.  
  634.     mov     eax, 53     ; Stack Interface
  635.     mov     ebx, 5      ; Open TCP socket
  636.     mov     esi, 0      ; No remote IP address
  637.     mov     edx, 0      ; No remote port
  638.     mov     ecx, 21     ; ftp command port id
  639.     mov     edi, 0      ; passive open
  640.     mcall
  641.     mov     [CmdSocket], eax
  642.  
  643.     popa
  644.  
  645.     ret
  646.  
  647.  
  648.  
  649. ;***************************************************************************
  650. ;   Function
  651. ;      connectData
  652. ;
  653. ;   Description
  654. ;       Opens the data socket
  655. ;
  656. ;   Inputs
  657. ;       None
  658. ;
  659. ;***************************************************************************
  660. connectData:
  661.     pusha
  662.  
  663.     mov     eax, 53     ; Stack Interface
  664.     mov     ebx, 5      ; Open TCP socket
  665.     mov     esi, [DataIP]      ; remote IP address
  666.     mov     edx, [DataPort]    ; remote port
  667.     mov     ecx, 0      ; ftp data port id
  668.     mov     edi, 1      ; active open
  669.     mcall
  670.     mov     [DataSocket], eax
  671.  
  672.     popa
  673.  
  674.     ret
  675.  
  676.  
  677.  
  678.  
  679. ;***************************************************************************
  680. ;   Function
  681. ;      findCmd
  682. ;
  683. ;   Description
  684. ;       Scans the command string for a valid command. The command string
  685. ;       is in the global variable buff.
  686. ;
  687. ;       Returns result in cmdPtr. This will be zero if none found
  688. ;
  689. ;   Inputs
  690. ;       None
  691. ;
  692. ;***************************************************************************
  693. findCmd:
  694.     ; Setup to return 'none' in cmdPtr, if we find no cmd
  695.     mov     eax, 0
  696.     mov     [cmdPtr], eax
  697.     cld
  698.     mov     esi, buff
  699.     mov     edi, CMDList
  700.  
  701. fc000:
  702.     cmp     [edi], byte 0   ; Are we at the end of the CMDList?
  703.     je      fc_exit
  704.  
  705. fc000a:
  706.     cmpsb
  707.  
  708.     je      fc_nextbyte
  709.  
  710.     ; Command is different - move to the next entry in cmd table
  711.     mov     esi, buff
  712.  
  713. fc001:
  714.     ; skip to the next command in the list
  715.     cmp     [edi], byte 0
  716.     je      fc002
  717.     inc     edi
  718.     jmp     fc001
  719. fc002:
  720.     add     edi, 5
  721.     jmp     fc000
  722.  
  723. fc_nextbyte:
  724.     ; Have we reached the end of the CMD text?
  725.     cmp     [edi], byte 0
  726.     je      fc_got      ; Yes - so we have a match
  727.     jmp     fc000a      ; No - loop back
  728.  
  729. fc_got:
  730.     ; Copy the function pointer for the selected command
  731.     inc     edi
  732.     mov     eax, [edi]
  733.     mov     [cmdPtr], eax
  734.  
  735. fc_exit:
  736.     ret
  737.  
  738.  
  739.  
  740. ;***************************************************************************
  741. ;   Function
  742. ;      decStr2Byte
  743. ;
  744. ;   Description
  745. ;       Converts the decimal string pointed to by esi to a byte
  746. ;
  747. ;   Inputs
  748. ;       string ptr in esi
  749. ;
  750. ;   Outputs
  751. ;       esi points to next character not in string
  752. ;       eax holds result ( 0..255)
  753. ;
  754. ;***************************************************************************
  755. decStr2Byte:
  756.     xor     eax, eax
  757.     xor     ebx, ebx
  758.     mov     ecx, 3
  759.  
  760. dsb001:
  761.     mov     bl, [esi]
  762.  
  763.     cmp     bl, '0'
  764.     jb      dsb_exit
  765.     cmp     bl, '9'
  766.     ja      dsb_exit
  767.  
  768.     imul    eax, 10
  769.     add     eax, ebx
  770.     sub     eax, '0'
  771.     inc     esi
  772.     loop    dsb001
  773.  
  774. dsb_exit:
  775.     ret
  776.  
  777.  
  778.  
  779. ;***************************************************************************
  780. ;   Function
  781. ;      parsePortStr
  782. ;
  783. ;   Description
  784. ;       Converts the parameters of the PORT command, and stores them in the
  785. ;       appropriate variables.
  786. ;
  787. ;   Inputs
  788. ;       None ( string in global variable buff )
  789. ;
  790. ;   Outputs
  791. ;       None
  792. ;
  793. ;***************************************************************************
  794. parsePortStr:
  795.     ; skip past the PORT text to get the the parameters. The command format
  796.     ; is
  797.     ; PORT i,i,i,i,p,p,0x0d,0x0a
  798.     ; where i and p are decimal byte values, high byte first.
  799.     xor     eax, eax
  800.     mov     [DataIP], eax
  801.     mov     [DataPort], eax
  802.     mov     esi, buff + 4       ; Start at first space character
  803.  
  804. pps001:
  805.     cmp     [esi], byte ' '     ; Look for first non space character
  806.     jne     pps002
  807.     inc     esi
  808.     jmp     pps001
  809.  
  810. pps002:
  811.     call    decStr2Byte
  812.     add     [DataIP], eax
  813.     ror     dword [DataIP], 8
  814.     inc     esi
  815.     call    decStr2Byte
  816.     add     [DataIP], eax
  817.     ror     dword [DataIP], 8
  818.     inc     esi
  819.     call    decStr2Byte
  820.     add     [DataIP], eax
  821.     ror     dword [DataIP], 8
  822.     inc     esi
  823.     call    decStr2Byte
  824.     add     [DataIP], eax
  825.     ror     dword [DataIP], 8
  826.     inc     esi
  827.     call    decStr2Byte
  828.     add     [DataPort], eax
  829.     shl     [DataPort], 8
  830.     inc     esi
  831.     call    decStr2Byte
  832.     add     [DataPort], eax
  833.  
  834.     ret
  835.  
  836.  
  837.  
  838. ;***************************************************************************
  839. ;   Function
  840. ;      sendDir
  841. ;
  842. ;   Description
  843. ;       Transmits the directory listing over the data connection.
  844. ;       The data connection is already open.
  845. ;
  846. ;   Inputs
  847. ;       None
  848. ;
  849. ;   Outputs
  850. ;       None
  851. ;
  852. ;***************************************************************************
  853. sendDir:
  854.         mov     eax, text+0x4000
  855.         mov     [fsize], eax
  856.         mov     ebx, dirinfoblock
  857.         and     dword [ebx+4], 0        ; start from zero block
  858. sd001:
  859. ; Read the next DirBlocksPerCall (=16) blocks
  860.         mov     eax, 70
  861.         mcall
  862. ; Did we read anything?
  863.         test    eax, eax
  864.         jz      @f
  865.         cmp     eax, 6
  866.         jnz     sd_exit
  867. @@:
  868.         test    ebx, ebx
  869.         jz      sd_exit
  870. ; Parse these blocks. There could be up to 16 files specified
  871.         mov     esi, text + 0x1300 + 0x20
  872. sd002:
  873.         dec     ebx
  874.         js      sd004
  875.         push    ebx
  876. ; OK, lets parse the entry. Ignore volume entries
  877.         test    byte [esi], 8
  878.         jnz     sd003
  879. ; Valid file or directory. Start to compose the string we will send
  880.         mov     edi, dirStr
  881. ; If we have been called as a result of an NLST command, we only display
  882. ; the filename
  883.         cmp     [buff], byte 'N'
  884.         jz      sd006
  885.  
  886.         mov     [edi], byte '-'
  887.         test    byte [esi], 10h
  888.         jz      @f
  889.         mov     [edi], byte 'd'
  890. @@:
  891. ; Ok, now copy across the directory listing text that will be constant
  892. ; ( I dont bother looking at the read only or archive bits )
  893.  
  894.         mov     ebx, tmplStr
  895. @@:
  896.         inc     edi
  897.         mov     al, [ebx]
  898.         test    al, al
  899.         jz      @f
  900.         mov     [edi], al
  901.         inc     ebx
  902.         jmp     @b
  903. @@:
  904. ; point to the last character of the string;
  905. ; We will write the file size here, backwards
  906.         push    edi             ; Remember where the string ends
  907.  
  908.         dec     edi
  909. ; eax holds the number
  910.         mov     eax, [esi+32]
  911.         mov     ebx, 10
  912. @@:
  913.         xor     edx, edx
  914.         div     ebx
  915.         add     dl, '0'
  916.         mov     [edi], dl
  917.         dec     edi
  918.         test    eax, eax
  919.         jnz     @b
  920.  
  921.         pop     edi
  922. ; now create the time & date fields
  923. ;timeStr:            db ' Jan 1    2000 ',0
  924.         mov     al, ' '
  925.         stosb
  926.         movzx   eax, byte [esi+28+1]
  927.         mov     eax, dword [months + (eax-1)*4]
  928.         stosd
  929.         mov     al, byte [esi+28]
  930.         aam
  931.         test    ah, ah
  932.         jz      sd005a
  933.         xchg    al, ah
  934.         add     ax, '00'
  935.         jmp     sd005b
  936. sd005a:
  937.         add     al, '0'
  938.         mov     ah, ' '
  939. sd005b:
  940.         stosw
  941.         mov     al, ' '
  942.         mov     ecx, 6
  943.         rep     stosb
  944.         push    edi
  945.         movzx   eax, word [esi+28+2]
  946. @@:
  947.         xor     edx, edx
  948.         div     ebx
  949.         add     dl, '0'
  950.         mov     [edi], dl
  951.         dec     edi
  952.         test    eax, eax
  953.         jnz     @b
  954.         pop     edi
  955.         inc     edi
  956.         mov     al, ' '
  957.         stosb
  958. sd006:
  959. ; ** End of copying
  960.  
  961. ; now copy the filename across
  962.         lea     ebx, [esi+40]
  963. @@:
  964.         mov     al, [ebx]
  965.         inc     ebx
  966.         test    al, al
  967.         jz      @f
  968.         stosb
  969.         jmp     @b
  970. @@:
  971. terminate:
  972. ; Now terminate the line by putting CRLF sequence in
  973.         mov     al, 0x0D
  974.         stosb
  975.         mov     al, 0x0A
  976.         stosb
  977. ; Send the completed line to the user over data socket
  978.         push    esi
  979.         push    edi
  980.         mov     esi, dirStr
  981.         mov     ecx, edi
  982.         sub     ecx, esi
  983.         mov     edi, [fsize]
  984.         cld
  985.         rep     movsb
  986.         mov     [fsize], edi
  987.         cmp     edi, text+0x4400
  988.         jb      @f
  989.         mov     esi, text+0x4000
  990.         mov     edx, [fsize]
  991.         sub     edx, esi
  992.         mov     [fsize], esi
  993.         call    outputDataStr
  994.  
  995. @@:
  996.         pop     edi
  997.         pop     esi
  998.  
  999. sd003:                  ; Move to next entry in the block
  1000.         pop     ebx
  1001.         add     esi, 304
  1002.         jmp     sd002
  1003. sd004:
  1004.         mov     ebx, dirinfoblock
  1005.         add     dword [ebx+4], DirBlocksPerCall
  1006.         jmp     sd001
  1007.  
  1008. sd_exit:
  1009.         mov     esi, text+0x4000
  1010.         mov     edx, [fsize]
  1011.         sub     edx, esi
  1012.         call    outputDataStr
  1013.         ret
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019. ;***************************************************************************
  1020. ;   Function
  1021. ;      setupFilePath
  1022. ;
  1023. ;   Description
  1024. ;       Copies the file name from the input request string into the
  1025. ;       file descriptor
  1026. ;
  1027. ;   Inputs
  1028. ;       None
  1029. ;
  1030. ;   Outputs
  1031. ;       None
  1032. ;
  1033. ;***************************************************************************
  1034. setupFilePath:
  1035.     mov     esi, buff + 4       ; Point to (1 before) first character of file
  1036.  
  1037.     ; Skip any trailing spaces or / character
  1038. sfp001:
  1039.     inc     esi
  1040.     cmp     [esi], byte ' '
  1041.     je      sfp001
  1042.     cmp     [esi], byte '/'
  1043.     je      sfp001
  1044.  
  1045.     ; esi points to start of filename.
  1046.     cld
  1047.     push    esi
  1048.  
  1049.     ; Copy across the directory path '/'
  1050.     ; into the fileinfoblock
  1051.     mov     esi, dirpath
  1052.     mov     edi, filename
  1053. sfp003:
  1054.     movsb
  1055.     cmp     [esi], byte 0
  1056.     jne     sfp003
  1057.     mov     al, '/'
  1058.     stosb
  1059.     pop     esi
  1060.  
  1061.     ; Copy across the filename
  1062. sfp002:
  1063.     movsb
  1064.     cmp     [esi], byte 0x0d
  1065.     jne     sfp002
  1066.     mov     [edi], byte 0
  1067.     ret
  1068.  
  1069.  
  1070.  
  1071.  
  1072. ;***************************************************************************
  1073. ;   Function
  1074. ;      sendFile
  1075. ;
  1076. ;   Description
  1077. ;       Transmits the requested file over the open data socket
  1078. ;       The file to send is named in the buff string
  1079. ;
  1080. ;   Inputs
  1081. ;       None
  1082. ;
  1083. ;   Outputs
  1084. ;       None
  1085. ;
  1086. ;***************************************************************************
  1087. sendFile:
  1088.     call    setupFilePath
  1089.  
  1090.     ; init fileblock descriptor, for file read
  1091.     mov     ebx, fileinfoblock
  1092.     and     dword [ebx], 0 ; read cmd
  1093.     and     dword [ebx+4], 0 ; first block
  1094.     mov     dword [ebx+12], 0x400 ; block size
  1095.  
  1096. sf002a:
  1097.     ; now read the file..
  1098.     mov     eax,70
  1099.     mcall
  1100.     test    eax, eax
  1101.     jz      @f
  1102.     cmp     eax, 6
  1103.     jnz     sf_exit
  1104. @@:
  1105.     push    eax
  1106.     mov     esi, text + 0x1300
  1107.     mov     edx, ebx
  1108.     call    outputDataStr
  1109.     pop     eax
  1110.     test    eax, eax
  1111.     jnz     sf_exit
  1112. ; wait a bit
  1113.     mov     eax, 5
  1114.     mov     ebx, 1
  1115.     mcall
  1116.     mov     ebx, fileinfoblock
  1117.     add     dword [ebx+4], edx
  1118.     jmp     sf002a
  1119.  
  1120. sf_exit:
  1121.     ret
  1122.  
  1123.  
  1124. ;***************************************************************************
  1125. ;   Function
  1126. ;      getFile
  1127. ;
  1128. ;   Description
  1129. ;       Receives the specified file over the open data socket
  1130. ;       The file to receive is named in the buff string
  1131. ;
  1132. ;   Inputs
  1133. ;       None
  1134. ;
  1135. ;   Outputs
  1136. ;       None
  1137. ;
  1138. ;***************************************************************************
  1139. getFile:
  1140.     call    setupFilePath
  1141.  
  1142.     ; init fileblock descriptor, for file write
  1143.     xor     eax, eax
  1144.     mov     [fsize], eax            ; Start filelength at 0
  1145.     mov     [fileinfoblock+4], eax    ; set to 0
  1146.     inc     eax
  1147.     inc     eax
  1148.     mov     [fileinfoblock], eax    ; write cmd
  1149.  
  1150.     ; Read data from the socket until the socket closes
  1151.     ; loop
  1152.     ;   loop
  1153.     ;     read byte from socket
  1154.     ;     write byte to file buffer
  1155.     ;   until no more bytes in socket
  1156.     ;   sleep 100ms
  1157.     ; until socket no longer connected
  1158.     ; write file to ram
  1159.  
  1160. gf000:
  1161.     mov     eax, 53
  1162.     mov     ebx, 2                  ; Get # of bytes in input queue
  1163.     mov     ecx, [DataSocket]
  1164.     mcall
  1165.     test    eax, eax
  1166.     je      gf_sleep
  1167.  
  1168.     mov     eax, 53
  1169.     mov     ebx, 11                 ; Get bytes from socket
  1170.     mov     ecx, [DataSocket]
  1171.     mov     edx, text + 0x1300
  1172.     add     edx, dword [fsize]
  1173.     xor     esi, esi
  1174.     mcall                           ; returned data len in eax
  1175.     add     dword [fsize], eax
  1176.  
  1177.     jmp     gf000
  1178.  
  1179. gf_sleep:
  1180.     ; Check to see if socket closed...
  1181.     mov     eax,53
  1182.     mov     ebx,6               ; Get socket status
  1183.     mov     ecx,[DataSocket]
  1184.     mcall
  1185.  
  1186.     cmp     eax, 7
  1187.     jne     gf001               ; still open, so just sleep a bit
  1188.  
  1189.     ; Finished, so write the file
  1190.     mov     eax, [fsize]
  1191.     mov     [fileinfoblock+12], eax
  1192.     mov     eax,70
  1193.     mov     ebx,fileinfoblock
  1194.     mcall
  1195.  
  1196.     ret                         ; Finished
  1197.  
  1198. gf001:
  1199.     ; wait a bit
  1200.     mov     eax,5
  1201.     mov     ebx,1               ; Delay for up 10ms
  1202.     mcall
  1203.     jmp     gf000               ; try for more data
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209. ;***************************************************************************
  1210. ;   COMMAND HANDLERS FOLLOW
  1211. ;
  1212. ;   These handlers implement the functionality of each supported FTP Command
  1213. ;
  1214. ;***************************************************************************
  1215.  
  1216. cmdPWD:
  1217.     cld
  1218.     mov     edi, text+0x1300
  1219.  
  1220.     mov     esi, curdir_1
  1221.     mov     ecx, curdir_2-curdir_1
  1222.     rep     movsb
  1223.  
  1224.     mov     esi, [curdirptr]
  1225.     cmp     [esi], byte 0
  1226.     jne     cpwd_000
  1227.     mov     al, '/'
  1228.     stosb
  1229.     jmp     cpwd_001
  1230.  
  1231. cpwd_000:
  1232.     movsb
  1233.     cmp     [esi], byte 0
  1234.     jne     cpwd_000
  1235.  
  1236. cpwd_001:
  1237.     mov     esi, curdir_2
  1238.     mov     ecx, curdir_end-curdir_2
  1239.     rep     movsb
  1240.  
  1241.     ; OK, show the directory name text
  1242.     mov     esi, text+0x1300
  1243.     mov     edx, edi
  1244.     sub     edx, esi
  1245.     call    outputStr
  1246.  
  1247.     ret
  1248.  
  1249.  
  1250. cmdCWD:
  1251.     lea     esi, [buff+4]
  1252.     mov     edi, [curdirptr]
  1253.     mov     ecx, -1
  1254.     xor     eax, eax
  1255.     repne   scasb
  1256.     dec     edi
  1257.     cmp     [esi], word '..'
  1258.     je      ccwd_002
  1259.     test    [esi], byte 0xE0
  1260.     je      ccwd_000
  1261.     push    edi
  1262.     mov     al, '/'
  1263.     stosb
  1264. @@:
  1265.     movsb
  1266.     cmp     [esi], byte 0xD
  1267.     jne     @b
  1268.     xor     al, al
  1269.     stosb
  1270.  
  1271.     mov     eax, 70
  1272.     mov     ebx, dirinfoblock
  1273.     and     dword [ebx+4], 0
  1274.     mcall
  1275.     pop     edi
  1276.     test    eax, eax
  1277.     je      @f
  1278.     cmp     eax, 6
  1279.     jne     ccwd_000
  1280. @@:
  1281.     test    ebx, ebx
  1282.     je      ccwd_000
  1283.     mov     esi, text + 0x1300 + 0x20
  1284.  
  1285.     mov     al, byte [esi]
  1286.     and     al, 0x18
  1287.     cmp     al, 0x10
  1288.     jne     ccwd_000
  1289.  
  1290. ccwd_ok:
  1291.     ; OK, show the directory name text
  1292.     mov     esi, chdir
  1293.     mov     edx, chdir_end - chdir
  1294.     jmp     ccwd_001
  1295.  
  1296. ccwd_002:
  1297.     dec     edi
  1298.     cmp     byte [edi], '/'
  1299.     je      ccwd_003
  1300.     cmp     edi, [curdirptr]
  1301.     ja      ccwd_002
  1302.     jmp     ccwd_ok
  1303. ccwd_003:
  1304.     mov    byte [edi], 0
  1305.     jmp     ccwd_ok
  1306.  
  1307. ccwd_000:
  1308.     mov    byte [edi], 0
  1309.     ; Tell user there is no such directory
  1310.     mov     esi, noFileStr
  1311.     mov     edx, noFileStr_end - noFileStr
  1312.  
  1313. ccwd_001:
  1314.     call    outputStr
  1315.  
  1316.     ret
  1317.  
  1318.  
  1319. cmdQUIT:
  1320.     ; The remote end will do the close; We just
  1321.     ; say goodbye.
  1322.     mov     esi, byeStr
  1323.     mov     edx, byeStr_end - byeStr
  1324.     call    outputStr
  1325.     ret
  1326.  
  1327.  
  1328. cmdABOR:
  1329.  
  1330.     ; Close port
  1331.     call    disconnectData
  1332.  
  1333.     mov     esi, abortStr
  1334.     mov     edx, abortStr_end - abortStr
  1335.     call    outputStr
  1336.  
  1337.     ret
  1338.  
  1339. cmdPORT:
  1340.     ; TODO
  1341.     ; Copy the IP and port values to DataIP and DataPort
  1342.  
  1343.     call    parsePortStr
  1344.  
  1345.     ; Indicate the command was accepted
  1346.     mov     esi, cmdOKStr
  1347.     mov     edx, cmdOKStr_end - cmdOKStr
  1348.     call    outputStr
  1349.     ret
  1350.  
  1351. cmdnoop:
  1352.     ; Indicate the command was accepted
  1353.     mov     esi, cmdOKStr
  1354.     mov     edx, cmdOKStr_end - cmdOKStr
  1355.     call    outputStr
  1356.     ret
  1357.  
  1358.  
  1359. cmdTYPE:
  1360.     ; TODO
  1361.     ; Note the type field selected - reject if needed.
  1362.  
  1363.     ; Indicate the command was accepted
  1364.     mov     esi, cmdOKStr
  1365.     mov     edx, cmdOKStr_end - cmdOKStr
  1366.     call    outputStr
  1367.     ret
  1368.  
  1369. cmdsyst:
  1370.     ; Indicate the system type
  1371.     mov     esi, systStr
  1372.     mov     edx, systStr_end - systStr
  1373.     call    outputStr
  1374.     ret
  1375.  
  1376.  
  1377. cmdDELE:
  1378.     call    setupFilePath
  1379.  
  1380.     mov     ebx, fileinfoblock
  1381.     mov     dword [ebx], 8
  1382.     and     dword [ebx+4], 0
  1383.     push    dword [ebx+12]
  1384.     push    dword [ebx+16]
  1385.     and     dword [ebx+12], 0
  1386.     and     dword [ebx+16], 0
  1387.     mov     eax, 70
  1388.     mcall
  1389.     mov     ebx, fileinfoblock
  1390.     pop     dword [ebx+16]
  1391.     pop     dword [ebx+12]
  1392.  
  1393.     test    eax, eax
  1394.     jne     cmdDele_err
  1395.  
  1396.     mov     esi, delokStr
  1397.     mov     edx, delokStr_end - delokStr
  1398.     call    outputStr
  1399.  
  1400.     jmp     cmdDele_exit
  1401.  
  1402. cmdDele_err:
  1403.     mov     esi, noFileStr
  1404.     mov     edx, noFileStr_end - noFileStr
  1405.     call    outputStr
  1406.  
  1407.  
  1408. cmdDele_exit:
  1409.     ret
  1410.  
  1411.  
  1412. cmdNLST:
  1413. cmdLIST:
  1414.     ; Indicate the command was accepted
  1415.     mov     esi, startStr
  1416.     mov     edx, startStr_end - startStr
  1417.     call    outputStr
  1418.  
  1419.     call    connectData
  1420.  
  1421.     ; Wait for socket to establish
  1422.  
  1423. cl001:
  1424.     ; wait a bit
  1425.     mov     eax,5
  1426.     mov     ebx,10                ; Delay for up 100ms
  1427.     mcall
  1428.  
  1429.     ; check connection status
  1430.     mov     eax,53
  1431.     mov     ebx,6               ; Get socket status
  1432.     mov     ecx,[DataSocket]
  1433.     mcall
  1434.  
  1435.     cmp     eax, 4
  1436.     jne     cl001
  1437.  
  1438.     ; send directory listing
  1439.     call    sendDir
  1440.  
  1441.     ; Close port
  1442.     call    disconnectData
  1443.  
  1444.     mov     esi, endStr
  1445.     mov     edx, endStr_end - endStr
  1446.     call    outputStr
  1447.     ret
  1448.  
  1449. cmdRETR:
  1450.     ; Indicate the command was accepted
  1451.     mov     esi, startStr
  1452.     mov     edx, startStr_end - startStr
  1453.     call    outputStr
  1454.  
  1455.     call    connectData
  1456.  
  1457.     ; Wait for socket to establish
  1458.  
  1459. cr001:
  1460.     ; wait a bit
  1461.     mov     eax,5
  1462.     mov     ebx,10                ; Delay for up 100ms
  1463.     mcall
  1464.  
  1465.     ; check connection status
  1466.     mov     eax,53
  1467.     mov     ebx,6               ; Get socket status
  1468.     mov     ecx,[DataSocket]
  1469.     mcall
  1470.  
  1471.     cmp     eax, 4
  1472.     jne     cr001
  1473.  
  1474.     ; send data to remote user
  1475.     call    sendFile
  1476.  
  1477.     ; Close port
  1478.     call    disconnectData
  1479.  
  1480.     mov     esi, endStr
  1481.     mov     edx, endStr_end - endStr
  1482.     call    outputStr
  1483.  
  1484.  
  1485.     ret
  1486.  
  1487.  
  1488. cmdSTOR:
  1489.     ; Indicate the command was accepted
  1490.     mov     esi, storStr
  1491.     mov     edx, storStr_end - storStr
  1492.     call    outputStr
  1493.  
  1494.     call    connectData
  1495.  
  1496.     ; Wait for socket to establish
  1497.  
  1498. cs001:
  1499.     ; wait a bit
  1500.     mov     eax,5
  1501.     mov     ebx,10                ; Delay for up 100ms
  1502.     mcall
  1503.  
  1504.     ; check connection status
  1505.     mov     eax,53
  1506.     mov     ebx,6               ; Get socket status
  1507.     mov     ecx,[DataSocket]
  1508.     mcall
  1509.  
  1510.     cmp     eax, 4
  1511.     je      @f
  1512.     cmp     eax, 7
  1513.     jne     cs001
  1514. @@:
  1515.  
  1516.     ; get data file from remote user
  1517.     call    getFile
  1518.  
  1519.     mov     esi, endStr
  1520.     mov     edx, endStr_end - endStr
  1521.     call    outputStr
  1522.  
  1523.     ; Close port
  1524.     call    disconnectData
  1525.  
  1526.     ret
  1527.  
  1528.  
  1529.  
  1530. ; DATA AREA
  1531.  
  1532. ; This is the list of supported commands, and the function to call
  1533. ; The list end with a NULL.
  1534. CMDList:
  1535.                     db  'pwd',0
  1536.                     dd  cmdPWD
  1537.  
  1538.                     db  'PWD',0
  1539.                     dd  cmdPWD
  1540.  
  1541.                     db  'XPWD',0
  1542.                     dd  cmdPWD
  1543.  
  1544.                     db  'xpwd',0
  1545.                     dd  cmdPWD
  1546.  
  1547.                     db  'QUIT',0
  1548.                     dd  cmdQUIT
  1549.  
  1550.                     db  'quit',0
  1551.                     dd  cmdQUIT
  1552.  
  1553.                     db  'PORT',0
  1554.                     dd  cmdPORT
  1555.  
  1556.                     db  'port',0
  1557.                     dd  cmdPORT
  1558.  
  1559.                     db  'LIST',0
  1560.                     dd  cmdLIST
  1561.  
  1562.                     db  'list',0
  1563.                     dd  cmdLIST
  1564.  
  1565.                     db  'NLST',0
  1566.                     dd  cmdNLST
  1567.  
  1568.                     db  'nlst',0
  1569.                     dd  cmdNLST
  1570.  
  1571.                     db  'TYPE',0
  1572.                     dd  cmdTYPE
  1573.  
  1574.                     db  'type',0
  1575.                     dd  cmdTYPE
  1576.  
  1577.                     db  'syst',0
  1578.                     dd  cmdsyst
  1579.  
  1580.                     db  'noop',0
  1581.                     dd  cmdnoop
  1582.  
  1583.                     db  'CWD',0
  1584.                     dd  cmdCWD
  1585.  
  1586.                     db  'cwd',0
  1587.                     dd  cmdCWD
  1588.  
  1589.                     db  'RETR',0
  1590.                     dd  cmdRETR
  1591.  
  1592.                     db  'retr',0
  1593.                     dd  cmdRETR
  1594.  
  1595.                     db  'DELE',0
  1596.                     dd  cmdDELE
  1597.  
  1598.                     db  'dele',0
  1599.                     dd  cmdDELE
  1600.  
  1601.                     db  'stor',0
  1602.                     dd  cmdSTOR
  1603.  
  1604.                     db  'STOR',0
  1605.                     dd  cmdSTOR
  1606.  
  1607.                     db  'ABOR',0
  1608.                     dd  cmdABOR
  1609.  
  1610.                     db  'abor',0
  1611.                     dd  cmdABOR
  1612.  
  1613.                     db  0xff,0xf4,0xff,0xf2,'ABOR',0
  1614.                     dd  cmdABOR
  1615.  
  1616.                     db  0
  1617.  
  1618.  
  1619. cmdPtr              dd  0
  1620. CmdSocket           dd  0x0
  1621. CmdSocketStatus     dd  0x0
  1622. DataSocket          dd  0x0
  1623. DataSocketStatus    dd  0x0
  1624. DataPort            dd  0x00
  1625. DataIP              dd  0x00
  1626. pos                 dd  80 * 1
  1627. scroll              dd  1
  1628.                     dd  24
  1629.  
  1630. labelt              db  'FTP Server v0.1',0
  1631. contt               db  'Connected'
  1632. contlen:
  1633. discontt            db  'Disconnected'
  1634. discontlen:
  1635.  
  1636. cmdOKStr:           db  '200 Command OK',0x0d,0x0a
  1637. cmdOKStr_end:
  1638.  
  1639. loginStr0:          db  '220-  Menuet FTP Server v0.1',0x0d,0x0a
  1640.                     db  '220 Username and Password required',0x0d,0x0a
  1641. loginStr0_end:
  1642.  
  1643. loginStr1:          db  '331 Password now required',0x0d,0x0a
  1644. loginStr1_end:
  1645.  
  1646. loginStr2:          db  '230 You are now logged in.',0x0d,0x0a
  1647. loginStr2_end:
  1648.  
  1649. byeStr:             db  '221 Bye bye!',0x0d,0x0a
  1650. byeStr_end:
  1651.  
  1652. systStr:            db  '215 UNIX system type',0x0d,0x0a
  1653. systStr_end:
  1654.  
  1655. curdir_1:           db  '257 "'
  1656. curdir_2:           db  '"',0x0d,0x0a
  1657. curdir_end:
  1658.  
  1659. chdir:              db  '250 CWD command successful',0x0d,0x0a
  1660. chdir_end:
  1661.  
  1662. unsupStr:           db  '500 Unsupported command',0x0d,0x0a
  1663. unsupStr_end:
  1664.  
  1665. noFileStr:          db  '550 No such file',0x0d,0x0a
  1666. noFileStr_end:
  1667.  
  1668. delokStr:           db  '250 DELE command successful',0x0d,0x0a
  1669. delokStr_end:
  1670.  
  1671. startStr:           db  '150 Here it comes...',0x0d,0x0a
  1672. startStr_end:
  1673.  
  1674. storStr:            db  '150 Connecting for STOR',0x0d,0x0a
  1675. storStr_end:
  1676.  
  1677. endStr:             db  '226 Transfer OK, Closing connection',0x0d,0x0a
  1678. endStr_end:
  1679.  
  1680. abortStr:           db  '225 Abort successful',0x0d,0x0a
  1681. abortStr_end:
  1682.  
  1683.  ; This is the buffer used for building up a directory listing line
  1684. dirStr:             times 128 db 0
  1685.  
  1686. ; This is template string used in building up a directory listing line
  1687. tmplStr:            db 'rw-rw-rw-    1 0        0                ',0
  1688.  
  1689. months:
  1690.         dd     'Jan ','Feb ','Mar ','Apr ','May ','Jun '
  1691.         dd     'Jul ','Aug ','Sep ','Oct ','Nov ','Dec '
  1692.  
  1693. fileinfoblock:
  1694.                     dd      0x00
  1695.                     dd      0x00
  1696.                     dd      0x00
  1697.                     dd      0x200         ; bytes to read
  1698.                     dd      text + 0x1300 ; data area
  1699. filename:           times 256 db 0
  1700.  
  1701. ; The following lines define data for reading a directory block
  1702. DirBlocksPerCall = 16
  1703. dirinfoblock:
  1704.                     dd      1
  1705.                     dd      0x00
  1706.                     dd      0x00
  1707.                     dd      DirBlocksPerCall
  1708.                     dd      text + 0x1300   ; data area
  1709. ; The 'filename' for a directory listing
  1710. dirpath:            db      '/sys'
  1711.                     times 252 db 0
  1712. curdirptr:          dd      dirpath+4
  1713.  
  1714. fsize:              dd      0
  1715.  
  1716. state               db  0
  1717. buffptr             dd  0
  1718. buff:               times 256 db 0  ; Could put this after iend
  1719.  
  1720. ; Ram use at the end of the application:
  1721. ; text                  : 2400 bytes for screen memory
  1722. ; text + 0x1300          : file data area
  1723. text:
  1724. I_END:
  1725.