Subject: Re: core file name format: diffs
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-kern
Date: 09/21/1999 17:48:53
--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii

On Mon, Sep 20, 1999 at 11:55:08AM -0400, der Mouse wrote:
> > so I've got the core name format stuff ready to commit (I hope :).
> 
> Most excellent!
> 
> I personally have little use for the core-name stuff, but I'm very
> pleased by the supporting mechanisms you've added - they look like
> something that can be leveraged usefully in the future.

I hope so :)

> 
> > The basename of the per-process corename format have to be either
> > 'core' or end with '.core', so that it's easy to locate core dumps
> > with 'find'.
> 
> I'm not at all sure I like this; I think syscall calls made by root
> should be exempt from this, and personally would argue an option should

Easy to change

> exist to disable the check entirely.  (What I'm thinking here is
> something like a database startup script that does something like
> "sysctl -w proc.$$.corename = /var/mydb/cores/%p.%t" - appending
> ".core" is redundant and having to do it is annoying.)

I'm not sure adding yet another kernel option or sysctl variable for this
is the rigth thing to do. We should really change the semantic of securelevel
to a mask-based one.

> 
> Mind you, I do think such a restriction should be available. :-)  It's
> probably better to have it all the time than not have it at all.
> 
> > One thing I've found really usefull is that it's now possible to
> > change limits of other processes.
> 
> That rocks.
> 
> > +.It Li n	The process's name
> > +.It Li p	The PID of the process
> > +.It Li t	The process's creation date
> > +.It Li u	The login name, as returned by
> > +.Xr getlogin 2
> 
> It would be good to state how %p and %t are rendered into text
> (primarily for completeness).

What about this ? :
.It Li n        The process's name
.It Li p        The PID of the process (integer)
.It Li t        The process's creation date (in seconds)
.It Li u        The login name, as returned by
.Xr getlogin 2

> 
> > +.It Li PROC_PID_LIMIT
> > +Return resources limits, as defined for the
> 
> > +The fourth level name is one of:
> [...]
> 
> > +The fifth level name is one of PROC_PID_LIMIT_TYPE_SOFT or
> > +PROC_PID_LIMIT_TYPE_HARD, to select respectively the soft or hard limit.
> 
> What type is the value at the end of the chain?  My first reaction is
> to assume it's a struct rlimit, but of course this doesn't make sense
> on close examination.  In any case, I'd prefer to see an explicit
> statement here describing it.

Ok, what about this ? :
The fifth level name is one of PROC_PID_LIMIT_TYPE_SOFT or
PROC_PID_LIMIT_TYPE_HARD, to select respectively the soft or hard limit.
Both are of type integer.                           

> 
> > +		if (*s != '%') {
> [...]
> > +			continue;
> > +		}
> > +		if (*(s+1) == 'n') { /* %n */
> [...]
> > +		}
> > +		if (*(s+1) == 'p') { /* %p */
> [...]
> > +		}
> [...]
> 
> Why do sequential tests here, rather than just using a switch, any
> particular reason?

No. This function is poorly written in general, I've re-done it.
It's better now (and uses a switch :)

> 
> > +				/* don't allow '.core' as a valid file name */
> 
> Why not?

I though .core would not be detected by
'find . \( -name core -o -name \*.core \) -print'
It turns out I was wrong, I removed this restriction.

> 
> > +	if ((indx = findname(string, "third", bufpp, lp)) == -1)
> [...]
> > +	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
> [...]
> > +	if ((indx = findname(string, "5th", bufpp, lp)) == -1)
> 
> Shouldn't that be "fifth", for consistency?

When I wrote this I didn't know how to spell 'fifth' :)
I fixed it.

Thanks for your comments !

Appened below are diff for the current state of the changes. What are missing
now is support in /etc/rc*, I'll do this soon.

--
Manuel Bouyer <bouyer@antioche.eu.org>
--

--RnlQjJ0d97Da+TV1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=sysctl-diff

Index: bin/csh/csh.1
===================================================================
RCS file: /cvsroot/basesrc/bin/csh/csh.1,v
retrieving revision 1.25
diff -u -r1.25 csh.1
--- csh.1	1999/07/30 01:08:12	1.25
+++ csh.1	1999/09/21 15:13:05
@@ -1408,6 +1408,10 @@
 names and scale factors, unambiguous prefixes
 of the names suffice.
 .Pp
+Limits of an arbitrary process can be displayed or set using the
+.Xr sysctl(8)
+utility.
+.Pp
 .It Ic login
 Terminate a login shell, replacing it with an instance of
 .Pa /usr/bin/login.
@@ -2133,6 +2137,7 @@
 .Xr tty 4 ,
 .Xr a.out 5 ,
 .Xr environ 7 ,
+.Xr sysctl 8 ,
 .br
 .Em "An introduction to the C shell"
 .Sh HISTORY
Index: bin/sh/sh.1
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/sh.1,v
retrieving revision 1.30
diff -u -r1.30 sh.1
--- sh.1	1999/07/06 14:01:01	1.30
+++ sh.1	1999/09/21 15:13:14
@@ -1389,6 +1389,10 @@
 or set. If value is specified, the limit is set to that number; otherwise
 the current limit is displayed.
 .Pp
+Limits of an arbitrary process can be displayed or set using the
+.Xr sysctl 8
+utility.
+.Pp
 .It umask Op Ar mask
 Set the value of umask (see
 .Xr umask 2 )
@@ -1500,6 +1504,7 @@
 .Xr passwd 4 ,
 .Xr profile 4 ,
 .Xr environ 5
+.Xr sysctl 8
 .Sh HISTORY
 A
 .Nm
Index: lib/libc/gen/sysctl.3
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/gen/sysctl.3,v
retrieving revision 1.36
diff -u -r1.36 sysctl.3
--- sysctl.3	1999/06/24 14:18:10	1.36
+++ sysctl.3	1999/09/21 15:14:28
@@ -127,6 +127,7 @@
 .It CTL\_KERN	sys/sysctl.h	High kernel limits
 .It CTL\_MACHDEP	sys/sysctl.h	Machine dependent
 .It CTL\_NET	sys/socket.h	Networking
+.It CTL\_PROC	sys/sysctl.h	Per-process
 .It CTL\_USER	sys/sysctl.h	User-level
 .It CTL\_VM	vm/vm_param.h	Virtual memory
 .El
@@ -255,6 +256,7 @@
 .It KERN\_BOOTTIME	struct timeval	no
 .It KERN\_CHOWN\_RESTRICTED	integer	no
 .It KERN\_CLOCKRATE	struct clockinfo	no
+.It KERN\_DEFCORENAME	string	yes
 .It KERN\_DOMAINNAME	string	yes
 .It KERN\_FILE	struct file	no
 .It KERN\_FSYNC	integer	no
@@ -288,7 +290,6 @@
 .It KERN\_RAWPARTITION	integer	no
 .It KERN\_SAVED\_IDS	integer	no
 .It KERN\_SECURELVL	integer	raise only
