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