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