diff options
| -rw-r--r-- | src/cmd-launch.c | 15 | ||||
| -rw-r--r-- | src/launch.c | 87 | ||||
| -rw-r--r-- | src/launch.h | 2 |
3 files changed, 102 insertions, 2 deletions
diff --git a/src/cmd-launch.c b/src/cmd-launch.c index 2d44b44..02a4231 100644 --- a/src/cmd-launch.c +++ b/src/cmd-launch.c @@ -12,8 +12,14 @@ unsigned cmd_launch2(struct l2_context_node *ctx, char **args) unsigned ures; int res; - if (*args) { - CMD_FATAL0("sorry launch settings aren't implemented yet"); + bool detach = true; + + for (char **cur = args; *cur; ++cur) { + if (!strcmp(*cur, "--nodetach")) { + detach = false; + } else { + CMD_FATAL(CMD_MSG_UNKNOWN_ARGUMENT, *cur); + } } char *instancename = NULL; @@ -62,6 +68,10 @@ unsigned cmd_launch2(struct l2_context_node *ctx, char **args) if (l2_user_update_profile(user) < 0) { CMD_FATAL0("Failed to update profile"); } + + if (l2_user_save() < 0) { + CMD_FATAL0("Failed to save user"); + } } struct l2_launch launch = { 0 }; @@ -70,6 +80,7 @@ unsigned cmd_launch2(struct l2_context_node *ctx, char **args) } launch.user = user; + launch.detach = detach; if (l2_launch_init_substitutor(&launch) < 0) { CMD_FATAL0("Failed to initialize argument substitutor"); diff --git a/src/launch.c b/src/launch.c index 942cbbb..12246de 100644 --- a/src/launch.c +++ b/src/launch.c @@ -14,6 +14,8 @@ #include <stdarg.h> #include <stdio.h> #include <unistd.h> +#include <signal.h> +#include <sys/wait.h> bool l2_launch__check_feature(const char *name, json_t *val, void *user); int l2_launch_init_substitutor(struct l2_launch *launch); @@ -573,6 +575,84 @@ int l2_launch__find_jni(struct l2_launch *launch, char **jnifile) return 0; } +volatile bool l2_launch__signal_wait = true; +pid_t l2_launch__wait_pid = 0; + +void l2_launch__handle_sigusr1(int signum, siginfo_t *info, void *unk) +{ + L2_UNUSED(unk); + + if (signum == SIGUSR1 && info->si_pid == l2_launch__wait_pid) + l2_launch__signal_wait = false; +} + +int l2_launch__detach(void) +{ + pid_t childpid; + + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_sigaction = &l2_launch__handle_sigusr1; + act.sa_flags = SA_SIGINFO | SA_RESETHAND; + + if (sigaction(SIGUSR1, &act, NULL) < 0) { + CMD_ERROR("Failed to set signal action for SIGUSR1: %s", strerror(errno)); + return -1; + } + + if ((childpid = fork()) < 0) { + CMD_ERROR("Failed to fork(): %s", strerror(errno)); + return -1; + } else if (!childpid) { + raise(SIGUSR1); /* clear signal handler */ + return 0; + } else { + l2_launch__wait_pid = childpid; + + int waitres = 0; + pid_t pidret; + while (l2_launch__signal_wait) { + if ((pidret = waitpid(childpid, &waitres, WNOHANG)) < 0) { + CMD_ERROR("Failed to wait for child %d: %s", childpid, strerror(errno)); + return -1; + } + + if (pidret == childpid && WIFEXITED(waitres)) { + CMD_ERROR("Child exited prematurely (%d)", WEXITSTATUS(waitres)); + return -1; + } + + pause(); + } + + CMD_INFO0("Game launched! Exiting."); + fflush(stderr); + + _exit(0); + } +} + +int l2_launch__detach_complete(void) +{ + pid_t parent = getppid(); + + if (setsid() == (pid_t)-1) { + CMD_ERROR("Failed to set SID: %s", strerror(errno)); + return -1; + } + + if (kill(parent, SIGUSR1) < 0) { + CMD_ERROR("Failed to kill parent (%d): %s", parent, strerror(errno)); + return -1; + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + return 0; +} + int l2_launch_jni(struct l2_launch *launch) { int res = 0; @@ -602,6 +682,8 @@ int l2_launch_jni(struct l2_launch *launch) memset(&args, 0, sizeof(JavaVMInitArgs)); args.version = JNI_VERSION_1_8; + if (launch->detach && l2_launch__detach() < 0) return -1; + char *main_class_fq; size_t main_class_len; L2_ASTRDUP(main_class_fq, main_class_len, launch->main_class); @@ -660,6 +742,11 @@ int l2_launch_jni(struct l2_launch *launch) goto cleanup; } + if (launch->detach && l2_launch__detach_complete() < 0) { + res = -1; + goto cleanup; + } + (*env)->CallStaticVoidMethod(env, jmaincls, main_method, jargs); if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionDescribe(env); diff --git a/src/launch.h b/src/launch.h index 3378e41..b2e1871 100644 --- a/src/launch.h +++ b/src/launch.h @@ -37,6 +37,8 @@ struct l2_launch { size_t njvm_args; struct l2_user *user; + + bool detach; }; int l2_launch_init(struct l2_launch *launch, const char *vername, struct l2_instance *inst); |
