1) Added proc file system from Paul Kranenburg with changes from
authorDavid Greenman <davidg@Root.COM>
Sun, 12 Dec 1993 12:31:40 +0000 (12:31 +0000)
committerDavid Greenman <davidg@Root.COM>
Sun, 12 Dec 1993 12:31:40 +0000 (12:31 +0000)
John Dyson to make it reliably work under FreeBSD.
2) Added and enabled PROCFS in the GENERICxx and LINT kernels.
3) New execve() from me. Still work to be done here, but this version
works well and is needed before other changes can be made. For
a description of the design behind this, see freebsd-arch or
ask me.
4) Rewrote stack fault code; made user stack VM grow as needed rather
than all up front; improves performance a little and reduces
process memory requirements.
5) Incorporated fix from Gene Stark to fault/wire a user page table
page to fix a problem in copyout. This is a temporary fix and
is not appropriate for pageable page tables. For a description
of the problem, see Gene's post to the freebsd-hackers mailing
list.
6) Tighten up vm_page struct to reduce memory requirements for it. ifdef
pager page lock code as it's not being used currently.
7) Introduced new element to vmspace struct - vm_minsaddr; initial
(minimum) stack address. Compliment to vm_maxsaddr.
8) Added a panic if the allocation for process u-pages fails.
9) Improve performance and accuracy of kernel profiling by putting in
a little inline assembly instead of spl().
10) Made serial console with sio driver work. Still has problems with
serial input, but is almost useable.
11) Added -Bstatic to SYSTEM_LD in Makefile.i386 so that kernels will
build properly with the new ld.

28 files changed:
sys/conf/files
sys/i386/conf/GENERICAH
sys/i386/conf/GENERICBT
sys/i386/conf/LINT
sys/i386/conf/Makefile.i386
sys/i386/i386/cons.c
sys/i386/i386/machdep.c
sys/i386/i386/trap.c
sys/kern/aout_imgact.c [new file with mode: 0644]
sys/kern/kern_execve.c
sys/kern/shell_imgact.c [new file with mode: 0644]
sys/kern/subr_mcount.c
sys/kern/vfs_conf.c
sys/kern/vfs_vnops.c
sys/procfs/pfsnode.h [new file with mode: 0644]
sys/procfs/procfs_subr.c [new file with mode: 0644]
sys/procfs/procfs_vfsops.c [new file with mode: 0644]
sys/procfs/procfs_vnops.c [new file with mode: 0644]
sys/sys/imgact.h [new file with mode: 0644]
sys/sys/mount.h
sys/sys/procfs.h [new file with mode: 0644]
sys/sys/vnode.h
sys/vm/vm.h
sys/vm/vm_fault.c
sys/vm/vm_glue.c
sys/vm/vm_page.c
sys/vm/vm_page.h
sys/vm/vm_unix.c

index 948431a..51e4912 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: files,v 1.10 1993/11/18 00:06:16 wollman Exp $
+# $Id: files,v 1.11 1993/11/18 05:01:34 rgrimes Exp $
 #
 ddb/db_access.c                optional ddb
 ddb/db_aout.c          optional ddb
 #
 ddb/db_access.c                optional ddb
 ddb/db_aout.c          optional ddb
@@ -23,6 +23,7 @@ isofs/isofs_util.c    optional isofs
 isofs/isofs_vfsops.c   optional isofs
 isofs/isofs_vnops.c    optional isofs
 isofs/isofs_rrip.c      optional isofs
 isofs/isofs_vfsops.c   optional isofs
 isofs/isofs_vnops.c    optional isofs
 isofs/isofs_rrip.c      optional isofs
+kern/aout_imgact.c     standard
 kern/dead_vnops.c      standard
 kern/fifo_vnops.c      standard
 kern/init_main.c       standard
 kern/dead_vnops.c      standard
 kern/fifo_vnops.c      standard
 kern/init_main.c       standard
@@ -45,6 +46,7 @@ kern/kern_subr.c      standard
 kern/kern_synch.c      standard
 kern/kern_time.c       standard
 kern/kern_xxx.c                standard
 kern/kern_synch.c      standard
 kern/kern_time.c       standard
 kern/kern_xxx.c                standard
+kern/shell_imgact.c    standard
 kern/spec_vnops.c      standard
 kern/subr_log.c                standard
 kern/subr_mcount.c     optional profiling-routine
 kern/spec_vnops.c      standard
 kern/subr_log.c                standard
 kern/subr_mcount.c     optional profiling-routine
@@ -196,6 +198,9 @@ pcfs/pcfs_fat.c             optional pcfs
 pcfs/pcfs_lookup.c     optional pcfs
 pcfs/pcfs_vfsops.c     optional pcfs
 pcfs/pcfs_vnops.c      optional pcfs
 pcfs/pcfs_lookup.c     optional pcfs
 pcfs/pcfs_vfsops.c     optional pcfs
 pcfs/pcfs_vnops.c      optional pcfs
+procfs/procfs_vnops.c  optional procfs
+procfs/procfs_vfsops.c optional procfs
+procfs/procfs_subr.c   optional procfs
 scsi/cd.c              optional cd
 scsi/ch.c              optional ch
 scsi/scsiconf.c                optional scbus
 scsi/cd.c              optional cd
 scsi/ch.c              optional ch
 scsi/scsiconf.c                optional scbus
index 1e7dce9..2a6cce2 100644 (file)
@@ -1,7 +1,7 @@
 #
 # GENERICAH -- Generic machine with WD/AHx family disks
 #
 #
 # GENERICAH -- Generic machine with WD/AHx family disks
 #
-#      $Id: GENERICAH,v 1.16 1993/10/19 01:28:07 rgrimes Exp $
+#      $Id: GENERICAH,v 1.17 1993/11/03 20:02:20 ats Exp $
 #
 
 machine                "i386"
 #
 
 machine                "i386"
@@ -16,6 +16,7 @@ options               INET                    #InterNETworking
 options                ISOFS                   #ISO File System
 options                NFS                     #Network File System
 options                PCFS                    #MSDOS File System
 options                ISOFS                   #ISO File System
 options                NFS                     #Network File System
 options                PCFS                    #MSDOS File System
+options                PROCFS                  #Proc File System
 options                "COMPAT_43"             #Compatible with BSD 4.3
 options                "TCP_COMPAT_42"         #TCP/IP compatible with 4.2
 options                XSERVER                 #Xserver
 options                "COMPAT_43"             #Compatible with BSD 4.3
 options                "TCP_COMPAT_42"         #TCP/IP compatible with 4.2
 options                XSERVER                 #Xserver
index 9ac2d9f..5047fad 100644 (file)
@@ -1,7 +1,7 @@
 #
 # GENERICBT -- Generic machine with WD/BTx family disks
 #
 #
 # GENERICBT -- Generic machine with WD/BTx family disks
 #
-#      $Id: GENERICBT,v 1.15 1993/10/19 01:28:08 rgrimes Exp $
+#      $Id: GENERICBT,v 1.16 1993/11/03 20:02:21 ats Exp $
 #
 
 machine                "i386"
 #
 
 machine                "i386"
@@ -16,6 +16,7 @@ options               INET                    #InterNETworking
 options                ISOFS                   #ISO File System
 options                NFS                     #Network File System
 options                PCFS                    #MSDOS File System
 options                ISOFS                   #ISO File System
 options                NFS                     #Network File System
 options                PCFS                    #MSDOS File System
+options                PROCFS                  #Proc File System
 options                "COMPAT_43"             #Compatible with BSD 4.3
 options                "TCP_COMPAT_42"         #TCP/IP compatible with 4.2
 options                XSERVER                 #Xserver
 options                "COMPAT_43"             #Compatible with BSD 4.3
 options                "TCP_COMPAT_42"         #TCP/IP compatible with 4.2
 options                XSERVER                 #Xserver
index 351c07b..1bf083a 100644 (file)
@@ -4,7 +4,7 @@
 #
 #      This kernel is NOT MEANT to be runnable!
 #
 #
 #      This kernel is NOT MEANT to be runnable!
 #
-#      $Id: LINT,v 1.30 1993/11/18 05:01:45 rgrimes Exp $
+#      $Id: LINT,v 1.31 1993/12/06 01:57:16 wollman Exp $
 #
 
 machine                "i386"
 #
 
 machine                "i386"
@@ -70,6 +70,7 @@ options               NFS                     #Network File System
 options                NS                      #Xerox NS communications protocols
 options                NSIP                    #XNS over IP
 options                PCFS                    #PC (MSDOS) File System
 options                NS                      #Xerox NS communications protocols
 options                NSIP                    #XNS over IP
 options                PCFS                    #PC (MSDOS) File System
+options                PROCFS                  #Proc File System
 pseudo-device  ppp     2
 pseudo-device  pty     4
 options                QUOTA                   #enable disk quotas
 pseudo-device  ppp     2
 pseudo-device  pty     4
 options                QUOTA                   #enable disk quotas
index dcb8110..eb2e36c 100644 (file)
@@ -1,6 +1,6 @@
 # Copyright 1990 W. Jolitz
 #      from: @(#)Makefile.i386 7.1 5/10/91
 # Copyright 1990 W. Jolitz
 #      from: @(#)Makefile.i386 7.1 5/10/91
-#      $Id: Makefile.i386,v 1.15 1993/11/16 00:45:04 paul Exp $
+#      $Id: Makefile.i386,v 1.16 1993/11/25 01:30:38 wollman Exp $
 #
 # Makefile for FreeBSD
 #
 #
 # Makefile for FreeBSD
 #
@@ -54,7 +54,7 @@ SYSTEM_OBJS=locore.o exception.o swtch.o support.o ${OBJS} param.o \
        ioconf.o conf.o machdep.o
 SYSTEM_DEP=Makefile symbols.sort ${SYSTEM_OBJS}
 SYSTEM_LD_HEAD=        @echo loading $@; rm -f $@
        ioconf.o conf.o machdep.o
 SYSTEM_DEP=Makefile symbols.sort ${SYSTEM_OBJS}
 SYSTEM_LD_HEAD=        @echo loading $@; rm -f $@
-SYSTEM_LD= @${LD} -z -T ${LOAD_ADDRESS} -o $@ -X vers.o ${SYSTEM_OBJS}
+SYSTEM_LD= @${LD} -Bstatic -z -T ${LOAD_ADDRESS} -o $@ -X vers.o ${SYSTEM_OBJS}
 SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; \
        ${DBSYM} -fT ${LOAD_ADDRESS} $@; ${STRIP} -x $@; size $@; chmod 755 $@
 
 SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; \
        ${DBSYM} -fT ${LOAD_ADDRESS} $@; ${STRIP} -x $@; size $@; chmod 755 $@
 
index 4115310..8db8389 100644 (file)
@@ -36,7 +36,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)cons.c        7.2 (Berkeley) 5/9/91
  * SUCH DAMAGE.
  *
  *     from: @(#)cons.c        7.2 (Berkeley) 5/9/91
- *     $Id: cons.c,v 1.5 1993/11/07 17:41:32 wollman Exp $
+ *     $Id: cons.c,v 1.6 1993/11/25 01:30:50 wollman Exp $
  */
 
 
  */
 
 
 
 /* XXX - all this could be autoconfig()ed */
 int pccnprobe(), pccninit(), pccngetc(), pccnputc();
 
 /* XXX - all this could be autoconfig()ed */
 int pccnprobe(), pccninit(), pccngetc(), pccnputc();
+
+#include "sio.h"
+#if NSIO > 0
+int siocnprobe(), siocninit(), siocngetc(), siocnputc();
+#endif
+
 #include "com.h"
 #if NCOM > 0
 int comcnprobe(), comcninit(), comcngetc(), comcnputc();
 #include "com.h"
 #if NCOM > 0
 int comcnprobe(), comcninit(), comcngetc(), comcnputc();
@@ -62,6 +68,9 @@ int comcnprobe(), comcninit(), comcngetc(), comcnputc();
 
 struct consdev constab[] = {
        { pccnprobe,    pccninit,       pccngetc,       pccnputc },
 
 struct consdev constab[] = {
        { pccnprobe,    pccninit,       pccngetc,       pccnputc },
+#if NSIO > 0
+       { siocnprobe,   siocninit,      siocngetc,      siocnputc },
+#endif
 #if NCOM > 0
        { comcnprobe,   comcninit,      comcngetc,      comcnputc },
 #endif
 #if NCOM > 0
        { comcnprobe,   comcninit,      comcngetc,      comcnputc },
 #endif
index d89bf87..7e588e4 100644 (file)
@@ -35,7 +35,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
  * SUCH DAMAGE.
  *
  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
- *     $Id: machdep.c,v 1.19 1993/11/25 01:30:55 wollman Exp $
+ *     $Id: machdep.c,v 1.20 1993/12/03 05:07:43 alm Exp $
  */
 
 #include "npx.h"
  */
 
 #include "npx.h"
@@ -437,9 +437,6 @@ sendsig(catcher, sig, mask, code)
                                - sizeof(struct sigframe));
        }
 
                                - sizeof(struct sigframe));
        }
 
-       if ((unsigned)fp <= (unsigned)p->p_vmspace->vm_maxsaddr + MAXSSIZ - ctob(p->p_vmspace->vm_ssize)) 
-               (void)grow(p, (unsigned)fp);
-
        if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
                /*
                 * Process has trashed its stack; give it an illegal
        if (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == 0) {
                /*
                 * Process has trashed its stack; give it an illegal
index 97a7418..0aa2296 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)trap.c        7.4 (Berkeley) 5/13/91
  * SUCH DAMAGE.
  *
  *     from: @(#)trap.c        7.4 (Berkeley) 5/13/91
- *     $Id: trap.c,v 1.9 1993/11/28 09:28:54 davidg Exp $
+ *     $Id: trap.c,v 1.10 1993/12/03 05:07:45 alm Exp $
  */
 
 /*
  */
 
 /*
@@ -81,7 +81,6 @@ void  write_gs        __P((/* promoted u_short */ int gs));
 
 struct sysent sysent[];
 int    nsysent;
 
 struct sysent sysent[];
 int    nsysent;
-int dostacklimits;
 unsigned rcr2();
 extern short cpl;
 
 unsigned rcr2();
 extern short cpl;
 
@@ -117,6 +116,7 @@ char *trap_msg[] = {
        "stack fault",                          /* 27 T_STKFLT */
 };
 
        "stack fault",                          /* 27 T_STKFLT */
 };
 
+#define pde_v(v) (PTD[((v)>>PD_SHIFT)&1023].pd_v)
 
 /*
  * trap(frame):
 
 /*
  * trap(frame):
@@ -287,10 +287,11 @@ copyfault:
                register vm_offset_t va;
                register struct vmspace *vm = p->p_vmspace;
                register vm_map_t map;
                register vm_offset_t va;
                register struct vmspace *vm = p->p_vmspace;
                register vm_map_t map;
-               int rv;
+               int rv = 0;
                vm_prot_t ftype;
                extern vm_map_t kernel_map;
                vm_prot_t ftype;
                extern vm_map_t kernel_map;
-               unsigned nss,v;
+               unsigned nss;
+               char *v;
 
                va = trunc_page((vm_offset_t)eva);
                /*
 
                va = trunc_page((vm_offset_t)eva);
                /*
@@ -323,21 +324,45 @@ copyfault:
                nss = 0;
                if ((caddr_t)va >= vm->vm_maxsaddr
                        && (caddr_t)va < (caddr_t)USRSTACK
                nss = 0;
                if ((caddr_t)va >= vm->vm_maxsaddr
                        && (caddr_t)va < (caddr_t)USRSTACK
-                       && map != kernel_map
-                       && dostacklimits) {
-                       nss = clrnd(btoc((unsigned)vm->vm_maxsaddr
-                               + MAXSSIZ - (unsigned)va));
-                       if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
-/*pg("trap rlimit %d, maxsaddr %x va %x ", nss, vm->vm_maxsaddr, va);*/
+                       && map != kernel_map) {
+                       nss = roundup(USRSTACK - (unsigned)va, PAGE_SIZE);
+                       if (nss > p->p_rlimit[RLIMIT_STACK].rlim_cur) {
                                rv = KERN_FAILURE;
                                goto nogo;
                        }
                                rv = KERN_FAILURE;
                                goto nogo;
                        }
