static int run_cmds(clockid_t clkid, int cmdc, char *cmdv[]) { int i = 0, result = 0; cmd_func_t action = NULL; while (i < cmdc) { char *arg = cmdv[i]; /* increment now to remove the command argument */ i++; action = get_command_function(arg); if (action) result = action(clkid, cmdc - i, &cmdv[i]); else pr_err("unknown command %s.", arg); /* result is how many arguments were used up by the command, * not including the ";". We will increment the loop counter * to avoid processing the arguments as commands. */ if (result < 0) return result; else i += result; } return 0; }
void LineLocator(struct ConnectionNode *conn) { /* look for the end of the line */ char *str1, *saveptr1, *ntoken, *token; bool endswell = false; switch (conn->buf[conn->nbytes - 1]) { case '\r': case '\n': endswell = true; break; }; for (str1 = conn->buf;; str1 = NULL ) { ntoken = strtok_r(str1, "\r\n", &saveptr1); /* Reverse this so we know the next result. */ if (str1 == NULL ) { if (ntoken != NULL || endswell) { char *str2, *saveptr2, *subtoken; char **argv = NULL; while (argv == NULL ) argv = malloc(0); int argc = 0; for (str2 = token;; str2 = NULL ) { subtoken = strtok_r(str2, " \t", &saveptr2); if (subtoken == NULL ) break; void *i = NULL; while (i == NULL ) i = realloc(argv, sizeof(void*) * (argc + 1)); argv = i; argv[argc++] = subtoken; } CommandFunc f; f = get_command_function(argv[0]); if (!f) { write(conn->fd, "502 Bad command or it is not implemented here.\r\n", 48); } else f(conn, argc, argv); if (ntoken == NULL ) { free(conn->buf); conn->buf = NULL; conn->nbytes = 0; break; } } else { conn->nbytes = strlen(token); str1 = strdup(token); free(conn->buf); conn->buf = str1; break; } } token = ntoken; } }
static int parse_message(const char *str, Client *c) { typedef enum { ST_INITIAL, ST_WHITESPACE, ST_ARGUMENT, ST_FINAL } State; State state = ST_INITIAL; int error = 0; char quote = '\0'; /* The quote used to open a quote string */ int pos = 0; char *arg_space; int argc = 0; char *argv[MAX_ARGUMENTS]; int argpos = 0; CommandFunc function = NULL; debug(RPT_DEBUG, "%s(str=\"%.120s\", client=[%d])", __FUNCTION__, str, c->sock); /* We will create a list of strings that is shorter or equally long as * the original string str. */ arg_space = malloc(strlen(str)+1); if (arg_space == NULL) { report(RPT_ERR, "%s: Could not allocate memory", __FUNCTION__); sock_send_error(c->sock, "error allocating memory!\n"); } argv[0] = arg_space; while ((state != ST_FINAL) && !error) { char ch = str[pos++]; switch (state) { case ST_INITIAL: case ST_WHITESPACE: if (is_whitespace(ch)) break; if (is_final(ch)) { state = ST_FINAL; break; } /* otherwise fall through */ state = ST_ARGUMENT; case ST_ARGUMENT: if (is_final(ch)) { if (quote) error = 2; if (argc >= MAX_ARGUMENTS-1) { error = 1; } else { argv[argc][argpos] = '\0'; argv[argc+1] = argv[argc] + argpos + 1; argc++; argpos = 0; } state = ST_FINAL; } else if (ch == '\\') { if (str[pos]) { /* We solve quoted chars here right away */ const char escape_chars[] = "nrt"; const char escape_trans[] = "\n\r\t"; char *p = strchr(escape_chars, str[pos]); /* Is it wise to have the characters \n, \r & \t expanded ? * Can the displays deal with them ? */ if (p != NULL) { /* Insert a replacement for the code */ argv[argc][argpos++] = escape_trans[p - escape_chars]; } else { /* Copy char literally */ argv[argc][argpos++] = str[pos]; } pos++; } else { error = 2; /* alternative: argv[argc][argpos++] = ch; */ if (argc >= MAX_ARGUMENTS-1) { error = 1; } else { argv[argc][argpos] = '\0'; argv[argc+1] = argv[argc] + argpos + 1; argc++; argpos = 0; } state = ST_FINAL; } } else if (is_opening_quote(ch, quote)) { quote = ch; } else if (is_closing_quote(ch, quote)) { quote = '\0'; if (argc >= MAX_ARGUMENTS-1) { error = 1; } else { argv[argc][argpos] = '\0'; argv[argc+1] = argv[argc] + argpos + 1; argc++; argpos = 0; } state = ST_WHITESPACE; } else if (is_whitespace(ch) && (quote == '\0')) { if (argc >= MAX_ARGUMENTS-1) { error = 1; } else { argv[argc][argpos] = '\0'; argv[argc+1] = argv[argc] + argpos + 1; argc++; argpos = 0; } state = ST_WHITESPACE; } else { argv[argc][argpos++] = ch; } break; case ST_FINAL: /* This will never be reached */ break; } } if (argc < MAX_ARGUMENTS) argv[argc] = NULL; else error = 1; if (error) { sock_send_error(c->sock, "Could not parse command\n"); free(arg_space); return 0; } #if 0 /* show what we have parsed */ int i; for (i = 0; i < argc; i++) { printf("%s%c", argv[i], (i == argc-1) ? '\n' : ' '); } #endif /* Now find and call the appropriate function...*/ function = get_command_function(argv[0]); if (function != NULL) { error = function(c, argc, argv); if (error) { sock_printf_error(c->sock, "Function returned error \"%.40s\"\n", argv[0]); report(RPT_WARNING, "Command function returned an error after command from client on socket %d: %.40s", c->sock, str); } } else { sock_printf_error(c->sock, "Invalid command \"%.40s\"\n", argv[0]); report(RPT_WARNING, "Invalid command from client on socket %d: %.40s", c->sock, str); } free(arg_space); return 0; }
static inline int name_is_a_command(const char *name) { return get_command_function(name) != NULL; }