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