+
+                       if (vm->vm_ssize && roundup(vm->vm_ssize << PGSHIFT,
+                           DFLSSIZ) < nss) {
+                               int grow_amount;
+                               /*
+                                * If necessary, grow the VM that the stack occupies
+                                * to allow for the rlimit. This allows us to not have
+                                * to allocate all of the VM up-front in execve (which
+                                * is expensive).
+                                * Grow the VM by the amount requested rounded up to
+                                * the nearest DFLSSIZ to provide for some hysteresis.
+                                */
+                               grow_amount = roundup(nss, DFLSSIZ);
+                               v = (char *)USRSTACK - roundup(vm->vm_ssize << PGSHIFT,
+                                   DFLSSIZ) - grow_amount;
+                               /*
+                                * If there isn't enough room to extend by DFLSSIZ, then
+                                * just extend to the maximum size
+                                */
+                               if (v < vm->vm_maxsaddr) {
+                                       v = vm->vm_maxsaddr;
+                                       grow_amount = MAXSSIZ - (vm->vm_ssize << PGSHIFT);
+                               }
+                               if (vm_allocate(&vm->vm_map, &v, grow_amount, FALSE) !=
+                                   KERN_SUCCESS) {
+                                       goto nogo;
+                               }
+                       }
                }
 
                /* check if page table is mapped, if not, fault it first */
                }
 
                /* check if page table is mapped, if not, fault it first */
-#define pde_v(v) (PTD[((v)>>PD_SHIFT)&1023].pd_v)
                if (!pde_v(va)) {
                if (!pde_v(va)) {
-                       v = trunc_page(vtopte(va));
+                       v = (char *)trunc_page(vtopte(va));
                        rv = vm_fault(map, v, ftype, FALSE);
                        if (rv != KERN_SUCCESS) goto nogo;
                        /* check if page table fault, increment wiring */
                        rv = vm_fault(map, v, ftype, FALSE);
                        if (rv != KERN_SUCCESS) goto nogo;
                        /* check if page table fault, increment wiring */
@@ -348,13 +373,23 @@ copyfault:
                        /*
                         * XXX: continuation of rude stack hack
                         */
                        /*
                         * XXX: continuation of rude stack hack
                         */
+                       nss = nss >> PGSHIFT;
                        if (nss > vm->vm_ssize)
                                vm->vm_ssize = nss;
                        if (nss > vm->vm_ssize)
                                vm->vm_ssize = nss;
+                       /* 
+                        * va could be a page table address, if the fault
+                        * occurred from within copyout.  In that case,
+                        * we have to wire it. (EWS 12/11/93)
+                        */
+                       if (ispt(va))
+                               vm_map_pageable(map, va, round_page(va+1), FALSE);
                        va = trunc_page(vtopte(va));
                        va = trunc_page(vtopte(va));
-                       /* for page table, increment wiring
-                          as long as not a page table fault as well */
+                       /*
+                        * for page table, increment wiring
+                        * as long as not a page table fault as well
+                        */
                        if (!v && type != T_PAGEFLT)
                        if (!v && type != T_PAGEFLT)
-                         vm_map_pageable(map, va, round_page(va+1), FALSE);
+                               vm_map_pageable(map, va, round_page(va+1), FALSE);
                        if (type == T_PAGEFLT)
                                return;
                        goto out;
                        if (type == T_PAGEFLT)
                                return;
                        goto out;
@@ -370,9 +405,11 @@ nogo:
                        goto we_re_toast;
                }
                i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
                        goto we_re_toast;
                }
                i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
+
+               /* kludge to pass faulting virtual address to sendsig */
                ucode = type &~ T_USER;
                frame.tf_err = eva;
                ucode = type &~ T_USER;
                frame.tf_err = eva;
-                    /* kludge to pass faulting virtual address to sendsig */
+
                break;
            }
 
                break;
            }
 
@@ -464,6 +501,7 @@ int trapwrite(addr)
        struct proc *p;
        vm_offset_t va;
        struct vmspace *vm;
        struct proc *p;
        vm_offset_t va;
        struct vmspace *vm;
