|
|
@ -1,8 +1,10 @@ |
|
|
|
#define _POSIX_C_SOURCE 200809L |
|
|
|
#define _POSIX_C_SOURCE 200809L |
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
#include <sys/types.h> |
|
|
|
#include <sys/types.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
|
|
#include <stdlib.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <fcntl.h> |
|
|
|
#include <dirent.h> |
|
|
|
#include <dirent.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <errno.h> |
|
|
@ -10,8 +12,12 @@ |
|
|
|
#include <unistd.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <signal.h> |
|
|
|
#include <signal.h> |
|
|
|
#include <time.h> |
|
|
|
#include <time.h> |
|
|
|
|
|
|
|
#include <limits.h> |
|
|
|
|
|
|
|
|
|
|
|
const char *bat_base_path = "/sys/class/power_supply/"; |
|
|
|
// TODO: handle multiple batteries
|
|
|
|
|
|
|
|
const char *CAPACITY_PATH = "/sys/class/power_supply/BAT1/capacity"; |
|
|
|
|
|
|
|
const char *STATUS_PATH = "/sys/class/power_supply/BAT1/status"; |
|
|
|
|
|
|
|
const char *POWER_PATH = "/sys/class/power_supply/BAT1/power_now"; |
|
|
|
int dead = 0; |
|
|
|
int dead = 0; |
|
|
|
|
|
|
|
|
|
|
|
void usage (void) |
|
|
|
void usage (void) |
|
|
@ -26,17 +32,26 @@ void usage (void) |
|
|
|
|
|
|
|
|
|
|
|
void int_handler (int signum) |
|
|
|
void int_handler (int signum) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
(void)signum; |
|
|
|
dead = 1; |
|
|
|
dead = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int read_int (FILE *fp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int x; |
|
|
|
|
|
|
|
freopen(NULL, "r", fp); |
|
|
|
|
|
|
|
fscanf(fp, "%d", &x);
|
|
|
|
|
|
|
|
return x; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int main (int argc, char *argv[]) |
|
|
|
int main (int argc, char *argv[]) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/* Handle SIGINT */ |
|
|
|
/* Handle SIGINT */ |
|
|
|
dead = 0; |
|
|
|
dead = 0; |
|
|
|
struct sigaction action; |
|
|
|
struct sigaction action; |
|
|
|
memset(&action, 0, sizeof(action)); |
|
|
|
memset(&action, 0, sizeof(action)); |
|
|
|
action.sa_handler = int_handler; |
|
|
|
action.sa_handler = int_handler; |
|
|
|
sigaction(SIGINT, &action, NULL); |
|
|
|
sigaction(SIGINT, &action, NULL); |
|
|
|
|
|
|
|
|
|
|
|
int wflag = 0; |
|
|
|
int wflag = 0; |
|
|
|
int wait_time = 10; |
|
|
|
int wait_time = 10; |
|
|
@ -73,100 +88,87 @@ int main (int argc, char *argv[]) |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DIR *bdir = NULL; |
|
|
|
FILE *capacity_fp = NULL, *status_fp = NULL, *power_fp = NULL; |
|
|
|
if (!(bdir = opendir(bat_base_path))) { |
|
|
|
capacity_fp = fopen(CAPACITY_PATH, "r"); |
|
|
|
perror("error opening base directory"); |
|
|
|
if (capacity_fp == NULL) { |
|
|
|
|
|
|
|
fprintf(stderr, "Error opening %s: %s\n", CAPACITY_PATH, strerror(errno)); |
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct dirent *ent = NULL; |
|
|
|
if (wflag) { |
|
|
|
FILE **fp_list = NULL; |
|
|
|
power_fp = fopen(POWER_PATH, "r"); |
|
|
|
int fp_num = 0; |
|
|
|
if (power_fp == NULL) { |
|
|
|
for (;;) { |
|
|
|
fprintf(stderr, "Error opening %s: %s\n", POWER_PATH, strerror(errno)); |
|
|
|
errno = 0; |
|
|
|
exit(1); |
|
|
|
if (!(ent = readdir(bdir))) { |
|
|
|
} |
|
|
|
if (errno) { |
|
|
|
status_fp = fopen(STATUS_PATH, "r"); |
|
|
|
perror("error reading base directory"); |
|
|
|
if (status_fp == NULL) { |
|
|
|
exit(1); |
|
|
|
fprintf(stderr, "Error opening %s: %s\n", STATUS_PATH, strerror(errno)); |
|
|
|
} |
|
|
|
exit(1); |
|
|
|
else break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!strstr(ent->d_name, "BAT1")) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FILE *fp; |
|
|
|
|
|
|
|
char path[sizeof(bat_base_path) + 256 + 64]; |
|
|
|
|
|
|
|
strcpy(path, bat_base_path); |
|
|
|
|
|
|
|
strcat(path, ent->d_name); |
|
|
|
|
|
|
|
if (wflag) { |
|
|
|
|
|
|
|
char *tmp = malloc(1024); |
|
|
|
|
|
|
|
strcpy(tmp, path); |
|
|
|
|
|
|
|
strcat(tmp, "/status"); |
|
|
|
|
|
|
|
FILE *tmf = fopen(tmp, "r"); |
|
|
|
|
|
|
|
fgets(tmp, 1024, tmf); |
|
|
|
|
|
|
|
if (!strstr(tmp, "Dis")) { |
|
|
|
|
|
|
|
fprintf(stderr, "currently not discharging, cannot read power draw\n"); |
|
|
|
|
|
|
|
dead = 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
fclose(tmf); |
|
|
|
|
|
|
|
free(tmp); |
|
|
|
|
|
|
|
strcat(path, "/power_now"); |
|
|
|
|
|
|
|
} else strcat(path, "/capacity"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((fp = fopen(path, "r"))) { |
|
|
|
|
|
|
|
FILE **tmp = NULL; |
|
|
|
|
|
|
|
tmp = realloc(fp_list, sizeof(FILE *) * (fp_num + 1)); |
|
|
|
|
|
|
|
if (!tmp) |
|
|
|
|
|
|
|
perror("failed realloc"); |
|
|
|
|
|
|
|
fp_list = tmp; |
|
|
|
|
|
|
|
fp_list[fp_num++] = fp; |
|
|
|
|
|
|
|
} else printf("err: %s\n", strerror(errno)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
closedir(bdir); |
|
|
|
|
|
|
|
if (!fp_num) { |
|
|
|
|
|
|
|
printf("no files were opened\n"); |
|
|
|
|
|
|
|
dead = 1; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
FILE * ofile_ptr = stdout; |
|
|
|
|
|
|
|
|
|
|
|
FILE *output_fp = stdout; |
|
|
|
if (fflag) { |
|
|
|
if (fflag) { |
|
|
|
if (!(ofile_ptr = fopen(ofile_path, "w"))) { |
|
|
|
if ((output_fp = fopen(ofile_path, "w")) == NULL) { |
|
|
|
char *tmp = malloc(1024); |
|
|
|
fprintf(stderr, "Error opening %s: %s\n", ofile_path, strerror(errno)); |
|
|
|
snprintf(tmp, 1024, "could not open %s", ofile_path); |
|
|
|
|
|
|
|
perror(tmp); |
|
|
|
|
|
|
|
free(tmp); |
|
|
|
|
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
long int elapsed_time = 0; |
|
|
|
long int elapsed_time = 0; |
|
|
|
long val; |
|
|
|
fprintf(output_fp, "TIME\t"); |
|
|
|
char buf[64]; |
|
|
|
fprintf(output_fp, "CAP\t"); |
|
|
|
for (; !dead ; sleep(wait_time)) { |
|
|
|
if (wflag) fprintf(output_fp, "WATTS"); |
|
|
|
for (int i = 0; i < fp_num; i++) { |
|
|
|
fprintf(output_fp, "\n"); |
|
|
|
if (!freopen(NULL, "r", fp_list[i])) { |
|
|
|
while (!dead) { |
|
|
|
perror("error reading the file"); |
|
|
|
int capacity = read_int(capacity_fp); |
|
|
|
dead = 1; |
|
|
|
float power = 0; |
|
|
|
} |
|
|
|
if (capacity < 0) { |
|
|
|
if (!fgets(buf, 64, fp_list[i])) |
|
|
|
fprintf(stderr, "Error reading capacity: %s\n", strerror(errno)); |
|
|
|
dead = 1; |
|
|
|
break; |
|
|
|
val = atol(buf); |
|
|
|
|
|
|
|
fprintf(ofile_ptr, "%ld\t", wflag ? (long)(val / 1E3) : val); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
fprintf(ofile_ptr, "%ld\n", uflag ? time(NULL) : elapsed_time); |
|
|
|
if (wflag) { |
|
|
|
if (fflush(ofile_ptr)) { |
|
|
|
power = read_int(power_fp); |
|
|
|
perror("error writing to file"); |
|
|
|
if (power < 0) { |
|
|
|
dead = 1; |
|
|
|
fprintf(stderr, "Error reading power: %s\n", strerror(errno)); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
static char b[128] = {0}; |
|
|
|
|
|
|
|
freopen(NULL, "r", status_fp); |
|
|
|
|
|
|
|
if (fgets(b, sizeof(b), status_fp) == NULL) { |
|
|
|
|
|
|
|
fprintf(stderr, "Error reading status: %s\n", strerror(errno)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (strncmp(b, "Discharging\n", sizeof(b)) == 0) { |
|
|
|
|
|
|
|
power *= -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// power is in microwatts
|
|
|
|
|
|
|
|
power /= 1e6; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fprintf(output_fp, "%ld\t", uflag ? time(NULL) : elapsed_time); |
|
|
|
|
|
|
|
fprintf(output_fp, "%d\t", capacity); |
|
|
|
|
|
|
|
if (wflag) fprintf(output_fp, "%.2f", power); |
|
|
|
|
|
|
|
fprintf(output_fp, "\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sleep(wait_time); |
|
|
|
elapsed_time += wait_time; |
|
|
|
elapsed_time += wait_time; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fflag) |
|
|
|
if (fflag) { |
|
|
|
fclose(ofile_ptr); |
|
|
|
fclose(output_fp); |
|
|
|
for (int i = 0; i < fp_num; i++) |
|
|
|
} |
|
|
|
fclose(fp_list[i]); |
|
|
|
if (capacity_fp) { |
|
|
|
free(fp_list); |
|
|
|
fclose(capacity_fp); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (status_fp) { |
|
|
|
|
|
|
|
fclose(status_fp); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (power_fp) { |
|
|
|
|
|
|
|
fclose(power_fp); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|