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