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

📄 scp.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* * Execute the sink part of the SCP protocol. */static void sink(char *targ, char *src){    char *destfname;    int targisdir = 0;    int exists;    int attr;    WFile *f;    unsigned long received;    int wrerror = 0;    unsigned long stat_bytes;    time_t stat_starttime, stat_lasttime;    char *stat_name;    attr = file_type(targ);    if (attr == FILE_TYPE_DIRECTORY)	targisdir = 1;    if (targetshouldbedirectory && !targisdir)	bump("%s: Not a directory", targ);    scp_sink_init();    while (1) {	struct scp_sink_action act;	if (scp_get_sink_action(&act))	    return;	if (act.action == SCP_SINK_ENDDIR)	    return;	if (act.action == SCP_SINK_RETRY)	    continue;	if (targisdir) {	    /*	     * Prevent the remote side from maliciously writing to	     * files outside the target area by sending a filename	     * containing `../'. In fact, it shouldn't be sending	     * filenames with any slashes or colons in at all; so	     * we'll find the last slash, backslash or colon in the	     * filename and use only the part after that. (And	     * warn!)	     * 	     * In addition, we also ensure here that if we're	     * copying a single file and the target is a directory	     * (common usage: `pscp host:filename .') the remote	     * can't send us a _different_ file name. We can	     * distinguish this case because `src' will be non-NULL	     * and the last component of that will fail to match	     * (the last component of) the name sent.	     * 	     * Well, not always; if `src' is a wildcard, we do	     * expect to get back filenames that don't correspond	     * exactly to it. Ideally in this case, we would like	     * to ensure that the returned filename actually	     * matches the wildcard pattern - but one of SCP's	     * protocol infelicities is that wildcard matching is	     * done at the server end _by the server's rules_ and	     * so in general this is infeasible. Hence, we only	     * accept filenames that don't correspond to `src' if	     * unsafe mode is enabled or we are using SFTP (which	     * resolves remote wildcards on the client side and can	     * be trusted).	     */	    char *striptarget, *stripsrc;	    striptarget = stripslashes(act.name, 1);	    if (striptarget != act.name) {		tell_user(stderr, "warning: remote host sent a compound"			  " pathname '%s'", act.name);		tell_user(stderr, "         renaming local file to '%s'",                          striptarget);	    }	    /*	     * Also check to see if the target filename is '.' or	     * '..', or indeed '...' and so on because Windows	     * appears to interpret those like '..'.	     */	    if (is_dots(striptarget)) {		bump("security violation: remote host attempted to write to"		     " a '.' or '..' path!");	    }	    if (src) {		stripsrc = stripslashes(src, 1);		if (strcmp(striptarget, stripsrc) &&		    !using_sftp && !scp_unsafe_mode) {		    tell_user(stderr, "warning: remote host tried to write "			      "to a file called '%s'", striptarget);		    tell_user(stderr, "         when we requested a file "			      "called '%s'.", stripsrc);		    tell_user(stderr, "         If this is a wildcard, "			      "consider upgrading to SSH 2 or using");		    tell_user(stderr, "         the '-unsafe' option. Renaming"			      " of this file has been disallowed.");		    /* Override the name the server provided with our own. */		    striptarget = stripsrc;		}	    }	    if (targ[0] != '\0')		destfname = dir_file_cat(targ, striptarget);	    else		destfname = dupstr(striptarget);	} else {	    /*	     * In this branch of the if, the target area is a	     * single file with an explicitly specified name in any	     * case, so there's no danger.	     */	    destfname = dupstr(targ);	}	attr = file_type(destfname);	exists = (attr != FILE_TYPE_NONEXISTENT);	if (act.action == SCP_SINK_DIR) {	    if (exists && attr != FILE_TYPE_DIRECTORY) {		run_err("%s: Not a directory", destfname);		continue;	    }	    if (!exists) {		if (!create_directory(destfname)) {		    run_err("%s: Cannot create directory", destfname);		    continue;		}	    }	    sink(destfname, NULL);	    /* can we set the timestamp for directories ? */	    continue;	}	f = open_new_file(destfname);	if (f == NULL) {	    run_err("%s: Cannot create file", destfname);	    continue;	}	if (scp_accept_filexfer())	    return;	stat_bytes = 0;	stat_starttime = time(NULL);	stat_lasttime = 0;	stat_name = stripslashes(destfname, 1);	received = 0;	while (received < act.size) {	    char transbuf[4096];	    unsigned long blksize;	    int read;	    blksize = 4096;	    if (blksize > (act.size - received))		blksize = act.size - received;	    read = scp_recv_filedata(transbuf, (int)blksize);	    if (read <= 0)		bump("Lost connection");	    if (wrerror)		continue;	    if (write_to_file(f, transbuf, read) != (int)read) {		wrerror = 1;		/* FIXME: in sftp we can actually abort the transfer */		if (statistics)		    printf("\r%-25.25s | %50s\n",			   stat_name,			   "Write error.. waiting for end of file");		continue;	    }	    if (statistics) {		stat_bytes += read;		if (time(NULL) > stat_lasttime ||		    received + read == act.size) {		    stat_lasttime = time(NULL);		    print_stats(stat_name, act.size, stat_bytes,				stat_starttime, stat_lasttime);		}	    }	    received += read;	}	if (act.settime) {	    set_file_times(f, act.mtime, act.atime);	}	close_wfile(f);	if (wrerror) {	    run_err("%s: Write error", destfname);	    continue;	}	(void) scp_finish_filerecv();	sfree(destfname);	sfree(act.buf);    }}/* * We will copy local files to a remote server. */static void toremote(int argc, char *argv[]){    char *src, *targ, *host, *user;    char *cmd;    int i, wc_type;    targ = argv[argc - 1];    /* Separate host from filename */    host = targ;    targ = colon(targ);    if (targ == NULL)	bump("targ == NULL in toremote()");    *targ++ = '\0';    if (*targ == '\0')	targ = ".";    /* Substitute "." for emtpy target */    /* Separate host and username */    user = host;    host = strrchr(host, '@');    if (host == NULL) {	host = user;	user = NULL;    } else {	*host++ = '\0';	if (*user == '\0')	    user = NULL;    }    if (argc == 2) {	if (colon(argv[0]) != NULL)	    bump("%s: Remote to remote not supported", argv[0]);	wc_type = test_wildcard(argv[0], 1);	if (wc_type == WCTYPE_NONEXISTENT)	    bump("%s: No such file or directory\n", argv[0]);	else if (wc_type == WCTYPE_WILDCARD)	    targetshouldbedirectory = 1;    }    cmd = dupprintf("scp%s%s%s%s -t %s",		    verbose ? " -v" : "",		    recursive ? " -r" : "",		    preserve ? " -p" : "",		    targetshouldbedirectory ? " -d" : "", targ);    do_cmd(host, user, cmd);    sfree(cmd);    scp_source_setup(targ, targetshouldbedirectory);    for (i = 0; i < argc - 1; i++) {	src = argv[i];	if (colon(src) != NULL) {	    tell_user(stderr, "%s: Remote to remote not supported\n", src);	    errs++;	    continue;	}	wc_type = test_wildcard(src, 1);	if (wc_type == WCTYPE_NONEXISTENT) {	    run_err("%s: No such file or directory", src);	    continue;	} else if (wc_type == WCTYPE_FILENAME) {	    source(src);	    continue;	} else {	    WildcardMatcher *wc;	    char *filename;	    wc = begin_wildcard_matching(src);	    if (wc == NULL) {		run_err("%s: No such file or directory", src);		continue;	    }	    while ((filename = wildcard_get_filename(wc)) != NULL) {		source(filename);		sfree(filename);	    }	    finish_wildcard_matching(wc);	}    }}/* *  We will copy files from a remote server to the local machine. */static void tolocal(int argc, char *argv[]){    char *src, *targ, *host, *user;    char *cmd;    if (argc != 2)	bump("More than one remote source not supported");    src = argv[0];    targ = argv[1];    /* Separate host from filename */    host = src;    src = colon(src);    if (src == NULL)	bump("Local to local copy not supported");    *src++ = '\0';    if (*src == '\0')	src = ".";    /* Substitute "." for empty filename */    /* Separate username and hostname */    user = host;    host = strrchr(host, '@');    if (host == NULL) {	host = user;	user = NULL;    } else {	*host++ = '\0';	if (*user == '\0')	    user = NULL;    }    cmd = dupprintf("scp%s%s%s%s -f %s",		    verbose ? " -v" : "",		    recursive ? " -r" : "",		    preserve ? " -p" : "",		    targetshouldbedirectory ? " -d" : "", src);    do_cmd(host, user, cmd);    sfree(cmd);    if (scp_sink_setup(src, preserve, recursive))	return;    sink(targ, src);}/* *  We will issue a list command to get a remote directory. */static void get_dir_list(int argc, char *argv[]){    char *src, *host, *user;    char *cmd, *p, *q;    char c;    src = argv[0];    /* Separate host from filename */    host = src;    src = colon(src);    if (src == NULL)	bump("Local to local copy not supported");    *src++ = '\0';    if (*src == '\0')	src = ".";    /* Substitute "." for empty filename */    /* Separate username and hostname */    user = host;    host = strrchr(host, '@');    if (host == NULL) {	host = user;	user = NULL;    } else {	*host++ = '\0';	if (*user == '\0')	    user = NULL;    }    cmd = snewn(4 * strlen(src) + 100, char);    strcpy(cmd, "ls -la '");    p = cmd + strlen(cmd);    for (q = src; *q; q++) {	if (*q == '\'') {	    *p++ = '\'';	    *p++ = '\\';	    *p++ = '\'';	    *p++ = '\'';	} else {	    *p++ = *q;	}    }    *p++ = '\'';    *p = '\0';    do_cmd(host, user, cmd);    sfree(cmd);    if (using_sftp) {	scp_sftp_listdir(src);    } else {	while (ssh_scp_recv((unsigned char *) &c, 1) > 0)	    tell_char(stdout, c);    }}/* *  Short description of parameters. */static void usage(void){    printf("PuTTY Secure Copy client\n");    printf("%s\n", ver);    printf("Usage: pscp [options] [user@]host:source target\n");    printf	("       pscp [options] source [source...] [user@]host:target\n");    printf("       pscp [options] -ls [user@]host:filespec\n");    printf("Options:\n");    printf("  -p        preserve file attributes\n");    printf("  -q        quiet, don't show statistics\n");    printf("  -r        copy directories recursively\n");    printf("  -v        show verbose messages\n");    printf("  -load sessname  Load settings from saved session\n");    printf("  -P port   connect to specified port\n");    printf("  -l user   connect with specified username\n");    printf("  -pw passw login with specified password\n");    printf("  -1 -2     force use of particular SSH protocol version\n");    printf("  -C        enable compression\n");    printf("  -i key    private key file for authentication\n");    printf("  -batch    disable all interactive prompts\n");    printf("  -unsafe   allow server-side wildcards (DANGEROUS)\n");    printf("  -V        print version information\n");    printf("  -sftp     force use of SFTP protocol\n");    printf("  -scp      force use of SCP protocol\n");#if 0    /*     * -gui is an internal option, used by GUI front ends to get     * pscp to pass progress reports back to them. It's not an     * ordinary user-accessible option, so it shouldn't be part of     * the command-line help. The only people who need to know     * about it are programmers, and they can read the source.     */    printf	("  -gui hWnd GUI mode with the windows handle for receiving messages\n");#endif    cleanup_exit(1);}void version(void){    printf("pscp: %s\n", ver);    cleanup_exit(1);}void cmdline_error(char *p, ...){    va_list ap;    fprintf(stderr, "pscp: ");    va_start(ap, p);    vfprintf(stderr, p, ap);    va_end(ap);    fprintf(stderr, "\n      try typing just \"pscp\" for help\n");    exit(1);}/* * Main program. (Called `psftp_main' because it gets called from * *sftp.c; bit silly, I know, but it had to be called _something_.) */int psftp_main(int argc, char *argv[]){    int i;    statics()->default_protocol = PROT_TELNET;    statics()->flags = FLAG_STDERR#ifdef FLAG_SYNCAGENT	| FLAG_SYNCAGENT#endif	;    cmdline_tooltype = TOOLTYPE_FILETRANSFER;    statics()->ssh_get_line = &console_get_line;    sk_init();    /* Load Default Settings before doing anything else. */    do_defaults(NULL, &cfg);    loaded_session = FALSE;    for (i = 1; i < argc; i++) {	int ret;	if (argv[i][0] != '-')	    break;	ret = cmdline_process_param(argv[i], i+1<argc?argv[i+1]:NULL, 1, &cfg);	if (ret == -2) {	    cmdline_error("option \"%s\" requires an argument", argv[i]);	} else if (ret == 2) {	    i++;	       /* skip next argument */	} else if (ret == 1) {	    /* We have our own verbosity in addition to `flags'. */	    if (statics()->flags & FLAG_VERBOSE)		verbose = 1;	} else if (strcmp(argv[i], "-r") == 0) {	    recursive = 1;	} else if (strcmp(argv[i], "-p") == 0) {	    preserve = 1;	} else if (strcmp(argv[i], "-q") == 0) {	    statistics = 0;	} else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0) {	    usage();	} else if (strcmp(argv[i], "-V") == 0) {            version();	} else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {	    gui_enable(argv[++i]);	    gui_mode = 1;	    console_batch_mode = TRUE;        } else if (strcmp(argv[i], "-ls") == 0) {	    list = 1;	} else if (strcmp(argv[i], "-batch") == 0) {	    console_batch_mode = 1;	} else if (strcmp(argv[i], "-unsafe") == 0) {	    scp_unsafe_mode = 1;	} else if (strcmp(argv[i], "-sftp") == 0) {	    try_scp = 0; try_sftp = 1;	} else if (strcmp(argv[i], "-scp") == 0) {	    try_scp = 1; try_sftp = 0;	} else if (strcmp(argv[i], "--") == 0) {	    i++;	    break;	} else {	    cmdline_error("unknown option \"%s\"", argv[i]);	}    }    argc -= i;    argv += i;    back = NULL;    if (list) {	if (argc != 1)	    usage();	get_dir_list(argc, argv);    } else {	if (argc < 2)	    usage();	if (argc > 2)	    targetshouldbedirectory = 1;	if (colon(argv[argc - 1]) != NULL)	    toremote(argc, argv);	else	    tolocal(argc, argv);    }    if (back != NULL && back->socket(backhandle) != NULL) {	char ch;	back->special(backhandle, TS_EOF);	ssh_scp_recv((unsigned char *) &ch, 1);    }    random_save_seed();    if (gui_mode)	gui_send_errcount(list, errs);    cmdline_cleanup();    console_provide_logctx(NULL);    back->free(backhandle);    backhandle = NULL;    back = NULL;    sk_cleanup();    return (errs == 0 ? 0 : 1);}/* end */

⌨️ 快捷键说明

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