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