diff options
-rw-r--r-- | packaging/system-plugin.spec | 7 | ||||
-rw-r--r-- | src/systemd-user-helper/systemd-user-helper.c | 77 |
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 */ |