mirror of
https://github.com/notmaj0r/CheatRunner.git
synced 2026-10-22 00:32:59 -05:00
162 lines
5.0 KiB
C
162 lines
5.0 KiB
C
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h>
|
|
#include <signal.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
|
|
#include "jb.h"
|
|
#include "priv_bootstrap.h"
|
|
#include "ps5sdk_compat.h"
|
|
#include "cr_activity.h"
|
|
#include "cr_config.h"
|
|
#include "cr_game_monitor.h"
|
|
#include "cr_http.h"
|
|
#include "cr_launch.h"
|
|
#include "cr_log.h"
|
|
#include "cr_notifications.h"
|
|
#include "cr_paths.h"
|
|
#include "cr_shutdown.h"
|
|
#include "cr_cheats.h"
|
|
#include "cr_addr_cache.h"
|
|
#include "cr_title_prefs.h"
|
|
#include "cr_favorites.h"
|
|
#include "cr_fan.h"
|
|
#include "cr_tile_pkg.h"
|
|
|
|
#ifndef CHEATRUNNER_VERSION
|
|
#define CHEATRUNNER_VERSION "0.14"
|
|
#endif
|
|
|
|
/* Async-signal-safe crash handler: writes a one-line entry to the crash log
|
|
* using only open/write/close/_exit (no malloc, no stdio). */
|
|
static void
|
|
crash_sighandler(int sig) {
|
|
static const char path[] = CHEATRUNNER_CRASH_LOG_PATH;
|
|
int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644);
|
|
if (fd >= 0) {
|
|
static const char hdr[] = "signal=";
|
|
static const char tail[] = " CheatRunner crashed\n";
|
|
int s = (sig < 0 ? 0 : (sig > 99 ? 99 : sig));
|
|
char nb[2];
|
|
nb[0] = (char)('0' + s / 10);
|
|
nb[1] = (char)('0' + s % 10);
|
|
(void)write(fd, hdr, sizeof(hdr) - 1);
|
|
(void)write(fd, nb, 2);
|
|
(void)write(fd, tail, sizeof(tail) - 1);
|
|
close(fd);
|
|
}
|
|
_exit(sig);
|
|
}
|
|
|
|
int
|
|
main(void) {
|
|
pid_t old_pid;
|
|
signal(SIGPIPE, SIG_IGN);
|
|
{
|
|
struct sigaction sa;
|
|
sa.sa_handler = crash_sighandler;
|
|
sigemptyset(&sa.sa_mask);
|
|
sa.sa_flags = SA_RESETHAND;
|
|
sigaction(SIGSEGV, &sa, NULL);
|
|
sigaction(SIGBUS, &sa, NULL);
|
|
}
|
|
|
|
syscall(SYS_thr_set_name, -1, "CheatRunner.elf");
|
|
|
|
cr_log_klog_banner();
|
|
|
|
puts(" ____ _ _ ____ ");
|
|
puts(" / ___| |__ ___ __ _| |_| _ \\ _ _ _ __ _ __ ___ _ __ ");
|
|
puts(" | | | '_ \\ / _ \\/ _` | __| |_) | | | | '_ \\| '_ \\ / _ \\ '__|");
|
|
puts(" | |___| | | | __/ (_| | |_| _ <| |_| | | | | | | | __/ | ");
|
|
puts(" \\____|_| |_|\\___|\\__,_|\\__|_| \\_\\\\__,_|_| |_|_| |_|\\___|_| ");
|
|
log_msg("version: %s", CHEATRUNNER_VERSION);
|
|
|
|
#ifdef __SCE__
|
|
if (jb_escalate_pid(getpid()) != 0) {
|
|
cr_log("warn", "core", "jb_escalate_pid failed; privilege may be incomplete");
|
|
}
|
|
cr_priv_init();
|
|
{
|
|
const cr_priv_status_t *ps = cr_priv_get();
|
|
cr_log("info", "priv",
|
|
"uid=%d gid=%d euid=%d egid=%d uid_ok=%d sandbox=%d authid_ok=%d caps_ok=%d kernel_rw=%d mprotect=%d can_patch=%d",
|
|
ps->uid, ps->gid, ps->euid, ps->egid, ps->uid_ok, ps->sandbox_ok, ps->authid_ok, ps->caps_ok,
|
|
ps->kernel_rw_ok, ps->kernel_mprotect_ok, ps->can_patch_game);
|
|
if (!ps->can_patch_game) {
|
|
cr_log("warn", "priv", "privilege bootstrap incomplete; cheat writes may fail");
|
|
for (int i = 0; i < ps->n_warnings; i++) {
|
|
cr_log("warn", "priv", " %s", ps->warnings[i]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* Kill any previous instance before binding; EPERM (old instance escalated, we aren't) breaks fast, ESRCH treated as gone, capped at 60 spins so a zombie can't loop forever. */
|
|
{
|
|
int kill_spins = 0;
|
|
while ((old_pid = find_pid_by_name("CheatRunner.elf")) > 0 && kill_spins < 60) {
|
|
int kerr = kill(old_pid, SIGKILL);
|
|
if (kerr != 0) {
|
|
int e = errno;
|
|
cr_log("warn", "boot", "SIGKILL pid=%d errno=%d", old_pid, e);
|
|
if (e == EPERM) {
|
|
cr_log("error", "boot",
|
|
"cannot kill old instance (EPERM) — escalation may have failed");
|
|
break;
|
|
}
|
|
if (e == ESRCH) break; /* already dead */
|
|
}
|
|
usleep(150 * 1000);
|
|
kill_spins++;
|
|
}
|
|
if (old_pid > 0 && kill_spins >= 60) {
|
|
cr_log("warn", "boot", "old instance pid=%d still visible after 9s (zombie?)", old_pid);
|
|
}
|
|
}
|
|
|
|
{
|
|
int urc = sceUserServiceInitialize(NULL);
|
|
if (urc != 0 && urc != (int)0x80960003) {
|
|
cr_log("warn", "core", "sceUserServiceInitialize rc=0x%08X", (uint32_t)urc);
|
|
}
|
|
}
|
|
|
|
ensure_data_dirs();
|
|
config_load();
|
|
notifications_load();
|
|
activity_load();
|
|
crash_suspects_load();
|
|
addr_cache_load();
|
|
title_prefs_load();
|
|
favorites_load();
|
|
fan_init();
|
|
cr_tile_autoinstall_init();
|
|
rpc_refresh_title_and_notify();
|
|
set_launch_status_ex(0, "idle", "", "ready", 1, "", 0, 0);
|
|
notify("CheatRunner v" CHEATRUNNER_VERSION " by maj0r");
|
|
notification_add("boot", "CheatRunner v" CHEATRUNNER_VERSION " started");
|
|
cr_log("info", "boot", "version %s", CHEATRUNNER_VERSION);
|
|
|
|
pthread_t http_thread;
|
|
pthread_t monitor_thread;
|
|
if (pthread_create(&http_thread, NULL, http_server_thread, NULL) != 0) {
|
|
log_msg("error: could not start HTTP thread");
|
|
notify("CheatRunner HTTP thread failed");
|
|
return 1;
|
|
}
|
|
if (pthread_create(&monitor_thread, NULL, game_monitor_thread, NULL) != 0) {
|
|
log_msg("error: could not start game monitor thread");
|
|
notify("CheatRunner game monitor thread failed");
|
|
return 1;
|
|
}
|
|
|
|
pthread_join(http_thread, NULL);
|
|
g_game_monitor_running = 0;
|
|
pthread_join(monitor_thread, NULL);
|
|
return 0;
|
|
}
|