diff options
author | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2023-05-27 08:10:13 -0300 |
---|---|---|
committer | Anna (navi) Figueiredo Gomes <navi@vlhl.dev> | 2023-10-19 10:56:54 +0200 |
commit | b8613baa85965cbdf5fbe262b9464d5c0d98614f (patch) | |
tree | 97110f0bcdff7565cb95dc485653c20d5b27e06a | |
parent | e8f8f5ac734181ca313f0966f4397d9888baebd4 (diff) |
openrc: create lockfile for --user.
the pam module sets a variable that when in user mode, openrc should
pick up and either create/increment, or decrement. this is done so that
multiple session_open and session_close from pam doesn't randomly change
the user runlevel for the current user. only the first session open
starts the default runlevel, and only the last session close switches to
the none runlevel.
Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
-rw-r--r-- | src/openrc/rc.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/src/openrc/rc.c b/src/openrc/rc.c index dca94a7f..366ceca2 100644 --- a/src/openrc/rc.c +++ b/src/openrc/rc.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include <signal.h> #include <string.h> +#include <sys/file.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/types.h> @@ -819,6 +820,60 @@ handle_bad_signal(int sig) } #endif +#ifdef RC_USER_SERVICES + +static int +inc_dec_lockfile(int val) +{ + char *svcdir = NULL; + char *lockfile_path = NULL; + FILE *lockfile = NULL; + + int locknum = 0; + + einfov("locking lockfile"); + + svcdir = rc_user_svcdir(); + + if (mkdir(svcdir, 0700) != 0 && errno != EEXIST) + eerrorx("mkdir: %s, %s", svcdir, strerror(errno)); + + xasprintf(&lockfile_path, "%s/%s", svcdir, "lock"); + lockfile = fopen(lockfile_path, "r+"); + if (!lockfile) { + lockfile = fopen(lockfile_path, "w+"); + if (!lockfile) + eerrorx("fopen: failed to open file %s, %s", lockfile_path, strerror(errno)); + if (flock(fileno(lockfile), LOCK_EX) != 0) { + eerrorx("flock: %s", strerror(errno)); + } + locknum = 1; + } else { + if (flock(fileno(lockfile), LOCK_EX) != 0) { + eerrorx("flock: %s", strerror(errno)); + } + fscanf(lockfile, "%d", &locknum); + locknum += val; + rewind(lockfile); + } + + free(lockfile_path); + free(svcdir); + + fprintf(lockfile, "%d", locknum); + + if (flock(fileno(lockfile), LOCK_UN)) { + eerrorx("flock: %s", strerror(errno)); + } + fclose(lockfile); + + einfov("unlocking lockfile"); + + return locknum; +} + +#endif + int main(int argc, char **argv) { const char *bootlevel = NULL; @@ -839,7 +894,7 @@ int main(int argc, char **argv) bool nostop = false; #ifdef RC_USER_SERVICES char *user_svcdir = NULL; - char *user_sysconfdir = NULL; + int locknum = 0; #endif #ifdef __linux__ char *proc; @@ -946,6 +1001,18 @@ int main(int argc, char **argv) #ifdef RC_USER_SERVICES if (rc_is_user()) { + if (rc_yesno(getenv("RC_PAM_STARTING"))) { + /* the lockfile count -1 because we don't want to count ourselves */ + locknum = inc_dec_lockfile(1) - 1; + } else if (rc_yesno(getenv("RC_PAM_STOPPING"))) { + locknum = inc_dec_lockfile(-1); + } + + if (locknum > 0) { + einfov("lock set, skipping"); + return EXIT_SUCCESS; + } + user_svcdir = rc_user_svcdir(); xasprintf(&rc_stopping, "%s/%s", user_svcdir, RC_STOPPING_FOLDER); xasprintf(&rc_starting, "%s/%s", user_svcdir, RC_STARTING_FOLDER); |