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