battery_log/sources/main/battery.c
Sandy Mossgrave 15a20da1aa Quicksaving before I add the -f option.
Added ability to log the battery level continuously.
Added compile-time option #define USE_LIBNOTIFY to post a low-battery warning with libnotify.
2023-06-06 15:05:52 +00:00

219 lines
4.8 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#ifdef USE_SYSLOG
#include <syslog.h>
#endif
#include "main.h"
#ifdef USE_LIBNOTIFY
#include <libnotify/notify.h>
#endif
int run_verbose = 0;
int run_terse = 0;
int run_continuously = 0;
int interval = DEFAULT_LOG_INTERVAL;
int run_unsafe = 0;
int force_print_parameters = 0;
int warn_level = 10;
int warned = 0; /* Set if already warned */
const char * delimiter = "\n";
void print_help(void){
printf("%s %s\n", TITLE, VERSION);
printf("%s %s %s\n", USAGE0, PROGNAME, USAGE1);
printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
OPTIONS0, OPTIONS1, OPTIONS2, OPTIONS3, OPTIONS4,
OPTIONS5, OPTIONS6, OPTIONS7, OPTIONS8, OPTIONS9,
OPTIONS10);
}
int get_percentage
(FILE * fd_now, FILE * fd_full, int * c_now, int * c_full, float * frac, int *pct)
{
int vals_read = fscanf(fd_now, "%d", c_now);
if(vals_read != 1){
if(errno != 0){
perror("Error reading full battery charge: ");
} else if(vals_read == EOF){
printf("End-of-file reached while reading current battery charge(?)");
} else {
printf("Invalid number of arguments (%d) returned while reading full battery charge", vals_read);
}
return 1;
}
vals_read = fscanf(fd_full, "%d", c_full);
if(vals_read != 1){
if(errno != 0){
perror("Error reading full battery charge: ");
} else if(vals_read == EOF){
printf("End-of-file reached while reading full battery charge(?)");
} else {
printf("Invalid number of arguments (%d) returned while reading full battery charge", vals_read);
}
return 1;
}
(*frac) = ((float)(*c_now)) / ((float)(*c_full));
(*pct) = (int)((*frac) * 100);
return 0;
}
void warn(int pct){
if(!warned){
printf("Battery Low\n");
#ifdef USE_SYSLOG
syslog(LOG_WARNING, "Battery Low");
#endif
#ifdef USE_LIBNOTIFY
char warnmesg[MESGLEN];
snprintf(warnmesg, MESGLEN, "Battery is at %d percent", pct);
notify_init(PROGNAME);
NotifyNotification * levelwarn = notify_notification_new("Battery Low", warnmesg, "dialog-information");
notify_notification_show(levelwarn, NULL);
g_object_unref(G_OBJECT(levelwarn));
notify_uninit();
#endif
}
warned = 1;
}
int main(int argc, char *const argv[]){
int opt;
while((opt = getopt(argc, argv, "vhtli:uw:p")) != -1) {
switch(opt){
case 'v':
run_verbose = 1;
break;
case 'h':
print_help();
return 0;
case 't':
run_terse = 1;
break;
case 'l':
run_continuously = 1;
break;
case 'i':
interval = atoi(optarg);
run_continuously = 1;
break;
case 'u':
run_unsafe = 1;
break;
case 'w':
warn_level = atoi(optarg);
break;
case 'p':
force_print_parameters = 1;
break;
default:
printf("Literally how could you pass an unspecified argument to this program");
}
}
/**
Print run parameters at startup
*/
if(force_print_parameters) {
if(run_terse && run_verbose){
printf(PROGNAME " called with arguments to run both tersely and verbosely, the author legitimately cannot tell what you want her to do\n");
} else if(run_terse) {
printf(PROGNAME " will run tersely\n");
} else if(run_verbose) {
printf(PROGNAME " will run verbosely\n");
}
printf(PROGNAME " will poll every %d seconds\n", interval);
if(!run_terse){
printf(PROGNAME " will warn at %d%% battery\n", warn_level);
}
}
if(warn_level <= 0 && !run_terse){
fprintf(stderr, "Warn level set to %d. " PROGNAME " will not send warning on low battery.\n", warn_level);
}
if(interval < 15 && !run_unsafe){
fprintf(stderr, "Update interval less than 15 seconds, refusing to run. Specify -u to override this check.\n");
return 1;
}
#ifdef USE_SYSLOG
openlog(PROGNAME, 0, LOG_USER);
#endif
FILE * fd_now = fopen(CHARGE_NOW_PATH, "r");
FILE * fd_full = fopen(CHARGE_FULL_PATH, "r");
int c_now;
int c_full;
float frac;
int pct;
do{
int rval = get_percentage(fd_now, fd_full, &c_now, &c_full, &frac, &pct);
if (rval){
printf("Um, problem\n");
return 1;
}
if(run_verbose){
printf("Current charge: %d\n microampere-hours\n", c_now);
printf("Full charge: %d\n microampere-hours\n", c_full);
}
if(!run_terse) {
printf("Battery percentage: ");
}
if(pct > warn_level){
warned = 0;
}
if(pct <= warn_level && !warned){
warn(pct);
}
printf("%d%s", pct, delimiter);
#ifdef USE_SYSLOG
syslog(LOG_INFO, "%d%%%s", pct, delimiter);
#endif
if(run_continuously){
sleep(interval);/*
errno = 0;
rewind(fd_now);
if(errno != 0){
perror("Error rewinding " CHARGE_NOW_PATH);
return 1;
}
rewind(fd_full); //just for the hecc of it
if(errno != 0){
perror("Error rewinding " CHARGE_FULL_PATH);
return 1;
}*/
fclose(fd_now);
fclose(fd_full);
fd_now = fopen(CHARGE_NOW_PATH, "r");
fd_full = fopen(CHARGE_FULL_PATH, "r");
}
} while (run_continuously);
#ifdef USE_SYSLOG
closelog();
#endif
return 0;
}