00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "../rsync.h"
00027
00028 #define TIMEOUT_SECONDS 30
00029
00030 void run_program(char **command);
00031
00032 char buf[4096];
00033 int save_data_from_program = 0;
00034
00035 int
00036 main(int argc, char *argv[])
00037 {
00038 int fd_file, len;
00039 struct timeval tv;
00040 fd_set fds;
00041
00042 argv++;
00043 if (--argc && argv[0][0] == '-') {
00044 if (argv[0][1] == 'o')
00045 save_data_from_program = 1;
00046 else if (argv[0][1] == 'i')
00047 save_data_from_program = 0;
00048 else {
00049 fprintf(stderr, "Unknown option: %s\n", argv[0]);
00050 exit(1);
00051 }
00052 argv++;
00053 argc--;
00054 }
00055 if (argc < 2) {
00056 fprintf(stderr, "Usage: savetransfer [-i|-o] OUTPUT_FILE PROGRAM [ARGS...]\n");
00057 fprintf(stderr, "-i Save the input going to PROGRAM to the OUTPUT_FILE\n");
00058 fprintf(stderr, "-o Save the output coming from PROGRAM to the OUTPUT_FILE\n");
00059 exit(1);
00060 }
00061 if ((fd_file = open(*argv, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0644)) < 0) {
00062 fprintf(stderr, "Unable to write to `%s': %s\n", *argv, strerror(errno));
00063 exit(1);
00064 }
00065 set_blocking(fd_file);
00066
00067 signal(SIGPIPE, SIG_IGN);
00068
00069 run_program(argv + 1);
00070
00071 #if defined HAVE_SETMODE && O_BINARY
00072 setmode(STDIN_FILENO, O_BINARY);
00073 setmode(STDOUT_FILENO, O_BINARY);
00074 #endif
00075 set_nonblocking(STDIN_FILENO);
00076 set_blocking(STDOUT_FILENO);
00077
00078 while (1) {
00079 FD_ZERO(&fds);
00080 FD_SET(STDIN_FILENO, &fds);
00081 tv.tv_sec = TIMEOUT_SECONDS;
00082 tv.tv_usec = 0;
00083 if (!select(STDIN_FILENO+1, &fds, NULL, NULL, &tv))
00084 break;
00085 if (!FD_ISSET(STDIN_FILENO, &fds))
00086 break;
00087 if ((len = read(STDIN_FILENO, buf, sizeof buf)) <= 0)
00088 break;
00089 if (write(STDOUT_FILENO, buf, len) != len) {
00090 fprintf(stderr, "Failed to write data to stdout: %s\n", strerror(errno));
00091 exit(1);
00092 }
00093 if (write(fd_file, buf, len) != len) {
00094 fprintf(stderr, "Failed to write data to fd_file: %s\n", strerror(errno));
00095 exit(1);
00096 }
00097 }
00098 return 0;
00099 }
00100
00101 void
00102 run_program(char **command)
00103 {
00104 int pipe_fds[2], ret;
00105 pid_t pid;
00106
00107 if (pipe(pipe_fds) < 0) {
00108 fprintf(stderr, "pipe failed: %s\n", strerror(errno));
00109 exit(1);
00110 }
00111
00112 if ((pid = fork()) < 0) {
00113 fprintf(stderr, "fork failed: %s\n", strerror(errno));
00114 exit(1);
00115 }
00116
00117 if (pid == 0) {
00118 if (save_data_from_program)
00119 ret = dup2(pipe_fds[1], STDOUT_FILENO);
00120 else
00121 ret = dup2(pipe_fds[0], STDIN_FILENO);
00122 if (ret < 0) {
00123 fprintf(stderr, "Failed to dup (in child): %s\n", strerror(errno));
00124 exit(1);
00125 }
00126 close(pipe_fds[0]);
00127 close(pipe_fds[1]);
00128 set_blocking(STDIN_FILENO);
00129 set_blocking(STDOUT_FILENO);
00130 execvp(command[0], command);
00131 fprintf(stderr, "Failed to exec %s: %s\n", command[0], strerror(errno));
00132 exit(1);
00133 }
00134
00135 if (save_data_from_program)
00136 ret = dup2(pipe_fds[0], STDIN_FILENO);
00137 else
00138 ret = dup2(pipe_fds[1], STDOUT_FILENO);
00139 if (ret < 0) {
00140 fprintf(stderr, "Failed to dup (in parent): %s\n", strerror(errno));
00141 exit(1);
00142 }
00143 close(pipe_fds[0]);
00144 close(pipe_fds[1]);
00145 }
00146
00147 void
00148 set_nonblocking(int fd)
00149 {
00150 int val;
00151
00152 if ((val = fcntl(fd, F_GETFL, 0)) == -1)
00153 return;
00154 if (!(val & NONBLOCK_FLAG)) {
00155 val |= NONBLOCK_FLAG;
00156 fcntl(fd, F_SETFL, val);
00157 }
00158 }
00159
00160 void
00161 set_blocking(int fd)
00162 {
00163 int val;
00164
00165 if ((val = fcntl(fd, F_GETFL, 0)) < 0)
00166 return;
00167 if (val & NONBLOCK_FLAG) {
00168 val &= ~NONBLOCK_FLAG;
00169 fcntl(fd, F_SETFL, val);
00170 }
00171 }