*BSD News Article 65115


Return to BSD News archive

Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!hobyah.cc.uq.oz.au!bunyip.cc.uq.oz.au!munnari.OZ.AU!news.ecn.uoknor.edu!qns3.qns.com!imci4!newsfeed.internetmci.com!news.kei.com!nntp.coast.net!frankensun.altair.com!wlbr!moe!sms
From: sms@moe.2bsd.com (Steven M. Schultz)
Subject: sys_errlist[] wastes 2kb of D-space [+fix] (#309 1 of 4)
Organization: GTE Government Systems, Westlake Village
Message-ID: <Dp4GGu.G3s@moe.2bsd.com>
Date: Sun, 31 Mar 1996 07:50:53 GMT
Lines: 1284

Subject: sys_errlist[] wastes 2kb of D-space [+fix] (#309 1 of 4)
Index:	lib/libc/gen/errlst.c+many,many_more 2.11BSD

Description:
	The array of system error message strings occupies approximately
	2kb of Data space in any program which calls perror(), strerror()
	or explicitly references sys_errlist[] or sys_nerr.   Since sys_errlist
	is initialized data it also occupies ~4 sectors of disk space in
	each program's executable disk image.
	
Repeat-By:
	Observation.  Or by compiling these test programs and using size(1):

		extern char *sys_errlist[];
		main() { char *cp; cp = sys_errlist[0]; exit(0); }

		cc x.c
		size a.out

		text	data	bss	dec	hex
		362	2042	4	2408	968

		main() { perror("foo"); exit(0); }

		cc y.c
		size a.out

		text	data	bss	dec	hex
		3310	2298	4	5668	1624

	In both cases the 'data' segment is 100% sys_errlist[]'s contribution.

	After applying the updates in this kit the second program's size is:

		text	data	bss	dec	hex
		1008	60	68	1136	470

Fix:
	This has been a project lurking in the background since mid 1994 when
	the effect of sys_errlist[] on program size was noticed (again).

	The fix in this case was to move the error message strings into
	a file.  Then the necessary routine to retrieve a specified error
	string was created and finally strerror() was modified to use the 
	new access method.  A utility program used to create the error string
	file was written.  This program is general enough that it can be used
	by any program which wants to place error message strings in a file.

	The fun part of course was crawling thru the system replacing *all*
	instances of 'sys_errlist[err]' with 'strerror(err)'. 

	NOTE:  sys_errlist (and sys_nerr) NO LONGER EXIST except in a 
	       compatibility library.  Use of these symbols will cause an
	       undefined symbol error at link time UNLESS the library
	       'errlst.a' is specified to "ld" using a '-lerrlst'.

	       New programs have been (or should have been) using 'strerror'
	       already.   Older programs need to be converted.  If for
	       some strange reason a program must waste D-space the error
	       strings are available as a link time option (mentioned above).

	Placing the error message strings in a disk file has almost zero
	effect on the performance of the system.  Why?  Because the strings
	are almost never referenced and even when they are used it is almost
	always immediately prior to a program exiting after reporting a (fatal)
	error!  The several extra syscalls used to retrieve an error string 
	are far out weighed by the savings of not having to read in ~2kb of 
	extra data when a program is loaded into memory.

	There are several benefits from having the error message strings
	external to programs:

		1) The executable image on disk is smaller.   In the case of
		   the root filesystem the savings about to between 80 and 
		   100kb.  This is a welcome saving, especially in the case of
		   the GENERIC system which normally uses a 4mb root.

		2) If new error messages are defined or the text of old
		   messages needs to be changed it is now possible to
		   do this without relinking every program in the system.

		3) The amount of free memory in the system is higher.  Programs
		   such as 'init', 'update', 'getty', 'sendmail' all take less
		   memory now.  Forking processes is quicker because there is
		   2kb less data to copy.

		4) Programs load quicker.  Some of the most frequently used
		   programs (such as 'cp' which went from "5632+2674+66" to 
		   "6016+746+110" for size) have almost no data segment at
		   all now.

	The update kit is organized into 4 parts:

		Patch (part)	Content
		------------	-------
		309 (1 of 4)	Introduction, Instructions, File removal script,
				and a shar archive containing new files to be
				added to the system.

		310 (2 of 4)	First of 3 patch files to be used in updating
				existing files on the system.

		311 (3 of 4)	Second of 3 patch files.

		312 (4 of 4)	Third of 3 patch files.

	To install the update first make sure you have all 4 parts.  Cut where
	indicated and save (as /tmp/309 /tmp/310 /tmp/311 and /tmp/312 for
	example).

	Before applying the patches it might be a good idea to scan the
	system for any lingering remnants of earlier patches.  This makes it
	much easier to spot any errors (rejected patches):

	find / \( -name '*~' -o -name '*.old' -o -name '*.rej' \) -ls

	I remove those files from the system periodically but you may wish
	to simply note their presence and timestamps for later comparisons.

	Then:

		cd /tmp
		sh 309

	If you do not mind removing files from the system during an update
	(you have current backups or are confident that everything will work)
	then:

		./remove.sh  remove

	otherwise, if you prefer to rename files to .old and take care of the
	deletion later:

		./remove.sh rename

	Next install the new files:

		sh new.shar

	The three patches are applied in the usual manner:

		patch -p0 < 310
		patch -p0 < 311
		patch -p0 < 312

	NOTE:  If you have removed (or tar+compress'd) some of the larger
	       less used programs in /usr/src/new the patching will encounter
	       errors.  These errors can be ignored if you do not plan on
	       using those programs again.

	       Two modules in the Ingres (/usr/ingres) system are updated,
	       if you do not have Ingres installed on your system then ignore
	       the errors from patch (but remember to apply the patch if you
	       later install Ingres on the system).

	NOTE:  The "hack" game now compiles and links without errors.  It 
	       may even run now ;-)

	The real fun now begins.  The liberrlst.a compatibility library
	is created, the C library is compiled+installed, the mkerrlst(1)
	program is compiled and installed, and finally the /etc/syserrlst file 
	is created.

		cd /usr/src/usr.lib/liberrlst
		make
		make install
		make clean

		cd /usr/src/lib/libc
		make
		make install
		make clean

		cd /usr/src/usr.bin/mkerrlst
		make
		make install
		make clean

		/usr/bin/mkerrlst

	NOTE:  mkerrlst(1) can do more than simply recreate /etc/syserrlst.
	       The manpage for mkerrlst(1), syserrlst(3) and syserrlst(5)
	       have lots of interesting information.

	At this point a number of man pages need to be reformatted.  The
	'whatis' database should also be rebuilt to reflect the new reality.
		
		cd /usr/src/man3
		/usr/man/manroff syserrlst.3 > syserrlst.0
		/usr/man/manroff perror.3 > perror.0
		install -m 444 perror.0 syserrlst.0 /usr/man/cat3
		cd /usr/man/cat3
		rm -f strerror.0
		ln perror.0 strerror.0

		cd /usr/src/man5
		/usr/manroff syserrlst.5 > syserrlst.0
		install -m 444 syserrlst.0 /usr/man/cat5

		/usr/lib/makewhatis

	The libc lint library changed so the lint directory needs to be
	updated:

		cd /usr/src/usr.bin/lint
		./libs

	sys_errlist[] is now safely restricted to exactly *two* places
	in the system:  mkerrlst(1) and liberrlst.a.  If at a future date new 
	error messages are added to the system only liberrlst.a and mkerrlst
	need to be recompiled.  ACTUALLY, mkerrlst can accept as input a
	normal text file with one error string per line - thus new messages
	could be added without recompiling *anything*.

	The system is now fully patched but no programs have realized any
	space savings.  To do this requires that they be recompiled with the
	new routines in libc.a.  This can be done on a case by case basis.
	It is interesting the first couple times to recompile a program
	such as 'cp' or 'rmdir' or even 'csh' and compare the before and
	after sizes - but this gets old after a while.  Or the entire system 
	can be recompiled from sources.  I did the latter for a couple reasons
	(changing from the hosts file to the resolver routines was one, testing
	the Makefiles in the system was the other).

	To recompile the world takes about 18 hours on an 11/73 with fairly
	quick disks (I'm using a 1.2GB HP3724S).  RD54 and RA81 based systems 
	will take a bit longer.
		
		cd /usr/src
		make
		make install
		make clean
		/usr/lib/sendmail -bz
		reboot

	Enjoy the new improved but smaller system!

	As always, these and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.

---------------------------cut here----------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	remove.sh
#	new.shar
# This archive created: Sat Mar 30 22:45:45 1996
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'remove.sh'
then
	echo shar: "will not over-write existing file 'remove.sh'"
else
sed 's/^Y//' << \SHAR_EOF > 'remove.sh'
Y#!/bin/sh
Y
Yif [ $# != 1 ]; then
Y	echo "Usage:"
Y	echo "$0 remove"
Y	echo "or"
Y	echo "$0 rename"
Y	exit 1
Yfi
Y
Yif [ $1 = "remove" ]; then
Y	echo "Performing file removals..."
Y	rm -f /usr/man/cat3/errlist.0
Y	rm -f /usr/man/cat3/sys.0
Y	rm -f /usr/man/cat3/sys_errlist.0
Y	rm -f /usr/man/cat3/sys_nerr.0
Y	rm -rf /usr/src/new/news
Y	rm -f /usr/src/ucb/pascal/pi/osubr.c
Y	rm -f /usr/src/games/hack/errlst.c
Y	rm -f /usr/src/lib/libc/gen/errlst.c
Y	rm -f /usr/src/lib/libc/gen/perror.c
Y	exit 0
Yfi
Y
Yif [ $1 = "rename" ]; then
Y	echo "Renaming files to .old ..."
Y	mv -f /usr/man/cat3/errlist.0 /usr/man/cat3/errlist.0.old
Y	mv -f /usr/man/cat3/sys.0 /usr/man/cat3/sys.0.old
Y	mv -f /usr/man/cat3/sys_errlist.0 /usr/man/cat3/sys_errlist.0.old
Y	mv -f /usr/man/cat3/sys_nerr.0 /usr/man/cat3/sys_nerr.0.old
Y	mv -rf /usr/src/new/news /usr/src/new/news.old
Y	mv -f /usr/src/ucb/pascal/pi/osubr.c /usr/src/ucb/pascal/pi/osubr.c.old
Y	mv -f /usr/src/games/hack/errlst.c /usr/src/games/hack/errlst.c.old
Y	mv -f /usr/src/lib/libc/gen/errlst.c /usr/src/lib/libc/gen/errlst.c.old
Y	mv -f /usr/src/lib/libc/gen/perror.c /usr/src/lib/libc/gen/perror.c.old
Y	exit 0
Yfi
Y
Yecho "Argument must be rename or remove"
Yexit 1
SHAR_EOF
chmod 755 'remove.sh'
fi
if test -f 'new.shar'
then
	echo shar: "will not over-write existing file 'new.shar'"
else
sed 's/^Y//' << \SHAR_EOF > 'new.shar'
Y#! /bin/sh
Y# This is a shell archive, meaning:
Y# 1. Remove everything above the #! /bin/sh line.
Y# 2. Save the resulting text in a file.
Y# 3. Execute the file with /bin/sh (not csh) to create:
Y#	/usr/src/usr.bin/mkerrlst
Y#	/usr/src/usr.lib/liberrlst
Y#	/usr/include/errlst.h
Y#	/usr/src/lib/libc/gen/perror.c
Y#	/usr/src/lib/libc/string/strerror.c
Y#	/usr/src/lib/libc/gen/syserrlst.c
Y#	/usr/src/man/man3/syserrlst.3
Y#	/usr/src/man/man5/syserrlst.5
Y# This archive created: Sat Mar 30 20:26:17 1996
Yexport PATH; PATH=/bin:/usr/bin:$PATH
Yif test ! -d '/usr/src/usr.bin/mkerrlst'
Ythen
Y	mkdir '/usr/src/usr.bin/mkerrlst'
Yfi
Ycd '/usr/src/usr.bin/mkerrlst'
Yif test -f 'Makefile'
Ythen
Y	echo shar: "will not over-write existing file 'Makefile'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'Makefile'
YX#
YX# Public Domain.  1996/3/14 - Steven Schultz
YX#
YX#	@(#)Makefile	1.0 (2.11BSD GTE) 1996/3/14
YX#
YXCFLAGS=	 -O
YXSEPFLAG= -i
YXSRCS=	mkerrlst.c
YXOBJS=	mkerrlst.o
YXMAN=	mkerrlst.0
YXMANSRC=	mkerrlst.1
YX
YXall: mkerrlst mkerrlst.0
YX
YXmkerrlst: ${OBJS}
YX	${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} -lerrlst
YX
YXmkerrlst.0: ${MANSRC}
YX	/usr/man/manroff ${MANSRC} > ${MAN}
YX
YXclean:
YX	rm -f ${OBJS} ${MAN} mkerrlst tags 
YX
YXdepend: ${SRCS}
YX	mkdep ${CFLAGS} ${SRCS}
YX
YXinstall: mkerrlst
YX	install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat1
YX	install -s -o root -g bin -m 755 mkerrlst ${DESTDIR}/usr/bin/mkerrlst
YX
YXlint: ${SRCS}
YX	lint -hax ${SRCS}
YX
YXtags: ${SRCS}
YX	ctags ${SRCS}
YX# DO NOT DELETE THIS LINE -- mkdep uses it.
YX# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
YSHAR_EOF
Ychmod 644 'Makefile'
Yfi
Yif test -f 'mkerrlst.1'
Ythen
Y	echo shar: "will not over-write existing file 'mkerrlst.1'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'mkerrlst.1'
YX.\" Public Domain, March 1996, Steven M. Schultz
YX.\"
YX.\"	@(#)mkerrlst.1	1.0 (2.11BSD) 1996/3/14
YX.\"
YX.TH MKERRLST 1  "March 14, 1996"
YX.UC 2
YX.SH NAME
YXmkerrlst \- create system error file
YX.SH SYNOPSIS
YX.B mkerrlst
YX[
YX.B \-i
YX.I inputfile
YX]
YX[
YX.B \-o
YX.I outputfile
YX]
YX.SH DESCRIPTION
YX.BR Mkerrlst (1)
YXcreates error message files in the format described by
YX.BR syserrlst (5).
YX.PP
YXWith no arguments
YX.B mkerrlst
YXcreates the file
YX.I /etc/syserrlst
YXfrom the internal array
YX.BR sys_errlist .
YX.PP
YXGive just the
YX.B \-o
YXoption 
YX.B mkerrlst
YXwill create the file
YX.I outputfile
YXfrom the internal array
YX.BR sys_errlist .
YX.PP
YXGiven just the
YX.B \-i
YXoption
YX.B mkerrlst
YXwill create the file
YX.I /etc/syserrlst
YXfrom the input file
YX.I inputfile.
YX.PP
YXGiven both
YX.B \-i
YXand 
YX.B \-o
YXoptions 
YX.B mkerrlst
YXwill create the error message file
YX.I outputfile
YXfrom the strings contained in
YX.I inputfile.
YX.PP
YX.B NOTE:
YXerror messages are numbered from 0.  If the error 0 does not have a
YXmessage associated with it the first string in
YX.I inputfile
YXmust still be present.
YX.SH "RETURN VALUE"
YX.B mkerrlst
YXexits with status of 0 if no errors are encountered.  If errors do occur
YXan error message is printed on 
YX.I stderr
YXand the exit status is 1.
YX.SH ERRORS
YX.BR mkerrlst (1)
YXcan encounter any of the errors for the
YX.BR open (2),
YX.BR lseek (2),
YX.BR read (2),
YXor
YX.BR write(2)
YXsystem calls.
YX.SH "SEE ALSO"
YXsyserrlst(3)
YXsyserrlst(5)
YX.SH HISTORY
YX.BR mkerrlst (1),
YXfirst appeared in 2.11BSD.
YX.SH BUGS
YXError messages can be a maximum of 80 characters.
YSHAR_EOF
Ychmod 644 'mkerrlst.1'
Yfi
Yif test -f 'mkerrlst.c'
Ythen
Y	echo shar: "will not over-write existing file 'mkerrlst.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'mkerrlst.c'
YX/*
YX *      Program Name:   mkerrlst.c
YX *      Date: March 5, 1996
YX *      Author: S.M. Schultz
YX *
YX *      -----------------   Modification History   ---------------
YX *      Version Date            Reason For Modification
YX *      1.0     05Mar96         1. Initial release into the public domain.
YX *	1.1	14Mar96		2. Add ability to take messages from a file
YX *				   in place of a fixed array.
YX*/
YX
YX/*
YX * mkerrlst - writes the error messages from sys_errlist[] or a input file of
YX *	      strings to a formatted file prepending a header for quick access.
YX *
YX * This code can be used as a template for creating additional error message
YX * files.  The "-o" option can be used to specify a different output file 
YX * than _PATH_SYSERRLST.  The "-i" option is used to specify an input file
YX * of error messages (one per line, maximum length 80 characters).  Error
YX * messages are numbered starting at 0.
YX *
YX * If no "-i" option is used the sys_errlist[] array is used by default.
YX*/
YX
YX#include <stdio.h>
YX#include <stdlib.h>
YX#include <sys/types.h>
YX#include <sys/uio.h>
YX#include <fcntl.h>
YX#include <errlst.h>
YX#include <string.h>
YX
YX	int	outf;
YX	struct	iovec	iov[2];
YX	off_t	msgoff;
YX	char	*outfn, *infn, *msg, *getmsg();
YX	struct	ERRLSTHDR	ehdr;
YX	FILE	*infp;
YX
YXextern	char	*__progname;
YXextern	char	*sys_errlist[];
YXextern	int	sys_nerr;
YX
YXmain(argc,argv)
YX	{
YX	register int	c;
YX	int	len, maxlen = -1;
YX
YX	while	((c = getopt(argc, argv, "o:i:")) != EOF)
YX		{
YX		switch	(c)
YX			{
YX			case	'o':
YX				outfn = optarg;
YX				break;
YX			case	'i':
YX				infn = optarg;
YX				break;
YX			case	'?':
YX			default:
YX				usage();
YX			}
YX		}
YX
YX	if	(!outfn)
YX		outfn = _PATH_SYSERRLST;
YX
YX	if	((outf = open(outfn, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
YX		err(1, "can't create %s", outfn);
YX	if	(fchmod(outf, 0644) < 0)
YX		err(1, "fchmod(%d,644)", outf);
YX
YX	if	(infn)
YX		{
YX		infp = fopen(infn, "r");
YX		if	(!infp)
YX			err(1, "fopen(%s, r) failed\n", infn);
YX		}
YX
YX	for	(c = 0; msg = getmsg(c, infp); c++)
YX		{
YX		len = strlen(msg);
YX		if	(len > maxlen)
YX			maxlen = len;
YX		}
YX
YX	if	(infp)
YX		rewind(infp);
YX
YX/*
YX * Adjust the count so that the int written to the file is the highest valid
YX * message number rather than the number of the first invalid error number.
YX *
YX * At the present time nothing much uses the maximum message length.
YX*/
YX	ehdr.magic = ERRMAGIC;
YX	ehdr.maxmsgnum = c - 1;
YX	ehdr.maxmsglen = maxlen;
YX	if	(write(outf, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
YX		err(1, "write");
YX
YX	msgoff = sizeof (ehdr) + ((off_t)sizeof (struct ERRLST) * sys_nerr);
YX	iov[0].iov_base = (caddr_t)&msgoff;
YX	iov[0].iov_len = sizeof (off_t);
YX
YX	iov[1].iov_len = sizeof (int);
YX
YX	for	(c = 0; msg = getmsg(c, infp); c++)
YX		{
YX		len = strlen(msg);
YX		iov[1].iov_base = (caddr_t)&len;
YX		writev(outf, iov, 2);
YX		msgoff += len;
YX		msgoff++;		/* \n between messages */
YX		}
YX
YX	iov[1].iov_base = "\n";
YX	iov[1].iov_len = 1;
YX
YX	if	(infp)
YX		rewind(infp);
YX
YX	for	(c = 0; msg = getmsg(c, infp); c++)
YX		{
YX		iov[0].iov_base = msg;
YX		iov[0].iov_len = strlen(iov[0].iov_base);
YX		writev(outf, iov, 2);
YX		}
YX	close(outf);
YX	if	(infp)
YX		fclose(infp);
YX	exit(0);
YX	}
YX
YXchar *
YXgetmsg(c, fp)
YX	int	c;
YX	FILE	*fp;
YX	{
YX	static	char	buf[81];
YX	register char	*cp;
YX
YX	if	(fp)
YX		{
YX		cp = fgets(buf, sizeof (buf) - 1, fp);
YX		if	(!cp)
YX			return(NULL);
YX		cp = index(buf, '\n');
YX		if	(cp)
YX			*cp = '\0';
YX		return(buf);
YX		}
YX	if	(c < sys_nerr)
YX		return(sys_errlist[c]);
YX	return(NULL);
YX	}
YX
YXusage()
YX	{
YX	fprintf(stderr, "usage: %s -o filename\n", __progname);
YX	exit(1);
YX	}
YSHAR_EOF
Ychmod 644 'mkerrlst.c'
Yfi
Ychmod 755 .
Ycd ..
Yif test ! -d '/usr/src/usr.lib/liberrlst'
Ythen
Y	mkdir '/usr/src/usr.lib/liberrlst'
Yfi
Ycd '/usr/src/usr.lib/liberrlst'
Yif test -f 'errlst.c'
Ythen
Y	echo shar: "will not over-write existing file 'errlst.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'errlst.c'
YX/*
YX * Copyright (c) 1982, 1985, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if defined(LIBC_SCCS) && !defined(lint)
YXstatic char sccsid[] = "@(#)errlst.c	8.2.1 (2.11BSD) 1996/3/29";
YX#endif /* LIBC_SCCS and not lint */
YX
YXchar *sys_errlist[] = {
YX	"Undefined error: 0",			/*  0 - ENOERROR */
YX	"Operation not permitted",		/*  1 - EPERM */
YX	"No such file or directory",		/*  2 - ENOENT */
YX	"No such process",			/*  3 - ESRCH */
YX	"Interrupted system call",		/*  4 - EINTR */
YX	"Input/output error",			/*  5 - EIO */
YX	"Device not configured",		/*  6 - ENXIO */
YX	"Argument list too long",		/*  7 - E2BIG */
YX	"Exec format error",			/*  8 - ENOEXEC */
YX	"Bad file descriptor",			/*  9 - EBADF */
YX	"No child processes",			/* 10 - ECHILD */
YX	"No more processes",			/* 11 - EAGAIN */
YX	"Cannot allocate memory",		/* 12 - ENOMEM */
YX	"Permission denied",			/* 13 - EACCES */
YX	"Bad address",				/* 14 - EFAULT */
YX	"Block device required",		/* 15 - ENOTBLK */
YX	"Device busy",				/* 16 - EBUSY */
YX	"File exists",				/* 17 - EEXIST */
YX	"Cross-device link",			/* 18 - EXDEV */
YX	"Operation not supported by device",	/* 19 - ENODEV */
YX	"Not a directory",			/* 20 - ENOTDIR */
YX	"Is a directory",			/* 21 - EISDIR */
YX	"Invalid argument",			/* 22 - EINVAL */
YX	"Too many open files in system",	/* 23 - ENFILE */
YX	"Too many open files",			/* 24 - EMFILE */
YX	"Inappropriate ioctl for device",	/* 25 - ENOTTY */
YX	"Text file busy",			/* 26 - ETXTBSY */
YX	"File too large",			/* 27 - EFBIG */
YX	"No space left on device",		/* 28 - ENOSPC */
YX	"Illegal seek",				/* 29 - ESPIPE */
YX	"Read-only file system",		/* 30 - EROFS */
YX	"Too many links",			/* 31 - EMLINK */
YX	"Broken pipe",				/* 32 - EPIPE */
YX
YX/* math software */
YX	"Numerical argument out of domain",	/* 33 - EDOM */
YX	"Result too large",			/* 34 - ERANGE */
YX
YX/* non-blocking and interrupt i/o */
YX	"Resource temporarily unavailable",	/* 35 - EWOULDBLOCK */
YX	"Operation now in progress",		/* 36 - EINPROGRESS */
YX	"Operation already in progress",	/* 37 - EALREADY */
YX
YX/* ipc/network software -- argument errors */
YX	"Socket operation on non-socket",	/* 38 - ENOTSOCK */
YX	"Destination address required",		/* 39 - EDESTADDRREQ */
YX	"Message too long",			/* 40 - EMSGSIZE */
YX	"Protocol wrong type for socket",	/* 41 - EPROTOTYPE */
YX	"Protocol not available",		/* 42 - ENOPROTOOPT */
YX	"Protocol not supported",		/* 43 - EPROTONOSUPPORT */
YX	"Socket type not supported",		/* 44 - ESOCKTNOSUPPORT */
YX	"Operation not supported",		/* 45 - EOPNOTSUPP */
YX	"Protocol family not supported",	/* 46 - EPFNOSUPPORT */
YX						/* 47 - EAFNOSUPPORT */
YX	"Address family not supported by protocol family",
YX	"Address already in use",		/* 48 - EADDRINUSE */
YX	"Can't assign requested address",	/* 49 - EADDRNOTAVAIL */
YX
YX/* ipc/network software -- operational errors */
YX	"Network is down",			/* 50 - ENETDOWN */
YX	"Network is unreachable",		/* 51 - ENETUNREACH */
YX	"Network dropped connection on reset",	/* 52 - ENETRESET */
YX	"Software caused connection abort",	/* 53 - ECONNABORTED */
YX	"Connection reset by peer",		/* 54 - ECONNRESET */
YX	"No buffer space available",		/* 55 - ENOBUFS */
YX	"Socket is already connected",		/* 56 - EISCONN */
YX	"Socket is not connected",		/* 57 - ENOTCONN */
YX	"Can't send after socket shutdown",	/* 58 - ESHUTDOWN */
YX	"Too many references: can't splice",	/* 59 - ETOOMANYREFS */
YX	"Operation timed out",			/* 60 - ETIMEDOUT */
YX	"Connection refused",			/* 61 - ECONNREFUSED */
YX
YX	"Too many levels of symbolic links",	/* 62 - ELOOP */
YX	"File name too long",			/* 63 - ENAMETOOLONG */
YX
YX/* should be rearranged */
YX	"Host is down",				/* 64 - EHOSTDOWN */
YX	"No route to host",			/* 65 - EHOSTUNREACH */
YX	"Directory not empty",			/* 66 - ENOTEMPTY */
YX
YX/* quotas & mush */
YX	"Too many processes",			/* 67 - EPROCLIM */
YX	"Too many users",			/* 68 - EUSERS */
YX	"Disc quota exceeded",			/* 69 - EDQUOT */
YX
YX/* Network File System */
YX	"Stale NFS file handle",		/* 70 - ESTALE */
YX	"Too many levels of remote in path",	/* 71 - EREMOTE */
YX	"RPC struct is bad",			/* 72 - EBADRPC */
YX	"RPC version wrong",			/* 73 - ERPCMISMATCH */
YX	"RPC prog. not avail",			/* 74 - EPROGUNAVAIL */
YX	"Program version wrong",		/* 75 - EPROGMISMATCH */
YX	"Bad procedure for program",		/* 76 - EPROCUNAVAIL */
YX
YX	"No locks available",			/* 77 - ENOLCK */
YX	"Function not implemented",		/* 78 - ENOSYS */
YX	"Inappropriate file type or format",	/* 79 - EFTYPE */
YX	"Authentication error",			/* 80 - EAUTH */
YX	"Need authenticator",			/* 81 - ENEEDAUTH */
YX};
YXint sys_nerr = sizeof(sys_errlist) / sizeof(sys_errlist[0]);
YSHAR_EOF
Ychmod 644 'errlst.c'
Yfi
Yif test -f 'Makefile'
Ythen
Y	echo shar: "will not over-write existing file 'Makefile'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'Makefile'
YX#
YX# Public Domain.  1996/3/20 - Steven Schultz
YX#
YX#	@(#)Makefile	1.0 (2.11BSD GTE) 1996/3/20
YX#
YXDEFS=
YXCFLAGS=-O $(DEFS)
YXTAGSFILE=tags
YX
YXall: liberrlst.a liberrlst_p.a
YX
YXliberrlst.a: errlst.c
YX	${CC} -c ${CFLAGS} errlst.c
YX	ld -r -X -o liberrlst.a errlst.o
YX	rm -f errlst.o
YX
YXliberrlst_p.a: errlst.c
YX	${CC} -p -c ${CFLAGS} errlst.c
YX	ld -r -X -o liberrlst_p.a errlst.o
YX	rm -f errlst.o
YX
YXinstall: all
YX	install -m 644 liberrlst.a $(DESTDIR)/usr/lib
YX	install -m 644 liberrlst_p.a $(DESTDIR)/usr/lib
YX
YXtags:
YX	ctags -a -f ${TAGSFILE} `pwd`/errlst.c
YX
YXclean:
YX	rm -f *.o liberrlst.a liberrlst_p.a
YSHAR_EOF
Ychmod 644 'Makefile'
Yfi
Ychmod 755 .
Ycd ..
Yif test -f '/usr/include/errlst.h'
Ythen
Y	echo shar: "will not over-write existing file '/usr/include/errlst.h'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/include/errlst.h'
YX/*
YX *      Program Name:   errlst.h
YX *      Date: March 6, 1996
YX *      Author: S.M. Schultz
YX *
YX *      -----------------   Modification History   ---------------
YX *      Version Date            Reason For Modification
YX *      1.0     05Mar96         1. Initial release into the public domain.
YX*/
YX
YX/*
YX * Definitions used by the 'mkerrlst' program which creates error message 
YX * files.
YX *
YX * The format of the file created is:
YX *
YX *	struct	ERRLSTHDR	ehdr;
YX *	struct	ERRLST  emsg[num_of_msgs];
YX *	struct	{
YX *		char	msg[] = "error message string";
YX *		char	lf = '\n';
YX *		} [num_of_messages];
YX *
YX * Note:  the newlines are NOT included in the message lengths, the newlines
YX *        are present to make it easy to 'cat' or 'vi' the file.
YX*/
YX
YX	struct	ERRLSTHDR
YX		{
YX		short	magic;
YX		short	maxmsgnum;
YX		short	maxmsglen;
YX		short	pad[5];		/* Reserved */
YX		};
YX
YX	struct	ERRLST
YX		{
YX		off_t	offmsg;
YX		short	lenmsg;
YX		};
YX
YX#define	ERRMAGIC	012345
YX#define	_PATH_SYSERRLST	"/etc/syserrlst"
YSHAR_EOF
Ychmod 644 '/usr/include/errlst.h'
Yfi
Yif test -f '/usr/src/lib/libc/gen/perror.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/lib/libc/gen/perror.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/lib/libc/gen/perror.c'
YX/*
YX * Copyright (c) 1988, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if defined(LIBC_SCCS) && !defined(lint)
YXstatic char sccsid[] = "@(#)perror.c	8.1 (Berkeley) 6/4/93";
YX#endif /* LIBC_SCCS and not lint */
YX
YX#include <sys/types.h>
YX#include <sys/uio.h>
YX#include <unistd.h>
YX#include <errno.h>
YX#include <stdio.h>
YX#include <string.h>
YX
YXvoid
YXperror(s)
YX	char *s;
YX{
YX	register struct iovec *v;
YX	struct iovec iov[4];
YX
YX	v = iov;
YX	if (s && *s) {
YX		v->iov_base = (char *)s;
YX		v->iov_len = strlen(s);
YX		v++;
YX		v->iov_base = ": ";
YX		v->iov_len = 2;
YX		v++;
YX	}
YX	v->iov_base = strerror(errno);
YX	v->iov_len = strlen(v->iov_base);
YX	v++;
YX	v->iov_base = "\n";
YX	v->iov_len = 1;
YX	(void)writev(STDERR_FILENO, iov, (v - iov) + 1);
YX}
YSHAR_EOF
Ychmod 644 '/usr/src/lib/libc/gen/perror.c'
Yfi
Yif test -f '/usr/src/lib/libc/string/strerror.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/lib/libc/string/strerror.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/lib/libc/string/strerror.c'
YX/*
YX * Copyright (c) 1988, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if defined(LIBC_SCCS) && !defined(lint)
YXstatic char sccsid[] = "@(#)strerror.c	8.1.1 (2.11BSD) 1996/3/15";
YX#endif /* LIBC_SCCS and not lint */
YX
YX#include <string.h>
YX
YXchar *
YXstrerror(num)
YX	int num;
YX{
YX#define	UPREFIX	"Unknown error: "
YX	static char ebuf[30] = UPREFIX;		/* 32-bit number + slop */
YX	register unsigned int errnum;
YX	register char *p, *t;
YX	char tmp[20];
YX
YX	errnum = num;				/* convert to unsigned */
YX	if (p = syserrlst(errnum))
YX		return(p);
YX
YX	/* Do this by hand, so we don't include stdio(3). */
YX	t = tmp;
YX	do {
YX		*t++ = '0' + (errnum % 10);
YX	} while (errnum /= 10);
YX	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
YX		*p++ = *--t;
YX		if (t <= tmp)
YX			break;
YX	}
YX	return(ebuf);
YX}
YSHAR_EOF
Ychmod 644 '/usr/src/lib/libc/string/strerror.c'
Yfi
Yif test -f '/usr/src/lib/libc/gen/syserrlst.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/lib/libc/gen/syserrlst.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/lib/libc/gen/syserrlst.c'
YX/*
YX *      Program Name:   syserrlst.c
YX *      Date: March 6, 1996
YX *      Author: S.M. Schultz
YX *
YX *      -----------------   Modification History   ---------------
YX *      Version Date            Reason For Modification
YX *      1.0     06Mar96         1. Initial release into the public domain.
YX*/
YX
YX/*
YX * syserrlst - reads an error message from _PATH_SYSERRLST to a static
YX *	       buffer.
YX *
YX * __errlst - same as above but the caller must specify an error list file.
YX*/
YX
YX#include <stdio.h>
YX#include <stdlib.h>
YX#include <sys/types.h>
YX#include <sys/file.h>
YX#include <sys/uio.h>
YX#include <fcntl.h>
YX#include <errno.h>
YX#include <errlst.h>
YX
YXstatic	char	msgstr[64];
YX	char	*__errlst();
YX
YXchar *
YXsyserrlst(err)
YX	int	err;
YX	{
YX
YX	return(__errlst(err, _PATH_SYSERRLST));
YX	}
YX
YX/*
YX * Returns NULL if an error is encountered.  It is the responsiblity of the
YX * caller (strerror(3) is most cases) to convert NULL into a "Error N".
YX*/
YX
YXchar *
YX__errlst(err, path)
YX	int	err;
YX	char	*path;
YX	{
YX	register int	f;
YX	register char	*retval = NULL;
YX	int	saverrno;
YX	struct	iovec	iov[2];
YX	off_t	off;
YX	struct	ERRLST	emsg;
YX	struct	ERRLSTHDR ehdr;
YX
YX	saverrno = errno;
YX	f = open(path, O_RDONLY);
YX	if	(f < 0 || !path)
YX		goto oops;
YX
YX	if	(read(f, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
YX		goto oops;
YX
YX	if	(err < 0 || err > ehdr.maxmsgnum || ehdr.maxmsgnum <= 0 ||
YX		 ehdr.magic != ERRMAGIC)
YX		goto	oops;
YX
YX	off = sizeof (ehdr) + ((off_t)sizeof (struct ERRLST) * err);
YX	if	(lseek(f, off, L_SET) == (off_t)-1)
YX		goto oops;
YX
YX	if	(read(f, &emsg, sizeof (emsg)) != sizeof (emsg))
YX		goto oops;
YX
YX	if	(emsg.lenmsg >= sizeof (msgstr))
YX		emsg.lenmsg = sizeof (msgstr) - 1;
YX	
YX	if	(lseek(f, emsg.offmsg, L_SET) == (off_t)-1)
YX		goto oops;
YX
YX	if	(read(f, msgstr, emsg.lenmsg) != emsg.lenmsg)
YX		goto oops;
YX
YX	retval = msgstr;
YX	retval[emsg.lenmsg] = '\0';
YXoops:
YX	if	(f >= 0)
YX		close(f);
YX	errno = saverrno;
YX	return(retval);
YX	}
YSHAR_EOF
Ychmod 644 '/usr/src/lib/libc/gen/syserrlst.c'
Yfi
Yif test -f '/usr/src/man/man3/syserrlst.3'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/man/man3/syserrlst.3'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/man/man3/syserrlst.3'
YX.\" Public Domain, March 1996, Steven M. Schultz
YX.\"
YX.\"	@(#)syserrlst.3	1.1 (2.11BSD) 1996/3/26
YX.\"
YX.TH SYSERRLST 3  "March 26, 1996"
YX.UC 2
YX.SH NAME
YXsyserrlst, __errlst \- read system error messages from file
YX.SH SYNOPSIS
YX.nf
YX.B char *
YX.B syserrlst(err)
YX.B int err;
YX.PP
YX.B char *
YX.B __errlst(err, path);
YX.B int err;
YX.B char *path;
YX.fi
YX.SH DESCRIPTION
YX.BR Syserrlst (3)
YXreads the error message string corresponding to \fIerr\fP from the
YXfile \fI/etc/syserrlst\fP.
YX.PP
YX.BR __errlst(3)
YXreads the error message string corresponding to \fIerr\fP from the
YXfile \fIpath\fP.  The file \fIpath\fP must be in the format described
YXin 
YX.BR syserrlst (5).
YX.PP
YX.B NULL
YXis returned if \fIerr\fP is out of bounds (negative or greater than the
YXhighest message number in \fI/etc/syserrlst\fP or \fIpath\fP) or if the
YXerror message file can not be opened.  It is the
YXresponsibility of the caller (\fBstrerror\fP(3))
YXto check for and properly handle the \fINULL\fP return.
YX.SH "RETURN VALUE"
YX.B NULL
YXif an error was encountered in opening the error message file, if the
YXerror was out of bounds, or if the file did not start with the correct
YXmagic number.  Otherwise a 
YX.B "char *"
YXis returned pointing to a static buffer containing the text of the error
YXmessage.
YX.SH ERRORS
YX.BR syserrlst (3)
YXand
YX.BR __errlst (3)
YXcan return any of the errors for the
YX.BR open (2),
YX.BR lseek (2),
YXor
YX.BR read (2)
YXsystem calls.
YX.SH "SEE ALSO"
YXperror(3),
YXstrerror(3),
YXsyserrlst(5)
YX.SH HISTORY
YX.BR syserrlst (3),
YXand
YX.BR __errlst (3)
YXwere created for 2.11BSD with the aim of saving 2kb of \fBData\fP space
YXin programs which called 
YX.BR perror (3),
YXor
YX.BR strerror (3).
YX.SH BUGS
YXThe information is stored in a static buffer.
YSHAR_EOF
Ychmod 644 '/usr/src/man/man3/syserrlst.3'
Yfi
Yif test -f '/usr/src/man/man5/syserrlst.5'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/man/man5/syserrlst.5'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/man/man5/syserrlst.5'
YX.\" Public Domain, March 196, Steven M. Schultz
YX.\"
YX.\"	@(#)syserrlst.5	1.0 (2.11BSD) 1996/3/7
YX.\"
YX.TH SYSERRLST 5  "March 7, 1996"
YX.UC 2
YX.SH NAME
YXsyserrlst \- error message file format
YX.SH DESCRIPTION
YX.IR mkerrlst (1),
YXcreates error message files in the format described below.
YX.PP
YXAn ``error message file'' consists of a header, an array of structures
YXspecifying the offset and length of each message, and the array of
YXmessage strings separated by newlines.
YX.PP
YXThe message strings are separated by newlines but the newline characters
YXare \fBnot\fP included in the size of the message.  These newline characters
YXserve only to make the file editable or printable (after stripping off the
YXheader).
YX.PP
YXThe file format is:
YX.PP
YX.nf
YX.cs R 20
YX/*
YX * Definitions used by the 'mkerrlst' program which creates error message 
YX * files.
YX *
YX * The format of the file created is:
YX *
YX *	struct	ERRLSTHDR ehdr;
YX *	struct	ERRLST  emsg[num_of_messages];
YX *	struct	{
YX *		char	msg[] = "error message string";
YX *		char	lf = '\n';
YX *		} [num_of_messages];
YX *
YX * Note:  the newlines are NOT included in the message lengths, the newlines
YX *        are present to make it easy to 'cat' or 'vi' the file.
YX*/
YX
YX	struct	ERRLSTHDR
YX		{
YX		short	magic;
YX		short	maxmsgnum;
YX		short	maxmsglen;
YX		short	pad[5];		/* Reserved */
YX		};
YX
YX	struct	ERRLST
YX		{
YX		off_t	offmsg;
YX		short	lenmsg;
YX		};
YX
YX#define	ERRMAGIC	012345
YX.fi
YX.cs R
YX.SH "SEE ALSO"
YXmkerrlst(1), syserrlst(3)
YX.SH BUGS
YXFormat of the file isn't necessarily portable between machines.
YX.SH HISTORY
YXThis file format is new with 2.11BSD.
YSHAR_EOF
Ychmod 644 '/usr/src/man/man5/syserrlst.5'
Yfi
Yexit 0
Y#	End of shell archive
SHAR_EOF
chmod 644 'new.shar'
fi
exit 0
#	End of shell archive