1

(moved from SO)

My goal is to upload a file to an FTP server in an embedded device. The file is a configuration file. Once the file is accepted, the server reboots. What makes this a challenge is that the embedded device leaves the socket open or otherwise does not properly terminate the FTP connection.

The server does response with response code 150 which means "accepted". Then it reboots, but leaves the socket open.

I'm looking for a solution. One solution is to hand-code an FTP client in C, another is to use the built-in FTP client in UNIX via Bash script. In the comments below, someone suggested curl or wget/wput.

First Attempt

In my first attempt, I considered writing an FTP client in C. Is there a lib that I can use? Looking around, I see a lot of junky libs, but maybe I'm missing a good one.

Second Attempt

In another attempt, I tried to use a Bash script to operate the FTP client.

The following program uploads the file, but then it hangs

#!/bin/bash
HOST=192.168.1.10
USER='blah'
PASSWD='blah'
FILE='file1.conf'

ftp -n -i -v $HOST << EOT
ascii
user $USER $PASSWD
put $FILE myconfig.conf
bye
EOT

This is what it says:

Connected to 192.168.1.10 (192.168.1.10).
220 FTP server ready.
530 access denied.
331 Password required.
230 User logged in.
local: somefile.txt remote: newname.txt
227 Entering Passive Mode (192,168,1,10,208,169)
150 ready to take file.
150 Accepting XML configuration file for upload.
818 bytes sent in 4.1e-05 secs (19951.22 Kbytes/sec)
<it hangs here>

If I push Ctrl-Z it quits. If I sent Ctrl-C or Ctrl-X, it does not quite. And when I do Ctrl-Z, it leaves the child process hanging around and I have to execute jobs -p | xargs kill -9 to clean up.

Third Attempt

Next, I tried the curl idea:

$ curl -T file1.xml ftp://username:password@192.168.1.10/myfile.conf -v

Here is the response:

*   Trying 192.168.1.10...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 192.168.1.10 (192.168.1.10) port 21 (#0)
< 220 FTP server ready.
> USER admin
< 331 Password required.
> PASS PASS
< 230 User logged in.
> PWD
< 257 "/" is current directory
* Entry path is '/'
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 500 command not supported.
* Failed EPSV attempt. Disabling EPSV
> PASV
< 227 Entering Passive Mode (192,168,1,10,96,232)
*   Trying 192.168.1.10...
* Connecting to 192.168.1.10 (192.168.1.10) port 24808
* Connected to 192.168.1.10 (192.168.1.10) port 21 (#0)
> TYPE I
< 200 command okay
> STOR myfile.conf
< 150 ready to take file.
} [583 bytes data]
* We are completely uploaded and fine
* Remembering we are in dir ""
< 150 Accepting XML configuration file for upload.
* server did not report OK, got 150
100   583    0     0  100   583      0   4827 --:--:-- --:--:-- --:--:--  4858
* Connection #0 to host 192.168.1.10 left intact
curl: (18) server did not report OK, got 150

This was a little better. When I kill curl, it doesn't leave stuff hanging around like the ftp client does.

Fourth Attempt

In this attempt, I tried wput. Much to my surprise, I received a Segmention Fault.

wput file1.conf ftp://username:password@192.168.1.10/myconfig.conf
--09:37:50-- `file1.conf'
    => ftp://admin:xxxxx@192.168.1.10:21/myconfig.conf
Connecting to 192.168.1.10:21... connected! 
Logging in as admin ... Logged in!
==> LIST ... done.
Segmentation fault (core dumped)
  • 1
    have you tried lftp? – DopeGhoti Jan 30 '17 at 16:54
3

expect can detect the bytes sent line and at that point exit the script:

#!/usr/bin/env expect

set HOST 192.168.1.10
set USER blah
set PASSWD blah
set FILE file1.conf

spawn -noecho ftp -n -i -v $HOST
# TODO possibly some error checking or prompt detection here...
send "ascii\r"
send "user $USER $PASSWD\r"
send "put $FILE myconfig.conf\r"
send "bye\r"
set timeout 60
expect {
    # if paranoid confirm that the amount matches the size of file...
    -ex "bytes sent" { exit }
    timeout { exit 1 }
    eof { exit 1 }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.