[comp.os.minix] ps fix

stailey@iris613.gsfc.nasa.gov (Ken Stailey) (03/05/90)

This is a fix for ps.c, by Peter Valkenburg (valke@psy.vu.nl), january 1990.
This fix allows it to see the user process names under MINIX ST.  It may
even be portable to the PC too.  If you have PC MINIX I would appreciate
some feedback about this.  It works by looking at yet another system
variable, "aout", an array of proccess names generated for the PF1 key
dump by the system task routine, "do_exec()".  This hack does not allow
you to see path argv[0] too look at the command arguements, but future
enhancements will hopefully support this.

[climbing on soapbox]
Imagine if you had to locate and decode the inode table "by hand" in order
to find out basic information about files that the stat() call will tell you.
The program "ps" is just about as stupid.  Why isn't there a system call
to divulge process table entries?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*** ps.c.1.5.3	Sun Mar  4 20:26:32 1990
--- ps.c	Sun Mar  4 23:20:07 1990
***************
*** 85,96 ****
  #define	ID_MPROC	"_mproc"	/* from mm namelist */
  #define	ID_FPROC	"_fproc"	/* from fs namelist */
  #define	ID_TASKTAB	"_tasktab"	/* from kernel namelist */
  
  /*
   * Structure for system address info (also layout of ps's database).
   */
  typedef struct {
! 	struct nlist ke_proc[2], ke_tasktab[2];
  	struct nlist mm_mproc[2];
  	struct nlist fs_fproc[2];
  } sysinfo_t;
--- 85,97 ----
  #define	ID_MPROC	"_mproc"	/* from mm namelist */
  #define	ID_FPROC	"_fproc"	/* from fs namelist */
  #define	ID_TASKTAB	"_tasktab"	/* from kernel namelist */
+ #define	ID_AOUT		"_aout"		/* from kernel namelist */
  
  /*
   * Structure for system address info (also layout of ps's database).
   */
  typedef struct {
! 	struct nlist ke_proc[2], ke_tasktab[2], ke_aout[2];
  	struct nlist mm_mproc[2];
  	struct nlist fs_fproc[2];
  } sysinfo_t;
***************
*** 104,109 ****
--- 105,111 ----
  #define	MPROC	mproc
  #define	FPROC	fproc
  #define	TASKTAB	tasktab
+ #define AOUT	aout
  
  /* default paths for system binaries */
  #define KERNEL_PATH	"/usr/src/kernel/kernel.mix"
***************
*** 125,130 ****
--- 127,134 ----
  
  struct tasktab tasktab[NR_TASKS + INIT_PROC_NR + 1];	/* task table */
  
+ phys_bytes aout[NR_TASKS];
+ 
  /*
   * Short and long listing formats:
   *
***************
*** 299,306 ****
  	if (opt_update || (db_fd = open(DBASE_PATH, O_RDONLY)) == -1) {
  		strncpy(sysinfo.ke_proc[0].n_name, ID_PROC, NAME_SIZ);
  		strncpy(sysinfo.ke_tasktab[0].n_name, ID_TASKTAB, NAME_SIZ);
! 		if (nlist(kpath, sysinfo.ke_proc) != 0 ||
! 		    nlist(kpath, sysinfo.ke_tasktab) != 0)
  			err("Can't read kernel namelist");
  		strncpy(sysinfo.mm_mproc[0].n_name, ID_MPROC, NAME_SIZ);
  		if (nlist(mpath, sysinfo.mm_mproc) != 0)
--- 303,312 ----
  	if (opt_update || (db_fd = open(DBASE_PATH, O_RDONLY)) == -1) {
  		strncpy(sysinfo.ke_proc[0].n_name, ID_PROC, NAME_SIZ);
  		strncpy(sysinfo.ke_tasktab[0].n_name, ID_TASKTAB, NAME_SIZ);
! 		strncpy(sysinfo.ke_aout[0].n_name, ID_AOUT, NAME_SIZ);
! 		if (nlist(kpath, sysinfo.ke_proc) != 0 ||
! 		    nlist(kpath, sysinfo.ke_tasktab) != 0 ||
! 		    nlist(kpath, sysinfo.ke_aout))
  			err("Can't read kernel namelist");
  		strncpy(sysinfo.mm_mproc[0].n_name, ID_MPROC, NAME_SIZ);
  		if (nlist(mpath, sysinfo.mm_mproc) != 0)
***************
*** 322,328 ****
  			err("Can't read psdatabase");	 
  	}
  	(void) close (db_fd);
! 	    	
  	/* get kernel tables */    	
  	if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1)
  		err(KMEM_PATH);
