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

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

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