Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

main.c File Reference

Go to the source code of this file.

Functions

void show_malloc_stats (void)
 If our C library can get malloc statistics, then show them to FINFO. More...

void wait_process (pid_t pid, int *status)
void report (int f)
pid_t do_cmd (char *cmd, char *machine, char *user, char *path, int *f_in, int *f_out)
char * get_local_name (struct file_list *flist, char *name)
void do_server_sender (int f_in, int f_out, int argc, char *argv[])
int do_recv (int f_in, int f_out, struct file_list *flist, char *local_name)
void do_server_recv (int f_in, int f_out, int argc, char *argv[])
int child_main (int argc, char *argv[])
void start_server (int f_in, int f_out, int argc, char *argv[])
int client_run (int f_in, int f_out, pid_t pid, int argc, char *argv[])
char * find_colon (char *s)
int copy_argv (char *argv[])
int start_client (int argc, char *argv[])
 Start a client for either type of remote connection. More...

RETSIGTYPE sigusr1_handler (int UNUSED(val))
RETSIGTYPE sigusr2_handler (int UNUSED(val))
RETSIGTYPE sigchld_handler (int UNUSED(val))
const char * get_panic_action (void)
 This routine catches signals and tries to send them to gdb. More...

RETSIGTYPE rsync_panic_handler (int UNUSED(whatsig))
 Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION. More...

int main (int argc, char *argv[])

Variables

time_t starttime = 0
stats stats
int verbose


Function Documentation

void show_malloc_stats void    [static]
 

If our C library can get malloc statistics, then show them to FINFO.

Definition at line 138 of file main.c.

References am_daemon, am_sender, FINFO, and rprintf().

Referenced by report().

00139 {
00140 #ifdef HAVE_MALLINFO
00141         struct mallinfo mi;
00142         extern int am_server;
00143         extern int am_sender;
00144         extern int am_daemon;
00145 
00146         mi = mallinfo();
00147 
00148         rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
00149                 getpid(),
00150                 am_server ? "server " : "",
00151                 am_daemon ? "daemon " : "",
00152                 am_sender ? "sender" : "receiver");
00153         rprintf(FINFO, "  arena:     %10d   (bytes from sbrk)\n", mi.arena);
00154         rprintf(FINFO, "  ordblks:   %10d   (chunks not in use)\n", mi.ordblks);
00155         rprintf(FINFO, "  smblks:    %10d\n", mi.smblks);
00156         rprintf(FINFO, "  hblks:     %10d   (chunks from mmap)\n", mi.hblks);
00157         rprintf(FINFO, "  hblkhd:    %10d   (bytes from mmap)\n", mi.hblkhd);
00158         rprintf(FINFO, "  usmblks:   %10d\n", mi.usmblks);
00159         rprintf(FINFO, "  fsmblks:   %10d\n", mi.fsmblks);
00160         rprintf(FINFO, "  uordblks:  %10d   (bytes used)\n", mi.uordblks);
00161         rprintf(FINFO, "  fordblks:  %10d   (bytes free)\n", mi.fordblks);
00162         rprintf(FINFO, "  keepcost:  %10d   (bytes in releasable chunk)\n", mi.keepcost);
00163 #endif /* HAVE_MALLINFO */
00164 }

void wait_process pid_t    pid,
int *    status
 

Definition at line 34 of file main.c.

References io_flush(), msleep(), and waitpid().

Referenced by client_run(), and do_recv().

00035 {
00036         while (waitpid(pid, status, WNOHANG) == 0) {
00037                 msleep(20);
00038                 io_flush();
00039         }
00040         
00041         /* TODO: If the child exited on a signal, then log an
00042          * appropriate error message.  Perhaps we should also accept a
00043          * message describing the purpose of the child.  Also indicate
00044          * this to the caller so that thhey know something went
00045          * wrong.  */
00046         *status = WEXITSTATUS(*status);
00047 }

void report int    f [static]
 

Definition at line 49 of file main.c.

References am_daemon, am_sender, do_stats, FINFO, stats::flist_size, stats::literal_data, log_exit(), stats::matched_data, stats::num_files, stats::num_transferred_files, read_longint(), rprintf(), show_flist_stats(), show_malloc_stats(), starttime, stats::total_read, stats::total_size, stats::total_transferred_size, stats::total_written, verbose, and write_longint().

Referenced by client_run(), do_recv(), and do_server_sender().

