void terminal::spawn_child(std::string i_command) { if ( m_terminal != NULL ) { GError *error = NULL; gchar **args = NULL; GSpawnFlags spawn_flags = G_SPAWN_SEARCH_PATH; if ( i_command.empty() ) { gchar *user_shell = vte_get_user_shell(); g_shell_parse_argv(user_shell, 0, &args, 0); g_free(user_shell); } else { g_shell_parse_argv(i_command.c_str(), 0, &args, 0); } vte_terminal_spawn_sync(m_terminal, VTE_PTY_DEFAULT, NULL, args, NULL, spawn_flags, NULL, NULL, &m_child_pid, NULL, &error); if ( error != NULL ) { sterm::common::warning("sterm::terminal", "failed to spawn child process"); sterm::common::debug("sterm::terminal", "VteTerminal error message: %s", error->message); g_error_free(error); } g_strfreev(args); } }
static void gb_terminal_respawn (GbTerminalView *self, VteTerminal *terminal) { g_autoptr(GPtrArray) args = NULL; g_autofree gchar *workpath = NULL; GtkWidget *toplevel; GError *error = NULL; IdeContext *context; IdeVcs *vcs; GFile *workdir; GPid child_pid; gint64 now; g_assert (GB_IS_TERMINAL_VIEW (self)); vte_terminal_reset (terminal, TRUE, TRUE); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); if (!IDE_IS_WORKBENCH (toplevel)) return; /* Prevent flapping */ now = g_get_monotonic_time (); if ((now - self->last_respawn) < (G_USEC_PER_SEC / 10)) return; self->last_respawn = now; context = ide_workbench_get_context (IDE_WORKBENCH (toplevel)); vcs = ide_context_get_vcs (context); workdir = ide_vcs_get_working_directory (vcs); workpath = g_file_get_path (workdir); args = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (args, vte_get_user_shell ()); g_ptr_array_add (args, NULL); vte_terminal_spawn_sync (terminal, VTE_PTY_DEFAULT | VTE_PTY_NO_LASTLOG | VTE_PTY_NO_UTMP | VTE_PTY_NO_WTMP, workpath, (gchar **)args->pdata, NULL, G_SPAWN_DEFAULT, NULL, NULL, &child_pid, NULL, &error); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); return; } vte_terminal_watch_child (terminal, child_pid); }
Terminal::Terminal() { dock_hint = GdkRectangle{0, 0, 0, 0}; vte = vte_terminal_new(); char *argv[] = { vte_get_user_shell(), NULL }; vte_terminal_spawn_sync(VTE_TERMINAL(vte), VTE_PTY_DEFAULT, NULL, argv, NULL, (GSpawnFlags)0, NULL, NULL, &child_pid, NULL, NULL); set_orientation(Gtk::ORIENTATION_VERTICAL); scrollbox.set_orientation(Gtk::ORIENTATION_HORIZONTAL); scrollbar.set_orientation(Gtk::ORIENTATION_VERTICAL); eventbox.add(label); eventbox.signal_button_press_event().connect(mem_fun(this, &Terminal::header_button_press)); VteRegex *regex = vte_regex_new_for_match("(https?://|www\\.)[^\\s]*", -1, PCRE2_MULTILINE, NULL); vte_terminal_match_add_regex(VTE_TERMINAL(vte), regex, 0); vte_terminal_set_scrollback_lines(VTE_TERMINAL(vte), 10000); g_signal_connect(vte, "bell", G_CALLBACK(Terminal::vte_beep), this); g_signal_connect(vte, "child-exited", G_CALLBACK(Terminal::vte_child_exited), this); g_signal_connect(vte, "button-press-event", G_CALLBACK(Terminal::vte_click), this); g_signal_connect(vte, "focus-in-event", G_CALLBACK(Terminal::vte_got_focus), this); g_signal_connect(vte, "focus-out-event", G_CALLBACK(Terminal::vte_lost_focus), this); g_signal_connect(vte, "selection-changed", G_CALLBACK(Terminal::vte_selection_changed), this); g_signal_connect(vte, "window-title-changed", G_CALLBACK(Terminal::vte_title_changed), this); searchbar.add(searchentry); searchbar.connect_entry(searchentry); searchentry.signal_focus_out_event().connect(mem_fun(this, &Terminal::searchentry_lost_focus)); searchentry.signal_key_release_event().connect(mem_fun(this, &Terminal::searchentry_keypress)); pack_start(eventbox, false, false, 0); pack_start(scrollbox, true, true, 0); pack_start(searchbar, false, false, 0); gtk_box_pack_start(GTK_BOX(scrollbox.gobj()), vte, true, true, 0); scrollbox.pack_start(scrollbar, false, false, 0); gtk_range_set_adjustment(GTK_RANGE(scrollbar.gobj()), gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vte))); show_all_children(); find_label.terminal = this; find_label.set_alignment(0.0, 0.5); find_window->list_box.prepend(find_label); std::vector<Gtk::TargetEntry> listTargets; listTargets.push_back(Gtk::TargetEntry("SvanTerminal", Gtk::TARGET_SAME_APP, 0)); eventbox.drag_source_set(listTargets); drag_dest_set(listTargets); eventbox.signal_drag_begin().connect(sigc::mem_fun(this, &Terminal::on_my_drag_begin)); eventbox.signal_drag_failed().connect(sigc::mem_fun(this, &Terminal::on_my_drag_failed)); eventbox.signal_drag_end().connect(sigc::mem_fun(this, &Terminal::on_my_drag_end)); signal_drag_motion().connect(sigc::mem_fun(this, &Terminal::on_my_drag_motion)); signal_drag_drop().connect(sigc::mem_fun(this, &Terminal::on_my_drag_drop)); signal_drag_leave().connect(sigc::mem_fun(this, &Terminal::on_my_drag_leave)); }
static void terminal_shell_vte(GtkWidget *terminal) { char *argv[2]; argv[0] = vte_get_user_shell (); argv[1] = NULL; vte_terminal_spawn_sync(VTE_TERMINAL(terminal), VTE_PTY_DEFAULT, g_get_home_dir() ? g_get_home_dir() : NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, NULL); }
static void vte_spawn(VteTerminal* vte, char* working_directory, char* command, char** environment) { GError* error = NULL; char** command_argv = NULL; /* Parse command into array */ if (!command) command = vte_get_user_shell(); g_shell_parse_argv(command, NULL, &command_argv, &error); if (error) { g_printerr("Failed to parse command: %s\n", error->message); g_error_free(error); exit(EXIT_FAILURE); } /* Create pty object */ VtePty* pty = vte_terminal_pty_new_sync(vte, VTE_PTY_NO_HELPER, NULL, &error); if (error) { g_printerr("Failed to create pty: %s\n", error->message); g_error_free(error); exit(EXIT_FAILURE); } vte_terminal_set_pty(vte, pty); int child_pid; /* Spawn default shell (or specified command) */ g_spawn_async(working_directory, command_argv, environment, (G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH | G_SPAWN_LEAVE_DESCRIPTORS_OPEN), // flags from GSpawnFlags (GSpawnChildSetupFunc)vte_pty_child_setup, // an extra child setup function to run in the child just before exec() pty, // user data for child_setup &child_pid, // a location to store the child PID &error); // return location for a GError if (error) { g_printerr("%s\n", error->message); g_error_free(error); exit(EXIT_FAILURE); } vte_terminal_watch_child(vte, child_pid); g_strfreev(command_argv); }
static void activate (GtkApplication* app, gpointer user_data) { GtkWidget *window; GtkWidget *bases, *keyLength, *errorBits, *errorTolerance, *playButton, *mode, *peerIp, *eveRate, *eveStrategy, *channelNoise, *genBias; GtkWidget *windowBox, *optionGrid, *playGrid, *playBox; GtkWidget *baseLabel, *keyLengthLabel, *errorBitsLabel, *errorToleranceLabel, *peerIpLabel, *eveRateLabel, *eveStrategyLabel, *channelNoiseLabel, *genBiasLabel; GtkWidget *tty1; GtkWidget *tty2; window = gtk_application_window_new (app); gtk_window_set_title (GTK_WINDOW (window), "Quantum Network Simulator"); gtk_window_set_default_size (GTK_WINDOW (window), 1280, 720); windowBox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL); gtk_container_add(GTK_CONTAINER(window), windowBox); playBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); gtk_container_add(GTK_CONTAINER(windowBox), playBox); optionGrid = gtk_grid_new (); gtk_container_add(GTK_CONTAINER(playBox), optionGrid); playGrid = gtk_grid_new (); gtk_grid_set_column_spacing(GTK_GRID(playGrid), 20); gtk_container_add(GTK_CONTAINER(playBox), playGrid); mode = gtk_combo_box_text_new (); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(mode), "Superposition Tutorial"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(mode), "Measurement Tutorial"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(mode), "Classic BB84 Tutorial"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(mode), "Polybase BB84 Tutorial"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(mode), "Bias BB84 Tutorial"); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT(mode), "Freestyle BB84"); gtk_grid_attach(GTK_GRID( optionGrid ), mode, 0, 0, 2, 1); baseLabel = gtk_label_new("Number of bases"); bases = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), baseLabel , 0, 1, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), bases , 1, 1, 1, 1); keyLengthLabel = gtk_label_new("Key Length"); keyLength = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), keyLengthLabel , 0, 2, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), keyLength, 1, 2, 1, 1); errorBitsLabel = gtk_label_new("Number of error detection bits"); errorBits = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorBitsLabel , 0, 3, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorBits , 1, 3, 1, 1); errorToleranceLabel = gtk_label_new("Number of error bits to tolerate"); errorTolerance = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorToleranceLabel , 0, 4, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorTolerance , 1, 4, 1, 1); errorToleranceLabel = gtk_label_new("Peer IP"); errorTolerance = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorToleranceLabel , 2, 0, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorTolerance , 3, 0, 1, 1); errorToleranceLabel = gtk_label_new("Eve Eavesdrop Rate"); errorTolerance = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorToleranceLabel , 2, 1, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorTolerance , 3, 1, 1, 1); errorToleranceLabel = gtk_label_new("Eve Eavesdrop Strategy"); errorTolerance = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorToleranceLabel , 2, 2, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorTolerance , 3, 2, 1, 1); errorToleranceLabel = gtk_label_new("Generator Bias"); errorTolerance = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorToleranceLabel , 2, 3, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorTolerance , 3, 3, 1, 1); errorToleranceLabel = gtk_label_new("Channel Noise"); errorTolerance = gtk_entry_new (); gtk_grid_attach(GTK_GRID( optionGrid ), errorToleranceLabel , 2, 4, 1, 1); gtk_grid_attach(GTK_GRID( optionGrid ), errorTolerance , 3, 4, 1, 1); playButton = gtk_button_new_with_label("PLAY QUANTUM ALGORITHM"); g_signal_connect (playButton, "clicked", G_CALLBACK(playAlgorithm), playButton); // g_signal_connect_swapped (playButton, "clicked", G_CALLBACK(gtk_widget_destroy), window); gtk_grid_attach(GTK_GRID( optionGrid ), playButton, 0, 5, 4, 1); char *startTerm[2] = {0,0}; startTerm[0] = vte_get_user_shell(); GPid pidTerm; tty1 = vte_terminal_new(); vte_terminal_fork_command_full(VTE_TERMINAL(tty1), VTE_PTY_DEFAULT, NULL, //"/tmp", startTerm, NULL, (GSpawnFlags)(G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH), NULL, NULL, NULL, NULL ); gtk_widget_set_size_request(tty1, 600, 400); gtk_grid_attach(GTK_GRID (playGrid ), tty1, 0, 6, 4, 15); gtk_widget_set_sensitive(tty1, FALSE); tty2 = vte_terminal_new(); vte_terminal_fork_command_full(VTE_TERMINAL(tty2), VTE_PTY_DEFAULT, NULL, //"/tmp", startTerm, NULL, (GSpawnFlags)(G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH), NULL, NULL, NULL, NULL ); gtk_widget_set_size_request(tty2, 600, 400); gtk_grid_attach(GTK_GRID (playGrid ), tty2, 4, 6, 4, 15); gtk_widget_set_sensitive(tty2, FALSE); g_object_set_data(G_OBJECT(playButton), "tty1", VTE_TERMINAL(tty1)); g_object_set_data(G_OBJECT(playButton), "tty2", VTE_TERMINAL(tty2)); g_object_set_data(G_OBJECT(playButton), "in_mode", GTK_COMBO_BOX_TEXT(mode)); g_object_set_data(G_OBJECT(playButton), "in_bases", GTK_ENTRY(bases)); g_object_set_data(G_OBJECT(playButton), "in_keyLength", GTK_ENTRY(keyLength)); g_object_set_data(G_OBJECT(playButton), "in_errorBits", GTK_ENTRY(errorBits)); g_object_set_data(G_OBJECT(playButton), "in_errorTolerance", GTK_ENTRY(errorTolerance)); gtk_widget_show_all (window); }
gboolean setup_term(GtkWidget *win, GtkWidget *term, struct term_options *to) { static char *args_default[] = { NULL, NULL, NULL }; char **args_use; size_t i; GdkRGBA c_foreground_gdk; GdkRGBA c_background_gdk; GdkRGBA c_palette_gdk[16]; GdkRGBA c_gdk; VteRegex *url_vregex = NULL; GError *err = NULL; GSpawnFlags spawn_flags; if (to->argv != NULL) { args_use = to->argv; spawn_flags = G_SPAWN_SEARCH_PATH; } else { if (args_default[0] == NULL) { args_default[0] = vte_get_user_shell(); if (args_default[0] == NULL) args_default[0] = "/bin/sh"; if (login_shell) args_default[1] = g_strdup_printf("-%s", args_default[0]); else args_default[1] = args_default[0]; } args_use = args_default; spawn_flags = G_SPAWN_SEARCH_PATH | G_SPAWN_FILE_AND_ARGV_ZERO; } /* Appearance. */ term_set_font(NULL, VTE_TERMINAL(term), 0); gtk_widget_show_all(win); vte_terminal_set_allow_bold(VTE_TERMINAL(term), enable_bold); vte_terminal_set_cursor_blink_mode(VTE_TERMINAL(term), VTE_CURSOR_BLINK_OFF); vte_terminal_set_geometry_hints_for_window(VTE_TERMINAL(term), GTK_WINDOW(win)); vte_terminal_set_mouse_autohide(VTE_TERMINAL(term), TRUE); vte_terminal_set_scrollback_lines(VTE_TERMINAL(term), scrollback_lines); gdk_rgba_parse(&c_foreground_gdk, c_foreground); gdk_rgba_parse(&c_background_gdk, c_background); for (i = 0; i < 16; i++) gdk_rgba_parse(&c_palette_gdk[i], c_palette[i]); vte_terminal_set_colors(VTE_TERMINAL(term), &c_foreground_gdk, &c_background_gdk, c_palette_gdk, 16); if (c_bold != NULL) { gdk_rgba_parse(&c_gdk, c_bold); vte_terminal_set_color_bold(VTE_TERMINAL(term), &c_gdk); } if (c_cursor != NULL) { gdk_rgba_parse(&c_gdk, c_cursor); vte_terminal_set_color_cursor(VTE_TERMINAL(term), &c_gdk); } if (c_cursor_foreground != NULL) { gdk_rgba_parse(&c_gdk, c_cursor_foreground); vte_terminal_set_color_cursor_foreground(VTE_TERMINAL(term), &c_gdk); } url_vregex = vte_regex_new_for_match(url_regex, strlen(url_regex), PCRE2_MULTILINE | PCRE2_CASELESS, &err); if (url_vregex == NULL) fprintf(stderr, "url_regex: %s\n", err == NULL ? "<err is NULL>" : err->message); else { vte_terminal_match_add_regex(VTE_TERMINAL(term), url_vregex, 0); vte_regex_unref(url_vregex); } /* Signals. */ g_signal_connect(G_OBJECT(term), "bell", G_CALLBACK(sig_bell), win); g_signal_connect(G_OBJECT(term), "button-press-event", G_CALLBACK(sig_button_press), NULL); if (!to->hold) g_signal_connect(G_OBJECT(term), "child-exited", G_CALLBACK(sig_child_exited), win); g_signal_connect(G_OBJECT(term), "decrease-font-size", G_CALLBACK(sig_decrease_font_size), win); g_signal_connect(G_OBJECT(term), "increase-font-size", G_CALLBACK(sig_increase_font_size), win); g_signal_connect(G_OBJECT(term), "key-press-event", G_CALLBACK(sig_key_press), win); g_signal_connect(G_OBJECT(term), "resize-window", G_CALLBACK(sig_window_resize), win); g_signal_connect(G_OBJECT(term), "window-title-changed", G_CALLBACK(sig_window_title_changed), win); /* Spawn child. */ return vte_terminal_spawn_sync(VTE_TERMINAL(term), VTE_PTY_DEFAULT, to->cwd, args_use, NULL, spawn_flags, NULL, NULL, NULL, NULL, NULL); }
static void gb_terminal_respawn (GbTerminalView *self, VteTerminal *terminal) { g_autoptr(GPtrArray) args = NULL; g_autoptr(IdeSubprocess) subprocess = NULL; g_autoptr(IdeSubprocessLauncher) launcher = NULL; g_autofree gchar *workpath = NULL; g_autofree gchar *shell = NULL; GtkWidget *toplevel; GError *error = NULL; IdeContext *context; IdeVcs *vcs; VtePty *pty = NULL; GFile *workdir; gint64 now; int tty_fd = -1; gint stdout_fd = -1; gint stderr_fd = -1; IDE_ENTRY; g_assert (GB_IS_TERMINAL_VIEW (self)); vte_terminal_reset (terminal, TRUE, TRUE); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); if (!IDE_IS_WORKBENCH (toplevel)) IDE_EXIT; /* Prevent flapping */ now = g_get_monotonic_time (); if ((now - self->last_respawn) < (G_USEC_PER_SEC / 10)) IDE_EXIT; self->last_respawn = now; context = ide_workbench_get_context (IDE_WORKBENCH (toplevel)); vcs = ide_context_get_vcs (context); workdir = ide_vcs_get_working_directory (vcs); workpath = g_file_get_path (workdir); shell = gb_terminal_view_discover_shell (NULL, &error); if (shell == NULL) { g_warning ("Failed to discover user shell: %s", error->message); /* We prefer bash in flatpak over sh */ if (ide_is_flatpak ()) shell = g_strdup ("/bin/bash"); else shell = vte_get_user_shell (); g_clear_error (&error); } args = g_ptr_array_new (); g_ptr_array_add (args, (gchar *)shell); g_ptr_array_add (args, NULL); pty = vte_terminal_pty_new_sync (terminal, VTE_PTY_DEFAULT | VTE_PTY_NO_LASTLOG | VTE_PTY_NO_UTMP | VTE_PTY_NO_WTMP, NULL, &error); if (pty == NULL) IDE_GOTO (failure); vte_terminal_set_pty (terminal, pty); if (-1 == (tty_fd = gb_vte_pty_create_slave (pty))) IDE_GOTO (failure); /* dup() is safe as it will inherit O_CLOEXEC */ if (-1 == (stdout_fd = dup (tty_fd)) || -1 == (stderr_fd = dup (tty_fd))) IDE_GOTO (failure); /* XXX: It would be nice to allow using the runtimes launcher */ launcher = ide_subprocess_launcher_new (0); ide_subprocess_launcher_set_run_on_host (launcher, TRUE); ide_subprocess_launcher_set_clear_env (launcher, FALSE); ide_subprocess_launcher_set_cwd (launcher, workpath); ide_subprocess_launcher_push_args (launcher, (const gchar * const *)args->pdata); ide_subprocess_launcher_take_stdin_fd (launcher, tty_fd); ide_subprocess_launcher_take_stdout_fd (launcher, stdout_fd); ide_subprocess_launcher_take_stderr_fd (launcher, stderr_fd); ide_subprocess_launcher_setenv (launcher, "TERM", "xterm-256color", TRUE); ide_subprocess_launcher_setenv (launcher, "INSIDE_GNOME_BUILDER", PACKAGE_VERSION, TRUE); ide_subprocess_launcher_setenv (launcher, "SHELL", shell, TRUE); tty_fd = -1; stdout_fd = -1; stderr_fd = -1; if (NULL == (subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error))) IDE_GOTO (failure); ide_subprocess_wait_async (subprocess, NULL, gb_terminal_view_wait_cb, g_object_ref (terminal)); failure: if (tty_fd != -1) close (tty_fd); if (stdout_fd != -1) close (stdout_fd); g_clear_object (&pty); if (error != NULL) { g_warning ("%s", error->message); g_clear_error (&error); } IDE_EXIT; }