dorne/cursetree/child.c

63 lines
1.5 KiB
C

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#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;
}