Don't leave zombies behind. Collect your children or ignore SIGCHLD.

On Fri, Jul 9, 2010 at 6:31 PM, Matthew Dempsky <[email protected]> wrote:
> On Sat, 10 Jul 2010 00:02:16 +0200, Christian Taube <[email protected]>
wrote:
>> What I am missing now is a way to run a script when the IP address on
>> the pppoe interface changes. There seems to be no mechanism
>> like the /etc/ppp/ppp.linkup script provided by the user-space pppoe(8)
>> driver.
>
> You might try the program below.  Just compile with:
>
>    cc -O2 -o watchaddr watchaddr.c
>
> You can then run something like:
>
>    ./watchaddr -i pppoe0 /path/to/script
>
> and whenever an address is added to or removed from pppoe0,
> /path/to/script will be run.  Omit the "-i pppoe0" option, and it will
> run when an address changes on any interface.
>
> Beware that changing an address involves an address both being removed
> and being added, so your script will run twice.
>
> (It looks like this functionality could easily be added to
> ifstated(8), but a diff for that would be a bit more involved than
> whipping up this one off program. ;-)
>
>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <net/if.h>
> #include <net/route.h>
> #include <err.h>
> #include <errno.h>
> #include <unistd.h>
> #include <stdio.h>
> #include <stdlib.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) {
>                        if (errno == EINTR)
>                                continue;
>                        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 = fork();
>                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