First step towards the v0.5 API. New configfile routines in use.
Configfile adapted. For drivers: configfile routines are available.
This commit is contained in:
@@ -1,114 +1,134 @@
|
||||
# LCDd.conf
|
||||
#
|
||||
# Each driver has a section which defines how it acts.
|
||||
# Drivers which are supported but unused are ignored.
|
||||
# Each driver section is begun by a "[drivername]" line
|
||||
# with no white space in the line at all.
|
||||
# This file contains the configuration for the LCDd server.
|
||||
#
|
||||
# The format is ini-file-like. It is divided into sections that start at
|
||||
# markers that look like [section]. Comments are all line-based comments,
|
||||
# and are lines that start with '#' or ';'.
|
||||
#
|
||||
# There is currently only one keyword for the driver sections:
|
||||
# The server has a 'central' section named [server]. Further each driver
|
||||
# has a section which defines how the driver acts.
|
||||
#
|
||||
# Arguments <str>
|
||||
# The drivers are activated by specifiying them in a driver= line in the
|
||||
# server section, like:
|
||||
#
|
||||
# These are the arguments to be passed to the
|
||||
# driver, without quotes. These are the same
|
||||
# arguments that the driver would have been passed
|
||||
# under the old command line format of
|
||||
# Driver=curses
|
||||
#
|
||||
# -d <driver> "<driverargs>"
|
||||
# This tells LCDd to use the curses driver. The first driver that is
|
||||
# loaded and is capable of output becomes 'the' output driver.
|
||||
# All extra drivers can only serve as input.
|
||||
# The default driver to use is curses.
|
||||
#
|
||||
# Before the driver sections, global settings can be set.
|
||||
# In the driver sections currently only one keyword is recognized:
|
||||
#
|
||||
# Global settings are:
|
||||
# Arguments="place arguments here"
|
||||
#
|
||||
# Driver <str>
|
||||
# These are the arguments to be passed to the driver, without quotes.
|
||||
# These are the same arguments that the driver would have been passed
|
||||
# under the old command line format of
|
||||
#
|
||||
# Use the specified driver. Second and further instances
|
||||
# of this command add input drivers to the server;
|
||||
# output is only to the first driver. The default driver
|
||||
# to use is curses.
|
||||
# -d <driver> "<driverargs>"
|
||||
#
|
||||
# Bind <addr>
|
||||
#
|
||||
# Bind to this address; defaults to 127.0.0.1
|
||||
#
|
||||
# Port <port>
|
||||
#
|
||||
# Listen on this specified port; defaults to 13666.
|
||||
#
|
||||
# Debug <level>
|
||||
#
|
||||
# Debugging level; defaults to 0 (no debugging output).
|
||||
#
|
||||
# Wait <time>
|
||||
# WaitTime <time>
|
||||
#
|
||||
# Set the default amount of time (in 1/8 seconds) to
|
||||
# display a screen on the LCD.
|
||||
#
|
||||
# User <user>
|
||||
#
|
||||
# User to run as. LCDd will drop its root priviledges,
|
||||
# if any, and run as this user instead.
|
||||
#
|
||||
# Comments are all line-based comments,
|
||||
# and are lines that start with one of '#', ';'
|
||||
# or '//' in the first columns.
|
||||
# Note that the -d option still works, but not allows arguments anymore.
|
||||
# If -d is specified on the command line, the Driver= options in the
|
||||
# config file are ignored.
|
||||
|
||||
Driver curses
|
||||
; Bind 172.16.3.69
|
||||
; Port 3777
|
||||
; Debug 5
|
||||
WaitTime 80
|
||||
User dgd
|
||||
|
||||
# Joystick driver
|
||||
[server]
|
||||
# Server section with all kinds of settings for the LCDd server
|
||||
|
||||
Driver=HD44780
|
||||
#Driver=curses
|
||||
#Driver=MtxOrb
|
||||
#
|
||||
# Tells the server to load the given drivers. Multiple lines can be given.
|
||||
|
||||
Bind=127.0.0.1
|
||||
# Tells the driver to bind to the given interface
|
||||
|
||||
Port=3777
|
||||
# Listen on this specified port; defaults to 13666.
|
||||
|
||||
#Debug=5
|
||||
# Sets the debugging level; defaults to 0 (no debugging output).
|
||||
|
||||
WaitTime=5
|
||||
# Sets the default time in seconds to displays a screen.
|
||||
|
||||
User=nobody
|
||||
# User to run as. LCDd will drop its root priviledges,
|
||||
# if any, and run as this user instead.
|
||||
|
||||
EnableServerScreen=yes
|
||||
# Enables the server screen also when other screens are active.
|
||||
|
||||
Foreground=no
|
||||
# The server will stay in the foreground if set to true.
|
||||
|
||||
|
||||
[joy]
|
||||
# Joystick driver
|
||||
|
||||
# LCDM001 driver
|
||||
|
||||
[lcdm001]
|
||||
Arguments -d /dev/lcd
|
||||
# LCDM driver
|
||||
|
||||
Arguments="-d /dev/lcd"
|
||||
|
||||
# MatrixOrbital driver
|
||||
|
||||
[MtxOrb]
|
||||
Arguments -d /dev/ttyS0 -t 20x2 -c 120
|
||||
# Matrix Orbital driver
|
||||
|
||||
Arguments="-d /dev/ttyS0 -t 20x2 -c 120"
|
||||
|
||||
# MatrixOrbital GLK driver
|
||||
|
||||
[GLK]
|
||||
# Matrix Orbital GLK driver
|
||||
|
||||
# CrystalFontz driver
|
||||
|
||||
[CFontz]
|
||||
# CrystalFontz driver
|
||||
|
||||
# Hitachi HD44780 driver
|
||||
|
||||
[HD44780]
|
||||
# Hitachi HD44780 driver
|
||||
# See docs/hd44780_howto.txt
|
||||
|
||||
Arguments="-p 0x378 -c 4bit -k -b"
|
||||
|
||||
# Meaning:
|
||||
# -p <port> Use the given port
|
||||
# -c <ct> Use the given connectiontype
|
||||
# -k Keypad support
|
||||
# -b Backlight support
|
||||
|
||||
# LB216
|
||||
|
||||
[LB216]
|
||||
# LB216 driver
|
||||
|
||||
# Text driver
|
||||
|
||||
[text]
|
||||
# Text driver
|
||||
|
||||
# BayRAD driver
|
||||
|
||||
[bayrad]
|
||||
# BayRAD driver
|
||||
|
||||
# Toshiba T6963 driver
|
||||
|
||||
[T6963]
|
||||
# Toshiba T6963 driver
|
||||
|
||||
# SVGAlib driver
|
||||
|
||||
[svgalib]
|
||||
# SVGAlib driver
|
||||
|
||||
# Curses driver
|
||||
|
||||
[curses]
|
||||
Arguments -f blue -b cyan -B red -t 20x4
|
||||
# Curses driver
|
||||
Arguments="-f blue -b cyan -B red -t 20x4"
|
||||
|
||||
# Meaning:
|
||||
# -f <color> Foreground color
|
||||
# -b <color> Background color
|
||||
# -B Big numbers size?
|
||||
# -t Display size
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
SUBDIRS=drivers
|
||||
sbin_PROGRAMS=LCDd
|
||||
LCDd_SOURCES= client_data.c client_data.h client_functions.c client_functions.h client_menu.h clients.c clients.h input.c input.h main.c main.h menu.c menu.h menus.c menus.h parse.c parse.h render.c render.h screen.c screen.h screenlist.c screenlist.h serverscreens.c serverscreens.h sock.c sock.h widget.c widget.h
|
||||
LCDd_SOURCES= client_data.c client_data.h client_functions.c client_functions.h client_menu.h clients.c clients.h input.c input.h main.c main.h menu.c menu.h menus.c menus.h parse.c parse.h render.c render.h screen.c screen.h screenlist.c screenlist.h serverscreens.c serverscreens.h sock.c sock.h widget.c widget.h configfile.c configfile.h drivers.c drivers.h
|
||||
LCDd_LDADD = drivers/libLCDdrivers.a ../shared/libLCDstuff.a @LIBCURSES@ @LIBIRMAN@ @LIBLIRC_CLIENT@ @LIBSVGA@
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
||||
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
* Defines routines to read ini-file-like files.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package
|
||||
*
|
||||
* (c) 2001 Joris Robijn
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
typedef struct key {
|
||||
char * name;
|
||||
char * value;
|
||||
struct key * next_key;
|
||||
} key;
|
||||
|
||||
typedef struct section {
|
||||
char * name;
|
||||
key * first_key;
|
||||
struct section * next_section;
|
||||
} section;
|
||||
|
||||
|
||||
static section * first_section = NULL;
|
||||
// Yes there is a static. It's C after all :)
|
||||
|
||||
|
||||
section * find_section( char * sectionname );
|
||||
section * add_section( char * sectionname );
|
||||
key * find_key( section * s, char * keyname, int skip );
|
||||
key * add_key( section * s, char * keyname, char * value );
|
||||
int process_config( section ** current_section, char (*get_next_char)(), char modify_section_allowed, char * source_descr );
|
||||
|
||||
|
||||
//// EXTERNAL FUNCTIONS ////
|
||||
|
||||
#define FILECHUNKSIZE 10
|
||||
|
||||
int config_read_file( char *filename )
|
||||
{
|
||||
FILE * f;
|
||||
char buf[FILECHUNKSIZE];
|
||||
int bytesread=0;
|
||||
int pos=0;
|
||||
section * curr_section = NULL;
|
||||
|
||||
// We use a nested fuction to transfer the characters from buffer to parser
|
||||
char get_next_char() {
|
||||
if( pos>=bytesread ) {
|
||||
if( !( bytesread = fread( buf, 1, FILECHUNKSIZE, f ))) {
|
||||
// We're at the end
|
||||
return 0;
|
||||
}
|
||||
pos = 0;
|
||||
}
|
||||
return buf[pos++];
|
||||
}
|
||||
|
||||
f = fopen( filename, "r" );
|
||||
if( f==NULL ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
process_config( &curr_section, get_next_char, 1, filename );
|
||||
|
||||
fclose( f );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int config_read_string( char *sectionname, char *str )
|
||||
// All the config parameters are placed in the given section in memory.
|
||||
{
|
||||
int pos=0;
|
||||
section * s;
|
||||
|
||||
// We use a nested fuction to transfer the characters from buffer to parser
|
||||
char get_next_char() {
|
||||
return str[pos++];
|
||||
}
|
||||
|
||||
if( !( s=find_section( sectionname ))) {
|
||||
s=add_section( sectionname );
|
||||
}
|
||||
|
||||
process_config( &s, get_next_char, 0, "command line" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *config_get_string( char * sectionname, char * keyname,
|
||||
int skip, char * default_value )
|
||||
{
|
||||
section * s;
|
||||
key * k;
|
||||
|
||||
s = find_section( sectionname );
|
||||
if( !s ) return default_value;
|
||||
k = find_key( s, keyname, skip );
|
||||
if( !k ) return default_value;
|
||||
|
||||
return k->value;
|
||||
|
||||
/* This is the safer way:
|
||||
|
||||
// Reallocate memory space for the return value
|
||||
string_storage = realloc( string_storage, ( strlen( k->value ) / 256 + 1) * 256 );
|
||||
strcpy( string_storage, k->value );
|
||||
|
||||
But then you also need a global static string_storage = NULL;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
unsigned char config_get_bool( char *sectionname, char *keyname,
|
||||
unsigned int skip, unsigned char default_value )
|
||||
{
|
||||
section * s;
|
||||
key * k;
|
||||
|
||||
s = find_section( sectionname );
|
||||
if( !s ) return default_value;
|
||||
k = find_key( s, keyname, skip );
|
||||
if( !k ) return default_value;
|
||||
|
||||
if( strcasecmp( k->value, "0" )==0 || strcasecmp( k->value, "false" )==0
|
||||
|| strcasecmp( k->value, "n" )==0 || strcasecmp( k->value, "no" )==0 ) {
|
||||
return 0;
|
||||
}
|
||||
if( strcasecmp( k->value, "1" )==0 || strcasecmp( k->value, "true" )==0
|
||||
|| strcasecmp( k->value, "y" )==0 || strcasecmp( k->value, "yes" )==0 ) {
|
||||
return 1;
|
||||
}
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
long int config_get_int( char *sectionname, char *keyname,
|
||||
unsigned int skip, long int default_value )
|
||||
{
|
||||
section * s;
|
||||
key * k;
|
||||
long int v;
|
||||
char * v_end;
|
||||
|
||||
s = find_section( sectionname );
|
||||
if( !s ) return default_value;
|
||||
k = find_key( s, keyname, skip );
|
||||
if( !k ) return default_value;
|
||||
|
||||
v = strtol( k->value, &v_end, 0 );
|
||||
if( v_end-(k->value) != strlen(k->value) ) {
|
||||
// Conversion not succesful
|
||||
return default_value;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
double config_get_float( char *sectionname, char *keyname,
|
||||
unsigned int skip, double default_value )
|
||||
{
|
||||
section * s;
|
||||
key * k;
|
||||
double v;
|
||||
char * v_end;
|
||||
|
||||
s = find_section( sectionname );
|
||||
if( !s ) return default_value;
|
||||
k = find_key( s, keyname, skip );
|
||||
if( !k ) return default_value;
|
||||
|
||||
v = strtod( k->value, &v_end );
|
||||
if( v_end-(k->value) != strlen(k->value) ) {
|
||||
// Conversion not succesful
|
||||
return default_value;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
int config_has_section( char *sectionname )
|
||||
{
|
||||
section * s;
|
||||
|
||||
s = find_section( sectionname );
|
||||
if( s ) return 1; else return 0;
|
||||
}
|
||||
|
||||
|
||||
int config_has_key( char *sectionname, char *keyname )
|
||||
{
|
||||
section * s;
|
||||
key * k;
|
||||
|
||||
int count = 0;
|
||||
|
||||
s = find_section( sectionname );
|
||||
if( !s ) return 0;
|
||||
|
||||
for( k=s->first_key; k; k=k->next_key ) {
|
||||
|
||||
// Did we find the right key ?
|
||||
if( strcasecmp( k->name, keyname ) == 0 ) {
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
void config_clear()
|
||||
{
|
||||
printf( "config_clear is unimplemented" );
|
||||
}
|
||||
|
||||
|
||||
//// INTERNAL FUNCTIONS ////
|
||||
|
||||
section * find_section( char * sectionname )
|
||||
{
|
||||
section * s;
|
||||
|
||||
for( s=first_section; s; s=s->next_section ) {
|
||||
if( strcasecmp( s->name, sectionname ) == 0 ) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return NULL; // not found
|
||||
}
|
||||
|
||||
section * add_section( char * sectionname )
|
||||
{
|
||||
section *s;
|
||||
section ** place = &first_section;
|
||||
|
||||
for( s=first_section; s; s=s->next_section )
|
||||
place = &(s->next_section);
|
||||
|
||||
*place = (section*) malloc( sizeof( section ));
|
||||
(*place)->name = (char*) malloc( strlen(sectionname)+1 );
|
||||
strcpy( (*place)->name, sectionname );
|
||||
(*place)->first_key = NULL;
|
||||
(*place)->next_section = NULL;
|
||||
|
||||
return (*place);
|
||||
}
|
||||
|
||||
key * find_key( section * s, char * keyname, int skip )
|
||||
{
|
||||
key * k;
|
||||
int count = 0;
|
||||
key * last_key = NULL;
|
||||
|
||||
// Check for NULL section
|
||||
if(!s) return NULL;
|
||||
|
||||
for( k=s->first_key; k; k=k->next_key ) {
|
||||
|
||||
// Did we find the right key ?
|
||||
if( strcasecmp( k->name, keyname ) == 0 ) {
|
||||
if( count == skip ) {
|
||||
return k;
|
||||
} else {
|
||||
count ++;
|
||||
last_key = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( skip == -1 ) {
|
||||
return last_key;
|
||||
}
|
||||
return NULL; // not found
|
||||
}
|
||||
|
||||
key * add_key( section * s, char * keyname, char * value )
|
||||
{
|
||||
key * k;
|
||||
|
||||
key ** place = &( s->first_key );
|
||||
|
||||
for( k=s->first_key; k; k=k->next_key )
|
||||
place = &(k->next_key);
|
||||
|
||||
*place = (key*) malloc( sizeof( key ));
|
||||
(*place)->name = (char*) malloc( strlen(keyname)+1 );
|
||||
strcpy( (*place)->name, keyname );
|
||||
(*place)->value = (char*) malloc( strlen(value)+1 );
|
||||
strcpy( (*place)->value, value );
|
||||
(*place)->next_key = NULL;
|
||||
|
||||
return (*place);
|
||||
}
|
||||
|
||||
|
||||
// Parser states
|
||||
#define ST_INITIAL 0
|
||||
#define ST_IGNORE 1
|
||||
#define ST_SECTIONNAME 2
|
||||
#define ST_KEYNAME 3
|
||||
#define ST_VALUE 10
|
||||
#define ST_QUOTEDVALUE 11
|
||||
#define ST_QUOTEDVALUE_ESCCHAR 12
|
||||
#define ST_INVALID_SECTIONNAME 23
|
||||
#define ST_INVALID_KEYNAME 24
|
||||
#define ST_INVALID_VALUE 30
|
||||
#define ST_INVALID_QUOTEDVALUE 31
|
||||
#define ST_END 99
|
||||
|
||||
// Limits
|
||||
#define MAXSECTIONNAMELENGTH 40
|
||||
#define MAXKEYNAMELENGTH 40
|
||||
#define MAXVALUELENGTH 200
|
||||
|
||||
|
||||
|
||||
int process_config( section ** current_section, char (*get_next_char)(), char modify_section_allowed, char * source_descr )
|
||||
{
|
||||
char state = ST_INITIAL;
|
||||
char ch;
|
||||
char sectionname[MAXSECTIONNAMELENGTH+1];
|
||||
int sectionname_pos;
|
||||
char keyname[MAXKEYNAMELENGTH+1];
|
||||
int keyname_pos;
|
||||
char value[MAXVALUELENGTH+1];
|
||||
int value_pos;
|
||||
int quote = 0;
|
||||
key * k;
|
||||
int line_nr = 1;
|
||||
|
||||
while( state != ST_END ) {
|
||||
|
||||
ch = get_next_char();
|
||||
|
||||
// Secretly keep count of the line numbers
|
||||
if( ch == '\n' ) {
|
||||
line_nr ++;
|
||||
}
|
||||
|
||||
switch( state ) {
|
||||
case ST_INITIAL:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case ' ':
|
||||
break;
|
||||
case '#':
|
||||
case ';':
|
||||
case '=':
|
||||
case ']':
|
||||
// It's a comment or an error
|
||||
state = ST_IGNORE;
|
||||
break;
|
||||
case '[':
|
||||
// It's a section name
|
||||
state = ST_SECTIONNAME;
|
||||
sectionname[0] = 0;
|
||||
sectionname_pos = 0;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
// It's a keyname
|
||||
state = ST_KEYNAME;
|
||||
keyname[0] = ch;
|
||||
keyname[1] = 0;
|
||||
keyname_pos = 1;
|
||||
}
|
||||
break;
|
||||
case ST_IGNORE:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ST_SECTIONNAME:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
fprintf( stderr, "Section name incorrectly closed on line %d of %s: %s\n", line_nr, source_descr, sectionname );
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
case '\r':
|
||||
case '\t':
|
||||
case ' ':
|
||||
case '"':
|
||||
case '[':
|
||||
fprintf( stderr, "Section name contains invalid chars on line %d of %s: %s\n", line_nr, source_descr, sectionname );
|
||||
state = ST_INVALID_SECTIONNAME;
|
||||
break;
|
||||
case ']':
|
||||
if( !( *current_section=find_section( sectionname ))) {
|
||||
*current_section=add_section( sectionname );
|
||||
}
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
case 0:
|
||||
fprintf( stderr, "Section name incorrectly closed on line %d of %s: %s\n", line_nr, source_descr, sectionname );
|
||||
break;
|
||||
default:
|
||||
if( sectionname_pos<MAXSECTIONNAMELENGTH ) {
|
||||
sectionname[sectionname_pos++] = ch;
|
||||
sectionname[sectionname_pos] = 0;
|
||||
} else {
|
||||
fprintf( stderr, "Section name too long on line %d of %s: %s\n", line_nr, source_descr, sectionname );
|
||||
state = ST_INVALID_SECTIONNAME;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_INVALID_SECTIONNAME:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
case ']':
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ST_KEYNAME:
|
||||
switch( ch ) {
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case ' ':
|
||||
fprintf( stderr, "Loose word found on line %d of %s: %s\n", line_nr, source_descr, keyname );
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
case '"':
|
||||
case '[':
|
||||
case ']':
|
||||
fprintf( stderr, "Key name contains invalid characters on line %d of %s: %s\n", line_nr, source_descr, keyname );
|
||||
state = ST_INVALID_KEYNAME;
|
||||
break;
|
||||
case '=':
|
||||
state = ST_VALUE;
|
||||
value[0] = 0;
|
||||
value_pos = 0;
|
||||
break;
|
||||
default:
|
||||
if( keyname_pos>=MAXKEYNAMELENGTH ) {
|
||||
fprintf( stderr, "Key name too long on line %d of %s: %s\n", line_nr, source_descr, keyname );
|
||||
state = ST_INVALID_KEYNAME;
|
||||
} else {
|
||||
keyname[keyname_pos++] = ch;
|
||||
keyname[keyname_pos] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_INVALID_KEYNAME:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
state = ST_INITIAL;
|
||||
case ' ':
|
||||
}
|
||||
break;
|
||||
case ST_VALUE:
|
||||
switch( ch ) {
|
||||
case '[':
|
||||
case ']':
|
||||
case '#':
|
||||
case ';':
|
||||
case '=':
|
||||
fprintf( stderr, "Value contains invalid characters on line %d of %s, at key: %s\n", line_nr, source_descr, keyname );
|
||||
state = ST_INVALID_VALUE;
|
||||
break;
|
||||
case '"':
|
||||
state = ST_QUOTEDVALUE;
|
||||
break;
|
||||
case 0:
|
||||
case '\n':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case ' ':
|
||||
// Value complete !
|
||||
if( ! *current_section ) {
|
||||
fprintf( stderr, "Data before any section on line %d of %s with key: %s\n", line_nr, source_descr, keyname );
|
||||
}
|
||||
else {
|
||||
// Store the value
|
||||
k = add_key( *current_section, keyname, value );
|
||||
}
|
||||
// And be ready for next thing...
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
default:
|
||||
if( value_pos<MAXVALUELENGTH ) {
|
||||
value[value_pos++] = ch;
|
||||
value[value_pos] = 0;
|
||||
} else {
|
||||
fprintf( stderr, "Value key is too long on line %d of %s, at key: %s\n", line_nr, source_descr, keyname );
|
||||
state = ST_INVALID_KEYNAME;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_INVALID_VALUE:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
case '"':
|
||||
state = ST_INVALID_QUOTEDVALUE;
|
||||
}
|
||||
break;
|
||||
case ST_QUOTEDVALUE:
|
||||
switch( ch ) {
|
||||
case 0:
|
||||
case '\n':
|
||||
fprintf( stderr, "String is incorrectly terminated on line %d of %s: %s\n", line_nr, source_descr, keyname );
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
case '\\':
|
||||
if( !quote ) {
|
||||
quote = 1;
|
||||
break;
|
||||
}
|
||||
case '"':
|
||||
if( !quote ) {
|
||||
state = ST_VALUE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if( quote ) {
|
||||
switch( ch ) {
|
||||
case 'n': ch = '\n'; break;
|
||||
case 'r': ch = '\r'; break;
|
||||
case 't': ch = '\t'; break;
|
||||
// default: litteral
|
||||
}
|
||||
quote = 0;
|
||||
}
|
||||
value[value_pos++] = ch;
|
||||
value[value_pos] = 0;
|
||||
}
|
||||
break;
|
||||
case ST_INVALID_QUOTEDVALUE:
|
||||
switch( ch ) {
|
||||
case '\n':
|
||||
state = ST_INITIAL;
|
||||
break;
|
||||
case '"':
|
||||
state = ST_INVALID_VALUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( ch == 0 ) {
|
||||
state = ST_END;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#ifndef CONFIGFILE_H
|
||||
#define CONFIGFILE_H
|
||||
|
||||
/*
|
||||
* Defines routines to read ini-file-like files.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package
|
||||
*
|
||||
* (c) 2001 Joris Robijn
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
int config_read_file( char *filename );
|
||||
// Opens the specified file and reads everything into memory.
|
||||
// Returns -1 on parsing errors.
|
||||
// Returns -2 if the file could not be opened or a read error occured.
|
||||
// Returns -16 if a malloc went wrong.
|
||||
|
||||
int config_read_string( char *sectionname, char *str );
|
||||
// Reads everything in the string into memory.
|
||||
// Returns -1 on parsing errors.
|
||||
// Returns -16 if a malloc went wrong.
|
||||
|
||||
unsigned char config_get_bool( char *sectionname, char *keyname,
|
||||
int skip, unsigned char default_value );
|
||||
// Tries to interpret a value in the config file as a boolean.
|
||||
// 0, false, no, n = false
|
||||
// 1, true, yes, y = true
|
||||
// If the key is not found or cannot be interpreted, the given default value is
|
||||
// returned.
|
||||
// The skip value can be used to iterate over multiple values with the same
|
||||
// key. Should be 0 to get the first one, 1 for the second etc. and -1 for the
|
||||
// last.
|
||||
|
||||
long int config_get_int( char *sectionname, char *keyname,
|
||||
int skip, long int default_value );
|
||||
// Tries to interpret a value in the config file as an integer.
|
||||
|
||||
double config_get_float( char *sectionname, char *keyname,
|
||||
int skip, double default_value );
|
||||
// Tries to interpret a value in the config file as a float.
|
||||
|
||||
char *config_get_string( char * sectionname, char * keyname,
|
||||
int skip, char * default_value );
|
||||
// Returns a pointer to the string associated with the specified key.
|
||||
// The string should never be modified, but for example immediately be
|
||||
// copied.
|
||||
|
||||
int config_has_section( char *sectionname );
|
||||
// Checks if a specified section exists.
|
||||
// Returns whether it exists.
|
||||
|
||||
int config_has_key( char *sectionname, char *keyname );
|
||||
// Checks if a specified key within the specified section exists.
|
||||
// Returns the number of times the key exists.
|
||||
|
||||
void config_clear();
|
||||
// Clears all data stored by the config_read_* functions.
|
||||
// Should be called if the config should be reread.
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Driver loader
|
||||
*
|
||||
* This code does all driver handling, loading, initializing, unloading.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "shared/LL.h"
|
||||
#include "shared/debug.h"
|
||||
#include "configfile.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
// lcd.h is used for the driver API definition
|
||||
|
||||
|
||||
LL * loaded_drivers = NULL;
|
||||
|
||||
long int empty_function() { return 0; }
|
||||
|
||||
static int fill_driver_functions( lcd_logical_driver * driver );
|
||||
|
||||
static int store_private_ptr(struct lcd_logical_driver * driver, void * private_data);
|
||||
|
||||
int
|
||||
load_driver ( char * name, char * filename, char * args )
|
||||
{
|
||||
int res;
|
||||
void (*driver_init)();
|
||||
lcd_logical_driver * driver;
|
||||
|
||||
debug ("load_driver(%s,%s,%s)\n", name,filename,args);
|
||||
|
||||
// First driver ?
|
||||
if( !loaded_drivers ) {
|
||||
// Create linked list
|
||||
loaded_drivers = LL_new ();
|
||||
if( !loaded_drivers ) {
|
||||
fprintf( stderr, "Error allocating driver list.\n" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find the driver in the array of driver types
|
||||
if ((driver_init = (void *) lcd_find_init(name)) == NULL) {
|
||||
// Driver not found
|
||||
fprintf( stderr, "invalid driver: %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Allocate memory for new driver struct
|
||||
driver = malloc( sizeof( lcd_logical_driver ));
|
||||
//memset( driver, 0, sizeof (lcd_logical_driver ));
|
||||
|
||||
lcd_ptr = driver;
|
||||
|
||||
fill_driver_functions( driver );
|
||||
|
||||
|
||||
// Rebind the init function and call it
|
||||
driver->init = driver_init;
|
||||
|
||||
res = driver->init( driver, args );
|
||||
if( res < 0 ) {
|
||||
fprintf( stderr, "res<0\n" );
|
||||
// driver load failed, don't add driver to list
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add driver to list
|
||||
LL_Push( loaded_drivers, driver );
|
||||
|
||||
// Check the driver type
|
||||
if( driver->daemonize ) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 1; // We can't see if it's an input driver only...
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
unload_all_drivers ()
|
||||
{
|
||||
lcd_logical_driver * driver;
|
||||
|
||||
debug ("unload_all_driver()\n");
|
||||
|
||||
while( (driver = LL_Pop( loaded_drivers )) != NULL ) {
|
||||
debug ("driver->close %p\n", driver );
|
||||
driver->close();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fill_driver_functions( lcd_logical_driver * driver )
|
||||
{
|
||||
driver->wid = LCD_STD_WIDTH;
|
||||
driver->hgt = LCD_STD_HEIGHT;
|
||||
|
||||
driver->cellwid = LCD_STD_CELL_WIDTH;
|
||||
driver->cellhgt = LCD_STD_CELL_HEIGHT;
|
||||
|
||||
driver->framebuf = NULL;
|
||||
driver->nextkey = NULL;
|
||||
|
||||
driver->daemonize = 1;
|
||||
|
||||
// Set pointers to empty function
|
||||
|
||||
// Basic functions
|
||||
driver->init = empty_function;
|
||||
driver->close = empty_function;
|
||||
|
||||
driver->getinfo = empty_function;
|
||||
// and don't forget other get_* functions later...
|
||||
|
||||
driver->clear = empty_function;
|
||||
driver->flush = empty_function;
|
||||
driver->string = empty_function;
|
||||
driver->chr = empty_function;
|
||||
|
||||
// Extended functions
|
||||
driver->init_vbar = empty_function;
|
||||
driver->vbar = empty_function;
|
||||
driver->init_hbar = empty_function;
|
||||
driver->hbar = empty_function;
|
||||
driver->init_num = empty_function;
|
||||
driver->num = empty_function;
|
||||
driver->heartbeat = empty_function;
|
||||
|
||||
// Hardware functions
|
||||
driver->contrast = empty_function;
|
||||
driver->backlight = empty_function;
|
||||
driver->output = empty_function;
|
||||
|
||||
// Uesrdef character functions
|
||||
driver->set_char = empty_function;
|
||||
driver->icon = empty_function;
|
||||
|
||||
// Key functions
|
||||
driver->getkey = empty_function;
|
||||
|
||||
// Ancient functions
|
||||
driver->flush_box = empty_function;
|
||||
driver->draw_frame = empty_function;
|
||||
|
||||
// Config file functions
|
||||
driver->config_get_bool = config_get_bool;
|
||||
driver->config_get_int = config_get_int;
|
||||
driver->config_get_float = config_get_float;
|
||||
driver->config_get_string = config_get_string;
|
||||
driver->config_has_section = config_has_section;
|
||||
driver->config_has_key = config_has_key;
|
||||
|
||||
// Driver private data
|
||||
driver->store_private_ptr = store_private_ptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
store_private_ptr(struct lcd_logical_driver * driver, void * private_data)
|
||||
{
|
||||
driver->private_data = private_data;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
int
|
||||
load_driver( char * name, char * filename, char * args );
|
||||
// returns:
|
||||
// <0 error
|
||||
// 0 ok, driver is an input driver only
|
||||
// 1 ok, driver is an output driver
|
||||
// 2 ok, driver is an output driver that needs to run in the foreground
|
||||
|
||||
int
|
||||
unload_all_drivers();
|
||||
@@ -257,7 +257,7 @@ lcd_list_drivers (void) {
|
||||
// This function initializes a few basics as well as the
|
||||
// "base" array. To initialize a specific driver, use the
|
||||
// lcd_add_driver() function.
|
||||
//
|
||||
//
|
||||
// This was eliminated; everything
|
||||
// done here is to be replaced by the use of lcd_add_driver()...
|
||||
int
|
||||
@@ -379,7 +379,6 @@ lcd_drv_patch_init (struct lcd_logical_driver *driver)
|
||||
*
|
||||
*/
|
||||
|
||||
static
|
||||
void *
|
||||
lcd_find_init (char *driver) {
|
||||
int i;
|
||||
|
||||
@@ -71,6 +71,26 @@ typedef struct lcd_logical_driver {
|
||||
void (*heartbeat) (int type);
|
||||
// more?
|
||||
|
||||
// Config file functions, filled by server
|
||||
char (*config_get_bool) (char * sectionname, char * keyname,
|
||||
int skip, char default_value);
|
||||
int (*config_get_int) (char * sectionname, char * keyname,
|
||||
int skip, int default_value);
|
||||
double (*config_get_float) (char * sectionname, char * keyname,
|
||||
int skip, double default_value);
|
||||
char *(*config_get_string) (char * sectionname, char * keyname,
|
||||
int skip, char * default_value);
|
||||
// Returns a string in server memory space.
|
||||
// Copy this string.
|
||||
int (*config_has_section) (char *sectionname);
|
||||
int (*config_has_key) (char *sectionname, char *keyname);
|
||||
|
||||
// Driver private data
|
||||
int (*store_private_ptr) (struct lcd_logical_driver * driver, void * private_data);
|
||||
void * private_data; // Filled by server by calling store_private_ptr()
|
||||
// Driver should cast this to it's own
|
||||
// private structure pointer
|
||||
|
||||
} lcd_logical_driver;
|
||||
|
||||
typedef struct lcd_physical_driver {
|
||||
|
||||
+361
-432
@@ -10,7 +10,7 @@
|
||||
Some of this stuff should probably be move elsewhere eventually,
|
||||
such as command-line handling and the main loop. main() is supposed
|
||||
to be "dumb".
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
@@ -30,7 +31,7 @@ extern int optind, optopt, opterr;
|
||||
|
||||
#include "shared/debug.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
#include "drivers.h"
|
||||
#include "sock.h"
|
||||
#include "clients.h"
|
||||
#include "screenlist.h"
|
||||
@@ -39,18 +40,30 @@ extern int optind, optopt, opterr;
|
||||
#include "render.h"
|
||||
#include "serverscreens.h"
|
||||
#include "input.h"
|
||||
#include "configfile.h"
|
||||
#include "drivers.h"
|
||||
#include "main.h"
|
||||
|
||||
#define MAX_TIMER 0x10000
|
||||
#define DEFAULT_USER "nobody"
|
||||
#define DEFAULT_CONFIG_FILE "/etc/LCDd.conf"
|
||||
#define DEFAULT_DRIVER "curses"
|
||||
|
||||
int debug_level = 0;
|
||||
#define DEFAULT_DEBUG_LEVEL 1
|
||||
#define DEFAULT_LCD_PORT LCDPORT
|
||||
#define DEFAULT_BIND_ADDR "127.0.0.1"
|
||||
#define DEFAULT_CONFIGFILE "/etc/LCDd.conf"
|
||||
#define DEFAULT_USER "nobody"
|
||||
#define DEFAULT_DRIVER "curses"
|
||||
#define DEFAULT_WAITTIME 8
|
||||
#define MAX_DRIVERS 8
|
||||
#define DEFAULT_DAEMON_MODE 1
|
||||
#define DEFAULT_ENABLE_SERVER_SCREEN 0
|
||||
|
||||
|
||||
/* Store some standard defines into vars... */
|
||||
char *version = VERSION;
|
||||
char *protocol_version = PROTOCOL_VERSION;
|
||||
char *build_date = __DATE__;
|
||||
|
||||
|
||||
/* Socket to bind to...
|
||||
|
||||
Using loopback is much more secure; it means that this port is
|
||||
@@ -59,8 +72,25 @@ char *build_date = __DATE__;
|
||||
Using variables for these means that (later) we can select which port
|
||||
and which address to bind to at run time. */
|
||||
|
||||
char bind_addr[64];
|
||||
int lcd_port = 0;
|
||||
|
||||
/**** Configuration variables ****/
|
||||
|
||||
// All are set to 'unset' values
|
||||
int debug_level = -1;
|
||||
int lcd_port = -1;
|
||||
char bind_addr[64] = "";
|
||||
char configfile[256] = "";
|
||||
char user[64] = "";
|
||||
|
||||
int daemon_mode = -1;
|
||||
int enable_server_screen = -1;
|
||||
|
||||
// The drivers and their driver parameters
|
||||
char *drivernames[MAX_DRIVERS];
|
||||
char *driverfilenames[MAX_DRIVERS];
|
||||
char *driverargs[MAX_DRIVERS];
|
||||
int num_drivers = 0;
|
||||
|
||||
|
||||
// The parameter structure and args[] should
|
||||
// be removed when getopt(3) is implemented,
|
||||
@@ -83,59 +113,30 @@ int lcd_port = 0;
|
||||
// {NULL, NULL},
|
||||
//};
|
||||
|
||||
|
||||
/**** Local functions ****/
|
||||
void exit_program (int val);
|
||||
void HelpScreen ();
|
||||
|
||||
// At this point, this function will only succeed;
|
||||
// all other options will stop the program.
|
||||
// However, it may not always be thus; so we prepared
|
||||
// for this possibility by making it return an int.
|
||||
//
|
||||
int drop_privs(char *user) {
|
||||
struct passwd *pwent;
|
||||
void clear_settings();
|
||||
int process_command_line (int argc, char **argv);
|
||||
int process_configfile (char *cfgfile);
|
||||
void set_default_settings();
|
||||
int daemonize();
|
||||
int init_sockets();
|
||||
int drop_privs(char *user);
|
||||
int init_drivers();
|
||||
int init_screens();
|
||||
void do_mainloop();
|
||||
|
||||
if (getuid() == 0 || geteuid() == 0) {
|
||||
if ((pwent = getpwnam(user)) == NULL) {
|
||||
if (errno) {
|
||||
perror("LCDd: getpwnam");
|
||||
exit(1);
|
||||
} else {
|
||||
fprintf(stderr, "user %s not a valid user!", user);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (setuid(pwent->pw_uid) < 0) {
|
||||
fprintf(stderr, "unable to switch to user %s\n", user);
|
||||
perror("LCDd: setuid");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_DRIVERS 12
|
||||
#define MAX_DRIVER_NAME_SIZE 64
|
||||
#define ESSENTIAL(f) {int r; if( ( r=f )!=0 ) return r;}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
char cfgfile[256] = DEFAULT_CONFIG_FILE;
|
||||
FILE *config;
|
||||
|
||||
int i, err;
|
||||
int daemon_mode = 1;
|
||||
int disable_server_screen = 1;
|
||||
|
||||
// FIXME: s is getting clobbered - in MANY places!!!
|
||||
screen *s = NULL;
|
||||
|
||||
//char *str, *ing; // strings for commandline handling
|
||||
char user[64];
|
||||
char c, buf[64], *driverlist[MAX_DRIVERS], *driverargs[MAX_DRIVERS];
|
||||
char linebuf[128], driver_name[64];
|
||||
int driver_index, list_index;
|
||||
//char *nullargs[64];
|
||||
//screen *s = NULL;
|
||||
//char buf[64];
|
||||
|
||||
signal (SIGINT, exit_program); // Ctrl-C will cause a clean exit...
|
||||
signal (SIGTERM, exit_program); // and "kill"...
|
||||
@@ -146,11 +147,6 @@ main (int argc, char **argv)
|
||||
//if (argc == 1)
|
||||
// HelpScreen ();
|
||||
|
||||
memset(driverlist, '\0', sizeof(driverlist));
|
||||
memset(bind_addr, '\0', sizeof(bind_addr));
|
||||
memset(user, '\0', sizeof(user));
|
||||
memset(driverargs, '\0', sizeof(driverargs));
|
||||
|
||||
/*
|
||||
* Settings in order of preference:
|
||||
*
|
||||
@@ -171,18 +167,99 @@ main (int argc, char **argv)
|
||||
* in the variable declaration...
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
// Open syslog facility
|
||||
openlog("LCDd", LOG_PID, LOG_DAEMON);
|
||||
syslog(LOG_NOTICE, "server version %s starting up (protocol version %s)",
|
||||
version, protocol_version);
|
||||
syslog(LOG_NOTICE, "server built on %s",
|
||||
build_date);
|
||||
|
||||
clear_settings();
|
||||
|
||||
// Read command line
|
||||
ESSENTIAL( process_command_line (argc, argv) );
|
||||
|
||||
// Read config file
|
||||
ESSENTIAL( process_configfile (configfile) );
|
||||
|
||||
// Set default values
|
||||
set_default_settings();
|
||||
|
||||
if (debug_level > 0)
|
||||
syslog(LOG_NOTICE, "debug level set to %d", debug_level);
|
||||
|
||||
ESSENTIAL( init_sockets() );
|
||||
ESSENTIAL( drop_privs(user) );
|
||||
ESSENTIAL( init_drivers() );
|
||||
ESSENTIAL( init_screens() );
|
||||
|
||||
#ifndef DEBUG
|
||||
// Now, go into daemon mode...
|
||||
if (daemon_mode) {
|
||||
syslog(LOG_NOTICE, "server forking to background");
|
||||
ESSENTIAL( daemonize() );
|
||||
} else {
|
||||
syslog(LOG_NOTICE, "server running in foreground");
|
||||
}
|
||||
#endif
|
||||
|
||||
do_mainloop();
|
||||
// This loop never stops; we'll get out only with a signal...
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
clear_settings ()
|
||||
{
|
||||
int i;
|
||||
|
||||
debug_level = -1;
|
||||
lcd_port = 0;
|
||||
bind_addr[0] = 0;
|
||||
configfile[0] = 0;
|
||||
user[0] = 0;
|
||||
daemon_mode = -1;
|
||||
enable_server_screen = -1;
|
||||
|
||||
default_duration = -1;
|
||||
|
||||
for( i=0; i < num_drivers; i++ ) {
|
||||
free( drivernames[i] );
|
||||
free( driverfilenames[i] );
|
||||
free( driverargs[i] );
|
||||
drivernames[i] = NULL;
|
||||
driverfilenames[i] = NULL;
|
||||
driverargs[i] = NULL;
|
||||
}
|
||||
num_drivers = 0;
|
||||
}
|
||||
|
||||
|
||||
/* parses arguments given on command line */
|
||||
int
|
||||
process_command_line (int argc, char **argv)
|
||||
{
|
||||
char c;
|
||||
char buf[64];
|
||||
|
||||
// analyze options here..
|
||||
while ((c = getopt(argc, argv, "a:p:d:hfiw:c:u:")) > 0) {
|
||||
// FIXME: Setting of c in this loop clobbers s!
|
||||
// s is set equivalent to c.
|
||||
switch(c) {
|
||||
case 'd':
|
||||
case 'd':
|
||||
// Add to a list of drivers to be initialized later...
|
||||
if (i < MAX_DRIVERS) {
|
||||
driverlist[i] = malloc(MAX_DRIVER_NAME_SIZE);
|
||||
strncpy(driverlist[i], optarg, MAX_DRIVER_NAME_SIZE);
|
||||
i++;
|
||||
if (num_drivers < MAX_DRIVERS) {
|
||||
drivernames[num_drivers] = malloc( strlen(optarg)+1 );
|
||||
driverfilenames[num_drivers] = malloc( strlen(optarg)+1 );
|
||||
driverargs[num_drivers] = malloc(1);
|
||||
|
||||
strcpy( drivernames[num_drivers], optarg );
|
||||
strcpy( driverfilenames[num_drivers], optarg );
|
||||
strcpy( driverargs[num_drivers], "");
|
||||
num_drivers ++;
|
||||
} else
|
||||
fprintf(stderr, "too many drivers!");
|
||||
break;
|
||||
@@ -202,10 +279,10 @@ main (int argc, char **argv)
|
||||
daemon_mode = 0;
|
||||
break;
|
||||
case 'c':
|
||||
strncpy(cfgfile, optarg, sizeof(cfgfile));
|
||||
strncpy(configfile, optarg, sizeof(configfile));
|
||||
break;
|
||||
case 'i':
|
||||
disable_server_screen = 1;
|
||||
enable_server_screen = 0;
|
||||
break;
|
||||
case 'w':
|
||||
default_duration = atoi(optarg);
|
||||
@@ -230,386 +307,246 @@ main (int argc, char **argv)
|
||||
if (optind < argc)
|
||||
fprintf(stderr, "non-option arguments!! BAD...");
|
||||
|
||||
openlog("LCDd", LOG_PID, LOG_DAEMON);
|
||||
syslog(LOG_NOTICE, "server version %s starting up (protocol version %s)",
|
||||
version, protocol_version);
|
||||
syslog(LOG_NOTICE, "server built on %s",
|
||||
build_date);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((config = fopen(cfgfile, "r")) == NULL) {
|
||||
syslog(LOG_WARNING, "no configuration file found... using defaults");
|
||||
} else {
|
||||
driver_index = -1;
|
||||
list_index = 0;
|
||||
|
||||
memset(linebuf, '\0', sizeof(linebuf));
|
||||
/* reads and parses configuration file */
|
||||
int
|
||||
process_configfile ( char *configfile )
|
||||
{
|
||||
int i;
|
||||
char * s;
|
||||
//char buf[64];
|
||||
|
||||
while (fgets(linebuf, sizeof(linebuf), config)) {
|
||||
if (linebuf[strlen(linebuf) - 1] == '\n')
|
||||
linebuf[strlen(linebuf) - 1] = '\0';
|
||||
// Read server settings
|
||||
|
||||
/*
|
||||
* Comment lines and empty lines...
|
||||
*
|
||||
*/
|
||||
config_read_file( configfile );
|
||||
|
||||
if (linebuf[0] == '\0' || // empty line
|
||||
linebuf[0] == '\n' || // empty line
|
||||
linebuf[0] == '\r' || // empty line
|
||||
linebuf[0] == '#' || // comment line (#)
|
||||
linebuf[0] == ';' || // comment line (;)
|
||||
(linebuf[0] == '/' && linebuf[1] == '/')) // comment line (//)
|
||||
continue;
|
||||
if( debug_level == -1 )
|
||||
debug_level = config_get_int( "server", "debug", 0, -1 );
|
||||
|
||||
/*
|
||||
* Driver section lines...
|
||||
*
|
||||
*/
|
||||
if( lcd_port == -1 )
|
||||
lcd_port = config_get_int( "server", "port", 0, -1 );
|
||||
|
||||
else if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') {
|
||||
driver_index = -1;
|
||||
if( bind_addr == "" )
|
||||
strncpy( bind_addr, config_get_string( "server", "bind", 0, "" ), sizeof(bind_addr));
|
||||
|
||||
linebuf[strlen(linebuf) - 1] = '\0';
|
||||
if( user == "" )
|
||||
strncpy( user, config_get_string( "server", "user", 0, "" ), sizeof(user));
|
||||
|
||||
// FIXME: This sets s to point to the current driver_name!!!
|
||||
strncpy(driver_name, linebuf + 1, sizeof(driver_name));
|
||||
|
||||
for (i = 0; i < MAX_DRIVERS; i++) {
|
||||
if (driverlist[i] == NULL)
|
||||
break;
|
||||
|
||||
if (strcasecmp(driver_name, driverlist[i]) == 0) {
|
||||
driver_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Driver section data lines
|
||||
*
|
||||
* These are only scanned for drivers that are being used...
|
||||
*
|
||||
*/
|
||||
|
||||
} else if (driver_index >= 0) {
|
||||
if (strncasecmp(linebuf, "arguments ", 10) == 0) {
|
||||
if ((driverargs[driver_index] = malloc(strlen(linebuf))) == NULL) {
|
||||
fprintf(stderr, "could not allocate memory for driver arguments!");
|
||||
exit(1);
|
||||
} else {
|
||||
strncpy(driverargs[driver_index], linebuf + 9, strlen(linebuf));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "unknown command line: %s\n", linebuf);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Global settings..
|
||||
*
|
||||
*/
|
||||
|
||||
// not in a driver section...
|
||||
if (strncasecmp(linebuf, "Driver ", 7) == 0) {
|
||||
if (driverlist[0] == NULL) { // check for arguments: override conf file drivers...
|
||||
driverlist[list_index] = malloc(MAX_DRIVER_NAME_SIZE);
|
||||
snprintf(driverlist[list_index++], MAX_DRIVER_NAME_SIZE, "%s", linebuf + 7);
|
||||
}
|
||||
} else if (strncasecmp(linebuf, "Bind ", 5) == 0) {
|
||||
if (bind_addr[0] == '\0')
|
||||
strncpy(bind_addr, linebuf + 5, sizeof(bind_addr));
|
||||
} else if (strncasecmp(linebuf, "User ", 5) == 0) {
|
||||
if (user[0] == '\0')
|
||||
strncpy(user, linebuf + 5, sizeof(user));
|
||||
} else if (strncasecmp(linebuf, "Port ", 5) == 0) {
|
||||
if (lcd_port == 0)
|
||||
lcd_port = atoi(linebuf + 5);
|
||||
} else if ((strncasecmp(linebuf, "Wait ", 5) == 0) ||
|
||||
(strncasecmp(linebuf, "WaitTime ", 9) == 0)) {
|
||||
char *p;
|
||||
|
||||
p = linebuf;
|
||||
while (*p != ' ') p++;
|
||||
p++;
|
||||
|
||||
default_duration = atoi(p);
|
||||
if ( default_duration < 16 || default_duration > 10000 ) {
|
||||
snprintf(buf, sizeof(buf),
|
||||
"wait time should be between 16 and 10000 (in 1/8ths of second), not %s\n", optarg);
|
||||
fprintf(stderr, "%s", buf);
|
||||
HelpScreen ();
|
||||
}
|
||||
} else if (strncasecmp(linebuf, "Debug ", 5) == 0) {
|
||||
debug_level = atoi(linebuf + 5);
|
||||
}
|
||||
}
|
||||
if( default_duration == -1 ) {
|
||||
default_duration = (config_get_float( "server", "waittime", 0, 0 ) * 1000000 / TIME_UNIT );
|
||||
if( default_duration == 0 )
|
||||
default_duration = -1;
|
||||
else if( default_duration < 16 ) {
|
||||
fprintf( stderr, "waittime should be at least 2 (seconds)\n" );
|
||||
return -1;
|
||||
}
|
||||
fclose(config);
|
||||
}
|
||||
|
||||
if (debug_level > 0)
|
||||
syslog(LOG_NOTICE, "debug level set to %d",
|
||||
debug_level);
|
||||
if( daemon_mode == -1 )
|
||||
daemon_mode = ! config_get_bool( "server", "foreground", 0, -1 );
|
||||
|
||||
// set defaults....
|
||||
if( enable_server_screen == -1 )
|
||||
enable_server_screen = config_get_bool( "server", "serverscreen", 0, -1 );
|
||||
|
||||
// Read drivers
|
||||
|
||||
// If drivers have been specified on the command line, then do not
|
||||
// use the driver list from the config file.
|
||||
if( num_drivers == 0 ) {
|
||||
// read the drivernames
|
||||
s = ""; // fill with anything
|
||||
|
||||
while( s ) {
|
||||
s = config_get_string( "server", "driver", num_drivers, "" );
|
||||
if( s ) {
|
||||
|
||||
drivernames[num_drivers] = malloc(strlen(s) + 1);
|
||||
driverfilenames[num_drivers] = malloc(1);
|
||||
driverargs[num_drivers] = malloc(1);
|
||||
|
||||
strcpy( drivernames[num_drivers], s );
|
||||
strcpy( driverfilenames[num_drivers], s );
|
||||
strcpy( driverargs[num_drivers], "" );
|
||||
|
||||
num_drivers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now read the driver options that the server needs
|
||||
// Drivers can read their own options later...
|
||||
for( i=0; i<num_drivers; i ++ ) {
|
||||
s = config_get_string( drivernames[i], "file", 0, "" );
|
||||
driverfilenames[i] = realloc( driverfilenames[i], strlen(s)+1 );
|
||||
strcpy (driverfilenames[i], s );
|
||||
|
||||
s = config_get_string( drivernames[i], "arguments", 0, "" );
|
||||
driverargs[i] = realloc( driverargs[i], strlen(s)+1 );
|
||||
strcpy (driverargs[i], s );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
set_default_settings()
|
||||
{
|
||||
// Set defaults into unfilled variables....
|
||||
|
||||
if (debug_level == -1)
|
||||
debug_level = DEFAULT_DEBUG_LEVEL;
|
||||
if (lcd_port == 0)
|
||||
lcd_port = DEFAULT_LCD_PORT;
|
||||
if (bind_addr[0] == 0)
|
||||
strncpy (bind_addr, DEFAULT_BIND_ADDR, sizeof(bind_addr));
|
||||
if (configfile[0] == 0)
|
||||
strncpy (configfile, DEFAULT_CONFIGFILE, sizeof(configfile));
|
||||
if (user[0] == '\0')
|
||||
strncpy(user, DEFAULT_USER, sizeof(user));
|
||||
if (bind_addr[0] == '\0')
|
||||
strncpy(bind_addr, DEFAULT_ADDR, sizeof(bind_addr));
|
||||
if (lcd_port == 0)
|
||||
lcd_port = LCDPORT;
|
||||
if (default_duration == 0)
|
||||
if (daemon_mode == -1)
|
||||
daemon_mode = DEFAULT_DAEMON_MODE;
|
||||
if (enable_server_screen == -1)
|
||||
enable_server_screen = DEFAULT_ENABLE_SERVER_SCREEN;
|
||||
|
||||
if (default_duration == -1)
|
||||
default_duration = DEFAULT_SCREEN_DURATION;
|
||||
|
||||
// Use default driver
|
||||
if (driverlist[0] == NULL) {
|
||||
driverlist[0] = malloc(MAX_DRIVER_NAME_SIZE);
|
||||
strcpy(driverlist[0], DEFAULT_DRIVER);
|
||||
if( num_drivers == 0 ) {
|
||||
drivernames[0] = malloc(strlen(DEFAULT_DRIVER)+1);
|
||||
strcpy(drivernames[0], DEFAULT_DRIVER);
|
||||
driverfilenames[0] = malloc(1);
|
||||
strcpy(driverfilenames[0], DEFAULT_DRIVER);
|
||||
driverargs[0] = malloc(1);
|
||||
strcpy(driverargs[0], "");
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This sets s equal to a value related to i
|
||||
// (bitshifted left?) FIX FIX FIX ARGH....
|
||||
|
||||
int
|
||||
daemonize()
|
||||
{
|
||||
int child;
|
||||
|
||||
switch ((child = fork ()) ) {
|
||||
case -1:
|
||||
syslog(LOG_ERR, "could not fork");
|
||||
return 1;
|
||||
case 0: // We are the child
|
||||
break;
|
||||
default: // We are the parent
|
||||
usleep (1500000); // Wait for child to initialize
|
||||
exit (0); /* PARENT EXITS */
|
||||
}
|
||||
// This line removed because it eats error messages...
|
||||
//setsid(); /* RELEASE TTY */
|
||||
//
|
||||
// Go thru all drivers and initialize all of them
|
||||
for (i = 0; i < MAX_DRIVERS; i++) {
|
||||
if (driverlist[i] == NULL)
|
||||
continue;
|
||||
|
||||
if ((err = lcd_add_driver (driverlist[i], driverargs[i])) > 0) {
|
||||
// if we are to run as a background daemon,
|
||||
// make this fact dependent on the output driver's
|
||||
// sayso - if the output driver desires, do NOT daemonize...
|
||||
if (daemon_mode == 1)
|
||||
daemon_mode = lcd_ptr->daemonize;
|
||||
} else {
|
||||
if (i == 0) {
|
||||
snprintf(buf, sizeof(buf), "error loading output driver %s...\n", driverlist[i]);
|
||||
fprintf(stderr, buf);
|
||||
exit(1);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "error loading input driver %s... continuing\n", driverlist[i]);
|
||||
fprintf(stderr, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DEBUG
|
||||
// Now, go into daemon mode...
|
||||
if (daemon_mode) {
|
||||
int child;
|
||||
|
||||
syslog(LOG_NOTICE, "server forking to background");
|
||||
|
||||
if ((child = fork ()) != 0) {
|
||||
usleep (1500000); // Wait for child to initialize
|
||||
exit (0); /* PARENT EXITS */
|
||||
}
|
||||
// This line removed because it eats error messages...
|
||||
//setsid(); /* RELEASE TTY */
|
||||
//
|
||||
// After this point, as a daemon, no error messages should
|
||||
// go to the console unless drastic; rather, they should go to syslog
|
||||
//
|
||||
// However, option processing is not yet done, nor is any initialization (!)
|
||||
// So we must wait until the main loop.
|
||||
} else {
|
||||
syslog(LOG_NOTICE, "server running in foreground");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set up lcd driver base system
|
||||
//lcd_init ("");
|
||||
|
||||
#ifdef IGNORE_THIS
|
||||
// Parse the command line now...
|
||||
// TODO: Move this to a separate function?
|
||||
// After this point, as a daemon, no error messages should
|
||||
// go to the console unless drastic; rather, they should go to syslog
|
||||
//
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
// However, option processing is not yet done, nor is any initialization (!)
|
||||
// So we must wait until the main loop.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* -d <driver> [ <driver_opts> ... ]
|
||||
* --driver <driver> [ <driver_opts> ... ]
|
||||
*
|
||||
* This option does not transfer to a getopt() version;
|
||||
* will have to change the option format...
|
||||
*/
|
||||
|
||||
if (0 == strcmp (argv[i], "-d") || 0 == strcmp (argv[i], "--driver")) {
|
||||
if (argc <= i + 1)
|
||||
HelpScreen ();
|
||||
str = argv[++i];
|
||||
ing = NULL;
|
||||
|
||||
// Check to see if the next parameter is intended for LCDd,
|
||||
// or if it should be passed to the driver...
|
||||
if (argc > i + 1) {
|
||||
int j, skip = 0;
|
||||
for (j = 1; args[j].lg; j++) // check each option except "help"
|
||||
if (!strcmp (argv[i + 1], args[j].sh) || !strcmp (argv[i + 1], args[j].lg))
|
||||
skip = 1;
|
||||
|
||||
if (!skip) {
|
||||
ing = argv[++i];
|
||||
}
|
||||
//else i++;
|
||||
}
|
||||
err = lcd_add_driver (str, ing);
|
||||
if (err <= 0) {
|
||||
printf ("Error loading driver %s. Continuing anyway...\n", str);
|
||||
}
|
||||
if ((err > 0) && (0 == strcmp (str, "curses")))
|
||||
daemon_mode = 0;
|
||||
|
||||
/*
|
||||
* -h
|
||||
* --help
|
||||
*
|
||||
* Help function
|
||||
*/
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-h") || 0 == strcmp (argv[i], "--help")) {
|
||||
HelpScreen ();
|
||||
}
|
||||
|
||||
/*
|
||||
* -f
|
||||
* --foreground
|
||||
*
|
||||
* Keep program in foreground; use for debugging, such
|
||||
* as with gdb
|
||||
*/
|
||||
|
||||
// Redundant, but it prevents errors...
|
||||
else if (0 == strcmp (argv[i], "-f") || 0 == strcmp (argv[i], "--foreground")) {
|
||||
daemon_mode = 0;
|
||||
|
||||
/*
|
||||
* -b [ "on" | "off" | "open" ]
|
||||
* --backlight [ "on" | "off" | "open" ]
|
||||
*
|
||||
* This should be a driver option, likely within the config file.
|
||||
* What IS "open" anyway?
|
||||
*/
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-b") || 0 == strcmp (argv[i], "--backlight")) {
|
||||
if (argc <= i + 1)
|
||||
HelpScreen ();
|
||||
str = argv[++i];
|
||||
if (0 == strcmp (str, "off"))
|
||||
backlight_state = backlight = BACKLIGHT_OFF;
|
||||
else if (0 == strcmp (str, "on"))
|
||||
backlight_state = backlight = BACKLIGHT_ON;
|
||||
else if (0 == strcmp (str, "open"))
|
||||
backlight = BACKLIGHT_OPEN;
|
||||
else
|
||||
HelpScreen ();
|
||||
|
||||
/*
|
||||
* -t
|
||||
* --type
|
||||
*
|
||||
* Type of LCD; this *DEFINITELY* should only be
|
||||
* a driver option.
|
||||
*/
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-t") || 0 == strcmp (argv[i], "--type")) {
|
||||
if (i + 1 > argc)
|
||||
HelpScreen ();
|
||||
else {
|
||||
int wid, hgt;
|
||||
|
||||
i++;
|
||||
sscanf (argv[i], "%ix%i", &wid, &hgt);
|
||||
if (wid > 80 || wid < 16 || hgt > 25 || hgt < 2) {
|
||||
fprintf (stderr, "LCDd: Invalid lcd size \"%s\". Using 20x4.\n", argv[i]);
|
||||
lcd_ptr->wid = 20;
|
||||
lcd_ptr->hgt = 4;
|
||||
} else {
|
||||
lcd_ptr->wid = wid;
|
||||
lcd_ptr->hgt = hgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* -i
|
||||
* --serverinfo
|
||||
*
|
||||
* Display server information during normal screen
|
||||
* updates when windows are active; server information
|
||||
* is always shown if there are no windows active.
|
||||
*/
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-i") || 0 == strcmp (argv[i], "--serverinfo")) {
|
||||
if (i + 1 > argc)
|
||||
HelpScreen ();
|
||||
else {
|
||||
i++;
|
||||
if (0 == strcmp (argv[i], "off"))
|
||||
disable_server_screen = 1;
|
||||
if (0 == strcmp (argv[i], "on"))
|
||||
disable_server_screen = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* -w <1/8 secs>
|
||||
* --waittime <1/8 secs>
|
||||
*
|
||||
* Sets the default duration that a screen
|
||||
* is present.
|
||||
*/
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-w") || 0 == strcmp (argv[i], "--waittime")) {
|
||||
if (i + 1 > argc)
|
||||
HelpScreen ();
|
||||
else {
|
||||
int tmp ;
|
||||
i++;
|
||||
tmp = atoi( argv[i] );
|
||||
if ( tmp < 16 || tmp > 10000 ) {
|
||||
printf ("Wait time should be between 16 and 10000 (1/8ths of second), not %s\n", argv[i]);
|
||||
HelpScreen ();
|
||||
} else {
|
||||
default_duration = tmp ;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* End of valid options
|
||||
*/
|
||||
|
||||
printf ("Invalid parameter: %s\n", argv[i]);
|
||||
HelpScreen ();
|
||||
}
|
||||
} else {
|
||||
printf("non-option: %s", argv[i]);
|
||||
HelpScreen ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// switch to a different user for the real work...
|
||||
if (lcd_port >= 1024) // unpriviledged port
|
||||
drop_privs(user);
|
||||
int
|
||||
init_sockets ()
|
||||
{
|
||||
|
||||
if (sock_create_server (&bind_addr, lcd_port) <= 0) {
|
||||
syslog(LOG_ERR, "error opening socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lcd_port < 1024) // priviledged port
|
||||
drop_privs(user);
|
||||
|
||||
// Now init a bunch of required stuff...
|
||||
|
||||
if (client_init () < 0) {
|
||||
syslog(LOG_ERR, "error initializing client list");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_drivers()
|
||||
{
|
||||
int i, res;
|
||||
char buf[64];
|
||||
|
||||
int output_loaded = 0;
|
||||
|
||||
// FIXME: This sets s equal to a value related to i
|
||||
// (bitshifted left?) FIX FIX FIX ARGH....
|
||||
//
|
||||
// Go thru all drivers and initialize all of them
|
||||
for (i = 0; i < num_drivers; i++) {
|
||||
|
||||
res = load_driver (drivernames[i], driverfilenames[i], driverargs[i]);
|
||||
if (res >= 0) {
|
||||
// Load went OK
|
||||
|
||||
switch( res ) {
|
||||
case 0: // Driver does input only
|
||||
break;
|
||||
case 1: // Driver does output
|
||||
output_loaded = 1;
|
||||
break;
|
||||
case 2: // Driver does output in foreground (don't daemonize)
|
||||
if ( !output_loaded ) {
|
||||
daemon_mode = 1;
|
||||
}
|
||||
output_loaded = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "Could not load driver %s\n", drivernames[i]);
|
||||
fprintf(stderr, buf);
|
||||
}
|
||||
}
|
||||
|
||||
// Do we have a running output driver ?
|
||||
if ( output_loaded ) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int drop_privs(char *user)
|
||||
{
|
||||
struct passwd *pwent;
|
||||
|
||||
if (getuid() == 0 || geteuid() == 0) {
|
||||
if ((pwent = getpwnam(user)) == NULL) {
|
||||
if (errno) {
|
||||
perror("LCDd: getpwnam");
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, "user %s not a valid user!", user);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (setuid(pwent->pw_uid) < 0) {
|
||||
fprintf(stderr, "unable to switch to user %s\n", user);
|
||||
perror("LCDd: setuid");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_screens ()
|
||||
{
|
||||
if (screenlist_init () < 0) {
|
||||
syslog(LOG_ERR, "error initializing screen list");
|
||||
return 1;
|
||||
@@ -618,22 +555,20 @@ main (int argc, char **argv)
|
||||
if (server_screen_init () < 0) {
|
||||
syslog(LOG_ERR, "error initializing server screens");
|
||||
return 1;
|
||||
} else if (disable_server_screen) {
|
||||
} else if (!enable_server_screen) {
|
||||
server_screen->priority = 256;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Probably a better place to fork
|
||||
//
|
||||
// Main loop...
|
||||
|
||||
syslog(LOG_NOTICE, "using %dx%d LCD with cells %dx%d",
|
||||
lcd_ptr->wid, lcd_ptr->hgt, lcd_ptr->cellwid, lcd_ptr->cellhgt);
|
||||
if (debug_level > 2)
|
||||
syslog(LOG_DEBUG, "framebuffer at %0X",
|
||||
lcd_ptr->framebuf);
|
||||
void
|
||||
do_mainloop ()
|
||||
{
|
||||
screen *s = NULL;
|
||||
//char buf[64];
|
||||
|
||||
// FIXME: s should still be null from initialization.... what's happening here?!
|
||||
s = NULL;
|
||||
while (1) {
|
||||
sock_poll_clients (); // poll clients for input
|
||||
parse_all_client_messages (); // analyze input from network clients
|
||||
@@ -686,8 +621,6 @@ main (int argc, char **argv)
|
||||
|
||||
// Quit!
|
||||
exit_program (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -709,26 +642,22 @@ exit_program (int val)
|
||||
|
||||
syslog(LOG_NOTICE, buf); // send message to syslog
|
||||
|
||||
if (lcd_ptr->framebuf != NULL) {
|
||||
goodbye_screen (); // display goodbye screen on LCD display
|
||||
lcd_shutdown (); // release driver memory and file descriptors
|
||||
|
||||
client_shutdown (); // shutdown clients (must come first)
|
||||
goodbye_screen (); // display goodbye screen on LCD display
|
||||
unload_all_drivers (); // release driver memory and file descriptors
|
||||
|
||||
client_shutdown (); // shutdown clients (must come first)
|
||||
screenlist_shutdown (); // shutdown screens (must come after client_shutdown)
|
||||
sock_close_all (); // close all open sockets (must come after client_shutdown)
|
||||
|
||||
screenlist_shutdown (); // shutdown screens (must come after client_shutdown)
|
||||
sock_close_all (); // close all open sockets (must come after client_shutdown)
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HelpScreen ()
|
||||
{
|
||||
// This cleans up any messes on the display output if needed...
|
||||
if (lcd_ptr)
|
||||
if (lcd_ptr->framebuf != NULL)
|
||||
lcd_ptr->close();
|
||||
|
||||
printf ("\nLCDd Server Daemon (part of lcdproc), %s\n", version);
|
||||
printf ("Copyright (c) 1999 Scott Scriven, William Ferrell, and misc contributors\n");
|
||||
@@ -737,7 +666,7 @@ HelpScreen ()
|
||||
printf ("Available options are:\n");
|
||||
|
||||
printf ("\t-h\t\tDisplay this help screen\n");
|
||||
printf ("\t-c <config>\tUse a configuration file other than %s\n", DEFAULT_CONFIG_FILE);
|
||||
printf ("\t-c <config>\tUse a configuration file other than %s\n", DEFAULT_CONFIGFILE);
|
||||
//printf ("\t-t\t\tSelect an LCD size (20x4, 16x2, etc...)\n");
|
||||
printf ("\t-d <driver>\tAdd a driver to use (output only to first)\n");
|
||||
//printf ("\t\t\tCFontz, curses, HD44780, irmanin, joy,\n\t\t\tMtxOrb, LB216, text\n");
|
||||
|
||||
Reference in New Issue
Block a user