main.c revision 1.9
1/* $NetBSD: main.c,v 1.9 2009/06/05 09:31:07 wiz Exp $ */ 2 3/*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30#ifndef lint 31__RCSID("$NetBSD: main.c,v 1.9 2009/06/05 09:31:07 wiz Exp $"); 32#endif /* !lint */ 33 34#include <sys/module.h> 35 36#include <assert.h> 37#include <stdbool.h> 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42#include <err.h> 43 44#include <prop/proplib.h> 45 46int main(int, char **); 47static void parse_bool_param(prop_dictionary_t, const char *, 48 const char *); 49static void parse_int_param(prop_dictionary_t, const char *, 50 const char *); 51static void parse_param(prop_dictionary_t, const char *, 52 void (*)(prop_dictionary_t, const char *, 53 const char *)); 54static void parse_string_param(prop_dictionary_t, const char *, 55 const char *); 56static void usage(void) __dead; 57static void merge_dicts(prop_dictionary_t, const prop_dictionary_t); 58 59int 60main(int argc, char **argv) 61{ 62 modctl_load_t cmdargs; 63 prop_dictionary_t ext_props, props; 64 bool merge_props, output_props; 65 const char *ext_file; 66 char *propsstr; 67 int ch; 68 int flags; 69 70 ext_file = NULL; 71 ext_props = NULL; 72 props = prop_dictionary_create(); 73 merge_props = output_props = false; 74 flags = 0; 75 76 while ((ch = getopt(argc, argv, "b:fi:m:ps:")) != -1) { 77 switch (ch) { 78 case 'b': 79 parse_param(props, optarg, parse_bool_param); 80 break; 81 82 case 'f': 83 flags |= MODCTL_LOAD_FORCE; 84 break; 85 86 case 'i': 87 parse_param(props, optarg, parse_int_param); 88 break; 89 90 case 'm': 91 merge_props = true; 92 ext_file = optarg; 93 break; 94 95 case 'p': 96 output_props = true; 97 break; 98 99 case 's': 100 parse_param(props, optarg, parse_string_param); 101 break; 102 103 default: 104 usage(); 105 /* NOTREACHED */ 106 } 107 } 108 109 argc -= optind; 110 argv += optind; 111 112 propsstr = prop_dictionary_externalize(props); 113 if (propsstr == NULL) 114 errx(EXIT_FAILURE, "Failed to process properties"); 115 116 if (output_props) { 117 if (merge_props) { 118 ext_props = 119 prop_dictionary_internalize_from_file(ext_file); 120 if (ext_props == NULL) { 121 errx(EXIT_FAILURE, "Failed to read existing " 122 "property list"); 123 } 124 125 free(propsstr); 126 merge_dicts(ext_props, props); 127 propsstr = prop_dictionary_externalize(ext_props); 128 } 129 130 fputs(propsstr, stdout); 131 } else { 132 if (argc != 1) 133 usage(); 134 cmdargs.ml_filename = argv[0]; 135 cmdargs.ml_flags = flags; 136 cmdargs.ml_props = propsstr; 137 cmdargs.ml_propslen = strlen(propsstr); 138 139 if (modctl(MODCTL_LOAD, &cmdargs)) { 140 err(EXIT_FAILURE, NULL); 141 } 142 } 143 144 free(propsstr); 145 prop_object_release(props); 146 147 exit(EXIT_SUCCESS); 148} 149 150static void 151parse_bool_param(prop_dictionary_t props, const char *name, 152 const char *value) 153{ 154 bool boolvalue; 155 156 assert(name != NULL); 157 assert(value != NULL); 158 159 if (strcasecmp(value, "1") == 0 || 160 strcasecmp(value, "true") == 0 || 161 strcasecmp(value, "yes") == 0) 162 boolvalue = true; 163 else if (strcasecmp(value, "0") == 0 || 164 strcasecmp(value, "false") == 0 || 165 strcasecmp(value, "no") == 0) 166 boolvalue = false; 167 else 168 errx(EXIT_FAILURE, "Invalid boolean value `%s'", value); 169 170 prop_dictionary_set(props, name, prop_bool_create(boolvalue)); 171} 172 173static void 174parse_int_param(prop_dictionary_t props, const char *name, 175 const char *value) 176{ 177 int64_t intvalue; 178 179 assert(name != NULL); 180 assert(value != NULL); 181 182 if (dehumanize_number(value, &intvalue) != 0) 183 err(EXIT_FAILURE, "Invalid integer value `%s'", value); 184 185 prop_dictionary_set(props, name, 186 prop_number_create_integer(intvalue)); 187} 188 189static void 190parse_param(prop_dictionary_t props, const char *origstr, 191 void (*fmt_handler)(prop_dictionary_t, const char *, const char *)) 192{ 193 char *name, *value; 194 195 name = strdup(origstr); 196 197 value = strchr(name, '='); 198 if (value == NULL) { 199 free(name); 200 errx(EXIT_FAILURE, "Invalid parameter `%s'", origstr); 201 } 202 *value++ = '\0'; 203 204 fmt_handler(props, name, value); 205 206 free(name); 207} 208 209static void 210parse_string_param(prop_dictionary_t props, const char *name, 211 const char *value) 212{ 213 214 assert(name != NULL); 215 assert(value != NULL); 216 217 prop_dictionary_set(props, name, prop_string_create_cstring(value)); 218} 219 220static void 221usage(void) 222{ 223 224 (void)fprintf(stderr, 225 "Usage: %s [-f] [-b var=boolean] [-i var=integer] " 226 "[-s var=string] module\n" 227 " %s -p [-b var=boolean] [-i var=integer] [-m plist] " 228 "[-s var=string]\n", 229 getprogname(), getprogname()); 230 exit(EXIT_FAILURE); 231} 232 233static void 234merge_dicts(prop_dictionary_t existing_dict, const prop_dictionary_t new_dict) 235{ 236 prop_dictionary_keysym_t props_keysym; 237 prop_object_iterator_t props_iter; 238 prop_object_t props_obj; 239 const char *props_key; 240 241 props_iter = prop_dictionary_iterator(new_dict); 242 if (props_iter == NULL) { 243 errx(EXIT_FAILURE, "Failed to iterate new property list"); 244 } 245 246 while ((props_obj = prop_object_iterator_next(props_iter)) != NULL) { 247 props_keysym = (prop_dictionary_keysym_t)props_obj; 248 props_key = prop_dictionary_keysym_cstring_nocopy(props_keysym); 249 props_obj = prop_dictionary_get_keysym(new_dict, props_keysym); 250 if ((props_obj == NULL) || !prop_dictionary_set(existing_dict, 251 props_key, props_obj)) { 252 errx(EXIT_FAILURE, "Failed to copy " 253 "existing property list"); 254 } 255 } 256 prop_object_iterator_release(props_iter); 257 258 return; 259} 260