Subject: core file name format: diffs
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 09/20/1999 14:43:06
--lrZ03NoBR/3+SXJZ
Content-Type: text/plain; charset=us-ascii

Hi,
so I've got the core name format stuff ready to commit (I hope :).
For this I had to introduce generalise struct plimit to 'per process
attributes'. These attributes are inherited at process creation, and can
be reset on some conditions (like exec of a set-id binary).
To manipulate these attributes I created a new sysctl hierarchy, CTL_PROC.
The second level name is the PID of the target process, or a magic value
for 'curproc'. Then we have a tree of sysctl nodes and variables for the
attributes.
A process can access another's process (read/write) based on almost the
same permissions as signals: the process doing the sysctl call is root, or
has to have the same uid as the target process (both effective and saved), and
have the target's process effective group id in it's group list. Especially
this prevent a user from changing the attributes of a suid/sgid process.
For now there are 2 attributes implemented: corename (the corename format)
and rlimit (the resources limits, as defined in the getrlimit/setrlimit
syscalls).

The default value for the corename format can be controlled by
kern.defcorename (kern.shortcorename is gone). The default value
is '%n.core' and can be changed either with sysctl or by a kernel
config option "DEFCORENAME".
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'.
There's no restrictions on the default corename format, I assume someone
changing this know what he's doing :)
4 formats are implemented: %n (process's name), %u (login name), %p (pid) and
%t (start time). A combinaison of %p and %t can be used to get a unique name
for each core dump.

More details on the implementation:
- attributes are hold in 'struct plimit' (maybe its name should be changed now)
  A new field have been added: char *pl_corename; which points to the
  corename format (either points to the default corename string, or is a
  malloced area).
- a new function, p_sugid(), is called at places where the P_SUGID flag would
  have been set. It's intended to take all action needed when a set-id binary
  is loaded (currently: sets P_SUGID and reset pl_corename to the default
  value).
- dosetrlimit() takes an additionnal 'struct  pcred*' argument, as the
  proc changing the limit may not be the one owning the limit.
- sysctl(8) has been changed to handle the new top-level domain.
  If no pid has been specified ('sysctl -a', or 'sysctl proc'), 'curproc' is
  used for the second-level name. Also the magic keyword 'unlimited' can be
  used in place of the magic integer value used for 'infinity' in rlimit.

Initially I though about rewrinting getrlimit()/setrlimit() as wrappers around
sysctl(), but this will add bloat to libc, and the syscalls can't go
completely because of the emulations.

Example of use:
antifer:/comptes2/bouyer>sysctl proc
proc.curproc.corename = %n.core
proc.curproc.rlimit.cputime.soft = unlimited
proc.curproc.rlimit.cputime.hard = unlimited
proc.curproc.rlimit.filesize.soft = unlimited
proc.curproc.rlimit.filesize.hard = unlimited
proc.curproc.rlimit.datasize.soft = 134217728
proc.curproc.rlimit.datasize.hard = 1073741824
proc.curproc.rlimit.stacksize.soft = 2097152
proc.curproc.rlimit.stacksize.hard = 33554432
proc.curproc.rlimit.coredumpsize.soft = unlimited
proc.curproc.rlimit.coredumpsize.hard = unlimited
proc.curproc.rlimit.memoryuse.soft = 63344640
proc.curproc.rlimit.memoryuse.hard = 63348736
proc.curproc.rlimit.memorylocked.soft = 21116245
proc.curproc.rlimit.memorylocked.hard = 63348736
proc.curproc.rlimit.maxproc.soft = 80
proc.curproc.rlimit.maxproc.hard = 532
proc.curproc.rlimit.descriptors.soft = 64
proc.curproc.rlimit.descriptors.hard = 1772
(curproc points to the sysctl process here, not to the shell process !!)

antifer:/comptes2/bouyer>sysctl proc.$$
proc.353.corename = %n.core
proc.353.rlimit.cputime.soft = unlimited
proc.353.rlimit.cputime.hard = unlimited
proc.353.rlimit.filesize.soft = unlimited
proc.353.rlimit.filesize.hard = unlimited
proc.353.rlimit.datasize.soft = 134217728
proc.353.rlimit.datasize.hard = 1073741824
proc.353.rlimit.stacksize.soft = 2097152
proc.353.rlimit.stacksize.hard = 33554432
proc.353.rlimit.coredumpsize.soft = unlimited
proc.353.rlimit.coredumpsize.hard = unlimited
proc.353.rlimit.memoryuse.soft = 63344640
proc.353.rlimit.memoryuse.hard = 63348736
proc.353.rlimit.memorylocked.soft = 21116245
proc.353.rlimit.memorylocked.hard = 63348736
proc.353.rlimit.maxproc.soft = 80
proc.353.rlimit.maxproc.hard = 532
proc.353.rlimit.descriptors.soft = 64
proc.353.rlimit.descriptors.hard = 1772
(these are really the values for the shell process).

antifer:/comptes2/bouyer>sysctl -w proc.$$.corename=/var/tmp/foo
sysctl: sysctl() for proc.353.corename failed: Invalid argument
antifer:/comptes2/bouyer>sysctl -w proc.$$.corename=/var/tmp/core
proc.353.corename: %n.core -> /var/tmp/core

antifer:/comptes2/bouyer>sysctl -w proc.$$.rlimit.descriptors.soft=20
proc.353.rlimit.descriptors.soft: 64 -> 20
antifer:/comptes2/bouyer>limit
cputime         unlimited
filesize        unlimited
datasize        131072 kbytes
stacksize       2048 kbytes
coredumpsize    unlimited
memoryuse       61860 kbytes
descriptors     20 
memorylocked    20621 kbytes
maxproc         80 

One thing I've found really usefull is that it's now possible to change limits
of other processes. For example, when I've open too many xterms from my fvwm
menu I can:
antifer:/comptes2/bouyer>ps ax | fgrep fvwm
  338 ??  S      0:00.23 fvwm 
  736 p1  D+     0:00.01 fgrep fvwm 
antifer:/comptes2/bouyer>sysctl -w proc.338.rlimit.maxproc.soft=200
proc.338.rlimit.maxproc.soft: 80 -> 200

More attributes could probably go under proc.<pid>, now that the machinery
is in place it's easy to add.

I noone object I'll commit this before the end of the week.
Comments, anyone ?

--
Manuel Bouyer, LIP6, Universite Paris VI.           Manuel.Bouyer@lip6.fr
--

--lrZ03NoBR/3+SXJZ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sysctl.diff"

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/20 11:35:51
@@ -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
+.It Li t	The process's creation date
+.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,76 @@
 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.
+.El
+.Pp
+
 .Sh CTL_USER
 The string and integer information available for the CTL_USER level
 is detailed below.
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/20 11:36:10
@@ -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/20 11:36:27
@@ -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/20 11:36:32
@@ -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/20 11:36:32
@@ -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/20 11:36:33
@@ -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/20 11:36:34
@@ -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/20 11:36:35
@@ -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/20 11:36:35
@@ -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/20 11:36:35
@@ -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/20 11:36:35
@@ -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/20 11:36:36
@@ -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,67 @@
 
 	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 != '%') {
+			*d = *s;
+			d++;
+			len++;
+			if (len >= MAXPATHLEN - 1)
+				return ENAMETOOLONG;
+			continue;
+		}
+		if (*(s+1) == 'n') { /* %n */
+			i = snprintf(d,MAXPATHLEN - 1 - len, "%s",
+			    curproc->p_comm);
+			if (i >= MAXPATHLEN - 1 - len)
+				return ENAMETOOLONG;
+			len += i;
+			d += i;
+			s++;
+			continue;
+		}
+		if (*(s+1) == 'p') { /* %p */
+			i = snprintf(d, MAXPATHLEN - 1 - len, "%d",
+			    curproc->p_pid);
+			if (i >= MAXPATHLEN - 1 - len)
+				return ENAMETOOLONG;
+			len += i;
+			d += i;
+			s++;
+			continue;
+		}
+		if (*(s+1) == 'u') { /* %u */
+			i = snprintf(d, MAXPATHLEN - 1 - len, "%s",
+			    curproc->p_pgrp->pg_session->s_login);
+			if (i >= MAXPATHLEN - 1 - len)
+				return ENAMETOOLONG;
+			len += i;
+			d += i;
+			s++;
+			continue;
+		}
+		if (*(s+1) == 't') { /* %t */
+			i = snprintf(d, MAXPATHLEN - 1 - len, "%ld",
+			    curproc->p_stats->p_start.tv_sec);
+			if (i >= MAXPATHLEN - 1 - len)
+				return ENAMETOOLONG;
+			len += i;
+			d += i;
+			s++;
+			continue;
+		}
+		*d = *s;
+	}
+	*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/20 11:36:42
@@ -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,137 @@
 }
 #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;
+				/* don't allow '.core' as a valid file name */
+				if (tmps[len - 1] == '.' &&
+				    (len < 2 || tmps[len - 2] == '/'))
+					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 +689,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 +899,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/20 11:36:44
@@ -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/20 11:36:44
@@ -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/20 11:36:45
@@ -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/20 11:36:45
@@ -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/20 11:37:06
@@ -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/20 11:37:06
@@ -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, "5th", 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
  */

--lrZ03NoBR/3+SXJZ--