| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <getopt.h> | |
| #include <string.h> | |
| #include <dlfcn.h> | |
| extern char *optarg; | |
| extern int optind, opterr, optopt; | |
| static struct option long_options[] = { | |
| {"library", required_argument, 0, 'l'}, | |
| {"symbol", required_argument, 0, 's'}, | |
| {"help", no_argument, 0, 'h'}, | |
| {0, 0, 0, 0}, | |
| }; | |
| /* This array must parallel long_options[] */ | |
| static const char *descriptions[] = { | |
| "specify a library path to look up symbol", | |
| "specify symbol to look up", | |
| "print this help screen", | |
| }; | |
| void print_help(const char *name) { | |
| fprintf(stdout, | |
| "invokation:\n" | |
| "\t%s [-l <libname>] -s <symbol name>\n" | |
| "\t%s -h\n\n", name, name); | |
| fprintf(stdout, "options:\n"); | |
| struct option *opt = long_options; | |
| const char **desc = descriptions; | |
| while (opt->name) { | |
| fprintf(stdout, "\t-%c/--%s%s: %s\n", | |
| opt->val, | |
| opt->name, | |
| (opt->has_arg ? " (argument)" : ""), | |
| *desc); | |
| opt++; | |
| desc++; | |
| } | |
| } | |
| int get_options(int argc, char **argv, char **lib, char **sym) | |
| { | |
| int c; | |
| *lib = 0; | |
| *sym = 0; | |
| while (1) { | |
| /* getopt_long stores the option index here. */ | |
| int option_index = 0; | |
| c = getopt_long (argc, argv, | |
| "l:s:h", | |
| long_options, | |
| &option_index); | |
| /* Detect the end of the options. */ | |
| if (c == -1) break; | |
| switch (c) { | |
| case 'l': | |
| *lib = strdup(optarg); | |
| break; | |
| case 's': | |
| *sym = strdup(optarg); | |
| break; | |
| case 'h': print_help(argv[0]); exit(EXIT_FAILURE); break; | |
| case '?': | |
| /* getopt_long already printed an error message. */ | |
| break; | |
| default: | |
| fprintf(stderr, "Unknown option"); | |
| exit(EXIT_FAILURE); | |
| } | |
| } | |
| return optind; | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| char *libname, *symname, *prog = *argv; | |
| get_options(argc, argv, &libname, &symname); | |
| if (symname == NULL) { | |
| fprintf(stderr, "You must specify a symbol!\n"); | |
| print_help(prog); | |
| exit(EXIT_FAILURE); | |
| } | |
| { | |
| const char *dlerr; | |
| void *handle, *symbol; | |
| printf("opening library [%s]\n", libname); | |
| dlerr = dlerror(); | |
| handle = libname ? dlopen(libname, RTLD_NOW) : RTLD_DEFAULT; | |
| dlerr = dlerror(); | |
| if (dlerr != NULL) fprintf(stderr, "dlopen() error: %s\n", dlerr); | |
| printf("opening symbol [%s]\n", symname); | |
| symbol = dlsym(handle, symname); | |
| dlerr = dlerror(); | |
| if (dlerr != NULL) fprintf(stderr, "dlsym() error: %s\n", dlerr); | |
| printf("closing library [%s]\n", libname); | |
| dlclose(handle); | |
| dlerr = dlerror(); | |
| if (dlerr != NULL) fprintf(stderr, "dlclose() error: %s\n", dlerr); | |
| else printf("successfully opened symbol\n"); | |
| } | |
| if (libname != NULL) free(libname); | |
| if (symname != NULL) free(symname); | |
| return 0; | |
| } |