summaryrefslogtreecommitdiff
path: root/usr/src/cmd/fmtmsg
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/fmtmsg
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/fmtmsg')
-rw-r--r--usr/src/cmd/fmtmsg/Makefile50
-rw-r--r--usr/src/cmd/fmtmsg/main.c829
2 files changed, 879 insertions, 0 deletions
diff --git a/usr/src/cmd/fmtmsg/Makefile b/usr/src/cmd/fmtmsg/Makefile
new file mode 100644
index 0000000000..7c8b77a890
--- /dev/null
+++ b/usr/src/cmd/fmtmsg/Makefile
@@ -0,0 +1,50 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1989 by Sun Microsystems, Inc.
+#
+
+PROG= fmtmsg
+OBJS= main.o
+SRCS= $(OBJS:%.o=%.c)
+
+include ../Makefile.cmd
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+install: all $(ROOTPROG)
+
+clean:
+ $(RM) $(OBJS)
+
+lint:
+ $(LINT.c) $(SRCS)
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/fmtmsg/main.c b/usr/src/cmd/fmtmsg/main.c
new file mode 100644
index 0000000000..9a35f55d76
--- /dev/null
+++ b/usr/src/cmd/fmtmsg/main.c
@@ -0,0 +1,829 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+/*
+ * fmtmsg.c
+ *
+ * Contains:
+ * fmtmsg Command that writes a message in the standard
+ * message format. May in future make these
+ * messages available for logging.
+ */
+
+
+/*
+ * Header files used:
+ * <stdio.h> C Standard I/O function definitions
+ * <string.h> C string-handling definitions
+ * <errno.h> UNIX error-code "errno" definitions
+ * <fmtmsg.h> Standard Message definitions
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fmtmsg.h>
+
+
+/*
+ * Externals referenced:
+ * strtol Function that converts char strings to "long"
+ * fmtmsg Function that writes a message in standard format
+ * getenv Function that extracts an environment variable's
+ * value
+ * malloc Allocate memory from the memory pool
+ * free Frees allocated memory
+ * getopt Function that extracts arguments from the command-
+ * optarg Points to option's argument (from getopt())
+ * optind Option's argument index (from getopt())
+ * opterr FLAG, write error if invalid option (for getopt())
+ * line.
+ * exit Exits the command
+ */
+
+extern long strtol();
+extern int fmtmsg();
+extern char *getenv();
+extern void *malloc();
+extern void free();
+extern int getopt();
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern void exit();
+
+/*
+ * Local definitions
+ */
+
+/*
+ * Local constants
+ */
+
+
+/*
+ * Boolean constants
+ * TRUE Boolean value for "true" (any bits on)
+ * FALSE Boolean value for "false" (all bits off)
+ */
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+
+
+#define CLASS (MM_PRINT|MM_SOFT|MM_NRECOV|MM_UTIL)
+#define BIGUSAGE "fmtmsg [-a action] [-c class] [-l label] [-s severity] [-t tag]\n [-u subclass[,subclass[,...]]] [text]\n"
+
+
+/*
+ * Local data-type definitions
+ */
+
+/*
+ * Structure used for tables containing keywords and integer values
+ */
+
+struct sev_info {
+ char *keyword;
+ int value;
+};
+
+
+/*
+ * Structure used for tables containing keywords, long values
+ */
+
+struct class_info {
+ char *keyword;
+ long value;
+ long conflict;
+};
+
+
+/*
+ * Severity string structure
+ *
+ * struct sevstr
+ * sevvalue Value of the severity-level being defined
+ * sevkywd Keyword identifying the severity
+ * sevprptr Pointer to the string associated with the value
+ * sevnext Pointer to the next value in the list.
+ */
+
+struct sevstr {
+ int sevvalue;
+ char *sevkywd;
+ char *sevprstr;
+ struct sevstr *sevnext;
+};
+
+
+/*
+ * Local static data
+ */
+
+
+/*
+ * Table contains the keywords for the classes of a message
+ */
+
+static struct class_info classes[] = {
+
+ {"hard", MM_HARD, MM_SOFT|MM_FIRM}, /* hardware */
+ {"soft", MM_SOFT, MM_HARD|MM_FIRM}, /* software */
+ {"firm", MM_FIRM, MM_SOFT|MM_FIRM}, /* firmware */
+
+ {(char *) NULL, 0L, 0L} /* end of list */
+
+};
+
+
+/*
+ * Table contains the keywords for the subclasses for a message
+ */
+
+static struct class_info subclasses[] = {
+
+ {"appl", MM_APPL, MM_UTIL|MM_OPSYS}, /* Application */
+ {"util", MM_UTIL, MM_APPL|MM_OPSYS}, /* Utility */
+ {"opsys", MM_OPSYS, MM_APPL|MM_UTIL}, /* Operating System */
+
+ {"recov", MM_RECOVER, MM_NRECOV}, /* Recoverable */
+ {"nrecov", MM_NRECOV, MM_RECOVER}, /* Non-recoverable */
+
+ {"print", MM_PRINT, 0L}, /* Write message to stderr */
+ {"console", MM_CONSOLE, 0L}, /* Write message on /dev/console */
+ {(char *) NULL, 0L, 0L} /* End of list */
+
+};
+
+
+/*
+ * Table contains the keywords for the standard severities of a message.
+ * User may supply more through the SEV_LEVEL environment variable.
+ */
+
+static struct sev_info severities[] = {
+ {"halt", MM_HALT}, /* halt */
+ {"error", MM_ERROR}, /* error */
+ {"warn", MM_WARNING}, /* warn */
+ {"info", MM_INFO}, /* info */
+ {(char *) NULL, 0} /* end of list */
+};
+
+
+/*
+ * Buffers used by the command
+ */
+
+static char labelbuf[128]; /* Buf for message label */
+static char msgbuf[256]; /* Buf for messages */
+
+/*
+ * static char *exttok(str, delims)
+ * char *str
+ * char *delims
+ *
+ * This function examines the string pointed to by "str", looking
+ * for the first occurrence of any of the characters in the string
+ * whose address is "delims". It returns the address of that
+ * character or (char *) NULL if there was nothing to search.
+ *
+ * Arguments:
+ * str Address of the string to search
+ * delims Address of the string containing delimiters
+ *
+ * Returns: char *
+ * Returns the address of the first occurrence of any of the characters
+ * in "delim" in the string "str" (incl '\0'). If there was nothing
+ * to search, the function returns (char *) NULL.
+ *
+ * Notes:
+ * - This function is needed because strtok() can't be used inside a
+ * function. Besides, strtok() is destructive in the string, which
+ * is undesirable in many circumstances.
+ * - This function understands escaped delimiters as non-delimiters.
+ * Delimiters are escaped by preceding them with '\' characters.
+ * The '\' character also must be escaped.
+ */
+
+static char *
+exttok(tok, delims)
+ char *tok; /* Ptr to the token we're parsing */
+ char *delims; /* Ptr to string with delimiters */
+{
+
+ /* Automatic Data */
+ char *tokend; /* Ptr to the end of the token */
+ char *p, *q; /* Temp pointers */
+
+
+ /* Algorithm:
+ * 1. Get the starting address (new string or where we
+ * left off). If nothing to search, return (char *) NULL
+ * 2. Find the end of the string
+ * 3. Look for the first unescaped delimiter closest to the
+ * beginning of the string
+ * 4. Remember where we left off
+ * 5. Return a pointer to the delimiter we found
+ */
+
+ /* Begin at the beginning, if any */
+ if (tok == (char *) NULL) {
+ return ((char *) NULL);
+ }
+
+ /* Find end of the token string */
+ tokend = tok + strlen(tok);
+
+ /* Look for the 1st occurrence of any delimiter */
+ for (p = delims ; *p != '\0' ; p++) {
+ for (q = strchr(tok, *p) ; q && (q != tok) && (*(q-1) == '\\') ; q = strchr(q+1, *p)) ;
+ if (q && (q < tokend)) tokend = q;
+ }
+
+ /* Done */
+ return(tokend);
+}
+
+/*
+ * char *noesc(str)
+ *
+ * This function squeezes out all of the escaped character sequences
+ * from the string <str>. It returns a pointer to that string.
+ *
+ * Arguments:
+ * str char *
+ * The string that is to have its escaped characters removed.
+ *
+ * Returns: char *
+ * This function returns its argument <str> always.
+ *
+ * Notes:
+ * This function potentially modifies the string it is given.
+ */
+
+char *
+noesc(str)
+ char *str; /* String to remove escaped characters from */
+{
+ char *p; /* Temp string pointer */
+ char *q; /* Temp string pointer */
+
+ /* Look for an escaped character */
+ p = str;
+ while (*p && (*p != '\\')) p++;
+
+
+ /*
+ * If there was at least one, squeeze them out
+ * Otherwise, don't touch the argument string
+ */
+
+ if (*p) {
+ q = p++;
+ while (*q++ = *p++) if (*p == '\\') p++;
+ }
+
+ /* Finished. Return our argument */
+ return(str);
+}
+
+/*
+ * struct sevstr *getauxsevs(ptr)
+ *
+ * Parses a string that is in the format of the severity definitions.
+ * Returns a pointer to a (malloc'd) structure that contains the
+ * definition, or (struct sevstr *) NULL if none was parsed.
+ *
+ * Arguments:
+ * ptr char *
+ * References the string from which data is to be extracted.
+ * If (char *) NULL, continue where we left off. Otherwise,
+ * start with the string referenced by ptr.
+ *
+ * Returns: struct sevstr *
+ * A pointer to a malloc'd structure containing the severity definition
+ * parsed from string, or (struct sevstr *) NULL if none.
+ *
+ * Notes:
+ * - This function is destructive to the string referenced by its argument.
+ */
+
+
+/* Static data */
+static char *leftoff = (char *) NULL;
+
+static struct sevstr *
+getauxsevs(ptr)
+ char *ptr;
+{
+
+ /* Automatic data */
+ char *current; /* Ptr to current sev def'n */
+ char *tokend; /* Ptr to end of current sev def'n */
+ char *kywd; /* Ptr to extracted kywd */
+ char *valstr; /* Ptr to extracted sev value */
+ char *prstr; /* Ptr to extracted print str */
+ char *p; /* Temp pointer */
+ int val; /* Converted severity value */
+ int done; /* Flag, sev def'n found and ok? */
+ struct sevstr *rtnval; /* Value to return */
+
+
+ /* Start anew or start where we left off? */
+ current = (ptr == (char *) NULL) ? leftoff : ptr;
+
+
+ /* If nothing to parse, return (char *) NULL */
+ if (current == (char *) NULL) {
+ return ((struct sevstr *) NULL);
+ }
+
+
+ /*
+ * Look through the string "current" for a token of the form
+ * <kywd>,<sev>,<printstring> delimited by ':' or '\0'
+ */
+
+ /* Loop initializations */
+ done = FALSE;
+ rtnval = (struct sevstr *) NULL;
+ while (!done) {
+
+ /* Eat leading junk */
+ while (*(tokend = exttok(current, ":,")) == ':') {
+ current = tokend + 1;
+ }
+
+ /* If we've found a <kywd>,... */
+ if (*tokend == ',') {
+ kywd = current;
+ *tokend = '\0';
+
+ /* Look for <kywd>,<sev>,... */
+ current = tokend + 1;
+ if (*(tokend = exttok(current, ":,")) == ',') {
+ valstr = current;
+ *tokend = '\0';
+ current = tokend+1;
+ prstr = current;
+
+ /* Make sure <sev> > 4 */
+ val = (int) strtol(noesc(valstr), &p, 0);
+ if ((val > 4) && (p == tokend)) {
+
+ /*
+ * Found <kywd>,<sev>,<printstring>.
+ * remember where we left off
+ */
+
+ if (*(tokend = exttok(current, ":")) == ':') {
+ *tokend = '\0';
+ leftoff = tokend + 1;
+ } else leftoff = (char *) NULL;
+
+ /* Alloc structure to contain severity definition */
+ if (rtnval = (struct sevstr *) malloc(sizeof(struct sevstr))) {
+
+ /* Fill in structure */
+ rtnval->sevkywd = noesc(kywd);
+ rtnval->sevvalue = val;
+ rtnval->sevprstr = noesc(prstr);
+ rtnval->sevnext = (struct sevstr *) NULL;
+ }
+
+ done = TRUE;
+
+ } else {
+
+ /* Invalid severity value, eat thru end of token */
+ current = tokend;
+ if (*(tokend = exttok(prstr, ":")) == ':')
+ current++;
+ }
+
+ } else {
+
+ /* Invalid severity definition, eat thru end of token */
+ current = tokend;
+ if (*tokend == ':')
+ current++;
+ }
+
+ } else {
+
+ /* End of string found */
+ done = TRUE;
+ leftoff = (char *) NULL;
+ }
+
+ } /* while (!done) */
+
+ /* Finished */
+ return(rtnval);
+}
+
+/*
+ * fmtmsg [-a action] [-c classification] [-l label] [-s severity] [-t tag]
+ * [-u subclass[,subclass[,...]]] [text]
+ *
+ * Function:
+ * Writes a message in the standard format. Typically used by shell
+ * scripts to write error messages to the user.
+ *
+ * Arguments:
+ * text String that is the text of the message
+ *
+ * Options:
+ * -a action String that describes user action to take to
+ * correct the situation
+ * -c classification Keyword that identifies the type of the message
+ * -l label String that identifies the source of the message
+ * -s severity Keyword that identifies the severity of the message
+ * -t tag String that identifies the message (use unclear)
+ * -u sub_classes Comma-list of keywords that refines the type of
+ * the message
+ *
+ * Environment Variables Used:
+ * MSGVERB Defines the pieces of a message the user expects
+ * to see. It is a list of keywords separated by
+ * colons (':').
+ * SEV_LEVEL Defines a list of auxiliary severity keywords, values,
+ * and print-strings. It is a list of fields separated
+ * by colons (':'). Each field consists of three
+ * elements, keyword, value (in octal, hex, or decimal),
+ * and print-string, separated by commas (',').
+ *
+ * Needs:
+ *
+ * Open Issues:
+ */
+
+main(argc, argv)
+ int argc; /* Argument count */
+ char *argv[]; /* Pointers to arguments */
+{
+
+ /* Local automatic data */
+
+ long class; /* Classification (built) */
+
+ int severity; /* User specified severity */
+ int msgrtn; /* Value returned by fmtmsg() */
+ int optchar; /* Opt char on cmdline */
+ int exitval; /* Value to return */
+
+ int found; /* FLAG, kywd found yet? */
+ int errflg; /* FLAG, error seen in cmd */
+ int a_seen; /* FLAG, -a option seen */
+ int c_seen; /* FLAG, -c option seen */
+ int l_seen; /* FLAG, -l option seen */
+ int s_seen; /* FLAG, -s option seen */
+ int t_seen; /* FLAG, -t option seen */
+ int u_seen; /* FLAG, -u option seen */
+ int text_seen; /* FLAG, text seen */
+
+ char *text; /* Ptr to user's text */
+ char *label; /* Ptr to user's label */
+ char *tag; /* Ptr to user's tag */
+ char *action; /* Ptr to user's action str */
+ char *sstr; /* Ptr to -s (severity) arg */
+ char *ustr; /* Ptr to -u (subclass) arg */
+ char *cstr; /* Ptr to -c (class) arg */
+ char *sevstrval; /* Ptr to SEV_LEVEL argument */
+ char *sevval; /* Ptr to temp SEV_LEVEL arg */
+ char *tokenptr; /* Ptr to current token */
+ char *cmdname; /* Ptr to base command name */
+ char *p; /* Multipurpose ptr */
+
+ struct class_info *class_info; /* Ptr to class/subclass info structure */
+ struct sev_info *sev_info; /* Ptr to severity info struct */
+ struct sevstr *penvsev; /* Ptr to SEV_LEVEL values */
+
+
+
+ /*
+ * fmtmsg
+ */
+
+
+ /* Initializations */
+
+
+ /* Extract the base command name from the command */
+ if ((p = strrchr(argv[0], '/')) == (char *) NULL)
+ cmdname = argv[0];
+ else
+ cmdname = p+1;
+
+ /* Build the label for messages from "fmtmsg" */
+ (void) snprintf(labelbuf, sizeof (labelbuf), "UX:%s", cmdname);
+
+
+ /*
+ * Extract arguments from the command line
+ */
+
+ /* Initializations */
+
+ opterr = 0; /* Disable messages from getopt() */
+ errflg = FALSE; /* No errors seen yet */
+
+ a_seen = FALSE; /* No action (-a) text seen yet */
+ c_seen = FALSE; /* No classification (-c) seen yet */
+ l_seen = FALSE; /* No label (-l) seen yet */
+ s_seen = FALSE; /* No severity (-s) seen yet */
+ t_seen = FALSE; /* No tag (-t) seen yet */
+ u_seen = FALSE; /* No subclass (-u) seen yet */
+ text_seen = FALSE; /* No text seen yet */
+
+
+ /*
+ * If only the command name was used, write out a usage string to
+ * the standard output file.
+ */
+
+ if (argc == 1) {
+ (void) fputs(BIGUSAGE, stderr);
+ exit(0);
+ }
+
+
+ /* Parce command line */
+ while (((optchar = getopt(argc, argv, "a:c:l:s:t:u:")) != EOF) &&
+ !errflg) {
+
+ switch(optchar) {
+
+ case 'a': /* -a actiontext */
+ if (!a_seen) {
+ action = optarg;
+ a_seen = TRUE;
+ } else errflg = TRUE;
+ break;
+
+ case 'c': /* -c classification */
+ if (!c_seen) {
+ cstr = optarg;
+ c_seen = TRUE;
+ } else errflg = TRUE;
+ break;
+
+ case 'l': /* -l label */
+ if (!l_seen) {
+ label = optarg;
+ l_seen = TRUE;
+ } else errflg = TRUE;
+ break;
+
+ case 's': /* -s severity */
+ if (!s_seen) {
+ sstr = optarg;
+ s_seen = TRUE;
+ } else errflg = TRUE;
+ break;
+
+ case 't': /* -t tag */
+ if (!t_seen) {
+ tag = optarg;
+ t_seen = TRUE;
+ } else errflg = TRUE;
+ break;
+
+ case 'u': /* -u subclasslist */
+ if (!u_seen) {
+ ustr = optarg;
+ u_seen = TRUE;
+ } else errflg = TRUE;
+ break;
+
+ case '?': /* -? or unknown option */
+ default:
+ errflg = TRUE;
+ break;
+
+ } /* esac */
+ }
+
+
+ /* Get the text */
+ if (!errflg) {
+ if (argc == (optind+1)) {
+ text = argv[optind];
+ text_seen = TRUE;
+ }
+ else if (argc != optind) {
+ errflg = TRUE;
+ }
+ }
+
+
+ /* Report syntax errors */
+ if (errflg) {
+ (void) fputs(BIGUSAGE, stderr);
+ exit(1);
+ }
+
+
+ /*
+ * Classification.
+ */
+
+ class = 0L;
+ if (c_seen) {
+
+ /* Search for keyword in list */
+ for (class_info = &classes[0] ;
+ (class_info->keyword != (char *) NULL) &&
+ (strcmp(cstr, class_info->keyword)) ;
+ class_info++) ;
+
+ /* If invalid (keyword unknown), write a message and exit */
+ if (class_info->keyword == (char *) NULL) {
+ (void) snprintf(msgbuf, sizeof (msgbuf),
+ "Invalid class: %s", cstr);
+ (void) fmtmsg(CLASS, labelbuf, MM_ERROR, msgbuf,
+ MM_NULLACT, MM_NULLTAG);
+ exit(1);
+ }
+
+ /* Save classification */
+ class = class_info->value;
+
+ }
+
+
+ /*
+ * Subclassification.
+ */
+
+ if (u_seen) {
+
+ errflg = FALSE;
+ p = strcpy(malloc((unsigned int) strlen(ustr)+1), ustr);
+ if ((tokenptr = strtok(p, ",")) == (char *) NULL) errflg = TRUE;
+ else do {
+
+ /* Got a keyword. Look for it in keyword list */
+ for (class_info = subclasses ;
+ (class_info->keyword != (char *) NULL) &&
+ (strcmp(tokenptr, class_info->keyword) != 0) ;
+ class_info++) ;
+
+ /* If found in list and no conflict, remember in class */
+ if ((class_info->keyword != (char *) NULL) && ((class & class_info->conflict) == 0L))
+ class |= class_info->value;
+ else
+ errflg = TRUE;
+
+ } while (!errflg && ((tokenptr = strtok((char *) NULL, ",")) != (char *) NULL)) ;
+
+ if (errflg) {
+ (void) snprintf(msgbuf, sizeof (msgbuf),
+ "Invalid subclass: %s", ustr);
+ (void) fmtmsg(CLASS, labelbuf, MM_ERROR, msgbuf,
+ MM_NULLACT, MM_NULLTAG);
+ exit(1);
+ }
+
+ }
+
+ if (!c_seen & !u_seen) class = MM_NULLMC;
+
+
+
+ /*
+ * Severity.
+ */
+
+ if (s_seen) {
+
+ /* If the severity is specified as a number, use that value */
+ severity = strtol(sstr, &p, 10);
+ if (*p || (strlen(sstr) == 0)) {
+
+ /* Look for the standard severities */
+ for (sev_info = severities ;
+ (sev_info->keyword != (char *) NULL) &&
+ (strcmp(sstr, sev_info->keyword)) ;
+ sev_info++) ;
+
+ /*
+ * If the "severity" argument is one of the standard keywords,
+ * remember it for fmtmsg(). Otherwise, look at the SEV_LEVEL
+ * environment variable for severity extensions.
+ */
+
+ /* If the keyword is one of the standard ones, save severity */
+ if (sev_info->keyword != (char *) NULL) severity = sev_info->value;
+
+ else {
+
+ /*
+ * Severity keyword may be one of the extended set, if any.
+ */
+
+ /* Get the value of the SEV_LEVEL environment variable */
+ found = FALSE;
+ if ((sevstrval = getenv(SEV_LEVEL)) != (char *) NULL) {
+ sevval = (char *) malloc((unsigned int) strlen(sevstrval)+1);
+ penvsev = getauxsevs(strcpy(sevval, sevstrval));
+ if (penvsev != (struct sevstr *) NULL) do {
+ if (strcmp(penvsev->sevkywd, sstr) == 0) {
+ severity = penvsev->sevvalue;
+ found = TRUE;
+ }
+ else {
+ free(penvsev);
+ penvsev = getauxsevs((char *) NULL);
+ }
+ } while (!found && (penvsev != (struct sevstr *) NULL));
+
+ if (found) free(penvsev);
+ free(sevval);
+ }
+
+ if (!found) {
+ (void) snprintf(msgbuf, sizeof (msgbuf),
+ "Invalid severity: %s", sstr);
+ (void) fmtmsg(CLASS, labelbuf, MM_ERROR, msgbuf,
+ MM_NULLACT, MM_NULLTAG);
+ exit(1);
+ }
+
+ } /* <severity> is not one of the standard severities */
+
+ } /* <severity> is not numeric */
+
+ } /* if (s_seen) */
+
+ else severity = MM_NULLSEV;
+
+
+ /*
+ * Other options
+ */
+
+ if (!a_seen) action = MM_NULLACT;
+ if (!l_seen) label = MM_NULLLBL;
+ if (!t_seen) tag = MM_NULLTAG;
+ if (!text_seen) text = MM_NULLTXT;
+
+
+ /*
+ * Write the message
+ */
+
+ msgrtn = fmtmsg(class, label, severity, text, action ,tag);
+
+
+ /*
+ * Return appropriate value to the shell (or wherever)
+ */
+
+ exitval = 0;
+ if (msgrtn == MM_NOTOK) exitval = 32;
+ else {
+ if (msgrtn & MM_NOMSG) exitval += 2;
+ if (msgrtn & MM_NOCON) exitval += 4;
+ }
+
+ exit(exitval);
+ return(exitval);
+}