#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #include #include #include // 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; void usage (void) { printf("usage: bmon [-wuh] [-f file] [-t interval]\n" "-w\tDisplay power draw from battery\n" "-u\tPrint seconds as epoch\n" "-h\tPrint this message\n" "-f\tWrite output to file\n" "-t\tSet the update interval in seconds\n"); } void int_handler (int signum) { (void)signum; 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[]) { /* Handle SIGINT */ dead = 0; struct sigaction action; memset(&action, 0, sizeof(action)); action.sa_handler = int_handler; sigaction(SIGINT, &action, NULL); int wflag = 0; int wait_time = 10; int fflag = 0; int uflag = 0; char ofile_path[256]; int opc; while ((opc = getopt(argc, argv, "uhwf:t:")) != -1) { switch (opc) { case 'w': wflag = 1; break; case 'f': fflag = 1; strncpy(ofile_path, optarg, 255); break; case 't': wait_time = atoi(optarg); if (wait_time < 1) { usage(); exit(1); } break; case 'u': uflag = 1; break; case 'h': default: /* '?' */ usage(); exit(1); break; } } FILE *capacity_fp = NULL, *status_fp = NULL, *power_fp = NULL; capacity_fp = fopen(CAPACITY_PATH, "r"); if (capacity_fp == NULL) { fprintf(stderr, "Error opening %s: %s\n", CAPACITY_PATH, strerror(errno)); exit(1); } if (wflag) { power_fp = fopen(POWER_PATH, "r"); if (power_fp == NULL) { fprintf(stderr, "Error opening %s: %s\n", POWER_PATH, strerror(errno)); exit(1); } status_fp = fopen(STATUS_PATH, "r"); if (status_fp == NULL) { fprintf(stderr, "Error opening %s: %s\n", STATUS_PATH, strerror(errno)); exit(1); } } FILE *output_fp = stdout; if (fflag) { if ((output_fp = fopen(ofile_path, "w")) == NULL) { fprintf(stderr, "Error opening %s: %s\n", ofile_path, strerror(errno)); exit(1); } } long int elapsed_time = 0; fprintf(output_fp, "TIME\t"); fprintf(output_fp, "CAP\t"); if (wflag) fprintf(output_fp, "WATTS"); fprintf(output_fp, "\n"); while (!dead) { int capacity = read_int(capacity_fp); float power = 0; if (capacity < 0) { fprintf(stderr, "Error reading capacity: %s\n", strerror(errno)); break; } if (wflag) { power = read_int(power_fp); if (power < 0) { 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; } if (fflag) { fclose(output_fp); } if (capacity_fp) { fclose(capacity_fp); } if (status_fp) { fclose(status_fp); } if (power_fp) { fclose(power_fp); } return 0; }