Document more recent changes.
[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 {
690 path="";
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) {
6902ed17 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
ca6c93f8 728 p = find_colon(argv[argc-1]);
5d6bcd44
AT
729 if (!p) {
730 local_server = 1;
75aeac44 731 } else if (p[1] == ':') { /* double colon */
9486289c 732 *p = 0;
75aeac44
WD
733 if (!shell_cmd) {
734 return start_socket_client(argv[argc-1], p+2,
735 argc-1, argv);
736 }
737 p++;
738 daemon_over_rsh = 1;
5d6bcd44 739 }
3591c066
AT
740
741 if (argc < 2) {
742 usage(FERROR);
65417579 743 exit_cleanup(RERR_SYNTAX);
3591c066 744 }
9486289c 745
5d6bcd44
AT
746 if (local_server) {
747 shell_machine = NULL;
748 shell_path = argv[argc-1];
749 } else {
750 *p = 0;
751 shell_machine = argv[argc-1];
752 shell_path = p+1;
753 }
754 argc--;
755 }
6902ed17 756 } else {
088aac85
DD
757 am_sender = 1;
758 local_server = 1;
759 shell_path = argv[argc-1];
6902ed17
MP
760 }
761
5d6bcd44
AT
762 if (shell_machine) {
763 p = strchr(shell_machine,'@');
764 if (p) {
765 *p = 0;
766 shell_user = shell_machine;
767 shell_machine = p+1;
768 }
769 }
770
771 if (verbose > 3) {
9486289c 772 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
773 shell_cmd?shell_cmd:"",
774 shell_machine?shell_machine:"",
775 shell_user?shell_user:"",
776 shell_path?shell_path:"");
777 }
778
f7632fc6 779 if (!am_sender && argc > 1) {
5d6bcd44 780 usage(FERROR);
65417579 781 exit_cleanup(RERR_SYNTAX);
5d6bcd44 782 }
27e3e9c9
AT
783
784 if (argc == 0 && !am_sender) {
785 extern int list_only;
786 list_only = 1;
787 }
5d6bcd44 788
75aeac44
WD
789 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
790 &f_in,&f_out);
791
792 /* if we're running an rsync server on the remote host over a
793 remote shell command, we need to do the RSYNCD protocol first */
794 if (daemon_over_rsh) {
795 int tmpret;
796 tmpret = start_inband_exchange(shell_user, shell_path,
797 f_in, f_out, argc);
798 if (tmpret < 0)
799 return tmpret;
800 }
801
fc8a6b97
AT
802 ret = client_run(f_in, f_out, pid, argc, argv);
803
804 fflush(stdout);
805 fflush(stderr);
806
807 return ret;
5d6bcd44
AT
808}
809
366345fe 810
0f0ea7f7 811static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
65417579 812 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
813}
814
0f0ea7f7 815static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
ff81e809 816 extern int log_got_error;
19b27a48 817 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
818 _exit(0);
819}
820
0f0ea7f7 821static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
029c1713
AT
822#ifdef WNOHANG
823 while (waitpid(-1, NULL, WNOHANG) > 0) ;
824#endif
19b27a48
AT
825}
826
c0531332
MP
827
828/**
829 * This routine catches signals and tries to send them to gdb.
830 *
831 * Because it's called from inside a signal handler it ought not to
832 * use too many library routines.
833 *
834 * @todo Perhaps use "screen -X" instead/as well, to help people
835 * debugging without easy access to X. Perhaps use an environment
836 * variable, or just call a script?
837 *
838 * @todo The /proc/ magic probably only works on Linux (and
839 * Solaris?) Can we be more portable?
840 **/
841#ifdef MAINTAINER_MODE
4fdc39dd
MP
842const char *get_panic_action(void)
843{
844 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
845
846 if (cmd_fmt)
847 return cmd_fmt;
848 else
849 return "xterm -display :0 -T Panic -n Panic "
850 "-e gdb /proc/%d/exe %d";
851}
852
853
9fb3f7a9
MP
854/**
855 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
856 *
857 * This signal handler is only installed if we were configured with
858 * --enable-maintainer-mode. Perhaps it should always be on and we
859 * should just look at the environment variable, but I'm a bit leery
860 * of a signal sending us into a busy loop.
861 **/
c0531332
MP
862static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
863{
864 char cmd_buf[300];
865 int ret;
4fdc39dd
MP
866
867 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
868 getpid(), getpid());
869
870 /* Unless we failed to execute gdb, we allow the process to
871 * continue. I'm not sure if that's right. */
872 ret = system(cmd_buf);
873 if (ret)
874 _exit(ret);
875}
876#endif
877
878
5d6bcd44 879int main(int argc,char *argv[])
7a6421fa
AT
880{
881 extern int am_root;
882 extern int orig_umask;
883 extern int dry_run;
884 extern int am_daemon;
885 extern int am_server;
ff81e809 886 int ret;
088aac85
DD
887 extern int write_batch;
888 int orig_argc;
76f79ba7 889 char **orig_argv;
6902ed17 890
088aac85 891 orig_argc = argc;
76f79ba7 892 orig_argv = argv;
5d6bcd44 893
7a6421fa 894 signal(SIGUSR1, sigusr1_handler);
8b35435f 895 signal(SIGUSR2, sigusr2_handler);
19b27a48 896 signal(SIGCHLD, sigchld_handler);
c0531332
MP
897#ifdef MAINTAINER_MODE
898 signal(SIGSEGV, rsync_panic_handler);
899 signal(SIGFPE, rsync_panic_handler);
900 signal(SIGABRT, rsync_panic_handler);
901 signal(SIGBUS, rsync_panic_handler);
902#endif /* def MAINTAINER_MODE */
5d6bcd44 903
7a6421fa
AT
904 starttime = time(NULL);
905 am_root = (getuid() == 0);
c627d613 906
a800434a
AT
907 memset(&stats, 0, sizeof(stats));
908
df5e03da
AT
909 if (argc < 2) {
910 usage(FERROR);
65417579 911 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
912 }
913
7a6421fa
AT
914 /* we set a 0 umask so that correct file permissions can be
915 carried across */
916 orig_umask = (int)umask(0);
5d6bcd44 917
50135767 918 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
305ab133
MP
919 /* FIXME: We ought to call the same error-handling
920 * code here, rather than relying on getopt. */
50135767 921 option_error();
65417579 922 exit_cleanup(RERR_SYNTAX);
b11ed3b1 923 }
5d6bcd44 924
7a6421fa 925 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 926 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 927 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 928
34758d5c
MP
929 /* Ignore SIGPIPE; we consistently check error codes and will
930 * see the EPIPE. */
931 signal(SIGPIPE, SIG_IGN);
932
c226b7c2
DD
933 /* Initialize push_dir here because on some old systems getcwd
934 (implemented by forking "pwd" and reading its output) doesn't
935 work when there are other child processes. Also, on all systems
936 that implement getcwd that way "pwd" can't be found after chroot. */
937 push_dir(NULL,0);
938
088aac85 939 if (write_batch && !am_server) {
76f79ba7 940 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
941 }
942
75aeac44 943 if (am_daemon && !am_server)
7a6421fa 944 return daemon_main();
f0fca04e 945
08ac228f
AT
946 if (argc < 1) {
947 usage(FERROR);
65417579 948 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
949 }
950
7a6421fa
AT
951 if (dry_run)
952 verbose = MAX(verbose,1);
c627d613 953
cbbe4892 954#ifndef SUPPORT_LINKS
7a6421fa
AT
955 if (!am_server && preserve_links) {
956 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 957 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 958 }
cbbe4892
AT
959#endif
960
7a6421fa 961 if (am_server) {
f0359dd0
AT
962 set_nonblocking(STDIN_FILENO);
963 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
964 if (am_daemon)
965 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
966 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
967 }
c627d613 968
ff81e809 969 ret = start_client(argc, argv);
088aac85 970 if (ret == -1)
9098bbf3 971 exit_cleanup(RERR_STARTCLIENT);
088aac85 972 else
9098bbf3
MP
973 exit_cleanup(ret);
974
975 exit(ret);
976 /* NOTREACHED */
c627d613 977}