Allow failure when finding functions that are new to the API

This allows a game using a newer client header than the installed gamemode to still function
This commit is contained in:
Marc Di Luzio 2018-04-25 15:24:07 +01:00
parent 4f3bc2c9a2
commit eac854b753

View File

@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
* returns a string describing any of the above errors * returns a string describing any of the above errors
*/ */
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -128,19 +129,24 @@ __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
const char *name; const char *name;
void **functor; void **functor;
size_t func_size; size_t func_size;
bool required;
} bindings[] = { } bindings[] = {
{ "real_gamemode_request_start", { "real_gamemode_request_start",
(void **)&REAL_internal_gamemode_request_start, (void **)&REAL_internal_gamemode_request_start,
sizeof(REAL_internal_gamemode_request_start) }, sizeof(REAL_internal_gamemode_request_start),
true },
{ "real_gamemode_request_end", { "real_gamemode_request_end",
(void **)&REAL_internal_gamemode_request_end, (void **)&REAL_internal_gamemode_request_end,
sizeof(REAL_internal_gamemode_request_end) }, sizeof(REAL_internal_gamemode_request_end),
true },
{ "real_gamemode_query_status", { "real_gamemode_query_status",
(void **)&REAL_internal_gamemode_query_status, (void **)&REAL_internal_gamemode_query_status,
sizeof(REAL_internal_gamemode_query_status) }, sizeof(REAL_internal_gamemode_query_status),
false },
{ "real_gamemode_error_string", { "real_gamemode_error_string",
(void **)&REAL_internal_gamemode_error_string, (void **)&REAL_internal_gamemode_error_string,
sizeof(REAL_internal_gamemode_error_string) }, sizeof(REAL_internal_gamemode_error_string),
true },
}; };
void *libgamemode = NULL; void *libgamemode = NULL;
@ -163,7 +169,8 @@ __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
if (internal_bind_libgamemode_symbol(libgamemode, if (internal_bind_libgamemode_symbol(libgamemode,
binder->name, binder->name,
binder->functor, binder->functor,
binder->func_size) != 0) { binder->func_size) != 0 &&
binder->required) {
internal_libgamemode_loaded = -1; internal_libgamemode_loaded = -1;
return -1; return -1;
}; };
@ -179,8 +186,9 @@ __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
*/ */
__attribute__((always_inline)) static inline const char *gamemode_error_string(void) __attribute__((always_inline)) static inline const char *gamemode_error_string(void)
{ {
/* If we fail to load the system gamemode, return our error string */ /* If we fail to load the system gamemode, or we have an error string already, return our error
if (internal_load_libgamemode() < 0) { * string instead of diverting to the system version */
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
return internal_gamemode_client_error_string; return internal_gamemode_client_error_string;
} }
@ -251,6 +259,13 @@ __attribute__((always_inline)) static inline int gamemode_query_status(void)
return -1; return -1;
} }
if (REAL_internal_gamemode_query_status == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_query_status missing (older host?)");
return -1;
}
return REAL_internal_gamemode_query_status(); return REAL_internal_gamemode_query_status();
} }