aboutsummaryrefslogtreecommitdiff
path: root/brightnessd.c
blob: ebd71a20a3f6377f3ac12cfb58053cdb57b976fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include <pwd.h>

#define FIFO_PATH   "/tmp/brightnessd-fifo"
#define BRIGHT_FILE	"/sys/class/backlight/radeon_bl0/brightness"
#define DELAY		5
#define STEP		1
#define BIG_STEP	10
#define USER        "nobody"

int get_now(FILE *f)
{
	char buffer[4096]; /* FIXME: magic constant is icky */
	/* FIXME: check return value for error */
	fgets(buffer, sizeof(buffer), f);

	return atoi(buffer);
}

int brightness_within_bounds(int bright, int lower, int upper)
{
	/* FIXME: make a horrible but funny ternary statement */
	if (bright < lower)
		return lower;

	if (bright > upper)
		return upper;

	return bright;
}

int main(int argc, char **argv)
{
	int target = 0;
	int now = 0;
	FILE *f = NULL;
	int fifo = 0;
	struct pollfd fds;
	struct passwd *p;
	int delay = 0;
	int nread = 0;
	char buffer[4]; /* size 4 because max bright is 255, plus null terminator */

	/* Open brightness file */
	if ((f = fopen(BRIGHT_FILE, "w+")) == NULL)
	{
		perror("fopen");
		exit(EXIT_FAILURE);
	}

	now = get_now(f);
	target = now;

	/* create and open fifo, using chmod since mkfifo is affected by umask */
	remove(FIFO_PATH);
	mkfifo(FIFO_PATH, 0666);
	chmod(FIFO_PATH, 0666);

	/* FIXME : check return val */
	fifo = open(FIFO_PATH, O_RDWR);


	fds.fd = fifo;
	fds.events = POLLIN;

	p = getpwnam(USER);

	if (p == NULL)
	{
		fprintf(stderr, "Failed to get uid and gid of user \""USER"\", bailing\n");
		return 1;
	}

	if (setgid(p->pw_gid))
	{
		fprintf(stderr, "Failed to set gid to %d\n", p->pw_gid);
		perror("setuid");
		return 1;
	}

	if (setuid(p->pw_uid))
	{
		fprintf(stderr, "Failed to set uid to %d\n", p->pw_uid);
		perror("setuid");
		return 1;
	}

	if (!setuid(0) || !setgid(0))
	{
		fprintf(stderr, "Got uid 0 or gid 0 back after dropping, bailing\n");
		return 1;
	}

	delay = -1;
	while(1)
	{
		poll(&fds, 1, delay);
		if (fds.revents & POLLIN)
		{
			delay = DELAY;
			nread = read(fifo, buffer, sizeof(buffer));
			if (nread == 0)
				perror("read");
			switch(buffer[0])
			{
				case '+':
					target += BIG_STEP;
					break;
				case '-':
					target -= BIG_STEP;
					break;
				default:
					target = atoi(buffer);
					break;
			}
			target = brightness_within_bounds(target, 1, 255);
		}
		if (now < target) {
			now += STEP;
			if (now > target)
				now = target;
		} else if (now > target) {
			now -= STEP;
			if (now < target)
				now = target;
		} else if (now == target) {
			delay = -1;
		}
		fprintf(f, "%d\n", now);
		rewind(f);
	}

	close(fifo);
	remove(FIFO_PATH);
	return 0;
}