Cause all three processes to report memory stats when -vv --stats
[rsync/rsync.git] / main.c
CommitLineData
0ba48136 1/* -*- c-file-style: "linux" -*-
d9c7edf6 2
50135767 3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
c627d613 4 Copyright (C) Paul Mackerras 1996
e5a2b854 5 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
d9c7edf6 6
c627d613
AT
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
d9c7edf6 11
c627d613
AT
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
d9c7edf6 16
c627d613
AT
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rsync.h"
23
f0fca04e 24time_t starttime = 0;
a800434a 25
b35d0d8e 26extern struct stats stats;
32eda096 27extern int am_root;
d9c7edf6
WD
28extern int am_server;
29extern int am_sender;
b695f242 30extern int am_generator;
d9c7edf6 31extern int am_daemon;
7a6421fa 32extern int verbose;
32eda096
WD
33extern int blocking_io;
34extern int cvs_exclude;
35extern int delete_mode;
36extern int delete_excluded;
37extern int delete_after;
38extern int daemon_over_rsh;
39extern int do_stats;
40extern int dry_run;
41extern int list_only;
42extern int local_server;
43extern int log_got_error;
44extern int module_id;
45extern int orig_umask;
46extern int preserve_hard_links;
d04e9c51 47extern int protocol_version;
32eda096
WD
48extern int recurse;
49extern int relative_paths;
50extern int rsync_port;
51extern int read_batch;
52extern int write_batch;
53extern int filesfrom_fd;
54extern pid_t cleanup_child_pid;
55extern char *files_from;
56extern char *remote_filesfrom_file;
57extern char *rsync_path;
58extern char *shell_cmd;
59extern struct file_list *batch_flist;
c627d613 60
b695f242 61
ee7118a8
DD
62/* there's probably never more than at most 2 outstanding child processes,
63 * but set it higher just in case.
64 */
65#define MAXCHILDPROCS 5
66
67struct pid_status {
68 pid_t pid;
69 int status;
70} pid_stat_table[MAXCHILDPROCS];
71
e5a2b854 72static void show_malloc_stats(void);
82980a23
AT
73
74/****************************************************************************
75wait for a process to exit, calling io_flush while waiting
76****************************************************************************/
77void wait_process(pid_t pid, int *status)
78{
ee7118a8
DD
79 pid_t waited_pid;
80 int cnt;
81
82 while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
a24c6870 83 msleep(20);
f1e3656e 84 io_flush(FULL_FLUSH);
82980a23 85 }
d9c7edf6 86
ee7118a8
DD
87 if ((waited_pid == -1) && (errno == ECHILD)) {
88 /* status of requested child no longer available.
89 * check to see if it was processed by the sigchld_handler.
90 */
91 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
92 if (pid == pid_stat_table[cnt].pid) {
93 *status = pid_stat_table[cnt].status;
94 pid_stat_table[cnt].pid = 0;
95 break;
96 }
97 }
98 }
99
d9c7edf6
WD
100 /* TODO: If the child exited on a signal, then log an
101 * appropriate error message. Perhaps we should also accept a
102 * message describing the purpose of the child. Also indicate
103 * this to the caller so that thhey know something went
104 * wrong. */
82980a23
AT
105 *status = WEXITSTATUS(*status);
106}
107
c627d613
AT
108static void report(int f)
109{
7a6421fa 110 time_t t = time(NULL);
17d31b38 111 int send_stats;
7a6421fa 112
7bb7058e 113 if (do_stats && verbose > 1) {
5c15e29f 114 /* These come out from every process */
7bb7058e 115 show_malloc_stats();
86943126 116 show_flist_stats();
5c15e29f
MP
117 }
118
e5fbaa71
S
119 if (am_generator)
120 return;
121
248fbb8c 122 if (am_daemon) {
a9766ef1 123 log_exit(0, __FILE__, __LINE__);
7b372642 124 if (f == -1 || !am_sender) return;
248fbb8c
AT
125 }
126
d04e9c51 127 send_stats = verbose || protocol_version >= 20;
e19452a9 128 if (am_server) {
17d31b38 129 if (am_sender && send_stats) {
23c5aef1
DD
130 int64 w;
131 /* store total_written in a temporary
d9c7edf6 132 * because write_longint changes it */
23c5aef1 133 w = stats.total_written;
e19452a9 134 write_longint(f,stats.total_read);
23c5aef1 135 write_longint(f,w);
e19452a9
DD
136 write_longint(f,stats.total_size);
137 }
7a6421fa
AT
138 return;
139 }
e19452a9
DD
140
141 /* this is the client */
d9c7edf6 142
17d31b38 143 if (!am_sender && send_stats) {
23c5aef1 144 int64 r;
a800434a 145 stats.total_written = read_longint(f);
23c5aef1
DD
146 /* store total_read in a temporary, read_longint changes it */
147 r = read_longint(f);
a800434a 148 stats.total_size = read_longint(f);
23c5aef1 149 stats.total_read = r;
a800434a
AT
150 }
151
152 if (do_stats) {
17d31b38 153 if (!am_sender && !send_stats) {
d9c7edf6
WD
154 /* missing the bytes written by the generator */
155 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
156 rprintf(FINFO, "Use --stats -v to show stats\n");
157 return;
17d31b38 158 }
1f658d42 159 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
d9c7edf6
WD
160 rprintf(FINFO,"Number of files transferred: %d\n",
161 stats.num_transferred_files);
162 rprintf(FINFO,"Total file size: %.0f bytes\n",
163 (double)stats.total_size);
164 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
165 (double)stats.total_transferred_size);
166 rprintf(FINFO,"Literal data: %.0f bytes\n",
167 (double)stats.literal_data);
168 rprintf(FINFO,"Matched data: %.0f bytes\n",
169 (double)stats.matched_data);
1f658d42 170 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
d9c7edf6
WD
171 rprintf(FINFO,"Total bytes written: %.0f\n",
172 (double)stats.total_written);
577ab12c 173 rprintf(FINFO,"Total bytes read: %.0f\n",
d9c7edf6 174 (double)stats.total_read);
7a6421fa 175 }
d9c7edf6 176
e19452a9 177 if (verbose || do_stats) {
577ab12c 178 rprintf(FINFO,"\nwrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
d9c7edf6
WD
179 (double)stats.total_written,
180 (double)stats.total_read,
181 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
e19452a9 182 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
d9c7edf6
WD
183 (double)stats.total_size,
184 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
e19452a9 185 }
fc8a6b97
AT
186
187 fflush(stdout);
188 fflush(stderr);
c627d613
AT
189}
190
191
e5a2b854
MP
192/**
193 * If our C library can get malloc statistics, then show them to FINFO
194 **/
195static void show_malloc_stats(void)
196{
197#ifdef HAVE_MALLINFO
198 struct mallinfo mi;
199
200 mi = mallinfo();
201
ce672562 202 rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
5c15e29f
MP
203 getpid(),
204 am_server ? "server " : "",
205 am_daemon ? "daemon " : "",
b695f242 206 who_am_i());
e5a2b854
MP
207 rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
208 rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
209 rprintf(FINFO, " smblks: %10d\n", mi.smblks);
210 rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
211 rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
212 rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
213 rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
214 rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
215 rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
216 rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
217#endif /* HAVE_MALLINFO */
218}
219
220
0882faa2 221/* Start the remote shell. cmd may be NULL to use the default. */
19b27a48 222static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
c627d613 223{
366345fe 224 char *args[100];
19b27a48
AT
225 int i,argc=0;
226 pid_t ret;
366345fe 227 char *tok,*dir=NULL;
bb4aa89c 228 int dash_l_set = 0;
366345fe 229
088aac85 230 if (!read_batch && !local_server) {
9af87151 231 char *rsh_env = getenv(RSYNC_RSH_ENV);
366345fe 232 if (!cmd)
9af87151 233 cmd = rsh_env;
366345fe
AT
234 if (!cmd)
235 cmd = RSYNC_RSH;
236 cmd = strdup(cmd);
d9c7edf6 237 if (!cmd)
366345fe
AT
238 goto oom;
239
240 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
241 args[argc++] = tok;
242 }
c627d613 243
d9c7edf6 244 /* check to see if we've already been given '-l user' in
9af87151 245 * the remote-shell command */
bb4aa89c
WD
246 for (i = 0; i < argc-1; i++) {
247 if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
248 dash_l_set = 1;
249 }
250
7b8356d0 251#if HAVE_REMSH
366345fe
AT
252 /* remsh (on HPUX) takes the arguments the other way around */
253 args[argc++] = machine;
bb4aa89c 254 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
255 args[argc++] = "-l";
256 args[argc++] = user;
257 }
7b8356d0 258#else
bb4aa89c 259 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
260 args[argc++] = "-l";
261 args[argc++] = user;
262 }
263 args[argc++] = machine;
7b8356d0 264#endif
c627d613 265
366345fe 266 args[argc++] = rsync_path;
c627d613 267
9af87151 268 if (blocking_io < 0) {
90e22f4b
WD
269 char *cp;
270 if ((cp = strrchr(cmd, '/')) != NULL)
271 cp++;
272 else
273 cp = cmd;
274 if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
275 blocking_io = 1;
66b71163 276 }
e384bfbd 277
93689aa5 278 server_options(args,&argc);
366345fe 279 }
c627d613 280
366345fe 281 args[argc++] = ".";
76076c4b 282
d9c7edf6 283 if (!daemon_over_rsh && path && *path)
366345fe 284 args[argc++] = path;
c627d613 285
366345fe 286 args[argc] = NULL;
c627d613 287
366345fe 288 if (verbose > 3) {
9486289c 289 rprintf(FINFO,"cmd=");
366345fe 290 for (i=0;i<argc;i++)
9486289c
AT
291 rprintf(FINFO,"%s ",args[i]);
292 rprintf(FINFO,"\n");
366345fe
AT
293 }
294
295 if (local_server) {
6902ed17 296 if (read_batch)
d9c7edf6 297 create_flist_from_batch(); /* sets batch_flist */
25d34a5c 298 ret = local_child(argc, args, f_in, f_out, child_main);
366345fe
AT
299 } else {
300 ret = piped_child(args,f_in,f_out);
301 }
c627d613 302
366345fe 303 if (dir) free(dir);
82306bf6 304
366345fe 305 return ret;
c627d613
AT
306
307oom:
366345fe
AT
308 out_of_memory("do_cmd");
309 return 0; /* not reached */
c627d613
AT
310}
311
312
c627d613
AT
313static char *get_local_name(struct file_list *flist,char *name)
314{
7a6421fa 315 STRUCT_STAT st;
87cc45e1 316 int e;
c627d613 317
c95da96a 318 if (verbose > 2)
d9c7edf6 319 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
320 flist->count, NS(name));
321
d9c7edf6 322 if (!name)
1f0610ef 323 return NULL;
c95da96a 324
1ff5450d
AT
325 if (do_stat(name,&st) == 0) {
326 if (S_ISDIR(st.st_mode)) {
59187666 327 if (!push_dir(name)) {
ea42541f
WD
328 rprintf(FERROR, "push_dir %s failed: %s (1)\n",
329 full_fname(name), strerror(errno));
65417579 330 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
331 }
332 return NULL;
333 }
334 if (flist->count > 1) {
335 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 336 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
337 }
338 return name;
339 }
340
87cc45e1 341 if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
1ff5450d
AT
342 return name;
343
1ff5450d 344 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
ea42541f
WD
345 rprintf(FERROR, "mkdir %s failed: %s\n",
346 full_fname(name), strerror(errno));
65417579 347 exit_cleanup(RERR_FILEIO);
1ff5450d 348 } else {
b536f47e
AT
349 if (verbose > 0)
350 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
351 }
352
59187666 353 if (!push_dir(name)) {
ea42541f
WD
354 rprintf(FERROR, "push_dir %s failed: %s (2)\n",
355 full_fname(name), strerror(errno));
65417579 356 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
357 }
358
359 return NULL;
c627d613
AT
360}
361
362
9486289c 363static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 364{
7a6421fa
AT
365 int i;
366 struct file_list *flist;
367 char *dir = argv[0];
c627d613 368
45e08edb
WD
369 if (verbose > 2) {
370 rprintf(FINFO, "server_sender starting pid=%ld\n",
371 (long)getpid());
372 }
d9c7edf6 373
59187666 374 if (!relative_paths && !push_dir(dir)) {
ea42541f
WD
375 rprintf(FERROR, "push_dir %s failed: %s (3)\n",
376 full_fname(dir), strerror(errno));
65417579 377 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
378 }
379 argc--;
380 argv++;
d9c7edf6 381
7a6421fa
AT
382 if (strcmp(dir,".")) {
383 int l = strlen(dir);
d9c7edf6 384 if (strcmp(dir,"/") == 0)
7a6421fa
AT
385 l = 0;
386 for (i=0;i<argc;i++)
387 argv[i] += l+1;
388 }
c627d613 389
7a6421fa
AT
390 if (argc == 0 && recurse) {
391 argc=1;
392 argv--;
393 argv[0] = ".";
394 }
d9c7edf6 395
7a6421fa 396 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
397 if (!flist || flist->count == 0) {
398 exit_cleanup(0);
399 }
400
76c21947
WD
401 io_start_buffering_in(f_in);
402 io_start_buffering_out(f_out);
7a6421fa 403 send_files(flist,f_out,f_in);
f1e3656e 404 io_flush(FULL_FLUSH);
7a6421fa 405 report(f_out);
d04e9c51 406 if (protocol_version >= 24) {
d9c7edf6 407 /* final goodbye message */
64c3523a
WD
408 read_int(f_in);
409 }
f1e3656e 410 io_flush(FULL_FLUSH);
7a6421fa 411 exit_cleanup(0);
c627d613
AT
412}
413
414
dc5ddbcc
AT
415static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
416{
d186eb1a
AT
417 int pid;
418 int status=0;
554e0a8d 419 int error_pipe[2];
dc5ddbcc 420
d186eb1a
AT
421 if (preserve_hard_links)
422 init_hard_links(flist);
dc5ddbcc 423
6957ae33
AT
424 if (!delete_after) {
425 /* I moved this here from recv_files() to prevent a race condition */
426 if (recurse && delete_mode && !local_name && flist->count>0) {
427 delete_files(flist);
428 }
429 }
430
08f15335 431 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
432 rprintf(FERROR,"error pipe failed in do_recv\n");
433 exit_cleanup(RERR_SOCKETIO);
434 }
d9c7edf6 435
f1e3656e 436 io_flush(NORMAL_FLUSH);
c6e7fcb4 437
d186eb1a 438 if ((pid=do_fork()) == 0) {
554e0a8d 439 close(error_pipe[0]);
e08c9610
AT
440 if (f_in != f_out) close(f_out);
441
554e0a8d
AT
442 /* we can't let two processes write to the socket at one time */
443 io_multiplexing_close();
444
445 /* set place to send errors */
f1e3656e 446 set_msg_fd_out(error_pipe[1]);
554e0a8d 447
f1e3656e
WD
448 recv_files(f_in,flist,local_name);
449 io_flush(FULL_FLUSH);
ba5e128d 450 report(f_in);
e08c9610 451
f1e3656e
WD
452 send_msg(MSG_DONE, "", 0);
453 io_flush(FULL_FLUSH);
4a748188 454 /* finally we go to sleep until our parent kills us
9af87151
WD
455 * with a USR2 signal. We sleep for a short time as on
456 * some OSes a signal won't interrupt a sleep! */
f1e3656e
WD
457 while (1)
458 msleep(20);
d186eb1a 459 }
dc5ddbcc 460
b695f242
WD
461 am_generator = 1;
462
554e0a8d 463 close(error_pipe[1]);
e08c9610 464 if (f_in != f_out) close(f_in);
e1b3d5c4 465
76c21947 466 io_start_buffering_out(f_out);
b3e10ed7 467
f1e3656e 468 set_msg_fd_in(error_pipe[0]);
554e0a8d 469
f1e3656e 470 generate_files(f_out, flist, local_name);
8d9dc9f9 471
40da9042 472 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
e5fbaa71 473 report(-1);
f1e3656e 474 io_flush(FULL_FLUSH);
d04e9c51 475 if (protocol_version >= 24) {
8ada7518
AT
476 /* send a final goodbye message */
477 write_int(f_out, -1);
478 }
f1e3656e 479 io_flush(FULL_FLUSH);
8ada7518 480
f1e3656e 481 set_msg_fd_in(-1);
089a2435 482 kill(pid, SIGUSR2);
d79d1c69 483 wait_process(pid, &status);
d186eb1a 484 return status;
dc5ddbcc
AT
485}
486
c627d613 487
9486289c 488static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 489{
7a6421fa
AT
490 int status;
491 struct file_list *flist;
492 char *local_name=NULL;
493 char *dir = NULL;
f0fca04e 494
45e08edb
WD
495 if (verbose > 2) {
496 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
497 argc, (long)getpid());
498 }
09b7f5db
AT
499
500 if (am_daemon && lp_read_only(module_id) && !am_sender) {
501 rprintf(FERROR,"ERROR: module is read only\n");
502 exit_cleanup(RERR_SYNTAX);
503 return;
504 }
505
d9c7edf6 506
7a6421fa
AT
507 if (argc > 0) {
508 dir = argv[0];
509 argc--;
510 argv++;
59187666 511 if (!am_daemon && !push_dir(dir)) {
ea42541f
WD
512 rprintf(FERROR, "push_dir %s failed: %s (4)\n",
513 full_fname(dir), strerror(errno));
65417579 514 exit_cleanup(RERR_FILESELECT);
d9c7edf6 515 }
7a6421fa 516 }
c627d613 517
76c21947 518 io_start_buffering_in(f_in);
b33b791e 519 if (delete_mode && !delete_excluded)
7a6421fa 520 recv_exclude_list(f_in);
c627d613 521
7c2a9e76
WD
522 if (filesfrom_fd >= 0) {
523 /* We're receiving the file info from the sender, so we need
524 * the IO routines to automatically write out the names onto
525 * our f_out socket as we read the list info from the sender.
526 * This avoids both deadlock and extra delays/buffers. */
527 io_set_filesfrom_fds(filesfrom_fd, f_out);
528 filesfrom_fd = -1;
529 }
530
088aac85 531 if (read_batch)
d9c7edf6 532 flist = batch_flist;
6902ed17 533 else
d9c7edf6 534 flist = recv_file_list(f_in);
4c36a13e
AT
535 if (!flist) {
536 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 537 exit_cleanup(RERR_FILESELECT);
7a6421fa 538 }
d9c7edf6
WD
539
540 if (argc > 0) {
7a6421fa
AT
541 if (strcmp(dir,".")) {
542 argv[0] += strlen(dir);
543 if (argv[0][0] == '/') argv[0]++;
544 }
545 local_name = get_local_name(flist,argv[0]);
546 }
c627d613 547
7a6421fa
AT
548 status = do_recv(f_in,f_out,flist,local_name);
549 exit_cleanup(status);
c627d613
AT
550}
551
552
734a94a2 553int child_main(int argc, char *argv[])
25d34a5c
MP
554{
555 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 556 return 0;
25d34a5c
MP
557}
558
559
9486289c 560void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 561{
6d7b6081
AT
562 setup_protocol(f_out, f_in);
563
f0359dd0
AT
564 set_nonblocking(f_in);
565 set_nonblocking(f_out);
566
d04e9c51 567 if (protocol_version >= 23)
ff41a59f 568 io_start_multiplex_out(f_out);
7a6421fa 569
7a6421fa 570 if (am_sender) {
088aac85 571 if (!read_batch) {
d9c7edf6
WD
572 recv_exclude_list(f_in);
573 if (cvs_exclude)
574 add_cvs_excludes();
6902ed17 575 }
7a6421fa
AT
576 do_server_sender(f_in, f_out, argc, argv);
577 } else {
578 do_server_recv(f_in, f_out, argc, argv);
579 }
580 exit_cleanup(0);
366345fe
AT
581}
582
0ba48136
MP
583
584/*
585 * This is called once the connection has been negotiated. It is used
586 * for rsyncd, remote-shell, and local connections.
587 */
19b27a48 588int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 589{
088aac85 590 struct file_list *flist = NULL;
9486289c
AT
591 int status = 0, status2 = 0;
592 char *local_name = NULL;
19b27a48
AT
593
594 cleanup_child_pid = pid;
6902ed17 595 if (read_batch)
d9c7edf6 596 flist = batch_flist;
ff41a59f 597
f0359dd0
AT
598 set_nonblocking(f_in);
599 set_nonblocking(f_out);
600
6d7b6081
AT
601 setup_protocol(f_out,f_in);
602
d04e9c51 603 if (protocol_version >= 23)
ff41a59f 604 io_start_multiplex_in(f_in);
d9c7edf6 605
9486289c 606 if (am_sender) {
76c21947 607 io_start_buffering_out(f_out);
9486289c
AT
608 if (cvs_exclude)
609 add_cvs_excludes();
d9c7edf6 610 if (delete_mode && !delete_excluded)
9486289c 611 send_exclude_list(f_out);
7c2a9e76
WD
612 if (remote_filesfrom_file)
613 filesfrom_fd = f_in;
64c3523a 614 if (!read_batch) /* don't write to pipe */
d9c7edf6
WD
615 flist = send_file_list(f_out,argc,argv);
616 if (verbose > 3)
9486289c 617 rprintf(FINFO,"file list sent\n");
e1b3d5c4 618
f1e3656e 619 io_flush(NORMAL_FLUSH);
9486289c 620 send_files(flist,f_out,f_in);
f1e3656e 621 io_flush(FULL_FLUSH);
d04e9c51 622 if (protocol_version >= 24) {
d9c7edf6 623 /* final goodbye message */
6c65e146
AT
624 read_int(f_in);
625 }
9486289c
AT
626 if (pid != -1) {
627 if (verbose > 3)
08a740ff 628 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 629 io_flush(FULL_FLUSH);
d79d1c69 630 wait_process(pid, &status);
9486289c 631 }
3d382777 632 report(-1);
f1e3656e 633 io_flush(FULL_FLUSH);
9486289c
AT
634 exit_cleanup(status);
635 }
f7632fc6 636
27e3e9c9 637 if (argc == 0) {
27e3e9c9
AT
638 list_only = 1;
639 }
d9c7edf6 640
088aac85 641 if (!write_batch)
d9c7edf6
WD
642 send_exclude_list(f_out);
643
7c2a9e76
WD
644 if (filesfrom_fd >= 0) {
645 io_set_filesfrom_fds(filesfrom_fd, f_out);
646 filesfrom_fd = -1;
647 }
648
9486289c
AT
649 flist = recv_file_list(f_in);
650 if (!flist || flist->count == 0) {
796d484b 651 rprintf(FINFO, "client: nothing to do: "
d9c7edf6
WD
652 "perhaps you need to specify some filenames or "
653 "the --recursive option?\n");
9486289c
AT
654 exit_cleanup(0);
655 }
d9c7edf6 656
9486289c 657 local_name = get_local_name(flist,argv[0]);
d9c7edf6 658
9486289c 659 status2 = do_recv(f_in,f_out,flist,local_name);
d9c7edf6 660
9486289c 661 if (pid != -1) {
8d9dc9f9 662 if (verbose > 3)
08a740ff 663 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 664 io_flush(FULL_FLUSH);
d79d1c69 665 wait_process(pid, &status);
9486289c 666 }
d9c7edf6 667
ff81e809 668 return MAX(status, status2);
9486289c
AT
669}
670
7169bb4a
MP
671static int copy_argv (char *argv[])
672{
673 int i;
674
675 for (i = 0; argv[i]; i++) {
676 if (!(argv[i] = strdup(argv[i]))) {
677 rprintf (FERROR, "out of memory at %s(%d)\n",
678 __FILE__, __LINE__);
679 return RERR_MALLOC;
680 }
681 }
682
683 return 0;
684}
685
686
c1a04ecb 687/**
0ba48136
MP
688 * Start a client for either type of remote connection. Work out
689 * whether the arguments request a remote shell or rsyncd connection,
690 * and call the appropriate connection function, then run_client.
0b4af330
MP
691 *
692 * Calls either start_socket_client (for sockets) or do_cmd and
693 * client_run (for ssh).
c1a04ecb 694 **/
fc8a6b97 695static int start_client(int argc, char *argv[])
5d6bcd44
AT
696{
697 char *p;
698 char *shell_machine = NULL;
699 char *shell_path = NULL;
700 char *shell_user = NULL;
19b27a48
AT
701 int ret;
702 pid_t pid;
5d6bcd44 703 int f_in,f_out;
7169bb4a
MP
704 int rc;
705
706 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 707 * command line. */
75aeac44 708 if ((rc = copy_argv(argv)))
7169bb4a 709 return rc;
5d6bcd44 710
75aeac44 711 /* rsync:// always uses rsync server over direct socket connection */
7169bb4a 712 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
f7632fc6
AT
713 char *host, *path;
714
7169bb4a 715 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
716 p = strchr(host,'/');
717 if (p) {
718 *p = 0;
719 path = p+1;
720 } else {
a125c82a 721 path = "";
f7632fc6 722 }
2acf81eb
DD
723 p = strchr(host,':');
724 if (p) {
725 rsync_port = atoi(p+1);
726 *p = 0;
727 }
f7632fc6
AT
728 return start_socket_client(host, path, argc-1, argv+1);
729 }
730
088aac85 731 if (!read_batch) {
a125c82a 732 p = find_colon(argv[0]);
d9c7edf6 733 if (p) {
7c2a9e76
WD
734 if (remote_filesfrom_file
735 && remote_filesfrom_file != files_from + 1
736 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
737 rprintf(FERROR,
738 "--files-from hostname is not transfer hostname\n");
739 exit_cleanup(RERR_SYNTAX);
740 }
d9c7edf6
WD
741 if (p[1] == ':') { /* double colon */
742 *p = 0;
743 if (!shell_cmd) {
744 return start_socket_client(argv[0], p+2,
745 argc-1, argv+1);
746 }
747 p++;
748 daemon_over_rsh = 1;
75aeac44 749 }
3591c066 750
d9c7edf6
WD
751 if (argc < 1) {
752 usage(FERROR);
753 exit_cleanup(RERR_SYNTAX);
754 }
a125c82a 755
d9c7edf6
WD
756 am_sender = 0;
757 *p = 0;
758 shell_machine = argv[0];
759 shell_path = p+1;
760 argc--;
761 argv++;
762 } else {
763 am_sender = 1;
764
765 /* rsync:// destination uses rsync server over direct socket */
766 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
767 char *host, *path;
768
769 host = argv[argc-1] + strlen(URL_PREFIX);
770 p = strchr(host,'/');
771 if (p) {
772 *p = 0;
773 path = p+1;
774 } else {
775 path = "";
776 }
777 p = strchr(host,':');
778 if (p) {
779 rsync_port = atoi(p+1);
780 *p = 0;
781 }
782 return start_socket_client(host, path, argc-1, argv);
a125c82a 783 }
d9c7edf6
WD
784
785 p = find_colon(argv[argc-1]);
7c2a9e76
WD
786 if (p && remote_filesfrom_file
787 && remote_filesfrom_file != files_from + 1
788 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
789 rprintf(FERROR,
790 "--files-from hostname is not transfer hostname\n");
791 exit_cleanup(RERR_SYNTAX);
792 }
d9c7edf6
WD
793 if (!p) {
794 local_server = 1;
7c2a9e76
WD
795 if (remote_filesfrom_file) {
796 rprintf(FERROR,
797 "--files-from is remote but transfer is local\n");
798 exit_cleanup(RERR_SYNTAX);
799 }
d9c7edf6 800 } else if (p[1] == ':') { /* double colon */
a125c82a 801 *p = 0;
d9c7edf6
WD
802 if (!shell_cmd) {
803 return start_socket_client(argv[argc-1], p+2,
804 argc-1, argv);
805 }
806 p++;
807 daemon_over_rsh = 1;
a125c82a 808 }
a125c82a 809
d9c7edf6
WD
810 if (argc < 2) {
811 usage(FERROR);
812 exit_cleanup(RERR_SYNTAX);
75aeac44 813 }
3591c066 814
d9c7edf6
WD
815 if (local_server) {
816 shell_machine = NULL;
817 shell_path = argv[argc-1];
818 } else {
819 *p = 0;
820 shell_machine = argv[argc-1];
821 shell_path = p+1;
822 }
823 argc--;
5d6bcd44 824 }
6902ed17 825 } else {
d9c7edf6
WD
826 am_sender = 1;
827 local_server = 1;
828 shell_path = argv[argc-1];
6902ed17
MP
829 }
830
5d6bcd44 831 if (shell_machine) {
6fc048f4 832 p = strrchr(shell_machine,'@');
5d6bcd44
AT
833 if (p) {
834 *p = 0;
835 shell_user = shell_machine;
836 shell_machine = p+1;
837 }
838 }
839
840 if (verbose > 3) {
9486289c 841 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
842 shell_cmd?shell_cmd:"",
843 shell_machine?shell_machine:"",
844 shell_user?shell_user:"",
845 shell_path?shell_path:"");
846 }
d9c7edf6 847
f7632fc6 848 if (!am_sender && argc > 1) {
5d6bcd44 849 usage(FERROR);
65417579 850 exit_cleanup(RERR_SYNTAX);
5d6bcd44 851 }
27e3e9c9
AT
852
853 if (argc == 0 && !am_sender) {
27e3e9c9
AT
854 list_only = 1;
855 }
d9c7edf6 856
75aeac44
WD
857 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
858 &f_in,&f_out);
859
860 /* if we're running an rsync server on the remote host over a
9af87151 861 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
862 if (daemon_over_rsh) {
863 int tmpret;
864 tmpret = start_inband_exchange(shell_user, shell_path,
865 f_in, f_out, argc);
866 if (tmpret < 0)
867 return tmpret;
868 }
869
fc8a6b97
AT
870 ret = client_run(f_in, f_out, pid, argc, argv);
871
872 fflush(stdout);
873 fflush(stderr);
874
875 return ret;
5d6bcd44
AT
876}
877
366345fe 878
067669da
WD
879static RETSIGTYPE sigusr1_handler(UNUSED(int val))
880{
65417579 881 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
882}
883
067669da
WD
884static RETSIGTYPE sigusr2_handler(UNUSED(int val))
885{
19b27a48 886 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
887 _exit(0);
888}
889
067669da
WD
890static RETSIGTYPE sigchld_handler(UNUSED(int val))
891{
029c1713 892#ifdef WNOHANG
ee7118a8
DD
893 int cnt, status;
894 pid_t pid;
895 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 896 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
897 * out we're instead saving the child exit statuses for later use.
898 * The waitpid() loop presumably eliminates all possibility of leaving
899 * zombie children, maybe that's why he did it.
900 */
901 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
902 /* save the child's exit status */
903 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
904 if (pid_stat_table[cnt].pid == 0) {
905 pid_stat_table[cnt].pid = pid;
906 pid_stat_table[cnt].status = status;
907 break;
908 }
909 }
ee7118a8 910 }
029c1713 911#endif
19b27a48
AT
912}
913
c0531332
MP
914
915/**
916 * This routine catches signals and tries to send them to gdb.
917 *
918 * Because it's called from inside a signal handler it ought not to
919 * use too many library routines.
920 *
921 * @todo Perhaps use "screen -X" instead/as well, to help people
922 * debugging without easy access to X. Perhaps use an environment
923 * variable, or just call a script?
924 *
925 * @todo The /proc/ magic probably only works on Linux (and
926 * Solaris?) Can we be more portable?
927 **/
928#ifdef MAINTAINER_MODE
4fdc39dd
MP
929const char *get_panic_action(void)
930{
931 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
932
933 if (cmd_fmt)
934 return cmd_fmt;
935 else
936 return "xterm -display :0 -T Panic -n Panic "
937 "-e gdb /proc/%d/exe %d";
938}
939
940
9fb3f7a9
MP
941/**
942 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
943 *
944 * This signal handler is only installed if we were configured with
945 * --enable-maintainer-mode. Perhaps it should always be on and we
946 * should just look at the environment variable, but I'm a bit leery
947 * of a signal sending us into a busy loop.
948 **/
067669da 949static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
950{
951 char cmd_buf[300];
952 int ret;
4fdc39dd
MP
953
954 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
955 getpid(), getpid());
956
957 /* Unless we failed to execute gdb, we allow the process to
958 * continue. I'm not sure if that's right. */
959 ret = system(cmd_buf);
960 if (ret)
961 _exit(ret);
962}
963#endif
964
965
5d6bcd44 966int main(int argc,char *argv[])
d9c7edf6 967{
ff81e809 968 int ret;
088aac85 969 int orig_argc;
76f79ba7 970 char **orig_argv;
6902ed17 971
088aac85 972 orig_argc = argc;
76f79ba7 973 orig_argv = argv;
5d6bcd44 974
7a6421fa 975 signal(SIGUSR1, sigusr1_handler);
8b35435f 976 signal(SIGUSR2, sigusr2_handler);
19b27a48 977 signal(SIGCHLD, sigchld_handler);
c0531332
MP
978#ifdef MAINTAINER_MODE
979 signal(SIGSEGV, rsync_panic_handler);
980 signal(SIGFPE, rsync_panic_handler);
981 signal(SIGABRT, rsync_panic_handler);
982 signal(SIGBUS, rsync_panic_handler);
983#endif /* def MAINTAINER_MODE */
5d6bcd44 984
7a6421fa 985 starttime = time(NULL);
6fe05820 986 am_root = (MY_UID() == 0);
c627d613 987
a800434a
AT
988 memset(&stats, 0, sizeof(stats));
989
df5e03da
AT
990 if (argc < 2) {
991 usage(FERROR);
65417579 992 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
993 }
994
7a6421fa 995 /* we set a 0 umask so that correct file permissions can be
9af87151 996 * carried across */
7a6421fa 997 orig_umask = (int)umask(0);
5d6bcd44 998
50135767 999 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
1000 /* FIXME: We ought to call the same error-handling
1001 * code here, rather than relying on getopt. */
50135767 1002 option_error();
65417579 1003 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1004 }
5d6bcd44 1005
7a6421fa 1006 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1007 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1008 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1009
34758d5c
MP
1010 /* Ignore SIGPIPE; we consistently check error codes and will
1011 * see the EPIPE. */
1012 signal(SIGPIPE, SIG_IGN);
1013
c226b7c2 1014 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1015 * (implemented by forking "pwd" and reading its output) doesn't
1016 * work when there are other child processes. Also, on all systems
1017 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1018 push_dir(NULL);
c226b7c2 1019
44e9e221
WD
1020 init_flist();
1021
088aac85 1022 if (write_batch && !am_server) {
d9c7edf6 1023 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
1024 }
1025
75aeac44 1026 if (am_daemon && !am_server)
7a6421fa 1027 return daemon_main();
f0fca04e 1028
08ac228f
AT
1029 if (argc < 1) {
1030 usage(FERROR);
65417579 1031 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1032 }
1033
7a6421fa
AT
1034 if (dry_run)
1035 verbose = MAX(verbose,1);
c627d613 1036
7a6421fa 1037 if (am_server) {
f0359dd0
AT
1038 set_nonblocking(STDIN_FILENO);
1039 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1040 if (am_daemon)
1041 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1042 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1043 }
c627d613 1044
ff81e809 1045 ret = start_client(argc, argv);
d9c7edf6 1046 if (ret == -1)
9098bbf3 1047 exit_cleanup(RERR_STARTCLIENT);
088aac85 1048 else
9098bbf3
MP
1049 exit_cleanup(ret);
1050
0f5a04e3 1051 return ret;
c627d613 1052}