4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
35 * fmtmsg() Writes a message in standard format.
36 * addseverity() Adds a severity definition to the list of known
37 * severity definitions.
40 * - None of these functions can use strtok().
44 * Header Files Referenced:
45 * <stdio.h> C Standard I/O Definitions
46 * <string.h> C string handling definitions
47 * <fcntl.h> UNIX file control definitions
48 * <errno.h> UNIX error numbers and definitions
49 * <fmtmsg.h> Global definitions for fmtmsg()
50 * <stdlib.h> miscellaneous function declarations
53 #pragma weak _fmtmsg = fmtmsg
54 #pragma weak _addseverity = addseverity
59 #include <sys/types.h>
72 * External functions referenced:
73 * (Others may be defined in header files above)
75 * getenv Extracts data from the environment
76 * libc_malloc Allocates space from main memory
77 * libc_free Frees space allocated via libc_malloc()
78 * strtol Convert string to "long"
79 * clearerr Clears an error on a stream (this is to make "lint"
85 * Local Constant Definitions
90 * TRUE Boolean value for "true" (any bits on)
91 * FALSE Boolean value for "false" (all bits off)
102 #define MAX_MSG_SIZE 1024
105 * Keywords for fields named in the MSGVERB environment variable.
108 #define ST_LBL "label"
109 #define ST_SEV "severity"
110 #define ST_TXT "text"
112 #define ST_ACT "action"
116 * The following constants define the value of the "msgverb"
117 * variable. This variable tells fmtmsg() which parts of the
118 * standard message it is to display. If !(msgverb&MV_SET),
119 * fmtmsg() will interrogate the "MSGVERB" environment variable
120 * and set "msgverb" accordingly.
122 * NOTE: This means that if MSGVERB changes after the first call
123 * to fmtmsg(), it will be ignored.
126 * MV_INV Check MSGVERB environment variable (invalidates value)
127 * MV_SET MSGVERB checked, msgverb value valid
128 * MV_LBL "label" selected
129 * MV_SEV "severity" selected
130 * MV_TXT "text" selected
131 * MV_TAG "messageID" selected
132 * MV_ACT "action" selected
134 * MV_ALL All components selected
135 * MV_DFLT Default value for MSGVERB
139 #define MV_SET 0x0001
140 #define MV_LBL 0x0002
141 #define MV_SEV 0x0004
142 #define MV_TXT 0x0008
143 #define MV_TAG 0x0010
144 #define MV_ACT 0x0020
146 #define MV_ALL (MV_LBL|MV_SEV|MV_TXT|MV_TAG|MV_ACT)
147 #define MV_DFLT (MV_LBL|MV_SEV|MV_TXT|MV_TAG|MV_ACT)
152 * Strings defining the different severities of a message.
153 * Internationalization may demand that these come from the message database
156 #define SV_UNK "UNKNOWN"
157 #define SV_HALT "HALT"
158 #define SV_ERROR "ERROR"
159 #define SV_WARN "WARNING"
160 #define SV_INF "INFO"
164 * Text string if none is provided:
167 #define DEFLT_TEXT "No text provided with this message"
171 * Text string introduction for "action". This may have to come from
172 * the message database because of internationalization.
175 #define ACTINTRO "TO FIX: "
180 * SEPSTR is the string that separates the "label" from what follows it,
181 * and the severity from what follows it.
189 * Miscellaneous constants:
190 * CONNAME Filesystem entry name for the system console
193 #define CONNAME "/dev/console"
196 * Local data type definitions
200 * Severity string structure
203 * sevvalue Value of the severity-level being defined
204 * sevkywd Keyword identifying the severity
205 * sevprptr Pointer to the string associated with the value
206 * sevnext Pointer to the next value in the list.
209 * sevvalue Must be a non-negative integer (>=0)
211 * There are three (possibly null) lists of these structures.
212 * 1) is the list of standard severities
213 * 2) is the list of severity-levels defined by SEV_LEVEL
214 * 3) is the list of severity-levels defined by calls to
221 const char *sevprstr
;
222 struct sevstr
*sevnext
;
228 * Contains the internal representation or the
229 * MSGVERB environment variable.
230 * sevlook TRUE if fmtmsg() has to look at SEV_LEVEL the
231 * next time it is called.
232 * paugsevs struct sevstr *
233 * Head of the linked list of structures that define
234 * severities that augment the standard severities,
235 * as defined by addseverity().
236 * penvsevs struct sevstrs *
237 * Head of the linked list of structures that define
238 * severities that augment the standard severities,
239 * as defined by SEV_LEVEL.
240 * pstdsevs struct sevstrs *
241 * Head of the linked list of structures that define
242 * the standard severities.
245 static mutex_t fmt_lock
= DEFAULTMUTEX
;
247 static int msgverb
= 0;
248 static int sevlook
= TRUE
;
250 static struct sevstr
*paugsevs
= NULL
;
251 static struct sevstr
*penvsevs
= NULL
;
253 static struct sevstr sevstrs
[] = {
254 { MM_HALT
, "", SV_HALT
, &sevstrs
[1]},
255 { MM_ERROR
, "", SV_ERROR
, &sevstrs
[2]},
256 { MM_WARNING
, "", SV_WARN
, &sevstrs
[3]},
257 { MM_INFO
, "", SV_INF
, NULL
},
259 static struct sevstr
*pstdsevs
= &sevstrs
[0];
262 * static char *exttok(str, delims)
266 * This function examines the string pointed to by "str", looking
267 * for the first occurrence of any of the characters in the string
268 * whose address is "delims". It returns the address of that
269 * character or NULL if there was nothing to search.
272 * str Address of the string to search
273 * delims Address of the string containing delimiters
276 * Returns the address of the first occurrence of any of the characters
277 * in "delim" in the string "str" (incl '\0'). If there was nothing
278 * to search, the function returns NULL.
281 * - This function is needed because strtok() can't be used inside a
282 * function. Besides, strtok() is destructive in the string, which
283 * is undesirable in many circumstances.
284 * - This function understands escaped delimiters as non-delimiters.
285 * Delimiters are escaped by preceding them with '\' characters.
286 * The '\' character also must be escaped.
290 exttok(const char *tok
, const char *delims
)
292 char *tokend
; /* Ptr to the end of the token */
293 char *p
, *q
; /* Temp pointers */
297 * 1. Get the starting address(new string or where we
298 * left off). If nothing to search, returnNULL
299 * 2. Find the end of the string
300 * 3. Look for the first unescaped delimiter closest to the
301 * beginning of the string
302 * 4. Remember where we left off
303 * 5. Return a pointer to the delimiter we found
306 /* Begin at the beginning, if any */
311 /* Find end of the token string */
312 tokend
= (char *)tok
+ (ptrdiff_t)strlen(tok
);
314 /* Look for the 1st occurrence of any delimiter */
315 for (p
= (char *)delims
; *p
!= '\0'; p
++) {
316 for (q
= strchr(tok
, (int)*p
);
317 (q
!= 0) && (q
!= tok
) && (*(q
- (ptrdiff_t)1) == '\\');
318 q
= strchr(q
+ (ptrdiff_t)1, (int)*p
))
320 if ((q
!= 0) && (q
< tokend
))
331 * This function squeezes out all of the escaped character sequences
332 * from the string <str>. It returns a pointer to that string.
336 * The string that is to have its escaped characters removed.
339 * This function returns its argument <str> always.
342 * This function potentially modifies the string it is given.
348 char *p
; /* Temp string pointer */
349 char *q
; /* Temp string pointer */
351 /* Look for an escaped character */
353 while (*p
&& (*p
!= '\\')) p
++;
357 * If there was at least one, squeeze them out
358 * Otherwise, don't touch the argument string
363 while (*q
++ = *p
++) {
369 /* Finished. Return our argument */
374 * struct sevstr *getauxsevs(ptr)
376 * Parses a string that is in the format of the severity definitions.
377 * Returns a pointer to a (malloc'd) structure that contains the
378 * definition, or NULL if none was parsed.
382 * References the string from which data is to be extracted.
383 * If NULL, continue where we left off. Otherwise,
384 * start with the string referenced by ptr.
386 * Returns: struct sevstr *
387 * A pointer to a malloc'd structure containing the severity definition
388 * parsed from string, or NULL if none.
391 * - This function is destructive to the string referenced by its argument.
395 static char *leftoff
= NULL
;
397 static struct sevstr
*
398 getauxsevs(char *ptr
)
400 char *current
; /* Ptr to current sev def'n */
401 char *tokend
; /* Ptr to end of current sev def'n */
402 char *kywd
; /* Ptr to extracted kywd */
403 char *valstr
; /* Ptr to extracted sev value */
404 char *prstr
; /* Ptr to extracted print str */
405 char *p
; /* Temp pointer */
406 int val
; /* Converted severity value */
407 int done
; /* Flag, sev def'n found and ok? */
408 struct sevstr
*rtnval
; /* Value to return */
411 /* Start anew or start where we left off? */
412 current
= (ptr
== NULL
) ? leftoff
: ptr
;
415 /* If nothing to parse, return NULL */
416 if (current
== NULL
) {
422 * Look through the string "current" for a token of the form
423 * <kywd>,<sev>,<printstring> delimited by ':' or '\0'
426 /* Loop initializations */
430 /* Eat leading junk */
431 while (*(tokend
= exttok(current
, ":,")) == ':') {
432 current
= tokend
+ (ptrdiff_t)1;
435 /* If we've found a <kywd>,... */
436 if (*tokend
== ',') {
440 /* Look for <kywd>,<sev>,... */
441 current
= tokend
+ (ptrdiff_t)1;
442 if (*(tokend
= exttok(current
, ":,")) == ',') {
446 current
= tokend
+ (ptrdiff_t)1;
449 /* Make sure <sev> > 4 */
450 val
= (int)strtol(noesc(valstr
), &p
, 0);
451 if ((val
> 4) && (p
== tokend
)) {
454 * Found <kywd>,<sev>,<printstring>.
455 * remember where we left off
459 exttok(current
, ":")) == ':') {
468 * Alloc structure to contain
469 * severity definition
471 rtnval
= libc_malloc(
472 sizeof (struct sevstr
));
473 if (rtnval
!= NULL
) {
475 /* Fill in structure */
476 rtnval
->sevkywd
= noesc(kywd
);
477 rtnval
->sevvalue
= val
;
478 rtnval
->sevprstr
= noesc(prstr
);
485 * Invalid severity value,
486 * eat thru end of token
489 if (*(tokend
= exttok(prstr
, ":")) ==
496 * Invalid severity definition,
497 * eat thru end of token
504 /* End of string found */
508 } /* while (!done) */
517 * Parces the argument of the MSGVERB environment variable and places
518 * a representation of the value of that value in "msgverb"
531 char *opts
; /* Pointer to MSGVERB's value */
532 char *alloced
; /* Pointer to MSGVERB's value */
533 char *tok
; /* Pointer to current token */
534 char *tokend
; /* Pointer to end of current token */
535 char *nexttok
; /* Pointer to next token */
538 /* Rid ourselves of junk in "msgverb" */
541 /* Get the value of MSGVERB. If none, use default value */
542 if ((opts
= getenv(MSGVERB
)) == NULL
) {
544 } else { /* MSGVERB has a value. Interpret it */
545 if ((alloced
= libc_malloc(strlen(opts
) + 1)) == NULL
) {
548 /* Make a copy of the value of MSGVERB */
549 nexttok
= strcpy(alloced
, opts
);
551 /* Parse the options given by the user */
552 while ((tok
= nexttok
) != NULL
) {
554 * Find end of the next token and squeeze
555 * out escaped characters
557 tokend
= exttok(tok
, ":");
560 /* Delimit token and mark next, if any */
561 if (*tokend
== ':') {
562 nexttok
= tokend
+ (ptrdiff_t)1;
568 /* Check for "text" */
569 if (strcmp(tok
, ST_TXT
) == 0) {
572 /* Check for "label" */
573 } else if (strcmp(tok
, ST_LBL
) == 0) {
576 /* Check for "action */
577 } else if (strcmp(tok
, ST_ACT
) == 0) {
580 /* Check for "severity" */
581 } else if (strcmp(tok
, ST_SEV
) == 0) {
584 /* Check for "tag" */
585 } else if (strcmp(tok
, ST_TAG
) == 0) {
588 /* Unknown, ignore MSGVERB value */
596 * Use default if no keywords on MSGVERB
597 * environment variable
602 /* Free allocated space */
613 * This function builds a structure containing auxillary severity
621 static char *sevspace
= NULL
;
626 struct sevstr
*plast
;
631 /* Look for SEV_LEVEL definition */
632 if ((value
= getenv(SEV_LEVEL
)) != NULL
) {
634 /* Allocate space and make a copy of the value of SEV_LEVEL */
635 if ((sevspace
= libc_malloc(strlen(value
) + 1)) != NULL
) {
636 (void) strcpy(sevspace
, value
);
638 /* Continue for all severity descriptions */
639 psev
= getauxsevs(sevspace
);
644 while (psev
= getauxsevs(NULL
)) {
645 plast
->sevnext
= psev
;
649 } /* if sevspace != NULL */
650 } /* if value != NULL */
654 * int addseverity(value, string)
655 * int value Value of the severity
656 * const char *string Print-string for the severity
660 * The integer value of the severity being added
662 * A pointer to the character-string to be printed
663 * whenever a severity of "value" is printed
666 * Zero if successful, -1 if failed. The function can fail under
667 * the following circumstances:
668 * - libc_malloc() fails
669 * - The "value" is one of the reserved values.
671 * This function permits C applications to define severity-levels
672 * that augment the standard levels and those defined by the
673 * SEV_LEVEL environment variable.
677 addseverity(int value
, const char *string
)
679 struct sevstr
*p
; /* Temp ptr to severity structs */
680 struct sevstr
*q
; /* Temp ptr(follower) to severity */
681 int found
; /* FLAG, element found in the list */
682 int rtnval
; /* Value to return to the caller */
684 /* Make sure we're not trying to redefine one of the reserved values */
690 lmutex_lock(&fmt_lock
);
692 /* Make sure we've interpreted SEV_LEVEL */
701 * Leaf through the list. We may be redefining or removing a
706 for (p
= paugsevs
; !found
&& (p
!= NULL
);
708 if (p
->sevvalue
== value
) {
709 /* We've a match. Remove or modify the entry */
710 if (string
== NULL
) {
712 paugsevs
= p
->sevnext
;
714 q
->sevnext
= p
->sevnext
;
718 p
->sevprstr
= string
;
725 /* Adding a definition */
726 if (!found
&& (string
!= NULL
)) {
727 /* Allocate space for the severity structure */
728 if ((p
= libc_malloc(sizeof (struct sevstr
))) == NULL
) {
729 lmutex_unlock(&fmt_lock
);
734 * Fill in the new structure with the data supplied and add to
735 * the head of the augmented severity list.
739 p
->sevprstr
= string
;
741 p
->sevnext
= paugsevs
;
744 /* Successfully added a new severity */
746 } else if (string
== NULL
) {
747 /* Attempting to undefined a non-defined severity */
751 /* Successfully redefined a severity */
754 /* Finished, successful */
755 lmutex_unlock(&fmt_lock
);
760 * Utility function for converting an integer to a string, avoiding stdio.
765 char buf
[12]; /* 32 bits fits in 10 decimal digits */
767 uint_t un
= (n
< 0)? -n
: n
;
770 *cp
++ = "0123456789"[un
% 10];
785 * void writemsg(buf, size, verbosity, label, severity, text, action, tag)
788 * char *buf The buffer in which to format the message
789 * size_t size The size of the buffer
790 * int verbosity A bit-string that indicates which components
792 * const char *label The address of the label-component
793 * int severity The severity value of the message
794 * const char *text The address of the text-component
795 * const char *action The address of the action-component
796 * const char *tag The address of the tag-component
798 * This function formats the message consisting of the label-component,
799 * severity-component, text-component, action-component, and tag-
800 * component into the provided buffer. The "verbosity" argument
801 * tells which components can be selected. Any or all of the
802 * components can be their null-values.
810 writemsg(char *buf
, size_t size
,
811 int verbosity
, const char *label
, int severity
,
812 const char *text
, const char *action
, const char *tag
)
814 struct sevstr
*psev
; /* Ptr for severity str list */
815 char *p
; /* General purpose pointer */
816 char *sevpstr
= NULL
; /* Pointer to severity string */
817 int l1indent
; /* # chars to indent line 1 */
818 int l2indent
; /* # chars to indent line 2 */
819 int textindent
; /* # spaces to indent text */
820 int actindent
= 0; /* # spaces to indent action */
821 int i
; /* General purpose counter */
822 int dolabel
; /* TRUE if label to be written */
823 int dotext
; /* TRUE if text to be written */
824 int dosev
; /* TRUE if severity to be written */
825 int doaction
; /* TRUE if action to be written */
826 int dotag
; /* TRUE if tag to be written */
827 char c
; /* Temp, multiuse character */
828 char sevpstrbuf
[15]; /* Space for SV=%d */
830 char lcllbl
[MM_MXLABELLN
+1]; /* Space for (possibly */
831 /* truncated) label */
832 char lcltag
[MM_MXTAGLN
+1]; /* Space for (possibly */
834 char *ebuf
= buf
+ size
- 2;
837 * initialize variables.
839 sevpstrbuf
[0] = '\0';
844 * Figure out what fields are to be written (all are optional)
847 dolabel
= (verbosity
& MV_LBL
) && (label
!= MM_NULLLBL
);
848 dosev
= (verbosity
& MV_SEV
) && (severity
!= MM_NULLSEV
);
849 dotext
= (verbosity
& MV_TXT
) && (text
!= MM_NULLTXT
);
850 doaction
= (verbosity
& MV_ACT
) && (action
!= MM_NULLACT
);
851 dotag
= (verbosity
& MV_TAG
) && (tag
!= MM_NULLTAG
);
854 * Figure out how much we'll need to indent the text of the message
857 /* Count the label of the message, if requested */
860 (void) strncpy(lcllbl
, label
, (size_t)MM_MXLABELLN
);
861 lcllbl
[MM_MXLABELLN
] = '\0';
862 textindent
= (int)strlen(lcllbl
) + SEPSTRLN
;
866 * If severity req'd, determine the severity string and factor
867 * into indent count. Severity string generated by:
868 * 1. Search the standard list of severities.
869 * 2. Search the severities added by the application.
870 * 3. Search the severities added by the environment.
871 * 4. Use the default (SV=n where n is the value of the severity).
875 /* Search the default severity definitions */
877 while (psev
!= NULL
) {
878 if (psev
->sevvalue
== severity
)
880 psev
= psev
->sevnext
;
885 * Search the severity definitions
886 * added by the application
889 while (psev
!= NULL
) {
890 if (psev
->sevvalue
== severity
)
892 psev
= psev
->sevnext
;
896 * Search the severity definitions
897 * added by the environment
900 while (psev
!= NULL
) {
901 if (psev
->sevvalue
== severity
)
903 psev
= psev
->sevnext
;
906 /* Use default string, SV=severity */
907 (void) strcpy(sevpstrbuf
, "SV=");
908 itoa(severity
, &sevpstrbuf
[3]);
909 sevpstr
= sevpstrbuf
;
911 sevpstr
= (char *)psev
->sevprstr
;
914 sevpstr
= (char *)psev
->sevprstr
;
917 sevpstr
= (char *)psev
->sevprstr
;
919 /* Factor into indent counts */
920 textindent
+= (int)strlen(sevpstr
) + SEPSTRLN
;
924 * Figure out the indents.
927 if (doaction
&& dotext
) {
928 if (textindent
> ACTINTROLN
) {
930 l2indent
= textindent
- ACTINTROLN
;
931 actindent
= textindent
;
934 actindent
= ACTINTROLN
;
935 if (dosev
|| dolabel
) {
936 l1indent
= ACTINTROLN
- textindent
;
937 textindent
= ACTINTROLN
;
947 actindent
= textindent
+ ACTINTROLN
;
957 /* Write the LABEL, if requested */
959 /* Write spaces to align on the ':' char, if needed */
960 while (--l1indent
>= 0 && buf
< ebuf
)
963 /* Write the label */
964 buf
+= strlcpy(buf
, lcllbl
, ebuf
- buf
);
967 * Write the separator string
968 * (if another component is to follow)
970 if (dosev
|| dotext
|| doaction
|| dotag
)
971 buf
+= strlcpy(buf
, SEPSTR
, ebuf
- buf
);
974 /* Write the SEVERITY, if requested */
976 /* Write spaces to align on the ':' char, if needed */
977 while (--l1indent
>= 0 && buf
< ebuf
)
980 /* Write the severity print-string */
981 buf
+= strlcpy(buf
, sevpstr
, ebuf
- buf
);
984 * Write the separator string
985 * (if another component is to follow)
987 if (dotext
|| doaction
|| dotag
)
988 buf
+= strlcpy(buf
, SEPSTR
, ebuf
- buf
);
991 /* Write the TEXT, if requested */
994 for (c
= *p
++; c
!= '\0' && buf
< ebuf
; c
= *p
++) {
997 for (i
= 0; i
< textindent
&& buf
< ebuf
; i
++)
1004 * Write ACTION if requested.
1008 if (dotext
&& buf
< ebuf
) {
1010 while (--l2indent
>= 0 && buf
< ebuf
)
1014 /* Write the action-string's introduction */
1015 buf
+= strlcpy(buf
, ACTINTRO
, ebuf
- buf
);
1017 /* Write the "action" string */
1019 for (c
= *p
++; c
!= '\0' && buf
< ebuf
; c
= *p
++) {
1022 for (i
= 0; i
< actindent
&& buf
< ebuf
; i
++)
1029 * Write the TAG if requested
1034 buf
+= strlcpy(buf
, " ", ebuf
- buf
);
1035 else if (dotext
&& buf
< ebuf
)
1037 (void) strncpy(lcltag
, tag
, (size_t)MM_MXTAGLN
);
1038 lcltag
[MM_MXTAGLN
] = '\0';
1039 buf
+= strlcpy(buf
, lcltag
, ebuf
- buf
);
1043 * Write terminating newline and null byte.
1044 * We reserved space for these at the start.
1051 * int fmtmsg(class, label, severity, text, action, tag)
1056 * const char *action
1059 * If requested, the fmtmsg() function writes a message to the standard
1060 * error stream in the standard message format. Also if requested, it
1061 * will write a message to the system console.
1064 * class Fields which classify the message for the system
1066 * label A character-string that is printed as the "label"
1067 * of the message. Typically identifies the source
1069 * severity Identifies the severity of the message. Either one
1070 * of the standard severities, or possibly one of the
1071 * augmented severities
1072 * text Pointer to the text of the message
1073 * action Pointer to a char string that describes some type
1074 * of corrective action.
1075 * tag A character-string that is printed as the "tag" or
1076 * the message. Typically a pointer to documentation
1079 * -1 if nothing was generated, 0 if everything requested was
1080 * generated, or flags if partially generated.
1083 * - Nothing special for 4.0.
1087 fmtmsg(long class, const char *label
, int severity
,
1088 const char *text
, const char *action
, const char *tag
)
1090 int rtnval
; /* Value to return */
1091 FILE *console
; /* Ptr to "console" stream */
1096 * Determine the "verbosity" of the message. If "msgverb" is
1097 * already set, don't interrogate the "MSGVERB" environment vbl.
1098 * If so, interrogate "MSGVERB" and do initialization stuff also.
1101 lmutex_lock(&fmt_lock
);
1103 if (!(msgverb
& MV_SET
)) {
1110 * Extract the severity definitions from the SEV_LEVEL
1111 * environment variable and save away for later.
1120 /* Set up the default text component [if text==NULL] */
1124 /* Prepare the message for stderr if requested */
1125 if (class & MM_PRINT
) {
1126 message1
= alloca(MAX_MSG_SIZE
);
1127 writemsg(message1
, MAX_MSG_SIZE
,
1128 msgverb
, label
, severity
, text
, action
, tag
);
1131 /* Prepare the message for the console if requested */
1132 if (class & MM_CONSOLE
) {
1133 message2
= alloca(MAX_MSG_SIZE
);
1134 writemsg(message2
, MAX_MSG_SIZE
,
1135 MV_ALL
, label
, severity
, text
, action
, tag
);
1138 lmutex_unlock(&fmt_lock
);
1142 /* Write the message to stderr if requested */
1143 if (class & MM_PRINT
) {
1145 (void) fputs(message1
, stderr
);
1150 /* Write the message to the console if requested */
1151 if (class & MM_CONSOLE
) {
1152 if ((console
= fopen(CONNAME
, "wF")) != NULL
) {
1154 (void) fputs(message2
, console
);
1155 if (ferror(console
))
1157 (void) fclose(console
);
1163 if ((rtnval
& (MM_NOCON
| MM_NOMSG
)) == (MM_NOCON
| MM_NOMSG
))