+       char *v;
 
        va = trunc_page((vm_offset_t)addr);
        /*
 
        va = trunc_page((vm_offset_t)addr);
        /*
@@ -478,12 +516,38 @@ int trapwrite(addr)
        p = curproc;
        vm = p->p_vmspace;
        if ((caddr_t)va >= vm->vm_maxsaddr
        p = curproc;
        vm = p->p_vmspace;
        if ((caddr_t)va >= vm->vm_maxsaddr
-           && (caddr_t)va < (caddr_t)USRSTACK  /* EWS 11/27/93 */
-           && dostacklimits) {
-               nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
-                                - (unsigned)va));
-               if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
+           && (caddr_t)va < (caddr_t)USRSTACK) {
+               nss = roundup(USRSTACK - (unsigned)va, PAGE_SIZE);
+               if (nss > p->p_rlimit[RLIMIT_STACK].rlim_cur)
                        return (1);
                        return (1);
+       
+               if (vm->vm_ssize && roundup(vm->vm_ssize << PGSHIFT,
+                       DFLSSIZ) < nss) {
+                       int grow_amount;
+                       /*
+                        * If necessary, grow the VM that the stack occupies
+                        * to allow for the rlimit. This allows us to not have
+                        * to allocate all of the VM up-front in execve (which
+                        * is expensive).
+                        * Grow the VM by the amount requested rounded up to
+                        * the nearest DFLSSIZ to provide for some hysteresis.
+                        */
+                       grow_amount = roundup(nss, DFLSSIZ);
+                       v = (char *)USRSTACK - roundup(vm->vm_ssize << PGSHIFT, DFLSSIZ) -
+                               grow_amount;
+                       /*
+                        * If there isn't enough room to extend by DFLSSIZ, then
+                        * just extend to the maximum size
+                        */
+                       if (v < vm->vm_maxsaddr) {
+                               v = vm->vm_maxsaddr;
+                               grow_amount = MAXSSIZ - (vm->vm_ssize << PGSHIFT);
+                       }
+                       if (vm_allocate(&vm->vm_map, &v, grow_amount, FALSE) !=
+                           KERN_SUCCESS) {
+                               return(1);
+                       }
+               }
        }
 
        if (vm_fault(&vm->vm_map, va, VM_PROT_READ | VM_PROT_WRITE, FALSE)
        }
 
        if (vm_fault(&vm->vm_map, va, VM_PROT_READ | VM_PROT_WRITE, FALSE)
@@ -493,6 +557,7 @@ int trapwrite(addr)
        /*
         * XXX: continuation of rude stack hack
         */
        /*
         * XXX: continuation of rude stack hack
         */
+       nss = nss >> PGSHIFT;
        if (nss > vm->vm_ssize)
                vm->vm_ssize = nss;
 
        if (nss > vm->vm_ssize)
                vm->vm_ssize = nss;
 
diff --git a/sys/kern/aout_imgact.c b/sys/kern/aout_imgact.c
new file mode 100644 (file)
index 0000000..e4314d4
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1993, David Greenman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by David Greenman
+ * 4. The name of the developer may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $Id: aout_imgact.c,v 1.3 1993/12/11 06:55:33 davidg Exp davidg $
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "resourcevar.h"
+#include "exec.h"
+#include "mman.h"
+#include "imgact.h"
+
+#include "vm/vm.h"
+
+int
+exec_aout_imgact(iparams)
+       struct image_params *iparams;
+{
+       struct exec *a_out = (struct exec *) iparams->image_header;
+       struct vmspace *vmspace = iparams->proc->p_vmspace;
+       unsigned long vmaddr, virtual_offset, file_offset;
+       unsigned long bss_size;
+       int error, len;
+
+       /*
+        * Set file/virtual offset based on a.out variant.
+        *      We do two cases: host byte order and network byte order
+        *      (for NetBSD compatibility)
+        */
+       switch (a_out->a_magic & 0xffff) {
+       case ZMAGIC:
+               virtual_offset = 0;
+               if (a_out->a_text) {
+                       file_offset = NBPG;
+               } else {
+                       /* Bill's "screwball mode" */
+                       file_offset = 0;
+               }
+               break;
+       case QMAGIC:
+               virtual_offset = NBPG;
+               file_offset = 0;
+               break;
+       default:
+               /* NetBSD compatibility */
+               switch (ntohl(a_out->a_magic) & 0xffff) {
+               case ZMAGIC:
+               case QMAGIC:
+                       virtual_offset = NBPG;
+                       file_offset = 0;
+                       break;
+               default:
+                       return (-1);
+               }
+       }
+
+       bss_size = roundup(a_out->a_bss, NBPG);
+
+       /*
+        * Check various fields in header for validity/bounds.
+        */
+       if (/* entry point must lay with text region */
+           a_out->a_entry < virtual_offset ||
+           a_out->a_entry >= virtual_offset + a_out->a_text ||
+
+           /* text and data size must each be page rounded */
+           a_out->a_text % NBPG ||
+           a_out->a_data % NBPG)
+               return (-1);
+
+       /* text + data can't exceed file size */
+       if (a_out->a_data + a_out->a_text > iparams->attr->va_size)
+               return (EFAULT);
+
+       /*
+        * text/data/bss must not exceed limits
+        */
+       if (/* text can't exceed maximum text size */
+           a_out->a_text > MAXTSIZ ||
+
+           /* data + bss can't exceed maximum data size */
+           a_out->a_data + bss_size > MAXDSIZ ||
+
+           /* data + bss can't exceed rlimit */
+           a_out->a_data + bss_size >
+               iparams->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
+                       return (ENOMEM);
+
+       /* copy in arguments and/or environment from old process */
+       error = exec_extract_strings(iparams);
+       if (error)
+               return (error);
+
+       /*
+        * Destroy old process VM and create a new one (with a new stack)
+        */
+       exec_new_vmspace(iparams);
+
+       /*
+        * Map text read/execute
+        */
+       vmaddr = virtual_offset;
+       error =
+           vm_mmap(&vmspace->vm_map,                   /* map */
+               &vmaddr,                                /* address */
+               a_out->a_text,                          /* size */
+               VM_PROT_READ | VM_PROT_EXECUTE,         /* protection */
+               VM_PROT_READ | VM_PROT_EXECUTE,         /* max protection */
+               MAP_FILE | MAP_PRIVATE | MAP_FIXED,     /* flags */
+               iparams->vnodep,                        /* vnode */
+               file_offset);                           /* offset */
+       if (error)
+               return (error);
+
+       /*
+        * Map data read/write (if text is 0, assume text is in data area
+        *      [Bill's screwball mode])
+        */
+       vmaddr = virtual_offset + a_out->a_text;
+       error =
+           vm_mmap(&vmspace->vm_map,
+               &vmaddr,
+               a_out->a_data,
+               VM_PROT_READ | VM_PROT_WRITE | (a_out->a_text ? 0 : VM_PROT_EXECUTE),
+               VM_PROT_READ | VM_PROT_WRITE | (a_out->a_text ? 0 : VM_PROT_EXECUTE),
+               MAP_FILE | MAP_PRIVATE | MAP_FIXED,
+               iparams->vnodep,
+               file_offset + a_out->a_text);
+       if (error)
+               return (error);
+
+       /*
+        * Allocate demand-zeroed area for uninitialized data
+        * "bss" = 'block started by symbol' - named after the IBM 7090
+        *      instruction of the same name.
+        */
+       vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
+       error = vm_allocate(&vmspace->vm_map, &vmaddr, bss_size, FALSE);
+       if (error)
+               return (error);
+
+       /* Fill in process VM information */
+       vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT;
+       vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT;
+       vmspace->vm_taddr = (caddr_t) virtual_offset;
+       vmspace->vm_daddr = (caddr_t) virtual_offset + a_out->a_text;
+
+       /* Fill in image_params */
+       iparams->interpreted = 0;
+       iparams->entry_addr = a_out->a_entry;
+       
+       return (0);
+}
index 22d2ff0..bd08ab7 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 1989, 1990, 1991, 1992 William F. Jolitz, TeleMuse
+ * Copyright (c) 1993, David Greenman
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *     This software is a component of "386BSD" developed by 
- *     William F. Jolitz, TeleMuse.
- * 4. Neither the name of the developer nor the name "386BSD"
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
+ *     This product includes software developed by David Greenman
+ * 4. The name of the developer may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
  *
  *
- * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 
- * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 
- * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 
- * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 
- * NOT MAKE USE OF THIS WORK.
- *
- * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
- * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 
- * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES 
- * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 
- * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 
- * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 
- * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 
- * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * This procedure implements a minimal program execution facility for
- * 386BSD. It interfaces to the BSD kernel as the execve system call.
- * Significant limitations and lack of compatiblity with POSIX are
- * present with this version, to make its basic operation more clear.
- *
- *     $Id: kern_execve.c,v 1.8 1993/10/25 17:26:01 davidg Exp $
+ *     $Id: kern_execve.c,v 1.4 1993/12/11 06:55:33 davidg Exp davidg $
  */
 
 #include "param.h"
 #include "systm.h"
 #include "signalvar.h"
 #include "resourcevar.h"
  */
 
 #include "param.h"
 #include "systm.h"
 #include "signalvar.h"
 #include "resourcevar.h"
-#include "proc.h"
+#include "imgact.h"
 #include "mount.h"
 #include "mount.h"
-#include "namei.h"
-#include "vnode.h"
 #include "file.h"
 #include "acct.h"
 #include "exec.h"
 #include "file.h"
 #include "acct.h"
 #include "exec.h"
@@ -68,6 +44,7 @@
 #include "wait.h"
 #include "mman.h"
 #include "malloc.h"
 #include "wait.h"
 #include "mman.h"
 #include "malloc.h"
+#include "syslog.h"
 
 #include "vm/vm.h"
 #include "vm/vm_param.h"
 
 #include "vm/vm.h"
 #include "vm/vm_param.h"
 
 #include "machine/reg.h"
 
 
 #include "machine/reg.h"
 
-extern int dostacklimits;
-#define        copyinoutstr    copyinstr
+int exec_extract_strings __P((struct image_params *));
+caddr_t exec_copyout_strings __P((struct image_params *));
+
+int exec_aout_imgact __P((struct image_params *));
+int exec_shell_imgact __P((struct image_params *));
+
+struct execsw {
+       int (*imgact) __P((struct image_params *));
+};
+
+struct execsw execsw[] = {
+       { exec_aout_imgact },
+       { exec_shell_imgact },
+       { NULL },
+       { NULL },
+       { NULL },
+       { NULL },
+       { NULL },
+       { NULL },
+};
 
 /*
  * execve() system call.
  */
 
 
 /*
  * execve() system call.
  */
 
-struct execve_args {
-       char    *fname;
-       char    **argp;
-       char    **envp;
-};
-
-/* ARGSUSED */
 int
 execve(p, uap, retval)
        struct proc *p;
        register struct execve_args *uap;
        int *retval;
 {
 int
 execve(p, uap, retval)
        struct proc *p;
        register struct execve_args *uap;
        int *retval;
 {
-       register struct nameidata *ndp;
-       struct nameidata nd;
-       char **argbuf, **argbufp, *stringbuf, *stringbufp;
-       char **vectp, *ep;
-       int needsenv, limitonargs, stringlen, addr, size, len,
-               rv, amt, argc = 0, tsize, dsize, bsize, cnt, file_offset,
-               virtual_offset;
+       struct nameidata nd, *ndp;
+       char *stringbase, *stringp, *stack_base;
+       int error, resid, len, i;
+#if 0
+       char image_header[256];
+#endif
+       struct image_params image_params, *iparams;
+       struct vnode *vnodep;
        struct vattr attr;
        struct vattr attr;
-       struct vmspace *vs;
-       caddr_t newframe;
-       char shellname[MAXINTERP];                      /* 05 Aug 92*/
-       char *shellargs = 0;
-       union {
-               char    ex_shell[MAXINTERP];    /* #! and interpreter name */
-               struct  exec ex_hdr;
-       } exdata;
-       int indir = 0;
+       char *image_header;
+
+       iparams = &image_params;
+       bzero((caddr_t)iparams, sizeof(struct image_params));
+       image_header = (char *)0;
 
        /*
 
        /*
-        * Step 1. Lookup filename to see if we have something to execute.
+        * Initialize a few constants in the common area
+        */
+       iparams->proc = p;
+       iparams->uap = uap;
+       iparams->attr = &attr;
+
+       /*
+        * Allocate temporary demand zeroed space for argument and
+        *      environment strings
+        */
+       error = vm_allocate(kernel_map, &iparams->stringbase, ARG_MAX, TRUE);
+       if (error) {
+               log(LOG_WARNING, "execve: failed to allocate string space\n");
+               return (error);
+       }
+
+       if (!iparams->stringbase) {
+               error = ENOMEM;
+               goto exec_fail;
+       }
+       iparams->stringp = iparams->stringbase;
+       iparams->stringspace = ARG_MAX;
+
+       /*
+        * Translate the file name. namei() returns a vnode pointer
+        *      in ni_vp amoung other things.
         */
        ndp = &nd;
         */
        ndp = &nd;
+       ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW | SAVENAME;
        ndp->ni_segflg = UIO_USERSPACE;
        ndp->ni_dirp = uap->fname;
 
        ndp->ni_segflg = UIO_USERSPACE;
        ndp->ni_dirp = uap->fname;
 
-again:                                                 /* 05 Aug 92*/
-       ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW | SAVENAME;
-
-       /* is it there? */
-       if (rv = namei(ndp, p))
-               return (rv);
+interpret:
 
 
-       if (ndp->ni_vp->v_writecount) { /* don't exec if file is busy */
-               rv = EBUSY;
-               goto exec_fail;
+       error = namei(ndp, p);
+       if (error) {
+               vm_deallocate(kernel_map, iparams->stringbase, ARG_MAX);
+               goto exec_fail; 
        }
        }
-       /* does it have any attributes? */
-       rv = VOP_GETATTR(ndp->ni_vp, &attr, p->p_ucred, p);
-       if (rv)
-               goto exec_fail;
 
 
-       if (ndp->ni_vp->v_mount->mnt_flag & MNT_NOEXEC) { /* no exec on fs ?*/
-               rv = EACCES;
-               goto exec_fail;
-       }
+       iparams->vnodep = vnodep = ndp->ni_vp;
 
 
-       /* is it executable, and a regular file? */
-       if ((ndp->ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||     /* 29 Jul 92*/
-               (VOP_ACCESS(ndp->ni_vp, VEXEC, p->p_ucred, p)) ||
-               ((attr.va_mode & 0111) == 0) ||
-               (attr.va_type != VREG)) {
-               rv = EACCES;
-               goto exec_fail;
+       if (vnodep == NULL) {
+               error = ENOEXEC;
+               goto exec_fail_dealloc;
        }
 
        /*
        }
 
        /*
-        * Step 2. Does the file contain a format we can
-        * understand and execute
-        *
-        * XXX 05 Aug 92
-        * Read in first few bytes of file for segment sizes, magic number:
-        *      ZMAGIC = demand paged RO text
-        * Also an ASCII line beginning with #! is
-        * the file name of a ``shell'' and arguments may be prepended
-        * to the argument list if given here.
+        * Check file permissions (also 'opens' file)
         */
         */
-       exdata.ex_shell[0] = '\0';      /* for zero length files */
-
-       rv = vn_rdwr(UIO_READ, ndp->ni_vp, (caddr_t)&exdata, sizeof(exdata),
-               0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &amt, p);
+       error = exec_check_permissions(iparams);
+       if (error)
+               goto exec_fail_dealloc;
 
 
-       /* big enough to hold a header? */
-       if (rv)
-               goto exec_fail;
-
-        if (exdata.ex_hdr.a_text != 0 && (ndp->ni_vp->v_flag & VTEXT) == 0 &&
-           ndp->ni_vp->v_writecount != 0) {
-               rv = ETXTBSY;
-               goto exec_fail;
+#if 0
+       /*
+        * Read the image header from the file.
+        */
+       error = vn_rdwr(UIO_READ,
+                       vnodep,
+                       image_header,
+                       sizeof(image_header),
+                       0,
+                       UIO_SYSSPACE, IO_NODELOCKED,
+                       p->p_ucred,
+                       &resid,
+                       p);
+       if (error)
+               goto exec_fail_dealloc;
+
+       /* Clear out junk in image_header if a partial read (small file) */
+       if (resid)
+               bzero(image_header + (sizeof(image_header) - resid), resid);
+#endif
+       /*
+        * Map the image header (first page) of the file into
+        *      kernel address space
+        */
+       error = vm_mmap(kernel_map,     /* map */
+                   &image_header,      /* address */
+                   NBPG,               /* size */
+                   VM_PROT_READ,       /* protection */
+                   VM_PROT_READ,       /* maximum protection */
+                   MAP_FILE,           /* flags */
+                   vnodep,             /* vnode */
+                   0);                 /* offset */
+       if (error) {
+               printf("mmap filed: %d\n",error);
+               goto exec_fail_dealloc;
        }
        }
-               
-#define SHELLMAGIC     0x2123 /* #! */
-
-       switch (exdata.ex_hdr.a_magic) {
-       case ZMAGIC:
-               virtual_offset = 0;
-               if (exdata.ex_hdr.a_text) {
-                       file_offset = NBPG;
-               } else {
-                       /* Bill's "screwball mode" */
-                       file_offset = 0;
-               }
-               break;
-       case QMAGIC:
-               virtual_offset = NBPG;
-               file_offset = 0;
-               break;
-       default:
-               if ((exdata.ex_hdr.a_magic & 0xffff) != SHELLMAGIC) {
-                       /* NetBSD compatibility */
-                       switch (ntohl(exdata.ex_hdr.a_magic) & 0xffff) {
-                       case ZMAGIC:
-                       case QMAGIC:
-                               virtual_offset = NBPG;
-                               file_offset = 0;
-                               break;
-                       default:
-                               rv = ENOEXEC;
-                               goto exec_fail;
-                       }
-               } else {
-                       char *cp, *sp;
-
-                       if (indir) {
-                               rv = ENOEXEC;
-                               goto exec_fail;
-                       }
-                       for (cp = &exdata.ex_shell[2];; ++cp) {
-                               if (cp >= &exdata.ex_shell[MAXINTERP]) {
-                                       rv = ENOEXEC;
-                                       goto exec_fail;
-                               }
-                               if (*cp == '\n') {
-                                       *cp = '\0';
-                                       break;
-                               }
-                               if (*cp == '\t')
-                                       *cp = ' ';
-                       }
-                       cp = &exdata.ex_shell[2]; /* get shell interpreter name */
-                       while (*cp == ' ')
-                               cp++;
-
-                       sp = shellname;
-                       while (*cp && *cp != ' ')
-                               *sp++ = *cp++;
-                       *sp = '\0';
-
-                       /* copy the args in the #! line */
-                       while (*cp == ' ')
-                         cp++;
-                       if (*cp) {
-                           sp++;
-                           shellargs = sp;
-                           while (*cp)
-                             *sp++ = *cp++;
-                           *sp = '\0';
-                       } else {
-                           shellargs = 0;
-                       }
-
-                       indir = 1;              /* indicate this is a script file */
+       iparams->image_header = image_header;
+
+       /*
+        * Loop through list of image activators, calling each one.
+        *      If there is no match, the activator returns -1. If there
+        *      is a match, but there was an error during the activation,
+        *      the error is returned. Otherwise 0 means success. If the
+        *      image is interpreted, loop back up and try activating
+        *      the interpreter.
+        */
+       for (i = 0; i < sizeof(execsw)/sizeof(execsw[0]); ++i) {
+               if (execsw[i].imgact)
+                       error = (*execsw[i].imgact)(iparams);
+               else
+                       continue;
+
+               if (error == -1)
+                       continue;
+               if (error)
+                       goto exec_fail_dealloc;
+               if (iparams->interpreted) {
+                       /* free old vnode and name buffer */
                        vput(ndp->ni_vp);
                        FREE(ndp->ni_pnbuf, M_NAMEI);
                        vput(ndp->ni_vp);
                        FREE(ndp->ni_pnbuf, M_NAMEI);
+                       if (vm_deallocate(kernel_map, image_header, NBPG))
+                               panic("execve: header dealloc failed (1)");
 
 
-                       ndp->ni_dirp = shellname;       /* find shell interpreter */
+                       /* set new name to that of the interpreter */
                        ndp->ni_segflg = UIO_SYSSPACE;
                        ndp->ni_segflg = UIO_SYSSPACE;
-                       goto again;
+                       ndp->ni_dirp = iparams->interpreter_name;
+                       ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW | SAVENAME;
+                       goto interpret;
                }
                }
-                       /* NOT REACHED */
+               break;
+       }
+       /* If we made it through all the activators and none matched, exit. */
+       if (error == -1) {
+               error = ENOEXEC;
+               goto exec_fail_dealloc;
        }
 
        }
 
-       /* sanity check  "ain't not such thing as a sanity clause" -groucho */
-       rv = ENOMEM;
-       if (/*exdata.ex_hdr.a_text == 0 || */ exdata.ex_hdr.a_text > MAXTSIZ ||
-           exdata.ex_hdr.a_text % NBPG || exdata.ex_hdr.a_text > attr.va_size)
-               goto exec_fail;
+       /*
+        * Copy out strings (args and env) and initialize stack base
+        */
+       stack_base = exec_copyout_strings(iparams);
+       p->p_vmspace->vm_minsaddr = stack_base;
+       p->p_regs[SP] = (int) stack_base;
 
 
-       if (exdata.ex_hdr.a_data == 0 || exdata.ex_hdr.a_data > DFLDSIZ
-               || exdata.ex_hdr.a_data > attr.va_size
-               || exdata.ex_hdr.a_data + exdata.ex_hdr.a_text > attr.va_size)
-               goto exec_fail;
+       p->p_vmspace->vm_ssize = (((caddr_t)USRSTACK - stack_base) >> PAGE_SHIFT) + 1;
 
 
-       if (exdata.ex_hdr.a_bss > MAXDSIZ)
-               goto exec_fail;
-       
-       if (exdata.ex_hdr.a_text + exdata.ex_hdr.a_data + exdata.ex_hdr.a_bss > MAXTSIZ + MAXDSIZ)
-               goto exec_fail;
+       /*
+        * Stuff argument count as first item on stack
+        */
+       p->p_regs[SP] -= sizeof(int);
+       *(int *)(p->p_regs[SP]) = iparams->argc;
 
 
-       if (exdata.ex_hdr.a_data + exdata.ex_hdr.a_bss > p->p_rlimit[RLIMIT_DATA].rlim_cur)
-               goto exec_fail;
+       /* close files on exec, fixup signals */
+       fdcloseexec(p);
+       execsigs(p);
 
 
-       if (exdata.ex_hdr.a_entry > exdata.ex_hdr.a_text + exdata.ex_hdr.a_data)
-               goto exec_fail;
+       /* name this process - nameiexec(p, ndp) */
+       len = MIN(ndp->ni_namelen,MAXCOMLEN);
+       bcopy(ndp->ni_ptr, p->p_comm, len);
+       p->p_comm[len] = 0;
        
        /*
        
        /*
-        * Step 3.  File and header are valid. Now, dig out the strings
-        * out of the old process image.
+        * mark as executable, wakeup any process that was vforked and tell
+        * it that it now has it's own resources back
         */
         */
+       p->p_flag |= SEXEC;
+       if (p->p_pptr && (p->p_flag & SPPWAIT)) {
+               p->p_flag &= ~SPPWAIT;
+               wakeup((caddr_t)p->p_pptr);
+       }
+       
+       /* implement set userid/groupid */
+       if ((attr.va_mode&VSUID) && (p->p_flag & STRC) == 0) {
+               p->p_ucred = crcopy(p->p_ucred);
+               p->p_cred->p_svuid = p->p_ucred->cr_uid = attr.va_uid;
+       }
+       if ((attr.va_mode&VSGID) && (p->p_flag & STRC) == 0) {
+               p->p_ucred = crcopy(p->p_ucred);
+               p->p_cred->p_svgid = p->p_ucred->cr_groups[0] = attr.va_gid;
+       }
+
+       /* mark vnode pure text */
+       ndp->ni_vp->v_flag |= VTEXT;
 
        /*
 
        /*
-        * We implement a single-pass algorithm that builds a new stack
-        * frame within the address space of the "old" process image,
-        * avoiding the second pass entirely. Thus, the new frame is
-        * in position to be run. This consumes much virtual address space,
-        * and two pages more of 'real' memory, such are the costs.
-        * [Also, note the cache wipe that's avoided!]
+        * If tracing the process, trap to debugger so breakpoints
+        *      can be set before the program executes.
         */
         */
+       if (p->p_flag & STRC)
+               psignal(p, SIGTRAP);
 
 
-       /* create anonymous memory region for new stack */
-       vs = p->p_vmspace;
-       if ((unsigned)vs->vm_maxsaddr + MAXSSIZ < USRSTACK)
-               newframe = (caddr_t) USRSTACK - MAXSSIZ;
-       else
-               vs->vm_maxsaddr = newframe = (caddr_t) USRSTACK - 2*MAXSSIZ;
-
-       /* don't do stack limit checking on traps temporarily XXX*/
-       dostacklimits = 0;
-
-       rv = vm_allocate(&vs->vm_map, &newframe, MAXSSIZ, FALSE);
-       if (rv) goto exec_fail;
-
-       /* allocate string buffer and arg buffer */
-       argbuf = (char **) (newframe + MAXSSIZ - 3*ARG_MAX);
-       stringbuf = stringbufp = ((char *)argbuf) + 2*ARG_MAX;
-       argbufp = argbuf;
-
-       /* first, do args */
-       vectp = uap->argp;
-       needsenv = 1;
-       limitonargs = ARG_MAX;
-       cnt = 0;
-
-       /* first, do (shell name if any then) args */
-       if (indir)  {
-               ep = shellname;
-thrice:
-               if (ep) {
-                       /* did we outgrow initial argbuf, if so, die */
-                       if (argbufp >= (char **)stringbuf) {
-                               rv = E2BIG;
-                               goto exec_dealloc;
-                       }
-
-                       if (rv = copyoutstr(ep, stringbufp,
-                               (u_int)limitonargs, (u_int *)&stringlen)) {
-                               if (rv == ENAMETOOLONG)
-                                       rv = E2BIG;
-                               goto exec_dealloc;
-                       }
-                       suword(argbufp++, (int)stringbufp);
-                       cnt++;
-                       stringbufp += stringlen;
-                       limitonargs -= stringlen;
-               }
-
-               if (shellargs) {
-                   ep = shellargs;
-                   shellargs = 0;
-                   goto thrice;
-               }
-
-               if (indir) {
-                       indir = 0;
-                       /* orginal executable is 1st argument with scripts */
-                       ep = uap->fname;
-                       goto thrice;
-               }
-               /* terminate in case no more args to script */
-               suword(argbufp, 0);
-               if (vectp = uap->argp) vectp++; /* manually doing the first
-                                                  argument with scripts */
-       }
+       /* clear "fork but no exec" flag, as we _are_ execing */
+       p->p_acflag &= ~AFORK;
 
 
-do_env_as_well:
-       if(vectp == 0) goto dont_bother;
+       /* Set entry address */
+       setregs(p, iparams->entry_addr);
 
 
-       /* for each envp, copy in string */
-       do {
-               /* did we outgrow initial argbuf, if so, die */
-               if (argbufp == (char **)stringbuf) {
-                       rv = E2BIG;
-                       goto exec_dealloc;
-               }
-       
-               /* get an string pointer */
-               ep = (char *)fuword(vectp++);
-               if (ep == (char *)-1) {
-                       rv = EFAULT;
-                       goto exec_dealloc;
-               }
+       /*
+        * free various allocated resources
+        */
+       if (vm_deallocate(kernel_map, iparams->stringbase, ARG_MAX))
+               panic("execve: string buffer dealloc failed (1)");
+       if (vm_deallocate(kernel_map, image_header, NBPG))
+               panic("execve: header dealloc failed (2)");
+       vput(ndp->ni_vp);
+       FREE(ndp->ni_pnbuf, M_NAMEI);
 
 
-               /* if not a null pointer, copy string */
-               if (ep) {
-                       if (rv = copyinoutstr(ep, stringbufp,
-                               (u_int)limitonargs, (u_int *) &stringlen)) {
-                               if (rv == ENAMETOOLONG)
-                                       rv = E2BIG;
-                               goto exec_dealloc;
-                       }
-                       suword(argbufp++, (int)stringbufp);
-                       cnt++;
-                       stringbufp += stringlen;
-                       limitonargs -= stringlen;
-               } else {
-                       suword(argbufp++, 0);
-                       break;
-               }
-       } while (limitonargs > 0);
+       return (0);
 
 
-dont_bother:
-       if (limitonargs <= 0) {
-               rv = E2BIG;
-               goto exec_dealloc;
-       }
+exec_fail_dealloc:
+       if (iparams->stringbase && iparams->stringbase != (char *)-1)
+               if (vm_deallocate(kernel_map, iparams->stringbase, ARG_MAX))
+                       panic("execve: string buffer dealloc failed (2)");
+       if (iparams->image_header && iparams->image_header != (char *)-1)
+               if (vm_deallocate(kernel_map, image_header, NBPG))
+                       panic("execve: header dealloc failed (3)");
+       vput(ndp->ni_vp);
+       FREE(ndp->ni_pnbuf, M_NAMEI);
 
 
-       /* have we done the environment yet ? */
-       if (needsenv) {
-               /* remember the arg count for later */
-               argc = cnt;
-               vectp = uap->envp;
-               needsenv = 0;
-               goto do_env_as_well;
+exec_fail:
+       if (iparams->vmspace_destroyed) {
+               /* sorry, no more process anymore. exit gracefully */
+#if 0  /* XXX */
+               vm_deallocate(&vs->vm_map, USRSTACK - MAXSSIZ, MAXSSIZ);
+#endif
+               kexit(p, W_EXITCODE(0, SIGABRT));
+               /* NOT REACHED */
+               return(0);
+       } else {
+               return(error);
        }
        }
-       /* At this point, one could optionally implement a
-        * second pass to condense the strings, arguement vectors,
-        * and stack to fit the fewest pages.
-        *
-        * One might selectively do this when copying was cheaper
-        * than leaving allocated two more pages per process.
-        */
+}
 
 
-       /* stuff arg count on top of "new" stack */
-       /* argbuf[-1] = (char *)argc;*/
-       suword(argbuf-1,argc);
+/*
+ * Destroy old address space, and allocate a new stack
+ *     The new stack is only DFLSSIZ large because it is grown
+ *     automatically in trap.c.
+ */
+int
+exec_new_vmspace(iparams)
+       struct image_params *iparams;
+{
+       int error;
+       struct vmspace *vmspace = iparams->proc->p_vmspace;
+       caddr_t stack_addr = (caddr_t) (USRSTACK - DFLSSIZ);
 
 
-       /*
-        * Step 4. Build the new processes image.
-        *
-        * At this point, we are committed -- destroy old executable!
-        */
+       iparams->vmspace_destroyed = 1;
 
 
-       /* blow away all address space, except the stack */
-       rv = vm_deallocate(&vs->vm_map, 0, USRSTACK - 2*MAXSSIZ);
-       if (rv)
-               goto exec_abort;
+       /* Blow away entire process VM */
+       vm_deallocate(&vmspace->vm_map, 0, USRSTACK);
 
 
-       /* destroy "old" stack */
-       if ((unsigned)newframe < USRSTACK - MAXSSIZ) {
-               rv = vm_deallocate(&vs->vm_map, USRSTACK - MAXSSIZ, MAXSSIZ);
-               if (rv)
-                       goto exec_abort;
-       } else {
-               rv = vm_deallocate(&vs->vm_map, USRSTACK - 2*MAXSSIZ, MAXSSIZ);
-               if (rv)
-                       goto exec_abort;
-       }
+       /* Allocate a new stack */
+       error = vm_allocate(&vmspace->vm_map, &stack_addr, DFLSSIZ, FALSE);
+       if (error)
+               return(error);
 
 
-       /* build a new address space */
+       /* Initialize maximum stack address */
+       vmspace->vm_maxsaddr = (char *)USRSTACK - MAXSSIZ;
 
 
+       return(0);
+}
 
 
+/*
+ * Copy out argument and environment strings from the old process
+ *     address space into the temporary string buffer.
+ */
+int
+exec_extract_strings(iparams)
+       struct image_params *iparams;
+{
+       char    **argv, **envv;
+       char    *argp, *envp;
+       int     length;
 
 
-       /* treat text, data, and bss in terms of integral page size */
-       tsize = roundup(exdata.ex_hdr.a_text, NBPG);
-       dsize = roundup(exdata.ex_hdr.a_data, NBPG);
-       bsize = roundup(exdata.ex_hdr.a_bss, NBPG);
+       /*
+        * extract arguments first
+        */
 
 
-       addr = virtual_offset;
+       argv = iparams->uap->argv; 
+
+       if (argv)
+               while (argp = (caddr_t) fuword(argv++)) {
+                       if (argp == (caddr_t) -1)
+                               return (EFAULT);
+                       if (copyinstr(argp, iparams->stringp, iparams->stringspace,
+                               &length) == ENAMETOOLONG)
+                                       return(E2BIG);
+                       iparams->stringspace -= length;
+                       iparams->stringp += length;
+                       iparams->argc++;
+               }
 
 
-       /* map text as being read/execute only and demand paged */
-       rv = vm_mmap(&vs->vm_map, &addr, tsize, VM_PROT_READ|VM_PROT_EXECUTE,
-               VM_PROT_DEFAULT, MAP_FILE|MAP_PRIVATE|MAP_FIXED,
-               (caddr_t)ndp->ni_vp, file_offset);
-       if (rv)
-               goto exec_abort;
+       /*
+        * extract environment strings
+        */
 
 
-       addr = virtual_offset + tsize;
+       envv = iparams->uap->envv; 
+
+       if (envv)
+               while (envp = (caddr_t) fuword(envv++)) {
+                       if (envp == (caddr_t) -1)
+                               return (EFAULT);
+                       if (copyinstr(envp, iparams->stringp, iparams->stringspace,
+                               &length) == ENAMETOOLONG)
+                                       return(E2BIG);
+                       iparams->stringspace -= length;
+                       iparams->stringp += length;
+                       iparams->envc++;
+               }
 
 
-       /* map data as being read/write and demand paged */
-       rv = vm_mmap(&vs->vm_map, &addr, dsize,
-               VM_PROT_READ | VM_PROT_WRITE | (tsize ? 0 : VM_PROT_EXECUTE),
-               VM_PROT_DEFAULT, MAP_FILE|MAP_PRIVATE|MAP_FIXED,
-               (caddr_t)ndp->ni_vp, file_offset + tsize);
-       if (rv)
-               goto exec_abort;
+       return (0);
+}
 
 
-       /* create anonymous memory region for bss */
-       addr = virtual_offset + tsize + dsize;
-       rv = vm_allocate(&vs->vm_map, &addr, bsize, FALSE);
-       if (rv)
-               goto exec_abort;
+/*
+ * Copy strings out to the new process address space, constructing
+ *     new arg and env vector tables. Return a pointer to the base
+ *     so that it can be used as the initial stack pointer.
+ */
+caddr_t
+exec_copyout_strings(iparams)
+       struct image_params *iparams;
+{
+       int argc, envc;
+       char **vectp;
+       char *stack_base, *stringp, *destp;
+       int vect_table_size, string_table_size;
 
        /*
 
        /*
-        * Step 5. Prepare process for execution.
+        * Calculate string base and vector table pointers.
+        */
+       destp = (caddr_t) ((caddr_t)USRSTACK -
+               roundup((ARG_MAX - iparams->stringspace), sizeof(char *)));
+       /*
+        * The '+ 2' is for the null pointers at the end of each of the
+        *      arg and env vector sets
         */
         */
+       vectp = (char **) (destp -
+               (iparams->argc + iparams->envc + 2) * sizeof(char *));
 
 
-       /* touchup process information -- vm system is unfinished! */
-       vs->vm_tsize = tsize/NBPG;              /* text size (pages) XXX */
-       vs->vm_dsize = (dsize+bsize)/NBPG;      /* data size (pages) XXX */
-       vs->vm_taddr = (caddr_t) virtual_offset; /* virtual address of text */
-       vs->vm_daddr = (caddr_t) virtual_offset + tsize; /* virtual address of data */
-       vs->vm_maxsaddr = newframe;     /* user VA at max stack growth XXX */
-       vs->vm_ssize =  ((unsigned)vs->vm_maxsaddr + MAXSSIZ
-               - (unsigned)argbuf)/ NBPG + 1; /* stack size (pages) */
-       dostacklimits = 1;      /* allow stack limits to be enforced XXX */
+       /*
+        * vectp also becomes our initial stack base
+        */
+       stack_base = (caddr_t)vectp;
 
 
-       /* close files on exec, fixup signals */
-       fdcloseexec(p);
-       execsigs(p);
+       stringp = iparams->stringbase;
+       argc = iparams->argc;
+       envc = iparams->envc;
 
 
-       /* name this process - nameiexec(p, ndp) */
-       len = MIN(ndp->ni_namelen,MAXCOMLEN);
-       bcopy(ndp->ni_ptr, p->p_comm, len);
-       p->p_comm[len] = 0;
-       
-       /* mark as executable, wakeup any process that was vforked and tell
-        * it that it now has it's own resources back */
-       p->p_flag |= SEXEC;
-       if (p->p_pptr && (p->p_flag & SPPWAIT)) {
-           p->p_flag &= ~SPPWAIT;
-           wakeup((caddr_t)p->p_pptr);
+       for (; argc > 0; --argc) {
+               *(vectp++) = destp;
+               while (*destp++ = *stringp++);
        }
        }
-       
-       /* implement set userid/groupid */
-       if ((attr.va_mode&VSUID) && (p->p_flag & STRC) == 0) {
-           p->p_ucred = crcopy(p->p_ucred);
-           p->p_cred->p_svuid = p->p_ucred->cr_uid = attr.va_uid;
-       }
-       if ((attr.va_mode&VSGID) && (p->p_flag & STRC) == 0) {
-           p->p_ucred = crcopy(p->p_ucred);
-           p->p_cred->p_svgid = p->p_ucred->cr_groups[0] = attr.va_gid;
+
+       /* a null vector table pointer seperates the argp's from the envp's */
+       *(vectp++) = NULL;
+
+       for (; envc > 0; --envc) {
+               *(vectp++) = destp;
+               while (*destp++ = *stringp++);
        }
 
        }
 
-       /* setup initial register state */
-       p->p_regs[SP] = (unsigned) (argbuf - 1);
-       setregs(p, exdata.ex_hdr.a_entry);
+       /* end of vector table is a null pointer */
+       *vectp = NULL;
 
 
-       ndp->ni_vp->v_flag |= VTEXT;            /* mark vnode pure text */
+       return (stack_base);
+}
 
 
-       vput(ndp->ni_vp);
-       FREE(ndp->ni_pnbuf, M_NAMEI);
+/*
+ * Check permissions of file to execute.
+ *     Return 0 for success or error code on failure.
+ */
+int
+exec_check_permissions(iparams)
+       struct image_params *iparams;
+{
+       struct proc *p = iparams->proc;
+       struct vnode *vnodep = iparams->vnodep;
+       struct vattr *attr = iparams->attr;
+       int error;
 
 
-       /* if tracing process, pass control back to debugger so breakpoints
-          can be set before the program "runs" */
-       if (p->p_flag & STRC)
-               psignal(p, SIGTRAP);
-       p->p_acflag &= ~AFORK;          /* remove fork, but no exec flag */
+       /*
+        * Check number of open-for-writes on the file and deny execution
+        *      if there are any.
+        */
+       if (vnodep->v_writecount) {
+               return (ETXTBSY);
+       }
 
 
-       return (0);
+       /* Get file attributes */
+       error = VOP_GETATTR(vnodep, attr, p->p_ucred, p);
+       if (error)
+               return (error);
 
 
-exec_dealloc:
-       /* remove interim "new" stack frame we were building */
-       vm_deallocate(&vs->vm_map, newframe, MAXSSIZ);
+       /*
+        * 1) Check if file execution is disabled for the filesystem that this
+        *      file resides on.
+        * 2) Insure that at least one execute bit is on - otherwise root
+        *      will always succeed, and we don't want to happen unless the
+        *      file really is executable.
+        * 3) Insure that the file is a regular file.
+        */
+       if ((vnodep->v_mount->mnt_flag & MNT_NOEXEC) ||
+           ((attr->va_mode & 0111) == 0) ||
+           (attr->va_type != VREG)) {
+               return (EACCES);
+       }
 
 
-exec_fail:
-       dostacklimits = 1;
-       vput(ndp->ni_vp);
-       FREE(ndp->ni_pnbuf, M_NAMEI);
+       /*
+        * Disable setuid/setgid if the filesystem prohibits it or if
+        *      the process is being traced.
+        */
+        if ((vnodep->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & STRC))
+               attr->va_mode &= ~(VSUID | VSGID);
 
 
-       return(rv);
+       /*
+        *  Check for execute permission to file based on current credentials.
+        *      Then call filesystem specific open routine (which does nothing
+        *      in the general case).
+        */
+       error = VOP_ACCESS(vnodep, VEXEC, p->p_ucred, p);
+       if (error)
+               return (error);
 
 
-exec_abort:
-       /* sorry, no more process anymore. exit gracefully */
-       vm_deallocate(&vs->vm_map, newframe, MAXSSIZ);
-       vput(ndp->ni_vp);
-       FREE(ndp->ni_pnbuf, M_NAMEI);
-       kexit(p, W_EXITCODE(0, SIGABRT));
+       error = VOP_OPEN(vnodep, FREAD, p->p_ucred, p);
+       if (error)
+               return (error);
 
 
-       /* NOTREACHED */
-       return(0);
+       return (0);
 }
 }
diff --git a/sys/kern/shell_imgact.c b/sys/kern/shell_imgact.c
new file mode 100644 (file)
index 0000000..356c943
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 1993, David Greenman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by David Greenman
+ * 4. The name of the developer may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $Id: shell_imgact.c,v 1.3 1993/12/11 06:55:33 davidg Exp davidg $
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "resourcevar.h"
+#include "imgact.h"
+
+#define SHELLMAGIC     0x2123 /* #! */
+#define MAXSHELLCMDLEN 64
+
+/*
+ * Shell interpreter image activator. A interpreter name beginning
+ *     at iparams->stringbase is the minimal successful exit requirement.
+ */
+int
+exec_shell_imgact(iparams)
+       struct image_params *iparams;
+{
+       const char *image_header = iparams->image_header;
+       const char *ihp, *line_endp;
+       int length;
+       char *interp;
+       char **argv;
+
+       /* a shell script? */
+       if (((short *) image_header)[0] != SHELLMAGIC)
+               return(-1);
+
+       /*
+        * Don't allow a shell script to be the shell for a shell
+        *      script. :-)
+        */
+       if (iparams->interpreted)
+               return(ENOEXEC);
+
+       iparams->interpreted = 1;
+
+       /*
+        * Copy shell name and arguments from image_header into string
+        *      buffer.
+        */
+
+       /*
+        * Find end of line; return if the line > MAXSHELLCMDLEN long.
+        */
+       for (ihp = &image_header[2]; *ihp != '\n'; ++ihp) {
+               if (ihp >= &image_header[MAXSHELLCMDLEN])
+                       return(ENOEXEC);
+       }
+       line_endp = ihp;
+
+       /* reset for another pass */
+       ihp = &image_header[2];
+
+       /* Skip over leading spaces - until the interpreter name */
+       while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
+
+       /* copy the interpreter name */
+       interp = iparams->interpreter_name;
+       while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t'))
+               *interp++ = *ihp++;
+       *interp = '\0';
+
+       /* Disallow a null interpreter filename */
+       if (*iparams->interpreter_name == '\0')
+               return(ENOEXEC);
+
+       /* reset for another pass */
+       ihp = &image_header[2];
+
+       /* copy the interpreter name and arguments */
+       while (ihp < line_endp) {
+               /* Skip over leading spaces */
+               while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
+
+               if (ihp < line_endp) {
+                       /*
+                        * Copy to end of token. No need to watch stringspace
+                        *      because this is at the front of the string buffer
+                        *      and the maximum shell command length is tiny.
+                        */
+                       while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) {
+                               *iparams->stringp++ = *ihp++;
+                               iparams->stringspace--;
+                       }
+
+                       *iparams->stringp++ = 0;
+                       iparams->stringspace--;
+
+                       iparams->argc++;
+               }
+       }
+
+       /* set argv[0] to point to original file name */
+       suword(iparams->uap->argv, (int)iparams->uap->fname);
+
+       return(0);
+}
index 89e76e9..a4dd98c 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)subr_mcount.c 7.10 (Berkeley) 5/7/91
  * SUCH DAMAGE.
  *
  *     from: @(#)subr_mcount.c 7.10 (Berkeley) 5/7/91
- *     $Id$
+ *     $Id: subr_mcount.c,v 1.3 1993/10/16 15:24:41 rgrimes Exp $
  */
 
 #ifdef GPROF
  */
 
 #ifdef GPROF
@@ -167,9 +167,6 @@ mcount()
        asm("   movl (sp), r11");       /* selfpc = ... (jsb frame) */
        asm("   movl 16(fp), r10");     /* frompcindex =     (calls frame) */
 #endif
        asm("   movl (sp), r11");       /* selfpc = ... (jsb frame) */
        asm("   movl 16(fp), r10");     /* frompcindex =     (calls frame) */
 #endif
-#if defined(i386)
-       Fix Me!!
-#endif /* i386 */
 #if defined(tahoe)
        asm("   movl -8(fp),r12");      /* selfpc = callf frame */
        asm("   movl (fp),r11");
 #if defined(tahoe)
        asm("   movl -8(fp),r12");      /* selfpc = callf frame */
        asm("   movl (fp),r11");
@@ -188,8 +185,12 @@ mcount()
 #if defined(hp300)
        asm("movw       sr,%0" : "=g" (s));
        asm("movw       #0x2700,sr");
 #if defined(hp300)
        asm("movw       sr,%0" : "=g" (s));
        asm("movw       #0x2700,sr");
+#else
+#if defined(i386)
+       asm("cli");
 #else
        s = splhigh();
 #else
        s = splhigh();
+#endif
 #endif
        /*
         * Check that frompcindex is a reasonable pc value.
 #endif
        /*
         * Check that frompcindex is a reasonable pc value.
@@ -270,8 +271,12 @@ mcount()
 done:
 #if defined(hp300)
        asm("movw       %0,sr" : : "g" (s));
 done:
 #if defined(hp300)
        asm("movw       %0,sr" : : "g" (s));
+#else
+#if defined(i386)
+       asm("sti");
 #else
        splx(s);
 #else
        splx(s);
+#endif
 #endif
        /* and fall through */
 out:
 #endif
        /* and fall through */
 out:
index abbe629..01b3815 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vfs_conf.c    7.3 (Berkeley) 6/28/90
  * SUCH DAMAGE.
  *
  *     from: @(#)vfs_conf.c    7.3 (Berkeley) 6/28/90
- *     $Id$
+ *     $Id: vfs_conf.c,v 1.2 1993/10/16 15:25:21 rgrimes Exp $
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -72,6 +72,10 @@ extern       struct vfsops pcfs_vfsops;
 extern struct vfsops isofs_vfsops;
 #endif
 
 extern struct vfsops isofs_vfsops;
 #endif
 
+#ifdef PROCFS
+extern struct vfsops procfs_vfsops;
+#endif
+
 struct vfsops *vfssw[] = {
        (struct vfsops *)0,     /* 0 = MOUNT_NONE */
        &ufs_vfsops,            /* 1 = MOUNT_UFS */
 struct vfsops *vfssw[] = {
        (struct vfsops *)0,     /* 0 = MOUNT_NONE */
        &ufs_vfsops,            /* 1 = MOUNT_UFS */
@@ -95,4 +99,9 @@ struct vfsops *vfssw[] = {
 #else
        (struct vfsops *)0,
 #endif
 #else
        (struct vfsops *)0,
 #endif
+#ifdef PROCFS
+       &procfs_vfsops,         /* 6 = MOUNT_PROCFS */
+#else
+       (struct vfsops *)0,
+#endif
 };
 };
index e58bf3e..e0127bc 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vfs_vnops.c   7.33 (Berkeley) 6/27/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vfs_vnops.c   7.33 (Berkeley) 6/27/91
- *     $Id: vfs_vnops.c,v 1.2 1993/10/16 15:25:29 rgrimes Exp $
+ *     $Id: vfs_vnops.c,v 1.3 1993/11/25 01:33:45 wollman Exp $
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -307,6 +307,7 @@ vn_stat(vp, sb, p)
        mode = vap->va_mode;
        switch (vp->v_type) {
        case VREG:
        mode = vap->va_mode;
        switch (vp->v_type) {
        case VREG:
+       case VPROC:
                mode |= S_IFREG;
                break;
        case VDIR:
                mode |= S_IFREG;
                break;
        case VDIR:
diff --git a/sys/procfs/pfsnode.h b/sys/procfs/pfsnode.h
new file mode 100644 (file)
index 0000000..e8fd84b
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     $Id: pfsnode.h,v 1.6 1993/09/07 15:41:24 ws Exp $
+ */
+
+/*
+ * This structure defines the control data for the proc file system.
+ */
+
+struct pfsnode {
+       struct  pfsnode *pfs_next;      /* next on list */
+       struct  vnode   *pfs_vnode;     /* vnode associated with this pfsnode */
+       pid_t   pfs_pid;                /* associated process */
+       u_short pfs_mode;               /* mode bits for stat() */
+       uid_t   pfs_uid;                /* process' owner */
+       gid_t   pfs_gid;                /* process' group */
+       u_long  pfs_vflags;             /* chflags() flags */
+       u_long  pfs_flags;              /* open flags */
+       struct  vmspace *pfs_vs;
+};
+
+struct pfsnode *pfshead;
+
+/*
+ * Format of a directory entry in /proc
+ */
+struct pfsdent {
+       unsigned long   d_fileno;
+       unsigned short  d_reclen;
+       unsigned short  d_namlen;
+       char            d_nam[8];
+};
+#define PFSDENTSIZE    (sizeof(struct direct) - MAXNAMELEN + 8)
+
+#ifndef DIRBLKSIZ
+#define DIRBLKSIZ      DEV_BSIZE
+#endif
+
+#ifdef DEBUG
+int pfs_debug;
+#endif
+
+/*
+ * Convert between pfsnode pointers and vnode pointers
+ */
+#define VTOPFS(vp)     ((struct pfsnode *)(vp)->v_data)
+#define PFSTOV(pfsp)   ((pfsp)->pfs_vnode)
+
+/*
+ * Prototypes for PFS operations on vnodes.
+ */
+int    pfs_badop();
+int    pfs_doio();
+int    pfs_lookup __P(( \
+               struct vnode *vp, \
+               struct nameidata *ndp, \
+               struct proc *p));
+#define pfs_create ((int (*) __P(( \
+               struct nameidata *ndp, \
+               struct vattr *vap, \
+               struct proc *p))) pfs_badop)
+#define pfs_mknod ((int (*) __P(( \
+               struct nameidata *ndp, \
+               struct vattr *vap, \
+               struct ucred *cred, \
+               struct proc *p))) pfs_badop)
+int    pfs_open __P((
+               struct vnode *vp,
+               int mode,
+               struct ucred *cred,
+               struct proc *p));
+int    pfs_close __P((
+               struct vnode *vp,
+               int fflag,
+               struct ucred *cred,
+               struct proc *p));
+int    pfs_access __P((
+               struct vnode *vp,
+               int mode,
+               struct ucred *cred,
+               struct proc *p));
+int    pfs_getattr __P((
+               struct vnode *vp,
+               struct vattr *vap,
+               struct ucred *cred,
+               struct proc *p));
+int    pfs_setattr __P((
+               struct vnode *vp,
+               struct vattr *vap,
+               struct ucred *cred,
+               struct proc *p));
+#define        pfs_read ((int (*)  __P(( \
+               struct vnode *vp, \
+               struct uio *uio, \
+               int ioflag, \
+               struct ucred *cred))) pfs_doio)
+#define        pfs_write ((int (*) __P(( \
+               struct vnode *vp, \
+               struct uio *uio, \
+               int ioflag, \
+               struct ucred *cred))) pfs_doio)
+int    pfs_ioctl __P((
+               struct vnode *vp,
+               int command,
+               caddr_t data,
+               int fflag,
+               struct ucred *cred,
+               struct proc *p));
+#define pfs_select ((int (*) __P(( \
+               struct vnode *vp, \
+               int which, \
+               int fflags, \
+               struct ucred *cred, \
+               struct proc *p))) pfs_badop)
+#define pfs_mmap ((int (*) __P(( \
+               struct vnode *vp, \
+               int fflags, \
+               struct ucred *cred, \
+               struct proc *p))) pfs_badop)
+#define pfs_fsync ((int (*) __P(( \
+               struct vnode *vp, \
+               int fflags, \
+               struct ucred *cred, \
+               int waitfor, \
+               struct proc *p))) pfs_badop)
+#define pfs_seek ((int (*) __P(( \
+               struct vnode *vp, \
+               off_t oldoff, \
+               off_t newoff, \
+               struct ucred *cred))) pfs_badop)
+#define pfs_remove ((int (*) __P(( \
+               struct nameidata *ndp, \
+               struct proc *p))) pfs_badop)
+#define pfs_link ((int (*) __P(( \
+               struct vnode *vp, \
+               struct nameidata *ndp, \
+               struct proc *p))) pfs_badop)
+#define pfs_rename ((int (*) __P(( \
+               struct nameidata *fndp, \
+               struct nameidata *tdnp, \
+               struct proc *p))) pfs_badop)
+#define pfs_mkdir ((int (*) __P(( \
+               struct nameidata *ndp, \
+               struct vattr *vap, \
+               struct proc *p))) pfs_badop)
+#define pfs_rmdir ((int (*) __P(( \
+               struct nameidata *ndp, \
+               struct proc *p))) pfs_badop)
+#define pfs_symlink ((int (*) __P(( \
+               struct nameidata *ndp, \
+               struct vattr *vap, \
+               char *target, \
+               struct proc *p))) pfs_badop)
+int    pfs_readdir __P((
+               struct vnode *vp,
+               struct uio *uio,
+               struct ucred *cred,
+               int *eofflagp));
+#define pfs_readlink ((int (*) __P(( \
+               struct vnode *vp, \
+               struct uio *uio, \
+               struct ucred *cred))) pfs_badop)
+#define pfs_abortop ((int (*) __P(( \
+               struct nameidata *ndp))) pfs_badop)
+int    pfs_inactive __P((
+               struct vnode *vp,
+               struct proc *p));
+int    pfs_reclaim __P((
+               struct vnode *vp));
+#define pfs_lock ((int (*) __P(( \
+               struct vnode *vp))) nullop)
+#define pfs_unlock ((int (*) __P(( \
+               struct vnode *vp))) nullop)
+int    pfs_bmap __P((
+               struct vnode *vp,
+               daddr_t bn,
+               struct vnode **vpp,
+               daddr_t *bnp));
+int    pfs_strategy __P((
+               struct buf *bp));
+void   pfs_print __P((
+               struct vnode *vp));
+#define pfs_islocked ((int (*) __P(( \
+               struct vnode *vp))) nullop)
+#define pfs_advlock ((int (*) __P(( \
+               struct vnode *vp, \
+               caddr_t id, \
+               int op, \
+               struct flock *fl, \
+               int flags))) pfs_badop)
diff --git a/sys/procfs/procfs_subr.c b/sys/procfs/procfs_subr.c
new file mode 100644 (file)
index 0000000..5a8af99
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     $Id: procfs_subr.c,v 1.3 1993/08/24 16:47:24 pk Exp $
+ */
+#include "param.h"
+#include "systm.h"
+#include "time.h"
+#include "kernel.h"
+#include "ioctl.h"
+#include "proc.h"
+#include "buf.h"
+#include "vnode.h"
+#include "file.h"
+#include "resourcevar.h"
+#include "vm/vm.h"
+#include "vm/vm_page.h"
+#include "vm/vm_kern.h"
+#include "kinfo.h"
+#include "kinfo_proc.h"
+#include "machine/pmap.h"
+
+#include "procfs.h"
+#include "pfsnode.h"
+
+#include "machine/vmparam.h"
+
+/*
+ * Get process address map (PIOCGMAP)
+ */
+int
+pfs_vmmap(procp, pfsp, pmapp)
+struct proc    *procp;
+struct nfsnode *pfsp;
+struct procmap *pmapp;
+{
+       int             error = 0;
+       vm_map_t        map;
+       vm_map_entry_t  entry;
+       struct procmap  prmap;
+
+       map = &procp->p_vmspace->vm_map;
+       vm_map_lock(map);
+       entry = map->header.next;
+
+       while (entry != &map->header) {
+               if (entry->is_a_map) {
+                       vm_map_t        submap = entry->object.share_map;
+                       vm_map_entry_t  subentry;
+
+                       vm_map_lock(submap);
+                       subentry = submap->header.next;
+                       while (subentry != &submap->header) {
+                               prmap.vaddr = subentry->start;
+                               prmap.size = subentry->end - subentry->start;
+                               prmap.offset = subentry->offset;
+                               prmap.prot = subentry->protection;
+                               error = copyout(&prmap, pmapp, sizeof(prmap));
+                               if (error)
+                                       break;
+                               pmapp++;
+                               subentry = subentry->next;
+                       }
+                       vm_map_unlock(submap);
+                       if (error)
+                               break;
+               }
+               prmap.vaddr = entry->start;
+               prmap.size = entry->end - entry->start;
+               prmap.offset = entry->offset;
+               prmap.prot = entry->protection;
+               error = copyout(&prmap, pmapp, sizeof(prmap));
+               if (error)
+                       break;
+               pmapp++;
+               entry = entry->next;
+       }
+
+       vm_map_unlock(map);
+       return error;
+}
+
+/*
+ * Count number of VM entries of process (PIOCNMAP)
+ */
+int
+pfs_vm_nentries(procp, pfsp)
+struct proc    *procp;
+struct nfsnode *pfsp;
+{
+       int             count = 0;
+       vm_map_t        map;
+       vm_map_entry_t  entry;
+
+       map = &procp->p_vmspace->vm_map;
+       vm_map_lock(map);
+       entry = map->header.next;
+
+       while (entry != &map->header) {
+               if (entry->is_a_map)
+                       count += entry->object.share_map->nentries;
+               else
+                       count++;
+               entry = entry->next;
+       }
+
+       vm_map_unlock(map);
+       return count;
+}
+
+/*
+ * Map process mapped file to file descriptor (PIOCGMAPFD)
+ */
+int
+pfs_vmfd(procp, pfsp, vmfdp, p)
+struct proc    *procp;
+struct pfsnode *pfsp;
+struct vmfd    *vmfdp;
+struct proc    *p;
+{
+       int             rv;
+       vm_map_t        map;
+       vm_offset_t     addr;
+       vm_size_t       size;
+       vm_prot_t       prot, maxprot;
+       vm_inherit_t    inherit;
+       boolean_t       shared;
+       vm_object_t     object;
+       vm_offset_t     objoff;
+       struct vnode    *vp;
+       struct file     *fp;
+       extern struct fileops   vnops;
+
+       map = &procp->p_vmspace->vm_map;
+
+       addr = vmfdp->vaddr;
+       rv = vm_region(map, &addr, &size, &prot, &maxprot,
+                       &inherit, &shared, &object, &objoff);
+
+       if (rv != KERN_SUCCESS)
+               return EINVAL;
+
+       while (object != NULL && object->pager == NULL)
+               object = object->shadow;
+
+       if (object == NULL || object->pager == NULL
+                       /* Nobody seems to care || !object->pager_ready */ )
+               return ENOENT;
+
+       if (object->pager->pg_type != PG_VNODE)
+               return ENOENT;
+
+       /* We have a vnode pager, allocate file descriptor */
+       vp = (struct vnode *)object->pager->pg_handle;
+       if (VOP_ACCESS(vp, VREAD, p->p_ucred, p)) {
+               rv = EACCES;
+               goto out;
+       }
+       rv = falloc(p, &fp, &vmfdp->fd);
+       if (rv)
+               goto out;
+
+       VREF(vp);
+       fp->f_type = DTYPE_VNODE;
+       fp->f_ops = &vnops;
+       fp->f_data = (caddr_t)vp;
+       fp->f_flag = FREAD;
+
+out:
+       vm_object_unlock(object);
+       return rv;
+}
+
+
+/*
+ * Vnode op for reading/writing.
+ */
+/* ARGSUSED */
+int
+pfs_doio(vp, uio, ioflag, cred)
+       struct vnode *vp;
+       register struct uio *uio;
+       int ioflag;
+       struct ucred *cred;
+{
+       struct pfsnode  *pfsp = VTOPFS(vp);
+       struct proc     *procp;
+       int             error = 0;
+       long            n, on;
+       vm_offset_t     kva, kbuf;
+       int             pflag;
+
+#ifdef DEBUG
+       if (pfs_debug)
+               printf("pfs_doio(%s): vp 0x%x, proc %x, offset %d\n",
+                       uio->uio_rw==UIO_READ?"R":"W", vp, uio->uio_procp, uio->uio_offset);
+#endif
+
+#ifdef DIAGNOSTIC
+       if (vp->v_type != VPROC)
+               panic("pfs_doio vtype");
+#endif
+       procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
+       if (!procp)
+               return ESRCH;
+
+       if (procp->p_flag & SSYS)
+               return EACCES;
+
+       if (uio->uio_resid == 0) {
+               return (0);
+       }
+       /* allocate a bounce buffer */
+       /* notice that this bounce buffer bogosity is due to
+          a problem with wiring/unwiring procs pages, so
+          rather than wire the destination procs data pages
+          I used a kernel bounce buffer
+       */
+       kbuf = kmem_alloc(kernel_map, NBPG); 
+       if( !kbuf)
+               return ENOMEM;
+
+       /* allocate a kva */
+       kva = kmem_alloc_pageable(kernel_map, NBPG);
+       if( !kva) {
+               kmem_free(kernel_map, kbuf, NBPG);
+               return ENOMEM;
+       }
+
+       pflag = procp->p_flag & SKEEP;
+       procp->p_flag |= SKEEP;
+
+       do { /* One page at a time */
+               int             rv;
+               vm_map_t        map;
+               vm_offset_t     offset, v, pa;
+               vm_prot_t       oldprot = 0, prot, maxprot;
+               vm_inherit_t    inherit;
+               boolean_t       shared;
+               vm_object_t     object;
+               vm_offset_t     objoff;
+               vm_page_t       m;
+               vm_offset_t     size;
+               int s;
+
+
+               on = uio->uio_offset - trunc_page(uio->uio_offset);
+               n = MIN(NBPG-on, uio->uio_resid);
+
+               /* Map page into kernel space */
+
+               /* printf("rw: offset: %d, n: %d, resid: %d\n", 
+                       uio->uio_offset, n, uio->uio_resid); */
+#ifdef FULLSWAP
+               if (procp->p_vmspace != pfsp->pfs_vs) {
+                       error = EFAULT;
+                       break;
+               }
+#endif
+
+               map = &procp->p_vmspace->vm_map;
+
+               offset = trunc_page((vm_offset_t)uio->uio_offset);
+
+#ifndef FULLSWAP
+               if( offset >= USRSTACK) {
+                       error = EINVAL;
+                       break;
+               }
+#endif
+               
+
+               /* make sure that the offset exists in the procs map */
+               rv = vm_region(map, &offset, &size, &prot, &maxprot,
+                               &inherit, &shared, &object, &objoff);
+               if (rv != KERN_SUCCESS) {
+                       error = EINVAL;
+                       break;
+               }
+
+
+               /* change protections if need be */
+               if (uio->uio_rw == UIO_WRITE && (prot & VM_PROT_WRITE) == 0) {
+                       oldprot = prot;
+                       prot |= VM_PROT_WRITE;
+                       rv = vm_protect(map, offset, NBPG, FALSE, prot);
+                       if (rv != KERN_SUCCESS) {
+                               error = EPERM;
+                               break;
+                       }
+               } 
+
+               if( uio->uio_rw != UIO_WRITE) {
+                       prot &= ~VM_PROT_WRITE;
+               }
+
+               /* check for stack area -- don't fault in unused pages */
+               if( (caddr_t) offset >= procp->p_vmspace->vm_maxsaddr &&
+                       offset < USRSTACK) {
+                       if( (caddr_t) offset <
+                               ((procp->p_vmspace->vm_maxsaddr + MAXSSIZ) - ctob( procp->p_vmspace->vm_ssize))) {
+                               error = EFAULT;
+                               goto reprot;
+                       }
+                       if( (caddr_t) offset >=
+                               ((procp->p_vmspace->vm_maxsaddr + MAXSSIZ))) {
+                               error = EFAULT;
+                               goto reprot;
+                       }
+               }
+
+               /* wire the page table page */
+               v = trunc_page(((vm_offset_t)vtopte( offset)));
+               vm_map_pageable(map, v, round_page(v+1), FALSE);
+
+               if( uio->uio_rw == UIO_READ) {
+                       /* Now just fault the page table and the page */
+                       rv = vm_fault(map, offset, VM_PROT_READ, FALSE);
+
+                       if (rv != KERN_SUCCESS) {
+                               procp->p_flag = (procp->p_flag & ~SKEEP) | pflag;
+                               vm_map_pageable(map, v, round_page(v+1), TRUE);
+                               error = EFAULT;
+                               goto reprot;
+                       }
+
+
+                       /* get the physical address of the page */
+                       pa = pmap_extract( vm_map_pmap(map), offset);
+
+                       if( !pa) {
+                               printf("pfs: cannot get pa -- read\n");
+                       } else {
+                               /* enter the physical address into the kernel pmap */
+                               pmap_enter(vm_map_pmap(kernel_map), kva, pa, prot, TRUE);
+                               /* copy the data */
+                               bcopy( (caddr_t)kva, (caddr_t)kbuf, NBPG);
+                               /* remove the physical address from the kernel pmap */
+                               pmap_remove(vm_map_pmap(kernel_map), kva, round_page(kva + 1));
+                       }
+               }
+
+               error = uiomove(kbuf + on, (int)n, uio);
+
+               if( !error && uio->uio_rw == UIO_WRITE) {
+                       /* Now just fault the page table and the page */
+                       rv = vm_fault(map, offset, VM_PROT_READ|VM_PROT_WRITE, FALSE);
+
+                       if (rv != KERN_SUCCESS) {
+                               procp->p_flag = (procp->p_flag & ~SKEEP) | pflag;
+                               vm_map_pageable(map, v, round_page(v+1), TRUE);
+                               error = EFAULT;
+                               goto reprot;
+                       }
+
+                       /* get the physical address of the page */
+                       pa = pmap_extract( vm_map_pmap(map), offset);
+                       
+                       if( !pa) {
+                               printf("pfs: cannot get pa -- write\n");
+                       } else {
+                               /* enter the physical address into the kernel pmap */
+                               pmap_enter(vm_map_pmap(kernel_map), kva, pa, prot, TRUE);
+                               /* copy the data */
+                               bcopy( (caddr_t)kbuf, (caddr_t)kva + on, n);
+                               /* remove the physical address from the kernel pmap */
+                               pmap_remove(vm_map_pmap(kernel_map), kva, round_page(kva + 1));
+                       }
+               }
+
+               /* unwire the page table page */
+               vm_map_pageable(map, v, round_page(v+1), TRUE);
+
+       reprot:
+
+               if (oldprot) {
+                       rv = vm_protect(map, offset, NBPG, FALSE, oldprot);
+                       if (rv != KERN_SUCCESS && error == 0) {
+                               error = EPERM;
+                               break;
+                       }
+               }
+
+       } while (error == 0 && uio->uio_resid > 0);
+
+       procp->p_flag = (procp->p_flag & ~SKEEP) | pflag;
+/* free the kva and bounce buffer */
+       kmem_free_wakeup(kernel_map, kva, NBPG);
+       kmem_free(kernel_map, kbuf, NBPG);
+
+       return (error);
+}
+
diff --git a/sys/procfs/procfs_vfsops.c b/sys/procfs/procfs_vfsops.c
new file mode 100644 (file)
index 0000000..3ee8a8e
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     $Id: procfs_vfsops.c,v 1.7 1993/08/26 19:01:01 pk Exp $
+ */
+
+/*
+ * PROCFS VFS interface routines
+ */
+
+#include "param.h"
+#include "time.h"
+#include "kernel.h"
+#include "proc.h"
+#include "buf.h"
+#include "mount.h"
+#include "signalvar.h"
+#include "vnode.h"
+
+#include "pfsnode.h"
+
+extern struct vnodeops pfs_vnodeops;
+
+/*
+ * mfs vfs operations.
+ */
+int pfs_mount();
+int pfs_start();
+int pfs_unmount();
+int pfs_root();
+int pfs_quotactl();
+int pfs_statfs();
+int pfs_sync();
+int pfs_fhtovp();
+int pfs_vptofh();
+void pfs_init();
+
+struct vfsops procfs_vfsops = {
+       pfs_mount,
+       pfs_start,
+       pfs_unmount,
+       pfs_root,
+       pfs_quotactl,
+       pfs_statfs,
+       pfs_sync,
+       pfs_fhtovp,
+       pfs_vptofh,
+       pfs_init,
+};
+
+/*
+ * VFS Operations.
+ *
+ * mount system call
+ */
+/* ARGSUSED */
+int
+pfs_mount(mp, path, data, ndp, p)
+       register struct mount *mp;
+       char *path;
+       caddr_t data;
+       struct nameidata *ndp;
+       struct proc *p;
+{
+#if 0
+       struct pfs_args args;
+#endif
+       struct vnode *pvp;
+       u_int size;
+       int error;
+
+       if (mp->mnt_flag & MNT_UPDATE) {
+               return (0);
+       }
+
+#if 0
+       if (error = copyin(data, (caddr_t)&args, sizeof (struct pfs_args)))
+               return (error);
+#endif
+       (void) copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname, MNAMELEN, &size);
+       bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
+
+       size = sizeof("proc") - 1;
+       bcopy("proc", mp->mnt_stat.f_mntfromname, size);
+       bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+
+       (void) pfs_statfs(mp, &mp->mnt_stat, p);
+       return (0);
+}
+
+/*
+ * unmount system call
+ */
+int
+pfs_unmount(mp, mntflags, p)
+       struct mount *mp;
+       int mntflags;
+       struct proc *p;
+{
+       return (0);
+}
+
+#if 0
+int
+pfs_root(mp, vpp)
+       struct mount *mp;
+       struct vnode **vpp;
+{
+       struct vnode *vp;
+       struct pfsnode *pfsp, **pp;
+       int error;
+
+       /* Look in "cache" first */
+       for (pfsp = pfshead; pfsp != NULL; pfsp = pfsp->pfs_next) {
+               if (pfsp->pfs_vnode->v_flag & VROOT) {
+                       *vpp = pfsp->pfs_vnode;
+                       vref(*vpp);
+                       return 0;
+               }
+       }
+
+       /* Not on list, allocate new vnode */
+       error = getnewvnode(VT_PROCFS, mp, &pfs_vnodeops, &vp);
+       if (error)
+               return error;
+
+       vp->v_type = VDIR;
+       vp->v_flag = VROOT;
+       pfsp = VTOPFS(vp);
+       pfsp->pfs_next = NULL;
+       pfsp->pfs_pid = 0;
+       pfsp->pfs_vnode = vp;
+       pfsp->pfs_flags = 0;
+       pfsp->pfs_vflags = 0;
+       pfsp->pfs_uid = 0;
+       pfsp->pfs_gid = 0;
+       pfsp->pfs_mode = 0755;  /* /proc = drwxr-xr-x */
+
+       /* Append to pfs node list */
+
+       pfsp->pfs_next = pfshead;
+       pfshead = pfsp;
+
+       *vpp = vp;
+       return 0;
+}
+#endif
+
+
+int
+pfs_root(mp, vpp)
+       struct mount *mp;
+       struct vnode **vpp;
+{
+       struct vnode *vp;
+       struct pfsnode *pfsp;
+       int error;
+
+       error = getnewvnode(VT_PROCFS, mp, &pfs_vnodeops, &vp);
+       if (error)
+               return error;
+
+       vp->v_type = VDIR;
+       vp->v_flag = VROOT;
+       pfsp = VTOPFS(vp);
+       pfsp->pfs_vnode = vp;
+       pfsp->pfs_pid = 0;
+       pfsp->pfs_pid = 0;
+       pfsp->pfs_flags = 0;
+       pfsp->pfs_vflags = 0;
+       pfsp->pfs_uid = 0;
+       pfsp->pfs_gid = 0;
+       pfsp->pfs_mode = 0755;  /* /proc = drwxr-xr-x */
+
+       *vpp = vp;
+       return 0;
+}
+
+/*
+ */
+/* ARGSUSED */
+int
+pfs_start(mp, flags, p)
+       struct mount *mp;
+       int flags;
+       struct proc *p;
+{
+       return 0;
+}
+
+/*
+ * Get file system statistics.
+ */
+int
+pfs_statfs(mp, sbp, p)
+       struct mount *mp;
+       struct statfs *sbp;
+       struct proc *p;
+{
+
+       sbp->f_type = MOUNT_PROCFS;
+       sbp->f_fsize = 512;
+       sbp->f_bsize = NBPG;
+       sbp->f_blocks = maxproc;
+       sbp->f_bfree = maxproc - nprocs;
+       sbp->f_bavail = sbp->f_bfree;
+       sbp->f_files =  maxproc; /* plus . and .. */
+       sbp->f_ffree = maxproc - nprocs;
+
+       return 0;
+}
+
+
+int
+pfs_quotactl(mp, cmds, uid, arg, p)
+       struct mount *mp;
+       int cmds;
+       uid_t uid;
+       caddr_t arg;
+       struct proc *p;
+{
+       return EOPNOTSUPP;
+}
+
+int
+pfs_sync(mp, waitfor)
+       struct mount *mp;
+       int waitfor;
+{
+       return 0;
+}
+
+int
+pfs_fhtovp(mp, fhp, vpp)
+       register struct mount *mp;
+       struct fid *fhp;
+       struct vnode **vpp;
+{
+       return EINVAL;
+}
+
+int
+pfs_vptofh(vp, fhp)
+       struct vnode *vp;
+       struct fid *fhp;
+{
+       return EINVAL;
+}
+
+void
+pfs_init()
+{
+       return;
+}
diff --git a/sys/procfs/procfs_vnops.c b/sys/procfs/procfs_vnops.c
new file mode 100644 (file)
index 0000000..8834a51
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     $Id: procfs_vnops.c,v 1.7 1993/09/16 22:08:30 cgd Exp $
+ */
+
+/*
+ * PROCFS vnode interface routines
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "time.h"
+#include "kernel.h"
+#include "ioctl.h"
+#include "file.h"
+#include "proc.h"
+#include "buf.h"
+#include "vnode.h"
+#include "namei.h"
+#include "resourcevar.h"
+#include "vm/vm.h"
+#include "kinfo.h"
+#include "kinfo_proc.h"
+
+#include "procfs.h"
+#include "pfsnode.h"
+
+#include "machine/vmparam.h"
+
+/*
+ * procfs vnode operations.
+ */
+struct vnodeops pfs_vnodeops = {
+       pfs_lookup,             /* lookup */
+       pfs_create,             /* create */
+       pfs_mknod,              /* mknod */
+       pfs_open,               /* open */
+       pfs_close,              /* close */
+       pfs_access,             /* access */
+       pfs_getattr,            /* getattr */
+       pfs_setattr,            /* setattr */
+       pfs_read,               /* read */
+       pfs_write,              /* write */
+       pfs_ioctl,              /* ioctl */
+       pfs_select,             /* select */
+       pfs_mmap,               /* mmap */
+       pfs_fsync,              /* fsync */
+       pfs_seek,               /* seek */
+       pfs_remove,             /* remove */
+       pfs_link,               /* link */
+       pfs_rename,             /* rename */
+       pfs_mkdir,              /* mkdir */
+       pfs_rmdir,              /* rmdir */
+       pfs_symlink,            /* symlink */
+       pfs_readdir,            /* readdir */
+       pfs_readlink,           /* readlink */
+       pfs_abortop,            /* abortop */
+       pfs_inactive,           /* inactive */
+       pfs_reclaim,            /* reclaim */
+       pfs_lock,               /* lock */
+       pfs_unlock,             /* unlock */
+       pfs_bmap,               /* bmap */
+       pfs_strategy,           /* strategy */
+       pfs_print,              /* print */
+       pfs_islocked,           /* islocked */
+       pfs_advlock,            /* advlock */
+};
+
+/*
+ * Vnode Operations.
+ *
+ */
+/* ARGSUSED */
+int
+pfs_open(vp, mode, cred, p)
+       register struct vnode *vp;
+       int mode;
+       struct ucred *cred;
+       struct proc *p;
+{
+       struct pfsnode  *pfsp = VTOPFS(vp);
+       struct proc *procp;
+
+#ifdef DEBUG
+       if (pfs_debug)
+               printf("pfs_open: vp 0x%x, proc %d\n", vp, p->p_pid);
+#endif
+
+       if ( (procp = (pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0)) == NULL)
+               return ESRCH;
+
+       if (    (pfsp->pfs_flags & FWRITE) && (mode & O_EXCL) ||
+               (pfsp->pfs_flags & O_EXCL) && (mode & FWRITE)   )
+               return EBUSY;
+
+
+       if (mode & FWRITE)
+               pfsp->pfs_flags = (mode & (FWRITE|O_EXCL));
+
+#ifdef FULLSWAP
+       procp->p_vmspace->vm_refcnt++;
+       pfsp->pfs_vs = procp->p_vmspace;
+#endif
+       return 0;
+}
+
+/*
+ * /proc filesystem close routine
+ */
+/* ARGSUSED */
+int
+pfs_close(vp, flag, cred, p)
+       register struct vnode *vp;
+       int flag;
+       struct ucred *cred;
+       struct proc *p;
+{
+       struct pfsnode  *pfsp = VTOPFS(vp);
+
+#ifdef DEBUG
+       if (pfs_debug)
+               printf("pfs_close: vp 0x%x proc %d\n", vp, p->p_pid);
+#endif
+       if ((flag & FWRITE) && (pfsp->pfs_flags & O_EXCL))
+               pfsp->pfs_flags &= ~(FWRITE|O_EXCL);
+
+#ifdef FULLSWAP
+       vmspace_free(pfsp->pfs_vs);
+#endif
+       return (0);
+}
+
+/*
+ * Ioctl operation.
+ */
+/* ARGSUSED */
+int
+pfs_ioctl(vp, com, data, fflag, cred, p)
+       struct vnode *vp;
+       int com;
+       caddr_t data;
+       int fflag;
+       struct ucred *cred;
+       struct proc *p;
+{
+       int             error = 0;
+       struct proc     *procp;
+       struct pfsnode  *pfsp = VTOPFS(vp);
+
+       procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
+       if (!procp)
+               return ESRCH;
+
+       switch (com) {
+
+       case PIOCGPINFO: {
+               int copysize = sizeof(struct kinfo_proc), needed;
+               kinfo_doproc(KINFO_PROC_PID, data, &copysize,
+                                               pfsp->pfs_pid, &needed);
+               break;
+               }
+
+#ifdef notyet /* Changes to proc.h needed */
+       case PIOCGSIGSET:
+               procp->p_psigset = *(sigset_t *)data;
+               break;
+
+       case PIOCSSIGSET:
+               *(sigset_t *)data = procp->p_psigset;
+               break;
+
+       case PIOCGFLTSET:
+               procp->p_pfltset = *(sigflt_t *)data;
+               break;
+
+       case PIOCSFLTSET:
+               *(fltset_t *)data = procp->p_pfltset;
+               break;
+#endif
+
+       case PIOCGMAPFD:
+               error = pfs_vmfd(procp, pfsp, (struct vmfd *)data, p);
+               break;
+
+       case PIOCGNMAP:
+               *(int *)data = pfs_vm_nentries(procp, pfsp);
+               break;
+
+       case PIOCGMAP:
+               error = pfs_vmmap(procp, pfsp, *(struct procmap *)data);
+               break;
+
+       default:
+               error = EIO;
+               break;
+       }
+       return error;
+}
+
+/*
+ * Pass I/O requests to the memory filesystem process.
+ */
+int
+pfs_strategy(bp)
+       register struct buf *bp;
+{
+       struct vnode *vp;
+       struct proc *p = curproc;               /* XXX */
+
+       return (0);
+}
+
+/*
+ * This is a noop, simply returning what one has been given.
+ */
+int
+pfs_bmap(vp, bn, vpp, bnp)
+       struct vnode *vp;
+       daddr_t bn;
+       struct vnode **vpp;
+       daddr_t *bnp;
+{
+
+       if (vpp != NULL)
+               *vpp = vp;
+       if (bnp != NULL)
+               *bnp = bn;
+       return (0);
+}
+
+/*
+ * /proc filesystem inactive routine
+ */
+/* ARGSUSED */
+int
+pfs_inactive(vp, p)
+       struct vnode *vp;
+       struct proc *p;
+{
+       struct pfsnode  *pfsp = VTOPFS(vp);
+
+/*
+       if ((pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0) == NULL
+                       && vp->v_usecount == 0)
+*/
+       if( vp->v_usecount == 0)
+               vgone(vp);
+
+       return 0;
+}
+
+/*
+ * /proc filesystem reclaim routine
+ */
+/* ARGSUSED */
+int
+pfs_reclaim(vp)
+       struct vnode *vp;
+{
+       struct pfsnode  **pp, *pfsp = VTOPFS(vp);
+
+       for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) {
+               if (*pp == pfsp) {
+                       *pp = pfsp->pfs_next;
+                       break;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Print out the contents of an pfsnode.
+ */
+void
+pfs_print(vp)
+       struct vnode *vp;
+{
+       struct pfsnode  *pfsp = VTOPFS(vp);
+
+       printf("tag VT_PROCFS, pid %d, uid %d, gid %d, mode %x, flags %x\n",
+               pfsp->pfs_pid,
+               pfsp->pfs_uid, pfsp->pfs_gid,
+               pfsp->pfs_mode, pfsp->pfs_flags);
+
+       return;
+}
+
+/*
+ * /proc bad operation
+ */
+int
+pfs_badop()
+{
+       printf("pfs_badop called\n");
+       return EIO;
+}
+
+/*
+ * Make up some attributes for a process file
+ */
+int
+pfs_getattr (vp, vap, cred, p)
+       struct vnode *vp;
+       struct vattr *vap;
+       struct ucred *cred;
+       struct proc *p;
+{
+       struct pfsnode *pfsp = VTOPFS(vp);
+       struct proc *procp;
+
+       VATTR_NULL(vap);
+       vap->va_type = vp->v_type;
+       vap->va_flags = pfsp->pfs_vflags;
+
+       if (vp->v_flag & VROOT) {
+               vap->va_mode = 0755;
+               vap->va_nlink = 2;
+               vap->va_size =
+                       roundup((2+nprocs)*sizeof(struct pfsdent), DIRBLKSIZ);
+               vap->va_size_rsv = 0;
+               vap->va_uid = 0;
+               vap->va_gid = 0;
+               vap->va_bytes = 0;
+               vap->va_atime = vap->va_mtime = vap->va_ctime = time; /*XXX*/
+               vap->va_rdev = makedev(255, 255);
+               return 0;
+       }
+
+
+       vap->va_rdev = makedev(255, pfsp->pfs_pid);
+       vap->va_mode = 0600;
+       procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
+       if (!procp)
+               return ESRCH;
+
+       vap->va_nlink = 1;
+       vap->va_size = ctob(    procp->p_vmspace->vm_tsize +
+                               procp->p_vmspace->vm_dsize +
+                               procp->p_vmspace->vm_ssize);
+       vap->va_bytes = 0;
+       vap->va_size_rsv = 0;
+       vap->va_blocksize = page_size;
+       vap->va_uid = procp->p_ucred->cr_uid;
+       vap->va_gid = procp->p_ucred->cr_gid;
+       if (vap->va_uid != procp->p_cred->p_ruid)
+               vap->va_mode |= VSUID;
+       if (vap->va_gid != procp->p_cred->p_rgid)
+               vap->va_mode |= VSGID;
+       if (procp->p_flag & SLOAD) {
+               vap->va_atime = vap->va_mtime = vap->va_ctime =
+                       procp->p_stats->p_start;
+       }
+
+       return 0;
+}
+
+/*
+ * Set some attributes for a process file
+ */
+int
+pfs_setattr (vp, vap, cred, p)
+       struct vnode *vp;
+       struct vattr *vap;
+       struct ucred *cred;
+       struct proc *p;
+{
+       struct pfsnode *pfsp = VTOPFS(vp);
+       struct proc *procp;
+       int error = 0;
+
+       procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
+               if (!procp)
+                       return ESRCH;
+
+       /*
+        * Check for unsetable attributes.
+        */
+       if ((vap->va_type != VNON) || (vap->va_nlink != (short)VNOVAL) ||
+           (vap->va_fsid != (long)VNOVAL) ||
+           (vap->va_fileid != (long)VNOVAL) ||
+           (vap->va_blocksize != (long)VNOVAL) ||
+           (vap->va_rdev != (dev_t)VNOVAL) ||
+           ((int)vap->va_bytes != (u_long)VNOVAL) ||
+           ((int)vap->va_bytes_rsv != (u_long)VNOVAL) ||
+           ((int)vap->va_size != (u_long)VNOVAL) ||
+           ((int)vap->va_size_rsv != (u_long)VNOVAL) ||
+           (vap->va_gen != (long)VNOVAL) ||
+           ((int)vap->va_atime.tv_sec != (u_long)VNOVAL) ||
+           ((int)vap->va_mtime.tv_sec != (u_long)VNOVAL) ||
+           ((int)vap->va_ctime.tv_sec != (u_long)VNOVAL) ||
+           ((  (vap->va_uid != (uid_t)VNOVAL) ||
+               (vap->va_gid != (gid_t)VNOVAL)) && !(vp->v_flag & VROOT)) ) {
+               return (EINVAL);
+       }
+
+       /* set mode bits, only rwx bits are modified */
+       if (vap->va_mode != (u_short)VNOVAL) {
+               if (cred->cr_uid != pfsp->pfs_uid &&
+                       (error = suser(cred, &p->p_acflag)))
+                               return (error);
+               pfsp->pfs_mode = vap->va_mode & 0777;
+       }
+
+       /* For now, only allow to change ownership of "/proc" itself */
+       if ((vp->v_flag & VROOT) && vap->va_uid != (uid_t)VNOVAL) {
+               if ((error = suser(cred, &p->p_acflag)))
+                       return (error);
+               pfsp->pfs_uid = vap->va_uid;
+       }
+
+       if ((vp->v_flag & VROOT) && vap->va_gid != (gid_t)VNOVAL) {
+               if ((cred->cr_uid != pfsp->pfs_uid ||
+                       !groupmember(vap->va_gid, cred)) &&
+                               (error = suser(cred, &p->p_acflag)))
+                       return error;
+
+               pfsp->pfs_gid = vap->va_gid;
+       }
+
+       /* chflags() */
+       if (vap->va_flags != (u_long)VNOVAL) {
+               if (cred->cr_uid != pfsp->pfs_uid &&
+                       (error = suser(cred, &p->p_acflag)))
+                               return (error);
+               if (cred->cr_uid == 0) {
+                       pfsp->pfs_vflags = vap->va_flags;
+               } else {
+                       pfsp->pfs_vflags &= 0xffff0000;
+                       pfsp->pfs_vflags |= (vap->va_flags & 0xffff);
+               }
+       }
+       return 0;
+}
+
+int
+pfs_access (vp, mode, cred, p)
+       struct vnode *vp;
+       int mode;
+       struct ucred *cred;
+       struct proc *p;
+{
+       register struct vattr *vap;
+       register gid_t *gp;
+       struct vattr vattr;
+       register int i;
+       int error;
+
+       /*
+        * If you're the super-user,
+        * you always get access.
+        */
+       if (cred->cr_uid == (uid_t)0)
+               return (0);
+       vap = &vattr;
+       if (error = pfs_getattr(vp, vap, cred, p))
+               return (error);
+       /*
+        * Access check is based on only one of owner, group, public.
+        * If not owner, then check group. If not a member of the
+        * group, then check public access.
+        */
+       if (cred->cr_uid != vap->va_uid) {
+               mode >>= 3;
+               gp = cred->cr_groups;
+               for (i = 0; i < cred->cr_ngroups; i++, gp++)
+                       if (vap->va_gid == *gp)
+                               goto found;
+               mode >>= 3;
+found:
+               ;
+       }
+       if ((vap->va_mode & mode) != 0)
+               return (0);
+       return (EACCES);
+}
+
+/*
+ * /proc lookup
+ */
+int
+pfs_lookup(vp, ndp, p)
+       register struct vnode *vp;
+       register struct nameidata *ndp;
+       struct proc *p;
+{
+       int lockparent, wantparent, flag, error = 0;
+       pid_t pid;
+       struct vnode *nvp;
+       struct pfsnode *pfsp;
+       struct proc *procp;
+
+#ifdef DEBUG
+       if (pfs_debug)
+               printf("pfs_lookup: vp 0x%x name %s proc %d\n",
+                       vp, ndp->ni_ptr, p->p_pid);
+#endif
+
+       ndp->ni_dvp = vp;
+       ndp->ni_vp = NULL;
+       if (vp->v_type != VDIR)
+               return (ENOTDIR);
+
+       lockparent = ndp->ni_nameiop & LOCKPARENT;
+       flag = ndp->ni_nameiop & OPMASK;
+       wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
+       if (flag != LOOKUP)
+               return EACCES;
+       if (ndp->ni_isdotdot) {
+               /* Should not happen */
+               printf("pfs_lookup: vp 0x%x: dotdot\n", vp);
+               return EIO;
+       }
+       if (ndp->ni_namelen == 1 && *ndp->ni_ptr == '.') {
+               VREF(vp);
+               ndp->ni_vp = vp;
+               return 0;
+       }
+
+       pid = (pid_t)atoi(ndp->ni_ptr, ndp->ni_namelen);
+       if (pid == (pid_t)-1)
+               return ENOENT;
+
+       if ((procp = pid?pfind(pid):&proc0) == NULL)
+               return ENOENT;
+
+       /* Search pfs node list first */
+       for (pfsp = pfshead; pfsp != NULL; pfsp = pfsp->pfs_next) {
+               if (pfsp->pfs_pid == pid)
+                       break;
+       }
+
+       if (pfsp == NULL) {
+               struct pfsnode  **pp;
+               error = getnewvnode(VT_PROCFS, vp->v_mount, &pfs_vnodeops, &nvp);
+               if (error)
+                       return error;
+
+               nvp->v_type = VPROC;
+               pfsp = VTOPFS(nvp);
+               pfsp->pfs_next = NULL;
+               pfsp->pfs_pid = pid;
+               pfsp->pfs_vnode = nvp;
+               pfsp->pfs_flags = 0;
+               pfsp->pfs_vflags = 0;
+               pfsp->pfs_uid = procp->p_ucred->cr_uid;
+               pfsp->pfs_gid = procp->p_ucred->cr_gid;
+               pfsp->pfs_mode = 0700;  /* Initial access bits */
+
+               /* Append to pfs node list */
+               pfsp->pfs_next = pfshead;
+               pfshead = pfsp;
+
+       }
+       ndp->ni_vp = pfsp->pfs_vnode;
+
+       return (error);
+}
+
+int
+pfs_readdir(vp, uio, cred, eofflagp)
+        struct vnode *vp;
+        register struct uio *uio;
+        struct ucred *cred;
+        int *eofflagp;
+{
+       int     error = 0;
+       int     count, lost, pcnt, skipcnt, doingzomb = 0;
+       struct proc *p;
+       struct pfsdent dent;
+
+#ifdef DEBUG
+       if (pfs_debug)
+               printf("pfs_readdir: vp 0x%x proc %d\n",
+                               vp, uio->uio_procp->p_pid);
+#endif
+       count = uio->uio_resid;
+       count &= ~(DIRBLKSIZ - 1);
+       lost = uio->uio_resid - count;
+       if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
+               return (EINVAL);
+       uio->uio_resid = count;
+       uio->uio_iov->iov_len = count;
+       *eofflagp = 1;
+       skipcnt = uio->uio_offset / sizeof(struct pfsdent);
+
+       count = 0;
+       if (skipcnt == 0) {
+               /* Fake "." and ".." entries? */
+#if 0
+               dent.d_fileno = 2;              /* XXX - Filesystem root */
+               dent.d_reclen = sizeof(struct pfsdent);
+
+               dent.d_namlen = 1;
+               dent.d_nam[0] = '.';
+               dent.d_nam[1] = '\0';
+               error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
+               if (error)
+                       return error;
+               
+               dent.d_fileno = 2;
+               dent.d_namlen = 2;
+               dent.d_nam[1] = '.';
+               dent.d_nam[2] = '\0';
+               error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
+               if (error)
+                       return error;
+#endif
+               count += 2*dent.d_reclen;
+       }
+
+       p = (struct proc *)allproc;
+       for (pcnt = 0; p && uio->uio_resid; pcnt++) {
+               if (pcnt < skipcnt) {
+                       p = p->p_nxt;
+                       if (p == NULL && doingzomb == 0) {
+                               doingzomb = 1;
+                               p = zombproc;
+                       }
+                       continue;
+               }
+               *eofflagp = 0;
+
+               /* "inode" is process slot (actually position on list) */
+               dent.d_fileno = (unsigned long)(pcnt+1);
+               dent.d_namlen = itos((unsigned int)p->p_pid, dent.d_nam);
+               dent.d_nam[dent.d_namlen] = '\0';
+
+               p = p->p_nxt;
+               if (p == NULL && doingzomb == 0) {
+                       doingzomb = 1;
+                       p = zombproc;
+               }
+               if (p == NULL) {
+                       /* Extend 'reclen' to end of block */;
+                       dent.d_reclen = DIRBLKSIZ - (count & (DIRBLKSIZ - 1));
+               } else
+                       dent.d_reclen = sizeof(struct pfsdent);
+               count += dent.d_reclen;
+               error = uiomove((char *)&dent, dent.d_reclen, uio);
+               if (error)
+                       break;
+       }
+       if (count == 0)
+               *eofflagp = 1;
+
+       uio->uio_resid += lost;
+       return error;
+}
+
+/*
+ * convert n to decimal representation in character array b
+ * return number of decimal digits produced.
+ */
+int
+itos(n, b)
+unsigned int n;
+char *b;
+{
+#define BASE   10
+       int m = (n<BASE)?0:itos(n/BASE, b);
+       *(b+m) = "0123456789abcdef"[n%BASE];
+       return m+1;
+}
+
+/*
+ * convert decimal ascii representation in b of length len to integer
+ */
+int
+atoi(b, len)
+char *b;
+unsigned int len;
+{
+       int n = 0;
+
+       while (len--) {
+               register char c = *b++;
+               if (c < '0' || c > '9')
+                       return -1;
+               n = 10 * n + (c - '0');
+       }
+       return n;
+}
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
new file mode 100644 (file)
index 0000000..9818796
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1993, David Greenman
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     $Id: imgact.h,v 1.2 1993/12/11 06:56:02 davidg Exp davidg $
+ */
+
+#include "proc.h"
+#include "namei.h"
+#include "vnode.h"
+
+struct execve_args {
+       char    *fname;         /* file name */
+       char    **argv;         /* pointer to table of argument pointers */
+       char    **envv;         /* pointer to table of environment pointers */
+};
+
+struct image_params {
+       struct proc *proc;      /* our process struct */
+       struct execve_args *uap; /* syscall arguments */
+       struct vnode *vnodep;   /* pointer to vnode of file to exec */
+       struct vattr *attr;     /* attributes of file */
+       const char *image_header; /* head of file to exec */
+       char *stringbase;       /* base address of tmp string storage */
+       char *stringp;          /* current 'end' pointer of tmp strings */
+       int stringspace;        /* space left in tmp string storage area */
+       int argc, envc;         /* count of argument and environment strings */
+       unsigned long entry_addr; /* entry address of target executable */
+       char vmspace_destroyed; /* flag - we've blown away original vm space */
+       char interpreted;       /* flag - this executable is interpreted */
+       char interpreter_name[64]; /* name of the interpreter */
+};
index 7bb0f61..12c5fa3 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)mount.h       7.22 (Berkeley) 6/3/91
  * SUCH DAMAGE.
  *
  *     from: @(#)mount.h       7.22 (Berkeley) 6/3/91
- *     $Id: mount.h,v 1.7 1993/11/12 10:14:37 chmr Exp $
+ *     $Id: mount.h,v 1.8 1993/11/25 01:37:59 wollman Exp $
  */
 
 #ifndef _SYS_MOUNT_H_
  */
 
 #ifndef _SYS_MOUNT_H_
@@ -82,7 +82,8 @@ struct statfs {
 #define        MOUNT_MFS       3               /* Memory Filesystem */
 #define        MOUNT_MSDOS     4               /* MSDOS Filesystem */
 #define MOUNT_ISOFS    5               /* iso9660 cdrom */
 #define        MOUNT_MFS       3               /* Memory Filesystem */
 #define        MOUNT_MSDOS     4               /* MSDOS Filesystem */
 #define MOUNT_ISOFS    5               /* iso9660 cdrom */
-#define        MOUNT_MAXTYPE   5
+#define MOUNT_PROCFS   6               /* proc filesystem */
+#define        MOUNT_MAXTYPE   6
 
 /*
  * Structure per mounted file system.
 
 /*
  * Structure per mounted file system.
diff --git a/sys/sys/procfs.h b/sys/sys/procfs.h
new file mode 100644 (file)
index 0000000..e48a889
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ *    derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *     $Id: procfs.h,v 1.3 1993/08/24 16:47:42 pk Exp $
+ */
+#ifndef _SYS_PROCFS_H_
+#define _SYS_PROCFS_H_
+
+struct procmap {       /* Simplified VM maps */
+       vm_offset_t     vaddr;
+       vm_size_t       size;
+       vm_offset_t     offset;
+       vm_prot_t       prot;
+};
+
+struct vmfd {          /* Mapped file descriptor */
+       vm_offset_t     vaddr;  /* IN */
+       int             fd;     /* OUT */
+};
+
+typedef        unsigned long   fltset_t;
+
+#define PIOCGPINFO     _IOR('P', 0, struct kinfo_proc)
+#define PIOCGSIGSET    _IOR('P', 1, sigset_t)
+#define PIOCSSIGSET    _IOW('P', 2, sigset_t)
+#define PIOCGFLTSET    _IOR('P', 3, fltset_t)
+#define PIOCSFLTSET    _IOW('P', 4, fltset_t)
+#define PIOCGNMAP      _IOR('P', 5, int)
+#define PIOCGMAP       _IO ('P', 6)
+#define PIOCGMAPFD     _IOWR('P', 7, struct vmfd)
+
+#endif /* _SYS_PROCFS_H_ */
index 3300d1a..04d5f94 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vnode.h       7.39 (Berkeley) 6/27/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vnode.h       7.39 (Berkeley) 6/27/91
- *     $Id: vnode.h,v 1.4 1993/11/07 17:53:23 wollman Exp $
+ *     $Id: vnode.h,v 1.5 1993/11/25 01:38:11 wollman Exp $
  */
 
 #ifndef _SYS_VNODE_H_
  */
 
 #ifndef _SYS_VNODE_H_
 /*
  * vnode types. VNON means no type.
  */
 /*
  * vnode types. VNON means no type.
  */
-enum vtype     { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD };
+enum vtype     { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VPROC, VBAD };
 
 /*
  * Vnode tag types.
  * These are for the benefit of external programs only (e.g., pstat)
  * and should NEVER be inspected inside the kernel.
  */
 
 /*
  * Vnode tag types.
  * These are for the benefit of external programs only (e.g., pstat)
  * and should NEVER be inspected inside the kernel.
  */
-enum vtagtype  { VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PCFS, VT_ISOFS };
+enum vtagtype  { VT_NON, VT_UFS, VT_NFS, VT_MFS, VT_PCFS, VT_ISOFS, VT_PROCFS };
 
 /*
  * This defines the maximum size of the private data area
 
 /*
  * This defines the maximum size of the private data area
index 325bd44..73fb0c0 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vm.h  7.1 (Berkeley) 5/5/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vm.h  7.1 (Berkeley) 5/5/91
- *     $Id: vm.h,v 1.3 1993/11/07 17:54:08 wollman Exp $
+ *     $Id: vm.h,v 1.4 1993/11/25 01:38:58 wollman Exp $
  */
 
 #ifndef _VM_H_
  */
 
 #ifndef _VM_H_
@@ -67,6 +67,7 @@ struct vmspace {
        caddr_t vm_taddr;       /* user virtual address of text XXX */
        caddr_t vm_daddr;       /* user virtual address of data XXX */
        caddr_t vm_maxsaddr;    /* user VA at max stack growth */
        caddr_t vm_taddr;       /* user virtual address of text XXX */
        caddr_t vm_daddr;       /* user virtual address of data XXX */
        caddr_t vm_maxsaddr;    /* user VA at max stack growth */
+       caddr_t vm_minsaddr;    /* user VA of initial stack base */
 };
 
 struct vmspace *vmspace_alloc __P((vm_offset_t min, vm_offset_t max,
 };
 
 struct vmspace *vmspace_alloc __P((vm_offset_t min, vm_offset_t max,
index 6f3a9fa..673d4cd 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_fault.c    7.6 (Berkeley) 5/7/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_fault.c    7.6 (Berkeley) 5/7/91
- *     $Id: vm_fault.c,v 1.6 1993/11/07 17:54:09 wollman Exp $
+ *     $Id: vm_fault.c,v 1.7 1993/11/25 01:38:59 wollman Exp $
  */
 
 /*
  */
 
 /*
@@ -273,6 +273,7 @@ vm_fault(map, vaddr, fault_type, change_wiring)
                         *      been locked out, request that it be unlocked.
                         */
 
                         *      been locked out, request that it be unlocked.
                         */
 
+#ifdef PAGER_PAGE_LOCKING
                        if (fault_type & m->page_lock) {
 #ifdef DOTHREADS
                                int     wait_result;
                        if (fault_type & m->page_lock) {
 #ifdef DOTHREADS
                                int     wait_result;
@@ -300,6 +301,7 @@ vm_fault(map, vaddr, fault_type, change_wiring)
                                goto RetryFault;
 #endif
                        }
                                goto RetryFault;
 #endif
                        }
+#endif
 
                        /*
                         *      Remove the page from the pageout daemon's
 
                        /*
                         *      Remove the page from the pageout daemon's
@@ -866,8 +868,12 @@ vm_fault(map, vaddr, fault_type, change_wiring)
         *      that the page-out daemon won't find us (yet).
         */
 
         *      that the page-out daemon won't find us (yet).
         */
 
+#ifdef PAGER_PAGE_LOCKING
        pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), 
                        prot & ~(m->page_lock), wired);
        pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), 
                        prot & ~(m->page_lock), wired);
+#else
+       pmap_enter(map->pmap, vaddr, VM_PAGE_TO_PHYS(m), prot, wired);
+#endif
 
        /*
         *      If the page is not wired down, then put it where the
 
        /*
         *      If the page is not wired down, then put it where the
index 603446c..ee62f79 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_glue.c     7.8 (Berkeley) 5/15/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_glue.c     7.8 (Berkeley) 5/15/91
- *     $Id: vm_glue.c,v 1.11 1993/11/07 21:48:36 wollman Exp $
+ *     $Id: vm_glue.c,v 1.12 1993/11/25 01:39:01 wollman Exp $
  */
 
 /*
  */
 
 /*
@@ -217,6 +217,8 @@ vm_fork(p1, p2, isvfork)
        vm_map_pageable(kernel_map, addr, addr + ctob(UPAGES), FALSE);
 #else
        addr = kmem_alloc(kernel_map, ctob(UPAGES));
        vm_map_pageable(kernel_map, addr, addr + ctob(UPAGES), FALSE);
 #else
        addr = kmem_alloc(kernel_map, ctob(UPAGES));
+       if (!addr)
+               panic("vm_fork: failed to allocate UPAGES");
 #endif
        up = (struct user *)addr;
        p2->p_addr = up;
 #endif
        up = (struct user *)addr;
        p2->p_addr = up;
index a61e494..495bed6 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_page.c     7.4 (Berkeley) 5/7/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_page.c     7.4 (Berkeley) 5/7/91
- *     $Id: vm_page.c,v 1.2 1993/10/16 16:20:44 rgrimes Exp $
+ *     $Id: vm_page.c,v 1.3 1993/11/25 01:39:12 wollman Exp $
  */
 
 /*
  */
 
 /*
@@ -486,50 +486,33 @@ void vm_page_rename(mem, new_object, new_offset)
        vm_page_unlock_queues();
 }
 
        vm_page_unlock_queues();
 }
 
-void           vm_page_init(mem, object, offset)
+void
+vm_page_init(mem, object, offset)
        vm_page_t       mem;
        vm_object_t     object;
        vm_offset_t     offset;
 {
        vm_page_t       mem;
        vm_object_t     object;
        vm_offset_t     offset;
 {
+               mem->busy = TRUE;
+               mem->tabled = FALSE;
+               vm_page_insert(mem, object, offset);
+               mem->absent = FALSE;
+               mem->fictitious = FALSE;
+#ifdef PAGER_PAGE_LOCKING
+               mem->page_lock = VM_PROT_NONE;
+               mem->unlock_request = VM_PROT_NONE;
+#endif
+               mem->laundry = FALSE;
+               mem->active = FALSE;
+               mem->inactive = FALSE;
+               mem->wire_count = 0;
+               mem->clean = TRUE;
+               mem->copy_on_write = FALSE;
+               mem->fake = TRUE;
 #ifdef DEBUG
 #ifdef DEBUG
-#define        vm_page_init(mem, object, offset)  {\
-               (mem)->busy = TRUE; \
-               (mem)->tabled = FALSE; \
-               vm_page_insert((mem), (object), (offset)); \
-               (mem)->absent = FALSE; \
-               (mem)->fictitious = FALSE; \
-               (mem)->page_lock = VM_PROT_NONE; \
-               (mem)->unlock_request = VM_PROT_NONE; \
-               (mem)->laundry = FALSE; \
-               (mem)->active = FALSE; \
-               (mem)->inactive = FALSE; \
-               (mem)->wire_count = 0; \
-               (mem)->clean = TRUE; \
-               (mem)->copy_on_write = FALSE; \
-               (mem)->fake = TRUE; \
-               (mem)->pagerowned = FALSE; \
-               (mem)->ptpage = FALSE; \
-       }
-#else
-#define        vm_page_init(mem, object, offset)  {\
-               (mem)->busy = TRUE; \
-               (mem)->tabled = FALSE; \
-               vm_page_insert((mem), (object), (offset)); \
-               (mem)->absent = FALSE; \
-               (mem)->fictitious = FALSE; \
-               (mem)->page_lock = VM_PROT_NONE; \
-               (mem)->unlock_request = VM_PROT_NONE; \
-               (mem)->laundry = FALSE; \
-               (mem)->active = FALSE; \
-               (mem)->inactive = FALSE; \
-               (mem)->wire_count = 0; \
-               (mem)->clean = TRUE; \
-               (mem)->copy_on_write = FALSE; \
-               (mem)->fake = TRUE; \
-       }
+               mem->pagerowned = FALSE;
+               mem->ptpage = FALSE;
 #endif
 
 #endif
 
-       vm_page_init(mem, object, offset);
 }
 
 /*
 }
 
 /*
index 2b1980f..f551c17 100644 (file)
@@ -34,7 +34,7 @@
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_page.h     7.3 (Berkeley) 4/21/91
  * SUCH DAMAGE.
  *
  *     from: @(#)vm_page.h     7.3 (Berkeley) 4/21/91
- *     $Id: vm_page.h,v 1.2 1993/10/16 16:20:46 rgrimes Exp $
+ *     $Id: vm_page.h,v 1.3 1993/11/07 17:54:21 wollman Exp $
  */
 
 /*
  */
 
 /*
@@ -107,20 +107,11 @@ struct vm_page {
 
        unsigned int    wire_count:16,  /* how many wired down maps use me?
                                           (P) */
 
        unsigned int    wire_count:16,  /* how many wired down maps use me?
                                           (P) */
-       /* boolean_t */ inactive:1,     /* page is in inactive list (P) */
+                       inactive:1,     /* page is in inactive list (P) */
                        active:1,       /* page is in active list (P) */
                        laundry:1,      /* page is being cleaned now (P)*/
                        active:1,       /* page is in active list (P) */
                        laundry:1,      /* page is being cleaned now (P)*/
-#ifdef DEBUG
-                       pagerowned:1,   /* async paging op in progress */
-                       ptpage:1,       /* is a user page table page */
-#endif
-                       :0;             /* (force to 'long' boundary) */
-#ifdef ns32000
-       int             pad;            /* extra space for ns32000 bit ops */
-#endif /* ns32000 */
-       boolean_t       clean;          /* page has not been modified */
-       unsigned int
-       /* boolean_t */ busy:1,         /* page is in transit (O) */
+                       clean:1,        /* page has not been modified */
+                       busy:1,         /* page is in transit (O) */
                        wanted:1,       /* someone is waiting for page (O) */
                        tabled:1,       /* page is in VP table (O) */
                        copy_on_write:1,/* page must be copied before being
                        wanted:1,       /* someone is waiting for page (O) */
                        tabled:1,       /* page is in VP table (O) */
                        copy_on_write:1,/* page must be copied before being
@@ -129,11 +120,21 @@ struct vm_page {
                        absent:1,       /* virtual page doesn't exist (O) */
                        fake:1,         /* page is a placeholder for page-in
                                           (O) */
                        absent:1,       /* virtual page doesn't exist (O) */
                        fake:1,         /* page is a placeholder for page-in
                                           (O) */
-                       :0;
+#ifdef DEBUG
+                       pagerowned:1,   /* async paging op in progress */
+                       ptpage:1,       /* is a user page table page */
+#endif
+                       :0;             /* (force to 'long' boundary) */
+#ifdef ns32000
+       int             pad;            /* extra space for ns32000 bit ops */
+#endif /* ns32000 */
 
        vm_offset_t     phys_addr;      /* physical address of page */
 
        vm_offset_t     phys_addr;      /* physical address of page */
+
+#ifdef PAGER_PAGE_LOCKING
        vm_prot_t       page_lock;      /* Uses prohibited by data manager */
        vm_prot_t       unlock_request; /* Outstanding unlock request */
        vm_prot_t       page_lock;      /* Uses prohibited by data manager */
        vm_prot_t       unlock_request; /* Outstanding unlock request */
+#endif
 };
 
 typedef struct vm_page *vm_page_t;
 };
 
 typedef struct vm_page *vm_page_t;
