/* @configure_input@ */ /* ** Copyright 2000-2004 University of Illinois Board of Trustees ** Copyright 2000-2004 Mark D. Roth ** All rights reserved. ** ** @NETIO_PREFIX@_netio_options.c - netio option code ** ** Mark D. Roth */ #include <@NETIO_PREFIX@_netio_internal.h> #include #ifdef STDC_HEADERS # include # include #endif /****************************************************************************** *** value type information ******************************************************************************/ /* ** value types for options */ enum value_types { VAL_TYPE_UNSIGNED_SHORT = 1, VAL_TYPE_TIME_T, VAL_TYPE_LONG, VAL_TYPE_NETIO_HOOKFUNC_T, VAL_TYPE_CHAR_P, VAL_TYPE_VOID_P }; /* ** size for each type */ struct type_size { enum value_types ts_type; size_t ts_size; }; typedef struct type_size type_size_t; /* ** table of sizes for each value type */ static const type_size_t type_sizes[] = { { VAL_TYPE_UNSIGNED_SHORT, sizeof(unsigned short) }, { VAL_TYPE_TIME_T, sizeof(time_t) }, { VAL_TYPE_LONG, sizeof(long) }, { VAL_TYPE_NETIO_HOOKFUNC_T, sizeof(netio_hookfunc_t) }, { VAL_TYPE_CHAR_P, sizeof(char *) }, { VAL_TYPE_VOID_P, sizeof(void *) }, { 0, 0 } }; /* ** utility function for finding the size for a given type */ static size_t _type_sizeof(enum value_types value_type) { int i; for (i = 0; type_sizes[i].ts_type != 0; i++) { if (type_sizes[i].ts_type == value_type) return type_sizes[i].ts_size; } return (size_t)0; } /****************************************************************************** *** option description information ******************************************************************************/ /* ** finds the offset within the NETIO handle of a given field */ #define netio_field_offset(field) \ ((unsigned int) (((char *) (&(((NETIO *)NULL)->field))) - ((char *)NULL))) /* ** description of an option */ struct netio_option_description { int o_option; /* option number */ size_t o_offset; /* offset of field into NETIO struct */ enum value_types o_type; /* value type */ }; typedef struct netio_option_description netio_option_description_t; /* ** here's the actual table of option descriptions */ static const netio_option_description_t netio_option_descriptions[] = { { NETIO_OPT_DEFAULT_SERVICE, netio_field_offset(n_default_service), VAL_TYPE_CHAR_P }, { NETIO_OPT_DEFAULT_PORT, netio_field_offset(n_default_port), VAL_TYPE_UNSIGNED_SHORT }, { NETIO_OPT_SEND_HOOK, netio_field_offset(n_sendhook), VAL_TYPE_NETIO_HOOKFUNC_T }, { NETIO_OPT_RECV_HOOK, netio_field_offset(n_recvhook), VAL_TYPE_NETIO_HOOKFUNC_T }, { NETIO_OPT_HOOK_HANDLE, netio_field_offset(n_hook_handle), VAL_TYPE_VOID_P }, { NETIO_OPT_HOOK_DATA, netio_field_offset(n_hook_data), VAL_TYPE_VOID_P }, { 0, 0, 0 } }; /* ** utility function for finding the right option description in the table */ static const netio_option_description_t * _find_option_description(int option) { int i; for (i = 0; netio_option_descriptions[i].o_option != 0; i++) { if (netio_option_descriptions[i].o_option == option) return &(netio_option_descriptions[i]); } return NULL; } /* ** set option defaults */ void @NETIO_PREFIX@_netio_init_options(NETIO *netio) { /* ** netio_connect() uses calloc(3) to create the NETIO handle, ** so we only need to set those options that have a non-zero ** default value */ #if 0 netio_set_options( netio, NETIO_OPT_PASSIVE, (unsigned short)1, NETIO_OPT_CACHE_MAXSIZE, (long)-1, NETIO_OPT_CACHE_EXPIRE, (long)-1, 0 ); #endif } /****************************************************************************** *** code for setting options ******************************************************************************/ void @NETIO_PREFIX@_netio_vset_options(NETIO *netio, va_list args) { const netio_option_description_t *netio_option_description; int option; void *ptr; unsigned short val_unsigned_short; unsigned short *ptr_unsigned_short; time_t val_time_t; time_t *ptr_time_t; long val_long; long *ptr_long; netio_hookfunc_t val_netio_hookfunc_t; netio_hookfunc_t *ptr_netio_hookfunc_t; void *val_void_p; void **ptr_void_p; char **ptr_char_p; char *cp; while ((option = va_arg(args, int)) != 0) { #ifdef DEBUG printf(" _vnetio_set_options(): option=%d\n", option); #endif netio_option_description = _find_option_description(option); if (netio_option_description == NULL) continue; ptr = ((char *)netio + netio_option_description->o_offset); switch (netio_option_description->o_type) { case VAL_TYPE_UNSIGNED_SHORT: ptr_unsigned_short = (unsigned short *)ptr; /* ** NOTE: we use int instead of short when ** calling va_arg() because short will be ** promoted to int when passed to a ** varags function */ *ptr_unsigned_short = va_arg(args, unsigned int); #ifdef DEBUG printf(" _vnetio_set_options(): value=%hu\n", *ptr_unsigned_short); #endif break; case VAL_TYPE_TIME_T: ptr_time_t = (time_t *)ptr; *ptr_time_t = va_arg(args, time_t); #ifdef DEBUG printf(" _vnetio_set_options(): value=%lu\n", (unsigned long)*ptr_time_t); #endif break; case VAL_TYPE_LONG: ptr_long = (long *)ptr; *ptr_long = va_arg(args, long); #ifdef DEBUG printf(" _vnetio_set_options(): value=%ld\n", *ptr_long); #endif break; case VAL_TYPE_NETIO_HOOKFUNC_T: ptr_netio_hookfunc_t = (netio_hookfunc_t *)ptr; *ptr_netio_hookfunc_t = va_arg(args, netio_hookfunc_t); #ifdef DEBUG printf(" _vnetio_set_options(): value=0x%lx\n", *ptr_netio_hookfunc_t); #endif break; case VAL_TYPE_CHAR_P: ptr_char_p = (char **)ptr; cp = va_arg(args, char *); if (cp == NULL) *ptr_char_p = cp; else { if (*ptr_char_p != NULL) free(*ptr_char_p); *ptr_char_p = strdup(cp); } #ifdef DEBUG printf(" _vnetio_set_options(): value=\"%s\"\n", *ptr_char_p); #endif break; case VAL_TYPE_VOID_P: ptr_void_p = (void **)ptr; *ptr_void_p = va_arg(args, void *); #ifdef DEBUG printf(" _vnetio_set_options(): value=0x%lx\n", *ptr_void_p); #endif break; default: /* can't happen */ break; } } } /* ** set options */ void @NETIO_PREFIX@_netio_set_options(NETIO *netio, ...) { va_list args; va_start(args, netio); @NETIO_PREFIX@_netio_vset_options(netio, args); va_end(args); } /****************************************************************************** *** code for getting options ******************************************************************************/ static void @NETIO_PREFIX@_netio_vget_options(NETIO *netio, va_list args) { const netio_option_description_t *netio_option_description; int option; void *opt_ptr, *arg_ptr; size_t sz; while ((option = va_arg(args, int)) != 0) { netio_option_description = _find_option_description(option); if (netio_option_description == NULL) return; opt_ptr = ((char *)netio + netio_option_description->o_offset); sz = _type_sizeof(netio_option_description->o_type); arg_ptr = va_arg(args, void *); #ifdef DEBUG printf(" _vnetio_get_options(): option=%d sz=%lu\n", option, (unsigned long)sz); #endif memcpy(arg_ptr, opt_ptr, sz); } } /* ** get options */ void @NETIO_PREFIX@_netio_get_options(NETIO *netio, ...) { va_list args; va_start(args, netio); @NETIO_PREFIX@_netio_vget_options(netio, args); va_end(args); }