+ umask(context->umask);
+
+ if (chdir(context->directory ? context->directory : "/") < 0) {
+ r = EXIT_CHDIR;
+ goto fail;
+ }
+
+ snprintf(t, sizeof(t), "%i", context->oom_adjust);
+ char_array_0(t);
+
+ if (write_one_line_file("/proc/self/oom_adj", t) < 0) {
+ r = EXIT_OOM_ADJUST;
+ goto fail;
+ }
+
+ if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
+ r = EXIT_NICE;
+ goto fail;
+ }
+
+ if (close_fds(fds, n_fds) < 0 ||
+ shift_fds(fds, n_fds) < 0) {
+ r = EXIT_FDS;
+ goto fail;
+ }
+
+ for (i = 0; i < RLIMIT_NLIMITS; i++) {
+ if (!context->rlimit[i])
+ continue;
+
+ if (setrlimit(i, context->rlimit[i]) < 0) {
+ r = EXIT_LIMITS;
+ goto fail;
+ }
+ }
+
+ if (n_fds > 0) {
+ char a[64], b[64];
+ char *listen_env[3] = {
+ a,
+ b,
+ NULL
+ };
+
+ snprintf(a, sizeof(a), "LISTEN_PID=%llu", (unsigned long long) getpid());
+ snprintf(b, sizeof(b), "LISTEN_FDS=%u", n_fds);
+
+ a[sizeof(a)-1] = 0;
+ b[sizeof(b)-1] = 0;
+
+ if (context->environment) {
+ if (!(f = strv_merge(listen_env, context->environment))) {
+ r = EXIT_MEMORY;
+ goto fail;
+ }
+ e = f;
+ } else
+ e = listen_env;
+
+ } else
+ e = context->environment;
+
+ execve(command->path, command->argv, e);
+ r = EXIT_EXEC;
+
+ fail:
+ strv_free(f);
+ _exit(r);
+ }
+
+ *ret = pid;