1 /* $Id: fargs.c,v 1.17 2019/05/08 20:00:25 benno 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 <stdint.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include "extern.h" 25 26 #define RSYNC_PATH "rsync" 27 28 char ** 29 fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip) 30 { 31 arglist args; 32 size_t j; 33 char *rsync_path, *ap, *arg; 34 35 memset(&args, 0, sizeof args); 36 37 assert(f != NULL); 38 assert(f->sourcesz > 0); 39 40 if ((rsync_path = sess->opts->rsync_path) == NULL) 41 rsync_path = RSYNC_PATH; 42 43 if (f->host != NULL) { 44 /* 45 * Splice arguments from -e "foo bar baz" into array 46 * elements required for execve(2). 47 * This doesn't do anything fancy: it splits along 48 * whitespace into the array. 49 */ 50 51 if (sess->opts->ssh_prog) { 52 ap = strdup(sess->opts->ssh_prog); 53 if (ap == NULL) 54 goto out; 55 56 while ((arg = strsep(&ap, " \t")) != NULL) { 57 if (arg[0] == '\0') { 58 ap++; /* skip seperators */ 59 continue; 60 } 61 62 addargs(&args, "%s", arg); 63 } 64 } else 65 addargs(&args, "ssh"); 66 67 addargs(&args, "%s", f->host); 68 addargs(&args, "%s", rsync_path); 69 if (skip) 70 *skip = args.num; 71 addargs(&args, "--server"); 72 if (f->mode == FARGS_RECEIVER) 73 addargs(&args, "--sender"); 74 } else { 75 addargs(&args, "%s", rsync_path); 76 addargs(&args, "--server"); 77 } 78 79 /* Shared arguments. */ 80 81 if (sess->opts->del) 82 addargs(&args, "--delete"); 83 if (sess->opts->numeric_ids) 84 addargs(&args, "--numeric-ids"); 85 if (sess->opts->preserve_gids) 86 addargs(&args, "-g"); 87 if (sess->opts->preserve_links) 88 addargs(&args, "-l"); 89 if (sess->opts->dry_run) 90 addargs(&args, "-n"); 91 if (sess->opts->preserve_uids) 92 addargs(&args, "-o"); 93 if (sess->opts->preserve_perms) 94 addargs(&args, "-p"); 95 if (sess->opts->devices) 96 addargs(&args, "-D"); 97 if (sess->opts->recursive) 98 addargs(&args, "-r"); 99 if (sess->opts->preserve_times) 100 addargs(&args, "-t"); 101 if (verbose > 3) 102 addargs(&args, "-v"); 103 if (verbose > 2) 104 addargs(&args, "-v"); 105 if (verbose > 1) 106 addargs(&args, "-v"); 107 if (verbose > 0) 108 addargs(&args, "-v"); 109 if (sess->opts->one_file_system > 1) 110 addargs(&args, "-x"); 111 if (sess->opts->one_file_system > 0) 112 addargs(&args, "-x"); 113 if (sess->opts->specials && !sess->opts->devices) 114 addargs(&args, "--specials"); 115 if (!sess->opts->specials && sess->opts->devices) 116 /* --devices is sent as -D --no-specials */ 117 addargs(&args, "--no-specials"); 118 119 /* Terminate with a full-stop for reasons unknown. */ 120 121 addargs(&args, "."); 122 123 if (f->mode == FARGS_RECEIVER) { 124 for (j = 0; j < f->sourcesz; j++) 125 addargs(&args, "%s", f->sources[j]); 126 } else 127 addargs(&args, "%s", f->sink); 128 129 return args.list; 130 out: 131 freeargs(&args); 132 ERR("calloc"); 133 return NULL; 134 } 135