--- 328,334 ----
  			err("Can't read psdatabase");	 
  	}
  	(void) close (db_fd);
! 
  	/* get kernel tables */    	
  	if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1)
  		err(KMEM_PATH);
***************
*** 334,339 ****
--- 340,349 ----
  		     (vir_bytes) sysinfo.ke_tasktab[0].n_value,
  		     (char *) TASKTAB, sizeof(TASKTAB)) != sizeof(TASKTAB))
  		err("Can't get kernel task table from /dev/kmem");
+ 	if (addrread(kmemfd, (phys_clicks) 0,
+ 		     (vir_bytes) sysinfo.ke_aout[0].n_value,
+ 		     (char *) AOUT, sizeof(AOUT)) != sizeof(AOUT))
+ 		err("Can't get kernel aout table from /dev/kmem");
  
  	/* get mm/fs tables */
  	if ((memfd = open(MEM_PATH, O_RDONLY)) == -1)
***************
*** 346,352 ****
  		     (vir_bytes) sysinfo.fs_fproc[0].n_value,
  		     (char *) FPROC, sizeof(FPROC)) != sizeof(FPROC))
  		err("Can't get fs proc table from /dev/mem");
! 		
  	/* now loop through process table and handle each entry */
  	printf("%s", opt_long ? L_HEADER : S_HEADER);
  	for (i = -NR_TASKS; i < NR_PROCS; i++) {
--- 356,362 ----
  		     (vir_bytes) sysinfo.fs_fproc[0].n_value,
  		     (char *) FPROC, sizeof(FPROC)) != sizeof(FPROC))
  		err("Can't get fs proc table from /dev/mem");
! 
  	/* now loop through process table and handle each entry */
  	printf("%s", opt_long ? L_HEADER : S_HEADER);
  	for (i = -NR_TASKS; i < NR_PROCS; i++) {
***************
*** 477,489 ****
  	}
  	
  	if (state != DONE)
! 		return NULL;
  
  	/* get a local version of argv[0]; l is offset back from end of stack */
  	l = (bufp->ps_stack + bufp->ps_ssize) -
  		(bufp->ps_data + (vir_bytes) sp[1].stk_cp);
  	if (l < 0 || l > cnt)
! 		return NULL;
  	args = &((char *) stk)[cnt - (int) l];
  	neos = 0;
  	for (cp = args; cp < &((char *) stk)[cnt]; cp++)
--- 487,499 ----
  	}
  	
  	if (state != DONE)
! 		return (char *) NULL;
  
  	/* get a local version of argv[0]; l is offset back from end of stack */
  	l = (bufp->ps_stack + bufp->ps_ssize) -
  		(bufp->ps_data + (vir_bytes) sp[1].stk_cp);
  	if (l < 0 || l > cnt)
! 		return (char *) NULL;
  	args = &((char *) stk)[cnt - (int) l];
  	neos = 0;
  	for (cp = args; cp < &((char *) stk)[cnt]; cp++)
***************
*** 493,499 ****
  			else
  				*cp = ' ';	
  	if (neos != sp[0].stk_i)
! 		return NULL;			
  
  	return args;
  }
--- 503,509 ----
  			else
  				*cp = ' ';	
  	if (neos != sp[0].stk_i)
! 		return (char *) NULL;			
  
  	return args;
  }
***************
*** 576,582 ****
  	if (bufp->ps_state == Z_STATE)
  		bufp->ps_args = "<defunct>";
  	else if (p_nr > INIT_PROC_NR)
! 		bufp->ps_args = get_args(bufp);
  	
  	return 0;
  }
--- 586,593 ----
  	if (bufp->ps_state == Z_STATE)
  		bufp->ps_args = "<defunct>";
  	else if (p_nr > INIT_PROC_NR)
! /*		bufp->ps_args = get_args(bufp); */
! 		bufp->ps_args = (off_t) AOUT[p_nr];
  	
  	return 0;
  }

INET stailey@iris613.gsfc.nasa.gov
UUCP {backbone}!dftsrv!iris613!stailey

leo@marco.UUCP (Matthias Pfaller) (03/12/90)

