Annotation of embedaddon/rsync/main.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * The startup routines, including main(), for rsync.
                      3:  *
                      4:  * Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
                      5:  * Copyright (C) 1996 Paul Mackerras
                      6:  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
1.1.1.2 ! misho       7:  * Copyright (C) 2003-2013 Wayne Davison
1.1       misho       8:  *
                      9:  * This program is free software; you can redistribute it and/or modify
                     10:  * it under the terms of the GNU General Public License as published by
                     11:  * the Free Software Foundation; either version 3 of the License, or
                     12:  * (at your option) any later version.
                     13:  *
                     14:  * This program is distributed in the hope that it will be useful,
                     15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17:  * GNU General Public License for more details.
                     18:  *
                     19:  * You should have received a copy of the GNU General Public License along
                     20:  * with this program; if not, visit the http://fsf.org website.
                     21:  */
                     22: 
                     23: #include "rsync.h"
1.1.1.2 ! misho      24: #include "inums.h"
1.1       misho      25: #include "io.h"
                     26: #if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
                     27: #include <locale.h>
                     28: #endif
                     29: 
1.1.1.2 ! misho      30: extern int force_change;
1.1       misho      31: extern int dry_run;
                     32: extern int list_only;
1.1.1.2 ! misho      33: extern int io_timeout;
1.1       misho      34: extern int am_root;
                     35: extern int am_server;
                     36: extern int am_sender;
                     37: extern int am_daemon;
                     38: extern int inc_recurse;
                     39: extern int blocking_io;
1.1.1.2 ! misho      40: extern int always_checksum;
1.1       misho      41: extern int remove_source_files;
1.1.1.2 ! misho      42: extern int output_needs_newline;
1.1       misho      43: extern int need_messages_from_generator;
                     44: extern int kluge_around_eof;
                     45: extern int got_xfer_error;
1.1.1.2 ! misho      46: extern int msgs2stderr;
1.1       misho      47: extern int module_id;
1.1.1.2 ! misho      48: extern int read_only;
1.1       misho      49: extern int copy_links;
                     50: extern int copy_dirlinks;
                     51: extern int copy_unsafe_links;
                     52: extern int keep_dirlinks;
                     53: extern int preserve_hard_links;
                     54: extern int protocol_version;
                     55: extern int file_total;
                     56: extern int recurse;
                     57: extern int xfer_dirs;
                     58: extern int protect_args;
                     59: extern int relative_paths;
                     60: extern int sanitize_paths;
                     61: extern int curr_dir_depth;
                     62: extern int curr_dir_len;
                     63: extern int module_id;
                     64: extern int rsync_port;
                     65: extern int whole_file;
                     66: extern int read_batch;
                     67: extern int write_batch;
                     68: extern int batch_fd;
1.1.1.2 ! misho      69: extern int sock_f_in;
        !            70: extern int sock_f_out;
1.1       misho      71: extern int filesfrom_fd;
                     72: extern int connect_timeout;
1.1.1.2 ! misho      73: extern int send_msgs_to_gen;
1.1       misho      74: extern dev_t filesystem_dev;
                     75: extern pid_t cleanup_child_pid;
1.1.1.2 ! misho      76: extern size_t bwlimit_writemax;
1.1       misho      77: extern unsigned int module_dirlen;
1.1.1.2 ! misho      78: extern BOOL flist_receiving_enabled;
        !            79: extern BOOL shutting_down;
        !            80: extern int basis_dir_cnt;
1.1       misho      81: extern struct stats stats;
1.1.1.2 ! misho      82: extern char *stdout_format;
        !            83: extern char *logfile_format;
1.1       misho      84: extern char *filesfrom_host;
                     85: extern char *partial_dir;
                     86: extern char *dest_option;
                     87: extern char *rsync_path;
                     88: extern char *shell_cmd;
                     89: extern char *batch_name;
                     90: extern char *password_file;
1.1.1.2 ! misho      91: extern char *backup_dir;
1.1       misho      92: extern char curr_dir[MAXPATHLEN];
1.1.1.2 ! misho      93: extern char backup_dir_buf[MAXPATHLEN];
        !            94: extern char *basis_dir[MAX_BASIS_DIRS+1];
1.1       misho      95: extern struct file_list *first_flist;
1.1.1.2 ! misho      96: extern filter_rule_list daemon_filter_list;
1.1       misho      97: 
                     98: uid_t our_uid;
1.1.1.2 ! misho      99: gid_t our_gid;
1.1       misho     100: int am_receiver = 0;  /* Only set to 1 after the receiver/generator fork. */
                    101: int am_generator = 0; /* Only set to 1 after the receiver/generator fork. */
                    102: int local_server = 0;
                    103: int daemon_over_rsh = 0;
                    104: mode_t orig_umask = 0;
                    105: int batch_gen_fd = -1;
1.1.1.2 ! misho     106: int sender_keeps_checksum = 0;
1.1       misho     107: 
                    108: /* There's probably never more than at most 2 outstanding child processes,
                    109:  * but set it higher, just in case. */
                    110: #define MAXCHILDPROCS 7
                    111: 
                    112: #ifdef HAVE_SIGACTION
                    113: # ifdef HAVE_SIGPROCMASK
                    114: #  define SIGACTMASK(n,h) SIGACTION(n,h), sigaddset(&sigmask,(n))
                    115: # else
                    116: #  define SIGACTMASK(n,h) SIGACTION(n,h)
                    117: # endif
                    118: static struct sigaction sigact;
                    119: #endif
                    120: 
                    121: struct pid_status {
                    122:        pid_t pid;
                    123:        int status;
                    124: } pid_stat_table[MAXCHILDPROCS];
                    125: 
                    126: static time_t starttime, endtime;
                    127: static int64 total_read, total_written;
                    128: 
                    129: static void show_malloc_stats(void);
                    130: 
                    131: /* Works like waitpid(), but if we already harvested the child pid in our
                    132:  * remember_children(), we succeed instead of returning an error. */
                    133: pid_t wait_process(pid_t pid, int *status_ptr, int flags)
                    134: {
                    135:        pid_t waited_pid;
1.1.1.2 ! misho     136: 
1.1       misho     137:        do {
                    138:                waited_pid = waitpid(pid, status_ptr, flags);
                    139:        } while (waited_pid == -1 && errno == EINTR);
                    140: 
                    141:        if (waited_pid == -1 && errno == ECHILD) {
                    142:                /* Status of requested child no longer available:  check to
                    143:                 * see if it was processed by remember_children(). */
                    144:                int cnt;
                    145:                for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
                    146:                        if (pid == pid_stat_table[cnt].pid) {
                    147:                                *status_ptr = pid_stat_table[cnt].status;
                    148:                                pid_stat_table[cnt].pid = 0;
                    149:                                return pid;
                    150:                        }
                    151:                }
                    152:        }
                    153: 
                    154:        return waited_pid;
                    155: }
                    156: 
                    157: /* Wait for a process to exit, calling io_flush while waiting. */
                    158: static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
                    159: {
                    160:        pid_t waited_pid;
                    161:        int status;
                    162: 
                    163:        while ((waited_pid = wait_process(pid, &status, WNOHANG)) == 0) {
                    164:                msleep(20);
                    165:                io_flush(FULL_FLUSH);
                    166:        }
                    167: 
                    168:        /* TODO: If the child exited on a signal, then log an
                    169:         * appropriate error message.  Perhaps we should also accept a
                    170:         * message describing the purpose of the child.  Also indicate
                    171:         * this to the caller so that they know something went wrong. */
                    172:        if (waited_pid < 0) {
                    173:                rsyserr(FERROR, errno, "waitpid");
                    174:                *exit_code_ptr = RERR_WAITCHILD;
                    175:        } else if (!WIFEXITED(status)) {
                    176: #ifdef WCOREDUMP
                    177:                if (WCOREDUMP(status))
                    178:                        *exit_code_ptr = RERR_CRASHED;
                    179:                else
                    180: #endif
                    181:                if (WIFSIGNALED(status))
                    182:                        *exit_code_ptr = RERR_TERMINATED;
                    183:                else
                    184:                        *exit_code_ptr = RERR_WAITCHILD;
                    185:        } else
                    186:                *exit_code_ptr = WEXITSTATUS(status);
                    187: }
                    188: 
1.1.1.2 ! misho     189: void write_del_stats(int f)
        !           190: {
        !           191:        if (read_batch)
        !           192:                write_int(f, NDX_DEL_STATS);
        !           193:        else
        !           194:                write_ndx(f, NDX_DEL_STATS);
        !           195:        write_varint(f, stats.deleted_files - stats.deleted_dirs
        !           196:                      - stats.deleted_symlinks - stats.deleted_devices
        !           197:                      - stats.deleted_specials);
        !           198:        write_varint(f, stats.deleted_dirs);
        !           199:        write_varint(f, stats.deleted_symlinks);
        !           200:        write_varint(f, stats.deleted_devices);
        !           201:        write_varint(f, stats.deleted_specials);
        !           202: }
        !           203: 
        !           204: void read_del_stats(int f)
        !           205: {
        !           206:        stats.deleted_files = read_varint(f);
        !           207:        stats.deleted_files += stats.deleted_dirs = read_varint(f);
        !           208:        stats.deleted_files += stats.deleted_symlinks = read_varint(f);
        !           209:        stats.deleted_files += stats.deleted_devices = read_varint(f);
        !           210:        stats.deleted_files += stats.deleted_specials = read_varint(f);
        !           211: }
        !           212: 
