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 */
}

Reply via email to