Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6da7c51d22 |
@@ -1,17 +0,0 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
|
||||||
* text=auto
|
|
||||||
|
|
||||||
# Custom for Visual Studio
|
|
||||||
*.cs diff=csharp
|
|
||||||
|
|
||||||
# Standard to msysgit
|
|
||||||
*.doc diff=astextplain
|
|
||||||
*.DOC diff=astextplain
|
|
||||||
*.docx diff=astextplain
|
|
||||||
*.DOCX diff=astextplain
|
|
||||||
*.dot diff=astextplain
|
|
||||||
*.DOT diff=astextplain
|
|
||||||
*.pdf diff=astextplain
|
|
||||||
*.PDF diff=astextplain
|
|
||||||
*.rtf diff=astextplain
|
|
||||||
*.RTF diff=astextplain
|
|
||||||
-243
@@ -1,243 +0,0 @@
|
|||||||
#################
|
|
||||||
## Eclipse
|
|
||||||
#################
|
|
||||||
|
|
||||||
*.pydevproject
|
|
||||||
.project
|
|
||||||
.metadata
|
|
||||||
bin/
|
|
||||||
tmp/
|
|
||||||
*.tmp
|
|
||||||
*.bak
|
|
||||||
*.swp
|
|
||||||
*~.nib
|
|
||||||
local.properties
|
|
||||||
.classpath
|
|
||||||
.settings/
|
|
||||||
.loadpath
|
|
||||||
|
|
||||||
# External tool builders
|
|
||||||
.externalToolBuilders/
|
|
||||||
|
|
||||||
# Locally stored "Eclipse launch configurations"
|
|
||||||
*.launch
|
|
||||||
|
|
||||||
# CDT-specific
|
|
||||||
.cproject
|
|
||||||
|
|
||||||
# PDT-specific
|
|
||||||
.buildpath
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
|
||||||
## Visual Studio
|
|
||||||
#################
|
|
||||||
|
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
|
|
||||||
[Dd]ebug/
|
|
||||||
[Rr]elease/
|
|
||||||
x64/
|
|
||||||
build/
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*.log
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.log
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
*.ncrunch*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.Publish.xml
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# NuGet Packages Directory
|
|
||||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
|
||||||
#packages/
|
|
||||||
|
|
||||||
# Windows Azure Build Output
|
|
||||||
csx
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Windows Store app package directory
|
|
||||||
AppPackages/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
sql/
|
|
||||||
*.Cache
|
|
||||||
ClientBin/
|
|
||||||
[Ss]tyle[Cc]op.*
|
|
||||||
~$*
|
|
||||||
*~
|
|
||||||
*.dbmdl
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file to a newer
|
|
||||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
App_Data/*.mdf
|
|
||||||
App_Data/*.ldf
|
|
||||||
|
|
||||||
#############
|
|
||||||
## Windows detritus
|
|
||||||
#############
|
|
||||||
|
|
||||||
# Windows image file caches
|
|
||||||
Thumbs.db
|
|
||||||
ehthumbs.db
|
|
||||||
|
|
||||||
# Folder config file
|
|
||||||
Desktop.ini
|
|
||||||
|
|
||||||
# Recycle Bin used on file shares
|
|
||||||
$RECYCLE.BIN/
|
|
||||||
|
|
||||||
# Mac crap
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
|
|
||||||
#############
|
|
||||||
## Python
|
|
||||||
#############
|
|
||||||
|
|
||||||
*.py[cod]
|
|
||||||
|
|
||||||
# Packages
|
|
||||||
*.egg
|
|
||||||
*.egg-info
|
|
||||||
dist/
|
|
||||||
build/
|
|
||||||
eggs/
|
|
||||||
parts/
|
|
||||||
var/
|
|
||||||
sdist/
|
|
||||||
develop-eggs/
|
|
||||||
.installed.cfg
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
.coverage
|
|
||||||
.tox
|
|
||||||
|
|
||||||
#Translations
|
|
||||||
*.mo
|
|
||||||
|
|
||||||
#Mr Developer
|
|
||||||
.mr.developer.cfg
|
|
||||||
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
aclocal.m4
|
|
||||||
autom4te.cache
|
|
||||||
compile
|
|
||||||
config.guess
|
|
||||||
config.h
|
|
||||||
config.h.in
|
|
||||||
config.log
|
|
||||||
config.status
|
|
||||||
config.sub
|
|
||||||
configure
|
|
||||||
depcomp
|
|
||||||
install-sh
|
|
||||||
missing
|
|
||||||
mkinstalldirs
|
|
||||||
stamp-h1
|
|
||||||
tags
|
|
||||||
|
|
||||||
*.a
|
|
||||||
*.o
|
|
||||||
*.so
|
|
||||||
.deps
|
|
||||||
*.debian
|
|
||||||
*.LSB
|
|
||||||
*.rpm
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
# Travis-CI file for Espruino
|
|
||||||
|
|
||||||
language: c
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- chmod +x ./autogen.sh
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./autogen.sh && ./configure --enable-drivers=all
|
|
||||||
- make
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
Hey, thanks for reading this first! :)
|
|
||||||
|
|
||||||
*** NOTICE ****************************************************
|
|
||||||
This is a development version of LCDproc, straight from the Git
|
|
||||||
repository.
|
|
||||||
|
|
||||||
THIS VERSION OF LCDproc IS *NOT* GUARANTEED TO RUN, OR EVEN
|
|
||||||
COMPILE! YOU'VE BEEN WARNED!
|
|
||||||
***************************************************************
|
|
||||||
|
|
||||||
With that out of the way, welcome to the bleeding edge of LCDproc.
|
|
||||||
To build and run this version, you'll need autoconf 2.59 or higher
|
|
||||||
and friends installed.
|
|
||||||
|
|
||||||
Run:
|
|
||||||
|
|
||||||
$ sh ./autogen.sh
|
|
||||||
|
|
||||||
This produces the configure script and supporting files. Once the above
|
|
||||||
command has run, the rest is pretty standard:
|
|
||||||
|
|
||||||
$ ./configure --help
|
|
||||||
[read about the options, figure out what to use]
|
|
||||||
$ ./configure --prefix=/usr/local --enable-drivers=curses,CFontz
|
|
||||||
[replace curses,CFontz with comma-separated list of drivers you want]
|
|
||||||
$ make
|
|
||||||
$ su
|
|
||||||
$ make install
|
|
||||||
[make install is OPTIONAL ... might not want to replace a stable
|
|
||||||
version of LCDproc with a development release]
|
|
||||||
|
|
||||||
Patches and suggestions are welcome! Join the mailing list to get
|
|
||||||
started. See http://lcdproc.org/ for more information.
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
#include <LiquidCrystal.h>
|
|
||||||
|
|
||||||
LiquidCrystal lcd(9, 8, 7, 6, 5, 4, 3, 2);
|
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
int line = 0;
|
|
||||||
bool controller = false;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(115200);
|
|
||||||
// set up the LCD's number of columns and rows:
|
|
||||||
lcd.begin(40, 4);
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LCDSERIALIZER_LCDI 0xFE
|
|
||||||
|
|
||||||
byte serial_getch() {
|
|
||||||
int incoming;
|
|
||||||
while (Serial.available() == 0) {
|
|
||||||
}
|
|
||||||
// read the incoming byte:
|
|
||||||
incoming = Serial.read();
|
|
||||||
//Serial.write(incoming);
|
|
||||||
|
|
||||||
return (incoming & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
byte rxbyte = serial_getch(); // Fetch byte
|
|
||||||
|
|
||||||
if (rxbyte == LCDSERIALIZER_LCDI) // If LCD instruction
|
|
||||||
{
|
|
||||||
//Serial.write("[CMD]");
|
|
||||||
|
|
||||||
rxbyte = serial_getch(); // Fetch byte
|
|
||||||
|
|
||||||
if (rxbyte == 0x01)
|
|
||||||
{
|
|
||||||
Serial.println("Clear screen");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0c)
|
|
||||||
{
|
|
||||||
Serial.println("Restore the display (with cursor hidden)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x08)
|
|
||||||
{
|
|
||||||
Serial.println("Blank the display (without clearing)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0c)
|
|
||||||
{
|
|
||||||
Serial.println("Make cursor invisible");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0f)
|
|
||||||
{
|
|
||||||
Serial.println("Turn on visible blinking-block cursor");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0e)
|
|
||||||
{
|
|
||||||
Serial.println("Turn on visible underline cursor");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x10)
|
|
||||||
{
|
|
||||||
Serial.println("Move cursor one character left");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x14)
|
|
||||||
{
|
|
||||||
Serial.println("Move cursor one character right");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x15)
|
|
||||||
{
|
|
||||||
Serial.println("(15)Move cursor one character right");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x02)
|
|
||||||
{
|
|
||||||
Serial.println("Home (move cursor to top/left character position)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x18)
|
|
||||||
{
|
|
||||||
Serial.println("Scroll display one character left (all lines)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x1e)
|
|
||||||
{
|
|
||||||
Serial.println("Scroll display one character right (all lines)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x20)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (4-bit interface, 1 line, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x28)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (4-bit interface, 2 lines, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x30)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (8-bit interface, 1 line, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x38)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (8-bit interface, 2 lines, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x80)
|
|
||||||
{
|
|
||||||
serial_getch(); // instruction
|
|
||||||
row = serial_getch();
|
|
||||||
serial_getch(); // instruction
|
|
||||||
line = serial_getch();
|
|
||||||
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
|
|
||||||
Serial.println("Set Cursor to " + String(row) + "," + String(line));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (rxbyte & 0x40)
|
|
||||||
{
|
|
||||||
//Serial.println("Set pointer in character-generator RAM (CG RAM address)");
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
lcd.setController(0);
|
|
||||||
lcd.command(rxbyte);
|
|
||||||
lcd.setController(1);
|
|
||||||
lcd.command(rxbyte);
|
|
||||||
|
|
||||||
// get custom char
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
rxbyte = serial_getch(); // Fetch byte
|
|
||||||
lcd.setController(0);
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
lcd.setController(1);
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// print byte.
|
|
||||||
String thisString = String(rxbyte, HEX);
|
|
||||||
Serial.println("UNKNOWN " + thisString);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (rxbyte != 0x80 && !(rxbyte & 0x40))
|
|
||||||
lcd.command(rxbyte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// print byte.
|
|
||||||
//String thisString = String(rxbyte, HEX);
|
|
||||||
//Serial.println(thisString);
|
|
||||||
//Serial.println("position " + String(row) + " " + String(line));
|
|
||||||
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
line++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
@@ -1,193 +0,0 @@
|
|||||||
#include <LiquidCrystal.h>
|
|
||||||
|
|
||||||
LiquidCrystal lcd(9, 8, 7, 6, 5, 4, 3, 2);
|
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
int line = 0;
|
|
||||||
bool controller = false;
|
|
||||||
int temp = 0;
|
|
||||||
int ignore = 0;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(115200);
|
|
||||||
// set up the LCD's number of columns and rows:
|
|
||||||
lcd.begin(40, 4);
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LCDSERIALIZER_LCDI 0xFE
|
|
||||||
|
|
||||||
byte serial_getch() {
|
|
||||||
int incoming;
|
|
||||||
while (Serial.available() == 0) {
|
|
||||||
}
|
|
||||||
// read the incoming byte:
|
|
||||||
incoming = Serial.read();
|
|
||||||
//Serial.write(incoming);
|
|
||||||
|
|
||||||
return (incoming & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
byte rxbyte = serial_getch(); // Fetch byte
|
|
||||||
|
|
||||||
if (rxbyte == LCDSERIALIZER_LCDI) // If LCD instruction
|
|
||||||
{
|
|
||||||
//Serial.write("[CMD]");
|
|
||||||
|
|
||||||
rxbyte = serial_getch(); // Fetch byte
|
|
||||||
|
|
||||||
if (rxbyte == 0x01)
|
|
||||||
{
|
|
||||||
Serial.println("Clear screen");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0c)
|
|
||||||
{
|
|
||||||
Serial.println("Restore the display (with cursor hidden)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x08)
|
|
||||||
{
|
|
||||||
Serial.println("Blank the display (without clearing)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0c)
|
|
||||||
{
|
|
||||||
Serial.println("Make cursor invisible");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0f)
|
|
||||||
{
|
|
||||||
Serial.println("Turn on visible blinking-block cursor");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0e)
|
|
||||||
{
|
|
||||||
Serial.println("Turn on visible underline cursor");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x10)
|
|
||||||
{
|
|
||||||
Serial.println("Move cursor one character left");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x14)
|
|
||||||
{
|
|
||||||
Serial.println("Move cursor one character right");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x15)
|
|
||||||
{
|
|
||||||
Serial.println("(15)Move cursor one character right");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x02)
|
|
||||||
{
|
|
||||||
Serial.println("Home (move cursor to top/left character position)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x18)
|
|
||||||
{
|
|
||||||
Serial.println("Scroll display one character left (all lines)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x1e)
|
|
||||||
{
|
|
||||||
Serial.println("Scroll display one character right (all lines)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x20)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (4-bit interface, 1 line, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x28)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (4-bit interface, 2 lines, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x30)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (8-bit interface, 1 line, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x38)
|
|
||||||
{
|
|
||||||
Serial.println("Function set (8-bit interface, 2 lines, 5*7 Pixels)");
|
|
||||||
}
|
|
||||||
else if (rxbyte & 0x80)
|
|
||||||
{
|
|
||||||
byte address = rxbyte & 0x7f;
|
|
||||||
|
|
||||||
row = address <= 0x27 ? 0 : 1;
|
|
||||||
line = address <= 0x27 ? address : address - 64;
|
|
||||||
|
|
||||||
Serial.print("Address received " + String(row) + "," + String(line) + " \t");
|
|
||||||
|
|
||||||
if (controller)
|
|
||||||
row = row + 2;
|
|
||||||
|
|
||||||
if (row == 1 && line == 0)
|
|
||||||
controller = true;
|
|
||||||
else if (row == 3)
|
|
||||||
controller = false;
|
|
||||||
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
|
|
||||||
Serial.println("Set Cursor to " + String(row) + "," + String(line));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (rxbyte & 0x40)
|
|
||||||
{
|
|
||||||
//Serial.println("Set pointer in character-generator RAM (CG RAM address)");
|
|
||||||
Serial.println();
|
|
||||||
|
|
||||||
// uhh?
|
|
||||||
//ignore = 8;
|
|
||||||
|
|
||||||
lcd.setController(0);
|
|
||||||
lcd.command(rxbyte);
|
|
||||||
lcd.setController(1);
|
|
||||||
lcd.command(rxbyte);
|
|
||||||
|
|
||||||
// get custom char
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
rxbyte = serial_getch(); // Fetch byte
|
|
||||||
lcd.setController(0);
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
lcd.setController(1);
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// print byte.
|
|
||||||
String thisString = String(rxbyte, HEX);
|
|
||||||
Serial.println("UNKNOWN " + thisString);
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (rxbyte != 0x80 && !(rxbyte & 0x40))
|
|
||||||
lcd.command(rxbyte);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// print byte.
|
|
||||||
//String thisString = String(rxbyte, HEX);
|
|
||||||
//Serial.println(thisString);
|
|
||||||
//Serial.println("position " + String(row) + " " + String(line));
|
|
||||||
|
|
||||||
|
|
||||||
//if (ignore == 0)
|
|
||||||
//{
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
line++;
|
|
||||||
//}
|
|
||||||
/*else
|
|
||||||
{
|
|
||||||
lcd.setController(0);
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
lcd.setController(1);
|
|
||||||
lcd.write(rxbyte);
|
|
||||||
ignore--;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*if (line > 39)
|
|
||||||
{
|
|
||||||
row = row < 3 ? row + 1 : 0;
|
|
||||||
line = 0;
|
|
||||||
Serial.println("row increased by line count");
|
|
||||||
}
|
|
||||||
lcd.setCursor(line, row);*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
/*#include <LiquidCrystal.h>
|
|
||||||
|
|
||||||
LiquidCrystal lcd(9, 8, 7, 6, 5, 4, 3, 2);
|
|
||||||
|
|
||||||
int row = 0;
|
|
||||||
int line = 0;
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
Serial.begin(115200);
|
|
||||||
// set up the LCD's number of columns and rows:
|
|
||||||
lcd.begin(40, 4);
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define LCDSERIALIZER_LCDI 0xFE
|
|
||||||
|
|
||||||
byte serial_getch() {
|
|
||||||
int incoming;
|
|
||||||
while (Serial.available() == 0) {
|
|
||||||
}
|
|
||||||
// read the incoming byte:
|
|
||||||
incoming = Serial.read();
|
|
||||||
//Serial.write(incoming);
|
|
||||||
|
|
||||||
return (incoming & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
byte rxbyte;
|
|
||||||
|
|
||||||
rxbyte = serial_getch(); // Fetch byte
|
|
||||||
|
|
||||||
if (rxbyte == 0x11) // If LCD instruction
|
|
||||||
{
|
|
||||||
Serial.write("[CMD]");
|
|
||||||
|
|
||||||
rxbyte = serial_getch(); // Fetch byte
|
|
||||||
|
|
||||||
if (rxbyte == 0x0C)
|
|
||||||
{
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
Serial.println("[ff]");
|
|
||||||
line = 0;
|
|
||||||
row = 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x01)
|
|
||||||
{
|
|
||||||
Serial.println("[clr]");
|
|
||||||
lcd.clear();
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0D)
|
|
||||||
{
|
|
||||||
Serial.println("[cr]");
|
|
||||||
lcd.setCursor(0, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0A)
|
|
||||||
{
|
|
||||||
Serial.println("[nl]");
|
|
||||||
row = row < 3 ? row + 1 : 0;
|
|
||||||
line = 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0xc0) {
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
Serial.println("[ff]");
|
|
||||||
row = 0;
|
|
||||||
line = 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x12) {
|
|
||||||
Serial.println("[\n]");
|
|
||||||
row = row < 3 ? row + 1 : 0;
|
|
||||||
line = 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x04) {
|
|
||||||
Serial.println("[ ]");
|
|
||||||
line++;
|
|
||||||
if (line > 39)
|
|
||||||
{
|
|
||||||
row = row < 3 ? row + 1 : 0;
|
|
||||||
line = 0;
|
|
||||||
}
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x02) {
|
|
||||||
Serial.write("[hm]");
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
Serial.println("[ff]");
|
|
||||||
line = 0;
|
|
||||||
row = 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x80) {
|
|
||||||
lcd.clear();
|
|
||||||
lcd.home();
|
|
||||||
Serial.println("[80 clr]");
|
|
||||||
line = 0;
|
|
||||||
row = 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.print("[?]");
|
|
||||||
String thisString = String(rxbyte, HEX);
|
|
||||||
Serial.println(thisString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*else if (rxbyte == 0x12) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x15) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}*/
|
|
||||||
/*else if (rxbyte == 0x20) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
/*else if (rxbyte == 0x15) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x00) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x1b) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x1f) {
|
|
||||||
Serial.println("[]");
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x0e) {
|
|
||||||
Serial.println("[<]");
|
|
||||||
line--;
|
|
||||||
if (line < 0)
|
|
||||||
{
|
|
||||||
row = row > 0 ? row - 1 : 3;
|
|
||||||
line = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rxbyte == 0x01) {
|
|
||||||
Serial.print("[pos]");
|
|
||||||
serial_getch();
|
|
||||||
serial_getch();
|
|
||||||
serial_getch();
|
|
||||||
serial_getch();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (rxbyte == 0x0a) {
|
|
||||||
row = row < 3 ? row + 1 : 0;
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
String thisString = String(rxbyte, HEX);
|
|
||||||
Serial.println(thisString);
|
|
||||||
lcd.write(rxbyte); //Otherwise just dump it as text
|
|
||||||
line++;
|
|
||||||
if (line > 39)
|
|
||||||
{
|
|
||||||
row = row < 3 ? row + 1 : 0;
|
|
||||||
line = 0;
|
|
||||||
}
|
|
||||||
lcd.setCursor(line, row);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
Known Bugs:
|
|
||||||
--------------
|
|
||||||
|
|
||||||
V0.5dev:
|
|
||||||
- If vBars are used together with ICON_BLOCK_FILLED on the same screen and
|
|
||||||
that icon is implemented as a custom char, it sometimes is replaced with
|
|
||||||
a non full block from the vBar. Affected drivers: IOWarrior, CwLinux
|
|
||||||
- On Solaris the mtc_s16209x driver fails to compile. Configure LCDproc to
|
|
||||||
exclude this driver.
|
|
||||||
- The lcdproc client currently ignores errors from the machine dependent
|
|
||||||
functions. This may result in strange behaviour of the screens or core
|
|
||||||
dumps.
|
|
||||||
|
|
||||||
|
|
||||||
Bugs in previous versions (not checked if the still exist):
|
|
||||||
-----------------------------------------------------------
|
|
||||||
|
|
||||||
- A client may cause the connection to LCDd to break or even crash
|
|
||||||
LCDd by not reading the replies from LCDd
|
|
||||||
See one of the example clients (clients/examples) for details.
|
|
||||||
- MtxOrb driver
|
|
||||||
- "lcdproc K" does not display properly in between digit.
|
|
||||||
- The server tends to crash if the joystick driver is the last one loaded.
|
|
||||||
Specifically, if the "E" key is pressed...
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
# Code of Merit
|
|
||||||
|
|
||||||
1. The project creators, lead developers, core team, constitute
|
|
||||||
the managing members of the project and have final say in every decision
|
|
||||||
of the project, technical or otherwise, including overruling previous decisions.
|
|
||||||
There are no limitations to this decisional power.
|
|
||||||
|
|
||||||
2. Contributions are an expected result of your membership on the project.
|
|
||||||
Don't expect others to do your work or help you with your work forever.
|
|
||||||
|
|
||||||
3. All members have the same opportunities to seek any challenge they want
|
|
||||||
within the project.
|
|
||||||
|
|
||||||
4. Authority or position in the project will be proportional
|
|
||||||
to the accrued contribution. Seniority must be earned.
|
|
||||||
|
|
||||||
5. Software is evolutive: the better implementations must supersede lesser
|
|
||||||
implementations. Technical advantage is the primary evaluation metric.
|
|
||||||
|
|
||||||
6. This is a space for technical prowess; topics outside of the project
|
|
||||||
will not be tolerated.
|
|
||||||
|
|
||||||
7. Non technical conflicts will be discussed in a separate space. Disruption
|
|
||||||
of the project will not be allowed.
|
|
||||||
|
|
||||||
8. Individual characteristics, including but not limited to,
|
|
||||||
body, sex, sexual preference, race, language, religion, nationality,
|
|
||||||
or political preferences are irrelevant in the scope of the project and
|
|
||||||
will not be taken into account concerning your value or that of your contribution
|
|
||||||
to the project.
|
|
||||||
|
|
||||||
9. Discuss or debate the idea, not the person.
|
|
||||||
|
|
||||||
10. There is no room for ambiguity: Ambiguity will be met with questioning;
|
|
||||||
further ambiguity will be met with silence. It is the responsibility
|
|
||||||
of the originator to provide requested context.
|
|
||||||
|
|
||||||
11. If something is illegal outside the scope of the project, it is illegal
|
|
||||||
in the scope of the project. This Code of Merit does not take precedence over
|
|
||||||
governing law.
|
|
||||||
|
|
||||||
12. This Code of Merit governs the technical procedures of the project not the
|
|
||||||
activities outside of it.
|
|
||||||
|
|
||||||
13. Participation on the project equates to agreement of this Code of Merit.
|
|
||||||
|
|
||||||
14. No objectives beyond the stated objectives of this project are relevant
|
|
||||||
to the project. Any intent to deviate the project from its original purpose
|
|
||||||
of existence will constitute grounds for remedial action which may include
|
|
||||||
expulsion from the project.
|
|
||||||
|
|
||||||
This document is the Code of Merit (http://code-of-merit.org), version 1.0.
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
|
||||||
675 Mass Ave, Cambridge, MA 02139, USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) 19yy <name of author>
|
|
||||||
|
|
||||||
This program 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 program 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 program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Library General
|
|
||||||
Public License instead of this License.
|
|
||||||
-436
@@ -1,436 +0,0 @@
|
|||||||
# Introduction
|
|
||||||
|
|
||||||
LCDproc wouldn't have been possible without the efforts and work of many
|
|
||||||
dedicated enthusiasts and dabblers who have contributed to its development
|
|
||||||
over the years. We acknowledge their contributions here.
|
|
||||||
|
|
||||||
Please help us keeping this file up to date. If you're submitting a pull
|
|
||||||
request for the project, be sure to update this file to include yourself
|
|
||||||
if you're not already listed. Include a brief bio if you'd like, and be sure
|
|
||||||
to highlight the contributions you've made to the project. It's your
|
|
||||||
spotlight!
|
|
||||||
|
|
||||||
If you're absent, misattributed or your name and/or contact information
|
|
||||||
is inaccurate, please let us know (or submit a pull request to fix it)!
|
|
||||||
|
|
||||||
If you'd like to be removed from this file for some reason, please let us
|
|
||||||
know so we can take care of it. You're also welcome to list only your
|
|
||||||
name (or profile name) with no email address or other contact information
|
|
||||||
as well. We love putting our contributors' names up in lights, but we're
|
|
||||||
flexible :)
|
|
||||||
|
|
||||||
# Contributors
|
|
||||||
|
|
||||||
(listed in order of appearance)
|
|
||||||
|
|
||||||
- [William Ferrell (willfe)](mailto:willfe@gmail.com)
|
|
||||||
|
|
||||||
- Project founder, author of first versions and much documentation, design
|
|
||||||
for V0.4, "benevolent dictator for life" (to shamelessly borrow a page
|
|
||||||
from Linus Torvald's playbook).
|
|
||||||
|
|
||||||
> It's willfe's fault that LCDproc exists. He wanted his computer to have a
|
|
||||||
heartbeat, like some HP workstations and servers do. So he found a nice LCD,
|
|
||||||
wrote some amazingly spiffy software for it, and life was good.
|
|
||||||
|
|
||||||
- [Selene Scriven (ToyKeeper)](mailto:lcdproc@toykeeper.net)
|
|
||||||
|
|
||||||
- Wrote V0.3 and most of V0.4, and helped procrastinate the rest
|
|
||||||
of the time...
|
|
||||||
|
|
||||||
> ToyKeeper was the main programmer for LCDproc 0.2 - 0.4-pre9. She took
|
|
||||||
willfe's idea and put it in its current form.
|
|
||||||
|
|
||||||
- Gareth Watts (Xeno42)
|
|
||||||
|
|
||||||
- Patches, mailing list, ideas, web hosting, CVS, etc.
|
|
||||||
|
|
||||||
|
|
||||||
- [Matrix Orbital Corporation](http://www.matrixorbital.com/)
|
|
||||||
|
|
||||||
- Free displays for many of the developers, and immeasurable help
|
|
||||||
(especially early on).
|
|
||||||
|
|
||||||
|
|
||||||
- [Crystalfontz America, Inc.](http://www.crystalfontz.com/)
|
|
||||||
|
|
||||||
- Sends us sample/test units to get LCDproc running on all their models
|
|
||||||
- Rescued the lcdproc.org/com/net domains when their registrations
|
|
||||||
expired and they were "ransomed" by a domain squatter
|
|
||||||
|
|
||||||
|
|
||||||
- [Lorand Bruhacs](mailto:bruhacs@ip23.net)
|
|
||||||
|
|
||||||
- Developed LCDproc v0.3.5, which added lots of nifty stuff while
|
|
||||||
keeping the old program model
|
|
||||||
|
|
||||||
|
|
||||||
- [Benjamin Tse](mailto:blt@Comports.com), [Matthias Prinke](mailto:m.prinke@trashcan.mcnet.de)
|
|
||||||
|
|
||||||
- HD44780 driver and predecessors
|
|
||||||
|
|
||||||
|
|
||||||
- [Richard Rognlie](mailto:rrognlie@gamerz.net)
|
|
||||||
|
|
||||||
- Work on HD44780 driver
|
|
||||||
- GIF driver (lost code)
|
|
||||||
|
|
||||||
|
|
||||||
- Tom Wheeley
|
|
||||||
|
|
||||||
- IRMan input driver
|
|
||||||
|
|
||||||
|
|
||||||
- Bjoern Andersson
|
|
||||||
|
|
||||||
- Autoconf/automake build system
|
|
||||||
- Curses driver
|
|
||||||
|
|
||||||
|
|
||||||
- [Andrew McMeikan](mailto:andrewm@engineer.com)
|
|
||||||
|
|
||||||
- HD44780 driver
|
|
||||||
|
|
||||||
|
|
||||||
- David Glaude
|
|
||||||
|
|
||||||
- Lirc driver (not the current version)
|
|
||||||
- IRMAN driver,
|
|
||||||
- lcdproc big clocK screen.
|
|
||||||
- Matrix Orbital enhancement: Big Number, general-purpose output,
|
|
||||||
dynamic custom char allocation, i2c support (lost)
|
|
||||||
- Crystal Fontz drivers
|
|
||||||
- Matrix orbital GLK driver
|
|
||||||
|
|
||||||
|
|
||||||
- Todd Porter
|
|
||||||
|
|
||||||
- Windows 95/98 and NT version
|
|
||||||
|
|
||||||
|
|
||||||
- Jason Dale Woodward
|
|
||||||
|
|
||||||
- widget scrolling
|
|
||||||
|
|
||||||
|
|
||||||
- Ethan Dicks
|
|
||||||
|
|
||||||
- PIC-an-LCD original driver (later merged into HD44780 driver)
|
|
||||||
- fixes & tests to the MtxOrb driver and some clients
|
|
||||||
- lcdident.pl client
|
|
||||||
|
|
||||||
|
|
||||||
- Michael Reinelt
|
|
||||||
|
|
||||||
- SED1520 (copied work of him)
|
|
||||||
|
|
||||||
|
|
||||||
- Simon Harrison
|
|
||||||
|
|
||||||
- SVGAlib driver
|
|
||||||
|
|
||||||
|
|
||||||
- Horizon Technologies
|
|
||||||
|
|
||||||
- WIRZ-SLI driver
|
|
||||||
|
|
||||||
|
|
||||||
- Charles Steinkuehler
|
|
||||||
|
|
||||||
- Work on HD44780 timing code
|
|
||||||
|
|
||||||
|
|
||||||
- Harald Klein
|
|
||||||
|
|
||||||
- Lirc driver (initial version of the current code)
|
|
||||||
- Metar Client
|
|
||||||
|
|
||||||
- Philip Pokorny
|
|
||||||
|
|
||||||
- Crystal Fontz driver
|
|
||||||
- Matrix Orbital driver
|
|
||||||
- Matrix Orbital GLK driver
|
|
||||||
- Curses driver
|
|
||||||
|
|
||||||
|
|
||||||
- Glen Gray
|
|
||||||
|
|
||||||
- David Douthitt
|
|
||||||
|
|
||||||
- Crystal Fontz driver
|
|
||||||
- Matrix Orbital driver
|
|
||||||
- Matrix Orbital GLK driver
|
|
||||||
- Curses driver
|
|
||||||
|
|
||||||
- Eddie Sheldrake
|
|
||||||
|
|
||||||
- Crystal Fontz driver
|
|
||||||
|
|
||||||
|
|
||||||
- Rene Wagner
|
|
||||||
|
|
||||||
- LCDM001 driver
|
|
||||||
- ASCII emulation of BigNum
|
|
||||||
- CFontz v2.0 patches merging,
|
|
||||||
- LIRC driver updates (new API, merged David's code)
|
|
||||||
- Lots of driver updates for v0.4.3 (configfile, reporting):
|
|
||||||
- CFontz
|
|
||||||
- curses
|
|
||||||
- glk
|
|
||||||
- MtxOrb
|
|
||||||
- EPM list file for automatic package generation,
|
|
||||||
- current documentation in docbook format
|
|
||||||
- v0.4.3 backlight and heartbeat implementation
|
|
||||||
- Lots of other stuff for the v0.4.3 release
|
|
||||||
|
|
||||||
|
|
||||||
- Andre Breiler
|
|
||||||
|
|
||||||
- Matrix Orbital driver
|
|
||||||
|
|
||||||
|
|
||||||
- Joris Robijn
|
|
||||||
|
|
||||||
- HD44780 driver maintenance and enhancement
|
|
||||||
- Config file stuff
|
|
||||||
- Reporting stuff
|
|
||||||
- Work on API v0.5 architecture and implementation, loadable drivers.
|
|
||||||
- Menu stuff of v0.5
|
|
||||||
- SED1330 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Guillaume Filion
|
|
||||||
|
|
||||||
- Portability bug fixes on the curses, HD44780, SED1520 and
|
|
||||||
STV5730 drivers.
|
|
||||||
- Partially implemented Thomas Runge's BSD port of lcdproc.
|
|
||||||
- Ported the parallel functions in port.h to BSD.
|
|
||||||
- Autoconf/automake stuff.
|
|
||||||
- Various small 0.4.3 changes.
|
|
||||||
|
|
||||||
|
|
||||||
- Chris Debenham
|
|
||||||
|
|
||||||
- Matrix Orbital GLK driver
|
|
||||||
- LB216 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Mark Haemmerling
|
|
||||||
|
|
||||||
- HD44780 character conversion table
|
|
||||||
|
|
||||||
- Robin Adams
|
|
||||||
|
|
||||||
- SED1520 driver
|
|
||||||
- STV5730 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Manuel Stahl
|
|
||||||
|
|
||||||
- T6963 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Mike Patnode
|
|
||||||
|
|
||||||
- Crystal Fontz
|
|
||||||
- Various 0.4.3 changes
|
|
||||||
|
|
||||||
|
|
||||||
- Peter Marschall
|
|
||||||
|
|
||||||
- new drivers: IOWarrior, xosdlib
|
|
||||||
- bwctusb connectiontype for the HD44780 driver
|
|
||||||
- extensions to CFontz* drivers: support CF631 & CF635
|
|
||||||
- various fixes in preparation of 0.5
|
|
||||||
- lcd2usb connectiontype for the HD44780 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Markus Dolze
|
|
||||||
|
|
||||||
- project maintainer
|
|
||||||
- various fixes (especially for *BSD)
|
|
||||||
- merged and extended network interface statistics to lcdproc client
|
|
||||||
- new LCDd network input buffering
|
|
||||||
|
|
||||||
|
|
||||||
- Volker Boerchers
|
|
||||||
|
|
||||||
- fixes and extensions to the menu system
|
|
||||||
|
|
||||||
- Lucian Muresan
|
|
||||||
|
|
||||||
- glcdlib meta driver
|
|
||||||
|
|
||||||
- Matteo Pillon
|
|
||||||
|
|
||||||
- lcdserializer connectiontype to the hd44780 driver
|
|
||||||
- various improvements to the serial connections of the hd44780 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Laurent Arnal
|
|
||||||
|
|
||||||
- connectiontype for LIS2 displays from VLSystem
|
|
||||||
(http://www.vlsys.co.kr)
|
|
||||||
|
|
||||||
|
|
||||||
- Simon Funke
|
|
||||||
|
|
||||||
- driver for Noritake VFD
|
|
||||||
|
|
||||||
|
|
||||||
- Matthias Goebl <matthias.goebl@goebl.net>
|
|
||||||
|
|
||||||
- I2C connectiontype for the HD44780 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Stefan Herdler
|
|
||||||
|
|
||||||
- serialVFD driver
|
|
||||||
- bignum library
|
|
||||||
|
|
||||||
|
|
||||||
- Bernhard Walle
|
|
||||||
|
|
||||||
- driver for the ULA-200 device from ELV (http://www.elv.de)
|
|
||||||
|
|
||||||
|
|
||||||
- Andrew Foss
|
|
||||||
|
|
||||||
- menu support for lcdproc client
|
|
||||||
|
|
||||||
|
|
||||||
- Anthony J. Mirabella
|
|
||||||
|
|
||||||
- Logitech g15 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Cedric Tessier
|
|
||||||
|
|
||||||
- EyeBoxOne driver
|
|
||||||
|
|
||||||
|
|
||||||
- John Sanders
|
|
||||||
|
|
||||||
- iMon driver graphics support
|
|
||||||
|
|
||||||
|
|
||||||
- Eric Pooch
|
|
||||||
|
|
||||||
- Mac OS X / Darwin support
|
|
||||||
- serialPOS driver
|
|
||||||
- uss720 connection type for hd44780 driver
|
|
||||||
- driver for SoundGraph iMON OEM LCD Modules
|
|
||||||
|
|
||||||
|
|
||||||
- Benjamin Wiedmann
|
|
||||||
|
|
||||||
- Added functionality for HITACHI SP14Q002 gLCD (320x240)
|
|
||||||
- Implemented dynamic wiring scheme selection for SED1330 driver
|
|
||||||
("ConnectionType")
|
|
||||||
|
|
||||||
|
|
||||||
- Frank Jepsen
|
|
||||||
|
|
||||||
- vdr-wakeup support in hd44780 driver (originally for v0.4.5)
|
|
||||||
- new options for the hd44780 driver
|
|
||||||
|
|
||||||
- Karsten Festag
|
|
||||||
|
|
||||||
- ea65 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Gatewood Green
|
|
||||||
|
|
||||||
- picolcd driver
|
|
||||||
|
|
||||||
|
|
||||||
- Dave Platt
|
|
||||||
|
|
||||||
- overhauled CwLnx driver
|
|
||||||
|
|
||||||
|
|
||||||
- Nicu Pavel
|
|
||||||
|
|
||||||
- overhauled & extended picolcd driver
|
|
||||||
|
|
||||||
|
|
||||||
- Daryl Fonseca-Holt
|
|
||||||
|
|
||||||
- lis driver
|
|
||||||
|
|
||||||
|
|
||||||
- Thien Vu
|
|
||||||
|
|
||||||
- shuttleVFD driver
|
|
||||||
|
|
||||||
|
|
||||||
- Thomas Jarosch
|
|
||||||
|
|
||||||
- support reporting in hd44780's ConnectionType functions
|
|
||||||
- build-system clean up: use pkg-config for some libs
|
|
||||||
- HD44780 connection type for a USB connection via a FTDI FT2232D chip
|
|
||||||
- i2500vfd driver
|
|
||||||
|
|
||||||
|
|
||||||
- Christian Jodar
|
|
||||||
|
|
||||||
- mx5000 driver
|
|
||||||
|
|
||||||
|
|
||||||
- Mariusz Bialonczyk
|
|
||||||
|
|
||||||
- ethlcd connection type for HD44780
|
|
||||||
|
|
||||||
|
|
||||||
- Jack Cleaver
|
|
||||||
|
|
||||||
- LIRC support in picolcd
|
|
||||||
|
|
||||||
|
|
||||||
- Aron Parsons (Phant0m)
|
|
||||||
|
|
||||||
-IRtrans driver
|
|
||||||
|
|
||||||
|
|
||||||
- Malte Poeggel
|
|
||||||
|
|
||||||
- support for ST7036 controller in hd44780
|
|
||||||
|
|
||||||
|
|
||||||
- Dean Harding, Christian Leuschen, Jonathan Kyler
|
|
||||||
|
|
||||||
- driver for SoundGraph iMON OEM LCD Modules
|
|
||||||
|
|
||||||
|
|
||||||
- Laurent Latil
|
|
||||||
|
|
||||||
- SureElec driver for devices made by SURE Electronics
|
|
||||||
|
|
||||||
|
|
||||||
- Christoph Rasim
|
|
||||||
|
|
||||||
- MDM166A driver for Futaba/Targa USB VFD
|
|
||||||
|
|
||||||
|
|
||||||
- bjo81
|
|
||||||
|
|
||||||
- Driver for lcm162-module (by H. Rasch)
|
|
||||||
(https://github.com/lcdproc/lcdproc/pull/6)
|
|
||||||
|
|
||||||
|
|
||||||
- [Harald Geyer](mailto:harald@ccbib.org)
|
|
||||||
|
|
||||||
- Driver for the linux input subsystem
|
|
||||||
- Driver and font for Olimex MOD-LCD1x9 14 segment display
|
|
||||||
- Various minor and not-so-minor cleanups and fixes
|
|
||||||
|
|
||||||
|
|
||||||
- M. Feser and R. Geigenberger <yard2lcdproc (.A.T.) yard2usb.de>
|
|
||||||
|
|
||||||
- Driver for YARD2 display devices
|
|
||||||
|
|
||||||
|
|
||||||
- Colin Munro (colinmunro)
|
|
||||||
- Shane Spencer (hardwire)
|
|
||||||
- Jim McCracken (merlin_jim)
|
|
||||||
- Luis Llorente (luisllo)
|
|
||||||
-516
@@ -1,516 +0,0 @@
|
|||||||
v0.5dev (ongoing development)
|
|
||||||
- [added] Add travis file for Auto build testing of lcdproc (https://github.com/lcdproc/lcdproc/pull/2)
|
|
||||||
- [fixed] Update hd44780-i2c driver, pins defined via config file, rather than hardcoded (https://github.com/lcdproc/lcdproc/pull/1)
|
|
||||||
- [fixed] Portability fixes (https://github.com/lcdproc/lcdproc/pull/4)
|
|
||||||
- [added] Add driver for lcm162-module (by H. Rasch) (https://github.com/lcdproc/lcdproc/pull/6)
|
|
||||||
- [added] New driver linux_input (https://github.com/lcdproc/lcdproc/pull/7)
|
|
||||||
- [fixed] Cleanup I2C handling (https://github.com/lcdproc/lcdproc/pull/8)
|
|
||||||
- [fixed] Add more patterns to .gitignore (https://github.com/lcdproc/lcdproc/pull/9)
|
|
||||||
- [added] New driver for Olimex MOD-LCD1x9
|
|
||||||
- [fixed] Allow multibyte characters (from string widget)
|
|
||||||
- [added] New driver for YARD2 devices (https://github.com/lcdproc/lcdproc/pull/19)
|
|
||||||
|
|
||||||
v0.5.7
|
|
||||||
- [fixed] Fix using the left key to change the ring and checkbox menu items
|
|
||||||
- [fixed] sed1520: Add an option for inverted segment mapping (idea by R. Buchert)
|
|
||||||
- [fixed] Fix build if compiled with --enable-permissive-menu-goto (#3599609)
|
|
||||||
- [fixed] glcd driver: Add direct support for framebuffer with paged memory layout
|
|
||||||
- [added] hd44780: Added 'raspberrypi' connection type (P. Corner)
|
|
||||||
- [fixed] Build system: Rename configure.in to configure.ac
|
|
||||||
- [added] hd44780: Add support for FreeBSD's iic I2C framework
|
|
||||||
- [added] hd44780: New connection type 'piplate' (J. Brogdon)
|
|
||||||
- [fixed] lcdproc client: Add option to turn off title on OldTime screen
|
|
||||||
- [added] glcd driver: Connection type 'x11' that draws to a X window (S. Meharg)
|
|
||||||
- [added] glcd driver: 'picolcdgfx' for picoLCD 256x64 from Mini-Box.com (S. Meharg)
|
|
||||||
- [fixed] picolcd: Improvements to IR processing (M. Jones)
|
|
||||||
- [added] hd44780: Added 'spi' connection type (S. Dawson)
|
|
||||||
- [fixed] hd55780/serial: Change data escape handling (G. Smith)
|
|
||||||
- [added] hd44780: New connection type 'pifacecad' (T. Preston)
|
|
||||||
- [added] new driver: rawserial - dump framebuffer to serial port (C. Wolf)
|
|
||||||
|
|
||||||
v0.5.6
|
|
||||||
- [removed] Remove deprecated CFontz633 driver. Use CFontzPacket with Model=633 instead!
|
|
||||||
- [added] new driver: glcd unified graphic display driver (M. Dolze)
|
|
||||||
- [added] new driver: vlsys_m428 driver for Moneual MonCaso 320 (W. Hauck)
|
|
||||||
- [fixed] hd44780/serial: Fix handling of keys for LoS-Panel (M. Kirchner)
|
|
||||||
- [fixed] hd44780/serial: Change backlight handling (see commit message)
|
|
||||||
- [added] glcd driver: Add FreeType 2 rendering support (B. Walle and M. Dolze)
|
|
||||||
- [added] glcd driver: New connection type 'png', writes framebuffer as PNG image
|
|
||||||
- [added] hd44780: Fix vBars and block icon not working correctly on the same screen
|
|
||||||
- [fixed] Build system: Link LCDd itself with pthread library if available
|
|
||||||
- [fixed] lcdproc client: Unbreak build on OpenBSD non-i386 (E. Barrett)
|
|
||||||
- [fixed] lcdproc client: Fix core dumps on FreeBSD if started as non-root
|
|
||||||
- [added] glcd driver: new connection type 'serdisplib'
|
|
||||||
- [added] glcd driver: new connection type 'glcd2usb'
|
|
||||||
- [fixed] lcdproc client: On FreeBSD show only unique processes in 'S' screen
|
|
||||||
- [fixed] picolcd: Use libusb-1.0 asynchronous transfers to fix missed keys (M. Jones)
|
|
||||||
- [fixed] sed1520: Make it work without using an external inverter
|
|
||||||
- [fixed] lis driver: Make the last pixel row work (add lastline option parsing)
|
|
||||||
- [fixed] hd44780/ftdi: Fix error in setting backlight and add backlight for 4bit mode
|
|
||||||
- [added] new driver: sdeclcd for Watchguard FireBox appliances (F. Mertz)
|
|
||||||
- [added] hd44780: Added 'usb4all' connection type (T. Mohaupt)
|
|
||||||
- [fixed] Fix RPM init script hanging on recent OS (#3488223)
|
|
||||||
- [fixed] lcdproc client: Fix build on OpenBSD >= 5.0
|
|
||||||
- [fixed] hd44780/serial: Add support for adjustable backlight
|
|
||||||
- [fixed] Build system: Fix build with automake >= 1.11.3 (#3494755)
|
|
||||||
- [fixed] Fix clang compiler warnings about obsolete GNU designated initializers
|
|
||||||
- [fixed] Fix crash when adding a menu item without text and options (S. Dawson)
|
|
||||||
|
|
||||||
v0.5.5
|
|
||||||
- [added] sed1330 driver: Add support for HG25504 (L. Lagendijk)
|
|
||||||
- [fixed] Build system: Fix xosd detection
|
|
||||||
- [fixed] Reset ccmode on screen clear for NoritakeVFD, tyan driver
|
|
||||||
- [fixed] All drivers: Refactor CGmode enum into lcd.h
|
|
||||||
- [fixed] hd44780: New (possible faster) screen update algorithm
|
|
||||||
- [added] Add an option to start LCDd with screen rotation disabled (M. Zanetti)
|
|
||||||
- [fixed] Rewrite of the t6963 driver fixing several problems (see commit note).
|
|
||||||
- [fixed] picolcd: Add OffBrightness (S. Crane), more icons and fix bignum
|
|
||||||
- [fixed] lcdproc: Fix a single dot appearing on line 5 of the D screen
|
|
||||||
- [fixed] lcdproc: Make the iface screen more readable on 2x16 displays
|
|
||||||
- [fixed] All drivers: sync functions with prototypes
|
|
||||||
- [fixed] Port remaining drivers to 0.5 API (glk, lcdm001, stv5730)
|
|
||||||
- [fixed] Pyramid: Only send LED state changes, doxygen-ize
|
|
||||||
- [fixed] sed1520: Make it work with 68-family style interface, convert to 0.5 API
|
|
||||||
- [fixed] hd44780/imon: Add charmap for NEC uPD16314 and make it configurable
|
|
||||||
- [fixed] Pyramid: Convert set_char to 8 byte bitmap, add support for bignum
|
|
||||||
- [fixed] Convert set_char of drivers bayrad, lb216, lcterm, mtc_s16209x, wirz-sli
|
|
||||||
- [fixed] CFontzPacket: Fix not using select() even if its available
|
|
||||||
- [fixed] CFontzPacket: Use cellwidth = 5 on CFA-631 and CFA-635 too
|
|
||||||
- [fixed] t6963: Convert font to 8 byte bitmap
|
|
||||||
- [fixed] convert i2500vfd and mdm166a driver to use 8 byte bitmap custom character
|
|
||||||
- [fixed] ula200: convert custom characters to 8 byte bitmap
|
|
||||||
- [fixed] Build system: Fix trying to install svga driver twice
|
|
||||||
- [added] imon: Add bignum support (Y. Scheglyuk)
|
|
||||||
- [fixed] hd44780/ethlcd: fix LCDd hang up on network error (exits now) (M. Bialonczyk)
|
|
||||||
- [added] New common 5x8 font for t6963, sed1520, mdm166a and i2500vfd
|
|
||||||
- [fixed] t6963: Size has now to be configured in pixels instead of characters
|
|
||||||
- [added] Build system: --enable-extra-charmaps option adds language specific charmaps
|
|
||||||
- [fixed] imonlcd: Fix spinning of disc icon (E. Pooch)
|
|
||||||
- [fixed] SureElec: Change port initialization (SF 3212891)
|
|
||||||
- [fixed] curses: Fix missed keystrokes (from Debian)
|
|
||||||
- [fixed] curses: Correct the name of the info function.
|
|
||||||
- [fixed] Update LCDd.conf to be better understood by Config::Model (D. Dumont)
|
|
||||||
- [fixed] CFontz: Fix display of bars
|
|
||||||
|
|
||||||
v0.5.4
|
|
||||||
- [fixed] Update driver includes and LDFLAGS (fixed glk and bayrad binding error)
|
|
||||||
- [fixed] Modify all drivers to use server/drivers/report.h instead of shared/report.h
|
|
||||||
- [fixed] Make all drivers using parallel port fail if they cannot get IO permission
|
|
||||||
- [fixed] Include <errno.h> instead of <sys/errno.h> everywhere (found by S. Klauer)
|
|
||||||
- [fixed] configure: Fix de-selecting of drivers
|
|
||||||
- [fixed] Build system: Add a check testing if SA_RESTART flag is available.
|
|
||||||
- [fixed] picolcd driver: Fix RC-5 for picoLCD 20x2 (A. van Schie)
|
|
||||||
- [fixed] Introduce shared/defines.h to collect commonly used macros
|
|
||||||
- [added] new driver: SureElec for devices made by SURE Electronics (Laurent Latil)
|
|
||||||
- [fixed] hd44780-4bit: Fix bug not checking for keypad rows 7-10 correctly
|
|
||||||
- [fixed] Modify serial drivers to use cfmakeraw
|
|
||||||
- [added] hd44780: Add a 'none' charmap which does not replace any character
|
|
||||||
- [fixed] hd44780: Change mapping for spanish 'n with tilde' characters
|
|
||||||
- [fixed] hd44780: Exclude pin for switchable backlight from keypad scanning
|
|
||||||
- [fixed] server core: New network input buffering
|
|
||||||
- [fixed] hd44780: Extended subdriver API and performance improvement for lcd2usb
|
|
||||||
- [fixed] hd44780: Add KOI8-R character mapping (Yura Scheglyuk)
|
|
||||||
- [fixed] shuttleVFD: Add support for devices with USB VID 0x1308 again
|
|
||||||
- [fixed] CFontzPacket: Add CFA-533. Use HD44780 character mapping for CFA533/633.
|
|
||||||
- [fixed] CFontzPacket: Report cell size correctly, use block character for icon.
|
|
||||||
- [fixed] CFontz633: Deprecate this driver. Use CFontzPacket with Model=633 instead!
|
|
||||||
- [removed] Remove native win32 support.
|
|
||||||
- [fixed] picolcd: Use module output function to control key LEDs (Martin Jones)
|
|
||||||
- [added] hd44780: Added 'usbtiny' connection type (Siarhei Herasimchuk)
|
|
||||||
- [fixed] SureElec: Fix stall on startup
|
|
||||||
- [added] new driver: MDM166A for Futaba/Targa USB VFD (Christoph Rasim)
|
|
||||||
- [fixed] picolcd: Fix backlight and contrast handling (M. T. Jones)
|
|
||||||
- [fixed] picolcd: Fix heartbeat icon messing up with vbar
|
|
||||||
- [fixed] imonlcd: Fix possible lockup in output (icons) function (E. Pooch)
|
|
||||||
- [fixed] pyramid: Fix buffer overflow in set_leds, incorrect escaping, and icons
|
|
||||||
|
|
||||||
v0.5.3
|
|
||||||
- [added] lcdexec: notification when called program finishes
|
|
||||||
- [added] xosd driver: offset from top-left corner
|
|
||||||
- [added] LCDd: Hello= config option for startup message
|
|
||||||
- [fixed] glk driver: bignum support fixed
|
|
||||||
- [fixed] update local snprintf to the last one, which is GPL
|
|
||||||
- [removed] server core: cleanup - remove unnecessary cruft
|
|
||||||
- [fixed] server core: refactor rendering code
|
|
||||||
- [added] LCDd: config options TitleSpeed= and Heartbeat=
|
|
||||||
- [fixed] overhauled CwLnx driver (Dave Platt)
|
|
||||||
- [fixed] overhauled picolcd driver (Nicu Pavel)
|
|
||||||
- [added] add ServerScreen=blank option value
|
|
||||||
- [fixed] MtxOrb driver: fix VFD/VKD support (Ethan Dicks)
|
|
||||||
- [added] new driver lis for VLSystem L.I.S VFD (Daryl Fonseca-Holt)
|
|
||||||
- [fixed] serialPOS driver: input support, cleanup (Eric Pooch)
|
|
||||||
- [added] new driver shuttleVFD for USB-based Shuttle VFDs (Thien Vu)
|
|
||||||
- [fixed] enable building lcdproc client on FreeBSD AMD64 platform (M. Dolze)
|
|
||||||
- [fixed] Autoconf fixes for Net/FreeBSD (M. Dolze)
|
|
||||||
- [fixed] fixes for the lcpdroc client iface screen on *BSD (M.Dolze)
|
|
||||||
- [added] key support for hd44780/lcd2usb (M. Dolze)
|
|
||||||
- [added] option Priority for NoritakeVFD (idea: Richard Muratti)
|
|
||||||
- [fixed] overhauled NoritakeVFD driver (idea: Richard Muratti)
|
|
||||||
- [fixed] allow wrapping slider menu items with <= 4 keys (M. Dolze)
|
|
||||||
- [fixed] a bit more Doxygen-ation and documentation
|
|
||||||
- [fixed] hd44780 driver: make ConnectionType 4bit more fool-proof (M. Dolze)
|
|
||||||
- [fixed] picolcd driver: overhaul USB init for more portability (M. Dolze)
|
|
||||||
- [added] curses driver: new option DrawBorder (Bruno Schwander)
|
|
||||||
- [fixed] avoid sending duplicate "success" messages in response to menu_add_item
|
|
||||||
- [added] lcdexec: parameter support using widgets
|
|
||||||
- [fixed] server core: display values in menu for all input MenuEntry types
|
|
||||||
- [fixed] hd44780 driver: reorganize ConnectionType recognition
|
|
||||||
- [added] hd44780 driver: new ConnectionType mplay
|
|
||||||
- [added] hd44780 driver: get/set contrast & brightness support for lcd2usb (M. Dolze)
|
|
||||||
- [added] hd44780 driver: reporting in ConnectionType functions (Thomas Jarosch)
|
|
||||||
- [fixed] clean up build system (T. Jarosch, with tests/fixes by M. Dolze)
|
|
||||||
- [added] hd44780 driver: new ConnectionType ftdi (Thomas Jarosch)
|
|
||||||
- [fixed] shuttleVFD driver: fix VendorID, support newer models (Miska Sulander)
|
|
||||||
- [added] i2500vfd driver for a graphical Noritake VFD (Thomas Jarosch)
|
|
||||||
- [fixed] hd44780 driver: more complete initialization (idea by Pierre Ossman)
|
|
||||||
- [fixed] hd44780 driver: "euro" character mapping table (Markus Dolze)
|
|
||||||
- [fixed] CwLnx driver: support for CW12832
|
|
||||||
- [added] new driver mx5000 for Logitech MX5000 keyboards (Christian Jodar)
|
|
||||||
- [fixed] update debian init scripts to allow multiple instances of clients
|
|
||||||
- [added] serialVFD driver: support for 4 more display types (Stefan Herdler)
|
|
||||||
- [fixed] IOWarrior driver: fixed 4-line display use
|
|
||||||
- [added] IOWarrior driver: add ExtendedMode option
|
|
||||||
- [fixed] lcdproc: unbreak compilation on OS X 1.5 and higher (Topher Fangio)
|
|
||||||
- [fixed] server: fix interpretation of numeric priorities (Andrew M. Bishop)
|
|
||||||
- [added] hd44780 driver: new ConnectionType ethlcd (Mariusz Bialonczyk)
|
|
||||||
- [added] picolcd driver: support to send IR commands to LIRC (Jack Cleaver)
|
|
||||||
- [added] picolcd driver: support for 20x4 picoLCDs (Nicu Pavel)
|
|
||||||
- [added] hd44780 driver: new ConnectionType uss720 (Eric Pooch)
|
|
||||||
- [fixed] new make targets to compile & install server & clients separately
|
|
||||||
- [fixed] autoconf fixes: check for pkg-config macros
|
|
||||||
- [added] new driver irtrans (Phant0m / Aron Parsons)
|
|
||||||
- [added] serialVFD driver: support Siemens/Wincor Nixdorf BA63/66 (Stefan Herdler)
|
|
||||||
- [added] new client lcdident.pl (Ethan Dicks)
|
|
||||||
- [fixed] server: prevent stalling if time goes backwards (M. Vallevand)
|
|
||||||
- [fixed] hd44780 driver: update the backlight setting only on change
|
|
||||||
- [added] hd44780 driver: add lineaddress option to support ST7036 (Malte Poeggel)
|
|
||||||
- [added] lcdproc: Retrieve per CPU usage statistics on FreeBSD (M. Dolze)
|
|
||||||
- [fixed] Change drivers to start in background by default: bayrad, CFontz, ea65, glk
|
|
||||||
- [fixed] imon driver: Change hbars to make last char in-/decrease vertically
|
|
||||||
- [added] hd44780 driver: port usblcd connection type from 0.4.5 to 0.5 (M. Dolze)
|
|
||||||
- [fixed] server: Fix interpretation of named screen priorities
|
|
||||||
- [added] new driver imonlcd for SoundGraph iMON LCD (Dean Harding, Jonathan Kyler)
|
|
||||||
- [fixed] MtxOrb driver: Fix backlight for old firmware
|
|
||||||
- [fixed] Add checks for null pointer / failed malloc to menu code
|
|
||||||
- [fixed] lcdproc, lcdexec, lcdvc clients: Use our included getopt.h
|
|
||||||
- [fixed] documentation: Fix XML errors in user and developer guide
|
|
||||||
- [added] documentation: Add man page for lcdvc
|
|
||||||
|
|
||||||
v.0.5.2
|
|
||||||
- [fixed] fix switching on/off the Load screen in lcdproc client using the menu
|
|
||||||
- [fixed] refactor adv_bignum: support height > 4, loadable chars with offset
|
|
||||||
- [fixed] ged rid of global variables buffer & tmp in lcdproc client
|
|
||||||
- [added] add init-script templates for LSB 3.x conforming systems
|
|
||||||
- [fixed] fix cellwidth in iMon driver
|
|
||||||
- [added] graphics character support in iMon driver (John Saunders)
|
|
||||||
- [fixed] try harder to find a shell in lcdexec
|
|
||||||
- [added] big number support in CwLnx driver via bignum library
|
|
||||||
- [fixed] do not copy more bytes than reserved in get_fs() in lcdproc's machine_*.c
|
|
||||||
- [fixed] update lcdproc's About screen with credits
|
|
||||||
- [fixed] fixes to ula200 build environment and documentation (B. Walle)
|
|
||||||
- [fixed] update g15 driver to be compatible with g15daemon > 1.2 (Anthony J. Mirabella)
|
|
||||||
- [fixed] allow compiling with LDFLAG "--as-needed" (Robert Buchholz)
|
|
||||||
- [fixed] optimize MtxOrb flush()
|
|
||||||
- [fixed] make MtxOrb use Brightness and OffBrightness like CFontzPacket
|
|
||||||
- [fixed] make Brightness & OffBrightness run-time configurable in CFontz & MtxOrb
|
|
||||||
- [fixed] add support for Iface and ProcSize screens for OS X / Darwin (Eric Pooch)
|
|
||||||
- [fixed] update & fix serialVFD driver (Stefan Herdler)
|
|
||||||
- [added] Hitachi SP14Q002 support & ConnectionType setting for sed1330 (Benjamin Wiedmann)
|
|
||||||
- [fixed] replace obsolete index() by strchr() (Guillaume LECERF)
|
|
||||||
- [fixed] fixes for CwLinux driver (Gideon Tsang)
|
|
||||||
- [added] new ConnectionType vdr-wakeup in hd44780 driver (originally Frank Jepsen)
|
|
||||||
- [fixed] fixes for the hd44780-serial drivers (Matteo Pillon)
|
|
||||||
- [added] new options for the hd44780 driver (Frank Jepsen)
|
|
||||||
- [added] new driver for text based serial Point of Sale displays (Eric Pooch)
|
|
||||||
- [added] new 2-line bignum mode using 6 user defined characters (Robin Gilks)
|
|
||||||
- [fixed] fix custom characters [with NewFirmware=yes] & backlight in CFontz
|
|
||||||
- [added] ea65 - driver for VFD in AOpen XC Cube AV EA65 barebones (Karsten Festag)
|
|
||||||
- [added] picolcd - driver for Mini-box.com USB LCD picoLCD (Gatewood Green)
|
|
||||||
- [added] new ConnectionType pertelian in hd44780 driver (Matteo Pillon)
|
|
||||||
- [added] new ConnectionType lcd2usb in hd44780 driver
|
|
||||||
- [added] make LCDd's GoodBye message configurable
|
|
||||||
- [removed] remove compile-time option to read configuration from LDAP
|
|
||||||
|
|
||||||
v.0.5.1
|
|
||||||
- [added] config file support in lcdproc client (Andrew Foss)
|
|
||||||
- [fixed] install server & client config files in $(sysconfdir)
|
|
||||||
- [added] new client lcdvc: virtual console on LCD
|
|
||||||
- [fixed] convert adv_bignum library to bitwise set_char()
|
|
||||||
- [fixed] adapt drivers to modified bignum library:
|
|
||||||
- [added] CFontz
|
|
||||||
- [added] CFontz633
|
|
||||||
- [added] CFontzPacket
|
|
||||||
- [added] hd44780
|
|
||||||
- [added] IOWarrior
|
|
||||||
- [added] MtxOrb
|
|
||||||
- [added] serialVFD
|
|
||||||
- [added] tyan
|
|
||||||
- [added] add iface screen(s) to lcdproc client (Andrew Foss/Markus Dolze)
|
|
||||||
- [fixed] update sample Perl clients
|
|
||||||
- [fixed] fix LCDd crash on shutdown of clients using "menu_set_main" (Andrew Foss)
|
|
||||||
- [fixed] fix sock_connect() to allow 0 as legal socket (Frederick Nacino)
|
|
||||||
- [fixed] improve serialVFD driver (Stefan Herdler)
|
|
||||||
- [added] add MD8800 driver for LCDs in Medion MD8800 PCs (Stefan Herdler/Martin Møller)
|
|
||||||
- [fixed] make bigclock client screen more flexible: centered, require only 14 chars
|
|
||||||
- [fixed] correct axis mapping logic for joystick driver (Jannis Achstetter)
|
|
||||||
- [fixed] fixes to the CFontz driver
|
|
||||||
- [added] new unified serial sub-driver for hd44780 (Matteo Pillon)
|
|
||||||
- [removed] obsolete hd44780 subdrivers-removed: lcdserializer, picanlcd
|
|
||||||
- [fixed] character mapping for special HD44780 modules (Matteo Pillon)
|
|
||||||
- [added] g15 - driver for LCD in Logitech G15 gaming keyboards (Anthony J. Mirabella)
|
|
||||||
- [added] EyeboxOne - driver for the LCD display on the EyeboxOne (Cedric TESSIER)
|
|
||||||
- [fixed] more flexible parsing of config files: allow spaces around sections and keys
|
|
||||||
- [fixed] updated & extended documentation
|
|
||||||
- [fixed] command line options more synchronizd between server and clients
|
|
||||||
- [fixed] CFontzPacket & CFontz633 support big & little endian systems
|
|
||||||
- [fixed] MtxOrb driver completely rewritten to support used-defined characters
|
|
||||||
- [fixed] CwLnx driver completely rewritten to support Cw1602 LCDs in addition
|
|
||||||
to the CW12232 LCDs
|
|
||||||
- [fixed] more options in lcdproc's config file lcdproc.conf:
|
|
||||||
- [added] time and date formats can be changed using strftime formats
|
|
||||||
- [added] Load screen's LowLoad & HighLoad thresholds
|
|
||||||
- [fixed] revamped lcdexec's menu configuration
|
|
||||||
- [fixed] various little fixes
|
|
||||||
|
|
||||||
v0.5.0
|
|
||||||
This version has split off from unstable-0.4.3. Includes major changes.
|
|
||||||
- [added] LCDd now does dynamic loading of driver modules
|
|
||||||
- [fixed] New API in use
|
|
||||||
- [added] LCDd will use fill-in functions for drivers that don't support a certain
|
|
||||||
function. Available for: vbar, hbar, bignum, heartbeat, icon, cursor.
|
|
||||||
- [fixed] Server internal functions cleaned up, moved to other files etc.
|
|
||||||
- [fixed] Menu system rewritten
|
|
||||||
- [added] Client-supplied menus are now supported
|
|
||||||
- [fixed] Key support improved: now keys have descriptive names, not just a letter
|
|
||||||
anymore.
|
|
||||||
- [added] Reloading of configuration and drivers by sending a SIGHUP. Probably
|
|
||||||
needs improvement ;)
|
|
||||||
- [fixed] HD44780 output register support on winamp wiring
|
|
||||||
- [fixed] Reporting levels are now used more consistently
|
|
||||||
- [added] lcdexec client added
|
|
||||||
- [fixed] Display update frequency is now exactly 8Hz. Key scan frequency increased
|
|
||||||
to 32Hz.
|
|
||||||
- [fixed] Priority scheme changed. Priority classes are now used, that indicate what
|
|
||||||
kind of a screen we're dealing with. More useful for interactive clients.
|
|
||||||
- [added] better support for operating systems other than Linux: *BSD, Darwin
|
|
||||||
- [added] menu support for lcdproc client (configure option)
|
|
||||||
- [added] Added CFontz633 driver for CrytalFontz CFA633
|
|
||||||
- [added] Added CFontzPacket driver fro CrystalFontz CFA-633, CFA-631, CFA-635
|
|
||||||
- [added] Added glcdlib meta-driver for all LCDs supported by graphlcd-base
|
|
||||||
- [added] Added icp_a106 driver for A106 alarm/LCD boards in 19" racks by ICP
|
|
||||||
- [added] Added imon driver for iMON IR/VFD Modules from Silverstone, Uneed, ...
|
|
||||||
- [added] Added IOWarrior driver for IOWarrior USB controllers
|
|
||||||
- [added] Added lcterm driver for serial LCD terminal from Neumark Elektronik
|
|
||||||
- [added] Added ms6931 driver for MSI-6931 displays in 1U rack servers by MSI
|
|
||||||
- [added] Added mtc_s16209x driver for MTC-S16209x by Microtips Technology Inc
|
|
||||||
- [added] Added NoritakeVFD driver for Noritake VFD Device CU20045SCPB-T28A
|
|
||||||
- [added] Added pyramid driver for Pyramid LC-Displays
|
|
||||||
- [added] Added serialVFD driver for NEC FIPC8367 based serial VFDs
|
|
||||||
- [added] Added tyan driver for LCDs in Tyan Barebone GS series
|
|
||||||
- [added] Added ula200 driver for the USB board ULA-200 from ELV
|
|
||||||
- [added] Added xosd driver for On Screen Display on X
|
|
||||||
- [added] Added HD44780 subdriver bwctusb for USB-to-LCD converters from BWCT
|
|
||||||
- [added] Added HD44780 subdriver lcdserializer for an serial-LCD converter
|
|
||||||
- [added] Added HD44780 subdriver i2c to conned LCDs using the I2C bus
|
|
||||||
- [added] Added HD44780 subdriver lis2 for the LIS2 serial-to-USB converter
|
|
||||||
|
|
||||||
v0.4.3
|
|
||||||
- [removed] Removed possibility of passing arguments to the drivers from the
|
|
||||||
command line, which can be done in the configuration file now
|
|
||||||
- [added] Added configuration file support
|
|
||||||
- [added] Added ability of dropping root privileges to LCDd
|
|
||||||
- [added] Added LCDM001 driver (kernelconcepts.de)
|
|
||||||
- [added] Added Toshiba T6963 driver
|
|
||||||
- [added] Added Seiko-Epson SED 1520 driver
|
|
||||||
- [added] Added Seiko-Epson SED 1330 driver
|
|
||||||
- [added] Added STV5730 driver composite TV signal character generation driver
|
|
||||||
- [fixed] Modified the CFontz driver so that the new ROM version is
|
|
||||||
supported
|
|
||||||
- [added] Added ASCII emulation of BigNum to the drivers that did not
|
|
||||||
support custom characters
|
|
||||||
- [added] Added ability of configuring (rearranging) the keypad of MtxOrb
|
|
||||||
displays
|
|
||||||
- [added] Added .lircrc location to the options of the lirc driver
|
|
||||||
- [fixed] Fixed backlight code (partly rewritten)
|
|
||||||
- [fixed] Fixed heartbeat code (completely rewritten analogous to
|
|
||||||
the backlight code)
|
|
||||||
- [added] Added init scripts for debian and Redhat/Mandrake
|
|
||||||
- [added] Added EPM list file so that you can use EPM
|
|
||||||
(http://www.easysw.com/epm) to generate packages of LCDproc
|
|
||||||
- [added] Added documentation in docbook format
|
|
||||||
(LCDproc User's Guide - docs/lcdproc-user)
|
|
||||||
- [fixed] Ported some screens of lcdproc to *BSD.
|
|
||||||
- [fixed] Ported the parallel port functions in port.h to *BSD.
|
|
||||||
|
|
||||||
v0.4.2:
|
|
||||||
- [removed] Removed multiple output driver support - to simplify life
|
|
||||||
- [fixed] Removed use of sprintf() (in favor of snprintf) for security
|
|
||||||
- [added] Added ability to use defined port and address to listen on
|
|
||||||
(for security) - now defaults to 127.0.0.1
|
|
||||||
- [added] Revamped curses driver: now supports color; has border; and
|
|
||||||
can be (with recompile) placed anywhere on screen it fits
|
|
||||||
- [added] Added --waittime server argument. You can now specify how long
|
|
||||||
a screen should stay on the display. The default is 64 ticks or
|
|
||||||
8 seconds.
|
|
||||||
- [added] Fixed compile problems on non-Linux platforms where cfmakeraw,
|
|
||||||
CBAUD, and ioperm don't exist. All drivers now use the same code
|
|
||||||
to initialize a serial port.
|
|
||||||
|
|
||||||
v0.4.1:
|
|
||||||
- [added] Changed protocol to 0.3 because we now accept both -foo and foo
|
|
||||||
as argument introducers. in 0.4-pre10, these were changed
|
|
||||||
from foo to -foo and this broke many clients. This change
|
|
||||||
should fix that and be backward/forward compatible.
|
|
||||||
- [added] Added a noop function to the protocol. This is useful for writing
|
|
||||||
shell script clients of LCDproc.
|
|
||||||
- [added] Changed the shared sock_send_string function to NOT send the
|
|
||||||
ending NUL ('\0') byte with the string. This was confusing
|
|
||||||
in Perl clients which saw NUL's as the first character of
|
|
||||||
each reply. WARNING: The LCDPROC client depended on this
|
|
||||||
behavior, your client may too. Use the newline instead.
|
|
||||||
See the code in clients/lcdproc/main.c (look for "switch(buf[i])")
|
|
||||||
to see one way to handle this. This should allow new clients
|
|
||||||
to connect to old servers and vice-versa.
|
|
||||||
- [added] Messed with include structure in .c files. It should no longer
|
|
||||||
be necessary to specify ../.. to get to shared code headers.
|
|
||||||
Also, since we are using automake, the global config.h can be
|
|
||||||
found with just #include "config.h" as it's location is included
|
|
||||||
in a -I to the compilers. As a result "make distcheck" now works.
|
|
||||||
- [added] Added support for client_add_key and friends. Clients MUST now
|
|
||||||
request keys to get notified. Keys are NO LONGER broadcast to all
|
|
||||||
clients. Keys are now tied to a SCREEN and CLIENT. There are new
|
|
||||||
commands (screen_add_key, screen_del_key) to bind keys to a
|
|
||||||
screen. If the current screen has requested the key just pressed,
|
|
||||||
the client gets the key and no other client gets it. If the current
|
|
||||||
screen has not requested the current key, then the key is broadcast
|
|
||||||
to all clients who requested that key with client_add_key. Clients
|
|
||||||
might want to request a "hotkey" with client_add_key so they will
|
|
||||||
be notified of that key no matter what screen is currently on the
|
|
||||||
display, and then request whatever other keys a screen uses with
|
|
||||||
screen_add_key.
|
|
||||||
- [added] Added driver for Matrix Orbital GLK12232-25 graphical display.
|
|
||||||
Display is run in text mode since there isn't enough information in
|
|
||||||
the widgets. If we knew the max width/height of an hbar/vbar, we
|
|
||||||
could use graphical vbar/hbar's. Oh well. BigNums' look really
|
|
||||||
cool though. You'll need some additional characters in the "Small Font"
|
|
||||||
font (and the BigNumbers font) for this to work.
|
|
||||||
- [added] Rewrote Big Number Clock function in chrono.c. Many problems with
|
|
||||||
it have been fixed. It now uses number value 10 to display a colon
|
|
||||||
in between the digits. Don't know what this will do on a the MtxOrb
|
|
||||||
driver. GLK driver draws a colon.
|
|
||||||
- [added] Cleaned up the CPU GRAPH (G) function in cpu.c and made get_load take
|
|
||||||
a 'struct load' from the caller to save the last time values. This
|
|
||||||
allows two callers (CPU GRAPH and CPU LOAD) to call get_load and
|
|
||||||
both get reaosonable values. Without this, CPU GRAPH was always
|
|
||||||
getting 0 because it was called immediatly after CPU LOAD called
|
|
||||||
get_load and no clock ticks had gone by.
|
|
||||||
- [added] Changed --enable-debug autoconf option to be processed correctly.
|
|
||||||
Debug now turns on -g and turns off -O6
|
|
||||||
- [added] Lots of other little fixes.
|
|
||||||
|
|
||||||
v0.4-pre10:
|
|
||||||
- [added] Metar client added (Weather information)
|
|
||||||
- [added] Linux infrared control (LIRC) driver added.
|
|
||||||
- [added] "rotating slash" heartbeat mode (looks weird on CFontz displays)
|
|
||||||
Use "screen_set s -heartbeat slash" to use this.
|
|
||||||
- [fixed] Switched to client-server protocol V0.2, so arguments can come in
|
|
||||||
any order, and require a "-" on the front. Instead of
|
|
||||||
"widget_set s w 1 2 foo", use "widget_set s w -x 1 -y 2 -text foo".
|
|
||||||
- [fixed] Server info screen no longer enabled by default.
|
|
||||||
- [fixed] Merged Andrew McMeikan's HD44780 driver changes
|
|
||||||
- [removed] Removed WHATSNEW
|
|
||||||
- [added] Added ChangeLog (okay, fine, I renamed WHATSNEW and typed a few
|
|
||||||
entries into it :)
|
|
||||||
|
|
||||||
V0.4-pre9:
|
|
||||||
- [fixed] small fixes for irix
|
|
||||||
- [fixed] Added flag in LCDd to shut off server screen:
|
|
||||||
"-i off" or "--serverinfo off"
|
|
||||||
- [added] Wirz SLI driver
|
|
||||||
- [added] 16x2 support (server only)
|
|
||||||
- [added] MtxOrb generic output support in driver
|
|
||||||
- [fixed] Misc libc5 fixes
|
|
||||||
- [added] support for arbitrary display sizes; anything 16-80 characters
|
|
||||||
wide, and 2-25 characters tall. (doesn't work if you try to use
|
|
||||||
a display size bigger than your LCD.. :)
|
|
||||||
- [fixed] curses driver looks slightly better (titles)
|
|
||||||
- [fixed] sizes > 20x4 no longer crash
|
|
||||||
|
|
||||||
V0.4-pre8:
|
|
||||||
- [fixed] LCDd gives more updated info in the connect string:
|
|
||||||
cell size, lcd dimensions.
|
|
||||||
- [fixed] bargraphs are now the correct length on CFontz displays, in the main
|
|
||||||
lcdproc client. For other clients, please parse the connect string!
|
|
||||||
- [fixed] MtxOrb driver supports simultaneous vbars/hbars now, with a
|
|
||||||
mechanism to automatically use custom characters for as many
|
|
||||||
as possible.
|
|
||||||
- [added] 20x2 support in LCDd! Use "--type 20x2".
|
|
||||||
(LCDd --type 20x2 -d MtxOrb )
|
|
||||||
- [fixed] LCDd can change backlight brightness instead of shutting it "off"
|
|
||||||
- [fixed] HD44780 should work again (LCDd forks earlier now.. oops :)
|
|
||||||
- [added] 20x2 support in lcdproc client for the following screens:
|
|
||||||
C G T M X D B S U A
|
|
||||||
Support will not be added for K and O screens.
|
|
||||||
- [added] BSD support (?)
|
|
||||||
- [fixed] 20x4 screens should display correctly on 40x4 displays
|
|
||||||
|
|
||||||
V0.4-pre7: new driver
|
|
||||||
- [added] CrystalFontz (CFontz) LCD driver added
|
|
||||||
- [fixed] Backlight control improved
|
|
||||||
- [added] Brightness control added
|
|
||||||
|
|
||||||
V0.4-pre6:
|
|
||||||
- [added] Backlight control added. Modes so far are "on", "off", and "open".
|
|
||||||
Client commands are "on", "off", "toggle", "blink", and "flash".
|
|
||||||
- [fixed] Main clients' screen titles now include hostname
|
|
||||||
- [added] New sample client: fortune.pl
|
|
||||||
- [fixed] Added changes from David Glaude:
|
|
||||||
- [added] IRman support
|
|
||||||
- [added] Big Digit support (MtxOrb driver doesn't display it correctly yet)
|
|
||||||
- [added] Big cloc[K] screen
|
|
||||||
- [fixed] MtxOrb serial speed is configurable with "--speed"
|
|
||||||
- [fixed] misc bugfixes
|
|
||||||
- [added] ... more
|
|
||||||
|
|
||||||
V0.4-pre5:
|
|
||||||
- [fixed] Fixed bug which could take server down with a dead client
|
|
||||||
- [fixed] Fixed small scroller bug
|
|
||||||
- [added] Added "frame" widgets.. use "-in <frame_name>" after widget_add
|
|
||||||
to put something in a frame.
|
|
||||||
- [added] The disk screen is back!
|
|
||||||
- [removed] Frame rendering isn't finished.. the renderer probably needs a
|
|
||||||
complete rewrite. Any volunteers? :)
|
|
||||||
|
|
||||||
V0.4-pre4:
|
|
||||||
- [added] Server menus (fairly small so far)
|
|
||||||
- [added] Ability to shut down, reboot, change some options, etc (menu only)
|
|
||||||
- [fixed] Driver arguments no longer required
|
|
||||||
- [fixed] Curses driver doesn't start server in background any more...
|
|
||||||
- [fixed] Argument handling fixed...
|
|
||||||
- [fixed] Drivers support "--help" for command-line info
|
|
||||||
|
|
||||||
V0.4-pre3:
|
|
||||||
- [added] Scroller widgets
|
|
||||||
- [fixed] Proper errno messages...
|
|
||||||
- [fixed] "make install" should work now
|
|
||||||
- [fixed] Joystick driver allows key remapping
|
|
||||||
- [added] Screen "durations" are actually *used* now. (oops)
|
|
||||||
- [added] Initial support for screen priorities (strict priority queue)
|
|
||||||
- [fixed] Misc (but annoying!) bugs fixed, which hadn't yet affected anything
|
|
||||||
- [added] Drivers support parameters now (MtxOrb, joy, at least)
|
|
||||||
|
|
||||||
V0.4-pre2:
|
|
||||||
- [fixed] Memory leaks fixed
|
|
||||||
- [added] Memory "top" screen (S)
|
|
||||||
- [added] Titles now autoscroll
|
|
||||||
- [fix] Fixed small screen-visibility bug (clients weren't always
|
|
||||||
notified of screen cycles)
|
|
||||||
- [added] Heartbeat modes implemented. Clients can remove it with
|
|
||||||
widget_del my_screen heartbeat
|
|
||||||
or turn it back on with
|
|
||||||
widget_add my_screen heartbeat " "
|
|
||||||
Note that the client only has control over this when the heartbeat
|
|
||||||
is in "open" mode. (currently, it always is)
|
|
||||||
|
|
||||||
V0.4-pre1:
|
|
||||||
* Too much to mention...
|
|
||||||
@@ -1,300 +0,0 @@
|
|||||||
-- REALLY-QUICK START --------------------------------------------------
|
|
||||||
|
|
||||||
If you're in a desperate hurry type:
|
|
||||||
./configure --enable-drivers=all
|
|
||||||
make
|
|
||||||
|
|
||||||
And if you start wondering why it doesn't work, come back and read the
|
|
||||||
rest of the file. 8)
|
|
||||||
|
|
||||||
|
|
||||||
-- PREREQUISITES -----------------------------------------------------
|
|
||||||
|
|
||||||
First read the README if you haven't already.
|
|
||||||
|
|
||||||
Please take a few minutes to read the user guide located at
|
|
||||||
http://lcdproc.sourceforge.net/docs/
|
|
||||||
|
|
||||||
For the details on supported platforms, see the PLATFORM SPECIFIC section
|
|
||||||
of this file.
|
|
||||||
|
|
||||||
In order to compile LCDproc, you'll need the following programs:
|
|
||||||
|
|
||||||
* A C compiler which supports C99, we recommend GCC. Most Linux or BSD systems
|
|
||||||
come with GCC.
|
|
||||||
|
|
||||||
* GNU Make. It is available for all major distributions. If you want to
|
|
||||||
compile it yourself, see http://www.gnu.org/software/make/make.html .
|
|
||||||
|
|
||||||
* The GNU autotools, that is automake and autoconf. They are only required
|
|
||||||
if you want to build LCdproc directory from CVS.
|
|
||||||
The GNU autotools are available for all major distributions. If you want
|
|
||||||
to compile them yourself, see
|
|
||||||
http://www.gnu.org/software/autoconf/ and
|
|
||||||
http://www.gnu.org/software/automake/.
|
|
||||||
|
|
||||||
Depending on the ./configure options and your choice of drivers, you will
|
|
||||||
need some additional programs or libraries installed:
|
|
||||||
|
|
||||||
* DocBook XML converter "xmlto" if you want to create the documentation
|
|
||||||
or Doxygen when used with --enable-doxygen, also see
|
|
||||||
http://cyberelk.net/tim/software/xmlto/ and
|
|
||||||
http://www.stack.nl/~dimitri/doxygen/
|
|
||||||
|
|
||||||
* libusb if you --enable-libusb, see http://libusb.sourceforge.net/
|
|
||||||
|
|
||||||
* G15daemon, libg15 and libg15render (>= 1.1.1) for use with the 'g15' driver,
|
|
||||||
see http://www.g15tools.com/
|
|
||||||
|
|
||||||
* GraphLCD and GLCDprocDriver for use with the 'glcdlib' driver, see
|
|
||||||
http://projects.vdr-developer.org/projects/graphlcd/ and
|
|
||||||
http://lucianm.github.com/GLCDprocDriver/
|
|
||||||
|
|
||||||
* libirman for use with the 'irman' driver, see
|
|
||||||
http://www.evation.com/libirman/libirman.html for the home page and
|
|
||||||
http://www.lirc.org/software/snapshots/ for current downloads
|
|
||||||
|
|
||||||
* LIRC for use with the 'lirc' driver, see http://www.lirc.org/
|
|
||||||
|
|
||||||
* ncurses for use with the 'curses' driver, see
|
|
||||||
http://www.gnu.org/software/ncurses/
|
|
||||||
|
|
||||||
* svgalib for use with the 'svga' driver, see http://www.svgalib.org/
|
|
||||||
|
|
||||||
* libftdi and libusb for use with the 'ula200', 'lis', and 'i2500vfd' driver,
|
|
||||||
see http://www.intra2net.com/en/developer/libftdi/ and
|
|
||||||
http://libusb.sourceforge.net/
|
|
||||||
|
|
||||||
* XOSD for use with the 'xosd' driver, see http://sourceforge.net/projects/libxosd/ ,
|
|
||||||
as well as an x11 implementation, more precisely libX11 and libXext.
|
|
||||||
|
|
||||||
|
|
||||||
-- DISPLAYS -----------------------------------------------------------
|
|
||||||
|
|
||||||
Many different displays (or better said: output devices) are supported.
|
|
||||||
Some of these devices also support input, for example with a keypad.
|
|
||||||
There are drivers for input-only devices, too.
|
|
||||||
|
|
||||||
For LCDd (the server) to use the device, it needs to load a driver. The
|
|
||||||
drivers are so called 'shared modules', that usually have an extension
|
|
||||||
of .so . The drivers to be loaded should be specified in the config file
|
|
||||||
(by one or more Driver= lines), or on the command line. The command line
|
|
||||||
should only be used to override things in the config file. The drivers
|
|
||||||
should be in a directory that is indicated by the DriverPath= line in
|
|
||||||
the configfile.
|
|
||||||
|
|
||||||
Depending on what kind of LCD display that you have, there are several
|
|
||||||
sources for information. If your LCD display came with a manual, this
|
|
||||||
is a great place to start. If you don't have a manual, then you must
|
|
||||||
find out what kind of display this is, and check the related
|
|
||||||
information:
|
|
||||||
|
|
||||||
HD44780 and compatible:
|
|
||||||
read the HD44780 section in the LCDproc User's Guide (docs/lcdproc-user)
|
|
||||||
or alternatively see http://www.robijn.net/lcdproc/
|
|
||||||
|
|
||||||
If you still have problems you could take a look at the comments in the
|
|
||||||
driver source code in server/drivers/. You may have some good indications
|
|
||||||
there.
|
|
||||||
|
|
||||||
You may want to take a look at LCDproc's hardware page at
|
|
||||||
http://lcdproc.org/hardware.php3 for details. Several
|
|
||||||
different types of displays are now supported.
|
|
||||||
|
|
||||||
|
|
||||||
-- BUILDING LCDPROC -------------------------------------------------
|
|
||||||
|
|
||||||
--- Preparing a CVS distro ---
|
|
||||||
If you retrieved these files from the CVS, you will first need to run:
|
|
||||||
sh ./autogen.sh
|
|
||||||
|
|
||||||
--- Configuration ---
|
|
||||||
The simplest way of doing it is with:
|
|
||||||
./configure
|
|
||||||
But it may not do what you want, so please take a few seconds to type:
|
|
||||||
./configure --help
|
|
||||||
And read the available options, especially --enable-drivers
|
|
||||||
|
|
||||||
--- Compilation ---
|
|
||||||
Run make to build the server and all clients
|
|
||||||
make
|
|
||||||
|
|
||||||
If you only want to compile the clients, you can omit to compile the
|
|
||||||
server:
|
|
||||||
make clients
|
|
||||||
|
|
||||||
Similarly, if you only want to compile the server, you can omit to
|
|
||||||
compile the clients:
|
|
||||||
make server
|
|
||||||
|
|
||||||
Depending on your system, LCDproc will build in a few seconds to a
|
|
||||||
few minutes. It's not very big.
|
|
||||||
|
|
||||||
If you want to, you can install it (if you're root) by typing:
|
|
||||||
make install
|
|
||||||
|
|
||||||
This will install the binaries and the man pages in the directory you
|
|
||||||
specified in configure.
|
|
||||||
You may have to copy the configuration file (LCDd.conf) to /etc
|
|
||||||
(or /usr/local/etc) manually.
|
|
||||||
|
|
||||||
|
|
||||||
-- CREATING DISTRIBUTION SPECIFIC PACKAGES --------------------------
|
|
||||||
|
|
||||||
Instead of manually configuring, compiling and installing LCDproc you
|
|
||||||
may use the support files in the LCDproc source tree to create an
|
|
||||||
installation package specific to your distribution
|
|
||||||
|
|
||||||
Debian:
|
|
||||||
- Rename the .tgz file with the sources to lcdproc_VERSION.orig.tar.gz
|
|
||||||
cp lcdproc-VERSION.tgz lcdproc_VERSION.orig.tar.gz
|
|
||||||
- Extract the source tar ball
|
|
||||||
tar xvzf lcdproc_VERSION.orig.tar.gz
|
|
||||||
- Copy the debian/ directory below scripts/ to the root of the
|
|
||||||
source tree
|
|
||||||
cp -a lcdproc-VERSION/scripts/debian lcdproc-VERSION/
|
|
||||||
- Generate .deb debian package
|
|
||||||
cd lcdproc-VERSION/
|
|
||||||
dpkg-buildpackage -rfakeroot -sd
|
|
||||||
cd ..
|
|
||||||
This creates a file named lcdproc_VERSION-RELEASE_ARCH.deb
|
|
||||||
that contains the LCDproc suite as a regular Debian package.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- PLATFORM SPECIFIC ------------------------------------------------
|
|
||||||
|
|
||||||
The lcdproc crew has tried to support a number of platforms. Platforms
|
|
||||||
that are very non-standard are not and probably will never be supported.
|
|
||||||
Both, the server with its drivers and the clients, have their own
|
|
||||||
difficulties in porting. Here's are the prerequisites for both:
|
|
||||||
|
|
||||||
--- Client ---
|
|
||||||
The client should run on any POSIX compliant system.
|
|
||||||
It has been successfully tested on:
|
|
||||||
Linux 2.2.x - 2.6.x, FreeBSD 6.x - 8.1, NetBSD 1.5 & 3.x, OpenBSD 3.0,
|
|
||||||
Darwin, Solaris and MacOS.
|
|
||||||
|
|
||||||
--- Server ---
|
|
||||||
The server needs to talk to the LCD display. At this time, it works
|
|
||||||
on very little more than on the Intel i386 (PC Compatible)
|
|
||||||
architecture. It has been successfully tested on:
|
|
||||||
Linux 2.2.x - 2.6.x, FreeBSD 6.x - 8.1, NetBSD 1.5 & 3.x, OpenBSD 3.0,
|
|
||||||
Darwin, Solaris and MacOS.
|
|
||||||
|
|
||||||
Here are some comments specific to each platform that LCDproc has been
|
|
||||||
tested on.
|
|
||||||
|
|
||||||
--- Linux ---
|
|
||||||
Nothing special to say, everything should go well.
|
|
||||||
|
|
||||||
You may not be able to compile all drivers on something else than i386
|
|
||||||
if your linux installation does not have ioperm, inb and outb commands.
|
|
||||||
./configure should leave all drivers that need those functions out
|
|
||||||
(drivers for parallel port displays), so that LCDd should compile anyway.
|
|
||||||
|
|
||||||
--- NetBSD ---
|
|
||||||
You need to use GNU Make instead of NetBSD's make.
|
|
||||||
Remember to type gmake instead of make to compile LCDproc.
|
|
||||||
The server will probably only compile on NetBSD/i386.
|
|
||||||
|
|
||||||
If you try to run LCDd and you get this error:
|
|
||||||
Bus error (core dumped)
|
|
||||||
It is likely that you did not have the right permission to access the ports.
|
|
||||||
Try starting the program as root.
|
|
||||||
|
|
||||||
--- OpenBSD ---
|
|
||||||
You need to use GNU Make instead of OpenBSD's make.
|
|
||||||
Remember to type gmake instead of make to compile LCDproc.
|
|
||||||
The server will probably only compile on OpenBSD/i386.
|
|
||||||
|
|
||||||
--- FreeBSD ---
|
|
||||||
It should compile fine on i386. Must be started as root to be able to use
|
|
||||||
parallel and USB ports.
|
|
||||||
|
|
||||||
--- Other platforms ---
|
|
||||||
If the build process fails, but you do know how to link a loadable
|
|
||||||
module by hand, you can add the appropriate flags et cetera into
|
|
||||||
acinclude.m4. Experience required. Please let us know if you got it
|
|
||||||
working on a previously unsupported system, so we can include it in a
|
|
||||||
next release.
|
|
||||||
|
|
||||||
|
|
||||||
-- RUNNING LCDPROC -----------------------------------------------------
|
|
||||||
|
|
||||||
--- Configuration file ---
|
|
||||||
|
|
||||||
The first thing that you need to do is to modify the configuration file
|
|
||||||
for your server. A example file (LCDd.conf) is available in the tarball.
|
|
||||||
The comments present in this file should give you indications on what
|
|
||||||
to do.
|
|
||||||
|
|
||||||
--- Starting the server ---
|
|
||||||
|
|
||||||
If you're in the LCDproc source directory, and have just built it, run:
|
|
||||||
server/LCDd -c path/to/config/file
|
|
||||||
|
|
||||||
For security reasons, LCDd by default only accepts connections from
|
|
||||||
localhost (127.0.0.1), it will not accept connections from other computers on
|
|
||||||
your network / the Internet. You can change this behaviour in the
|
|
||||||
configuration file.
|
|
||||||
|
|
||||||
--- Starting the client(s) ---
|
|
||||||
|
|
||||||
Then, you'll need some clients. LCDproc comes with a few, of which the
|
|
||||||
'lcdproc' client is the main client:
|
|
||||||
clients/lcdproc/lcdproc -f C M T L
|
|
||||||
|
|
||||||
This will run the LCDproc client, with the [C]pu, [M]emory,
|
|
||||||
[T]ime, and [L]oad screens. The option "-f" causes it not to daemonize,
|
|
||||||
but run in the foreground.
|
|
||||||
|
|
||||||
By default, the client tries to connect to a server located on localhost
|
|
||||||
and listening to port 13666. To change this, use the -s and -p options.
|
|
||||||
|
|
||||||
|
|
||||||
-- PUTTING LCDPROC IN SYSTEM STARTUP -----------------------------------
|
|
||||||
|
|
||||||
It's nice to have LCDproc start when the computer boots, so here's how
|
|
||||||
to do it:
|
|
||||||
|
|
||||||
WARNING: Make sure you have modified the configuration file (/etc/LCDd.conf)
|
|
||||||
so that LCDd enters the background mode.
|
|
||||||
Otherwise LCDd will lock your system.
|
|
||||||
|
|
||||||
Slackware:
|
|
||||||
Add lines to your /etc/rc.d/rc.local, such as the following:
|
|
||||||
echo "Starting LCDd..."
|
|
||||||
/usr/local/sbin/LCDd -c /etc/LCDd.conf
|
|
||||||
echo "Starting lcdproc..."
|
|
||||||
/usr/local/bin/lcdproc C M X &
|
|
||||||
|
|
||||||
Debian: (the hard way)
|
|
||||||
- Copy (as root) the debian init script from the scripts/ directory of the
|
|
||||||
sources to /etc/init.d
|
|
||||||
(cp scripts/init-LCDd.debian /etc/init.d/LCDd && \
|
|
||||||
cp scripts/init-lcdproc.debian /etc/init.d/lcdproc)
|
|
||||||
- Run (as root): update-rc.d LCDd defaults
|
|
||||||
This will create symlinks to start and stop the daemon, resp.
|
|
||||||
from /etc/rc[2-5].d/S50LCDd to /etc/init.d/LCDd, and from
|
|
||||||
/etc/rc[016].d/K50LCDd to /etc/init.d/LCDd.
|
|
||||||
- Run (as root): update-rc.d lcdproc defaults
|
|
||||||
This will create symlinks to start and stop the lcdproc client, resp.
|
|
||||||
from /etc/rc[2-5].d/S50lcdproc to /etc/init.d/lcdproc, and from
|
|
||||||
/etc/rc[016].d/K50lcdproc to /etc/init.d/lcdproc.
|
|
||||||
|
|
||||||
Debian: (the easy way)
|
|
||||||
- Install the previously created .deb package (as root)
|
|
||||||
dpkg -i lcdproc_VERSION-RELEASE_ARCH.deb
|
|
||||||
|
|
||||||
Redhat / Mandrake:
|
|
||||||
- Copy the scripts:
|
|
||||||
cp scripts/init-lcdd.rpm /etc/rc.d/init.d/lcdd && \
|
|
||||||
cp scripts/init-lcdproc.rpm /etc/rc.d/init.d/lcdproc)
|
|
||||||
- enable the scripts with e.g. linuxconf or create the symlinks manually
|
|
||||||
|
|
||||||
FreeBSD:
|
|
||||||
- If you install from the ports collection startup script are
|
|
||||||
installed by default.
|
|
||||||
|
|
||||||
That's all the OS's we've actually done this with so far.
|
|
||||||
-55
@@ -1,55 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
## set automake strictness to 'foreign'
|
|
||||||
AUTOMAKE_OPTIONS = foreign
|
|
||||||
|
|
||||||
SUBDIRS = shared clients server docs scripts
|
|
||||||
|
|
||||||
sysconf_DATA = LCDd.conf
|
|
||||||
|
|
||||||
EXTRA_DIST = $(sysconf_DATA) CREDITS contrib
|
|
||||||
|
|
||||||
|
|
||||||
dist-hook:
|
|
||||||
rm -rf `find $(distdir)/contrib -name CVS`
|
|
||||||
|
|
||||||
|
|
||||||
## convenience targets
|
|
||||||
|
|
||||||
.PHONY: $(SUBDIRS) install-server install-clients
|
|
||||||
|
|
||||||
$(SUBDIRS):
|
|
||||||
$(MAKE) -C $@
|
|
||||||
|
|
||||||
clients server: shared
|
|
||||||
|
|
||||||
install-server: server
|
|
||||||
$(MAKE) -C server install
|
|
||||||
$(MAKE) -C docs install-server-man
|
|
||||||
|
|
||||||
install-clients: clients
|
|
||||||
$(MAKE) -C clients install
|
|
||||||
$(MAKE) -C docs install-client-man
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: install-html-guides install-html-developerguide install-html-userguide
|
|
||||||
|
|
||||||
install-html-guides: install-html-developerguide install-html-userguide
|
|
||||||
|
|
||||||
install-html-developerguide:
|
|
||||||
$(MAKE) -C docs $@
|
|
||||||
|
|
||||||
install-html-userguide:
|
|
||||||
$(MAKE) -C docs $@
|
|
||||||
|
|
||||||
|
|
||||||
.PHONY: dox topleveltags
|
|
||||||
|
|
||||||
dox:
|
|
||||||
$(MAKE) -C docs $@
|
|
||||||
|
|
||||||
topleveltags:
|
|
||||||
$(CTAGS) --format=1 -f - --languages=C --c-kinds=f --recurse=yes server shared clients \
|
|
||||||
| perl -p -e 's/^([^\t]+)\t[^\t]+\/([^\t\/]+)\t(.*)$/$1\t$2\t$3/' > tags
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
[](https://travis-ci.org/lcdproc/lcdproc)
|
|
||||||
|
|
||||||
This is the official repository for the LCDproc project.
|
|
||||||
|
|
||||||
_Note: this project is currently being migrated from Sourceforge. Documentation
|
|
||||||
is still being updated to reflect this and we're still getting our bearings here
|
|
||||||
on GitHub, so please excuse the dust while we set up shop._
|
|
||||||
|
|
||||||
# Introduction
|
|
||||||
|
|
||||||
LCDproc is a client/server suite including drivers for all kinds of nifty LCD
|
|
||||||
devices. The server works with different display sizes and supports several
|
|
||||||
serial devices: Matrix Orbital, Crystal Fontz, Bayrad, LB216, LCDM001
|
|
||||||
(kernelconcepts.de), Wirz-SLI and PIC-an-LCD; some devices connected to the
|
|
||||||
parallel port: HD44780, STV5730, T6963, SED1520 and SED1330; and also some
|
|
||||||
displays connected via USB: CFontzPacket, CwLnx, IOWarrior, LIS2 and BWCT.
|
|
||||||
|
|
||||||
Various clients are available that display things like CPU load, system load,
|
|
||||||
memory usage, uptime, and a lot more.
|
|
||||||
|
|
||||||
LCDproc also supports key or remote control input for controlling the clients.
|
|
||||||
|
|
||||||
The client and the server use a TCP connection to communicate, so it is
|
|
||||||
possible to have a client on a box in Sweden showing its stats on a LCD device
|
|
||||||
in the United States.
|
|
||||||
|
|
||||||
Visit our [website](http://lcdproc.org/) for more information. The project's
|
|
||||||
repository, issue tracking and pull requests can be found at
|
|
||||||
https://github.com/lcdproc/lcdproc. Our mailing list can be found at
|
|
||||||
https://groups.google.com/d/forum/lcdproc-mailing-list.
|
|
||||||
|
|
||||||
LCDproc was originally written by [William Ferrell](mailto:willfe@gmail.com)
|
|
||||||
and [Selene Scriven](mailto:lcdproc@toykeeper.net).
|
|
||||||
|
|
||||||
# Installation
|
|
||||||
|
|
||||||
Refer to [INSTALL](INSTALL) (included with this archive) for installation
|
|
||||||
instructions (including how to connect an LCD to your system).
|
|
||||||
|
|
||||||
# Changes
|
|
||||||
|
|
||||||
Refer to [ChangeLog.md](ChangeLog.md) file for details.
|
|
||||||
|
|
||||||
# Contributing
|
|
||||||
|
|
||||||
If you've found a bug or want to add new functionality to LCDproc, feel free to
|
|
||||||
fork the repository, make your changes and send us a pull request. They're
|
|
||||||
always welcome!
|
|
||||||
|
|
||||||
If you want to help but need some inspiration, take a look at the project's
|
|
||||||
[open issues](https://github.com/lcdproc/lcdproc/issues).
|
|
||||||
|
|
||||||
To learn more about how LCDproc works, first have a look at the docs/
|
|
||||||
directory. Some important things are documented there, but because this is
|
|
||||||
still somewhat a big hacking project, some documentation will be missing ;)
|
|
||||||
|
|
||||||
Please don't hesitate to ask us for help if you're having trouble getting LCDproc
|
|
||||||
working with your hardware or you'd like to contribute to the project but need
|
|
||||||
guidance on how something works or how things fit together. We're a friendly
|
|
||||||
bunch!
|
|
||||||
|
|
||||||
## Mailing List
|
|
||||||
|
|
||||||
We also maintain a [mailing list](https://groups.google.com/d/forum/lcdproc-mailing-list)
|
|
||||||
for development and user discussions. There are several ways to join the mailing list:
|
|
||||||
|
|
||||||
- If you have a Google account, and you're already logged in, browse to
|
|
||||||
https://groups.google.com/d/forum/lcdproc-mailing-list and click "Join this group".
|
|
||||||
|
|
||||||
- If you'd like to subscribe with a non-Google email address, you can either:
|
|
||||||
|
|
||||||
- Browse to https://groups.google.com/forum/#!forum/lcdproc-mailing-list/join
|
|
||||||
and provide your email address, solve the displayed captcha (if any) and
|
|
||||||
click "Subscribe". You may need to click a confirmation link (that Google will
|
|
||||||
mail to the provided address) to actually be subscribed to the mailing list.
|
|
||||||
|
|
||||||
- Send an email to lcdproc-mailing-list+subscribe@googlegroups.com.
|
|
||||||
|
|
||||||
## Code of Merit
|
|
||||||
|
|
||||||
This project adopts the Code of Merit, version 1.0, originally published at
|
|
||||||
http://code-of-merit.org/. Refer to [CODE_OF_MERIT.md](CODE_OF_MERIT.md) for
|
|
||||||
details, but in short, we focus on writing software and leave politics out of
|
|
||||||
it.
|
|
||||||
|
|
||||||
# Special Thanks
|
|
||||||
|
|
||||||
LCDproc wouldn't be possible without the ongoing patience and efforts by its
|
|
||||||
amazing community of developers and users. We'd like to recognize everyone's
|
|
||||||
contributions to the project, and we've tried to list them all in
|
|
||||||
[CREDITS](CREDITS). If we've overlooked your contributions, please let us know
|
|
||||||
so we can attribute your work immediately!
|
|
||||||
|
|
||||||
_From William Ferrell, original developer:_ This project is almost twenty years
|
|
||||||
old as I write this, and I'm so proud of what it's become over the years thanks
|
|
||||||
in no small part to the people (past and present) who not only contributed
|
|
||||||
their work and ideas to the project, but helped to manage and maintain it when
|
|
||||||
I couldn't. To see this project start as a small single-system utility program
|
|
||||||
supporting a single type of device and flourish into a client/server daemon
|
|
||||||
used around the world to drive all sorts of display devices is beyond anything
|
|
||||||
I could have ever hoped for, and I'm eternally grateful to everyone who's
|
|
||||||
contributed over the years. Thank you all for being part of this project and
|
|
||||||
for making it amazing. Here's to another twenty years! :)
|
|
||||||
|
|
||||||
# Legal Stuff
|
|
||||||
|
|
||||||
LCDproc is Copyright (C) 1998-2016 William Ferrell, Selene Scriven and many
|
|
||||||
other contributors.
|
|
||||||
|
|
||||||
This program 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 program 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.
|
|
||||||
|
|
||||||
The file COPYING contains the GNU General Public License. You should have
|
|
||||||
received a copy of the GNU General Public License along with this program; if
|
|
||||||
not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
||||||
Floor, Boston, MA 02110-1301, USA.
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
NOTE: Use of this TODO list is obsolete! A list of things to be done is
|
|
||||||
automatically created by Doxygen. You may create the Doxygen documentation
|
|
||||||
yourself by running the doxygen command from the docs/ directory.
|
|
||||||
|
|
||||||
Ideas for new features can be entered at the IdeaTorrent:
|
|
||||||
http://sourceforge.net/apps/ideatorrent/lcdproc/
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Stuff planned for future releases... (in no particular order)
|
|
||||||
Feel free to help out with any of this stuff! :)
|
|
||||||
Please send a message to the mailing list if you have any question.
|
|
||||||
|
|
||||||
Things for the short term
|
|
||||||
=========================
|
|
||||||
- Use non-standard serial baud rates (57600 and higher) only optional.
|
|
||||||
|
|
||||||
|
|
||||||
Things for the longer term
|
|
||||||
==========================
|
|
||||||
|
|
||||||
lcdproc client
|
|
||||||
--------------
|
|
||||||
|
|
||||||
- allow more than one instance of a screen with different configuration
|
|
||||||
sections (implementation should be possible similar to the one with
|
|
||||||
the drivers in LCDd where File=... points to the original driver file)
|
|
||||||
- more options in the config file (clocks with offsets from localtime, ...)
|
|
||||||
- more options changeable in the lcdproc client menu
|
|
||||||
- rewrite machine_get_fs() in machine_Linux.c to use functions from mntent.h
|
|
||||||
- get rid of MTAB_FILE compile time definition (for Linux & SunOS)
|
|
||||||
|
|
||||||
|
|
||||||
lcdexec client
|
|
||||||
--------------
|
|
||||||
|
|
||||||
more flexbibility: do not just only execute commands, but
|
|
||||||
maybe also display their result in a screen, get a command's
|
|
||||||
parameters interactively using the builtin input menus,
|
|
||||||
confirmation of commands, jumping between commands depending
|
|
||||||
on the output of a command (wizards), ...
|
|
||||||
|
|
||||||
|
|
||||||
Client driver
|
|
||||||
-------------
|
|
||||||
|
|
||||||
An LCDproc client can connect, request the "client" driver, then get
|
|
||||||
all screen information sent to it! This allows things such as logging
|
|
||||||
in remotely and starting up a curses display of LCDproc. It also
|
|
||||||
gives another method for writing drivers. In a sense, it could even
|
|
||||||
let you write and link in new drivers without having to recompile and
|
|
||||||
restart LCDproc...
|
|
||||||
|
|
||||||
Another bonus is that LCDproc will come with a client which can, for
|
|
||||||
example, start up a "client" driver to send "keypresses" from the
|
|
||||||
command line. Or,
|
|
||||||
|
|
||||||
lcdtool -key A
|
|
||||||
|
|
||||||
would have the same result as pressing a key on the keypad.
|
|
||||||
-1207
File diff suppressed because it is too large
Load Diff
-53
@@ -1,53 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Run this to generate all the initial makefiles, etc.
|
|
||||||
|
|
||||||
# set default values for variables
|
|
||||||
: ${AUTOCONF:=autoconf}
|
|
||||||
: ${AUTOHEADER:=autoheader}
|
|
||||||
: ${AUTOMAKE:=automake}
|
|
||||||
: ${ACLOCAL:=aclocal}
|
|
||||||
|
|
||||||
DIE=0
|
|
||||||
|
|
||||||
($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
|
|
||||||
echo
|
|
||||||
echo "**Error**: You must have \`autoconf' installed."
|
|
||||||
echo "Download the appropriate package for your distribution,"
|
|
||||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
|
||||||
DIE=1
|
|
||||||
}
|
|
||||||
|
|
||||||
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
|
|
||||||
echo
|
|
||||||
echo "**Error**: You must have \`automake' installed."
|
|
||||||
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
|
||||||
echo "(or a newer version if it is available)"
|
|
||||||
DIE=1
|
|
||||||
NO_AUTOMAKE=yes
|
|
||||||
}
|
|
||||||
|
|
||||||
# if no automake, don't bother testing for aclocal
|
|
||||||
test -n "$NO_AUTOMAKE" || ($ACLOCAL --version) < /dev/null > /dev/null 2>&1 || {
|
|
||||||
echo
|
|
||||||
echo "**Error**: Missing \`aclocal'. The version of \`automake'"
|
|
||||||
echo "installed doesn't appear recent enough."
|
|
||||||
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
|
||||||
echo "(or a newer version if it is available)"
|
|
||||||
DIE=1
|
|
||||||
}
|
|
||||||
|
|
||||||
if test "$DIE" -eq 1; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Running aclocal ..."
|
|
||||||
$ACLOCAL
|
|
||||||
if grep "^A[CM]_CONFIG_HEADER" configure.ac >/dev/null; then
|
|
||||||
echo "Running autoheader..."
|
|
||||||
$AUTOHEADER
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Running automake ..."
|
|
||||||
$AUTOMAKE --add-missing --copy
|
|
||||||
echo "Running autoconf ..."
|
|
||||||
$AUTOCONF
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
SUBDIRS = examples lcdexec lcdproc lcdvc metar
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
bin_SCRIPTS = fortune.pl iosock.pl tail.pl x11amp.pl lcdident.pl
|
|
||||||
|
|
||||||
EXTRA_DIST = $(bin_SCRIPTS)
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# fortune.pl - an example client for LCDproc
|
|
||||||
|
|
||||||
# This is just a small example of a client for LCDd the
|
|
||||||
# LCDproc server
|
|
||||||
#
|
|
||||||
# Copyright (c) 1999, William Ferrell, Selene Scriven
|
|
||||||
# 2001, David Glaude
|
|
||||||
# 2002, Jonathan Oxer
|
|
||||||
# 2002, Rene Wagner <reenoo@gmx.de>
|
|
||||||
# 2006, Peter Marschall
|
|
||||||
#
|
|
||||||
# This file 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
|
|
||||||
# any later version.
|
|
||||||
#
|
|
||||||
# This file 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 file; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
#
|
|
||||||
|
|
||||||
use 5.005;
|
|
||||||
use strict;
|
|
||||||
use Getopt::Std;
|
|
||||||
use IO::Socket;
|
|
||||||
use Fcntl;
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# Configurable part. Set it according your setup.
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# Path to `fortune' program.
|
|
||||||
my $FORTUNE = "fortune";
|
|
||||||
|
|
||||||
# Host which runs lcdproc daemon (LCDd)
|
|
||||||
my $SERVER = "localhost";
|
|
||||||
|
|
||||||
# Port on which LCDd listens to requests
|
|
||||||
my $PORT = "13666";
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# End of user configurable parts
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
my $progname = $0;
|
|
||||||
$progname =~ s#.*/(.*?)$#$1#;
|
|
||||||
|
|
||||||
# declare functions
|
|
||||||
sub update_text($);
|
|
||||||
sub error($@);
|
|
||||||
sub usage($);
|
|
||||||
|
|
||||||
|
|
||||||
## main routine ##
|
|
||||||
my %opt = ();
|
|
||||||
|
|
||||||
# get options #
|
|
||||||
if (getopts('F:s:p:hV', \%opt) == 0) {
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check options
|
|
||||||
usage(0) if ($opt{h});
|
|
||||||
if ($opt{V}) {
|
|
||||||
print STDERR $progname ." version 1.1\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check number of arguments
|
|
||||||
usage(1) if ($#ARGV >= 0);
|
|
||||||
|
|
||||||
|
|
||||||
# set variables
|
|
||||||
$SERVER = defined($opt{s}) ? $opt{s} : $SERVER;
|
|
||||||
$PORT = defined($opt{p}) ? $opt{p} : $PORT;
|
|
||||||
$FORTUNE = defined($opt{F}) ? $opt{F} : $FORTUNE;
|
|
||||||
|
|
||||||
# Connect to the server...
|
|
||||||
my $remote = IO::Socket::INET->new(
|
|
||||||
Proto => 'tcp',
|
|
||||||
PeerAddr => $SERVER,
|
|
||||||
PeerPort => $PORT,
|
|
||||||
)
|
|
||||||
or error(1, "cannot connect to LCDd daemon at $SERVER:$PORT");
|
|
||||||
|
|
||||||
# Make sure our messages get there right away
|
|
||||||
$remote->autoflush(1);
|
|
||||||
|
|
||||||
sleep 1; # Give server plenty of time to notice us...
|
|
||||||
|
|
||||||
print $remote "hello\n";
|
|
||||||
# Note: it's good practice to listen for a response after a print to the
|
|
||||||
# server even if there isn't meant to be one. If you don't, you may find
|
|
||||||
# your program crashes after running for a while when the buffers fill up:
|
|
||||||
my $lcdresponse = <$remote>;
|
|
||||||
#print $lcdresponse;
|
|
||||||
|
|
||||||
# Turn off blocking mode...
|
|
||||||
fcntl($remote, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
# Set up some screen widgets...
|
|
||||||
print $remote "client_set name {$progname}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_add fortune\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_set fortune name {Fortune}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add fortune title title\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set fortune title {Fortune}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add fortune text scroller\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
update_text($remote);
|
|
||||||
|
|
||||||
# Forever, we should do stuff...
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
# Handle input... (spew it to the console)
|
|
||||||
# Also, certain keys scroll the display
|
|
||||||
while (defined(my $input = <$remote>)) {
|
|
||||||
#print $input;
|
|
||||||
|
|
||||||
# Make sure we handle each line...
|
|
||||||
my @lines = split(/\n/, $input);
|
|
||||||
|
|
||||||
foreach my $line (@lines) {
|
|
||||||
next if ( $line =~ /^success$/ );
|
|
||||||
|
|
||||||
# Update just after disappearing
|
|
||||||
if ($line =~ /^ignore (\S)/) {
|
|
||||||
update_text($remote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# And wait a little while before we check for input again.
|
|
||||||
sleep 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
close($remote) or error(1, "close() failed: $!");
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
# update text on LCD
|
|
||||||
sub update_text($)
|
|
||||||
{
|
|
||||||
my $remote = shift;
|
|
||||||
my $text;
|
|
||||||
|
|
||||||
# Grab some text
|
|
||||||
$text = `$FORTUNE` || error(1, "error running `$FORTUNE'.\nPlease check that the path is correct.");
|
|
||||||
# replace new-line by slashes
|
|
||||||
$text =~ s,\n, / ,g;
|
|
||||||
|
|
||||||
# Now, show a fortune...
|
|
||||||
print $remote "widget_set fortune text 1 2 20 4 v 16 {$text}\n";
|
|
||||||
$text = <$remote>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## print out error message and eventually exit ##
|
|
||||||
# Synopsis: error($status, $message)
|
|
||||||
sub error($@)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
my @msg = @_;
|
|
||||||
|
|
||||||
print STDERR $progname . ": " . join(" ", @msg) . "\n";
|
|
||||||
|
|
||||||
exit($status) if ($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## print out usage message and exit ##
|
|
||||||
# Synopsis: usage($status)
|
|
||||||
sub usage($)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
|
|
||||||
print STDERR "Usage: $progname [<options>]\n";
|
|
||||||
if (!$status) {
|
|
||||||
print STDERR " where <options> are\n" .
|
|
||||||
" -s <server> connect to <server> (default: $SERVER)\n" .
|
|
||||||
" -p <port> connect to <port> on <server> (default: $PORT)\n" .
|
|
||||||
" -F <fortune> use <fortune> as fortune program (default: $FORTUNE)\n" .
|
|
||||||
" -h show this help page\n" .
|
|
||||||
" -V display version number\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print STDERR "For help, type: $progname -h\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__END__
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
fortune.pl -- display fortune messages on the LCD
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<fortune.pl>
|
|
||||||
[B<-s> I<server>]
|
|
||||||
[B<-p> I<port>]
|
|
||||||
[B<-F> I<fortune>]
|
|
||||||
[B<-h>]
|
|
||||||
[B<-V>]
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<fortune.pl> is a small example client for LCDd, the lcdproc server.
|
|
||||||
|
|
||||||
It connects to the LCDd daemon and displays fortune cookies as delivered
|
|
||||||
by the well known fortune program.
|
|
||||||
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<-s> I<server>
|
|
||||||
|
|
||||||
Connect to the LCDd daemon at host I<server> instead of the default C<localhost>.
|
|
||||||
|
|
||||||
=item B<-p> I<port>
|
|
||||||
|
|
||||||
Use port I<port> when connecting to the LCDd server instead of the default
|
|
||||||
LCDd port C<13666>.
|
|
||||||
|
|
||||||
=item B<-F> I<fortune>
|
|
||||||
|
|
||||||
Use I<fortune> as the program generation fortune messages instead of the
|
|
||||||
default C<fortune>
|
|
||||||
|
|
||||||
=item B<-h>
|
|
||||||
|
|
||||||
Display a short help page and exit.
|
|
||||||
|
|
||||||
=item B<-V>
|
|
||||||
|
|
||||||
Display fortune.pl's version number and exit.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<fortune(6)>,
|
|
||||||
L<LCDd(8)>
|
|
||||||
|
|
||||||
|
|
||||||
=head1 AUTHORS
|
|
||||||
|
|
||||||
fortune.pl was written by various members of the LCDproc project team;
|
|
||||||
this manual page was written by Peter Marschall.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
use 5.005;
|
|
||||||
use strict;
|
|
||||||
use Getopt::Std;
|
|
||||||
use IO::Socket;
|
|
||||||
use Fcntl;
|
|
||||||
|
|
||||||
# iosock.pl - an example client for LCDproc
|
|
||||||
|
|
||||||
#
|
|
||||||
# This LCDproc client takes a list of machines to ping and and reports
|
|
||||||
# number of those which ping and number of those which do not and their list
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Copyright (c) 1999, William Ferrell, Selene Scriven
|
|
||||||
# 2001, David Glaude
|
|
||||||
# 2001, Jarda Benkovsky
|
|
||||||
# 2002, Jonathan Oxer
|
|
||||||
# 2002, Rene Wagner <reenoo@gmx.de>
|
|
||||||
# 2006, Peter Marschall
|
|
||||||
#
|
|
||||||
# This file 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
|
|
||||||
# any later version.
|
|
||||||
#
|
|
||||||
# This file 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 file; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# Configurable part. Set it according your setup.
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# Host which runs lcdproc daemon (LCDd)
|
|
||||||
my $SERVER = "localhost";
|
|
||||||
|
|
||||||
# Port on which LCDd listens to requests
|
|
||||||
my $PORT = "13666";
|
|
||||||
|
|
||||||
# Path to `ping' command
|
|
||||||
my $PING = "ping";
|
|
||||||
|
|
||||||
# list of hosts to be ping'ed
|
|
||||||
my @MACHINES = ("lcdproc.omnipotent.net",
|
|
||||||
"www.linux.org",
|
|
||||||
"www.daemonnews.org",
|
|
||||||
"127.0.0.1",
|
|
||||||
"seurat",
|
|
||||||
"rodin",
|
|
||||||
"matisse",
|
|
||||||
);
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# End of user configurable parts
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
my $progname = $0;
|
|
||||||
$progname =~ s#.*/(.*?)$#$1#;
|
|
||||||
|
|
||||||
# declare functions
|
|
||||||
sub error($@);
|
|
||||||
sub usage($);
|
|
||||||
|
|
||||||
|
|
||||||
## main routine ##
|
|
||||||
my %opt = ();
|
|
||||||
|
|
||||||
# get options #
|
|
||||||
if (getopts('F:s:p:P:hV', \%opt) == 0) {
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check options
|
|
||||||
usage(0) if ($opt{h});
|
|
||||||
if ($opt{V}) {
|
|
||||||
print STDERR $progname ." version 1.1\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check number of arguments
|
|
||||||
#usage(1) if ($#ARGV >= 0);
|
|
||||||
|
|
||||||
# set variables
|
|
||||||
$SERVER = defined($opt{s}) ? $opt{s} : $SERVER;
|
|
||||||
$PORT = defined($opt{p}) ? $opt{p} : $PORT;
|
|
||||||
$PING = defined($opt{P}) ? $opt{P} : $PING;
|
|
||||||
@MACHINES = ($#ARGV >= 0) ? @ARGV : @MACHINES;
|
|
||||||
|
|
||||||
# Connect to the server...
|
|
||||||
my $remote = IO::Socket::INET->new(
|
|
||||||
Proto => 'tcp',
|
|
||||||
PeerAddr => $SERVER,
|
|
||||||
PeerPort => $PORT,
|
|
||||||
)
|
|
||||||
or error(1, "cannot connect to LCDd daemon at $SERVER:$PORT");
|
|
||||||
|
|
||||||
# Make sure our messages get there right away
|
|
||||||
$remote->autoflush(1);
|
|
||||||
|
|
||||||
sleep (1); # Give server plenty of time to notice us...
|
|
||||||
|
|
||||||
print $remote "hello\n";
|
|
||||||
# Note: it's good practice to listen for a response after a print to the
|
|
||||||
# server even if there isn't meant to be one. If you don't, you may find
|
|
||||||
# your program crashes after running for a while when the buffers fill up:
|
|
||||||
my $lcdresponse = <$remote>;
|
|
||||||
#print $lcdresponse;
|
|
||||||
|
|
||||||
# Turn off blocking mode...
|
|
||||||
fcntl($remote, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
# Set up some screen widgets...
|
|
||||||
print $remote "client_set name {$progname}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_add pings\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_set pings name {Ping Status}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add pings title title\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set pings title {Ping Status}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add pings one string\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add pings two string\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set pings one 1 2 {Checking machines...}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
my %pingstatus = (); # pingstatus{host} = 1 <=> host is up
|
|
||||||
my @list;
|
|
||||||
|
|
||||||
#print "Main loop...\n";
|
|
||||||
|
|
||||||
# Handle input... (just spew it to the console)
|
|
||||||
while (defined(my $line = <$remote>)) {
|
|
||||||
next if ($line =~ /^success$/o);
|
|
||||||
print $line;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach my $machine (@MACHINES) {
|
|
||||||
`$PING -c 1 $machine`;
|
|
||||||
$pingstatus{$machine} = ($?) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# count reachablei (up) machines
|
|
||||||
@list = grep { $pingstatus{$_} == 1 } @MACHINES;
|
|
||||||
print $remote "widget_set pings one 1 2 {Machines Up: ",scalar(@list),"}\n";
|
|
||||||
my $lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
# count unreachable (down) machines
|
|
||||||
@list = grep { $pingstatus{$_} == 0 } @MACHINES;
|
|
||||||
print $remote "widget_set pings two 1 3 {Down (",scalar(@list),"): ",join(", ", @list),"}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
# wait a bit
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
close($remote) or error(1, "close() failed: $!");
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
## print out error message and eventually exit ##
|
|
||||||
# Synopsis: error($status, $message)
|
|
||||||
sub error($@)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
my @msg = @_;
|
|
||||||
|
|
||||||
print STDERR $progname . ": " . join(" ", @msg) . "\n";
|
|
||||||
|
|
||||||
exit($status) if ($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## print out usage message and exit ##
|
|
||||||
# Synopsis: usage($status)
|
|
||||||
sub usage($)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
|
|
||||||
print STDERR "Usage: $progname [<options>] [<host> ...]\n";
|
|
||||||
if (!$status) {
|
|
||||||
print STDERR " where <options> are\n" .
|
|
||||||
" -s <server> connect to <server> (default: $SERVER)\n" .
|
|
||||||
" -p <port> connect to <port> on <server> (default: $PORT)\n" .
|
|
||||||
" -P <ping> use <ping> as the ping cmmand (default: $PING)\n" .
|
|
||||||
" -h show this help page\n" .
|
|
||||||
" -V display version number\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print STDERR "For help, type: $progname -h\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__END__
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
iosock.pl -- show reachability of hosts and display it on the LCD
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<iosock.pl>
|
|
||||||
[B<-s> I<server>]
|
|
||||||
[B<-p> I<port>]
|
|
||||||
[B<-P> I<ping>]
|
|
||||||
[B<-h>]
|
|
||||||
[B<-V>]
|
|
||||||
[I<host> ...]
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<iosock.pl> is a small example client for LCDd, the lcdproc server.
|
|
||||||
|
|
||||||
It tries to ping the servers given as parameters and displays on the LCD
|
|
||||||
whether they are reachable or not.
|
|
||||||
If no hosts are given as parameters a built-in list of default machines will be checked.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<-s> I<server>
|
|
||||||
|
|
||||||
Connect to the LCDd daemon at host I<server> instead of the default C<localhost>.
|
|
||||||
|
|
||||||
=item B<-p> I<port>
|
|
||||||
|
|
||||||
Use port I<port> when connecting to the LCDd server instead of the default
|
|
||||||
LCDd port C<13666>.
|
|
||||||
|
|
||||||
=item B<-P> I<ping>
|
|
||||||
|
|
||||||
Use I<ping> as the command to check whether the remote hosts are reachable
|
|
||||||
instead of the default C<ping>.
|
|
||||||
|
|
||||||
Any I<ping> given using this options must understand the C<-c 1>
|
|
||||||
command line option of the default C<ping>.
|
|
||||||
|
|
||||||
=item B<-h>
|
|
||||||
|
|
||||||
Display a short help page and exit.
|
|
||||||
|
|
||||||
=item B<-V>
|
|
||||||
|
|
||||||
Display iosock.pl's version number and exit.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<LCDd(8)>
|
|
||||||
|
|
||||||
|
|
||||||
=head1 AUTHORS
|
|
||||||
|
|
||||||
iosock.pl was written by various members of the LCDproc project team;
|
|
||||||
this manual page was written by Peter Marschall.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# Copyright (c) 2008, Ethan Dicks <ethan.dicks@gmail.com>
|
|
||||||
#
|
|
||||||
# This file 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
|
|
||||||
# any later version.
|
|
||||||
#
|
|
||||||
# This file 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 file; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
#
|
|
||||||
|
|
||||||
# Following is the POD documentation, type perldoc lcdident.pl to read it.
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
lcdident - identify LCDproc displays
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<lcdident.pl>
|
|
||||||
[B<-s> I<server>]
|
|
||||||
[B<-p> I<port>]
|
|
||||||
[B<-t> I<seconds>]
|
|
||||||
[B<-v> I<verbosity>]
|
|
||||||
[B<-h>]
|
|
||||||
[B<-V>]
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<lcdident> is a simple LCDproc client program that writes a port
|
|
||||||
number and display geometry to a particular instance of B<LCDd>. For
|
|
||||||
systems with multiple display modules and multiple B<LCDd> processes,
|
|
||||||
it can be quite handy to know which TCP port is associated with
|
|
||||||
which physical module.
|
|
||||||
|
|
||||||
|
|
||||||
B<lcdident> is also an example of how to code for different display
|
|
||||||
geometries. In particular, it differentiates between 2-line and
|
|
||||||
more-than-2-line (typically 4-line) displays.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
-s <server>
|
|
||||||
connect to <server>.
|
|
||||||
|
|
||||||
-p <port>
|
|
||||||
connect to port <port>
|
|
||||||
|
|
||||||
-t <seconds>
|
|
||||||
how long to keep this client running (default is 5 seconds).
|
|
||||||
|
|
||||||
-v <verbosity>
|
|
||||||
set logging verbosity level to <verbosity>.
|
|
||||||
|
|
||||||
-V
|
|
||||||
display the present version number of lcdident.
|
|
||||||
|
|
||||||
-h
|
|
||||||
print out a list of the available program options and exit.
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DIAGNOSTICS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item Cannot connect to LCDproc port
|
|
||||||
|
|
||||||
By default, lcdident tries to connect to localhost port 13666, but by using
|
|
||||||
the B<-s> and B<-p> options, you can point B<lcdident> at other servers and
|
|
||||||
other ports. If you get this error, that means that there was a problem
|
|
||||||
opening up the requested port on the requested machine. Typically this
|
|
||||||
means that B<LCDd> is not listening on that particular port. The two most
|
|
||||||
common causes of this are because B<LCDd> was configured to listen on a
|
|
||||||
different port, or because B<LCDd> is not running at all.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 REQUIRES
|
|
||||||
|
|
||||||
Perl 5.004;
|
|
||||||
|
|
||||||
=head1 DISCLAMER
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License version 2 as
|
|
||||||
published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<LCDd>
|
|
||||||
|
|
||||||
=head1 BUGS
|
|
||||||
|
|
||||||
Yes, there might be some. Please report any you find to LCDproc's mailing list.
|
|
||||||
See the website for more information.
|
|
||||||
|
|
||||||
=head1 AUTHORS
|
|
||||||
|
|
||||||
B<lcdident> was written by Ethan Dicks <ethan.dicks@gmail.com>
|
|
||||||
|
|
||||||
=head1 WEBSITE
|
|
||||||
|
|
||||||
Visit B<http://www.lcdproc.org/> for more info and the lastest version.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
use 5.004;
|
|
||||||
use strict;
|
|
||||||
use IO::Socket;
|
|
||||||
use Getopt::Std;
|
|
||||||
use Fcntl;
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# Configurable part. Set it according your setup
|
|
||||||
# or use input args.
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# Verbose
|
|
||||||
# 0 : None (only fatal errors)
|
|
||||||
# 1 : Warnings
|
|
||||||
# 5 : Explain every step.
|
|
||||||
my $verbose = 0;
|
|
||||||
|
|
||||||
# Host which runs lcdproc daemon (LCDd)
|
|
||||||
my $server = "localhost";
|
|
||||||
|
|
||||||
# Port on which LCDd listens to requests
|
|
||||||
my $port = "13666";
|
|
||||||
|
|
||||||
# wait-time (in seconds) when we are all done
|
|
||||||
my $waittime = 5;
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# End of user configurable parts
|
|
||||||
############################################################
|
|
||||||
$SIG{INT} = \&grace;
|
|
||||||
$SIG{TERM} = \&grace;
|
|
||||||
|
|
||||||
my $progname = $0;
|
|
||||||
$progname =~ s#.*/(.*?)$#$1#;
|
|
||||||
|
|
||||||
# declare functions
|
|
||||||
sub grace();
|
|
||||||
sub usage($);
|
|
||||||
|
|
||||||
# Process input arguments
|
|
||||||
my %opt = ();
|
|
||||||
|
|
||||||
# get options #
|
|
||||||
if (getopts('s:p:v:t:hV', \%opt) == 0) {
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check options
|
|
||||||
usage(0) if ($opt{h});
|
|
||||||
|
|
||||||
if ($opt{V}) {
|
|
||||||
print STDERR $progname ." version 1.05\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check number of arguments
|
|
||||||
usage(1) if ($#ARGV >= 0);
|
|
||||||
|
|
||||||
# set variables
|
|
||||||
$server = defined($opt{s}) ? $opt{s} : $server;
|
|
||||||
$port = defined($opt{p}) ? $opt{p} : $port;
|
|
||||||
$verbose = defined($opt{v}) ? $opt{v} : $verbose;
|
|
||||||
$waittime= defined($opt{t}) ? $opt{t} : $waittime;
|
|
||||||
|
|
||||||
|
|
||||||
# Connect to the server...
|
|
||||||
print "Connecting to LCDproc at $server\n" if ($verbose >= 5);
|
|
||||||
my $remote = IO::Socket::INET->new(
|
|
||||||
Proto => "tcp",
|
|
||||||
PeerAddr => $server,
|
|
||||||
PeerPort => $port,
|
|
||||||
) or die "Cannot connect to LCDproc port ($server:$port)\n";
|
|
||||||
|
|
||||||
# Make sure our messages get there right away
|
|
||||||
$remote->autoflush(1);
|
|
||||||
|
|
||||||
sleep 1; # Give server plenty of time to notice us...
|
|
||||||
|
|
||||||
print $remote "hello\n";
|
|
||||||
my $lcdconnect = <$remote>;
|
|
||||||
print $lcdconnect if ($verbose >= 5);
|
|
||||||
# connect LCDproc 0.5.2 protocol 0.3 lcd wid 20 hgt 4 cellwid 5 cellhgt 8
|
|
||||||
($lcdconnect =~ /lcd.+wid\s+(\d+)\s+hgt\s+(\d+)/);
|
|
||||||
my $lcdwidth = $1; my $lcdheight= $2;
|
|
||||||
print "Detected LCD size of $lcdwidth x $lcdheight\n" if ($verbose >= 5);
|
|
||||||
|
|
||||||
# Turn off blocking mode...
|
|
||||||
fcntl($remote, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
# Set up some screen widgets...
|
|
||||||
print $remote "client_set name {lcdident}\n";
|
|
||||||
print $remote "screen_add lcdident\n";
|
|
||||||
print $remote "screen_set lcdident name {lcdident}\n";
|
|
||||||
|
|
||||||
print $remote "widget_add lcdident title title\n";
|
|
||||||
print $remote "widget_set lcdident title {lcdident}\n";
|
|
||||||
|
|
||||||
print $remote "widget_add lcdident ident1 string\n";
|
|
||||||
print $remote "widget_add lcdident ident2 string\n";
|
|
||||||
|
|
||||||
|
|
||||||
# Compose the ident message(s) and calculate where to render it/them
|
|
||||||
my $ident1;
|
|
||||||
my $ident2;
|
|
||||||
my $ident2_y = $lcdheight; # put the second bit on the bottom line
|
|
||||||
my $ident1_y = $ident2_y - 1; # put the first bit one line up from the second
|
|
||||||
|
|
||||||
# check for 2-line displays to see if we have to put all the info on one line
|
|
||||||
if ($lcdheight > 2) {
|
|
||||||
$ident1 = "Port ${port}";
|
|
||||||
$ident2 = "Geom ${lcdwidth}x${lcdheight}";
|
|
||||||
} else {
|
|
||||||
$ident1 = "Port $port ${lcdwidth}x${lcdheight}";
|
|
||||||
$ident2 = "";
|
|
||||||
|
|
||||||
$ident1_y = $lcdheight; # use the bottom line
|
|
||||||
}
|
|
||||||
|
|
||||||
# Display the ident message(s)
|
|
||||||
if ($ident1) {
|
|
||||||
my $cmd = sprintf("widget_set lcdident ident1 1 %d {%s}", $ident1_y, $ident1);
|
|
||||||
print "Cmd is '$cmd'\n" if ($verbose >= 5);
|
|
||||||
print $remote $cmd, "\n";
|
|
||||||
}
|
|
||||||
if ($ident2) {
|
|
||||||
my $cmd = sprintf("widget_set lcdident ident2 1 %d {%s}", $ident2_y, $ident2);
|
|
||||||
print "Cmd is '$cmd'\n" if ($verbose >= 5);
|
|
||||||
print $remote $cmd, "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# hold the client screen up for as long as we were asked (default 5 seconds);
|
|
||||||
print "Keeping screen up for $waittime seconds\n" if ($verbose >= 5);
|
|
||||||
sleep($waittime);
|
|
||||||
|
|
||||||
# eat all input from LCDd
|
|
||||||
while(defined(my $input = <$remote>)) { }
|
|
||||||
|
|
||||||
# all done
|
|
||||||
grace();
|
|
||||||
|
|
||||||
# send a SIGINT or SIGTERM to exit nicely.
|
|
||||||
|
|
||||||
# To be called on exit and on SIGINT or SIGTERM.
|
|
||||||
sub grace() {
|
|
||||||
print "Exiting...\n" if ($verbose >= 5);
|
|
||||||
close($remote);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
## print out usage message and exit ##
|
|
||||||
# Synopsis: usage($status)
|
|
||||||
sub usage($)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
|
|
||||||
print STDERR "Usage: $progname [<options>]\n";
|
|
||||||
if (!$status) {
|
|
||||||
print STDERR " where <options> are\n" .
|
|
||||||
" -s <server> connect to <server> (default: $server)\n" .
|
|
||||||
" -p <port> connect to <port> on <server> (default: $port)\n" .
|
|
||||||
" -t <seconds> how long to hold the client screen up (default: $waittime seconds).\n" .
|
|
||||||
" -v <verbosity> verbosity level (default: $verbose, max verbosity: 5)\n" .
|
|
||||||
" -h show this help page\n" .
|
|
||||||
" -V display version number\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print STDERR "For help, type: $progname -h\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
__END__
|
|
||||||
@@ -1,342 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# tail.pl - an example client for LCDproc
|
|
||||||
|
|
||||||
#
|
|
||||||
# This client for LCDproc displays the tail of a specified file.
|
|
||||||
# It's possible to change the visible part of the file with LCDproc
|
|
||||||
# controlled keys
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Copyright (c) 1999, William Ferrell, Selene Scriven
|
|
||||||
# 2001, David Glaude
|
|
||||||
# 2001, Jarda Benkovsky
|
|
||||||
# 2002, Jonathan Oxer
|
|
||||||
# 2002, Rene Wagner <reenoo@gmx.de>
|
|
||||||
# 2008, Peter Marschall
|
|
||||||
#
|
|
||||||
# This file 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
|
|
||||||
# any later version.
|
|
||||||
#
|
|
||||||
# This file 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 file; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
#
|
|
||||||
|
|
||||||
use 5.005;
|
|
||||||
use strict;
|
|
||||||
use Getopt::Std;
|
|
||||||
use IO::Socket;
|
|
||||||
use Fcntl;
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# Configurable part. Set it according your setup.
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# Host which runs LCDproc daemon (LCDd)
|
|
||||||
my $SERVER = "localhost";
|
|
||||||
|
|
||||||
# Port on which LCDd listens to requests
|
|
||||||
my $PORT = "13666";
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# End of user configurable parts
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# These define the visible part of the file...
|
|
||||||
my $top = 3; # How far from the end of the file should we start by default?
|
|
||||||
my $lines = 3; # How many lines to display by default ?
|
|
||||||
my $left = 1; # Left/right scrolling position,
|
|
||||||
my $width = 20; # and number of characters per line to show
|
|
||||||
|
|
||||||
|
|
||||||
my $progname = $0;
|
|
||||||
$progname =~ s#.*/(.*?)$#$1#;
|
|
||||||
|
|
||||||
# declare functions
|
|
||||||
sub error($@);
|
|
||||||
sub usage($);
|
|
||||||
|
|
||||||
|
|
||||||
## main routine ##
|
|
||||||
my %opt = ();
|
|
||||||
|
|
||||||
# get options #
|
|
||||||
if (getopts('F:s:p:hV', \%opt) == 0) {
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check options
|
|
||||||
usage(0) if ($opt{h});
|
|
||||||
if ($opt{V}) {
|
|
||||||
print STDERR $progname ." version 1.1\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check number of arguments
|
|
||||||
usage(1) if ($#ARGV != 0);
|
|
||||||
|
|
||||||
|
|
||||||
# set variables
|
|
||||||
$SERVER = defined($opt{s}) ? $opt{s} : $SERVER;
|
|
||||||
$PORT = defined($opt{p}) ? $opt{p} : $PORT;
|
|
||||||
my $filename = shift @ARGV;
|
|
||||||
my $slow = 1; # Should we pause after the current frame?
|
|
||||||
|
|
||||||
|
|
||||||
# Connect to the server...
|
|
||||||
my $remote = IO::Socket::INET->new(
|
|
||||||
Proto => 'tcp',
|
|
||||||
PeerAddr => $SERVER,
|
|
||||||
PeerPort => $PORT,
|
|
||||||
)
|
|
||||||
or error(1, "cannot connect to LCDd daemon at $SERVER:$PORT");
|
|
||||||
|
|
||||||
# Make sure our messages get there right away
|
|
||||||
$remote->autoflush(1);
|
|
||||||
|
|
||||||
sleep 1; # Give server plenty of time to notice us...
|
|
||||||
|
|
||||||
print $remote "hello\n";
|
|
||||||
# Note: it's good practice to listen for a response after a print to the
|
|
||||||
# server even if there isn't meant to be one. If you don't, you may find
|
|
||||||
# your program crashes after running for a while when the buffers fill up.
|
|
||||||
my $lcdresponse = <$remote>;
|
|
||||||
#print $lcdresponse;
|
|
||||||
|
|
||||||
# get width & height from server's greet message
|
|
||||||
if ($lcdresponse =~ /\bwid\s+(\d+)\b/) {
|
|
||||||
$width = 0 + $1;
|
|
||||||
}
|
|
||||||
if ($lcdresponse =~ /\bhgt\s+(\d+)\b/) {
|
|
||||||
$lines = (0 + $1) - 1;
|
|
||||||
$top = $lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Turn off blocking mode...
|
|
||||||
fcntl($remote, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
# Set up some screen widgets...
|
|
||||||
print $remote "client_set name {$progname}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_add tail\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_set tail name {Tail $filename}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add tail title title\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set tail title {Tail: $filename}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
# create one widget called lineX (x in {1,2,...}) per line
|
|
||||||
for (my $i = 1; $i <= $lines; $i++) {
|
|
||||||
print $remote "widget_add tail line$i string\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
}
|
|
||||||
|
|
||||||
# NOTE: You have to ask LCDd to send you keys you want to handle
|
|
||||||
print $remote "client_add_key Left\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_add_key Right\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_add_key Up\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_add_key Down\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
|
|
||||||
# Forever, we should do stuff...
|
|
||||||
while (1) {
|
|
||||||
# Handle input... (spew it to the console)
|
|
||||||
# Also, certain keys scroll the display
|
|
||||||
while(defined(my $input = <$remote>)) {
|
|
||||||
next if ($input =~ /^success$/o);
|
|
||||||
|
|
||||||
#print $input;
|
|
||||||
|
|
||||||
$slow = -10;
|
|
||||||
# Make sure we handle each line...
|
|
||||||
my @lines = split(/\n/, $input);
|
|
||||||
foreach my $line (@lines) {
|
|
||||||
if ($line =~ /^key (\S+)/) { # Keypresses are useful.
|
|
||||||
my $key = $1;
|
|
||||||
|
|
||||||
if ($key eq 'Down') {
|
|
||||||
$top-- if ($top > $lines);
|
|
||||||
}
|
|
||||||
elsif ($key eq 'Up') {
|
|
||||||
$top++;
|
|
||||||
}
|
|
||||||
elsif ($key eq 'Right') {
|
|
||||||
$left++;
|
|
||||||
}
|
|
||||||
elsif ($key eq 'Left') {
|
|
||||||
$left-- if ($left > 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Now, show what the file contains, if anything...
|
|
||||||
if ( -f $filename ) {
|
|
||||||
# Grab some text.
|
|
||||||
my $right = $left + $width - 1;
|
|
||||||
# get the data by calling external programs tail, head & cut
|
|
||||||
my $text = `tail -$top $filename | head -$lines | cut -c$left-$right`;
|
|
||||||
my @lines = split(/\n/, $text);
|
|
||||||
|
|
||||||
# Now, display that text...
|
|
||||||
for (my $i = 0; $i < $lines; $i++) {
|
|
||||||
my $j = $i + 1;
|
|
||||||
my $k = $i + 2;
|
|
||||||
|
|
||||||
# Avoid blank lines
|
|
||||||
my $line = ($#lines < $i) ? " " : $lines[$i];
|
|
||||||
$line = " " if ($line =~ /^\s*$/o);
|
|
||||||
|
|
||||||
# expand tabs to spaces
|
|
||||||
while ((my $idx = index($line, "\t")) >= 0) {
|
|
||||||
use integer; # calculate integers like in C
|
|
||||||
my $w = 8 + 8 * ($idx / 8) - $idx;
|
|
||||||
my $subst = " " x $w;
|
|
||||||
|
|
||||||
$line =~ s/\t/" " x $w/e;
|
|
||||||
}
|
|
||||||
|
|
||||||
# write to the display
|
|
||||||
print $remote "widget_set tail line$j 1 $k {$line}\n";
|
|
||||||
my $lcdresponse = <$remote>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { # If the file is unreadable, show an error
|
|
||||||
print $remote "widget_set tail line1 1 2 {$filename}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set tail line2 1 3 {doesn't exist.}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set tail line3 1 4 { }\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
}
|
|
||||||
|
|
||||||
# And wait a little while before we show stuff again.
|
|
||||||
if ($slow > 0) { sleep 1; $slow++; }
|
|
||||||
elsif ($slow > 4) { sleep 2; $slow++; }
|
|
||||||
elsif ($slow > 64) { sleep 4; }
|
|
||||||
else { $slow++; }
|
|
||||||
# The "slow" thing just lets us have a better response time
|
|
||||||
# while the user is pressing keys... But while the user
|
|
||||||
# is inactive, it gradually decreases update frequency.
|
|
||||||
}
|
|
||||||
|
|
||||||
close ($remote) or error(1, "close() failed");
|
|
||||||
exit;
|
|
||||||
|
|
||||||
|
|
||||||
## print out error message and eventually exit ##
|
|
||||||
# Synopsis: error($status, $message)
|
|
||||||
sub error($@)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
my @msg = @_;
|
|
||||||
|
|
||||||
print STDERR $progname . ": " . join(" ", @msg) . "\n";
|
|
||||||
|
|
||||||
exit($status) if ($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## print out usage message and exit ##
|
|
||||||
# Synopsis: usage($status)
|
|
||||||
sub usage($)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
|
|
||||||
print STDERR "Usage: $progname [<options>] <file>\n";
|
|
||||||
if (!$status) {
|
|
||||||
print STDERR " where <options> are\n" .
|
|
||||||
" -s <server> connect to <server> (default: $SERVER)\n" .
|
|
||||||
" -p <port> connect to <port> on <server> (default: $PORT)\n" .
|
|
||||||
" -h show this help page\n" .
|
|
||||||
" -V display version number\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print STDERR "For help, type: $progname -h\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
__END__
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
tail.pl -- show tail of a file on LCD
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<tail.pl>
|
|
||||||
[B<-s> I<server>]
|
|
||||||
[B<-p> I<port>]
|
|
||||||
[B<-h>]
|
|
||||||
[B<-V>]
|
|
||||||
I<file>
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<tail.pl> is a small example client for LCDd, the LCDproc server.
|
|
||||||
|
|
||||||
It shows the tail of th file given as parameter on the LCD.
|
|
||||||
|
|
||||||
If the LCD supports keys you can use the keys mapped to C<Up>, C<Down>,
|
|
||||||
C<Left> and C<Right> to scroll the contents shown on the screen.
|
|
||||||
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<-s> I<server>
|
|
||||||
|
|
||||||
Connect to the LCDd daemon at host I<server> instead of the default C<localhost>.
|
|
||||||
|
|
||||||
=item B<-p> I<port>
|
|
||||||
|
|
||||||
Use port I<port> when connecting to the LCDd server instead of the default
|
|
||||||
LCDd port C<13666>.
|
|
||||||
|
|
||||||
=item B<-h>
|
|
||||||
|
|
||||||
Display a short help page and exit.
|
|
||||||
|
|
||||||
=item B<-V>
|
|
||||||
|
|
||||||
Display tail.pl's version number and exit.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<tail(1)>,
|
|
||||||
L<LCDd(8)>
|
|
||||||
|
|
||||||
|
|
||||||
=head1 AUTHORS
|
|
||||||
|
|
||||||
tail.pl was written by various members of the LCDproc project team;
|
|
||||||
this manual page was written by Peter Marschall.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
|
|
||||||
@@ -1,338 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# x11amp.pl - an example client for LCDproc
|
|
||||||
|
|
||||||
#
|
|
||||||
# Simple client for LCDproc which controls XMMS/X11AMP MP3 player
|
|
||||||
# from the keyboard controlled by LCDproc. It can only rewind to
|
|
||||||
# previous song and skip forward to previous one.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Copyright (c) 1999, William Ferrell, Selene Scriven
|
|
||||||
# 2001, David Glaude
|
|
||||||
# 2001, Jarda Benkovsky
|
|
||||||
# 2002, Jonathan Oxer
|
|
||||||
# 2002, Rene Wagner <reenoo@gmx.de>
|
|
||||||
# 2006, Peter Marschall
|
|
||||||
# 2006, Ethan Dicks
|
|
||||||
#
|
|
||||||
# This file 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
|
|
||||||
# any later version.
|
|
||||||
#
|
|
||||||
# This file 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 file; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE: This is just a test! It's simple, cheesy, and doesn't do much
|
|
||||||
# or even look very nice.
|
|
||||||
#
|
|
||||||
# However, it demonstrates one way to handle input from the server.
|
|
||||||
|
|
||||||
use 5.005;
|
|
||||||
use strict;
|
|
||||||
use Getopt::Std;
|
|
||||||
use IO::Socket;
|
|
||||||
use Fcntl;
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# Configurable part. Set it according your setup.
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# Verbose
|
|
||||||
# 0 : None (only fatal errors)
|
|
||||||
# 1 : Warnings
|
|
||||||
# 5 : Explain every step.
|
|
||||||
my $default_verbosity = 0;
|
|
||||||
my $verbose;
|
|
||||||
|
|
||||||
# Host which runs lcdproc daemon (LCDd)
|
|
||||||
my $SERVER = "localhost";
|
|
||||||
|
|
||||||
# Port on which LCDd listens to requests
|
|
||||||
my $PORT = "13666";
|
|
||||||
|
|
||||||
# Path to command which controls XMMS/X11AMP
|
|
||||||
my $XMMS = "xmms";
|
|
||||||
|
|
||||||
# Commands to set to previous / next song
|
|
||||||
my $XMMS_FORWARD = "$XMMS --fwd";
|
|
||||||
my $XMMS_REWIND = "$XMMS --rew";
|
|
||||||
my $XMMS_PLAY_PAUSE = "$XMMS --play-pause";
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# End of user configurable parts
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# catch SIGINT and SIGTERM to invoke our cleanup routine
|
|
||||||
$SIG{INT} = \&grace;
|
|
||||||
$SIG{TERM} = \&grace;
|
|
||||||
|
|
||||||
|
|
||||||
my $progname = $0;
|
|
||||||
$progname =~ s#.*/(.*?)$#$1#;
|
|
||||||
|
|
||||||
# declare functions
|
|
||||||
sub error($@);
|
|
||||||
sub usage($);
|
|
||||||
|
|
||||||
|
|
||||||
## main routine ##
|
|
||||||
my %opt = ();
|
|
||||||
|
|
||||||
# get options #
|
|
||||||
if (getopts('s:p:v:hV', \%opt) == 0) {
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check options
|
|
||||||
usage(0) if ($opt{h});
|
|
||||||
if ($opt{V}) {
|
|
||||||
print STDERR $progname ." version 1.2\n";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
# check number of arguments
|
|
||||||
usage(1) if ($#ARGV >= 0);
|
|
||||||
|
|
||||||
|
|
||||||
# set variables
|
|
||||||
$SERVER = defined($opt{s}) ? $opt{s} : $SERVER;
|
|
||||||
$PORT = defined($opt{p}) ? $opt{p} : $PORT;
|
|
||||||
$verbose = defined($opt{v}) ? $opt{v} : $default_verbosity;
|
|
||||||
|
|
||||||
# Connect to the server...
|
|
||||||
my $remote = IO::Socket::INET->new(
|
|
||||||
Proto => 'tcp',
|
|
||||||
PeerAddr => $SERVER,
|
|
||||||
PeerPort => $PORT,
|
|
||||||
)
|
|
||||||
|| die "Cannot connect to LCDproc port\n";
|
|
||||||
|
|
||||||
# Make sure our messages get there right away
|
|
||||||
$remote->autoflush(1);
|
|
||||||
|
|
||||||
sleep 1; # Give server plenty of time to notice us...
|
|
||||||
|
|
||||||
print $remote "hello\n";
|
|
||||||
# Note: it's good practice to listen for a response after a print to the
|
|
||||||
# server even if there isn't meant to be one. If you don't, you may find
|
|
||||||
# your program crashes after running for a while when the buffers fill up:
|
|
||||||
my $lcdresponse = <$remote>;
|
|
||||||
print $lcdresponse if ($verbose >= 5);
|
|
||||||
|
|
||||||
# determine LCD size (not needed here, but useful for other clients)
|
|
||||||
($lcdresponse =~ /lcd.+wid\s+(\d+)\s+hgt\s+(\d+)/);
|
|
||||||
my $lcdwidth = $1; my $lcdheight= $2;
|
|
||||||
print "Detected LCD size of $lcdwidth x $lcdheight\n" if ($verbose >= 5);
|
|
||||||
|
|
||||||
# Turn off blocking mode...
|
|
||||||
fcntl($remote, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
# Set up some screen widgets...
|
|
||||||
print $remote "client_set name {X11AMP}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_add x11amp\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "screen_set x11amp name {X11AMP test}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add x11amp title title\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set x11amp title {$XMMS test}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_add x11amp one string\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "widget_set x11amp one 1 2 {[<<] [>|] [>>]}\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
# NOTE: You have to ask LCDd to send you keys you want to handle
|
|
||||||
print $remote "client_add_key Left\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_add_key Right\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_add_key Enter\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
# Handle input...
|
|
||||||
while (defined(my $line = <$remote>)) {
|
|
||||||
chomp $line;
|
|
||||||
print "Received '$line'\n" if ($verbose >= 5);
|
|
||||||
my @items = split(/ /, $line);
|
|
||||||
my $command = shift @items;
|
|
||||||
|
|
||||||
|
|
||||||
# Use input to change songs...
|
|
||||||
if ($command eq 'key') {
|
|
||||||
my $key = shift @items;
|
|
||||||
|
|
||||||
if ($key eq 'Left') {
|
|
||||||
system($XMMS_REWIND);
|
|
||||||
}
|
|
||||||
elsif ($key eq 'Right') {
|
|
||||||
system($XMMS_FORWARD);
|
|
||||||
}
|
|
||||||
elsif ($key eq 'Enter') {
|
|
||||||
system($XMMS_PLAY_PAUSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# And ignore everything else
|
|
||||||
elsif ($command eq 'connect') {
|
|
||||||
}
|
|
||||||
elsif ($command eq 'listen') {
|
|
||||||
}
|
|
||||||
elsif ($command eq 'ignore') {
|
|
||||||
}
|
|
||||||
elsif ($command eq 'success') {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
error(0, "Huh?", $line)
|
|
||||||
if ($line !~ /^\s*$/o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# wait a bit
|
|
||||||
sleep 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# To be called on exit and on SIGINT or SIGTERM.
|
|
||||||
sub grace() {
|
|
||||||
print "Exiting...\n" if ($verbose >= 5);
|
|
||||||
|
|
||||||
# release keys
|
|
||||||
print $remote "client_del_key Left\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_del_key Right\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
print $remote "client_del_key Enter\n";
|
|
||||||
$lcdresponse = <$remote>;
|
|
||||||
|
|
||||||
# close socket
|
|
||||||
close($remote);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## print out error message and eventually exit ##
|
|
||||||
# Synopsis: error($status, $message)
|
|
||||||
sub error($@)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
my @msg = @_;
|
|
||||||
|
|
||||||
print STDERR $progname . ": " . join(" ", @msg) . "\n";
|
|
||||||
|
|
||||||
exit($status) if ($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## print out usage message and exit ##
|
|
||||||
# Synopsis: usage($status)
|
|
||||||
sub usage($)
|
|
||||||
{
|
|
||||||
my $status = shift;
|
|
||||||
|
|
||||||
print STDERR "Usage: $progname [<options>]\n";
|
|
||||||
if (!$status) {
|
|
||||||
print STDERR " where <options> are\n" .
|
|
||||||
" -s <server> connect to <server> (default: $SERVER)\n" .
|
|
||||||
" -p <port> connect to <port> on <server> (default: $PORT)\n" .
|
|
||||||
" -v <verbosity> verbosity level (default: $default_verbosity, max verbosity: 5)\n" .
|
|
||||||
" -h show this help page\n" .
|
|
||||||
" -V display version number\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print STDERR "For help, type: $progname -h\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__END__
|
|
||||||
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
x11amp.pl - LCDproc client controlling XMMS/X11AMP
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<x11amp.pl>
|
|
||||||
[B<-s> I<server>]
|
|
||||||
[B<-p> I<port>]
|
|
||||||
[B<-v> I<verbosity>]
|
|
||||||
[B<-h>]
|
|
||||||
[B<-V>]
|
|
||||||
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<x11amp.pl> is a simple client for LCDproc which controls an XMMS/X11AMP
|
|
||||||
MP3 player from the keypad controlled by LCDproc.
|
|
||||||
It can only rewind to the previous song, skip forward to the next song, and switch between pause and play.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<-s> I<server>
|
|
||||||
|
|
||||||
Connect to the LCDd daemon at host I<server> instead of the default C<localhost>.
|
|
||||||
|
|
||||||
=item B<-p> I<port>
|
|
||||||
|
|
||||||
Use port I<port> when connecting to the LCDd server instead of the default
|
|
||||||
LCDd port C<13666>.
|
|
||||||
|
|
||||||
=item B<-v> I<verbosity>
|
|
||||||
|
|
||||||
Set message verbosity (0 is silent, 1 is warnings only, 5 describes events in detail).
|
|
||||||
|
|
||||||
=item B<-h>
|
|
||||||
|
|
||||||
Display a short help page and exit.
|
|
||||||
|
|
||||||
=item B<-V>
|
|
||||||
|
|
||||||
Display x11amp's version number and exit.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<xmms(6)>,
|
|
||||||
L<LCDd(8)>
|
|
||||||
|
|
||||||
|
|
||||||
=head1 AUTHORS
|
|
||||||
|
|
||||||
x11amp.pl was written by various members of the LCDproc project team;
|
|
||||||
this manual page was written by Peter Marschall.
|
|
||||||
|
|
||||||
|
|
||||||
=head1 BUGS
|
|
||||||
|
|
||||||
Yes, there might be some. Please report any you find to LCDproc's mailing list.
|
|
||||||
See the website for more information.
|
|
||||||
|
|
||||||
|
|
||||||
=head1 WEBSITE
|
|
||||||
|
|
||||||
Visit B<http://www.lcdproc.org/> for more info and the latest version.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.deps
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
lcdexec
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
sysconf_DATA = lcdexec.conf
|
|
||||||
|
|
||||||
bin_PROGRAMS = lcdexec
|
|
||||||
|
|
||||||
lcdexec_SOURCES = lcdexec.c menu.c menu.h
|
|
||||||
|
|
||||||
lcdexec_LDADD = ../../shared/libLCDstuff.a
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -DSYSCONFDIR=\"$(sysconfdir)\" -DPIDFILEDIR=\"$(pidfiledir)\"
|
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = $(sysconf_DATA)
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,753 +0,0 @@
|
|||||||
/** \file clients/lcdexec/lcdexec.c
|
|
||||||
* Main file for \c lcdexec, the program starter in the LCDproc suite.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This file is part of lcdexec, an LCDproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License. Refer to the
|
|
||||||
* COPYING file distributed with this package.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Joris Robijn
|
|
||||||
* 2006-2008, Peter Marschall
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "getopt.h"
|
|
||||||
|
|
||||||
#include "shared/str.h"
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "menu.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(SYSCONFDIR)
|
|
||||||
# define SYSCONFDIR "/etc"
|
|
||||||
#endif
|
|
||||||
#if !defined(PIDFILEDIR)
|
|
||||||
# define PIDFILEDIR "/var/run"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEFAULT_CONFIGFILE SYSCONFDIR "/lcdexec.conf"
|
|
||||||
#define DEFAULT_PIDFILE PIDFILEDIR "/lcdexec.pid"
|
|
||||||
|
|
||||||
|
|
||||||
/** information about a process started by lcdexec */
|
|
||||||
typedef struct ProcInfo {
|
|
||||||
struct ProcInfo *next; /**< pointer to the next ProcInfo entry */
|
|
||||||
const MenuEntry *cmd; /**< pointer to the corresponding menu entry */
|
|
||||||
pid_t pid; /**< PID the process was started with */
|
|
||||||
time_t starttime; /**< start time of the process */
|
|
||||||
time_t endtime; /**< finishing time of the process */
|
|
||||||
int status; /**< exit status of the process */
|
|
||||||
int feedback; /**< what info to show to the user */
|
|
||||||
int shown; /**< tell if the info has been shown to the user */
|
|
||||||
} ProcInfo;
|
|
||||||
|
|
||||||
|
|
||||||
char * help_text =
|
|
||||||
"lcdexec - LCDproc client to execute commands from the LCDd menu\n"
|
|
||||||
"\n"
|
|
||||||
"Copyright (c) 2002, Joris Robijn, 2006-2008 Peter Marschall.\n"
|
|
||||||
"This program is released under the terms of the GNU General Public License.\n"
|
|
||||||
"\n"
|
|
||||||
"Usage: lcdexec [<options>]\n"
|
|
||||||
" where <options> are:\n"
|
|
||||||
" -c <file> Specify configuration file ["DEFAULT_CONFIGFILE"]\n"
|
|
||||||
" -a <address> DNS name or IP address of the LCDd server [localhost]\n"
|
|
||||||
" -p <port> port of the LCDd server [13666]\n"
|
|
||||||
" -f Run in foreground\n"
|
|
||||||
" -r <level> Set reporting level (0-5) [2: errors and warnings]\n"
|
|
||||||
" -s <0|1> Report to syslog (1) or stderr (0, default)\n"
|
|
||||||
" -h Show this help\n";
|
|
||||||
|
|
||||||
char *progname = "lcdexec";
|
|
||||||
|
|
||||||
/* Variables set by config */
|
|
||||||
#define UNSET_INT -1
|
|
||||||
#define UNSET_STR "\01"
|
|
||||||
char *configfile = NULL;
|
|
||||||
char *address = NULL;
|
|
||||||
int port = UNSET_INT;
|
|
||||||
int foreground = FALSE;
|
|
||||||
static int report_level = UNSET_INT;
|
|
||||||
static int report_dest = UNSET_INT;
|
|
||||||
char *pidfile = NULL;
|
|
||||||
int pidfile_written = FALSE;
|
|
||||||
char *displayname = NULL;
|
|
||||||
char *default_shell = NULL;
|
|
||||||
|
|
||||||
/* Other global variables */
|
|
||||||
MenuEntry *main_menu = NULL; /**< pointer to the main menu */
|
|
||||||
ProcInfo *proc_queue = NULL; /**< pointer to the list of executed processes */
|
|
||||||
|
|
||||||
int lcd_wid = 0; /**< LCD display width reported by the server */
|
|
||||||
int lcd_hgt = 0; /**< LCD display height reported by the server */
|
|
||||||
|
|
||||||
int sock = -1; /**< socket to connect to server */
|
|
||||||
|
|
||||||
int Quit = 0; /**< indicate end of main loop */
|
|
||||||
|
|
||||||
|
|
||||||
/* Function prototypes */
|
|
||||||
static void exit_program(int val);
|
|
||||||
static void sigchld_handler(int signal);
|
|
||||||
static int process_command_line(int argc, char **argv);
|
|
||||||
static int process_configfile(char * configfile);
|
|
||||||
static int connect_and_setup(void);
|
|
||||||
static int process_response(char *str);
|
|
||||||
static int exec_command(MenuEntry *cmd);
|
|
||||||
static int show_procinfo_msg(ProcInfo *p);
|
|
||||||
static int main_loop(void);
|
|
||||||
|
|
||||||
|
|
||||||
#define CHAIN(e,f) { if (e>=0) { e=(f); }}
|
|
||||||
#define CHAIN_END(e) { if (e<0) { report(RPT_CRIT,"Critical error, abort"); exit(e); }}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
struct sigaction sa;
|
|
||||||
|
|
||||||
CHAIN(error, process_command_line(argc, argv));
|
|
||||||
if (configfile == NULL)
|
|
||||||
configfile = DEFAULT_CONFIGFILE;
|
|
||||||
CHAIN(error, process_configfile(configfile));
|
|
||||||
|
|
||||||
if (report_dest == UNSET_INT || report_level == UNSET_INT) {
|
|
||||||
report_dest = RPT_DEST_STDERR;
|
|
||||||
report_level = RPT_ERR;
|
|
||||||
}
|
|
||||||
set_reporting(progname, report_level, report_dest);
|
|
||||||
CHAIN_END(error);
|
|
||||||
|
|
||||||
CHAIN(error, connect_and_setup());
|
|
||||||
CHAIN_END(error);
|
|
||||||
|
|
||||||
if(foreground != TRUE) {
|
|
||||||
if (daemon(1,1) != 0) {
|
|
||||||
report(RPT_ERR, "Error: daemonize failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pidfile != NULL) {
|
|
||||||
FILE *pidf = fopen(pidfile, "w");
|
|
||||||
|
|
||||||
if (pidf) {
|
|
||||||
fprintf(pidf, "%d\n", (int) getpid());
|
|
||||||
fclose(pidf);
|
|
||||||
pidfile_written = TRUE;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error creating pidfile %s: %s\n",
|
|
||||||
pidfile, strerror(errno));
|
|
||||||
return(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup signal handlers for common signals */
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
#ifdef HAVE_SA_RESTART
|
|
||||||
sa.sa_flags = SA_RESTART;
|
|
||||||
#endif
|
|
||||||
sa.sa_handler = exit_program;
|
|
||||||
sigaction(SIGINT, &sa, NULL); // Ctrl-C
|
|
||||||
sigaction(SIGTERM, &sa, NULL); // "regular" kill
|
|
||||||
sigaction(SIGHUP, &sa, NULL); // kill -HUP
|
|
||||||
sigaction(SIGPIPE, &sa, NULL); // write to closed socket
|
|
||||||
sigaction(SIGKILL, &sa, NULL); // kill -9 [cannot be trapped; but ...]
|
|
||||||
|
|
||||||
/* setup signal handler for children to avoid zombies */
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
|
|
||||||
sa.sa_handler = sigchld_handler;
|
|
||||||
sigaction(SIGCHLD, &sa, NULL);
|
|
||||||
|
|
||||||
main_loop();
|
|
||||||
|
|
||||||
exit_program(EXIT_SUCCESS);
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void exit_program(int val)
|
|
||||||
{
|
|
||||||
//printf("exit program\n");
|
|
||||||
Quit = 1;
|
|
||||||
sock_close(sock);
|
|
||||||
if ((foreground != TRUE) && (pidfile != NULL) && (pidfile_written == TRUE))
|
|
||||||
unlink(pidfile);
|
|
||||||
exit(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* the grim reaper ;-) */
|
|
||||||
static void sigchld_handler(int signal)
|
|
||||||
{
|
|
||||||
pid_t pid;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
/* wait for the child that was signalled as finished */
|
|
||||||
if ((pid = wait(&status)) != -1) {
|
|
||||||
ProcInfo *p;
|
|
||||||
|
|
||||||
/* fill the procinfo structure with the necessary information */
|
|
||||||
for (p = proc_queue; p != NULL; p = p->next) {
|
|
||||||
if (p->pid == pid) {
|
|
||||||
p->status = status;
|
|
||||||
p->endtime = time(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int process_command_line(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
/* No error output from getopt */
|
|
||||||
opterr = 0;
|
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "c:a:p:fr:s:h")) > 0) {
|
|
||||||
char *end;
|
|
||||||
int temp_int;
|
|
||||||
|
|
||||||
switch(c) {
|
|
||||||
case 'c':
|
|
||||||
configfile = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
address = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
temp_int = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg != '\0') && (*end == '\0') &&
|
|
||||||
(temp_int > 0) && (temp_int <= 0xFFFF)) {
|
|
||||||
port = temp_int;
|
|
||||||
} else {
|
|
||||||
report(RPT_ERR, "Illegal port value %s", optarg);
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
foreground = TRUE;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
temp_int = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg != '\0') && (*end == '\0') && (temp_int >= 0)) {
|
|
||||||
report_level = temp_int;
|
|
||||||
} else {
|
|
||||||
report(RPT_ERR, "Illegal report level value %s", optarg);
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
temp_int = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg != '\0') && (*end == '\0') && (temp_int >= 0)) {
|
|
||||||
report_dest = (temp_int ? RPT_DEST_SYSLOG : RPT_DEST_STDERR);
|
|
||||||
} else {
|
|
||||||
report(RPT_ERR, "Illegal log destination value %s", optarg);
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
fprintf(stderr, "%s", help_text);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
/* NOTREACHED */
|
|
||||||
case ':':
|
|
||||||
report(RPT_ERR, "Missing option argument for %c", optopt);
|
|
||||||
error = -1;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
report(RPT_ERR, "Unknown option: %c", optopt);
|
|
||||||
error = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int process_configfile(char *configfile)
|
|
||||||
{
|
|
||||||
const char *tmp;
|
|
||||||
|
|
||||||
if (configfile == NULL)
|
|
||||||
configfile = DEFAULT_CONFIGFILE;
|
|
||||||
|
|
||||||
if (config_read_file(configfile) < 0) {
|
|
||||||
report(RPT_WARNING, "Could not read config file: %s", configfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (address == NULL) {
|
|
||||||
address = strdup(config_get_string(progname, "Address", 0, "localhost"));
|
|
||||||
}
|
|
||||||
if (port == UNSET_INT) {
|
|
||||||
port = config_get_int(progname, "Port", 0, 13666);
|
|
||||||
}
|
|
||||||
if (report_level == UNSET_INT) {
|
|
||||||
report_level = config_get_int(progname, "ReportLevel", 0, RPT_WARNING);
|
|
||||||
}
|
|
||||||
if (report_dest == UNSET_INT) {
|
|
||||||
report_dest = (config_get_bool(progname, "ReportToSyslog", 0, 0))
|
|
||||||
? RPT_DEST_SYSLOG
|
|
||||||
: RPT_DEST_STDERR;
|
|
||||||
}
|
|
||||||
if (foreground != TRUE) {
|
|
||||||
foreground = config_get_bool(progname, "Foreground", 0, FALSE);
|
|
||||||
}
|
|
||||||
if (pidfile == NULL) {
|
|
||||||
pidfile = strdup(config_get_string(progname, "PidFile", 0, DEFAULT_PIDFILE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmp = config_get_string(progname, "DisplayName", 0, NULL)) != NULL)
|
|
||||||
displayname = strdup(tmp);
|
|
||||||
|
|
||||||
/* try to find a shell that understands the -c COMMAND syntax */
|
|
||||||
if ((tmp = config_get_string(progname, "Shell", 0, NULL)) != NULL)
|
|
||||||
default_shell = strdup(tmp);
|
|
||||||
else {
|
|
||||||
/* 1st fallback: SHELL environment variable */
|
|
||||||
report(RPT_WARNING, "Shell not set in configuration, falling back to variable SHELL");
|
|
||||||
default_shell = getenv("SHELL");
|
|
||||||
|
|
||||||
/* 2nd fallback: /bin/sh */
|
|
||||||
if (default_shell == NULL) {
|
|
||||||
report(RPT_WARNING, "variable SHELL not set, falling back to /bin/sh");
|
|
||||||
default_shell = "/bin/sh";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main_menu = menu_read(NULL, "MainMenu");
|
|
||||||
#if defined(DEBUG)
|
|
||||||
menu_dump(main_menu);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// fail on non-existent main menu;
|
|
||||||
if (main_menu == NULL) {
|
|
||||||
report(RPT_ERR, "no main menu found in configuration");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int connect_and_setup(void)
|
|
||||||
{
|
|
||||||
report(RPT_INFO, "Connecting to %s:%d", address, port);
|
|
||||||
|
|
||||||
sock = sock_connect(address, port);
|
|
||||||
if (sock < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init connection and set client name */
|
|
||||||
sock_send_string(sock, "hello\n");
|
|
||||||
if (displayname != NULL) {
|
|
||||||
sock_printf(sock, "client_set -name {%s}\n", displayname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
struct utsname unamebuf;
|
|
||||||
|
|
||||||
if (uname(&unamebuf) == 0)
|
|
||||||
sock_printf(sock, "client_set -name {%s %s}\n", progname, unamebuf.nodename);
|
|
||||||
else
|
|
||||||
sock_printf(sock, "client_set -name {%s}\n", progname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create our menu */
|
|
||||||
if (menu_sock_send(main_menu, NULL, sock) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int process_response(char *str)
|
|
||||||
{
|
|
||||||
char *argv[20];
|
|
||||||
int argc;
|
|
||||||
char *str2 = strdup(str); /* get_args modifies str2 */
|
|
||||||
|
|
||||||
report(RPT_DEBUG, "Server said: \"%s\"", str);
|
|
||||||
|
|
||||||
/* Check what the server just said to us... */
|
|
||||||
argc = get_args(argv, str2, sizeof(argv)/sizeof(argv[0]));
|
|
||||||
if (argc < 1) {
|
|
||||||
free(str2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(argv[0], "menuevent") == 0) {
|
|
||||||
/* Ah, this is what we were waiting for ! */
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
report(RPT_WARNING, "Server gave invalid response");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((strcmp(argv[1], "select") == 0) ||
|
|
||||||
(strcmp(argv[1], "leave") == 0)) {
|
|
||||||
MenuEntry *entry;
|
|
||||||
|
|
||||||
if (argc < 3) {
|
|
||||||
report(RPT_WARNING, "Server gave invalid response");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the entry by id */
|
|
||||||
entry = menu_find_by_id(main_menu, atoi(argv[2]));
|
|
||||||
if (entry == NULL) {
|
|
||||||
report(RPT_WARNING, "Could not find the item id given by the server");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The id has been found.
|
|
||||||
* We trigger on the following conditions:
|
|
||||||
* - command entry without args
|
|
||||||
* - last arg of a command entry with args */
|
|
||||||
if (((entry->type == MT_EXEC) && (entry->children == NULL)) ||
|
|
||||||
((entry->type & MT_ARGUMENT) && (entry->next == NULL))) {
|
|
||||||
|
|
||||||
// last arg => get parent entry
|
|
||||||
if ((entry->type & MT_ARGUMENT) && (entry->next == NULL))
|
|
||||||
entry = entry->parent;
|
|
||||||
|
|
||||||
if (entry->type == MT_EXEC)
|
|
||||||
exec_command(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((strcmp(argv[1], "plus") == 0) ||
|
|
||||||
(strcmp(argv[1], "minus") == 0) ||
|
|
||||||
(strcmp(argv[1], "update") == 0)) {
|
|
||||||
MenuEntry *entry;
|
|
||||||
|
|
||||||
if (argc < 4) {
|
|
||||||
report(RPT_WARNING, "Server gave invalid response");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the entry by id */
|
|
||||||
entry = menu_find_by_id(main_menu, atoi(argv[2]));
|
|
||||||
if (entry == NULL) {
|
|
||||||
report(RPT_WARNING, "Could not find the item id given by the server");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (entry->type) {
|
|
||||||
case MT_ARG_SLIDER:
|
|
||||||
entry->data.slider.value = atoi(argv[3]);
|
|
||||||
break;
|
|
||||||
case MT_ARG_RING:
|
|
||||||
entry->data.ring.value = atoi(argv[3]);
|
|
||||||
break;
|
|
||||||
case MT_ARG_NUMERIC:
|
|
||||||
entry->data.numeric.value = atoi(argv[3]);
|
|
||||||
break;
|
|
||||||
case MT_ARG_ALPHA:
|
|
||||||
entry->data.alpha.value = realloc(entry->data.alpha.value,
|
|
||||||
strlen(argv[3]));
|
|
||||||
strcpy(entry->data.alpha.value, argv[3]);
|
|
||||||
break;
|
|
||||||
case MT_ARG_IP:
|
|
||||||
entry->data.ip.value = realloc(entry->data.ip.value,
|
|
||||||
strlen(argv[3]));
|
|
||||||
strcpy(entry->data.ip.value, argv[3]);
|
|
||||||
break;
|
|
||||||
case MT_ARG_CHECKBOX:
|
|
||||||
if ((entry->data.checkbox.allow_gray) &&
|
|
||||||
(strcasecmp(argv[3], "gray") == 0))
|
|
||||||
entry->data.checkbox.value = 2;
|
|
||||||
else if (strcasecmp(argv[3], "on") == 0)
|
|
||||||
entry->data.checkbox.value = 1;
|
|
||||||
else
|
|
||||||
entry->data.checkbox.value = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
report(RPT_WARNING, "Illegal menu entry type for event");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
; /* Ignore other menuevents */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "connect") == 0) {
|
|
||||||
int a;
|
|
||||||
|
|
||||||
/* determine display height and width */
|
|
||||||
for (a = 1; a < argc; a++) {
|
|
||||||
if (strcmp(argv[a], "wid") == 0)
|
|
||||||
lcd_wid = atoi(argv[++a]);
|
|
||||||
else if (strcmp(argv[a], "hgt") == 0)
|
|
||||||
lcd_hgt = atoi(argv[++a]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "bye") == 0) {
|
|
||||||
// TODO: make it better
|
|
||||||
report(RPT_INFO, "Server said: \"%s\"", str);
|
|
||||||
exit_program(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "huh?") == 0) {
|
|
||||||
/* Report errors */
|
|
||||||
report(RPT_WARNING, "Server said: \"%s\"", str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
; /* Ignore all other responses */
|
|
||||||
}
|
|
||||||
free(str2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int exec_command(MenuEntry *cmd)
|
|
||||||
{
|
|
||||||
if ((cmd != NULL) && (menu_command(cmd) != NULL)) {
|
|
||||||
const char *command = menu_command(cmd);
|
|
||||||
const char *argv[4];
|
|
||||||
pid_t pid;
|
|
||||||
ProcInfo *p;
|
|
||||||
char *envp[cmd->numChildren+1];
|
|
||||||
MenuEntry *arg;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* set argument vector */
|
|
||||||
argv[0] = default_shell;
|
|
||||||
argv[1] = "-c";
|
|
||||||
argv[2] = command;
|
|
||||||
argv[3] = NULL;
|
|
||||||
|
|
||||||
/* set environment vector: allocate & fill contents */
|
|
||||||
for (arg = cmd->children, i = 0; arg != NULL; arg = arg->next, i++) {
|
|
||||||
char buf[1025];
|
|
||||||
|
|
||||||
switch (arg->type) {
|
|
||||||
case MT_ARG_SLIDER:
|
|
||||||
snprintf(buf, sizeof(buf)-1, "%s=%d",
|
|
||||||
arg->name, arg->data.slider.value);
|
|
||||||
break;
|
|
||||||
case MT_ARG_RING:
|
|
||||||
snprintf(buf, sizeof(buf)-1, "%s=%s", arg->name,
|
|
||||||
arg->data.ring.strings[arg->data.ring.value]);
|
|
||||||
break;
|
|
||||||
case MT_ARG_NUMERIC:
|
|
||||||
snprintf(buf, sizeof(buf)-1, "%s=%d",
|
|
||||||
arg->name, arg->data.numeric.value);
|
|
||||||
break;
|
|
||||||
case MT_ARG_ALPHA:
|
|
||||||
snprintf(buf, sizeof(buf)-1, "%s=%s",
|
|
||||||
arg->name, arg->data.alpha.value);
|
|
||||||
break;
|
|
||||||
case MT_ARG_IP:
|
|
||||||
snprintf(buf, sizeof(buf)-1, "%s=%s",
|
|
||||||
arg->name, arg->data.ip.value);
|
|
||||||
break;
|
|
||||||
case MT_ARG_CHECKBOX:
|
|
||||||
if (arg->data.checkbox.map[arg->data.checkbox.value] != NULL)
|
|
||||||
strncpy(buf, arg->data.checkbox.map[arg->data.checkbox.value],
|
|
||||||
sizeof(buf)-1);
|
|
||||||
else
|
|
||||||
snprintf(buf, sizeof(buf)-1, "%s=%d",
|
|
||||||
arg->name, arg->data.checkbox.value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* error ? */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf[sizeof(buf)-1] ='\0';
|
|
||||||
envp[i] = strdup(buf);
|
|
||||||
|
|
||||||
debug(RPT_DEBUG, "Environment: %s", envp[i]);
|
|
||||||
}
|
|
||||||
envp[cmd->numChildren] = NULL;
|
|
||||||
|
|
||||||
debug(RPT_DEBUG, "Executing '%s' via Shell %s", command, default_shell);
|
|
||||||
|
|
||||||
switch (pid = fork()) {
|
|
||||||
case 0:
|
|
||||||
/* We're the child: execute the command */
|
|
||||||
execve(argv[0], (char **) argv, envp);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* We're the parent: setup the ProcInfo structure */
|
|
||||||
p = calloc(1, sizeof(ProcInfo));
|
|
||||||
if (p != NULL) {
|
|
||||||
p->cmd = cmd;
|
|
||||||
p->pid = pid;
|
|
||||||
p->starttime = time(NULL);
|
|
||||||
p->feedback = cmd->data.exec.feedback;
|
|
||||||
/* prepend it to existing queue atomically */
|
|
||||||
p->next = proc_queue;
|
|
||||||
proc_queue = p;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
report(RPT_ERR, "Could not fork");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* free envp's contents */
|
|
||||||
for (i = 0; envp[i] != NULL; i++)
|
|
||||||
free(envp[i]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int show_procinfo_msg(ProcInfo *p)
|
|
||||||
{
|
|
||||||
if ((p != NULL) && (lcd_wid > 0) && (lcd_hgt > 0)) {
|
|
||||||
if (p->endtime > 0) {
|
|
||||||
/* nothing to do => the quick way out (successful) */
|
|
||||||
if ((p->shown) || (!p->feedback))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
sock_printf(sock, "screen_add [%u]\n", p->pid);
|
|
||||||
sock_printf(sock, "screen_set [%u] -name {lcdexec [%u]}"
|
|
||||||
" -priority alert -timeout %d"
|
|
||||||
" -heartbeat off\n",
|
|
||||||
p->pid, p->pid, 6*8);
|
|
||||||
|
|
||||||
if (lcd_hgt > 2) {
|
|
||||||
sock_printf(sock, "widget_add [%u] t title\n", p->pid);
|
|
||||||
sock_printf(sock, "widget_set [%u] t {%s}\n", p->pid, p->cmd->displayname);
|
|
||||||
sock_printf(sock, "widget_add [%u] s1 string\n", p->pid);
|
|
||||||
sock_printf(sock, "widget_add [%u] s2 string\n", p->pid);
|
|
||||||
sock_printf(sock, "widget_add [%u] s3 string\n", p->pid);
|
|
||||||
|
|
||||||
sock_printf(sock, "widget_set [%u] s1 1 2 {[%u] finished%s}\n",
|
|
||||||
p->pid, p->pid, (WIFSIGNALED(p->status) ? "," : ""));
|
|
||||||
|
|
||||||
if (WIFEXITED(p->status)) {
|
|
||||||
if (WEXITSTATUS(p->status) == EXIT_SUCCESS) {
|
|
||||||
sock_printf(sock, "widget_set [%u] s2 1 3 {successfully.}\n",
|
|
||||||
p->pid);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_printf(sock, "widget_set [%u] s2 1 3 {with code 0x%02X.}\n",
|
|
||||||
p->pid, WEXITSTATUS(p->status));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (WIFSIGNALED(p->status)) {
|
|
||||||
sock_printf(sock, "widget_set [%u] s2 1 3 {killed by SIG %d.}\n",
|
|
||||||
p->pid, WTERMSIG(p->status));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcd_hgt > 3)
|
|
||||||
sock_printf(sock, "widget_set [%u] s3 1 4 {Exec time: %lds}\n",
|
|
||||||
p->pid, p->endtime - p->starttime);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_printf(sock, "widget_add [%u] s1 string\n", p->pid);
|
|
||||||
sock_printf(sock, "widget_add [%u] s2 string\n", p->pid);
|
|
||||||
sock_printf(sock, "widget_set [%u] s1 1 1 {%s}\n",
|
|
||||||
p->pid, p->cmd->displayname);
|
|
||||||
if (WIFEXITED(p->status)) {
|
|
||||||
if (WEXITSTATUS(p->status) == EXIT_SUCCESS) {
|
|
||||||
sock_printf(sock, "widget_set [%u] s2 1 2 {succeeded}\n",
|
|
||||||
p->pid, p->status);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_printf(sock, "widget_set [%u] s2 1 2 {finished (0x%02X)}\n",
|
|
||||||
p->pid, p->status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (WIFSIGNALED(p->status)) {
|
|
||||||
sock_printf(sock, "widget_set [%u] s2 1 2 {killed by SIG %d}\n",
|
|
||||||
p->pid, WTERMSIG(p->status));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int main_loop(void)
|
|
||||||
{
|
|
||||||
int num_bytes;
|
|
||||||
char buf[100];
|
|
||||||
int keepalive_delay = 0;
|
|
||||||
int status_delay = 0;
|
|
||||||
|
|
||||||
/* Continuously check if we get a menu event... */
|
|
||||||
while (!Quit && ((num_bytes = sock_recv_string(sock, buf, sizeof(buf)-1)) >= 0)) {
|
|
||||||
if (num_bytes == 0) {
|
|
||||||
ProcInfo *p;
|
|
||||||
|
|
||||||
/* wait for 1/10th of a second */
|
|
||||||
usleep(100000);
|
|
||||||
|
|
||||||
/* send an empty line every 3 seconds to make sure the server still exists */
|
|
||||||
if (keepalive_delay++ >= 30) {
|
|
||||||
keepalive_delay = 0;
|
|
||||||
if (sock_send_string(sock, "\n") < 0) {
|
|
||||||
break; /* Out of while loop */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for a screen to show and procinfo deletion every second */
|
|
||||||
if (status_delay++ >= 10) {
|
|
||||||
status_delay = 0;
|
|
||||||
|
|
||||||
/* delete the ProcInfo from the queue */
|
|
||||||
for (p = proc_queue; p != NULL; p = p->next) {
|
|
||||||
ProcInfo *pn = p->next;
|
|
||||||
|
|
||||||
if ((pn != NULL) && (pn->shown)) {
|
|
||||||
p->next = pn->next;
|
|
||||||
free(pn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* deleting queue head is special */
|
|
||||||
if ((proc_queue != NULL) && (proc_queue->shown)) {
|
|
||||||
p = proc_queue;
|
|
||||||
proc_queue = proc_queue->next;
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look for a process to display, display it & mark it as shown */
|
|
||||||
for (p = proc_queue; p != NULL; p = p->next) {
|
|
||||||
p->shown |= show_procinfo_msg(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
process_response(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Quit)
|
|
||||||
report(RPT_ERR, "Server disconnected (or connection error)");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
# lcdexec LCDproc client configuration file
|
|
||||||
|
|
||||||
## general options for lcdexec ##
|
|
||||||
[lcdexec]
|
|
||||||
# address of the LCDd server to connect to
|
|
||||||
Address=localhost
|
|
||||||
|
|
||||||
# Port of the server to connect to
|
|
||||||
Port=13666
|
|
||||||
|
|
||||||
# set reporting level
|
|
||||||
ReportLevel=2
|
|
||||||
|
|
||||||
# report to to syslog ?
|
|
||||||
ReportToSyslog=false
|
|
||||||
|
|
||||||
# run in foreground [default: false; legal: true, false]
|
|
||||||
Foreground=false
|
|
||||||
|
|
||||||
# PidFile location when running as daemon [default: /var/run/lcdexec.pid]
|
|
||||||
#PidFile=/var/run/lcdexec.pid
|
|
||||||
|
|
||||||
# shell to use for executing programsi
|
|
||||||
# [default: $SHELL or /bin/sh; legal: any shell that understands: -c COMMAND]
|
|
||||||
#Shell=/bin/sh
|
|
||||||
|
|
||||||
# display name for the main menu [default: lcdexec HOST]
|
|
||||||
#DisplayName=lcdexec
|
|
||||||
|
|
||||||
|
|
||||||
# main menu definition
|
|
||||||
[MainMenu]
|
|
||||||
# the Entry=... lines (one for each menu entry) tell it is a menu definition
|
|
||||||
Entry=CmdA
|
|
||||||
Entry=CmdB
|
|
||||||
Entry=MenuC
|
|
||||||
|
|
||||||
# definition of a command
|
|
||||||
[CmdA]
|
|
||||||
# name to display in the menu instead of the section name
|
|
||||||
DisplayName="You can say A"
|
|
||||||
# the exec=... line tells that it is a command
|
|
||||||
Exec="echo a"
|
|
||||||
# show a temporary feedback screen upon completion [default: no; legal: yes, no]
|
|
||||||
Feedback= yes
|
|
||||||
|
|
||||||
[CmdB]
|
|
||||||
DisplayName="Or you can say B"
|
|
||||||
Exec="echo b"
|
|
||||||
|
|
||||||
# definition of a menu
|
|
||||||
# a menu contains an Entry=... line for each menu entry
|
|
||||||
[MenuC]
|
|
||||||
DisplayName="A menu"
|
|
||||||
Entry=CmdP
|
|
||||||
Entry=CmdQ
|
|
||||||
|
|
||||||
[CmdP]
|
|
||||||
DisplayName=P
|
|
||||||
Exec="echo P"
|
|
||||||
|
|
||||||
[CmdQ]
|
|
||||||
DisplayName="Show environment"
|
|
||||||
Exec="env"
|
|
||||||
# Now you can change parameters for commands within lcdexec.
|
|
||||||
# Parameters are handed to the program as environment variables;
|
|
||||||
# so they can be easily used in the Exec=... line as $XXX
|
|
||||||
# (e.g. "echo $SLIDER_ARG").
|
|
||||||
# Please note: commands with parameters get an action entry
|
|
||||||
# added to end of the parameter menu automatically.
|
|
||||||
# Activating this action named "Apply!" will execute the program.
|
|
||||||
# This is IMHO not ideal, but the best idea I could come up with.
|
|
||||||
# I'm open for ideas to improve it.
|
|
||||||
# Here's how paramters get defined:
|
|
||||||
Parameter=SLIDER_ARG
|
|
||||||
Parameter=RING_ARG
|
|
||||||
Parameter=NUMERIC_ARG
|
|
||||||
Parameter=ALPHA_ARG
|
|
||||||
Parameter=CHECKBOX_ARG
|
|
||||||
Parameter=IP_ARG
|
|
||||||
|
|
||||||
[SLIDER_ARG]
|
|
||||||
DisplayName="Slider"
|
|
||||||
# Type of argument widget [legal: Slider, Checkbox, Ring, Numeric, Alpha, IP]
|
|
||||||
Type=Slider
|
|
||||||
# inital value of the argument
|
|
||||||
Value=5
|
|
||||||
# options depending on the widget type
|
|
||||||
MinValue=0
|
|
||||||
MaxValue=10
|
|
||||||
|
|
||||||
[CHECKBOX_ARG]
|
|
||||||
DisplayName="Checkbox"
|
|
||||||
Type=Checkbox
|
|
||||||
Value=on
|
|
||||||
AllowGray=yes
|
|
||||||
# replacement texts for the possible values
|
|
||||||
OffText="off"
|
|
||||||
OnText="on"
|
|
||||||
GrayText="gray"
|
|
||||||
|
|
||||||
[RING_ARG]
|
|
||||||
DisplayName="Ring"
|
|
||||||
Type=Ring
|
|
||||||
Value=0
|
|
||||||
# list of alternative strings to choose from
|
|
||||||
String=Eins
|
|
||||||
String=Zwei
|
|
||||||
String=Drei
|
|
||||||
|
|
||||||
[NUMERIC_ARG]
|
|
||||||
DisplayName="Numeric"
|
|
||||||
Type=Numeric
|
|
||||||
Value=5
|
|
||||||
MinValue=0
|
|
||||||
MaxValue=10
|
|
||||||
|
|
||||||
[ALPHA_ARG]
|
|
||||||
DisplayName="Alpha"
|
|
||||||
Type=Alpha
|
|
||||||
# range of characters allowed [default: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
|
|
||||||
AllowedChars = "+-0123456789ABCDEF"
|
|
||||||
Value=5
|
|
||||||
MinLength=0
|
|
||||||
MaxLength=10
|
|
||||||
|
|
||||||
[IP_ARG]
|
|
||||||
DisplayName="IP"
|
|
||||||
Type=IP
|
|
||||||
Value=10.230.2.2
|
|
||||||
v6=no
|
|
||||||
|
|
||||||
|
|
||||||
# Ideas for further extensions (patches welcome):
|
|
||||||
# - shell selectable in command sections
|
|
||||||
# - display configurable result of a command on the display
|
|
||||||
# - jump to other menus depending on the output/result of a command
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
@@ -1,641 +0,0 @@
|
|||||||
/** \file clients/lcdexec/menu.c
|
|
||||||
* Menu parsing and building functions for the \c lcdexec client
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This file is part of lcdexec, an LCDproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License. Refer to the
|
|
||||||
* COPYING file distributed with this package.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Joris Robijn
|
|
||||||
* Copyright (c) 2006-7, Peter Marschall
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "menu.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* names for boolean and tristate values */
|
|
||||||
static char *boolValueName[] = { "false", "true" };
|
|
||||||
static char *triGrayValueName[] = { "off", "on", "gray" };
|
|
||||||
|
|
||||||
|
|
||||||
/** recursively read the menu hierarchy */
|
|
||||||
MenuEntry *menu_read(MenuEntry *parent, const char *name)
|
|
||||||
{
|
|
||||||
static int id = 0;
|
|
||||||
|
|
||||||
if ((name != NULL) && (config_has_section(name))) {
|
|
||||||
MenuEntry *me = calloc(1, sizeof(MenuEntry)); // auto-NULL elements
|
|
||||||
|
|
||||||
if (me == NULL)
|
|
||||||
return NULL;
|
|
||||||
// set common entries
|
|
||||||
me->id = id++;
|
|
||||||
me->name = strdup(name);
|
|
||||||
if (me->name == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
me->displayname = strdup(config_get_string(name, "DisplayName", 0, name));
|
|
||||||
if (me->displayname == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
me->parent = parent;
|
|
||||||
me->next = NULL;
|
|
||||||
me->children = NULL;
|
|
||||||
me->numChildren = 0;
|
|
||||||
|
|
||||||
if (config_get_string(name, "Entry", 0, NULL) != NULL) {
|
|
||||||
MenuEntry **addr = &me->children;
|
|
||||||
const char *entryname;
|
|
||||||
|
|
||||||
// it is a sub-menu
|
|
||||||
me->type = MT_MENU;
|
|
||||||
|
|
||||||
// read menu entries
|
|
||||||
while ((entryname = config_get_string(name, "Entry", me->numChildren, NULL)) != NULL) {
|
|
||||||
MenuEntry *entry = menu_read(me, entryname);
|
|
||||||
|
|
||||||
if (entry == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
me->numChildren++;
|
|
||||||
|
|
||||||
*addr = entry;
|
|
||||||
addr = &entry->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (config_get_string(name, "Exec", 0, NULL) != NULL) {
|
|
||||||
MenuEntry **addr = &me->children;
|
|
||||||
const char *entryname;
|
|
||||||
|
|
||||||
// it's a command to execute
|
|
||||||
me->type = MT_EXEC;
|
|
||||||
|
|
||||||
me->data.exec.command = strdup(config_get_string(name, "Exec", 0, ""));
|
|
||||||
if (me->data.exec.command == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
me->data.exec.feedback = config_get_bool(name, "Feedback", 0, 0);
|
|
||||||
|
|
||||||
// try to read parameters
|
|
||||||
while ((entryname = config_get_string(name, "Parameter", me->numChildren, NULL)) != NULL) {
|
|
||||||
MenuEntry *entry = menu_read(me, entryname);
|
|
||||||
|
|
||||||
if (entry == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
me->numChildren++;
|
|
||||||
|
|
||||||
*addr = entry;
|
|
||||||
addr = &entry->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// automagically add an "Apply ?" action
|
|
||||||
if ((me->numChildren > 0) && (addr != NULL))
|
|
||||||
*addr = menu_read(me, NULL);
|
|
||||||
}
|
|
||||||
else if (config_get_string(name, "Type", 0, NULL) != NULL) {
|
|
||||||
// it's a command parameter
|
|
||||||
const char *type;
|
|
||||||
|
|
||||||
type = config_get_string(name, "Type", 0, "");
|
|
||||||
|
|
||||||
if (strcasecmp(type, "slider") == 0) {
|
|
||||||
char buf[35];
|
|
||||||
|
|
||||||
me->type = MT_ARG_SLIDER;
|
|
||||||
|
|
||||||
me->data.slider.value = config_get_int(name, "Value", 0, 0);
|
|
||||||
me->data.slider.minval = config_get_int(name, "MinValue", 0, 0);
|
|
||||||
me->data.slider.maxval = config_get_int(name, "MaxValue", 0, 1000);
|
|
||||||
|
|
||||||
sprintf(buf, "%d", me->data.slider.minval);
|
|
||||||
me->data.slider.mintext = strdup(config_get_string(name, "MinText", 0, buf));
|
|
||||||
sprintf(buf, "%d", me->data.slider.maxval);
|
|
||||||
me->data.slider.maxtext = strdup(config_get_string(name, "MaxText", 0, buf));
|
|
||||||
|
|
||||||
me->data.slider.stepsize = config_get_int(name, "StepSize", 0, 1);
|
|
||||||
}
|
|
||||||
else if (strcasecmp(type, "ring") == 0) {
|
|
||||||
const char *tmp;
|
|
||||||
int numStrings = 0;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
me->type = MT_ARG_RING;
|
|
||||||
|
|
||||||
me->data.ring.value = config_get_int(name, "Value", 0, 0);
|
|
||||||
numStrings = config_has_key(name, "String");
|
|
||||||
me->data.ring.strings = calloc(sizeof(char *), numStrings+1);
|
|
||||||
me->data.ring.strings[numStrings] = NULL;
|
|
||||||
|
|
||||||
while ((tmp = config_get_string(name, "String", i, NULL)) != NULL) {
|
|
||||||
me->data.ring.strings[i] = strdup(tmp);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
me->data.ring.strings[i] = NULL;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(type, "numeric") == 0) {
|
|
||||||
me->type = MT_ARG_NUMERIC;
|
|
||||||
|
|
||||||
me->data.numeric.value = config_get_int(name, "Value", 0, 0);
|
|
||||||
me->data.numeric.minval = config_get_int(name, "MinValue", 0, 0);
|
|
||||||
me->data.numeric.maxval = config_get_int(name, "MaxValue", 0, 1000);
|
|
||||||
}
|
|
||||||
else if (strcasecmp(type, "alpha") == 0) {
|
|
||||||
me->type = MT_ARG_ALPHA;
|
|
||||||
|
|
||||||
me->data.alpha.value = strdup(config_get_string(name, "Value", 0, ""));
|
|
||||||
me->data.alpha.minlen = config_get_int(name, "MinLength", 0, 0);
|
|
||||||
me->data.alpha.maxlen = config_get_int(name, "MaxLength", 0, 100);
|
|
||||||
me->data.alpha.allowed = strdup(config_get_string(name, "AllowedChars", 0,
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
|
|
||||||
}
|
|
||||||
else if (strcasecmp(type, "ip") == 0) {
|
|
||||||
me->type = MT_ARG_IP;
|
|
||||||
|
|
||||||
me->data.ip.value = strdup(config_get_string(name, "Value", 0, ""));
|
|
||||||
me->data.ip.v6 = config_get_bool(name, "Value", 0, 0);
|
|
||||||
}
|
|
||||||
else if (strcasecmp(type, "checkbox") == 0) {
|
|
||||||
const char *tmp;
|
|
||||||
|
|
||||||
me->type = MT_ARG_CHECKBOX;
|
|
||||||
|
|
||||||
me->data.checkbox.allow_gray = config_get_bool(name, "AllowGray", 0, 0);
|
|
||||||
me->data.checkbox.value = (me->data.checkbox.allow_gray)
|
|
||||||
? config_get_tristate(name, "Value", 0, "gray", 0)
|
|
||||||
: config_get_bool(name, "Value", 0, 0);
|
|
||||||
// get replacement strings for different values
|
|
||||||
tmp = config_get_string(name, "OffText", 0, NULL);
|
|
||||||
me->data.checkbox.map[0] = (tmp != NULL) ? strdup(tmp) : NULL;
|
|
||||||
tmp = config_get_string(name, "OnText", 0, NULL);
|
|
||||||
me->data.checkbox.map[1] = (tmp != NULL) ? strdup(tmp) : NULL;
|
|
||||||
tmp = config_get_string(name, "GrayText", 0, NULL);
|
|
||||||
me->data.checkbox.map[2] = (tmp != NULL) ? strdup(tmp) : NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
report(RPT_DEBUG, "illegal parameter type");
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
report(RPT_DEBUG, "unknown menu entry type");
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return me;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* the magic stuff: if name is NULL and parent is an EXEC entry,
|
|
||||||
* then generate an Action entry with the name "Apply" */
|
|
||||||
if ((name == NULL) && (parent != NULL) && (parent->type = MT_EXEC)) {
|
|
||||||
MenuEntry *me = calloc(1, sizeof(MenuEntry)); // auto-NULL elements
|
|
||||||
|
|
||||||
if (me == NULL)
|
|
||||||
return NULL;
|
|
||||||
// set common entries
|
|
||||||
me->id = id++;
|
|
||||||
me->name = malloc(strlen(parent->name) + 10);
|
|
||||||
if (me->name == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
strcpy(me->name, "Apply_");
|
|
||||||
strcat(me->name, parent->name);
|
|
||||||
|
|
||||||
me->displayname = strdup("Apply!");
|
|
||||||
if (me->displayname == NULL) {
|
|
||||||
//menu_free(me);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
me->parent = parent;
|
|
||||||
me->next = NULL;
|
|
||||||
me->children = NULL;
|
|
||||||
me->numChildren = 0;
|
|
||||||
me->type = MT_ARG_ACTION | MT_AUTOMATIC;
|
|
||||||
|
|
||||||
return me;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** create LCDproc commands for the menu entry hierarchy and send it to the server */
|
|
||||||
int menu_sock_send(MenuEntry *me, MenuEntry *parent, int sock)
|
|
||||||
{
|
|
||||||
if ((me != NULL) && (sock > 0)) {
|
|
||||||
char parent_id[12];
|
|
||||||
|
|
||||||
// set parent_id depending on the parent given
|
|
||||||
if ((parent != NULL) && (parent->id != 0))
|
|
||||||
sprintf(parent_id, "%d", parent->id);
|
|
||||||
else
|
|
||||||
strcpy(parent_id, "");
|
|
||||||
|
|
||||||
switch (me->type) {
|
|
||||||
MenuEntry *entry;
|
|
||||||
|
|
||||||
case MT_MENU:
|
|
||||||
// don't create a separate entry for the main menu
|
|
||||||
if ((parent != NULL) && (me->id != 0)) {
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" menu \"%s\"\n",
|
|
||||||
parent_id, me->id, me->displayname) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// recursively do it for the menu's sub-menus
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next) {
|
|
||||||
if (menu_sock_send(entry, me, sock) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_EXEC:
|
|
||||||
if (me->children == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" action \"%s\"\n",
|
|
||||||
parent_id, me->id, me->displayname) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -menu_result quit\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((parent != NULL) && (me->id != 0)) {
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" menu \"%s\"\n",
|
|
||||||
parent_id, me->id, me->displayname) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// (recursively) do it for the entry's parameters
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next) {
|
|
||||||
if (menu_sock_send(entry, me, sock) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_SLIDER:
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" slider -text \"%s\""
|
|
||||||
" -value %d -minvalue %d -maxvalue %d"
|
|
||||||
" -mintext \"%s\" -maxtext \"%s\" -stepsize %d\n",
|
|
||||||
parent_id, me->id, me->displayname,
|
|
||||||
me->data.slider.value,
|
|
||||||
me->data.slider.minval,
|
|
||||||
me->data.slider.maxval,
|
|
||||||
me->data.slider.mintext,
|
|
||||||
me->data.slider.maxtext,
|
|
||||||
me->data.slider.stepsize) <0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (me->next == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -next _quit_\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_RING:
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *tmp = strdup("");
|
|
||||||
|
|
||||||
// join all strings with TAB as separator
|
|
||||||
for (i = 0; me->data.ring.strings[i] != NULL; i++) {
|
|
||||||
tmp = realloc(tmp, strlen(tmp) + 1 +
|
|
||||||
strlen(me->data.ring.strings[i]) + 1);
|
|
||||||
if (tmp[0] != '\0')
|
|
||||||
strcat(tmp, "\t");
|
|
||||||
strcat(tmp, me->data.ring.strings[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" ring -text \"%s\""
|
|
||||||
" -value %d -strings \"%s\"\n",
|
|
||||||
parent_id, me->id, me->displayname,
|
|
||||||
me->data.ring.value,
|
|
||||||
tmp) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->next == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -next _quit_\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_NUMERIC:
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" numeric -text \"%s\""
|
|
||||||
" -value %d -minvalue %d -maxvalue %d\n",
|
|
||||||
parent_id, me->id, me->displayname,
|
|
||||||
me->data.numeric.value,
|
|
||||||
me->data.numeric.minval,
|
|
||||||
me->data.numeric.maxval) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (me->next == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -next _quit_\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_ALPHA:
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" alpha -text \"%s\""
|
|
||||||
" -value \"%s\" -minlength %d -maxlength %d"
|
|
||||||
" -allow_caps false -allow_noncaps false"
|
|
||||||
" -allow_numbers false -allowed_extra \"%s\"\n",
|
|
||||||
parent_id, me->id, me->displayname,
|
|
||||||
me->data.alpha.value,
|
|
||||||
me->data.alpha.minlen,
|
|
||||||
me->data.alpha.maxlen,
|
|
||||||
me->data.alpha.allowed) <0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (me->next == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -next _quit_\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_IP:
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" ip -text \"%s\""
|
|
||||||
" -value \"%s\" -v6 %s\n",
|
|
||||||
parent_id, me->id, me->displayname,
|
|
||||||
me->data.ip.value,
|
|
||||||
boolValueName[me->data.ip.v6]) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (me->next == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -next _quit_\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_CHECKBOX:
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" checkbox -text \"%s\""
|
|
||||||
" -value %s -allow_gray %s\n",
|
|
||||||
parent_id, me->id, me->displayname,
|
|
||||||
triGrayValueName[me->data.checkbox.value],
|
|
||||||
boolValueName[me->data.checkbox.allow_gray]) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (me->next == NULL) {
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -next _quit_\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_AUTOMATIC:
|
|
||||||
case MT_ARG_ACTION:
|
|
||||||
if (sock_printf(sock, "menu_add_item \"%s\" \"%d\" action \"%s\"\n",
|
|
||||||
parent_id, me->id, me->displayname) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (sock_printf(sock, "menu_set_item \"%s\" \"%d\" -menu_result quit\n",
|
|
||||||
parent_id, me->id) < 0)
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** find menu entry by its id */
|
|
||||||
MenuEntry *menu_find_by_id(MenuEntry *me, int id)
|
|
||||||
{
|
|
||||||
if (me != NULL) {
|
|
||||||
if (me->id == id)
|
|
||||||
return me;
|
|
||||||
|
|
||||||
if ((me->type == MT_MENU) || (me->type == MT_EXEC)) {
|
|
||||||
MenuEntry *entry;
|
|
||||||
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next) {
|
|
||||||
MenuEntry *result = menu_find_by_id(entry, id);
|
|
||||||
|
|
||||||
if (result != NULL)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** return command of a menu entry */
|
|
||||||
const char *menu_command(MenuEntry *me)
|
|
||||||
{
|
|
||||||
if ((me != NULL) && (me->type == MT_EXEC))
|
|
||||||
return me->data.exec.command;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** free menu entry hierarchy */
|
|
||||||
void menu_free(MenuEntry *me)
|
|
||||||
{
|
|
||||||
if (me != NULL) {
|
|
||||||
MenuEntry *entry;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (me->type) {
|
|
||||||
case MT_EXEC:
|
|
||||||
if (me->data.exec.command != NULL)
|
|
||||||
free(me->data.exec.command);
|
|
||||||
me->data.exec.command = NULL;
|
|
||||||
/* fall through */
|
|
||||||
case MT_MENU:
|
|
||||||
for (entry = me->children; entry != NULL; ) {
|
|
||||||
MenuEntry *old = entry;
|
|
||||||
|
|
||||||
entry = entry->next;
|
|
||||||
old->next = NULL;
|
|
||||||
menu_free(old);
|
|
||||||
}
|
|
||||||
me->children = NULL;
|
|
||||||
break;
|
|
||||||
case MT_ARG_SLIDER:
|
|
||||||
if (me->data.slider.mintext != NULL)
|
|
||||||
free(me->data.slider.mintext);
|
|
||||||
me->data.slider.mintext = NULL;
|
|
||||||
if (me->data.slider.maxtext != NULL)
|
|
||||||
free(me->data.slider.maxtext);
|
|
||||||
me->data.slider.maxtext = NULL;
|
|
||||||
break;
|
|
||||||
case MT_ARG_RING:
|
|
||||||
if (me->data.ring.strings != NULL) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; me->data.ring.strings[i] != NULL; i++)
|
|
||||||
free(me->data.ring.strings[i]);
|
|
||||||
|
|
||||||
free(me->data.ring.strings);
|
|
||||||
me->data.ring.strings = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MT_ARG_ALPHA:
|
|
||||||
if (me->data.alpha.value != NULL)
|
|
||||||
free(me->data.alpha.value);
|
|
||||||
me->data.alpha.value = NULL;
|
|
||||||
if (me->data.alpha.allowed != NULL)
|
|
||||||
free(me->data.alpha.allowed);
|
|
||||||
me->data.alpha.allowed = NULL;
|
|
||||||
break;
|
|
||||||
case MT_ARG_IP:
|
|
||||||
if (me->data.ip.value != NULL)
|
|
||||||
free(me->data.ip.value);
|
|
||||||
me->data.ip.value = NULL;
|
|
||||||
break;
|
|
||||||
case MT_ARG_CHECKBOX:
|
|
||||||
for (i = 0; i < sizeof(me->data.checkbox.map)/sizeof(me->data.checkbox.map[0]); i++) {
|
|
||||||
if (me->data.checkbox.map[i] != NULL) {
|
|
||||||
free(me->data.checkbox.map[i]);
|
|
||||||
me->data.checkbox.map[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->name != NULL)
|
|
||||||
free(me->name);
|
|
||||||
me->name = NULL;
|
|
||||||
|
|
||||||
if (me->displayname != NULL)
|
|
||||||
free(me->displayname);
|
|
||||||
me->displayname = NULL;
|
|
||||||
|
|
||||||
me->type = MT_UNKNOWN;
|
|
||||||
|
|
||||||
free(me);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(DEBUG)
|
|
||||||
/** dump menu entry hierarchy to screen */
|
|
||||||
void menu_dump(MenuEntry *me)
|
|
||||||
{
|
|
||||||
if (me != NULL) {
|
|
||||||
/* the quick way out */
|
|
||||||
if (me->type & MT_AUTOMATIC)
|
|
||||||
return;
|
|
||||||
|
|
||||||
report(RPT_DEBUG, "# menu ID: %d", me->id);
|
|
||||||
report(RPT_DEBUG, "[%s]", me->name);
|
|
||||||
if (me->displayname != NULL)
|
|
||||||
report(RPT_DEBUG, "DisplayName=\"%s\"", me->displayname);
|
|
||||||
|
|
||||||
switch (me->type) {
|
|
||||||
MenuEntry *entry;
|
|
||||||
|
|
||||||
case MT_MENU:
|
|
||||||
// dump menu entry references
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next)
|
|
||||||
report(RPT_DEBUG, "Entry=%s", entry->name);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
|
|
||||||
// recursively walk through sub-menus
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next)
|
|
||||||
menu_dump(entry);
|
|
||||||
break;
|
|
||||||
case MT_EXEC:
|
|
||||||
report(RPT_DEBUG, "Exec=\"%s\"", me->data.exec.command);
|
|
||||||
report(RPT_DEBUG, "Feedback=%s", boolValueName[me->data.exec.feedback]);
|
|
||||||
|
|
||||||
// dump entry's parameter referencess
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next)
|
|
||||||
report(RPT_DEBUG, "Parameter=%s", entry->name);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
|
|
||||||
// dump entry's parameters
|
|
||||||
for (entry = me->children; entry != NULL; entry = entry->next)
|
|
||||||
menu_dump(entry);
|
|
||||||
break;
|
|
||||||
case MT_ARG_SLIDER:
|
|
||||||
report(RPT_DEBUG, "Type=slider");
|
|
||||||
report(RPT_DEBUG, "Value=%d", me->data.slider.value);
|
|
||||||
report(RPT_DEBUG, "MinValue=%d", me->data.slider.minval);
|
|
||||||
report(RPT_DEBUG, "MaxValue=%d", me->data.slider.maxval);
|
|
||||||
report(RPT_DEBUG, "Stepsize=%d", me->data.slider.stepsize);
|
|
||||||
report(RPT_DEBUG, "MinText=%s", me->data.slider.mintext);
|
|
||||||
report(RPT_DEBUG, "MaxText=%s", me->data.slider.maxtext);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
break;
|
|
||||||
case MT_ARG_RING:
|
|
||||||
report(RPT_DEBUG, "Type=ring");
|
|
||||||
report(RPT_DEBUG, "Value: %d", me->data.ring.value);
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; me->data.ring.strings[i] != NULL; i++)
|
|
||||||
report(RPT_DEBUG, "String=\"%s\"", me->data.ring.strings[i]);
|
|
||||||
}
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
break;
|
|
||||||
case MT_ARG_NUMERIC:
|
|
||||||
report(RPT_DEBUG, "Type=numeric");
|
|
||||||
report(RPT_DEBUG, "Value=%d", me->data.numeric.value);
|
|
||||||
report(RPT_DEBUG, "MinValue=%d", me->data.numeric.minval);
|
|
||||||
report(RPT_DEBUG, "MaxValue=%d", me->data.numeric.maxval);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
break;
|
|
||||||
case MT_ARG_ALPHA:
|
|
||||||
report(RPT_DEBUG, "Type:=lpha");
|
|
||||||
report(RPT_DEBUG, "Value=\"%s\"", me->data.alpha.value);
|
|
||||||
report(RPT_DEBUG, "AllowedChars=\"%s\"", me->data.alpha.allowed);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
break;
|
|
||||||
case MT_ARG_IP:
|
|
||||||
report(RPT_DEBUG, "Type=ip");
|
|
||||||
report(RPT_DEBUG, "Value=\"%s\"", me->data.ip.value);
|
|
||||||
report(RPT_DEBUG, "V6=%s", boolValueName[me->data.ip.v6]);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
break;
|
|
||||||
case MT_ARG_CHECKBOX:
|
|
||||||
report(RPT_DEBUG, "Type=ip");
|
|
||||||
report(RPT_DEBUG, "Value=%s", triGrayValueName[me->data.checkbox.value]);
|
|
||||||
report(RPT_DEBUG, "AllowGray=%s", boolValueName[me->data.checkbox.allow_gray]);
|
|
||||||
if (me->data.checkbox.map[0] != NULL)
|
|
||||||
report(RPT_DEBUG, "OffText=%s", me->data.checkbox.map[0]);
|
|
||||||
if (me->data.checkbox.map[1] != NULL)
|
|
||||||
report(RPT_DEBUG, "OnText=%s", me->data.checkbox.map[1]);
|
|
||||||
if (me->data.checkbox.map[2] != NULL)
|
|
||||||
report(RPT_DEBUG, "GrayText=%s", me->data.checkbox.map[2]);
|
|
||||||
report(RPT_DEBUG, "");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
report(RPT_DEBUG, "ERROR: unknown menu entry type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* EOF */
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
/** \file clients/lcdexec/menu.h
|
|
||||||
* Declare constants, data types and functions for menu functions in clients/lcdexec/menu.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This file is part of lcdexec, an LCDproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License. Refer to the
|
|
||||||
* COPYING file distributed with this package.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Joris Robijn
|
|
||||||
* Copyright (c) 2006-7, Peter Marschall
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LCDEXEC_MENU_H
|
|
||||||
#define LCDEXEC_MENU_H
|
|
||||||
|
|
||||||
/* boolean values */
|
|
||||||
#ifndef TRUE
|
|
||||||
# define TRUE 1
|
|
||||||
#endif
|
|
||||||
#ifndef FALSE
|
|
||||||
# define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** Symbolic names for the types of a MenuEntry */
|
|
||||||
typedef enum {
|
|
||||||
MT_UNKNOWN = 0x00, /**< Unknown MenuEntry type. */
|
|
||||||
MT_MENU = 0x10, /**< MenuEntry representing a menu. */
|
|
||||||
MT_EXEC = 0x20, /**< MenuEntry representing an executable command. */
|
|
||||||
MT_ARGUMENT = 0x40, /**< Mask denoting a parameter of any type */
|
|
||||||
MT_AUTOMATIC = 0x80, /**< BitFlag denoting automatically generated entries */
|
|
||||||
|
|
||||||
MT_ARG_SLIDER = 0x41, /**< MenuEntry representing a slider parameter. */
|
|
||||||
MT_ARG_RING = 0x42, /**< MenuEntry representing a ring parameter. */
|
|
||||||
MT_ARG_NUMERIC = 0x43, /**< MenuEntry representing a numeric input parameter. */
|
|
||||||
MT_ARG_ALPHA = 0x44, /**< MenuEntry representing a alpha input parameter. */
|
|
||||||
MT_ARG_IP = 0x45, /**< MenuEntry representing a IP input parameter. */
|
|
||||||
MT_ARG_CHECKBOX = 0x46, /**< MenuEntry representing a checkbox input parameter. */
|
|
||||||
MT_ARG_ACTION = 0x47, /**< MenuEntry representing a checkbox input parameter. */
|
|
||||||
} MenuType;
|
|
||||||
|
|
||||||
|
|
||||||
/** Data structure to hold a menu entry in \c lcdexec */
|
|
||||||
typedef struct menu_entry {
|
|
||||||
// Variables necessary for multiple/all types
|
|
||||||
char *name; /**< Name of the menu entry (from section name). */
|
|
||||||
char *displayname; /**< Visible name of the entry. */
|
|
||||||
int id; /**< Internal ID of the entry. */
|
|
||||||
MenuType type; /**< Type of the entry. */
|
|
||||||
struct menu_entry *parent; /**< Parent menu entry. */
|
|
||||||
int numChildren; /**< # of child entries. */
|
|
||||||
struct menu_entry *children; /**< Subordinate menu entries (for type \c MT_MENU & \c MT_EXEC). */
|
|
||||||
struct menu_entry *next; /**< Next sibling menu entry (for type \c MT_MENU). */
|
|
||||||
|
|
||||||
// Variables specific to one special type
|
|
||||||
union data {
|
|
||||||
struct exec{ // elements necessary for type MT_EXEC
|
|
||||||
char *command; /**< Command to execute. */
|
|
||||||
int feedback; /**< Feedback flag. */
|
|
||||||
} exec;
|
|
||||||
struct slider { // elements necessary for type MT_ARG_SLIDER
|
|
||||||
int value; /**< Numeric value of slider. */
|
|
||||||
int minval; /**< Minimal allowed value. */
|
|
||||||
int maxval; /**< Maximal allowed value. */
|
|
||||||
int stepsize; /**< Increments/decrement for value. */
|
|
||||||
char *mintext; /**< Label for the min. value. */
|
|
||||||
char *maxtext; /**< Label for the max. value. */
|
|
||||||
} slider;
|
|
||||||
struct ring { // elements necessary for type MT_ARG_RING
|
|
||||||
int value; /**< Index into list of alternatives. */
|
|
||||||
char **strings; /**< List of alternatives. */
|
|
||||||
} ring;
|
|
||||||
struct numeric { // elements necessary for type MT_ARG_NUMERIC
|
|
||||||
int value; /**< Numeric input value. */
|
|
||||||
int minval; /**< Minimal allowed value. */
|
|
||||||
int maxval; /**< Maximal allowed value. */
|
|
||||||
} numeric;
|
|
||||||
struct alpha { // elements necessary for type MT_ARG_ALPHA
|
|
||||||
char *value; /**< Text value. */
|
|
||||||
int minlen; /**< Maximal allowed length. */
|
|
||||||
int maxlen; /**< Minimal required length. */
|
|
||||||
char *allowed; /**< Characters allowed in input. */
|
|
||||||
} alpha;
|
|
||||||
struct ip { // elements necessary for type MT_ARG_IP
|
|
||||||
char *value; /**< IP address value. */
|
|
||||||
int v6; /**< Flag: use IPv6 editing logic. */
|
|
||||||
} ip;
|
|
||||||
struct checkbox { // elements necessary for type MT_ARG_CHECKBOX
|
|
||||||
int value; /**< Checkbox value. */
|
|
||||||
int allow_gray; /**< Flag for tristate chechboxes. */
|
|
||||||
char *map[3]; /**< Replacement strings for each value. */
|
|
||||||
} checkbox;
|
|
||||||
} data;
|
|
||||||
} MenuEntry;
|
|
||||||
|
|
||||||
|
|
||||||
MenuEntry *menu_read(MenuEntry *parent, const char *name);
|
|
||||||
int menu_sock_send(MenuEntry *me, MenuEntry *parent, int sock);
|
|
||||||
MenuEntry *menu_find_by_id(MenuEntry *me, int id);
|
|
||||||
const char *menu_command(MenuEntry *me);
|
|
||||||
void menu_free(MenuEntry *me);
|
|
||||||
void menu_dump(MenuEntry *me);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.deps
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
lcdproc
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
sysconf_DATA = lcdproc.conf
|
|
||||||
|
|
||||||
bin_PROGRAMS = lcdproc
|
|
||||||
|
|
||||||
lcdproc_SOURCES = main.c main.h mode.c mode.h batt.c batt.h chrono.c chrono.h cpu.c cpu.h cpu_smp.c cpu_smp.h disk.c disk.h load.c load.h mem.c mem.h eyebox.c eyebox.h machine.h machine_Linux.c machine_OpenBSD.c machine_FreeBSD.c machine_NetBSD.c machine_Darwin.c machine_SunOS.c util.c util.h iface.c iface.h
|
|
||||||
|
|
||||||
lcdproc_LDADD = ../../shared/libLCDstuff.a
|
|
||||||
|
|
||||||
if DARWIN
|
|
||||||
AM_LDFLAGS = -framework CoreFoundation -framework IOKit
|
|
||||||
endif
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -DSYSCONFDIR=\"$(sysconfdir)\" -DPIDFILEDIR=\"$(pidfiledir)\"
|
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = $(sysconf_DATA)
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
/** \file clients/lcdproc/batt.c
|
|
||||||
* Implements the 'battery' screen showing the APM battery status.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "batt.h"
|
|
||||||
#include "machine.h"
|
|
||||||
|
|
||||||
/** Map status code > status text */
|
|
||||||
typedef struct {
|
|
||||||
int status;
|
|
||||||
const char *name;
|
|
||||||
} NameTable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a numeric AC power status into a status text.
|
|
||||||
*
|
|
||||||
* \param status Numeric status as returned by machine_get_battstat
|
|
||||||
* \return Name of the status
|
|
||||||
*/
|
|
||||||
static const char *
|
|
||||||
ac_status(int status)
|
|
||||||
{
|
|
||||||
const NameTable ac_table[] = {
|
|
||||||
{ LCDP_AC_OFF, "Off" },
|
|
||||||
{ LCDP_AC_ON, "On" },
|
|
||||||
{ LCDP_AC_BACKUP, "Backup" },
|
|
||||||
{ LCDP_AC_UNKNOWN, "Unknown" },
|
|
||||||
{ 0, NULL }
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; ac_table[i].name != NULL; i++)
|
|
||||||
if (status == ac_table[i].status)
|
|
||||||
return ac_table[i].name;
|
|
||||||
|
|
||||||
return ac_table[LCDP_AC_UNKNOWN].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a numeric battery status into a status text.
|
|
||||||
*
|
|
||||||
* \param status Numeric status as returned by machine_get_battstat
|
|
||||||
* \return Name of the status
|
|
||||||
*/
|
|
||||||
static const char *
|
|
||||||
battery_status(int status)
|
|
||||||
{
|
|
||||||
const NameTable batt_table[] = {
|
|
||||||
{ LCDP_BATT_HIGH, "High" },
|
|
||||||
{ LCDP_BATT_LOW, "Low" },
|
|
||||||
{ LCDP_BATT_CRITICAL, "Critical" },
|
|
||||||
{ LCDP_BATT_CHARGING, "Charging" },
|
|
||||||
{ LCDP_BATT_ABSENT, "Absent" },
|
|
||||||
{ LCDP_BATT_UNKNOWN, "Unknown" },
|
|
||||||
{ 0, NULL }
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; batt_table[i].name != NULL; i++)
|
|
||||||
if (status == batt_table[i].status)
|
|
||||||
return batt_table[i].name;
|
|
||||||
|
|
||||||
return batt_table[LCDP_AC_UNKNOWN].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Battery Screen shows apm battery status...
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## AC: 100%: myho #@| |## AC: 100%: myho #@|
|
|
||||||
* |AC: On | |AC, Batt: Absent |
|
|
||||||
* |Batt: Absent | +--------------------+
|
|
||||||
* |E------------------F|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
battery_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
int acstat = 0, battstat = 0, percent = 0;
|
|
||||||
int gauge_wid = lcd_wid - 2;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add B\n");
|
|
||||||
sock_printf(sock, "screen_set B -name {APM stats: %s}\n", get_hostname());
|
|
||||||
sock_send_string(sock, "widget_add B title title\n");
|
|
||||||
sock_printf(sock, "widget_set B title {LCDPROC %s}\n", version);
|
|
||||||
sock_send_string(sock, "widget_add B one string\n");
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
sock_send_string(sock, "widget_add B two string\n");
|
|
||||||
sock_send_string(sock, "widget_add B three string\n");
|
|
||||||
sock_send_string(sock, "widget_add B gauge hbar\n");
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_set B one 1 2 {AC: Unknown}\n");
|
|
||||||
sock_send_string(sock, "widget_set B two 1 3 {Batt: Unknown}\n");
|
|
||||||
sock_printf(sock, "widget_set B three 1 4 {E%*sF}\n", gauge_wid, "");
|
|
||||||
sock_send_string(sock, "widget_set B gauge 2 4 0\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_get_battstat(&acstat, &battstat, &percent);
|
|
||||||
|
|
||||||
if (display) {
|
|
||||||
char tmp[20];
|
|
||||||
|
|
||||||
if (percent >= 0)
|
|
||||||
sprintf(tmp, "%d%%", percent);
|
|
||||||
else
|
|
||||||
sprintf(tmp, "??%%");
|
|
||||||
sock_printf(sock, "widget_set B title {%s: %s: %s}\n",
|
|
||||||
(acstat == LCDP_AC_ON && battstat == LCDP_BATT_ABSENT) ? "AC" : "Batt",
|
|
||||||
tmp, get_hostname());
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) { /* 4-line version of the screen */
|
|
||||||
sock_printf(sock, "widget_set B one 1 2 {AC: %s}\n", ac_status(acstat));
|
|
||||||
sock_printf(sock, "widget_set B two 1 3 {Batt: %s}\n", battery_status(battstat));
|
|
||||||
if (percent > 0)
|
|
||||||
sock_printf(sock, "widget_set B gauge 2 4 %d\n",
|
|
||||||
(percent * gauge_wid * lcd_cellwid) / 100);
|
|
||||||
}
|
|
||||||
else { /* two-line version of the screen */
|
|
||||||
sock_printf(sock, "widget_set B one 1 2 {%sBatt: %s}\n",
|
|
||||||
(acstat == LCDP_AC_ON) ? "AC, " : "",
|
|
||||||
battery_status(battstat));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef BATT_H
|
|
||||||
#define BATT_H
|
|
||||||
|
|
||||||
int battery_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,528 +0,0 @@
|
|||||||
/** \file clients/lcdproc/chrono.c
|
|
||||||
* Implements the 'OldTime', 'TimeDate', 'Uptime', 'MiniClock', and 'BigClock'
|
|
||||||
* screens.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TIME_WITH_SYS_TIME
|
|
||||||
# include <sys/time.h>
|
|
||||||
# include <time.h>
|
|
||||||
#else
|
|
||||||
# if HAVE_SYS_TIME_H
|
|
||||||
# include <sys/time.h>
|
|
||||||
# else
|
|
||||||
# include <time.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "chrono.h"
|
|
||||||
|
|
||||||
|
|
||||||
static char *tickTime(char *time, int heartbeat);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TimeDate Screen displays current time and date, uptime, OS ver...
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## Linux 2.6.11 ###@| |### TIME: myhost ##@|
|
|
||||||
* |Up xxx days hh:mm:ss| |17.05.2005 11:32:57a|
|
|
||||||
* | Wed May 17, 1998 | +--------------------+
|
|
||||||
* |11:32:57a 100% idle|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
time_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
char now[40];
|
|
||||||
char today[40];
|
|
||||||
int xoffs;
|
|
||||||
int days, hour, min, sec;
|
|
||||||
static int heartbeat = 0;
|
|
||||||
static const char *timeFormat = NULL;
|
|
||||||
static const char *dateFormat = NULL;
|
|
||||||
time_t thetime;
|
|
||||||
struct tm *rtime;
|
|
||||||
double uptime, idle;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
/* get config values */
|
|
||||||
timeFormat = config_get_string("TimeDate", "TimeFormat", 0, "%H:%M:%S");
|
|
||||||
dateFormat = config_get_string("TimeDate", "DateFormat", 0, "%b %d %Y");
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add T\n");
|
|
||||||
sock_printf(sock, "screen_set T -name {Time Screen: %s}\n", get_hostname());
|
|
||||||
sock_send_string(sock, "widget_add T title title\n");
|
|
||||||
sock_send_string(sock, "widget_add T one string\n");
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
sock_send_string(sock, "widget_add T two string\n");
|
|
||||||
sock_send_string(sock, "widget_add T three string\n");
|
|
||||||
|
|
||||||
/* write title bar: OS name, OS version, hostname */
|
|
||||||
sock_printf(sock, "widget_set T title {%s %s: %s}\n",
|
|
||||||
get_sysname(), get_sysrelease(), get_hostname());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* write title bar: hostname */
|
|
||||||
sock_printf(sock, "widget_set T title {TIME: %s}\n", get_hostname());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* toggle colon display */
|
|
||||||
heartbeat ^= 1;
|
|
||||||
|
|
||||||
time(&thetime);
|
|
||||||
rtime = localtime(&thetime);
|
|
||||||
|
|
||||||
if (strftime(today, sizeof(today), dateFormat, rtime) == 0)
|
|
||||||
*today = '\0';
|
|
||||||
if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
|
|
||||||
*now = '\0';
|
|
||||||
tickTime(now, heartbeat);
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
char tmp[40]; /* should be large enough */
|
|
||||||
|
|
||||||
machine_get_uptime(&uptime, &idle);
|
|
||||||
|
|
||||||
/* display the uptime... */
|
|
||||||
days = (int) uptime / 86400;
|
|
||||||
hour = ((int) uptime % 86400) / 3600;
|
|
||||||
min = ((int) uptime % 3600) / 60;
|
|
||||||
sec = ((int) uptime % 60);
|
|
||||||
|
|
||||||
if (lcd_wid >= 20)
|
|
||||||
sprintf(tmp, "Up %3d day%s %02d:%02d:%02d",
|
|
||||||
days, ((days != 1) ? "s" : ""), hour, min, sec);
|
|
||||||
else
|
|
||||||
sprintf(tmp, "Up %dd %02d:%02d:%02d", days, hour, min, sec);
|
|
||||||
|
|
||||||
xoffs = (lcd_wid > strlen(tmp)) ? ((lcd_wid - strlen(tmp)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set T one %i 2 {%s}\n", xoffs, tmp);
|
|
||||||
|
|
||||||
/* display the date */
|
|
||||||
xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set T two %i 3 {%s}\n", xoffs, today);
|
|
||||||
|
|
||||||
/* display the time & idle time... */
|
|
||||||
sprintf(tmp, "%s %3i%% idle", now, (int) idle);
|
|
||||||
xoffs = (lcd_wid > strlen(tmp)) ? ((lcd_wid - strlen(tmp)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set T three %i 4 {%s}\n", xoffs, tmp);
|
|
||||||
}
|
|
||||||
else { /* 2 line version of the screen */
|
|
||||||
xoffs = (lcd_wid > (strlen(today) + strlen(now) + 1))
|
|
||||||
? ((lcd_wid - ((strlen(today) + strlen(now) + 1))) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set T one %i 2 {%s %s}\n", xoffs, today, now);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* End time_screen() */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OldTime Screen displays current time and date...
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## DATE & TIME ####@| |### TIME: myhost ##@|
|
|
||||||
* | myhost | |2005-05-17 11:32:57a|
|
|
||||||
* |11:32:75a Wednesday,| +--------------------+
|
|
||||||
* | May 17, 2005 |
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
* Alternate 2-line version without the title bar:
|
|
||||||
*
|
|
||||||
* +----------------+
|
|
||||||
* | 2012-12-27 @|
|
|
||||||
* | 15:07:01 |
|
|
||||||
* +----------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clock_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
char now[40];
|
|
||||||
char today[40];
|
|
||||||
int xoffs;
|
|
||||||
static int heartbeat = 0;
|
|
||||||
static int showTitle = 1;
|
|
||||||
static const char *timeFormat = NULL;
|
|
||||||
static const char *dateFormat = NULL;
|
|
||||||
time_t thetime;
|
|
||||||
struct tm *rtime;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
char tmp[257]; /* should be large enough for host name */
|
|
||||||
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
/* get config values */
|
|
||||||
timeFormat = config_get_string("OldTime", "TimeFormat", 0, "%H:%M:%S");
|
|
||||||
dateFormat = config_get_string("OldTime", "DateFormat", 0, "%b %d %Y");
|
|
||||||
showTitle = config_get_bool("OldTime", "ShowTitle", 0, 1);
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add O\n");
|
|
||||||
sock_printf(sock, "screen_set O -name {Old Clock Screen: %s}\n", get_hostname());
|
|
||||||
if (!showTitle)
|
|
||||||
sock_send_string(sock, "screen_set O -heartbeat off\n");
|
|
||||||
sock_send_string(sock, "widget_add O one string\n");
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
sock_send_string(sock, "widget_add O title title\n");
|
|
||||||
sock_send_string(sock, "widget_add O two string\n");
|
|
||||||
sock_send_string(sock, "widget_add O three string\n");
|
|
||||||
|
|
||||||
sock_printf(sock, "widget_set O title {DATE & TIME}\n");
|
|
||||||
|
|
||||||
sprintf(tmp, "%s", get_hostname());
|
|
||||||
xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
|
|
||||||
sock_printf(sock, "widget_set O one %i 2 {%s}\n", xoffs, tmp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (showTitle) {
|
|
||||||
sock_send_string(sock, "widget_add O title title\n");
|
|
||||||
sock_printf(sock, "widget_set O title {TIME: %s}\n", get_hostname());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "widget_add O two string\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* toggle colon display */
|
|
||||||
heartbeat ^= 1;
|
|
||||||
|
|
||||||
time(&thetime);
|
|
||||||
rtime = localtime(&thetime);
|
|
||||||
|
|
||||||
if (strftime(today, sizeof(today), dateFormat, rtime) == 0)
|
|
||||||
*today = '\0';
|
|
||||||
if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
|
|
||||||
*now = '\0';
|
|
||||||
tickTime(now, heartbeat);
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) { /* 4-line version of the screen */
|
|
||||||
xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set O two %i 3 {%s}\n", xoffs, today);
|
|
||||||
|
|
||||||
xoffs = (lcd_wid > strlen(now)) ? ((lcd_wid - strlen(now)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set O three %i 4 {%s}\n", xoffs, now);
|
|
||||||
}
|
|
||||||
else { /* 2-line version of the screen */
|
|
||||||
if (showTitle) {
|
|
||||||
xoffs = (lcd_wid > (strlen(today) + strlen(now) + 1))
|
|
||||||
? ((lcd_wid - ((strlen(today) + strlen(now) + 1))) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set O one %i 2 {%s %s}\n", xoffs, today, now);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
xoffs = (lcd_wid > strlen(today)) ? ((lcd_wid - strlen(today)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set O one %i 1 {%s}\n", xoffs, today);
|
|
||||||
xoffs = (lcd_wid > strlen(now)) ? ((lcd_wid - strlen(now)) / 2) + 1 : 1;
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set O two %i 2 {%s}\n", xoffs, now);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* End clock_screen() */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uptime Screen shows info about system uptime and OS version
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## SYSTEM UPTIME ##@| |# Linux 2.6.11: my#@|
|
|
||||||
* | myhost | | xxx days hh:mm:ss |
|
|
||||||
* | xxx days hh:mm:ss | +--------------------+
|
|
||||||
* | Linux 2.6.11 |
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
uptime_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
int xoffs;
|
|
||||||
int days, hour, min, sec;
|
|
||||||
double uptime, idle;
|
|
||||||
static int heartbeat = 0;
|
|
||||||
char tmp[257]; /* should be large enough for host name */
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add U\n");
|
|
||||||
sock_printf(sock, "screen_set U -name {Uptime Screen: %s}\n", get_hostname());
|
|
||||||
sock_send_string(sock, "widget_add U title title\n");
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
sock_send_string(sock, "widget_add U one string\n");
|
|
||||||
sock_send_string(sock, "widget_add U two string\n");
|
|
||||||
sock_send_string(sock, "widget_add U three string\n");
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_set U title {SYSTEM UPTIME}\n");
|
|
||||||
|
|
||||||
sprintf(tmp, "%s", get_hostname());
|
|
||||||
xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
|
|
||||||
sock_printf(sock, "widget_set U one %i 2 {%s}\n", xoffs, tmp);
|
|
||||||
|
|
||||||
sprintf(tmp, "%s %s", get_sysname(), get_sysrelease());
|
|
||||||
xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
|
|
||||||
sock_printf(sock, "widget_set U three %i 4 {%s}\n", xoffs, tmp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "widget_add U one string\n");
|
|
||||||
|
|
||||||
sock_printf(sock, "widget_set U title {%s %s: %s}\n",
|
|
||||||
get_sysname(), get_sysrelease(), get_hostname());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* toggle colon display */
|
|
||||||
heartbeat ^= 1;
|
|
||||||
|
|
||||||
machine_get_uptime(&uptime, &idle);
|
|
||||||
days = (int) uptime / 86400;
|
|
||||||
hour = ((int) uptime % 86400) / 3600;
|
|
||||||
min = ((int) uptime % 3600) / 60;
|
|
||||||
sec = ((int) uptime % 60);
|
|
||||||
if (lcd_wid >= 20)
|
|
||||||
sprintf(tmp, "%d day%s %02d:%02d:%02d",
|
|
||||||
days, ((days != 1) ? "s" : ""), hour, min, sec);
|
|
||||||
else
|
|
||||||
sprintf(tmp, "%dd %02d:%02d:%02d", days, hour, min, sec);
|
|
||||||
|
|
||||||
if (display) {
|
|
||||||
xoffs = (lcd_wid > strlen(tmp)) ? (((lcd_wid - strlen(tmp)) / 2) + 1) : 1;
|
|
||||||
if (lcd_hgt >= 4)
|
|
||||||
sock_printf(sock, "widget_set U two %d 3 {%s}\n", xoffs, tmp);
|
|
||||||
else
|
|
||||||
sock_printf(sock, "widget_set U one %d 2 {%s}\n", xoffs, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* End uptime_screen() */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Big Clock Screen displays current time...
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+
|
|
||||||
* | _ _ _ _ |
|
|
||||||
* | ||_ . _||_|. _| ||
|
|
||||||
* | ||_|. _| |.|_ ||
|
|
||||||
* | |
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
big_clock_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
time_t thetime;
|
|
||||||
struct tm *rtime;
|
|
||||||
int pos[] = {1, 4, 8, 11, 15, 18};
|
|
||||||
char fulltxt[16];
|
|
||||||
static char old_fulltxt[16];
|
|
||||||
static int heartbeat = 0;
|
|
||||||
static int TwentyFourHour = 1;
|
|
||||||
int j = 0;
|
|
||||||
int digits = (lcd_wid >= 20) ? 6 : 4;
|
|
||||||
int xoffs = (lcd_wid + 1 - (pos[digits - 1] + 2)) / 2;
|
|
||||||
|
|
||||||
/* toggle colon display */
|
|
||||||
heartbeat ^= 1;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add K\n");
|
|
||||||
sock_send_string(sock, "screen_set K -name {Big Clock Screen} -heartbeat off\n");
|
|
||||||
sock_send_string(sock, "widget_add K d0 num\n");
|
|
||||||
sock_send_string(sock, "widget_add K d1 num\n");
|
|
||||||
sock_send_string(sock, "widget_add K d2 num\n");
|
|
||||||
sock_send_string(sock, "widget_add K d3 num\n");
|
|
||||||
sock_send_string(sock, "widget_add K c0 num\n");
|
|
||||||
|
|
||||||
if (digits > 4) {
|
|
||||||
sock_send_string(sock, "widget_add K d4 num\n");
|
|
||||||
sock_send_string(sock, "widget_add K d5 num\n");
|
|
||||||
sock_send_string(sock, "widget_add K c1 num\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(old_fulltxt, " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
time(&thetime);
|
|
||||||
rtime = localtime(&thetime);
|
|
||||||
|
|
||||||
sprintf(fulltxt, "%02d%02d%02d",
|
|
||||||
((TwentyFourHour) ? rtime->tm_hour : (((rtime->tm_hour + 11) % 12) + 1)),
|
|
||||||
rtime->tm_min, rtime->tm_sec);
|
|
||||||
|
|
||||||
for (j = 0; j < digits; j++) {
|
|
||||||
if (fulltxt[j] != old_fulltxt[j]) {
|
|
||||||
sock_printf(sock, "widget_set K d%d %d %c\n", j, xoffs+pos[j], fulltxt[j]);
|
|
||||||
old_fulltxt[j] = fulltxt[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heartbeat) { /* 10 means: colon */
|
|
||||||
sock_printf(sock, "widget_set K c0 %d 10\n", xoffs + 7);
|
|
||||||
if (digits > 4)
|
|
||||||
sock_printf(sock, "widget_set K c1 %d 10\n", xoffs + 14);
|
|
||||||
}
|
|
||||||
else { /* kludge: use illegal number to clear colon display */
|
|
||||||
sock_printf(sock, "widget_set K c0 %d 11\n", xoffs + 7);
|
|
||||||
if (digits > 4)
|
|
||||||
sock_printf(sock, "widget_set K c1 %d 11\n", xoffs + 14);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* End big_clock_screen() */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MiniClock Screen displays the current time with hours & minutes only
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* | | | 11:32 |
|
|
||||||
* | 11:32 | | |
|
|
||||||
* | | +--------------------+
|
|
||||||
* | |
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
mini_clock_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
char now[40];
|
|
||||||
time_t thetime;
|
|
||||||
struct tm *rtime;
|
|
||||||
static const char *timeFormat = NULL;
|
|
||||||
static int heartbeat = 0;
|
|
||||||
int xoffs;
|
|
||||||
|
|
||||||
/* toggle colon display */
|
|
||||||
heartbeat ^= 1;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
/* get config values */
|
|
||||||
timeFormat = config_get_string("MiniClock", "TimeFormat", 0, "%H:%M");
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add N\n");
|
|
||||||
sock_send_string(sock, "screen_set N -name {Mini Clock Screen} -heartbeat off\n");
|
|
||||||
sock_send_string(sock, "widget_add N one string\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
time(&thetime);
|
|
||||||
rtime = localtime(&thetime);
|
|
||||||
|
|
||||||
if (strftime(now, sizeof(now), timeFormat, rtime) == 0)
|
|
||||||
*now = '\0';
|
|
||||||
tickTime(now, heartbeat);
|
|
||||||
|
|
||||||
xoffs = (lcd_wid > strlen(now)) ? (((lcd_wid - strlen(now)) / 2) + 1) : 1;
|
|
||||||
sock_printf(sock, "widget_set N one %d %d {%s}\n", xoffs, (lcd_hgt / 2), now);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} /* End mini_clock_screen() */
|
|
||||||
|
|
||||||
|
|
||||||
/** Helper function: toggle between ':' and ' ' in time strings.
|
|
||||||
* \note The time string passed is modified directly!
|
|
||||||
* \param time String containing a formatted time value.
|
|
||||||
* \param heartbeat Even numbers to display ':', odd to display ' '.
|
|
||||||
* \return Pointer to the modfied time string.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
tickTime(char *time, int heartbeat)
|
|
||||||
{
|
|
||||||
if (time != NULL) {
|
|
||||||
static char colon[] = {':', ' '};
|
|
||||||
char *ptr = time;
|
|
||||||
|
|
||||||
for (heartbeat %= 2; *ptr != '\0'; ptr++) {
|
|
||||||
if (*ptr == colon[0])
|
|
||||||
*ptr = colon[heartbeat];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (time);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#ifndef CHRONO_H
|
|
||||||
#define CHRONO_H
|
|
||||||
|
|
||||||
int clock_screen(int rep, int display, int *flags_ptr);
|
|
||||||
int uptime_screen(int rep, int display, int *flags_ptr);
|
|
||||||
int time_screen(int rep, int display, int *flags_ptr);
|
|
||||||
int big_clock_screen(int rep, int display, int *flags_ptr);
|
|
||||||
int mini_clock_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
/** \file clients/lcdproc/cpu.c
|
|
||||||
* Implements the 'CPU' and 'CPUGraph' screens.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CPU screen shows info about percentage of the CPU being used
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## CPU 51.9%: myh #@| |CPU [---- ]48.1%@|
|
|
||||||
* |Usr 46.0% Nice 0.0%| |U-- S- N I--- |
|
|
||||||
* |Sys 5.9% Idle 48.1%| +--------------------+
|
|
||||||
* |0%-------- 100%|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cpu_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
#undef CPU_BUF_SIZE
|
|
||||||
#define CPU_BUF_SIZE 4
|
|
||||||
static double cpu[CPU_BUF_SIZE + 1][5]; /* last buffer is scratch */
|
|
||||||
static int gauge_wid = 0;
|
|
||||||
static int usni_wid = 0;
|
|
||||||
|
|
||||||
int i, j, n;
|
|
||||||
double value;
|
|
||||||
load_type load;
|
|
||||||
char tmp[25]; /* should be large enough */
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add C\n");
|
|
||||||
sock_printf(sock, "screen_set C -name {CPU Use: %s}\n", get_hostname());
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
gauge_wid = lcd_wid - 6; /* room between 0%...100% */
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_add C title title\n");
|
|
||||||
sock_send_string(sock, "widget_set C title {CPU LOAD}\n");
|
|
||||||
sock_send_string(sock, "widget_add C one string\n");
|
|
||||||
sock_send_string(sock, "widget_add C two string\n");
|
|
||||||
sock_send_string(sock, "widget_add C three string\n");
|
|
||||||
sock_printf(sock, "widget_set C one 1 2 {%-*s%-*s}\n",
|
|
||||||
lcd_wid / 2, "Usr", lcd_wid / 2, "Nice");
|
|
||||||
sock_printf(sock, "widget_set C two 1 3 {%-*s%-*s}\n",
|
|
||||||
lcd_wid / 2, "Sys", lcd_wid / 2, "Idle");
|
|
||||||
sock_printf(sock, "widget_set C three 1 4 {0%%%*s100%%}\n", gauge_wid, "");
|
|
||||||
sock_send_string(sock, "widget_add C usr string\n");
|
|
||||||
sock_send_string(sock, "widget_add C nice string\n");
|
|
||||||
sock_send_string(sock, "widget_add C idle string\n");
|
|
||||||
sock_send_string(sock, "widget_add C sys string\n");
|
|
||||||
sock_send_string(sock, "widget_add C bar hbar\n");
|
|
||||||
sock_send_string(sock, "widget_set C bar 3 4 0\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
usni_wid = (lcd_wid - 4) / 4; /* 4 gauges + 1 letter for each */
|
|
||||||
gauge_wid = lcd_wid - 12; /* room between [...] */
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_add C cpu string\n");
|
|
||||||
sock_printf(sock, "widget_set C cpu 1 1 {CPU [%*s]}\n", gauge_wid, "");
|
|
||||||
sock_send_string(sock, "widget_add C cpu% string\n");
|
|
||||||
sock_printf(sock, "widget_set C cpu%% 1 %d { 0.0%%}\n", lcd_wid - 5);
|
|
||||||
sock_send_string(sock, "widget_add C usni string\n");
|
|
||||||
sock_printf(sock, "widget_set C usni 1 2 {U%*sS%*sN%*sI%*s}\n",
|
|
||||||
usni_wid, "", usni_wid, "", usni_wid, "", usni_wid, "");
|
|
||||||
sock_send_string(sock, "widget_add C usr hbar\n");
|
|
||||||
sock_send_string(sock, "widget_add C sys hbar\n");
|
|
||||||
sock_send_string(sock, "widget_add C nice hbar\n");
|
|
||||||
sock_send_string(sock, "widget_add C idle hbar\n");
|
|
||||||
sock_send_string(sock, "widget_add C total hbar\n");
|
|
||||||
sock_send_string(sock, "widget_set C total 6 1 0\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_get_load(&load);
|
|
||||||
|
|
||||||
/* Shift values over by one */
|
|
||||||
for (i = 0; i < (CPU_BUF_SIZE - 1); i++)
|
|
||||||
for (j = 0; j < 5; j++)
|
|
||||||
cpu[i][j] = cpu[i + 1][j];
|
|
||||||
|
|
||||||
/* Read new data */
|
|
||||||
if (load.total > 0L) {
|
|
||||||
cpu[CPU_BUF_SIZE - 1][0] = 100.0 * ((double) load.user / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][1] = 100.0 * ((double) load.system / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][2] = 100.0 * ((double) load.nice / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][3] = 100.0 * ((double) load.idle / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][4] = 100.0 * (((double) load.user + (double) load.system + (double) load.nice) / (double) load.total);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cpu[CPU_BUF_SIZE - 1][0] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][1] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][2] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][3] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][4] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Average values for final result */
|
|
||||||
for (i = 0; i < 5; i++) {
|
|
||||||
value = 0.0;
|
|
||||||
for (j = 0; j < CPU_BUF_SIZE; j++)
|
|
||||||
value += cpu[j][i];
|
|
||||||
value /= CPU_BUF_SIZE;
|
|
||||||
cpu[CPU_BUF_SIZE][i] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!display)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) { /* 4-line display */
|
|
||||||
sprintf_percent(tmp, cpu[CPU_BUF_SIZE][4]);
|
|
||||||
sock_printf(sock, "widget_set C title {CPU %5s: %s}\n", tmp, get_hostname());
|
|
||||||
|
|
||||||
sprintf_percent(tmp, cpu[CPU_BUF_SIZE][0]);
|
|
||||||
sock_printf(sock, "widget_set C usr %i 2 {%5s}\n", (lcd_wid / 2) - 5, tmp);
|
|
||||||
|
|
||||||
sprintf_percent(tmp, cpu[CPU_BUF_SIZE][1]);
|
|
||||||
sock_printf(sock, "widget_set C sys %i 3 {%5s}\n", (lcd_wid / 2) - 5, tmp);
|
|
||||||
|
|
||||||
sprintf_percent(tmp, cpu[CPU_BUF_SIZE][2]);
|
|
||||||
sock_printf(sock, "widget_set C nice %i 2 {%5s}\n", lcd_wid - 4, tmp);
|
|
||||||
|
|
||||||
sprintf_percent(tmp, cpu[CPU_BUF_SIZE][3]);
|
|
||||||
sock_printf(sock, "widget_set C idle %i 3 {%5s}\n", lcd_wid - 4, tmp);
|
|
||||||
|
|
||||||
n = (int) ((cpu[CPU_BUF_SIZE][4] * lcd_cellwid * gauge_wid) / 100.0);
|
|
||||||
sock_printf(sock, "widget_set C bar 3 4 %d\n", n);
|
|
||||||
}
|
|
||||||
else { /* 2-line display */
|
|
||||||
sprintf_percent(tmp, cpu[CPU_BUF_SIZE][4]);
|
|
||||||
sock_printf(sock, "widget_set C cpu%% %d 1 {%5s}\n", lcd_wid - 5, tmp);
|
|
||||||
|
|
||||||
n = (int) ((cpu[CPU_BUF_SIZE][4] * lcd_cellwid * gauge_wid) / 100.0);
|
|
||||||
sock_printf(sock, "widget_set C total 6 1 %d\n", n);
|
|
||||||
|
|
||||||
n = (int) ((cpu[CPU_BUF_SIZE][0] * lcd_cellwid * usni_wid) / 100.0);
|
|
||||||
sock_printf(sock, "widget_set C usr %d 2 %d\n", 0 * (usni_wid + 1) + 2, n);
|
|
||||||
|
|
||||||
n = (int) ((cpu[CPU_BUF_SIZE][1] * lcd_cellwid * usni_wid) / 100.0);
|
|
||||||
sock_printf(sock, "widget_set C sys %d 2 %d\n", 1 * (usni_wid + 1) + 2, n);
|
|
||||||
|
|
||||||
n = (int) ((cpu[CPU_BUF_SIZE][2] * lcd_cellwid * usni_wid) / 100.0);
|
|
||||||
sock_printf(sock, "widget_set C nice %d 2 %d\n", 2 * (usni_wid + 1) + 2, n);
|
|
||||||
|
|
||||||
n = (int) ((cpu[CPU_BUF_SIZE][3] * lcd_cellwid * usni_wid) / 100.0);
|
|
||||||
sock_printf(sock, "widget_set C idle %d 2 %d\n", 3 * (usni_wid + 1) + 2, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
} /* End cpu_screen() */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cpu Graph Screen shows a quick-moving histogram of CPU use.
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## CPU: myhost ####@| |CPU: myhos|| @|
|
|
||||||
* | || | | |||| |
|
|
||||||
* | ||| | +--------------------+
|
|
||||||
* | |||| |
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cpu_graph_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
#undef CPU_BUF_SIZE
|
|
||||||
#define CPU_BUF_SIZE 2
|
|
||||||
static double cpu[CPU_BUF_SIZE];
|
|
||||||
static int cpu_past[LCD_MAX_WIDTH];
|
|
||||||
static int gauge_hgt = 0;
|
|
||||||
|
|
||||||
int i, n = 0;
|
|
||||||
double value;
|
|
||||||
load_type load;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
gauge_hgt = (lcd_hgt > 2) ? (lcd_hgt - 1) : lcd_hgt;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add G\n");
|
|
||||||
sock_printf(sock, "screen_set G -name {CPU Graph: %s}\n", get_hostname());
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
sock_send_string(sock, "widget_add G title title\n");
|
|
||||||
sock_printf(sock, "widget_set G title {CPU: %s}\n", get_hostname());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "widget_add G title string\n");
|
|
||||||
sock_printf(sock, "widget_set G title 1 1 {CPU: %s}\n", get_hostname());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 1; i <= lcd_wid; i++) {
|
|
||||||
sock_printf(sock, "widget_add G bar%d vbar\n", i);
|
|
||||||
sock_printf(sock, "widget_set G bar%d %d %d 0\n", i, i, lcd_hgt);
|
|
||||||
cpu_past[i - 1] = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Clear out CPU averaging array */
|
|
||||||
for (i = 0; i < CPU_BUF_SIZE; i++)
|
|
||||||
cpu[i] = 0.;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shift values over by one */
|
|
||||||
for (i = 0; i < (CPU_BUF_SIZE - 1); i++)
|
|
||||||
cpu[i] = cpu[i + 1];
|
|
||||||
|
|
||||||
/* Read and save new data */
|
|
||||||
machine_get_load(&load);
|
|
||||||
cpu[CPU_BUF_SIZE-1] = (load.total > 0L)
|
|
||||||
? ((double) load.user + (double) load.system + (double) load.nice) / (double) load.total
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
/* Average values for final result */
|
|
||||||
value = 0.0;
|
|
||||||
for (i = 0; i < CPU_BUF_SIZE; i++)
|
|
||||||
value += cpu[i];
|
|
||||||
value /= CPU_BUF_SIZE;
|
|
||||||
|
|
||||||
/* Scale result to available height (leave 1st line free when height > 2) */
|
|
||||||
n = (int) (value * lcd_cellhgt * gauge_hgt);
|
|
||||||
|
|
||||||
/* Shift and update display the graph */
|
|
||||||
for (i = 0; i < lcd_wid - 1; i++) {
|
|
||||||
cpu_past[i] = cpu_past[i + 1];
|
|
||||||
|
|
||||||
if (display) {
|
|
||||||
sock_printf(sock, "widget_set G bar%d %d %d %d\n",
|
|
||||||
i + 1, i + 1, lcd_hgt, cpu_past[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the newest entry and display it */
|
|
||||||
cpu_past[lcd_wid - 1] = n;
|
|
||||||
if (display) {
|
|
||||||
sock_printf(sock, "widget_set G bar%d %d %d %d\n", lcd_wid, lcd_wid, lcd_hgt, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
} /* End cpu_graph_screen() */
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#ifndef CPU_H
|
|
||||||
#define CPU_H
|
|
||||||
|
|
||||||
int cpu_screen(int rep, int display, int *flags_ptr);
|
|
||||||
int cpu_graph_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
/** \file clients/lcdproc/cpu_smp.c
|
|
||||||
* Display cpu info for multi-processor machines.
|
|
||||||
*
|
|
||||||
* Adapted from cpu.c.
|
|
||||||
*
|
|
||||||
* Really boring for the moment, it only shows a current usage percentage graph
|
|
||||||
* for each CPU.
|
|
||||||
*
|
|
||||||
* It will handle up to 2xlcd_hgt or 8 CPUs, whichever is less. If there are
|
|
||||||
* more CPUs than lines on the LCD, it puts 2 CPUs per line, splitting the line
|
|
||||||
* in half. Otherwise, it uses one line per CPU.
|
|
||||||
*
|
|
||||||
* If the number of lines used to display the bar graphs for the CPUs is smaller
|
|
||||||
* than the LCD's height, a title line is introduced, so that the screen looks
|
|
||||||
* similar to other lcdproc screens.
|
|
||||||
* In all other cases (i.e. \#CPUs == LCD height or \#CPUs >= 2 * LCD height),
|
|
||||||
* the title is left out to display as many CPUs graphs as possible.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (C) 2000 J Robert Ray
|
|
||||||
* Copyright (C) 2006,2007 Peter Marschall
|
|
||||||
*
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "cpu_smp.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CPU screen shows info about percentage of the CPU being used
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
cpu_smp_screen (int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
#undef CPU_BUF_SIZE
|
|
||||||
#define CPU_BUF_SIZE 4
|
|
||||||
int z;
|
|
||||||
static float cpu[MAX_CPUS][CPU_BUF_SIZE + 1]; /* last buffer is scratch */
|
|
||||||
load_type load[MAX_CPUS];
|
|
||||||
int num_cpus = MAX_CPUS;
|
|
||||||
int bar_size;
|
|
||||||
int lines_used;
|
|
||||||
|
|
||||||
/* get SMP load - inform about max #CPUs allowed */
|
|
||||||
machine_get_smpload(load, &num_cpus);
|
|
||||||
|
|
||||||
/* restrict num_cpus to max. twice the display height */
|
|
||||||
if (num_cpus > 2 * lcd_hgt)
|
|
||||||
num_cpus = 2 * lcd_hgt;
|
|
||||||
|
|
||||||
/* 2 CPUs per line if more CPUs than lines */
|
|
||||||
bar_size = (num_cpus > lcd_hgt) ? (lcd_wid / 2 - 6) : (lcd_wid - 6);
|
|
||||||
lines_used = (num_cpus > lcd_hgt) ? (num_cpus + 1) / 2 : num_cpus;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add P\n");
|
|
||||||
|
|
||||||
/* print title if he have room for it */
|
|
||||||
if (lines_used < lcd_hgt) {
|
|
||||||
sock_send_string(sock, "widget_add P title title\n");
|
|
||||||
sock_printf(sock, "widget_set P title {SMP CPU %s}\n", get_hostname());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "screen_set P -heartbeat off\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
sock_printf(sock, "screen_set P -name {CPU Use: %s}\n", get_hostname());
|
|
||||||
|
|
||||||
for (z = 0; z < num_cpus; z++) {
|
|
||||||
int y_offs = (lines_used < lcd_hgt) ? 2 : 1;
|
|
||||||
int x = (num_cpus > lcd_hgt) ? ((z % 2) * (lcd_wid/2) + 1) : 1;
|
|
||||||
int y = (num_cpus > lcd_hgt) ? (z/2 + y_offs) : (z + y_offs);
|
|
||||||
|
|
||||||
sock_printf(sock, "widget_add P cpu%d_title string\n", z);
|
|
||||||
sock_printf(sock, "widget_set P cpu%d_title %d %d \"CPU%d[%*s]\"\n",
|
|
||||||
z, x, y, z, bar_size, "");
|
|
||||||
sock_printf(sock, "widget_add P cpu%d_bar hbar\n", z);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (z = 0; z < num_cpus; z++) {
|
|
||||||
int y_offs = (lines_used < lcd_hgt) ? 2 : 1;
|
|
||||||
int x = (num_cpus > lcd_hgt) ? ((z % 2) * (lcd_wid/2) + 6) : 6;
|
|
||||||
int y = (num_cpus > lcd_hgt) ? (z/2 + y_offs) : (z + y_offs);
|
|
||||||
float value = 0.0;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
/* Shift values over by one */
|
|
||||||
for (i = 0; i < (CPU_BUF_SIZE - 1); i++)
|
|
||||||
cpu[z][i] = cpu[z][i + 1];
|
|
||||||
|
|
||||||
/* Read new data */
|
|
||||||
cpu[z][CPU_BUF_SIZE-1] = (load[z].total > 0L)
|
|
||||||
? (((float) load[z].user + (float) load[z].system + (float) load[z].nice) / (float) load[z].total) * 100.0
|
|
||||||
: 0.0;
|
|
||||||
|
|
||||||
/* Average values for final result */
|
|
||||||
for (i = 0; i < CPU_BUF_SIZE; i++) {
|
|
||||||
value += cpu[z][i];
|
|
||||||
}
|
|
||||||
value /= CPU_BUF_SIZE;
|
|
||||||
|
|
||||||
n = (int) ((value * lcd_cellwid * bar_size) / 100.0 + 0.5);
|
|
||||||
sock_printf(sock, "widget_set P cpu%d_bar %d %d %d\n", z, x, y, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef CPU_SMP_H
|
|
||||||
#define CPU_SMP_H
|
|
||||||
|
|
||||||
int cpu_smp_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
/** \file clients/lcdproc/disk.c
|
|
||||||
* Implements the 'Disk' screen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "disk.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives disk stats.
|
|
||||||
* Stays onscreen until it is done; rolls over all mounted file systems
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## DISKS: myhost ##@| |## DISKS: myhost ##@|
|
|
||||||
* |/ 18.3G E-- F| |-local 18.3G E--- F|
|
|
||||||
* |-local 18.3G E--- F| +--------------------+
|
|
||||||
* |/boot 949.6M E- F|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
disk_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
static mounts_type mnt[256];
|
|
||||||
static int count = 0;
|
|
||||||
|
|
||||||
/* Holds info to display (avoid recalculating it) */
|
|
||||||
struct disp {
|
|
||||||
char dev[16];
|
|
||||||
char cap[8];
|
|
||||||
int full;
|
|
||||||
} table[256];
|
|
||||||
int i;
|
|
||||||
static int num_disks = 0;
|
|
||||||
static int dev_wid = 6;
|
|
||||||
static int gauge_wid = 6;
|
|
||||||
|
|
||||||
#define huge long long int
|
|
||||||
huge size;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
dev_wid = (lcd_wid >= 20) ? (lcd_wid - 8) / 2 : (lcd_wid / 2) - 1;
|
|
||||||
gauge_wid = (lcd_wid >= 20) ? (lcd_wid - dev_wid - 10) : (lcd_wid - dev_wid - 3);
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add D\n");
|
|
||||||
sock_printf(sock, "screen_set D -name {Disk Use: %s}\n", get_hostname());
|
|
||||||
sock_send_string(sock, "widget_add D title title\n");
|
|
||||||
sock_printf(sock, "widget_set D title {DISKS: %s}\n", get_hostname());
|
|
||||||
sock_send_string(sock, "widget_add D f frame\n");
|
|
||||||
sock_printf(sock, "widget_set D f 1 2 %i %i %i %i v 12\n", lcd_wid, lcd_hgt, lcd_wid, lcd_hgt - 1);
|
|
||||||
sock_send_string(sock, "widget_add D err1 string\n");
|
|
||||||
sock_send_string(sock, "widget_add D err2 string\n");
|
|
||||||
sock_send_string(sock, "widget_set D err1 5 2 { Reading }\n");
|
|
||||||
sock_send_string(sock, "widget_set D err2 5 3 {Filesystems}\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get rid of old, unmounted filesystems... */
|
|
||||||
machine_get_fs(mnt, &count);
|
|
||||||
|
|
||||||
/* Fill the display structure... */
|
|
||||||
if (count) {
|
|
||||||
sock_send_string(sock, "widget_set D err1 0 0 .\n");
|
|
||||||
sock_send_string(sock, "widget_set D err2 0 0 .\n");
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
if (strlen(mnt[i].mpoint) > dev_wid)
|
|
||||||
sprintf(table[i].dev, "-%s", (mnt[i].mpoint) + (strlen(mnt[i].mpoint) - (dev_wid - 1)));
|
|
||||||
else
|
|
||||||
sprintf(table[i].dev, "%s", mnt[i].mpoint);
|
|
||||||
|
|
||||||
table[i].full = (huge) (lcd_cellwid * gauge_wid)
|
|
||||||
* (huge) (mnt[i].blocks - mnt[i].bfree)
|
|
||||||
/ (huge) mnt[i].blocks;
|
|
||||||
|
|
||||||
size = (huge) mnt[i].bsize * (huge) mnt[i].blocks;
|
|
||||||
memset(table[i].cap, '\0', 8);
|
|
||||||
|
|
||||||
sprintf_memory(table[i].cap, (double) size, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "widget_set D err1 1 2 {Error Retrieving}\n");
|
|
||||||
sock_send_string(sock, "widget_set D err2 1 3 {Filesystem Stats}\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Display stuff... (show for two seconds, then scroll once per
|
|
||||||
* second, then hold at the end for two seconds)
|
|
||||||
*/
|
|
||||||
sock_printf(sock, "widget_set D f 1 2 %i %i %i %i v 12\n", lcd_wid, lcd_hgt, lcd_wid, count);
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
char tmp[lcd_wid + 1]; /* should be large enough */
|
|
||||||
|
|
||||||
if (table[i].dev[0] == '\0')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (i >= num_disks) { /* Make sure we have enough lines... */
|
|
||||||
sock_printf(sock, "widget_add D s%i string -in f\n", i);
|
|
||||||
sock_printf(sock, "widget_add D h%i hbar -in f\n", i);
|
|
||||||
}
|
|
||||||
if (lcd_wid >= 20) { /* 20+x columns */
|
|
||||||
sprintf(tmp, "%-*s %6s E%*sF", dev_wid, table[i].dev, table[i].cap, gauge_wid, "");
|
|
||||||
sock_printf(sock, "widget_set D s%i 1 %i {%s}\n", i, i + 1, tmp);
|
|
||||||
sock_printf(sock, "widget_set D h%i %i %i %i\n", i, 10 + dev_wid, i + 1, table[i].full);
|
|
||||||
}
|
|
||||||
else { /* < 20 columns */
|
|
||||||
sprintf(tmp, "%-*s E%*sF", dev_wid, table[i].dev, gauge_wid, "");
|
|
||||||
sock_printf(sock, "widget_set D s%i 1 %i {%s}\n", i, i + 1, tmp);
|
|
||||||
sock_printf(sock, "widget_set D h%i %i %i %i\n", i, 3 + dev_wid, i + 1, table[i].full);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now remove extra widgets... */
|
|
||||||
for (; i < num_disks; i++) {
|
|
||||||
sock_printf(sock, "widget_del D s%i\n", i);
|
|
||||||
sock_printf(sock, "widget_del D h%i\n", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
num_disks = count;
|
|
||||||
|
|
||||||
#undef huge
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef DISK_H
|
|
||||||
#define DISK_H
|
|
||||||
|
|
||||||
int disk_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
/** \file clients/lcdproc/eyebox.c
|
|
||||||
* This is the LCDproc client module for EyeboxOne devices
|
|
||||||
*
|
|
||||||
* This allows to use leds, one as a free CPU meter, and one as a free RAM
|
|
||||||
* meter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (C) 2006 Cedric TESSIER (aka NeZetiC) http://www.nezetic.info
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "eyebox.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
eyebox_screen(char display, int init)
|
|
||||||
{
|
|
||||||
#undef CPU_BUF_SIZE
|
|
||||||
#define CPU_BUF_SIZE 4
|
|
||||||
int i, j;
|
|
||||||
double value;
|
|
||||||
static double cpu[CPU_BUF_SIZE + 1][5]; /* last buffer is scratch */
|
|
||||||
meminfo_type mem[2];
|
|
||||||
load_type load;
|
|
||||||
|
|
||||||
if (init == 0) {
|
|
||||||
sock_printf(sock, "widget_add %c eyebo_cpu string\n", display);
|
|
||||||
sock_printf(sock, "widget_add %c eyebo_mem string\n", display);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_get_load(&load);
|
|
||||||
machine_get_meminfo(mem);
|
|
||||||
|
|
||||||
/* Shift values over by one */
|
|
||||||
for (i = 0; i < (CPU_BUF_SIZE - 1); i++)
|
|
||||||
for (j = 0; j < 5; j++)
|
|
||||||
cpu[i][j] = cpu[i + 1][j];
|
|
||||||
|
|
||||||
/* Read new data */
|
|
||||||
if (load.total > 0L) {
|
|
||||||
cpu[CPU_BUF_SIZE - 1][0] = 100.0 * ((double) load.user / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][1] = 100.0 * ((double) load.system / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][2] = 100.0 * ((double) load.nice / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][3] = 100.0 * ((double) load.idle / (double) load.total);
|
|
||||||
cpu[CPU_BUF_SIZE - 1][4] = 100.0 * (((double) load.user + (double) load.system + (double) load.nice) / (double) load.total);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
cpu[CPU_BUF_SIZE - 1][0] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][1] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][2] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][3] = 0.0;
|
|
||||||
cpu[CPU_BUF_SIZE - 1][4] = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Average values for final result */
|
|
||||||
for (i = 0; i < 5; i++) {
|
|
||||||
value = 0.0;
|
|
||||||
for (j = 0; j < CPU_BUF_SIZE; j++)
|
|
||||||
value += cpu[j][i];
|
|
||||||
value /= CPU_BUF_SIZE;
|
|
||||||
cpu[CPU_BUF_SIZE][i] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* /xBab = Use Bar
|
|
||||||
* a = Bar ID
|
|
||||||
* b = Level
|
|
||||||
*/
|
|
||||||
sock_printf(sock, "widget_set %c eyebo_cpu 1 2 {/xB%d%d}\n",
|
|
||||||
display, 2,(int)(cpu[CPU_BUF_SIZE][4]/10));
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* /xBab = Use Bas
|
|
||||||
* a = Bar ID
|
|
||||||
* b = Level
|
|
||||||
*/
|
|
||||||
value = 1.0 - (double) (mem[0].free + mem[0].buffers + mem[0].cache)
|
|
||||||
/ (double) mem[0].total;
|
|
||||||
sock_printf(sock, "widget_set %c eyebo_mem 1 3 {/xB%d%d}\n", display, 1, (int) (value * 10));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
eyebox_clear(void)
|
|
||||||
{
|
|
||||||
/* Clear LEDs before exit */
|
|
||||||
sock_send_string(sock, "screen_add OFF\n");
|
|
||||||
sock_send_string(sock, "screen_set OFF -priority alert -name {EyeBO}\n");
|
|
||||||
sock_send_string(sock, "widget_add OFF title title\n");
|
|
||||||
sock_send_string(sock, "widget_set OFF title {EYEBOX ONE}\n");
|
|
||||||
sock_send_string(sock, "widget_add OFF text string\n");
|
|
||||||
sock_send_string(sock, "widget_add OFF about string\n");
|
|
||||||
sock_send_string(sock, "widget_add OFF cpu string\n");
|
|
||||||
sock_send_string(sock, "widget_add OFF mem string\n");
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_set OFF text 1 2 {Reseting Leds...}\n");
|
|
||||||
sock_send_string(sock, "widget_set OFF about 5 4 {EyeBO by NeZetiC}\n");
|
|
||||||
sock_printf(sock, "widget_set OFF cpu 1 2 {/xB%d%d}\n", 2, 0);
|
|
||||||
sock_printf(sock, "widget_set OFF mem 1 3 {/xB%d%d}\n", 1, 0);
|
|
||||||
usleep(2000000); /* Wait last order execution */
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#ifndef CTRL_H
|
|
||||||
#define CTRL_H
|
|
||||||
|
|
||||||
int eyebox_screen(char display, int init);
|
|
||||||
void eyebox_clear(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,519 +0,0 @@
|
|||||||
/** \file clients/lcdproc/iface.c
|
|
||||||
* Shows networks statistics. Imported from netlcdclient.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (C) 2002 Luis Llorente Campo <luisllorente@luisllorente.com>
|
|
||||||
*
|
|
||||||
* Multi-interface extension by Stephan Skrodzki <skrodzki@stevekist.de>
|
|
||||||
* Adaptions to lcdproc by Andrew Foss with fixes by M. Dolze
|
|
||||||
* Cleanup, reorganization by Peter Marschall
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "iface.h"
|
|
||||||
|
|
||||||
#define UNSET_INT -1
|
|
||||||
#define UNSET_STR "\01"
|
|
||||||
|
|
||||||
|
|
||||||
static int iface_count = 0; /* number of interfaces */
|
|
||||||
static char unit_label[10] = "B"; /* default unit label is Bytes */
|
|
||||||
static int transfer_screen = 0; /* by default, transfer screen is not shown */
|
|
||||||
|
|
||||||
|
|
||||||
/** Reads and parses configuration file.
|
|
||||||
* \return 0 on success, -1 on error
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
iface_process_configfile(void)
|
|
||||||
{
|
|
||||||
const char *unit;
|
|
||||||
|
|
||||||
debug(RPT_DEBUG, "%s()", __FUNCTION__);
|
|
||||||
|
|
||||||
/* Read config settings */
|
|
||||||
for (iface_count = 0; iface_count < MAX_INTERFACES; iface_count++) {
|
|
||||||
char iface_label[12];
|
|
||||||
|
|
||||||
sprintf(iface_label, "Interface%i", iface_count);
|
|
||||||
debug(RPT_DEBUG, "Label %s count %i", iface_label, iface_count);
|
|
||||||
iface[iface_count].name = strdup(config_get_string("Iface", iface_label, 0, ""));
|
|
||||||
if (iface[iface_count].name == NULL) {
|
|
||||||
report(RPT_CRIT, "malloc failure");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*iface[iface_count].name == '\0')
|
|
||||||
break;
|
|
||||||
sprintf(iface_label, "Alias%i", iface_count);
|
|
||||||
iface[iface_count].alias = strdup(config_get_string("Iface", iface_label, 0, iface[iface_count].name));
|
|
||||||
if (iface[iface_count].alias == NULL)
|
|
||||||
/*
|
|
||||||
* make alias the same as the interface name in case
|
|
||||||
* strdup() failed
|
|
||||||
*/
|
|
||||||
iface[iface_count].alias = iface[iface_count].name;
|
|
||||||
debug(RPT_DEBUG, "Interface %i: %s alias %s",
|
|
||||||
iface_count, iface[iface_count].name, iface[iface_count].alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
unit = config_get_string("Iface", "Unit", 0, "byte");
|
|
||||||
if ((strcasecmp(unit, "byte") == 0) ||
|
|
||||||
(strcasecmp(unit, "bytes") == 0))
|
|
||||||
strncpy(unit_label, "B", sizeof(unit_label));
|
|
||||||
else if ((strcasecmp(unit, "bit") == 0) ||
|
|
||||||
(strcasecmp(unit, "bits") == 0))
|
|
||||||
strncpy(unit_label, "b", sizeof(unit_label));
|
|
||||||
else if ((strcasecmp(unit, "packet") == 0) ||
|
|
||||||
(strcasecmp(unit, "packets") == 0))
|
|
||||||
strncpy(unit_label, "pkt", sizeof(unit_label));
|
|
||||||
else {
|
|
||||||
report(RPT_ERR, "illegal Unit value: %s", unit);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
unit_label[sizeof(unit_label) - 1] = '\0';
|
|
||||||
|
|
||||||
transfer_screen = config_get_bool("Iface", "Transfer", 0, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IFace screen shows info about percentage of the Network interface usage /
|
|
||||||
* throughput.
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## Net Load: LAN ##@| |### Net Load ######@|
|
|
||||||
* |UL: 123.456 Kb| |LAN: U: 34kb D: 56Mb|
|
|
||||||
* |DL: 654.321 Kb| +--------------------+
|
|
||||||
* |Total: 777.777 Kb|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
iface_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
/* interval since last update */
|
|
||||||
unsigned int interval = difftime(time(NULL), iface[0].last_online);
|
|
||||||
int iface_nmbr;
|
|
||||||
|
|
||||||
if (!interval)
|
|
||||||
return 0; /* need at least 1 second, no divide by 0 */
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
/* get configuration options */
|
|
||||||
iface_process_configfile();
|
|
||||||
|
|
||||||
/* set initial speed screen with widgets */
|
|
||||||
initialize_speed_screen();
|
|
||||||
|
|
||||||
/* set initial transfer screen if needed */
|
|
||||||
if (transfer_screen) {
|
|
||||||
initialize_transfer_screen();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize all interface structs */
|
|
||||||
for (iface_nmbr = 0; iface_nmbr < iface_count; iface_nmbr++) {
|
|
||||||
iface[iface_nmbr].last_online = 0;
|
|
||||||
iface[iface_nmbr].status = down;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* for each interface do */
|
|
||||||
for (iface_nmbr = 0; iface_nmbr < iface_count; iface_nmbr++) {
|
|
||||||
/* read iface_parameter stats */
|
|
||||||
if (!machine_get_iface_stats(&iface[iface_nmbr])) {
|
|
||||||
/* there was an error, so we exit the loop */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* actualize speed values in display */
|
|
||||||
actualize_speed_screen(&iface[iface_nmbr], interval, iface_nmbr);
|
|
||||||
|
|
||||||
/* if needed, actualize transfer values in display */
|
|
||||||
if (transfer_screen)
|
|
||||||
actualize_transfer_screen(&iface[iface_nmbr], iface_nmbr);
|
|
||||||
|
|
||||||
/* Actual values are the old ones in the next loop */
|
|
||||||
iface[iface_nmbr].rc_byte_old = iface[iface_nmbr].rc_byte;
|
|
||||||
iface[iface_nmbr].tr_byte_old = iface[iface_nmbr].tr_byte;
|
|
||||||
iface[iface_nmbr].rc_pkt_old = iface[iface_nmbr].rc_pkt;
|
|
||||||
iface[iface_nmbr].tr_pkt_old = iface[iface_nmbr].tr_pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send commands to server to add speed screen with all required widgets.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
initialize_speed_screen(void)
|
|
||||||
{
|
|
||||||
int iface_nmbr; /* interface number */
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add I\n");
|
|
||||||
sock_send_string(sock, "screen_set I name {Load}\n");
|
|
||||||
sock_send_string(sock, "widget_add I title title\n");
|
|
||||||
|
|
||||||
/* Single interface mode */
|
|
||||||
if ((iface_count == 1) && (lcd_hgt >= 4 )) {
|
|
||||||
sock_printf(sock, "widget_set I title {Net Load: %s}\n", iface[0].alias);
|
|
||||||
sock_send_string(sock, "widget_add I dl string\n");
|
|
||||||
sock_send_string(sock, "widget_set I dl 1 2 {DL:}\n");
|
|
||||||
sock_send_string(sock, "widget_add I ul string\n");
|
|
||||||
sock_send_string(sock, "widget_set I ul 1 3 {UL:}\n");
|
|
||||||
sock_send_string(sock, "widget_add I total string\n");
|
|
||||||
sock_send_string(sock, "widget_set I total 1 4 {Total:}\n");
|
|
||||||
}
|
|
||||||
/* multi-interfaces mode: one line per interface */
|
|
||||||
else {
|
|
||||||
/* Set title */
|
|
||||||
if (strstr(unit_label, "B")) {
|
|
||||||
sock_printf(sock, "widget_set I title {Net Load (bytes)}\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (strstr(unit_label, "b")) {
|
|
||||||
sock_printf(sock, "widget_set I title {Net Load (bits)}\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_printf(sock, "widget_set I title {Net Load (packets)}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* frame from (2, left) to (width, height) that is iface_count lines high */
|
|
||||||
sock_send_string (sock, "widget_add I f frame\n");
|
|
||||||
sock_printf(sock, "widget_set I f 1 2 %d %d %d %d v 16\n",
|
|
||||||
lcd_wid, lcd_hgt, lcd_wid, iface_count,
|
|
||||||
/* scroll rate: 1 line every X ticks (=1/8 sec) */
|
|
||||||
((lcd_hgt >= 4) ? 8 : 16));
|
|
||||||
|
|
||||||
/* Add interfaces to frame */
|
|
||||||
for (iface_nmbr = 0; iface_nmbr < iface_count; iface_nmbr++) {
|
|
||||||
sock_printf(sock, "widget_add I i%1d string -in f\n", iface_nmbr);
|
|
||||||
sock_printf(sock, "widget_set I i%1d 1 %1d {%5.5s NA (never)}\n",
|
|
||||||
iface_nmbr, iface_nmbr+1, iface[iface_nmbr].alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the value (in bytes) passed as parameter according to its scale,
|
|
||||||
* adding the proper suffix. Store the formatted value string in the
|
|
||||||
* variable 'buff' passed as pointer.
|
|
||||||
* \param buff Pointer to target buffer
|
|
||||||
* \param value Number of bytes
|
|
||||||
* \param unit String describing the unit. If this contains 'b', \c value is
|
|
||||||
* converted to bits. If this contains 'B', value is converted
|
|
||||||
* to binary multiples (1024 bytes = 1 KiB).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
format_value (char *buff, double value, char *unit)
|
|
||||||
{
|
|
||||||
char *mag;
|
|
||||||
|
|
||||||
/* Convert bytes to bits, if necessary */
|
|
||||||
if (strstr(unit, "b"))
|
|
||||||
value *= 8;
|
|
||||||
|
|
||||||
/* If units are bytes, then divide by 2^10, otherwise by 10^3 */
|
|
||||||
mag = convert_double(&value, (strstr(unit, "B")) ? 1024 : 1000, 1.0f);
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Formatting rules:
|
|
||||||
* - if original value was < 1000, output decimal value only
|
|
||||||
* - otherwise format with 3 precision
|
|
||||||
*/
|
|
||||||
if (mag[0] == 0)
|
|
||||||
sprintf(buff, "%8ld %s", (long) value, unit);
|
|
||||||
else
|
|
||||||
sprintf(buff, "%7.3f %s%s", value, mag, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the value (in bytes) passed as parameter according to its scale,
|
|
||||||
* adding the proper suffix. Store the formatted value string in the
|
|
||||||
* variable 'buff' passed as pointer. Version for multi-interfaces mode.
|
|
||||||
* \param buff Pointer to target buffer
|
|
||||||
* \param value Number of bytes
|
|
||||||
* \param unit String describing the unit. If this contains 'b', \c value is
|
|
||||||
* converted to bits. If this contains 'B', value is converted
|
|
||||||
* to binary multiples (1024 bytes = 1 KiB).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
format_value_multi_interface(char *buff, double value, char *unit)
|
|
||||||
{
|
|
||||||
char *mag;
|
|
||||||
|
|
||||||
if (strstr(unit, "b"))
|
|
||||||
value *= 8;
|
|
||||||
|
|
||||||
mag = convert_double(&value, (strstr(unit, "B")) ? 1024 : 1000, 1.0f);
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Formatting rules:
|
|
||||||
* - if original value was < 1000, output decimal value only
|
|
||||||
* - with 1 precision if <10
|
|
||||||
* - decimal value with magnitude otherwise
|
|
||||||
*/
|
|
||||||
if (mag[0] == 0)
|
|
||||||
sprintf(buff, "%4ld", (long) value);
|
|
||||||
else if (value < 10)
|
|
||||||
sprintf(buff, "%3.1f%s", value, mag);
|
|
||||||
else
|
|
||||||
sprintf(buff, "%3.0f%s", value, mag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the time in ASCII, depending on the elapsed time.
|
|
||||||
* \param buff Pointer to buffer for storing result
|
|
||||||
* \param last_online Time value
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
get_time_string(char *buff, time_t last_online)
|
|
||||||
{
|
|
||||||
|
|
||||||
time_t act_time; /* actual time */
|
|
||||||
char timebuff[30];
|
|
||||||
|
|
||||||
act_time = time(NULL);
|
|
||||||
|
|
||||||
if (last_online == 0) { /* never was online */
|
|
||||||
sprintf(buff, "never");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Transform Unix time format to UTC time format */
|
|
||||||
strcpy(timebuff, ctime(&last_online));
|
|
||||||
|
|
||||||
/* 86400 = 24 * 60 * 60. Is it more than 24 hours? */
|
|
||||||
if ((act_time - last_online) > 86400 ) {
|
|
||||||
timebuff[10] = '\0';
|
|
||||||
sprintf(buff, "%s", &timebuff[4]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
timebuff[19] = '\0';
|
|
||||||
sprintf(buff, "%s", &timebuff[11]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actualize values in display, calculating speeds in the defined interval
|
|
||||||
* of time and sending proper commands to server. If measure unit is
|
|
||||||
* 'pkt', we don't format this speed. Is always XXXX pkt/s.
|
|
||||||
* \param iface Pointer to interface data
|
|
||||||
* \param interval Time of last update
|
|
||||||
* \param index Interface index
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
actualize_speed_screen(IfaceInfo *iface, unsigned int interval, int index)
|
|
||||||
{
|
|
||||||
char speed[20]; /* buffer to store the formated speed string */
|
|
||||||
double rc_speed;
|
|
||||||
double tr_speed;
|
|
||||||
|
|
||||||
/* single interface mode */
|
|
||||||
if ((iface_count == 1) && ( lcd_hgt >= 4)) {
|
|
||||||
if (iface->status == up) {
|
|
||||||
/* Calculate and actualize download speed */
|
|
||||||
if (strstr(unit_label, "pkt")) {
|
|
||||||
rc_speed = (iface->rc_pkt - iface->rc_pkt_old) / interval;
|
|
||||||
sprintf(speed, "%8ld %s", (long) rc_speed, unit_label);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rc_speed = (iface->rc_byte - iface->rc_byte_old) / interval;
|
|
||||||
format_value(speed, rc_speed, unit_label);
|
|
||||||
}
|
|
||||||
sock_printf(sock, "widget_set I dl 1 2 {DL: %*s/s}\n", lcd_wid - 6, speed);
|
|
||||||
|
|
||||||
/* Calculate and actualize upload speed */
|
|
||||||
if (strstr(unit_label, "pkt")) {
|
|
||||||
tr_speed = (iface->tr_pkt - iface->tr_pkt_old) / interval;
|
|
||||||
sprintf(speed, "%8ld %s", (long)tr_speed, unit_label);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tr_speed = (iface->tr_byte - iface->tr_byte_old) / interval;
|
|
||||||
format_value(speed, tr_speed, unit_label);
|
|
||||||
}
|
|
||||||
sock_printf(sock, "widget_set I ul 1 3 {UL: %*s/s}\n", lcd_wid - 6, speed);
|
|
||||||
|
|
||||||
/* Calculate and actualize total speed */
|
|
||||||
if (strstr(unit_label, "pkt")) {
|
|
||||||
sprintf(speed, "%7ld %s", (long)(rc_speed + tr_speed), unit_label);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
format_value(speed, rc_speed + tr_speed, unit_label);
|
|
||||||
}
|
|
||||||
sock_printf(sock, "widget_set I total 1 4 {Total: %*s/s}\n", lcd_wid - 9, speed);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
get_time_string(speed, iface->last_online);
|
|
||||||
sock_printf(sock, "widget_set I dl 1 2 {NA (%s)}\n", speed);
|
|
||||||
sock_send_string(sock, "widget_set I ul 1 3 {}\n");
|
|
||||||
sock_send_string(sock, "widget_set I total 1 4 {}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* multi-interfaces mode: 1 line per interface */
|
|
||||||
else {
|
|
||||||
char speed1[20]; /* buffer to store the formated speed string */
|
|
||||||
|
|
||||||
if (iface->status == up) {
|
|
||||||
if (strstr(unit_label, "pkt")) {
|
|
||||||
rc_speed = (iface->rc_pkt - iface->rc_pkt_old) / interval;
|
|
||||||
tr_speed = (iface->tr_pkt - iface->tr_pkt_old) / interval;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rc_speed = (iface->rc_byte - iface->rc_byte_old) / interval;
|
|
||||||
tr_speed = (iface->tr_byte - iface->tr_byte_old) / interval;
|
|
||||||
}
|
|
||||||
format_value_multi_interface(speed, rc_speed, unit_label);
|
|
||||||
format_value_multi_interface(speed1, tr_speed, unit_label);
|
|
||||||
if (lcd_wid > 16)
|
|
||||||
sock_printf(sock, "widget_set I i%1d 1 %1d {%5.5s U:%.4s D:%.4s}\n",
|
|
||||||
index, index+1, iface->alias, speed1, speed);
|
|
||||||
else
|
|
||||||
sock_printf(sock, "widget_set I i%1d 1 %1d {%4.4s ^%.4s v%.4s}\n",
|
|
||||||
index, index+1, iface->alias, speed1, speed);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
get_time_string(speed, iface->last_online);
|
|
||||||
sock_printf(sock, "widget_set I i%1d 1 %1d {%5.5s NA (%s)}\n",
|
|
||||||
index, index+1, iface->alias, speed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send commands to server to add transfer screen with all required widgets.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
initialize_transfer_screen(void)
|
|
||||||
{
|
|
||||||
int iface_nmbr; /* interface number */
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add NT\n");
|
|
||||||
sock_send_string(sock, "screen_set NT name {Transfer}\n");
|
|
||||||
sock_send_string(sock, "widget_add NT title title\n");
|
|
||||||
|
|
||||||
/* single interface mode */
|
|
||||||
if ((iface_count == 1) && (lcd_hgt >= 4)) {
|
|
||||||
sock_printf(sock, "widget_set NT title {Transfer: %s}\n", iface[0].alias);
|
|
||||||
sock_send_string(sock, "widget_add NT dl string\n");
|
|
||||||
sock_send_string(sock, "widget_set NT dl 1 2 {DL:}\n");
|
|
||||||
sock_send_string(sock, "widget_add NT ul string\n");
|
|
||||||
sock_send_string(sock, "widget_set NT ul 1 3 {UL:}\n");
|
|
||||||
sock_send_string(sock, "widget_add NT total string\n");
|
|
||||||
sock_send_string(sock, "widget_set NT total 1 4 {Total:}\n");
|
|
||||||
}
|
|
||||||
/* multi-interfaces mode: one line per interface */
|
|
||||||
else {
|
|
||||||
/* Set title (transfer screen is always in "bytes") */
|
|
||||||
sock_send_string(sock, "widget_set NT title {Net Transfer (bytes)}\n");
|
|
||||||
|
|
||||||
/* frame from (2, left) to (width, height) that is iface_count lines high */
|
|
||||||
sock_send_string(sock, "widget_add NT f frame\n");
|
|
||||||
sock_printf(sock, "widget_set NT f 1 2 %d %d %d %d v 16\n",
|
|
||||||
lcd_wid, lcd_hgt, lcd_wid, iface_count,
|
|
||||||
/* scroll rate: 1 line every X ticks (=1/8 sec) */
|
|
||||||
((lcd_hgt >= 4) ? 8 : 16));
|
|
||||||
|
|
||||||
/* Add interfaces */
|
|
||||||
for (iface_nmbr = 0; iface_nmbr < iface_count; iface_nmbr++) {
|
|
||||||
sock_printf(sock, "widget_add NT i%1d string -in f\n", iface_nmbr);
|
|
||||||
sock_printf(sock, "widget_set NT i%1d 1 %1d {%5.5s NA (never)}\n",
|
|
||||||
iface_nmbr, iface_nmbr+1, iface[iface_nmbr].alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actualize values in display, formatting transfer measures and sending
|
|
||||||
* proper commands to server. Traffic is shown in "bytes" unit.
|
|
||||||
* \param iface Pointer to interface data
|
|
||||||
* \param index Interface index
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
actualize_transfer_screen(IfaceInfo *iface, int index)
|
|
||||||
{
|
|
||||||
char transfer[20]; /* buffer to store the formated traffic string */
|
|
||||||
|
|
||||||
/* single interface mode */
|
|
||||||
if ((iface_count == 1) && (lcd_hgt >= 4)) {
|
|
||||||
if (iface->status == up) {
|
|
||||||
/* download traffic */
|
|
||||||
format_value(transfer, iface->rc_byte, "B");
|
|
||||||
sock_printf(sock, "widget_set NT dl 1 2 {DL: %*s}\n", lcd_wid - 4, transfer);
|
|
||||||
|
|
||||||
/* upload traffic */
|
|
||||||
format_value(transfer, iface->tr_byte, "B");
|
|
||||||
sock_printf(sock, "widget_set NT ul 1 3 {UL: %*s}\n", lcd_wid - 4, transfer);
|
|
||||||
|
|
||||||
/* total traffic */
|
|
||||||
format_value(transfer, iface->rc_byte + iface->tr_byte, "B");
|
|
||||||
sock_printf(sock, "widget_set NT total 1 4 {Total: %*s}\n", lcd_wid - 7, transfer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
get_time_string(transfer, iface->last_online);
|
|
||||||
sock_printf(sock, "widget_set NT dl 1 2 {NA (%s)}\n", transfer);
|
|
||||||
sock_send_string(sock, "widget_set NT ul 1 3 {}\n");
|
|
||||||
sock_send_string(sock, "widget_set NT total 1 4 {}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* multi-interfaces mode: one line per interface */
|
|
||||||
else {
|
|
||||||
char transfer1[20]; /* buffer to store the formated traffic string */
|
|
||||||
|
|
||||||
if (iface->status == up) {
|
|
||||||
format_value_multi_interface(transfer, iface->rc_byte, "B");
|
|
||||||
format_value_multi_interface(transfer1, iface->tr_byte, "B");
|
|
||||||
if (lcd_wid > 16)
|
|
||||||
sock_printf(sock, "widget_set NT i%1d 1 %1d {%5.5s U:%.4s D:%.4s}\n",
|
|
||||||
index, index+1, iface->alias, transfer1, transfer);
|
|
||||||
else
|
|
||||||
sock_printf(sock, "widget_set NT i%1d 1 %1d {%4.4s ^%.4s v%.4s}\n",
|
|
||||||
index, index+1, iface->alias, transfer1, transfer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
get_time_string(transfer, iface->last_online);
|
|
||||||
sock_printf(sock, "widget_set NT i%1d 1 %1d {%5.5s NA (%s)}\n",
|
|
||||||
index, index+1, iface->alias, transfer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/** \file clients/lcdproc/iface.h
|
|
||||||
* Definitions and function prototypes for \c iface.c.
|
|
||||||
* Imported from \c netlcdclient.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (C) 2002 Luis Llorente Campo
|
|
||||||
*
|
|
||||||
* This program 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, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef IFACE_H
|
|
||||||
#define IFACE_H
|
|
||||||
|
|
||||||
/** max number of interfaces in multi-interface mode */
|
|
||||||
#define MAX_INTERFACES 3
|
|
||||||
|
|
||||||
IfaceInfo iface[MAX_INTERFACES]; /* interface info */
|
|
||||||
|
|
||||||
/** Update screen content */
|
|
||||||
int iface_screen(int rep, int display, int *flags_ptr);
|
|
||||||
/** read interface stats from /proc/net/dev */
|
|
||||||
int get_iface_stats(IfaceInfo *interface);
|
|
||||||
/** send initial commands to server to add the speed screen */
|
|
||||||
void initialize_speed_screen(void);
|
|
||||||
/** send initial commands to server to add the transfer screen */
|
|
||||||
void initialize_transfer_screen(void);
|
|
||||||
/** format the time in ASCII */
|
|
||||||
void get_time_string(char *buff, time_t last_online);
|
|
||||||
/** format value, scaling value and adding proper suffixes */
|
|
||||||
void format_value(char *buff, double value, char *unit);
|
|
||||||
/** format value, scaling value and adding proper suffixes (for multi-interface
|
|
||||||
* mode) */
|
|
||||||
void format_value_multi_interface(char *buff, double value, char *unit);
|
|
||||||
/** actualize widgets values in speed screen */
|
|
||||||
void actualize_speed_screen(IfaceInfo *iface, unsigned int interval, int index);
|
|
||||||
/** actualize widgets values in transfer screen */
|
|
||||||
void actualize_transfer_screen(IfaceInfo *iface, int index);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
# LCDproc client configuration file
|
|
||||||
|
|
||||||
## general options ##
|
|
||||||
[lcdproc]
|
|
||||||
# address of the LCDd server to connect to
|
|
||||||
Server=localhost
|
|
||||||
|
|
||||||
# Port of the server to connect to
|
|
||||||
Port=13666
|
|
||||||
|
|
||||||
# set reporting level
|
|
||||||
ReportLevel=2
|
|
||||||
|
|
||||||
# report to to syslog ?
|
|
||||||
ReportToSyslog=false
|
|
||||||
|
|
||||||
# run in foreground [default: false; legal: true, false]
|
|
||||||
#Foreground=true
|
|
||||||
|
|
||||||
# PidFile location when running as daemon [default: /var/run/lcdproc.pid]
|
|
||||||
#PidFile=/var/run/lcdproc.pid
|
|
||||||
|
|
||||||
# slow down initial announcement of modes (in 1/100s)
|
|
||||||
#delay=2
|
|
||||||
|
|
||||||
# display name for the main menu [default: LCDproc HOST]
|
|
||||||
#DisplayName=lcdproc
|
|
||||||
|
|
||||||
|
|
||||||
## screen specific configuration options ##
|
|
||||||
|
|
||||||
[CPU]
|
|
||||||
# Show screen
|
|
||||||
Active=True
|
|
||||||
OnTime=1
|
|
||||||
OffTime=2
|
|
||||||
ShowInvisible=false
|
|
||||||
|
|
||||||
|
|
||||||
[Iface]
|
|
||||||
# Show screen
|
|
||||||
Active=True
|
|
||||||
|
|
||||||
# Show stats for Interface0
|
|
||||||
Interface0=eth0
|
|
||||||
# Interface alias name to display [default: <interface name>]
|
|
||||||
Alias0=LAN
|
|
||||||
|
|
||||||
# Show stats for Interface1
|
|
||||||
#Interface1=eth1
|
|
||||||
#Alias1=WAN
|
|
||||||
|
|
||||||
# Show stats for Interface2
|
|
||||||
#Interface2=eth2
|
|
||||||
#Alias2=MGMT
|
|
||||||
|
|
||||||
# for more than 3 interfaces change MAX_INTERFACES in iface.h and rebuild
|
|
||||||
|
|
||||||
# Units to display [default: byte; legal: byte, bit, packet]
|
|
||||||
unit=bit
|
|
||||||
|
|
||||||
# add screen with transferred traffic
|
|
||||||
#transfer=TRUE
|
|
||||||
|
|
||||||
|
|
||||||
[Memory]
|
|
||||||
# Show screen
|
|
||||||
Active=True
|
|
||||||
|
|
||||||
|
|
||||||
[Load]
|
|
||||||
# Show screen
|
|
||||||
Active=True
|
|
||||||
# Min Load Avg at which the backlight will be turned off [default: 0.05]
|
|
||||||
LowLoad=0.05
|
|
||||||
# Max Load Avg at which the backlight will start blinking [default: 1.3]
|
|
||||||
HighLoad=1.3
|
|
||||||
|
|
||||||
|
|
||||||
[TimeDate]
|
|
||||||
# Show screen
|
|
||||||
Active=True
|
|
||||||
# time format [default: %H:%M:%S; legal: see strftime(3)]
|
|
||||||
TimeFormat="%H:%M:%S"
|
|
||||||
# date format [default: %x; legal: see strftime(3)]
|
|
||||||
DateFormat="%x"
|
|
||||||
|
|
||||||
|
|
||||||
[About]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[SMP-CPU]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[OldTime]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
# time format [default: %H:%M:%S; legal: see strftime(3)]
|
|
||||||
TimeFormat="%H:%M:%S"
|
|
||||||
# date format [default: %x; legal: see strftime(3)]
|
|
||||||
DateFormat="%x"
|
|
||||||
# Display the title bar in two-line mode. Note that with four lines or more
|
|
||||||
# the title is always shown. [default: true; legal: true, false]
|
|
||||||
#ShowTitle=false
|
|
||||||
|
|
||||||
|
|
||||||
[BigClock]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[Uptime]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[Battery]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[CPUGraph]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[ProcSize]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[Disk]
|
|
||||||
# Show screen
|
|
||||||
Active=false
|
|
||||||
|
|
||||||
|
|
||||||
[MiniClock]
|
|
||||||
# Show screen
|
|
||||||
Active=True
|
|
||||||
# time format [default: %H:%M; legal: see strftime(3)]
|
|
||||||
TimeFormat="%H:%M"
|
|
||||||
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
/** \file clients/lcdproc/load.c
|
|
||||||
* Implements the 'Load' screen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "load.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a display very similar to "xload"'s histogram.
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## LOAD 0.44: myh #@| |myhost 0.24 1|
|
|
||||||
* | 1| | |||||||||||0|
|
|
||||||
* | |||||| | +--------------------+
|
|
||||||
* | |||| |||||||| 0|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return The backlight state
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xload_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
static int gauge_hgt = 0;
|
|
||||||
static double loads[LCD_MAX_WIDTH];
|
|
||||||
static double lowLoad = LOAD_MIN;
|
|
||||||
static double highLoad = LOAD_MAX;
|
|
||||||
int loadtop, i;
|
|
||||||
double loadmax = 0, factor;
|
|
||||||
int status = BACKLIGHT_ON;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
/* get config values */
|
|
||||||
lowLoad = config_get_float("Load", "LowLoad", 0, LOAD_MIN);
|
|
||||||
highLoad = config_get_float("Load", "HighLoad", 0, LOAD_MAX);
|
|
||||||
|
|
||||||
gauge_hgt = (lcd_hgt > 2) ? (lcd_hgt - 1) : lcd_hgt;
|
|
||||||
memset(loads, '\0', sizeof(double) * LCD_MAX_WIDTH);
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add L\n");
|
|
||||||
sock_printf(sock, "screen_set L -name {Load: %s}\n", get_hostname());
|
|
||||||
/* Add the vbars... */
|
|
||||||
for (i = 1; i < lcd_wid; i++) {
|
|
||||||
sock_printf(sock, "widget_add L bar%i vbar\n", i);
|
|
||||||
sock_printf(sock, "widget_set L bar%i %i %i 0\n", i, i, lcd_hgt);
|
|
||||||
}
|
|
||||||
/* And add a title... */
|
|
||||||
if (lcd_hgt > 2) {
|
|
||||||
sock_send_string(sock, "widget_add L title title\n");
|
|
||||||
sock_send_string(sock, "widget_set L title {LOAD }\n");
|
|
||||||
} else {
|
|
||||||
sock_send_string(sock, "widget_add L title string\n");
|
|
||||||
sock_send_string(sock, "widget_set L title 1 1 {LOAD}\n");
|
|
||||||
sock_send_string(sock, "screen_set L -heartbeat off\n");
|
|
||||||
}
|
|
||||||
sock_send_string(sock, "widget_add L zero string\n");
|
|
||||||
sock_send_string(sock, "widget_add L top string\n");
|
|
||||||
sock_printf(sock, "widget_set L zero %i %i 0\n", lcd_wid, lcd_hgt);
|
|
||||||
sock_printf(sock, "widget_set L top %i %i 1\n", lcd_wid, (lcd_hgt + 1 - gauge_hgt));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* shift load history */
|
|
||||||
for (i = 0; i < (lcd_wid - 2); i++)
|
|
||||||
loads[i] = loads[i + 1];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get new load value, ignore failure: the shift above makes sure we
|
|
||||||
* still have the previous value
|
|
||||||
*/
|
|
||||||
machine_get_loadavg(&(loads[lcd_wid - 2]));
|
|
||||||
|
|
||||||
/* determine max. load from history */
|
|
||||||
for (i = 0; i < lcd_wid - 1; i++)
|
|
||||||
loadmax = max(loadmax, loads[i]);
|
|
||||||
|
|
||||||
/* poor man's ceil() */
|
|
||||||
loadtop = (int) loadmax;
|
|
||||||
if (loadtop < loadmax)
|
|
||||||
loadtop++;
|
|
||||||
loadtop = max(1, loadtop);
|
|
||||||
|
|
||||||
factor = (double) (lcd_cellhgt * gauge_hgt) / (double) loadtop;
|
|
||||||
|
|
||||||
/* display load */
|
|
||||||
sock_printf(sock, "widget_set L top %i %i %i\n", lcd_wid, (lcd_hgt + 1 - gauge_hgt), loadtop);
|
|
||||||
|
|
||||||
for (i = 0; i < lcd_wid - 1; i++) {
|
|
||||||
double x = loads[i] * factor;
|
|
||||||
|
|
||||||
sock_printf(sock, "widget_set L bar%i %i %i %i\n", i + 1, i + 1, lcd_hgt, (int) x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And now the title... */
|
|
||||||
if (lcd_hgt > 2)
|
|
||||||
sock_printf(sock, "widget_set L title {LOAD %2.2f: %s}\n", loads[lcd_wid - 2], get_hostname());
|
|
||||||
else
|
|
||||||
sock_printf(sock, "widget_set L title 1 1 {%s %2.2f}\n", get_hostname(), loads[lcd_wid - 2]);
|
|
||||||
|
|
||||||
/* set return status depending on max & current load */
|
|
||||||
if (lowLoad < highLoad) {
|
|
||||||
status = (loadmax > lowLoad) ? BACKLIGHT_ON : BACKLIGHT_OFF;
|
|
||||||
if (loads[lcd_wid - 2] > highLoad)
|
|
||||||
status = BLINK_ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#ifndef LOAD_H
|
|
||||||
#define LOAD_H
|
|
||||||
|
|
||||||
#ifndef LOAD_MAX
|
|
||||||
#define LOAD_MAX 1.3
|
|
||||||
#endif
|
|
||||||
#ifndef LOAD_MIN
|
|
||||||
#define LOAD_MIN 0.05
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int xload_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine.h
|
|
||||||
* Common data types and function declarations
|
|
||||||
* for OS specific sources in \c machine_{Darwin,Linux,SunOS,*BSD}.c.
|
|
||||||
*
|
|
||||||
* In order to port the \e lcdproc client to a new operating system,
|
|
||||||
* a new file \c machine_XXX.c (where \c XXX = OS name) needs to be
|
|
||||||
* created, that provides functions to the function declarations below.
|
|
||||||
* The aleady existing \c machine_*.c files can be used as examples.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _lcdproc_machine_h_
|
|
||||||
#define _lcdproc_machine_h_
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
#ifndef LOADAVG_NSTATS
|
|
||||||
# define LOADAVG_NSTATS 3 /**< size of loadavg[] parameter to getloadavg() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LOADAVG_1MIN
|
|
||||||
# define LOADAVG_1MIN 0 /**< index in loadavg[] parameter to getloadavg() for 1 minute load average */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LOADAVG_5MIN
|
|
||||||
# define LOADAVG_5MIN 1 /**< index in loadavg[] parameter to getloadavg() for 5 minute load average */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LOADAVG_15MIN
|
|
||||||
# define LOADAVG_15MIN 2 /**< index in loadavg[] parameter to getloadavg() for 15 minute load average */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX_CPUS
|
|
||||||
# define MAX_CPUS 16 /**< maximal number of CPUs for which load history is kept */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/** Information about CPU load */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned long total; /**< total time (in USER_HZ; since last call) */
|
|
||||||
unsigned long user; /**< time in user mode (in USER_HZ; since last call) */
|
|
||||||
unsigned long system; /**< time in kernel mode (in USER_HZ; since last call) */
|
|
||||||
unsigned long nice; /**< time in 'niced' user mode (in USER_HZ; since last call) */
|
|
||||||
unsigned long idle; /**< time idling (in USER_HZ; since last call) */
|
|
||||||
} load_type;
|
|
||||||
|
|
||||||
|
|
||||||
/** Information about mounted file systems */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char dev[256]; /**< device name */
|
|
||||||
char type[64]; /**< file system type (as string) */
|
|
||||||
char mpoint[256]; /**< mount point name */
|
|
||||||
long bsize; /**< transfer block size */
|
|
||||||
long blocks; /**< total data blocks in file system */
|
|
||||||
long bfree; /**< free blocks in fs */
|
|
||||||
long files; /**< total file nodes in file system */
|
|
||||||
long ffree; /**< free file nodes in fs */
|
|
||||||
} mounts_type;
|
|
||||||
|
|
||||||
|
|
||||||
/** Information about memory status */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
long total; /**< total memory (in kB) */
|
|
||||||
long cache; /**< memory in page cache (in kB) */
|
|
||||||
long buffers; /**< memory in buffer cache (in kB) */
|
|
||||||
long free; /**< free memory (in kB) */
|
|
||||||
long shared; /**< ??? (in kB) */
|
|
||||||
} meminfo_type;
|
|
||||||
|
|
||||||
|
|
||||||
/** Information about processes and their size */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char name[16]; /**< process name */
|
|
||||||
long totl; /**< process memory usage (in kB) */
|
|
||||||
int number; /**< incstances of the process */
|
|
||||||
} procinfo_type;
|
|
||||||
|
|
||||||
|
|
||||||
/** Status definitions for network interfaces */
|
|
||||||
typedef enum {
|
|
||||||
down = 0,
|
|
||||||
up = 1,
|
|
||||||
} IfaceStatus;
|
|
||||||
|
|
||||||
/* Network Interface information */
|
|
||||||
typedef struct iface_info
|
|
||||||
{
|
|
||||||
char *name; /**< physical interface name */
|
|
||||||
char *alias; /**< displayed name of interface */
|
|
||||||
|
|
||||||
IfaceStatus status; /**< status of the interface */
|
|
||||||
|
|
||||||
time_t last_online;
|
|
||||||
|
|
||||||
double rc_byte; /**< currently received bytes */
|
|
||||||
double rc_byte_old; /**< previously received bytes */
|
|
||||||
|
|
||||||
double tr_byte; /**< currently sent bytes */
|
|
||||||
double tr_byte_old; /**< previously sent bytes */
|
|
||||||
|
|
||||||
double rc_pkt; /**< currently received packages */
|
|
||||||
double rc_pkt_old; /**< previously received packages */
|
|
||||||
|
|
||||||
double tr_pkt; /**< currently sent packages */
|
|
||||||
double tr_pkt_old; /**< previously sent packages */
|
|
||||||
} IfaceInfo;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up OS specific functions.
|
|
||||||
* \retval FALSE Error
|
|
||||||
* \retval TRUE OK
|
|
||||||
*/
|
|
||||||
int machine_init(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tear down (clean up) OS specific functions.
|
|
||||||
* \retval FALSE Error
|
|
||||||
* \retval TRUE OK
|
|
||||||
*/
|
|
||||||
int machine_close(void);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get battery information.
|
|
||||||
* \param acstat Pointer to information whether the system runs on AC power or on battery.
|
|
||||||
* \param battflag Pointer to information about the battery load status.
|
|
||||||
* \param percent Pointer to the battery fill state.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_battstat(int *acstat, int *battflag, int *percent);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get information about mounted file systems.
|
|
||||||
* \param fs Pointer to array where file system information gets stored.
|
|
||||||
* \param cnt Number of mounted file systems.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_fs(mounts_type fs[], int *cnt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get total CPU load (added over all CPUs).
|
|
||||||
* \param cur_load Pointer where to store current load information.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_load(load_type *cur_load);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get load 1min load average.
|
|
||||||
* \param load Pointer where to store the current 1min load average.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_loadavg(double *load);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get information about memory.
|
|
||||||
* \param result Pointer where meminfo is to be stored.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_meminfo(meminfo_type *result);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get list of processes and their sizes.
|
|
||||||
* \param procs Pointer where to store the linked List of processes.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_procs(LinkedList *procs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get CPU load split up for each CPU.
|
|
||||||
* \param result Pointer to array of CPU load info.
|
|
||||||
* \param numcpus Number of CPUs found.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_smpload(load_type *result, int *numcpus);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get uptime.
|
|
||||||
* \param up Pointer to store the uptime in seconds.
|
|
||||||
* \param idle Pointer to store the percentage in which the CPUs idled since boot.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_uptime(double *up, double *idle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read network interface statistics for a single interface from system and
|
|
||||||
* store results in the struct IfaceInfo.
|
|
||||||
*
|
|
||||||
* \param interface Pointer where to store interface info.
|
|
||||||
* \retval FALSE Error, do not trust the contents of the parameter pointers.
|
|
||||||
* \retval TRUE OK, parameter pointers are filled with sensible data.
|
|
||||||
*/
|
|
||||||
int machine_get_iface_stats(IfaceInfo *interface);
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _lcdproc_machine_h_ */
|
|
||||||
@@ -1,549 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine_Darwin.c
|
|
||||||
* Collects system information on MacOS / Darwin.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003 Thomas Runge (coto@core.de)
|
|
||||||
*
|
|
||||||
* Mach and Darwin specific code is:
|
|
||||||
* Copyright (c) 2006 Eric Pooch (epooch@tenon.com)
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this
|
|
||||||
* software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/dkstat.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_mib.h>
|
|
||||||
#include <mach/mach.h>
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#include <IOKit/ps/IOPowerSources.h>
|
|
||||||
#include <IOKit/ps/IOPSKeys.h>
|
|
||||||
|
|
||||||
static int pageshift;
|
|
||||||
#define pagetok(size) ((size) << pageshift)
|
|
||||||
static int swapmode(int *rettotal, int *retfree);
|
|
||||||
|
|
||||||
static mach_port_t lcdproc_port;
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_init(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* get the page size with "getpagesize" and calculate pageshift from
|
|
||||||
* it
|
|
||||||
*/
|
|
||||||
unsigned int pagesize = 0;
|
|
||||||
pageshift = 0;
|
|
||||||
|
|
||||||
lcdproc_port = mach_host_self();
|
|
||||||
host_page_size(lcdproc_port, &pagesize);
|
|
||||||
|
|
||||||
while (pagesize > 1) {
|
|
||||||
pageshift++;
|
|
||||||
pagesize >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we only need the amount of log(2)1024 for our conversion */
|
|
||||||
pageshift -= 10;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_close(void)
|
|
||||||
{
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_battstat(int *acstat, int *battflag, int *percent)
|
|
||||||
{
|
|
||||||
CFTypeRef blob = IOPSCopyPowerSourcesInfo();
|
|
||||||
CFArrayRef sources = IOPSCopyPowerSourcesList(blob);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
CFDictionaryRef pSource = NULL;
|
|
||||||
const void *psValue;
|
|
||||||
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
*percent = 100;
|
|
||||||
|
|
||||||
if (CFArrayGetCount(sources) == 0)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(sources); i++) {
|
|
||||||
pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i));
|
|
||||||
if (!pSource)
|
|
||||||
break;
|
|
||||||
|
|
||||||
psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey));
|
|
||||||
|
|
||||||
if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsPresentKey), &psValue) && (CFBooleanGetValue(psValue) > 0)) {
|
|
||||||
psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey));
|
|
||||||
|
|
||||||
if (CFStringCompare(psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo) {
|
|
||||||
/* We are running on a battery power source. */
|
|
||||||
*battflag = LCDP_BATT_UNKNOWN;
|
|
||||||
*acstat = LCDP_AC_OFF;
|
|
||||||
}
|
|
||||||
else if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsChargingKey), &psValue)) {
|
|
||||||
/*
|
|
||||||
* We are running on an AC power source, but
|
|
||||||
* we also have a battery power source
|
|
||||||
* present.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (CFBooleanGetValue(psValue) > 0)
|
|
||||||
*battflag = LCDP_BATT_CHARGING;
|
|
||||||
else
|
|
||||||
*battflag = LCDP_BATT_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*battflag != LCDP_BATT_ABSENT) {
|
|
||||||
int curCapacity = 0;
|
|
||||||
int maxCapacity = 0;
|
|
||||||
|
|
||||||
psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSCurrentCapacityKey));
|
|
||||||
CFNumberGetValue(psValue, kCFNumberSInt32Type, &curCapacity);
|
|
||||||
|
|
||||||
psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSMaxCapacityKey));
|
|
||||||
CFNumberGetValue(psValue, kCFNumberSInt32Type, &maxCapacity);
|
|
||||||
|
|
||||||
*percent = (int)((double)curCapacity / (double)maxCapacity * 100);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There is a way to check this through the
|
|
||||||
* IOKit, but I am not sure what gets
|
|
||||||
* returned for kIOPSLowWarnLevelKey and
|
|
||||||
* kIOPSDeadWarnLevelKey, and this is easier.
|
|
||||||
*/
|
|
||||||
if (*battflag == LCDP_BATT_UNKNOWN) {
|
|
||||||
if (*percent > 50)
|
|
||||||
*battflag = LCDP_BATT_HIGH;
|
|
||||||
else if (*percent > 2)
|
|
||||||
*battflag = LCDP_BATT_LOW;
|
|
||||||
else
|
|
||||||
*battflag = LCDP_BATT_CRITICAL;
|
|
||||||
}
|
|
||||||
/* printf ("powerSource %d of %d: percent: %d/%d %d\n", i, CFArrayGetCount(sources), curCapacity, maxCapacity, *percent);*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(blob);
|
|
||||||
CFRelease(sources);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_fs(mounts_type fs[], int *cnt)
|
|
||||||
{
|
|
||||||
struct statfs *mntbuf;
|
|
||||||
struct statfs *pp;
|
|
||||||
int statcnt, fscnt, i;
|
|
||||||
|
|
||||||
fscnt = getmntinfo(&mntbuf, MNT_WAIT);
|
|
||||||
if (fscnt == 0) {
|
|
||||||
perror("getmntinfo");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
for (statcnt = 0, pp = mntbuf, i = 0; i < fscnt; pp++, i++) {
|
|
||||||
if (strcmp(pp->f_fstypename, "procfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "kernfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "linprocfs")
|
|
||||||
#ifndef STAT_NFS
|
|
||||||
&& strcmp(pp->f_fstypename, "nfs")
|
|
||||||
#endif
|
|
||||||
#ifndef STAT_SMBFS
|
|
||||||
&& strcmp(pp->f_fstypename, "smbfs")
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
snprintf(fs[statcnt].dev, 255, "%s", pp->f_mntfromname);
|
|
||||||
snprintf(fs[statcnt].mpoint, 255, "%s", pp->f_mntonname);
|
|
||||||
snprintf(fs[statcnt].type, 63, "%s", pp->f_fstypename);
|
|
||||||
|
|
||||||
fs[statcnt].blocks = pp->f_blocks;
|
|
||||||
if (fs[statcnt].blocks > 0) {
|
|
||||||
fs[statcnt].bsize = pp->f_bsize;
|
|
||||||
fs[statcnt].bfree = pp->f_bfree;
|
|
||||||
fs[statcnt].files = pp->f_files;
|
|
||||||
fs[statcnt].ffree = pp->f_ffree;
|
|
||||||
}
|
|
||||||
statcnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*cnt = statcnt;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_load(load_type * curr_load)
|
|
||||||
{
|
|
||||||
static load_type last_load = {0, 0, 0, 0, 0};
|
|
||||||
static load_type last_ret_load;
|
|
||||||
load_type load;
|
|
||||||
|
|
||||||
host_cpu_load_info_data_t load_info;
|
|
||||||
mach_msg_type_number_t info_count;
|
|
||||||
|
|
||||||
info_count = HOST_CPU_LOAD_INFO_COUNT;
|
|
||||||
if (host_statistics(lcdproc_port, HOST_CPU_LOAD_INFO, (host_info_t) & load_info, &info_count)) {
|
|
||||||
perror("host_statistics");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
load.user = (unsigned long)(load_info.cpu_ticks[CPU_STATE_USER]);
|
|
||||||
load.nice = (unsigned long)(load_info.cpu_ticks[CPU_STATE_NICE]);
|
|
||||||
load.system = (unsigned long)(load_info.cpu_ticks[CPU_STATE_SYSTEM]);
|
|
||||||
load.idle = (unsigned long)(load_info.cpu_ticks[CPU_STATE_IDLE]);
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
if (load.total != last_load.total) {
|
|
||||||
curr_load->user = load.user - last_load.user;
|
|
||||||
curr_load->nice = load.nice - last_load.nice;
|
|
||||||
curr_load->system = load.system - last_load.system;
|
|
||||||
curr_load->idle = load.idle - last_load.idle;
|
|
||||||
curr_load->total = load.total - last_load.total;
|
|
||||||
last_ret_load = *curr_load;
|
|
||||||
last_load = load;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*curr_load = last_ret_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_loadavg(double *load)
|
|
||||||
{
|
|
||||||
double loadavg[LOADAVG_NSTATS];
|
|
||||||
|
|
||||||
if (getloadavg(loadavg, LOADAVG_NSTATS) <= LOADAVG_1MIN)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
*load = loadavg[LOADAVG_1MIN];
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_meminfo(meminfo_type * result)
|
|
||||||
{
|
|
||||||
int total_pages, free_pages;
|
|
||||||
|
|
||||||
vm_statistics_data_t vm_info;
|
|
||||||
mach_msg_type_number_t info_count;
|
|
||||||
|
|
||||||
info_count = HOST_VM_INFO_COUNT;
|
|
||||||
if (host_statistics(lcdproc_port, HOST_VM_INFO, (host_info_t) & vm_info, &info_count)) {
|
|
||||||
perror("host_statistics");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
result[0].total = pagetok(vm_info.active_count + vm_info.inactive_count +
|
|
||||||
vm_info.free_count + vm_info.wire_count);
|
|
||||||
result[0].free = pagetok(vm_info.free_count);
|
|
||||||
result[0].buffers = 0;
|
|
||||||
result[0].cache = 0;
|
|
||||||
result[0].shared = 0;
|
|
||||||
|
|
||||||
/* swap */
|
|
||||||
result[1].total = 0;
|
|
||||||
result[1].free = 0;
|
|
||||||
|
|
||||||
if (swapmode(&total_pages, &free_pages) != -1) {
|
|
||||||
result[1].total = total_pages;
|
|
||||||
result[1].free = free_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_procs(LinkedList * procs)
|
|
||||||
{
|
|
||||||
struct kinfo_proc *kprocs;
|
|
||||||
|
|
||||||
procinfo_type *p;
|
|
||||||
int nproc, i;
|
|
||||||
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
|
|
||||||
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
/* Call sysctl with a NULL buffer as a dry run. */
|
|
||||||
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
|
|
||||||
perror("Failure calling sysctl");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
/* Allocate a buffer based on previous results of sysctl. */
|
|
||||||
kprocs = (struct kinfo_proc *)alloca(size);
|
|
||||||
if (kprocs == NULL) {
|
|
||||||
perror("mem_alloca");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
/* Call sysctl again with the new buffer. */
|
|
||||||
if (sysctl(mib, 4, kprocs, &size, NULL, 0) < 0) {
|
|
||||||
perror("Failure calling sysctl");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nproc = size / sizeof(struct kinfo_proc);
|
|
||||||
|
|
||||||
for (i = 0; i < nproc; i++, kprocs++) {
|
|
||||||
mach_port_t task;
|
|
||||||
unsigned int status = kprocs->kp_proc.p_stat;
|
|
||||||
|
|
||||||
if (status == SIDL || status == SZOMB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
p = malloc(sizeof(procinfo_type));
|
|
||||||
if (!p) {
|
|
||||||
perror("mem_malloc");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
strncpy(p->name, kprocs->kp_proc.p_comm, 15);
|
|
||||||
p->name[15] = '\0';
|
|
||||||
|
|
||||||
p->number = kprocs->kp_proc.p_pid;
|
|
||||||
|
|
||||||
LL_Push(procs, (void *)p);
|
|
||||||
|
|
||||||
/* Normal user can't get tasks for processes owned by root. */
|
|
||||||
if (kprocs->kp_eproc.e_pcred.p_ruid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Get the memory data for each pid from Mach. */
|
|
||||||
if (task_for_pid(mach_task_self(), kprocs->kp_proc.p_pid, &task) == KERN_SUCCESS) {
|
|
||||||
task_basic_info_data_t info;
|
|
||||||
mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
|
|
||||||
|
|
||||||
if (task_info(task, TASK_BASIC_INFO, (task_info_t) & info, &count) == KERN_SUCCESS) {
|
|
||||||
p->totl = (unsigned long)( /* info.virtual_size */ info.resident_size / 1024);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* This error pops up very often because of Mac OS X
|
|
||||||
* security fixes. It might pop up all of the time on
|
|
||||||
* an intel Mac. Basically, we cannot get many tasks
|
|
||||||
* unless we are root.
|
|
||||||
*/
|
|
||||||
/* perror("task_for_pid"); */
|
|
||||||
p->totl = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kprocs -= i;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_smpload(load_type * result, int *numcpus)
|
|
||||||
{
|
|
||||||
int i, num;
|
|
||||||
size_t size;
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
size = sizeof(int);
|
|
||||||
if (sysctlbyname("hw.ncpu", &num, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl hw.ncpu");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if (numcpus == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
/* restrict #CPUs to max. *numcpus */
|
|
||||||
num = (*numcpus >= num) ? num : *numcpus;
|
|
||||||
*numcpus = num;
|
|
||||||
|
|
||||||
/* Don't know how to get per-cpu-load values */
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
result[i] = curr_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_uptime(double *up, double *idle)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
time_t now;
|
|
||||||
struct timeval boottime;
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
int mib[2];
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_BOOTTIME;
|
|
||||||
size = sizeof(boottime);
|
|
||||||
|
|
||||||
time(&now);
|
|
||||||
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
|
|
||||||
boottime.tv_sec != 0)
|
|
||||||
*up = (double)(now - boottime.tv_sec);
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
*idle = 100.;
|
|
||||||
else
|
|
||||||
*idle = 100. * curr_load.idle / curr_load.total;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
swapmode(int *rettotal, int *retfree)
|
|
||||||
{
|
|
||||||
#ifdef VM_SWAPUSAGE
|
|
||||||
size_t size;
|
|
||||||
struct xsw_usage xsu;
|
|
||||||
|
|
||||||
int mib[2];
|
|
||||||
mib[0] = CTL_VM;
|
|
||||||
mib[1] = VM_SWAPUSAGE;
|
|
||||||
size = sizeof(xsu);
|
|
||||||
|
|
||||||
*rettotal = 0;
|
|
||||||
*retfree = 0;
|
|
||||||
|
|
||||||
if (sysctl(mib, 2, &xsu, &size, NULL, 0) != 0) {
|
|
||||||
perror("sysctl");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
*rettotal = (xsu.xsu_total / 1024);
|
|
||||||
*retfree = ((xsu.xsu_total - xsu.xsu_used) / 1024);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*rettotal = 0;
|
|
||||||
*retfree = 0;
|
|
||||||
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get network statistics */
|
|
||||||
int
|
|
||||||
machine_get_iface_stats(IfaceInfo * interface)
|
|
||||||
{
|
|
||||||
int rows;
|
|
||||||
int name[6] = {CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_SYSTEM, IFMIB_IFCOUNT};
|
|
||||||
size_t len;
|
|
||||||
struct ifmibdata ifmd; /* ifmibdata contains the network statistics */
|
|
||||||
|
|
||||||
len = sizeof(rows);
|
|
||||||
/* get number of interfaces */
|
|
||||||
if (sysctl(name, 5, &rows, &len, 0, 0) == 0) {
|
|
||||||
interface->status = down; /* set status down by default */
|
|
||||||
|
|
||||||
name[3] = IFMIB_IFDATA;
|
|
||||||
name[4] = 0;
|
|
||||||
name[5] = IFDATA_GENERAL;
|
|
||||||
|
|
||||||
len = sizeof(ifmd);
|
|
||||||
/*
|
|
||||||
* walk through all interfaces in the ifmib table from last
|
|
||||||
* to first
|
|
||||||
*/
|
|
||||||
for (; rows > 0; rows--) {
|
|
||||||
name[4] = rows; /* set the interface index */
|
|
||||||
/* retrive the ifmibdata for the current index */
|
|
||||||
if (sysctl(name, 6, &ifmd, &len, NULL, 0) == -1) {
|
|
||||||
perror("read sysctl");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* check if its interface name matches */
|
|
||||||
if (strcmp(ifmd.ifmd_name, interface->name) == 0) {
|
|
||||||
|
|
||||||
interface->rc_byte = ifmd.ifmd_data.ifi_ibytes;
|
|
||||||
interface->tr_byte = ifmd.ifmd_data.ifi_obytes;
|
|
||||||
interface->rc_pkt = ifmd.ifmd_data.ifi_ipackets;
|
|
||||||
interface->tr_pkt = ifmd.ifmd_data.ifi_opackets;
|
|
||||||
|
|
||||||
if (interface->last_online == 0) {
|
|
||||||
interface->rc_byte_old = interface->rc_byte;
|
|
||||||
interface->tr_byte_old = interface->tr_byte;
|
|
||||||
interface->rc_pkt_old = interface->rc_pkt;
|
|
||||||
interface->tr_pkt_old = interface->tr_pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ifmd.ifmd_flags & IFF_UP) == IFF_UP) {
|
|
||||||
interface->status = up; /* is up */
|
|
||||||
interface->last_online = time(NULL); /* save actual time */
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* if we are here there is no interface with the given name */
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
perror("read sysctl IFMIB_IFCOUNT");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* __APPLE__ */
|
|
||||||
@@ -1,536 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine_FreeBSD.c
|
|
||||||
* Collects system information on FreeBSD.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003 Thomas Runge (coto@core.de)
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this
|
|
||||||
* software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/dkstat.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_mib.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_MACHINE_APM_BIOS_H
|
|
||||||
# include <machine/apm_bios.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_PCPU_H
|
|
||||||
# include <sys/pcpu.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
static int pageshift;
|
|
||||||
static kvm_t *kvmd;
|
|
||||||
#define pagetok(size) ((size) << pageshift)
|
|
||||||
static int swapmode(int *retavail, int *retfree);
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_init(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* get the page size with "getpagesize" and calculate pageshift from
|
|
||||||
* it
|
|
||||||
*/
|
|
||||||
int pagesize = getpagesize();
|
|
||||||
pageshift = 0;
|
|
||||||
while (pagesize > 1) {
|
|
||||||
pageshift++;
|
|
||||||
pagesize >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we only need the amount of log(2)1024 for our conversion */
|
|
||||||
pageshift -= 10;
|
|
||||||
|
|
||||||
/* open kernel virtual memory */
|
|
||||||
if ((kvmd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) {
|
|
||||||
perror("kvm_open failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_close(void)
|
|
||||||
{
|
|
||||||
if (kvmd != NULL) {
|
|
||||||
kvm_close(kvmd);
|
|
||||||
kvmd = NULL;
|
|
||||||
}
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_battstat(int *acstat, int *battflag, int *percent)
|
|
||||||
{
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
*percent = 100;
|
|
||||||
|
|
||||||
#ifdef HAVE_MACHINE_APM_BIOS_H
|
|
||||||
int apmd;
|
|
||||||
struct apm_info aip;
|
|
||||||
|
|
||||||
if ((apmd = open("/dev/apm", O_RDONLY)) == -1) {
|
|
||||||
perror("get_battstat_open");
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(apmd, APMIO_GETINFO, &aip) == -1) {
|
|
||||||
perror("get_battstat_ioctl");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (aip.ai_acline) {
|
|
||||||
case 0:
|
|
||||||
*acstat = LCDP_AC_OFF;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*acstat = LCDP_AC_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (aip.ai_batt_stat) {
|
|
||||||
case 0:
|
|
||||||
*battflag = LCDP_BATT_HIGH;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*battflag = LCDP_BATT_LOW;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*battflag = LCDP_BATT_CRITICAL;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
*battflag = LCDP_BATT_CHARGING;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*battflag = LCDP_BATT_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*percent = aip.ai_batt_life;
|
|
||||||
if (*percent == 255)
|
|
||||||
*percent = -1;
|
|
||||||
|
|
||||||
close(apmd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_fs(mounts_type fs[], int *cnt)
|
|
||||||
{
|
|
||||||
struct statfs *mntbuf;
|
|
||||||
struct statfs *pp;
|
|
||||||
int statcnt, fscnt, i;
|
|
||||||
|
|
||||||
fscnt = getmntinfo(&mntbuf, MNT_WAIT);
|
|
||||||
if (fscnt == 0) {
|
|
||||||
perror("getmntinfo");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
for (statcnt = 0, pp = mntbuf, i = 0; i < fscnt; pp++, i++) {
|
|
||||||
if (strcmp(pp->f_fstypename, "procfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "devfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "kernfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "linprocfs")
|
|
||||||
#ifndef STAT_NFS
|
|
||||||
&& strcmp(pp->f_fstypename, "nfs")
|
|
||||||
#endif
|
|
||||||
#ifndef STAT_SMBFS
|
|
||||||
&& strcmp(pp->f_fstypename, "smbfs")
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
snprintf(fs[statcnt].dev, 255, "%s", pp->f_mntfromname);
|
|
||||||
snprintf(fs[statcnt].mpoint, 255, "%s", pp->f_mntonname);
|
|
||||||
snprintf(fs[statcnt].type, 63, "%s", pp->f_fstypename);
|
|
||||||
|
|
||||||
fs[statcnt].blocks = pp->f_blocks;
|
|
||||||
if (fs[statcnt].blocks > 0) {
|
|
||||||
fs[statcnt].bsize = pp->f_bsize;
|
|
||||||
fs[statcnt].bfree = pp->f_bfree;
|
|
||||||
fs[statcnt].files = pp->f_files;
|
|
||||||
fs[statcnt].ffree = pp->f_ffree;
|
|
||||||
}
|
|
||||||
statcnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*cnt = statcnt;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_load(load_type * curr_load)
|
|
||||||
{
|
|
||||||
static load_type last_load = {0, 0, 0, 0, 0};
|
|
||||||
static load_type last_ret_load;
|
|
||||||
load_type load;
|
|
||||||
long cp_time[CPUSTATES];
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
size = sizeof(cp_time);
|
|
||||||
if (sysctlbyname("kern.cp_time", cp_time, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl kern.cp_time failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
load.user = (unsigned long)(cp_time[CP_USER]);
|
|
||||||
load.nice = (unsigned long)(cp_time[CP_NICE]);
|
|
||||||
load.system = (unsigned long)(cp_time[CP_SYS] + cp_time[CP_INTR]);
|
|
||||||
load.idle = (unsigned long)(cp_time[CP_IDLE]);
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
if (load.total != last_load.total) {
|
|
||||||
curr_load->user = load.user - last_load.user;
|
|
||||||
curr_load->nice = load.nice - last_load.nice;
|
|
||||||
curr_load->system = load.system - last_load.system;
|
|
||||||
curr_load->idle = load.idle - last_load.idle;
|
|
||||||
curr_load->total = load.total - last_load.total;
|
|
||||||
last_ret_load = *curr_load;
|
|
||||||
last_load = load;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*curr_load = last_ret_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_loadavg(double *load)
|
|
||||||
{
|
|
||||||
double loadavg[LOADAVG_NSTATS];
|
|
||||||
|
|
||||||
if (getloadavg(loadavg, LOADAVG_NSTATS) <= LOADAVG_1MIN)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
*load = loadavg[LOADAVG_1MIN];
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_meminfo(meminfo_type * result)
|
|
||||||
{
|
|
||||||
int total_pages, free_pages;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
size = sizeof(int);
|
|
||||||
|
|
||||||
if (sysctlbyname("vm.stats.vm.v_page_count", &total_pages, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl vm.stats.vm.v_page_count");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sysctlbyname("vm.stats.vm.v_free_count", &free_pages, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl vm.stats.vm.v_free_count");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* memory */
|
|
||||||
result[0].total = pagetok(total_pages);
|
|
||||||
result[0].free = pagetok(free_pages);
|
|
||||||
|
|
||||||
/* unused anyway */
|
|
||||||
result[0].shared = 0;
|
|
||||||
result[0].buffers = 0;
|
|
||||||
result[0].cache = 0;
|
|
||||||
|
|
||||||
/* swap */
|
|
||||||
result[1].total = 0;
|
|
||||||
result[1].free = 0;
|
|
||||||
|
|
||||||
if (swapmode(&total_pages, &free_pages) != -1) {
|
|
||||||
result[1].total = total_pages;
|
|
||||||
result[1].free = free_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_procs(LinkedList * procs)
|
|
||||||
{
|
|
||||||
struct kinfo_proc *kprocs;
|
|
||||||
int nproc, i;
|
|
||||||
procinfo_type *p;
|
|
||||||
|
|
||||||
if (kvmd == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
kprocs = kvm_getprocs(kvmd, KERN_PROC_PROC, 0, &nproc);
|
|
||||||
if (kprocs == NULL) {
|
|
||||||
perror("kvm_getprocs");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nproc; i++) {
|
|
||||||
p = malloc(sizeof(procinfo_type));
|
|
||||||
if (!p) {
|
|
||||||
perror("mem_top_malloc");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
#if (__FreeBSD_version > 500000)
|
|
||||||
strncpy(p->name, kprocs->ki_comm, 15);
|
|
||||||
#else
|
|
||||||
strncpy(p->name, kprocs->kp_proc.p_comm, 15);
|
|
||||||
#endif
|
|
||||||
p->name[15] = '\0';
|
|
||||||
#if (__FreeBSD_version > 500000)
|
|
||||||
p->totl = kprocs->ki_size / 1024;
|
|
||||||
p->number = kprocs->ki_pid;
|
|
||||||
#else
|
|
||||||
p->totl = kprocs->kp_eproc.e_vm.vm_map.size / 1024;
|
|
||||||
p->number = kprocs->kp_proc.p_pid;
|
|
||||||
#endif
|
|
||||||
LL_Push(procs, (void *)p);
|
|
||||||
|
|
||||||
kprocs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_smpload(load_type * result, int *numcpus)
|
|
||||||
{
|
|
||||||
int i, num;
|
|
||||||
size_t size;
|
|
||||||
load_type load;
|
|
||||||
#ifdef HAVE_SYS_PCPU_H
|
|
||||||
static load_type last_load[MAX_CPUS];
|
|
||||||
struct pcpu *pcpudata;
|
|
||||||
|
|
||||||
if (kvmd == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (numcpus == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
size = sizeof(int);
|
|
||||||
if (sysctlbyname("hw.ncpu", &num, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl hw.ncpu");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* restrict #CPUs to max. *numcpus */
|
|
||||||
num = (*numcpus >= num) ? num : *numcpus;
|
|
||||||
*numcpus = num;
|
|
||||||
|
|
||||||
#ifndef HAVE_SYS_PCPU_H
|
|
||||||
if (machine_get_load(&load) == FALSE)
|
|
||||||
return (FALSE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
#ifdef HAVE_SYS_PCPU_H
|
|
||||||
pcpudata = kvm_getpcpu(kvmd, i);
|
|
||||||
|
|
||||||
if (pcpudata == NULL || pcpudata == (void *)-1)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
/* extract the data for single CPU */
|
|
||||||
load.user = (unsigned long)(pcpudata->pc_cp_time[CP_USER]);
|
|
||||||
load.nice = (unsigned long)(pcpudata->pc_cp_time[CP_NICE]);
|
|
||||||
load.system = (unsigned long)(pcpudata->pc_cp_time[CP_SYS] +
|
|
||||||
pcpudata->pc_cp_time[CP_INTR]);
|
|
||||||
load.idle = (unsigned long)(pcpudata->pc_cp_time[CP_IDLE]);
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
/* store difference in result */
|
|
||||||
result[i].user = load.user - last_load[i].user;
|
|
||||||
result[i].nice = load.nice - last_load[i].nice;
|
|
||||||
result[i].system = load.system - last_load[i].system;
|
|
||||||
result[i].idle = load.idle - last_load[i].idle;
|
|
||||||
result[i].total = load.total - last_load[i].total;
|
|
||||||
|
|
||||||
/* store current value for next round */
|
|
||||||
last_load[i].user = load.user;
|
|
||||||
last_load[i].nice = load.nice;
|
|
||||||
last_load[i].system = load.system;
|
|
||||||
last_load[i].idle = load.idle;
|
|
||||||
last_load[i].total = load.total;
|
|
||||||
|
|
||||||
/* free pcpu buffer */
|
|
||||||
free(pcpudata);
|
|
||||||
#else
|
|
||||||
result[i] = load;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_uptime(double *up, double *idle)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
time_t now;
|
|
||||||
struct timeval boottime;
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
size = sizeof(boottime);
|
|
||||||
time(&now);
|
|
||||||
if (sysctlbyname("kern.boottime", &boottime, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl kern.cp_time failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
*up = (double)(now - boottime.tv_sec);
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
*idle = 100.;
|
|
||||||
else
|
|
||||||
*idle = 100. * curr_load.idle / curr_load.total;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads info about swap space from system and returns it in parameters passed.
|
|
||||||
* \param retavail Total available swap space
|
|
||||||
* \param retfree Free swap space
|
|
||||||
* \return -1 on error, otherwise number of swap areas (typically 0 for total)
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
swapmode(int *retavail, int *retfree)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
struct kvm_swap swapary[1];
|
|
||||||
|
|
||||||
*retavail = 0;
|
|
||||||
*retfree = 0;
|
|
||||||
|
|
||||||
if (kvmd == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
n = kvm_getswapinfo(kvmd, swapary, 1, 0);
|
|
||||||
if (n < 0 || swapary[0].ksw_total == 0) {
|
|
||||||
/* strange */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*retavail = pagetok(swapary[0].ksw_total);
|
|
||||||
*retfree = pagetok(swapary[0].ksw_total - swapary[0].ksw_used);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_iface_stats(IfaceInfo * interface)
|
|
||||||
{
|
|
||||||
int rows;
|
|
||||||
int name[6] = {CTL_NET, PF_LINK, NETLINK_GENERIC, IFMIB_IFDATA, 0, IFDATA_GENERAL};
|
|
||||||
size_t len;
|
|
||||||
struct ifmibdata ifmd; /* ifmibdata contains the network statistics */
|
|
||||||
|
|
||||||
len = sizeof(rows);
|
|
||||||
/* get number of interfaces */
|
|
||||||
if (sysctlbyname("net.link.generic.system.ifcount", &rows, &len, NULL, 0) == 0) {
|
|
||||||
interface->status = down; /* set status down by default */
|
|
||||||
|
|
||||||
len = sizeof(ifmd);
|
|
||||||
/*
|
|
||||||
* walk through all interfaces in the ifmib table from last
|
|
||||||
* to first
|
|
||||||
*/
|
|
||||||
for (; rows > 0; rows--) {
|
|
||||||
name[4] = rows; /* set the interface index */
|
|
||||||
/* retrive the ifmibdata for the current index */
|
|
||||||
if (sysctl(name, 6, &ifmd, &len, NULL, 0) == -1) {
|
|
||||||
perror("read sysctl");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* check if its interface name matches */
|
|
||||||
if (strcmp(ifmd.ifmd_name, interface->name) == 0) {
|
|
||||||
|
|
||||||
interface->rc_byte = ifmd.ifmd_data.ifi_ibytes;
|
|
||||||
interface->tr_byte = ifmd.ifmd_data.ifi_obytes;
|
|
||||||
interface->rc_pkt = ifmd.ifmd_data.ifi_ipackets;
|
|
||||||
interface->tr_pkt = ifmd.ifmd_data.ifi_opackets;
|
|
||||||
|
|
||||||
if (interface->last_online == 0) {
|
|
||||||
interface->rc_byte_old = interface->rc_byte;
|
|
||||||
interface->tr_byte_old = interface->tr_byte;
|
|
||||||
interface->rc_pkt_old = interface->rc_pkt;
|
|
||||||
interface->tr_pkt_old = interface->tr_pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ifmd.ifmd_flags & IFF_UP) == IFF_UP) {
|
|
||||||
interface->status = up; /* is up */
|
|
||||||
interface->last_online = time(NULL); /* save actual time */
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* if we are here there is no interface with the given name */
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
perror("read sysctlbyname");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __FreeBSD__ */
|
|
||||||
@@ -1,631 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine_Linux.c
|
|
||||||
* Collects system information on Linux.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef linux
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/statvfs.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TIME_WITH_SYS_TIME
|
|
||||||
# include <sys/time.h>
|
|
||||||
# include <time.h>
|
|
||||||
#else
|
|
||||||
# if HAVE_SYS_TIME_H
|
|
||||||
# include <sys/time.h>
|
|
||||||
# else
|
|
||||||
# include <time.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_GETLOADAVG
|
|
||||||
# define USE_GETLOADAVG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_GETLOADAVG
|
|
||||||
# ifdef HAVE_SYS_LOADAVG_H
|
|
||||||
# include <sys/loadavg.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_PROCFS_H
|
|
||||||
# include <procfs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_PROCFS_H
|
|
||||||
# include <sys/procfs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int batt_fd;
|
|
||||||
static int load_fd;
|
|
||||||
static int loadavg_fd;
|
|
||||||
static int meminfo_fd;
|
|
||||||
static int uptime_fd;
|
|
||||||
|
|
||||||
static char procbuf[1024]; /* TODO ugly hack! */
|
|
||||||
|
|
||||||
static FILE *mtab_fd;
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_init(void)
|
|
||||||
{
|
|
||||||
uptime_fd = -1;
|
|
||||||
batt_fd = -1;
|
|
||||||
load_fd = -1;
|
|
||||||
loadavg_fd = -1;
|
|
||||||
meminfo_fd = -1;
|
|
||||||
|
|
||||||
if (uptime_fd < 0) {
|
|
||||||
uptime_fd = open("/proc/uptime", O_RDONLY);
|
|
||||||
if (uptime_fd < 0) {
|
|
||||||
perror("open /proc/uptime");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (load_fd < 0) {
|
|
||||||
load_fd = open("/proc/stat", O_RDONLY);
|
|
||||||
if (load_fd < 0) {
|
|
||||||
perror("open /proc/stat");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef USE_GETLOADAVG
|
|
||||||
if (loadavg_fd < 0) {
|
|
||||||
loadavg_fd = open("/proc/loadavg", O_RDONLY);
|
|
||||||
if (loadavg_fd < 0) {
|
|
||||||
perror("open /proc/loadavg");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (meminfo_fd < 0) {
|
|
||||||
meminfo_fd = open("/proc/meminfo", O_RDONLY);
|
|
||||||
if (meminfo_fd < 0) {
|
|
||||||
perror("open /proc/meminfo");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batt_fd < 0) {
|
|
||||||
batt_fd = open("/proc/apm", O_RDONLY);
|
|
||||||
if (batt_fd < 0) {
|
|
||||||
/* allow opening /proc/apm to fail */
|
|
||||||
batt_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_close(void)
|
|
||||||
{
|
|
||||||
if (batt_fd >= 0)
|
|
||||||
close(batt_fd);
|
|
||||||
batt_fd = -1;
|
|
||||||
|
|
||||||
if (load_fd >= 0)
|
|
||||||
close(load_fd);
|
|
||||||
load_fd = -1;
|
|
||||||
|
|
||||||
#ifndef USE_GETLOADAVG
|
|
||||||
if (loadavg_fd >= 0)
|
|
||||||
close(loadavg_fd);
|
|
||||||
loadavg_fd = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (meminfo_fd >= 0)
|
|
||||||
close(meminfo_fd);
|
|
||||||
meminfo_fd = -1;
|
|
||||||
|
|
||||||
if (uptime_fd >= 0)
|
|
||||||
close(uptime_fd);
|
|
||||||
uptime_fd = -1;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
reread(int f, char *errmsg)
|
|
||||||
{
|
|
||||||
if (lseek(f, 0L, 0) == 0 && read(f, procbuf, sizeof(procbuf) - 1) > 0)
|
|
||||||
return;
|
|
||||||
perror(errmsg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
getentry(const char *tag, const char *bufptr, long *value)
|
|
||||||
{
|
|
||||||
char *tail;
|
|
||||||
int len = strlen(tag);
|
|
||||||
long val;
|
|
||||||
|
|
||||||
while (bufptr != NULL) {
|
|
||||||
if (*bufptr == '\n')
|
|
||||||
bufptr++;
|
|
||||||
if (!strncmp(tag, bufptr, len)) {
|
|
||||||
errno = 0;
|
|
||||||
val = strtol(bufptr + len, &tail, 10);
|
|
||||||
if ((errno == 0) && (tail != bufptr + len)) {
|
|
||||||
*value = val;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
bufptr = strchr(bufptr, '\n');
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_battstat(int *acstat, int *battflag, int *percent)
|
|
||||||
{
|
|
||||||
char str[64];
|
|
||||||
int battstat;
|
|
||||||
|
|
||||||
/* no battery status available: fake one ;-) */
|
|
||||||
if (batt_fd < 0) {
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
*percent = 100;
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lseek(batt_fd, 0, 0) != 0)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if (read(batt_fd, str, sizeof(str) - 1) < 0)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if (3 > sscanf(str + 13, "0x%x 0x%x 0x%x %d", acstat, &battstat, battflag, percent))
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if (*battflag == 0xff)
|
|
||||||
*battflag = LCDP_BATT_UNKNOWN;
|
|
||||||
else {
|
|
||||||
if (*battflag & 1)
|
|
||||||
*battflag = LCDP_BATT_HIGH;
|
|
||||||
if (*battflag & 2)
|
|
||||||
*battflag = LCDP_BATT_LOW;
|
|
||||||
if (*battflag & 4)
|
|
||||||
*battflag = LCDP_BATT_CRITICAL;
|
|
||||||
if (*battflag & 8 || battstat == 3)
|
|
||||||
*battflag = LCDP_BATT_CHARGING;
|
|
||||||
if (*battflag & 128)
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (*acstat) {
|
|
||||||
case 0:
|
|
||||||
*acstat = LCDP_AC_OFF;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*acstat = LCDP_AC_BACKUP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*acstat = LCDP_AC_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_fs(mounts_type fs[], int *cnt)
|
|
||||||
{
|
|
||||||
#ifdef STAT_STATVFS
|
|
||||||
struct statvfs fsinfo;
|
|
||||||
#else
|
|
||||||
struct statfs fsinfo;
|
|
||||||
#endif
|
|
||||||
char line[256];
|
|
||||||
int x = 0, y;
|
|
||||||
|
|
||||||
#ifdef MTAB_FILE
|
|
||||||
mtab_fd = fopen(MTAB_FILE, "r");
|
|
||||||
#else
|
|
||||||
#error "Can't find your mounted filesystem table file."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get rid of old, unmounted filesystems... */
|
|
||||||
memset(fs, 0, sizeof(mounts_type) * 256);
|
|
||||||
|
|
||||||
while (x < 256) {
|
|
||||||
if (fgets(line, 256, mtab_fd) == NULL) {
|
|
||||||
fclose(mtab_fd);
|
|
||||||
*cnt = x;
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sscanf(line, "%s %s %s", fs[x].dev, fs[x].mpoint, fs[x].type);
|
|
||||||
|
|
||||||
if (strcmp(fs[x].type, "proc")
|
|
||||||
&& strcmp(fs[x].type, "tmpfs")
|
|
||||||
#ifndef STAT_NFS
|
|
||||||
&& strcmp(fs[x].type, "nfs")
|
|
||||||
#endif
|
|
||||||
#ifndef STAT_SMBFS
|
|
||||||
&& strcmp(fs[x].type, "smbfs")
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
#ifdef STAT_STATVFS
|
|
||||||
y = statvfs(fs[x].mpoint, &fsinfo);
|
|
||||||
#elif STAT_STATFS2_BSIZE
|
|
||||||
y = statfs(fs[x].mpoint, &fsinfo);
|
|
||||||
#elif STAT_STATFS4
|
|
||||||
y = statfs(fs[x].mpoint, &fsinfo, sizeof(fsinfo), 0);
|
|
||||||
#else
|
|
||||||
#error "statfs for this system not yet supported"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fs[x].blocks = fsinfo.f_blocks;
|
|
||||||
if (fs[x].blocks > 0) {
|
|
||||||
fs[x].bsize = fsinfo.f_bsize;
|
|
||||||
fs[x].bfree = fsinfo.f_bfree;
|
|
||||||
fs[x].files = fsinfo.f_files;
|
|
||||||
fs[x].ffree = fsinfo.f_ffree;
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(mtab_fd);
|
|
||||||
*cnt = x;
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_load(load_type * curr_load)
|
|
||||||
{
|
|
||||||
static load_type last_load = {0, 0, 0, 0, 0};
|
|
||||||
load_type load;
|
|
||||||
int ret;
|
|
||||||
unsigned long load_iowait, load_irq, load_softirq;
|
|
||||||
|
|
||||||
reread(load_fd, "get_load");
|
|
||||||
|
|
||||||
ret = sscanf(procbuf, "cpu %lu %lu %lu %lu %lu %lu %lu",
|
|
||||||
&load.user, &load.nice, &load.system, &load.idle,
|
|
||||||
&load_iowait, &load_irq, &load_softirq);
|
|
||||||
|
|
||||||
if (ret >= 5)
|
|
||||||
load.idle += load_iowait;
|
|
||||||
if (ret >= 6)
|
|
||||||
load.system += load_irq;
|
|
||||||
if (ret >= 7)
|
|
||||||
load.system += load_softirq;
|
|
||||||
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
curr_load->user = load.user - last_load.user;
|
|
||||||
curr_load->nice = load.nice - last_load.nice;
|
|
||||||
curr_load->system = load.system - last_load.system;
|
|
||||||
curr_load->idle = load.idle - last_load.idle;
|
|
||||||
curr_load->total = load.total - last_load.total;
|
|
||||||
|
|
||||||
/* struct assignment is legal in C89 */
|
|
||||||
last_load = load;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_loadavg(double *load)
|
|
||||||
{
|
|
||||||
#ifdef USE_GETLOADAVG
|
|
||||||
double loadavg[LOADAVG_NSTATS];
|
|
||||||
|
|
||||||
if (getloadavg(loadavg, LOADAVG_NSTATS) <= LOADAVG_1MIN) {
|
|
||||||
perror("getloadavg"); /* ToDo: correct error reporting */
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
*load = loadavg[LOADAVG_1MIN];
|
|
||||||
#else
|
|
||||||
reread(loadavg_fd, "get_loadavg");
|
|
||||||
sscanf(procbuf, "%lf", load);
|
|
||||||
#endif
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_meminfo(meminfo_type * result)
|
|
||||||
{
|
|
||||||
long tmp;
|
|
||||||
|
|
||||||
reread(meminfo_fd, "get_meminfo");
|
|
||||||
result[0].total = (getentry("MemTotal:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
result[0].free = (getentry("MemFree:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
result[0].shared = (getentry("MemShared:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
result[0].buffers = (getentry("Buffers:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
result[0].cache = (getentry("Cached:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
result[1].total = (getentry("SwapTotal:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
result[1].free = (getentry("SwapFree:", procbuf, &tmp) == TRUE) ? tmp : 0L;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_procs(LinkedList * procs)
|
|
||||||
{
|
|
||||||
/* Much of this code was ripped from "gmemusage" */
|
|
||||||
DIR *proc;
|
|
||||||
FILE *StatusFile;
|
|
||||||
struct dirent *procdir;
|
|
||||||
|
|
||||||
char procName[16];
|
|
||||||
int procSize, procRSS, procData, procStk, procExe;
|
|
||||||
const char
|
|
||||||
*NameLine = "Name:",
|
|
||||||
*VmSizeLine = "VmSize:",
|
|
||||||
*VmRSSLine = "VmRSS",
|
|
||||||
*VmDataLine = "VmData",
|
|
||||||
*VmStkLine = "VmStk",
|
|
||||||
*VmExeLine = "VmExe";
|
|
||||||
const int
|
|
||||||
NameLineLen = strlen(NameLine),
|
|
||||||
VmSizeLineLen = strlen(VmSizeLine),
|
|
||||||
VmDataLineLen = strlen(VmDataLine),
|
|
||||||
VmStkLineLen = strlen(VmStkLine),
|
|
||||||
VmExeLineLen = strlen(VmExeLine),
|
|
||||||
VmRSSLineLen = strlen(VmRSSLine);
|
|
||||||
int threshold = 400, unique;
|
|
||||||
|
|
||||||
if ((proc = opendir("/proc")) == NULL) {
|
|
||||||
/* ToDo: correct error reporting */
|
|
||||||
perror("mem_top_screen: unable to open /proc");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((procdir = readdir(proc))) {
|
|
||||||
char buf[128];
|
|
||||||
|
|
||||||
/* ignore everything in proc except process ids */
|
|
||||||
if (!strchr("1234567890", procdir->d_name[0]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sprintf(buf, "/proc/%s/status", procdir->d_name);
|
|
||||||
if ((StatusFile = fopen(buf, "r")) == NULL) {
|
|
||||||
/*
|
|
||||||
* Not a serious error; process has finished before
|
|
||||||
* we could examine it:
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
procRSS = procSize = procData = procStk = procExe = 0;
|
|
||||||
while (fgets(buf, sizeof(buf), StatusFile)) {
|
|
||||||
if (!strncmp(buf, NameLine, NameLineLen)) {
|
|
||||||
/* Name: procName */
|
|
||||||
sscanf(buf, "%*s %s", procName);
|
|
||||||
}
|
|
||||||
else if (!strncmp(buf, VmSizeLine, VmSizeLineLen)) {
|
|
||||||
/* VmSize: procSize kB */
|
|
||||||
sscanf(buf, "%*s %d", &procSize);
|
|
||||||
}
|
|
||||||
else if (!strncmp(buf, VmRSSLine, VmRSSLineLen)) {
|
|
||||||
/* VmRSS: procRSS kB */
|
|
||||||
sscanf(buf, "%*s %d", &procRSS);
|
|
||||||
}
|
|
||||||
else if (!strncmp(buf, VmDataLine, VmDataLineLen)) {
|
|
||||||
/* VmData: procData kB */
|
|
||||||
sscanf(buf, "%*s %d", &procData);
|
|
||||||
}
|
|
||||||
else if (!strncmp(buf, VmStkLine, VmStkLineLen)) {
|
|
||||||
/* VmStk: procStk kB */
|
|
||||||
sscanf(buf, "%*s %d", &procStk);
|
|
||||||
}
|
|
||||||
else if (!strncmp(buf, VmExeLine, VmExeLineLen)) {
|
|
||||||
/* VmExe: procExe kB */
|
|
||||||
sscanf(buf, "%*s %d", &procExe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(StatusFile);
|
|
||||||
|
|
||||||
if (procSize > threshold) {
|
|
||||||
/* Figure out if it's sharing any memory... */
|
|
||||||
unique = 1;
|
|
||||||
LL_Rewind(procs);
|
|
||||||
do {
|
|
||||||
procinfo_type *p = LL_Get(procs);
|
|
||||||
|
|
||||||
if ((p != NULL) && (0 == strcmp(p->name, procName))) {
|
|
||||||
unique = 0;
|
|
||||||
p->number++;
|
|
||||||
p->totl += procData + procStk + procExe;
|
|
||||||
}
|
|
||||||
} while (LL_Next(procs) == 0);
|
|
||||||
|
|
||||||
/* If this is the first one by this name... */
|
|
||||||
if (unique) {
|
|
||||||
procinfo_type *p = malloc(sizeof(procinfo_type));
|
|
||||||
if (p == NULL) {
|
|
||||||
perror("mem_top_screen: Error allocating process entry");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
strcpy(p->name, procName);
|
|
||||||
p->totl = procData + procStk + procExe;
|
|
||||||
p->number = 1;
|
|
||||||
/* TODO: Check for errors here? */
|
|
||||||
LL_Push(procs, (void *)p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(proc);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_smpload(load_type * result, int *numcpus)
|
|
||||||
{
|
|
||||||
char *token;
|
|
||||||
static load_type last_load[MAX_CPUS];
|
|
||||||
load_type curr_load[MAX_CPUS];
|
|
||||||
int ncpu = 0;
|
|
||||||
int ret;
|
|
||||||
unsigned long load_iowait, load_irq, load_softirq;
|
|
||||||
|
|
||||||
reread(load_fd, "get_load");
|
|
||||||
|
|
||||||
/* Look for lines starting with "cpu0", "cpu1", etc. */
|
|
||||||
token = strtok(procbuf, "\n");
|
|
||||||
while (token != NULL) {
|
|
||||||
if ((strlen(token) > 3) && (!strncmp(token, "cpu", 3)) && isdigit(token[3])) {
|
|
||||||
ret = sscanf(token, "cpu%*d %lu %lu %lu %lu %lu %lu %lu",
|
|
||||||
&curr_load[ncpu].user, &curr_load[ncpu].nice, &curr_load[ncpu].system,
|
|
||||||
&curr_load[ncpu].idle, &load_iowait, &load_irq, &load_softirq);
|
|
||||||
|
|
||||||
if (ret >= 5)
|
|
||||||
curr_load[ncpu].idle += load_iowait;
|
|
||||||
if (ret >= 6)
|
|
||||||
curr_load[ncpu].system += load_irq;
|
|
||||||
if (ret >= 7)
|
|
||||||
curr_load[ncpu].system += load_softirq;
|
|
||||||
|
|
||||||
curr_load[ncpu].total = curr_load[ncpu].user + curr_load[ncpu].nice +
|
|
||||||
curr_load[ncpu].system + curr_load[ncpu].idle;
|
|
||||||
|
|
||||||
result[ncpu].total = curr_load[ncpu].total - last_load[ncpu].total;
|
|
||||||
result[ncpu].user = curr_load[ncpu].user - last_load[ncpu].user;
|
|
||||||
result[ncpu].nice = curr_load[ncpu].nice - last_load[ncpu].nice;
|
|
||||||
result[ncpu].system = curr_load[ncpu].system - last_load[ncpu].system;
|
|
||||||
result[ncpu].idle = curr_load[ncpu].idle - last_load[ncpu].idle;
|
|
||||||
|
|
||||||
/* struct assignment is legal in C89 */
|
|
||||||
last_load[ncpu] = curr_load[ncpu];
|
|
||||||
|
|
||||||
/* restrict # CPUs to min(*numcpus, MAX_CPUS) */
|
|
||||||
ncpu++;
|
|
||||||
if ((ncpu >= *numcpus) || (ncpu >= MAX_CPUS))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = strtok(NULL, "\n");
|
|
||||||
}
|
|
||||||
*numcpus = ncpu;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_uptime(double *up, double *idle)
|
|
||||||
{
|
|
||||||
double local_up, local_idle;
|
|
||||||
|
|
||||||
reread(uptime_fd, "get_uptime");
|
|
||||||
sscanf(procbuf, "%lf %lf", &local_up, &local_idle);
|
|
||||||
if (up != NULL)
|
|
||||||
*up = local_up;
|
|
||||||
if (idle != NULL)
|
|
||||||
*idle = (local_up != 0)
|
|
||||||
? 100 * local_idle / local_up
|
|
||||||
: 100;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_iface_stats(IfaceInfo * interface)
|
|
||||||
{
|
|
||||||
FILE *file; /* file handler */
|
|
||||||
char buffer[1024]; /* buffer to work with the file */
|
|
||||||
static int first_time = 1; /* is it first time we call this
|
|
||||||
* function? */
|
|
||||||
char *ch_pointer = NULL;/* pointer to where interface values are in
|
|
||||||
* file */
|
|
||||||
|
|
||||||
/* Open the file in read-only mode and parse */
|
|
||||||
if ((file = fopen("/proc/net/dev", "r")) != NULL) {
|
|
||||||
/* Skip first 2 header lines of file */
|
|
||||||
fgets(buffer, sizeof(buffer), file);
|
|
||||||
fgets(buffer, sizeof(buffer), file);
|
|
||||||
|
|
||||||
/* By default, treat interface as down */
|
|
||||||
interface->status = down;
|
|
||||||
|
|
||||||
/* Search iface_name and scan values */
|
|
||||||
while ((fgets(buffer, sizeof(buffer), file) != NULL)) {
|
|
||||||
if (strstr(buffer, interface->name)) {
|
|
||||||
/* interface exists */
|
|
||||||
interface->status = up; /* is up */
|
|
||||||
interface->last_online = time(NULL); /* save actual time */
|
|
||||||
|
|
||||||
/* search ':' and skip over it */
|
|
||||||
ch_pointer = strchr(buffer, ':');
|
|
||||||
ch_pointer++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now ch_pointer points to values of
|
|
||||||
* iface_name
|
|
||||||
*/
|
|
||||||
/* Scan values from here */
|
|
||||||
sscanf(ch_pointer, "%lf %lf %*s %*s %*s %*s %*s %*s %lf %lf",
|
|
||||||
&interface->rc_byte,
|
|
||||||
&interface->rc_pkt,
|
|
||||||
&interface->tr_byte,
|
|
||||||
&interface->tr_pkt);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if is the first time we call this
|
|
||||||
* function, old values are the same as new
|
|
||||||
* so we don't get big speeds when
|
|
||||||
* calculating
|
|
||||||
*/
|
|
||||||
if (first_time) {
|
|
||||||
interface->rc_byte_old = interface->rc_byte;
|
|
||||||
interface->tr_byte_old = interface->tr_byte;
|
|
||||||
interface->rc_pkt_old = interface->rc_pkt;
|
|
||||||
interface->tr_pkt_old = interface->tr_pkt;
|
|
||||||
first_time = 0; /* now it isn't first
|
|
||||||
* time */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(file);
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
else { /* error when opening the file */
|
|
||||||
perror("Error: Could not open DEVFILE");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* linux */
|
|
||||||
@@ -1,427 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine_NetBSD.c
|
|
||||||
* Collects system information on NetBSD.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003 Thomas Runge (coto@core.de)
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this
|
|
||||||
* software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __NetBSD__
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/fcntl.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/dkstat.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <uvm/uvm_extern.h>
|
|
||||||
#include <machine/apmvar.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <ifaddrs.h>
|
|
||||||
|
|
||||||
#if (__NetBSD_Version__ >= 300000000)
|
|
||||||
# include <sys/statvfs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "machine.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
static int pageshift;
|
|
||||||
#define pagetok(size) ((size) << pageshift)
|
|
||||||
#define PROCSIZE(pp) ((pp)->p_vm_tsize + (pp)->p_vm_dsize + (pp)->p_vm_ssize)
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_init(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* get the page size with "getpagesize" and calculate pageshift from
|
|
||||||
* it
|
|
||||||
*/
|
|
||||||
int pagesize = getpagesize();
|
|
||||||
pageshift = 0;
|
|
||||||
while (pagesize > 1) {
|
|
||||||
pageshift++;
|
|
||||||
pagesize >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we only need the amount of log(2)1024 for our conversion */
|
|
||||||
pageshift -= 10;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_close(void)
|
|
||||||
{
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_battstat(int *acstat, int *battflag, int *percent)
|
|
||||||
{
|
|
||||||
int apmd;
|
|
||||||
struct apm_power_info apmi;
|
|
||||||
|
|
||||||
if ((apmd = open("/dev/apm", O_RDONLY)) == -1) {
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
*percent = 100;
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&apmi, 0, sizeof(apmi));
|
|
||||||
if (ioctl(apmd, APM_IOC_GETPOWER, &apmi) == -1) {
|
|
||||||
perror("APM_IOC_GETPOWER failed in get_batt_stat()");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (apmi.ac_state) {
|
|
||||||
case APM_AC_OFF:
|
|
||||||
*acstat = LCDP_AC_OFF;
|
|
||||||
break;
|
|
||||||
case APM_AC_ON:
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
break;
|
|
||||||
case APM_AC_BACKUP:
|
|
||||||
*acstat = LCDP_AC_BACKUP;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*acstat = LCDP_AC_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*battflag = apmi.battery_state;
|
|
||||||
*percent = apmi.battery_life;
|
|
||||||
|
|
||||||
close(apmd);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_fs(mounts_type fs[], int *cnt)
|
|
||||||
{
|
|
||||||
#if (__NetBSD_Version__ >= 300000000)
|
|
||||||
struct statvfs *mntbuf;
|
|
||||||
struct statvfs *pp;
|
|
||||||
#else
|
|
||||||
struct statfs *mntbuf;
|
|
||||||
struct statfs *pp;
|
|
||||||
#endif
|
|
||||||
int statcnt, fscnt, i;
|
|
||||||
|
|
||||||
fscnt = getmntinfo(&mntbuf, MNT_WAIT);
|
|
||||||
if (fscnt == 0) {
|
|
||||||
perror("getmntinfo");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
for (statcnt = 0, pp = mntbuf, i = 0; i < fscnt; pp++, i++) {
|
|
||||||
if (strcmp(pp->f_fstypename, "procfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "kernfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "linprocfs")
|
|
||||||
#ifndef STAT_NFS
|
|
||||||
&& strcmp(pp->f_fstypename, "nfs")
|
|
||||||
#endif
|
|
||||||
#ifndef STAT_SMBFS
|
|
||||||
&& strcmp(pp->f_fstypename, "smbfs")
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
snprintf(fs[statcnt].dev, 255, "%s", pp->f_mntfromname);
|
|
||||||
snprintf(fs[statcnt].mpoint, 255, "%s", pp->f_mntonname);
|
|
||||||
snprintf(fs[statcnt].type, 63, "%s", pp->f_fstypename);
|
|
||||||
|
|
||||||
fs[statcnt].blocks = pp->f_blocks;
|
|
||||||
if (fs[statcnt].blocks > 0) {
|
|
||||||
fs[statcnt].bsize = pp->f_bsize;
|
|
||||||
fs[statcnt].bfree = pp->f_bfree;
|
|
||||||
fs[statcnt].files = pp->f_files;
|
|
||||||
fs[statcnt].ffree = pp->f_ffree;
|
|
||||||
}
|
|
||||||
statcnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*cnt = statcnt;
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_load(load_type * curr_load)
|
|
||||||
{
|
|
||||||
static load_type last_load = {0, 0, 0, 0, 0};
|
|
||||||
static load_type last_ret_load;
|
|
||||||
load_type load;
|
|
||||||
u_int64_t cp_time[CPUSTATES];
|
|
||||||
size_t size;
|
|
||||||
int mib[2];
|
|
||||||
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_CP_TIME;
|
|
||||||
size = sizeof(cp_time);
|
|
||||||
if (sysctl(mib, 2, cp_time, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl kern.cp_time failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
load.user = (unsigned long)(cp_time[CP_USER]);
|
|
||||||
load.nice = (unsigned long)(cp_time[CP_NICE]);
|
|
||||||
load.system = (unsigned long)(cp_time[CP_SYS] + cp_time[CP_INTR]);
|
|
||||||
load.idle = (unsigned long)(cp_time[CP_IDLE]);
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
if (load.total != last_load.total) {
|
|
||||||
curr_load->user = load.user - last_load.user;
|
|
||||||
curr_load->nice = load.nice - last_load.nice;
|
|
||||||
curr_load->system = load.system - last_load.system;
|
|
||||||
curr_load->idle = load.idle - last_load.idle;
|
|
||||||
curr_load->total = load.total - last_load.total;
|
|
||||||
last_ret_load = *curr_load;
|
|
||||||
last_load = load;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*curr_load = last_ret_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_loadavg(double *load)
|
|
||||||
{
|
|
||||||
double loadavg[LOADAVG_NSTATS];
|
|
||||||
|
|
||||||
if (getloadavg(loadavg, LOADAVG_NSTATS) <= LOADAVG_1MIN)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
*load = loadavg[LOADAVG_1MIN];
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_meminfo(meminfo_type * result)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
int mib[2];
|
|
||||||
struct uvmexp_sysctl uvmexp;
|
|
||||||
|
|
||||||
mib[0] = CTL_VM;
|
|
||||||
mib[1] = VM_UVMEXP2;
|
|
||||||
size = sizeof(uvmexp);
|
|
||||||
if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl vm.uvmexp2 failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* memory */
|
|
||||||
result[0].total = pagetok(uvmexp.npages);
|
|
||||||
result[0].free = pagetok(uvmexp.free);
|
|
||||||
|
|
||||||
/* not really */
|
|
||||||
result[0].shared = pagetok(uvmexp.wired);
|
|
||||||
result[0].buffers = pagetok(uvmexp.execpages);
|
|
||||||
result[0].cache = pagetok(uvmexp.filepages);
|
|
||||||
|
|
||||||
/* swap */
|
|
||||||
result[1].total = pagetok(uvmexp.swpages);
|
|
||||||
result[1].free = pagetok(uvmexp.swpginuse);
|
|
||||||
result[1].free = result[1].total - result[1].free;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_procs(LinkedList * procs)
|
|
||||||
{
|
|
||||||
int nproc, i;
|
|
||||||
kvm_t *kvmd;
|
|
||||||
struct kinfo_proc2 *kprocs;
|
|
||||||
procinfo_type *p;
|
|
||||||
|
|
||||||
kprocs = NULL;
|
|
||||||
if ((kvmd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open")) == NULL) {
|
|
||||||
perror("kvm_openfiles");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
kprocs = kvm_getproc2(kvmd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &nproc);
|
|
||||||
if (kprocs == NULL) {
|
|
||||||
perror("kvm_getproc2");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nproc; i++) {
|
|
||||||
p = malloc(sizeof(procinfo_type));
|
|
||||||
if (!p) {
|
|
||||||
perror("mem_top_malloc");
|
|
||||||
kvm_close(kvmd);
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
strncpy(p->name, kprocs->p_comm, 15);
|
|
||||||
p->name[15] = '\0';
|
|
||||||
p->totl = pagetok(PROCSIZE(kprocs));
|
|
||||||
p->number = kprocs->p_pid;
|
|
||||||
LL_Push(procs, (void *)p);
|
|
||||||
|
|
||||||
kprocs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
kvm_close(kvmd);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_smpload(load_type * result, int *numcpus)
|
|
||||||
{
|
|
||||||
int mib[2], i, num;
|
|
||||||
size_t size;
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
mib[0] = CTL_HW;
|
|
||||||
mib[1] = HW_NCPU;
|
|
||||||
size = sizeof(int);
|
|
||||||
|
|
||||||
if (sysctl(mib, 2, &num, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl hw.ncpu");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if (numcpus == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
/* restrict #CPUs to max. *numcpus */
|
|
||||||
num = (*numcpus >= num) ? num : *numcpus;
|
|
||||||
*numcpus = num;
|
|
||||||
|
|
||||||
/* Don't know how to get per-cpu-load values */
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
result[i] = curr_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_uptime(double *up, double *idle)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
time_t now;
|
|
||||||
struct timeval boottime;
|
|
||||||
load_type curr_load;
|
|
||||||
int mib[2];
|
|
||||||
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_BOOTTIME;
|
|
||||||
size = sizeof(boottime);
|
|
||||||
time(&now);
|
|
||||||
if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl kern.boottime failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
*up = (double)(now - boottime.tv_sec);
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
*idle = 100.;
|
|
||||||
else
|
|
||||||
*idle = 100. * curr_load.idle / curr_load.total;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get network statistics */
|
|
||||||
int
|
|
||||||
machine_get_iface_stats(IfaceInfo * interface)
|
|
||||||
{
|
|
||||||
struct ifaddrs *ifa, *ifa_ptr;
|
|
||||||
struct if_data *ifd;
|
|
||||||
|
|
||||||
/* get first interface */
|
|
||||||
if (getifaddrs(&ifa) == -1)
|
|
||||||
perror("getifaddr failed");
|
|
||||||
|
|
||||||
/* loop through all interfaces */
|
|
||||||
for (ifa_ptr = ifa; ifa_ptr != NULL; ifa_ptr = ifa_ptr->ifa_next) {
|
|
||||||
interface->status = down; /* set status down by default */
|
|
||||||
|
|
||||||
/* check if we got the right interface and if it is Link type */
|
|
||||||
if ((strcmp(ifa_ptr->ifa_name, interface->name) == 0) &&
|
|
||||||
(ifa_ptr->ifa_addr->sa_family == AF_LINK)) {
|
|
||||||
|
|
||||||
ifd = (struct if_data *)ifa_ptr->ifa_data;
|
|
||||||
|
|
||||||
interface->rc_byte = ifd->ifi_ibytes;
|
|
||||||
interface->tr_byte = ifd->ifi_obytes;
|
|
||||||
interface->rc_pkt = ifd->ifi_ipackets;
|
|
||||||
interface->tr_pkt = ifd->ifi_opackets;
|
|
||||||
|
|
||||||
if (interface->last_online == 0) {
|
|
||||||
interface->rc_byte_old = interface->rc_byte;
|
|
||||||
interface->tr_byte_old = interface->tr_byte;
|
|
||||||
interface->rc_pkt_old = interface->rc_pkt;
|
|
||||||
interface->tr_pkt_old = interface->tr_pkt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ifa_ptr->ifa_flags & IFF_UP) == IFF_UP) {
|
|
||||||
interface->status = up; /* is up */
|
|
||||||
interface->last_online = time(NULL); /* save actual time */
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
freeifaddrs(ifa);
|
|
||||||
|
|
||||||
/* if we are here there is no interface with the given name */
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __NetBSD__ */
|
|
||||||
@@ -1,406 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine_OpenBSD.c
|
|
||||||
* Collects system information on OpenBSD.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003 Thomas Runge (coto@core.de)
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Neither the name of the author nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this
|
|
||||||
* software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
#include <sys/sched.h>
|
|
||||||
#include <sys/ucred.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
#include <machine/apmvar.h>
|
|
||||||
#include <kvm.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
static int pageshift;
|
|
||||||
#define pagetok(size) ((size) << pageshift)
|
|
||||||
#if OpenBSD >= 201111
|
|
||||||
#define PROCSIZE(pp) ((pp)->p_vm_tsize + (pp)->p_vm_dsize + (pp)->p_vm_ssize)
|
|
||||||
#else
|
|
||||||
#define PROCSIZE(pp) ((pp).vm_tsize + (pp).vm_dsize + (pp).vm_ssize)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_init(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* get the page size with "getpagesize" and calculate pageshift from
|
|
||||||
* it
|
|
||||||
*/
|
|
||||||
int pagesize = getpagesize();
|
|
||||||
pageshift = 0;
|
|
||||||
while (pagesize > 1) {
|
|
||||||
pageshift++;
|
|
||||||
pagesize >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we only need the amount of log(2)1024 for our conversion */
|
|
||||||
pageshift -= 10;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_close(void)
|
|
||||||
{
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_battstat(int *acstat, int *battflag, int *percent)
|
|
||||||
{
|
|
||||||
int apmd;
|
|
||||||
struct apm_power_info api;
|
|
||||||
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
*percent = 100;
|
|
||||||
|
|
||||||
if ((apmd = open("/dev/apm", O_RDONLY)) == -1) {
|
|
||||||
perror("get_battstat_open");
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(apmd, APM_IOC_GETPOWER, &api) == -1) {
|
|
||||||
perror("get_battstat_ioctl");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (api.ac_state) {
|
|
||||||
case APM_AC_OFF:
|
|
||||||
*acstat = LCDP_AC_OFF;
|
|
||||||
break;
|
|
||||||
case APM_AC_ON:
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*acstat = LCDP_AC_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (api.battery_state) {
|
|
||||||
case APM_BATT_HIGH:
|
|
||||||
*battflag = LCDP_BATT_HIGH;
|
|
||||||
break;
|
|
||||||
case APM_BATT_LOW:
|
|
||||||
*battflag = LCDP_BATT_LOW;
|
|
||||||
break;
|
|
||||||
case APM_BATT_CRITICAL:
|
|
||||||
*battflag = LCDP_BATT_CRITICAL;
|
|
||||||
break;
|
|
||||||
case APM_BATT_CHARGING:
|
|
||||||
*battflag = LCDP_BATT_CHARGING;
|
|
||||||
break;
|
|
||||||
case APM_BATTERY_ABSENT:
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*battflag = LCDP_BATT_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*percent = api.battery_life;
|
|
||||||
|
|
||||||
close(apmd);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_fs(mounts_type fs[], int *cnt)
|
|
||||||
{
|
|
||||||
struct statfs *mntbuf;
|
|
||||||
struct statfs *pp;
|
|
||||||
int statcnt, fscnt, i;
|
|
||||||
|
|
||||||
fscnt = getmntinfo(&mntbuf, MNT_WAIT);
|
|
||||||
if (fscnt == 0) {
|
|
||||||
perror("getmntinfo");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
for (statcnt = 0, pp = mntbuf, i = 0; i < fscnt; pp++, i++) {
|
|
||||||
if (strcmp(pp->f_fstypename, "procfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "kernfs")
|
|
||||||
&& strcmp(pp->f_fstypename, "linprocfs")
|
|
||||||
#ifndef STAT_NFS
|
|
||||||
&& strcmp(pp->f_fstypename, "nfs")
|
|
||||||
#endif
|
|
||||||
#ifndef STAT_SMBFS
|
|
||||||
&& strcmp(pp->f_fstypename, "smbfs")
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
snprintf(fs[statcnt].dev, 255, "%s", pp->f_mntfromname);
|
|
||||||
snprintf(fs[statcnt].mpoint, 255, "%s", pp->f_mntonname);
|
|
||||||
snprintf(fs[statcnt].type, 63, "%s", pp->f_fstypename);
|
|
||||||
|
|
||||||
fs[statcnt].blocks = pp->f_blocks;
|
|
||||||
if (fs[statcnt].blocks > 0) {
|
|
||||||
fs[statcnt].bsize = pp->f_bsize;
|
|
||||||
fs[statcnt].bfree = pp->f_bfree;
|
|
||||||
fs[statcnt].files = pp->f_files;
|
|
||||||
fs[statcnt].ffree = pp->f_ffree;
|
|
||||||
}
|
|
||||||
statcnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*cnt = statcnt;
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_load(load_type * curr_load)
|
|
||||||
{
|
|
||||||
static load_type last_load = {0, 0, 0, 0, 0};
|
|
||||||
static load_type last_ret_load;
|
|
||||||
load_type load;
|
|
||||||
long cp_time[CPUSTATES];
|
|
||||||
size_t size;
|
|
||||||
int mib[2];
|
|
||||||
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_CPTIME;
|
|
||||||
size = sizeof(cp_time);
|
|
||||||
if (sysctl(mib, 2, cp_time, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl kern.cp_time failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
load.user = (unsigned long)(cp_time[CP_USER]);
|
|
||||||
load.nice = (unsigned long)(cp_time[CP_NICE]);
|
|
||||||
load.system = (unsigned long)(cp_time[CP_SYS] + cp_time[CP_INTR]);
|
|
||||||
load.idle = (unsigned long)(cp_time[CP_IDLE]);
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
if (load.total != last_load.total) {
|
|
||||||
curr_load->user = load.user - last_load.user;
|
|
||||||
curr_load->nice = load.nice - last_load.nice;
|
|
||||||
curr_load->system = load.system - last_load.system;
|
|
||||||
curr_load->idle = load.idle - last_load.idle;
|
|
||||||
curr_load->total = load.total - last_load.total;
|
|
||||||
last_ret_load = *curr_load;
|
|
||||||
last_load = load;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*curr_load = last_ret_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_loadavg(double *load)
|
|
||||||
{
|
|
||||||
double loadavg[LOADAVG_NSTATS];
|
|
||||||
|
|
||||||
if (getloadavg(loadavg, LOADAVG_NSTATS) <= LOADAVG_1MIN)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
*load = loadavg[LOADAVG_1MIN];
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_meminfo(meminfo_type * result)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
int mib[2];
|
|
||||||
struct uvmexp suvm;
|
|
||||||
|
|
||||||
mib[0] = CTL_VM;
|
|
||||||
mib[1] = VM_UVMEXP;
|
|
||||||
size = sizeof(suvm);
|
|
||||||
|
|
||||||
if (sysctl(mib, 2, &suvm, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl vm.uvmexp failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* memory */
|
|
||||||
result[0].total = pagetok(suvm.npages);
|
|
||||||
result[0].free = pagetok(suvm.free);
|
|
||||||
|
|
||||||
/* not used anyway */
|
|
||||||
result[0].shared = 0;
|
|
||||||
result[0].buffers = 0;
|
|
||||||
result[0].cache = 0;
|
|
||||||
|
|
||||||
/* swap */
|
|
||||||
result[1].total = suvm.pagesize * suvm.swpages;
|
|
||||||
result[1].free = suvm.pagesize * suvm.swpginuse;
|
|
||||||
result[1].free = result[1].total - result[1].free;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_procs(LinkedList * procs)
|
|
||||||
{
|
|
||||||
struct kinfo_proc *kprocs;
|
|
||||||
int nproc, i;
|
|
||||||
procinfo_type *p;
|
|
||||||
kvm_t *kvmd;
|
|
||||||
|
|
||||||
if ((kvmd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) {
|
|
||||||
perror("kvm_open");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OpenBSD >= 201111
|
|
||||||
kprocs = kvm_getprocs(kvmd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &nproc);
|
|
||||||
#else
|
|
||||||
kprocs = kvm_getprocs(kvmd, KERN_PROC_ALL, 0, &nproc);
|
|
||||||
#endif
|
|
||||||
if (kprocs == NULL) {
|
|
||||||
perror("kvm_getprocs");
|
|
||||||
kvm_close(kvmd);
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nproc; i++) {
|
|
||||||
p = malloc(sizeof(procinfo_type));
|
|
||||||
if (!p) {
|
|
||||||
perror("mem_top_malloc");
|
|
||||||
kvm_close(kvmd);
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
#if OpenBSD >= 201111
|
|
||||||
strncpy(p->name, kprocs->p_comm, 15);
|
|
||||||
p->name[15] = '\0';
|
|
||||||
p->totl = pagetok(PROCSIZE(kprocs));
|
|
||||||
p->number = kprocs->p_pid;
|
|
||||||
#else
|
|
||||||
strncpy(p->name, kprocs->kp_proc.p_comm, 15);
|
|
||||||
p->name[15] = '\0';
|
|
||||||
p->totl = pagetok(PROCSIZE(kprocs->kp_eproc.e_vm));
|
|
||||||
p->number = kprocs->kp_proc.p_pid;
|
|
||||||
#endif
|
|
||||||
LL_Push(procs, (void *)p);
|
|
||||||
|
|
||||||
kprocs++;
|
|
||||||
}
|
|
||||||
kvm_close(kvmd);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_smpload(load_type * result, int *numcpus)
|
|
||||||
{
|
|
||||||
int mib[2], i, num;
|
|
||||||
size_t size;
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
mib[0] = CTL_HW;
|
|
||||||
mib[1] = HW_NCPU;
|
|
||||||
size = sizeof(int);
|
|
||||||
|
|
||||||
if (sysctl(mib, 2, &num, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl hw.ncpu");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if (numcpus == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
/* restrict #CPUs to max. *numcpus */
|
|
||||||
num = (*numcpus >= num) ? num : *numcpus;
|
|
||||||
*numcpus = num;
|
|
||||||
|
|
||||||
/* Don't know how to get per-cpu-load values */
|
|
||||||
for (i = 0; i < num; i++) {
|
|
||||||
result[i] = curr_load;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_uptime(double *up, double *idle)
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
time_t now;
|
|
||||||
struct timeval boottime;
|
|
||||||
int mib[2];
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_BOOTTIME;
|
|
||||||
size = sizeof(boottime);
|
|
||||||
time(&now);
|
|
||||||
if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
|
|
||||||
perror("sysctl kern.boottime failed");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
*up = (double)(now - boottime.tv_sec);
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
*idle = 100.;
|
|
||||||
else
|
|
||||||
*idle = 100. * curr_load.idle / curr_load.total;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get network statistics */
|
|
||||||
int
|
|
||||||
machine_get_iface_stats(IfaceInfo * interface)
|
|
||||||
{
|
|
||||||
/* Implementation missing */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __OpenBSD__ */
|
|
||||||
@@ -1,441 +0,0 @@
|
|||||||
/** \file clients/lcdproc/machine_SunOS.c
|
|
||||||
* Collects system information on Solaris.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef sun
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <utmpx.h>
|
|
||||||
#include <procfs.h>
|
|
||||||
#include <kstat.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/fcntl.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/loadavg.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/cpuvar.h>
|
|
||||||
#include <sys/swap.h>
|
|
||||||
#include <sys/statvfs.h>
|
|
||||||
|
|
||||||
#include "machine.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
|
|
||||||
static kstat_ctl_t *kc;
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_init(void)
|
|
||||||
{
|
|
||||||
kc = NULL;
|
|
||||||
|
|
||||||
kc = kstat_open();
|
|
||||||
if (kc == NULL) {
|
|
||||||
perror("kstat_open");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_close(void)
|
|
||||||
{
|
|
||||||
if (kc != NULL) {
|
|
||||||
kstat_close(kc);
|
|
||||||
kc = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_battstat(int *acstat, int *battflag, int *percent)
|
|
||||||
{
|
|
||||||
*acstat = LCDP_AC_ON;
|
|
||||||
*battflag = LCDP_BATT_ABSENT;
|
|
||||||
*percent = 100;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_fs(mounts_type fs[], int *cnt)
|
|
||||||
{
|
|
||||||
FILE *mtab_fd;
|
|
||||||
char line[256];
|
|
||||||
int x = 0, y;
|
|
||||||
|
|
||||||
#ifdef STAT_STATVFS
|
|
||||||
struct statvfs fsinfo;
|
|
||||||
#else
|
|
||||||
struct statfs fsinfo;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MTAB_FILE
|
|
||||||
mtab_fd = fopen(MTAB_FILE, "r");
|
|
||||||
#else
|
|
||||||
#error "Can't find your mounted filesystem table file."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get rid of old, unmounted filesystems... */
|
|
||||||
memset(fs, 0, sizeof(mounts_type) * 256);
|
|
||||||
|
|
||||||
while (x < 256) {
|
|
||||||
if (fgets(line, 256, mtab_fd) == NULL) {
|
|
||||||
fclose(mtab_fd);
|
|
||||||
*cnt = x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sscanf(line, "%s %s %s", fs[x].dev, fs[x].mpoint, fs[x].type);
|
|
||||||
|
|
||||||
if (strcmp(fs[x].type, "proc")
|
|
||||||
#ifndef STAT_NFS
|
|
||||||
&& strcmp(fs[x].type, "nfs")
|
|
||||||
#endif
|
|
||||||
#ifndef STAT_SMBFS
|
|
||||||
&& strcmp(fs[x].type, "smbfs")
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
#ifdef STAT_STATVFS
|
|
||||||
y = statvfs(fs[x].mpoint, &fsinfo);
|
|
||||||
#elif STAT_STATFS2_BSIZE
|
|
||||||
y = statfs(fs[x].mpoint, &fsinfo);
|
|
||||||
#elif STAT_STATFS4
|
|
||||||
y = statfs(fs[x].mpoint, &fsinfo, sizeof(fsinfo), 0);
|
|
||||||
#else
|
|
||||||
#error "statfs for this system noy yet supported"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fs[x].blocks = fsinfo.f_blocks;
|
|
||||||
if (fs[x].blocks > 0) {
|
|
||||||
fs[x].bsize = fsinfo.f_bsize;
|
|
||||||
fs[x].bfree = fsinfo.f_bfree;
|
|
||||||
fs[x].files = fsinfo.f_files;
|
|
||||||
fs[x].ffree = fsinfo.f_ffree;
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(mtab_fd);
|
|
||||||
*cnt = x;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_load(load_type * curr_load)
|
|
||||||
{
|
|
||||||
static load_type last_load = {0, 0, 0, 0, 0};
|
|
||||||
load_type load;
|
|
||||||
kstat_t *k_space;
|
|
||||||
struct cpu_stat cinfo;
|
|
||||||
|
|
||||||
k_space = kstat_lookup(kc, "cpu_stat", 0, "cpu_stat0");
|
|
||||||
if (k_space == NULL) {
|
|
||||||
fprintf(stderr, "kstat lookup error\n");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kstat_read(kc, k_space, NULL) == -1) {
|
|
||||||
fprintf(stderr, "kstat read error\n");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
k_space = kstat_lookup(kc, "cpu_stat", -1, "cpu_stat0");
|
|
||||||
if (k_space == NULL) {
|
|
||||||
fprintf(stderr, "kstat lookup error\n");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
if (kstat_read(kc, k_space, &cinfo) == -1) {
|
|
||||||
fprintf(stderr, "kstat read error\n");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
load.idle = cinfo.cpu_sysinfo.cpu[CPU_IDLE];
|
|
||||||
load.user = cinfo.cpu_sysinfo.cpu[CPU_USER];
|
|
||||||
load.system = cinfo.cpu_sysinfo.cpu[CPU_KERNEL];
|
|
||||||
load.nice = cinfo.cpu_sysinfo.cpu[CPU_WAIT];
|
|
||||||
load.total = load.user + load.nice + load.system + load.idle;
|
|
||||||
|
|
||||||
curr_load->user = load.user - last_load.user;
|
|
||||||
curr_load->nice = load.nice - last_load.nice;
|
|
||||||
curr_load->system = load.system - last_load.system;
|
|
||||||
curr_load->idle = load.idle - last_load.idle;
|
|
||||||
curr_load->total = load.total - last_load.total;
|
|
||||||
|
|
||||||
/* struct assingment is legal in C89 */
|
|
||||||
last_load = load;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_loadavg(double *load)
|
|
||||||
{
|
|
||||||
double loadavg[LOADAVG_NSTATS];
|
|
||||||
|
|
||||||
if (getloadavg(loadavg, LOADAVG_NSTATS) <= LOADAVG_1MIN)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
*load = loadavg[LOADAVG_1MIN];
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_meminfo(meminfo_type * result)
|
|
||||||
{
|
|
||||||
#define MAXSTRSIZE 80
|
|
||||||
swaptbl_t *s;
|
|
||||||
int i, n, num;
|
|
||||||
char *strtab; /* string table for path names */
|
|
||||||
|
|
||||||
s = NULL;
|
|
||||||
|
|
||||||
result[0].total = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / 1024;
|
|
||||||
result[0].free = sysconf(_SC_AVPHYS_PAGES) * sysconf(_SC_PAGESIZE) / 1024;
|
|
||||||
result[0].shared = 0;
|
|
||||||
result[0].buffers = 0;
|
|
||||||
result[0].cache = 0;
|
|
||||||
|
|
||||||
again:
|
|
||||||
if ((num = swapctl(SC_GETNSWP, 0)) == -1) {
|
|
||||||
perror("swapctl: GETNSWP");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num == 0) {
|
|
||||||
fprintf(stderr, "No Swap Devices Configured\n");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate swaptable for num+1 entries */
|
|
||||||
if ((s = (swaptbl_t *) malloc(num * sizeof(swapent_t) + sizeof(struct swaptable))) == NULL) {
|
|
||||||
perror("malloc swap");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate num+1 string holders */
|
|
||||||
if ((strtab = (char *)malloc((num + 1) * MAXSTRSIZE)) == NULL) {
|
|
||||||
perror("malloc string holder");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize string pointers */
|
|
||||||
for (i = 0; i < (num + 1); i++) {
|
|
||||||
s->swt_ent[i].ste_path = strtab + (i * MAXSTRSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
s->swt_n = num + 1;
|
|
||||||
if ((n = swapctl(SC_LIST, s)) < 0) {
|
|
||||||
perror("swapctl");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* more were added */
|
|
||||||
if (n > num) {
|
|
||||||
free(s);
|
|
||||||
free(strtab);
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
result[1].total = 0;
|
|
||||||
result[1].free = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
result[1].total = result[1].total + s->swt_ent[i].ste_pages * sysconf(_SC_PAGESIZE) / 1024;
|
|
||||||
result[1].free = result[1].free + s->swt_ent[i].ste_free * sysconf(_SC_PAGESIZE) / 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_procs(LinkedList * procs)
|
|
||||||
{
|
|
||||||
char buf[128];
|
|
||||||
DIR *proc;
|
|
||||||
FILE *StatusFile;
|
|
||||||
struct dirent *procdir;
|
|
||||||
procinfo_type *p;
|
|
||||||
|
|
||||||
char procName[16];
|
|
||||||
int procSize, procRSS, procData, procStk, procExe;
|
|
||||||
int threshold = 400, unique;
|
|
||||||
|
|
||||||
if ((proc = opendir("/proc")) == NULL) {
|
|
||||||
perror("open /proc");
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((procdir = readdir(proc))) {
|
|
||||||
psinfo_t psinfo;
|
|
||||||
|
|
||||||
if (!strchr("1234567890", procdir->d_name[0]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sprintf(buf, "/proc/%s/psinfo", procdir->d_name);
|
|
||||||
if ((StatusFile = fopen(buf, "r")) == NULL) {
|
|
||||||
/*
|
|
||||||
* Not a serious error; process has finished before
|
|
||||||
* we could examine it:
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
procRSS = procSize = procData = procStk = procExe = 0;
|
|
||||||
fread(&psinfo, sizeof(psinfo), 1, StatusFile);
|
|
||||||
strcpy(procName, psinfo.pr_fname);
|
|
||||||
procSize = psinfo.pr_size;
|
|
||||||
procRSS = psinfo.pr_rssize;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Following values not accurate, not sure what needs to be
|
|
||||||
* set to
|
|
||||||
*/
|
|
||||||
procData = psinfo.pr_size;
|
|
||||||
procStk = 0;
|
|
||||||
procExe = 0;
|
|
||||||
|
|
||||||
fclose(StatusFile);
|
|
||||||
|
|
||||||
if (procSize > threshold) {
|
|
||||||
/* Figure out if it's sharing any memory... */
|
|
||||||
unique = 1;
|
|
||||||
LL_Rewind(procs);
|
|
||||||
do {
|
|
||||||
p = LL_Get(procs);
|
|
||||||
if (p) {
|
|
||||||
if (0 == strcmp(p->name, procName)) {
|
|
||||||
unique = 0;
|
|
||||||
p->number++;
|
|
||||||
p->totl += procData + procStk + procExe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (LL_Next(procs) == 0);
|
|
||||||
|
|
||||||
/* If this is the first one by this name... */
|
|
||||||
if (unique) {
|
|
||||||
p = malloc(sizeof(procinfo_type));
|
|
||||||
if (p == NULL) {
|
|
||||||
perror("allocating process entry");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
strcpy(p->name, procName);
|
|
||||||
p->totl = procData + procStk + procExe;
|
|
||||||
p->number = 1;
|
|
||||||
/* TODO: Check for errors here? */
|
|
||||||
LL_Push(procs, (void *)p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end:
|
|
||||||
closedir(proc);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
machine_get_smpload(load_type * result, int *numcpus)
|
|
||||||
{
|
|
||||||
static load_type last_load[MAX_CPUS];
|
|
||||||
load_type curr_load[MAX_CPUS];
|
|
||||||
int ncpu = 0;
|
|
||||||
int max_cpu, count;
|
|
||||||
|
|
||||||
max_cpu = sysconf(_SC_NPROCESSORS_CONF);
|
|
||||||
for (count = 0; count < max_cpu; count++) {
|
|
||||||
kstat_t *k_space;
|
|
||||||
char buffer[16];
|
|
||||||
|
|
||||||
sprintf(buffer, "cpu_stat%d", count);
|
|
||||||
|
|
||||||
k_space = kstat_lookup(kc, "cpu_stat", count, buffer);
|
|
||||||
|
|
||||||
if ((k_space != NULL) && (kstat_read(kc, k_space, NULL) != -1)) {
|
|
||||||
struct cpu_stat cinfo;
|
|
||||||
|
|
||||||
k_space = kstat_lookup(kc, "cpu_stat", -1, buffer);
|
|
||||||
kstat_read(kc, k_space, &cinfo);
|
|
||||||
|
|
||||||
curr_load[ncpu].idle = cinfo.cpu_sysinfo.cpu[CPU_IDLE];
|
|
||||||
curr_load[ncpu].user = cinfo.cpu_sysinfo.cpu[CPU_USER];
|
|
||||||
curr_load[ncpu].system = cinfo.cpu_sysinfo.cpu[CPU_KERNEL];
|
|
||||||
curr_load[ncpu].nice = cinfo.cpu_sysinfo.cpu[CPU_WAIT];
|
|
||||||
curr_load[ncpu].total = curr_load[ncpu].user + curr_load[ncpu].nice +
|
|
||||||
curr_load[ncpu].system + curr_load[ncpu].idle;
|
|
||||||
|
|
||||||
result[ncpu].total = curr_load[ncpu].total - last_load[ncpu].total;
|
|
||||||
result[ncpu].user = curr_load[ncpu].user - last_load[ncpu].user;
|
|
||||||
result[ncpu].nice = curr_load[ncpu].nice - last_load[ncpu].nice;
|
|
||||||
result[ncpu].system = curr_load[ncpu].system - last_load[ncpu].system;
|
|
||||||
result[ncpu].idle = curr_load[ncpu].idle - last_load[ncpu].idle;
|
|
||||||
|
|
||||||
/* struct assignment is legal in C89 */
|
|
||||||
last_load[ncpu] = curr_load[ncpu];
|
|
||||||
|
|
||||||
/* restrict # CPUs to min(*numcpus, MAX_CPUS) */
|
|
||||||
ncpu++;
|
|
||||||
if ((ncpu >= *numcpus) || (ncpu >= MAX_CPUS))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*numcpus = ncpu;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO get idle time! */
|
|
||||||
int
|
|
||||||
machine_get_uptime(double *up, double *idle)
|
|
||||||
{
|
|
||||||
struct utmpx *u, id;
|
|
||||||
load_type curr_load;
|
|
||||||
|
|
||||||
*up = 0;
|
|
||||||
*idle = 0;
|
|
||||||
|
|
||||||
id.ut_type = BOOT_TIME;
|
|
||||||
|
|
||||||
u = getutxid(&id);
|
|
||||||
if (u == NULL)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
*up = time(0) - u->ut_xtime;
|
|
||||||
|
|
||||||
if (machine_get_load(&curr_load) == FALSE)
|
|
||||||
*idle = 100.;
|
|
||||||
else
|
|
||||||
*idle = 100. * curr_load.idle / curr_load.total;
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get network statistics */
|
|
||||||
int
|
|
||||||
machine_get_iface_stats(IfaceInfo * interface)
|
|
||||||
{
|
|
||||||
/* Implementation missing */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* sun */
|
|
||||||
@@ -1,709 +0,0 @@
|
|||||||
/** \file clients/lcdproc/main.c
|
|
||||||
* Contains main(), plus signal callback functions and a help screen.
|
|
||||||
*
|
|
||||||
* Program init, command-line handling, and the main loop are
|
|
||||||
* implemented here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "getopt.h" /* This is our local getopt.h! */
|
|
||||||
|
|
||||||
/* Import screens */
|
|
||||||
#include "batt.h"
|
|
||||||
#include "chrono.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "cpu_smp.h"
|
|
||||||
#include "disk.h"
|
|
||||||
#include "load.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "iface.h"
|
|
||||||
#ifdef LCDPROC_EYEBOXONE
|
|
||||||
# include "eyebox.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The following 8 variables are defined 'external' in main.h! */
|
|
||||||
int Quit = 0;
|
|
||||||
int sock = -1;
|
|
||||||
|
|
||||||
char *version = VERSION;
|
|
||||||
char *build_date = __DATE__;
|
|
||||||
|
|
||||||
int lcd_wid = 0;
|
|
||||||
int lcd_hgt = 0;
|
|
||||||
int lcd_cellwid = 0;
|
|
||||||
int lcd_cellhgt = 0;
|
|
||||||
|
|
||||||
static struct utsname unamebuf;
|
|
||||||
|
|
||||||
/* local prototypes */
|
|
||||||
static void HelpScreen(int exit_state);
|
|
||||||
static void exit_program(int val);
|
|
||||||
static void main_loop(void);
|
|
||||||
static int process_configfile(char *cfgfile);
|
|
||||||
|
|
||||||
|
|
||||||
#define TIME_UNIT 125000 /**< 1/8th second is a single time unit. */
|
|
||||||
|
|
||||||
#if !defined(SYSCONFDIR)
|
|
||||||
# define SYSCONFDIR "/etc"
|
|
||||||
#endif
|
|
||||||
#if !defined(PIDFILEDIR)
|
|
||||||
# define PIDFILEDIR "/var/run"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define UNSET_INT -1
|
|
||||||
#define UNSET_STR "\01"
|
|
||||||
#define DEFAULT_SERVER "127.0.0.1"
|
|
||||||
#define DEFAULT_CONFIGFILE SYSCONFDIR "/lcdproc.conf"
|
|
||||||
#define DEFAULT_PIDFILE PIDFILEDIR "/lcdproc.pid"
|
|
||||||
#define DEFAULT_REPORTDEST RPT_DEST_STDERR
|
|
||||||
#define DEFAULT_REPORTLEVEL RPT_WARNING
|
|
||||||
|
|
||||||
/** list of screen modes to run */
|
|
||||||
ScreenMode sequence[] =
|
|
||||||
{
|
|
||||||
/* flags default ACTIVE will run by default */
|
|
||||||
/* longname which on off inv timer flags */
|
|
||||||
{ "CPU", 'C', 1, 2, 0, 0xffff, ACTIVE, cpu_screen }, // [C]PU
|
|
||||||
{ "Iface", 'I', 1, 2, 0, 0xffff, 0, iface_screen }, // [I]face
|
|
||||||
{ "Memory", 'M', 4, 16, 0, 0xffff, ACTIVE, mem_screen }, // [M]emory
|
|
||||||
{ "Load", 'L', 64, 128, 1, 0xffff, ACTIVE, xload_screen }, // [L]oad (load histogram)
|
|
||||||
{ "TimeDate", 'T', 4, 64, 0, 0xffff, ACTIVE, time_screen }, // [T]ime/Date
|
|
||||||
{ "About", 'A', 999, 9999, 0, 0xffff, ACTIVE, credit_screen }, // [A]bout (credits)
|
|
||||||
{ "SMP-CPU", 'P', 1, 2, 0, 0xffff, 0, cpu_smp_screen }, // CPU_SM[P]
|
|
||||||
{ "OldTime", 'O', 4, 64, 0, 0xffff, 0, clock_screen }, // [O]ld Timescreen
|
|
||||||
{ "BigClock", 'K', 4, 64, 0, 0xffff, 0, big_clock_screen }, // big cloc[K]
|
|
||||||
{ "Uptime", 'U', 4, 128, 0, 0xffff, 0, uptime_screen }, // Old [U]ptime Screen
|
|
||||||
{ "Battery", 'B', 32, 256, 1, 0xffff, 0, battery_screen }, // [B]attery Status
|
|
||||||
{ "CPUGraph", 'G', 1, 2, 0, 0xffff, 0, cpu_graph_screen }, // CPU histogram [G]raph
|
|
||||||
{ "ProcSize", 'S', 16, 256, 1, 0xffff, 0, mem_top_screen }, // [S]ize of biggest processes
|
|
||||||
{ "Disk", 'D', 256, 256, 1, 0xffff, 0, disk_screen }, // [D]isk stats
|
|
||||||
{ "MiniClock", 'N', 4, 64, 0, 0xffff, 0, mini_clock_screen }, // Mi[n]i clock
|
|
||||||
{ NULL, 0, 0, 0, 0, 0, 0, NULL}, // No more.. all done.
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* All variables are set to 'unset' values */
|
|
||||||
static int islow = -1; /**< pause after mode update (in 1/100s) */
|
|
||||||
char *progname = "lcdproc";
|
|
||||||
char *server = NULL;
|
|
||||||
int port = LCDPORT;
|
|
||||||
int foreground = FALSE;
|
|
||||||
static int report_level = UNSET_INT;
|
|
||||||
static int report_dest = UNSET_INT;
|
|
||||||
char *configfile = NULL;
|
|
||||||
char *pidfile = NULL;
|
|
||||||
int pidfile_written = FALSE;
|
|
||||||
char *displayname = NULL; /**< display name for the main menu */
|
|
||||||
|
|
||||||
/** Returns the network name of this machine */
|
|
||||||
const char *
|
|
||||||
get_hostname(void)
|
|
||||||
{
|
|
||||||
return (unamebuf.nodename);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the name of the client's OS */
|
|
||||||
const char *
|
|
||||||
get_sysname(void)
|
|
||||||
{
|
|
||||||
return (unamebuf.sysname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the release version of the client's OS */
|
|
||||||
const char *
|
|
||||||
get_sysrelease(void)
|
|
||||||
{
|
|
||||||
return (unamebuf.release);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Enables or disables (and deletes) a screen */
|
|
||||||
static int
|
|
||||||
set_mode(int shortname, char *longname, int state)
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
|
|
||||||
for (k = 0; sequence[k].which != 0; k++) {
|
|
||||||
if (((sequence[k].longname != NULL) &&
|
|
||||||
(0 == strcasecmp(longname, sequence[k].longname))) ||
|
|
||||||
(toupper(shortname) == sequence[k].which)) {
|
|
||||||
if (!state) {
|
|
||||||
/*
|
|
||||||
* clean both the active and initialized bits
|
|
||||||
* since we delete the screen
|
|
||||||
*/
|
|
||||||
sequence[k].flags &= (~ACTIVE & ~INITIALIZED);
|
|
||||||
/* delete the screen if we are connected */
|
|
||||||
if (sock >= 0) {
|
|
||||||
sock_printf(sock, "screen_del %c\n", sequence[k].which);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sequence[k].flags |= ACTIVE;
|
|
||||||
return 1; /* found */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0; /* not found */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Sets all screens inactive */
|
|
||||||
static void
|
|
||||||
clear_modes(void)
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
|
|
||||||
for (k = 0; sequence[k].which != 0; k++) {
|
|
||||||
sequence[k].flags &= (~ACTIVE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int cfgresult;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
/* set locale for cwdate & time formatting in chrono.c */
|
|
||||||
setlocale(LC_TIME, "");
|
|
||||||
|
|
||||||
/* get uname information */
|
|
||||||
if (uname(&unamebuf) == -1) {
|
|
||||||
perror("uname");
|
|
||||||
return (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup error handlers */
|
|
||||||
signal(SIGINT, exit_program); /* Ctrl-C */
|
|
||||||
signal(SIGTERM, exit_program); /* "regular" kill */
|
|
||||||
signal(SIGHUP, exit_program); /* kill -HUP */
|
|
||||||
signal(SIGPIPE, exit_program); /* write to closed socket */
|
|
||||||
signal(SIGKILL, exit_program); /* kill -9 [cannot be trapped; but ...] */
|
|
||||||
|
|
||||||
/* No error output from getopt */
|
|
||||||
opterr = 0;
|
|
||||||
|
|
||||||
/* get options from command line */
|
|
||||||
while ((c = getopt(argc, argv, "s:p:e:c:fhv")) > 0) {
|
|
||||||
char *end;
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
/* c is for config file */
|
|
||||||
case 'c':
|
|
||||||
configfile = optarg;
|
|
||||||
break;
|
|
||||||
/* s is for server */
|
|
||||||
case 's':
|
|
||||||
server = optarg;
|
|
||||||
break;
|
|
||||||
/* p is for port */
|
|
||||||
case 'p':
|
|
||||||
port = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg == '\0') || (*end != '\0') ||
|
|
||||||
(port <= 0) || (port >= 0xFFFF)) {
|
|
||||||
fprintf(stderr, "Illegal port value %s\n", optarg);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
islow = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg == '\0') || (*end != '\0') || (islow < 0)) {
|
|
||||||
fprintf(stderr, "Illegal delay value %s\n", optarg);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
foreground = TRUE;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
HelpScreen(EXIT_SUCCESS);
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
fprintf(stderr, "LCDproc %s\n", version);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
break;
|
|
||||||
/* otherwise... Get help! */
|
|
||||||
case '?': /* unknown option or missing argument */
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
default:
|
|
||||||
HelpScreen(EXIT_FAILURE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read config file */
|
|
||||||
cfgresult = process_configfile(configfile);
|
|
||||||
if (cfgresult < 0) {
|
|
||||||
fprintf(stderr, "Error reading config file\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set default reporting options */
|
|
||||||
if (report_dest == UNSET_INT)
|
|
||||||
report_dest = DEFAULT_REPORTDEST;
|
|
||||||
if (report_level == UNSET_INT)
|
|
||||||
report_level = DEFAULT_REPORTLEVEL;
|
|
||||||
|
|
||||||
/* Set reporting settings */
|
|
||||||
set_reporting("lcdproc", report_level, report_dest);
|
|
||||||
|
|
||||||
/* parse non-option arguments: modes to add/delete */
|
|
||||||
if (argc > max(optind, 1)) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if no config file was read, ignore hard coded default
|
|
||||||
* modes
|
|
||||||
*/
|
|
||||||
if (cfgresult == 0)
|
|
||||||
clear_modes();
|
|
||||||
|
|
||||||
/* turn additional options on or off (using ! as prefix) */
|
|
||||||
for (i = max(optind, 1); i < argc; i++) {
|
|
||||||
int state = (*argv[i] == '!') ? 0 : 1;
|
|
||||||
char *name = (state) ? argv[i] : argv[i] + 1;
|
|
||||||
int shortname = (strlen(name) == 1) ? name[0] : '\0';
|
|
||||||
int found = set_mode(shortname, name, state);
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
fprintf(stderr, "Invalid Screen: %s\n", name);
|
|
||||||
return (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server == NULL)
|
|
||||||
server = DEFAULT_SERVER;
|
|
||||||
|
|
||||||
/* Connect to the server... */
|
|
||||||
sock = sock_connect(server, port);
|
|
||||||
if (sock < 0) {
|
|
||||||
fprintf(stderr, "Error connecting to LCD server %s on port %d.\n"
|
|
||||||
"Check to see that the server is running and operating normally.\n",
|
|
||||||
server, port);
|
|
||||||
return (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sock_send_string(sock, "hello\n");
|
|
||||||
usleep(500000); /* wait for the server to say hi. */
|
|
||||||
|
|
||||||
/* We grab the real values below, from the "connect" line. */
|
|
||||||
lcd_wid = 20;
|
|
||||||
lcd_hgt = 4;
|
|
||||||
lcd_cellwid = 5;
|
|
||||||
lcd_cellhgt = 8;
|
|
||||||
|
|
||||||
if (foreground != TRUE) {
|
|
||||||
if (daemon(1, 0) != 0) {
|
|
||||||
fprintf(stderr, "Error: daemonize failed\n");
|
|
||||||
return (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pidfile != NULL) {
|
|
||||||
FILE *pidf = fopen(pidfile, "w");
|
|
||||||
|
|
||||||
if (pidf) {
|
|
||||||
fprintf(pidf, "%d\n", (int)getpid());
|
|
||||||
fclose(pidf);
|
|
||||||
pidfile_written = TRUE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Error creating pidfile %s: %s\n",
|
|
||||||
pidfile, strerror(errno));
|
|
||||||
return (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init the status gatherers... */
|
|
||||||
mode_init();
|
|
||||||
|
|
||||||
/* And spew stuff! */
|
|
||||||
main_loop();
|
|
||||||
exit_program(EXIT_SUCCESS);
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads and parses configuration file.
|
|
||||||
* \param configfile The configfile to read or NULL for the default config.
|
|
||||||
* \retval 1 if configfile was read,
|
|
||||||
* \retval 0 if default configfile doesn't exist
|
|
||||||
* \retval <0 on error
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
process_configfile(char *configfile)
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
const char *tmp;
|
|
||||||
|
|
||||||
debug(RPT_DEBUG, "%s(%s)", __FUNCTION__, (configfile) ? configfile : "<null>");
|
|
||||||
|
|
||||||
/* Read config settings */
|
|
||||||
|
|
||||||
if (configfile == NULL) {
|
|
||||||
struct stat statbuf;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if default config file does not exist, do not consider
|
|
||||||
* this an error and continue
|
|
||||||
*/
|
|
||||||
if ((lstat(DEFAULT_CONFIGFILE, &statbuf) == -1) && (errno = ENOENT))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
configfile = DEFAULT_CONFIGFILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_read_file(configfile) != 0) {
|
|
||||||
report(RPT_CRIT, "Could not read config file: %s", configfile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server == NULL) {
|
|
||||||
server = strdup(config_get_string(progname, "Server", 0, DEFAULT_SERVER));
|
|
||||||
}
|
|
||||||
if (port == UNSET_INT) {
|
|
||||||
port = config_get_int(progname, "Port", 0, LCDPORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (report_level == UNSET_INT) {
|
|
||||||
report_level = config_get_int(progname, "ReportLevel", 0, RPT_WARNING);
|
|
||||||
}
|
|
||||||
if (report_dest == UNSET_INT) {
|
|
||||||
if (config_get_bool(progname, "ReportToSyslog", 0, 0)) {
|
|
||||||
report_dest = RPT_DEST_SYSLOG;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
report_dest = RPT_DEST_STDERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (foreground != TRUE) {
|
|
||||||
foreground = config_get_bool(progname, "Foreground", 0, FALSE);
|
|
||||||
}
|
|
||||||
if (pidfile == NULL) {
|
|
||||||
pidfile = strdup(config_get_string(progname, "PidFile", 0, DEFAULT_PIDFILE));
|
|
||||||
}
|
|
||||||
if (islow < 0) {
|
|
||||||
islow = config_get_int(progname, "Delay", 0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmp = config_get_string(progname, "DisplayName", 0, NULL)) != NULL)
|
|
||||||
displayname = strdup(tmp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check for config file variables to override all the sequence
|
|
||||||
* defaults
|
|
||||||
*/
|
|
||||||
for (k = 0; sequence[k].which != 0; k++) {
|
|
||||||
if (sequence[k].longname != NULL) {
|
|
||||||
sequence[k].on_time = config_get_int(sequence[k].longname, "OnTime", 0, sequence[k].on_time);
|
|
||||||
sequence[k].off_time = config_get_int(sequence[k].longname, "OffTime", 0, sequence[k].off_time);
|
|
||||||
sequence[k].show_invisible = config_get_bool(sequence[k].longname, "ShowInvisible", 0, sequence[k].show_invisible);
|
|
||||||
if (config_get_bool(sequence[k].longname, "Active", 0, sequence[k].flags & ACTIVE))
|
|
||||||
sequence[k].flags |= ACTIVE;
|
|
||||||
else
|
|
||||||
sequence[k].flags &= (~ACTIVE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Print help screen and exit */
|
|
||||||
void
|
|
||||||
HelpScreen(int exit_state)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"lcdproc - LCDproc system status information viewer\n"
|
|
||||||
"\n"
|
|
||||||
"Copyright (c) 1999-2014 Selene Scriven, William Ferrell, and misc. contributors.\n"
|
|
||||||
"This program is released under the terms of the GNU General Public License.\n"
|
|
||||||
"\n"
|
|
||||||
"Usage: lcdproc [<options>] [<screens> ...]\n"
|
|
||||||
" where <options> are\n"
|
|
||||||
" -s <host> connect to LCDd daemon on <host>\n"
|
|
||||||
" -p <port> connect to LCDd daemon using <port>\n"
|
|
||||||
" -f run in foreground\n"
|
|
||||||
" -e <delay> slow down initial announcement of screens (in 1/100s)\n"
|
|
||||||
" -c <config> use a configuration file other than %s\n"
|
|
||||||
" -h show this help screen\n"
|
|
||||||
" -v display program version\n"
|
|
||||||
" and <screens> are\n"
|
|
||||||
" C CPU detailed CPU usage\n"
|
|
||||||
" P SMP-CPU CPU usage overview (one line per CPU)\n"
|
|
||||||
" G CPUGraph CPU usage histogram\n"
|
|
||||||
" L Load load histogram\n"
|
|
||||||
" M Memory memory & swap usage\n"
|
|
||||||
" S ProcSize biggest processes size\n"
|
|
||||||
" D Disk filling level of mounted file systems\n"
|
|
||||||
" I Iface network interface usage\n"
|
|
||||||
" B Battery battery status\n"
|
|
||||||
" T TimeDate time & date information\n"
|
|
||||||
" O OldTime old time screen\n"
|
|
||||||
" U Uptime uptime screen\n"
|
|
||||||
" K BigClock big clock\n"
|
|
||||||
" N MiniClock minimal clock\n"
|
|
||||||
" A About credits page\n"
|
|
||||||
"\n"
|
|
||||||
"Example:\n"
|
|
||||||
" lcdproc -s my.lcdproc.server.com -p 13666 C M L\n"
|
|
||||||
, DEFAULT_CONFIGFILE);
|
|
||||||
|
|
||||||
exit(exit_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Called upon TERM and INTR signals. Also removes the pid-file. */
|
|
||||||
void
|
|
||||||
exit_program(int val)
|
|
||||||
{
|
|
||||||
#ifdef LCDPROC_EYEBOXONE
|
|
||||||
/*
|
|
||||||
* Clear Eyebox Leds
|
|
||||||
*/
|
|
||||||
eyebox_clear();
|
|
||||||
#endif
|
|
||||||
Quit = 1;
|
|
||||||
sock_close(sock);
|
|
||||||
mode_close();
|
|
||||||
if ((foreground != TRUE) && (pidfile != NULL) && (pidfile_written == TRUE))
|
|
||||||
unlink(pidfile);
|
|
||||||
exit(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LCDPROC_MENUS
|
|
||||||
int
|
|
||||||
menus_init()
|
|
||||||
{
|
|
||||||
int k;
|
|
||||||
|
|
||||||
for (k = 0; sequence[k].which; k++) {
|
|
||||||
if (sequence[k].longname) {
|
|
||||||
sock_printf(sock, "menu_add_item {} %c checkbox {%s} -value %s\n",
|
|
||||||
sequence[k].which, sequence[k].longname,
|
|
||||||
(sequence[k].flags & ACTIVE) ? "on" : "off");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef LCDPROC_CLIENT_TESTMENUS
|
|
||||||
/*
|
|
||||||
* to be entered on escape from test_menu (but overwritten for
|
|
||||||
* test_{checkbox,ring}
|
|
||||||
*/
|
|
||||||
sock_send_string(sock, "menu_add_item {} ask menu {Leave menus?} -is_hidden true\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {ask} ask_yes action {Yes} -next _quit_\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {ask} ask_no action {No} -next _close_\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {} test menu {Test}\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_action action {Action}\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_checkbox checkbox {Checkbox}\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_ring ring {Ring} -strings {one\ttwo\tthree}\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_slider slider {Slider} -mintext < -maxtext > -value 50\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_numeric numeric {Numeric} -value 42\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_alpha alpha {Alpha} -value abc\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_ip ip {IP} -v6 false -value 192.168.1.1\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test} test_menu menu {Menu}\n");
|
|
||||||
sock_send_string(sock, "menu_add_item {test_menu} test_menu_action action {Submenu's action}\n");
|
|
||||||
/*
|
|
||||||
* no successor for menus. Since test_checkbox and test_ring have
|
|
||||||
* their own predecessors defined the "ask" rule will not work for
|
|
||||||
* them.
|
|
||||||
*/
|
|
||||||
sock_send_string(sock, "menu_set_item {} test -prev {ask}\n");
|
|
||||||
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_action -next {test_checkbox}\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_checkbox -next {test_ring} -prev test_action\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_ring -next {test_slider} -prev {test_checkbox}\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_slider -next {test_numeric} -prev {test_ring}\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_numeric -next {test_alpha} -prev {test_slider}\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_alpha -next {test_ip} -prev {test_numeric}\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_ip -next {test_menu} -prev {test_alpha}\n");
|
|
||||||
sock_send_string(sock, "menu_set_item {test} test_menu_action -next {_close_}\n");
|
|
||||||
#endif /* LCDPROC_CLIENT_TESTMENUS */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* LCDPROC_MENUS */
|
|
||||||
|
|
||||||
|
|
||||||
/** Main program loop... */
|
|
||||||
void
|
|
||||||
main_loop(void)
|
|
||||||
{
|
|
||||||
int i = 0, j;
|
|
||||||
int connected = 0;
|
|
||||||
char buf[8192];
|
|
||||||
char *argv[256];
|
|
||||||
int argc, newtoken;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
while (!Quit) {
|
|
||||||
/* Check for server input... */
|
|
||||||
len = sock_recv(sock, buf, 8000);
|
|
||||||
|
|
||||||
/* Handle server input... */
|
|
||||||
while (len > 0) {
|
|
||||||
/* Now split the string into tokens... */
|
|
||||||
argc = 0;
|
|
||||||
newtoken = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
switch (buf[i]) {
|
|
||||||
case ' ':
|
|
||||||
newtoken = 1;
|
|
||||||
buf[i] = 0;
|
|
||||||
break;
|
|
||||||
default: /* regular chars, keep
|
|
||||||
* tokenizing */
|
|
||||||
if (newtoken)
|
|
||||||
argv[argc++] = buf + i;
|
|
||||||
newtoken = 0;
|
|
||||||
break;
|
|
||||||
case '\0':
|
|
||||||
case '\n':
|
|
||||||
buf[i] = 0;
|
|
||||||
if (argc > 0) {
|
|
||||||
if (0 == strcmp(argv[0], "listen")) {
|
|
||||||
for (j = 0; sequence[j].which; j++) {
|
|
||||||
if (sequence[j].which == argv[1][0]) {
|
|
||||||
sequence[j].flags |= VISIBLE;
|
|
||||||
debug(RPT_DEBUG, "Listen %s", argv[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(argv[0], "ignore")) {
|
|
||||||
for (j = 0; sequence[j].which; j++) {
|
|
||||||
if (sequence[j].which == argv[1][0]) {
|
|
||||||
sequence[j].flags &= ~VISIBLE;
|
|
||||||
debug(RPT_DEBUG, "Ignore %s", argv[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(argv[0], "key")) {
|
|
||||||
debug(RPT_DEBUG, "Key %s", argv[1]);
|
|
||||||
}
|
|
||||||
#ifdef LCDPROC_MENUS
|
|
||||||
else if (0 == strcmp(argv[0], "menuevent")) {
|
|
||||||
if (argc == 4 && (0 == strcmp(argv[1], "update"))) {
|
|
||||||
set_mode(argv[2][0], "", strcmp(argv[3], "off"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
else if (0 == strcmp(argv[0], "menu")) {
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (0 == strcmp(argv[0], "connect")) {
|
|
||||||
int a;
|
|
||||||
for (a = 1; a < argc; a++) {
|
|
||||||
if (0 == strcmp(argv[a], "wid"))
|
|
||||||
lcd_wid = atoi(argv[++a]);
|
|
||||||
else if (0 == strcmp(argv[a], "hgt"))
|
|
||||||
lcd_hgt = atoi(argv[++a]);
|
|
||||||
else if (0 == strcmp(argv[a], "cellwid"))
|
|
||||||
lcd_cellwid = atoi(argv[++a]);
|
|
||||||
else if (0 == strcmp(argv[a], "cellhgt"))
|
|
||||||
lcd_cellhgt = atoi(argv[++a]);
|
|
||||||
}
|
|
||||||
connected = 1;
|
|
||||||
if (displayname != NULL)
|
|
||||||
sock_printf(sock, "client_set -name \"%s\"\n", displayname);
|
|
||||||
else
|
|
||||||
sock_printf(sock, "client_set -name {LCDproc %s}\n", get_hostname());
|
|
||||||
#ifdef LCDPROC_MENUS
|
|
||||||
menus_init();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(argv[0], "bye")) {
|
|
||||||
exit_program(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
else if (0 == strcmp(argv[0], "success")) {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < argc; j++)
|
|
||||||
printf("%s ", argv[j]);
|
|
||||||
printf("\n");
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restart tokenizing */
|
|
||||||
argc = 0;
|
|
||||||
newtoken = 1;
|
|
||||||
break;
|
|
||||||
} /* switch( buf[i] ) */
|
|
||||||
}
|
|
||||||
|
|
||||||
len = sock_recv(sock, buf, 8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Gather stats and update screens */
|
|
||||||
if (connected) {
|
|
||||||
for (i = 0; sequence[i].which > 0; i++) {
|
|
||||||
sequence[i].timer++;
|
|
||||||
|
|
||||||
if (!(sequence[i].flags & ACTIVE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (sequence[i].flags & VISIBLE) {
|
|
||||||
if (sequence[i].timer >= sequence[i].on_time) {
|
|
||||||
sequence[i].timer = 0;
|
|
||||||
/* Now, update the screen... */
|
|
||||||
update_screen(&sequence[i], 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (sequence[i].timer >= sequence[i].off_time) {
|
|
||||||
sequence[i].timer = 0;
|
|
||||||
/* Now, update the screen... */
|
|
||||||
update_screen(&sequence[i], sequence[i].show_invisible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (islow > 0)
|
|
||||||
usleep(islow * 10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now sleep... */
|
|
||||||
usleep(TIME_UNIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/** \file clients/lcdproc/main.h
|
|
||||||
* Contains mode related defines and structures.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MAIN_H
|
|
||||||
#define MAIN_H
|
|
||||||
|
|
||||||
#include "shared/defines.h"
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
# define TRUE 1
|
|
||||||
#endif
|
|
||||||
#ifndef FALSE
|
|
||||||
# define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LCDP_BATT_HIGH 0x00
|
|
||||||
#define LCDP_BATT_LOW 0x01
|
|
||||||
#define LCDP_BATT_CRITICAL 0x02
|
|
||||||
#define LCDP_BATT_CHARGING 0x03
|
|
||||||
#define LCDP_BATT_ABSENT 0x04
|
|
||||||
#define LCDP_BATT_UNKNOWN 0xFF
|
|
||||||
|
|
||||||
#define LCDP_AC_OFF 0x00
|
|
||||||
#define LCDP_AC_ON 0x01
|
|
||||||
#define LCDP_AC_BACKUP 0x02
|
|
||||||
#define LCDP_AC_UNKNOWN 0x03
|
|
||||||
|
|
||||||
extern int Quit;
|
|
||||||
extern int sock;
|
|
||||||
extern char *version;
|
|
||||||
extern char *build_date;
|
|
||||||
|
|
||||||
extern int lcd_wid;
|
|
||||||
extern int lcd_hgt;
|
|
||||||
extern int lcd_cellwid;
|
|
||||||
extern int lcd_cellhgt;
|
|
||||||
|
|
||||||
/** Screen data structure */
|
|
||||||
typedef struct _screen_mode
|
|
||||||
{
|
|
||||||
char *longname; /**< Which screen is it (long name)? */
|
|
||||||
char which; /**< Which screen is it (short name)? */
|
|
||||||
int on_time; /**< How often to update while visible? */
|
|
||||||
int off_time; /**< How often to get stats while not visible? */
|
|
||||||
int show_invisible; /**< Send stats while not visible? */
|
|
||||||
int timer; /**< Time since last update */
|
|
||||||
int flags; /**< See mode flags defines */
|
|
||||||
int (*func)(int,int,int *); /**< Pointer to init / update function */
|
|
||||||
} ScreenMode;
|
|
||||||
|
|
||||||
/* mode flags */
|
|
||||||
#define VISIBLE 0x00000001 /**< currently visible */
|
|
||||||
#define ACTIVE 0x00000002 /**< selected for display */
|
|
||||||
#define INITIALIZED 0x00000004 /**< screen had already been initialized */
|
|
||||||
|
|
||||||
#define BLINK_ON 0x10
|
|
||||||
#define BLINK_OFF 0x11
|
|
||||||
#define BACKLIGHT_OFF 0x20
|
|
||||||
#define BACKLIGHT_ON 0x21
|
|
||||||
#define HOLD_SCREEN 0x30
|
|
||||||
#define CONTINUE 0x31
|
|
||||||
|
|
||||||
#define LCD_MAX_WIDTH 80
|
|
||||||
#define LCD_MAX_HEIGHT 80
|
|
||||||
|
|
||||||
const char *get_hostname(void);
|
|
||||||
const char *get_sysname(void);
|
|
||||||
const char *get_sysrelease(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,346 +0,0 @@
|
|||||||
/** \file clients/lcdproc/mem.c
|
|
||||||
* Implements the 'Memory' and 'ProcSize' screens.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#ifdef IRIX
|
|
||||||
#include <strings.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
#include "shared/LL.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mem Screen displays info about memory and swap usage...
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## MEM #### SWAP #@| |M 758.3M [- ] 35.3%@|
|
|
||||||
* | 758.3M Totl 1.884G | |S 1.884G [ ] 0.1% |
|
|
||||||
* | 490.8M Free 1.882G | +--------------------+
|
|
||||||
* |E--- F E F|
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
mem_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
static int which_title = 0;
|
|
||||||
static int gauge_wid = 0;
|
|
||||||
static int gauge_offs = 0;
|
|
||||||
meminfo_type mem[2];
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add M\n");
|
|
||||||
sock_printf(sock, "screen_set M -name {Memory & Swap: %s}\n", get_hostname());
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
gauge_wid = (lcd_wid >= 18)
|
|
||||||
? (lcd_wid - 6) / 2 /* room for E..F pairs and 2 spaces in between */
|
|
||||||
: (lcd_wid - 4) / 2; /* leave room for the E...F pairs */
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_add M title title\n");
|
|
||||||
sock_send_string(sock, "widget_set M title { MEM}\n");
|
|
||||||
sock_send_string(sock, "widget_add M subtitle string\n");
|
|
||||||
sock_printf(sock, "widget_set M subtitle %i 1 { SWAP }\n", lcd_wid - 6);
|
|
||||||
sock_send_string(sock, "widget_add M totl string\n");
|
|
||||||
sock_send_string(sock, "widget_add M used string\n");
|
|
||||||
sock_printf(sock, "widget_set M totl %i 2 Totl\n", lcd_wid/2 - 1);
|
|
||||||
sock_printf(sock, "widget_set M used %i 3 Free\n", lcd_wid/2 - 1);
|
|
||||||
sock_send_string(sock, "widget_add M EFmem string\n");
|
|
||||||
sock_printf(sock, "widget_set M EFmem 1 4 {E%*sF}\n", gauge_wid, "");
|
|
||||||
sock_send_string(sock, "widget_add M EFswap string\n");
|
|
||||||
sock_printf(sock, "widget_set M EFswap %i 4 {E%*sF}\n",
|
|
||||||
lcd_wid - gauge_wid - 1, gauge_wid, "");
|
|
||||||
sock_send_string(sock, "widget_add M memused string\n");
|
|
||||||
sock_send_string(sock, "widget_add M swapused string\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gauge_wid = (lcd_wid >= 18) ? max(2, lcd_wid - 18) : 0;
|
|
||||||
gauge_offs = (lcd_wid - gauge_wid) / 2 + 2;
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_add M m string\n");
|
|
||||||
sock_send_string(sock, "widget_add M s string\n");
|
|
||||||
if (gauge_wid > 0) {
|
|
||||||
sock_printf(sock, "widget_set M m 1 1 {M%*s[%*s]}\n",
|
|
||||||
gauge_offs - 3, "", gauge_wid, "");
|
|
||||||
sock_printf(sock, "widget_set M s 1 2 {S%*s[%*s]}\n",
|
|
||||||
gauge_offs - 3, "", gauge_wid, "");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "widget_set M m 1 1 {M }\n");
|
|
||||||
sock_send_string(sock, "widget_set M s 1 2 {S }\n");
|
|
||||||
}
|
|
||||||
sock_send_string(sock, "widget_add M mem% string\n");
|
|
||||||
sock_send_string(sock, "widget_add M swap% string\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_add M memtotl string\n");
|
|
||||||
sock_send_string(sock, "widget_add M swaptotl string\n");
|
|
||||||
|
|
||||||
sock_send_string(sock, "widget_add M memgauge hbar\n");
|
|
||||||
sock_send_string(sock, "widget_add M swapgauge hbar\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_get_meminfo(mem);
|
|
||||||
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
char tmp[12]; /* should be sufficient */
|
|
||||||
|
|
||||||
/* flip the title back and forth... (every 4 updates) */
|
|
||||||
if (which_title & 4) {
|
|
||||||
sock_printf(sock, "widget_set M subtitle %i 1 {}\n", lcd_wid - 7);
|
|
||||||
sock_printf(sock, "widget_set M title {%s}\n", get_hostname());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sock_send_string(sock, "widget_set M title { MEM}\n");
|
|
||||||
sock_printf(sock, "widget_set M subtitle %i 1 { SWAP }\n", lcd_wid - 7);
|
|
||||||
}
|
|
||||||
which_title = (which_title + 1) & 7;
|
|
||||||
|
|
||||||
/* Total memory */
|
|
||||||
sprintf_memory(tmp, mem[0].total * 1024.0, 1);
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M memtotl 1 2 {%7s}\n", tmp);
|
|
||||||
|
|
||||||
/* Free memory (plus buffers and cache) */
|
|
||||||
sprintf_memory(tmp, (mem[0].free + mem[0].buffers + mem[0].cache) * 1024.0, 1);
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M memused 1 3 {%7s}\n", tmp);
|
|
||||||
|
|
||||||
/* Total swap */
|
|
||||||
sprintf_memory(tmp, mem[1].total * 1024.0, 1);
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M swaptotl %i 2 {%7s}\n", lcd_wid - 7, tmp);
|
|
||||||
|
|
||||||
/* Free swap */
|
|
||||||
sprintf_memory(tmp, mem[1].free * 1024.0, 1);
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M swapused %i 3 {%7s}\n", lcd_wid - 7, tmp);
|
|
||||||
|
|
||||||
if (gauge_wid > 0) {
|
|
||||||
/* Free memory graph */
|
|
||||||
if (mem[0].total > 0) {
|
|
||||||
double value = 1.0 - (double) (mem[0].free + mem[0].buffers + mem[0].cache)
|
|
||||||
/ (double) mem[0].total;
|
|
||||||
|
|
||||||
/* printf(".0f", val) only prints the integer part */
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M memgauge 2 4 %.0f\n",
|
|
||||||
lcd_cellwid * gauge_wid * value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free swap graph */
|
|
||||||
if (mem[1].total > 0) {
|
|
||||||
double value = 1.0 - ((double) mem[1].free / (double) mem[1].total);
|
|
||||||
|
|
||||||
/* printf(".0f", val) only prints the integer part */
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M swapgauge %i 4 %.0f\n",
|
|
||||||
lcd_wid - gauge_wid, lcd_cellwid * gauge_wid * value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
char tmp[12]; /* should be sufficient */
|
|
||||||
|
|
||||||
/* Total memory */
|
|
||||||
sprintf_memory(tmp, mem[0].total * 1024.0, 1);
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M memtotl 3 1 {%6s}\n", tmp);
|
|
||||||
|
|
||||||
/* Total swap */
|
|
||||||
sprintf_memory(tmp, mem[1].total * 1024.0, 1);
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M swaptotl 3 2 {%6s}\n", tmp);
|
|
||||||
|
|
||||||
/* Free memory graph */
|
|
||||||
strcpy(tmp, "N/A");
|
|
||||||
if (mem[0].total > 0) {
|
|
||||||
double value = 1.0 - (double) (mem[0].free + mem[0].buffers + mem[0].cache)
|
|
||||||
/ (double) mem[0].total;
|
|
||||||
|
|
||||||
if (gauge_wid > 0) {
|
|
||||||
/* printf(".0f", val) only prints the integer part */
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M memgauge %i 1 %.0f\n",
|
|
||||||
gauge_offs, lcd_cellwid * gauge_wid * value);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf_percent(tmp, value * 100);
|
|
||||||
}
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M mem%% %i 1 {%5s}\n", lcd_wid - 5, tmp);
|
|
||||||
|
|
||||||
/* Free swap graph */
|
|
||||||
strcpy(tmp, "N/A");
|
|
||||||
if (mem[1].total > 0) {
|
|
||||||
double value = 1.0 - ((double) mem[1].free / (double) mem[1].total);
|
|
||||||
|
|
||||||
if (gauge_wid > 0) {
|
|
||||||
/* printf(".0f", val) only prints the integer part */
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M swapgauge %i 2 %.0f\n",
|
|
||||||
gauge_offs, lcd_cellwid * gauge_wid * value);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf_percent(tmp, value * 100);
|
|
||||||
}
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set M swap%% %i 2 {%5s}\n", lcd_wid - 5, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares memory usage two procinfo structures and returns 1 (true) if the
|
|
||||||
* second one's is larger than the first one's, 0 (false) otherwise.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sort_procs(void *a, void *b)
|
|
||||||
{
|
|
||||||
procinfo_type *one, *two;
|
|
||||||
|
|
||||||
if ((a == NULL) || (b == NULL))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
one = (procinfo_type *) a;
|
|
||||||
two = (procinfo_type *) b;
|
|
||||||
|
|
||||||
return (two->totl > one->totl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mem Top Screen displays info about top 5 memory hogs...
|
|
||||||
*
|
|
||||||
*\verbatim
|
|
||||||
*
|
|
||||||
* +--------------------+ +--------------------+
|
|
||||||
* |## TOP MEM: myhos #@| |## TOP MEM: myhos #@|
|
|
||||||
* |1 110.4M mysqld | |1 110.4M mysqld |
|
|
||||||
* |2 35.38M konqueror(2| +--------------------+
|
|
||||||
* |3 29.21M XFree86 |
|
|
||||||
* +--------------------+
|
|
||||||
*
|
|
||||||
*\endverbatim
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
mem_top_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
LinkedList *procs;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add S\n");
|
|
||||||
sock_printf(sock, "screen_set S -name {Top Memory Use: %s}\n", get_hostname());
|
|
||||||
sock_send_string(sock, "widget_add S title title\n");
|
|
||||||
sock_printf(sock, "widget_set S title {TOP MEM: %s}\n", get_hostname());
|
|
||||||
|
|
||||||
/* frame from (2nd line, left) to (last line, right) */
|
|
||||||
sock_send_string(sock, "widget_add S f frame\n");
|
|
||||||
|
|
||||||
/* scroll rate: 1 line every X ticks (= 1/8 sec) */
|
|
||||||
sock_printf(sock, "widget_set S f 1 2 %i %i %i 5 v %i\n",
|
|
||||||
lcd_wid, lcd_hgt, lcd_wid,
|
|
||||||
((lcd_hgt >= 4) ? 8 : 12));
|
|
||||||
|
|
||||||
/* frame contents */
|
|
||||||
for (i = 1; i <= 5; i++) {
|
|
||||||
sock_printf(sock, "widget_add S %i string -in f\n", i);
|
|
||||||
}
|
|
||||||
sock_send_string(sock, "widget_set S 1 1 1 Checking...\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a new process list */
|
|
||||||
procs = LL_new();
|
|
||||||
if (procs == NULL) {
|
|
||||||
fprintf(stderr, "mem_top_screen: Error allocating list\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
machine_get_procs(procs);
|
|
||||||
/*
|
|
||||||
* Ignore if machine_get_procs returns an errror. The list will be
|
|
||||||
* empty then and all process info will be shown empty, too.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Now, print some info... */
|
|
||||||
LL_Rewind(procs);
|
|
||||||
LL_Sort(procs, sort_procs);
|
|
||||||
LL_Rewind(procs);
|
|
||||||
for (i = 1; i <= 5; i++) {
|
|
||||||
procinfo_type *p = LL_Get(procs);
|
|
||||||
|
|
||||||
if (p != NULL) {
|
|
||||||
char mem[10];
|
|
||||||
|
|
||||||
sprintf_memory(mem, (double) p->totl * 1024.0, 1);
|
|
||||||
|
|
||||||
if (display) {
|
|
||||||
if (p->number > 1)
|
|
||||||
sock_printf(sock, "widget_set S %i 1 %i {%i %5s %s(%i)}\n",
|
|
||||||
i, i, i, mem, p->name, p->number);
|
|
||||||
else
|
|
||||||
sock_printf(sock, "widget_set S %i 1 %i {%i %5s %s}\n",
|
|
||||||
i, i, i, mem, p->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (display)
|
|
||||||
sock_printf(sock, "widget_set S %i 1 %i { }\n", i, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
LL_Next(procs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete the process list */
|
|
||||||
LL_Rewind(procs);
|
|
||||||
do {
|
|
||||||
procinfo_type *p = (procinfo_type *) LL_Get(procs);
|
|
||||||
if (p != NULL) {
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
} while (LL_Next(procs) == 0);
|
|
||||||
LL_Destroy(procs);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#ifndef MEM_H
|
|
||||||
#define MEM_H
|
|
||||||
|
|
||||||
int mem_screen(int rep, int display, int *flags_ptr);
|
|
||||||
int mem_top_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
/** \file clients/lcdproc/mode.c
|
|
||||||
* Implements the 'About' screen and contains wrappers for machine dependend
|
|
||||||
* initialization / closing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined( IRIX ) || defined( SOLARIS )
|
|
||||||
# include <strings.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "mode.h"
|
|
||||||
#include "machine.h"
|
|
||||||
#ifdef LCDPROC_EYEBOXONE
|
|
||||||
# include "eyebox.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Initialize mode specific things. */
|
|
||||||
int
|
|
||||||
mode_init(void)
|
|
||||||
{
|
|
||||||
machine_init();
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clean up modes on exit */
|
|
||||||
void
|
|
||||||
mode_close(void)
|
|
||||||
{
|
|
||||||
machine_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls the mode specific screen init / update function and updates the Eyebox
|
|
||||||
* screen as well. Sets the backlight state according to return value of the
|
|
||||||
* mode specific screen function.
|
|
||||||
*
|
|
||||||
* \param m The screen mode
|
|
||||||
* \param display Flag whether to update screen even if not visible.
|
|
||||||
* \return Backlight state
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
update_screen(ScreenMode *m, int display)
|
|
||||||
{
|
|
||||||
static int status = -1;
|
|
||||||
int old_status = status;
|
|
||||||
|
|
||||||
if (m && m->func) {
|
|
||||||
#ifdef LCDPROC_EYEBOXONE
|
|
||||||
/* Save the initialized flag (may be modified by m->func) */
|
|
||||||
int init_flag = (m->flags & INITIALIZED);
|
|
||||||
#endif
|
|
||||||
status = m->func(m->timer, display, &(m->flags));
|
|
||||||
#ifdef LCDPROC_EYEBOXONE
|
|
||||||
/* Eyebox Init */
|
|
||||||
if (init_flag == 0)
|
|
||||||
eyebox_screen(m->which, 0);
|
|
||||||
/* Eyebox Flush */
|
|
||||||
eyebox_screen(m->which, 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != old_status) {
|
|
||||||
if (status == BACKLIGHT_OFF)
|
|
||||||
sock_send_string(sock, "backlight off\n");
|
|
||||||
if (status == BACKLIGHT_ON)
|
|
||||||
sock_send_string(sock, "backlight on\n");
|
|
||||||
if (status == BLINK_ON)
|
|
||||||
sock_send_string(sock, "backlight blink\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Credit Screen shows who wrote this...
|
|
||||||
*
|
|
||||||
* \param rep Time since last screen update
|
|
||||||
* \param display 1 if screen is visible or data should be updated
|
|
||||||
* \param flags_ptr Mode flags
|
|
||||||
* \return Always 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
credit_screen(int rep, int display, int *flags_ptr)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* List of persons who contributed to LCDproc. Keep in sync with
|
|
||||||
* CREDITS file (ordered by appearance)
|
|
||||||
*/
|
|
||||||
const char *contributors[] = {
|
|
||||||
"William Ferrell",
|
|
||||||
"Selene Scriven",
|
|
||||||
"Gareth Watts",
|
|
||||||
"Lorand Bruhacs",
|
|
||||||
"Benjamin Tse",
|
|
||||||
"Matthias Prinke",
|
|
||||||
"Richard Rognlie",
|
|
||||||
"Tom Wheeley",
|
|
||||||
"Bjoern Andersson",
|
|
||||||
"Andrew McMeikan",
|
|
||||||
"David Glaude",
|
|
||||||
"Todd Porter",
|
|
||||||
"Bjoern Andersson",
|
|
||||||
"Jason Dale Woodward",
|
|
||||||
"Ethan Dicks",
|
|
||||||
"Michael Reinelt",
|
|
||||||
"Simon Harrison",
|
|
||||||
"Charles Steinkuehler",
|
|
||||||
"Harald Klein",
|
|
||||||
"Philip Pokorny",
|
|
||||||
"Glen Gray",
|
|
||||||
"David Douthitt",
|
|
||||||
"Eddie Sheldrake",
|
|
||||||
"Rene Wagner",
|
|
||||||
"Andre Breiler",
|
|
||||||
"Joris Robijn",
|
|
||||||
"Guillaume Filion",
|
|
||||||
"Chris Debenham",
|
|
||||||
"Mark Haemmerling",
|
|
||||||
"Robin Adams",
|
|
||||||
"Manuel Stahl",
|
|
||||||
"Mike Patnode",
|
|
||||||
"Peter Marschall",
|
|
||||||
"Markus Dolze",
|
|
||||||
"Volker Boerchers",
|
|
||||||
"Lucian Muresan",
|
|
||||||
"Matteo Pillon",
|
|
||||||
"Laurent Arnal",
|
|
||||||
"Simon Funke",
|
|
||||||
"Matthias Goebl",
|
|
||||||
"Stefan Herdler",
|
|
||||||
"Bernhard Walle",
|
|
||||||
"Andrew Foss",
|
|
||||||
"Anthony J. Mirabella",
|
|
||||||
"Cedric Tessier",
|
|
||||||
"John Sanders",
|
|
||||||
"Eric Pooch",
|
|
||||||
"Benjamin Wiedmann",
|
|
||||||
"Frank Jepsen",
|
|
||||||
"Karsten Festag",
|
|
||||||
"Gatewood Green",
|
|
||||||
"Dave Platt",
|
|
||||||
"Nicu Pavel",
|
|
||||||
"Daryl Fonseca-Holt",
|
|
||||||
"Thien Vu",
|
|
||||||
"Thomas Jarosch",
|
|
||||||
"Christian Jodar",
|
|
||||||
"Mariusz Bialonczyk",
|
|
||||||
"Jack Cleaver",
|
|
||||||
"Aron Parsons",
|
|
||||||
"Malte Poeggel",
|
|
||||||
"Dean Harding",
|
|
||||||
"Christian Leuschen",
|
|
||||||
"Jonathan Kyler",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
int contr_num = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((*flags_ptr & INITIALIZED) == 0) {
|
|
||||||
*flags_ptr |= INITIALIZED;
|
|
||||||
|
|
||||||
/* get number of contributors */
|
|
||||||
for (contr_num = 0; contributors[contr_num] != NULL; contr_num++)
|
|
||||||
; /* NADA */
|
|
||||||
|
|
||||||
sock_send_string(sock, "screen_add A\n");
|
|
||||||
sock_send_string(sock, "screen_set A -name {Credits for LCDproc}\n");
|
|
||||||
sock_send_string(sock, "widget_add A title title\n");
|
|
||||||
sock_printf(sock, "widget_set A title {LCDPROC %s}\n", version);
|
|
||||||
if (lcd_hgt >= 4) {
|
|
||||||
sock_send_string(sock, "widget_add A text scroller\n");
|
|
||||||
sock_printf(sock, "widget_set A text 1 2 %d 2 h 8 {%s}\n",
|
|
||||||
lcd_wid, "LCDproc was brought to you by:");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* frame from (2nd/3rd line, left) to (last line, right) */
|
|
||||||
sock_send_string(sock, "widget_add A f frame\n");
|
|
||||||
sock_printf(sock, "widget_set A f 1 %i %i %i %i %i v %i\n",
|
|
||||||
((lcd_hgt >= 4) ? 3 : 2), lcd_wid, lcd_hgt, lcd_wid, contr_num,
|
|
||||||
/* scroll rate: 1 line every X ticks (= 1/8 sec) */
|
|
||||||
((lcd_hgt >= 4) ? 8 : 12));
|
|
||||||
|
|
||||||
/* frame contents */
|
|
||||||
for (i = 1; i < contr_num; i++) {
|
|
||||||
sock_printf(sock, "widget_add A c%i string -in f\n", i);
|
|
||||||
sock_printf(sock, "widget_set A c%i 1 %i {%s}\n", i, i, contributors[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#ifndef MODE_H
|
|
||||||
#define MODE_H
|
|
||||||
|
|
||||||
int mode_init(void);
|
|
||||||
void mode_close(void);
|
|
||||||
int update_screen(ScreenMode *m, int display);
|
|
||||||
int credit_screen(int rep, int display, int *flags_ptr);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
/** \file clients/lcdproc/util.c
|
|
||||||
* Utility functions to print some numerical values in a nice fashion
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (C) 2005 Peter Marschall
|
|
||||||
*
|
|
||||||
* This program 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 program 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 program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
|
|
||||||
/** Print a memory value with the correct unit to a given string.
|
|
||||||
* \param *dst String to print the value to.
|
|
||||||
* \param value Value to print.
|
|
||||||
* \param roundlimit Set < 1.0 if precision of original input value is not sufficient.
|
|
||||||
* \return dst
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sprintf_memory(char *dst, double value, double roundlimit)
|
|
||||||
{
|
|
||||||
if (dst != NULL) {
|
|
||||||
char *format = "%.1f%s";
|
|
||||||
|
|
||||||
char *unit = convert_double(&value, 1024, roundlimit);
|
|
||||||
|
|
||||||
if (value < 100)
|
|
||||||
format = "%.2f%s";
|
|
||||||
if (value < 10)
|
|
||||||
format = "%.3f%s";
|
|
||||||
|
|
||||||
sprintf(dst, format, value, unit);
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Print a percentage value to a given string.
|
|
||||||
* \param *dst String to print the percentage value to.
|
|
||||||
* \param percent Value to print.
|
|
||||||
* \return dst
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
sprintf_percent(char *dst, double percent)
|
|
||||||
{
|
|
||||||
if (dst != NULL) {
|
|
||||||
if (percent > 99.9)
|
|
||||||
strcpy(dst, "100%");
|
|
||||||
else
|
|
||||||
sprintf(dst, "%.1f%%", (percent >= 0) ? percent : 0);
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Convert a value with unit value.
|
|
||||||
* does not do formatting
|
|
||||||
* \param *value Pointer to the value to be scaled
|
|
||||||
* \param base Base used for scaling (e.g. 1000 for decimal, 1024 for binary units)
|
|
||||||
* \param roundlimit Set < 1.0 if precision of original input value is not sufficient
|
|
||||||
* \return Unit string to be used when displaying value
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
convert_double(double *value, int base, double roundlimit)
|
|
||||||
{
|
|
||||||
static char *units[] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y", NULL};
|
|
||||||
int off = 0;
|
|
||||||
|
|
||||||
if ((roundlimit <= 0.0) || (roundlimit > 1.0))
|
|
||||||
roundlimit = 0.5;
|
|
||||||
|
|
||||||
/* Get value's order of magnitude */
|
|
||||||
while (units[off] != NULL) {
|
|
||||||
/*
|
|
||||||
* Note: the check for 1000 is to idenfity the number of
|
|
||||||
* characters in the output needed, not to decide if to scale
|
|
||||||
* value.
|
|
||||||
*/
|
|
||||||
if (*value < 1000 * roundlimit)
|
|
||||||
break;
|
|
||||||
off++;
|
|
||||||
*value /= base;
|
|
||||||
}
|
|
||||||
return units[off];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/** \file clients/lcdproc/util.h
|
|
||||||
* Header file for \c util.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (C) 2005 Peter Marschall
|
|
||||||
*
|
|
||||||
* This file is part of lcdproc, the lcdproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License.
|
|
||||||
* Refer to the COPYING file distributed with this package.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LCDPROC_UTIL_H
|
|
||||||
#define LCDPROC_UTIL_H
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/** print a memory value with the correct unit to a given string */
|
|
||||||
char *sprintf_memory(char *dst, double value, double roundlimit);
|
|
||||||
|
|
||||||
/** print a percentage value to a given string */
|
|
||||||
char *sprintf_percent(char *dst, double percent);
|
|
||||||
|
|
||||||
/** converts value into power-of-x representation */
|
|
||||||
char *convert_double(double *value, int base, double roundlimit);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
.deps
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
lcdvc
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
sysconf_DATA = lcdvc.conf
|
|
||||||
|
|
||||||
bin_PROGRAMS = lcdvc
|
|
||||||
|
|
||||||
lcdvc_SOURCES = lcdvc.c lcdvc.h lcd_link.c lcd_link.h vc_link.c vc_link.h
|
|
||||||
|
|
||||||
lcdvc_LDADD = ../../shared/libLCDstuff.a
|
|
||||||
|
|
||||||
if DARWIN
|
|
||||||
AM_LDFLAGS = -framework CoreFoundation -framework IOKit
|
|
||||||
endif
|
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -DSYSCONFDIR=\"$(sysconfdir)\" -DPIDFILEDIR=\"$(pidfiledir)\"
|
|
||||||
|
|
||||||
#AM_CFLAGS = -g -O0
|
|
||||||
#AM_LDFLAGS = -g
|
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = $(sysconf_DATA)
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,379 +0,0 @@
|
|||||||
/** \file clients/lcdvc/lcd_link.c
|
|
||||||
* Functions to build and update the display and to handle server input.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdvc, an LCDproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License. Refer to the
|
|
||||||
* COPYING file distributed with this package.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Joris Robijn
|
|
||||||
* 2006-2008, Peter Marschall
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcd_link.h"
|
|
||||||
#include "vc_link.h"
|
|
||||||
#include "lcdvc.h"
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/str.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
char *address = UNSET_STR;
|
|
||||||
int port = UNSET_INT;
|
|
||||||
short autoscroll = 1;
|
|
||||||
|
|
||||||
int sock;
|
|
||||||
short listening = 0;
|
|
||||||
short scroll_x = 0, scroll_y = 0;
|
|
||||||
short lcd_cursor_x, lcd_cursor_y;
|
|
||||||
short lcd_width = 0, lcd_height = 0;
|
|
||||||
char *lcd_buf = NULL;
|
|
||||||
|
|
||||||
short last_vc_cursor_y = 0;
|
|
||||||
short last_vc_cursor_x = 0;
|
|
||||||
short last_lcd_cursor_x = 0;
|
|
||||||
short last_lcd_cursor_y = 0;
|
|
||||||
|
|
||||||
static int read_connect_string(void);
|
|
||||||
static int split(char *str, char delim, char *parts[], int maxparts);
|
|
||||||
|
|
||||||
|
|
||||||
int setup_connection(void)
|
|
||||||
{
|
|
||||||
char buf[200];
|
|
||||||
int i;
|
|
||||||
int e = 0;
|
|
||||||
short line;
|
|
||||||
|
|
||||||
report(RPT_INFO, "Connecting to %s:%d", address, port);
|
|
||||||
|
|
||||||
sock = sock_connect(address, port);
|
|
||||||
if (sock < 0) {
|
|
||||||
report(RPT_ERR, "Connecting to %s:%d failed", address, port);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* Create our menu */
|
|
||||||
sock_send_string(sock, "hello\n");
|
|
||||||
if (read_connect_string() < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf)-1, "client_set -name \"%s\"\n", progname);
|
|
||||||
sock_send_string(sock, buf);
|
|
||||||
|
|
||||||
/* Create screen */
|
|
||||||
CHAIN(e, sock_send_string(sock, "screen_add console\n"));
|
|
||||||
for (line = 0; line < lcd_height; line++) {
|
|
||||||
snprintf(buf, sizeof(buf)-1, "widget_add console line%d string\n", line);
|
|
||||||
buf[sizeof(buf)-1] = 0;
|
|
||||||
CHAIN(e, sock_send_string(sock, buf));
|
|
||||||
}
|
|
||||||
/* Add menu items */
|
|
||||||
CHAIN(e, sock_send_string(sock, "menu_add_item \"\" autoscroll checkbox \"Auto scroll\"\n"));
|
|
||||||
CHAIN(e, sock_send_string(sock, "menu_set_item \"\" autoscroll -value on\n"));
|
|
||||||
|
|
||||||
/* Reserve keys */
|
|
||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
snprintf(buf, sizeof(buf)-1, "client_add_key \"%s\"\n", keys[i]);
|
|
||||||
CHAIN(e, sock_send_string(sock, buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e < 0) {
|
|
||||||
report(RPT_ERR, "Could not send to to LCDd");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int teardown_connection(void)
|
|
||||||
{
|
|
||||||
sock_close(sock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int read_connect_string(void)
|
|
||||||
{
|
|
||||||
char buf[8192];
|
|
||||||
int len = 0;
|
|
||||||
int a;
|
|
||||||
char *argv[20];
|
|
||||||
int argc;
|
|
||||||
short received = 0;
|
|
||||||
short timeout = 50; /* Give the server 5 secs to respond */
|
|
||||||
|
|
||||||
buf[0] = '\0';
|
|
||||||
|
|
||||||
while (!received && timeout > 0) {
|
|
||||||
len = sock_recv_string(sock, buf, sizeof(buf));
|
|
||||||
if (len == 0) {
|
|
||||||
usleep(100000);
|
|
||||||
timeout --;
|
|
||||||
} else {
|
|
||||||
received = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
report(RPT_INFO, "Received: %s", buf);
|
|
||||||
|
|
||||||
if (len <= 0) {
|
|
||||||
report(RPT_ERR, "Did not receive LCDd connect response.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
argc = split(buf, ' ', argv, 20);
|
|
||||||
for (a = 1; a < argc; a++) {
|
|
||||||
if (0 == strcmp(argv[a], "wid"))
|
|
||||||
lcd_width = atoi(argv[++a]);
|
|
||||||
else if (0 == strcmp(argv[a], "hgt"))
|
|
||||||
lcd_height = atoi(argv[++a]);
|
|
||||||
}
|
|
||||||
if (argc <= 0 || strcmp(argv[0], "connect") != 0
|
|
||||||
|| lcd_width == 0 || lcd_width == 0) {
|
|
||||||
report(RPT_ERR, "Received invalid LCDd connect response.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits a string into parts, to which pointers will be returned in &parts.
|
|
||||||
* The return value is the number of parts.
|
|
||||||
* maxparts is the maximum number of parts returned. If more parts exist
|
|
||||||
* they are (unsplit) in the last part.
|
|
||||||
* The parts are split at the character delim.
|
|
||||||
* No new space will be allocated, the string str will be mutated !
|
|
||||||
*/
|
|
||||||
static int split(char *str, char delim, char *parts[], int maxparts)
|
|
||||||
{
|
|
||||||
char *p1 = str;
|
|
||||||
char *p2;
|
|
||||||
int part_nr = 0;
|
|
||||||
|
|
||||||
/* Find the delim char to end the current part */
|
|
||||||
while (part_nr < maxparts - 1 && (p2 = strchr(p1, delim))) {
|
|
||||||
|
|
||||||
/* subsequent parts... */
|
|
||||||
*p2 = 0;
|
|
||||||
parts[part_nr] = p1;
|
|
||||||
|
|
||||||
p1 = p2 + 1; /* Just after the delim char */
|
|
||||||
part_nr ++;
|
|
||||||
}
|
|
||||||
/* and the last part... */
|
|
||||||
parts[part_nr] = p1;
|
|
||||||
part_nr ++;
|
|
||||||
|
|
||||||
return part_nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int read_response(char *buf, int maxsize)
|
|
||||||
{
|
|
||||||
return sock_recv_string(sock, buf, maxsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int process_response(char *str)
|
|
||||||
{
|
|
||||||
char *argv[10];
|
|
||||||
int argc;
|
|
||||||
//int i;
|
|
||||||
//char *p;
|
|
||||||
char *str2 = strdup(str); /* get_args modifies str2 */
|
|
||||||
|
|
||||||
report(RPT_DEBUG, "Server said: \"%s\"", str);
|
|
||||||
|
|
||||||
/* Check what the server just said to us... */
|
|
||||||
argc = get_args(argv, str2, 10);
|
|
||||||
if (argc < 1) {
|
|
||||||
free(str2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(argv[0], "listen") == 0) {
|
|
||||||
listening = 1;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "ignore") == 0) {
|
|
||||||
listening = 0;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "menuevent") == 0) {
|
|
||||||
/* Ah, this is what we were waiting for ! */
|
|
||||||
if (argc < 2) {
|
|
||||||
report(RPT_WARNING, "Server gave invalid response");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[1], "update") == 0) {
|
|
||||||
if (argc < 4) {
|
|
||||||
report(RPT_WARNING, "Server gave invalid response");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (strcmp(argv[2], "autoscroll") == 0) {
|
|
||||||
if (strcmp(argv[3], "on") == 0) {
|
|
||||||
autoscroll = 1;
|
|
||||||
} else if (strcmp(argv[3], "off") == 0) {
|
|
||||||
autoscroll = 0;
|
|
||||||
}
|
|
||||||
report(RPT_INFO, "Autoscroll set to %d", autoscroll);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
; /* Ignore other menuevents */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "key") == 0) {
|
|
||||||
if (argc < 2) {
|
|
||||||
report(RPT_WARNING, "Server gave invalid response");
|
|
||||||
free(str2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (strcmp(argv[1], keys[0]) == 0) {
|
|
||||||
if (scroll_y > 0) scroll_y --;
|
|
||||||
} else if (strcmp(argv[1], keys[1]) == 0) {
|
|
||||||
if (scroll_y + lcd_height < vc_height) scroll_y ++;
|
|
||||||
} else if (strcmp(argv[1], keys[2]) == 0) {
|
|
||||||
if (scroll_x > 0) scroll_x --;
|
|
||||||
} else if (strcmp(argv[1], keys[3]) == 0) {
|
|
||||||
if (scroll_x + lcd_width < vc_width) scroll_x ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(argv[0], "huh?") == 0) {
|
|
||||||
/* Report errors */
|
|
||||||
report(RPT_WARNING, "Server said: \"%s\"", str);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
; /* Ignore all other responses */
|
|
||||||
}
|
|
||||||
free(str2);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int update_display(void)
|
|
||||||
{
|
|
||||||
//int bytes_read;
|
|
||||||
short line;
|
|
||||||
int e = 0;
|
|
||||||
char buf[80];
|
|
||||||
char *str_buf;
|
|
||||||
short num_lines;
|
|
||||||
num_lines = min(lcd_height, vc_height);
|
|
||||||
|
|
||||||
if (!listening)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!lcd_buf) {
|
|
||||||
/* Not yet allocated */
|
|
||||||
lcd_buf = malloc(lcd_width * lcd_height);
|
|
||||||
memset(lcd_buf, ' ', lcd_width * lcd_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (autoscroll
|
|
||||||
&& (last_vc_cursor_x != vc_cursor_x || last_vc_cursor_y != vc_cursor_y)) {
|
|
||||||
last_vc_cursor_x = vc_cursor_x;
|
|
||||||
last_vc_cursor_y = vc_cursor_y;
|
|
||||||
|
|
||||||
/* Adjust scroll position */
|
|
||||||
if (scroll_x > vc_cursor_x)
|
|
||||||
scroll_x = vc_cursor_x;
|
|
||||||
if (scroll_x < vc_cursor_x - lcd_width + 1)
|
|
||||||
scroll_x = vc_cursor_x - lcd_width + 1;
|
|
||||||
if (scroll_y > vc_cursor_y)
|
|
||||||
scroll_y = vc_cursor_y;
|
|
||||||
if (scroll_y < vc_cursor_y - lcd_height + 1)
|
|
||||||
scroll_y = vc_cursor_y - lcd_height + 1;
|
|
||||||
}
|
|
||||||
lcd_cursor_x = vc_cursor_x - scroll_x + 1;
|
|
||||||
lcd_cursor_y = vc_cursor_y - scroll_y + 1;
|
|
||||||
if (lcd_cursor_x != last_lcd_cursor_x || lcd_cursor_y != last_lcd_cursor_y) {
|
|
||||||
last_lcd_cursor_x = lcd_cursor_x;
|
|
||||||
last_lcd_cursor_y = lcd_cursor_y;
|
|
||||||
|
|
||||||
/* New scroll positions, send the cursor command */
|
|
||||||
if (lcd_cursor_x < 1 || lcd_cursor_x > lcd_width
|
|
||||||
|| lcd_cursor_y < 1 || lcd_cursor_y > lcd_height) {
|
|
||||||
snprintf(buf, sizeof(buf)-1, "screen_set console -cursor off\n");
|
|
||||||
} else {
|
|
||||||
snprintf(buf, sizeof(buf)-1, "screen_set console -cursor on -cursor_x %d -cursor_y %d\n",
|
|
||||||
lcd_cursor_x, lcd_cursor_y);
|
|
||||||
}
|
|
||||||
buf[sizeof(buf)-1] = 0;
|
|
||||||
CHAIN(e, sock_send_string(sock, buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send all (changed) lines */
|
|
||||||
str_buf = malloc(80 + 2 * lcd_width);
|
|
||||||
for (line = 0; line < num_lines; line++) {
|
|
||||||
|
|
||||||
char *vc_p;
|
|
||||||
char *lcd_p;
|
|
||||||
short line_width;
|
|
||||||
|
|
||||||
line_width = min(lcd_width, vc_width);
|
|
||||||
|
|
||||||
/* Where does the data for this line come from ? */
|
|
||||||
vc_p = vc_buf + vc_width * (scroll_y + line) + scroll_x;
|
|
||||||
lcd_p = lcd_buf + lcd_width * line;
|
|
||||||
|
|
||||||
/* Has the line data changed ? */
|
|
||||||
if (memcmp(vc_p, lcd_p, line_width) != 0) {
|
|
||||||
/* Yes, so send it */
|
|
||||||
char *a;
|
|
||||||
short pos;
|
|
||||||
|
|
||||||
/* Format/escape the data */
|
|
||||||
snprintf(str_buf, 80, "widget_set console line%d 1 %d \"", line, line+1);
|
|
||||||
|
|
||||||
a = str_buf + strlen(str_buf); /* start just after the " */
|
|
||||||
for (pos = 0; pos < line_width; pos++) {
|
|
||||||
if (vc_p[pos] == '\\' || vc_p[pos] == '\"') {
|
|
||||||
*a++ = '\\'; /* add escape char */
|
|
||||||
}
|
|
||||||
if ((signed char) vc_p[pos] >= 32) {
|
|
||||||
*a++ = vc_p[pos]; /* add char */
|
|
||||||
} else {
|
|
||||||
*a++ = '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*a++ = '\"'; /* end string */
|
|
||||||
*a++ = '\n'; /* newline */
|
|
||||||
*a = 0; /* terminate */
|
|
||||||
CHAIN(e, sock_send_string(sock, str_buf));
|
|
||||||
|
|
||||||
/* And store the new data */
|
|
||||||
memcpy(lcd_p, vc_p, line_width);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(str_buf);
|
|
||||||
|
|
||||||
if (e < 0) {
|
|
||||||
report(RPT_ERR, "Error while sending data to LCDd");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int send_nop(void)
|
|
||||||
{
|
|
||||||
return sock_send_string(sock, "\n");
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#ifndef LCD_LINK_H
|
|
||||||
#define LCD_LINK_H
|
|
||||||
|
|
||||||
extern char *address;
|
|
||||||
extern int port;
|
|
||||||
|
|
||||||
int setup_connection(void);
|
|
||||||
int teardown_connection(void);
|
|
||||||
int read_response(char *str, int maxsize);
|
|
||||||
int process_response(char *str);
|
|
||||||
int update_display(void);
|
|
||||||
int send_nop(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,300 +0,0 @@
|
|||||||
/** \file clients/lcdvc/lcdvc.c
|
|
||||||
* Main file for \c lcdvc, the LCDproc virtual console.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdvc, an LCDproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License. Refer to the
|
|
||||||
* COPYING file distributed with this package.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Joris Robijn
|
|
||||||
* 2006-2008, Peter Marschall
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "getopt.h"
|
|
||||||
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/configfile.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
#include "lcd_link.h"
|
|
||||||
#include "vc_link.h"
|
|
||||||
#include "lcdvc.h"
|
|
||||||
|
|
||||||
#if !defined(SYSCONFDIR)
|
|
||||||
# define SYSCONFDIR "/etc"
|
|
||||||
#endif
|
|
||||||
#if !defined(PIDFILEDIR)
|
|
||||||
# define PIDFILEDIR "/var/run"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEFAULT_CONFIGFILE SYSCONFDIR "/lcdvc.conf"
|
|
||||||
#define DEFAULT_PIDFILE PIDFILEDIR "/lcdvc.pid"
|
|
||||||
|
|
||||||
|
|
||||||
char *help_text =
|
|
||||||
"lcdvc - LCDproc virtual console\n"
|
|
||||||
"\n"
|
|
||||||
"Copyright (c) 2002, Joris Robijn, 2006-2008 Peter Marschall.\n"
|
|
||||||
"This program is released under the terms of the GNU General Public License.\n"
|
|
||||||
"\n"
|
|
||||||
"Usage: lcdvc [<options>]\n"
|
|
||||||
" where <options> are:\n"
|
|
||||||
" -c <file> Specify configuration file ["DEFAULT_CONFIGFILE"]\n"
|
|
||||||
" -a <address> DNS name or IP address of the LCDd server [localhost]\n"
|
|
||||||
" -p <port> port of the LCDd server [13666]\n"
|
|
||||||
" -f Run in foreground\n"
|
|
||||||
" -r <level> Set reporting level (0-5) [2: errors and warnings]\n"
|
|
||||||
" -s <0|1> Report to syslog (1) or stderr (0, default)\n"
|
|
||||||
" -h Show this help\n";
|
|
||||||
|
|
||||||
/* Variables set by config */
|
|
||||||
int foreground = FALSE;
|
|
||||||
static int report_level = UNSET_INT;
|
|
||||||
static int report_dest = UNSET_INT;
|
|
||||||
char *vcsa_device = UNSET_STR;
|
|
||||||
char *vcs_device = UNSET_STR;
|
|
||||||
char *keys[4];
|
|
||||||
|
|
||||||
/* Other global variables */
|
|
||||||
char *progname = "lcdvc";
|
|
||||||
char *configfile = UNSET_STR;
|
|
||||||
char *pidfile = NULL;
|
|
||||||
int pidfile_written = FALSE;
|
|
||||||
|
|
||||||
int Quit = 0; /**< indicate end of main loop */
|
|
||||||
|
|
||||||
/* Function prototypes */
|
|
||||||
static void exit_program(int val);
|
|
||||||
static int process_command_line(int argc, char **argv);
|
|
||||||
static int process_configfile(char *configfile);
|
|
||||||
static int main_loop(void);
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int e = 0;
|
|
||||||
struct sigaction sa;
|
|
||||||
|
|
||||||
CHAIN( e, process_command_line( argc, argv ));
|
|
||||||
if (strcmp( configfile, UNSET_STR ) == 0) {
|
|
||||||
configfile = DEFAULT_CONFIGFILE;
|
|
||||||
}
|
|
||||||
CHAIN( e, process_configfile( configfile ));
|
|
||||||
if (report_dest == UNSET_INT || report_level == UNSET_INT) {
|
|
||||||
report_dest = RPT_DEST_STDERR;
|
|
||||||
report_level = RPT_ERR;
|
|
||||||
}
|
|
||||||
set_reporting( progname, report_level, report_dest );
|
|
||||||
|
|
||||||
CHAIN( e, open_vcs() );
|
|
||||||
CHAIN( e, setup_connection() );
|
|
||||||
CHAIN_END( e );
|
|
||||||
|
|
||||||
if (foreground != TRUE) {
|
|
||||||
if (daemon(1,1) != 0) {
|
|
||||||
report(RPT_ERR, "Error: daemonize failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pidfile != NULL) {
|
|
||||||
FILE *pidf = fopen(pidfile, "w");
|
|
||||||
|
|
||||||
if (pidf) {
|
|
||||||
fprintf(pidf, "%d\n", (int) getpid());
|
|
||||||
fclose(pidf);
|
|
||||||
pidfile_written = TRUE;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Error creating pidfile %s: %s\n",
|
|
||||||
pidfile, strerror(errno));
|
|
||||||
return(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup signal handlers for common signals */
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
#ifdef HAVE_SA_RESTART
|
|
||||||
sa.sa_flags = SA_RESTART;
|
|
||||||
#endif
|
|
||||||
sa.sa_handler = exit_program;
|
|
||||||
sigaction(SIGINT, &sa, NULL); // Ctrl-C
|
|
||||||
sigaction(SIGTERM, &sa, NULL); // "regular" kill
|
|
||||||
sigaction(SIGHUP, &sa, NULL); // kill -HUP
|
|
||||||
sigaction(SIGPIPE, &sa, NULL); // write to closed socket
|
|
||||||
sigaction(SIGKILL, &sa, NULL); // kill -9 [cannot be trapped; but ...]
|
|
||||||
|
|
||||||
main_loop();
|
|
||||||
|
|
||||||
exit_program(EXIT_SUCCESS);
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void exit_program(int val)
|
|
||||||
{
|
|
||||||
//printf("exit program\n");
|
|
||||||
Quit = 1;
|
|
||||||
teardown_connection();
|
|
||||||
if ((foreground != TRUE) && (pidfile != NULL) && (pidfile_written == TRUE))
|
|
||||||
unlink(pidfile);
|
|
||||||
exit(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int process_command_line(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
/* No error output from getopt */
|
|
||||||
opterr = 0;
|
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "hc:a:p:fr:s:")) > 0) {
|
|
||||||
char *end;
|
|
||||||
int temp_int;
|
|
||||||
|
|
||||||
switch (c) {
|
|
||||||
case 'h':
|
|
||||||
fprintf(stderr, "%s", help_text);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
/* NOTREACHED */
|
|
||||||
case 'c':
|
|
||||||
configfile = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
address = strdup(optarg);
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
temp_int = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg != '\0') && (*end == '\0') &&
|
|
||||||
(temp_int > 0) && (temp_int <= 0xFFFF)) {
|
|
||||||
port = temp_int;
|
|
||||||
} else {
|
|
||||||
report(RPT_ERR, "Illegal port value %s", optarg);
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
foreground = TRUE;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
temp_int = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg != '\0') && (*end == '\0') && (temp_int >= 0)) {
|
|
||||||
report_level = temp_int;
|
|
||||||
} else {
|
|
||||||
report(RPT_ERR, "Illegal report level value %s", optarg);
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
temp_int = strtol(optarg, &end, 0);
|
|
||||||
if ((*optarg != '\0') && (*end == '\0') && (temp_int >= 0)) {
|
|
||||||
report_dest = (temp_int ? RPT_DEST_SYSLOG : RPT_DEST_STDERR);
|
|
||||||
} else {
|
|
||||||
report(RPT_ERR, "Illegal log destination value %s", optarg);
|
|
||||||
error = -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ':':
|
|
||||||
report(RPT_ERR, "Missing option argument for %c", optopt);
|
|
||||||
error = -1;
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
report(RPT_ERR, "Unknown option: %c", optopt);
|
|
||||||
error = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int process_configfile(char *configfile)
|
|
||||||
{
|
|
||||||
if (strcmp(configfile, UNSET_STR) == 0) {
|
|
||||||
configfile = DEFAULT_CONFIGFILE;
|
|
||||||
}
|
|
||||||
if (config_read_file( configfile ) < 0) {
|
|
||||||
report( RPT_WARNING, "Could not read config file: %s", configfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(address, UNSET_STR ) == 0) {
|
|
||||||
address = strdup(config_get_string( progname, "Address", 0, "localhost"));
|
|
||||||
}
|
|
||||||
if (port == UNSET_INT) {
|
|
||||||
port = config_get_int(progname, "Port", 0, 13666);
|
|
||||||
}
|
|
||||||
if (report_level == UNSET_INT ) {
|
|
||||||
report_level = config_get_int(progname, "ReportLevel", 0, RPT_WARNING);
|
|
||||||
}
|
|
||||||
if (report_dest == UNSET_INT) {
|
|
||||||
if (config_get_bool(progname, "ReportToSyslog", 0, 0)) {
|
|
||||||
report_dest = RPT_DEST_SYSLOG;
|
|
||||||
} else {
|
|
||||||
report_dest = RPT_DEST_STDERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (foreground != TRUE) {
|
|
||||||
foreground = config_get_bool(progname, "Foreground", 0, FALSE);
|
|
||||||
}
|
|
||||||
if (pidfile == NULL) {
|
|
||||||
pidfile = strdup(config_get_string(progname, "PidFile", 0, DEFAULT_PIDFILE));
|
|
||||||
}
|
|
||||||
|
|
||||||
vcs_device = strdup(config_get_string(progname, "vcsDevice", 0, "/dev/vcs"));
|
|
||||||
vcsa_device = strdup(config_get_string(progname, "vcsaDevice", 0, "/dev/vcsa"));
|
|
||||||
|
|
||||||
keys[0] = strdup(config_get_string( progname, "UpKey", 0, "Up"));
|
|
||||||
keys[1] = strdup(config_get_string( progname, "DownKey", 0, "Down"));
|
|
||||||
keys[2] = strdup(config_get_string( progname, "LeftKey", 0, "Left"));
|
|
||||||
keys[3] = strdup(config_get_string( progname, "RightKey", 0, "Right"));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int main_loop(void)
|
|
||||||
{
|
|
||||||
int num_bytes;
|
|
||||||
char buf[80];
|
|
||||||
short w = 0;
|
|
||||||
|
|
||||||
/* Continuously check if we get a menu event... */
|
|
||||||
|
|
||||||
while (!Quit && ((num_bytes = read_response(buf, sizeof(buf)-1)) >= 0)) {
|
|
||||||
if (num_bytes != 0) {
|
|
||||||
process_response(buf);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
read_vcdata();
|
|
||||||
update_display();
|
|
||||||
|
|
||||||
/* Send an empty line every 3 seconds to make sure the server still exists */
|
|
||||||
if (w++ >= 60) {
|
|
||||||
w = 0;
|
|
||||||
if (send_nop() < 0) {
|
|
||||||
break; /* Out of while loop */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usleep(50000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Quit)
|
|
||||||
report(RPT_WARNING, "Server disconnected %d", num_bytes);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# lcdvc client configuration file
|
|
||||||
|
|
||||||
## general options ##
|
|
||||||
[lcdvc]
|
|
||||||
|
|
||||||
# Address of the LCDd server
|
|
||||||
#Address=127.0.0.1
|
|
||||||
|
|
||||||
# Port to attach to LCDd server
|
|
||||||
#Port=13666
|
|
||||||
|
|
||||||
#If false, report to stderr. If true, to syslog.
|
|
||||||
#ReportToSyslog=true
|
|
||||||
|
|
||||||
# Same as with LCDd.
|
|
||||||
#ReportLevel=4
|
|
||||||
|
|
||||||
# run in foreground [default: false; legal: true, false]
|
|
||||||
#Foreground=false
|
|
||||||
|
|
||||||
# PidFile location when running as daemon [default: /var/run/lcdvc.pid]
|
|
||||||
#PidFile=/var/run/lcdvc.pid
|
|
||||||
|
|
||||||
# Keys to move the visible area around the screen.
|
|
||||||
#UpKey=Up
|
|
||||||
#DownKey=Down
|
|
||||||
#LeftKey=Left
|
|
||||||
#RightKey=Right
|
|
||||||
|
|
||||||
# VC devices to use [default: /dev/vcs, /dev/vcsa]
|
|
||||||
vcsDevice=/dev/vcs
|
|
||||||
vcsaDevice=/dev/vcsa
|
|
||||||
|
|
||||||
# EOF
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#ifndef LCDVC_H
|
|
||||||
#define LCDVC_H
|
|
||||||
|
|
||||||
#include "shared/defines.h"
|
|
||||||
|
|
||||||
#define CHAIN(e,f) { if( e>=0 ) { e=(f); }}
|
|
||||||
#define CHAIN_END(e) { if( e<0 ) { report( RPT_CRIT,"Critical error, abort"); exit(e); }}
|
|
||||||
|
|
||||||
#define UNSET_INT -1
|
|
||||||
#define UNSET_STR "\01"
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
# define TRUE 1
|
|
||||||
#endif
|
|
||||||
#ifndef FALSE
|
|
||||||
# define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern char *vcs_device;
|
|
||||||
extern char *vcsa_device;
|
|
||||||
|
|
||||||
extern char *keys[4];
|
|
||||||
|
|
||||||
extern char *progname;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
/** \file clients/lcdvc/vc_link.c
|
|
||||||
* Functions to handle a virtual console.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* This file is part of lcdvc, an LCDproc client.
|
|
||||||
*
|
|
||||||
* This file is released under the GNU General Public License. Refer to the
|
|
||||||
* COPYING file distributed with this package.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002, Joris Robijn
|
|
||||||
* 2006-2008, Peter Marschall
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcdvc.h"
|
|
||||||
#include "vc_link.h"
|
|
||||||
#include "shared/report.h"
|
|
||||||
#include "shared/sockets.h"
|
|
||||||
|
|
||||||
int vcs0, vcsa;
|
|
||||||
unsigned short vc_width = 0, vc_height = 0;
|
|
||||||
unsigned short vc_cursor_x = 0, vc_cursor_y = 0;
|
|
||||||
char *vc_buf = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
int open_vcs(void)
|
|
||||||
{
|
|
||||||
/* Open the /dev/vcsX and /dev/vcsaX devices */
|
|
||||||
vcs0 = open(vcs_device, O_RDONLY);
|
|
||||||
if (vcs0 < 0) {
|
|
||||||
report(RPT_ERR, "Could not open %s: %s", vcs_device, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
vcsa = open(vcsa_device, O_RDONLY);
|
|
||||||
if (vcsa < 0) {
|
|
||||||
report(RPT_ERR, "Could not open %s: %s", vcsa_device, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int read_vcdata(void)
|
|
||||||
{
|
|
||||||
unsigned short new_vc_height;
|
|
||||||
unsigned short new_vc_width;
|
|
||||||
|
|
||||||
int bytes_read;
|
|
||||||
unsigned char buf[20];
|
|
||||||
|
|
||||||
/* Read size and cursor position from /dev/vcsa */
|
|
||||||
lseek(vcsa, 0, SEEK_SET);
|
|
||||||
bytes_read = read(vcsa, buf, 4);
|
|
||||||
if (bytes_read != 4) {
|
|
||||||
report(RPT_ERR, "Could not read from %s", vcsa_device);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
new_vc_height = buf[0];
|
|
||||||
new_vc_width = buf[1];
|
|
||||||
vc_cursor_x = buf[2];
|
|
||||||
vc_cursor_y = buf[3];
|
|
||||||
|
|
||||||
/* Screen resize or initial buffer allocation ? */
|
|
||||||
if ((new_vc_width != vc_width) || (new_vc_height != vc_height)) {
|
|
||||||
vc_width = new_vc_width;
|
|
||||||
vc_height = new_vc_height;
|
|
||||||
|
|
||||||
if (vc_width * vc_height > 0) {
|
|
||||||
vc_buf = realloc(vc_buf, vc_width * vc_height);
|
|
||||||
|
|
||||||
if (vc_buf == NULL) {
|
|
||||||
report(RPT_ERR, "malloc failure: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(vc_buf, ' ', vc_width * vc_height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read characters from /dev/cvs0 */
|
|
||||||
lseek(vcs0, 0, SEEK_SET);
|
|
||||||
bytes_read = read(vcs0, vc_buf, vc_width * vc_height);
|
|
||||||
if (bytes_read != vc_width * vc_height) {
|
|
||||||
report(RPT_ERR, "Could not read from %s", vcs_device);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#ifndef VC_LINK_H
|
|
||||||
#define VC_LINK_H
|
|
||||||
|
|
||||||
extern unsigned short vc_width, vc_height;
|
|
||||||
extern unsigned short vc_cursor_x, vc_cursor_y;
|
|
||||||
extern char *vc_buf;
|
|
||||||
|
|
||||||
int open_vcs(void);
|
|
||||||
int read_vcdata(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in
|
|
||||||
|
|
||||||
bin_SCRIPTS = lcdmetar.pl
|
|
||||||
|
|
||||||
EXTRA_DIST = $(bin_SCRIPTS)
|
|
||||||
|
|
||||||
## EOF
|
|
||||||
@@ -1,260 +0,0 @@
|
|||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# Following is the POD documentation, type perldoc lcdmetar.pl to read it.
|
|
||||||
=pod
|
|
||||||
|
|
||||||
=head1 NAME
|
|
||||||
|
|
||||||
lcdMetar - Fetches METAR Weather information and send it to LCDproc.
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
|
||||||
|
|
||||||
B<lcdmetar.pl> [I<METAR-Code>]
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
B<lcdMetar> is a program to fetch METAR Weather information (e.g.
|
|
||||||
temperature) from a nearby (or not) airport using Geo::METAR and the
|
|
||||||
LWP modules.
|
|
||||||
|
|
||||||
Given an airport site code on the command line, lcdMetar
|
|
||||||
fetches the current weather observations,
|
|
||||||
and displays them via LCDproc (http://lcdproc.omnipotent.net/)
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<METAR-Code>
|
|
||||||
|
|
||||||
The METAR code related of the city you want weather observations.
|
|
||||||
|
|
||||||
For fun, here are some example METAR codes:
|
|
||||||
LA : KLAX
|
|
||||||
Dallas : KDFW
|
|
||||||
Detroit: KDTW
|
|
||||||
Chicago: KMDW
|
|
||||||
Graz/Austria (Thalerhof) : LOWG
|
|
||||||
Quebec City: CYQB
|
|
||||||
|
|
||||||
More informations about METAR codes is available at:
|
|
||||||
http://www.nws.noaa.gov/oso/oso1/oso12/metar.htm
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 DIAGNOSTICS
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item Cannot connect to LCDproc port
|
|
||||||
|
|
||||||
By default, lcdMetar tries to connect to localhost port 13666. If you get this
|
|
||||||
error, that means that this is not possible to connect to this port. You can change
|
|
||||||
the port lcdMetar connects to by modifying the script's variables $host and $port.
|
|
||||||
|
|
||||||
=item METAR is too short! Something went wrong.
|
|
||||||
|
|
||||||
The METAR data we received is not what we expected, check out NOOA's web site
|
|
||||||
(http://weather.noaa.gov/) to see if something has changed.
|
|
||||||
|
|
||||||
=item Can't connect to METAR source
|
|
||||||
|
|
||||||
lcdMetar tried to fetch weather observations from NOAA's web site and failed. It
|
|
||||||
will retry in 15 minutes.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head1 REQUIRES
|
|
||||||
|
|
||||||
Perl 5.004, Geo::METAR, LWP::Simple;
|
|
||||||
|
|
||||||
These are all available on CPAN: http://www.cpan.org/
|
|
||||||
|
|
||||||
=head1 DISCLAMER
|
|
||||||
|
|
||||||
Data distribution via the Internet is not considered an operational
|
|
||||||
delivery mechanism by the NWS due to our inability to insure access
|
|
||||||
to this service, therefore, the information available here shall not
|
|
||||||
be used for flight planning or other operational purposes.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License version 2 as
|
|
||||||
published by the Free Software Foundation.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
|
|
||||||
=head1 BUGS
|
|
||||||
|
|
||||||
Yes, there might be some. Please report any one you find to LCDproc's mailing list.
|
|
||||||
See the website for more informations.
|
|
||||||
|
|
||||||
=head1 WEBSITE
|
|
||||||
|
|
||||||
Visit B<http://www.lcdproc.org/> for more infos and the lastest version.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use Geo::METAR;
|
|
||||||
use LWP::Simple;
|
|
||||||
use IO::Socket;
|
|
||||||
use Fcntl;
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# Configurable part. Set it according your setup.
|
|
||||||
############################################################
|
|
||||||
|
|
||||||
# Verbose
|
|
||||||
# 0 : None (only fatal errors)
|
|
||||||
# 1 : Warnings
|
|
||||||
# 5 : Explain every step.
|
|
||||||
my $verbose = 1;
|
|
||||||
|
|
||||||
# METAR Code for your city/region.
|
|
||||||
my $site_code;
|
|
||||||
|
|
||||||
# Host which runs lcdproc daemon (LCDd)
|
|
||||||
my $host = "localhost";
|
|
||||||
|
|
||||||
# Port on which LCDd listens to requests
|
|
||||||
my $port = "13666";
|
|
||||||
|
|
||||||
# Metric or English data system?
|
|
||||||
# Can be either "metric", "nautical" or "english"
|
|
||||||
my $datasystem = "metric";
|
|
||||||
|
|
||||||
############################################################
|
|
||||||
# End of user configurable parts
|
|
||||||
############################################################
|
|
||||||
$SIG{INT} = \&grace;
|
|
||||||
$SIG{TERM} = \&grace;
|
|
||||||
|
|
||||||
# Get the site code.
|
|
||||||
$site_code = shift @ARGV || $site_code;
|
|
||||||
die "Usage: $0 <site_code>\n" unless $site_code;
|
|
||||||
|
|
||||||
# Connect to the server...
|
|
||||||
print "Connecting to LCDproc at $host\n" if ($verbose >= 5);
|
|
||||||
my $remote = IO::Socket::INET->new(
|
|
||||||
Proto => "tcp",
|
|
||||||
PeerAddr => $host,
|
|
||||||
PeerPort => $port,
|
|
||||||
) or die "Cannot connect to LCDproc port\n";
|
|
||||||
|
|
||||||
# Make sure our messages get there right away
|
|
||||||
$remote->autoflush(1);
|
|
||||||
|
|
||||||
sleep 1; # Give server plenty of time to notice us...
|
|
||||||
|
|
||||||
print $remote "hello\n";
|
|
||||||
my $lcdconnect = <$remote>;
|
|
||||||
print $lcdconnect if ($verbose >= 5);
|
|
||||||
# connect LCDproc 0.4.2 protocol 0.3 lcd wid 20 hgt 4 cellwid 5 cellhgt 8
|
|
||||||
($lcdconnect =~ /lcd.+wid\s+(\d+)\s+hgt\s+(\d+)/);
|
|
||||||
my $lcdwidth = $1; my $lcdheight= $2;
|
|
||||||
print "Detected LCD size of $lcdwidth x $lcdheight\n" if ($verbose >= 5);
|
|
||||||
|
|
||||||
# Turn off blocking mode...
|
|
||||||
fcntl($remote, F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
# Set up some screen widgets...
|
|
||||||
print $remote "client_set name {Metar}\n";
|
|
||||||
print $remote "screen_add metar\n";
|
|
||||||
print $remote "screen_set metar name {Metar}\n";
|
|
||||||
print $remote "widget_add metar title title\n";
|
|
||||||
print $remote "widget_set metar title {Weather $site_code}\n";
|
|
||||||
print $remote "widget_add metar temp string\n";
|
|
||||||
print $remote "widget_add metar wind string\n";
|
|
||||||
print $remote "widget_add metar visib scroller\n";
|
|
||||||
print $remote "widget_add metar cloud string\n" if ($lcdheight > 4);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
# fetch weather information
|
|
||||||
print "Fetching weather information\n" if ($verbose >= 5);
|
|
||||||
my $data = get("http://weather.noaa.gov/cgi-bin/mgetmetar.pl?cccc=$site_code");
|
|
||||||
|
|
||||||
if (not $data) {
|
|
||||||
warn "Can't connect to METAR source." if ($verbose >= 1);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
# Yep, get the data and find the METAR.
|
|
||||||
|
|
||||||
my $m = new Geo::METAR;
|
|
||||||
$data =~ s/\n//go; # remove newlines
|
|
||||||
$data =~ m/($site_code\s\d+Z.*?)</go; # find the METAR string
|
|
||||||
my $metar = $1; # keep it
|
|
||||||
|
|
||||||
# Sanity check
|
|
||||||
die "METAR is too short! Something went wrong." if (length($metar)<1);
|
|
||||||
|
|
||||||
# pass the data to the METAR module.
|
|
||||||
# print("$metar\n");
|
|
||||||
$m->metar($metar);
|
|
||||||
|
|
||||||
# ask for the temperature(s)
|
|
||||||
my $temp; my $temp_u; my $dew; my $dew_u; my $wind; my $wind_u; my $wind_dir;
|
|
||||||
|
|
||||||
if ($datasystem eq "nautical") {
|
|
||||||
$temp = $m->C_TEMP;
|
|
||||||
$temp_u = "C";
|
|
||||||
$dew = $m->C_DEW;
|
|
||||||
$dew_u = "C";
|
|
||||||
$wind = $m->WIND_KTS;
|
|
||||||
$wind_u = " Knots";
|
|
||||||
$wind_dir = $m->WIND_DIR_DEG ."deg";
|
|
||||||
} elsif ($datasystem eq "english") {
|
|
||||||
$temp = $m->F_TEMP;
|
|
||||||
$temp_u = "F";
|
|
||||||
$dew = $m->F_DEW;
|
|
||||||
$dew_u = "F";
|
|
||||||
$wind = $m->WIND_MPH;
|
|
||||||
$wind_u = "mph";
|
|
||||||
$wind_dir = $m->WIND_DIR_ENG;
|
|
||||||
} else {
|
|
||||||
# Default: metric system (aka: international system)
|
|
||||||
$temp = $m->C_TEMP;
|
|
||||||
$temp_u = "C";
|
|
||||||
$dew = $m->C_DEW;
|
|
||||||
$dew_u = "C";
|
|
||||||
$wind = $m->WIND_MPH * 1.609344;
|
|
||||||
$wind_u = "km/h";
|
|
||||||
$wind_dir = $m->WIND_DIR_ENG;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $metartime = $m->TIME;
|
|
||||||
my $sky = $m->SKY;
|
|
||||||
my $visibility = $m->VISIBILITY;
|
|
||||||
|
|
||||||
print $remote sprintf("widget_set metar title {Weather %s %s}\n", $site_code, $metartime);
|
|
||||||
print $remote sprintf("widget_set metar temp 1 2 {Temp %i%s (%i%s Dew)}\n", $temp, $temp_u, $dew, $dew_u) if ($temp and $dew);
|
|
||||||
print $remote sprintf("widget_set metar wind 1 3 {Wind %i%s, %s}\n", $wind, $wind_u, $wind_dir) if ($wind_dir and $wind);
|
|
||||||
print $remote sprintf("widget_set metar visib 1 %i %i %i h 3 {Visibility %s}\n", $lcdheight, $lcdwidth, $lcdheight, $visibility ) if ($visibility);
|
|
||||||
print $remote sprintf("widget_set metar cloud 1 4 {Sky %s}\n", join(',', @{$m->{sky}}) ) if ($m->{sky} and ($lcdheight>4));
|
|
||||||
} # end else
|
|
||||||
|
|
||||||
# eat all input from LCDd
|
|
||||||
while(defined(my $input = <$remote>)) { }
|
|
||||||
|
|
||||||
print "Sleeping for 15 minutes.\n" if ($verbose >= 5);
|
|
||||||
sleep 900;
|
|
||||||
}
|
|
||||||
# Should never go there since above is an infinite loop,
|
|
||||||
# send a SIGINT or SIGTERM to exit nicely.
|
|
||||||
|
|
||||||
# To be called on exit and on SIGINT or SIGTERM.
|
|
||||||
sub grace() {
|
|
||||||
print "Exiting...\n" if ($verbose >= 5);
|
|
||||||
close($remote);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
__END__
|
|
||||||
-531
@@ -1,531 +0,0 @@
|
|||||||
# -*- mode: m4; -*-
|
|
||||||
dnl Process this file with autoconf 2.61 (or higher) to produce a configure script.
|
|
||||||
AC_PREREQ(2.61)
|
|
||||||
AC_INIT([lcdproc], [0.5dev], [lcdproc@lists.omnipotent.net])
|
|
||||||
AC_CONFIG_SRCDIR([clients/lcdproc/batt.c])
|
|
||||||
AM_INIT_AUTOMAKE
|
|
||||||
|
|
||||||
AC_CONFIG_HEADERS(config.h)
|
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
|
||||||
case "$host" in
|
|
||||||
*-*-*linux*) dnl i586-pc-linux-gnu
|
|
||||||
AC_DEFINE([LINUX],[1],[Define if you're using Linux.])
|
|
||||||
ac_system_host=Linux
|
|
||||||
;;
|
|
||||||
*-*-*solaris*)
|
|
||||||
AC_DEFINE([SOLARIS],[1],[Define if you're using Solaris.])
|
|
||||||
ac_system_host=Solaris
|
|
||||||
;;
|
|
||||||
*-*-*openbsd*) dnl i386-unknown-openbsd3.0
|
|
||||||
AC_DEFINE([OPENBSD],[1],[Define if you're using OpenBSD.])
|
|
||||||
ac_system_host=OpenBSD
|
|
||||||
;;
|
|
||||||
*-*-*netbsd*)
|
|
||||||
AC_DEFINE([NETBSD],[1],[Define if you're using NetBSD.])
|
|
||||||
ac_system_host=NetBSD
|
|
||||||
;;
|
|
||||||
*-*-*freebsd*)
|
|
||||||
AC_DEFINE([FREEBSD],[1],[Define if you're using FreeBSD.])
|
|
||||||
ac_system_host=FreeBSD
|
|
||||||
;;
|
|
||||||
*-*-*darwin*)
|
|
||||||
AC_DEFINE([DARWIN],[1],[Define if you're using Darwin/Mac OS X.])
|
|
||||||
ac_system_host=Darwin
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AC_DEFINE_UNQUOTED([SYSTEM_HOST], [$ac_system_host], [Set this to your system host (Linux, Solaris, OpenBSD, NetBSD, FreeBSD or Darwin)])
|
|
||||||
|
|
||||||
dnl treat Darwin special in Makefiles
|
|
||||||
AM_CONDITIONAL(DARWIN, test x$ac_system_host = xDarwin)
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether to enable debugging])
|
|
||||||
AC_ARG_ENABLE(debug,
|
|
||||||
[AS_HELP_STRING([--enable-debug], [show debug information])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
AC_DEFINE(DEBUG, [1], [Define to 1 to show debug information])
|
|
||||||
debug="yes"
|
|
||||||
else
|
|
||||||
debug="no"
|
|
||||||
fi ],
|
|
||||||
[ debug=no ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($debug)
|
|
||||||
|
|
||||||
if test $debug = "yes"; then
|
|
||||||
dnl Enable debugging information with minimal optimisation if not set differently
|
|
||||||
dnl (the spaces before $CFLAGS and -O are significant)
|
|
||||||
CFLAGS="$CFLAGS -g"
|
|
||||||
if ! echo " $CFLAGS" | grep -q -- " -O" ; then
|
|
||||||
CFLAGS="$CFLAGS -O"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
dnl Maximum optimisation if not already set
|
|
||||||
dnl (the spaces before $CFLAGS and -O are significant)
|
|
||||||
if ! echo " $CFLAGS" | grep -q -- " -O" ; then
|
|
||||||
CFLAGS="$CFLAGS -O3"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Checks for programs used in building
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_CPP
|
|
||||||
AC_PROG_INSTALL
|
|
||||||
AC_PROG_RANLIB
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_PATH_PROG([XMLTO], [xmlto], [no])
|
|
||||||
|
|
||||||
dnl Avoid unused static function warnings
|
|
||||||
CFLAGS="-Wall $CFLAGS"
|
|
||||||
AX_CFLAGS_GCC_OPTION(-Wno-unused-function)
|
|
||||||
AX_CFLAGS_GCC_OPTION(-ftrampolines)
|
|
||||||
export CFLAGS
|
|
||||||
|
|
||||||
dnl Solaris
|
|
||||||
AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
|
|
||||||
AC_CHECK_FUNC(connect,,[AC_CHECK_LIB(socket,connect)])
|
|
||||||
AC_CHECK_FUNC(inet_aton,,[AC_CHECK_LIB(resolv,inet_aton)])
|
|
||||||
AC_CHECK_LIB(kstat, kstat_open)
|
|
||||||
AC_CHECK_LIB(posix4, nanosleep)
|
|
||||||
AC_CHECK_FUNCS(getloadavg swapctl)
|
|
||||||
AC_CHECK_HEADERS(procfs.h sys/procfs.h sys/loadavg.h utmpx.h)
|
|
||||||
|
|
||||||
dnl Some versions of Solaris require -lelf for -lkvm
|
|
||||||
AC_CHECK_LIB(kvm, kvm_open,[
|
|
||||||
LIBS="-lkvm $LIBS"
|
|
||||||
],[AC_MSG_CHECKING([for kvm_open in -lkvm with -lelf])
|
|
||||||
AC_CACHE_VAL(ac_cv_lib_kvm_with_elf,
|
|
||||||
[ac_save_LIBS="$LIBS"
|
|
||||||
LIBS="-lkvm -lelf $LIBS"
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[char kvm_open();]], [[kvm_open()]])],[ac_cv_lib_kvm_with_elf=yes],[ac_cv_lib_kvm_with_elf=no])
|
|
||||||
LIBS="$ac_save_LIBS"
|
|
||||||
])
|
|
||||||
if test "$ac_cv_lib_kvm_with_elf" = "yes"; then
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
LIBS="-lkvm -lelf $LIBS"
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl NetBSD, OpenBSD and FreeBSD
|
|
||||||
AC_CHECK_HEADERS(sched.h sys/types.h machine/pio.h machine/sysarch.h sys/cpuvar.h machine/apm_bios.h)
|
|
||||||
ETR_SYSV_IPC
|
|
||||||
ETR_UNION_SEMUN
|
|
||||||
|
|
||||||
dnl machine/cpufunc.h needs additional header on FreeBSD
|
|
||||||
AC_CHECK_HEADERS([machine/cpufunc.h], [], [],
|
|
||||||
[[#if HAVE_SYS_TYPES_H
|
|
||||||
# include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
]])
|
|
||||||
|
|
||||||
dnl sched_setscheduler on OpenBSD
|
|
||||||
AC_CHECK_FUNCS(sched_setscheduler)
|
|
||||||
AC_CHECK_LIB(posix4, sched_setscheduler, [
|
|
||||||
AC_DEFINE([HAVE_SCHED_SETSCHEDULER], [1],
|
|
||||||
[Define if you have the sched_setscheduler function.])
|
|
||||||
])
|
|
||||||
AC_CHECK_LIB(rt, sched_setscheduler, [
|
|
||||||
AC_DEFINE([HAVE_SCHED_SETSCHEDULER], [1],
|
|
||||||
[Define if you have the sched_setscheduler function.])
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl i386_get_ioperm on NetBSD&OpenBSD
|
|
||||||
AC_CHECK_LIB(i386, i386_get_ioperm,
|
|
||||||
LIBS="-li386 $LIBS"
|
|
||||||
AC_DEFINE([HAVE_I386_IOPERM_NETBSD], [1],
|
|
||||||
[Define if you have the NetBSD&OpenBSD version of i386_ioperm functions.]),[
|
|
||||||
dnl i386_get_ioperm on FreeBSD
|
|
||||||
AC_CHECK_LIB(c, i386_get_ioperm,
|
|
||||||
AC_DEFINE([HAVE_I386_IOPERM_FREEBSD],[1],
|
|
||||||
[Define if you have the FreeBSD version of the i386_ioperm functions.]),
|
|
||||||
[])]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_CHECK_FUNCS(iopl)
|
|
||||||
AC_CHECK_FUNCS(ioperm)
|
|
||||||
AC_CHECK_HEADERS(sys/io.h)
|
|
||||||
|
|
||||||
dnl Check if we support this parallel (LPT) port
|
|
||||||
dnl IMPORTANT: we must do all the checks used in port.h before doing this test!
|
|
||||||
AC_CACHE_CHECK([for a parallel port], ac_cv_port_have_lpt,
|
|
||||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "${srcdir}/server/drivers/port.h"]],
|
|
||||||
[[char val = port_in(0x350)]])],
|
|
||||||
[ac_cv_port_have_lpt=yes],[ac_cv_port_have_lpt=no])])
|
|
||||||
|
|
||||||
if test "$ac_cv_port_have_lpt" = yes; then
|
|
||||||
AC_DEFINE([HAVE_PCSTYLE_LPT_CONTROL], [1],
|
|
||||||
[Define if you have a parallel port and LCDproc knows how to talk to it.])
|
|
||||||
else
|
|
||||||
AC_MSG_WARN([Cannot talk to the parallel port, disabling drivers that use it.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
x_ac_have_i2c=no
|
|
||||||
AC_CHECK_HEADERS([linux/i2c-dev.h dev/iicbus/iic.h], [x_ac_have_i2c=yes])
|
|
||||||
if test "$x_ac_have_i2c" = yes; then
|
|
||||||
AC_DEFINE(HAVE_I2C,[1],[Define to 1 if you have the i2c headers])
|
|
||||||
fi
|
|
||||||
|
|
||||||
x_ac_have_spi=no
|
|
||||||
AC_CHECK_HEADERS([linux/spi/spidev.h], [x_ac_have_spi=yes])
|
|
||||||
if test "$x_ac_have_spi" = yes; then
|
|
||||||
AC_DEFINE(HAVE_SPI,[1],[Define to 1 if you have the spi headers])
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl Checks for header files.
|
|
||||||
AC_HEADER_DIRENT
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h unistd.h sys/io.h errno.h)
|
|
||||||
AC_CHECK_HEADERS(limits.h kvm.h sys/param.h sys/dkstat.h stdbool.h)
|
|
||||||
|
|
||||||
dnl check sys/sysctl.h seperately, as it requires other headers on at least OpenBSD
|
|
||||||
AC_CHECK_HEADERS([sys/sysctl.h], [], [],
|
|
||||||
[[#if HAVE_SYS_PARAM_H
|
|
||||||
# include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
]])
|
|
||||||
|
|
||||||
dnl On FreeBSD >= 8 checking sys/pcpu.h fails without sys/param.h and kvm.h
|
|
||||||
AC_CHECK_HEADERS([sys/pcpu.h], [], [],
|
|
||||||
[[#if HAVE_SYS_PARAM_H
|
|
||||||
# include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_KVM_H
|
|
||||||
# include <kvm.h>
|
|
||||||
#endif
|
|
||||||
]])
|
|
||||||
|
|
||||||
|
|
||||||
dnl Check for particular preprocessor macros
|
|
||||||
LCD_SA_RESTART
|
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
|
||||||
AC_C_CONST
|
|
||||||
AC_C_INLINE
|
|
||||||
AC_TYPE_SIZE_T
|
|
||||||
AC_HEADER_TIME
|
|
||||||
AC_STRUCT_TM
|
|
||||||
AC_TYPE_UID_T
|
|
||||||
|
|
||||||
dnl Checks for library functions.
|
|
||||||
AC_PROG_GCC_TRADITIONAL
|
|
||||||
AC_TYPE_SIGNAL
|
|
||||||
AC_CHECK_FUNCS(select socket strdup strerror strtol uname cfmakeraw snprintf)
|
|
||||||
|
|
||||||
dnl Many people on non-GNU/Linux systems don't have getopt
|
|
||||||
AC_CONFIG_LIBOBJ_DIR(shared)
|
|
||||||
AC_CHECK_FUNC(getopt,
|
|
||||||
[
|
|
||||||
AC_ARG_WITH(included-getopt,
|
|
||||||
[AS_HELP_STRING([--with-included-getopt], [Use the included getopt rather than glibc's])],
|
|
||||||
with_getopt=$withval,
|
|
||||||
with_getopt=$no)
|
|
||||||
if test "x$with_getopt" = xyes; then
|
|
||||||
AC_LIBOBJ(getopt)
|
|
||||||
AC_LIBOBJ(getopt1)
|
|
||||||
fi
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AC_LIBOBJ(getopt)
|
|
||||||
AC_LIBOBJ(getopt1)
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
dnl Check how to find the mtab file and how to get filesystem staticstics
|
|
||||||
AC_FIND_MTAB_FILE
|
|
||||||
AC_GET_FS_INFO
|
|
||||||
|
|
||||||
|
|
||||||
dnl Check for various defines and features
|
|
||||||
AC_ARG_WITH(lcdport,
|
|
||||||
[AS_HELP_STRING([--with-lcdport=<port>], [the server port [13666]])],
|
|
||||||
LCDPORT=$withval,
|
|
||||||
LCDPORT="13666"
|
|
||||||
)
|
|
||||||
AC_DEFINE_UNQUOTED(LCDPORT, $LCDPORT, [Set default port where LCDd should listen])
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(PROTOCOL_VERSION, "0.3", [Define version of lcdproc client-server protocol])
|
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(API_VERSION, "0.5", [Define version of lcdproc API])
|
|
||||||
|
|
||||||
|
|
||||||
dnl Check compiler flags to dynamically load modules
|
|
||||||
AC_MODULES_INFO
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl libusb support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if libusb support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(libusb,
|
|
||||||
[AS_HELP_STRING([--disable-libusb],[disable USB support using libusb])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_libusb=yes
|
|
||||||
fi ],
|
|
||||||
[ enable_libusb=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_libusb)
|
|
||||||
|
|
||||||
if test "$enable_libusb" = "yes"; then
|
|
||||||
ifdef([PKG_CHECK_MODULES],
|
|
||||||
[PKG_CHECK_MODULES(LIBUSB, libusb,
|
|
||||||
[AC_DEFINE(HAVE_LIBUSB, [1], [Define to 1 if you have libusb])],
|
|
||||||
[ enable_libusb=no ])],
|
|
||||||
[AC_MSG_WARN([pkg-config not (fully) installed; drivers requiring libusb may not be built])])
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBUSB_LIBS)
|
|
||||||
AC_SUBST(LIBUSB_CFLAGS)
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl libusb-1.0 support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if libusb-1-0 support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(libusb_1_0,
|
|
||||||
[AS_HELP_STRING([--disable-libusb-1-0],[disable USB support using libusb-1.0])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_libusb_1_0="yes"
|
|
||||||
fi ],
|
|
||||||
[ enable_libusb_1_0=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_libusb_1_0)
|
|
||||||
|
|
||||||
if test "$enable_libusb_1_0" = "yes"; then
|
|
||||||
ifdef([PKG_CHECK_MODULES],
|
|
||||||
[PKG_CHECK_MODULES(LIBUSB_1_0, libusb-1.0 >= 1.0,
|
|
||||||
[AC_DEFINE(HAVE_LIBUSB_1_0, [1], [Define to 1 if you have libusb-1.0])],
|
|
||||||
[ enable_libusb_1_0=no ])],
|
|
||||||
[AC_MSG_WARN([pkg-config not (fully) installed; drivers requiring libusb-1.0 may not be built])])
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBUSB_1_0_LIBS)
|
|
||||||
AC_SUBST(LIBUSB_1_0_CFLAGS)
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl libftdi support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if libftdi support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(libftdi,
|
|
||||||
[AS_HELP_STRING([--disable-libftdi],[disable FTDI support using libftdi])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_libftdi=yes
|
|
||||||
fi ],
|
|
||||||
[ enable_libftdi=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_libftdi)
|
|
||||||
|
|
||||||
if test "$enable_libftdi" = "yes"; then
|
|
||||||
ifdef([PKG_CHECK_MODULES],
|
|
||||||
[PKG_CHECK_MODULES(LIBFTDI, libftdi >= 0.8,
|
|
||||||
[AC_DEFINE(HAVE_LIBFTDI, [1], [Define to 1 if you have libftdi])],
|
|
||||||
[ enable_libftdi=no ])],
|
|
||||||
[AC_MSG_WARN([pkg-config not (fully) installed; drivers requiring libftdi may not be built])])
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBFTDI_LIBS)
|
|
||||||
AC_SUBST(LIBFTDI_CFLAGS)
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl X11 library support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if X11 support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(libX11,
|
|
||||||
[AS_HELP_STRING([--disable-libX11],[disable X11 support])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_libX11=yes
|
|
||||||
fi ],
|
|
||||||
[ enable_libX11=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_libX11)
|
|
||||||
|
|
||||||
if test "$enable_libX11" = "yes"; then
|
|
||||||
ifdef([PKG_CHECK_MODULES],
|
|
||||||
[PKG_CHECK_MODULES([LIBX11], [x11],
|
|
||||||
[AC_DEFINE(HAVE_LIBX11, [1], [Define to 1 if you have X11 library])],
|
|
||||||
[ enable_libX11=no ])],
|
|
||||||
[AC_MSG_WARN([pkg-config not (fully) installed; drivers requiring X11 may not be built])])
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBX11_LIBS)
|
|
||||||
AC_SUBST(LIBX11_CFLAGS)
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl libhid support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if libhid support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(libhid,
|
|
||||||
[AS_HELP_STRING([--disable-libhid],[disable HID support using libhid])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_libhid=yes
|
|
||||||
fi ],
|
|
||||||
[ enable_libhid=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_libhid)
|
|
||||||
|
|
||||||
if test "$enable_libhid" = "yes"; then
|
|
||||||
ifdef([PKG_CHECK_MODULES],
|
|
||||||
[PKG_CHECK_MODULES(LIBHID, libhid >= 0.2.16,
|
|
||||||
[AC_DEFINE(HAVE_LIBHID, [1], [Define to 1 if you have libhid])],
|
|
||||||
[ enable_libhid=no ])],
|
|
||||||
[AC_MSG_WARN([pkg-config not (fully) installed; drivers requiring libhid may not be built])])
|
|
||||||
fi
|
|
||||||
AC_SUBST(LIBHID_LIBS)
|
|
||||||
AC_SUBST(LIBHID_CFLAGS)
|
|
||||||
|
|
||||||
# PNG library
|
|
||||||
LCD_PNG_LIB
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl freetype support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if freetype support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(freetype,
|
|
||||||
[AS_HELP_STRING([--disable-freetype],[disable freetype support])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_freetype=yes
|
|
||||||
fi ],
|
|
||||||
[ enable_freetype=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_freetype)
|
|
||||||
|
|
||||||
if test "$enable_freetype" = "yes"; then
|
|
||||||
ifdef([AC_CHECK_FT2],
|
|
||||||
[AC_CHECK_FT2([],
|
|
||||||
[AC_DEFINE(HAVE_FT2, [1], [Define to 1 if you have freetype])],
|
|
||||||
[enable_freetype=no])],
|
|
||||||
[AC_MSG_WARN([freetype does not seem to be installed])])
|
|
||||||
fi
|
|
||||||
AC_SUBST([FT2_CFLAGS])
|
|
||||||
AC_SUBST([FT2_LIBS])
|
|
||||||
|
|
||||||
|
|
||||||
dnl ######################################################################
|
|
||||||
dnl ethlcd support
|
|
||||||
dnl ######################################################################
|
|
||||||
AC_MSG_CHECKING([if ethlcd support has been enabled]);
|
|
||||||
AC_ARG_ENABLE(ethlcd,
|
|
||||||
[AS_HELP_STRING([--disable-ethlcd],[disable ethlcd connection type for HD44780])],
|
|
||||||
[ if test "$enableval" != "no"; then
|
|
||||||
enable_ethlcd=yes
|
|
||||||
fi ],
|
|
||||||
[ enable_ethlcd=yes ]
|
|
||||||
)
|
|
||||||
AC_MSG_RESULT($enable_ethlcd)
|
|
||||||
|
|
||||||
|
|
||||||
# check for doxygen
|
|
||||||
BB_ENABLE_DOXYGEN
|
|
||||||
|
|
||||||
|
|
||||||
# Select drivers to build
|
|
||||||
LCD_DRIVERS_SELECT
|
|
||||||
|
|
||||||
|
|
||||||
# directory for PID files
|
|
||||||
pidfiledir=/var/run
|
|
||||||
# make sure the directory exists
|
|
||||||
if test ! -d $pidfiledir ; then
|
|
||||||
pidfiledir=`eval echo ${sysconfdir}`
|
|
||||||
case $pidfiledir in
|
|
||||||
NONE/*) pidfiledir=`echo $pidfiledir | sed "s~NONE~$ac_default_prefix~"` ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_ARG_WITH(pidfile-dir,
|
|
||||||
[AS_HELP_STRING([--with-pidfile-dir=PATH], [specify location of pid files [/var/run]])],
|
|
||||||
[ if test -n "$withval" && test "x$withval" != "xno" && \
|
|
||||||
test "x${withval}" != "xyes"; then
|
|
||||||
pidfiledir=$withval
|
|
||||||
if test ! -d $pidfiledir ; then
|
|
||||||
AC_MSG_WARN([** no $pidfiledir directory on this system **])
|
|
||||||
fi
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_SUBST(pidfiledir)
|
|
||||||
|
|
||||||
|
|
||||||
# Features applicable to the server
|
|
||||||
AC_ARG_ENABLE(seamless-hbars,
|
|
||||||
[AS_HELP_STRING([--enable-seamless-hbars], [no gaps in horizontal bar graphs (if HW supports it)])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(SEAMLESS_HBARS, [1],
|
|
||||||
[Define to 1 to avoid gaps in horizontal bar graphs (if HW supports it)])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(testmenus,
|
|
||||||
[AS_HELP_STRING([--enable-testmenus], [enable server test menus])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(LCDPROC_TESTMENUS, [1],
|
|
||||||
[Define to 1 to enable server test menus])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(permissive_menu_goto,
|
|
||||||
[AS_HELP_STRING([--enable-permissive-menu-goto], [allow transitions between different client's menus])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(LCDPROC_PERMISSIVE_MENU_GOTO, [1],
|
|
||||||
[Define to 1 to allow transitions between different client's menus])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
dnl Features applicable to the lcdproc client
|
|
||||||
AC_ARG_ENABLE(lcdproc-menus,
|
|
||||||
[AS_HELP_STRING([--enable-lcdproc-menus], [enable menu support in lcdproc client])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(LCDPROC_MENUS, [1],
|
|
||||||
[Define to 1 to enable menu support in lcdproc client])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(stat-nfs,
|
|
||||||
[AS_HELP_STRING([--enable-stat-nfs], [display NFS filesystem stats in lcdproc client])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(STAT_NFS, [1],
|
|
||||||
[Define to 1 to display NFS filesystem stats in lcdproc client])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(stat-smbfs,
|
|
||||||
[AS_HELP_STRING([--enable-stat-smbfs], [display SMBFS filesystem stats in lcdproc client])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(STAT_SMBFS, [1],
|
|
||||||
[Define to 1 to display SMBFS filesystem stats in lcdproc client])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(extra-charmaps,
|
|
||||||
[AS_HELP_STRING([--enable-extra-charmaps],
|
|
||||||
[enable additional character mapping tables in drivers])],
|
|
||||||
[ if test "$enableval" != "no" ; then
|
|
||||||
AC_DEFINE(EXTRA_CHARMAPS, [1],
|
|
||||||
[Define to 1 to enable additional charmaps in drivers])
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
|
||||||
shared/Makefile
|
|
||||||
server/Makefile
|
|
||||||
server/commands/Makefile
|
|
||||||
server/drivers/Makefile
|
|
||||||
clients/Makefile
|
|
||||||
clients/lcdproc/Makefile
|
|
||||||
clients/lcdexec/Makefile
|
|
||||||
clients/lcdvc/Makefile
|
|
||||||
clients/examples/Makefile
|
|
||||||
clients/metar/Makefile
|
|
||||||
docs/Makefile
|
|
||||||
docs/Doxyfile
|
|
||||||
docs/lcdproc-dev/Makefile
|
|
||||||
docs/lcdproc-user/Makefile
|
|
||||||
docs/lcdproc-user/drivers/Makefile
|
|
||||||
scripts/Makefile
|
|
||||||
scripts/init-LCDd.LSB
|
|
||||||
scripts/init-lcdproc.LSB
|
|
||||||
scripts/init-lcdexec.LSB
|
|
||||||
scripts/init-lcdvc.LSB
|
|
||||||
scripts/init-LCDd.debian
|
|
||||||
scripts/init-lcdproc.debian
|
|
||||||
scripts/init-lcdexec.debian
|
|
||||||
scripts/init-lcdvc.debian
|
|
||||||
scripts/init-LCDd.rpm
|
|
||||||
scripts/init-lcdproc.rpm])
|
|
||||||
AC_OUTPUT
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
CFLAGS=-Wall -g -MD
|
|
||||||
LDFLAGS=
|
|
||||||
CC=gcc
|
|
||||||
|
|
||||||
TARGET = if_demo
|
|
||||||
|
|
||||||
MEMBERS=${TARGET} lib-myconnect lib-mylcd interface af sockets nstrcmp util hw unix inet loopback ether tunnel ppp frame arcnet
|
|
||||||
|
|
||||||
DEPS = $(patsubst %,%.d,$(MEMBERS))
|
|
||||||
OBJECTS = $(patsubst %,%.o,$(MEMBERS))
|
|
||||||
|
|
||||||
all: ${TARGET}
|
|
||||||
|
|
||||||
${TARGET}: ${OBJECTS}
|
|
||||||
${CC} -o ${TARGET} ${OBJECTS} ${CFLAGS} ${LDFLAGS}
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm *.o *.d ${TARGET}
|
|
||||||
|
|
||||||
-include ${DEPS}
|
|
||||||
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
From: Thomas Riewe <thomas.riewe@pyramid.de>
|
|
||||||
|
|
||||||
may be someone else will find our little testing setup also helpful ?!
|
|
||||||
|
|
||||||
i attached it to this mail (since it's just 28K though i didn't clean up the files ...)
|
|
||||||
and one can download it from the "Test/demo" link at
|
|
||||||
http://www.pyramid.de/en/products/programmable_lcd.php
|
|
||||||
respectively
|
|
||||||
http://www.pyramid.de/upload/files/divers/demo_for_pylcd-lcdproc.tgz
|
|
||||||
|
|
||||||
AFAIK it will be quite easy to adapt it to other LCDs
|
|
||||||
|
|
||||||
HTH & keep up the good work
|
|
||||||
|
|
||||||
regards,
|
|
||||||
thomas
|
|
||||||
@@ -1,345 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/af.c This file contains the top-level part of the protocol
|
|
||||||
* support functions module for the NET-2 base distribution.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
|
|
||||||
* Copyright 1993 MicroWalt Corporation
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "intl.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
int flag_unx;
|
|
||||||
int flag_ipx;
|
|
||||||
int flag_ax25;
|
|
||||||
int flag_ddp;
|
|
||||||
int flag_netrom;
|
|
||||||
int flag_inet;
|
|
||||||
int flag_inet6;
|
|
||||||
int flag_econet;
|
|
||||||
int flag_x25 = 0;
|
|
||||||
int flag_ash;
|
|
||||||
|
|
||||||
|
|
||||||
struct aftrans_t {
|
|
||||||
char *alias;
|
|
||||||
char *name;
|
|
||||||
int *flag;
|
|
||||||
} aftrans[] = {
|
|
||||||
|
|
||||||
{
|
|
||||||
"ax25", "ax25", &flag_ax25
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ip", "inet", &flag_inet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ip6", "inet6", &flag_inet6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ipx", "ipx", &flag_ipx
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"appletalk", "ddp", &flag_ddp
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"netrom", "netrom", &flag_netrom
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inet", "inet", &flag_inet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inet6", "inet6", &flag_inet6
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ddp", "ddp", &flag_ddp
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"unix", "unix", &flag_unx
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"tcpip", "inet", &flag_inet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"econet", "ec", &flag_econet
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"x25", "x25", &flag_x25
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ash", "ash", &flag_ash
|
|
||||||
},
|
|
||||||
{
|
|
||||||
0, 0, 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
char afname[256] = "";
|
|
||||||
|
|
||||||
extern struct aftype unspec_aftype;
|
|
||||||
extern struct aftype unix_aftype;
|
|
||||||
extern struct aftype inet_aftype;
|
|
||||||
extern struct aftype inet6_aftype;
|
|
||||||
extern struct aftype ax25_aftype;
|
|
||||||
extern struct aftype netrom_aftype;
|
|
||||||
extern struct aftype ipx_aftype;
|
|
||||||
extern struct aftype ddp_aftype;
|
|
||||||
extern struct aftype ec_aftype;
|
|
||||||
extern struct aftype x25_aftype;
|
|
||||||
extern struct aftype rose_aftype;
|
|
||||||
extern struct aftype ash_aftype;
|
|
||||||
|
|
||||||
static short sVafinit = 0;
|
|
||||||
|
|
||||||
struct aftype *aftypes[] =
|
|
||||||
{
|
|
||||||
#if HAVE_AFUNIX
|
|
||||||
&unix_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFINET
|
|
||||||
&inet_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFINET6
|
|
||||||
&inet6_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFAX25
|
|
||||||
&ax25_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFNETROM
|
|
||||||
&netrom_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFROSE
|
|
||||||
&rose_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
&ipx_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFATALK
|
|
||||||
&ddp_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFECONET
|
|
||||||
&ec_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFASH
|
|
||||||
&ash_aftype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFX25
|
|
||||||
&x25_aftype,
|
|
||||||
#endif
|
|
||||||
&unspec_aftype,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
void afinit()
|
|
||||||
{
|
|
||||||
unspec_aftype.title = _("UNSPEC");
|
|
||||||
#if HAVE_AFUNIX
|
|
||||||
unix_aftype.title = _("UNIX Domain");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFINET
|
|
||||||
inet_aftype.title = _("DARPA Internet");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFINET6
|
|
||||||
inet6_aftype.title = _("IPv6");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFAX25
|
|
||||||
ax25_aftype.title = _("AMPR AX.25");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFNETROM
|
|
||||||
netrom_aftype.title = _("AMPR NET/ROM");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
ipx_aftype.title = _("Novell IPX");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFATALK
|
|
||||||
ddp_aftype.title = _("Appletalk DDP");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFECONET
|
|
||||||
ec_aftype.title = _("Econet");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFX25
|
|
||||||
x25_aftype.title = _("CCITT X.25");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFROSE
|
|
||||||
rose_aftype.title = _("AMPR ROSE");
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFASH
|
|
||||||
ash_aftype.title = _("Ash");
|
|
||||||
#endif
|
|
||||||
sVafinit = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the default AF list from the program name or a constant value */
|
|
||||||
void aftrans_def(char *tool, char *argv0, char *dflt)
|
|
||||||
{
|
|
||||||
char *tmp;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
strcpy(afname, dflt);
|
|
||||||
|
|
||||||
if (!(tmp = strrchr(argv0, '/')))
|
|
||||||
tmp = argv0; /* no slash?! */
|
|
||||||
else
|
|
||||||
tmp++;
|
|
||||||
|
|
||||||
if (!(buf = strdup(tmp)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (strlen(tool) >= strlen(tmp)) {
|
|
||||||
free(buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tmp = buf + (strlen(tmp) - strlen(tool));
|
|
||||||
|
|
||||||
if (strcmp(tmp, tool) != 0) {
|
|
||||||
free(buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*tmp = '\0';
|
|
||||||
if ((tmp = strchr(buf, '_')))
|
|
||||||
*tmp = '\0';
|
|
||||||
|
|
||||||
afname[0] = '\0';
|
|
||||||
if (aftrans_opt(buf))
|
|
||||||
strcpy(afname, buf);
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Check our protocol family table for this family. */
|
|
||||||
struct aftype *get_aftype(const char *name)
|
|
||||||
{
|
|
||||||
struct aftype **afp;
|
|
||||||
|
|
||||||
if (!sVafinit)
|
|
||||||
afinit();
|
|
||||||
|
|
||||||
afp = aftypes;
|
|
||||||
while (*afp != NULL) {
|
|
||||||
if (!strcmp((*afp)->name, name))
|
|
||||||
return (*afp);
|
|
||||||
afp++;
|
|
||||||
}
|
|
||||||
if (index(name, ','))
|
|
||||||
fprintf(stderr, _("Please don't supply more than one address family.\n"));
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Check our protocol family table for this family. */
|
|
||||||
struct aftype *get_afntype(int af)
|
|
||||||
{
|
|
||||||
struct aftype **afp;
|
|
||||||
|
|
||||||
if (!sVafinit)
|
|
||||||
afinit();
|
|
||||||
|
|
||||||
afp = aftypes;
|
|
||||||
while (*afp != NULL) {
|
|
||||||
if ((*afp)->af == af)
|
|
||||||
return (*afp);
|
|
||||||
afp++;
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check our protocol family table for this family and return its socket */
|
|
||||||
int get_socket_for_af(int af)
|
|
||||||
{
|
|
||||||
struct aftype **afp;
|
|
||||||
|
|
||||||
if (!sVafinit)
|
|
||||||
afinit();
|
|
||||||
|
|
||||||
afp = aftypes;
|
|
||||||
while (*afp != NULL) {
|
|
||||||
if ((*afp)->af == af)
|
|
||||||
return (*afp)->fd;
|
|
||||||
afp++;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int aftrans_opt(const char *arg)
|
|
||||||
{
|
|
||||||
struct aftrans_t *paft;
|
|
||||||
char *tmp1, *tmp2;
|
|
||||||
char buf[256];
|
|
||||||
|
|
||||||
safe_strncpy(buf, arg, sizeof(buf));
|
|
||||||
|
|
||||||
tmp1 = buf;
|
|
||||||
|
|
||||||
while (tmp1) {
|
|
||||||
|
|
||||||
tmp2 = index(tmp1, ',');
|
|
||||||
|
|
||||||
if (tmp2)
|
|
||||||
*(tmp2++) = '\0';
|
|
||||||
|
|
||||||
paft = aftrans;
|
|
||||||
for (paft = aftrans; paft->alias; paft++) {
|
|
||||||
if (strcmp(tmp1, paft->alias))
|
|
||||||
continue;
|
|
||||||
if (strlen(paft->name) + strlen(afname) + 1 >= sizeof(afname)) {
|
|
||||||
fprintf(stderr, _("Too much address family arguments.\n"));
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
if (paft->flag)
|
|
||||||
(*paft->flag)++;
|
|
||||||
if (afname[0])
|
|
||||||
strcat(afname, ",");
|
|
||||||
strcat(afname, paft->name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!paft->alias) {
|
|
||||||
fprintf(stderr, _("Unknown address family `%s'.\n"), tmp1);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
tmp1 = tmp2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* type: 0=all, 1=getroute */
|
|
||||||
void print_aflist(int type) {
|
|
||||||
int count = 0;
|
|
||||||
char * txt;
|
|
||||||
struct aftype **afp;
|
|
||||||
|
|
||||||
if (!sVafinit)
|
|
||||||
afinit();
|
|
||||||
|
|
||||||
afp = aftypes;
|
|
||||||
while (*afp != NULL) {
|
|
||||||
if ((type == 1 && ((*afp)->rprint == NULL)) || ((*afp)->af == 0)) {
|
|
||||||
afp++; continue;
|
|
||||||
}
|
|
||||||
if ((count % 3) == 0) fprintf(stderr,count?"\n ":" ");
|
|
||||||
txt = (*afp)->name; if (!txt) txt = "..";
|
|
||||||
fprintf(stderr,"%s (%s) ",txt,(*afp)->title);
|
|
||||||
count++;
|
|
||||||
afp++;
|
|
||||||
}
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/arcnet.c This file contains an implementation of the "ARCnet"
|
|
||||||
* support functions for the NET-2 base distribution.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
|
|
||||||
* Copyright 1993 MicroWalt Corporation
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if HAVE_HWARC
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#include <linux/if_ether.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "intl.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
extern struct hwtype arcnet_hwtype;
|
|
||||||
|
|
||||||
|
|
||||||
/* Display an ARCnet address in readable format. */
|
|
||||||
static char *pr_arcnet(unsigned char *ptr)
|
|
||||||
{
|
|
||||||
static char buff[64];
|
|
||||||
|
|
||||||
snprintf(buff, sizeof(buff), "%02X", (ptr[0] & 0377));
|
|
||||||
return (buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Input an ARCnet address and convert to binary. */
|
|
||||||
static int in_arcnet(char *bufp, struct sockaddr *sap)
|
|
||||||
{
|
|
||||||
unsigned char *ptr;
|
|
||||||
char c, *orig;
|
|
||||||
int i, val;
|
|
||||||
|
|
||||||
sap->sa_family = arcnet_hwtype.type;
|
|
||||||
ptr = sap->sa_data;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
orig = bufp;
|
|
||||||
while ((*bufp != '\0') && (i < 1)) {
|
|
||||||
val = 0;
|
|
||||||
c = *bufp++;
|
|
||||||
if (isdigit(c))
|
|
||||||
val = c - '0';
|
|
||||||
else if (c >= 'a' && c <= 'f')
|
|
||||||
val = c - 'a' + 10;
|
|
||||||
else if (c >= 'A' && c <= 'F')
|
|
||||||
val = c - 'A' + 10;
|
|
||||||
else {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_arcnet(%s): invalid arcnet address!\n"), orig);
|
|
||||||
#endif
|
|
||||||
errno = EINVAL;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
val <<= 4;
|
|
||||||
c = *bufp++;
|
|
||||||
if (isdigit(c))
|
|
||||||
val |= c - '0';
|
|
||||||
else if (c >= 'a' && c <= 'f')
|
|
||||||
val |= c - 'a' + 10;
|
|
||||||
else if (c >= 'A' && c <= 'F')
|
|
||||||
val |= c - 'A' + 10;
|
|
||||||
else {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_arcnet(%s): invalid arcnet address!\n"), orig);
|
|
||||||
#endif
|
|
||||||
errno = EINVAL;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
*ptr++ = (unsigned char) (val & 0377);
|
|
||||||
i++;
|
|
||||||
|
|
||||||
/* We might get a semicolon here - not required. */
|
|
||||||
if (*bufp == ':') {
|
|
||||||
if (i == ETH_ALEN) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_arcnet(%s): trailing : ignored!\n"),
|
|
||||||
orig)
|
|
||||||
#endif
|
|
||||||
; /* nothing */
|
|
||||||
}
|
|
||||||
bufp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* That's it. Any trailing junk? */
|
|
||||||
if ((i == ETH_ALEN) && (*bufp != '\0')) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_arcnet(%s): trailing junk!\n"), orig);
|
|
||||||
errno = EINVAL;
|
|
||||||
return (-1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "in_arcnet(%s): %s\n", orig, pr_arcnet(sap->sa_data));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct hwtype arcnet_hwtype =
|
|
||||||
{
|
|
||||||
"arcnet", NULL, /*"2.5Mbps ARCnet", */ ARPHRD_ARCNET, 1,
|
|
||||||
pr_arcnet, in_arcnet, NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_HWARC */
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* config.h Automatically generated configuration includefile
|
|
||||||
*
|
|
||||||
* NET-TOOLS A collection of programs that form the base set of the
|
|
||||||
* NET-3 Networking Distribution for the LINUX operating
|
|
||||||
* system.
|
|
||||||
*
|
|
||||||
* DO NOT EDIT DIRECTLY
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Internationalization
|
|
||||||
*
|
|
||||||
* The net-tools package has currently been translated to French,
|
|
||||||
* German and Brazilian Portugese. Other translations are, of
|
|
||||||
* course, welcome. Answer `n' here if you have no support for
|
|
||||||
* internationalization on your system.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define I18N 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Protocol Families.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define HAVE_AFUNIX 1
|
|
||||||
#define HAVE_AFINET 1
|
|
||||||
#define HAVE_AFINET6 0
|
|
||||||
#define HAVE_AFIPX 0
|
|
||||||
#define HAVE_AFATALK 0
|
|
||||||
#define HAVE_AFAX25 0
|
|
||||||
#define HAVE_AFNETROM 0
|
|
||||||
#define HAVE_AFROSE 0
|
|
||||||
#define HAVE_AFX25 0
|
|
||||||
#define HAVE_AFECONET 0
|
|
||||||
#define HAVE_AFDECnet 0
|
|
||||||
#define HAVE_AFASH 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Device Hardware types.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define HAVE_HWETHER 1
|
|
||||||
#define HAVE_HWARC 1
|
|
||||||
#define HAVE_HWSLIP 0
|
|
||||||
#define HAVE_HWPPP 1
|
|
||||||
#define HAVE_HWTUNNEL 1
|
|
||||||
#define HAVE_HWSTRIP 0
|
|
||||||
#define HAVE_HWTR 0
|
|
||||||
#define HAVE_HWAX25 0
|
|
||||||
#define HAVE_HWROSE 0
|
|
||||||
#define HAVE_HWNETROM 0
|
|
||||||
#define HAVE_HWX25 0
|
|
||||||
#define HAVE_HWFR 1
|
|
||||||
#define HAVE_HWSIT 0
|
|
||||||
#define HAVE_HWFDDI 0
|
|
||||||
#define HAVE_HWHIPPI 0
|
|
||||||
#define HAVE_HWASH 0
|
|
||||||
#define HAVE_HWHDLCLAPB 0
|
|
||||||
#define HAVE_HWIRDA 0
|
|
||||||
#define HAVE_HWEC 0
|
|
||||||
#define HAVE_HWEUI64 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Other Features.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define HAVE_FW_MASQUERADE 0
|
|
||||||
#define HAVE_IP_TOOLS 0
|
|
||||||
#define HAVE_MII 0
|
|
||||||
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/ether.c This file contains an implementation of the "Ethernet"
|
|
||||||
* support functions.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
|
|
||||||
* Copyright 1993 MicroWalt Corporation
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if HAVE_HWETHER
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#include <linux/if_ether.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "intl.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
extern struct hwtype ether_hwtype;
|
|
||||||
|
|
||||||
|
|
||||||
/* Display an Ethernet address in readable format. */
|
|
||||||
static char *pr_ether(unsigned char *ptr)
|
|
||||||
{
|
|
||||||
static char buff[64];
|
|
||||||
|
|
||||||
snprintf(buff, sizeof(buff), "%02X:%02X:%02X:%02X:%02X:%02X",
|
|
||||||
(ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
|
|
||||||
(ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
|
|
||||||
);
|
|
||||||
return (buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Input an Ethernet address and convert to binary. */
|
|
||||||
static int in_ether(char *bufp, struct sockaddr *sap)
|
|
||||||
{
|
|
||||||
unsigned char *ptr;
|
|
||||||
char c, *orig;
|
|
||||||
int i;
|
|
||||||
unsigned val;
|
|
||||||
|
|
||||||
sap->sa_family = ether_hwtype.type;
|
|
||||||
ptr = sap->sa_data;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
orig = bufp;
|
|
||||||
while ((*bufp != '\0') && (i < ETH_ALEN)) {
|
|
||||||
val = 0;
|
|
||||||
c = *bufp++;
|
|
||||||
if (isdigit(c))
|
|
||||||
val = c - '0';
|
|
||||||
else if (c >= 'a' && c <= 'f')
|
|
||||||
val = c - 'a' + 10;
|
|
||||||
else if (c >= 'A' && c <= 'F')
|
|
||||||
val = c - 'A' + 10;
|
|
||||||
else {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig);
|
|
||||||
#endif
|
|
||||||
errno = EINVAL;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
val <<= 4;
|
|
||||||
c = *bufp;
|
|
||||||
if (isdigit(c))
|
|
||||||
val |= c - '0';
|
|
||||||
else if (c >= 'a' && c <= 'f')
|
|
||||||
val |= c - 'a' + 10;
|
|
||||||
else if (c >= 'A' && c <= 'F')
|
|
||||||
val |= c - 'A' + 10;
|
|
||||||
else if (c == ':' || c == 0)
|
|
||||||
val >>= 4;
|
|
||||||
else {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig);
|
|
||||||
#endif
|
|
||||||
errno = EINVAL;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
if (c != 0)
|
|
||||||
bufp++;
|
|
||||||
*ptr++ = (unsigned char) (val & 0377);
|
|
||||||
i++;
|
|
||||||
|
|
||||||
/* We might get a semicolon here - not required. */
|
|
||||||
if (*bufp == ':') {
|
|
||||||
if (i == ETH_ALEN) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_ether(%s): trailing : ignored!\n"),
|
|
||||||
orig)
|
|
||||||
#endif
|
|
||||||
; /* nothing */
|
|
||||||
}
|
|
||||||
bufp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* That's it. Any trailing junk? */
|
|
||||||
if ((i == ETH_ALEN) && (*bufp != '\0')) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("in_ether(%s): trailing junk!\n"), orig);
|
|
||||||
errno = EINVAL;
|
|
||||||
return (-1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct hwtype ether_hwtype =
|
|
||||||
{
|
|
||||||
"ether", NULL, /*"10Mbps Ethernet", */ ARPHRD_ETHER, ETH_ALEN,
|
|
||||||
pr_ether, in_ether, NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_HWETHER */
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/frame.c This file contains the Frame Relay support.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
|
|
||||||
*
|
|
||||||
* Author: Mike McLagan <mike.mclagan@linux.org>
|
|
||||||
*
|
|
||||||
* Changes:
|
|
||||||
*
|
|
||||||
*962303 {0.01} Mike McLagan : creation
|
|
||||||
*960413 {0.02} Bernd Eckenfels : included in net-lib
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#if HAVE_HWFR
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
|
|
||||||
char *pr_dlci(unsigned char *ptr)
|
|
||||||
{
|
|
||||||
static char buf[12];
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%i", *(short *) ptr);
|
|
||||||
return (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hwtype dlci_hwtype =
|
|
||||||
{
|
|
||||||
"dlci", NULL, /*"Frame Relay DLCI", */ ARPHRD_DLCI, 3,
|
|
||||||
pr_dlci, NULL, NULL, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hwtype frad_hwtype =
|
|
||||||
{
|
|
||||||
"frad", NULL, /*"Frame Relay Access Device", */ ARPHRD_FRAD, 0,
|
|
||||||
NULL, NULL, NULL, 0
|
|
||||||
};
|
|
||||||
#endif /* HAVE_HWFR */
|
|
||||||
@@ -1,298 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/hw.c This file contains the top-level part of the hardware
|
|
||||||
* support functions module.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Maintainer: Bernd 'eckes' Eckenfels, <net-tools@lina.inka.de>
|
|
||||||
*
|
|
||||||
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
|
|
||||||
* Copyright 1993 MicroWalt Corporation
|
|
||||||
*
|
|
||||||
*980701 {1.21} Arnaldo C. Melo GNU gettext instead of catgets
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "intl.h"
|
|
||||||
|
|
||||||
extern struct hwtype unspec_hwtype;
|
|
||||||
extern struct hwtype loop_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype slip_hwtype;
|
|
||||||
extern struct hwtype cslip_hwtype;
|
|
||||||
extern struct hwtype slip6_hwtype;
|
|
||||||
extern struct hwtype cslip6_hwtype;
|
|
||||||
extern struct hwtype adaptive_hwtype;
|
|
||||||
extern struct hwtype strip_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype ether_hwtype;
|
|
||||||
extern struct hwtype fddi_hwtype;
|
|
||||||
extern struct hwtype hippi_hwtype;
|
|
||||||
extern struct hwtype tr_hwtype;
|
|
||||||
#ifdef ARPHRD_IEEE802_TR
|
|
||||||
extern struct hwtype tr_hwtype1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern struct hwtype ax25_hwtype;
|
|
||||||
extern struct hwtype rose_hwtype;
|
|
||||||
extern struct hwtype netrom_hwtype;
|
|
||||||
extern struct hwtype x25_hwtype;
|
|
||||||
extern struct hwtype tunnel_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype ash_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype ppp_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype arcnet_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype dlci_hwtype;
|
|
||||||
extern struct hwtype frad_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype hdlc_hwtype;
|
|
||||||
extern struct hwtype lapb_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype sit_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype irda_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype ec_hwtype;
|
|
||||||
|
|
||||||
extern struct hwtype eui64_hwtype;
|
|
||||||
|
|
||||||
static struct hwtype *hwtypes[] =
|
|
||||||
{
|
|
||||||
|
|
||||||
&loop_hwtype,
|
|
||||||
|
|
||||||
#if HAVE_HWSLIP
|
|
||||||
&slip_hwtype,
|
|
||||||
&cslip_hwtype,
|
|
||||||
&slip6_hwtype,
|
|
||||||
&cslip6_hwtype,
|
|
||||||
&adaptive_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWSTRIP
|
|
||||||
&strip_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWASH
|
|
||||||
&ash_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWETHER
|
|
||||||
ðer_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWTR
|
|
||||||
&tr_hwtype,
|
|
||||||
#ifdef ARPHRD_IEEE802_TR
|
|
||||||
&tr_hwtype1,
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWAX25
|
|
||||||
&ax25_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWNETROM
|
|
||||||
&netrom_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWROSE
|
|
||||||
&rose_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWTUNNEL
|
|
||||||
&tunnel_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWPPP
|
|
||||||
&ppp_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWHDLCLAPB
|
|
||||||
&hdlc_hwtype,
|
|
||||||
&lapb_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWARC
|
|
||||||
&arcnet_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWFR
|
|
||||||
&dlci_hwtype,
|
|
||||||
&frad_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWSIT
|
|
||||||
&sit_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWFDDI
|
|
||||||
&fddi_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWHIPPI
|
|
||||||
&hippi_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWIRDA
|
|
||||||
&irda_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWEC
|
|
||||||
&ec_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWX25
|
|
||||||
&x25_hwtype,
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWEUI64
|
|
||||||
&eui64_hwtype,
|
|
||||||
#endif
|
|
||||||
&unspec_hwtype,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static short sVhwinit = 0;
|
|
||||||
|
|
||||||
void hwinit()
|
|
||||||
{
|
|
||||||
loop_hwtype.title = _("Local Loopback");
|
|
||||||
unspec_hwtype.title = _("UNSPEC");
|
|
||||||
#if HAVE_HWSLIP
|
|
||||||
slip_hwtype.title = _("Serial Line IP");
|
|
||||||
cslip_hwtype.title = _("VJ Serial Line IP");
|
|
||||||
slip6_hwtype.title = _("6-bit Serial Line IP");
|
|
||||||
cslip6_hwtype.title = _("VJ 6-bit Serial Line IP");
|
|
||||||
adaptive_hwtype.title = _("Adaptive Serial Line IP");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWETHER
|
|
||||||
ether_hwtype.title = _("Ethernet");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWASH
|
|
||||||
ash_hwtype.title = _("Ash");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWFDDI
|
|
||||||
fddi_hwtype.title = _("Fiber Distributed Data Interface");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWHIPPI
|
|
||||||
hippi_hwtype.title = _("HIPPI");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWAX25
|
|
||||||
ax25_hwtype.title = _("AMPR AX.25");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWROSE
|
|
||||||
rose_hwtype.title = _("AMPR ROSE");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWNETROM
|
|
||||||
netrom_hwtype.title = _("AMPR NET/ROM");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWX25
|
|
||||||
x25_hwtype.title = _("generic X.25");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWTUNNEL
|
|
||||||
tunnel_hwtype.title = _("IPIP Tunnel");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWPPP
|
|
||||||
ppp_hwtype.title = _("Point-to-Point Protocol");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWHDLCLAPB
|
|
||||||
hdlc_hwtype.title = _("(Cisco)-HDLC");
|
|
||||||
lapb_hwtype.title = _("LAPB");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWARC
|
|
||||||
arcnet_hwtype.title = _("ARCnet");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWFR
|
|
||||||
dlci_hwtype.title = _("Frame Relay DLCI");
|
|
||||||
frad_hwtype.title = _("Frame Relay Access Device");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWSIT
|
|
||||||
sit_hwtype.title = _("IPv6-in-IPv4");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWIRDA
|
|
||||||
irda_hwtype.title = _("IrLAP");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWTR
|
|
||||||
tr_hwtype.title = _("16/4 Mbps Token Ring");
|
|
||||||
#ifdef ARPHRD_IEEE802_TR
|
|
||||||
tr_hwtype1.title = _("16/4 Mbps Token Ring (New)") ;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWEC
|
|
||||||
ec_hwtype.title = _("Econet");
|
|
||||||
#endif
|
|
||||||
#if HAVE_HWEUI64
|
|
||||||
eui64_hwtype.title = _("Generic EUI-64");
|
|
||||||
#endif
|
|
||||||
sVhwinit = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check our hardware type table for this type. */
|
|
||||||
struct hwtype *get_hwtype(const char *name)
|
|
||||||
{
|
|
||||||
struct hwtype **hwp;
|
|
||||||
|
|
||||||
if (!sVhwinit)
|
|
||||||
hwinit();
|
|
||||||
|
|
||||||
hwp = hwtypes;
|
|
||||||
while (*hwp != NULL) {
|
|
||||||
if (!strcmp((*hwp)->name, name))
|
|
||||||
return (*hwp);
|
|
||||||
hwp++;
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Check our hardware type table for this type. */
|
|
||||||
struct hwtype *get_hwntype(int type)
|
|
||||||
{
|
|
||||||
struct hwtype **hwp;
|
|
||||||
|
|
||||||
if (!sVhwinit)
|
|
||||||
hwinit();
|
|
||||||
|
|
||||||
hwp = hwtypes;
|
|
||||||
while (*hwp != NULL) {
|
|
||||||
if ((*hwp)->type == type)
|
|
||||||
return (*hwp);
|
|
||||||
hwp++;
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* type: 0=all, 1=ARPable */
|
|
||||||
void print_hwlist(int type) {
|
|
||||||
int count = 0;
|
|
||||||
char * txt;
|
|
||||||
struct hwtype **hwp;
|
|
||||||
|
|
||||||
if (!sVhwinit)
|
|
||||||
hwinit();
|
|
||||||
|
|
||||||
hwp = hwtypes;
|
|
||||||
while (*hwp != NULL) {
|
|
||||||
if (((type == 1) && ((*hwp)->alen == 0)) || ((*hwp)->type == -1)) {
|
|
||||||
hwp++; continue;
|
|
||||||
}
|
|
||||||
if ((count % 3) == 0) fprintf(stderr,count?"\n ":" ");
|
|
||||||
txt = (*hwp)->name; if (!txt) txt = "..";
|
|
||||||
fprintf(stderr,"%s (%s) ",txt,(*hwp)->title);
|
|
||||||
count++;
|
|
||||||
hwp++;
|
|
||||||
}
|
|
||||||
fprintf(stderr,"\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return 1 if address is all zeros */
|
|
||||||
int hw_null_address(struct hwtype *hw, void *ap)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
unsigned char *address = (unsigned char *)ap;
|
|
||||||
for (i = 0; i < hw->alen; i++)
|
|
||||||
if (address[i])
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -1,590 +0,0 @@
|
|||||||
/* if_demo.c
|
|
||||||
|
|
||||||
interfacedemo for "pyramid" LCD device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (C) 2005 Silvan Marco Fin <silvan@kernelconcepts.de>
|
|
||||||
|
|
||||||
This program 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
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <wait.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include "lib-myconnect.h"
|
|
||||||
#include "lib-mylcd.h"
|
|
||||||
|
|
||||||
#include "interface.h"
|
|
||||||
#include "sockets.h"
|
|
||||||
#include "net-support.h"
|
|
||||||
|
|
||||||
#define DEBUG 0
|
|
||||||
#define SUCC_DUR 10 /* Duration in sec. how long a success-message is displayed */
|
|
||||||
|
|
||||||
/* External programs to be called. */
|
|
||||||
#define INTERFACE_SCRIPT "./scripts/MyIPSet"
|
|
||||||
#define REBOOT_SCRIPT "./scripts/MyReboot"
|
|
||||||
#define HALT_SCRIPT "./scripts/MyHalt"
|
|
||||||
|
|
||||||
/* Modes for action */
|
|
||||||
#define BLANK 0
|
|
||||||
#define UPDATE 1
|
|
||||||
#define IFSELECTED 2
|
|
||||||
#define IPCHANGED 3
|
|
||||||
#define NMCHANGED 4
|
|
||||||
#define GWCHANGED 5
|
|
||||||
#define MENULEFT 6
|
|
||||||
#define SELECT 7
|
|
||||||
|
|
||||||
struct iftype
|
|
||||||
{
|
|
||||||
char name[32];
|
|
||||||
char ip[16];
|
|
||||||
char netmask[16];
|
|
||||||
char gateway[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned int sIF;
|
|
||||||
unsigned int IFnum;
|
|
||||||
struct iftype IFdata[32];
|
|
||||||
} status;
|
|
||||||
|
|
||||||
int skfd;
|
|
||||||
|
|
||||||
void print_help()
|
|
||||||
{
|
|
||||||
printf("Usage:\n");
|
|
||||||
printf(" [-p #] specify Portnumber (defaults to 13666).\n");
|
|
||||||
printf(" -d ... specify comma separated list of devices to manage.\n");
|
|
||||||
printf("\n");
|
|
||||||
printf("Example: if_demo -d eth0,wlan0 -p 12345\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_screen(int SD)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
|
|
||||||
buffer=basic_send(SD, "hello");
|
|
||||||
buffer=basic_send(SD, "client_set -name {Managment}");
|
|
||||||
buffer=basic_send(SD, "screen_add main");
|
|
||||||
buffer=basic_send(SD, "screen_set main -name {main}");
|
|
||||||
buffer=basic_send(SD, "screen_set main -heartbeat off");
|
|
||||||
buffer=basic_send(SD, "screen_set main -priority foreground");
|
|
||||||
/* buffer=basic_send(SD, "screen_set main -duration 80"); */
|
|
||||||
/* buffer=basic_send(SD, "screen_set main -cursor on"); */
|
|
||||||
}
|
|
||||||
|
|
||||||
void alert_screen(int SD, char *line1, char *line2, int duration)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
char mesg[255];
|
|
||||||
|
|
||||||
/* buffer=basic_send(SD, "widget_del main mainscroller"); */
|
|
||||||
buffer=basic_send(SD, "screen_add info");
|
|
||||||
buffer=basic_send(SD, "screen_set info -priority alert");
|
|
||||||
sprintf(mesg, "screen_set info -timeout %d", duration);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
buffer=basic_send(SD, "widget_add info infostring1 string");
|
|
||||||
buffer=basic_send(SD, "widget_add info infostring2 string");
|
|
||||||
sprintf(mesg, "widget_set info infostring1 1 1 {%s}", line1);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
sprintf(mesg, "widget_set info infostring2 1 2 {%s}", line2);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void interfaces(int SD, char *cs_iflist)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
char *retval;
|
|
||||||
char *next=cs_iflist;
|
|
||||||
char mesg[255];
|
|
||||||
unsigned int orig_len=strlen(cs_iflist);
|
|
||||||
unsigned int i=0;
|
|
||||||
|
|
||||||
/* Now we fill the interfaces to the status variable. */
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
retval=strtok(next, ",");
|
|
||||||
next=NULL;
|
|
||||||
if (retval==NULL)
|
|
||||||
break; /* or return? */
|
|
||||||
strcpy(status.IFdata[i].name, retval);
|
|
||||||
/* If interface is up, then get it's numbers and use them, else set to default-Values */
|
|
||||||
/* Default values: */
|
|
||||||
sprintf(status.IFdata[i].ip, "000.000.000.000");
|
|
||||||
sprintf(status.IFdata[i].netmask, "255.255.255.255");
|
|
||||||
sprintf(status.IFdata[i].gateway, "000.000.000.000");
|
|
||||||
if (DEBUG)
|
|
||||||
printf("IF %s: IP=%s, NM=%s, GW=%s\n", status.IFdata[i].name, status.IFdata[i].ip, status.IFdata[i].netmask, status.IFdata[i].gateway);
|
|
||||||
sprintf(mesg, "menu_add_item SIF %d action {sel. %s} -next CHSET", i, status.IFdata[i].name);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
status.IFnum=i+1;
|
|
||||||
/* now prepare cs_iflist so that we can generate a menu entry. */
|
|
||||||
for (i=0; i<orig_len; i++)
|
|
||||||
if (cs_iflist[i]=='\0') cs_iflist[i]='\t';
|
|
||||||
/* sprintf(mesg, "menu_add_item SIF selection ring {IF:} -strings {%s}", cs_iflist); */ /* For use of a selection ring */
|
|
||||||
/* buffer=basic_send(SD, mesg); */
|
|
||||||
status.sIF=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void old_autointerfaces(int SD)
|
|
||||||
{
|
|
||||||
struct if_nameindex *if_list;
|
|
||||||
char buffer[1000]="";
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if_list=if_nameindex();
|
|
||||||
for (i=0; if_list[i].if_name!=NULL; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(if_list[i].if_name, "lo")==0)
|
|
||||||
continue;
|
|
||||||
if (strlen(buffer)==0)
|
|
||||||
sprintf(buffer, "%s", if_list[i].if_name);
|
|
||||||
else
|
|
||||||
sprintf(buffer, "%s,%s", buffer, if_list[i].if_name);
|
|
||||||
}
|
|
||||||
interfaces(SD, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_if_action(int SD, struct interface *ife, void *cookie)
|
|
||||||
{
|
|
||||||
int *opt_a = (int *) cookie;
|
|
||||||
int res;
|
|
||||||
struct aftype *ap;
|
|
||||||
static unsigned int i=0;
|
|
||||||
char mesg[255];
|
|
||||||
char *buffer;
|
|
||||||
|
|
||||||
res = do_if_fetch(ife);
|
|
||||||
if (strcmp(ife->name, "lo")==0)
|
|
||||||
return 0;
|
|
||||||
if (res >= 0) {
|
|
||||||
if ((ife->flags & IFF_UP) || *opt_a)
|
|
||||||
{
|
|
||||||
ap = get_afntype(ife->addr.sa_family);
|
|
||||||
strcpy(status.IFdata[i].name, ife->name);
|
|
||||||
if (ife->has_ip)
|
|
||||||
{
|
|
||||||
sprintf(status.IFdata[i].ip, "%s", ap->sprint(&ife->addr, 1));
|
|
||||||
sprintf(status.IFdata[i].netmask, "%s", ap->sprint(&ife->netmask, 1));
|
|
||||||
sprintf(status.IFdata[i].gateway, "%s", ap->sprint(&ife->addr, 1));
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
sprintf(status.IFdata[i].ip, "000.000.000.000");
|
|
||||||
sprintf(status.IFdata[i].netmask, "255.255.255.255");
|
|
||||||
sprintf(status.IFdata[i].gateway, "000.000.000.000");
|
|
||||||
}
|
|
||||||
sprintf(mesg, "menu_add_item SIF %d action {sel. %s} -next CHSET", i, status.IFdata[i].name);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void autointerfaces(int SD)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
int opt_a=0;
|
|
||||||
|
|
||||||
/* Create a channel to the NET kernel. */
|
|
||||||
if ((skfd = sockets_open(0)) < 0) {
|
|
||||||
perror("socket");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
res=for_all_interfaces(SD, do_if_action, &opt_a);
|
|
||||||
close(skfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_main_info(int SD, char *ifname, char *ip, char *netmask, char *gateway)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
char mesg[255];
|
|
||||||
|
|
||||||
sprintf(mesg, "widget_set main mainscroller 1 1 16 2 v 10 {%*s%*s%*s%*s%*s%*s%*s%*s}",
|
|
||||||
16, " Watching IF: ",
|
|
||||||
16, ifname,
|
|
||||||
16, " IP-Address: ",
|
|
||||||
16, ip,
|
|
||||||
16, " Netmask: ",
|
|
||||||
16, netmask,
|
|
||||||
16, " Gateway: ",
|
|
||||||
16, gateway);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void CHSET_menus_add(int SD)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
char mesg[255];
|
|
||||||
|
|
||||||
sprintf(mesg, "menu_add_item CHSET CHIP ip {%s IP} -v6 false -value {%s}",
|
|
||||||
status.IFdata[status.sIF].name, status.IFdata[status.sIF].ip);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
sprintf(mesg, "menu_add_item CHSET CHNM ip {%s netmask} -v6 false -value {%s}",
|
|
||||||
status.IFdata[status.sIF].name, status.IFdata[status.sIF].netmask);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
sprintf(mesg, "menu_add_item CHSET CHGW ip {%s gateway} -v6 false -value {%s}",
|
|
||||||
status.IFdata[status.sIF].name, status.IFdata[status.sIF].gateway);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
buffer=basic_send(SD, "menu_set_item CHSET CHIP -next CHNM");
|
|
||||||
buffer=basic_send(SD, "menu_set_item CHSET CHNM -next CHGW");
|
|
||||||
set_main_info(SD, status.IFdata[status.sIF].name, status.IFdata[status.sIF].ip, status.IFdata[status.sIF].netmask, status.IFdata[status.sIF].gateway);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHSET_menus(int SD)
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
char mesg[255];
|
|
||||||
|
|
||||||
sprintf(mesg, "menu_set_item CHSET CHIP -text {%s IP} -v6 false -value {%s}",
|
|
||||||
status.IFdata[status.sIF].name, status.IFdata[status.sIF].ip);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
sprintf(mesg, "menu_set_item CHSET CHNM -text {%s netmask} -v6 false -value {%s}",
|
|
||||||
status.IFdata[status.sIF].name, status.IFdata[status.sIF].netmask);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
sprintf(mesg, "menu_set_item CHSET CHGW -text {%s gateway} -v6 false -value {%s}",
|
|
||||||
status.IFdata[status.sIF].name, status.IFdata[status.sIF].gateway);
|
|
||||||
buffer=basic_send(SD, mesg);
|
|
||||||
set_main_info(SD, status.IFdata[status.sIF].name, status.IFdata[status.sIF].ip, status.IFdata[status.sIF].netmask, status.IFdata[status.sIF].gateway);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void action(int SD, char *input)
|
|
||||||
{
|
|
||||||
char *next=input;
|
|
||||||
char *retstr;
|
|
||||||
int len=0;
|
|
||||||
int mode=0;
|
|
||||||
int myid;
|
|
||||||
|
|
||||||
if(DEBUG)
|
|
||||||
printf("Eingabe: %s\n", input);
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
retstr=strtok(next, " \n");
|
|
||||||
next=NULL;
|
|
||||||
if (retstr==NULL)
|
|
||||||
{
|
|
||||||
input[0]=0; /* wofür war das? */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len+=strlen(retstr)+1;
|
|
||||||
/* key detected? */
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case BLANK:
|
|
||||||
{
|
|
||||||
if (strcmp(retstr, "update")==0) mode=UPDATE;
|
|
||||||
if (strcmp(retstr, "leave")==0) mode=MENULEFT;
|
|
||||||
if (strcmp(retstr, "select")==0) mode=SELECT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case UPDATE:
|
|
||||||
{
|
|
||||||
/* if (strcmp(retstr, "sIF")==0) mode=IFSELECTED; */
|
|
||||||
if (strcmp(retstr, "CHIP")==0) mode=IPCHANGED;
|
|
||||||
if (strcmp(retstr, "CHNM")==0) mode=NMCHANGED;
|
|
||||||
if (strcmp(retstr, "CHGW")==0) mode=GWCHANGED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IFSELECTED:
|
|
||||||
{
|
|
||||||
status.sIF=atoi(retstr);
|
|
||||||
CHSET_menus(SD);
|
|
||||||
mode=BLANK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case IPCHANGED:
|
|
||||||
{
|
|
||||||
strcpy(status.IFdata[status.sIF].ip, retstr);
|
|
||||||
mode=BLANK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NMCHANGED:
|
|
||||||
{
|
|
||||||
strcpy(status.IFdata[status.sIF].netmask, retstr);
|
|
||||||
mode=BLANK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GWCHANGED:
|
|
||||||
{
|
|
||||||
strcpy(status.IFdata[status.sIF].gateway, retstr);
|
|
||||||
mode=BLANK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MENULEFT:
|
|
||||||
{
|
|
||||||
CHSET_menus(SD);
|
|
||||||
mode=BLANK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SELECT:
|
|
||||||
/* Now it gets a bit difficult: If we want to call the
|
|
||||||
external script, we have to do the fork twice of
|
|
||||||
wait for the child process (which we don't want to).
|
|
||||||
The approach ist repeated for every call to external
|
|
||||||
programm. */
|
|
||||||
{
|
|
||||||
if (strcmp(retstr, "APPLY")==0)
|
|
||||||
{
|
|
||||||
char mesg[17];
|
|
||||||
myid=fork();
|
|
||||||
switch (myid)
|
|
||||||
{
|
|
||||||
int mynewid;
|
|
||||||
case 0:
|
|
||||||
mynewid=fork();
|
|
||||||
switch (mynewid)
|
|
||||||
{
|
|
||||||
case 0: /* Child of the child */
|
|
||||||
close(SD);
|
|
||||||
execl(INTERFACE_SCRIPT,
|
|
||||||
INTERFACE_SCRIPT,
|
|
||||||
status.IFdata[status.sIF].name,
|
|
||||||
status.IFdata[status.sIF].ip,
|
|
||||||
status.IFdata[status.sIF].netmask,
|
|
||||||
status.IFdata[status.sIF].gateway,
|
|
||||||
NULL);
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
sprintf(mesg, "Error %d", errno);
|
|
||||||
alert_screen(SD, mesg, "during apply.", SUCC_DUR);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
default: /* At this point, the child exits and the grandchild's parent is set to "1". */
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
sprintf(mesg, "Error %d", errno);
|
|
||||||
alert_screen(SD, mesg, "during apply.", SUCC_DUR);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sprintf(mesg, "for IF %s", status.IFdata[status.sIF].name);
|
|
||||||
alert_screen(SD, "Settings applied", mesg, 160);
|
|
||||||
waitpid(myid, NULL, 0); /* the child's exitstate is read, but we don't need it. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (strcmp(retstr, "HALT")==0)
|
|
||||||
{
|
|
||||||
char mesg[17];
|
|
||||||
myid=fork();
|
|
||||||
switch (myid)
|
|
||||||
{
|
|
||||||
int mynewid;
|
|
||||||
case 0:
|
|
||||||
mynewid=fork();
|
|
||||||
switch(mynewid)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
close(SD);
|
|
||||||
execl(HALT_SCRIPT,
|
|
||||||
HALT_SCRIPT,
|
|
||||||
NULL);
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
sprintf(mesg, "Error %d", errno);
|
|
||||||
alert_screen(SD, mesg, "during halt.", SUCC_DUR);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
sprintf(mesg, "Error %d", errno);
|
|
||||||
alert_screen(SD, mesg, "during halt.", SUCC_DUR);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
alert_screen(SD, "Going down for", "halt now.", 160);
|
|
||||||
waitpid(myid, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (strcmp(retstr, "REBOOT")==0)
|
|
||||||
{
|
|
||||||
char mesg[17];
|
|
||||||
myid=fork();
|
|
||||||
switch (myid)
|
|
||||||
{
|
|
||||||
int mynewid;
|
|
||||||
case 0:
|
|
||||||
mynewid=fork();
|
|
||||||
switch (mynewid)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
close(SD);
|
|
||||||
execl(REBOOT_SCRIPT,
|
|
||||||
REBOOT_SCRIPT,
|
|
||||||
NULL);
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
sprintf(mesg, "Error %d", errno);
|
|
||||||
alert_screen(SD, mesg, "during reboot.", SUCC_DUR);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case -1:
|
|
||||||
sprintf(mesg, "Error %d", errno);
|
|
||||||
alert_screen(SD, mesg, "during reboot.", SUCC_DUR);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
alert_screen(SD, "Going down for", "reboot now.", 160);
|
|
||||||
waitpid(myid, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else /* Assume the Selection is a number and refers to the Index of an interface */
|
|
||||||
{
|
|
||||||
status.sIF=atoi(retstr);
|
|
||||||
CHSET_menus(SD);
|
|
||||||
}
|
|
||||||
mode=BLANK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int SD;
|
|
||||||
int conn_port=13666;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
char *buffer;
|
|
||||||
int starttime;
|
|
||||||
int nowtime;
|
|
||||||
int devpos=-1;
|
|
||||||
int manualif=0;
|
|
||||||
|
|
||||||
for(i = 1, j = 0; i < argc; i++)
|
|
||||||
{
|
|
||||||
if(argv[i][0] == '-')
|
|
||||||
{
|
|
||||||
switch(argv[i][1])
|
|
||||||
{
|
|
||||||
/* Port number specified */
|
|
||||||
case 'p':
|
|
||||||
{
|
|
||||||
if(argc < i + 1)
|
|
||||||
print_help();
|
|
||||||
conn_port = atoi(argv[++i]);
|
|
||||||
if(conn_port < 1 && conn_port > 0xffff)
|
|
||||||
fprintf(stderr, "Warning: Port %d outside of standard range\n", conn_port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* List of devices */
|
|
||||||
case 'd':
|
|
||||||
{
|
|
||||||
devpos=i+1;
|
|
||||||
manualif=1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* otherwise... Get help!*/
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
print_help();
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manualif && devpos<1)
|
|
||||||
{
|
|
||||||
printf("No interfaces specified, exiting (use -h for usage information).\n");
|
|
||||||
close(SD);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SD=get_connection("localhost", conn_port);
|
|
||||||
if (SD<0)
|
|
||||||
exit(0);
|
|
||||||
|
|
||||||
init_screen(SD);
|
|
||||||
|
|
||||||
buffer=basic_send(SD, "menu_add_item {} SIF menu {Current IF}");
|
|
||||||
buffer=basic_send(SD, "menu_add_item {} CHSET menu {IF setting}");
|
|
||||||
if (manualif)
|
|
||||||
interfaces(SD, argv[devpos]);
|
|
||||||
else
|
|
||||||
autointerfaces(SD);
|
|
||||||
|
|
||||||
/* buffer=basic_send(SD, "menu_set_item {} SIF -next CHSET"); */ /* Doesn't work like that */
|
|
||||||
|
|
||||||
buffer=basic_send(SD, "menu_set_main {}");
|
|
||||||
/* buffer=basic_send(SD, "widget_add main maintitle title");
|
|
||||||
buffer=basic_send(SD, "widget_set main maintitle {IF-Status}"); */
|
|
||||||
buffer=basic_send(SD, "widget_add main mainscroller scroller");
|
|
||||||
buffer=basic_send(SD, "widget_set main mainscroller 1 1 16 2 v 4 {Please stand by. }");
|
|
||||||
|
|
||||||
CHSET_menus_add(SD); /* Remember to set the status.sIF to a valid value before call to CHSET_menus*() (e.g. done by interfaces()). */
|
|
||||||
buffer=basic_send(SD, "menu_add_item CHSET APPLY action {Apply settings} -next _quit_");
|
|
||||||
buffer=basic_send(SD, "menu_set_item CHSET CHGW -next APPLY");
|
|
||||||
|
|
||||||
buffer=basic_send(SD, "menu_add_item {} ASKREBOOT menu {Confirm reboot?} -is_hidden true");
|
|
||||||
buffer=basic_send(SD, "menu_add_item ASKREBOOT REBOOT action { [Yes][No]} -next _quit_");
|
|
||||||
|
|
||||||
buffer=basic_send(SD, "menu_add_item {} ASKHALT menu {Really halt?} -is_hidden true");
|
|
||||||
buffer=basic_send(SD, "menu_add_item ASKHALT HALT action { [Yes][No]} -next _quit_");
|
|
||||||
|
|
||||||
buffer=basic_send(SD, "menu_add_item {} SHUTDOWN menu {Shutdown}");
|
|
||||||
buffer=basic_send(SD, "menu_add_item SHUTDOWN DOHALT action {Halt system} -next ASKHALT");
|
|
||||||
buffer=basic_send(SD, "menu_add_item SHUTDOWN DOREBOOT action {Reboot system} -next ASKREBOOT");
|
|
||||||
|
|
||||||
starttime=time(NULL);
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
nowtime=time(NULL);
|
|
||||||
/* sprintf(cmd, "widget_set main c0 1 2 \"%ld\"\n", nowtime-starttime); */
|
|
||||||
/* if nothing else to do, send noop, so we know for sure, that basic_send gets something to read */
|
|
||||||
/* buffer=basic_send(SD, "noop\n"); */
|
|
||||||
buffer=basic_read(SD);
|
|
||||||
action(SD, buffer);
|
|
||||||
usleep(250000);
|
|
||||||
} /* while ((nowtime-starttime)<500); */
|
|
||||||
|
|
||||||
close(SD);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,451 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/inet.c This file contains an implementation of the "INET"
|
|
||||||
* support functions for the net-tools.
|
|
||||||
* (NET-3 base distribution).
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
|
|
||||||
* Copyright 1993 MicroWalt Corporation
|
|
||||||
*
|
|
||||||
* Modified:
|
|
||||||
*960113 {1.21} Bernd Eckenfels : rresolve cache bug.
|
|
||||||
*960128 {1.22} Bernd Eckenfels : endian bug in print
|
|
||||||
*960203 {1.23} Bernd Eckenfels : net-features support
|
|
||||||
*960217 {1.24} Bernd Eckenfels : get_sname
|
|
||||||
*960219 {1.25} Bernd Eckenfels : extern int h_errno
|
|
||||||
*960329 {1.26} Bernd Eckenfels : resolve 255.255.255.255
|
|
||||||
*980101 {1.27} Bernd Eckenfels : resolve raw sockets in /etc/protocols
|
|
||||||
*990302 {1.28} Phil Blundell : add netmask to INET_rresolve
|
|
||||||
*991007 Kurt Garloff : rresolve, resolve: may be hosts
|
|
||||||
* <garloff@suse.de> store type (host?) in cache
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
/* FIXME. Split this file into inet4.c for the IPv4 specific parts
|
|
||||||
and inet.c for those shared between IPv4 and IPv6. */
|
|
||||||
|
|
||||||
#if HAVE_AFINET || HAVE_AFINET6
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <arpa/nameser.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <resolv.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "version.h"
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "intl.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
extern int h_errno; /* some netdb.h versions don't export this */
|
|
||||||
|
|
||||||
/* cache */
|
|
||||||
struct addr {
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
char *name;
|
|
||||||
int host;
|
|
||||||
struct addr *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct service {
|
|
||||||
int number;
|
|
||||||
char *name;
|
|
||||||
struct service *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct service *tcp_name = NULL, *udp_name = NULL, *raw_name = NULL;
|
|
||||||
|
|
||||||
#if HAVE_AFINET
|
|
||||||
|
|
||||||
static struct addr *INET_nn = NULL; /* addr-to-name cache */
|
|
||||||
|
|
||||||
|
|
||||||
static int INET_resolve(char *name, struct sockaddr_in *sin, int hostfirst)
|
|
||||||
{
|
|
||||||
struct hostent *hp;
|
|
||||||
struct netent *np;
|
|
||||||
|
|
||||||
/* Grmpf. -FvK */
|
|
||||||
sin->sin_family = AF_INET;
|
|
||||||
sin->sin_port = 0;
|
|
||||||
|
|
||||||
/* Default is special, meaning 0.0.0.0. */
|
|
||||||
if (!strcmp(name, "default")) {
|
|
||||||
sin->sin_addr.s_addr = INADDR_ANY;
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
/* Look to see if it's a dotted quad. */
|
|
||||||
if (inet_aton(name, &sin->sin_addr)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* If we expect this to be a hostname, try hostname database first */
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (hostfirst) fprintf (stderr, "gethostbyname (%s)\n", name);
|
|
||||||
#endif
|
|
||||||
if (hostfirst &&
|
|
||||||
(hp = gethostbyname(name)) != (struct hostent *) NULL) {
|
|
||||||
memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0],
|
|
||||||
sizeof(struct in_addr));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Try the NETWORKS database to see if this is a known network. */
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "getnetbyname (%s)\n", name);
|
|
||||||
#endif
|
|
||||||
if ((np = getnetbyname(name)) != (struct netent *) NULL) {
|
|
||||||
sin->sin_addr.s_addr = htonl(np->n_net);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (hostfirst) {
|
|
||||||
/* Don't try again */
|
|
||||||
errno = h_errno;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
res_init();
|
|
||||||
_res.options |= RES_DEBUG;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "gethostbyname (%s)\n", name);
|
|
||||||
#endif
|
|
||||||
if ((hp = gethostbyname(name)) == (struct hostent *) NULL) {
|
|
||||||
errno = h_errno;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0],
|
|
||||||
sizeof(struct in_addr));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* numeric: & 0x8000: default instead of *,
|
|
||||||
* & 0x4000: host instead of net,
|
|
||||||
* & 0x0fff: don't resolve
|
|
||||||
*/
|
|
||||||
static int INET_rresolve(char *name, size_t len, struct sockaddr_in *sin,
|
|
||||||
int numeric, unsigned int netmask)
|
|
||||||
{
|
|
||||||
struct hostent *ent;
|
|
||||||
struct netent *np;
|
|
||||||
struct addr *pn;
|
|
||||||
u_int32_t ad, host_ad;
|
|
||||||
int host = 0;
|
|
||||||
|
|
||||||
/* Grmpf. -FvK */
|
|
||||||
if (sin->sin_family != AF_INET) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf(stderr, _("rresolve: unsupport address family %d !\n"), sin->sin_family);
|
|
||||||
#endif
|
|
||||||
errno = EAFNOSUPPORT;
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
ad = sin->sin_addr.s_addr;
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "rresolve: %08lx, mask %08x, num %08x \n", ad, netmask, numeric);
|
|
||||||
#endif
|
|
||||||
if (ad == INADDR_ANY) {
|
|
||||||
if ((numeric & 0x0FFF) == 0) {
|
|
||||||
if (numeric & 0x8000)
|
|
||||||
safe_strncpy(name, "default", len);
|
|
||||||
else
|
|
||||||
safe_strncpy(name, "*", len);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numeric & 0x0FFF) {
|
|
||||||
safe_strncpy(name, inet_ntoa(sin->sin_addr), len);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ad & (~netmask)) != 0 || (numeric & 0x4000))
|
|
||||||
host = 1;
|
|
||||||
#if 0
|
|
||||||
INET_nn = NULL;
|
|
||||||
#endif
|
|
||||||
pn = INET_nn;
|
|
||||||
while (pn != NULL) {
|
|
||||||
if (pn->addr.sin_addr.s_addr == ad && pn->host == host) {
|
|
||||||
safe_strncpy(name, pn->name, len);
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "rresolve: found %s %08lx in cache\n", (host? "host": "net"), ad);
|
|
||||||
#endif
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
pn = pn->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
host_ad = ntohl(ad);
|
|
||||||
np = NULL;
|
|
||||||
ent = NULL;
|
|
||||||
if (host) {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "gethostbyaddr (%08lx)\n", ad);
|
|
||||||
#endif
|
|
||||||
ent = gethostbyaddr((char *) &ad, 4, AF_INET);
|
|
||||||
if (ent != NULL)
|
|
||||||
safe_strncpy(name, ent->h_name, len);
|
|
||||||
} else {
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "getnetbyaddr (%08lx)\n", host_ad);
|
|
||||||
#endif
|
|
||||||
np = getnetbyaddr(host_ad, AF_INET);
|
|
||||||
if (np != NULL)
|
|
||||||
safe_strncpy(name, np->n_name, len);
|
|
||||||
}
|
|
||||||
if ((ent == NULL) && (np == NULL))
|
|
||||||
safe_strncpy(name, inet_ntoa(sin->sin_addr), len);
|
|
||||||
pn = (struct addr *) malloc(sizeof(struct addr));
|
|
||||||
pn->addr = *sin;
|
|
||||||
pn->next = INET_nn;
|
|
||||||
pn->host = host;
|
|
||||||
pn->name = (char *) malloc(strlen(name) + 1);
|
|
||||||
strcpy(pn->name, name);
|
|
||||||
INET_nn = pn;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void INET_reserror(char *text)
|
|
||||||
{
|
|
||||||
herror(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Display an Internet socket address. */
|
|
||||||
static char *INET_print(unsigned char *ptr)
|
|
||||||
{
|
|
||||||
return (inet_ntoa((*(struct in_addr *) ptr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Display an Internet socket address. */
|
|
||||||
static char *INET_sprint(struct sockaddr *sap, int numeric)
|
|
||||||
{
|
|
||||||
static char buff[128];
|
|
||||||
|
|
||||||
if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
|
|
||||||
return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
|
|
||||||
|
|
||||||
if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
|
|
||||||
numeric, 0xffffff00) != 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
return (buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *INET_sprintmask(struct sockaddr *sap, int numeric,
|
|
||||||
unsigned int netmask)
|
|
||||||
{
|
|
||||||
static char buff[128];
|
|
||||||
|
|
||||||
if (sap->sa_family == 0xFFFF || sap->sa_family == 0)
|
|
||||||
return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff));
|
|
||||||
if (INET_rresolve(buff, sizeof(buff), (struct sockaddr_in *) sap,
|
|
||||||
numeric, netmask) != 0)
|
|
||||||
return (NULL);
|
|
||||||
return (buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int INET_getsock(char *bufp, struct sockaddr *sap)
|
|
||||||
{
|
|
||||||
char *sp = bufp, *bp;
|
|
||||||
unsigned int i;
|
|
||||||
unsigned val;
|
|
||||||
struct sockaddr_in *sin;
|
|
||||||
|
|
||||||
sin = (struct sockaddr_in *) sap;
|
|
||||||
sin->sin_family = AF_INET;
|
|
||||||
sin->sin_port = 0;
|
|
||||||
|
|
||||||
val = 0;
|
|
||||||
bp = (char *) &val;
|
|
||||||
for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) {
|
|
||||||
*sp = toupper(*sp);
|
|
||||||
|
|
||||||
if ((*sp >= 'A') && (*sp <= 'F'))
|
|
||||||
bp[i] |= (int) (*sp - 'A') + 10;
|
|
||||||
else if ((*sp >= '0') && (*sp <= '9'))
|
|
||||||
bp[i] |= (int) (*sp - '0');
|
|
||||||
else
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
bp[i] <<= 4;
|
|
||||||
sp++;
|
|
||||||
*sp = toupper(*sp);
|
|
||||||
|
|
||||||
if ((*sp >= 'A') && (*sp <= 'F'))
|
|
||||||
bp[i] |= (int) (*sp - 'A') + 10;
|
|
||||||
else if ((*sp >= '0') && (*sp <= '9'))
|
|
||||||
bp[i] |= (int) (*sp - '0');
|
|
||||||
else
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
sp++;
|
|
||||||
}
|
|
||||||
sin->sin_addr.s_addr = htonl(val);
|
|
||||||
|
|
||||||
return (sp - bufp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int INET_input(int type, char *bufp, struct sockaddr *sap)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case 1:
|
|
||||||
return (INET_getsock(bufp, sap));
|
|
||||||
case 256:
|
|
||||||
return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
|
|
||||||
default:
|
|
||||||
return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int INET_getnetmask(char *adr, struct sockaddr *m, char *name)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *mask = (struct sockaddr_in *) m;
|
|
||||||
char *slash, *end;
|
|
||||||
int prefix;
|
|
||||||
|
|
||||||
if ((slash = strchr(adr, '/')) == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
*slash++ = '\0';
|
|
||||||
prefix = strtoul(slash, &end, 0);
|
|
||||||
if (*end != '\0')
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (name) {
|
|
||||||
sprintf(name, "/%d", prefix);
|
|
||||||
}
|
|
||||||
mask->sin_family = AF_INET;
|
|
||||||
mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct aftype inet_aftype =
|
|
||||||
{
|
|
||||||
"inet", NULL, /*"DARPA Internet", */ AF_INET, sizeof(unsigned long),
|
|
||||||
INET_print, INET_sprint, INET_input, INET_reserror,
|
|
||||||
NULL /*INET_rprint */ , NULL /*INET_rinput */ ,
|
|
||||||
INET_getnetmask,
|
|
||||||
-1,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* HAVE_AFINET */
|
|
||||||
|
|
||||||
static void add2list(struct service **namebase, struct service *item)
|
|
||||||
{
|
|
||||||
if (*namebase == NULL) {
|
|
||||||
*namebase = item;
|
|
||||||
item->next = NULL;
|
|
||||||
} else {
|
|
||||||
item->next = *namebase;
|
|
||||||
*namebase = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct service *searchlist(struct service *servicebase, int number)
|
|
||||||
{
|
|
||||||
struct service *item;
|
|
||||||
|
|
||||||
for (item = servicebase; item != NULL; item = item->next) {
|
|
||||||
if (item->number == number)
|
|
||||||
return (item);
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int read_services(void)
|
|
||||||
{
|
|
||||||
struct servent *se;
|
|
||||||
struct protoent *pe;
|
|
||||||
struct service *item;
|
|
||||||
|
|
||||||
setservent(1);
|
|
||||||
while ((se = getservent())) {
|
|
||||||
/* Allocate a service entry. */
|
|
||||||
item = (struct service *) malloc(sizeof(struct service));
|
|
||||||
if (item == NULL)
|
|
||||||
perror("netstat");
|
|
||||||
item->name = strdup(se->s_name);
|
|
||||||
item->number = se->s_port;
|
|
||||||
|
|
||||||
/* Fill it in. */
|
|
||||||
if (!strcmp(se->s_proto, "tcp")) {
|
|
||||||
add2list(&tcp_name, item);
|
|
||||||
} else if (!strcmp(se->s_proto, "udp")) {
|
|
||||||
add2list(&udp_name, item);
|
|
||||||
} else if (!strcmp(se->s_proto, "raw")) {
|
|
||||||
add2list(&raw_name, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endservent();
|
|
||||||
setprotoent(1);
|
|
||||||
while ((pe = getprotoent())) {
|
|
||||||
/* Allocate a service entry. */
|
|
||||||
item = (struct service *) malloc(sizeof(struct service));
|
|
||||||
if (item == NULL)
|
|
||||||
perror("netstat");
|
|
||||||
item->name = strdup(pe->p_name);
|
|
||||||
item->number = htons(pe->p_proto);
|
|
||||||
add2list(&raw_name, item);
|
|
||||||
}
|
|
||||||
endprotoent();
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *get_sname(int socknumber, char *proto, int numeric)
|
|
||||||
{
|
|
||||||
static char buffer[64], init = 0;
|
|
||||||
struct service *item;
|
|
||||||
|
|
||||||
if (socknumber == 0)
|
|
||||||
return ("*");
|
|
||||||
if (numeric) {
|
|
||||||
sprintf(buffer, "%d", ntohs(socknumber));
|
|
||||||
return (buffer);
|
|
||||||
}
|
|
||||||
if (!init) {
|
|
||||||
(void) read_services();
|
|
||||||
init = 1;
|
|
||||||
}
|
|
||||||
buffer[0] = '\0';
|
|
||||||
if (!strcmp(proto, "tcp")) {
|
|
||||||
if ((item = searchlist(tcp_name, socknumber)) != NULL)
|
|
||||||
sprintf(buffer, "%s", item->name);
|
|
||||||
} else if (!strcmp(proto, "udp")) {
|
|
||||||
if ((item = searchlist(udp_name, socknumber)) != NULL)
|
|
||||||
sprintf(buffer, "%s", item->name);
|
|
||||||
} else if (!strcmp(proto, "raw")) {
|
|
||||||
if ((item = searchlist(raw_name, socknumber)) != NULL)
|
|
||||||
sprintf(buffer, "%s", item->name);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!buffer[0])
|
|
||||||
sprintf(buffer, "%d", ntohs(socknumber));
|
|
||||||
return (buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_AFINET || HAVE_AFINET6 */
|
|
||||||
@@ -1,935 +0,0 @@
|
|||||||
/* Code to manipulate interface information, shared between ifconfig and
|
|
||||||
netstat.
|
|
||||||
|
|
||||||
10/1998 partly rewriten by Andi Kleen to support an interface list.
|
|
||||||
I don't claim that the list operations are efficient @).
|
|
||||||
|
|
||||||
8/2000 Andi Kleen make the list operations a bit more efficient.
|
|
||||||
People are crazy enough to use thousands of aliases now.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
|
|
||||||
#include <netipx/ipx.h>
|
|
||||||
#else
|
|
||||||
#include "ipx.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFECONET
|
|
||||||
#include <neteconet/ec.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_HWSLIP
|
|
||||||
#include <linux/if_slip.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "version.h"
|
|
||||||
#include "proc.h"
|
|
||||||
|
|
||||||
#include "interface.h"
|
|
||||||
#include "sockets.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "intl.h"
|
|
||||||
|
|
||||||
#ifdef IFF_PORTSEL
|
|
||||||
const char *if_port_text[][4] =
|
|
||||||
{
|
|
||||||
/* Keep in step with <linux/netdevice.h> */
|
|
||||||
{"unknown", NULL, NULL, NULL},
|
|
||||||
{"10base2", "bnc", "coax", NULL},
|
|
||||||
{"10baseT", "utp", "tpe", NULL},
|
|
||||||
{"AUI", "thick", "db15", NULL},
|
|
||||||
{"100baseT", NULL, NULL, NULL},
|
|
||||||
{"100baseTX", NULL, NULL, NULL},
|
|
||||||
{"100baseFX", NULL, NULL, NULL},
|
|
||||||
{NULL, NULL, NULL, NULL},
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IPV6_ADDR_ANY 0x0000U
|
|
||||||
|
|
||||||
#define IPV6_ADDR_UNICAST 0x0001U
|
|
||||||
#define IPV6_ADDR_MULTICAST 0x0002U
|
|
||||||
#define IPV6_ADDR_ANYCAST 0x0004U
|
|
||||||
|
|
||||||
#define IPV6_ADDR_LOOPBACK 0x0010U
|
|
||||||
#define IPV6_ADDR_LINKLOCAL 0x0020U
|
|
||||||
#define IPV6_ADDR_SITELOCAL 0x0040U
|
|
||||||
|
|
||||||
#define IPV6_ADDR_COMPATv4 0x0080U
|
|
||||||
|
|
||||||
#define IPV6_ADDR_SCOPE_MASK 0x00f0U
|
|
||||||
|
|
||||||
#define IPV6_ADDR_MAPPED 0x1000U
|
|
||||||
#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
|
|
||||||
|
|
||||||
int procnetdev_vsn = 1;
|
|
||||||
|
|
||||||
int ife_short;
|
|
||||||
|
|
||||||
int if_list_all = 0; /* do we have requested the complete proc list, yet? */
|
|
||||||
|
|
||||||
static struct interface *int_list, *int_last;
|
|
||||||
|
|
||||||
static int if_readlist_proc(char *);
|
|
||||||
|
|
||||||
static struct interface *if_cache_add(char *name)
|
|
||||||
{
|
|
||||||
struct interface *ife, **nextp, *new;
|
|
||||||
|
|
||||||
if (!int_list)
|
|
||||||
int_last = NULL;
|
|
||||||
|
|
||||||
/* the cache is sorted, so if we hit a smaller if, exit */
|
|
||||||
for (ife = int_last; ife; ife = ife->prev) {
|
|
||||||
int n = nstrcmp(ife->name, name);
|
|
||||||
if (n == 0)
|
|
||||||
return ife;
|
|
||||||
if (n < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
new(new);
|
|
||||||
safe_strncpy(new->name, name, IFNAMSIZ);
|
|
||||||
nextp = ife ? &ife->next : &int_list; // keep sorting
|
|
||||||
new->prev = ife;
|
|
||||||
new->next = *nextp;
|
|
||||||
if (new->next)
|
|
||||||
new->next->prev = new;
|
|
||||||
else
|
|
||||||
int_last = new;
|
|
||||||
*nextp = new;
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct interface *lookup_interface(char *name)
|
|
||||||
{
|
|
||||||
/* if we have read all, use it */
|
|
||||||
if (if_list_all)
|
|
||||||
return if_cache_add(name);
|
|
||||||
|
|
||||||
/* otherwise we read a limited list */
|
|
||||||
if (if_readlist_proc(name) < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return if_cache_add(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int for_all_interfaces(int SD, int (*doit) (int, struct interface *, void *), void *cookie)
|
|
||||||
{
|
|
||||||
struct interface *ife;
|
|
||||||
|
|
||||||
if (!if_list_all && (if_readlist() < 0))
|
|
||||||
return -1;
|
|
||||||
for (ife = int_list; ife; ife = ife->next) {
|
|
||||||
int err = doit(SD, ife, cookie);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int if_cache_free(void)
|
|
||||||
{
|
|
||||||
struct interface *ife;
|
|
||||||
while ((ife = int_list) != NULL) {
|
|
||||||
int_list = ife->next;
|
|
||||||
free(ife);
|
|
||||||
}
|
|
||||||
int_last = NULL;
|
|
||||||
if_list_all = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int if_readconf(void)
|
|
||||||
{
|
|
||||||
int numreqs = 30;
|
|
||||||
struct ifconf ifc;
|
|
||||||
struct ifreq *ifr;
|
|
||||||
int n, err = -1;
|
|
||||||
int skfd;
|
|
||||||
|
|
||||||
/* SIOCGIFCONF currently seems to only work properly on AF_INET sockets
|
|
||||||
(as of 2.1.128) */
|
|
||||||
skfd = get_socket_for_af(AF_INET);
|
|
||||||
if (skfd < 0) {
|
|
||||||
fprintf(stderr, _("warning: no inet socket available: %s\n"),
|
|
||||||
strerror(errno));
|
|
||||||
/* Try to soldier on with whatever socket we can get hold of. */
|
|
||||||
skfd = sockets_open(0);
|
|
||||||
if (skfd < 0)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifc.ifc_buf = NULL;
|
|
||||||
for (;;) {
|
|
||||||
ifc.ifc_len = sizeof(struct ifreq) * numreqs;
|
|
||||||
ifc.ifc_buf = xrealloc(ifc.ifc_buf, ifc.ifc_len);
|
|
||||||
|
|
||||||
if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
|
|
||||||
perror("SIOCGIFCONF");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
|
|
||||||
/* assume it overflowed and try again */
|
|
||||||
numreqs *= 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ifr = ifc.ifc_req;
|
|
||||||
for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
|
|
||||||
if_cache_add(ifr->ifr_name);
|
|
||||||
ifr++;
|
|
||||||
}
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
free(ifc.ifc_buf);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *get_name(char *name, char *p)
|
|
||||||
{
|
|
||||||
while (isspace(*p))
|
|
||||||
p++;
|
|
||||||
while (*p) {
|
|
||||||
if (isspace(*p))
|
|
||||||
break;
|
|
||||||
if (*p == ':') { /* could be an alias */
|
|
||||||
char *dot = p++;
|
|
||||||
while (*p && isdigit(*p)) p++;
|
|
||||||
if (*p == ':') {
|
|
||||||
/* Yes it is, backup and copy it. */
|
|
||||||
p = dot;
|
|
||||||
*name++ = *p++;
|
|
||||||
while (*p && isdigit(*p)) {
|
|
||||||
*name++ = *p++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* No, it isn't */
|
|
||||||
p = dot;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*name++ = *p++;
|
|
||||||
}
|
|
||||||
*name++ = '\0';
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
int procnetdev_version(char *buf)
|
|
||||||
{
|
|
||||||
if (strstr(buf, "compressed"))
|
|
||||||
return 3;
|
|
||||||
if (strstr(buf, "bytes"))
|
|
||||||
return 2;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_dev_fields(char *bp, struct interface *ife)
|
|
||||||
{
|
|
||||||
switch (procnetdev_vsn) {
|
|
||||||
case 3:
|
|
||||||
sscanf(bp,
|
|
||||||
"%Lu %Lu %lu %lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu %lu",
|
|
||||||
&ife->stats.rx_bytes,
|
|
||||||
&ife->stats.rx_packets,
|
|
||||||
&ife->stats.rx_errors,
|
|
||||||
&ife->stats.rx_dropped,
|
|
||||||
&ife->stats.rx_fifo_errors,
|
|
||||||
&ife->stats.rx_frame_errors,
|
|
||||||
&ife->stats.rx_compressed,
|
|
||||||
&ife->stats.rx_multicast,
|
|
||||||
|
|
||||||
&ife->stats.tx_bytes,
|
|
||||||
&ife->stats.tx_packets,
|
|
||||||
&ife->stats.tx_errors,
|
|
||||||
&ife->stats.tx_dropped,
|
|
||||||
&ife->stats.tx_fifo_errors,
|
|
||||||
&ife->stats.collisions,
|
|
||||||
&ife->stats.tx_carrier_errors,
|
|
||||||
&ife->stats.tx_compressed);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
sscanf(bp, "%Lu %Lu %lu %lu %lu %lu %Lu %Lu %lu %lu %lu %lu %lu",
|
|
||||||
&ife->stats.rx_bytes,
|
|
||||||
&ife->stats.rx_packets,
|
|
||||||
&ife->stats.rx_errors,
|
|
||||||
&ife->stats.rx_dropped,
|
|
||||||
&ife->stats.rx_fifo_errors,
|
|
||||||
&ife->stats.rx_frame_errors,
|
|
||||||
|
|
||||||
&ife->stats.tx_bytes,
|
|
||||||
&ife->stats.tx_packets,
|
|
||||||
&ife->stats.tx_errors,
|
|
||||||
&ife->stats.tx_dropped,
|
|
||||||
&ife->stats.tx_fifo_errors,
|
|
||||||
&ife->stats.collisions,
|
|
||||||
&ife->stats.tx_carrier_errors);
|
|
||||||
ife->stats.rx_multicast = 0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
sscanf(bp, "%Lu %lu %lu %lu %lu %Lu %lu %lu %lu %lu %lu",
|
|
||||||
&ife->stats.rx_packets,
|
|
||||||
&ife->stats.rx_errors,
|
|
||||||
&ife->stats.rx_dropped,
|
|
||||||
&ife->stats.rx_fifo_errors,
|
|
||||||
&ife->stats.rx_frame_errors,
|
|
||||||
|
|
||||||
&ife->stats.tx_packets,
|
|
||||||
&ife->stats.tx_errors,
|
|
||||||
&ife->stats.tx_dropped,
|
|
||||||
&ife->stats.tx_fifo_errors,
|
|
||||||
&ife->stats.collisions,
|
|
||||||
&ife->stats.tx_carrier_errors);
|
|
||||||
ife->stats.rx_bytes = 0;
|
|
||||||
ife->stats.tx_bytes = 0;
|
|
||||||
ife->stats.rx_multicast = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int if_readlist_proc(char *target)
|
|
||||||
{
|
|
||||||
FILE *fh;
|
|
||||||
char buf[512];
|
|
||||||
struct interface *ife;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
fh = fopen(_PATH_PROCNET_DEV, "r");
|
|
||||||
if (!fh) {
|
|
||||||
fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
|
|
||||||
_PATH_PROCNET_DEV, strerror(errno));
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
fgets(buf, sizeof buf, fh); /* eat line */
|
|
||||||
fgets(buf, sizeof buf, fh);
|
|
||||||
|
|
||||||
#if 0 /* pretty, but can't cope with missing fields */
|
|
||||||
fmt = proc_gen_fmt(_PATH_PROCNET_DEV, 1, fh,
|
|
||||||
"face", "", /* parsed separately */
|
|
||||||
"bytes", "%lu",
|
|
||||||
"packets", "%lu",
|
|
||||||
"errs", "%lu",
|
|
||||||
"drop", "%lu",
|
|
||||||
"fifo", "%lu",
|
|
||||||
"frame", "%lu",
|
|
||||||
"compressed", "%lu",
|
|
||||||
"multicast", "%lu",
|
|
||||||
"bytes", "%lu",
|
|
||||||
"packets", "%lu",
|
|
||||||
"errs", "%lu",
|
|
||||||
"drop", "%lu",
|
|
||||||
"fifo", "%lu",
|
|
||||||
"colls", "%lu",
|
|
||||||
"carrier", "%lu",
|
|
||||||
"compressed", "%lu",
|
|
||||||
NULL);
|
|
||||||
if (!fmt)
|
|
||||||
return -1;
|
|
||||||
#else
|
|
||||||
procnetdev_vsn = procnetdev_version(buf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
while (fgets(buf, sizeof buf, fh)) {
|
|
||||||
char *s, name[IFNAMSIZ];
|
|
||||||
s = get_name(name, buf);
|
|
||||||
ife = if_cache_add(name);
|
|
||||||
get_dev_fields(s, ife);
|
|
||||||
ife->statistics_valid = 1;
|
|
||||||
if (target && !strcmp(target,name))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ferror(fh)) {
|
|
||||||
perror(_PATH_PROCNET_DEV);
|
|
||||||
err = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
free(fmt);
|
|
||||||
#endif
|
|
||||||
fclose(fh);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int if_readlist(void)
|
|
||||||
{
|
|
||||||
/* caller will/should check not to call this too often
|
|
||||||
* (i.e. only if if_list_all == 0
|
|
||||||
*/
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
err |= if_readlist_proc(NULL);
|
|
||||||
err |= if_readconf();
|
|
||||||
|
|
||||||
if_list_all = 1;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Support for fetching an IPX address */
|
|
||||||
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
static int ipx_getaddr(int sock, int ft, struct ifreq *ifr)
|
|
||||||
{
|
|
||||||
((struct sockaddr_ipx *) &ifr->ifr_addr)->sipx_type = ft;
|
|
||||||
return ioctl(sock, SIOCGIFADDR, ifr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Fetch the interface configuration from the kernel. */
|
|
||||||
int if_fetch(struct interface *ife)
|
|
||||||
{
|
|
||||||
struct ifreq ifr;
|
|
||||||
int fd;
|
|
||||||
char *ifname = ife->name;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
|
|
||||||
return (-1);
|
|
||||||
ife->flags = ifr.ifr_flags;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
|
|
||||||
memset(ife->hwaddr, 0, 32);
|
|
||||||
else
|
|
||||||
memcpy(ife->hwaddr, ifr.ifr_hwaddr.sa_data, 8);
|
|
||||||
|
|
||||||
ife->type = ifr.ifr_hwaddr.sa_family;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0)
|
|
||||||
ife->metric = 0;
|
|
||||||
else
|
|
||||||
ife->metric = ifr.ifr_metric;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
|
|
||||||
ife->mtu = 0;
|
|
||||||
else
|
|
||||||
ife->mtu = ifr.ifr_mtu;
|
|
||||||
|
|
||||||
#ifdef HAVE_HWSLIP
|
|
||||||
if (ife->type == ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
|
|
||||||
ife->type == ARPHRD_SLIP6 || ife->type == ARPHRD_CSLIP6 ||
|
|
||||||
ife->type == ARPHRD_ADAPT) {
|
|
||||||
#ifdef SIOCGOUTFILL
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGOUTFILL, &ifr) < 0)
|
|
||||||
ife->outfill = 0;
|
|
||||||
else
|
|
||||||
ife->outfill = (unsigned int) ifr.ifr_data;
|
|
||||||
#endif
|
|
||||||
#ifdef SIOCGKEEPALIVE
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGKEEPALIVE, &ifr) < 0)
|
|
||||||
ife->keepalive = 0;
|
|
||||||
else
|
|
||||||
ife->keepalive = (unsigned int) ifr.ifr_data;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
|
|
||||||
memset(&ife->map, 0, sizeof(struct ifmap));
|
|
||||||
else
|
|
||||||
memcpy(&ife->map, &ifr.ifr_map, sizeof(struct ifmap));
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0)
|
|
||||||
memset(&ife->map, 0, sizeof(struct ifmap));
|
|
||||||
else
|
|
||||||
ife->map = ifr.ifr_map;
|
|
||||||
|
|
||||||
#ifdef HAVE_TXQUEUELEN
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(skfd, SIOCGIFTXQLEN, &ifr) < 0)
|
|
||||||
ife->tx_queue_len = -1; /* unknown value */
|
|
||||||
else
|
|
||||||
ife->tx_queue_len = ifr.ifr_qlen;
|
|
||||||
#else
|
|
||||||
ife->tx_queue_len = -1; /* unknown value */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFINET
|
|
||||||
/* IPv4 address? */
|
|
||||||
fd = get_socket_for_af(AF_INET);
|
|
||||||
if (fd >= 0) {
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
ifr.ifr_addr.sa_family = AF_INET;
|
|
||||||
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
|
|
||||||
ife->has_ip = 1;
|
|
||||||
ife->addr = ifr.ifr_addr;
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
|
|
||||||
memset(&ife->dstaddr, 0, sizeof(struct sockaddr));
|
|
||||||
else
|
|
||||||
ife->dstaddr = ifr.ifr_dstaddr;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
|
|
||||||
memset(&ife->broadaddr, 0, sizeof(struct sockaddr));
|
|
||||||
else
|
|
||||||
ife->broadaddr = ifr.ifr_broadaddr;
|
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
|
|
||||||
memset(&ife->netmask, 0, sizeof(struct sockaddr));
|
|
||||||
else
|
|
||||||
ife->netmask = ifr.ifr_netmask;
|
|
||||||
} else
|
|
||||||
memset(&ife->addr, 0, sizeof(struct sockaddr));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFATALK
|
|
||||||
/* DDP address maybe ? */
|
|
||||||
fd = get_socket_for_af(AF_APPLETALK);
|
|
||||||
if (fd >= 0) {
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
|
|
||||||
ife->ddpaddr = ifr.ifr_addr;
|
|
||||||
ife->has_ddp = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
/* Look for IPX addresses with all framing types */
|
|
||||||
fd = get_socket_for_af(AF_IPX);
|
|
||||||
if (fd >= 0) {
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (!ipx_getaddr(fd, IPX_FRAME_ETHERII, &ifr)) {
|
|
||||||
ife->has_ipx_bb = 1;
|
|
||||||
ife->ipxaddr_bb = ifr.ifr_addr;
|
|
||||||
}
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (!ipx_getaddr(fd, IPX_FRAME_SNAP, &ifr)) {
|
|
||||||
ife->has_ipx_sn = 1;
|
|
||||||
ife->ipxaddr_sn = ifr.ifr_addr;
|
|
||||||
}
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (!ipx_getaddr(fd, IPX_FRAME_8023, &ifr)) {
|
|
||||||
ife->has_ipx_e3 = 1;
|
|
||||||
ife->ipxaddr_e3 = ifr.ifr_addr;
|
|
||||||
}
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (!ipx_getaddr(fd, IPX_FRAME_8022, &ifr)) {
|
|
||||||
ife->has_ipx_e2 = 1;
|
|
||||||
ife->ipxaddr_e2 = ifr.ifr_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFECONET
|
|
||||||
/* Econet address maybe? */
|
|
||||||
fd = get_socket_for_af(AF_ECONET);
|
|
||||||
if (fd >= 0) {
|
|
||||||
strcpy(ifr.ifr_name, ifname);
|
|
||||||
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
|
|
||||||
ife->ecaddr = ifr.ifr_addr;
|
|
||||||
ife->has_econet = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_if_fetch(struct interface *ife)
|
|
||||||
{
|
|
||||||
if (if_fetch(ife) < 0) {
|
|
||||||
char *errmsg;
|
|
||||||
if (errno == ENODEV) {
|
|
||||||
/* Give better error message for this case. */
|
|
||||||
errmsg = _("Device not found");
|
|
||||||
} else {
|
|
||||||
errmsg = strerror(errno);
|
|
||||||
}
|
|
||||||
fprintf(stderr, _("%s: error fetching interface information: %s\n"),
|
|
||||||
ife->name, errmsg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_if_print(struct interface *ife, void *cookie)
|
|
||||||
{
|
|
||||||
int *opt_a = (int *) cookie;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
res = do_if_fetch(ife);
|
|
||||||
if (res >= 0) {
|
|
||||||
if ((ife->flags & IFF_UP) || *opt_a)
|
|
||||||
ife_print(ife);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ife_print_short(struct interface *ptr)
|
|
||||||
{
|
|
||||||
printf("%-5.5s ", ptr->name);
|
|
||||||
printf("%5d %-2d ", ptr->mtu, ptr->metric);
|
|
||||||
/* If needed, display the interface statistics. */
|
|
||||||
if (ptr->statistics_valid) {
|
|
||||||
printf("%8llu %6lu %6lu %6lu ",
|
|
||||||
ptr->stats.rx_packets, ptr->stats.rx_errors,
|
|
||||||
ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors);
|
|
||||||
printf("%8llu %6lu %6lu %6lu ",
|
|
||||||
ptr->stats.tx_packets, ptr->stats.tx_errors,
|
|
||||||
ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors);
|
|
||||||
} else {
|
|
||||||
printf("%-56s", _(" - no statistics available -"));
|
|
||||||
}
|
|
||||||
/* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
|
|
||||||
if (ptr->flags == 0)
|
|
||||||
printf(_("[NO FLAGS]"));
|
|
||||||
if (ptr->flags & IFF_ALLMULTI)
|
|
||||||
printf("A");
|
|
||||||
if (ptr->flags & IFF_BROADCAST)
|
|
||||||
printf("B");
|
|
||||||
if (ptr->flags & IFF_DEBUG)
|
|
||||||
printf("D");
|
|
||||||
if (ptr->flags & IFF_LOOPBACK)
|
|
||||||
printf("L");
|
|
||||||
if (ptr->flags & IFF_MULTICAST)
|
|
||||||
printf("M");
|
|
||||||
#ifdef HAVE_DYNAMIC
|
|
||||||
if (ptr->flags & IFF_DYNAMIC)
|
|
||||||
printf("d");
|
|
||||||
#endif
|
|
||||||
if (ptr->flags & IFF_PROMISC)
|
|
||||||
printf("P");
|
|
||||||
if (ptr->flags & IFF_NOTRAILERS)
|
|
||||||
printf("N");
|
|
||||||
if (ptr->flags & IFF_NOARP)
|
|
||||||
printf("O");
|
|
||||||
if (ptr->flags & IFF_POINTOPOINT)
|
|
||||||
printf("P");
|
|
||||||
if (ptr->flags & IFF_SLAVE)
|
|
||||||
printf("s");
|
|
||||||
if (ptr->flags & IFF_MASTER)
|
|
||||||
printf("m");
|
|
||||||
if (ptr->flags & IFF_RUNNING)
|
|
||||||
printf("R");
|
|
||||||
if (ptr->flags & IFF_UP)
|
|
||||||
printf("U");
|
|
||||||
/* DONT FORGET TO ADD THE FLAGS IN ife_print_long, too */
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ife_print_long(struct interface *ptr)
|
|
||||||
{
|
|
||||||
struct aftype *ap;
|
|
||||||
struct hwtype *hw;
|
|
||||||
int hf;
|
|
||||||
int can_compress = 0;
|
|
||||||
unsigned long long rx, tx, short_rx, short_tx;
|
|
||||||
const char *Rext = "b";
|
|
||||||
const char *Text = "b";
|
|
||||||
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
static struct aftype *ipxtype = NULL;
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFECONET
|
|
||||||
static struct aftype *ectype = NULL;
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFATALK
|
|
||||||
static struct aftype *ddptype = NULL;
|
|
||||||
#endif
|
|
||||||
#if HAVE_AFINET6
|
|
||||||
FILE *f;
|
|
||||||
char addr6[40], devname[20];
|
|
||||||
struct sockaddr_in6 sap;
|
|
||||||
int plen, scope, dad_status, if_idx;
|
|
||||||
extern struct aftype inet6_aftype;
|
|
||||||
char addr6p[8][5];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ap = get_afntype(ptr->addr.sa_family);
|
|
||||||
if (ap == NULL)
|
|
||||||
ap = get_afntype(0);
|
|
||||||
|
|
||||||
hf = ptr->type;
|
|
||||||
|
|
||||||
if (hf == ARPHRD_CSLIP || hf == ARPHRD_CSLIP6)
|
|
||||||
can_compress = 1;
|
|
||||||
|
|
||||||
hw = get_hwntype(hf);
|
|
||||||
if (hw == NULL)
|
|
||||||
hw = get_hwntype(-1);
|
|
||||||
|
|
||||||
printf(_("%-9.9s Link encap:%s "), ptr->name, hw->title);
|
|
||||||
/* For some hardware types (eg Ash, ATM) we don't print the
|
|
||||||
hardware address if it's null. */
|
|
||||||
if (hw->print != NULL && (! (hw_null_address(hw, ptr->hwaddr) &&
|
|
||||||
hw->suppress_null_addr)))
|
|
||||||
printf(_("HWaddr %s "), hw->print(ptr->hwaddr));
|
|
||||||
#ifdef IFF_PORTSEL
|
|
||||||
if (ptr->flags & IFF_PORTSEL) {
|
|
||||||
printf(_("Media:%s"), if_port_text[ptr->map.port][0]);
|
|
||||||
if (ptr->flags & IFF_AUTOMEDIA)
|
|
||||||
printf(_("(auto)"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
#if HAVE_AFINET
|
|
||||||
if (ptr->has_ip) {
|
|
||||||
printf(_(" %s addr:%s "), ap->name,
|
|
||||||
ap->sprint(&ptr->addr, 1));
|
|
||||||
if (ptr->flags & IFF_POINTOPOINT) {
|
|
||||||
printf(_(" P-t-P:%s "), ap->sprint(&ptr->dstaddr, 1));
|
|
||||||
}
|
|
||||||
if (ptr->flags & IFF_BROADCAST) {
|
|
||||||
printf(_(" Bcast:%s "), ap->sprint(&ptr->broadaddr, 1));
|
|
||||||
}
|
|
||||||
printf(_(" Mask:%s\n"), ap->sprint(&ptr->netmask, 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFINET6
|
|
||||||
/* FIXME: should be integrated into interface.c. */
|
|
||||||
|
|
||||||
if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
|
|
||||||
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
|
|
||||||
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
|
|
||||||
addr6p[4], addr6p[5], addr6p[6], addr6p[7],
|
|
||||||
&if_idx, &plen, &scope, &dad_status, devname) != EOF) {
|
|
||||||
if (!strcmp(devname, ptr->name)) {
|
|
||||||
sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
|
|
||||||
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
|
|
||||||
addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
|
|
||||||
inet6_aftype.input(1, addr6, (struct sockaddr *) &sap);
|
|
||||||
printf(_(" inet6 addr: %s/%d"),
|
|
||||||
inet6_aftype.sprint((struct sockaddr *) &sap, 1), plen);
|
|
||||||
printf(_(" Scope:"));
|
|
||||||
switch (scope) {
|
|
||||||
case 0:
|
|
||||||
printf(_("Global"));
|
|
||||||
break;
|
|
||||||
case IPV6_ADDR_LINKLOCAL:
|
|
||||||
printf(_("Link"));
|
|
||||||
break;
|
|
||||||
case IPV6_ADDR_SITELOCAL:
|
|
||||||
printf(_("Site"));
|
|
||||||
break;
|
|
||||||
case IPV6_ADDR_COMPATv4:
|
|
||||||
printf(_("Compat"));
|
|
||||||
break;
|
|
||||||
case IPV6_ADDR_LOOPBACK:
|
|
||||||
printf(_("Host"));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf(_("Unknown"));
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFIPX
|
|
||||||
if (ipxtype == NULL)
|
|
||||||
ipxtype = get_afntype(AF_IPX);
|
|
||||||
|
|
||||||
if (ipxtype != NULL) {
|
|
||||||
if (ptr->has_ipx_bb)
|
|
||||||
printf(_(" IPX/Ethernet II addr:%s\n"),
|
|
||||||
ipxtype->sprint(&ptr->ipxaddr_bb, 1));
|
|
||||||
if (ptr->has_ipx_sn)
|
|
||||||
printf(_(" IPX/Ethernet SNAP addr:%s\n"),
|
|
||||||
ipxtype->sprint(&ptr->ipxaddr_sn, 1));
|
|
||||||
if (ptr->has_ipx_e2)
|
|
||||||
printf(_(" IPX/Ethernet 802.2 addr:%s\n"),
|
|
||||||
ipxtype->sprint(&ptr->ipxaddr_e2, 1));
|
|
||||||
if (ptr->has_ipx_e3)
|
|
||||||
printf(_(" IPX/Ethernet 802.3 addr:%s\n"),
|
|
||||||
ipxtype->sprint(&ptr->ipxaddr_e3, 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFATALK
|
|
||||||
if (ddptype == NULL)
|
|
||||||
ddptype = get_afntype(AF_APPLETALK);
|
|
||||||
if (ddptype != NULL) {
|
|
||||||
if (ptr->has_ddp)
|
|
||||||
printf(_(" EtherTalk Phase 2 addr:%s\n"), ddptype->sprint(&ptr->ddpaddr, 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_AFECONET
|
|
||||||
if (ectype == NULL)
|
|
||||||
ectype = get_afntype(AF_ECONET);
|
|
||||||
if (ectype != NULL) {
|
|
||||||
if (ptr->has_econet)
|
|
||||||
printf(_(" econet addr:%s\n"), ectype->sprint(&ptr->ecaddr, 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printf(" ");
|
|
||||||
/* DONT FORGET TO ADD THE FLAGS IN ife_print_short, too */
|
|
||||||
if (ptr->flags == 0)
|
|
||||||
printf(_("[NO FLAGS] "));
|
|
||||||
if (ptr->flags & IFF_UP)
|
|
||||||
printf(_("UP "));
|
|
||||||
if (ptr->flags & IFF_BROADCAST)
|
|
||||||
printf(_("BROADCAST "));
|
|
||||||
if (ptr->flags & IFF_DEBUG)
|
|
||||||
printf(_("DEBUG "));
|
|
||||||
if (ptr->flags & IFF_LOOPBACK)
|
|
||||||
printf(_("LOOPBACK "));
|
|
||||||
if (ptr->flags & IFF_POINTOPOINT)
|
|
||||||
printf(_("POINTOPOINT "));
|
|
||||||
if (ptr->flags & IFF_NOTRAILERS)
|
|
||||||
printf(_("NOTRAILERS "));
|
|
||||||
if (ptr->flags & IFF_RUNNING)
|
|
||||||
printf(_("RUNNING "));
|
|
||||||
if (ptr->flags & IFF_NOARP)
|
|
||||||
printf(_("NOARP "));
|
|
||||||
if (ptr->flags & IFF_PROMISC)
|
|
||||||
printf(_("PROMISC "));
|
|
||||||
if (ptr->flags & IFF_ALLMULTI)
|
|
||||||
printf(_("ALLMULTI "));
|
|
||||||
if (ptr->flags & IFF_SLAVE)
|
|
||||||
printf(_("SLAVE "));
|
|
||||||
if (ptr->flags & IFF_MASTER)
|
|
||||||
printf(_("MASTER "));
|
|
||||||
if (ptr->flags & IFF_MULTICAST)
|
|
||||||
printf(_("MULTICAST "));
|
|
||||||
#ifdef HAVE_DYNAMIC
|
|
||||||
if (ptr->flags & IFF_DYNAMIC)
|
|
||||||
printf(_("DYNAMIC "));
|
|
||||||
#endif
|
|
||||||
/* DONT FORGET TO ADD THE FLAGS IN ife_print_short */
|
|
||||||
printf(_(" MTU:%d Metric:%d"),
|
|
||||||
ptr->mtu, ptr->metric ? ptr->metric : 1);
|
|
||||||
#ifdef SIOCSKEEPALIVE
|
|
||||||
if (ptr->outfill || ptr->keepalive)
|
|
||||||
printf(_(" Outfill:%d Keepalive:%d"),
|
|
||||||
ptr->outfill, ptr->keepalive);
|
|
||||||
#endif
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
/* If needed, display the interface statistics. */
|
|
||||||
|
|
||||||
if (ptr->statistics_valid) {
|
|
||||||
/* XXX: statistics are currently only printed for the primary address,
|
|
||||||
* not for the aliases, although strictly speaking they're shared
|
|
||||||
* by all addresses.
|
|
||||||
*/
|
|
||||||
printf(" ");
|
|
||||||
|
|
||||||
printf(_("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n"),
|
|
||||||
ptr->stats.rx_packets, ptr->stats.rx_errors,
|
|
||||||
ptr->stats.rx_dropped, ptr->stats.rx_fifo_errors,
|
|
||||||
ptr->stats.rx_frame_errors);
|
|
||||||
if (can_compress)
|
|
||||||
printf(_(" compressed:%lu\n"), ptr->stats.rx_compressed);
|
|
||||||
|
|
||||||
rx = ptr->stats.rx_bytes;
|
|
||||||
tx = ptr->stats.tx_bytes;
|
|
||||||
short_rx = rx * 10;
|
|
||||||
short_tx = tx * 10;
|
|
||||||
if (rx > 1125899906842624ull) {
|
|
||||||
short_rx /= 1125899906842624ull;
|
|
||||||
Rext = "PiB";
|
|
||||||
} else if (rx > 1099511627776ull) {
|
|
||||||
short_rx /= 1099511627776ull;
|
|
||||||
Rext = "TiB";
|
|
||||||
} else if (rx > 1073741824ull) {
|
|
||||||
short_rx /= 1073741824ull;
|
|
||||||
Rext = "GiB";
|
|
||||||
} else if (rx > 1048576) {
|
|
||||||
short_rx /= 1048576;
|
|
||||||
Rext = "MiB";
|
|
||||||
} else if (rx > 1024) {
|
|
||||||
short_rx /= 1024;
|
|
||||||
Rext = "KiB";
|
|
||||||
}
|
|
||||||
if (tx > 1125899906842624ull) {
|
|
||||||
short_tx /= 1125899906842624ull;
|
|
||||||
Text = "PiB";
|
|
||||||
} else if (tx > 1099511627776ull) {
|
|
||||||
short_tx /= 1099511627776ull;
|
|
||||||
Text = "TiB";
|
|
||||||
} else if (tx > 1073741824ull) {
|
|
||||||
short_tx /= 1073741824ull;
|
|
||||||
Text = "GiB";
|
|
||||||
} else if (tx > 1048576) {
|
|
||||||
short_tx /= 1048576;
|
|
||||||
Text = "MiB";
|
|
||||||
} else if (tx > 1024) {
|
|
||||||
short_tx /= 1024;
|
|
||||||
Text = "KiB";
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(" ");
|
|
||||||
printf(_("TX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n"),
|
|
||||||
ptr->stats.tx_packets, ptr->stats.tx_errors,
|
|
||||||
ptr->stats.tx_dropped, ptr->stats.tx_fifo_errors,
|
|
||||||
ptr->stats.tx_carrier_errors);
|
|
||||||
printf(_(" collisions:%lu "), ptr->stats.collisions);
|
|
||||||
if (can_compress)
|
|
||||||
printf(_("compressed:%lu "), ptr->stats.tx_compressed);
|
|
||||||
if (ptr->tx_queue_len != -1)
|
|
||||||
printf(_("txqueuelen:%d "), ptr->tx_queue_len);
|
|
||||||
printf("\n ");
|
|
||||||
printf(_("RX bytes:%llu (%lu.%lu %s) TX bytes:%llu (%lu.%lu %s)\n"),
|
|
||||||
rx, (unsigned long)(short_rx / 10),
|
|
||||||
(unsigned long)(short_rx % 10), Rext,
|
|
||||||
tx, (unsigned long)(short_tx / 10),
|
|
||||||
(unsigned long)(short_tx % 10), Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ptr->map.irq || ptr->map.mem_start || ptr->map.dma ||
|
|
||||||
ptr->map.base_addr >= 0x100)) {
|
|
||||||
printf(" ");
|
|
||||||
if (ptr->map.irq)
|
|
||||||
printf(_("Interrupt:%d "), ptr->map.irq);
|
|
||||||
if (ptr->map.base_addr >= 0x100) /* Only print devices using it for
|
|
||||||
I/O maps */
|
|
||||||
printf(_("Base address:0x%x "), ptr->map.base_addr);
|
|
||||||
if (ptr->map.mem_start) {
|
|
||||||
printf(_("Memory:%lx-%lx "), ptr->map.mem_start, ptr->map.mem_end);
|
|
||||||
}
|
|
||||||
if (ptr->map.dma)
|
|
||||||
printf(_("DMA chan:%x "), ptr->map.dma);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ife_print(struct interface *i)
|
|
||||||
{
|
|
||||||
if (ife_short)
|
|
||||||
ife_print_short(i);
|
|
||||||
else
|
|
||||||
ife_print_long(i);
|
|
||||||
}
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
struct user_net_device_stats {
|
|
||||||
unsigned long long rx_packets; /* total packets received */
|
|
||||||
unsigned long long tx_packets; /* total packets transmitted */
|
|
||||||
unsigned long long rx_bytes; /* total bytes received */
|
|
||||||
unsigned long long tx_bytes; /* total bytes transmitted */
|
|
||||||
unsigned long rx_errors; /* bad packets received */
|
|
||||||
unsigned long tx_errors; /* packet transmit problems */
|
|
||||||
unsigned long rx_dropped; /* no space in linux buffers */
|
|
||||||
unsigned long tx_dropped; /* no space available in linux */
|
|
||||||
unsigned long rx_multicast; /* multicast packets received */
|
|
||||||
unsigned long rx_compressed;
|
|
||||||
unsigned long tx_compressed;
|
|
||||||
unsigned long collisions;
|
|
||||||
|
|
||||||
/* detailed rx_errors: */
|
|
||||||
unsigned long rx_length_errors;
|
|
||||||
unsigned long rx_over_errors; /* receiver ring buff overflow */
|
|
||||||
unsigned long rx_crc_errors; /* recved pkt with crc error */
|
|
||||||
unsigned long rx_frame_errors; /* recv'd frame alignment error */
|
|
||||||
unsigned long rx_fifo_errors; /* recv'r fifo overrun */
|
|
||||||
unsigned long rx_missed_errors; /* receiver missed packet */
|
|
||||||
/* detailed tx_errors */
|
|
||||||
unsigned long tx_aborted_errors;
|
|
||||||
unsigned long tx_carrier_errors;
|
|
||||||
unsigned long tx_fifo_errors;
|
|
||||||
unsigned long tx_heartbeat_errors;
|
|
||||||
unsigned long tx_window_errors;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct interface {
|
|
||||||
struct interface *next, *prev;
|
|
||||||
char name[IFNAMSIZ]; /* interface name */
|
|
||||||
short type; /* if type */
|
|
||||||
short flags; /* various flags */
|
|
||||||
int metric; /* routing metric */
|
|
||||||
int mtu; /* MTU value */
|
|
||||||
int tx_queue_len; /* transmit queue length */
|
|
||||||
struct ifmap map; /* hardware setup */
|
|
||||||
struct sockaddr addr; /* IP address */
|
|
||||||
struct sockaddr dstaddr; /* P-P IP address */
|
|
||||||
struct sockaddr broadaddr; /* IP broadcast address */
|
|
||||||
struct sockaddr netmask; /* IP network mask */
|
|
||||||
struct sockaddr ipxaddr_bb; /* IPX network address */
|
|
||||||
struct sockaddr ipxaddr_sn; /* IPX network address */
|
|
||||||
struct sockaddr ipxaddr_e3; /* IPX network address */
|
|
||||||
struct sockaddr ipxaddr_e2; /* IPX network address */
|
|
||||||
struct sockaddr ddpaddr; /* Appletalk DDP address */
|
|
||||||
struct sockaddr ecaddr; /* Econet address */
|
|
||||||
int has_ip;
|
|
||||||
int has_ipx_bb;
|
|
||||||
int has_ipx_sn;
|
|
||||||
int has_ipx_e3;
|
|
||||||
int has_ipx_e2;
|
|
||||||
int has_ax25;
|
|
||||||
int has_ddp;
|
|
||||||
int has_econet;
|
|
||||||
char hwaddr[32]; /* HW address */
|
|
||||||
int statistics_valid;
|
|
||||||
struct user_net_device_stats stats; /* statistics */
|
|
||||||
int keepalive; /* keepalive value for SLIP */
|
|
||||||
int outfill; /* outfill value for SLIP */
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int if_fetch(struct interface *ife);
|
|
||||||
|
|
||||||
extern int for_all_interfaces(int, int (*)(int, struct interface *, void *), void *);
|
|
||||||
extern int if_cache_free(void);
|
|
||||||
extern struct interface *lookup_interface(char *name);
|
|
||||||
extern int if_readlist(void);
|
|
||||||
|
|
||||||
extern int do_if_fetch(struct interface *ife);
|
|
||||||
extern int do_if_print(struct interface *ife, void *cookie);
|
|
||||||
|
|
||||||
extern int procnetdev_version(char *buf);
|
|
||||||
extern int get_dev_fields(char *bp, struct interface *ife);
|
|
||||||
extern char * get_name(char *name, char *p);
|
|
||||||
|
|
||||||
extern void ife_print(struct interface *ptr);
|
|
||||||
|
|
||||||
extern int ife_short;
|
|
||||||
|
|
||||||
extern const char *if_port_text[][4];
|
|
||||||
|
|
||||||
/* Defines for poor glibc2.0 users, the feature check is done at runtime */
|
|
||||||
#if !defined(SIOCSIFTXQLEN)
|
|
||||||
#define SIOCSIFTXQLEN 0x8943
|
|
||||||
#define SIOCGIFTXQLEN 0x8942
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(ifr_qlen)
|
|
||||||
/* Actually it is ifru_ivalue, but that is not present in 2.0 kernel headers */
|
|
||||||
#define ifr_qlen ifr_ifru.ifru_mtu
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define HAVE_TXQUEUELEN
|
|
||||||
|
|
||||||
#define HAVE_DYNAMIC
|
|
||||||
#ifndef IFF_DYNAMIC
|
|
||||||
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
|
|
||||||
#endif
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
/* Dummy header for libintl.h */
|
|
||||||
|
|
||||||
#if I18N
|
|
||||||
#include <locale.h>
|
|
||||||
#undef __OPTIMIZE__
|
|
||||||
#include <libintl.h>
|
|
||||||
#define _(String) gettext((String))
|
|
||||||
#define N_(String) (String)
|
|
||||||
#else
|
|
||||||
#define _(String) (String)
|
|
||||||
#define N_(String) (String)
|
|
||||||
#endif
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/* lib-myconnect.c:
|
|
||||||
|
|
||||||
used by interfacedemo for "pyramid" LCD device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (C) 2005 Silvan Marco Fin <silvan@kernelconcepts.de>
|
|
||||||
|
|
||||||
This program 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
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* TCP connection to given host/port
|
|
||||||
*/
|
|
||||||
int get_connection(char *peername, int peerport)
|
|
||||||
{
|
|
||||||
struct sockaddr_in peeraddr;
|
|
||||||
int SocketDescriptor;
|
|
||||||
struct hostent *HostEntry;
|
|
||||||
|
|
||||||
HostEntry=gethostbyname(peername);
|
|
||||||
if (HostEntry==NULL)
|
|
||||||
{
|
|
||||||
switch (h_errno)
|
|
||||||
{
|
|
||||||
case HOST_NOT_FOUND:
|
|
||||||
printf("Host not found.\n");
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
case NO_ADDRESS:
|
|
||||||
printf("No IP found for valid hostname.\n");
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
case NO_RECOVERY:
|
|
||||||
printf("Name service error.\n");
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
case TRY_AGAIN:
|
|
||||||
printf("Temporary error in name resolution.\n");
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* peeraddr must contain information to reach the server */
|
|
||||||
memset(&peeraddr, 0, sizeof(peeraddr));
|
|
||||||
peeraddr.sin_family = AF_INET;
|
|
||||||
peeraddr.sin_port = htons(peerport);
|
|
||||||
peeraddr.sin_addr = *(struct in_addr *) HostEntry->h_addr;
|
|
||||||
|
|
||||||
SocketDescriptor=socket(PF_INET, SOCK_STREAM, 0);
|
|
||||||
if (SocketDescriptor==-1)
|
|
||||||
{
|
|
||||||
printf("Error creating socket\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connect(SocketDescriptor, (struct sockaddr *) &peeraddr, sizeof(peeraddr))==-1)
|
|
||||||
{
|
|
||||||
perror("Error connecting");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return SocketDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* lib-myconnect.h
|
|
||||||
|
|
||||||
used by interfacedemo for "pyramid" LCD device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (C) 2005 Silvan Marco Fin <silvan@kernelconcepts.de>
|
|
||||||
|
|
||||||
This program 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
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIB_MYCONNECT
|
|
||||||
#define LIB_MYCONNECT
|
|
||||||
|
|
||||||
/*
|
|
||||||
lib-myconnect.c:
|
|
||||||
|
|
||||||
used by interfacedemo to connect to a TCP socket.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* TCP connection to given host/port
|
|
||||||
*/
|
|
||||||
int get_connection(char *peername, int peerport);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
/* lib-mylcd.h
|
|
||||||
|
|
||||||
used by interfacedemo for "pyramid" LCD device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (C) 2005 Silvan Marco Fin <silvan@kernelconcepts.de>
|
|
||||||
|
|
||||||
This program 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
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "lib-mylcd.h"
|
|
||||||
|
|
||||||
#define DEBUG 0
|
|
||||||
|
|
||||||
/* Request information from LCDd */
|
|
||||||
|
|
||||||
int get_integer(int SD, char *request)
|
|
||||||
{
|
|
||||||
static char output[MAXREAD];
|
|
||||||
|
|
||||||
write(SD, request, strlen(request));
|
|
||||||
read(SD, output, MAXREAD-1);
|
|
||||||
return atoi(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Used to parse the reply from the hello-msg.
|
|
||||||
*/
|
|
||||||
void parse_hello(char *input)
|
|
||||||
{
|
|
||||||
char *next=input;
|
|
||||||
char *retval;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
retval=strtok(next, " ");
|
|
||||||
next=NULL;
|
|
||||||
if (retval==NULL)
|
|
||||||
break;
|
|
||||||
if (strcmp(retval, "wid")==0)
|
|
||||||
screen.width=atoi(strtok(next, " "));
|
|
||||||
if (strcmp(retval, "hgt")==0)
|
|
||||||
screen.height=atoi(strtok(next, " "));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_reply(char *input)
|
|
||||||
{
|
|
||||||
char *next=input;
|
|
||||||
char *retstr;
|
|
||||||
int retint=UNKNOWNKEY;
|
|
||||||
int inputlen=strlen(input);
|
|
||||||
int len=0;
|
|
||||||
|
|
||||||
printf("Eingabe: %s\n", input);
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
retstr=strtok(next, " \n");
|
|
||||||
next=NULL;
|
|
||||||
if (retstr==NULL)
|
|
||||||
{
|
|
||||||
input[0]=0; /* wofür war das? */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
len+=strlen(retstr)+1;
|
|
||||||
/* key detected? */
|
|
||||||
if (strcmp(retstr, "key")==0)
|
|
||||||
{
|
|
||||||
retstr=strtok(next, " \n");
|
|
||||||
len+=strlen(retstr)+1;
|
|
||||||
if (strcmp(retstr, "Escape")==0)
|
|
||||||
retint=ESCAPEKEY;
|
|
||||||
if (strcmp(retstr, "Down")==0)
|
|
||||||
retint=DOWNKEY;
|
|
||||||
if (strcmp(retstr, "Right")==0)
|
|
||||||
retint=RIGHTKEY;
|
|
||||||
if (strcmp(retstr, "Enter")==0)
|
|
||||||
retint=ENTERKEY;
|
|
||||||
|
|
||||||
input=strncpy(input, &input[len], inputlen-len+1);
|
|
||||||
|
|
||||||
return retint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NOKEY;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *basic_send(int SD, char *request)
|
|
||||||
{
|
|
||||||
static char answer[MAXREAD];
|
|
||||||
if (DEBUG)
|
|
||||||
printf("Sending command: %s\n", request);
|
|
||||||
memset(answer, 0, MAXREAD);
|
|
||||||
write(SD, request, strlen(request));
|
|
||||||
write(SD, "\n", strlen("\n"));
|
|
||||||
read(SD, answer, MAXREAD);
|
|
||||||
if (DEBUG)
|
|
||||||
printf("Answer to command to LCDproc: %s\n", answer);
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *basic_read(int SD)
|
|
||||||
{
|
|
||||||
static char answer[MAXREAD];
|
|
||||||
memset(answer, 0, MAXREAD);
|
|
||||||
if (DEBUG)
|
|
||||||
printf("Going for read!\n");
|
|
||||||
read(SD, answer, MAXREAD);
|
|
||||||
if (DEBUG)
|
|
||||||
printf("Read returned: %s\n", answer);
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/* lib-mylcd.h
|
|
||||||
|
|
||||||
used by interfacedemo for "pyramid" LCD device.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright (C) 2005 Silvan Marco Fin <silvan@kernelconcepts.de>
|
|
||||||
|
|
||||||
This program 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
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program 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 program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIB_MYLCD_H
|
|
||||||
#define LIB_MYLCD_H
|
|
||||||
|
|
||||||
#define MAXREAD 1024
|
|
||||||
/* Keys */
|
|
||||||
#define UNKNOWNKEY -1
|
|
||||||
#define NOKEY 0
|
|
||||||
#define DOWNKEY 1
|
|
||||||
#define ENTERKEY 2
|
|
||||||
#define RIGHTKEY 3
|
|
||||||
#define ESCAPEKEY 4
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
} screen;
|
|
||||||
|
|
||||||
|
|
||||||
/* Request information from LCDd
|
|
||||||
*/
|
|
||||||
int get_integer(int SD, char *request);
|
|
||||||
|
|
||||||
/* Used to parse the reply from the hello-msg.
|
|
||||||
*/
|
|
||||||
void parse_hello(char *input);
|
|
||||||
|
|
||||||
int parse_reply(char *input);
|
|
||||||
|
|
||||||
char *basic_send(int SD, char *request);
|
|
||||||
|
|
||||||
char *basic_read(int SD);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* lib/loopback.c This file contains the general hardware types.
|
|
||||||
*
|
|
||||||
* Version: $Id$
|
|
||||||
*
|
|
||||||
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
|
|
||||||
* Copyright 1993 MicroWalt Corporation
|
|
||||||
*
|
|
||||||
* Modifications:
|
|
||||||
* 1998-07-01 - Arnaldo Carvalho de Melo - GNU gettext instead of catgets
|
|
||||||
*
|
|
||||||
* This program 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.
|
|
||||||
*/
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <net/if_arp.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "net-support.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "intl.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/* Display an UNSPEC address. */
|
|
||||||
static char *pr_unspec(unsigned char *ptr)
|
|
||||||
{
|
|
||||||
static char buff[64];
|
|
||||||
char *pos;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
pos = buff;
|
|
||||||
for (i = 0; i < sizeof(struct sockaddr); i++) {
|
|
||||||
pos += sprintf(pos, "%02X-", (*ptr++ & 0377));
|
|
||||||
}
|
|
||||||
buff[strlen(buff) - 1] = '\0';
|
|
||||||
return (buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hwtype unspec_hwtype =
|
|
||||||
{
|
|
||||||
"unspec", NULL, /*"UNSPEC", */ -1, 0,
|
|
||||||
pr_unspec, NULL, NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hwtype loop_hwtype =
|
|
||||||
{
|
|
||||||
"loop", NULL, /*"Local Loopback", */ ARPHRD_LOOPBACK, 0,
|
|
||||||
NULL, NULL, NULL
|
|
||||||
};
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user