echo x - Makefile.ansi
sed '/^X/s///' > Makefile.ansi << '/'
X# Set O=o for ANSI compiler and 68000 K&R compiler, or O=s for PC K&R compiler.
XO=o
X#O=s
X
X# Set b=/usr for /usr/include or b=<null string> for /include.
X#b=/usr
Xb=
X
X# Directories
Xi = $b/include
Xs = $i/sys
Xh = $i/minix
Xl = $b/lib
X
X# Programs, flags, and libraries
XCC = exec cc
XLD = $l/ld
XCV = $l/cv
X
X# Set compiler flags.
XCFLAGS = -I$i
X
X# Set LDFLAGS to -i for PC or <null string> for 68000.
XLDFLAGS =  -i
X#LDFLAGS = 
XHEAD = $l/nhead.$O
XLIB = $l/libc.A $l/libe.A $l/end.A
X
Xa = mm.h $h/config.h $s/types.h $h/const.h $h/type.h \
X  $i/ansi.h $i/tiny-fcntl.h $i/tiny-unistd.h $h/syslib.h \
X  $i/limits.h $i/errno.h \
X  const.h type.h proto.h glo.h
X
XOBJ = 	main.$O forkexit.$O break.$O exec.$O \
X	signal.$O alloc.$O utility.$O table.$O putk.$O trace.$O \
X	getset.$O
X
Xmm:	Makefile $(HEAD) $(OBJ) $(LIB)
X	$(LD) -o tmp $(LDFLAGS) $(HEAD) $(OBJ) $(LIB)
X	$(CV) tmp $@
X	@rm -f tmp
X
Xclean:
X	@rm -f *.s *.o *.bak mm
X
Xalloc.$O:	$a
X
Xbreak.$O:	$a
Xbreak.$O:	$i/signal.h
Xbreak.$O:	mproc.h
Xbreak.$O:	param.h
X
Xexec.$O:	$a
Xexec.$O:	$s/stat.h
Xexec.$O:	$h/callnr.h
Xexec.$O:	$i/signal.h
Xexec.$O:	mproc.h
Xexec.$O:	param.h
X
Xforkexit.$O:	$a
Xforkexit.$O:	$s/wait.h
Xforkexit.$O:	$h/callnr.h
Xforkexit.$O:	mproc.h
Xforkexit.$O:	param.h
X
Xgetset.$O:	$a
Xgetset.$O:	$h/callnr.h
Xgetset.$O:	mproc.h
Xgetset.$O:	param.h
X
Xmain.$O:	$a
Xmain.$O:	$h/callnr.h
Xmain.$O:	$h/com.h
Xmain.$O:	$i/signal.h
Xmain.$O:	mproc.h
Xmain.$O:	param.h
X
Xputk.$O:	$a
Xputk.$O:	$h/com.h
X
Xsignal.$O:	$a
Xsignal.$O:	$s/stat.h
Xsignal.$O:	$h/callnr.h
Xsignal.$O:	$h/com.h
Xsignal.$O:	$i/signal.h
Xsignal.$O:	mproc.h
Xsignal.$O:	param.h
X
Xtable.$O:	$a
Xtable.$O:	$h/callnr.h
Xtable.$O:	mproc.h
Xtable.$O:	param.h
X
Xtrace.$O:	$a
Xtrace.$O:	$i/signal.h
Xtrace.$O:	mproc.h
Xtrace.$O:	param.h
X
Xutility.$O:	$a
Xutility.$O:	$s/stat.h
Xutility.$O:	$h/callnr.h
Xutility.$O:	$h/com.h
Xutility.$O:	mproc.h
/
echo x - Makefile.kr
sed '/^X/s///' > Makefile.kr << '/'
X# Set O=o for ANSI compiler and 68000 K&R compiler, or O=s for PC K&R compiler.
X#O=o
XO=s
X
X# Set b=/usr for /usr/include or b=<null string> for /include.
Xb=/usr
X#b=
X
X# Directories
Xi = $b/include
Xs = $i/sys
Xh = $i/minix
Xl = $b/lib
X
X# Programs, flags, and libraries
XCC = exec cc
XLD = asld
X
X# Set compiler flags.
XCFLAGS = -I$i -D_EM_WSIZE=2
X
X# Set LDFLAGS to -i for PC or <null string> for 68000.
XLDFLAGS =  -i
X#LDFLAGS = 
XHEAD = $l/head.$O
XLIB = $l/libc.a $l/end.s
X
Xa = mm.h $h/config.h $s/types.h $h/const.h $h/type.h \
X  $i/ansi.h $i/tiny-fcntl.h $i/tiny-unistd.h $h/syslib.h \
X  $i/limits.h $i/errno.h \
X  const.h type.h proto.h glo.h
X
XOBJ = 	main.$O forkexit.$O break.$O exec.$O \
X	signal.$O alloc.$O utility.$O table.$O putk.$O trace.$O \
X	getset.$O
X
Xmm:	Makefile $(HEAD) $(OBJ) $(LIB)
X	$(LD) -i -s -o mm $(HEAD) $(OBJ)  $(LIB) >symbol.out
X	ast -X mm
X	@rm symbol.out
X
Xclean:
X	@rm -f *.s *.o *.bak mm
X
Xalloc.$O:	$a
X
Xbreak.$O:	$a
Xbreak.$O:	$i/signal.h
Xbreak.$O:	mproc.h
Xbreak.$O:	param.h
X
Xexec.$O:	$a
Xexec.$O:	$s/stat.h
Xexec.$O:	$h/callnr.h
Xexec.$O:	$i/signal.h
Xexec.$O:	mproc.h
Xexec.$O:	param.h
X
Xforkexit.$O:	$a
Xforkexit.$O:	$s/wait.h
Xforkexit.$O:	$h/callnr.h
Xforkexit.$O:	mproc.h
Xforkexit.$O:	param.h
X
Xgetset.$O:	$a
Xgetset.$O:	$h/callnr.h
Xgetset.$O:	mproc.h
Xgetset.$O:	param.h
X
Xmain.$O:	$a
Xmain.$O:	$h/callnr.h
Xmain.$O:	$h/com.h
Xmain.$O:	$i/signal.h
Xmain.$O:	mproc.h
Xmain.$O:	param.h
X
Xputk.$O:	$a
Xputk.$O:	$h/com.h
X
Xsignal.$O:	$a
Xsignal.$O:	$s/stat.h
Xsignal.$O:	$h/callnr.h
Xsignal.$O:	$h/com.h
Xsignal.$O:	$i/signal.h
Xsignal.$O:	mproc.h
Xsignal.$O:	param.h
X
Xtable.$O:	$a
Xtable.$O:	$h/callnr.h
Xtable.$O:	mproc.h
Xtable.$O:	param.h
X
Xtrace.$O:	$a
Xtrace.$O:	$i/signal.h
Xtrace.$O:	mproc.h
Xtrace.$O:	param.h
X
Xutility.$O:	$a
Xutility.$O:	$s/stat.h
Xutility.$O:	$h/callnr.h
Xutility.$O:	$h/com.h
Xutility.$O:	mproc.h
/
echo x - putk.c
sed '/^X/s///' > putk.c << '/'
X/* MM must occasionally print some message.  It uses the standard library
X * routine prink().  (The name "printf" is really a macro defined as "printk").
X * Printing is done by calling the TTY task directly, not going through FS.
X */
X
X#include "mm.h"
X#include <minix/com.h>
X
X#define BUF_SIZE          100	/* print buffer size */
X
XPRIVATE int buf_count;		/* # characters in the buffer */
XPRIVATE char print_buf[BUF_SIZE];	/* output is buffered here */
XPRIVATE message putch_msg;	/* used for message to TTY task */
X
X_PROTOTYPE( FORWARD void flush, (void) );
X
X/*===========================================================================*
X *				putk					     *
X *===========================================================================*/
XPUBLIC void putk(c)
Xint c;
X{
X/* Accumulate another character.  If '\n' or buffer full, print it. */
X
X  if (c == 0) {
X	flush();
X	return;
X  }
X  print_buf[buf_count++] = (char) c;
X  if (c == '\n' || buf_count == BUF_SIZE) flush();
X}
X
X
X/*===========================================================================*
X *				flush					     *
X *===========================================================================*/
XPRIVATE void flush()
X{
X/* Flush the print buffer by calling TTY task. */
X
X  if (buf_count == 0) return;
X  putch_msg.m_type = DEV_WRITE;
X  putch_msg.PROC_NR  = 0;
X  putch_msg.TTY_LINE = 0;
X  putch_msg.ADDRESS  = print_buf;
X  putch_msg.COUNT = buf_count;
X  sendrec(TTY, &putch_msg);
X  buf_count = 0;
X}
/
echo x - mm.cd
sed '/^X/s///' > mm.cd << '/'
Xecho x - alloc.c.d
Xsed '/^X/s///' > alloc.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/alloc.c  crc=65261   8510	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/alloc.c  crc=29940   8601	Tue Nov  3 21:19:34 1992
XX***************
XX*** 31,38 ****
XX  PRIVATE struct hole *hole_head;	/* pointer to first hole */
XX  PRIVATE struct hole *free_slots;	/* ptr to list of unused table slots */
XX  
XX! FORWARD void del_slot();
XX! FORWARD void merge();
XX  
XX  /*===========================================================================*
XX   *				alloc_mem				     *
XX--- 31,38 ----
XX  PRIVATE struct hole *hole_head;	/* pointer to first hole */
XX  PRIVATE struct hole *free_slots;	/* ptr to list of unused table slots */
XX  
XX! FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
XX! FORWARD _PROTOTYPE( void merge, (struct hole *hp)			    );
XX  
XX  /*===========================================================================*
XX   *				alloc_mem				     *
X/
Xecho x - break.c.d
Xsed '/^X/s///' > break.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/break.c  crc=32718   7430	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/break.c  crc=19900   7440	Tue Nov  3 21:19:34 1992
XX***************
XX*** 80,86 ****
XX    mem_sp = &rmp->mp_seg[S];	/* pointer to stack segment map */
XX    changed = 0;			/* set when either segment changed */
XX  
XX!   if(rmp - mproc == INIT_PROC_NR) return(OK);	/* don't bother init */
XX  
XX    /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
XX    base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
XX--- 80,86 ----
XX    mem_sp = &rmp->mp_seg[S];	/* pointer to stack segment map */
XX    changed = 0;			/* set when either segment changed */
XX  
XX!   if (mem_sp->mem_len == 0) return(OK);	/* don't bother init */
XX  
XX    /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
XX    base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
XX***************
XX*** 193,198 ****
XX    if (r == OK) return;
XX  
XX    /* Stack has bumped into data segment.  Kill the process. */
XX!   rmp->mp_catch = 0;		/* don't catch this signal */
XX    sig_proc(rmp, SIGSEGV);	/* terminate process */
XX  }
XX--- 193,198 ----
XX    if (r == OK) return;
XX  
XX    /* Stack has bumped into data segment.  Kill the process. */
XX!   sigdelset(&rmp->mp_catch, SIGSEGV);	/* don't catch this signal */
XX    sig_proc(rmp, SIGSEGV);	/* terminate process */
XX  }
X/
Xecho x - const.h.d
Xsed '/^X/s///' > const.h.d << '/'
XX*** /home/top/ast/minix/1.5/mm/const.h  crc=53152    990	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/const.h  crc=52618    985	Tue Nov  3 21:19:34 1992
XX***************
XX*** 3,16 ****
XX  #define ZEROBUF_SIZE	1024	/* buffer size for erasing memory */
XX  
XX  /* Size of MM's stack depends mostly on do_exec(). */
XX! #if (ZEROBUF_SIZE > MAX_PATH)
XX! #define MM_STACK_BYTES	(ARG_MAX + ZEROBUF_SIZE + 192 *sizeof (char *))
XX! #else
XX! #define MM_STACK_BYTES	(ARG_MAX + MAX_PATH + 192 * sizeof (char *))
XX! #endif
XX  
XX! #define NO_MEM (phys_clicks)0	/* returned by alloc_mem() with mem is up */
XX  
XX  /*DEBUG*/
XX  /* PAGE_SIZE should be SEGMENT_GRANULARITY and MAX_PAGES MAX_SEGMENTS.
XX   * The 386 segment granularity is 1 for segments smaller than 1M and 4096
XX--- 3,17 ----
XX  #define ZEROBUF_SIZE	1024	/* buffer size for erasing memory */
XX  
XX  /* Size of MM's stack depends mostly on do_exec(). */
XX! #define MM_STACK_BYTES	((ARG_MAX + PATH_MAX +  ZEROBUF_SIZE + \
XX! 	256 *sizeof (char *)) / sizeof(char *) * sizeof(char *))
XX  
XX! /* DEBUG.  Rounding the stack size to a multiple of sizeof (char *) is
XX!  * not sufficient on all machines.
XX!  */
XX  
XX+ #define NO_MEM ((phys_clicks) 0)  /* returned by alloc_mem() with mem is up */
XX+ 
XX  /*DEBUG*/
XX  /* PAGE_SIZE should be SEGMENT_GRANULARITY and MAX_PAGES MAX_SEGMENTS.
XX   * The 386 segment granularity is 1 for segments smaller than 1M and 4096
XX***************
XX*** 21,27 ****
XX  #define MAX_PAGES       4096	/* how many pages in the virtual addr space */
XX  #endif
XX  
XX- #define HDR_SIZE	  32	/* # bytes in the exec file header */
XX  #define printf        printk
XX  
XX  #define INIT_PID	   1	/* init's process id number */
XX--- 22,27 ----
X/
Xecho x - exec.c.d
Xsed '/^X/s///' > exec.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/exec.c  crc=35847  17169	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/exec.c  crc=12288  18715	Sat Mar 13 23:21:46 1993
XX***************
XX*** 8,13 ****
XX--- 8,14 ----
XX   *    - take care of setuid and setgid bits
XX   *    - fix up 'mproc' table
XX   *    - tell kernel about EXEC
XX+  *    - save offset to initial argc (for ps)
XX   *
XX   *   The only entry point is do_exec.
XX   */
XX***************
XX*** 15,42 ****
XX  #include "mm.h"
XX  #include <sys/stat.h>
XX  #include <minix/callnr.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX! #if INTEL_32BITS
XX! #define MAGIC    0x10000301L
XX! #else
XX! #define MAGIC    0x04000301L	/* magic number with 2 bits masked off */
XX! #endif
XX! #define SEP      0x00200000L	/* value for separate I & D */
XX! #define TEXTB              2	/* location of text size in header */
XX! #define DATAB              3	/* location of data size in header */
XX! #define BSSB               4	/* location of bss size in header */
XX! #define TOTB               6	/* location of total size in header */
XX! #define SYMB               7	/* location of symbol size in header */
XX  
XX! FORWARD void load_seg();
XX! FORWARD int new_mem();
XX! FORWARD void patch_ptr();
XX! FORWARD int read_header();
XX! 
XX! #if (CHIP == M68000)
XX! FORWARD int relocate();
XX  #endif
XX  
XX  /*===========================================================================*
XX--- 16,38 ----
XX  #include "mm.h"
XX  #include <sys/stat.h>
XX  #include <minix/callnr.h>
XX+ #include <a.out.h>
XX+ #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX! FORWARD _PROTOTYPE( void load_seg, (int fd, int seg, vir_bytes seg_bytes) );
XX! FORWARD _PROTOTYPE( int new_mem, (vir_bytes text_bytes, vir_bytes data_bytes,
XX! 		vir_bytes bss_bytes, vir_bytes stk_bytes, phys_bytes tot_bytes,
XX! 		char bf [ZEROBUF_SIZE ], int zs)			);
XX! FORWARD _PROTOTYPE( void patch_ptr, (char stack [ARG_MAX ], vir_bytes base) );
XX! FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes,
XX! 		vir_bytes *data_bytes, vir_bytes *bss_bytes,
XX! 		phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc,
XX! 		vir_bytes *pc)						);
XX  
XX! #if (SHADOWING == 1)
XX! FORWARD _PROTOTYPE( int relocate, (int fd, unsigned char *buf)		);
XX  #endif
XX  
XX  /*===========================================================================*
XX***************
XX*** 50,67 ****
XX   */
XX  
XX    register struct mproc *rmp;
XX!   int m, r, fd, ft;
XX!   char mbuf[ARG_MAX];	/* buffer for stack and zeroes */
XX!   union u {
XX! 	char name_buf[PATH_MAX];/* the name of the file to exec */
XX! 	char zb[ZEROBUF_SIZE];	/* used to zero bss */
XX!   } u;
XX    char *new_sp;
XX    vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
XX    phys_bytes tot_bytes;		/* total space for program, including gap */
XX    long sym_bytes;
XX    vir_clicks sc;
XX    struct stat s_buf;
XX  
XX    /* Do some validity checks. */
XX    rmp = mp;
XX--- 46,62 ----
XX   */
XX  
XX    register struct mproc *rmp;
XX!   int m, r, fd, ft, sn;
XX!   char mbuf[ARG_MAX];		/* buffer for stack and zeroes */
XX!   char name_buf[PATH_MAX];	/* the name of the file to exec */
XX!   char zb[ZEROBUF_SIZE];	/* used to zero bss */
XX    char *new_sp;
XX    vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
XX    phys_bytes tot_bytes;		/* total space for program, including gap */
XX    long sym_bytes;
XX    vir_clicks sc;
XX    struct stat s_buf;
XX+   vir_bytes pc;
XX  
XX    /* Do some validity checks. */
XX    rmp = mp;
XX***************
XX*** 71,88 ****
XX  
XX    /* Get the exec file name and see if the file is executable. */
XX    src = (vir_bytes) exec_name;
XX!   dst = (vir_bytes) u.name_buf;
XX    r = mem_copy(who, D, (long) src, MM_PROC_NR, D, (long) dst, (long) exec_len);
XX    if (r != OK) return(r);	/* file name not in user data segment */
XX!   tell_fs(CHDIR, who, 0, 0);	/* temporarily switch to user's directory */
XX!   fd = allowed(u.name_buf, &s_buf, X_BIT);	/* is file executable? */
XX!   tell_fs(CHDIR, 0, 1, 0);	/* switch back to MM's own directory */
XX    if (fd < 0) return(fd);	/* file was not executable */
XX  
XX    /* Read the file header and extract the segment sizes. */
XX    sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
XX! 						&tot_bytes, &sym_bytes, sc);
XX    if (m < 0) {
XX  	close(fd);		/* something wrong with header */
XX  	return(ENOEXEC);
XX--- 66,82 ----
XX  
XX    /* Get the exec file name and see if the file is executable. */
XX    src = (vir_bytes) exec_name;
XX!   dst = (vir_bytes) name_buf;
XX    r = mem_copy(who, D, (long) src, MM_PROC_NR, D, (long) dst, (long) exec_len);
XX    if (r != OK) return(r);	/* file name not in user data segment */
XX!   tell_fs(CHDIR, who, FALSE, 0);	/* switch to the user's FS environ. */
XX!   fd = allowed(name_buf, &s_buf, X_BIT);	/* is file executable? */
XX    if (fd < 0) return(fd);	/* file was not executable */
XX  
XX    /* Read the file header and extract the segment sizes. */
XX    sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 
XX! 					&tot_bytes, &sym_bytes, sc, &pc);
XX    if (m < 0) {
XX  	close(fd);		/* something wrong with header */
XX  	return(ENOEXEC);
XX***************
XX*** 91,97 ****
XX    /* Fetch the stack from the user before destroying the old core image. */
XX    src = (vir_bytes) stack_ptr;
XX    dst = (vir_bytes) mbuf;
XX!   r = mem_copy(who, D, (long) src, MM_PROC_NR, D, (long) dst, (long) stk_bytes);
XX    if (r != OK) {
XX  	close(fd);		/* can't fetch stack (e.g. bad virtual addr) */
XX  	return(EACCES);
XX--- 85,91 ----
XX    /* Fetch the stack from the user before destroying the old core image. */
XX    src = (vir_bytes) stack_ptr;
XX    dst = (vir_bytes) mbuf;
XX!   r = mem_copy(who, D, (long) src, MM_PROC_NR, D, (long) dst, (long)stk_bytes);
XX    if (r != OK) {
XX  	close(fd);		/* can't fetch stack (e.g. bad virtual addr) */
XX  	return(EACCES);
XX***************
XX*** 99,105 ****
XX  
XX    /* Allocate new memory and release old memory.  Fix map and tell kernel. */
XX    r = new_mem(text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes,
XX! 							u.zb, ZEROBUF_SIZE);
XX    if (r != OK) {
XX  	close(fd);		/* insufficient core or program too big */
XX  	return(r);
XX--- 93,99 ----
XX  
XX    /* Allocate new memory and release old memory.  Fix map and tell kernel. */
XX    r = new_mem(text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes,
XX! 							zb, ZEROBUF_SIZE);
XX    if (r != OK) {
XX  	close(fd);		/* insufficient core or program too big */
XX  	return(r);
XX***************
XX*** 111,148 ****
XX    vsp -= stk_bytes;
XX    patch_ptr(mbuf, vsp);
XX    src = (vir_bytes) mbuf;
XX!   r = mem_copy(MM_PROC_NR, D, (long) src, who, D, (long) vsp, (long) stk_bytes);
XX    if (r != OK) panic("do_exec stack copy err", NO_NUM);
XX  
XX    /* Read in text and data segments. */
XX    load_seg(fd, T, text_bytes);
XX    load_seg(fd, D, data_bytes);
XX! #if (CHIP == M68000)
XX!   if (lseek(fd, sym_bytes, 1) < 0)
XX! 	;	/* error */
XX!   if (relocate(fd, mbuf) < 0)
XX! 	;	/* error */
XX  #endif
XX    close(fd);			/* don't need exec file any more */
XX  
XX    /* Take care of setuid/setgid bits. */
XX    if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
XX  	if (s_buf.st_mode & I_SET_UID_BIT) {
XX  		rmp->mp_effuid = s_buf.st_uid;
XX! 		tell_fs(SETUID, who, (int) rmp->mp_realuid, (int) rmp->mp_effuid);
XX  	}
XX  	if (s_buf.st_mode & I_SET_GID_BIT) {
XX  		rmp->mp_effgid = s_buf.st_gid;
XX! 		tell_fs(SETGID, who, (int) rmp->mp_realgid, (int) rmp->mp_effgid);
XX  	}
XX    }
XX  
XX!   /* Fix up some 'mproc' fields and tell kernel that exec is done. */
XX!   rmp->mp_catch = 0;		/* reset all caught signals */
XX    rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
XX    rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
XX    new_sp = (char *) vsp;
XX!   sys_exec(who, new_sp, rmp->mp_flags & TRACED);
XX    return(OK);
XX  }
XX  
XX--- 105,155 ----
XX    vsp -= stk_bytes;
XX    patch_ptr(mbuf, vsp);
XX    src = (vir_bytes) mbuf;
XX!   r = mem_copy(MM_PROC_NR, D, (long) src, who, D, (long) vsp, (long)stk_bytes);
XX    if (r != OK) panic("do_exec stack copy err", NO_NUM);
XX  
XX    /* Read in text and data segments. */
XX    load_seg(fd, T, text_bytes);
XX    load_seg(fd, D, data_bytes);
XX! 
XX! #if (SHADOWING == 1)
XX!   if (lseek(fd, sym_bytes, 1) < 0) 	;		/* error */
XX!   if (relocate(fd, (unsigned char *)mbuf) < 0) 	;	/* error */
XX  #endif
XX+ 
XX    close(fd);			/* don't need exec file any more */
XX  
XX    /* Take care of setuid/setgid bits. */
XX    if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
XX  	if (s_buf.st_mode & I_SET_UID_BIT) {
XX  		rmp->mp_effuid = s_buf.st_uid;
XX! 		tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
XX  	}
XX  	if (s_buf.st_mode & I_SET_GID_BIT) {
XX  		rmp->mp_effgid = s_buf.st_gid;
XX! 		tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
XX  	}
XX    }
XX  
XX!   /* Save offset to initial argc (for ps) */
XX!   rmp->mp_procargs = vsp;
XX! 
XX!   /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
XX!   for (sn = 1; sn <= _NSIG; sn++) {
XX! 	if (sigismember(&rmp->mp_catch, sn)) {
XX! 		sigdelset(&rmp->mp_catch, sn);
XX! 		rmp->mp_sigact[sn].sa_handler = SIG_DFL;
XX! 		sigemptyset(&rmp->mp_sigact[sn].sa_mask);
XX! 		/* XXX - check what to do for sa_flags. */
XX! 	}
XX!   }
XX! 
XX    rmp->mp_flags &= ~SEPARATE;	/* turn off SEPARATE bit */
XX    rmp->mp_flags |= ft;		/* turn it on for separate I & D files */
XX    new_sp = (char *) vsp;
XX! 
XX!   tell_fs(EXEC, who, 0, 0);	/* allow FS to handle FD_CLOEXEC files */
XX!   sys_exec(who, new_sp, rmp->mp_flags & TRACED, name_buf, pc);
XX    return(OK);
XX  }
XX  
XX***************
XX*** 151,157 ****
XX   *				read_header				     *
XX   *===========================================================================*/
XX  PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, 
XX! 						    tot_bytes, sym_bytes, sc)
XX  int fd;				/* file descriptor for reading exec file */
XX  int *ft;			/* place to return ft number */
XX  vir_bytes *text_bytes;		/* place to return text size */
XX--- 158,164 ----
XX   *				read_header				     *
XX   *===========================================================================*/
XX  PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, 
XX! 						tot_bytes, sym_bytes, sc, pc)
XX  int fd;				/* file descriptor for reading exec file */
XX  int *ft;			/* place to return ft number */
XX  vir_bytes *text_bytes;		/* place to return text size */
XX***************
XX*** 160,204 ****
XX  phys_bytes *tot_bytes;		/* place to return total size */
XX  long *sym_bytes;		/* place to return symbol table size */
XX  vir_clicks sc;			/* stack size in clicks */
XX  {
XX  /* Read the header and extract the text, data, bss and total sizes from it. */
XX  
XX!   int m, ct;
XX    vir_clicks tc, dc, s_vir, dvir;
XX    phys_clicks totc;
XX!   long buf[HDR_SIZE/sizeof(long)];
XX  
XX    /* Read the header and check the magic number.  The standard MINIX header 
XX!    * consists of 8 longs, as follows:
XX!    *	0: 0x04100301L (combined I & D space) or 0x04200301L (separate I & D)
XX!    *	1: 0x00000020L 
XX!    *	2: size of text segments in bytes
XX!    *	3: size of initialized data segment in bytes
XX!    *	4: size of bss in bytes
XX!    *	5: 0x00000000L
XX!    *	6: total memory allocated to program (text, data and stack, combined)
XX!    *	7: size of symbol table in bytes
XX     * The longs are represented in a machine dependent order,
XX     * little-endian on the 8088, big-endian on the 68000.
XX     * The header is followed directly by the text and data segments, whose sizes
XX     * are given in the header.
XX     */
XX  
XX!   if (read(fd, buf, HDR_SIZE) != HDR_SIZE) return(ENOEXEC);
XX!   if ( (buf[0] & 0xFF0FFFFFL) != MAGIC) return(ENOEXEC);
XX!   *ft = (buf[0] & SEP ? SEPARATE : 0);	/* separate I & D or not */
XX  
XX    /* Get text and data sizes. */
XX!   *text_bytes = (vir_bytes) buf[TEXTB];	/* text size in bytes */
XX!   *data_bytes = (vir_bytes) buf[DATAB];	/* data size in bytes */
XX!   *bss_bytes = (vir_bytes) buf[BSSB];	/* bss size in bytes */
XX!   *sym_bytes = buf[SYMB];	/* symbol table size in bytes */
XX!   *tot_bytes = buf[TOTB];	/* total bytes to allocate for program */
XX    if (*tot_bytes == 0) return(ENOEXEC);
XX  
XX    if (*ft != SEPARATE) {
XX! #if (CHIP != M68000)
XX! 	/* If I & D space is not separated, it is all considered data. Text=0 */
XX  	*data_bytes += *text_bytes;
XX  	*text_bytes = 0;
XX  #else
XX--- 167,238 ----
XX  phys_bytes *tot_bytes;		/* place to return total size */
XX  long *sym_bytes;		/* place to return symbol table size */
XX  vir_clicks sc;			/* stack size in clicks */
XX+ vir_bytes *pc;
XX  {
XX  /* Read the header and extract the text, data, bss and total sizes from it. */
XX  
XX!   int m, ct, hdr_size;
XX    vir_clicks tc, dc, s_vir, dvir;
XX    phys_clicks totc;
XX!   struct exec hdr;		/* a.out header is read in here */
XX  
XX    /* Read the header and check the magic number.  The standard MINIX header 
XX!    * is defined in <a.out.h>.  It consists of 8 chars followed by 6 longs.
XX!    * Then come 4 more longs that are not used here.
XX!    *    Byte 0: magic number 0x01
XX!    *	Byte 1: magic number 0x03
XX!    *	Byte 2: normal = 0x10; separate I/D = 0x20
XX!    *	Byte 3: CPU type, Intel = 0x04, Motorola = 0x0B
XX!    *	Byte 4: Header length = 0x20
XX!    *	Bytes 5-7 are not used.
XX!    *
XX!    *	Now come the 6 longs
XX!    *	Bytes  8-11: size of text segments in bytes
XX!    *	Bytes 12-15: size of initialized data segment in bytes
XX!    *	Bytes 16-19: size of bss in bytes
XX!    *	Bytes 20-23: 0x00000000L
XX!    *	Bytes 24-27: total memory allocated to program (text, data + stack)
XX!    *	Bytes 28-31: size of symbol table in bytes
XX     * The longs are represented in a machine dependent order,
XX     * little-endian on the 8088, big-endian on the 68000.
XX     * The header is followed directly by the text and data segments, whose sizes
XX     * are given in the header.
XX     */
XX  
XX!   hdr_size = sizeof(struct exec) - 4 * sizeof(long);
XX!   if (read(fd, (char *) &hdr, hdr_size) != hdr_size) return(ENOEXEC);
XX! #if (CHIP == M68000)
XX!   if (hdr.a_cpu == A_MAGIC0 && hdr.a_flags == A_MAGIC1)
XX!   {
XX!     /* old style 68000 executable; convert header */
XX  
XX+     short version;
XX+ 
XX+     hdr.a_flags = hdr.a_magic[1];
XX+     hdr.a_cpu = 0xb; /* A_M68K */
XX+     hdr.a_magic[0] = A_MAGIC0;
XX+     hdr.a_magic[1] = A_MAGIC1;
XX+     version = (hdr.a_unused << 8) + hdr.a_hdrlen;
XX+     hdr.a_hdrlen = hdr.a_version & 0xff;
XX+     hdr.a_unused = (hdr.a_version >> 8) & 0xff;
XX+     hdr.a_version = version;
XX+   }
XX+ #endif
XX+   if (hdr.a_magic[0] != A_MAGIC0 || hdr.a_magic[1] != A_MAGIC1)return(ENOEXEC);
XX+   *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0);    /* separate I & D or not */
XX+ 
XX    /* Get text and data sizes. */
XX!   *text_bytes = (vir_bytes) hdr.a_text;	/* text size in bytes */
XX!   *data_bytes = (vir_bytes) hdr.a_data;	/* data size in bytes */
XX!   *bss_bytes  = (vir_bytes) hdr.a_bss;	/* bss size in bytes */
XX!   *tot_bytes  = hdr.a_total;		/* total bytes to allocate for prog */
XX!   *sym_bytes  = hdr.a_syms;		/* symbol table size in bytes */
XX    if (*tot_bytes == 0) return(ENOEXEC);
XX  
XX    if (*ft != SEPARATE) {
XX! 
XX! #if (SHADOWING == 0)
XX! 	/* If I & D space is not separated, it is all considered data. Text=0*/
XX  	*data_bytes += *text_bytes;
XX  	*text_bytes = 0;
XX  #else
XX***************
XX*** 217,235 ****
XX  	*data_bytes -= *text_bytes;
XX  	*tot_bytes -= *text_bytes;
XX  #endif
XX    }
XX  
XX- 
XX    /* Check to see if segment sizes are feasible. */
XX!   tc = (*text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    if (dc >= totc) return(ENOEXEC);	/* stack must be at least 1 click */
XX    dvir = (*ft == SEPARATE ? 0 : tc);
XX    s_vir = dvir + (totc - sc);
XX    m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
XX!   ct = buf[1] & BYTE;		/* header length */
XX!   if (ct > HDR_SIZE) read(fd, buf, ct - HDR_SIZE);	/* skip unused hdr */
XX    return(m);
XX  }
XX  
XX--- 251,270 ----
XX  	*data_bytes -= *text_bytes;
XX  	*tot_bytes -= *text_bytes;
XX  #endif
XX+ 
XX    }
XX+   *pc = 0x0;	/* XXX */
XX  
XX    /* Check to see if segment sizes are feasible. */
XX!   tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    if (dc >= totc) return(ENOEXEC);	/* stack must be at least 1 click */
XX    dvir = (*ft == SEPARATE ? 0 : tc);
XX    s_vir = dvir + (totc - sc);
XX    m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
XX!   ct = hdr.a_hdrlen & BYTE;		/* header length */
XX!   if (ct > hdr_size) read(fd, (char *)&hdr, ct-hdr_size); /* skip unused hdr*/
XX    return(m);
XX  }
XX  
XX***************
XX*** 237,243 ****
XX  /*===========================================================================*
XX   *				new_mem					     *
XX   *===========================================================================*/
XX! PRIVATE int new_mem(text_bytes, data_bytes, bss_bytes,stk_bytes,tot_bytes,bf,zs)
XX  vir_bytes text_bytes;		/* text segment size in bytes */
XX  vir_bytes data_bytes;		/* size of initialized data in bytes */
XX  vir_bytes bss_bytes;		/* size of bss in bytes */
XX--- 272,278 ----
XX  /*===========================================================================*
XX   *				new_mem					     *
XX   *===========================================================================*/
XX! PRIVATE int new_mem(text_bytes, data_bytes,bss_bytes,stk_bytes,tot_bytes,bf,zs)
XX  vir_bytes text_bytes;		/* text segment size in bytes */
XX  vir_bytes data_bytes;		/* size of initialized data in bytes */
XX  vir_bytes bss_bytes;		/* size of bss in bytes */
XX***************
XX*** 253,259 ****
XX    register struct mproc *rmp;
XX    vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
XX    phys_clicks new_base;
XX! #if (CHIP == M68000)
XX    phys_clicks base, size;
XX  #else
XX    char *rzp;
XX--- 288,295 ----
XX    register struct mproc *rmp;
XX    vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
XX    phys_clicks new_base;
XX! 
XX! #if (SHADOWING == 1)
XX    phys_clicks base, size;
XX  #else
XX    char *rzp;
XX***************
XX*** 267,273 ****
XX     * boundary.  The data and bss parts are run together with no space.
XX     */
XX  
XX!   text_clicks = (text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX--- 303,310 ----
XX     * boundary.  The data and bss parts are run together with no space.
XX     */
XX  
XX!   text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX! 				/* HACK */
XX    data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX    tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
XX***************
XX*** 282,288 ****
XX  
XX    /* There is enough memory for the new core image.  Release the old one. */
XX    rmp = mp;
XX! #if (CHIP != M68000)
XX    old_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
XX    old_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
XX    if (rmp->mp_flags & SEPARATE) old_clicks += rmp->mp_seg[T].mem_len;
XX--- 319,326 ----
XX  
XX    /* There is enough memory for the new core image.  Release the old one. */
XX    rmp = mp;
XX! 
XX! #if (SHADOWING == 0)
XX    old_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
XX    old_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
XX    if (rmp->mp_flags & SEPARATE) old_clicks += rmp->mp_seg[T].mem_len;
XX***************
XX*** 300,324 ****
XX    rmp->mp_seg[D].mem_phys = new_base + text_clicks;
XX    rmp->mp_seg[S].mem_len = stack_clicks;
XX    rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
XX  #if (CHIP == M68000)
XX    rmp->mp_seg[T].mem_vir = rmp->mp_seg[T].mem_phys;
XX    rmp->mp_seg[D].mem_vir = rmp->mp_seg[D].mem_phys;
XX    rmp->mp_seg[S].mem_vir = rmp->mp_seg[S].mem_phys;
XX  #else
XX    rmp->mp_seg[T].mem_vir = 0;
XX    rmp->mp_seg[D].mem_vir = 0;
XX    rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
XX  #endif
XX! #if (CHIP == M68000)
XX    sys_fresh(who, rmp->mp_seg, (phys_clicks)(data_bytes >> CLICK_SHIFT),
XX  			&base, &size);
XX    free_mem(base, size);
XX  #else
XX!   sys_newmap(who, rmp->mp_seg);	/* report new map to the kernel */
XX  
XX    /* Zero the bss, gap, and stack segment. Start just above text.  */
XX    for (rzp = &bf[0]; rzp < &bf[zs]; rzp++) *rzp = 0;	/* clear buffer */
XX!   bytes = (phys_bytes) (data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
XX    vzb = (vir_bytes) bf;
XX    base = (long) rmp->mp_seg[T].mem_phys + rmp->mp_seg[T].mem_len;
XX    base = base << CLICK_SHIFT;
XX--- 338,370 ----
XX    rmp->mp_seg[D].mem_phys = new_base + text_clicks;
XX    rmp->mp_seg[S].mem_len = stack_clicks;
XX    rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
XX+ 
XX  #if (CHIP == M68000)
XX+ #if (SHADOWING == 0)
XX+   rmp->mp_seg[T].mem_vir = 0;
XX+   rmp->mp_seg[D].mem_vir = rmp->mp_seg[T].mem_len;
XX+   rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + rmp->mp_seg[D].mem_len + gap_clicks;
XX+ #else
XX    rmp->mp_seg[T].mem_vir = rmp->mp_seg[T].mem_phys;
XX    rmp->mp_seg[D].mem_vir = rmp->mp_seg[D].mem_phys;
XX    rmp->mp_seg[S].mem_vir = rmp->mp_seg[S].mem_phys;
XX+ #endif
XX  #else
XX    rmp->mp_seg[T].mem_vir = 0;
XX    rmp->mp_seg[D].mem_vir = 0;
XX    rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
XX  #endif
XX! 
XX! #if (SHADOWING == 1)
XX    sys_fresh(who, rmp->mp_seg, (phys_clicks)(data_bytes >> CLICK_SHIFT),
XX  			&base, &size);
XX    free_mem(base, size);
XX  #else
XX!   sys_newmap(who, rmp->mp_seg);   /* report new map to the kernel */
XX  
XX    /* Zero the bss, gap, and stack segment. Start just above text.  */
XX    for (rzp = &bf[0]; rzp < &bf[zs]; rzp++) *rzp = 0;	/* clear buffer */
XX!   bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
XX    vzb = (vir_bytes) bf;
XX    base = (long) rmp->mp_seg[T].mem_phys + rmp->mp_seg[T].mem_len;
XX    base = base << CLICK_SHIFT;
XX***************
XX*** 334,339 ****
XX--- 380,386 ----
XX  	bytes -= count;
XX    }
XX  #endif
XX+ 
XX    return(OK);
XX  }
XX  
XX***************
XX*** 394,401 ****
XX  
XX    new_fd = (who << 8) | (seg << 6) | fd;
XX    ubuf_ptr = (char *) ((vir_bytes)mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
XX!   while (seg_bytes) {
XX! 	bytes = 31*1024;		/* <= 32767 */
XX  	if (seg_bytes < bytes)
XX  		bytes = (int)seg_bytes;
XX  	if (read(new_fd, ubuf_ptr, bytes) != bytes)
XX--- 441,448 ----
XX  
XX    new_fd = (who << 8) | (seg << 6) | fd;
XX    ubuf_ptr = (char *) ((vir_bytes)mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
XX!   while (seg_bytes != 0) {
XX! 	bytes = (INT_MAX / BLOCK_SIZE) * BLOCK_SIZE;
XX  	if (seg_bytes < bytes)
XX  		bytes = (int)seg_bytes;
XX  	if (read(new_fd, ubuf_ptr, bytes) != bytes)
XX***************
XX*** 405,424 ****
XX    }
XX  }
XX  
XX! #if (CHIP == M68000)
XX  /*===========================================================================*
XX   *				relocate				     *
XX   *===========================================================================*/
XX  PRIVATE int relocate(fd, buf)
XX  int fd;				/* file descriptor to read from */
XX! char *buf;			/* borrowed from do_exec() */
XX  {
XX!   register n;
XX!   register char *p;
XX!   register c;
XX    register phys_bytes off;
XX    register phys_bytes adr;
XX-   register struct mproc *rmp = mp;
XX  
XX    /* Read in relocation info from the exec file and relocate.
XX     * Relocation info is in GEMDOS format. Only longs can be relocated.
XX--- 452,469 ----
XX    }
XX  }
XX  
XX! #if (SHADOWING == 1)
XX  /*===========================================================================*
XX   *				relocate				     *
XX   *===========================================================================*/
XX  PRIVATE int relocate(fd, buf)
XX  int fd;				/* file descriptor to read from */
XX! unsigned char *buf;		/* borrowed from do_exec() */
XX  {
XX!   register int n;
XX!   register unsigned char *p, c;
XX    register phys_bytes off;
XX    register phys_bytes adr;
XX  
XX    /* Read in relocation info from the exec file and relocate.
XX     * Relocation info is in GEMDOS format. Only longs can be relocated.
XX***************
XX*** 440,476 ****
XX     * B==0bXXXXXXX1:
XX     *	illegal
XX     */
XX!   off = (phys_bytes)rmp->mp_seg[T].mem_phys << CLICK_SHIFT;
XX    p = buf;
XX!   n = read(fd, p, ARG_MAX);
XX!   if (n < sizeof(long))
XX! 	return(-1);	/* error */
XX!   if (*((long *)p) == 0)
XX! 	return(0);	/* ok */
XX    adr = off + *((long *)p);
XX    n -= sizeof(long);
XX    p += sizeof(long);
XX! 
XX!   for (;;) {			/* once per relocation */
XX! 	*((long *)adr) += off;
XX! 	for (;;) {		/* once per byte */
XX! 		if (--n < 0) {
XX! 			p = buf;
XX! 			n = read(fd, p, ARG_MAX);
XX! 			if (--n < 0)
XX! 				return(-1);	/* error */
XX! 		}
XX! 		c = *p++ & 0xFF;
XX! 		if (c != 1)
XX! 			break;
XX! 		adr += 254;
XX  	}
XX! 	if (c == 0)
XX! 		break;
XX! 	if (c & 1)
XX  		return(-1);	/* error */
XX! 	adr += c;
XX    }
XX-   return(0);	/* ok */
XX  }
XX  #endif
XX--- 485,517 ----
XX     * B==0bXXXXXXX1:
XX     *	illegal
XX     */
XX!   off = (phys_bytes)mp->mp_seg[T].mem_phys << CLICK_SHIFT;
XX    p = buf;
XX!   n = read(fd, (char *)p, ARG_MAX);
XX!   if (n < sizeof(long)) return(-1);	/* error */
XX!   if (*((long *)p) == 0) return(0);	/* ok */
XX    adr = off + *((long *)p);
XX    n -= sizeof(long);
XX    p += sizeof(long);
XX!   *((long *)adr) += off;
XX!   while (1) {			/* once per relocation byte */
XX! 	if (--n < 0) {
XX! 		p = buf;
XX! 		n = read(fd, (char *)p, ARG_MAX);
XX! 		if (--n < 0)
XX! 			return(-1);	/* error */
XX  	}
XX! 	c = *p++;
XX! 	if (c == 1)
XX! 		adr += 254;
XX! 	else if (c == 0)
XX! 		return(0);	/* ok */
XX! 	else if (c & 1)
XX  		return(-1);	/* error */
XX! 	else {
XX! 		adr += c;
XX! 		*((long *)adr) += off;
XX! 	}
XX    }
XX  }
XX  #endif
X/
Xecho x - forkexit.c.d
Xsed '/^X/s///' > forkexit.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/forkexit.c  crc=27670  10047	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/forkexit.c  crc=62795  10943	Mon Apr  5 15:48:20 1993
XX***************
XX*** 7,29 ****
XX   * exits first, it continues to occupy a slot until the parent does a WAIT.
XX   *
XX   * The entry points into this file are:
XX!  *   do_fork:	perform the FORK system call
XX!  *   do_mm_exit:	perform the EXIT system call (by calling mm_exit())
XX!  *   mm_exit:	actually do the exiting
XX!  *   do_wait:	perform the WAIT system call
XX   */
XX  
XX  
XX  #include "mm.h"
XX  #include <minix/callnr.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX  #define LAST_FEW            2	/* last few slots reserved for superuser */
XX  
XX! PRIVATE next_pid = INIT_PID+1;	/* next pid to be assigned */
XX  
XX! FORWARD void cleanup();
XX  
XX  /*===========================================================================*
XX   *				do_fork					     *
XX--- 7,31 ----
XX   * exits first, it continues to occupy a slot until the parent does a WAIT.
XX   *
XX   * The entry points into this file are:
XX!  *   do_fork:	 perform the FORK system call
XX!  *   do_mm_exit: perform the EXIT system call (by calling mm_exit())
XX!  *   mm_exit:	 actually do the exiting
XX!  *   do_wait:	 perform the WAITPID or WAIT system call
XX   */
XX  
XX  
XX  #include "mm.h"
XX+ #include <sys/wait.h>
XX  #include <minix/callnr.h>
XX+ #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX  #define LAST_FEW            2	/* last few slots reserved for superuser */
XX  
XX! PRIVATE pid_t next_pid = INIT_PID+1;	/* next pid to be assigned */
XX  
XX! FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
XX  
XX  /*===========================================================================*
XX   *				do_fork					     *
XX***************
XX*** 36,65 ****
XX    register struct mproc *rmc;	/* pointer to child */
XX    int i, child_nr, t;
XX    char *sptr, *dptr;
XX!   phys_clicks prog_clicks, child_base;
XX! #if (CHIP == INTEL)
XX!   long prog_bytes;
XX!   long parent_abs, child_abs;
XX! #endif
XX  
XX   /* If tables might fill up during FORK, don't even start since recovery half
XX    * way through is such a nuisance.
XX    */
XX- 
XX    rmp = mp;
XX    if (procs_in_use == NR_PROCS) return(EAGAIN);
XX!   if (procs_in_use >= NR_PROCS - LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN);
XX  
XX    /* Determine how much memory to allocate. */
XX    prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
XX    prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
XX! #if (CHIP == INTEL)
XX    if (rmp->mp_flags & SEPARATE) prog_clicks += rmp->mp_seg[T].mem_len;
XX    prog_bytes = (long) prog_clicks << CLICK_SHIFT;
XX  #endif
XX    if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(EAGAIN);
XX  
XX! #if (CHIP == INTEL)
XX    /* Create a copy of the parent's core image for the child. */
XX    child_abs = (long) child_base << CLICK_SHIFT;
XX    parent_abs = (long) rmp->mp_seg[T].mem_phys << CLICK_SHIFT;
XX--- 38,63 ----
XX    register struct mproc *rmc;	/* pointer to child */
XX    int i, child_nr, t;
XX    char *sptr, *dptr;
XX!   phys_clicks prog_clicks, child_base = 0;
XX!   long prog_bytes, parent_abs, child_abs;	/* Intel only */
XX  
XX   /* If tables might fill up during FORK, don't even start since recovery half
XX    * way through is such a nuisance.
XX    */
XX    rmp = mp;
XX    if (procs_in_use == NR_PROCS) return(EAGAIN);
XX!   if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN);
XX  
XX    /* Determine how much memory to allocate. */
XX    prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
XX    prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
XX! #if (SHADOWING == 0)
XX    if (rmp->mp_flags & SEPARATE) prog_clicks += rmp->mp_seg[T].mem_len;
XX    prog_bytes = (long) prog_clicks << CLICK_SHIFT;
XX  #endif
XX    if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(EAGAIN);
XX  
XX! #if (SHADOWING == 0)
XX    /* Create a copy of the parent's core image for the child. */
XX    child_abs = (long) child_base << CLICK_SHIFT;
XX    parent_abs = (long) rmp->mp_seg[T].mem_phys << CLICK_SHIFT;
XX***************
XX*** 81,87 ****
XX  
XX    rmc->mp_parent = who;		/* record child's parent */
XX    rmc->mp_flags &= ~TRACED;	/* child does not inherit trace status */
XX! #if (CHIP == INTEL)
XX    rmc->mp_seg[T].mem_phys = child_base;
XX    rmc->mp_seg[D].mem_phys = child_base + rmc->mp_seg[T].mem_len;
XX    rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
XX--- 79,85 ----
XX  
XX    rmc->mp_parent = who;		/* record child's parent */
XX    rmc->mp_flags &= ~TRACED;	/* child does not inherit trace status */
XX! #if (SHADOWING == 0)
XX    rmc->mp_seg[T].mem_phys = child_base;
XX    rmc->mp_seg[D].mem_phys = child_base + rmc->mp_seg[T].mem_len;
XX    rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 
XX***************
XX*** 106,120 ****
XX    if (who == INIT_PROC_NR) rmc->mp_procgrp = rmc->mp_pid;
XX  
XX    /* Tell kernel and file system about the (now successful) FORK. */
XX! #if (CHIP == M68000)
XX!   sys_fork(who, child_nr, rmc->mp_pid, child_base);
XX! #else
XX!   sys_fork(who, child_nr, rmc->mp_pid);
XX! #endif
XX! 
XX    tell_fs(FORK, who, child_nr, rmc->mp_pid);
XX  
XX! #if (CHIP == INTEL)
XX    /* Report child's memory map to kernel. */
XX    sys_newmap(child_nr, rmc->mp_seg);
XX  #endif
XX--- 104,113 ----
XX    if (who == INIT_PROC_NR) rmc->mp_procgrp = rmc->mp_pid;
XX  
XX    /* Tell kernel and file system about the (now successful) FORK. */
XX!   sys_fork(who, child_nr, rmc->mp_pid, child_base); /* child_base is 68K only*/
XX    tell_fs(FORK, who, child_nr, rmc->mp_pid);
XX  
XX! #if (SHADOWING == 0)
XX    /* Report child's memory map to kernel. */
XX    sys_newmap(child_nr, rmc->mp_seg);
XX  #endif
XX***************
XX*** 147,188 ****
XX  register struct mproc *rmp;	/* pointer to the process to be terminated */
XX  int exit_status;		/* the process' exit status (for parent) */
XX  {
XX! /* A process is done.  If parent is waiting for it, clean it up, else hang. */
XX! #if (CHIP == M68000)
XX!   phys_clicks base, size;
XX! #else
XX!   phys_clicks s;
XX! #endif
XX!   register int proc_nr = (int)(rmp - mproc);
XX  
XX!   /* How to terminate a process is determined by whether or not the
XX!    * parent process has already done a WAIT.  Test to see if it has.
XX!    */
XX!   rmp->mp_exitstatus = (char) exit_status;	/* store status in 'mproc' */
XX  
XX!   if (mproc[rmp->mp_parent].mp_flags & WAITING)
XX! 	cleanup(rmp);		/* release parent and tell everybody */
XX!   else
XX! 	rmp->mp_flags |= HANGING;	/* Parent not waiting.  Suspend proc */
XX  
XX    /* If the exited process has a timer pending, kill it. */
XX    if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0);
XX  
XX- #if AM_KERNEL
XX- /* see if an amoeba transaction was pending or a putrep needed to be done */
XX-   am_check_sig(proc_nr, 1);
XX- #endif
XX- 
XX    /* Tell the kernel and FS that the process is no longer runnable. */
XX! #if (CHIP == M68000)
XX    sys_xit(rmp->mp_parent, proc_nr, &base, &size);
XX    free_mem(base, size);
XX- #else
XX-   sys_xit(rmp->mp_parent, proc_nr);
XX  #endif
XX-   tell_fs(EXIT, proc_nr, 0, 0);  /* file system can free the proc slot */
XX  
XX! #if (CHIP == INTEL)
XX    /* Release the memory occupied by the child. */
XX    s = (phys_clicks) rmp->mp_seg[S].mem_len;
XX    s += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
XX--- 140,167 ----
XX  register struct mproc *rmp;	/* pointer to the process to be terminated */
XX  int exit_status;		/* the process' exit status (for parent) */
XX  {
XX! /* A process is done.  Release most of the process' possessions.  If its
XX!  * parent is waiting, release the rest, else hang.
XX!  */
XX  
XX!   register int proc_nr;
XX!   int parent_waiting, right_child;
XX!   pid_t pidarg;
XX!   phys_clicks base, size, s;	/* base and size used on 68000 only */
XX  
XX!   proc_nr = (int) (rmp - mproc);	/* get process slot number */
XX  
XX    /* If the exited process has a timer pending, kill it. */
XX    if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0);
XX  
XX    /* Tell the kernel and FS that the process is no longer runnable. */
XX!   tell_fs(EXIT, proc_nr, 0, 0);  /* file system can free the proc slot */
XX    sys_xit(rmp->mp_parent, proc_nr, &base, &size);
XX+ #if (SHADOWING == 1)
XX    free_mem(base, size);
XX  #endif
XX  
XX! #if (SHADOWING == 0)
XX    /* Release the memory occupied by the child. */
XX    s = (phys_clicks) rmp->mp_seg[S].mem_len;
XX    s += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
XX***************
XX*** 190,228 ****
XX    free_mem(rmp->mp_seg[T].mem_phys, s);	/* free the memory */
XX  #endif
XX  
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_wait					     *
XX   *===========================================================================*/
XX! PUBLIC int do_wait()
XX  {
XX  /* A process wants to wait for a child to terminate. If one is already waiting,
XX   * go clean it up and let this WAIT call terminate.  Otherwise, really wait.
XX   */
XX  
XX    register struct mproc *rp;
XX!   register int children;
XX  
XX    /* A process calling WAIT never gets a reply in the usual way via the
XX!    * reply() in the main loop.  If a child has already exited, the routine
XX!    * cleanup() sends the reply to awaken the caller.
XX     */
XX  
XX!   /* Is there a child waiting to be collected? */
XX    children = 0;
XX    for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
XX  	if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) {
XX! 		children++;
XX  		if (rp->mp_flags & HANGING) {
XX! 			cleanup(rp);	/* a child has already exited */
XX  			dont_reply = TRUE;
XX  			return(OK);
XX  		}
XX! 		if (rp->mp_flags & STOPPED && rp->mp_sigstatus) {
XX! 			reply(who, rp->mp_pid, 0177 | (rp->mp_sigstatus << 8),
XX! 				NIL_PTR);
XX  			dont_reply = TRUE;
XX  			rp->mp_sigstatus = 0;
XX  			return(OK);
XX--- 169,246 ----
XX    free_mem(rmp->mp_seg[T].mem_phys, s);	/* free the memory */
XX  #endif
XX  
XX+   /* The process slot can only be freed if the parent has done a WAIT. */
XX+   rmp->mp_exitstatus = (char) exit_status;
XX+   pidarg = mproc[rmp->mp_parent].mp_wpid;	/* who's being waited for? */
XX+   parent_waiting = mproc[rmp->mp_parent].mp_flags & WAITING;
XX+   if (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp)
XX+ 	right_child = TRUE;		/* child meets one of the 3 tests */
XX+   else
XX+ 	right_child = FALSE;		/* child fails all 3 tests */
XX+   if (parent_waiting && right_child)
XX+ 	cleanup(rmp);		/* tell parent and release child slot */
XX+   else
XX+ 	rmp->mp_flags |= HANGING;	/* parent not waiting, suspend child */
XX+ 
XX+   /* If the process has children, disinherit them.  INIT is the new parent. */
XX+   for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
XX+ 	if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
XX+ 		/* 'rmp' now points to a child to be disinherited. */
XX+ 		rmp->mp_parent = INIT_PROC_NR;
XX+ 		parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
XX+ 		if (parent_waiting && (rmp->mp_flags & HANGING)) cleanup(rmp);
XX+ 	}
XX+   }
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				do_waitpid				     *
XX   *===========================================================================*/
XX! PUBLIC int do_waitpid()
XX  {
XX  /* A process wants to wait for a child to terminate. If one is already waiting,
XX   * go clean it up and let this WAIT call terminate.  Otherwise, really wait.
XX+  * Both WAIT and WAITPID are handled by this code.
XX   */
XX  
XX    register struct mproc *rp;
XX!   int pidarg, options, children, res2;
XX  
XX    /* A process calling WAIT never gets a reply in the usual way via the
XX!    * reply() in the main loop (unless WNOHANG is set or no qualifying child
XX!    * exists).  If a child has already exited, the routine cleanup() sends 
XX!    * the reply to awaken the caller.
XX     */
XX  
XX!   /* Set internal variables, depending on whether this is WAIT or WAITPID. */
XX!   pidarg  = (mm_call == WAIT ? -1 : pid);	/* first param of waitpid */
XX!   options = (mm_call == WAIT ?  0 : sig_nr);	/* third param of waitpid */
XX!   if (pidarg == 0) pidarg = -mp->mp_procgrp;	/* pidarg < 0 ==> proc grp */
XX! 
XX!   /* Is there a child waiting to be collected? At this point, pidarg != 0:
XX!    *	pidarg  >  0 means pidarg is pid of a specific process to wait for
XX!    *	pidarg == -1 means wait for any child
XX!    *	pidarg  < -1 means wait for any child whose process group = -pidarg
XX!    */
XX    children = 0;
XX    for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
XX  	if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) {
XX! 		/* The value of pidarg determines which children qualify. */
XX! 		if (pidarg  > 0 && pidarg != rp->mp_pid) continue;
XX! 		if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
XX! 
XX! 		children++;		/* this child is acceptable */
XX  		if (rp->mp_flags & HANGING) {
XX! 			/* This child meets the pid test and has exited. */
XX! 			cleanup(rp);	/* this child has already exited */
XX  			dont_reply = TRUE;
XX  			return(OK);
XX  		}
XX! 		if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
XX! 			/* This child meets the pid test and is being traced.*/
XX! 			res2 =  0177 | (rp->mp_sigstatus << 8);
XX! 			reply(who, rp->mp_pid, res2, NIL_PTR);
XX  			dont_reply = TRUE;
XX  			rp->mp_sigstatus = 0;
XX  			return(OK);
XX***************
XX*** 230,242 ****
XX  	}
XX    }
XX  
XX!   /* No child has exited.  Wait for one, unless none exists. */
XX!   if (children > 0) {		/* does this process have any children? */
XX! 	mp->mp_flags |= WAITING;
XX! 	dont_reply = TRUE;
XX! 	return(OK);		/* yes - wait for one to exit */
XX!   } else
XX! 	return(ECHILD);		/* no - parent has no children */
XX  }
XX  
XX  
XX--- 248,265 ----
XX  	}
XX    }
XX  
XX!   /* No qualifying child has exited.  Wait for one, unless none exists. */
XX!   if (children > 0) {
XX! 	/* At least 1 child meets the pid test exists, but has not exited. */
XX! 	if (options & WNOHANG) return(0);    /* parent does not want to wait */
XX! 	mp->mp_flags |= WAITING;	     /* parent wants to wait */
XX! 	mp->mp_wpid = (pid_t) pidarg;	     /* save pid for later */
XX! 	dont_reply = TRUE;		     /* do not reply now though */
XX! 	return(OK);			     /* yes - wait for one to exit */
XX!   } else {
XX! 	/* No child even meets the pid test.  Return error immediately. */
XX! 	return(ECHILD);			     /* no - parent has no children */
XX!   }
XX  }
XX  
XX  
XX***************
XX*** 246,291 ****
XX  PRIVATE void cleanup(child)
XX  register struct mproc *child;	/* tells which process is exiting */
XX  {
XX! /* Clean up the remains of a process.  This routine is only called if two
XX!  * conditions are satisfied:
XX!  *     1. The process has done an EXIT or has been killed by a signal.
XX!  *     2. The process' parent has done a WAIT.
XX!  *
XX!  * It releases the memory, if that has not been done yet.  Whether it has or
XX!  * has not been done depends on the order of the EXIT and WAIT calls.
XX   */
XX  
XX!   register struct mproc *parent, *rp;
XX!   int init_waiting, child_nr;
XX!   unsigned int r;
XX  
XX!   child_nr = (int)(child - mproc);
XX!   parent = &mproc[child->mp_parent];
XX  
XX!   /* Wakeup the parent. */
XX!   r = child->mp_sigstatus & 0377;
XX!   r = r | (child->mp_exitstatus << 8);
XX!   reply(child->mp_parent, child->mp_pid, r, NIL_PTR);
XX! 
XX!   /* Update flags. */
XX!   child->mp_flags  &= ~TRACED;	/* turn off TRACED bit */
XX!   child->mp_flags  &= ~HANGING;	/* turn off HANGING bit */
XX!   child->mp_flags  &= ~PAUSED;	/* turn off PAUSED bit */
XX!   parent->mp_flags &= ~WAITING;	/* parent is no longer waiting */
XX!   child->mp_flags  &= ~IN_USE;	/* release the table slot */
XX    procs_in_use--;
XX- 
XX-   /* If exiting process has children, disinherit them.  INIT is new parent. */
XX-   init_waiting = (mproc[INIT_PROC_NR].mp_flags & WAITING ? 1 : 0);
XX-   for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
XX-   	if (rp->mp_parent == child_nr) {
XX-   		/* 'rp' points to a child to be disinherited. */
XX-   		rp->mp_parent = INIT_PROC_NR;	/* init takes over */
XX-   		if (init_waiting && (rp->mp_flags & HANGING) ) {
XX-   			/* Init was waiting. */
XX-   			cleanup(rp);	/* recursive call */
XX-   			init_waiting = 0;
XX-   		}
XX-   	}
XX-   }
XX  }
XX--- 269,286 ----
XX  PRIVATE void cleanup(child)
XX  register struct mproc *child;	/* tells which process is exiting */
XX  {
XX! /* Finish off the exit of a process.  The process has exited or been killed
XX!  * by a signal, and its parent is waiting.
XX   */
XX  
XX!   int exitstatus;
XX  
XX!   /* Wake up the parent. */
XX!   exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377);
XX!   reply(child->mp_parent, child->mp_pid, exitstatus, NIL_PTR);
XX!   mproc[child->mp_parent].mp_flags &= ~WAITING;	/* parent no longer waiting */
XX  
XX!   /* Release the process table entry. */
XX!   child->mp_flags = 0;
XX    procs_in_use--;
XX  }
X/
Xecho x - getset.c.d
Xsed '/^X/s///' > getset.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/getset.c  crc=50882   1482	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/getset.c  crc=07482   1536	Tue Nov  3 21:19:35 1992
XX***************
XX*** 5,10 ****
XX--- 5,11 ----
XX  
XX  #include "mm.h"
XX  #include <minix/callnr.h>
XX+ #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX***************
XX*** 54,59 ****
XX--- 55,63 ----
XX  		tell_fs(SETGID, who, grpid, grpid);
XX  		r = OK;
XX  		break;
XX+ 	default:
XX+ 		r = EINVAL;
XX+ 		break;	
XX    }
XX  
XX    return(r);
X/
Xecho x - glo.h.d
Xsed '/^X/s///' > glo.h.d << '/'
XX*** /home/top/ast/minix/1.5/mm/glo.h  crc=11409   1145	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/glo.h  crc=36294   1303	Tue Nov  3 21:19:35 1992
XX***************
XX*** 20,30 ****
XX  EXTERN int result2;		/* secondary result */
XX  EXTERN char *res_ptr;		/* result, if pointer */
XX  
XX! extern int (*call_vec[])();	/* functions to handle system calls */
XX  extern char core_name[];	/* file name where core images are produced */
XX! extern unshort core_bits;	/* which signals cause core images */
XX  EXTERN char mm_stack[MM_STACK_BYTES];	/* MM's stack */
XX  
XX! /* Library variables. */
XX! extern int errno;
XX! 
XX--- 20,31 ----
XX  EXTERN int result2;		/* secondary result */
XX  EXTERN char *res_ptr;		/* result, if pointer */
XX  
XX! extern _PROTOTYPE (int (*call_vec[]), (void) );	/* system call handlers */
XX  extern char core_name[];	/* file name where core images are produced */
XX! EXTERN sigset_t core_bits;	/* which signals cause core images */
XX  EXTERN char mm_stack[MM_STACK_BYTES];	/* MM's stack */
XX  
XX! /* DEBUG.  There is nothing to force this stack to be aligned.  char variables
XX!  * do not require alignment on most systems.  The rounding of MM_STACK_BYTES
XX!  * in const.h is not sufficient.
XX!  */
X/
Xecho x - main.c.d
Xsed '/^X/s///' > main.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/main.c  crc=16831   7979	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/main.c  crc=21798   8774	Tue Nov  3 21:19:35 1992
XX***************
XX*** 16,26 ****
XX  #include "mm.h"
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX! FORWARD void get_work();
XX! FORWARD void mm_init();
XX  
XX  /*===========================================================================*
XX   *				main					     *
XX--- 16,27 ----
XX  #include "mm.h"
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX+ #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX! FORWARD _PROTOTYPE( void get_work, (void)				);
XX! FORWARD _PROTOTYPE( void mm_init, (void)				);
XX  
XX  /*===========================================================================*
XX   *				main					     *
XX***************
XX*** 62,68 ****
XX   *				get_work				     *
XX   *===========================================================================*/
XX  PRIVATE void get_work()
XX! {  
XX  /* Wait for the next message and extract useful information from it. */
XX  
XX    if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
XX--- 63,69 ----
XX   *				get_work				     *
XX   *===========================================================================*/
XX  PRIVATE void get_work()
XX! {
XX  /* Wait for the next message and extract useful information from it. */
XX  
XX    if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
XX***************
XX*** 84,92 ****
XX  
XX    register struct mproc *proc_ptr;
XX  
XX-   /* To make MM robust, check to see if destination is still alive. */
XX    proc_ptr = &mproc[proc_nr];
XX!   if ( (proc_ptr->mp_flags&IN_USE) == 0 || (proc_ptr->mp_flags&HANGING)) return;
XX    reply_type = result;
XX    reply_i1 = res2;
XX    reply_p1 = respt;
XX--- 85,98 ----
XX  
XX    register struct mproc *proc_ptr;
XX  
XX    proc_ptr = &mproc[proc_nr];
XX!   /* 
XX!    * To make MM robust, check to see if destination is still alive.  This
XX!    * validy check must be skipped if the caller is a task.
XX!    */
XX!   if ((who >=0) && ((proc_ptr->mp_flags&IN_USE) == 0 || 
XX! 	(proc_ptr->mp_flags&HANGING))) return;
XX! 
XX    reply_type = result;
XX    reply_i1 = res2;
XX    reply_p1 = respt;
XX***************
XX*** 101,114 ****
XX  {
XX  /* Initialize the memory manager. */
XX  
XX    mem_init();			/* initialize tables to all physical mem */
XX  
XX    /* Initialize MM's tables. */
XX!   mproc[MM_PROC_NR].mp_flags |= IN_USE;
XX!   mproc[FS_PROC_NR].mp_flags |= IN_USE;
XX    mproc[INIT_PROC_NR].mp_flags |= IN_USE;
XX    mproc[INIT_PROC_NR].mp_pid = INIT_PID;
XX!   procs_in_use = 3;
XX  }
XX  
XX  
XX--- 107,135 ----
XX  {
XX  /* Initialize the memory manager. */
XX  
XX+   static char core_sigs[] = {
XX+ 	SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
XX+ 	SIGEMT, SIGFPE, SIGUSR1, SIGSEGV,
XX+ 	SIGUSR2, 0 };
XX+   register struct mproc *rmp;
XX+   register char *sig_ptr;
XX+ 
XX    mem_init();			/* initialize tables to all physical mem */
XX  
XX+   /* Build the set of signals which cause core dumps.
XX+    * (core_bits is now misnamed.  DEBUG.)
XX+    */
XX+   sigemptyset(&core_bits);
XX+   for (sig_ptr = core_sigs; *sig_ptr != 0; sig_ptr++)
XX+ 	sigaddset(&core_bits, *sig_ptr);
XX+ 
XX    /* Initialize MM's tables. */
XX!   for (rmp = &mproc[0]; rmp < &mproc[LOW_USER]; rmp++) rmp->mp_flags |= IN_USE;
XX    mproc[INIT_PROC_NR].mp_flags |= IN_USE;
XX    mproc[INIT_PROC_NR].mp_pid = INIT_PID;
XX!   sigemptyset(&mproc[INIT_PROC_NR].mp_ignore);
XX!   sigemptyset(&mproc[INIT_PROC_NR].mp_catch);
XX!   procs_in_use = LOW_USER + 1;
XX  }
XX  
XX  
XX***************
XX*** 137,143 ****
XX    /* Remove the memory used by MINIX from the memory map. */
XX    init_text_clicks = mm_in.m1_i1;	/* size of INIT in clicks */
XX    init_data_clicks = mm_in.m1_i2;	/* size of INIT in clicks */
XX!   init_org = (phys_clicks) mm_in.m1_p1;	/* addr where INIT begins in memory */
XX    init_clicks = init_text_clicks + init_data_clicks;
XX    minix_clicks = init_org + init_clicks;	/* size of system in clicks */
XX    ram_base = alloc_mem(minix_clicks);	/* remove MINIX from map */
XX--- 158,164 ----
XX    /* Remove the memory used by MINIX from the memory map. */
XX    init_text_clicks = mm_in.m1_i1;	/* size of INIT in clicks */
XX    init_data_clicks = mm_in.m1_i2;	/* size of INIT in clicks */
XX!   init_org = (phys_clicks) ((int) mm_in.m1_p1);	/* INIT's mem addr */
XX    init_clicks = init_text_clicks + init_data_clicks;
XX    minix_clicks = init_org + init_clicks;	/* size of system in clicks */
XX    ram_base = alloc_mem(minix_clicks);	/* remove MINIX from map */
XX***************
XX*** 168,184 ****
XX    mem2 = click_to_round_k(minix_clicks);
XX  #endif
XX    mem3 = click_to_round_k(ram_clicks);
XX! #if (CHIP == INTEL)
XX!   printf("%c[H%c[J",033, 033);	/* go to top of screen and clear screen */
XX  #endif
XX!   printf("Memory size = %4dK     ", mem1);
XX!   printf("MINIX = %3dK     ", mem2);
XX!   printf("RAM disk = %4dK     ", mem3);
XX!   printf("Available = %dK\n\n", mem1 - mem2 - mem3);
XX!   if (mem1 - mem2 - mem3 < 32) {
XX! 	printf("\nNot enough memory to run MINIX\n\n", NO_NUM);
XX! 	sys_abort();
XX!   }
XX  
XX    /* Initialize INIT's table entry. */
XX    rmp = &mproc[INIT_PROC_NR];
XX--- 189,203 ----
XX    mem2 = click_to_round_k(minix_clicks);
XX  #endif
XX    mem3 = click_to_round_k(ram_clicks);
XX! #if (MACHINE == IBM_PC)		/* why not for no-one or everyone? */
XX!   printf("\033[H\033[J");	/* go to top of screen and clear screen */
XX  #endif
XX!   printf("Memory size =%5dK   ", mem1);
XX!   printf("MINIX =%4dK   ", mem2);
XX!   printf("RAM disk =%5dK   ", mem3);
XX!   printf("Available =%5dK\n\n", mem1 - mem2 - mem3);
XX!   if (mem1 - mem2 - mem3 < 32)
XX! 	panic("not enough memory to run MINIX", NO_NUM);
XX  
XX    /* Initialize INIT's table entry. */
XX    rmp = &mproc[INIT_PROC_NR];
XX***************
XX*** 188,196 ****
XX--- 207,221 ----
XX    rmp->mp_seg[D].mem_len  = init_data_clicks;
XX    rmp->mp_seg[S].mem_phys = init_org + init_clicks;
XX  #if (CHIP == M68000)
XX+ #if (SHADOWING == 0)
XX+   rmp->mp_seg[T].mem_vir  = 0;
XX+   rmp->mp_seg[D].mem_vir  = init_text_clicks;
XX+   rmp->mp_seg[S].mem_vir  = init_clicks;
XX+ #else
XX    rmp->mp_seg[T].mem_vir  = rmp->mp_seg[T].mem_phys;
XX    rmp->mp_seg[D].mem_vir  = rmp->mp_seg[D].mem_phys;
XX    rmp->mp_seg[S].mem_vir  = rmp->mp_seg[S].mem_phys;
XX+ #endif
XX  #else
XX    rmp->mp_seg[S].mem_vir  = init_clicks;
XX  #endif
XX***************
XX*** 216,222 ****
XX    mm_out.m_type = SYS_MEM;
XX    mm_out.DEVICE = extflag;
XX    if (sendrec(SYSTASK, &mm_out) != OK || mm_out.m_type != OK)
XX! 	panic("Kernel didn't respond to get_mem", NO_NUM);
XX    *pbase = (phys_clicks) mm_out.POSITION;
XX    return((phys_clicks) mm_out.COUNT);
XX  }
XX--- 241,247 ----
XX    mm_out.m_type = SYS_MEM;
XX    mm_out.DEVICE = extflag;
XX    if (sendrec(SYSTASK, &mm_out) != OK || mm_out.m_type != OK)
XX! 	panic("kernel didn't respond to get_mem", NO_NUM);
XX    *pbase = (phys_clicks) mm_out.POSITION;
XX    return((phys_clicks) mm_out.COUNT);
XX  }
X/
Xecho x - mm.h.d
Xsed '/^X/s///' > mm.h.d << '/'
XX*** /home/top/ast/minix/1.5/mm/mm.h  crc=42350    635	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/mm.h  crc=51746   1272	Tue Nov  3 21:19:35 1992
XX***************
XX*** 5,16 ****
XX  #define _MINIX             1	/* tell headers to include MINIX stuff */
XX  #define _SYSTEM            1	/* tell headers that this is the kernel */
XX  
XX  /* The following are so basic, all the *.c files get them automatically. */
XX  #include <minix/config.h>	/* MUST be first */
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  
XX! #include <sys/types.h>
XX  #include <limits.h>
XX  #include <errno.h>
XX  
XX--- 5,33 ----
XX  #define _MINIX             1	/* tell headers to include MINIX stuff */
XX  #define _SYSTEM            1	/* tell headers that this is the kernel */
XX  
XX+ /* The ANSI C namespace pollution rules forbid the use of sendrec etc. */
XX+ /* No.  ANSI encourages applications (here the kernel(+mm+fs+init) is the
XX+  * application) not to use names starting with underscores. send and
XX+  * receive are only used by the kernel, so they should be in a kernel
XX+  * library.  sendrec is used to support the standard library, so we might
XX+  * as well use the library version.  But because of ANSI, it is now called
XX+  * _sendrec.
XX+ */
XX+ #define send _send
XX+ #define receive _receive
XX+ #define sendrec _sendrec
XX+ 
XX  /* The following are so basic, all the *.c files get them automatically. */
XX  #include <minix/config.h>	/* MUST be first */
XX+ #include <ansi.h>		/* MUST be second */
XX+ #include <sys/types.h>
XX  #include <minix/const.h>
XX  #include <minix/type.h>
XX  
XX! #include <tiny-fcntl.h>
XX! #include <tiny-unistd.h>
XX! #include <minix/syslib.h>
XX! 
XX  #include <limits.h>
XX  #include <errno.h>
XX  
XX***************
XX*** 18,21 ****
XX  #include "type.h"
XX  #include "proto.h"
XX  #include "glo.h"
XX- 
XX--- 35,37 ----
X/
Xecho x - mproc.h.d
Xsed '/^X/s///' > mproc.h.d << '/'
XX*** /home/top/ast/minix/1.5/mm/mproc.h  crc=51976   1793	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/mproc.h  crc=33112   2387	Sun Feb  7 20:27:03 1993
XX***************
XX*** 6,17 ****
XX   */
XX  
XX  EXTERN struct mproc {
XX!   struct mem_map mp_seg[NR_SEGS];	/* points to text, data, stack */
XX    char mp_exitstatus;		/* storage for status when process exits */
XX!   char mp_sigstatus;		/* storage for signal # for killed processes */
XX    pid_t mp_pid;			/* process id */
XX    int mp_parent;		/* index of parent process */
XX-   int mp_procgrp;		/* process group (used for signals) */
XX  
XX    /* Real and effective uids and gids. */
XX    uid_t mp_realuid;		/* process' real uid */
XX--- 6,18 ----
XX   */
XX  
XX  EXTERN struct mproc {
XX!   struct mem_map mp_seg[NR_SEGS];/* points to text, data, stack */
XX    char mp_exitstatus;		/* storage for status when process exits */
XX!   char mp_sigstatus;		/* storage for signal # for killed procs */
XX    pid_t mp_pid;			/* process id */
XX+   pid_t mp_procgrp;		/* pid of process group (used for signals) */
XX+   pid_t mp_wpid;		/* pid this process is waiting for */
XX    int mp_parent;		/* index of parent process */
XX  
XX    /* Real and effective uids and gids. */
XX    uid_t mp_realuid;		/* process' real uid */
XX***************
XX*** 19,30 ****
XX    gid_t mp_realgid;		/* process' real gid */
XX    gid_t mp_effgid;		/* process' effective gid */
XX  
XX!   /* Bit maps for signals. */
XX!   unshort mp_ignore;		/* 1 means ignore the signal, 0 means don't */
XX!   unshort mp_catch;		/* 1 means catch the signal, 0 means don't */
XX!   void (*mp_func)();		/* all signals vectored to a single user fcn */
XX  
XX    unsigned mp_flags;		/* flag bits */
XX  } mproc[NR_PROCS];
XX  
XX  /* Flag values */
XX--- 20,39 ----
XX    gid_t mp_realgid;		/* process' real gid */
XX    gid_t mp_effgid;		/* process' effective gid */
XX  
XX!   /* Signal handling information. */
XX!   sigset_t mp_ignore;		/* 1 means ignore the signal, 0 means don't */
XX!   sigset_t mp_catch;		/* 1 means catch the signal, 0 means don't */
XX!   sigset_t mp_sigmask;		/* signals to be blocked */
XX!   sigset_t mp_sigmask2;		/* saved copy of mp_sigmask */
XX!   sigset_t mp_sigpending;	/* signals being blocked */
XX!   struct sigaction mp_sigact[_NSIG + 1]; /* as in sigact(2) */
XX!   vir_bytes mp_sigreturn; 	/* address of C library __sigreturn function */
XX  
XX+   /* Backwards compatibility for signals. */
XX+   sighandler_t mp_func;		/* all sigs vectored to a single user fcn */
XX+ 
XX    unsigned mp_flags;		/* flag bits */
XX+   vir_bytes mp_procargs;        /* ptr to proc's initial stack arguments */
XX  } mproc[NR_PROCS];
XX  
XX  /* Flag values */
XX***************
XX*** 36,38 ****
XX--- 45,50 ----
XX  #define SEPARATE	 040	/* set if file is separate I & D space */
XX  #define	TRACED		0100	/* set if process is to be traced */
XX  #define STOPPED		0200	/* set if process stopped for tracing */
XX+ #define SIGSUSPENDED 	0400	/* set by SIGSUSPEND system call */
XX+ 
XX+ #define NIL_MPROC ((struct mproc *) 0)
X/
Xecho x - param.h.d
Xsed '/^X/s///' > param.h.d << '/'
XX*** /home/top/ast/minix/1.5/mm/param.h  crc=22236    763	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/param.h  crc=57418   1057	Tue Nov  3 21:19:36 1992
XX***************
XX*** 4,10 ****
XX  #define exec_len	mm_in.m1_i1
XX  #define func		mm_in.m6_f1
XX  #define grpid		(gid_t) mm_in.m1_i1
XX- #define kill_sig	mm_in.m1_i2
XX  #define namelen		mm_in.m1_i1
XX  #define pid		mm_in.m1_i1
XX  #define seconds		mm_in.m1_i1
XX--- 4,9 ----
XX***************
XX*** 16,23 ****
XX--- 15,35 ----
XX  #define request		mm_in.m2_i2
XX  #define taddr		mm_in.m2_l1
XX  #define data		mm_in.m2_l2
XX+ #define sig_nr		mm_in.m1_i2
XX+ #define sig_nsa		mm_in.m1_p1
XX+ #define sig_osa		mm_in.m1_p2
XX+ #define sig_ret		mm_in.m1_p3
XX+ #define sig_set		mm_in.m2_l1
XX+ #define sig_how		mm_in.m2_i1
XX+ #define sig_flags	mm_in.m2_i2
XX+ #define sig_context	mm_in.m2_p1
XX+ #ifdef _SIGMESSAGE
XX+ #define sig_msg		mm_in.m1_i1
XX+ #endif
XX  
XX  /* The following names are synonyms for the variables in the output message. */
XX  #define reply_type      mm_out.m_type
XX  #define reply_i1        mm_out.m2_i1
XX  #define reply_p1        mm_out.m2_p1
XX+ #define ret_mask	mm_out.m2_l1 	
XX+ 
X/
Xecho x - proto.h.d
Xsed '/^X/s///' > proto.h.d << '/'
XX*** /home/top/ast/minix/1.5/mm/proto.h  crc=62859   1567	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/proto.h  crc=37768   3593	Tue Nov  3 21:19:36 1992
XX***************
XX*** 1,85 ****
XX  /* Function prototypes. */
XX  
XX  /* alloc.c */
XX! extern phys_clicks alloc_mem();
XX! extern void free_mem();
XX! extern phys_clicks max_hole();
XX! extern void mem_init();
XX! extern phys_clicks mem_left();
XX  
XX- /* amoeba.c */
XX- #if AM_KERNEL
XX- extern do_amoeba();
XX- #endif
XX- 
XX  /* break.c */
XX! extern int adjust();
XX! extern int do_brk();
XX! extern int size_ok();
XX! extern void stack_fault();
XX  
XX  /* exec.c */
XX! extern int do_exec();
XX  
XX  /* forkexit.c */
XX! extern int do_fork();
XX! extern int do_mm_exit();
XX! extern int do_wait();
XX! extern void mm_exit();
XX  
XX  /* getset.c */
XX! extern int do_getset();
XX  
XX  /* main.c */
XX! extern int do_brk2();
XX! extern phys_clicks get_mem();
XX  #if (MACHINE == MACINTOSH)
XX! extern phys_clicks start_click();
XX  #endif
XX- extern void main();
XX- extern void reply();
XX  
XX! /* putc.c */
XX! extern void putc();
XX  
XX  /* signal.c */
XX! extern int do_alarm();
XX! extern int do_kill();
XX! extern int do_ksig();
XX! extern int do_pause();
XX! extern int do_signal();
XX! extern int set_alarm();
XX! extern void sig_proc();
XX  
XX  /* trace.c */
XX! extern int do_trace();
XX! extern void stop_proc();
XX  
XX  /* utility.c */
XX! extern int allowed();
XX! extern int mem_copy();
XX! extern int no_sys();
XX! extern void panic();
XX  
XX- /* library */
XX- extern int close();
XX- extern int creat();
XX- extern int fstat();
XX- extern long lseek();
XX- extern int open();
XX- extern void printk();
XX- extern int read();
XX- extern int receive();
XX- extern int send();
XX- extern int sendrec();
XX- extern void sys_abort();
XX- extern void sys_copy();
XX- extern void sys_exec();
XX- extern void sys_fork();
XX- extern void sys_getsp();
XX- extern void sys_newmap();
XX- extern void sys_sig();
XX- extern int sys_trace();
XX- extern void sys_xit();
XX- extern void tell_fs();
XX- extern int write();
XX--- 1,92 ----
XX  /* Function prototypes. */
XX  
XX+ struct mproc;		/* need types outside of parameter list --kub */
XX+ struct stat;
XX+ 
XX  /* alloc.c */
XX! _PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks)			);
XX! _PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks)	);
XX! _PROTOTYPE( phys_clicks max_hole, (void)				);
XX! _PROTOTYPE( void mem_init, (void)					);
XX! _PROTOTYPE( phys_clicks mem_left, (void)				);
XX! _PROTOTYPE( int do_brk3, (void)						);
XX  
XX  /* break.c */
XX! _PROTOTYPE( int adjust, (struct mproc *rmp,
XX! 			vir_clicks data_clicks, vir_bytes sp)		);
XX! _PROTOTYPE( int do_brk, (void)						);
XX! _PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc,
XX! 			vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) );
XX! _PROTOTYPE( void stack_fault, (int proc_nr)				);
XX  
XX  /* exec.c */
XX! _PROTOTYPE( int do_exec, (void)						);
XX  
XX  /* forkexit.c */
XX! _PROTOTYPE( int do_fork, (void)						);
XX! _PROTOTYPE( int do_mm_exit, (void)					);
XX! _PROTOTYPE( int do_waitpid, (void)					);
XX! _PROTOTYPE( void mm_exit, (struct mproc *rmp, int exit_status)		);
XX  
XX  /* getset.c */
XX! _PROTOTYPE( int do_getset, (void)					);
XX  
XX  /* main.c */
XX! _PROTOTYPE( void main, (void)						);
XX! _PROTOTYPE( int do_brk2, (void)						);
XX! _PROTOTYPE( phys_clicks get_mem, (phys_clicks *pbase, int extflag)	);
XX! 
XX  #if (MACHINE == MACINTOSH)
XX! _PROTOTYPE( phys_clicks start_click, (void)				);
XX  #endif
XX  
XX! _PROTOTYPE( void reply, (int proc_nr, int result, int res2, char *respt));
XX  
XX+ /* putk.c */
XX+ _PROTOTYPE( void putk, (int c)						);
XX+ 
XX  /* signal.c */
XX! _PROTOTYPE( int do_alarm, (void)					);
XX! _PROTOTYPE( int do_kill, (void)						);
XX! _PROTOTYPE( int do_ksig, (void)						);
XX! _PROTOTYPE( int do_pause, (void)					);
XX! _PROTOTYPE( int do_signal, (void)					);
XX! _PROTOTYPE( int set_alarm, (int proc_nr, int sec)			);
XX! _PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr)		);
XX! _PROTOTYPE( int do_sigaction, (void)					);
XX! _PROTOTYPE( int do_sigpending, (void)					);
XX! _PROTOTYPE( int do_sigmask, (void)					);
XX! _PROTOTYPE( int do_sigreturn, (void)					);
XX! _PROTOTYPE( int do_sigsuspend, (void)					);
XX  
XX  /* trace.c */
XX! _PROTOTYPE( int do_trace, (void)					);
XX! _PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr)		);
XX  
XX  /* utility.c */
XX! _PROTOTYPE( int allowed, (char *name_buf, struct stat *s_buf, int mask)	);
XX! _PROTOTYPE( struct mproc * find_proc, (int pid)				);
XX! _PROTOTYPE( int mem_copy, (int src_proc, int src_seg, long src_vir, 
XX! 		   int dst_proc, int dst_seg, long dst_vir, long bytes) );
XX! _PROTOTYPE( int no_sys, (void)						);
XX! _PROTOTYPE( void panic, (char *format, int num)				);
XX! _PROTOTYPE( int sys_adjmap, (int proc, struct mem_map *ptr, 
XX! 		vir_clicks data_clicks, vir_clicks sp)			);
XX! _PROTOTYPE( void sys_exec, (int proc, char *ptr, int traced, 
XX! 				char *aout, vir_bytes initpc)		);
XX! _PROTOTYPE( int sys_execmap, (int proc, struct mem_map *ptr)		);
XX! _PROTOTYPE( int sys_fork, (int parent, int child, int pid, 
XX! 					phys_clicks shadow)		);
XX! _PROTOTYPE( void sys_fresh, (int proc, struct mem_map *ptr, 
XX! 		phys_clicks dc, phys_clicks *basep, phys_clicks *sizep)	);
XX! _PROTOTYPE( void sys_getsp, (int proc, vir_bytes *newsp)		);
XX! _PROTOTYPE( void sys_newmap, (int proc, struct mem_map *ptr)		);
XX! _PROTOTYPE( void sys_sendsig, (int proc, struct sigmsg *ptr)		);
XX! _PROTOTYPE( void sys_oldsig, (int proc, int sig, sighandler_t sighandler));
XX! _PROTOTYPE( void sys_endsig, (int proc)					);
XX! _PROTOTYPE( void sys_sigreturn, (int proc, vir_bytes scp, int flags)	);
XX! _PROTOTYPE( int sys_trace,(int req, int procnr, long addr, long *data_p));
XX! _PROTOTYPE( void sys_xit, (int parent, int proc, phys_clicks *basep, 
XX! 						 phys_clicks *sizep));
XX! _PROTOTYPE( void tell_fs, (int what, int p1, int p2, int p3)		);
XX  
X/
Xecho x - signal.c.d
Xsed '/^X/s///' > signal.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/signal.c  crc=13035  14374	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/signal.c  crc=53180  22794	Sat Feb 20 20:47:24 1993
XX***************
XX*** 7,73 ****
XX   * The entry points into this file are:
XX   *   do_signal:	perform the SIGNAL system call
XX   *   do_kill:	perform the KILL system call
XX   *   do_ksig:	accept a signal originating in the kernel (e.g., SIGINT)
XX   *   sig_proc:	interrupt or terminate a signaled process
XX   *   do_alarm:	perform the ALARM system call by calling set_alarm()
XX   *   set_alarm:	tell the clock task to start or stop a timer
XX   *   do_pause:	perform the PAUSE system call
XX-  *   unpause:	check to see if process is suspended on anything
XX   */
XX  
XX- 
XX  #include "mm.h"
XX  #include <sys/stat.h>
XX- #include <signal.h>
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX- #define DUMP_SIZE	 256	/* buffer size for core dumps */
XX  #define CORE_MODE	0777	/* mode to use on core image files */
XX  #define DUMPED          0200	/* bit set in status when core dumped */
XX  
XX! PRIVATE message m_sig;
XX  
XX- #if AM_KERNEL
XX- PRIVATE int Tfs;		/* if true then Tell file server to unpause */
XX- #endif
XX- 
XX- FORWARD int check_sig();
XX- FORWARD void dump_core();
XX- FORWARD void unpause();
XX- 
XX  /*===========================================================================*
XX   *				do_signal				     *
XX   *===========================================================================*/
XX  PUBLIC int do_signal()
XX  {
XX! /* Perform the signal(sig, func) call by setting bits to indicate that a signal
XX!  * is to be caught or ignored.
XX   */
XX  
XX!   int mask;
XX!   int sigign = mp->mp_ignore;
XX  
XX    if (sig < 1 || sig > _NSIG) return(EINVAL);
XX    if (sig == SIGKILL) return(OK);	/* SIGKILL may not ignored/caught */
XX!   mask = 1 << (sig - 1);	/* singleton set with 'sig' bit on */
XX  
XX!   /* All this func does is set the bit maps for subsequent sig processing. */
XX    if (func == SIG_IGN) {
XX! 	mp->mp_ignore |= mask;
XX! 	mp->mp_catch &= ~mask;
XX!   } else if (func == SIG_DFL) {
XX! 	mp->mp_ignore &= ~mask;
XX! 	mp->mp_catch &= ~mask;
XX    } else {
XX! 	mp->mp_ignore &= ~mask;
XX! 	mp->mp_catch |= mask;
XX! 	mp->mp_func = func;
XX    }
XX! 
XX!   if (sigign & mask) return(1);
XX    return(OK);
XX  }
XX  
XX--- 7,88 ----
XX   * The entry points into this file are:
XX   *   do_signal:	perform the SIGNAL system call
XX   *   do_kill:	perform the KILL system call
XX+  *   do_sigaction:   perform the SIGACTION system call
XX+  *   do_sigpending:  perform the SIGPENDING system call
XX+  *   do_sigmask:     perform the SIGMASK system call
XX+  *   do_sigreturn:   perform the SIGRETURN system call
XX+  *   do_sigsuspend:  perform the SIGSUSPEND system call
XX   *   do_ksig:	accept a signal originating in the kernel (e.g., SIGINT)
XX   *   sig_proc:	interrupt or terminate a signaled process
XX   *   do_alarm:	perform the ALARM system call by calling set_alarm()
XX   *   set_alarm:	tell the clock task to start or stop a timer
XX   *   do_pause:	perform the PAUSE system call
XX   */
XX  
XX  #include "mm.h"
XX  #include <sys/stat.h>
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX+ #include <signal.h>
XX+ #include <sys/sigcontext.h>
XX+ #include <unistd.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX  #define CORE_MODE	0777	/* mode to use on core image files */
XX  #define DUMPED          0200	/* bit set in status when core dumped */
XX+ #define DUMP_SIZE	((INT_MAX / BLOCK_SIZE) * BLOCK_SIZE)
XX+ 				/* buffer size for core dumps */
XX  
XX! FORWARD _PROTOTYPE( void check_pending, (void)				);
XX! FORWARD _PROTOTYPE( int check_sig, (pid_t proc_id, int signo)		);
XX! FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp)			);
XX! FORWARD _PROTOTYPE( void unpause, (int pro)				);
XX  
XX  /*===========================================================================*
XX   *				do_signal				     *
XX   *===========================================================================*/
XX  PUBLIC int do_signal()
XX  {
XX! /* Perform the signal(sig, func) call by setting bits to indicate that a 
XX!  * signal is to be caught or ignored.
XX!  *
XX!  * This function exists only for compatibility with old binaries.  In the
XX!  * new implementation, signal(2) is a library function built on top of the
XX!  * POSIX sigaction(2) system call.  The present system level function ties
XX!  * into the mechanism used to implement sigaction().
XX!  *
XX!  * Since the process invoking this system call is oblivious to signal
XX!  * masks, it is assumed that the signal is not in the process signal
XX!  * mask, and is therefore also not pending. 
XX   */
XX  
XX!   sigset_t old_ignore;
XX  
XX    if (sig < 1 || sig > _NSIG) return(EINVAL);
XX    if (sig == SIGKILL) return(OK);	/* SIGKILL may not ignored/caught */
XX!   old_ignore = mp->mp_ignore;
XX  
XX!   sigemptyset(&mp->mp_sigact[sig].sa_mask);
XX!   sigdelset(&mp->mp_sigmask, sig);
XX!   mp->mp_sigact[sig].sa_flags = SA_COMPAT | SA_NODEFER;
XX!   mp->mp_sigact[sig].sa_handler = func;
XX! 
XX    if (func == SIG_IGN) {
XX! 	sigaddset(&mp->mp_ignore, sig);
XX! 	sigdelset(&mp->mp_catch, sig);
XX    } else {
XX! 	sigdelset(&mp->mp_ignore, sig);
XX! 	if (func == SIG_DFL)
XX! 		sigdelset(&mp->mp_catch, sig);
XX!   	else {
XX! 		sigaddset(&mp->mp_catch, sig);
XX! 		if (sig != SIGILL && sig != SIGTRAP)
XX! 			mp->mp_sigact[sig].sa_flags |= SA_RESETHAND;
XX! 		mp->mp_func = func;
XX!   	}
XX    }
XX!   if (sigismember(&old_ignore, sig)) return(1);
XX    return(OK);
XX  }
XX  
XX***************
XX*** 77,89 ****
XX   *===========================================================================*/
XX  PUBLIC int do_kill()
XX  {
XX! /* Perform the kill(pid, kill_sig) system call. */
XX  
XX!   return check_sig(pid, kill_sig, mp->mp_effuid);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX   *				do_ksig					     *
XX   *===========================================================================*/
XX  PUBLIC int do_ksig()
XX--- 92,304 ----
XX   *===========================================================================*/
XX  PUBLIC int do_kill()
XX  {
XX! /* Perform the kill(pid, signo) system call. */
XX  
XX!   return check_sig(pid, sig_nr);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX+  *			       do_sigaction				     *
XX+  *===========================================================================*/
XX+ PUBLIC int do_sigaction()
XX+ {
XX+   int r;
XX+   long svec_size;
XX+   struct sigaction svec;
XX+   struct sigaction *svp;
XX+ 
XX+   if (sig_nr == SIGKILL) return(OK);
XX+   if (sig_nr < 1 || sig_nr > _NSIG) return (EINVAL);
XX+   svp = &mp->mp_sigact[sig_nr];
XX+   svec_size = (long) sizeof(svec);
XX+   if ((struct sigaction *) sig_osa != (struct sigaction *) NULL) {
XX+ 	r = mem_copy(MM_PROC_NR,D, (long)svp, who,D, (long)sig_osa, svec_size);
XX+ 	if (r != OK) return(r);
XX+   }
XX+ 
XX+   if ((struct sigaction *) sig_nsa == (struct sigaction *) NULL) return(OK);
XX+ 
XX+   /* Read in the sigaction structure. */
XX+   r = mem_copy(who, D, (long) sig_nsa, MM_PROC_NR, D, (long) &svec, svec_size);
XX+   if (r != OK) return(r);
XX+ 
XX+   if (svec.sa_handler == SIG_IGN) {
XX+ 	sigaddset(&mp->mp_ignore, sig_nr);
XX+ 	sigdelset(&mp->mp_sigpending, sig_nr);
XX+ 	sigdelset(&mp->mp_catch, sig_nr);
XX+   } else {
XX+ 	sigdelset(&mp->mp_ignore, sig_nr);
XX+ 	if (svec.sa_handler == SIG_DFL)
XX+ 		sigdelset(&mp->mp_catch, sig_nr);
XX+ 	else
XX+ 		sigaddset(&mp->mp_catch, sig_nr);
XX+   }
XX+   mp->mp_sigact[sig_nr].sa_handler = svec.sa_handler;
XX+   sigdelset(&svec.sa_mask, SIGKILL);
XX+   mp->mp_sigact[sig_nr].sa_mask = svec.sa_mask;
XX+   mp->mp_sigact[sig_nr].sa_flags = svec.sa_flags & ~SA_COMPAT;
XX+   mp->mp_sigreturn = (vir_bytes) sig_ret;
XX+   return(OK);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *                            do_sigpending                                  *
XX+  *===========================================================================*/
XX+ PUBLIC int do_sigpending()
XX+ {
XX+   ret_mask = (long) mp->mp_sigpending;
XX+   return OK;
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *                            do_sigmask                                     *
XX+  *===========================================================================*/
XX+ PUBLIC int do_sigmask()
XX+ {
XX+ /* Note that the library interface passes the actual mask in sigmask_set,
XX+  * not a pointer to the mask, in order to save a mem_copy.  Similarly,
XX+  * the old mask is placed in the return message which the library
XX+  * interface copies (if requested) to the user specified address.
XX+  *
XX+  * The library interface must set SIG_INQUIRE if the 'act' argument
XX+  * is NULL.
XX+  */
XX+ 
XX+   int i;
XX+ 
XX+   ret_mask = (long) mp->mp_sigmask;
XX+ 
XX+   switch (sig_how) {
XX+       case SIG_BLOCK:
XX+ 	sigdelset((sigset_t *)&sig_set, SIGKILL);
XX+ 	for (i = 1; i < _NSIG; i++) {
XX+ 		if (sigismember((sigset_t *)&sig_set, i))
XX+ 			sigaddset(&mp->mp_sigmask, i);
XX+ 	}
XX+ 	break;
XX+ 
XX+       case SIG_UNBLOCK:
XX+ 	for (i = 1; i < _NSIG; i++) {
XX+ 		if (sigismember((sigset_t *)&sig_set, i))
XX+ 			sigdelset(&mp->mp_sigmask, i);
XX+ 	}
XX+ 	check_pending();
XX+ 	break;
XX+ 
XX+       case SIG_SETMASK:
XX+ 	sigdelset((sigset_t *)&sig_set, SIGKILL);
XX+ 	mp->mp_sigmask = (sigset_t)sig_set;
XX+ 	check_pending();
XX+ 	break;
XX+ 
XX+       case SIG_INQUIRE:
XX+ 	break;
XX+ 
XX+       default:
XX+ 	return(EINVAL);
XX+ 	break;
XX+   }
XX+   return OK;
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *                               do_sigreturn				     *
XX+  *===========================================================================*/
XX+ PUBLIC int do_sigreturn()
XX+ {
XX+ /* A user signal handler is done.  Restore context and check for
XX+  * pending unblocked signals.
XX+  */
XX+ 
XX+   mp->mp_sigmask = (sigset_t) sig_set;
XX+   sigdelset(&mp->mp_sigmask, SIGKILL);
XX+ 
XX+   sys_sigreturn(who, (vir_bytes)sig_context, sig_flags);
XX+   check_pending();
XX+   return OK;
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *                            do_sigsuspend                                  *
XX+  *===========================================================================*/
XX+ PUBLIC int do_sigsuspend()
XX+ {
XX+   mp->mp_sigmask2 = mp->mp_sigmask;	/* save the old mask */
XX+   mp->mp_sigmask = (sigset_t) sig_set;
XX+   sigdelset(&mp->mp_sigmask, SIGKILL);
XX+   mp->mp_flags |= SIGSUSPENDED;
XX+   dont_reply = TRUE;
XX+   check_pending();
XX+   return OK;
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				check_sig				     *
XX+  *===========================================================================*/
XX+ PRIVATE int check_sig(proc_id, signo)
XX+ pid_t proc_id;			/* pid of proc to sig, or 0 or -1, or -pgrp */
XX+ int signo;			/* signal to send to process (0 to _NSIG) */
XX+ {
XX+ /* Check to see if it is possible to send a signal.  The signal may have to be
XX+  * sent to a group of processes.  This routine is invoked by the KILL system
XX+  * call, and also when the kernel catches a DEL or other signal.
XX+  */
XX+ 
XX+   register struct mproc *rmp;
XX+   int count;			/* count # of signals sent */
XX+   int error_code;
XX+ 
XX+   if (signo < 0 || signo > _NSIG) return(EINVAL);
XX+ 
XX+   /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
XX+   if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
XX+ 
XX+   /* Search the proc table for processes to signal. */
XX+   /* XXX - see forkexit.c about pid magic. */
XX+   count = 0;
XX+   error_code = ESRCH;
XX+   for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) {
XX+ 	if ( (rmp->mp_flags & IN_USE) == 0) continue;
XX+ 	if (rmp->mp_flags & HANGING && signo != 0) continue;
XX+ 
XX+ 	/* Check for selection. */
XX+ 	if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
XX+ 	if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
XX+ 	if (proc_id == -1 && rmp->mp_pid == INIT_PID) continue;
XX+ 	if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
XX+ 
XX+ 	/* Check for permission. */
XX+ 	if (mp->mp_effuid != SUPER_USER
XX+ 	    && mp->mp_realuid != rmp->mp_realuid
XX+ 	    && mp->mp_effuid != rmp->mp_realuid
XX+ 	    && mp->mp_realuid != rmp->mp_effuid
XX+ 	    && mp->mp_effuid != rmp->mp_effuid) {
XX+ 		error_code = EPERM;
XX+ 		continue;
XX+ 	}
XX+ 
XX+ 	count++;
XX+ 	if (signo == 0) continue;
XX+ 
XX+ 	/* 'sig_proc' will handle the disposition of the signal.  The
XX+ 	 * signal may be caught, blocked, ignored, or cause process
XX+ 	 * termination, possibly with core dump.
XX+ 	 */
XX+ 	sig_proc(rmp, signo);
XX+ 
XX+ 	if (proc_id > 0) break;	/* only one process being signaled */
XX+   }
XX+ 
XX+   /* If the calling process has killed itself, don't reply. */
XX+   if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))
XX+ 	dont_reply = TRUE;
XX+   return(count > 0 ? OK : error_code);
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX   *				do_ksig					     *
XX   *===========================================================================*/
XX  PUBLIC int do_ksig()
XX***************
XX*** 96,264 ****
XX   */
XX  
XX    register struct mproc *rmp;
XX!   int i, j, proc_id, proc_nr, id;
XX!   unshort sig_map;		/* bits 0 - 15 for sigs 1 - 16 */
XX  
XX    /* Only kernel may make this call. */
XX    if (who != HARDWARE) return(EPERM);
XX    dont_reply = TRUE;		/* don't reply to the kernel */
XX! 
XX!   proc_nr = mm_in.PROC1;
XX    rmp = &mproc[proc_nr];
XX    if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
XX    proc_id = rmp->mp_pid;
XX!   sig_map = (unshort) mm_in.SIG_MAP;
XX    mp = &mproc[0];		/* pretend kernel signals are from MM */
XX    mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */
XX  
XX!   /* Stack faults are passed from kernel to MM as pseudo-signal 16. */
XX!   if (sig_map == 1 << (SIGSTKFLT - 1))
XX! 	stack_fault(proc_nr);
XX  
XX    /* Check each bit in turn to see if a signal is to be sent.  Unlike
XX!    * kill(), the kernel may collect several unrelated signals for a process
XX!    * and pass them to MM in one blow.  Thus loop on the bit map. For SIGINT
XX!    * and SIGQUIT, use proc_id 0, since multiple processes may have to signaled.
XX     */
XX!   for (i = 0, j = 1; i < _NSIG - 1; i++, j++) {
XX! 	id = (j == SIGINT || j == SIGQUIT) ? 0 : proc_id;
XX! 	if (j == SIGKILL) id = -1;	/* simulate kill -1 9 */
XX! 	if ( (sig_map >> i) & 1) {
XX! 		check_sig(id, j, SUPER_USER);
XX! 		sys_sig(proc_nr, -1, SIG_DFL);	/* tell kernel it's done */
XX  	}
XX    }
XX- 
XX    return(OK);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				check_sig				     *
XX   *===========================================================================*/
XX! PRIVATE int check_sig(proc_id, sig_nr, send_uid)
XX! int proc_id;			/* pid of process to signal, or 0 or -1 */
XX! int sig_nr;			/* which signal to send (1-16) */
XX! uid_t send_uid;			/* identity of process sending the signal */
XX  {
XX! /* Check to see if it is possible to send a signal.  The signal may have to be
XX!  * sent to a group of processes.  This routine is invoked by the KILL system
XX!  * call, and also when the kernel catches a DEL or other signal. SIGALRM too.
XX   */
XX  
XX!   register struct mproc *rmp;
XX!   int count, send_sig;
XX!   unshort mask;
XX  
XX!   if (sig_nr < 1 || sig_nr > _NSIG) return(EINVAL);
XX!   count = 0;			/* count # of signals sent */
XX!   mask = 1 << (sig_nr - 1);
XX! 
XX!   /* Search the proc table for processes to signal.  Several tests are made:
XX!    * 	- if proc's uid != sender's, and sender is not superuser, don't signal
XX!    *	- if specific process requested (i.e., 'procpid' > 0), check for match
XX!    *	- if a process has already exited, it can't receive signals
XX!    *	- if 'proc_id' is 0 signal everyone in same process group except caller
XX!    */
XX!   for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++ ) {
XX! 	if ( (rmp->mp_flags & IN_USE) == 0) continue;
XX! 	send_sig = TRUE;	/* if it's FALSE at end of loop, don't signal*/
XX! 	if (send_uid != rmp->mp_effuid && send_uid != SUPER_USER)send_sig=FALSE;
XX! 	if (proc_id > 0 && proc_id != rmp->mp_pid) send_sig = FALSE;
XX! 	if (rmp->mp_flags & HANGING) send_sig = FALSE;   /*don't wake the dead*/
XX! 	if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp)send_sig = FALSE;
XX! 	if (send_uid == SUPER_USER && proc_id == -1) send_sig = TRUE;
XX! 	if (rmp->mp_pid == INIT_PID && proc_id == -1) send_sig = FALSE;
XX! 	if (rmp->mp_pid == INIT_PID && sig_nr == SIGKILL) send_sig = FALSE;
XX! 
XX! 	/* SIGALARM is a little special.  When a process exits, a clock signal
XX! 	 * can arrive just as the timer is being turned off.  Also, turn off
XX! 	 * ALARM_ON bit when timer goes off to keep it accurate.
XX! 	 */
XX! 	if (sig_nr == SIGALRM) {
XX! 		if ( (rmp->mp_flags & ALARM_ON) == 0) continue;
XX! 		if (send_sig) rmp->mp_flags &= ~ALARM_ON;
XX  	}
XX  
XX! 	if (send_sig == FALSE) continue;
XX! 	count++;
XX! 	if (rmp->mp_ignore & mask) continue;
XX  
XX! #if AM_KERNEL
XX! 	/* see if an amoeba transaction should be signalled */
XX! 	Tfs = am_check_sig((int)(rmp - mproc), 0);
XX! #endif
XX  
XX! 	/* Send the signal or kill the process, possibly with core dump. */
XX! 	sig_proc(rmp, sig_nr);
XX  
XX! 	/* If process is hanging on PAUSE, WAIT, tty, pipe, etc. release it. */
XX! 	unpause((int)(rmp - mproc));	/* check to see if process is paused */
XX! 	if (proc_id > 0) break;	/* only one process being signaled */
XX    }
XX! 
XX!   /* If the calling process has killed itself, don't reply. */
XX!   if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))dont_reply=TRUE;
XX!   return(count > 0 ? OK : ESRCH);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				sig_proc				     *
XX   *===========================================================================*/
XX! PUBLIC void sig_proc(rmp, sig_nr)
XX! register struct mproc *rmp;	/* pointer to the process to be signaled */
XX! int sig_nr;			/* signal to send to process (1-16) */
XX  {
XX! /* Send a signal to a process.  Check to see if the signal is to be caught.
XX!  * If so, the pc, psw, and signal number are to be pushed onto the process'
XX!  * stack.  If the stack cannot grow or the signal is not to be caught, kill
XX!  * the process.
XX   */
XX  
XX!   unshort mask;
XX!   int core_file;
XX!   vir_bytes new_sp;
XX  
XX!   if ( (rmp->mp_flags & IN_USE) == 0) return;	/* if already dead forget it */
XX!   if (rmp->mp_flags & TRACED && sig_nr != SIGKILL) {
XX! 	/* A traced process has special handling. */
XX! 	stop_proc(rmp, sig_nr); /* a signal causes it to stop */
XX  	return;
XX    }
XX!   mask = 1 << (sig_nr - 1);
XX!   if (rmp->mp_catch & mask) {
XX! 	/* Signal should be caught. */
XX! 	rmp->mp_catch &= ~mask;		/* disable further signals */
XX! 	sys_getsp((int)(rmp - mproc), &new_sp);
XX! 	new_sp -= SIG_PUSH_BYTES;
XX! 	if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) == OK) {
XX! 		sys_sig((int)(rmp - mproc), sig_nr, rmp->mp_func);
XX! 		return;		/* successful signal */
XX! 	}
XX    }
XX  
XX!   /* Signal should not or cannot be caught.  Take default action. */
XX!   core_file = ( core_bits >> (sig_nr - 1 )) & 1;
XX!   rmp->mp_sigstatus = (char) sig_nr;
XX!   if (core_file) dump_core(rmp); /* dump core */
XX!   mm_exit(rmp, 0);		/* terminate process */
XX  }
XX  
XX  
XX  /*===========================================================================*
XX   *				do_alarm				     *
XX   *===========================================================================*/
XX  PUBLIC int do_alarm()
XX  {
XX  /* Perform the alarm(seconds) system call. */
XX  
XX!   register int r;
XX!   unsigned sec;
XX! 
XX!   sec = (unsigned) seconds;
XX!   r = set_alarm(who, sec);
XX!   return(r);
XX  }
XX  
XX  
XX--- 311,555 ----
XX   */
XX  
XX    register struct mproc *rmp;
XX!   int i, proc_nr;
XX!   pid_t proc_id, id;
XX!   sigset_t sig_map;
XX  
XX    /* Only kernel may make this call. */
XX    if (who != HARDWARE) return(EPERM);
XX    dont_reply = TRUE;		/* don't reply to the kernel */
XX!   proc_nr = mm_in.SIG_PROC;
XX    rmp = &mproc[proc_nr];
XX    if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
XX    proc_id = rmp->mp_pid;
XX!   sig_map = (sigset_t) mm_in.SIG_MAP;
XX    mp = &mproc[0];		/* pretend kernel signals are from MM */
XX    mp->mp_procgrp = rmp->mp_procgrp;	/* get process group right */
XX  
XX!   /* Stack faults are passed from kernel to MM as pseudo-signal SIGSTKFLT. */
XX!   if (sigismember(&sig_map, SIGSTKFLT)) stack_fault(proc_nr);
XX  
XX    /* Check each bit in turn to see if a signal is to be sent.  Unlike
XX!    * kill(), the kernel may collect several unrelated signals for a
XX!    * process and pass them to MM in one blow.  Thus loop on the bit
XX!    * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast
XX!    * to the recipient's process group.  For SIGKILL, use proc_id -1 to
XX!    * indicate a systemwide broadcast.
XX     */
XX!   for (i = 1; i <= _NSIG; i++) {
XX! 	if (!sigismember(&sig_map, i)) continue;
XX! 	switch (i) {
XX! 	    case SIGSTKFLT:
XX! 		continue;	/* XXX - not sure if this special case
XX! 	    			 * is still necessary; however it would be
XX! 	    			 * nice to eliminate the special test for
XX! 	    			 * SIGSTKFLT above */
XX! 	    case SIGINT: 
XX! 	    case SIGQUIT: 
XX! 		id = 0; break;	/* broadcast to process group */
XX! 	    case SIGKILL: 
XX! 		id = -1; break;	/* broadcast to all except INIT */
XX! 	    case SIGALRM:
XX!    		/* Disregard SIGALRM when the target process has not
XX! 		 * requested an alarm.  This only applies for a KERNEL
XX! 		 * generated signal.
XX! 		 */
XX! 		if ((rmp->mp_flags & ALARM_ON) == 0) continue;
XX! 		rmp->mp_flags &= ~ALARM_ON;
XX! 		/* fall through */
XX! 	    default:
XX! 		id = proc_id; 
XX! 		break;	
XX  	}
XX+ 	check_sig(id, i);
XX+ 	sys_endsig(proc_nr);	/* tell kernel it's done */
XX    }
XX    return(OK);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				sig_proc				     *
XX   *===========================================================================*/
XX! PUBLIC void sig_proc(rmp, signo)
XX! register struct mproc *rmp;	/* pointer to the process to be signaled */
XX! int signo;			/* signal to send to process (1 to _NSIG) */
XX  {
XX! /* Send a signal to a process.  Check to see if the signal is to be caught,
XX!  * ignored, or blocked.  If the signal is to be caught, coordinate with
XX!  * KERNEL to push a sigcontext structure and a sigframe structure onto
XX!  * the catcher's stack.  Also, KERNEL will reset the program counter and
XX!  * stack pointer, so that when the process next runs, it will be executing
XX!  * the signal handler.  When the signal handler returns,  sigreturn(2)
XX!  * will be called.  Then KERNEL will restore the signal context from the
XX!  * sigcontext structure.
XX!  *
XX!  * If there is insufficient stack space, kill the process.
XX   */
XX  
XX!   vir_bytes new_sp;
XX!   int slot;
XX!   int sigflags;
XX!   struct sigmsg sm;
XX  
XX!   slot = (int) (rmp - mproc);
XX!   if (!(rmp->mp_flags & IN_USE)) {
XX! 	printf("MM: signal %d sent to dead process %d\n", signo, slot);
XX! 	panic("", NO_NUM);
XX!   }
XX!   if (rmp->mp_flags & HANGING) {
XX! 	printf("MM: signal %d sent to HANGING process %d\n", signo, slot);
XX! 	panic("", NO_NUM);
XX!   }
XX!   if (rmp->mp_flags & TRACED && signo != SIGKILL) {
XX! 	/* A traced process has special handling. */
XX! 	unpause(slot);
XX! 	stop_proc(rmp, signo);	/* a signal causes it to stop */
XX! 	return;
XX!   }
XX!   if (sigismember(&rmp->mp_ignore, signo)) return;
XX!   if (sigismember(&rmp->mp_sigmask, signo)) {
XX! 	/* Signal should be blocked. */
XX! 	sigaddset(&rmp->mp_sigpending, signo);
XX! 	return;
XX!   }
XX!   sigflags = rmp->mp_sigact[signo].sa_flags;
XX!   if (sigismember(&rmp->mp_catch, signo)) {
XX! 	if (rmp->mp_flags & SIGSUSPENDED)
XX! 		sm.sm_mask = rmp->mp_sigmask2;
XX! 	else
XX! 		sm.sm_mask = rmp->mp_sigmask;
XX! 	sm.sm_signo = signo;
XX! 	sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
XX! 	sm.sm_sigreturn = rmp->mp_sigreturn;
XX! 	sys_getsp(slot, &new_sp);
XX! 	sm.sm_stkptr = new_sp;
XX! 	if (sigflags & SA_COMPAT) {
XX! 		/* Make room for an old style stack frame. */
XX! 		new_sp -= SIG_PUSH_BYTES;
XX! 	} else {
XX! 		/* Make room for the sigcontext and sigframe struct. */
XX! 		new_sp = new_sp - sizeof(struct sigcontext) 
XX! 			 - 3 * sizeof(char *) - 2 * sizeof(int);
XX  	}
XX  
XX! 	if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
XX! 		goto dodefault;
XX  
XX! 	rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
XX! 	if (sigflags & SA_NODEFER)
XX! 		sigdelset(&rmp->mp_sigmask, signo);
XX! 	else
XX! 		sigaddset(&rmp->mp_sigmask, signo);
XX  
XX! 	if (sigflags & SA_RESETHAND) {
XX! 		sigdelset(&rmp->mp_catch, signo);
XX! 		rmp->mp_sigact[signo].sa_handler = SIG_DFL;
XX! 	}
XX  
XX!   	if (sigflags & SA_COMPAT)
XX! 		sys_oldsig(slot, signo, rmp->mp_func);
XX! 	else
XX! 		sys_sendsig(slot, &sm);
XX! 	sigdelset(&rmp->mp_sigpending, signo);
XX! 	/* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
XX! 	 * release it.
XX!  	 */
XX! 	unpause(slot);
XX! 	return;
XX    }
XX! dodefault:
XX!   /* Signal should not or cannot be caught.  Take default action. */
XX!   rmp->mp_sigstatus = (char) signo;
XX!   if (sigismember(&core_bits, signo)) {
XX! 	/* Switch to the user's FS environment and dump core. */
XX! 	tell_fs(CHDIR, slot, FALSE, 0);
XX! 	dump_core(rmp);
XX!   }
XX!   mm_exit(rmp, 0);		/* terminate process */
XX  }
XX  
XX  
XX  /*===========================================================================*
XX!  *				unpause					     *
XX   *===========================================================================*/
XX! PRIVATE void unpause(pro)
XX! int pro;			/* which process number */
XX  {
XX! /* A signal is to be sent to a process.  If that process is hanging on a
XX!  * system call, the system call must be terminated with EINTR.  Possible
XX!  * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
XX!  * First check if the process is hanging on an MM call.  If not, tell FS,
XX!  * so it can check for READs and WRITEs from pipes, ttys and the like.
XX   */
XX  
XX!   register struct mproc *rmp;
XX  
XX!   rmp = &mproc[pro];
XX! 
XX!   /* Check to see if process is hanging on a PAUSE call. */
XX!   if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
XX! 	rmp->mp_flags &= ~PAUSED;
XX! 	reply(pro, EINTR, 0, NIL_PTR);
XX  	return;
XX    }
XX! 
XX!   /* Check to see if process is hanging on a WAIT call. */
XX!   if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
XX! 	rmp->mp_flags &= ~WAITING;
XX! 	reply(pro, EINTR, 0, NIL_PTR);
XX! 	return;
XX    }
XX  
XX!   /* Check to see if process is hanging on a SIGSUSPEND call. */
XX!   if ((rmp->mp_flags & SIGSUSPENDED) && (rmp->mp_flags & HANGING) == 0) {
XX! 	rmp->mp_flags &= ~SIGSUSPENDED;
XX! 	reply(pro, EINTR, 0, NIL_PTR);
XX! 	return;
XX!   }
XX! 
XX!   /* Process is not hanging on an MM call.  Ask FS to take a look. */
XX! 	tell_fs(UNPAUSE, pro, 0, 0);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX+  *                               check_pending				     *
XX+  *===========================================================================*/
XX+ PRIVATE void check_pending()
XX+ {
XX+   /* Check to see if any pending signals have been unblocked.  The
XX+    * first such signal found is delivered.
XX+    *
XX+    * If multiple pending unmasked signals are found, they will be
XX+    * delivered sequentially.
XX+    *
XX+    * There are several places in this file where the signal mask is
XX+    * changed.  At each such place, check_pending() should be called to
XX+    * check for newly unblocked signals.
XX+    */
XX+ 
XX+   int i;
XX+ 
XX+   for (i = 1; i < _NSIG; i++) {
XX+ 	if (sigismember(&mp->mp_sigpending, i) &&
XX+ 		!sigismember(&mp->mp_sigmask, i)) {
XX+ 		sigdelset(&mp->mp_sigpending, i);
XX+ 		sig_proc(mp, i);
XX+ 		break;
XX+ 	}
XX+   }
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX   *				do_alarm				     *
XX   *===========================================================================*/
XX  PUBLIC int do_alarm()
XX  {
XX  /* Perform the alarm(seconds) system call. */
XX  
XX!   return(set_alarm(who, seconds));
XX  }
XX  
XX  
XX***************
XX*** 267,291 ****
XX   *===========================================================================*/
XX  PUBLIC int set_alarm(proc_nr, sec)
XX  int proc_nr;			/* process that wants the alarm */
XX! unsigned sec;			/* how many seconds delay before the signal */
XX  {
XX  /* This routine is used by do_alarm() to set the alarm timer.  It is also used
XX   * to turn the timer off when a process exits with the timer still on.
XX   */
XX  
XX    int remaining;
XX  
XX-   m_sig.m_type = SET_ALARM;
XX-   m_sig.CLOCK_PROC_NR = proc_nr;
XX-   m_sig.DELTA_TICKS = HZ * sec;
XX    if (sec != 0)
XX! 	mproc[proc_nr].mp_flags |= ALARM_ON;	/* turn ALARM_ON bit on */
XX    else
XX! 	mproc[proc_nr].mp_flags &= ~ALARM_ON;	/* turn ALARM_ON bit off */
XX  
XX!   /* Tell the clock task to provide a signal message when the time comes. */
XX    if (sendrec(CLOCK, &m_sig) != OK) panic("alarm er", NO_NUM);
XX    remaining = (int) m_sig.SECONDS_LEFT;
XX    return(remaining);
XX  }
XX  
XX--- 558,602 ----
XX   *===========================================================================*/
XX  PUBLIC int set_alarm(proc_nr, sec)
XX  int proc_nr;			/* process that wants the alarm */
XX! int sec;			/* how many seconds delay before the signal */
XX  {
XX  /* This routine is used by do_alarm() to set the alarm timer.  It is also used
XX   * to turn the timer off when a process exits with the timer still on.
XX   */
XX  
XX+   message m_sig;
XX    int remaining;
XX  
XX    if (sec != 0)
XX! 	mproc[proc_nr].mp_flags |= ALARM_ON;
XX    else
XX! 	mproc[proc_nr].mp_flags &= ~ALARM_ON;
XX  
XX!   /* Tell the clock task to provide a signal message when the time comes.
XX!    *
XX!    * Large delays cause a lot of problems.  First, the alarm system call
XX!    * takes an unsigned seconds count and the library has cast it to an int.
XX!    * That probably works, but on return the library will convert "negative"
XX!    * unsigneds to errors.  Presumably no one checks for these errors, so
XX!    * force this call through.  Second, If unsigned and long have the same
XX!    * size, converting from seconds to ticks can easily overflow.  Finally,
XX!    * the kernel has similar overflow bugs adding ticks.
XX!    *
XX!    * Fixing this requires a lot of ugly casts to fit the wrong interface
XX!    * types and to avoid overflow traps.  DELTA_TICKS has the right type
XX!    * (clock_t) although it is declared as long.  How can variables like
XX!    * this be declared properly without combinatorial explosion of message
XX!    * types?
XX!    */
XX!   m_sig.m_type = SET_ALARM;
XX!   m_sig.CLOCK_PROC_NR = proc_nr;
XX!   m_sig.DELTA_TICKS = (clock_t) (HZ * (unsigned long) (unsigned) sec);
XX!   if ( (unsigned long) m_sig.DELTA_TICKS / HZ != (unsigned) sec)
XX! 	m_sig.DELTA_TICKS = LONG_MAX;	/* eternity (really CLOCK_T_MAX) */
XX    if (sendrec(CLOCK, &m_sig) != OK) panic("alarm er", NO_NUM);
XX    remaining = (int) m_sig.SECONDS_LEFT;
XX+   if (remaining != m_sig.SECONDS_LEFT || remaining < 0)
XX+ 	remaining = INT_MAX;	/* true value is not representable */
XX    return(remaining);
XX  }
XX  
XX***************
XX*** 297,351 ****
XX  {
XX  /* Perform the pause() system call. */
XX  
XX!   mp->mp_flags |= PAUSED;	/* turn on PAUSE bit */
XX    dont_reply = TRUE;
XX    return(OK);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX-  *				unpause					     *
XX-  *===========================================================================*/
XX- PRIVATE void unpause(pro)
XX- int pro;			/* which process number */
XX- {
XX- /* A signal is to be sent to a process.  If that process is hanging on a
XX-  * system call, the system call must be terminated with EINTR.  Possible
XX-  * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
XX-  * First check if the process is hanging on PAUSE or WAIT.  If not, tell FS,
XX-  * so it can check for READs and WRITEs from pipes, ttys and the like.
XX-  */
XX- 
XX-   register struct mproc *rmp;
XX- 
XX-   rmp = &mproc[pro];
XX- 
XX-   /* Check to see if process is hanging on a PAUSE call. */
XX-   if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
XX- 	rmp->mp_flags &= ~PAUSED;	/* turn off PAUSED bit */
XX- 	reply(pro, EINTR, 0, NIL_PTR);
XX- 	return;
XX-   }
XX- 
XX-   /* Check to see if process is hanging on a WAIT call. */
XX-   if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
XX- 	rmp->mp_flags &= ~WAITING;	/* turn off WAITING bit */
XX- 	reply(pro, EINTR, 0, NIL_PTR);
XX- 	return;
XX-   }
XX- 
XX- #if AM_KERNEL
XX-   /* if it was an amoeba transaction, it is already tidied up by now. */
XX-   if (Tfs)
XX- #endif
XX-   /* Process is not hanging on an MM call.  Ask FS to take a look. */
XX- 	tell_fs(UNPAUSE, pro, 0, 0);
XX- 
XX-   return;
XX- }
XX- 
XX- 
XX- /*===========================================================================*
XX   *				dump_core				     *
XX   *===========================================================================*/
XX  PRIVATE void dump_core(rmp)
XX--- 608,620 ----
XX  {
XX  /* Perform the pause() system call. */
XX  
XX!   mp->mp_flags |= PAUSED;
XX    dont_reply = TRUE;
XX    return(OK);
XX  }
XX  
XX  
XX  /*===========================================================================*
XX   *				dump_core				     *
XX   *===========================================================================*/
XX  PRIVATE void dump_core(rmp)
XX***************
XX*** 353,430 ****
XX  {
XX  /* Make a core dump on the file "core", if possible. */
XX  
XX!   struct stat s_buf, d_buf;
XX!   char buf[DUMP_SIZE];
XX!   int i, r, s, er1, er2, slot;
XX!   vir_bytes v_buf;
XX!   long a, c, ct, dest;
XX!   struct mproc *xmp;
XX!   long trace_data;
XX!   int trace_off;
XX  
XX!   /* Change to working directory of dumpee. */
XX!   slot = (int)(rmp - mproc);
XX!   tell_fs(CHDIR, slot, 0, 0);
XX  
XX!   /* Can core file be written? */
XX!   if (rmp->mp_realuid != rmp->mp_effuid) {
XX! 	tell_fs(CHDIR, 0, 1, 0);	/* go back to MM's directory */
XX  	return;
XX    }
XX-   xmp = mp;			/* allowed() looks at 'mp' */
XX-   mp = rmp;
XX-   r = allowed(core_name, &s_buf, W_BIT);	/* is core_file writable */
XX-   s = allowed(".", &d_buf, W_BIT);	/* is directory writable? */
XX-   mp = xmp;
XX-   if (r >= 0) close(r);
XX-   if (s >= 0) close(s);
XX-   if (rmp->mp_effuid == SUPER_USER) r = 0;	/* su can always dump core */
XX  
XX!   if (s >= 0 && (r >= 0 || r == ENOENT)) {
XX! 	/* Either file is writable or it doesn't exist & dir is writable */
XX! 	r = creat(core_name, CORE_MODE);
XX! 	tell_fs(CHDIR, 0, 1, 0);	/* go back to MM's own dir */
XX! 	if (r < 0) return;
XX! 	rmp->mp_sigstatus |= DUMPED;
XX! 
XX! 	/* First write the memory map of all segments on core file. */
XX! 	if (write(r, (char *) rmp->mp_seg, (int)sizeof(rmp->mp_seg)) < 0) {
XX! 		close(r);
XX  		return;
XX  	}
XX  
XX! 	/* Write out the whole kernel process table entry to get the regs. */
XX! 	trace_off = 0;
XX! 	while (sys_trace(3, slot, (long)trace_off, (long)&trace_data) == OK) { 
XX! 		write(r, (char *) &trace_data, (unsigned) sizeof(long));
XX!  		trace_off += sizeof(long);
XX! 	}
XX  
XX! 	/* Now loop through segments and write the segments themselves out. */
XX! 	v_buf = (vir_bytes) buf;
XX! 	dest = (long) v_buf;
XX! 	for (i = 0; i < NR_SEGS; i++) {
XX! 		a = (phys_bytes) rmp->mp_seg[i].mem_vir << CLICK_SHIFT;
XX! 		c = (phys_bytes) rmp->mp_seg[i].mem_len << CLICK_SHIFT;
XX! 
XX! 		/* Loop through a segment, dumping it. */
XX! 		while (c > 0) {
XX! 			ct = MIN(c, DUMP_SIZE);
XX! 			er1 = mem_copy(slot, i, a, MM_PROC_NR, D, dest, ct);
XX! 			er2 = write(r, buf, (int) ct);
XX! 			if (er1 < 0 || er2 < 0) {
XX! 				close(r);
XX! 				return;
XX! 			}
XX! 			a += ct;
XX! 			c -= ct;
XX  		}
XX  	}
XX-   } else {
XX- 	tell_fs(CHDIR, 0, 1, 0);	/* go back to MM's own dir */
XX- 	close(r);
XX- 	return;
XX    }
XX! 
XX!   close(r);
XX  }
XX--- 622,686 ----
XX  {
XX  /* Make a core dump on the file "core", if possible. */
XX  
XX!   int fd, fake_fd, nr_written, seg, slot;
XX!   char *buf;
XX!   vir_bytes current_sp;
XX!   phys_bytes left;		/* careful; 64K might overflow vir_bytes */
XX!   unsigned nr_to_write;		/* unsigned for arg to write() but < INT_MAX */
XX!   long trace_data, trace_off;
XX  
XX!   slot = (int) (rmp - mproc);
XX  
XX!   /* Can core file be written?  We are operating in the user's FS environment,
XX!    * so no special permission checks are needed.
XX!    */
XX!   if (rmp->mp_realuid != rmp->mp_effuid) return;
XX!   if ( (fd = creat(core_name, CORE_MODE)) < 0) return;
XX!   rmp->mp_sigstatus |= DUMPED;
XX! 
XX!   /* Make sure the stack segment is up to date.
XX!    * DEBUG.  We don't want adjust() to fail unless current_sp is preposteous,
XX!    * but it might fail due to safety checking.  Also, we don't really want the
XX!    * adjust() for sending a signal to fail due to safety checking.  Maybe make
XX!    * SAFETY_BYTES a parameter.
XX!    */
XX!   sys_getsp(slot, &current_sp);
XX!   adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
XX! 
XX!   /* Write the memory map of all segments to begin the core file. */
XX!   if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
XX!       != (unsigned) sizeof rmp->mp_seg) {
XX! 	close(fd);
XX  	return;
XX    }
XX  
XX!   /* Write out the whole kernel process table entry to get the regs. */
XX!   trace_off = 0;
XX!   while (sys_trace(3, slot, trace_off, &trace_data) == OK) {
XX! 	if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
XX! 	    != (unsigned) sizeof (long)) {
XX! 		close(fd);
XX  		return;
XX  	}
XX+ 	trace_off += sizeof (long);
XX+   }
XX  
XX!   /* Loop through segments and write the segments themselves out. */
XX!   for (seg = 0; seg < NR_SEGS; seg++) {
XX! 	buf = (char *) ((vir_bytes) rmp->mp_seg[seg].mem_vir << CLICK_SHIFT);
XX! 	left = (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT;
XX! 	fake_fd = (slot << 8) | (seg << 6) | fd;
XX  
XX! 	/* Loop through a segment, dumping it. */
XX! 	while (left != 0) {
XX! 		nr_to_write = (unsigned) MIN(left, DUMP_SIZE);
XX! 		if ( (nr_written = write(fake_fd, buf, nr_to_write)) < 0) {
XX! 			close(fd);
XX! 			return;
XX  		}
XX+ 		buf += nr_written;
XX+ 		left -= nr_written;
XX  	}
XX    }
XX!   close(fd);
XX  }
X/
Xecho x - table.c.d
Xsed '/^X/s///' > table.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/table.c  crc=30609   2579	Sat Apr 21 22:26:24 1990
XX--- /home/top/ast/minix/1.6.25/mm/table.c  crc=22567   2674	Tue Nov  3 21:19:37 1992
XX***************
XX*** 6,21 ****
XX  
XX  #include "mm.h"
XX  #include <minix/callnr.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX  /* Miscellaneous */
XX  char core_name[] = "core";	/* file name where core images are produced */
XX- unshort core_bits = 0x0EFC;	/* which signals cause core images */
XX  
XX  char *stackpt = &mm_stack[MM_STACK_BYTES];	/* initial stack pointer */
XX  
XX! int (*call_vec[NCALLS])() = {
XX  	no_sys,		/*  0 = unused	*/
XX  	do_mm_exit,	/*  1 = exit	*/
XX  	do_fork,	/*  2 = fork	*/
XX--- 6,21 ----
XX  
XX  #include "mm.h"
XX  #include <minix/callnr.h>
XX+ #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX  /* Miscellaneous */
XX  char core_name[] = "core";	/* file name where core images are produced */
XX  
XX  char *stackpt = &mm_stack[MM_STACK_BYTES];	/* initial stack pointer */
XX  
XX! _PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
XX  	no_sys,		/*  0 = unused	*/
XX  	do_mm_exit,	/*  1 = exit	*/
XX  	do_fork,	/*  2 = fork	*/
XX***************
XX*** 23,33 ****
XX  	no_sys,		/*  4 = write	*/
XX  	no_sys,		/*  5 = open	*/
XX  	no_sys,		/*  6 = close	*/
XX! 	do_wait,	/*  7 = wait	*/
XX  	no_sys,		/*  8 = creat	*/
XX  	no_sys,		/*  9 = link	*/
XX  	no_sys,		/* 10 = unlink	*/
XX! 	no_sys,		/* 11 = exec	*/
XX  	no_sys,		/* 12 = chdir	*/
XX  	no_sys,		/* 13 = time	*/
XX  	no_sys,		/* 14 = mknod	*/
XX--- 23,33 ----
XX  	no_sys,		/*  4 = write	*/
XX  	no_sys,		/*  5 = open	*/
XX  	no_sys,		/*  6 = close	*/
XX! 	do_waitpid,	/*  7 = wait	*/
XX  	no_sys,		/*  8 = creat	*/
XX  	no_sys,		/*  9 = link	*/
XX  	no_sys,		/* 10 = unlink	*/
XX! 	do_waitpid,	/* 11 = waitpid	*/
XX  	no_sys,		/* 12 = chdir	*/
XX  	no_sys,		/* 13 = time	*/
XX  	no_sys,		/* 14 = mknod	*/
XX***************
XX*** 86,96 ****
XX  	do_brk2, 	/* 66 = BRK2 (used to tell MM size of FS,INIT) */
XX  	no_sys,		/* 67 = REVIVE	*/
XX  	no_sys,		/* 68 = TASK_REPLY	*/
XX- #if (CHIP == INTEL)
XX- #if AM_KERNEL
XX- 	do_amoeba,	/* 69 = AMOEBA SYSTEM CALL */
XX- #else
XX  	no_sys,		/* 69 = AMOEBA SYSTEM CALL */
XX! #endif
XX! #endif
XX  };
XX--- 86,96 ----
XX  	do_brk2, 	/* 66 = BRK2 (used to tell MM size of FS,INIT) */
XX  	no_sys,		/* 67 = REVIVE	*/
XX  	no_sys,		/* 68 = TASK_REPLY	*/
XX  	no_sys,		/* 69 = AMOEBA SYSTEM CALL */
XX! 	no_sys,		/* 70 = unused */
XX! 	do_sigaction,	/* 71 = SIGACTION */
XX! 	do_sigsuspend,	/* 72 = SIGSUSPEND */
XX! 	do_sigpending,	/* 73 = SIGPENDING */
XX! 	do_sigmask,	/* 74 = SIGMASK */
XX! 	do_sigreturn,	/* 75 = SIGRETURN */
XX  };
X/
Xecho x - trace.c.d
Xsed '/^X/s///' > trace.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/trace.c  crc=13911   2186	Sat Apr 21 22:26:25 1990
XX--- /home/top/ast/minix/1.6.25/mm/trace.c  crc=30492   2389	Tue Nov  3 21:19:37 1992
XX***************
XX*** 1,22 ****
XX  #include "mm.h"
XX  #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX! FORWARD struct mproc *findproc();
XX  
XX  /*===========================================================================*
XX   *				findproc  				     *
XX   *===========================================================================*/
XX  PRIVATE struct mproc *findproc(lpid)
XX! int lpid;
XX  {
XX    register struct mproc *rmp;
XX  
XX!   for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++ )
XX! 	if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return rmp;
XX! 
XX!   return 0;
XX  }
XX  
XX  /*===========================================================================*
XX--- 1,26 ----
XX+ /* This file header doesn't contain the usual boilerplate. */
XX+ 
XX  #include "mm.h"
XX+ #include <sys/ptrace.h>
XX  #include <signal.h>
XX  #include "mproc.h"
XX  #include "param.h"
XX  
XX! #define NIL_MPROC	((struct mproc *) 0)
XX  
XX+ FORWARD _PROTOTYPE( struct mproc *findproc, (pid_t lpid) );
XX+ 
XX  /*===========================================================================*
XX   *				findproc  				     *
XX   *===========================================================================*/
XX  PRIVATE struct mproc *findproc(lpid)
XX! pid_t lpid;
XX  {
XX    register struct mproc *rmp;
XX  
XX!   for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++)
XX! 	if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
XX!   return(NIL_MPROC);
XX  }
XX  
XX  /*===========================================================================*
XX***************
XX*** 26,78 ****
XX  {
XX    register struct mproc *child;
XX  
XX!   if (request == 0) {  /* enable tracing by parent for this process */
XX  	mp->mp_flags |= TRACED;
XX  	mm_out.m2_l2 = 0;
XX! 	return OK;
XX    }
XX!   if ((child = findproc(pid)) == 0 || (child->mp_flags & STOPPED) == 0) {
XX! 	return ESRCH;
XX    }
XX!   if (request == 8) { /* exit */
XX  	mm_exit(child, data);
XX  	mm_out.m2_l2 = 0;
XX! 	return OK;
XX    }
XX!   if (request == 7) { /* resume execution */
XX! 	if (data > _NSIG) {
XX! 		return EIO;
XX! 	}
XX! 	if (data > 0) { /* issue signal */
XX! 		child->mp_flags &= ~TRACED; /* so signal is not diverted */
XX! 		sig_proc(child, (int)data);
XX  		child->mp_flags |= TRACED;
XX  	}
XX  	child->mp_flags &= ~STOPPED;
XX!   }	
XX!   if (sys_trace(request, (int)(child - mproc), (long)taddr, (long *)&data) != OK)
XX! 	return -errno;
XX    mm_out.m2_l2 = data;
XX!   return OK;
XX  }
XX  
XX  /*===========================================================================*
XX   *				stop_proc  				     *
XX   *===========================================================================*/
XX! PUBLIC void stop_proc(rmp, sig_nr) /* a traced process got a signal so stop */
XX  register struct mproc *rmp;
XX! int sig_nr;
XX  {
XX    register struct mproc *rpmp = mproc + rmp->mp_parent;
XX  
XX!   if (sys_trace(-1, (int)(rmp - mproc), 0L, (long *)0) != OK) return;
XX    rmp->mp_flags |= STOPPED;
XX    if (rpmp->mp_flags & WAITING) {
XX  	rpmp->mp_flags &= ~WAITING;	/* parent is no longer waiting */
XX! 	reply(rmp->mp_parent, rmp->mp_pid, 0177 | (sig_nr << 8), NIL_PTR);
XX!   }
XX!   else {
XX! 	rmp->mp_sigstatus = sig_nr;
XX    }
XX    return;
XX  }
XX--- 30,81 ----
XX  {
XX    register struct mproc *child;
XX  
XX!   if (request == T_OK) {	/* enable tracing by parent for this process */
XX  	mp->mp_flags |= TRACED;
XX  	mm_out.m2_l2 = 0;
XX! 	return(OK);
XX    }
XX!   if ((child = findproc(pid)) == NIL_MPROC || !(child->mp_flags & STOPPED)) {
XX! 	return(ESRCH);
XX    }
XX!   if (request == T_EXIT) {	/* exit */
XX  	mm_exit(child, data);
XX  	mm_out.m2_l2 = 0;
XX! 	return(OK);
XX    }
XX!   if (request == T_RESUME || request == T_STEP) {	/* resume execution */
XX! 	if (data < 0 || data > _NSIG) return(EIO);
XX! 	if (data > 0) {		/* issue signal */
XX! 		child->mp_flags &= ~TRACED;  /* so signal is not diverted */
XX! 		sig_proc(child, (int) data);
XX  		child->mp_flags |= TRACED;
XX  	}
XX  	child->mp_flags &= ~STOPPED;
XX!   }
XX!   if (sys_trace(request, (int) (child - mproc), taddr, &data) != OK)
XX! 	return(-errno);
XX    mm_out.m2_l2 = data;
XX!   return(OK);
XX  }
XX  
XX  /*===========================================================================*
XX   *				stop_proc  				     *
XX   *===========================================================================*/
XX! PUBLIC void stop_proc(rmp, signo)
XX  register struct mproc *rmp;
XX! int signo;
XX  {
XX+ /* A traced process got a signal so stop it. */
XX+ 
XX    register struct mproc *rpmp = mproc + rmp->mp_parent;
XX  
XX!   if (sys_trace(-1, (int) (rmp - mproc), 0L, (long *) 0) != OK) return;
XX    rmp->mp_flags |= STOPPED;
XX    if (rpmp->mp_flags & WAITING) {
XX  	rpmp->mp_flags &= ~WAITING;	/* parent is no longer waiting */
XX! 	reply(rmp->mp_parent, rmp->mp_pid, 0177 | (signo << 8), NIL_PTR);
XX!   } else {
XX! 	rmp->mp_sigstatus = signo;
XX    }
XX    return;
XX  }
X/
Xecho x - utility.c.d
Xsed '/^X/s///' > utility.c.d << '/'
XX*** /home/top/ast/minix/1.5/mm/utility.c  crc=13020   4080	Sat Apr 21 22:26:25 1990
XX--- /home/top/ast/minix/1.6.25/mm/utility.c  crc=05303  11390	Tue Nov  3 21:19:37 1992
XX***************
XX*** 1,61 ****
XX! /* This file contains some useful utility routines used by MM.
XX   *
XX!  * The entries into the file are:
XX   *   allowed:	see if an access is permitted
XX   *   mem_copy:	copy data from somewhere in memory to somewhere else
XX   *   no_sys:	this routine is called for invalid system call numbers
XX   *   panic:	MM has run aground of a fatal error and cannot continue
XX   */
XX  
XX  #include "mm.h"
XX  #include <sys/stat.h>
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX  #include "mproc.h"
XX  
XX- PRIVATE message copy_mess;
XX- 
XX  /*===========================================================================*
XX   *				allowed					     *
XX   *===========================================================================*/
XX  PUBLIC int allowed(name_buf, s_buf, mask)
XX  char *name_buf;			/* pointer to file name to be EXECed */
XX! struct stat *s_buf;		/* buffer for doing and returning stat struct */
XX  int mask;			/* R_BIT, W_BIT, or X_BIT */
XX  {
XX  /* Check to see if file can be accessed.  Return EACCES or ENOENT if the access
XX   * is prohibited.  If it is legal open the file and return a file descriptor.
XX   */
XX  
XX!   register int fd, shift;
XX!   int mode;
XX  
XX!   /* Open the file and stat it. */
XX!   if ( (fd = open(name_buf, 0)) < 0) return(-errno);
XX    if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM);
XX  
XX    /* Only regular files can be executed. */
XX!   mode = s_buf->st_mode & I_TYPE;
XX!   if (mask == X_BIT && mode != I_REGULAR) {
XX  	close(fd);
XX  	return(EACCES);
XX    }
XX!   /* Even for superuser, at least 1 X bit must be on. */
XX!   if (mp->mp_effuid == SUPER_USER && mask == X_BIT &&
XX! 	(s_buf->st_mode & (X_BIT << 6 | X_BIT << 3 | X_BIT))) return(fd);
XX  
XX-   /* Right adjust the relevant set of permission bits. */
XX-   if (mp->mp_effuid == s_buf->st_uid) shift = 6;
XX-   else if (mp->mp_effgid == s_buf->st_gid) shift = 3;
XX-   else shift = 0;
XX  
XX!   if (mp->mp_effuid == SUPER_USER && mask != X_BIT) return(fd);
XX!   if (s_buf->st_mode >> shift & mask)	/* test the relevant bits */
XX! 	return(fd);		/* permission granted */
XX!   else {
XX! 	close(fd);		/* permission denied */
XX! 	return(EACCES);
XX!   }
XX  }
XX  
XX  
XX--- 1,76 ----
XX! 
XX! /* This file contains some utility routines for MM.
XX   *
XX!  * The entry points are:
XX   *   allowed:	see if an access is permitted
XX   *   mem_copy:	copy data from somewhere in memory to somewhere else
XX   *   no_sys:	this routine is called for invalid system call numbers
XX   *   panic:	MM has run aground of a fatal error and cannot continue
XX+  *   sys_*:	various interfaces to sendrec(SYSTASK, ...)
XX+  *   tell_fs:	interface to FS
XX   */
XX  
XX  #include "mm.h"
XX  #include <sys/stat.h>
XX  #include <minix/callnr.h>
XX  #include <minix/com.h>
XX+ #include <fcntl.h>
XX+ #include <signal.h>		/* needed only because mproc.h needs it */
XX+ #include <unistd.h>
XX  #include "mproc.h"
XX  
XX  /*===========================================================================*
XX   *				allowed					     *
XX   *===========================================================================*/
XX  PUBLIC int allowed(name_buf, s_buf, mask)
XX  char *name_buf;			/* pointer to file name to be EXECed */
XX! struct stat *s_buf;		/* buffer for doing and returning stat struct*/
XX  int mask;			/* R_BIT, W_BIT, or X_BIT */
XX  {
XX  /* Check to see if file can be accessed.  Return EACCES or ENOENT if the access
XX   * is prohibited.  If it is legal open the file and return a file descriptor.
XX   */
XX  
XX!   int fd;
XX!   int save_errno;
XX  
XX!   /* Use the fact that mask for access() is the same as the permissions mask.
XX!    * E.g., X_BIT in <minix/const.h> is the same as X_OK in <unistd.h> and
XX!    * S_IXOTH in <sys/stat.h>.  tell_fs(DO_CHDIR, ...) has set MM's real ids
XX!    * to the user's effective ids, so access() works right for setuid programs.
XX!    */
XX!   if (access(name_buf, mask) < 0) return(-errno);
XX! 
XX!   /* The file is accessible but might not be readable.  Make it readable. */
XX!   tell_fs(SETUID, MM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
XX! 
XX!   /* Open the file and fstat it.  Restore the ids early to handle errors. */
XX!   fd = open(name_buf, O_RDONLY);
XX!   save_errno = errno;		/* open might fail, e.g. from ENFILE */
XX!   tell_fs(SETUID, MM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
XX!   if (fd < 0) return(-save_errno);
XX    if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM);
XX  
XX    /* Only regular files can be executed. */
XX!   if (mask == X_BIT && (s_buf->st_mode & I_TYPE) != I_REGULAR) {
XX  	close(fd);
XX  	return(EACCES);
XX    }
XX!   return(fd);
XX! }
XX  
XX  
XX! /*===========================================================================*
XX!  *				find_proc  				     *
XX!  *===========================================================================*/
XX! PUBLIC struct mproc *find_proc(pid)
XX! pid_t pid;
XX! {
XX!   register struct mproc *rmp;
XX! 
XX!   for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++)
XX! 	if (rmp->mp_flags & IN_USE && rmp->mp_pid == pid) return(rmp);
XX!   return(NIL_MPROC);
XX  }
XX  
XX  
XX***************
XX*** 65,81 ****
XX  PUBLIC int mem_copy(src_proc,src_seg, src_vir, dst_proc,dst_seg, dst_vir, bytes)
XX  int src_proc;			/* source process */
XX  int src_seg;			/* source segment: T, D, or S */
XX! long src_vir;			/* source virtual address (clicks for ABS) */
XX  int dst_proc;			/* dest process */
XX  int dst_seg;			/* dest segment: T, D, or S */
XX! long dst_vir;			/* dest virtual address (clicks for ABS) */
XX! long bytes;			/* how many bytes (clicks for ABS) */
XX  {
XX  /* Transfer a block of data.  The source and destination can each either be a
XX   * process (including MM) or absolute memory, indicate by setting 'src_proc'
XX   * or 'dst_proc' to ABS.
XX   */
XX  
XX    if (bytes == 0L) return(OK);
XX    copy_mess.SRC_SPACE = (char) src_seg;
XX    copy_mess.SRC_PROC_NR = src_proc;
XX--- 80,98 ----
XX  PUBLIC int mem_copy(src_proc,src_seg, src_vir, dst_proc,dst_seg, dst_vir, bytes)
XX  int src_proc;			/* source process */
XX  int src_seg;			/* source segment: T, D, or S */
XX! long src_vir;			/* source virtual address (phys addr for ABS)*/
XX  int dst_proc;			/* dest process */
XX  int dst_seg;			/* dest segment: T, D, or S */
XX! long dst_vir;			/* dest virtual address (phys addr for ABS) */
XX! long bytes;			/* how many bytes */
XX  {
XX  /* Transfer a block of data.  The source and destination can each either be a
XX   * process (including MM) or absolute memory, indicate by setting 'src_proc'
XX   * or 'dst_proc' to ABS.
XX   */
XX  
XX+   message copy_mess;
XX+ 
XX    if (bytes == 0L) return(OK);
XX    copy_mess.SRC_SPACE = (char) src_seg;
XX    copy_mess.SRC_PROC_NR = src_proc;
XX***************
XX*** 89,94 ****
XX--- 106,113 ----
XX    sys_copy(&copy_mess);
XX    return(copy_mess.m_type);
XX  }
XX+ 
XX+ 
XX  /*===========================================================================*
XX   *				no_sys					     *
XX   *===========================================================================*/
XX***************
XX*** 113,120 ****
XX   */
XX  
XX    printf("Memory manager panic: %s ", format);
XX!   if (num != NO_NUM) printf("%d",num); 
XX    printf("\n");
XX    tell_fs(SYNC, 0, 0, 0);	/* flush the cache to the disk */
XX    sys_abort();
XX  }
XX--- 132,368 ----
XX   */
XX  
XX    printf("Memory manager panic: %s ", format);
XX!   if (num != NO_NUM) printf("%d",num);
XX    printf("\n");
XX    tell_fs(SYNC, 0, 0, 0);	/* flush the cache to the disk */
XX    sys_abort();
XX+ }
XX+ 
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_exec				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_exec(proc, ptr, traced, prog_name, initpc)
XX+ int proc;			/* process that did exec */
XX+ char *ptr;			/* new stack pointer */
XX+ int traced;			/* is tracing enabled? */
XX+ char *prog_name;		/* name of the new program */
XX+ vir_bytes initpc;
XX+ {
XX+ /* A process has exec'd.  Tell the kernel. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   m.m1_i2 = traced;
XX+   m.m1_p1 = ptr;
XX+   m.m1_p2 = prog_name;
XX+   m.m1_p3 = (char *)initpc;
XX+   _taskcall(SYSTASK, SYS_EXEC, &m);
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_fork				     *
XX+  *===========================================================================*/
XX+ PUBLIC int sys_fork(parent, child, pid, child_base_or_shadow)
XX+ int parent;			/* process doing the fork */
XX+ int child;			/* which proc has been created by the fork */
XX+ int pid;			/* process id assigned by MM */
XX+ phys_clicks child_base_or_shadow;	/* position for child [VM386];
XX+ 				 * memory allocated for shadow [68000] */
XX+ {
XX+ /* A process has forked.  Tell the kernel. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = parent;
XX+   m.m1_i2 = child;
XX+   m.m1_i3 = pid;
XX+   m.m1_p1 = (char *) child_base_or_shadow;
XX+   return(_taskcall(SYSTASK, SYS_FORK, &m));
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_getsp				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_getsp(proc, newsp)
XX+ int proc;			/* process whose sp is wanted */
XX+ vir_bytes *newsp;		/* place to put sp read from kernel */
XX+ {
XX+ /* Ask the kernel what the sp is. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   _taskcall(SYSTASK, SYS_GETSP, &m);
XX+   *newsp = (vir_bytes) m.STACK_PTR;
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_newmap				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_newmap(proc, ptr)
XX+ int proc;			/* process whose map is to be changed */
XX+ struct mem_map *ptr;		/* pointer to new map */
XX+ {
XX+ /* A process has been assigned a new memory map.  Tell the kernel. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   m.m1_p1 = (char *) ptr;
XX+   _taskcall(SYSTASK, SYS_NEWMAP, &m);
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_sendsig				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_sendsig(proc, smp)
XX+ int proc;
XX+ struct sigmsg *smp;
XX+ {
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   m.m1_p1 = (char *) smp;
XX+   _taskcall(SYSTASK, SYS_SENDSIG, &m);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_oldsig				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_oldsig(proc, sig, sighandler)
XX+ int proc;			/* process to be signaled  */
XX+ int sig;			/* signal number: 1 to _NSIG */
XX+ sighandler_t sighandler;	/* pointer to signal handler in user space */
XX+ {
XX+ /* A proc has to be signaled.  Tell the kernel. This function is obsolete. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m6_i1 = proc;
XX+   m.m6_i2 = sig;
XX+   m.m6_f1 = sighandler;
XX+   _taskcall(SYSTASK, SYS_OLDSIG, &m);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_endsig				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_endsig(proc)
XX+ int proc;
XX+ {
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   _taskcall(SYSTASK, SYS_ENDSIG, &m);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_sigreturn				     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_sigreturn(proc, scp, flags)
XX+ int proc;
XX+ vir_bytes scp;
XX+ int flags;
XX+ {
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   m.m1_i2 = flags;
XX+   m.m1_p1 = (char *) scp;
XX+   _taskcall(SYSTASK, SYS_SIGRETURN, &m);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_trace				     *
XX+  *===========================================================================*/
XX+ PUBLIC int sys_trace(req, procnr, addr, data_p)
XX+ int req, procnr;
XX+ long addr, *data_p;
XX+ {
XX+   message m;
XX+   int r;
XX+ 
XX+   m.m2_i1 = procnr;
XX+   m.m2_i2 = req;
XX+   m.m2_l1 = addr;
XX+   if (data_p) m.m2_l2 = *data_p;
XX+   r = _taskcall(SYSTASK, SYS_TRACE, &m);
XX+   if (data_p) *data_p = m.m2_l2;
XX+   return(r);
XX+ }
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_xit					     *
XX+  *===========================================================================*/
XX+ PUBLIC void sys_xit(parent, proc, basep, sizep)
XX+ int parent;			/* parent of exiting process */
XX+ int proc;			/* which process has exited */
XX+ phys_clicks *basep;		/* where to return base of shadow [68000] */
XX+ phys_clicks *sizep;		/* where to return size of shadow [68000] */
XX+ {
XX+ /* A process has exited.  Tell the kernel. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = parent;
XX+   m.m1_i2 = proc;
XX+   _taskcall(SYSTASK, SYS_XIT, &m);
XX+   *basep = (phys_clicks) m.m1_i1;
XX+   *sizep = (phys_clicks) m.m1_i2;
XX+ }
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				sys_fresh				     *
XX+  *===========================================================================*/
XX+ #if (CHIP == M68000) /* funny, the text cache version simply used sys_newmap */
XX+ PUBLIC void sys_fresh(proc, ptr, dc, basep, sizep)
XX+ int proc;			/* process whose map is to be changed */
XX+ struct mem_map *ptr;		/* pointer to new map */
XX+ phys_clicks dc;			/* size of initialized data */
XX+ phys_clicks *basep, *sizep;	/* base and size for free_mem() */
XX+ {
XX+ /* Create a fresh process image for exec().  Tell the kernel. */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = proc;
XX+   m.m1_i2 = (int) dc;
XX+   m.m1_p1 = (char *) ptr;
XX+   _taskcall(SYSTASK, SYS_FRESH, &m);
XX+   *basep = (phys_clicks) m.m1_i1;
XX+   *sizep = (phys_clicks) m.m1_i2;
XX+ }
XX+ #endif
XX+ 
XX+ 
XX+ /*===========================================================================*
XX+  *				tell_fs					     *
XX+  *===========================================================================*/
XX+ PUBLIC void tell_fs(what, p1, p2, p3)
XX+ int what, p1, p2, p3;
XX+ {
XX+ /* This routine is only used by MM to inform FS of certain events:
XX+  *      tell_fs(CHDIR, slot, dir, 0)
XX+  *      tell_fs(EXEC, proc, 0, 0)
XX+  *      tell_fs(EXIT, proc, 0, 0)
XX+  *      tell_fs(FORK, parent, child, pid)
XX+  *      tell_fs(SETGID, proc, realgid, effgid)
XX+  *      tell_fs(SETUID, proc, realuid, effuid)
XX+  *      tell_fs(SYNC, 0, 0, 0)
XX+  *      tell_fs(UNPAUSE, proc, signr, 0)
XX+  *      tell_fs(SETPGRP, proc, 0, 0)
XX+  */
XX+ 
XX+   message m;
XX+ 
XX+   m.m1_i1 = p1;
XX+   m.m1_i2 = p2;
XX+   m.m1_i3 = p3;
XX+   _taskcall(FS_PROC_NR, what, &m);
XX  }
X/
/
