My error-handling library and ANSI prototypes (Part 1/2)

Bennett Todd bet at dukeac.UUCP
Sat Feb 4 11:49:49 AEST 1989


: This is a sharchive -- extract the files by running through sh.
echo x - README
sed 's/^X//' <<\Shar_Eof >README
XThis is the first release of the Bent utility library. See intro(3b) for
Xinformation on the functions provided. As distributed this package installs
Xand runs on my Sun 3 systems running SunOS 3.5. I expect that everything
Xexcept maybe a few details in bent-stdio.h will work with few changes in any
XBSD 4.2 or greater system; the guts of it should be extremely portable.
XOutside of BSD the getdtablesize() call might have to be replaced with some
Xdefine out of a header file to identify the number of available file
Xdescriptors; if they aren't guaranteed to be low integers from [0..MAX] for
Xsome compile-time-fixed MAX then some more sophisticated associative scheme
Xwill be necessary to maintain the _bentio_filename_table. I haven't checked
Xthe #else clauses in the #ifdef __STDC__ definitions for a while; it is
Xpossible some have drifted (I use gcc; I am expecting to rip out the sop for
Xobsolete compilers in the future).
X
XI am well aware that some folks won't like the bent-stdio.h approach of
X#including everything in the universe; that could be done away with. I
Xprefer not having to bother with keeping track of which things need to be
Xincluded for various system functions.
X
XI have added e* routines as I have needed them; in principle I expect to end
Xup with e* wrappers around the majority of section 2 and section 3 routines.
XAs I find other generally-useful-to-me routines I expect to add them in.
XThis is basically the collection of oddments that I like to have on hand
Xbecause I don't like to have to keep rewriting them, and I want them in one
Xplace so that I don't have to go find all the copies of the source when I
Xfix a bug.
X
XNote that I edit with tabstops every 4 columns, so except for tabular stuff
Xin man pages all the alignment will be off if you look at it with default
Xtabstops every 8 columns.
X
XPorting to systems that haven't got >14 character long filenames, that don't
Xtake long C identifiers, that don't have the UNIX complement of text
Xprocessing tools (egrep and sed and like that), or are otherwise more
Xsubstantially different from BSD UNIX will probably take some little effort.
XI don't program in such environments myself or I would have done this
Xalready; if anyone does anything to fix bugs or improve portability of this
Xlibrary I would appreciate it if they sent me the fixes, and I will attempt
Xto incorporate them into future releases.
X
XAs for installation, if you are on a Sun you can adjust the directory names
Xfor installation in Makefile and run make, followed by make install (you
Xmight want to run make -n install first to ensure that you like the approach
XI take to installing the files). If not, best of luck. The only really
Xtricky thing I have is the mkprototypes script, which uses egrep and sed to
Xsynthesize function prototypes for a file, and more sed abuse to turn them
Xinto declarations. Note that these scripts are extremely sensitive to
Xtypographical layout of function declarations! I have included a "bent.h" in
Xthe distribution that matches the functions as they currently are defined;
Xif mkprototypes doesn't work on your system then you can start with that
Xbent.h and manually adjust it to match whenever you add or change a routine.
X
X-Bennett (bet at orion.mc.duke.edu)
Shar_Eof
echo x - Makefile
sed 's/^X//' <<\Shar_Eof >Makefile
X# If you have a repository for local stuff (on our system /usr/local) which
X# contains .../lib for /usr/lib type stuff, .../include for header files, and
X# .../man for man pages (on Suns and 4.3 BSD systems you can have a local
X# heirarchy by setting the MANPATH environment variable) then you can set ROOT
X# to that location and all the target directories will be fixed.  Otherwise set
X# LIBDIR, INCDIR, and MANDIR properly. Note that *.3b will be installed in
X# $(MANDIR)/man3, and "catman -M $(MANDIR)" will be invoked.
X
XROOT=/usr/local
XLIBDIR=$(ROOT)/lib
XINCDIR=$(ROOT)/include
XMANDIR=$(ROOT)/man
X
X# The following are how Bennett approaches the task of compiling C programs
XCC=gcc
XCFLAGS=-O -g -Wall -Wwrite-strings -msoft-float -fstrength-reduce -finline-functions -I.
X
XSRC=eclose.c efclose.c efdopen.c efflush.c efgets.c efopen.c efprintf.c \
X	efread.c efree.c efseek.c efwrite.c emalloc.c emkstemp.c eopen.c \
X	eprintf.c eputchar.c erealloc.c error.c etruncate.c eunlink.c ewrite.c \
X	getline.c max.c min.c progname.c putline.c readfile.c standrand.c \
X	strdup.c syntax.c
X
XOBJ=eclose.o efclose.o efdopen.o efflush.o efgets.o efopen.o efprintf.o \
X	efread.o efree.o efseek.o efwrite.o emalloc.o emkstemp.o eopen.o \
X	eprintf.o eputchar.o erealloc.o error.o etruncate.o eunlink.o ewrite.o \
X	getline.o max.o min.o progname.o putline.o readfile.o standrand.o \
X	strdup.o syntax.o \
X	filename_tab.o
X
XSHAR1=README Makefile VERSION bent.header eclose.c efclose.c efdopen.c \
X	  efflush.c efgets.c efopen.c efprintf.c efread.c efree.c efseek.c \
X	  efwrite.c emalloc.c emkstemp.c eopen.c eprintf.c eputchar.c erealloc.c \
X	  error.3b error.c etruncate.c eunlink.c ewrite.c getdtablesize.c \
X	  getline.3b getline.c intro.3b max.3b max.c min.c mkprototypes \
X	  progname.c putline.c readfile.3b readfile.c standrand.3b standrand.c \
X	  strdup.3b strdup.c syntax.3b syntax.c
X
XSHAR2=bent-stdio.h
X
XMAN=error.3b getline.3b intro.3b max.3b readfile.3b standrand.3b strdup.3b \
X	syntax.3b
X
Xlibbent.a : $(OBJ)
X	ar r libbent.a $(OBJ)
X	ranlib libbent.a
X
X$(OBJ) : bent.h
X
Xbent.h : bent.header $(SRC)
X	cat bent.header					 >bent.h.tmp
X	echo '#ifdef __STDC__'			>>bent.h.tmp
X	./mkprototypes $(SRC)           >>bent.h.tmp
X	echo '#else /* __STDC__ */'		>>bent.h.tmp
X	./mkprototypes $(SRC) | sed 's/(.*);/();/' >>bent.h.tmp
X	echo '#endif /* __STDC__ */'	>>bent.h.tmp
X	cmp -s bent.h bent.h.tmp || mv bent.h.tmp bent.h
X	rm -f bent.h.tmp
X
Xfilename_tab.o: /vmunix getdtablesize
X	$(CC) $(CFLAGS) getdtablesize.c -o getdtablesize
X	echo 'const char *_bentio_filename_table['`./getdtablesize`']={"stdin","stdout","stderr",};'>filename_tab.c
X	$(CC) $(CFLAGS) -c filename_tab.c
X	rm filename_tab.c
X
Xinstall : $(LIBDIR)/libbent.a $(INCDIR)/bent.h $(INCDIR)/bent-stdio.h $(MANDIR)/man3/intro.3b
X
X$(LIBDIR)/libbent.a : libbent.a
X	cp libbent.a $(LIBDIR)
X	ranlib -t $(LIBDIR)/libbent.a
X
X$(INCDIR)/bent.h : bent.h
X	cp bent.h $(INCDIR)
X
X$(INCDIR)/bent-stdio.h : bent-stdio.h
X	cp bent-stdio.h $(INCDIR)
X
X$(MANDIR)/man3/intro.3b : $(MAN)
X	for f in $(MAN);do \
X		cmp -s $$f $(MANDIR)/man3/$$f || cp $$f $(MANDIR)/man3; \
X	done
X	catman -M $(MANDIR)
X
Xclean :
X	rm -f $(OBJ) getdtablesize
X
Xrealclean : clean
X	rm -f libbent.a bent.h
X
Xshar : libbent.shar.1 libbent.shar.2
X
Xlibbent.shar.1 : $(SHAR1)
X	shar $(SHAR1) >libbent.shar.1
X
Xlibbent.shar.2 : $(SHAR2)
X	shar $(SHAR2) >libbent.shar.2
Shar_Eof
echo x - VERSION
sed 's/^X//' <<\Shar_Eof >VERSION
XVersion 1.0, Fri Dec  2 13:07:34 EST 1988
Shar_Eof
echo x - bent.header
sed 's/^X//' <<\Shar_Eof >bent.header
X#include <bent-stdio.h>
Xextern char *progname;
Xextern char syntax_args[];
X
Xtypedef struct {
X	long magic;	/* MAXIMUM ALIGNMENT TYPE! */
X	unsigned len;
X} _BENT_MALLOC_HEADER;
X
X#define _BENT_MALLOC_MAGIC 0x13713713
X
Xlong stand_rand_seed;
X
Xextern const char *_bentio_filename_table[];
X
X#define _FD2FN(fd) (_bentio_filename_table[(fd)] ? _bentio_filename_table[(fd)] : "(unknown file)")
Shar_Eof
echo x - eclose.c
sed 's/^X//' <<\Shar_Eof >eclose.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid eclose(int fd) {
X#else /* __STDC__ */
Xvoid eclose(fd)
Xint fd;
X{
X#endif /* __STDC__ */
X	if (close(fd) != 0)
X		error("eclose(%d: %s) failed: %s", fd, _FD2FN(fd), BENT_ERRMSG);
X	if (fd > 2 && _bentio_filename_table[fd]) {
X		efree((char *)_bentio_filename_table[fd]);
X		_bentio_filename_table[fd] = 0;
X	}
X}
Shar_Eof
echo x - efclose.c
sed 's/^X//' <<\Shar_Eof >efclose.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efclose(FILE *fp) {
X#else /* __STDC__ */
Xvoid efclose(fp)
XFILE *fd;
X{
X#endif /* __STDC__ */
X	if (fclose(fp) != 0)
X		error("efclose(%s) failed: %s", _FD2FN(fileno(fp)), BENT_ERRMSG);
X	if (fileno(fp) > 2 && _bentio_filename_table[fileno(fp)]) {
X		efree((char *)_bentio_filename_table[fileno(fp)]);
X		_bentio_filename_table[fileno(fp)] = 0;
X	}
X}
Shar_Eof
echo x - efdopen.c
sed 's/^X//' <<\Shar_Eof >efdopen.c
X#include <bent.h>
X
X#ifdef __STDC__
XFILE *efdopen(int fd, const char *mode) {
X#else /* __STDC__ */
XFILE *efdopen(fd, mode)
Xint fd;
Xchar *mode;
X{
X#endif /* __STDC__ */
X	FILE *fp;
X	char *filename;
X
X	if ((fp = fdopen(fd, mode)) == NULL)
X		error("fdopen(%d) failed: %s\n", fd, BENT_ERRMSG);
X
X	filename = emalloc(20);
X	(void) sprintf(filename, "(fdopen %d)", fd);
X	_bentio_filename_table[fd] = filename;
X
X	return(fp);
X}
Shar_Eof
echo x - efflush.c
sed 's/^X//' <<\Shar_Eof >efflush.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efflush(FILE *fp) {
X#else /* __STDC__ */
Xvoid efflush(fp)
XFILE *fp;
X{
X#endif /* __STDC__ */
X	if (fflush(fp) != NULL)
X		error("fflush(%s) failed: %s", _FD2FN(fileno(fp)), BENT_ERRMSG);
X}
Shar_Eof
echo x - efgets.c
sed 's/^X//' <<\Shar_Eof >efgets.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efgets(char *buff, int n, FILE *fp) {
X#else /* __STDC__ */
Xvoid efgets(buff, n, fp)
Xchar *buff;
Xint n;
XFILE *fp;
X{
X#endif /* __STDC__ */
X	if (fgets(buff, n, fp) == NULL)
X		error("fgets(0x%lx, int n, %s) failed: %s", buff, n, _FD2FN(fileno(fp)), BENT_ERRMSG);
X}
Shar_Eof
echo x - efopen.c
sed 's/^X//' <<\Shar_Eof >efopen.c
X#include <bent.h>
X
X#ifdef __STDC__
XFILE *efopen(const char *name, const char *mode) {
X#else /* __STDC__ */
XFILE *efopen(name, mode)
Xchar *name, *mode;
X{
X#endif /* __STDC__ */
X	FILE *fp;
X
X	if ((fp = fopen(name, mode)) == NULL)
X		error("fopen(%s, %s) failed: %s", name, mode, BENT_ERRMSG);
X	_bentio_filename_table[fileno(fp)] = strdup(name);
X	return(fp);
X}
Shar_Eof
echo x - efprintf.c
sed 's/^X//' <<\Shar_Eof >efprintf.c
X#include <bent.h>
X
X#ifdef __STDC__
X#include <stdarg.h>
Xvoid efprintf(FILE *fp, const char *fmt, ...) {
X	va_list ap;
X
X	va_start(ap, fmt);
X	if (vfprintf(fp, fmt, ap) == EOF)
X		error("efprintf(0x%lx, \"%s\", ...) failed: %s", fp, fmt, BENT_ERRMSG);
X	va_end(ap);
X}
X#else /* __STDC__ */
X#include <varargs.h>
Xvoid efprintf(va_list)
Xva_dcl
X{
X	va_list ap;
X	FILE *fp;
X	char *fmt;
X
X	va_start(ap);
X	fp = va_arg(ap, FILE *);
X	fmt = va_arg(ap, char *);
X	if (vfprintf(fp, fmt, ap) == EOF)
X		error("efprintf(0x%lx, "%s", ...) failed: %s", fp, fmt, BENT_ERRMSG);
X	va_end(ap);
X}
X#endif /* __STDC__ */
Shar_Eof
echo x - efread.c
sed 's/^X//' <<\Shar_Eof >efread.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efread(char *buff, int len, int count, FILE *fp) {
X#else /* __STDC__ */
Xvoid efread(buff, len, count, fp)
Xchar *buff;
Xint len, count;
XFILE *fp;
X{
X#endif /* __STDC__ */
X	if (fread(buff, len, count, fp) != count)
X		error("fread(0x%lx, %d, %d, %s) failed: %s", buff, len, count, _FD2FN(fileno(fp)), BENT_ERRMSG);
X}
Shar_Eof
echo x - efree.c
sed 's/^X//' <<\Shar_Eof >efree.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efree(char *ptr) {
X#else /* __STDC__ */
Xvoid efree(char *ptr)
Xchar *ptr;
X{
X#endif /* __STDC__ */
X	_BENT_MALLOC_HEADER *header, *trailer;
X
X	header = (_BENT_MALLOC_HEADER *) (ptr - sizeof(_BENT_MALLOC_HEADER));
X	if (header->magic != _BENT_MALLOC_MAGIC) {
X		(void) fprintf(stderr, "%s: warning: bogus call to efree(0x%lx)", progname, ptr);
X		if (header->magic == _BENT_MALLOC_MAGIC - 1)
X			(void) fprintf(stderr, " -- possible double free\n");
X		else
X			(void) fprintf(stderr, "\n");
X		return;
X	}
X	header->magic = _BENT_MALLOC_MAGIC - 1;
X	trailer = (_BENT_MALLOC_HEADER *) (ptr + header->len);
X	if (trailer->magic != _BENT_MALLOC_MAGIC || trailer->len != header->len) {
X		(void) fprintf(stderr, "%s: warning: bogus call to efree(0x%lx) -- possible pointer overruns treading on malloc arena\n", progname, ptr);
X		return;
X	}
X	free((char *)header);
X}
Shar_Eof
echo x - efseek.c
sed 's/^X//' <<\Shar_Eof >efseek.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efseek(FILE *fp, long offset, int whence) {
X#else /* __STDC__ */
Xvoid efseek(fp, offset, whence)
XFILE *fp;
Xlong offset;
Xint whence;
X{
X#endif /* __STDC__ */
X	if (fseek(fp, offset, whence) != NULL)
X		error("fseek(%s, %ld, %d) failed: %s", _FD2FN(fileno(fp)), offset, whence, BENT_ERRMSG);
X}
Shar_Eof
echo x - efwrite.c
sed 's/^X//' <<\Shar_Eof >efwrite.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid efwrite(const char *buff, int len, int count, FILE *fp) {
X#else /* __STDC__ */
Xvoid efwrite(buff, len, count, fp)
Xchar *buff;
Xint len, count;
XFILE *fp;
X{
X#endif /* __STDC__ */
X	if (fwrite(buff, len, count, fp) != count)
X		error("fwrite(0x%lx, %d, %d, %s) failed: %s", buff, len, count, _FD2FN(fileno(fp)), BENT_ERRMSG);
X}
Shar_Eof
echo x - emalloc.c
sed 's/^X//' <<\Shar_Eof >emalloc.c
X#include <bent.h>
X
X#ifdef __STDC__
Xchar *emalloc(unsigned n) {
X#else /* __STDC__ */
Xchar *emalloc(n)
Xunsigned n;
X{
X#endif /* __STDC__ */
X	char *ptr;
X	_BENT_MALLOC_HEADER *tmp;
X
X	if ((ptr = malloc(n + 2*sizeof(_BENT_MALLOC_HEADER))) == NULL)
X		error("malloc(%d) failed: %s", n, BENT_ERRMSG);
X
X	tmp = (_BENT_MALLOC_HEADER *) ptr;
X	tmp->magic = _BENT_MALLOC_MAGIC;
X	tmp->len = n;
X
X	tmp = (_BENT_MALLOC_HEADER *) (ptr + sizeof(_BENT_MALLOC_HEADER) + n);
X	tmp->magic = _BENT_MALLOC_MAGIC;
X	tmp->len = n;
X
X	return(ptr + sizeof(_BENT_MALLOC_HEADER));
X}
Shar_Eof
echo x - emkstemp.c
sed 's/^X//' <<\Shar_Eof >emkstemp.c
X#include <bent.h>
X
X#ifdef __STDC__
Xint emkstemp(char *ptr) {
X#else /* __STDC__ */
Xint emkstemp(ptr)
Xchar *ptr;
X{
X#endif /* __STDC__ */
X	int fd;
X
X	if ((fd = mkstemp(ptr)) < 0)
X		error("mkstemp(%s) failed: %s", ptr, BENT_ERRMSG);
X
X	return(fd);
X}
Shar_Eof
echo x - eopen.c
sed 's/^X//' <<\Shar_Eof >eopen.c
X#include <bent.h>
X
X#ifdef __STDC__
Xint eopen(const char *name, int flags, int mode) {
X#else /* __STDC__ */
Xint eopen(name, flags, mode)
Xchar *name;
Xint flags, mode;
X{
X#endif /* __STDC__ */
X	int fd;
X
X	if ((fd = open(name, flags, mode)) < 0)
X		error("open(%s, %d, %d) failed: %s", name, flags, mode, BENT_ERRMSG);
X	_bentio_filename_table[fd] = strdup(name);
X	return(fd);
X}
Shar_Eof
echo x - eprintf.c
sed 's/^X//' <<\Shar_Eof >eprintf.c
X#include <bent.h>
X
X#ifdef __STDC__
X#include <stdarg.h>
Xvoid eprintf(const char *fmt, ...) {
X	va_list ap;
X
X	va_start(ap, fmt);
X	if (vprintf(fmt, ap) == EOF)
X		error("eprintf(\"%s\", ...) failed: %s", fmt, BENT_ERRMSG);
X	va_end(ap);
X}
X#else /* __STDC__ */
X#include <varargs.h>
Xvoid eprintf(va_list)
Xva_dcl
X{
X	va_list ap;
X	char *fmt;
X
X	va_start(ap);
X	fmt = va_arg(ap, char *);
X	if (vprintf(fmt, ap) == EOF)
X		error("eprintf("%s", ...) failed: %s", fmt, BENT_ERRMSG);
X	va_end(ap);
X}
X#endif /* __STDC__ */
Shar_Eof
echo x - eputchar.c
sed 's/^X//' <<\Shar_Eof >eputchar.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid eputchar(int c) {
X#else /* __STDC__ */
Xvoid eputchar(c)
Xint c;
X{
X#endif /* __STDC__ */
X	if (putchar(c) == EOF)
X		error("eputchar('%c') failed: %s", c, BENT_ERRMSG);
X}
Shar_Eof
echo x - erealloc.c
sed 's/^X//' <<\Shar_Eof >erealloc.c
X#include <bent.h>
X
X#ifdef __STDC__
Xchar *erealloc(char *ptr, unsigned n) {
X#else /* __STDC__ */
Xchar *erealloc(ptr, n)
Xchar *ptr;
Xunsigned n;
X{
X#endif /* __STDC__ */
X	_BENT_MALLOC_HEADER *header, *trailer;
X
X	header = (_BENT_MALLOC_HEADER *) (ptr - sizeof(_BENT_MALLOC_HEADER));
X	if (header->magic != _BENT_MALLOC_MAGIC) {
X		(void) fprintf(stderr, "%s: warning: bogus call to erealloc(0x%lx, %u)", progname, ptr, n);
X		if (header->magic == _BENT_MALLOC_MAGIC - 1) {
X			(void) fprintf(stderr, " -- possible double free\n");
X		} else {
X			(void) fprintf(stderr, "\n");
X			return(realloc(ptr, n));
X		}
X	}
X
X	trailer = (_BENT_MALLOC_HEADER *) (ptr + header->len);
X	if (trailer->magic != _BENT_MALLOC_MAGIC || trailer->len != header->len)
X		(void) fprintf(stderr, "%s: warning: bogus call to erealloc(0x%lx) -- possible pointer overruns treading on malloc arena\n", progname, ptr);
X
X	header = (_BENT_MALLOC_HEADER *) realloc((char *)header, n+2*sizeof(_BENT_MALLOC_HEADER));
X	if (header == NULL)
X		error("erealloc(%lx, %u) failed: %s", ptr, n, BENT_ERRMSG);
X
X	header->len = n;
X	ptr = ((char *) header) + sizeof(_BENT_MALLOC_HEADER);
X	trailer = (_BENT_MALLOC_HEADER *) (ptr + header->len);
X	trailer->magic = _BENT_MALLOC_MAGIC;
X	trailer->len = header->len;
X
X	return(ptr);
X}
Shar_Eof
echo x - error.3b
sed 's/^X//' <<\Shar_Eof >error.3b
X.TH ERROR 3B "18 November 1988"
X.SH NAME
Xerror \- error handling library routines
X.SH SYNOPSIS
X#include <bent.h>
X.br
Xextern char *progname;
X.br
X.SH DESCRIPTION
X.PP
XThe \fImain()\fR procedure should initialize \fIprogname\fR to argv[0], as
Xthat is used in generating error messages. These routines behave exactly
Xlike the system calls and library routines they are wrapped around, except
Xthat they don't return if the call failed. Instead they print a suitable
Xerror message to stderr and exit with status 1. The routine \fIerror\fR
Xhas syntax identical to printf(3S), but prepends the message with
X\fIprogname\fR, and exits with status 1.
X.SH "LIST OF FUNCTIONS"
X.sp 2
X.nf
X\fIName\fP		\fIDescription\fP
Xeclose	wrapper around close(2)
Xefclose	wrapper around fclose(3S)
Xefdopen	wrapper around fdopen(3S)
Xefflush	wrapper around fflush(3S)
Xefgets	wrapper around fgets(3S)
Xefopen	wrapper around fopen(3S)
Xefprintf	wrapper around fprintf(3S)
Xefread	wrapper around fread(3S)
Xefree	wrapper around free(3S)
Xefseek	wrapper around fseek(3S)
Xefwrite	wrapper around fwrite(3S)
Xemalloc	wrapper around malloc(3S)
Xemkstemp	wrapper around mkstemp(3S)
Xeopen	wrapper around open(2)
Xeprintf	wrapper around printf(3S)
Xeputchar	wrapper around putchar(3S)
Xerealloc	wrapper around realloc(3S)
Xerror	print message and exit
Xetruncate	wrapper around truncate(2)
Xeunlink	wrapper around unlink(2)
Xewrite	wrapper around write(2)
X.fi
X.SH "SEE ALSO"
Xintro(3B), perror(3S), printf(3S), intro(2), intro(3)
Shar_Eof
echo x - error.c
sed 's/^X//' <<\Shar_Eof >error.c
X#include <bent.h>
X
X#ifdef __STDC__
X#include <stdarg.h>
Xvoid error(const char *fmt, ...) {
X	va_list ap;
X
X	(void) fprintf(stderr, "%s: ", progname);
X	va_start(ap, fmt);
X	(void) vfprintf(stderr, fmt, ap);
X	va_end(ap);
X	(void) fprintf(stderr, "\n");
X	exit(1);
X}
X#else /* __STDC__ */
X#include <varargs.h>
Xvoid error(va_list)
Xva_dcl
X{
X	va_list ap;
X	char *fmt;
X
X	(void) fprintf(stderr, "%s: ", progname);
X	va_start(ap);
X	fmt = va_arg(ap, char *);
X	(void) vfprintf(stderr, fmt, ap);
X	va_end(ap);
X	(void) fprintf(stderr, "\n");
X	exit(1);
X}
X#endif /* __STDC__ */
Shar_Eof
echo x - etruncate.c
sed 's/^X//' <<\Shar_Eof >etruncate.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid etruncate(const char *name, unsigned long len) {
X#else /* __STDC__ */
Xvoid etruncate(name, len)
Xchar *name;
Xunsigned long len;
X{
X#endif /* __STDC__ */
X	if (truncate(name, len) < 0)
X		error("etruncate(%s, %ul) failed: %s", name, len, BENT_ERRMSG);
X}
Shar_Eof
echo x - eunlink.c
sed 's/^X//' <<\Shar_Eof >eunlink.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid eunlink(const char *name) {
X#else /* __STDC__ */
Xvoid eunlink(name)
Xchar *name;
X{
X#endif /* __STDC__ */
X	if (unlink(name) != NULL)
X		error("unlink(%s) failed: %s", name, BENT_ERRMSG);
X}
Shar_Eof
echo x - ewrite.c
sed 's/^X//' <<\Shar_Eof >ewrite.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid ewrite(int fd, const char *buff, int count) {
X#else /* __STDC__ */
Xvoid ewrite(fd, buff, count)
Xint fd;
Xchar *buff;
Xint count;
X{
X#endif /* __STDC__ */
X	if (write(fd, buff, count) != count)
X		error("write(%s, 0x%lx, %d) failed: %s", _FD2FN(fd), buff, count, BENT_ERRMSG);
X}
Shar_Eof
echo x - getdtablesize.c
sed 's/^X//' <<\Shar_Eof >getdtablesize.c
X#include <bent-stdio.h>
X
X#ifdef __STDC__
Xint main(int argc, char **argv) {
X#else /* __STDC__ */
Xint main(argc, argv)
Xint argc;
Xchar **argv;
X{
X#endif /* __STDC__ */
X	return(printf("%d\n", getdtablesize()) < 0);
X}
Shar_Eof
echo x - getline.3b
sed 's/^X//' <<\Shar_Eof >getline.3b
X.TH GETLINE 3B  "18 November 1988"
X.SH NAME
Xgetline, putline \- read and write arbitrarily long text lines
X.SH SYNOPSIS
X.B #include <bent.h>
X.PP
X.B char *getline(buff, stream)
X.br
X.B char *buff;
X.br
X.B FILE *stream;
X.PP
X.B void putline(buff, stream)
X.br
X.B char *buff;
X.br
X.SM
X.B FILE
X.B *stream;
X.SH DESCRIPTION
X\fIgetline\fR reads characters from \fIstream\fR until newline or EOF is
Xreached.  It reads them into \fIbuff\fR, growing it as necessary. \fIbuff\fR
XMUST be a buffer created by \fIgetline\fR. If \fIbuff\fR is "(char *)NULL"
X\fIgetline\fR will allocate a new buffer. \fIgetline\fR returns the pointer
Xto the filled buffer, or NULL on EOF (in which case it de-allocates
X\fIbuff\fR).
X.PP
X\fIputline\fR writes a buffer created by \fIgetline\fR to \fIstream\fR.
X.SH "SEE ALSO"
Xintro(3B), gets(3S), puts(3S)
Shar_Eof
echo x - getline.c
sed 's/^X//' <<\Shar_Eof >getline.c
X#include <bent.h>
X
X#define _GETLINE_INIT_SIZE 7	/* 2**N == 128 bytes initial */
X
X#ifdef __STDC__
Xchar *getline(char *buff, FILE *fp) {
X#else /* __STDC__ */
Xchar *getline(buff, fp)
Xchar *buff;
XFILE *fp;
X{
X#endif /* __STDC__ */
X	char *curch, *stop;
X	int c;
X
X	if (feof(fp)) {
X		if (buff)
X			efree(buff-1);
X		return(0);
X	}
X
X	if (buff == NULL) {
X		buff = emalloc(1<<_GETLINE_INIT_SIZE);
X		*buff++ = _GETLINE_INIT_SIZE;
X	}
X
X	curch = buff;
X	stop = buff + (1<<buff[-1]) - 2;
X	while ((c = getc(fp)) != EOF && c != '\n') {
X		if (curch >= stop) {
X			buff = erealloc(buff, 1<<(buff[-1]+1)) + 1;
X			curch = buff + (1<<buff[-1]) - 2;
X			buff[-1]++;
X			stop = buff + (1<<buff[-1]) - 2;
X		}
X		if (c == '\0')
X			*curch++ = '\n';
X		else
X			*curch++ = c;
X	}
X	*curch = 0;
X
X	if (feof(fp)) {
X		if (strlen(buff) == 0) {
X			efree(buff-1);
X			return(0);
X		} else {
X			clearerr(fp);
X		}
X	}
X
X	return(buff);
X}
Shar_Eof
echo x - intro.3b
sed 's/^X//' <<\Shar_Eof >intro.3b
X.TH INTRO 3B "18 November 1988"
X.SH NAME
Xintro \- introduction to Bennett's library of handy routines
X.SH SYNOPSIS
X#include <bent.h>
X.br
Xextern char *progname;
X.br
Xextern char syntax_args[];
X.SH DESCRIPTION
XThe include file <bent.h> contains declarations of all the functions in the
X\fIbent\fR library \fIlibbent\fR (described in Section 3B).
X.PP
XThe routines are divided into two catagories: first there are wrappers around
Xmany standard system calls found in section 2 of the Unix Programmer's
XManual (UPM) and library routines (section 3 of the UPM) which check for
Xerror conditions and only return on success. On failure they will exit with
Xan errorlevel of 1 after printing \fIprogname\fR (should be initialized to
Xargv[0] at the beginning of main), the name of the routine that failed, and
Xsys_errlist[errno] (these will be printed to stderr). All these routines are
Xthe same name as the routines they are built upon, preceded by "e". Thus
X\fIemalloc()\fR, \fIefopen()\fR, etc. See error(3B).  The second catagory is
Xauxiliary helpful support routines.
X.PP
X\fIBent.h\fR includes support declarations and function prototypes (under
X#ifdef __STDC __; old-style declarations are also provided for older
Xcompilers). It also includes \fIbent-stdio.h\fR which in turn includes all
Xthe relevant support files for all the calls in sections 2 and 3 of the UPM,
Xand function prototypes for them all.
X.PP
XThe link editor searches this library under the \*(lq\-lbent\*(rq option.
X.SH "LIST OF FUNCTIONS"
X.sp 2
X.nf
X\fIName\fP		\fIAppears on Page\fP	\fIDescription\fP
Xeclose	error(3B)			wrapper around close(2)
Xefclose	error(3B)			wrapper around fclose(3S)
Xefdopen	error(3B)			wrapper around fdopen(3S)
Xefflush	error(3B)			wrapper around fflush(3S)
Xefgets	error(3B)			wrapper around fgets(3S)
Xefopen	error(3B)			wrapper around fopen(3S)
Xefprintf	error(3B)			wrapper around fprintf(3S)
Xefread	error(3B)			wrapper around fread(3S)
Xefree	error(3B)			wrapper around free(3S)
Xefseek	error(3B)			wrapper around fseek(3S)
Xefwrite	error(3B)			wrapper around fwrite(3S)
Xemalloc	error(3B)			wrapper around malloc(3S)
Xemkstemp	error(3B)			wrapper around mkstemp(3S)
Xeopen	error(3B)			wrapper around open(2)
Xeprintf	error(3B)			wrapper around printf(3S)
Xeputchar	error(3B)			wrapper around putchar(3S)
Xerealloc	error(3B)			wrapper around realloc(3S)
Xerror	error(3B)			print message and exit
Xetruncate	error(3B)			wrapper around truncate(2)
Xeunlink	error(3B)			wrapper around unlink(2)
Xewrite	error(3B)			wrapper around write(2)
Xgetline	getline(3B)			read arbitrarily long text line
Xmax		max(3B)				maximum of two integers
Xmin		max(3B)				minimum of two integers
Xputline	getline(3B)			write line read by getline(3B)
Xreadfile	readfile(3B)			read a whole file into a buffer
Xstandrand	standrand(3B)			standard pseudo-random number generator
Xstrdup	strdup(3B)			return a duplicate of a string
Xsyntax	syntax(3B)			print a syntax error message and exit
X.fi
X.SH "SEE ALSO"
Xerror(3B), perror(3), getline(3B), max(3B), readfile(3B), standrand(3B),
Xstrdup(3B), syntax(3B)
Shar_Eof
echo x - max.3b
sed 's/^X//' <<\Shar_Eof >max.3b
X.TH MAX 3B  "5 December 1988"
X.SH NAME
Xmax, min \- maximum or minimum of two integers
X.SH SYNOPSIS
X.B int max(x, y)
X.br
X.B int x, y;
X.PP
X.B int min(x, y)
X.br
X.B int x, y;
X.SH DESCRIPTION
XReally staggeringly obvious.
Shar_Eof
echo x - max.c
sed 's/^X//' <<\Shar_Eof >max.c
X#ifdef __STDC__
Xint max(int x, int y) {
X#else /* __STDC__ */
Xint max(x, y)
Xint x, y;
X{
X#endif /* __STDC__ */
X	return(x>y ? x : y);
X}
Shar_Eof
echo x - min.c
sed 's/^X//' <<\Shar_Eof >min.c
X#ifdef __STDC__
Xint min(int x, int y) {
X#else /* __STDC__ */
Xint min(x, y)
Xint x, y;
X{
X#endif /* __STDC__ */
X	return(x<y ? x : y);
X}
Shar_Eof
echo x - mkprototypes
sed 's/^X//' <<\Shar_Eof >mkprototypes
Xegrep '^[a-zA-Z_].*{$' $* | sed -e 's/[ 	]*[a-z_0-9]*,/,/g' \
X								-e 's/[ 	]*[a-z_0-9]*)/)/g' \
X								-e 's/[ 	]*{$/;/' \
X								-e 's/();/(void);/' \
X								-e 's/^.*\.c://'
Shar_Eof
echo x - progname.c
sed 's/^X//' <<\Shar_Eof >progname.c
Xstatic char progname_initializer[] = "[UNINITIALIZED]";
Xchar *progname = progname_initializer;
Shar_Eof
echo x - putline.c
sed 's/^X//' <<\Shar_Eof >putline.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid putline(char *buff, FILE *fp) {
X#else /* __STDC__ */
Xvoid putline(buff, fp)
Xchar *buff;
XFILE *fp;
X{
X#endif /* __STDC__ */
X	char *ptr, *stop;
X
X	ptr = buff;
X	stop = buff + (1<<buff[-1]) - 2;
X	while ((ptr = index(ptr, '\n')) && ptr < stop)
X		*ptr++ = '\0';
X	while (*ptr++)
X		/* NULL BODY */;
X	*ptr++ = '\n';
X	efwrite(buff, 1, ptr-buff, fp);
X}
Shar_Eof
echo x - readfile.3b
sed 's/^X//' <<\Shar_Eof >readfile.3b
X.TH READFILE 3B  "5 December 1988"
X.SH NAME
Xreadfile \- read a whole file into a buffer
X.SH SYNOPSIS
X.B #include <bent.h>
X.PP
X.B char *readfile(fp, len)
X.br
X.B FILE *fp;
X.br
X.B int *len;
X.SH DESCRIPTION
X\fIreadfile\fR reads the entire contents of the file pointed to by \fIfp\fR
Xinto a dynamically allocated buffer, adjusting the size as necessary. It
Xreturns a pointer to the buffer, with the actual length stored in the int
Xpointed to by \fIlen\fR. \fIfp\fR is closed.
Shar_Eof
echo x - readfile.c
sed 's/^X//' <<\Shar_Eof >readfile.c
X#include <bent.h>
X
X#ifdef __STDC__
Xchar *readfile(FILE *fp, int *len) {
X#else /* __STDC__ */
Xchar *readfile(fp, len)
XFILE *fp;
Xint *len;
X{
X#endif /* __STDC__ */
X	char *buff, *ptr;
X	int allocated, n;
X
X	allocated = 65536;
X	*len = 0;
X	ptr = buff = emalloc(allocated);
X	while (n = fread(ptr, 1, allocated - *len, fp)) {
X		*len += n;
X		ptr += n;
X		if (*len == allocated) {
X			allocated *= 2;
X			buff = erealloc(buff, allocated);
X			ptr = buff + *len;
X		}
X	}
X	efclose(fp);
X	return(erealloc(buff, *len));
X}
Shar_Eof
echo x - standrand.3b
sed 's/^X//' <<\Shar_Eof >standrand.3b
X.TH STANDRAND 3B  "18 November 1988"
X.SH NAME
Xstandrand \- standard pseudo-random number generator
X.SH SYNOPSIS
X.B #include <bent.h>
X.PP
X.B
Xstand_rand_seed = /* some good integer */;
X.PP
X.B double stand_rand();
X.SH DESCRIPTION
X\fIstand_rand\fR implements a pseudo-random number generator as described in
XCACM V31N10 (10/88). It returns a double uniformly distributed on [0,1). It
Xhas a period of 2**31 - 2.
Shar_Eof
echo x - standrand.c
sed 's/^X//' <<\Shar_Eof >standrand.c
X#include <bent.h>
X/* seed[i+1] == A*seed[i] % M */
X#define A 16807
X#define M 2147483647
X#define Q 127773		/* M div A */
X#define R 2836			/* M mod A */
X
X#ifdef __STDC__
Xdouble stand_rand(void) {
X#else /* __STDC__ */
Xdouble stand_rand()
X{
X#endif /* __STDC__ */
X	int lo, hi;
X
X	hi = stand_rand_seed / Q;
X	lo = stand_rand_seed % Q;
X	stand_rand_seed = A*lo - R*hi;
X	if (stand_rand_seed <= 0)
X		stand_rand_seed += M;
X	return(((double)stand_rand_seed-1.0) / ((double)M-1.0));
X}
Shar_Eof
echo x - strdup.3b
sed 's/^X//' <<\Shar_Eof >strdup.3b
X.TH STRDUP 3B  "18 November 1988"
X.SH NAME
Xstrdup \- make a copy of a string
X.SH SYNOPSIS
X.B #include <bent.h>
X.PP
X.B char *strdup(s)
X.br
X.B char *s;
X.SH DESCRIPTION
X\fIstrdup\fR returns a copy of the string pointed to by \fIs\fR. It can be
Xdestroyed later by passing it to \fIefree(3B)\fR.
Shar_Eof
echo x - strdup.c
sed 's/^X//' <<\Shar_Eof >strdup.c
X#include <bent.h>
X
X#ifdef __STDC__
Xchar *strdup(const char *s) {
X#else /* __STDC__ */
Xchar *strdup(s)
Xchar *s;
X{
X#endif /* __STDC__ */
X	return(strcpy(emalloc(strlen(s)+1), s));
X}
Shar_Eof
echo x - syntax.3b
sed 's/^X//' <<\Shar_Eof >syntax.3b
X.TH SYNTAX 3B "18 November 1988"
X.SH NAME
Xsyntax \- print syntax message and exit
X.SH SYNOPSIS
X#include <bent.h>
X.br
Xchar *progname;
X.br
Xchar syntax_args[] = "(optional flags and arguments)"
X.PP
Xvoid syntax();
X.SH DESCRIPTION
X\fIsyntax\fR prints a syntax message using \fIprogname\fR (which should be
Xinitialized by \fImain()\fR to argv[0]), then exits.
X.SH "SEE ALSO"
Xintro(3B), error(3B)
Shar_Eof
echo x - syntax.c
sed 's/^X//' <<\Shar_Eof >syntax.c
X#include <bent.h>
X
X#ifdef __STDC__
Xvoid syntax(void) {
X#else /* __STDC__ */
Xvoid syntax()
X{
X#endif /* __STDC__ */
X	(void) fprintf(stderr, "syntax: %s %s\n", progname, syntax_args);
X	exit(1);
X}
Shar_Eof
exit 0

-Bennett
bet at orion.mc.duke.edu



More information about the Comp.lang.c mailing list