aos/lib/spawn/argv.c
Daniel Schwyn 6d444bf552 Main handout
Signed-off-by: Daniel Schwyn <daniel.schwyn@inf.ethz.ch>
2022-03-03 14:57:51 +01:00

92 lines
2.8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <aos/aos.h>
#include <barrelfish_kpi/init.h>
#include <spawn/argv.h>
/**
* \brief Tokenize the command line arguments and count them
*
* \param cmdline The string to be parsed. Must not be NULL.
* \param _argc Will be filled out with the number of arguments
* found in 'cmdline'. Must not be NULL.
* \param buf Will be filled out with a char array that contains
* the continuously in memory arranged arguments separated by '\0'.
* (Note that there might also be some extra whitespace intbetween
* the arguments.)
* \return If 'cmdline' was parsed and tokenized successfully, argv
* (an array of the arguments) will be returned, NULL otherwise.
*/
char ** make_argv(const char *cmdline, int *_argc, char **buf) {
char **argv= calloc(MAX_CMDLINE_ARGS+1, sizeof(char *));
if(!argv) return NULL;
/* Carefully calculate the length of the command line. */
size_t len= strnlen(cmdline, PATH_MAX+1);
if(len > PATH_MAX) return NULL;
/* Copy the command line, as we'll chop it up. */
*buf= malloc(len + 1);
if(!*buf) {
free(argv);
return NULL;
}
strncpy(*buf, cmdline, len + 1);
(*buf)[len]= '\0';
int argc= 0;
size_t i= 0;
while(i < len && argc < MAX_CMDLINE_ARGS) {
/* Skip leading whitespace. */
while(i < len && isspace((unsigned char)(*buf)[i])) i++;
/* We may have just walked off the end. */
if(i >= len) break;
if((*buf)[i] == '"') {
/* If the first character is ", then we need to scan until the
* closing ". */
/* The next argument starts *after* the opening ". */
i++;
argv[argc]= &(*buf)[i];
argc++;
/* Find the closing ". */
while(i < len && (*buf)[i] != '"') i++;
/* If we've found a ", overwrite it to null-terminate the string.
* Otherwise, let the argument be terminated by end-of-line. */
if(i < len) {
(*buf)[i]= '\0';
i++;
}
}
else {
/* Otherwise grab everything until the next whitespace
* character. */
/* The next argument starts here. */
argv[argc]= &(*buf)[i];
argc++;
/* Find the next whitespace (if any). */
while(i < len && !isspace((unsigned char)(*buf)[i])) i++;
/* Null-terminate the string by overwriting the first whitespace
* character, unless we're at the end, in which case the null at
* the end of buf will terminate this argument. */
if(i < len) {
(*buf)[i]= '\0';
i++;
}
}
}
/* (*buf)[argc] == NULL */
*_argc= argc;
return argv;
}