-.It KERN\_SHORTCORENAME	integer	yes
 .It KERN\_SYNCHRONIZED\_IO	integer	no
 .It KERN\_SYSVMSG	integer	no
 .It KERN\_SYSVSEM	integer	no
@@ -326,6 +327,26 @@
 This structure contains the clock, statistics clock and profiling clock
 frequencies, the number of micro-seconds per hz tick, and the clock
 skew rate.
+.It Li KERN_DEFCORENAME
+Default template for the name of core dumps (see also PROC_PID_CORENAME in the
+per-process variables CTL_PROC).  This can be either an absolute
+or relative path name. Format characters can be used in the template,
+preceeded by the percent character (``%''). The following characters
+are recognised as format and subsitued:
+.Bl -column "cAA" "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -offset indent
+.It Li n	The process's name
+.It Li p	The PID of the process (integer)
+.It Li t	The process's creation date (in seconds)
+.It Li u	The login name, as returned by
+.Xr getlogin 2
+.El
+The default value is
+.Nm %n.core
+and can be changed with the kernel configuration option
+.Cd options DEFCORENAME
+(see 
+.Xr options 4 ,
+.Xr core 5 ).
 .It Li KERN_DOMAINNAME
 Get or set the YP domain name.
 .It Li KERN_FILE
@@ -466,17 +487,6 @@
 The system security level.
 This level may be raised by processes with appropriate privilege.
 It may only be lowered by process 1.
-.It Li KERN_SHORTCORENAME
-Whether core dumps are named 
-.Nm programname.core
-(default, value 0) or 
-.Nm core
-(value 1).
-The default value can be changed to 1 with the kernel configuration option
-.Cd options SHORTCORENAME
-(see 
-.Xr options 4 ,
-.Xr core 5 ).
 .It Li KERN_SYNCHRONIZED_IO
 Returns 1 if the POSIX 1003.1b Synchronized I/O Option is available
 on this system,
@@ -717,6 +727,77 @@
 Returns the default UDP receive buffer size.
 .El
 .El
+.Sh CTL_PROC
+The string and integer information available for the CTL_PROC
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+These values are per-process, and as such may change from one process
+to another. When a process is created, the default values are inherited from
+its parent. When a set-user-ID or set-group-ID binary is executed, the
+value of PROC_PID_CORENAME is reset to the system default value.
+The second level name is either the magic value PROC_CURPROC, which
+points to the current process, or the PID of the target process.
+.Bl -column "USER_COLL_WEIGHTS_MAXXXX" "integerXXX" "yes" -offset indent
+.It Sy Pa Third level name	Type	Changeable
+.It PROC\_PID\_CORENAME	string	yes
+.It PROC\_PID\_LIMIT	node	not applicable
+.El
+.Bl -tag -width "123456"
+.Pp
+.It Li PROC_PID_CORENAME
+The template of the core dump file name. Modifiers are the same as for
+KERN_DEFCORENAME. The base name must either be 
+.Nm core
+or end with the suffix ``.core''.
+.It Li PROC_PID_LIMIT
+Return resources limits, as defined for the
+.Xr getrlimit 2
+and 
+.Xr setrlimit 2
+system calls.
+The fourth level name is one of:
+.Bl -tag -width PROC_PID_LIMIT_MEMLOCKAA
+.It Li PROC_PID_LIMIT_CPU
+The maximum amount of cpu time (in seconds) to be used by each process.
+.It Li PROC_PID_LIMIT_FSIZE
+The largest size (in bytes) file that may be created.
+.It Li PROC_PID_LIMIT_DATA
+The maximum size (in bytes) of the data segment for a process;
+this defines how far a program may extend its break with the
+.Xr sbrk 2
+system call.
+.It Li PROC_PID_LIMIT_STACK
+The maximum size (in bytes) of the stack segment for a process;
+this defines how far a program's stack segment may be extended.
+Stack extension is performed automatically by the system.
+.It Li PROC_PID_LIMIT_CORE
+The largest size (in bytes)
+.Pa core
+file that may be created.
+.It Li PROC_PID_LIMIT_RSS
+The maximum size (in bytes) to which a process's resident set size may
+grow.
+This imposes a limit on the amount of physical memory to be given to
+a process; if memory is tight, the system will prefer to take memory
+from processes that are exceeding their declared resident set size.
+.It Li PROC_PID_LIMIT_MEMLOCK
+The maximum size (in bytes) which a process may lock into memory
+using the
+.Xr mlock 2
+function.
+.It Li PROC_PID_LIMIT_NPROC
+The maximum number of simultaneous processes for this user id.
+.It Li PROC_PID_LIMIT_NOFILE
+The maximum number of open files for this process.
+.El
+.Pp
+The fifth level name is one of PROC_PID_LIMIT_TYPE_SOFT or
+PROC_PID_LIMIT_TYPE_HARD, to select respectively the soft or hard limit.
+Both are of type integer.
+.El
+.Pp
+
 .Sh CTL_USER
 The string and integer information available for the CTL_USER level
 is detailed below.
Index: lib/libc/sys/getrlimit.2
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/sys/getrlimit.2,v
retrieving revision 1.13
diff -u -r1.13 getrlimit.2
--- getrlimit.2	1999/03/22 19:45:04	1.13
+++ getrlimit.2	1999/09/21 15:14:29
@@ -54,7 +54,9 @@
 .Fn getrlimit
 call, and set with the
 .Fn setrlimit
-call.  
+call.  Resources of an arbitrary process can be obtained/changed using
+.Xr sysctl 3 .
+..
 .Pp
 The
 .Fa resource
Index: sbin/init/init.8
===================================================================
RCS file: /cvsroot/basesrc/sbin/init/init.8,v
retrieving revision 1.18
diff -u -r1.18 init.8
--- init.8	1998/11/14 07:47:36	1.18
+++ init.8	1999/09/21 15:14:30
@@ -116,6 +116,9 @@
 .Xr ipf 8
 (the in-kernel IP filtering facility) may not be changed.
 
+Users may not change the per-process core name template format, only the
+default can be changed.
+
 Downgrading from highly secure mode to insecure mode (that is, to single-user
 mode) always requires the root password to be entered on the console, whether
 the console is marked as 'secure' in
Index: share/man/man5/core.5
===================================================================
RCS file: /cvsroot/sharesrc/share/man/man5/core.5,v
retrieving revision 1.8
diff -u -r1.8 core.5
--- core.5	1999/03/17 20:19:44	1.8
+++ core.5	1999/09/21 15:15:32
@@ -56,14 +56,10 @@
 .Xr savecore 8 . )
 The file is normally named 
 .Nm programname.core ,
-but is called
-.Nm core
-if the 
-kernel configuration option 
-.Cd options SHORTCORENAME
-is defined or the sysctl variable
-.Em kern.shortcorename
-is set to 1.
+but the name can be changed with the sysctl variables
+.Em kern.defcorename
+and
+.Em proc.<pid>.corename
 .Pp
 The maximum size of a
 .Nm programname.core