1.1       misho     213: /* This function gets called from all 3 processes.  We want the client side
                    214:  * to actually output the text, but the sender is the only process that has
                    215:  * all the stats we need.  So, if we're a client sender, we do the report.
                    216:  * If we're a server sender, we write the stats on the supplied fd.  If
                    217:  * we're the client receiver we read the stats from the supplied fd and do
                    218:  * the report.  All processes might also generate a set of debug stats, if
                    219:  * the verbose level is high enough (this is the only thing that the
                    220:  * generator process and the server receiver ever do here). */
                    221: static void handle_stats(int f)
                    222: {
                    223:        endtime = time(NULL);
                    224: 
                    225:        /* Cache two stats because the read/write code can change it. */
                    226:        total_read = stats.total_read;
                    227:        total_written = stats.total_written;
                    228: 
1.1.1.2 ! misho     229:        if (INFO_GTE(STATS, 3)) {
1.1       misho     230:                /* These come out from every process */
                    231:                show_malloc_stats();
                    232:                show_flist_stats();
                    233:        }
                    234: 
                    235:        if (am_generator)
                    236:                return;
                    237: 
                    238:        if (am_daemon) {
                    239:                if (f == -1 || !am_sender)
                    240:                        return;
                    241:        }
                    242: 
                    243:        if (am_server) {
                    244:                if (am_sender) {
                    245:                        write_varlong30(f, total_read, 3);
                    246:                        write_varlong30(f, total_written, 3);
                    247:                        write_varlong30(f, stats.total_size, 3);
                    248:                        if (protocol_version >= 29) {
                    249:                                write_varlong30(f, stats.flist_buildtime, 3);
                    250:                                write_varlong30(f, stats.flist_xfertime, 3);
                    251:                        }
                    252:                }
                    253:                return;
                    254:        }
                    255: 
                    256:        /* this is the client */
                    257: 
                    258:        if (f < 0 && !am_sender) /* e.g. when we got an empty file list. */
                    259:                ;
                    260:        else if (!am_sender) {
                    261:                /* Read the first two in opposite order because the meaning of
                    262:                 * read/write swaps when switching from sender to receiver. */
                    263:                total_written = read_varlong30(f, 3);
                    264:                total_read = read_varlong30(f, 3);
                    265:                stats.total_size = read_varlong30(f, 3);
                    266:                if (protocol_version >= 29) {
                    267:                        stats.flist_buildtime = read_varlong30(f, 3);
                    268:                        stats.flist_xfertime = read_varlong30(f, 3);
                    269:                }
                    270:        } else if (write_batch) {
                    271:                /* The --read-batch process is going to be a client
                    272:                 * receiver, so we need to give it the stats. */
                    273:                write_varlong30(batch_fd, total_read, 3);
                    274:                write_varlong30(batch_fd, total_written, 3);
                    275:                write_varlong30(batch_fd, stats.total_size, 3);
                    276:                if (protocol_version >= 29) {
                    277:                        write_varlong30(batch_fd, stats.flist_buildtime, 3);
                    278:                        write_varlong30(batch_fd, stats.flist_xfertime, 3);
                    279:                }
                    280:        }
                    281: }
                    282: 
1.1.1.2 ! misho     283: static void output_itemized_counts(const char *prefix, int *counts)
        !           284: {
        !           285:        static char *labels[] = { "reg", "dir", "link", "dev", "special" };
        !           286:        char buf[1024], *pre = " (";
        !           287:        int j, len = 0;
        !           288:        int total = counts[0];
        !           289:        if (total) {
        !           290:                counts[0] -= counts[1] + counts[2] + counts[3] + counts[4];
        !           291:                for (j = 0; j < 5; j++) {
        !           292:                        if (counts[j]) {
        !           293:                                len += snprintf(buf+len, sizeof buf - len - 2,
        !           294:                                        "%s%s: %s",
        !           295:                                        pre, labels[j], comma_num(counts[j]));
        !           296:                                pre = ", ";
        !           297:                        }
        !           298:                }
        !           299:                buf[len++] = ')';
        !           300:        }
        !           301:        buf[len] = '\0';
        !           302:        rprintf(FINFO, "%s: %s%s\n", prefix, comma_num(total), buf);
        !           303: }
        !           304: 
