void ftp_flush_reply(void) { fd_set ready; struct timeval poll; if(!ftp_connected()) return; #ifdef HAVE_LIBSSH if (ftp->session) return; #endif /* ftp_set_signal(SIGINT, SIG_IGN);*/ fprintf(stderr, "flushing replies...\r"); /* ftp_reply_timeout(10);*/ while(ftp_connected()) { poll.tv_sec = 1; poll.tv_usec = 0; FD_ZERO(&ready); int handle = sock_handle(ftp->ctrl); FD_SET(handle, &ready); if(select(handle+1, &ready, 0, 0, &poll) == 1) ftp_read_reply(); else break; } #if 0 if(ftp_loggedin()) ftp_chdir(ftp->curdir); #endif ftp_set_close_handler(); }
void ftp_flush_reply(void) { if(!ftp_connected()) return; #ifdef HAVE_LIBSSH if (ftp->session) return; #endif /* ftp_set_signal(SIGINT, SIG_IGN);*/ fprintf(stderr, "flushing replies...\r"); /* ftp_reply_timeout(10);*/ while(ftp_connected()) { if (sock_check_pending(ftp->ctrl, false) == 1) ftp_read_reply(); else break; } #if 0 if(ftp_loggedin()) ftp_chdir(ftp->curdir); #endif ftp_set_close_handler(); }
void print_xterm_title(void) { char *xterm_title = expand_prompt(ftp_connected() ? (ftp_loggedin() ? gvXtermTitle3 : gvXtermTitle2) : gvXtermTitle1); print_xterm_title_string(xterm_title); free(xterm_title); }
char* ftp_connected_user() { if (!ftp_loggedin()) return NULL; #ifdef HAVE_LIBSSH if (ftp->session) return ssh_connected_user(); return ftp->url->username ? xstrdup(ftp->url->username) : NULL; #endif }
void cmd_status(int argc, char **argv) { OPT_HELP_NEW(_("Show status."), "status [options]", NULL); maxargs(optind - 1); if(ftp_connected()) printf(_("connected to '%s'\n"), host_getoname(ftp->host)); else puts(_("not connected")); if(ftp_loggedin()) printf(_("logged in as '%s'\n"), ftp->url->username); #ifdef HAVE_KERBEROS if(ftp_connected()) sec_status(); #endif if(list_numitem(gvFtpList) > 1 || ftp_connected()) printf(_("There are totally %u connections open\n"), list_numitem(gvFtpList)); }
void cmd_status(int argc, char **argv) { OPT_HELP("Show status. Usage:\n" " status [options]\n" "Options:\n" " -h, --help show this help\n"); maxargs(optind - 1); if(ftp_connected()) printf(_("connected to '%s'\n"), ftp->host->ohostname); else puts(_("not connected")); if(ftp_loggedin()) printf(_("logged in as '%s'\n"), ftp->url->username); #ifdef HAVE_KERBEROS if(ftp_connected()) sec_status(); #endif if(list_numitem(gvFtpList) > 1 || ftp_connected()) printf(_("There are totally %u connections open\n"), list_numitem(gvFtpList)); }
int ftp_login(const char *guessed_username, const char *anonpass) { int ptype, r; static url_t *purl = 0; if(!ftp_connected()) return 1; if(!ftp->url) return -1; #ifdef HAVE_LIBSSH if (ftp->session) /* login authentication is performed by the ssh program */ return 0; #endif ptype = proxy_type(ftp->url); if(purl) { url_destroy(purl); purl = 0; } if(ptype > 0) purl = url_clone(gvProxyUrl); r = get_username(ftp->url, guessed_username, false); if(r != 0) return r; if(ptype > 1 && ptype < 7) { r = get_username(purl, 0, true); if(r != 0) return r; } #ifdef SECFTP ftp->sec_complete = false; ftp->data_prot = prot_clear; /* don't use secure stuff if anonymous */ if(!url_isanon(ftp->url)) { list *mechlist; /* request a protection level */ if(ftp->url->protlevel) { if(sec_request_prot(ftp->url->protlevel) != 0) ftp_err(_("Invalid protection level '%s'\n"), ftp->url->protlevel); } /* get list of mechanisms to try */ mechlist = ftp->url->mech ? ftp->url->mech : gvDefaultMechanism; if(mechlist) { listitem *li = mechlist->first; int ret = 0; for(; li; li=li->next) { const char *mech_name; mech_name = secext_name((char *)li->data); if(mech_name == 0) { ftp_err(_("unknown mechanism '%s'\n"), (char *)li->data); continue; } if(mech_unsupported(mech_name)) { ftp_err(_("Yafc was not compiled with support for %s\n"), mech_name); continue; } ret = sec_login(host_getname(ftp->host), mech_name); if(ret == -1) { if(ftp->code == ctError && ftp->fullcode != 504 && ftp->fullcode != 534) url_setmech(ftp->url, "none"); } if(ret != 1) break; } } if(ftp->sec_complete) ftp_err(_("Authentication successful.\n")); else ftp_err(_("*** Using plaintext username" " and password ***\n")); } #endif if(url_isanon(ftp->url)) fprintf(stderr, _("logging in anonymously...\n")); ftp_set_tmp_verbosity(ftp->url->password ? vbError : vbCommand); switch(ptype) { case 0: default: ftp_cmd("USER %s", ftp->url->username); break; case 1: ftp_cmd("USER %s@%s", ftp->url->username, ftp->url->hostname); break; case 2: case 3: case 4: ftp_cmd("USER %s", purl->username); if(ftp->code == ctContinue) { r = get_password(purl, 0, true); if(r != 0) return 0; ftp_cmd("PASS %s", purl->password); /* FIXME: what reply code do we expect now? */ if(ftp->code < ctTransient) { if(ptype == 2) { ftp_cmd("USER %s@%s", ftp->url->username, ftp->url->hostname); } else { if(ptype == 3) ftp_cmd("SITE %s", purl->hostname); else ftp_cmd("OPEN %s", purl->hostname); if(ftp->code < ctTransient) ftp_cmd("USER %s", ftp->url->username); } } } break; case 5: ftp_cmd("USER %s@%s@%s", ftp->url->username, purl->username, ftp->url->hostname); break; case 6: ftp_cmd("USER %s@%s", purl->username, ftp->url->hostname); if(ftp->code == ctContinue) { r = get_password(purl, 0, true); if(r != 0) return 0; ftp_cmd("PASS %s", purl->password); if(ftp->code < ctTransient) ftp_cmd("USER %s", ftp->url->username); } break; case 7: ftp_cmd("USER %s@%s:%i", ftp->url->username, ftp->url->hostname, ftp->url->port); break; } if(ftp->code == ctContinue) { ftp->loggedin = false; r = get_password(ftp->url, anonpass, false); if(r != 0) return r; if(ptype == 5) { r = get_password(purl, 0, true); if(r != 0) { url_destroy(purl); purl = 0; return 0; } } ftp_set_tmp_verbosity(vbCommand); switch(ptype) { default: case 0: case 1: case 2: case 3: case 4: case 6: ftp_cmd("PASS %s", ftp->url->password); break; case 5: ftp_cmd("PASS %s@%s", ftp->url->password, purl->password); break; } } url_destroy(purl); purl = 0; if(ftp->code > ctContinue) { if(ftp->fullcode == 530 && ftp_loggedin()) { /* this probable means '530 Already logged in' */ return 2; } ftp->loggedin = false; return 1; } if(ftp->code == ctComplete) { ftp->loggedin = true; #ifdef SECFTP /* we are logged in, now set the requested data protection level * requested from the autologin information in the config file, * if any, else uses default protection level 'clear', ie * no protection on the data channel */ if(ftp->sec_complete) { sec_set_protection_level(); fprintf(stderr, _("Data protection is %s\n"), level_to_name(ftp->data_prot)); } #endif ftp->homedir = ftp_getcurdir(); ftp->curdir = xstrdup(ftp->homedir); ftp->prevdir = xstrdup(ftp->homedir); if(ftp->url->directory) ftp_chdir(ftp->url->directory); ftp_get_feat(); return 0; } if(ftp->code == ctTransient) return 1; return -1; }
/* sends an FTP command on the control channel * returns reply status code on success or -1 on error */ int ftp_cmd(const char *cmd, ...) { va_list ap; int resp; bool recon = false; if(!sock_connected(ftp->ctrl)) { ftp_err(_("No control connection\n")); ftp->code = ctNone; ftp->fullcode = -1; return -1; } ftp_set_abort_handler(); ugly: va_start(ap, cmd); sock_krb_vprintf(ftp->ctrl, cmd, ap); sock_printf(ftp->ctrl, "\r\n"); sock_flush(ftp->ctrl); va_end(ap); if(ferror(sock_sout(ftp->ctrl))) { ftp_err(_("error writing command")); ftp_err(" ("); va_start(ap, cmd); vfprintf(stderr, cmd, ap); va_end(ap); va_start(ap, cmd); ftp_vtrace(cmd, ap); va_end(ap); ftp_err(")\n"); ftp->code = ctNone; ftp->fullcode = -1; return -1; } va_start(ap, cmd); ftp_print_cmd(cmd, ap); va_end(ap); resp = ftp_read_reply(); ftp_set_close_handler(); if(resp == 421) { /* server is closing control connection! */ ftp_err(_("Server closed control connection\n")); if(gvAutoReconnect && ftp_loggedin() && strcasecmp(cmd, "QUIT") != 0) { if(recon) { ftp_err(_("Reconnect failed\n")); } else { ftp_err(_("Automatic reconnect...\n")); ftp_reopen(); recon = true; goto ugly; } } else { /* ftp_close();*/ ftp->fullcode = 421; ftp->code = 4; return -1; } } return resp; }
static char *remote_completion_function(const char *text, int state) { static int len; /* length of unquoted */ static char *dir = NULL; /* any initial directory in text */ static char *unquoted = NULL; /* the unquoted filename (or beginning of it) */ static listitem *lip = NULL; static rdirectory *rdir = NULL; /* the cached remote directory */ static char merge_fmt[] = "%s/%s"; if (!ftp_loggedin()) return 0; /* this is not really true, this is for local filename completion, * but it works here too (sort of), and it looks nicer, since * the whole path is not printed by readline, ie * only foo is printed and not /bar/fu/foo (if cwd == /bar/fu) * readline appends a class character (ie /,@,*) in _local_ filenames */ rl_filename_completion_desired = 1; #ifndef HAVE_LIBEDIT rl_filename_quoting_desired = 1; #endif if (!state) { dir = base_dir_xptr(text); if (dir) { stripslash(dir); char* e = strchr(dir, 0); if (e[-1]=='\"') e[-1] = '\0'; unquote(dir); if (strcmp(dir, "/") == 0) strlcpy(merge_fmt, "%s%s", sizeof(merge_fmt)); else strlcpy(merge_fmt, "%s/%s", sizeof(merge_fmt)); } #ifndef HAVE_LIBEDIT if(gvWaitingDots) { rl_insert_text("..."); /* show dots while waiting, like ncftp */ rl_redisplay(); } #endif char* ap = ftp_path_absolute(dir); rdir = ftp_cache_get_directory(ap); const bool dir_is_cached = (rdir != 0); if (!rdir) rdir = ftp_read_directory(ap); free(ap); #ifndef HAVE_LIBEDIT if (gvWaitingDots) rl_do_undo(); /* remove the dots */ #endif if (!dir_is_cached && ftp_get_verbosity() >= vbCommand) rl_forced_update_display(); if (!rdir) { free(dir); return 0; } unquoted = dequote_filename(base_name_ptr(text), 0); if (!unquoted) unquoted = (char *)xmalloc(1); len = strlen(unquoted); lip = rdir->files->first; } while (lip) { rfile* fp = (rfile *)lip->data; lip = lip->next; /* 0 = not dir, 1 = dir, 2 = link (maybe dir) */ const int isdir = ftp_maybe_isdir(fp); if (remote_dir_only && isdir == 0) continue; const char* name = base_name_ptr(fp->path); /* skip dotdirs in completion */ if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue; if (strncmp(name, unquoted, len) == 0) { char *ret; if (dir) { if (asprintf(&ret, merge_fmt, dir, name) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); free(unquoted); free(dir); return NULL; } } else ret = xstrdup(name); if (isdir == 1) { rl_completion_append_character = '/'; } else { rl_completion_append_character = ' '; } return ret; } } free(unquoted); free(dir); return NULL; }
char *expand_prompt(const char *fmt) { unsigned maxlen; char *ins, *e; bool freeins; char *tmp; if(!fmt) return 0; char* prompt = (char *)xmalloc(strlen(fmt)+1); char* cp = prompt; while(fmt && *fmt) { if(*fmt == '%') { fmt++; ins = 0; freeins = false; maxlen = (unsigned)-1; if(isdigit((int)*fmt)) { maxlen = (unsigned)atoi(fmt); while(isdigit((int)*fmt)) fmt++; } switch(*fmt) { case 'c': if (asprintf(&ins, "%u", list_numitem(gvFtpList)) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); free(prompt); return NULL; } freeins = true; break; case 'C': if (asprintf(&ins, "%u", connection_number()) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); free(prompt); return NULL; } freeins = true; break; case 'u': /* username */ ins = ftp_loggedin() ? ftp->url->username : "******"; break; case 'h': /* remote hostname (as passed to cmd_open()) */ ins = ftp_connected() ? ftp->url->hostname : "?"; break; case 'H': /* %h up to first '.' */ if(!ftp_connected()) { ins = "?"; break; } e = strchr(ftp->url->hostname, '.'); if(e) { ins = xstrndup(ftp->url->hostname, e - ftp->url->hostname); freeins = true; } else ins = ftp->url->hostname; break; case 'm': /* remote machine name (as returned from gethostbynmame) */ ins = xstrdup(ftp_connected() ? host_getoname(ftp->host) : "?"); freeins = true; break; case 'M': /* %m up to first '.' */ if(!ftp_connected()) { ins = "?"; break; } e = strchr(host_getoname(ftp->host), '.'); if(e) { ins = xstrndup(host_getoname(ftp->host), e - host_getoname(ftp->host)); } else ins = xstrdup(host_getoname(ftp->host)); freeins = true; break; case 'n': /* remote ip number */ ins = xstrdup(ftp_connected() ? host_getoname(ftp->host) : "?"); freeins = true; break; case 'w': /* current remote directory */ if(!ftp_loggedin()) { ins = "?"; break; } ins = shortpath(ftp->curdir, maxlen, 0); freeins = true; break; case 'W': /* basename(%w) */ if(!ftp_loggedin()) { ins = "?"; break; } ins = (char *)base_name_ptr(ftp->curdir); break; case '~': /* %w but homedir replaced with '~' */ if(!ftp_loggedin()) { ins = "?"; break; } ins = shortpath(ftp->curdir, maxlen, ftp->homedir); freeins = true; break; case 'l': /* current local directory */ tmp = getcwd(NULL, 0); ins = shortpath(tmp, maxlen, 0); freeins = true; free(tmp); break; case 'L': /* basename(%l) */ tmp = getcwd(NULL, 0); ins = (char *)base_name_ptr(tmp); free(tmp); break; case '%': /* percent sign */ ins = "%"; break; case '#': /* local user == root ? '#' : '$' */ ins = getuid() == 0 ? "#" : "$"; break; case '{': /* begin non-printable character string */ #ifdef HAVE_LIBREADLINE ins = "\001\001"; /* \001 + RL_PROMPT_START_IGNORE */ #endif break; case '}': /* end non-printable character string */ #ifdef HAVE_LIBREADLINE ins = "\001\002"; /* \001 + RL_PROMPT_END_IGNORE */ #endif break; case 'e': /* escape (0x1B) */ ins = "\x1B"; break; default: /* illegal format specifier */ break; } if(ins) { const size_t len = strlen(prompt) + strlen(ins) + strlen(fmt+1) + 1; char* tmp = xmalloc(len); strlcpy(tmp, prompt, len); strlcat(tmp, ins, len); cp = tmp + strlen(prompt) + strlen(ins); free(prompt); prompt = tmp; if(freeins) free(ins); } } else *cp++ = *fmt; fmt++; } unquote_escapes(prompt); return prompt; }
void auto_create_bookmark(void) { listitem *li; int a; bool auto_create, had_passwd = false; bool update = false; if(gvAutoBookmark == 0 && gvAutoBookmarkUpdate == 0) return; if(!ftp_loggedin() || gvSighupReceived) return; auto_create = (gvAutoBookmark == 1); /* check if bookmark already exists */ li = list_search(gvBookmarks, (listsearchfunc)urlcmp, ftp->url); if(li) { if(!should_update_bookmark((url_t *)li->data)) return; /* bookmark already exist, update it */ if(gvAutoBookmarkUpdate == 2) { a = ask(ASKYES|ASKNO, ASKYES, _("Do you want to update the bookmark for this site?")); if(a == ASKNO) return; } update = true; auto_create = true; had_passwd = (((url_t *)li->data)->password != 0); } if(gvAutoBookmark == 2 && !auto_create) { a = ask(ASKYES|ASKNO, ASKYES, _("Do you want to create a bookmark for this site?")); if(a == ASKNO) return; create_bookmark(0); } else { /* auto autobookmark... */ url_t* url = url_clone(ftp->url); char* a = guess_alias(ftp->url); url_setalias(url, a); free(a); li = list_search(gvBookmarks, (listsearchfunc)urlcmp, url); if(li) { /* bookmark already exist, overwrite it */ while(true) { url_t *xurl = (url_t *)li->data; if(xurl->alias && (strcmp(xurl->alias, url->alias) == 0) && (strcmp(xurl->hostname, url->hostname) != 0)) { /* create a new version of the alias, since guessed alias * already exists but for another host */ update = false; char* par = strrchr(url->alias, '('); int ver = 1; if (par) { *par = 0; ver = atoi(par + 1); } if (asprintf(&a, "%s(%d)", url->alias, ver + 1) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); url_destroy(url); return; } url_setalias(url, a); free(a); } else { update = true; had_passwd = (xurl->password != 0); break; } li = list_search(gvBookmarks, (listsearchfunc)urlcmp, url); if(li == 0) break; } if(li) /* overwrite bookmark (ie, delete old and create a new) */ list_delitem(gvBookmarks, li); if(!url_isanon(url) && gvAutoBookmarkSavePasswd == false && !had_passwd) url_setpassword(url, 0); } else { if(!url_isanon(url) && gvAutoBookmarkSavePasswd == false) url_setpassword(url, 0); } create_the_bookmark(url); if(!gvAutoBookmarkSilent) { if(update) printf(_("updated bookmark %s\n"), url->alias); else printf(_("created bookmark %s\n"), url->alias); } } }