742 lines
20 KiB
C
742 lines
20 KiB
C
/*
|
|
main.c for LCDd
|
|
|
|
Contains main(), plus signal callback functions and a help screen.
|
|
|
|
Program init, command-line handling, and the main loop are
|
|
implemented here. Also, minimal data about the program such as
|
|
the revision number.
|
|
|
|
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>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <pwd.h>
|
|
#include <errno.h>
|
|
#include <syslog.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
|
|
extern char *optarg;
|
|
extern int optind, optopt, opterr;
|
|
|
|
#include "shared/debug.h"
|
|
|
|
#include "drivers/lcd.h"
|
|
#include "sock.h"
|
|
#include "clients.h"
|
|
#include "screenlist.h"
|
|
#include "screen.h"
|
|
#include "parse.h"
|
|
#include "render.h"
|
|
#include "serverscreens.h"
|
|
#include "input.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;
|
|
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
|
|
accessible only to programs running locally on the same host as LCDd.
|
|
|
|
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;
|
|
|
|
// The parameter structure and args[] should
|
|
// be removed when getopt(3) is implemented,
|
|
// as there won't be any need for them then.
|
|
//typedef struct parameter {
|
|
// char *sh, *lg; // short and long versions
|
|
//} parameter;
|
|
|
|
// This is currently only a list of available arguments, but doesn't
|
|
// really *do* anything. It just helps to figure out which parameters
|
|
// go to the server, and which ones go to individual drivers...
|
|
//static parameter args[] = {
|
|
// {"-h", "--help"},
|
|
// {"-d", "--driver"},
|
|
// {"-t", "--type"},
|
|
// {"-f", "--foreground"},
|
|
// {"-b", "--backlight"},
|
|
// {"-i", "--serverinfo"},
|
|
// {"-w", "--waittime"},
|
|
// {NULL, NULL},
|
|
//};
|
|
|
|
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;
|
|
|
|
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
|
|
|
|
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;
|
|
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];
|
|
|
|
signal (SIGINT, exit_program); // Ctrl-C will cause a clean exit...
|
|
signal (SIGTERM, exit_program); // and "kill"...
|
|
signal (SIGHUP, exit_program); // and "kill -HUP" (hangup)...
|
|
signal (SIGKILL, exit_program); // and just in case, "kill -KILL" (which cannot be trapped; but oh well)
|
|
|
|
// If no paramaters given, give the help screen.
|
|
//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:
|
|
*
|
|
* 1: Settings specified in command line options...
|
|
* 2: Settings specified in configuration file...
|
|
* 3: Default settings
|
|
*
|
|
* Because of this, and because one option (-c) specifies where
|
|
* the configuration file is, things are done in this order:
|
|
*
|
|
* 1. Read and set options.
|
|
* 2. Read configuration file; if option is read in configuration
|
|
* file and not already set, then set it.
|
|
* 3. Having read configuration file, if parameter is not set,
|
|
* set it to the default value.
|
|
*
|
|
* It is for this reason that the default values are **NOT** set
|
|
* in the variable declaration...
|
|
*/
|
|
|
|
i = 0;
|
|
// analyze options here..
|
|
while ((c = getopt(argc, argv, "a:p:d:hfiw:c:u:")) > 0) {
|
|
switch(c) {
|
|
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++;
|
|
} else
|
|
fprintf(stderr, "too many drivers!");
|
|
break;
|
|
case 'p':
|
|
lcd_port = atoi(optarg);
|
|
break;
|
|
case 'u':
|
|
strncpy(user, optarg, sizeof(user));
|
|
break;
|
|
case 'a':
|
|
strncpy(bind_addr, optarg, sizeof(bind_addr));
|
|
break;
|
|
case 'h':
|
|
HelpScreen ();
|
|
break;
|
|
case 'f':
|
|
daemon_mode = 0;
|
|
break;
|
|
case 'c':
|
|
strncpy(cfgfile, optarg, sizeof(cfgfile));
|
|
break;
|
|
case 'i':
|
|
disable_server_screen = 1;
|
|
break;
|
|
case 'w':
|
|
default_duration = atoi(optarg);
|
|
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 ();
|
|
};
|
|
break;
|
|
case '?':
|
|
fprintf(stderr, "unknown option: '%c'\n", optopt);
|
|
HelpScreen();
|
|
break;
|
|
case ':':
|
|
fprintf(stderr, "missing option argument!");
|
|
HelpScreen();
|
|
break;
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
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));
|
|
|
|
while (fgets(linebuf, sizeof(linebuf), config)) {
|
|
if (linebuf[strlen(linebuf) - 1] == '\n')
|
|
linebuf[strlen(linebuf) - 1] = '\0';
|
|
|
|
/*
|
|
* Comment lines and empty lines...
|
|
*
|
|
*/
|
|
|
|
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;
|
|
|
|
/*
|
|
* Driver section lines...
|
|
*
|
|
*/
|
|
|
|
else if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') {
|
|
driver_index = -1;
|
|
|
|
linebuf[strlen(linebuf) - 1] = '\0';
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
fclose(config);
|
|
}
|
|
|
|
if (debug_level > 0)
|
|
syslog(LOG_NOTICE, "debug level set to %d",
|
|
debug_level);
|
|
|
|
// set defaults....
|
|
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)
|
|
default_duration = DEFAULT_SCREEN_DURATION;
|
|
|
|
// Use default driver
|
|
if (driverlist[0] == NULL) {
|
|
driverlist[0] = malloc(MAX_DRIVER_NAME_SIZE);
|
|
strcpy(driverlist[0], DEFAULT_DRIVER);
|
|
}
|
|
|
|
// 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?
|
|
//
|
|
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...
|
|
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);
|
|
|
|
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;
|
|
}
|
|
|
|
if (screenlist_init () < 0) {
|
|
syslog(LOG_ERR, "error initializing screen list");
|
|
return 1;
|
|
}
|
|
// Make sure the server screen shows up every once in a while..
|
|
if (server_screen_init () < 0) {
|
|
syslog(LOG_ERR, "error initializing server screens");
|
|
return 1;
|
|
} else if (disable_server_screen) {
|
|
server_screen->priority = 256;
|
|
}
|
|
|
|
// 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);
|
|
|
|
while (1) {
|
|
sock_poll_clients (); // poll clients for input
|
|
parse_all_client_messages (); // analyze input from network clients
|
|
handle_input (); // handle key input from devices
|
|
|
|
// TODO: Move this code to screenlist.c...
|
|
// ... it should just say "handle_screens();"
|
|
// Timer gets reset by screenlist_next()
|
|
|
|
timer++;
|
|
|
|
// this line's here because s was getting overwritten at one time...
|
|
//s = screenlist_current();
|
|
|
|
if (s && (timer >= s->duration)) {
|
|
screenlist_next ();
|
|
}
|
|
|
|
// Just in case it gets out of hand...
|
|
if (timer >= MAX_TIMER)
|
|
timer = 0;
|
|
|
|
// Update server screen with the right number
|
|
// of clients and screens...
|
|
//
|
|
// TODO: Move this call to every client connection
|
|
// and every screen add...
|
|
|
|
update_server_screen (timer);
|
|
|
|
// draw the current scren
|
|
|
|
if ((s = screenlist_current ()) != NULL)
|
|
|
|
draw_screen (s, timer);
|
|
else
|
|
no_screen_screen (timer);
|
|
|
|
usleep (TIME_UNIT);
|
|
}
|
|
|
|
// Quit!
|
|
exit_program (0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
exit_program (int val)
|
|
{
|
|
char buf[64];
|
|
|
|
// TODO: These things shouldn't be so interdependent. The order
|
|
// things are shut down in shouldn't matter...
|
|
|
|
strcpy(buf, "server shutting down on ");
|
|
switch(val) {
|
|
case 1: strcat(buf, "SIGHUP"); break;
|
|
case 2: strcat(buf, "SIGINT"); break;
|
|
case 15: strcat(buf, "SIGTERM"); break;
|
|
default: snprintf(buf, sizeof(buf), "server shutting down on signal %d", val); break;
|
|
// Other values should not be seen, but just in case..
|
|
}
|
|
|
|
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)
|
|
|
|
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");
|
|
printf ("This program is freely redistributable under the terms of the GNU Public License\n\n");
|
|
printf ("Usage: LCDd [ -hfiw ] [ -c <config> ] [ -d <driver> ] [ -a <addr> ] \\\n\t[ -p <port> ] [ -u <user> ] [ -w <time> ]\n\n");
|
|
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-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");
|
|
//printf ("\t\t\t(args will be passed to the driver for init)\n");
|
|
printf ("\t-f\t\tRun in the foreground\n");
|
|
//printf ("\t-b\t--backlight <mode>\n\t\t\tSet backlight mode (on, off, open)\n");
|
|
printf ("\t-i\t\tDisable showing of the main LCDproc server screen\n");
|
|
printf ("\t-w <waittime>\tTime to pause at each screen (in 1/8s of a second)\n");
|
|
printf ("\t-a <addr>\tNetwork (IP) address to bind to\n");
|
|
printf ("\t-p <port>\tNetwork port to listen for connections on\n");
|
|
printf ("\t-u <user>\tUser to run as\n");
|
|
|
|
printf ("\nCurrently available drivers:\n");
|
|
lcd_list_drivers();
|
|
|
|
//printf ("\tHelp on each driver's parameters are obtained upon request:\n\t\t\"LCDd -d driver --help\"\n");
|
|
//printf ("Example:\n");
|
|
//printf ("\tLCDd -d MtxOrb \"--device /dev/lcd --contrast 200\" -d joy\n");
|
|
printf ("\n");
|
|
|
|
exit (0);
|
|
}
|