You will need to use fork and execvp to the run the command specified by an action. Fortunately in Part 1, you already prepared the array of arguments to pass into execvp. The parent process should wait for each child to complete. If the child terminates with a non-zero exit status, the parent should also terminate with a non-zero exit status. This means that pmake will stop when it encounters an error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

#include "pmake.h"

void execute_action(Action *action) {
	printf("%s\n", *action->args);
	pid_t pid = fork();
	if (pid == 0) {
		execvp(action->args[0], action->args);
		fprintf(stderr, "Error: execvp failed\n");
		exit(1);
	} else if (pid < 0) {
		fprintf(stderr, "Error: Fork failed\n");
		exit(1);
	} else {
		int status;
		waitpid(pid, &status, 0);
		if (WIFSIGNALED(status) || WEXITSTATUS(status) != 0) {
			fprintf(stderr, "Error: Child process exited with non-zero status\n");
			exit(1);
		}
	}
}