#include #include #include #include char *questions[] = {".*food.*", "^nons", "-E ^.?r..k.?$"}; char* getoutput(char* command); char* get_result(char *pattern){ char command[256]; printf("We're about to run: \n%s\n", command); if(strlen(pattern) > 192){ printf("Maximum pattern length exceeded\n"); exit(1); } snprintf(command, 128, "grep %s /usr/share/dict/american-english", pattern); return getoutput(command); } int main(int argc, char ** argv){ if(argc == 1){ printf("Usage: %s questionnumber [grep_pattern]\n", argv[0]); return 1; } unsigned qnum = atoi(argv[1]); char *correct_result = get_result(questions[qnum - 1]); if(argc == 2){ puts(correct_result); goto out_and_free; } char *users_result = get_result(argv[2]); if(!strcmp(correct_result, users_result)){ printf("You got it!\n"); } else { puts("Sorry, results differ. Your command generated: "); puts(users_result); } free(users_result); out_and_free: free(correct_result); if(argc > 3) printf("Extra parameter detected: %s\n", argv[3]); return 0; } char* getoutput(char* command){ // We'll need a pipe to put the output into // The command will have to run, and put output into the pipe // We'll have to read from the pipe int pipe_fds[2]; char *buffer = malloc(16); pipe(pipe_fds); pid_t child = fork(); if(!child){ // Command part: // 1. Do plumbing as needed to send output into the pipe // 2. Run the command dup2(pipe_fds[1], 1); execl("/bin/sh", "sh", "-c", command, (char *) 0); } else { // Capture part: // 1. Wait for the command to run // 2. Collect the output from the pipe // while there's more to read: // read more stuff size_t sofar = 0; close(pipe_fds[1]); for(;;) { ssize_t readlen = read(pipe_fds[0], buffer + sofar, 16); if(readlen <= 0) break; sofar += readlen; buffer = realloc(buffer, sofar + 16); } buffer[sofar] = 0; // printf("We read: %s\n", buffer); return buffer; } }