index d03e51d..25951f4 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     from: Utah $Hdr: vm_unix.c 1.1 89/11/07$
  *     from: @(#)vm_unix.c     7.2 (Berkeley) 4/20/91
  *
  *     from: Utah $Hdr: vm_unix.c 1.1 89/11/07$
  *     from: @(#)vm_unix.c     7.2 (Berkeley) 4/20/91
- *     $Id: vm_unix.c,v 1.3 1993/10/16 16:20:58 rgrimes Exp $
+ *     $Id: vm_unix.c,v 1.4 1993/11/25 01:39:17 wollman Exp $
  */
 
 /*
  */
 
 /*
@@ -91,38 +91,6 @@ obreak(p, uap, retval)
        return(0);
 }
 
        return(0);
 }
 
-/*
- * Enlarge the "stack segment" to include the specified
- * stack pointer for the process.
- */
-int
-grow(p, sp)
-       struct proc *p;
-       unsigned sp;
-{
-       register struct vmspace *vm = p->p_vmspace;
-       register int si;
-
-       /*
-        * For user defined stacks (from sendsig).
-        */
-       if (sp < (unsigned)vm->vm_maxsaddr)
-               return (0);
-       /*
-        * For common case of already allocated (from trap).
-        */
-       if (sp >= (unsigned)vm->vm_maxsaddr + MAXSSIZ - ctob(vm->vm_ssize))
-               return (1);
-       /*
-        * Really need to check vs limit and increment stack size if ok.
-        */
-       si = clrnd(btoc(vm->vm_maxsaddr + MAXSSIZ - sp) - vm->vm_ssize);
-       if (vm->vm_ssize + si > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
-               return (0);
-       vm->vm_ssize += si;
-       return (1);
-}
-
 struct ovadvise_args {
        int     anom;
 };
 struct ovadvise_args {
        int     anom;
 };