inital commit
This commit is contained in:
commit
d700ffac51
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
## Ignore the output binary
|
||||||
|
dexedrine
|
||||||
21
Makefile
Normal file
21
Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Define the variables for the compiler and the flags
|
||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -g
|
||||||
|
|
||||||
|
# Define the libraries to link
|
||||||
|
LIBS = -lsystemd -lbsd
|
||||||
|
|
||||||
|
# Define the source file and the output binary
|
||||||
|
BIN = dexedrine
|
||||||
|
SRC := $(BIN).c
|
||||||
|
|
||||||
|
# Define the default rule to build the program
|
||||||
|
all: $(BIN)
|
||||||
|
|
||||||
|
# Define the rule to compile the source file
|
||||||
|
$(BIN): $(SRC)
|
||||||
|
$(CC) $(CFLAGS) $(SRC) -o $(BIN) $(LIBS)
|
||||||
|
|
||||||
|
# Define the rule to clean the generated files
|
||||||
|
clean:
|
||||||
|
rm -f $(BIN)
|
||||||
50
Readme.md
Normal file
50
Readme.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Dexedrine - A simple way to keep your system up
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- libsystemd
|
||||||
|
- libbsd
|
||||||
|
- A C compiler (although this may only work with GCC)
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
- Run `make`
|
||||||
|
- Move the binary to somewhere in your PATH
|
||||||
|
- Run `dexedrine`
|
||||||
|
- Your system will now be blocked from suspending, going idle, and it
|
||||||
|
will ignore the lid switch
|
||||||
|
- To stop it either:
|
||||||
|
- Run `dexedrine` again (if you started it outside
|
||||||
|
of a terminal) it will find the running instance and send it a `SIGINT`
|
||||||
|
for you.
|
||||||
|
- Send `SIGINT` to `dexedrine`.
|
||||||
|
|
||||||
|
### Advanced usage
|
||||||
|
It is also possible to run `dexedrine` as a user `systemd` unit.
|
||||||
|
TODO: WRITE THE UNIT FILE
|
||||||
|
|
||||||
|
|
||||||
|
## Backstory
|
||||||
|
This is by all means a very dumb program, All it does is take out an
|
||||||
|
inhibitor on `systemd` to prevent your device from going idle, suspending, or
|
||||||
|
handling its lid switch.
|
||||||
|
|
||||||
|
I wrote it to solve a problem that I had in a way that made sense to me.
|
||||||
|
I wanted to turn off a monitor connected to my laptop without it realising
|
||||||
|
it was no longer connected to it, and as such re-reading the lid switch and
|
||||||
|
suspending.
|
||||||
|
|
||||||
|
While I could just disable sleep altogether when connected to power I
|
||||||
|
figured it would be easier if I could control when sleep could happen and
|
||||||
|
when it couldn't.
|
||||||
|
|
||||||
|
My original solution was much more basic, just running `systemd-inhibit`
|
||||||
|
with a long running program inside it. First I tried using `yes` but the
|
||||||
|
constant flood of output to `stdout` completely consumes a single core of
|
||||||
|
my CPU. I then thought about just using any program but that's a waste of
|
||||||
|
resources.
|
||||||
|
|
||||||
|
As such I decided to learn the basics of `dBus` in C and wrote Dexedrine.
|
||||||
|
|
||||||
|
## Why the Name?
|
||||||
|
Dexedrine is named for a brand of dextroamphetamine originally from 1937.
|
||||||
|
Dextroamphetamine is a potent CNS stimulant inspiring, in my opinion, a
|
||||||
|
clever name.
|
||||||
160
dexedrine.c
Normal file
160
dexedrine.c
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user