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