// найти аргумент cli_result_t cli_parse ( cli_arg_t *Args, int argc, char** argv ) { cli_result_t Result = CLI_SUCCESS; // номер аргумента из полученного списка int i = 1; // кол-во необходимых аргументов size_t NeedArgAmount = get_need_arg_amount ( Args ); while ( ( i < argc ) && ( Result == CLI_SUCCESS ) ) { // найти аргумент cli_arg_t *Arg; switch ( get_argtype ( argv[ i ] ) ) { case CLI_LONG_ARG: Arg = find_arg_by_longname ( Args, argv[ i ] + 2 ); break; case CLI_SHORT_ARG: Arg = find_arg_by_shortname ( Args, argv[ i ][ 1 ] ); break; default: Arg = NULL; Result = CLI_ERROR_ARGTYPE; // ошибка определения типа аргумента break; } if ( Arg != NULL ) { // аргумент обязателен if ( Arg->ArgNeed == CLI_REQUIRED_ARG ) NeedArgAmount--; // поиск значения аргумента const char *Val; if ( Arg->ValNeed != CLI_NO_VAL ) // обязателен или опционален { Val = find_val ( argv[ i ] ); if ( Arg->ValNeed == CLI_REQUIRED_VAL && Val == NULL ) { Result = CLI_ERROR_NOVAL; } Result = ( Arg->Handler ( Arg->Var, Val ) == 0 ) ? CLI_SUCCESS : CLI_ERROR_HANDLER; } else { Val = NULL; Result = ( Arg->Handler ( Arg->Var, Val ) == 0 ) ? CLI_SUCCESS : CLI_ERROR_HANDLER; } } i++; } return ( !NeedArgAmount ) ? Result : CLI_ERROR_NEEDARG; }
void generic_free_arg(struct syscallrecord *rec) { struct syscallentry *entry; unsigned int i, call; call = rec->nr; entry = syscalls[call].entry; for_each_arg(i) { enum argtype argtype; argtype = get_argtype(entry, i); if (argtype == ARG_IOVEC) free((void *) get_argval(rec, i)); } }
// поиск аргумента static cli_arg_t* find_arg ( cli_arg_t *Args, const char *ArgName ) { cli_arg_t *Arg; // определение длинны аргумента switch ( get_argtype ( ArgName ) ) { case CLI_LONG_ARG: Arg = find_arg_by_longname ( Args, ArgName + 2 ); break; case CLI_SHORT_ARG: Arg = find_arg_by_shortname ( Args, ArgName[ 1 ] ); break; default: Arg = NULL; break; } return Arg; }
static unsigned long fill_arg(struct syscallrecord *rec, unsigned int argnum) { struct syscallentry *entry; unsigned int call; enum argtype argtype; call = rec->nr; entry = syscalls[call].entry; if (argnum > entry->num_args) return 0; argtype = get_argtype(entry, argnum); switch (argtype) { case ARG_UNDEFINED: if (RAND_BOOL()) return (unsigned long) rand64(); return (unsigned long) get_writable_address(page_size); case ARG_FD: if (RAND_BOOL()) { unsigned int i; /* If this is the 2nd or more ARG_FD, make it unique */ for (i = 0; i < argnum; i++) { enum argtype arg; arg = get_argtype(entry, i); if (arg == ARG_FD) return get_new_random_fd(); } } return get_random_fd(); case ARG_LEN: return (unsigned long) get_len(); case ARG_ADDRESS: return handle_arg_address(rec, argnum); case ARG_NON_NULL_ADDRESS: return (unsigned long) get_non_null_address(); case ARG_MMAP: return (unsigned long) get_map(); case ARG_PID: return (unsigned long) get_pid(); case ARG_RANGE: return handle_arg_range(entry, argnum); case ARG_OP: /* Like ARG_LIST, but just a single value. */ return handle_arg_op(entry, argnum); case ARG_LIST: return handle_arg_list(entry, argnum); case ARG_CPU: return (unsigned long) get_cpu(); case ARG_PATHNAME: return (unsigned long) generate_pathname(); case ARG_IOVEC: return handle_arg_iovec(entry, rec, argnum); case ARG_IOVECLEN: case ARG_SOCKADDRLEN: /* We already set the len in the ARG_IOVEC/ARG_SOCKADDR case * So here we just return what we had set there. */ return get_argval(rec, argnum); case ARG_SOCKADDR: return handle_arg_sockaddr(entry, rec, argnum); case ARG_MODE_T: return handle_arg_mode_t(); case ARG_SOCKETINFO: return (unsigned long) get_rand_socketinfo(); } BUG("unreachable!\n"); }
static unsigned long fill_arg(struct syscallrecord *rec, unsigned int argnum) { struct syscallentry *entry; unsigned int call; enum argtype argtype; call = rec->nr; entry = syscalls[call].entry; if (argnum > entry->num_args) return 0; argtype = get_argtype(entry, argnum); switch (argtype) { case ARG_UNDEFINED: return (unsigned long) rand64(); case ARG_FD: return get_random_fd(); case ARG_LEN: return (unsigned long) get_len(); case ARG_ADDRESS: return handle_arg_address(rec, argnum); case ARG_NON_NULL_ADDRESS: return (unsigned long) get_non_null_address(); case ARG_MMAP: return (unsigned long) get_map(); case ARG_PID: return (unsigned long) get_pid(); case ARG_RANGE: return handle_arg_range(entry, argnum); case ARG_OP: /* Like ARG_LIST, but just a single value. */ return handle_arg_op(entry, argnum); case ARG_LIST: return handle_arg_list(entry, argnum); case ARG_RANDPAGE: return handle_arg_randpage(); case ARG_CPU: return (unsigned long) get_cpu(); case ARG_PATHNAME: return (unsigned long) generate_pathname(); case ARG_IOVEC: return handle_arg_iovec(entry, rec, argnum); case ARG_IOVECLEN: case ARG_SOCKADDRLEN: /* We already set the len in the ARG_IOVEC/ARG_SOCKADDR case * So here we just return what we had set there. */ return get_argval(rec, argnum); case ARG_SOCKADDR: return handle_arg_sockaddr(entry, rec, argnum); case ARG_MODE_T: return handle_arg_mode_t(); } BUG("unreachable!\n"); }