mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	Update to scp from OpenSSH portable 4.3p2
--HG-- extra : convert_revision : e2bccdd6ba49edd575b1d0272c7dfee5f9f7acf6
This commit is contained in:
		
							parent
							
								
									a7a5365af2
								
							
						
					
					
						commit
						3a5c4b68bb
					
				| @ -252,6 +252,8 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */ | ||||
| 
 | ||||
| #define _PATH_TTY "/dev/tty" | ||||
| 
 | ||||
| #define _PATH_CP "/bin/cp" | ||||
| 
 | ||||
| /* Timeouts in seconds */ | ||||
| #define SELECT_TIMEOUT 20 | ||||
| 
 | ||||
|  | ||||
| @ -24,7 +24,7 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "includes.h" | ||||
| /*RCSID("OpenBSD: progressmeter.c,v 1.15 2003/08/31 12:14:22 markus Exp ");*/ | ||||
| /*RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");*/ | ||||
| 
 | ||||
| #include "progressmeter.h" | ||||
| #include "atomicio.h" | ||||
| @ -43,21 +43,26 @@ static int can_output(void); | ||||
| static void format_size(char *, int, off_t); | ||||
| static void format_rate(char *, int, off_t); | ||||
| 
 | ||||
| /* window resizing */ | ||||
| static void sig_winch(int); | ||||
| static void setscreensize(void); | ||||
| 
 | ||||
| /* updates the progressmeter to reflect the current state of the transfer */ | ||||
| void refresh_progress_meter(void); | ||||
| 
 | ||||
| /* signal handler for updating the progress meter */ | ||||
| static void update_progress_meter(int); | ||||
| 
 | ||||
| static time_t start; 		/* start progress */ | ||||
| static time_t last_update; 	/* last progress update */ | ||||
| static char *file; 		/* name of the file being transferred */ | ||||
| static off_t end_pos; 		/* ending position of transfer */ | ||||
| static off_t cur_pos; 		/* transfer position as of last refresh */ | ||||
| static time_t start;		/* start progress */ | ||||
| static time_t last_update;	/* last progress update */ | ||||
| static char *file;		/* name of the file being transferred */ | ||||
| static off_t end_pos;		/* ending position of transfer */ | ||||
| static off_t cur_pos;		/* transfer position as of last refresh */ | ||||
| static volatile off_t *counter;	/* progress counter */ | ||||
| static long stalled; 		/* how long we have been stalled */ | ||||
| static int bytes_per_second; 	/* current speed in bytes per second */ | ||||
| static int win_size; 		/* terminal window size */ | ||||
| static long stalled;		/* how long we have been stalled */ | ||||
| static int bytes_per_second;	/* current speed in bytes per second */ | ||||
| static int win_size;		/* terminal window size */ | ||||
| static volatile sig_atomic_t win_resized; /* for window resizing */ | ||||
| 
 | ||||
| /* units for format_size */ | ||||
| static const char unit[] = " KMGT"; | ||||
| @ -81,8 +86,8 @@ format_rate(char *buf, int size, off_t bytes) | ||||
| 		bytes = (bytes + 512) / 1024; | ||||
| 	} | ||||
| 	snprintf(buf, size, "%3lld.%1lld%c%s", | ||||
| 	    (int64_t) bytes / 100, | ||||
| 	    (int64_t) (bytes + 5) / 10 % 10, | ||||
| 	    (long long) (bytes + 5) / 100, | ||||
| 	    (long long) (bytes + 5) / 10 % 10, | ||||
| 	    unit[i], | ||||
| 	    i ? "B" : " "); | ||||
| } | ||||
| @ -95,7 +100,7 @@ format_size(char *buf, int size, off_t bytes) | ||||
| 	for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++) | ||||
| 		bytes = (bytes + 512) / 1024; | ||||
| 	snprintf(buf, size, "%4lld%c%s", | ||||
| 	    (int64_t) bytes, | ||||
| 	    (long long) bytes, | ||||
| 	    unit[i], | ||||
| 	    i ? "B" : " "); | ||||
| } | ||||
| @ -108,7 +113,7 @@ refresh_progress_meter(void) | ||||
| 	off_t transferred; | ||||
| 	double elapsed; | ||||
| 	int percent; | ||||
| 	int bytes_left; | ||||
| 	off_t bytes_left; | ||||
| 	int cur_speed; | ||||
| 	int hours, minutes, seconds; | ||||
| 	int i, len; | ||||
| @ -121,14 +126,18 @@ refresh_progress_meter(void) | ||||
| 
 | ||||
| 	if (bytes_left > 0) | ||||
| 		elapsed = now - last_update; | ||||
| 	else | ||||
| 	else { | ||||
| 		elapsed = now - start; | ||||
| 		/* Calculate true total speed when done */ | ||||
| 		transferred = end_pos; | ||||
| 		bytes_per_second = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	/* calculate speed */ | ||||
| 	if (elapsed != 0) | ||||
| 		cur_speed = (transferred / elapsed); | ||||
| 	else | ||||
| 		cur_speed = 0; | ||||
| 		cur_speed = transferred; | ||||
| 
 | ||||
| #define AGE_FACTOR 0.9 | ||||
| 	if (bytes_per_second != 0) { | ||||
| @ -144,6 +153,8 @@ refresh_progress_meter(void) | ||||
| 		len = snprintf(buf, file_len + 1, "\r%s", file); | ||||
| 		if (len < 0) | ||||
| 			len = 0; | ||||
| 		if (len >= file_len + 1) | ||||
| 			len = file_len; | ||||
| 		for (i = len;  i < file_len; i++ ) | ||||
| 			buf[i] = ' '; | ||||
| 		buf[file_len] = '\0'; | ||||
| @ -164,7 +175,7 @@ refresh_progress_meter(void) | ||||
| 
 | ||||
| 	/* bandwidth usage */ | ||||
| 	format_rate(buf + strlen(buf), win_size - strlen(buf), | ||||
| 	    bytes_per_second); | ||||
| 	    (off_t)bytes_per_second); | ||||
| 	strlcat(buf, "/s ", win_size); | ||||
| 
 | ||||
| 	/* ETA */ | ||||
| @ -201,7 +212,7 @@ refresh_progress_meter(void) | ||||
| 			strlcat(buf, "    ", win_size); | ||||
| 	} | ||||
| 
 | ||||
