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

📄 psftp.c

📁 一个支持FTP,SFTP的客户端程序
💻 C
📖 第 1 页 / 共 3 页
字号:
{
    struct sftp_packet *pktin;
    struct sftp_request *req, *rreq;

    /*
     * Do protocol initialisation. 
     */
    if (!fxp_init()) {
	FzSFtpIpc_Error1("Fatal: unable to initialise SFTP: %s", fxp_error());
	return 1;		       /* failure */
    }

    /*
     * Find out where our home directory is.
     */
    sftp_register(req = fxp_realpath_send("."));
    rreq = sftp_find_request(pktin = sftp_recv());
    assert(rreq == req);
    homedir = fxp_realpath_recv(pktin, rreq);

    if (!homedir) {
	FzSFtpIpc_Status1("Warning: failed to resolve home directory: %s",
			   fxp_error());
	homedir = dupstr(".");
    } else {
	FzSFtpIpc_Status1("Remote working directory is %s", homedir);
    }
    pwd = dupstr(homedir);

    FzSFtpIpc_SendRequest(SFTP_DATAID_CTS_CONNECTED, 0, 0);

    return 0;
}

/* ----------------------------------------------------------------------
 * Dirty bits: integration with PuTTY.
 */

static int verbose = 0;

/*
 *  Print an error message and perform a fatal exit.
 */
void fatalbox(char *fmt, ...)
{
    char *str, *str2;
    va_list ap;
    va_start(ap, fmt);
    str = dupvprintf(fmt, ap);
    str2 = dupcat("Fatal: ", str, NULL);
    sfree(str);
    va_end(ap);
    FzSFtpIpc_FatalError(str2);
    sfree(str2);

    cleanup_exit(1);
}
void modalfatalbox(char *fmt, ...)
{
    char *str, *str2;
    va_list ap;
    va_start(ap, fmt);
    str = dupvprintf(fmt, ap);
    str2 = dupcat("Fatal: ", str, NULL);
    sfree(str);
    va_end(ap);
    FzSFtpIpc_FatalError(str2);
    sfree(str2);

    cleanup_exit(1);
}
void connection_fatal(void *frontend, char *fmt, ...)
{
    char *str, *str2;
    va_list ap;
    va_start(ap, fmt);
    str = dupvprintf(fmt, ap);
    str2 = dupcat("Fatal: ", str, NULL);
    sfree(str);
    va_end(ap);
    FzSFtpIpc_FatalError(str2);
    sfree(str2);

    cleanup_exit(1);
}

void ldisc_send(void *handle, char *buf, int len, int interactive)
{
    /*
     * This is only here because of the calls to ldisc_send(NULL,
     * 0) in ssh.c. Nothing in PSFTP actually needs to use the
     * ldisc as an ldisc. So if we get called with any real data, I
     * want to know about it.
     */
    assert(len == 0);
}

/*
 * In psftp, all agent requests should be synchronous, so this is a
 * never-called stub.
 */
void agent_schedule_callback(void (*callback)(void *, void *, int),
			     void *callback_ctx, void *data, int len)
{
    assert(!"We shouldn't be here");
}

/*
 * Receive a block of data from the SSH link. Block until all data
 * is available.
 *
 * To do this, we repeatedly call the SSH protocol module, with our
 * own trap in from_backend() to catch the data that comes back. We
 * do this until we have enough data.
 */

