Beispiel #1
0
static char* get_backtrace(unsigned show_nframes) {
    void* trace[32];
    int n_frames;
    char **symbols, *e, *r;
    unsigned j, n, s;
    size_t a;

    pa_assert(show_nframes > 0);

    n_frames = backtrace(trace, PA_ELEMENTSOF(trace));

    if (n_frames <= 0)
        return NULL;

    symbols = backtrace_symbols(trace, n_frames);

    if (!symbols)
        return NULL;

    s = skip_backtrace;
    n = PA_MIN((unsigned) n_frames, s + show_nframes);

    a = 4;

    for (j = s; j < n; j++) {
        if (j > s)
            a += 2;
        a += strlen(pa_path_get_filename(symbols[j]));
    }

    r = pa_xnew(char, a);

    strcpy(r, " (");
    e = r + 2;

    for (j = s; j < n; j++) {
        const char *sym;

        if (j > s) {
            strcpy(e, "<<");
            e += 2;
        }

        sym = pa_path_get_filename(symbols[j]);

        strcpy(e, sym);
        e += strlen(sym);
    }

    strcpy(e, ")");

    free(symbols);

    return r;
}
static int add_dbus_match(struct cmtspeech_dbus_conn *e, DBusConnection *dbusconn, char *match)
{
    DBusError error;
    uint i;

    dbus_error_init(&error);

    for(i = 0; i < PA_ELEMENTSOF(e->dbus_match_rules) && e->dbus_match_rules[i] != NULL; i++);

    pa_return_val_if_fail (i < PA_ELEMENTSOF(e->dbus_match_rules), -1);

    dbus_bus_add_match(dbusconn, match, &error);
    if (dbus_error_is_set(&error)) {
        pa_log_error("Unable to add dbus match:\"%s\": %s: %s", match, error.name, error.message);
        return -1;;
    }

    e->dbus_match_rules[i] = pa_xstrdup(match);
    pa_log_debug("added dbus match \"%s\"", match);

    return 0;
}
static void clear_dbus_matches(struct cmtspeech_dbus_conn *e, DBusConnection *dbusconn)
{
    int i;

    for(i = PA_ELEMENTSOF(e->dbus_match_rules) - 1; i >= 0; i--) {
        if (e->dbus_match_rules[i] == NULL)
            continue;

        dbus_bus_remove_match(dbusconn, e->dbus_match_rules[i], NULL);
        pa_log_debug("removed dbus match \"%s\"", e->dbus_match_rules[i]);
        pa_xfree(e->dbus_match_rules[i]);
        e->dbus_match_rules[i] = NULL;
    }
}
Beispiel #4
0
END_TEST

START_TEST(int_test) {
    pa_json_object *o;
    unsigned int i;
    const char *ints_parse[] = { "1", "-1", "1234", "0" };
    const int ints_compare[] = { 1, -1, 1234, 0 };

    for (i = 0; i < PA_ELEMENTSOF(ints_parse); i++) {
        o = pa_json_parse(ints_parse[i]);

        fail_unless(o != NULL);
        fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_INT);
        fail_unless(pa_json_object_get_int(o) == ints_compare[i]);

        pa_json_object_free(o);
    }
}
Beispiel #5
0
END_TEST

START_TEST(double_test) {
    pa_json_object *o;
    unsigned int i;
    const char *doubles_parse[] = {
        "1.0", "-1.1", "1234e2", "1234e0", "0.1234", "-0.1234", "1234e-1", "1234.5e-1", "1234.5e+2",
    };
    const double doubles_compare[] = {
        1.0, -1.1, 123400.0, 1234.0, 0.1234, -0.1234, 123.4, 123.45, 123450.0,
    };

    for (i = 0; i < PA_ELEMENTSOF(doubles_parse); i++) {
        o = pa_json_parse(doubles_parse[i]);

        fail_unless(o != NULL);
        fail_unless(pa_json_object_get_type(o) == PA_JSON_TYPE_DOUBLE);
        fail_unless(PA_DOUBLE_IS_EQUAL(pa_json_object_get_double(o), doubles_compare[i]));

        pa_json_object_free(o);
    }
}
Beispiel #6
0
END_TEST

