[comp.os.minix] Changes to make F1 command display work better

rmtodd@uokmax.UUCP (Richard Michael Todd) (06/05/87)

  As most of you have probably noticed, the 'commands' list in the display
produced by pressing F1 is often inaccurate.  From what I've heard on the net,
the display gets even more confused if you have the memory compaction
mods posted by ganesh@utah-cs.UUCP.  Below I detail the problems with the
dump code and their solutions.  (I don't have the mem. compaction mods
installed, so I don't guarantee that the fixes I present here will solve that
part of the problem with F1. It looks as if they should.)
    In kernel/dmp.c, the names of the executing user processes are kept track
of through an array called aout, indexed by process number.  This array
contains pointers to the starts of the command strings for the processes. 
Zero indicates an inactive process slot. 
    Problem 1: Whenever the system task (kernel/system.c) does an exec or
exit for a process, it does a subroutine call to notify the dump routine,
which sets the appropriate entry in aout[] to the command name (for exec) or
0 (for exit).  Alas, system does not inform the dump routines when a process
forks.  Thus when a process forks (and the child does not immediately do an
exec), the dump routine still has aout[] for the child set to zero and thus
will not display what command the child is executing.  The fix is simple:
a new routine in dmp.c (named set_n_forked) to handle forks, and changing 
the system task fork routine to notify dmp.c.  The context diffs below
include this fix.
    Problem 2: The aout[] array stores the physical addresses of the command
strings, not the virtual addresses.  This means that if a process is moved
from one section of memory to another, the dump routine will still look for
the command string in the original location.  No wonder it gets confused by
the memory compaction.  The fix is simple: Change dmp.c to store virtual
addresses in aout[] and do the umap() call to derive physical addresses at
dump time.  This doesn't appear to add a significant amount of overhead to
the dump.  This fix is also included in the c-diffs below.
    Problem 3: The main loop in the p_dmp routine includes code to
automatically display "/bin/sh" for process 3, even though that may not be
what proc.  3 is executing.  Seeing "/bin/sh" is a bit disconcerting when you
know darn well it's executing /usr/bin/login.  Fix: delete this code. 
However,when you do this, you soon discover:
    Problem 4.  Processes created by INIT have null strings for argv[0]. 
This problem was concealed by problem 3 (though it wouldn't have stayed
concealed long when someone added another tty line and INIT had an immediate
descendant that wasn't process 3).  INIT uses a special variant of exec,
execn, that passes no arguments or environment pointers.  This allows it to
get away with not allocating a 1K buffer on the stack like all the other
versions of exec have to.  If you don't mind having INIT take up an extra 1K,
apply the patch below to cause INIT to use a different exec variant.
    With these patches installed, the F1 display seems to be fairly accurate.
It will display a null string in the command field only when the process is
actually in the middle of the exec system call.  Before, it'll show the name
it inherited from its parent; after, it'll show its new name.  A slight
difference between UNIX and MINIX is apparent: login shells (exec'd by
/usr/bin/login) display only "-" in their command field in MINIX, whereas
under UNIX, the argv[0] string is "-" followed by the shell's name (i.e.
"-csh" appears for a login C-shell).  If you think this is worth fixing in
MINIX, change login.c.
  Here are the context diffs to kernel/dmp.c, kernel/system.c, and
tools/init.c. Enjoy.
*** kernel/dmp.c.old	Fri May 29 07:54:15 1987
--- kernel/dmp.c.new	Thu Jun  4 21:37:47 1987
***************
*** 11,17
  #include "proc.h"
  
  #define NSIZE 20
! phys_bytes aout[NR_PROCS];	/* pointers to the program names */
  char nbuff[NSIZE+1];
  int vargv;
  

--- 11,17 -----
  #include "proc.h"
  
  #define NSIZE 20
! vir_bytes aout[NR_PROCS];	/* pointers to the program names */
  char nbuff[NSIZE+1];
  int vargv;
  
***************
*** 55,62
  	/* Fetch the command string from the user process. */
  	index = rp - proc - NR_TASKS;
  	if (index > LOW_USER && aout[index] != 0) {
! 		phys_copy(aout[index], dst, (long) NSIZE);
! 		aout[NSIZE] = 0;
  		for (np = &nbuff[0]; np < &nbuff[NSIZE]; np++)
  			if (*np <= ' ' || *np >= 0177) *np = 0;
  		if (index == LOW_USER + 1)

--- 55,66 -----
  	/* Fetch the command string from the user process. */
  	index = rp - proc - NR_TASKS;
  	if (index > LOW_USER && aout[index] != 0) {
! 		/* look up physical address of process name data */
! 		ltmp = umap(proc_addr(index),D,aout[index],NSIZE);
! 		if (ltmp == 0) continue;
! 		/* and copy the name string */
! 		phys_copy(ltmp, dst, (long) NSIZE);
! 		nbuff[NSIZE] = 0;
  		for (np = &nbuff[0]; np < &nbuff[NSIZE]; np++)
  			if (*np <= ' ' || *np >= 0177) *np = 0;
  		printf("%s", nbuff);
***************
*** 59,68
  		aout[NSIZE] = 0;
  		for (np = &nbuff[0]; np < &nbuff[NSIZE]; np++)
  			if (*np <= ' ' || *np >= 0177) *np = 0;
! 		if (index == LOW_USER + 1)
! 			printf("/bin/sh");
! 		else
! 			printf("%s", nbuff);
  	}
  	printf("\n");
    }

