From: Jonathan Leffler <jleffler@informix.com>
Date: Tue, 20 Oct 1998 09:26:09 -0700 (PDT)

On Tue, 20 Oct 1998, John H. Frantz wrote:

> finderr 100 shows me the duplicate value message.
> finderr -100 also shows me this.

Unless you put an explicit + in front of the number, finderr interprets
numbers as error numbers, and hence as negative.

> finderr +100 shows me a no matching record message (i.e. not found).

It could, equivalently, have shown the duplicate value message.
C-ISAM can return iserrno = +100 for the duplicate value error.

Note that finderr simply (well, not all that simply) greps through a
text file to produce the text of an error message.  By contrast, rgetmsg()
goes to the actual iem-file for the raw message.

> Apparently finderr assumes a negative value unless otherwise specified.

Yes.

> I'm not sure about rgetmsg() but if it accepts the message number as an
> integer then it may always assume a negative number, dealing only with
> messages categorized as errors.

No!  rgetmsg() interprets the number you supply as the number you supply.
Internally, Informix code uses positive numbers for messages (including
things like menu options), and negative numbers for errors.

> Art S. Kagel wrote:
> > Henry A.L. Wollman wrote:
> > > How come rgetmsg returns the wrong description for an error code 100? It
> > > should be "not found" but instead returns something about a duplicate
> > > value on insert or update of a unique key.
> > >
> > > Are there other error codes for which rgetmsg returns the wrong
> > > description? It seems that even the manual as far back as several years
> > > ago has the wrong message for a 100. Aren't these things ever fixed? Is
> > > rgetmsg not a reliable function? Must I write my own?
> > 
> > There is nothing to fix since nothing is broken!
> > 
> > Rgetmsg does not return the wrong message.  SQLNOTFOUND, or 100 is NOT
> > an error, however, there IS an ISAM error -100 which is described as:
> > 
> > -100    ISAM error: duplicate value for a record with a unique key.
> > 
> > It is a convenience that finderr and rgetmsg return the message whether
> > you enter the message number as positive or negative, but remember that
> > ALL error message numbers are negative!  SQLNOTFOUND is an INDICATOR
> > that there is no more data to fetch NOT and error caused by fetching
> > beyond the end of the select set.

I threatened to send a chkmsg() program to c.d.i; I'm now carrying out that
threat.  I'm not all that keen on the way it uses getopt(), but it more or
less works.  To compile:

	esql -o chkmsg chkmsg.ec range2.c stderr.c

To use:
	chkmsg 100
	chkmsg +100
	chkmsg -100
	chkmsg -100:+100
	chkmsg -100..+100

This is a direct interface to rgetmsg(), so you can see what messages are
really in the message files.  You might care to note that both +100 and
-100 produce the same message text:

	-100: ISAM error:  duplicate value for a record with unique key.
	100: ISAM error:  duplicate value for a record with unique key.

Yours,
Jonathan Leffler (jleffler@informix.com) #include <witticism.h>
Guardian of DBD::Informix v0.60 -- http://www.perl.com/CPAN
Informix IDN for D4GL & Linux -- http://www.informix.com/idn

PS: I think this might be useful in the IIUG software archives.