| 	atomicio(vwrite, STDOUT_FILENO, buf, win_size); | ||||
| 	atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1); | ||||
| 	last_update = now; | ||||
| } | ||||
| 
 | ||||
| @ -212,6 +223,10 @@ update_progress_meter(int ignore) | ||||
| 
 | ||||
| 	save_errno = errno; | ||||
| 
 | ||||
| 	if (win_resized) { | ||||
| 		setscreensize(); | ||||
| 		win_resized = 0; | ||||
| 	} | ||||
| 	if (can_output()) | ||||
| 		refresh_progress_meter(); | ||||
| 
 | ||||
| @ -221,32 +236,22 @@ update_progress_meter(int ignore) | ||||
| } | ||||
| 
 | ||||
| void | ||||
| start_progress_meter(char *f, off_t filesize, off_t *stat) | ||||
| start_progress_meter(char *f, off_t filesize, off_t *ctr) | ||||
| { | ||||
| 	struct winsize winsize; | ||||
| 
 | ||||
| 	start = last_update = time(NULL); | ||||
| 	file = f; | ||||
| 	end_pos = filesize; | ||||
| 	cur_pos = 0; | ||||
| 	counter = stat; | ||||
| 	counter = ctr; | ||||
| 	stalled = 0; | ||||
| 	bytes_per_second = 0; | ||||
| 
 | ||||
| 	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 && | ||||
| 	    winsize.ws_col != 0) { | ||||
| 		if (winsize.ws_col > MAX_WINSIZE) | ||||
| 			win_size = MAX_WINSIZE; | ||||
| 		else | ||||
| 			win_size = winsize.ws_col; | ||||
| 	} else | ||||
| 		win_size = DEFAULT_WINSIZE; | ||||
| 	win_size += 1;					/* trailing \0 */ | ||||
| 
 | ||||
| 	setscreensize(); | ||||
| 	if (can_output()) | ||||
| 		refresh_progress_meter(); | ||||
| 
 | ||||
| 	signal(SIGALRM, update_progress_meter); | ||||
| 	signal(SIGWINCH, sig_winch); | ||||
| 	alarm(UPDATE_INTERVAL); | ||||
| } | ||||
| 
 | ||||
| @ -264,4 +269,26 @@ stop_progress_meter(void) | ||||
| 
 | ||||
| 	atomicio(vwrite, STDOUT_FILENO, "\n", 1); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| sig_winch(int sig) | ||||
| { | ||||
| 	win_resized = 1; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| setscreensize(void) | ||||
| { | ||||
| 	struct winsize winsize; | ||||
| 
 | ||||
| 	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 && | ||||
| 	    winsize.ws_col != 0) { | ||||
| 		if (winsize.ws_col > MAX_WINSIZE) | ||||
| 			win_size = MAX_WINSIZE; | ||||
| 		else | ||||
| 			win_size = winsize.ws_col; | ||||
| 	} else | ||||
| 		win_size = DEFAULT_WINSIZE; | ||||
| 	win_size += 1;					/* trailing \0 */ | ||||
| } | ||||
| #endif /* PROGRESS_METER */ | ||||
|  | ||||
							
								
								
									
										343
									
								
								scp.c
									
									
									
									
									
								
							
							
						
						
									
										343
									
								
								scp.c
									
									
									
									
									
								
							| @ -71,40 +71,20 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "includes.h" | ||||
| /*RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");*/ | ||||
| 
 | ||||
| #include "atomicio.h" | ||||
| #include "compat.h" | ||||
| #include "scpmisc.h" | ||||
| #include "progressmeter.h" | ||||
| 
 | ||||
| #define _PATH_CP "/bin/cp" | ||||
| 
 | ||||
