Example #1
0
/* just gets the file SRC and store in local file DEST
 * doesn't parse any LIST output
 * returns 0 on success, else -1
 */
static int do_the_get(const char *src, const char *dest,
                      putmode_t how, unsigned opt)
{
    char *fulldest;
    char *tmp;
    transfer_mode_t type;

    type = ascii_transfer(src) ? tmAscii : gvDefaultType;
    if(test(opt, GET_ASCII))
        type = tmAscii;
    else if(test(opt, GET_BINARY))
        type = tmBinary;

    tmp = getcwd(NULL, 0);
    if (tmp == (char *)NULL)
        return -1;

    fulldest = path_absolute(dest, tmp, 0);

#if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux))
    if(gvUseEnvString && ftp_connected())
        setproctitle("%s, get %s", ftp->url->hostname, src);
#endif

    int r = ftp_getfile(src, dest, how, type,
                        test(opt, GET_VERBOSE)
                        && !gvSighupReceived
                        && !test(opt, GET_NOHUP) ? transfer : 0);

    if(r == 0 && (test(opt, GET_NOHUP) || gvSighupReceived)) {
        fprintf(stderr, "%s [%sb of ",
                src, human_size(ftp->ti.size));
        fprintf(stderr, "%sb]\n", human_size(ftp->ti.total_size));
    }
    if(test(opt, GET_NOHUP)) {
        if(r == 0)
            transfer_mail_msg(_("received %s\n"), src);
        else
            transfer_mail_msg(_("failed to receive %s: %s\n"),
                              src, ftp_getreply(false));
    }
    free(fulldest);
#if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux))
    if(gvUseEnvString && ftp_connected())
        setproctitle("%s", ftp->url->hostname);
#endif

    free(tmp);

    return r;
}
Example #2
0
void transfer_end_nohup(void)
{
	nohup_end_time = time(0);
	printf(_("Done\nTransfer ended %s\n"), ctime(&nohup_end_time));

	if(gvNohupMailAddress) {
		FILE *fp;
		char *cmd;

		asprintf(&cmd, "%s %s", gvSendmailPath, gvNohupMailAddress);
		fp = popen(cmd, "w");
		if(fp == 0)
			printf(_("Unable to send mail (using %s)\n"), gvSendmailPath);
		else {
			transfer_mail_msg("\n");
			rewind(mailfp);
			while(true) {
				int c = fgetc(mailfp);
				if(c == EOF) {
					fclose(mailfp);
					break;
				}
				fputc(c, fp);
			}
			pclose(fp);
		}
	}

	ftp_quit_all();
	list_free(gvFtpList);
	free(nohup_logfile);
	free(nohup_command);
	gvars_destroy();
	exit(0);
}
Example #3
0
static void term_handler(int signum)
{
	time_t now = time(0);

	fprintf(stderr, "%s [%sB of ", ftp->ti.remote_name,
			human_size(ftp->ti.size));
	fprintf(stderr, "%sB]\n", human_size(ftp->ti.total_size));
	printf(_("SIGTERM (terminate) received, exiting...\n"));
	printf(_("Transfer aborted %s"), ctime(&now));
	if(ftp->ti.remote_name)
		printf(_("%s may not have transferred correctly\n"),
			   ftp->ti.remote_name);

	transfer_mail_msg(_("SIGTERM (terminate) received, exiting...\n"));
	transfer_mail_msg(_("Transfer aborted %s"), ctime(&now));
	transfer_mail_msg(_("%s may not have transferred correctly\n"),
					  ftp->ti.remote_name);

	transfer_end_nohup();
}
Example #4
0
File: fxp.c Project: Celelibi/yafc
static int do_the_fxp(Ftp *srcftp, const char *src,
					  Ftp *destftp, const char *dest,
					  fxpmode_t how, unsigned opt)
{
	transfer_mode_t type;

	if(test(opt, FXP_NOHUP))
		fprintf(stderr, "%s\n", src);

	type = ascii_transfer(src) ? tmAscii : gvDefaultType;
	if(test(opt, FXP_ASCII))
		type = tmAscii;
	else if(test(opt, FXP_BINARY))
		type = tmBinary;

#if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux))
	if(gvUseEnvString && ftp_connected())
		setproctitle("%s, fxp %s", srcftp->url->hostname, src);
#endif
	if(test(opt, FXP_VERBOSE)) {
		printf("%s\n", src);
	}
	const int r = ftp_fxpfile(srcftp, src, destftp, dest, how, type);
#if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux))
	if(gvUseEnvString && ftp_connected())
		setproctitle("%s", srcftp->url->hostname);
#endif

	if(test(opt, FXP_NOHUP)) {
		if(r == 0)
			transfer_mail_msg(_("sent %s\n"), src);
		else
			transfer_mail_msg(_("failed to send %s: %s\n"),
							  src, ftp_getreply(false));
	}

	return r;
}
Example #5
0
void transfer_mail_msg(const char *fmt, ...)
{
	static bool opened = false;
	va_list ap;

	if(!gvNohupMailAddress)
		return;

	if(!opened) {
		char *e;
		char *tmpfilename;

		asprintf(&e, "%s/yafcmail.tmp", gvWorkingDirectory);
		tmpfilename = make_unique_filename(e);
		free(e);

		mailfp = fopen(tmpfilename, "w+");
		opened = true;
		if(mailfp) {
			unlink(tmpfilename);
			setbuf(logfp, 0); /* change buffering */
			transfer_mail_msg(_("From: yafc@%s\n"
								"Subject: yafc transfer finished on %s\n"
								"\n"
								"This is an automatic message sent by yafc\n"
								"Your transfer is finished!\n"
								"\n"
								"connected to %s as user %s\n"
								"command was: %s\n"
								"started %s\n"
								"\n"
								"(please do not reply to this mail)\n"
								"\n"),
							  gvLocalHost, gvLocalHost,
							  ftp->url->hostname, ftp->url->username,
							  nohup_command ? nohup_command :
							  "(unknown, SIGHUPed)",
							  ctime(&nohup_start_time));
		}
	}

	if(mailfp == 0)
		return;

	va_start(ap, fmt);
	vfprintf(mailfp, fmt, ap);
	va_end(ap);
}
Example #6
0
/* returns:
 * 0   ok, remove file from list
 * -1  failure
 */
