main.c revision 1.10
1/* $NetBSD: main.c,v 1.10 2009/06/05 11:37:30 jnemeth 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.10 2009/06/05 11:37:30 jnemeth Exp $"); 32#endif /* !lint */ 33 34#include <sys/module.h> 35#include <sys/queue.h> 36 37#include <assert.h> 38#include <stdbool.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <unistd.h> 43#include <err.h> 44 45#include <prop/proplib.h> 46 47int main(int, char **); 48static void parse_bool_param(prop_dictionary_t, const char *, 49 const char *); 50static void parse_int_param(prop_dictionary_t, const char *, 51 const char *); 52static void parse_param(prop_dictionary_t, const char *, 53 void (*)(prop_dictionary_t, const char *, 54 const char *)); 55static void parse_string_param(prop_dictionary_t, const char *, 56 const char *); 57static void usage(void) __dead; 58static void merge_dicts(prop_dictionary_t, const prop_dictionary_t); 59 60int 61main(int argc, char **argv) 62{ 63 SIMPLEQ_HEAD(del_head, del_item) del_head; 64 modctl_load_t cmdargs; 65 prop_dictionary_t ext_props, props; 66 bool del_props, merge_props, output_props; 67 const char *ext_file; 68 char *propsstr; 69 int ch; 70 int flags; 71 72 struct del_item { 73 SIMPLEQ_ENTRY(del_item) del_items; 74 const char *del_key; 75 } *delp; 76 77 SIMPLEQ_INIT(&del_head); 78 ext_file = NULL; 79 ext_props = NULL; 80 props = prop_dictionary_create(); 81 del_props = merge_props = output_props = false; 82 flags = 0; 83 84 while ((ch = getopt(argc, argv, "b:d:fi:m:ps:")) != -1) { 85 switch (ch) { 86 case 'b': 87 parse_param(props, optarg, parse_bool_param); 88 break; 89 90 case 'd': 91 del_props = true; 92 delp = malloc(sizeof(struct del_item)); 93 if (delp == NULL) 94 errx(EXIT_FAILURE, "Out of memory"); 95 delp->del_key = optarg; 96 SIMPLEQ_INSERT_TAIL(&del_head, delp, del_items); 97 break; 98 99 case 'f': 100 flags |= MODCTL_LOAD_FORCE; 101 break; 102 103 case 'i': 104 parse_param(props, optarg, parse_int_param); 105 break; 106 107 case 'm': 108 merge_props = true; 109 ext_file = optarg; 110 break; 111 112 case 'p': 113 output_props = true; 114 break; 115 116 case 's': 117 parse_param(props, optarg, parse_string_param); 118 break; 119 120 default: 121 usage(); 122 /* NOTREACHED */ 123 } 124 } 125 126 argc -= optind; 127 argv += optind; 128 129 propsstr = prop_dictionary_externalize(props); 130 if (propsstr == NULL) 131 errx(EXIT_FAILURE, "Failed to process properties"); 132 133 if (output_props) { 134 if (merge_props) { 135 ext_props = 136 prop_dictionary_internalize_from_file(ext_file); 137 if (ext_props == NULL) { 138 errx(EXIT_FAILURE, "Failed to read existing " 139 "property list"); 140 } 141 142 free(propsstr); 143 merge_dicts(ext_props, props); 144 145 if (del_props) 146 SIMPLEQ_FOREACH(delp, &del_head, del_items) 147 prop_dictionary_remove(ext_props, 148 delp->del_key); 149 150 propsstr = prop_dictionary_externalize(ext_props); 151 if (propsstr == NULL) 152 errx(EXIT_FAILURE, "Failed to process " 153 "properties"); 154 } 155 156 fputs(propsstr, stdout); 157 } else { 158 if (argc != 1) 159 usage(); 160 cmdargs.ml_filename = argv[0]; 161 cmdargs.ml_flags = flags; 162 cmdargs.ml_props = propsstr; 163 cmdargs.ml_propslen = strlen(propsstr); 164 165 if (modctl(MODCTL_LOAD, &cmdargs)) { 166 err(EXIT_FAILURE, NULL); 167 } 168 } 169 170 free(propsstr); 171 prop_object_release(props); 172 173 exit(EXIT_SUCCESS); 174} 175 176static void 177parse_bool_param(prop_dictionary_t props, const char *name, 178 const char *value) 179{ 180 bool boolvalue; 181 182 assert(name != NULL); 183 assert(value != NULL); 184 185 if (strcasecmp(value, "1") == 0 || 186 strcasecmp(value, "true") == 0 || 187 strcasecmp(value, "yes") == 0) 188 boolvalue = true; 189 else if (strcasecmp(value, "0") == 0 || 190 strcasecmp(value, "false") == 0 || 191 strcasecmp(value, "no") == 0) 192 boolvalue = false; 193 else 194 errx(EXIT_FAILURE, "Invalid boolean value `%s'", value); 195 196 prop_dictionary_set(props, name, prop_bool_create(boolvalue)); 197} 198 199static void 200parse_int_param(prop_dictionary_t props, const char *name, 201 const char *value) 202{ 203 int64_t intvalue; 204 205 assert(name != NULL); 206 assert(value != NULL); 207 208 if (dehumanize_number(value, &intvalue) != 0) 209 err(EXIT_FAILURE, "Invalid integer value `%s'", value); 210 211 prop_dictionary_set(props, name, 212 prop_number_create_integer(intvalue)); 213} 214 215static void 216parse_param(prop_dictionary_t props, const char *origstr, 217 void (*fmt_handler)(prop_dictionary_t, const char *, const char *)) 218{ 219 char *name, *value; 220 221 name = strdup(origstr); 222 223 value = strchr(name, '='); 224 if (value == NULL) { 225 free(name); 226 errx(EXIT_FAILURE, "Invalid parameter `%s'", origstr); 227 } 228 *value++ = '\0'; 229 230 fmt_handler(props, name, value); 231 232 free(name); 233} 234 235static void 236parse_string_param(prop_dictionary_t props, const char *name, 237 const char *value) 238{ 239 240 assert(name != NULL); 241 assert(value != NULL); 242 243 prop_dictionary_set(props, name, prop_string_create_cstring(value)); 244} 245 246static void 247usage(void) 248{ 249 250 (void)fprintf(stderr, 251 "Usage: %s [-f] [-b var=boolean] [-i var=integer] " 252 "[-s var=string] module\n" 253 " %s -p [-b var=boolean] [-d var] [-i var=integer] " 254 "[-m plist]\n [-s var=string]\n", 255 getprogname(), getprogname()); 256 exit(EXIT_FAILURE); 257} 258 259static void 260merge_dicts(prop_dictionary_t existing_dict, const prop_dictionary_t new_dict) 261{ 262 prop_dictionary_keysym_t props_keysym; 263 prop_object_iterator_t props_iter; 264 prop_object_t props_obj; 265 const char *props_key; 266 267 props_iter = prop_dictionary_iterator(new_dict); 268 if (props_iter == NULL) { 269 errx(EXIT_FAILURE, "Failed to iterate new property list"); 270 } 271 272 while ((props_obj = prop_object_iterator_next(props_iter)) != NULL) { 273 props_keysym = (prop_dictionary_keysym_t)props_obj; 274 props_key = prop_dictionary_keysym_cstring_nocopy(props_keysym); 275 props_obj = prop_dictionary_get_keysym(new_dict, props_keysym); 276 if ((props_obj == NULL) || !prop_dictionary_set(existing_dict, 277 props_key, props_obj)) { 278 errx(EXIT_FAILURE, "Failed to copy " 279 "existing property list"); 280 } 281 } 282 prop_object_iterator_release(props_iter); 283 284 return; 285} 286