summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/Makefile2
-rw-r--r--include/fmtmsg.h72
-rw-r--r--lib/libc/gen/Makefile.inc4
-rw-r--r--lib/libc/gen/err.31
-rw-r--r--lib/libc/gen/fmtmsg.3256
-rw-r--r--lib/libc/gen/fmtmsg.c214
6 files changed, 546 insertions, 3 deletions
diff --git a/include/Makefile b/include/Makefile
index 1591211..ae4247f 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -10,7 +10,7 @@ CLEANFILES= osreldate.h version vers.c
SUBDIR= arpa protocols rpcsvc rpc
INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \
dirent.h \
- dlfcn.h elf.h elf-hints.h err.h fnmatch.h fstab.h \
+ dlfcn.h elf.h elf-hints.h err.h fnmatch.h fmtmsg.h fstab.h \
fts.h glob.h grp.h \
hesiod.h histedit.h ieeefp.h ifaddrs.h inttypes.h iso646.h kenv.h \
langinfo.h \
diff --git a/include/fmtmsg.h b/include/fmtmsg.h
new file mode 100644
index 0000000..0de69c2
--- /dev/null
+++ b/include/fmtmsg.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FMTMSG_H_
+#define _FMTMSG_H_
+
+/* Source of condition is... */
+#define MM_HARD 0x0001 /* hardware. */
+#define MM_SOFT 0x0002 /* software. */
+#define MM_FIRM 0x0004 /* fireware. */
+
+/* Condition detected by... */
+#define MM_APPL 0x0010 /* application. */
+#define MM_UTIL 0x0020 /* utility. */
+#define MM_OPSYS 0x0040 /* operating system. */
+
+/* Display on... */
+#define MM_PRINT 0x0100 /* standard error. */
+#define MM_CONSOLE 0x0200 /* system console. */
+
+#define MM_RECOVER 0x1000 /* Recoverable error. */
+#define MM_NRECOV 0x2000 /* Non-recoverable error. */
+
+/* Severity levels. */
+#define MM_NOSEV 0 /* No severity level provided. */
+#define MM_HALT 1 /* Error causing application to halt. */
+#define MM_ERROR 2 /* Non-fault fault. */
+#define MM_WARNING 3 /* Unusual non-error condition. */
+#define MM_INFO 4 /* Informative message. */
+
+/* Null options. */
+#define MM_NULLLBL (char *)0
+#define MM_NULLSEV 0
+#define MM_NULLMC 0L
+#define MM_NULLTXT (char *)0
+#define MM_NULLACT (char *)0
+#define MM_NULLTAG (char *)0
+
+/* Return values. */
+#define MM_OK 0 /* Success. */
+#define MM_NOMSG 1 /* Failed to output to stderr. */
+#define MM_NOCON 2 /* Failed to output to console. */
+#define MM_NOTOK 3 /* Failed to output anything. */
+
+int fmtmsg(long, const char *, int, const char *, const char *, const char *);
+
+#endif /* _FMTMSG_H_ */
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 92a8854..c27ffd1 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -9,7 +9,7 @@ SRCS+= __xuname.c _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c \
- exec.c fmtcheck.c fnmatch.c fstab.c ftok.c fts.c \
+ exec.c fmtcheck.c fmtmsg.c fnmatch.c fstab.c ftok.c fts.c \
getbootfile.c getbsize.c \
getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
@@ -41,7 +41,7 @@ MAN+= alarm.3 arc4random.3 \
basename.3 clock.3 \
confstr.3 ctermid.3 daemon.3 \
devname.3 directory.3 dirname.3 dladdr.3 dllockinit.3 dlopen.3 \
- err.3 exec.3 fmtcheck.3 fnmatch.3 frexp.3 ftok.3 fts.3 \
+ err.3 exec.3 fmtcheck.3 fmtmsg.3 fnmatch.3 frexp.3 ftok.3 fts.3 \
getbootfile.3 getbsize.3 getcap.3 getcwd.3 \
getdiskbyname.3 getdomainname.3 getfsent.3 \
getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
diff --git a/lib/libc/gen/err.3 b/lib/libc/gen/err.3
index b2754f5..753ef15 100644
--- a/lib/libc/gen/err.3
+++ b/lib/libc/gen/err.3
@@ -207,6 +207,7 @@ if (error != 0)
.Ed
.Sh SEE ALSO
.Xr exit 3 ,
+.Xr fmtmsg 3 ,
.Xr printf 3 ,
.Xr strerror 3
.Sh HISTORY
diff --git a/lib/libc/gen/fmtmsg.3 b/lib/libc/gen/fmtmsg.3
new file mode 100644
index 0000000..4b7cbfd
--- /dev/null
+++ b/lib/libc/gen/fmtmsg.3
@@ -0,0 +1,256 @@
+.\"
+.\" Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 5, 2002
+.Dt FMTMSG 3
+.Os
+.Sh NAME
+.Nm fmtmsg
+.Nd display a detailed diagnostic message
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fmtmsg.h
+.Ft int
+.Fn fmtmsg "long classification" "const char *label" "int severity" "const char *text" "const char *action" "const char *tag"
+.Sh DESCRIPTION
+The
+.Fn fmtmsg
+function displays a detailed diagnostic message, based on
+the supplied augments, to
+.Em stderr
+and/or the system console.
+.Pp
+The
+.Fa classification
+argument is the bitwise inclusive
+.Tn OR
+of zero or one of the manifest constants from
+each of the classification groups below.
+The Output classification group is an exception since both
+.Dv MM_PRINT
+and
+.Dv MM_CONSOLE
+may be specified.
+.Pp
+Output
+.Bl -tag -offset indent -width MM_CONSOLE
+.It Dv MM_PRINT
+Output should take place on
+.Em stderr .
+.It Dv MM_CONSOLE
+Output should take place on the system console.
+.El
+.Pp
+Source of Condition (Major)
+.Bl -tag -offset indent -width MM_CONSOLE
+.It Dv MM_HARD
+The source of the condition is hardware related.
+.It Dv MM_SOFT
+The source of the condition is software related.
+.It Dv MM_FIRM
+The source of the condition is firmware related.
+.El
+.Pp
+Source of Condition (Minor)
+.Bl -tag -offset indent -width MM_CONSOLE
+.It Dv MM_APPL
+The condition was detected at the application level.
+.It Dv MM_UTIL
+The condition was detected at the utility level.
+.It Dv MM_OPSYS
+The condition was detected at the operating system level.
+.El
+.Pp
+Status
+.Bl -tag -offset indent -width MM_CONSOLE
+.It Dv MM_RECOVER
+The application can recover from the condition.
+.It Dv MM_NRECOV
+The application is unable to recover from the condition.
+.El
+.Pp
+Alternatively, the
+.Dv MM_NULLMC
+manifest constant may be used to specify no classification.
+.Pp
+The
+.Fa label
+argument indicates the source of the message.
+It is made up of two fields seperated by a colon
+.Pq \&: .
+The first field can be up to 10 bytes,
+and the second field can be up to 14 bytes.
+The
+.Dv MM_NULLLBL
+manifest constant may be used to specify no label.
+.Pp
+The
+.Fa severity
+argument identifies the importance of the condition.
+One of the following manifest constants should be used for this argument.
+.Bl -tag -offset indent -width MM_WARNING
+.It Dv MM_HALT
+The application has confronted a serious fault and is halting.
+.It Dv MM_ERROR
+The application has detected a fault.
+.It Dv MM_WARNING
+The application has detected an unusual condition,
+that could be indicative of a problem.
+.It Dv MM_INFO
+The application is providing information about a non-error condition.
+.It Dv MM_NOSEV
+No severity level supplied.
+.El
+.Pp
+The
+.Fa text
+argument details the error condition that caused the message.
+There is no limit on the size of this character string.
+The
+.Dv MM_NULLTXT
+manifest constant may be used to specify no text.
+.Pp
+The
+.Fa action
+argument details how the error-recovery process should begin.
+Upon output,
+.Fn fmtmsg
+will prefix
+.Qq TO FIX:
+to the begin of the
+.Fa action
+argument.
+The
+.Dv MM_NULLACT
+manifest constant may be used to specify no action.
+.Pp
+The
+.Fa tag
+argument should reference online documentation for the message.
+This usually includes the
+.Fa label
+and a unique identifying number.
+An example tag is
+.Qq BSD:ls:168 .
+The
+.Dv MM_NULLTAG
+manifest constant may be used to specify no tag.
+.Sh RETURN VALUES
+The
+.Fn fmtmsg
+function returns
+.Dv MM_OK
+upon success,
+.Dv MM_NOMSG
+to indicate output to
+.Em stderr
+failed,
+.Dv MM_NOCON
+to indicate output to the system console failed, or
+.Dv MM_NOTOK
+to indicate output to
+.Em stderr
+and the system console failed.
+.Sh ENVIRONMENT
+The
+.Va MSGVERB
+.Pq message verbosity
+environment variable specifies which arguments to
+.Fn fmtmsg
+will be outputted to
+.Em stderr ,
+and in which order.
+.Va MSGVERB
+should be a colon
+.Pq \&:
+seperated list of identifiers.
+Valid identifiers include: label, severity, text, action, and tag.
+If invalid identifiers are specified or incorrectly seperated,
+the default message verbosity and ordering will be used.
+The default ordering is equivalent to a
+.Va MSGVERB
+with a value of
+.Qq label:severity:text:action:tag .
+.Sh EXAMPLES
+The code:
+.Bd -literal -offset indent
+fmtmsg(MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001");
+.Ed
+.Pp
+will output:
+.Bd -literal -offset indent
+BSD:ls: ERROR: illegal option -- z
+TO FIX: refer to manual BSD:ls:001
+.Ed
+.Pp
+to
+.Em stderr .
+.Pp
+The same code, with
+.Va MSGVERB
+set to
+.Qq "text:severity:action:tag" ,
+produces:
+.Bd -literal -offset indent
+illegal option -- z: ERROR
+TO FIX: refer to manual BSD:ls:001
+.Ed
+.Sh SEE ALSO
+.Xr err 3 ,
+.Xr exit 3 ,
+.Xr strerror 3
+.Sh STANDARDS
+The
+.Fn fmtmsg
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn fmtmsg
+function first appeared in
+.Fx 5.0 .
+.Sh BUGS
+Specifying
+.Dv MM_NULLMC
+for the
+.Fa classification
+argument makes little sense, since without an output specified,
+.Fn fmtmsg
+is unable to do anything useful.
+.Pp
+In order for
+.Fn fmtmsg
+to output to the system console, the effective
+user must have appropriate permission to write to
+.Pa /dev/console .
+This means that on most systems
+.Fn fmtmsg
+will return
+.Dv MM_NOCON
+unless the effective user is root.
diff --git a/lib/libc/gen/fmtmsg.c b/lib/libc/gen/fmtmsg.c
new file mode 100644
index 0000000..121a898
--- /dev/null
+++ b/lib/libc/gen/fmtmsg.c
@@ -0,0 +1,214 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fmtmsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Default value for MSGVERB. */
+#define DFLT_MSGVERB "label:severity:text:action:tag"
+
+/* Maximum valid size for a MSGVERB. */
+#define MAX_MSGVERB sizeof(DFLT_MSGVERB)
+
+static char *printfmt(char *, long, const char *, int, const char *,
+ const char *, const char *);
+static char *nextcomp(const char *);
+static const char
+ *sevinfo(int);
+static int validmsgverb(const char *);
+
+static const char *validlist[] = {
+ "label", "severity", "text", "action", "tag", NULL
+};
+
+int
+fmtmsg(long class, const char *label, int sev, const char *text,
+ const char *action, const char *tag)
+{
+ FILE *fp;
+ char *env, *msgverb, *output;
+
+ if (class & MM_PRINT) {
+ if ((env = getenv("MSGVERB")) != NULL && *env != '\0' &&
+ strlen(env) <= strlen(DFLT_MSGVERB)) {
+ if ((msgverb = strdup(env)) == NULL)
+ return (MM_NOTOK);
+ else if (validmsgverb(msgverb) == 0)
+ goto def;
+ } else {
+def:
+ if ((msgverb = strdup(DFLT_MSGVERB)) == NULL)
+ return (MM_NOTOK);
+ }
+ output = printfmt(msgverb, class, label, sev, text, action,
+ tag);
+ if (output == NULL)
+ return (MM_NOTOK);
+ if (*output != '\0')
+ fprintf(stderr, "%s", output);
+ free(msgverb);
+ free(output);
+ }
+ if (class & MM_CONSOLE) {
+ output = printfmt(DFLT_MSGVERB, class, label, sev, text,
+ action, tag);
+ if (output == NULL)
+ return (MM_NOCON);
+ if (*output != '\0') {
+ if ((fp = fopen("/dev/console", "a")) == NULL) {
+ free(output);
+ return (MM_NOCON);
+ }
+ fprintf(fp, "%s", output);
+ fclose(fp);
+ }
+ free(output);
+ }
+ return (MM_OK);
+}
+
+#define INSERT_COLON \
+ if (*output != '\0') \
+ strlcat(output, ": ", size)
+#define INSERT_NEWLINE \
+ if (*output != '\0') \
+ strlcat(output, "\n", size)
+#define INSERT_SPACE \
+ if (*output != '\0') \
+ strlcat(output, " ", size)
+
+/*
+ * Returns NULL on memory allocation failure, otherwise returns a pointer to
+ * a newly malloc()'d output buffer.
+ */
+static char *
+printfmt(char *msgverb, long class, const char *label, int sev,
+ const char *text, const char *act, const char *tag)
+{
+ size_t size;
+ char *comp, *output;
+ const char *sevname;
+
+ size = 32;
+ if (label != MM_NULLLBL)
+ size += strlen(label);
+ if ((sevname = sevinfo(sev)) != NULL)
+ size += strlen(sevname);
+ if (text != MM_NULLTXT)
+ size += strlen(text);
+ if (text != MM_NULLACT)
+ size += strlen(act);
+ if (tag != MM_NULLTAG)
+ size += strlen(tag);
+
+ if ((output = malloc(size)) == NULL)
+ return (NULL);
+ *output = '\0';
+ while ((comp = nextcomp(msgverb)) != NULL) {
+ if (strcmp(comp, "label") == 0 && label != MM_NULLLBL) {
+ INSERT_COLON;
+ strlcat(output, label, size);
+ } else if (strcmp(comp, "severity") == 0 && sevname != NULL) {
+ INSERT_COLON;
+ strlcat(output, sevinfo(sev), size);
+ } else if (strcmp(comp, "text") == 0 && text != MM_NULLTXT) {
+ INSERT_COLON;
+ strlcat(output, text, size);
+ } else if (strcmp(comp, "action") == 0 && act != MM_NULLACT) {
+ INSERT_NEWLINE;
+ strlcat(output, "TO FIX: ", size);
+ strlcat(output, act, size);
+ } else if (strcmp(comp, "tag") == 0 && tag != MM_NULLTAG) {
+ INSERT_SPACE;
+ strlcat(output, tag, size);
+ }
+ }
+ INSERT_NEWLINE;
+ return (output);
+}
+
+static char *
+nextcomp(const char *msgverb)
+{
+ static char lmsgverb[MAX_MSGVERB], *state;
+ char *retval;
+
+ if (*lmsgverb == '\0') {
+ strlcpy(lmsgverb, msgverb, sizeof(lmsgverb));
+ retval = strtok_r(lmsgverb, ":", &state);
+ } else {
+ retval = strtok_r(NULL, ":", &state);
+ }
+ if (retval == NULL)
+ *lmsgverb = '\0';
+ return (retval);
+}
+
+static const char *
+sevinfo(int sev)
+{
+
+ switch (sev) {
+ case MM_HALT:
+ return ("HALT");
+ case MM_ERROR:
+ return ("ERROR");
+ case MM_WARNING:
+ return ("WARNING");
+ case MM_INFO:
+ return ("INFO");
+ default:
+ return (NULL);
+ }
+}
+
+/*
+ * Returns 1 if the msgverb list is valid, otherwise 0.
+ */
+static int
+validmsgverb(const char *msgverb)
+{
+ char *msgcomp;
+ const char *validcomp;
+
+ while ((msgcomp = nextcomp(msgverb)) != NULL) {
+ if (*msgcomp == '\0')
+ return (0);
+ for (validcomp = *validlist;
+ validcomp != NULL; validcomp++) {
+ if (strcmp(msgcomp, validcomp) == 0)
+ break;
+ }
+ if (validcomp == NULL)
+ return (0);
+ }
+ return (1);
+}
OpenPOWER on IntegriCloud