[PATCH] s3: Add headers for sysctlbyname() and rewrite get_freebsd_corepath()

Timur I. Bakeyev timur at FreeBSD.org
Mon Jul 20 20:52:46 MDT 2009


In lib/fault.c and param/loadparm.c there are functions that use
sysctlbyname() which is defined in sys/sysctl.h. So, this header HAS to
be included. I do add it localy to the affected files, but maybe
includes.h would be better idea.

To guess core file name and location on FreeBSD a kernel tunable is
consulted. It can use expandable variables %N, %P and %U to reflect name
of the program, it's PID and UID. So, if we want to use that kernel
tunable, we have to do expansion ourselves.
---
 source3/configure.in     |    2 +-
 source3/lib/fault.c      |  126 +++++++++++++++++++++++++++++++---------------
 source3/param/loadparm.c |    4 ++
 3 files changed, 90 insertions(+), 42 deletions(-)

diff --git a/source3/configure.in b/source3/configure.in
index 7cfd3fb..c2faa41 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -655,7 +655,7 @@ AC_CHECK_HEADERS(aio.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h
 AC_CHECK_HEADERS(unistd.h grp.h sys/id.h memory.h alloca.h)
 AC_CHECK_HEADERS(limits.h float.h pthread.h libintl.h)
 AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
-AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
+AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h sys/sysctl.h)
 AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h)
 AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
 AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h)
diff --git a/source3/lib/fault.c b/source3/lib/fault.c
index 51fc53b..7e969e0 100644
--- a/source3/lib/fault.c
+++ b/source3/lib/fault.c
@@ -20,6 +20,10 @@
 
 #include "includes.h"
 
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
 #ifdef HAVE_SYS_PRCTL_H
 #include <sys/prctl.h>
 #endif
@@ -138,52 +142,93 @@ static char *get_default_corepath(const char *logbase, const char *progname)
  * before dump_core() calls abort.
  */
 #if (defined(FREEBSD) && defined(HAVE_SYSCTLBYNAME))
-static char *get_freebsd_corepath(void)
+/*
+ * 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".
+ */
+static char *get_freebsd_corepath(const char *name)
 {
-	char *tmp_corepath = NULL;
-	char *end = NULL;
-	size_t len = 128;
+	TALLOC_CTX *tmp_ctx;
+	char format[MAXPATHLEN];
+	char *freebsd_corepath = NULL, *buffer = NULL;
+	char *start, *end;
+	size_t len;
 	int ret;
 
-	/* Loop with increasing sizes so we don't allocate too much. */
-	do {
-		if (len > 1024)  {
-			goto err_out;
-		}
-
-		tmp_corepath = (char *)talloc_realloc(NULL, tmp_corepath,
-						      char, len);
-		if (!tmp_corepath) {
-			return NULL;
-		}
-
-		ret = sysctlbyname("kern.corefile", tmp_corepath, &len, NULL,
-				   0);
-		if (ret == -1) {
-			if (errno != ENOMEM) {
-				DEBUG(0, ("sysctlbyname failed getting "
-					  "kern.corefile %s\n",
-					  strerror(errno)));
-				goto err_out;
-			}
-
-			/* Not a large enough array, try a bigger one. */
-			len = len << 1;
-		}
-	} while (ret == -1);
-
+	len = sizeof(format);
+	/* Read format string */
+	if((ret = sysctlbyname("kern.corefile", format, &len, NULL, 0)) == -1) {
+		return NULL;
+	}
 	/* Strip off the common filename expansion */
-	if ((end = strrchr_m(tmp_corepath, '/'))) {
+	if ((end=strrchr_m(format, '/')) != NULL) {
 		*end = '\0';
 	}
+	/* Core file is relative to the cwd */
+	if(!format[0] || format[0] != '/') {
+		return NULL;
+	}
 
-	return tmp_corepath;
-
- err_out:
-	if (tmp_corepath) {
-		talloc_free(tmp_corepath);
+	if((tmp_ctx = talloc_new(NULL)) == NULL) {
+		DEBUG(0, ("talloc_new failed\n"));
+		return NULL;
 	}
-	return NULL;
+	if((buffer = talloc_strdup(tmp_ctx, "")) == NULL) {
+		DEBUG(0, ("talloc_strdup: Out of memory!\n"));
+		goto failed;
+	}
+	/* Parse format string and expand variables */
+	start = format;
+	while((end=strchr_m(start, '%')) != NULL) {
+		/* Copy part of the string without format arguments */
+		if(end != start) {
+			buffer = talloc_strndup_append_buffer(buffer, start, end - start);
+			if(buffer == NULL) {
+				DEBUG(0, ("talloc_strdup: Out of memory!\n"));
+				goto failed;
+			}
+		}
+		start = end + 1;
+		switch (*start) {
+			case '%':
+				buffer = talloc_strdup_append_buffer(buffer, "%%");
+				break;
+			case 'N':	/* process name */
+				buffer = talloc_asprintf_append_buffer(buffer, "%s", name);
+				break;
+			case 'P':	/* process id */
+				buffer = talloc_asprintf_append_buffer(buffer, "%u", getpid());
+				break;
+			case 'U':	/* user id */
+				buffer = talloc_asprintf_append_buffer(buffer, "%u", getuid());
+				break;
+			default:
+				DEBUG(0,(
+				    "Unknown format character %c in "
+				    "corename `%s'\n", *start, format));
+		}
+		if(buffer == NULL) {
+			DEBUG(0, ("talloc_asprintf_append_buffer: Out of memory!\n"));
+			goto failed;
+		}
+		start++;
+	}
+	/* Copy remaining part, if any */
+	if((buffer = talloc_strdup_append_buffer(buffer, start)) == NULL) {
+		DEBUG(0, ("talloc_strdup_append_buffer: Out of memory!\n"));
+		goto failed;
+	}
+	/* Duplicate assembled string in the unattached contenxt */
+	freebsd_corepath = talloc_strdup(NULL, buffer);
+failed:
+	TALLOC_FREE(tmp_ctx);
+
+	return freebsd_corepath;
 }
 #endif
 
@@ -199,8 +244,7 @@ static char *get_corepath(const char *logbase, const char *progname)
 	/* @todo: Add support for the linux corepath. */
 
 	char *tmp_corepath = NULL;
-	tmp_corepath = get_freebsd_corepath();
-
+	tmp_corepath = get_freebsd_corepath(progname);
 	/* If this has been set correctly, we're done. */
 	if (tmp_corepath) {
 		return tmp_corepath;
@@ -276,7 +320,7 @@ void dump_core_setup(const char *progname)
 	SAFE_FREE(logbase);
 }
 
- void dump_core(void)
+void dump_core(void)
 {
 	static bool called;
 
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index dbbd6e3..e3de084 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -58,6 +58,10 @@
 #include <cups/http.h>
 #endif
 
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
 bool bLoaded = False;
 
 extern enum protocol_types Protocol;
-- 
1.6.3.1


--jRHKVT23PllUwdXP--


More information about the samba-technical mailing list