1.1       misho     305: static void output_summary(void)
                    306: {
1.1.1.2 ! misho     307:        if (INFO_GTE(STATS, 2)) {
1.1       misho     308:                rprintf(FCLIENT, "\n");
1.1.1.2 ! misho     309:                output_itemized_counts("Number of files", &stats.num_files);
        !           310:                if (protocol_version >= 29)
        !           311:                        output_itemized_counts("Number of created files", &stats.created_files);
        !           312:                if (protocol_version >= 31)
        !           313:                        output_itemized_counts("Number of deleted files", &stats.deleted_files);
        !           314:                rprintf(FINFO,"Number of regular files transferred: %s\n",
        !           315:                        comma_num(stats.xferred_files));
1.1       misho     316:                rprintf(FINFO,"Total file size: %s bytes\n",
                    317:                        human_num(stats.total_size));
                    318:                rprintf(FINFO,"Total transferred file size: %s bytes\n",
                    319:                        human_num(stats.total_transferred_size));
                    320:                rprintf(FINFO,"Literal data: %s bytes\n",
                    321:                        human_num(stats.literal_data));
                    322:                rprintf(FINFO,"Matched data: %s bytes\n",
                    323:                        human_num(stats.matched_data));
                    324:                rprintf(FINFO,"File list size: %s\n",
                    325:                        human_num(stats.flist_size));
                    326:                if (stats.flist_buildtime) {
                    327:                        rprintf(FINFO,
1.1.1.2 ! misho     328:                                "File list generation time: %s seconds\n",
        !           329:                                comma_dnum((double)stats.flist_buildtime / 1000, 3));
1.1       misho     330:                        rprintf(FINFO,
1.1.1.2 ! misho     331:                                "File list transfer time: %s seconds\n",
        !           332:                                comma_dnum((double)stats.flist_xfertime / 1000, 3));
1.1       misho     333:                }
                    334:                rprintf(FINFO,"Total bytes sent: %s\n",
                    335:                        human_num(total_written));
                    336:                rprintf(FINFO,"Total bytes received: %s\n",
                    337:                        human_num(total_read));
                    338:        }
                    339: 
1.1.1.2 ! misho     340:        if (INFO_GTE(STATS, 1)) {
1.1       misho     341:                rprintf(FCLIENT, "\n");
                    342:                rprintf(FINFO,
                    343:                        "sent %s bytes  received %s bytes  %s bytes/sec\n",
                    344:                        human_num(total_written), human_num(total_read),
                    345:                        human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
1.1.1.2 ! misho     346:                rprintf(FINFO, "total size is %s  speedup is %s%s\n",
1.1       misho     347:                        human_num(stats.total_size),
1.1.1.2 ! misho     348:                        comma_dnum((double)stats.total_size / (total_written+total_read), 2),
1.1       misho     349:                        write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : "");
                    350:        }
                    351: 
                    352:        fflush(stdout);
                    353:        fflush(stderr);
                    354: }
                    355: 
                    356: 
                    357: /**
                    358:  * If our C library can get malloc statistics, then show them to FINFO
                    359:  **/
                    360: static void show_malloc_stats(void)
                    361: {
                    362: #ifdef HAVE_MALLINFO
                    363:        struct mallinfo mi;
                    364: 
                    365:        mi = mallinfo();
                    366: 
                    367:        rprintf(FCLIENT, "\n");
                    368:        rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
1.1.1.2 ! misho     369:                (int)getpid(), am_server ? "server " : "",
1.1       misho     370:                am_daemon ? "daemon " : "", who_am_i());
                    371:        rprintf(FINFO, "  arena:     %10ld   (bytes from sbrk)\n",
                    372:                (long)mi.arena);
                    373:        rprintf(FINFO, "  ordblks:   %10ld   (chunks not in use)\n",
                    374:                (long)mi.ordblks);
                    375:        rprintf(FINFO, "  smblks:    %10ld\n",
                    376:                (long)mi.smblks);
                    377:        rprintf(FINFO, "  hblks:     %10ld   (chunks from mmap)\n",
                    378:                (long)mi.hblks);
                    379:        rprintf(FINFO, "  hblkhd:    %10ld   (bytes from mmap)\n",
                    380:                (long)mi.hblkhd);
                    381:        rprintf(FINFO, "  allmem:    %10ld   (bytes from sbrk + mmap)\n",
                    382:                (long)mi.arena + mi.hblkhd);
                    383:        rprintf(FINFO, "  usmblks:   %10ld\n",
                    384:                (long)mi.usmblks);
                    385:        rprintf(FINFO, "  fsmblks:   %10ld\n",
                    386:                (long)mi.fsmblks);
                    387:        rprintf(FINFO, "  uordblks:  %10ld   (bytes used)\n",
                    388:                (long)mi.uordblks);
                    389:        rprintf(FINFO, "  fordblks:  %10ld   (bytes free)\n",
                    390:                (long)mi.fordblks);
                    391:        rprintf(FINFO, "  keepcost:  %10ld   (bytes in releasable chunk)\n",
                    392:                (long)mi.keepcost);
                    393: #endif /* HAVE_MALLINFO */
                    394: }
                    395: 
                    396: 
                    397: /* Start the remote shell.   cmd may be NULL to use the default. */
                    398: static pid_t do_cmd(char *cmd, char *machine, char *user, char **remote_argv, int remote_argc,
                    399:                    int *f_in_p, int *f_out_p)
                    400: {
                    401:        int i, argc = 0;
1.1.1.2 ! misho     402:        char *args[MAX_ARGS], *need_to_free = NULL;
1.1       misho     403:        pid_t pid;
                    404:        int dash_l_set = 0;
                    405: 
                    406:        if (!read_batch && !local_server) {
                    407:                char *t, *f, in_quote = '\0';
                    408:                char *rsh_env = getenv(RSYNC_RSH_ENV);
                    409:                if (!cmd)
                    410:                        cmd = rsh_env;
                    411:                if (!cmd)
                    412:                        cmd = RSYNC_RSH;
1.1.1.2 ! misho     413:                cmd = need_to_free = strdup(cmd);
1.1       misho     414:                if (!cmd)
                    415:                        goto oom;
                    416: 
                    417:                for (t = f = cmd; *f; f++) {
                    418:                        if (*f == ' ')
                    419:                                continue;
                    420:                        /* Comparison leaves rooms for server_options(). */
                    421:                        if (argc >= MAX_ARGS - MAX_SERVER_ARGS)
                    422:                                goto arg_overflow;
                    423:                        args[argc++] = t;
                    424:                        while (*f != ' ' || in_quote) {
                    425:                                if (!*f) {
                    426:                                        if (in_quote) {
                    427:                                                rprintf(FERROR,
                    428:                                                    "Missing trailing-%c in remote-shell command.\n",
                    429:                                                    in_quote);
                    430:                                                exit_cleanup(RERR_SYNTAX);
                    431:                                        }
                    432:                                        f--;
                    433:                                        break;
                    434:                                }
                    435:                                if (*f == '\'' || *f == '"') {
                    436:                                        if (!in_quote) {
                    437:                                                in_quote = *f++;
                    438:                                                continue;
                    439:                                        }
                    440:                                        if (*f == in_quote && *++f != in_quote) {
                    441:                                                in_quote = '\0';
                    442:                                                continue;
                    443:                                        }
                    444:                                }
                    445:                                *t++ = *f++;
                    446:                        }
                    447:                        *t++ = '\0';
                    448:                }
                    449: 
                    450:                /* check to see if we've already been given '-l user' in
                    451:                 * the remote-shell command */
                    452:                for (i = 0; i < argc-1; i++) {
                    453:                        if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
                    454:                                dash_l_set = 1;
                    455:                }
                    456: 
                    457: #ifdef HAVE_REMSH
                    458:                /* remsh (on HPUX) takes the arguments the other way around */
                    459:                args[argc++] = machine;
                    460:                if (user && !(daemon_over_rsh && dash_l_set)) {
                    461:                        args[argc++] = "-l";
                    462:                        args[argc++] = user;
                    463:                }
                    464: #else
                    465:                if (user && !(daemon_over_rsh && dash_l_set)) {
                    466:                        args[argc++] = "-l";
                    467:                        args[argc++] = user;
                    468:                }
                    469:                args[argc++] = machine;
                    470: #endif
                    471: 
                    472:                args[argc++] = rsync_path;
                    473: 
                    474:                if (blocking_io < 0) {
                    475:                        char *cp;
                    476:                        if ((cp = strrchr(cmd, '/')) != NULL)
                    477:                                cp++;
                    478:                        else
                    479:                                cp = cmd;
                    480:                        if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
                    481:                                blocking_io = 1;
                    482:                }
                    483: 
                    484:                server_options(args,&argc);
                    485: 
                    486:                if (argc >= MAX_ARGS - 2)
                    487:                        goto arg_overflow;
                    488:        }
                    489: 
                    490:        args[argc++] = ".";
                    491: 
                    492:        if (!daemon_over_rsh) {
                    493:                while (remote_argc > 0) {
                    494:                        if (argc >= MAX_ARGS - 1) {
                    495:                          arg_overflow:
                    496:                                rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
                    497:                                exit_cleanup(RERR_SYNTAX);
                    498:                        }
                    499:                        if (**remote_argv == '-') {
                    500:                                if (asprintf(args + argc++, "./%s", *remote_argv++) < 0)
                    501:                                        out_of_memory("do_cmd");
                    502:                        } else
                    503:                                args[argc++] = *remote_argv++;
                    504:                        remote_argc--;
                    505:                }
                    506:        }
                    507: 
                    508:        args[argc] = NULL;
                    509: 
1.1.1.2 ! misho     510:        if (DEBUG_GTE(CMD, 2)) {
1.1       misho     511:                for (i = 0; i < argc; i++)
                    512:                        rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]);
                    513:                rprintf(FCLIENT, "\n");
                    514:        }
                    515: 
                    516:        if (read_batch) {
                    517:                int from_gen_pipe[2];
                    518:                set_allow_inc_recurse();
                    519:                if (fd_pair(from_gen_pipe) < 0) {
                    520:                        rsyserr(FERROR, errno, "pipe");
                    521:                        exit_cleanup(RERR_IPC);
                    522:                }
                    523:                batch_gen_fd = from_gen_pipe[0];
                    524:                *f_out_p = from_gen_pipe[1];
                    525:                *f_in_p = batch_fd;
                    526:                pid = (pid_t)-1; /* no child pid */
                    527: #ifdef ICONV_CONST
                    528:                setup_iconv();
                    529: #endif
                    530:        } else if (local_server) {
                    531:                /* If the user didn't request --[no-]whole-file, force
                    532:                 * it on, but only if we're not batch processing. */
                    533:                if (whole_file < 0 && !write_batch)
                    534:                        whole_file = 1;
                    535:                set_allow_inc_recurse();
                    536:                pid = local_child(argc, args, f_in_p, f_out_p, child_main);
                    537: #ifdef ICONV_CONST
                    538:                setup_iconv();
                    539: #endif
                    540:        } else {
                    541:                pid = piped_child(args, f_in_p, f_out_p);
                    542: #ifdef ICONV_CONST
                    543:                setup_iconv();
                    544: #endif
                    545:                if (protect_args && !daemon_over_rsh)
                    546:                        send_protected_args(*f_out_p, args);
                    547:        }
                    548: 
1.1.1.2 ! misho     549:        if (need_to_free)
        !           550:                free(need_to_free);
        !           551: 