Index: sys/compat/common/kern_resource_43.c
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/common/kern_resource_43.c,v
retrieving revision 1.5
diff -u -r1.5 kern_resource_43.c
--- kern_resource_43.c	1997/10/15 17:03:52	1.5
+++ kern_resource_43.c	1999/09/21 15:16:09
@@ -101,5 +101,5 @@
 		return (error);
 	lim.rlim_cur = olim.rlim_cur;
 	lim.rlim_max = olim.rlim_max;
-	return (dosetrlimit(p, which, &lim));
+	return (dosetrlimit(p, p->p_cred, which, &lim));
 }
Index: sys/compat/netbsd32/netbsd32_netbsd.c
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/netbsd32/netbsd32_netbsd.c,v
retrieving revision 1.17
diff -u -r1.17 netbsd32_netbsd.c
--- netbsd32_netbsd.c	1999/08/05 18:08:15	1.17
+++ netbsd32_netbsd.c	1999/09/21 15:16:11
@@ -3591,7 +3591,7 @@
 	error = copyin((caddr_t)(u_long)SCARG(uap, rlp), &alim, sizeof(struct rlimit));
 	if (error)
 		return (error);
-	return (dosetrlimit(p, which, &alim));
+	return (dosetrlimit(p, p->p_cred, which, &alim));
 }
 
 int
Index: sys/compat/svr4/svr4_resource.c
===================================================================
RCS file: /cvsroot/syssrc/sys/compat/svr4/svr4_resource.c,v
retrieving revision 1.4
diff -u -r1.4 svr4_resource.c
--- svr4_resource.c	1999/09/07 18:20:19	1.4
+++ svr4_resource.c	1999/09/21 15:16:11
@@ -185,7 +185,7 @@
 	else if (slim.rlim_cur == SVR4_RLIM_SAVED_CUR)
 		blim.rlim_cur = limp->rlim_cur;
 
-	return dosetrlimit(p, rl, &blim);
+	return dosetrlimit(p, p->p_cred, rl, &blim);
 }
 
 
@@ -283,5 +283,5 @@
 	else if (slim.rlim_cur == SVR4_RLIM64_SAVED_CUR)
 		blim.rlim_cur = limp->rlim_cur;
 
-	return dosetrlimit(p, rl, &blim);
+	return dosetrlimit(p, p->p_cred, rl, &blim);
 }
Index: sys/conf/files
===================================================================
RCS file: /cvsroot/syssrc/sys/conf/files,v
retrieving revision 1.316
diff -u -r1.316 files
--- files	1999/09/19 21:48:09	1.316
+++ files	1999/09/21 15:16:15
@@ -9,7 +9,7 @@
 defopt	KTRACE
 defopt	LOCKDEBUG
 defopt	RTC_OFFSET
-defopt	SHORTCORENAME
+defopt	DEFCORENAME
 defopt	UCONSOLE
 
 defopt	MULTIPROCESSOR
Index: sys/kern/init_main.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/init_main.c,v
retrieving revision 1.156
diff -u -r1.156 init_main.c
--- init_main.c	1999/09/17 20:11:56	1.156
+++ init_main.c	1999/09/21 15:17:30
@@ -182,6 +182,7 @@
 #if defined(NFSSERVER) || defined(NFS)
 	extern void nfs_init __P((void));
 #endif
+	extern char defcorename[];
 
 	/*
 	 * Initialize the current process pointer (curproc) before
@@ -286,6 +287,7 @@
 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
+	limit0.pl_corename = defcorename;
 	limit0.p_refcnt = 1;
 
 	/*
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v
retrieving revision 1.102
diff -u -r1.102 kern_exec.c
--- kern_exec.c	1999/08/09 02:42:20	1.102
+++ kern_exec.c	1999/09/21 15:17:30
@@ -457,7 +457,7 @@
 			p->p_ucred->cr_uid = attr.va_uid;
 		if (attr.va_mode & S_ISGID)
 			p->p_ucred->cr_gid = attr.va_gid;
-		p->p_flag |= P_SUGID;
+		p_sugid(p);
 	} else
 		p->p_flag &= ~P_SUGID;
 	p->p_cred->p_svuid = p->p_ucred->cr_uid;
Index: sys/kern/kern_proc.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_proc.c,v
retrieving revision 1.34
diff -u -r1.34 kern_proc.c
--- kern_proc.c	1999/07/25 06:30:34	1.34
+++ kern_proc.c	1999/09/21 15:17:31
@@ -519,6 +519,25 @@
 	}
 }
 
+/* mark process as suid/sgid, reset some values do defaults */
+void
+p_sugid(p)
+	struct proc *p;
+{
+	extern char defcorename[];
+
+	p->p_flag |= P_SUGID;
+	/* reset what needs to be reset in plimit */
+	if (p->p_limit->pl_corename != defcorename) {
+		if (p->p_limit->p_refcnt > 1) {
+			p->p_limit->p_refcnt--;
+			p->p_limit = limcopy(p->p_limit);
+		}
+		p->p_limit->pl_corename = defcorename;
+	}
+}
+
+
 #ifdef DEBUG
 void
 pgrpdump()
Index: sys/kern/kern_prot.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_prot.c,v
retrieving revision 1.54
diff -u -r1.54 kern_prot.c
--- kern_prot.c	1999/04/30 05:30:32	1.54
+++ kern_prot.c	1999/09/21 15:17:32
@@ -335,7 +335,7 @@
 	pc->pc_ucred->cr_uid = uid;
 	pc->p_ruid = uid;
 	pc->p_svuid = uid;
-	p->p_flag |= P_SUGID;
+	p_sugid(p);
 	return (0);
 }
 
@@ -363,7 +363,7 @@
 	 */
 	pc->pc_ucred = crcopy(pc->pc_ucred);
 	pc->pc_ucred->cr_uid = euid;
-	p->p_flag |= P_SUGID;
+	p_sugid(p);
 	return (0);
 }
 
@@ -408,7 +408,7 @@
 	}
 
 	if (euid != (uid_t)-1 && ruid != (uid_t)-1)
-		p->p_flag |= P_SUGID;
+		p_sugid(p);
 	return (0);
 }
 
@@ -434,7 +434,7 @@
 	pc->pc_ucred->cr_gid = gid;
 	pc->p_rgid = gid;
 	pc->p_svgid = gid;
-	p->p_flag |= P_SUGID;
+	p_sugid(p);
 	return (0);
 }
 
@@ -458,7 +458,7 @@
 		return (error);
 	pc->pc_ucred = crcopy(pc->pc_ucred);
 	pc->pc_ucred->cr_gid = egid;
-	p->p_flag |= P_SUGID;
+	p_sugid(p);
 	return (0);
 }
 
@@ -501,7 +501,7 @@
 	}
 
 	if (egid != (gid_t)-1 && rgid != (gid_t)-1)
-		p->p_flag |= P_SUGID;
+		p_sugid(p);
 	return (0);
 }
 
@@ -531,7 +531,7 @@
 	if (error)
 		return (error);
 	pc->pc_ucred->cr_ngroups = ngrp;
