Files
lcdproc/server/parse.c
T

190 lines
4.9 KiB
C
Raw Normal View History

1999-12-09 23:15:14 +00:00
/*
* parse.c
* This file is part of LCDd, the lcdproc server.
*
* This file is released under the GNU General Public License. Refer to the
* COPYING file distributed with this package.
*
* Copyright (c) 1999, William Ferrell, Scott Scriven
*
*
* Handles input commands from clients, by splitting strings into tokens
* and passing arguments to the appropriate handler.
*
* It works much like a command line. Only the first token is used to
* determine what function to call.
*
1999-12-09 23:15:14 +00:00
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "shared/LL.h"
#include "shared/sockets.h"
2001-11-29 14:09:13 +00:00
#include "shared/report.h"
1999-12-09 23:15:14 +00:00
#include "clients.h"
#include "client_functions.h"
#include "parse.h"
2001-12-30 00:15:25 +00:00
/* This is a big function... TOO big. How to trim....
* TODO: Simplify... simplify...
*/
#define MAX_ARGUMENTS 256
int
parse_all_client_messages ()
1999-12-09 23:15:14 +00:00
{
2001-12-30 00:15:25 +00:00
int i; /* int j, len;*/
/*int newtoken, inquote;*/
2000-04-03 22:13:57 +00:00
client *c;
char *str, *p, *q, *s;
2001-12-30 00:15:25 +00:00
/* char *tok;*/
2000-04-03 22:13:57 +00:00
int argc;
char *argv[MAX_ARGUMENTS];
2001-12-30 00:15:25 +00:00
/*char delimiters[] = " ";*/
char leftquote[] = "\"'`([{";
char rightquote[] = "\"'`)]}";
2000-04-03 22:13:57 +00:00
char errmsg[256];
int invalid = 0;
int quoteindex;
2001-11-29 14:09:13 +00:00
debug( RPT_DEBUG, "parse_all_client_messages()" );
for (i = 0; i < MAX_ARGUMENTS; i++) {
argv[i] = NULL;
}
#define SEPARATOR_CHAR ' '
#define LINE_TERM_CHAR '\0'
#define COMMENT_CHAR '#'
2001-12-30 00:15:25 +00:00
/*debug("parse: Rewinding list...");*/
2000-04-03 22:13:57 +00:00
LL_Rewind (clients);
do {
2001-12-30 00:15:25 +00:00
/* Get the next client...*/
/*debug("parse: Getting client...");*/
2000-04-03 22:13:57 +00:00
c = LL_Get (clients);
if (c) {
2001-12-30 00:15:25 +00:00
/* And parse all its messages...*/
/*debug(RPT_DEBUG, "parse: Getting messages...");*/
2000-04-03 22:13:57 +00:00
for (str = client_get_message (c); str; str = client_get_message (c)) {
2001-11-29 14:09:13 +00:00
debug (RPT_DEBUG, "parse: ...%s", str);
2001-12-30 00:15:25 +00:00
/* Now, split up the string...*/
2000-04-03 22:13:57 +00:00
argc = 0;
i = 0;
q = p = str;
if (*p == COMMENT_CHAR) {
2001-12-30 00:15:25 +00:00
continue; /* found a comment line - skip it...*/
}
2001-11-29 14:09:13 +00:00
debug (RPT_DEBUG, "starting string scan...");
do {
2001-12-30 00:15:25 +00:00
/* bypass initial white space...*/
while ((*p == SEPARATOR_CHAR) && (*p)) {
p++;
q++;
2000-04-03 22:13:57 +00:00
}
2001-12-30 00:15:25 +00:00
/* If (*p) is null here, we reached the end of
* an empty parameter... so one of two things
* is true:
*
* 1. There is nothing but white space on this line (odd..)
* 2. This is trailing white space (odd... but allowable)
*/
if (*p == LINE_TERM_CHAR) {
break;
2001-12-30 00:15:25 +00:00
/* if there are no arguments, argc == 0 and will fail
* appropriately...
*
* if this is trailing white space, ignore the argc++ at the
* end and claim this as the end...
*/
}
2001-12-30 00:15:25 +00:00
/* Handle quoted strings...*/
if ((s = strchr(leftquote, *p)) != NULL) {
quoteindex = s - leftquote;
2001-12-30 00:15:25 +00:00
/*debug(RPT_DEBUG, "found <%c> at index [%d] = <%c>", *p, quoteindex, leftquote[quoteindex]);*/
q = ++p; /* past open quote...*/
while ((rightquote[quoteindex] != *p) && (*p != LINE_TERM_CHAR)) {
p++;
}
if (*p == LINE_TERM_CHAR) {
2001-12-30 00:15:25 +00:00
/* We just sucked up the rest of the command line: ERROR!!*/
snprintf (errmsg, sizeof(errmsg), "huh? unterminated string! missing ending %c\n",
rightquote[quoteindex]);
sock_send_string (c->sock, errmsg);
continue;
} else {
2001-12-30 00:15:25 +00:00
*p = LINE_TERM_CHAR; /* terminate string*/
p++; /* bypass to next character*/
/* Note that next character could be a EndOfLine (null)
* if the string was last on the line, or it could be
* something else... is it a blank?
*/
if (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR) {
sock_send_string (c->sock, "huh? improperly terminated string! (missing whitespace)\n");
continue;
}
}
2001-12-30 00:15:25 +00:00
/* Otherwise, normal string...*/
2000-04-03 22:13:57 +00:00
} else {
while (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR)
p++;
2000-04-03 22:13:57 +00:00
}
2001-12-30 00:15:25 +00:00
/* Not end of line?*/
if (*p) {
*p = LINE_TERM_CHAR;
2001-12-30 00:15:25 +00:00
/*debug(RPT_DEBUG, "found new token: %s", q);*/
argv[i++] = q;
q = ++p;
} else {
2001-12-30 00:15:25 +00:00
/*debug(RPT_DEBUG, "found new token: %s", q);*/
argv[i++] = q;
}
2001-12-30 00:15:25 +00:00
/* At the end of this statement,
* *p will be '\0' if end of input reached;
* otherwise, it is the first character of the
* next part of the string.
*/
argc++;
} while (*p);
2001-12-30 00:15:25 +00:00
/*debug(RPT_DEBUG, "exiting string scan...");*/
2000-04-03 22:13:57 +00:00
argv[argc] = NULL;
if (argc < 1)
continue;
2001-12-30 00:15:25 +00:00
/* Now find and call the appropriate function...*/
2000-04-03 22:13:57 +00:00
invalid = 1;
for (i = 0; commands[i].keyword; i++) {
if (0 == strcmp (argv[0], commands[i].keyword)) {
invalid = commands[i].function (c, argc, argv);
2001-12-30 00:15:25 +00:00
break; /* found our function - don't continue on...*/
2000-04-03 22:13:57 +00:00
}
}
2000-04-03 22:13:57 +00:00
if (invalid) {
snprintf (errmsg, sizeof(errmsg), "huh? Invalid command \"%s\"\n", argv[0]);
2000-04-03 22:13:57 +00:00
sock_send_string (c->sock, errmsg);
}
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
free (str); /* fixed memory leak?*/
} /* end for(str...)*/
} /* end if (c)*/
2000-04-03 22:13:57 +00:00
} while (LL_Next (clients) == 0);
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
}