aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/dead_vnops.c22
-rw-r--r--sys/kern/fifo_vnops.c21
-rw-r--r--sys/kern/imgact_aout.c191
-rw-r--r--sys/kern/imgact_shell.c144
-rw-r--r--sys/kern/init_main.c74
-rw-r--r--sys/kern/init_sysent.c44
-rw-r--r--sys/kern/kern_acct.c29
-rw-r--r--sys/kern/kern_clock.c82
-rw-r--r--sys/kern/kern_descrip.c25
-rw-r--r--sys/kern/kern_execve.c846
-rw-r--r--sys/kern/kern_exit.c73
-rw-r--r--sys/kern/kern_fork.c29
-rw-r--r--sys/kern/kern_kinfo.c37
-rw-r--r--sys/kern/kern_ktrace.c29
-rw-r--r--sys/kern/kern_malloc.c17
-rw-r--r--sys/kern/kern_physio.c (renamed from sys/kern/kern__physio.c)148
-rw-r--r--sys/kern/kern_proc.c25
-rw-r--r--sys/kern/kern_prot.c130
-rw-r--r--sys/kern/kern_resource.c17
-rw-r--r--sys/kern/kern_sig.c32
-rw-r--r--sys/kern/kern_subr.c45
-rw-r--r--sys/kern/kern_synch.c65
-rw-r--r--sys/kern/kern_time.c18
-rw-r--r--sys/kern/kern_xxx.c21
-rw-r--r--sys/kern/makesyscalls.sh11
-rw-r--r--sys/kern/spec_vnops.c33
-rw-r--r--sys/kern/subr_log.c13
-rw-r--r--sys/kern/subr_mcount.c22
-rw-r--r--sys/kern/subr_prf.c20
-rw-r--r--sys/kern/subr_rlist.c127
-rw-r--r--sys/kern/subr_xxx.c8
-rw-r--r--sys/kern/sys_generic.c18
-rw-r--r--sys/kern/sys_process.c611
-rw-r--r--sys/kern/sys_socket.c13
-rw-r--r--sys/kern/syscalls.c19
-rw-r--r--sys/kern/syscalls.master19
-rw-r--r--sys/kern/sysv_ipc.c103
-rw-r--r--sys/kern/sysv_msg.c1038
-rw-r--r--sys/kern/sysv_sem.c1114
-rw-r--r--sys/kern/sysv_shm.c72
-rw-r--r--sys/kern/tty.c604
-rw-r--r--sys/kern/tty_chu.c276
-rw-r--r--sys/kern/tty_clk.c303
-rw-r--r--sys/kern/tty_compat.c20
-rw-r--r--sys/kern/tty_conf.c48
-rw-r--r--sys/kern/tty_pty.c34
-rw-r--r--sys/kern/tty_ring.c37
-rw-r--r--sys/kern/tty_tty.c13
-rw-r--r--sys/kern/uipc_domain.c21
-rw-r--r--sys/kern/uipc_mbuf.c249
-rw-r--r--sys/kern/uipc_proto.c6
-rw-r--r--sys/kern/uipc_socket.c56
-rw-r--r--sys/kern/uipc_socket2.c35
-rw-r--r--sys/kern/uipc_syscalls.c116
-rw-r--r--sys/kern/uipc_usrreq.c26
-rw-r--r--sys/kern/vfs__bio.c174
-rw-r--r--sys/kern/vfs_bio.old.c593
-rw-r--r--sys/kern/vfs_cache.c7
-rw-r--r--sys/kern/vfs_conf.c13
-rw-r--r--sys/kern/vfs_lookup.c20
-rw-r--r--sys/kern/vfs_subr.c60
-rw-r--r--sys/kern/vfs_syscalls.c88
-rw-r--r--sys/kern/vfs_vnops.c23
63 files changed, 6155 insertions, 2072 deletions
diff --git a/sys/kern/dead_vnops.c b/sys/kern/dead_vnops.c
index df66b12f7d13..59cb231c83f2 100644
--- a/sys/kern/dead_vnops.c
+++ b/sys/kern/dead_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)dead_vnops.c 7.13 (Berkeley) 4/15/91
- * $Id: dead_vnops.c,v 1.2 1993/10/16 15:23:59 rgrimes Exp $
+ * $Id: dead_vnops.c,v 1.5 1993/12/19 00:51:17 wollman Exp $
*/
#include "param.h"
@@ -42,6 +42,8 @@
#include "namei.h"
#include "buf.h"
+static int chkvnlock(struct vnode *);
+
/*
* Prototypes for dead operations on vnodes.
*/
@@ -174,7 +176,7 @@ int dead_bmap __P((
daddr_t *bnp));
int dead_strategy __P((
struct buf *bp));
-int dead_print __P((
+void dead_print __P((
struct vnode *vp));
#define dead_islocked ((int (*) __P(( \
struct vnode *vp))) nullop)
@@ -225,6 +227,7 @@ struct vnodeops dead_vnodeops = {
* Trivial lookup routine that always fails.
*/
/* ARGSUSED */
+int
dead_lookup(vp, ndp, p)
struct vnode *vp;
struct nameidata *ndp;
@@ -240,6 +243,7 @@ dead_lookup(vp, ndp, p)
* Open always fails as if device did not exist.
*/
/* ARGSUSED */
+int
dead_open(vp, mode, cred, p)
struct vnode *vp;
int mode;
@@ -254,6 +258,7 @@ dead_open(vp, mode, cred, p)
* Vnode op for read
*/
/* ARGSUSED */
+int
dead_read(vp, uio, ioflag, cred)
struct vnode *vp;
struct uio *uio;
@@ -275,6 +280,7 @@ dead_read(vp, uio, ioflag, cred)
* Vnode op for write
*/
/* ARGSUSED */
+int
dead_write(vp, uio, ioflag, cred)
register struct vnode *vp;
struct uio *uio;
@@ -291,6 +297,7 @@ dead_write(vp, uio, ioflag, cred)
* Device ioctl operation.
*/
/* ARGSUSED */
+int
dead_ioctl(vp, com, data, fflag, cred, p)
struct vnode *vp;
register int com;
@@ -306,6 +313,7 @@ dead_ioctl(vp, com, data, fflag, cred, p)
}
/* ARGSUSED */
+int
dead_select(vp, which, fflags, cred, p)
struct vnode *vp;
int which, fflags;
@@ -322,6 +330,7 @@ dead_select(vp, which, fflags, cred, p)
/*
* Just call the device strategy routine
*/
+int
dead_strategy(bp)
register struct buf *bp;
{
@@ -337,6 +346,7 @@ dead_strategy(bp)
/*
* Wait until the vnode has finished changing state.
*/
+int
dead_lock(vp)
struct vnode *vp;
{
@@ -349,6 +359,7 @@ dead_lock(vp)
/*
* Wait until the vnode has finished changing state.
*/
+int
dead_bmap(vp, bn, vpp, bnp)
struct vnode *vp;
daddr_t bn;
@@ -365,6 +376,7 @@ dead_bmap(vp, bn, vpp, bnp)
* Print out the contents of a dead vnode.
*/
/* ARGSUSED */
+void
dead_print(vp)
struct vnode *vp;
{
@@ -375,6 +387,7 @@ dead_print(vp)
/*
* Empty vnode failed operation
*/
+int
dead_ebadf()
{
@@ -384,6 +397,7 @@ dead_ebadf()
/*
* Empty vnode bad operation
*/
+int
dead_badop()
{
@@ -394,6 +408,7 @@ dead_badop()
/*
* Empty vnode null operation
*/
+int
dead_nullop()
{
@@ -404,6 +419,7 @@ dead_nullop()
* We have to wait during times when the vnode is
* in a state of change.
*/
+static int
chkvnlock(vp)
register struct vnode *vp;
{
@@ -411,7 +427,7 @@ chkvnlock(vp)
while (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
- sleep((caddr_t)vp, PINOD);
+ tsleep((caddr_t)vp, PINOD, "chkvnlk", 0);
locked = 1;
}
return (locked);
diff --git a/sys/kern/fifo_vnops.c b/sys/kern/fifo_vnops.c
index d51400a2872b..2affc734e213 100644
--- a/sys/kern/fifo_vnops.c
+++ b/sys/kern/fifo_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)fifo_vnops.c 7.7 (Berkeley) 4/15/91
- * $Id: fifo_vnops.c,v 1.4 1993/10/16 15:24:02 rgrimes Exp $
+ * $Id: fifo_vnops.c,v 1.5 1993/11/25 01:32:44 wollman Exp $
*/
#ifdef FIFO
@@ -100,6 +100,7 @@ struct vnodeops fifo_vnodeops = {
* Trivial lookup routine that always fails.
*/
/* ARGSUSED */
+int
fifo_lookup(vp, ndp, p)
struct vnode *vp;
struct nameidata *ndp;
@@ -116,6 +117,7 @@ fifo_lookup(vp, ndp, p)
* to find an active instance of a fifo.
*/
/* ARGSUSED */
+int
fifo_open(vp, mode, cred, p)
register struct vnode *vp;
int mode;
@@ -203,6 +205,7 @@ fifo_open(vp, mode, cred, p)
* Vnode op for read
*/
/* ARGSUSED */
+int
fifo_read(vp, uio, ioflag, cred)
struct vnode *vp;
register struct uio *uio;
@@ -222,8 +225,8 @@ fifo_read(vp, uio, ioflag, cred)
rso->so_state |= SS_NBIO;
startresid = uio->uio_resid;
VOP_UNLOCK(vp);
- error = soreceive(rso, (struct mbuf **)0, uio, (int *)0,
- (struct mbuf **)0, (struct mbuf **)0);
+ error = soreceive(rso, (struct mbuf **)0, uio,
+ (struct mbuf **)0, (struct mbuf **)0, (int *)0);
VOP_LOCK(vp);
/*
* Clear EOF indication after first such return.
@@ -239,6 +242,7 @@ fifo_read(vp, uio, ioflag, cred)
* Vnode op for write
*/
/* ARGSUSED */
+int
fifo_write(vp, uio, ioflag, cred)
struct vnode *vp;
register struct uio *uio;
@@ -266,6 +270,7 @@ fifo_write(vp, uio, ioflag, cred)
* Device ioctl operation.
*/
/* ARGSUSED */
+int
fifo_ioctl(vp, com, data, fflag, cred, p)
struct vnode *vp;
int com;
@@ -287,6 +292,7 @@ fifo_ioctl(vp, com, data, fflag, cred, p)
}
/* ARGSUSED */
+int
fifo_select(vp, which, fflag, cred, p)
struct vnode *vp;
int which, fflag;
@@ -306,6 +312,7 @@ fifo_select(vp, which, fflag, cred, p)
/*
* This is a noop, simply returning what one has been given.
*/
+int
fifo_bmap(vp, bn, vpp, bnp)
struct vnode *vp;
daddr_t bn;
@@ -324,6 +331,7 @@ fifo_bmap(vp, bn, vpp, bnp)
* At the moment we do not do any locking.
*/
/* ARGSUSED */
+int
fifo_lock(vp)
struct vnode *vp;
{
@@ -332,6 +340,7 @@ fifo_lock(vp)
}
/* ARGSUSED */
+int
fifo_unlock(vp)
struct vnode *vp;
{
@@ -343,6 +352,7 @@ fifo_unlock(vp)
* Device close routine
*/
/* ARGSUSED */
+int
fifo_close(vp, fflag, cred, p)
register struct vnode *vp;
int fflag;
@@ -375,6 +385,7 @@ fifo_close(vp, fflag, cred, p)
/*
* Print out the contents of a fifo vnode.
*/
+void
fifo_print(vp)
struct vnode *vp;
{
@@ -387,6 +398,7 @@ fifo_print(vp)
/*
* Print out internal contents of a fifo vnode.
*/
+void
fifo_printinfo(vp)
struct vnode *vp;
{
@@ -399,6 +411,7 @@ fifo_printinfo(vp)
/*
* Fifo failed operation
*/
+int
fifo_ebadf()
{
@@ -409,6 +422,7 @@ fifo_ebadf()
* Fifo advisory byte-level locks.
*/
/* ARGSUSED */
+int
fifo_advlock(vp, id, op, fl, flags)
struct vnode *vp;
caddr_t id;
@@ -423,6 +437,7 @@ fifo_advlock(vp, id, op, fl, flags)
/*
* Fifo bad operation
*/
+int
fifo_badop()
{
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
new file mode 100644
index 000000000000..8bfb19cfe28d
--- /dev/null
+++ b/sys/kern/imgact_aout.c
@@ -0,0 +1,191 @@
+/*
+ * 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: imgact_aout.c,v 1.3 1993/12/30 01:39:29 davidg Exp $
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "resourcevar.h"
+#include "exec.h"
+#include "mman.h"
+#include "imgact.h"
+#include "kernel.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 ((int)(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 ((int)(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 | VM_PROT_WRITE, /* 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);
+}
+
+/*
+ * Tell kern_execve.c about it, with a little help from the linker.
+ * Since `const' objects end up in the text segment, TEXT_SET is the
+ * correct directive to use.
+ */
+static const struct execsw aout_execsw = { exec_aout_imgact };
+TEXT_SET(execsw_set, aout_execsw);
+
diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c
new file mode 100644
index 000000000000..8a7c0545d705
--- /dev/null
+++ b/sys/kern/imgact_shell.c
@@ -0,0 +1,144 @@
+/*
+ * 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: imgact_shell.c,v 1.2 1993/12/20 19:31:15 wollman Exp $
+ */
+
+#include "param.h"
+#include "systm.h"
+#include "resourcevar.h"
+#include "imgact.h"
+#include "kernel.h"
+#include "machine/endian.h"
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SHELLMAGIC 0x2123 /* #! */
+#else
+#define SHELLMAGIC 0x2321
+#endif
+
+#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);
+}
+
+/*
+ * Tell kern_execve.c about it, with a little help from the linker.
+ * Since `const' objects end up in the text segment, TEXT_SET is the
+ * correct directive to use.
+ */
+static const struct execsw shell_execsw = { exec_shell_imgact };
+TEXT_SET(execsw_set, shell_execsw);
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 8200ee199c70..ce2f1bf8065f 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)init_main.c 7.41 (Berkeley) 5/15/91
- * $Id: init_main.c,v 1.7 1993/10/08 10:50:42 rgrimes Exp $
+ * $Id: init_main.c,v 1.14 1994/01/14 16:24:45 davidg Exp $
*/
#include "param.h"
@@ -57,7 +57,7 @@
#include "vm/vm.h"
-char copyright[] =
+const char copyright[] =
"Copyright (c) 1989,1990,1991,1992 William F. Jolitz. All rights reserved.\n\
Copyright (c) 1982,1986,1989,1991 The Regents of the University\n\
of California. All rights reserved.\n\n";
@@ -86,24 +86,36 @@ extern int (*mountroot)();
struct vnode *rootvp, *swapdev_vp;
int boothowto;
+struct proc *updateproc;
+
#if __GNUC__ >= 2
-__main() {}
+void __main() {}
#endif
/*
+ * This table is filled in by the linker with functions that need to be
+ * called to initialize various pseudo-devices and whatnot.
+ */
+typedef void (*pseudo_func_t)(void);
+extern const struct linker_set pseudo_set;
+static const pseudo_func_t *pseudos =
+ (const pseudo_func_t *)&pseudo_set.ls_items[0];
+
+/*
* System startup; initialize the world, create process 0,
* mount root filesystem, and fork to create init and pagedaemon.
* Most of the hard work is done in the lower-level initialization
* routines including startup(), which does memory initialization
* and autoconfiguration.
*/
+void
main()
{
register int i;
register struct proc *p;
register struct filedesc0 *fdp;
int s, rval[2];
- char *cp;
+ const char *cp;
/*
* Initialize curproc before any possible traps/probes
@@ -220,21 +232,11 @@ main()
* Initialize tables, protocols, and set up well-known inodes.
*/
mbinit();
-#ifdef SYSVSHM
- shminit();
-#endif
-#include "sl.h"
-#if NSL > 0
- slattach(); /* XXX */
-#endif
-#include "ppp.h"
-#if NPPP > 0
- pppattach(); /* XXX */
-#endif
-#include "loop.h"
-#if NLOOP > 0
- loattach(); /* XXX */
-#endif
+
+ while(*pseudos) {
+ (**pseudos++)();
+ }
+
/*
* Block reception of incoming packets
* until protocols have been initialized.
@@ -249,8 +251,8 @@ main()
#endif
/* kick off timeout driven events by calling first time */
- roundrobin();
- schedcpu();
+ roundrobin(0, 0);
+ schedcpu(0, 0);
enablertclock(); /* enable realtime clock interrupts */
/*
@@ -281,22 +283,20 @@ main()
* XXX probably should go elsewhere.
*/
bzero(utsname.sysname, sizeof(utsname.sysname));
- for (cp = version, i= 0;
- *cp && *cp != ' ' && i <= sizeof(utsname.sysname);
- )
- utsname.sysname[i++] = *cp++;
+ for (cp = version, i= 0; *cp && *cp != ' ' && i <= sizeof(utsname.sysname);)
+ utsname.sysname[i++] = *cp++;
bzero(utsname.release, sizeof(utsname.release));
for (cp++, i= 0; *cp && *cp != ' ' && i <= sizeof(utsname.release);)
- utsname.release[i++] = *cp++;
+ utsname.release[i++] = *cp++;
bzero(utsname.version, sizeof(utsname.version));
for (; *cp != '('; cp++);
for (cp++, i= 0; *cp && *cp != ')' && i <= sizeof(utsname.version);)
- utsname.version[i++] = *cp++;
+ utsname.version[i++] = *cp++;
for (; *cp != '#'; cp++);
if(i <= sizeof(utsname.version))
- utsname.version[i++] = '#';
+ utsname.version[i++] = '#';
for (cp++; *cp && *cp != ':' && i <= sizeof(utsname.version);)
- utsname.version[i++] = *cp++;
+ utsname.version[i++] = *cp++;
strncpy(utsname.machine, MACHINE, sizeof(utsname.machine));
utsname.machine[sizeof(utsname.machine)-1] = '\0';
@@ -326,6 +326,8 @@ main()
if (boothowto&RB_FASTBOOT)
*ip++ = 'f';
#endif
+ if (ip == initflags + 1)
+ *ip++ = '-';
*ip++ = '\0';
if (vm_allocate(&p->p_vmspace->vm_map, &addr,
@@ -363,6 +365,20 @@ main()
}
/*
+ * Start update daemon (process 3).
+ */
+ if (fork(p, (void *) NULL, rval))
+ panic("fork update");
+ if (rval[1]) {
+ p = curproc;
+ updateproc = p;
+ p->p_flag |= SLOAD|SSYS;
+ bcopy("update", p->p_comm, sizeof("update"));
+ vfs_update();
+ /*NOTREACHED*/
+ }
+
+ /*
* enter scheduling loop
*/
sched();
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 55e428c00fa4..97056b0c3bbc 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -2,7 +2,7 @@
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * created from $Id: syscalls.master,v 1.5 1993/10/24 06:19:58 paul Exp $
+ * created from $Id: syscalls.master,v 1.8 1994/01/31 10:27:25 davidg Exp $
*/
#include "param.h"
@@ -161,10 +161,26 @@ int getfh();
int getdomainname();
int setdomainname();
int uname();
+int sysarch();
+#ifdef SYSVSEM
+int semsys();
+#else
+#endif
+#ifdef SYSVMSG
+int msgsys();
+#else
+#endif
#ifdef SYSVSHM
int shmsys();
#else
#endif
+#ifdef MACHVMCOMPAT
+int svm_allocate();
+int svm_deallocate();
+int svm_inherit();
+int svm_protect();
+#else
+#endif
int setgid();
int setegid();
int seteuid();
@@ -207,9 +223,18 @@ int ogetsockname();
#ifdef NFS
#else
#endif
+#ifdef SYSVSEM
+#else
+#endif
+#ifdef SYSVMSG
+#else
+#endif
#ifdef SYSVSHM
#else
#endif
+#ifdef MACHVMCOMPAT
+#else
+#endif
#else /* COMPAT_43 */
#define compat(n, name) 0, nosys
@@ -406,12 +431,20 @@ struct sysent sysent[] = {
2, getdomainname, /* 162 = getdomainname */
2, setdomainname, /* 163 = setdomainname */
1, uname, /* 164 = uname */
- 0, nosys, /* 165 = nosys */
+ 2, sysarch, /* 165 = sysarch */
0, nosys, /* 166 = nosys */
0, nosys, /* 167 = nosys */
0, nosys, /* 168 = nosys */
+#ifdef SYSVSEM
+ 5, semsys, /* 169 = semsys */
+#else
0, nosys, /* 169 = nosys */
+#endif
+#ifdef SYSVMSG
+ 6, msgsys, /* 170 = msgsys */
+#else
0, nosys, /* 170 = nosys */
+#endif
#ifdef SYSVSHM
4, shmsys, /* 171 = shmsys */
#else
@@ -422,10 +455,17 @@ struct sysent sysent[] = {
0, nosys, /* 174 = nosys */
0, nosys, /* 175 = nosys */
0, nosys, /* 176 = nosys */
+#ifdef MACHVMCOMPAT
+ 4, svm_allocate, /* 177 = vm_allocate */
+ 3, svm_deallocate, /* 178 = vm_deallocate */
+ 4, svm_inherit, /* 179 = vm_inherit */
+ 5, svm_protect, /* 180 = vm_protect */
+#else
0, nosys, /* 177 = nosys */
0, nosys, /* 178 = nosys */
0, nosys, /* 179 = nosys */
0, nosys, /* 180 = nosys */
+#endif
1, setgid, /* 181 = setgid */
1, setegid, /* 182 = setegid */
1, seteuid, /* 183 = seteuid */
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index 05cb3bfb4451..6d2c0e6536c7 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* All rights reserved.
*
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_acct.c 7.18 (Berkeley) 5/11/91
- * $Id: kern_acct.c,v 1.5 1993/10/19 05:46:05 davidg Exp $
+ * $Id: kern_acct.c,v 1.9.2.1 1994/05/04 07:54:32 rgrimes Exp $
*/
#include "param.h"
@@ -57,10 +64,12 @@
*/
int acctsuspend = 2; /* stop accounting when < 2% free space left */
int acctresume = 4; /* resume when free space risen to > 4% */
-struct timeval chk = { 15, 0 };/* frequency to check space for accounting */
+struct timeval chk; /* frequency to check space for accounting */
struct vnode *acctp = NULL; /* file to which to do accounting */
struct vnode *savacctp = NULL; /* file to which to do accounting when space */
+static void acctwatch(caddr_t, int);
+
/*
* Enable or disable process accounting.
*
@@ -80,6 +89,7 @@ struct sysacct_args {
};
/* ARGSUSED */
+int
sysacct(p, uap, retval)
struct proc *p;
struct sysacct_args *uap;
@@ -89,7 +99,7 @@ sysacct(p, uap, retval)
register struct nameidata *ndp;
struct nameidata nd;
struct vattr attr;
- int rv, acctwatch();
+ int rv;
if (p->p_ucred->cr_uid != 0)
return(EPERM); /* must be root */
@@ -147,8 +157,8 @@ sysacct(p, uap, retval)
acctp = nd.ni_vp;
savacctp = NULL;
- acctwatch(&chk); /* look for full system */
VOP_UNLOCK(acctp);
+ acctwatch((caddr_t)&chk, 0); /* look for full system */
return(0); /* end successfully */
acct_fail:
@@ -161,10 +171,14 @@ acct_fail:
* Periodically check the file system to see if accounting
* should be turned on or off.
*/
-acctwatch(resettime)
- struct timeval *resettime;
+static void
+acctwatch(arg1, arg2)
+ caddr_t arg1;
+ int arg2;
{
+ struct timeval *resettime = (struct timeval *)arg1;
struct statfs sb;
+ int s;
if (savacctp) {
(void)VFS_STATFS(savacctp->v_mount, &sb, (struct proc *)0);
@@ -183,6 +197,8 @@ acctwatch(resettime)
acctp = NULL;
log(LOG_NOTICE, "Accounting suspended\n");
}
+ s = splhigh(); *resettime = time; splx(s);
+ resettime->tv_sec += 15;
timeout(acctwatch, (caddr_t)resettime, hzto(resettime));
}
@@ -193,6 +209,7 @@ acctwatch(resettime)
/* Mark Tinguely (tinguely@plains.NoDak.edu) 8/10/93 */
+void
acct(p)
register struct proc *p;
{
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index eca7041a3e35..44a334e00ebc 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_clock.c 7.16 (Berkeley) 5/9/91
- * $Id: kern_clock.c,v 1.6 1993/10/25 02:02:51 davidg Exp $
+ * $Id: kern_clock.c,v 1.11 1993/12/19 00:51:20 wollman Exp $
*/
#include "param.h"
@@ -40,6 +40,7 @@
#include "callout.h"
#include "kernel.h"
#include "proc.h"
+#include "signalvar.h"
#include "resourcevar.h"
#include "machine/cpu.h"
@@ -51,6 +52,12 @@
#include "gprof.h"
#endif
+static void gatherstats(clockframe *);
+
+/* From callout.h */
+struct callout *callfree, *callout, calltodo;
+int ncallout;
+
/*
* Clock handling routines.
*
@@ -91,12 +98,13 @@
* If this timer is also being used to gather statistics,
* we run through the statistics gathering routine as well.
*/
+void
hardclock(frame)
clockframe frame;
{
register struct callout *p1;
register struct proc *p = curproc;
- register struct pstats *pstats;
+ register struct pstats *pstats = 0;
register struct rusage *ru;
register struct vmspace *vm;
register int s;
@@ -282,6 +290,7 @@ int dk_ndrive = DK_NDRIVE;
* or idle state) for the entire last time interval, and
* update statistics accordingly.
*/
+void
gatherstats(framep)
clockframe *framep;
{
@@ -335,6 +344,7 @@ gatherstats(framep)
* Run periodic events from timeout queue.
*/
/*ARGSUSED*/
+void
softclock(frame)
clockframe frame;
{
@@ -342,7 +352,7 @@ softclock(frame)
for (;;) {
register struct callout *p1;
register caddr_t arg;
- register int (*func)();
+ register timeout_func_t func;
register int a, s;
s = splhigh();
@@ -389,8 +399,9 @@ softclock(frame)
/*
* Arrange that (*func)(arg) is called in t/hz seconds.
*/
+void
timeout(func, arg, t)
- int (*func)();
+ timeout_func_t func;
caddr_t arg;
register int t;
{
@@ -420,8 +431,9 @@ timeout(func, arg, t)
* untimeout is called to remove a function timeout call
* from the callout structure.
*/
+void
untimeout(func, arg)
- int (*func)();
+ timeout_func_t func;
caddr_t arg;
{
register struct callout *p1, *p2;
@@ -446,30 +458,60 @@ untimeout(func, arg)
* Used to compute third argument to timeout() from an
* absolute time.
*/
+
+/* XXX clock_t */
+u_long
hzto(tv)
struct timeval *tv;
{
- register long ticks;
+ register unsigned long ticks;
register long sec;
- int s = splhigh();
+ register long usec;
+ int s;
/*
- * If number of milliseconds will fit in 32 bit arithmetic,
- * then compute number of milliseconds to time and scale to
- * ticks. Otherwise just compute number of hz in time, rounding
- * times greater than representible to maximum value.
+ * If the number of usecs in the whole seconds part of the time
+ * difference fits in a long, then the total number of usecs will
+ * fit in an unsigned long. Compute the total and convert it to
+ * ticks, rounding up and adding 1 to allow for the current tick
+ * to expire. Rounding also depends on unsigned long arithmetic
+ * to avoid overflow.
+ *
+ * Otherwise, if the number of ticks in the whole seconds part of
+ * the time difference fits in a long, then convert the parts to
+ * ticks separately and add, using similar rounding methods and
+ * overflow avoidance. This method would work in the previous
+ * case but it is slightly slower and assumes that hz is integral.
+ *
+ * Otherwise, round the time difference down to the maximum
+ * representable value.
*
- * Delta times less than 25 days can be computed ``exactly''.
- * Maximum value for any timeout in 10ms ticks is 250 days.
+ * Maximum value for any timeout in 10ms ticks is 248 days.
*/
+ s = splhigh();
sec = tv->tv_sec - time.tv_sec;
- if (sec <= 0x7fffffff / 1000 - 1000)
- ticks = ((tv->tv_sec - time.tv_sec) * 1000 +
- (tv->tv_usec - time.tv_usec) / 1000) / (tick / 1000);
- else if (sec <= 0x7fffffff / hz)
- ticks = sec * hz;
- else
- ticks = 0x7fffffff;
+ usec = tv->tv_usec - time.tv_usec;
splx(s);
+ if (usec < 0) {
+ sec--;
+ usec += 1000000;
+ }
+ if (sec < 0) {
+#ifdef DIAGNOSTIC
+ printf("hzto: negative time difference %ld sec %ld usec\n",
+ sec, usec);
+#endif
+ ticks = 1;
+ } else if (sec <= LONG_MAX / 1000000)
+ ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
+ / tick + 1;
+ else if (sec <= LONG_MAX / hz)
+ ticks = sec * hz
+ + ((unsigned long)usec + (tick - 1)) / tick + 1;
+ else
+ ticks = LONG_MAX;
+#define CLOCK_T_MAX INT_MAX /* XXX should be ULONG_MAX */
+ if (ticks > CLOCK_T_MAX)
+ ticks = CLOCK_T_MAX;
return (ticks);
}
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index f8987ae8611a..d28faac16cbe 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
* All rights reserved.
*
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_descrip.c 7.28 (Berkeley) 6/25/91
- * $Id: kern_descrip.c,v 1.4 1993/10/16 15:24:11 rgrimes Exp $
+ * $Id: kern_descrip.c,v 1.6.2.1 1994/05/04 07:54:36 rgrimes Exp $
*/
#include "param.h"
@@ -50,6 +57,8 @@
#include "syslog.h"
#include "resourcevar.h"
+#include "vm/vm_user.h"
+
/*
* Descriptor management.
*/
@@ -61,6 +70,7 @@ extern int maxfdescs; /* maximum number of file descriptors to a process */
* System calls on descriptors.
*/
/* ARGSUSED */
+int
getdtablesize(p, uap, retval)
struct proc *p;
struct args *uap;
@@ -80,6 +90,7 @@ struct dup_args {
};
/* ARGSUSED */
+int
dup(p, uap, retval)
struct proc *p;
struct dup_args *uap;
@@ -118,6 +129,7 @@ struct dup2_args {
};
/* ARGSUSED */
+int
dup2(p, uap, retval)
struct proc *p;
struct dup2_args *uap;
@@ -168,6 +180,7 @@ struct fcntl_args {
};
/* ARGSUSED */
+int
fcntl(p, uap, retval)
struct proc *p;
register struct fcntl_args *uap;
@@ -317,6 +330,7 @@ struct close_args {
int fd;
};
+int
close(p, uap, retval)
struct proc *p;
struct close_args *uap;
@@ -352,6 +366,7 @@ struct fstat_args {
};
/* ARGSUSED */
+int
fstat(p, uap, retval)
struct proc *p;
register struct fstat_args *uap;
@@ -389,6 +404,7 @@ fstat(p, uap, retval)
*/
int fdexpand;
+int
fdalloc(p, want, result)
struct proc *p;
int want;
@@ -457,6 +473,7 @@ fdalloc(p, want, result)
* Check to see whether n user file descriptors
* are available to the process p.
*/
+int
fdavail(p, n)
struct proc *p;
register int n;
@@ -479,6 +496,7 @@ fdavail(p, n)
* Create a new open file structure and allocate
* a file decriptor for the process that refers to it.
*/
+int
falloc(p, resultfp, resultfd)
register struct proc *p;
struct file **resultfp;
@@ -526,6 +544,7 @@ falloc(p, resultfp, resultfd)
/*
* Free a file descriptor.
*/
+void
ffree(fp)
register struct file *fp;
{
@@ -659,6 +678,7 @@ fdcloseexec(p)
* Internal form of close.
* Decrement reference count on file structure.
*/
+int
closef(fp, p)
register struct file *fp;
register struct proc *p;
@@ -713,6 +733,7 @@ struct flock_args {
};
/* ARGSUSED */
+int
flock(p, uap, retval)
struct proc *p;
register struct flock_args *uap;
@@ -759,6 +780,7 @@ flock(p, uap, retval)
* references to this file will be direct to the other driver.
*/
/* ARGSUSED */
+int
fdopen(dev, mode, type)
dev_t dev;
int mode, type;
@@ -779,6 +801,7 @@ fdopen(dev, mode, type)
/*
* Duplicate the specified descriptor to a free descriptor.
*/
+int
dupfdopen(fdp, indx, dfd, mode)
register struct filedesc *fdp;
register int indx, dfd;
diff --git a/sys/kern/kern_execve.c b/sys/kern/kern_execve.c
index 003b2f768b07..5e0aa6565d3d 100644
--- a/sys/kern/kern_execve.c
+++ b/sys/kern/kern_execve.c
@@ -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
@@ -12,31 +12,14 @@
* 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
- * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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)
@@ -45,22 +28,16 @@
* 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.15.2.2 1994/03/24 08:57:16 rgrimes Exp $
*/
#include "param.h"
#include "systm.h"
#include "signalvar.h"
#include "resourcevar.h"
-#include "proc.h"
+#include "imgact.h"
+#include "kernel.h"
#include "mount.h"
-#include "namei.h"
-#include "vnode.h"
#include "file.h"
#include "acct.h"
#include "exec.h"
@@ -68,492 +45,505 @@
#include "wait.h"
#include "mman.h"
#include "malloc.h"
+#include "syslog.h"
#include "vm/vm.h"
#include "vm/vm_param.h"
#include "vm/vm_map.h"
#include "vm/vm_kern.h"
+#include "vm/vm_user.h"
#include "machine/reg.h"
-extern int dostacklimits;
-#define copyinoutstr copyinstr
+int exec_extract_strings __P((struct image_params *));
+int *exec_copyout_strings __P((struct image_params *));
/*
- * execve() system call.
+ * execsw_set is constructed for us by the linker. Each of the items
+ * is a pointer to a `const struct execsw', hence the double pointer here.
*/
+extern const struct linker_set execsw_set;
+const struct execsw **execsw = (const struct execsw **)&execsw_set.ls_items[0];
-struct execve_args {
- char *fname;
- char **argp;
- char **envp;
-};
-
-/* ARGSUSED */
+/*
+ * execve() system call.
+ */
+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, tsize, dsize, bsize, cnt, file_offset,
- virtual_offset;
+ struct nameidata nd, *ndp;
+ char *stringbase, *stringp;
+ int *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 vmspace *vs;
- caddr_t newframe;
- char shellname[MAXINTERP]; /* 05 Aug 92*/
- char *shellargs;
- 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;
+
+ /*
+ * Initialize a few constants in the common area
+ */
+ iparams->proc = p;
+ iparams->uap = uap;
+ iparams->attr = &attr;
/*
- * Step 1. Lookup filename to see if we have something to execute.
+ * Allocate temporary demand zeroed space for argument and
+ * environment strings
+ */
+ error = vm_allocate(kernel_map, (vm_offset_t *)&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->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW | SAVENAME;
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, (vm_offset_t)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 */
+ (vm_offset_t *)&image_header, /* address */
+ NBPG, /* size */
+ VM_PROT_READ, /* protection */
+ VM_PROT_READ, /* max protection */
+ MAP_FILE, /* flags */
+ (caddr_t)vnodep, /* vnode */
+ 0); /* offset */
+ if (error) {
+ uprintf("mmap failed: %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; execsw[i]; ++i) {
+ if (execsw[i]->ex_imgact)
+ error = (*execsw[i]->ex_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);
+ if (vm_deallocate(kernel_map,
+ (vm_offset_t)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;
- 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 = (char *)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;
- 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
+ */
+ *(--stack_base) = 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 */
+ p->p_flag &= ~SUGID;
/*
- * 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!]
+ * Turn off kernel tracing for set-id programs, except for
+ * root.
*/
-
- /* 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 */
+ if (p->p_tracep && (attr.va_mode & (VSUID | VSGID)) &&
+ suser(p->p_ucred, &p->p_acflag)) {
+ p->p_traceflag = 0;
+ vrele(p->p_tracep);
+ p->p_tracep = 0;
+ }
+ if ((attr.va_mode&VSUID) && (p->p_flag & STRC) == 0) {
+ p->p_ucred = crcopy(p->p_ucred);
+ p->p_ucred->cr_uid = attr.va_uid;
+ p->p_flag |= SUGID;
+ }
+ if ((attr.va_mode&VSGID) && (p->p_flag & STRC) == 0) {
+ p->p_ucred = crcopy(p->p_ucred);
+ p->p_ucred->cr_groups[0] = attr.va_gid;
+ p->p_flag |= SUGID;
}
-do_env_as_well:
- if(vectp == 0) goto dont_bother;
-
- /* 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;
- }
-
- /* 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);
+ /*
+ * Implement correct POSIX saved uid behavior.
+ */
+ p->p_cred->p_svuid = p->p_ucred->cr_uid;
+ p->p_cred->p_svgid = p->p_ucred->cr_gid;
-dont_bother:
- if (limitonargs <= 0) {
- rv = E2BIG;
- goto exec_dealloc;
- }
+ /* mark vnode pure text */
+ ndp->ni_vp->v_flag |= VTEXT;
- /* 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;
- }
-
- /* 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.
+ /*
+ * If tracing the process, trap to debugger so breakpoints
+ * can be set before the program executes.
*/
+ if (p->p_flag & STRC)
+ psignal(p, SIGTRAP);
- /* stuff arg count on top of "new" stack */
- /* argbuf[-1] = (char *)argc;*/
- suword(argbuf-1,argc);
+ /* clear "fork but no exec" flag, as we _are_ execing */
+ p->p_acflag &= ~AFORK;
+
+ /* Set entry address */
+ setregs(p, iparams->entry_addr, stack_base);
/*
- * Step 4. Build the new processes image.
- *
- * At this point, we are committed -- destroy old executable!
+ * free various allocated resources
*/
+ if (vm_deallocate(kernel_map, (vm_offset_t)iparams->stringbase,
+ ARG_MAX))
+ panic("execve: string buffer dealloc failed (1)");
+ if (vm_deallocate(kernel_map, (vm_offset_t)image_header, NBPG))
+ panic("execve: header dealloc failed (2)");
+ vput(ndp->ni_vp);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
- /* blow away all address space, except the stack */
- rv = vm_deallocate(&vs->vm_map, 0, USRSTACK - 2*MAXSSIZ);
- if (rv)
- goto exec_abort;
+ return (0);
- /* destroy "old" stack */
- if ((unsigned)newframe < USRSTACK - MAXSSIZ) {
- rv = vm_deallocate(&vs->vm_map, USRSTACK - MAXSSIZ, MAXSSIZ);
- if (rv)
- goto exec_abort;
+exec_fail_dealloc:
+ if (iparams->stringbase && iparams->stringbase != (char *)-1)
+ if (vm_deallocate(kernel_map, (vm_offset_t)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,
+ (vm_offset_t)iparams->image_header, NBPG))
+ panic("execve: header dealloc failed (3)");
+ vput(ndp->ni_vp);
+ FREE(ndp->ni_pnbuf, M_NAMEI);
+
+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 {
- rv = vm_deallocate(&vs->vm_map, USRSTACK - 2*MAXSSIZ, MAXSSIZ);
- if (rv)
- goto exec_abort;
+ return(error);
}
+}
- /* build a new address space */
+/*
+ * Destroy old address space, and allocate a new stack
+ * The new stack is only SGROWSIZ 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 - SGROWSIZ);
+ iparams->vmspace_destroyed = 1;
+ /* Blow away entire process VM */
+ vm_deallocate(&vmspace->vm_map, 0, USRSTACK);
- /* 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);
+ /* Allocate a new stack */
+ error = vm_allocate(&vmspace->vm_map, (vm_offset_t *)&stack_addr,
+ SGROWSIZ, FALSE);
+ if (error)
+ return(error);
- addr = virtual_offset;
+ vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT;
- /* 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;
+ /* Initialize maximum stack address */
+ vmspace->vm_maxsaddr = (char *)USRSTACK - MAXSSIZ;
- addr = virtual_offset + tsize;
+ return(0);
+}
- /* 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;
+/*
+ * 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;
- /* 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;
+ /*
+ * extract arguments first
+ */
+
+ 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++;
+ }
/*
- * Step 5. Prepare process for execution.
+ * extract environment strings
*/
- /* 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 */
+ 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++;
+ }
- /* close files on exec, fixup signals */
- fdcloseexec(p);
- execsigs(p);
+ return (0);
+}
- /* 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(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;
+/*
+ * 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.
+ */
+int *
+exec_copyout_strings(iparams)
+ struct image_params *iparams;
+{
+ int argc, envc;
+ char **vectp;
+ char *stringp, *destp;
+ int *stack_base;
+ int vect_table_size, string_table_size;
+
+ /*
+ * 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 *));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = (int *)vectp;
+
+ stringp = iparams->stringbase;
+ argc = iparams->argc;
+ envc = iparams->envc;
+
+ for (; argc > 0; --argc) {
+ *(vectp++) = destp;
+ while (*destp++ = *stringp++);
}
- 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);
+ /*
+ * Zero length files can't be exec'd
+ */
+ if (attr->va_size == 0)
+ return (ENOEXEC);
- return(rv);
+ /*
+ * 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);
-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));
+ /*
+ * 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);
- /* NOTREACHED */
- return(0);
+ error = VOP_OPEN(vnodep, FREAD, p->p_ucred, p);
+ if (error)
+ return (error);
+
+ return (0);
}
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 6a742b0e160c..e1deb4d855fe 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_exit.c 7.35 (Berkeley) 6/27/91
- * $Id: kern_exit.c,v 1.9 1993/10/19 01:01:20 nate Exp $
+ * $Id: kern_exit.c,v 1.14 1994/01/29 04:04:23 davidg Exp $
*/
#include "param.h"
@@ -48,6 +48,7 @@
#include "vnode.h"
#include "syslog.h"
#include "malloc.h"
+#include "signalvar.h"
#include "resourcevar.h"
#include "machine/cpu.h"
@@ -117,6 +118,10 @@ kexit(p, rv)
*/
fdfree(p);
+#ifdef SYSVSEM
+ semexit(p);
+#endif
+
/* The next two chunks should probably be moved to vmspace_exit. */
#ifdef SYSVSHM
if (p->p_vmspace->vm_shm)
@@ -153,7 +158,7 @@ kexit(p, rv)
(void) ttywait(sp->s_ttyp);
vgoneall(sp->s_ttyvp);
}
- vrele(sp->s_ttyvp);
+ vn_close(sp->s_ttyvp, FREAD, p->p_ucred, p);
sp->s_ttyvp = NULL;
/*
* s_ttyp is not zero'd; we use this to indicate
@@ -170,19 +175,9 @@ kexit(p, rv)
* release trace file
*/
if (p->p_tracep)
- vrele(p->p_tracep);
+ vn_close(p->p_tracep, FREAD|FWRITE, p->p_ucred, p);
#endif
- /* current process does not exist, as far as other parts of the
- * system (clock) is concerned, since parts of it might not be
- * there anymore */
- curproc = NULL;
-
- if (--p->p_limit->p_refcnt == 0) {
- FREE(p->p_limit, M_SUBPROC);
- p->p_limit = (struct plimit *) -1;
- }
-
/*
* Remove proc from allproc queue and pidhash chain.
* Place onto zombproc. Unlink from parent's child list.
@@ -246,6 +241,18 @@ done:
p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
#endif
/*
+ * current process does not exist, as far as other parts of the
+ * system (clock) is concerned, since parts of it might not be
+ * there anymore
+ */
+ curproc = NULL;
+
+ if (--p->p_limit->p_refcnt == 0) {
+ FREE(p->p_limit, M_SUBPROC);
+ p->p_limit = (struct plimit *) -1;
+ }
+
+ /*
* Finally, call machine-dependent code to release the remaining
* resources including address space, the kernel stack and pcb.
* The address space is released by "vmspace_free(p->p_vmspace)";
@@ -258,7 +265,24 @@ done:
/* NOTREACHED */
}
+/*
+ * Wait: check child processes to see if any have exited,
+ * stopped under trace, or (optionally) stopped by a signal.
+ * Pass back status and deallocate exited child's proc structure.
+ */
+
+struct wait1_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
#ifdef COMPAT_43
+ int compat;
+#endif
+};
+
+#ifdef COMPAT_43
+static int wait1(struct proc *, struct wait1_args *, int *);
struct owait_args {
int pid;
@@ -268,6 +292,7 @@ struct owait_args {
int compat;
};
+int
owait(p, uap, retval)
struct proc *p;
register struct owait_args *uap;
@@ -279,7 +304,7 @@ owait(p, uap, retval)
uap->pid = WAIT_ANY;
uap->status = 0;
uap->compat = 1;
- return (wait1(p, uap, retval));
+ return (wait1(p, (struct wait1_args *)uap, retval));
}
struct wait4_args {
@@ -290,6 +315,7 @@ struct wait4_args {
int compat;
};
+int
wait4(p, uap, retval)
struct proc *p;
struct wait4_args *uap;
@@ -297,28 +323,13 @@ wait4(p, uap, retval)
{
uap->compat = 0;
- return (wait1(p, uap, retval));
+ return (wait1(p, (struct wait1_args *)uap, retval));
}
#else
#define wait1 wait4
#endif
-/*
- * Wait: check child processes to see if any have exited,
- * stopped under trace, or (optionally) stopped by a signal.
- * Pass back status and deallocate exited child's proc structure.
- */
-
-struct wait1_args {
- int pid;
- int *status;
- int options;
- struct rusage *rusage;
-#ifdef COMPAT_43
- int compat;
-#endif
-};
-
+static int
wait1(q, uap, retval)
register struct proc *q;
register struct wait1_args *uap;
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index a387af7e9577..5ca1d910f937 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
* All rights reserved.
*
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_fork.c 7.29 (Berkeley) 5/15/91
- * $Id: kern_fork.c,v 1.2 1993/10/16 15:24:17 rgrimes Exp $
+ * $Id: kern_fork.c,v 1.6.2.1 1994/05/04 07:54:38 rgrimes Exp $
*/
#include "param.h"
@@ -47,7 +54,10 @@
#include "ktrace.h"
#include "vm/vm.h"
+static int fork1(struct proc *, int, int *);
+
/* ARGSUSED */
+int
fork(p, uap, retval)
struct proc *p;
void *uap;
@@ -58,6 +68,7 @@ fork(p, uap, retval)
}
/* ARGSUSED */
+int
vfork(p, uap, retval)
struct proc *p;
void *uap;
@@ -69,6 +80,7 @@ vfork(p, uap, retval)
int nprocs = 1; /* process 0 */
+static int
fork1(p1, isvfork, retval)
register struct proc *p1;
int isvfork, retval[];
@@ -156,26 +168,21 @@ again:
*/
MALLOC(p2, struct proc *, sizeof(struct proc), M_PROC, M_WAITOK);
nprocs++;
+
+ /* Initialize all fields to zero */
+ bzero((struct proc *)p2, sizeof(struct proc));
+
p2->p_nxt = allproc;
p2->p_nxt->p_prev = &p2->p_nxt; /* allproc is never NULL */
p2->p_prev = &allproc;
allproc = p2;
- p2->p_link = NULL; /* shouldn't be necessary */
- p2->p_rlink = NULL; /* shouldn't be necessary */
/*
* Make a proc table entry for the new process.
- * Start by zeroing the section of proc that is zero-initialized,
- * then copy the section that is copied directly from the parent.
+ * Copy the section that is copied directly from the parent.
*/
- bzero(&p2->p_startzero,
- (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero));
bcopy(&p1->p_startcopy, &p2->p_startcopy,
(unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
- p2->p_spare[0] = 0; /* XXX - should be in zero range */
- p2->p_spare[1] = 0; /* XXX - should be in zero range */
- p2->p_spare[2] = 0; /* XXX - should be in zero range */
- p2->p_spare[3] = 0; /* XXX - should be in zero range */
/*
* Duplicate sub-structures as needed.
diff --git a/sys/kern/kern_kinfo.c b/sys/kern/kern_kinfo.c
index e9c97b6d3a0c..5d6da494162b 100644
--- a/sys/kern/kern_kinfo.c
+++ b/sys/kern/kern_kinfo.c
@@ -31,10 +31,11 @@
* SUCH DAMAGE.
*
* from: @(#)kern_kinfo.c 7.17 (Berkeley) 6/26/91
- * $Id: kern_kinfo.c,v 1.3 1993/10/16 15:24:18 rgrimes Exp $
+ * $Id: kern_kinfo.c,v 1.9 1993/12/19 00:51:26 wollman Exp $
*/
#include "param.h"
+#include "systm.h"
#include "proc.h"
#include "kinfo.h"
#include "ioctl.h"
@@ -58,6 +59,7 @@ struct getkerninfo_args {
};
/* ARGSUSED */
+int
getkerninfo(p, uap, retval)
struct proc *p;
register struct getkerninfo_args *uap;
@@ -67,10 +69,6 @@ getkerninfo(p, uap, retval)
int bufsize; /* max size of users buffer */
int needed, locked, (*server)(), error = 0;
- if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
- sizeof (bufsize)))
- goto done;
-
switch (ki_type(uap->op)) {
case KINFO_PROC:
@@ -97,9 +95,14 @@ getkerninfo(p, uap, retval)
error = (*server)(uap->op, NULL, NULL, uap->arg, &needed);
goto done;
}
+
+ if (error = copyin((caddr_t)uap->size, (caddr_t)&bufsize,
+ sizeof (bufsize)))
+ goto done;
+
while (kinfo_lock.kl_lock) {
kinfo_lock.kl_want++;
- sleep(&kinfo_lock, PRIBIO+1);
+ tsleep((caddr_t)&kinfo_lock, PRIBIO+1, "kinflck", 0);
kinfo_lock.kl_want--;
kinfo_lock.kl_locked++;
}
@@ -119,7 +122,7 @@ getkerninfo(p, uap, retval)
release:
kinfo_lock.kl_lock--;
if (kinfo_lock.kl_want)
- wakeup(&kinfo_lock);
+ wakeup((caddr_t)&kinfo_lock);
done:
if (!error)
*retval = needed;
@@ -131,14 +134,18 @@ done:
*/
#define KINFO_PROCSLOP (5 * sizeof (struct kinfo_proc))
+int
kinfo_doproc(op, where, acopysize, arg, aneeded)
+ int op;
char *where;
- int *acopysize, *aneeded;
+ int *acopysize;
+ int arg;
+ int *aneeded;
{
register struct proc *p;
register struct kinfo_proc *dp = (struct kinfo_proc *)where;
- register needed = 0;
- int buflen;
+ register int needed = 0;
+ int buflen = 0;
int doingzomb;
struct eproc eproc;
int error = 0;
@@ -243,8 +250,10 @@ fill_eproc(p, ep)
ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
if (SESS_LEADER(p))
ep->e_flag |= EPROC_SLEADER;
- if (p->p_wmesg)
+ if (p->p_wmesg) {
strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
+ ep->e_wmesg[WMESGLEN] = 0; /* prevents fault on long wmesg */
+ }
ep->e_xsize = ep->e_xrssize = 0;
ep->e_xccount = ep->e_xswrss = 0;
}
@@ -252,9 +261,13 @@ fill_eproc(p, ep)
/*
* Get file structures.
*/
+int
kinfo_file(op, where, acopysize, arg, aneeded)
+ int op;
register char *where;
- int *acopysize, *aneeded;
+ int *acopysize;
+ int arg;
+ int *aneeded;
{
int buflen, needed, error;
struct file *fp;
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index 9b218294e33c..42ee4f550928 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_ktrace.c 7.15 (Berkeley) 6/21/91
- * $Id: kern_ktrace.c,v 1.4 1993/10/16 15:24:20 rgrimes Exp $
+ * $Id: kern_ktrace.c,v 1.6 1993/12/19 00:51:27 wollman Exp $
*/
#ifdef KTRACE
@@ -46,8 +46,14 @@
#include "malloc.h"
#include "syslog.h"
-struct ktr_header *
+static void ktrwrite(struct vnode *, struct ktr_header *);
+static int ktrops(struct proc *, struct proc *, int, int, struct vnode *);
+static int ktrsetchildren(struct proc *, struct proc *, int, int, struct vnode *);
+static int ktrcanset(struct proc *, struct proc *);
+
+static struct ktr_header *
ktrgetheader(type)
+ int type;
{
register struct ktr_header *kth;
struct proc *p = curproc; /* XXX */
@@ -61,6 +67,7 @@ ktrgetheader(type)
return (kth);
}
+void
ktrsyscall(vp, code, narg, args)
struct vnode *vp;
int code, narg, args[];
@@ -83,6 +90,7 @@ ktrsyscall(vp, code, narg, args)
FREE(kth, M_TEMP);
}
+void
ktrsysret(vp, code, error, retval)
struct vnode *vp;
int code, error, retval;
@@ -101,6 +109,7 @@ ktrsysret(vp, code, error, retval)
FREE(kth, M_TEMP);
}
+void
ktrnamei(vp, path)
struct vnode *vp;
char *path;
@@ -114,11 +123,14 @@ ktrnamei(vp, path)
FREE(kth, M_TEMP);
}
+void
ktrgenio(vp, fd, rw, iov, len, error)
struct vnode *vp;
int fd;
enum uio_rw rw;
register struct iovec *iov;
+ int len;
+ int error;
{
struct ktr_header *kth = ktrgetheader(KTR_GENIO);
register struct ktr_genio *ktp;
@@ -150,9 +162,13 @@ done:
FREE(ktp, M_TEMP);
}
+void
ktrpsig(vp, sig, action, mask, code)
struct vnode *vp;
+ int sig;
sig_t action;
+ int mask;
+ int code;
{
struct ktr_header *kth = ktrgetheader(KTR_PSIG);
struct ktr_psig kp;
@@ -182,6 +198,7 @@ struct ktrace_args {
};
/* ARGSUSED */
+int
ktrace(curp, uap, retval)
struct proc *curp;
register struct ktrace_args *uap;
@@ -276,8 +293,11 @@ done:
return (error);
}
+static int
ktrops(curp, p, ops, facs, vp)
struct proc *curp, *p;
+ int ops;
+ int facs;
struct vnode *vp;
{
@@ -311,8 +331,11 @@ ktrops(curp, p, ops, facs, vp)
return (1);
}
+static int
ktrsetchildren(curp, top, ops, facs, vp)
struct proc *curp, *top;
+ int ops;
+ int facs;
struct vnode *vp;
{
register struct proc *p;
@@ -345,6 +368,7 @@ ktrsetchildren(curp, top, ops, facs, vp)
/*NOTREACHED*/
}
+static void
ktrwrite(vp, kth)
struct vnode *vp;
register struct ktr_header *kth;
@@ -399,6 +423,7 @@ ktrwrite(vp, kth)
*
* TODO: check groups. use caller effective gid.
*/
+static int
ktrcanset(callp, targetp)
struct proc *callp, *targetp;
{
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index 1a27d598ffcd..6841827446d0 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -31,16 +31,19 @@
* SUCH DAMAGE.
*
* from: @(#)kern_malloc.c 7.25 (Berkeley) 5/8/91
- * $Id: kern_malloc.c,v 1.3 1993/10/18 03:46:54 davidg Exp $
+ * $Id: kern_malloc.c,v 1.8 1994/02/10 08:04:07 davidg Exp $
*/
#include "param.h"
+#include "systm.h"
#include "proc.h"
#include "kernel.h"
#include "malloc.h"
#include "vm/vm.h"
#include "vm/vm_kern.h"
+extern int vm_page_count;
+
struct kmembuckets bucket[MINBUCKET + 16];
struct kmemstats kmemstats[M_LAST];
struct kmemusage *kmemusage;
@@ -63,7 +66,7 @@ malloc(size, type, flags)
#ifdef KMEMSTATS
register struct kmemstats *ksp = &kmemstats[type];
- if (((unsigned long)type) > M_LAST)
+ if (((unsigned long)type) >= M_LAST)
panic("malloc - bogus type");
#endif
@@ -224,18 +227,19 @@ free(addr, type)
/*
* Initialize the kernel memory allocator
*/
+void
kmeminit()
{
register long indx;
int npg;
#if (MAXALLOCSAVE > MINALLOCSIZE * 32768)
- ERROR!_kmeminit:_MAXALLOCSAVE_too_big
+# error "kmeminit: MAXALLOCSAVE too big"
#endif
#if (MAXALLOCSAVE < CLBYTES-1)
- ERROR!_kmeminit:_MAXALLOCSAVE_too_small
+# error "kmeminit: MAXALLOCSAVE too small"
#endif
- npg = VM_KMEM_SIZE/ NBPG;
+ npg = (VM_KMEM_SIZE + VM_MBUF_SIZE) / NBPG;
kmemusage = (struct kmemusage *) kmem_alloc(kernel_map,
(vm_size_t)(npg * sizeof(struct kmemusage)));
kmem_map = kmem_suballoc(kernel_map, (vm_offset_t *)&kmembase,
@@ -250,5 +254,8 @@ kmeminit()
}
for (indx = 0; indx < M_LAST; indx++)
kmemstats[indx].ks_limit = npg * NBPG * 6 / 10;
+
+ /* limit the amount of mbuf space to 1/16 of system memory */
+ kmemstats[M_MBUF].ks_limit = (vm_page_count * NBPG) / 16;
#endif
}
diff --git a/sys/kern/kern__physio.c b/sys/kern/kern_physio.c
index 1e08acd734d1..cf76f80ae202 100644
--- a/sys/kern/kern__physio.c
+++ b/sys/kern/kern_physio.c
@@ -45,7 +45,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: kern__physio.c,v 1.2 1993/10/16 15:24:06 rgrimes Exp $
+ * $Id: kern_physio.c,v 1.1.2.2 1994/05/01 18:59:48 rgrimes Exp $
*/
#include "param.h"
@@ -58,44 +58,70 @@
#include "vm/vm.h"
#include "specdev.h"
-static physio(int (*)(), int, int, int, caddr_t, int *, struct proc *);
-
/*
* Driver interface to do "raw" I/O in the address space of a
* user process directly for read and write operations..
*/
+int
rawread(dev, uio)
dev_t dev; struct uio *uio;
{
- return (uioapply(physio, cdevsw[major(dev)].d_strategy, dev, uio));
+ return (uioapply(physio, (caddr_t) cdevsw[major(dev)].d_strategy,
+ (caddr_t) (u_long) dev, uio));
}
+int
rawwrite(dev, uio)
dev_t dev; struct uio *uio;
{
- return (uioapply(physio, cdevsw[major(dev)].d_strategy, dev, uio));
+ return (uioapply(physio, (caddr_t) cdevsw[major(dev)].d_strategy,
+ (caddr_t) (u_long) dev, uio));
}
-static physio(strat, dev, off, rw, base, len, p)
- int (*strat)();
+
+int physio(strat, dev, bp, off, rw, base, len, p)
+ d_strategy_t strat;
dev_t dev;
+ struct buf *bp;
int rw, off;
caddr_t base;
int *len;
struct proc *p;
{
- register struct buf *bp;
- int amttodo = *len, error, amtdone;
+ int amttodo = *len;
+ int error, amtdone;
vm_prot_t ftype;
- static zero;
+ vm_offset_t v, lastv;
caddr_t adr;
+ int oldflags;
+ int s;
+
+ int bp_alloc = (bp == 0);
+
+/*
+ * keep the process from being swapped
+ */
+ oldflags = p->p_flag;
+ p->p_flag |= SPHYSIO;
rw = rw == UIO_READ ? B_READ : 0;
/* create and build a buffer header for a transfer */
- bp = (struct buf *)malloc(sizeof(*bp), M_TEMP, M_NOWAIT);
- bzero((char *)bp, sizeof(*bp)); /* 09 Sep 92*/
+
+ if (bp_alloc) {
+ bp = (struct buf *)getpbuf();
+ bzero((char *)bp, sizeof(*bp)); /* 09 Sep 92*/
+ } else {
+ s = splbio();
+ while (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ tsleep((caddr_t)bp, PRIBIO, "physbw", 0);
+ }
+ bp->b_flags |= B_BUSY;
+ splx(s);
+ }
+
bp->b_flags = B_BUSY | B_PHYS | rw;
bp->b_proc = p;
bp->b_dev = dev;
@@ -112,12 +138,12 @@ static physio(strat, dev, off, rw, base, len, p)
/* first, check if accessible */
if (rw == B_READ && !useracc(base, bp->b_bcount, B_WRITE)) {
- free(bp, M_TEMP);
- return (EFAULT);
+ error = EFAULT;
+ goto errrtn;
}
if (rw == B_WRITE && !useracc(base, bp->b_bcount, B_READ)) {
- free(bp, M_TEMP);
- return (EFAULT);
+ error = EFAULT;
+ goto errrtn;
}
/* update referenced and dirty bits, handle copy objects */
@@ -125,21 +151,84 @@ static physio(strat, dev, off, rw, base, len, p)
ftype = VM_PROT_READ | VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
-/* 09 Sep 92*/ for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
+
+ lastv = 0;
+ for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
adr += NBPG) {
- vm_fault(&curproc->p_vmspace->vm_map,
- adr, ftype, FALSE);
- *(int *) adr += zero;
+
+/*
+ * make sure that the pde is valid and wired
+ */
+ v = trunc_page(((vm_offset_t)vtopte(adr)));
+ if (v != lastv) {
+ vm_map_pageable(&p->p_vmspace->vm_map, v,
+ round_page(v+1), FALSE);
+ lastv = v;
+ }
+
+/*
+ * do the vm_fault if needed, do the copy-on-write thing when
+ * reading stuff off device into memory.
+ */
+ if (ftype & VM_PROT_WRITE) {
+ /*
+ * properly handle copy-on-write
+ */
+#if 0
+ *(volatile int *) adr += 0;
+#endif
+ vm_fault(&curproc->p_vmspace->vm_map,
+ (vm_offset_t) adr,
+ VM_PROT_READ|VM_PROT_WRITE, FALSE);
+ }
+#if 0
+ else {
+ /*
+ * this clause is not really necessary because
+ * vslock does a vm_map_pageable FALSE.
+ * It is not optimally efficient to reference the
+ * page with the possiblity of it being paged out, but
+ * if this page is faulted here, it will be placed on the
+ * active queue, with the probability of it being paged
+ * out being very very low. This is here primarily for
+ * "symmetry".
+ */
+ *(volatile int *) adr;
+ }
+#endif
}
+/*
+ * if the process has been blocked by the wiring of the page table pages
+ * above or faults of other pages, then the vm_map_pageable contained in the
+ * vslock will fault the pages back in if they have been paged out since
+ * being referenced in the loop above. (vm_map_pageable calls vm_fault_wire
+ * which calls vm_fault to get the pages if needed.)
+ */
- /* lock in core */
+ /* lock in core (perform vm_map_pageable, FALSE) */
vslock (base, bp->b_bcount);
/* perform transfer */
physstrat(bp, strat, PRIBIO);
- /* unlock */
+ /* unlock (perform vm_map_pageable, TRUE) */
vsunlock (base, bp->b_bcount, 0);
+
+ lastv = 0;
+
+/*
+ * unwire the pde
+ */
+ for (adr = (caddr_t)trunc_page(base); adr < base + bp->b_bcount;
+ adr += NBPG) {
+ v = trunc_page(((vm_offset_t)vtopte(adr)));
+ if (v != lastv) {
+ vm_map_pageable(&p->p_vmspace->vm_map, v, round_page(v+1), TRUE);
+ lastv = v;
+ }
+ }
+
+
amtdone = bp->b_bcount - bp->b_resid;
amttodo -= amtdone;
base += amtdone;
@@ -147,7 +236,20 @@ static physio(strat, dev, off, rw, base, len, p)
} while (amttodo && (bp->b_flags & B_ERROR) == 0 && amtdone > 0);
error = bp->b_error;
- free(bp, M_TEMP);
+errrtn:
+ if (bp_alloc) {
+ relpbuf(bp);
+ } else {
+ bp->b_flags &= ~B_BUSY;
+ wakeup((caddr_t)bp);
+ }
*len = amttodo;
+
+/*
+ * allow the process to be swapped
+ */
+ p->p_flag &= ~SPHYSIO;
+ p->p_flag |= (oldflags & SPHYSIO);
+
return (error);
}
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 3dc511da238a..e1f84a331dff 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_proc.c 7.16 (Berkeley) 6/28/91
- * $Id: kern_proc.c,v 1.2 1993/10/16 15:24:23 rgrimes Exp $
+ * $Id: kern_proc.c,v 1.4 1993/12/19 00:51:28 wollman Exp $
*/
#include "param.h"
@@ -49,9 +49,17 @@
#include "ioctl.h"
#include "tty.h"
+struct prochd qs[NQS]; /* as good a place as any... */
+struct proc *zombproc;
+struct proc *allproc;
+
+static void pgdelete(struct pgrp *);
+static void orphanpg(struct pgrp *);
+
/*
* Is p an inferior of the current process?
*/
+int
inferior(p)
register struct proc *p;
{
@@ -66,8 +74,7 @@ inferior(p)
* Locate a process by number
*/
struct proc *
-pfind(pid)
- register pid;
+pfind(int pid)
{
register struct proc *p = pidhash[PIDHASH(pid)];
@@ -81,8 +88,7 @@ pfind(pid)
* Locate a process group by number
*/
struct pgrp *
-pgfind(pgid)
- register pid_t pgid;
+pgfind(pid_t pgid)
{
register struct pgrp *pgrp = pgrphash[PIDHASH(pgid)];
@@ -95,9 +101,11 @@ pgfind(pgid)
/*
* Move p to a new or existing process group (and session)
*/
+void
enterpgrp(p, pgid, mksess)
register struct proc *p;
pid_t pgid;
+ int mksess;
{
register struct pgrp *pgrp = pgfind(pgid);
register struct proc **pp;
@@ -186,6 +194,7 @@ done:
/*
* remove process from process group
*/
+void
leavepgrp(p)
register struct proc *p;
{
@@ -206,6 +215,7 @@ done:
/*
* delete a process group
*/
+static void
pgdelete(pgrp)
register struct pgrp *pgrp;
{
@@ -226,8 +236,6 @@ done:
FREE(pgrp, M_PGRP);
}
-static orphanpg();
-
/*
* Adjust pgrp jobc counters when specified process changes process group.
* We count the number of processes in each process group that "qualify"
@@ -238,6 +246,7 @@ static orphanpg();
* entering == 0 => p is leaving specified group.
* entering == 1 => p is entering specified group.
*/
+void
fixjobc(p, pgrp, entering)
register struct proc *p;
register struct pgrp *pgrp;
@@ -277,7 +286,7 @@ fixjobc(p, pgrp, entering)
* if there are any stopped processes in the group,
* hang-up all process in that group.
*/
-static
+static void
orphanpg(pg)
struct pgrp *pg;
{
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index cc76c7c6f406..2d1d7db1ce4e 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
* of California. All rights reserved.
*
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_prot.c 7.21 (Berkeley) 5/3/91
- * $Id: kern_prot.c,v 1.3 1993/10/16 15:24:24 rgrimes Exp $
+ * $Id: kern_prot.c,v 1.5.2.2 1994/05/04 07:54:41 rgrimes Exp $
*/
/*
@@ -39,8 +46,8 @@
*/
#include "param.h"
-#include "acct.h"
#include "systm.h"
+#include "acct.h"
#include "ucred.h"
#include "proc.h"
#include "timeb.h"
@@ -48,6 +55,7 @@
#include "malloc.h"
/* ARGSUSED */
+int
getpid(p, uap, retval)
struct proc *p;
void *uap;
@@ -62,6 +70,7 @@ getpid(p, uap, retval)
}
/* ARGSUSED */
+int
getppid(p, uap, retval)
struct proc *p;
void *uap;
@@ -73,6 +82,7 @@ getppid(p, uap, retval)
}
/* Get process group ID; note that POSIX getpgrp takes no parameter */
+int
getpgrp(p, uap, retval)
struct proc *p;
void *uap;
@@ -84,6 +94,7 @@ getpgrp(p, uap, retval)
}
/* ARGSUSED */
+int
getuid(p, uap, retval)
struct proc *p;
void *uap;
@@ -98,6 +109,7 @@ getuid(p, uap, retval)
}
/* ARGSUSED */
+int
geteuid(p, uap, retval)
struct proc *p;
void *uap;
@@ -109,6 +121,7 @@ geteuid(p, uap, retval)
}
/* ARGSUSED */
+int
getgid(p, uap, retval)
struct proc *p;
void *uap;
@@ -128,6 +141,7 @@ getgid(p, uap, retval)
* correctly in a library function.
*/
/* ARGSUSED */
+int
getegid(p, uap, retval)
struct proc *p;
void *uap;
@@ -143,6 +157,7 @@ struct getgroups_args {
int *gidset; /* XXX not yet POSIX */
};
+int
getgroups(p, uap, retval)
struct proc *p;
register struct getgroups_args *uap;
@@ -172,6 +187,7 @@ getgroups(p, uap, retval)
}
/* ARGSUSED */
+int
setsid(p, uap, retval)
register struct proc *p;
void *uap;
@@ -207,6 +223,7 @@ struct setpgid_args {
};
/* ARGSUSED */
+int
setpgid(curp, uap, retval)
struct proc *curp;
register struct setpgid_args *uap;
@@ -241,6 +258,7 @@ struct setuid_args {
};
/* ARGSUSED */
+int
setuid(p, uap, retval)
struct proc *p;
struct setuid_args *uap;
@@ -262,6 +280,7 @@ setuid(p, uap, retval)
pc->pc_ucred->cr_uid = uid;
pc->p_ruid = uid;
pc->p_svuid = uid;
+ p->p_flag |= SUGID;
return (0);
}
@@ -270,6 +289,7 @@ struct seteuid_args {
};
/* ARGSUSED */
+int
seteuid(p, uap, retval)
struct proc *p;
struct seteuid_args *uap;
@@ -289,6 +309,7 @@ seteuid(p, uap, retval)
*/
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_uid = euid;
+ p->p_flag |= SUGID;
return (0);
}
@@ -297,6 +318,7 @@ struct setgid_args {
};
/* ARGSUSED */
+int
setgid(p, uap, retval)
struct proc *p;
struct setgid_args *uap;
@@ -312,7 +334,8 @@ setgid(p, uap, retval)
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_groups[0] = gid;
pc->p_rgid = gid;
- pc->p_svgid = gid; /* ??? */
+ pc->p_svgid = gid;
+ p->p_flag |= SUGID;
return (0);
}
@@ -321,6 +344,7 @@ struct setegid_args {
};
/* ARGSUSED */
+int
setegid(p, uap, retval)
struct proc *p;
struct setegid_args *uap;
@@ -336,6 +360,7 @@ setegid(p, uap, retval)
return (error);
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_groups[0] = egid;
+ p->p_flag |= SUGID;
return (0);
}
@@ -347,44 +372,37 @@ struct osetreuid_args {
};
/* ARGSUSED */
+int
osetreuid(p, uap, retval)
register struct proc *p;
struct osetreuid_args *uap;
int *retval;
{
register struct pcred *pc = p->p_cred;
- register uid_t ruid, euid;
- int error;
+ struct seteuid_args e_args;
- if (uap->ruid == -1)
- ruid = pc->p_ruid;
- else
- ruid = uap->ruid;
- /*
- * Allow setting real uid to previous effective, for swapping real and
- * effective. This should be:
- *
- * if (ruid != pc->p_ruid &&
- * (error = suser(pc->pc_ucred, &p->p_acflag)))
- */
- if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
- (error = suser(pc->pc_ucred, &p->p_acflag)))
- return (error);
- if (uap->euid == -1)
- euid = pc->pc_ucred->cr_uid;
- else
- euid = uap->euid;
- if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
- euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
- return (error);
/*
- * Everything's okay, do it. Copy credentials so other references do
- * not see our changes.
+ * Most calls to setreuid() are done in order to swap real and
+ * effective uids. In old versions of BSD, this was the only
+ * way to temporarily renounce privileges and be able to get
+ * them back. In the presence of the POSIX saved id, however,
+ * we can do this without modifying the real uid, which could have
+ * opened up a security hole. So, we implement this: when the user
+ * attempts to set its real uid, we just check to make sure
+ * that they will be able to seteuid() back to that id at some
+ * later time, but don't actually change the real uid.
+ * Logic taken from 4.4BSD.
*/
- pc->pc_ucred = crcopy(pc->pc_ucred);
- pc->pc_ucred->cr_uid = euid;
- pc->p_ruid = ruid;
- return (0);
+ if(uap->ruid != -1 && uap->ruid != pc->p_ruid
+ && uap->ruid != pc->p_svuid) {
+ return EPERM;
+ }
+
+ if(uap->euid == -1) {
+ return 0;
+ }
+ e_args.euid = uap->euid;
+ return seteuid(p, &e_args, retval);
}
struct osetregid_args {
@@ -393,41 +411,29 @@ struct osetregid_args {
};
/* ARGSUSED */
+int
osetregid(p, uap, retval)
register struct proc *p;
struct osetregid_args *uap;
int *retval;
{
register struct pcred *pc = p->p_cred;
- register gid_t rgid, egid;
- int error;
+ struct setegid_args e_args;
- if (uap->rgid == -1)
- rgid = pc->p_rgid;
- else
- rgid = uap->rgid;
/*
- * Allow setting real gid to previous effective, for swapping real and
- * effective. This didn't really work correctly in 4.[23], but is
- * preserved so old stuff doesn't fail. This should be:
- *
- * if (rgid != pc->p_rgid &&
- * (error = suser(pc->pc_ucred, &p->p_acflag)))
+ * Same comments as for setreuid() apply here.
*/
- if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
- (error = suser(pc->pc_ucred, &p->p_acflag)))
- return (error);
- if (uap->egid == -1)
- egid = pc->pc_ucred->cr_groups[0];
- else
- egid = uap->egid;
- if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
- egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
- return (error);
- pc->pc_ucred = crcopy(pc->pc_ucred);
- pc->pc_ucred->cr_groups[0] = egid;
- pc->p_rgid = rgid;
- return (0);
+ if(uap->rgid != -1
+ && uap->rgid != pc->p_rgid
+ && uap->rgid != pc->p_svgid) {
+ return EPERM;
+ }
+
+ if(uap->egid == -1) {
+ return 0;
+ }
+ e_args.egid = uap->egid;
+ return setegid(p, &e_args, retval);
}
#endif
@@ -437,6 +443,7 @@ struct setgroups_args {
};
/* ARGSUSED */
+int
setgroups(p, uap, retval)
struct proc *p;
struct setgroups_args *uap;
@@ -466,6 +473,7 @@ setgroups(p, uap, retval)
/*
* Check if gid is a member of the group set.
*/
+int
groupmember(gid, cred)
gid_t gid;
register struct ucred *cred;
@@ -486,6 +494,7 @@ groupmember(gid, cred)
* indicating use of super-powers.
* Returns 0 or error.
*/
+int
suser(cred, acflag)
struct ucred *cred;
u_short *acflag;
@@ -516,10 +525,11 @@ crget()
* Free a cred structure.
* Throws away space when ref count gets to 0.
*/
+void
crfree(cr)
struct ucred *cr;
{
- int s = splimp(); /* ??? */
+ int s = splimp(); /* ??? XXX FIXME */
if (--cr->cr_ref != 0) {
(void) splx(s);
@@ -572,6 +582,7 @@ struct getlogin_args {
};
/* ARGSUSED */
+int
getlogin(p, uap, retval)
struct proc *p;
struct getlogin_args *uap;
@@ -593,6 +604,7 @@ struct setlogin_args {
};
/* ARGSUSED */
+int
setlogin(p, uap, retval)
struct proc *p;
struct setlogin_args *uap;
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index e2f42e706c27..941ead222a34 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -1,3 +1,10 @@
+/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
/*-
* Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
* All rights reserved.
@@ -31,10 +38,11 @@
* SUCH DAMAGE.
*
* from: @(#)kern_resource.c 7.13 (Berkeley) 5/9/91
- * $Id: kern_resource.c,v 1.6 1993/10/19 01:02:16 nate Exp $
+ * $Id: kern_resource.c,v 1.7.2.1 1994/05/04 07:54:43 rgrimes Exp $
*/
#include "param.h"
+#include "systm.h"
#include "resourcevar.h"
#include "malloc.h"
#include "proc.h"
@@ -50,6 +58,7 @@ struct getpriority_args {
int who;
};
+int
getpriority(curp, uap, retval)
struct proc *curp;
register struct getpriority_args *uap;
@@ -110,6 +119,7 @@ struct setpriority_args {
};
/* ARGSUSED */
+int
setpriority(curp, uap, retval)
struct proc *curp;
register struct setpriority_args *uap;
@@ -163,6 +173,7 @@ setpriority(curp, uap, retval)
return (0);
}
+int
donice(curp, chgp, n)
register struct proc *curp, *chgp;
register int n;
@@ -190,6 +201,7 @@ struct setrlimit_args {
};
/* ARGSUSED */
+int
setrlimit(p, uap, retval)
struct proc *p;
register struct setrlimit_args *uap;
@@ -273,6 +285,7 @@ struct getrlimit_args {
};
/* ARGSUSED */
+int
getrlimit(p, uap, retval)
struct proc *p;
register struct getrlimit_args *uap;
@@ -291,6 +304,7 @@ struct getrusage_args {
};
/* ARGSUSED */
+int
getrusage(p, uap, retval)
register struct proc *p;
register struct getrusage_args *uap;
@@ -322,6 +336,7 @@ getrusage(p, uap, retval)
sizeof (struct rusage)));
}
+void
ruadd(ru, ru2)
register struct rusage *ru, *ru2;
{
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index e0e40b77809d..8450e1c2f588 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_sig.c 7.35 (Berkeley) 6/28/91
- * $Id: kern_sig.c,v 1.5 1993/10/16 15:24:27 rgrimes Exp $
+ * $Id: kern_sig.c,v 1.9 1993/12/19 00:51:30 wollman Exp $
*/
#define SIGPROP /* include signal properties table */
@@ -59,6 +59,11 @@
#include "kinfo_proc.h"
#include "user.h" /* for coredump */
+static void setsigvec(struct proc *, int, struct sigaction *);
+static void stop(struct proc *);
+static void sigexit(struct proc *, int);
+static int killpg1(struct proc *, int, int, int);
+
/*
* Can process p, with pcred pc, send the signal signo to process q?
*/
@@ -77,6 +82,7 @@ struct sigaction_args {
};
/* ARGSUSED */
+int
sigaction(p, uap, retval)
struct proc *p;
register struct sigaction_args *uap;
@@ -116,6 +122,7 @@ sigaction(p, uap, retval)
return (0);
}
+void
setsigvec(p, sig, sa)
register struct proc *p;
int sig;
@@ -229,6 +236,7 @@ struct sigprocmask_args {
sigset_t mask;
};
+int
sigprocmask(p, uap, retval)
register struct proc *p;
struct sigprocmask_args *uap;
@@ -261,6 +269,7 @@ sigprocmask(p, uap, retval)
}
/* ARGSUSED */
+int
sigpending(p, uap, retval)
struct proc *p;
void *uap;
@@ -283,6 +292,7 @@ struct osigvec_args {
};
/* ARGSUSED */
+int
osigvec(p, uap, retval)
struct proc *p;
register struct osigvec_args *uap;
@@ -327,6 +337,7 @@ struct osigblock_args {
int mask;
};
+int
osigblock(p, uap, retval)
register struct proc *p;
struct osigblock_args *uap;
@@ -344,6 +355,7 @@ struct osigsetmask_args {
int mask;
};
+int
osigsetmask(p, uap, retval)
struct proc *p;
struct osigsetmask_args *uap;
@@ -369,6 +381,7 @@ struct sigsuspend_args {
};
/* ARGSUSED */
+int
sigsuspend(p, uap, retval)
register struct proc *p;
struct sigsuspend_args *uap;
@@ -397,6 +410,7 @@ struct sigstack_args {
};
/* ARGSUSED */
+int
sigstack(p, uap, retval)
struct proc *p;
register struct sigstack_args *uap;
@@ -420,6 +434,7 @@ struct kill_args {
};
/* ARGSUSED */
+int
kill(cp, uap, retval)
register struct proc *cp;
register struct kill_args *uap;
@@ -460,6 +475,7 @@ struct okillpg_args {
};
/* ARGSUSED */
+int
okillpg(p, uap, retval)
struct proc *p;
register struct okillpg_args *uap;
@@ -476,6 +492,7 @@ okillpg(p, uap, retval)
* Common code for kill process group/broadcast kill.
* cp is calling process.
*/
+static int
killpg1(cp, signo, pgid, all)
register struct proc *cp;
int signo, pgid, all;
@@ -605,6 +622,10 @@ psignal(p, sig)
register sig_t action;
int mask;
+ /* Ignore signals to system (internal) daemons */
+ if (p->p_flag & SSYS)
+ return;
+
if ((unsigned)sig >= NSIG || sig == 0)
panic("psignal sig");
mask = sigmask(sig);
@@ -795,6 +816,7 @@ out:
* while (sig = CURSIG(curproc))
* psig(sig);
*/
+int
issig(p)
register struct proc *p;
{
@@ -932,6 +954,7 @@ issig(p)
* Signals are handled elsewhere.
* The process must not be on the run queue.
*/
+static void
stop(p)
register struct proc *p;
{
@@ -1012,6 +1035,7 @@ psig(sig)
* If dumping core, save the signal number for the debugger.
* Calls exit and does not return.
*/
+static void
sigexit(p, sig)
register struct proc *p;
int sig;
@@ -1037,6 +1061,7 @@ sigexit(p, sig)
* or was not produced from the same program,
* the link count to the corefile is > 1.
*/
+int
coredump(p)
register struct proc *p;
{
@@ -1061,12 +1086,12 @@ coredump(p)
sprintf(name, "%s.core", p->p_comm);
nd.ni_dirp = name;
nd.ni_segflg = UIO_SYSSPACE;
- if ((error = vn_open(&nd, p, FWRITE, 0644)) == 0)
+ if ((error = vn_open(&nd, p, FWRITE, 0600)) == 0)
exists = 1;
else
exists = 0;
if (error == ENOENT)
- error = vn_open(&nd, p, O_CREAT | FWRITE, 0644);
+ error = vn_open(&nd, p, O_CREAT | FWRITE, 0600);
if (error)
return (error);
vp = nd.ni_vp;
@@ -1131,6 +1156,7 @@ out:
* Flag error in case process won't see signal immediately (blocked or ignored).
*/
/* ARGSUSED */
+int
nosys(p, args, retval)
struct proc *p;
void *args;
diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c
index 6b9a5aba202d..bb860d2ca6bd 100644
--- a/sys/kern/kern_subr.c
+++ b/sys/kern/kern_subr.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1991 Regents of the University of California.
* All rights reserved.
*
@@ -31,18 +38,20 @@
* SUCH DAMAGE.
*
* from: @(#)kern_subr.c 7.7 (Berkeley) 4/15/91
- * $Id: kern_subr.c,v 1.2 1993/10/16 15:24:30 rgrimes Exp $
+ * $Id: kern_subr.c,v 1.5.2.1 1994/05/04 07:54:46 rgrimes Exp $
*/
#include "param.h"
#include "systm.h"
#include "proc.h"
-uiomove(cp, n, uio)
- register caddr_t cp;
+int
+uiomove(xcp, n, uio)
+ register void *xcp;
register int n;
register struct uio *uio;
{
+ caddr_t cp = (caddr_t)xcp;
register struct iovec *iov;
u_int cnt;
int error = 0;
@@ -93,8 +102,11 @@ uiomove(cp, n, uio)
return (error);
}
+int
uioapply(func, arg1, arg2, uio)
int (*func)() ;
+ caddr_t arg1;
+ caddr_t arg2;
register struct uio *uio;
{
register struct iovec *iov;
@@ -117,7 +129,7 @@ uioapply(func, arg1, arg2, uio)
continue;
}
cnt1 = cnt;
- error = (*func)(arg1, arg2, uio->uio_offset, uio->uio_rw,
+ error = (*func)(arg1, arg2, NULL, uio->uio_offset, uio->uio_rw,
iov->iov_base, &cnt1, uio->uio_procp);
cnt -= cnt1;
iov->iov_base += cnt;
@@ -133,6 +145,7 @@ uioapply(func, arg1, arg2, uio)
/*
* Give next character to user as result of read.
*/
+int
ureadc(c, uio)
register int c;
register struct uio *uio;
@@ -171,32 +184,43 @@ again:
return (0);
}
+char *
strcat(src, append)
- register char *src, *append;
+ register char *src;
+ const char *append;
{
+ char *old = src;
for (; *src; ++src)
;
while (*src++ = *append++)
;
+ return old;
}
+char *
strcpy(to, from)
- register char *to, *from;
+ char *to;
+ const char *from;
{
-
+ char *old = to;
for (; *to = *from; ++from, ++to)
;
+ return old;
}
+char *
strncpy(to, from, cnt)
- register char *to, *from;
- register int cnt;
+ char *to;
+ const char *from;
+ int cnt;
{
+ char *old = to;
for (; cnt && (*to = *from); --cnt, ++from, ++to)
;
*to = '\0';
+ return old;
}
@@ -215,10 +239,11 @@ strcmp(s1, s2)
-#ifndef lint /* unused except by ct.c, other oddities XXX */
+#ifdef notdef /* unused except by ct.c, other oddities XXX */
/*
* Get next character written in by user from uio.
*/
+int
uwritec(uio)
struct uio *uio;
{
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 4b888509b915..554d38b004c4 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_synch.c 7.18 (Berkeley) 6/27/91
- * $Id: kern_synch.c,v 1.2 1993/10/16 15:24:32 rgrimes Exp $
+ * $Id: kern_synch.c,v 1.4 1994/02/11 21:14:28 guido Exp $
*/
#include "param.h"
@@ -45,12 +45,17 @@
#include "machine/cpu.h"
+static void endtsleep(caddr_t, int);
+
u_char curpri; /* usrpri of curproc */
/*
* Force switch among equal priority processes every 100ms.
*/
-roundrobin()
+void
+roundrobin(dummy1, dummy2)
+ caddr_t dummy1;
+ int dummy2;
{
need_resched();
@@ -145,7 +150,10 @@ fixpt_t ccpu = 0.95122942450071400909 * FSCALE; /* exp(-1/20) */
/*
* Recompute process priorities, once a second
*/
-schedcpu()
+void
+schedcpu(dummy1, dummy2)
+ caddr_t dummy1;
+ int dummy2;
{
register fixpt_t loadfac = loadfactor(averunnable[0]);
register struct proc *p;
@@ -211,6 +219,7 @@ schedcpu()
* For all load averages >= 1 and max p_cpu of 255, sleeping for at least
* six times the loadfactor will decay p_cpu to zero.
*/
+void
updatepri(p)
register struct proc *p;
{
@@ -259,18 +268,18 @@ int safepri;
* if possible, and EINTR is returned if the system call should
* be interrupted by the signal (return EINTR).
*/
+int
tsleep(chan, pri, wmesg, timo)
caddr_t chan;
int pri;
- char *wmesg;
+ const char *wmesg;
int timo;
{
register struct proc *p = curproc;
register struct slpque *qp;
register s;
- int sig, catch = pri & PCATCH;
+ int sig = 0, catch = pri & PCATCH;
extern int cold;
- int endtsleep();
s = splhigh();
if (cold || panicstr) {
@@ -326,7 +335,7 @@ tsleep(chan, pri, wmesg, timo)
p->p_stats->p_ru.ru_nvcsw++;
swtch();
#include "ddb.h"
-#ifdef NDDB
+#if NDDB > 0
/* handy breakpoint location after process "wakes" */
asm(".globl bpendtsleep ; bpendtsleep:");
#endif
@@ -354,9 +363,12 @@ resume:
* set timeout flag and undo the sleep. If proc
* is stopped, just unsleep so it will remain stopped.
*/
-endtsleep(p)
- register struct proc *p;
+void
+endtsleep(arg1, dummy)
+ caddr_t arg1;
+ int dummy;
{
+ register struct proc *p = (struct proc *)arg1;
int s = splhigh();
if (p->p_wchan) {
@@ -369,9 +381,11 @@ endtsleep(p)
splx(s);
}
+#if 1 /* XXX this should go away... */
/*
* Short-term, non-interruptable sleep.
*/
+void
sleep(chan, pri)
caddr_t chan;
int pri;
@@ -417,17 +431,19 @@ sleep(chan, pri)
p->p_stat = SSLEEP;
p->p_stats->p_ru.ru_nvcsw++;
swtch();
-#ifdef NDDB
+#if NDDB > 0
/* handy breakpoint location after process "wakes" */
asm(".globl bpendsleep ; bpendsleep:");
#endif
curpri = p->p_usrpri;
splx(s);
}
+#endif
/*
* Remove a process from its wait queue
*/
+void
unsleep(p)
register struct proc *p;
{
@@ -452,6 +468,7 @@ unsleep(p)
* Wakeup on "chan"; set all processes
* sleeping on chan to run state.
*/
+void
wakeup(chan)
register caddr_t chan;
{
@@ -501,6 +518,7 @@ restart:
* Initialize the (doubly-linked) run queues
* to be empty.
*/
+void
rqinit()
{
register int i;
@@ -514,6 +532,7 @@ rqinit()
* placing it on the run queue if it is in memory,
* and awakening the swapper if it isn't in memory.
*/
+void
setrun(p)
register struct proc *p;
{
@@ -555,6 +574,7 @@ setrun(p)
* Arrange to reschedule if the resulting priority
* is better than that of the current process.
*/
+void
setpri(p)
register struct proc *p;
{
@@ -567,29 +587,40 @@ setpri(p)
need_resched();
}
-#ifdef NDDB
-#define DDBFUNC(s) ddb_##s
+#if NDDB > 0
+#define DDBFUNC(s) db_##s
+void
DDBFUNC(ps) () {
int np;
+ int nl=0;
struct proc *ap, *p, *pp;
np = nprocs;
p = ap = allproc;
- printf(" pid proc addr uid ppid pgrp flag stat comm wchan\n");
+ db_printf(" pid proc addr uid ppid pgrp flag stat comm wchan\n");
while (--np >= 0) {
+ /*
+ * XXX just take 20 for now...
+ */
+ if(nl++==20) {
+ db_printf("--More--");
+ cngetc();
+ db_printf("\b\b\b\b\b\b\b\b");
+ nl=0;
+ }
pp = p->p_pptr;
if (pp == 0)
pp = p;
if (p->p_stat) {
- printf("%5d %06x %06x %3d %5d %5d %06x %d %s ",
+ db_printf("%5d %06x %06x %3d %5d %5d %06x %d %s ",
p->p_pid, ap, p->p_addr, p->p_cred->p_ruid, pp->p_pid,
p->p_pgrp->pg_id, p->p_flag, p->p_stat,
p->p_comm);
if (p->p_wchan) {
if (p->p_wmesg)
- printf("%s ", p->p_wmesg);
- printf("%x", p->p_wchan);
+ db_printf("%s ", p->p_wmesg);
+ db_printf("%x", p->p_wchan);
}
- printf("\n");
+ db_printf("\n");
}
ap = p->p_nxt;
if (ap == 0 && np > 0)
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index f78786c3668a..a0c4a117bb2f 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -31,10 +31,11 @@
* SUCH DAMAGE.
*
* from: @(#)kern_time.c 7.15 (Berkeley) 3/17/91
- * $Id: kern_time.c,v 1.3 1993/10/16 15:24:33 rgrimes Exp $
+ * $Id: kern_time.c,v 1.4 1993/11/25 01:33:14 wollman Exp $
*/
#include "param.h"
+#include "systm.h"
#include "resourcevar.h"
#include "kernel.h"
#include "proc.h"
@@ -57,6 +58,7 @@ struct gettimeofday_args {
};
/* ARGSUSED */
+int
gettimeofday(p, uap, retval)
struct proc *p;
register struct gettimeofday_args *uap;
@@ -83,6 +85,7 @@ struct settimeofday_args {
};
/* ARGSUSED */
+int
settimeofday(p, uap, retval)
struct proc *p;
struct settimeofday_args *uap;
@@ -120,6 +123,7 @@ struct adjtime_args {
};
/* ARGSUSED */
+int
adjtime(p, uap, retval)
struct proc *p;
register struct adjtime_args *uap;
@@ -185,6 +189,7 @@ struct getitimer_args {
};
/* ARGSUSED */
+int
getitimer(p, uap, retval)
struct proc *p;
register struct getitimer_args *uap;
@@ -222,6 +227,7 @@ struct setitimer_args {
};
/* ARGSUSED */
+int
setitimer(p, uap, retval)
struct proc *p;
register struct setitimer_args *uap;
@@ -265,9 +271,10 @@ setitimer(p, uap, retval)
* This is where delay in processing this timeout causes multiple
* SIGALRM calls to be compressed into one.
*/
-realitexpire(p)
- register struct proc *p;
+void
+realitexpire(caddr_t arg1, int arg2)
{
+ register struct proc *p = (struct proc *)arg1;
int s;
psignal(p, SIGALRM);
@@ -295,6 +302,7 @@ realitexpire(p)
* fix it to have at least minimal value (i.e. if it is less
* than the resolution of the clock, round it up.)
*/
+int
itimerfix(tv)
struct timeval *tv;
{
@@ -317,6 +325,7 @@ itimerfix(tv)
* that it is called in a context where the timers
* on which it is operating cannot change in value.
*/
+int
itimerdecr(itp, usec)
register struct itimerval *itp;
int usec;
@@ -356,6 +365,7 @@ expire:
* it just gets very confused in this case.
* Caveat emptor.
*/
+void
timevaladd(t1, t2)
struct timeval *t1, *t2;
{
@@ -365,6 +375,7 @@ timevaladd(t1, t2)
timevalfix(t1);
}
+void
timevalsub(t1, t2)
struct timeval *t1, *t2;
{
@@ -374,6 +385,7 @@ timevalsub(t1, t2)
timevalfix(t1);
}
+void
timevalfix(t1)
struct timeval *t1;
{
diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c
index d904a8a6af26..e9445e3db512 100644
--- a/sys/kern/kern_xxx.c
+++ b/sys/kern/kern_xxx.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)kern_xxx.c 7.17 (Berkeley) 4/20/91
- * $Id: kern_xxx.c,v 1.5 1993/10/24 06:19:56 paul Exp $
+ * $Id: kern_xxx.c,v 1.7 1994/01/18 05:28:24 nate Exp $
*/
#include "param.h"
@@ -42,6 +42,7 @@
#include "utsname.h"
/* ARGSUSED */
+int
gethostid(p, uap, retval)
struct proc *p;
void *uap;
@@ -57,6 +58,7 @@ struct sethostid_args {
};
/* ARGSUSED */
+int
sethostid(p, uap, retval)
struct proc *p;
struct sethostid_args *uap;
@@ -76,6 +78,7 @@ struct gethostname_args {
};
/* ARGSUSED */
+int
gethostname(p, uap, retval)
struct proc *p;
struct gethostname_args *uap;
@@ -93,6 +96,7 @@ struct sethostname_args {
};
/* ARGSUSED */
+int
sethostname(p, uap, retval)
struct proc *p;
register struct sethostname_args *uap;
@@ -173,6 +177,7 @@ struct reboot_args {
};
/* ARGSUSED */
+int
reboot(p, uap, retval)
struct proc *p;
struct reboot_args *uap;
@@ -187,9 +192,23 @@ reboot(p, uap, retval)
}
#ifdef COMPAT_43
+int
oquota()
{
return (ENOSYS);
}
#endif
+
+
+void
+shutdown_nice(void)
+{
+ register struct proc *p;
+
+ /* Send a signal to init(8) and have it shutdown the world */
+ p = pfind(1);
+ psignal(p, SIGINT);
+
+ return;
+}
diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh
index 709065445b1a..77f61280c1bd 100644
--- a/sys/kern/makesyscalls.sh
+++ b/sys/kern/makesyscalls.sh
@@ -1,6 +1,6 @@
#! /bin/sh -
# from: @(#)makesyscalls.sh 7.6 (Berkeley) 4/20/91
-# $Id: makesyscalls.sh,v 1.2 1993/10/16 15:24:36 rgrimes Exp $
+# $Id: makesyscalls.sh,v 1.3 1993/11/07 21:22:30 wollman Exp $
set -e
@@ -36,6 +36,8 @@ awk < $1 "
infile = \"$1\"
"'
+ printf "#ifndef _SYS_SYSCALL_H_\n" > syshdr
+ printf "#define _SYS_SYSCALL_H_ 1\n" > syshdr
printf "/*\n * System call switch table.\n *\n" > sysdcl
printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
@@ -160,6 +162,7 @@ awk < $1 "
printf("\n#else /* %s */\n", compat) > syscompat
printf("#define compat(n, name) 0, nosys\n") > syscompat
printf("#endif /* %s */\n\n", compat) > syscompat
+ printf("#endif /* _SYS_SYSCALL_H_ */") > syshdr
printf("};\n\n") > sysent
printf("int\tnsysent = sizeof(sysent) / sizeof(sysent[0]);\n") > sysent
@@ -169,4 +172,8 @@ awk < $1 "
cat $sysdcl $syscompat $sysent >$syssw
-chmod 444 $sysnames $syshdr $syssw
+if [ -d CVS ]; then
+ true
+else
+ chmod 444 $sysnames $syshdr $syssw
+fi
diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c
index d60ea0218fc1..dd7a7c8be283 100644
--- a/sys/kern/spec_vnops.c
+++ b/sys/kern/spec_vnops.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)spec_vnops.c 7.37 (Berkeley) 5/30/91
- * $Id: spec_vnops.c,v 1.2 1993/10/16 15:24:37 rgrimes Exp $
+ * $Id: spec_vnops.c,v 1.3 1993/11/25 01:33:15 wollman Exp $
*/
#include "param.h"
@@ -52,13 +52,13 @@
#include "disklabel.h"
/* symbolic sleep message strings for devices */
-char devopn[] = "devopn";
-char devio[] = "devio";
-char devwait[] = "devwait";
-char devin[] = "devin";
-char devout[] = "devout";
-char devioc[] = "devioc";
-char devcls[] = "devcls";
+const char devopn[] = "devopn";
+const char devio[] = "devio";
+const char devwait[] = "devwait";
+const char devin[] = "devin";
+const char devout[] = "devout";
+const char devioc[] = "devioc";
+const char devcls[] = "devcls";
struct vnodeops spec_vnodeops = {
spec_lookup, /* lookup */
@@ -99,6 +99,7 @@ struct vnodeops spec_vnodeops = {
/*
* Trivial lookup routine that always fails.
*/
+int
spec_lookup(vp, ndp, p)
struct vnode *vp;
struct nameidata *ndp;
@@ -116,6 +117,7 @@ spec_lookup(vp, ndp, p)
* Otherwise, call device driver open function.
*/
/* ARGSUSED */
+int
spec_open(vp, mode, cred, p)
register struct vnode *vp;
int mode;
@@ -153,6 +155,7 @@ spec_open(vp, mode, cred, p)
* Vnode op for read
*/
/* ARGSUSED */
+int
spec_read(vp, uio, ioflag, cred)
register struct vnode *vp;
register struct uio *uio;
@@ -237,6 +240,7 @@ spec_read(vp, uio, ioflag, cred)
* Vnode op for write
*/
/* ARGSUSED */
+int
spec_write(vp, uio, ioflag, cred)
register struct vnode *vp;
register struct uio *uio;
@@ -319,6 +323,7 @@ spec_write(vp, uio, ioflag, cred)
* Device ioctl operation.
*/
/* ARGSUSED */
+int
spec_ioctl(vp, com, data, fflag, cred, p)
struct vnode *vp;
int com;
@@ -351,6 +356,7 @@ spec_ioctl(vp, com, data, fflag, cred, p)
}
/* ARGSUSED */
+int
spec_select(vp, which, fflags, cred, p)
struct vnode *vp;
int which, fflags;
@@ -373,6 +379,7 @@ spec_select(vp, which, fflags, cred, p)
/*
* Just call the device strategy routine
*/
+int
spec_strategy(bp)
register struct buf *bp;
{
@@ -384,6 +391,7 @@ spec_strategy(bp)
/*
* This is a noop, simply returning what one has been given.
*/
+int
spec_bmap(vp, bn, vpp, bnp)
struct vnode *vp;
daddr_t bn;
@@ -402,6 +410,7 @@ spec_bmap(vp, bn, vpp, bnp)
* At the moment we do not do any locking.
*/
/* ARGSUSED */
+int
spec_lock(vp)
struct vnode *vp;
{
@@ -410,6 +419,7 @@ spec_lock(vp)
}
/* ARGSUSED */
+int
spec_unlock(vp)
struct vnode *vp;
{
@@ -421,6 +431,7 @@ spec_unlock(vp)
* Device close routine
*/
/* ARGSUSED */
+int
spec_close(vp, flag, cred, p)
register struct vnode *vp;
int flag;
@@ -428,7 +439,7 @@ spec_close(vp, flag, cred, p)
struct proc *p;
{
dev_t dev = vp->v_rdev;
- int (*devclose) __P((dev_t, int, int, struct proc *));
+ int (*devclose) __P((int /*dev_t*/, int, int, struct proc *));
int mode;
switch (vp->v_type) {
@@ -479,6 +490,7 @@ spec_close(vp, flag, cred, p)
/*
* Print out the contents of a special device vnode.
*/
+void
spec_print(vp)
struct vnode *vp;
{
@@ -491,6 +503,7 @@ spec_print(vp)
* Special device advisory byte-level locks.
*/
/* ARGSUSED */
+int
spec_advlock(vp, id, op, fl, flags)
struct vnode *vp;
caddr_t id;
@@ -505,6 +518,7 @@ spec_advlock(vp, id, op, fl, flags)
/*
* Special device failed operation
*/
+int
spec_ebadf()
{
@@ -514,6 +528,7 @@ spec_ebadf()
/*
* Special device bad operation
*/
+int
spec_badop()
{
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c
index bc054fcd56dc..dcda60defa3b 100644
--- a/sys/kern/subr_log.c
+++ b/sys/kern/subr_log.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)subr_log.c 7.11 (Berkeley) 3/17/91
- * $Id: subr_log.c,v 1.4 1993/10/16 15:24:39 rgrimes Exp $
+ * $Id: subr_log.c,v 1.5 1993/11/25 01:33:16 wollman Exp $
*/
/*
@@ -60,6 +60,7 @@ struct logsoftc {
int log_open; /* also used in log() */
/*ARGSUSED*/
+int
logopen(dev, flags, mode, p)
dev_t dev;
int flags, mode;
@@ -88,15 +89,19 @@ logopen(dev, flags, mode, p)
}
/*ARGSUSED*/
+int
logclose(dev, flag)
dev_t dev;
+ int flag;
{
log_open = 0;
logsoftc.sc_state = 0;
logsoftc.sc_sel = 0; /* 16 Jun 93 */
+ return 0;
}
/*ARGSUSED*/
+int
logread(dev, uio, flag)
dev_t dev;
struct uio *uio;
@@ -142,6 +147,7 @@ logread(dev, uio, flag)
}
/*ARGSUSED*/
+int
logselect(dev, rw, p)
dev_t dev;
int rw;
@@ -163,6 +169,7 @@ logselect(dev, rw, p)
return (0);
}
+void
logwakeup()
{
struct proc *p;
@@ -186,8 +193,12 @@ logwakeup()
}
/*ARGSUSED*/
+int
logioctl(dev, com, data, flag)
+ dev_t dev;
+ int com;
caddr_t data;
+ int flag;
{
long l;
int s;
diff --git a/sys/kern/subr_mcount.c b/sys/kern/subr_mcount.c
index 7d57dc190c21..e36d21815333 100644
--- a/sys/kern/subr_mcount.c
+++ b/sys/kern/subr_mcount.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)subr_mcount.c 7.10 (Berkeley) 5/7/91
- * $Id: subr_mcount.c,v 1.3 1993/10/16 15:24:41 rgrimes Exp $
+ * $Id: subr_mcount.c,v 1.6 1993/12/20 16:41:12 davidg Exp $
*/
#ifdef GPROF
@@ -47,14 +47,16 @@ int profiling = 3;
u_short *froms;
struct tostruct *tos = 0;
long tolimit = 0;
-char *s_lowpc = (char *)KERNBASE;
-extern char etext;
-char *s_highpc = &etext;
+extern char btext[];
+char *s_lowpc = btext;
+extern char etext[];
+char *s_highpc = etext;
u_long s_textsize = 0;
int ssiz;
u_short *sbuf;
u_short *kcount;
+void
kmstartup()
{
u_long fromssize, tossize;
@@ -107,6 +109,7 @@ kmstartup()
kcount = (u_short *)(((int)sbuf) + sizeof (struct phdr));
}
+void
mcount()
{
register char *selfpc; /* r11 => r5 */
@@ -167,9 +170,6 @@ mcount()
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");
@@ -189,8 +189,12 @@ mcount()
asm("movw sr,%0" : "=g" (s));
asm("movw #0x2700,sr");
#else
+#if defined(i386)
+ asm("cli");
+#else
s = splhigh();
#endif
+#endif
/*
* Check that frompcindex is a reasonable pc value.
* For example: signal catchers get called from the stack,
@@ -271,8 +275,12 @@ done:
#if defined(hp300)
asm("movw %0,sr" : : "g" (s));
#else
+#if defined(i386)
+ asm("sti");
+#else
splx(s);
#endif
+#endif
/* and fall through */
out:
#if defined(vax)
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index 66c9e13f0c22..6d4a61735965 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -1,3 +1,10 @@
+/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
/*-
* Copyright (c) 1986, 1988, 1991 The Regents of the University of California.
* All rights reserved.
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)subr_prf.c 7.30 (Berkeley) 6/29/91
- * $Id: subr_prf.c,v 1.4.2.1 1993/11/14 18:13:07 rgrimes Exp $
+ * $Id: subr_prf.c,v 1.6.2.1 1994/05/04 07:54:49 rgrimes Exp $
*/
#include "param.h"
@@ -129,7 +136,7 @@ panic(msg)
#endif
#include "ddb.h"
#if NDDB > 0
- Debugger ();
+ Debugger ("panic");
#endif
boot(bootopt);
}
@@ -139,7 +146,7 @@ panic(msg)
*/
void
tablefull(tab)
- char *tab;
+ const char *tab;
{
log(LOG_ERR, "%s: table is full\n", tab);
@@ -285,12 +292,12 @@ logpri(level)
putchar('>', TOLOG, NULL);
}
-int
+void
#ifdef __STDC__
addlog(const char *fmt, ...)
#else
addlog(fmt /*, va_alist */)
- char *fmt;
+ const char *fmt;
#endif
{
register int s;
@@ -307,7 +314,6 @@ addlog(fmt /*, va_alist */)
va_end(ap);
}
logwakeup();
- return (0);
}
int consintr = 1; /* ok to handle console interrupts? */
@@ -317,7 +323,7 @@ int
printf(const char *fmt, ...)
#else
printf(fmt /*, va_alist */)
- char *fmt;
+ const char *fmt;
#endif
{
va_list ap;
diff --git a/sys/kern/subr_rlist.c b/sys/kern/subr_rlist.c
index 8185be26e30a..de25f048fe9c 100644
--- a/sys/kern/subr_rlist.c
+++ b/sys/kern/subr_rlist.c
@@ -45,35 +45,96 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: subr_rlist.c,v 1.2 1993/10/16 15:24:44 rgrimes Exp $
+ * $Id: subr_rlist.c,v 1.5 1993/12/22 12:51:39 davidg Exp $
*/
-#include "sys/param.h"
-#include "sys/cdefs.h"
-#include "sys/malloc.h"
+#include "param.h"
+#include "systm.h"
+#include "cdefs.h"
+#include "malloc.h"
#include "rlist.h"
+#include "vm/vm.h"
+#include "vm/vm_map.h"
+
+extern vm_map_t kernel_map;
/*
* Resource lists.
*/
+#define RLIST_MIN 128
+static int rlist_count=0;
+static struct rlist *rlfree;
+int rlist_active;
+
+static struct rlist *
+rlist_malloc()
+{
+ struct rlist *rl;
+ int i;
+ while( rlist_count < RLIST_MIN) {
+ extern vm_map_t kmem_map;
+ int s = splhigh();
+ rl = (struct rlist *)kmem_malloc(kmem_map, NBPG, 0);
+ splx(s);
+ if( !rl)
+ break;
+
+ for(i=0;i<(NBPG/(sizeof *rl));i++) {
+ rl->rl_next = rlfree;
+ rlfree = rl;
+ rlist_count++;
+ rl++;
+ }
+ }
+
+ if( (rl = rlfree) == 0 )
+ panic("Cannot get an rlist entry");
+
+ --rlist_count;
+ rlfree = rl->rl_next;
+ return rl;
+}
+
+inline static void
+rlist_mfree( struct rlist *rl)
+{
+ rl->rl_next = rlfree;
+ rlfree = rl;
+ ++rlist_count;
+}
+
+
/*
* Add space to a resource list. Used to either
* initialize a list or return free space to it.
*/
+void
rlist_free (rlp, start, end)
-register struct rlist **rlp; unsigned start, end; {
+ register struct rlist **rlp;
+ unsigned start, end;
+{
struct rlist *head;
+ register struct rlist *olp = 0;
+ int s;
+
+ s = splhigh();
+ while( rlist_active)
+ tsleep((caddr_t)&rlist_active, PSWP, "rlistf", 0);
+ rlist_active = 1;
+ splx(s);
head = *rlp;
loop:
/* if nothing here, insert (tail of list) */
if (*rlp == 0) {
- *rlp = (struct rlist *)malloc(sizeof(**rlp), M_TEMP, M_NOWAIT);
+ *rlp = rlist_malloc();
(*rlp)->rl_start = start;
(*rlp)->rl_end = end;
(*rlp)->rl_next = 0;
+ rlist_active = 0;
+ wakeup((caddr_t)&rlist_active);
return;
}
@@ -100,11 +161,21 @@ loop:
if (end < (*rlp)->rl_start) {
register struct rlist *nlp;
- nlp = (struct rlist *)malloc(sizeof(*nlp), M_TEMP, M_NOWAIT);
+ nlp = rlist_malloc();
nlp->rl_start = start;
nlp->rl_end = end;
nlp->rl_next = *rlp;
- *rlp = nlp;
+ /*
+ * If the new element is in front of the list,
+ * adjust *rlp, else don't.
+ */
+ if( olp) {
+ olp->rl_next = nlp;
+ } else {
+ *rlp = nlp;
+ }
+ rlist_active = 0;
+ wakeup((caddr_t)&rlist_active);
return;
}
@@ -117,6 +188,7 @@ loop:
/* are we after this element */
if (start > (*rlp)->rl_end) {
+ olp = *rlp;
rlp = &((*rlp)->rl_next);
goto loop;
} else
@@ -134,11 +206,13 @@ scan:
if (lp->rl_end + 1 == lpn->rl_start) {
lp->rl_end = lpn->rl_end;
lp->rl_next = lpn->rl_next;
- free(lpn, M_TEMP);
+ rlist_mfree(lpn);
} else
lp = lp->rl_next;
}
}
+ rlist_active = 0;
+ wakeup((caddr_t)&rlist_active);
}
/*
@@ -148,9 +222,18 @@ scan:
* "*loc". (Note: loc can be zero if we don't wish the value)
*/
int rlist_alloc (rlp, size, loc)
-struct rlist **rlp; unsigned size, *loc; {
+ struct rlist **rlp;
+ unsigned size, *loc;
+{
register struct rlist *lp;
+ int s;
+ register struct rlist *olp = 0;
+ s = splhigh();
+ while( rlist_active)
+ tsleep((caddr_t)&rlist_active, PSWP, "rlista", 0);
+ rlist_active = 1;
+ splx(s);
/* walk list, allocating first thing that's big enough (first fit) */
for (; *rlp; rlp = &((*rlp)->rl_next))
@@ -163,13 +246,27 @@ struct rlist **rlp; unsigned size, *loc; {
/* did we eat this element entirely? */
if ((*rlp)->rl_start > (*rlp)->rl_end) {
lp = (*rlp)->rl_next;
- free (*rlp, M_TEMP);
- *rlp = lp;
+ rlist_mfree(*rlp);
+ /*
+ * if the deleted element was in fromt
+ * of the list, adjust *rlp, else don't.
+ */
+ if (olp) {
+ olp->rl_next = lp;
+ } else {
+ *rlp = lp;
+ }
}
+ rlist_active = 0;
+ wakeup((caddr_t)&rlist_active);
return (1);
+ } else {
+ olp = *rlp;
}
+ rlist_active = 0;
+ wakeup((caddr_t)&rlist_active);
/* nothing in list that's big enough */
return (0);
}
@@ -178,14 +275,16 @@ struct rlist **rlp; unsigned size, *loc; {
* Finished with this resource list, reclaim all space and
* mark it as being empty.
*/
+void
rlist_destroy (rlp)
-struct rlist **rlp; {
+ struct rlist **rlp;
+{
struct rlist *lp, *nlp;
lp = *rlp;
*rlp = 0;
for (; lp; lp = nlp) {
nlp = lp->rl_next;
- free (lp, M_TEMP);
+ rlist_mfree(lp);
}
}
diff --git a/sys/kern/subr_xxx.c b/sys/kern/subr_xxx.c
index e6457a2cd237..1c9cc9afe043 100644
--- a/sys/kern/subr_xxx.c
+++ b/sys/kern/subr_xxx.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)subr_xxx.c 7.10 (Berkeley) 4/20/91
- * $Id: subr_xxx.c,v 1.2 1993/10/16 15:24:45 rgrimes Exp $
+ * $Id: subr_xxx.c,v 1.3 1993/11/25 01:33:19 wollman Exp $
*/
/*
@@ -45,6 +45,7 @@
/*
* Unsupported device function (e.g. writing to read-only device).
*/
+int
enodev()
{
@@ -54,6 +55,7 @@ enodev()
/*
* Unconfigured device function; driver not configured.
*/
+int
enxio()
{
@@ -63,6 +65,7 @@ enxio()
/*
* Unsupported ioctl function.
*/
+int
enoioctl()
{
@@ -74,6 +77,7 @@ enoioctl()
* This is used for an otherwise-reasonable operation
* that is not supported by the current system binary.
*/
+int
enosys()
{
@@ -84,6 +88,7 @@ enosys()
* Return error for operation not supported
* on a specific object or file type.
*/
+int
eopnotsupp()
{
@@ -93,6 +98,7 @@ eopnotsupp()
/*
* Generic null operation, always returns success.
*/
+int
nullop()
{
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 2a4222496a0f..9f01bd7f3fcf 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)sys_generic.c 7.30 (Berkeley) 5/30/91
- * $Id: sys_generic.c,v 1.4 1993/10/16 15:24:47 rgrimes Exp $
+ * $Id: sys_generic.c,v 1.6 1993/12/19 00:51:34 wollman Exp $
*/
#include "param.h"
@@ -45,6 +45,7 @@
#include "kernel.h"
#include "stat.h"
#include "malloc.h"
+#include "signalvar.h"
#ifdef KTRACE
#include "ktrace.h"
#endif
@@ -59,6 +60,7 @@ struct read_args {
* Read system call.
*/
/* ARGSUSED */
+int
read(p, uap, retval)
struct proc *p;
register struct read_args *uap;
@@ -117,6 +119,7 @@ struct readv_args {
};
/* ARGSUSED */
+int
readv(p, uap, retval)
struct proc *p;
register struct readv_args *uap;
@@ -126,7 +129,7 @@ readv(p, uap, retval)
register struct filedesc *fdp = p->p_fd;
struct uio auio;
register struct iovec *iov;
- struct iovec *saveiov;
+ struct iovec *saveiov = 0;
struct iovec aiov[UIO_SMALLIOV];
long i, cnt, error = 0;
unsigned iovlen;
@@ -207,6 +210,7 @@ struct write_args {
unsigned count;
};
+int
write(p, uap, retval)
struct proc *p;
register struct write_args *uap;
@@ -268,6 +272,7 @@ struct writev_args {
unsigned iovcnt;
};
+int
writev(p, uap, retval)
struct proc *p;
register struct writev_args *uap;
@@ -277,7 +282,7 @@ writev(p, uap, retval)
register struct filedesc *fdp = p->p_fd;
struct uio auio;
register struct iovec *iov;
- struct iovec *saveiov;
+ struct iovec *saveiov = 0;
struct iovec aiov[UIO_SMALLIOV];
long i, cnt, error = 0;
unsigned iovlen;
@@ -362,6 +367,7 @@ struct ioctl_args {
};
/* ARGSUSED */
+int
ioctl(p, uap, retval)
struct proc *p;
register struct ioctl_args *uap;
@@ -500,6 +506,7 @@ struct select_args {
struct timeval *tv;
};
+int
select(p, uap, retval)
register struct proc *p;
register struct select_args *uap;
@@ -605,6 +612,7 @@ selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval)
case 1:
flag = FWRITE; break;
+ default: /* pacify GCC */
case 2:
flag = 0; break;
}
@@ -630,14 +638,14 @@ selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval)
/*ARGSUSED*/
int
-seltrue(dev_t dev, int which, struct proc *p)
+seltrue(int /*dev_t*/ dev, int which, struct proc *p)
{
return (1);
}
void
-selwakeup(pid_t pid, int coll)
+selwakeup(int /*pid_t*/ pid, int coll)
{
register struct proc *p;
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index a0717fdc4e63..b129f4f4d5bd 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -31,23 +31,21 @@
* SUCH DAMAGE.
*
* from: @(#)sys_process.c 7.22 (Berkeley) 5/11/91
- * $Id: sys_process.c,v 1.5 1993/10/16 15:24:48 rgrimes Exp $
+ * $Id: sys_process.c,v 1.9.2.2 1994/05/03 20:44:01 rgrimes Exp $
*/
-#include <stddef.h>
-
-#define IPCREG
#include "param.h"
+#include "systm.h"
#include "proc.h"
#include "vnode.h"
#include "buf.h"
#include "ptrace.h"
-#include "machine/eflags.h"
#include "machine/reg.h"
#include "machine/psl.h"
#include "vm/vm.h"
#include "vm/vm_page.h"
+#include "vm/vm_kern.h"
#include "user.h"
@@ -76,30 +74,165 @@
#define SFTRC 0
#endif
-/*
- * `ipcreg' defined in <machine/reg.h>
- * Should we define a structure with all regs?
- */
-int sipcreg[NIPCREG] =
- { 0,0,sEDI,sESI,sEBP,sEBX,sEDX,sECX,sEAX,sEIP,sCS,sEFLAGS,sESP,sSS };
-
-struct {
- int flag;
-#define IPC_BUSY 1
-#define IPC_WANT 2
-#define IPC_DONE 4
- int req; /* copy of ptrace request */
- int *addr; /* copy of ptrace address */
- int data; /* copy of ptrace data */
- int error; /* errno from `procxmt' */
- int regs[NIPCREG]; /* PT_[GS]ETREG */
- caddr_t buf; /* PT_BREAD/WRITE */
- int buflen; /* " */
-} ipc;
+int
+pread (struct proc *procp, unsigned int addr, unsigned int *retval) {
+ int rv;
+ vm_map_t map, tmap;
+ vm_object_t object;
+ vm_offset_t kva = 0;
+ int page_offset; /* offset into page */
+ vm_offset_t pageno; /* page number */
+ vm_map_entry_t out_entry;
+ vm_prot_t out_prot;
+ boolean_t wired, single_use;
+ vm_offset_t off;
+
+ /* Map page into kernel space */
+
+ map = &procp->p_vmspace->vm_map;
+
+ page_offset = addr - trunc_page(addr);
+ pageno = trunc_page(addr);
+
+ tmap = map;
+ rv = vm_map_lookup (&tmap, pageno, VM_PROT_READ, &out_entry,
+ &object, &off, &out_prot, &wired, &single_use);
+
+ if (rv != KERN_SUCCESS)
+ return EINVAL;
+
+ vm_map_lookup_done (tmap, out_entry);
+
+ /* Find space in kernel_map for the page we're interested in */
+ rv = vm_map_find (kernel_map, object, off, &kva, PAGE_SIZE, 1);
+
+ if (!rv) {
+ vm_object_reference (object);
+
+ rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, 0);
+ if (!rv) {
+ *retval = 0;
+ bcopy ((caddr_t)(kva + page_offset), retval,
+ sizeof *retval);
+ }
+ vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
+ }
-/*
- * Process debugging system call.
- */
+ return rv;
+}
+
+int
+pwrite (struct proc *procp, unsigned int addr, unsigned int datum) {
+ int rv;
+ vm_map_t map, tmap;
+ vm_object_t object;
+ vm_offset_t kva = 0;
+ int page_offset; /* offset into page */
+ vm_offset_t pageno; /* page number */
+ vm_map_entry_t out_entry;
+ vm_prot_t out_prot;
+ boolean_t wired, single_use;
+ vm_offset_t off;
+ boolean_t fix_prot = 0;
+
+ /* Map page into kernel space */
+
+ map = &procp->p_vmspace->vm_map;
+
+ page_offset = addr - trunc_page(addr);
+ pageno = trunc_page(addr);
+
+ /*
+ * Check the permissions for the area we're interested in.
+ */
+
+ if (vm_map_check_protection (map, pageno, pageno + PAGE_SIZE,
+ VM_PROT_WRITE) == FALSE) {
+ /*
+ * If the page was not writable, we make it so.
+ * XXX It is possible a page may *not* be read/executable,
+ * if a process changes that!
+ */
+ fix_prot = 1;
+ /* The page isn't writable, so let's try making it so... */
+ if ((rv = vm_map_protect (map, pageno, pageno + PAGE_SIZE,
+ VM_PROT_ALL, 0)) != KERN_SUCCESS)
+ return EFAULT; /* I guess... */
+ }
+
+ /*
+ * Now we need to get the page. out_entry, out_prot, wired, and
+ * single_use aren't used. One would think the vm code would be
+ * a *bit* nicer... We use tmap because vm_map_lookup() can
+ * change the map argument.
+ */
+
+ tmap = map;
+ rv = vm_map_lookup (&tmap, pageno, VM_PROT_WRITE, &out_entry,
+ &object, &off, &out_prot, &wired, &single_use);
+ if (rv != KERN_SUCCESS) {
+ return EINVAL;
+ }
+
+ /*
+ * Okay, we've got the page. Let's release tmap.
+ */
+
+ vm_map_lookup_done (tmap, out_entry);
+
+ /*
+ * Fault the page-table-page in...
+ */
+ vm_map_pageable(map, trunc_page(vtopte(pageno)),
+ trunc_page(vtopte(pageno)) + NBPG, FALSE);
+ /*
+ * Fault the page in...
+ */
+
+ rv = vm_fault (map, pageno, VM_PROT_WRITE, FALSE);
+ if (rv != KERN_SUCCESS) {
+ /*
+ * release the page table page
+ */
+ vm_map_pageable(map, trunc_page(vtopte(pageno)),
+ trunc_page(vtopte(pageno)) + NBPG, TRUE);
+ return EFAULT;
+ }
+
+ /*
+ * The page may need to be faulted in again, it seems.
+ * This covers COW pages, I believe.
+ */
+
+ if (!rv)
+ rv = vm_fault (map, pageno, VM_PROT_WRITE, 0);
+
+ /* Find space in kernel_map for the page we're interested in */
+ rv = vm_map_find (kernel_map, object, off, (vm_offset_t *)&kva,
+ PAGE_SIZE, 1);
+
+ if (!rv) {
+ vm_object_reference (object);
+
+ rv = vm_map_pageable (kernel_map, kva, kva + PAGE_SIZE, FALSE);
+ if (!rv) {
+ bcopy (&datum, (caddr_t)(kva + page_offset), sizeof datum);
+ }
+ vm_map_remove (kernel_map, kva, kva + PAGE_SIZE);
+ }
+
+ if (fix_prot)
+ vm_map_protect (map, pageno, pageno + PAGE_SIZE,
+ VM_PROT_READ|VM_PROT_EXECUTE, 0);
+
+ /*
+ * release the page table page
+ */
+ vm_map_pageable(map, trunc_page(vtopte(pageno)),
+ trunc_page(vtopte(pageno)) + NBPG, TRUE);
+
+ return rv;
+}
struct ptrace_args {
int req;
@@ -108,6 +241,10 @@ struct ptrace_args {
int data;
};
+/*
+ * Process debugging system call.
+ */
+int
ptrace(curp, uap, retval)
struct proc *curp;
register struct ptrace_args *uap;
@@ -119,14 +256,13 @@ ptrace(curp, uap, retval)
*retval = 0;
if (uap->req == PT_TRACE_ME) {
curp->p_flag |= STRC;
- /*p->p_tptr = p->p_pptr; * What shall we do here ? */
return 0;
}
if ((p = pfind(uap->pid)) == NULL) {
return ESRCH;
}
-#ifdef notyet
+#ifdef PT_ATTACH
if (uap->req != PT_ATTACH && (
(p->p_flag & STRC) == 0 ||
(p->p_tptr && curp != p->p_tptr) ||
@@ -134,10 +270,25 @@ ptrace(curp, uap, retval)
return ESRCH;
#endif
-
-
#ifdef PT_ATTACH
+ if (uap->req != PT_ATTACH) {
+#endif
+ if ((p->p_flag & STRC) == 0)
+ return EPERM;
+ if (p->p_stat != SSTOP || (p->p_flag & SWTED) == 0)
+ return EBUSY;
+#ifdef PT_ATTACH
+ }
+#endif
+ /*
+ * XXX The PT_ATTACH code is completely broken. It will
+ * be obsoleted by a /proc filesystem, so is it worth it
+ * to fix it? (Answer, probably. So that'll be next,
+ * I guess.)
+ */
+
switch (uap->req) {
+#ifdef PT_ATTACH
case PT_ATTACH:
if (curp->p_ucred->cr_uid != 0 && (
curp->p_ucred->cr_uid != p->p_ucred->cr_uid ||
@@ -146,7 +297,7 @@ ptrace(curp, uap, retval)
p->p_tptr = curp;
p->p_flag |= STRC;
- psignal(p, SIGTRAP);
+ psignal(p, SIGSTOP);
return 0;
case PT_DETACH:
@@ -166,346 +317,100 @@ ptrace(curp, uap, retval)
splx(s);
return 0;
-#ifdef PT_INHERIT
+# ifdef PT_INHERIT
case PT_INHERIT:
if ((p->p_flag & STRC) == 0)
return ESRCH;
p->p_flag |= SFTRC;
return 0;
-#endif
-
- default:
- break;
- }
-#endif
-
- /* Other ptrace calls require target process to be in stopped state */
- if ((p->p_flag & STRC) == 0 || p->p_stat != SSTOP) {
- return ESRCH;
- }
-
- /* Acquire the ipc structure */
- while (ipc.flag & IPC_BUSY) {
- ipc.flag |= IPC_WANT;
- error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
- if (error)
- goto out;
- }
-
- /* Got it, fill it */
- ipc.flag = IPC_BUSY;
- ipc.error = 0;
- ipc.req = uap->req;
- ipc.addr = uap->addr;
- ipc.data = uap->data;
+# endif /* PT_INHERIT */
+#endif /* PT_ATTACH */
-#ifdef PT_GETREGS
- switch (uap->req) {
- case PT_SETREGS:
- error = copyin((char *)ipc.addr, (char *)ipc.regs, sizeof(ipc.regs));
- if (error)
- goto out;
- break;
-
-#ifdef notyet /* requires change in number of args to ptrace syscall */
- case PT_BWRITE_I:
- case PT_BWRITE_D:
- ipc.buflen = uap->data;
- ipc.buf = kmem_alloc_wait(kernelmap, uap->data);
- error = copyin((char *)ipc.addr, (char *)ipc.buf, ipc.buflen);
- if (error) {
- kmem_free_wakeup(kernelmap, ipc.buf, ipc.buflen);
- goto out;
- }
-#endif
- default:
- break;
- }
-#endif
-
- setrun(p);
- while ((ipc.flag & IPC_DONE) == 0) {
- error = tsleep((caddr_t)&ipc, PWAIT|PCATCH, "ipc", 0);
- if (error)
- goto out;
- }
-
- *retval = ipc.data;
- if (error = ipc.error)
- goto out;
-
-#ifdef PT_GETREGS
- switch (uap->req) {
- case PT_GETREGS:
- error = copyout((char *)ipc.regs, (char *)ipc.addr, sizeof(ipc.regs));
- break;
-
- case PT_BREAD_I:
- case PT_BREAD_D:
- /* Not yet */
- default:
- break;
- }
-#endif
-
-out:
- /* Release ipc structure */
- ipc.flag &= ~IPC_BUSY;
- if (ipc.flag & IPC_WANT) {
- ipc.flag &= ~IPC_WANT;
- wakeup((caddr_t)&ipc);
- }
- return error;
-}
-
-procxmt(p)
- register struct proc *p;
-{
- int i, *xreg, rv = 0;
-#ifdef i386
- int new_eflags, old_cs, old_ds, old_es, old_ss, old_eflags;
- int *regs;
-#endif
-
- /* Are we still being traced? */
- if ((p->p_flag & STRC) == 0)
- return 1;
-
- p->p_addr->u_kproc.kp_proc = *p;
- fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
-
- switch (ipc.req) {
case PT_READ_I:
case PT_READ_D:
- if (!useracc(ipc.addr, sizeof(ipc.data), B_READ)) {
- ipc.error = EFAULT;
- break;
- }
- ipc.error = copyin((char *)ipc.addr, (char *)&ipc.data, sizeof(ipc.data));
- break;
-
- case PT_READ_U:
- if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
- ipc.error = EFAULT;
- break;
- }
- ipc.data = *(int *)((u_int)p->p_addr + (u_int)ipc.addr);
- break;
-
+ if (error = pread (p, (unsigned int)uap->addr, retval))
+ return error;
+ return 0;
case PT_WRITE_I:
- case PT_WRITE_D: { /* 04 Sep 92*/
- vm_prot_t prot; /* current protection of region */
- int cow; /* ensure copy-on-write happens */
-
- if (cow = (useracc(ipc.addr, sizeof(ipc.data), B_WRITE) == 0)) {
- vm_offset_t addr = (vm_offset_t)ipc.addr;
- vm_size_t size;
- vm_prot_t max_prot;
- vm_inherit_t inh;
- boolean_t shared;
- vm_object_t object;
- vm_offset_t objoff;
-
- /*
- * XXX - the useracc check is stronger than the vm
- * checks because the user page tables are in the map.
- * Anyway, most of this can be removed now that COW
- * works.
- */
- if (!useracc(ipc.addr, sizeof(ipc.data), B_READ) ||
- vm_region(&p->p_vmspace->vm_map, &addr, &size,
- &prot, &max_prot, &inh, &shared,
- &object, &objoff) != KERN_SUCCESS ||
- vm_protect(&p->p_vmspace->vm_map, ipc.addr,
- sizeof(ipc.data), FALSE,
- prot|VM_PROT_WRITE) != KERN_SUCCESS ||
- vm_fault(&p->p_vmspace->vm_map,trunc_page(ipc.addr),
- VM_PROT_WRITE, FALSE) != KERN_SUCCESS) {
-
- ipc.error = EFAULT;
- break;
- }
- }
- ipc.error = copyout((char *)&ipc.data,
- (char *)ipc.addr, sizeof(ipc.data));
- if (cow)
- if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
- sizeof(ipc.data), FALSE,
- prot) != KERN_SUCCESS)
- printf("ptrace: oops\n");
- break;
- }
-
- case PT_WRITE_U:
-#ifdef i386
- regs = p->p_regs;
- /*
- * XXX - privileged kernel state is scattered all over the
- * user area. Only allow write access to areas known to
- * be safe.
- */
-#define GO_IF_SAFE(min, size) \
- if ((u_int)ipc.addr >= (min) \
- && (u_int)ipc.addr <= (min) + (size) - sizeof(int)) \
- goto pt_write_u
- /*
- * Allow writing entire FPU state.
- */
- GO_IF_SAFE(offsetof(struct user, u_pcb)
- + offsetof(struct pcb, pcb_savefpu),
- sizeof(struct save87));
- /*
- * Allow writing ordinary registers. Changes to segment
- * registers and to some bits in %eflags will be silently
- * ignored. Such changes ought to be an error.
- */
-/*
- * XXX - there is no define for the base of the user area except USRSTACK.
- * XXX - USRSTACK is not the base of the user stack. It is the base of the
- * user area.
- */
-#define USER_OFF(va) ((u_int)(va) - USRSTACK)
- GO_IF_SAFE(USER_OFF(regs),
- (curpcb->pcb_flags & FM_TRAP ? tSS + 1 : sSS + 1)
- * sizeof *regs);
- ipc.error = EFAULT;
- break;
-#else
- if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
- ipc.error = EFAULT;
- break;
- }
-#endif
- pt_write_u:
-#ifdef i386
- if (curpcb->pcb_flags & FM_TRAP) {
- old_cs = regs[tCS];
- old_ds = regs[tES];
- old_es = regs[tES];
- old_ss = regs[tSS];
- old_eflags = regs[tEFLAGS];
- } else {
- old_cs = regs[sCS];
- old_ss = regs[sSS];
- old_eflags = regs[sEFLAGS];
- }
-#endif
- *(int *)((u_int)p->p_addr + (u_int)ipc.addr) = ipc.data;
-#ifdef i386
+ case PT_WRITE_D:
+ if (error = pwrite (p, (unsigned int)uap->addr,
+ (unsigned int)uap->data))
+ return error;
+ return 0;
+ case PT_STEP:
+ if (error = ptrace_single_step (p))
+ return error;
+ /* fallthrough */
+ case PT_CONTINUE:
/*
- * Don't allow segment registers to change (although they can
- * be changed directly to certain values).
- * Don't allow privileged bits in %eflags to change. Users
- * have privilege to change TF and NT although although they
- * usually shouldn't.
- * XXX - fix PT_SETREGS.
- * XXX - simplify. Maybe copy through a temporary struct.
- * Watch out for problems when ipc.addr is not a multiple
- * of the register size.
+ * Continue at addr uap->addr with signal
+ * uap->data; if uap->addr is 1, then we just
+ * let the chips fall where they may.
+ *
+ * The only check I'll make right now is for
+ * uap->data to be larger than NSIG; if so, we return
+ * EINVAL.
*/
-#define EFL_UNPRIVILEGED (EFL_CF | EFL_PF | EFL_AF | EFL_ZF | EFL_SF \
- | EFL_TF | EFL_DF | EFL_OF | EFL_NT)
- if (curpcb->pcb_flags & FM_TRAP) {
- regs[tCS] = old_cs;
- regs[tDS] = old_ds;
- regs[tES] = old_es;
- regs[tSS] = old_es;
- new_eflags = regs[tEFLAGS];
- regs[tEFLAGS]
- = (new_eflags & EFL_UNPRIVILEGED)
- | (old_eflags & ~EFL_UNPRIVILEGED);
- } else {
- regs[sCS] = old_cs;
- regs[sSS] = old_ss;
- new_eflags = regs[sEFLAGS];
- regs[sEFLAGS]
- = (new_eflags & EFL_UNPRIVILEGED)
- | (old_eflags & ~EFL_UNPRIVILEGED);
- }
-#endif
- break;
+ if (uap->data >= NSIG)
+ return EINVAL;
- case PT_CONTINUE:
- if (ipc.addr != (int *)1) {
-#ifdef i386
- p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
-#endif
+ if (uap->addr != (int*)1) {
+ fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
+ if (error = ptrace_set_pc (p, uap->addr))
+ return error;
}
- p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
- if ((unsigned)ipc.data >= NSIG) {
- ipc.error = EINVAL;
- } else {
- p->p_xstat = ipc.data;
- rv = 1;
- }
- break;
- case PT_KILL:
- p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
- rv = 2;
- break;
+ p->p_xstat = uap->data;
- case PT_STEP:
-#ifdef i386
- if (ipc.addr != (int *)1) {
- p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
+/* if (p->p_stat == SSTOP) */
+ setrun (p);
+ return 0;
+ case PT_READ_U:
+ if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
+ return EFAULT;
}
- p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEFLAGS:sEFLAGS] |= PSL_T;
-#endif
- p->p_flag &= ~SSTRC; /* Only set by PT_SYSCALL */
- p->p_xstat = 0;
- rv = 1;
- break;
-
-#ifdef PT_SYSCALL
- case PT_SYSCALL:
- if (ipc.addr != (int *)1) {
-#ifdef i386
- p->p_regs[(curpcb->pcb_flags&FM_TRAP)?tEIP:sEIP] = (int)ipc.addr;
-#endif
+ p->p_addr->u_kproc.kp_proc = *p;
+ fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
+ *retval = *(int*)((u_int)p->p_addr + (u_int)uap->addr);
+ return 0;
+ case PT_WRITE_U:
+ if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
+ return EFAULT;
}
- p->p_flag |= SSTRC;
- p->p_xstat = 0;
- rv = 1;
- break;
-#endif
+ p->p_addr->u_kproc.kp_proc = *p;
+ fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
+ *(int*)((u_int)p->p_addr + (u_int)uap->addr) = uap->data;
+ return 0;
+ case PT_KILL:
+ p->p_xstat = SIGKILL;
+ setrun(p);
+ return 0;
#ifdef PT_GETREGS
case PT_GETREGS:
-#ifdef i386
- xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
-#endif
-
- for (i = 0; i < NIPCREG; i++)
- ipc.regs[i] = p->p_regs[xreg[i]];
- break;
-
+ /*
+ * copyout the registers into addr. There's no
+ * size constraint!!! *GRRR*
+ */
+ return ptrace_getregs(p, uap->addr);
case PT_SETREGS:
-#ifdef i386
- xreg = (curpcb->pcb_flags&FM_TRAP)?ipcreg:sipcreg;
-#endif
-
- for (i = 0; i < NIPCREG; i++)
- p->p_regs[xreg[i]] = ipc.regs[i];
- break;
-#endif
-
-#ifdef PT_DUMP
- case PT_DUMP:
- /* Should be able to specify core file name */
- ipc.error = coredump(p);
- break;
-#endif
-
+ /*
+ * copyin the registers from addr. Again, no
+ * size constraint!!! *GRRRR*
+ */
+ return ptrace_setregs (p, uap->addr);
+#endif /* PT_GETREGS */
default:
- ipc.error = EINVAL;
+ break;
}
- ipc.flag |= IPC_DONE;
- wakeup((caddr_t)&ipc);
- if (rv == 2)
- kexit(p, 0); /*???*/
+ return 0;
+}
- return rv;
+int
+procxmt(p)
+ register struct proc *p;
+{
+ return 1;
}
/*
@@ -520,6 +425,7 @@ struct profil_args {
};
/* ARGSUSED */
+int
profil(p, uap, retval)
struct proc *p;
register struct profil_args *uap;
@@ -539,9 +445,14 @@ profil(p, uap, retval)
*
* so we've gotta check to make sure that the info set up for
* addupc is set right... it's gotta be writable by the user...
+ *
+ * Add a little extra sanity checking so that end profil requests
+ * don't generate spurious faults. -jkh
*/
- if (useracc(uap->bufbase,uap->bufsize*sizeof(short),B_WRITE) == 0)
+ if (uap->bufbase && uap->bufsize &&
+ useracc((caddr_t)uap->bufbase, uap->bufsize * sizeof(short),
+ B_WRITE) == 0)
return EFAULT;
p->p_stats->p_prof.pr_base = uap->bufbase;
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 247dbc9a2a59..3d59f7fc3f77 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)sys_socket.c 7.11 (Berkeley) 4/16/91
- * $Id: sys_socket.c,v 1.2 1993/10/16 15:24:50 rgrimes Exp $
+ * $Id: sys_socket.c,v 1.4 1993/12/19 00:51:36 wollman Exp $
*/
#include "param.h"
@@ -51,6 +51,7 @@ struct fileops socketops =
{ soo_read, soo_write, soo_ioctl, soo_select, soo_close };
/* ARGSUSED */
+int
soo_read(fp, uio, cred)
struct file *fp;
struct uio *uio;
@@ -62,6 +63,7 @@ soo_read(fp, uio, cred)
}
/* ARGSUSED */
+int
soo_write(fp, uio, cred)
struct file *fp;
struct uio *uio;
@@ -72,6 +74,7 @@ soo_write(fp, uio, cred)
uio, (struct mbuf *)0, (struct mbuf *)0, 0));
}
+int
soo_ioctl(fp, cmd, data, p)
struct file *fp;
int cmd;
@@ -127,9 +130,11 @@ soo_ioctl(fp, cmd, data, p)
if (IOCGROUP(cmd) == 'r')
return (rtioctl(cmd, data, p));
return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
- (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0));
+ (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)0,
+ (struct mbuf *)0));
}
+int
soo_select(fp, which, p)
struct file *fp;
int which;
@@ -169,6 +174,7 @@ soo_select(fp, which, p)
return (0);
}
+int
soo_stat(so, ub)
register struct socket *so;
register struct stat *ub;
@@ -177,10 +183,11 @@ soo_stat(so, ub)
bzero((caddr_t)ub, sizeof (*ub));
return ((*so->so_proto->pr_usrreq)(so, PRU_SENSE,
(struct mbuf *)ub, (struct mbuf *)0,
- (struct mbuf *)0));
+ (struct mbuf *)0, (struct mbuf *)0));
}
/* ARGSUSED */
+int
soo_close(fp, p)
struct file *fp;
struct proc *p;
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index 4fe1c433549c..2f624acebcf7 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -2,7 +2,7 @@
* System call names.
*
* DO NOT EDIT-- this file is automatically generated.
- * created from $Id: syscalls.master,v 1.5 1993/10/24 06:19:58 paul Exp $
+ * created from $Id: syscalls.master,v 1.8 1994/01/31 10:27:25 davidg Exp $
*/
char *syscallnames[] = {
@@ -196,12 +196,20 @@ char *syscallnames[] = {
"getdomainname", /* 162 = getdomainname */
"setdomainname", /* 163 = setdomainname */
"uname", /* 164 = uname */
- "#165", /* 165 = nosys */
+ "sysarch", /* 165 = sysarch */
"#166", /* 166 = nosys */
"#167", /* 167 = nosys */
"#168", /* 168 = nosys */
+#ifdef SYSVSEM
+ "semsys", /* 169 = semsys */
+#else
"#169", /* 169 = nosys */
+#endif
+#ifdef SYSVMSG
+ "msgsys", /* 170 = msgsys */
+#else
"#170", /* 170 = nosys */
+#endif
#ifdef SYSVSHM
"shmsys", /* 171 = shmsys */
#else
@@ -212,10 +220,17 @@ char *syscallnames[] = {
"#174", /* 174 = nosys */
"#175", /* 175 = nosys */
"#176", /* 176 = nosys */
+#ifdef MACHVMCOMPAT
+ "vm_allocate", /* 177 = vm_allocate */
+ "vm_deallocate", /* 178 = vm_deallocate */
+ "vm_inherit", /* 179 = vm_inherit */
+ "vm_protect", /* 180 = vm_protect */
+#else
"#177", /* 177 = nosys */
"#178", /* 178 = nosys */
"#179", /* 179 = nosys */
"#180", /* 180 = nosys */
+#endif
"setgid", /* 181 = setgid */
"setegid", /* 182 = setegid */
"seteuid", /* 183 = seteuid */
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index f7470cccbd84..a43845ebd1a4 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
- $Id: syscalls.master,v 1.5 1993/10/24 06:19:58 paul Exp $
+ $Id: syscalls.master,v 1.8 1994/01/31 10:27:25 davidg Exp $
; from: @(#)syscalls.master 7.26 (Berkeley) 3/25/91
; System call name/number master file.
; Processed to created init_sysent.c, syscalls.c and syscall.h.
@@ -221,12 +221,20 @@
162 STD 2 getdomainname
163 STD 2 setdomainname
164 STD 1 uname
-165 UNIMPL 0 nosys
+165 STD 2 sysarch
166 UNIMPL 0 nosys
167 UNIMPL 0 nosys
168 UNIMPL 0 nosys
+#ifdef SYSVSEM
+169 STD 5 semsys
+#else
169 UNIMPL 0 nosys
+#endif
+#ifdef SYSVMSG
+170 STD 6 msgsys
+#else
170 UNIMPL 0 nosys
+#endif
#ifdef SYSVSHM
171 STD 4 shmsys
#else
@@ -237,10 +245,17 @@
174 UNIMPL 0 nosys
175 UNIMPL 0 nosys
176 UNIMPL 0 nosys
+#ifdef MACHVMCOMPAT
+177 STD 4 svm_allocate vm_allocate
+178 STD 3 svm_deallocate vm_deallocate
+179 STD 4 svm_inherit vm_inherit
+180 STD 5 svm_protect vm_protect
+#else
177 UNIMPL 0 nosys
178 UNIMPL 0 nosys
179 UNIMPL 0 nosys
180 UNIMPL 0 nosys
+#endif
; Syscalls 180-199 are used by/reserved for BSD
181 STD 1 setgid
diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c
new file mode 100644
index 000000000000..767c1d9ff19b
--- /dev/null
+++ b/sys/kern/sysv_ipc.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department. Originally from University of Wisconsin.
+ *
+ * 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 REGENTS 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.
+ *
+ * from: Utah $Hdr: uipc_shm.c 1.9 89/08/14$
+ *
+ * @(#)sysv_shm.c 7.15 (Berkeley) 5/13/91
+ */
+
+/*
+ * IPC routines shared by some or all of the SYSV IPC system calls.
+ */
+
+#ifndef SYSVIPC
+
+#ifdef SYSVSHM
+#define SYSVIPC
+#endif
+
+#ifdef SYSVSEM
+#define SYSVIPC
+#endif
+
+#ifdef SYSVMSG
+#define SYSVIPC
+#endif
+
+#endif
+
+#ifdef SYSVIPC
+
+#include "param.h"
+#include "systm.h"
+#include "kernel.h"
+#include "proc.h"
+#include "ipc.h"
+#include "shm.h"
+
+/*
+ * Perform access checking.
+ */
+
+int
+ipcaccess(ipc, mode, cred)
+ register struct ipc_perm *ipc;
+ int mode;
+ register struct ucred *cred;
+{
+ register int m;
+
+ if (cred->cr_uid == 0)
+ return(0);
+ /*
+ * 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.
+ */
+ mode &= 0700;
+ m = ipc->mode;
+ if (cred->cr_uid != ipc->uid && cred->cr_uid != ipc->cuid) {
+ m <<= 3;
+ if (!groupmember(ipc->gid, cred) &&
+ !groupmember(ipc->cgid, cred))
+ m <<= 3;
+ }
+ if ((mode&m) == mode)
+ return (0);
+ return (EACCES);
+}
+#endif /* SYSVSHM */
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
new file mode 100644
index 000000000000..f861f53ece52
--- /dev/null
+++ b/sys/kern/sysv_msg.c
@@ -0,0 +1,1038 @@
+/*
+ * Implementation of SVID messages
+ *
+ * Author: Daniel Boulet
+ *
+ * Copyright 1993 Daniel Boulet and RTMX Inc.
+ *
+ * This system call was implemented by Daniel Boulet under contract from RTMX.
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ */
+
+#ifdef SYSVMSG
+
+#include "param.h"
+#include "systm.h"
+#include "kernel.h"
+#include "proc.h"
+#include "msg.h"
+#include "malloc.h"
+
+static int msgctl(), msgget(), msgsnd(), msgrcv();
+
+int (*msgcalls[])() = { msgctl, msgget, msgsnd, msgrcv };
+
+int nfree_msgmaps; /* # of free map entries */
+short free_msgmaps; /* head of linked list of free map entries */
+struct msg *free_msghdrs; /* list of free msg headers */
+
+void
+msginit()
+{
+ register int i;
+ vm_offset_t whocares1, whocares2;
+
+ /*
+ * msginfo.msgssz should be a power of two for efficiency reasons.
+ * It is also pretty silly if msginfo.msgssz is less than 8
+ * or greater than about 256 so ...
+ */
+
+ i = 8;
+ while ( i < 1024 && i != msginfo.msgssz ) {
+ i <<= 1;
+ }
+ if ( i != msginfo.msgssz ) {
+ printf("msginfo.msgssz=%d (0x%x)\n",msginfo.msgssz,msginfo.msgssz);
+ panic("msginfo.msgssz not a small power of 2");
+ }
+
+ if ( msginfo.msgseg > 32767 ) {
+ printf("msginfo.msgseg=%d\n",msginfo.msgseg);
+ panic("msginfo.msgseg > 32767");
+ }
+
+ if ( msgmaps == NULL ) {
+ panic("msgmaps is NULL");
+ }
+ for ( i = 0; i < msginfo.msgseg; i += 1 ) {
+ if ( i > 0 ) {
+ msgmaps[i-1].next = i;
+ }
+ msgmaps[i].next = -1; /* implies entry is available */
+ }
+ free_msgmaps = 0;
+ nfree_msgmaps = msginfo.msgseg;
+
+ if ( msghdrs == NULL ) {
+ panic("msghdrs is NULL");
+ }
+ for ( i = 0; i < msginfo.msgtql; i += 1 ) {
+ msghdrs[i].msg_type = 0;
+ if ( i > 0 ) {
+ msghdrs[i-1].msg_next = &msghdrs[i];
+ }
+ msghdrs[i].msg_next = NULL;
+ }
+ free_msghdrs = &msghdrs[0];
+
+ if ( msqids == NULL ) {
+ panic("msqids is NULL");
+ }
+ for ( i = 0; i < msginfo.msgmni; i += 1 ) {
+ msqids[i].msg_qbytes = 0; /* implies entry is available */
+ msqids[i].msg_perm.seq = 0; /* reset to a known value */
+ }
+
+}
+
+TEXT_SET(pseudo_set, msginit);
+
+/*
+ * Entry point for all MSG calls
+ */
+
+struct msgsys_args {
+ u_int which;
+};
+
+int
+msgsys(p, uap, retval)
+ struct caller *p;
+ struct msgsys_args *uap;
+ int *retval;
+{
+ if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0]))
+ return (EINVAL);
+ return ((*msgcalls[uap->which])(p, &uap[1], retval));
+}
+
+static
+void
+msg_freehdr(msghdr)
+struct msg *msghdr;
+{
+ while ( msghdr->msg_ts > 0 ) {
+ short next;
+ if ( msghdr->msg_spot < 0 || msghdr->msg_spot >= msginfo.msgseg ) {
+ panic("msghdr->msg_spot out of range");
+ }
+ next = msgmaps[msghdr->msg_spot].next;
+ msgmaps[msghdr->msg_spot].next = free_msgmaps;
+ free_msgmaps = msghdr->msg_spot;
+ nfree_msgmaps += 1;
+ msghdr->msg_spot = next;
+ if ( msghdr->msg_ts >= msginfo.msgssz ) {
+ msghdr->msg_ts -= msginfo.msgssz;
+ } else {
+ msghdr->msg_ts = 0;
+ }
+ }
+ if ( msghdr->msg_spot != -1 ) {
+ panic("msghdr->msg_spot != -1");
+ }
+ msghdr->msg_next = free_msghdrs;
+ free_msghdrs = msghdr;
+}
+
+struct msgctl_args {
+ int msqid;
+ int cmd;
+ struct msqid_ds *user_msqptr;
+};
+
+int
+msgctl(p, uap, retval)
+ struct proc *p;
+ register struct msgctl_args *uap;
+ int *retval;
+{
+ int msqid = uap->msqid;
+ int cmd = uap->cmd;
+ struct msqid_ds *user_msqptr = uap->user_msqptr;
+ struct ucred *cred = p->p_ucred;
+ int i, rval, eval;
+ struct msqid_ds msqbuf;
+ register struct msqid_ds *msqptr;
+
+#ifdef MSG_DEBUG
+ printf("call to msgctl(%d,%d,0x%x)\n",msqid,cmd,user_msqptr);
+#endif
+
+ msqid = IPCID_TO_IX(msqid);
+
+ if ( msqid < 0 || msqid >= msginfo.msgmni ) {
+#ifdef MSG_DEBUG
+ printf("msqid (%d) out of range (0<=msqid<%d)\n",msqid,msginfo.msgmni);
+#endif
+ return(EINVAL);
+ }
+
+ msqptr = &msqids[msqid];
+
+ if ( msqptr->msg_qbytes == 0 ) {
+#ifdef MSG_DEBUG
+ printf("no such msqid\n");
+#endif
+ return(EINVAL);
+ }
+ if ( msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid) ) {
+#ifdef MSG_DEBUG
+ printf("wrong sequence number\n");
+#endif
+ return(EINVAL);
+ }
+
+ eval = 0;
+ rval = 0;
+
+ switch (cmd) {
+
+ case IPC_RMID:
+#ifdef MSG_DEBUG
+ printf("IPC_RMID\n");
+#endif
+ {
+ struct msg *msghdr;
+
+ if ( cred->cr_uid != 0
+ && msqptr->msg_perm.cuid != cred->cr_uid
+ && msqptr->msg_perm.uid != cred->cr_uid ) {
+ return(EPERM);
+ }
+ msghdr = msqptr->msg_first;
+
+ /* Free the message headers */
+
+ while ( msghdr != NULL ) {
+ struct msg *msghdr_tmp;
+
+ /* Free the segments of each message */
+
+ msqptr->msg_cbytes -= msghdr->msg_ts;
+ msqptr->msg_qnum -= 1;
+ msghdr_tmp = msghdr;
+ msghdr = msghdr->msg_next;
+ msg_freehdr(msghdr_tmp);
+
+ }
+
+ if ( msqptr->msg_cbytes != 0 ) {
+ panic("msg_cbytes is screwed up");
+ }
+ if ( msqptr->msg_qnum != 0 ) {
+ panic("msg_qnum is screwed up");
+ }
+
+ msqptr->msg_qbytes = 0; /* Mark it as free */
+
+ /* Make sure that anybody who is waiting notices the deletion */
+
+ wakeup( (caddr_t)msqptr );
+ }
+
+ break;
+
+ case IPC_SET:
+#ifdef MSG_DEBUG
+ printf("IPC_SET\n");
+#endif
+ if ( cred->cr_uid != 0
+ && msqptr->msg_perm.cuid != cred->cr_uid
+ && msqptr->msg_perm.uid != cred->cr_uid ) {
+ return(EPERM);
+ }
+ if ( (eval = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0 ) {
+ return(eval);
+ }
+ if ( msqbuf.msg_qbytes > msqptr->msg_qbytes
+ && cred->cr_uid != 0 ) {
+ return(EPERM);
+ }
+ if ( msqbuf.msg_qbytes > msginfo.msgmnb ) {
+#ifdef MSG_DEBUG
+ printf("can't increase msg_qbytes beyond %d (truncating)\n",msginfo.msgmnb);
+#endif
+ msqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */
+ }
+ if ( msqbuf.msg_qbytes == 0 ) {
+#ifdef MSG_DEBUG
+ printf("can't reduce msg_qbytes to 0\n");
+#endif
+ return(EINVAL); /* non-standard errno! */
+ }
+ msqptr->msg_perm.uid = msqbuf.msg_perm.uid; /* change the owner */
+ msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */
+ msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777)
+ | (msqbuf.msg_perm.mode & 0777);
+ msqptr->msg_qbytes = msqbuf.msg_qbytes;
+ msqptr->msg_ctime = time.tv_sec;
+ break;
+
+ case IPC_STAT:
+#ifdef MSG_DEBUG
+ printf("IPC_STAT\n");
+#endif
+ if ( (eval = ipcaccess(&msqptr->msg_perm, IPC_R, cred)) ) {
+#ifdef MSG_DEBUG
+ printf("requester doesn't have read access\n");
+#endif
+ return(eval);
+ }
+ rval = 0;
+ eval = copyout((caddr_t)msqptr, user_msqptr, sizeof(struct msqid_ds));
+ break;
+
+ default:
+#ifdef MSG_DEBUG
+ printf("invalid command %d\n",cmd);
+#endif
+ return(EINVAL);
+ }
+
+ if ( eval == 0 ) {
+ *retval = rval;
+ }
+ return(eval);
+}
+
+struct msgget_args {
+ key_t key;
+ int msgflg;
+};
+
+int
+msgget(p, uap, retval)
+ struct proc *p;
+ register struct msgget_args *uap;
+ int *retval;
+{
+ int msqid, eval;
+ int key = uap->key;
+ int msgflg = uap->msgflg;
+ struct ucred *cred = p->p_ucred;
+ register struct msqid_ds *msqptr = NULL;
+
+#ifdef MSG_DEBUG
+ printf("msgget(0x%x,0%o)\n",key,msgflg);
+#endif
+
+ if ( key == IPC_PRIVATE ) {
+#ifdef MSG_DEBUG
+ printf("private key\n");
+#endif
+ msqid = msginfo.msgmni;
+ } else {
+ for ( msqid = 0; msqid < msginfo.msgmni; msqid += 1 ) {
+ msqptr = &msqids[msqid];
+ if ( msqptr->msg_qbytes != 0 && msqptr->msg_perm.key == key ) {
+ break;
+ }
+ }
+ if ( msqid < msginfo.msgmni ) {
+#ifdef MSG_DEBUG
+ printf("found public key\n");
+#endif
+ if ( (msgflg & IPC_CREAT) && (msgflg & IPC_EXCL) ) {
+#ifdef MSG_DEBUG
+ printf("not exclusive\n");
+#endif
+ return(EEXIST);
+ }
+ if ( (eval = ipcaccess(&msqptr->msg_perm, msgflg & 0700, cred)) ) {
+#ifdef MSG_DEBUG
+ printf("requester doesn't have 0%o access\n",msgflg & 0700);
+#endif
+ return(eval);
+ }
+ } else {
+#ifdef MSG_DEBUG
+ printf("didn't find public key\n");
+#endif
+ }
+ }
+
+ if ( msqid == msginfo.msgmni ) {
+#ifdef MSG_DEBUG
+ printf("need to allocate the msqid_ds\n");
+#endif
+ if ( key == IPC_PRIVATE || (msgflg & IPC_CREAT) ) {
+ for ( msqid = 0; msqid < msginfo.msgmni; msqid += 1 ) {
+ /*
+ * Look for an unallocated and unlocked msqid_ds.
+ * msqid_ds's can be locked by msgsnd or msgrcv while they
+ * are copying the message in/out. We can't re-use the
+ * entry until they release it.
+ */
+
+ msqptr = &msqids[msqid];
+ if ( msqptr->msg_qbytes == 0
+ && (msqptr->msg_perm.mode & MSG_LOCKED) == 0 ) {
+ break;
+ }
+ }
+ if ( msqid == msginfo.msgmni ) {
+#ifdef MSG_DEBUG
+ printf("no more msqid_ds's available\n");
+#endif
+ return(ENOSPC);
+ }
+#ifdef MSG_DEBUG
+ printf("msqid %d is available\n",msqid+1);
+#endif
+ msqptr->msg_perm.key = key;
+ msqptr->msg_perm.cuid = cred->cr_uid;
+ msqptr->msg_perm.uid = cred->cr_uid;
+ msqptr->msg_perm.cgid = cred->cr_gid;
+ msqptr->msg_perm.gid = cred->cr_gid;
+ msqptr->msg_perm.mode = (msgflg & 0777);
+ msqptr->msg_perm.seq += 1; /* Make sure that the returned msqid is unique */
+ msqptr->msg_first = NULL;
+ msqptr->msg_last = NULL;
+ msqptr->msg_cbytes = 0;
+ msqptr->msg_qnum = 0;
+ msqptr->msg_qbytes = msginfo.msgmnb;
+ msqptr->msg_lspid = 0;
+ msqptr->msg_lrpid = 0;
+ msqptr->msg_stime = 0;
+ msqptr->msg_rtime = 0;
+ msqptr->msg_ctime = time.tv_sec;
+ } else {
+#ifdef MSG_DEBUG
+ printf("didn't find it and wasn't asked to create it\n");
+#endif
+ return(ENOENT);
+ }
+ }
+
+ *retval = IXSEQ_TO_IPCID(msqid,msqptr->msg_perm); /* Construct the unique msqid */
+ return(0);
+}
+
+struct msgsnd_args {
+ int msqid;
+ void *user_msgp;
+ size_t msgsz;
+ int msgflg;
+};
+
+int
+msgsnd(p, uap, retval)
+ struct proc *p;
+ register struct msgsnd_args *uap;
+ int *retval;
+{
+ int msqid = uap->msqid;
+ void *user_msgp = uap->user_msgp;
+ size_t msgsz = uap->msgsz;
+ int msgflg = uap->msgflg;
+ int segs_needed, eval;
+ struct ucred *cred = p->p_ucred;
+ register struct msqid_ds *msqptr;
+ register struct msg *msghdr;
+ short next;
+
+#ifdef MSG_DEBUG
+ printf("call to msgsnd(%d,0x%x,%d,%d)\n",msqid,user_msgp,msgsz,msgflg);
+#endif
+
+ msqid = IPCID_TO_IX(msqid);
+
+ if ( msqid < 0 || msqid >= msginfo.msgmni ) {
+#ifdef MSG_DEBUG
+ printf("msqid (%d) out of range (0<=msqid<%d)\n",msqid,msginfo.msgmni);
+#endif
+ return(EINVAL);
+ }
+
+ msqptr = &msqids[msqid];
+ if ( msqptr->msg_qbytes == 0 ) {
+#ifdef MSG_DEBUG
+ printf("no such message queue id\n");
+#endif
+ return(EINVAL);
+ }
+ if ( msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid) ) {
+#ifdef MSG_DEBUG
+ printf("wrong sequence number\n");
+#endif
+ return(EINVAL);
+ }
+
+ if ( (eval = ipcaccess(&msqptr->msg_perm, IPC_W, cred)) ) {
+#ifdef MSG_DEBUG
+ printf("requester doesn't have write access\n");
+#endif
+ return(eval);
+ }
+
+ segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
+#ifdef MSG_DEBUG
+ printf("msgsz=%d, msgssz=%d, segs_needed=%d\n",msgsz,msginfo.msgssz,segs_needed);
+#endif
+ while ( 1 ) {
+ int need_more_resources = 0;
+
+ /*
+ * check msgsz
+ * (inside this loop in case msg_qbytes changes while we sleep)
+ */
+
+ if ( msgsz > msqptr->msg_qbytes ) {
+#ifdef MSG_DEBUG
+ printf("msgsz > msqptr->msg_qbytes\n");
+#endif
+ return(EINVAL);
+ }
+
+ if ( msqptr->msg_perm.mode & MSG_LOCKED ) {
+#ifdef MSG_DEBUG
+ printf("msqid is locked\n");
+#endif
+ need_more_resources = 1;
+ }
+ if ( msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes ) {
+#ifdef MSG_DEBUG
+ printf("msgsz + msg_cbytes > msg_qbytes\n");
+#endif
+ need_more_resources = 1;
+ }
+ if ( segs_needed > nfree_msgmaps ) {
+#ifdef MSG_DEBUG
+ printf("segs_needed > nfree_msgmaps\n");
+#endif
+ need_more_resources = 1;
+ }
+ if ( free_msghdrs == NULL ) {
+#ifdef MSG_DEBUG
+ printf("no more msghdrs\n");
+#endif
+ need_more_resources = 1;
+ }
+
+ if ( need_more_resources ) {
+
+ int we_own_it;
+
+ if ( (msgflg & IPC_NOWAIT) != 0 ) {
+#ifdef MSG_DEBUG
+ printf("need more resources but caller doesn't want to wait\n");
+#endif
+ return(EAGAIN);
+ }
+
+ if ( (msqptr->msg_perm.mode & MSG_LOCKED) != 0 ) {
+#ifdef MSG_DEBUG
+ printf("we don't own the msqid_ds\n");
+#endif
+ we_own_it = 0;
+ } else {
+ /* Force later arrivals to wait for our request */
+#ifdef MSG_DEBUG
+ printf("we own the msqid_ds\n");
+#endif
+ msqptr->msg_perm.mode |= MSG_LOCKED;
+ we_own_it = 1;
+ }
+#ifdef MSG_DEBUG
+ printf("goodnight\n");
+#endif
+ eval = tsleep( (caddr_t)msqptr, (PZERO - 4) | PCATCH, "msg wait", 0 );
+#ifdef MSG_DEBUG
+ printf("good morning, eval=%d\n",eval);
+#endif
+ if ( we_own_it ) {
+ msqptr->msg_perm.mode &= ~MSG_LOCKED;
+ }
+ if ( eval != 0 ) {
+#ifdef MSG_DEBUG
+ printf("msgsnd: interrupted system call\n");
+#endif
+ return( EINTR );
+ }
+
+ /*
+ * Make sure that the msq queue still exists
+ */
+
+ if ( msqptr->msg_qbytes == 0 ) {
+#ifdef MSG_DEBUG
+ printf("msqid deleted\n");
+#endif
+ /* The SVID says to return EIDRM. */
+#ifdef EIDRM
+ return(EIDRM);
+#else
+ /* Unfortunately, BSD doesn't define that code (yet)! */
+ return(EINVAL);
+#endif
+ }
+
+ } else {
+#ifdef MSG_DEBUG
+ printf("got all the resources that we need\n");
+#endif
+ break;
+ }
+
+ }
+
+ /*
+ * We have the resources that we need.
+ * Make sure!
+ */
+
+ if ( msqptr->msg_perm.mode & MSG_LOCKED ) {
+ panic("msg_perm.mode & MSG_LOCKED"); /* bug somewhere */
+ }
+ if ( segs_needed > nfree_msgmaps ) {
+ panic("segs_needed > nfree_msgmaps"); /* bug somewhere */
+ }
+ if ( msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes ) {
+ panic("msgsz + msg_cbytes > msg_qbytes"); /* bug somewhere */
+ }
+ if ( free_msghdrs == NULL ) {
+ panic("no more msghdrs"); /* bug somewhere */
+ }
+
+ /*
+ * Re-lock the msqid_ds in case we page-fault when copying in the message
+ */
+
+ if ( (msqptr->msg_perm.mode & MSG_LOCKED) != 0 ) {
+ panic("msqid_ds is already locked");
+ }
+ msqptr->msg_perm.mode |= MSG_LOCKED;
+
+ /*
+ * Allocate a message header
+ */
+
+ msghdr = free_msghdrs;
+ free_msghdrs = msghdr->msg_next;
+ msghdr->msg_spot = -1;
+ msghdr->msg_ts = msgsz;
+
+ /*
+ * Allocate space for the message
+ */
+
+ while ( segs_needed > 0 ) {
+ if ( nfree_msgmaps <= 0 ) {
+ panic("not enough msgmaps");
+ }
+ if ( free_msgmaps == -1 ) {
+ panic("nil free_msgmaps");
+ }
+ next = free_msgmaps;
+ if ( next <= -1 ) {
+ panic("next too low #1");
+ }
+ if ( next >= msginfo.msgseg ) {
+ panic("next out of range #1");
+ }
+#ifdef MSG_DEBUG
+ printf("allocating segment %d to message\n",next);
+#endif
+ free_msgmaps = msgmaps[next].next;
+ nfree_msgmaps -= 1;
+ msgmaps[next].next = msghdr->msg_spot;
+ msghdr->msg_spot = next;
+ segs_needed -= 1;
+ }
+
+ /*
+ * Copy in the message type
+ */
+
+ if ( (eval = copyin(user_msgp,&msghdr->msg_type,sizeof(msghdr->msg_type))) != 0 ) {
+#ifdef MSG_DEBUG
+ printf("error %d copying the message type\n",eval);
+#endif
+ msg_freehdr(msghdr);
+ msqptr->msg_perm.mode &= ~MSG_LOCKED;
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ return(eval);
+ }
+ user_msgp += sizeof(msghdr->msg_type);
+
+ /*
+ * Validate the message type
+ */
+
+ if ( msghdr->msg_type < 1 ) {
+ msg_freehdr(msghdr);
+ msqptr->msg_perm.mode &= ~MSG_LOCKED;
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+#ifdef MSG_DEBUG
+ printf("mtype (%d) < 1\n",msghdr->msg_type);
+#endif
+ return(EINVAL);
+ }
+
+ /*
+ * Copy in the message body
+ */
+
+ next = msghdr->msg_spot;
+ while ( msgsz > 0 ) {
+ size_t tlen;
+ if ( msgsz > msginfo.msgssz ) {
+ tlen = msginfo.msgssz;
+ } else {
+ tlen = msgsz;
+ }
+ if ( next <= -1 ) {
+ panic("next too low #2");
+ }
+ if ( next >= msginfo.msgseg ) {
+ panic("next out of range #2");
+ }
+ if ( (eval = copyin(user_msgp, &msgpool[next * msginfo.msgssz], tlen)) != 0 ) {
+#ifdef MSG_DEBUG
+ printf("error %d copying in message segment\n",eval);
+#endif
+ msg_freehdr(msghdr);
+ msqptr->msg_perm.mode &= ~MSG_LOCKED;
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ return(eval);
+ }
+ msgsz -= tlen;
+ user_msgp += tlen;
+ next = msgmaps[next].next;
+ }
+ if ( next != -1 ) {
+ panic("didn't use all the msg segments");
+ }
+
+ /*
+ * We've got the message. Unlock the msqid_ds.
+ */
+
+ msqptr->msg_perm.mode &= ~MSG_LOCKED;
+
+ /*
+ * Make sure that the msqid_ds is still allocated.
+ */
+
+ if ( msqptr->msg_qbytes == 0 ) {
+ msg_freehdr(msghdr);
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ /* The SVID says to return EIDRM. */
+#ifdef EIDRM
+ return(EIDRM);
+#else
+ /* Unfortunately, BSD doesn't define that code (yet)! */
+ return(EINVAL);
+#endif
+ }
+
+ /*
+ * Put the message into the queue
+ */
+
+ if ( msqptr->msg_first == NULL ) {
+ msqptr->msg_first = msghdr;
+ msqptr->msg_last = msghdr;
+ } else {
+ msqptr->msg_last->msg_next = msghdr;
+ msqptr->msg_last = msghdr;
+ }
+ msqptr->msg_last->msg_next = NULL;
+
+ msqptr->msg_cbytes += msghdr->msg_ts;
+ msqptr->msg_qnum += 1;
+ msqptr->msg_lspid = p->p_pid;
+ msqptr->msg_stime = time.tv_sec;
+
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ *retval = 0;
+ return(0);
+}
+
+struct msgrcv_args {
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ long msgtyp;
+ int msgflg;
+};
+
+int
+msgrcv(p, uap, retval)
+ struct proc *p;
+ register struct msgrcv_args *uap;
+ int *retval;
+{
+ int msqid = uap->msqid;
+ void *user_msgp = uap->msgp;
+ size_t msgsz = uap->msgsz;
+ long msgtyp = uap->msgtyp;
+ int msgflg = uap->msgflg;
+ size_t len;
+ struct ucred *cred = p->p_ucred;
+ register struct msqid_ds *msqptr;
+ register struct msg *msghdr;
+ int eval;
+ short next;
+
+#ifdef MSG_DEBUG
+ printf("call to msgrcv(%d,0x%x,%d,%ld,%d)\n",msqid,user_msgp,msgsz,msgtyp,msgflg);
+#endif
+
+ msqid = IPCID_TO_IX(msqid);
+
+ if ( msqid < 0 || msqid >= msginfo.msgmni ) {
+#ifdef MSG_DEBUG
+ printf("msqid (%d) out of range (0<=msqid<%d)\n",msqid,msginfo.msgmni);
+#endif
+ return(EINVAL);
+ }
+
+ msqptr = &msqids[msqid];
+ if ( msqptr->msg_qbytes == 0 ) {
+#ifdef MSG_DEBUG
+ printf("no such message queue id\n");
+#endif
+ return(EINVAL);
+ }
+ if ( msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid) ) {
+#ifdef MSG_DEBUG
+ printf("wrong sequence number\n");
+#endif
+ return(EINVAL);
+ }
+
+ if ( (eval = ipcaccess(&msqptr->msg_perm, IPC_R, cred)) ) {
+#ifdef MSG_DEBUG
+ printf("requester doesn't have read access\n");
+#endif
+ return(eval);
+ }
+
+ msghdr = NULL;
+ while ( msghdr == NULL ) {
+
+ if ( msgtyp == 0 ) {
+
+ msghdr = msqptr->msg_first;
+ if ( msghdr != NULL ) {
+ if ( msgsz < msghdr->msg_ts && (msgflg & MSG_NOERROR) == 0 ) {
+#ifdef MSG_DEBUG
+ printf("first message on the queue is too big (want %d, got %d)\n",msgsz,msghdr->msg_ts);
+#endif
+ return(E2BIG);
+ }
+ if ( msqptr->msg_first == msqptr->msg_last ) {
+ msqptr->msg_first = NULL;
+ msqptr->msg_last = NULL;
+ } else {
+ msqptr->msg_first = msghdr->msg_next;
+ if ( msqptr->msg_first == NULL ) {
+ panic("msg_first/last screwed up #1");
+ }
+ }
+ }
+
+ } else {
+ struct msg *previous;
+ struct msg **prev;
+
+ previous = NULL;
+ prev = &(msqptr->msg_first);
+ while ( (msghdr = *prev) != NULL ) {
+
+ /*
+ * Is this message's type an exact match or is this message's
+ * type less than or equal to the absolute value of a negative msgtyp?
+ * Note that the second half of this test can NEVER be true
+ * if msgtyp is positive since msg_type is always positive!
+ */
+
+ if ( msgtyp == msghdr->msg_type || msghdr->msg_type <= -msgtyp ) {
+#ifdef MSG_DEBUG
+ printf("found message type %d, requested %d\n",msghdr->msg_type,msgtyp);
+#endif
+ if ( msgsz < msghdr->msg_ts && (msgflg & MSG_NOERROR) == 0 ) {
+#ifdef MSG_DEBUG
+ printf("requested message on the queue is too big (want %d, got %d)\n",msgsz,msghdr->msg_ts);
+#endif
+ return(E2BIG);
+ }
+ *prev = msghdr->msg_next;
+ if ( msghdr == msqptr->msg_last ) {
+ if ( previous == NULL ) {
+ if ( prev != &msqptr->msg_first ) {
+ panic("msg_first/last screwed up #2");
+ }
+ msqptr->msg_first = NULL;
+ msqptr->msg_last = NULL;
+ } else {
+ if ( prev == &msqptr->msg_first ) {
+ panic("msg_first/last screwed up #3");
+ }
+ msqptr->msg_last = previous;
+ }
+ }
+ break;
+ }
+ previous = msghdr;
+ prev = &(msghdr->msg_next);
+ }
+
+ }
+
+ /*
+ * We've either extracted the msghdr for the appropriate message
+ * or there isn't one.
+ * If there is one then bail out of this loop.
+ */
+
+ if ( msghdr != NULL ) {
+ break;
+ }
+
+ /*
+ * Hmph! No message found. Does the user want to wait?
+ */
+
+ if ( (msgflg & IPC_NOWAIT) != 0 ) {
+#ifdef MSG_DEBUG
+ printf("no appropriate message found (msgtyp=%d)\n",msgtyp);
+#endif
+ /* The SVID says to return ENOMSG. */
+#ifdef ENOMSG
+ return(ENOMSG);
+#else
+ /* Unfortunately, BSD doesn't define that code (yet)! */
+ return(EAGAIN);
+#endif
+ }
+
+ /*
+ * Wait for something to happen
+ */
+
+#ifdef MSG_DEBUG
+ printf("msgrcv: goodnight\n");
+#endif
+ eval = tsleep( (caddr_t)msqptr, (PZERO - 4) | PCATCH, "msg wait", 0 );
+#ifdef MSG_DEBUG
+ printf("msgrcv: good morning (eval=%d)\n",eval);
+#endif
+
+ if ( eval != 0 ) {
+#ifdef MSG_DEBUG
+ printf("msgsnd: interrupted system call\n");
+#endif
+ return( EINTR );
+ }
+
+ /*
+ * Make sure that the msq queue still exists
+ */
+
+ if ( msqptr->msg_qbytes == 0
+ || msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid) ) {
+#ifdef MSG_DEBUG
+ printf("msqid deleted\n");
+#endif
+ /* The SVID says to return EIDRM. */
+#ifdef EIDRM
+ return(EIDRM);
+#else
+ /* Unfortunately, BSD doesn't define that code (yet)! */
+ return(EINVAL);
+#endif
+ }
+
+ }
+
+ /*
+ * Return the message to the user.
+ *
+ * First, do the bookkeeping (before we risk being interrupted).
+ */
+
+ msqptr->msg_cbytes -= msghdr->msg_ts;
+ msqptr->msg_qnum -= 1;
+ msqptr->msg_lrpid = p->p_pid;
+ msqptr->msg_rtime = time.tv_sec;
+
+ /*
+ * Make msgsz the actual amount that we'll be returning.
+ * Note that this effectively truncates the message if it is too long
+ * (since msgsz is never increased).
+ */
+
+#ifdef MSG_DEBUG
+ printf("found a message, msgsz=%d, msg_ts=%d\n",msgsz,msghdr->msg_ts);
+#endif
+ if ( msgsz > msghdr->msg_ts ) {
+ msgsz = msghdr->msg_ts;
+ }
+
+ /*
+ * Return the type to the user.
+ */
+
+ eval = copyout((caddr_t)&(msghdr->msg_type), user_msgp, sizeof(msghdr->msg_type));
+ if ( eval != 0 ) {
+#ifdef MSG_DEBUG
+ printf("error (%d) copying out message type\n",eval);
+#endif
+ msg_freehdr(msghdr);
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ return(eval);
+ }
+ user_msgp += sizeof(msghdr->msg_type);
+
+ /*
+ * Return the segments to the user
+ */
+
+ next = msghdr->msg_spot;
+ for ( len = 0; len < msgsz; len += msginfo.msgssz ) {
+ size_t tlen;
+ if ( msgsz > msginfo.msgssz ) {
+ tlen = msginfo.msgssz;
+ } else {
+ tlen = msgsz;
+ }
+ if ( next <= -1 ) {
+ panic("next too low #3");
+ }
+ if ( next >= msginfo.msgseg ) {
+ panic("next out of range #3");
+ }
+ eval = copyout((caddr_t)&msgpool[next * msginfo.msgssz], user_msgp, tlen);
+ if ( eval != 0 ) {
+#ifdef MSG_DEBUG
+ printf("error (%d) copying out message segment\n",eval);
+#endif
+ msg_freehdr(msghdr);
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ return(eval);
+ }
+ user_msgp += tlen;
+ next = msgmaps[next].next;
+ }
+
+ /*
+ * Done, return the actual number of bytes copied out.
+ */
+
+ msg_freehdr(msghdr);
+ wakeup( (caddr_t)msqptr ); /* Somebody might care - we should check! */
+ *retval = msgsz;
+ return(0);
+}
+#endif
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
new file mode 100644
index 000000000000..6344018d9514
--- /dev/null
+++ b/sys/kern/sysv_sem.c
@@ -0,0 +1,1114 @@
+/*
+ * Implementation of SVID semaphores
+ *
+ * Author: Daniel Boulet
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ */
+
+#ifdef SYSVSEM
+
+#include "param.h"
+#include "systm.h"
+#include "kernel.h"
+#include "proc.h"
+#include "sem.h"
+#include "malloc.h"
+
+static int semctl(), semget(), semop(), semconfig();
+int (*semcalls[])() = { semctl, semget, semop, semconfig };
+int semtot = 0;
+
+static struct proc *semlock_holder = NULL;
+
+void
+seminit()
+{
+ register int i;
+ vm_offset_t whocares1, whocares2;
+
+ if ( sema == NULL ) {
+ panic("sema is NULL");
+ }
+ for ( i = 0; i < seminfo.semmni; i += 1 ) {
+ sema[i].sem_base = 0;
+ sema[i].sem_perm.mode = 0;
+ }
+ if ( semu == NULL ) {
+ panic("semu is NULL");
+ }
+ for ( i = 0; i < seminfo.semmnu; i += 1 ) {
+ register struct sem_undo *suptr = SEMU(i);
+ suptr->un_proc = NULL;
+ }
+ semu_list = NULL;
+}
+
+TEXT_SET(pseudo_set, seminit);
+
+/*
+ * Entry point for all SEM calls
+ */
+
+struct semsys_args {
+ u_int which;
+};
+
+int
+semsys(p, uap, retval)
+ struct proc *p;
+ struct semsys_args *uap;
+ int *retval;
+{
+ while ( semlock_holder != NULL && semlock_holder != p ) {
+ /* printf("semaphore facility locked - sleeping ...\n"); */
+ sleep( (caddr_t)&semlock_holder, (PZERO - 4) );
+ }
+
+ if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
+ return (EINVAL);
+ return ((*semcalls[uap->which])(p, &uap[1], retval));
+}
+
+/*
+ * Lock or unlock the entire semaphore facility.
+ *
+ * This will probably eventually evolve into a general purpose semaphore
+ * facility status enquiry mechanism (I don't like the "read /dev/kmem"
+ * approach currently taken by ipcs and the amount of info that we want
+ * to be able to extract for ipcs is probably beyond what the capability
+ * of the getkerninfo facility.
+ *
+ * At the time that the current version of semconfig was written, ipcs is
+ * the only user of the semconfig facility. It uses it to ensure that the
+ * semaphore facility data structures remain static while it fishes around
+ * in /dev/kmem.
+ */
+
+struct semconfig_args {
+ semconfig_ctl_t flag;
+};
+
+int
+semconfig(p, uap, retval)
+ struct proc *p;
+ struct semconfig_args *uap;
+ int *retval;
+{
+ int eval = 0;
+
+ switch ( uap->flag ) {
+ case SEM_CONFIG_FREEZE:
+ semlock_holder = p;
+ break;
+ case SEM_CONFIG_THAW:
+ semlock_holder = NULL;
+ wakeup( (caddr_t)&semlock_holder );
+ break;
+ default:
+ printf("semconfig: unknown flag parameter value (%d) - ignored\n",uap->flag);
+ eval = EINVAL;
+ break;
+ }
+
+ *retval = 0;
+ return(eval);
+}
+
+/*
+ * Allocate a new sem_undo structure for a process
+ * (returns ptr to structure or NULL if no more room)
+ */
+
+struct sem_undo *
+semu_alloc(struct proc *p)
+{
+ register int i;
+ register struct sem_undo *suptr;
+ register struct sem_undo **supptr;
+ int attempt;
+
+ /*
+ * Try twice to allocate something.
+ * (we'll purge any empty structures after the first pass so
+ * two passes are always enough)
+ */
+
+ for ( attempt = 0; attempt < 2; attempt += 1 ) {
+
+ /*
+ * Look for a free structure.
+ * Fill it in and return it if we find one.
+ */
+
+ for ( i = 0; i < seminfo.semmnu; i += 1 ) {
+ suptr = SEMU(i);
+ if ( suptr->un_proc == NULL ) {
+ suptr->un_next = semu_list;
+ semu_list = suptr;
+ suptr->un_cnt = 0;
+ suptr->un_proc = p;
+ return(suptr);
+ }
+ }
+
+ /*
+ * We didn't find a free one, if this is the first attempt
+ * then try to free some structures.
+ */
+
+ if ( attempt == 0 ) {
+
+ /* All the structures are in use - try to free some */
+
+ int did_something = 0;
+
+ supptr = &semu_list;
+ while ( (suptr = *supptr) != NULL ) {
+ if ( suptr->un_cnt == 0 ) {
+ suptr->un_proc = NULL;
+ *supptr = suptr->un_next;
+ did_something = 1;
+ } else {
+ supptr = &(suptr->un_next);
+ }
+ }
+
+ /* If we didn't free anything then just give-up */
+
+ if ( !did_something ) {
+ return(NULL);
+ }
+
+ } else {
+
+ /*
+ * The second pass failed even though we freed
+ * something after the first pass!
+ * This is IMPOSSIBLE!
+ */
+
+ panic("semu_alloc - second attempt failed");
+
+ }
+
+ }
+
+ /* NOTREACHED */
+ while (1);
+}
+
+/*
+ * Adjust a particular entry for a particular proc
+ */
+
+int
+semundo_adjust(register struct proc *p,struct sem_undo **supptr,int semid,int semnum,int adjval)
+{
+ register struct sem_undo *suptr;
+ register struct undo *sunptr;
+ int i;
+
+ /* Look for and remember the sem_undo if the caller doesn't provide it */
+
+ suptr = *supptr;
+ if ( suptr == NULL ) {
+ /* printf("adjust: need to find suptr\n"); */
+ for ( suptr = semu_list; suptr != NULL; suptr = suptr->un_next ) {
+ if ( suptr->un_proc == p ) {
+ /* printf("adjust: found suptr @%08x\n",suptr); */
+ *supptr = suptr;
+ break;
+ }
+ }
+ if ( suptr == NULL ) {
+ if ( adjval == 0 ) {
+ return(0); /* Don't create it if it doesn't exist */
+ }
+ suptr = semu_alloc(p);
+ if ( suptr == NULL ) {
+ return(ENOSPC);
+ }
+ /* printf("adjust: allocated suptr @%08x\n",suptr); */
+ *supptr = suptr;
+ }
+ }
+
+ /* Look for the requested entry and adjust it (delete if adjval becomes 0) */
+
+ sunptr = &(suptr->un_ent[0]);
+ for ( i = 0; i < suptr->un_cnt; i += 1, sunptr += 1 ) {
+
+ if ( sunptr->un_id == semid && sunptr->un_num == semnum ) {
+
+ /* Found the right entry - adjust it */
+
+ if ( adjval == 0 ) {
+ sunptr->un_adjval = 0;
+ } else {
+ /* printf("adjust: %08x %d:%d(%d) += %d\n",suptr->un_proc,semid,semnum,sunptr->un_adjval,adjval); */
+ sunptr->un_adjval += adjval;
+ }
+ if ( sunptr->un_adjval == 0 ) {
+ /* printf("adjust: %08x deleting entry %d:%d\n",suptr->un_proc,semid,semnum); */
+ suptr->un_cnt -= 1;
+ if ( i < suptr->un_cnt ) {
+ suptr->un_ent[i] = suptr->un_ent[suptr->un_cnt];
+ }
+ }
+ return(0);
+
+ }
+ }
+
+ /* Didn't find the right entry - create it */
+
+ if ( adjval == 0 ) {
+ return(0);
+ }
+ if ( suptr->un_cnt == SEMUME ) {
+ return(EINVAL);
+ } else {
+ /* printf("adjust: %08x allocating entry %d as %d:%d(%d)\n",suptr->un_proc,suptr->un_cnt,semid,semnum,adjval); */
+ sunptr = &(suptr->un_ent[suptr->un_cnt]);
+ suptr->un_cnt += 1;
+ sunptr->un_adjval = adjval;
+ sunptr->un_id = semid; sunptr->un_num = semnum;
+ }
+ return(0);
+}
+
+
+void
+semundo_clear(int semid,int semnum)
+{
+ register struct sem_undo *suptr;
+
+ for ( suptr = semu_list; suptr != NULL; suptr = suptr->un_next ) {
+
+ register struct undo *sunptr = &(suptr->un_ent[0]);
+ register int i = 0;
+
+ while ( i < suptr->un_cnt ) {
+ int advance = 1;
+
+ if ( sunptr->un_id == semid ) {
+ if ( semnum == -1 || sunptr->un_num == semnum ) {
+ /* printf("clear: %08x %d:%d(%d)\n",suptr->un_proc,semid,sunptr->un_num,sunptr->un_adjval); */
+ suptr->un_cnt -= 1;
+ if ( i < suptr->un_cnt ) {
+ suptr->un_ent[i] = suptr->un_ent[suptr->un_cnt];
+ advance = 0;
+ }
+ }
+ if ( semnum != -1 ) {
+ break;
+ }
+ }
+
+ if ( advance ) {
+ i += 1;
+ sunptr += 1;
+ }
+
+ }
+
+ }
+
+}
+
+struct semctl_args {
+ int semid;
+ int semnum;
+ int cmd;
+ union semun *arg;
+};
+
+int
+semctl(p, uap, retval)
+ struct proc *p;
+ register struct semctl_args *uap;
+ int *retval;
+{
+ int semid = uap->semid;
+ int semnum = uap->semnum;
+ int cmd = uap->cmd;
+ union semun *arg = uap->arg;
+ union semun real_arg;
+ struct ucred *cred = p->p_ucred;
+ int i, rval, eval;
+ struct semid_ds sbuf;
+ register struct semid_ds *semaptr;
+
+#ifdef SEM_DEBUG
+ printf("call to semctl(%d,%d,%d,0x%x)\n",semid,semnum,cmd,arg);
+#endif
+
+ semid = IPCID_TO_IX(semid);
+
+ if ( semid < 0 || semid >= seminfo.semmsl ) {
+ /* printf("semid out of range (0<=%d<%d)\n",semid,seminfo.semmsl); */
+ return(EINVAL);
+ }
+
+ semaptr = &sema[semid];
+
+ if ( semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid) ) {
+ /* printf("invalid sequence number\n"); */
+ return(EINVAL);
+ }
+
+ if ( (semaptr->sem_perm.mode & SEM_ALLOC) == 0 ) {
+ /* printf("no such semaphore id\n"); */
+ return(EINVAL);
+ }
+
+ eval = 0;
+ rval = 0;
+
+ switch (cmd) {
+
+ case IPC_RMID:
+ if ( cred->cr_uid != 0
+ && semaptr->sem_perm.cuid != cred->cr_uid
+ && semaptr->sem_perm.uid != cred->cr_uid ) {
+ return(EPERM);
+ }
+ semaptr->sem_perm.cuid = cred->cr_uid;
+ semaptr->sem_perm.uid = cred->cr_uid;
+ semtot -= semaptr->sem_nsems;
+ for ( i = semaptr->sem_base - sem; i < semtot; i += 1 ) {
+ /* printf("0x%x = 0x%x; ",&sem[i],&sem[i + semaptr->sem_nsems]); */
+ sem[i] = sem[i + semaptr->sem_nsems];
+ }
+ /* printf("\n"); */
+ for ( i = 0; i < seminfo.semmni; i += 1 ) {
+ if ( (sema[i].sem_perm.mode & SEM_ALLOC)
+ && sema[i].sem_base > semaptr->sem_base ) {
+ /* printf("sema[%d].sem_base was 0x%x",i,sema[i].sem_base); */
+ sema[i].sem_base -= semaptr->sem_nsems;
+ /* printf(", now 0x%x\n",sema[i].sem_base); */
+ }
+ }
+ semaptr->sem_perm.mode = 0;
+
+ /* Delete any undo entries for this semid */
+
+ semundo_clear(semid,-1);
+
+ /* Make sure that anybody who is waiting notices the deletion */
+
+ wakeup( (caddr_t)semaptr );
+
+ break;
+
+ case IPC_SET:
+ /* printf("IPC_SET\n"); */
+ if ( cred->cr_uid != 0
+ && semaptr->sem_perm.cuid != cred->cr_uid
+ && semaptr->sem_perm.uid != cred->cr_uid ) {
+ return(EPERM);
+ }
+ if ( (eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0 ) {
+ return(eval);
+ }
+ if ( (eval = copyin(real_arg.buf, (caddr_t)&sbuf, sizeof(sbuf)) ) != 0 ) {
+ return(eval);
+ }
+ semaptr->sem_perm.uid = sbuf.sem_perm.uid;
+ semaptr->sem_perm.gid = sbuf.sem_perm.gid;
+ semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777)
+ | (sbuf.sem_perm.mode & 0777);
+ semaptr->sem_ctime = time.tv_sec;
+ break;
+
+ case IPC_STAT:
+ /* printf("IPC_STAT\n"); */
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_R, cred)) ) {
+ return(eval);
+ }
+ rval = 0;
+ if ( (eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0 ) {
+ return(eval);
+ }
+ eval = copyout((caddr_t)semaptr, real_arg.buf, sizeof(struct semid_ds)) ;
+ break;
+
+ case GETNCNT:
+ /* printf("GETNCNT(%d)\n",semnum); */
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_R, cred)) ) {
+ return(eval);
+ }
+ if ( semnum < 0 || semnum >= semaptr->sem_nsems ) return(EINVAL);
+ rval = semaptr->sem_base[semnum].semncnt;
+ break;
+
+ case GETPID:
+ /* printf("GETPID(%d)\n",semnum); */
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_R, cred)) ) {
+ return(eval);
+ }
+ if ( semnum < 0 || semnum >= semaptr->sem_nsems ) return(EINVAL);
+ rval = semaptr->sem_base[semnum].sempid;
+ break;
+
+ case GETVAL:
+ /* printf("GETVAL(%d)\n",semnum); */
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_R, cred)) ) {
+ return(eval);
+ }
+ if ( semnum < 0 || semnum >= semaptr->sem_nsems ) return(EINVAL);
+ rval = semaptr->sem_base[semnum].semval;
+ break;
+
+ case GETALL:
+ /* printf("GETALL\n"); */
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_R, cred)) ) {
+ return(eval);
+ }
+ rval = 0;
+ if ( (eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0 ) {
+ /* printf("initial copyin failed (addr=0x%x)\n",arg); */
+ return(eval);
+ }
+ /* printf("%d semaphores\n",semaptr->sem_nsems); */
+ for ( i = 0; i < semaptr->sem_nsems; i += 1 ) {
+ /* printf("copyout to 0x%x\n",&real_arg.array[i]); */
+ eval =
+ copyout((caddr_t)&semaptr->sem_base[i].semval,
+ &real_arg.array[i],
+ sizeof(real_arg.array[0]));
+ if ( eval != 0 ) {
+ /* printf("copyout to 0x%x failed\n",&real_arg.array[i]); */
+ break;
+ }
+ }
+ break;
+
+ case GETZCNT:
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_R, cred)) ) {
+ return(eval);
+ }
+ /* printf("GETZCNT(%d)\n",semnum); */
+ if ( semnum < 0 || semnum >= semaptr->sem_nsems ) return(EINVAL);
+ rval = semaptr->sem_base[semnum].semzcnt;
+ break;
+
+ case SETVAL:
+#ifdef SEM_DEBUG
+ printf("SETVAL(%d)\n",semnum);
+#endif
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_W, cred)) ) {
+ return(eval);
+ }
+ if ( semnum < 0 || semnum >= semaptr->sem_nsems ) return(EINVAL);
+ rval = 0;
+ if ( (eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0 ) {
+ return(eval);
+ }
+#ifdef SEM_DEBUG
+ printf("semaptr=%x, sem_base=%x, semptr=%x, oldval=%d, ",
+ semaptr,semaptr->sem_base,&semaptr->sem_base[semnum],semaptr->sem_base[semnum].semval);
+#endif
+ semaptr->sem_base[semnum].semval = real_arg.val;
+#ifdef SEM_DEBUG
+ printf(" newval=%d\n", semaptr->sem_base[semnum].semval);
+#endif
+ semundo_clear(semid,semnum);
+ wakeup( (caddr_t)semaptr ); /* somebody else might care */
+ break;
+
+ case SETALL:
+ /* printf("SETALL\n"); */
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_W, cred)) ) {
+ return(eval);
+ }
+ rval = 0;
+ if ( (eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0 ) {
+ return(eval);
+ }
+ for ( i = 0; i < semaptr->sem_nsems; i += 1 ) {
+ eval =
+ copyin(&real_arg.array[i],
+ (caddr_t)&semaptr->sem_base[i].semval,
+ sizeof(real_arg.array[0]));
+ if ( eval != 0 ) {
+ break;
+ }
+ }
+ semundo_clear(semid,-1);
+ wakeup( (caddr_t)semaptr ); /* somebody else might care */
+ break;
+ default:
+ /* printf("invalid command %d\n",cmd); */
+ return(EINVAL);
+ }
+
+ if ( eval == 0 ) {
+ *retval = rval;
+ }
+ return(eval);
+}
+
+struct semget_args {
+ key_t key;
+ int nsems;
+ int semflg;
+};
+
+int
+semget(p, uap, retval)
+ struct proc *p;
+ register struct semget_args *uap;
+ int *retval;
+{
+ int semid, eval;
+ int key = uap->key;
+ int nsems = uap->nsems;
+ int semflg = uap->semflg;
+ struct ucred *cred = p->p_ucred;
+
+#ifdef SEM_DEBUG
+ printf("semget(0x%x,%d,0%o)\n",key,nsems,semflg);
+#endif
+
+ if ( key == IPC_PRIVATE ) {
+#ifdef SEM_DEBUG
+ printf("private key\n");
+#endif
+ semid = seminfo.semmni;
+ } else {
+ for ( semid = 0; semid < seminfo.semmni; semid += 1 ) {
+ if ( (sema[semid].sem_perm.mode & SEM_ALLOC)
+ && sema[semid].sem_perm.key == key ) {
+ break;
+ }
+ }
+ if ( semid < seminfo.semmni ) {
+#ifdef SEM_DEBUG
+ printf("found public key\n");
+#endif
+ if ( (eval = ipcaccess(&sema[semid].sem_perm, semflg & 0700, cred)) ) {
+ return(eval);
+ }
+ if ( nsems > 0 && sema[semid].sem_nsems < nsems ) {
+#ifdef SEM_DEBUG
+ printf("too small\n");
+#endif
+ return(EINVAL);
+ }
+ if ( (semflg & IPC_CREAT) && (semflg & IPC_EXCL) ) {
+#ifdef SEM_DEBUG
+ printf("not exclusive\n");
+#endif
+ return(EEXIST);
+ }
+ } else {
+#ifdef SEM_DEBUG
+ printf("didn't find public key\n");
+#endif
+ }
+ }
+
+ if ( semid == seminfo.semmni ) {
+#ifdef SEM_DEBUG
+ printf("need to allocate the semid_ds\n");
+#endif
+ if ( key == IPC_PRIVATE || (semflg & IPC_CREAT) ) {
+ if ( nsems <= 0 || nsems > seminfo.semmsl ) {
+#ifdef SEM_DEBUG
+ printf("nsems out of range (0<%d<=%d)\n",nsems,seminfo.semmsl);
+#endif
+ return(EINVAL);
+ }
+ if ( nsems > seminfo.semmns - semtot ) {
+#ifdef SEM_DEBUG
+ printf("not enough semaphores left (need %d, got %d)\n",
+ nsems,seminfo.semmns - semtot);
+#endif
+ return(ENOSPC);
+ }
+ for ( semid = 0; semid < seminfo.semmni; semid += 1 ) {
+ if ( (sema[semid].sem_perm.mode & SEM_ALLOC) == 0 ) {
+ break;
+ }
+ }
+ if ( semid == seminfo.semmni ) {
+#ifdef SEM_DEBUG
+ printf("no more semid_ds's available\n");
+#endif
+ return(ENOSPC);
+ }
+#ifdef SEM_DEBUG
+ printf("semid %d is available\n",semid);
+#endif
+ sema[semid].sem_perm.key = key;
+ sema[semid].sem_perm.cuid = cred->cr_uid;
+ sema[semid].sem_perm.uid = cred->cr_uid;
+ sema[semid].sem_perm.cgid = cred->cr_gid;
+ sema[semid].sem_perm.gid = cred->cr_gid;
+ sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
+ sema[semid].sem_perm.seq = (sema[semid].sem_perm.seq + 1) & 0x7fff; /* avoid semid overflows */
+ sema[semid].sem_nsems = nsems;
+ sema[semid].sem_otime = 0;
+ sema[semid].sem_ctime = time.tv_sec;
+ sema[semid].sem_base = &sem[semtot];
+ semtot += nsems;
+ bzero(sema[semid].sem_base,sizeof(sema[semid].sem_base[0])*nsems);
+#ifdef SEM_DEBUG
+ printf("sembase = 0x%x, next = 0x%x\n",sema[semid].sem_base,&sem[semtot]);
+#endif
+ } else {
+#ifdef SEM_DEBUG
+ printf("didn't find it and wasn't asked to create it\n");
+#endif
+ return(ENOENT);
+ }
+ }
+
+ *retval = IXSEQ_TO_IPCID(semid,sema[semid].sem_perm); /* Convert to one origin */
+ return(0);
+}
+
+struct semop_args {
+ int semid;
+ struct sembuf *sops;
+ int nsops;
+};
+
+int
+semop(p, uap, retval)
+ struct proc *p;
+ register struct semop_args *uap;
+ int *retval;
+{
+ int semid = uap->semid;
+ int nsops = uap->nsops;
+ struct sembuf sops[MAX_SOPS];
+ register struct semid_ds *semaptr;
+ register struct sembuf *sopptr;
+ register struct sem *semptr;
+ struct sem_undo *suptr = NULL;
+ struct ucred *cred = p->p_ucred;
+ int i, j, eval;
+ int all_ok, do_wakeup, do_undos;
+
+#ifdef SEM_DEBUG
+ printf("call to semop(%d,0x%x,%d)\n",semid,sops,nsops);
+#endif
+
+ semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
+
+ if ( semid < 0 || semid >= seminfo.semmsl ) {
+ /* printf("semid out of range (0<=%d<%d)\n",semid,seminfo.semmsl); */
+ return(EINVAL);
+ }
+
+ semaptr = &sema[semid];
+ if ( (semaptr->sem_perm.mode & SEM_ALLOC) == 0 ) {
+ /* printf("no such semaphore id\n"); */
+ return(EINVAL);
+ }
+
+ if ( semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid) ) {
+ /* printf("invalid sequence number\n"); */
+ return(EINVAL);
+ }
+
+ if ( (eval = ipcaccess(&semaptr->sem_perm, IPC_W, cred)) ) {
+#ifdef SEM_DEBUG
+ printf("eval = %d from ipaccess\n",eval);
+#endif
+ return(eval);
+ }
+
+ if ( nsops > MAX_SOPS ) {
+#ifdef SEM_DEBUG
+ printf("too many sops (max=%d, nsops=%d)\n",MAX_SOPS,nsops);
+#endif
+ return(E2BIG);
+ }
+
+ if ( (eval = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0 ) {
+#ifdef SEM_DEBUG
+ printf("eval = %d from copyin(%08x, %08x, %d)\n",eval,uap->sops,&sops,nsops * sizeof(sops[0]));
+#endif
+ return(eval);
+ }
+
+ /*
+ * Loop trying to satisfy the vector of requests.
+ * If we reach a point where we must wait, any requests already
+ * performed are rolled back and we go to sleep until some other
+ * process wakes us up. At this point, we start all over again.
+ *
+ * This ensures that from the perspective of other tasks, a set
+ * of requests is atomic (never partially satisfied).
+ */
+
+ do_undos = 0;
+
+ while (1) {
+
+ do_wakeup = 0;
+
+ for ( i = 0; i < nsops; i += 1 ) {
+
+ sopptr = &sops[i];
+
+ if ( sopptr->sem_num >= semaptr->sem_nsems ) {
+ return(EFBIG);
+ }
+
+ semptr = &semaptr->sem_base[sopptr->sem_num];
+
+#ifdef SEM_DEBUG
+ printf("semop: semaptr=%x, sem_base=%x, semptr=%x, sem[%d]=%d : op=%d, flag=%s\n",
+ semaptr,semaptr->sem_base,semptr,
+ sopptr->sem_num,semptr->semval,sopptr->sem_op,
+ (sopptr->sem_flg & IPC_NOWAIT) ? "nowait" : "wait");
+#endif
+
+ if ( sopptr->sem_op < 0 ) {
+
+ if ( semptr->semval + sopptr->sem_op < 0 ) {
+#ifdef SEM_DEBUG
+ printf("semop: can't do it now\n");
+#endif
+ break;
+ } else {
+ semptr->semval += sopptr->sem_op;
+ if ( semptr->semval == 0 && semptr->semzcnt > 0 ) {
+ do_wakeup = 1;
+ }
+ }
+ if ( sopptr->sem_flg & SEM_UNDO ) {
+ do_undos = 1;
+ }
+
+ } else if ( sopptr->sem_op == 0 ) {
+
+ if ( semptr->semval > 0 ) {
+#ifdef SEM_DEBUG
+ printf("semop: not zero now\n");
+#endif
+ break;
+ }
+
+ } else {
+
+ if ( semptr->semncnt > 0 ) {
+ do_wakeup = 1;
+ }
+ semptr->semval += sopptr->sem_op;
+ if ( sopptr->sem_flg & SEM_UNDO ) {
+ do_undos = 1;
+ }
+
+ }
+ }
+
+ /*
+ * Did we get through the entire vector?
+ */
+
+ if ( i < nsops ) {
+
+ /*
+ * No ... rollback anything that we've already done
+ */
+
+#ifdef SEM_DEBUG
+ printf("semop: rollback 0 through %d\n",i-1);
+#endif
+ for ( j = 0; j < i; j += 1 ) {
+ semaptr->sem_base[sops[j].sem_num].semval -= sops[j].sem_op;
+ }
+
+ /*
+ * If the request that we couldn't satisfy has the NOWAIT
+ * flag set then return with EAGAIN.
+ */
+
+ if ( sopptr->sem_flg & IPC_NOWAIT ) {
+ return(EAGAIN);
+ }
+
+ if ( sopptr->sem_op == 0 ) {
+ semptr->semzcnt += 1;
+ } else {
+ semptr->semncnt += 1;
+ }
+
+#ifdef SEM_DEBUG
+ printf("semop: good night!\n");
+#endif
+ eval = tsleep( (caddr_t)semaptr, (PZERO - 4) | PCATCH, "sem wait", 0 );
+#ifdef SEM_DEBUG
+ printf("semop: good morning (eval=%d)!\n",eval);
+#endif
+
+ suptr = NULL; /* The sem_undo may have been reallocated */
+
+ if ( eval != 0 ) {
+ /* printf("semop: interrupted system call\n"); */
+ return( EINTR );
+ }
+#ifdef SEM_DEBUG
+ printf("semop: good morning!\n");
+#endif
+
+ /*
+ * Make sure that the semaphore still exists
+ */
+
+ if ( (semaptr->sem_perm.mode & SEM_ALLOC) == 0
+ || semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid) ) {
+
+ /* printf("semaphore id deleted\n"); */
+ /* The man page says to return EIDRM. */
+ /* Unfortunately, BSD doesn't define that code! */
+#ifdef EIDRM
+ return(EIDRM);
+#else
+ return(EINVAL);
+#endif
+ }
+
+ /*
+ * The semaphore is still alive. Readjust the count of
+ * waiting processes.
+ */
+
+ if ( sopptr->sem_op == 0 ) {
+ semptr->semzcnt -= 1;
+ } else {
+ semptr->semncnt -= 1;
+ }
+
+
+ } else {
+
+ /*
+ * Yes ... we're done.
+ * Process any SEM_UNDO requests.
+ */
+
+ if ( do_undos ) {
+
+ for ( i = 0; i < nsops; i += 1 ) {
+
+ /* We only need to deal with SEM_UNDO's for non-zero op's */
+ int adjval;
+
+ if ( (sops[i].sem_flg & SEM_UNDO) != 0 && (adjval = sops[i].sem_op) != 0 ) {
+
+ eval = semundo_adjust(p,&suptr,semid,sops[i].sem_num,-adjval);
+ if ( eval != 0 ) {
+
+ /*
+ * Oh-Oh! We ran out of either sem_undo's or undo's.
+ * Rollback the adjustments to this point and then
+ * rollback the semaphore ups and down so we can
+ * return with an error with all structures restored.
+ * We rollback the undo's in the exact reverse order that
+ * we applied them. This guarantees that we won't run
+ * out of space as we roll things back out.
+ */
+
+ for ( j = i - 1; j >= 0; j -= 1 ) {
+
+ if ( (sops[i].sem_flg & SEM_UNDO) != 0 && (adjval = sops[i].sem_op) != 0 ) {
+
+ if ( semundo_adjust(p,&suptr,semid,sops[j].sem_num,adjval) != 0 ) {
+
+ /* This is impossible! */
+ panic("semop - can't undo undos");
+
+ }
+ }
+
+ } /* loop backwards through sops */
+
+ for ( j = 0; j < nsops; j += 1 ) {
+ semaptr->sem_base[sops[j].sem_num].semval -= sops[j].sem_op;
+ }
+
+#ifdef SEM_DEBUG
+ printf("eval = %d from semundo_adjust\n",eval);
+#endif
+ return( eval );
+
+ } /* semundo_adjust failed */
+
+ } /* if ( SEM_UNDO && adjval != 0 ) */
+
+ } /* loop through the sops */
+
+ } /* if ( do_undos ) */
+
+ /* We're definitely done - set the sempid's */
+
+ for ( i = 0; i < nsops; i += 1 ) {
+
+ sopptr = &sops[i];
+ semptr = &semaptr->sem_base[sopptr->sem_num];
+ semptr->sempid = p->p_pid;
+
+ }
+
+ /* Do a wakeup if any semaphore was up'd. */
+
+ if ( do_wakeup ) {
+#ifdef SEM_DEBUG
+ printf("semop: doing wakeup\n");
+#ifdef SEM_WAKEUP
+ sem_wakeup( (caddr_t)semaptr );
+#else
+ wakeup( (caddr_t)semaptr );
+#endif
+ printf("semop: back from wakeup\n");
+#else
+ wakeup( (caddr_t)semaptr );
+#endif
+ }
+#ifdef SEM_DEBUG
+ printf("semop: done\n");
+#endif
+ *retval = 0;
+ return(0);
+
+ }
+
+ }
+
+ panic("semop: how did we get here???");
+}
+
+/*
+ * Go through the undo structures for this process and apply the
+ * adjustments to semaphores.
+ */
+
+void
+semexit(p)
+ struct proc *p;
+{
+ register struct sem_undo *suptr;
+ register struct sem_undo **supptr;
+ int did_something;
+
+ /*
+ * If somebody else is holding the global semaphore facility lock
+ * then sleep until it is released.
+ */
+
+ while ( semlock_holder != NULL && semlock_holder != p ) {
+#ifdef SEM_DEBUG
+ printf("semaphore facility locked - sleeping ...\n");
+#endif
+ sleep( (caddr_t)&semlock_holder, (PZERO - 4) );
+ }
+
+ did_something = 0;
+
+ /*
+ * Go through the chain of undo vectors looking for one
+ * associated with this process.
+ */
+
+ for ( supptr = &semu_list;
+ (suptr = *supptr) != NULL;
+ supptr = &(suptr->un_next)
+ ) {
+
+ if ( suptr->un_proc == p ) {
+
+#ifdef SEM_DEBUG
+ printf("proc @%08x has undo structure with %d entries\n",p,suptr->un_cnt);
+#endif
+
+ /*
+ * If there are any active undo elements then process them.
+ */
+
+ if ( suptr->un_cnt > 0 ) {
+
+ int ix;
+
+ for ( ix = 0; ix < suptr->un_cnt; ix += 1 ) {
+
+ int semid = suptr->un_ent[ix].un_id;
+ int semnum = suptr->un_ent[ix].un_num;
+ int adjval = suptr->un_ent[ix].un_adjval;
+ struct semid_ds *semaptr;
+
+ semaptr = &sema[semid];
+ if ( (semaptr->sem_perm.mode & SEM_ALLOC) == 0 ) {
+ panic("semexit - semid not allocated");
+ }
+ if ( semnum >= semaptr->sem_nsems ) {
+ panic("semexit - semnum out of range");
+ }
+
+#ifdef SEM_DEBUG
+ printf("semexit: %08x id=%d num=%d(adj=%d) ; sem=%d\n",suptr->un_proc,
+ suptr->un_ent[ix].un_id,suptr->un_ent[ix].un_num,suptr->un_ent[ix].un_adjval,
+ semaptr->sem_base[semnum].semval);
+#endif
+
+ if ( adjval < 0 ) {
+ if ( semaptr->sem_base[semnum].semval < -adjval ) {
+ semaptr->sem_base[semnum].semval = 0;
+ } else {
+ semaptr->sem_base[semnum].semval += adjval;
+ }
+ } else {
+ semaptr->sem_base[semnum].semval += adjval;
+ }
+
+ /* printf("semval now %d\n",semaptr->sem_base[semnum].semval); */
+
+#ifdef SEM_WAKEUP
+ sem_wakeup((caddr_t)semaptr); /* A little sloppy (we should KNOW if anybody is waiting). */
+#else
+ wakeup((caddr_t)semaptr); /* A little sloppy (we should KNOW if anybody is waiting). */
+#endif
+#ifdef SEM_DEBUG
+ printf("semexit: back from wakeup\n");
+#endif
+
+ }
+
+ }
+
+ /*
+ * Deallocate the undo vector.
+ */
+
+#ifdef SEM_DEBUG
+ printf("removing vector\n");
+#endif
+ suptr->un_proc = NULL;
+ *supptr = suptr->un_next;
+
+ /* Done. */
+
+ break;
+
+
+ }
+
+ }
+
+ /*
+ * If the exiting process is holding the global semaphore facility
+ * lock then release it.
+ */
+
+ if ( semlock_holder == p ) {
+ semlock_holder = NULL;
+ wakeup( (caddr_t)&semlock_holder );
+ }
+}
+#endif
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 0e7c3c84db29..00f123f529c5 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -37,7 +37,7 @@
*
* from: Utah $Hdr: uipc_shm.c 1.9 89/08/14$
* from: @(#)sysv_shm.c 7.15 (Berkeley) 5/13/91
- * $Id: sysv_shm.c,v 1.4 1993/10/16 15:24:52 rgrimes Exp $
+ * $Id: sysv_shm.c,v 1.9 1994/01/21 09:56:31 davidg Exp $
*/
/*
@@ -59,13 +59,18 @@
#include "vm/vm_kern.h"
#include "vm/vm_inherit.h"
#include "vm/vm_pager.h"
+#include "vm/vm_user.h"
#ifdef HPUXCOMPAT
#include "hp300/hpux/hpux.h"
#endif
-int shmat(), shmctl(), shmdt(), shmget();
-int (*shmcalls[])() = { shmat, shmctl, shmdt, shmget };
+/* From shm.h */
+struct shmid_ds *shmsegs;
+struct shminfo shminfo;
+
+int shmat(), shmctl(), shmdt(), shmget(); /* XXX */
+int (*shmcalls[])() = { shmat, shmctl, shmdt, shmget }; /* XXX */
int shmtot = 0;
/*
@@ -85,8 +90,15 @@ struct shmhandle {
caddr_t shmh_id;
};
+static int ipcaccess(struct ipc_perm *, int, struct ucred *);
+static void shmufree(struct proc *, struct shmdesc *);
+static void shmfree(struct shmid_ds *);
+static int shmvalid(int);
+
+
vm_map_t shm_map; /* address space for shared memory segments */
+void
shminit()
{
register int i;
@@ -102,6 +114,8 @@ shminit()
}
}
+TEXT_SET(pseudo_set, shminit);
+
/*
* Entry point for all SHM calls
*/
@@ -110,6 +124,7 @@ struct shmsys_args {
u_int which;
};
+int
shmsys(p, uap, retval)
struct proc *p;
struct shmsys_args *uap;
@@ -131,6 +146,7 @@ struct shmget_args {
int shmflg;
};
+int
shmget(p, uap, retval)
struct proc *p;
register struct shmget_args *uap;
@@ -183,7 +199,7 @@ shmget(p, uap, retval)
shmh = (struct shmhandle *)
malloc(sizeof(struct shmhandle), M_SHM, M_WAITOK);
shmh->shmh_kva = 0;
- shmh->shmh_id = (caddr_t)(0xc0000000|rval); /* XXX */
+ shmh->shmh_id = (caddr_t)(0xc0000000UL|rval); /* XXX */
error = vm_mmap(shm_map, &shmh->shmh_kva, ctob(size),
VM_PROT_ALL, VM_PROT_DEFAULT, MAP_ANON, shmh->shmh_id, 0);
if (error) {
@@ -228,6 +244,7 @@ struct shmctl_args {
};
/* ARGSUSED */
+int
shmctl(p, uap, retval)
struct proc *p;
register struct shmctl_args *uap;
@@ -299,6 +316,7 @@ struct shmat_args {
int shmflg;
};
+int
shmat(p, uap, retval)
struct proc *p;
register struct shmat_args *uap;
@@ -356,9 +374,11 @@ shmat(p, uap, retval)
if (uva)
flags |= MAP_FIXED;
else
- uva = (caddr_t)0x1000000; /* XXX */
- error = vm_mmap(&p->p_vmspace->vm_map, &uva, (vm_size_t)size, prot, VM_PROT_DEFAULT,
- flags, ((struct shmhandle *)shp->shm_handle)->shmh_id, 0);
+ uva = (caddr_t)0x1000000UL; /* XXX */
+ error = vm_mmap(&p->p_vmspace->vm_map, (vm_offset_t *)&uva,
+ (vm_size_t)size, prot, VM_PROT_DEFAULT,
+ flags, ((struct shmhandle *)shp->shm_handle)->shmh_id,
+ 0);
if (error)
return(error);
shmd->shmd_uva = (vm_offset_t)uva;
@@ -382,6 +402,7 @@ struct shmdt_args {
};
/* ARGSUSED */
+int
shmdt(p, uap, retval)
struct proc *p;
struct shmdt_args *uap;
@@ -399,8 +420,10 @@ shmdt(p, uap, retval)
return(EINVAL);
shmufree(p, shmd);
shmsegs[shmd->shmd_id % SHMMMNI].shm_lpid = p->p_pid;
+ return 0;
}
+void
shmfork(p1, p2, isvfork)
struct proc *p1, *p2;
int isvfork;
@@ -423,6 +446,7 @@ shmfork(p1, p2, isvfork)
shmsegs[shmd->shmd_id % SHMMMNI].shm_nattch++;
}
+void
shmexit(p)
struct proc *p;
{
@@ -437,6 +461,7 @@ shmexit(p)
p->p_vmspace->vm_shm = NULL;
}
+static int
shmvalid(id)
register int id;
{
@@ -454,6 +479,7 @@ shmvalid(id)
/*
* Free user resources associated with a shared memory segment
*/
+static void
shmufree(p, shmd)
struct proc *p;
struct shmdesc *shmd;
@@ -473,6 +499,7 @@ shmufree(p, shmd)
/*
* Deallocate resources associated with a shared memory segment
*/
+static void
shmfree(shp)
register struct shmid_ds *shp;
{
@@ -500,35 +527,4 @@ shmfree(shp)
if ((int)(shp->shm_perm.seq * SHMMMNI) < 0)
shp->shm_perm.seq = 0;
}
-
-/*
- * XXX This routine would be common to all sysV style IPC
- * (if the others were implemented).
- */
-ipcaccess(ipc, mode, cred)
- register struct ipc_perm *ipc;
- int mode;
- register struct ucred *cred;
-{
- register int m;
-
- if (cred->cr_uid == 0)
- return(0);
- /*
- * 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.
- */
- mode &= 0700;
- m = ipc->mode;
- if (cred->cr_uid != ipc->uid && cred->cr_uid != ipc->cuid) {
- m <<= 3;
- if (!groupmember(ipc->gid, cred) &&
- !groupmember(ipc->cgid, cred))
- m <<= 3;
- }
- if ((mode&m) == mode)
- return (0);
- return (EACCES);
-}
#endif /* SYSVSHM */
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index faf8b4d4a1a4..519b910ccfdb 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* from: @(#)tty.c 7.44 (Berkeley) 5/28/91
- * $Id: tty.c,v 1.5 1993/10/16 15:24:54 rgrimes Exp $
+ * $Id: tty.c,v 1.19.2.1 1994/03/24 08:19:44 rgrimes Exp $
*/
#include "param.h"
@@ -49,18 +49,43 @@
#include "kernel.h"
#include "vnode.h"
#include "syslog.h"
-
+#include "signalvar.h"
#include "vm/vm.h"
+#include "kinfo.h"
+#include "kinfo_proc.h"
+
+
+/*
+ * Input control starts when we would not be able to fit the maximum
+ * contents of the ping-pong buffers and finishes when we would be able
+ * to fit that much plus 1/8 more.
+ */
+#define I_HIGH_WATER (TTYHOG - 2 * 256) /* XXX */
+#define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8) /* XXX */
+
+/* XXX RB_LEN() is too slow. */
+#define INPUT_LEN(tp) (RB_LEN(&(tp)->t_can) + RB_LEN(&(tp)->t_raw))
+#undef MAX_INPUT /* XXX wrong in <sys/syslimits.h> */
+#define MAX_INPUT TTYHOG
static int proc_compare __P((struct proc *p1, struct proc *p2));
+static void ttyblock __P((struct tty *tp));
+static void ttyecho __P((int c, struct tty *tp));
+static int ttyoutput __P((int c, register struct tty *tp));
+static void ttyoutstr __P((char *cp, struct tty *tp));
+static void ttypend __P((struct tty *tp));
+static void ttyretype __P((struct tty *tp));
+static void ttyrub __P((int c, struct tty *tp));
+static void ttyrubo __P((struct tty *tp, int cnt));
+static void ttyunblock __P((struct tty *tp));
/* symbolic sleep message strings */
-char ttyin[] = "ttyin";
-char ttyout[] = "ttyout";
-char ttopen[] = "ttyopn";
-char ttclos[] = "ttycls";
-char ttybg[] = "ttybg";
-char ttybuf[] = "ttybuf";
+const char ttyin[] = "ttyin";
+const char ttyout[] = "ttyout";
+const char ttopen[] = "ttyopn";
+const char ttclos[] = "ttycls";
+const char ttybg[] = "ttybg";
+const char ttybuf[] = "ttybuf";
/*
* Table giving parity for characters and indicating
@@ -138,6 +163,7 @@ char partab[] = {
#undef CR
extern struct tty *constty; /* temporary virtual console */
+extern int nldisp;
/*
* Is 'c' a line delimiter ("break" character)?
@@ -145,6 +171,7 @@ extern struct tty *constty; /* temporary virtual console */
#define ttbreakc(c) ((c) == '\n' || ((c) == cc[VEOF] || \
(c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)
+void
ttychars(tp)
struct tty *tp;
{
@@ -155,6 +182,7 @@ ttychars(tp)
/*
* Flush tty after output has drained.
*/
+int
ttywflush(tp)
struct tty *tp;
{
@@ -168,6 +196,7 @@ ttywflush(tp)
/*
* Wait for output to drain.
*/
+int
ttywait(tp)
register struct tty *tp;
{
@@ -176,12 +205,33 @@ ttywait(tp)
while ((RB_LEN(&tp->t_out) || tp->t_state&TS_BUSY) &&
(tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) &&
tp->t_oproc) {
+ /*
+ * XXX temporary fix for deadlock.
+ *
+ * If two processes wait for output to drain from the same
+ * tty, and the amount of output to drain is > 0 and
+ * <= tp->t_lowat, then the processes will take turns
+ * uselessly waking each other up until the output drains,
+ * with cpl higher than spltty() throughout.
+ *
+ * The sleep address and TS_ASLEEP flag ought to be different
+ * for the different events (output done) and (output almost
+ * done).
+ */
+ tp->t_lowat = 0;
+
(*tp->t_oproc)(tp);
- tp->t_state |= TS_ASLEEP;
- if (error = ttysleep(tp, (caddr_t)&tp->t_out,
- TTOPRI | PCATCH, ttyout, 0))
+ if ((RB_LEN(&tp->t_out) || tp->t_state&TS_BUSY) &&
+ (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL)) {
+ tp->t_state |= TS_ASLEEP;
+ if (error = ttysleep(tp, (caddr_t)&tp->t_out,
+ TTOPRI | PCATCH, "ttywai", 0))
+ break;
+ } else
break;
}
+ if (tp->t_lowat == 0)
+ ttsetwater(tp);
splx(s);
return (error);
}
@@ -195,23 +245,26 @@ ttywait(tp)
* Flush TTY read and/or write queues,
* notifying anyone waiting.
*/
+void
ttyflush(tp, rw)
register struct tty *tp;
+ int rw;
{
- register s;
+ register int s;
s = spltty();
+ if (rw & FWRITE)
+ tp->t_state &= ~TS_TTSTOP;
+ (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
if (rw & FREAD) {
flushq(&tp->t_can);
flushq(&tp->t_raw);
tp->t_rocount = 0;
tp->t_rocol = 0;
- tp->t_state &= ~(TS_LOCAL|TS_TBLOCK); /* XXX - should be TS_RTSBLOCK */
+ tp->t_state &= ~TS_LOCAL;
ttwakeup(tp);
}
if (rw & FWRITE) {
- tp->t_state &= ~TS_TTSTOP;
- (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
flushq(&tp->t_out);
wakeup((caddr_t)&tp->t_out);
if (tp->t_wsel) {
@@ -220,38 +273,74 @@ ttyflush(tp, rw)
tp->t_state &= ~TS_WCOLL;
}
}
+ if (rw & FREAD) {
+ if (tp->t_state & (TS_TBLOCK | TS_HW_IFLOW)
+ && INPUT_LEN(tp) < I_LOW_WATER) {
+ int out_cc;
+ int t_state;
+
+ /*
+ * We delayed turning off input flow control in case
+ * we have to send a start character and the output
+ * queue was previously full. Sending a start char
+ * is still tricky because we don't want to add a
+ * new obstruction to draining the output queue.
+ */
+ out_cc = RB_LEN(&tp->t_out);
+ t_state = tp->t_state;
+ ttyunblock(tp);
+ tp->t_state &= ~TS_TBLOCK;
+ if (t_state & TS_TBLOCK && RB_LEN(&tp->t_out) != 0)
+ ttysleep(tp, (caddr_t)&tp->t_out, TTIPRI,
+ "ttyfls", hz / 10);
+ if (out_cc == 0 && RB_LEN(&tp->t_out) != 0) {
+ (*cdevsw[major(tp->t_dev)].d_stop)(tp, FWRITE);
+ flushq(&tp->t_out);
+ }
+ }
+ }
splx(s);
}
/*
- * Send stop character on input overflow.
+ * Handle input high water. Send stop character for the IXOFF case. Turn
+ * on all enabled input flow control bits and propagate the change to the
+ * driver.
*/
+static void
ttyblock(tp)
- register struct tty *tp;
+ struct tty *tp;
{
- register x;
- int rawcc, cancc;
- rawcc = RB_LEN(&tp->t_raw);
- cancc = RB_LEN(&tp->t_can);
- x = rawcc + cancc;
- if (rawcc > TTYHOG) {
- ttyflush(tp, FREAD|FWRITE);
- }
- /*
- * Block further input iff:
- * Current input > threshold AND input is available to user program
- */
- if (x >= TTYHOG/2 && (tp->t_state & TS_TBLOCK) == 0 &&
- ((tp->t_lflag&ICANON) == 0) || (cancc > 0)) {
- if (tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
- putc(tp->t_cc[VSTOP], &tp->t_out);
- }
- tp->t_state |= TS_TBLOCK; /* XXX - should be TS_RTSBLOCK? */
- ttstart(tp);
- }
+ if ((tp->t_state & TS_TBLOCK) == 0
+ && tp->t_cc[VSTOP] != _POSIX_VDISABLE
+ && putc(tp->t_cc[VSTOP], &tp->t_out) == 0)
+ tp->t_state |= TS_TBLOCK;
+ if (tp->t_cflag & CDTR_IFLOW)
+ tp->t_state |= TS_DTR_IFLOW;
+ if (tp->t_cflag & CRTS_IFLOW)
+ tp->t_state |= TS_RTS_IFLOW;
+ ttstart(tp);
}
+/*
+ * Handle input low water. Send start character for the IXOFF case. Turn
+ * off our input flow control bits and propagate the change to the driver.
+ */
+static void
+ttyunblock(tp)
+ struct tty *tp;
+{
+
+ if (tp->t_state & TS_TBLOCK
+ && tp->t_cc[VSTART] != _POSIX_VDISABLE
+ && putc(tp->t_cc[VSTART], &tp->t_out) == 0)
+ tp->t_state &= ~TS_TBLOCK;
+ tp->t_state &= ~TS_HW_IFLOW;
+ ttstart(tp);
+}
+
+void
ttstart(tp)
struct tty *tp;
{
@@ -260,6 +349,8 @@ ttstart(tp)
(*tp->t_oproc)(tp);
}
+#ifdef notused
+void
ttrstrt(tp) /* XXX */
struct tty *tp;
{
@@ -271,6 +362,7 @@ ttrstrt(tp) /* XXX */
tp->t_state &= ~TS_TIMEOUT;
ttstart(tp);
}
+#endif /* notused */
/*
@@ -280,12 +372,14 @@ ttrstrt(tp) /* XXX */
* and/or reject any of these ioctl commands.
*/
/*ARGSUSED*/
+int
ttioctl(tp, com, data, flag)
register struct tty *tp;
+ int com;
caddr_t data;
+ int flag;
{
register struct proc *p = curproc; /* XXX */
- extern int nldisp;
int s, error;
/*
@@ -345,9 +439,9 @@ ttioctl(tp, com, data, flag)
if (t != tp->t_line) {
s = spltty();
(*linesw[tp->t_line].l_close)(tp, flag);
- error = (*linesw[t].l_open)(dev, tp);
+ error = (*linesw[t].l_open)(dev, tp, 0);
if (error) {
- (void)(*linesw[tp->t_line].l_open)(dev, tp);
+ (void)(*linesw[tp->t_line].l_open)(dev, tp, 0);
splx(s);
return (error);
}
@@ -462,6 +556,22 @@ ttioctl(tp, com, data, flag)
splx(s);
return (error);
} else {
+ /*
+ * XXX doubtful. We mostly check both CLOCAL
+ * and TS_CARR_ON before doing anything, and
+ * changing TS_ISOPEN here just give another
+ * flag to worry about, and is probably
+ * inconsistent with not changing TS_ISOPEN
+ * when carrier drops or CLOCAL rises. OTOH
+ * we should maintain a flag to keep track
+ * of the combination of CLOCAL and TS_CARR_ON.
+ * This could be just TS_CARR_ON (if we don't
+ * need to
+ *
+ * XXX ttselect() doesn't worry about
+ * TS_ISOPEN, so it is inconsistent with
+ * ttread() after TS_ISOPEN gets cleared here.
+ */
if ((tp->t_state&TS_CARR_ON) == 0 &&
(tp->t_cflag&CLOCAL) &&
(t->c_cflag&CLOCAL) == 0) {
@@ -586,19 +696,25 @@ ttioctl(tp, com, data, flag)
return (0);
}
+int
ttnread(tp)
struct tty *tp;
{
int nread = 0;
+ /* XXX races. */
if (tp->t_lflag & PENDIN)
ttypend(tp);
nread = RB_LEN(&tp->t_can);
- if ((tp->t_lflag & ICANON) == 0)
+ if ((tp->t_lflag & ICANON) == 0) {
nread += RB_LEN(&tp->t_raw);
+ if (nread < tp->t_cc[VMIN])
+ nread = 0;
+ }
return (nread);
}
+int
ttselect(dev, rw, p)
dev_t dev;
int rw;
@@ -641,9 +757,11 @@ win:
/*
* Initial open of tty, or (re)entry to standard tty line discipline.
*/
-ttyopen(dev, tp)
+int
+ttyopen(dev, tp, dummy)
dev_t dev;
register struct tty *tp;
+ int dummy;
{
tp->t_dev = dev;
@@ -662,6 +780,7 @@ ttyopen(dev, tp)
/*
* "close" a line discipline
*/
+void
ttylclose(tp, flag)
struct tty *tp;
int flag;
@@ -678,6 +797,7 @@ ttylclose(tp, flag)
* bumping generation number so that pending read/write calls
* can detect recycling of the tty.
*/
+int
ttyclose(tp)
register struct tty *tp;
{
@@ -686,10 +806,6 @@ ttyclose(tp)
ttyflush(tp, FREAD|FWRITE);
tp->t_session = NULL;
tp->t_pgrp = NULL;
-/*
- * XXX - do we need to send cc[VSTART] or do a ttstart() here in some cases?
- * (TS_TBLOCK and TS_RTSBLOCK are being cleared.)
- */
tp->t_state = 0;
tp->t_gen++;
return (0);
@@ -700,8 +816,10 @@ ttyclose(tp)
* Flag indicates new state of carrier.
* Returns 0 if the line should be turned off, otherwise 1.
*/
+int
ttymodem(tp, flag)
register struct tty *tp;
+ int flag;
{
if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag&MDMBUF)) {
@@ -709,10 +827,10 @@ ttymodem(tp, flag)
* MDMBUF: do flow control according to carrier flag
*/
if (flag) {
- tp->t_state &= ~TS_TTSTOP;
+ tp->t_state &= ~TS_CAR_OFLOW;
ttstart(tp);
- } else if ((tp->t_state&TS_TTSTOP) == 0) {
- tp->t_state |= TS_TTSTOP;
+ } else if ((tp->t_state&TS_CAR_OFLOW) == 0) {
+ tp->t_state |= TS_CAR_OFLOW;
(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
}
} else if (flag == 0) {
@@ -740,6 +858,7 @@ ttymodem(tp, flag)
* Default modem control routine (for other line disciplines).
* Return argument flag, to turn off device on carrier drop.
*/
+int
nullmodem(tp, flag)
register struct tty *tp;
int flag;
@@ -762,10 +881,10 @@ nullmodem(tp, flag)
* reinput pending characters after state switch
* call at spltty().
*/
+static void
ttypend(tp)
register struct tty *tp;
{
- register c;
char *hd, *tl;
tp->t_lflag &= ~PENDIN;
@@ -783,13 +902,14 @@ ttypend(tp)
/*
* Process input of a single character received on a tty.
*/
+void
ttyinput(c, tp)
- register c;
+ register int c;
register struct tty *tp;
{
- register int iflag = tp->t_iflag;
- register int lflag = tp->t_lflag;
- register u_char *cc = tp->t_cc;
+ register tcflag_t iflag = tp->t_iflag;
+ register tcflag_t lflag = tp->t_lflag;
+ register cc_t *cc = tp->t_cc;
int i, err;
/*
@@ -809,6 +929,17 @@ ttyinput(c, tp)
tp->t_rawcc++;
}
/*
+ * If input flow control is enabled and not yet invoked, check the
+ * high water mark. Block further input iff:
+ * current input > threshold AND input is available to user program.
+ * The 3 is slop for PARMRK.
+ */
+ if ((iflag & IXOFF && (tp->t_state & TS_TBLOCK) == 0
+ || tp->t_cflag & TS_HW_IFLOW && (tp->t_state & TS_HW_IFLOW) == 0)
+ && INPUT_LEN(tp) > I_HIGH_WATER - 3
+ && ((lflag & ICANON) == 0 || RB_LEN(&tp->t_can) != 0))
+ ttyblock(tp);
+ /*
* Handle exceptional conditions (break, parity, framing).
*/
if (err = (c&TTY_ERRORMASK)) {
@@ -826,6 +957,8 @@ ttyinput(c, tp)
goto endcase;
else if (iflag&PARMRK) {
parmrk:
+ if (INPUT_LEN(tp) > MAX_INPUT - 3)
+ goto input_overflow;
putc(0377|TTY_QUOTE, &tp->t_raw);
putc(0|TTY_QUOTE, &tp->t_raw);
putc(c|TTY_QUOTE, &tp->t_raw);
@@ -834,11 +967,6 @@ parmrk:
c = 0;
}
}
- /*
- * In tandem mode, check high water mark.
- */
- if (iflag&IXOFF)
- ttyblock(tp);
if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP))
c &= ~0x80;
if ((tp->t_lflag&EXTPROC) == 0) {
@@ -878,7 +1006,7 @@ parmrk:
else {
ttyflush(tp, FWRITE);
ttyecho(c, tp);
- if (RB_LEN(&tp->t_raw) + RB_LEN(&tp->t_can))
+ if (INPUT_LEN(tp) != 0)
ttyretype(tp);
tp->t_lflag |= FLUSHO;
}
@@ -974,7 +1102,6 @@ parmrk:
*/
if (CCEQ(cc[VWERASE], c)) {
int ctype;
- int alt = lflag&ALTWERASE;
/*
* erase whitespace
@@ -991,6 +1118,13 @@ parmrk:
c = unputc(&tp->t_raw);
if (c == -1)
goto endcase;
+ /*
+ * Handle one-letter word cases.
+ */
+ if (c == ' ' || c == '\t') {
+ putc(c, &tp->t_raw);
+ goto endcase;
+ }
ctype = ISALPHA(c);
/*
* erase rest of word
@@ -1001,7 +1135,8 @@ parmrk:
if (c == -1)
goto endcase;
} while (c != ' ' && c != '\t' &&
- (alt == 0 || ISALPHA(c) == ctype));
+ ((lflag & ALTWERASE) == 0
+ || ISALPHA(c) == ctype));
(void) putc(c, &tp->t_raw);
goto endcase;
}
@@ -1025,12 +1160,13 @@ parmrk:
/*
* Check for input buffer overflow
*/
- if (RB_LEN(&tp->t_raw)+RB_LEN(&tp->t_can) >= TTYHOG) {
+ if (INPUT_LEN(tp) >= MAX_INPUT) {
+input_overflow:
if (iflag&IMAXBEL) {
if (RB_LEN(&tp->t_out) < tp->t_hiwat)
(void) ttyoutput(CTRL('g'), tp);
} else
- ttyflush(tp, FREAD | FWRITE);
+ ttyflush(tp, FREAD);
goto endcase;
}
/*
@@ -1062,7 +1198,7 @@ parmrk:
/*
* Place the cursor over the '^' of the ^D.
*/
- i = MIN(2, tp->t_col - i);
+ i = imin(2, tp->t_col - i);
while (i > 0) {
(void) ttyoutput('\b', tp);
i--;
@@ -1089,12 +1225,13 @@ startoutput:
* Returns < 0 if putc succeeds, otherwise returns char to resend.
* Must be recursive.
*/
+static int
ttyoutput(c, tp)
- register c;
+ register int c;
register struct tty *tp;
{
register int col;
- register long oflag = tp->t_oflag;
+ register tcflag_t oflag = tp->t_oflag;
if ((oflag&OPOST) == 0) {
if (tp->t_lflag&FLUSHO)
@@ -1124,11 +1261,11 @@ ttyoutput(c, tp)
#ifdef was
c -= b_to_q(" ", c, &tp->t_outq);
#else
- i = min (c, RB_CONTIGPUT(&tp->t_out));
+ i = imin(c, RB_CONTIGPUT(&tp->t_out));
bcopy(" ", tp->t_out.rb_tl, i);
tp->t_out.rb_tl =
RB_ROLLOVER(&tp->t_out, tp->t_out.rb_tl+i);
- i = min (c-i, RB_CONTIGPUT(&tp->t_out));
+ i = imin(c - i, RB_CONTIGPUT(&tp->t_out));
/* off end and still have space? */
if (i) {
@@ -1189,16 +1326,20 @@ ttyoutput(c, tp)
/*
* Process a read call on a tty device.
*/
+int
ttread(tp, uio, flag)
register struct tty *tp;
struct uio *uio;
+ int flag;
{
register struct ringb *qp;
register int c;
- register long lflag;
- register u_char *cc = tp->t_cc;
+ register tcflag_t lflag;
+ register cc_t *cc = tp->t_cc;
register struct proc *p = curproc;
- int s, first, error = 0;
+ int s, first, error = 0, rblen;
+ int has_stime = 0, last_cc = 0;
+ long slp = 0; /* XXX this should be renamed `timo'. */
loop:
lflag = tp->t_lflag;
@@ -1206,14 +1347,17 @@ loop:
/*
* take pending input first
*/
- if (lflag&PENDIN)
+ if (lflag&PENDIN) {
ttypend(tp);
- splx(s);
+ splx(s); /* reduce latency */
+ s = spltty();
+ }
/*
* Hang process if it's in the background.
*/
if (isbackground(p, tp)) {
+ splx(s);
if ((p->p_sigignore & sigmask(SIGTTIN)) ||
(p->p_sigmask & sigmask(SIGTTIN)) ||
p->p_flag&SPPWAIT || p->p_pgrp->pg_jobc == 0)
@@ -1230,16 +1374,100 @@ loop:
* else use the raw queue.
*/
qp = lflag&ICANON ? &tp->t_can : &tp->t_raw;
+ rblen = RB_LEN(qp);
- /*
- * If there is no input, sleep on rawq
- * awaiting hardware receipt and notification.
- * If we have data, we don't need to check for carrier.
- */
- s = spltty();
- if (RB_LEN(qp) <= 0) {
+ if ((lflag & ICANON) == 0) {
+ int m = cc[VMIN];
+ long t = cc[VTIME];
+ struct timeval stime, timecopy;
+ int x;
+
+ /*
+ * Check each of the four combinations.
+ * (m > 0 && t == 0) is the normal read case.
+ * It should be fairly efficient, so we check that and its
+ * companion case (m == 0 && t == 0) first.
+ * For the other two cases, we compute the target sleep time
+ * into slp.
+ */
+ if (t == 0) {
+ if (rblen < m)
+ goto sleep;
+ if (rblen > 0)
+ goto read;
+
+ /* m, t and rblen are all 0. 0 is enough input. */
+ splx(s);
+ return (0);
+ }
+ t *= 100000; /* time in us */
+#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
+ ((t1).tv_usec - (t2).tv_usec))
+ if (m > 0) {
+ if (rblen <= 0)
+ goto sleep;
+ if (rblen >= m)
+ goto read;
+ x = splclock();
+ timecopy = time;
+ splx(x);
+ if (!has_stime) {
+ /* first character, start timer */
+ has_stime = 1;
+ stime = timecopy;
+ slp = t;
+ } else if (rblen > last_cc) {
+ /* got a character, restart timer */
+ stime = timecopy;
+ slp = t;
+ } else {
+ /* nothing, check expiration */
+ slp = t - diff(timecopy, stime);
+ if (slp <= 0)
+ goto read;
+ }
+ last_cc = rblen;
+ } else { /* m == 0 */
+ if (rblen > 0)
+ goto read;
+ x = splclock();
+ timecopy = time;
+ splx(x);
+ if (!has_stime) {
+ has_stime = 1;
+ stime = timecopy;
+ slp = t;
+ } else {
+ slp = t - diff(timecopy, stime);
+ if (slp <= 0) {
+ /* Timed out, but 0 is enough input. */
+ splx(s);
+ return (0);
+ }
+ }
+ }
+#undef diff
+ /*
+ * Rounding down may make us wake up just short
+ * of the target, so we round up.
+ * The formula is ceiling(slp * hz/1000000).
+ * 32-bit arithmetic is enough for hz < 169.
+ * XXX see hzto() for how to avoid overflow if hz
+ * is large (divide by `tick' and/or arrange to
+ * use hzto() if hz is large).
+ */
+ slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
+ goto sleep;
+ }
+ if (rblen <= 0) {
int carrier;
+sleep:
+ /*
+ * If there is no input, sleep on rawq
+ * awaiting hardware receipt and notification.
+ * If we have data, we don't need to check for carrier.
+ */
carrier = (tp->t_state&TS_CARR_ON) || (tp->t_cflag&CLOCAL);
if (!carrier && tp->t_state&TS_ISOPEN) {
splx(s);
@@ -1249,20 +1477,70 @@ loop:
splx(s);
return (EWOULDBLOCK);
}
+ if (slp) {
+ /*
+ * Use plain wakeup() not ttwakeup().
+ * XXX why not use the timeout built into tsleep?
+ */
+ timeout((timeout_func_t)wakeup, (caddr_t)qp, (int)slp);
+ }
error = ttysleep(tp, (caddr_t)&tp->t_raw, TTIPRI | PCATCH,
carrier ? ttyin : ttopen, 0);
+ if (slp) {
+ slp = 0;
+ untimeout((timeout_func_t)wakeup, (caddr_t)qp);
+ }
splx(s);
if (error)
return (error);
+ /*
+ * XXX what happens if ICANON, MIN or TIME changes or
+ * another process eats some input while we are asleep
+ * (not just here)? It would be safest to detect changes
+ * and reset our state variables (has_stime and last_cc).
+ */
goto loop;
}
- splx(s);
+read:
/*
* Input present, check for input mapping and processing.
*/
first = 1;
- while ((c = getc(qp)) >= 0) {
+ if (lflag & (ICANON | ISIG))
+ goto slowcase;
+ for (;;) {
+ int rcc;
+
+ rcc = RB_CONTIGGET(qp);
+ if (rcc > uio->uio_resid)
+ rcc = uio->uio_resid;
+ if (rcc <= 0) {
+ if (first) {
+ /* queue got flushed (can't happen) */
+ splx(s);
+ goto loop;
+ }
+ break;
+ }
+ error = uiomove(qp->rb_hd, rcc, uio);
+ if (error)
+ break;
+ qp->rb_hd = RB_ROLLOVER(qp, qp->rb_hd + rcc);
+ splx(s);
+ s = spltty();
+ first = 0;
+ }
+ goto out;
+slowcase:
+ for (;;) {
+ c = getc(qp);
+ splx(s);
+ if (c < 0) {
+ if (first)
+ goto loop;
+ break;
+ }
/*
* delayed suspend (^Y)
*/
@@ -1295,28 +1573,21 @@ loop:
*/
if (lflag&ICANON && ttbreakc(c))
break;
+ s = spltty();
first = 0;
}
+ s = spltty();
+
/*
- * Look to unblock output now that (presumably)
+ * Look to unblock input now that (presumably)
* the input queue has gone down.
*/
-#if 0
- if (tp->t_state&TS_TBLOCK && RB_LEN(&tp->t_raw) < TTYHOG/5) {
- if (cc[VSTART] != _POSIX_VDISABLE &&
- putc(cc[VSTART], &tp->t_out) == 0) {
- tp->t_state &= ~TS_TBLOCK;
- ttstart(tp);
- }
- }
-#else
-#define TS_RTSBLOCK TS_TBLOCK /* XXX */
-#define RB_I_LOW_WATER ((RBSZ - 2 * 256) * 7 / 8) /* XXX */
- if (tp->t_state&TS_RTSBLOCK && RB_LEN(&tp->t_raw) <= RB_I_LOW_WATER) {
- tp->t_state &= ~TS_RTSBLOCK;
- ttstart(tp);
- }
-#endif
+out:
+ if (tp->t_state & (TS_TBLOCK | TS_HW_IFLOW)
+ && INPUT_LEN(tp) <= I_LOW_WATER)
+ ttyunblock(tp);
+
+ splx(s);
return (error);
}
@@ -1328,12 +1599,12 @@ loop:
* Sleeps here are not interruptible, but we return prematurely
* if new signals come in.
*/
+int
ttycheckoutq(tp, wait)
register struct tty *tp;
int wait;
{
int hiwat, s, oldsig;
- extern int wakeup();
hiwat = tp->t_hiwat;
s = spltty();
@@ -1348,9 +1619,10 @@ ttycheckoutq(tp, wait)
splx(s);
return (0);
}
- timeout(wakeup, (caddr_t)&tp->t_out, hz);
+ timeout((timeout_func_t)wakeup, (caddr_t)&tp->t_out,
+ hz); /* XXX */
tp->t_state |= TS_ASLEEP;
- sleep((caddr_t)&tp->t_out, PZERO - 1);
+ tsleep((caddr_t)&tp->t_out, PZERO - 1, "ttchout", 0);
}
splx(s);
return (1);
@@ -1359,11 +1631,13 @@ ttycheckoutq(tp, wait)
/*
* Process a write call on a tty device.
*/
+int
ttwrite(tp, uio, flag)
register struct tty *tp;
register struct uio *uio;
+ int flag;
{
- register char *cp;
+ register char *cp = NULL;
register int cc = 0, ce;
register struct proc *p = curproc;
int i, hiwat, cnt, error, s;
@@ -1420,14 +1694,27 @@ loop:
uio->uio_resid = 0;
return (0);
}
- if (RB_LEN(&tp->t_out) > hiwat)
+ /*
+ * The output queue may be changed by the interrupt handler:
+ * (1) certain inputs flush it
+ * (2) sio hacks on it for output completion.
+ * The queue length always (?) shrinks so stale counts from
+ * RB_LEN() are not a problem. However, incorrect counts
+ * caused by in-between pointers are a problem. The locking
+ * to fix this is messy because of all the gotos.
+ */
+ s = spltty();
+ if (RB_LEN(&tp->t_out) > hiwat) {
+ splx(s);
goto ovhiwat;
+ }
+ splx(s);
/*
* Grab a hunk of data from the user,
* unless we have some leftover from last time.
*/
if (cc == 0) {
- cc = min(uio->uio_resid, OBUFSIZ);
+ cc = imin(uio->uio_resid, OBUFSIZ);
cp = obuf;
error = uiomove(cp, cc, uio);
if (error) {
@@ -1459,7 +1746,6 @@ loop:
if (ttyoutput(*cp, tp) >= 0) {
/* no c-lists, wait a bit */
ttstart(tp);
-printf("\nttysleep - no c-lists\n"); /* XXX */
if (error = ttysleep(tp,
(caddr_t)&lbolt,
TTOPRI | PCATCH, ttybuf, 0))
@@ -1467,9 +1753,13 @@ printf("\nttysleep - no c-lists\n"); /* XXX */
goto loop;
}
cp++, cc--;
+ s = spltty();
if ((tp->t_lflag&FLUSHO) ||
- RB_LEN(&tp->t_out) > hiwat)
+ RB_LEN(&tp->t_out) > hiwat) {
+ splx(s);
goto ovhiwat;
+ }
+ splx(s);
continue;
}
}
@@ -1487,7 +1777,8 @@ printf("\nttysleep - no c-lists\n"); /* XXX */
ce -= i;
#else
i = ce;
- ce = min (ce, RB_CONTIGPUT(&tp->t_out));
+ s = spltty();
+ ce = imin(ce, RB_CONTIGPUT(&tp->t_out));
bcopy(cp, tp->t_out.rb_tl, ce);
tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out,
tp->t_out.rb_tl + ce);
@@ -1495,30 +1786,41 @@ printf("\nttysleep - no c-lists\n"); /* XXX */
if (i > 0) {
int ii;
- ii = min (i, RB_CONTIGPUT(&tp->t_out));
+ ii = imin(i, RB_CONTIGPUT(&tp->t_out));
bcopy(cp + ce, tp->t_out.rb_tl, ii);
tp->t_out.rb_tl = RB_ROLLOVER(&tp->t_out,
tp->t_out.rb_tl + ii);
i -= ii;
ce += ii;
}
+ splx(s);
#endif
tp->t_col += ce;
cp += ce, cc -= ce, tk_nout += ce;
tp->t_outcc += ce;
if (i > 0) {
ttstart(tp);
- if (RB_CONTIGPUT(&tp->t_out) > 0)
+ s = spltty();
+ if (RB_CONTIGPUT(&tp->t_out) > 0) {
+ splx(s);
goto loop; /* synchronous/fast */
+ }
/* out of space, wait a bit */
tp->t_state |= TS_ASLEEP;
if (error = ttysleep(tp, (caddr_t)&tp->t_out,
- TTOPRI | PCATCH, ttybuf, 0))
+ TTOPRI | PCATCH, ttybuf, 0)) {
+ splx(s);
break;
+ }
+ splx(s);
goto loop;
}
- if (tp->t_lflag&FLUSHO || RB_LEN(&tp->t_out) > hiwat)
+ s = spltty();
+ if (tp->t_lflag&FLUSHO || RB_LEN(&tp->t_out) > hiwat) {
+ splx(s);
break;
+ }
+ splx(s);
}
ttstart(tp);
}
@@ -1562,8 +1864,9 @@ ovhiwat:
* Rubout one character from the rawq of tp
* as cleanly as possible.
*/
+static void
ttyrub(c, tp)
- register c;
+ register int c;
register struct tty *tp;
{
char *cp;
@@ -1650,6 +1953,7 @@ ttyrub(c, tp)
* Crt back over cnt chars perhaps
* erasing them.
*/
+static void
ttyrubo(tp, cnt)
register struct tty *tp;
int cnt;
@@ -1663,6 +1967,7 @@ ttyrubo(tp, cnt)
* Reprint the rawq line.
* We assume c_cc has already been checked.
*/
+static void
ttyretype(tp)
register struct tty *tp;
{
@@ -1690,20 +1995,17 @@ ttyretype(tp)
/*
* Echo a typed character to the terminal.
*/
+static void
ttyecho(c, tp)
- register c;
+ register int c;
register struct tty *tp;
{
if ((tp->t_state & TS_CNTTB) == 0)
tp->t_lflag &= ~FLUSHO;
- if (tp->t_lflag & EXTPROC)
+ if (tp->t_lflag & EXTPROC
+ || (tp->t_lflag & ECHO) == 0
+ && (c != '\n' || (tp->t_lflag & ECHONL) == 0))
return;
- if ((tp->t_lflag & ECHO) == 0) {
- if ((tp->t_lflag & ECHONL) == 0)
- return;
- else if (c != '\n')
- return;
- }
if (tp->t_lflag & ECHOCTL) {
if ((c & TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' ||
c == 0177) {
@@ -1721,6 +2023,7 @@ ttyecho(c, tp)
/*
* send string cp to tp
*/
+static void
ttyoutstr(cp, tp)
register char *cp;
register struct tty *tp;
@@ -1734,6 +2037,7 @@ ttyoutstr(cp, tp)
/*
* Wake up any readers on a tty.
*/
+void
ttwakeup(tp)
register struct tty *tp;
{
@@ -1752,7 +2056,9 @@ ttwakeup(tp)
* Look up a code for a specified speed in a conversion table;
* used by drivers to map software speed values to hardware parameters.
*/
+int
ttspeedtab(speed, table)
+ int speed;
register struct speedtab *table;
{
@@ -1769,6 +2075,7 @@ ttspeedtab(speed, table)
* from hi to low water.
*
*/
+void
ttsetwater(tp)
struct tty *tp;
{
@@ -1786,19 +2093,20 @@ ttsetwater(tp)
/*
* Report on state of foreground process group.
*/
+void
ttyinfo(tp)
register struct tty *tp;
{
register struct proc *p, *pick;
struct timeval utime, stime;
- int tmp;
+ int loadtmp;
if (ttycheckoutq(tp,0) == 0)
return;
/* Print load average. */
- tmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
- ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
+ loadtmp = (averunnable[0] * 100 + FSCALE / 2) >> FSHIFT;
+ ttyprintf(tp, "load: %d.%02d ", loadtmp / 100, loadtmp % 100);
if (tp->t_session == NULL)
ttyprintf(tp, "not a controlling terminal\n");
@@ -1807,25 +2115,47 @@ ttyinfo(tp)
else if ((p = tp->t_pgrp->pg_mem) == NULL)
ttyprintf(tp, "empty foreground process group\n");
else {
+ int kspace;
+ int s;
+ pid_t pid;
+ char wmesg[WMESGLEN+1];
+ char comm[MAXCOMLEN+1];
/* Pick interesting process. */
for (pick = NULL; p != NULL; p = p->p_pgrpnxt)
if (proc_compare(pick, p))
pick = p;
- ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
+ if( pick == NULL) {
+ ttyprintf(tp, "process went away\n");
+ goto finish;
+ }
+
+#define pgtok(a) (((a) * NBPG) / 1024)
+
+ if( (pick->p_flag & SLOAD) && (pick->p_vmspace))
+ kspace = pgtok(pick->p_vmspace->vm_pmap.pm_stats.resident_count);
+ else
+ kspace = 0;
+ strncpy(wmesg, ((pick->p_flag & SLOAD) == 0 ? "swapped":
pick->p_stat == SRUN ? "running" :
- pick->p_wmesg ? pick->p_wmesg : "iowait");
+ pick->p_wmesg ? pick->p_wmesg : "iowait"), WMESGLEN);
+ wmesg[WMESGLEN] = 0;
+
+ strncpy(comm, pick->p_comm ? pick->p_comm : "", MAXCOMLEN);
+ comm[MAXCOMLEN] = 0;
+
+ loadtmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
+
+ pid = pick->p_pid;
/*
* Lock out clock if process is running; get user/system
* cpu time.
*/
- if (curproc == pick)
- tmp = splclock();
utime = pick->p_utime;
stime = pick->p_stime;
- if (curproc == pick)
- splx(tmp);
+
+ ttyprintf(tp, " cmd: %s %d [%s] ", comm, pid, wmesg);
/* Print user time. */
ttyprintf(tp, "%d.%02du ",
@@ -1835,12 +2165,10 @@ ttyinfo(tp)
ttyprintf(tp, "%d.%02ds ",
stime.tv_sec, (stime.tv_usec + 5000) / 10000);
-#define pgtok(a) (((a) * NBPG) / 1024)
/* Print percentage cpu, resident set size. */
- tmp = pick->p_pctcpu * 10000 + FSCALE / 2 >> FSHIFT;
- ttyprintf(tp, "%d%% %dk\n",
- tmp / 100, pgtok(pick->p_vmspace->vm_rssize));
+ ttyprintf(tp, "%d%% %dk\n", loadtmp / 100, kspace);
}
+finish:
tp->t_rocount = 0; /* so pending input will be retyped if BS */
}
@@ -1923,6 +2251,7 @@ proc_compare(p1, p2)
/*
* Output char to tty; console putchar style.
*/
+int
tputchar(c, tp)
int c;
struct tty *tp;
@@ -1947,15 +2276,16 @@ tputchar(c, tp)
* reported by tsleep. If the tty is revoked, restarting a pending
* call will redo validation done at the start of the call.
*/
+int
ttysleep(tp, chan, pri, wmesg, timo)
struct tty *tp;
caddr_t chan;
int pri;
- char *wmesg;
+ const char *wmesg;
int timo;
{
int error;
- short gen = tp->t_gen;
+ int gen = tp->t_gen;
if (error = tsleep(chan, pri, wmesg, timo))
return (error);
diff --git a/sys/kern/tty_chu.c b/sys/kern/tty_chu.c
new file mode 100644
index 000000000000..4615875e77e0
--- /dev/null
+++ b/sys/kern/tty_chu.c
@@ -0,0 +1,276 @@
+/* tty_chu.c,v 3.1 1993/07/06 01:07:30 jbj Exp
+ * tty_chu.c - CHU line driver
+ */
+
+#include "chu.h"
+#if NCHU > 0
+
+#include "../h/param.h"
+#include "../h/types.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/ioctl.h"
+#include "../h/tty.h"
+#include "../h/proc.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/uio.h"
+
+#include "../h/chudefs.h"
+
+/*
+ * Line discipline for receiving CHU time codes.
+ * Does elementary noise elimination, takes time stamps after
+ * the arrival of each character, returns a buffer full of the
+ * received 10 character code and the associated time stamps.
+ */
+#define NUMCHUBUFS 3
+
+struct chudata {
+ u_char used; /* Set to 1 when structure in use */
+ u_char lastindex; /* least recently used buffer */
+ u_char curindex; /* buffer to use */
+ u_char sleeping; /* set to 1 when we're sleeping on a buffer */
+ struct chucode chubuf[NUMCHUBUFS];
+} chu_data[NCHU];
+
+/*
+ * Number of microseconds we allow between
+ * character arrivals. The speed is 300 baud
+ * so this should be somewhat more than 30 msec
+ */
+#define CHUMAXUSEC (50*1000) /* 50 msec */
+
+int chu_debug = 0;
+
+/*
+ * Open as CHU time discipline. Called when discipline changed
+ * with ioctl, and changes the interpretation of the information
+ * in the tty structure.
+ */
+/*ARGSUSED*/
+chuopen(dev, tp)
+ dev_t dev;
+ register struct tty *tp;
+{
+ register struct chudata *chu;
+
+ /*
+ * Don't allow multiple opens. This will also protect us
+ * from someone opening /dev/tty
+ */
+ if (tp->t_line == CHULDISC)
+ return (EBUSY);
+ ttywflush(tp);
+ for (chu = chu_data; chu < &chu_data[NCHU]; chu++)
+ if (!chu->used)
+ break;
+ if (chu >= &chu[NCHU])
+ return (EBUSY);
+ chu->used++;
+ chu->lastindex = chu->curindex = 0;
+ chu->sleeping = 0;
+ chu->chubuf[0].ncodechars = 0;
+ tp->T_LINEP = (caddr_t) chu;
+ return (0);
+}
+
+/*
+ * Break down... called when discipline changed or from device
+ * close routine.
+ */
+chuclose(tp)
+ register struct tty *tp;
+{
+ register int s = spl5();
+
+ ((struct chudata *) tp->T_LINEP)->used = 0;
+ tp->t_cp = 0;
+ tp->t_inbuf = 0;
+ tp->t_rawq.c_cc = 0; /* clear queues -- paranoid */
+ tp->t_canq.c_cc = 0;
+ tp->t_line = 0; /* paranoid: avoid races */
+ splx(s);
+}
+
+/*
+ * Read a CHU buffer. Sleep on the current buffer
+ */
+churead(tp, uio)
+ register struct tty *tp;
+ struct uio *uio;
+{
+ register struct chudata *chu;
+ register struct chucode *chucode;
+ register int s;
+
+ if ((tp->t_state&TS_CARR_ON)==0)
+ return (EIO);
+
+ chu = (struct chudata *) (tp->T_LINEP);
+
+ s = spl5();
+ chucode = &(chu->chubuf[chu->lastindex]);
+ while (chu->curindex == chu->lastindex) {
+ chu->sleeping = 1;
+ sleep((caddr_t)chucode, TTIPRI);
+ }
+ chu->sleeping = 0;
+ if (++(chu->lastindex) >= NUMCHUBUFS)
+ chu->lastindex = 0;
+ splx(s);
+
+ return (uiomove((caddr_t)chucode, sizeof(*chucode), UIO_READ, uio));
+}
+
+/*
+ * Low level character input routine.
+ * If the character looks okay, grab a time stamp. If the stuff in
+ * the buffer is too old, dump it and start fresh. If the character is
+ * non-BCDish, everything in the buffer too.
+ */
+chuinput(c, tp)
+ register int c;
+ register struct tty *tp;
+{
+ register struct chudata *chu = (struct chudata *) tp->T_LINEP;
+ register struct chucode *chuc;
+ register int i;
+ long sec, usec;
+ struct timeval tv;
+
+ /*
+ * Do a check on the BSDness of the character. This delays
+ * the time stamp a bit but saves a fair amount of overhead
+ * when the static is bad.
+ */
+ if (((c) & 0xf) > 9 || (((c)>>4) & 0xf) > 9) {
+ chuc = &(chu->chubuf[chu->curindex]);
+ chuc->ncodechars = 0; /* blow all previous away */
+ return;
+ }
+
+ /*
+ * Call microtime() to get the current time of day
+ */
+ microtime(&tv);
+
+ /*
+ * Compute the difference in this character's time stamp
+ * and the last. If it exceeds the margin, blow away all
+ * the characters currently in the buffer.
+ */
+ chuc = &(chu->chubuf[chu->curindex]);
+ i = (int)chuc->ncodechars;
+ if (i > 0) {
+ sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec;
+ usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec;
+ if (usec < 0) {
+ sec -= 1;
+ usec += 1000000;
+ }
+ if (sec != 0 || usec > CHUMAXUSEC) {
+ i = 0;
+ chuc->ncodechars = 0;
+ }
+ }
+
+ /*
+ * Store the character. If we're done, have to tell someone
+ */
+ chuc->codechars[i] = (u_char)c;
+ chuc->codetimes[i] = tv;
+
+ if (++i < NCHUCHARS) {
+ /*
+ * Not much to do here. Save the count and wait
+ * for another character.
+ */
+ chuc->ncodechars = (u_char)i;
+ } else {
+ /*
+ * Mark this buffer full and point at next. If the
+ * next buffer is full we overwrite it by bumping the
+ * next pointer.
+ */
+ chuc->ncodechars = NCHUCHARS;
+ if (++(chu->curindex) >= NUMCHUBUFS)
+ chu->curindex = 0;
+ if (chu->curindex == chu->lastindex)
+ if (++(chu->lastindex) >= NUMCHUBUFS)
+ chu->lastindex = 0;
+ chu->chubuf[chu->curindex].ncodechars = 0;
+
+ /*
+ * Wake up anyone sleeping on this. Also wake up
+ * selectors and/or deliver a SIGIO as required.
+ */
+ if (tp->t_rsel) {
+ selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
+ tp->t_state &= ~TS_RCOLL;
+ tp->t_rsel = 0;
+ }
+ if (tp->t_state & TS_ASYNC)
+ gsignal(tp->t_pgrp, SIGIO);
+ if (chu->sleeping)
+ (void) wakeup((caddr_t)chuc);
+ }
+}
+
+/*
+ * Handle ioctls. We reject all tty-style except those that
+ * change the line discipline.
+ */
+chuioctl(tp, cmd, data, flag)
+ struct tty *tp;
+ int cmd;
+ caddr_t data;
+ int flag;
+{
+
+ if ((cmd>>8) != 't')
+ return (-1);
+ switch (cmd) {
+ case TIOCSETD:
+ case TIOCGETD:
+ case TIOCGETP:
+ case TIOCGETC:
+ return (-1);
+ }
+ return (ENOTTY); /* not quite appropriate */
+}
+
+
+chuselect(dev, rw)
+ dev_t dev;
+ int rw;
+{
+ register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
+ struct chudata *chu;
+ int s = spl5();
+
+ chu = (struct chudata *) (tp->T_LINEP);
+
+ switch (rw) {
+
+ case FREAD:
+ if (chu->curindex != chu->lastindex)
+ goto win;
+ if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
+ tp->t_state |= TS_RCOLL;
+ else
+ tp->t_rsel = u.u_procp;
+ break;
+
+ case FWRITE:
+ goto win;
+ }
+ splx(s);
+ return (0);
+win:
+ splx(s);
+ return (1);
+}
+#endif NCHU
diff --git a/sys/kern/tty_clk.c b/sys/kern/tty_clk.c
new file mode 100644
index 000000000000..d1b4bbef64b4
--- /dev/null
+++ b/sys/kern/tty_clk.c
@@ -0,0 +1,303 @@
+/* tty_clk.c,v 3.1 1993/07/06 01:07:33 jbj Exp
+ * tty_clk.c - Generic line driver for receiving radio clock timecodes
+ */
+
+#include "clk.h"
+#if NCLK > 0
+
+#include "../h/param.h"
+#include "../h/types.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/ioctl.h"
+#include "../h/tty.h"
+#include "../h/proc.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/uio.h"
+#include "../h/clist.h"
+
+/*
+ * This line discipline is intended to provide well performing
+ * generic support for the reception and time stamping of radio clock
+ * timecodes. Most radio clock devices return a string where a
+ * particular character in the code (usually a \r) is on-time
+ * synchronized with the clock. The idea here is to collect characters
+ * until (one of) the synchronization character(s) (we allow two) is seen.
+ * When the magic character arrives we take a timestamp by calling
+ * microtime() and insert the eight bytes of struct timeval into the
+ * buffer after the magic character. We then wake up anyone waiting
+ * for the buffer and return the whole mess on the next read.
+ *
+ * To use this the calling program is expected to first open the
+ * port, and then to set the port into raw mode with the speed
+ * set appropriately with a TIOCSETP ioctl(), with the erase and kill
+ * characters set to those to be considered magic (yes, I know this
+ * is gross, but they were so convenient). If only one character is
+ * magic you can set then both the same, or perhaps to the alternate
+ * parity versions of said character. After getting all this set,
+ * change the line discipline to CLKLDISC and you are on your way.
+ *
+ * The only other bit of magic we do in here is to flush the receive
+ * buffers on writes if the CRMOD flag is set (hack, hack).
+ */
+
+/*
+ * We run this very much like a raw mode terminal, with the exception
+ * that we store up characters locally until we hit one of the
+ * magic ones and then dump it into the rawq all at once. We keep
+ * the buffered data in clists since we can then often move it to
+ * the rawq without copying. For sanity we limit the number of
+ * characters between specials, and the total number of characters
+ * before we flush the rawq, as follows.
+ */
+#define CLKLINESIZE (256)
+#define NCLKCHARS (CLKLINESIZE*4)
+
+struct clkdata {
+ int inuse;
+ struct clist clkbuf;
+};
+#define clk_cc clkbuf.c_cc
+#define clk_cf clkbuf.c_cf
+#define clk_cl clkbuf.c_cl
+
+struct clkdata clk_data[NCLK];
+
+/*
+ * Routine for flushing the internal clist
+ */
+#define clk_bflush(clk) (ndflush(&((clk)->clkbuf), (clk)->clk_cc))
+
+int clk_debug = 0;
+
+/*ARGSUSED*/
+clkopen(dev, tp)
+ dev_t dev;
+ register struct tty *tp;
+{
+ register struct clkdata *clk;
+
+ /*
+ * Don't allow multiple opens. This will also protect us
+ * from someone opening /dev/tty
+ */
+ if (tp->t_line == CLKLDISC)
+ return (EBUSY);
+ ttywflush(tp);
+ for (clk = clk_data; clk < &clk_data[NCLK]; clk++)
+ if (!clk->inuse)
+ break;
+ if (clk >= &clk_data[NCLK])
+ return (EBUSY);
+ clk->inuse++;
+ clk->clk_cc = 0;
+ clk->clk_cf = clk->clk_cl = NULL;
+ tp->T_LINEP = (caddr_t) clk;
+ return (0);
+}
+
+
+/*
+ * Break down... called when discipline changed or from device
+ * close routine.
+ */
+clkclose(tp)
+ register struct tty *tp;
+{
+ register struct clkdata *clk;
+ register int s = spltty();
+
+ clk = (struct clkdata *)tp->T_LINEP;
+ if (clk->clk_cc > 0)
+ clk_bflush(clk);
+ clk->inuse = 0;
+ tp->t_line = 0; /* paranoid: avoid races */
+ splx(s);
+}
+
+
+/*
+ * Receive a write request. We pass these requests on to the terminal
+ * driver, except that if the CRMOD bit is set in the flags we
+ * first flush the input queues.
+ */
+clkwrite(tp, uio)
+ register struct tty *tp;
+ struct uio *uio;
+{
+ if (tp->t_flags & CRMOD) {
+ register struct clkdata *clk;
+ int s;
+
+ s = spltty();
+ if (tp->t_rawq.c_cc > 0)
+ ndflush(&tp->t_rawq, tp->t_rawq.c_cc);
+ clk = (struct clkdata *) tp->T_LINEP;
+ if (clk->clk_cc > 0)
+ clk_bflush(clk);
+ (void)splx(s);
+ }
+ ttwrite(tp, uio);
+}
+
+
+/*
+ * Low level character input routine.
+ * If the character looks okay, grab a time stamp. If the stuff in
+ * the buffer is too old, dump it and start fresh. If the character is
+ * non-BCDish, everything in the buffer too.
+ */
+clkinput(c, tp)
+ register int c;
+ register struct tty *tp;
+{
+ register struct clkdata *clk;
+ register int i;
+ register long s;
+ struct timeval tv;
+
+ /*
+ * Check to see whether this isn't the magic character. If not,
+ * save the character and return.
+ */
+#ifdef ultrix
+ if (c != tp->t_cc[VERASE] && c != tp->t_cc[VKILL]) {
+#else
+ if (c != tp->t_erase && c != tp->t_kill) {
+#endif
+ clk = (struct clkdata *) tp->T_LINEP;
+ if (clk->clk_cc >= CLKLINESIZE)
+ clk_bflush(clk);
+ if (putc(c, &clk->clkbuf) == -1) {
+ /*
+ * Hopeless, no clists. Flush what we have
+ * and hope things improve.
+ */
+ clk_bflush(clk);
+ }
+ return;
+ }
+
+ /*
+ * Here we have a magic character. Get a timestamp and store
+ * everything.
+ */
+ microtime(&tv);
+ clk = (struct clkdata *) tp->T_LINEP;
+
+ if (putc(c, &clk->clkbuf) == -1)
+ goto flushout;
+
+ s = tv.tv_sec;
+ for (i = 0; i < sizeof(long); i++) {
+ if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)
+ goto flushout;
+ s <<= 8;
+ }
+
+ s = tv.tv_usec;
+ for (i = 0; i < sizeof(long); i++) {
+ if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)
+ goto flushout;
+ s <<= 8;
+ }
+
+ /*
+ * If the length of the rawq exceeds our sanity limit, dump
+ * all the old crap in there before copying this in.
+ */
+ if (tp->t_rawq.c_cc > NCLKCHARS)
+ ndflush(&tp->t_rawq, tp->t_rawq.c_cc);
+
+ /*
+ * Now copy the buffer in. There is a special case optimization
+ * here. If there is nothing on the rawq at present we can
+ * just copy the clists we own over. Otherwise we must concatenate
+ * the present data on the end.
+ */
+ s = (long)spltty();
+ if (tp->t_rawq.c_cc <= 0) {
+ tp->t_rawq = clk->clkbuf;
+ clk->clk_cc = 0;
+ clk->clk_cl = clk->clk_cf = NULL;
+ (void) splx((int)s);
+ } else {
+ (void) splx((int)s);
+ catq(&clk->clkbuf, &tp->t_rawq);
+ clk_bflush(clk);
+ }
+
+ /*
+ * Tell the world
+ */
+ ttwakeup(tp);
+ return;
+
+flushout:
+ /*
+ * It would be nice if this never happened. Flush the
+ * internal clists and hope someone else frees some of them
+ */
+ clk_bflush(clk);
+ return;
+}
+
+
+/*
+ * Handle ioctls. We reject most tty-style except those that
+ * change the line discipline and a couple of others..
+ */
+clkioctl(tp, cmd, data, flag)
+ struct tty *tp;
+ int cmd;
+ caddr_t data;
+ int flag;
+{
+ int flags;
+ struct sgttyb *sg;
+
+ if ((cmd>>8) != 't')
+ return (-1);
+ switch (cmd) {
+ case TIOCSETD:
+ case TIOCGETD:
+ case TIOCGETP:
+ case TIOCGETC:
+ case TIOCOUTQ:
+ return (-1);
+
+ case TIOCSETP:
+ /*
+ * He likely wants to set new magic characters in.
+ * Do this part.
+ */
+ sg = (struct sgttyb *)data;
+#ifdef ultrix
+ tp->t_cc[VERASE] = sg->sg_erase;
+ tp->t_cc[VKILL] = sg->sg_kill;
+#else
+ tp->t_erase = sg->sg_erase;
+ tp->t_kill = sg->sg_kill;
+#endif
+ return (0);
+
+ case TIOCFLUSH:
+ flags = *(int *)data;
+ if (flags == 0 || (flags & FREAD)) {
+ register struct clkdata *clk;
+
+ clk = (struct clkdata *) tp->T_LINEP;
+ if (clk->clk_cc > 0)
+ clk_bflush(clk);
+ }
+ return (-1);
+
+ default:
+ break;
+ }
+ return (ENOTTY); /* not quite appropriate */
+}
+#endif NCLK
diff --git a/sys/kern/tty_compat.c b/sys/kern/tty_compat.c
index a3b92500059c..45994be7ee27 100644
--- a/sys/kern/tty_compat.c
+++ b/sys/kern/tty_compat.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)tty_compat.c 7.10 (Berkeley) 5/9/91
- * $Id: tty_compat.c,v 1.2 1993/10/16 15:24:57 rgrimes Exp $
+ * $Id: tty_compat.c,v 1.4 1993/12/19 00:51:40 wollman Exp $
*/
/*
@@ -51,6 +51,10 @@
#include "kernel.h"
#include "syslog.h"
+static int ttcompatgetflags(struct tty *);
+static void ttcompatsetflags(struct tty *, struct termios *);
+static void ttcompatsetlflags(struct tty *, struct termios *);
+
int ttydebug = 0;
static struct speedtab compatspeeds[] = {
@@ -81,9 +85,12 @@ static int compatspcodes[] = {
};
/*ARGSUSED*/
+int
ttcompat(tp, com, data, flag)
register struct tty *tp;
+ int com;
caddr_t data;
+ int flag;
{
switch (com) {
@@ -123,7 +130,7 @@ ttcompat(tp, com, data, flag)
term.c_ospeed = compatspcodes[speed];
term.c_cc[VERASE] = sg->sg_erase;
term.c_cc[VKILL] = sg->sg_kill;
- tp->t_flags = tp->t_flags&0xffff0000 | sg->sg_flags&0xffff;
+ tp->t_flags = tp->t_flags&0xffff0000UL | sg->sg_flags&0xffff;
ttcompatsetflags(tp, &term);
return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
(caddr_t)&term, flag));
@@ -189,7 +196,8 @@ ttcompat(tp, com, data, flag)
tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
else {
tp->t_flags =
- (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
+ (ttcompatgetflags(tp) & 0xffff0000UL)
+ | (tp->t_flags & 0xffff);
if (com == TIOCLBIS)
tp->t_flags |= *(int *)data<<16;
else
@@ -200,7 +208,8 @@ ttcompat(tp, com, data, flag)
}
case TIOCLGET:
tp->t_flags =
- (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
+ (ttcompatgetflags(tp) & 0xffff0000UL)
+ | (tp->t_flags & 0xffff);
*(int *)data = tp->t_flags>>16;
if (ttydebug)
printf("CLGET: returning %x\n", *(int *)data);
@@ -227,6 +236,7 @@ ttcompat(tp, com, data, flag)
return (0);
}
+static int
ttcompatgetflags(tp)
register struct tty *tp;
{
@@ -284,6 +294,7 @@ if (ttydebug)
return (flags);
}
+static void
ttcompatsetflags(tp, t)
register struct tty *tp;
register struct termios *t;
@@ -356,6 +367,7 @@ ttcompatsetflags(tp, t)
t->c_cflag = cflag;
}
+static void
ttcompatsetlflags(tp, t)
register struct tty *tp;
register struct termios *t;
diff --git a/sys/kern/tty_conf.c b/sys/kern/tty_conf.c
index 861adfe4b324..6b9ad4917460 100644
--- a/sys/kern/tty_conf.c
+++ b/sys/kern/tty_conf.c
@@ -1,3 +1,10 @@
+/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
/*-
* Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
* All rights reserved.
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)tty_conf.c 7.6 (Berkeley) 5/9/91
- * $Id: tty_conf.c,v 1.3 1993/10/16 15:24:58 rgrimes Exp $
+ * $Id: tty_conf.c,v 1.6.2.1 1994/05/04 07:54:52 rgrimes Exp $
*/
#include "param.h"
@@ -43,10 +50,12 @@
int enodev();
int nullop();
+static int nullioctl(struct tty *, int, caddr_t, int);
-int ttyopen(),ttylclose(),ttread(),ttwrite(),nullioctl(),ttstart();
-int ttymodem(), nullmodem(), ttyinput();
+#define VE(x) ((void (*)())x) /* XXX */
+#define IE(x) ((int (*)())x) /* XXX */
+/* XXX - doesn't work */
#include "tb.h"
#if NTB > 0
int tbopen(),tbclose(),tbread(),tbinput(),tbioctl();
@@ -68,31 +77,32 @@ struct linesw linesw[] =
ttyopen, ttylclose, ttread, ttwrite, nullioctl,
ttyinput, enodev, nullop, ttstart, ttymodem, /* 0- termios */
- enodev, enodev, enodev, enodev, enodev, /* 1- defunct */
- enodev, enodev, enodev, enodev, enodev,
+ IE(enodev), VE(enodev), IE(enodev), IE(enodev), IE(enodev), /* 1- defunct */
+ VE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev),
+
+ ttyopen, ttylclose, ttread, ttwrite, nullioctl,
+ ttyinput, enodev, nullop, ttstart, ttymodem, /* 2- NTTYDISC */
- enodev, enodev, enodev, enodev, enodev, /* 2- defunct */
- enodev, enodev, enodev, enodev, enodev,
#if NTB > 0
- tbopen, tbclose, tbread, enodev, tbioctl,
+ tbopen, tbclose, tbread, IE(enodev), tbioctl,
tbinput, enodev, nullop, ttstart, nullmodem, /* 3- TABLDISC */
#else
- enodev, enodev, enodev, enodev, enodev,
- enodev, enodev, enodev, enodev, enodev,
+ IE(enodev), VE(enodev), IE(enodev), IE(enodev), IE(enodev),
+ VE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev),
#endif
#if NSL > 0
- slopen, slclose, enodev, enodev, sltioctl,
- slinput, enodev, nullop, slstart, nullmodem, /* 4- SLIPDISC */
+ slopen, VE(slclose), IE(enodev), IE(enodev), sltioctl,
+ VE(slinput), enodev, nullop, VE(slstart), nullmodem, /* 4- SLIPDISC */
#else
- enodev, enodev, enodev, enodev, enodev,
- enodev, enodev, enodev, enodev, enodev,
+ IE(enodev), VE(enodev), IE(enodev), IE(enodev), IE(enodev),
+ VE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev),
#endif
#if NPPP > 0
- pppopen, pppclose, pppread, pppwrite, ppptioctl,
- pppinput, enodev, nullop, pppstart, ttymodem, /* 5- PPPDISC */
+ pppopen, VE(pppclose), pppread, pppwrite, ppptioctl,
+ VE(pppinput), enodev, nullop, VE(pppstart), ttymodem, /* 5- PPPDISC */
#else
- enodev, enodev, enodev, enodev, enodev,
- enodev, enodev, enodev, enodev, enodev,
+ IE(enodev), VE(enodev), IE(enodev), IE(enodev), IE(enodev),
+ VE(enodev), IE(enodev), IE(enodev), VE(enodev), IE(enodev),
#endif
};
@@ -103,8 +113,10 @@ int nldisp = sizeof (linesw) / sizeof (linesw[0]);
* discipline specific ioctl command.
*/
/*ARGSUSED*/
+static int
nullioctl(tp, cmd, data, flags)
struct tty *tp;
+ int cmd;
char *data;
int flags;
{
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index b324ca4a1b29..0e99e9329e0a 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)tty_pty.c 7.21 (Berkeley) 5/30/91
- * $Id: tty_pty.c,v 1.4 1993/10/16 15:25:00 rgrimes Exp $
+ * $Id: tty_pty.c,v 1.9 1994/01/29 04:04:26 davidg Exp $
*/
/*
@@ -51,6 +51,7 @@
#include "uio.h"
#include "kernel.h"
#include "vnode.h"
+#include "signalvar.h"
#if NPTY == 1
#undef NPTY
@@ -59,6 +60,8 @@
#define BUFSIZ 100 /* Chunk size iomoved to/from user */
+static void ptcwakeup(struct tty *, int);
+
/*
* pts == /dev/tty[pqrs]?
* ptc == /dev/pty[pqrs]?
@@ -81,8 +84,11 @@ int npty = NPTY; /* for pstat -t */
#define PF_UCNTL 0x80 /* user control mode */
/*ARGSUSED*/
+int
ptsopen(dev, flag, devtype, p)
dev_t dev;
+ int flag;
+ int devtype;
struct proc *p;
{
register struct tty *tp;
@@ -120,6 +126,7 @@ ptsopen(dev, flag, devtype, p)
return (error);
}
+int
ptsclose(dev, flag, mode, p)
dev_t dev;
int flag, mode;
@@ -134,9 +141,11 @@ ptsclose(dev, flag, mode, p)
return(0);
}
+int
ptsread(dev, uio, flag)
dev_t dev;
struct uio *uio;
+ int flag;
{
struct proc *p = curproc;
register struct tty *tp = &pt_tty[minor(dev)];
@@ -185,9 +194,11 @@ again:
* Wakeups of controlling tty will happen
* indirectly, when tty driver calls ptsstart.
*/
+int
ptswrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
+ int flag;
{
register struct tty *tp;
@@ -201,6 +212,7 @@ ptswrite(dev, uio, flag)
* Start output on pseudo-tty.
* Wake up process selecting or sleeping for input from controlling tty.
*/
+void
ptsstart(tp)
struct tty *tp;
{
@@ -215,8 +227,10 @@ ptsstart(tp)
ptcwakeup(tp, FREAD);
}
+static void
ptcwakeup(tp, flag)
struct tty *tp;
+ int flag;
{
struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
@@ -239,8 +253,9 @@ ptcwakeup(tp, flag)
}
/*ARGSUSED*/
+int
#ifdef __STDC__
-ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
+ptcopen(int /*dev_t*/ dev, int flag, int devtype, struct proc *p)
#else
ptcopen(dev, flag, devtype, p)
dev_t dev;
@@ -267,6 +282,8 @@ ptcopen(dev, flag, devtype, p)
}
extern struct tty *constty; /* -hv- 06.Oct.92*/
+
+int
ptcclose(dev)
dev_t dev;
{
@@ -278,16 +295,17 @@ ptcclose(dev)
tp->t_oproc = 0; /* mark closed */
tp->t_session = 0;
-/* XXX -hv- 6.Oct.92 this prevents the "hanging console bug" with X11 */
if (constty==tp)
constty = 0;
return (0);
}
+int
ptcread(dev, uio, flag)
dev_t dev;
struct uio *uio;
+ int flag;
{
register struct tty *tp = &pt_tty[minor(dev)];
struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
@@ -363,6 +381,7 @@ ptcread(dev, uio, flag)
return (error);
}
+void
ptsstop(tp, flush)
register struct tty *tp;
int flush;
@@ -386,6 +405,7 @@ ptsstop(tp, flush)
ptcwakeup(tp, flag);
}
+int
ptcselect(dev, rw, p)
dev_t dev;
int rw;
@@ -447,12 +467,14 @@ ptcselect(dev, rw, p)
return (0);
}
+int
ptcwrite(dev, uio, flag)
dev_t dev;
register struct uio *uio;
+ int flag;
{
register struct tty *tp = &pt_tty[minor(dev)];
- register u_char *cp;
+ register u_char *cp = 0;
register int cc = 0;
u_char locbuf[BUFSIZ];
int cnt = 0;
@@ -542,15 +564,17 @@ block:
}
/*ARGSUSED*/
+int
ptyioctl(dev, cmd, data, flag)
caddr_t data;
+ int cmd;
dev_t dev;
+ int flag;
{
register struct tty *tp = &pt_tty[minor(dev)];
register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
register u_char *cc = tp->t_cc;
int stop, error;
- extern ttyinput();
/*
* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
diff --git a/sys/kern/tty_ring.c b/sys/kern/tty_ring.c
index f4149e576214..5c1e1fbcb4fa 100644
--- a/sys/kern/tty_ring.c
+++ b/sys/kern/tty_ring.c
@@ -45,7 +45,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: tty_ring.c,v 1.2 1993/10/16 15:25:01 rgrimes Exp $
+ * $Id: tty_ring.c,v 1.4 1993/12/19 00:51:42 wollman Exp $
*/
#include "param.h"
@@ -54,12 +54,10 @@
#include "ioctl.h"
#include "tty.h"
-/*
- * XXX - put this in tty.h someday.
- */
-size_t rb_write __P((struct ringb *to, char *buf, size_t nfrom));
-
-putc(c, rbp) struct ringb *rbp;
+int
+putc(c, rbp)
+ int c;
+ struct ringb *rbp;
{
char *nxtp;
@@ -72,7 +70,9 @@ putc(c, rbp) struct ringb *rbp;
return(0);
}
-getc(rbp) struct ringb *rbp;
+int
+getc(rbp)
+ struct ringb *rbp;
{
u_char c;
@@ -85,7 +85,11 @@ getc(rbp) struct ringb *rbp;
return (c);
}
-nextc(cpp, rbp) struct ringb *rbp; char **cpp; {
+int
+nextc(cpp, rbp)
+ char **cpp;
+ struct ringb *rbp;
+{
if (*cpp == rbp->rb_tl) return (0);
else { char *cp;
@@ -95,7 +99,10 @@ nextc(cpp, rbp) struct ringb *rbp; char **cpp; {
}
}
-ungetc(c, rbp) struct ringb *rbp;
+int
+ungetc(c, rbp)
+ int c;
+ struct ringb *rbp;
{
char *backp;
@@ -108,7 +115,9 @@ ungetc(c, rbp) struct ringb *rbp;
return(0);
}
-unputc(rbp) struct ringb *rbp;
+int
+unputc(rbp)
+ struct ringb *rbp;
{
char *backp;
int c;
@@ -126,7 +135,10 @@ unputc(rbp) struct ringb *rbp;
#define peekc(rbp) (*(rbp)->rb_hd)
-initrb(rbp) struct ringb *rbp; {
+void
+initrb(rbp)
+ struct ringb *rbp;
+{
rbp->rb_hd = rbp->rb_tl = rbp->rb_buf;
}
@@ -157,6 +169,7 @@ initrb(rbp) struct ringb *rbp; {
/*
* Concatenate ring buffers.
*/
+void
catb(from, to)
struct ringb *from, *to;
{
diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c
index d00e79092680..30fbe19eef73 100644
--- a/sys/kern/tty_tty.c
+++ b/sys/kern/tty_tty.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)tty_tty.c 7.15 (Berkeley) 5/28/91
- * $Id: tty_tty.c,v 1.2 1993/10/16 15:25:05 rgrimes Exp $
+ * $Id: tty_tty.c,v 1.3 1993/11/25 01:33:30 wollman Exp $
*/
/*
@@ -49,6 +49,7 @@
#define cttyvp(p) ((p)->p_flag&SCTTY ? (p)->p_session->s_ttyvp : NULL)
/*ARGSUSED*/
+int
cttyopen(dev, flag, mode, p)
dev_t dev;
int flag, mode;
@@ -69,9 +70,11 @@ cttyopen(dev, flag, mode, p)
}
/*ARGSUSED*/
+int
cttyread(dev, uio, flag)
dev_t dev;
struct uio *uio;
+ int flag;
{
register struct vnode *ttyvp = cttyvp(uio->uio_procp);
int error;
@@ -85,9 +88,11 @@ cttyread(dev, uio, flag)
}
/*ARGSUSED*/
+int
cttywrite(dev, uio, flag)
dev_t dev;
struct uio *uio;
+ int flag;
{
register struct vnode *ttyvp = cttyvp(uio->uio_procp);
int error;
@@ -101,6 +106,7 @@ cttywrite(dev, uio, flag)
}
/*ARGSUSED*/
+int
cttyioctl(dev, cmd, addr, flag, p)
dev_t dev;
int cmd;
@@ -112,7 +118,9 @@ cttyioctl(dev, cmd, addr, flag, p)
if (ttyvp == NULL)
return (EIO);
- if (cmd == TIOCNOTTY) {
+ if (cmd == TIOCSCTTY) /* don't allow controlling tty to be set */
+ return EINVAL; /* to controlling tty - infinite recursion */
+ else if (cmd == TIOCNOTTY) {
if (!SESS_LEADER(p)) {
p->p_flag &= ~SCTTY;
return (0);
@@ -123,6 +131,7 @@ cttyioctl(dev, cmd, addr, flag, p)
}
/*ARGSUSED*/
+int
cttyselect(dev, flag, p)
dev_t dev;
int flag;
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 41a132996202..93a5088a11d8 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -31,11 +31,11 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_domain.c 7.9 (Berkeley) 3/4/91
- * $Id: uipc_domain.c,v 1.2 1993/10/16 15:25:06 rgrimes Exp $
+ * $Id: uipc_domain.c,v 1.5 1993/12/19 00:51:43 wollman Exp $
*/
-#include <sys/cdefs.h>
#include "param.h"
+#include "systm.h"
#include "socket.h"
#include "protosw.h"
#include "domain.h"
@@ -43,12 +43,18 @@
#include "time.h"
#include "kernel.h"
+struct domain *domains;
+
#define ADDDOMAIN(x) { \
extern struct domain __CONCAT(x,domain); \
__CONCAT(x,domain.dom_next) = domains; \
domains = &__CONCAT(x,domain); \
}
+static void pfslowtimo(caddr_t, int);
+static void pffasttimo(caddr_t, int);
+
+void
domaininit()
{
register struct domain *dp;
@@ -91,8 +97,8 @@ if (max_linkhdr < 16) /* XXX */
max_linkhdr = 16;
max_hdr = max_linkhdr + max_protohdr;
max_datalen = MHLEN - max_hdr;
- pffasttimo();
- pfslowtimo();
+ pffasttimo(0, 0);
+ pfslowtimo(0, 0);
}
struct protosw *
@@ -139,6 +145,7 @@ found:
return (maybe);
}
+void
pfctlinput(cmd, sa)
int cmd;
struct sockaddr *sa;
@@ -152,7 +159,8 @@ pfctlinput(cmd, sa)
(*pr->pr_ctlinput)(cmd, sa, (caddr_t) 0);
}
-pfslowtimo()
+static void
+pfslowtimo(caddr_t dummy1, int dummy2)
{
register struct domain *dp;
register struct protosw *pr;
@@ -164,7 +172,8 @@ pfslowtimo()
timeout(pfslowtimo, (caddr_t)0, hz/2);
}
-pffasttimo()
+static void
+pffasttimo(caddr_t dummy1, int dummy2)
{
register struct domain *dp;
register struct protosw *pr;
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 552653436890..c0cf7a4c68cd 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_mbuf.c 7.19 (Berkeley) 4/20/91
- * $Id: uipc_mbuf.c,v 1.3 1993/10/16 15:25:07 rgrimes Exp $
+ * $Id: uipc_mbuf.c,v 1.6 1993/12/19 00:51:44 wollman Exp $
*/
#include "param.h"
@@ -46,10 +46,22 @@
#include "protosw.h"
#include "vm/vm.h"
+/* From sys/mbuf.h */
+struct mbstat mbstat;
+int nmbclusters;
+union mcluster *mclfree;
+int max_linkhdr;
+int max_protohdr;
+int max_hdr;
+int max_datalen;
+
extern vm_map_t mb_map;
struct mbuf *mbutl;
char *mclrefcnt;
+static void m_reclaim(void);
+
+void
mbinit()
{
int s;
@@ -74,8 +86,10 @@ bad:
* Must be called at splimp.
*/
/* ARGSUSED */
+int
m_clalloc(ncl, how) /* 31 Aug 92*/
register int ncl;
+ int how;
{
int npg, mbx;
register caddr_t p;
@@ -136,6 +150,7 @@ m_retryhdr(i, t)
return (m);
}
+static void
m_reclaim()
{
register struct domain *dp;
@@ -198,6 +213,7 @@ m_free(m)
return (n);
}
+void
m_freem(m)
register struct mbuf *m;
{
@@ -321,6 +337,7 @@ nospace:
* Copy data from an mbuf chain starting "off" bytes from the beginning,
* continuing for "len" bytes, into the indicated buffer.
*/
+void
m_copydata(m, off, len, cp)
register struct mbuf *m;
register int off;
@@ -356,6 +373,7 @@ m_copydata(m, off, len, cp)
* Both chains must be of the same type (e.g. MT_DATA).
* Any m_pkthdr is not updated.
*/
+void
m_cat(m, n)
register struct mbuf *m, *n;
{
@@ -376,8 +394,10 @@ m_cat(m, n)
}
}
+void
m_adj(mp, req_len)
struct mbuf *mp;
+ int req_len;
{
register int len = req_len;
register struct mbuf *m;
@@ -516,3 +536,230 @@ bad:
MPFail++;
return (0);
}
+
+/*
+ * Copy data from a buffer back into the indicated mbuf chain,
+ * starting "off" bytes from the beginning, extending the mbuf
+ * chain if necessary.
+ */
+void
+m_copyback(m0, off, len, cp)
+ struct mbuf *m0;
+ register int off;
+ register int len;
+ caddr_t cp;
+
+{
+ register int mlen;
+ register struct mbuf *m = m0, *n;
+ int totlen = 0;
+
+ if (m0 == 0)
+ return;
+ while (off > (mlen = m->m_len)) {
+ off -= mlen;
+ totlen += mlen;
+ if (m->m_next == 0) {
+ n = m_getclr(M_DONTWAIT, m->m_type);
+ if (n == 0)
+ goto out;
+ n->m_len = min(MLEN, len + off);
+ m->m_next = n;
+ }
+ m = m->m_next;
+ }
+ while (len > 0) {
+ mlen = min (m->m_len - off, len);
+ bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
+ cp += mlen;
+ len -= mlen;
+ mlen += off;
+ off = 0;
+ totlen += mlen;
+ if (len == 0)
+ break;
+ if (m->m_next == 0) {
+ n = m_get(M_DONTWAIT, m->m_type);
+ if (n == 0)
+ break;
+ n->m_len = min(MLEN, len);
+ m->m_next = n;
+ }
+ m = m->m_next;
+ }
+out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
+ m->m_pkthdr.len = totlen;
+}
+
+struct mbuf *
+m_split (m0, len0, wait)
+ register struct mbuf *m0;
+ int len0;
+ int wait;
+{
+ register struct mbuf *m, *n;
+ unsigned len = len0, remain;
+
+ for (m = m0; m && len > m -> m_len; m = m -> m_next)
+ len -= m -> m_len;
+ if (m == 0)
+ return (0);
+ remain = m -> m_len - len;
+ if (m0 -> m_flags & M_PKTHDR) {
+ MGETHDR(n, wait, m0 -> m_type);
+ if (n == 0)
+ return (0);
+ n -> m_pkthdr.rcvif = m0 -> m_pkthdr.rcvif;
+ n -> m_pkthdr.len = m0 -> m_pkthdr.len - len0;
+ m0 -> m_pkthdr.len = len0;
+ if (m -> m_flags & M_EXT)
+ goto extpacket;
+ if (remain > MHLEN) {
+ /* m can't be the lead packet */
+ MH_ALIGN(n, 0);
+ n -> m_next = m_split (m, len, wait);
+ if (n -> m_next == 0) {
+ (void) m_free (n);
+ return (0);
+ } else
+ return (n);
+ } else
+ MH_ALIGN(n, remain);
+ } else if (remain == 0) {
+ n = m -> m_next;
+ m -> m_next = 0;
+ return (n);
+ } else {
+ MGET(n, wait, m -> m_type);
+ if (n == 0)
+ return (0);
+ M_ALIGN(n, remain);
+ }
+extpacket:
+ if (m -> m_flags & M_EXT) {
+ n -> m_flags |= M_EXT;
+ n -> m_ext = m -> m_ext;
+ mclrefcnt[mtocl (m -> m_ext.ext_buf)]++;
+ n -> m_data = m -> m_data + len;
+ } else {
+ bcopy (mtod (m, caddr_t) + len, mtod (n, caddr_t), remain);
+ }
+ n -> m_len = remain;
+ m -> m_len = len;
+ n -> m_next = m -> m_next;
+ m -> m_next = 0;
+ return (n);
+}
+
+/* The following taken from netiso/iso_chksum.c */
+struct mbuf *
+m_append(head, m) /* XXX */
+ struct mbuf *head, *m;
+{
+ register struct mbuf *n;
+
+ if (m == 0)
+ return head;
+ if (head == 0)
+ return m;
+ n = head;
+ while (n->m_next)
+ n = n->m_next;
+ n->m_next = m;
+ return head;
+}
+
+/*
+ * FUNCTION: m_datalen
+ *
+ * PURPOSE: returns length of the mbuf chain.
+ * used all over the iso code.
+ *
+ * RETURNS: integer
+ *
+ * SIDE EFFECTS: none
+ *
+ * NOTES:
+ */
+int
+m_datalen (morig) /* XXX */
+ struct mbuf *morig;
+{
+ int s = splimp();
+ register struct mbuf *n=morig;
+ register int datalen = 0;
+
+ if( morig == (struct mbuf *)0)
+ return 0;
+ for(;;) {
+ datalen += n->m_len;
+ if (n->m_next == (struct mbuf *)0 ) {
+ break;
+ }
+ n = n->m_next;
+ }
+ splx(s);
+ return datalen;
+}
+
+int
+m_compress(in, out)
+ register struct mbuf *in, **out;
+{
+ register int datalen = 0;
+ int s = splimp();
+
+ if(!in->m_next) {
+ *out = in;
+ splx(s);
+ return in->m_len;
+ }
+ MGET((*out), M_DONTWAIT, MT_DATA);
+ if(! (*out)) {
+ *out = in;
+ splx(s);
+ return -1;
+ }
+ (*out)->m_len = 0;
+ (*out)->m_act = 0;
+
+ while (in) {
+ if (in->m_flags & M_EXT) {
+#ifdef DEBUG
+ ASSERT(in->m_len == 0);
+#endif
+ }
+ if ( in->m_len == 0) {
+ in = in->m_next;
+ continue;
+ }
+ if (((*out)->m_flags & M_EXT) == 0) {
+ int len;
+
+ len = M_TRAILINGSPACE(*out);
+ len = MIN(len, in->m_len);
+ datalen += len;
+
+ bcopy(mtod(in, caddr_t), mtod((*out), caddr_t) + (*out)->m_len,
+ (unsigned)len);
+
+ (*out)->m_len += len;
+ in->m_len -= len;
+ continue;
+ } else {
+ /* (*out) is full */
+ if( !((*out)->m_next = m_get(M_DONTWAIT, MT_DATA))) {
+ m_freem(*out);
+ *out = in;
+ splx(s);
+ return -1;
+ }
+ (*out)->m_len = 0;
+ (*out)->m_act = 0;
+ *out = (*out)->m_next;
+ }
+ }
+ m_freem(in);
+ splx(s);
+ return datalen;
+}
diff --git a/sys/kern/uipc_proto.c b/sys/kern/uipc_proto.c
index 4c25dab81108..881602c3af23 100644
--- a/sys/kern/uipc_proto.c
+++ b/sys/kern/uipc_proto.c
@@ -31,21 +31,23 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_proto.c 7.6 (Berkeley) 5/9/91
- * $Id: uipc_proto.c,v 1.2 1993/10/16 15:25:09 rgrimes Exp $
+ * $Id: uipc_proto.c,v 1.3 1993/12/19 00:51:45 wollman Exp $
*/
#include "param.h"
+#include "systm.h"
#include "socket.h"
#include "protosw.h"
#include "domain.h"
#include "mbuf.h"
+#include "net/raw_cb.h"
+
/*
* Definitions of protocols supported in the UNIX domain.
*/
int uipc_usrreq();
-int raw_init(),raw_usrreq(),raw_input(),raw_ctlinput();
extern struct domain unixdomain; /* or at least forward */
struct protosw unixsw[] = {
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 3195bcd3d4c2..8202529d308b 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_socket.c 7.28 (Berkeley) 5/4/91
- * $Id: uipc_socket.c,v 1.8 1993/10/23 16:23:49 davidg Exp $
+ * $Id: uipc_socket.c,v 1.10 1993/12/19 00:51:46 wollman Exp $
*/
#include "param.h"
@@ -55,7 +55,9 @@
* switching out to the protocol specific routines.
*/
/*ARGSUSED*/
+int
socreate(dom, aso, type, proto)
+ int dom;
struct socket **aso;
register int type;
int proto;
@@ -81,7 +83,8 @@ socreate(dom, aso, type, proto)
so->so_proto = prp;
error =
(*prp->pr_usrreq)(so, PRU_ATTACH,
- (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
+ (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0,
+ (struct mbuf *)0);
if (error) {
so->so_state |= SS_NOFDREF;
sofree(so);
@@ -91,6 +94,7 @@ socreate(dom, aso, type, proto)
return (0);
}
+int
sobind(so, nam)
struct socket *so;
struct mbuf *nam;
@@ -100,11 +104,12 @@ sobind(so, nam)
error =
(*so->so_proto->pr_usrreq)(so, PRU_BIND,
- (struct mbuf *)0, nam, (struct mbuf *)0);
+ (struct mbuf *)0, nam, (struct mbuf *)0, (struct mbuf *)0);
splx(s);
return (error);
}
+int
solisten(so, backlog)
register struct socket *so;
int backlog;
@@ -113,7 +118,8 @@ solisten(so, backlog)
error =
(*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
+ (struct mbuf *)0);
if (error) {
splx(s);
return (error);
@@ -127,6 +133,7 @@ solisten(so, backlog)
return (0);
}
+void
sofree(so)
register struct socket *so;
{
@@ -148,6 +155,7 @@ sofree(so)
* Initiate disconnect if connected.
* Free socket when disconnect complete.
*/
+int
soclose(so)
register struct socket *so;
{
@@ -182,7 +190,8 @@ drop:
if (so->so_pcb) {
int error2 =
(*so->so_proto->pr_usrreq)(so, PRU_DETACH,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
+ (struct mbuf *)0);
if (error == 0)
error = error2;
}
@@ -198,15 +207,18 @@ discard:
/*
* Must be called at splnet...
*/
+int
soabort(so)
struct socket *so;
{
return (
(*so->so_proto->pr_usrreq)(so, PRU_ABORT,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
+ (struct mbuf *)0));
}
+int
soaccept(so, nam)
register struct socket *so;
struct mbuf *nam;
@@ -218,11 +230,12 @@ soaccept(so, nam)
panic("soaccept: !NOFDREF");
so->so_state &= ~SS_NOFDREF;
error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
- (struct mbuf *)0, nam, (struct mbuf *)0);
+ (struct mbuf *)0, nam, (struct mbuf *)0, (struct mbuf *)0);
splx(s);
return (error);
}
+int
soconnect(so, nam)
register struct socket *so;
struct mbuf *nam;
@@ -245,11 +258,12 @@ soconnect(so, nam)
error = EISCONN;
else
error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
- (struct mbuf *)0, nam, (struct mbuf *)0);
+ (struct mbuf *)0, nam, (struct mbuf *)0, (struct mbuf *)0);
splx(s);
return (error);
}
+int
soconnect2(so1, so2)
register struct socket *so1;
struct socket *so2;
@@ -258,11 +272,13 @@ soconnect2(so1, so2)
int error;
error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
- (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
+ (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0,
+ (struct mbuf *)0);
splx(s);
return (error);
}
+int
sodisconnect(so)
register struct socket *so;
{
@@ -278,7 +294,8 @@ sodisconnect(so)
goto bad;
}
error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
+ (struct mbuf *)0);
bad:
splx(s);
return (error);
@@ -301,6 +318,7 @@ bad:
* must check for short counts if EINTR/ERESTART are returned.
* Data and control buffers are freed on return.
*/
+int
sosend(so, addr, uio, top, control, flags)
register struct socket *so;
struct mbuf *addr;
@@ -424,7 +442,7 @@ nopages:
s = splnet(); /* XXX */
error = (*so->so_proto->pr_usrreq)(so,
(flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
- top, addr, control);
+ top, addr, control, (struct mbuf *)0);
splx(s);
if (dontroute)
so->so_options &= ~SO_DONTROUTE;
@@ -463,6 +481,7 @@ out:
* an mbuf **mp0 for use in returning the chain. The uio is then used
* only for the count in uio_resid.
*/
+int
soreceive(so, paddr, uio, mp0, controlp, flagsp)
register struct socket *so;
struct mbuf **paddr;
@@ -476,7 +495,7 @@ soreceive(so, paddr, uio, mp0, controlp, flagsp)
register int flags, len, error, s, offset;
struct protosw *pr = so->so_proto;
struct mbuf *nextrecord;
- int moff, type;
+ int moff, type = 0;
int orig_resid = uio->uio_resid;
mp = mp0;
@@ -491,7 +510,8 @@ soreceive(so, paddr, uio, mp0, controlp, flagsp)
if (flags & MSG_OOB) {
m = m_get(M_WAIT, MT_DATA);
error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
- m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
+ m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0,
+ (struct mbuf *)0);
if (error)
goto bad;
do {
@@ -508,7 +528,7 @@ bad:
*mp = (struct mbuf *)0;
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
(*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
- (struct mbuf *)0, (struct mbuf *)0);
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
restart:
if (error = sblock(&so->so_rcv))
@@ -759,6 +779,7 @@ release:
return (error);
}
+int
soshutdown(so, how)
register struct socket *so;
register int how;
@@ -770,10 +791,12 @@ soshutdown(so, how)
sorflush(so);
if (how & FWRITE)
return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
+ (struct mbuf *)0));
return (0);
}
+void
sorflush(so)
register struct socket *so;
{
@@ -795,6 +818,7 @@ sorflush(so)
sbrelease(&asb);
}
+int
sosetopt(so, level, optname, m0)
register struct socket *so;
int level, optname;
@@ -905,6 +929,7 @@ bad:
return (error);
}
+int
sogetopt(so, level, optname, mp)
register struct socket *so;
int level, optname;
@@ -988,6 +1013,7 @@ sogetopt(so, level, optname, mp)
}
}
+void
sohasoutofband(so)
register struct socket *so;
{
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 349096aeee29..d6d103466abb 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_socket2.c 7.17 (Berkeley) 5/4/91
- * $Id: uipc_socket2.c,v 1.2 1993/10/16 15:25:12 rgrimes Exp $
+ * $Id: uipc_socket2.c,v 1.4 1993/12/19 00:51:47 wollman Exp $
*/
#include "param.h"
@@ -50,9 +50,9 @@
*/
/* strings for sleep message: */
-char netio[] = "netio";
-char netcon[] = "netcon";
-char netcls[] = "netcls";
+const char netio[] = "netio";
+const char netcon[] = "netcon";
+const char netcls[] = "netcls";
u_long sb_max = SB_MAX; /* patchable */
@@ -86,6 +86,7 @@ u_long sb_max = SB_MAX; /* patchable */
* cause software-interrupt process scheduling.
*/
+void
soisconnecting(so)
register struct socket *so;
{
@@ -94,6 +95,7 @@ soisconnecting(so)
so->so_state |= SS_ISCONNECTING;
}
+void
soisconnected(so)
register struct socket *so;
{
@@ -112,6 +114,7 @@ soisconnected(so)
}
}
+void
soisdisconnecting(so)
register struct socket *so;
{
@@ -123,6 +126,7 @@ soisdisconnecting(so)
sorwakeup(so);
}
+void
soisdisconnected(so)
register struct socket *so;
{
@@ -169,7 +173,8 @@ sonewconn1(head, connstatus)
(void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
soqinsque(head, so, soqueue);
if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH,
- (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) {
+ (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0,
+ (struct mbuf *)0)) {
(void) soqremque(so, soqueue);
(void) free((caddr_t)so, M_SOCKET);
return ((struct socket *)0);
@@ -182,6 +187,7 @@ sonewconn1(head, connstatus)
return (so);
}
+void
soqinsque(head, so, q)
register struct socket *head, *so;
int q;
@@ -203,6 +209,7 @@ soqinsque(head, so, q)
*prev = so;
}
+int
soqremque(so, q)
register struct socket *so;
int q;
@@ -241,6 +248,7 @@ soqremque(so, q)
* Data queued for reading in the socket may yet be read.
*/
+void
socantsendmore(so)
struct socket *so;
{
@@ -249,6 +257,7 @@ socantsendmore(so)
sowwakeup(so);
}
+void
socantrcvmore(so)
struct socket *so;
{
@@ -264,6 +273,7 @@ socantrcvmore(so)
/*
* Queue a process for a select on a socket buffer.
*/
+void
sbselqueue(sb, cp)
struct sockbuf *sb;
struct proc *cp;
@@ -281,6 +291,7 @@ sbselqueue(sb, cp)
/*
* Wait for data to arrive at/drain from a socket buffer.
*/
+int
sbwait(sb)
struct sockbuf *sb;
{
@@ -295,6 +306,7 @@ sbwait(sb)
* Lock a sockbuf already known to be locked;
* return any error returned from sleep (EINTR).
*/
+int
sb_lock(sb)
register struct sockbuf *sb;
{
@@ -316,6 +328,7 @@ sb_lock(sb)
* Do asynchronous notification via SIGIO
* if the socket has the SS_ASYNC flag set.
*/
+void
sowakeup(so, sb)
register struct socket *so;
register struct sockbuf *sb;
@@ -371,6 +384,7 @@ sowakeup(so, sb)
* should be released by calling sbrelease() when the socket is destroyed.
*/
+int
soreserve(so, sndcc, rcvcc)
register struct socket *so;
u_long sndcc, rcvcc;
@@ -398,6 +412,7 @@ bad:
* Attempt to scale mbmax so that mbcnt doesn't become limiting
* if buffering efficiency is near the normal case.
*/
+int
sbreserve(sb, cc)
struct sockbuf *sb;
u_long cc;
@@ -415,6 +430,7 @@ sbreserve(sb, cc)
/*
* Free mbufs held by a socket, and reserved mbuf space.
*/
+void
sbrelease(sb)
struct sockbuf *sb;
{
@@ -454,6 +470,7 @@ sbrelease(sb)
* the mbuf chain is recorded in sb. Empty mbufs are
* discarded and mbufs are compacted where possible.
*/
+void
sbappend(sb, m)
struct sockbuf *sb;
struct mbuf *m;
@@ -502,6 +519,7 @@ sbcheck(sb)
* As above, except the mbuf chain
* begins a new record.
*/
+void
sbappendrecord(sb, m0)
register struct sockbuf *sb;
register struct mbuf *m0;
@@ -536,6 +554,7 @@ sbappendrecord(sb, m0)
* is inserted at the beginning of the sockbuf,
* but after any other OOB data.
*/
+void
sbinsertoob(sb, m0)
register struct sockbuf *sb;
register struct mbuf *m0;
@@ -580,6 +599,7 @@ sbinsertoob(sb, m0)
* m0 must include a packet header with total length.
* Returns 0 if no space in sockbuf or insufficient mbufs.
*/
+int
sbappendaddr(sb, asa, m0, control)
register struct sockbuf *sb;
struct sockaddr *asa;
@@ -622,6 +642,7 @@ panic("sbappendaddr");
return (1);
}
+int
sbappendcontrol(sb, m0, control)
struct sockbuf *sb;
struct mbuf *control, *m0;
@@ -658,6 +679,7 @@ sbappendcontrol(sb, m0, control)
* buffer sb following mbuf n. If n
* is null, the buffer is presumed empty.
*/
+void
sbcompress(sb, m, n)
register struct sockbuf *sb;
register struct mbuf *m, *n;
@@ -706,6 +728,7 @@ sbcompress(sb, m, n)
* Free all mbufs in a sockbuf.
* Check that all resources are reclaimed.
*/
+void
sbflush(sb)
register struct sockbuf *sb;
{
@@ -721,6 +744,7 @@ sbflush(sb)
/*
* Drop data from (the front of) a sockbuf.
*/
+void
sbdrop(sb, len)
register struct sockbuf *sb;
register int len;
@@ -764,6 +788,7 @@ sbdrop(sb, len)
* Drop a record off the front of a sockbuf
* and move the next record to the front.
*/
+void
sbdroprecord(sb)
register struct sockbuf *sb;
{
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index cf82c089a5bc..2f7889d060ca 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -31,10 +31,11 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_syscalls.c 7.24 (Berkeley) 6/3/91
- * $Id: uipc_syscalls.c,v 1.4 1993/10/16 15:25:14 rgrimes Exp $
+ * $Id: uipc_syscalls.c,v 1.6 1993/12/19 00:51:48 wollman Exp $
*/
#include "param.h"
+#include "systm.h"
#include "filedesc.h"
#include "proc.h"
#include "file.h"
@@ -48,6 +49,12 @@
#include "ktrace.h"
#endif
+/* First two also used by NFS, boooo, hiss! */
+int getsock(struct filedesc *, int, struct file **);
+int sockargs(struct mbuf **, caddr_t, int, int);
+static int sendit(struct proc *, int, struct msghdr *, int, int *);
+static int recvit(struct proc *, int, struct msghdr *, caddr_t, int *);
+
/*
* System call interface to the socket abstraction.
*/
@@ -60,6 +67,7 @@ struct socket_args {
int protocol;
};
+int
socket(p, uap, retval)
struct proc *p;
register struct socket_args *uap;
@@ -92,6 +100,7 @@ struct bind_args {
};
/* ARGSUSED */
+int
bind(p, uap, retval)
struct proc *p;
register struct bind_args *uap;
@@ -116,6 +125,7 @@ struct listen_args {
};
/* ARGSUSED */
+int
listen(p, uap, retval)
struct proc *p;
register struct listen_args *uap;
@@ -129,7 +139,18 @@ listen(p, uap, retval)
return (solisten((struct socket *)fp->f_data, uap->backlog));
}
+struct accept1_args {
+ int s;
+ caddr_t name;
+ int *anamelen;
#ifdef COMPAT_43
+ int compat_43;
+#endif
+};
+
+#ifdef COMPAT_43
+
+int accept1(struct proc *, struct accept1_args *, int *);
struct accept_args {
int s;
@@ -138,6 +159,7 @@ struct accept_args {
int compat_43;
};
+int
accept(p, uap, retval)
struct proc *p;
struct accept_args *uap;
@@ -145,7 +167,7 @@ accept(p, uap, retval)
{
uap->compat_43 = 0;
- return (accept1(p, uap, retval));
+ return (accept1(p, (struct accept1_args *)uap, retval));
}
struct oaccept_args {
@@ -155,6 +177,7 @@ struct oaccept_args {
int compat_43;
};
+int
oaccept(p, uap, retval)
struct proc *p;
struct oaccept_args *uap;
@@ -162,22 +185,14 @@ oaccept(p, uap, retval)
{
uap->compat_43 = 1;
- return (accept1(p, uap, retval));
+ return (accept1(p, (struct accept1_args *)uap, retval));
}
#else /* COMPAT_43 */
#define accept1 accept
#endif
-struct accept1_args {
- int s;
- caddr_t name;
- int *anamelen;
-#ifdef COMPAT_43
- int compat_43;
-#endif
-};
-
+int
accept1(p, uap, retval)
struct proc *p;
register struct accept1_args *uap;
@@ -261,6 +276,7 @@ struct connect_args {
};
/* ARGSUSED */
+int
connect(p, uap, retval)
struct proc *p;
register struct connect_args *uap;
@@ -310,6 +326,7 @@ struct socketpair_args {
int *rsv;
};
+int
socketpair(p, uap, retval)
struct proc *p;
register struct socketpair_args *uap;
@@ -373,6 +390,7 @@ struct sendto_args {
int tolen;
};
+int
sendto(p, uap, retval)
struct proc *p;
register struct sendto_args *uap;
@@ -404,6 +422,7 @@ struct osend_args {
int flags;
};
+int
osend(p, uap, retval)
struct proc *p;
register struct osend_args *uap;
@@ -431,6 +450,7 @@ struct osendmsg_args {
int flags;
};
+int
osendmsg(p, uap, retval)
struct proc *p;
register struct osendmsg_args *uap;
@@ -469,6 +489,7 @@ struct sendmsg_args {
int flags;
};
+int
sendmsg(p, uap, retval)
struct proc *p;
register struct sendmsg_args *uap;
@@ -503,6 +524,7 @@ done:
return (error);
}
+static int
sendit(p, s, mp, flags, retsize)
register struct proc *p;
int s;
@@ -615,6 +637,7 @@ struct orecvfrom_args {
int *fromlenaddr;
};
+int
orecvfrom(p, uap, retval)
struct proc *p;
struct orecvfrom_args *uap;
@@ -635,6 +658,7 @@ struct recvfrom_args {
int *fromlenaddr;
};
+int
recvfrom(p, uap, retval)
struct proc *p;
register struct recvfrom_args *uap;
@@ -669,6 +693,7 @@ struct orecv_args {
int flags;
};
+int
orecv(p, uap, retval)
struct proc *p;
register struct orecv_args *uap;
@@ -700,6 +725,7 @@ struct orecvmsg_args {
int flags;
};
+int
orecvmsg(p, uap, retval)
struct proc *p;
register struct orecvmsg_args *uap;
@@ -743,6 +769,7 @@ struct recvmsg_args {
int flags;
};
+int
recvmsg(p, uap, retval)
struct proc *p;
register struct recvmsg_args *uap;
@@ -782,6 +809,7 @@ done:
return (error);
}
+int
recvit(p, s, mp, namelenp, retsize)
register struct proc *p;
int s;
@@ -918,6 +946,7 @@ struct shutdown_args {
};
/* ARGSUSED */
+int
shutdown(p, uap, retval)
struct proc *p;
register struct shutdown_args *uap;
@@ -940,6 +969,7 @@ struct setsocketopt_args {
};
/* ARGSUSED */
+int
setsockopt(p, uap, retval)
struct proc *p;
register struct setsocketopt_args *uap;
@@ -977,6 +1007,7 @@ struct getsockopt_args {
};
/* ARGSUSED */
+int
getsockopt(p, uap, retval)
struct proc *p;
register struct getsockopt_args *uap;
@@ -1009,6 +1040,7 @@ getsockopt(p, uap, retval)
}
/* ARGSUSED */
+int
pipe(p, uap, retval)
struct proc *p;
struct args *uap;
@@ -1056,8 +1088,19 @@ free1:
/*
* Get socket name.
*/
+struct getsockname1_args {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+#ifdef COMPAT_43
+ int compat_43;
+#endif
+};
+
#ifdef COMPAT_43
+int getsockname1(struct proc *, struct getsockname1_args *, int *);
+
struct getsockname_args {
int fdes;
caddr_t asa;
@@ -1065,6 +1108,7 @@ struct getsockname_args {
int compat_43;
};
+int
getsockname(p, uap, retval)
struct proc *p;
struct getsockname_args *uap;
@@ -1072,7 +1116,7 @@ getsockname(p, uap, retval)
{
uap->compat_43 = 0;
- return (getsockname1(p, uap, retval));
+ return (getsockname1(p, (struct getsockname1_args *)uap, retval));
}
struct ogetsockname_args {
@@ -1082,6 +1126,7 @@ struct ogetsockname_args {
int compat_43;
};
+int
ogetsockname(p, uap, retval)
struct proc *p;
struct ogetsockname_args *uap;
@@ -1089,23 +1134,15 @@ ogetsockname(p, uap, retval)
{
uap->compat_43 = 1;
- return (getsockname1(p, uap, retval));
+ return (getsockname1(p, (struct getsockname1_args *)uap, retval));
}
#else /* COMPAT_43 */
#define getsockname1 getsockname
#endif
-struct getsockname1_args {
- int fdes;
- caddr_t asa;
- int *alen;
-#ifdef COMPAT_43
- int compat_43;
-#endif
-};
-
/* ARGSUSED */
+int
getsockname1(p, uap, retval)
struct proc *p;
register struct getsockname1_args *uap;
@@ -1124,7 +1161,7 @@ getsockname1(p, uap, retval)
m = m_getclr(M_WAIT, MT_SONAME);
if (m == NULL)
return (ENOBUFS);
- if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
+ if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, 0))
goto bad;
if (len > m->m_len)
len = m->m_len;
@@ -1145,8 +1182,19 @@ bad:
/*
* Get name of peer for connected socket.
*/
+struct getpeername1_args {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+#ifdef COMPAT_43
+ int compat_43;
+#endif
+};
+
#ifdef COMPAT_43
+int getpeername1(struct proc *, struct getpeername1_args *, int *);
+
struct getpeername_args {
int fdes;
caddr_t asa;
@@ -1154,6 +1202,7 @@ struct getpeername_args {
int compat_43;
};
+int
getpeername(p, uap, retval)
struct proc *p;
struct getpeername_args *uap;
@@ -1161,7 +1210,7 @@ getpeername(p, uap, retval)
{
uap->compat_43 = 0;
- return (getpeername1(p, uap, retval));
+ return (getpeername1(p, (struct getpeername1_args *)uap, retval));
}
struct ogetpeername_args {
@@ -1171,6 +1220,7 @@ struct ogetpeername_args {
int compat_43;
};
+int
ogetpeername(p, uap, retval)
struct proc *p;
struct ogetpeername_args *uap;
@@ -1178,23 +1228,15 @@ ogetpeername(p, uap, retval)
{
uap->compat_43 = 1;
- return (getpeername1(p, uap, retval));
+ return (getpeername1(p, (struct getpeername1_args *)uap, retval));
}
#else /* COMPAT_43 */
#define getpeername1 getpeername
#endif
-struct getpeername1_args {
- int fdes;
- caddr_t asa;
- int *alen;
-#ifdef COMPAT_43
- int compat_43;
-#endif
-};
-
/* ARGSUSED */
+int
getpeername1(p, uap, retval)
struct proc *p;
register struct getpeername1_args *uap;
@@ -1215,7 +1257,7 @@ getpeername1(p, uap, retval)
return (ENOBUFS);
if (error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)))
return (error);
- if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
+ if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, 0))
goto bad;
if (len > m->m_len)
len = m->m_len;
@@ -1232,6 +1274,7 @@ bad:
return (error);
}
+int
sockargs(mp, buf, buflen, type)
struct mbuf **mp;
caddr_t buf;
@@ -1270,6 +1313,7 @@ sockargs(mp, buf, buflen, type)
return (0);
}
+int
getsock(fdp, fdes, fpp)
struct filedesc *fdp;
int fdes;
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 6914ffeac913..a20bfa39bb76 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -31,10 +31,11 @@
* SUCH DAMAGE.
*
* from: @(#)uipc_usrreq.c 7.26 (Berkeley) 6/3/91
- * $Id: uipc_usrreq.c,v 1.4 1993/10/23 16:34:45 davidg Exp $
+ * $Id: uipc_usrreq.c,v 1.5 1993/11/25 01:33:37 wollman Exp $
*/
#include "param.h"
+#include "systm.h"
#include "proc.h"
#include "filedesc.h"
#include "domain.h"
@@ -61,6 +62,7 @@ struct sockaddr sun_noname = { sizeof(sun_noname), AF_UNIX };
ino_t unp_ino; /* prototype for fake inode numbers */
/*ARGSUSED*/
+int
uipc_usrreq(so, req, m, nam, control)
struct socket *so;
int req;
@@ -313,6 +315,7 @@ u_long unpdg_recvspace = 4*1024;
int unp_rights; /* file descriptors in flight */
+int
unp_attach(so)
struct socket *so;
{
@@ -330,6 +333,8 @@ unp_attach(so)
case SOCK_DGRAM:
error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
break;
+ default:
+ panic("unp_attach");
}
if (error)
return (error);
@@ -343,6 +348,7 @@ unp_attach(so)
return (0);
}
+void
unp_detach(unp)
register struct unpcb *unp;
{
@@ -373,6 +379,7 @@ unp_detach(unp)
}
}
+int
unp_bind(unp, nam, p)
struct unpcb *unp;
struct mbuf *nam;
@@ -422,6 +429,7 @@ unp_bind(unp, nam, p)
return (0);
}
+int
unp_connect(so, nam, p)
struct socket *so;
struct mbuf *nam;
@@ -481,6 +489,7 @@ bad:
return (error);
}
+int
unp_connect2(so, so2)
register struct socket *so;
register struct socket *so2;
@@ -512,6 +521,7 @@ unp_connect2(so, so2)
return (0);
}
+void
unp_disconnect(unp)
struct unpcb *unp;
{
@@ -557,6 +567,7 @@ unp_abort(unp)
}
#endif
+void
unp_shutdown(unp)
struct unpcb *unp;
{
@@ -567,6 +578,7 @@ unp_shutdown(unp)
socantrcvmore(so);
}
+void
unp_drop(unp, errno)
struct unpcb *unp;
int errno;
@@ -590,6 +602,7 @@ unp_drain()
}
#endif
+int
unp_externalize(rights)
struct mbuf *rights;
{
@@ -621,6 +634,7 @@ unp_externalize(rights)
return (0);
}
+int
unp_internalize(control, p)
struct mbuf *control;
struct proc *p;
@@ -655,9 +669,9 @@ unp_internalize(control, p)
}
int unp_defer, unp_gcing;
-int unp_mark();
extern struct domain unixdomain;
+void
unp_gc()
{
register struct file *fp;
@@ -719,18 +733,18 @@ restart:
unp_gcing = 0;
}
+void
unp_dispose(m)
struct mbuf *m;
{
- int unp_discard();
-
if (m)
unp_scan(m, unp_discard);
}
+void
unp_scan(m0, op)
register struct mbuf *m0;
- int (*op)();
+ void (*op)(struct file *);
{
register struct mbuf *m;
register struct file **rp;
@@ -757,6 +771,7 @@ unp_scan(m0, op)
}
}
+void
unp_mark(fp)
struct file *fp;
{
@@ -767,6 +782,7 @@ unp_mark(fp)
fp->f_flag |= (FMARK|FDEFER);
}
+void
unp_discard(fp)
struct file *fp;
{
diff --git a/sys/kern/vfs__bio.c b/sys/kern/vfs__bio.c
index db8c6ad98e73..2ccf2e6126b7 100644
--- a/sys/kern/vfs__bio.c
+++ b/sys/kern/vfs__bio.c
@@ -45,11 +45,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: vfs__bio.c,v 1.7 1993/10/19 01:06:29 nate Exp $
+ * $Id: vfs__bio.c,v 1.15 1994/01/31 05:57:45 davidg Exp $
*/
#include "param.h"
#include "systm.h"
+#include "kernel.h"
#include "proc.h"
#include "vnode.h"
#include "buf.h"
@@ -59,6 +60,18 @@
#include "vm/vm.h"
#include "resourcevar.h"
+/* From sys/buf.h */
+struct buf *buf; /* the buffer pool itself */
+char *buffers;
+int nbuf; /* number of buffer headers */
+int bufpages; /* number of memory pages in the buffer pool */
+struct buf *swbuf; /* swap I/O headers */
+int nswbuf;
+struct bufhd bufhash[BUFHSZ]; /* heads of hash lists */
+struct buf bfreelist[BQUEUES]; /* heads of available lists */
+struct buf bswlist; /* head of free swap header list */
+struct buf *bclnlist; /* head of cleaned page list */
+
static struct buf *getnewbuf(int);
extern vm_map_t buffer_map;
@@ -283,12 +296,12 @@ brelse(register struct buf *bp)
x=splbio();
if ((bfreelist + BQ_AGE)->b_flags & B_WANTED) {
(bfreelist + BQ_AGE) ->b_flags &= ~B_WANTED;
- wakeup(bfreelist);
+ wakeup((caddr_t)bfreelist);
}
/* anyone need this very block? */
if (bp->b_flags & B_WANTED) {
bp->b_flags &= ~B_WANTED;
- wakeup(bp);
+ wakeup((caddr_t)bp);
}
if (bp->b_flags & (B_INVAL|B_ERROR)) {
@@ -342,14 +355,14 @@ start:
/*#define notyet*/
#ifndef notyet
- if ((addr = malloc (sz, M_TEMP, M_WAITOK)) == 0) goto tryfree;
+ if ((addr = malloc (sz, M_IOBUF, M_WAITOK)) == 0) goto tryfree;
#else /* notyet */
/* get new memory buffer */
if (round_page(sz) == sz)
addr = (caddr_t) kmem_alloc_wired_wait(buffer_map, sz);
else
- addr = (caddr_t) malloc (sz, M_TEMP, M_WAITOK);
- /*if ((addr = malloc (sz, M_TEMP, M_NOWAIT)) == 0) goto tryfree;*/
+ addr = (caddr_t) malloc (sz, M_IOBUF, M_WAITOK);
+ /*if ((addr = malloc (sz, M_IOBUF, M_NOWAIT)) == 0) goto tryfree;*/
bzero(addr, sz);
#endif /* notyet */
freebufspace -= sz;
@@ -373,7 +386,7 @@ tryfree:
} else {
/* wait for a free buffer of any kind */
(bfreelist + BQ_AGE)->b_flags |= B_WANTED;
- sleep(bfreelist, PRIBIO);
+ tsleep((caddr_t)bfreelist, PRIBIO, "newbuf", 0);
splx(x);
return (0);
}
@@ -448,33 +461,30 @@ getblk(register struct vnode *vp, daddr_t blkno, int size)
struct buf *bp, *bh;
int x;
- for (;;) {
- if (bp = incore(vp, blkno)) {
- x = splbio();
- if (bp->b_flags & B_BUSY) {
- bp->b_flags |= B_WANTED;
- sleep (bp, PRIBIO);
- splx(x);
- continue;
- }
- bp->b_flags |= B_BUSY | B_CACHE;
- bremfree(bp);
- if (size > bp->b_bufsize)
- panic("now what do we do?");
- /* if (bp->b_bufsize != size) allocbuf(bp, size); */
- } else {
-
- if((bp = getnewbuf(size)) == 0) continue;
- bp->b_blkno = bp->b_lblkno = blkno;
- bgetvp(vp, bp);
- x = splbio();
- bh = BUFHASH(vp, blkno);
- binshash(bp, bh);
- bp->b_flags = B_BUSY;
+ x = splbio();
+loop:
+ if (bp = incore(vp, blkno)) {
+ if (bp->b_flags & B_BUSY) {
+ bp->b_flags |= B_WANTED;
+ tsleep ((caddr_t)bp, PRIBIO, "getblk", 0);
+ goto loop;
}
- splx(x);
- return (bp);
+ bp->b_flags |= B_BUSY | B_CACHE;
+ bremfree(bp);
+ if (size > bp->b_bufsize)
+ panic("now what do we do?");
+ /* if (bp->b_bufsize != size) allocbuf(bp, size); */
+ } else {
+
+ if ((bp = getnewbuf(size)) == 0) goto loop;
+ bp->b_blkno = bp->b_lblkno = blkno;
+ bgetvp(vp, bp);
+ bh = BUFHASH(vp, blkno);
+ binshash(bp, bh);
+ bp->b_flags = B_BUSY;
}
+ splx(x);
+ return (bp);
}
/*
@@ -512,12 +522,12 @@ allocbuf(register struct buf *bp, int size)
/* get new memory buffer */
#ifndef notyet
- newcontents = (caddr_t) malloc (size, M_TEMP, M_WAITOK);
+ newcontents = (caddr_t) malloc (size, M_IOBUF, M_WAITOK);
#else /* notyet */
if (round_page(size) == size)
newcontents = (caddr_t) kmem_alloc_wired_wait(buffer_map, size);
else
- newcontents = (caddr_t) malloc (size, M_TEMP, M_WAITOK);
+ newcontents = (caddr_t) malloc (size, M_IOBUF, M_WAITOK);
#endif /* notyet */
/* copy the old into the new, up to the maximum that will fit */
@@ -525,12 +535,12 @@ allocbuf(register struct buf *bp, int size)
/* return old contents to free heap */
#ifndef notyet
- free (bp->b_un.b_addr, M_TEMP);
+ free (bp->b_un.b_addr, M_IOBUF);
#else /* notyet */
if (round_page(bp->b_bufsize) == bp->b_bufsize)
kmem_free_wakeup(buffer_map, bp->b_un.b_addr, bp->b_bufsize);
else
- free (bp->b_un.b_addr, M_TEMP);
+ free (bp->b_un.b_addr, M_IOBUF);
#endif /* notyet */
/* adjust buffer cache's idea of memory allocated to buffer contents */
@@ -555,7 +565,7 @@ biowait(register struct buf *bp)
x = splbio();
while ((bp->b_flags & B_DONE) == 0)
- sleep((caddr_t)bp, PRIBIO);
+ tsleep((caddr_t)bp, PRIBIO, "biowait", 0);
if((bp->b_flags & B_ERROR) || bp->b_error) {
if ((bp->b_flags & B_INVAL) == 0) {
bp->b_flags |= B_INVAL;
@@ -575,28 +585,84 @@ biowait(register struct buf *bp)
}
/*
- * Finish up operations on a buffer, calling an optional
- * function (if requested), and releasing the buffer if
- * marked asynchronous. Then mark this buffer done so that
- * others biowait()'ing for it will notice when they are
- * woken up from sleep().
+ * Finish up operations on a buffer, calling an optional function
+ * (if requested), and releasing the buffer if marked asynchronous.
+ * Mark this buffer done so that others biowait()'ing for it will
+ * notice when they are woken up from sleep().
*/
-int
+void
biodone(register struct buf *bp)
{
- int x;
+ bp->b_flags |= B_DONE;
- x = splbio();
- if (bp->b_flags & B_CALL) (*bp->b_iodone)(bp);
- bp->b_flags &= ~B_CALL;
- if ((bp->b_flags & (B_READ|B_DIRTY)) == B_DIRTY) {
- bp->b_flags &= ~B_DIRTY;
+ if ((bp->b_flags & B_READ) == 0) {
vwakeup(bp);
}
- if (bp->b_flags & B_ASYNC)
+
+ /* call optional completion function if requested */
+ if (bp->b_flags & B_CALL) {
+ bp->b_flags &= ~B_CALL;
+ (*bp->b_iodone)(bp);
+ return;
+ }
+
+/*
+ * For asynchronous completions, release the buffer now. The brelse
+ * checks for B_WANTED and will do the wakeup there if necessary -
+ * so no need to do a wakeup here in the async case.
+ */
+
+ if (bp->b_flags & B_ASYNC) {
brelse(bp);
- bp->b_flags &= ~B_ASYNC;
- bp->b_flags |= B_DONE;
- wakeup(bp);
- splx(x);
+ } else {
+ bp->b_flags &= ~B_WANTED;
+ wakeup((caddr_t) bp);
+ }
+}
+
+/*
+ * Internel update daemon, process 3
+ * The variable vfs_update_wakeup allows for internal syncs.
+ */
+int vfs_update_wakeup;
+
+void
+vfs_update() {
+ (void) spl0();
+ while(1) {
+ tsleep((caddr_t)&vfs_update_wakeup, PRIBIO, "update", hz*30);
+ vfs_update_wakeup = 0;
+ sync(curproc, NULL, NULL);
+ }
+}
+
+/*
+ * Print out statistics on the current allocation of the buffer pool.
+ * Can be enabled to print out on every ``sync'' by setting "syncprt"
+ * in ufs/ufs_vfsops.c.
+ */
+void
+bufstats()
+{
+ int s, i, j, count;
+ register struct buf *bp, *dp;
+ int counts[MAXBSIZE/CLBYTES+1];
+ static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
+
+ for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
+ count = 0;
+ for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
+ counts[j] = 0;
+ s = splbio();
+ for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
+ counts[dp->b_bufsize/CLBYTES]++;
+ count++;
+ }
+ splx(s);
+ printf("%s: total-%d", bname[i], count);
+ for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
+ if (counts[j] != 0)
+ printf(", %d-%d", j * CLBYTES, counts[j]);
+ printf("\n");
+ }
}
diff --git a/sys/kern/vfs_bio.old.c b/sys/kern/vfs_bio.old.c
deleted file mode 100644
index a791bafcc439..000000000000
--- a/sys/kern/vfs_bio.old.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * Copyright (c) 1989, 1990, 1991, 1992 William F. Jolitz, TeleMuse
- * 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 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 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 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
- * 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
- * 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: vfs_bio.old.c,v 1.2 1993/10/16 15:25:18 rgrimes Exp $
- */
-
-#include "param.h"
-#include "proc.h"
-#include "vnode.h"
-#include "buf.h"
-#include "specdev.h"
-#include "mount.h"
-#include "malloc.h"
-#ifdef notyet
-#include "vm/vm.h"
-#include "vm/vm_kern.h"
-#endif /* notyet */
-#include "resourcevar.h"
-
-/*
- * Initialize buffer headers and related structures.
- */
-void bufinit()
-{
- struct bufhd *bh;
- struct buf *bp;
-
- /* first, make a null hash table */
- for(bh = bufhash; bh < bufhash + BUFHSZ; bh++) {
- bh->b_flags = 0;
- bh->b_forw = (struct buf *)bh;
- bh->b_back = (struct buf *)bh;
- }
-
- /* next, make a null set of free lists */
- for(bp = bfreelist; bp < bfreelist + BQUEUES; bp++) {
- bp->b_flags = 0;
- bp->av_forw = bp;
- bp->av_back = bp;
- bp->b_forw = bp;
- bp->b_back = bp;
- }
-
- /* finally, initialize each buffer header and stick on empty q */
- for(bp = buf; bp < buf + nbuf ; bp++) {
- bp->b_flags = B_HEAD | B_INVAL; /* we're just an empty header */
- bp->b_dev = NODEV;
- bp->b_vp = 0;
- binstailfree(bp, bfreelist + BQ_EMPTY);
- binshash(bp, bfreelist + BQ_EMPTY);
- }
-}
-
-/*
- * Find the block in the buffer pool.
- * If the buffer is not present, allocate a new buffer and load
- * its contents according to the filesystem fill routine.
- */
-bread(vp, blkno, size, cred, bpp)
- struct vnode *vp;
- daddr_t blkno;
- int size;
- struct ucred *cred;
- struct buf **bpp;
-{
- struct buf *bp;
- int rv = 0;
-
- bp = getblk (vp, blkno, size);
-
- /* if not found in cache, do some I/O */
- if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) {
- bp->b_flags |= B_READ;
- bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
- bp->b_rcred = cred;
- VOP_STRATEGY(bp);
- rv = biowait (bp);
- }
- *bpp = bp;
-
- return (rv);
-}
-
-/*
- * Operates like bread, but also starts I/O on the specified
- * read-ahead block. [See page 55 of Bach's Book]
- */
-breada(vp, blkno, size, rablkno, rabsize, cred, bpp)
- struct vnode *vp;
- daddr_t blkno; int size;
- daddr_t rablkno; int rabsize;
- struct ucred *cred;
- struct buf **bpp;
-{
- struct buf *bp, *rabp;
- int rv = 0, needwait = 0;
-
- bp = getblk (vp, blkno, size);
-
- /* if not found in cache, do some I/O */
- if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) {
- bp->b_flags |= B_READ;
- bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
- bp->b_rcred = cred;
- VOP_STRATEGY(bp);
- needwait++;
- }
-
- rabp = getblk (vp, rablkno, rabsize);
-
- /* if not found in cache, do some I/O (overlapped with first) */
- if ((rabp->b_flags & B_CACHE) == 0 || (rabp->b_flags & B_INVAL) != 0) {
- rabp->b_flags |= B_READ | B_ASYNC;
- rabp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL);
- rabp->b_rcred = cred;
- VOP_STRATEGY(rabp);
- } else
- brelse(rabp);
-
- /* wait for original I/O */
- if (needwait)
- rv = biowait (bp);
-
- *bpp = bp;
- return (rv);
-}
-
-/*
- * Synchronous write.
- * Release buffer on completion.
- */
-bwrite(bp)
- register struct buf *bp;
-{
- int rv;
-
- if(bp->b_flags & B_INVAL) {
- brelse(bp);
- return (0);
- } else {
- int wasdelayed;
-
- if(!(bp->b_flags & B_BUSY))panic("bwrite: not busy");
- wasdelayed = bp->b_flags & B_DELWRI;
- bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_ASYNC|B_DELWRI);
- if(wasdelayed) reassignbuf(bp, bp->b_vp);
- bp->b_flags |= B_DIRTY;
- bp->b_vp->v_numoutput++;
- VOP_STRATEGY(bp);
- rv = biowait(bp);
- brelse(bp);
- return (rv);
- }
-}
-
-/*
- * Delayed write.
- *
- * The buffer is marked dirty, but is not queued for I/O.
- * This routine should be used when the buffer is expected
- * to be modified again soon, typically a small write that
- * partially fills a buffer.
- *
- * NB: magnetic tapes cannot be delayed; they must be
- * written in the order that the writes are requested.
- */
-void bdwrite(bp)
- register struct buf *bp;
-{
-
- if(!(bp->b_flags & B_BUSY))panic("bdwrite: not busy");
- if(bp->b_flags & B_INVAL) {
- brelse(bp);
- }
- if(bp->b_flags & B_TAPE) {
- bwrite(bp);
- return;
- }
- bp->b_flags &= ~(B_READ|B_DONE);
- bp->b_flags |= B_DIRTY|B_DELWRI;
- reassignbuf(bp, bp->b_vp);
- brelse(bp);
- return;
-}
-
-/*
- * Asynchronous write.
- * Start I/O on a buffer, but do not wait for it to complete.
- * The buffer is released when the I/O completes.
- */
-bawrite(bp)
- register struct buf *bp;
-{
-
- if(!(bp->b_flags & B_BUSY))panic("bawrite: not busy");
- if(bp->b_flags & B_INVAL)
- brelse(bp);
- else {
- int wasdelayed;
-
- wasdelayed = bp->b_flags & B_DELWRI;
- bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
- if(wasdelayed) reassignbuf(bp, bp->b_vp);
-
- bp->b_flags |= B_DIRTY | B_ASYNC;
- bp->b_vp->v_numoutput++;
- VOP_STRATEGY(bp);
- }
-}
-
-/*
- * Release a buffer.
- * Even if the buffer is dirty, no I/O is started.
- */
-brelse(bp)
- register struct buf *bp;
-{
- int x;
-
- /* anyone need a "free" block? */
- x=splbio();
- if ((bfreelist + BQ_AGE)->b_flags & B_WANTED) {
- (bfreelist + BQ_AGE) ->b_flags &= ~B_WANTED;
- wakeup(bfreelist);
- }
- /* anyone need this very block? */
- if (bp->b_flags & B_WANTED) {
- bp->b_flags &= ~B_WANTED;
- wakeup(bp);
- }
-
- if (bp->b_flags & (B_INVAL|B_ERROR)) {
- bp->b_flags |= B_INVAL;
- bp->b_flags &= ~(B_DELWRI|B_CACHE);
- if(bp->b_vp)
- brelvp(bp);
- }
-
- /* enqueue */
- /* just an empty buffer head ... */
- /*if(bp->b_flags & B_HEAD)
- binsheadfree(bp, bfreelist + BQ_EMPTY)*/
- /* buffers with junk contents */
- /*else*/ if(bp->b_flags & (B_ERROR|B_INVAL|B_NOCACHE))
- binsheadfree(bp, bfreelist + BQ_AGE)
- /* buffers with stale but valid contents */
- else if(bp->b_flags & B_AGE)
- binstailfree(bp, bfreelist + BQ_AGE)
- /* buffers with valid and quite potentially reuseable contents */
- else
- binstailfree(bp, bfreelist + BQ_LRU)
-
- /* unlock */
- bp->b_flags &= ~B_BUSY;
- splx(x);
-
- return;
-}
-
-int freebufspace;
-int allocbufspace;
-
-/*
- * Find a buffer which is available for use.
- * If free memory for buffer space and an empty header from the empty list,
- * use that. Otherwise, select something from a free list.
- * Preference is to AGE list, then LRU list.
- */
-struct buf *
-getnewbuf(sz)
-{
- struct buf *bp;
- int x;
-
- x = splbio();
-start:
- /* can we constitute a new buffer? */
- if (freebufspace > sz
- && bfreelist[BQ_EMPTY].av_forw != (struct buf *)bfreelist+BQ_EMPTY) {
- caddr_t addr;
-
-#ifndef notyet
- if ((addr = malloc (sz, M_TEMP, M_NOWAIT)) == 0) goto tryfree;
-#else /* notyet */
- /* get new memory buffer */
- if (round_page(sz) == sz)
- addr = (caddr_t) kmem_alloc(buffer_map, sz);
- else
- addr = (caddr_t) malloc (sz, M_TEMP, M_WAITOK);
- /*if ((addr = malloc (sz, M_TEMP, M_NOWAIT)) == 0) goto tryfree;*/
-#endif /* notyet */
- freebufspace -= sz;
- allocbufspace += sz;
-
- bp = bfreelist[BQ_EMPTY].av_forw;
- bp->b_flags = B_BUSY | B_INVAL;
- bremfree(bp);
-#ifndef notyet
- bp->b_un.b_addr = (caddr_t) addr;
-#else /* notyet */
- bp->b_un.b_addr = addr;
-#endif /* notyet */
- goto fillin;
- }
-
-tryfree:
- if (bfreelist[BQ_AGE].av_forw != (struct buf *)bfreelist+BQ_AGE) {
- bp = bfreelist[BQ_AGE].av_forw;
- bremfree(bp);
- } else if (bfreelist[BQ_LRU].av_forw != (struct buf *)bfreelist+BQ_LRU) {
- bp = bfreelist[BQ_LRU].av_forw;
- bremfree(bp);
- } else {
- /* wait for a free buffer of any kind */
- (bfreelist + BQ_AGE)->b_flags |= B_WANTED;
- sleep(bfreelist, PRIBIO);
- splx(x);
- return (0);
- }
-
- /* if we are a delayed write, convert to an async write! */
- if (bp->b_flags & B_DELWRI) {
- /*bp->b_flags &= ~B_DELWRI;*/
- bp->b_flags |= B_BUSY;
- bawrite (bp);
- goto start;
- }
-
- /*if (bp->b_flags & (B_INVAL|B_ERROR) == 0) {
- bremhash(bp);
- }*/
-
- if(bp->b_vp)
- brelvp(bp);
-
- /* we are not free, nor do we contain interesting data */
- bp->b_flags = B_BUSY;
-fillin:
- bremhash(bp);
- splx(x);
- bp->b_dev = NODEV;
- bp->b_vp = NULL;
- bp->b_blkno = bp->b_lblkno = 0;
- bp->b_iodone = 0;
- bp->b_error = 0;
- bp->b_wcred = bp->b_rcred = NOCRED;
- if (bp->b_bufsize != sz) allocbuf(bp, sz);
- bp->b_bcount = bp->b_bufsize = sz;
- bp->b_dirtyoff = bp->b_dirtyend = 0;
- return (bp);
-}
-
-/*
- * Check to see if a block is currently memory resident.
- */
-struct buf *incore(vp, blkno)
- struct vnode *vp;
- daddr_t blkno;
-{
- struct buf *bh;
- struct buf *bp;
-
- bh = BUFHASH(vp, blkno);
-
- /* Search hash chain */
- bp = bh->b_forw;
- while (bp != (struct buf *) bh) {
- /* hit */
- if (bp->b_lblkno == blkno && bp->b_vp == vp
- && (bp->b_flags & B_INVAL) == 0)
- return (bp);
- bp = bp->b_forw;
- }
-
- return(0);
-}
-
-/*
- * Get a block of requested size that is associated with
- * a given vnode and block offset. If it is found in the
- * block cache, mark it as having been found, make it busy
- * and return it. Otherwise, return an empty block of the
- * correct size. It is up to the caller to insure that the
- * cached blocks be of the correct size.
- */
-struct buf *
-getblk(vp, blkno, size)
- register struct vnode *vp;
- daddr_t blkno;
- int size;
-{
- struct buf *bp, *bh;
- int x;
-
- for (;;) {
- if (bp = incore(vp, blkno)) {
- x = splbio();
- if (bp->b_flags & B_BUSY) {
- bp->b_flags |= B_WANTED;
- sleep (bp, PRIBIO);
- splx(x);
- continue;
- }
- bp->b_flags |= B_BUSY | B_CACHE;
- bremfree(bp);
- if (size > bp->b_bufsize)
- panic("now what do we do?");
- /* if (bp->b_bufsize != size) allocbuf(bp, size); */
- } else {
-
- if((bp = getnewbuf(size)) == 0) continue;
- bp->b_blkno = bp->b_lblkno = blkno;
- bgetvp(vp, bp);
- x = splbio();
- bh = BUFHASH(vp, blkno);
- binshash(bp, bh);
- bp->b_flags = B_BUSY;
- }
- splx(x);
- return (bp);
- }
-}
-
-/*
- * Get an empty, disassociated buffer of given size.
- */
-struct buf *
-geteblk(size)
- int size;
-{
- struct buf *bp;
- int x;
-
- while ((bp = getnewbuf(size)) == 0)
- ;
- x = splbio();
- binshash(bp, bfreelist + BQ_AGE);
- splx(x);
-
- return (bp);
-}
-
-/*
- * Exchange a buffer's underlying buffer storage for one of different
- * size, taking care to maintain contents appropriately. When buffer
- * increases in size, caller is responsible for filling out additional
- * contents. When buffer shrinks in size, data is lost, so caller must
- * first return it to backing store before shrinking the buffer, as
- * no implied I/O will be done.
- *
- * Expanded buffer is returned as value.
- */
-void
-allocbuf(bp, size)
- register struct buf *bp;
- int size;
-{
- caddr_t newcontents;
-
- /* get new memory buffer */
-#ifndef notyet
- newcontents = (caddr_t) malloc (size, M_TEMP, M_WAITOK);
-#else /* notyet */
- if (round_page(size) == size)
- newcontents = (caddr_t) kmem_alloc(buffer_map, size);
- else
- newcontents = (caddr_t) malloc (size, M_TEMP, M_WAITOK);
-#endif /* notyet */
-
- /* copy the old into the new, up to the maximum that will fit */
- bcopy (bp->b_un.b_addr, newcontents, min(bp->b_bufsize, size));
-
- /* return old contents to free heap */
-#ifndef notyet
- free (bp->b_un.b_addr, M_TEMP);
-#else /* notyet */
- if (round_page(bp->b_bufsize) == bp->b_bufsize)
- kmem_free(buffer_map, bp->b_un.b_addr, bp->b_bufsize);
- else
- free (bp->b_un.b_addr, M_TEMP);
-#endif /* notyet */
-
- /* adjust buffer cache's idea of memory allocated to buffer contents */
- freebufspace -= size - bp->b_bufsize;
- allocbufspace += size - bp->b_bufsize;
-
- /* update buffer header */
- bp->b_un.b_addr = newcontents;
- bp->b_bcount = bp->b_bufsize = size;
-}
-
-/*
- * Patiently await operations to complete on this buffer.
- * When they do, extract error value and return it.
- * Extract and return any errors associated with the I/O.
- * If an invalid block, force it off the lookup hash chains.
- */
-biowait(bp)
- register struct buf *bp;
-{
- int x;
-
- x = splbio();
- while ((bp->b_flags & B_DONE) == 0)
- sleep((caddr_t)bp, PRIBIO);
- if((bp->b_flags & B_ERROR) || bp->b_error) {
- if ((bp->b_flags & B_INVAL) == 0) {
- bp->b_flags |= B_INVAL;
- bremhash(bp);
- binshash(bp, bfreelist + BQ_AGE);
- }
- if (!bp->b_error)
- bp->b_error = EIO;
- else
- bp->b_flags |= B_ERROR;
- splx(x);
- return (bp->b_error);
- } else {
- splx(x);
- return (0);
- }
-}
-
-/*
- * Finish up operations on a buffer, calling an optional
- * function (if requested), and releasing the buffer if
- * marked asynchronous. Then mark this buffer done so that
- * others biowait()'ing for it will notice when they are
- * woken up from sleep().
- */
-biodone(bp)
- register struct buf *bp;
-{
- int x;
-
- x = splbio();
- if (bp->b_flags & B_CALL) (*bp->b_iodone)(bp);
- bp->b_flags &= ~B_CALL;
- if ((bp->b_flags & (B_READ|B_DIRTY)) == B_DIRTY) {
- bp->b_flags &= ~B_DIRTY;
- vwakeup(bp);
- }
- if (bp->b_flags & B_ASYNC)
- brelse(bp);
- bp->b_flags &= ~B_ASYNC;
- bp->b_flags |= B_DONE;
- wakeup(bp);
- splx(x);
-}
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index e34c14a04ba4..1df65b9f395f 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)vfs_cache.c 7.8 (Berkeley) 2/28/91
- * $Id: vfs_cache.c,v 1.2 1993/10/16 15:25:19 rgrimes Exp $
+ * $Id: vfs_cache.c,v 1.3 1993/11/25 01:33:40 wollman Exp $
*/
#include "param.h"
@@ -92,6 +92,7 @@ int doingcache = 1; /* 1 => enable the cache */
* the name does not exist (negative cacheing), a status of ENOENT
* is returned. If the lookup fails, a status of zero is returned.
*/
+int
cache_lookup(ndp)
register struct nameidata *ndp;
{
@@ -189,6 +190,7 @@ cache_lookup(ndp)
/*
* Add an entry to the cache
*/
+void
cache_enter(ndp)
register struct nameidata *ndp;
{
@@ -240,6 +242,7 @@ cache_enter(ndp)
/*
* Name cache initialization, from vfs_init() when we are booting
*/
+void
nchinit()
{
register union nchash *nchp;
@@ -264,6 +267,7 @@ nchinit()
* Cache flush, a particular vnode; called when a vnode is renamed to
* hide entries that would now be invalid
*/
+void
cache_purge(vp)
struct vnode *vp;
{
@@ -291,6 +295,7 @@ cache_purge(vp)
* if the cache lru chain is modified while we are dumping the
* inode. This makes the algorithm O(n^2), but do you think I care?
*/
+void
cache_purgevfs(mp)
struct mount *mp;
{
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index 574efd4b8d73..0623ec831a68 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -31,20 +31,14 @@
* SUCH DAMAGE.
*
* from: @(#)vfs_conf.c 7.3 (Berkeley) 6/28/90
- * $Id: vfs_conf.c,v 1.2 1993/10/16 15:25:21 rgrimes Exp $
+ * $Id: vfs_conf.c,v 1.5 1994/01/16 02:26:39 martin Exp $
*/
#include "param.h"
+#include "systm.h"
#include "mount.h"
/*
- * This specifies the filesystem used to mount the root.
- * This specification should be done by /etc/config.
- */
-extern int ufs_mountroot();
-int (*mountroot)() = ufs_mountroot;
-
-/*
* These define the root filesystem and device.
*/
struct mount *rootfs;
@@ -72,6 +66,8 @@ extern struct vfsops pcfs_vfsops;
extern struct vfsops isofs_vfsops;
#endif
+extern struct vfsops procfs_vfsops;
+
struct vfsops *vfssw[] = {
(struct vfsops *)0, /* 0 = MOUNT_NONE */
&ufs_vfsops, /* 1 = MOUNT_UFS */
@@ -95,4 +91,5 @@ struct vfsops *vfssw[] = {
#else
(struct vfsops *)0,
#endif
+ &procfs_vfsops, /* 6 = MOUNT_PROCFS */
};
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 1202e9de838d..f35002a9460f 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* All rights reserved.
*
@@ -31,10 +38,11 @@
* SUCH DAMAGE.
*
* from: @(#)vfs_lookup.c 7.32 (Berkeley) 5/21/91
- * $Id: vfs_lookup.c,v 1.2 1993/10/16 15:25:23 rgrimes Exp $
+ * $Id: vfs_lookup.c,v 1.5.2.1 1994/05/04 07:54:56 rgrimes Exp $
*/
#include "param.h"
+#include "systm.h"
#include "syslimits.h"
#include "time.h"
#include "namei.h"
@@ -49,6 +57,8 @@
#include "ktrace.h"
#endif
+u_long nextvnodeid;
+
/*
* Convert a pathname into a pointer to a locked inode.
*
@@ -69,6 +79,7 @@
* if symbolic link, massage name in buffer and continue
* }
*/
+int
namei(ndp, p)
register struct nameidata *ndp;
struct proc *p;
@@ -91,10 +102,10 @@ namei(ndp, p)
MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
if (ndp->ni_segflg == UIO_SYSSPACE)
error = copystr(ndp->ni_dirp, ndp->ni_pnbuf,
- MAXPATHLEN, &ndp->ni_pathlen);
+ MAXPATHLEN, (u_int *)&ndp->ni_pathlen);
else
error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf,
- MAXPATHLEN, &ndp->ni_pathlen);
+ MAXPATHLEN, (u_int *)&ndp->ni_pathlen);
if (error) {
free(ndp->ni_pnbuf, M_NAMEI);
ndp->ni_vp = NULL;
@@ -230,6 +241,7 @@ namei(ndp, p)
* if LOCKPARENT set, return locked parent in ni_dvp
* if WANTPARENT set, return unlocked parent in ni_dvp
*/
+int
lookup(ndp, p)
register struct nameidata *ndp;
struct proc *p;
@@ -399,7 +411,7 @@ mntloop:
(ndp->ni_nameiop & NOCROSSMOUNT) == 0) {
while(mp->mnt_flag & MNT_MLOCK) {
mp->mnt_flag |= MNT_MWAIT;
- sleep((caddr_t)mp, PVFS);
+ tsleep((caddr_t)mp, PVFS, "lookup", 0);
goto mntloop;
}
if (error = VFS_ROOT(dp->v_mountedhere, &tdp))
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index e0d9d1201431..024c5679000b 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
@@ -31,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)vfs_subr.c 7.60 (Berkeley) 6/21/91
- * $Id: vfs_subr.c,v 1.4 1993/10/18 14:22:16 davidg Exp $
+ * $Id: vfs_subr.c,v 1.7.2.2 1994/05/04 07:55:00 rgrimes Exp $
*/
/*
@@ -39,6 +46,7 @@
*/
#include "param.h"
+#include "systm.h"
#include "proc.h"
#include "mount.h"
#include "time.h"
@@ -50,6 +58,10 @@
#include "errno.h"
#include "malloc.h"
+static void insmntque(struct vnode *, struct mount *);
+
+struct vnode *speclisth[SPECHSZ]; /* device special file vnode hash table */
+
/*
* Remove a mount point from the list of mounted filesystems.
* Unmount of the root is illegal.
@@ -71,13 +83,14 @@ vfs_remove(mp)
* Lock a filesystem.
* Used to prevent access to it while mounting and unmounting.
*/
+int
vfs_lock(mp)
register struct mount *mp;
{
while(mp->mnt_flag & MNT_MLOCK) {
mp->mnt_flag |= MNT_MWAIT;
- sleep((caddr_t)mp, PVFS);
+ tsleep((caddr_t)mp, PVFS, "vfslock", 0);
}
mp->mnt_flag |= MNT_MLOCK;
return (0);
@@ -105,13 +118,14 @@ vfs_unlock(mp)
* Mark a mount point as busy.
* Used to synchronize access and to delay unmounting.
*/
+int
vfs_busy(mp)
register struct mount *mp;
{
while(mp->mnt_flag & MNT_MPBUSY) {
mp->mnt_flag |= MNT_MPWANT;
- sleep((caddr_t)&mp->mnt_flag, PVFS);
+ tsleep((caddr_t)&mp->mnt_flag, PVFS, "vfsbusy", 0);
}
if (mp->mnt_flag & MNT_UNMOUNT)
return (1);
@@ -123,6 +137,7 @@ vfs_busy(mp)
* Free a busy filesystem.
* Panic if filesystem is not busy.
*/
+void
vfs_unbusy(mp)
register struct mount *mp;
{
@@ -179,13 +194,13 @@ void vattr_null(vap)
*/
struct vnode *vfreeh, **vfreet;
extern struct vnodeops dead_vnodeops, spec_vnodeops;
-extern void vclean();
long numvnodes;
struct vattr va_null;
/*
* Initialize the vnode structures and initialize each file system type.
*/
+void
vfsinit()
{
struct vfsops **vfsp;
@@ -208,6 +223,7 @@ vfsinit()
/*
* Return the next vnode from the free list.
*/
+int
getnewvnode(tag, mp, vops, vpp)
enum vtagtype tag;
struct mount *mp;
@@ -255,6 +271,7 @@ getnewvnode(tag, mp, vops, vpp)
/*
* Move a vnode from one mount queue to another.
*/
+static void
insmntque(vp, mp)
register struct vnode *vp;
register struct mount *mp;
@@ -289,6 +306,7 @@ insmntque(vp, mp)
* Make sure all write-behind blocks associated
* with mount point are flushed out (from sync).
*/
+void
mntflushbuf(mountp, flags)
struct mount *mountp;
int flags;
@@ -313,6 +331,7 @@ loop:
/*
* Flush all dirty buffers associated with a vnode.
*/
+void
vflushbuf(vp, flags)
register struct vnode *vp;
int flags;
@@ -350,7 +369,7 @@ loop:
s = splbio();
while (vp->v_numoutput) {
vp->v_flag |= VBWAIT;
- sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
+ tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "vflushbf", 0);
}
splx(s);
if (vp->v_dirtyblkhd) {
@@ -362,6 +381,7 @@ loop:
/*
* Update outstanding I/O count and do wakeup if requested.
*/
+void
vwakeup(bp)
register struct buf *bp;
{
@@ -388,6 +408,7 @@ vwakeup(bp)
* filesystem there will be no dirty buffers when we are done. Binval
* returns the count of dirty buffers when it is finished.
*/
+int
mntinvalbuf(mountp)
struct mount *mountp;
{
@@ -412,6 +433,7 @@ loop:
* Flush out and invalidate all buffers associated with a vnode.
* Called with the underlying object locked.
*/
+int
vinvalbuf(vp, save)
register struct vnode *vp;
int save;
@@ -432,7 +454,7 @@ vinvalbuf(vp, save)
s = splbio();
if (bp->b_flags & B_BUSY) {
bp->b_flags |= B_WANTED;
- sleep((caddr_t)bp, PRIBIO + 1);
+ tsleep((caddr_t)bp, PRIBIO + 1, "vinvalbf", 0);
splx(s);
break;
}
@@ -459,6 +481,7 @@ vinvalbuf(vp, save)
/*
* Associate a buffer with a vnode.
*/
+void
bgetvp(vp, bp)
register struct vnode *vp;
register struct buf *bp;
@@ -487,6 +510,7 @@ bgetvp(vp, bp)
/*
* Disassociate a buffer from a vnode.
*/
+void
brelvp(bp)
register struct buf *bp;
{
@@ -515,6 +539,7 @@ brelvp(bp)
* Used to assign file specific control information
* (indirect blocks) to the vnode to which they belong.
*/
+void
reassignbuf(bp, newvp)
register struct buf *bp;
register struct vnode *newvp;
@@ -551,6 +576,7 @@ reassignbuf(bp, newvp)
* Used for root filesystem, argdev, and swap areas.
* Also used for memory file system special devices.
*/
+int
bdevvp(dev, vpp)
dev_t dev;
struct vnode **vpp;
@@ -644,6 +670,7 @@ loop:
* indicate that the vnode is no longer usable (possibly having
* been changed to a new file system type).
*/
+int
vget(vp)
register struct vnode *vp;
{
@@ -651,7 +678,7 @@ vget(vp)
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
- sleep((caddr_t)vp, PINOD);
+ tsleep((caddr_t)vp, PINOD, "vget", 0);
return (1);
}
if (vp->v_usecount == 0) {
@@ -710,6 +737,7 @@ void vrele(vp)
panic("vrele: ref cnt");
}
#endif
+ vp->v_writecount = 0; /* XXX */
if (vfreeh == NULLVP) {
/*
* insert into empty list
@@ -731,6 +759,7 @@ void vrele(vp)
/*
* Page or buffer structure gets a reference.
*/
+void
vhold(vp)
register struct vnode *vp;
{
@@ -741,6 +770,7 @@ vhold(vp)
/*
* Page or buffer structure frees a reference.
*/
+void
holdrele(vp)
register struct vnode *vp;
{
@@ -760,6 +790,7 @@ holdrele(vp)
*/
int busyprt = 0; /* patch to print out busy vnodes */
+int
vflush(mp, skipvp, flags)
struct mount *mp;
struct vnode *skipvp;
@@ -902,7 +933,7 @@ void vgoneall(vp)
*/
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
- sleep((caddr_t)vp, PINOD);
+ tsleep((caddr_t)vp, PINOD, "vgoneall", 0);
return;
}
/*
@@ -933,11 +964,12 @@ void vgoneall(vp)
* Eliminate all activity associated with a vnode
* in preparation for reuse.
*/
-void vgone(vp)
+void
+vgone(vp)
register struct vnode *vp;
{
register struct vnode *vq;
- struct vnode *vx;
+ struct vnode *vx = 0;
long count;
/*
@@ -946,7 +978,7 @@ void vgone(vp)
*/
if (vp->v_flag & VXLOCK) {
vp->v_flag |= VXWANT;
- sleep((caddr_t)vp, PINOD);
+ tsleep((caddr_t)vp, PINOD, "vgone", 0);
return;
}
/*
@@ -1017,6 +1049,7 @@ void vgone(vp)
/*
* Lookup a vnode by device number.
*/
+int
vfinddev(dev, type, vpp)
dev_t dev;
enum vtype type;
@@ -1036,6 +1069,7 @@ vfinddev(dev, type, vpp)
/*
* Calculate the total number of references to a special device.
*/
+int
vcount(vp)
register struct vnode *vp;
{
@@ -1066,8 +1100,9 @@ loop:
static char *typename[] =
{ "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };
+void
vprint(label, vp)
- char *label;
+ const char *label;
register struct vnode *vp;
{
char buf[64];
@@ -1127,6 +1162,7 @@ int kinfo_vgetfailed;
* Copyout address of vnode followed by vnode.
*/
/* ARGSUSED */
+int
kinfo_vnode(op, where, acopysize, arg, aneeded)
int op;
char *where;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 395dc90e63aa..396bd6326f98 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)vfs_syscalls.c 7.74 (Berkeley) 6/21/91
- * $Id: vfs_syscalls.c,v 1.5 1993/10/23 16:02:54 davidg Exp $
+ * $Id: vfs_syscalls.c,v 1.10 1994/01/19 21:09:13 jtc Exp $
*/
#include "param.h"
@@ -47,6 +47,9 @@
#include "uio.h"
#include "malloc.h"
+static int getvnode(struct filedesc *, int, struct file **);
+static int chdirec(struct nameidata *, struct proc *);
+
/*
* Virtual File System System Calls
*/
@@ -63,6 +66,7 @@ struct mount_args {
};
/* ARGSUSED */
+int
mount(p, uap, retval)
struct proc *p;
register struct mount_args *uap;
@@ -71,7 +75,7 @@ mount(p, uap, retval)
register struct nameidata *ndp;
register struct vnode *vp;
register struct mount *mp;
- int error, flag;
+ int error, flag = 0;
struct nameidata nd;
/*
@@ -150,30 +154,10 @@ update:
/*
* Set the mount level flags.
*/
- if (uap->flags & MNT_RDONLY)
- mp->mnt_flag |= MNT_RDONLY;
- else
- mp->mnt_flag &= ~MNT_RDONLY;
- if (uap->flags & MNT_NOSUID)
- mp->mnt_flag |= MNT_NOSUID;
- else
- mp->mnt_flag &= ~MNT_NOSUID;
- if (uap->flags & MNT_NOEXEC)
- mp->mnt_flag |= MNT_NOEXEC;
- else
- mp->mnt_flag &= ~MNT_NOEXEC;
- if (uap->flags & MNT_NODEV)
- mp->mnt_flag |= MNT_NODEV;
- else
- mp->mnt_flag &= ~MNT_NODEV;
- if (uap->flags & MNT_NOCORE)
- mp->mnt_flag |= MNT_NOCORE;
- else
- mp->mnt_flag &= ~MNT_NOCORE;
- if (uap->flags & MNT_SYNCHRONOUS)
- mp->mnt_flag |= MNT_SYNCHRONOUS;
- else
- mp->mnt_flag &= ~MNT_SYNCHRONOUS;
+ mp->mnt_flag &=
+ ~(MNT_RDONLY|MNT_NOSUID|MNT_NOEXEC|MNT_NODEV|MNT_SYNCHRONOUS);
+ mp->mnt_flag |= uap->flags &
+ (MNT_RDONLY|MNT_NOSUID|MNT_NOEXEC|MNT_NODEV|MNT_SYNCHRONOUS);
/*
* Mount the filesystem.
*/
@@ -218,6 +202,7 @@ struct umount_args {
};
/* ARGSUSED */
+int
unmount(p, uap, retval)
struct proc *p;
register struct umount_args *uap;
@@ -257,6 +242,7 @@ unmount(p, uap, retval)
/*
* Do an unmount.
*/
+int
dounmount(mp, flags, p)
register struct mount *mp;
int flags;
@@ -293,6 +279,7 @@ dounmount(mp, flags, p)
* Sync each mounted filesystem.
*/
/* ARGSUSED */
+int
sync(p, uap, retval)
struct proc *p;
void *uap;
@@ -332,6 +319,7 @@ struct quotactl_args {
};
/* ARGSUSED */
+int
quotactl(p, uap, retval)
struct proc *p;
register struct quotactl_args *uap;
@@ -363,6 +351,7 @@ struct statfs_args {
};
/* ARGSUSED */
+int
statfs(p, uap, retval)
struct proc *p;
register struct statfs_args *uap;
@@ -399,6 +388,7 @@ struct fstatfs_args {
};
/* ARGSUSED */
+int
fstatfs(p, uap, retval)
struct proc *p;
register struct fstatfs_args *uap;
@@ -429,6 +419,7 @@ struct getfsstat_args {
int flags;
};
+int
getfsstat(p, uap, retval)
struct proc *p;
register struct getfsstat_args *uap;
@@ -481,6 +472,7 @@ struct fchdir_args {
};
/* ARGSUSED */
+int
fchdir(p, uap, retval)
struct proc *p;
struct fchdir_args *uap;
@@ -517,6 +509,7 @@ struct chdir_args {
};
/* ARGSUSED */
+int
chdir(p, uap, retval)
struct proc *p;
struct chdir_args *uap;
@@ -547,6 +540,7 @@ struct chroot_args {
};
/* ARGSUSED */
+int
chroot(p, uap, retval)
struct proc *p;
struct chroot_args *uap;
@@ -574,6 +568,7 @@ chroot(p, uap, retval)
/*
* Common routine for chroot and chdir.
*/
+static int
chdirec(ndp, p)
struct nameidata *ndp;
struct proc *p;
@@ -606,6 +601,7 @@ struct open_args {
int crtmode;
};
+int
open(p, uap, retval)
struct proc *p;
register struct open_args *uap;
@@ -645,6 +641,7 @@ open(p, uap, retval)
return (error);
}
vp = ndp->ni_vp;
+ VOP_UNLOCK(vp);
fp->f_flag = fmode & FMASK;
if (fmode & (O_EXLOCK | O_SHLOCK)) {
lf.l_whence = SEEK_SET;
@@ -658,7 +655,6 @@ open(p, uap, retval)
if ((fmode & FNONBLOCK) == 0)
type |= F_WAIT;
if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) {
- VOP_UNLOCK(vp);
(void) vn_close(vp, fp->f_flag, fp->f_cred, p);
ffree(fp);
fdp->fd_ofiles[indx] = NULL;
@@ -666,7 +662,6 @@ open(p, uap, retval)
}
fp->f_flag |= FHASLOCK;
}
- VOP_UNLOCK(vp);
fp->f_type = DTYPE_VNODE;
fp->f_ops = &vnops;
fp->f_data = (caddr_t)vp;
@@ -684,6 +679,7 @@ struct ocreat_args {
int fmode;
};
+int
ocreat(p, uap, retval)
struct proc *p;
register struct ocreat_args *uap;
@@ -713,6 +709,7 @@ struct mknod_args {
};
/* ARGSUSED */
+int
mknod(p, uap, retval)
struct proc *p;
register struct mknod_args *uap;
@@ -780,6 +777,7 @@ struct mkfifo_args {
};
/* ARGSUSED */
+int
mkfifo(p, uap, retval)
struct proc *p;
register struct mkfifo_args *uap;
@@ -825,6 +823,7 @@ struct link_args {
};
/* ARGSUSED */
+int
link(p, uap, retval)
struct proc *p;
register struct link_args *uap;
@@ -884,6 +883,7 @@ struct symlink_args {
};
/* ARGSUSED */
+int
symlink(p, uap, retval)
struct proc *p;
register struct symlink_args *uap;
@@ -931,6 +931,7 @@ struct unlink_args {
};
/* ARGSUSED */
+int
unlink(p, uap, retval)
struct proc *p;
struct unlink_args *uap;
@@ -983,6 +984,7 @@ struct lseek_args {
int sbase;
};
+int
lseek(p, uap, retval)
struct proc *p;
register struct lseek_args *uap;
@@ -1033,6 +1035,7 @@ struct saccess_args {
};
/* ARGSUSED */
+int
saccess(p, uap, retval)
struct proc *p;
register struct saccess_args *uap;
@@ -1087,6 +1090,7 @@ struct stat_args {
};
/* ARGSUSED */
+int
stat(p, uap, retval)
struct proc *p;
register struct stat_args *uap;
@@ -1122,6 +1126,7 @@ struct lstat_args {
};
/* ARGSUSED */
+int
lstat(p, uap, retval)
struct proc *p;
register struct lstat_args *uap;
@@ -1157,6 +1162,7 @@ struct readlink_args {
};
/* ARGSUSED */
+int
readlink(p, uap, retval)
struct proc *p;
register struct readlink_args *uap;
@@ -1206,6 +1212,7 @@ struct chflags_args {
};
/* ARGSUSED */
+int
chflags(p, uap, retval)
struct proc *p;
register struct chflags_args *uap;
@@ -1246,6 +1253,7 @@ struct fdchflags_args {
};
/* ARGSUSED */
+int
fchflags(p, uap, retval)
struct proc *p;
register struct fdchflags_args *uap;
@@ -1282,6 +1290,7 @@ struct chmod_args {
};
/* ARGSUSED */
+int
chmod(p, uap, retval)
struct proc *p;
register struct chmod_args *uap;
@@ -1322,6 +1331,7 @@ struct fchmod_args {
};
/* ARGSUSED */
+int
fchmod(p, uap, retval)
struct proc *p;
register struct fchmod_args *uap;
@@ -1359,6 +1369,7 @@ struct chown_args {
};
/* ARGSUSED */
+int
chown(p, uap, retval)
struct proc *p;
register struct chown_args *uap;
@@ -1401,6 +1412,7 @@ struct fchown_args {
};
/* ARGSUSED */
+int
fchown(p, uap, retval)
struct proc *p;
register struct fchown_args *uap;
@@ -1438,6 +1450,7 @@ struct utimes_args {
};
/* ARGSUSED */
+int
utimes(p, uap, retval)
struct proc *p;
register struct utimes_args *uap;
@@ -1450,7 +1463,12 @@ utimes(p, uap, retval)
int error;
struct nameidata nd;
- if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
+ VATTR_NULL(&vattr);
+ if ((caddr_t)uap->tptr == NULL) {
+ microtime(&tv[0]);
+ tv[1] = tv[0];
+ vattr.va_vaflags |= VA_UTIMES_NULL;
+ } else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))
return (error);
ndp = &nd;
ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
@@ -1463,7 +1481,6 @@ utimes(p, uap, retval)
error = EROFS;
goto out;
}
- VATTR_NULL(&vattr);
vattr.va_atime = tv[0];
vattr.va_mtime = tv[1];
error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
@@ -1482,6 +1499,7 @@ struct truncate_args {
};
/* ARGSUSED */
+int
truncate(p, uap, retval)
struct proc *p;
register struct truncate_args *uap;
@@ -1525,6 +1543,7 @@ struct ftruncate_args {
};
/* ARGSUSED */
+int
ftruncate(p, uap, retval)
struct proc *p;
register struct ftruncate_args *uap;
@@ -1564,6 +1583,7 @@ struct fsync_args {
};
/* ARGSUSED */
+int
fsync(p, uap, retval)
struct proc *p;
struct fsync_args *uap;
@@ -1595,6 +1615,7 @@ struct rename_args {
};
/* ARGSUSED */
+int
rename(p, uap, retval)
struct proc *p;
register struct rename_args *uap;
@@ -1685,6 +1706,7 @@ struct mkdir_args {
};
/* ARGSUSED */
+int
mkdir(p, uap, retval)
struct proc *p;
register struct mkdir_args *uap;
@@ -1730,6 +1752,7 @@ struct rmdir_args {
};
/* ARGSUSED */
+int
rmdir(p, uap, retval)
struct proc *p;
struct rmdir_args *uap;
@@ -1788,6 +1811,7 @@ struct getdirentries_args {
long *basep;
};
+int
getdirentries(p, uap, retval)
struct proc *p;
register struct getdirentries_args *uap;
@@ -1858,6 +1882,7 @@ struct revoke_args {
};
/* ARGSUSED */
+int
revoke(p, uap, retval)
struct proc *p;
register struct revoke_args *uap;
@@ -1895,10 +1920,11 @@ out:
/*
* Convert a user file descriptor to a kernel file entry.
*/
+static int
getvnode(fdp, fdes, fpp)
struct filedesc *fdp;
- struct file **fpp;
int fdes;
+ struct file **fpp;
{
struct file *fp;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index ed2dc6214a45..b273dc8b3604 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,11 @@
/*
+ * Copyright (c) UNIX System Laboratories, Inc. All or some portions
+ * of this file are derived from material licensed to the
+ * University of California by American Telephone and Telegraph Co.
+ * or UNIX System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ */
+/*
* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* All rights reserved.
*
@@ -31,7 +38,7 @@
* 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.4.2.2 1994/05/04 07:55:04 rgrimes Exp $
*/
#include "param.h"
@@ -54,6 +61,7 @@ struct fileops vnops =
* Common code for vnode open operations.
* Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
*/
+int
vn_open(ndp, p, fmode, cmode)
register struct nameidata *ndp;
struct proc *p;
@@ -139,6 +147,7 @@ bad:
* The read-only status of the file system is checked.
* Also, prototype text segments cannot be written.
*/
+int
vn_writechk(vp)
register struct vnode *vp;
{
@@ -167,6 +176,7 @@ vn_writechk(vp)
/*
* Vnode close call
*/
+int
vn_close(vp, flags, cred, p)
register struct vnode *vp;
int flags;
@@ -186,6 +196,7 @@ vn_close(vp, flags, cred, p)
* Package up an I/O request on a vnode into a uio and do it.
* [internal interface to file i/o for kernel only]
*/
+int
vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
enum uio_rw rw;
struct vnode *vp;
@@ -230,6 +241,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p)
/*
* File table vnode read routine.
*/
+int
vn_read(fp, uio, cred)
struct file *fp;
struct uio *uio;
@@ -251,6 +263,7 @@ vn_read(fp, uio, cred)
/*
* File table vnode write routine.
*/
+int
vn_write(fp, uio, cred)
struct file *fp;
struct uio *uio;
@@ -278,6 +291,7 @@ vn_write(fp, uio, cred)
/*
* File table vnode stat routine.
*/
+int
vn_stat(vp, sb, p)
struct vnode *vp;
register struct stat *sb;
@@ -300,6 +314,7 @@ vn_stat(vp, sb, p)
mode = vap->va_mode;
switch (vp->v_type) {
case VREG:
+ case VPROC:
mode |= S_IFREG;
break;
case VDIR:
@@ -345,6 +360,7 @@ vn_stat(vp, sb, p)
/*
* File table vnode ioctl routine.
*/
+int
vn_ioctl(fp, com, data, p)
struct file *fp;
int com;
@@ -376,7 +392,7 @@ vn_ioctl(fp, com, data, p)
case VCHR:
case VBLK:
error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
- if (error == 0 && com == TIOCSCTTY) {
+ if (error == 0 && com == TIOCSCTTY && (p->p_session->s_ttyvp != vp)) {
p->p_session->s_ttyvp = vp;
VREF(vp);
}
@@ -387,6 +403,7 @@ vn_ioctl(fp, com, data, p)
/*
* File table vnode select routine.
*/
+int
vn_select(fp, which, p)
struct file *fp;
int which;
@@ -400,6 +417,7 @@ vn_select(fp, which, p)
/*
* File table vnode close routine.
*/
+int
vn_closefile(fp, p)
struct file *fp;
struct proc *p;
@@ -415,6 +433,7 @@ vn_closefile(fp, p)
* - get vp by calling VFS_FHTOVP() macro
* - if lockflag lock it with VOP_LOCK()
*/
+int
vn_fhtovp(fhp, lockflag, vpp)
fhandle_t *fhp;
int lockflag;