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