Files
lcdproc/server/client_functions.c
T

1479 lines
36 KiB
C
Raw Normal View History

1999-12-09 23:15:14 +00:00
/*
client_functions.c
This contains definitions for all the functions which clients can run.
The functions here are to be called only from parse.c's interpreter.
The client's available function set is defined here, as is the syntax
for each command.
*/
#include <unistd.h>
1999-12-09 23:15:14 +00:00
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
2001-03-22 22:51:49 +00:00
#include <errno.h>
#include <syslog.h>
1999-12-09 23:15:14 +00:00
#include "shared/debug.h"
#include "shared/sockets.h"
1999-12-09 23:15:14 +00:00
#include "drivers/lcd.h"
#include "main.h"
#include "render.h"
#include "clients.h"
#include "parse.h"
#include "screen.h"
#include "widget.h"
#include "client_functions.h"
int info_func (client * c, int argc, char **argv);
int sleep_func (client * c, int argc, char **argv);
1999-12-09 23:15:14 +00:00
client_function commands[] = {
2000-04-03 22:13:57 +00:00
{"test_func", test_func_func},
{"hello", hello_func},
{"client_set", client_set_func},
{"client_add_key", client_add_key_func},
{"client_del_key", client_del_key_func},
{"screen_add_key", screen_add_key_func},
{"screen_del_key", screen_del_key_func},
2000-04-03 22:13:57 +00:00
{"screen_add", screen_add_func},
{"screen_del", screen_del_func},
{"screen_set", screen_set_func},
{"widget_add", widget_add_func},
{"widget_del", widget_del_func},
{"widget_set", widget_set_func},
{"menu_add", menu_add_func},
{"menu_del", menu_del_func},
{"menu_set", menu_set_func},
{"menu_add_item", menu_add_item_func},
{"menu_del_item", menu_del_item_func},
{"menu_set_item", menu_set_item_func},
2000-04-03 22:13:57 +00:00
// Misc stuff...
{"backlight", backlight_func},
{"output", output_func},
{"noop", noop_func},
{"info", info_func},
{"sleep", sleep_func},
2000-04-03 22:13:57 +00:00
{NULL, NULL},
1999-12-09 23:15:14 +00:00
};
// Remember: argc counts all arguments, including the command name;
// so it will actually be one more than the number of arguments given
// to the command...
#define NoArguments (argc == 1)
#define AnyArguments (argc != 1)
#define MoreArgumentsThan(a) (argc > (a))
1999-12-09 23:15:14 +00:00
// TODO: Maybe more error-checking for "->"'s?
///////////////////////////////////////////////////////////////////////////
// Debugging only.. prints out a list of arguments it receives
//
int
test_func_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int i;
char str[256];
2000-04-03 22:13:57 +00:00
for (i = 0; i < argc; i++) {
snprintf (str, sizeof(str), "test_func_func: %i -> %s\n", i, argv[i]);
2000-04-03 22:13:57 +00:00
printf (str);
sock_send_string (c->sock, str);
}
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// The client must say "hello" before doing anything else.
//
// It returns a string of info about the server to the client
//
// usage: hello
//
int
hello_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
char str[256];
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// TODO: Give *real* info about the server/lcd...
1999-12-09 23:15:14 +00:00
if (AnyArguments) {
sock_send_string (c->sock, "huh? extra parameters ignored\n");
}
2000-04-03 22:13:57 +00:00
debug ("Hello!\n");
1999-12-09 23:15:14 +00:00
memset(str, '\0', sizeof(str));
snprintf (str, sizeof(str), "connect LCDproc %s protocol %s lcd wid %i hgt %i cellwid %i cellhgt %i\n",
version, protocol_version, lcd_ptr->wid, lcd_ptr->hgt, lcd_ptr->cellwid, lcd_ptr->cellhgt);
// lcdproc (client) depends on the above format...
// snprintf (str, sizeof(str), "connect LCDproc %s protocol %s LCD %ix%i with cells %ix%i\n",
// version, protocol_version, lcd.wid, lcd.hgt, lcd.cellwid, lcd.cellhgt);
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, str);
2000-04-03 22:13:57 +00:00
if (c->data)
c->data->ack = 1;
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// sets info about the client, such as its name
//
// usage: client_set -name <id>
//
int
client_set_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int i;
char str[16], buf[80];
1999-12-09 23:15:14 +00:00
memset(str, '\0', sizeof(str));
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 3) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: client_set -name <name>\n");
break;
case 2:
sock_send_string (c->sock, "huh? Not enough parameters\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters\n");
break;
}
return 0;
}
i = 1;
do {
char *p;
// This bit of code means that "-name" is the same as "name"...
p = argv[i];
if (*p == '-')
p++;
2000-04-03 22:13:57 +00:00
// Handle the "name" parameter
if (strcmp (p, "name") == 0) {
i++;
if (argv[i] == '\0') {
snprintf (buf, sizeof(buf), "huh? internal error: no parameter #%d\n", i);
sock_send_string (c->sock, buf);
continue;
}
if (strlen(argv[i]) > sizeof(str) -1) {
sock_send_string (c->sock, "huh? name too long\n");
} else {
strncpy(str, argv[i], sizeof(str) - 1);
2000-04-03 22:13:57 +00:00
debug ("client_set: name=\"%s\"\n", argv[i]);
1999-12-09 23:15:14 +00:00
syslog(LOG_INFO, "client set name to %s", str);
2000-04-03 22:13:57 +00:00
// set the name...
if (c->data->name)
free (c->data->name);
if ((c->data->name = strdup (str)) == NULL) {
sock_send_string(c->sock, "huh? error allocating memory!\n");
} else {
sock_send_string(c->sock, "success\n");
i++; // bypass argument (name string)
}
2000-04-03 22:13:57 +00:00
}
} else {
snprintf (buf, sizeof(buf), "huh? invalid parameter (%s)\n", p);
sock_send_string (c->sock, buf);
2000-04-03 22:13:57 +00:00
}
} while (++i < argc);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Tells the server the client would like to accept keypresses
// of a particular type
//
// usage: client_add_key <keylist>
//
int
client_add_key_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
char * keys ;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 2) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: client_add_key <keylist>\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
break;
}
return 0;
}
keys = argv[1];
debug ("client_add_key: current client will handle key(s) %s\n", keys);
if (!c->data->client_keys) {
// No keys list, create a new one
c->data->client_keys = strdup( keys );
} else {
// Add supplied keys to existing list
// NOTE: There could be duplicates in the resulting list
// That's OK, it's the existence of the key in the list
// that's important. We'll be more careful in the delete
// key function.
char * new ;
int new_len = strlen(c->data->client_keys) + strlen(keys) + 1 ;
new = realloc( c->data->client_keys, new_len );
if( new ) {
c->data->client_keys = new ;
strcat( new, keys );
} else {
sock_send_string(c->sock, "huh? could not allocate memory for new keys\n");
return 0;
}
}
if (c->data->client_keys) {
sock_send_string(c->sock, "success\n");
} else {
sock_send_string(c->sock, "huh? failed\n");
}
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Tells the server the client would NOT like to accept keypresses
// of a particular type
//
// usage: client_del_key <keylist>
//
int
client_del_key_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
char * keys ;
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 2) {
if (argc == 1) {
sock_send_string (c->sock, "huh? usage: client_del_key <keylist>\n");
return 0;
} else {
sock_send_string (c->sock, "huh? Too many parameters...\n");
return 0;
}
}
keys = argv[1] ;
debug ("client_del_key: Deleting key(s) %s from client_keys\n", keys);
if (c->data->client_keys) {
// Client has keys, remove keys from the list
// NOTE: We let malloc/realloc remember the length
// of the allocated storage. If keys are later
// added, realloc (in add_key above) will make
// sure there is enough space at c->data->client_keys
char * from ;
char * to ;
to = from = c->data->client_keys ;
while( *from ) {
// Is this key to be deleted from the list?
if( strchr( keys, *from ) ) {
// Yes, skip it
++from ;
} else {
// No, save it
*to++ = *from++ ;
}
}
}
sock_send_string(c->sock, "success\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////
// Tells the server the client would like to accept keypresses
// of a particular type when the given screen is active on the display
//
// screen_add_key <screenid> <keylist>
//
int
screen_add_key_func (client * c, int argc, char **argv)
{
widget * w ; /* Keys are stored on a WID_KEYS widget */
screen * s ; /* Attached to a specific screen */
char * id ; /* Screen ID */
char * keys ; /* Keys wanted */
if (!c->data->ack)
return 1;
if (argc != 3) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: screen_add_key <screenid> <keylist>\n");
break;
case 2:
sock_send_string (c->sock, "huh? You must specify a key list\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
break;
}
return 0;
}
id = argv[1];
keys = argv[2];
debug ("screen_add_key: Adding key(s) %s to screen %s\n", keys, id);
// Find the screen
s = screen_find (c, id);
if (!s) {
sock_send_string (c->sock, "huh? Invalid screen id\n");
return 0;
}
// Save the keys
if (!s->keys) {
// Save supplied key list
s->keys = strdup( keys );
} else {
// Add supplied keys to existing list
// NOTE: There could be duplicates in the resulting list
// That's OK, it's the existence of the key in the list
// that's important. We'll be more careful in the delete
// key function.
char * new ;
new = realloc( s->keys, strlen(s->keys) + strlen(keys) +1 );
if( new ) {
s->keys = new ;
strcat( new, keys );
} else {
sock_send_string(c->sock, "huh? could not allocate memory for new keys\n");
return 0;
}
}
if (!s->keys) {
sock_send_string(c->sock, "huh? failed\n");
} else
sock_send_string(c->sock, "success\n");
return 0;
}
///////////////////////////////////////////////////////////////////////////
// Tells the server the client would NOT like to accept keypresses
// of a particular type when the given screen is active on the display
//
// usage: screen_del_key <screenid> <keylist>
//
int
screen_del_key_func (client * c, int argc, char **argv)
{
widget * w ; /* Keys are stored on a WID_KEYS widget */
screen * s ; /* Attached to a specific screen */
char * id ; /* Screen ID */
char * keys ; /* Keys wanted */
if (!c->data->ack)
return 1;
if (argc != 3) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: screen_del_key <screenid> <keylist>\n");
break;
case 2:
sock_send_string (c->sock, "huh? You must specify a key list\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters\n");
break;
}
return 0;
}
id = argv[1] ;
keys = argv[2] ;
debug ("screen_del_key: Deleting key(s) %s from screen %s\n", keys, id);
// Find the screen
s = screen_find (c, id);
if (!s) {
sock_send_string (c->sock, "huh? Invalid screen id\n");
return 0;
}
// Do we have keys?
if (s->keys) {
// Have keys, remove keys from the list
// NOTE: We let malloc/realloc remember the length
// of the allocated storage. If keys are later
// added, realloc (in add_key above) will make
// sure there is enough space at s->keys
char * from ;
char * to ;
to = from = s->keys ;
while( *from ) {
// Is this key to be deleted from the list?
if( strchr( keys, *from ) ) {
// Yes, skip it
++from ;
} else {
// No, save it
*to++ = *from++ ;
}
}
to = '\0'; // terminates the new keys string...
}
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Tells the server the client has another screen to offer
//
// usage: screen_add <id>
//
int
screen_add_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int err = 0;
char scr[128];
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 2) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: screen_add <screenid>\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
break;
}
2000-04-03 22:13:57 +00:00
return 0;
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
debug ("screen_add: Adding screen %s\n", argv[1]);
memset(scr, '\0', sizeof(scr));
strncpy(scr, argv[1], sizeof(scr) - 1);
err = screen_add (c, scr);
2001-03-22 22:51:49 +00:00
if (err == 0)
sock_send_string(c->sock, "success\n");
else if (err < 0) {
fprintf (stderr, "screen_add_func: Error adding screen\n");
sock_send_string (c->sock, "huh? failed to add screen id#\n");
} else
sock_send_string (c->sock, "huh? You already have a screen with that id#\n");
syslog(LOG_NOTICE, "added a screen (%s) to the display", scr);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Client requests that the server forget about a screen
//
// usage: screen_del <screenid>
//
int
screen_del_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int err = 0;
char scr[128];
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 2) {
if (NoArguments)
sock_send_string (c->sock, "huh? usage: screen_del <screenid>\n");
else
sock_send_string (c->sock, "huh? Too many parameters...\n");
2000-04-03 22:13:57 +00:00
return 0;
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
debug ("screen_del: Deleting screen %s\n", argv[1]);
// Enforce bounds limits on argv[1]
memset(scr, '\0', sizeof(scr));
strncpy(scr, argv[1], sizeof(scr) - 1);
err = screen_remove (c, scr);
2001-03-22 22:51:49 +00:00
if ( err == 0 )
sock_send_string(c->sock, "success\n");
else if (err < 0) {
fprintf (stderr, "screen_del_func: Error removing screen\n");
sock_send_string(c->sock, "huh? failed to remove screen\n");
} else
sock_send_string (c->sock, "huh? You don't have a screen with that id#\n");
syslog(LOG_NOTICE, "removed a screen (%s) from the display", scr);
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Configures info about a particular screen, such as its
// name, priority, or duration
//
// usage: screen_set <id> [ -priority <int> ] [ -name <name> ] [ -duration <int> ]
// [ -wid <width> ] [ -hgt <height> ] [ -heartbeat <type> ]
int
screen_set_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int i;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
int number;
char *id;
screen *s;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (NoArguments) {
sock_send_string (c->sock, "huh? usage: screen_set <id> [ -priority <int> ] [ -name <name> ] [ -duration <int> ] [ -wid <width> ] [ -hgt <height> ] [ -heartbeat <type> ]\n");
2000-04-03 22:13:57 +00:00
return 0;
} else if (argc == 2) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? What do you want to set?\n");
return 0;
}
2000-04-03 22:13:57 +00:00
id = argv[1];
s = screen_find (c, id);
if (!s) {
sock_send_string (c->sock, "huh? Invalid screen id\n");
return 0;
}
// Handle the rest of the parameters
for (i = 2; i < argc; i++) {
char *p;
// The following code allows us to use p for comparisions,
// ignoring a (valid) single leading '-' - reduces string comparisons
// by half.
p = argv[i];
if (*p == '-')
p++;
2000-04-03 22:13:57 +00:00
// Handle the "name" parameter
if (strcmp (p, "name")) {
2000-04-03 22:13:57 +00:00
if (argc > i + 1) {
i++;
debug ("screen_set: name=\"%s\"\n", argv[i]);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// set the name...
if (s->name)
free (s->name);
s->name = strdup (argv[i]);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
} else {
sock_send_string (c->sock, "huh? -name requires a parameter\n");
}
}
// Handle the "priority" parameter
else if (strcmp (p, "priority")) {
2000-04-03 22:13:57 +00:00
if (argc > i + 1) {
i++;
debug ("screen_set: priority=\"%s\"\n", argv[i]);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// set the priority...
number = atoi (argv[i]);
if (number > 0)
s->priority = number;
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
} else {
sock_send_string (c->sock, "huh? -priority requires a parameter\n");
}
}
// Handle the "duration" parameter
else if (strcmp (p, "duration")) {
2000-04-03 22:13:57 +00:00
if (argc > i + 1) {
i++;
debug ("screen_set: duration=\"%s\"\n", argv[i]);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// set the duration...
number = atoi (argv[i]);
if (number > 0)
s->duration = number;
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
} else {
sock_send_string (c->sock, "huh? -duration requires a parameter\n");
}
}
// Handle the "heartbeat" parameter
else if (strcmp (p, "heartbeat")) {
2000-04-03 22:13:57 +00:00
if (argc > i + 1) {
i++;
debug ("screen_set: heartbeat=\"%s\"\n", argv[i]);
2000-01-05 00:03:25 +00:00
2000-04-03 22:13:57 +00:00
// set the heartbeat type...
if (0 == strcmp (argv[i], "on"))
s->heartbeat = HEART_ON;
2000-04-03 22:13:57 +00:00
if (0 == strcmp (argv[i], "heart"))
s->heartbeat = HEART_ON;
2000-04-03 22:13:57 +00:00
if (0 == strcmp (argv[i], "normal"))
s->heartbeat = HEART_ON;
2000-04-03 22:13:57 +00:00
if (0 == strcmp (argv[i], "default"))
s->heartbeat = HEART_ON;
2000-04-03 22:13:57 +00:00
if (0 == strcmp (argv[i], "off"))
s->heartbeat = HEART_OFF;
2000-04-03 22:13:57 +00:00
if (0 == strcmp (argv[i], "none"))
s->heartbeat = HEART_OFF;
2000-04-03 22:13:57 +00:00
if (0 == strcmp (argv[i], "slash"))
s->heartbeat = HEART_OPEN;
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
} else {
sock_send_string (c->sock, "huh? -heartbeat requires a parameter\n");
}
}
// Handle the "wid" parameter
else if (strcmp (p, "wid")) {
2000-04-03 22:13:57 +00:00
if (argc > i + 1) {
i++;
debug ("screen_set: wid=\"%s\"\n", argv[i]);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// set the duration...
number = atoi (argv[i]);
if (number > 0)
s->wid = number;
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
} else {
sock_send_string (c->sock, "huh? -wid requires a parameter\n");
}
}
// Handle the "hgt" parameter
else if (strcmp (p, "hgt")) {
2000-04-03 22:13:57 +00:00
if (argc > i + 1) {
i++;
debug ("screen_set: hgt=\"%s\"\n", argv[i]);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// set the duration...
number = atoi (argv[i]);
if (number > 0)
s->hgt = number;
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
} else {
sock_send_string (c->sock, "huh? -hgt requires a parameter\n");
}
} else {
sock_send_string (c->sock, "huh? invalid parameter\n");
}
} // done checking argv
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Adds a widget to a screen, but doesn't give it a value
//
// usage: widget_add <screenid> <widgetid> <widgettype> [ -in <id> ]
//
int
widget_add_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int err;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
char *type;
char *sid;
char *wid;
char *in = NULL;
screen *s;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if ((argc < 4) || (argc > 6)) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: widget_add <screenid> <widgetid> <widgettype> [ -in <id> ]\n");
break;
case 2:
sock_send_string (c->sock, "huh? Widget ID and Widget Type not specified!\n");
break;
case 3:
sock_send_string (c->sock, "huh? Widget Type not specified!\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters\n");
break;
}
2000-04-03 22:13:57 +00:00
return 0;
}
2000-04-03 22:13:57 +00:00
sid = argv[1];
wid = argv[2];
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
s = screen_find (c, sid);
if (!s) {
sock_send_string (c->sock, "huh? Invalid screen id\n");
return 0;
}
2000-04-03 22:13:57 +00:00
type = argv[3];
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// Check for additional flags...
if (argc > 4) {
char *p;
p = argv[4];
if (*p == '-')
p++;
// Handle the "in" flag to place widgets in a container...
if (strcmp (p, "in")) {
2000-04-03 22:13:57 +00:00
if (argc < 6) {
sock_send_string (c->sock, "huh? Specify a frame to place widget in\n");
return 0;
}
in = argv[5];
}
}
2000-04-03 22:13:57 +00:00
// Add the widget and set its type...
err = widget_add (s, wid, type, in, c->sock);
if (err == 0)
sock_send_string(c->sock, "success\n");
else {
2000-04-03 22:13:57 +00:00
fprintf (stderr, "widget_add_func: Error adding widget\n");
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "huh? failed\n");
}
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Removes a widget from a screen, and forgets about it
//
// usage: widget_del <screenid> <widgetid>
//
int
widget_del_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int err = 0;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
char *sid;
char *wid;
screen *s;
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 3) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: widget_del <screenid> <widgetid>\n");
break;
case 2:
sock_send_string (c->sock, "huh? Specify a widget #id\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
break;
}
2000-04-03 22:13:57 +00:00
return 0;
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
sid = argv[1];
wid = argv[2];
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
debug ("screen_del: Deleting widget %s.%s\n", sid, wid);
2000-04-03 22:13:57 +00:00
s = screen_find (c, sid);
if (!s) {
sock_send_string (c->sock, "huh? Invalid screen id\n");
}
2000-04-03 22:13:57 +00:00
err = widget_remove (s, wid, c->sock);
if (err == 0)
sock_send_string(c->sock, "success\n");
else {
2000-04-03 22:13:57 +00:00
fprintf (stderr, "widget_del_func: Error removing widget\n");
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "huh? failed\n");
}
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Configures information about a widget, such as its size, shape,
// contents, position, speed, etc...
//
// Ack! This is long!
//
// widget_set <screenid> <widgetid> <widget-SPECIFIC-data>
//
int
widget_set_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
int i;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
int x, y;
int left, top, right, bottom;
int length, direction;
int width, height;
int speed;
char *sid, *wid;
screen *s;
widget *w;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
// If there weren't enough parameters...
// We can't test for too many, since each widget may have a
// different number - plus, if the argument count is wrong, what ELSE
// could be wrong...?
2000-04-03 22:13:57 +00:00
if (argc < 4) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: widget_set <screenid> <widgetid> <widget-SPECIFIC-data>\n");
break;
case 2:
sock_send_string (c->sock, "huh? You must specify a widget id\n");
break;
case 3:
sock_send_string (c->sock, "huh? You must send some widget data\n");
break;
}
2000-04-03 22:13:57 +00:00
return 0;
}
2000-04-03 22:13:57 +00:00
sid = argv[1];
wid = argv[2];
s = screen_find (c, sid);
if (!s) {
sock_send_string (c->sock, "huh? Invalid screen id\n");
return 0;
}
w = widget_find (s, wid);
if (!w) {
sock_send_string (c->sock, "huh? Invalid widget id\n");
// Client Debugging...
{
int i;
fprintf (stderr, "huh? Invalid widget id (%s)\n", wid);
for (i = 0; i < argc; i++)
fprintf (stderr, "%s ", argv[i]);
fprintf (stderr, "\n");
}
return 0;
}
// FIXME? Shouldn't this be handled in widget.c?
i = 3;
switch (w->type) {
case WID_STRING: // String takes "x y text"
if (argc != i + 3)
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
else {
if ((!isdigit ((unsigned int) argv[i][0])) ||
(!isdigit ((unsigned int) argv[i + 1][0]))) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else // Set all the data...
{
x = atoi (argv[i]);
y = atoi (argv[i + 1]);
w->x = x;
w->y = y;
if (w->text)
free (w->text);
w->text = strdup (argv[i + 2]);
if (!w->text) {
fprintf (stderr, "widget_set_func: Error allocating string\n");
return -1;
}
debug ("Widget %s set to %s\n", wid, w->text);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
}
break;
case WID_HBAR: // Hbar takes "x y length"
if (argc != i + 3)
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
else {
if ((!isdigit ((unsigned int) argv[i][0])) ||
(!isdigit ((unsigned int) argv[i + 1][0]))) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else {
x = atoi (argv[i]);
y = atoi (argv[i + 1]);
length = atoi (argv[i + 2]);
w->x = x;
w->y = y;
w->length = length;
}
debug ("Widget %s set to %i\n", wid, w->length);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
break;
case WID_VBAR: // Vbar takes "x y length"
if (argc != i + 3)
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
else {
if ((!isdigit ((unsigned int) argv[i][0])) ||
(!isdigit ((unsigned int) argv[i + 1][0]))) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else {
x = atoi (argv[i]);
y = atoi (argv[i + 1]);
length = atoi (argv[i + 2]);
w->x = x;
w->y = y;
w->length = length;
}
debug ("Widget %s set to %i\n", wid, w->length);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
break;
case WID_ICON: // Icon takes "x y binary_data"
if (argc != i + 3)
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
else {
if ((!isdigit ((unsigned int) argv[i][0])) ||
(!isdigit ((unsigned int) argv[i + 1][0]))) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else {
x = atoi (argv[i]);
y = atoi (argv[i + 1]);
w->x = x;
w->y = y;
// TODO: Parse binary data and copy it to widget's data...
}
}
sock_send_string (c->sock, "huh? Widget type not yet implemented\n");
break;
case WID_TITLE: // title takes "text"
if (argc != i + 1)
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
else {
if (w->text)
free (w->text);
w->text = strdup (argv[i]);
if (!w->text) {
fprintf (stderr, "widget_set_func: Error allocating string\n");
return -1;
}
debug ("Widget %s set to %s\n", wid, w->text);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
break;
case WID_SCROLLER: // Scroller takes "left top right bottom direction speed text"
if (argc != i + 7) {
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
} else {
if ((!isdigit ((unsigned int) argv[i][0])) ||
(!isdigit ((unsigned int) argv[i + 1][0])) ||
(!isdigit ((unsigned int) argv[i + 2][0])) ||
(!isdigit ((unsigned int) argv[i + 3][0]))) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else {
left = atoi (argv[i]);
//debug("left: %d\n",left);
top = atoi (argv[i + 1]);
//debug("top: %d\n",top);
right = atoi (argv[i + 2]);
//debug("right: %d\n",right);
bottom = atoi (argv[i + 3]);
//debug("bottom: %d\n",bottom);
direction = (int) (argv[i + 4][0]);
//debug("dir: %c\n",(char)direction);
speed = atoi (argv[i + 5]);
//debug("speed: %d\n",speed);
// Direction must be v or h
if (((char) direction != 'h') && ((char) direction != 'v')) {
sock_send_string (c->sock, "huh? Invalid direction\n");
} else {
w->left = left;
w->top = top;
w->right = right;
w->bottom = bottom;
w->length = direction;
w->speed = speed;
if (w->text)
free (w->text);
w->text = strdup (argv[i + 6]);
if (!w->text) {
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "huh? out of memory\n");
2000-04-03 22:13:57 +00:00
fprintf (stderr, "widget_set_func: Error allocating string\n");
return -1;
}
debug ("Widget %s set to %s\n", wid, w->text);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
}
}
break;
case WID_FRAME: // Frame takes "left top right bottom wid hgt direction speed"
if (argc != i + 8) {
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
} else {
if ((!isdigit ((unsigned int) argv[i][0])) ||
(!isdigit ((unsigned int) argv[i + 1][0])) ||
(!isdigit ((unsigned int) argv[i + 2][0])) ||
(!isdigit ((unsigned int) argv[i + 3][0])) ||
(!isdigit ((unsigned int) argv[i + 4][0])) ||
(!isdigit ((unsigned int) argv[i + 5][0]))) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else {
left = atoi (argv[i]);
//debug("left: %d\n",left);
top = atoi (argv[i + 1]);
//debug("top: %d\n",top);
right = atoi (argv[i + 2]);
//debug("right: %d\n",right);
bottom = atoi (argv[i + 3]);
//debug("bottom: %d\n",bottom);
width = atoi (argv[i + 4]);
//debug("right: %d\n",right);
height = atoi (argv[i + 5]);
//debug("bottom: %d\n",bottom);
direction = (int) (argv[i + 6][0]);
//debug("dir: %c\n",(char)direction);
speed = atoi (argv[i + 7]);
//debug("speed: %d\n",speed);
// Direction must be v or h
if (((char) direction != 'h') && ((char) direction != 'v')) {
sock_send_string (c->sock, "huh? Invalid direction\n");
} else {
w->left = left;
w->top = top;
w->right = right;
w->bottom = bottom;
w->wid = width;
w->hgt = height;
w->length = direction;
w->speed = speed;
debug ("Widget %s set to (%i,%i)-(%i,%i) %ix%i\n", wid, left, top, right, bottom, width, height);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
}
}
break;
case WID_NUM: // Num takes "x num"
if (argc != i + 2)
sock_send_string (c->sock, "huh? Wrong number of arguments\n");
else {
if (!isdigit ((unsigned int) argv[i][0])) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid coordinates\n");
} else if (!isdigit ((unsigned int) argv[i + 1][0])) {
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Invalid number\n");
} else {
x = atoi (argv[i]);
y = atoi (argv[i + 1]);
w->x = x;
w->y = y;
}
debug ("Widget %s set to %i\n", wid, w->y);
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
}
break;
case WID_NONE:
default:
sock_send_string (c->sock, "huh? Widget has no type\n");
break;
}
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Adds a menu to the client; handled by the server...
//
// usage: menu_add ...?
//
int
menu_add_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Not implemented yet.\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Removes a client's menu and all contents from the server
//
// usage: menu_del ...?
//
int
menu_del_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Not implemented yet.\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Sets info about a menu, but not its items
//
// For example, should the menu be top-level, or buried somewhere?
//
// usage: menu_set ...?
//
int
menu_set_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Not implemented yet.\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Adds an item to a menu
//
// usage: menu_add_item ...?
//
int
menu_add_item_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Not implemented yet.\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Deletes an item from a menu
//
// usage: menu_del_item ...?
int
menu_del_item_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Not implemented yet.\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Sets the info about a menu item
//
// For example, text displayed, widget type, value, etc...
//
// usage: menu_set_item ...?
//
int
menu_set_item_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, "huh? Not implemented yet.\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Toggles the backlight, if enabled.
//
// usage: backlight <on|off|toggle|blink|flash>
//
int
backlight_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
if (!c->data->ack)
return 1;
if (argc != 2) {
switch (argc) {
case 1:
sock_send_string (c->sock, "huh? usage: backlight <on|off|toggle|blink|flash>\n");
break;
default:
sock_send_string (c->sock, "huh? Too many parameters...\n");
break;
}
2000-04-03 22:13:57 +00:00
return 0;
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
debug ("backlight(%s)\n", argv[1]);
1999-12-09 23:15:14 +00:00
// TODO: The following don't seem to be used;
// either use them or lose them:
//
// #define BACKLIGHT_LOAD 3
// #define BACKLIGHT_VIS 4
//
// TODO: The meaning of this one isn't clear; make it so...
//
// #define BACKLIGHT_OPEN 2
backlight = (backlight && 1); // only preserves ON/OFF bit
if (strcmp ("on", argv[1]) == 0) {
backlight_state = BACKLIGHT_ON;
} else if (strcmp ("off", argv[1]) == 0) {
backlight_state = BACKLIGHT_OFF;
} else if (strcmp ("toggle", argv[1]) == 0) {
if (backlight_state == BACKLIGHT_ON)
2000-04-03 22:13:57 +00:00
backlight_state = BACKLIGHT_OFF;
else if (backlight_state == BACKLIGHT_OFF)
backlight_state = BACKLIGHT_ON;
} else if (strcmp ("blink", argv[1]) == 0) {
backlight_state |= BACKLIGHT_BLINK;
} else if (0 == strcmp ("flash", argv[1])) {
backlight_state |= BACKLIGHT_FLASH;
2000-04-03 22:13:57 +00:00
}
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
////////////////////////////////////////////////////////////////////////////
// Sets the state of the output port (such as on MtxOrb LCDs)
//
// usage: output <on|off|int>
//
//
#define ALL_OUTPUTS_ON -1
#define ALL_OUTPUTS_OFF 0
int
output_func (client * c, int argc, char **argv)
1999-12-09 23:15:14 +00:00
{
2001-03-22 22:51:49 +00:00
int rc = 0;
char str[128];
2001-03-22 22:51:49 +00:00
if (argc != 2) {
if (NoArguments)
sock_send_string (c->sock, "huh? usage: output <on|off|num> -- num may be decimal, hex, or octal\n");
else
sock_send_string (c->sock, "huh? Too many parameters...\n");
return 0;
}
if (0 == strcmp (argv[1], "on"))
output_state = ALL_OUTPUTS_ON;
else if (0 == strcmp (argv[1], "off"))
output_state = ALL_OUTPUTS_OFF;
else {
long out;
char *endptr, *p;
// Note that there is no valid range set for
// output_state; thus a value in the 12 digits
// is not considered out of range.
errno = 0;
// errno is set here, because if strtol does not result in
// ERANGE (out of range error) it will not set errno (!).
// At least, this is the case with glibc 2.1.3 ...
p = argv[1];
out = strtol(p, &endptr, 0);
// From the man page for strtol(3)
//
// In particular, if *nptr is not `\0' but **endptr is
// `\0' on return, the entire string is valid.
//
// In this case, argv[1] is *nptr, and &endptr is **endptr.
if (errno) {
int space;
strcat(str, "huh? number argument: ");
space = sizeof(str) - 3 - strlen(str);
strncat(str, strerror(errno), space);
strcat(str, "\n");
sock_send_string (c->sock, str);
return 0;
} else if (*p != '\0' && *endptr == '\0') {
output_state = out;
} else {
sock_send_string (c->sock, "huh? invalid parameter...\n");
return 0;
2001-03-22 22:51:49 +00:00
}
2000-04-03 22:13:57 +00:00
}
2001-03-22 22:51:49 +00:00
sock_send_string(c->sock, "success\n");
// Makes sense to me to set the output immediately;
// however, the outputs are currently set in
// draw_screen(screen * s, int timer)
// Whatever for?
// lcd_ptr->output (output_state);
syslog(LOG_NOTICE, "output states changed");
return 0;
}
///////////////////////////////////////////////////////////////////////////
// info_func
//
// usage: info
//
int
info_func (client * c, int argc, char **argv)
{
char str[1024];
if (! NoArguments) {
sock_send_string (c->sock, "huh? Extra arguments ignored...\n");
2001-03-22 22:51:49 +00:00
}
memset(str, '\0', sizeof(str));
snprintf (str, sizeof(str), (char*) lcd_ptr->getinfo());
sock_send_string (c->sock, str);
return 0;
}
///////////////////////////////////////////////////////////////////////////
// sleep_func
//
// usage: sleep <seconds>
//
int
sleep_func (client * c, int argc, char **argv)
{
int secs;
long out;
char *endptr, *p;
char str[120];
#define MAX_SECS 60
#define MIN_SECS 1
if (argc != 2) {
if (NoArguments)
sock_send_string (c->sock, "huh? usage: sleep <secs>\n");
else
sock_send_string (c->sock, "huh? Too many parameters...\n");
return 0;
}
errno = 0;
// errno is set here, because if strtol does not result in
// ERANGE (out of range error) it will not set errno (!).
// At least, this is the case with glibc 2.1.3 ...
p = argv[1];
out = strtol(p, &endptr, 0);
// From the man page for strtol(3)
//
// In particular, if *nptr is not `\0' but **endptr is
// `\0' on return, the entire string is valid.
//
// In this case, argv[1] is *nptr, and &endptr is **endptr.
if (errno) {
int space;
strcat(str, "huh? number argument: ");
space = sizeof(str) - 3 - strlen(str);
strncat(str, strerror(errno), space);
strcat(str, "\n");
sock_send_string (c->sock, str);
return 0;
} else if (*p != '\0' && *endptr == '\0') {
secs = out;
out = out > MAX_SECS ? MAX_SECS : out;
out = out < MIN_SECS ? MIN_SECS : out;
} else {
sock_send_string (c->sock, "huh? invalid parameter...\n");
return 0;
}
// Repeat until no more remains - should normally be zero
// on exit the first time...
snprintf(str, sizeof(str), "sleeping %d seconds\n", secs);
sock_send_string (c->sock, str);
// whoops.... if this takes place as planned, ALL screens
// will "freeze" for the alloted time...
//
// while ((secs = sleep(secs)) > 0)
// ;
sock_send_string (c->sock, "huh? ignored (not fully implemented)\n");
2000-04-03 22:13:57 +00:00
return 0;
1999-12-09 23:15:14 +00:00
}
///////////////////////////////////////////////////////////////////////////
// Does nothing, returns "noop complete" message
//
// This is useful for shell scripts or programs that want to talk
// with LCDproc and not get deadlocked. Send a noop after each
// command and look for the "noop complete" message.
int
noop_func (client * c, int argc, char **argv)
{
sock_send_string (c->sock, "noop complete\n");
return 0;
}
1999-12-09 23:15:14 +00:00
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////