00050 {
00051         time_t t = time(NULL);
00052         extern int am_server;
00053         extern int am_sender;
00054         extern int am_daemon;
00055         extern int do_stats;
00056         extern int remote_version;
00057         int send_stats;
00058 
00059         if (do_stats) {
00060                 /* These come out from every process */
00061                 show_malloc_stats();
00062                 show_flist_stats();
00063         }
00064 
00065         if (am_daemon) {
00066                 log_exit(0, __FILE__, __LINE__);
00067                 if (f == -1 || !am_sender) return;
00068         }
00069 
00070         send_stats = verbose || (remote_version >= 20);
00071         if (am_server) {
00072                 if (am_sender && send_stats) {
00073                         int64 w;
00074                         /* store total_written in a temporary
00075                             because write_longint changes it */
00076                         w = stats.total_written;
00077                         write_longint(f,stats.total_read);
00078                         write_longint(f,w);
00079                         write_longint(f,stats.total_size);
00080                 }
00081                 return;
00082         }
00083 
00084         /* this is the client */
00085             
00086         if (!am_sender && send_stats) {
00087                 int64 r;
00088                 stats.total_written = read_longint(f);
00089                 /* store total_read in a temporary, read_longint changes it */
00090                 r = read_longint(f);
00091                 stats.total_size = read_longint(f);
00092                 stats.total_read = r;
00093         }
00094 
00095         if (do_stats) {
00096                 if (!am_sender && !send_stats) {
00097                     /* missing the bytes written by the generator */
00098                     rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
00099                     rprintf(FINFO, "Use --stats -v to show stats\n");
00100                     return;
00101                 }
00102                 rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
00103                 rprintf(FINFO,"Number of files transferred: %d\n", 
00104                        stats.num_transferred_files);
00105                 rprintf(FINFO,"Total file size: %.0f bytes\n", 
00106                        (double)stats.total_size);
00107                 rprintf(FINFO,"Total transferred file size: %.0f bytes\n", 
00108                        (double)stats.total_transferred_size);
00109                 rprintf(FINFO,"Literal data: %.0f bytes\n", 
00110                        (double)stats.literal_data);
00111                 rprintf(FINFO,"Matched data: %.0f bytes\n", 
00112                        (double)stats.matched_data);
00113                 rprintf(FINFO,"File list size: %d\n", stats.flist_size);
00114                 rprintf(FINFO,"Total bytes written: %.0f\n", 
00115                        (double)stats.total_written);
00116                 rprintf(FINFO,"Total bytes read: %.0f\n\n", 
00117                        (double)stats.total_read);
00118         }
00119         
00120         if (verbose || do_stats) {
00121                 rprintf(FINFO,"wrote %.0f bytes  read %.0f bytes  %.2f bytes/sec\n",
00122                        (double)stats.total_written,
00123                        (double)stats.total_read,
00124                        (stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
00125                 rprintf(FINFO,"total size is %.0f  speedup is %.2f\n",
00126                        (double)stats.total_size,
00127                        (1.0*stats.total_size)/(stats.total_written+stats.total_read));
00128         }
00129 
00130         fflush(stdout);
00131         fflush(stderr);
00132 }

pid_t do_cmd char *    cmd,
char *    machine,
char *    user,
char *    path,
int *    f_in,
int *    f_out
[static]
 

Definition at line 168 of file main.c.

References blocking_io, child_main(), create_flist_from_batch(), FINFO, getenv(), local_child(), local_server, out_of_memory(), piped_child(), rprintf(), rsync_path, server_options(), strdup(), and verbose.

Referenced by start_client().

00169 {
00170         char *args[100];
00171         int i,argc=0;
00172         pid_t ret;
00173         char *tok,*dir=NULL;
00174         extern int local_server;
00175         extern char *rsync_path;
00176         extern int blocking_io;
00177         extern int read_batch;
00178 
00179         if (!read_batch && !local_server) {
00180                 if (!cmd)
00181                         cmd = getenv(RSYNC_RSH_ENV);
00182                 if (!cmd)
00183                         cmd = RSYNC_RSH;
00184                 cmd = strdup(cmd);
00185                 if (!cmd) 
00186                         goto oom;
00187 
00188                 for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
00189                         args[argc++] = tok;
00190                 }
00191 
00192 #if HAVE_REMSH
00193                 /* remsh (on HPUX) takes the arguments the other way around */
00194                 args[argc++] = machine;
00195                 if (user) {
00196                         args[argc++] = "-l";
00197                         args[argc++] = user;
00198                 }
00199 #else
00200                 if (user) {
00201                         args[argc++] = "-l";
00202                         args[argc++] = user;
00203                 }
00204                 args[argc++] = machine;
00205 #endif
00206 
00207                 args[argc++] = rsync_path;
00208 
00209                 if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
00210                         blocking_io = 1;
00211 
00212                 server_options(args,&argc);
00213 
00214         }
00215 
00216         args[argc++] = ".";
00217 
00218         if (path && *path) 
00219                 args[argc++] = path;
00220 
00221         args[argc] = NULL;
00222 
00223         if (verbose > 3) {
00224                 rprintf(FINFO,"cmd=");
00225                 for (i=0;i<argc;i++)
00226                         rprintf(FINFO,"%s ",args[i]);
00227                 rprintf(FINFO,"\n");
00228         }
00229 
00230         if (local_server) {
00231                 if (read_batch)
00232                     create_flist_from_batch(); /* sets batch_flist */
00233                 ret = local_child(argc, args, f_in, f_out, child_main);
00234         } else {
00235                 ret = piped_child(args,f_in,f_out);
00236         }
00237 
00238         if (dir) free(dir);
00239 
00240         return ret;
00241 
00242 oom:
00243         out_of_memory("do_cmd");
00244         return 0; /* not reached */
00245 }

char* get_local_name struct file_list   flist,
char *    name
[static]
 

Definition at line 250 of file main.c.

References file_list::count, do_mkdir(), do_stat(), FERROR, FINFO, orig_umask, push_dir(), rprintf(), and verbose.

Referenced by client_run(), and do_server_recv().

00251 {
00252         STRUCT_STAT st;
00253         extern int orig_umask;
00254 
00255         if (verbose > 2)
00256                 rprintf(FINFO,"get_local_name count=%d %s\n", 
00257                         flist->count, NS(name));
00258 
00259         if (!name) 
00260                 return NULL;
00261 
00262         if (do_stat(name,&st) == 0) {
00263                 if (S_ISDIR(st.st_mode)) {
00264                         if (!push_dir(name, 0)) {
00265                                 rprintf(FERROR,"push_dir %s : %s (1)\n",
00266                                         name,strerror(errno));
00267                                 exit_cleanup(RERR_FILESELECT);
00268                         }
00269                         return NULL;
00270                 }
00271                 if (flist->count > 1) {
00272                         rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
00273                         exit_cleanup(RERR_FILESELECT);
00274                 }
00275                 return name;
00276         }
00277 
00278         if (flist->count <= 1)
00279                 return name;
00280 
00281         if (do_mkdir(name,0777 & ~orig_umask) != 0) {
00282                 rprintf(FERROR, RSYNC_NAME ": mkdir %s: %s\n",
00283                         name, strerror(errno));
00284                 exit_cleanup(RERR_FILEIO);
00285         } else {
00286                 if (verbose > 0)
00287                         rprintf(FINFO,"created directory %s\n",name);
00288         }
00289 
00290         if (!push_dir(name, 0)) {
00291                 rprintf(FERROR, RSYNC_NAME ": push_dir %s: %s\n",
00292                         name, strerror(errno));
00293                 exit_cleanup(RERR_FILESELECT);
00294         }
00295 
00296         return NULL;
00297 }

void do_server_sender int    f_in,
int    f_out,
int    argc,
char *    argv[]
[static]
 

Definition at line 302 of file main.c.

References file_list::count, FERROR, FINFO, io_flush(), push_dir(), read_int(), report(), rprintf(), send_file_list(), send_files(), and verbose.

Referenced by start_server().

00303 {
00304         int i;
00305         struct file_list *flist;
00306         char *dir = argv[0];
00307         extern int relative_paths;
00308         extern int recurse;
00309         extern int remote_version;
00310 
00311         if (verbose > 2)
00312                 rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
00313   
00314         if (!relative_paths && !push_dir(dir, 0)) {
00315                 rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
00316                 exit_cleanup(RERR_FILESELECT);
00317         }
00318         argc--;
00319         argv++;
00320   
00321         if (strcmp(dir,".")) {
00322                 int l = strlen(dir);
00323                 if (strcmp(dir,"/") == 0) 
00324                         l = 0;
00325                 for (i=0;i<argc;i++)
00326                         argv[i] += l+1;
00327         }
00328 
00329         if (argc == 0 && recurse) {
00330                 argc=1;
00331                 argv--;
00332                 argv[0] = ".";
00333         }
00334         
00335         flist = send_file_list(f_out,argc,argv);
00336         if (!flist || flist->count == 0) {
00337                 exit_cleanup(0);
00338         }
00339 
00340         send_files(flist,f_out,f_in);
00341         io_flush();
00342         report(f_out);
00343         if (remote_version >= 24) {
00344                 /* final goodbye message */             
00345                 read_int(f_in);
00346         }
00347         io_flush();
00348         exit_cleanup(0);
00349 }

int do_recv int    f_in,
int    f_out,
struct file_list   flist,
char *    local_name
[static]
 

Definition at line 352 of file main.c.

References file_list::count, delete_after, delete_files(), do_fork(), fd_pair(), FERROR, generate_files(), init_hard_links(), io_flush(), io_multiplexing_close(), io_set_error_fd(), io_start_buffering(), msleep(), read_int(), recv_files(), report(), rprintf(), set_error_fd(), wait_process(), and write_int().

Referenced by client_run(), and do_server_recv().

00353 {
00354         int pid;
00355         int status=0;
00356         int recv_pipe[2];
00357         int error_pipe[2];
00358         extern int preserve_hard_links;
00359         extern int delete_after;
00360         extern int recurse;
00361         extern int delete_mode;
00362         extern int remote_version;
00363 
00364         if (preserve_hard_links)
00365                 init_hard_links(flist);
00366 
00367         if (!delete_after) {
00368                 /* I moved this here from recv_files() to prevent a race condition */
00369                 if (recurse && delete_mode && !local_name && flist->count>0) {
00370                         delete_files(flist);
00371                 }
00372         }
00373 
00374         if (fd_pair(recv_pipe) < 0) {
00375                 rprintf(FERROR,"pipe failed in do_recv\n");
00376                 exit_cleanup(RERR_SOCKETIO);
00377         }
00378 
00379         if (fd_pair(error_pipe) < 0) {
00380                 rprintf(FERROR,"error pipe failed in do_recv\n");
00381                 exit_cleanup(RERR_SOCKETIO);
00382         }
00383   
00384         io_flush();
00385 
00386         if ((pid=do_fork()) == 0) {
00387                 close(recv_pipe[0]);
00388                 close(error_pipe[0]);
00389                 if (f_in != f_out) close(f_out);
00390 
00391                 /* we can't let two processes write to the socket at one time */
00392                 io_multiplexing_close();
00393 
00394                 /* set place to send errors */
00395                 set_error_fd(error_pipe[1]);
00396 
00397                 recv_files(f_in,flist,local_name,recv_pipe[1]);
00398                 io_flush();
00399                 report(f_in);
00400 
00401                 write_int(recv_pipe[1],1);
00402                 close(recv_pipe[1]);
00403                 io_flush();
00404                 /* finally we go to sleep until our parent kills us
00405                    with a USR2 signal. We sleep for a short time as on
00406                    some OSes a signal won't interrupt a sleep! */
00407                 while (msleep(20))
00408                         ;
00409         }
00410 
00411         close(recv_pipe[1]);
00412         close(error_pipe[1]);
00413         if (f_in != f_out) close(f_in);
00414 
00415         io_start_buffering(f_out);
00416 
00417         io_set_error_fd(error_pipe[0]);
00418 
00419         generate_files(f_out,flist,local_name,recv_pipe[0]);
00420 
00421         read_int(recv_pipe[0]);
00422         close(recv_pipe[0]);
00423         if (remote_version >= 24) {
00424                 /* send a final goodbye message */
00425                 write_int(f_out, -1);
00426         }
00427         io_flush();
00428 
00429         kill(pid, SIGUSR2);
00430         wait_process(pid, &status);
00431         return status;
00432 }

void do_server_recv int    f_in,
int    f_out,
int    argc,
char *    argv[]
[static]
 

Definition at line 435 of file main.c.

References am_daemon, am_sender, delete_excluded, do_recv(), FERROR, FINFO, get_local_name(), push_dir(), recv_exclude_list(), recv_file_list(), rprintf(), and verbose.

Referenced by start_server().

00436 {
00437         int status;
00438         struct file_list *flist;
00439         char *local_name=NULL;
00440         char *dir = NULL;
00441         extern int delete_mode;
00442         extern int delete_excluded;
00443         extern int am_daemon;
00444         extern int module_id;
00445         extern int am_sender;
00446         extern int read_batch;
00447         extern struct file_list *batch_flist;
00448 
00449         if (verbose > 2)
00450                 rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
00451 
00452         if (am_daemon && lp_read_only(module_id) && !am_sender) {
00453                 rprintf(FERROR,"ERROR: module is read only\n");
00454                 exit_cleanup(RERR_SYNTAX);
00455                 return;
00456         }
00457 
00458         
00459         if (argc > 0) {
00460                 dir = argv[0];
00461                 argc--;
00462                 argv++;
00463                 if (!am_daemon && !push_dir(dir, 0)) {
00464                         rprintf(FERROR,"push_dir %s : %s (4)\n",
00465                                 dir,strerror(errno));
00466                         exit_cleanup(RERR_FILESELECT);
00467                 }    
00468         }
00469 
00470         if (delete_mode && !delete_excluded)
00471                 recv_exclude_list(f_in);
00472 
00473         if (read_batch)
00474             flist = batch_flist;
00475         else
00476             flist = recv_file_list(f_in);
00477         if (!flist) {
00478                 rprintf(FERROR,"server_recv: recv_file_list error\n");
00479                 exit_cleanup(RERR_FILESELECT);
00480         }
00481         
00482         if (argc > 0) {    
00483                 if (strcmp(dir,".")) {
00484                         argv[0] += strlen(dir);
00485                         if (argv[0][0] == '/') argv[0]++;
00486                 }
00487                 local_name = get_local_name(flist,argv[0]);
00488         }
00489 
00490         status = do_recv(f_in,f_out,flist,local_name);
00491         exit_cleanup(status);
00492 }

int child_main int    argc,
char *    argv[]
 

Definition at line 495 of file main.c.

References start_server().

Referenced by do_cmd(), and local_child().

00496 {
00497         start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
00498         return 0;
00499 }

void start_server int    f_in,
int    f_out,
int    argc,
char *    argv[]
 

Definition at line 502 of file main.c.

References add_cvs_excludes(), am_sender, do_server_recv(), do_server_sender(), io_start_multiplex_out(), recv_exclude_list(), set_nonblocking(), and setup_protocol().

Referenced by child_main(), main(), and rsync_module().

00503 {
00504         extern int cvs_exclude;
00505         extern int am_sender;
00506         extern int remote_version;
00507         extern int read_batch;
00508 
00509         setup_protocol(f_out, f_in);
00510 
00511         set_nonblocking(f_in);
00512         set_nonblocking(f_out);
00513 
00514         if (remote_version >= 23)
00515                 io_start_multiplex_out(f_out);
00516 
00517         if (am_sender) {
00518                 if (!read_batch) {
00519                     recv_exclude_list(f_in);
00520                     if (cvs_exclude)
00521                         add_cvs_excludes();
00522                 }
00523                 do_server_sender(f_in, f_out, argc, argv);
00524         } else {
00525                 do_server_recv(f_in, f_out, argc, argv);
00526         }
00527         exit_cleanup(0);
00528 }

int client_run int    f_in,
int    f_out,
pid_t    pid,
int    argc,
char *    argv[]
 

Definition at line 535 of file main.c.

References add_cvs_excludes(), am_sender, cleanup_child_pid, file_list::count, delete_excluded, do_recv(), FINFO, get_local_name(), io_flush(), io_start_multiplex_in(), read_int(), recv_file_list(), report(), rprintf(), send_exclude_list(), send_file_list(), send_files(), set_nonblocking(), setup_protocol(), verbose, and wait_process().

Referenced by start_client(), and start_socket_client().

00536 {
00537         struct file_list *flist = NULL;
00538         int status = 0, status2 = 0;
00539         char *local_name = NULL;
00540         extern int am_sender;
00541         extern int remote_version;
00542         extern pid_t cleanup_child_pid;
00543         extern int write_batch;
00544         extern int read_batch;
00545         extern struct file_list *batch_flist;
00546 
00547         cleanup_child_pid = pid;
00548         if (read_batch)
00549             flist = batch_flist;
00550 
00551         set_nonblocking(f_in);
00552         set_nonblocking(f_out);
00553 
00554         setup_protocol(f_out,f_in);
00555 
00556         if (remote_version >= 23)
00557                 io_start_multiplex_in(f_in);
00558         
00559         if (am_sender) {
00560                 extern int cvs_exclude;
00561                 extern int delete_mode;
00562                 extern int delete_excluded;
00563                 if (cvs_exclude)
00564                         add_cvs_excludes();
00565                 if (delete_mode && !delete_excluded) 
00566                         send_exclude_list(f_out);
00567                 if (!read_batch) /*  dw -- don't write to pipe */
00568                     flist = send_file_list(f_out,argc,argv);
00569                 if (verbose > 3) 
00570                         rprintf(FINFO,"file list sent\n");
00571 
00572                 send_files(flist,f_out,f_in);
00573                 if (remote_version >= 24) {
00574                         /* final goodbye message */             
00575                         read_int(f_in);
00576                 }
00577                 if (pid != -1) {
00578                         if (verbose > 3)
00579                                 rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
00580                         io_flush();
00581                         wait_process(pid, &status);
00582                 }
00583                 report(-1);
00584                 exit_cleanup(status);
00585         }
00586 
00587         if (argc == 0) {
00588                 extern int list_only;
00589                 list_only = 1;
00590         }
00591         
00592         if (!write_batch)
00593             send_exclude_list(f_out);
00594         
00595         flist = recv_file_list(f_in);
00596         if (!flist || flist->count == 0) {
00597                 rprintf(FINFO, "client: nothing to do: "
00598                         "perhaps you need to specify some filenames or "
00599                         "the --recursive option?\n");
00600                 exit_cleanup(0);
00601         }
00602         
00603         local_name = get_local_name(flist,argv[0]);
00604         
00605         status2 = do_recv(f_in,f_out,flist,local_name);
00606         
00607         if (pid != -1) {
00608                 if (verbose > 3)
00609                         rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
00610                 io_flush();
00611                 wait_process(pid, &status);
00612         }
00613         
00614         return MAX(status, status2);
00615 }

char* find_colon char *    s [static]
 

Definition at line 617 of file main.c.

Referenced by start_client().

00618 {
00619         char *p, *p2;
00620 
00621         p = strchr(s,':');
00622         if (!p) return NULL;
00623         
00624         /* now check to see if there is a / in the string before the : - if there is then
00625            discard the colon on the assumption that the : is part of a filename */
00626         p2 = strchr(s,'/');
00627         if (p2 && p2 < p) return NULL;
00628 
00629         return p;
00630 }

int copy_argv char *    argv[] [static]
 

Definition at line 633 of file main.c.

References FERROR, rprintf(), and strdup().

Referenced by start_client().

00634 {
00635         int i;
00636 
00637         for (i = 0; argv[i]; i++) {
00638                 if (!(argv[i] = strdup(argv[i]))) {
00639                         rprintf (FERROR, "out of memory at %s(%d)\n",
00640                                  __FILE__, __LINE__);
00641                         return RERR_MALLOC;
00642                 }
00643         }
00644 
00645         return 0;
00646 }

int start_client int    argc,
char *    argv[]
[static]
 

Start a client for either type of remote connection.

Work out whether the arguments request a remote shell or rsyncd connection, and call the appropriate connection function, then run_client.

Calls either start_socket_client (for sockets) or do_cmd and client_run (for ssh).

Definition at line 657 of file main.c.

References am_sender, client_run(), copy_argv(), do_cmd(), FERROR, find_colon(), FINFO, host, local_server, rprintf(), shell_cmd, start_socket_client(), usage(), and verbose.

Referenced by main().

00658 {
00659         char *p;
00660         char *shell_machine = NULL;
00661         char *shell_path = NULL;
00662         char *shell_user = NULL;
00663         int ret;
00664         pid_t pid;
00665         int f_in,f_out;
00666         extern int local_server;
00667         extern int am_sender;
00668         extern char *shell_cmd;
00669         extern int rsync_port;
00670         extern int read_batch;
00671         int rc;
00672 
00673         /* Don't clobber argv[] so that ps(1) can still show the right
00674            command line. */
00675         if ((rc = copy_argv (argv)))
00676                 return rc;
00677 
00678         if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
00679                 char *host, *path;
00680 
00681                 host = argv[0] + strlen(URL_PREFIX);
00682                 p = strchr(host,'/');
00683                 if (p) {
00684                         *p = 0;
00685                         path = p+1;
00686                 } else {
00687                         path="";
00688                 }
00689                 p = strchr(host,':');
00690                 if (p) {
00691                         rsync_port = atoi(p+1);
00692                         *p = 0;
00693                 }
00694                 return start_socket_client(host, path, argc-1, argv+1);
00695         }
00696 
00697         if (!read_batch) {
00698             p = find_colon(argv[0]);
00699 
00700         if (p) {
00701                 if (p[1] == ':') { /* double colon */
00702                         *p = 0;
00703                         return start_socket_client(argv[0], p+2, argc-1, argv+1);
00704                 }
00705 
00706                 if (argc < 1) {
00707                         usage(FERROR);
00708                         exit_cleanup(RERR_SYNTAX);
00709                 }
00710 
00711                 am_sender = 0;
00712                 *p = 0;
00713                 shell_machine = argv[0];
00714                 shell_path = p+1;
00715                 argc--;
00716                 argv++;
00717         } else {
00718                 am_sender = 1;
00719 
00720                 p = find_colon(argv[argc-1]);
00721                 if (!p) {
00722                         local_server = 1;
00723                 } else if (p[1] == ':') {
00724                         *p = 0;
00725                         return start_socket_client(argv[argc-1], p+2, argc-1, argv);
00726                 }
00727 
00728                 if (argc < 2) {
00729                         usage(FERROR);
00730                         exit_cleanup(RERR_SYNTAX);
00731                 }
00732                 
00733                 if (local_server) {
00734                         shell_machine = NULL;
00735                         shell_path = argv[argc-1];
00736                 } else {
00737                         *p = 0;
00738                         shell_machine = argv[argc-1];
00739                         shell_path = p+1;
00740                 }
00741                 argc--;
00742         }
00743         } else {
00744             am_sender = 1;
00745             local_server = 1;
00746             shell_path = argv[argc-1];
00747         }
00748 
00749         if (shell_machine) {
00750                 p = strchr(shell_machine,'@');
00751                 if (p) {
00752                         *p = 0;
00753                         shell_user = shell_machine;
00754                         shell_machine = p+1;
00755                 }
00756         }
00757 
00758         if (verbose > 3) {
00759                 rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
00760                         shell_cmd?shell_cmd:"",
00761                         shell_machine?shell_machine:"",
00762                         shell_user?shell_user:"",
00763                         shell_path?shell_path:"");
00764         }
00765         
00766         if (!am_sender && argc > 1) {
00767                 usage(FERROR);
00768                 exit_cleanup(RERR_SYNTAX);
00769         }
00770 
00771         if (argc == 0 && !am_sender) {
00772                 extern int list_only;
00773                 list_only = 1;
00774         }
00775         
00776         pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
00777         
00778         ret = client_run(f_in, f_out, pid, argc, argv);
00779 
00780         fflush(stdout);
00781         fflush(stderr);
00782 
00783         return ret;
00784 }