1.1       misho     552:        return pid;
                    553: 
                    554:   oom:
                    555:        out_of_memory("do_cmd");
                    556:        return 0; /* not reached */
                    557: }
                    558: 
                    559: /* The receiving side operates in one of two modes:
                    560:  *
                    561:  * 1. it receives any number of files into a destination directory,
                    562:  * placing them according to their names in the file-list.
                    563:  *
                    564:  * 2. it receives a single file and saves it using the name in the
                    565:  * destination path instead of its file-list name.  This requires a
                    566:  * "local name" for writing out the destination file.
                    567:  *
                    568:  * So, our task is to figure out what mode/local-name we need.
                    569:  * For mode 1, we change into the destination directory and return NULL.
                    570:  * For mode 2, we change into the directory containing the destination
                    571:  * file (if we aren't already there) and return the local-name. */
                    572: static char *get_local_name(struct file_list *flist, char *dest_path)
                    573: {
                    574:        STRUCT_STAT st;
                    575:        int statret;
                    576:        char *cp;
                    577: 
1.1.1.2 ! misho     578:        if (DEBUG_GTE(RECV, 1)) {
1.1       misho     579:                rprintf(FINFO, "get_local_name count=%d %s\n",
                    580:                        file_total, NS(dest_path));
                    581:        }
                    582: 
                    583:        if (!dest_path || list_only)
                    584:                return NULL;
                    585: 
                    586:        /* Treat an empty string as a copy into the current directory. */
                    587:        if (!*dest_path)
                    588:            dest_path = ".";
                    589: 
                    590:        if (daemon_filter_list.head) {
                    591:                char *slash = strrchr(dest_path, '/');
                    592:                if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
                    593:                        *slash = '\0';
                    594:                else
                    595:                        slash = NULL;
                    596:                if ((*dest_path != '.' || dest_path[1] != '\0')
                    597:                 && (check_filter(&daemon_filter_list, FLOG, dest_path, 0) < 0
                    598:                  || check_filter(&daemon_filter_list, FLOG, dest_path, 1) < 0)) {
                    599:                        rprintf(FERROR, "ERROR: daemon has excluded destination \"%s\"\n",
                    600:                                dest_path);
                    601:                        exit_cleanup(RERR_FILESELECT);
                    602:                }
                    603:                if (slash)
                    604:                        *slash = '/';
                    605:        }
                    606: 
                    607:        /* See what currently exists at the destination. */
                    608:        if ((statret = do_stat(dest_path, &st)) == 0) {
                    609:                /* If the destination is a dir, enter it and use mode 1. */
                    610:                if (S_ISDIR(st.st_mode)) {
                    611:                        if (!change_dir(dest_path, CD_NORMAL)) {
                    612:                                rsyserr(FERROR, errno, "change_dir#1 %s failed",
                    613:                                        full_fname(dest_path));
                    614:                                exit_cleanup(RERR_FILESELECT);
                    615:                        }
                    616:                        filesystem_dev = st.st_dev; /* ensures --force works right w/-x */
                    617:                        return NULL;
                    618:                }
                    619:                if (file_total > 1) {
                    620:                        rprintf(FERROR,
                    621:                                "ERROR: destination must be a directory when"
                    622:                                " copying more than 1 file\n");
                    623:                        exit_cleanup(RERR_FILESELECT);
                    624:                }
                    625:                if (file_total == 1 && S_ISDIR(flist->files[0]->mode)) {
                    626:                        rprintf(FERROR,
                    627:                                "ERROR: cannot overwrite non-directory"
                    628:                                " with a directory\n");
                    629:                        exit_cleanup(RERR_FILESELECT);
                    630:                }
                    631:        } else if (errno != ENOENT) {
                    632:                /* If we don't know what's at the destination, fail. */
                    633:                rsyserr(FERROR, errno, "ERROR: cannot stat destination %s",
                    634:                        full_fname(dest_path));
                    635:                exit_cleanup(RERR_FILESELECT);
                    636:        }
                    637: 
                    638:        cp = strrchr(dest_path, '/');
                    639: 
                    640:        /* If we need a destination directory because the transfer is not
                    641:         * of a single non-directory or the user has requested one via a
                    642:         * destination path ending in a slash, create one and use mode 1. */
                    643:        if (file_total > 1 || (cp && !cp[1])) {
                    644:                /* Lop off the final slash (if any). */
                    645:                if (cp && !cp[1])
                    646:                        *cp = '\0';
                    647: 
                    648:                if (statret == 0) {
                    649:                        rprintf(FERROR,
                    650:                            "ERROR: destination path is not a directory\n");
                    651:                        exit_cleanup(RERR_SYNTAX);
                    652:                }
                    653: 
1.1.1.2 ! misho     654:                if (do_mkdir(dest_path, ACCESSPERMS) != 0) {
1.1       misho     655:                        rsyserr(FERROR, errno, "mkdir %s failed",
                    656:                                full_fname(dest_path));
                    657:                        exit_cleanup(RERR_FILEIO);
                    658:                }
                    659: 
                    660:                if (flist->high >= flist->low
                    661:                 && strcmp(flist->files[flist->low]->basename, ".") == 0)
                    662:                        flist->files[0]->flags |= FLAG_DIR_CREATED;
                    663: 
1.1.1.2 ! misho     664:                if (INFO_GTE(NAME, 1))
1.1       misho     665:                        rprintf(FINFO, "created directory %s\n", dest_path);
                    666: 
                    667:                if (dry_run) {
                    668:                        /* Indicate that dest dir doesn't really exist. */
                    669:                        dry_run++;
                    670:                }
                    671: 
                    672:                if (!change_dir(dest_path, dry_run > 1 ? CD_SKIP_CHDIR : CD_NORMAL)) {
                    673:                        rsyserr(FERROR, errno, "change_dir#2 %s failed",
                    674:                                full_fname(dest_path));
                    675:                        exit_cleanup(RERR_FILESELECT);
                    676:                }
                    677: 
                    678:                return NULL;
                    679:        }
                    680: 
                    681:        /* Otherwise, we are writing a single file, possibly on top of an
                    682:         * existing non-directory.  Change to the item's parent directory
                    683:         * (if it has a path component), return the basename of the
                    684:         * destination file as the local name, and use mode 2. */
                    685:        if (!cp)
                    686:                return dest_path;
                    687: 
                    688:        if (cp == dest_path)
                    689:                dest_path = "/";
                    690: 
                    691:        *cp = '\0';
                    692:        if (!change_dir(dest_path, CD_NORMAL)) {
                    693:                rsyserr(FERROR, errno, "change_dir#3 %s failed",
                    694:                        full_fname(dest_path));
                    695:                exit_cleanup(RERR_FILESELECT);
                    696:        }
                    697:        *cp = '/';
                    698: 
                    699:        return cp + 1;
                    700: }
                    701: 
                    702: /* This function checks on our alternate-basis directories.  If we're in
                    703:  * dry-run mode and the destination dir does not yet exist, we'll try to
                    704:  * tweak any dest-relative paths to make them work for a dry-run (the
                    705:  * destination dir must be in curr_dir[] when this function is called).
                    706:  * We also warn about any arg that is non-existent or not a directory. */
                    707: static void check_alt_basis_dirs(void)
                    708: {
                    709:        STRUCT_STAT st;
1.1.1.2 ! misho     710:        char *slash = strrchr(curr_dir, '/');
        !           711:        int j;
1.1       misho     712: 
1.1.1.2 ! misho     713:        for (j = 0; j < basis_dir_cnt; j++) {
        !           714:                char *bdir = basis_dir[j];
        !           715:                int bd_len = strlen(bdir);
        !           716:                if (bd_len > 1 && bdir[bd_len-1] == '/')
        !           717:                        bdir[--bd_len] = '\0';
        !           718:                if (dry_run > 1 && *bdir != '/') {
        !           719:                        int len = curr_dir_len + 1 + bd_len + 1;
1.1       misho     720:                        char *new = new_array(char, len);
                    721:                        if (!new)
                    722:                                out_of_memory("check_alt_basis_dirs");
1.1.1.2 ! misho     723:                        if (slash && strncmp(bdir, "../", 3) == 0) {
1.1       misho     724:                            /* We want to remove only one leading "../" prefix for
                    725:                             * the directory we couldn't create in dry-run mode:
                    726:                             * this ensures that any other ".." references get
                    727:                             * evaluated the same as they would for a live copy. */
                    728:                            *slash = '\0';
1.1.1.2 ! misho     729:                            pathjoin(new, len, curr_dir, bdir + 3);
1.1       misho     730:                            *slash = '/';
                    731:                        } else
1.1.1.2 ! misho     732:                            pathjoin(new, len, curr_dir, bdir);
        !           733:                        basis_dir[j] = bdir = new;
1.1       misho     734:                }
1.1.1.2 ! misho     735:                if (do_stat(bdir, &st) < 0)
        !           736:                        rprintf(FWARNING, "%s arg does not exist: %s\n", dest_option, bdir);
        !           737:                else if (!S_ISDIR(st.st_mode))
        !           738:                        rprintf(FWARNING, "%s arg is not a dir: %s\n", dest_option, bdir);
1.1       misho     739:        }
                    740: }
                    741: 
                    742: /* This is only called by the sender. */
