21625f40b5
I tried to get the latest versions from dockapps.org, but I haven't tested any of them. More dockapps will be added as time permits.
318 lines
6.4 KiB
C
318 lines
6.4 KiB
C
/*
|
|
* Copyright (c) 2007 Daniel Borca All rights reserved.
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
|
|
#include <dirent.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../list.h"
|
|
#include "../sensors.h"
|
|
|
|
|
|
static int
|
|
spawn_sync_read (const char *filename, const char *const argv[], int max, char *out)
|
|
{
|
|
#define READ 0
|
|
#define WRITE 1
|
|
pid_t pid;
|
|
int fd[2];
|
|
int status;
|
|
|
|
int size;
|
|
int eof;
|
|
|
|
if (pipe(fd) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
pid = fork();
|
|
if (pid == -1) {
|
|
return -1;
|
|
}
|
|
if (pid == 0) {
|
|
close(fd[READ]);
|
|
close(STDERR_FILENO);
|
|
dup2(fd[WRITE], STDOUT_FILENO);
|
|
|
|
exit(execvp(filename, (char *const *)argv));
|
|
}
|
|
|
|
close(fd[WRITE]);
|
|
|
|
for (--max, size = 0, eof = 0; !eof;) {
|
|
char buf[512];
|
|
int chunk = read(fd[READ], buf, sizeof(buf));
|
|
if (chunk < 0) {
|
|
break;
|
|
}
|
|
eof = (chunk < (int)sizeof(buf));
|
|
if (size + chunk > max) {
|
|
chunk = max - size;
|
|
}
|
|
memcpy(&out[size], buf, chunk);
|
|
size += chunk;
|
|
}
|
|
out[size] = '\0';
|
|
|
|
close(fd[READ]);
|
|
|
|
wait(&status);
|
|
|
|
return size;
|
|
#undef WRITE
|
|
#undef READ
|
|
}
|
|
|
|
|
|
int
|
|
sensors_nvidia (const char *setting, int *val)
|
|
{
|
|
const char *argv[] = { "nvidia-settings", "-q" , NULL, NULL };
|
|
char out[BUFSIZ];
|
|
int dummy;
|
|
|
|
argv[2] = (char *)setting;
|
|
|
|
if (val == NULL) {
|
|
val = &dummy;
|
|
}
|
|
|
|
if (spawn_sync_read(argv[0], argv, sizeof(out), out) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (sscanf(out, " Attribute %*s %*s %d", val) != 1) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
sensors_read_line (const char *filename, int max, char *out)
|
|
{
|
|
char *p;
|
|
FILE *f;
|
|
f = fopen(filename, "rt");
|
|
if (f == NULL) {
|
|
return -1;
|
|
}
|
|
if (fgets(out, max, f) == NULL) {
|
|
fclose(f);
|
|
return -1;
|
|
}
|
|
fclose(f);
|
|
p = strchr(out, '\n');
|
|
if (p != NULL) {
|
|
*p = '\0';
|
|
return p - out;
|
|
}
|
|
return strlen(out);
|
|
}
|
|
|
|
|
|
static int
|
|
add_sensor (SENSOR *list, const char *filename, const char *name, SENSOR_TYPE type)
|
|
{
|
|
SENSOR *s;
|
|
char *p, buf[256];
|
|
|
|
s = malloc(sizeof(SENSOR));
|
|
if (s == NULL) {
|
|
return -1;
|
|
}
|
|
s->type = type;
|
|
s->idata = 0;
|
|
|
|
switch (type) {
|
|
case S_ACPI_THERMAL_ZONE:
|
|
p = malloc(strlen(filename) + 32);
|
|
if (p == NULL) {
|
|
break;
|
|
}
|
|
strcat(strcpy(p, filename), "/trip_points");
|
|
s->idata = 100;
|
|
if (sensors_read_line(p, sizeof(buf), buf) > 0) {
|
|
sscanf(buf, "%*s %*s %d", &s->idata);
|
|
}
|
|
s->filename = strcat(strcpy(p, filename), "/temperature");
|
|
s->name = strdup(name);
|
|
if (s->name == NULL) {
|
|
free(p);
|
|
break;
|
|
}
|
|
list_append(list, s);
|
|
return 0;
|
|
case S_ACPI_AC_ADAPTER:
|
|
p = malloc(strlen(filename) + 32);
|
|
if (p == NULL) {
|
|
break;
|
|
}
|
|
s->filename = strcat(strcpy(p, filename), "/state");
|
|
s->name = strdup(name);
|
|
if (s->name == NULL) {
|
|
free(p);
|
|
break;
|
|
}
|
|
list_append(list, s);
|
|
return 0;
|
|
case S_ACPI_BATTERY:
|
|
p = malloc(strlen(filename) + 32);
|
|
if (p == NULL) {
|
|
break;
|
|
}
|
|
s->filename = strcat(strcpy(p, filename), "/");
|
|
s->name = strdup(name);
|
|
if (s->name == NULL) {
|
|
free(p);
|
|
break;
|
|
}
|
|
list_append(list, s);
|
|
return 0;
|
|
case S_HWMON_CORETEMP:
|
|
p = malloc(strlen(filename) + 32);
|
|
if (p == NULL) {
|
|
break;
|
|
}
|
|
strcat(strcpy(p, filename), "/device/name");
|
|
if (sensors_read_line(p, sizeof(buf), buf) <= 0) {
|
|
free(p);
|
|
break;
|
|
}
|
|
if (strcmp(buf, "coretemp")) {
|
|
free(p);
|
|
break;
|
|
}
|
|
strcat(strcpy(p, filename), "/device/temp1_crit");
|
|
s->idata = 100;
|
|
if (sensors_read_line(p, sizeof(buf), buf) > 0) {
|
|
sscanf(buf, "%d", &s->idata);
|
|
}
|
|
strcat(strcpy(p, filename), "/device/temp1_label");
|
|
if (sensors_read_line(p, sizeof(buf), buf) > 0) {
|
|
s->name = strdup(buf);
|
|
} else {
|
|
s->name = strdup(name);
|
|
}
|
|
s->filename = strcat(strcpy(p, filename), "/device/temp1_input");
|
|
if (s->name == NULL) {
|
|
free(s->filename);
|
|
break;
|
|
}
|
|
list_append(list, s);
|
|
return 0;
|
|
case S_NVIDIA_SETTINGS_GPUCORETEMP:
|
|
if (sensors_nvidia(name, NULL) != 0) {
|
|
break;
|
|
}
|
|
p = strdup(filename);
|
|
if (p == NULL) {
|
|
break;
|
|
}
|
|
s->filename = p;
|
|
s->name = strdup(name);
|
|
if (s->name == NULL) {
|
|
free(p);
|
|
break;
|
|
}
|
|
list_append(list, s);
|
|
return 0;
|
|
}
|
|
|
|
free(s);
|
|
return -1;
|
|
}
|
|
|
|
|
|
static void
|
|
scan_dirs (const char *dirname, SENSOR *list, SENSOR_TYPE type)
|
|
{
|
|
DIR *dir;
|
|
int len = strlen(dirname);
|
|
|
|
dir = opendir(dirname);
|
|
if (dir != NULL) {
|
|
struct dirent *ent;
|
|
while ((ent = readdir(dir))) {
|
|
if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) {
|
|
char *fullname = malloc(len + 1 + strlen(ent->d_name) + 1);
|
|
if (fullname != NULL) {
|
|
struct stat buf;
|
|
int l = len;
|
|
strcpy(fullname, dirname);
|
|
if (fullname[l - 1] != '/') {
|
|
fullname[l++] = '/';
|
|
}
|
|
strcpy(&fullname[l], ent->d_name);
|
|
/* don't use d_type */
|
|
if (stat(fullname, &buf) == 0 && S_ISDIR(buf.st_mode)) {
|
|
add_sensor(list, fullname, ent->d_name, type);
|
|
}
|
|
free(fullname);
|
|
}
|
|
}
|
|
}
|
|
closedir(dir);
|
|
}
|
|
}
|
|
|
|
|
|
SENSOR *
|
|
sensors_init (void)
|
|
{
|
|
SENSOR *list;
|
|
|
|
list = malloc(sizeof(SENSOR));
|
|
if (list == NULL) {
|
|
return NULL;
|
|
}
|
|
list->type = -1;
|
|
|
|
list_create(list);
|
|
|
|
scan_dirs("/proc/acpi/thermal_zone", list, S_ACPI_THERMAL_ZONE);
|
|
scan_dirs("/proc/acpi/ac_adapter", list, S_ACPI_AC_ADAPTER);
|
|
scan_dirs("/proc/acpi/battery", list, S_ACPI_BATTERY);
|
|
scan_dirs("/sys/class/hwmon", list, S_HWMON_CORETEMP);
|
|
add_sensor(list, "nvidia-settings", "GPUCoreTemp", S_NVIDIA_SETTINGS_GPUCORETEMP);
|
|
|
|
return list;
|
|
}
|
|
|
|
|
|
void
|
|
sensors_free (SENSOR *list)
|
|
{
|
|
SENSOR *s, *tmp;
|
|
|
|
list_foreach_s (s, tmp, list) {
|
|
list_remove(s);
|
|
free(s->filename);
|
|
free((char *)s->name);
|
|
free(s);
|
|
}
|
|
|
|
free(list);
|
|
}
|