Subversion Repositories Kolibri OS

Rev

Rev 4922 | Rev 6436 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2013-2014. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ftpc.asm - FTP client for KolibriOS                            ;;
  7. ;;                                                                 ;;
  8. ;;  Written by hidnplayr@kolibrios.org                             ;;
  9. ;;                                                                 ;;
  10. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  11. ;;             Version 2, June 1991                                ;;
  12. ;;                                                                 ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. format binary as ""
  16.  
  17. TIMEOUT                 = 3     ; seconds
  18.  
  19. BUFFERSIZE              = 4096
  20.  
  21. STATUS_CONNECTING       = 0
  22. STATUS_CONNECTED        = 1
  23. STATUS_NEEDPASSWORD     = 2
  24. STATUS_LOGGED_IN        = 3
  25.  
  26. OPERATION_NONE          = 0
  27. OPERATION_LIST          = 1
  28. OPERATION_RETR          = 2
  29. OPERATION_STOR          = 3
  30. OPERATION_RDIR          = 4
  31.        
  32. use32
  33. ; standard header
  34.         db      'MENUET01'      ; signature
  35.         dd      1               ; header version
  36.         dd      start           ; entry point
  37.         dd      i_end           ; initialized size
  38.         dd      mem+0x1000      ; required memory
  39.         dd      mem+0x1000      ; stack pointer
  40.         dd      buf_cmd         ; parameters
  41.         dd      path            ; path
  42.  
  43. include '../../macros.inc'
  44. purge mov,add,sub
  45. include '../../proc32.inc'
  46. include '../../dll.inc'
  47. include '../../network.inc'
  48.  
  49. include 'usercommands.inc'
  50. include 'servercommands.inc'
  51.  
  52. start:
  53. ; initialize heap for using dynamic blocks
  54.         mcall   68,11
  55.         test    eax,eax
  56.         je      exit2
  57.        
  58. ; disable all events except network event
  59.         mcall   40, EV_STACK
  60. ; load libraries
  61.         stdcall dll.Load, @IMPORT
  62.         test    eax, eax
  63.         jnz     exit
  64. ; initialize console
  65.         invoke  con_start, 1
  66.         invoke  con_init, 80, 25, 80, 250, str_title
  67. ; find path to main settings file (ftpc.ini)
  68.         mov     edi, path               ; Calculate the length of zero-terminated string
  69.         xor     al, al
  70.         mov     ecx, 1024
  71.         repne   scasb
  72.         dec     edi
  73.         mov     esi, str_ini            ; append it with '.ini', 0
  74.         movsd
  75.         movsb
  76. ; get settings from ini
  77.         invoke  ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0
  78.         mov     esi, str_active_ip
  79.   .ip_loop:
  80.         lodsb
  81.         test    al, al
  82.         jz      .ip_ok
  83.         cmp     al, ' '
  84.         je      .ip_ok
  85.         cmp     al, '.'
  86.         jne     .ip_loop
  87.         mov     byte[esi-1], ','
  88.         jmp     .ip_loop
  89.   .ip_ok:
  90.         mov     byte[esi-1], 0
  91.  
  92.         invoke  ini.get_int, path, str_active, str_port_start, 64000
  93.         mov     [acti_port_start], ax
  94.  
  95.         invoke  ini.get_int, path, str_active, str_port_stop, 65000
  96.         mov     [acti_port_stop], ax
  97.  
  98.         invoke  ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0
  99.         mcall   30, 1, buf_buffer1                      ; set working directory
  100.  
  101. ; Check for parameters, if there are some, resolve the address right away
  102. ; TODO: parse ftp://user:password@server.com:port/folder/subfolder type urls.
  103.         cmp     byte [buf_cmd], 0
  104.         jne     resolve
  105.  
  106. main:
  107. ; Clear screen
  108.         invoke  con_cls
  109. ; Welcome user
  110.         invoke  con_write_asciiz, str_welcome
  111. ; write prompt (in green color)
  112.         invoke  con_set_flags, 0x0a
  113.         invoke  con_write_asciiz, str_prompt
  114. ; read string
  115.         invoke  con_gets, buf_cmd, 256
  116. ; check for exit
  117.         test    eax, eax
  118.         jz      done
  119.         cmp     byte [buf_cmd], 10
  120.         jz      done
  121. ; reset color back to grey and print newline
  122.         invoke  con_set_flags, 0x07
  123.         invoke  con_write_asciiz, str_newline
  124.  
  125. resolve:
  126.         mov     [sockaddr1.port], 21 shl 8
  127.  
  128. ; delete terminating '\n'
  129.         mov     esi, buf_cmd
  130.   @@:
  131.         lodsb
  132.         cmp     al, ':'
  133.         je      .do_port
  134.         cmp     al, 0x20
  135.         ja      @r
  136.         mov     byte [esi-1], 0
  137.         jmp     .done
  138.  
  139.   .do_port:
  140.         xor     eax, eax
  141.         xor     ebx, ebx
  142.         mov     byte [esi-1], 0
  143.   .portloop:
  144.         lodsb
  145.         cmp     al, 0x20
  146.         jbe     .port_done
  147.         sub     al, '0'
  148.         jb      error_hostname
  149.         cmp     al, 9
  150.         ja      error_hostname
  151.         lea     ebx, [ebx*4 + ebx]
  152.         shl     ebx, 1
  153.         add     ebx, eax
  154.         jmp     .portloop
  155.  
  156.   .port_done:
  157.         xchg    bl, bh
  158.         mov     [sockaddr1.port], bx
  159.  
  160.   .done:
  161. ; Say to the user that we're resolving
  162.         invoke  con_write_asciiz, str_resolve
  163.         invoke  con_write_asciiz, buf_cmd
  164. ; resolve name
  165.         push    esp     ; reserve stack place
  166.         invoke  getaddrinfo, buf_cmd, 0, 0, esp
  167.         pop     esi
  168. ; test for error
  169.         test    eax, eax
  170.         jnz     error_resolve
  171. ; write results
  172.         invoke  con_write_asciiz, str8          ; ' (',0
  173.         mov     eax, [esi+addrinfo.ai_addr]     ; convert IP address to decimal notation
  174.         mov     eax, [eax+sockaddr_in.sin_addr] ;
  175.         mov     [sockaddr1.ip], eax             ;
  176.         invoke  inet_ntoa, eax                  ;
  177.         invoke  con_write_asciiz, eax           ; print ip
  178.         invoke  freeaddrinfo, esi               ; free allocated memory
  179.         invoke  con_write_asciiz, str9          ; ')',10,0
  180. ; open the socket
  181.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  182.         cmp     eax, -1
  183.         je      error_socket
  184.         mov     [controlsocket], eax
  185. ; connect to the server
  186.         invoke  con_write_asciiz, str_connect
  187.         mcall   connect, [controlsocket], sockaddr1, 18
  188.         cmp     eax, -1
  189.         je      error_connect
  190.         mov     [status], STATUS_CONNECTING
  191. ; Tell the user we're waiting for the server now.
  192.         invoke  con_write_asciiz, str_waiting
  193.  
  194. ; Reset 'offset' variable, it's used by the data receiver
  195.         mov     [offset], 0
  196.  
  197. wait_for_servercommand:
  198. ; Any commands still in our buffer?
  199.         cmp     [offset], 0
  200.         je      .receive                        ; nope, receive some more
  201.         mov     esi, [offset]
  202.         mov     edi, buf_cmd
  203.         mov     ecx, [size]
  204.         add     ecx, esi
  205.         jmp     .byteloop
  206.  
  207. ; receive socket data
  208.   .receive:
  209.         mcall   26, 9
  210.         add     eax, TIMEOUT*100
  211.         mov     [timeout], eax
  212.   .receive_loop:
  213.         mcall   23, 50          ; Wait for event with timeout
  214.         mcall   26, 9
  215.         cmp     eax, [timeout]
  216.         jge     error_timeout
  217.         mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT
  218.         test    eax, eax
  219.         jnz     .got_data
  220.         cmp     ebx, EWOULDBLOCK
  221.         jne     error_socket
  222.         jmp     .receive_loop
  223.  
  224.   .got_data:
  225.         mov     [offset], 0
  226.  
  227. ; extract commands, copy them to "buf_cmd" buffer
  228.         lea     ecx, [eax + buf_buffer1]         ; ecx = end pointer
  229.         mov     esi, buf_buffer1                 ; esi = current pointer
  230.         mov     edi, buf_cmd
  231.   .byteloop:
  232.         cmp     esi, ecx
  233.         jae     wait_for_servercommand
  234.         lodsb
  235.         cmp     al, 10                          ; excellent, we might have a command
  236.         je      .got_command
  237.         cmp     al, 13                          ; just ignore this byte
  238.         je      .byteloop
  239.         stosb
  240.         jmp     .byteloop
  241.   .got_command:                                 ; we have a newline check if its a command
  242.         cmp     esi, ecx
  243.         je      .no_more_data
  244.         mov     [offset], esi
  245.         sub     ecx, esi
  246.         mov     [size], ecx
  247.         jmp     .go_cmd
  248.   .no_more_data:
  249.         mov     [offset], 0
  250.   .go_cmd:
  251.         lea     ecx, [edi - buf_cmd]                  ; length of command
  252.         xor     al, al
  253.         stosb
  254.  
  255.         invoke  con_set_flags, 0x03             ; change color
  256.         invoke  con_write_asciiz, buf_cmd             ; print servercommand
  257.         invoke  con_write_asciiz, str_newline
  258.         invoke  con_set_flags, 0x07             ; reset color
  259.  
  260.         jmp     server_parser                   ; parse command
  261.  
  262.  
  263.  
  264. wait_for_usercommand:
  265.  
  266. ; Are there any files in the transfer queue?
  267.  
  268.         cmp     [queued], 0
  269.         ja      transfer_queued                 ; Yes, transfer those first.
  270.        
  271. ; change color to green for user input
  272.         invoke  con_set_flags, 0x0a
  273.  
  274. ; If we are not yet connected, request username/password
  275.         cmp     [status], STATUS_CONNECTED
  276.         je      .connected
  277.  
  278.         cmp     [status], STATUS_NEEDPASSWORD
  279.         je      .needpass
  280.  
  281. ; write prompt
  282.         invoke  con_write_asciiz, str_prompt
  283. ; read string
  284.         invoke  con_gets, buf_cmd, 256
  285.  
  286. ; print a newline and reset the color back to grey
  287.         invoke  con_write_asciiz, str_newline
  288.         invoke  con_set_flags, 0x07
  289.  
  290.         cmp     dword[buf_cmd], "cwd "
  291.         je      cmd_cwd
  292.  
  293.         cmp     dword[buf_cmd], "mkd "
  294.         je      cmd_mkd
  295.  
  296.         cmp     dword[buf_cmd], "rmd "
  297.         je      cmd_rmd
  298.  
  299.         cmp     dword[buf_cmd], "pwd" + 10 shl 24
  300.         je      cmd_pwd
  301.  
  302.         cmp     dword[buf_cmd], "bye" + 10 shl 24
  303.         je      cmd_bye
  304.  
  305.         cmp     dword[buf_cmd], "rdir"
  306.         je      cmd_rdir
  307.        
  308.         cmp     byte[buf_cmd+4], " "
  309.         jne     @f
  310.  
  311.         cmp     dword[buf_cmd], "lcwd"
  312.         je      cmd_lcwd
  313.  
  314.         cmp     dword[buf_cmd], "retr"
  315.         je      cmd_retr
  316.  
  317.         cmp     dword[buf_cmd], "stor"
  318.         je      cmd_stor
  319.  
  320.         cmp     dword[buf_cmd], "dele"
  321.         je      cmd_dele
  322.  
  323.   @@:
  324.         cmp     byte[buf_cmd+4], 10
  325.         jne     @f
  326.  
  327.         cmp     dword[buf_cmd], "list"
  328.         je      cmd_list
  329.  
  330.         cmp     dword[buf_cmd], "help"
  331.         je      cmd_help
  332.  
  333.         cmp     dword[buf_cmd], "cdup"
  334.         je      cmd_cdup
  335.  
  336.   @@:
  337. ; Uh oh.. unknown command, tell the user and wait for new input
  338.         invoke  con_write_asciiz, str_unknown
  339.         jmp     wait_for_usercommand
  340.  
  341.  
  342.   .connected:
  343. ; request username
  344.         invoke  con_write_asciiz, str_user
  345.         mov     dword[buf_cmd], "USER"
  346.         mov     byte[buf_cmd+4], " "
  347.         jmp     .send
  348.  
  349.  
  350.   .needpass:
  351. ; request password
  352.         invoke  con_write_asciiz, str_pass
  353.         mov     dword[buf_cmd], "PASS"
  354.         mov     byte[buf_cmd+4], " "
  355.         invoke  con_set_flags, 0x00             ; black text on black background for password
  356.  
  357.   .send:
  358. ; read string
  359.         mov     esi, buf_cmd+5
  360.         invoke  con_gets, esi, 256
  361.  
  362. ; find end of string
  363.         mov     edi, buf_cmd+5
  364.         mov     ecx, 256
  365.         xor     al, al
  366.         repne   scasb
  367.         lea     esi, [edi-buf_cmd]
  368.         mov     word[edi-2], 0x0a0d
  369. ; and send it to the server
  370.         mcall   send, [controlsocket], buf_cmd, , 0
  371.  
  372.         invoke  con_write_asciiz, str_newline
  373.         invoke  con_set_flags, 0x07             ; reset color
  374.         jmp     wait_for_servercommand
  375.  
  376.  
  377.  
  378. ; files for rdir operation are queued
  379. transfer_queued:
  380.  
  381.         mov     esi, [ptr_queue]                ; always pointing to current part of ptr_fname_start
  382.         mov     edi, buf_cmd+5                  ; always point to filename for retr command
  383.   .build_filename:
  384.         lodsb  
  385.         stosb
  386.         cmp     al, 10
  387.         je      .get_file                       ; filename ends with character 10
  388.         test    al, al
  389.         jnz     .build_filename
  390.  
  391.         ; Error occured, we reached the end of the buffer before [queued] reached 0
  392.         mov     [queued], 0
  393.         mcall   68, 13, [ptr_fname]             ; free buffer
  394.         test    eax, eax
  395.         jz      error_heap
  396.         jmp     wait_for_usercommand
  397.  
  398.   .get_file:
  399.         mov     byte[edi], 0                    ; end filename with 0 byte
  400.         mov     [ptr_queue], esi
  401.         dec     [queued]
  402.         jnz     cmd_retr
  403.  
  404.         mcall   68, 13, [ptr_fname]             ; free buffer
  405.         test    eax, eax
  406.         jz      error_heap
  407.         jmp     cmd_retr
  408.  
  409.  
  410.  
  411. open_dataconnection:
  412.  
  413.         test    [mode], 1
  414.         jnz     .active
  415.  
  416.         mcall   send, [controlsocket], str_PASV, str_PASV.length, 0
  417.         ret
  418.  
  419.   .active:
  420.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  421.         cmp     eax, -1
  422.         je      error_socket
  423.         mov     [datasocket], eax
  424.  
  425.         mov     ax, [acti_port_start]
  426.         xchg    al, ah
  427.         mov     [sockaddr2.port], ax
  428.  
  429.         mcall   bind, [datasocket], sockaddr2, 18
  430.         cmp     eax, -1
  431.         je      error_socket
  432.  
  433.         mcall   listen, [datasocket], 1
  434.         cmp     eax, -1
  435.         je      error_socket
  436.  
  437.         mov     dword[buf_buffer1], 'PORT'
  438.         mov     byte[buf_buffer1+4], ' '
  439.         mov     edi, buf_buffer1+5
  440.         mov     esi, str_active_ip
  441.   .loop:
  442.         lodsb
  443.         test    al, al
  444.         jz      .ip_ok
  445.         stosb
  446.         jmp     .loop
  447.   .ip_ok:
  448.         mov     al, ','
  449.         stosb
  450.         movzx   eax, byte[sockaddr2.port+0]
  451.         call    dword_ascii
  452.         mov     al, ','
  453.         stosb
  454.         movzx   eax, byte[sockaddr2.port+1]
  455.         call    dword_ascii
  456.         mov     ax, 0x0a0d
  457.         stosw
  458.         lea     esi, [edi - buf_buffer1]
  459.         mcall   send, [controlsocket], buf_buffer1, , 0
  460.  
  461.         mcall   accept, [datasocket], sockaddr2, 18        ; time to accept the awaiting connection..
  462.         cmp     eax, -1
  463.         je      error_socket
  464.         push    eax
  465.         mcall   close, [datasocket]
  466.         pop     [datasocket]
  467.  
  468.         mcall   recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0
  469.  
  470.         ret
  471.  
  472. ; eax = input
  473. ; edi = ptr where to write
  474. dword_ascii:
  475.  
  476.         push    edx ebx ecx
  477.         mov     ebx, 10
  478.         xor     ecx, ecx
  479.  
  480.        @@:
  481.         xor     edx, edx
  482.         div     ebx
  483.         add     edx, '0'
  484.         push    dx
  485.         inc     ecx
  486.         test    eax, eax
  487.         jnz     @r
  488.  
  489.        @@:
  490.         pop     ax
  491.         stosb
  492.         dec     ecx
  493.         jnz     @r
  494.  
  495.         pop     ecx ebx edx
  496.         ret
  497.  
  498. error_hostname:
  499.         invoke  con_set_flags, 0x0c                     ; print errors in red
  500.         invoke  con_write_asciiz, str_err_host
  501.         jmp     wait_for_keypress
  502.  
  503. error_connect:
  504.         invoke  con_set_flags, 0x0c                     ; print errors in red
  505.         invoke  con_write_asciiz, str_err_connect
  506.         jmp     wait_for_keypress
  507.  
  508. error_timeout:
  509.         invoke  con_set_flags, 0x0c                     ; print errors in red
  510.         invoke  con_write_asciiz, str_err_timeout
  511.         jmp     wait_for_keypress
  512.  
  513. error_socket:
  514.         invoke  con_set_flags, 0x0c                     ; print errors in red
  515.         invoke  con_write_asciiz, str_err_socket
  516.         jmp     wait_for_keypress
  517.  
  518. error_resolve:
  519.         invoke  con_set_flags, 0x0c                     ; print errors in red
  520.         invoke  con_write_asciiz, str_err_resolve
  521.         jmp     wait_for_keypress
  522.  
  523. error_heap:
  524.         invoke  con_set_flags, 0x0c                     ; print errors in red
  525.         invoke  con_write_asciiz, str_err_heap
  526.        
  527. wait_for_keypress:
  528.         invoke  con_set_flags, 0x07                     ; reset color to grey
  529.         invoke  con_write_asciiz, str_push
  530.         invoke  con_getch2
  531.         mcall   close, [controlsocket]
  532.         jmp     main
  533.  
  534. done:
  535.         invoke  con_exit, 1
  536.  
  537. exit:
  538.         mcall   close, [controlsocket]
  539. exit2:  
  540.         mcall   -1
  541.  
  542.  
  543.  
  544. ; data
  545. str_title       db 'FTP client',0
  546. str_welcome     db 'FTP client for KolibriOS v0.12',10
  547.                 db 10
  548.                 db 'Please enter ftp server address.',10,0
  549.  
  550. str_prompt      db '> ',0
  551. str_resolve     db 'Resolving ',0
  552. str_newline     db 10,0
  553. str_err_resolve db 10,'Name resolution failed.',10,0
  554. str_err_socket  db 10,'Socket error.',10,0
  555. str_err_heap    db 10,'Cannot allocate memory from heap.',10,0
  556. str_err_timeout db 10,'Timeout - no response from server.',10,0
  557. str_err_connect db 10,'Cannot connect to the server.',10,0
  558. str_err_host    db 10,'Invalid hostname.',10,0
  559. str8            db ' (',0
  560. str9            db ')',10,0
  561. str_push        db 'Push any key to continue.',0
  562. str_connect     db 'Connecting...',10,0
  563. str_waiting     db 'Waiting for welcome message.',10,0
  564. str_user        db "username: ",0
  565. str_pass        db "password: ",0
  566. str_unknown     db "Unknown command or insufficient parameters - type help for more information.",10,0
  567. str_lcwd        db "Local working directory is now: ",0
  568.  
  569. str_open        db "opening data socket",10,0
  570. str_close       db 10,"closing data socket",10,0
  571. str_dot         db '.',0
  572.  
  573. str_help        db "available commands:",10
  574.                 db 10
  575.                 db "bye             - close the connection",10
  576.                 db "cdup            - change to parent of current directory on the server",10
  577.                 db "cwd <directory> - change working directoy on the server",10
  578.                 db "dele <file>     - delete file from the server",10
  579.                 db "list            - list files and folders in current server directory",10
  580.                 db "lcwd <path>     - change local working directory",10
  581.                 db "mkd <directory> - make directory on the server",10
  582.                 db "pwd             - print server working directory",10
  583.                 db "retr <file>     - retreive file from the server",10
  584.                 db "rmd <directory> - remove directory from the server",10
  585.                 db "stor <file>     - store file on the server",10
  586.                     db "rdir            - retreive all files from current server dir",10
  587.                 db 10,0
  588.  
  589. str_ini         db '.ini', 0
  590. str_active      db 'active', 0
  591. str_port_start  db 'port_start', 0
  592. str_port_stop   db 'port_stop', 0
  593. str_ip          db 'ip', 0
  594. str_dir         db 'dir', 0
  595. str_general     db 'general', 0
  596.  
  597. queued          dd 0
  598. mode            db 0    ; passive = 0, active = 1
  599.  
  600. ; FTP strings
  601.  
  602. str_PASV        db 'PASV',13,10
  603. .length = $ - str_PASV
  604.  
  605. sockaddr1:
  606.         dw AF_INET4
  607. .port   dw ?
  608. .ip     dd ?
  609.         rb 10
  610.  
  611. sockaddr2:
  612.         dw AF_INET4
  613. .port   dw ?
  614. .ip     dd ?
  615.         rb 10
  616.  
  617. ; import
  618. align 4
  619. @IMPORT:
  620.  
  621. library network, 'network.obj', console, 'console.obj', libini, 'libini.obj'
  622.  
  623. import  network,        \
  624.         getaddrinfo,    'getaddrinfo',  \
  625.         freeaddrinfo,   'freeaddrinfo', \
  626.         inet_ntoa,      'inet_ntoa'
  627.  
  628. import  console,        \
  629.         con_start,      'START',        \
  630.         con_init,       'con_init',     \
  631.         con_write_asciiz,'con_write_asciiz',     \
  632.         con_exit,       'con_exit',     \
  633.         con_gets,       'con_gets',\
  634.         con_cls,        'con_cls',\
  635.         con_getch2,     'con_getch2',\
  636.         con_set_cursor_pos, 'con_set_cursor_pos',\
  637.         con_write_string, 'con_write_string',\
  638.         con_get_flags,  'con_get_flags', \
  639.         con_set_flags,  'con_set_flags'
  640.  
  641. import  libini,         \
  642.         ini.get_str,    'ini_get_str',\
  643.         ini.get_int,    'ini_get_int'
  644.  
  645.  
  646. i_end:
  647.  
  648. ; uninitialised data
  649.  
  650. status          db ?
  651.  
  652. controlsocket   dd ?
  653. datasocket      dd ?
  654. offset          dd ?
  655. size            dd ?
  656. operation       dd ?
  657. timeout         dd ?
  658.  
  659. ptr_fname       dd ?
  660. size_fname      dd ?
  661. ptr_queue       dd ?
  662.  
  663. acti_port_start dw ?
  664. acti_port_stop  dw ?
  665. acti_port       dw ?
  666.  
  667. str_active_ip   rb 16
  668.  
  669. filestruct:
  670.   .subfn        dd ?
  671.   .offset       dd ?
  672.                 dd ?
  673.   .size         dd ?
  674.   .ptr          dd ?
  675.   .name         rb 1024
  676.  
  677. buf_buffer1     rb BUFFERSIZE+1
  678. buf_buffer2     rb BUFFERSIZE+1
  679. buf_cmd         rb 1024                 ; buffer for holding command string
  680.  
  681. path            rb 1024
  682.  
  683. mem:
  684.