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