Print this page
4450 pointless condfree in libfmnotify
Reviewed by: Dan McDonald <danmcd@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/fm/libfmnotify/common/libfmnotify.c
+++ new/usr/src/lib/fm/libfmnotify/common/libfmnotify.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25 #include <alloca.h>
26 26
27 27 #include "libfmnotify.h"
28 28
29 29 /*ARGSUSED*/
30 30 void
31 31 nd_cleanup(nd_hdl_t *nhdl)
32 32 {
33 33 nd_debug(nhdl, "Cleaning up ...");
34 34 if (nhdl->nh_evhdl)
35 35 (void) fmev_shdl_fini(nhdl->nh_evhdl);
36 36
37 37 if (nhdl->nh_msghdl)
38 38 fmd_msg_fini(nhdl->nh_msghdl);
39 39
40 40 nhdl->nh_keep_running = B_FALSE;
41 41 (void) fclose(nhdl->nh_log_fd);
42 42 }
43 43
44 44 static void
45 45 get_timestamp(char *buf, size_t bufsize)
46 46 {
47 47 time_t utc_time;
48 48 struct tm *p_tm;
49 49
50 50 (void) time(&utc_time);
51 51 p_tm = localtime(&utc_time);
52 52
53 53 (void) strftime(buf, bufsize, "%b %d %H:%M:%S", p_tm);
54 54 }
55 55
56 56 /* PRINTFLIKE2 */
57 57 void
58 58 nd_debug(nd_hdl_t *nhdl, const char *format, ...)
59 59 {
60 60 char timestamp[64];
61 61 va_list ap;
62 62
63 63 if (nhdl->nh_debug) {
64 64 get_timestamp(timestamp, sizeof (timestamp));
65 65 (void) fprintf(nhdl->nh_log_fd, "[ %s ", timestamp);
66 66 va_start(ap, format);
67 67 (void) vfprintf(nhdl->nh_log_fd, format, ap);
68 68 va_end(ap);
69 69 (void) fprintf(nhdl->nh_log_fd, " ]\n");
70 70 }
71 71 (void) fflush(nhdl->nh_log_fd);
72 72 }
73 73
74 74 void
75 75 nd_dump_nvlist(nd_hdl_t *nhdl, nvlist_t *nvl)
76 76 {
77 77 if (nhdl->nh_debug)
78 78 nvlist_print(nhdl->nh_log_fd, nvl);
79 79 }
80 80
81 81 /* PRINTFLIKE2 */
82 82 void
83 83 nd_error(nd_hdl_t *nhdl, const char *format, ...)
84 84 {
85 85 char timestamp[64];
86 86 va_list ap;
87 87
88 88 get_timestamp(timestamp, sizeof (timestamp));
89 89 (void) fprintf(nhdl->nh_log_fd, "[ %s ", timestamp);
90 90 va_start(ap, format);
91 91 (void) vfprintf(nhdl->nh_log_fd, format, ap);
92 92 va_end(ap);
93 93 (void) fprintf(nhdl->nh_log_fd, " ]\n");
94 94 (void) fflush(nhdl->nh_log_fd);
95 95 }
96 96
97 97 /* PRINTFLIKE2 */
98 98 void
99 99 nd_abort(nd_hdl_t *nhdl, const char *format, ...)
100 100 {
101 101 char timestamp[64];
102 102 va_list ap;
103 103
104 104 get_timestamp(timestamp, sizeof (timestamp));
105 105 (void) fprintf(nhdl->nh_log_fd, "[ %s ", timestamp);
106 106 va_start(ap, format);
107 107 (void) vfprintf(nhdl->nh_log_fd, format, ap);
108 108 va_end(ap);
109 109 (void) fprintf(nhdl->nh_log_fd, " ]\n");
110 110 (void) fflush(nhdl->nh_log_fd);
111 111 nd_cleanup(nhdl);
112 112 }
113 113
114 114 void
115 115 nd_daemonize(nd_hdl_t *nhdl)
116 116 {
117 117 pid_t pid;
118 118
119 119 if ((pid = fork()) < 0)
120 120 nd_abort(nhdl, "Failed to fork child (%s)", strerror(errno));
121 121 else if (pid > 0)
122 122 exit(0);
123 123
124 124 (void) setsid();
125 125 (void) close(0);
126 126 (void) close(1);
127 127 /*
128 128 * We leave stderr open so we can write debug/err messages to the SMF
129 129 * service log
130 130 */
131 131 nhdl->nh_is_daemon = B_TRUE;
132 132 }
133 133
134 134 /*
135 135 * This function returns a pointer to the specified SMF property group for the
136 136 * specified SMF service. The caller is responsible for freeing the property
137 137 * group. On failure, the function returns NULL.
138 138 */
139 139 static scf_propertygroup_t *
140 140 nd_get_pg(nd_hdl_t *nhdl, scf_handle_t *handle, const char *svcname,
141 141 const char *pgname)
142 142 {
143 143 scf_scope_t *sc = NULL;
144 144 scf_service_t *svc = NULL;
145 145 scf_propertygroup_t *pg = NULL, *ret = NULL;
146 146
147 147 sc = scf_scope_create(handle);
148 148 svc = scf_service_create(handle);
149 149 pg = scf_pg_create(handle);
150 150
151 151 if (sc == NULL || svc == NULL || pg == NULL) {
152 152 nd_error(nhdl, "Failed to allocate libscf structures");
153 153 scf_pg_destroy(pg);
154 154 goto get_pg_done;
155 155 }
156 156
157 157 if (scf_handle_bind(handle) != -1 &&
158 158 scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, sc) != -1 &&
159 159 scf_scope_get_service(sc, svcname, svc) != -1 &&
160 160 scf_service_get_pg(svc, pgname, pg) != -1)
161 161 ret = pg;
162 162 else
163 163 scf_pg_destroy(pg);
164 164
165 165 get_pg_done:
166 166 scf_service_destroy(svc);
167 167 scf_scope_destroy(sc);
168 168
169 169 return (ret);
170 170 }
171 171
172 172 int
173 173 nd_get_astring_prop(nd_hdl_t *nhdl, const char *svcname, const char *pgname,
174 174 const char *propname, char **val)
175 175 {
176 176 scf_handle_t *handle = NULL;
177 177 scf_propertygroup_t *pg;
178 178 scf_property_t *prop = NULL;
179 179 scf_value_t *value = NULL;
180 180 char strval[255];
181 181 int ret = -1;
182 182
183 183 if ((handle = scf_handle_create(SCF_VERSION)) == NULL)
184 184 return (ret);
185 185
186 186 if ((pg = nd_get_pg(nhdl, handle, svcname, pgname)) == NULL) {
187 187 nd_error(nhdl, "Failed to read retrieve %s "
188 188 "property group for %s", pgname, svcname);
189 189 goto astring_done;
190 190 }
191 191 prop = scf_property_create(handle);
192 192 value = scf_value_create(handle);
193 193 if (prop == NULL || value == NULL) {
194 194 nd_error(nhdl, "Failed to allocate SMF structures");
195 195 goto astring_done;
196 196 }
197 197 if (scf_pg_get_property(pg, propname, prop) == -1 ||
198 198 scf_property_get_value(prop, value) == -1 ||
199 199 scf_value_get_astring(value, strval, 255) == -1) {
200 200 nd_error(nhdl, "Failed to retrieve %s prop (%s)", propname,
201 201 scf_strerror(scf_error()));
202 202 goto astring_done;
203 203 }
204 204 *val = strdup(strval);
205 205 ret = 0;
206 206
207 207 astring_done:
208 208 scf_value_destroy(value);
209 209 scf_property_destroy(prop);
210 210 scf_pg_destroy(pg);
211 211 scf_handle_destroy(handle);
212 212
213 213 return (ret);
214 214 }
215 215
216 216 int
217 217 nd_get_boolean_prop(nd_hdl_t *nhdl, const char *svcname, const char *pgname,
218 218 const char *propname, uint8_t *val)
219 219 {
220 220 scf_handle_t *handle = NULL;
221 221 scf_propertygroup_t *pg;
222 222 scf_property_t *prop = NULL;
223 223 scf_value_t *value = NULL;
224 224 int ret = -1;
225 225
226 226 if ((handle = scf_handle_create(SCF_VERSION)) == NULL)
227 227 return (ret);
228 228
229 229 if ((pg = nd_get_pg(nhdl, handle, svcname, pgname)) == NULL) {
230 230 nd_error(nhdl, "Failed to read retrieve %s "
231 231 "property group for %s", pgname, svcname);
232 232 goto bool_done;
233 233 }
234 234 prop = scf_property_create(handle);
235 235 value = scf_value_create(handle);
236 236 if (prop == NULL || value == NULL) {
237 237 nd_error(nhdl, "Failed to allocate SMF structures");
238 238 goto bool_done;
239 239 }
240 240 if (scf_pg_get_property(pg, propname, prop) == -1 ||
241 241 scf_property_get_value(prop, value) == -1 ||
242 242 scf_value_get_boolean(value, val) == -1) {
243 243 nd_error(nhdl, "Failed to retrieve %s prop (%s)", propname,
244 244 scf_strerror(scf_error()));
245 245 goto bool_done;
246 246 }
247 247 ret = 0;
248 248
249 249 bool_done:
250 250 scf_value_destroy(value);
251 251 scf_property_destroy(prop);
252 252 scf_pg_destroy(pg);
253 253 scf_handle_destroy(handle);
254 254
255 255 return (ret);
256 256 }
257 257
258 258 char *
259 259 nd_get_event_fmri(nd_hdl_t *nhdl, fmev_t ev)
260 260 {
261 261 nvlist_t *ev_nvl, *attr_nvl;
262 262 char *svcname;
263 263
264 264 if ((ev_nvl = fmev_attr_list(ev)) == NULL) {
265 265 nd_error(nhdl, "Failed to lookup event attr nvlist");
266 266 return (NULL);
267 267 }
268 268 if (nvlist_lookup_nvlist(ev_nvl, "attr", &attr_nvl) ||
269 269 nvlist_lookup_string(attr_nvl, "svc-string", &svcname)) {
270 270 nd_error(nhdl, "Malformed event 0x%p", (void *)ev_nvl);
271 271 return (NULL);
272 272 }
273 273
274 274 return (strdup((const char *)svcname));
275 275 }
276 276
277 277 int
278 278 nd_get_notify_prefs(nd_hdl_t *nhdl, const char *mech, fmev_t ev,
279 279 nvlist_t ***pref_nvl, uint_t *nprefs)
280 280 {
281 281 nvlist_t *ev_nvl, *top_nvl, **np_nvlarr, *mech_nvl;
282 282 int ret = 1;
283 283 uint_t nelem;
284 284
285 285 if ((ev_nvl = fmev_attr_list(ev)) == NULL) {
286 286 nd_error(nhdl, "Failed to lookup event attr nvlist");
287 287 return (-1);
288 288 }
289 289
290 290 if ((ret = smf_notify_get_params(&top_nvl, ev_nvl)) != SCF_SUCCESS) {
291 291 ret = scf_error();
292 292 if (ret == SCF_ERROR_NOT_FOUND) {
293 293 nd_debug(nhdl, "No notification preferences specified "
294 294 "for this event");
295 295 goto pref_done;
296 296 } else {
297 297 nd_error(nhdl, "Error looking up notification "
298 298 "preferences (%s)", scf_strerror(ret));
299 299 nd_dump_nvlist(nhdl, top_nvl);
300 300 goto pref_done;
301 301 }
302 302 }
303 303
304 304 if (nvlist_lookup_nvlist_array(top_nvl, SCF_NOTIFY_PARAMS, &np_nvlarr,
305 305 &nelem) != 0) {
306 306 nd_error(nhdl, "Malformed nvlist");
307 307 nd_dump_nvlist(nhdl, top_nvl);
308 308 ret = 1;
309 309 goto pref_done;
310 310 }
311 311 *pref_nvl = malloc(nelem * sizeof (nvlist_t *));
312 312 *nprefs = 0;
313 313
314 314 for (int i = 0; i < nelem; i++) {
315 315 if (nvlist_lookup_nvlist(np_nvlarr[i], mech, &mech_nvl) == 0) {
316 316 (void) nvlist_dup(mech_nvl, *pref_nvl + *nprefs, 0);
317 317 ++*nprefs;
318 318 }
319 319 }
320 320
321 321 if (*nprefs == 0) {
322 322 nd_debug(nhdl, "No %s notification preferences specified",
323 323 mech);
324 324 free(*pref_nvl);
325 325 ret = SCF_ERROR_NOT_FOUND;
326 326 goto pref_done;
327 327 }
328 328 ret = 0;
329 329 pref_done:
330 330 nvlist_free(top_nvl);
331 331 return (ret);
332 332 }
333 333
334 334 static int
335 335 nd_seq_search(char *key, char **list, uint_t nelem)
336 336 {
337 337 for (int i = 0; i < nelem; i++)
338 338 if (strcmp(key, list[i]) == 0)
339 339 return (1);
340 340 return (0);
341 341 }
342 342
343 343 /*
344 344 * This function takes a single string list and splits it into
345 345 * an string array (analogous to PERL split)
346 346 *
347 347 * The caller is responsible for freeing the array.
348 348 */
349 349 int
350 350 nd_split_list(nd_hdl_t *nhdl, char *list, char *delim, char ***arr,
351 351 uint_t *nelem)
352 352 {
353 353 char *item, *tmpstr;
354 354 int i = 1, size = 1;
355 355
356 356 tmpstr = strdup(list);
357 357 item = strtok(tmpstr, delim);
358 358 while (item && strtok(NULL, delim) != NULL)
359 359 size++;
360 360 free(tmpstr);
361 361
362 362 if ((*arr = calloc(size, sizeof (char *))) == NULL) {
363 363 nd_error(nhdl, "Error allocating memory (%s)", strerror(errno));
364 364 return (-1);
365 365 }
366 366 if (size == 1)
367 367 (*arr)[0] = strdup(list);
368 368 else {
369 369 tmpstr = strdup(list);
370 370 item = strtok(tmpstr, delim);
371 371 (*arr)[0] = strdup(item);
372 372 while ((item = strtok(NULL, delim)) != NULL)
373 373 (*arr)[i++] = strdup(item);
374 374 free(tmpstr);
375 375 }
376 376 *nelem = size;
377 377 return (0);
378 378 }
379 379
380 380 /*
381 381 * This function merges two string arrays into a single array, removing any
382 382 * duplicates
383 383 *
384 384 * The caller is responsible for freeing the merged array.
385 385 */
386 386 int
387 387 nd_merge_strarray(nd_hdl_t *nhdl, char **arr1, uint_t n1, char **arr2,
388 388 uint_t n2, char ***buf)
389 389 {
390 390 char **tmparr;
391 391 int uniq = -1;
392 392
393 393 tmparr = alloca((n1 + n2) * sizeof (char *));
394 394 bzero(tmparr, (n1 + n2) * sizeof (char *));
395 395
396 396 while (++uniq < n1)
397 397 tmparr[uniq] = strdup(arr1[uniq]);
398 398
399 399 for (int j = 0; j < n2; j++)
400 400 if (!nd_seq_search(arr2[j], tmparr, uniq))
401 401 tmparr[uniq++] = strdup(arr2[j]);
402 402
403 403 if ((*buf = calloc(uniq, sizeof (char *))) == NULL) {
404 404 nd_error(nhdl, "Error allocating memory (%s)", strerror(errno));
405 405 for (int j = 0; j < uniq; j++) {
406 406 if (tmparr[j])
407 407 free(tmparr[j]);
408 408 }
409 409 return (-1);
410 410 }
411 411
412 412 bcopy(tmparr, *buf, uniq * sizeof (char *));
413 413 return (uniq);
414 414 }
415 415
416 416 void
417 417 nd_free_strarray(char **arr, uint_t arrsz)
418 418 {
419 419 for (uint_t i = 0; i < arrsz; i++)
420 420 free(arr[i]);
421 421 free(arr);
422 422 }
423 423
424 424 /*
425 425 * This function joins all the strings in a string array into a single string
426 426 * Each element will be delimited by a comma
427 427 *
428 428 * The caller is responsible for freeing the joined string.
429 429 */
430 430 int
431 431 nd_join_strarray(nd_hdl_t *nhdl, char **arr, uint_t arrsz, char **buf)
432 432 {
433 433 uint_t len = 0;
434 434 char *jbuf;
435 435 int i;
436 436
437 437 /*
438 438 * First, figure out how much space we need to allocate to store the
439 439 * joined string.
440 440 */
441 441 for (i = 0; i < arrsz; i++)
442 442 len += strlen(arr[i]) + 1;
443 443
444 444 if ((jbuf = calloc(len, sizeof (char))) == NULL) {
445 445 nd_error(nhdl, "Error allocating memory (%s)", strerror(errno));
446 446 return (-1);
447 447 }
448 448
449 449 (void) snprintf(jbuf, len, "%s", arr[0]);
450 450 for (i = 1; i < arrsz; i++) {
451 451 (void) strlcat(jbuf, ",", len);
452 452 (void) strlcat(jbuf, arr[i], len);
453 453 }
454 454
455 455 *buf = jbuf;
456 456 return (0);
457 457 }
458 458
459 459 void
460 460 nd_free_nvlarray(nvlist_t **arr, uint_t arrsz)
461 461 {
462 462 for (uint_t i = 0; i < arrsz; i++)
463 463 nvlist_free(arr[i]);
464 464 free(arr);
465 465 }
466 466
467 467 /*
468 468 * This function takes a dictionary name and event class and then uses
469 469 * libdiagcode to compute the MSG ID. We need this for looking up messages
470 470 * for the committed ireport.* events. For FMA list.* events, the MSG ID is
471 471 * is contained in the event payload.
472 472 */
473 473 int
474 474 nd_get_diagcode(nd_hdl_t *nhdl, const char *dict, const char *class, char *buf,
475 475 size_t buflen)
476 476 {
477 477 fm_dc_handle_t *dhp;
478 478 size_t dlen;
479 479 char *dirpath;
480 480 const char *key[2];
481 481 int ret = 0;
482 482
483 483 dlen = (strlen(nhdl->nh_rootdir) + strlen(ND_DICTDIR) + 2);
484 484 dirpath = alloca(dlen);
485 485 (void) snprintf(dirpath, dlen, "%s/%s", nhdl->nh_rootdir, ND_DICTDIR);
486 486
487 487 if ((dhp = fm_dc_opendict(FM_DC_VERSION, dirpath, dict)) == NULL) {
488 488 nd_error(nhdl, "fm_dc_opendict failed for %s/%s",
489 489 dirpath, dict);
490 490 return (-1);
491 491 }
492 492
493 493 key[0] = class;
494 494 key[1] = NULL;
495 495 if (fm_dc_key2code(dhp, key, buf, buflen) < 0) {
496 496 nd_error(nhdl, "fm_dc_key2code failed for %s", key[0]);
497 497 ret = -1;
498 498 }
499 499 fm_dc_closedict(dhp);
500 500 return (ret);
501 501 }
502 502
503 503 /*
504 504 * This function takes an event and extracts the bits of the event payload that
505 505 * are of interest to notification daemons and conveniently tucks them into a
506 506 * single struct.
507 507 *
508 508 * The caller is responsible for freeing ev_info and any contained strings and
509 509 * nvlists. A convenience function, nd_free_event_info(), is provided for this
510 510 * purpose.
511 511 */
512 512 int
513 513 nd_get_event_info(nd_hdl_t *nhdl, const char *class, fmev_t ev,
514 514 nd_ev_info_t **ev_info)
515 515 {
516 516 nvlist_t *ev_nvl, *attr_nvl;
517 517 nd_ev_info_t *evi;
518 518 char *code, *uuid, *fmri, *from_state, *to_state, *reason;
519 519
520 520 if ((evi = calloc(1, sizeof (nd_ev_info_t))) == NULL) {
521 521 nd_error(nhdl, "Failed to allocate memory");
522 522 return (-1);
523 523 }
524 524
525 525 /*
526 526 * Hold event; class and payload will be valid for as long as
527 527 * we hold the event.
528 528 */
529 529 fmev_hold(ev);
530 530 evi->ei_ev = ev;
531 531 ev_nvl = fmev_attr_list(ev);
532 532
533 533 /*
534 534 * Lookup the MSGID, event description and severity and KA URL
535 535 *
536 536 * For FMA list.* events we just pull it out of the the event nvlist.
537 537 * For all other events we call a utility function that computes the
538 538 * diagcode using the dict name and class.
539 539 */
540 540 evi->ei_diagcode = calloc(32, sizeof (char));
541 541 if ((nvlist_lookup_string(ev_nvl, FM_SUSPECT_DIAG_CODE, &code) == 0 &&
542 542 strcpy(evi->ei_diagcode, code)) ||
543 543 nd_get_diagcode(nhdl, "SMF", class, evi->ei_diagcode, 32)
544 544 == 0) {
545 545 evi->ei_severity = fmd_msg_getitem_id(nhdl->nh_msghdl,
546 546 NULL, evi->ei_diagcode, FMD_MSG_ITEM_SEVERITY);
547 547 evi->ei_descr = fmd_msg_getitem_id(nhdl->nh_msghdl,
548 548 NULL, evi->ei_diagcode, FMD_MSG_ITEM_DESC);
549 549 evi->ei_url = fmd_msg_getitem_id(nhdl->nh_msghdl,
550 550 NULL, evi->ei_diagcode, FMD_MSG_ITEM_URL);
551 551 } else
552 552 (void) strcpy(evi->ei_diagcode, ND_UNKNOWN);
553 553
554 554 if (!evi->ei_severity)
555 555 evi->ei_severity = strdup(ND_UNKNOWN);
556 556 if (!evi->ei_descr)
557 557 evi->ei_descr = strdup(ND_UNKNOWN);
558 558 if (!evi->ei_url)
559 559 evi->ei_url = strdup(ND_UNKNOWN);
560 560
561 561 evi->ei_payload = ev_nvl;
562 562 evi->ei_class = fmev_class(ev);
563 563 if (nvlist_lookup_string(ev_nvl, FM_SUSPECT_UUID, &uuid) == 0)
564 564 evi->ei_uuid = strdup(uuid);
565 565 else {
566 566 nd_error(nhdl, "Malformed event");
567 567 nd_dump_nvlist(nhdl, evi->ei_payload);
568 568 nd_free_event_info(evi);
569 569 return (-1);
570 570 }
571 571
572 572 if (strncmp(class, "ireport.os.smf", 14) == 0) {
573 573 if ((fmri = nd_get_event_fmri(nhdl, ev)) == NULL) {
574 574 nd_error(nhdl, "Failed to get fmri from event payload");
575 575 nd_free_event_info(evi);
576 576 return (-1);
577 577 }
578 578 if (nvlist_lookup_nvlist(evi->ei_payload, "attr", &attr_nvl) ||
579 579 nvlist_lookup_string(attr_nvl, "from-state", &from_state) ||
580 580 nvlist_lookup_string(attr_nvl, "to-state", &to_state) ||
581 581 nvlist_lookup_string(attr_nvl, "reason-long", &reason)) {
582 582 nd_error(nhdl, "Malformed event");
583 583 nd_dump_nvlist(nhdl, evi->ei_payload);
584 584 nd_free_event_info(evi);
585 585 free(fmri);
586 586 return (-1);
|
↓ open down ↓ |
586 lines elided |
↑ open up ↑ |
587 587 }
588 588 evi->ei_fmri = fmri;
589 589 evi->ei_to_state = strdup(to_state);
590 590 evi->ei_from_state = strdup(from_state);
591 591 evi->ei_reason = strdup(reason);
592 592 }
593 593 *ev_info = evi;
594 594 return (0);
595 595 }
596 596
597 -static void
598 -condfree(void *buf)
599 -{
600 - if (buf != NULL)
601 - free(buf);
602 -}
603 -
604 597 void
605 598 nd_free_event_info(nd_ev_info_t *ev_info)
606 599 {
607 - condfree(ev_info->ei_severity);
608 - condfree(ev_info->ei_descr);
609 - condfree(ev_info->ei_diagcode);
610 - condfree(ev_info->ei_url);
611 - condfree(ev_info->ei_uuid);
612 - condfree(ev_info->ei_fmri);
613 - condfree(ev_info->ei_from_state);
614 - condfree(ev_info->ei_to_state);
615 - condfree(ev_info->ei_reason);
600 + free(ev_info->ei_severity);
601 + free(ev_info->ei_descr);
602 + free(ev_info->ei_diagcode);
603 + free(ev_info->ei_url);
604 + free(ev_info->ei_uuid);
605 + free(ev_info->ei_fmri);
606 + free(ev_info->ei_from_state);
607 + free(ev_info->ei_to_state);
608 + free(ev_info->ei_reason);
616 609 fmev_rele(ev_info->ei_ev);
617 610 free(ev_info);
618 611 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX