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
+85 -65
View File
@@ -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
View File
@@ -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)
+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 -2
View File
@@ -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;
+20
View File
@@ -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
View File
@@ -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");