// Check whether LINE is a valid PS line. Exclude occurrences of PS_COMMAND. static bool valid_ps_line(const string& line, const string& ps_command) { int pid = ps_pid(line); if (pid == 0) return false; // No PID // You don't want to debug DDD, don't you? if (!remote_gdb() && pid == getpid()) return false; // Neither should you debug GDB by itself. if (pid == gdb->pid()) return false; // Don't issue lines containing `ps' (or whatever the first word // in PS_COMMAND is). string ps = ps_command; if (ps.contains(' ')) ps = ps.before(' '); ps = basename(ps.chars()); int index = line.index(ps); if (index > 0 && (line[index - 1] == '/' || is_separator(line[index - 1])) && (line.length() == index + ps.length() || is_separator(line[index + ps.length()]))) return false; // Okay, just leave it return true; }
// Create a file dialog NAME with DO_SEARCH_FILES and DO_SEARCH_DIRS // as search procedures for files and directories, respectively, and // OK_CALLBACK as the procedure called when a file is selected. static Widget file_dialog(Widget w, const string& name, FileSearchProc do_search_files = 0, FileSearchProc do_search_dirs = 0, XtCallbackProc ok_callback = 0) { Delay delay(w); Arg args[10]; int arg = 0; string pwd; arg = 0; if (do_search_files) { XtSetArg(args[arg], XmNfileSearchProc, do_search_files); arg++; } if (do_search_dirs) { XtSetArg(args[arg], XmNdirSearchProc, do_search_dirs); arg++; } if (remote_gdb()) { static MString xmpwd; xmpwd = source_view->pwd(); XtSetArg(args[arg], XmNdirectory, xmpwd.xmstring()); arg++; } Widget dialog = verify(XmCreateFileSelectionDialog(w, XMST(name.chars()), args, arg)); Delay::register_shell(dialog); if (ok_callback != 0) XtAddCallback(dialog, XmNokCallback, ok_callback, 0); XtAddCallback(dialog, XmNcancelCallback, UnmanageThisCB, XtPointer(dialog)); XtAddCallback(dialog, XmNhelpCallback, ImmediateHelpCB, 0); Widget filter = XmFileSelectionBoxGetChild(dialog, XmDIALOG_FILTER_TEXT); file_filters += filter; if (!current_file_filter.empty()) XmTextSetString(filter, XMST(current_file_filter.chars())); XtAddCallback(filter, XmNvalueChangedCallback, SyncFiltersCB, 0); Widget filter_button = XmFileSelectionBoxGetChild(dialog, XmDIALOG_APPLY_BUTTON); XtAddCallback(filter_button, XmNactivateCallback, FilterAllCB, 0); XtAddCallback(dialog, XmNunmapCallback, ClearStatusCB, 0); file_dialogs += dialog; return dialog; }
string _sh_command(string command, bool force_local, bool force_display_settings) { // Fetch display settings string display; if (command_shell != 0) display = XDisplayString(XtDisplay(command_shell)); else if (getenv("DISPLAY") != 0) display = getenv("DISPLAY"); else display = ""; // Make sure display contains host name if (display.contains("unix:", 0) || display.contains(":", 0)) { display = string(hostname()) + display.from(":"); } // Make sure display contains fully qualified host name if (display.contains(":") && !display.contains("::")) { string host = display.before(':'); display = string(fullhostname(host.chars())) + display.from(":"); } string settings = ""; if (!display.empty()) { settings += "DISPLAY=${DISPLAY-" + sh_quote(display) + "}; export DISPLAY; "; } settings += set_environment_command(); if (force_local || !remote_gdb()) { if (command.empty()) return ""; if (force_display_settings) command = settings + command; return "/bin/sh -c " + sh_quote(command); } string rsh = app_data.rsh_command; const string login = app_data.debugger_host_login; if (!login.empty()) rsh += " -l " + login; rsh += " " + gdb_host; if (!command.empty()) rsh += " /bin/sh -c " + sh_quote(sh_quote(settings + command)); return rsh; }
static void update_recent_menu(const MMDesc *items) { StringArray recent_files; { StringArray r; get_recent(r); for (int i = 0; i < r.size() && items[i].widget != 0; i++) recent_files += r[i]; } // Uniquify labels char sep = '/'; if (gdb->type() == JDB) sep = '.'; StringArray labels; uniquify(recent_files, labels, sep); // Set labels int i; for (i = 0; i < labels.size(); i++) { MString label(itostring(i + 1) + " "); label += tt(labels[i]); Widget w = items[i].widget; set_label(w, label); const string& file = recent_files[i]; bool sens = true; if (!remote_gdb()) { if (gdb->has_exec_files() && !is_debuggee_file(file)) sens = false; // File not accessible else if (!gdb->has_classes() && !is_regular_file(file)) sens = false; // File not accessible } set_sensitive(w, sens); XtManageChild(w); } // Unmanage remaining items for (; items[i].widget != 0; i++) XtUnmanageChild(items[i].widget); }
// Create various file dialogs static Widget create_file_dialog(Widget w, const _XtString name, FileSearchProc searchRemoteFiles = 0, FileSearchProc searchRemoteDirectories = 0, FileSearchProc searchLocalFiles = 0, FileSearchProc searchLocalDirectories = 0, XtCallbackProc openDone = 0) { if (remote_gdb()) return file_dialog(find_shell(w), name, searchRemoteFiles, searchRemoteDirectories, openDone); else if (app_data.filter_files) return file_dialog(find_shell(w), name, searchLocalFiles, searchLocalDirectories, openDone); else return file_dialog(find_shell(w), name, 0, 0, openDone); }
// Add FILE to recent file history void add_to_recent(const string& file) { string full_path; if (gdb->type() != JDB) full_path = SourceView::full_path(file); else full_path = file; if (recent_files.size() > 0 && recent_files[recent_files.size() - 1] == full_path) return; // Already in list for (int i = 0; i < recent_files.size(); i++) if (recent_files[i] == full_path || (!remote_gdb() && gdb->type() != JDB && same_file(recent_files[i], full_path))) recent_files[i] = ""; // Clear old entry recent_files += full_path; update_recent_menus(); }
// Create a separate tty window; return its name in TTYNAME, its // process id in PID, its terminal type in TERM, and its window id in // WINDOWID. static void launch_separate_tty(string& ttyname, pid_t& pid, string& term, Window& windowid, Widget origin) { // If we're already running, all is done. if (pid > 0 && (remote_gdb() || kill(pid, 0) == 0)) return; string term_command = app_data.term_command; term_command.gsub("@FONT@", make_font(app_data, FixedWidthDDDFont)); static bool canceled; canceled = false; static Widget dialog = 0; if (dialog == 0) { Arg args[10]; Cardinal arg = 0; XtSetArg(args[arg], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); arg++; dialog = verify(XmCreateWorkingDialog(find_shell(origin), XMST("launch_tty_dialog"), args, arg)); XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON)); XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); XtAddCallback(dialog, XmNcancelCallback, CancelTTYCB, XtPointer(&canceled)); } string base = term_command; if (base.contains(' ')) base = base.before(' '); MString msg = rm("Starting ") + tt(base) + rm("..."); XtVaSetValues(dialog, XmNmessageString, msg.xmstring(), XtPointer(0)); manage_and_raise(dialog); wait_until_mapped(dialog); StatusDelay delay("Starting execution window"); // Fill in defaults ttyname = ""; pid = -1; string command = // Set up a temporary file in TMP. "tmp=${TMPDIR-/tmp}/ddd$$; export tmp; " // Be sure to remove it when exiting... "trap \"rm -f $tmp\" 0; " // ... or being interrupted. "trap 'exit 1' 1 2 15; " // Now execute the xterm command + term_command + // which saves TTY, PID, TERM, and WINDOWID in TMP and goes to // sleep forever. Signal 2 (SIGINT) is blocked for two // reasons: first, we don't want ^C to kill the tty window; // second, later invocations will send us SIGINT to find out // whether we're still alive. " '" "echo `tty` $$ $TERM $WINDOWID >$tmp; " "trap \"\" 2; " "while true; do sleep 3600; done" "' " // The whole thing is redirected and in the background such // that rsh won't wait for us. ">/dev/null </dev/null 2>&1 & " // The main file waits for TMP to be created... "while test ! -s $tmp; do sleep 1; done; " // ...and sends TMP's contents to stdout, where DDD is waiting. "cat $tmp"; if (pid > 0 && remote_gdb()) { // We're already running. Don't start a new tty // if the old one is still running. std::ostringstream os; os << "kill -2 " << pid << " 2>/dev/null" << " || ( " << command << " )"; command = string(os); } command = sh_command(command); { XtAppContext app_context = XtWidgetToApplicationContext(dialog); LiterateAgent tty(app_context, command); string reply = ""; tty.addHandler(Input, GotReplyHP, (void *)&reply); tty.start(); while (!reply.contains('\n') && !canceled && tty.running()) XtAppProcessEvent(app_context, XtIMAll); if (reply.length() > 2) { std::istringstream is(reply.chars()); is >> ttyname >> pid >> term >> windowid; } tty.terminate(); }