1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/ctfs.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/contract/process.h> 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <unistd.h> 36*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <errno.h> 39*7c478bd9Sstevel@tonic-gate #include <limits.h> 40*7c478bd9Sstevel@tonic-gate #include <libcontract.h> 41*7c478bd9Sstevel@tonic-gate #include <libcontract_priv.h> 42*7c478bd9Sstevel@tonic-gate #include <libuutil.h> 43*7c478bd9Sstevel@tonic-gate #include <poll.h> 44*7c478bd9Sstevel@tonic-gate #include <port.h> 45*7c478bd9Sstevel@tonic-gate #include <signal.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 47*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <locale.h> 50*7c478bd9Sstevel@tonic-gate #include <langinfo.h> 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate struct { 53*7c478bd9Sstevel@tonic-gate const char *name; 54*7c478bd9Sstevel@tonic-gate int found; 55*7c478bd9Sstevel@tonic-gate } types[] = { 56*7c478bd9Sstevel@tonic-gate { "process", 0 }, 57*7c478bd9Sstevel@tonic-gate { NULL } 58*7c478bd9Sstevel@tonic-gate }; 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate typedef struct watched_fd { 61*7c478bd9Sstevel@tonic-gate int wf_fd; 62*7c478bd9Sstevel@tonic-gate int wf_type; 63*7c478bd9Sstevel@tonic-gate } watched_fd_t; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * usage 67*7c478bd9Sstevel@tonic-gate * 68*7c478bd9Sstevel@tonic-gate * Educate the user. 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate static void 71*7c478bd9Sstevel@tonic-gate usage(void) 72*7c478bd9Sstevel@tonic-gate { 73*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 74*7c478bd9Sstevel@tonic-gate "Usage: %s [-f] [-r] [-v] contract-id | contract-type ...\n"), 75*7c478bd9Sstevel@tonic-gate uu_getpname()); 76*7c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE); 77*7c478bd9Sstevel@tonic-gate } 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* 80*7c478bd9Sstevel@tonic-gate * sopen 81*7c478bd9Sstevel@tonic-gate * 82*7c478bd9Sstevel@tonic-gate * Given a format string and a variable number of arguments, create a 83*7c478bd9Sstevel@tonic-gate * file name and open it. Warn with 'permerror' and return -1 if 84*7c478bd9Sstevel@tonic-gate * opening the file returned EPERM or EACCES, die with 'error' on all 85*7c478bd9Sstevel@tonic-gate * other error conditions. 86*7c478bd9Sstevel@tonic-gate */ 87*7c478bd9Sstevel@tonic-gate static int 88*7c478bd9Sstevel@tonic-gate sopen(const char *format, const char *error, const char *permerror, ...) 89*7c478bd9Sstevel@tonic-gate { 90*7c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 91*7c478bd9Sstevel@tonic-gate int fd; 92*7c478bd9Sstevel@tonic-gate va_list varg; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate va_start(varg, permerror); 95*7c478bd9Sstevel@tonic-gate if (vsnprintf(path, PATH_MAX, format, varg) >= PATH_MAX) { 96*7c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 97*7c478bd9Sstevel@tonic-gate uu_vdie(error, varg); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate if ((fd = open64(path, O_RDONLY | O_NONBLOCK)) == -1) { 101*7c478bd9Sstevel@tonic-gate if (permerror && (errno == EPERM || errno == EACCES)) 102*7c478bd9Sstevel@tonic-gate uu_vwarn(permerror, varg); 103*7c478bd9Sstevel@tonic-gate else 104*7c478bd9Sstevel@tonic-gate uu_vdie(error, varg); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate va_end(varg); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate return (fd); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * hdr_event 113*7c478bd9Sstevel@tonic-gate * 114*7c478bd9Sstevel@tonic-gate * Display the output header. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate static void 117*7c478bd9Sstevel@tonic-gate hdr_event(void) 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate (void) printf("%-8s%-8s%-5s%-4s%-9s%s\n", 120*7c478bd9Sstevel@tonic-gate "CTID", "EVID", "CRIT", "ACK", "CTTYPE", "SUMMARY"); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * get_event 125*7c478bd9Sstevel@tonic-gate * 126*7c478bd9Sstevel@tonic-gate * Read and display a contract event. 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate static int 129*7c478bd9Sstevel@tonic-gate get_event(int fd, int type, int verbose) 130*7c478bd9Sstevel@tonic-gate { 131*7c478bd9Sstevel@tonic-gate ct_evthdl_t ev; 132*7c478bd9Sstevel@tonic-gate uint_t flags; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * Read a contract event. 136*7c478bd9Sstevel@tonic-gate */ 137*7c478bd9Sstevel@tonic-gate if (errno = ct_event_read(fd, &ev)) { 138*7c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 139*7c478bd9Sstevel@tonic-gate return (0); 140*7c478bd9Sstevel@tonic-gate uu_die(gettext("could not receive contract event")); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * Emit a one-line event summary. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate flags = ct_event_get_flags(ev); 147*7c478bd9Sstevel@tonic-gate (void) printf("%-8ld%-8lld%-5s%-4s%-9s", 148*7c478bd9Sstevel@tonic-gate ct_event_get_ctid(ev), 149*7c478bd9Sstevel@tonic-gate ct_event_get_evid(ev), 150*7c478bd9Sstevel@tonic-gate (flags & CTE_INFO) ? "info" : (flags & CTE_NEG) ? "neg" : "crit", 151*7c478bd9Sstevel@tonic-gate flags & CTE_ACK ? "yes" : "no", 152*7c478bd9Sstevel@tonic-gate types[type].name); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate * Display event details, if requested. 156*7c478bd9Sstevel@tonic-gate * (Since this is also needed by ctrun, the common 157*7c478bd9Sstevel@tonic-gate * contract_event_dump is found in libcontract.) 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate contract_event_dump(stdout, ev, verbose); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate ct_event_free(ev); 162*7c478bd9Sstevel@tonic-gate return (1); 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * get_type 167*7c478bd9Sstevel@tonic-gate * 168*7c478bd9Sstevel@tonic-gate * Given a contract type name, return an index into the 'types' array. 169*7c478bd9Sstevel@tonic-gate * Exits on failure. 170*7c478bd9Sstevel@tonic-gate */ 171*7c478bd9Sstevel@tonic-gate static int 172*7c478bd9Sstevel@tonic-gate get_type(const char *typestr) 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate int i; 175*7c478bd9Sstevel@tonic-gate for (i = 0; types[i].name; i++) 176*7c478bd9Sstevel@tonic-gate if (strcmp(types[i].name, typestr) == 0) 177*7c478bd9Sstevel@tonic-gate return (i); 178*7c478bd9Sstevel@tonic-gate uu_die(gettext("invalid contract type: %s\n"), typestr); 179*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* 183*7c478bd9Sstevel@tonic-gate * contract_type 184*7c478bd9Sstevel@tonic-gate * 185*7c478bd9Sstevel@tonic-gate * Given a contract id, return an index into the 'types' array. 186*7c478bd9Sstevel@tonic-gate * Returns -1 on failure. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate static int 189*7c478bd9Sstevel@tonic-gate contract_type(ctid_t id) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate ct_stathdl_t hdl; 192*7c478bd9Sstevel@tonic-gate int type, fd; 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * This could be faster (e.g. by reading the link itself), but 196*7c478bd9Sstevel@tonic-gate * this is the most straightforward implementation. 197*7c478bd9Sstevel@tonic-gate */ 198*7c478bd9Sstevel@tonic-gate if ((fd = contract_open(id, NULL, "status", O_RDONLY)) == -1) 199*7c478bd9Sstevel@tonic-gate return (-1); 200*7c478bd9Sstevel@tonic-gate if (errno = ct_status_read(fd, CTD_COMMON, &hdl)) { 201*7c478bd9Sstevel@tonic-gate (void) close(fd); 202*7c478bd9Sstevel@tonic-gate return (-1); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate type = get_type(ct_status_get_type(hdl)); 205*7c478bd9Sstevel@tonic-gate ct_status_free(hdl); 206*7c478bd9Sstevel@tonic-gate (void) close(fd); 207*7c478bd9Sstevel@tonic-gate return (type); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate /* 211*7c478bd9Sstevel@tonic-gate * ctid_compar 212*7c478bd9Sstevel@tonic-gate * 213*7c478bd9Sstevel@tonic-gate * A simple contract ID comparator. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate static int 216*7c478bd9Sstevel@tonic-gate ctid_compar(const void *a1, const void *a2) 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate ctid_t id1 = *(ctid_t *)a1; 219*7c478bd9Sstevel@tonic-gate ctid_t id2 = *(ctid_t *)a2; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate if (id1 > id2) 222*7c478bd9Sstevel@tonic-gate return (1); 223*7c478bd9Sstevel@tonic-gate if (id2 > id1) 224*7c478bd9Sstevel@tonic-gate return (-1); 225*7c478bd9Sstevel@tonic-gate return (0); 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate int 229*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 230*7c478bd9Sstevel@tonic-gate { 231*7c478bd9Sstevel@tonic-gate int opt_reliable = 0; 232*7c478bd9Sstevel@tonic-gate int opt_reset = 0; 233*7c478bd9Sstevel@tonic-gate int opt_verbose = 0; 234*7c478bd9Sstevel@tonic-gate int port_fd; 235*7c478bd9Sstevel@tonic-gate watched_fd_t *wfd; 236*7c478bd9Sstevel@tonic-gate int i, nfds, nids; 237*7c478bd9Sstevel@tonic-gate ctid_t *ids, last; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 240*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate (void) uu_setpname(argv[0]); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate while ((i = getopt(argc, argv, "rfv")) != EOF) { 245*7c478bd9Sstevel@tonic-gate switch (i) { 246*7c478bd9Sstevel@tonic-gate case 'r': 247*7c478bd9Sstevel@tonic-gate opt_reliable = 1; 248*7c478bd9Sstevel@tonic-gate break; 249*7c478bd9Sstevel@tonic-gate case 'f': 250*7c478bd9Sstevel@tonic-gate opt_reset = 1; 251*7c478bd9Sstevel@tonic-gate break; 252*7c478bd9Sstevel@tonic-gate case 'v': 253*7c478bd9Sstevel@tonic-gate opt_verbose = 1; 254*7c478bd9Sstevel@tonic-gate break; 255*7c478bd9Sstevel@tonic-gate default: 256*7c478bd9Sstevel@tonic-gate usage(); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate argc -= optind; 261*7c478bd9Sstevel@tonic-gate argv += optind; 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (argc <= 0) 264*7c478bd9Sstevel@tonic-gate usage(); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate wfd = calloc(argc, sizeof (struct pollfd)); 267*7c478bd9Sstevel@tonic-gate if (wfd == NULL) 268*7c478bd9Sstevel@tonic-gate uu_die("calloc"); 269*7c478bd9Sstevel@tonic-gate ids = calloc(argc, sizeof (ctid_t)); 270*7c478bd9Sstevel@tonic-gate if (ids == NULL) 271*7c478bd9Sstevel@tonic-gate uu_die("calloc"); 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* 274*7c478bd9Sstevel@tonic-gate * Scan our operands for contract ids and types. 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate nfds = 0; 277*7c478bd9Sstevel@tonic-gate nids = 0; 278*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 279*7c478bd9Sstevel@tonic-gate int id; 280*7c478bd9Sstevel@tonic-gate if (strchr(argv[i], '/') != NULL) 281*7c478bd9Sstevel@tonic-gate uu_die(gettext("invalid contract type: %s\n"), argv[i]); 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* 284*7c478bd9Sstevel@tonic-gate * If argument isn't a number between 0 and INT_MAX, 285*7c478bd9Sstevel@tonic-gate * treat it as a contract type. 286*7c478bd9Sstevel@tonic-gate */ 287*7c478bd9Sstevel@tonic-gate if (uu_strtoint(argv[i], &id, sizeof (id), 10, 1, INT_MAX)) { 288*7c478bd9Sstevel@tonic-gate int type; 289*7c478bd9Sstevel@tonic-gate wfd[nfds].wf_fd = 290*7c478bd9Sstevel@tonic-gate sopen(CTFS_ROOT "/%s/bundle", 291*7c478bd9Sstevel@tonic-gate gettext("invalid contract type: %s\n"), NULL, 292*7c478bd9Sstevel@tonic-gate argv[i]); 293*7c478bd9Sstevel@tonic-gate wfd[nfds].wf_type = type = get_type(argv[i]); 294*7c478bd9Sstevel@tonic-gate if (types[type].found) { 295*7c478bd9Sstevel@tonic-gate (void) close(wfd[nfds].wf_fd); 296*7c478bd9Sstevel@tonic-gate continue; 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate types[type].found = 1; 299*7c478bd9Sstevel@tonic-gate nfds++; 300*7c478bd9Sstevel@tonic-gate } else { 301*7c478bd9Sstevel@tonic-gate ids[nids++] = id; 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate /* 306*7c478bd9Sstevel@tonic-gate * Eliminate those contract ids which are represented by 307*7c478bd9Sstevel@tonic-gate * contract types, so we don't get duplicate event reports from 308*7c478bd9Sstevel@tonic-gate * them. 309*7c478bd9Sstevel@tonic-gate * 310*7c478bd9Sstevel@tonic-gate * Sorting the array first allows us to efficiently skip 311*7c478bd9Sstevel@tonic-gate * duplicate ids. We know that the array only contains 312*7c478bd9Sstevel@tonic-gate * integers [0, INT_MAX]. 313*7c478bd9Sstevel@tonic-gate */ 314*7c478bd9Sstevel@tonic-gate qsort(ids, nids, sizeof (ctid_t), ctid_compar); 315*7c478bd9Sstevel@tonic-gate last = -1; 316*7c478bd9Sstevel@tonic-gate for (i = 0; i < nids; i++) { 317*7c478bd9Sstevel@tonic-gate int type, fd; 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (ids[i] == last) 320*7c478bd9Sstevel@tonic-gate continue; 321*7c478bd9Sstevel@tonic-gate last = ids[i]; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate fd = sopen(CTFS_ROOT "/all/%d/events", 324*7c478bd9Sstevel@tonic-gate gettext("invalid contract id: %d\n"), 325*7c478bd9Sstevel@tonic-gate gettext("could not access contract id %d\n"), ids[i]); 326*7c478bd9Sstevel@tonic-gate if (fd == -1) 327*7c478bd9Sstevel@tonic-gate continue; 328*7c478bd9Sstevel@tonic-gate if ((type = contract_type(ids[i])) == -1) { 329*7c478bd9Sstevel@tonic-gate (void) close(fd); 330*7c478bd9Sstevel@tonic-gate uu_warn(gettext("could not access contract id %d\n"), 331*7c478bd9Sstevel@tonic-gate ids[i]); 332*7c478bd9Sstevel@tonic-gate continue; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate if (types[type].found) { 335*7c478bd9Sstevel@tonic-gate (void) close(fd); 336*7c478bd9Sstevel@tonic-gate continue; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate wfd[nfds].wf_fd = fd; 339*7c478bd9Sstevel@tonic-gate wfd[nfds].wf_type = type; 340*7c478bd9Sstevel@tonic-gate nfds++; 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate free(ids); 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate if (nfds == 0) 345*7c478bd9Sstevel@tonic-gate uu_die(gettext("no contracts to watch\n")); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Handle options. 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate if (opt_reliable) 351*7c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) 352*7c478bd9Sstevel@tonic-gate if (ioctl(wfd[i].wf_fd, CT_ERELIABLE, NULL) == -1) { 353*7c478bd9Sstevel@tonic-gate uu_warn("could not request reliable events"); 354*7c478bd9Sstevel@tonic-gate break; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate 357*7c478bd9Sstevel@tonic-gate if (opt_reset) 358*7c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) 359*7c478bd9Sstevel@tonic-gate (void) ioctl(wfd[i].wf_fd, CT_ERESET, NULL); 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate /* 363*7c478bd9Sstevel@tonic-gate * Allocate an event point, and associate all our endpoint file 364*7c478bd9Sstevel@tonic-gate * descriptors with it. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate if ((port_fd = port_create()) == -1) 367*7c478bd9Sstevel@tonic-gate goto port_error; 368*7c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) 369*7c478bd9Sstevel@tonic-gate if (port_associate(port_fd, PORT_SOURCE_FD, wfd[i].wf_fd, 370*7c478bd9Sstevel@tonic-gate POLLIN, &wfd[i]) == -1) 371*7c478bd9Sstevel@tonic-gate goto port_error; 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate /* 374*7c478bd9Sstevel@tonic-gate * Loop waiting for and displaying events. 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate hdr_event(); 377*7c478bd9Sstevel@tonic-gate for (;;) { 378*7c478bd9Sstevel@tonic-gate port_event_t pe; 379*7c478bd9Sstevel@tonic-gate watched_fd_t *w; 380*7c478bd9Sstevel@tonic-gate if (port_get(port_fd, &pe, NULL) == -1) { 381*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 382*7c478bd9Sstevel@tonic-gate continue; 383*7c478bd9Sstevel@tonic-gate goto port_error; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate w = pe.portev_user; 386*7c478bd9Sstevel@tonic-gate while (get_event(pe.portev_object, w->wf_type, opt_verbose)) 387*7c478bd9Sstevel@tonic-gate ; 388*7c478bd9Sstevel@tonic-gate if (port_associate(port_fd, PORT_SOURCE_FD, pe.portev_object, 389*7c478bd9Sstevel@tonic-gate POLLIN, pe.portev_user) == -1) 390*7c478bd9Sstevel@tonic-gate goto port_error; 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate port_error: 394*7c478bd9Sstevel@tonic-gate uu_die(gettext("error waiting for contract events")); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate return (1); /* placate cc */ 397*7c478bd9Sstevel@tonic-gate } 398