]>
git.proxmox.com Git - mirror_zfs-debian.git/blob - cmd/zed/zed_exec.c
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license from the top-level
9 * OPENSOLARIS.LICENSE or <http://opensource.org/licenses/CDDL-1.0>.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each file
14 * and include the License file from the top-level OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
24 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
38 #include "zed_strings.h"
40 #define ZEVENT_FILENO 3
43 * Create an environment string array for passing to execve() using the
44 * NAME=VALUE strings in container [zsp].
45 * Return a newly-allocated environment, or NULL on error.
48 _zed_exec_create_env(zed_strings_t
*zsp
)
59 num_ptrs
= zed_strings_count(zsp
) + 1;
60 buflen
= num_ptrs
* sizeof (char *);
61 for (q
= zed_strings_first(zsp
); q
; q
= zed_strings_next(zsp
))
62 buflen
+= strlen(q
) + 1;
64 buf
= calloc(1, buflen
);
69 p
= buf
+ (num_ptrs
* sizeof (char *));
71 for (q
= zed_strings_first(zsp
); q
; q
= zed_strings_next(zsp
)) {
79 assert(buf
+ buflen
== p
);
80 return ((char **) buf
);
84 * Fork a child process to handle event [eid]. The program [prog]
85 * in directory [dir] is executed with the envionment [env].
87 * The file descriptor [zfd] is the zevent_fd used to track the
88 * current cursor location within the zevent nvlist.
91 _zed_exec_fork_child(uint64_t eid
, const char *dir
, const char *prog
,
102 assert(prog
!= NULL
);
106 n
= snprintf(path
, sizeof (path
), "%s/%s", dir
, prog
);
107 if ((n
< 0) || (n
>= sizeof (path
))) {
108 zed_log_msg(LOG_WARNING
,
109 "Failed to fork \"%s\" for eid=%llu: %s",
110 prog
, eid
, strerror(ENAMETOOLONG
));
115 zed_log_msg(LOG_WARNING
,
116 "Failed to fork \"%s\" for eid=%llu: %s",
117 prog
, eid
, strerror(errno
));
119 } else if (pid
== 0) {
121 fd
= open("/dev/null", O_RDWR
);
122 (void) dup2(fd
, STDIN_FILENO
);
123 (void) dup2(fd
, STDOUT_FILENO
);
124 (void) dup2(fd
, STDERR_FILENO
);
125 (void) dup2(zfd
, ZEVENT_FILENO
);
126 zed_file_close_from(ZEVENT_FILENO
+ 1);
127 execle(path
, prog
, NULL
, env
);
130 zed_log_msg(LOG_INFO
, "Invoking \"%s\" eid=%llu pid=%d",
132 /* FIXME: Timeout rogue child processes with sigalarm? */
134 wpid
= waitpid(pid
, &status
, 0);
135 if (wpid
== (pid_t
) -1) {
138 zed_log_msg(LOG_WARNING
,
139 "Failed to wait for \"%s\" eid=%llu pid=%d",
141 } else if (WIFEXITED(status
)) {
142 zed_log_msg(LOG_INFO
,
143 "Finished \"%s\" eid=%llu pid=%d exit=%d",
144 prog
, eid
, pid
, WEXITSTATUS(status
));
145 } else if (WIFSIGNALED(status
)) {
146 zed_log_msg(LOG_INFO
,
147 "Finished \"%s\" eid=%llu pid=%d sig=%d/%s",
148 prog
, eid
, pid
, WTERMSIG(status
),
149 strsignal(WTERMSIG(status
)));
151 zed_log_msg(LOG_INFO
,
152 "Finished \"%s\" eid=%llu pid=%d status=0x%X",
153 prog
, eid
, (unsigned int) status
);
159 * Process the event [eid] by synchronously invoking all zedlets with a
160 * matching class prefix.
162 * Each executable in [zedlets] from the directory [dir] is matched against
163 * the event's [class], [subclass], and the "all" class (which matches
164 * all events). Every zedlet with a matching class prefix is invoked.
165 * The NAME=VALUE strings in [envs] will be passed to the zedlet as
166 * environment variables.
168 * The file descriptor [zfd] is the zevent_fd used to track the
169 * current cursor location within the zevent nvlist.
171 * Return 0 on success, -1 on error.
174 zed_exec_process(uint64_t eid
, const char *class, const char *subclass
,
175 const char *dir
, zed_strings_t
*zedlets
, zed_strings_t
*envs
, int zfd
)
177 const char *class_strings
[4];
178 const char *allclass
= "all";
184 if (!dir
|| !zedlets
|| !envs
|| zfd
< 0)
200 e
= _zed_exec_create_env(envs
);
202 for (z
= zed_strings_first(zedlets
); z
; z
= zed_strings_next(zedlets
)) {
203 for (csp
= class_strings
; *csp
; csp
++) {
205 if ((strncmp(z
, *csp
, n
) == 0) && !isalpha(z
[n
]))
206 _zed_exec_fork_child(eid
, dir
, z
, e
, zfd
);