-	p->p_flag |= P_SUGID;
+	p_sugid(p);
 	return (0);
 }
 
Index: sys/kern/kern_resource.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_resource.c,v
retrieving revision 1.52
diff -u -r1.52 kern_resource.c
--- kern_resource.c	1999/07/25 06:30:34	1.52
+++ kern_resource.c	1999/09/21 15:17:32
@@ -225,12 +225,13 @@
 	error = copyin(SCARG(uap, rlp), &alim, sizeof(struct rlimit));
 	if (error)
 		return (error);
-	return (dosetrlimit(p, which, &alim));
+	return (dosetrlimit(p, p->p_cred, which, &alim));
 }
 
 int
-dosetrlimit(p, which, limp)
+dosetrlimit(p, cred, which, limp)
 	struct proc *p;
+	struct  pcred *cred;
 	int which;
 	struct rlimit *limp;
 {
@@ -247,7 +248,7 @@
 	alimp = &p->p_rlimit[which];
 	if (limp->rlim_cur > alimp->rlim_max || 
 	    limp->rlim_max > alimp->rlim_max)
-		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+		if ((error = suser(cred->pc_ucred, &p->p_acflag)) != 0)
 			return (error);
 	if (limp->rlim_cur > limp->rlim_max)
 		limp->rlim_cur = limp->rlim_max;
@@ -458,6 +459,7 @@
 	newlim = pool_get(&plimit_pool, PR_WAITOK);
 	memcpy(newlim->pl_rlimit, lim->pl_rlimit,
 	    sizeof(struct rlimit) * RLIM_NLIMITS);
+	newlim->pl_corename = lim->pl_corename;
 	newlim->p_lflags = 0;
 	newlim->p_refcnt = 1;
 	return (newlim);
Index: sys/kern/kern_sig.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_sig.c,v
retrieving revision 1.93
diff -u -r1.93 kern_sig.c
--- kern_sig.c	1999/08/31 12:30:35	1.93
+++ kern_sig.c	1999/09/21 15:17:33
@@ -79,6 +79,7 @@
 
 void stop __P((struct proc *p));
 void killproc __P((struct proc *, char *));
+static int build_corename __P((char *));
 
 sigset_t contsigmask, stopsigmask, sigcantmask;
 
@@ -1264,9 +1265,8 @@
 	struct nameidata nd;
 	struct vattr vattr;
 	int error, error1;
-	char name[MAXCOMLEN+6];		/* progname.core */
+	char name[MAXPATHLEN];
 	struct core core;
-	extern int shortcorename;
 
 	/*
 	 * Make sure the process has not set-id, to prevent data leaks.
@@ -1293,11 +1293,10 @@
 	    (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0)
 		return (EPERM);
 
-	if (shortcorename) 
-		sprintf(name, "core");
-	else
-		sprintf(name, "%s.core", p->p_comm);
-	
+	error = build_corename(name);
+	if (error)
+		return error;
+
 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
 	error = vn_open(&nd, O_CREAT | FWRITE | FNOSYMLINK, S_IRUSR | S_IWUSR);
 	if (error)
@@ -1393,4 +1392,52 @@
 
 	psignal(p, SIGSYS);
 	return (ENOSYS);
+}
+
+static int
+build_corename(dst)
+	char *dst;
+{
+	const char *s;
+	char *d;
+	int len, i;
+
+	for (s = curproc->p_limit->pl_corename, len = 0, d = dst;
+	    *s != '\0'; s++) {
+		if (*s == '%') {
+			switch (*(s+1)) {
+			case 'n':
+				i = snprintf(d,MAXPATHLEN - 1 - len, "%s",
+				    curproc->p_comm);
+				break;
+			case 'p':
+				i = snprintf(d, MAXPATHLEN - 1 - len, "%d",
+				    curproc->p_pid);
+				break;
+			case 'u':
+				i = snprintf(d, MAXPATHLEN - 1 - len, "%s",
+				    curproc->p_pgrp->pg_session->s_login);
+				break;
+			case 't':
+				i = snprintf(d, MAXPATHLEN - 1 - len, "%ld",
+				    curproc->p_stats->p_start.tv_sec);
+				break;
+			default:
+				goto copy;
+			}
+			if (i >= MAXPATHLEN - 1 - len)
+				return ENAMETOOLONG;
+			len += i;
+			d += i;
+			s++;
+		} else {
+copy:			*d = *s;
+			d++;
+			len++;
+			if (len >= MAXPATHLEN - 1)
+				return ENAMETOOLONG;
+		}
+	}
+	*d = '\0';
+	return 0;
 }
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_sysctl.c,v
retrieving revision 1.50
diff -u -r1.50 kern_sysctl.c
--- kern_sysctl.c	1999/07/25 06:30:35	1.50
+++ kern_sysctl.c	1999/09/21 15:17:33
@@ -44,7 +44,7 @@
 
 #include "opt_ddb.h"
 #include "opt_insecure.h"
-#include "opt_shortcorename.h"
+#include "opt_defcorename.h"
 #include "opt_sysv.h"
 
 #include <sys/param.h>
@@ -68,6 +68,8 @@
 
 #include <sys/mount.h>
 #include <sys/syscallargs.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
 
 
 #if defined(DDB)
@@ -102,9 +104,6 @@
 	sysctlfn *fn;
 	int name[CTL_MAXNAME];
 
-	if (SCARG(uap, new) != NULL &&
-	    (error = suser(p->p_ucred, &p->p_acflag)))
-		return (error);
 	/*
 	 * all top-level sysctl names are non-terminal
 	 */
@@ -115,6 +114,15 @@
 	if (error)
 		return (error);
 
+	/*
+	 * For all but CTL_PROC, must be root to change a value.
+	 * For CTL_PROC, must be root, or owner of the proc (and not suid),
+	 * this is checked in proc_sysctl() (once we know the targer proc).
+	 */
+	if (SCARG(uap, new) != NULL && name[0] != CTL_PROC &&
+		    (error = suser(p->p_ucred, &p->p_acflag)))
+			return error;
+
 	switch (name[0]) {
 	case CTL_KERN:
 		fn = kern_sysctl;
@@ -146,6 +154,9 @@
 		fn = ddb_sysctl;
 		break;
 #endif
+	case CTL_PROC:
+		fn = proc_sysctl;
+		break;
 	default:
 		return (EOPNOTSUPP);
 	}
@@ -210,10 +221,12 @@
 #else
 int securelevel = 0;
 #endif
-#ifdef SHORTCORENAME
-int shortcorename = 1;
+#ifdef DEFCORENAME
+char defcorename[MAXPATHLEN] = DEFCORENAME;
+int defcorenamelen = sizeof(DEFCORENAME);
 #else
-int shortcorename = 0;
+char defcorename[MAXPATHLEN] = "%n.core";
+int defcorenamelen = sizeof("%n.core");
 #endif
 
 /*
@@ -232,7 +245,6 @@
 	int error, level, inthostid;
 	int old_autonicetime;
 	int old_vnodes;
-	int old_shortcorename;
 	extern char ostype[], osrelease[], version[];
 
 	/* All sysctl names at this level, except for a few, are terminal. */
@@ -304,7 +316,7 @@
 	case KERN_VNODE:
 		return (sysctl_vnode(oldp, oldlenp, p));
 	case KERN_PROC:
-		return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
+		return (sysctl_doeproc(name + 1, namelen - 1, oldp, oldlenp));
 	case KERN_FILE:
 		return (sysctl_file(oldp, oldlenp));
 #ifdef GPROF
@@ -380,16 +392,14 @@
 #else
 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
 #endif
- 	case KERN_SHORTCORENAME:
- 		/* Only allow values of zero or one. */
- 		old_shortcorename = shortcorename;
- 		error = sysctl_int(oldp, oldlenp, newp, newlen, 
- 		    &shortcorename);
- 		if (shortcorename != 0 && shortcorename != 1) {
- 			shortcorename = old_shortcorename;
- 			return (EINVAL);
- 		}
- 		return (error);
+ 	case KERN_DEFCORENAME:
+		if (newp && newlen < 1)
+			return (EINVAL);
+		error = sysctl_string(oldp, oldlenp, newp, newlen,
+		    defcorename, sizeof(defcorename));
+		if (newp && !error)
+			defcorenamelen = newlen;
+		return (error);
 	case KERN_SYNCHRONIZED_IO:
 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
 	case KERN_IOV_MAX:
@@ -498,6 +508,133 @@
 }
 #endif /* DEBUG */
 
