Implement POSIX.1-2001 (XSI)'s fmtmsg(3).
This commit is contained in:
parent
c679b309f1
commit
823f68a28a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=101353
@ -10,7 +10,7 @@ CLEANFILES= osreldate.h version vers.c
|
|||||||
SUBDIR= arpa protocols rpcsvc rpc
|
SUBDIR= arpa protocols rpcsvc rpc
|
||||||
INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \
|
INCS= a.out.h ar.h assert.h bitstring.h complex.h cpio.h ctype.h db.h \
|
||||||
dirent.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 \
|
fts.h glob.h grp.h \
|
||||||
hesiod.h histedit.h ieeefp.h ifaddrs.h inttypes.h iso646.h kenv.h \
|
hesiod.h histedit.h ieeefp.h ifaddrs.h inttypes.h iso646.h kenv.h \
|
||||||
langinfo.h \
|
langinfo.h \
|
||||||
|
72
include/fmtmsg.h
Normal file
72
include/fmtmsg.h
Normal file
@ -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_ */
|
@ -9,7 +9,7 @@ SRCS+= __xuname.c _pthread_stubs.c _rand48.c _spinlock_stub.c _thread_init.c \
|
|||||||
clock.c closedir.c confstr.c \
|
clock.c closedir.c confstr.c \
|
||||||
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.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 \
|
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 \
|
getbootfile.c getbsize.c \
|
||||||
getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
|
getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
|
||||||
gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
|
gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
|
||||||
@ -41,7 +41,7 @@ MAN+= alarm.3 arc4random.3 \
|
|||||||
basename.3 clock.3 \
|
basename.3 clock.3 \
|
||||||
confstr.3 ctermid.3 daemon.3 \
|
confstr.3 ctermid.3 daemon.3 \
|
||||||
devname.3 directory.3 dirname.3 dladdr.3 dllockinit.3 dlopen.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 \
|
getbootfile.3 getbsize.3 getcap.3 getcwd.3 \
|
||||||
getdiskbyname.3 getdomainname.3 getfsent.3 \
|
getdiskbyname.3 getdomainname.3 getfsent.3 \
|
||||||
getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
|
getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
|
||||||
|
@ -207,6 +207,7 @@ if (error != 0)
|
|||||||
.Ed
|
.Ed
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr exit 3 ,
|
.Xr exit 3 ,
|
||||||
|
.Xr fmtmsg 3 ,
|
||||||
.Xr printf 3 ,
|
.Xr printf 3 ,
|
||||||
.Xr strerror 3
|
.Xr strerror 3
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
|
256
lib/libc/gen/fmtmsg.3
Normal file
256
lib/libc/gen/fmtmsg.3
Normal file
@ -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.
|
214
lib/libc/gen/fmtmsg.c
Normal file
214
lib/libc/gen/fmtmsg.c
Normal file
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user