foo
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 21 Jan 2023 05:56:50 +0000 (07:56 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 21 Jan 2023 05:56:50 +0000 (07:56 +0200)
src/ftp.c
src/ftp.h
src/main.c
src/tui.c
src/tui.h
src/unix/tgfx.c

index 59bc284..961eea3 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1,7 +1,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdarg.h>
 #include <errno.h>
+#include <ctype.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #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)
+{
 }
index 2d69ce7..c9ebbe2 100644 (file)
--- a/src/ftp.h
+++ b/src/ftp.h
@@ -3,6 +3,22 @@
 
 enum {FTP_DIR, FTP_FILE};      /* ftp_dirent type */
 
+enum {
+       FTP_PWD,
+       FTP_CHDIR,
+       FTP_MKDIR,
+       FTP_RMDIR,
+       FTP_DEL,
+       FTP_LIST,
+       FTP_RETR,
+       FTP_STORE
+};
+
+struct ftp_op {
+       int op;
+       char *arg;
+};
+
 struct ftp_dirent {
        char *name;
        int type;
@@ -11,19 +27,30 @@ struct ftp_dirent {
 struct ftp {
        int ctl, data;  /* sockets */
 
+       int status;
+       char *user, *pass;
+
+       void (*cproc)(struct ftp *ftp, int code, const char *buf, void *cls);
+       void (*dproc)(struct ftp *ftp, const char *buf, int sz, void *cls);
+       void *cproc_cls, *dproc_cls;
+
        char crecv[256];
        int num_crecv;
        char drecv[256];
        int num_drecv;
 
-       char *cwd;
+       char *curdir_rem, *curdir_loc;
        struct ftp_dirent *dent;
        int num_dent;
+
+       int modified;
 };
 
 struct ftp *ftp_alloc(void);
 void ftp_free(struct ftp *ftp);
 
+void ftp_auth(const char *user, const char *pass);
+
 int ftp_connect(struct ftp *ftp, const char *host, int port);
 void ftp_close(struct ftp *ftp);
 
@@ -33,6 +60,7 @@ int ftp_pending(struct ftp *ftp);
 int ftp_handle(struct ftp *ftp, int s);
 
 int ftp_update(struct ftp *ftp);
+int ftp_pwd(struct ftp *ftp);
 int ftp_chdir(struct ftp *ftp, const char *dirname);
 
 
index 611508d..c2820ba 100644 (file)
@@ -1,3 +1,5 @@
+#include <stdio.h>
+#include <string.h>
 #include <signal.h>
 #include <errno.h>
 #include <sys/select.h>
@@ -6,6 +8,7 @@
 #include "tui.h"
 #include "ftp.h"
 
+void updateui(void);
 int proc_input(void);
 int keypress(int key);
 
@@ -79,6 +82,11 @@ int main(void)
                                ftp_handle(ftp, ftpsock[i]);
                        }
                }
+
+               if(ftp->modified) {
+                       updateui();
+                       ftp->modified = 0;
+               }
        }
 
        tg_cleanup();
@@ -88,6 +96,20 @@ int main(void)
        return 0;
 }
 
+void updateui(void)
+{
+       unsigned int upd = 0;
+
+       if(ftp->curdir_rem && strcmp(tui_get_title(uilist), ftp->curdir_rem) != 0) {
+               tui_set_title(uilist, ftp->curdir_rem);
+               upd |= 1;
+       }
+
+       if(upd & 1) {
+               tui_draw(uilist);
+       }
+}
+
 int proc_input(void)
 {
        union event ev;
index 106b28f..2a4d431 100644 (file)
--- a/src/tui.c
+++ b/src/tui.c
@@ -6,6 +6,7 @@
 #include "tuipriv.h"
 #include "tgfx.h"
 #include "darray.h"
+#include "util.h"
 
 
 int tui_init(void)
@@ -101,6 +102,18 @@ void tui_set_callback(struct tui_widget *w, int type, tui_callback func, void *c
        w->cbcls[type] = cls;
 }
 
+int tui_set_title(struct tui_widget *w, const char *s)
+{
+       free(w->title);
+       w->title = strdup_nf(s);
+       return 0;
+}
+
+const char *tui_get_title(struct tui_widget *w)
+{
+       return w->title;
+}
+
 struct tui_widget *tui_window(const char *title, int x, int y, int width, int height)
 {
        struct tui_widget *w;
index 5e3012e..78ec8bd 100644 (file)
--- a/src/tui.h
+++ b/src/tui.h
@@ -31,6 +31,9 @@ void tui_draw(struct tui_widget *w);
 
 void tui_set_callback(struct tui_widget *w, int type, tui_callback func, void *cls);
 
+int tui_set_title(struct tui_widget *w, const char *s);
+const char *tui_get_title(struct tui_widget *w);
+
 struct tui_widget *tui_window(const char *title, int x, int y, int w, int h);
 struct tui_widget *tui_button(const char *title, int x, int y, tui_callback cbfunc, void *cbdata);
 struct tui_widget *tui_list(const char *title, int x, int y, int w, int h, tui_callback cbfunc, void *cbdata);
index b7f9f82..c807aed 100644 (file)
@@ -10,7 +10,7 @@ static int curses_color(int col);
 void tg_init(void)
 {
        initscr();
-       raw();
+       cbreak();
        keypad(stdscr, TRUE);
        noecho();
        start_color();