| 1 |  |  | /*	$OpenBSD: distopt.c,v 1.13 2015/01/20 09:00:16 guenther 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. | 
    
    | 138 |  |  |  */ | 
    
    | 139 |  |  | char * | 
    
    | 140 |  |  | getdistoptlist(void) | 
    
    | 141 |  |  | { | 
    
    | 142 |  |  | 	int i; | 
    
    | 143 |  |  | 	static char buf[1024]; | 
    
    | 144 |  |  |  | 
    
    | 145 |  |  | 	for (i = 0, buf[0] = CNULL; distoptinfo[i].do_name; ++i) { | 
    
    | 146 |  |  | 		if (buf[0] == CNULL) | 
    
    | 147 |  |  | 			(void) strlcpy(buf, distoptinfo[i].do_name, sizeof buf); | 
    
    | 148 |  |  | 		else { | 
    
    | 149 |  |  | 			(void) strlcat(buf, ",", sizeof buf); | 
    
    | 150 |  |  | 			(void) strlcat(buf, distoptinfo[i].do_name, sizeof buf); | 
    
    | 151 |  |  | 		} | 
    
    | 152 |  |  | 	} | 
    
    | 153 |  |  |  | 
    
    | 154 |  |  | 	return(buf); | 
    
    | 155 |  |  | } | 
    
    | 156 |  |  |  | 
    
    | 157 |  |  | /* | 
    
    | 158 |  |  |  * Get a list of the Distfile Option Entries for each enabled | 
    
    | 159 |  |  |  * value in "opts". | 
    
    | 160 |  |  |  */ | 
    
    | 161 |  |  | char * | 
    
    | 162 |  |  | getondistoptlist(opt_t opts) | 
    
    | 163 |  |  | { | 
    
    | 164 |  |  | 	int i; | 
    
    | 165 |  |  | 	static char buf[1024]; | 
    
    | 166 |  |  |  | 
    
    | 167 |  |  | 	for (i = 0, buf[0] = CNULL; distoptinfo[i].do_name; ++i) { | 
    
    | 168 |  |  | 		if (!IS_ON(opts, distoptinfo[i].do_value)) | 
    
    | 169 |  |  | 			continue; | 
    
    | 170 |  |  |  | 
    
    | 171 |  |  | 		if (buf[0] == CNULL) | 
    
    | 172 |  |  | 			(void) strlcpy(buf, distoptinfo[i].do_name, sizeof buf); | 
    
    | 173 |  |  | 		else { | 
    
    | 174 |  |  | 			(void) strlcat(buf, ",", sizeof buf); | 
    
    | 175 |  |  | 			(void) strlcat(buf, distoptinfo[i].do_name, sizeof buf); | 
    
    | 176 |  |  | 		} | 
    
    | 177 |  |  | 		if (distoptinfo[i].do_arg) { | 
    
    | 178 |  |  | 			(void) strlcat(buf, "=", sizeof buf); | 
    
    | 179 |  |  | 			(void) strlcat(buf, distoptinfo[i].do_arg, sizeof buf); | 
    
    | 180 |  |  | 		} | 
    
    | 181 |  |  | 	} | 
    
    | 182 |  |  |  | 
    
    | 183 |  |  | 	return(buf); | 
    
    | 184 |  |  | } | 
    
    | 185 |  |  |  |