static unsigned char *outptr;	       /* where to put the data */
static unsigned outlen;		       /* how much data required */
static unsigned char *pending = NULL;  /* any spare data */
static unsigned pendlen = 0, pendsize = 0;	/* length and phys. size of buffer */
int from_backend(void *frontend, int is_stderr, const char *data, int datalen)
{
    unsigned char *p = (unsigned char *) data;
    unsigned len = (unsigned) datalen;

    /*
     * stderr data is just spouted to local stderr and otherwise
     * ignored.
     */
    if (is_stderr) {
	if (len > 0)
	    fwrite(data, 1, len, stderr);
	return 0;
    }

    /*
     * If this is before the real session begins, just return.
     */
    if (!outptr)
	return 0;

    if ((outlen > 0) && (len > 0)) {
	unsigned used = outlen;
	if (used > len)
	    used = len;
	memcpy(outptr, p, used);
	outptr += used;
	outlen -= used;
	p += used;
	len -= used;
    }

    if (len > 0) {
	if (pendsize < pendlen + len) {
	    pendsize = pendlen + len + 4096;
	    pending = sresize(pending, pendsize, unsigned char);
	}
	memcpy(pending + pendlen, p, len);
	pendlen += len;
    }

    return 0;
}
int sftp_recvdata(char *buf, int len)
{
    outptr = (unsigned char *) buf;
    outlen = len;

    /*
     * See if the pending-input block contains some of what we
     * need.
     */
    if (pendlen > 0) {
	unsigned pendused = pendlen;
	if (pendused > outlen)
	    pendused = outlen;
	memcpy(outptr, pending, pendused);
	memmove(pending, pending + pendused, pendlen - pendused);
	outptr += pendused;
	outlen -= pendused;
	pendlen -= pendused;
	if (pendlen == 0) {
	    pendsize = 0;
	    sfree(pending);
	    pending = NULL;
	}
	if (outlen == 0)
	    return 1;
    }

    while (outlen > 0) {
	if (ssh_sftp_loop_iteration() < 0)
	    return 0;		       /* doom */
    }

    return 1;
}
int sftp_senddata(char *buf, int len)
{
    back->send(backhandle, buf, len);
    return 1;
}


/*
 * Connect to a host.
 */
