+/*
+ * Maps JUL loglevel from string to value
+ */
+static int loglevel_jul_str_to_value(const char *inputstr)
+{
+ int i = 0;
+ char str[LTTNG_SYMBOL_NAME_LEN];
+
+ /*
+ * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
+ * added at the end of the loop so a the upper bound we avoid the overflow.
+ */
+ while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') {
+ str[i] = toupper(inputstr[i]);
+ i++;
+ }
+ str[i] = '\0';
+
+ if (!strcmp(str, "JUL_OFF") || !strcmp(str, "OFF")) {
+ return LTTNG_LOGLEVEL_JUL_OFF;
+ } else if (!strcmp(str, "JUL_SEVERE") || !strcmp(str, "SEVERE")) {
+ return LTTNG_LOGLEVEL_JUL_SEVERE;
+ } else if (!strcmp(str, "JUL_WARNING") || !strcmp(str, "WARNING")) {
+ return LTTNG_LOGLEVEL_JUL_WARNING;
+ } else if (!strcmp(str, "JUL_INFO") || !strcmp(str, "INFO")) {
+ return LTTNG_LOGLEVEL_JUL_INFO;
+ } else if (!strcmp(str, "JUL_CONFIG") || !strcmp(str, "CONFIG")) {
+ return LTTNG_LOGLEVEL_JUL_CONFIG;
+ } else if (!strcmp(str, "JUL_FINE") || !strcmp(str, "FINE")) {
+ return LTTNG_LOGLEVEL_JUL_FINE;
+ } else if (!strcmp(str, "JUL_FINER") || !strcmp(str, "FINER")) {
+ return LTTNG_LOGLEVEL_JUL_FINER;
+ } else if (!strcmp(str, "JUL_FINEST") || !strcmp(str, "FINEST")) {
+ return LTTNG_LOGLEVEL_JUL_FINEST;
+ } else if (!strcmp(str, "JUL_ALL") || !strcmp(str, "ALL")) {
+ return LTTNG_LOGLEVEL_JUL_ALL;
+ } else {
+ return -1;
+ }
+}
+
+/*
+ * Maps loglevel from string to value
+ */
+static
+int loglevel_str_to_value(const char *inputstr)
+{
+ int i = 0;
+ char str[LTTNG_SYMBOL_NAME_LEN];
+
+ /*
+ * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is
+ * added at the end of the loop so a the upper bound we avoid the overflow.
+ */
+ while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') {
+ str[i] = toupper(inputstr[i]);
+ i++;
+ }
+ str[i] = '\0';
+ if (!strcmp(str, "TRACE_EMERG") || !strcmp(str, "EMERG")) {
+ return LTTNG_LOGLEVEL_EMERG;
+ } else if (!strcmp(str, "TRACE_ALERT") || !strcmp(str, "ALERT")) {
+ return LTTNG_LOGLEVEL_ALERT;
+ } else if (!strcmp(str, "TRACE_CRIT") || !strcmp(str, "CRIT")) {
+ return LTTNG_LOGLEVEL_CRIT;
+ } else if (!strcmp(str, "TRACE_ERR") || !strcmp(str, "ERR")) {
+ return LTTNG_LOGLEVEL_ERR;
+ } else if (!strcmp(str, "TRACE_WARNING") || !strcmp(str, "WARNING")) {
+ return LTTNG_LOGLEVEL_WARNING;
+ } else if (!strcmp(str, "TRACE_NOTICE") || !strcmp(str, "NOTICE")) {
+ return LTTNG_LOGLEVEL_NOTICE;
+ } else if (!strcmp(str, "TRACE_INFO") || !strcmp(str, "INFO")) {
+ return LTTNG_LOGLEVEL_INFO;
+ } else if (!strcmp(str, "TRACE_DEBUG_SYSTEM") || !strcmp(str, "DEBUG_SYSTEM") || !strcmp(str, "SYSTEM")) {
+ return LTTNG_LOGLEVEL_DEBUG_SYSTEM;
+ } else if (!strcmp(str, "TRACE_DEBUG_PROGRAM") || !strcmp(str, "DEBUG_PROGRAM") || !strcmp(str, "PROGRAM")) {
+ return LTTNG_LOGLEVEL_DEBUG_PROGRAM;
+ } else if (!strcmp(str, "TRACE_DEBUG_PROCESS") || !strcmp(str, "DEBUG_PROCESS") || !strcmp(str, "PROCESS")) {
+ return LTTNG_LOGLEVEL_DEBUG_PROCESS;
+ } else if (!strcmp(str, "TRACE_DEBUG_MODULE") || !strcmp(str, "DEBUG_MODULE") || !strcmp(str, "MODULE")) {
+ return LTTNG_LOGLEVEL_DEBUG_MODULE;
+ } else if (!strcmp(str, "TRACE_DEBUG_UNIT") || !strcmp(str, "DEBUG_UNIT") || !strcmp(str, "UNIT")) {
+ return LTTNG_LOGLEVEL_DEBUG_UNIT;
+ } else if (!strcmp(str, "TRACE_DEBUG_FUNCTION") || !strcmp(str, "DEBUG_FUNCTION") || !strcmp(str, "FUNCTION")) {
+ return LTTNG_LOGLEVEL_DEBUG_FUNCTION;
+ } else if (!strcmp(str, "TRACE_DEBUG_LINE") || !strcmp(str, "DEBUG_LINE") || !strcmp(str, "LINE")) {
+ return LTTNG_LOGLEVEL_DEBUG_LINE;
+ } else if (!strcmp(str, "TRACE_DEBUG") || !strcmp(str, "DEBUG")) {
+ return LTTNG_LOGLEVEL_DEBUG;
+ } else {
+ return -1;
+ }
+}
+
+static
+const char *print_channel_name(const char *name)
+{
+ return name ? : DEFAULT_CHANNEL_NAME;
+}
+
+static
+const char *print_raw_channel_name(const char *name)
+{
+ return name ? : "<default>";
+}
+
+/*
+ * Return allocated string for pretty-printing exclusion names.
+ */
+static
+char *print_exclusions(int count, char **names)
+{
+ int length = 0;
+ int i;
+ const char *preamble = " excluding ";
+ char *ret;
+
+ if (count == 0) {
+ return strdup("");
+ }
+
+ /* calculate total required length */
+ for (i = 0; i < count; i++) {
+ length += strlen(names[i]) + 1;
+ }
+
+ /* add length of preamble + one for NUL - one for last (missing) comma */
+ length += strlen(preamble);
+ ret = malloc(length);
+ strncpy(ret, preamble, length);
+ for (i = 0; i < count; i++) {
+ strcat(ret, names[i]);
+ if (i != count - 1) {
+ strcat(ret, ",");
+ }
+ }
+ return ret;
+}
+
+/*
+ * Compare list of exclusions against an event name.
+ * Return a list of legal exclusion names.
+ * Produce an error or a warning about others (depending on the situation)
+ */
+static
+int check_exclusion_subsets(const char *event_name,
+ const char *exclusions,
+ int *exclusion_count_ptr,
+ char ***exclusion_list_ptr)
+{
+ const char *excluder_ptr;
+ const char *event_ptr;
+ const char *next_excluder;
+ int excluder_length;
+ int exclusion_count = 0;
+ char **exclusion_list = NULL;
+ int ret = CMD_SUCCESS;
+
+ if (event_name[strlen(event_name) - 1] != '*') {
+ ERR("Event %s: Excluders can only be used with wildcarded events", event_name);
+ goto error;
+ }
+
+ next_excluder = exclusions;
+ while (*next_excluder != 0) {
+ event_ptr = event_name;
+ excluder_ptr = next_excluder;
+ excluder_length = strcspn(next_excluder, ",");
+
+ /* Scan both the excluder and the event letter by letter */
+ while (1) {
+ char e, x;
+
+ e = *event_ptr;
+ x = *excluder_ptr;
+
+ if (x == '*') {
+ /* Event is a subset of the excluder */
+ ERR("Event %s: %.*s excludes all events from %s",
+ event_name,
+ excluder_length,
+ next_excluder,
+ event_name);
+ goto error;
+ }
+ if (e == '*') {
+ /* Excluder is a proper subset of event */
+ exclusion_count++;
+ exclusion_list = realloc(exclusion_list, sizeof(char **) * exclusion_count);
+ exclusion_list[exclusion_count - 1] = strndup(next_excluder, excluder_length);
+
+ break;
+ }
+ if (x != e) {
+ /* Excluder and event sets have no common elements */
+ WARN("Event %s: %.*s does not exclude any events from %s",
+ event_name,
+ excluder_length,
+ next_excluder,
+ event_name);
+ break;
+ }
+ excluder_ptr++;
+ event_ptr++;
+ }
+ /* next excluder */
+ next_excluder += excluder_length;
+ if (*next_excluder == ',') {
+ next_excluder++;
+ }
+ }
+ goto end;
+error:
+ while (exclusion_count--) {
+ free(exclusion_list[exclusion_count]);
+ }
+ if (exclusion_list != NULL) {
+ free(exclusion_list);
+ }
+ exclusion_list = NULL;
+ exclusion_count = 0;
+ ret = CMD_ERROR;
+end:
+ *exclusion_count_ptr = exclusion_count;
+ *exclusion_list_ptr = exclusion_list;
+ return ret;
+}