1*0c06d385Sjwpoduska /*
2*0c06d385Sjwpoduska  * CDDL HEADER START
3*0c06d385Sjwpoduska  *
4*0c06d385Sjwpoduska  * The contents of this file are subject to the terms of the
5*0c06d385Sjwpoduska  * Common Development and Distribution License, Version 1.0 only
6*0c06d385Sjwpoduska  * (the "License").  You may not use this file except in compliance
7*0c06d385Sjwpoduska  * with the License.
8*0c06d385Sjwpoduska  *
9*0c06d385Sjwpoduska  * You can obtain a copy of the license at http://smartos.org/CDDL
10*0c06d385Sjwpoduska  *
11*0c06d385Sjwpoduska  * See the License for the specific language governing permissions
12*0c06d385Sjwpoduska  * and limitations under the License.
13*0c06d385Sjwpoduska  *
14*0c06d385Sjwpoduska  * When distributing Covered Code, include this CDDL HEADER in each
15*0c06d385Sjwpoduska  * file.
16*0c06d385Sjwpoduska  *
17*0c06d385Sjwpoduska  * If applicable, add the following below this CDDL HEADER, with the
18*0c06d385Sjwpoduska  * fields enclosed by brackets "[]" replaced with your own identifying
19*0c06d385Sjwpoduska  * information: Portions Copyright [yyyy] [name of copyright owner]
20*0c06d385Sjwpoduska  *
21*0c06d385Sjwpoduska  * CDDL HEADER END
22*0c06d385Sjwpoduska  *
23*0c06d385Sjwpoduska  * Copyright 2020 Joyent, Inc.
24*0c06d385Sjwpoduska  *
25*0c06d385Sjwpoduska  */
26*0c06d385Sjwpoduska 
27*0c06d385Sjwpoduska #include <err.h>
28*0c06d385Sjwpoduska #include <errno.h>
29*0c06d385Sjwpoduska #include <stdio.h>
30*0c06d385Sjwpoduska #include <stdlib.h>
31*0c06d385Sjwpoduska #include <string.h>
32*0c06d385Sjwpoduska #include <unistd.h>
33*0c06d385Sjwpoduska #include <sys/debug.h>
34*0c06d385Sjwpoduska #include <sys/sysmacros.h>
35*0c06d385Sjwpoduska #include <sys/types.h>
36*0c06d385Sjwpoduska #include <libsysevent.h>
37*0c06d385Sjwpoduska #include <sys/sysevent/eventdefs.h>
38*0c06d385Sjwpoduska 
39*0c06d385Sjwpoduska FILE *out;
40*0c06d385Sjwpoduska 
41*0c06d385Sjwpoduska static void
42*0c06d385Sjwpoduska process_event(sysevent_t *ev)
43*0c06d385Sjwpoduska {
44*0c06d385Sjwpoduska 	char *class = NULL;
45*0c06d385Sjwpoduska 	char *subclass = NULL;
46*0c06d385Sjwpoduska 
47*0c06d385Sjwpoduska 	/* get sysevent metadata and add to the nvlist */
48*0c06d385Sjwpoduska 	class = sysevent_get_class_name(ev);
49*0c06d385Sjwpoduska 	subclass = sysevent_get_subclass_name(ev);
50*0c06d385Sjwpoduska 
51*0c06d385Sjwpoduska 	if (class == NULL || subclass == NULL)
52*0c06d385Sjwpoduska 		errx(EXIT_FAILURE, "failed to retrieve sysevent metadata");
53*0c06d385Sjwpoduska 
54*0c06d385Sjwpoduska 	VERIFY0(strcmp(class, EC_ZFS));
55*0c06d385Sjwpoduska 	VERIFY0(strcmp(subclass, ESC_ZFS_RESILVER_START));
56*0c06d385Sjwpoduska 
57*0c06d385Sjwpoduska 	flockfile(out);
58*0c06d385Sjwpoduska 	(void) fprintf(out, "Received %s.%s event\n", class, subclass);
59*0c06d385Sjwpoduska 	(void) fflush(out);
60*0c06d385Sjwpoduska 	funlockfile(out);
61*0c06d385Sjwpoduska }
62*0c06d385Sjwpoduska 
63*0c06d385Sjwpoduska static void
64*0c06d385Sjwpoduska child_fatal(int fd, const char *msg, ...)
65*0c06d385Sjwpoduska {
66*0c06d385Sjwpoduska 	va_list ap;
67*0c06d385Sjwpoduska 	int fail = EXIT_FAILURE;
68*0c06d385Sjwpoduska 
69*0c06d385Sjwpoduska 	va_start(ap, msg);
70*0c06d385Sjwpoduska 	(void) vfprintf(stderr, msg, ap);
71*0c06d385Sjwpoduska 	va_end(ap);
72*0c06d385Sjwpoduska 	(void) fputc('\n', stderr);
73*0c06d385Sjwpoduska 
74*0c06d385Sjwpoduska 	(void) write(fd, &fail, sizeof (fail));
75*0c06d385Sjwpoduska 	(void) close(fd);
76*0c06d385Sjwpoduska 	exit(EXIT_FAILURE);
77*0c06d385Sjwpoduska }
78*0c06d385Sjwpoduska 
79*0c06d385Sjwpoduska static void
80*0c06d385Sjwpoduska do_child(int fd)
81*0c06d385Sjwpoduska {
82*0c06d385Sjwpoduska 	const char *subclasses[] = {
83*0c06d385Sjwpoduska 		ESC_ZFS_RESILVER_START,
84*0c06d385Sjwpoduska 	};
85*0c06d385Sjwpoduska 	sysevent_handle_t *handle;
86*0c06d385Sjwpoduska 	int ret = 0;
87*0c06d385Sjwpoduska 
88*0c06d385Sjwpoduska 	if ((handle = sysevent_bind_handle(process_event)) == NULL) {
89*0c06d385Sjwpoduska 		child_fatal(fd, "sysevent_bind_handle() failed: %s",
90*0c06d385Sjwpoduska 		    strerror(errno));
91*0c06d385Sjwpoduska 	}
92*0c06d385Sjwpoduska 
93*0c06d385Sjwpoduska 	if (sysevent_subscribe_event(handle, EC_ZFS, subclasses,
94*0c06d385Sjwpoduska 	    ARRAY_SIZE(subclasses)) != 0) {
95*0c06d385Sjwpoduska 		child_fatal(fd, "failed to subscribe to sysevents: %s",
96*0c06d385Sjwpoduska 		    strerror(errno));
97*0c06d385Sjwpoduska 	}
98*0c06d385Sjwpoduska 
99*0c06d385Sjwpoduska 	(void) write(fd, &ret, sizeof (ret));
100*0c06d385Sjwpoduska 	(void) close(fd);
101*0c06d385Sjwpoduska 
102*0c06d385Sjwpoduska 	/* leave stderr open so any errors get captured by test harness */
103*0c06d385Sjwpoduska 	(void) fclose(stdin);
104*0c06d385Sjwpoduska 	(void) fclose(stdout);
105*0c06d385Sjwpoduska 
106*0c06d385Sjwpoduska 	for (;;)
107*0c06d385Sjwpoduska 		(void) pause();
108*0c06d385Sjwpoduska }
109*0c06d385Sjwpoduska 
110*0c06d385Sjwpoduska int
111*0c06d385Sjwpoduska main(int argc, char **argv)
112*0c06d385Sjwpoduska {
113*0c06d385Sjwpoduska 	pid_t child;
114*0c06d385Sjwpoduska 	int fds[2];
115*0c06d385Sjwpoduska 	int ret = 0;
116*0c06d385Sjwpoduska 
117*0c06d385Sjwpoduska 	if (argc < 2) {
118*0c06d385Sjwpoduska 		(void) fprintf(stderr, "Usage: %s outfile\n", argv[0]);
119*0c06d385Sjwpoduska 		exit(EXIT_FAILURE);
120*0c06d385Sjwpoduska 	}
121*0c06d385Sjwpoduska 
122*0c06d385Sjwpoduska 	if ((out = fopen(argv[1], "w")) == NULL)
123*0c06d385Sjwpoduska 		err(EXIT_FAILURE, "unable to open %s", argv[1]);
124*0c06d385Sjwpoduska 
125*0c06d385Sjwpoduska 	VERIFY0(pipe(fds));
126*0c06d385Sjwpoduska 
127*0c06d385Sjwpoduska 	switch (child = fork()) {
128*0c06d385Sjwpoduska 	case -1:
129*0c06d385Sjwpoduska 		err(EXIT_FAILURE, "unable to fork");
130*0c06d385Sjwpoduska 	case 0:
131*0c06d385Sjwpoduska 		do_child(fds[1]);
132*0c06d385Sjwpoduska 		break;
133*0c06d385Sjwpoduska 	default:
134*0c06d385Sjwpoduska 		break;
135*0c06d385Sjwpoduska 	}
136*0c06d385Sjwpoduska 
137*0c06d385Sjwpoduska 	(void) close(fds[1]);
138*0c06d385Sjwpoduska 
139*0c06d385Sjwpoduska 	if (read(fds[0], &ret, sizeof (ret)) < 0)
140*0c06d385Sjwpoduska 		err(EXIT_FAILURE, "failure waiting on child");
141*0c06d385Sjwpoduska 
142*0c06d385Sjwpoduska 	if (ret != 0)
143*0c06d385Sjwpoduska 		return (ret);
144*0c06d385Sjwpoduska 
145*0c06d385Sjwpoduska 	(void) close(fds[0]);
146*0c06d385Sjwpoduska 	(void) printf("%d\n", child);
147*0c06d385Sjwpoduska 	return (0);
148*0c06d385Sjwpoduska }
149