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/man/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/man/man5 /usr/man/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 YX#include YX#include YX#include YX#include YX#include YX#include 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 YX#include YX#include YX#include YX#include YX#include 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 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 YX#include YX#include YX#include YX#include YX#include YX#include YX#include 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