Use MY_GID() instead of getgid().
[rsync/rsync.git] / main.c
CommitLineData
0ba48136 1/* -*- c-file-style: "linux" -*-
d9c7edf6 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>
d9c7edf6 6
c627d613
AT
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.
d9c7edf6 11
c627d613
AT
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.
d9c7edf6 16
c627d613
AT
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;
32eda096 27extern int am_root;
d9c7edf6
WD
28extern int am_server;
29extern int am_sender;
b695f242 30extern int am_generator;
d9c7edf6 31extern int am_daemon;
7a6421fa 32extern int verbose;
32eda096
WD
33extern int blocking_io;
34extern int cvs_exclude;
35extern int delete_mode;
36extern int delete_excluded;
37extern int delete_after;
38extern int daemon_over_rsh;
39extern int do_stats;
40extern int dry_run;
41extern int list_only;
42extern int local_server;
43extern int log_got_error;
44extern int module_id;
45extern int orig_umask;
46extern int preserve_hard_links;
d04e9c51 47extern int protocol_version;
32eda096
WD
48extern int recurse;
49extern int relative_paths;
50extern int rsync_port;
51extern int read_batch;
52extern int write_batch;
53extern int filesfrom_fd;
54extern pid_t cleanup_child_pid;
55extern char *files_from;
56extern char *remote_filesfrom_file;
57extern char *rsync_path;
58extern char *shell_cmd;
59extern struct file_list *batch_flist;
c627d613 60
b695f242 61
ee7118a8
DD
62/* there's probably never more than at most 2 outstanding child processes,
63 * but set it higher just in case.
64 */
65#define MAXCHILDPROCS 5
66
67struct pid_status {
68 pid_t pid;
69 int status;
70} pid_stat_table[MAXCHILDPROCS];
71
e5a2b854 72static void show_malloc_stats(void);
82980a23
AT
73
74/****************************************************************************
75wait for a process to exit, calling io_flush while waiting
76****************************************************************************/
77void wait_process(pid_t pid, int *status)
78{
ee7118a8
DD
79 pid_t waited_pid;
80 int cnt;
81
82 while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
a24c6870 83 msleep(20);
f1e3656e 84 io_flush(FULL_FLUSH);
82980a23 85 }
d9c7edf6 86
ee7118a8
DD
87 if ((waited_pid == -1) && (errno == ECHILD)) {
88 /* status of requested child no longer available.
89 * check to see if it was processed by the sigchld_handler.
90 */
91 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
92 if (pid == pid_stat_table[cnt].pid) {
93 *status = pid_stat_table[cnt].status;
94 pid_stat_table[cnt].pid = 0;
95 break;
96 }
97 }
98 }
99
d9c7edf6
WD
100 /* TODO: If the child exited on a signal, then log an
101 * appropriate error message. Perhaps we should also accept a
102 * message describing the purpose of the child. Also indicate
103 * this to the caller so that thhey know something went
104 * wrong. */
82980a23
AT
105 *status = WEXITSTATUS(*status);
106}
107
c627d613
AT
108static void report(int f)
109{
7a6421fa 110 time_t t = time(NULL);
17d31b38 111 int send_stats;
7a6421fa 112
7bb7058e 113 if (do_stats && verbose > 1) {
5c15e29f 114 /* These come out from every process */
7bb7058e 115 show_malloc_stats();
86943126 116 show_flist_stats();
5c15e29f
MP
117 }
118
248fbb8c 119 if (am_daemon) {
a9766ef1 120 log_exit(0, __FILE__, __LINE__);
7b372642 121 if (f == -1 || !am_sender) return;
248fbb8c
AT
122 }
123
d04e9c51 124 send_stats = verbose || protocol_version >= 20;
e19452a9 125 if (am_server) {
17d31b38 126 if (am_sender && send_stats) {
23c5aef1
DD
127 int64 w;
128 /* store total_written in a temporary
d9c7edf6 129 * because write_longint changes it */
23c5aef1 130 w = stats.total_written;
e19452a9 131 write_longint(f,stats.total_read);
23c5aef1 132 write_longint(f,w);
e19452a9
DD
133 write_longint(f,stats.total_size);
134 }
7a6421fa
AT
135 return;
136 }
e19452a9
DD
137
138 /* this is the client */
d9c7edf6 139
17d31b38 140 if (!am_sender && send_stats) {
23c5aef1 141 int64 r;
a800434a 142 stats.total_written = read_longint(f);
23c5aef1
DD
143 /* store total_read in a temporary, read_longint changes it */
144 r = read_longint(f);
a800434a 145 stats.total_size = read_longint(f);
23c5aef1 146 stats.total_read = r;
a800434a
AT
147 }
148
149 if (do_stats) {
17d31b38 150 if (!am_sender && !send_stats) {
d9c7edf6
WD
151 /* missing the bytes written by the generator */
152 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
153 rprintf(FINFO, "Use --stats -v to show stats\n");
154 return;
17d31b38 155 }
1f658d42 156 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
d9c7edf6
WD
157 rprintf(FINFO,"Number of files transferred: %d\n",
158 stats.num_transferred_files);
159 rprintf(FINFO,"Total file size: %.0f bytes\n",
160 (double)stats.total_size);
161 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
162 (double)stats.total_transferred_size);
163 rprintf(FINFO,"Literal data: %.0f bytes\n",
164 (double)stats.literal_data);
165 rprintf(FINFO,"Matched data: %.0f bytes\n",
166 (double)stats.matched_data);
1f658d42 167 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
d9c7edf6
WD
168 rprintf(FINFO,"Total bytes written: %.0f\n",
169 (double)stats.total_written);
577ab12c 170 rprintf(FINFO,"Total bytes read: %.0f\n",
d9c7edf6 171 (double)stats.total_read);
7a6421fa 172 }
d9c7edf6 173
e19452a9 174 if (verbose || do_stats) {
577ab12c 175 rprintf(FINFO,"\nwrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
d9c7edf6
WD
176 (double)stats.total_written,
177 (double)stats.total_read,
178 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
e19452a9 179 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
d9c7edf6
WD
180 (double)stats.total_size,
181 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
e19452a9 182 }
fc8a6b97
AT
183
184 fflush(stdout);
185 fflush(stderr);
c627d613
AT
186}
187
188
e5a2b854
MP
189/**
190 * If our C library can get malloc statistics, then show them to FINFO
191 **/
192static void show_malloc_stats(void)
193{
194#ifdef HAVE_MALLINFO
195 struct mallinfo mi;
196
197 mi = mallinfo();
198
ce672562 199 rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
5c15e29f
MP
200 getpid(),
201 am_server ? "server " : "",
202 am_daemon ? "daemon " : "",
b695f242 203 who_am_i());
e5a2b854
MP
204 rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
205 rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
206 rprintf(FINFO, " smblks: %10d\n", mi.smblks);
207 rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
208 rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
209 rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
210 rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
211 rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
212 rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
213 rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
214#endif /* HAVE_MALLINFO */
215}
216
217
0882faa2 218/* Start the remote shell. cmd may be NULL to use the default. */
19b27a48 219static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
c627d613 220{
366345fe 221 char *args[100];
19b27a48
AT
222 int i,argc=0;
223 pid_t ret;
366345fe 224 char *tok,*dir=NULL;
bb4aa89c 225 int dash_l_set = 0;
366345fe 226
088aac85 227 if (!read_batch && !local_server) {
9af87151 228 char *rsh_env = getenv(RSYNC_RSH_ENV);
366345fe 229 if (!cmd)
9af87151 230 cmd = rsh_env;
366345fe
AT
231 if (!cmd)
232 cmd = RSYNC_RSH;
233 cmd = strdup(cmd);
d9c7edf6 234 if (!cmd)
366345fe
AT
235 goto oom;
236
237 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
238 args[argc++] = tok;
239 }
c627d613 240
d9c7edf6 241 /* check to see if we've already been given '-l user' in
9af87151 242 * the remote-shell command */
bb4aa89c
WD
243 for (i = 0; i < argc-1; i++) {
244 if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
245 dash_l_set = 1;
246 }
247
7b8356d0 248#if HAVE_REMSH
366345fe
AT
249 /* remsh (on HPUX) takes the arguments the other way around */
250 args[argc++] = machine;
bb4aa89c 251 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
252 args[argc++] = "-l";
253 args[argc++] = user;
254 }
7b8356d0 255#else
bb4aa89c 256 if (user && !(daemon_over_rsh && dash_l_set)) {
366345fe
AT
257 args[argc++] = "-l";
258 args[argc++] = user;
259 }
260 args[argc++] = machine;
7b8356d0 261#endif
c627d613 262
366345fe 263 args[argc++] = rsync_path;
c627d613 264
9af87151 265 if (blocking_io < 0) {
90e22f4b
WD
266 char *cp;
267 if ((cp = strrchr(cmd, '/')) != NULL)
268 cp++;
269 else
270 cp = cmd;
271 if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
272 blocking_io = 1;
66b71163 273 }
e384bfbd 274
93689aa5 275 server_options(args,&argc);
366345fe 276 }
c627d613 277
366345fe 278 args[argc++] = ".";
76076c4b 279
d9c7edf6 280 if (!daemon_over_rsh && path && *path)
366345fe 281 args[argc++] = path;
c627d613 282
366345fe 283 args[argc] = NULL;
c627d613 284
366345fe 285 if (verbose > 3) {
9486289c 286 rprintf(FINFO,"cmd=");
366345fe 287 for (i=0;i<argc;i++)
9486289c
AT
288 rprintf(FINFO,"%s ",args[i]);
289 rprintf(FINFO,"\n");
366345fe
AT
290 }
291
292 if (local_server) {
6902ed17 293 if (read_batch)
d9c7edf6 294 create_flist_from_batch(); /* sets batch_flist */
25d34a5c 295 ret = local_child(argc, args, f_in, f_out, child_main);
366345fe
AT
296 } else {
297 ret = piped_child(args,f_in,f_out);
298 }
c627d613 299
366345fe 300 if (dir) free(dir);
82306bf6 301
366345fe 302 return ret;
c627d613
AT
303
304oom:
366345fe
AT
305 out_of_memory("do_cmd");
306 return 0; /* not reached */
c627d613
AT
307}
308
309
c627d613
AT
310static char *get_local_name(struct file_list *flist,char *name)
311{
7a6421fa 312 STRUCT_STAT st;
87cc45e1 313 int e;
c627d613 314
c95da96a 315 if (verbose > 2)
d9c7edf6 316 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
317 flist->count, NS(name));
318
d9c7edf6 319 if (!name)
1f0610ef 320 return NULL;
c95da96a 321
1ff5450d
AT
322 if (do_stat(name,&st) == 0) {
323 if (S_ISDIR(st.st_mode)) {
59187666 324 if (!push_dir(name)) {
ea42541f
WD
325 rprintf(FERROR, "push_dir %s failed: %s (1)\n",
326 full_fname(name), strerror(errno));
65417579 327 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
328 }
329 return NULL;
330 }
331 if (flist->count > 1) {
332 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 333 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
334 }
335 return name;
336 }
337
87cc45e1 338 if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
1ff5450d
AT
339 return name;
340
1ff5450d 341 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
ea42541f
WD
342 rprintf(FERROR, "mkdir %s failed: %s\n",
343 full_fname(name), strerror(errno));
65417579 344 exit_cleanup(RERR_FILEIO);
1ff5450d 345 } else {
b536f47e
AT
346 if (verbose > 0)
347 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
348 }
349
59187666 350 if (!push_dir(name)) {
ea42541f
WD
351 rprintf(FERROR, "push_dir %s failed: %s (2)\n",
352 full_fname(name), strerror(errno));
65417579 353 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
354 }
355
356 return NULL;
c627d613
AT
357}
358
359
9486289c 360static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 361{
7a6421fa
AT
362 int i;
363 struct file_list *flist;
364 char *dir = argv[0];
c627d613 365
45e08edb
WD
366 if (verbose > 2) {
367 rprintf(FINFO, "server_sender starting pid=%ld\n",
368 (long)getpid());
369 }
d9c7edf6 370
59187666 371 if (!relative_paths && !push_dir(dir)) {
ea42541f
WD
372 rprintf(FERROR, "push_dir %s failed: %s (3)\n",
373 full_fname(dir), strerror(errno));
65417579 374 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
375 }
376 argc--;
377 argv++;
d9c7edf6 378
7a6421fa
AT
379 if (strcmp(dir,".")) {
380 int l = strlen(dir);
d9c7edf6 381 if (strcmp(dir,"/") == 0)
7a6421fa
AT
382 l = 0;
383 for (i=0;i<argc;i++)
384 argv[i] += l+1;
385 }
c627d613 386
7a6421fa
AT
387 if (argc == 0 && recurse) {
388 argc=1;
389 argv--;
390 argv[0] = ".";
391 }
d9c7edf6 392
7a6421fa 393 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
394 if (!flist || flist->count == 0) {
395 exit_cleanup(0);
396 }
397
76c21947
WD
398 io_start_buffering_in(f_in);
399 io_start_buffering_out(f_out);
7a6421fa 400 send_files(flist,f_out,f_in);
f1e3656e 401 io_flush(FULL_FLUSH);
7a6421fa 402 report(f_out);
d04e9c51 403 if (protocol_version >= 24) {
d9c7edf6 404 /* final goodbye message */
64c3523a
WD
405 read_int(f_in);
406 }
f1e3656e 407 io_flush(FULL_FLUSH);
7a6421fa 408 exit_cleanup(0);
c627d613
AT
409}
410
411
dc5ddbcc
AT
412static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
413{
d186eb1a
AT
414 int pid;
415 int status=0;
554e0a8d 416 int error_pipe[2];
dc5ddbcc 417
d186eb1a
AT
418 if (preserve_hard_links)
419 init_hard_links(flist);
dc5ddbcc 420
6957ae33
AT
421 if (!delete_after) {
422 /* I moved this here from recv_files() to prevent a race condition */
423 if (recurse && delete_mode && !local_name && flist->count>0) {
424 delete_files(flist);
425 }
426 }
427
08f15335 428 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
429 rprintf(FERROR,"error pipe failed in do_recv\n");
430 exit_cleanup(RERR_SOCKETIO);
431 }
d9c7edf6 432
f1e3656e 433 io_flush(NORMAL_FLUSH);
c6e7fcb4 434
d186eb1a 435 if ((pid=do_fork()) == 0) {
554e0a8d 436 close(error_pipe[0]);
e08c9610
AT
437 if (f_in != f_out) close(f_out);
438
554e0a8d
AT
439 /* we can't let two processes write to the socket at one time */
440 io_multiplexing_close();
441
442 /* set place to send errors */
f1e3656e 443 set_msg_fd_out(error_pipe[1]);
554e0a8d 444
f1e3656e
WD
445 recv_files(f_in,flist,local_name);
446 io_flush(FULL_FLUSH);
ba5e128d 447 report(f_in);
e08c9610 448
f1e3656e
WD
449 send_msg(MSG_DONE, "", 0);
450 io_flush(FULL_FLUSH);
4a748188 451 /* finally we go to sleep until our parent kills us
9af87151
WD
452 * with a USR2 signal. We sleep for a short time as on
453 * some OSes a signal won't interrupt a sleep! */
f1e3656e
WD
454 while (1)
455 msleep(20);
d186eb1a 456 }
dc5ddbcc 457
b695f242
WD
458 am_generator = 1;
459
554e0a8d 460 close(error_pipe[1]);
e08c9610 461 if (f_in != f_out) close(f_in);
e1b3d5c4 462
76c21947 463 io_start_buffering_out(f_out);
b3e10ed7 464
f1e3656e 465 set_msg_fd_in(error_pipe[0]);
554e0a8d 466
f1e3656e 467 generate_files(f_out, flist, local_name);
8d9dc9f9 468
40da9042 469 get_redo_num(); /* Read final MSG_DONE and any prior messages. */
f1e3656e 470 io_flush(FULL_FLUSH);
d04e9c51 471 if (protocol_version >= 24) {
8ada7518
AT
472 /* send a final goodbye message */
473 write_int(f_out, -1);
474 }
f1e3656e 475 io_flush(FULL_FLUSH);
8ada7518 476
f1e3656e 477 set_msg_fd_in(-1);
089a2435 478 kill(pid, SIGUSR2);
d79d1c69 479 wait_process(pid, &status);
d186eb1a 480 return status;
dc5ddbcc
AT
481}
482
c627d613 483
9486289c 484static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 485{
7a6421fa
AT
486 int status;
487 struct file_list *flist;
488 char *local_name=NULL;
489 char *dir = NULL;
f0fca04e 490
45e08edb
WD
491 if (verbose > 2) {
492 rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
493 argc, (long)getpid());
494 }
09b7f5db
AT
495
496 if (am_daemon && lp_read_only(module_id) && !am_sender) {
497 rprintf(FERROR,"ERROR: module is read only\n");
498 exit_cleanup(RERR_SYNTAX);
499 return;
500 }
501
d9c7edf6 502
7a6421fa
AT
503 if (argc > 0) {
504 dir = argv[0];
505 argc--;
506 argv++;
59187666 507 if (!am_daemon && !push_dir(dir)) {
ea42541f
WD
508 rprintf(FERROR, "push_dir %s failed: %s (4)\n",
509 full_fname(dir), strerror(errno));
65417579 510 exit_cleanup(RERR_FILESELECT);
d9c7edf6 511 }
7a6421fa 512 }
c627d613 513
76c21947 514 io_start_buffering_in(f_in);
b33b791e 515 if (delete_mode && !delete_excluded)
7a6421fa 516 recv_exclude_list(f_in);
c627d613 517
7c2a9e76
WD
518 if (filesfrom_fd >= 0) {
519 /* We're receiving the file info from the sender, so we need
520 * the IO routines to automatically write out the names onto
521 * our f_out socket as we read the list info from the sender.
522 * This avoids both deadlock and extra delays/buffers. */
523 io_set_filesfrom_fds(filesfrom_fd, f_out);
524 filesfrom_fd = -1;
525 }
526
088aac85 527 if (read_batch)
d9c7edf6 528 flist = batch_flist;
6902ed17 529 else
d9c7edf6 530 flist = recv_file_list(f_in);
4c36a13e
AT
531 if (!flist) {
532 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 533 exit_cleanup(RERR_FILESELECT);
7a6421fa 534 }
d9c7edf6
WD
535
536 if (argc > 0) {
7a6421fa
AT
537 if (strcmp(dir,".")) {
538 argv[0] += strlen(dir);
539 if (argv[0][0] == '/') argv[0]++;
540 }
541 local_name = get_local_name(flist,argv[0]);
542 }
c627d613 543
7a6421fa
AT
544 status = do_recv(f_in,f_out,flist,local_name);
545 exit_cleanup(status);
c627d613
AT
546}
547
548
734a94a2 549int child_main(int argc, char *argv[])
25d34a5c
MP
550{
551 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 552 return 0;
25d34a5c
MP
553}
554
555
9486289c 556void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 557{
6d7b6081
AT
558 setup_protocol(f_out, f_in);
559
f0359dd0
AT
560 set_nonblocking(f_in);
561 set_nonblocking(f_out);
562
d04e9c51 563 if (protocol_version >= 23)
ff41a59f 564 io_start_multiplex_out(f_out);
7a6421fa 565
7a6421fa 566 if (am_sender) {
088aac85 567 if (!read_batch) {
d9c7edf6
WD
568 recv_exclude_list(f_in);
569 if (cvs_exclude)
570 add_cvs_excludes();
6902ed17 571 }
7a6421fa
AT
572 do_server_sender(f_in, f_out, argc, argv);
573 } else {
574 do_server_recv(f_in, f_out, argc, argv);
575 }
576 exit_cleanup(0);
366345fe
AT
577}
578
0ba48136
MP
579
580/*
581 * This is called once the connection has been negotiated. It is used
582 * for rsyncd, remote-shell, and local connections.
583 */
19b27a48 584int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 585{
088aac85 586 struct file_list *flist = NULL;
9486289c
AT
587 int status = 0, status2 = 0;
588 char *local_name = NULL;
19b27a48
AT
589
590 cleanup_child_pid = pid;
6902ed17 591 if (read_batch)
d9c7edf6 592 flist = batch_flist;
ff41a59f 593
f0359dd0
AT
594 set_nonblocking(f_in);
595 set_nonblocking(f_out);
596
6d7b6081
AT
597 setup_protocol(f_out,f_in);
598
d04e9c51 599 if (protocol_version >= 23)
ff41a59f 600 io_start_multiplex_in(f_in);
d9c7edf6 601
9486289c 602 if (am_sender) {
76c21947 603 io_start_buffering_out(f_out);
9486289c
AT
604 if (cvs_exclude)
605 add_cvs_excludes();
d9c7edf6 606 if (delete_mode && !delete_excluded)
9486289c 607 send_exclude_list(f_out);
7c2a9e76
WD
608 if (remote_filesfrom_file)
609 filesfrom_fd = f_in;
64c3523a 610 if (!read_batch) /* don't write to pipe */
d9c7edf6
WD
611 flist = send_file_list(f_out,argc,argv);
612 if (verbose > 3)
9486289c 613 rprintf(FINFO,"file list sent\n");
e1b3d5c4 614
f1e3656e 615 io_flush(NORMAL_FLUSH);
9486289c 616 send_files(flist,f_out,f_in);
f1e3656e 617 io_flush(FULL_FLUSH);
d04e9c51 618 if (protocol_version >= 24) {
d9c7edf6 619 /* final goodbye message */
6c65e146
AT
620 read_int(f_in);
621 }
9486289c
AT
622 if (pid != -1) {
623 if (verbose > 3)
08a740ff 624 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
f1e3656e 625 io_flush(FULL_FLUSH);
d79d1c69 626 wait_process(pid, &status);
9486289c 627 }
3d382777 628 report(-1);
f1e3656e 629 io_flush(FULL_FLUSH);
9486289c
AT
630 exit_cleanup(status);
631 }
f7632fc6 632
27e3e9c9 633 if (argc == 0) {
27e3e9c9
AT
634 list_only = 1;
635 }
d9c7edf6 636
088aac85 637 if (!write_batch)
d9c7edf6
WD
638 send_exclude_list(f_out);
639
7c2a9e76
WD
640 if (filesfrom_fd >= 0) {
641 io_set_filesfrom_fds(filesfrom_fd, f_out);
642 filesfrom_fd = -1;
643 }
644
9486289c
AT
645 flist = recv_file_list(f_in);
646 if (!flist || flist->count == 0) {
796d484b 647 rprintf(FINFO, "client: nothing to do: "
d9c7edf6
WD
648 "perhaps you need to specify some filenames or "
649 "the --recursive option?\n");
9486289c
AT
650 exit_cleanup(0);
651 }
d9c7edf6 652
9486289c 653 local_name = get_local_name(flist,argv[0]);
d9c7edf6 654
9486289c 655 status2 = do_recv(f_in,f_out,flist,local_name);
d9c7edf6 656
9486289c 657 if (pid != -1) {
8d9dc9f9 658 if (verbose > 3)
08a740ff 659 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
f1e3656e 660 io_flush(FULL_FLUSH);
d79d1c69 661 wait_process(pid, &status);
9486289c 662 }
d9c7edf6 663
ff81e809 664 return MAX(status, status2);
9486289c
AT
665}
666
7169bb4a
MP
667static int copy_argv (char *argv[])
668{
669 int i;
670
671 for (i = 0; argv[i]; i++) {
672 if (!(argv[i] = strdup(argv[i]))) {
673 rprintf (FERROR, "out of memory at %s(%d)\n",
674 __FILE__, __LINE__);
675 return RERR_MALLOC;
676 }
677 }
678
679 return 0;
680}
681
682
c1a04ecb 683/**
0ba48136
MP
684 * Start a client for either type of remote connection. Work out
685 * whether the arguments request a remote shell or rsyncd connection,
686 * and call the appropriate connection function, then run_client.
0b4af330
MP
687 *
688 * Calls either start_socket_client (for sockets) or do_cmd and
689 * client_run (for ssh).
c1a04ecb 690 **/
fc8a6b97 691static int start_client(int argc, char *argv[])
5d6bcd44
AT
692{
693 char *p;
694 char *shell_machine = NULL;
695 char *shell_path = NULL;
696 char *shell_user = NULL;
19b27a48
AT
697 int ret;
698 pid_t pid;
5d6bcd44 699 int f_in,f_out;
7169bb4a
MP
700 int rc;
701
702 /* Don't clobber argv[] so that ps(1) can still show the right
d9c7edf6 703 * command line. */
75aeac44 704 if ((rc = copy_argv(argv)))
7169bb4a 705 return rc;
5d6bcd44 706
75aeac44 707 /* rsync:// always uses rsync server over direct socket connection */
7169bb4a 708 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
f7632fc6
AT
709 char *host, *path;
710
7169bb4a 711 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
712 p = strchr(host,'/');
713 if (p) {
714 *p = 0;
715 path = p+1;
716 } else {
a125c82a 717 path = "";
f7632fc6 718 }
2acf81eb
DD
719 p = strchr(host,':');
720 if (p) {
721 rsync_port = atoi(p+1);
722 *p = 0;
723 }
f7632fc6
AT
724 return start_socket_client(host, path, argc-1, argv+1);
725 }
726
088aac85 727 if (!read_batch) {
a125c82a 728 p = find_colon(argv[0]);
d9c7edf6 729 if (p) {
7c2a9e76
WD
730 if (remote_filesfrom_file
731 && remote_filesfrom_file != files_from + 1
732 && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
733 rprintf(FERROR,
734 "--files-from hostname is not transfer hostname\n");
735 exit_cleanup(RERR_SYNTAX);
736 }
d9c7edf6
WD
737 if (p[1] == ':') { /* double colon */
738 *p = 0;
739 if (!shell_cmd) {
740 return start_socket_client(argv[0], p+2,
741 argc-1, argv+1);
742 }
743 p++;
744 daemon_over_rsh = 1;
75aeac44 745 }
3591c066 746
d9c7edf6
WD
747 if (argc < 1) {
748 usage(FERROR);
749 exit_cleanup(RERR_SYNTAX);
750 }
a125c82a 751
d9c7edf6
WD
752 am_sender = 0;
753 *p = 0;
754 shell_machine = argv[0];
755 shell_path = p+1;
756 argc--;
757 argv++;
758 } else {
759 am_sender = 1;
760
761 /* rsync:// destination uses rsync server over direct socket */
762 if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
763 char *host, *path;
764
765 host = argv[argc-1] + strlen(URL_PREFIX);
766 p = strchr(host,'/');
767 if (p) {
768 *p = 0;
769 path = p+1;
770 } else {
771 path = "";
772 }
773 p = strchr(host,':');
774 if (p) {
775 rsync_port = atoi(p+1);
776 *p = 0;
777 }
778 return start_socket_client(host, path, argc-1, argv);
a125c82a 779 }
d9c7edf6
WD
780
781 p = find_colon(argv[argc-1]);
7c2a9e76
WD
782 if (p && remote_filesfrom_file
783 && remote_filesfrom_file != files_from + 1
784 && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
785 rprintf(FERROR,
786 "--files-from hostname is not transfer hostname\n");
787 exit_cleanup(RERR_SYNTAX);
788 }
d9c7edf6
WD
789 if (!p) {
790 local_server = 1;
7c2a9e76
WD
791 if (remote_filesfrom_file) {
792 rprintf(FERROR,
793 "--files-from is remote but transfer is local\n");
794 exit_cleanup(RERR_SYNTAX);
795 }
d9c7edf6 796 } else if (p[1] == ':') { /* double colon */
a125c82a 797 *p = 0;
d9c7edf6
WD
798 if (!shell_cmd) {
799 return start_socket_client(argv[argc-1], p+2,
800 argc-1, argv);
801 }
802 p++;
803 daemon_over_rsh = 1;
a125c82a 804 }
a125c82a 805
d9c7edf6
WD
806 if (argc < 2) {
807 usage(FERROR);
808 exit_cleanup(RERR_SYNTAX);
75aeac44 809 }
3591c066 810
d9c7edf6
WD
811 if (local_server) {
812 shell_machine = NULL;
813 shell_path = argv[argc-1];
814 } else {
815 *p = 0;
816 shell_machine = argv[argc-1];
817 shell_path = p+1;
818 }
819 argc--;
5d6bcd44 820 }
6902ed17 821 } else {
d9c7edf6
WD
822 am_sender = 1;
823 local_server = 1;
824 shell_path = argv[argc-1];
6902ed17
MP
825 }
826
5d6bcd44 827 if (shell_machine) {
6fc048f4 828 p = strrchr(shell_machine,'@');
5d6bcd44
AT
829 if (p) {
830 *p = 0;
831 shell_user = shell_machine;
832 shell_machine = p+1;
833 }
834 }
835
836 if (verbose > 3) {
9486289c 837 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
838 shell_cmd?shell_cmd:"",
839 shell_machine?shell_machine:"",
840 shell_user?shell_user:"",
841 shell_path?shell_path:"");
842 }
d9c7edf6 843
f7632fc6 844 if (!am_sender && argc > 1) {
5d6bcd44 845 usage(FERROR);
65417579 846 exit_cleanup(RERR_SYNTAX);
5d6bcd44 847 }
27e3e9c9
AT
848
849 if (argc == 0 && !am_sender) {
27e3e9c9
AT
850 list_only = 1;
851 }
d9c7edf6 852
75aeac44
WD
853 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
854 &f_in,&f_out);
855
856 /* if we're running an rsync server on the remote host over a
9af87151 857 * remote shell command, we need to do the RSYNCD protocol first */
75aeac44
WD
858 if (daemon_over_rsh) {
859 int tmpret;
860 tmpret = start_inband_exchange(shell_user, shell_path,
861 f_in, f_out, argc);
862 if (tmpret < 0)
863 return tmpret;
864 }
865
fc8a6b97
AT
866 ret = client_run(f_in, f_out, pid, argc, argv);
867
868 fflush(stdout);
869 fflush(stderr);
870
871 return ret;
5d6bcd44
AT
872}
873
366345fe 874
067669da
WD
875static RETSIGTYPE sigusr1_handler(UNUSED(int val))
876{
65417579 877 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
878}
879
067669da
WD
880static RETSIGTYPE sigusr2_handler(UNUSED(int val))
881{
19b27a48 882 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
883 _exit(0);
884}
885
067669da
WD
886static RETSIGTYPE sigchld_handler(UNUSED(int val))
887{
029c1713 888#ifdef WNOHANG
ee7118a8
DD
889 int cnt, status;
890 pid_t pid;
891 /* An empty waitpid() loop was put here by Tridge and we could never
d9c7edf6 892 * get him to explain why he put it in, so rather than taking it
ee7118a8
DD
893 * out we're instead saving the child exit statuses for later use.
894 * The waitpid() loop presumably eliminates all possibility of leaving
895 * zombie children, maybe that's why he did it.
896 */
897 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
9af87151
WD
898 /* save the child's exit status */
899 for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
900 if (pid_stat_table[cnt].pid == 0) {
901 pid_stat_table[cnt].pid = pid;
902 pid_stat_table[cnt].status = status;
903 break;
904 }
905 }
ee7118a8 906 }
029c1713 907#endif
19b27a48
AT
908}
909
c0531332
MP
910
911/**
912 * This routine catches signals and tries to send them to gdb.
913 *
914 * Because it's called from inside a signal handler it ought not to
915 * use too many library routines.
916 *
917 * @todo Perhaps use "screen -X" instead/as well, to help people
918 * debugging without easy access to X. Perhaps use an environment
919 * variable, or just call a script?
920 *
921 * @todo The /proc/ magic probably only works on Linux (and
922 * Solaris?) Can we be more portable?
923 **/
924#ifdef MAINTAINER_MODE
4fdc39dd
MP
925const char *get_panic_action(void)
926{
927 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
928
929 if (cmd_fmt)
930 return cmd_fmt;
931 else
932 return "xterm -display :0 -T Panic -n Panic "
933 "-e gdb /proc/%d/exe %d";
934}
935
936
9fb3f7a9
MP
937/**
938 * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
939 *
940 * This signal handler is only installed if we were configured with
941 * --enable-maintainer-mode. Perhaps it should always be on and we
942 * should just look at the environment variable, but I'm a bit leery
943 * of a signal sending us into a busy loop.
944 **/
067669da 945static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
c0531332
MP
946{
947 char cmd_buf[300];
948 int ret;
4fdc39dd
MP
949
950 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
951 getpid(), getpid());
952
953 /* Unless we failed to execute gdb, we allow the process to
954 * continue. I'm not sure if that's right. */
955 ret = system(cmd_buf);
956 if (ret)
957 _exit(ret);
958}
959#endif
960
961
5d6bcd44 962int main(int argc,char *argv[])
d9c7edf6 963{
ff81e809 964 int ret;
088aac85 965 int orig_argc;
76f79ba7 966 char **orig_argv;
6902ed17 967
088aac85 968 orig_argc = argc;
76f79ba7 969 orig_argv = argv;
5d6bcd44 970
7a6421fa 971 signal(SIGUSR1, sigusr1_handler);
8b35435f 972 signal(SIGUSR2, sigusr2_handler);
19b27a48 973 signal(SIGCHLD, sigchld_handler);
c0531332
MP
974#ifdef MAINTAINER_MODE
975 signal(SIGSEGV, rsync_panic_handler);
976 signal(SIGFPE, rsync_panic_handler);
977 signal(SIGABRT, rsync_panic_handler);
978 signal(SIGBUS, rsync_panic_handler);
979#endif /* def MAINTAINER_MODE */
5d6bcd44 980
7a6421fa
AT
981 starttime = time(NULL);
982 am_root = (getuid() == 0);
c627d613 983
a800434a
AT
984 memset(&stats, 0, sizeof(stats));
985
df5e03da
AT
986 if (argc < 2) {
987 usage(FERROR);
65417579 988 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
989 }
990
7a6421fa 991 /* we set a 0 umask so that correct file permissions can be
9af87151 992 * carried across */
7a6421fa 993 orig_umask = (int)umask(0);
5d6bcd44 994
50135767 995 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
d9c7edf6
WD
996 /* FIXME: We ought to call the same error-handling
997 * code here, rather than relying on getopt. */
50135767 998 option_error();
65417579 999 exit_cleanup(RERR_SYNTAX);
b11ed3b1 1000 }
5d6bcd44 1001
7a6421fa 1002 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 1003 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 1004 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 1005
34758d5c
MP
1006 /* Ignore SIGPIPE; we consistently check error codes and will
1007 * see the EPIPE. */
1008 signal(SIGPIPE, SIG_IGN);
1009
c226b7c2 1010 /* Initialize push_dir here because on some old systems getcwd
9af87151
WD
1011 * (implemented by forking "pwd" and reading its output) doesn't
1012 * work when there are other child processes. Also, on all systems
1013 * that implement getcwd that way "pwd" can't be found after chroot. */
59187666 1014 push_dir(NULL);
c226b7c2 1015
44e9e221
WD
1016 init_flist();
1017
088aac85 1018 if (write_batch && !am_server) {
d9c7edf6 1019 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
1020 }
1021
75aeac44 1022 if (am_daemon && !am_server)
7a6421fa 1023 return daemon_main();
f0fca04e 1024
08ac228f
AT
1025 if (argc < 1) {
1026 usage(FERROR);
65417579 1027 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
1028 }
1029
7a6421fa
AT
1030 if (dry_run)
1031 verbose = MAX(verbose,1);
c627d613 1032
7a6421fa 1033 if (am_server) {
f0359dd0
AT
1034 set_nonblocking(STDIN_FILENO);
1035 set_nonblocking(STDOUT_FILENO);
75aeac44
WD
1036 if (am_daemon)
1037 return start_daemon(STDIN_FILENO, STDOUT_FILENO);
7a6421fa
AT
1038 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
1039 }
c627d613 1040
ff81e809 1041 ret = start_client(argc, argv);
d9c7edf6 1042 if (ret == -1)
9098bbf3 1043 exit_cleanup(RERR_STARTCLIENT);
088aac85 1044 else
9098bbf3
MP
1045 exit_cleanup(ret);
1046
0f5a04e3 1047 return ret;
c627d613 1048}