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