:	"@(#): shar.sh,v 2.1 1998/06/02 17:13:43 jleffler Exp $"
#! /bin/sh
#
#	This is a shell archive.
#	Remove everything above this line and run sh on the resulting file.
#	If this archive is complete, you will see this message at the end:
#	"All files extracted"
#
#	Created on: Tue Oct 20 09:20:00 PDT 1998
#	Created by: jleffler at Informix Software Inc.
#
#	Files archived in this archive:
#	chkmsg.ec
#	getopt.h
#	range.h
#	range2.c
#	stderr.c
#	stderr.h
#
#--------------------
if [ -f chkmsg.ec -a "$1" != "-c" ]
then echo shar: chkmsg.ec already exists
else
echo 'x - chkmsg.ec (2190 characters)'
sed -e 's/^X//' >chkmsg.ec <<'SHAR-EOF'
X/*
X@(#)File:            $RCSfile: chkmsg.ec,v $
X@(#)Version:         $Revision: 1.1 $
X@(#)Last changed:    $Date: 1997/03/28 14:28:12 $
X@(#)Purpose:         Check specified message numbers
X@(#)Author:          J Leffler
X@(#)Copyright:       (C) JLSS 1997
X*/
X
X/*TABSTOP=4*/
X
X#define MAIN_PROGRAM
X#include <stdio.h>
X#include <stdlib.h>
X#include "stderr.h"
X#include "getopt.h"
X#include "range.h"
X
X#define	NIL(x)		((x)0)
X
X/* -- Declarations */
X
Xstatic const char usestr[] = "[-qV] lo[-hi] ...";
X
X#ifndef lint
Xstatic const char sccs[] = "@(#)$Id: chkmsg.ec,v 1.1 1997/03/28 14:28:12 johnl Exp $";
X#endif
X
Xstatic int chkmsg(char *arg, int qflag)
X{
X	int estat = EXIT_SUCCESS;
X	long lo;
X	long hi;
X	char *endp;
X	long msg;
X
X	endp = numeric_range(arg, &lo, &hi);
X	if (endp == arg || *endp != '\0')
X		err_report(ERR_ERR, ERR_STAT,
X			"Non-numeric character after range '%s'\n", arg);
X
X	for (msg = lo; msg <= hi; msg++)
X	{
X		int actlen;
X		long err;
X		char buffer[BUFSIZ];
X		if ((err = rgetlmsg(msg, buffer, sizeof(buffer), &actlen)) != 0)
X		{
X			err_report(ERR_REM, ERR_STAT,
X				"cannot locate message %ld -- error %ld\n", msg, err);
X			estat = EXIT_FAILURE;
X		}
X		else if (qflag == 0)
X		{
X			printf("%ld: %s", msg, buffer);
X			if (actlen >= sizeof(buffer))
X				putchar('\n');
X		}
X	}
X	return(estat);
X}
X
Xint main(int argc, char **argv)
X{
X	int i;
X	int opt;
X	int nstat;
X	int estat = EXIT_SUCCESS;
X	int qflag = 0;
X	int nflag = 0;
X
X	setarg0(argv[0]);
X
X	while ((opt = getopt(argc, argv, "qV0:1:2:3:4:5:6:7:8:9:")) != EOF)
X	{
X		switch (opt)
X		{
X		case 'q':
X			qflag = 1;
X			break;
X		case 'V':
X			version("CHKMSG", "$Revision: 1.1 $ ($Date: 1997/03/28 14:28:12 $)");
X			break;
X
X		case '0':
X		case '1':
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X		case '8':
X		case '9':
X			/* GETOPT() is probably not the right tool for this job! */
X			nstat = chkmsg(optarg-2, qflag);
X			if (estat == EXIT_SUCCESS)
X				estat = nstat;
X			nflag = 1;
X			break;
X
X		default:
X			usage(usestr);
X			break;
X		}
X	}
X
X	if (optind >= argc && nflag == 0)
X		usage(usestr);
X
X	for (i = optind; i < argc; i++)
X	{
X		nstat = chkmsg(argv[i], qflag);
X		if (estat == EXIT_SUCCESS)
X			estat = nstat;
X	}
X
X	return(estat);
X}
SHAR-EOF
chmod 444 chkmsg.ec
if [ `wc -c <chkmsg.ec` -ne 2190 ]
then echo shar: chkmsg.ec unpacked with wrong size
fi
# end of overwriting check
fi
#--------------------
if [ -f getopt.h -a "$1" != "-c" ]
then echo shar: getopt.h already exists
else
echo 'x - getopt.h (1772 characters)'
sed -e 's/^X//' >getopt.h <<'SHAR-EOF'
X/*
X@(#)File:            $RCSfile: getopt.h,v $
X@(#)Version:         $Revision: 1.10 $
X@(#)Last changed:    $Date: 1998/04/09 18:48:20 $
X@(#)Purpose:         Declarations for GETOPT(3) and GETSUBOPT(3)
X@(#)Author:          J Leffler
X@(#)Copyright:       JLSS (C) 1992-93,1996-97
X@(#)Product:         :PRODUCT:
X*/
X
X#ifndef GETOPT_H
X#define GETOPT_H
X
X#ifdef MAIN_PROGRAM
X#ifndef lint
Xstatic const char getopt_h[] = "@(#)$Id: getopt.h,v 1.10 1998/04/09 18:48:20 jleffler Exp $";
X#endif	/* lint */
X#endif	/* MAIN_PROGRAM */
X
X/*
X** GNU getopt provides facilities not available in standard getopt.
X** Specifically, it will reorder all option arguments before all non-option
X** arguments unless the environment variable _POSIX_OPTION_ORDER is
X** defined.  It can also handle optional arguments, which must be attached
X** to option letter on the command line, indicated by two colons after the
X** option letter.  It can be told to return all arguments in order, with a
X** value of '\0' indicating a file option by starting the options string
X** with a '-'.  It also has a different interface from standard getopt
X** because the second (argv) argument is not const.
X*/
X
X#ifdef USE_GNU_GETOPT
X#define GETOPT(argc, argv, opts)	gnu_getopt(argc, argv, opts)
X#define opterr	gnu_opterr
X#define optind	gnu_optind
X#define optarg	gnu_optarg
X#define optopt	gnu_optopt
X#else
X#define GETOPT(argc, argv, opts)	getopt(argc, argv, opts)
X#endif /* USE_GNU_GETOPT */
X
Xextern int      optopt;
Xextern int      opterr;
Xextern int      optind;
Xextern char    *optarg;
X
Xextern int      getopt(int argc, char *const*argv, const char *opts);
Xextern int      getsubopt(char **opt, char *const*names, char **value);
Xextern int      gnu_getopt(int argc, char **argv, const char *opts);
X
X#endif	/* GETOPT_H */
SHAR-EOF
chmod 440 getopt.h
if [ `wc -c <getopt.h` -ne 1772 ]
then echo shar: getopt.h unpacked with wrong size
fi
# end of overwriting check
fi
#--------------------
if [ -f range.h -a "$1" != "-c" ]
then echo shar: range.h already exists
else
echo 'x - range.h (1802 characters)'
sed -e 's/^X//' >range.h <<'SHAR-EOF'
X/*
X@(#)File:            $RCSfile: range.h,v $
X@(#)Version:         $Revision: 1.3 $
X@(#)Last changed:    $Date: 1997/06/02 16:24:26 $
X@(#)Purpose:         Declaration of range parsing functions
X@(#)Author:          J Leffler
X@(#)Copyright:       (C) JLSS 1997
X@(#)Product:         :PRODUCT:
X*/
X
X/*TABSTOP=4*/
X
X#ifndef RANGE_H
X#define RANGE_H
X
X#ifdef MAIN_PROGRAM
X#ifndef lint
Xstatic const char range_h[] = "@(#)$Id: range.h,v 1.3 1997/06/02 16:24:26 johnl Exp $";
X#endif	/* lint */
X#endif	/* MAIN_PROGRAM */
X
X/*
X** parse_range(): parse range of positive numbers.
X**
X** Given a string, parse_range() returns the lo and hi values corresponding
X** to the range specified by the string.  For example:
X**      Input:          Low             High
X**      23              23              23
X**      23-25           23              25
X**      23-             23              0
X**      -23             0               23
X** Any delimiter other than '-' before or after a number terminates the
X** scan.  Returns pointer to character after last character parsed (which
X** may or may not be '\0') if successful.  Otherwise, returns pointer to
X** str if it fails, and does not set *lo or *hi.
X*/
Xextern char    *parse_range(char *str, long *lo, long *hi);
X
X/*
X** numeric_range(): parse range of numbers, positive or negative.
X**
X**  Input:      Low     High
X**  23          23      23
X**  -23        -23     -23
X**  23:25       23      25
X**  23..25      23      25
X**  -23..-25   -25     -23
X**  -23..25    -23      25
X**  23..-25    -25      23
X**  Returns pointer to '\0' at end of string if OK, sets *lo and *hi,
X**  and guarantees *lo <= *hi.
X**  Otherwise, returns pointer to start of string and does not set *lo or *hi.
X*/
Xextern char    *numeric_range(char *str, long *lo, long *hi);
X
X#endif	/* RANGE_H */
SHAR-EOF
chmod 444 range.h
if [ `wc -c <range.h` -ne 1802 ]
then echo shar: range.h unpacked with wrong size
fi
# end of overwriting check
fi
#--------------------
if [ -f range2.c -a "$1" != "-c" ]
then echo shar: range2.c already exists
else
echo 'x - range2.c (1861 characters)'
sed -e 's/^X//' >range2.c <<'SHAR-EOF'
X/*
X@(#)File:            $RCSfile: range2.c,v $
X@(#)Version:         $Revision: 1.2 $
X@(#)Last changed:    $Date: 1997/06/02 16:41:57 $
X@(#)Purpose:         Decode string into range of integers.
X@(#)Author:          J Leffler
X@(#)Product:         :PRODUCT:
X*/
X
X/*TABSTOP=4*/
X/*LINTLIBRARY*/
X
X/*
X**  Input:      Low     High
X**  23          23      23
X**  -23        -23     -23
X**  23:25       23      25
X**  23..25      23      25
X**  -23..-25   -25     -23
X**  -23..25    -23      25
X**  23..-25    -25      23
X**  Any other delimiter after number (or before number) terminates input
X*/
X
X#include <stdlib.h>
X#include "range.h"
X
X#define NIL(x)	((x)0)
X
X#ifndef lint
Xstatic const char rcs[] = "@(#)$Id: range2.c,v 1.2 1997/06/02 16:41:57 johnl Exp $";
X#endif
X
X/*
X** Parse numeric range.
X** Return pointer to trailing '\0' if OK, else pointer to input string
X*/
Xchar *numeric_range(char *str, long *lo, long *hi)
X{
X	register char	*s = str;
X	char	*t;
X	long	l;
X	long	h;
X
X	l = strtol(s, &t, 10);
X	if (*t == '\0')
X	{
X		/* Just one number */
X		*lo = *hi = l;
X		return(t);
X	}
X
X	if (*t == ':')
X		t += 1;
X	else if (t[0] == '.' && t[1] == '.')
X		t += 2;
X	else
X	{
X		/* Format error */
X		return(str);
X	}
X
X	h = strtol(t, &t, 10);
X	if (*t != '\0')
X	{
X		/* Format error */
X		return(str);
X	}
X
X	if (h < l)
X	{
X		long x = h;
X		h = l;
X		l = x;
X	}
X
X	*lo = l;
X	*hi = h;
X
X	return(t);
X}
X
X#ifdef TEST
X#include <stdio.h>
X#include "stderr.h"
X
Xint main(int argc, char **argv)
X{
X	int	i;
X	long	lo;
X	long	hi;
X	char	*t;
X
X	setarg0(argv[0]);
X	if (argc <= 1)
X		usage("range [...]");
X	for (i = 1; i < argc; i++)
X	{
X		t = argv[i];
X		while (t != NIL(char *) && *t != '\0')
X		{
X			printf("Parse: %15s (addr = 0x%08lX) ", t, t);
X			fflush(stdout);
X			t = numeric_range(t, &lo, &hi);
X			printf("Range: %2d -> %2d (addr = 0x%08lX)\n", lo, hi, t);
X			fflush(stdout);
X		}
X	}
X	return(0);
X}
X#endif /* TEST */
SHAR-EOF
chmod 444 range2.c
if [ `wc -c <range2.c` -ne 1861 ]
then echo shar: range2.c unpacked with wrong size
fi
# end of overwriting check
fi
#--------------------
if [ -f stderr.c -a "$1" != "-c" ]
then echo shar: stderr.c already exists
else
echo 'x - stderr.c (7206 characters)'
sed -e 's/^X//' >stderr.c <<'SHAR-EOF'
X/*
X@(#)File:            $RCSfile: stderr.c,v $
X@(#)Version:         $Revision: 6.21 $
X@(#)Last changed:    $Date: 1998/04/07 19:09:04 $
X@(#)Purpose:         Error reporting routines -- using stdio
X@(#)Author:          J Leffler
X@(#)Copyright:       (C) JLSS 1988-91,1996-98
X@(#)Product:         :PRODUCT:
X*/
X
X/*TABSTOP=4*/
X/*LINTLIBRARY*/
X
X#include <errno.h>
X#include <stdio.h>
X#include <string.h>
X#include <stdlib.h>
X#include <stdarg.h>
X#include <sys/types.h>
X#include <time.h>
X#include <unistd.h>
X#include "stderr.h"
X
Xstatic char arg0[15] = "**undefined**";
Xstatic FILE *errout = stderr;
X
X#ifndef lint
Xstatic const char rcs[] = "@(#)$Id: stderr.c,v 6.21 1998/04/07 19:09:04 jleffler Exp $";
X#endif	/* lint */
X
X/* Change the definition of 'stderr', reporting on the old one too */
X/* NB: using err_stderr((FILE *)0) simply reports the current 'stderr' */
XFILE *err_stderr(FILE *newerr)
X{
X	FILE *old = errout;
X	if (newerr != (FILE *)0)
X		errout = newerr;
X	return(old);
X}
X
Xconst char *getarg0(void)
X{
X	return(arg0);
X}
X
Xvoid            remark2(const char *s1, const char *s2)
X{
X	err_report(ERR_REM, ERR_STAT, "%s %s\n", (s1), (s2));
X}
X
Xvoid            remark(const char *s1)
X{
X	err_report(ERR_REM, ERR_STAT, "%s\n", (s1));
X}
X
Xvoid            error2(const char *s1, const char *s2)
X{
X	err_report(ERR_ERR, ERR_STAT, "%s %s\n", (s1), (s2));
X}
X
Xvoid            error(const char *s1)
X{
X	err_report(ERR_ERR, ERR_STAT, "%s\n", (s1));
X}
X
Xvoid            stop(const char *s1)
X{
X	err_report(ERR_ABT, ERR_STAT, "%s\n", (s1));
X}
X
Xvoid            usage(const char *s1)
X{
X	err_report(ERR_USE, ERR_STAT, (s1));
X}
X
Xconst char *err_rcs_string(const char *s2, char *buffer, size_t buflen)
X{
X	const char *src = s2;
X	char *dst = buffer;
X	char *end = buffer + buflen - 1;
X
X	/*
X	** Bother RCS!  We've probably been given something like:
X	** "$Revision: 6.21 $ ($Date: 1998/04/07 19:09:04 $)"
X	** We only want to emit the revision number and the date/time.
X	** Skip the components between '$' and ': ', copy up to ' $',
X	** repeating as necessary.  And we have to test for overflow!
X	*/
X	while (*src != '\0' && dst < end)
X	{
X		while (*src != '\0' && *src != '$')
X		{
X			*dst++ = *src++;
X			if (dst >= end)
X				break;
X		}
X		if (*src == '$')
X			src++;
X		while (*src != '\0' && *src != ':' && *src != '$')
X			src++;
X		if (*src == '\0')
X			break;
X		if (*src == '$')
X		{
X			/* Unexpanded keyword '$Keyword$' notation */
X			src++;
X			continue;
X		}
X		if (*src == ':')
X			src++;
X		if (*src == ' ')
X			src++;
X		while (*src != '\0' && *src != '$')
X		{
X			*dst++ = *src++;
X			if (dst >= end)
X				break;
X		}
X		if (*src == '$')
X		{
X			if (*(dst-1) == ' ')
X				dst--;
X			src++;
X		}
X	}
X	*dst = '\0';
X	return(buffer);
X}
X
X/* Report version information, removing embedded RCS keyword strings (but not values) */
Xvoid version(const char *s1, const char *s2)
X{
X	char buffer[64];
X
X	if (strchr(s2, '$'))
X		s2 = err_rcs_string(s2, buffer, sizeof(buffer));
X	err_logmsg(stdout, ERR_ERR, EXIT_SUCCESS, "%s Version %s\n", s1, s2);
X}
X
X/* Store basename of command, excluding trailing slashes */
X/* Doesn't handle two pathological cases -- "/" and "" */
Xvoid            setarg0(const char *argv0)
X{
X	const char *cp;
X	size_t nbytes = sizeof(arg0) - 1;
X
X	if ((cp = strrchr(argv0, '/')) != (char *)0 && *(cp + 1) == '\0')
X    {
X        /* Skip backwards over trailing slashes */
X		const char *ep = cp;
X        while (ep > argv0 && *ep == '/')
X            ep--;
X        /* Skip backwards over non-slashes */
X		cp = ep;
X        while (cp > argv0 && *cp != '/')
X            cp--;
X		cp++;
X		nbytes = ep - cp + 1;
X		if (nbytes > sizeof(arg0) - 1)
X			nbytes = sizeof(arg0) - 1;
X    }
X	else if (cp != (char *)0)
X	{
X		/* Regular pathname containing slashes */
X		cp++;
X	}
X	else
X	{
X		/* Basename of file only */
X		cp = argv0;
X	}
X	strncpy(arg0, cp, nbytes);
X	arg0[nbytes] = '\0';
X}
X
X/* Format a time string for now (using ISO8601 format) */
X/* Allow for future settable time format with tm_format */
Xstatic char *err_time(void)
X{
X	static char buffer[32];
X	static const char tm_format[] = "%Y-%m-%d %H:%M:%S";
X	time_t  now;
X	struct tm *tp;
X
X	now = time((time_t *)0);
X	tp = localtime(&now);
X	strftime(buffer, sizeof(buffer), tm_format, tp);
X	return(buffer);
X}
X
X/* Most fundamental (and flexible) error message printing routine */
X/* Not singularly convenient for ordinary mortals -- see err_logmsg() */
Xvoid err_fprint(FILE *fp, int flags, int estat, const char *string, va_list args)
X{
X	int errnum = errno;		/* Capture errno before it is damaged! */
X	if (flags & ERR_FLUSH)
X		(void)fflush(stdout);
X	if (flags & ERR_USAGE)
X		(void)fprintf(fp, "Usage: %s %s\n", arg0, string);
X	else if (flags & ERR_COMM)
X	{
X		if ((flags & ERR_NOARG0) == 0)
X			(void)fprintf(fp, "%s: ", arg0);
X		if (flags & ERR_STAMP)
X			(void)fprintf(fp, "%s - ", err_time());
X		if (flags & ERR_PID)
X			(void)fprintf(fp, "pid=%d: ", (int)getpid());
X		(void)vfprintf(fp, string, args);
X		if (flags & ERR_ERRNO)
X			(void)fprintf(fp, "error (%d) %s\n", errnum, strerror(errnum));
X	}
X	(void)fflush(fp);
X	if (flags & ERR_ABORT)
X		abort();
X	if (flags & ERR_EXIT)
X		exit(estat);
X}
X
X/* Most convenient external interface to err_fprint() */
Xvoid err_logmsg(FILE *fp, int flags, int estat, const char *string, ...)
X{
X	va_list         args;
X
X	va_start(args, string);
X	err_fprint(fp, flags, estat, string, args);
X	va_end(args);
X}
X
X/* Cover function for err_fprint() using default output file (normally stderr) */
Xvoid err_print(int flags, int estat, const char *string, va_list args)
X{
X	err_fprint(errout, flags, estat, string, args);
X}
X
Xvoid            err_remark(const char *format, ...)
X{
X	va_list         args;
X
X	va_start(args, format);
X	err_print(ERR_REM, ERR_STAT, format, args);
X	va_end(args);
X}
X
Xvoid            err_error(const char *format, ...)
X{
X	va_list         args;
X
X	va_start(args, format);
X	err_print(ERR_ERR, ERR_STAT, format, args);
X	va_end(args);
X}
X
Xvoid            err_report(int flags, int estat, const char *string, ...)
X{
X	va_list         args;
X
X	va_start(args, string);
X	err_print(flags, estat, string, args);
X	va_end(args);
X}
X
X#ifdef TEST
X
Xstatic const char *list[] =
X{
X	"/usr/fred/bloggs",
X	"/usr/fred/bloggs/",
X	"/usr/fred/bloggs////",
X	"bloggs",
X	"/.",
X	".",
X	"/",
X	"//",
X	"///",
X	"////",
X	"",
X	(char *)0
X};
X
Xint main(int argc, char **argv)
X{
X	const char **name;
X	char *data;
X
X	setarg0(argv[0]);
X
X	err_logmsg(stdout, ERR_LOG, EXIT_SUCCESS, "testing ERR_LOG\n");
X	err_logmsg(stdout, ERR_STAMP|ERR_REM|ERR_FLUSH, EXIT_SUCCESS,
X				"testing ERR_STAMP\n");
X	err_logmsg(stdout, ERR_PID|ERR_REM|ERR_FLUSH, EXIT_SUCCESS,
X				"testing ERR_PID\n");
X	errno = EXDEV;
X	err_logmsg(stdout, ERR_ERRNO|ERR_REM|ERR_FLUSH, EXIT_SUCCESS,
X				"testing ERR_ERRNO\n");
X
X	remark("testing values for argv[0]");
X
X	for (name = list; *name != (char *)0; name++)
X	{
X		data = malloc(strlen(*name) + 1);
X		strcpy(data, *name);
X		printf("name = <<%s>>; ", *name);
X		setarg0(*name);
X		printf(" (<<%s>>) arg0 = <<%s>>\n", *name, getarg0());
X		free(data);
X	}
X
X	setarg0(argv[0]);
X	remark("reporting arguments to program");
X	while (*++argv != (char *)0)
X		remark2("next argument", *argv);
X
X	remark("reporting on version!");
X	version("STDERR", "$Revision: 6.21 $ ($Date: 1998/04/07 19:09:04 $)");
X	return(0);
X}
X
X#endif /* TEST */
SHAR-EOF
chmod 440 stderr.c
if [ `wc -c <stderr.c` -ne 7206 ]
then echo shar: stderr.c unpacked with wrong size
fi
# end of overwriting check
fi
#--------------------
if [ -f stderr.h -a "$1" != "-c" ]
then echo shar: stderr.h already exists
else
echo 'x - stderr.h (2378 characters)'
sed -e 's/^X//' >stderr.h <<'SHAR-EOF'
X/*
X@(#)File:           $RCSfile: stderr.h,v $
X@(#)Version:        $Revision: 6.17 $
X@(#)Last changed:   $Date: 1998/04/07 19:02:25 $
X@(#)Purpose:        Header file for standard error functions
X@(#)Author:         J Leffler
X@(#)Copyright:      (C) JLSS 1989-93,1996-98
X@(#)Product:        :PRODUCT:
X*/
X
X#ifndef STDERR_H
X#define STDERR_H
X
X#ifdef MAIN_PROGRAM
X#ifndef lint
Xstatic const char stderr_h[] = "@(#)$Id: stderr.h,v 6.17 1998/04/07 19:02:25 jleffler Exp $";
X#endif
X#endif
X
X#include <stdio.h>
X#include <stdarg.h>
X
X/* -- Definitions for error handling */
X
X#define ERR_STAT	(1)			/* Default exit status     */
X
X#define ERR_COMM	(0x0001)		/* Print message on stderr  */
X#define ERR_USAGE	(0x0002)		/* Print usage   on stderr  */
X#define ERR_EXIT	(0x0004)		/* Exit  -- do not return   */
X#define ERR_ABORT	(0x0008)		/* Abort -- do not return   */
X#define ERR_FLUSH	(0x0010)		/* Flush stdout             */
X#define ERR_STAMP	(0x0020)		/* Timestamp messages       */
X#define ERR_NOARG0	(0x0040)		/* Do not print arg0 prefix */
X#define ERR_PID		(0x0080)		/* Include pid=nnnnn info   */
X#define ERR_ERRNO	(0x0100)		/* Include system error     */
X
X/* -- Standard combinations of flags */
X
X#define ERR_USE	(ERR_USAGE|ERR_EXIT|ERR_FLUSH)
X#define ERR_REM	(ERR_COMM|ERR_FLUSH)
X#define ERR_ERR	(ERR_COMM|ERR_EXIT|ERR_FLUSH)
X#define ERR_ABT	(ERR_COMM|ERR_ABORT|ERR_FLUSH)
X#define ERR_LOG	(ERR_STAMP|ERR_PID|ERR_COMM|ERR_FLUSH)
X
X/* -- Global definitions */
X
Xextern const char *getarg0(void);
Xextern void setarg0(const char *argv0);
X
Xextern FILE *err_stderr(FILE *fp);
Xextern const char *err_rcs_string(const char *s, char *buffer, size_t buflen);
X
Xextern void err_error(const char *format, ...);
Xextern void err_fprint(FILE *fp, int flags, int estat, const char *string, va_list args);
Xextern void err_logmsg(FILE *fp, int flags, int estat, const char *string, ...);
Xextern void err_print(int flags, int estat, const char *string, va_list args);
Xextern void err_remark(const char *format, ...);
Xextern void err_report(int flags, int estat, const char *string, ...);
X
Xextern void error(const char *s1);
Xextern void error2(const char *s1, const char *s2);
Xextern void remark(const char *s1);
Xextern void remark2(const char *s1, const char *s2);
Xextern void stop(const char *s1);
Xextern void usage(const char *s1);
Xextern void version(const char *s1, const char *s2);
X
X#endif /* STDERR_H */
SHAR-EOF
chmod 440 stderr.h
if [ `wc -c <stderr.h` -ne 2378 ]
then echo shar: stderr.h unpacked with wrong size
fi
# end of overwriting check
fi
echo All files extracted
exit 0
