static void CreateHelper(EscalateHelper **helper, GIOChannel **stdin_writer, GIOChannel **stdout_reader) { int stdin_fds [2]; int stdout_fds [2]; g_assert(g_unix_open_pipe(stdin_fds, 0, NULL)); g_assert(g_unix_open_pipe(stdout_fds, 0, NULL)); *helper = EscalateHelperNew(stdin_fds[0], stdout_fds[1]); *stdin_writer = g_io_channel_unix_new(stdin_fds[1]); *stdout_reader = g_io_channel_unix_new(stdout_fds[0]); g_assert(*helper); }
/** * g_wakeup_new: * * Creates a new #GWakeup. * * You should use g_wakeup_free() to free it when you are done. * * Returns: a new #GWakeup * * Since: 2.30 **/ GWakeup * g_wakeup_new (void) { GError *error = NULL; GWakeup *wakeup; wakeup = g_slice_new (GWakeup); /* try eventfd first, if we think we can */ #if defined (HAVE_EVENTFD) #ifndef TEST_EVENTFD_FALLBACK wakeup->fds[0] = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK); #else wakeup->fds[0] = -1; #endif if (wakeup->fds[0] != -1) { wakeup->fds[1] = -1; return wakeup; } /* for any failure, try a pipe instead */ #endif if (!g_unix_open_pipe (wakeup->fds, FD_CLOEXEC, &error)) g_error ("Creating pipes for GWakeup: %s\n", error->message); if (!g_unix_set_fd_nonblocking (wakeup->fds[0], TRUE, &error) || !g_unix_set_fd_nonblocking (wakeup->fds[1], TRUE, &error)) g_error ("Set pipes non-blocking for GWakeup: %s\n", error->message); return wakeup; }
static void TestWrite(gconstpointer user_data) { guint index = GPOINTER_TO_UINT(user_data); gint fds [] = { 0, 0 }; GIOChannel *reader = NULL; GIOChannel *writer = NULL; GThread *thread = NULL; EscalateMessage *message = NULL; GError *error = NULL; gboolean success = FALSE; gchar *result = NULL; g_assert(g_unix_open_pipe(fds, 0, NULL)); reader = g_io_channel_unix_new(fds[0]); writer = g_io_channel_unix_new(fds[1]); thread = g_thread_new("Reader", (GThreadFunc) ReaderThread, reader); message = EscalateMessageLoad(example_messages[index], NULL); g_assert(message); success = EscalateMessageWrite(message, writer, &error); g_assert_no_error(error); g_assert(success); g_assert_cmpint(G_IO_STATUS_NORMAL, ==, g_io_channel_shutdown(writer, TRUE, NULL)); result = (gchar *) g_thread_join(thread); result[strlen(result)-1] = '\0'; // Cut off newline. g_assert_cmpstr(example_messages[index], ==, result); g_io_channel_unref(reader); g_io_channel_unref(writer); EscalateMessageUnref(message); g_free(result); }
gboolean __wrap_g_spawn_async_with_pipes(const gchar *working_directory, gchar **argv, gchar **envp, GSpawnFlags flags, GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid, gint *standard_input, gint *standard_output, gint *standard_error, GError **error) { int standard_input_fds [2] = { 0, 0 }; int standard_output_fds [2] = { 0, 0 }; pid_t pid = 0; g_assert_cmpstr("/", ==, working_directory); g_assert(argv); g_assert_cmpstr("/usr/bin/pam-escalate-helper", ==, argv[0]); g_assert_cmpstr(NULL, ==, argv[1]); g_assert(!envp); g_assert_cmpint(0, ==, flags); g_assert(!child_setup); g_assert(!user_data); g_assert(child_pid); g_assert(standard_input); g_assert(standard_output); g_assert(!standard_error); g_assert(g_unix_open_pipe(standard_input_fds, 0, NULL)); g_assert(g_unix_open_pipe(standard_output_fds, 0, NULL)); pid = fork(); if (pid) { close(standard_input_fds[0]); close(standard_output_fds[1]); *child_pid = pid; *standard_input = standard_input_fds[1]; *standard_output = standard_output_fds[0]; return TRUE; } else { close(standard_input_fds[1]); close(standard_output_fds[0]); exit(EscalateTestMockHelperProcess(standard_input_fds[0], standard_output_fds[1])); } }
static void TestRead(gconstpointer user_data) { guint index = GPOINTER_TO_UINT(user_data); gint fds [] = { 0, 0 }; GIOChannel *reader = NULL; WriterThreadContext thread_ctx = { NULL, NULL }; GThread *thread = NULL; GError *error = NULL; EscalateMessage *message = NULL; GVariant *expected_values = CreateExampleMessageValues(index); g_assert(g_unix_open_pipe(fds, 0, NULL)); reader = g_io_channel_unix_new(fds[0]); thread_ctx.channel = g_io_channel_unix_new(fds[1]); thread_ctx.contents = example_messages[index]; thread = g_thread_new("Writer", (GThreadFunc) WriterThread, &thread_ctx); g_assert(thread); message = EscalateMessageRead(reader, &error); g_assert_no_error(error); g_assert(message); g_assert_cmpint(EscalateMessageGetType(message), ==, example_message_types[index]); g_assert(g_variant_equal(expected_values, message->values)); EscalateMessageUnref(message); message = EscalateMessageRead(reader, &error); g_assert_error(error, ESCALATE_MESSAGE_ERROR, ESCALATE_MESSAGE_ERROR_EOF); g_assert(!message); g_error_free(error); g_thread_join(thread); g_variant_unref(expected_values); g_io_channel_shutdown(reader, FALSE, NULL); g_io_channel_unref(reader); g_io_channel_unref(thread_ctx.channel); }
void _gdk_wayland_display_convert_selection (GdkDisplay *display, GdkWindow *requestor, GdkAtom selection, GdkAtom target, guint32 time) { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); SelectionBuffer *buffer_data; if (!wayland_selection->offer) { GdkEvent *event; event = gdk_event_new (GDK_SELECTION_NOTIFY); event->selection.window = g_object_ref (requestor); event->selection.send_event = FALSE; event->selection.selection = selection; event->selection.target = target; event->selection.property = GDK_NONE; event->selection.time = GDK_CURRENT_TIME; event->selection.requestor = g_object_ref (requestor); gdk_event_put (event); gdk_event_free (event); return; } wl_data_offer_accept (wayland_selection->offer, _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)), gdk_atom_name (target)); buffer_data = g_hash_table_lookup (wayland_selection->selection_buffers, target); if (buffer_data) selection_buffer_add_requestor (buffer_data, requestor); else { GInputStream *stream = NULL; int pipe_fd[2], natoms = 0; GdkAtom *atoms = NULL; if (target == gdk_atom_intern_static_string ("TARGETS")) { gint i = 0; GList *l; natoms = g_list_length (wayland_selection->targets); atoms = g_new0 (GdkAtom, natoms); for (l = wayland_selection->targets; l; l = l->next) atoms[i++] = l->data; } else { g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL); wl_data_offer_receive (wayland_selection->offer, gdk_atom_name (target), pipe_fd[1]); stream = g_unix_input_stream_new (pipe_fd[0], TRUE); close (pipe_fd[1]); } buffer_data = selection_buffer_new (stream, selection, target); selection_buffer_add_requestor (buffer_data, requestor); if (stream) g_object_unref (stream); if (atoms) { /* Store directly the local atoms */ selection_buffer_append_data (buffer_data, atoms, natoms * sizeof (GdkAtom)); g_free (atoms); } g_hash_table_insert (wayland_selection->selection_buffers, GDK_ATOM_TO_POINTER (target), buffer_data); } if (!buffer_data->stream) selection_buffer_notify (buffer_data); }
static gboolean spawn_bus (State *state, GCancellable *cancellable) { GPtrArray *arguments = NULL; GSubprocessLauncher *launcher = NULL; GSubprocess *subprocess = NULL; GInputStream *input_stream = NULL; GDataInputStream *data_stream = NULL; GError *error = NULL; const char *bus_env = NULL; char *bus_address_fd_string; char *bus_address = NULL; gsize bus_address_size; gboolean is_running = FALSE; int ret; int pipe_fds[2]; g_debug ("Running session message bus"); bus_env = g_getenv ("DBUS_SESSION_BUS_ADDRESS"); if (bus_env != NULL) { g_debug ("session message bus already running, not starting another one"); state->bus_address = g_strdup (bus_env); return TRUE; } ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error); if (!ret) { g_debug ("could not open pipe: %s", error->message); goto out; } arguments = g_ptr_array_new (); launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); g_subprocess_launcher_setenv (launcher, "DISPLAY", state->display_name, TRUE); g_subprocess_launcher_setenv (launcher, "XAUTHORITY", state->auth_file, TRUE); g_subprocess_launcher_take_fd (launcher, pipe_fds[1], BUS_ADDRESS_FILENO); bus_address_fd_string = g_strdup_printf ("%d", BUS_ADDRESS_FILENO); g_ptr_array_add (arguments, "dbus-daemon"); g_ptr_array_add (arguments, "--print-address"); g_ptr_array_add (arguments, bus_address_fd_string); g_ptr_array_add (arguments, "--session"); g_ptr_array_add (arguments, NULL); subprocess = g_subprocess_launcher_spawnv (launcher, (const char * const *) arguments->pdata, &error); g_free (bus_address_fd_string); g_clear_object (&launcher); g_ptr_array_free (arguments, TRUE); if (subprocess == NULL) { g_debug ("could not start dbus-daemon: %s", error->message); goto out; } input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE); data_stream = g_data_input_stream_new (input_stream); g_clear_object (&input_stream); bus_address = g_data_input_stream_read_line (data_stream, &bus_address_size, cancellable, &error); if (error != NULL) { g_debug ("could not read address from session message bus: %s", error->message); goto out; } if (bus_address == NULL) { g_debug ("session message bus did not write address"); goto out; } state->bus_address = bus_address; state->bus_subprocess = g_object_ref (subprocess); g_subprocess_wait_async (state->bus_subprocess, cancellable, (GAsyncReadyCallback) on_bus_finished, state); is_running = TRUE; out: g_clear_object (&data_stream); g_clear_object (&subprocess); g_clear_object (&launcher); g_clear_error (&error); return is_running; }
static gboolean spawn_x_server (State *state, gboolean allow_remote_connections, GCancellable *cancellable) { GPtrArray *arguments = NULL; GSubprocessLauncher *launcher = NULL; GSubprocess *subprocess = NULL; GInputStream *input_stream = NULL; GDataInputStream *data_stream = NULL; GError *error = NULL; char *auth_file; gboolean is_running = FALSE; int ret; int pipe_fds[2]; char *display_fd_string = NULL; char *vt_string = NULL; char *display_number; gsize display_number_size; auth_file = prepare_auth_file (); g_debug ("Running X server"); ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error); if (!ret) { g_debug ("could not open pipe: %s", error->message); goto out; } arguments = g_ptr_array_new (); launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_INHERIT); g_subprocess_launcher_setenv (launcher, "XORG_RUN_AS_USER_OK", "1", TRUE); g_subprocess_launcher_take_fd (launcher, pipe_fds[1], DISPLAY_FILENO); if (g_getenv ("XDG_VTNR") != NULL) { int vt; vt = atoi (g_getenv ("XDG_VTNR")); if (vt > 0 && vt < 64) { vt_string = g_strdup_printf ("vt%d", vt); } } display_fd_string = g_strdup_printf ("%d", DISPLAY_FILENO); g_ptr_array_add (arguments, X_SERVER); if (vt_string != NULL) { g_ptr_array_add (arguments, vt_string); } g_ptr_array_add (arguments, "-displayfd"); g_ptr_array_add (arguments, display_fd_string); g_ptr_array_add (arguments, "-auth"); g_ptr_array_add (arguments, auth_file); /* If we were compiled with Xserver >= 1.17 we need to specify * '-listen tcp' as the X server dosen't listen on tcp sockets * by default anymore. In older versions we need to pass * -nolisten tcp to disable listening on tcp sockets. */ #ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY if (allow_remote_connections) { g_ptr_array_add (arguments, "-listen"); g_ptr_array_add (arguments, "tcp"); } #else if (!allow_remote_connections) { g_ptr_array_add (arguments, "-nolisten"); g_ptr_array_add (arguments, "tcp"); } #endif g_ptr_array_add (arguments, "-background"); g_ptr_array_add (arguments, "none"); g_ptr_array_add (arguments, "-noreset"); g_ptr_array_add (arguments, "-keeptty"); g_ptr_array_add (arguments, "-verbose"); if (state->debug_enabled) { g_ptr_array_add (arguments, "7"); } else { g_ptr_array_add (arguments, "3"); } if (state->debug_enabled) { g_ptr_array_add (arguments, "-core"); } g_ptr_array_add (arguments, NULL); subprocess = g_subprocess_launcher_spawnv (launcher, (const char * const *) arguments->pdata, &error); g_free (display_fd_string); g_clear_object (&launcher); g_ptr_array_free (arguments, TRUE); if (subprocess == NULL) { g_debug ("could not start X server: %s", error->message); goto out; } input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE); data_stream = g_data_input_stream_new (input_stream); g_clear_object (&input_stream); display_number = g_data_input_stream_read_line (data_stream, &display_number_size, cancellable, &error); if (error != NULL) { g_debug ("could not read display string from X server: %s", error->message); goto out; } if (display_number == NULL) { g_debug ("X server did not write display string"); goto out; } state->display_name = g_strdup_printf (":%s", display_number); g_clear_pointer (&display_number, g_free); state->auth_file = g_strdup (auth_file); state->x_subprocess = g_object_ref (subprocess); g_subprocess_wait_async (state->x_subprocess, cancellable, (GAsyncReadyCallback) on_x_server_finished, state); is_running = TRUE; out: g_clear_pointer (&auth_file, g_free); g_clear_object (&data_stream); g_clear_object (&subprocess); g_clear_object (&launcher); g_clear_error (&error); return is_running; }
static gboolean launch_test_binary (const char *binary, guint skip_tests) { GTestLogBuffer *tlb; GSList *slist, *free_list = NULL; GError *error = NULL; int argc = 0; const gchar **argv; GPid pid = 0; gint report_pipe[2] = { -1, -1 }; guint child_report_cb_id = 0; gboolean loop_pending; gint i = 0; if (!g_unix_open_pipe (report_pipe, FD_CLOEXEC, &error)) { if (subtest_mode_fatal) g_error ("Failed to open pipe for test binary: %s: %s", binary, error->message); else g_warning ("Failed to open pipe for test binary: %s: %s", binary, error->message); g_clear_error (&error); return FALSE; } /* setup argc */ for (slist = subtest_args; slist; slist = slist->next) argc++; /* argc++; */ if (subtest_quiet) argc++; if (subtest_verbose) argc++; if (!subtest_mode_fatal) argc++; /* Either -m=quick or -m=slow is always appended. */ argc++; if (subtest_mode_perf) argc++; if (!subtest_mode_undefined) argc++; if (gtester_list_tests) argc++; if (subtest_seedstr) argc++; argc++; if (skip_tests) argc++; for (slist = subtest_paths; slist; slist = slist->next) argc++; for (slist = skipped_paths; slist; slist = slist->next) argc++; /* setup argv */ argv = g_malloc ((argc + 2) * sizeof(gchar *)); argv[i++] = binary; for (slist = subtest_args; slist; slist = slist->next) argv[i++] = (gchar*) slist->data; /* argv[i++] = "--debug-log"; */ if (subtest_quiet) argv[i++] = "--quiet"; if (subtest_verbose) argv[i++] = "--verbose"; if (!subtest_mode_fatal) argv[i++] = "--keep-going"; if (subtest_mode_quick) argv[i++] = "-m=quick"; else argv[i++] = "-m=slow"; if (subtest_mode_perf) argv[i++] = "-m=perf"; if (!subtest_mode_undefined) argv[i++] = "-m=no-undefined"; if (gtester_list_tests) argv[i++] = "-l"; if (subtest_seedstr) argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr)); argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1])); if (skip_tests) argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestSkipCount=%u", skip_tests)); for (slist = subtest_paths; slist; slist = slist->next) argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data)); for (slist = skipped_paths; slist; slist = slist->next) argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-s=%s", (gchar*) slist->data)); argv[i++] = NULL; g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */ (gchar**) argv, NULL, /* envp */ G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */ unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */ &pid, NULL, /* standard_input */ NULL, /* standard_output */ NULL, /* standard_error */ &error); g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL); g_slist_free (free_list); free_list = NULL; close (report_pipe[1]); if (!gtester_quiet) g_print ("(pid=%lu)\n", (unsigned long) pid); if (error) { close (report_pipe[0]); if (subtest_mode_fatal) g_error ("Failed to execute test binary: %s: %s", argv[0], error->message); else g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message); g_clear_error (&error); g_free (argv); return FALSE; } g_free (argv); subtest_running = TRUE; subtest_io_pending = TRUE; tlb = g_test_log_buffer_new(); if (report_pipe[0] >= 0) { ioc_report = g_io_channel_unix_new (report_pipe[0]); g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL); g_io_channel_set_encoding (ioc_report, NULL, NULL); g_io_channel_set_buffered (ioc_report, FALSE); child_report_cb_id = g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL); g_io_channel_unref (ioc_report); } g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL); loop_pending = g_main_context_pending (NULL); while (subtest_running || /* FALSE once child exits */ subtest_io_pending || /* FALSE once ioc_report closes */ loop_pending) /* TRUE while idler, etc are running */ { /* g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending); */ /* check for unexpected hangs that are not signalled on report_pipe */ if (!subtest_running && /* child exited */ subtest_io_pending && /* no EOF detected on report_pipe */ !loop_pending) /* no IO events pending however */ break; g_main_context_iteration (NULL, TRUE); loop_pending = g_main_context_pending (NULL); } if (subtest_io_pending) g_source_remove (child_report_cb_id); close (report_pipe[0]); g_test_log_buffer_free (tlb); return TRUE; }
static void test_once (Fixture *f, gconstpointer context) { GDBusMessage *message; gboolean pipe_res; pipe_res = g_unix_open_pipe (f->server_to_client, FD_CLOEXEC, &f->error); g_assert (pipe_res); pipe_res = g_unix_open_pipe (f->client_to_server, FD_CLOEXEC, &f->error); g_assert (pipe_res); f->server_iostream = my_io_stream_new_for_fds (f->client_to_server[0], f->server_to_client[1]); f->iostream = my_io_stream_new_for_fds (f->server_to_client[0], f->client_to_server[1]); g_dbus_connection_new (f->server_iostream, f->guid, (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS), NULL /* auth observer */, NULL /* cancellable */, on_new_conn, &f->server_conn); g_dbus_connection_new (f->iostream, NULL, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL /* auth observer */, NULL /* cancellable */, on_new_conn, &f->connection); while (f->server_conn == NULL || f->connection == NULL) g_main_context_iteration (NULL, TRUE); /* * queue a message - it'll sometimes be sent while the close is pending, * triggering the bug */ message = g_dbus_message_new_signal ("/", "com.example.Foo", "Bar"); g_dbus_connection_send_message (f->connection, message, 0, NULL, &f->error); g_assert_no_error (f->error); g_object_unref (message); /* close the connection (deliberately or via last-unref) */ if (g_strcmp0 (context, "unref") == 0) { g_clear_object (&f->connection); } else { g_dbus_connection_close_sync (f->connection, NULL, &f->error); g_assert_no_error (f->error); } /* either way, wait for the connection to close */ while (!g_dbus_connection_is_closed (f->server_conn)) g_main_context_iteration (NULL, TRUE); /* clean up before the next run */ g_clear_object (&f->iostream); g_clear_object (&f->server_iostream); g_clear_object (&f->connection); g_clear_object (&f->server_conn); g_clear_error (&f->error); }
void _gdk_wayland_display_convert_selection (GdkDisplay *display, GdkWindow *requestor, GdkAtom selection, GdkAtom target, guint32 time) { GdkWaylandSelection *wayland_selection = gdk_wayland_display_get_selection (display); const SelectionData *selection_data; SelectionBuffer *buffer_data; gpointer offer; gchar *mimetype; GList *target_list; selection_data = selection_lookup_offer_by_atom (wayland_selection, selection); if (!selection_data) return; offer = gdk_wayland_selection_get_offer (display, selection); target_list = gdk_wayland_selection_get_targets (display, selection); if (!offer || target == gdk_atom_intern_static_string ("DELETE")) { emit_empty_selection_notify (requestor, selection, target); return; } mimetype = gdk_atom_name (target); if (target != gdk_atom_intern_static_string ("TARGETS")) { if (!g_list_find (target_list, GDK_ATOM_TO_POINTER (target))) { emit_empty_selection_notify (requestor, selection, target); return; } if (selection != atoms[ATOM_PRIMARY]) wl_data_offer_accept (offer, _gdk_wayland_display_get_serial (GDK_WAYLAND_DISPLAY (display)), mimetype); } buffer_data = g_hash_table_lookup (selection_data->buffers, target); if (buffer_data) selection_buffer_add_requestor (buffer_data, requestor); else { GInputStream *stream = NULL; int pipe_fd[2], natoms = 0; GdkAtom *targets = NULL; if (target == gdk_atom_intern_static_string ("TARGETS")) { gint i = 0; GList *l; natoms = g_list_length (target_list); targets = g_new0 (GdkAtom, natoms); for (l = target_list; l; l = l->next) targets[i++] = l->data; } else { g_unix_open_pipe (pipe_fd, FD_CLOEXEC, NULL); if (selection == atoms[ATOM_PRIMARY]) gtk_primary_selection_offer_receive (offer, mimetype, pipe_fd[1]); else wl_data_offer_receive (offer, mimetype, pipe_fd[1]); stream = g_unix_input_stream_new (pipe_fd[0], TRUE); close (pipe_fd[1]); } buffer_data = selection_buffer_new (stream, selection, target); selection_buffer_add_requestor (buffer_data, requestor); if (stream) g_object_unref (stream); if (targets) { /* Store directly the local atoms */ selection_buffer_append_data (buffer_data, targets, natoms * sizeof (GdkAtom)); g_free (targets); } g_hash_table_insert (selection_data->buffers, GDK_ATOM_TO_POINTER (target), buffer_data); } if (!buffer_data->stream) selection_buffer_notify (buffer_data); g_free (mimetype); }