| #ifndef TIMEVAL_TO_TIMESPEC | ||||
| #define	TIMEVAL_TO_TIMESPEC(tv, ts) {					\ | ||||
| 	(ts)->tv_sec = (tv)->tv_sec;					\ | ||||
| 	(ts)->tv_nsec = (tv)->tv_usec * 1000;				\ | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef timersub | ||||
| #define timersub(tvp, uvp, vvp)					 \ | ||||
| 	do {								\ | ||||
| 		(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;	  \ | ||||
| 		(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;   \ | ||||
| 		if ((vvp)->tv_usec < 0) {			   \ | ||||
| 			(vvp)->tv_sec--;				\ | ||||
| 			(vvp)->tv_usec += 1000000;		  \ | ||||
| 		}						   \ | ||||
| 	} while (/* CONSTCOND */ 0) | ||||
| #endif /* timersub */ | ||||
| 
 | ||||
| 
 | ||||
| void bwlimit(int); | ||||
| 
 | ||||
| /* Struct for addargs */ | ||||
| arglist args; | ||||
| 
 | ||||
| /* Bandwidth limit */ | ||||
| off_t limitbw = 0; | ||||
| off_t limit_rate = 0; | ||||
| 
 | ||||
| /* Name of current file being transferred. */ | ||||
| char *curfile; | ||||
| @ -112,10 +92,8 @@ char *curfile; | ||||
| /* This is set to non-zero to enable verbose mode. */ | ||||
| int verbose_mode = 0; | ||||
| 
 | ||||
| #ifdef PROGRESS_METER | ||||
| /* This is set to zero if the progressmeter is not desired. */ | ||||
| int showprogress = 1; | ||||
| #endif | ||||
| 
 | ||||
| /* This is the program to execute for the secured connection. ("ssh" or -S) */ | ||||
| char *ssh_program = _PATH_SSH_PROGRAM; | ||||
| @ -126,10 +104,56 @@ pid_t do_cmd_pid = -1; | ||||
| static void | ||||
| killchild(int signo) | ||||
| { | ||||
| 	if (do_cmd_pid > 1) | ||||
| 		kill(do_cmd_pid, signo); | ||||
| 	if (do_cmd_pid > 1) { | ||||
| 		kill(do_cmd_pid, signo ? signo : SIGTERM); | ||||
| 		waitpid(do_cmd_pid, NULL, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	_exit(1); | ||||
| 	if (signo) | ||||
| 		_exit(1); | ||||
| 	exit(1); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| do_local_cmd(arglist *a) | ||||
| { | ||||
| 	u_int i; | ||||
| 	int status; | ||||
| 	pid_t pid; | ||||
| 
 | ||||
| 	if (a->num == 0) | ||||
| 		fatal("do_local_cmd: no arguments"); | ||||
| 
 | ||||
| 	if (verbose_mode) { | ||||
| 		fprintf(stderr, "Executing:"); | ||||
| 		for (i = 0; i < a->num; i++) | ||||
| 			fprintf(stderr, " %s", a->list[i]); | ||||
| 		fprintf(stderr, "\n"); | ||||
| 	} | ||||
| 	if ((pid = fork()) == -1) | ||||
| 		fatal("do_local_cmd: fork: %s", strerror(errno)); | ||||
| 
 | ||||
| 	if (pid == 0) { | ||||
| 		execvp(a->list[0], a->list); | ||||
| 		perror(a->list[0]); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	do_cmd_pid = pid; | ||||
| 	signal(SIGTERM, killchild); | ||||
| 	signal(SIGINT, killchild); | ||||
| 	signal(SIGHUP, killchild); | ||||
| 
 | ||||
| 	while (waitpid(pid, &status, 0) == -1) | ||||
| 		if (errno != EINTR) | ||||
| 			fatal("do_local_cmd: waitpid: %s", strerror(errno)); | ||||
| 
 | ||||
| 	do_cmd_pid = -1; | ||||
| 
 | ||||
| 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) | ||||
| 		return (-1); | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -156,11 +180,10 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) | ||||
| 	pipe(reserved); | ||||
| 
 | ||||
| 	/* Create a socket pair for communicating with ssh. */ | ||||
| 	if (pipe(pin) < 0 || pipe(pout) < 0) | ||||
| 	{ | ||||
| 		fprintf(stderr, "Fatal error: pipe: %s\n", strerror(errno)); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (pipe(pin) < 0) | ||||
| 		fatal("pipe: %s", strerror(errno)); | ||||
| 	if (pipe(pout) < 0) | ||||
| 		fatal("pipe: %s", strerror(errno)); | ||||
| 
 | ||||
| 	/* Free the reserved descriptors. */ | ||||
| 	close(reserved[0]); | ||||
| @ -169,19 +192,20 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) | ||||
|     /* uClinux needs to build the args here before vforking,
 | ||||
|        otherwise we do it later on. */ | ||||
| #ifdef __uClinux__ | ||||
| 	args.list[0] = ssh_program; | ||||
| 	if (remuser != NULL) | ||||
| 		addargs(&args, "-l%s", remuser); | ||||
| 	addargs(&args, "%s", host); | ||||
| 	addargs(&args, "%s", cmd); | ||||
| 		replacearg(&args, 0, "%s", ssh_program); | ||||
| 		if (remuser != NULL) | ||||
| 			addargs(&args, "-l%s", remuser); | ||||
| 		addargs(&args, "%s", host); | ||||
| 		addargs(&args, "%s", cmd); | ||||
| #endif /* __uClinux__ */ | ||||
| 
 | ||||
| 	/* Fork a child to execute the command on the remote host using ssh. */ | ||||
| #ifdef __uClinux__ | ||||
| #ifndef __uClinux__ | ||||
| 	do_cmd_pid = vfork(); | ||||
| #else | ||||
| 	do_cmd_pid = fork(); | ||||
| #endif /* __uClinux__ */ | ||||
| 
 | ||||
| 	if (do_cmd_pid == 0) { | ||||
| 		/* Child. */ | ||||
| 		close(pin[1]); | ||||
| @ -192,38 +216,39 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) | ||||
| 		close(pout[1]); | ||||
| 
 | ||||
| #ifndef __uClinux__ | ||||
| 		args.list[0] = ssh_program; | ||||
| 		if (remuser != NULL) { | ||||
| 			addargs(&args, "-l"); | ||||
| 			addargs(&args, "%s", remuser); | ||||
| 		} | ||||
| 		replacearg(&args, 0, "%s", ssh_program); | ||||
| 		if (remuser != NULL) | ||||
| 			addargs(&args, "-l%s", remuser); | ||||
| 		addargs(&args, "%s", host); | ||||
| 		addargs(&args, "%s", cmd); | ||||
| #endif | ||||
| #endif /* __uClinux__ */ | ||||
| 
 | ||||
| 		execvp(ssh_program, args.list); | ||||
| 		perror(ssh_program); | ||||
| 		exit(1); | ||||
| 	} else if (do_cmd_pid == -1) { | ||||
| 		fprintf(stderr, "Fatal error: fork: %s\n", strerror(errno)); | ||||
| 		exit(1); | ||||
| 		fatal("fork: %s", strerror(errno)); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __uClinux__ | ||||
| 	/* clean up command */ | ||||
| 	/* pop cmd */ | ||||
| 	xfree(args->list[--args->num]); | ||||
| 	args->list[args->num]=NULL; | ||||
| 	xfree(args->list[args->num-1]); | ||||
| 	args->list[args->num-1]=NULL; | ||||
| 	args->num--; | ||||
| 	/* pop host */ | ||||
| 	xfree(args->list[--args->num-1]); | ||||
| 	args->list[args->num]=NULL; | ||||
| 	xfree(args->list[args->num-1]); | ||||
| 	args->list[args->num-1]=NULL; | ||||
| 	args->num--; | ||||
| 	/* pop user */ | ||||
| 	if (remuser != NULL) { | ||||
| 		xfree(args->list[--args->num-1]); | ||||
| 		args->list[args->num]=NULL; | ||||
| 		xfree(args->list[args->num-1]); | ||||
| 		args->list[args->num-1]=NULL; | ||||
| 		args->num--; | ||||
| 	} | ||||
| #endif /* __uClinux__ */ | ||||
| 	   | ||||
| 
 | ||||
| 	/* Parent.  Close the other side, and return the local side. */ | ||||
| 	close(pin[0]); | ||||
| 	*fdout = pin[1]; | ||||
| @ -236,7 +261,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) | ||||
| } | ||||
| 
 | ||||
| typedef struct { | ||||
| 	int cnt; | ||||
| 	size_t cnt; | ||||
| 	char *buf; | ||||
| } BUF; | ||||
| 
 | ||||
| @ -267,6 +292,7 @@ void usage(void); | ||||
| #if defined(DBMULTI_scp) && defined(DROPBEAR_MULTI) | ||||
| int scp_main(int argc, char **argv) | ||||
| #else | ||||
| int | ||||
| main(int argc, char **argv) | ||||
| #endif | ||||
| { | ||||
| @ -276,10 +302,15 @@ main(int argc, char **argv) | ||||
| 	extern char *optarg; | ||||
| 	extern int optind; | ||||
| 
 | ||||
| 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | ||||
| 	sanitise_stdfd(); | ||||
| 
 | ||||
| 	memset(&args, '\0', sizeof(args)); | ||||
| 	args.list = NULL; | ||||
| 	addargs(&args, "ssh");		/* overwritten with ssh_program */ | ||||
| 	addargs(&args, "%s", ssh_program); | ||||
| 	addargs(&args, "-x"); | ||||
| 	addargs(&args, "-oForwardAgent no"); | ||||
| 	addargs(&args, "-oPermitLocalCommand no"); | ||||
| 	addargs(&args, "-oClearAllForwardings yes"); | ||||
| 
 | ||||
| 	fflag = tflag = 0; | ||||
| @ -309,7 +340,7 @@ main(int argc, char **argv) | ||||
| 			speed = strtod(optarg, &endp); | ||||
| 			if (speed <= 0 || *endp != '\0') | ||||
| 				usage(); | ||||
| 			limitbw = speed * 1024; | ||||
| 			limit_rate = speed * 1024; | ||||
| 			break; | ||||
| 		case 'p': | ||||
| 			pflag = 1; | ||||
| @ -326,6 +357,7 @@ main(int argc, char **argv) | ||||
| 			break; | ||||
| #ifdef PROGRESS_METER | ||||
| 		case 'q': | ||||
| 			addargs(&args, "-q"); | ||||
| 			showprogress = 0; | ||||
| 			break; | ||||
| #endif | ||||
| @ -351,14 +383,11 @@ main(int argc, char **argv) | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
| 
 | ||||
| 	if ((pwd = getpwuid(userid = getuid())) == NULL) { | ||||
| 		fprintf(stderr, "unknown user %u", (u_int) userid); | ||||
| 	} | ||||
| 	if ((pwd = getpwuid(userid = getuid())) == NULL) | ||||
| 		fatal("unknown user %u", (u_int) userid); | ||||
| 
 | ||||
| #ifdef PROGRESS_METER | ||||
| 	if (!isatty(STDERR_FILENO)) | ||||
| 		showprogress = 0; | ||||
| #endif | ||||
| 
 | ||||
| 	remin = STDIN_FILENO; | ||||
| 	remout = STDOUT_FILENO; | ||||
| @ -392,9 +421,9 @@ main(int argc, char **argv) | ||||
| 	if ((targ = colon(argv[argc - 1])))	/* Dest is remote host. */ | ||||
| 		toremote(targ, argc, argv); | ||||
| 	else { | ||||
| 		tolocal(argc, argv);	/* Dest is local host. */ | ||||
| 		if (targetshouldbedirectory) | ||||
| 			verifydir(argv[argc - 1]); | ||||
| 		tolocal(argc, argv);	/* Dest is local host. */ | ||||
| 	} | ||||
| 	/*
 | ||||
| 	 * Finally check the exit status of the ssh process, if one was forked | ||||
| @ -414,78 +443,76 @@ main(int argc, char **argv) | ||||
| 	} | ||||
| 	exit(errs != 0); | ||||
| } | ||||
| #endif /* DBMULTI stuff */ | ||||
| #endif /* DBMULTI_scp stuff */ | ||||
| 
 | ||||
| void | ||||
| toremote(char *targ, int argc, char **argv) | ||||
| { | ||||
| 	int i, len; | ||||
| 	char *bp, *host, *src, *suser, *thost, *tuser; | ||||
| 	char *bp, *host, *src, *suser, *thost, *tuser, *arg; | ||||
| 	arglist alist; | ||||
| 
 | ||||
| 	memset(&alist, '\0', sizeof(alist)); | ||||
| 	alist.list = NULL; | ||||
| 
 | ||||
| 	*targ++ = 0; | ||||
| 	if (*targ == 0) | ||||
| 		targ = "."; | ||||
| 
 | ||||
| 	if ((thost = strrchr(argv[argc - 1], '@'))) { | ||||
| 	arg = xstrdup(argv[argc - 1]); | ||||
| 	if ((thost = strrchr(arg, '@'))) { | ||||
| 		/* user@host */ | ||||
| 		*thost++ = 0; | ||||
| 		tuser = argv[argc - 1]; | ||||
| 		tuser = arg; | ||||
| 		if (*tuser == '\0') | ||||
| 			tuser = NULL; | ||||
| 	} else { | ||||
| 		thost = argv[argc - 1]; | ||||
| 		thost = arg; | ||||
| 		tuser = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (tuser != NULL && !okname(tuser)) { | ||||
| 		xfree(arg); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < argc - 1; i++) { | ||||
| 		src = colon(argv[i]); | ||||
| 		if (src) {	/* remote to remote */ | ||||
| 			static char *ssh_options = | ||||
| 			    "-x -o'ClearAllForwardings yes'"; | ||||
| 			freeargs(&alist); | ||||
| 			addargs(&alist, "%s", ssh_program); | ||||
| 			if (verbose_mode) | ||||
| 				addargs(&alist, "-v"); | ||||
| 			addargs(&alist, "-x"); | ||||
| 			addargs(&alist, "-oClearAllForwardings yes"); | ||||
| 			addargs(&alist, "-n"); | ||||
| 
 | ||||
| 			*src++ = 0; | ||||
| 			if (*src == 0) | ||||
| 				src = "."; | ||||
| 			host = strrchr(argv[i], '@'); | ||||
| 			len = strlen(ssh_program) + strlen(argv[i]) + | ||||
| 			    strlen(src) + (tuser ? strlen(tuser) : 0) + | ||||
| 			    strlen(thost) + strlen(targ) + | ||||
| 			    strlen(ssh_options) + CMDNEEDS + 20; | ||||
| 			bp = xmalloc(len); | ||||
| 
 | ||||
| 			if (host) { | ||||
| 				*host++ = 0; | ||||
| 				host = cleanhostname(host); | ||||
| 				suser = argv[i]; | ||||
| 				if (*suser == '\0') | ||||
| 					suser = pwd->pw_name; | ||||
| 				else if (!okname(suser)) { | ||||
| 					xfree(bp); | ||||
| 				else if (!okname(suser)) | ||||
| 					continue; | ||||
| 				} | ||||
| 				if (tuser && !okname(tuser)) { | ||||
| 					xfree(bp); | ||||
| 					continue; | ||||
| 				} | ||||
| 				snprintf(bp, len, | ||||
| 				    "%s%s %s -n " | ||||
| 				    "-l %s %s %s %s '%s%s%s:%s'", | ||||
| 				    ssh_program, verbose_mode ? " -v" : "", | ||||
| 				    ssh_options, suser, host, cmd, src, | ||||
| 				    tuser ? tuser : "", tuser ? "@" : "", | ||||
| 				    thost, targ); | ||||
| 				addargs(&alist, "-l"); | ||||
| 				addargs(&alist, "%s", suser); | ||||
| 			} else { | ||||
| 				host = cleanhostname(argv[i]); | ||||
| 				snprintf(bp, len, | ||||
| 				    "exec %s%s %s -n %s " | ||||
| 				    "%s %s '%s%s%s:%s'", | ||||
| 				    ssh_program, verbose_mode ? " -v" : "", | ||||
| 				    ssh_options, host, cmd, src, | ||||
| 				    tuser ? tuser : "", tuser ? "@" : "", | ||||
| 				    thost, targ); | ||||
| 			} | ||||
| 			if (verbose_mode) | ||||
| 				fprintf(stderr, "Executing: %s\n", bp); | ||||
| 			(void) system(bp); | ||||
| 			(void) xfree(bp); | ||||
| 			addargs(&alist, "%s", host); | ||||
| 			addargs(&alist, "%s", cmd); | ||||
| 			addargs(&alist, "%s", src); | ||||
| 			addargs(&alist, "%s%s%s:%s", | ||||
| 			    tuser ? tuser : "", tuser ? "@" : "", | ||||
| 			    thost, targ); | ||||
| 			if (do_local_cmd(&alist) != 0) | ||||
| 				errs = 1; | ||||
| 		} else {	/* local to remote */ | ||||
| 			if (remin == -1) { | ||||
| 				len = strlen(targ) + CMDNEEDS + 20; | ||||
| @ -509,20 +536,23 @@ tolocal(int argc, char **argv) | ||||
| { | ||||
| 	int i, len; | ||||
| 	char *bp, *host, *src, *suser; | ||||
| 	arglist alist; | ||||
| 
 | ||||
| 	memset(&alist, '\0', sizeof(alist)); | ||||
| 	alist.list = NULL; | ||||
| 
 | ||||
| 	for (i = 0; i < argc - 1; i++) { | ||||
| 		if (!(src = colon(argv[i]))) {	/* Local to local. */ | ||||
| 			len = strlen(_PATH_CP) + strlen(argv[i]) + | ||||
| 			    strlen(argv[argc - 1]) + 20; | ||||
| 			bp = xmalloc(len); | ||||
| 			(void) snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, | ||||
| 			    iamrecursive ? " -r" : "", pflag ? " -p" : "", | ||||
| 			    argv[i], argv[argc - 1]); | ||||
| 			if (verbose_mode) | ||||
| 				fprintf(stderr, "Executing: %s\n", bp); | ||||
| 			if (system(bp)) | ||||
| 			freeargs(&alist); | ||||
| 			addargs(&alist, "%s", _PATH_CP); | ||||
| 			if (iamrecursive) | ||||
| 				addargs(&alist, "-r"); | ||||
| 			if (pflag) | ||||
| 				addargs(&alist, "-p"); | ||||
| 			addargs(&alist, "%s", argv[i]); | ||||
| 			addargs(&alist, "%s", argv[argc-1]); | ||||
| 			if (do_local_cmd(&alist)) | ||||
| 				++errs; | ||||
| 			(void) xfree(bp); | ||||
| 			continue; | ||||
| 		} | ||||
| 		*src++ = 0; | ||||
| @ -559,8 +589,9 @@ source(int argc, char **argv) | ||||
| 	struct stat stb; | ||||
| 	static BUF buffer; | ||||
| 	BUF *bp; | ||||
| 	off_t i, amt, result, statbytes; | ||||
| 	int fd, haderr, indx; | ||||
| 	off_t i, amt, statbytes; | ||||
| 	size_t result; | ||||
| 	int fd = -1, haderr, indx; | ||||
| 	char *last, *name, buf[2048]; | ||||
| 	int len; | ||||
| 
 | ||||
| @ -614,7 +645,7 @@ syserr:			run_err("%s: %s", name, strerror(errno)); | ||||
| #define	FILEMODEMASK	(S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) | ||||
| 		snprintf(buf, sizeof buf, "C%04o %lld %s\n", | ||||
| 		    (u_int) (stb.st_mode & FILEMODEMASK), | ||||
| 		    (int64_t)stb.st_size, last); | ||||
| 		    (long long)stb.st_size, last); | ||||
| 		if (verbose_mode) { | ||||
| 			fprintf(stderr, "Sending file modes: %s", buf); | ||||
| 		} | ||||
| @ -622,10 +653,13 @@ syserr:			run_err("%s: %s", name, strerror(errno)); | ||||
| 		if (response() < 0) | ||||
| 			goto next; | ||||
| 		if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { | ||||
| next:			(void) close(fd); | ||||
| next:			if (fd != -1) { | ||||
| 				(void) close(fd); | ||||
| 				fd = -1; | ||||
| 			} | ||||
| 			continue; | ||||
| 		} | ||||
| #ifdef PROGRESS_METER | ||||
| #if PROGRESS_METER | ||||
| 		if (showprogress) | ||||
| 			start_progress_meter(curfile, stb.st_size, &statbytes); | ||||
| #endif | ||||
| @ -637,17 +671,17 @@ next:			(void) close(fd); | ||||
| 			if (!haderr) { | ||||
| 				result = atomicio(read, fd, bp->buf, amt); | ||||
| 				if (result != amt) | ||||
| 					haderr = result >= 0 ? EIO : errno; | ||||
| 					haderr = errno; | ||||
| 			} | ||||
| 			if (haderr) | ||||
| 				(void) atomicio(vwrite, remout, bp->buf, amt); | ||||
| 			else { | ||||
| 				result = atomicio(vwrite, remout, bp->buf, amt); | ||||
| 				if (result != amt) | ||||
| 					haderr = result >= 0 ? EIO : errno; | ||||
| 					haderr = errno; | ||||
| 				statbytes += result; | ||||
| 			} | ||||
| 			if (limitbw) | ||||
| 			if (limit_rate) | ||||
| 				bwlimit(amt); | ||||
| 		} | ||||
| #ifdef PROGRESS_METER | ||||
| @ -655,8 +689,11 @@ next:			(void) close(fd); | ||||
| 			stop_progress_meter(); | ||||
| #endif | ||||
| 
 | ||||
| 		if (close(fd) < 0 && !haderr) | ||||
| 			haderr = errno; | ||||
| 		if (fd != -1) { | ||||
| 			if (close(fd) < 0 && !haderr) | ||||
| 				haderr = errno; | ||||
| 			fd = -1; | ||||
| 		} | ||||
| 		if (!haderr) | ||||
| 			(void) atomicio(vwrite, remout, "", 1); | ||||
| 		else | ||||
| @ -723,7 +760,7 @@ bwlimit(int amount) | ||||
| { | ||||
| 	static struct timeval bwstart, bwend; | ||||
| 	static int lamt, thresh = 16384; | ||||
| 	uint64_t wait; | ||||
| 	u_int64_t waitlen; | ||||
| 	struct timespec ts, rm; | ||||
| 
 | ||||
| 	if (!timerisset(&bwstart)) { | ||||
| @ -741,10 +778,10 @@ bwlimit(int amount) | ||||
| 		return; | ||||
| 
 | ||||
| 	lamt *= 8; | ||||
| 	wait = (double)1000000L * lamt / limitbw; | ||||
| 	waitlen = (double)1000000L * lamt / limit_rate; | ||||
| 
 | ||||
| 	bwstart.tv_sec = wait / 1000000L; | ||||
| 	bwstart.tv_usec = wait % 1000000L; | ||||
| 	bwstart.tv_sec = waitlen / 1000000L; | ||||
| 	bwstart.tv_usec = waitlen % 1000000L; | ||||
| 
 | ||||
| 	if (timercmp(&bwstart, &bwend, >)) { | ||||
| 		timersub(&bwstart, &bwend, &bwend); | ||||
| @ -781,8 +818,9 @@ sink(int argc, char **argv) | ||||
| 		YES, NO, DISPLAYED | ||||
| 	} wrerr; | ||||
| 	BUF *bp; | ||||
| 	off_t i, j; | ||||
| 	int amt, count, exists, first, mask, mode, ofd, omode; | ||||
| 	off_t i; | ||||
| 	size_t j, count; | ||||
| 	int amt, exists, first, mask, mode, ofd, omode; | ||||
| 	off_t size, statbytes; | ||||
| 	int setimes, targisdir, wrerrno = 0; | ||||
| 	char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; | ||||
| @ -790,7 +828,7 @@ sink(int argc, char **argv) | ||||
| 
 | ||||
| #define	atime	tv[0] | ||||
| #define	mtime	tv[1] | ||||
| #define	SCREWUP(str)	do { why = str; goto screwup; } while (0) | ||||
| #define	SCREWUP(str)	{ why = str; goto screwup; } | ||||
| 
 | ||||
| 	setimes = targisdir = 0; | ||||
| 	mask = umask(0); | ||||
| @ -809,7 +847,7 @@ sink(int argc, char **argv) | ||||
| 		targisdir = 1; | ||||
| 	for (first = 1;; first = 0) { | ||||
| 		cp = buf; | ||||
| 		if (atomicio(read, remin, cp, 1) <= 0) | ||||
| 		if (atomicio(read, remin, cp, 1) != 1) | ||||
| 			return; | ||||
| 		if (*cp++ == '\n') | ||||
| 			SCREWUP("unexpected <newline>"); | ||||
| @ -819,6 +857,8 @@ sink(int argc, char **argv) | ||||
| 			*cp++ = ch; | ||||
| 		} while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); | ||||
| 		*cp = 0; | ||||
| 		if (verbose_mode) | ||||
| 			fprintf(stderr, "Sink: %s", buf); | ||||
| 
 | ||||
| 		if (buf[0] == '\01' || buf[0] == '\02') { | ||||
| 			if (iamremote == 0) | ||||
| @ -882,9 +922,13 @@ sink(int argc, char **argv) | ||||
| 			size = size * 10 + (*cp++ - '0'); | ||||
| 		if (*cp++ != ' ') | ||||
| 			SCREWUP("size not delimited"); | ||||
| 		if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) { | ||||
| 			run_err("error: unexpected filename: %s", cp); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		if (targisdir) { | ||||
| 			static char *namebuf; | ||||
| 			static int cursize; | ||||
| 			static size_t cursize; | ||||
| 			size_t need; | ||||
| 
 | ||||
| 			need = strlen(targ) + strlen(cp) + 250; | ||||
| @ -903,6 +947,8 @@ sink(int argc, char **argv) | ||||
| 		exists = stat(np, &stb) == 0; | ||||
| 		if (buf[0] == 'D') { | ||||
| 			int mod_flag = pflag; | ||||
| 			if (!iamrecursive) | ||||
| 				SCREWUP("received directory without -r"); | ||||
| 			if (exists) { | ||||
| 				if (!S_ISDIR(stb.st_mode)) { | ||||
| 					errno = ENOTDIR; | ||||
| @ -956,11 +1002,8 @@ bad:			run_err("%s: %s", np, strerror(errno)); | ||||
| 				amt = size - i; | ||||
| 			count += amt; | ||||
| 			do { | ||||
| 				j = read(remin, cp, amt); | ||||
| 				if (j == -1 && (errno == EINTR || | ||||
| 				    errno == EAGAIN)) { | ||||
| 					continue; | ||||
| 				} else if (j <= 0) { | ||||
| 				j = atomicio(read, remin, cp, amt); | ||||
| 				if (j == 0) { | ||||
| 					run_err("%s", j ? strerror(errno) : | ||||
| 					    "dropped connection"); | ||||
| 					exit(1); | ||||
| @ -969,17 +1012,17 @@ bad:			run_err("%s: %s", np, strerror(errno)); | ||||
| 				cp += j; | ||||
| 				statbytes += j; | ||||
| 			} while (amt > 0); | ||||
| 		 | ||||
| 			if (limitbw) | ||||
| 
 | ||||
| 			if (limit_rate) | ||||
| 				bwlimit(4096); | ||||
| 
 | ||||
| 			if (count == bp->cnt) { | ||||
| 				/* Keep reading so we stay sync'd up. */ | ||||
| 				if (wrerr == NO) { | ||||
| 					j = atomicio(vwrite, ofd, bp->buf, count); | ||||
| 					if (j != count) { | ||||
| 					if (atomicio(vwrite, ofd, bp->buf, | ||||
| 					    count) != count) { | ||||
| 						wrerr = YES; | ||||
| 						wrerrno = j >= 0 ? EIO : errno; | ||||
| 						wrerrno = errno; | ||||
| 					} | ||||
| 				} | ||||
| 				count = 0; | ||||
| @ -991,9 +1034,9 @@ bad:			run_err("%s: %s", np, strerror(errno)); | ||||
| 			stop_progress_meter(); | ||||
| #endif | ||||
| 		if (count != 0 && wrerr == NO && | ||||
| 		    (j = atomicio(vwrite, ofd, bp->buf, count)) != count) { | ||||
| 		    atomicio(vwrite, ofd, bp->buf, count) != count) { | ||||
| 			wrerr = YES; | ||||
| 			wrerrno = j >= 0 ? EIO : errno; | ||||
| 			wrerrno = errno; | ||||
| 		} | ||||
| 		if (wrerr == NO && ftruncate(ofd, size) != 0) { | ||||
| 			run_err("%s: truncate: %s", np, strerror(errno)); | ||||
| @ -1002,21 +1045,25 @@ bad:			run_err("%s: %s", np, strerror(errno)); | ||||
| 		if (pflag) { | ||||
| 			if (exists || omode != mode) | ||||
| #ifdef HAVE_FCHMOD | ||||
| 				if (fchmod(ofd, omode)) | ||||
| 				if (fchmod(ofd, omode)) { | ||||
| #else /* HAVE_FCHMOD */ | ||||
| 				if (chmod(np, omode)) | ||||
| 				if (chmod(np, omode)) { | ||||
| #endif /* HAVE_FCHMOD */ | ||||
| 					run_err("%s: set mode: %s", | ||||
| 					    np, strerror(errno)); | ||||
| 					wrerr = DISPLAYED; | ||||
| 				} | ||||
| 		} else { | ||||
| 			if (!exists && omode != mode) | ||||
| #ifdef HAVE_FCHMOD | ||||
| 				if (fchmod(ofd, omode & ~mask)) | ||||
| 				if (fchmod(ofd, omode & ~mask)) { | ||||
| #else /* HAVE_FCHMOD */ | ||||
| 				if (chmod(np, omode & ~mask)) | ||||
| 				if (chmod(np, omode & ~mask)) { | ||||
| #endif /* HAVE_FCHMOD */ | ||||
| 					run_err("%s: set mode: %s", | ||||
| 					    np, strerror(errno)); | ||||
| 					wrerr = DISPLAYED; | ||||
| 				} | ||||
| 		} | ||||
| 		if (close(ofd) == -1) { | ||||
| 			wrerr = YES; | ||||
| @ -1084,8 +1131,8 @@ void | ||||
| usage(void) | ||||
| { | ||||
| 	(void) fprintf(stderr, | ||||
| 	    "usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n" | ||||
| 	    "           [-c cipher] [-i identity] [-l limit] [-o option]\n" | ||||
| 	    "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n" | ||||
| 	    "           [-l limit] [-o ssh_option] [-P port] [-S program]\n" | ||||
| 	    "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); | ||||
| 	exit(1); | ||||
| } | ||||
| @ -1126,7 +1173,7 @@ verifydir(char *cp) | ||||
| 		errno = ENOTDIR; | ||||
| 	} | ||||
| 	run_err("%s: %s", cp, strerror(errno)); | ||||
| 	exit(1); | ||||
| 	killchild(0); | ||||
| } | ||||
| 
 | ||||
| int | ||||
|  | ||||
							
								
								
									
										95
									
								
								scpmisc.c
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								scpmisc.c
									
									
									
									
									
								
							| @ -140,12 +140,15 @@ void | ||||
| addargs(arglist *args, char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	char buf[1024]; | ||||
| 	int nalloc; | ||||
| 	char *cp; | ||||
| 	u_int nalloc; | ||||
| 	int r; | ||||
| 
 | ||||
| 	va_start(ap, fmt); | ||||
| 	vsnprintf(buf, sizeof(buf), fmt, ap); | ||||
| 	r = vasprintf(&cp, fmt, ap); | ||||
| 	va_end(ap); | ||||
| 	if (r == -1) | ||||
| 		fatal("addargs: argument too long"); | ||||
| 
 | ||||
| 	nalloc = args->nalloc; | ||||
| 	if (args->list == NULL) { | ||||
| @ -156,6 +159,90 @@ addargs(arglist *args, char *fmt, ...) | ||||
| 
 | ||||
| 	args->list = xrealloc(args->list, nalloc * sizeof(char *)); | ||||
| 	args->nalloc = nalloc; | ||||
| 	args->list[args->num++] = xstrdup(buf); | ||||
| 	args->list[args->num++] = cp; | ||||
| 	args->list[args->num] = NULL; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| replacearg(arglist *args, u_int which, char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 	char *cp; | ||||
| 	int r; | ||||
| 
 | ||||
| 	va_start(ap, fmt); | ||||
| 	r = vasprintf(&cp, fmt, ap); | ||||
| 	va_end(ap); | ||||
| 	if (r == -1) | ||||
| 		fatal("replacearg: argument too long"); | ||||
| 
 | ||||
| 	if (which >= args->num) | ||||
| 		fatal("replacearg: tried to replace invalid arg %d >= %d", | ||||
| 		    which, args->num); | ||||
| 	xfree(args->list[which]); | ||||
| 	args->list[which] = cp; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| freeargs(arglist *args) | ||||
| { | ||||
| 	u_int i; | ||||
| 
 | ||||
| 	if (args->list != NULL) { | ||||
| 		for (i = 0; i < args->num; i++) | ||||
| 			xfree(args->list[i]); | ||||
| 		xfree(args->list); | ||||
| 		args->nalloc = args->num = 0; | ||||
| 		args->list = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * NB. duplicate __progname in case it is an alias for argv[0] | ||||
|  * Otherwise it may get clobbered by setproctitle() | ||||
|  */ | ||||
| char *ssh_get_progname(char *argv0) | ||||
| { | ||||
| 	char *p; | ||||
| 
 | ||||
| 	if (argv0 == NULL) | ||||
| 		return ("unknown");	/* XXX */ | ||||
| 	p = strrchr(argv0, '/'); | ||||
| 	if (p == NULL) | ||||
| 		p = argv0; | ||||
| 	else | ||||
| 		p++; | ||||
| 
 | ||||
| 	return (xstrdup(p)); | ||||
| } | ||||
| 
 | ||||
| void fatal(char* fmt,...) | ||||
| { | ||||
| 	va_list args; | ||||
| 	va_start(args, fmt); | ||||
| 	vfprintf(stderr, fmt, args); | ||||
| 	va_end(args); | ||||
| 	exit(255); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| sanitise_stdfd(void) | ||||
| { | ||||
| 	int nullfd, dupfd; | ||||
| 
 | ||||
| 	if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { | ||||
| 		fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno)); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	while (++dupfd <= 2) { | ||||
| 		/* Only clobber closed fds */ | ||||
| 		if (fcntl(dupfd, F_GETFL, 0) >= 0) | ||||
| 			continue; | ||||
| 		if (dup2(nullfd, dupfd) == -1) { | ||||
| 			fprintf(stderr, "dup2: %s", strerror(errno)); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 	} | ||||
| 	if (nullfd > 2) | ||||
| 		close(nullfd); | ||||
| } | ||||
|  | ||||
| @ -34,6 +34,8 @@ struct arglist { | ||||
| 	int     nalloc; | ||||
| }; | ||||
| void	 addargs(arglist *, char *, ...); | ||||
| void	 replacearg(arglist *, u_int, char *, ...); | ||||
| void	 freeargs(arglist *); | ||||
| 
 | ||||
| /* from xmalloc.h */ | ||||
| void	*xmalloc(size_t); | ||||
| @ -41,4 +43,6 @@ void	*xrealloc(void *, size_t); | ||||
| void     xfree(void *); | ||||
| char	*xstrdup(const char *); | ||||
| 
 | ||||
| 
 | ||||
| char *ssh_get_progname(char *); | ||||
| void fatal(char* fmt,...); | ||||
| void sanitise_stdfd(void); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user