+int
+proc_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+	int *name;
+	u_int namelen;
+	void *oldp;
+	size_t *oldlenp;
+	void *newp;
+	size_t newlen;
+	struct proc *p;
+{
+	struct proc *ptmp;
+	const struct proclist_desc *pd;
+	int error = 0;
+	struct rlimit alim;
+	char *tmps;
+	int i, curlen, len;
+
+	if (namelen < 2)
+		return EINVAL;
+
+	if (name[0] == PROC_CURPROC) {
+		ptmp = p;
+	} else {
+		proclist_lock_read();
+		for (pd = proclists; pd->pd_list != NULL; pd++) {
+			for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL;
+			    ptmp = LIST_NEXT(ptmp, p_list)) {
+				/* Skip embryonic processes. */
+				if (ptmp->p_stat == SIDL)
+					continue;
+				if (ptmp->p_pid == (pid_t)name[0])
+					break;
+			}
+			if (ptmp != NULL)
+				break;
+		}
+		proclist_unlock_read();
+		if (ptmp == NULL)
+			return(ESRCH);
+		if (p->p_ucred->cr_uid != 0) {
+			if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid ||
+			    p->p_cred->p_ruid != ptmp->p_cred->p_svuid)
+				return EPERM;
+			if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid)
+				return EPERM; /* sgid proc */
+			for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
+				if (p->p_ucred->cr_groups[i] ==
+				    ptmp->p_cred->p_rgid)
+					break;
+			}
+			if (i == p->p_ucred->cr_ngroups)
+				return EPERM;
+		}
+	}
+	if (name[1] == PROC_PID_CORENAME) {
+		if (namelen != 2)
+			return EINVAL;
+		/*
+		 * Can't use sysctl_string() here because we may malloc a new
+		 * area during the process, so we have to do it by hand.
+		 */
+		curlen = strlen(ptmp->p_limit->pl_corename) + 1;
+		if (oldp && *oldlenp < curlen)
+			return (ENOMEM);
+		if (newp) {
+			tmps = (char*)newp;
+			if (securelevel > 2)
+				return EPERM;
+			if (newlen > MAXPATHLEN)
+				return ENAMETOOLONG;
+			/* Enforce to be either 'core' for end with '.core' */
+			if (newlen < 4) /* c.o.r.e */
+				return EINVAL;
+			len = newlen - 4;
+			if (len > 0) {
+				if (tmps[len - 1] != '.' &&
+				    tmps[len - 1] != '/')
+					return EINVAL;
+			}
+			if (strcmp(&tmps[len], "core") != 0)
+				return EINVAL;
+		}
+		if (oldp) {
+			*oldlenp = curlen;
+			error = copyout(ptmp->p_limit->pl_corename, oldp,
+			    curlen);
+		}
+		if (newp && error == 0) {
+			if (ptmp->p_limit->p_refcnt > 1 &&
+			    (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) {
+				ptmp->p_limit->p_refcnt--;
+				ptmp->p_limit = limcopy(ptmp->p_limit);
+			} else if (ptmp->p_limit->pl_corename != defcorename) {
+				free(ptmp->p_limit->pl_corename, M_TEMP);
+			}
+			ptmp->p_limit->pl_corename = malloc(newlen + 1,
+			    M_TEMP, M_WAITOK);
+			error = copyin(newp, ptmp->p_limit->pl_corename,
+			    newlen + 1);
+			ptmp->p_limit->pl_corename[newlen] = 0;
+		}
+		return (error);
+	}
+	if (name[1] == PROC_PID_LIMIT) {
+		if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID)
+			return EINVAL;
+		memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim));
+		if (name[3] == PROC_PID_LIMIT_TYPE_HARD)
+			error = sysctl_quad(oldp, oldlenp, newp, newlen,
+			    &alim.rlim_max);
+		else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT)
+			error = sysctl_quad(oldp, oldlenp, newp, newlen,
+			    &alim.rlim_cur);
+		else 
+			error = EINVAL;
+
+		if (error)
+			return error;
+
+		if (newp)
+			error = dosetrlimit(ptmp, p->p_cred,
+			    name[2] - 1, &alim);
+		return error;
+	}
+	return (EINVAL);
+}
+
 /*
  * Validate parameters and get old / set new parameters
  * for an integer-valued sysctl function.
@@ -548,6 +685,55 @@
 
 /*
  * Validate parameters and get old / set new parameters
+ * for an quad-valued sysctl function.
+ */
+int
+sysctl_quad(oldp, oldlenp, newp, newlen, valp)
+	void *oldp;
+	size_t *oldlenp;
+	void *newp;
+	size_t newlen;
+	quad_t *valp;
+{
+	int error = 0;
+
+	if (oldp && *oldlenp < sizeof(quad_t))
+		return (ENOMEM);
+	if (newp && newlen != sizeof(quad_t))
+		return (EINVAL);
+	*oldlenp = sizeof(quad_t);
+	if (oldp)
+		error = copyout(valp, oldp, sizeof(quad_t));
+	if (error == 0 && newp)
+		error = copyin(newp, valp, sizeof(quad_t));
+	return (error);
+}
+
+/*
+ * As above, but read-only.
+ */
+int
+sysctl_rdquad(oldp, oldlenp, newp, val)
+	void *oldp;
+	size_t *oldlenp;
+	void *newp;
+	quad_t val;
+{
+	int error = 0;
+
+	if (oldp && *oldlenp < sizeof(quad_t))
+		return (ENOMEM);
+	if (newp)
+		return (EPERM);
+	*oldlenp = sizeof(quad_t);
+	if (oldp)
+		error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
+	return (error);
+}
+
+
+/*
+ * Validate parameters and get old / set new parameters
  * for a string-valued sysctl function.
  */
 int
