Пример #1
0
/*
 * Add the environment variable specified by the format string [fmt].
 */
static void
_zed_event_add_var(uint64_t eid, zed_strings_t *zsp, const char *fmt, ...)
{
	char buf[4096];
	va_list vargs;
	int n;
	const char *p;
	size_t namelen;

	assert(zsp != NULL);
	assert(fmt != NULL);

	va_start(vargs, fmt);
	n = vsnprintf(buf, sizeof (buf), fmt, vargs);
	va_end(vargs);
	p = strchr(buf, '=');
	namelen = (p) ? p - buf : strlen(buf);

	if ((n < 0) || (n >= sizeof (buf))) {
		zed_log_msg(LOG_WARNING, "Failed to add %.*s for eid=%llu: %s",
		    namelen, buf, eid, "Exceeded buffer size");
	} else if (!p) {
		zed_log_msg(LOG_WARNING, "Failed to add %.*s for eid=%llu: %s",
		    namelen, buf, eid, "Missing assignment");
	} else if (zed_strings_add(zsp, buf) < 0) {
		zed_log_msg(LOG_WARNING, "Failed to add %.*s for eid=%llu: %s",
		    namelen, buf, eid, strerror(ENOMEM));
	}
}
Пример #2
0
/*
 * Scan the [zcp] zedlet_dir for files to exec based on the event class.
 * Files must be executable by user, but not writable by group or other.
 * Dotfiles are ignored.
 *
 * Return 0 on success with an updated set of zedlets,
 * or -1 on error with errno set.
 *
 * FIXME: Check if zedlet_dir and all parent dirs are secure.
 */
int
zed_conf_scan_dir(struct zed_conf *zcp)
{
	zed_strings_t *zedlets;
	DIR *dirp;
	struct dirent *direntp;
	char pathname[PATH_MAX];
	struct stat st;
	int n;

	if (!zcp) {
		errno = EINVAL;
		zed_log_msg(LOG_ERR, "Failed to scan zedlet dir: %s",
		    strerror(errno));
		return (-1);
	}
	zedlets = zed_strings_create();
	if (!zedlets) {
		errno = ENOMEM;
		zed_log_msg(LOG_WARNING, "Failed to scan dir \"%s\": %s",
		    zcp->zedlet_dir, strerror(errno));
		return (-1);
	}
	dirp = opendir(zcp->zedlet_dir);
	if (!dirp) {
		int errno_bak = errno;
		zed_log_msg(LOG_WARNING, "Failed to open dir \"%s\": %s",
		    zcp->zedlet_dir, strerror(errno));
		zed_strings_destroy(zedlets);
		errno = errno_bak;
		return (-1);
	}
	while ((direntp = readdir(dirp))) {
		if (direntp->d_name[0] == '.')
			continue;

		n = snprintf(pathname, sizeof (pathname),
		    "%s/%s", zcp->zedlet_dir, direntp->d_name);
		if ((n < 0) || (n >= sizeof (pathname))) {
			zed_log_msg(LOG_WARNING, "Failed to stat \"%s\": %s",
			    direntp->d_name, strerror(ENAMETOOLONG));
			continue;
		}
		if (stat(pathname, &st) < 0) {
			zed_log_msg(LOG_WARNING, "Failed to stat \"%s\": %s",
			    pathname, strerror(errno));
			continue;
		}
		if (!S_ISREG(st.st_mode)) {
			zed_log_msg(LOG_INFO,
			    "Ignoring \"%s\": not a regular file",
			    direntp->d_name);
			continue;
		}
		if ((st.st_uid != 0) && !zcp->do_force) {
			zed_log_msg(LOG_NOTICE,
			    "Ignoring \"%s\": not owned by root",
			    direntp->d_name);
			continue;
		}
		if (!(st.st_mode & S_IXUSR)) {
			zed_log_msg(LOG_INFO,
			    "Ignoring \"%s\": not executable by user",
			    direntp->d_name);
			continue;
		}
		if ((st.st_mode & S_IWGRP) & !zcp->do_force) {
			zed_log_msg(LOG_NOTICE,
			    "Ignoring \"%s\": writable by group",
			    direntp->d_name);
			continue;
		}
		if ((st.st_mode & S_IWOTH) & !zcp->do_force) {
			zed_log_msg(LOG_NOTICE,
			    "Ignoring \"%s\": writable by other",
			    direntp->d_name);
			continue;
		}
		if (zed_strings_add(zedlets, direntp->d_name) < 0) {
			zed_log_msg(LOG_WARNING,
			    "Failed to register \"%s\": %s",
			    direntp->d_name, strerror(errno));
			continue;
		}
		if (zcp->do_verbose)
			zed_log_msg(LOG_INFO,
			    "Registered zedlet \"%s\"", direntp->d_name);
	}
	if (closedir(dirp) < 0) {
		int errno_bak = errno;
		zed_log_msg(LOG_WARNING, "Failed to close dir \"%s\": %s",
		    zcp->zedlet_dir, strerror(errno));
		zed_strings_destroy(zedlets);
		errno = errno_bak;
		return (-1);
	}
	if (zcp->zedlets)
		zed_strings_destroy(zcp->zedlets);

	zcp->zedlets = zedlets;
	return (0);
}
Пример #3
0
/*
 * Add an environment variable for [eid] to the container [zsp].
 *
 * The variable name is the concatenation of [prefix] and [name] converted to
 * uppercase with non-alphanumeric characters converted to underscores;
 * [prefix] is optional, and [name] must begin with an alphabetic character.
 * If the converted variable name already exists within the container [zsp],
 * its existing value will be replaced with the new value.
 *
 * The variable value is specified by the format string [fmt].
 *
 * Returns 0 on success, and -1 on error (with errno set).
 *
 * All environment variables in [zsp] should be added through this function.
 */
