1 /* $Id: fargs.c,v 1.18 2021/05/17 12:02:58 claudio Exp $ */ 2 /* 3 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/stat.h> 18 19 #include <assert.h> 20 #include <err.h> 21 #include <stdint.h> 22 #include <stdlib.h> 23 #include <string.h> 24 25 #include "extern.h" 26 27 #define RSYNC_PATH "rsync" 28 29 char ** 30 fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip) 31 { 32 arglist args; 33 size_t j; 34 char *rsync_path, *ap, *arg; 35 36 memset(&args, 0, sizeof args); 37 38 assert(f != NULL); 39 assert(f->sourcesz > 0); 40 41 if ((rsync_path = sess->opts->rsync_path) == NULL) 42 rsync_path = RSYNC_PATH; 43 44 if (f->host != NULL) { 45 /* 46 * Splice arguments from -e "foo bar baz" into array 47 * elements required for execve(2). 48 * This doesn't do anything fancy: it splits along 49 * whitespace into the array. 50 */ 51 52 if (sess->opts->ssh_prog) { 53 ap = strdup(sess->opts->ssh_prog); 54 if (ap == NULL) 55 err(ERR_NOMEM, NULL); 56 57 while ((arg = strsep(&ap, " \t")) != NULL) { 58 if (arg[0] == '\0') { 59 ap++; /* skip seperators */ 60 continue; 61 } 62 63 addargs(&args, "%s", arg); 64 } 65 } else 66 addargs(&args, "ssh"); 67 68 addargs(&args, "%s", f->host); 69 addargs(&args, "%s", rsync_path); 70 if (skip) 71 *skip = args.num; 72 addargs(&args, "--server"); 73 if (f->mode == FARGS_RECEIVER) 74 addargs(&args, "--sender"); 75 } else { 76 addargs(&args, "%s", rsync_path); 77 addargs(&args, "--server"); 78 } 79 80 /* Shared arguments. */ 81 82 if (sess->opts->del) 83 addargs(&args, "--delete"); 84 if (sess->opts->numeric_ids) 85 addargs(&args, "--numeric-ids"); 86 if (sess->opts->preserve_gids) 87 addargs(&args, "-g"); 88 if (sess->opts->preserve_links) 89 addargs(&args, "-l"); 90 if (sess->opts->dry_run) 91 addargs(&args, "-n"); 92 if (sess->opts->preserve_uids) 93 addargs(&args, "-o"); 94 if (sess->opts->preserve_perms) 95 addargs(&args, "-p"); 96 if (sess->opts->devices) 97 addargs(&args, "-D"); 98 if (sess->opts->recursive) 99 addargs(&args, "-r"); 100 if (sess->opts->preserve_times) 101 addargs(&args, "-t"); 102 if (verbose > 3) 103 addargs(&args, "-v"); 104 if (verbose > 2) 105 addargs(&args, "-v"); 106 if (verbose > 1) 107 addargs(&args, "-v"); 108 if (verbose > 0) 109 addargs(&args, "-v"); 110 if (sess->opts->one_file_system > 1) 111 addargs(&args, "-x"); 112 if (sess->opts->one_file_system > 0) 113 addargs(&args, "-x"); 114 if (sess->opts->specials && !sess->opts->devices) 115 addargs(&args, "--specials"); 116 if (!sess->opts->specials && sess->opts->devices) 117 /* --devices is sent as -D --no-specials */ 118 addargs(&args, "--no-specials"); 119 120 /* Terminate with a full-stop for reasons unknown. */ 121 122 addargs(&args, "."); 123 124 if (f->mode == FARGS_RECEIVER) { 125 for (j = 0; j < f->sourcesz; j++) 126 addargs(&args, "%s", f->sources[j]); 127 } else 128 addargs(&args, "%s", f->sink); 129 130 return args.list; 131 } 132