/* * Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: demo-isset.c,v 1.6 2005/09/26 23:26:41 ca Exp $") #if SM_LIBCONF_ALONE #include #include #include #include #include "sm-conf.h" #else /* SM_LIBCONF_ALONE */ #include "sm/string.h" #include "sm/sm-conf.h" #include "sm/net.h" #include #endif /* SM_LIBCONF_ALONE */ /* DEMO-ISSET.C -- demo sm_conf_scan() */ char const * const opt[] = { "int_u32", "unnamed.num", "sub{foo}sub_u32", NULL }; #ifndef offsetof #define offsetof(type, member) ((char *)&((type *)0)->member - (char *)0) #endif typedef struct substructure { char const *sub_string; unsigned int sub_u32; } substructure; static sm_conf_definition_T subdefinitions[] = { { SM_CONF_DEF_MAGIC, "sub_u32", sm_conf_type_u32, offsetof(substructure, sub_u32), sizeof(unsigned int), "1" }, { SM_CONF_DEF_MAGIC, "sub_string", sm_conf_type_string, offsetof(substructure, sub_string), 0, "Foo!" }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; static sm_conf_definition_T subdefinitions_lefty[] = { { SM_CONF_DEF_MAGIC, "sub_lefty", sm_conf_type_bool, 0, sizeof(unsigned int), "yes" }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; static sm_conf_definition_T subdefinitions_unnamed[] = { { SM_CONF_DEF_MAGIC, "num", sm_conf_type_u32, 0, sizeof(unsigned int), "1" }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; typedef union vehicle_U { enum vehicle_type { AIRPLANE = 1, BOAT = 2, CAR = 3 } type; struct { enum vehicle_type air_type; char *air_flight; int air_passengers; } airplane; struct { enum vehicle_type boat_type; int boat_knots; char *boat_name; } boat; struct { enum vehicle_type car_type; int car_mpg; char *car_plate; } car; } vehicle_T; sm_conf_definition_T const air_definitions[] = { { SM_CONF_DEF_MAGIC, "flight", sm_conf_type_string, offsetof(vehicle_T, airplane.air_flight), 0, NULL }, { SM_CONF_DEF_MAGIC, "passengers", sm_conf_type_u32, offsetof(vehicle_T, airplane.air_passengers), sizeof(unsigned int), "1" }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T const boat_definitions[] = { { SM_CONF_DEF_MAGIC, "name", sm_conf_type_string, offsetof(vehicle_T, boat.boat_name), 0, NULL }, { SM_CONF_DEF_MAGIC, "knots", sm_conf_type_u32, offsetof(vehicle_T, boat.boat_knots), sizeof(unsigned int), NULL }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T const car_definitions[] = { { SM_CONF_DEF_MAGIC, "plate", sm_conf_type_string, offsetof(vehicle_T, car.car_plate), 0, NULL }, { SM_CONF_DEF_MAGIC, "mpg", sm_conf_type_u32, offsetof(vehicle_T, car.car_mpg), sizeof(unsigned int), NULL }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T vehicle_definitions[] = { { SM_CONF_DEF_MAGIC, "airplane", sm_conf_type_union_choice, AIRPLANE, sizeof(vehicle_T), /* default */ NULL, /* flags */ 0, air_definitions }, { SM_CONF_DEF_MAGIC, "boat", sm_conf_type_union_choice, BOAT, sizeof(vehicle_T), /* default */ NULL, /* flags */ 0, boat_definitions }, { SM_CONF_DEF_MAGIC, "car", sm_conf_type_union_choice, CAR, sizeof(vehicle_T), /* default */ NULL, /* flags */ 0, car_definitions }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; typedef struct { unsigned long long_u32; unsigned int int_u32; unsigned short short_u32; unsigned short dice_roll; /* between 2 and 12 */ unsigned long duration; char const *string; char suffix[4]; unsigned int bool_true; unsigned int bool_false; sm_conf_bytes_T bytes; unsigned int color; uint32_t flags; ipv4_T ipv4; substructure sub; unsigned int lefty; vehicle_T vehicle; char *twostrings[2]; char **argv; unsigned int unnamed; } structure; sm_conf_definition_T const dice_roll_constraints[] = { { SM_CONF_DEF_MAGIC, "", sm_conf_type_u32_minimum, 2 }, { SM_CONF_DEF_MAGIC, "", sm_conf_type_u32_maximum, 12 }, /* Sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T const duration_suffixes[] = { { SM_CONF_DEF_MAGIC, "s", sm_conf_type_u32_suffix, 1 }, { SM_CONF_DEF_MAGIC, "m", sm_conf_type_u32_suffix, 60 }, { SM_CONF_DEF_MAGIC, "h", sm_conf_type_u32_suffix, 60 * 60 }, { SM_CONF_DEF_MAGIC, "d", sm_conf_type_u32_suffix, 60 * 60 * 24 }, { SM_CONF_DEF_MAGIC, "w", sm_conf_type_u32_suffix, 60 * 60 * 24 * 7 }, { SM_CONF_DEF_MAGIC, "y", sm_conf_type_u32_suffix, 60 * 60 * 24 * 365 }, /* Sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T const color_names[] = { { SM_CONF_DEF_MAGIC, "yellow", sm_conf_type_choice_value, 0xFFFF00}, { SM_CONF_DEF_MAGIC, "orange", sm_conf_type_choice_value, 0xCCCC00}, { SM_CONF_DEF_MAGIC, "red", sm_conf_type_choice_value, 0xFF0000}, { SM_CONF_DEF_MAGIC, "blue", sm_conf_type_choice_value, 0x0000FF}, { SM_CONF_DEF_MAGIC, "green", sm_conf_type_choice_value, 0x00FF00}, { SM_CONF_DEF_MAGIC, "brown", sm_conf_type_choice_value, 0x333300}, { SM_CONF_DEF_MAGIC, "black", sm_conf_type_choice_value, 0x000000}, { SM_CONF_DEF_MAGIC, "white", sm_conf_type_choice_value, 0xFFFFFF}, /* Sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T const flags_names[] = { { SM_CONF_DEF_MAGIC, "opt1", sm_conf_type_choice_value, 0x000001}, { SM_CONF_DEF_MAGIC, "opt2", sm_conf_type_choice_value, 0x000002}, { SM_CONF_DEF_MAGIC, "opt3", sm_conf_type_choice_value, 0x000010}, /* Sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; sm_conf_definition_T definitions[] = { /* ** N U M B E R S */ { SM_CONF_DEF_MAGIC, "long_u32", sm_conf_type_u32, offsetof(structure, long_u32), sizeof(unsigned long), "1" }, { SM_CONF_DEF_MAGIC, "int_u32", sm_conf_type_u32, offsetof(structure, int_u32), sizeof(unsigned int), "2" }, { SM_CONF_DEF_MAGIC, "short_u32", sm_conf_type_u32, offsetof(structure, short_u32), sizeof(unsigned short), "3" }, { SM_CONF_DEF_MAGIC, "ipv4", sm_conf_type_ipv4, offsetof(structure, ipv4), sizeof(ipv4_T), "0" }, /* A number that's constrained. */ { SM_CONF_DEF_MAGIC, "dice_roll", sm_conf_type_u32, offsetof(structure, dice_roll), sizeof(unsigned short), "7", 0, dice_roll_constraints }, /* A number with suffix multipliers. */ { SM_CONF_DEF_MAGIC, "duration", sm_conf_type_u32, offsetof(structure, duration), sizeof(unsigned long), "0", 0, duration_suffixes }, /* ** S T R I N G S */ /* Your basic string. */ { SM_CONF_DEF_MAGIC, "string", sm_conf_type_string, offsetof(structure, string), 0, "Hello, World?" }, /* fixed-length string */ { SM_CONF_DEF_MAGIC, "suffix", sm_conf_type_string, offsetof(structure, suffix), 4, "c" }, /* argv-style NULL-terminated array, char ** storage. */ { SM_CONF_DEF_MAGIC, "argv", sm_conf_type_argv, offsetof(structure, argv), 0 }, /* argv-style NULL-terminated array, char *[] storage. */ { SM_CONF_DEF_MAGIC, "twostrings", sm_conf_type_argv, offsetof(structure, twostrings), 2 }, /* ** B O O L E A N */ { SM_CONF_DEF_MAGIC, "bool_true", sm_conf_type_bool, offsetof(structure, bool_true), sizeof(unsigned int), "true" }, { SM_CONF_DEF_MAGIC, "bool_false", sm_conf_type_bool, offsetof(structure, bool_false), sizeof(unsigned int), "false" }, /* ** B Y T E S T R I N G */ { SM_CONF_DEF_MAGIC, "bytes", sm_conf_type_bytes, offsetof(structure, bytes) }, /* ** E N U M */ { SM_CONF_DEF_MAGIC, "color", sm_conf_type_choice, offsetof(structure, color), sizeof(unsigned int), "green", 0, color_names }, { SM_CONF_DEF_MAGIC, "flags", sm_conf_type_choice, offsetof(structure, flags), sizeof(uint32_t), "0", SM_CONF_FLAG_MULTIPLE | SM_CONF_FLAG_NUMERIC, flags_names }, /* ** S E C T I O N */ { SM_CONF_DEF_MAGIC, "sub", sm_conf_type_section, offsetof(structure, sub), sizeof(struct substructure), NULL, 0, subdefinitions }, { SM_CONF_DEF_MAGIC, "sub{lefty}", sm_conf_type_section, offsetof(structure, lefty), sizeof(unsigned int), NULL, 0, subdefinitions_lefty }, { SM_CONF_DEF_MAGIC, "unnamed", sm_conf_type_section, offsetof(structure, unnamed), sizeof(unsigned int), NULL, 0, subdefinitions_unnamed }, /* ** U N I O N */ { SM_CONF_DEF_MAGIC, "vehicle", sm_conf_type_union, offsetof(structure, vehicle.type), sizeof(enum vehicle_type), NULL, 0, vehicle_definitions }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; #if 0 static void print_structure(structure *s) { size_t i; printf("long_u32: %lu\n", s->long_u32); printf("int_u32: %u\n", s->int_u32); printf("short_u32: %hu\n", s->short_u32); printf("ipv4: %X\n", (unsigned int) htonl(s->ipv4)); printf("dice_roll: %hu\n", s->dice_roll); printf("duration: %lu\n", s->duration); printf("string: '%s'\n", s->string); printf("suffix: '%s'\n", s->suffix); printf("bool_true: '%d'\n", s->bool_true); printf("bool_false: '%d'\n", s->bool_false); printf("bytes: [%d]", (int)s->bytes.scb_size); for (i = 0; i < s->bytes.scb_size; i++) printf(" %2.2hx", (unsigned char)s->bytes.scb_data[i]); putchar('\n'); printf("color: 0x%6.6x\n", s->color); printf("flags: 0x%6.6x\n", s->flags); printf("sub.sub_u32: %d\n", s->sub.sub_u32); printf("sub.sub_string: %s\n", s->sub.sub_string); printf("lefty: %d\n", s->lefty); printf("argv:"); if (s->argv == NULL) fputs(" NULL", stdout); else for (i = 0; s->argv[i] != NULL; i++) printf(" '%s'", s->argv[i]); putchar('\n'); printf("twostrings:"); for (i = 0; i < 2 && s->twostrings[i] != NULL; i++) printf(" '%s'", s->twostrings[i]); putchar('\n'); } #endif /* 0 */ static int process(char const *name, FILE *fp) { sm_conf_T *stream; int err; int val; size_t i; if (((stream = sm_conf_new(name ? name : "*stdin*"))) == NULL) { fprintf(stderr, "error -- sm_conf_new() returns NULL!\n"); return 1; } if ((err = sm_conf_read_FILE(stream, name, fp)) != 0) { char buf[SM_CONF_ERROR_BUFFER_SIZE]; char const *e = NULL; fprintf(stderr, "%s: %s\n", name ? name : "*stdin*", sm_conf_strerror(err, buf, sizeof buf)); while ((e = sm_conf_syntax_error(stream, e)) != NULL) fprintf(stderr, "%s\n", e); sm_conf_destroy(stream); return 2; } for (i = 0; opt[i] != NULL; i++) { val = 0; err = sm_conf_get(stream, opt[i], sm_conf_type_u32, NULL, 0, &val, sizeof val); if (err) { char buf[200]; printf("%s: %s\n", opt[i], sm_conf_strerror(err, buf, sizeof buf)); } else { printf("%s: ok.\n", opt[i]); } } sm_conf_destroy(stream); return 0; } int main(int ac, char **av) { int ai; if (ac == 1) return process("*stdin*", stdin); for (ai = 1; ai < ac; ai++) { int ret = process(av[ai], NULL); if (ret != 0) return ret; } return 0; }