|
@@ -48,6 +48,20 @@ POSSIBILITY OF SUCH DAMAGE.
|
|
|
* 2 if gamemode is active and this client is registered
|
|
|
* -1 if the query failed
|
|
|
*
|
|
|
+ * int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process
|
|
|
+ * 0 if the request was sent successfully
|
|
|
+ * -1 if the request failed
|
|
|
+ * -2 if the request was rejected
|
|
|
+ *
|
|
|
+ * int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process
|
|
|
+ * 0 if the request was sent successfully
|
|
|
+ * -1 if the request failed
|
|
|
+ * -2 if the request was rejected
|
|
|
+ *
|
|
|
+ * int gamemode_query_status_for(pid_t pid) - Query the current status of gamemode for another
|
|
|
+ * process 0 if gamemode is inactive 1 if gamemode is active 2 if gamemode is active and this client
|
|
|
+ * is registered -1 if the query failed
|
|
|
+ *
|
|
|
* const char* gamemode_error_string() - Get an error string
|
|
|
* returns a string describing any of the above errors
|
|
|
*/
|
|
@@ -61,6 +75,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|
|
#include <errno.h>
|
|
|
#include <string.h>
|
|
|
|
|
|
+#include <sys/types.h>
|
|
|
+
|
|
|
static char internal_gamemode_client_error_string[512] = { 0 };
|
|
|
|
|
|
/**
|
|
@@ -72,26 +88,26 @@ static char internal_gamemode_client_error_string[512] = { 0 };
|
|
|
static volatile int internal_libgamemode_loaded = 1;
|
|
|
|
|
|
/* Typedefs for the functions to load */
|
|
|
-typedef int (*internal_gamemode_request_start)(void);
|
|
|
-typedef int (*internal_gamemode_request_end)(void);
|
|
|
-typedef int (*internal_gamemode_query_status)(void);
|
|
|
-typedef const char *(*internal_gamemode_error_string)(void);
|
|
|
+typedef int (*api_call_return_int)(void);
|
|
|
+typedef const char *(*api_call_return_cstring)(void);
|
|
|
+typedef int (*api_call_pid_return_int)(pid_t);
|
|
|
|
|
|
/* Storage for functors */
|
|
|
-static internal_gamemode_request_start REAL_internal_gamemode_request_start = NULL;
|
|
|
-static internal_gamemode_request_end REAL_internal_gamemode_request_end = NULL;
|
|
|
-static internal_gamemode_query_status REAL_internal_gamemode_query_status = NULL;
|
|
|
-static internal_gamemode_error_string REAL_internal_gamemode_error_string = NULL;
|
|
|
+static api_call_return_int REAL_internal_gamemode_request_start = NULL;
|
|
|
+static api_call_return_int REAL_internal_gamemode_request_end = NULL;
|
|
|
+static api_call_return_int REAL_internal_gamemode_query_status = NULL;
|
|
|
+static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
|
|
|
+static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
|
|
|
+static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
|
|
|
+static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
|
|
|
|
|
|
/**
|
|
|
* Internal helper to perform the symbol binding safely.
|
|
|
*
|
|
|
* Returns 0 on success and -1 on failure
|
|
|
*/
|
|
|
-__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(void *handle,
|
|
|
- const char *name,
|
|
|
- void **out_func,
|
|
|
- size_t func_size)
|
|
|
+__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
|
|
|
+ void *handle, const char *name, void **out_func, size_t func_size, bool required)
|
|
|
{
|
|
|
void *symbol_lookup = NULL;
|
|
|
char *dl_error = NULL;
|
|
@@ -99,7 +115,7 @@ __attribute__((always_inline)) static inline int internal_bind_libgamemode_symbo
|
|
|
/* Safely look up the symbol */
|
|
|
symbol_lookup = dlsym(handle, name);
|
|
|
dl_error = dlerror();
|
|
|
- if (dl_error || !symbol_lookup) {
|
|
|
+ if (required && (dl_error || !symbol_lookup)) {
|
|
|
snprintf(internal_gamemode_client_error_string,
|
|
|
sizeof(internal_gamemode_client_error_string),
|
|
|
"dlsym failed - %s",
|
|
@@ -147,6 +163,18 @@ __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
|
|
|
(void **)&REAL_internal_gamemode_error_string,
|
|
|
sizeof(REAL_internal_gamemode_error_string),
|
|
|
true },
|
|
|
+ { "real_gamemode_request_start_for",
|
|
|
+ (void **)&REAL_internal_gamemode_request_start_for,
|
|
|
+ sizeof(REAL_internal_gamemode_request_start_for),
|
|
|
+ false },
|
|
|
+ { "real_gamemode_request_end_for",
|
|
|
+ (void **)&REAL_internal_gamemode_request_end_for,
|
|
|
+ sizeof(REAL_internal_gamemode_request_end_for),
|
|
|
+ false },
|
|
|
+ { "real_gamemode_query_status_for",
|
|
|
+ (void **)&REAL_internal_gamemode_query_status_for,
|
|
|
+ sizeof(REAL_internal_gamemode_query_status_for),
|
|
|
+ false },
|
|
|
};
|
|
|
|
|
|
void *libgamemode = NULL;
|
|
@@ -175,8 +203,8 @@ __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
|
|
|
if (internal_bind_libgamemode_symbol(libgamemode,
|
|
|
binder->name,
|
|
|
binder->functor,
|
|
|
- binder->func_size) != 0 &&
|
|
|
- binder->required) {
|
|
|
+ binder->func_size,
|
|
|
+ binder->required)) {
|
|
|
internal_libgamemode_loaded = -1;
|
|
|
return -1;
|
|
|
};
|
|
@@ -275,4 +303,58 @@ __attribute__((always_inline)) static inline int gamemode_query_status(void)
|
|
|
return REAL_internal_gamemode_query_status();
|
|
|
}
|
|
|
|
|
|
+/* Redirect to the real libgamemode */
|
|
|
+__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
|
|
|
+{
|
|
|
+ /* Need to load gamemode */
|
|
|
+ if (internal_load_libgamemode() < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (REAL_internal_gamemode_request_start_for == NULL) {
|
|
|
+ snprintf(internal_gamemode_client_error_string,
|
|
|
+ sizeof(internal_gamemode_client_error_string),
|
|
|
+ "gamemode_request_start_for missing (older host?)");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return REAL_internal_gamemode_request_start_for(pid);
|
|
|
+}
|
|
|
+
|
|
|
+/* Redirect to the real libgamemode */
|
|
|
+__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
|
|
|
+{
|
|
|
+ /* Need to load gamemode */
|
|
|
+ if (internal_load_libgamemode() < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (REAL_internal_gamemode_request_end_for == NULL) {
|
|
|
+ snprintf(internal_gamemode_client_error_string,
|
|
|
+ sizeof(internal_gamemode_client_error_string),
|
|
|
+ "gamemode_request_end_for missing (older host?)");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return REAL_internal_gamemode_request_end_for(pid);
|
|
|
+}
|
|
|
+
|
|
|
+/* Redirect to the real libgamemode */
|
|
|
+__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
|
|
|
+{
|
|
|
+ /* Need to load gamemode */
|
|
|
+ if (internal_load_libgamemode() < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (REAL_internal_gamemode_query_status_for == NULL) {
|
|
|
+ snprintf(internal_gamemode_client_error_string,
|
|
|
+ sizeof(internal_gamemode_client_error_string),
|
|
|
+ "gamemode_query_status_for missing (older host?)");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return REAL_internal_gamemode_query_status_for(pid);
|
|
|
+}
|
|
|
+
|
|
|
#endif // CLIENT_GAMEMODE_H
|