summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packaging/system-plugin.spec7
-rw-r--r--src/systemd-user-helper/systemd-user-helper.c77
2 files changed, 72 insertions, 12 deletions
diff --git a/packaging/system-plugin.spec b/packaging/system-plugin.spec
index 3622003..13684a2 100644
--- a/packaging/system-plugin.spec
+++ b/packaging/system-plugin.spec
@@ -308,12 +308,13 @@ mv %{_sysconfdir}/fstab_lazymnt %{_sysconfdir}/fstab
%manifest systemd-user-helper.manifest
%caps(cap_sys_admin,cap_mac_admin,cap_mac_override,cap_dac_override,cap_setgid=ei) %{_bindir}/systemd_user_helper
+#TODO: when uninstalling, it should be restored to original file
%posttrans -n systemd-user-helper
cp -a /usr/lib/systemd/system/user\@.service /usr/lib/systemd/system/__user@.service
-/usr/bin/sed -i -e 's/Type=\(.*\)/Type=simple/' /usr/lib/systemd/system/user\@.service
+/usr/bin/sed -i -e 's/Type=\(.*\)/Type=forking/' /usr/lib/systemd/system/user\@.service
/usr/bin/sed -i -e 's/ExecStart=\(.*\)/ExecStart=\/usr\/bin\/systemd_user_helper %i/' /usr/lib/systemd/system/user\@.service
-/usr/bin/sed -i -e '/RemainAfterExit=\(.*\)/d' /usr/lib/systemd/system/user\@.service
-echo 'RemainAfterExit=yes' >> /usr/lib/systemd/system/user\@.service
+/usr/bin/sed -i -e '/PIDFile=\(.*\)/d' /usr/lib/systemd/system/user\@.service
+echo 'PIDFile=/run/user/%i/.systemd.pid' >> /usr/lib/systemd/system/user\@.service
%files profile_ivi
%{_prefix}/lib/udev/rules.d/99-usb-ethernet.rules
diff --git a/src/systemd-user-helper/systemd-user-helper.c b/src/systemd-user-helper/systemd-user-helper.c
index a5e22e0..a61a90d 100644
--- a/src/systemd-user-helper/systemd-user-helper.c
+++ b/src/systemd-user-helper/systemd-user-helper.c
@@ -19,13 +19,19 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <signal.h>
#include <errno.h>
+#include <limits.h>
+#include <sys/stat.h>
#include <sched.h>
#include <sys/mount.h>
#include <tzplatform_config.h>
+#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0]))
+#define PIDFILE_PATH ".systemd.pid"
+
// For compatibility, Using hard-coded path
#define LEGACY_CONTENTS_DIR "/opt/usr/media"
#define LEGACY_APPS_DIR "/opt/usr/apps"
@@ -34,7 +40,7 @@
#define CONTAINER_LIB "/usr/lib/security/pam_krate.so"
#define LOAD_SYMBOL(handle, sym, name) \
- do{ \
+ do { \
sym = dlsym(handle, name); \
if (!sym) { \
fprintf(stderr, "dlsym %s error\n", name); \
@@ -45,18 +51,24 @@
static void *container_handle = NULL;
+static const char *systemd_arg[] = {
+ "/usr/lib/systemd/systemd",
+ "--user",
+ NULL
+};
+
static int normal_user_preprocess(char *username)
{
int r;
r = unshare(CLONE_NEWNS);
if (r < 0) {
- fprintf(stderr,"unshare failed\n");
+ fprintf(stderr, "unshare failed\n");
return r;
}
r = mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL);
if (r < 0) {
- fprintf(stderr,"Failed to change the propagation type of root to SLAVE\n");
+ fprintf(stderr, "Failed to change the propagation type of root to SLAVE\n");
return r;
}
@@ -69,14 +81,14 @@ static int normal_user_postprocess(char *username)
r = mount(tzplatform_getenv(TZ_USER_CONTENT),
LEGACY_CONTENTS_DIR, NULL, MS_BIND, NULL);
if (r < 0) {
- fprintf(stderr, "user content bind mount failed - %d\n",errno);
+ fprintf(stderr, "user content bind mount failed - %d\n", errno);
return r;
}
r = mount(tzplatform_getenv(TZ_USER_APP),
LEGACY_APPS_DIR, NULL, MS_BIND, NULL);
if (r < 0) {
- fprintf(stderr, "user app bind mount failed - %d\n",errno);
+ fprintf(stderr, "user app bind mount failed - %d\n", errno);
return r;
}
@@ -143,8 +155,8 @@ static int wait_condition(void)
int (*wait_mount_user)(void);
- r = access(LAZYMOUNT_LIB,F_OK);
- if (r < 0){
+ r = access(LAZYMOUNT_LIB, F_OK);
+ if (r < 0) {
fprintf(stderr, "cannot find lazymount module - No support lazymount\n");
return 0;
}
@@ -168,6 +180,52 @@ static int wait_condition(void)
return 0;
}
+static int make_pid_file(int pid, char* user_id)
+{
+ FILE *fp;
+ char pidpath[PATH_MAX];
+ int r = 0;
+
+ snprintf(pidpath, PATH_MAX, "/run/user/%s/%s", user_id, PIDFILE_PATH);
+
+ fp = fopen(pidpath, "w+");
+ if (fp != NULL) {
+ fprintf(fp, "%d", pid);
+ fclose(fp);
+ } else
+ r = -1;
+
+ return r;
+}
+
+int run_child(int argc, const char *argv[], char* user_id)
+{
+ pid_t pid;
+ int r = 0;
+ int i;
+
+ if (!argv)
+ return -EINVAL;
+
+ pid = fork();
+
+ if (pid < 0) {
+ fprintf(stderr, "failed to fork");
+ r = -errno;
+ } else if (pid == 0) {
+ for (i = 0; i < _NSIG; ++i)
+ signal(i, SIG_DFL);
+
+ r = execv(argv[0], (char **)argv);
+ /* NOT REACH */
+ } else{
+ make_pid_file(pid, user_id);
+ r = pid;
+ }
+
+ return r;
+}
+
int main(int argc, char *argv[])
{
int r = 0;
@@ -195,11 +253,12 @@ int main(int argc, char *argv[])
}
}
- /* TODO: fork & exec */
- r = system("/usr/lib/systemd/systemd --user &");
+ r = run_child(ARRAY_SIZE(systemd_arg), systemd_arg, argv[1]);
if (r < 0) {
fprintf(stderr, "systemd user execution failed\n");
return r;
+ } else{
+ fprintf(stderr, "success = pid = %d\n", r);
}
/* sync-style since there is no need to process other signal */