static int
_zed_event_add_var(uint64_t eid, zed_strings_t *zsp,
    const char *prefix, const char *name, const char *fmt, ...)
{
	char keybuf[MAXBUF];
	char valbuf[MAXBUF];
	char *dstp;
	const char *srcp;
	const char *lastp;
	int n;
	int buflen;
	va_list vargs;

	assert(zsp != NULL);
	assert(fmt != NULL);

	if (!name) {
		errno = EINVAL;
		zed_log_msg(LOG_WARNING,
		    "Failed to add variable for eid=%llu: Name is empty", eid);
		return (-1);
	} else if (!isalpha(name[0])) {
		errno = EINVAL;
		zed_log_msg(LOG_WARNING,
		    "Failed to add variable for eid=%llu: "
		    "Name \"%s\" is invalid", eid, name);
		return (-1);
	}
	/*
	 * Construct the string key by converting PREFIX (if present) and NAME.
	 */
	dstp = keybuf;
	lastp = keybuf + sizeof (keybuf);
	if (prefix) {
		for (srcp = prefix; *srcp && (dstp < lastp); srcp++)
			*dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';
	}
	for (srcp = name; *srcp && (dstp < lastp); srcp++)
		*dstp++ = isalnum(*srcp) ? toupper(*srcp) : '_';

	if (dstp == lastp) {
		errno = ENAMETOOLONG;
		zed_log_msg(LOG_WARNING,
		    "Failed to add variable for eid=%llu: Name too long", eid);
		return (-1);
	}
	*dstp = '\0';
	/*
	 * Construct the string specified by "[PREFIX][NAME]=[FMT]".
	 */
	dstp = valbuf;
	buflen = sizeof (valbuf);
	n = strlcpy(dstp, keybuf, buflen);
	if (n >= sizeof (valbuf)) {
		errno = EMSGSIZE;
		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
		    keybuf, eid, "Exceeded buffer size");
		return (-1);
	}
	dstp += n;
	buflen -= n;

	*dstp++ = '=';
	buflen--;

	va_start(vargs, fmt);
	n = vsnprintf(dstp, buflen, fmt, vargs);
	va_end(vargs);

	if ((n < 0) || (n >= buflen)) {
		errno = EMSGSIZE;
		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
		    keybuf, eid, "Exceeded buffer size");
		return (-1);
	} else if (zed_strings_add(zsp, keybuf, valbuf) < 0) {
		zed_log_msg(LOG_WARNING, "Failed to add %s for eid=%llu: %s",
		    keybuf, eid, strerror(errno));
		return (-1);
	}
	return (0);
}
Пример #4
0
/*
 * Convert the nvpair [nvp] to a string which is added to the environment
 * of the child process.
 * Return 0 on success, -1 on error.
 *
 * FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()?
 */
