]> git.webhop.me Git - lcd4linux.git/commitdiff
[lcd4linux @ 2000-01-16 12:17:59 by reinelt]
authorreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 16 Jan 2000 12:17:59 +0000 (12:17 +0000)
committerreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 16 Jan 2000 12:17:59 +0000 (12:17 +0000)
Initial revision

git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@2 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

16 files changed:
Makefile [new file with mode: 0644]
MatrixOrbital.c [new file with mode: 0644]
config.c [new file with mode: 0644]
config.h [new file with mode: 0644]
display.c [new file with mode: 0644]
display.h [new file with mode: 0644]
filter.c [new file with mode: 0644]
filter.h [new file with mode: 0644]
isdn.c [new file with mode: 0644]
isdn.h [new file with mode: 0644]
lcd2041.c [new file with mode: 0644]
lcd2041.h [new file with mode: 0644]
lcd4linux.c [new file with mode: 0644]
lcd4linux.h [new file with mode: 0644]
system.c [new file with mode: 0644]
system.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..218e296
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+CC=gcc -m486 -g -Wall -I. -DVERSION=\"V0.5\"
+
+all: lcd4linux
+
+#lcd4linux: lcd4linux.c config.c lcd2041.c system.c isdn.c filter.c Makefile
+#      ${CC} -lm -o lcd4linux lcd4linux.c config.c lcd2041.c system.c isdn.c filter.c
+
+lcd4linux: display.c MatrixOrbital.c
+       ${CC} -lm -o lcd4linux display.c MatrixOrbital.c
+
+clean:
+       rm -f lcd4linux *.o *~
diff --git a/MatrixOrbital.c b/MatrixOrbital.c
new file mode 100644 (file)
index 0000000..38c2d26
--- /dev/null
@@ -0,0 +1,49 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "display.h"
+
+
+int MO_init (void)
+{
+  printf ("initializing MatrixOrbital...\n");
+  return 0;
+}
+
+int MO_clear (void)
+{
+  return 0;
+}
+
+int MO_put (int x, int y, char *text)
+{
+  return 0;
+}
+
+int MO_bar (int type, int x, int y, int max, int len1, int len2)
+{
+  return 0;
+}
+
+int MO_flush (void)
+{
+  return 0;
+}
+
+
+#define BARS ( BAR_L | BAR_R | BAR_U | BAR_D | BAR_S )
+
+DISPLAY MatrixOrbital[] = {
+  { "LCD0821",  8, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush },
+  { "LCD1621", 16, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush },
+  { "LCD2021", 20, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush },
+  { "LCD2041", 20, 4, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush },
+  { "LCD4021", 40, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush }, 
+  { "" }
+};
+
diff --git a/config.c b/config.c
new file mode 100644 (file)
index 0000000..c55d63c
--- /dev/null
+++ b/config.c
@@ -0,0 +1,98 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "config.h"
+
+typedef struct {
+  char *key;
+  char *val;
+} ENTRY;
+
+static ENTRY *Config=NULL;
+static int   nConfig=0;
+
+static char *strip (char *s)
+{
+  char *p;
+  
+  while (isblank(*s)) s++;
+  for (p=s; *p; p++) {
+    if (*p=='"') do p++; while (*p && *p!='\n' && *p!='"');
+    if (*p=='\'') do p++; while (*p && *p!='\n' && *p!='\'');
+    if (*p=='#' || *p=='\n') {
+      *p='\0';
+      break;
+    }
+  }
+  for (p--; p>s && isblank(*p); p--) *p='\0';
+  return s;
+}
+
+void set_cfg (char *key, char *val)
+{
+  int i;
+  
+  for (i=0; i<nConfig; i++) {
+    if (strcasecmp(Config[i].key, key)==0) {
+      if (Config[i].val) free (Config[i].val);
+      Config[i].val=strdup(val);
+      return;
+    }
+  }
+  nConfig++;
+  Config=realloc(Config, nConfig*sizeof(ENTRY));
+  Config[i].key=strdup(key);
+  Config[i].val=strdup(val);
+}
+
+char *get_cfg (char *key)
+{
+  int i;
+
+  for (i=0; i<nConfig; i++) {
+    if (strcasecmp(Config[i].key, key)==0) {
+      return Config[i].val;
+    }
+  }
+  return NULL;
+}
+
+
+int read_cfg (char *file)
+{
+  FILE *stream;
+  char buffer[256];
+  char *line, *p, *s;
+  
+  stream=fopen (file, "r");
+  if (stream==NULL) {
+    fprintf (stderr, "open(%s) failed: %s\n", file, strerror(errno));
+    return-1;
+  }
+  while ((line=fgets(buffer,256,stream))!=NULL) {
+    if (*(line=strip(line))=='\0') continue;
+    for (p=line; *p; p++) {
+      if (isblank(*p)) {
+       *p++='\0';
+       break;
+      }
+    }
+    p=strip(p);
+    if (*p) for (s=p; *(s+1); s++);
+    else s=p;
+    if (*p=='"' && *s=='"') {
+      *s='\0';
+      p++;
+    }
+    else if (*p=='\'' && *s=='\'') {
+      *s='\0';
+      p++;
+    }
+    set_cfg (line, p);
+  }
+  fclose (stream);
+  return 0;
+}
+
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..b07adc6
--- /dev/null
+++ b/config.h
@@ -0,0 +1,3 @@
+int  read_cfg (char *file);
+char *get_cfg (char *key);
+void  set_cfg (char *key, char *value);
diff --git a/display.c b/display.c
new file mode 100644 (file)
index 0000000..d154b67
--- /dev/null
+++ b/display.c
@@ -0,0 +1,57 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "display.h"
+
+extern DISPLAY MatrixOrbital[];
+
+FAMILY Driver[] = {
+  { "MatrixOrbital", MatrixOrbital },
+  { "" }
+};
+
+
+static DISPLAY *Display = NULL;
+
+int lcd_init (char *display)
+{
+  int i, j;
+  for (i=0; Driver[i].name[0]; i++) {
+    for (j=0; Driver[i].Display[j].name[0]; j++) {
+      if (strcmp (Driver[i].Display[j].name, display)==0) {
+       Display=&Driver[i].Display[j];
+       return Display->init();
+      }
+    }
+  }
+  fprintf (stderr, "lcd_init(%s) failed: no such display\n", display);
+  return -1;
+}
+
+int lcd_clear (void)
+{
+  return 0;
+}
+
+int lcd_put (int x, int y, char *text)
+{
+  return 0;
+}
+
+int lcd_bar (int type, int x, int y, int max, int len1, int len2)
+{
+  return 0;
+}
+
+int lcd_flush (void)
+{
+  return 0;
+}
+
+void main (void) {
+  int i, j;
+  
+  lcd_init ("junk");
+  lcd_init ("LCD2041");
+
+}
diff --git a/display.h b/display.h
new file mode 100644 (file)
index 0000000..0be2d50
--- /dev/null
+++ b/display.h
@@ -0,0 +1,30 @@
+#define BAR_L 1
+#define BAR_R 2
+#define BAR_U 4
+#define BAR_D 8
+#define BAR_S 256
+
+typedef struct {
+  char name[16];
+  int rows;
+  int cols;
+  int xres;
+  int yres;
+  int bars;
+  int (*init) (void);
+  int (*clear) (void);
+  int (*put) (int x, int y, char *text);
+  int (*bar) (int type, int x, int y, int max, int len1, int len2);
+  int (*flush) (void);
+} DISPLAY;
+
+typedef struct {
+  char name[16];
+  DISPLAY *Display;
+} FAMILY;
+
+int lcd_init (char *display);
+int lcd_clear (void);
+int lcd_put (int x, int y, char *text);
+int lcd_bar (int type, int x, int y, int max, int len1, int len2);
+int lcd_flush (void);
diff --git a/filter.c b/filter.c
new file mode 100644 (file)
index 0000000..f61a9ed
--- /dev/null
+++ b/filter.c
@@ -0,0 +1,117 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/time.h>
+
+#include "lcd4linux.h"
+#include "filter.h"
+
+#define SLOTS 64
+
+typedef struct {
+  char *name;
+  int slots;
+  struct timeval *time;
+  double *value;
+} FILTER;
+
+#define SECONDS(x) (x.tv_sec+x.tv_usec/1000000.0)
+
+double smooth(char *name, int period, double value)
+{
+  static FILTER *Filter=NULL;
+  static int nFilter=0;
+  struct timeval now;
+  double t, v;
+  int i, j;
+  
+  gettimeofday (&now, NULL);
+  
+  for (i=0; i<nFilter; i++) {
+    if (strcmp(name, Filter[i].name)==0) 
+      break;
+  }
+  
+  if (i==nFilter) {
+    int slots=(period+tick-1)/tick;
+    if (slots<2) 
+      slots=2;
+    else if (slots>SLOTS)
+      slots=SLOTS;
+
+    nFilter++;
+    Filter=realloc(Filter, nFilter*sizeof(FILTER));
+    Filter[i].name=strdup(name);
+    Filter[i].slots=slots;
+    Filter[i].time=malloc(slots*sizeof(Filter[i].time[0]));
+    Filter[i].value=malloc(slots*sizeof(Filter[i].value[0]));
+    for (j=0; j<slots; j++) {
+      Filter[i].time[j]=now;
+      Filter[i].value[j]=value;
+    }
+  }
+  
+  for (j=Filter[i].slots-1; j>0; j--) {
+    Filter[i].time[j]=Filter[i].time[j-1];
+    Filter[i].value[j]=Filter[i].value[j-1];
+  }
+  Filter[i].time[0]=now;
+  Filter[i].value[0]=value;
+  
+  t = SECONDS(Filter[i].time[0]) - SECONDS(Filter[i].time[Filter[i].slots-1]);
+  v = Filter[i].value[0]-Filter[i].value[Filter[i].slots-1];
+
+  if (t==0.0 || v<0.0)
+    return 0;
+  else
+    return v/t;
+}
+
+double damp(char *name, double value)
+{
+  static FILTER *Filter=NULL;
+  static int nFilter=0;
+  struct timeval now;
+  double max;
+  int i, j;
+  
+  gettimeofday (&now, NULL);
+  
+  for (i=0; i<nFilter; i++) {
+    if (strcmp(name, Filter[i].name)==0) 
+      break;
+  }
+  
+  if (i==nFilter) {
+    int slots=log(100)*tau/tick;
+    if (slots<1) 
+      slots=1;
+    else if (slots>SLOTS)
+      slots=SLOTS;
+
+    nFilter++;
+    Filter=realloc(Filter, nFilter*sizeof(FILTER));
+    Filter[i].name=strdup(name);
+    Filter[i].slots=slots;
+    Filter[i].time=malloc(slots*sizeof(Filter[i].time));
+    Filter[i].value=malloc(slots*sizeof(Filter[i].value));
+    for (j=0; j<slots; j++) {
+      Filter[i].time[j]=now;
+      Filter[i].value[j]=0;
+    }
+  }
+  
+  max=value;
+  for (j=Filter[i].slots-1; j>0; j--) {
+    double t = SECONDS(Filter[i].time[j]) - SECONDS(Filter[i].time[j-1]);
+    Filter[i].time[j]=Filter[i].time[j-1];
+    Filter[i].value[j]=Filter[i].value[j-1]*exp(-t/tau);
+    if (Filter[i].value[j]>max) max=Filter[i].value[j];
+  }
+
+  Filter[i].time[0]=now;
+  Filter[i].value[0]=value;
+  
+  return max;
+}
diff --git a/filter.h b/filter.h
new file mode 100644 (file)
index 0000000..a3b44a4
--- /dev/null
+++ b/filter.h
@@ -0,0 +1,2 @@
+double smooth (char *name, int period, double value);
+double damp (char *name, double value);
diff --git a/isdn.c b/isdn.c
new file mode 100644 (file)
index 0000000..fab470a
--- /dev/null
+++ b/isdn.c
@@ -0,0 +1,98 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <linux/isdn.h>
+
+#include "isdn.h"
+#include "filter.h"
+#include "lcd4linux.h"
+
+typedef struct {
+  unsigned long in;
+  unsigned long out;
+} CPS;
+
+
+static int Usage (void)
+{
+  static int fd=0;
+  char buffer[4096], *p;
+  int i, usage;
+
+  if (fd==-1) return 0;
+
+  fd=open ("/dev/isdninfo", O_RDONLY | O_NDELAY);
+  if (fd==-1) {
+    perror ("open(/dev/isdninfo) failed");
+    return 0;
+  }
+  
+  if (read (fd, buffer, sizeof(buffer))==-1) {
+    perror ("read(/dev/isdninfo) failed");
+    fd=-1;
+    return 0;
+  }
+
+  if (close(fd)==-1) {
+    perror ("close(/dev/isdninfo) failed");
+    fd=-1;
+    return 0;
+  }
+
+  p=strstr(buffer, "usage:");
+  if (p==NULL) {
+    fprintf (stderr, "parse(/dev/isdninfo) failed: no usage line\n");
+    fd=-1;
+    return 0;
+  }
+  p+=6;
+
+  usage=0;
+  for (i=0; i<ISDN_MAX_CHANNELS; i++) {
+    usage|=strtol(p, &p, 10);
+  }
+
+  return usage;
+}
+
+int Isdn (int *rx, int *tx)
+{
+  static int fd=-2;
+  CPS cps[ISDN_MAX_CHANNELS];
+  double cps_i, cps_o;
+  int i;
+
+  *rx=0;
+  *tx=0;
+
+  if (fd==-1) return 0;
+  
+  if (fd==-2) {
+    fd = open("/dev/isdninfo", O_RDONLY | O_NDELAY);
+    if (fd==-1) {
+      perror ("open(/dev/isdninfo) failed");
+      return 0;
+    }
+  }
+  if (ioctl(fd, IIOCGETCPS, &cps)) {
+    perror("ioctl(IIOCGETCPS) failed");
+    fd=-1;
+    return 0;
+  }
+  cps_i=0;
+  cps_o=0;
+  for (i=0; i<ISDN_MAX_CHANNELS; i++) {
+    cps_i+=cps[i].in;
+    cps_o+=cps[i].out;
+  }
+
+  *rx=(int)smooth("isdn_rx", 1000, cps_i);
+  *tx=(int)smooth("isdn_tx", 1000, cps_o);
+
+  return Usage();
+}
+
diff --git a/isdn.h b/isdn.h
new file mode 100644 (file)
index 0000000..62f1979
--- /dev/null
+++ b/isdn.h
@@ -0,0 +1 @@
+int Isdn (int *rx, int *tx);
diff --git a/lcd2041.c b/lcd2041.c
new file mode 100644 (file)
index 0000000..4987697
--- /dev/null
+++ b/lcd2041.c
@@ -0,0 +1,314 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "lcd2041.h"
+
+#define BAR_HORI 1
+#define BAR_VERT 2
+#define BAR_DUAL 3
+
+static int lcd;
+static char *lcd_device=NULL;
+static int bar_mode=0;
+
+typedef struct {
+  int l1;
+  int l2;
+  int chr;
+} SEGMENT;
+
+typedef struct {
+  int l1;
+  int l2;
+  int lru;
+} CHARACTER;
+
+static SEGMENT Segment[COLS+1][ROWS+1];
+static CHARACTER Character[CHAR];
+
+static int lcd_open(void)
+{
+  int fd;
+  struct termios portset;
+  
+  fd = open(lcd_device, O_RDWR | O_NOCTTY | O_NDELAY); 
+  if (fd==-1) {
+    fprintf (stderr, "open(%s) failed: %s\n", lcd_device, strerror(errno));
+    return -1;
+  }
+  if (tcgetattr(fd, &portset)==-1) {
+    fprintf (stderr, "tcgetattr(%s) failed: %s\n", lcd_device, strerror(errno));
+    return -1;
+  }
+  cfmakeraw(&portset);
+  cfsetospeed(&portset, B19200);
+  if (tcsetattr(fd, TCSANOW, &portset)==-1) {
+    fprintf (stderr, "tcsetattr(%s) failed: %s\n", lcd_device, strerror(errno));
+    return -1;
+  }
+  return fd;
+}
+
+
+static void lcd_write (char *string, int len)
+{
+  if (lcd==-1) return;
+  if (write (lcd, string, len)==-1) {
+    if (errno==EAGAIN) {
+      usleep(1000);
+      if (write (lcd, string, len)>=0) return;
+    }
+    fprintf (stderr, "write(%s) failed: %s\n", lcd_device, strerror(errno));
+  }
+}
+
+
+void lcd_clear (void)
+{
+  lcd_write ("\014", 1);
+}
+
+
+void lcd_put (int x, int y, char *string)
+{
+  char buffer[256];
+  snprintf (buffer, sizeof(buffer), "\376G%c%c%s", x, y, string);
+  lcd_write (buffer, strlen(buffer));
+}
+void lcd_hbar (int x, int y, int dir, int max, int len)
+{
+  char buffer[COLS+5];
+  char *p;
+
+  if (bar_mode!=BAR_HORI) {
+    lcd_write ("\376h", 2);
+    bar_mode=BAR_HORI;
+  }
+
+  if (len<1) len=1;
+  else if (len>max) len=max;
+  if (dir!=0) len=max-len;
+
+  snprintf (buffer, sizeof(buffer), "\376G%c%c", x, y);
+  p=buffer+4;
+  
+  while (max>0 && p-buffer<sizeof(buffer)) {
+    if (len==0) {
+      *p=dir?255:32;
+    } else if (len>=XRES) {
+      *p=dir?32:255;
+      len-=XRES;
+    } else {
+      *p=dir?8-len:len-1;
+      len=0;
+    }
+    max-=XRES;
+    p++;
+  }
+  lcd_write (buffer, p-buffer);
+}
+
+
+void lcd_vbar (int x, int y, int dir, int max, int len)
+{
+  char buffer[6];
+  unsigned char c;
+
+  if (bar_mode!=BAR_VERT) {
+    lcd_write ("\376v", 2);
+    bar_mode=BAR_VERT;
+  }
+
+  if (len<1) len=1;
+  else if (len>max) len=max;
+
+  while (max>0 && y>0) {
+    if (len==0) {
+      c=32;
+    } else if (len>=XRES) {
+      c=255;
+      len-=XRES;
+    } else {
+      c=len;
+      len=0;
+    }
+    snprintf (buffer, sizeof(buffer), "\376G%c%c%c", x, y, c);
+    lcd_write (buffer, 5);
+    max-=XRES;
+    y--;
+  }
+}
+
+
+static void lcd_dbar_init (void)
+{
+  int x, y;
+  
+  bar_mode=BAR_DUAL;
+
+  for (x=0; x<CHAR; x++) {
+    Character[x].l1=-1;
+    Character[x].l2=-1;
+    Character[x].lru=0;
+  }
+  
+  for (x=0; x<COLS; x++) {
+    for (y=0; y<ROWS; y++) {
+      Segment[x][y].l1=-1;
+      Segment[x][y].l2=-1;
+    }
+  }
+}
+
+static int lcd_dbar_char (int l1, int l2)
+{
+  int i, j, min;
+
+  if (l1==127) l1=0;
+  if (l2==127) l2=0;
+  
+  if (l1==0 && l2==0) return 32;
+  if (l1==XRES && l2==XRES) return 255;
+
+  for (i=0; i<CHAR; i++) {
+    if (Character[i].l1==l1 && Character[i].l2==l2) {
+      Character[i].lru=2;
+      return i;
+    }
+  }
+
+  for (i=0; i<CHAR; i++) {
+    if (Character[i].lru==0) {
+      printf ("creating char %d (%d/%d)\n", i, l1, l2);
+      Character[i].l1=l1;
+      Character[i].l2=l2;
+      Character[i].lru=2;
+      return i;
+    }
+  }
+
+  min=XRES*YRES;
+  for (i=0; i<CHAR; i++) {
+    int diff;
+    if (l1==0 && Character[i].l1!=0) continue;
+    if (l2==0 && Character[i].l2!=0) continue;
+    if (l1==XRES && Character[i].l1!=XRES) continue;
+    if (l2==XRES && Character[i].l2!=XRES) continue;
+    diff=abs(Character[i].l1-l1)+abs(Character[i].l2-l2);
+    if (diff<min) {
+      min=diff;
+      j=i;
+    }
+  }
+  printf ("lcd_dbar: diff=%d\n", min);
+  return j;
+}
+
+void lcd_dbar (int x, int y, int dir, int max, int len1, int len2)
+{
+  if (bar_mode!=BAR_DUAL)
+    lcd_dbar_init();
+  
+  if (len1<1) len1=1;
+  else if (len1>max) len1=max;
+
+  if (len2<1) len2=1;
+  else if (len2>max) len2=max;
+
+  while (max>0 && x<=COLS) {
+    if (len1==0) {
+      Segment[x][y].l1=0;
+    } else if (len1>=XRES) {
+      Segment[x][y].l1=XRES;
+      len1-=XRES;
+    } else {
+      Segment[x][y].l1=len1;
+      len1=0;
+    }
+    if (len2==0) {
+      Segment[x][y].l2=0;
+    } else if (len2>=XRES) {
+      Segment[x][y].l2=XRES;
+      len2-=XRES;
+    } else {
+      Segment[x][y].l2=len2;
+      len2=0;
+    }
+    max-=XRES;
+    x++;
+  }
+}
+
+void lcd_dbar_flush (void)
+{
+  int i, x, y;
+  
+  for (y=0; y<=ROWS; y++) {
+    for (x=0; x<=COLS; x++) {
+      if ((Segment[x][y].l1==0 && Segment[x][y].l2==XRES) || (Segment[x][y].l1==XRES && Segment[x][y].l2==0))
+       Segment[x][y].chr=lcd_dbar_char(Segment[x][y].l1, Segment[x][y].l2);
+    }
+  }
+  for (y=0; y<=ROWS; y++) {
+    for (x=0; x<=COLS; x++) {
+      if (Segment[x][y].l1!=-1 || Segment[x][y].l2!=-1) 
+       Segment[x][y].chr=lcd_dbar_char(Segment[x][y].l1, Segment[x][y].l2);
+    }
+  }
+
+  for (i=0; i<CHAR; i++) {
+    if (Character[i].lru==2) {
+      char buffer[12];
+      char pixel[XRES+1]={0, 16, 24, 28, 30, 31};
+      char p0=pixel[Character[i].l1];
+      char p1=pixel[Character[i].l2];
+      snprintf (buffer, sizeof(buffer), "\376N%c%c%c%c%c%c%c%c%c", i, p0, p0, p0, p0, p1, p1, p1, p1);
+      lcd_write (buffer, 11);
+    }
+    if (Character[i].lru>0)
+      Character[i].lru--;
+  }
+
+  for (y=0; y<=ROWS; y++) {
+    for (x=0; x<=COLS; x++) {
+      if (Segment[x][y].l1!=-1 || Segment[x][y].l2!=-1) {
+       char buffer[6];
+       snprintf (buffer, sizeof(buffer), "\376G%c%c%c", x, y, Segment[x][y].chr);
+       lcd_write (buffer, 5);
+      }
+    }
+  }
+}
+
+
+int lcd_init (char *device)
+{
+  if (lcd_device) free (lcd_device);
+  lcd_device=strdup(device);
+  lcd=lcd_open();
+  if (lcd==-1) return -1;
+  
+  lcd_clear();
+  lcd_write ("\376B", 3); // backlight on
+  lcd_write ("\376K", 2);   // cursor off
+  lcd_write ("\376T", 2);   // blink off
+  lcd_write ("\376D", 2);   // line wrapping off
+  lcd_write ("\376R", 2);   // auto scroll off
+  lcd_write ("\376V", 2);   // GPO off
+
+  return 0;
+}
+
+void lcd_contrast (int contrast)
+{
+  char buffer[4];
+  snprintf (buffer, 4, "\376P%c", contrast);
+  lcd_write (buffer, 3);
+}
+
diff --git a/lcd2041.h b/lcd2041.h
new file mode 100644 (file)
index 0000000..4951d4e
--- /dev/null
+++ b/lcd2041.h
@@ -0,0 +1,14 @@
+#define ROWS 4
+#define COLS 20
+#define XRES 5
+#define YRES 8
+#define CHAR 8
+
+int lcd_init (char *device);
+void lcd_contrast (int contrast);
+void lcd_clear (void);
+void lcd_put (int x, int y, char *string);
+void lcd_hbar (int x, int y, int dir, int max, int len);
+void lcd_vbar (int x, int y, int dir, int max, int len);
+void lcd_dbar (int x, int y, int dir, int max, int len1, int len2);
+void lcd_dbar_flush (void);
diff --git a/lcd4linux.c b/lcd4linux.c
new file mode 100644 (file)
index 0000000..9dbe92f
--- /dev/null
@@ -0,0 +1,499 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "config.h"
+#include "lcd2041.h"
+#include "system.h"
+#include "isdn.h"
+
+int tick, tack, tau;
+double overload;
+double temp_min, temp_max;
+char *sensor;
+char *row[ROWS];
+
+void usage(void)
+{
+  printf ("LCD4Linux " VERSION " (c) 1999 Michael Reinelt <reinelt@eunet.at>");
+  printf ("usage: LCD4Linux [configuration]\n");
+}
+
+char *parse (char *string)
+{
+  static char buffer[256];
+  char *s=string;
+  char *p=buffer;
+
+  do {
+    if (*s=='%') {
+      if (strchr("orpmlLbtdDnNiI%", *++s)==NULL) {
+       fprintf (stderr, "WARNING: unknown format <%%%c> in <%s>\n", *s, string);
+       continue;
+      } 
+      *p='%';
+      *(p+1)=*s;
+      switch (*s) {
+      case 'd':
+       if (strchr("rwmt", *++s)==NULL) {
+         fprintf (stderr, "WARNING: unknown disk tag <%%i%c> in <%s>\n", *s, string);
+         continue;
+       } 
+       *(p+2)=*s;
+       p+=3;
+       break;
+      case 'n':
+       if (strchr("rwmt", *++s)==NULL) {
+         fprintf (stderr, "WARNING: unknown net tag <%%i%c> in <%s>\n", *s, string);
+         continue;
+       } 
+       *(p+2)=*s;
+       p+=3;
+       break;
+      case 'i':
+       if (strchr("iomt", *++s)==NULL) {
+         fprintf (stderr, "WARNING: unknown ISDN tag <%%i%c> in <%s>\n", *s, string);
+         continue;
+       } 
+       *(p+2)=*s;
+       p+=3;
+       break;
+      default:
+       p+=2;
+      }
+      
+    } else if (*s=='$') {
+      char hv, dir;
+      int len=0;
+      hv=*++s;
+      if (tolower(hv)!='h' && tolower(hv)!='v') {
+       fprintf (stderr, "invalid bar orientation '%c' in <%s>\n", hv, string);
+       continue;
+      }
+      s++;
+      if (isdigit(*s)) len=strtol(s, &s, 10);
+      if (len<1 || len>255) {
+       fprintf (stderr, "invalid bar length in <%s>\n", string);
+       continue;
+      }
+      dir=*s++;
+      if ((tolower(hv)=='h' && dir!='l' && dir !='r') || (tolower(hv)=='v' && dir!='u' && dir !='d')) {
+       fprintf (stderr, "invalid bar direction '%c' in <%s>\n", dir, string);
+       continue;
+      }
+      *p='$';
+      *(p+1)=hv;
+      *(p+2)=len;
+      if (dir=='r' || dir=='u') *(p+3)='0';
+      else *(p+3)='1';
+      *(p+4)=*s;
+      switch (*s) {
+      case 'd':
+       if (strchr("rwmt", *++s)==NULL) {
+         fprintf (stderr, "WARNING: unknown disk tag <$i*%c> in <%s>\n", *s, string);
+         continue;
+       } 
+       *(p+5)=*s;
+       p+=6;
+       break;
+      case 'n':
+       if (strchr("rwmt", *++s)==NULL) {
+         fprintf (stderr, "WARNING: unknown net tag <$i*%c> in <%s>\n", *s, string);
+         continue;
+       } 
+       *(p+5)=*s;
+       p+=6;
+       break;
+      case 'i':
+       if (strchr("iomt", *++s)==NULL) {
+         fprintf (stderr, "WARNING: unknown ISDN tag <$i*%c> in <%s>\n", *s, string);
+         continue;
+       } 
+       *(p+5)=*s;
+       p+=6;
+       break;
+      default:
+       p+=5;
+      }
+      
+    } else if (*s=='\\') {
+      unsigned int c=0; int n;
+      if (*(s+1)=='\\') {
+       *p++='\\';
+       s+=2;
+      } else {
+       sscanf (s+1, "%3o%n", &c, &n);
+       if (c==0 || c>255) {
+         fprintf (stderr, "WARNING: illegal '\\' in <%s> <%s>\n", string, s);
+         continue;
+       }
+       *p++=c;
+       s+=n;
+      }
+      
+    } else {
+      *p++=*s;
+    }
+    
+  } while (*s++);
+  
+  return buffer;
+}
+
+
+void display (int smooth) {
+  static double disk_max=1.0;
+  static double net_max=1.0;
+  double busy, load, temp, disk, net, isdn;
+  int disk_r, disk_w;
+  int net_tx, net_rx;
+  int isdn_usage, isdn_in, isdn_out;
+  char buffer[256];
+  int i;
+  
+  busy=Busy();
+  load=Load();
+  Disk (&disk_r, &disk_w);
+  Net (&net_rx, &net_tx);
+  temp=Temperature();
+  isdn_usage=Isdn(&isdn_in, &isdn_out);
+
+  if (disk_r>disk_max) disk_max=disk_r;
+  if (disk_w>disk_max) disk_max=disk_w;
+
+  if (net_rx>net_max) net_max=net_rx;
+  if (net_tx>net_max) net_max=net_tx;
+  
+  for (i=0; i<ROWS; i++) {
+    char *s=row[i];
+    char *p=buffer;
+    do {
+      if (*s=='%') {
+       switch (*++s) {
+       case '%':
+         *p++='%';
+         break;
+       case 'o':
+         p+=sprintf (p, "%s", System());
+         break;
+       case 'r':
+         p+=sprintf (p, "%s", Release());
+         break;
+       case 'p':
+         p+=sprintf (p, "%s", Processor());
+         break;
+       case 'm':
+         p+=sprintf (p, "%d", Memory());
+         break;
+       case 'l':
+         if (load<10.0)
+           p+=sprintf (p, "%4.2f", load);
+         else
+           p+=sprintf (p, "%4.1f", load);
+         break;
+       case 'L':
+         *p++=load>overload?'!':' ';
+         break;
+       case 'b':
+         p+=sprintf (p, "%3.0f", 100.0*busy);
+         break;
+       case 'd':
+         switch (*++s) {
+         case 'r':
+           disk=disk_r;
+           break;
+         case 'w':
+           disk=disk_w;
+           break;
+         case 'm':
+           disk=disk_r>disk_w?disk_r:disk_w;
+           break;
+         default:
+           disk=disk_r+disk_w;
+           break;
+         }
+         disk/=1024;
+         if (disk<10.0) {
+           p+=sprintf (p, "%4.2f", disk);
+         } else if (disk<100.0) {
+           p+=sprintf (p, "%4.1f", disk);
+         } else {
+           p+=sprintf (p, "%4.0f", disk);
+         }
+         break;
+       case 'D':
+         if (disk_r+disk_w==0)
+           *p++=' ';
+         else
+           *p++=disk_r>disk_w?'\176':'\177';
+         break;
+       case 'n':
+         switch (*++s) {
+         case 'r':
+           net=net_rx;
+           break;
+         case 'w':
+           net=net_tx;
+           break;
+         case 'm':
+           net=net_rx>net_tx?net_rx:net_tx;
+           break;
+         default:
+           net=net_rx+net_tx;
+           break;
+         }
+         net/=1024.0;
+         if (net<10.0) {
+           p+=sprintf (p, "%4.2f", net);
+         } else if (net<100.0) {
+           p+=sprintf (p, "%4.1f", net);
+         } else {
+           p+=sprintf (p, "%4.0f", net);
+         }
+         break;
+       case 'N':
+         if (net_rx+net_tx==0)
+           *p++=' ';
+         else
+           *p++=net_rx>net_tx?'\176':'\177';
+         break;
+       case 't':
+         p+=sprintf (p, "%5.1f", temp);
+         break;
+       case 'i':
+         if (isdn_usage) {
+           switch (*++s) {
+           case 'i':
+             isdn=isdn_in;
+             break;
+           case 'o':
+             isdn=isdn_out;
+             break;
+           case 'm':
+             isdn=isdn_in>isdn_out?isdn_in:isdn_out;
+             break;
+           default:
+             isdn=isdn_in+isdn_out;
+             break;
+           }
+           isdn/=1024.0;
+           if (isdn<10.0) {
+             p+=sprintf (p, "%4.2f", isdn);
+           } else if (isdn<100.0) {
+             p+=sprintf (p, "%4.1f", isdn);
+           } else {
+             p+=sprintf (p, "%4.0f", isdn);
+           }
+         } else {
+           p+=sprintf (p, "----");
+           s++;
+         }
+         break;
+       case 'I':
+         if (isdn_in+isdn_out==0)
+           *p++=' ';
+         else
+           *p++=isdn_in>isdn_out?'\176':'\177';
+         break;
+       }
+       
+      } else if (*s=='$') {
+      double val;
+      int hv, len, dir;
+      hv=*++s;
+      len=*++s;
+      dir=*++s;
+      switch (*++s) {
+      case 'l':
+       val=load/overload;
+       break;
+      case  'b':
+       val=busy;
+       break;
+      case 'd':
+       switch (*++s) {
+       case 'r':
+         val=disk_r/disk_max;
+         break;
+       case 'w':
+         val=disk_w/disk_max;
+         break;
+       case 'm':
+         val=(disk_r>disk_w?disk_r:disk_w)/disk_max;
+         break;
+       default:
+         val=(disk_r+disk_w)/(2*disk_max);
+         break;
+       }
+       break;
+      case 'n':
+       switch (*++s) {
+       case 'r':
+         val=net_rx/net_max;
+         break;
+       case 'w':
+         val=net_tx/net_max;
+         break;
+       case 'm':
+         val=(net_rx>net_tx?net_rx:net_tx)/net_max;
+         break;
+       default:
+         val=(net_rx+net_tx)/(2*net_max);
+         break;
+       }
+       break;
+      case 't':
+       val=(temp-temp_min)/(temp_max-temp_min);
+       break;
+      case 'i':
+       switch (*++s) {
+       case 'i':
+         val=isdn_in;
+         break;
+       case 'o':
+         val=isdn_out;
+         break;
+       case 'm':
+         val=isdn_in>isdn_out?isdn_in:isdn_out;
+         break;
+       default:
+         val=isdn_in+isdn_out;
+         break;
+       }
+       val/=8000.0;
+       break;
+      default:
+       val=0.0;
+      }
+      switch (hv) {
+      case 'h':
+       lcd_hbar (p-buffer+1, i+1, dir-'0', len*XRES, val*len*XRES); 
+       break;
+      case 'H':
+       lcd_hbar (p-buffer+1, i+1, dir-'0', len*XRES, (double)len*XRES*log(val*len*XRES+1)/log(len*XRES)); 
+       break;
+      case 'v':
+       lcd_vbar (p-buffer+1, i+1, dir-'0', len*YRES, val*len*XRES); 
+       break;
+      }
+      while (len-->0) {
+       *p++='\t'; 
+      }
+      
+    } else {
+      *p++=*s;
+    }
+  } while (*s++);
+    
+    if (smooth==0) {
+      p=buffer;
+      while (*p) {
+       while (*p=='\t') p++;
+       for (s=p; *s; s++) {
+         if (*s=='\t') {
+           *s++='\0';
+           break;
+         }
+       }
+       if (*p) {
+         lcd_put (p-buffer+1, i+1, p);
+       }
+       p=s;
+      }
+    }
+  }
+}
+
+
+void main (int argc, char *argv[])
+{
+  char *cfg_file="/etc/lcd4linux.conf";
+  char *port;
+  int i;
+  int contrast;
+  int smooth;
+  
+  if (argc>2) {
+    usage();
+    exit (2);
+  }
+  if (argc==2) {
+    cfg_file=argv[1];
+  }
+
+  set_cfg ("row1", "*** %o %r ***");
+  set_cfg ("row2", "%p CPU  %m MB RAM");
+  set_cfg ("row3", "Busy %b%% $r50b");
+  set_cfg ("row4", "Load %l$r50l");
+
+  set_cfg ("tick", "100");
+  set_cfg ("tack", "500");
+  set_cfg ("tau", "500");
+  set_cfg ("contrast", "140");
+  set_cfg ("overload", "2.0");
+  set_cfg ("temp_min", "20");
+  set_cfg ("temp_max", "70");
+  
+  set_cfg ("fifo", "/var/run/LCD4Linux");
+
+  if (read_cfg (cfg_file)==-1)
+    exit (1);
+
+  port=get_cfg("port");
+  sensor=get_cfg("temperature");
+  tick=atoi(get_cfg("tick"));
+  tack=atoi(get_cfg("tack"));
+  tau=atoi(get_cfg("tau"));
+  contrast=atoi(get_cfg("contrast"));
+  overload=atof(get_cfg("overload"));
+  temp_min=atof(get_cfg("temp_min"));
+  temp_max=atof(get_cfg("temp_max"));
+
+  if (port==NULL || *port=='\0') {
+    fprintf (stderr, "%s: missing 'port' entry!\n", cfg_file);
+    exit (1);
+  }
+  
+  for (i=0; i<ROWS; i++) {
+    char buffer[8];
+    snprintf (buffer, sizeof(buffer), "row%d", i+1);
+    row[i]=strdup(parse(get_cfg(buffer)));
+  }
+  
+  lcd_init(port);
+  lcd_clear();
+  lcd_contrast (contrast);
+
+  lcd_put (1, 1, "** LCD4Linux " VERSION " **");
+  lcd_put (1, 3, "(c) 1999 M. Reinelt");
+
+
+  { 
+    int a, b, c, d;
+
+    lcd_dbar_init();
+    for (a=0; a<40; a++) {
+      b=40-a;
+      c=2*a;
+      d=c+a;
+      lcd_dbar (2, 1, 0, 80, a, b);
+      lcd_dbar (2, 2, 0, 80, c, d);
+      lcd_dbar_flush();
+      usleep( 300*1000);
+    }
+  }
+
+  sleep (2);
+  lcd_clear();
+
+  smooth=0;
+  while (1) {
+    display(smooth);
+    smooth+=tick;
+    if (smooth>tack) smooth=0;
+    usleep(1000*tick);
+  }
+}
diff --git a/lcd4linux.h b/lcd4linux.h
new file mode 100644 (file)
index 0000000..f7c91ae
--- /dev/null
@@ -0,0 +1,6 @@
+extern int tick;
+extern int tack;
+extern int tau;
+extern char *sensor;
+
+
diff --git a/system.c b/system.c
new file mode 100644 (file)
index 0000000..0d3679f
--- /dev/null
+++ b/system.c
@@ -0,0 +1,306 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <asm/param.h>
+
+#include "system.h"
+#include "filter.h"
+#include "lcd4linux.h"
+
+char *System(void)
+{
+  static char buffer[32]="";
+  struct utsname ubuf;
+
+  if (*buffer=='\0') {
+    if (uname(&ubuf)==-1) {
+      perror ("uname() failed");
+      strcpy (buffer, "unknown");
+    } else {
+      strncpy (buffer, ubuf.sysname, sizeof(buffer));
+    }
+  }
+  return buffer;
+}
+
+char *Release(void)
+{
+  static char buffer[32]="";
+  struct utsname ubuf;
+
+  if (*buffer=='\0') {
+    if (uname(&ubuf)==-1) {
+      perror ("uname() failed");
+      strcpy (buffer, "unknown");
+    } else {
+      strncpy (buffer, ubuf.release, sizeof(buffer));
+    }
+  }
+  return buffer;
+}
+
+
+char *Processor(void)
+{
+  static char buffer[16]="";
+  struct utsname ubuf;
+
+  if (*buffer=='\0') {
+    if (uname(&ubuf)==-1) {
+      perror ("uname() failed");
+      strcpy (buffer, "unknown");
+    } else {
+      strncpy (buffer, ubuf.machine, sizeof(buffer));
+    }
+  }
+  return buffer;
+}
+
+
+int Memory(void)
+{
+  static int value=-1;
+  struct stat buf;
+
+  if (value==-1) {
+    if (stat("/proc/kcore", &buf)==-1) {
+      perror ("stat(/proc/kcore) failed");
+      value=0;
+    } else {
+      value=buf.st_size>>20;
+    }
+  }
+  return value;
+}
+
+
+double Load (void)
+{
+  static int fd=-2;
+  char buffer[16];
+  static double value=0;
+  static time_t now=0;
+
+  if (fd==-1) return 0;
+  
+  if (time(NULL)==now) return value;
+  time(&now);
+
+  if (fd==-2) {
+    fd=open("/proc/loadavg", O_RDONLY);
+    if (fd==-1) {
+      perror ("open(/proc/loadavg) failed");
+      return 0;
+    }
+  }
+  if (lseek(fd, 0L, SEEK_SET)!=0) {
+    perror("lseek(/proc/loadavg) failed");
+    fd=-1;
+    return 0;
+  }
+  if (read (fd, &buffer, sizeof(buffer)-1)==-1) {
+    perror("read(/proc/loadavg) failed");
+    fd=-1;
+    return 0;
+  }
+  if (sscanf(buffer, "%lf", &value)<1) {
+    fprintf(stderr, "scanf(/proc/loadavg) failed\n");
+    fd=-1;
+    return 0;
+  }
+  return (value);
+}
+
+
+double Busy (void)
+{
+  static int fd=-2;
+  char buffer[64];
+  unsigned long v1, v2, v3, v4;
+  double busy, idle;
+
+  if (fd==-1) return 0;
+
+  if (fd==-2) {
+    fd=open("/proc/stat", O_RDONLY);
+    if (fd==-1) {
+      perror ("open(proc/stat) failed");
+      return 0;
+    }
+  }
+  if (lseek(fd, 0L, SEEK_SET)!=0) {
+    perror ("lseek(/proc/stat) failed");
+    fd=-1;
+    return 0;
+  }
+  if (read (fd, &buffer, sizeof(buffer)-1)==-1) {
+    perror ("read(/proc/stat) failed");
+    fd=-1;
+    return 0;
+  }
+  if (sscanf(buffer, "%*s %lu %lu %lu %lu\n", &v1, &v2, &v3, &v4)<4) {
+    fprintf (stderr, "scanf(/proc/stat) failed\n");
+    fd=-1;
+    return 0;
+  }
+
+  busy=smooth("cpu_busy", 500, v1+v2+v3);
+  idle=smooth("cpu_idle", 500, v4);
+  
+  if (busy+idle==0.0)
+    return 0.0;
+  else
+    return busy/(busy+idle);
+}
+
+
+int Disk (int *r, int *w)
+{
+  char buffer[4096], *p;
+  static int fd=-2;
+  unsigned long r1, r2, r3, r4;
+  unsigned long w1, w2, w3, w4;
+  
+  *r=0;
+  *w=0;
+
+  if (fd==-1) return 0;
+  
+  if (fd==-2) {
+    fd = open("/proc/stat", O_RDONLY | O_NDELAY);
+    if (fd==-1) {
+      perror ("open(/proc/stat) failed");
+      return 0;
+    }
+  }
+  
+  if (lseek(fd, 0L, SEEK_SET)!=0) {
+    perror ("lseek(/proc/stat) failed");
+    fd=-1;
+    return 0;
+  }
+  if (read (fd, &buffer, sizeof(buffer)-1)==-1) {
+    perror ("read(/proc/stat) failed");
+    fd=-1;
+    return 0;
+  }
+  p=strstr(buffer, "disk_rblk");
+  if (p==NULL) {
+    fprintf (stderr, "parse(/proc/stat) failed: no disk_rblk line\n");
+    fd=-1;
+    return 0;
+  }
+  if (sscanf(p+9, "%lu %lu %lu %lu\n", &r1, &r2, &r3, &r4)<4) {
+    fprintf (stderr, "scanf(/proc/stat) failed\n");
+    fd=-1;
+    return 0;
+  }
+  p=strstr(buffer, "disk_wblk");
+  if (p==NULL) {
+    fprintf (stderr, "parse(/proc/stat) failed: no disk_wblk line\n");
+    fd=-1;
+    return 0;
+  }
+  if (sscanf(p+9, "%lu %lu %lu %lu\n", &w1, &w2, &w3, &w4)<4) {
+    fprintf (stderr, "scanf(/proc/stat) failed\n");
+    fd=-1;
+    return 0;
+  }
+  
+  *r=smooth ("disk_r", 500, r1+r2+r3+r4);
+  *w=smooth ("disk_w", 500, w1+w2+w3+w4);
+
+  return *r+*w;
+}
+
+
+int Net (int *rx, int *tx)
+{
+  char buffer[4096], *p, *s;
+  static int fd=-2;
+  unsigned long pkg_rx, pkg_tx;
+  
+  *rx=0;
+  *tx=0;
+
+  if (fd==-1) return 0;
+  
+  if (fd==-2) {
+    fd = open("/proc/net/dev", O_RDONLY | O_NDELAY);
+    if (fd==-1) {
+      perror ("open(/proc/net/dev) failed");
+      return 0;
+    }
+  }
+  
+  if (lseek(fd, 0L, SEEK_SET)!=0) {
+    perror ("lseek(/proc/net/dev) failed");
+    fd=-1;
+    return 0;
+  }
+  if (read (fd, &buffer, sizeof(buffer)-1)==-1) {
+    perror ("read(/proc/net/dev) failed");
+    fd=-1;
+    return 0;
+  }
+  pkg_rx=0;
+  pkg_tx=0;
+  p=buffer;
+  while ((s=strsep(&p, "\n"))) {
+    unsigned long r, t;
+    if (sscanf (s, " eth%*d:%*d: %ld %*d %*d %*d %*d %ld", &r, &t)==2 ||
+       sscanf (s, " eth%*d: %ld %*d %*d %*d %*d %ld", &r, &t)==2) {
+      pkg_rx+=r;
+      pkg_tx+=t;
+    }  
+  }
+  *rx=smooth("net_rx", 500, pkg_rx);
+  *tx=smooth("net_tx", 500, pkg_tx);
+
+  return *rx+*tx;
+}
+
+
+double Temperature (void)
+{
+  static int fd=-2;
+  char buffer[32];
+  static double value=0.0;
+  static time_t now=0;
+
+  if (fd==-1) return 0;
+  
+  if (time(NULL)==now) return value;
+  time(&now);
+
+  if (fd==-2) {
+    fd=open(sensor, O_RDONLY);
+    if (fd==-1) {
+      fprintf (stderr, "open (%s) failed: %s\n", sensor, strerror(errno));
+      return 0;
+    }
+  }
+  if (lseek(fd, 0L, SEEK_SET)!=0) {
+    fprintf (stderr, "lseek(%s) failed: %s\n", sensor, strerror(errno));
+    fd=-1;
+    return 0;
+  }
+  if (read (fd, &buffer, sizeof(buffer)-1)==-1) {
+    fprintf (stderr, "read(%s) failed: %s\n", sensor, strerror(errno));
+    fd=-1;
+    return 0;
+  }
+  if (sscanf(buffer, "%*f %*f %lf", &value)<1) {
+    fprintf (stderr, "scanf(%s) failed\n", sensor);
+    fd=-1;
+    return 0;
+  }
+  return (value);
+}
diff --git a/system.h b/system.h
new file mode 100644 (file)
index 0000000..d3e3e28
--- /dev/null
+++ b/system.h
@@ -0,0 +1,9 @@
+char *System (void);
+char *Release (void);
+char *Processor (void);
+int   Memory (void);
+double Load (void);
+double Busy (void);
+int Disk (int *r, int *w);
+int Net (int *r, int *w);
+double Temperature (void);