--- 63,69 -----
  		nbuff[NSIZE] = 0;
  		for (np = &nbuff[0]; np < &nbuff[NSIZE]; np++)
  			if (*np <= ' ' || *np >= 0177) *np = 0;
! 		printf("%s", nbuff);
  	}
  	printf("\n");
    }
***************
*** 122,128
    phys_bytes src, dst, count;
  
    if (ptr == (char *) 0) {
! 	aout[proc_nr] = (phys_bytes) 0;
  	return;
    }
  

--- 123,129 -----
    phys_bytes src, dst, count;
  
    if (ptr == (char *) 0) {
! 	aout[proc_nr] = (vir_bytes) 0;
  	return;
    }
  
***************
*** 131,135
    dst = umap(proc_addr(SYSTASK), D, &vargv, 2);
    phys_copy(src, dst, 2L);
  
!   aout[proc_nr] = umap(proc_addr(proc_nr), D, vargv, NSIZE);
  }

--- 132,144 -----
    dst = umap(proc_addr(SYSTASK), D, &vargv, 2);
    phys_copy(src, dst, 2L);
  
!   aout[proc_nr] = vargv;
! }
! /*
! ** When a fork is done, dmp needs to know about it so that the entry in the
! ** aout table can be copied for the child process.
! ** Function added 5-29-86 by rmtodd@uokmax
! */
! set_n_forked(parent,child) int parent,child; {
!   aout[child] = aout[parent];
  }
*** kernel/system.c.old	Fri May 29 07:54:31 1987
--- kernel/system.c.new	Fri May 29 08:19:50 1987
***************
*** 139,144
    rpc->sys_time = 0;
    rpc->child_utime = 0;
    rpc->child_stime = 0;
    return(OK);
  }
  

--- 139,145 -----
    rpc->sys_time = 0;
    rpc->child_utime = 0;
    rpc->child_stime = 0;
+   set_n_forked(k1,k2); /* notify F1 process table dump routine about fork */
    return(OK);
  }
  
*** tools/init.c.old	Sun Feb  6 00:34:36 2106
--- tools/init.c.new	Sun Feb  6 00:48:28 2106
***************
*** 5,10
   */
  
  #include "../h/signal.h"
  
  #define PIDSLOTS          10
  #define STACKSIZE        256

--- 5,11 -----
   */
  
  #include "../h/signal.h"
+ #include "../h/const.h"
  
  #define PIDSLOTS          10
  #define STACKSIZE        (256+MAX_ISTACK_BYTES)
***************
*** 7,13
  #include "../h/signal.h"
  
  #define PIDSLOTS          10
! #define STACKSIZE        256
  #define DIGIT              8
  
  char name[] = {"/dev/tty?"};	/* terminal names */

--- 8,15 -----
  #include "../h/const.h"
  
  #define PIDSLOTS          10
! #define STACKSIZE        (256+MAX_ISTACK_BYTES)
! /* ensure there's always enough space to exec */
  #define DIGIT              8
  
  char name[] = {"/dev/tty?"};	/* terminal names */
***************
*** 33,39
  	if (open("/etc/rc", 0) < 0) exit(-1);
  	open("/dev/tty0", 1);	/* std output */
  	open("/dev/tty0", 1);	/* std error */
! 	execn("/bin/sh");
  	exit(-2);		/* impossible */
    }
  

--- 35,41 -----
  	if (open("/etc/rc", 0) < 0) exit(-1);
  	open("/dev/tty0", 1);	/* std output */
  	open("/dev/tty0", 1);	/* std error */
! 	execl("/bin/sh","sh",0);
  	exit(-2);		/* impossible */
    }
  
***************
*** 90,99
  	if (open(name, 0) != 0) exit(-3);	/* standard input */
  	if (open(name, 1) != 1) exit(-3);	/* standard output */
  	if (open(name, 1) != 2) exit(-3);	/* standard error */
! 	execn("/usr/bin/login");
! 	execn("/bin/login");
! 	execn("/bin/sh");	/* last resort, if mount of /usr failed */
! 	execn("/usr/bin/sh");	/* last resort, if mount of /usr failed */
  	return;			/* impossible */
    }
  }

--- 92,101 -----
  	if (open(name, 0) != 0) exit(-3);	/* standard input */
  	if (open(name, 1) != 1) exit(-3);	/* standard output */
  	if (open(name, 1) != 2) exit(-3);	/* standard error */
! 	execl("/usr/bin/login","login",0);
! 	execl("/bin/login","login",0);
! 	execl("/bin/sh","sh",0);	/* last resort, if mount of /usr failed */
! 	execl("/usr/bin/sh","sh",0);	/* last resort, if mount of /usr failed */
  	return;			/* impossible */
    }
  }