redshift: Add hooks for user actions on period switch

Hooks are executable scripts in ~/.config/redshift/hooks/ that
are run when a certain event happens. The first parameter to the
script indicates the event and further parameters may indicate
more details about the event.

The event "period-changed" is indicated when the period changes
("night", "daytime", "transition"). The second parameter is the old
period and the third is the new period. The event is signaled when
Redshift starts up with the old period set to "none".
This commit is contained in:
Jon Lund Steffensen
2014-12-28 01:36:26 -05:00
parent 4a572e85e9
commit 159754c1cd
4 changed files with 162 additions and 0 deletions
+1
View File
@@ -15,6 +15,7 @@ redshift_SOURCES = \
location-manual.c location-manual.h \
solar.c solar.h \
systemtime.c systemtime.h \
hooks.c hooks.h \
gamma-dummy.c gamma-dummy.h
EXTRA_redshift_SOURCES = \
+113
View File
@@ -0,0 +1,113 @@
/* hooks.c -- Hooks triggered by events
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Redshift is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
Copyright (c) 2014 Jon Lund Steffensen <jonlst@gmail.com>
*/
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#ifndef _WIN32
# include <pwd.h>
#endif
#include "hooks.h"
#include "redshift.h"
#define MAX_HOOK_PATH 4096
/* Names of periods supplied to scripts. */
static const char *period_names[] = {
"none",
"daytime",
"night",
"transition"
};
/* Try to open the directory containing hooks. HP is a string
of MAX_HOOK_PATH length that will be filled with the path
of the returned directory. */
static DIR *
open_hooks_dir(char *hp)
{
char *env;
if ((env = getenv("XDG_CONFIG_HOME")) != NULL &&
env[0] != '\0') {
snprintf(hp, MAX_HOOK_PATH, "%s/redshift/hooks", env);
return opendir(hp);
}
if ((env = getenv("HOME")) != NULL &&
env[0] != '\0') {
snprintf(hp, MAX_HOOK_PATH, "%s/.config/redshift/hooks", env);
return opendir(hp);
}
#ifndef _WIN32
struct passwd *pwd = getpwuid(getuid());
snprintf(hp, MAX_HOOK_PATH, "%s/.config/redshift/hooks", pwd->pw_dir);
return opendir(hp);
#else
return NULL;
#endif
}
/* Run hooks with a signal that the period changed. */
void
hooks_signal_period_change(period_t prev_period, period_t period)
{
char hooksdir_path[MAX_HOOK_PATH];
DIR *hooks_dir = open_hooks_dir(hooksdir_path);
if (hooks_dir == NULL) return;
struct dirent* ent;
while ((ent = readdir(hooks_dir)) != NULL) {
/* Skip hidden and special files (., ..) */
if (ent->d_name[0] == '\0' || ent->d_name[0] == '.') continue;
char *hook_name = ent->d_name;
char hook_path[MAX_HOOK_PATH];
snprintf(hook_path, sizeof(hook_path), "%s/%s",
hooksdir_path, hook_name);
#ifndef _WIN32
/* Fork and exec the hook. We close stdout
so the hook cannot interfere with the normal
output. */
pid_t pid = fork();
if (pid == (pid_t)-1) {
perror("fork");
continue;
} else if (pid == 0) { /* Child */
close(STDOUT_FILENO);
int r = execl(hook_path, hook_name,
"period-changed",
period_names[prev_period],
period_names[period], NULL);
if (r < 0 && errno != EACCES) perror("execl");
/* Only reached on error */
_exit(EXIT_FAILURE);
}
#endif
}
}
+29
View File
@@ -0,0 +1,29 @@
/* hooks.h -- Hooks triggered by events
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Redshift is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
Copyright (c) 2014 Jon Lund Steffensen <jonlst@gmail.com>
*/
#ifndef REDSHIFT_HOOKS_H
#define REDSHIFT_HOOKS_H
#include "redshift.h"
void hooks_signal_period_change(period_t prev_period,
period_t period);
#endif /* ! REDSHIFT_HOOKS_H */
+19
View File
@@ -48,6 +48,7 @@
#include "config-ini.h"
#include "solar.h"
#include "systemtime.h"
#include "hooks.h"
#define MIN(x,y) ((x) < (y) ? (x) : (y))
@@ -1422,6 +1423,18 @@ main(int argc, char *argv[])
perror("sigaction");
exit(EXIT_FAILURE);
}
/* Ignore CHLD signal. This causes child processes
(hooks) to be reaped automatically. */
sigact.sa_handler = SIG_IGN;
sigact.sa_mask = sigset;
sigact.sa_flags = 0;
r = sigaction(SIGCHLD, &sigact, NULL);
if (r < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
#endif /* HAVE_SIGNAL_H && ! __WIN32__ */
if (verbose) {
@@ -1517,6 +1530,12 @@ main(int argc, char *argv[])
print_period(period, transition);
}
/* Activate hooks if period changed */
if (period != prev_period) {
hooks_signal_period_change(prev_period,
period);
}
/* Ongoing short transition */
if (short_trans_delta) {
/* Calculate alpha */