aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/buffer2array.c120
-rw-r--r--src/buffer2array.h10
-rw-r--r--src/command.c29
-rw-r--r--src/conf.c17
4 files changed, 59 insertions, 117 deletions
diff --git a/src/buffer2array.c b/src/buffer2array.c
index 4a0751eae..322036df0 100644
--- a/src/buffer2array.c
+++ b/src/buffer2array.c
@@ -21,99 +21,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
-int buffer2array(char *origBuffer, char ***array)
+int cstrtok(char *buffer, char *array[], const int max)
{
- int quotes = 0;
- int count = 0;
- int i;
- int curr;
- int *beginArray;
- char *buffer = strdup(origBuffer);
- int bufferLength = strlen(buffer);
- char *markArray = malloc(sizeof(char) * (bufferLength + 1));
-
- for (curr = 0; curr < bufferLength; curr++) {
- if (!quotes && (buffer[curr] == ' ' || buffer[curr] == '\t')) {
- markArray[curr] = '0';
- } else if (buffer[curr] == '\"') {
- if (curr > 0 && buffer[curr - 1] != '\\') {
- quotes = quotes ? 0 : 1;
- markArray[curr] = '0';
- } else {
- markArray[curr] = '1';
- }
- } else {
- markArray[curr] = '1';
- }
- if (markArray[curr] == '1') {
- if (curr > 0) {
- if (markArray[curr - 1] == '0') {
- count++;
- }
- } else {
- count++;
- }
- }
- }
- markArray[bufferLength] = '\0';
-
- if (!count) {
- free(buffer);
- free(markArray);
- return count;
- }
-
- beginArray = malloc(sizeof(int) * count);
- (*array) = malloc(sizeof(char *) * count);
-
- count = 0;
-
- for (curr = 0; curr < bufferLength; curr++) {
- if (markArray[curr] == '1') {
- if (curr > 0) {
- if (markArray[curr - 1] == '0') {
- beginArray[count++] = curr;
+ int i = 0;
+ char *c = buffer;
+
+ while (*c != '\0' && i < max) {
+ if (*c == '\"') {
+ int escape = 0;
+ array[i++] = ++c;
+ while (*c != '\0') {
+ if (*c == '\"') {
+ if (escape)
+ memmove(c - 1, c,
+ strlen(c) + 1);
+ else {
+ *(c++) = '\0';
+ break;
+ }
}
- } else {
- beginArray[count++] = curr;
+ escape = (*(c++) != '\\') ? 0 : !escape;
}
} else {
- buffer[curr] = '\0';
+ while (isspace(*c))
+ ++c;
+ array[i++] = c++;
+ if (*c == '\0')
+ return i;
+ while (!isspace(*c) && *c != '\0')
+ ++c;
}
+ if (*c == '\0')
+ return i;
+ *(c++) = '\0';
+ while (isspace(*c))
+ ++c;
}
-
- for (i = 0; i < count; i++) {
- int len = strlen(buffer + beginArray[i]) + 1;
- int arrayCurr = 0;
- (*array)[i] = malloc(sizeof(char) * len);
- for (curr = beginArray[i]; buffer[curr] != '\0'; curr++) {
- if (buffer[curr] == '\\') {
- if (buffer[curr + 1] != '\0') {
- curr++;
- }
- }
- (*array)[i][arrayCurr++] = buffer[curr];
- }
- (*array)[i][arrayCurr] = '\0';
- }
-
- free(markArray);
- free(beginArray);
- free(buffer);
-
- return count;
-}
-
-void freeArgArray(char **array, int argArrayLength)
-{
- int i;
-
- if (argArrayLength == 0)
- return;
-
- for (i = 0; i < argArrayLength; i++) {
- free(array[i]);
- }
- free(array);
+ return i;
}
diff --git a/src/buffer2array.h b/src/buffer2array.h
index fa6882fd9..cecd3b6d3 100644
--- a/src/buffer2array.h
+++ b/src/buffer2array.h
@@ -21,8 +21,12 @@
#include "../config.h"
-int buffer2array(char *buffer, char ***array);
-
-void freeArgArray(char **array, int argArrayLength);
+/* tokenizes up to max elements in buffer (a null-terminated string) and
+ * stores the result in array (which must be capable of holding up to
+ * max elements). Tokenization is based on C string quoting rules.
+ * The arguments buffer and array are modified.
+ * Returns the number of elements tokenized.
+ */
+int cstrtok(char *buffer, char *array[], const int max);
#endif
diff --git a/src/command.c b/src/command.c
index 8158032a6..cf4a37ae7 100644
--- a/src/command.c
+++ b/src/command.c
@@ -104,6 +104,11 @@
#define COMMAND_STATUS_AUDIO "audio"
#define COMMAND_STATUS_UPDATING_DB "updating_db"
+/* the most we ever use is argv[2], so argv[] has (at most)
+ * 3 usable elements. This means we tokenize up to 4 elements to
+ * detect errors clients may send us */
+#define COMMAND_ARGV_MAX 4
+
typedef struct _CommandEntry CommandEntry;
typedef int (*CommandHandlerFunction) (FILE *, int *, int, char **);
@@ -1138,16 +1143,14 @@ static CommandEntry *getCommandEntryAndCheckArgcAndPermission(FILE * fp,
static CommandEntry *getCommandEntryFromString(char *string, int *permission)
{
CommandEntry *cmd = NULL;
- char **argv;
- int argc = buffer2array(string, &argv);
+ char *argv[COMMAND_ARGV_MAX] = { 0 };
+ int argc = cstrtok(string, argv, COMMAND_ARGV_MAX);
if (0 == argc)
return NULL;
cmd = getCommandEntryAndCheckArgcAndPermission(NULL, permission,
- argc,
- argv);
- freeArgArray(argv, argc);
+ argc, argv);
return cmd;
}
@@ -1156,29 +1159,25 @@ static int processCommandInternal(FILE * fp, int *permission,
char *commandString, ListNode * commandNode)
{
int argc;
- char **argv;
+ char *argv[COMMAND_ARGV_MAX] = { 0 };
CommandEntry *cmd;
int ret = -1;
- argc = buffer2array(commandString, &argv);
+ argc = cstrtok(commandString, argv, COMMAND_ARGV_MAX);
if (argc == 0)
return 0;
if ((cmd = getCommandEntryAndCheckArgcAndPermission(fp, permission,
- argc,
- argv))) {
+ argc, argv))) {
if (NULL == commandNode || NULL == cmd->listHandler) {
- ret = cmd->handler(fp, permission, argc,
- argv);
+ ret = cmd->handler(fp, permission, argc, argv);
} else {
- ret = cmd->listHandler(fp, permission, argc,
- argv, commandNode, cmd);
+ ret = cmd->listHandler(fp, permission, argc, argv,
+ commandNode, cmd);
}
}
- freeArgArray(argv, argc);
-
current_command = NULL;
return ret;
diff --git a/src/conf.c b/src/conf.c
index 5aefa016f..f130334ba 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -41,6 +41,7 @@
#define CONF_REPEATABLE_MASK 0x01
#define CONF_BLOCK_MASK 0x02
+#define CONF_LINE_TOKEN_MAX 3
typedef struct _configEntry {
unsigned char mask;
@@ -193,15 +194,16 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string)
{
ConfigParam *ret = newConfigParam(NULL, *count);
- char **array;
int i;
int numberOfArgs;
int argsMinusComment;
while (myFgets(string, MAX_STRING_SIZE, fp)) {
+ char *array[CONF_LINE_TOKEN_MAX] = { 0 };
+
(*count)++;
- numberOfArgs = buffer2array(string, &array);
+ numberOfArgs = cstrtok(string, array, CONF_LINE_TOKEN_MAX);
for (i = 0; i < numberOfArgs; i++) {
if (array[i][0] == CONF_COMMENT)
@@ -211,13 +213,11 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string)
argsMinusComment = i;
if (0 == argsMinusComment) {
- freeArgArray(array, numberOfArgs);
continue;
}
if (1 == argsMinusComment &&
0 == strcmp(array[0], CONF_BLOCK_END)) {
- freeArgArray(array, numberOfArgs);
break;
}
@@ -238,8 +238,6 @@ static ConfigParam *readConfigBlock(FILE * fp, int *count, char *string)
}
addBlockParam(ret, array[0], array[1], *count);
-
- freeArgArray(array, numberOfArgs);
}
return ret;
@@ -249,7 +247,6 @@ void readConf(char *file)
{
FILE *fp;
char string[MAX_STRING_SIZE + 1];
- char **array;
int i;
int numberOfArgs;
int argsMinusComment;
@@ -265,9 +262,10 @@ void readConf(char *file)
}
while (myFgets(string, MAX_STRING_SIZE, fp)) {
+ char *array[CONF_LINE_TOKEN_MAX] = { 0 };
count++;
- numberOfArgs = buffer2array(string, &array);
+ numberOfArgs = cstrtok(string, array, CONF_LINE_TOKEN_MAX);
for (i = 0; i < numberOfArgs; i++) {
if (array[i][0] == CONF_COMMENT)
@@ -277,7 +275,6 @@ void readConf(char *file)
argsMinusComment = i;
if (0 == argsMinusComment) {
- freeArgArray(array, numberOfArgs);
continue;
}
@@ -316,8 +313,6 @@ void readConf(char *file)
param = newConfigParam(array[1], count);
insertInListWithoutKey(entry->configParamList, param);
-
- freeArgArray(array, numberOfArgs);
}
fclose(fp);
}