static int getfile(const rfile *fi, unsigned int opt,
             const char *output, const char *destname)
{
    struct stat sb;
    char* dest = NULL;
    getmode_t how = getNormal;
    bool mkunique = false;
    int r, ret = -1;

    if((get_glob_mask && fnmatch(get_glob_mask, base_name_ptr(fi->path),
                                 FNM_EXTMATCH) == FNM_NOMATCH)
#ifdef HAVE_REGEX
       || (get_rx_mask_set && regexec(&get_rx_mask, base_name_ptr(fi->path),
                                      0, 0, 0) == REG_NOMATCH)
#endif
        )
    {
        return 0;
    }

    if(!output)
        output = ".";

    if(test(opt, GET_PARENTS)) {
        char *apath = base_dir_xptr(fi->path);
        if (asprintf(&dest, "%s%s/%s", output, apath, destname) == -1)
        {
          free(apath);
          fprintf(stderr, _("Failed to allocate memory.\n"));
          return -1;
        }
        free(apath);
    } else {
        /* check if -o option is given, if GET_OUTPUT_FILE is set, we only
         * transfer one file and output is set to the filename. However, if
         * the destination already exists and is a directory, we assume
         * that the user meant a directory */

        int dest_is_file = test(opt, GET_OUTPUT_FILE);

        if(stat(output, &sb) == 0) {
            if(S_ISDIR(sb.st_mode)) {
                dest_is_file = false;
            }
        }

        if(dest_is_file)
            dest = xstrdup(output);
        else
            if (asprintf(&dest, "%s/%s", output, destname) == -1)
            {
              fprintf(stderr, _("Failed to allocate memory.\n"));
              return -1;
            }
    }

    /* make sure destination directory exists */
    {
        char *destdir = base_dir_xptr(dest);
        if(destdir) {
            bool r = make_path(destdir);
            if(!r) {
                if (errno == EEXIST)
                  ftp_err("`%s' exists but is not a directory\n", destdir);
                else
                  ftp_err("%s: %s\n", destdir, strerror(errno));
                transfer_mail_msg(_("Couldn't create directory: %s\n"),
                                  destdir);
                free(destdir);
                return -1;
            }
            /* change permission and group, if requested */
            if(test(opt, GET_CHMOD)) {
                if(stat(destdir, &sb) == 0) {
                    mode_t m = sb.st_mode;
                    m = mode_adjust(m, cmod);
                    if(chmod(destdir, m) != 0)
                        perror(destdir);
                }           }
            if(test(opt, GET_CHGRP)) {
                if(chown(destdir, -1, group_change) != 0)
                    perror(dest);
            }
            free(destdir);
        }
    }

    /* check if destination file exists */
    if(stat(dest, &sb) == 0) {
        if(test(opt, GET_SKIP_EXISTING)) {
            if(test(opt, GET_VERBOSE)) {
							char* sp = shortpath(dest, 42, gvLocalHomeDir);
              fprintf(stderr, _("Local file '%s' exists, skipping...\n"),
                      sp);
							stats_file(STATS_SKIP, 0);
							free(sp);
						}
            return 0;
        }
        if(test(opt, GET_UNIQUE))
            mkunique = true;
        else if(test(opt, GET_APPEND))
            how = getAppend;
        else if(test(opt, GET_NEWER)) {
            struct tm *fan = gmtime(&sb.st_mtime);
            time_t ft = ftp_filetime(fi->path, test(opt, GET_FORCE_NEWER));
            sb.st_mtime = gmt_mktime(fan);

            ftp_trace("get -n: remote file: %s", ctime(&ft));
            ftp_trace("get -n: local file: %s\n", ctime(&sb.st_mtime));

            if(sb.st_mtime >= ft && ft != (time_t)-1) {
                if(test(opt, GET_VERBOSE)) {
									char* sp = shortpath(dest, 30, gvLocalHomeDir);
                    ftp_err(_(
                        "Local file '%s' is newer than remote, skipping...\n"),
                            sp);
									stats_file(STATS_SKIP, 0);
									free(sp);
								}
                return 0;
            }
        } else if(!test(opt, GET_RESUME)) {
            if(!get_owbatch && !gvSighupReceived) {
                struct tm *fan = gmtime(&sb.st_mtime);
                time_t ft = ftp_filetime(fi->path, test(opt, GET_FORCE_NEWER));
                int a;
                char *e;

                sb.st_mtime = gmt_mktime(fan);
                e = xstrdup(ctime(&sb.st_mtime));
								char* sp = shortpath(dest, 42, gvLocalHomeDir);
                a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME,
                        ASKRESUME,
                        _("Local file '%s' exists\nLocal: %lld bytes, %sRemote: %lld bytes, %sOverwrite?"),
                        sp,
                        (unsigned long long) sb.st_size, e ? e : "unknown date\n",
                        ftp_filesize(fi->path), ctime(&ft));
								free(sp);
                free(e);
                if(a == ASKCANCEL) {
                    get_quit = true;
                    return 0;
                }
                else if(a == ASKNO)
                    return 0;
                else if(a == ASKUNIQUE)
                    mkunique = true;
                else if(a == ASKALL) {
                    get_owbatch = true;
                }
                else if(a == ASKRESUME)
                    opt |= GET_RESUME; /* for this file only */
                /* else a == ASKYES */
            }
        }
        if(test(opt, GET_RESUME))
            how = getResume;
    }

    if(mkunique) {
        char* newdest = make_unique_filename(dest);
        free(dest);
        dest = newdest;
    }

    /* the file doesn't exist or we choosed to overwrite it, or changed dest */

    if(rislink(fi) && test(opt, GET_NO_DEREFERENCE)) {
        /* remove any existing destination */
        unlink(dest);
        ftp_err(_("symlinking '%s' to '%s'\n"), dest, fi->link);
        if(symlink(fi->link, dest) != 0)
            perror(dest);
        ret = 0;
    }
    else {
        r = do_the_get(fi->path, dest, how, opt);

        if(r == 0) {
			stats_file(STATS_SUCCESS, ftp->ti.total_size);
            ret = 0;
            if(test(opt, GET_PRESERVE))
                get_preserve_attribs(fi, dest);
            if(test(opt, GET_CHMOD)) {
                mode_t m = rfile_getmode(fi);
                m = mode_adjust(m, cmod);
                if(chmod(dest, m) != 0)
                    perror(dest);
            }
            if(test(opt, GET_CHGRP)) {
                if(chown(dest, -1, group_change) != 0)
                    perror(dest);
            }
            if(test(opt, GET_DELETE_AFTER)) {
                bool dodel = false;
								char* sp = shortpath(fi->path, 42, ftp->homedir);
                if(!test(opt, GET_FORCE)
                   && !get_delbatch && !gvSighupReceived)
                {
                    int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES,
                                _("Delete remote file '%s'?"), sp);
                    if(a == ASKALL) {
                        get_delbatch = true;
                        dodel = true;
                    }
                    else if(a == ASKCANCEL)
                        get_quit = true;
                    else if(a != ASKNO)
                        dodel = true;
                } else
                    dodel = true;

                if(dodel) {
                    ftp_unlink(fi->path);
                    if(ftp->code == ctComplete)
                        fprintf(stderr, _("%s: deleted\n"), sp);
                    else
                        fprintf(stderr, _("error deleting '%s': %s\n"),
															  sp, ftp_getreply(false));
                }
								free(sp);
            }
        } else {
			stats_file(STATS_FAIL, 0);
			ret = -1;
		}
    }

    free(dest);
    return ret;
}
Example #7
0
static void putfile(const char *path, struct stat *sb,
					unsigned opt, const char *output)
{
	putmode_t how = putNormal;
	bool file_exists = false;
	char *dest, *dpath;
	int r;
	bool dir_created;
	char *dest_dir, *q_dest_dir;

	if((put_glob_mask && fnmatch(put_glob_mask, base_name_ptr(path),
								 FNM_EXTMATCH) == FNM_NOMATCH)
#ifdef HAVE_REGEX
	   || (put_rx_mask_set && regexec(&put_rx_mask, base_name_ptr(path),
									  0, 0, 0) == REG_NOMATCH)
#endif
		)
		return;

	if(!output)
		output = ".";

	if(test(opt, PUT_PARENTS)) {
		char *p = base_dir_xptr(path);
		asprintf(&dest, "%s/%s/%s", output, p, base_name_ptr(path));
		free(p);
	} else if(test(opt, PUT_OUTPUT_FILE))
		dest = xstrdup(output);
	else
		asprintf(&dest, "%s/%s", output, base_name_ptr(path));

	path_collapse(dest);

	/* make sure destination directory exists */
	dpath = base_dir_xptr(dest);
	dest_dir = ftp_path_absolute(dpath);
	q_dest_dir = bash_backslash_quote(dest_dir);
	r = ftp_mkpath(q_dest_dir);
	free(q_dest_dir);
	free(dest_dir);
	if(r == -1) {
		transfer_mail_msg(_("failed to create directory %s\n"), dest_dir);
		free(dpath);
		free(dest);
		return;
	}
	dir_created = (r == 1);

	if(!dir_created && !test(opt, PUT_UNIQUE) && !test(opt, PUT_FORCE)) {
		rfile *f;
		f = ftp_get_file(dest);
		file_exists = (f != 0);
		if(f && risdir(f)) {
			/* can't overwrite a directory */
			printf(_("%s: is a directory\n"), dest);
			free(dest);
			return;
		}
	}

	if(test(opt, PUT_APPEND)) {
		how = putAppend;
	} else if(file_exists) {
		if(test(opt, PUT_SKIP_EXISTING)) {
			printf(_("Remote file '%s' exists, skipping...\n"),
				   shortpath(dest, 42, ftp->homedir));
			free(dest);
			return;
		}
		else if(test(opt, PUT_NEWER)) {
			time_t ft = ftp_filetime(dest);
			if(ft != (time_t)-1 && ft >= sb->st_mtime) {
				printf(_("Remote file '%s' is newer than local, skipping...\n"),
					   shortpath(dest, 42, ftp->homedir));
				free(dest);
				return;
			}
		}
		else if(!test(opt, PUT_RESUME)) {
			if(!put_owbatch) {
				struct tm *fan = gmtime(&sb->st_mtime);
				time_t ft;
				int a;
				rfile *f;
				char *e;

				f = ftp_get_file(dest);
				ft = ftp_filetime(f->path);
				sb->st_mtime = gmt_mktime(fan);
				e = xstrdup(ctime(&sb->st_mtime));
				a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME,
						ASKRESUME,
						_("Remote file '%s' exists\nLocal: %lld bytes, %sRemote: %lld bytes, %sOverwrite?"),
						shortpath(dest, 42, ftp->homedir),
						(unsigned long long) sb->st_size, e ? e : "unknown size",
						ftp_filesize(f->path), ctime(&ft));
				free(e);
				if(a == ASKCANCEL) {
					put_quit = true;
					free(dest);
					return;
				}
				else if(a == ASKNO) {
					free(dest);
					return;
				}
				else if(a == ASKUNIQUE)
					opt |= PUT_UNIQUE; /* for this file only */
				else if(a == ASKALL)
					put_owbatch = true;
				else if(a == ASKRESUME)
					opt |= PUT_RESUME; /* for this file only */
				/* else a == ASKYES */
			}
		}
	}

	if(test(opt, PUT_RESUME))
		how = putResume;
	if(test(opt, PUT_UNIQUE))
		how = putUnique;

	r = do_the_put(path, dest, how, opt);
	free(dest);
	if(r != 0)
		return;

	if(test(opt, PUT_PRESERVE)) {
		if(ftp->has_site_chmod_command)
			ftp_chmod(ftp->ti.local_name, get_mode_string(sb->st_mode));
	}

	if(test(opt, PUT_DELETE_AFTER)) {
		bool dodel = false;

		if(!test(opt, PUT_FORCE) && !put_delbatch) {
			int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES,
						_("Delete local file '%s'?"),
						shortpath(path, 42, gvLocalHomeDir));
			if(a == ASKALL) {
				put_delbatch = true;
				dodel = true;
			}
			else if(a == ASKCANCEL)
				put_quit = true;
			else if(a != ASKNO)
				dodel = true;
		} else
			dodel = true;

		if(dodel) {
			if(unlink(path) == 0)
				printf(_("%s: deleted\n"),
					   shortpath(path, 42, gvLocalHomeDir));
			else
				printf(_("error deleting '%s': %s\n"),
					   shortpath(path, 42, gvLocalHomeDir),
					   strerror(errno));
		}
	}
}
Example #8
0
File: fxp.c Project: Celelibi/yafc
static int fxpfile(const rfile *fi, unsigned int opt,
					const char *output, const char *destname)
{
	fxpmode_t how = fxpNormal;
	bool file_exists = false;
	char *dest, *dpath;
	bool dir_created;
	char *dest_dir, *q_dest_dir;
	Ftp *thisftp = ftp;

	if((fxp_glob_mask
		&& fnmatch(fxp_glob_mask, base_name_ptr(fi->path), 0) == FNM_NOMATCH)
#ifdef HAVE_REGEX
	   || (fxp_rx_mask_set
		   && regexec(&fxp_rx_mask,
					  base_name_ptr(fi->path), 0, 0, 0) == REG_NOMATCH)
#endif
		)
		return 0;

	if(!output)
		output = ".";

	if(test(opt, FXP_PARENTS)) {
		char *p = base_dir_xptr(fi->path);
		if (asprintf(&dest, "%s/%s/%s", output, p, base_name_ptr(fi->path)) == -1)
    {
      fprintf(stderr, _("Failed to allocate memory.\n"));
      free(p);
      return -1;
    }
		free(p);
	} else if(test(opt, FXP_OUTPUT_FILE))
		dest = xstrdup(output);
	else
		if (asprintf(&dest, "%s/%s", output, base_name_ptr(fi->path)) == -1)
    {
      fprintf(stderr, _("Failed to allocate memory.\n"));
      return -1;
    }

	path_collapse(dest);

	ftp_use(fxp_target);

	/* make sure destination directory exists */
	dpath = base_dir_xptr(dest);
	dest_dir = ftp_path_absolute(dpath);
	q_dest_dir = backslash_quote(dest_dir);
	int r = ftp_mkpath(q_dest_dir);
	free(q_dest_dir);
	free(dest_dir);
	if(r == -1) {
		transfer_mail_msg(_("Couldn't create directory: %s\n"), dest_dir);
		free(dpath);
		free(dest);
		ftp_use(thisftp);
		return -1;
	}
	dir_created = (r == 1);

	if(!dir_created && !test(opt, FXP_UNIQUE) && !test(opt, FXP_FORCE)) {
		rfile *f;
		f = ftp_get_file(dest);
		file_exists = (f != 0);
		if(f && risdir(f)) {
			/* can't overwrite a directory */
			printf(_("%s: is a directory\n"), dest);
			free(dest);
			return 0;
		}
	}

	if(test(opt, FXP_APPEND)) {
		how = fxpAppend;
	} else if(file_exists) {
		if(test(opt, FXP_SKIP_EXISTING)) {
			char* sp = shortpath(dest, 42, ftp->homedir);
			printf(_("Remote file '%s' exists, skipping...\n"), sp);
			free(sp);
			free(dest);
			ftp_use(thisftp);
			return 0;
		}
		else if(test(opt, FXP_NEWER)) {
			time_t src_ft;
			time_t dst_ft;

			ftp_use(thisftp);
			src_ft = ftp_filetime(fi->path, test(opt, FXP_FORCE_NEWER));
			ftp_use(fxp_target);

			dst_ft = ftp_filetime(dest, test(opt, FXP_FORCE_NEWER));

			if(src_ft != (time_t)-1 && dst_ft != (time_t)-1 && dst_ft >= src_ft) {
				char* sp = shortpath(dest, 42, ftp->homedir);
				printf(_("Remote file '%s' is newer than local, skipping...\n"), sp);
				free(sp);
				free(dest);
				ftp_use(thisftp);
				return 0;
			}
		}
		else if(!test(opt, FXP_RESUME)) {
			if(!fxp_owbatch) {
				char* sp = shortpath(dest, 42, ftp->homedir);
				int a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME,
							ASKRESUME,
							_("File '%s' exists, overwrite?"),
							sp);
				free(sp);
				if(a == ASKCANCEL) {
					fxp_quit = true;
					free(dest);
					ftp_use(thisftp);
					return 0;
				}
				else if(a == ASKNO) {
					free(dest);
					ftp_use(thisftp);
					return 0;
				}
				else if(a == ASKUNIQUE)
					opt |= FXP_UNIQUE; /* for this file only */
				else if(a == ASKALL)
					fxp_owbatch = true;
				else if(a == ASKRESUME)
					opt |= FXP_RESUME; /* for this file only */
				/* else a == ASKYES */
			}
		}
	}

	if(test(opt, FXP_RESUME))
		how = fxpResume;
	if(test(opt, FXP_UNIQUE))
		how = fxpUnique;

	r = do_the_fxp(thisftp, fi->path, fxp_target, dest, how, opt);
	free(dest);
	if(r != 0) {
		ftp_use(thisftp);
		return -1;
	}

	if(test(opt, FXP_PRESERVE))
		fxp_preserve_attribs(fi, dest);

	if(test(opt, FXP_DELETE_AFTER)) {
		bool dodel = false;

		ftp_use(thisftp);

		if(!test(opt, FXP_FORCE)
		   && !fxp_delbatch && !gvSighupReceived)
			{
				char* sp = shortpath(fi->path, 42, ftp->homedir);
				int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES,
							_("Delete remote file '%s'?"),
							sp);
				free(sp);
				if(a == ASKALL) {
					fxp_delbatch = true;
					dodel = true;
				}
				else if(a == ASKCANCEL)
					fxp_quit = true;
				else if(a != ASKNO)
					dodel = true;
			} else
				dodel = true;

		if(dodel) {
			ftp_unlink(fi->path);
			char* sp = shortpath(fi->path, 42, ftp->homedir);
			if(ftp->code == ctComplete)
				fprintf(stderr, _("%s: deleted\n"), sp);
			else
				fprintf(stderr, _("error deleting '%s': %s\n"), sp,
						ftp_getreply(false));
			free(sp);
		}
	}

	ftp_use(thisftp);
	return 0;
}