RETSIGTYPE sigusr1_handler int UNUSED(val)    [static]
 

Definition at line 787 of file main.c.

Referenced by main().

00787                                                    {
00788         exit_cleanup(RERR_SIGNAL);
00789 }

RETSIGTYPE sigusr2_handler int UNUSED(val)    [static]
 

Definition at line 791 of file main.c.

References log_got_error.

Referenced by main().

00791                                                    {
00792         extern int log_got_error;
00793         if (log_got_error) _exit(RERR_PARTIAL);
00794         _exit(0);
00795 }

RETSIGTYPE sigchld_handler int UNUSED(val)    [static]
 

Definition at line 797 of file main.c.

References waitpid().

Referenced by main().

00797                                                    {
00798 #ifdef WNOHANG
00799         while (waitpid(-1, NULL, WNOHANG) > 0) ;
00800 #endif
00801 }

const char* get_panic_action void   
 

This routine catches signals and tries to send them to gdb.

Because it's called from inside a signal handler it ought not to use too many library routines.

Todo:
Perhaps use "screen -X" instead/as well, to help people debugging without easy access to X. Perhaps use an environment variable, or just call a script?

The /proc/ magic probably only works on Linux (and Solaris?) Can we be more portable?

Definition at line 818 of file main.c.

References getenv().