1.1.1.2 ! misho     743: static void read_final_goodbye(int f_in, int f_out)
1.1       misho     744: {
                    745:        int i, iflags, xlen;
                    746:        uchar fnamecmp_type;
                    747:        char xname[MAXPATHLEN];
                    748: 
1.1.1.2 ! misho     749:        shutting_down = True;
        !           750: 
1.1       misho     751:        if (protocol_version < 29)
                    752:                i = read_int(f_in);
                    753:        else {
1.1.1.2 ! misho     754:                i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
        !           755:                if (protocol_version >= 31 && i == NDX_DONE) {
        !           756:                        if (am_sender)
        !           757:                                write_ndx(f_out, NDX_DONE);
        !           758:                        else {
        !           759:                                if (batch_gen_fd >= 0) {
        !           760:                                        while (read_int(batch_gen_fd) != NDX_DEL_STATS) {}
        !           761:                                        read_del_stats(batch_gen_fd);
        !           762:                                }
        !           763:                                write_int(f_out, NDX_DONE);
        !           764:                        }
        !           765:                        i = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type, xname, &xlen);
        !           766:                }
1.1       misho     767:        }
                    768: 
                    769:        if (i != NDX_DONE) {
                    770:                rprintf(FERROR, "Invalid packet at end of run (%d) [%s]\n",
                    771:                        i, who_am_i());
                    772:                exit_cleanup(RERR_PROTOCOL);
                    773:        }
                    774: }
                    775: 
                    776: static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
                    777: {
                    778:        struct file_list *flist;
                    779:        char *dir = argv[0];
                    780: 
1.1.1.2 ! misho     781:        if (DEBUG_GTE(SEND, 1))
        !           782:                rprintf(FINFO, "server_sender starting pid=%d\n", (int)getpid());
1.1       misho     783: 
                    784:        if (am_daemon && lp_write_only(module_id)) {
                    785:                rprintf(FERROR, "ERROR: module is write only\n");
                    786:                exit_cleanup(RERR_SYNTAX);
                    787:                return;
                    788:        }
1.1.1.2 ! misho     789:        if (am_daemon && read_only && remove_source_files) {
1.1       misho     790:                rprintf(FERROR,
                    791:                    "ERROR: --remove-%s-files cannot be used with a read-only module\n",
                    792:                    remove_source_files == 1 ? "source" : "sent");
                    793:                exit_cleanup(RERR_SYNTAX);
                    794:                return;
                    795:        }
                    796: 
                    797:        if (!relative_paths) {
                    798:                if (!change_dir(dir, CD_NORMAL)) {
                    799:                        rsyserr(FERROR, errno, "change_dir#3 %s failed",
                    800:                                full_fname(dir));
                    801:                        exit_cleanup(RERR_FILESELECT);
                    802:                }
                    803:        }
                    804:        argc--;
                    805:        argv++;
                    806: 
                    807:        if (argc == 0 && (recurse || xfer_dirs || list_only)) {
                    808:                argc = 1;
                    809:                argv--;
                    810:                argv[0] = ".";
                    811:        }
                    812: 
                    813:        flist = send_file_list(f_out,argc,argv);
1.1.1.2 ! misho     814:        if (!flist || flist->used == 0) {
        !           815:                /* Make sure input buffering is off so we can't hang in noop_io_until_death(). */
        !           816:                io_end_buffering_in(0);
        !           817:                /* TODO:  we should really exit in a more controlled manner. */
1.1       misho     818:                exit_cleanup(0);
1.1.1.2 ! misho     819:        }
1.1       misho     820: 
                    821:        io_start_buffering_in(f_in);
                    822: 
                    823:        send_files(f_in, f_out);
                    824:        io_flush(FULL_FLUSH);
                    825:        handle_stats(f_out);
                    826:        if (protocol_version >= 24)
1.1.1.2 ! misho     827:                read_final_goodbye(f_in, f_out);
1.1       misho     828:        io_flush(FULL_FLUSH);
                    829:        exit_cleanup(0);
                    830: }
                    831: 
                    832: 
                    833: static int do_recv(int f_in, int f_out, char *local_name)
                    834: {
                    835:        int pid;
                    836:        int exit_code = 0;
                    837:        int error_pipe[2];
                    838: 
                    839:        /* The receiving side mustn't obey this, or an existing symlink that
                    840:         * points to an identical file won't be replaced by the referent. */
                    841:        copy_links = copy_dirlinks = copy_unsafe_links = 0;
                    842: 
                    843: #ifdef SUPPORT_HARD_LINKS
                    844:        if (preserve_hard_links && !inc_recurse)
                    845:                match_hard_links(first_flist);
                    846: #endif
                    847: 
                    848:        if (fd_pair(error_pipe) < 0) {
                    849:                rsyserr(FERROR, errno, "pipe failed in do_recv");
                    850:                exit_cleanup(RERR_IPC);
                    851:        }
                    852: 
1.1.1.2 ! misho     853:        if (backup_dir) {
        !           854:                int ret = make_path(backup_dir_buf, MKP_DROP_NAME); /* drops trailing slash */
        !           855:                if (ret < 0)
        !           856:                        exit_cleanup(RERR_SYNTAX);
        !           857:                if (ret)
        !           858:                        rprintf(FINFO, "Created backup_dir %s\n", backup_dir_buf);
        !           859:                else if (INFO_GTE(BACKUP, 1))
        !           860:                        rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
        !           861:        }
        !           862: 
        !           863:        io_flush(FULL_FLUSH);
1.1       misho     864: 
                    865:        if ((pid = do_fork()) == -1) {
                    866:                rsyserr(FERROR, errno, "fork failed in do_recv");
                    867:                exit_cleanup(RERR_IPC);
                    868:        }
                    869: 
                    870:        if (pid == 0) {
                    871:                am_receiver = 1;
1.1.1.2 ! misho     872:                send_msgs_to_gen = am_server;
1.1       misho     873: 
                    874:                close(error_pipe[0]);
1.1.1.2 ! misho     875: 
        !           876:                /* We can't let two processes write to the socket at one time. */
        !           877:                io_end_multiplex_out(MPLX_SWITCHING);
1.1       misho     878:                if (f_in != f_out)
                    879:                        close(f_out);
1.1.1.2 ! misho     880:                sock_f_out = -1;
        !           881:                f_out = error_pipe[1];
1.1       misho     882: 
1.1.1.2 ! misho     883:                bwlimit_writemax = 0; /* receiver doesn't need to do this */
1.1       misho     884: 
1.1.1.2 ! misho     885:                if (read_batch)
        !           886:                        io_start_buffering_in(f_in);
        !           887:                io_start_multiplex_out(f_out);
1.1       misho     888: 
1.1.1.2 ! misho     889:                recv_files(f_in, f_out, local_name);
1.1       misho     890:                io_flush(FULL_FLUSH);
                    891:                handle_stats(f_in);
                    892: 
1.1.1.2 ! misho     893:                if (output_needs_newline) {
        !           894:                        fputc('\n', stdout);
        !           895:                        output_needs_newline = 0;
        !           896:                }
        !           897: 
        !           898:                write_int(f_out, NDX_DONE);
        !           899:                send_msg(MSG_STATS, (char*)&stats.total_read, sizeof stats.total_read, 0);
1.1       misho     900:                io_flush(FULL_FLUSH);
                    901: 
                    902:                /* Handle any keep-alive packets from the post-processing work
                    903:                 * that the generator does. */
                    904:                if (protocol_version >= 29) {
                    905:                        kluge_around_eof = -1;
                    906: 
                    907:                        /* This should only get stopped via a USR2 signal. */
1.1.1.2 ! misho     908:                        read_final_goodbye(f_in, f_out);
1.1       misho     909: 
                    910:                        rprintf(FERROR, "Invalid packet at end of run [%s]\n",
                    911:                                who_am_i());
                    912:                        exit_cleanup(RERR_PROTOCOL);
                    913:                }
                    914: 
                    915:                /* Finally, we go to sleep until our parent kills us with a
                    916:                 * USR2 signal.  We sleep for a short time, as on some OSes
                    917:                 * a signal won't interrupt a sleep! */
                    918:                while (1)
                    919:                        msleep(20);
                    920:        }
                    921: 
                    922:        am_generator = 1;
1.1.1.2 ! misho     923:        flist_receiving_enabled = True;
1.1       misho     924: 
1.1.1.2 ! misho     925:        io_end_multiplex_in(MPLX_SWITCHING);
1.1       misho     926:        if (write_batch && !am_server)
                    927:                stop_write_batch();
                    928: 
                    929:        close(error_pipe[1]);
                    930:        if (f_in != f_out)
                    931:                close(f_in);
1.1.1.2 ! misho     932:        sock_f_in = -1;
        !           933:        f_in = error_pipe[0];
1.1       misho     934: 
                    935:        io_start_buffering_out(f_out);
1.1.1.2 ! misho     936:        io_start_multiplex_in(f_in);
1.1       misho     937: 
                    938: #ifdef SUPPORT_HARD_LINKS
                    939:        if (preserve_hard_links && inc_recurse) {
                    940:                struct file_list *flist;
                    941:                for (flist = first_flist; flist; flist = flist->next)
                    942:                        match_hard_links(flist);
                    943:        }
                    944: #endif
                    945: 
                    946:        generate_files(f_out, local_name);
                    947: 
                    948:        handle_stats(-1);
                    949:        io_flush(FULL_FLUSH);
1.1.1.2 ! misho     950:        shutting_down = True;
1.1       misho     951:        if (protocol_version >= 24) {
                    952:                /* send a final goodbye message */
                    953:                write_ndx(f_out, NDX_DONE);
                    954:        }
                    955:        io_flush(FULL_FLUSH);
                    956: 
                    957:        kill(pid, SIGUSR2);
                    958:        wait_process_with_flush(pid, &exit_code);
                    959:        return exit_code;
                    960: }
                    961: 
                    962: static void do_server_recv(int f_in, int f_out, int argc, char *argv[])
                    963: {
                    964:        int exit_code;
                    965:        struct file_list *flist;
                    966:        char *local_name = NULL;
1.1.1.2 ! misho     967:        int negated_levels;
1.1       misho     968: 
1.1.1.2 ! misho     969:        if (filesfrom_fd >= 0 && !msgs2stderr && protocol_version < 31) {
1.1       misho     970:                /* We can't mix messages with files-from data on the socket,
1.1.1.2 ! misho     971:                 * so temporarily turn off info/debug messages. */
        !           972:                negate_output_levels();
        !           973:                negated_levels = 1;
        !           974:        } else
        !           975:                negated_levels = 0;
1.1       misho     976: 
1.1.1.2 ! misho     977:        if (DEBUG_GTE(RECV, 1))
        !           978:                rprintf(FINFO, "server_recv(%d) starting pid=%d\n", argc, (int)getpid());
1.1       misho     979: 
1.1.1.2 ! misho     980:        if (am_daemon && read_only) {
1.1       misho     981:                rprintf(FERROR,"ERROR: module is read only\n");
                    982:                exit_cleanup(RERR_SYNTAX);
                    983:                return;
                    984:        }
                    985: 
                    986:        if (argc > 0) {
                    987:                char *dir = argv[0];
                    988:                argc--;
                    989:                argv++;
                    990:                if (!am_daemon && !change_dir(dir, CD_NORMAL)) {
                    991:                        rsyserr(FERROR, errno, "change_dir#4 %s failed",
                    992:                                full_fname(dir));
                    993:                        exit_cleanup(RERR_FILESELECT);
                    994:                }
                    995:        }
                    996: 
                    997:        if (protocol_version >= 30)
1.1.1.2 ! misho     998:                io_start_multiplex_in(f_in);
1.1       misho     999:        else
                   1000:                io_start_buffering_in(f_in);
                   1001:        recv_filter_list(f_in);
                   1002: 
                   1003:        if (filesfrom_fd >= 0) {
                   1004:                /* We need to send the files-from names to the sender at the
                   1005:                 * same time that we receive the file-list from them, so we
                   1006:                 * need the IO routines to automatically write out the names
                   1007:                 * onto our f_out socket as we read the file-list.  This
                   1008:                 * avoids both deadlock and extra delays/buffers. */
1.1.1.2 ! misho    1009:                start_filesfrom_forwarding(filesfrom_fd);
1.1       misho    1010:                filesfrom_fd = -1;
                   1011:        }
                   1012: 
                   1013:        flist = recv_file_list(f_in);
                   1014:        if (!flist) {
                   1015:                rprintf(FERROR,"server_recv: recv_file_list error\n");
                   1016:                exit_cleanup(RERR_FILESELECT);
                   1017:        }
                   1018:        if (inc_recurse && file_total == 1)
                   1019:                recv_additional_file_list(f_in);
1.1.1.2 ! misho    1020: 
        !          1021:        if (negated_levels)
        !          1022:                negate_output_levels();
1.1       misho    1023: 
                   1024:        if (argc > 0)
                   1025:                local_name = get_local_name(flist,argv[0]);
                   1026: 
                   1027:        /* Now that we know what our destination directory turned out to be,
                   1028:         * we can sanitize the --link-/copy-/compare-dest args correctly. */
                   1029:        if (sanitize_paths) {
                   1030:                char **dir_p;
                   1031:                for (dir_p = basis_dir; *dir_p; dir_p++)
                   1032:                        *dir_p = sanitize_path(NULL, *dir_p, NULL, curr_dir_depth, SP_DEFAULT);
                   1033:                if (partial_dir)
                   1034:                        partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, SP_DEFAULT);
                   1035:        }
                   1036:        check_alt_basis_dirs();
                   1037: 
                   1038:        if (daemon_filter_list.head) {
                   1039:                char **dir_p;
1.1.1.2 ! misho    1040:                filter_rule_list *elp = &daemon_filter_list;
1.1       misho    1041: 
                   1042:                for (dir_p = basis_dir; *dir_p; dir_p++) {
                   1043:                        char *dir = *dir_p;
                   1044:                        if (*dir == '/')
                   1045:                                dir += module_dirlen;
                   1046:                        if (check_filter(elp, FLOG, dir, 1) < 0)
                   1047:                                goto options_rejected;
                   1048:                }
                   1049:                if (partial_dir && *partial_dir == '/'
                   1050:                 && check_filter(elp, FLOG, partial_dir + module_dirlen, 1) < 0) {
                   1051:                    options_rejected:
                   1052:                        rprintf(FERROR,
                   1053:                                "Your options have been rejected by the server.\n");
                   1054:                        exit_cleanup(RERR_SYNTAX);
                   1055:                }
                   1056:        }
                   1057: 
                   1058:        exit_code = do_recv(f_in, f_out, local_name);
                   1059:        exit_cleanup(exit_code);
                   1060: }
                   1061: 
                   1062: 
                   1063: int child_main(int argc, char *argv[])
                   1064: {
                   1065:        start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
                   1066:        return 0;
                   1067: }
                   1068: 
                   1069: 
                   1070: void start_server(int f_in, int f_out, int argc, char *argv[])
                   1071: {
                   1072:        set_nonblocking(f_in);
                   1073:        set_nonblocking(f_out);
                   1074: 
                   1075:        io_set_sock_fds(f_in, f_out);
                   1076:        setup_protocol(f_out, f_in);
                   1077: 
                   1078:        if (protocol_version >= 23)
1.1.1.2 ! misho    1079:                io_start_multiplex_out(f_out);
        !          1080:        if (am_daemon && io_timeout && protocol_version >= 31)
        !          1081:                send_msg_int(MSG_IO_TIMEOUT, io_timeout);
1.1       misho    1082: 
                   1083:        if (am_sender) {
                   1084:                keep_dirlinks = 0; /* Must be disabled on the sender. */
                   1085:                if (need_messages_from_generator)
1.1.1.2 ! misho    1086:                        io_start_multiplex_in(f_in);
        !          1087:                else
        !          1088:                        io_start_buffering_in(f_in);
1.1       misho    1089:                recv_filter_list(f_in);
                   1090:                do_server_sender(f_in, f_out, argc, argv);
                   1091:        } else
                   1092:                do_server_recv(f_in, f_out, argc, argv);
                   1093:        exit_cleanup(0);
                   1094: }
                   1095: 
