Skip to content

Instantly share code, notes, and snippets.

@stevommmm
Created November 19, 2019 01:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stevommmm/d5959888b281820e642e8c904f7ed57b to your computer and use it in GitHub Desktop.
Save stevommmm/d5959888b281820e642e8c904f7ed57b to your computer and use it in GitHub Desktop.
split strings into exec-able args list
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
typedef struct func_args {
char **data;
int count;
} func_args;
void run_command(char **program) {
if (fork()) return;
execvp((char*)program[0], (char**)program);
}
int cmd_count_args(const char *line) {
int count = 0;
int i;
bool in_quotes = false;
bool in_dquotes = false;
for (i = 0; i < strlen(line); i++) {
switch (line[i]) {
case ' ':
if (!in_quotes && !in_dquotes){
count++;
}
break;
case '\'':
if (in_dquotes)
break;
in_quotes = !in_quotes;
break;
case '"':
if (in_quotes)
break;
in_dquotes = !in_dquotes;
break;
}
}
return ++count; // extra for NULL terminator
}
func_args *cmd_split_line(const char *line) {
func_args *fa;
fa = (func_args*)malloc(sizeof(func_args));
fa->count = cmd_count_args(line);
fa->data = malloc((fa->count + 1) * sizeof(char *));
int data_i = 0;
char tmp[strlen(line)];
int tmp_i = 0;
int i;
bool in_quotes = false;
bool in_dquotes = false;
for (i = 0; i < strlen(line); i++) {
switch (line[i]) {
case ' ':
if (!in_quotes && !in_dquotes) {
tmp[tmp_i] = '\0';
fa->data[data_i++] = strndup(tmp, tmp_i);
tmp_i = 0;
} else{
tmp[tmp_i++] = line[i];
}
break;
case '\'':
if (in_dquotes){
tmp[tmp_i++] = line[i];
break;
}
in_quotes = !in_quotes;
break;
case '"':
if (in_quotes){
tmp[tmp_i++] = line[i];
break;
}
in_dquotes = !in_dquotes;
break;
case '\0':
break;
default:
tmp[tmp_i++] = line[i];
break;
}
}
if (tmp_i > 0) {
fa->data[data_i++] = strndup(tmp, tmp_i);
}
fa->data[data_i] = NULL;
return fa;
}
void free_func_args(func_args *fa) {
int i;
for (i = 0; i < fa->count; i++) {
free(fa->data[i]);
}
free(fa->data);
free(fa);
}
int main(int argc, char *argv[]) {
func_args *fa;
int i;
const char *cmd = "echo -e \"$PWD\" 'things and stuff' 'me\"ow' hmmmmm";
fa = cmd_split_line(cmd);
for (i = 0; i < fa->count; i++) {
printf("> %s\n", fa->data[i]);
}
run_command(fa->data);
free_func_args(fa);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment