17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*25e8c5aaSvikram * Common Development and Distribution License (the "License"). 6*25e8c5aaSvikram * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*25e8c5aaSvikram * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/types.h> 297c478bd9Sstevel@tonic-gate #include <sys/wait.h> 307c478bd9Sstevel@tonic-gate #include <sys/ctfs.h> 317c478bd9Sstevel@tonic-gate #include <sys/contract/process.h> 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <fcntl.h> 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <limits.h> 397c478bd9Sstevel@tonic-gate #include <libcontract.h> 407c478bd9Sstevel@tonic-gate #include <libcontract_priv.h> 417c478bd9Sstevel@tonic-gate #include <libuutil.h> 427c478bd9Sstevel@tonic-gate #include <poll.h> 437c478bd9Sstevel@tonic-gate #include <port.h> 447c478bd9Sstevel@tonic-gate #include <signal.h> 457c478bd9Sstevel@tonic-gate #include <sys/wait.h> 467c478bd9Sstevel@tonic-gate #include <stdarg.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include <locale.h> 497c478bd9Sstevel@tonic-gate #include <langinfo.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate struct { 527c478bd9Sstevel@tonic-gate const char *name; 537c478bd9Sstevel@tonic-gate int found; 547c478bd9Sstevel@tonic-gate } types[] = { 557c478bd9Sstevel@tonic-gate { "process", 0 }, 56*25e8c5aaSvikram { "device", 0 }, 577c478bd9Sstevel@tonic-gate { NULL } 587c478bd9Sstevel@tonic-gate }; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate typedef struct watched_fd { 617c478bd9Sstevel@tonic-gate int wf_fd; 627c478bd9Sstevel@tonic-gate int wf_type; 637c478bd9Sstevel@tonic-gate } watched_fd_t; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * usage 677c478bd9Sstevel@tonic-gate * 687c478bd9Sstevel@tonic-gate * Educate the user. 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate static void 717c478bd9Sstevel@tonic-gate usage(void) 727c478bd9Sstevel@tonic-gate { 737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 747c478bd9Sstevel@tonic-gate "Usage: %s [-f] [-r] [-v] contract-id | contract-type ...\n"), 757c478bd9Sstevel@tonic-gate uu_getpname()); 767c478bd9Sstevel@tonic-gate exit(UU_EXIT_USAGE); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate /* 807c478bd9Sstevel@tonic-gate * sopen 817c478bd9Sstevel@tonic-gate * 827c478bd9Sstevel@tonic-gate * Given a format string and a variable number of arguments, create a 837c478bd9Sstevel@tonic-gate * file name and open it. Warn with 'permerror' and return -1 if 847c478bd9Sstevel@tonic-gate * opening the file returned EPERM or EACCES, die with 'error' on all 857c478bd9Sstevel@tonic-gate * other error conditions. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate static int 887c478bd9Sstevel@tonic-gate sopen(const char *format, const char *error, const char *permerror, ...) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 917c478bd9Sstevel@tonic-gate int fd; 927c478bd9Sstevel@tonic-gate va_list varg; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate va_start(varg, permerror); 957c478bd9Sstevel@tonic-gate if (vsnprintf(path, PATH_MAX, format, varg) >= PATH_MAX) { 967c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 977c478bd9Sstevel@tonic-gate uu_vdie(error, varg); 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate if ((fd = open64(path, O_RDONLY | O_NONBLOCK)) == -1) { 1017c478bd9Sstevel@tonic-gate if (permerror && (errno == EPERM || errno == EACCES)) 1027c478bd9Sstevel@tonic-gate uu_vwarn(permerror, varg); 1037c478bd9Sstevel@tonic-gate else 1047c478bd9Sstevel@tonic-gate uu_vdie(error, varg); 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate va_end(varg); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate return (fd); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * hdr_event 1137c478bd9Sstevel@tonic-gate * 1147c478bd9Sstevel@tonic-gate * Display the output header. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate static void 1177c478bd9Sstevel@tonic-gate hdr_event(void) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate (void) printf("%-8s%-8s%-5s%-4s%-9s%s\n", 1207c478bd9Sstevel@tonic-gate "CTID", "EVID", "CRIT", "ACK", "CTTYPE", "SUMMARY"); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * get_event 1257c478bd9Sstevel@tonic-gate * 1267c478bd9Sstevel@tonic-gate * Read and display a contract event. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static int 1297c478bd9Sstevel@tonic-gate get_event(int fd, int type, int verbose) 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate ct_evthdl_t ev; 1327c478bd9Sstevel@tonic-gate uint_t flags; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate /* 1357c478bd9Sstevel@tonic-gate * Read a contract event. 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate if (errno = ct_event_read(fd, &ev)) { 1387c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 1397c478bd9Sstevel@tonic-gate return (0); 1407c478bd9Sstevel@tonic-gate uu_die(gettext("could not receive contract event")); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * Emit a one-line event summary. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate flags = ct_event_get_flags(ev); 1477c478bd9Sstevel@tonic-gate (void) printf("%-8ld%-8lld%-5s%-4s%-9s", 1487c478bd9Sstevel@tonic-gate ct_event_get_ctid(ev), 1497c478bd9Sstevel@tonic-gate ct_event_get_evid(ev), 1507c478bd9Sstevel@tonic-gate (flags & CTE_INFO) ? "info" : (flags & CTE_NEG) ? "neg" : "crit", 1517c478bd9Sstevel@tonic-gate flags & CTE_ACK ? "yes" : "no", 1527c478bd9Sstevel@tonic-gate types[type].name); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * Display event details, if requested. 1567c478bd9Sstevel@tonic-gate * (Since this is also needed by ctrun, the common 1577c478bd9Sstevel@tonic-gate * contract_event_dump is found in libcontract.) 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate contract_event_dump(stdout, ev, verbose); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate ct_event_free(ev); 1627c478bd9Sstevel@tonic-gate return (1); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * get_type 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * Given a contract type name, return an index into the 'types' array. 1697c478bd9Sstevel@tonic-gate * Exits on failure. 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate static int 1727c478bd9Sstevel@tonic-gate get_type(const char *typestr) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate int i; 1757c478bd9Sstevel@tonic-gate for (i = 0; types[i].name; i++) 1767c478bd9Sstevel@tonic-gate if (strcmp(types[i].name, typestr) == 0) 1777c478bd9Sstevel@tonic-gate return (i); 1787c478bd9Sstevel@tonic-gate uu_die(gettext("invalid contract type: %s\n"), typestr); 1797c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * contract_type 1847c478bd9Sstevel@tonic-gate * 1857c478bd9Sstevel@tonic-gate * Given a contract id, return an index into the 'types' array. 1867c478bd9Sstevel@tonic-gate * Returns -1 on failure. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate static int 1897c478bd9Sstevel@tonic-gate contract_type(ctid_t id) 1907c478bd9Sstevel@tonic-gate { 1917c478bd9Sstevel@tonic-gate ct_stathdl_t hdl; 1927c478bd9Sstevel@tonic-gate int type, fd; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * This could be faster (e.g. by reading the link itself), but 1967c478bd9Sstevel@tonic-gate * this is the most straightforward implementation. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate if ((fd = contract_open(id, NULL, "status", O_RDONLY)) == -1) 1997c478bd9Sstevel@tonic-gate return (-1); 2007c478bd9Sstevel@tonic-gate if (errno = ct_status_read(fd, CTD_COMMON, &hdl)) { 2017c478bd9Sstevel@tonic-gate (void) close(fd); 2027c478bd9Sstevel@tonic-gate return (-1); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate type = get_type(ct_status_get_type(hdl)); 2057c478bd9Sstevel@tonic-gate ct_status_free(hdl); 2067c478bd9Sstevel@tonic-gate (void) close(fd); 2077c478bd9Sstevel@tonic-gate return (type); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * ctid_compar 2127c478bd9Sstevel@tonic-gate * 2137c478bd9Sstevel@tonic-gate * A simple contract ID comparator. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate static int 2167c478bd9Sstevel@tonic-gate ctid_compar(const void *a1, const void *a2) 2177c478bd9Sstevel@tonic-gate { 2187c478bd9Sstevel@tonic-gate ctid_t id1 = *(ctid_t *)a1; 2197c478bd9Sstevel@tonic-gate ctid_t id2 = *(ctid_t *)a2; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (id1 > id2) 2227c478bd9Sstevel@tonic-gate return (1); 2237c478bd9Sstevel@tonic-gate if (id2 > id1) 2247c478bd9Sstevel@tonic-gate return (-1); 2257c478bd9Sstevel@tonic-gate return (0); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate int 2297c478bd9Sstevel@tonic-gate main(int argc, char **argv) 2307c478bd9Sstevel@tonic-gate { 2317c478bd9Sstevel@tonic-gate int opt_reliable = 0; 2327c478bd9Sstevel@tonic-gate int opt_reset = 0; 2337c478bd9Sstevel@tonic-gate int opt_verbose = 0; 2347c478bd9Sstevel@tonic-gate int port_fd; 2357c478bd9Sstevel@tonic-gate watched_fd_t *wfd; 2367c478bd9Sstevel@tonic-gate int i, nfds, nids; 2377c478bd9Sstevel@tonic-gate ctid_t *ids, last; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2407c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate (void) uu_setpname(argv[0]); 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate while ((i = getopt(argc, argv, "rfv")) != EOF) { 2457c478bd9Sstevel@tonic-gate switch (i) { 2467c478bd9Sstevel@tonic-gate case 'r': 2477c478bd9Sstevel@tonic-gate opt_reliable = 1; 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate case 'f': 2507c478bd9Sstevel@tonic-gate opt_reset = 1; 2517c478bd9Sstevel@tonic-gate break; 2527c478bd9Sstevel@tonic-gate case 'v': 2537c478bd9Sstevel@tonic-gate opt_verbose = 1; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate default: 2567c478bd9Sstevel@tonic-gate usage(); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate argc -= optind; 2617c478bd9Sstevel@tonic-gate argv += optind; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (argc <= 0) 2647c478bd9Sstevel@tonic-gate usage(); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate wfd = calloc(argc, sizeof (struct pollfd)); 2677c478bd9Sstevel@tonic-gate if (wfd == NULL) 2687c478bd9Sstevel@tonic-gate uu_die("calloc"); 2697c478bd9Sstevel@tonic-gate ids = calloc(argc, sizeof (ctid_t)); 2707c478bd9Sstevel@tonic-gate if (ids == NULL) 2717c478bd9Sstevel@tonic-gate uu_die("calloc"); 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * Scan our operands for contract ids and types. 2757c478bd9Sstevel@tonic-gate */ 2767c478bd9Sstevel@tonic-gate nfds = 0; 2777c478bd9Sstevel@tonic-gate nids = 0; 2787c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 2797c478bd9Sstevel@tonic-gate int id; 2807c478bd9Sstevel@tonic-gate if (strchr(argv[i], '/') != NULL) 2817c478bd9Sstevel@tonic-gate uu_die(gettext("invalid contract type: %s\n"), argv[i]); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * If argument isn't a number between 0 and INT_MAX, 2857c478bd9Sstevel@tonic-gate * treat it as a contract type. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate if (uu_strtoint(argv[i], &id, sizeof (id), 10, 1, INT_MAX)) { 2887c478bd9Sstevel@tonic-gate int type; 2897c478bd9Sstevel@tonic-gate wfd[nfds].wf_fd = 2907c478bd9Sstevel@tonic-gate sopen(CTFS_ROOT "/%s/bundle", 2917c478bd9Sstevel@tonic-gate gettext("invalid contract type: %s\n"), NULL, 2927c478bd9Sstevel@tonic-gate argv[i]); 2937c478bd9Sstevel@tonic-gate wfd[nfds].wf_type = type = get_type(argv[i]); 2947c478bd9Sstevel@tonic-gate if (types[type].found) { 2957c478bd9Sstevel@tonic-gate (void) close(wfd[nfds].wf_fd); 2967c478bd9Sstevel@tonic-gate continue; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate types[type].found = 1; 2997c478bd9Sstevel@tonic-gate nfds++; 3007c478bd9Sstevel@tonic-gate } else { 3017c478bd9Sstevel@tonic-gate ids[nids++] = id; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Eliminate those contract ids which are represented by 3077c478bd9Sstevel@tonic-gate * contract types, so we don't get duplicate event reports from 3087c478bd9Sstevel@tonic-gate * them. 3097c478bd9Sstevel@tonic-gate * 3107c478bd9Sstevel@tonic-gate * Sorting the array first allows us to efficiently skip 3117c478bd9Sstevel@tonic-gate * duplicate ids. We know that the array only contains 3127c478bd9Sstevel@tonic-gate * integers [0, INT_MAX]. 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate qsort(ids, nids, sizeof (ctid_t), ctid_compar); 3157c478bd9Sstevel@tonic-gate last = -1; 3167c478bd9Sstevel@tonic-gate for (i = 0; i < nids; i++) { 3177c478bd9Sstevel@tonic-gate int type, fd; 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate if (ids[i] == last) 3207c478bd9Sstevel@tonic-gate continue; 3217c478bd9Sstevel@tonic-gate last = ids[i]; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate fd = sopen(CTFS_ROOT "/all/%d/events", 3247c478bd9Sstevel@tonic-gate gettext("invalid contract id: %d\n"), 3257c478bd9Sstevel@tonic-gate gettext("could not access contract id %d\n"), ids[i]); 3267c478bd9Sstevel@tonic-gate if (fd == -1) 3277c478bd9Sstevel@tonic-gate continue; 3287c478bd9Sstevel@tonic-gate if ((type = contract_type(ids[i])) == -1) { 3297c478bd9Sstevel@tonic-gate (void) close(fd); 3307c478bd9Sstevel@tonic-gate uu_warn(gettext("could not access contract id %d\n"), 3317c478bd9Sstevel@tonic-gate ids[i]); 3327c478bd9Sstevel@tonic-gate continue; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate if (types[type].found) { 3357c478bd9Sstevel@tonic-gate (void) close(fd); 3367c478bd9Sstevel@tonic-gate continue; 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate wfd[nfds].wf_fd = fd; 3397c478bd9Sstevel@tonic-gate wfd[nfds].wf_type = type; 3407c478bd9Sstevel@tonic-gate nfds++; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate free(ids); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (nfds == 0) 3457c478bd9Sstevel@tonic-gate uu_die(gettext("no contracts to watch\n")); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * Handle options. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate if (opt_reliable) 3517c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) 3527c478bd9Sstevel@tonic-gate if (ioctl(wfd[i].wf_fd, CT_ERELIABLE, NULL) == -1) { 3537c478bd9Sstevel@tonic-gate uu_warn("could not request reliable events"); 3547c478bd9Sstevel@tonic-gate break; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (opt_reset) 3587c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) 3597c478bd9Sstevel@tonic-gate (void) ioctl(wfd[i].wf_fd, CT_ERESET, NULL); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * Allocate an event point, and associate all our endpoint file 3647c478bd9Sstevel@tonic-gate * descriptors with it. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate if ((port_fd = port_create()) == -1) 3677c478bd9Sstevel@tonic-gate goto port_error; 3687c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) 3697c478bd9Sstevel@tonic-gate if (port_associate(port_fd, PORT_SOURCE_FD, wfd[i].wf_fd, 3707c478bd9Sstevel@tonic-gate POLLIN, &wfd[i]) == -1) 3717c478bd9Sstevel@tonic-gate goto port_error; 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * Loop waiting for and displaying events. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate hdr_event(); 3777c478bd9Sstevel@tonic-gate for (;;) { 3787c478bd9Sstevel@tonic-gate port_event_t pe; 3797c478bd9Sstevel@tonic-gate watched_fd_t *w; 3807c478bd9Sstevel@tonic-gate if (port_get(port_fd, &pe, NULL) == -1) { 3817c478bd9Sstevel@tonic-gate if (errno == EINTR) 3827c478bd9Sstevel@tonic-gate continue; 3837c478bd9Sstevel@tonic-gate goto port_error; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate w = pe.portev_user; 3867c478bd9Sstevel@tonic-gate while (get_event(pe.portev_object, w->wf_type, opt_verbose)) 3877c478bd9Sstevel@tonic-gate ; 3887c478bd9Sstevel@tonic-gate if (port_associate(port_fd, PORT_SOURCE_FD, pe.portev_object, 3897c478bd9Sstevel@tonic-gate POLLIN, pe.portev_user) == -1) 3907c478bd9Sstevel@tonic-gate goto port_error; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate port_error: 3947c478bd9Sstevel@tonic-gate uu_die(gettext("error waiting for contract events")); 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate return (1); /* placate cc */ 3977c478bd9Sstevel@tonic-gate } 398