Referenced by print_rsync_version(), and rsync_panic_handler().

00819 {
00820         const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
00821 
00822         if (cmd_fmt)
00823                 return cmd_fmt;
00824         else
00825                 return "xterm -display :0 -T Panic -n Panic "
00826                         "-e gdb /proc/%d/exe %d";
00827 }

RETSIGTYPE rsync_panic_handler int UNUSED(whatsig)    [static]
 

Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.

This signal handler is only installed if we were configured with --enable-maintainer-mode. Perhaps it should always be on and we should just look at the environment variable, but I'm a bit leery of a signal sending us into a busy loop.

Definition at line 838 of file main.c.

References get_panic_action(), and sprintf().

Referenced by main().

00839 {
00840         char cmd_buf[300];
00841         int ret;
00842 
00843         sprintf(cmd_buf, get_panic_action(),
00844                 getpid(), getpid());
00845 
00846         /* Unless we failed to execute gdb, we allow the process to
00847          * continue.  I'm not sure if that's right. */
00848         ret = system(cmd_buf);
00849         if (ret)
00850                 _exit(ret);
00851 }

int main int    argc,
char *    argv[]
 

Definition at line 855 of file main.c.

References am_daemon, daemon_main(), FERROR, option_error(), orig_umask, parse_arguments(), push_dir(), rprintf(), rsync_panic_handler(), set_nonblocking(), sig_int(), sigchld_handler(), sigusr1_handler(), sigusr2_handler(), start_client(), start_server(), starttime, usage(), verbose, and write_batch_argvs_file().

00856 {       
00857         extern int am_root;
00858         extern int orig_umask;
00859         extern int dry_run;
00860         extern int am_daemon;
00861         extern int am_server;
00862         int ret;
00863         extern int write_batch;
00864         int orig_argc;
00865         char **orig_argv;
00866 
00867         orig_argc = argc;
00868         orig_argv = argv;
00869 
00870         signal(SIGUSR1, sigusr1_handler);
00871         signal(SIGUSR2, sigusr2_handler);
00872         signal(SIGCHLD, sigchld_handler);
00873 #ifdef MAINTAINER_MODE
00874         signal(SIGSEGV, rsync_panic_handler);
00875         signal(SIGFPE, rsync_panic_handler);
00876         signal(SIGABRT, rsync_panic_handler);
00877         signal(SIGBUS, rsync_panic_handler);
00878 #endif /* def MAINTAINER_MODE */
00879 
00880         starttime = time(NULL);
00881         am_root = (getuid() == 0);
00882 
00883         memset(&stats, 0, sizeof(stats));
00884 
00885         if (argc < 2) {
00886                 usage(FERROR);
00887                 exit_cleanup(RERR_SYNTAX);
00888         }
00889 
00890         /* we set a 0 umask so that correct file permissions can be
00891            carried across */
00892         orig_umask = (int)umask(0);
00893 
00894         if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
00895                 /* FIXME: We ought to call the same error-handling
00896                  * code here, rather than relying on getopt. */
00897                 option_error();
00898                 exit_cleanup(RERR_SYNTAX);
00899         }
00900 
00901         signal(SIGINT,SIGNAL_CAST sig_int);
00902         signal(SIGHUP,SIGNAL_CAST sig_int);
00903         signal(SIGTERM,SIGNAL_CAST sig_int);
00904 
00905         /* Ignore SIGPIPE; we consistently check error codes and will
00906          * see the EPIPE. */
00907         signal(SIGPIPE, SIG_IGN);
00908 
00909         /* Initialize push_dir here because on some old systems getcwd
00910            (implemented by forking "pwd" and reading its output) doesn't
00911            work when there are other child processes.  Also, on all systems
00912            that implement getcwd that way "pwd" can't be found after chroot. */
00913         push_dir(NULL,0);
00914 
00915         if (write_batch && !am_server) {
00916             write_batch_argvs_file(orig_argc, orig_argv);
00917         }
00918 
00919         if (am_daemon) {
00920                 return daemon_main();
00921         }
00922 
00923         if (argc < 1) {
00924                 usage(FERROR);
00925                 exit_cleanup(RERR_SYNTAX);
00926         }
00927 
00928         if (dry_run)
00929                 verbose = MAX(verbose,1);
00930 
00931 #ifndef SUPPORT_LINKS
00932         if (!am_server && preserve_links) {
00933                 rprintf(FERROR,"ERROR: symbolic links not supported\n");
00934                 exit_cleanup(RERR_UNSUPPORTED);
00935         }
00936 #endif
00937 
00938         if (am_server) {
00939                 set_nonblocking(STDIN_FILENO);
00940                 set_nonblocking(STDOUT_FILENO);
00941                 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
00942         }
00943 
00944         ret = start_client(argc, argv);
00945         if (ret == -1) 
00946                 exit_cleanup(RERR_STARTCLIENT);
00947         else
00948                 exit_cleanup(ret);
00949 
00950         exit(ret);
00951         /* NOTREACHED */
00952 }


Variable Documentation

time_t starttime = 0
 

Definition at line 24 of file main.c.

Referenced by main(), and report().

struct stats stats
 

Definition at line 26 of file main.c.

int verbose
 

Definition at line 27 of file main.c.

Referenced by client_run(), do_cmd(), do_server_recv(), do_server_sender(), get_local_name(), main(), report(), and start_client().


Generated on Tue Apr 16 12:37:38 2002 for rsync by doxygen1.2.15