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