Clean up prototype.
[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;
6902ed17 177 extern int read_batch;
366345fe 178
088aac85 179 if (!read_batch && !local_server) {
366345fe
AT
180 if (!cmd)
181 cmd = getenv(RSYNC_RSH_ENV);
182 if (!cmd)
183 cmd = RSYNC_RSH;
184 cmd = strdup(cmd);
185 if (!cmd)
186 goto oom;
187
188 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
189 args[argc++] = tok;
190 }
c627d613 191
7b8356d0 192#if HAVE_REMSH
366345fe
AT
193 /* remsh (on HPUX) takes the arguments the other way around */
194 args[argc++] = machine;
195 if (user) {
196 args[argc++] = "-l";
197 args[argc++] = user;
198 }
7b8356d0 199#else
366345fe
AT
200 if (user) {
201 args[argc++] = "-l";
202 args[argc++] = user;
203 }
204 args[argc++] = machine;
7b8356d0 205#endif
c627d613 206
366345fe 207 args[argc++] = rsync_path;
c627d613 208
93689aa5
DD
209 if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
210 blocking_io = 1;
e384bfbd 211
93689aa5 212 server_options(args,&argc);
e384bfbd 213
366345fe 214 }
c627d613 215
366345fe 216 args[argc++] = ".";
76076c4b 217
366345fe
AT
218 if (path && *path)
219 args[argc++] = path;
c627d613 220
366345fe 221 args[argc] = NULL;
c627d613 222
366345fe 223 if (verbose > 3) {
9486289c 224 rprintf(FINFO,"cmd=");
366345fe 225 for (i=0;i<argc;i++)
9486289c
AT
226 rprintf(FINFO,"%s ",args[i]);
227 rprintf(FINFO,"\n");
366345fe
AT
228 }
229
230 if (local_server) {
6902ed17 231 if (read_batch)
088aac85 232 create_flist_from_batch(); /* sets batch_flist */
25d34a5c 233 ret = local_child(argc, args, f_in, f_out, child_main);
366345fe
AT
234 } else {
235 ret = piped_child(args,f_in,f_out);
236 }
c627d613 237
366345fe 238 if (dir) free(dir);
82306bf6 239
366345fe 240 return ret;
c627d613
AT
241
242oom:
366345fe
AT
243 out_of_memory("do_cmd");
244 return 0; /* not reached */
c627d613
AT
245}
246
247
248
249
250static char *get_local_name(struct file_list *flist,char *name)
251{
7a6421fa
AT
252 STRUCT_STAT st;
253 extern int orig_umask;
c627d613 254
c95da96a
AT
255 if (verbose > 2)
256 rprintf(FINFO,"get_local_name count=%d %s\n",
1f0610ef
DD
257 flist->count, NS(name));
258
259 if (!name)
260 return NULL;
c95da96a 261
1ff5450d
AT
262 if (do_stat(name,&st) == 0) {
263 if (S_ISDIR(st.st_mode)) {
5243c216
AT
264 if (!push_dir(name, 0)) {
265 rprintf(FERROR,"push_dir %s : %s (1)\n",
1ff5450d 266 name,strerror(errno));
65417579 267 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
268 }
269 return NULL;
270 }
271 if (flist->count > 1) {
272 rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
65417579 273 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
274 }
275 return name;
276 }
277
cec8aa77 278 if (flist->count <= 1)
1ff5450d
AT
279 return name;
280
1ff5450d 281 if (do_mkdir(name,0777 & ~orig_umask) != 0) {
b84ba896
MP
282 rprintf(FERROR, RSYNC_NAME ": mkdir %s: %s\n",
283 name, strerror(errno));
65417579 284 exit_cleanup(RERR_FILEIO);
1ff5450d 285 } else {
b536f47e
AT
286 if (verbose > 0)
287 rprintf(FINFO,"created directory %s\n",name);
1ff5450d
AT
288 }
289
5243c216 290 if (!push_dir(name, 0)) {
b84ba896
MP
291 rprintf(FERROR, RSYNC_NAME ": push_dir %s: %s\n",
292 name, strerror(errno));
65417579 293 exit_cleanup(RERR_FILESELECT);
1ff5450d
AT
294 }
295
296 return NULL;
c627d613
AT
297}
298
299
300
301
9486289c 302static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
c627d613 303{
7a6421fa
AT
304 int i;
305 struct file_list *flist;
306 char *dir = argv[0];
307 extern int relative_paths;
7a6421fa 308 extern int recurse;
adc19c98 309 extern int remote_version;
c627d613 310
7a6421fa
AT
311 if (verbose > 2)
312 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
c627d613 313
5243c216
AT
314 if (!relative_paths && !push_dir(dir, 0)) {
315 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
65417579 316 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
317 }
318 argc--;
319 argv++;
c627d613 320
7a6421fa
AT
321 if (strcmp(dir,".")) {
322 int l = strlen(dir);
323 if (strcmp(dir,"/") == 0)
324 l = 0;
325 for (i=0;i<argc;i++)
326 argv[i] += l+1;
327 }
c627d613 328
7a6421fa
AT
329 if (argc == 0 && recurse) {
330 argc=1;
331 argv--;
332 argv[0] = ".";
333 }
334
7a6421fa 335 flist = send_file_list(f_out,argc,argv);
8d9dc9f9
AT
336 if (!flist || flist->count == 0) {
337 exit_cleanup(0);
338 }
339
7a6421fa 340 send_files(flist,f_out,f_in);
3d382777 341 io_flush();
7a6421fa 342 report(f_out);
adc19c98
AT
343 if (remote_version >= 24) {
344 /* final goodbye message */
345 read_int(f_in);
346 }
8d9dc9f9 347 io_flush();
7a6421fa 348 exit_cleanup(0);
c627d613
AT
349}
350
351
dc5ddbcc
AT
352static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
353{
d186eb1a
AT
354 int pid;
355 int status=0;
356 int recv_pipe[2];
554e0a8d 357 int error_pipe[2];
d186eb1a 358 extern int preserve_hard_links;
6957ae33
AT
359 extern int delete_after;
360 extern int recurse;
361 extern int delete_mode;
8ada7518 362 extern int remote_version;
dc5ddbcc 363
d186eb1a
AT
364 if (preserve_hard_links)
365 init_hard_links(flist);
dc5ddbcc 366
6957ae33
AT
367 if (!delete_after) {
368 /* I moved this here from recv_files() to prevent a race condition */
369 if (recurse && delete_mode && !local_name && flist->count>0) {
370 delete_files(flist);
371 }
372 }
373
08f15335 374 if (fd_pair(recv_pipe) < 0) {
d186eb1a 375 rprintf(FERROR,"pipe failed in do_recv\n");
65417579 376 exit_cleanup(RERR_SOCKETIO);
d186eb1a 377 }
554e0a8d 378
08f15335 379 if (fd_pair(error_pipe) < 0) {
554e0a8d
AT
380 rprintf(FERROR,"error pipe failed in do_recv\n");
381 exit_cleanup(RERR_SOCKETIO);
382 }
c6e7fcb4 383
8d9dc9f9 384 io_flush();
c6e7fcb4 385
d186eb1a 386 if ((pid=do_fork()) == 0) {
e08c9610 387 close(recv_pipe[0]);
554e0a8d 388 close(error_pipe[0]);
e08c9610
AT
389 if (f_in != f_out) close(f_out);
390
554e0a8d
AT
391 /* we can't let two processes write to the socket at one time */
392 io_multiplexing_close();
393
394 /* set place to send errors */
395 set_error_fd(error_pipe[1]);
396
e08c9610 397 recv_files(f_in,flist,local_name,recv_pipe[1]);
3d382777 398 io_flush();
ba5e128d 399 report(f_in);
e08c9610 400
8b35435f
AT
401 write_int(recv_pipe[1],1);
402 close(recv_pipe[1]);
8d9dc9f9 403 io_flush();
4a748188 404 /* finally we go to sleep until our parent kills us
27e3e9c9 405 with a USR2 signal. We sleep for a short time as on
4a748188 406 some OSes a signal won't interrupt a sleep! */
e1bd49d6
MP
407 while (msleep(20))
408 ;
d186eb1a 409 }
dc5ddbcc 410
e08c9610 411 close(recv_pipe[1]);
554e0a8d 412 close(error_pipe[1]);
e08c9610 413 if (f_in != f_out) close(f_in);
e1b3d5c4 414
b3e10ed7
AT
415 io_start_buffering(f_out);
416
554e0a8d
AT
417 io_set_error_fd(error_pipe[0]);
418
e08c9610 419 generate_files(f_out,flist,local_name,recv_pipe[0]);
8d9dc9f9 420
8b35435f
AT
421 read_int(recv_pipe[0]);
422 close(recv_pipe[0]);
8ada7518
AT
423 if (remote_version >= 24) {
424 /* send a final goodbye message */
425 write_int(f_out, -1);
426 }
8d9dc9f9 427 io_flush();
8ada7518 428
8b35435f 429 kill(pid, SIGUSR2);
d79d1c69 430 wait_process(pid, &status);
d186eb1a 431 return status;
dc5ddbcc
AT
432}
433
c627d613 434
9486289c 435static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
c627d613 436{
7a6421fa
AT
437 int status;
438 struct file_list *flist;
439 char *local_name=NULL;
440 char *dir = NULL;
441 extern int delete_mode;
b33b791e 442 extern int delete_excluded;
7a6421fa 443 extern int am_daemon;
09b7f5db
AT
444 extern int module_id;
445 extern int am_sender;
088aac85
DD
446 extern int read_batch;
447 extern struct file_list *batch_flist;
f0fca04e 448
7a6421fa
AT
449 if (verbose > 2)
450 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
09b7f5db
AT
451
452 if (am_daemon && lp_read_only(module_id) && !am_sender) {
453 rprintf(FERROR,"ERROR: module is read only\n");
454 exit_cleanup(RERR_SYNTAX);
455 return;
456 }
457
7a6421fa 458
7a6421fa
AT
459 if (argc > 0) {
460 dir = argv[0];
461 argc--;
462 argv++;
5243c216
AT
463 if (!am_daemon && !push_dir(dir, 0)) {
464 rprintf(FERROR,"push_dir %s : %s (4)\n",
7a6421fa 465 dir,strerror(errno));
65417579 466 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
467 }
468 }
c627d613 469
b33b791e 470 if (delete_mode && !delete_excluded)
7a6421fa 471 recv_exclude_list(f_in);
c627d613 472
088aac85 473 if (read_batch)
6902ed17
MP
474 flist = batch_flist;
475 else
476 flist = recv_file_list(f_in);
4c36a13e
AT
477 if (!flist) {
478 rprintf(FERROR,"server_recv: recv_file_list error\n");
65417579 479 exit_cleanup(RERR_FILESELECT);
7a6421fa
AT
480 }
481
482 if (argc > 0) {
483 if (strcmp(dir,".")) {
484 argv[0] += strlen(dir);
485 if (argv[0][0] == '/') argv[0]++;
486 }
487 local_name = get_local_name(flist,argv[0]);
488 }
c627d613 489
7a6421fa
AT
490 status = do_recv(f_in,f_out,flist,local_name);
491 exit_cleanup(status);
c627d613
AT
492}
493
494
734a94a2 495int child_main(int argc, char *argv[])
25d34a5c
MP
496{
497 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
734a94a2 498 return 0;
25d34a5c
MP
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;
6902ed17 670 extern int read_batch;
7169bb4a
MP
671 int rc;
672
673 /* Don't clobber argv[] so that ps(1) can still show the right
674 command line. */
675 if ((rc = copy_argv (argv)))
676 return rc;
5d6bcd44 677
7169bb4a 678 if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
f7632fc6
AT
679 char *host, *path;
680
7169bb4a 681 host = argv[0] + strlen(URL_PREFIX);
f7632fc6
AT
682 p = strchr(host,'/');
683 if (p) {
684 *p = 0;
685 path = p+1;
686 } else {
687 path="";
688 }
2acf81eb
DD
689 p = strchr(host,':');
690 if (p) {
691 rsync_port = atoi(p+1);
692 *p = 0;
693 }
f7632fc6
AT
694 return start_socket_client(host, path, argc-1, argv+1);
695 }
696
088aac85 697 if (!read_batch) {
6902ed17 698 p = find_colon(argv[0]);
5d6bcd44
AT
699
700 if (p) {
c1a04ecb 701 if (p[1] == ':') { /* double colon */
9486289c 702 *p = 0;
7169bb4a 703 return start_socket_client(argv[0], p+2, argc-1, argv+1);
9486289c 704 }
3591c066 705
f7632fc6 706 if (argc < 1) {
3591c066 707 usage(FERROR);
65417579 708 exit_cleanup(RERR_SYNTAX);
3591c066
AT
709 }
710
5d6bcd44
AT
711 am_sender = 0;
712 *p = 0;
7169bb4a 713 shell_machine = argv[0];
5d6bcd44
AT
714 shell_path = p+1;
715 argc--;
716 argv++;
717 } else {
718 am_sender = 1;
9486289c 719
ca6c93f8 720 p = find_colon(argv[argc-1]);
5d6bcd44
AT
721 if (!p) {
722 local_server = 1;
9486289c
AT
723 } else if (p[1] == ':') {
724 *p = 0;
725 return start_socket_client(argv[argc-1], p+2, argc-1, argv);
5d6bcd44 726 }
3591c066
AT
727
728 if (argc < 2) {
729 usage(FERROR);
65417579 730 exit_cleanup(RERR_SYNTAX);
3591c066 731 }
9486289c 732
5d6bcd44
AT
733 if (local_server) {
734 shell_machine = NULL;
735 shell_path = argv[argc-1];
736 } else {
737 *p = 0;
738 shell_machine = argv[argc-1];
739 shell_path = p+1;
740 }
741 argc--;
742 }
6902ed17 743 } else {
088aac85
DD
744 am_sender = 1;
745 local_server = 1;
746 shell_path = argv[argc-1];
6902ed17
MP
747 }
748
5d6bcd44
AT
749 if (shell_machine) {
750 p = strchr(shell_machine,'@');
751 if (p) {
752 *p = 0;
753 shell_user = shell_machine;
754 shell_machine = p+1;
755 }
756 }
757
758 if (verbose > 3) {
9486289c 759 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
5d6bcd44
AT
760 shell_cmd?shell_cmd:"",
761 shell_machine?shell_machine:"",
762 shell_user?shell_user:"",
763 shell_path?shell_path:"");
764 }
765
f7632fc6 766 if (!am_sender && argc > 1) {
5d6bcd44 767 usage(FERROR);
65417579 768 exit_cleanup(RERR_SYNTAX);
5d6bcd44 769 }
27e3e9c9
AT
770
771 if (argc == 0 && !am_sender) {
772 extern int list_only;
773 list_only = 1;
774 }
5d6bcd44
AT
775
776 pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
777
fc8a6b97
AT
778 ret = client_run(f_in, f_out, pid, argc, argv);
779
780 fflush(stdout);
781 fflush(stderr);
782
783 return ret;
5d6bcd44
AT
784}
785
366345fe 786
0f0ea7f7 787static RETSIGTYPE sigusr1_handler(int UNUSED(val)) {
65417579 788 exit_cleanup(RERR_SIGNAL);
82306bf6
AT
789}
790
0f0ea7f7 791static RETSIGTYPE sigusr2_handler(int UNUSED(val)) {
ff81e809 792 extern int log_got_error;
19b27a48 793 if (log_got_error) _exit(RERR_PARTIAL);
8b35435f
AT
794 _exit(0);
795}
796
0f0ea7f7 797static RETSIGTYPE sigchld_handler(int UNUSED(val)) {
029c1713
AT
798#ifdef WNOHANG
799 while (waitpid(-1, NULL, WNOHANG) > 0) ;
800#endif
19b27a48
AT
801}
802
c0531332
MP
803
804/**
805 * This routine catches signals and tries to send them to gdb.
806 *
807 * Because it's called from inside a signal handler it ought not to
808 * use too many library routines.
809 *
810 * @todo Perhaps use "screen -X" instead/as well, to help people
811 * debugging without easy access to X. Perhaps use an environment
812 * variable, or just call a script?
813 *
814 * @todo The /proc/ magic probably only works on Linux (and
815 * Solaris?) Can we be more portable?
816 **/
817#ifdef MAINTAINER_MODE
4fdc39dd
MP
818const char *get_panic_action(void)
819{
820 const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
821
822 if (cmd_fmt)
823 return cmd_fmt;
824 else
825 return "xterm -display :0 -T Panic -n Panic "
826 "-e gdb /proc/%d/exe %d";
827}
828
829
c0531332
MP
830static RETSIGTYPE rsync_panic_handler(int UNUSED(whatsig))
831{
832 char cmd_buf[300];
833 int ret;
4fdc39dd
MP
834
835 sprintf(cmd_buf, get_panic_action(),
c0531332
MP
836 getpid(), getpid());
837
838 /* Unless we failed to execute gdb, we allow the process to
839 * continue. I'm not sure if that's right. */
840 ret = system(cmd_buf);
841 if (ret)
842 _exit(ret);
843}
844#endif
845
846
5d6bcd44 847int main(int argc,char *argv[])
7a6421fa
AT
848{
849 extern int am_root;
850 extern int orig_umask;
851 extern int dry_run;
852 extern int am_daemon;
853 extern int am_server;
ff81e809 854 int ret;
088aac85
DD
855 extern int write_batch;
856 int orig_argc;
76f79ba7 857 char **orig_argv;
6902ed17 858
088aac85 859 orig_argc = argc;
76f79ba7 860 orig_argv = argv;
5d6bcd44 861
7a6421fa 862 signal(SIGUSR1, sigusr1_handler);
8b35435f 863 signal(SIGUSR2, sigusr2_handler);
19b27a48 864 signal(SIGCHLD, sigchld_handler);
c0531332
MP
865#ifdef MAINTAINER_MODE
866 signal(SIGSEGV, rsync_panic_handler);
867 signal(SIGFPE, rsync_panic_handler);
868 signal(SIGABRT, rsync_panic_handler);
869 signal(SIGBUS, rsync_panic_handler);
870#endif /* def MAINTAINER_MODE */
5d6bcd44 871
7a6421fa
AT
872 starttime = time(NULL);
873 am_root = (getuid() == 0);
c627d613 874
a800434a
AT
875 memset(&stats, 0, sizeof(stats));
876
df5e03da
AT
877 if (argc < 2) {
878 usage(FERROR);
65417579 879 exit_cleanup(RERR_SYNTAX);
df5e03da
AT
880 }
881
7a6421fa
AT
882 /* we set a 0 umask so that correct file permissions can be
883 carried across */
884 orig_umask = (int)umask(0);
5d6bcd44 885
50135767 886 if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
305ab133
MP
887 /* FIXME: We ought to call the same error-handling
888 * code here, rather than relying on getopt. */
50135767 889 option_error();
65417579 890 exit_cleanup(RERR_SYNTAX);
b11ed3b1 891 }
5d6bcd44 892
7a6421fa 893 signal(SIGINT,SIGNAL_CAST sig_int);
7a6421fa 894 signal(SIGHUP,SIGNAL_CAST sig_int);
8638dd48 895 signal(SIGTERM,SIGNAL_CAST sig_int);
6b83141d 896
34758d5c
MP
897 /* Ignore SIGPIPE; we consistently check error codes and will
898 * see the EPIPE. */
899 signal(SIGPIPE, SIG_IGN);
900
c226b7c2
DD
901 /* Initialize push_dir here because on some old systems getcwd
902 (implemented by forking "pwd" and reading its output) doesn't
903 work when there are other child processes. Also, on all systems
904 that implement getcwd that way "pwd" can't be found after chroot. */
905 push_dir(NULL,0);
906
088aac85 907 if (write_batch && !am_server) {
76f79ba7 908 write_batch_argvs_file(orig_argc, orig_argv);
6902ed17
MP
909 }
910
7a6421fa
AT
911 if (am_daemon) {
912 return daemon_main();
913 }
f0fca04e 914
08ac228f
AT
915 if (argc < 1) {
916 usage(FERROR);
65417579 917 exit_cleanup(RERR_SYNTAX);
08ac228f
AT
918 }
919
7a6421fa
AT
920 if (dry_run)
921 verbose = MAX(verbose,1);
c627d613 922
cbbe4892 923#ifndef SUPPORT_LINKS
7a6421fa
AT
924 if (!am_server && preserve_links) {
925 rprintf(FERROR,"ERROR: symbolic links not supported\n");
65417579 926 exit_cleanup(RERR_UNSUPPORTED);
7a6421fa 927 }
cbbe4892
AT
928#endif
929
7a6421fa 930 if (am_server) {
f0359dd0
AT
931 set_nonblocking(STDIN_FILENO);
932 set_nonblocking(STDOUT_FILENO);
7a6421fa
AT
933 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
934 }
c627d613 935
ff81e809 936 ret = start_client(argc, argv);
088aac85 937 if (ret == -1)
9098bbf3 938 exit_cleanup(RERR_STARTCLIENT);
088aac85 939 else
9098bbf3
MP
940 exit_cleanup(ret);
941
942 exit(ret);
943 /* NOTREACHED */
c627d613 944}