In article <1057@dftsrv.gsfc.nasa.gov>, stailey@iris613.gsfc.nasa.gov (Ken Stailey) writes:
> 
> This is a fix for ps.c, by Peter Valkenburg (valke@psy.vu.nl), january 1990.
> This fix allows it to see the user process names under MINIX ST.  It may
> even be portable to the PC too.  If you have PC MINIX I would appreciate
          ^^^^^^^^ ?????

Do you real think it is portable to dereference an absolute pointer
to read data of another process?

The following patch makes the 1.5.3-ps run with the st. It examines, like
the pc-version, the stack to figure out the commandname and arguments.
It also uses the aout kernel variable (based on <1057@dftsrv.gsfc.nasa.gov>)

	leo@marco.UUCP (Matthias Pfaller)


*** ps.c.1.5.3	Mon Mar 12 16:34:28 1990
--- ps.c	Mon Mar 12 16:28:05 1990
***************
*** 85,96 ****
  #define	ID_MPROC	"_mproc"	/* from mm namelist */
  #define	ID_FPROC	"_fproc"	/* from fs namelist */
  #define	ID_TASKTAB	"_tasktab"	/* from kernel namelist */
  
  /*
   * Structure for system address info (also layout of ps's database).
   */
  typedef struct {
! 	struct nlist ke_proc[2], ke_tasktab[2];
  	struct nlist mm_mproc[2];
  	struct nlist fs_fproc[2];
  } sysinfo_t;
--- 85,104 ----
  #define	ID_MPROC	"_mproc"	/* from mm namelist */
  #define	ID_FPROC	"_fproc"	/* from fs namelist */
  #define	ID_TASKTAB	"_tasktab"	/* from kernel namelist */
+ #if	(MACHINE == ATARI)
+ #define	ID_AOUT		"_aout"		/* from kernel namelist */
+ #endif
  
  /*
   * Structure for system address info (also layout of ps's database).
   */
  typedef struct {
! 	struct nlist ke_proc[2], ke_tasktab[2]
! #if	(MACHINE == ATARI)
! 	, ke_aout[2];
! #else
! 	;
! #endif
  	struct nlist mm_mproc[2];
  	struct nlist fs_fproc[2];
  } sysinfo_t;
***************
*** 104,109 ****
--- 112,120 ----
  #define	MPROC	mproc
  #define	FPROC	fproc
  #define	TASKTAB	tasktab
+ #if	(MACHINE == ATARI)
+ #define AOUT	aout
+ #endif
  
  /* default paths for system binaries */
  #define KERNEL_PATH	"/usr/src/kernel/kernel"
***************
*** 125,130 ****
--- 136,145 ----
  
  struct tasktab tasktab[NR_TASKS + INIT_PROC_NR + 1];	/* task table */
  
+ #if	(MACHINE == ATARI)
+ phys_bytes aout[NR_TASKS];
+ #endif
+ 
  /*
   * Short and long listing formats:
   *
***************
*** 299,306 ****
  	if (opt_update || (db_fd = open(DBASE_PATH, O_RDONLY)) == -1) {
  		strncpy(sysinfo.ke_proc[0].n_name, ID_PROC, NAME_SIZ);
  		strncpy(sysinfo.ke_tasktab[0].n_name, ID_TASKTAB, NAME_SIZ);
  		if (nlist(kpath, sysinfo.ke_proc) != 0 ||
! 		    nlist(kpath, sysinfo.ke_tasktab) != 0)
  			err("Can't read kernel namelist");
  		strncpy(sysinfo.mm_mproc[0].n_name, ID_MPROC, NAME_SIZ);
  		if (nlist(mpath, sysinfo.mm_mproc) != 0)
--- 314,329 ----
  	if (opt_update || (db_fd = open(DBASE_PATH, O_RDONLY)) == -1) {
  		strncpy(sysinfo.ke_proc[0].n_name, ID_PROC, NAME_SIZ);
  		strncpy(sysinfo.ke_tasktab[0].n_name, ID_TASKTAB, NAME_SIZ);
+ #if	(MACHINE == ATARI)
+ 		strncpy(sysinfo.ke_aout[0].n_name, ID_AOUT, NAME_SIZ);
+ #endif
  		if (nlist(kpath, sysinfo.ke_proc) != 0 ||
! 		    nlist(kpath, sysinfo.ke_tasktab) != 0
! #if	(MACHINE == ATARI)
! 		    || nlist(kpath, sysinfo.ke_aout))
! #else
! 		    ))
! #endif
  			err("Can't read kernel namelist");
  		strncpy(sysinfo.mm_mproc[0].n_name, ID_MPROC, NAME_SIZ);
  		if (nlist(mpath, sysinfo.mm_mproc) != 0)
***************
*** 322,328 ****
  			err("Can't read psdatabase");	 
  	}
  	(void) close (db_fd);
! 	    	
  	/* get kernel tables */    	
  	if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1)
  		err(KMEM_PATH);
