/* * showbatt.c -- print remaining battery life to standart output. * * Copyright (C) 1995 Yasuo Hibara * * adaptation against apm driver 1.2 or later * (C)Copyright 1998 by Hiroshi Takekawa * * This showbatt.c is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This showbatt.c is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this showbatt.c; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include const char sAPM_PROC[] = "/proc/apm"; const char sAPM_BIOS[] = "/dev/apm_bios"; char *name = "showbatt"; int opt_t = 0; /* apm information structure... not same as in apmd's apm.h */ typedef struct _apm_info { int driver_version; int bios_version; int bios_flags; int ac_status; int battery_status; int battery_flags; int percentage; int time; /* minutes ! */ } apm_info; void usage(void) { fprintf(stderr, "%s version 0.01\n", "Usage: %s [ -t ] [ ]\n" " -t: append remaining time of battery life\n" " update status per (default 30)\n", name); exit(EXIT_FAILURE); } int getproc(apm_info *info) { int fd, i, dvh, dvl, abvh, abvl, abf, acs, bs, bf, percent, time; char units[8], image[48]; if ((fd = open(sAPM_PROC, O_RDONLY)) < 0) { fprintf(stderr, "can't open %s\n", sAPM_PROC); exit(EXIT_FAILURE); } if (read(fd, image, 48) < 0) { fprintf(stderr, "can't read %s\n", sAPM_PROC); exit(EXIT_FAILURE); } close(fd); /* driver_version apm_bios_version ac_line_status battery_status batter_flag percentage time units */ i = sscanf(image, "%d.%d %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", &dvh, &dvl, &abvh, &abvl, &abf, &acs, &bs, &bf, &percent, &time, units); if (i < 7) { fprintf(stderr, "can't parse /proc/apm ... maybe older driver?\n"); exit(EXIT_FAILURE); } if (strcmp(units, "seconds") == 0) { info->time = time / 60; } else { info->time = time; } info->driver_version = (dvh << 8) + dvl; info->bios_version = (abvh << 8) + abvl; info->bios_flags = abf; info->ac_status = acs; info->battery_status = bs; info->battery_flags = bf; info->percentage = percent; return i; } void showbatt(void) { char image[32], *p; int percent, minutes, l, i; apm_info info; percent = minutes = -1; p = image; l = getproc(&info); if (info.bios_flags & (1 << 3)) { fprintf(stderr, "APM BIOS disabled\n"); exit(EXIT_FAILURE); } if (info.ac_status & 1) *p++ = '['; else if (info.ac_status & 2) *p++ = '#'; else if (info.ac_status != 0) *p++ = '-'; else if (info.battery_status & 1) *p++ = ')'; else if (info.battery_status & 2) *p++ = '>'; else *p++ = '|'; if (info.percentage >= 0) { sprintf(p, "%3d%% ", info.percentage); p += 4; } else { *p++ = '-'; *p++ = '-'; } if (opt_t) { if (minutes >= 0) sprintf(p, " %1d:%02d", minutes / 60, minutes % 60); else strcpy(p, " -:--"); p += 5; } if (info.battery_flags & 1) *p++ = ']'; else if (info.battery_flags & 2) *p++ = '('; else if (info.battery_flags & 4) *p++ = '<'; else if (info.battery_flags & 8) *p++ = '|'; else *p++ = '-'; strcat(p, "\n"); write(STDOUT_FILENO, image, strlen(image)); } int main(int argc, char **argv) { int timeout = 30; fd_set fds; int fd,n,i; apm_event_t events[32]; char c[1]; struct timeval tv; name = argv[0]; if ( argc > 1 && strcmp(argv[1], "-t") == 0 ) { opt_t = 1; argc--; argv++; } if ( argc > 1 ) { if ( argc > 2 || sscanf(argv[1], "%d%c", &timeout, &c) != 1 || timeout < 0 ) usage(); } if ( (fd = open(sAPM_BIOS, O_RDONLY)) == -1 ) { fprintf(stderr, "can't open %s\n", sAPM_BIOS); exit(EXIT_FAILURE); } for ( ; ; ) { showbatt(); FD_ZERO(&fds); FD_SET(fd, &fds); if ( timeout > 0 ) { tv.tv_sec = timeout; tv.tv_usec = 0; n = select(fd+1, &fds, NULL, NULL, &tv); } else { n = select(fd+1, &fds, NULL, NULL, NULL); } if ( n > 0 ) { n = read(fd, events, sizeof(events))/sizeof(*events); for ( i = 0; i < n; i++ ) { switch ( events[i] ) { case APM_SYS_STANDBY: case APM_USER_STANDBY: ioctl(fd, APM_IOC_STANDBY); break; case APM_SYS_SUSPEND: case APM_USER_SUSPEND: ioctl(fd, APM_IOC_SUSPEND); break; } } } } return EXIT_FAILURE; }