⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpsend.c

📁 UNIX环境下命令行FTP/SFTP工具源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: ftpsend.c,v 1.18 2005/10/05 19:32:47 splicednetworks Exp $ * * ftpsend.c -- send/receive files and file listings * * Yet Another FTP Client * Copyright (C) 1998-2001, Martin Hedenfalk <mhe@stacken.kth.se> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. See COPYING for more details. */#include "syshdr.h"#include "ftp.h"#include "socket.h"#include "xmalloc.h"#include "ftpsigs.h"#include "gvars.h"#include "ssh_cmd.h"#include "ssh_ftp.h"static int ftp_pasv(unsigned char result[6]){	int pa[6];	char *e;	int i;	if(!ftp->has_pasv_command) {		ftp_err(_("Host doesn't support passive mode\n"));		return -1;	}	ftp_set_tmp_verbosity(vbNone);	/* request passive mode */	ftp_cmd("PASV");	if(!ftp_connected())		return -1;	if(ftp->code != ctComplete) {		ftp_err(_("Unable to enter passive mode\n"));		if(ftp->code == ctError) /* no use try it again */			ftp->has_pasv_command = false;		return -1;	}	e = ftp->reply + 4;	while(!isdigit((int)*e))		e++;	if(sscanf(e, "%d,%d,%d,%d,%d,%d",			  &pa[0], &pa[1], &pa[2], &pa[3], &pa[4], &pa[5]) != 6) {		ftp_err(_("Error parsing PASV reply: '%s'\n"),				ftp_getreply(false));		return -1;	}	for(i=0; i<6; i++)		result[i] = (unsigned char)(pa[i] & 0xFF);	return 0;}static bool ftp_is_passive(void){	if(!ftp || !ftp->url || ftp->url->pasvmode == -1)		return gvPasvmode;	return ftp->url->pasvmode;}static int ftp_init_transfer(void){	struct sockaddr_in sa;	unsigned char *a, *p;	unsigned char pac[6];	if(!ftp_connected())		goto err0;	if (!(ftp->data = sock_create())) {		goto err0;	}	sock_copy(ftp->data, ftp->ctrl);	if(ftp_is_passive()) {		if(ftp_pasv(pac) != 0) {			goto err1;		}		sock_getsockname(ftp->ctrl, &sa);		memcpy(&sa.sin_addr, pac, (size_t)4);		memcpy(&sa.sin_port, pac+4, (size_t)2);		if(sock_connect_addr(ftp->data, &sa) == -1)			goto err1;	} else {		sock_listen(ftp->data);		a = (unsigned char *)&ftp->data->local_addr.sin_addr;		p = (unsigned char *)&ftp->data->local_addr.sin_port;		ftp_set_tmp_verbosity(vbError);		ftp_cmd("PORT %d,%d,%d,%d,%d,%d",				a[0], a[1], a[2], a[3], p[0], p[1]);		if(ftp->code != ctComplete)			goto err1;	}	sock_throughput(ftp->data);	return 0; err1:	sock_destroy(ftp->data); err0:	return -1;}int ftp_type(transfer_mode_t type){	if(ftp->ssh_pid)		/* FIXME: is this relevant for ssh ? */		return 0;	if(type == tmCurrent)		return 0;	if(ftp->prev_type != type) {		ftp_cmd("TYPE %c", type == tmAscii ? 'A' : 'I');		if(ftp->code != ctComplete)			return -1;		ftp->prev_type = type;	}	return 0;}static ftp_transfer_func foo_hookf = 0;/* abort routine originally from Cftp by Dieter Baron */int ftp_abort(FILE *fp){	char buf[4096];	fd_set ready;	struct timeval poll;	if(ftp->ssh_pid)		/* FIXME: what? */		return 0;	if(!ftp_connected())		return -1;	ftp_set_close_handler();	poll.tv_sec = poll.tv_usec = 0;	FD_ZERO(&ready);	FD_SET(ftp->ctrl->handle, &ready);	if(select(ftp->ctrl->handle+1, &ready, 0, 0, &poll) == 1) {		ftp_trace("There is data on the control channel, won't send ABOR\n");		/* read remaining bytes from connection */		while(fp && fread(buf, 1, 4096, fp) > 0)			/* LOOP */ ;		return 0;	}	ftp->ti.interrupted = true;	ftp_err(_("Waiting for remote to finish abort...\n"));	ftp_trace("--> telnet interrupt\n");	if(sock_telnet_interrupt(ftp->ctrl) != 0)		ftp_err("telnet interrupt: %s\n", strerror(errno));	/* ftp_cmd("ABOR") won't work here,	 * we must flush data between the ABOR command and ftp_read_reply()	 */	sock_krb_printf(ftp->ctrl, "ABOR");	sock_printf(ftp->ctrl, "\r\n");	sock_flush(ftp->ctrl);	if(ftp_get_verbosity() == vbDebug)		ftp_err("--> [%s] ABOR\n", ftp->url->hostname);	else		ftp_trace("--> [%s] ABOR\n", ftp->url->hostname);    /* read remaining bytes from connection */	while(fp && fread(buf, 1, 4096, fp) > 0)		/* LOOP */ ;	/* we expect a 426 or 226 reply here... */	ftp_read_reply();	if(ftp->fullcode != 426 && ftp->fullcode != 226)		ftp_trace("Huh!? Expected a 426 or 226 reply\n");	/* ... and a 226 or 225 reply here, respectively */	/* FIXME: should skip this reply if prev. reply wasn't 426 or 226 ? */	ftp_read_reply();	if(ftp->fullcode != 226 && ftp->fullcode != 225)		ftp_trace("Huh!? Expected a 226 or 225 reply\n");	return -1;}static int wait_for_data(FILE *fd, bool wait_for_read){	fd_set fds;	struct timeval tv;	int r;	/* watch fd to see if it has input */	FD_ZERO(&fds);	FD_SET(fileno(fd), &fds);	/* wait max 1 second */	tv.tv_sec = 10;	tv.tv_usec = 0;	if(wait_for_read)		r = select(fileno(fd)+1, &fds, 0, 0, &tv);	else /* wait for write */		r = select(fileno(fd)+1, 0, &fds, 0, &tv);#if 0	if(r < 0 && errno == EINTR && gvSigStopReceived && ftp_sigints() == 0) {		gvSigStopReceived = false;		r = 0;	}#endif	if(r < 0) {/*		perror("\nselect");*/		if(errno == EINTR) {			if(gvSighupReceived)				return 1;			if(gvInterrupted)				return -1;			if(ftp_sigints() == 0)				/* assume it is a SIGSTOP/SIGCONT signal */				return 0;		}		return -1;	}	if(r)		ftp->ti.stalled = 0;	else		ftp->ti.stalled++;	return r;}static int wait_for_input(void){	int r;	do {		r = wait_for_data(ftp->data->sin, true);		if(r == -1) {			if(errno == EINTR)				ftp->ti.interrupted = true;			return -1;		}		if(r == 0 && foo_hookf)			foo_hookf(&ftp->ti);	} while(r == 0);	return 0;}static int wait_for_output(void){	int r;	do {		r = wait_for_data(ftp->data->sout, false);		if(r == -1)			return -1;		if(r == 0 && foo_hookf)			foo_hookf(&ftp->ti);	} while(r == 0);	return 0;}static int maybe_abort(FILE *in, FILE *out){	unsigned i;	i = ftp_sigints();	ftp_set_close_handler();	ftp->ti.finished = true;	if(ftp->ti.interrupted)		i++;	if(i > 0 || ferror(in) || ferror(out)) {		if(ferror(in)) {			ftp_err(_("read error: %s\n"), strerror(errno));			ftp->ti.ioerror = true;		}		else if(ferror(out)) {			ftp_err(_("write error: %s\n"), strerror(errno));			ftp->ti.ioerror = true;		}		return ftp_abort(ftp->ti.transfer_is_put ? out : in);	}	return 0;}static int FILE_recv_binary(FILE *in, FILE *out){	size_t n;	char *buf;	time_t then = time(0) - 1;	time_t now;	ftp_set_close_handler();	if(foo_hookf)		foo_hookf(&ftp->ti);	ftp->ti.begin = false;	clearerr(in);	clearerr(out);	buf = (char *)xmalloc(FTP_BUFSIZ);	while(!feof(in)) {		if(wait_for_input() != 0) {			ftp_trace("wait_for_input() returned non-zero\n");			break;		}#ifdef SECFTP		n = sec_read(fileno(in), buf, FTP_BUFSIZ);#else		n = fread(buf, sizeof(char), FTP_BUFSIZ, in);#endif		if(n <= 0)			break;		if(ftp_sigints() > 0) {			ftp_trace("break due to sigint\n");			break;		}		if(fwrite(buf, sizeof(char), n, out) != n)			break;		ftp->ti.size += n;		if(foo_hookf) {			now = time(0);			if(now > then) {				foo_hookf(&ftp->ti);				then = now;			}		}	}	free(buf);	ftp_set_close_handler();	return maybe_abort(in, out);}static int FILE_send_binary(FILE *in, FILE *out){	size_t n;	char *buf;	time_t then = time(0) - 1;	time_t now;	ftp_set_close_handler();	if(foo_hookf)		foo_hookf(&ftp->ti);	ftp->ti.begin = false;	clearerr(in);	clearerr(out);	buf = (char *)xmalloc(FTP_BUFSIZ);	while(!feof(in)) {		n = fread(buf, sizeof(char), FTP_BUFSIZ, in);		if(n <= 0)			break;		if(ftp_sigints() > 0)			break;		if(wait_for_output() != 0)			break;#ifdef SECFTP		if(sec_write(fileno(out), buf, n) != n)			break;#else		if(fwrite(buf, sizeof(char), n, out) != n)			break;#endif		ftp->ti.size += n;		if(foo_hookf) {			now = time(0);			if(now > then) {				foo_hookf(&ftp->ti);				then = now;			}		}	}#ifdef SECFTP	sec_fflush(out);#endif	free(buf);	return maybe_abort(in, out);}static int krb_getc(FILE *fp){#ifdef SECFTP	return sec_getc(fp);#else	return fgetc(fp);#endif}static int FILE_recv_ascii(FILE *in, FILE *out){	char *buf = (char *)xmalloc(FTP_BUFSIZ);	int c;	time_t then = time(0) - 1;	time_t now;	ftp_set_close_handler();	if(foo_hookf)		foo_hookf(&ftp->ti);	ftp->ti.begin = false;	clearerr(in);	clearerr(out);	while((c = krb_getc(in)) != EOF) {		if(ftp_sigints() > 0)			break;		if(wait_for_input() != 0)			break;		if(c == '\n')			ftp->ti.barelfs++;		else if(c == '\r') {			c = krb_getc(in);			if(c == EOF)				break;			if(c != '\n') {				ungetc(c, in);				c = '\r';			}		}		if(fputc(c, out) == EOF)			break;		ftp->ti.size++;		if(foo_hookf) {			now = time(0);			if(now > then) {				foo_hookf(&ftp->ti);				then = now;			}		}	}	free(buf);	return maybe_abort(in, out);}static int FILE_send_ascii(FILE *in, FILE *out){	char *buf = (char *)xmalloc(FTP_BUFSIZ);	int c;	time_t then = time(0) - 1;	time_t now;	ftp_set_close_handler();	if(foo_hookf)		foo_hookf(&ftp->ti);	ftp->ti.begin = false;	clearerr(in);	clearerr(out);	while((c = fgetc(in)) != EOF) {		if(ftp_sigints() > 0)			break;		if(wait_for_output() != 0)			break;		if(c == '\n') {			if(fputc('\r', out) == EOF)				break;			ftp->ti.size++;		}		if(fputc(c, out) == EOF)			break;		ftp->ti.size++;		if(foo_hookf) {			now = time(0);			if(now > then) {				foo_hookf(&ftp->ti);				then = now;			}		}	}	free(buf);	return maybe_abort(in, out);}void reset_transfer_info(void){	ftp->ti.barelfs = 0;	ftp->ti.size = 0L;	ftp->ti.ioerror = false;	ftp->ti.interrupted = false;	ftp->ti.transfer_is_put = false;	ftp->ti.restart_size = 0L;	ftp->ti.finished = false;	ftp->ti.stalled = 0;	ftp->ti.begin = true;	gettimeofday(&ftp->ti.start_time, 0);	if(!ftp->ti.local_name)		ftp->ti.local_name = xstrdup("local");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -