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