/*----------------------------------------------------- Implementation of Sample for command line options This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Copyright Fred Smith 2006 All rights reserved Generated by aargh 1.2 Sun Mar 19 11:14:23 2006 -----------------------------------------------------*/ #include #include #include #include #include #include #include "sample_opts.h" static void initialize( Sample * pOpts ) { pOpts->new_argc = 0; pOpts->new_argv = NULL; pOpts->sample_bool = 0; pOpts->sample_dates_found = 0; pOpts->sample_dates_list = NULL; pOpts->host_found = 0; pOpts->host = NULL; pOpts->sample_int_found = 0; pOpts->sample_int = 0; pOpts->multiple_ints_found = 0; pOpts->multiple_ints_list = NULL; pOpts->universe_found = 0; pOpts->universe = 0; } int get_sample_opts( int argc, char * argv[], Sample * pOpts ) { int rc = 0; /* return code */ struct sample_dates_node * last_sample_dates = NULL; unsigned long sample_int_value = 0; unsigned long multiple_ints_value = 0; struct multiple_ints_node * last_multiple_ints = NULL; unsigned long universe_value = 0; char * tail = NULL; int opt; /* Define valid option characters */ const char optstring[] = ":cd:h:i:n:u:"; /* Initialize members of struct */ initialize( pOpts ); /* Suppress error messages from getopt() */ opterr = 0; /* Examine command line options */ while( ( opt = getopt( argc, argv, optstring ) ) != -1 ) { switch( opt ) { case 'c' : /* Get sample_bool */ pOpts->sample_bool = 1; break; case 'd' : /* Get sample_dates */ pOpts->sample_dates_found = 1; /* Check for too long or too short */ if( strlen( optarg ) < 3UL ) { fprintf( stderr, "Argument to -d option \"%s\" " "is less than the minimum length\n", optarg ); rc = 1; break; } if( strlen( optarg ) > 9UL ) { fprintf( stderr, "Argument to -d option \"%s\" " "is more than the maximum length\n", optarg ); rc = 1; break; } /* Call validator function */ if( val_date( optarg ) ) { fprintf( stderr, "Argument to -d option \"%s\" " "is invalid\n", optarg ); rc = 1; } { // Allocate new node, add to linked list struct sample_dates_node * new_sample_dates = malloc( sizeof( struct sample_dates_node ) ); if( new_sample_dates == NULL ) { fputs( "Out of memory!\n", stderr ); return 1; } new_sample_dates->pNext = NULL; new_sample_dates->value = optarg; if( pOpts->sample_dates_list ) last_sample_dates->pNext = new_sample_dates; else pOpts->sample_dates_list = new_sample_dates; last_sample_dates = new_sample_dates; } break; case 'h' : /* Get host */ if( pOpts->host_found ) { fprintf( stderr, "Only one occurrence of -h option allowed\n" ); rc = 1; break; } pOpts->host_found = 1; pOpts->host = optarg; break; case 'i' : /* Get sample_int */ if( pOpts->sample_int_found ) { fprintf( stderr, "Only one occurrence of -i option allowed\n" ); rc = 1; break; } pOpts->sample_int_found = 1; /* Skip white space; check for negative */ while( isspace( (unsigned char) *optarg ) ) ++optarg; if( '-' == *optarg ) { fprintf( stderr, "Negative argument not allowed for " "-i option: \"%s\"\n", optarg ); rc = 1; break; } /* Convert to numeric value */ errno = 0; sample_int_value = strtoul( optarg, &tail, 10 ); if( *tail != '\0' ) { fprintf( stderr, "Invalid or non-numeric argument " "to -i option: \"%s\"\n", optarg ); rc = 1; break; } else if( errno != 0 ) { fprintf( stderr, "Too large argument " "to -i option: \"%s\"\n", optarg ); rc = 1; break; } /* Check for values out of bounds */ if( sample_int_value < 1UL ) { fprintf( stderr, "Argument to -i option \"%s\" " "is less than minimum\n", optarg ); rc = 1; break; } if( sample_int_value > 6UL ) { fprintf( stderr, "Argument to -i option \"%s\" " "exceeds maximum value\n", optarg ); rc = 1; break; } pOpts->sample_int = sample_int_value; break; case 'n' : /* Get multiple_ints */ pOpts->multiple_ints_found = 1; /* Skip white space; check for negative */ while( isspace( (unsigned char) *optarg ) ) ++optarg; if( '-' == *optarg ) { fprintf( stderr, "Negative argument not allowed for " "-n option: \"%s\"\n", optarg ); rc = 1; break; } /* Convert to numeric value */ errno = 0; multiple_ints_value = strtoul( optarg, &tail, 10 ); if( *tail != '\0' ) { fprintf( stderr, "Invalid or non-numeric argument " "to -n option: \"%s\"\n", optarg ); rc = 1; break; } else if( errno != 0 ) { fprintf( stderr, "Too large argument " "to -n option: \"%s\"\n", optarg ); rc = 1; break; } { // Allocate new node, append to linked list struct multiple_ints_node * new_multiple_ints = malloc( sizeof( struct multiple_ints_node ) ); if( new_multiple_ints == NULL ) { fputs( "Out of memory!\n", stderr ); return 1; } new_multiple_ints->pNext = NULL; new_multiple_ints->value = multiple_ints_value; if( pOpts->multiple_ints_list ) last_multiple_ints->pNext = new_multiple_ints; else pOpts->multiple_ints_list = new_multiple_ints; last_multiple_ints = new_multiple_ints; } break; case 'u' : /* Get universe */ if( pOpts->universe_found ) { fprintf( stderr, "Only one occurrence of -u option allowed\n" ); rc = 1; break; } pOpts->universe_found = 1; /* Skip white space; check for negative */ while( isspace( (unsigned char) *optarg ) ) ++optarg; if( '-' == *optarg ) { fprintf( stderr, "Negative argument not allowed for " "-u option: \"%s\"\n", optarg ); rc = 1; break; } /* Convert to numeric value */ errno = 0; universe_value = strtoul( optarg, &tail, 10 ); if( *tail != '\0' ) { fprintf( stderr, "Invalid or non-numeric argument " "to -u option: \"%s\"\n", optarg ); rc = 1; break; } else if( errno != 0 ) { fprintf( stderr, "Too large argument " "to -u option: \"%s\"\n", optarg ); rc = 1; break; } pOpts->universe = universe_value; break; case ':' : /* Missing argument */ fprintf( stderr, "Required argument missing on -%c option\n", (char) optopt ); rc = 1; break; case '?' : /* Invalid option */ fprintf( stderr, "Invalid option '-%c' on command line\n", (char) optopt ); rc = 1; break; default : /* Programmer error */ fprintf( stderr, "Internal error: unexpected value '-%c'" "for optopt", (char) optopt ); rc = 1; break; } /* end switch */ } /* end while */ /* See if required options were supplied; apply defaults */ if( ! pOpts->sample_dates_found ) { fprintf( stderr, "Required option -d not provided on command line\n" ); rc = 1; } if( ! pOpts->host_found ) pOpts->host = "localhost"; if( ! pOpts->sample_int_found ) { fprintf( stderr, "Required option -i not provided on command line\n" ); rc = 1; } if( ! pOpts->universe_found ) pOpts->universe = 42; if( optind > argc ) { /* This should never happen! */ fprintf( stderr, "Program error: found more arguments than expected\n" ); rc = 1; } else { /* Calculate new_argcv and new_argc to reflect */ /* the number of arguments consumed */ pOpts->new_argc = argc - optind + 1; pOpts->new_argv = argv + optind - 1; if( pOpts->new_argc < 2UL ) { fprintf( stderr, "Not enough arguments beyond options; " "must be at least 1\n" ); rc = 1; } if( pOpts->new_argc > 3UL ) { fprintf( stderr, "Too many arguments beyond option; " "must be no more than 2\n" ); rc = 1; } } return rc; } void clear_Sample( Sample * pOpts ) { { sample_dates_node * pTemp = NULL; sample_dates_node * pCurr = pOpts->sample_dates_list; pOpts->sample_dates_list = NULL; while( pCurr ) { pTemp = pCurr->pNext; free( pCurr ); pCurr = pTemp; } } { multiple_ints_node * pTemp = NULL; multiple_ints_node * pCurr = pOpts->multiple_ints_list; pOpts->multiple_ints_list = NULL; while( pCurr ) { pTemp = pCurr->pNext; free( pCurr ); pCurr = pTemp; } } return; }