A few minor text improvements.
[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
59187666 372 if (!relative_paths && !push_dir(dir)) {
982e05bb
WD
373 rsyserr(FERROR, errno, "push_dir#3 %s failed",
374 full_fname(dir));
65417579 375 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
376 }
377 argc--;
378 argv++;
d9c7edf6 379
7a6421fa
AT
380 if (strcmp(dir,".")) {
381 int l = strlen(dir);
d9c7edf6 382 if (strcmp(dir,"/") == 0)
7a6421fa
AT
383 l = 0;
384 for (i=0;i<argc;i++)
385 argv[i] += l+1;
386 }
c627d613 387
7a6421fa
AT
388 if (argc == 0 && recurse) {
389 argc=1;
390 argv--;
391 argv[0] = ".";
392 }
d9c7edf6 393
7a6421fa 394 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
395 if (!flist || flist->count == 0) {
396 exit_cleanup(0);
397 }
398
76c21947
WD
399 io_start_buffering_in(f_in);
400 io_start_buffering_out(f_out);
7a6421fa 401 send_files(flist,f_out,f_in);
f1e3656e 402 io_flush(FULL_FLUSH);
7a6421fa 403 report(f_out);
d04e9c51 404 if (protocol_version >= 24) {
d9c7edf6 405 /* final goodbye message */
64c3523a
WD
406 read_int(f_in);
407 }
f1e3656e 408 io_flush(FULL_FLUSH);
7a6421fa 409 exit_cleanup(0);
c627d613
AT
410}
411
412
dc5ddbcc
AT
413static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
414{
d186eb1a
AT
415 int pid;
416 int status=0;
554e0a8d 417 int error_pipe[2];
dc5ddbcc 418
d186eb1a
AT
419 if (preserve_hard_links)
420 init_hard_links(flist);
dc5ddbcc 421
6957ae33
AT
422 if (!delete_after) {
423 /* I moved this here from recv_files() to prevent a race condition */
424 if (recurse && delete_mode && !local_name && flist->count>0) {
425 delete_files(flist);
426 }
427 }
428
08f15335 429 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
430 rprintf(FERROR,"error pipe failed in do_recv\n");
431 exit_cleanup(RERR_SOCKETIO);
432 }
d9c7edf6 433
f1e3656e 434 io_flush(NORMAL_FLUSH);
c6e7fcb4 435
d186eb1a 436 if ((pid=do_fork()) == 0) {
554e0a8d 437 close(error_pipe[0]);
e08c9610
AT
438 if (f_in != f_out) close(f_out);
439
554e0a8d
AT
440 /* we can't let two processes write to the socket at one time */
441 io_multiplexing_close();
442
443 /* set place to send errors */
f1e3656e 444 set_msg_fd_out(error_pipe[1]);
554e0a8d 445
f1e3656e
WD
446 recv_files(f_in,flist,local_name);
447 io_flush(FULL_FLUSH);
ba5e128d 448 report(f_in);
e08c9610 449
f1e3656e
WD
450 send_msg(MSG_DONE, "", 0);
451 io_flush(FULL_FLUSH);
4a748188 452 /* finally we go to sleep until our parent kills us
9af87151
WD
453 * with a USR2 signal. We sleep for a short time as on
454 * some OSes a signal won't interrupt a sleep! */
f1e3656e
WD
455 while (1)
456 msleep(20);
d186eb1a 457 }
dc5ddbcc 458
b695f242
WD
459 am_generator = 1;
460
554e0a8d 461 close(error_pipe[1]);
e08c9610 462 if (f_in != f_out) close(f_in);
e1b3d5c4 463
76c21947 464 io_start_buffering_out(f_out);
b3e10ed7 465
f1e3656e 466 set_msg_fd_in(error_pipe[0]);
554e0a8d 467
f1e3656e 468 generate_files(f_out, flist, local_name);
8d9dc9f9 469
40da9042 470 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
e5fbaa71 471 report(-1);
f1e3656e 472 io_flush(FULL_FLUSH);
d04e9c51 473 if (protocol_version >= 24) {
8ada7518
AT
474 /* send a final goodbye message */
475 write_int(f_out, -1);
476 }
f1e3656e 477 io_flush(FULL_FLUSH);
8ada7518 478
f1e3656e 479 set_msg_fd_in(-1);
089a2435 480 kill(pid, SIGUSR2);
d79d1c69 481 wait_process(pid, &status);
d186eb1a 482 return status;
dc5ddbcc
AT
483}
484
c627d613 485
9486289c 486static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 487{
7a6421fa
AT
488 int status;
489 struct file_list *flist;
6c2e5b56 490 char *local_name = NULL;
7a6421fa 491 char *dir = NULL;
f0fca04e 492
45e08edb
WD
493 if (verbose > 2) {
494 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
495 argc, (long)getpid());
496 }
09b7f5db
AT
497
498 if (am_daemon && lp_read_only(module_id) && !am_sender) {
499 rprintf(FERROR,"ERROR: module is read only\n");
500 exit_cleanup(RERR_SYNTAX);
501 return;
502 }
503
d9c7edf6 504
7a6421fa
AT
505 if (argc > 0) {
506 dir = argv[0];
507 argc--;
508 argv++;
59187666 509 if (!am_daemon && !push_dir(dir)) {
982e05bb
WD
510 rsyserr(FERROR, errno, "push_dir#4 %s failed",
511 full_fname(dir));
65417579 512 exit_cleanup(RERR_FILESELECT);
d9c7edf6 513 }
7a6421fa 514 }
c627d613 515
76c21947 516 io_start_buffering_in(f_in);
b33b791e 517 if (delete_mode && !delete_excluded)
7a6421fa 518 recv_exclude_list(f_in);
c627d613 519
7c2a9e76
WD
520 if (filesfrom_fd >= 0) {
521 /* We're receiving the file info from the sender, so we need
522 * the IO routines to automatically write out the names onto
523 * our f_out socket as we read the list info from the sender.
524 * This avoids both deadlock and extra delays/buffers. */
525 io_set_filesfrom_fds(filesfrom_fd, f_out);
526 filesfrom_fd = -1;
527 }
528
088aac85 529 if (read_batch)
d9c7edf6 530 flist = batch_flist;
6902ed17 531 else
d9c7edf6 532 flist = recv_file_list(f_in);
4c36a13e
AT
533 if (!flist) {
534 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 535 exit_cleanup(RERR_FILESELECT);
7a6421fa 536 }
d9c7edf6
WD
537
538 if (argc > 0) {
7a6421fa
AT
539 if (strcmp(dir,".")) {
540 argv[0] += strlen(dir);
541 if (argv[0][0] == '/') argv[0]++;
542 }
543 local_name = get_local_name(flist,argv[0]);
544 }
c627d613 545
7a6421fa
AT
546 status = do_recv(f_in,f_out,flist,local_name);
547 exit_cleanup(status);
c627d613
AT
548}
549
550
734a94a2 551int child_main(int argc, char *argv[])
25d34a5c
MP
552{
553 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 554 return 0;
25d34a5c
MP
555}
556
557
9486289c 558void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 559{
6d7b6081
AT
560 setup_protocol(f_out, f_in);
561
f0359dd0
AT
562 set_nonblocking(f_in);
563 set_nonblocking(f_out);
564
d04e9c51 565 if (protocol_version >= 23)
ff41a59f 566 io_start_multiplex_out(f_out);
7a6421fa 567
7a6421fa 568 if (am_sender) {
088aac85 569 if (!read_batch) {
d9c7edf6
WD
570 recv_exclude_list(f_in);
571 if (cvs_exclude)
572 add_cvs_excludes();
6902ed17 573 }
7a6421fa
AT
574 do_server_sender(f_in, f_out, argc, argv);
575 } else {
576 do_server_recv(f_in, f_out, argc, argv);
577 }
578 exit_cleanup(0);
366345fe
AT
579}
580
0ba48136
MP
581
582/*
583 * This is called once the connection has been negotiated. It is used
584 * for rsyncd, remote-shell, and local connections.
585 */
19b27a48 586int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 587{
088aac85 588 struct file_list *flist = NULL;
9486289c
AT
589 int status = 0, status2 = 0;
590 char *local_name = NULL;
19b27a48
AT
591
592 cleanup_child_pid = pid;
6902ed17 593 if (read_batch)
d9c7edf6 594 flist = batch_flist;
ff41a59f 595
f0359dd0
AT
596 set_nonblocking(f_in);
597 set_nonblocking(f_out);
598
6d7b6081
AT
599 setup_protocol(f_out,f_in);
600
d04e9c51 601 if (protocol_version >= 23)
ff41a59f 602 io_start_multiplex_in(f_in);
d9c7edf6 603
9486289c 604 if (am_sender) {
76c21947 605 io_start_buffering_out(f_out);
9486289c
AT
606 if (cvs_exclude)
607 add_cvs_excludes();
d9c7edf6 608 if (delete_mode && !delete_excluded)
9486289c 609 send_exclude_list(f_out);
7c2a9e76
WD
610 if (remote_filesfrom_file)
611 filesfrom_fd = f_in;
64c3523a 612 if (!read_batch) /* don't write to pipe */
d9c7edf6
WD
613 flist = send_file_list(f_out,argc,argv);
614 if (verbose > 3)
9486289c 615 rprintf(FINFO,"file list sent\n");
e1b3d5c4 616
f1e3656e 617 io_flush(NORMAL_FLUSH);
9486289c 618 send_files(flist,f_out,f_in);
f1e3656e 619 io_flush(FULL_FLUSH);
d04e9c51 620 if (protocol_version >= 24) {
d9c7edf6 621 /* final goodbye message */
6c65e146
AT
622 read_int(f_in);
623 }
9486289c
AT
624 if (pid != -1) {
625 if (verbose > 3)
08a740ff 626 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 627 io_flush(FULL_FLUSH);
d79d1c69 628 wait_process(pid, &status);
9486289c 629 }
3d382777 630 report(-1);
f1e3656e 631 io_flush(FULL_FLUSH);
9486289c
AT
632 exit_cleanup(status);
633 }
f7632fc6 634
1082b52b 635 if (argc == 0)
27e3e9c9 636 list_only = 1;
d9c7edf6 637
1082b52b 638 if (!read_batch)
d9c7edf6
WD
639 send_exclude_list(f_out);
640
7c2a9e76
WD
641 if (filesfrom_fd >= 0) {
642 io_set_filesfrom_fds(filesfrom_fd, f_out);
643 filesfrom_fd = -1;
644 }
645
9486289c
AT
646 flist = recv_file_list(f_in);
647 if (!flist || flist->count == 0) {
796d484b 648 rprintf(FINFO, "client: nothing to do: "
d9c7edf6
WD
649 "perhaps you need to specify some filenames or "
650 "the --recursive option?\n");
9486289c
AT
651 exit_cleanup(0);
652 }
d9c7edf6 653
9486289c 654 local_name = get_local_name(flist,argv[0]);
d9c7edf6 655
9486289c 656 status2 = do_recv(f_in,f_out,flist,local_name);
d9c7edf6 657
9486289c 658 if (pid != -1) {
8d9dc9f9 659 if (verbose > 3)
08a740ff 660 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 661 io_flush(FULL_FLUSH);
d79d1c69 662 wait_process(pid, &status);
9486289c 663 }
d9c7edf6 664
ff81e809 665 return MAX(status, status2);
9486289c
AT
666}
667
7169bb4a
MP
668static int copy_argv (char *argv[])
669{
670 int i;
671
672 for (i = 0; argv[i]; i++) {
673 if (!(argv[i] = strdup(argv[i]))) {
674 rprintf (FERROR, "out of memory at %s(%d)\n",
675 __FILE__, __LINE__);
676 return RERR_MALLOC;
677 }
678 }
679
680 return 0;
681}
682
683
c1a04ecb 684/**
0ba48136
MP
685 * Start a client for either type of remote connection. Work out
686 * whether the arguments request a remote shell or rsyncd connection,
687 * and call the appropriate connection function, then run_client.
0b4af330
MP
688 *
689 * Calls either start_socket_client (for sockets) or do_cmd and
690 * client_run (for ssh).
c1a04ecb 691 **/
fc8a6b97 692static int start_client(int argc, char *argv[])
5d6bcd44
AT
693{
694 char *p;
695 char *shell_machine = NULL;
696 char *shell_path = NULL;
697 char *shell_user = NULL;
19b27a48
AT
698 int ret;
699 pid_t pid;
5d6bcd44 700 int f_in,f_out;
7169bb4a
MP
701 int rc;
702
703 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 704 * command line. */
75aeac44 705 if ((rc = copy_argv(argv)))
7169bb4a 706 return rc;
5d6bcd44 707
75aeac44 708 /* rsync:// always uses rsync server over direct socket connection */
7169bb4a 709 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
f7632fc6
AT
710 char *host, *path;
711
7169bb4a 712 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
713 p = strchr(host,'/');
714 if (p) {
715 *p = 0;
716 path = p+1;
717 } else {
a125c82a 718 path = "";
f7632fc6 719 }
2acf81eb
DD
720 p = strchr(host,':');
721 if (p) {
722 rsync_port = atoi(p+1);
723 *p = 0;
724 }
f7632fc6
AT
725 return start_socket_client(host, path, argc-1, argv+1);
726 }
727
088aac85 728 if (!read_batch) {
a125c82a 729 p = find_colon(argv[0]);
d9c7edf6 730 if (p) {
7c2a9e76
WD
731 if (remote_filesfrom_file
732 && remote_filesfrom_file != files_from + 1
733 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
734 rprintf(FERROR,
735 "--files-from hostname is not transfer hostname\n");
736 exit_cleanup(RERR_SYNTAX);
737 }
d9c7edf6
WD
738 if (p[1] == ':') { /* double colon */
739 *p = 0;
740 if (!shell_cmd) {
741 return start_socket_client(argv[0], p+2,
742 argc-1, argv+1);
743 }
744 p++;
745 daemon_over_rsh = 1;
75aeac44 746 }
3591c066 747
d9c7edf6
WD
748 if (argc < 1) {
749 usage(FERROR);
750 exit_cleanup(RERR_SYNTAX);
751 }
a125c82a 752
d9c7edf6
WD
753 am_sender = 0;
754 *p = 0;
755 shell_machine = argv[0];
756 shell_path = p+1;
757 argc--;
758 argv++;
759 } else {
760 am_sender = 1;
761
762 /* rsync:// destination uses rsync server over direct socket */
763 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
764 char *host, *path;
765
766 host = argv[argc-1] + strlen(URL_PREFIX);
767 p = strchr(host,'/');
768 if (p) {
769 *p = 0;
770 path = p+1;
771 } else {
772 path = "";
773 }
774 p = strchr(host,':');
775 if (p) {
776 rsync_port = atoi(p+1);
777 *p = 0;
778 }
779 return start_socket_client(host, path, argc-1, argv);
a125c82a 780 }
d9c7edf6
WD
781
782 p = find_colon(argv[argc-1]);
7c2a9e76
WD
783 if (p && remote_filesfrom_file
784 && remote_filesfrom_file != files_from + 1
785 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
786 rprintf(FERROR,
787 "--files-from hostname is not transfer hostname\n");
788 exit_cleanup(RERR_SYNTAX);
789 }
d9c7edf6
WD
790 if (!p) {
791 local_server = 1;
7c2a9e76
WD
792 if (remote_filesfrom_file) {
793 rprintf(FERROR,
794 "--files-from is remote but transfer is local\n");
795 exit_cleanup(RERR_SYNTAX);
796 }
d9c7edf6 797 } else if (p[1] == ':') { /* double colon */
a125c82a 798 *p = 0;
d9c7edf6
WD
799 if (!shell_cmd) {
800 return start_socket_client(argv[argc-1], p+2,
801 argc-1, argv);
802 }
803 p++;
804 daemon_over_rsh = 1;
a125c82a 805 }
a125c82a 806
d9c7edf6
WD
807 if (argc < 2) {
808 usage(FERROR);
809 exit_cleanup(RERR_SYNTAX);
75aeac44 810 }
3591c066 811
d9c7edf6
WD
812 if (local_server) {
813 shell_machine = NULL;
814 shell_path = argv[argc-1];
815 } else {
816 *p = 0;
817 shell_machine = argv[argc-1];
818 shell_path = p+1;
819 }
820 argc--;
5d6bcd44 821 }
6902ed17 822 } else {
d9c7edf6
WD
823 am_sender = 1;
824 local_server = 1;
825 shell_path = argv[argc-1];
6902ed17
MP
826 }
827
5d6bcd44 828 if (shell_machine) {
6fc048f4 829 p = strrchr(shell_machine,'@');
5d6bcd44
AT
830 if (p) {
831 *p = 0;
832 shell_user = shell_machine;
833 shell_machine = p+1;
834 }
835 }
836
837 if (verbose > 3) {
9486289c 838 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
839 shell_cmd?shell_cmd:"",
840 shell_machine?shell_machine:"",
841 shell_user?shell_user:"",
842 shell_path?shell_path:"");
843 }
d9c7edf6 844
f7632fc6 845 if (!am_sender && argc > 1) {
5d6bcd44 846 usage(FERROR);
65417579 847 exit_cleanup(RERR_SYNTAX);
5d6bcd44 848 }
27e3e9c9
AT
849
850 if (argc == 0 && !am_sender) {
27e3e9c9
AT
851 list_only = 1;
852 }
d9c7edf6 853
75aeac44
WD
854 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
855 &f_in,&f_out);
856
857 /* if we're running an rsync server on the remote host over a
9af87151 858 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
859 if (daemon_over_rsh) {
860 int tmpret;
861 tmpret = start_inband_exchange(shell_user, shell_path,
862 f_in, f_out, argc);
863 if (tmpret < 0)
864 return tmpret;
865 }
866
fc8a6b97
AT
867 ret = client_run(f_in, f_out, pid, argc, argv);
868
869 fflush(stdout);
870 fflush(stderr);
871
872 return ret;
5d6bcd44
AT
873}
874
366345fe 875
067669da
WD
876static RETSIGTYPE sigusr1_handler(UNUSED(int val))
877{
65417579 878 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
879}
880
067669da
WD
881static RETSIGTYPE sigusr2_handler(UNUSED(int val))
882{
19b27a48 883 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
884 _exit(0);
885}
886
067669da
WD
887static RETSIGTYPE sigchld_handler(UNUSED(int val))
888{
029c1713 889#ifdef WNOHANG
ee7118a8
DD
890 int cnt, status;
891 pid_t pid;
892 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 893 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
894 * out we're instead saving the child exit statuses for later use.
895 * The waitpid() loop presumably eliminates all possibility of leaving
896 * zombie children, maybe that's why he did it.
897 */
898 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
899 /* save the child's exit status */
900 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
901 if (pid_stat_table[cnt].pid == 0) {
902 pid_stat_table[cnt].pid = pid;
903 pid_stat_table[cnt].status = status;
904 break;
905 }
906 }
ee7118a8 907 }
029c1713 908#endif
19b27a48
AT
909}
910
c0531332
MP
911
912/**
913 * This routine catches signals and tries to send them to gdb.
914 *
915 * Because it's called from inside a signal handler it ought not to
916 * use too many library routines.
917 *
918 * @todo Perhaps use "screen -X" instead/as well, to help people
919 * debugging without easy access to X. Perhaps use an environment
920 * variable, or just call a script?
921 *
922 * @todo The /proc/ magic probably only works on Linux (and
923 * Solaris?) Can we be more portable?
924 **/
925#ifdef MAINTAINER_MODE
4fdc39dd
MP
926const char *get_panic_action(void)
927{
928 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
929
930 if (cmd_fmt)
931 return cmd_fmt;
932 else
933 return "xterm -display :0 -T Panic -n Panic "
934 "-e gdb /proc/%d/exe %d";
935}
936
937
9fb3f7a9
MP
938/**
939 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
940 *
941 * This signal handler is only installed if we were configured with
942 * --enable-maintainer-mode. Perhaps it should always be on and we
943 * should just look at the environment variable, but I'm a bit leery
944 * of a signal sending us into a busy loop.
945 **/
067669da 946static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
947{
948 char cmd_buf[300];
949 int ret;
4fdc39dd
MP
950
951 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
952 getpid(), getpid());
953
954 /* Unless we failed to execute gdb, we allow the process to
955 * continue. I'm not sure if that's right. */
956 ret = system(cmd_buf);
957 if (ret)
958 _exit(ret);
959}
960#endif
961
962
5d6bcd44 963int main(int argc,char *argv[])
d9c7edf6 964{
ff81e809 965 int ret;
088aac85 966 int orig_argc;
76f79ba7 967 char **orig_argv;
6902ed17 968
088aac85 969 orig_argc = argc;
76f79ba7 970 orig_argv = argv;
5d6bcd44 971
7a6421fa 972 signal(SIGUSR1, sigusr1_handler);
8b35435f 973 signal(SIGUSR2, sigusr2_handler);
19b27a48 974 signal(SIGCHLD, sigchld_handler);
c0531332
MP
975#ifdef MAINTAINER_MODE
976 signal(SIGSEGV, rsync_panic_handler);
977 signal(SIGFPE, rsync_panic_handler);
978 signal(SIGABRT, rsync_panic_handler);
979 signal(SIGBUS, rsync_panic_handler);
980#endif /* def MAINTAINER_MODE */
5d6bcd44 981
7a6421fa 982 starttime = time(NULL);
6fe05820 983 am_root = (MY_UID() == 0);
c627d613 984
a800434a
AT
985 memset(&stats, 0, sizeof(stats));
986
df5e03da
AT
987 if (argc < 2) {
988 usage(FERROR);
65417579 989 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
990 }
991
7a6421fa 992 /* we set a 0 umask so that correct file permissions can be
9af87151 993 * carried across */
7a6421fa 994 orig_umask = (int)umask(0);
5d6bcd44 995
50135767 996 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
997 /* FIXME: We ought to call the same error-handling
998 * code here, rather than relying on getopt. */
50135767 999 option_error();
65417579 1000 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1001 }
5d6bcd44 1002
7a6421fa 1003 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1004 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1005 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1006
34758d5c
MP
1007 /* Ignore SIGPIPE; we consistently check error codes and will
1008 * see the EPIPE. */
1009 signal(SIGPIPE, SIG_IGN);
1010
c226b7c2 1011 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1012 * (implemented by forking "pwd" and reading its output) doesn't
1013 * work when there are other child processes. Also, on all systems
1014 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1015 push_dir(NULL);
c226b7c2 1016
44e9e221
WD
1017 init_flist();
1018
088aac85 1019 if (write_batch && !am_server) {
d9c7edf6 1020 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
1021 }
1022
75aeac44 1023 if (am_daemon && !am_server)
7a6421fa 1024 return daemon_main();
f0fca04e 1025
08ac228f
AT
1026 if (argc < 1) {
1027 usage(FERROR);
65417579 1028 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1029 }
1030
7a6421fa
AT
1031 if (dry_run)
1032 verbose = MAX(verbose,1);
c627d613 1033
7a6421fa 1034 if (am_server) {
f0359dd0
AT
1035 set_nonblocking(STDIN_FILENO);
1036 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1037 if (am_daemon)
1038 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1039 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1040 }
c627d613 1041
ff81e809 1042 ret = start_client(argc, argv);
d9c7edf6 1043 if (ret == -1)
9098bbf3 1044 exit_cleanup(RERR_STARTCLIENT);
088aac85 1045 else
9098bbf3
MP
1046 exit_cleanup(ret);
1047
0f5a04e3 1048 return ret;
c627d613 1049}