Subject: Re: core file name format: diffs
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 09/22/1999 18:23:12
--bp/iNruPH9dso1Pn
Content-Type: text/plain; charset=us-ascii


Hi,
here is a new diff file, which include suggestions from der Mouse and fixes
for the problems he pointed out, and:
- honnor PL_SHAREMOD in p_sugid
- don't call limcopy() if no data change
- proc_sysctl(): always copyin(), don't use newp directly
- add support to /etc/rc, /etc/rc.conf and document it
- move description of the core file name format to core(5) and xref it from
  other places
- a few more man pages update (shells, ...)

I all goes well my plan is to commit this friday.

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

--bp/iNruPH9dso1Pn
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sysctl.diff3"

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/22 15:11:13
@@ -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/22 15:11:23
@@ -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: etc/rc
===================================================================
RCS file: /cvsroot/basesrc/etc/rc,v
retrieving revision 1.131
diff -u -r1.131 rc
--- rc	1999/09/16 11:00:44	1.131
+++ rc	1999/09/22 15:11:24
@@ -316,6 +316,12 @@
 	. /etc/rc.lkm
 fi
 
+# if $defcorename is set, change it here.
+if [ -n "$defcorename" ]; then
+	echo -n 'setting default core name template: '
+	sysctl -w kern.defcorename=$defcorename
+fi
+
 # if $securelevel is set, change it here, else if it is 0, change
 # it to 1 here, before we start login services.
 if [ -n "$securelevel" ]; then
Index: etc/rc.conf
===================================================================
RCS file: /cvsroot/basesrc/etc/rc.conf,v
retrieving revision 1.57
diff -u -r1.57 rc.conf
--- rc.conf	1999/09/03 13:40:16	1.57
+++ rc.conf	1999/09/22 15:11:24
@@ -41,6 +41,11 @@
 update_motd=YES					# updates /etc/motd
 dmesg=YES		dmesg_flags=""		# write /var/run/dmesg.boot
 
+# default core name template. If $defcorename is non-empty, this value will be  
+# used for core dumps names for programs that didn't get their per-process
+# template set (see sysctl(3) and sysctl(8)).
+defcorename=""      
+
 # Security setting.  If $securelevel is non-empty, the system securelevel
 # is set to this value early in the boot sequence.  Otherwise the default
 # action is taken (see init(8)).
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/22 15:11:56
@@ -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,17 @@
 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 dump files (see also PROC_PID_CORENAME
+in the per-process variables CTL_PROC, and
+.Xr core 5
+for format of this template).  The default value is
+.Nm %n.core
+and can be changed with the kernel configuration option
+.Cd options DEFCORENAME
+(see 
+.Xr options 4
+).
 .It Li KERN_DOMAINNAME
 Get or set the YP domain name.
 .It Li KERN_FILE
@@ -466,17 +478,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 +718,79 @@
 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 used for the core dump file name (see
+.Xr core 5
+for details). The base name must either be 
+.Nm core
+or end with the suffix ``.core'' (the super-user may set arbitrary names). By
+default it points to KERN_DEFCORENAME.
+.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/22 15:11:57
@@ -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/22 15:12:00
@@ -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/man4/options.4
===================================================================
RCS file: /cvsroot/sharesrc/share/man/man4/options.4,v
retrieving revision 1.86
diff -u -r1.86 options.4
--- options.4	1999/08/05 15:47:07	1.86
+++ options.4	1999/09/22 15:12:15
@@ -837,18 +837,16 @@
 .Em CHILD_MAX
 is not permitted, as this would result in a violation of the semantics of
 .St -p1003.1-90 .
-.It Cd options SHORTCORENAME
-If set, process core dumps are named 
-.Nm core .
-If not specified, they are named
-.Nm programname.core 
-(the default in 4.4BSD). Note that this changes the value of the 
-.Em kern.shortcorename 
-sysctl variable which may be changed at run time. See
+.It Cd options DEFCORENAME=string
+Sets the default value of the
+.Em kern.defcorename
+sysctl variable, otherwise it is set to
+.Nm %n.core .
+See
 .Xr sysctl 8
 and
 .Xr sysctl 3
-for details. 
+for details.
 .El
 .Ss Networking Options
 .Bl -ohang
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/22 15:12:15
@@ -47,33 +47,49 @@
 to disk for later examination by one of the available debuggers.
 (See
 .Xr sigaction 2 . )
-This memory image is written to a file 
-in the working directory;
-provided the terminated process had write permission in the directory,
-and provided the abnormality did not cause
-a system crash.
+This memory image is written to a file named from a per-process template;
+provided the terminated process had write permission, and provided the
+abnormality did not cause a system crash.
 (In this event, the decision to save the core file is arbitrary, see
 .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.
+The file is named from a per-process template, mapped to the sysctl
+variable
+.Em proc.<pid>.corename
+(where <pid> has to be remplaced by the pid in decimal format of the
+process).
+This template is either an absolute or relative path name, in which format
+characters can be used, preceeded by the percent character (``%''). 
+The following characters are recognised as format and subsitued:
+.Bl -column "cAA" "The process's creation date (in seconds)xxx" -offset indent
+.It Li n        The process's name
+.It Li p        The PID of the process (in decimal) 
+.It Li t        The process's creation date (a la
+.Xr time 3 ,
+in decimal)
+.It Li u        The login name, as returned by
+.Xr getlogin 2
+.El
+.Pp
+By default, the per-process template string points to the default core name
+template, which is mapped to the sysctl variable
+.Em kern.defcorename .
+Changing this value on a live system will change the core name template for
+all processes which didn't have a per-process template set.
+The default value of the default core name template is
+.Nm %n.core
+and can be changed at compile-time with the kernel configuration option
+.Cd options DEFCORENAME
+(see
+.Xr options 4 )
+.Pp
+The per-process template string is inherited on process creation, but is reset
+to point to the default core name template on execution of a set-id binary.
 .Pp
