+
+int ftp_store(struct ftp *ftp, const char *fname)
+{
+ return -1;
+}
+
+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 int cproc_active(struct ftp *ftp, int code, const char *buf, void *cls)
+{
+ if(code != 200) {
+ errmsg("ftp_active failed\n");
+ ftp_close(ftp);
+ } else {
+ ftp->status = FTP_CONN_ACT;
+ }
+ return 0;
+}
+
+static int cproc_pwd(struct ftp *ftp, int code, const char *buf, void *cls)
+{
+ char *dirname;
+
+ if(code != 257) {
+ warnmsg("pwd failed\n");
+ return -1;
+ }
+
+ dirname = alloca(strlen(buf) + 1);
+ if(get_quoted_text(buf, dirname) == -1) {
+ warnmsg("pwd: invalid response: %s\n", buf);
+ return -1;
+ }
+
+ free(ftp->curdir_rem);
+ ftp->curdir_rem = strdup_nf(dirname);
+ ftp->modified = 1;
+ return 0;
+}
+
+static int cproc_cwd(struct ftp *ftp, int code, const char *buf, void *cls)
+{
+ return -1;
+}
+
+static int cproc_list(struct ftp *ftp, int code, const char *buf, void *cls)
+{
+ if(code < 200) {
+ /* expect more */
+ return 1;
+ }
+
+ if(code >= 400) {
+ errmsg("failed to retrieve directory listing\n");
+ }
+ return 0;
+}
+
+static void dproc_list(struct ftp *ftp, const char *buf, int sz, void *cls)
+{
+ struct recvbuf *rbuf = cls;
+
+ if(sz == 0) {
+ /* EOF condition, we got the whole list, update directory entries */
+ /* TODO */
+ rbuf->buf[rbuf->size] = 0;
+ fprintf(stderr, "%s\n", rbuf->buf);
+
+ free(rbuf->buf);
+ free(rbuf);
+ ftp->dproc = 0;
+ return;
+ }
+
+ if(rbuf->size + sz > rbuf->bufsz) {
+ char *tmp;
+ int newsz = rbuf->bufsz << 1;
+
+ if(!(tmp = realloc(rbuf->buf, newsz))) {
+ errmsg("failed to resize receive buffer\n");
+ return;
+ }
+ rbuf->buf = tmp;
+ rbuf->bufsz = newsz;
+ }
+
+ memcpy(rbuf->buf + rbuf->size, buf, sz);
+ rbuf->size += sz;
+}