You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeutils/klaptopdaemon/acpi_helper.cpp

336 lines
8.8 KiB

/*
* acpi_helper.cpp - acpi helper
*
* Copyright (c) 2002 Paul Campbell <paul@taniwha.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//
// README!!
//
// This file contains code that is intended to be run setuid root
// (only if the end user enables it themselves, it's not set that
// way as part of a standard KDE build).
//
// Because of this this code should be simple and easily visually
// inspected for security holes and/or bugs - if you feel the need
// to change this file please get someone else to review your work
// (I'll happily do it for you - mail me at paul@taniwha.com, please
// review mine!)
//
// I recommend the following practices here - both for safety and
// transparency:
//
// - check all array references (snprintf/strncpy etc)
//
// - avoid malloc/new calls and pointers too if possible
//
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#define MAX_TOSHIBA_STRING 64
/* Write a value to /proc/acpi/sleep, where value may be between
1 and 4 (whatever they mean). Does not return; calls exit(). */
void write_to_proc_sleep(int value)
{
char tmp[256];
int fd;
/* Sanity check value */
if ((value<1) || (value>4))
exit(1);
/* Convert value to string */
snprintf(tmp,sizeof(tmp),"%d",value);
tmp[sizeof(tmp)-1]=0;
/* Broken imitation of typing sync <enter> sync <enter>
on the command line before shutting down the machine;
part of the lore of UNIX machines. */
sync();
sync();
fd = open("/proc/acpi/sleep", O_RDWR);
if (fd < 0)
exit(1);
write(fd, tmp, 1);
close(fd);
setuid(getuid()); // drop all priority asap
exit(0);
}
/* Write string to new acpi power interface */
void write_to_power(const char * str)
{
int fd;
/* Broken imitation of typing sync <enter> sync <enter>
on the command line before shutting down the machine;
part of the lore of UNIX machines. */
sync();
sync();
fd = open("/sys/power/state", O_RDWR);
if (fd < 0)
exit(1);
write(fd, str, strlen(str));
close(fd);
setuid(getuid()); // drop all priority asap
exit(0);
}
/* Run the program @param path, if it exists and seems safe to do so.
Returns only if the program does not exist; if the program exists
and is unsafe, exit; if the program exists and is safe, run it
and never return. */
void run_program(const char *path, const int action)
{
struct stat sb;
int err;
if (!path) exit(1); /* Bad pointer */
if (path[0] != '/') exit(1); /* Not an absolute path */
if ((err = stat(path, &sb)) != 0 || sb.st_mode&S_IWOTH) {
if (err != 0) {
fprintf(stderr, "Can't find %s\n", path);
return;
} else {
fprintf(stderr, "%s is writeable by anyone - we don't trust it\n", path);
}
exit(1);
}
::setuid(::geteuid()); // otherwise bash will throw it away
if (action == 1) {
system("/usr/sbin/pmi action hibernate");
} else if (action == 2) {
system("/usr/sbin/pmi action sleep");
} else {
::execl(path, NULL); // this is not KDE environment code
}
exit(0);
}
int
main(int argc, char **argv)
{
int fd;
int i;
int toshibalcd_val = 0;
bool useSysPower=false;
fd = open("/sys/power/state", O_RDWR);
if (fd >= 0)
useSysPower=true;
close(fd);
::close(0); // we're setuid - this is just in case
for (i = 1; i < argc; i++)
if (strcmp(argv[i], "--suspend") == 0 || strcmp(argv[i], "-suspend") == 0) {
/* Returns only if suspend does not exist. */
run_program("/usr/sbin/pmi", 2);
/*
if (useSysPower)
write_to_power("mem");
else
write_to_proc_sleep(3);
*/
exit(0);
} else
if (strcmp(argv[i], "--standby") == 0 || strcmp(argv[i], "-standby") == 0) {
if (useSysPower)
write_to_power("standby");
else
write_to_proc_sleep(1);
exit(0);
} else
if (strcmp(argv[i], "--standby2") == 0 || strcmp(argv[i], "-standby2") == 0) {
write_to_proc_sleep(2);
exit(0);
} else
if (strcmp(argv[i], "--hibernate") == 0 || strcmp(argv[i], "-hibernate") == 0) {
run_program("/usr/sbin/pmi", 1);
/*
if (useSysPower)
write_to_power("disk");
else
write_to_proc_sleep(4);
*/
exit(0);
} else
if (strcmp(argv[i], "--software-suspend") == 0 || strcmp(argv[i], "-software-suspend") == 0) {
run_program("/usr/sbin/hibernate", 0);
exit(0);
} else
if (strcmp(argv[i], "--throttling") == 0 || strcmp(argv[i], "-throttling") == 0) {
int val;
char tmp[256];
i++;
if (i >= argc)
break;
if (strlen(argv[i]) > 50 || strchr(argv[i], '.'))
break;
snprintf(tmp, sizeof(tmp), "/proc/acpi/processor/%s/throttling", argv[i]);
tmp[sizeof(tmp)-1] = 0;
i++;
if (i >= argc)
break;
val= atoi(argv[i]);
if (val < 0)
break;
sync();
sync();
fd = open(tmp, O_RDWR);
if (fd < 0)
exit(1);
snprintf(tmp, sizeof(tmp), "%d", val);
write(fd, tmp, strlen(tmp));
close(fd);
setuid(getuid()); // drop all priority asap
exit(0);
} else
if (strcmp(argv[i], "--performance") == 0 || strcmp(argv[i], "-performance") == 0) {
int val;
char tmp[256];
i++;
if (i >= argc)
break;
if (strlen(argv[i]) > 50 || strchr(argv[i], '.'))
break;
snprintf(tmp, sizeof(tmp), "/proc/acpi/processor/%s/performance", argv[i]);
tmp[sizeof(tmp)-1] = 0;
i++;
if (i >= argc)
break;
val= atoi(argv[i]);
if (val < 0)
break;
sync();
sync();
fd = open(tmp, O_RDWR);
if (fd < 0)
exit(1);
snprintf(tmp, sizeof(tmp), "%d", val);
write(fd, tmp, strlen(tmp));
close(fd);
setuid(getuid()); // drop all priority asap
exit(0);
} else
if (strcmp(argv[i], "--toshibalcd") == 0 || strcmp(argv[i], "-toshibalcd") == 0) {
i++;
if (i >= argc)
break;
toshibalcd_val= atoi(argv[i]);
if (toshibalcd_val < 0)
toshibalcd_val = 0;
if (toshibalcd_val > 7)
toshibalcd_val = 7;
fd = open("/proc/acpi/TOSHIBA1/lcd", O_RDWR);
if (fd >= 0 ) {
char c;
c = '0'+toshibalcd_val;
write(fd, &c, 1);
close(fd);
} else {
fd = open("/proc/acpi/toshiba/lcd", O_RDWR);
if (fd >= 0) {
char str[MAX_TOSHIBA_STRING];
snprintf(str,sizeof(str),"brightness : %d",toshibalcd_val);
str[sizeof(str)-1]=0;
write(fd,str,strlen(str));
close(fd);
}
}
setuid(getuid()); // drop all priority asap
exit(0);
} else
// CPUFreq support
if (strncmp(argv[i], "--cpufreq", 9) == 0 || strncmp(argv[i], "-cpufreq", 8) == 0) {
if ((i+1) >= argc)
break;
if (strlen(argv[i+1]) > 50 || strchr(argv[i+1], '.'))
break;
int val;
char tmp[256];
// CPUFreq support for the interface of the 2.4 kernell (/proc/sys/cpu/N/)
if (strcmp(argv[i], "--cpufreq-24") == 0 || strcmp(argv[i], "-cpufreq-24") == 0) {
++i;
snprintf(tmp, sizeof(tmp), "/proc/sys/cpu/%s/speed", argv[i]);
tmp[sizeof(tmp)-1] = 0;
++i;
if (i >= argc)
break;
val = atoi(argv[i]);
if (val < 0)
break;
fd = open(tmp, O_WRONLY);
if (fd < 0)
exit(1);
snprintf(tmp, sizeof(tmp), "%d", val);
write(fd, tmp, strlen(tmp));
} else
// CPUFreq support for the interface of the 2.5 kernel (/proc/cpufreq)
if (strcmp(argv[i], "--cpufreq-25") == 0 || strcmp(argv[i], "-cpufreq-25") == 0) {
++i;
snprintf(tmp, sizeof(tmp), "%s", argv[i]);
tmp[sizeof(tmp)-1] = 0;
fd = open("/proc/cpufreq", O_WRONLY);
if (fd < 0)
exit(1);
write(fd, tmp, strlen(tmp));
} else
// CPUFreq support fot the sysfs interface of the 2.5 kernel (/sys/devices/sys/cpuN/cpufreq/)
if (strcmp(argv[i], "--cpufreq-sysfs") == 0 || strcmp(argv[i], "-cpufreq-sysfs") == 0) {
++i;
snprintf(tmp, sizeof(tmp), "/sys/devices/system/cpu/%s/cpufreq/scaling_governor", argv[i]);
tmp[sizeof(tmp)-1] = 0;
++i;
if (i >= argc)
break;
fd = open(tmp, O_WRONLY);
if (fd < 0)
exit(1);
if (strlen(argv[i]) > 50)
break;
snprintf(tmp, sizeof(tmp), "%s", argv[i]);
tmp[sizeof(tmp)-1] = 0;
write(fd, tmp, strlen(tmp));
} else {
break;
}
close(fd);
setuid(getuid()); // drop all priority asap
exit(0);
} else {
usage:
setuid(getuid()); // drop all priority asap
fprintf(stderr, "Usage: %s [--suspend] [--standby] [--hibernate][--software-suspend][--toshibalcd N][--performance CPU N][--throttling CPU N][--cpufreq-[24|25|sysfs]]\n", argv[0]);
exit(1);
}
goto usage;
}