pwait.c (cfe30d02adda7c3b5c76156ac52d50d8cab325d9) pwait.c (b06b52baac41c3a6b7c0a30552c4776154f412c9)
1/*-
2 * Copyright (c) 2004-2009, Jilles Tjoelker
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with
6 * or without modification, are permitted provided that the
7 * following conditions are met:
8 *

--- 39 unchanged lines hidden (view full) ---

48#include <string.h>
49#include <sysexits.h>
50#include <unistd.h>
51
52static void
53usage(void)
54{
55
1/*-
2 * Copyright (c) 2004-2009, Jilles Tjoelker
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with
6 * or without modification, are permitted provided that the
7 * following conditions are met:
8 *

--- 39 unchanged lines hidden (view full) ---

48#include <string.h>
49#include <sysexits.h>
50#include <unistd.h>
51
52static void
53usage(void)
54{
55
56 fprintf(stderr, "usage: pwait [-v] pid ...\n");
56 fprintf(stderr, "usage: pwait [-t timeout] [-v] pid ...\n");
57 exit(EX_USAGE);
58}
59
60/*
61 * pwait - wait for processes to terminate
62 */
63int
64main(int argc, char *argv[])
65{
57 exit(EX_USAGE);
58}
59
60/*
61 * pwait - wait for processes to terminate
62 */
63int
64main(int argc, char *argv[])
65{
66 struct itimerval itv;
66 int kq;
67 struct kevent *e;
67 int kq;
68 struct kevent *e;
68 int verbose = 0;
69 int tflag, verbose;
69 int opt, nleft, n, i, duplicate, status;
70 long pid;
71 char *s, *end;
70 int opt, nleft, n, i, duplicate, status;
71 long pid;
72 char *s, *end;
73 double timeout;
72
74
73 while ((opt = getopt(argc, argv, "v")) != -1) {
75 tflag = verbose = 0;
76 memset(&itv, 0, sizeof(itv));
77 while ((opt = getopt(argc, argv, "t:v")) != -1) {
74 switch (opt) {
78 switch (opt) {
79 case 't':
80 tflag = 1;
81 errno = 0;
82 timeout = strtod(optarg, &end);
83 if (end == optarg || errno == ERANGE ||
84 timeout < 0)
85 errx(EX_DATAERR, "timeout value");
86 switch(*end) {
87 case 0:
88 case 's':
89 break;
90 case 'h':
91 timeout *= 60;
92 /* FALLTHROUGH */
93 case 'm':
94 timeout *= 60;
95 break;
96 default:
97 errx(EX_DATAERR, "timeout unit");
98 }
99 if (timeout > 100000000L)
100 errx(EX_DATAERR, "timeout value");
101 itv.it_value.tv_sec = (time_t)timeout;
102 timeout -= (time_t)timeout;
103 itv.it_value.tv_usec =
104 (suseconds_t)(timeout * 1000000UL);
105 break;
75 case 'v':
76 verbose = 1;
77 break;
78 default:
79 usage();
80 /* NOTREACHED */
81 }
82 }
83
84 argc -= optind;
85 argv += optind;
86
87 if (argc == 0)
88 usage();
89
90 kq = kqueue();
91 if (kq == -1)
92 err(1, "kqueue");
93
106 case 'v':
107 verbose = 1;
108 break;
109 default:
110 usage();
111 /* NOTREACHED */
112 }
113 }
114
115 argc -= optind;
116 argv += optind;
117
118 if (argc == 0)
119 usage();
120
121 kq = kqueue();
122 if (kq == -1)
123 err(1, "kqueue");
124
94 e = malloc(argc * sizeof(struct kevent));
125 e = malloc((argc + tflag) * sizeof(struct kevent));
95 if (e == NULL)
96 err(1, "malloc");
97 nleft = 0;
98 for (n = 0; n < argc; n++) {
99 s = argv[n];
100 if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */
101 s += 6;
102 errno = 0;

--- 11 unchanged lines hidden (view full) ---

114 0, NULL);
115 if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
116 warn("%ld", pid);
117 else
118 nleft++;
119 }
120 }
121
126 if (e == NULL)
127 err(1, "malloc");
128 nleft = 0;
129 for (n = 0; n < argc; n++) {
130 s = argv[n];
131 if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */
132 s += 6;
133 errno = 0;

--- 11 unchanged lines hidden (view full) ---

145 0, NULL);
146 if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
147 warn("%ld", pid);
148 else
149 nleft++;
150 }
151 }
152
153 if (tflag) {
154 /*
155 * Explicitly detect SIGALRM so that an exit status of 124
156 * can be returned rather than 142.
157 */
158 EV_SET(e + nleft, SIGALRM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
159 if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
160 err(EX_OSERR, "kevent");
161 /* Ignore SIGALRM to not interrupt kevent(2). */
162 signal(SIGALRM, SIG_IGN);
163 if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
164 err(EX_OSERR, "setitimer");
165 }
122 while (nleft > 0) {
166 while (nleft > 0) {
123 n = kevent(kq, NULL, 0, e, nleft, NULL);
167 n = kevent(kq, NULL, 0, e, nleft + tflag, NULL);
124 if (n == -1)
125 err(1, "kevent");
168 if (n == -1)
169 err(1, "kevent");
126 if (verbose)
127 for (i = 0; i < n; i++) {
170 for (i = 0; i < n; i++) {
171 if (e[i].filter == EVFILT_SIGNAL) {
172 if (verbose)
173 printf("timeout\n");
174 return (124);
175 }
176 if (verbose) {
128 status = e[i].data;
129 if (WIFEXITED(status))
130 printf("%ld: exited with status %d.\n",
131 (long)e[i].ident,
132 WEXITSTATUS(status));
133 else if (WIFSIGNALED(status))
134 printf("%ld: killed by signal %d.\n",
135 (long)e[i].ident,
136 WTERMSIG(status));
137 else
138 printf("%ld: terminated.\n",
139 (long)e[i].ident);
140 }
177 status = e[i].data;
178 if (WIFEXITED(status))
179 printf("%ld: exited with status %d.\n",
180 (long)e[i].ident,
181 WEXITSTATUS(status));
182 else if (WIFSIGNALED(status))
183 printf("%ld: killed by signal %d.\n",
184 (long)e[i].ident,
185 WTERMSIG(status));
186 else
187 printf("%ld: terminated.\n",
188 (long)e[i].ident);
189 }
141 nleft -= n;
190 --nleft;
191 }
142 }
143
144 exit(EX_OK);
145}
192 }
193
194 exit(EX_OK);
195}