10e5e4167SJilles Tjoelker /*- 20e5e4167SJilles Tjoelker * Copyright (c) 2004-2009, Jilles Tjoelker 30e5e4167SJilles Tjoelker * All rights reserved. 40e5e4167SJilles Tjoelker * 50e5e4167SJilles Tjoelker * Redistribution and use in source and binary forms, with 60e5e4167SJilles Tjoelker * or without modification, are permitted provided that the 70e5e4167SJilles Tjoelker * following conditions are met: 80e5e4167SJilles Tjoelker * 90e5e4167SJilles Tjoelker * 1. Redistributions of source code must retain the above 100e5e4167SJilles Tjoelker * copyright notice, this list of conditions and the 110e5e4167SJilles Tjoelker * following disclaimer. 120e5e4167SJilles Tjoelker * 2. Redistributions in binary form must reproduce the 130e5e4167SJilles Tjoelker * above copyright notice, this list of conditions and 140e5e4167SJilles Tjoelker * the following disclaimer in the documentation and/or 150e5e4167SJilles Tjoelker * other materials provided with the distribution. 160e5e4167SJilles Tjoelker * 170e5e4167SJilles Tjoelker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 180e5e4167SJilles Tjoelker * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 190e5e4167SJilles Tjoelker * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 200e5e4167SJilles Tjoelker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 210e5e4167SJilles Tjoelker * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 220e5e4167SJilles Tjoelker * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 230e5e4167SJilles Tjoelker * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240e5e4167SJilles Tjoelker * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 250e5e4167SJilles Tjoelker * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 260e5e4167SJilles Tjoelker * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 270e5e4167SJilles Tjoelker * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 280e5e4167SJilles Tjoelker * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 290e5e4167SJilles Tjoelker * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 300e5e4167SJilles Tjoelker * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 310e5e4167SJilles Tjoelker * OF SUCH DAMAGE. 320e5e4167SJilles Tjoelker */ 330e5e4167SJilles Tjoelker 340e5e4167SJilles Tjoelker #include <sys/cdefs.h> 350e5e4167SJilles Tjoelker __FBSDID("$FreeBSD$"); 360e5e4167SJilles Tjoelker 370e5e4167SJilles Tjoelker #include <sys/types.h> 380e5e4167SJilles Tjoelker #include <sys/event.h> 390e5e4167SJilles Tjoelker #include <sys/time.h> 400e5e4167SJilles Tjoelker #include <sys/wait.h> 410e5e4167SJilles Tjoelker 420e5e4167SJilles Tjoelker #include <err.h> 430e5e4167SJilles Tjoelker #include <errno.h> 440e5e4167SJilles Tjoelker #include <fcntl.h> 450e5e4167SJilles Tjoelker #include <signal.h> 460e5e4167SJilles Tjoelker #include <stdio.h> 470e5e4167SJilles Tjoelker #include <stdlib.h> 480e5e4167SJilles Tjoelker #include <string.h> 490e5e4167SJilles Tjoelker #include <sysexits.h> 500e5e4167SJilles Tjoelker #include <unistd.h> 510e5e4167SJilles Tjoelker 520e5e4167SJilles Tjoelker static void 530e5e4167SJilles Tjoelker usage(void) 540e5e4167SJilles Tjoelker { 550e5e4167SJilles Tjoelker 560e5e4167SJilles Tjoelker fprintf(stderr, "usage: pwait [-v] pid ...\n"); 570e5e4167SJilles Tjoelker exit(EX_USAGE); 580e5e4167SJilles Tjoelker } 590e5e4167SJilles Tjoelker 600e5e4167SJilles Tjoelker /* 610e5e4167SJilles Tjoelker * pwait - wait for processes to terminate 620e5e4167SJilles Tjoelker */ 630e5e4167SJilles Tjoelker int 640e5e4167SJilles Tjoelker main(int argc, char *argv[]) 650e5e4167SJilles Tjoelker { 660e5e4167SJilles Tjoelker int kq; 670e5e4167SJilles Tjoelker struct kevent *e; 680e5e4167SJilles Tjoelker int verbose = 0; 690e5e4167SJilles Tjoelker int opt, nleft, n, i, duplicate, status; 700e5e4167SJilles Tjoelker long pid; 710e5e4167SJilles Tjoelker char *s, *end; 720e5e4167SJilles Tjoelker 730e5e4167SJilles Tjoelker while ((opt = getopt(argc, argv, "v")) != -1) { 740e5e4167SJilles Tjoelker switch (opt) { 750e5e4167SJilles Tjoelker case 'v': 760e5e4167SJilles Tjoelker verbose = 1; 770e5e4167SJilles Tjoelker break; 780e5e4167SJilles Tjoelker default: 790e5e4167SJilles Tjoelker usage(); 800e5e4167SJilles Tjoelker /* NOTREACHED */ 810e5e4167SJilles Tjoelker } 820e5e4167SJilles Tjoelker } 830e5e4167SJilles Tjoelker 840e5e4167SJilles Tjoelker argc -= optind; 850e5e4167SJilles Tjoelker argv += optind; 860e5e4167SJilles Tjoelker 870e5e4167SJilles Tjoelker if (argc == 0) 880e5e4167SJilles Tjoelker usage(); 890e5e4167SJilles Tjoelker 900e5e4167SJilles Tjoelker kq = kqueue(); 910e5e4167SJilles Tjoelker if (kq == -1) 920e5e4167SJilles Tjoelker err(1, "kqueue"); 930e5e4167SJilles Tjoelker 940e5e4167SJilles Tjoelker e = malloc(argc * sizeof(struct kevent)); 950e5e4167SJilles Tjoelker if (e == NULL) 960e5e4167SJilles Tjoelker err(1, "malloc"); 970e5e4167SJilles Tjoelker nleft = 0; 980e5e4167SJilles Tjoelker for (n = 0; n < argc; n++) { 990e5e4167SJilles Tjoelker s = argv[n]; 1000e5e4167SJilles Tjoelker if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */ 1010e5e4167SJilles Tjoelker s += 6; 1020e5e4167SJilles Tjoelker errno = 0; 1030e5e4167SJilles Tjoelker pid = strtol(s, &end, 10); 1040e5e4167SJilles Tjoelker if (pid < 0 || *end != '\0' || errno != 0) { 1050e5e4167SJilles Tjoelker warnx("%s: bad process id", s); 1060e5e4167SJilles Tjoelker continue; 1070e5e4167SJilles Tjoelker } 1080e5e4167SJilles Tjoelker duplicate = 0; 1090e5e4167SJilles Tjoelker for (i = 0; i < nleft; i++) 1100e5e4167SJilles Tjoelker if (e[i].ident == (uintptr_t)pid) 1110e5e4167SJilles Tjoelker duplicate = 1; 1120e5e4167SJilles Tjoelker if (!duplicate) { 1130e5e4167SJilles Tjoelker EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 1140e5e4167SJilles Tjoelker 0, NULL); 1150e5e4167SJilles Tjoelker if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) 1160e5e4167SJilles Tjoelker warn("%ld", pid); 1170e5e4167SJilles Tjoelker else 1180e5e4167SJilles Tjoelker nleft++; 1190e5e4167SJilles Tjoelker } 1200e5e4167SJilles Tjoelker } 1210e5e4167SJilles Tjoelker 1220e5e4167SJilles Tjoelker while (nleft > 0) { 1230e5e4167SJilles Tjoelker n = kevent(kq, NULL, 0, e, nleft, NULL); 1240e5e4167SJilles Tjoelker if (n == -1) 1250e5e4167SJilles Tjoelker err(1, "kevent"); 1260e5e4167SJilles Tjoelker if (verbose) 1270e5e4167SJilles Tjoelker for (i = 0; i < n; i++) { 1280e5e4167SJilles Tjoelker status = e[i].data; 1290e5e4167SJilles Tjoelker if (WIFEXITED(status)) 1300e5e4167SJilles Tjoelker printf("%ld: exited with status %d.\n", 1310e5e4167SJilles Tjoelker (long)e[i].ident, 1320e5e4167SJilles Tjoelker WEXITSTATUS(status)); 1330e5e4167SJilles Tjoelker else if (WIFSIGNALED(status)) 1340e5e4167SJilles Tjoelker printf("%ld: killed by signal %d.\n", 1350e5e4167SJilles Tjoelker (long)e[i].ident, 1360e5e4167SJilles Tjoelker WTERMSIG(status)); 1370e5e4167SJilles Tjoelker else 1380e5e4167SJilles Tjoelker printf("%ld: terminated.\n", 1390e5e4167SJilles Tjoelker (long)e[i].ident); 1400e5e4167SJilles Tjoelker } 1410e5e4167SJilles Tjoelker nleft -= n; 1420e5e4167SJilles Tjoelker } 1430e5e4167SJilles Tjoelker 144*f3de285bSXin LI exit(EX_OK); 1450e5e4167SJilles Tjoelker } 146