START_TEST(bad_test) {
    unsigned int i;
    const char *bad_parse[] = {
        "\"" /* Quote not closed */,
        "123456789012345678901234567890" /* Overflow */,
        "0.123456789012345678901234567890" /* Overflow */,
        "1e123456789012345678901234567890" /* Overflow */,
        "1e" /* Bad number string */,
        "1." /* Bad number string */,
        "1.e3" /* Bad number string */,
        "-" /* Bad number string */,
        "{ \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": { \"a\": {  \"a\": { } } } } } } } } } } } } } } } } } } } } } }" /* Nested too deep */,
        "[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ { \"a\": \"b\" } ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]" /* Nested too deep */,
        "asdf" /* Unquoted string */,
        "{ a: true }" /* Unquoted key in object */,
        "\"    \a\"" /* Alarm is not a valid character */
    };

    for (i = 0; i < PA_ELEMENTSOF(bad_parse); i++) {
        fail_unless(pa_json_parse(bad_parse[i]) == NULL);
    }
}
Beispiel #7
0
static int context_autospawn(pa_context *c) {
    pid_t pid;
    int status, r;
    struct sigaction sa;

    pa_context_ref(c);

    if (sigaction(SIGCHLD, NULL, &sa) < 0) {
        pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno));
        pa_context_fail(c, PA_ERR_INTERNAL);
        goto fail;
    }

    if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) {
        pa_log_debug("Process disabled waitpid(), cannot autospawn.");
        pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
        goto fail;
    }

    pa_log_debug("Trying to autospawn...");

    if (c->spawn_api.prefork)
        c->spawn_api.prefork();

    if ((pid = fork()) < 0) {
        pa_log_error(_("fork(): %s"), pa_cstrerror(errno));
        pa_context_fail(c, PA_ERR_INTERNAL);

        if (c->spawn_api.postfork)
            c->spawn_api.postfork();

        goto fail;
    } else if (!pid) {
        /* Child */

        const char *state = NULL;
        const char * argv[32];
        unsigned n = 0;

        if (c->spawn_api.atfork)
            c->spawn_api.atfork();

        /* We leave most of the cleaning up of the process environment
         * to the executable. We only clean up the file descriptors to
         * make sure the executable can actually be loaded
         * correctly. */
        pa_close_all(-1);

        /* Setup argv */
        argv[n++] = c->conf->daemon_binary;
        argv[n++] = "--start";

        while (n < PA_ELEMENTSOF(argv)-1) {
            char *a;

            if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
                break;

            argv[n++] = a;
        }

        argv[n++] = NULL;
        pa_assert(n <= PA_ELEMENTSOF(argv));

        execv(argv[0], (char * const *) argv);
        _exit(1);
    }

    /* Parent */

    if (c->spawn_api.postfork)
        c->spawn_api.postfork();

    do {
        r = waitpid(pid, &status, 0);
    } while (r < 0 && errno == EINTR);

    if (r < 0) {

        if (errno != ESRCH) {
            pa_log(_("waitpid(): %s"), pa_cstrerror(errno));
            pa_context_fail(c, PA_ERR_INTERNAL);
            goto fail;
        }

        /* hmm, something already reaped our child, so we assume
         * startup worked, even if we cannot know */

    } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
        goto fail;
    }

    pa_context_unref(c);

    return 0;

fail:

    pa_context_unref(c);

    return -1;
}
static int context_autospawn(pa_context *c) {
    pid_t pid;
    int status, r;
    struct sigaction sa;

    pa_context_ref(c);

    if (sigaction(SIGCHLD, NULL, &sa) < 0) {
        pa_log_debug("sigaction() failed: %s", pa_cstrerror(errno));
        pa_context_fail(c, PA_ERR_INTERNAL);
        goto fail;
    }

#ifdef SA_NOCLDWAIT
    if ((sa.sa_flags & SA_NOCLDWAIT) || sa.sa_handler == SIG_IGN) {
#else
    if (sa.sa_handler == SIG_IGN) {
#endif
        pa_log_debug("Process disabled waitpid(), cannot autospawn.");
        pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
        goto fail;
    }

    pa_log_debug("Trying to autospawn...");

    if (c->spawn_api.prefork)
        c->spawn_api.prefork();

    if ((pid = fork()) < 0) {
        pa_log_error(_("fork(): %s"), pa_cstrerror(errno));
        pa_context_fail(c, PA_ERR_INTERNAL);

        if (c->spawn_api.postfork)
            c->spawn_api.postfork();

        goto fail;
    } else if (!pid) {
        /* Child */

        const char *state = NULL;
        const char * argv[32];
        unsigned n = 0;

        if (c->spawn_api.atfork)
            c->spawn_api.atfork();

        /* We leave most of the cleaning up of the process environment
         * to the executable. We only clean up the file descriptors to
         * make sure the executable can actually be loaded
         * correctly. */
        pa_close_all(-1);

        /* Setup argv */
        argv[n++] = c->conf->daemon_binary;
        argv[n++] = "--start";

        while (n < PA_ELEMENTSOF(argv)-1) {
            char *a;

            if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
                break;

            argv[n++] = a;
        }

        argv[n++] = NULL;
        pa_assert(n <= PA_ELEMENTSOF(argv));

        execv(argv[0], (char * const *) argv);
        _exit(1);
    }

    /* Parent */

    if (c->spawn_api.postfork)
        c->spawn_api.postfork();

    do {
        r = waitpid(pid, &status, 0);
    } while (r < 0 && errno == EINTR);

    if (r < 0) {

        if (errno != ESRCH) {
            pa_log(_("waitpid(): %s"), pa_cstrerror(errno));
            pa_context_fail(c, PA_ERR_INTERNAL);
            goto fail;
        }

        /* hmm, something already reaped our child, so we assume
         * startup worked, even if we cannot know */

    } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
        goto fail;
    }

    pa_context_unref(c);

    return 0;

fail:

    pa_context_unref(c);

    return -1;
}

#endif /* OS_IS_WIN32 */

static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata);

#ifdef HAVE_DBUS
static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) {
    DBusError error;

    pa_assert(c);
    pa_assert(conn);

    dbus_error_init(&error);

    if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, c->use_rtclock, type, &error)) || dbus_error_is_set(&error)) {
        pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);
        goto fail;
    }

    if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) {
        pa_log_warn("Failed to add filter function");
        goto fail;
    }
    c->filter_added = true;

    if (pa_dbus_add_matches(
                pa_dbus_wrap_connection_get(*conn), &error,
                "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0) {

        pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message);
        goto fail;
    }

    return;

