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

