static void setup_trace(const char *str)
{
    char *val;

    trace_data_stack = sk_tracedata_new_null();
    val = OPENSSL_strdup(str);

    if (val != NULL) {
        char *valp = val;
        char *item;

        for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) {
            int category = OSSL_trace_get_category_num(item);

            if (category >= 0) {
                BIO *channel = BIO_push(BIO_new(apps_bf_prefix()),
                                        dup_bio_err(FORMAT_TEXT));
                tracedata *trace_data = OPENSSL_zalloc(sizeof(*trace_data));

                if (trace_data == NULL
                    || (trace_data->bio = channel) == NULL
                    || OSSL_trace_set_callback(category, internal_trace_cb,
                                               trace_data) == 0
                    || sk_tracedata_push(trace_data_stack, trace_data) == 0) {
                    OSSL_trace_set_callback(category, NULL, NULL);
                    BIO_free_all(channel);
                    fprintf(stderr,
                            "warning: unable to setup trace callback for category '%s'.\n",
                            item);
                }
            } else {
                fprintf(stderr,
                        "warning: unknown trace category: '%s'.\n",
                        item);
            }
        }
    }

    OPENSSL_free(val);
    atexit(cleanup_trace);
}