Make console callback use split parameters (e.g. argc/argv style)
[attac-man.git] / console_args.c
blob8f0804a7acb2f36bfdc7393cbd4beedeaa99c7df
1 /**
2 * License - GPL
4 * Command-line splitter function.
5 * Lon Hohberger <lon@metamorphism.com>
6 */
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
11 typedef enum _command_state {
12 STATE_QUOTE = 0x1,
13 STATE_LITERAL = 0x2,
14 STATE_COPY = 0x4
15 } command_state_t;
18 /**
19 * Break up a command string into argv values. Rudimentary.
20 * Destroys the value of cmdline (inserts 0s in order to keep argv
21 * pointers 0-terminated in typical C-style)
23 int
24 command_split(char *cmdline, int *argc, char **argv, int max)
26 char *cmd_copy = NULL;
27 command_state_t state = 0;
28 int offset = 0, copy_offset = 0, ret = 1;
30 if (max <= 0 || argv == NULL || argc == NULL) {
31 errno = EINVAL;
32 return -1;
35 cmd_copy = strdup(cmdline);
36 if (!cmd_copy)
37 return -1;
39 memset(cmdline, 0, strlen(cmdline)+1);
40 *argc = 0;
42 while (cmd_copy[copy_offset]) {
43 switch(cmd_copy[copy_offset]) {
44 case ' ':
45 case '\t':
46 case '\r':
47 case '\n':
48 if (state & (STATE_LITERAL | STATE_QUOTE))
49 break;
50 if (state & STATE_COPY) {
51 state &= ~STATE_COPY;
52 cmdline[offset++] = 0;
53 continue;
55 if (!state) {
56 copy_offset++;
57 continue;
59 break;
60 case '\\':
61 if (state & STATE_LITERAL)
62 break;
63 state |= STATE_LITERAL;
64 ++copy_offset;
65 continue;
67 case '\"':
68 if (state & STATE_LITERAL)
69 break;
70 if (state & STATE_QUOTE) {
71 state &= ~STATE_QUOTE;
72 } else {
73 state |= STATE_QUOTE;
75 ++copy_offset;
76 continue;
79 if (!(state & STATE_COPY)) {
80 if (*argc >= max)
81 goto out;
82 state |= STATE_COPY;
83 argv[(*argc)++] = &cmdline[offset];
86 state &= ~STATE_LITERAL;
88 cmdline[offset] = cmd_copy[copy_offset];
89 ++offset;
90 ++copy_offset;
92 ret = 0;
94 out:
95 if (cmd_copy)
96 free(cmd_copy);
97 return ret;