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