Added lcdexec
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
||||
SUBDIRS = examples headlines lcdproc metar
|
||||
SUBDIRS = examples headlines lcdexec lcdproc metar
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
bin_PROGRAMS = lcdexec
|
||||
lcdexec_SOURCES = lcdexec.c menu.c menu.h
|
||||
lcdexec_LDADD = ../../shared/libLCDstuff.a
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* lcdexec.c
|
||||
* This file is part of lcdexec, an LCDproc client.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*
|
||||
* Copyright (c) 2002, Joris Robijn
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* How to use submenus in the config file:
|
||||
* [lcdexec]
|
||||
* MenuCommand="Shut down,shutdown -h now"
|
||||
* SubMenu="Internet,inet"
|
||||
* # The inet submenu is filled as follows:
|
||||
* inet_MenuCommand="open,inet open"
|
||||
* inet_MenuCommand="close,inet close"
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shared/str.h"
|
||||
#include "shared/report.h"
|
||||
#include "shared/configfile.h"
|
||||
#include "shared/sockets.h"
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
#define DEFAULT_CONFIGFILE "/etc/LCDclients.conf"
|
||||
|
||||
char * help_text =
|
||||
"lcdexec - LCDproc client to execute commands from the LCDd menu.\n"
|
||||
"Copyright (c) 2002, Joris Robijn\n"
|
||||
"This file is released under the GNU General Public License. Refer to the\n"
|
||||
"COPYING file distributed with this package.\n"
|
||||
"Options:\n"
|
||||
" -c <file>\tSpecify configuration file ["DEFAULT_CONFIGFILE"]\n"
|
||||
" -a <address>\tDNS name or IP address of the LCDd server [localhost]\n"
|
||||
" -p <port>\tport of the LCDd server [13666]\n"
|
||||
" -f <0|1>\tRun in foreground (1) or background (0, default)\n"
|
||||
" -r <level>\tSet reporting level (0-5) [2: errors and warnings]\n"
|
||||
" -s <0|1>\tReport to syslog (1) or stderr (0, default)\n"
|
||||
" -h\t\tShow this help\n";
|
||||
|
||||
char * progname = "lcdexec";
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, optopt, opterr;
|
||||
|
||||
/* Variables set by config */
|
||||
#define UNSET_INT -1
|
||||
#define UNSET_STR "\01"
|
||||
char * configfile = UNSET_STR;
|
||||
char * address = UNSET_STR;
|
||||
int port = UNSET_INT;
|
||||
int foreground_mode = UNSET_INT;
|
||||
char * appname = UNSET_STR;
|
||||
static int report_level = UNSET_INT;
|
||||
static int report_dest = UNSET_INT;
|
||||
|
||||
Menu * main_menu;
|
||||
|
||||
/* Other variables */
|
||||
int sock;
|
||||
|
||||
/* Function prototypes */
|
||||
int process_command_line( int argc, char **argv );
|
||||
int process_configfile( char * configfile );
|
||||
int split( char * str, char delim, char * parts[], int maxparts );
|
||||
int connect_and_setup ();
|
||||
int process_response( char * str );
|
||||
int exec_command( char * command );
|
||||
int main_loop ();
|
||||
|
||||
#define CHAIN(e,f) { if( e>=0 ) { e=(f); }}
|
||||
#define CHAIN_END(e) { if( e<0 ) { report( RPT_CRIT,"Critical error, abort"); exit(e); }}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
CHAIN( error, process_command_line( argc, argv ));
|
||||
if( configfile == NULL )
|
||||
configfile = DEFAULT_CONFIGFILE;
|
||||
CHAIN( error, process_configfile( configfile ));
|
||||
|
||||
if( report_dest == UNSET_INT || report_level == UNSET_INT ) {
|
||||
report_dest = RPT_DEST_STDERR;
|
||||
report_level = RPT_ERR;
|
||||
}
|
||||
set_reporting( progname, report_level, report_dest );
|
||||
CHAIN_END( error );
|
||||
|
||||
CHAIN( error, connect_and_setup() );
|
||||
CHAIN_END( error );
|
||||
|
||||
if(!foreground_mode) {
|
||||
if (daemon(1,1)!=0) {
|
||||
report(RPT_ERR, "Error: daemonize failed");
|
||||
}
|
||||
}
|
||||
|
||||
main_loop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_command_line( int argc, char **argv )
|
||||
{
|
||||
char c;
|
||||
char * p;
|
||||
int temp_int;
|
||||
int error = 0;
|
||||
|
||||
/* No error output from getopt */
|
||||
opterr = 0;
|
||||
|
||||
while(( c = getopt( argc, argv, "c:O:a:p:f:r:s:h" )) > 0) {
|
||||
switch( c ) {
|
||||
case 'c':
|
||||
configfile = strdup( optarg );
|
||||
break;
|
||||
case 'O':
|
||||
config_read_string( progname, optarg );
|
||||
break;
|
||||
case 'a':
|
||||
address = strdup( optarg );
|
||||
break;
|
||||
case 'p':
|
||||
temp_int = strtol( optarg, &p, 0 );
|
||||
if( *optarg != 0 && *p == 0 ) {
|
||||
port = temp_int;
|
||||
} else {
|
||||
report( RPT_ERR, "Could not interpret value for -%c", c );
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
temp_int = strtol( optarg, &p, 0 );
|
||||
if( *optarg != 0 && *p == 0 ) {
|
||||
foreground_mode = temp_int;
|
||||
} else {
|
||||
report( RPT_ERR, "Could not interpret value for -%c", c );
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
temp_int = strtol( optarg, &p, 0 );
|
||||
if( *optarg != 0 && *p == 0 ) {
|
||||
report_level = temp_int;
|
||||
} else {
|
||||
report( RPT_ERR, "Could not interpret value for -%c", c );
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 's':
|
||||
temp_int = strtol( optarg, &p, 0 );
|
||||
if( *optarg != 0 && *p == 0 ) {
|
||||
report_dest = (temp_int?RPT_DEST_SYSLOG:RPT_DEST_STDERR);
|
||||
} else {
|
||||
report( RPT_ERR, "Could not interpret value for -%c", c );
|
||||
error = -1;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
fprintf( stderr, "%s", help_text );
|
||||
exit( 0 );
|
||||
case ':':
|
||||
report( RPT_ERR, "Missing option argument for %c", optopt );
|
||||
error = -1;
|
||||
break;
|
||||
case '?':
|
||||
report( RPT_ERR, "Unknown option: %c", optopt );
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int process_configfile( char * configfile )
|
||||
{
|
||||
if( strcmp( configfile, UNSET_STR ) == 0 ) {
|
||||
configfile = DEFAULT_CONFIGFILE;
|
||||
}
|
||||
if( config_read_file( configfile ) < 0 ) {
|
||||
report( RPT_WARNING, "Could not read config file: %s", configfile );
|
||||
}
|
||||
|
||||
if( strcmp( address, UNSET_STR ) == 0 ) {
|
||||
address = strdup( config_get_string( progname, "Address", 0, "localhost" ));
|
||||
}
|
||||
if( port == UNSET_INT ) {
|
||||
port = config_get_int( progname, "Port", 0, 13666 );
|
||||
}
|
||||
if( report_level == UNSET_INT ) {
|
||||
report_level = config_get_int( progname, "ReportLevel", 0, RPT_WARNING );
|
||||
}
|
||||
if( report_dest == UNSET_INT ) {
|
||||
if( config_get_bool( progname, "ReportToSyslog", 0, 0 )) {
|
||||
report_dest = RPT_DEST_SYSLOG;
|
||||
} else {
|
||||
report_dest = RPT_DEST_STDERR;
|
||||
}
|
||||
}
|
||||
if( foreground_mode == UNSET_INT ) {
|
||||
foreground_mode = config_get_bool( progname, "Foreground", 0, 1 );
|
||||
}
|
||||
|
||||
main_menu = menu_read( "", progname );
|
||||
|
||||
if( main_menu->num_menucmds == 0 && main_menu->num_submenus == 0 ) {
|
||||
main_menu->menucmd_name[0] = "echo test";
|
||||
main_menu->menucmd_exec[0] = "echo \"This is a test using the echo command.\"";
|
||||
main_menu->num_menucmds ++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int connect_and_setup ()
|
||||
{
|
||||
char buf[200];
|
||||
|
||||
report( RPT_INFO, "Connecting to %s:%d", address, port );
|
||||
|
||||
sock = sock_connect( address, port );
|
||||
if( sock <= 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create our menu */
|
||||
sock_send_string( sock, "hello\n" );
|
||||
snprintf( buf, sizeof(buf)-1, "client_set -name \"%s\"\n", progname );
|
||||
sock_send_string( sock, buf );
|
||||
|
||||
if( menu_send_to_LCDd( main_menu, "", sock ) < 0 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_response( char * str )
|
||||
{
|
||||
char *argv[10];
|
||||
int argc;
|
||||
char * str2 = strdup( str ); /* get_args modifies str2 */
|
||||
|
||||
report( RPT_DEBUG, "Server said: \"%s\"", str );
|
||||
|
||||
/* Check what the server just said to us... */
|
||||
argc = get_args( argv, str2, 10 );
|
||||
if( argc < 1 ) {
|
||||
free( str2 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( strcmp( argv[0], "menuevent" ) == 0 ) {
|
||||
/* Ah, this is what we were waiting for ! */
|
||||
|
||||
if( argc < 2 ) {
|
||||
report( RPT_WARNING, "Server gave invalid response" );
|
||||
free( str2 );
|
||||
return -1;
|
||||
}
|
||||
if( strcmp( argv[1], "select" ) == 0 ) {
|
||||
char * exec;
|
||||
if( argc < 3 ) {
|
||||
report( RPT_WARNING, "Server gave invalid response" );
|
||||
free( str2 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Find the id */
|
||||
exec = menu_find_cmd_of_id( main_menu, argv[2] );
|
||||
if( !exec ) {
|
||||
report( RPT_WARNING, "Could not find the item id given by the server" );
|
||||
free( str2 );
|
||||
return -1;
|
||||
}
|
||||
/* The id has been found */
|
||||
exec_command( exec );
|
||||
}
|
||||
else {
|
||||
; /* Ignore other menuevents */
|
||||
}
|
||||
}
|
||||
else if( strcmp( argv[0], "huh?" ) == 0 ) {
|
||||
/* Report errors */
|
||||
report( RPT_WARNING, "Server said: \"%s\"", str );
|
||||
}
|
||||
else {
|
||||
; /* Ignore all other responses */
|
||||
}
|
||||
free( str2 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exec_command( char * command )
|
||||
{
|
||||
char *argv[4];
|
||||
|
||||
report( RPT_NOTICE, "Executing: %s", command );
|
||||
|
||||
argv[0] = getenv( "SHELL" );
|
||||
argv[1] = "-c";
|
||||
argv[2] = command;
|
||||
argv[3] = NULL;
|
||||
|
||||
if( !argv[0] ) {
|
||||
report( RPT_ERR, "SHELL environment variable not set." );
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch( fork() ) {
|
||||
case 0:
|
||||
/* We're the child. Execute the command. */
|
||||
execv( argv[0], argv );
|
||||
exit(0);
|
||||
break;
|
||||
case -1:
|
||||
report( RPT_ERR, "Could not fork" );
|
||||
return -1;
|
||||
default:
|
||||
/* We're the parent */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main_loop ()
|
||||
{
|
||||
int num_bytes;
|
||||
char buf[80];
|
||||
int w = 0;
|
||||
|
||||
/* Continuously check if we get a menu event... */
|
||||
|
||||
while(( num_bytes = sock_recv_string( sock, buf, sizeof(buf)-1)) >= 0 ) {
|
||||
if( num_bytes == 0 ) {
|
||||
usleep( 100000 );
|
||||
|
||||
/* Send an empty line every 3 seconds to make sure the server still exists */
|
||||
if( w++ >= 30 ) {
|
||||
w = 0;
|
||||
if( sock_send_string( sock, "\n" ) < 0 ) {
|
||||
break; /* Out of while loop */
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
process_response (buf);
|
||||
}
|
||||
}
|
||||
|
||||
report( RPT_ERR, "Server disconnected (or connection error)" );
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* lcdexec.c
|
||||
* This file is part of lcdexec, an LCDproc client.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*
|
||||
* Copyright (c) 2002, Joris Robijn
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shared/str.h"
|
||||
#include "shared/report.h"
|
||||
#include "shared/configfile.h"
|
||||
#include "shared/sockets.h"
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
Menu * menu_find_submenu( Menu * menu, char * submenu_id );
|
||||
|
||||
Menu * menu_read( char * menu_id, char * progname )
|
||||
{
|
||||
char buf[100];
|
||||
char * str;
|
||||
char * parts[3];
|
||||
int i;
|
||||
|
||||
Menu * menu;
|
||||
|
||||
report( RPT_DEBUG, "Reading menu: [%s]", menu_id );
|
||||
|
||||
menu = malloc( sizeof(Menu) );
|
||||
|
||||
/* Read the commands */
|
||||
str = "";
|
||||
while( str && menu->num_menucmds < MAX_NUM_MENUCMDS ) {
|
||||
|
||||
snprintf( buf, sizeof(buf)-1, "%s%sMenuCommand",
|
||||
menu_id, menu_id[0]?"_":"" );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
str = config_get_string( progname, buf, menu->num_menucmds, NULL );
|
||||
if( !str ) {
|
||||
; /* No more menucommands */
|
||||
} else {
|
||||
char * str2 = strdup( str );
|
||||
if( split( str2, ',', parts, 2 ) == 2 ) {
|
||||
menu->menucmd_name[menu->num_menucmds] = parts[0];
|
||||
while( parts[1][0] == ' ' ) parts[1]++; /* Skip spaces */
|
||||
menu->menucmd_exec[menu->num_menucmds] = parts[1];
|
||||
report( RPT_DEBUG, "Found command: [%s] [%s]", parts[0], parts[1] );
|
||||
} else {
|
||||
report( RPT_ERR, "Cannot read MenuCommand: \"%s\"", str );
|
||||
return NULL;
|
||||
}
|
||||
menu->num_menucmds ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the submenus */
|
||||
str = "";
|
||||
while( str && menu->num_submenus < MAX_NUM_SUBMENUS ) {
|
||||
|
||||
snprintf( buf, sizeof(buf)-1, "%s%sSubmenu",
|
||||
menu_id, menu_id[0]?"_":"" );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
str = config_get_string( progname, buf, menu->num_submenus, NULL );
|
||||
if( !str ) {
|
||||
; /* No more submenus */
|
||||
} else {
|
||||
char * str2 = strdup( str );
|
||||
if( split( str2, ',', parts, 2 ) == 2 ) {
|
||||
menu->submenu_name[menu->num_submenus] = parts[0];
|
||||
while( parts[1][0] == ' ' ) parts[1]++; /* Skip spaces */
|
||||
menu->submenu_id[menu->num_submenus] = parts[1];
|
||||
report( RPT_DEBUG, "Found submenu: [%s] [%s]", parts[0], parts[1] );
|
||||
} else {
|
||||
report( RPT_ERR, "Cannot read Submenu: \"%s\"", str );
|
||||
return NULL;
|
||||
}
|
||||
menu->num_submenus ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* And do the same for all submenus */
|
||||
for( i = 0; i < menu->num_submenus; i++ ) {
|
||||
menu->submenu[i] = menu_read (menu->submenu_id[i], progname );
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
int menu_send_to_LCDd( Menu * menu, char * id, int sock )
|
||||
{
|
||||
int i;
|
||||
char buf[100];
|
||||
|
||||
for( i = 0; i < menu->num_menucmds; i++ ) {
|
||||
snprintf( buf, sizeof(buf)-1,
|
||||
"menu_add_item \"%s\" \"%s%s%d\" action \"%s\"\n",
|
||||
id, id, id[0]?"_":"", i, menu->menucmd_name[i] );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
if( sock_send_string( sock, buf ) < 0 )
|
||||
return -1;
|
||||
snprintf( buf, sizeof(buf)-1,
|
||||
"menu_set_item \"%s\" \"%s%s%d\" -menu_result quit\n",
|
||||
id, id, id[0]?"_":"", i );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
if( sock_send_string( sock, buf ) < 0 )
|
||||
return -1;
|
||||
}
|
||||
for( i = 0; i < menu->num_submenus; i++ ) {
|
||||
snprintf( buf, sizeof(buf)-1,
|
||||
"menu_add_item \"%s\" \"%s\" menu \"%s\"\n",
|
||||
id, menu->submenu_id[i], menu->submenu_name[i] );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
if( sock_send_string( sock, buf ) < 0 )
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* And do the same for all submenus */
|
||||
for( i = 0; i < menu->num_submenus; i++ ) {
|
||||
if( menu_send_to_LCDd( menu->submenu[i], menu->submenu_id[i], sock ) < 0 )
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * menu_find_cmd_of_id( Menu * menu, char * id )
|
||||
{
|
||||
char * p;
|
||||
char * submenu_id;
|
||||
char * item_id;
|
||||
int i;
|
||||
|
||||
/* Find the submenu_id part of the id */
|
||||
submenu_id = strdup( id );
|
||||
p = strrchr( submenu_id, '_' );
|
||||
|
||||
/* Do we need to search the submenus ? */
|
||||
if( p ) {
|
||||
/* There is a menu id prepended to the id */
|
||||
*p = 0; /* Crop the submenu_id string */
|
||||
item_id = p + 1;
|
||||
menu = menu_find_submenu( menu, submenu_id );
|
||||
if( !menu ) {
|
||||
report( RPT_WARNING, "Server reported an unknown id: %s", id );
|
||||
free( submenu_id );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
item_id = id;
|
||||
}
|
||||
|
||||
/* Determine the number at the end of the id */
|
||||
i = strtol( item_id, &p, 10 );
|
||||
if( *item_id != 0 && *p == 0
|
||||
&& i >= 0 && i < menu->num_menucmds ) {
|
||||
/* OK */
|
||||
free( submenu_id );
|
||||
return menu->menucmd_exec[i];
|
||||
} else {
|
||||
report( RPT_WARNING, "Server reported an unknown id: %s", id );
|
||||
free( submenu_id );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Menu * menu_find_submenu( Menu * menu, char * submenu_id )
|
||||
{
|
||||
int i;
|
||||
Menu * found;
|
||||
|
||||
/* Search for the submenu in this menu and all submenus */
|
||||
for( i = 0; i < menu->num_submenus; i++ ) {
|
||||
if( strcmp( menu->submenu_id[i], submenu_id ) == 0 )
|
||||
return menu->submenu[i];
|
||||
found = menu_find_submenu( menu->submenu[i], submenu_id );
|
||||
if( found )
|
||||
return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int split( char * str, char delim, char * parts[], int maxparts )
|
||||
/* Splits a string into parts, to which pointers will be returned in &parts.
|
||||
* The return value is the number of parts.
|
||||
* maxparts is the maximum number of parts returned. If more parts exist
|
||||
* they are (unsplit) in the last part.
|
||||
* The parts are split at the character delim.
|
||||
* No new space will be allocated, the string str will be mutated !
|
||||
*/
|
||||
{
|
||||
char * p1 = str;
|
||||
char * p2;
|
||||
int part_nr = 0;
|
||||
|
||||
/* Find the delim char to end the current part */
|
||||
while( part_nr < maxparts - 1 && (p2 = strchr( p1, delim )) ) {
|
||||
|
||||
/* subsequent parts... */
|
||||
*p2 = 0;
|
||||
parts[part_nr] = p1;
|
||||
|
||||
p1 = p2 + 1; /* Just after the delim char */
|
||||
part_nr ++;
|
||||
}
|
||||
/* and the last part... */
|
||||
parts[part_nr] = p1;
|
||||
part_nr ++;
|
||||
|
||||
return part_nr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* lcdexec.c
|
||||
* This file is part of lcdexec, an LCDproc client.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*
|
||||
* Copyright (c) 2002, Joris Robijn
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shared/str.h"
|
||||
#include "shared/report.h"
|
||||
#include "shared/configfile.h"
|
||||
#include "shared/sockets.h"
|
||||
|
||||
#define MAX_NUM_MENUCMDS 40
|
||||
#define MAX_NUM_SUBMENUS 20
|
||||
|
||||
typedef struct Menu {
|
||||
char * menucmd_name[MAX_NUM_MENUCMDS];
|
||||
char * menucmd_exec[MAX_NUM_MENUCMDS];
|
||||
int num_menucmds;
|
||||
char * submenu_name[MAX_NUM_SUBMENUS];
|
||||
char * submenu_id[MAX_NUM_SUBMENUS];
|
||||
struct Menu * submenu[MAX_NUM_SUBMENUS];
|
||||
int num_submenus;
|
||||
} Menu;
|
||||
|
||||
Menu * menu_read (char * menu_id, char * progname);
|
||||
int menu_send_to_LCDd( Menu * menu, char * id, int sock );
|
||||
char * menu_find_cmd_of_id( Menu * menu, char * id );
|
||||
|
||||
int split( char * str, char delim, char * parts[], int maxparts );
|
||||
@@ -189,6 +189,7 @@ AC_OUTPUT(Makefile
|
||||
server/drivers/Makefile
|
||||
clients/Makefile
|
||||
clients/lcdproc/Makefile
|
||||
clients/lcdexec/Makefile
|
||||
clients/examples/Makefile
|
||||
clients/headlines/Makefile
|
||||
clients/metar/Makefile
|
||||
|
||||
Reference in New Issue
Block a user