main.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* 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
* 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 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;
};
/*
* Local static data
*/
/*
* Table contains the keywords for the classes of a message
*/
static struct class_info classes[] = {
{(char *) NULL, 0L, 0L} /* end of list */
};
/*
* Table contains the keywords for the subclasses for a message
*/
static struct class_info subclasses[] = {
{(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[] = {
{(char *) NULL, 0} /* end of list */
};
/*
* Buffers used by the command
*/
/*
* 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 *
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 */
return ((char *) NULL);
}
/* Find end of the token string */
/* Look for the 1st occurrence of any delimiter */
for (p = delims ; *p != '\0' ; p++) {
}
/* 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 *
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 struct sevstr *
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? */
/* Start anew or start where we left off? */
/* If nothing to parse, return (char *) NULL */
}
/*
* Look through the string "current" for a token of the form
* <kywd>,<sev>,<printstring> delimited by ':' or '\0'
*/
/* Loop initializations */
while (!done) {
/* Eat leading junk */
}
/* If we've found a <kywd>,... */
if (*tokend == ',') {
*tokend = '\0';
/* Look for <kywd>,<sev>,... */
*tokend = '\0';
/* Make sure <sev> > 4 */
/*
* Found <kywd>,<sev>,<printstring>.
* remember where we left off
*/
*tokend = '\0';
/* Alloc structure to contain severity definition */
/* Fill in structure */
}
} else {
/* Invalid severity value, eat thru end of token */
current++;
}
} else {
/* Invalid severity definition, eat thru end of token */
if (*tokend == ':')
current++;
}
} else {
/* End of string found */
}
} /* 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:
*/
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 */
/*
* fmtmsg
*/
/* Initializations */
/* Extract the base command name from the command */
else
cmdname = p+1;
/* Build the label for messages from "fmtmsg" */
/*
* Extract arguments from the command line
*/
/* Initializations */
opterr = 0; /* Disable messages from getopt() */
/*
* If only the command name was used, write out a usage string to
* the standard output file.
*/
if (argc == 1) {
exit(0);
}
/* Parce command line */
!errflg) {
switch(optchar) {
case 'a': /* -a actiontext */
if (!a_seen) {
break;
case 'c': /* -c classification */
if (!c_seen) {
break;
case 'l': /* -l label */
if (!l_seen) {
break;
case 's': /* -s severity */
if (!s_seen) {
break;
case 't': /* -t tag */
if (!t_seen) {
break;
case 'u': /* -u subclasslist */
if (!u_seen) {
break;
case '?': /* -? or unknown option */
default:
break;
} /* esac */
}
/* Get the text */
if (!errflg) {
}
}
}
/* Report syntax errors */
if (errflg) {
exit(1);
}
/*
* Classification.
*/
class = 0L;
if (c_seen) {
/* Search for keyword in list */
for (class_info = &classes[0] ;
class_info++) ;
/* If invalid (keyword unknown), write a message and exit */
"Invalid class: %s", cstr);
exit(1);
}
/* Save classification */
}
/*
* Subclassification.
*/
if (u_seen) {
else do {
/* Got a keyword. Look for it in keyword list */
for (class_info = subclasses ;
class_info++) ;
/* If found in list and no conflict, remember in class */
else
if (errflg) {
"Invalid subclass: %s", ustr);
exit(1);
}
}
/*
* Severity.
*/
if (s_seen) {
/* If the severity is specified as a number, use that value */
/* Look for the standard severities */
for (sev_info = severities ;
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 */
else {
/*
* Severity keyword may be one of the extended set, if any.
*/
/* Get the value of the SEV_LEVEL environment variable */
}
else {
}
}
if (!found) {
"Invalid severity: %s", sstr);
exit(1);
}
} /* <severity> is not one of the standard severities */
} /* <severity> is not numeric */
} /* if (s_seen) */
else severity = MM_NULLSEV;
/*
* Other options
*/
/*
* Write the message
*/
/*
* Return appropriate value to the shell (or wherever)
*/
exitval = 0;
else {
}
return(exitval);
}