/*- * Copyright (c) 2004-2009, Jilles Tjoelker * All rights reserved. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the * following conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include static void usage(void) { fprintf(stderr, "usage: pwait [-v] pid ...\n"); exit(EX_USAGE); } /* * pwait - wait for processes to terminate */ int main(int argc, char *argv[]) { int kq; struct kevent *e; int verbose = 0; int opt, nleft, n, i, duplicate, status; long pid; char *s, *end; while ((opt = getopt(argc, argv, "v")) != -1) { switch (opt) { case 'v': verbose = 1; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc == 0) usage(); kq = kqueue(); if (kq == -1) err(1, "kqueue"); e = malloc(argc * sizeof(struct kevent)); if (e == NULL) err(1, "malloc"); nleft = 0; for (n = 0; n < argc; n++) { s = argv[n]; if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */ s += 6; errno = 0; pid = strtol(s, &end, 10); if (pid < 0 || *end != '\0' || errno != 0) { warnx("%s: bad process id", s); continue; } duplicate = 0; for (i = 0; i < nleft; i++) if (e[i].ident == (uintptr_t)pid) duplicate = 1; if (!duplicate) { EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL); if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) warn("%ld", pid); else nleft++; } } while (nleft > 0) { n = kevent(kq, NULL, 0, e, nleft, NULL); if (n == -1) err(1, "kevent"); if (verbose) for (i = 0; i < n; i++) { status = e[i].data; if (WIFEXITED(status)) printf("%ld: exited with status %d.\n", (long)e[i].ident, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("%ld: killed by signal %d.\n", (long)e[i].ident, WTERMSIG(status)); else printf("%ld: terminated.\n", (long)e[i].ident); } nleft -= n; } exit(EX_OK); }