--- 345,351 ----
  			err("Can't read psdatabase");	 
  	}
  	(void) close (db_fd);
! 
  	/* get kernel tables */    	
  	if ((kmemfd = open(KMEM_PATH, O_RDONLY)) == -1)
  		err(KMEM_PATH);
***************
*** 334,339 ****
--- 357,368 ----
  		     (vir_bytes) sysinfo.ke_tasktab[0].n_value,
  		     (char *) TASKTAB, sizeof(TASKTAB)) != sizeof(TASKTAB))
  		err("Can't get kernel task table from /dev/kmem");
+ #if	(MACHINE == ATARI)
+ 	if (addrread(kmemfd, (phys_clicks) 0,
+ 		     (vir_bytes) sysinfo.ke_aout[0].n_value,
+ 		     (char *) AOUT, sizeof(AOUT)) != sizeof(AOUT))
+ 		err("Can't get kernel aout table from /dev/kmem");
+ #endif
  
  	/* get mm/fs tables */
  	if ((memfd = open(MEM_PATH, O_RDONLY)) == -1)
***************
*** 346,352 ****
  		     (vir_bytes) sysinfo.fs_fproc[0].n_value,
  		     (char *) FPROC, sizeof(FPROC)) != sizeof(FPROC))
  		err("Can't get fs proc table from /dev/mem");
! 		
  	/* now loop through process table and handle each entry */
  	printf("%s", opt_long ? L_HEADER : S_HEADER);
  	for (i = -NR_TASKS; i < NR_PROCS; i++) {
--- 375,381 ----
  		     (vir_bytes) sysinfo.fs_fproc[0].n_value,
  		     (char *) FPROC, sizeof(FPROC)) != sizeof(FPROC))
  		err("Can't get fs proc table from /dev/mem");
! 
  	/* now loop through process table and handle each entry */
  	printf("%s", opt_long ? L_HEADER : S_HEADER);
  	for (i = -NR_TASKS; i < NR_PROCS; i++) {
***************
*** 409,419 ****
   * Warning: this routine is inherently unreliable and probably doesn't work if
   * ptrs and ints have different sizes.
   */
! char *get_args(bufp)
! struct pstat *bufp;
  {
  	union {
  		int stk_i;
  		char *stk_cp;
  		char stk_c;
  	} stk[ARG_MAX / sizeof(char *)], *sp;
--- 438,452 ----
   * Warning: this routine is inherently unreliable and probably doesn't work if
   * ptrs and ints have different sizes.
   */
! char *get_args(bufp, p_nr)
! struct pstat *bufp; int p_nr;
  {
  	union {
+ #if	(CHIP == M68000) /* should be sizeof(int) != sizeof(void *) */
+ 		long stk_i;
+ #else
  		int stk_i;
+ #endif
  		char *stk_cp;
  		char stk_c;
  	} stk[ARG_MAX / sizeof(char *)], *sp;
***************
*** 421,428 ****
  	int nargv;		/* guessed # of (non-NULL) argv pointers seen */
  	int cnt;		/* # of bytes read from stack frame */
  	int neos;		/* # of '\0's seen in argv string space */
  	off_t l;
! 	char *cp, *args;
  	
  	
  	if (bufp->ps_ssize < ARG_MAX)
--- 454,462 ----
  	int nargv;		/* guessed # of (non-NULL) argv pointers seen */
  	int cnt;		/* # of bytes read from stack frame */
  	int neos;		/* # of '\0's seen in argv string space */
+ 	int flag=0;		/* argv not found */
  	off_t l;
! 	char *e, *cp, *args;
  	
  	
  	if (bufp->ps_ssize < ARG_MAX)
***************
*** 463,469 ****
  		case NULL2:	/* two NULLs seen */
  			if (sp[0].stk_cp == NULL)
  				nargv = 0;	/* restart counting */
! 			else if (sp[0].stk_i == nargv)
  				state = DONE;	/* think i got it */
  			/* next is same ugly patch as above */	
  			else if (sp > &stk[0] && sp[0].stk_cp == sp[-1].stk_cp)
--- 497,507 ----
  		case NULL2:	/* two NULLs seen */
  			if (sp[0].stk_cp == NULL)
  				nargv = 0;	/* restart counting */
! #if	(CHIP == M68000) /* should be sizeof(int) != sizeof(void *) */
! 			else if ((sp[0].stk_i & 0xffff) == nargv)
! #else
! 			else if ((sp[0].stk_i) == nargv)
! #endif
  				state = DONE;	/* think i got it */
  			/* next is same ugly patch as above */	
  			else if (sp > &stk[0] && sp[0].stk_cp == sp[-1].stk_cp)
***************
*** 475,501 ****
  			break;
  		}	
  	}
! 	
! 	if (state != DONE)
! 		return NULL;
  
  	/* get a local version of argv[0]; l is offset back from end of stack */
  	l = (bufp->ps_stack + bufp->ps_ssize) -
! 		(bufp->ps_data + (vir_bytes) sp[1].stk_cp);
  	if (l < 0 || l > cnt)
! 		return NULL;
  	args = &((char *) stk)[cnt - (int) l];
  	neos = 0;
! 	for (cp = args; cp < &((char *) stk)[cnt]; cp++)
  		if (*cp == '\0')
  			if (++neos >= sp[0].stk_i)
  				break;
  			else
  				*cp = ' ';	
  	if (neos != sp[0].stk_i)
! 		return NULL;			
  
! 	return args;
  }
  
  /*
--- 513,576 ----
  			break;
  		}	
  	}
! 
!   	if (state != DONE)
!  		flag = 1;
  
  	/* get a local version of argv[0]; l is offset back from end of stack */
  	l = (bufp->ps_stack + bufp->ps_ssize) -