fail:
    if (*conn) {
        pa_dbus_wrap_connection_free(*conn);
        *conn = NULL;
    }

    dbus_error_free(&error);
}
Beispiel #9
0
int main(int argc, char *argv[]) {
    pa_format_info *f1 = NULL, *f2 = NULL;
    int rates1[] = { 32000, 44100, 48000 };
    const char *strings[] = { "thing1", "thing2", "thing3" };

    /* 1. Simple fixed format int check */
    INIT(f1); INIT(f2);
    f1->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int(f1, PA_PROP_FORMAT_RATE, 32000);
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 44100);
    pa_assert(!pa_format_info_is_compatible(f1, f2));

    /* 2. Check int array membership - positive */
    REINIT(f1); REINIT(f2);
    f1->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int_array(f1, PA_PROP_FORMAT_RATE, rates1, PA_ELEMENTSOF(rates1));
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 44100);
    pa_assert(pa_format_info_is_compatible(f1, f2));
    pa_assert(pa_format_info_is_compatible(f2, f1));

    /* 3. Check int array memebership - negative */
    REINIT(f2);
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 96000);
    pa_assert(!pa_format_info_is_compatible(f1, f2));
    pa_assert(!pa_format_info_is_compatible(f2, f1));

    /* 4. Check int range - positive */
    REINIT(f1); REINIT(f2);
    f1->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int_range(f1, PA_PROP_FORMAT_RATE, 32000, 48000);
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 44100);
    pa_assert(pa_format_info_is_compatible(f1, f2));
    pa_assert(pa_format_info_is_compatible(f2, f1));

    /* 5. Check int range - negative */
    REINIT(f2);
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_int(f2, PA_PROP_FORMAT_RATE, 96000);
    pa_assert(!pa_format_info_is_compatible(f1, f2));
    pa_assert(!pa_format_info_is_compatible(f2, f1));

    /* 6. Simple fixed format string check */
    REINIT(f1); REINIT(f2);
    f1->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_string(f1, "format.test_string", "thing1");
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_string(f2, "format.test_string", "notthing1");
    pa_assert(!pa_format_info_is_compatible(f1, f2));

    /* 7. Check string array membership - positive */
    REINIT(f1); REINIT(f2);
    f1->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_string_array(f1, "format.test_string", strings, PA_ELEMENTSOF(strings));
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_string(f2, "format.test_string", "thing3");
    pa_assert(pa_format_info_is_compatible(f1, f2));
    pa_assert(pa_format_info_is_compatible(f2, f1));

    /* 8. Check string array memebership - negative */
    REINIT(f2);
    f2->encoding = PA_ENCODING_AC3_IEC61937;
    pa_format_info_set_prop_string(f2, "format.test_string", "thing5");
    pa_assert(!pa_format_info_is_compatible(f1, f2));
    pa_assert(!pa_format_info_is_compatible(f2, f1));

    DEINIT(f1);
    DEINIT(f2);

    return 0;
}
int pa__init(pa_module*m) {

    pa_modargs *ma = NULL;
    char t[256], *vendor, *client_id;
    SmcCallbacks callbacks;
    SmProp prop_program, prop_user;
    SmProp *prop_list[2];
    SmPropValue val_program, val_user;
    struct userdata *u;
    const char *e;
    pa_client_new_data data;

    pa_assert(m);

    if (ice_in_use) {
        pa_log("module-x11-xsmp may no be loaded twice.");
        return -1;
    }

    IceAddConnectionWatch(new_ice_connection, m->core);
    ice_in_use = TRUE;

    m->userdata = u = pa_xnew(struct userdata, 1);
    u->core = m->core;
    u->module = m;
    u->client = NULL;
    u->connection = NULL;
    u->x11 = NULL;

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments");
        goto fail;
    }

    if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
        goto fail;

    e = pa_modargs_get_value(ma, "session_manager", NULL);

    if (!e && !getenv("SESSION_MANAGER")) {
        pa_log("X11 session manager not running.");
        goto fail;
    }

    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.die.callback = die_cb;
    callbacks.die.client_data = u;
    callbacks.save_yourself.callback = save_yourself_cb;
    callbacks.save_yourself.client_data = m->core;
    callbacks.save_complete.callback = save_complete_cb;
    callbacks.save_complete.client_data = m->core;
    callbacks.shutdown_cancelled.callback = shutdown_cancelled_cb;
    callbacks.shutdown_cancelled.client_data = m->core;

    if (!(u->connection = SmcOpenConnection(
                              (char*) e, m->core,
                              SmProtoMajor, SmProtoMinor,
                              SmcSaveYourselfProcMask | SmcDieProcMask | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
                              &callbacks, NULL, &client_id,
                              sizeof(t), t))) {

        pa_log("Failed to open connection to session manager: %s", t);
        goto fail;
    }

    prop_program.name = (char*) SmProgram;
    prop_program.type = (char*) SmARRAY8;
    val_program.value = (char*) PACKAGE_NAME;
    val_program.length = (int) strlen(val_program.value);
    prop_program.num_vals = 1;
    prop_program.vals = &val_program;
    prop_list[0] = &prop_program;

    prop_user.name = (char*) SmUserID;
    prop_user.type = (char*) SmARRAY8;
    pa_get_user_name(t, sizeof(t));
    val_user.value = t;
    val_user.length = (int) strlen(val_user.value);
    prop_user.num_vals = 1;
    prop_user.vals = &val_user;
    prop_list[1] = &prop_user;

    SmcSetProperties(u->connection, PA_ELEMENTSOF(prop_list), prop_list);

    pa_log_info("Connected to session manager '%s' as '%s'.", vendor = SmcVendor(u->connection), client_id);

    pa_client_new_data_init(&data);
    data.module = m;
    data.driver = __FILE__;
    pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "XSMP Session on %s as %s", vendor, client_id);
    pa_proplist_sets(data.proplist, "xsmp.vendor", vendor);
    pa_proplist_sets(data.proplist, "xsmp.client.id", client_id);
    u->client = pa_client_new(u->core, &data);
    pa_client_new_data_done(&data);

    free(vendor);
    free(client_id);

    if (!u->client)
        goto fail;

    pa_modargs_free(ma);

    return 0;

fail:
    if (ma)
        pa_modargs_free(ma);

    pa__done(m);

    return -1;
}