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