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