1 /* $OpenBSD: distopt.c,v 1.14 2021/06/22 20:19:28 jmc Exp $ */ 2 3 /* 4 * Copyright (c) 1983 Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include "client.h" 36 37 /* 38 * Dist Option functions 39 */ 40 41 42 /* 43 * Distfile Option Information 44 */ 45 struct distoptinfo { 46 opt_t do_value; 47 char *do_name; 48 char *do_arg; 49 size_t arg_size; 50 } distoptinfo[] = { 51 { DO_CHKNFS, "chknfs", NULL, 0}, 52 { DO_CHKREADONLY, "chkreadonly", NULL, 0}, 53 { DO_CHKSYM, "chksym", NULL, 0}, 54 { DO_COMPARE, "compare", NULL, 0}, 55 { DO_DEFGROUP, "defgroup", defgroup, sizeof(defgroup) }, 56 { DO_DEFOWNER, "defowner", defowner, sizeof(defowner) }, 57 { DO_FOLLOW, "follow", NULL, 0}, 58 { DO_HISTORY, "history", NULL, 0}, 59 { DO_IGNLNKS, "ignlnks", NULL, 0}, 60 { DO_NOCHKGROUP, "nochkgroup", NULL, 0}, 61 { DO_NOCHKMODE, "nochkmode", NULL, 0}, 62 { DO_NOCHKOWNER, "nochkowner", NULL, 0}, 63 { DO_NODESCEND, "nodescend", NULL, 0}, 64 { DO_NOEXEC, "noexec", NULL, 0}, 65 { DO_NUMCHKGROUP, "numchkgroup", NULL, 0}, 66 { DO_NUMCHKOWNER, "numchkowner", NULL, 0}, 67 { DO_QUIET, "quiet", NULL, 0}, 68 { DO_REMOVE, "remove", NULL, 0}, 69 { DO_SAVETARGETS, "savetargets", NULL, 0}, 70 { DO_SPARSE, "sparse", NULL, 0}, 71 { DO_UPDATEPERM, "updateperm", NULL, 0}, 72 { DO_VERIFY, "verify", NULL, 0}, 73 { DO_WHOLE, "whole", NULL, 0}, 74 { DO_YOUNGER, "younger", NULL, 0}, 75 { 0 }, 76 }; 77 78 /* 79 * Get a Distfile Option entry named "name". 80 */ 81 static struct distoptinfo * 82 getdistopt(char *name, int *len) 83 { 84 int i; 85 86 for (i = 0; distoptinfo[i].do_name; ++i) 87 if (strncasecmp(name, distoptinfo[i].do_name, 88 *len = strlen(distoptinfo[i].do_name)) == 0) 89 return(&distoptinfo[i]); 90 91 return(NULL); 92 } 93 94 /* 95 * Parse a dist option string. Set option flags to optptr. 96 * If doerrs is true, print out own error message. Returns 97 * 0 on success. 98 */ 99 int 100 parsedistopts(char *str, opt_t *optptr, int doerrs) 101 { 102 char *string, *optstr; 103 struct distoptinfo *distopt; 104 int len; 105 106 /* strtok() is destructive */ 107 string = xstrdup(str); 108 109 for (optstr = strtok(string, ","); optstr; 110 optstr = strtok(NULL, ",")) { 111 /* Try Yes */ 112 if ((distopt = getdistopt(optstr, &len)) != NULL) { 113 FLAG_ON(*optptr, distopt->do_value); 114 if (distopt->do_arg && optstr[len] == '=') 115 (void) strlcpy(distopt->do_arg, 116 &optstr[len + 1], distopt->arg_size); 117 continue; 118 } 119 120 /* Try No */ 121 if ((distopt = getdistopt(optstr+2, &len)) != NULL) { 122 FLAG_OFF(*optptr, distopt->do_value); 123 continue; 124 } 125 126 if (doerrs) 127 error("Dist option \"%s\" is not valid.", optstr); 128 } 129 130 if (string) 131 (void) free(string); 132 133 return(nerrs); 134 } 135 136 /* 137 * Get a list of the Distfile Option Entries for each enabled 138 * value in "opts". 139 */ 140 char * 141 getondistoptlist(opt_t opts) 142 { 143 int i; 144 static char buf[1024]; 145 146 for (i = 0, buf[0] = CNULL; distoptinfo[i].do_name; ++i) { 147 if (!IS_ON(opts, distoptinfo[i].do_value)) 148 continue; 149 150 if (buf[0] == CNULL) 151 (void) strlcpy(buf, distoptinfo[i].do_name, sizeof buf); 152 else { 153 (void) strlcat(buf, ",", sizeof buf); 154 (void) strlcat(buf, distoptinfo[i].do_name, sizeof buf); 155 } 156 if (distoptinfo[i].do_arg) { 157 (void) strlcat(buf, "=", sizeof buf); 158 (void) strlcat(buf, distoptinfo[i].do_arg, sizeof buf); 159 } 160 } 161 162 return(buf); 163 } 164 165