@@ -709,7 +895,7 @@
 #define KERN_PROCSLOP	(5 * sizeof(struct kinfo_proc))
 
 int
-sysctl_doproc(name, namelen, where, sizep)
+sysctl_doeproc(name, namelen, where, sizep)
 	int *name;
 	u_int namelen;
 	char *where;
Index: sys/sys/proc.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/proc.h,v
retrieving revision 1.83
diff -u -r1.83 proc.h
--- proc.h	1999/08/10 23:33:27	1.83
+++ proc.h	1999/09/21 15:17:47
@@ -392,5 +392,6 @@
 void	proclist_unlock_read __P((void));
 int	proclist_lock_write __P((void));
 void	proclist_unlock_write __P((int));
+void	p_sugid __P((struct proc*));
 #endif	/* _KERNEL */
 #endif	/* !_SYS_PROC_H_ */
Index: sys/sys/resource.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/resource.h,v
retrieving revision 1.19
diff -u -r1.19 resource.h
--- resource.h	1998/12/09 14:39:09	1.19
+++ resource.h	1999/09/21 15:17:47
@@ -120,7 +120,8 @@
 
 #ifdef _KERNEL
 extern struct loadavg averunnable;
-int	dosetrlimit __P((struct proc *, int, struct rlimit *));
+struct pcred;
+int	dosetrlimit __P((struct proc *, struct pcred *, int, struct rlimit *));
 int	donice __P((struct proc *, struct proc *, int));
 
 #else
Index: sys/sys/resourcevar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/resourcevar.h,v
retrieving revision 1.13
diff -u -r1.13 resourcevar.h
--- resourcevar.h	1998/03/01 02:24:14	1.13
+++ resourcevar.h	1999/09/21 15:17:47
@@ -73,6 +73,7 @@
  */
 struct plimit {
 	struct	rlimit pl_rlimit[RLIM_NLIMITS];
+	char	*pl_corename;
 #define	PL_SHAREMOD	0x01		/* modifications are shared */
 	int	p_lflags;
 	int	p_refcnt;		/* number of references */
@@ -88,8 +89,7 @@
 void	 addupc_task __P((struct proc *p, u_long pc, u_int ticks));
 void	 calcru __P((struct proc *p, struct timeval *up, struct timeval *sp,
 	    struct timeval *ip));
-struct plimit
-	*limcopy __P((struct plimit *lim));
+struct plimit *limcopy __P((struct plimit *lim));
 void	 ruadd __P((struct rusage *ru, struct rusage *ru2));
 #endif
 #endif	/* !_SYS_RESOURCEVAR_H_ */
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/sysctl.h,v
retrieving revision 1.35
diff -u -r1.35 sysctl.h
--- sysctl.h	1999/06/24 14:18:12	1.35
+++ sysctl.h	1999/09/21 15:17:48
@@ -92,7 +92,8 @@
 #define	CTL_MACHDEP	7		/* machine dependent */
 #define	CTL_USER	8		/* user-level */
 #define	CTL_DDB		9		/* in-kernel debugger */
-#define	CTL_MAXID	10		/* number of valid top-level ids */
+#define	CTL_PROC	10		/* per-proc attr */
+#define	CTL_MAXID	11		/* number of valid top-level ids */
 
 #define CTL_NAMES { \
 	{ 0, 0 }, \
@@ -105,6 +106,7 @@
 	{ "machdep", CTLTYPE_NODE }, \
 	{ "user", CTLTYPE_NODE }, \
 	{ "ddb", CTLTYPE_NODE }, \
+	{ "proc", CTLTYPE_NODE }, \
 }
 
 /*
@@ -145,7 +147,7 @@
 #define	KERN_SYSVMSG		33	/* int: SysV message queue suppoprt */
 #define	KERN_SYSVSEM		34	/* int: SysV semaphore support */
 #define	KERN_SYSVSHM		35	/* int: SysV shared memory support */
-#define	KERN_SHORTCORENAME	36	/* int: programs dump core as "core" */
+#define	KERN_DEFCORENAME	36	/* string: default corename format */
 #define	KERN_SYNCHRONIZED_IO	37	/* int: POSIX synchronized I/O */
 #define	KERN_IOV_MAX		38	/* int: max iovec's for readv(2) etc. */
 #define	KERN_MBUF		39	/* node: mbuf parameters */
@@ -192,7 +194,7 @@
 	{ "sysvmsg", CTLTYPE_INT }, \
 	{ "sysvsem", CTLTYPE_INT }, \
 	{ "sysvshm", CTLTYPE_INT }, \
-	{ "shortcorename", CTLTYPE_INT }, \
+	{ "defcorename", CTLTYPE_STRING }, \
 	{ "synchronized_io", CTLTYPE_INT }, \
 	{ "iov_max", CTLTYPE_INT }, \
 	{ "mbuf", CTLTYPE_NODE }, \
@@ -356,6 +358,61 @@
 #define	CTL_DEBUG_VALUE		1	/* int: variable value */
 #define	CTL_DEBUG_MAXID		20
 
