Reference(s): proc/readproc.c: In function 'statm2proc' proc/readproc.c:627:9: warning: variable 'num' set but not used [-Wunused-but-set-variable] ps/output.c: In function 'pr_context': ps/output.c:1273:14: warning: unused variable 'tried_load' [-Wunused-variable] ps/output.c:1272:16: warning: unused variable 'ps_is_selinux_enabled' [-Wunused-variable] ps/output.c:1272:16: warning: 'ps_is_selinux_enabled' defined but not used [-Wunused-variable] ps/output.c:1273:14: warning: 'tried_load' defined but not used [-Wunused-variable] ps/output.c:1837:18: warning: 'shortsort_array_count' defined but not used [-Wunused-const-variable=] ps/output.c:1803:18: warning: 'aix_array_count' defined but not used [-Wunused-const-variable=] ps/parser.c: In function 'arg_type': ps/parser.c:1098:3: warning: this 'if' clause does not guard... [-Wmisleading-indentation] ps/parser.c:1099:34: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if' ps/sortformat.c: In function 'format_parse': ps/sortformat.c:241:1: warning: label 'out' defined but not used [-Wunused-label] ps/stacktrace.c:176:13: warning: 'stack_trace_sigsegv' defined but not used [-Wunused-function] watch.c: In function 'process_ansi': watch.c:234:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation] watch.c:237:2: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if' Signed-off-by: Jim Warner <james.warner@comcast.net>
		
			
				
	
	
		
			190 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * stacktrace.c - ps debugging additions
 | 
						|
 * Gnu debugger stack trace code provided by Peter Mattis
 | 
						|
 * <petm@CSUA.Berkeley.EDU> on Thu, 2 Nov 1995
 | 
						|
 *
 | 
						|
 * Modified for easy use by Albert Cahalan.
 | 
						|
 *
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Lesser General Public
 | 
						|
 * License as published by the Free Software Foundation; either
 | 
						|
 * version 2.1 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This library is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Lesser General Public
 | 
						|
 * License along with this library; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
						|
 */
 | 
						|
 | 
						|
#include <errno.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include <sys/time.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
 | 
						|
#include "common.h"
 | 
						|
 | 
						|
#define INTERACTIVE 0
 | 
						|
#define STACK_TRACE 1
 | 
						|
 | 
						|
char *stored_prog_name = "you forgot to set \"program\"";
 | 
						|
static int stack_trace_done;
 | 
						|
 | 
						|
/***********/
 | 
						|
static void debug_stop(char **args){
 | 
						|
  execvp (args[0], args);
 | 
						|
  perror ("exec failed");
 | 
						|
  _exit (0);
 | 
						|
}
 | 
						|
 | 
						|
/***********/
 | 
						|
static void stack_trace_sigchld(int signum){
 | 
						|
  (void)signum;
 | 
						|
  stack_trace_done = 1;
 | 
						|
}
 | 
						|
 | 
						|
/************/
 | 
						|
