Ejemplo n.º 1
0
void gdbEditSourceCB  (Widget w, XtPointer, XtPointer)
{
    string pos = source_view->file_of_cursor();
    string file = pos.before(':');
    string line = pos.after(':');

    if (file == "" || line == "0")
    {
	post_error("No source.", "no_source_edit_error", w);
	return;
    }

    StatusDelay delay("Invoking editor for " + quote(file));

    string cmd = app_data.edit_command;
    cmd.gsub("@FILE@", file);
    cmd.gsub("@LINE@", line);
    cmd = sh_command(cmd);

    // Invoke an editor in the background
    LiterateAgent *edit_agent = 
	new LiterateAgent(XtWidgetToApplicationContext(w), cmd);

    output_buffer = "";

    edit_agent->removeAllHandlers(Died);
    edit_agent->addHandler(InputEOF, gdbEditDoneHP);
    edit_agent->addHandler(Died,     gdbEditDoneHP);
    edit_agent->addHandler(Input,    gdbEditOutputHP);
    edit_agent->addHandler(Error,    gdbEditOutputHP);
    edit_agent->start();
}
Ejemplo n.º 2
0
// Search for remote files and directories, using the command CMD
static void searchRemote(Widget fs,
			 XmFileSelectionBoxCallbackStruct *cbs,
			 const _XtString cmd,
			 bool search_dirs)
{
    StatusDelay delay(delay_message);

    int nitems = 0;
    int size = 256;
    XmStringTable items = 
	XmStringTable(XtMalloc(size * sizeof(XmString)));

    String mask;
    if (!XmStringGetLtoR(cbs->mask, MSTRING_DEFAULT_CHARSET, &mask))
    {
	delay.outcome = "failed";
	return;
    }
    String dir;
    if (!XmStringGetLtoR(cbs->dir, MSTRING_DEFAULT_CHARSET, &dir))
    {
	delay.outcome = "failed";
	return;
    }

    if (search_dirs)
    {
	string extra_dir = string(dir) + ".";
	items[nitems++] = 
	    XmStringCreateLtoR(XMST(extra_dir.chars()), MSTRING_DEFAULT_CHARSET);
	extra_dir = string(dir) + "..";
	items[nitems++] = 
	    XmStringCreateLtoR(XMST(extra_dir.chars()), MSTRING_DEFAULT_CHARSET);
    }

    string command = cmd;
    command.gsub("@MASK@", mask);
    command = sh_command(command);

    Agent search(command);
    search.start();

    FILE *fp = search.inputfp();
    if (fp == 0)
    {
	delay.outcome = strerror(errno);
	return;
    }

    char buf[BUFSIZ];
    while (fgets(buf, sizeof(buf), fp))
    {
	if (buf[0] && buf[strlen(buf) - 1] == '\n')
	    buf[strlen(buf) - 1] = '\0';

	if (nitems >= size)
	{
	    size += 256;
	    items = XmStringTable(XtRealloc((char *)items,
					    size * sizeof(XmString)));
	}
	    
	items[nitems++] = XmStringCreateLtoR(buf, MSTRING_DEFAULT_CHARSET);

	if (nitems == 1 || nitems % 10 == 0)
	{
	    std::ostringstream status;
	    status << delay_message << "... ("
		   << nitems << " processed)";
	    string s(status);
	    set_status(s, true);
	}
    }

    if (search_dirs)
    {
	XtVaSetValues(fs,
		      XmNdirListItems,     items,
		      XmNdirListItemCount, nitems,
		      XmNdirectoryValid,   True,
		      XmNlistUpdated,      True,
		      XtPointer(0));
    }
    else
    {
	if (nitems > 0)
	{
	    XtVaSetValues(fs,
			  XmNfileListItems,     items,
			  XmNfileListItemCount, nitems,
			  XmNdirSpec,           items[0],
			  XmNlistUpdated,       True,
			  XtPointer(0));
	}
	else
	{
	    XtVaSetValues(fs,
			  XmNfileListItems,     0,
			  XmNfileListItemCount, 0,
			  XmNlistUpdated,       True,
			  XtPointer(0));
	}
    }
}
Ejemplo n.º 3
0
// Create list of processes
static void update_processes(Widget processes, bool keep_selection)
{
    StatusDelay delay("Getting list of processes");

    string cmd = sh_command(app_data.ps_command) + " 2>&1";
    FILE *fp = popen(cmd.chars(), "r");
    if (fp == 0)
    {
	delay.outcome = strerror(errno);
	return;
    }

    StringArray all_process_list;
    int c;
    string line = "";
    bool first_line = true;

    while ((c = getc(fp)) != EOF)
    {
	if (c == '\n')
	{
	    if (first_line || valid_ps_line(line, app_data.ps_command))
		all_process_list += line;
#if 0
	    else
		std::clog << "Excluded: " << line << "\n";
#endif

	    if (first_line)
	    {
		// Find first occurrence of `PID' title
		ps_pid_index = line.index(" PID ");
		if (ps_pid_index < 0)
		    ps_pid_index = 0;
	    }

	    line = "";
	    first_line = false;
	}
	else
	{
	    line += c;
	}
    }

    pclose(fp);
    sortProcesses(all_process_list);
    DynIntArray pids(all_process_list.size());

    // If GDB cannot send a signal to the process, we cannot debug it.
    // Try a `kill -0' (via GDB, as it may be setuid) and filter out
    // all processes in the `kill' diagnostic -- that is, all
    // processes that `kill' could not send a signal.
    string kill = "kill -0";

    if (gdb->has_handler_command())
	kill = "/usr/bin/kill -0"; // Bypass built-in SUN DBX command

    int i;
    for (i = 0; i < all_process_list.size(); i++)
    {
	pids[i] = ps_pid(all_process_list[i]);
	if (pids[i])
	    kill += string(" ") + itostring(pids[i]);
    }
#if defined(__sun) 
    // bypass underlying debugger
    // Fix for Sun: use /usr/bin/kill
    string kill_result;
    {
      std::ostringstream os;
      kill += " 2>&1";
      FILE *fp = popen(kill.chars(), "r");
      if (fp != 0)
      {
	  int c;
	  while ((c = getc(fp)) != EOF)
	  {
	      os << (char)c;
	  }
	  pclose(fp);
      }
      kill_result = os;
    }
#else
    string kill_result = gdb_question(gdb->shell_command(kill));
#endif
    i = 0;
    while (i >= 0)
    {
	i = kill_result.index(rxint, i);
	if (i >= 0)
	{
	    int bad_pid = atoi(kill_result.chars() + i);
	    for (int k = 0; k < all_process_list.size(); k++)
	    {
		if (pids[k] != 0 && pids[k] == bad_pid)
		{
#if 0
		    std::clog << "Excluded: " << all_process_list[k] << "\n";
#endif
		    all_process_list[k] = NO_GDB_ANSWER;
		}
	    }
	    i++;
	}
    }

    StringArray process_list;
    for (i = 0; i < all_process_list.size(); i++)
	if (all_process_list[i] != NO_GDB_ANSWER)
	    process_list += all_process_list[i];

    // Now set the selection.
    bool *selected = new bool[process_list.size()];
    for (i = 0; i < process_list.size(); i++)
	selected[i] = false;

    int pos = -1;
    if (keep_selection)
    {
	// Preserve old selection: each PID selected before will also be
	// selected after.
	IntArray selection;
	getPIDs(processes, selection);

	for (i = 0; i < selection.size(); i++)
	{
	    for (int j = 0; j < process_list.size(); j++)
		if (selection[i] == ps_pid(process_list[j]))
		{
		    if (pos < 0)
			pos = j;
		    selected[j] = true;
		}
	}
    }

    if (pos < 0)
    {
	// Create new selection from current file and current pid.
	ProgramInfo info;

	// Check for current pid; if found, highlight it.
	for (i = 0; pos < 0 && i < process_list.size(); i++)
	{
	    if (info.pid != 0 && ps_pid(process_list[i]) == info.pid)
		pos = i;
	}

	if (pos < 0)
	{
	    // Not found? Try leftmost occurrence of process base name.
	    string current_base = basename(info.file.chars());
	    int leftmost = INT_MAX;
	    for (i = 0; i < process_list.size(); i++)
	    {
		int occurrence = process_list[i].index(current_base);
		if (occurrence >= 0 && occurrence < leftmost 
		    && ps_pid(process_list[i]) > 0)
		{
		    leftmost = occurrence;
		    pos = i;
		}
	    }
	}
    }

    if (pos >= 0)
	selected[pos] = true;

    setLabelList(processes, process_list.values(),
		 selected, process_list.size(), true, false);

    if (pos >= 0)
	ListSetAndSelectPos(processes, pos + 1);

    delete[] selected;
}
Ejemplo n.º 4
0
// 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();
    }
