Merge modified --with-rsh patch: we now determine the default
[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
93689aa5
DD
210 if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
211 blocking_io = 1;
e384bfbd 212
93689aa5 213 server_options(args,&argc);
e384bfbd 214
366345fe 215 }
c627d613 216
366345fe 217 args[argc++] = ".";
76076c4b 218
366345fe
AT
219 if (path && *path)
220 args[argc++] = path;
c627d613 221
366345fe 222 args[argc] = NULL;
c627d613 223
366345fe 224 if (verbose > 3) {
9486289c 225 rprintf(FINFO,"cmd=");
366345fe 226 for (i=0;i<argc;i++)
9486289c
AT
227 rprintf(FINFO,"%s ",args[i]);
228 rprintf(FINFO,"\n");
366345fe
AT
229 }
230
231 if (local_server) {
6902ed17
MP
232 if (read_batch)
233 create_flist_from_batch();
366345fe
AT
234 ret = local_child(argc, args, f_in, f_out);
235 } else {
236 ret = piped_child(args,f_in,f_out);
237 }
c627d613 238
366345fe 239 if (dir) free(dir);
82306bf6 240
366345fe 241 return ret;
c627d613
AT
242
243oom:
366345fe
AT
244 out_of_memory("do_cmd");
245 return 0; /* not reached */
c627d613
AT
246}
247
248
249
250
251static char *get_local_name(struct file_list *flist,char *name)
252{
7a6421fa
AT
253 STRUCT_STAT st;
254 extern int orig_umask;
c627d613 255
c95da96a
AT
256 if (verbose > 2)
257 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
258 flist->count, NS(name));
259
260 if (!name)
261 return NULL;
c95da96a 262
1ff5450d
AT
263 if (do_stat(name,&st) == 0) {
264 if (S_ISDIR(st.st_mode)) {
5243c216
AT
265 if (!push_dir(name, 0)) {
266 rprintf(FERROR,"push_dir %s : %s (1)\n",
1ff5450d 267 name,strerror(errno));
65417579 268 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
269 }
270 return NULL;
271 }
272 if (flist->count > 1) {
273 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 274 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
275 }
276 return name;
277 }
278
cec8aa77 279 if (flist->count <= 1)
1ff5450d
AT
280 return name;
281
1ff5450d
AT
282 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
283 rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
65417579 284 exit_cleanup(RERR_FILEIO);
1ff5450d 285 } else {
b536f47e
AT
286 if (verbose > 0)
287 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
288 }
289
5243c216
AT
290 if (!push_dir(name, 0)) {
291 rprintf(FERROR,"push_dir %s : %s (2)\n",
292 name,strerror(errno));
65417579 293 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
294 }
295
296 return NULL;
c627d613
AT
297}
298
299
300
301
9486289c 302static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 303{
7a6421fa
AT
304 int i;
305 struct file_list *flist;
306 char *dir = argv[0];
307 extern int relative_paths;
7a6421fa 308 extern int recurse;
adc19c98 309 extern int remote_version;
c627d613 310
7a6421fa
AT
311 if (verbose > 2)
312 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
c627d613 313
5243c216
AT
314 if (!relative_paths && !push_dir(dir, 0)) {
315 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
65417579 316 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
317 }
318 argc--;
319 argv++;
c627d613 320
7a6421fa
AT
321 if (strcmp(dir,".")) {
322 int l = strlen(dir);
323 if (strcmp(dir,"/") == 0)
324 l = 0;
325 for (i=0;i<argc;i++)
326 argv[i] += l+1;
327 }
c627d613 328
7a6421fa
AT
329 if (argc == 0 && recurse) {
330 argc=1;
331 argv--;
332 argv[0] = ".";
333 }
334
7a6421fa 335 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
336 if (!flist || flist->count == 0) {
337 exit_cleanup(0);
338 }
339
7a6421fa 340 send_files(flist,f_out,f_in);
3d382777 341 io_flush();
7a6421fa 342 report(f_out);
adc19c98
AT
343 if (remote_version >= 24) {
344 /* final goodbye message */
345 read_int(f_in);
346 }
8d9dc9f9 347 io_flush();
7a6421fa 348 exit_cleanup(0);
c627d613
AT
349}
350
351
dc5ddbcc
AT
352static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
353{
d186eb1a
AT
354 int pid;
355 int status=0;
356 int recv_pipe[2];
554e0a8d 357 int error_pipe[2];
d186eb1a 358 extern int preserve_hard_links;
6957ae33
AT
359 extern int delete_after;
360 extern int recurse;
361 extern int delete_mode;
8ada7518 362 extern int remote_version;
dc5ddbcc 363
d186eb1a
AT
364 if (preserve_hard_links)
365 init_hard_links(flist);
dc5ddbcc 366
6957ae33
AT
367 if (!delete_after) {
368 /* I moved this here from recv_files() to prevent a race condition */
369 if (recurse && delete_mode && !local_name && flist->count>0) {
370 delete_files(flist);
371 }
372 }
373
08f15335 374 if (fd_pair(recv_pipe) < 0) {
d186eb1a 375 rprintf(FERROR,"pipe failed in do_recv\n");
65417579 376 exit_cleanup(RERR_SOCKETIO);
d186eb1a 377 }
554e0a8d 378
08f15335 379 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
380 rprintf(FERROR,"error pipe failed in do_recv\n");
381 exit_cleanup(RERR_SOCKETIO);
382 }
c6e7fcb4 383
8d9dc9f9 384 io_flush();
c6e7fcb4 385
d186eb1a 386 if ((pid=do_fork()) == 0) {
e08c9610 387 close(recv_pipe[0]);
554e0a8d 388 close(error_pipe[0]);
e08c9610
AT
389 if (f_in != f_out) close(f_out);
390
554e0a8d
AT
391 /* we can't let two processes write to the socket at one time */
392 io_multiplexing_close();
393
394 /* set place to send errors */
395 set_error_fd(error_pipe[1]);
396
e08c9610 397 recv_files(f_in,flist,local_name,recv_pipe[1]);
3d382777 398 io_flush();
ba5e128d 399 report(f_in);
e08c9610 400
8b35435f
AT
401 write_int(recv_pipe[1],1);
402 close(recv_pipe[1]);
8d9dc9f9 403 io_flush();
4a748188 404 /* finally we go to sleep until our parent kills us
27e3e9c9 405 with a USR2 signal. We sleep for a short time as on
4a748188 406 some OSes a signal won't interrupt a sleep! */
e1bd49d6
MP
407 while (msleep(20))
408 ;
d186eb1a 409 }
dc5ddbcc 410
e08c9610 411 close(recv_pipe[1]);
554e0a8d 412 close(error_pipe[1]);
e08c9610 413 if (f_in != f_out) close(f_in);
e1b3d5c4 414
b3e10ed7
AT
415 io_start_buffering(f_out);
416
554e0a8d
AT
417 io_set_error_fd(error_pipe[0]);
418
e08c9610 419 generate_files(f_out,flist,local_name,recv_pipe[0]);
8d9dc9f9 420
8b35435f
AT
421 read_int(recv_pipe[0]);
422 close(recv_pipe[0]);
8ada7518
AT
423 if (remote_version >= 24) {
424 /* send a final goodbye message */
425 write_int(f_out, -1);
426 }
8d9dc9f9 427 io_flush();
8ada7518 428
8b35435f 429 kill(pid, SIGUSR2);
d79d1c69 430 wait_process(pid, &status);
d186eb1a 431 return status;
dc5ddbcc
AT
432}
433
c627d613 434
9486289c 435static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 436{
7a6421fa
AT
437 int status;
438 struct file_list *flist;
439 char *local_name=NULL;
440 char *dir = NULL;
441 extern int delete_mode;
b33b791e 442 extern int delete_excluded;
7a6421fa 443 extern int am_daemon;
09b7f5db
AT
444 extern int module_id;
445 extern int am_sender;
6902ed17 446 extern int read_batch; /* dw */
6902ed17 447 extern struct file_list *batch_flist; /* dw */
f0fca04e 448
7a6421fa
AT
449 if (verbose > 2)
450 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
09b7f5db
AT
451
452 if (am_daemon && lp_read_only(module_id) && !am_sender) {
453 rprintf(FERROR,"ERROR: module is read only\n");
454 exit_cleanup(RERR_SYNTAX);
455 return;
456 }
457
7a6421fa 458
7a6421fa
AT
459 if (argc > 0) {
460 dir = argv[0];
461 argc--;
462 argv++;
5243c216
AT
463 if (!am_daemon && !push_dir(dir, 0)) {
464 rprintf(FERROR,"push_dir %s : %s (4)\n",
7a6421fa 465 dir,strerror(errno));
65417579 466 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
467 }
468 }
c627d613 469
b33b791e 470 if (delete_mode && !delete_excluded)
7a6421fa 471 recv_exclude_list(f_in);
c627d613 472
6902ed17
MP
473 if (read_batch) /* dw */
474 flist = batch_flist;
475 else
476 flist = recv_file_list(f_in);
4c36a13e
AT
477 if (!flist) {
478 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 479 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
480 }
481
482 if (argc > 0) {
483 if (strcmp(dir,".")) {
484 argv[0] += strlen(dir);
485 if (argv[0][0] == '/') argv[0]++;
486 }
487 local_name = get_local_name(flist,argv[0]);
488 }
c627d613 489
7a6421fa
AT
490 status = do_recv(f_in,f_out,flist,local_name);
491 exit_cleanup(status);
c627d613
AT
492}
493
494
9486289c 495void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 496{
7a6421fa
AT
497 extern int cvs_exclude;
498 extern int am_sender;
ff41a59f 499 extern int remote_version;
6902ed17 500 extern int read_batch; /* dw */
ff41a59f 501
6d7b6081
AT
502 setup_protocol(f_out, f_in);
503
f0359dd0
AT
504 set_nonblocking(f_in);
505 set_nonblocking(f_out);
506
ff41a59f
AT
507 if (remote_version >= 23)
508 io_start_multiplex_out(f_out);
7a6421fa 509
7a6421fa 510 if (am_sender) {
6902ed17
MP
511 if (!read_batch) { /* dw */
512 recv_exclude_list(f_in);
513 if (cvs_exclude)
7a6421fa 514 add_cvs_excludes();
6902ed17 515 }
7a6421fa
AT
516 do_server_sender(f_in, f_out, argc, argv);
517 } else {
518 do_server_recv(f_in, f_out, argc, argv);
519 }
520 exit_cleanup(0);
366345fe
AT
521}
522
0ba48136
MP
523
524/*
525 * This is called once the connection has been negotiated. It is used
526 * for rsyncd, remote-shell, and local connections.
527 */
19b27a48 528int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c
AT
529{
530 struct file_list *flist;
531 int status = 0, status2 = 0;
532 char *local_name = NULL;
7a6421fa 533 extern int am_sender;
ff41a59f 534 extern int remote_version;
19b27a48 535 extern pid_t cleanup_child_pid;
6902ed17
MP
536 extern int write_batch; /* dw */
537 extern int read_batch; /* dw */
538 extern struct file_list *batch_flist; /* dw */
19b27a48
AT
539
540 cleanup_child_pid = pid;
6902ed17
MP
541 if (read_batch)
542 flist = batch_flist; /* dw */
ff41a59f 543
f0359dd0
AT
544 set_nonblocking(f_in);
545 set_nonblocking(f_out);
546
6d7b6081
AT
547 setup_protocol(f_out,f_in);
548
ff41a59f
AT
549 if (remote_version >= 23)
550 io_start_multiplex_in(f_in);
9486289c
AT
551
552 if (am_sender) {
7a6421fa
AT
553 extern int cvs_exclude;
554 extern int delete_mode;
b33b791e 555 extern int delete_excluded;
9486289c
AT
556 if (cvs_exclude)
557 add_cvs_excludes();
b33b791e 558 if (delete_mode && !delete_excluded)
9486289c 559 send_exclude_list(f_out);
6902ed17
MP
560 if (!read_batch) /* dw -- don't write to pipe */
561 flist = send_file_list(f_out,argc,argv);
9486289c
AT
562 if (verbose > 3)
563 rprintf(FINFO,"file list sent\n");
e1b3d5c4 564
9486289c 565 send_files(flist,f_out,f_in);
6c65e146
AT
566 if (remote_version >= 24) {
567 /* final goodbye message */
568 read_int(f_in);
569 }
9486289c
AT
570 if (pid != -1) {
571 if (verbose > 3)
08a740ff 572 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
8d9dc9f9 573 io_flush();
d79d1c69 574 wait_process(pid, &status);
9486289c 575 }
3d382777 576 report(-1);
9486289c
AT
577 exit_cleanup(status);
578 }
f7632fc6 579
27e3e9c9
AT
580 if (argc == 0) {
581 extern int list_only;
582 list_only = 1;
583 }
9486289c 584
6902ed17
MP
585 if (!write_batch) /* dw */
586 send_exclude_list(f_out);
9486289c
AT
587
588 flist = recv_file_list(f_in);
589 if (!flist || flist->count == 0) {
796d484b
MP
590 rprintf(FINFO, "client: nothing to do: "
591 "perhaps you need to specify some filenames or "
592 "the --recursive option?\n");
9486289c
AT
593 exit_cleanup(0);
594 }
595
596 local_name = get_local_name(flist,argv[0]);
597
598 status2 = do_recv(f_in,f_out,flist,local_name);
599
9486289c 600 if (pid != -1) {
8d9dc9f9 601 if (verbose > 3)
08a740ff 602 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
8d9dc9f9 603 io_flush();
d79d1c69 604 wait_process(pid, &status);
9486289c
AT
605 }
606
ff81e809 607 return MAX(status, status2);
9486289c
AT
608}
609
ca6c93f8
AT
610static char *find_colon(char *s)
611{
612 char *p, *p2;
613
614 p = strchr(s,':');
615 if (!p) return NULL;
616
617 /* now check to see if there is a / in the string before the : - if there is then
618 discard the colon on the assumption that the : is part of a filename */
619 p2 = strchr(s,'/');
620 if (p2 && p2 < p) return NULL;
621
622 return p;
623}
9486289c 624
0ba48136 625
7169bb4a
MP
626static int copy_argv (char *argv[])
627{
628 int i;
629
630 for (i = 0; argv[i]; i++) {
631 if (!(argv[i] = strdup(argv[i]))) {
632 rprintf (FERROR, "out of memory at %s(%d)\n",
633 __FILE__, __LINE__);
634 return RERR_MALLOC;
635 }
636 }
637
638 return 0;
639}
640
641
0ba48136
MP
642/*
643 * Start a client for either type of remote connection. Work out
644 * whether the arguments request a remote shell or rsyncd connection,
645 * and call the appropriate connection function, then run_client.
646 */
fc8a6b97 647static int start_client(int argc, char *argv[])
5d6bcd44
AT
648{
649 char *p;
650 char *shell_machine = NULL;
651 char *shell_path = NULL;
652 char *shell_user = NULL;
19b27a48
AT
653 int ret;
654 pid_t pid;
5d6bcd44 655 int f_in,f_out;
7a6421fa
AT
656 extern int local_server;
657 extern int am_sender;
658 extern char *shell_cmd;
2acf81eb 659 extern int rsync_port;
a1a440c2 660 extern int whole_file;
6902ed17 661 extern int read_batch;
7169bb4a
MP
662 int rc;
663
664 /* Don't clobber argv[] so that ps(1) can still show the right
665 command line. */
666 if ((rc = copy_argv (argv)))
667 return rc;
5d6bcd44 668
7169bb4a 669 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
f7632fc6
AT
670 char *host, *path;
671
7169bb4a 672 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
673 p = strchr(host,'/');
674 if (p) {
675 *p = 0;
676 path = p+1;
677 } else {
678 path="";
679 }
2acf81eb
DD
680 p = strchr(host,':');
681 if (p) {
682 rsync_port = atoi(p+1);
683 *p = 0;
684 }
f7632fc6
AT
685 return start_socket_client(host, path, argc-1, argv+1);
686 }
687
6902ed17
MP
688 if (!read_batch) { /* dw */
689 p = find_colon(argv[0]);
5d6bcd44
AT
690
691 if (p) {
9486289c
AT
692 if (p[1] == ':') {
693 *p = 0;
7169bb4a 694 return start_socket_client(argv[0], p+2, argc-1, argv+1);
9486289c 695 }
3591c066 696
f7632fc6 697 if (argc < 1) {
3591c066 698 usage(FERROR);
65417579 699 exit_cleanup(RERR_SYNTAX);
3591c066
AT
700 }
701
5d6bcd44
AT
702 am_sender = 0;
703 *p = 0;
7169bb4a 704 shell_machine = argv[0];
5d6bcd44
AT
705 shell_path = p+1;
706 argc--;
707 argv++;
708 } else {
709 am_sender = 1;
9486289c 710
ca6c93f8 711 p = find_colon(argv[argc-1]);
5d6bcd44
AT
712 if (!p) {
713 local_server = 1;
a1a440c2 714 /* disable "rsync algorithm" when both sides local */
93689aa5
DD
715 if (whole_file == -1)
716 whole_file = 1;
9486289c
AT
717 } else if (p[1] == ':') {
718 *p = 0;
719 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
5d6bcd44 720 }
3591c066
AT
721
722 if (argc < 2) {
723 usage(FERROR);
65417579 724 exit_cleanup(RERR_SYNTAX);
3591c066 725 }
9486289c 726
5d6bcd44
AT
727 if (local_server) {
728 shell_machine = NULL;
729 shell_path = argv[argc-1];
730 } else {
731 *p = 0;
732 shell_machine = argv[argc-1];
733 shell_path = p+1;
734 }
735 argc--;
736 }
6902ed17
MP
737 } else {
738 am_sender = 1; /* dw */
739 local_server = 1; /* dw */
740 shell_path = argv[argc-1]; /* dw */
741 }
742
5d6bcd44
AT
743 if (shell_machine) {
744 p = strchr(shell_machine,'@');
745 if (p) {
746 *p = 0;
747 shell_user = shell_machine;
748 shell_machine = p+1;
749 }
750 }
751
752 if (verbose > 3) {
9486289c 753 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
754 shell_cmd?shell_cmd:"",
755 shell_machine?shell_machine:"",
756 shell_user?shell_user:"",
757 shell_path?shell_path:"");
758 }
759
f7632fc6 760 if (!am_sender && argc > 1) {
5d6bcd44 761 usage(FERROR);
65417579 762 exit_cleanup(RERR_SYNTAX);
5d6bcd44 763 }
27e3e9c9
AT
764
765 if (argc == 0 && !am_sender) {
766 extern int list_only;
767 list_only = 1;
768 }
5d6bcd44
AT
769
770 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
771
fc8a6b97
AT
772 ret = client_run(f_in, f_out, pid, argc, argv);
773
774 fflush(stdout);
775 fflush(stderr);
776
777 return ret;
5d6bcd44
AT
778}
779
366345fe 780
6e4fb64e 781static RETSIGTYPE sigusr1_handler(int val) {
65417579 782 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
783}
784
8b35435f 785static RETSIGTYPE sigusr2_handler(int val) {
ff81e809 786 extern int log_got_error;
19b27a48 787 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
788 _exit(0);
789}
790
19b27a48 791static RETSIGTYPE sigchld_handler(int val) {
029c1713
AT
792#ifdef WNOHANG
793 while (waitpid(-1, NULL, WNOHANG) > 0) ;
794#endif
19b27a48
AT
795}
796
5d6bcd44 797int main(int argc,char *argv[])
7a6421fa
AT
798{
799 extern int am_root;
800 extern int orig_umask;
801 extern int dry_run;
802 extern int am_daemon;
803 extern int am_server;
ff81e809 804 int ret;
6902ed17
MP
805 extern int read_batch; /* dw */
806 extern int write_batch; /* dw */
807 extern char *batch_ext; /* dw */
6902ed17 808 int orig_argc; /* dw */
76f79ba7 809 char **orig_argv;
6902ed17
MP
810
811 orig_argc = argc; /* dw */
76f79ba7 812 orig_argv = argv;
5d6bcd44 813
7a6421fa 814 signal(SIGUSR1, sigusr1_handler);
8b35435f 815 signal(SIGUSR2, sigusr2_handler);
19b27a48 816 signal(SIGCHLD, sigchld_handler);
5d6bcd44 817
7a6421fa
AT
818 starttime = time(NULL);
819 am_root = (getuid() == 0);
c627d613 820
a800434a
AT
821 memset(&stats, 0, sizeof(stats));
822
df5e03da
AT
823 if (argc < 2) {
824 usage(FERROR);
65417579 825 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
826 }
827
7a6421fa
AT
828 /* we set a 0 umask so that correct file permissions can be
829 carried across */
830 orig_umask = (int)umask(0);
5d6bcd44 831
50135767 832 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
305ab133
MP
833 /* FIXME: We ought to call the same error-handling
834 * code here, rather than relying on getopt. */
50135767 835 option_error();
65417579 836 exit_cleanup(RERR_SYNTAX);
b11ed3b1 837 }
5d6bcd44 838
7a6421fa
AT
839 signal(SIGINT,SIGNAL_CAST sig_int);
840 signal(SIGPIPE,SIGNAL_CAST sig_int);
841 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 842 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 843
c226b7c2
DD
844 /* Initialize push_dir here because on some old systems getcwd
845 (implemented by forking "pwd" and reading its output) doesn't
846 work when there are other child processes. Also, on all systems
847 that implement getcwd that way "pwd" can't be found after chroot. */
848 push_dir(NULL,0);
849
6902ed17
MP
850 if (write_batch) { /* dw */
851 create_batch_file_ext();
76f79ba7 852 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
853 }
854
855 if (read_batch) { /* dw */
856 set_batch_file_ext(batch_ext);
857 }
858
7a6421fa
AT
859 if (am_daemon) {
860 return daemon_main();
861 }
f0fca04e 862
08ac228f
AT
863 if (argc < 1) {
864 usage(FERROR);
65417579 865 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
866 }
867
7a6421fa
AT
868 if (dry_run)
869 verbose = MAX(verbose,1);
c627d613 870
cbbe4892 871#ifndef SUPPORT_LINKS
7a6421fa
AT
872 if (!am_server && preserve_links) {
873 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 874 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 875 }
cbbe4892
AT
876#endif
877
7a6421fa 878 if (am_server) {
f0359dd0
AT
879 set_nonblocking(STDIN_FILENO);
880 set_nonblocking(STDOUT_FILENO);
7a6421fa
AT
881 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
882 }
c627d613 883
ff81e809
AT
884 ret = start_client(argc, argv);
885 exit_cleanup(ret);
886 return ret;
c627d613 887}
82306bf6 888