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