+/*
+ * CTL_PROC subtype. Either a PID, or a magic value for the current proc.
+ */
+
+#define PROC_CURPROC	(~((u_int)1 << 31))
+
+/*
+ * CTL_PROC tree: either corename (string), or a limit
+ * (rlimit.<type>.{hard,soft}, int).
+ */
+#define PROC_PID_CORENAME	1
+#define	PROC_PID_LIMIT		2
+#define	PROC_PID_MAXID		3
+
+#define	PROC_PID_NAMES { \
+	{ 0, 0 }, \
+	{ "corename", CTLTYPE_STRING }, \
+	{ "rlimit", CTLTYPE_NODE }, \
+}
+
+/* Limit types from <sys/resources.h> */
+#define PROC_PID_LIMIT_CPU	(RLIMIT_CPU+1)
+#define PROC_PID_LIMIT_FSIZE	(RLIMIT_FSIZE+1)
+#define PROC_PID_LIMIT_DATA	(RLIMIT_DATA+1)
+#define PROC_PID_LIMIT_STACK	(RLIMIT_STACK+1)
+#define PROC_PID_LIMIT_CORE	(RLIMIT_CORE+1)
+#define PROC_PID_LIMIT_RSS	(RLIMIT_RSS+1)
+#define PROC_PID_LIMIT_MEMLOCK	(RLIMIT_MEMLOCK+1)
+#define PROC_PID_LIMIT_NPROC	(RLIMIT_NPROC+1)
+#define PROC_PID_LIMIT_NOFILE	(RLIMIT_NOFILE+1)
+#define PROC_PID_LIMIT_MAXID 	10
+
+#define PROC_PID_LIMIT_NAMES { \
+	{ 0, 0 }, \
+	{ "cputime", CTLTYPE_NODE }, \
+	{ "filesize", CTLTYPE_NODE }, \
+	{ "datasize", CTLTYPE_NODE }, \
+	{ "stacksize", CTLTYPE_NODE }, \
+	{ "coredumpsize", CTLTYPE_NODE }, \
+	{ "memoryuse", CTLTYPE_NODE }, \
+	{ "memorylocked", CTLTYPE_NODE }, \
+	{ "maxproc", CTLTYPE_NODE }, \
+	{ "descriptors", CTLTYPE_NODE }, \
+}
+/* for each type, either hard or soft value */
+#define PROC_PID_LIMIT_TYPE_SOFT	1
+#define PROC_PID_LIMIT_TYPE_HARD	2
+#define PROC_PID_LIMIT_TYPE_MAXID	3
+
+#define PROC_PID_LIMIT_TYPE_NAMES { \
+	{0, 0}, \
+	{ "soft", CTLTYPE_QUAD }, \
+	{ "hard", CTLTYPE_QUAD }, \
+}
+
 #ifdef	_KERNEL
 /*
  * CTL_DEBUG variables.
@@ -394,12 +451,14 @@
 
 int sysctl_int __P((void *, size_t *, void *, size_t, int *));
 int sysctl_rdint __P((void *, size_t *, void *, int));
+int sysctl_quad __P((void *, size_t *, void *, size_t, quad_t *));
+int sysctl_rdquad __P((void *, size_t *, void *, quad_t));
 int sysctl_string __P((void *, size_t *, void *, size_t, char *, int));
 int sysctl_rdstring __P((void *, size_t *, void *, char *));
 int sysctl_rdstruct __P((void *, size_t *, void *, void *, int));
 int sysctl_struct __P((void *, size_t *, void *, size_t, void *, int));
 int sysctl_file __P((char *, size_t *));
-int sysctl_doproc __P((int *, u_int, char *, size_t *));
+int sysctl_doeproc __P((int *, u_int, char *, size_t *));
 struct radix_node;
 struct walkarg;
 int sysctl_dumpentry __P((struct radix_node *, void *));
@@ -421,6 +480,8 @@
 		     struct proc *));
 int hw_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
 		   struct proc *));
+int proc_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
+		     struct proc *));
 #ifdef DEBUG
 int debug_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
 		      struct proc *));
Index: usr.sbin/sysctl/sysctl.8
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/sysctl/sysctl.8,v
retrieving revision 1.30
diff -u -r1.30 sysctl.8
--- sysctl.8	1999/07/02 08:58:22	1.30
+++ sysctl.8	1999/09/21 15:18:05
@@ -86,6 +86,13 @@
 flag must be specified and the MIB name followed
 by an equal sign and the new value to be used.
 .Pp
+The proc top-level MIB has a special semantic: it represent per-process values
+and as such may differ from one process to another. The second-level name
+is the pid of the process (in decimal form), or the special word 'curproc'.
+For variables below 'proc.<pid>.rlimit', the integer value may be remplaced
+with the string 'unlimited' if it matches the magic value used to disable
+a limit.
+.Pp
 The information available from
 .Nm sysctl
 consists of integers, strings, and tables.
@@ -137,7 +144,7 @@
 .It kern.sysvmsg	integer	no
 .It kern.sysvsem	integer	no
 .It kern.sysvshm	integer	no
-.It kern.shortcorename	integer	yes
+.It kern.defcorename	string	yes
 .It kern.synchronized_io	integer	no
 .It kern.iov_max	integer	no
 .It kern.mbuf.msize	integer	no
@@ -281,6 +288,23 @@
 .It ddb.tabstops	integer		yes
 .It ddb.lines	integer		yes
 .It ddb.onpanic	integer		yes
+.It proc.<pid>.corename	string	yes
+.It proc.<pid>.rlimit.cputime.soft	integer	yes
+.It proc.<pid>.rlimit.cputime.hard	integer	yes
+.It proc.<pid>.rlimit.filesize.soft	integer	yes
+.It proc.<pid>.rlimit.filesize.hard	integer	yes
+.It proc.<pid>.rlimit.datasize.soft	integer	yes
+.It proc.<pid>.rlimit.datasize.hard	integer	yes
+.It proc.<pid>.rlimit.stacksize.soft	integer	yes
+.It proc.<pid>.rlimit.stacksize.hard	integer	yes
+.It proc.<pid>.rlimit.coredumpsize.soft	integer	yes
+.It proc.<pid>.rlimit.coredumpsize.hard	integer	yes
+.It proc.<pid>.rlimit.memoryuse.soft	integer	yes
+.It proc.<pid>.rlimit.memoryuse.hard	integer	yes
+.It proc.<pid>.rlimit.memorylocked.soft	integer	yes
+.It proc.<pid>.rlimit.memorylocked.hard	integer	yes
+.It proc.<pid>.rlimit.maxproc.soft	integer	yes
+.It proc.<pid>.rlimit.maxproc.hard	integer	yes
 .El
 .Sh EXAMPLES
 .Pp
@@ -305,6 +329,26 @@
 .Bd -literal -offset indent -compact
 sysctl vm.loadavg
 .Ed
+.Pp
+To view the values of the per-process variables of the current shell,
+the request:
+.Bd -literal -offset indent -compact
+sysctl proc.$$
+.Ed
+can be used if the shell interpreter remplaces $$ with it's pid (this is true
+for most shells).
+.Pp
+To redirect core dumps to the /var/tmp/<username> directory,
+.Bd -literal -offset indent -compact
+sysctl -w proc.$$.corename=/var/tmp/%u/%n.core
+.Ed
+Shall be used.
+.Bd -literal -offset indent -compact
+sysctl -w proc.curproc.corename=/var/tmp/%u/%n.core
+.Ed
+changes the value for the sysctl process itself, and will not have the desired
+effect.
+
 .Sh FILES
 .Bl -tag -width <netinet/icmpXvar.h> -compact
 .It Pa <sys/sysctl.h>
Index: usr.sbin/sysctl/sysctl.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/sysctl/sysctl.c,v
retrieving revision 1.21
diff -u -r1.21 sysctl.c
--- sysctl.c	1999/07/30 10:29:35	1.21
+++ sysctl.c	1999/09/21 15:18:05
@@ -55,6 +55,7 @@
 #include <sys/socket.h>
 #include <sys/mount.h>
 #include <sys/mbuf.h>
+#include <sys/resource.h>
 #include <vm/vm_param.h>
 #include <machine/cpu.h>
 
@@ -119,6 +120,9 @@
 #ifdef CTL_MACHDEP_NAMES
 struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
 #endif
+/* this one is dummy, it's used only for '-a' or '-A' */
+struct ctlname procname[] = { {0, 0}, {"curproc", CTLTYPE_NODE} };
+
 char names[BUFSIZ];
 
 struct list {
@@ -141,6 +145,7 @@
 #endif
 	{ username, USER_MAXID },	/* CTL_USER_NAMES */
 	{ ddbname, DDBCTL_MAXID },	/* CTL_DDB_NAMES */
+	{ procname, 2 },		/* dummy name */
 };
 
 int	Aflag, aflag, nflag, wflag;
