dexedrine/dexedrine.c
2023-12-30 17:07:20 +00:00

161 lines
3.1 KiB
C

#include <bsd/libutil.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <systemd/sd-bus.h>
#include <unistd.h>
#include <linux/limits.h>
void handleSigs(int sig);
#define _cleanup_(f) __attribute__((cleanup(f)))
int main(int argc, char *argv[]) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
int fd = -1;
int r;
struct pidfh *pfh;
pid_t otherpid;
uid_t uid = getuid();
char pidfilePath[PATH_MAX];
/* Get the path to our pidfile in the users runtime directory */
r = snprintf(
pidfilePath,
PATH_MAX - 1 ,
"/run/user/%i/Dexedrine.pid", uid
);
if (r > PATH_MAX) {
fprintf(
stderr,
"Path generation failed, pidfilePath too long\n"
);
exit(EXIT_FAILURE);
}
/* Attempt to open/create out pidfile */
pfh = pidfile_open(pidfilePath, 0600, &otherpid);
if (pfh == NULL) {
switch (errno) {
case EEXIST:
fprintf(
stderr,
"Found an existing process at %jd, terminating\n",
(intmax_t)otherpid
);
kill(otherpid,SIGINT);
exit(EXIT_SUCCESS);
case EINVAL:
fprintf(
stderr,
"Pidfile at %s is locked, but the pid is invalid.\n",
pidfilePath
);
exit(EXIT_FAILURE);
default:
fprintf(
stderr,
"Failed to create/write pidfile %s\n",
strerror(errno)
);
exit(EXIT_FAILURE);
}
}
/* since pfh is not null we shall write to it. */
pidfile_write(pfh);
/* Catch sigint */
(void)signal(SIGINT,handleSigs);
/*
* WARNING:
* after this line you must always exit by `goto finish;`
*/
/* connect to system bus */
r = sd_bus_open_system(&bus);
if (r < 0) {
fprintf(
stderr,
"Failed to connect to system bus: %s\n",
strerror(-r)
);
goto finish;
}
/* call the Inhibit method and store fd */
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"Inhibit",
&error,
&msg,
"ssss",
/* What is being inhibited */
"idle:sleep:handle-lid-switch",
/* Who is inhibiting */
"Dexedrine",
/* Why are we inhibiting */
"Requested by user",
/* How are we inhibiting */
"block"
);
if (r < 0) {
fprintf(
stderr,
"Failed to issuse method call: %s\n",
error.message
);
goto finish;
}
r = sd_bus_message_read_basic(msg, 'h', &fd);
if (r < 0) {
fprintf(
stderr,
"Failed to read file descriptor: %s\n",
strerror(-r)
);
goto finish;
}
fd = dup(fd);
printf("Waiting for SIGINT...\n");
(void)pause(); /* Wait for any signal */
printf("Recieved signal. Exiting\n");
/* Close the file descriptor nicely */
r = close(fd);
if (r == -1) {
fprintf(
stderr,
"Failed to close file descriptor: %s\n",
strerror(errno));
}
/* Cleanup any mess before exiting */
finish:
pidfile_remove(pfh);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
/*
* While I don't want to actually do anything based on the signals
* I do need to make sure that they don't crash the program.
*/
void handleSigs(int sig)
{
return;
}