Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!nic.MR.NET!xanth!mcnc!ecsvax!dukeac!bet From: bet@dukeac.UUCP (Bennett Todd) Newsgroups: comp.lang.c Subject: My error-handling library and ANSI prototypes (Part 1/2) Message-ID: <1215@dukeac.UUCP> Date: 4 Feb 89 01:49:49 GMT Reply-To: bet@dukeac.UUCP (Bennett Todd) Organization: Radiology, Duke Med. Center, Durham, NC Lines: 1102 : 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@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 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 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 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 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 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 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 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 X X#ifdef __STDC__ X#include 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 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 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 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 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 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 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 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 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 X X#ifdef __STDC__ X#include 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 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 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 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 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 X X#ifdef __STDC__ X#include 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 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 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 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 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 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 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 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<= stop) { X buff = erealloc(buff, 1<<(buff[-1]+1)) + 1; X curch = buff + (1<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 X.br Xextern char *progname; X.br Xextern char syntax_args[]; X.SH DESCRIPTION XThe include file 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(xmkprototypes 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 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<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 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 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 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 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 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 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 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 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@orion.mc.duke.edu