#include #include #include #include #ifdef USE_SYSLOG #include #endif #include "main.h" #ifdef USE_LIBNOTIFY #include #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_fds(FILE ** fd_now, FILE ** fd_full, const char * bat_path, const char * unit_now, const char * unit_full) { size_t bat_path_len = strlen(bat_path); size_t unit_now_len = strlen(unit_now); size_t unit_full_len = strlen(unit_full); char * now_path = (char*)malloc(bat_path_len + unit_now_len + 1); char * full_path = (char*)malloc(bat_path_len + unit_full_len + 1); strncpy(now_path, bat_path, bat_path_len + 1); strncpy(full_path, bat_path, bat_path_len + 1); strncat(now_path, unit_now, unit_now_len); strncat(full_path, unit_full, unit_full_len); printf("Attempting to open:\n\t%s\n\t%s\n", now_path, full_path); (*fd_now) = fopen(now_path, "r"); if(*fd_now == NULL){ perror("Error opening file for current charge level"); // if exiting here, no need to close fd_now because it is null return 1; } (*fd_full) = fopen(full_path, "r"); if(*fd_full == NULL){ perror("Error opening file for maximum charge level"); // it just makes me feel safer, but this should be redundant if((*fd_now) != NULL){ fclose(*fd_now); } return 1; } printf("Successfully found files at %p and %p\n", (void*)fd_now, (void*)fd_full); return 0; } int get_percentage (FILE * fd_now, FILE * fd_full, double * c_now, double * c_full, double * frac, int *pct) { int vals_read = fscanf(fd_now, "%lf", 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, "%lf", 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) = *c_now / *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; FILE * fd_full; if(get_fds(&fd_now, &fd_full, BAT_PATH, CHARGE_NOW_PATH, CHARGE_FULL_PATH)){ printf("Charge unavailable, attempting to use energy\n"); if(get_fds(&fd_now, &fd_full, BAT_PATH, ENERGY_NOW_PATH, ENERGY_FULL_PATH)){ printf("Could not find a charge unit that works.\n"); exit(1); } else { printf("Unit is energy"); } } fflush(stdout); double c_now; double c_full; double 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: %lf\n microampere-hours\n", c_now); printf("Full charge: %lf\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; }