Ejemplo n.º 5
0
GDBAgent *new_gdb(DebuggerType type,
		  const AppData& app_data,
		  XtAppContext app_context,
		  int argc, char *argv[])
{
    // Build call
    static string gdb_call = app_data.debugger_command;

    if (app_data.play_log != 0)
    {
	gdb_call += string(" --PLAY ") + app_data.play_log;
    }
    else
    {
	switch(type)
	{
	case GDB:
	    // Do not issue introductiory messages; output full file names.
	    gdb_call += " -q -fullname";
	    break;

	case DBX:
	    // Nothing special.  (Anyway, every DBX has its own sets of
	    // options, so there is not much we could do here.)
	    break;

	case JDB:
	    // Nothing special.
	    break;

	case PERL:
	    // Be sure to invoke the debugger.
	    gdb_call += " -d";
	    break;

	case BASH:
	    // Be sure to invoke the debugger.
	    gdb_call += " --debugger";
	    break;

	case DBG:
	    // Nothing special?
	    break;

	case PYDB:
	    // Nothing special.
	    break;

	case XDB:
	    // Enable line mode.
	    gdb_call += " -L";
	    break;
	}
    }

    for (int i = 1; i < argc; i++) 
    {
	string arg = argv[i];
	gdb_call += " " + sh_quote(arg);
    }

    if (argc <= 1) 
    {
	if (type == PERL)
	{
	    // Invoked without args.  Add a dummy `eval' arg.
	    gdb_call += " -e 42";
	}
	else if (type == BASH)
	{
	    gdb_call += " -c ': type \\\"debug *script-name*\\\" to start your script.'";
	}
    }
    

    GDBAgent *gdb;
    if (app_data.debugger_rhost == 0 || app_data.debugger_rhost[0] == '\0')
    {
	// Use direct invocation
	gdb_call = sh_command("exec " + gdb_call);
	gdb = new GDBAgent(app_context, gdb_call, type);
    }
    else
    {
	// Use interactive rsh
	gdb = new GDBAgent(app_context, sh_command(), type);
	gdb_call = 
	    "exec " + _sh_command("exec " + gdb_call, true, true) + "\n";
	gdb->addHandler(Input, InvokeGDBFromShellHP, (void *)&gdb_call);
    }

    // Set up Agent resources
    switch (app_data.block_tty_input)
    {
    case On:
	gdb->block_tty_input(true);
	break;

    case Off:
	gdb->block_tty_input(false);
	break;

    case Auto:
	// Leave default setting unchanged
	break;
    }

    // Set up Agent resources
    switch (app_data.buffer_gdb_output)
    {
    case On:
	gdb->buffer_gdb_output(true);
	break;

    case Off:
	gdb->buffer_gdb_output(false);
	break;

    case Auto:
	// Tie buffering to existence of separate window
	gdb->buffer_gdb_output(app_data.separate_exec_window);
	break;
    }

    return gdb;
}