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

📄 sftp.c

📁 OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	case I_MKDIR:		path1 = make_absolute(path1, *pwd);		attrib_clear(&a);		a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;		a.perm = 0777;		err = do_mkdir(conn, path1, &a);		break;	case I_RMDIR:		path1 = make_absolute(path1, *pwd);		err = do_rmdir(conn, path1);		break;	case I_CHDIR:		path1 = make_absolute(path1, *pwd);		if ((tmp = do_realpath(conn, path1)) == NULL) {			err = 1;			break;		}		if ((aa = do_stat(conn, tmp, 0)) == NULL) {			xfree(tmp);			err = 1;			break;		}		if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {			error("Can't change directory: Can't check target");			xfree(tmp);			err = 1;			break;		}		if (!S_ISDIR(aa->perm)) {			error("Can't change directory: \"%s\" is not "			    "a directory", tmp);			xfree(tmp);			err = 1;			break;		}		xfree(*pwd);		*pwd = tmp;		break;	case I_LS:		if (!path1) {			do_globbed_ls(conn, *pwd, *pwd, lflag);			break;		}		/* Strip pwd off beginning of non-absolute paths */		tmp = NULL;		if (*path1 != '/')			tmp = *pwd;		path1 = make_absolute(path1, *pwd);		err = do_globbed_ls(conn, path1, tmp, lflag);		break;	case I_LCHDIR:		if (chdir(path1) == -1) {			error("Couldn't change local directory to "			    "\"%s\": %s", path1, strerror(errno));			err = 1;		}		break;	case I_LMKDIR:		if (mkdir(path1, 0777) == -1) {			error("Couldn't create local directory "			    "\"%s\": %s", path1, strerror(errno));			err = 1;		}		break;	case I_LLS:		local_do_ls(cmd);		break;	case I_SHELL:		local_do_shell(cmd);		break;	case I_LUMASK:		umask(n_arg);		printf("Local umask: %03lo\n", n_arg);		break;	case I_CHMOD:		path1 = make_absolute(path1, *pwd);		attrib_clear(&a);		a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;		a.perm = n_arg;		remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);		for (i = 0; g.gl_pathv[i] && !interrupted; i++) {			printf("Changing mode on %s\n", g.gl_pathv[i]);			err = do_setstat(conn, g.gl_pathv[i], &a);			if (err != 0 && err_abort)				break;		}		break;	case I_CHOWN:	case I_CHGRP:		path1 = make_absolute(path1, *pwd);		remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);		for (i = 0; g.gl_pathv[i] && !interrupted; i++) {			if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {				if (err != 0 && err_abort)					break;				else					continue;			}			if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {				error("Can't get current ownership of "				    "remote file \"%s\"", g.gl_pathv[i]);				if (err != 0 && err_abort)					break;				else					continue;			}			aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;			if (cmdnum == I_CHOWN) {				printf("Changing owner on %s\n", g.gl_pathv[i]);				aa->uid = n_arg;			} else {				printf("Changing group on %s\n", g.gl_pathv[i]);				aa->gid = n_arg;			}			err = do_setstat(conn, g.gl_pathv[i], aa);			if (err != 0 && err_abort)				break;		}		break;	case I_PWD:		printf("Remote working directory: %s\n", *pwd);		break;	case I_LPWD:		if (!getcwd(path_buf, sizeof(path_buf))) {			error("Couldn't get local cwd: %s", strerror(errno));			err = -1;			break;		}		printf("Local working directory: %s\n", path_buf);		break;	case I_QUIT:		/* Processed below */		break;	case I_HELP:		help();		break;	case I_VERSION:		printf("SFTP protocol version %u\n", sftp_proto_version(conn));		break;	case I_PROGRESS:		showprogress = !showprogress;		if (showprogress)			printf("Progress meter enabled\n");		else			printf("Progress meter disabled\n");		break;	default:		fatal("%d is not implemented", cmdnum);	}	if (g.gl_pathc)		globfree(&g);	if (path1)		xfree(path1);	if (path2)		xfree(path2);	/* If an unignored error occurs in batch mode we should abort. */	if (err_abort && err != 0)		return (-1);	else if (cmdnum == I_QUIT)		return (1);	return (0);}#ifdef USE_LIBEDITstatic char *prompt(EditLine *el){	return ("sftp> ");}#endifintinteractive_loop(int fd_in, int fd_out, char *file1, char *file2){	char *pwd;	char *dir = NULL;	char cmd[2048];	struct sftp_conn *conn;	int err;	EditLine *el = NULL;#ifdef USE_LIBEDIT	History *hl = NULL;	HistEvent hev;	extern char *__progname;	if (!batchmode && isatty(STDIN_FILENO)) {		if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)			fatal("Couldn't initialise editline");		if ((hl = history_init()) == NULL)			fatal("Couldn't initialise editline history");		history(hl, &hev, H_SETSIZE, 100);		el_set(el, EL_HIST, history, hl);		el_set(el, EL_PROMPT, prompt);		el_set(el, EL_EDITOR, "emacs");		el_set(el, EL_TERMINAL, NULL);		el_set(el, EL_SIGNAL, 1);		el_source(el, NULL);	}#endif /* USE_LIBEDIT */	conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);	if (conn == NULL)		fatal("Couldn't initialise connection to server");	pwd = do_realpath(conn, ".");	if (pwd == NULL)		fatal("Need cwd");	if (file1 != NULL) {		dir = xstrdup(file1);		dir = make_absolute(dir, pwd);		if (remote_is_dir(conn, dir) && file2 == NULL) {			printf("Changing to: %s\n", dir);			snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);			if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) {				xfree(dir);				xfree(pwd);				return (-1);			}		} else {			if (file2 == NULL)				snprintf(cmd, sizeof cmd, "get %s", dir);			else				snprintf(cmd, sizeof cmd, "get %s %s", dir,				    file2);			err = parse_dispatch_command(conn, cmd, &pwd, 1);			xfree(dir);			xfree(pwd);			return (err);		}		xfree(dir);	}#if HAVE_SETVBUF	setvbuf(stdout, NULL, _IOLBF, 0);	setvbuf(infile, NULL, _IOLBF, 0);#else       setlinebuf(stdout);       setlinebuf(infile);#endif	err = 0;	for (;;) {		char *cp;		signal(SIGINT, SIG_IGN);		if (el == NULL) {			printf("sftp> ");			if (fgets(cmd, sizeof(cmd), infile) == NULL) {				printf("\n");				break;			}			if (batchmode) /* Echo command */				printf("%s", cmd);		} else {#ifdef USE_LIBEDIT			const char *line;			int count = 0;			if ((line = el_gets(el, &count)) == NULL || count <= 0)				break;			history(hl, &hev, H_ENTER, line);			if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {				fprintf(stderr, "Error: input line too long\n");				continue;			}#endif /* USE_LIBEDIT */		}		cp = strrchr(cmd, '\n');		if (cp)			*cp = '\0';		/* Handle user interrupts gracefully during commands */		interrupted = 0;		signal(SIGINT, cmd_interrupt);		err = parse_dispatch_command(conn, cmd, &pwd, batchmode);		if (err != 0)			break;	}	xfree(pwd);	/* err == 1 signifies normal "quit" exit */	return (err >= 0 ? 0 : -1);}static voidconnect_to_server(char *path, char **args, int *in, int *out){	int c_in, c_out;#ifdef USE_PIPES	int pin[2], pout[2];	if ((pipe(pin) == -1) || (pipe(pout) == -1))		fatal("pipe: %s", strerror(errno));	*in = pin[0];	*out = pout[1];	c_in = pout[0];	c_out = pin[1];#else /* USE_PIPES */	int inout[2];	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)		fatal("socketpair: %s", strerror(errno));	*in = *out = inout[0];	c_in = c_out = inout[1];#endif /* USE_PIPES */	if ((sshpid = fork()) == -1)		fatal("fork: %s", strerror(errno));	else if (sshpid == 0) {		if ((dup2(c_in, STDIN_FILENO) == -1) ||		    (dup2(c_out, STDOUT_FILENO) == -1)) {			fprintf(stderr, "dup2: %s\n", strerror(errno));			_exit(1);		}		close(*in);		close(*out);		close(c_in);		close(c_out);		/*		 * The underlying ssh is in the same process group, so we must		 * ignore SIGINT if we want to gracefully abort commands,		 * otherwise the signal will make it to the ssh process and		 * kill it too		 */		signal(SIGINT, SIG_IGN);		execvp(path, args);		fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));		_exit(1);	}	signal(SIGTERM, killchild);	signal(SIGINT, killchild);	signal(SIGHUP, killchild);	close(c_in);	close(c_out);}static voidusage(void){	extern char *__progname;	fprintf(stderr,	    "usage: %s [-1Cv] [-B buffer_size] [-b batchfile] [-F ssh_config]\n"	    "            [-o ssh_option] [-P sftp_server_path] [-R num_requests]\n"	    "            [-S program] [-s subsystem | sftp_server] host\n"	    "       %s [[user@]host[:file [file]]]\n"	    "       %s [[user@]host[:dir[/]]]\n"	    "       %s -b batchfile [user@]host\n", __progname, __progname, __progname, __progname);	exit(1);}intmain(int argc, char **argv){	int in, out, ch, err;	char *host, *userhost, *cp, *file2 = NULL;	int debug_level = 0, sshver = 2;	char *file1 = NULL, *sftp_server = NULL;	char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;	LogLevel ll = SYSLOG_LEVEL_INFO;	arglist args;	extern int optind;	extern char *optarg;	__progname = ssh_get_progname(argv[0]);	args.list = NULL;	addargs(&args, "ssh");		/* overwritten with ssh_program */	addargs(&args, "-oForwardX11 no");	addargs(&args, "-oForwardAgent no");	addargs(&args, "-oClearAllForwardings yes");	ll = SYSLOG_LEVEL_INFO;	infile = stdin;	while ((ch = getopt(argc, argv, "1hvCo:s:S:b:B:F:P:R:")) != -1) {		switch (ch) {		case 'C':			addargs(&args, "-C");			break;		case 'v':			if (debug_level < 3) {				addargs(&args, "-v");				ll = SYSLOG_LEVEL_DEBUG1 + debug_level;			}			debug_level++;			break;		case 'F':		case 'o':			addargs(&args, "-%c%s", ch, optarg);			break;		case '1':			sshver = 1;			if (sftp_server == NULL)				sftp_server = _PATH_SFTP_SERVER;			break;		case 's':			sftp_server = optarg;			break;		case 'S':			ssh_program = optarg;			break;		case 'b':			if (batchmode)				fatal("Batch file already specified.");			/* Allow "-" as stdin */			if (strcmp(optarg, "-") != 0 &&			   (infile = fopen(optarg, "r")) == NULL)				fatal("%s (%s).", strerror(errno), optarg);			showprogress = 0;			batchmode = 1;			addargs(&args, "-obatchmode yes");			break;		case 'P':			sftp_direct = optarg;			break;		case 'B':			copy_buffer_len = strtol(optarg, &cp, 10);			if (copy_buffer_len == 0 || *cp != '\0')				fatal("Invalid buffer size \"%s\"", optarg);			break;		case 'R':			num_requests = strtol(optarg, &cp, 10);			if (num_requests == 0 || *cp != '\0')				fatal("Invalid number of requests \"%s\"",				    optarg);			break;		case 'h':		default:			usage();		}	}	if (!isatty(STDERR_FILENO))		showprogress = 0;	log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);	if (sftp_direct == NULL) {		if (optind == argc || argc > (optind + 2))			usage();		userhost = xstrdup(argv[optind]);		file2 = argv[optind+1];		if ((host = strrchr(userhost, '@')) == NULL)			host = userhost;		else {			*host++ = '\0';			if (!userhost[0]) {				fprintf(stderr, "Missing username\n");				usage();			}			addargs(&args, "-l%s",userhost);		}		if ((cp = colon(host)) != NULL) {			*cp++ = '\0';			file1 = cp;		}		host = cleanhostname(host);		if (!*host) {			fprintf(stderr, "Missing hostname\n");			usage();		}		addargs(&args, "-oProtocol %d", sshver);		/* no subsystem if the server-spec contains a '/' */		if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)			addargs(&args, "-s");		addargs(&args, "%s", host);		addargs(&args, "%s", (sftp_server != NULL ?		    sftp_server : "sftp"));		args.list[0] = ssh_program;		if (!batchmode)			fprintf(stderr, "Connecting to %s...\n", host);		connect_to_server(ssh_program, args.list, &in, &out);	} else {		args.list = NULL;		addargs(&args, "sftp-server");		if (!batchmode)			fprintf(stderr, "Attaching to %s...\n", sftp_direct);		connect_to_server(sftp_direct, args.list, &in, &out);	}	err = interactive_loop(in, out, file1, file2);#if !defined(USE_PIPES)       shutdown(in, SHUT_RDWR);       shutdown(out, SHUT_RDWR);#endif	close(in);	close(out);	if (batchmode)		fclose(infile);	while (waitpid(sshpid, NULL, 0) == -1)		if (errno != EINTR)			fatal("Couldn't wait for ssh process: %s",			    strerror(errno));	exit(err == 0 ? 0 : 1);}

⌨️ 快捷键说明

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