diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_sig.c | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index da79328..147717e 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 - * $Id: kern_sig.c,v 1.41 1998/06/07 17:11:35 dfr Exp $ + * $Id: kern_sig.c,v 1.42 1998/06/28 08:37:45 dg Exp $ */ #include "opt_compat.h" @@ -61,6 +61,7 @@ #include <sys/stat.h> #include <sys/sysent.h> #include <sys/sysctl.h> +#include <sys/malloc.h> #include <machine/cpu.h> #ifdef SMP @@ -79,6 +80,7 @@ static int coredump __P((struct proc *p)); static int killpg1 __P((struct proc *cp, int signum, int pgid, int all)); static void setsigvec __P((struct proc *p, int signum, struct sigaction *sa)); static void stop __P((struct proc *)); +static char *expand_name __P((const char*, int, int)); /* * Can process p, with pcred pc, send the signal signum to process q? @@ -1246,6 +1248,88 @@ sigexit(p, signum) /* NOTREACHED */ } +static char corefilename[MAXPATHLEN+1] = {"%N.core"}; +SYSCTL_STRING(_kern, OID_AUTO, corefile, CTLFLAG_RW, corefilename, + sizeof(corefilename), "process corefile name format string"); + +/* + * expand_name(name, uid, pid) + * Expand the name described in corefilename, using name, uid, and pid. + * corefilename is a printf-like string, with three format specifiers: + * %N name of process ("name") + * %P process id (pid) + * %U user id (uid) + * For example, "%N.core" is the default; they can be disabled completely + * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". + * This is controlled by the sysctl variable kern.corefile (see above). + */ + +static char * +expand_name(name, uid, pid) +const char *name; int uid; int pid; { + char *temp; + char buf[11]; /* Buffer for pid/uid -- max 4B */ + int i, n; + char *format = corefilename; + + temp = malloc(MAXPATHLEN + 3, M_TEMP, M_NOWAIT); + bzero(temp, MAXPATHLEN+3); + for (i = 0, n = 0; i < MAXPATHLEN && format[i]; i++) { + int l; + switch (format[i]) { + case '%': /* Format character */ + i++; + switch (format[i]) { + case '%': + temp[n++] = '%'; + break; + case 'N': /* process name */ + l = strlen(name); + if ((n + l) > MAXPATHLEN) { + log(LOG_ERR, "pid %d (%s), uid (%d): Path `%s%s' is too long\n", + pid, name, uid, temp, name); + free(temp, M_TEMP); + return NULL; + } + memcpy(temp+n, name, l); + n += l; + break; + case 'P': /* process id */ + sprintf(buf, "%u", pid); + l = strlen(buf); + if ((n + l) > MAXPATHLEN) { + log(LOG_ERR, "pid %d (%s), uid (%d): Path `%s%s' is too long\n", + pid, name, uid, temp, name); + free(temp, M_TEMP); + return NULL; + } + memcpy(temp+n, buf, l); + n += l; + break; + case 'U': /* user id */ + sprintf(buf, "%u", uid); + l = strlen(buf); + if ((n + l) > MAXPATHLEN) { + log(LOG_ERR, "pid %d (%s), uid (%d): Path `%s%s' is too long\n", + pid, name, uid, temp, name); + free(temp, M_TEMP); + return NULL; + } + memcpy(temp+n, buf, l); + n += l; + break; + default: + log(LOG_ERR, "Unknown format character %c in `%s'\n", format[i], format); + } + break; + default: + temp[n++] = format[i]; + } + } + return temp; +} + + /* * Dump core, into a file named "progname.core", unless the process was * setuid/setgid. @@ -1260,7 +1344,7 @@ coredump(p) struct nameidata nd; struct vattr vattr; int error, error1; - char name[MAXCOMLEN+6]; /* progname.core */ + char *name; /* name of corefile */ STOPEVENT(p, S_CORE, 0); @@ -1269,10 +1353,14 @@ coredump(p) if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= p->p_rlimit[RLIMIT_CORE].rlim_cur) return (EFAULT); - sprintf(name, "%s.core", p->p_comm); + name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid); + if (name == NULL) + return (EFAULT); /* XXX -- not the best error */ + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); - if ((error = vn_open(&nd, - O_CREAT | FWRITE, S_IRUSR | S_IWUSR))) + error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR); + free(name, M_TEMP); + if (error) return (error); vp = nd.ni_vp; |