static int psftp_connect(char *userhost, char *user, int portnumber, int use_compression, int protocol)
{
    char *host, *realhost;
    const char *err;
    
    /* Separate host and username */
    host = userhost;
    host = strrchr(host, '@');
    if (host == NULL) {
	host = userhost;
    } else {
	*host++ = '\0';
	if (user) {
	    printf("psftp: multiple usernames specified; using \"%s\"\n",
		   user);
	} else
	    user = userhost;
    }

    /* Try to load settings for this host */
    do_defaults(host, &cfg);
    if (cfg.host[0] == '\0') {
	/* No settings for this host; use defaults */
	do_defaults(NULL, &cfg);
	strncpy(cfg.host, host, sizeof(cfg.host) - 1);
	cfg.host[sizeof(cfg.host) - 1] = '\0';
    }

    /*
     * Force use of SSH. (If they got the protocol wrong we assume the
     * port is useless too.)
     */
    if (cfg.protocol != PROT_SSH) {
        cfg.protocol = PROT_SSH;
        cfg.port = 22;
    }

    /*
     * Enact command-line overrides.
     */
    cmdline_run_saved(&cfg);

    /*
     * Trim leading whitespace off the hostname if it's there.
     */
    {
	int space = strspn(cfg.host, " \t");
	memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
    }

    /* See if host is of the form user@host */
    if (cfg.host[0] != '\0') {
	char *atsign = strchr(cfg.host, '@');
	/* Make sure we're not overflowing the user field */
	if (atsign) {
	    if (atsign - cfg.host < sizeof cfg.username) {
		strncpy(cfg.username, cfg.host, atsign - cfg.host);
		cfg.username[atsign - cfg.host] = '\0';
	    }
	    memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
	}
    }

    /*
     * Trim a colon suffix off the hostname if it's there.
     */
    cfg.host[strcspn(cfg.host, ":")] = '\0';

    /*
     * Remove any remaining whitespace from the hostname.
     */
    {
	int p1 = 0, p2 = 0;
	while (cfg.host[p2] != '\0') {
	    if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
		cfg.host[p1] = cfg.host[p2];
		p1++;
	    }
	    p2++;
	}
	cfg.host[p1] = '\0';
    }

    /* Set username */
    if (user != NULL && user[0] != '\0') {
	strncpy(cfg.username, user, sizeof(cfg.username) - 1);
	cfg.username[sizeof(cfg.username) - 1] = '\0';
    }
    if (!cfg.username[0]) {
	printf("login as: ");
	fflush(stdout);
	if (!fgets(cfg.username, sizeof(cfg.username), stdin)) {
	    fprintf(stderr, "psftp: aborting\n");
	    cleanup_exit(1);
	} else {
	    int len = strlen(cfg.username);
	    if (cfg.username[len - 1] == '\n')
		cfg.username[len - 1] = '\0';
	}
    }

    if (portnumber)
	cfg.port = portnumber;

    /* SFTP uses SSH2 by default always */
    cfg.sshprot = 2;

    /* Override compression and protocol */
    if (use_compression == 1)
	cfg.compression = 1;
    else if (use_compression == 2)
	cfg.compression = 0;
    if (protocol == 1)
	cmdline_process_param("-1", 0, 0, &cfg);
    else if (protocol == 2)
	cmdline_process_param("-2", 0, 0, &cfg);
    
    /*
     * Disable scary things which shouldn't be enabled for simple
     * things like SCP and SFTP: agent forwarding, port forwarding,
     * X forwarding.
     */
    cfg.x11_forward = 0;
    cfg.agentfwd = 0;
    cfg.portfwd[0] = cfg.portfwd[1] = '\0';

    /* Set up subsystem name. */
    strcpy(cfg.remote_cmd, "sftp");
    cfg.ssh_subsys = TRUE;
    cfg.nopty = TRUE;

    /*
     * Set up fallback option, for SSH1 servers or servers with the
     * sftp subsystem not enabled but the server binary installed
     * in the usual place. We only support fallback on Unix
     * systems, and we use a kludgy piece of shellery which should
     * try to find sftp-server in various places (the obvious
     * systemwide spots /usr/lib and /usr/local/lib, and then the
     * user's PATH) and finally give up.
     * 
     *   test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server
     *   test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server
     *   exec sftp-server
     * 
     * the idea being that this will attempt to use either of the
     * obvious pathnames and then give up, and when it does give up
     * it will print the preferred pathname in the error messages.
     */
    cfg.remote_cmd_ptr2 =
	"test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n"
	"test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n"
	"exec sftp-server";
    cfg.ssh_subsys2 = FALSE;

    back = &ssh_backend;

    err = back->init(NULL, &backhandle, &cfg, cfg.host, cfg.port, &realhost,
						0, cfg.tcp_keepalives);
    if (err != NULL) {
	fprintf(stderr, "ssh_init: %s\n", err);
	return 1;
    }
    while (!back->sendok(backhandle)) {
	if (ssh_sftp_loop_iteration() < 0) {
	    fprintf(stderr, "ssh_init: error during SSH connection setup\n");
	    return 1;
	}
    }
    if (verbose && realhost != NULL)
	printf("Connected to %s\n", realhost);
    return 0;
}

