aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2023-05-27 08:10:13 -0300
committerAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2023-10-19 10:56:54 +0200
commitb8613baa85965cbdf5fbe262b9464d5c0d98614f (patch)
tree97110f0bcdff7565cb95dc485653c20d5b27e06a
parente8f8f5ac734181ca313f0966f4397d9888baebd4 (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.c69
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);