static void
_zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp)
{
	const char *name;
	data_type_t type;
	char buf[4096];
	int buflen;
	int n;
	char *p;
	const char *q;
	const char *fmt;

	boolean_t b;
	double d;
	uint8_t i8;
	uint16_t i16;
	uint32_t i32;
	uint64_t i64;
	char *str;

	assert(zsp != NULL);
	assert(nvp != NULL);

	name = nvpair_name(nvp);
	type = nvpair_type(nvp);
	buflen = sizeof (buf);

	/* Copy NAME prefix for ZED zevent namespace. */
	n = strlcpy(buf, ZEVENT_VAR_PREFIX, sizeof (buf));
	if (n >= sizeof (buf)) {
		zed_log_msg(LOG_WARNING,
		    "Failed to convert nvpair \"%s\" for eid=%llu: %s",
		    name, eid, "Exceeded buffer size");
		return;
	}
	buflen -= n;
	p = buf + n;

	/* Convert NAME to alphanumeric uppercase. */
	for (q = name; *q && (buflen > 0); q++) {
		*p++ = isalnum(*q) ? toupper(*q) : '_';
		buflen--;
	}

	/* Separate NAME from VALUE. */
	if (buflen > 0) {
		*p++ = '=';
		buflen--;
	}
	*p = '\0';

	/* Convert VALUE. */
	switch (type) {
	case DATA_TYPE_BOOLEAN:
		n = snprintf(p, buflen, "%s", "1");
		break;
	case DATA_TYPE_BOOLEAN_VALUE:
		(void) nvpair_value_boolean_value(nvp, &b);
		n = snprintf(p, buflen, "%s", b ? "1" : "0");
		break;
	case DATA_TYPE_BYTE:
		(void) nvpair_value_byte(nvp, &i8);
		n = snprintf(p, buflen, "%d", i8);
		break;
	case DATA_TYPE_INT8:
		(void) nvpair_value_int8(nvp, (int8_t *) &i8);
		n = snprintf(p, buflen, "%d", i8);
		break;
	case DATA_TYPE_UINT8:
		(void) nvpair_value_uint8(nvp, &i8);
		n = snprintf(p, buflen, "%u", i8);
		break;
	case DATA_TYPE_INT16:
		(void) nvpair_value_int16(nvp, (int16_t *) &i16);
		n = snprintf(p, buflen, "%d", i16);
		break;
	case DATA_TYPE_UINT16:
		(void) nvpair_value_uint16(nvp, &i16);
		n = snprintf(p, buflen, "%u", i16);
		break;
	case DATA_TYPE_INT32:
		(void) nvpair_value_int32(nvp, (int32_t *) &i32);
		n = snprintf(p, buflen, "%d", i32);
		break;
	case DATA_TYPE_UINT32:
		(void) nvpair_value_uint32(nvp, &i32);
		n = snprintf(p, buflen, "%u", i32);
		break;
	case DATA_TYPE_INT64:
		(void) nvpair_value_int64(nvp, (int64_t *) &i64);
		n = snprintf(p, buflen, "%lld", (longlong_t) i64);
		break;
	case DATA_TYPE_UINT64:
		(void) nvpair_value_uint64(nvp, &i64);
		fmt = _zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu";
		n = snprintf(p, buflen, fmt, (u_longlong_t) i64);
		break;
	case DATA_TYPE_DOUBLE:
		(void) nvpair_value_double(nvp, &d);
		n = snprintf(p, buflen, "%g", d);
		break;
	case DATA_TYPE_HRTIME:
		(void) nvpair_value_hrtime(nvp, (hrtime_t *) &i64);
		n = snprintf(p, buflen, "%llu", (u_longlong_t) i64);
		break;
	case DATA_TYPE_NVLIST:
		/* FIXME */
		n = snprintf(p, buflen, "%s", "_NOT_IMPLEMENTED_");
		break;
	case DATA_TYPE_STRING:
		(void) nvpair_value_string(nvp, &str);
		n = snprintf(p, buflen, "%s", (str ? str : "<NULL>"));
		break;
	case DATA_TYPE_BOOLEAN_ARRAY:
		/* FIXME */
		n = snprintf(p, buflen, "%s", "_NOT_IMPLEMENTED_");
		break;
	case DATA_TYPE_BYTE_ARRAY:
		/* FIXME */
		n = snprintf(p, buflen, "%s", "_NOT_IMPLEMENTED_");
		break;
	case DATA_TYPE_INT8_ARRAY:
		n = _zed_event_convert_int8_array(p, buflen, nvp);
		break;
	case DATA_TYPE_UINT8_ARRAY:
		n = _zed_event_convert_uint8_array(p, buflen, nvp);
		break;
	case DATA_TYPE_INT16_ARRAY:
		n = _zed_event_convert_int16_array(p, buflen, nvp);
		break;
	case DATA_TYPE_UINT16_ARRAY:
		n = _zed_event_convert_uint16_array(p, buflen, nvp);
		break;
	case DATA_TYPE_INT32_ARRAY:
		n = _zed_event_convert_int32_array(p, buflen, nvp);
		break;
	case DATA_TYPE_UINT32_ARRAY:
		n = _zed_event_convert_uint32_array(p, buflen, nvp);
		break;
	case DATA_TYPE_INT64_ARRAY:
		n = _zed_event_convert_int64_array(p, buflen, nvp);
		break;
	case DATA_TYPE_UINT64_ARRAY:
		fmt = _zed_event_value_is_hex(name) ? "0x%.16llX " : "%llu ";
		n = _zed_event_convert_uint64_array(p, buflen, nvp, fmt);
		break;
	case DATA_TYPE_STRING_ARRAY:
		n = _zed_event_convert_string_array(p, buflen, nvp);
		break;
	case DATA_TYPE_NVLIST_ARRAY:
		/* FIXME */
		n = snprintf(p, buflen, "%s", "_NOT_IMPLEMENTED_");
		break;
	default:
		zed_log_msg(LOG_WARNING,
		    "Failed to convert nvpair \"%s\" for eid=%llu: "
		    "Unrecognized type=%u", name, eid, (unsigned int) type);
		return;
	}
	if ((n < 0) || (n >= sizeof (buf))) {
		zed_log_msg(LOG_WARNING,
		    "Failed to convert nvpair \"%s\" for eid=%llu: %s",
		    name, eid, "Exceeded buffer size");
		return;
	}
	if (zed_strings_add(zsp, buf) < 0) {
		zed_log_msg(LOG_WARNING,
		    "Failed to convert nvpair \"%s\" for eid=%llu: %s",
		    name, eid, strerror(ENOMEM));
		return;
	}
}