1.1.1.2 ! misho    1096: /* This is called once the connection has been negotiated.  It is used
        !          1097:  * for rsyncd, remote-shell, and local connections. */
1.1       misho    1098: int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
                   1099: {
                   1100:        struct file_list *flist = NULL;
                   1101:        int exit_code = 0, exit_code2 = 0;
                   1102:        char *local_name = NULL;
                   1103: 
                   1104:        cleanup_child_pid = pid;
                   1105:        if (!read_batch) {
                   1106:                set_nonblocking(f_in);
                   1107:                set_nonblocking(f_out);
                   1108:        }
                   1109: 
                   1110:        io_set_sock_fds(f_in, f_out);
                   1111:        setup_protocol(f_out,f_in);
                   1112: 
                   1113:        /* We set our stderr file handle to blocking because ssh might have
                   1114:         * set it to non-blocking.  This can be particularly troublesome if
                   1115:         * stderr is a clone of stdout, because ssh would have set our stdout
                   1116:         * to non-blocking at the same time (which can easily cause us to lose
                   1117:         * output from our print statements).  This kluge shouldn't cause ssh
                   1118:         * any problems for how we use it.  Note also that we delayed setting
                   1119:         * this until after the above protocol setup so that we know for sure
                   1120:         * that ssh is done twiddling its file descriptors.  */
                   1121:        set_blocking(STDERR_FILENO);
                   1122: 
                   1123:        if (am_sender) {
                   1124:                keep_dirlinks = 0; /* Must be disabled on the sender. */
1.1.1.2 ! misho    1125: 
        !          1126:                if (always_checksum
        !          1127:                 && (log_format_has(stdout_format, 'C')
        !          1128:                  || log_format_has(logfile_format, 'C')))
        !          1129:                        sender_keeps_checksum = 1;
        !          1130: 
1.1       misho    1131:                if (protocol_version >= 30)
1.1.1.2 ! misho    1132:                        io_start_multiplex_out(f_out);
1.1       misho    1133:                else
                   1134:                        io_start_buffering_out(f_out);
1.1.1.2 ! misho    1135:                if (protocol_version >= 31 || (!filesfrom_host && protocol_version >= 23))
        !          1136:                        io_start_multiplex_in(f_in);
        !          1137:                else
        !          1138:                        io_start_buffering_in(f_in);
1.1       misho    1139:                send_filter_list(f_out);
                   1140:                if (filesfrom_host)
                   1141:                        filesfrom_fd = f_in;
                   1142: 
                   1143:                if (write_batch && !am_server)
                   1144:                        start_write_batch(f_out);
                   1145:                flist = send_file_list(f_out, argc, argv);
1.1.1.2 ! misho    1146:                if (DEBUG_GTE(FLIST, 3))
1.1       misho    1147:                        rprintf(FINFO,"file list sent\n");
                   1148: 
1.1.1.2 ! misho    1149:                if (protocol_version < 31 && filesfrom_host && protocol_version >= 23)
        !          1150:                        io_start_multiplex_in(f_in);
1.1       misho    1151: 
                   1152:                io_flush(NORMAL_FLUSH);
                   1153:                send_files(f_in, f_out);
                   1154:                io_flush(FULL_FLUSH);
                   1155:                handle_stats(-1);
                   1156:                if (protocol_version >= 24)
1.1.1.2 ! misho    1157:                        read_final_goodbye(f_in, f_out);
1.1       misho    1158:                if (pid != -1) {
1.1.1.2 ! misho    1159:                        if (DEBUG_GTE(EXIT, 2))
1.1       misho    1160:                                rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
                   1161:                        io_flush(FULL_FLUSH);
                   1162:                        wait_process_with_flush(pid, &exit_code);
                   1163:                }
                   1164:                output_summary();
                   1165:                io_flush(FULL_FLUSH);
                   1166:                exit_cleanup(exit_code);
                   1167:        }
                   1168: 
                   1169:        if (!read_batch) {
                   1170:                if (protocol_version >= 23)
1.1.1.2 ! misho    1171:                        io_start_multiplex_in(f_in);
1.1       misho    1172:                if (need_messages_from_generator)
1.1.1.2 ! misho    1173:                        io_start_multiplex_out(f_out);
        !          1174:                else
        !          1175:                        io_start_buffering_out(f_out);
1.1       misho    1176:        }
                   1177: 
                   1178:        send_filter_list(read_batch ? -1 : f_out);
                   1179: 
                   1180:        if (filesfrom_fd >= 0) {
1.1.1.2 ! misho    1181:                start_filesfrom_forwarding(filesfrom_fd);
1.1       misho    1182:                filesfrom_fd = -1;
                   1183:        }
                   1184: 
                   1185:        if (write_batch && !am_server)
                   1186:                start_write_batch(f_in);
                   1187:        flist = recv_file_list(f_in);
                   1188:        if (inc_recurse && file_total == 1)
                   1189:                recv_additional_file_list(f_in);
                   1190: 
                   1191:        if (flist && flist->used > 0) {
                   1192:                local_name = get_local_name(flist, argv[0]);
                   1193: 
                   1194:                check_alt_basis_dirs();
                   1195: 
                   1196:                exit_code2 = do_recv(f_in, f_out, local_name);
                   1197:        } else {
                   1198:                handle_stats(-1);
                   1199:                output_summary();
                   1200:        }
                   1201: 
                   1202:        if (pid != -1) {
1.1.1.2 ! misho    1203:                if (DEBUG_GTE(RECV, 1))
1.1       misho    1204:                        rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
                   1205:                io_flush(FULL_FLUSH);
                   1206:                wait_process_with_flush(pid, &exit_code);
                   1207:        }
                   1208: 
                   1209:        return MAX(exit_code, exit_code2);
                   1210: }
                   1211: 
                   1212: static int copy_argv(char *argv[])
                   1213: {
                   1214:        int i;
                   1215: 
                   1216:        for (i = 0; argv[i]; i++) {
                   1217:                if (!(argv[i] = strdup(argv[i]))) {
                   1218:                        rprintf (FERROR, "out of memory at %s(%d)\n",
                   1219:                                 __FILE__, __LINE__);
                   1220:                        return RERR_MALLOC;
                   1221:                }
                   1222:        }
                   1223: 
                   1224:        return 0;
                   1225: }
                   1226: 
                   1227: 
