/*****************************************************************************
* Ledsm 1.13 (c)1999 Juan José Álvarez Martinez
*
* enhanced by Tino Schwarze
* - let the user select whether to cound nice load or not
* (useful for distributed.net clients and similar background tasks)
* - support displaying 6 levels with 3 LEDs (blink LED for intermediate values)
* - support daemon mode (open /dev/console, fork to background)
*
*
* This program is distributed under the terms of the GPL license in his
* version 2 o later
* **************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define VERSION "d19"
#define PIDFNAME ".ledmpidf"
#define NUM 2
#define CAPS 4
#define SCROLL 1
#define TIME_DEF 100000 // Default time between execs
/* scroll = xx1;
num = x1x;
caps = 1xx;*/
static struct passwd *userstruct;
static char *homedir = "";
static int upp;
static char pidfilename[40] = "";
static int consider_nice = 1;
static int console_handle = 0;
float get_cpu(void);
float get_mem(void);
void die(void);
void usage(void);
void version(void);
/*****************************************************************************/
void usage(void){
printf("-c CPU Load\n\
-m Free memory\n\
-k Kid mode\n\
-s[seconds] Seconds between updates\n\
-M[miliseconds] Miliseconds between updates\n\
-v Prints version\n\
-d kills currently running daemon\n\
-D daemon mode (fork, open /dev/console)\n\
-n do not count niced load\n\
-h This help");
version();
}
/*****************************************************************************/
void version(void){
char *ver=VERSION;
printf("Leds Monitor Version %s\n",ver);
die();
}
/*****************************************************************************/
inline char getleds(void){ // Returns in a char the leds turned on
char var;
ioctl(console_handle,KDGETLED,&var);
return var;
}
inline void setleds(char luces){ // Turn on the leds specified by the luces byte
ioctl(console_handle,KDSETLED,luces);
}
void restore_leds(void){
char var;
if (ioctl(console_handle,KDSETLED,&var)){
perror("KDSETLED");
fprintf(stderr, "Error reseting ledmode\n");
exit(1);
}
}
/******************************************************************************/
char kid(char status){ // Stupid&Nice thing...
switch(status){
case 1: //continue
case 3:
case 4:
case 5: fprintf(stderr,
"Error 01: Anormal value for -k\n");
exit(1);
case 0:
setleds(NUM);
upp = 1;
status = 2;
break;
case 2:
if (upp) {
setleds(NUM|CAPS);
status = 6;
}
else {
setleds(0);
status = 0;
}
break;
case 6:
if (upp) {
setleds(NUM|CAPS|SCROLL);
status = 7;
}
else {
setleds(NUM);
status = 2;
}
break;
case 7: if (upp) {
setleds(NUM|CAPS);
status = 6;
upp = 0;
}
else {
printf("Error 02: In -k case 7\n");
exit(1);
}
break;
default:
printf("Error 03: In -k\n");
exit(1);
}
return status;
}
/************************************************************************/
void carga_de_cpu(void){
static int blinkflag = 0;
static int last_sw = -1;
float carga;
int sw, blinkmask;
carga = get_cpu();
blinkmask = 0;
if ( ( carga >= 0 ) && ( carga <= 0.25 ) ) {
sw = 0;
if (carga >= 0.125) blinkmask = NUM;
}
else if ( ( carga > 0.25 ) && ( carga <= 0.50 ) ) {
sw = NUM;
if (carga >= 0.375) blinkmask = CAPS;
}
else if ( ( carga > 0.50 ) && ( carga <= 0.75 ) ) {
sw = NUM|CAPS;
if (carga >= 0.625) blinkmask = SCROLL;
}
else if ( carga > 0.75 ) sw = NUM|CAPS|SCROLL;
else {
printf("Error 04: In cpu_load\n");
exit(1);
}
/* care for fast load changes */
if (sw != last_sw)
blinkmask = 0;
last_sw = sw;
/* toggle blinkflag each time */
blinkflag = (blinkflag) ? 0 : 7;
setleds (sw | (blinkflag & blinkmask));
return;
}
/******************************************************************************/
float get_cpu (void){
FILE *datos;
char buffer[256];
char tokens[4] = " \t\n"; // I'll never forget that whitespace before // the \t...
static long last_user = 0;
static long last_nice = 0;
static long last_sys = 0;
static long last_idle = 0;
long user, nice, sys, idle, total;
long d_user, d_nice, d_sys, d_idle;
float cpu_use;
user = nice = sys = idle = total = 0;
if ( (datos = fopen("/proc/stat", "r")) == NULL) {
return(0);
}
while ( fgets(buffer,256,datos) ) {
if ( strstr(buffer,"cpu") != NULL ){
strtok(buffer,tokens);
user = atol(strtok(NULL,tokens));
nice = atol(strtok(NULL,tokens));
sys = atol(strtok(NULL,tokens));
idle = atol(strtok(NULL,tokens));
}
}
fclose(datos);
d_user = user - last_user;
d_nice = nice - last_nice;
d_sys = sys - last_sys;
d_idle = idle - last_idle;
last_user = user;
last_nice = nice;
last_sys = sys;
last_idle = idle;
total = d_user + d_nice + d_sys + d_idle;
if (total < 1)
total = 1.0;
if (consider_nice)
{
cpu_use = 1.0 - ( (float) d_idle / (float) total );
}
else
{
cpu_use = (float) (d_user + d_sys) / (float) total;
}
return(cpu_use);
}
/******************************************************************************/
float get_mem(void){
FILE *datosmem;
char buffer[256];
char tokens[4] = " \t\n";
long total,libre,buffers,cached,total_libre;
float porcentaje;
if ( (datosmem = fopen("/proc/meminfo","r") ) == NULL) {
perror("Error 06:Opening /proc/meminfo\n");
return 0;
}
fgets(buffer,256,datosmem);
fgets(buffer,256,datosmem);
strtok(buffer,tokens);
total = atol(strtok(NULL,tokens) );
strtok(NULL,tokens); /* used */
libre = atol(strtok(NULL,tokens) );
strtok(NULL,tokens); /* shared */
buffers = atol( strtok(NULL,tokens) );
cached = atol( strtok(NULL,tokens) );
fclose(datosmem); // I will never forget this fclose...
total_libre = libre + cached + buffers;
porcentaje = (float)total_libre / (float) total;
return porcentaje;
}
void carga_de_mem(void){
static int blinkflag = 0;
static int last_sw = -1;
float carga;
int sw, blinkmask;
carga = get_mem();
blinkmask = 0;
if ( ( carga >= 0 ) && ( carga <= 0.25 ) ) {
sw = 0;
if (carga >= 0.125) blinkmask = NUM;
}
else if ( ( carga > 0.25 ) && ( carga <= 0.50 ) ) {
sw = NUM;
if (carga >= 0.375) blinkmask = CAPS;
}
else if ( ( carga > 0.50 ) && ( carga <= 0.75 ) ) {
sw = NUM|CAPS;
if (carga >= 0.625) blinkmask = SCROLL;
}
else if ( carga > 0.75 ) sw = NUM|CAPS|SCROLL;
else {
printf("Error 07:In mem_load\n");
printf("load: %f sw:%d\n",carga,sw);
exit(1);
}
if (sw != last_sw)
blinkmask = 0;
last_sw = sw;
/* toggle blinkflag each time */
blinkflag = (blinkflag) ? 0 : 7;
setleds (sw | (blinkflag & blinkmask));
return;
}
/*****************************************************************************/
/* If we do a Ctrl-C or a civilizated kill ... */
void die(){
restore_leds();
exit(0);
}
/*****************************************************************************/
void kill_other(){
FILE *pidfile;
char *pidstring;
pid_t otherpid;
char *errorf;
pidfile = fopen(pidfilename, "r"); /**/
if (pidfile == NULL){
fprintf(stderr, "Error opening pidfile, sure is an ledm running?\n");
exit(1);
}
else{
pidstring = (char *)malloc( (sizeof(char)) * 10);
errorf = fgets(pidstring, 10,pidfile);
if (errorf == NULL){
fprintf(stderr, "Error reading pidfile\n");
die();
}
else{
otherpid = atoi(pidstring);
kill(otherpid, SIGTERM);
die();
}
}
}
/*****************************************************************************/
void create_pidf(){
pid_t mipid;
FILE *pidfile;
mipid = getpid();
pidfile = fopen(pidfilename,"r"); /**/
if (pidfile != NULL){
fprintf(stderr, "\nFile %s already exist, delete it manually",pidfilename);
fprintf(stderr, " or kill the previous process with ledm -d \n");
fclose(pidfile);
die();
}
else{
pidfile = fopen(pidfilename,"w"); /**/
if (pidfile == NULL){
perror("Error opening pidfile\n");
die();
}
fprintf(pidfile, "%ld\n",(long)mipid);
fclose(pidfile);
}
}
/*****************************************************************************/
void delete_pidf(){
int err;
err = unlink(pidfilename); /**/
if (err){
fprintf(stderr, "Error in delete pidf\n");
die();
}
else if (!err)
die();
}
/********************************************************************/
int main(int argc, char **argv){
//struct led *lp;
char status,car;
char *tpo;
long tponum;
int opck,opcm,opccpu,opct,tiempo,tiemposec; //time in microseconds
int inicio=1;
int opdaemon = 0;
opck=opcm=opccpu=opct=0;
tiempo = TIME_DEF;
tiemposec = 0;
userstruct = getpwuid( getuid() );
if (!userstruct){
fprintf(stderr, "Error getting user information\n");
exit(1);
}
homedir = malloc( sizeof ( userstruct -> pw_dir ) + sizeof(char) );
strcpy(homedir, userstruct -> pw_dir);
strcat(homedir, "/");
strcat(pidfilename,homedir);
strcat(pidfilename,PIDFNAME);
/* Parameters:
* -d : Close the previously opened program
* -k : Stupid && Nice
* -m : Free memory
* -n : Consider nice value for load
* -c : CPU load
* -snumero : Time between in seconds
* -Mnumero : Time between in microseconds */
while (argc > 1){
if (!strcmp("-h", argv[1]))
usage();
if (!strcmp("-v", argv[1]))
version();
if (!strcmp("-d", argv[1]))
kill_other();
if (!strcmp("-k", argv[1]))
opck = 1;
if (!strcmp("-n", argv[1]))
consider_nice = 0;
else if (!strcmp("-r", argv[1])){
setleds(0);
exit(0);
}
else if (!strcmp("-m", argv[1]))
opcm = 1;
else if (!strcmp("-c",argv[1]))
opccpu = 1;
else if (!strcmp("-D",argv[1]))
opdaemon = 1;
else if ( (strlen(argv[1]) >=2) && ( ( ( car = argv[1][1] ) == 's') || (car == 'M') ) ) {
car = argv[1][1];
if ( car == 's' ){
tpo = (char *)malloc( strlen(argv[1]-2 ) * sizeof(char));
tpo = strtok(argv[1],"-s");
if (tpo == NULL){
printf("You must specify a time");
printf("(in seconds) after the -s\n");
exit(1);
}
else{
tponum = atol(tpo);
if (tponum == 0){
fprintf(stderr,"Invalid time value\n");
exit(1);
}
else
tiemposec = tponum;
}
}
else if ( car == 'M' ){
tpo = (char *)malloc( strlen(argv[1]-2 ) * sizeof(char));
tpo = strtok(argv[1],"-M");
if (tpo == NULL){
printf("You must specify a time ");
printf("(in miliseconds) after the -M\n");
exit(1);
}
else{
tponum = atol(tpo);
if (tponum == 0){
fprintf(stderr,"Invalid time\n");
exit(1);
}
else
tiempo = tponum*1000;
}
}
}
else
break;
argc--;
argv++;
}
if ( !(opck + opccpu + opcm) ){
fprintf(stderr, "\nError in arguments: You must select one in");
fprintf(stderr, " -kcm\n");
usage();
}
else if ( (opck + opccpu + opcm) > 1 ){
fprintf(stderr, "Error in arguments: You must select ONLY one in");
fprintf(stderr, " -kcm\n");
usage();
}
if (opdaemon)
{
console_handle = open ("/dev/console", 0);
if (fork() > 0) exit(0);
// be a nice little daemon
close (0);
close (1);
close (2);
}
signal(SIGINT, delete_pidf); // Turn off leds at exit
signal(SIGTERM, delete_pidf);
if (inicio){
ioctl(console_handle,KDSETLED,0);
inicio = 0;
}
/* Aquí creamos el archivo pidf y comprobamos que efectivamente somos la
* máquina y lo hemos hecho bien create_pidf, delete_pidf, kill_other*/
create_pidf();
status = getleds();
upp = 1;
while(1) {
if (opck)
status = kid(status);
else if (opcm)
carga_de_mem();
else if (opccpu)
carga_de_cpu();
else {
fprintf(stderr,"Error 09: In args parsing\n");
exit(1);
}
if (tiemposec)
sleep(tiemposec);
else
usleep(tiempo);
}
}
|