On Fri, 9 Jul 2010 23:23:52 -0700, patrick keshishian <[email protected]>
wrote:
> Don't leave zombies behind. Collect your children or ignore SIGCHLD.
Sigh, yeah... I meant to handle that, but then got side tracked and
forgot to fix it when I came back to send the email.
Oh well, updated zombie-proof version below.
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <net/if.h>
#include <net/route.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <err.h>
void
usage(void)
{
extern char *__progname;
fprintf(stderr, "usage: %s [-i interface] command ...\n", __progname);
exit(1);
}
int
main(int argc, char *argv[])
{
char msg[2048];
int fd;
ssize_t n;
pid_t pid;
struct rt_msghdr *rtm;
struct ifa_msghdr *ifam;
unsigned int rtfilter;
unsigned int ifindex = 0;
int ch;
while ((ch = getopt(argc, argv, "i:")) != -1) {
switch (ch) {
case 'i':
ifindex = if_nametoindex(optarg);
if (ifindex == 0)
errx(1, "no interface: %s", optarg);
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argv[0] == NULL)
usage();
fd = socket(PF_ROUTE, SOCK_RAW, 0);
if (fd == -1)
err(1, "unable to open route socket");
rtfilter = ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR);
if (setsockopt(fd, PF_ROUTE, ROUTE_MSGFILTER, &rtfilter,
sizeof(rtfilter)) == -1)
err(1, "unable to set route message filter");
for (;;) {
n = read(fd, msg, sizeof(msg));
if (n == -1)
err(1, "unable to read from route socket");
if (n == 0)
errx(1, "eof on route socket");
rtm = (struct rt_msghdr *)msg;
if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
warnx("route message truncated");
continue;
}
if (rtm->rtm_version != RTM_VERSION) {
warnx("bad route message version");
continue;
}
if (rtm->rtm_type != RTM_NEWADDR &&
rtm->rtm_type != RTM_DELADDR) {
warnx("unexpected route message");
continue;
}
ifam = (struct ifa_msghdr *)rtm;
if (ifindex != 0 && ifam->ifam_index != ifindex)
continue;
pid = rfork(RFFDG | RFPROC | RFNOWAIT);
if (pid == -1) {
warnx("unable to fork child");
continue;
}
if (pid == 0) {
execvp(argv[0], argv);
err(1, "unable to exec command");
}
}
/* NOTREACHED */
}