2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A/* Copyright (c) 1988 AT&T */ 2N/A/* All Rights Reserved */ 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * fmtmsg() Writes a message in standard format. 2N/A * addseverity() Adds a severity definition to the list of known 2N/A * severity definitions. 2N/A * - None of these functions can use strtok(). 2N/A * Header Files Referenced: 2N/A * External functions referenced: 2N/A * (Others may be defined in header files above) 2N/A * getenv Extracts data from the environment 2N/A * libc_malloc Allocates space from main memory 2N/A * libc_free Frees space allocated via libc_malloc() 2N/A * strtol Convert string to "long" 2N/A * clearerr Clears an error on a stream (this is to make "lint" 2N/A * Local Constant Definitions 2N/A * TRUE Boolean value for "true" (any bits on) 2N/A * FALSE Boolean value for "false" (all bits off) 2N/A * Keywords for fields named in the MSGVERB environment variable. 2N/A * The following constants define the value of the "msgverb" 2N/A * variable. This variable tells fmtmsg() which parts of the 2N/A * standard message it is to display. If !(msgverb&MV_SET), 2N/A * fmtmsg() will interrogate the "MSGVERB" environment variable 2N/A * and set "msgverb" accordingly. 2N/A * NOTE: This means that if MSGVERB changes after the first call 2N/A * to fmtmsg(), it will be ignored. 2N/A * MV_INV Check MSGVERB environment variable (invalidates value) 2N/A * MV_SET MSGVERB checked, msgverb value valid 2N/A * MV_LBL "label" selected 2N/A * MV_SEV "severity" selected 2N/A * MV_TXT "text" selected 2N/A * MV_TAG "messageID" selected 2N/A * MV_ACT "action" selected 2N/A * MV_ALL All components selected 2N/A * MV_DFLT Default value for MSGVERB 2N/A * Strings defining the different severities of a message. 2N/A * Internationalization may demand that these come from the message database 2N/A * Text string if none is provided: 2N/A * Text string introduction for "action". This may have to come from 2N/A * the message database because of internationalization. 2N/A * SEPSTR is the string that separates the "label" from what follows it, 2N/A * and the severity from what follows it. 2N/A * Miscellaneous constants: 2N/A * CONNAME Filesystem entry name for the system console 2N/A * Local data type definitions 2N/A * Severity string structure 2N/A * sevvalue Value of the severity-level being defined 2N/A * sevkywd Keyword identifying the severity 2N/A * sevprptr Pointer to the string associated with the value 2N/A * sevnext Pointer to the next value in the list. 2N/A * sevvalue Must be a non-negative integer (>=0) 2N/A * There are three (possibly null) lists of these structures. 2N/A * 1) is the list of standard severities 2N/A * 2) is the list of severity-levels defined by SEV_LEVEL 2N/A * 3) is the list of severity-levels defined by calls to 2N/A * Contains the internal representation or the 2N/A * MSGVERB environment variable. 2N/A * sevlook TRUE if fmtmsg() has to look at SEV_LEVEL the 2N/A * next time it is called. 2N/A * paugsevs struct sevstr * 2N/A * Head of the linked list of structures that define 2N/A * severities that augment the standard severities, 2N/A * as defined by addseverity(). 2N/A * penvsevs struct sevstrs * 2N/A * Head of the linked list of structures that define 2N/A * severities that augment the standard severities, 2N/A * as defined by SEV_LEVEL. 2N/A * pstdsevs struct sevstrs * 2N/A * Head of the linked list of structures that define 2N/A * the standard severities. 2N/A * static char *exttok(str, delims) 2N/A * const char *delims 2N/A * This function examines the string pointed to by "str", looking 2N/A * for the first occurrence of any of the characters in the string 2N/A * whose address is "delims". It returns the address of that 2N/A * character or (char *)NULL if there was nothing to search. 2N/A * str Address of the string to search 2N/A * delims Address of the string containing delimiters 2N/A * Returns the address of the first occurrence of any of the characters 2N/A * in "delim" in the string "str" (incl '\0'). If there was nothing 2N/A * to search, the function returns (char *)NULL. 2N/A * - This function is needed because strtok() can't be used inside a 2N/A * function. Besides, strtok() is destructive in the string, which 2N/A * is undesirable in many circumstances. 2N/A * - This function understands escaped delimiters as non-delimiters. 2N/A * Delimiters are escaped by preceding them with '\' characters. 2N/A * The '\' character also must be escaped. 2N/A char *
tokend;
/* Ptr to the end of the token */ 2N/A char *p, *q;
/* Temp pointers */ 2N/A * 1. Get the starting address(new string or where we 2N/A * left off). If nothing to search, return(char *)NULL 2N/A * 2. Find the end of the string 2N/A * 3. Look for the first unescaped delimiter closest to the 2N/A * beginning of the string 2N/A * 4. Remember where we left off 2N/A * 5. Return a pointer to the delimiter we found 2N/A /* Begin at the beginning, if any */ 2N/A /* Find end of the token string */ 2N/A /* Look for the 1st occurrence of any delimiter */ 2N/A * This function squeezes out all of the escaped character sequences 2N/A * from the string <str>. It returns a pointer to that string. 2N/A * The string that is to have its escaped characters removed. 2N/A * This function returns its argument <str> always. 2N/A * This function potentially modifies the string it is given. 2N/A char *p;
/* Temp string pointer */ 2N/A char *q;
/* Temp string pointer */ 2N/A /* Look for an escaped character */ 2N/A while (*p && (*p !=
'\\')) p++;
2N/A * If there was at least one, squeeze them out 2N/A * Otherwise, don't touch the argument string 2N/A while (*q++ = *p++) {
2N/A /* Finished. Return our argument */ 2N/A * struct sevstr *getauxsevs(ptr) 2N/A * Parses a string that is in the format of the severity definitions. 2N/A * Returns a pointer to a (malloc'd) structure that contains the 2N/A * definition, or (struct sevstr *)NULL if none was parsed. 2N/A * References the string from which data is to be extracted. 2N/A * If (char *)NULL, continue where we left off. Otherwise, 2N/A * start with the string referenced by ptr. 2N/A * Returns: struct sevstr * 2N/A * A pointer to a malloc'd structure containing the severity definition 2N/A * parsed from string, or (struct sevstr *)NULL if none. 2N/A * - This function is destructive to the string referenced by its argument. 2N/A char *
tokend;
/* Ptr to end of current sev def'n */ 2N/A char *
kywd;
/* Ptr to extracted kywd */ 2N/A char *
valstr;
/* Ptr to extracted sev value */ 2N/A char *
prstr;
/* Ptr to extracted print str */ 2N/A char *p;
/* Temp pointer */ 2N/A int val;
/* Converted severity value */ 2N/A int done;
/* Flag, sev def'n found and ok? */ 2N/A /* Start anew or start where we left off? */ 2N/A /* If nothing to parse, return (char *)NULL */ 2N/A * Look through the string "current" for a token of the form 2N/A * <kywd>,<sev>,<printstring> delimited by ':' or '\0' 2N/A /* Loop initializations */ 2N/A /* Eat leading junk */ 2N/A /* If we've found a <kywd>,... */ 2N/A /* Look for <kywd>,<sev>,... */ 2N/A /* Make sure <sev> > 4 */ 2N/A * Found <kywd>,<sev>,<printstring>. 2N/A * remember where we left off 2N/A * Alloc structure to contain 2N/A * severity definition 2N/A /* Fill in structure */ 2N/A * Invalid severity value, 2N/A * eat thru end of token 2N/A * Invalid severity definition, 2N/A * eat thru end of token 2N/A /* End of string found */ 2N/A }
/* while (!done) */ 2N/A * Parces the argument of the MSGVERB environment variable and places 2N/A * a representation of the value of that value in "msgverb" 2N/A char *
opts;
/* Pointer to MSGVERB's value */ 2N/A char *
tok;
/* Pointer to current token */ 2N/A char *
tokend;
/* Pointer to end of current token */ 2N/A /* Rid ourselves of junk in "msgverb" */ 2N/A /* Get the value of MSGVERB. If none, use default value */ 2N/A }
else {
/* MSGVERB has a value. Interpret it */ 2N/A /* Make a copy of the value of MSGVERB */ 2N/A /* Parse the options given by the user */ 2N/A * Find end of the next token and squeeze 2N/A * out escaped characters 2N/A /* Delimit token and mark next, if any */ 2N/A /* Check for "text" */ 2N/A /* Check for "label" */ 2N/A /* Check for "action */ 2N/A /* Check for "severity" */ 2N/A /* Check for "tag" */ 2N/A /* Unknown, ignore MSGVERB value */ 2N/A * Use default if no keywords on MSGVERB 2N/A * environment variable 2N/A /* Free allocated space */ 2N/A * This function builds a structure containing auxillary severity 2N/A /* Look for SEV_LEVEL definition */ 2N/A /* Allocate space and make a copy of the value of SEV_LEVEL */ 2N/A /* Continue for all severity descriptions */ 2N/A }
/* if sevspace != (char *)NULL */ 2N/A }
/* if value != (char *)NULL */ 2N/A * int addseverity(value, string) 2N/A * int value Value of the severity 2N/A * const char *string Print-string for the severity 2N/A * The integer value of the severity being added 2N/A * A pointer to the character-string to be printed 2N/A * whenever a severity of "value" is printed 2N/A * Zero if successful, -1 if failed. The function can fail under 2N/A * the following circumstances: 2N/A * - libc_malloc() fails 2N/A * - The "value" is one of the reserved values. 2N/A * This function permits C applications to define severity-levels 2N/A * that augment the standard levels and those defined by the 2N/A * SEV_LEVEL environment variable. 2N/A struct sevstr *p;
/* Temp ptr to severity structs */ 2N/A struct sevstr *q;
/* Temp ptr(follower) to severity */ 2N/A int found;
/* FLAG, element found in the list */ 2N/A int rtnval;
/* Value to return to the caller */ 2N/A /* Make sure we're not trying to redefine one of the reserved values */ 2N/A /* Make sure we've interpreted SEV_LEVEL */ 2N/A * Leaf through the list. We may be redefining or removing a 2N/A /* We've a match. Remove or modify the entry */ 2N/A /* Adding a definition */ 2N/A /* Allocate space for the severity structure */ 2N/A * Fill in the new structure with the data supplied and add to 2N/A * the head of the augmented severity list. 2N/A /* Successfully added a new severity */ 2N/A /* Attempting to undefined a non-defined severity */ 2N/A /* Successfully redefined a severity */ 2N/A /* Finished, successful */ 2N/A * Utility function for converting an integer to a string, avoiding stdio. 2N/A char buf[
12];
/* 32 bits fits in 10 decimal digits */ 2N/A * void writemsg(buf, size, verbosity, label, severity, text, action, tag) 2N/A * char *buf The buffer in which to format the message 2N/A * size_t size The size of the buffer 2N/A * int verbosity A bit-string that indicates which components 2N/A * const char *label The address of the label-component 2N/A * int severity The severity value of the message 2N/A * const char *text The address of the text-component 2N/A * const char *action The address of the action-component 2N/A * const char *tag The address of the tag-component 2N/A * This function formats the message consisting of the label-component, 2N/A * severity-component, text-component, action-component, and tag- 2N/A * component into the provided buffer. The "verbosity" argument 2N/A * tells which components can be selected. Any or all of the 2N/A * components can be their null-values. 2N/A char *p;
/* General purpose pointer */ 2N/A int i;
/* General purpose counter */ 2N/A int dosev;
/* TRUE if severity to be written */ 2N/A int dotag;
/* TRUE if tag to be written */ 2N/A char c;
/* Temp, multiuse character */ 2N/A /* truncated) label */ 2N/A /* truncated) tag */ 2N/A * initialize variables. 2N/A * Figure out what fields are to be written (all are optional) 2N/A * Figure out how much we'll need to indent the text of the message 2N/A /* Count the label of the message, if requested */ 2N/A * If severity req'd, determine the severity string and factor 2N/A * into indent count. Severity string generated by: 2N/A * 1. Search the standard list of severities. 2N/A * 2. Search the severities added by the application. 2N/A * 3. Search the severities added by the environment. 2N/A * 4. Use the default (SV=n where n is the value of the severity). 2N/A /* Search the default severity definitions */ 2N/A * Search the severity definitions 2N/A * added by the application 2N/A * Search the severity definitions 2N/A * added by the environment 2N/A /* Use default string, SV=severity */ 2N/A /* Factor into indent counts */ 2N/A * Figure out the indents. 2N/A * Write the message. 2N/A /* Write the LABEL, if requested */ 2N/A /* Write spaces to align on the ':' char, if needed */ 2N/A /* Write the label */ 2N/A * Write the separator string 2N/A * (if another component is to follow) 2N/A /* Write the SEVERITY, if requested */ 2N/A /* Write spaces to align on the ':' char, if needed */ 2N/A /* Write the severity print-string */ 2N/A * Write the separator string 2N/A * (if another component is to follow) 2N/A /* Write the TEXT, if requested */ 2N/A * Write ACTION if requested. 2N/A /* Write the action-string's introduction */ 2N/A /* Write the "action" string */ 2N/A * Write the TAG if requested 2N/A * Write terminating newline and null byte. 2N/A * We reserved space for these at the start. 2N/A * int fmtmsg(class, label, severity, text, action, tag) 2N/A * const char *action 2N/A * If requested, the fmtmsg() function writes a message to the standard 2N/A * error stream in the standard message format. Also if requested, it 2N/A * will write a message to the system console. 2N/A * class Fields which classify the message for the system 2N/A * label A character-string that is printed as the "label" 2N/A * of the message. Typically identifies the source 2N/A * severity Identifies the severity of the message. Either one 2N/A * of the standard severities, or possibly one of the 2N/A * augmented severities 2N/A * text Pointer to the text of the message 2N/A * action Pointer to a char string that describes some type 2N/A * of corrective action. 2N/A * tag A character-string that is printed as the "tag" or 2N/A * the message. Typically a pointer to documentation 2N/A * -1 if nothing was generated, 0 if everything requested was 2N/A * generated, or flags if partially generated. 2N/A * - Nothing special for 4.0. 2N/A * Determine the "verbosity" of the message. If "msgverb" is 2N/A * already set, don't interrogate the "MSGVERB" environment vbl. 2N/A * If so, interrogate "MSGVERB" and do initialization stuff also. 2N/A * Extract the severity definitions from the SEV_LEVEL 2N/A * environment variable and save away for later. 2N/A /* Set up the default text component [if text==(char *)NULL] */ 2N/A /* Prepare the message for stderr if requested */ 2N/A /* Prepare the message for the console if requested */ 2N/A /* Write the message to stderr if requested */ 2N/A /* Write the message to the console if requested */