/* * Copyright (c) 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: t-conf-6.c,v 1.2 2006/12/24 00:20:24 ca Exp $") #if SM_LIBCONF_ALONE #include #include #include #include "sm-conf.h" #else /* SM_LIBCONF_ALONE */ #include "sm/string.h" #include "sm/net.h" #include "sm/sm-conf.h" #include #endif /* SM_LIBCONF_ALONE */ /* ** Just a test program to play around with libconf. ** union_choice ** distinguish union types by a unique element in each part */ enum vehicle_type_E { AIRPLANE = 1, BOAT = 2, CAR = 3 }; typedef enum vehicle_type_E vehicle_type_T; typedef union vehicle_U { vehicle_type_T vehicle_type; struct { vehicle_type_T air_type; char *air_flight; int air_passengers; } airplane; struct { vehicle_type_T boat_type; int boat_knots; char *boat_name; } boat; struct { vehicle_type_T car_type; int car_mpg; char *car_plate; } car; } vehicle_T; static 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 } }; static 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 } }; static 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, "", sm_conf_type_union_type, offsetof(vehicle_T, vehicle_type), sizeof(vehicle_type_T) }, { SM_CONF_DEF_MAGIC, "flight", sm_conf_type_union_choice, AIRPLANE, sizeof(vehicle_T), /* default */ NULL, /* flags */ 0, air_definitions }, { SM_CONF_DEF_MAGIC, "name", sm_conf_type_union_choice, BOAT, sizeof(vehicle_T), /* default */ NULL, /* flags */ 0, boat_definitions }, { SM_CONF_DEF_MAGIC, "plate", sm_conf_type_union_choice, CAR, sizeof(vehicle_T), /* default */ NULL, /* flags */ 0, car_definitions }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; typedef struct { vehicle_T s_garage; } mts_T; sm_conf_definition_T mts_def[] = { { SM_CONF_DEF_MAGIC, "vehicle", sm_conf_type_union, offsetof(mts_T, s_garage.vehicle_type), sizeof(vehicle_type_T), NULL, 0, vehicle_definitions }, /* sentinel */ { SM_CONF_DEF_MAGIC, NULL } }; static mts_T mts; static void print_mts(mts_T *st) { switch (st->s_garage.vehicle_type) { case AIRPLANE: printf("airplane=\"%s\"\n", st->s_garage.airplane.air_flight); break; case BOAT: printf("boat=\"%s\"\n", st->s_garage.boat.boat_name); break; case CAR: printf("car=\"%s\"\n", st->s_garage.car.car_plate); break; default: break; } } static int process(char const *name, FILE *fp, const char *ssname) { sm_conf_T *stream; int err; char buf[SM_CONF_ERROR_BUFFER_SIZE]; char const *e = NULL; 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) { 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; } if ((err = sm_conf_scan(stream, mts_def, 0, &mts)) != 0) { fprintf(stderr, "(while scanning) %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 3; } print_mts(&mts); #if 0 sm_conf_destroy(stream); #endif /* 0 */ return 0; } int main(int ac, char **av) { int ai, c, ret, done; char *ssname; done = 0; ssname = NULL; while ((c = getopt(ac, av, "f:N:o:v:")) != -1) { switch (c) { case 'f': ret = process(optarg, NULL, ssname); if (ret != 0) return ret; done = 1; break; case 'N': ssname = strdup(optarg); if (ssname == NULL) return ENOMEM; break; } } ac -= optind; av += optind; if (done) { print_mts(&mts); return 0; } if (ac == 0) return process("*stdin*", stdin, ssname); for (ai = 0; ai < ac; ai++) { int ret = process(av[ai], NULL, ssname); if (ret != 0) return ret; } return 0; }