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:
robijn
2001-10-24 14:26:15 +00:00
parent 15325e8e3b
commit dc0f01850b
9 changed files with 1288 additions and 500 deletions
+83 -63
View File
@@ -1,114 +1,134 @@
# LCDd.conf # LCDd.conf
# #
# Each driver has a section which defines how it acts. # This file contains the configuration for the LCDd server.
# 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.
# #
# There is currently only one keyword for the driver sections: # 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 ';'.
# #
# Arguments <str> # The server has a 'central' section named [server]. Further each driver
# has a section which defines how the driver acts.
# #
# These are the arguments to be passed to the # The drivers are activated by specifiying them in a driver= line in the
# driver, without quotes. These are the same # server section, like:
# arguments that the driver would have been passed #
# Driver=curses
#
# 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.
#
# In the driver sections currently only one keyword is recognized:
#
# Arguments="place arguments here"
#
# 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 # under the old command line format of
# #
# -d <driver> "<driverargs>" # -d <driver> "<driverargs>"
# #
# Before the driver sections, global settings can be set. # 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
# Global settings are: # config file are ignored.
#
# Driver <str>
# [server]
# Use the specified driver. Second and further instances # Server section with all kinds of settings for the LCDd server
# of this command add input drivers to the server;
# output is only to the first driver. The default driver Driver=HD44780
# to use is curses. #Driver=curses
# #Driver=MtxOrb
# Bind <addr>
#
# Bind to this address; defaults to 127.0.0.1
#
# Port <port>
# #
# 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. # Listen on this specified port; defaults to 13666.
#
# Debug <level> #Debug=5
# # Sets the debugging level; defaults to 0 (no debugging output).
# Debugging level; defaults to 0 (no debugging output).
# WaitTime=5
# Wait <time> # Sets the default time in seconds to displays a screen.
# WaitTime <time>
# User=nobody
# 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, # User to run as. LCDd will drop its root priviledges,
# if any, and run as this user instead. # 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.
Driver curses EnableServerScreen=yes
; Bind 172.16.3.69 # Enables the server screen also when other screens are active.
; Port 3777
; Debug 5 Foreground=no
WaitTime 80 # The server will stay in the foreground if set to true.
User dgd
# Joystick driver
[joy] [joy]
# Joystick driver
# LCDM001 driver
[lcdm001] [lcdm001]
Arguments -d /dev/lcd # LCDM driver
Arguments="-d /dev/lcd"
# MatrixOrbital driver
[MtxOrb] [MtxOrb]
Arguments -d /dev/ttyS0 -t 20x2 -c 120 # Matrix Orbital driver
Arguments="-d /dev/ttyS0 -t 20x2 -c 120"
# MatrixOrbital GLK driver
[GLK] [GLK]
# Matrix Orbital GLK driver
# CrystalFontz driver
[CFontz] [CFontz]
# CrystalFontz driver
# Hitachi HD44780 driver
[HD44780] [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]
# LB216 driver
# Text driver
[text] [text]
# Text driver
# BayRAD driver
[bayrad] [bayrad]
# BayRAD driver
# Toshiba T6963 driver
[T6963] [T6963]
# Toshiba T6963 driver
# SVGAlib driver
[svgalib] [svgalib]
# SVGAlib driver
# Curses driver
[curses] [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
View File
@@ -1,5 +1,5 @@
SUBDIRS=drivers SUBDIRS=drivers
sbin_PROGRAMS=LCDd 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@ LCDd_LDADD = drivers/libLCDdrivers.a ../shared/libLCDstuff.a @LIBCURSES@ @LIBIRMAN@ @LIBLIRC_CLIENT@ @LIBSVGA@
INCLUDES = -I$(top_srcdir) INCLUDES = -I$(top_srcdir)
+560
View File
@@ -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;
}
+65
View File
@@ -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
+184
View File
@@ -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;
}
+11
View File
@@ -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();
-1
View File
@@ -379,7 +379,6 @@ lcd_drv_patch_init (struct lcd_logical_driver *driver)
* *
*/ */
static
void * void *
lcd_find_init (char *driver) { lcd_find_init (char *driver) {
int i; int i;
+20
View File
@@ -71,6 +71,26 @@ typedef struct lcd_logical_driver {
void (*heartbeat) (int type); void (*heartbeat) (int type);
// more? // 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; } lcd_logical_driver;
typedef struct lcd_physical_driver { typedef struct lcd_physical_driver {
+339 -410
View File
@@ -21,6 +21,7 @@
#include <pwd.h> #include <pwd.h>
#include <errno.h> #include <errno.h>
#include <syslog.h> #include <syslog.h>
#include <math.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
@@ -30,7 +31,7 @@ extern int optind, optopt, opterr;
#include "shared/debug.h" #include "shared/debug.h"
#include "drivers/lcd.h" #include "drivers.h"
#include "sock.h" #include "sock.h"
#include "clients.h" #include "clients.h"
#include "screenlist.h" #include "screenlist.h"
@@ -39,18 +40,30 @@ extern int optind, optopt, opterr;
#include "render.h" #include "render.h"
#include "serverscreens.h" #include "serverscreens.h"
#include "input.h" #include "input.h"
#include "configfile.h"
#include "drivers.h"
#include "main.h" #include "main.h"
#define MAX_TIMER 0x10000 #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 *version = VERSION;
char *protocol_version = PROTOCOL_VERSION; char *protocol_version = PROTOCOL_VERSION;
char *build_date = __DATE__; char *build_date = __DATE__;
/* Socket to bind to... /* Socket to bind to...
Using loopback is much more secure; it means that this port is 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 Using variables for these means that (later) we can select which port
and which address to bind to at run time. */ 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 // The parameter structure and args[] should
// be removed when getopt(3) is implemented, // be removed when getopt(3) is implemented,
@@ -83,59 +113,30 @@ int lcd_port = 0;
// {NULL, NULL}, // {NULL, NULL},
//}; //};
/**** Local functions ****/
void exit_program (int val); void exit_program (int val);
void HelpScreen (); void HelpScreen ();
// At this point, this function will only succeed; void clear_settings();
// all other options will stop the program. int process_command_line (int argc, char **argv);
// However, it may not always be thus; so we prepared int process_configfile (char *cfgfile);
// for this possibility by making it return an int. void set_default_settings();
// int daemonize();
int drop_privs(char *user) { int init_sockets();
struct passwd *pwent; int drop_privs(char *user);
int init_drivers();
int init_screens();
void do_mainloop();
if (getuid() == 0 || geteuid() == 0) { #define ESSENTIAL(f) {int r; if( ( r=f )!=0 ) return r;}
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
int int
main (int argc, char **argv) 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!!! // FIXME: s is getting clobbered - in MANY places!!!
screen *s = NULL; //screen *s = NULL;
//char buf[64];
//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];
signal (SIGINT, exit_program); // Ctrl-C will cause a clean exit... signal (SIGINT, exit_program); // Ctrl-C will cause a clean exit...
signal (SIGTERM, exit_program); // and "kill"... signal (SIGTERM, exit_program); // and "kill"...
@@ -146,11 +147,6 @@ main (int argc, char **argv)
//if (argc == 1) //if (argc == 1)
// HelpScreen (); // 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: * Settings in order of preference:
* *
@@ -171,7 +167,83 @@ main (int argc, char **argv)
* in the variable declaration... * 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.. // analyze options here..
while ((c = getopt(argc, argv, "a:p:d:hfiw:c:u:")) > 0) { while ((c = getopt(argc, argv, "a:p:d:hfiw:c:u:")) > 0) {
// FIXME: Setting of c in this loop clobbers s! // FIXME: Setting of c in this loop clobbers s!
@@ -179,10 +251,15 @@ main (int argc, char **argv)
switch(c) { switch(c) {
case 'd': case 'd':
// Add to a list of drivers to be initialized later... // Add to a list of drivers to be initialized later...
if (i < MAX_DRIVERS) { if (num_drivers < MAX_DRIVERS) {
driverlist[i] = malloc(MAX_DRIVER_NAME_SIZE); drivernames[num_drivers] = malloc( strlen(optarg)+1 );
strncpy(driverlist[i], optarg, MAX_DRIVER_NAME_SIZE); driverfilenames[num_drivers] = malloc( strlen(optarg)+1 );
i++; driverargs[num_drivers] = malloc(1);
strcpy( drivernames[num_drivers], optarg );
strcpy( driverfilenames[num_drivers], optarg );
strcpy( driverargs[num_drivers], "");
num_drivers ++;
} else } else
fprintf(stderr, "too many drivers!"); fprintf(stderr, "too many drivers!");
break; break;
@@ -202,10 +279,10 @@ main (int argc, char **argv)
daemon_mode = 0; daemon_mode = 0;
break; break;
case 'c': case 'c':
strncpy(cfgfile, optarg, sizeof(cfgfile)); strncpy(configfile, optarg, sizeof(configfile));
break; break;
case 'i': case 'i':
disable_server_screen = 1; enable_server_screen = 0;
break; break;
case 'w': case 'w':
default_duration = atoi(optarg); default_duration = atoi(optarg);
@@ -230,178 +307,138 @@ main (int argc, char **argv)
if (optind < argc) if (optind < argc)
fprintf(stderr, "non-option arguments!! BAD..."); fprintf(stderr, "non-option arguments!! BAD...");
openlog("LCDd", LOG_PID, LOG_DAEMON); return 0;
syslog(LOG_NOTICE, "server version %s starting up (protocol version %s)", }
version, protocol_version);
syslog(LOG_NOTICE, "server built on %s",
build_date);
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)) { // Read server settings
if (linebuf[strlen(linebuf) - 1] == '\n')
linebuf[strlen(linebuf) - 1] = '\0';
/* config_read_file( configfile );
* Comment lines and empty lines...
*
*/
if (linebuf[0] == '\0' || // empty line if( debug_level == -1 )
linebuf[0] == '\n' || // empty line debug_level = config_get_int( "server", "debug", 0, -1 );
linebuf[0] == '\r' || // empty line
linebuf[0] == '#' || // comment line (#)
linebuf[0] == ';' || // comment line (;)
(linebuf[0] == '/' && linebuf[1] == '/')) // comment line (//)
continue;
/* if( lcd_port == -1 )
* Driver section lines... lcd_port = config_get_int( "server", "port", 0, -1 );
*
*/
else if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') { if( bind_addr == "" )
driver_index = -1; 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!!! if( default_duration == -1 ) {
strncpy(driver_name, linebuf + 1, sizeof(driver_name)); default_duration = (config_get_float( "server", "waittime", 0, 0 ) * 1000000 / TIME_UNIT );
if( default_duration == 0 )
for (i = 0; i < MAX_DRIVERS; i++) { default_duration = -1;
if (driverlist[i] == NULL) else if( default_duration < 16 ) {
break; fprintf( stderr, "waittime should be at least 2 (seconds)\n" );
return -1;
if (strcasecmp(driver_name, driverlist[i]) == 0) {
driver_index = i;
break;
} }
} }
/* if( daemon_mode == -1 )
* Driver section data lines daemon_mode = ! config_get_bool( "server", "foreground", 0, -1 );
*
* These are only scanned for drivers that are being used...
*
*/
} else if (driver_index >= 0) { if( enable_server_screen == -1 )
if (strncasecmp(linebuf, "arguments ", 10) == 0) { enable_server_screen = config_get_bool( "server", "serverscreen", 0, -1 );
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 {
/* // Read drivers
* Global settings..
*
*/
// not in a driver section... // If drivers have been specified on the command line, then do not
if (strncasecmp(linebuf, "Driver ", 7) == 0) { // use the driver list from the config file.
if (driverlist[0] == NULL) { // check for arguments: override conf file drivers... if( num_drivers == 0 ) {
driverlist[list_index] = malloc(MAX_DRIVER_NAME_SIZE); // read the drivernames
snprintf(driverlist[list_index++], MAX_DRIVER_NAME_SIZE, "%s", linebuf + 7); 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++;
} }
} 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) { // Now read the driver options that the server needs
if (user[0] == '\0') // Drivers can read their own options later...
strncpy(user, linebuf + 5, sizeof(user)); for( i=0; i<num_drivers; i ++ ) {
} else if (strncasecmp(linebuf, "Port ", 5) == 0) { 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) if (lcd_port == 0)
lcd_port = atoi(linebuf + 5); lcd_port = DEFAULT_LCD_PORT;
} else if ((strncasecmp(linebuf, "Wait ", 5) == 0) || if (bind_addr[0] == 0)
(strncasecmp(linebuf, "WaitTime ", 9) == 0)) { strncpy (bind_addr, DEFAULT_BIND_ADDR, sizeof(bind_addr));
char *p; if (configfile[0] == 0)
strncpy (configfile, DEFAULT_CONFIGFILE, sizeof(configfile));
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);
}
}
}
fclose(config);
}
if (debug_level > 0)
syslog(LOG_NOTICE, "debug level set to %d",
debug_level);
// set defaults....
if (user[0] == '\0') if (user[0] == '\0')
strncpy(user, DEFAULT_USER, sizeof(user)); strncpy(user, DEFAULT_USER, sizeof(user));
if (bind_addr[0] == '\0') if (daemon_mode == -1)
strncpy(bind_addr, DEFAULT_ADDR, sizeof(bind_addr)); daemon_mode = DEFAULT_DAEMON_MODE;
if (lcd_port == 0) if (enable_server_screen == -1)
lcd_port = LCDPORT; enable_server_screen = DEFAULT_ENABLE_SERVER_SCREEN;
if (default_duration == 0)
if (default_duration == -1)
default_duration = DEFAULT_SCREEN_DURATION; default_duration = DEFAULT_SCREEN_DURATION;
// Use default driver // Use default driver
if (driverlist[0] == NULL) { if( num_drivers == 0 ) {
driverlist[0] = malloc(MAX_DRIVER_NAME_SIZE); drivernames[0] = malloc(strlen(DEFAULT_DRIVER)+1);
strcpy(driverlist[0], DEFAULT_DRIVER); strcpy(drivernames[0], DEFAULT_DRIVER);
} driverfilenames[0] = malloc(1);
strcpy(driverfilenames[0], DEFAULT_DRIVER);
// FIXME: This sets s equal to a value related to i driverargs[0] = malloc(1);
// (bitshifted left?) FIX FIX FIX ARGH.... strcpy(driverargs[0], "");
//
// 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... int
if (daemon_mode) { daemonize()
{
int child; int child;
syslog(LOG_NOTICE, "server forking to background"); switch ((child = fork ()) ) {
case -1:
if ((child = fork ()) != 0) { 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 usleep (1500000); // Wait for child to initialize
exit (0); /* PARENT EXITS */ exit (0); /* PARENT EXITS */
} }
@@ -413,203 +450,103 @@ main (int argc, char **argv)
// //
// However, option processing is not yet done, nor is any initialization (!) // However, option processing is not yet done, nor is any initialization (!)
// So we must wait until the main loop. // So we must wait until the main loop.
} else { return 0;
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?
//
for (i = 1; i < argc; i++) {
if (argv[i][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... int
else if (0 == strcmp (argv[i], "-f") || 0 == strcmp (argv[i], "--foreground")) { init_sockets ()
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);
if (sock_create_server (&bind_addr, lcd_port) <= 0) { if (sock_create_server (&bind_addr, lcd_port) <= 0) {
syslog(LOG_ERR, "error opening socket"); syslog(LOG_ERR, "error opening socket");
return 1; return 1;
} }
if (lcd_port < 1024) // priviledged port
drop_privs(user);
// Now init a bunch of required stuff... // Now init a bunch of required stuff...
if (client_init () < 0) { if (client_init () < 0) {
syslog(LOG_ERR, "error initializing client list"); syslog(LOG_ERR, "error initializing client list");
return 1; 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) { if (screenlist_init () < 0) {
syslog(LOG_ERR, "error initializing screen list"); syslog(LOG_ERR, "error initializing screen list");
return 1; return 1;
@@ -618,22 +555,20 @@ main (int argc, char **argv)
if (server_screen_init () < 0) { if (server_screen_init () < 0) {
syslog(LOG_ERR, "error initializing server screens"); syslog(LOG_ERR, "error initializing server screens");
return 1; return 1;
} else if (disable_server_screen) { } else if (!enable_server_screen) {
server_screen->priority = 256; 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", void
lcd_ptr->wid, lcd_ptr->hgt, lcd_ptr->cellwid, lcd_ptr->cellhgt); do_mainloop ()
if (debug_level > 2) {
syslog(LOG_DEBUG, "framebuffer at %0X", screen *s = NULL;
lcd_ptr->framebuf); //char buf[64];
// FIXME: s should still be null from initialization.... what's happening here?! // FIXME: s should still be null from initialization.... what's happening here?!
s = NULL;
while (1) { while (1) {
sock_poll_clients (); // poll clients for input sock_poll_clients (); // poll clients for input
parse_all_client_messages (); // analyze input from network clients parse_all_client_messages (); // analyze input from network clients
@@ -686,8 +621,6 @@ main (int argc, char **argv)
// Quit! // Quit!
exit_program (0); exit_program (0);
return 0;
} }
void void
@@ -709,26 +642,22 @@ exit_program (int val)
syslog(LOG_NOTICE, buf); // send message to syslog syslog(LOG_NOTICE, buf); // send message to syslog
if (lcd_ptr->framebuf != NULL) {
goodbye_screen (); // display goodbye screen on LCD display goodbye_screen (); // display goodbye screen on LCD display
lcd_shutdown (); // release driver memory and file descriptors unload_all_drivers (); // release driver memory and file descriptors
client_shutdown (); // shutdown clients (must come first) client_shutdown (); // shutdown clients (must come first)
screenlist_shutdown (); // shutdown screens (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) sock_close_all (); // close all open sockets (must come after client_shutdown)
}
exit (0); exit (0);
} }
void void
HelpScreen () 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 ("\nLCDd Server Daemon (part of lcdproc), %s\n", version);
printf ("Copyright (c) 1999 Scott Scriven, William Ferrell, and misc contributors\n"); printf ("Copyright (c) 1999 Scott Scriven, William Ferrell, and misc contributors\n");
@@ -737,7 +666,7 @@ HelpScreen ()
printf ("Available options are:\n"); printf ("Available options are:\n");
printf ("\t-h\t\tDisplay this help screen\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-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-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"); //printf ("\t\t\tCFontz, curses, HD44780, irmanin, joy,\n\t\t\tMtxOrb, LB216, text\n");