* by the original gdb process (the "parent").  Since processes * (unlike people) can have only one parent, if you are * debugging gdb itself (and your debugger is thus _already_ the * controller/parent for this child),  code from here on out * is undebuggable.  Indeed, you probably got an error message * saying "not parent".  Sorry--you'll have to use print statements! */
by the original gdb process (the "parent").  Since processes (unlike people) can have only one parent, if you are debugging gdb itself (and your debugger is thus _already_ the controller/parent for this child), code from here on out is undebuggable.  Indeed, you probably got an error message saying "not parent".  Sorry; you'll have to use print statements!  */
fork_inferior (char *exec_file_arg, char *allargs, char **env,	       void (*traceme_fun) (void), void (*init_trace_fun) (int),	       void (*pre_trace_fun) (void), char *shell_file_arg){  int pid;  char *shell_command;  static char default_shell_file[] = SHELL_FILE;  int len;  /* Set debug_fork then attach to the child while it sleeps, to debug. */  static int debug_fork = 0;  /* This is set to the result of setpgrp, which if vforked, will be visible     to you in the parent process.  It's only used by humans for debugging.  */  static int debug_setpgrp = 657473;  static char *shell_file;  static char *exec_file;  char **save_our_env;  int shell = 0;  static char **argv;  /* If no exec file handed to us, get it from the exec-file command -- with     a good, common error message if none is specified.  */  exec_file = exec_file_arg;  if (exec_file == 0)    exec_file = get_exec_file (1);  /* STARTUP_WITH_SHELL is defined in inferior.h.   * If 0, we'll just do a fork/exec, no shell, so don't   * bother figuring out what shell.   */  shell_file = shell_file_arg;  if (STARTUP_WITH_SHELL)    {      /* Figure out what shell to start up the user program under. */      if (shell_file == NULL)	shell_file = getenv ("SHELL");      if (shell_file == NULL)	shell_file = default_shell_file;      shell = 1;    }  /* Multiplying the length of exec_file by 4 is to account for the fact     that it may expand when quoted; it is a worst-case number based on     every character being '.  */  len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;  /* If desired, concat something onto the front of ALLARGS.     SHELL_COMMAND is the result.  */#ifdef SHELL_COMMAND_CONCAT  shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);  strcpy (shell_command, SHELL_COMMAND_CONCAT);#else  shell_command = (char *) alloca (len);  shell_command[0] = '\0';#endif  if (!shell)    {      /* We're going to call execvp. Create argv */      /* Largest case: every other character is a separate arg */      argv = (char **) xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) * sizeof (*argv));      argv[0] = exec_file;      breakup_args (allargs, &argv[1]);    }  else    {      /* We're going to call a shell */      /* Now add exec_file, quoting as necessary.  */      char *p;      int need_to_quote;      const int escape_bang = escape_bang_in_quoted_argument (shell_file);      strcat (shell_command, "exec ");      /* Quoting in this style is said to work with all shells.  But csh         on IRIX 4.0.1 can't deal with it.  So we only quote it if we need         to.  */      p = exec_file;      while (1)	{	  switch (*p)	    {	    case '\'':	    case '!':	    case '"':	    case '(':	    case ')':	    case '$':	    case '&':	    case ';':	    case '<':	    case '>':	    case ' ':	    case '\n':	    case '\t':	      need_to_quote = 1;	      goto end_scan;	    case '\0':	      need_to_quote = 0;	      goto end_scan;	    default:	      break;	    }	  ++p;	}    end_scan:      if (need_to_quote)	{	  strcat (shell_command, "'");	  for (p = exec_file; *p != '\0'; ++p)	    {	      if (*p == '\'')		strcat (shell_command, "'\\''");	      else if (*p == '!' && escape_bang)		strcat (shell_command, "\\!");	      else		strncat (shell_command, p, 1);	    }	  strcat (shell_command, "'");	}      else	strcat (shell_command, exec_file);      strcat (shell_command, " ");      strcat (shell_command, allargs);    }  /* exec is said to fail if the executable is open.  */  close_exec_file ();  /* Retain a copy of our environment variables, since the child will     replace the value of  environ  and if we're vforked, we have to     restore it.  */  save_our_env = environ;  /* Tell the terminal handling subsystem what tty we plan to run on;     it will just record the information for later.  */  new_tty_prefork (inferior_io_terminal);  /* It is generally good practice to flush any possible pending stdio     output prior to doing a fork, to avoid the possibility of both the     parent and child flushing the same data after the fork. */  gdb_flush (gdb_stdout);  gdb_flush (gdb_stderr);  /* If there's any initialization of the target layers that must happen     to prepare to handle the child we're about fork, do it now...   */  if (pre_trace_fun != NULL)    (*pre_trace_fun) ();  /* Create the child process.  Note that the apparent call to vfork()     below *might* actually be a call to fork() due to the fact that     autoconf will ``#define vfork fork'' on certain platforms.  */  if (debug_fork)    pid = fork ();  else    pid = vfork ();  if (pid < 0)    perror_with_name ("vfork");  if (pid == 0)    {      if (debug_fork)	sleep (debug_fork);      /* Run inferior in a separate process group.  */      debug_setpgrp = gdb_setpgid ();      if (debug_setpgrp == -1)	perror ("setpgrp failed in child");      /* Ask the tty subsystem to switch to the one we specified earlier         (or to share the current terminal, if none was specified).  */      new_tty ();      /* Changing the signal handlers for the inferior after         a vfork can also change them for the superior, so we don't mess         with signals here.  See comments in         initialize_signals for how we get the right signal handlers         for the inferior.  */      /* "Trace me, Dr. Memory!" */      (*traceme_fun) ();      /* The call above set this process (the "child") as debuggable       * by the original gdb process (the "parent").  Since processes       * (unlike people) can have only one parent, if you are       * debugging gdb itself (and your debugger is thus _already_ the       * controller/parent for this child),  code from here on out       * is undebuggable.  Indeed, you probably got an error message       * saying "not parent".  Sorry--you'll have to use print statements!       */      /* There is no execlpe call, so we have to set the environment         for our child in the global variable.  If we've vforked, this         clobbers the parent, but environ is restored a few lines down         in the parent.  By the way, yes we do need to look down the         path to find $SHELL.  Rich Pixley says so, and I agree.  */      environ = env;      /* If we decided above to start up with a shell,       * we exec the shell,       * "-c" says to interpret the next arg as a shell command       * to execute, and this command is "exec <target-program> <args>".       * "-f" means "fast startup" to the c-shell, which means       * don't do .cshrc file. Doing .cshrc may cause fork/exec       * events which will confuse debugger start-up code.       */      if (shell)	{	  execlp (shell_file, shell_file, "-c", shell_command, (char *) 0);	  /* If we get here, it's an error */	  fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,			      safe_strerror (errno));	  gdb_flush (gdb_stderr);	  _exit (0177);	}      else	{	  /* Otherwise, we directly exec the target program with execvp. */	  int i;	  char *errstring;	  execvp (exec_file, argv);	  /* If we get here, it's an error */	  errstring = safe_strerror (errno);	  fprintf_unfiltered (gdb_stderr, "Cannot exec %s ", exec_file);	  i = 1;	  while (argv[i] != NULL)	    {	      if (i != 1)		fprintf_unfiltered (gdb_stderr, " ");	      fprintf_unfiltered (gdb_stderr, "%s", argv[i]);	      i++;	    }	  fprintf_unfiltered (gdb_stderr, ".\n");	  /* This extra info seems to be useless	     fprintf_unfiltered (gdb_stderr, "Got error %s.\n", errstring);	   */	  gdb_flush (gdb_stderr);	  _exit (0177);	}    }  /* Restore our environment in case a vforked child clob'd it.  */  environ = save_our_env;  init_thread_list ();  inferior_ptid = pid_to_ptid (pid);	/* Needed for wait_for_inferior stuff below */  /* Now that we have a child process, make it our target, and     initialize anything target-vector-specific that needs initializing.  */  (*init_trace_fun) (pid);  /* We are now in the child process of interest, having exec'd the     correct program, and are poised at the first instruction of the     new program.  */  /* Allow target dependent code to play with the new process.  This might be     used to have target-specific code initialize a variable in the new process     prior to executing the first instruction.  */  TARGET_CREATE_INFERIOR_HOOK (pid);#ifdef SOLIB_CREATE_INFERIOR_HOOK  SOLIB_CREATE_INFERIOR_HOOK (pid);#endif}