diff --git a/.gitignore b/.gitignore index e1741f6..a90dfcb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # make gitignore /KoboRoot.tgz -/src/libnmi.so +/src/libnm.so /src/qtplugin.moc /src/qtplugin.o diff --git a/Makefile b/Makefile index 00b823f..c11897b 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ override CXXFLAGS += -march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard override LDFLAGS += -Wl,-rpath,/usr/local/Kobo -Wl,-rpath,/usr/local/Qt-5.2.1-arm/lib endif -all: src/libnmi.so +all: src/libnm.so clean: rm -f $(GENERATED) @@ -59,21 +59,21 @@ gitignore: sed 's/^./\/&/' >> .gitignore install: - install -Dm644 src/libnmi.so $(DESTDIR)/usr/local/Kobo/imageformats/libnmi.so - install -Dm644 res/doc $(DESTDIR)/mnt/onboard/.adds/nmi/doc + install -Dm644 src/libnm.so $(DESTDIR)/usr/local/Kobo/imageformats/libnm.so + install -Dm644 res/doc $(DESTDIR)/mnt/onboard/.adds/nm/doc koboroot: - tar cvzf KoboRoot.tgz --show-transformed --owner=root --group=root --mode="u=rwX,go=rX" --transform="s,src/libnmi.so,./usr/local/Kobo/imageformats/libnmi.so," --transform="s,res/doc,./mnt/onboard/.adds/nmi/doc," src/libnmi.so res/doc + tar cvzf KoboRoot.tgz --show-transformed --owner=root --group=root --mode="u=rwX,go=rX" --transform="s,src/libnm.so,./usr/local/Kobo/imageformats/libnm.so," --transform="s,res/doc,./mnt/onboard/.adds/nm/doc," src/libnm.so res/doc .PHONY: all clean gitignore install koboroot override GENERATED += KoboRoot.tgz -src/libnmi.so: override CFLAGS += $(PTHREAD_CFLAGS) -fPIC -src/libnmi.so: override CXXFLAGS += $(PTHREAD_CFLAGS) $(QT5CORE_CFLAGS) $(QT5WIDGETS_CFLAGS) -fPIC -src/libnmi.so: override LDFLAGS += $(PTHREAD_LIBS) $(QT5CORE_LIBS) $(QT5WIDGETS_LIBS) -ldl -Wl,-soname,libnmi.so -src/libnmi.so: src/qtplugin.o src/init.o src/config.o src/dlhook.o src/failsafe.o src/menu.o src/action_c.o src/action_cc.o +src/libnm.so: override CFLAGS += $(PTHREAD_CFLAGS) -fPIC +src/libnm.so: override CXXFLAGS += $(PTHREAD_CFLAGS) $(QT5CORE_CFLAGS) $(QT5WIDGETS_CFLAGS) -fPIC +src/libnm.so: override LDFLAGS += $(PTHREAD_LIBS) $(QT5CORE_LIBS) $(QT5WIDGETS_LIBS) -ldl -Wl,-soname,libnm.so +src/libnm.so: src/qtplugin.o src/init.o src/config.o src/dlhook.o src/failsafe.o src/menu.o src/action_c.o src/action_cc.o -override LIBRARIES += src/libnmi.so +override LIBRARIES += src/libnm.so override MOCS += src/qtplugin.moc define patw = diff --git a/res/doc b/res/doc index ea79c62..7c3b731 100644 --- a/res/doc +++ b/res/doc @@ -1,4 +1,4 @@ -# nickel-menu-inject (libnmi.so) +# NickelMenu (libnm.so) # # This tool injects menu items into Nickel. # @@ -7,7 +7,7 @@ # error checking, and a failsafe mechanism which automatically uninstalls it as # a last resort. # -# Place your configuration files in this folder (/mnt/onboard/.kobo/.adds/nmi). +# Place your configuration files in this folder (/mnt/onboard/.kobo/.adds/nm). # They can be named anything, and should consist of multiple lines either # starting with # for a comment, or in the the following format: # @@ -43,7 +43,7 @@ # force_usb_connection - forces a usb connection dialog to be shown # rescan_books - forces nickel to rescan books (TODO) # -# For example, you might have a configuration file in KOBOeReader/.adds/nmi/mystuff like: +# For example, you might have a configuration file in KOBOeReader/.adds/nm/mystuff like: # # menu_item :main :Show an error :dbg_error :This is an error message! # menu_item :reader :Invert Screen :nickel_setting :invert @@ -55,7 +55,7 @@ # which can be viewed over telnet or SSH (the username is root) with the command # logread. # -# To uninstall nickel-menu-inject, create a file named KOBOeReader/.adds/nmi/uninstall, -# or manually uninstall it by deleting libnmi.so. You can also uninstall it by +# To uninstall NickelMenu, create a file named KOBOeReader/.adds/nm/uninstall, +# or manually uninstall it by deleting libnm.so. You can also uninstall it by # triggering the failsafe mechanism by turning your Kobo off within 20 seconds # of turning it on. \ No newline at end of file diff --git a/src/action_c.c b/src/action_c.c index 8836ad9..2f859ca 100644 --- a/src/action_c.c +++ b/src/action_c.c @@ -3,21 +3,21 @@ #include "action_c.h" #include "util.h" -int nmi_action_dbgsyslog(const char *arg, char **err_out) { - #define NMI_ERR_RET 1 - NMI_LOG("dbgsyslog: %s", arg); - NMI_RETURN_OK(0); - #undef NMI_ERR_RET +int nm_action_dbgsyslog(const char *arg, char **err_out) { + #define NM_ERR_RET 1 + NM_LOG("dbgsyslog: %s", arg); + NM_RETURN_OK(0); + #undef NM_ERR_RET } -int nmi_action_dbgerror(const char *arg, char **err_out) { - #define NMI_ERR_RET 1 - NMI_RETURN_ERR("%s", arg); - #undef NMI_ERR_RET +int nm_action_dbgerror(const char *arg, char **err_out) { + #define NM_ERR_RET 1 + NM_RETURN_ERR("%s", arg); + #undef NM_ERR_RET } -int nmi_action_kfmon(const char *arg, char **err_out) { - #define NMI_ERR_RET 1 - NMI_RETURN_ERR("not implemented yet (arg=%s)", arg); // TODO - #undef NMI_ERR_RET +int nm_action_kfmon(const char *arg, char **err_out) { + #define NM_ERR_RET 1 + NM_RETURN_ERR("not implemented yet (arg=%s)", arg); // TODO + #undef NM_ERR_RET } diff --git a/src/action_c.h b/src/action_c.h index 7d3ec8c..375a43e 100644 --- a/src/action_c.h +++ b/src/action_c.h @@ -1,12 +1,12 @@ -#ifndef NMI_ACTION_C_H -#define NMI_ACTION_C_H +#ifndef NM_ACTION_C_H +#define NM_ACTION_C_H #ifdef __cplusplus extern "C" { #endif -int nmi_action_dbgsyslog(const char *arg, char **err_out); -int nmi_action_dbgerror(const char *arg, char **err_out); -int nmi_action_kfmon(const char *arg, char **err_out); +int nm_action_dbgsyslog(const char *arg, char **err_out); +int nm_action_dbgerror(const char *arg, char **err_out); +int nm_action_kfmon(const char *arg, char **err_out); #ifdef __cplusplus } diff --git a/src/action_cc.cc b/src/action_cc.cc index d43c310..f147fdc 100644 --- a/src/action_cc.cc +++ b/src/action_cc.cc @@ -13,23 +13,23 @@ typedef void Device; typedef void Settings; typedef void PlugWorkflowManager; -extern "C" int nmi_action_nickelsetting(const char *arg, char **err_out) { - #define NMI_ERR_RET 1 +extern "C" int nm_action_nickelsetting(const char *arg, char **err_out) { + #define NM_ERR_RET 1 Device *(*Device_getCurrentDevice)(); reinterpret_cast(Device_getCurrentDevice) = dlsym(RTLD_DEFAULT, "_ZN6Device16getCurrentDeviceEv"); - NMI_ASSERT(Device_getCurrentDevice, "could not dlsym Device::getCurrentDevice"); + NM_ASSERT(Device_getCurrentDevice, "could not dlsym Device::getCurrentDevice"); void *(*Settings_Settings)(Settings*, Device*, bool); reinterpret_cast(Settings_Settings) = dlsym(RTLD_DEFAULT, "_ZN8SettingsC2ERK6Deviceb"); - NMI_ASSERT(Device_getCurrentDevice, "could not dlsym Settings constructor"); + NM_ASSERT(Device_getCurrentDevice, "could not dlsym Settings constructor"); void *(*Settings_SettingsD)(Settings*); reinterpret_cast(Settings_SettingsD) = dlsym(RTLD_DEFAULT, "_ZN8SettingsD2Ev"); - NMI_ASSERT(Settings_SettingsD, "could not dlsym Settings destructor"); + NM_ASSERT(Settings_SettingsD, "could not dlsym Settings destructor"); Device *dev = Device_getCurrentDevice(); - NMI_ASSERT(dev, "could not get shared nickel device pointer"); + NM_ASSERT(dev, "could not get shared nickel device pointer"); Settings *settings = alloca(128); // way larger than it is, but better to be safe Settings_Settings(settings, dev, false); @@ -54,35 +54,35 @@ extern "C" int nmi_action_nickelsetting(const char *arg, char **err_out) { #define vtable_target(x) reinterpret_cast(reinterpret_cast(x)+8) void *Settings_vtable = dlsym(RTLD_DEFAULT, "_ZTV8Settings"); - NMI_ASSERT(Settings_vtable, "could not dlsym the vtable for Settings"); - NMI_ASSERT(vtable_ptr(settings) == vtable_target(Settings_vtable), "unexpected vtable layout (expected class to start with a pointer to 8 bytes into the vtable)"); + NM_ASSERT(Settings_vtable, "could not dlsym the vtable for Settings"); + NM_ASSERT(vtable_ptr(settings) == vtable_target(Settings_vtable), "unexpected vtable layout (expected class to start with a pointer to 8 bytes into the vtable)"); if (!strcmp(arg, "invert")) { void *FeatureSettings_vtable = dlsym(RTLD_DEFAULT, "_ZTV15FeatureSettings"); - NMI_ASSERT(FeatureSettings_vtable, "could not dlsym the vtable for FeatureSettings"); + NM_ASSERT(FeatureSettings_vtable, "could not dlsym the vtable for FeatureSettings"); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); bool (*FeatureSettings_invertScreen)(Settings*); reinterpret_cast(FeatureSettings_invertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings12invertScreenEv"); - NMI_ASSERT(FeatureSettings_invertScreen, "could not dlsym FeatureSettings::invertScreen"); + NM_ASSERT(FeatureSettings_invertScreen, "could not dlsym FeatureSettings::invertScreen"); bool (*FeatureSettings_setInvertScreen)(Settings*, bool); reinterpret_cast(FeatureSettings_setInvertScreen) = dlsym(RTLD_DEFAULT, "_ZN15FeatureSettings15setInvertScreenEb"); - NMI_ASSERT(FeatureSettings_setInvertScreen, "could not dlsym FeatureSettings::setInvertScreen"); + NM_ASSERT(FeatureSettings_setInvertScreen, "could not dlsym FeatureSettings::setInvertScreen"); bool v = FeatureSettings_invertScreen(settings); - NMI_LOG("invertScreen = %d", v); + NM_LOG("invertScreen = %d", v); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); FeatureSettings_setInvertScreen(settings, !v); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); - NMI_ASSERT(FeatureSettings_invertScreen(settings) == !v, "failed to set setting"); + NM_ASSERT(FeatureSettings_invertScreen(settings) == !v, "failed to set setting"); vtable_ptr(settings) = vtable_target(FeatureSettings_vtable); } else { // TODO: more settings Settings_SettingsD(settings); - NMI_RETURN_ERR("unknown setting name '%s'", arg); + NM_RETURN_ERR("unknown setting name '%s'", arg); } #undef vtable_ptr @@ -90,15 +90,15 @@ extern "C" int nmi_action_nickelsetting(const char *arg, char **err_out) { Settings_SettingsD(settings); - NMI_RETURN_OK(0); - #undef NMI_ERR_RET + NM_RETURN_OK(0); + #undef NM_ERR_RET } -extern "C" int nmi_action_nickelextras(const char *arg, char **err_out) { - #define NMI_ERR_RET 1 +extern "C" int nm_action_nickelextras(const char *arg, char **err_out) { + #define NM_ERR_RET 1 if (!strcmp(arg, "web_browser")) { - NMI_RETURN_ERR("not implemented yet"); // TODO + NM_RETURN_ERR("not implemented yet"); // TODO } const char* mimetype; @@ -108,45 +108,45 @@ extern "C" int nmi_action_nickelextras(const char *arg, char **err_out) { else if (!strcmp(arg, "solitaire")) mimetype = "application/x-games-Solitaire"; else if (!strcmp(arg, "sudoku")) mimetype = "application/x-games-Sudoku"; else if (!strcmp(arg, "word_scramble")) mimetype = "application/x-games-Boggle"; - else NMI_RETURN_ERR("unknown beta feature name or plugin mimetype '%s'", arg); + else NM_RETURN_ERR("unknown beta feature name or plugin mimetype '%s'", arg); void (*ExtrasPluginLoader_loadPlugin)(const char*); reinterpret_cast(ExtrasPluginLoader_loadPlugin) = dlsym(RTLD_DEFAULT, "_ZN18ExtrasPluginLoader10loadPluginEPKc"); - NMI_ASSERT(ExtrasPluginLoader_loadPlugin, "could not dlsym ExtrasPluginLoader::loadPlugin"); + NM_ASSERT(ExtrasPluginLoader_loadPlugin, "could not dlsym ExtrasPluginLoader::loadPlugin"); ExtrasPluginLoader_loadPlugin(mimetype); - NMI_RETURN_OK(0); - #undef NMI_ERR_RET + NM_RETURN_OK(0); + #undef NM_ERR_RET } -extern "C" int nmi_action_nickelmisc(const char *arg, char **err_out) { - #define NMI_ERR_RET 1 +extern "C" int nm_action_nickelmisc(const char *arg, char **err_out) { + #define NM_ERR_RET 1 if (!strcmp(arg, "rescan_books")) { PlugWorkflowManager *(*PlugWorkflowManager_sharedInstance)(); reinterpret_cast(PlugWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager14sharedInstanceEv"); - NMI_ASSERT(PlugWorkflowManager_sharedInstance, "could not dlsym PlugWorkflowManager::sharedInstance"); + NM_ASSERT(PlugWorkflowManager_sharedInstance, "could not dlsym PlugWorkflowManager::sharedInstance"); void (*PlugWorkflowManager_unplugged)(PlugWorkflowManager*); reinterpret_cast(PlugWorkflowManager_unplugged) = dlsym(RTLD_DEFAULT, "_ZN19PlugWorkflowManager9unpluggedEv"); - NMI_ASSERT(PlugWorkflowManager_unplugged, "could not dlsym PlugWorkflowManager::unplugged"); + NM_ASSERT(PlugWorkflowManager_unplugged, "could not dlsym PlugWorkflowManager::unplugged"); PlugWorkflowManager *wf = PlugWorkflowManager_sharedInstance(); - NMI_ASSERT(wf, "could not get shared PlugWorkflowManager pointer"); + NM_ASSERT(wf, "could not get shared PlugWorkflowManager pointer"); PlugWorkflowManager_unplugged(wf); // TODO: finish this up - NMI_RETURN_ERR("not completely implemented yet"); + NM_RETURN_ERR("not completely implemented yet"); } else if (!strcmp(arg, "force_usb_connection")) { FILE *nhs; - NMI_ASSERT((nhs = fopen("/tmp/nickel-hardware-status", "w")), "could not open nickel hardware status pipe: %s", strerror(errno)); + NM_ASSERT((nhs = fopen("/tmp/nickel-hardware-status", "w")), "could not open nickel hardware status pipe: %s", strerror(errno)); const char *msg = "usb plug add"; - NMI_ASSERT(fputs(msg, nhs) >= 0, "could not write message '%s' to pipe: %s", msg, strerror(errno)); + NM_ASSERT(fputs(msg, nhs) >= 0, "could not write message '%s' to pipe: %s", msg, strerror(errno)); fclose(nhs); } else { - NMI_RETURN_ERR("unknown action '%s'", arg); + NM_RETURN_ERR("unknown action '%s'", arg); } - NMI_RETURN_OK(0); - #undef NMI_ERR_RET + NM_RETURN_OK(0); + #undef NM_ERR_RET } diff --git a/src/action_cc.h b/src/action_cc.h index 5b34d21..10f1ec9 100644 --- a/src/action_cc.h +++ b/src/action_cc.h @@ -1,12 +1,12 @@ -#ifndef NMI_ACTION_CC_H -#define NMI_ACTION_CC_H +#ifndef NM_ACTION_CC_H +#define NM_ACTION_CC_H #ifdef __cplusplus extern "C" { #endif -int nmi_action_nickelsetting(const char *arg, char **err_out); -int nmi_action_nickelextras(const char *arg, char **err_out); -int nmi_action_nickelmisc(const char *arg, char **err_out); +int nm_action_nickelsetting(const char *arg, char **err_out); +int nm_action_nickelextras(const char *arg, char **err_out); +int nm_action_nickelmisc(const char *arg, char **err_out); #ifdef __cplusplus } diff --git a/src/config.c b/src/config.c index a1a36f3..b0fda39 100644 --- a/src/config.c +++ b/src/config.c @@ -16,20 +16,20 @@ #include "menu.h" #include "util.h" -#ifndef NMI_CONFIG_DIR -#define NMI_CONFIG_DIR "/mnt/onboard/.adds/nmi" +#ifndef NM_CONFIG_DIR +#define NM_CONFIG_DIR "/mnt/onboard/.adds/nm" #endif typedef enum { - NMI_CONFIG_TYPE_MENU_ITEM = 1, -} nmi_config_type_t; + NM_CONFIG_TYPE_MENU_ITEM = 1, +} nm_config_type_t; -struct nmi_config_t { - nmi_config_type_t type; +struct nm_config_t { + nm_config_type_t type; union { - nmi_menu_item_t *menu_item; + nm_menu_item_t *menu_item; } value; - nmi_config_t *next; + nm_config_t *next; }; // strtrim trims ASCII whitespace in-place (i.e. don't give it a string literal) @@ -43,53 +43,53 @@ static char *strtrim(char *s){ return a; } -static void nmi_config_push_menu_item(nmi_config_t **cfg, nmi_menu_item_t *it) { - nmi_config_t *tmp = calloc(1, sizeof(nmi_config_t)); - tmp->type = NMI_CONFIG_TYPE_MENU_ITEM; +static void nm_config_push_menu_item(nm_config_t **cfg, nm_menu_item_t *it) { + nm_config_t *tmp = calloc(1, sizeof(nm_config_t)); + tmp->type = NM_CONFIG_TYPE_MENU_ITEM; tmp->value.menu_item = it; tmp->next = *cfg; *cfg = tmp; } -nmi_config_t *nmi_config_parse(char **err_out) { - #define NMI_ERR_RET NULL - NMI_LOG("config: reading config dir %s", NMI_CONFIG_DIR); +nm_config_t *nm_config_parse(char **err_out) { + #define NM_ERR_RET NULL + NM_LOG("config: reading config dir %s", NM_CONFIG_DIR); // set up the linked list - nmi_config_t *cfg = NULL; + nm_config_t *cfg = NULL; // open the config dir DIR *cfgdir; - NMI_ASSERT((cfgdir = opendir(NMI_CONFIG_DIR)), "could not open config dir: %s", strerror(errno)); + NM_ASSERT((cfgdir = opendir(NM_CONFIG_DIR)), "could not open config dir: %s", strerror(errno)); // loop over the dirents of the config dir struct dirent *dirent; errno = 0; while ((dirent = readdir(cfgdir))) { char *fn; - NMI_ASSERT(asprintf(&fn, "%s/%s", NMI_CONFIG_DIR, dirent->d_name) != -1, "could not build full path for config file"); + NM_ASSERT(asprintf(&fn, "%s/%s", NM_CONFIG_DIR, dirent->d_name) != -1, "could not build full path for config file"); // skip it if it isn't a file bool reg = dirent->d_type == DT_REG; if (dirent->d_type == DT_UNKNOWN) { struct stat statbuf; - NMI_ASSERT(!stat(fn, &statbuf), "could not stat %s", fn); + NM_ASSERT(!stat(fn, &statbuf), "could not stat %s", fn); reg = S_ISREG(statbuf.st_mode); } if (!reg) { - NMI_LOG("config: skipping %s because not a regular file", fn); + NM_LOG("config: skipping %s because not a regular file", fn); continue; } // open the config file - NMI_LOG("config: reading config file %s", fn); + NM_LOG("config: reading config file %s", fn); FILE *cfgfile; - NMI_ASSERT((cfgfile = fopen(fn, "r")), "could not open file: %s", strerror(errno)); + NM_ASSERT((cfgfile = fopen(fn, "r")), "could not open file: %s", strerror(errno)); #define RETERR(fmt, ...) do { \ fclose(cfgfile); \ free(line); \ closedir(cfgdir); \ - NMI_RETURN_ERR(fmt, ##__VA_ARGS__); \ + NM_RETURN_ERR(fmt, ##__VA_ARGS__); \ } while (0) // parse each line @@ -109,13 +109,13 @@ nmi_config_t *nmi_config_parse(char **err_out) { char *c_typ = strtrim(strsep(&cur, ":")); if (!strcmp(c_typ, "menu_item")) { // type: menu_item - nmi_menu_item_t *it = calloc(1, sizeof(nmi_menu_item_t)); + nm_menu_item_t *it = calloc(1, sizeof(nm_menu_item_t)); // type: menu_item - field 2: location char *c_loc = strtrim(strsep(&cur, ":")); if (!c_loc) RETERR("file %s: line %d: field 2: expected location, got end of line", fn, line_n); - else if (!strcmp(c_loc, "main")) it->loc = NMI_MENU_LOCATION_MAIN_MENU; - else if (!strcmp(c_loc, "reader")) it->loc = NMI_MENU_LOCATION_READER_MENU; + else if (!strcmp(c_loc, "main")) it->loc = NM_MENU_LOCATION_MAIN_MENU; + else if (!strcmp(c_loc, "reader")) it->loc = NM_MENU_LOCATION_READER_MENU; else RETERR("file %s: line %d: field 2: unknown location '%s'", fn, line_n, c_loc); // type: menu_item - field 3: label @@ -126,12 +126,12 @@ nmi_config_t *nmi_config_parse(char **err_out) { // type: menu_item - field 4: action char *c_act = strtrim(strsep(&cur, ":")); if (!c_act) RETERR("file %s: line %d: field 4: expected action, got end of line", fn, line_n); - else if (!strcmp(c_act, "dbg_syslog")) it->act = nmi_action_dbgsyslog; - else if (!strcmp(c_act, "dbg_error")) it->act = nmi_action_dbgerror; - else if (!strcmp(c_act, "kfmon")) it->act = nmi_action_kfmon; - else if (!strcmp(c_act, "nickel_setting")) it->act = nmi_action_nickelsetting; - else if (!strcmp(c_act, "nickel_extras")) it->act = nmi_action_nickelextras; - else if (!strcmp(c_act, "nickel_misc")) it->act = nmi_action_nickelmisc; + else if (!strcmp(c_act, "dbg_syslog")) it->act = nm_action_dbgsyslog; + else if (!strcmp(c_act, "dbg_error")) it->act = nm_action_dbgerror; + else if (!strcmp(c_act, "kfmon")) it->act = nm_action_kfmon; + else if (!strcmp(c_act, "nickel_setting")) it->act = nm_action_nickelsetting; + else if (!strcmp(c_act, "nickel_extras")) it->act = nm_action_nickelextras; + else if (!strcmp(c_act, "nickel_misc")) it->act = nm_action_nickelmisc; else RETERR("file %s: line %d: field 4: unknown action '%s'", fn, line_n, c_act); // type: menu_item - field 5: argument @@ -139,7 +139,7 @@ nmi_config_t *nmi_config_parse(char **err_out) { if (!c_arg) RETERR("file %s: line %d: field 5: expected argument, got end of line\n", fn, line_n); else it->arg = strdup(c_arg); - nmi_config_push_menu_item(&cfg, it); + nm_config_push_menu_item(&cfg, it); } else RETERR("file %s: line %d: field 1: unknown type '%s'", fn, line_n, c_typ); } @@ -148,53 +148,53 @@ nmi_config_t *nmi_config_parse(char **err_out) { fclose(cfgfile); free(line); } - NMI_ASSERT(!errno, "could not read config dir: %s", strerror(errno)); + NM_ASSERT(!errno, "could not read config dir: %s", strerror(errno)); // close the config dir closedir(cfgdir); // add a default entry if none were found if (!cfg) { - nmi_menu_item_t *it = calloc(1, sizeof(nmi_menu_item_t)); - it->loc = NMI_MENU_LOCATION_MAIN_MENU; - it->lbl = strdup("nickel-menu-inject"); - it->arg = strdup("See KOBOeReader/.add/nmi/doc for instructions on how to customize this menu."); - it->act = nmi_action_dbgerror; - nmi_config_push_menu_item(&cfg, it); + nm_menu_item_t *it = calloc(1, sizeof(nm_menu_item_t)); + it->loc = NM_MENU_LOCATION_MAIN_MENU; + it->lbl = strdup("NickelMenu"); + it->arg = strdup("See KOBOeReader/.add/nm/doc for instructions on how to customize this menu."); + it->act = nm_action_dbgerror; + nm_config_push_menu_item(&cfg, it); } - for (nmi_config_t *cur = cfg; cur; cur = cur->next) - if (cur->type == NMI_CONFIG_TYPE_MENU_ITEM) - NMI_LOG("cfg(NMI_CONFIG_TYPE_MENU_ITEM) : %d:%s:%p:%s", cur->value.menu_item->loc, cur->value.menu_item->lbl, cur->value.menu_item->act, cur->value.menu_item->arg); + for (nm_config_t *cur = cfg; cur; cur = cur->next) + if (cur->type == NM_CONFIG_TYPE_MENU_ITEM) + NM_LOG("cfg(NM_CONFIG_TYPE_MENU_ITEM) : %d:%s:%p:%s", cur->value.menu_item->loc, cur->value.menu_item->lbl, cur->value.menu_item->act, cur->value.menu_item->arg); // return the head of the list - NMI_RETURN_OK(cfg); - #undef NMI_ERR_RET + NM_RETURN_OK(cfg); + #undef NM_ERR_RET } -nmi_menu_item_t **nmi_config_get_menu(nmi_config_t *cfg, size_t *n_out) { +nm_menu_item_t **nm_config_get_menu(nm_config_t *cfg, size_t *n_out) { *n_out = 0; - for (nmi_config_t *cur = cfg; cur; cur = cur->next) - if (cur->type == NMI_CONFIG_TYPE_MENU_ITEM) + for (nm_config_t *cur = cfg; cur; cur = cur->next) + if (cur->type == NM_CONFIG_TYPE_MENU_ITEM) (*n_out)++; - nmi_menu_item_t **it = calloc(*n_out, sizeof(nmi_menu_item_t*)); + nm_menu_item_t **it = calloc(*n_out, sizeof(nm_menu_item_t*)); if (!it) return NULL; - nmi_menu_item_t **tmp = it; - for (nmi_config_t *cur = cfg; cur; cur = cur->next) - if (cur->type == NMI_CONFIG_TYPE_MENU_ITEM) + nm_menu_item_t **tmp = it; + for (nm_config_t *cur = cfg; cur; cur = cur->next) + if (cur->type == NM_CONFIG_TYPE_MENU_ITEM) *(tmp++) = cur->value.menu_item; return it; } -void nmi_config_free(nmi_config_t *cfg) { +void nm_config_free(nm_config_t *cfg) { while (cfg) { - nmi_config_t *n = cfg->next; + nm_config_t *n = cfg->next; - if (cfg->type == NMI_CONFIG_TYPE_MENU_ITEM) { + if (cfg->type == NM_CONFIG_TYPE_MENU_ITEM) { free(cfg->value.menu_item->lbl); free(cfg->value.menu_item->arg); free(cfg->value.menu_item); diff --git a/src/config.h b/src/config.h index 822efc1..f9a6474 100644 --- a/src/config.h +++ b/src/config.h @@ -1,5 +1,5 @@ -#ifndef NMI_CONFIG_H -#define NMI_CONFIG_H +#ifndef NM_CONFIG_H +#define NM_CONFIG_H #ifdef __cplusplus extern "C" { #endif @@ -7,20 +7,20 @@ extern "C" { #include #include "menu.h" -typedef struct nmi_config_t nmi_config_t; +typedef struct nm_config_t nm_config_t; -// nmi_config_parse parses the configuration files in /mnt/onboard/.adds/nmi. +// nm_config_parse parses the configuration files in /mnt/onboard/.adds/nm. // An error is returned if there are syntax errors, file access errors, or // invalid action names for menu_item. -nmi_config_t *nmi_config_parse(char **err_out); +nm_config_t *nm_config_parse(char **err_out); -// nmi_config_get_menu gets a malloc'd array of pointers to the menu items -// defined in the config. These pointers will be valid until nmi_config_free is +// nm_config_get_menu gets a malloc'd array of pointers to the menu items +// defined in the config. These pointers will be valid until nm_config_free is // called. -nmi_menu_item_t **nmi_config_get_menu(nmi_config_t *cfg, size_t *n_out); +nm_menu_item_t **nm_config_get_menu(nm_config_t *cfg, size_t *n_out); -// nmi_config_free frees all allocated memory. -void nmi_config_free(nmi_config_t *cfg); +// nm_config_free frees all allocated memory. +void nm_config_free(nm_config_t *cfg); #ifdef __cplusplus } diff --git a/src/dlhook.c b/src/dlhook.c index 5a6c84b..1b5e7ab 100644 --- a/src/dlhook.c +++ b/src/dlhook.c @@ -28,15 +28,15 @@ // prevent GCC from giving us warnings everywhere about the format specifiers for the ELF typedefs #pragma GCC diagnostic ignored "-Wformat" -void *nmi_dlhook(void *handle, const char *symname, void *target, char **err_out) { - #define NMI_ERR_RET NULL +void *nm_dlhook(void *handle, const char *symname, void *target, char **err_out) { + #define NM_ERR_RET NULL - NMI_ASSERT(handle && symname && target, "BUG: required arguments are null"); + NM_ASSERT(handle && symname && target, "BUG: required arguments are null"); // the link_map conveniently gives use the base address without /proc/maps, and it gives us a pointer to dyn struct link_map *lm; - NMI_ASSERT(!dlinfo(handle, RTLD_DI_LINKMAP, &lm), "could not get link_map for lib"); - NMI_LOG("lib %s is mapped at %lx", lm->l_name, lm->l_addr); + NM_ASSERT(!dlinfo(handle, RTLD_DI_LINKMAP, &lm), "could not get link_map for lib"); + NM_LOG("lib %s is mapped at %lx", lm->l_name, lm->l_addr); // stuff extracted from DT_DYNAMIC struct { @@ -64,10 +64,10 @@ void *nmi_dlhook(void *handle, const char *symname, void *target, char **err_out case DT_STRTAB: dyn.str = (const char*)(lm->l_ld[i].d_un.d_val); break; // .dynstr - offset } } - NMI_LOG("DT_DYNAMIC: plt_is_rela=%d plt=%p plt_sz=%lu plt_ent_sz=%lu sym=%p str=%p", dyn.plt_is_rela, (void*)(dyn.plt)._, dyn.plt_sz, dyn.plt_ent_sz, dyn.sym, dyn.str); - NMI_ASSERT(dyn.plt_ent_sz, "plt_ent_sz is zero"); - NMI_ASSERT(dyn.plt_sz%dyn.plt_ent_sz == 0, ".rel.plt length is not a multiple of plt_ent_sz"); - NMI_ASSERT((dyn.plt_is_rela ? sizeof(*dyn.plt.rela) : sizeof(*dyn.plt.rel)) == dyn.plt_ent_sz, "size mismatch (%lu != %lu)", dyn.plt_is_rela ? sizeof(*dyn.plt.rela) : sizeof(*dyn.plt.rel), dyn.plt_ent_sz); + NM_LOG("DT_DYNAMIC: plt_is_rela=%d plt=%p plt_sz=%lu plt_ent_sz=%lu sym=%p str=%p", dyn.plt_is_rela, (void*)(dyn.plt)._, dyn.plt_sz, dyn.plt_ent_sz, dyn.sym, dyn.str); + NM_ASSERT(dyn.plt_ent_sz, "plt_ent_sz is zero"); + NM_ASSERT(dyn.plt_sz%dyn.plt_ent_sz == 0, ".rel.plt length is not a multiple of plt_ent_sz"); + NM_ASSERT((dyn.plt_is_rela ? sizeof(*dyn.plt.rela) : sizeof(*dyn.plt.rel)) == dyn.plt_ent_sz, "size mismatch (%lu != %lu)", dyn.plt_is_rela ? sizeof(*dyn.plt.rela) : sizeof(*dyn.plt.rel), dyn.plt_ent_sz); // parse the dynamic symbol table, resolve symbols to relocations, then GOT entries for (size_t i = 0; i < dyn.plt_sz/dyn.plt_ent_sz; i++) { @@ -75,7 +75,7 @@ void *nmi_dlhook(void *handle, const char *symname, void *target, char **err_out ElfW(Rel) *rel = dyn.plt_is_rela ? (ElfW(Rel)*)(&dyn.plt.rela[i]) : &dyn.plt.rel[i]; - NMI_ASSERT(ELFW(R_TYPE)(rel->r_info) == R_JUMP_SLOT, "not a jump slot relocation (R_TYPE=%lu)", ELFW(R_TYPE)(rel->r_info)); + NM_ASSERT(ELFW(R_TYPE)(rel->r_info) == R_JUMP_SLOT, "not a jump slot relocation (R_TYPE=%lu)", ELFW(R_TYPE)(rel->r_info)); ElfW(Sym) *sym = &dyn.sym[ELFW(R_SYM)(rel->r_info)]; const char *str = &dyn.str[sym->st_name]; @@ -83,35 +83,35 @@ void *nmi_dlhook(void *handle, const char *symname, void *target, char **err_out continue; void **gotoff = (void**)(lm->l_addr + rel->r_offset); - NMI_LOG("found symbol %s (gotoff=%p [mapped=%p])", str, (void*)(rel->r_offset), gotoff); + NM_LOG("found symbol %s (gotoff=%p [mapped=%p])", str, (void*)(rel->r_offset), gotoff); - NMI_ASSERT(ELFW(ST_TYPE)(sym->st_info) != STT_GNU_IFUNC, "STT_GNU_IFUNC not implemented (gotoff=%p)", (void*)(rel->r_offset)); - NMI_ASSERT(ELFW(ST_TYPE)(sym->st_info) == STT_FUNC, "not a function symbol (ST_TYPE=%d) (gotoff=%p)", ELFW(ST_TYPE)(sym->st_info), (void*)(rel->r_offset)); - NMI_ASSERT(ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL, "not a globally bound symbol (ST_BIND=%d) (gotoff=%p)", ELFW(ST_BIND)(sym->st_info), (void*)(rel->r_offset)); + NM_ASSERT(ELFW(ST_TYPE)(sym->st_info) != STT_GNU_IFUNC, "STT_GNU_IFUNC not implemented (gotoff=%p)", (void*)(rel->r_offset)); + NM_ASSERT(ELFW(ST_TYPE)(sym->st_info) == STT_FUNC, "not a function symbol (ST_TYPE=%d) (gotoff=%p)", ELFW(ST_TYPE)(sym->st_info), (void*)(rel->r_offset)); + NM_ASSERT(ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL, "not a globally bound symbol (ST_BIND=%d) (gotoff=%p)", ELFW(ST_BIND)(sym->st_info), (void*)(rel->r_offset)); // TODO: figure out why directly getting the offset from the GOT was broken on ARM, but not x86 - NMI_LOG("ensuring the symbol is loaded"); + NM_LOG("ensuring the symbol is loaded"); void *orig = dlsym(handle, symname); - NMI_ASSERT(orig, "could not dlsym symbol"); + NM_ASSERT(orig, "could not dlsym symbol"); // remove memory protection (to bypass RELRO if it is enabled) // note: this doesn't seem to be used on the Kobo, but we might as well stay on the safe side (plus, I test this on my local machine too) // note: the only way to read the current memory protection is to parse /proc/maps, but there's no harm in unprotecting it again if it's not protected // note: we won't put it back afterwards, as if full RELRO (i.e. RTLD_NOW) wasn't enabled, it would cause segfaults when resolving symbols later on - NMI_LOG("removing memory protection"); + NM_LOG("removing memory protection"); long pagesize = sysconf(_SC_PAGESIZE); - NMI_ASSERT(pagesize != -1, "could not get memory page size"); + NM_ASSERT(pagesize != -1, "could not get memory page size"); void *gotpage = (void*)((size_t)(gotoff) & ~(pagesize-1)); - NMI_ASSERT(!mprotect(gotpage, pagesize, PROT_READ|PROT_WRITE), "could not set memory protection of page %p containing %p to PROT_READ|PROT_WRITE", gotpage, gotoff); + NM_ASSERT(!mprotect(gotpage, pagesize, PROT_READ|PROT_WRITE), "could not set memory protection of page %p containing %p to PROT_READ|PROT_WRITE", gotpage, gotoff); // replace the target offset - NMI_LOG("patching symbol"); + NM_LOG("patching symbol"); //void *orig = *gotoff; *gotoff = target; - NMI_LOG("successfully patched symbol %s (orig=%p, new=%p)", str, orig, target); - NMI_RETURN_OK(orig); + NM_LOG("successfully patched symbol %s (orig=%p, new=%p)", str, orig, target); + NM_RETURN_OK(orig); } - NMI_RETURN_ERR("could not find symbol"); - #undef NMI_err_ret + NM_RETURN_ERR("could not find symbol"); + #undef NM_err_ret } diff --git a/src/dlhook.h b/src/dlhook.h index 238057d..ba52f75 100644 --- a/src/dlhook.h +++ b/src/dlhook.h @@ -1,16 +1,16 @@ -#ifndef NMI_DLHOOK_H -#define NMI_DLHOOK_H +#ifndef NM_DLHOOK_H +#define NM_DLHOOK_H #ifdef __cplusplus extern "C" { #endif -// nmi_dlhook takes a lib handle from dlopen and redirects the specified symbol +// nm_dlhook takes a lib handle from dlopen and redirects the specified symbol // to another, returning a pointer to the original one. Only calls from within // that library itself are affected (because it replaces that library's GOT). If // an error occurs, NULL is returned and if err is a valid pointer, it is set to // a malloc'd string describing it. This function requires glibc and Linux. It // should work on any architecture, and it should be resilient to most errors. -void *nmi_dlhook(void *handle, const char *symname, void *target, char **err_out); +void *nm_dlhook(void *handle, const char *symname, void *target, char **err_out); #ifdef __cplusplus } diff --git a/src/failsafe.c b/src/failsafe.c index 1f8a481..0f320c7 100644 --- a/src/failsafe.c +++ b/src/failsafe.c @@ -10,49 +10,49 @@ #include "failsafe.h" #include "util.h" -struct nmi_failsafe_t { +struct nm_failsafe_t { char *orig; char *tmp; int delay; }; -nmi_failsafe_t *nmi_failsafe_create(char **err_out) { - #define NMI_ERR_RET NULL +nm_failsafe_t *nm_failsafe_create(char **err_out) { + #define NM_ERR_RET NULL - NMI_LOG("failsafe: allocating memory"); - nmi_failsafe_t *fs; - NMI_ASSERT((fs = calloc(1, sizeof(nmi_failsafe_t))), "could not allocate memory"); + NM_LOG("failsafe: allocating memory"); + nm_failsafe_t *fs; + NM_ASSERT((fs = calloc(1, sizeof(nm_failsafe_t))), "could not allocate memory"); - NMI_LOG("failsafe: finding filenames"); + NM_LOG("failsafe: finding filenames"); Dl_info info; - NMI_ASSERT(dladdr(nmi_failsafe_create, &info), "could not find own path"); - NMI_ASSERT(info.dli_fname, "dladdr did not return a filename"); + NM_ASSERT(dladdr(nm_failsafe_create, &info), "could not find own path"); + NM_ASSERT(info.dli_fname, "dladdr did not return a filename"); char *d = strrchr(info.dli_fname, '.'); - NMI_ASSERT(!(d && !strcmp(d, ".failsafe")), "lib was loaded from the failsafe for some reason"); - NMI_ASSERT((fs->orig = realpath(info.dli_fname, NULL)), "could not resolve %s", info.dli_fname); - NMI_ASSERT(asprintf(&fs->tmp, "%s.failsafe", fs->orig) != -1, "could not generate temp filename"); + NM_ASSERT(!(d && !strcmp(d, ".failsafe")), "lib was loaded from the failsafe for some reason"); + NM_ASSERT((fs->orig = realpath(info.dli_fname, NULL)), "could not resolve %s", info.dli_fname); + NM_ASSERT(asprintf(&fs->tmp, "%s.failsafe", fs->orig) != -1, "could not generate temp filename"); - NMI_LOG("failsafe: ensuring own lib remains in memory even if it is dlclosed after being loaded with a dlopen"); - NMI_ASSERT(dlopen(fs->orig, RTLD_LAZY|RTLD_NODELETE), "could not dlopen self"); + NM_LOG("failsafe: ensuring own lib remains in memory even if it is dlclosed after being loaded with a dlopen"); + NM_ASSERT(dlopen(fs->orig, RTLD_LAZY|RTLD_NODELETE), "could not dlopen self"); - NMI_LOG("failsafe: renaming %s to %s", fs->orig, fs->tmp); - NMI_ASSERT(!rename(fs->orig, fs->tmp), "could not rename lib"); + NM_LOG("failsafe: renaming %s to %s", fs->orig, fs->tmp); + NM_ASSERT(!rename(fs->orig, fs->tmp), "could not rename lib"); - NMI_RETURN_OK(fs); - #undef NMI_ERR_RET + NM_RETURN_OK(fs); + #undef NM_ERR_RET } -static void *_nmi_failsafe_destroy(void* _fs) { - nmi_failsafe_t *fs = (nmi_failsafe_t*)(_fs); +static void *_nm_failsafe_destroy(void* _fs) { + nm_failsafe_t *fs = (nm_failsafe_t*)(_fs); - NMI_LOG("failsafe: restoring after %d seconds", fs->delay); + NM_LOG("failsafe: restoring after %d seconds", fs->delay); sleep(fs->delay); - NMI_LOG("failsafe: renaming %s to %s", fs->tmp, fs->orig); + NM_LOG("failsafe: renaming %s to %s", fs->tmp, fs->orig); if (rename(fs->tmp, fs->orig)) - NMI_LOG("error: could not rename lib"); + NM_LOG("error: could not rename lib"); - NMI_LOG("failsafe: freeing memory"); + NM_LOG("failsafe: freeing memory"); free(fs->orig); free(fs->tmp); free(fs); @@ -60,15 +60,15 @@ static void *_nmi_failsafe_destroy(void* _fs) { return NULL; } -void nmi_failsafe_destroy(nmi_failsafe_t *fs, int delay) { +void nm_failsafe_destroy(nm_failsafe_t *fs, int delay) { fs->delay = delay; - NMI_LOG("failsafe: scheduling restore"); + NM_LOG("failsafe: scheduling restore"); pthread_t t; - pthread_create(&t, NULL, _nmi_failsafe_destroy, fs); + pthread_create(&t, NULL, _nm_failsafe_destroy, fs); } -void nmi_failsafe_uninstall(nmi_failsafe_t *fs) { - NMI_LOG("failsafe: deleting %s", fs->tmp); +void nm_failsafe_uninstall(nm_failsafe_t *fs) { + NM_LOG("failsafe: deleting %s", fs->tmp); unlink(fs->tmp); } diff --git a/src/failsafe.h b/src/failsafe.h index bdcea17..1285a9d 100644 --- a/src/failsafe.h +++ b/src/failsafe.h @@ -1,27 +1,27 @@ -#ifndef NMI_FAILSAFE_H -#define NMI_FAILSAFE_H +#ifndef NM_FAILSAFE_H +#define NM_FAILSAFE_H #ifdef __cplusplus extern "C" { #endif -// nmi_failsafe_t is a failsafe mechanism for injected shared libraries. It +// nm_failsafe_t is a failsafe mechanism for injected shared libraries. It // works by moving it to a temporary file (so it won't get loaded the next time) // and dlopening itself (to prevent it from being unloaded if it is dlclose'd by // whatever dlopen'd it). When it is disarmed, the library is moved back to its // original location. -typedef struct nmi_failsafe_t nmi_failsafe_t; +typedef struct nm_failsafe_t nm_failsafe_t; -// nmi_failsafe_create allocates and arms a failsafe mechanism for the currently +// nm_failsafe_create allocates and arms a failsafe mechanism for the currently // dlopen'd or LD_PRELOAD'd library. -nmi_failsafe_t *nmi_failsafe_create(char **err_out); +nm_failsafe_t *nm_failsafe_create(char **err_out); -// nmi_failsafe_destroy starts a pthread which disarms and frees the failsafe -// after a delay. The nmi_failsafe_t must not be used afterwards. -void nmi_failsafe_destroy(nmi_failsafe_t *fs, int delay); +// nm_failsafe_destroy starts a pthread which disarms and frees the failsafe +// after a delay. The nm_failsafe_t must not be used afterwards. +void nm_failsafe_destroy(nm_failsafe_t *fs, int delay); -// nmi_failsafe_uninstall uninstalls the lib. The nmi_failsafe_t must not be +// nm_failsafe_uninstall uninstalls the lib. The nm_failsafe_t must not be // used afterwards. -void nmi_failsafe_uninstall(nmi_failsafe_t *fs); +void nm_failsafe_uninstall(nm_failsafe_t *fs); #ifdef __cplusplus } diff --git a/src/init.c b/src/init.c index 080e521..13fee32 100644 --- a/src/init.c +++ b/src/init.c @@ -14,71 +14,71 @@ #include "menu.h" #include "util.h" -__attribute__((constructor)) void nmi_init() { +__attribute__((constructor)) void nm_init() { // for if it's been loaded with LD_PRELOAD rather than as a Qt plugin if (strcmp(program_invocation_short_name, "nickel")) - if (!(getenv("LIBNMI_FORCE") && !strcmp(getenv("LIBNMI_FORCE"), "true"))) + if (!(getenv("LIBNM_FORCE") && !strcmp(getenv("LIBNM_FORCE"), "true"))) return; char *err; - NMI_LOG("init: creating failsafe"); - nmi_failsafe_t *fs; - if (!(fs = nmi_failsafe_create(&err)) && err) { - NMI_LOG("error: could not create failsafe: %s, stopping", err); + NM_LOG("init: creating failsafe"); + nm_failsafe_t *fs; + if (!(fs = nm_failsafe_create(&err)) && err) { + NM_LOG("error: could not create failsafe: %s, stopping", err); free(err); goto stop; } - NMI_LOG("init: checking for uninstall flag"); - if (!access("/mnt/onboard/.adds/nmi/uninstall", F_OK)) { - NMI_LOG("init: flag found, uninstalling"); - nmi_failsafe_uninstall(fs); - unlink("/mnt/onboard/.adds/nmi/uninstall"); + NM_LOG("init: checking for uninstall flag"); + if (!access("/mnt/onboard/.adds/nm/uninstall", F_OK)) { + NM_LOG("init: flag found, uninstalling"); + nm_failsafe_uninstall(fs); + unlink("/mnt/onboard/.adds/nm/uninstall"); goto stop; } - NMI_LOG("init: parsing config"); + NM_LOG("init: parsing config"); size_t items_n; - nmi_menu_item_t **items; - nmi_config_t *cfg; - if (!(cfg = nmi_config_parse(&err)) && err) { - NMI_LOG("error: could not parse config: %s, creating error item in main menu instead", err); + nm_menu_item_t **items; + nm_config_t *cfg; + if (!(cfg = nm_config_parse(&err)) && err) { + NM_LOG("error: could not parse config: %s, creating error item in main menu instead", err); items_n = 1; - items = calloc(items_n, sizeof(nmi_menu_item_t*)); - items[0] = calloc(1, sizeof(nmi_menu_item_t)); + items = calloc(items_n, sizeof(nm_menu_item_t*)); + items[0] = calloc(1, sizeof(nm_menu_item_t)); - items[0]->loc = NMI_MENU_LOCATION_MAIN_MENU; + items[0]->loc = NM_MENU_LOCATION_MAIN_MENU; items[0]->lbl = strdup("Config Error"); items[0]->arg = strdup(err); - items[0]->act = nmi_action_dbgerror; + items[0]->act = nm_action_dbgerror; free(err); - } else if (!(items = nmi_config_get_menu(cfg, &items_n))) { - NMI_LOG("error: could not allocate memory, stopping"); + } else if (!(items = nm_config_get_menu(cfg, &items_n))) { + NM_LOG("error: could not allocate memory, stopping"); goto stop_fs; } - NMI_LOG("init: opening libnickel"); + NM_LOG("init: opening libnickel"); void *libnickel = dlopen("libnickel.so.1.0.0", RTLD_LAZY|RTLD_NODELETE); if (!libnickel) { - NMI_LOG("error: could not dlopen libnickel, stopping"); + NM_LOG("error: could not dlopen libnickel, stopping"); goto stop_fs; } - NMI_LOG("init: hooking libnickel"); - if (nmi_menu_hook(libnickel, items, items_n, &err) && err) { - NMI_LOG("error: could not hook libnickel: %s, stopping", err); + NM_LOG("init: hooking libnickel"); + if (nm_menu_hook(libnickel, items, items_n, &err) && err) { + NM_LOG("error: could not hook libnickel: %s, stopping", err); free(err); goto stop_fs; } stop_fs: - NMI_LOG("init: destroying failsafe"); - nmi_failsafe_destroy(fs, 20); + NM_LOG("init: destroying failsafe"); + nm_failsafe_destroy(fs, 20); stop: - NMI_LOG("init: done"); + NM_LOG("init: done"); return; } diff --git a/src/menu.cc b/src/menu.cc index 9e41faf..1eb00f6 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -33,69 +33,69 @@ static QAction* (*AbstractNickelMenuController_createAction)(void*, QMenu*, QWid // a signal handler). static void (*ConfirmationDialogFactory_showOKDialog)(QString const&, QString const&); -static nmi_menu_item_t **_items; +static nm_menu_item_t **_items; static size_t _items_n; -extern "C" int nmi_menu_hook(void *libnickel, nmi_menu_item_t **items, size_t items_n, char **err_out) { - #define NMI_ERR_RET 1 +extern "C" int nm_menu_hook(void *libnickel, nm_menu_item_t **items, size_t items_n, char **err_out) { + #define NM_ERR_RET 1 reinterpret_cast(AbstractNickelMenuController_createMenuTextItem) = dlsym(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_"); reinterpret_cast(AbstractNickelMenuController_createAction) = dlsym(libnickel, "_ZN22AbstractMenuController12createActionEP5QMenuP7QWidgetbbb"); reinterpret_cast(ConfirmationDialogFactory_showOKDialog) = dlsym(libnickel, "_ZN25ConfirmationDialogFactory12showOKDialogERK7QStringS2_"); - NMI_ASSERT(AbstractNickelMenuController_createMenuTextItem, "unsupported firmware: could not find AbstractNickelMenuController::createMenuTextItem(void* _this, QMenu*, QString, bool, bool, QString const&)"); - NMI_ASSERT(AbstractNickelMenuController_createAction, "unsupported firmware: could not find AbstractNickelMenuController::createAction(void* _this, QMenu*, QWidget*, bool, bool, bool)"); - NMI_ASSERT(AbstractNickelMenuController_createAction, "unsupported firmware: could not find ConfirmationDialogFactory::showOKDialog(QString const&, QString const&)"); + NM_ASSERT(AbstractNickelMenuController_createMenuTextItem, "unsupported firmware: could not find AbstractNickelMenuController::createMenuTextItem(void* _this, QMenu*, QString, bool, bool, QString const&)"); + NM_ASSERT(AbstractNickelMenuController_createAction, "unsupported firmware: could not find AbstractNickelMenuController::createAction(void* _this, QMenu*, QWidget*, bool, bool, bool)"); + NM_ASSERT(AbstractNickelMenuController_createAction, "unsupported firmware: could not find ConfirmationDialogFactory::showOKDialog(QString const&, QString const&)"); - void* nmh = dlsym(RTLD_DEFAULT, "_nmi_menu_hook"); - NMI_ASSERT(nmh, "internal error: could not dlsym _nmi_menu_hook"); + void* nmh = dlsym(RTLD_DEFAULT, "_nm_menu_hook"); + NM_ASSERT(nmh, "internal error: could not dlsym _nm_menu_hook"); char *err; - reinterpret_cast(AbstractNickelMenuController_createMenuTextItem_orig) = nmi_dlhook(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_", nmh, &err); - NMI_ASSERT(AbstractNickelMenuController_createMenuTextItem_orig, "failed to hook _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_: %s", err); + reinterpret_cast(AbstractNickelMenuController_createMenuTextItem_orig) = nm_dlhook(libnickel, "_ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_", nmh, &err); + NM_ASSERT(AbstractNickelMenuController_createMenuTextItem_orig, "failed to hook _ZN28AbstractNickelMenuController18createMenuTextItemEP5QMenuRK7QStringbbS4_: %s", err); _items = items; _items_n = items_n; - NMI_RETURN_OK(0); - #undef NMI_ERR_RET + NM_RETURN_OK(0); + #undef NM_ERR_RET } -extern "C" MenuTextItem* _nmi_menu_hook(void* _this, QMenu* menu, QString const& label, bool checkable, bool checked, QString const& thingy) { - NMI_LOG("AbstractNickelMenuController::createMenuTextItem(%p, `%s`, %d, %d, `%s`)", menu, qPrintable(label), checkable, checked, qPrintable(thingy)); +extern "C" MenuTextItem* _nm_menu_hook(void* _this, QMenu* menu, QString const& label, bool checkable, bool checked, QString const& thingy) { + NM_LOG("AbstractNickelMenuController::createMenuTextItem(%p, `%s`, %d, %d, `%s`)", menu, qPrintable(label), checkable, checked, qPrintable(thingy)); QString trmm = QCoreApplication::translate("StatusBarMenuController", "Help"); QString trrm = QCoreApplication::translate("DictionaryActionProxy", "Dictionary"); - NMI_LOG("Comparing against '%s', '%s'", qPrintable(trmm), qPrintable(trrm)); + NM_LOG("Comparing against '%s', '%s'", qPrintable(trmm), qPrintable(trrm)); bool ismm, isrm; if ((ismm = (label == trmm) && !checkable)) - NMI_LOG("Intercepting main menu (label=Help, checkable=false)..."); + NM_LOG("Intercepting main menu (label=Help, checkable=false)..."); if ((isrm = (label == trrm) && !checkable)) - NMI_LOG("Intercepting reader menu (label=Dictionary, checkable=false)..."); + NM_LOG("Intercepting reader menu (label=Dictionary, checkable=false)..."); for (size_t i = 0; i < _items_n; i++) { - nmi_menu_item_t *it = _items[i]; - if (it->loc == NMI_MENU_LOCATION_MAIN_MENU && !ismm) + nm_menu_item_t *it = _items[i]; + if (it->loc == NM_MENU_LOCATION_MAIN_MENU && !ismm) continue; - if (it->loc == NMI_MENU_LOCATION_READER_MENU && !isrm) + if (it->loc == NM_MENU_LOCATION_READER_MENU && !isrm) continue; - NMI_LOG("Adding item '%s'...", it->lbl); + NM_LOG("Adding item '%s'...", it->lbl); MenuTextItem* item = AbstractNickelMenuController_createMenuTextItem_orig(_this, menu, QString::fromUtf8(it->lbl), false, false, ""); QAction* action = AbstractNickelMenuController_createAction(_this, menu, item, true, true, true); // note: we're capturing by value, i.e. the pointer to the global variable, rather then the stack variable, so this is safe QObject::connect(action, &QAction::triggered, std::function([it](bool){ - NMI_LOG("Item '%s' pressed...", it->lbl); + NM_LOG("Item '%s' pressed...", it->lbl); char *err; if (it->act(it->arg, &err) && err) { - NMI_LOG("Got error: '%s', displaying...", err); + NM_LOG("Got error: '%s', displaying...", err); ConfirmationDialogFactory_showOKDialog(QString::fromUtf8(it->lbl), QString::fromUtf8(err)); free(err); return; } - NMI_LOG("Success!"); + NM_LOG("Success!"); })); } diff --git a/src/menu.h b/src/menu.h index 77af1d2..61c0569 100644 --- a/src/menu.h +++ b/src/menu.h @@ -1,5 +1,5 @@ -#ifndef NMI_MENU_H -#define NMI_MENU_H +#ifndef NM_MENU_H +#define NM_MENU_H #ifdef __cplusplus extern "C" { #endif @@ -7,23 +7,23 @@ extern "C" { #include typedef enum { - NMI_MENU_LOCATION_MAIN_MENU = 1, - NMI_MENU_LOCATION_READER_MENU = 2, -} nmi_menu_location_t; + NM_MENU_LOCATION_MAIN_MENU = 1, + NM_MENU_LOCATION_READER_MENU = 2, +} nm_menu_location_t; typedef struct { - nmi_menu_location_t loc; + nm_menu_location_t loc; char *lbl; char *arg; int (*act)(const char *arg, char **out_err); // can block, must return 0 on success, nonzero with out_err set to the malloc'd error message on error -} nmi_menu_item_t; +} nm_menu_item_t; -// nmi_menu_hook hooks a dlopen'd libnickel handle to add the specified menus, +// nm_menu_hook hooks a dlopen'd libnickel handle to add the specified menus, // and returns 0 on success, or 1 with err_out (if provided) set to the malloc'd // error message on error. The provided configuration and all pointers it // references must remain valid for the lifetime of the program (i.e. not stack // allocated). It MUST NOT be called more than once. -int nmi_menu_hook(void *libnickel, nmi_menu_item_t **items, size_t items_n, char **err_out); +int nm_menu_hook(void *libnickel, nm_menu_item_t **items, size_t items_n, char **err_out); #ifdef __cplusplus } diff --git a/src/qtplugin.h b/src/qtplugin.h index b5e8f48..113a7aa 100644 --- a/src/qtplugin.h +++ b/src/qtplugin.h @@ -6,7 +6,7 @@ // we make it a fake image plugin so we can have Qt automatically load it // without needing extra configuration (e.g. LD_PRELOAD, -plugin arg, etc). -class NMIPlugin : public QImageIOPlugin { +class NMPlugin : public QImageIOPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface") public: diff --git a/src/util.h b/src/util.h index c15d18e..0971795 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,5 @@ -#ifndef NMI_UTIL_H -#define NMI_UTIL_H +#ifndef NM_UTIL_H +#define NM_UTIL_H #ifdef __cplusplus extern "C" { #endif @@ -13,34 +13,34 @@ extern "C" { // A bunch of useful macros to simplify error handling and logging. -// NMI_LOG writes a log message. -#define NMI_LOG(fmt, ...) syslog(LOG_DEBUG, "(nickel-menu-inject) " fmt " (%s:%d)", ##__VA_ARGS__, __FILE__, __LINE__) +// NM_LOG writes a log message. +#define NM_LOG(fmt, ...) syslog(LOG_DEBUG, "(NickelMenu) " fmt " (%s:%d)", ##__VA_ARGS__, __FILE__, __LINE__) -// NMI_RETURN returns ret, and if ret is NMI_ERR_RET and err_out is not NULL, it +// NM_RETURN returns ret, and if ret is NM_ERR_RET and err_out is not NULL, it // writes the formatted error message to *err_out as a malloc'd string. The // arguments may or may not be evaluated more than once. -#define NMI_RETURN(ret, fmt, ...) do { \ +#define NM_RETURN(ret, fmt, ...) do { \ typeof(ret) _ret = (ret); \ if (err_out) { \ - if (_ret == NMI_ERR_RET) asprintf(err_out, fmt " (%s:%d)", ##__VA_ARGS__, __FILE__, __LINE__); \ + if (_ret == NM_ERR_RET) asprintf(err_out, fmt " (%s:%d)", ##__VA_ARGS__, __FILE__, __LINE__); \ else *err_out = NULL; \ } \ return _ret; \ } while (0) -// NMI_ASSERT is like assert, but it writes the formatted error message to -// err_out as a malloc'd string, and returns NMI_ERR_RET. Cond will always be +// NM_ASSERT is like assert, but it writes the formatted error message to +// err_out as a malloc'd string, and returns NM_ERR_RET. Cond will always be // evaluated exactly once. The other arguments may or may not be evaluated one // or more times. -#define NMI_ASSERT(cond, fmt, ...) do { \ - if (!(cond)) NMI_RETURN(NMI_ERR_RET, fmt " (assertion failed: %s)", ##__VA_ARGS__, #cond); \ +#define NM_ASSERT(cond, fmt, ...) do { \ + if (!(cond)) NM_RETURN(NM_ERR_RET, fmt " (assertion failed: %s)", ##__VA_ARGS__, #cond); \ } while (0) -// NMI_RETURN_ERR is the same as NMI_RETURN(NMI_ERR_RET, fmt, ...). -#define NMI_RETURN_ERR(fmt, ...) NMI_RETURN(NMI_ERR_RET, fmt, ##__VA_ARGS__) +// NM_RETURN_ERR is the same as NM_RETURN(NM_ERR_RET, fmt, ...). +#define NM_RETURN_ERR(fmt, ...) NM_RETURN(NM_ERR_RET, fmt, ##__VA_ARGS__) -// NMI_RETURN_OK is the same as NMI_RETURN(ret, ""). -#define NMI_RETURN_OK(ret) NMI_RETURN(ret, "") +// NM_RETURN_OK is the same as NM_RETURN(ret, ""). +#define NM_RETURN_OK(ret) NM_RETURN(ret, "") #ifdef __cplusplus }