1199458Sjilles/*- 2199458Sjilles * Copyright (c) 2004-2009, Jilles Tjoelker 3199458Sjilles * All rights reserved. 4199458Sjilles * 5199458Sjilles * Redistribution and use in source and binary forms, with 6199458Sjilles * or without modification, are permitted provided that the 7199458Sjilles * following conditions are met: 8199458Sjilles * 9199458Sjilles * 1. Redistributions of source code must retain the above 10199458Sjilles * copyright notice, this list of conditions and the 11199458Sjilles * following disclaimer. 12199458Sjilles * 2. Redistributions in binary form must reproduce the 13199458Sjilles * above copyright notice, this list of conditions and 14199458Sjilles * the following disclaimer in the documentation and/or 15199458Sjilles * other materials provided with the distribution. 16199458Sjilles * 17199458Sjilles * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 18199458Sjilles * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 19199458Sjilles * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20199458Sjilles * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 21199458Sjilles * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22199458Sjilles * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 23199458Sjilles * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24199458Sjilles * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25199458Sjilles * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 26199458Sjilles * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27199458Sjilles * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28199458Sjilles * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29199458Sjilles * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 30199458Sjilles * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31199458Sjilles * OF SUCH DAMAGE. 32199458Sjilles */ 33199458Sjilles 34199458Sjilles#include <sys/cdefs.h> 35199458Sjilles__FBSDID("$FreeBSD$"); 36199458Sjilles 37199458Sjilles#include <sys/types.h> 38199458Sjilles#include <sys/event.h> 39199458Sjilles#include <sys/time.h> 40199458Sjilles#include <sys/wait.h> 41199458Sjilles 42199458Sjilles#include <err.h> 43199458Sjilles#include <errno.h> 44199458Sjilles#include <fcntl.h> 45199458Sjilles#include <signal.h> 46199458Sjilles#include <stdio.h> 47199458Sjilles#include <stdlib.h> 48199458Sjilles#include <string.h> 49199458Sjilles#include <sysexits.h> 50199458Sjilles#include <unistd.h> 51199458Sjilles 52199458Sjillesstatic void 53199458Sjillesusage(void) 54199458Sjilles{ 55199458Sjilles 56199458Sjilles fprintf(stderr, "usage: pwait [-v] pid ...\n"); 57199458Sjilles exit(EX_USAGE); 58199458Sjilles} 59199458Sjilles 60199458Sjilles/* 61199458Sjilles * pwait - wait for processes to terminate 62199458Sjilles */ 63199458Sjillesint 64199458Sjillesmain(int argc, char *argv[]) 65199458Sjilles{ 66199458Sjilles int kq; 67199458Sjilles struct kevent *e; 68199458Sjilles int verbose = 0; 69199458Sjilles int opt, nleft, n, i, duplicate, status; 70199458Sjilles long pid; 71199458Sjilles char *s, *end; 72199458Sjilles 73199458Sjilles while ((opt = getopt(argc, argv, "v")) != -1) { 74199458Sjilles switch (opt) { 75199458Sjilles case 'v': 76199458Sjilles verbose = 1; 77199458Sjilles break; 78199458Sjilles default: 79199458Sjilles usage(); 80199458Sjilles /* NOTREACHED */ 81199458Sjilles } 82199458Sjilles } 83199458Sjilles 84199458Sjilles argc -= optind; 85199458Sjilles argv += optind; 86199458Sjilles 87199458Sjilles if (argc == 0) 88199458Sjilles usage(); 89199458Sjilles 90199458Sjilles kq = kqueue(); 91199458Sjilles if (kq == -1) 92199458Sjilles err(1, "kqueue"); 93199458Sjilles 94199458Sjilles e = malloc(argc * sizeof(struct kevent)); 95199458Sjilles if (e == NULL) 96199458Sjilles err(1, "malloc"); 97199458Sjilles nleft = 0; 98199458Sjilles for (n = 0; n < argc; n++) { 99199458Sjilles s = argv[n]; 100199458Sjilles if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */ 101199458Sjilles s += 6; 102199458Sjilles errno = 0; 103199458Sjilles pid = strtol(s, &end, 10); 104199458Sjilles if (pid < 0 || *end != '\0' || errno != 0) { 105199458Sjilles warnx("%s: bad process id", s); 106199458Sjilles continue; 107199458Sjilles } 108199458Sjilles duplicate = 0; 109199458Sjilles for (i = 0; i < nleft; i++) 110199458Sjilles if (e[i].ident == (uintptr_t)pid) 111199458Sjilles duplicate = 1; 112199458Sjilles if (!duplicate) { 113199458Sjilles EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 114199458Sjilles 0, NULL); 115199458Sjilles if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) 116199458Sjilles warn("%ld", pid); 117199458Sjilles else 118199458Sjilles nleft++; 119199458Sjilles } 120199458Sjilles } 121199458Sjilles 122199458Sjilles while (nleft > 0) { 123199458Sjilles n = kevent(kq, NULL, 0, e, nleft, NULL); 124199458Sjilles if (n == -1) 125199458Sjilles err(1, "kevent"); 126199458Sjilles if (verbose) 127199458Sjilles for (i = 0; i < n; i++) { 128199458Sjilles status = e[i].data; 129199458Sjilles if (WIFEXITED(status)) 130199458Sjilles printf("%ld: exited with status %d.\n", 131199458Sjilles (long)e[i].ident, 132199458Sjilles WEXITSTATUS(status)); 133199458Sjilles else if (WIFSIGNALED(status)) 134199458Sjilles printf("%ld: killed by signal %d.\n", 135199458Sjilles (long)e[i].ident, 136199458Sjilles WTERMSIG(status)); 137199458Sjilles else 138199458Sjilles printf("%ld: terminated.\n", 139199458Sjilles (long)e[i].ident); 140199458Sjilles } 141199458Sjilles nleft -= n; 142199458Sjilles } 143199458Sjilles 144245506Sdelphij exit(EX_OK); 145199458Sjilles} 146