void cmdline_error(char *p, ...)
{
    va_list ap;
    fprintf(stderr, "psftp: ");
    va_start(ap, p);
    vfprintf(stderr, p, ap);
    va_end(ap);
    fprintf(stderr, "\n       try typing \"psftp -h\" for help\n");
    exit(1);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	bLTrace=TRUE;
	flags = FLAG_STDERR | FLAG_INTERACTIVE | FLAG_VERBOSE | FLAG_SYNCAGENT;
	cmdline_tooltype = TOOLTYPE_FILETRANSFER;
	ssh_get_line = &console_get_line;
	sk_init();

	if (!FzSFtpIpc_Init(lpCmdLine))
	{
		MessageBoxA(0, "Error: You can't start FzSFtp directly. It can only by started from FileZilla when connecting to an SFTP server.", "FzSFtp Error", MB_OK);
		return 1;
	}

	FzSFtpIpc_Trace("FzSFtp started and initialized.");
	while (TRUE)
	{
		char pMem[20480];
		DWORD nID, nDataLength;
		BOOL res=FzSFtpIpc_ReceiveRequest(&nID, &nDataLength, pMem);
		if (!res)
			break;
		switch(nID)
		{
		case SFTP_DATAID_STC_CONNECT:
			if (!nDataLength)
				cleanup_exit(1);
			{
			char *host;
			int port;
			char *user;
			char *pass;
			int use_compression;
			int protocol;

			host = pMem;
			port = *(int *)(pMem+strlen(host)+1);
			user = pMem+strlen(host)+1+4;
			pass = pMem+strlen(host)+1+4 + strlen(user) + 1;
			use_compression = *(pMem+strlen(host)+1+4 + strlen(user) + 1 + strlen(pass) + 1);
			protocol = *(pMem+strlen(host)+1+4 + strlen(user) + 1 + strlen(pass) + 2);
			cmdline_process_param("-pw", pass, 0, &cfg);
			if (psftp_connect (host, user, port, use_compression, protocol)<0)
				cleanup_exit(1);
			if (do_sftp_init())
				cleanup_exit(1);
			}
			break;
		case SFTP_DATAID_STC_PWD:
			if (sftp_cmd_pwd(0)<0)
				cleanup_exit(1);
			break;
		case SFTP_DATAID_STC_LIST:
			if (sftp_cmd_ls()<0)
				cleanup_exit(1);
			break;
		case SFTP_DATAID_STC_CD:
			if (!nDataLength)
				cleanup_exit(1);
			if (sftp_cmd_cd(pMem)<0)
				cleanup_exit(1);
			break;
		case SFTP_DATAID_STC_TRACE:
			if (nDataLength!=4)
				cleanup_exit(1);
			bLTrace=*(BOOL*)pMem;
			break;
		case SFTP_DATAID_STC_MKD:
			if (!nDataLength)
				cleanup_exit(1);
			sftp_cmd_mkdir(pMem);
			break;
		case SFTP_DATAID_STC_GET:
			if (!nDataLength)
				cleanup_exit(1);
			sftp_general_get(pMem, pMem+strlen(pMem)+1, *(int *)(pMem+strlen(pMem)+1+strlen(pMem+strlen(pMem)+1)+1) );
			break;
		case SFTP_DATAID_STC_PUT:
			if (!nDataLength)
				cleanup_exit(1);
			sftp_general_put(pMem, pMem+strlen(pMem)+1, *(int *)(pMem+strlen(pMem)+1+strlen(pMem+strlen(pMem)+1)+1) );
			break;
		case SFTP_DATAID_STC_RMD:
			if (!nDataLength)
				cleanup_exit(1);
			if (sftp_cmd_rmdir(pMem)<0)
				cleanup_exit(1);
			break;
		case SFTP_DATAID_STC_DELE:
			if (!nDataLength)
				cleanup_exit(1);
			if (sftp_cmd_rm(pMem)<0)
				cleanup_exit(1);
			break;
		case SFTP_DATAID_STC_RENAME:
			if (!nDataLength)
				cleanup_exit(1);
			sftp_cmd_mv(pMem, pMem+strlen(pMem)+1);
			break;
		case SFTP_DATAID_STC_CHMOD:
			if (!nDataLength)
				cleanup_exit(1);
			sftp_cmd_chmod(pMem, pMem+strlen(pMem)+1);
			break;
		case SFTP_DATAID_STC_FDREAD:
		case SFTP_DATAID_STC_FDWRITE:
			break;
		default:
			FzSFtpIpc_Trace("Unknown command, will be ignored");
			break;
		}
	}

        random_save_seed();

	return 0;
}

⌨️ 快捷键说明

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