-The maximum size of a
-.Nm programname.core
-file is limited by
+The maximum size of a core file is limited by
 .Xr setrlimit 2 .
 Files which would be larger than the limit are not created.
 .Pp
-The
-.Nm programname.core
-file consists of the
+The core file consists of the
 .Fa u. area ,
 whose size (in pages) is defined by the
 .Dv UPAGES
@@ -85,13 +101,9 @@
 .Fa user
 structure as given in
 .Aq Pa sys/user.h .
-The remainder of the
-.Nm programname.core
-file consists of the data pages followed by
+The remainder of the core file consists of the data pages followed by
 the stack pages of the process image.
-The amount of data space image in the
-.Nm programname.core
-file is given (in pages) by the
+The amount of data space image in the core file is given (in pages) by the
 variable
 .Fa u_dsize
 in the
@@ -109,6 +121,8 @@
 .Xr gdb 1 ,
 .Xr sigaction 2 ,
 .Xr setrlimit 2
+.Xr sysctl 3 ,
+.Xr sysctl 8
 .Sh HISTORY
 A
 .Nm core
Index: share/man/man5/rc.conf.5
===================================================================
RCS file: /cvsroot/sharesrc/share/man/man5/rc.conf.5,v
retrieving revision 1.25
diff -u -r1.25 rc.conf.5
--- rc.conf.5	1999/09/03 14:36:43	1.25
+++ rc.conf.5	1999/09/22 15:12:16
@@ -170,6 +170,17 @@
 file to reflect the version of the running kernel.
 See
 .Xr motd 5 .
+.It Sy defcorename
+A string.
+This sets the default core name template, from which are derived core dump
+files names. The template can include format charaters which are dynamically
+interpreted. See
+.Xr core 5
+for details of the format.
+If set to nothing, the default compiled-in value is keept (see
+.Xr options 4 ,
+.Xr sysctl 3
+).
 .El
 .Pp
 .Ss System security setting:
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/22 15:12:29
@@ -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/22 15:12:30
@@ -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/22 15:12:31
@@ -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/22 15:12:31
@@ -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/22 15:12:32
@@ -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/22 15:12:32
@@ -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/22 15:12:32
@@ -519,6 +519,28 @@
 	}
 }
 
+/* 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_lflags & PL_SHAREMOD) == 0) {
+			p->p_limit->p_refcnt--;
+			p->p_limit = limcopy(p->p_limit);
+		} else {
+			free(p->p_limit->pl_corename, M_TEMP);
+		}
+		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/22 15:12:33
@@ -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/22 15:12:33
@@ -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;
 {
@@ -245,9 +246,14 @@
 		return (EINVAL);
 
 	alimp = &p->p_rlimit[which];
+	/* if we don't change the value, no need to limcopy() */
+	if (limp->rlim_cur == alimp->rlim_cur &&
+	    limp->rlim_max == alimp->rlim_max)
+		return 0;
+
 	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;
@@ -454,10 +460,18 @@
 	struct plimit *lim;
 {
 	register struct plimit *newlim;
+	extern char *defcorename;
 
 	newlim = pool_get(&plimit_pool, PR_WAITOK);
 	memcpy(newlim->pl_rlimit, lim->pl_rlimit,
 	    sizeof(struct rlimit) * RLIM_NLIMITS);
+	if (lim->pl_corename == defcorename) {
+		newlim->pl_corename = lim->pl_corename;
+	} else {
+		newlim->pl_corename = malloc(strlen(lim->pl_corename)+1,
+		    M_TEMP, M_WAITOK);
+		strcpy(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/22 15:12:34
@@ -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/22 15:12:34
@@ -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,150 @@
 }
 #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 = NULL;
+	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) {
+			if (securelevel > 2)
+				return EPERM;
+			if (newlen > MAXPATHLEN)
+				return ENAMETOOLONG;
+			tmps = malloc(newlen + 1, M_TEMP, M_WAITOK);
+			if (tmps == NULL)
+				return ENOMEM;
+			error = copyin(newp, tmps, newlen + 1);
+			tmps[newlen] = '\0';
+			if (error)
+				goto cleanup;
+			/* Enforce to be either 'core' for end with '.core' */
+			if (newlen < 4)  { /* c.o.r.e */
+				error = EINVAL;
+				goto cleanup;
+			}
+			len = newlen - 4;
+			if (len > 0) {
+				if (tmps[len - 1] != '.' &&
+				    tmps[len - 1] != '/') {
+					error = EINVAL;
+					goto cleanup;
+				}
+			}
+			if (strcmp(&tmps[len], "core") != 0) {
+				error = EINVAL;
+				goto cleanup;
+			}
+		}
+		if (oldp) {
+			*oldlenp = curlen;
+			error = copyout(ptmp->p_limit->pl_corename, oldp,
+			    curlen);
+		}
+		if (newp && error == 0) {
+			/* if the 2 strings are identical, don't limcopy() */
+			if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) {
+				error = 0;
+				goto cleanup;
+			}
+			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 = tmps;
+			return (0);
+		}
+cleanup:
+		if (tmps)
+			free(tmps, M_TEMP);
+		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 +702,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 +912,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/22 15:12:54
@@ -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/22 15:12:54
@@ -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/22 15:12:54
@@ -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/22 15:12:55
@@ -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/22 15:13:03
@@ -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/22 15:13:04
@@ -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
  */

--bp/iNruPH9dso1Pn--