X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fftp.c;fp=src%2Fftp.c;h=961eea3779f8a44c7b3eebec24bae125a9c3c418;hb=c65c4562a19c45eda17d7d672afe15f5c8ce5fec;hp=59bc284cd303cb87654e7ab74c9d37bc67eef875;hpb=4577dd26b3ecbf7ccc5ff55efa991334136866e1;p=oftp diff --git a/src/ftp.c b/src/ftp.c index 59bc284..961eea3 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -17,10 +19,15 @@ #define fcntlsocket fcntl #endif +static int sendcmd(struct ftp *ftp, const char *fmt, ...); static int handle_control(struct ftp *ftp); static int handle_data(struct ftp *ftp, int s); static void proc_control(struct ftp *ftp, const char *buf); +static void cproc_pwd(struct ftp *ftp, int code, const char *buf, void *cls); +static void cproc_cwd(struct ftp *ftp, int code, const char *buf, void *cls); + + struct ftp *ftp_alloc(void) { struct ftp *ftp; @@ -129,6 +136,23 @@ int ftp_handle(struct ftp *ftp, int s) return -1; } +static int sendcmd(struct ftp *ftp, const char *fmt, ...) +{ + char buf[256]; + va_list ap; + + if(ftp->ctl < 0) { + return -1; + } + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + strcat(buf, "\r\n"); + + return send(ftp->ctl, buf, strlen(buf), 0); +} + static int handle_control(struct ftp *ftp) { int i, sz, rd; @@ -168,8 +192,59 @@ static int handle_data(struct ftp *ftp, int s) return -1; } +static int respcode(const char *resp) +{ + if(!isdigit(resp[0]) || !isdigit(resp[1]) || !isdigit(resp[2])) { + return 0; + } + + if(isspace(resp[3])) { + return atoi(resp); + } + if(resp[3] == '-') { + return -atoi(resp); + } + return 0; +} + static void proc_control(struct ftp *ftp, const char *buf) { + int code; + + while(*buf && isspace(*buf)) buf++; + + if((code = respcode(buf)) == 0) { + warnmsg("ignoring invalid response: %s\n", buf); + return; + } + if(code < 0) { + return; /* ignore continuations for now */ + } + + if(ftp->cproc) { + ftp->cproc(ftp, code, buf, ftp->cproc_cls); + ftp->cproc = 0; + return; + } + + switch(code) { + case 220: + sendcmd(ftp, "user %s", ftp->user ? ftp->user : "anonymous"); + break; + case 331: + sendcmd(ftp, "pass %s", ftp->pass ? ftp->pass : "foobar"); + break; + case 230: + ftp->status = 1; + infomsg("login successful\n"); + ftp_pwd(ftp); + ftp->modified = 1; + break; + case 530: + ftp->status = 0; + errmsg("login failed\n"); + break; + } } int ftp_update(struct ftp *ftp) @@ -177,7 +252,60 @@ int ftp_update(struct ftp *ftp) return -1; } +int ftp_pwd(struct ftp *ftp) +{ + sendcmd(ftp, "pwd"); + ftp->cproc = cproc_pwd; + return 0; +} + int ftp_chdir(struct ftp *ftp, const char *dirname) { - return -1; + // TODO queue + sendcmd(ftp, "cwd %s", dirname); + ftp->cproc = cproc_cwd; + return 0; +} + +static int get_quoted_text(const char *str, char *buf) +{ + int len; + const char *src, *end; + + if(!(src = strchr(str, '"'))) { + return -1; + } + src++; + end = src; + while(*end && *end != '"') end++; + if(!*end) return -1; + + len = end - src; + memcpy(buf, src, len); + buf[len] = 0; + return 0; +} + +static void cproc_pwd(struct ftp *ftp, int code, const char *buf, void *cls) +{ + char *dirname; + + if(code != 257) { + warnmsg("pwd failed\n"); + return; + } + + dirname = alloca(strlen(buf) + 1); + if(get_quoted_text(buf, dirname) == -1) { + warnmsg("pwd: invalid response: %s\n", buf); + return; + } + + free(ftp->curdir_rem); + ftp->curdir_rem = strdup_nf(dirname); + ftp->modified = 1; +} + +static void cproc_cwd(struct ftp *ftp, int code, const char *buf, void *cls) +{ }