Don't generate code for zlib and popt.
[rsync/rsync.git] / main.c
CommitLineData
0ba48136
MP
1/* -*- c-file-style: "linux" -*-
2
50135767 3 Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
c627d613 4 Copyright (C) Paul Mackerras 1996
e5a2b854 5 Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
c627d613
AT
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rsync.h"
23
f0fca04e 24time_t starttime = 0;
a800434a
AT
25
26struct stats stats;
5d6bcd44 27
7a6421fa 28extern int verbose;
c627d613 29
e5a2b854 30static void show_malloc_stats(void);
82980a23
AT
31
32/****************************************************************************
33wait for a process to exit, calling io_flush while waiting
34****************************************************************************/
35void wait_process(pid_t pid, int *status)
36{
37 while (waitpid(pid, status, WNOHANG) == 0) {
a24c6870 38 msleep(20);
82980a23
AT
39 io_flush();
40 }
50135767
MP
41
42 /* TODO: If the child exited on a signal, then log an
43 * appropriate error message. Perhaps we should also accept a
44 * message describing the purpose of the child. Also indicate
45 * this to the caller so that thhey know something went
46 * wrong. */
82980a23
AT
47 *status = WEXITSTATUS(*status);
48}
49
c627d613
AT
50static void report(int f)
51{
7a6421fa
AT
52 time_t t = time(NULL);
53 extern int am_server;
54 extern int am_sender;
248fbb8c 55 extern int am_daemon;
a800434a 56 extern int do_stats;
17d31b38
DD
57 extern int remote_version;
58 int send_stats;
7a6421fa 59
5c15e29f
MP
60 if (do_stats) {
61 /* These come out from every process */
62 show_malloc_stats();
86943126 63 show_flist_stats();
5c15e29f
MP
64 }
65
248fbb8c 66 if (am_daemon) {
a9766ef1 67 log_exit(0, __FILE__, __LINE__);
7b372642 68 if (f == -1 || !am_sender) return;
248fbb8c
AT
69 }
70
ebb00c8e 71 send_stats = verbose || (remote_version >= 20);
e19452a9 72 if (am_server) {
17d31b38 73 if (am_sender && send_stats) {
23c5aef1
DD
74 int64 w;
75 /* store total_written in a temporary
76 because write_longint changes it */
77 w = stats.total_written;
e19452a9 78 write_longint(f,stats.total_read);
23c5aef1 79 write_longint(f,w);
e19452a9
DD
80 write_longint(f,stats.total_size);
81 }
7a6421fa
AT
82 return;
83 }
e19452a9
DD
84
85 /* this is the client */
86
17d31b38 87 if (!am_sender && send_stats) {
23c5aef1 88 int64 r;
a800434a 89 stats.total_written = read_longint(f);
23c5aef1
DD
90 /* store total_read in a temporary, read_longint changes it */
91 r = read_longint(f);
a800434a 92 stats.total_size = read_longint(f);
23c5aef1 93 stats.total_read = r;
a800434a
AT
94 }
95
96 if (do_stats) {
17d31b38
DD
97 if (!am_sender && !send_stats) {
98 /* missing the bytes written by the generator */
ebb00c8e 99 rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
17d31b38
DD
100 rprintf(FINFO, "Use --stats -v to show stats\n");
101 return;
102 }
1f658d42
AT
103 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
104 rprintf(FINFO,"Number of files transferred: %d\n",
a800434a 105 stats.num_transferred_files);
1f658d42 106 rprintf(FINFO,"Total file size: %.0f bytes\n",
a800434a 107 (double)stats.total_size);
1f658d42 108 rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
a800434a 109 (double)stats.total_transferred_size);
1f658d42 110 rprintf(FINFO,"Literal data: %.0f bytes\n",
a800434a 111 (double)stats.literal_data);
1f658d42 112 rprintf(FINFO,"Matched data: %.0f bytes\n",
a800434a 113 (double)stats.matched_data);
1f658d42
AT
114 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
115 rprintf(FINFO,"Total bytes written: %.0f\n",
a800434a 116 (double)stats.total_written);
1f658d42 117 rprintf(FINFO,"Total bytes read: %.0f\n\n",
a800434a 118 (double)stats.total_read);
7a6421fa
AT
119 }
120
e19452a9
DD
121 if (verbose || do_stats) {
122 rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
123 (double)stats.total_written,
124 (double)stats.total_read,
125 (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
126 rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
127 (double)stats.total_size,
128 (1.0*stats.total_size)/(stats.total_written+stats.total_read));
129 }
fc8a6b97
AT
130
131 fflush(stdout);
132 fflush(stderr);
c627d613
AT
133}
134
135
e5a2b854
MP
136/**
137 * If our C library can get malloc statistics, then show them to FINFO
138 **/
139static void show_malloc_stats(void)
140{
141#ifdef HAVE_MALLINFO
142 struct mallinfo mi;
5c15e29f
MP
143 extern int am_server;
144 extern int am_sender;
145 extern int am_daemon;
e5a2b854
MP
146
147 mi = mallinfo();
148
5c15e29f
MP
149 rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
150 getpid(),
151 am_server ? "server " : "",
152 am_daemon ? "daemon " : "",
153 am_sender ? "sender" : "receiver");
e5a2b854
MP
154 rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
155 rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
156 rprintf(FINFO, " smblks: %10d\n", mi.smblks);
157 rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
158 rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
159 rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
160 rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
161 rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
162 rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
163 rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
164#endif /* HAVE_MALLINFO */
165}
166
167
0882faa2 168/* Start the remote shell. cmd may be NULL to use the default. */
19b27a48 169static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
c627d613 170{
366345fe 171 char *args[100];
19b27a48
AT
172 int i,argc=0;
173 pid_t ret;
366345fe 174 char *tok,*dir=NULL;
7a6421fa
AT
175 extern int local_server;
176 extern char *rsync_path;
e384bfbd 177 extern int blocking_io;
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
366345fe
AT
219 if (path && *path)
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
25d34a5c
MP
496void child_main(int argc, char *argv[])
497{
498 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
499}
500
501
9486289c 502void start_server(int f_in, int f_out, int argc, char *argv[])
366345fe 503{
7a6421fa
AT
504 extern int cvs_exclude;
505 extern int am_sender;
ff41a59f 506 extern int remote_version;
088aac85 507 extern int read_batch;
ff41a59f 508
6d7b6081
AT
509 setup_protocol(f_out, f_in);
510
f0359dd0
AT
511 set_nonblocking(f_in);
512 set_nonblocking(f_out);
513
ff41a59f
AT
514 if (remote_version >= 23)
515 io_start_multiplex_out(f_out);
7a6421fa 516
7a6421fa 517 if (am_sender) {
088aac85 518 if (!read_batch) {
6902ed17
MP
519 recv_exclude_list(f_in);
520 if (cvs_exclude)
7a6421fa 521 add_cvs_excludes();
6902ed17 522 }
7a6421fa
AT
523 do_server_sender(f_in, f_out, argc, argv);
524 } else {
525 do_server_recv(f_in, f_out, argc, argv);
526 }
527 exit_cleanup(0);
366345fe
AT
528}
529
0ba48136
MP
530
531/*
532 * This is called once the connection has been negotiated. It is used
533 * for rsyncd, remote-shell, and local connections.
534 */
19b27a48 535int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
9486289c 536{
088aac85 537 struct file_list *flist = NULL;
9486289c
AT
538 int status = 0, status2 = 0;
539 char *local_name = NULL;
7a6421fa 540 extern int am_sender;
ff41a59f 541 extern int remote_version;
19b27a48 542 extern pid_t cleanup_child_pid;
088aac85
DD
543 extern int write_batch;
544 extern int read_batch;
545 extern struct file_list *batch_flist;
19b27a48
AT
546
547 cleanup_child_pid = pid;
6902ed17 548 if (read_batch)
088aac85 549 flist = batch_flist;
ff41a59f 550
f0359dd0
AT
551 set_nonblocking(f_in);
552 set_nonblocking(f_out);
553
6d7b6081
AT
554 setup_protocol(f_out,f_in);
555
ff41a59f
AT
556 if (remote_version >= 23)
557 io_start_multiplex_in(f_in);
9486289c
AT
558
559 if (am_sender) {
7a6421fa
AT
560 extern int cvs_exclude;
561 extern int delete_mode;
b33b791e 562 extern int delete_excluded;
9486289c
AT
563 if (cvs_exclude)
564 add_cvs_excludes();
b33b791e 565 if (delete_mode && !delete_excluded)
9486289c 566 send_exclude_list(f_out);
6902ed17
MP
567 if (!read_batch) /* dw -- don't write to pipe */
568 flist = send_file_list(f_out,argc,argv);
9486289c
AT
569 if (verbose > 3)
570 rprintf(FINFO,"file list sent\n");
e1b3d5c4 571
9486289c 572 send_files(flist,f_out,f_in);
6c65e146
AT
573 if (remote_version >= 24) {
574 /* final goodbye message */
575 read_int(f_in);
576 }
9486289c
AT
577 if (pid != -1) {
578 if (verbose > 3)
08a740ff 579 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
8d9dc9f9 580 io_flush();
d79d1c69 581 wait_process(pid, &status);
9486289c 582 }
3d382777 583 report(-1);
9486289c
AT
584 exit_cleanup(status);
585 }
f7632fc6 586
27e3e9c9
AT
587 if (argc == 0) {
588 extern int list_only;
589 list_only = 1;
590 }
9486289c 591
088aac85 592 if (!write_batch)
6902ed17 593 send_exclude_list(f_out);
9486289c
AT
594
595 flist = recv_file_list(f_in);
596 if (!flist || flist->count == 0) {
796d484b
MP
597 rprintf(FINFO, "client: nothing to do: "
598 "perhaps you need to specify some filenames or "
599 "the --recursive option?\n");
9486289c
AT
600 exit_cleanup(0);
601 }
602
603 local_name = get_local_name(flist,argv[0]);
604
605 status2 = do_recv(f_in,f_out,flist,local_name);
606
9486289c 607 if (pid != -1) {
8d9dc9f9 608 if (verbose > 3)
08a740ff 609 rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
8d9dc9f9 610 io_flush();
d79d1c69 611 wait_process(pid, &status);
9486289c
AT
612 }
613
ff81e809 614 return MAX(status, status2);
9486289c
AT
615}
616
ca6c93f8
AT
617static char *find_colon(char *s)
618{
619 char *p, *p2;
620
621 p = strchr(s,':');
622 if (!p) return NULL;
623
624 /* now check to see if there is a / in the string before the : - if there is then
625 discard the colon on the assumption that the : is part of a filename */
626 p2 = strchr(s,'/');
627 if (p2 && p2 < p) return NULL;
628
629 return p;
630}
9486289c 631
0ba48136 632
7169bb4a
MP
633static int copy_argv (char *argv[])
634{
635 int i;
636
637 for (i = 0; argv[i]; i++) {
638 if (!(argv[i] = strdup(argv[i]))) {
639 rprintf (FERROR, "out of memory at %s(%d)\n",
640 __FILE__, __LINE__);
641 return RERR_MALLOC;
642 }
643 }
644
645 return 0;
646}
647
648
c1a04ecb 649/**
0ba48136
MP
650 * Start a client for either type of remote connection. Work out
651 * whether the arguments request a remote shell or rsyncd connection,
652 * and call the appropriate connection function, then run_client.
0b4af330
MP
653 *
654 * Calls either start_socket_client (for sockets) or do_cmd and
655 * client_run (for ssh).
c1a04ecb 656 **/
fc8a6b97 657static int start_client(int argc, char *argv[])
5d6bcd44
AT
658{
659 char *p;
660 char *shell_machine = NULL;
661 char *shell_path = NULL;
662 char *shell_user = NULL;
19b27a48
AT
663 int ret;
664 pid_t pid;
5d6bcd44 665 int f_in,f_out;
7a6421fa
AT
666 extern int local_server;
667 extern int am_sender;
668 extern char *shell_cmd;
2acf81eb 669 extern int rsync_port;
a1a440c2 670 extern int whole_file;
088aac85 671 extern int write_batch;
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. */
677 if ((rc = copy_argv (argv)))
678 return rc;
5d6bcd44 679
7169bb4a 680 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
f7632fc6
AT
681 char *host, *path;
682
7169bb4a 683 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
684 p = strchr(host,'/');
685 if (p) {
686 *p = 0;
687 path = p+1;
688 } else {
689 path="";
690 }
2acf81eb
DD
691 p = strchr(host,':');
692 if (p) {
693 rsync_port = atoi(p+1);
694 *p = 0;
695 }
f7632fc6
AT
696 return start_socket_client(host, path, argc-1, argv+1);
697 }
698
088aac85 699 if (!read_batch) {
6902ed17 700 p = find_colon(argv[0]);
5d6bcd44
AT
701
702 if (p) {
c1a04ecb 703 if (p[1] == ':') { /* double colon */
9486289c 704 *p = 0;
7169bb4a 705 return start_socket_client(argv[0], p+2, argc-1, argv+1);
9486289c 706 }
3591c066 707
f7632fc6 708 if (argc < 1) {
3591c066 709 usage(FERROR);
65417579 710 exit_cleanup(RERR_SYNTAX);
3591c066
AT
711 }
712
5d6bcd44
AT
713 am_sender = 0;
714 *p = 0;
7169bb4a 715 shell_machine = argv[0];
5d6bcd44
AT
716 shell_path = p+1;
717 argc--;
718 argv++;
719 } else {
720 am_sender = 1;
9486289c 721
ca6c93f8 722 p = find_colon(argv[argc-1]);
5d6bcd44
AT
723 if (!p) {
724 local_server = 1;
9486289c
AT
725 } else if (p[1] == ':') {
726 *p = 0;
727 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
5d6bcd44 728 }
3591c066
AT
729
730 if (argc < 2) {
731 usage(FERROR);
65417579 732 exit_cleanup(RERR_SYNTAX);
3591c066 733 }
9486289c 734
5d6bcd44
AT
735 if (local_server) {
736 shell_machine = NULL;
737 shell_path = argv[argc-1];
738 } else {
739 *p = 0;
740 shell_machine = argv[argc-1];
741 shell_path = p+1;
742 }
743 argc--;
744 }
6902ed17 745 } else {
088aac85
DD
746 am_sender = 1;
747 local_server = 1;
748 shell_path = argv[argc-1];
6902ed17
MP
749 }
750
5d6bcd44
AT
751 if (shell_machine) {
752 p = strchr(shell_machine,'@');
753 if (p) {
754 *p = 0;
755 shell_user = shell_machine;
756 shell_machine = p+1;
757 }
758 }
759
760 if (verbose > 3) {
9486289c 761 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
762 shell_cmd?shell_cmd:"",
763 shell_machine?shell_machine:"",
764 shell_user?shell_user:"",
765 shell_path?shell_path:"");
766 }
767
f7632fc6 768 if (!am_sender && argc > 1) {
5d6bcd44 769 usage(FERROR);
65417579 770 exit_cleanup(RERR_SYNTAX);
5d6bcd44 771 }
27e3e9c9
AT
772
773 if (argc == 0 && !am_sender) {
774 extern int list_only;
775 list_only = 1;
776 }
5d6bcd44
AT
777
778 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
779
fc8a6b97
AT
780 ret = client_run(f_in, f_out, pid, argc, argv);
781
782 fflush(stdout);
783 fflush(stderr);
784
785 return ret;
5d6bcd44
AT
786}
787
366345fe 788
0f0ea7f7 789static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
65417579 790 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
791}
792
0f0ea7f7 793static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
ff81e809 794 extern int log_got_error;
19b27a48 795 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
796 _exit(0);
797}
798
0f0ea7f7 799static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
029c1713
AT
800#ifdef WNOHANG
801 while (waitpid(-1, NULL, WNOHANG) > 0) ;
802#endif
19b27a48
AT
803}
804
c0531332
MP
805
806/**
807 * This routine catches signals and tries to send them to gdb.
808 *
809 * Because it's called from inside a signal handler it ought not to
810 * use too many library routines.
811 *
812 * @todo Perhaps use "screen -X" instead/as well, to help people
813 * debugging without easy access to X. Perhaps use an environment
814 * variable, or just call a script?
815 *
816 * @todo The /proc/ magic probably only works on Linux (and
817 * Solaris?) Can we be more portable?
818 **/
819#ifdef MAINTAINER_MODE
820static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
821{
822 char cmd_buf[300];
823 int ret;
824 sprintf(cmd_buf,
825 "xterm -display :0 -T Panic -n Panic "
826 "-e gdb /proc/%d/exe %d",
827 getpid(), getpid());
828
829 /* Unless we failed to execute gdb, we allow the process to
830 * continue. I'm not sure if that's right. */
831 ret = system(cmd_buf);
832 if (ret)
833 _exit(ret);
834}
835#endif
836
837
5d6bcd44 838int main(int argc,char *argv[])
7a6421fa
AT
839{
840 extern int am_root;
841 extern int orig_umask;
842 extern int dry_run;
843 extern int am_daemon;
844 extern int am_server;
ff81e809 845 int ret;
088aac85
DD
846 extern int write_batch;
847 int orig_argc;
76f79ba7 848 char **orig_argv;
6902ed17 849
088aac85 850 orig_argc = argc;
76f79ba7 851 orig_argv = argv;
5d6bcd44 852
7a6421fa 853 signal(SIGUSR1, sigusr1_handler);
8b35435f 854 signal(SIGUSR2, sigusr2_handler);
19b27a48 855 signal(SIGCHLD, sigchld_handler);
c0531332
MP
856#ifdef MAINTAINER_MODE
857 signal(SIGSEGV, rsync_panic_handler);
858 signal(SIGFPE, rsync_panic_handler);
859 signal(SIGABRT, rsync_panic_handler);
860 signal(SIGBUS, rsync_panic_handler);
861#endif /* def MAINTAINER_MODE */
5d6bcd44 862
7a6421fa
AT
863 starttime = time(NULL);
864 am_root = (getuid() == 0);
c627d613 865
a800434a
AT
866 memset(&stats, 0, sizeof(stats));
867
df5e03da
AT
868 if (argc < 2) {
869 usage(FERROR);
65417579 870 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
871 }
872
7a6421fa
AT
873 /* we set a 0 umask so that correct file permissions can be
874 carried across */
875 orig_umask = (int)umask(0);
5d6bcd44 876
50135767 877 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
305ab133
MP
878 /* FIXME: We ought to call the same error-handling
879 * code here, rather than relying on getopt. */
50135767 880 option_error();
65417579 881 exit_cleanup(RERR_SYNTAX);
b11ed3b1 882 }
5d6bcd44 883
7a6421fa 884 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 885 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 886 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 887
34758d5c
MP
888 /* Ignore SIGPIPE; we consistently check error codes and will
889 * see the EPIPE. */
890 signal(SIGPIPE, SIG_IGN);
891
c226b7c2
DD
892 /* Initialize push_dir here because on some old systems getcwd
893 (implemented by forking "pwd" and reading its output) doesn't
894 work when there are other child processes. Also, on all systems
895 that implement getcwd that way "pwd" can't be found after chroot. */
896 push_dir(NULL,0);
897
088aac85 898 if (write_batch && !am_server) {
76f79ba7 899 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
900 }
901
7a6421fa
AT
902 if (am_daemon) {
903 return daemon_main();
904 }
f0fca04e 905
08ac228f
AT
906 if (argc < 1) {
907 usage(FERROR);
65417579 908 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
909 }
910
7a6421fa
AT
911 if (dry_run)
912 verbose = MAX(verbose,1);
c627d613 913
cbbe4892 914#ifndef SUPPORT_LINKS
7a6421fa
AT
915 if (!am_server && preserve_links) {
916 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 917 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 918 }
cbbe4892
AT
919#endif
920
7a6421fa 921 if (am_server) {
f0359dd0
AT
922 set_nonblocking(STDIN_FILENO);
923 set_nonblocking(STDOUT_FILENO);
7a6421fa
AT
924 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
925 }
c627d613 926
ff81e809 927 ret = start_client(argc, argv);
088aac85 928 if (ret == -1)
9098bbf3 929 exit_cleanup(RERR_STARTCLIENT);
088aac85 930 else
9098bbf3
MP
931 exit_cleanup(ret);
932
933 exit(ret);
934 /* NOTREACHED */
c627d613 935}