! #if	(MACHINE == ATARI)
! 	(vir_bytes) sp[1].stk_cp;
! #else
! 	(bufp->ps_data + (vir_bytes) sp[1].stk_cp);
! #endif
  	if (l < 0 || l > cnt)
! 		flag = 1;
  	args = &((char *) stk)[cnt - (int) l];
  	neos = 0;
! 	for (cp = args; cp < &((char *) stk)[cnt] && !flag; cp++)
  		if (*cp == '\0')
+ #if	(CHIP == M68000) /* should be sizeof(int) != sizeof(void *) */
+ 			if (++neos >= (sp[0].stk_i & 0xffff))
+ #else
  			if (++neos >= sp[0].stk_i)
+ #endif
  				break;
  			else
  				*cp = ' ';	
+ #if	(CHIP == M68000) /* should be sizeof(int) != sizeof(void *) */
+ 	if (neos != (sp[0].stk_i & 0xffff))
+ #else
  	if (neos != sp[0].stk_i)
! #endif
! 		flag = 1;			
  
! 	if (flag)
! 	{
! #if	(MACHINE == ATARI)
! 		l = (bufp->ps_stack + bufp->ps_ssize) - (vir_bytes) AOUT[p_nr];
! 		args = &((char *) stk)[cnt - (int) l];
! 		e = &((char *) stk)[cnt];
! 		if ((args - 2) >= (char *)stk)
! 		{
! 			args -= 2;
! 			args[0] = '[';
! 			args[1] = ' ';
! 		}
! 		for (l = 0, cp = args; cp < e && *cp; cp++, l++)
! 			if (*cp < 0x20 || *cp > 0x7f)
! 				return (char *) NULL;
! 		if (cp >= e)
! 			return (char *) NULL;
! 		if ((args + strlen(args) + 3) < e)
! 			strcat(args, " ]");
! 		return(args);
! #else
! 		return (char *) NULL;
! #endif
! 	}
! 	else
! 		return args;
  }
  
  /*
***************
*** 576,582 ****
  	if (bufp->ps_state == Z_STATE)
  		bufp->ps_args = "<defunct>";
  	else if (p_nr > INIT_PROC_NR)
! 		bufp->ps_args = get_args(bufp);
  	
  	return 0;
  }
--- 651,657 ----
  	if (bufp->ps_state == Z_STATE)
  		bufp->ps_args = "<defunct>";
  	else if (p_nr > INIT_PROC_NR)
! 		bufp->ps_args = get_args(bufp, p_nr);
  	
  	return 0;
  }