2

I'm writing a mini UNIX shell, which supports the built-in UNIX commands and also some custom ones. I need to check the battery level inside my C-shell code in the style of

if (strcmp("BatteryLevel", commandArgv[0]) == 0) {

                printf("The battery level is ",);
                return 1;
        }  

I've written the chunk of the shell, all the parsing and built-in commands are working. I also know how to check the battery level from terminal(https://askubuntu.com/questions/69556/how-to-check-battery-status-using-terminal), but i can't get my head around how i can do this inside the code. Thanks for any help.

Community
  • 1
  • 1
Umut
  • 409
  • 3
  • 7
  • 20

1 Answers1

4

For 3.4.NN kernels current battery charge level and the maximum it can reach are available in /sys/class/power_supply/BAT* (usually BAT0 as you normally have just one battery) in files charge_now and charge_full. So something along the lines of following should meet your needs.

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <linux/limits.h>
#include <regex.h>

#define _DATADIR "/sys/class/power_supply"

int main(int argc, char **argv) {
  FILE *f_c, *f_f;
  long current, full;
  DIR *d;
  struct dirent *dp;
  char b[PATH_MAX]; 

  if((d = opendir(_DATADIR)) == NULL) {
    fprintf(stderr, "opendir: %s\n", strerror(errno));
    return 3;
  }

  while((dp = readdir(d)) != NULL) {
    snprintf(b, PATH_MAX, "%s/%s", _DATADIR, dp->d_name);

    regex_t regex;
    if(regcomp(&regex, "BAT[[:alnum:]]+", REG_EXTENDED) != 0) {
      fprintf(stderr, "regcomp: %s\n", strerror(errno));
      return 4;
    }
    if(regexec(&regex, b, 0, NULL, 0) == 0) {
      snprintf(b, PATH_MAX, "%s/%s/%s", _DATADIR, dp->d_name, "charge_now");
      f_c = fopen(b, "r");
      snprintf(b, PATH_MAX, "%s/%s/%s", _DATADIR, dp->d_name, "charge_full");
      f_f = fopen(b, "r");
      if(f_c != NULL && f_f != NULL) {
        if(fscanf(f_c, "%ld", &current) != 1 || fscanf(f_f, "%ld", &full) != 1)
          fprintf(stderr, "fscanf: %s\n", strerror(errno));
        else
          fprintf(stdout, "charge for %s %.2f\n", dp->d_name,
                  (current / full) * 100.0);
        fclose(f_c);
        fclose(f_f);
      }
    }
    regfree(&regex);
  }

  return 0;
}