1 /* $Id: fargs.c,v 1.9 2019/02/13 19:13:18 deraadt 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) 30 { 31 char **args = NULL, **new; 32 size_t i = 0, n = 1, j, argsz = 0; 33 char *rsync_path; 34 35 assert(f != NULL); 36 assert(f->sourcesz > 0); 37 38 if ((rsync_path = sess->opts->rsync_path) == NULL) 39 rsync_path = RSYNC_PATH; 40 41 /* Be explicit with array size. */ 42 43 argsz += 1; /* dot separator */ 44 argsz += 1; /* sink file */ 45 argsz += 5; /* per-mode maximum */ 46 argsz += 11; /* shared args */ 47 argsz += 1; /* NULL pointer */ 48 argsz += f->sourcesz; 49 50 args = calloc(argsz, sizeof(char *)); 51 if (args == NULL) 52 goto out; 53 54 if (f->host != NULL) { 55 assert(f->host != NULL); 56 57 if (sess->opts->ssh_prog) { 58 char *ap = strdup(sess->opts->ssh_prog); 59 60 if (ap == NULL) 61 goto out; 62 while ((args[i] = strsep(&ap, " \t")) != NULL) { 63 if (args[i][0] == '\0') { 64 ap++; /* skip seperators */ 65 continue; 66 } 67 68 /* Grow command-area of array */ 69 if (i++ < n) 70 continue; 71 n += 10; 72 new = reallocarray(args, argsz + n, sizeof(char *)); 73 if (new == NULL) 74 goto out; 75 args = new; 76 argsz += n; 77 } 78 } else 79 args[i++] = "ssh"; 80 args[i++] = f->host; 81 args[i++] = rsync_path; 82 args[i++] = "--server"; 83 if (f->mode == FARGS_RECEIVER) 84 args[i++] = "--sender"; 85 } else { 86 args[i++] = rsync_path; 87 args[i++] = "--server"; 88 } 89 90 /* Shared arguments. */ 91 92 if (sess->opts->del) 93 args[i++] = "--delete"; 94 if (sess->opts->preserve_gids) 95 args[i++] = "-g"; 96 if (sess->opts->preserve_links) 97 args[i++] = "-l"; 98 if (sess->opts->dry_run) 99 args[i++] = "-n"; 100 if (sess->opts->preserve_perms) 101 args[i++] = "-p"; 102 if (sess->opts->recursive) 103 args[i++] = "-r"; 104 if (sess->opts->preserve_times) 105 args[i++] = "-t"; 106 if (sess->opts->verbose > 3) 107 args[i++] = "-v"; 108 if (sess->opts->verbose > 2) 109 args[i++] = "-v"; 110 if (sess->opts->verbose > 1) 111 args[i++] = "-v"; 112 if (sess->opts->verbose > 0) 113 args[i++] = "-v"; 114 115 /* Terminate with a full-stop for reasons unknown. */ 116 117 args[i++] = "."; 118 119 if (f->mode == FARGS_RECEIVER) { 120 for (j = 0; j < f->sourcesz; j++) 121 args[i++] = f->sources[j]; 122 } else 123 args[i++] = f->sink; 124 125 args[i] = NULL; 126 return args; 127 out: 128 free(args); 129 ERR(sess, "calloc"); 130 return NULL; 131 } 132