1.1.1.2 ! misho    1228: /* Start a client for either type of remote connection.  Work out
1.1       misho    1229:  * whether the arguments request a remote shell or rsyncd connection,
                   1230:  * and call the appropriate connection function, then run_client.
                   1231:  *
                   1232:  * Calls either start_socket_client (for sockets) or do_cmd and
1.1.1.2 ! misho    1233:  * client_run (for ssh). */
1.1       misho    1234: static int start_client(int argc, char *argv[])
                   1235: {
                   1236:        char *p, *shell_machine = NULL, *shell_user = NULL;
                   1237:        char **remote_argv;
                   1238:        int remote_argc;
                   1239:        int f_in, f_out;
                   1240:        int ret;
                   1241:        pid_t pid;
                   1242: 
                   1243:        /* Don't clobber argv[] so that ps(1) can still show the right
                   1244:         * command line. */
                   1245:        if ((ret = copy_argv(argv)) != 0)
                   1246:                return ret;
                   1247: 
                   1248:        if (!read_batch) { /* for read_batch, NO source is specified */
                   1249:                char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
                   1250:                if (path) { /* source is remote */
                   1251:                        char *dummy_host;
                   1252:                        int dummy_port = 0;
                   1253:                        *argv = path;
                   1254:                        remote_argv = argv;
                   1255:                        remote_argc = argc;
                   1256:                        argv += argc - 1;
                   1257:                        if (argc == 1 || **argv == ':')
                   1258:                                argc = 0; /* no dest arg */
                   1259:                        else if (check_for_hostspec(*argv, &dummy_host, &dummy_port)) {
                   1260:                                rprintf(FERROR,
                   1261:                                        "The source and destination cannot both be remote.\n");
                   1262:                                exit_cleanup(RERR_SYNTAX);
                   1263:                        } else {
                   1264:                                remote_argc--; /* don't count dest */
                   1265:                                argc = 1;
                   1266:                        }
                   1267:                        if (filesfrom_host && *filesfrom_host
                   1268:                            && strcmp(filesfrom_host, shell_machine) != 0) {
                   1269:                                rprintf(FERROR,
                   1270:                                        "--files-from hostname is not the same as the transfer hostname\n");
                   1271:                                exit_cleanup(RERR_SYNTAX);
                   1272:                        }
                   1273:                        am_sender = 0;
                   1274:                        if (rsync_port)
                   1275:                                daemon_over_rsh = shell_cmd ? 1 : -1;
                   1276:                } else { /* source is local, check dest arg */
                   1277:                        am_sender = 1;
                   1278: 
                   1279:                        if (argc > 1) {
                   1280:                                p = argv[--argc];
                   1281:                                remote_argv = argv + argc;
                   1282:                        } else {
                   1283:                                static char *dotarg[1] = { "." };
                   1284:                                p = dotarg[0];
                   1285:                                remote_argv = dotarg;
                   1286:                        }
                   1287:                        remote_argc = 1;
                   1288: 
                   1289:                        path = check_for_hostspec(p, &shell_machine, &rsync_port);
                   1290:                        if (path && filesfrom_host && *filesfrom_host
                   1291:                            && strcmp(filesfrom_host, shell_machine) != 0) {
                   1292:                                rprintf(FERROR,
                   1293:                                        "--files-from hostname is not the same as the transfer hostname\n");
                   1294:                                exit_cleanup(RERR_SYNTAX);
                   1295:                        }
                   1296:                        if (!path) { /* no hostspec found, so src & dest are local */
                   1297:                                local_server = 1;
                   1298:                                if (filesfrom_host) {
                   1299:                                        rprintf(FERROR,
                   1300:                                                "--files-from cannot be remote when the transfer is local\n");
                   1301:                                        exit_cleanup(RERR_SYNTAX);
                   1302:                                }
                   1303:                                shell_machine = NULL;
                   1304:                        } else { /* hostspec was found, so dest is remote */
                   1305:                                argv[argc] = path;
                   1306:                                if (rsync_port)
                   1307:                                        daemon_over_rsh = shell_cmd ? 1 : -1;
                   1308:                        }
                   1309:                }
                   1310:        } else {  /* read_batch */
                   1311:                local_server = 1;
                   1312:                if (check_for_hostspec(argv[argc-1], &shell_machine, &rsync_port)) {
                   1313:                        rprintf(FERROR, "remote destination is not allowed with --read-batch\n");
                   1314:                        exit_cleanup(RERR_SYNTAX);
                   1315:                }
                   1316:                remote_argv = argv += argc - 1;
                   1317:                remote_argc = argc = 1;
                   1318:        }
                   1319: 
1.1.1.2 ! misho    1320:        if (!rsync_port && remote_argc && !**remote_argv) /* Turn an empty arg into a dot dir. */
        !          1321:                *remote_argv = ".";
        !          1322: 
1.1       misho    1323:        if (am_sender) {
                   1324:                char *dummy_host;
                   1325:                int dummy_port = rsync_port;
                   1326:                int i;
                   1327:                /* For local source, extra source args must not have hostspec. */
                   1328:                for (i = 1; i < argc; i++) {
                   1329:                        if (check_for_hostspec(argv[i], &dummy_host, &dummy_port)) {
                   1330:                                rprintf(FERROR, "Unexpected remote arg: %s\n", argv[i]);
                   1331:                                exit_cleanup(RERR_SYNTAX);
                   1332:                        }
                   1333:                }
                   1334:        } else {
                   1335:                char *dummy_host;
                   1336:                int dummy_port = rsync_port;
                   1337:                int i;
                   1338:                /* For remote source, any extra source args must have either
                   1339:                 * the same hostname or an empty hostname. */
                   1340:                for (i = 1; i < remote_argc; i++) {
                   1341:                        char *arg = check_for_hostspec(remote_argv[i], &dummy_host, &dummy_port);
                   1342:                        if (!arg) {
                   1343:                                rprintf(FERROR, "Unexpected local arg: %s\n", remote_argv[i]);
                   1344:                                rprintf(FERROR, "If arg is a remote file/dir, prefix it with a colon (:).\n");
                   1345:                                exit_cleanup(RERR_SYNTAX);
                   1346:                        }
                   1347:                        if (*dummy_host && strcmp(dummy_host, shell_machine) != 0) {
                   1348:                                rprintf(FERROR, "All source args must come from the same machine.\n");
                   1349:                                exit_cleanup(RERR_SYNTAX);
                   1350:                        }
                   1351:                        if (rsync_port != dummy_port) {
                   1352:                                if (!rsync_port || !dummy_port)
                   1353:                                        rprintf(FERROR, "All source args must use the same hostspec format.\n");
                   1354:                                else
                   1355:                                        rprintf(FERROR, "All source args must use the same port number.\n");
                   1356:                                exit_cleanup(RERR_SYNTAX);
                   1357:                        }
1.1.1.2 ! misho    1358:                        if (!rsync_port && !*arg) /* Turn an empty arg into a dot dir. */
        !          1359:                                arg = ".";
1.1       misho    1360:                        remote_argv[i] = arg;
                   1361:                }
                   1362:        }
                   1363: 
                   1364:        if (daemon_over_rsh < 0)
                   1365:                return start_socket_client(shell_machine, remote_argc, remote_argv, argc, argv);
                   1366: 
                   1367:        if (password_file && !daemon_over_rsh) {
                   1368:                rprintf(FERROR, "The --password-file option may only be "
                   1369:                                "used when accessing an rsync daemon.\n");
                   1370:                exit_cleanup(RERR_SYNTAX);
                   1371:        }
                   1372: 
                   1373:        if (connect_timeout) {
                   1374:                rprintf(FERROR, "The --contimeout option may only be "
                   1375:                                "used when connecting to an rsync daemon.\n");
                   1376:                exit_cleanup(RERR_SYNTAX);
                   1377:        }
                   1378: 
                   1379:        if (shell_machine) {
                   1380:                p = strrchr(shell_machine,'@');
                   1381:                if (p) {
                   1382:                        *p = 0;
                   1383:                        shell_user = shell_machine;
                   1384:                        shell_machine = p+1;
                   1385:                }
                   1386:        }
                   1387: 
1.1.1.2 ! misho    1388:        if (DEBUG_GTE(CMD, 2)) {
1.1       misho    1389:                rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
                   1390:                        NS(shell_cmd), NS(shell_machine), NS(shell_user),
1.1.1.2 ! misho    1391:                        NS(remote_argv[0]));
1.1       misho    1392:        }
                   1393: 
                   1394:        pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,
                   1395:                     &f_in, &f_out);
                   1396: 
                   1397:        /* if we're running an rsync server on the remote host over a
                   1398:         * remote shell command, we need to do the RSYNCD protocol first */
                   1399:        if (daemon_over_rsh) {
                   1400:                int tmpret;
                   1401:                tmpret = start_inband_exchange(f_in, f_out, shell_user, remote_argc, remote_argv);
                   1402:                if (tmpret < 0)
                   1403:                        return tmpret;
                   1404:        }
                   1405: 
                   1406:        ret = client_run(f_in, f_out, pid, argc, argv);
                   1407: 
                   1408:        fflush(stdout);
                   1409:        fflush(stderr);
                   1410: 
                   1411:        return ret;
                   1412: }
                   1413: 
                   1414: 
                   1415: static RETSIGTYPE sigusr1_handler(UNUSED(int val))
                   1416: {
                   1417:        exit_cleanup(RERR_SIGNAL1);
                   1418: }
                   1419: 
                   1420: static RETSIGTYPE sigusr2_handler(UNUSED(int val))
                   1421: {
                   1422:        if (!am_server)
                   1423:                output_summary();
                   1424:        close_all();
                   1425:        if (got_xfer_error)
                   1426:                _exit(RERR_PARTIAL);
                   1427:        _exit(0);
                   1428: }
                   1429: 
                   1430: RETSIGTYPE remember_children(UNUSED(int val))
                   1431: {
                   1432: #ifdef WNOHANG
                   1433:        int cnt, status;
                   1434:        pid_t pid;
                   1435:        /* An empty waitpid() loop was put here by Tridge and we could never
                   1436:         * get him to explain why he put it in, so rather than taking it
                   1437:         * out we're instead saving the child exit statuses for later use.
                   1438:         * The waitpid() loop presumably eliminates all possibility of leaving
                   1439:         * zombie children, maybe that's why he did it. */
                   1440:        while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
                   1441:                /* save the child's exit status */
                   1442:                for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
                   1443:                        if (pid_stat_table[cnt].pid == 0) {
                   1444:                                pid_stat_table[cnt].pid = pid;
                   1445:                                pid_stat_table[cnt].status = status;
                   1446:                                break;
                   1447:                        }
                   1448:                }
                   1449:        }
                   1450: #endif
                   1451: #ifndef HAVE_SIGACTION
                   1452:        signal(SIGCHLD, remember_children);
                   1453: #endif
                   1454: }
                   1455: 
                   1456: 
                   1457: /**
                   1458:  * This routine catches signals and tries to send them to gdb.
                   1459:  *
                   1460:  * Because it's called from inside a signal handler it ought not to
                   1461:  * use too many library routines.
                   1462:  *
                   1463:  * @todo Perhaps use "screen -X" instead/as well, to help people
                   1464:  * debugging without easy access to X.  Perhaps use an environment
                   1465:  * variable, or just call a script?
                   1466:  *
                   1467:  * @todo The /proc/ magic probably only works on Linux (and
                   1468:  * Solaris?)  Can we be more portable?
                   1469:  **/
                   1470: #ifdef MAINTAINER_MODE
                   1471: const char *get_panic_action(void)
                   1472: {
                   1473:        const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");
                   1474: 
                   1475:        if (cmd_fmt)
                   1476:                return cmd_fmt;
                   1477:        else
                   1478:                return "xterm -display :0 -T Panic -n Panic "
                   1479:                        "-e gdb /proc/%d/exe %d";
                   1480: }
                   1481: 
                   1482: 
                   1483: /**
                   1484:  * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION.
                   1485:  *
                   1486:  * This signal handler is only installed if we were configured with
                   1487:  * --enable-maintainer-mode.  Perhaps it should always be on and we
                   1488:  * should just look at the environment variable, but I'm a bit leery
                   1489:  * of a signal sending us into a busy loop.
                   1490:  **/
                   1491: static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
                   1492: {
                   1493:        char cmd_buf[300];
1.1.1.2 ! misho    1494:        int ret, pid_int = getpid();
1.1       misho    1495: 
1.1.1.2 ! misho    1496:        snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(), pid_int, pid_int);
1.1       misho    1497: 
                   1498:        /* Unless we failed to execute gdb, we allow the process to
                   1499:         * continue.  I'm not sure if that's right. */
                   1500:        ret = system(cmd_buf);
                   1501:        if (ret)
                   1502:                _exit(ret);
                   1503: }
                   1504: #endif
                   1505: 
                   1506: 
                   1507: int main(int argc,char *argv[])
                   1508: {
                   1509:        int ret;
                   1510:        int orig_argc = argc;
                   1511:        char **orig_argv = argv;
                   1512: #ifdef HAVE_SIGACTION
                   1513: # ifdef HAVE_SIGPROCMASK
                   1514:        sigset_t sigmask;
                   1515: 
                   1516:        sigemptyset(&sigmask);
                   1517: # endif
                   1518:        sigact.sa_flags = SA_NOCLDSTOP;
                   1519: #endif
                   1520:        SIGACTMASK(SIGUSR1, sigusr1_handler);
                   1521:        SIGACTMASK(SIGUSR2, sigusr2_handler);
                   1522:        SIGACTMASK(SIGCHLD, remember_children);
                   1523: #ifdef MAINTAINER_MODE
                   1524:        SIGACTMASK(SIGSEGV, rsync_panic_handler);
                   1525:        SIGACTMASK(SIGFPE, rsync_panic_handler);
                   1526:        SIGACTMASK(SIGABRT, rsync_panic_handler);
                   1527:        SIGACTMASK(SIGBUS, rsync_panic_handler);
                   1528: #endif
                   1529: 
                   1530:        starttime = time(NULL);
                   1531:        our_uid = MY_UID();
1.1.1.2 ! misho    1532:        our_gid = MY_GID();
1.1       misho    1533:        am_root = our_uid == 0;
                   1534: 
                   1535:        memset(&stats, 0, sizeof(stats));
                   1536: 
                   1537:        if (argc < 2) {
                   1538:                usage(FERROR);
                   1539:                exit_cleanup(RERR_SYNTAX);
                   1540:        }
                   1541: 
1.1.1.2 ! misho    1542:        /* Get the umask for use in permission calculations.  We no longer set
        !          1543:         * it to zero; that is ugly and pointless now that all the callers that
        !          1544:         * relied on it have been reeducated to work with default ACLs. */
        !          1545:        umask(orig_umask = umask(0));
1.1       misho    1546: 
                   1547: #if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
                   1548:        setlocale(LC_CTYPE, "");
                   1549: #endif
                   1550: 
                   1551:        if (!parse_arguments(&argc, (const char ***) &argv)) {
                   1552:                /* FIXME: We ought to call the same error-handling
                   1553:                 * code here, rather than relying on getopt. */
                   1554:                option_error();
                   1555:                exit_cleanup(RERR_SYNTAX);
                   1556:        }
                   1557: 
                   1558:        SIGACTMASK(SIGINT, sig_int);
                   1559:        SIGACTMASK(SIGHUP, sig_int);
                   1560:        SIGACTMASK(SIGTERM, sig_int);
                   1561: #if defined HAVE_SIGACTION && HAVE_SIGPROCMASK
                   1562:        sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
                   1563: #endif
                   1564: 
                   1565:        /* Ignore SIGPIPE; we consistently check error codes and will
                   1566:         * see the EPIPE. */
                   1567:        SIGACTION(SIGPIPE, SIG_IGN);
                   1568: #ifdef SIGXFSZ
                   1569:        SIGACTION(SIGXFSZ, SIG_IGN);
                   1570: #endif
                   1571: 
                   1572:        /* Initialize change_dir() here because on some old systems getcwd
                   1573:         * (implemented by forking "pwd" and reading its output) doesn't
                   1574:         * work when there are other child processes.  Also, on all systems
                   1575:         * that implement getcwd that way "pwd" can't be found after chroot. */
                   1576:        change_dir(NULL, CD_NORMAL);
                   1577: 
                   1578:        init_flist();
                   1579: 
                   1580:        if ((write_batch || read_batch) && !am_server) {
                   1581:                if (write_batch)
                   1582:                        write_batch_shell_file(orig_argc, orig_argv, argc);
                   1583: 
                   1584:                if (read_batch && strcmp(batch_name, "-") == 0)
                   1585:                        batch_fd = STDIN_FILENO;
                   1586:                else {
                   1587:                        batch_fd = do_open(batch_name,
                   1588:                                   write_batch ? O_WRONLY | O_CREAT | O_TRUNC
                   1589:                                   : O_RDONLY, S_IRUSR | S_IWUSR);
                   1590:                }
                   1591:                if (batch_fd < 0) {
                   1592:                        rsyserr(FERROR, errno, "Batch file %s open error",
                   1593:                                full_fname(batch_name));
                   1594:                        exit_cleanup(RERR_FILEIO);
                   1595:                }
                   1596:                if (read_batch)
                   1597:                        read_stream_flags(batch_fd);
                   1598:                else
                   1599:                        write_stream_flags(batch_fd);
                   1600:        }
                   1601:        if (write_batch < 0)
                   1602:                dry_run = 1;
                   1603: 
                   1604:        if (am_server) {
                   1605: #ifdef ICONV_CONST
                   1606:                setup_iconv();
                   1607: #endif
                   1608:        } else if (am_daemon)
                   1609:                return daemon_main();
                   1610: 
                   1611:        if (am_server && protect_args) {
                   1612:                char buf[MAXPATHLEN];
                   1613:                protect_args = 2;
                   1614:                read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
                   1615:                if (!parse_arguments(&argc, (const char ***) &argv)) {
                   1616:                        option_error();
                   1617:                        exit_cleanup(RERR_SYNTAX);
                   1618:                }
                   1619:        }
                   1620: 
                   1621:        if (argc < 1) {
                   1622:                usage(FERROR);
                   1623:                exit_cleanup(RERR_SYNTAX);
                   1624:        }
                   1625: 
                   1626:        if (am_server) {
                   1627:                set_nonblocking(STDIN_FILENO);
                   1628:                set_nonblocking(STDOUT_FILENO);
                   1629:                if (am_daemon)
                   1630:                        return start_daemon(STDIN_FILENO, STDOUT_FILENO);
                   1631:                start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
                   1632:        }
                   1633: 
                   1634:        ret = start_client(argc, argv);
                   1635:        if (ret == -1)
                   1636:                exit_cleanup(RERR_STARTCLIENT);
                   1637:        else
                   1638:                exit_cleanup(ret);
                   1639: 
                   1640:        return ret;
                   1641: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>