summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authorjb <jb@FreeBSD.org>2008-04-26 04:18:35 +0000
committerjb <jb@FreeBSD.org>2008-04-26 04:18:35 +0000
commit37e61e49bf4269676ebfdd8c7164620c8f19659d (patch)
tree369b2f0809efcd28d7ceabd52ce4c70615983809 /cddl
parent105579b1e61ea9ef331da56233092c96f78ea94d (diff)
downloadFreeBSD-src-37e61e49bf4269676ebfdd8c7164620c8f19659d.zip
FreeBSD-src-37e61e49bf4269676ebfdd8c7164620c8f19659d.tar.gz
freopen() on FreeBSD behaves differently to the Solaris one.
Diffstat (limited to 'cddl')
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
index 953511b..209b10a 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
@@ -26,10 +26,17 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#if defined(sun)
#include <sys/sysmacros.h>
+#else
+#define ABS(a) ((a) < 0 ? -(a) : (a))
+#endif
+#include <string.h>
#include <strings.h>
#include <stdlib.h>
+#if defined(sun)
#include <alloca.h>
+#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
@@ -299,9 +306,11 @@ pfprint_fp(dtrace_hdl_t *dtp, FILE *fp, const char *format,
case sizeof (double):
return (dt_printf(dtp, fp, format,
*((double *)addr) / n));
+#if !defined(__arm__) && !defined(__powerpc__)
case sizeof (long double):
return (dt_printf(dtp, fp, format,
*((long double *)addr) / ldn));
+#endif
default:
return (dt_set_errno(dtp, EDT_DMISMATCH));
}
@@ -454,7 +463,11 @@ pfprint_time(dtrace_hdl_t *dtp, FILE *fp, const char *format,
* Below, we turn this into the canonical adb/mdb /[yY] format,
* "1973 Dec 3 17:20:00".
*/
+#if defined(sun)
(void) ctime_r(&sec, src, sizeof (src));
+#else
+ (void) ctime_r(&sec, src);
+#endif
/*
* Place the 4-digit year at the head of the string...
@@ -1553,6 +1566,7 @@ dtrace_freopen(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
if (rval == -1 || fp == NULL)
return (rval);
+#if defined(sun)
if (pfd->pfd_preflen != 0 &&
strcmp(pfd->pfd_prefix, DT_FREOPEN_RESTORE) == 0) {
/*
@@ -1597,7 +1611,8 @@ dtrace_freopen(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
* fails, we can fail the operation without destroying stdout.
*/
if ((nfp = fopen(filename, "aF")) == NULL) {
- char *msg = strerror(errno), *faultstr;
+ char *msg = strerror(errno);
+ char *faultstr;
int len = 80;
len += strlen(msg) + strlen(filename);
@@ -1633,6 +1648,82 @@ dtrace_freopen(dtrace_hdl_t *dtp, FILE *fp, void *fmtdata,
}
(void) fclose(nfp);
+#else
+ /*
+ * The 'standard output' (which is not necessarily stdout)
+ * treatment on FreeBSD is implemented differently than on
+ * Solaris because FreeBSD's freopen() will attempt to re-use
+ * the current file descriptor, causing the previous file to
+ * be closed and thereby preventing it from be re-activated
+ * later.
+ *
+ * For FreeBSD we use the concept of setting an output file
+ * pointer in the DTrace handle if a dtrace_freopen() has
+ * enabled another output file and we leave the caller's
+ * file pointer untouched. If it was actually stdout, then
+ * stdout remains open. If it was another file, then that
+ * file remains open. While a dtrace_freopen() has activated
+ * another file, we keep a pointer to that which we use in
+ * the output functions by preference and only use the caller's
+ * file pointer if no dtrace_freopen() call has been made.
+ *
+ * The check to see if we're re-activating the caller's
+ * output file is much the same as on Solaris.
+ */
+ if (pfd->pfd_preflen != 0 &&
+ strcmp(pfd->pfd_prefix, DT_FREOPEN_RESTORE) == 0) {
+ /*
+ * The only way to have the format string set to the value
+ * DT_FREOPEN_RESTORE is via the empty freopen() string --
+ * denoting that we should restore the old stdout.
+ */
+ assert(strcmp(dtp->dt_sprintf_buf, DT_FREOPEN_RESTORE) == 0);
+
+ if (dtp->dt_freopen_fp == NULL) {
+ /*
+ * We could complain here by generating an error,
+ * but it seems like overkill: it seems that calling
+ * freopen() to restore stdout when freopen() has
+ * never before been called should just be a no-op,
+ * so we just return in this case.
+ */
+ return (rval);
+ }
+
+ /*
+ * At this point, to re-active the original output file,
+ * on FreeBSD we only code the current file that this
+ * function opened previously.
+ */
+ (void) fclose(dtp->dt_freopen_fp);
+ dtp->dt_freopen_fp = NULL;
+
+ return (rval);
+ }
+
+ if ((nfp = fopen(dtp->dt_sprintf_buf, "a")) == NULL) {
+ char *msg = strerror(errno);
+ char *faultstr;
+ int len = 80;
+
+ len += strlen(msg) + strlen(dtp->dt_sprintf_buf);
+ faultstr = alloca(len);
+
+ (void) snprintf(faultstr, len, "couldn't freopen() \"%s\": %s",
+ dtp->dt_sprintf_buf, strerror(errno));
+
+ if ((errval = dt_handle_liberr(dtp, data, faultstr)) == 0)
+ return (rval);
+
+ return (errval);
+ }
+
+ if (dtp->dt_freopen_fp != NULL)
+ (void) fclose(dtp->dt_freopen_fp);
+
+ /* Remember that the output has been redirected to the new file. */
+ dtp->dt_freopen_fp = nfp;
+#endif
return (rval);
}
OpenPOWER on IntegriCloud