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