static void stack_trace(char **args){
 | 
						|
  pid_t pid;
 | 
						|
  int in_fd[2];
 | 
						|
  int out_fd[2];
 | 
						|
  fd_set fdset;
 | 
						|
  fd_set readset;
 | 
						|
  struct timeval tv;
 | 
						|
  int sel, index, state;
 | 
						|
  char buffer[256];
 | 
						|
  char c;
 | 
						|
 | 
						|
  stack_trace_done = 0;
 | 
						|
  signal(SIGCHLD, stack_trace_sigchld);
 | 
						|
 | 
						|
  if((pipe (in_fd) == -1) || (pipe (out_fd) == -1)){
 | 
						|
    perror ("could open pipe");
 | 
						|
    _exit (0);
 | 
						|
  }
 | 
						|
 | 
						|
  pid = fork ();
 | 
						|
  if (pid == 0){
 | 
						|
    close (0); dup (in_fd[0]);   /* set the stdin to the in pipe */
 | 
						|
    close (1); dup (out_fd[1]);  /* set the stdout to the out pipe */
 | 
						|
    close (2); dup (out_fd[1]);  /* set the stderr to the out pipe */
 | 
						|
    execvp (args[0], args);      /* exec gdb */
 | 
						|
    perror ("exec failed");
 | 
						|
    _exit (0);
 | 
						|
  } else {
 | 
						|
    if(pid == (pid_t) -1){
 | 
						|
      perror ("could not fork");
 | 
						|
      _exit (0);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FD_ZERO (&fdset);
 | 
						|
  FD_SET (out_fd[0], &fdset);
 | 
						|
 | 
						|
  write (in_fd[1], "backtrace\n", 10);
 | 
						|
  write (in_fd[1], "p x = 0\n", 8);
 | 
						|
  write (in_fd[1], "quit\n", 5);
 | 
						|
 | 
						|
  index = 0;
 | 
						|
  state = 0;
 | 
						|
 | 
						|
  for(;;){
 | 
						|
    readset = fdset;
 | 
						|
    tv.tv_sec = 1;
 | 
						|
    tv.tv_usec = 0;
 | 
						|
 | 
						|
    sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv);
 | 
						|
    if (sel == -1) break;
 | 
						|
 | 
						|
    if((sel > 0) && (FD_ISSET (out_fd[0], &readset))){
 | 
						|
      if(read (out_fd[0], &c, 1)){
 | 
						|
        switch(state){
 | 
						|
        case 0:
 | 
						|
          if(c == '#'){
 | 
						|
            state = 1;
 | 
						|
            index = 0;
 | 
						|
            buffer[index++] = c;
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        case 1:
 | 
						|
          buffer[index++] = c;
 | 
						|
          if((c == '\n') || (c == '\r')){
 | 
						|
            buffer[index] = 0;
 | 
						|
            fprintf (stderr, "%s", buffer);
 | 
						|
            state = 0;
 | 
						|
            index = 0;
 | 
						|
          }
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else if(stack_trace_done) break;
 | 
						|
  }
 | 
						|
 | 
						|
  close (in_fd[0]);
 | 
						|
  close (in_fd[1]);
 | 
						|
  close (out_fd[0]);
 | 
						|
  close (out_fd[1]);
 | 
						|
  _exit (0);
 | 
						|
}
 | 
						|
 | 
						|
/************/
 | 
						|
void debug(int method, char *prog_name){
 | 
						|
  pid_t pid;
 | 
						|
  char buf[16];
 | 
						|
  char *args[4] = { "gdb", NULL, NULL, NULL };
 | 
						|
  int x;
 | 
						|
 | 
						|
  snprintf (buf, sizeof(buf), "%d", getpid ());
 | 
						|
 | 
						|
  args[1] = prog_name;
 | 
						|
  args[2] = buf;
 | 
						|
 | 
						|
  pid = fork ();
 | 
						|
  if(pid == 0){
 | 
						|
    switch (method){
 | 
						|
    case INTERACTIVE:
 | 
						|
      fprintf (stderr, "debug_stop\n");
 | 
						|
      debug_stop(args);
 | 
						|
      break;
 | 
						|
    case STACK_TRACE:
 | 
						|
      fprintf (stderr, "stack_trace\n");
 | 
						|
      stack_trace(args);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    _exit(0);
 | 
						|
  } else if(pid == (pid_t) -1){
 | 
						|
    perror ("could not fork");
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  x = 1;
 | 
						|
  while(x);  /* wait for debugger? */
 | 
						|
}
 | 
						|
 | 
						|
/************/
 | 
						|
#if 0
 | 
						|
static void stack_trace_sigsegv(int signum){
 | 
						|
  (void)signum;
 | 
						|
  debug(STACK_TRACE, stored_prog_name);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/************/
 | 
						|
#ifdef DEBUG
 | 
						|
void init_stack_trace(char *prog_name){
 | 
						|
  stored_prog_name = prog_name;
 | 
						|
  signal(SIGSEGV, stack_trace_sigsegv);
 | 
						|
}
 | 
						|
#endif
 |