aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd-launch.c15
-rw-r--r--src/launch.c87
-rw-r--r--src/launch.h2
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);