@@ -152,6 +157,11 @@
 #define	BOOTTIME	0x00000002
 #define	CONSDEV		0x00000004
 
+/*
+ * A dummy type for limits, which requires special parsing
+ */
+#define CTLTYPE_LIMIT	((~0x1) << 31)
+
 int main __P((int, char *[]));
 
 static void listall __P((char *, struct list *));
@@ -167,6 +177,7 @@
 static int sysctl_vfs __P((char *, char **, int[], int, int *));
 static int sysctl_vfsgen __P((char *, char **, int[], int, int *));
 static int sysctl_mbuf __P((char *, char **, int[], int, int *));
+static int sysctl_proc __P((char *, char **, int[], int, int *));
 static int findname __P((char *, char *, char **, struct list *));
 static void usage __P((void));
 
@@ -279,21 +290,26 @@
 	mib[0] = indx;
 	if (indx == CTL_DEBUG)
 		debuginit();
-	lp = &secondlevel[indx];
-	if (lp->list == 0) {
-		warnx("Class `%s' is not implemented",
-		    topname[indx].ctl_name);
-		return;
-	}
-	if (bufp == NULL) {
-		listall(topname[indx].ctl_name, lp);
-		return;
+	if (mib[0] == CTL_PROC) {
+		type = CTLTYPE_NODE;
+		len = 1;
+	} else {
+		lp = &secondlevel[indx];
+		if (lp->list == 0) {
+			warnx("Class `%s' is not implemented",
+		    	topname[indx].ctl_name);
+			return;
+		}
+		if (bufp == NULL) {
+			listall(topname[indx].ctl_name, lp);
+			return;
+		}
+		if ((indx = findname(string, "second", &bufp, lp)) == -1)
+			return;
+		mib[1] = indx;
+		type = lp->list[indx].ctl_type;
+		len = 2;
 	}
-	if ((indx = findname(string, "second", &bufp, lp)) == -1)
-		return;
-	mib[1] = indx;
-	type = lp->list[indx].ctl_type;
-	len = 2;
 	switch (mib[0]) {
 
 	case CTL_KERN:
@@ -423,7 +439,11 @@
 	case CTL_USER:
 	case CTL_DDB:
 		break;
-
+	case CTL_PROC:
+		len = sysctl_proc(string, &bufp, mib, flags, &type);
+		if (len < 0)
+			return;
+		break;
 	default:
 		warnx("Illegal top level value: %d", mib[0]);
 		return;
@@ -441,6 +461,14 @@
 			newsize = sizeof intval;
 			break;
 
+		case CTLTYPE_LIMIT:
+			if (strcmp(newval, "unlimited") == 0) {
+				quadval = RLIM_INFINITY;
+				newval = &quadval;
+				newsize = sizeof quadval;
+				break;
+			}
+			/* FALLTHROUGH */
 		case CTLTYPE_QUAD:
 			sscanf(newval, "%qd", (long long *)&quadval);
 			newval = &quadval;
@@ -526,6 +554,30 @@
 		}
 		return;
 
+	case CTLTYPE_LIMIT:
+#define PRINTF_LIMIT(lim) { \
+if ((lim) == RLIM_INFINITY) \
+	fprintf(stdout, "unlimited");\
+else \
+	fprintf(stdout, "%qd", (lim)); \
+}
+
+		if (newsize == 0) {
+			if (!nflag)
+				fprintf(stdout, "%s = ", string);
+			PRINTF_LIMIT((long long)(*(quad_t *)buf));
+		} else {
+			if (!nflag) {
+				fprintf(stdout, "%s: ", string);
+				PRINTF_LIMIT((long long)(*(quad_t *)buf));
+				fprintf(stdout, " -> ");
+			}
+			PRINTF_LIMIT((long long)(*(quad_t *)newval));
+		}
+		fprintf(stdout, "\n");
+		return;
+#undef PRINTF_LIMIT
+
 	case CTLTYPE_QUAD:
 		if (newsize == 0) {
 			if (!nflag)
@@ -897,9 +949,85 @@
 	return (3);
 }
 
+struct ctlname procnames[] = PROC_PID_NAMES;
+struct list procvars = {procnames, PROC_PID_MAXID};
+struct ctlname proclimitnames[] = PROC_PID_LIMIT_NAMES;
+struct list proclimitvars = {proclimitnames, PROC_PID_LIMIT_MAXID};
+struct ctlname proclimittypenames[] = PROC_PID_LIMIT_TYPE_NAMES;
+struct list proclimittypevars = {proclimittypenames,
+    PROC_PID_LIMIT_TYPE_MAXID};
+/*
+ * handle kern.proc requests
+ */
+static int
+sysctl_proc(string, bufpp, mib, flags, typep)
+	char *string;
+	char **bufpp;
+	int mib[];
+	int flags;
+	int *typep;
+{
+	char *cp, name[BUFSIZ];
+	struct list *lp;
+	int indx;
+
+	if (*bufpp == NULL) {
+		strcpy(name, string);
+		cp = &name[strlen(name)];
+		*cp++ = '.';
+		strcpy(cp, "curproc");
+		parse (name, Aflag);
+		return (-1);
+	}
+	cp = strsep(bufpp, ".");
+	if (cp == NULL) {
+		warnx("%s: incomplete specification", string);
+		return (-1);
+	}
+	if (strcmp(cp, "curproc") == 0) {
+		mib[1] = PROC_CURPROC;
+	} else {
+		mib[1] = atoi(cp);
+		if (mib[1] == 0) {
+			warnx("second level name %s in %s is invalid", cp,
+			    string);
+			return (-1);
+		}
+	}
+	*typep = CTLTYPE_NODE;
+	lp = &procvars;
+	if (*bufpp == NULL) {
+		listall(string, lp);
+		return (-1);
+	}
+	if ((indx = findname(string, "third", bufpp, lp)) == -1)
+		return (-1);
+	mib[2] = indx;
+	*typep = lp->list[indx].ctl_type;
+	if (*typep != CTLTYPE_NODE)
+		return(3);
+	lp = &proclimitvars;
+	if (*bufpp == NULL) {
+		listall(string, lp);
+		return (-1);
+	}
+	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
+		return (-1);
+	mib[3] = indx;
+	lp = &proclimittypevars;
+	if (*bufpp == NULL) {
+		listall(string, lp);
+		return (-1);
+	}
+	if ((indx = findname(string, "fifth", bufpp, lp)) == -1)
+		return (-1);
+	mib[4] = indx;
+	*typep = CTLTYPE_LIMIT;
+	return(5);
+}
+
 struct ctlname mbufnames[] = CTL_MBUF_NAMES;
 struct list mbufvars = { mbufnames, MBUF_MAXID };
-
 /*
  * handle kern.mbuf requests
  */

--RnlQjJ0d97Da+TV1--