#include #include #include #include #include "child.h" #include "epty.h" /* SIGTERM grace period before a child is sent SIGKILL. * Value is in microseconds (us), 1000us = 1ms */ #define CHILD_GRACE_US 100000 /* Check if a child is still alive by pid * by kill(3p) sending a null signal (0). */ static int is_alive(struct d_child *child) { return (kill(child->pid, 0) == 0); } /* Force a child to die, first by sending SIGTERM, otherwise SIGKILL. * NOTE: killchild() ASSUMES the child is LIVING at the start. * NOTE: Keep this in mind when threading! */ void killchild(struct d_child *child) { int stat; /* Request Death */ kill(child->pid, SIGTERM); usleep(CHILD_GRACE_US); /* Force Death */ if (is_alive(child)) kill(child->pid, SIGKILL); /* Reap */ waitpid(child->pid, &stat, 0); } /* Fork to spawn a child process running bin/shfx in an "epty". */ int spawnchild(struct d_child *child) { *child = (struct d_child){ 0 }; /* fork(2) and allocate an "error-piped pseudoterminal" (epty) */ switch (child->pid = forkepty(&child->fdmx, &child->fderr)) { case -1: perror("forkepty"); return EXIT_FAILURE; case 0: char *args[] = {"shfx", NULL}; execvp("shfx", args); perror("execvp"); exit(1); default: usleep(1000); char bufout[10]; bufout[9] = '\0'; read(child->fdmx, bufout, 9); printf("child stdout: \"%s\"\n", bufout); break; } return EXIT_SUCCESS; }