nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (09/30/89)
Here is my stdio package, in a number of pieces. The package is split up as follows: Part 0: Release notes Part 1: An install script, 2 makefiles, and a CRC list Part 2: New and replacement include files Part 3: The stdio routines Part 4: A few other routines that I'm throwing in Now for the notes: Part 0 ------ 1. Find some disk space to work in (500K should do nicely - if you're using 360K floppies only, you will have to do some juggling). 2. Make yourself a nice new directory with some name you like. Cd to it and make a subdirectory named "sys". Then feed parts 1 through 4 into /bin/sh, which extracts a bundle of files. Part 1 ------ 1. You'd better make sure everything unpacked alright. Type "make crclist" and compare crclist with the unpacked CRCLIST. 2. Edit "Install" and change the shell variables at the front to reflect your configuration. Note that MAKEDIR should be the directory you have unbundled things into, and that TMPDIR should be another directory entirely. DO NOT MAKE THESE TWO THE SAME! 3. Change the CFLAGS variable in accordance with the notes just above its definition. A few extra notes: - If you have installed Simon Poole's FS patches, then write() automatically writes at end of file when a file is opened for append. Otherwise, you need a kludge that (sort of) simulates this. To get it, the symbol _V7 must be defined. - The machine definition (i8088/ATARI_ST) is needed for stdarg.h and the files that use it. Since I do not have access to an Atari, I tested the Atari code on a Sun 3, where it seems to work fine. Please tell me if it doesn't. If you are running on a machine that is neither of these, edit stdarg.h to reflect how your machine handles the stack for procedure calls and define this symbol appropriately. If you are using another machine, I'd like to know what definitions you use; please email me. - Define NDEBUG if you want very little error checking in the stdio routines. Without this definition, more error checking is done than with the old stdio. With it, almost none is done. - Define _SAFEMACRO if you want a little extra speed out of the stdio and ctype routines. This is perhaps not worthwhile. 4. Edit "Makefile.libc". I use this makefile to build my libc.a. I think it's pretty logically laid out, and I have run into few ordering problems since I made it up. (I also suggest that something like this be supplied with distributions from now on.) If you have local modules that need to be added, do so in an appropriate place. 5. Ensure you have sufficient permissions to update the directories holding the standard headers and the library. Root is good (I promise, there's no "cd /;rm -rf *" in the script). I use a special id with fewer privileges. 6. Feed Install to /bin/sh. It will make copies of your old headers and library, install the new headers, make the new library routines, create a new library and install it. 7. You'd better save the source files in an archive somewhere. Since this is too variable, I figured you could do it manually. Make sure you save the file "stdiolib.h" with the stdio library sources. "lib.h" is the standard Minix issue - it's there for completeness. 8. You are ready to roll. Recompile your old sources ... I think you'll find this new stdio rather faster than the standard one. On my machine, it is competitive with Earl Chew's package (a little faster here, a little slower there). 9. Send me bug reports. Part 2 ------ This is a completely new set of standard headers. I have copies of the December 1988 draft ANSI C standard and POSIX, and have tried to be as faithful to both as possible. In particular: - The headers include prototypes for all required functions. An additional header, <prototype.h>, is used to get rid of the prototypes for nonconforming compilers (i.e. ACK and ilk). - Strictly conforming ANSI compilers will have a fit about "const" when compiling some code (GNU just gives warnings). Rather than copy const strings to non-const ones, which is what causes the most problems in the stdio package, I would elect to simply #define const to be the null string (even for __STDC__). - ANSI is pretty strict about name space pollution (if it doesn't start with an underscore and ANSI doesn't mention it, you can't have it). I think I've done pretty well in this regard, but there are exceptions (particuarly <signal.h> and <time.h>). - Various headers that should be included are not. I have not supplied <float.h>, <locale.h>, or <math.h>. I look forward to having them. - Copyright acknowledgements: <errno.h> is pretty much like the original; <dirent.h> and <sys/dirent.h> are minor variations on Doug Gwyn's. - Quite a few things are left undone, especially for POSIX. Grep for "PENDING" in the headers. Part 3 ------ The stdio part of the library is completely rewritten. Where that intersects with other parts of the library, I have modified small pieces of old code. Stdio is ANSI compatible (I hope). It includes the two POSIX extensions, fdopen() and fileno(). There are functions behind all macros; if you want them, you can simply #undef the macro name. FILEs are statically allocated; buffers are dynamically allocated. Further details include: - All error checking of arguments has been moved into _io_assert macros. By default, this macro returns the standard error value defined at the start of each function. If you want extra debugging, change the definition of _io_assert in "stdiolib.h" to squawk. Compiling with -DNDEBUG gets rid of all the error checking (if you want a faster library and you know your code is OK). I have two copies of libc.a, one with no debugging and one with debugging (which I named libdbg.a). I added support for -g in cc.c to link with libdbg.a. - fopen(), freopen(), fdopen() support update modes (r+,w+,a+). Until the kernel supports append mode properly, files opened a/a+ work almost correctly. The exception is on files with shared filp entries (fork() side effect), where problems may arise. - remove() added - rename() added (Freeman Pascal's version) - tmpfile() and tmpnam() added. Files opened by tmpfile() are automatically deleted at close() or exit(). - fflush() works as POSIX demands. fflush(NULL) flushes all streams. - setvbuf() added. Per ANSI, setbuf() now has slightly different semantics: if given a NULL buffer pointer, it makes the stream _IONBF. - printf() family supports all ANSI types except floating point (I'll get around to it). That includes %n. - scanf() family supports all ANSI types except floating point (including %n). - getc() and putc() are now unsafe macros. They're fast! - fgetc() and fputc() can be macros if you #define _SAFEMACRO when compiling source. Note that the library had better have been compiled similarly. - gets() has different semantics: a string ending in EOF with no NL will be returned; EOF will be returned on the next gets(). - ungetc() works once on unbuffered files - fread()/fwrite() are much faster than the standard issue; fread() with small objects is much faster than Earl Chew's. - fseek() no longer clears the error indicator - fgetpos() and fsetpos() are included - fseek() / fsetpos() / rewind() all allow switching of update mode streams from read to write and vice versa. Compiled with -DNDEBUG, the code will not verify that these switches occur at appropriate times. Without it, errors are returned if you switch without one of these being called. - perror() is pretty much standard Minix 1.3 - cleanup.c is replaced by _cleanup.c - atexit() is copyright Frank Wortner - exit() is slightly changed - streams attached to tty's are automatically line buffered (_IOLBF). This means that stdout, in particular, may work more slowly than in the standard package. ANSI requires this to be done, so I did it. If you take a big performance hit and are willing to lose a buffer full of your output, use setvbuf() to get full buffering (_IOFBF). Note that this holds for all interactive output streams. - stdout on a tty is flushed if any unbuffered or line buffered stream is read. In particular, you will see all of your stdout output before reading from stdin occurs. Note that this is not true for other output streams (ANSI says this may be done, but it's not required - the performance loss is substantial). Part 4 ------ There is a slightly modified version of ctype.c, which matches <ctype.h>. I have included rewritten versions of printk() and prints(). printk() is an exact duplicate of printf(), save for NO floating point support, and the fact that it uses the kernel's putc() for output. It includes _doprnt.c, which means that changes in the standard formatted output routines should be reflected in printk() as well. prints() is a cut-down version of printf() that only handles %c and %s, BUT (like the old one) it doesn't justify correctly, and it isn't synchronized with any stream. It does save space if you don't need numeric formatting (~1K). Included are ANSI conforming div(), ldiv(), strtol(), and strtoul(). strtol() includes replacements for atoi() and atol(), since they are so similar to strtol(). Also included are POSIX compliant versions of cuserid(), getlogin(), getgrent(), and getpwent(). The first two are pretty much the same as Terrence Holm's versions; the second two are adaptations of the originals by Patrick van Kleef. getgrent() needs more work to be really POSIX compliant. The commands [chgrp, chown, id, login, ls, passwd, stat, su, uudecode, whoami] depend on either <grp.h> or <pwd.h> and should probably be recompiled. The existing versions will continue to work as currently linked.
nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (09/30/89)
echo x - Install sed '/^X/s///' > Install << '/' X#!/bin/sh X# Run with appropriate permissions. X# Assumes entire package is unpacked in ${MAKEDIR}. X# Before running, modify the following to reflect what you want. X X# Should be an absolute directory with sufficient size to hold the X# packaged source and the accompanying object files. XMAKEDIR=/usr/nfs/lib X X# Should be an absolute directory with sufficient size to hold all X# !!!EXISTING!!! library objects. Must be different than MAKEDIR. XTMPDIR=/usr/nfs/tmp X X# Should be the existing location of standard headers. XINCLUDE=/usr/include X X# Should be the existing location of the C library. XLIB=/usr/lib X X# Should be the C library name. XLIBC=libc.a X X# Old include files will have this suffix added to their names. X# Old library will be moved to its existing name plus this suffix. XSUFFIX=.orig X X# Change to reflect what you want. X# -LIB -D_MINIX should always be there (for the ACK compiler). X# -D_V7 is required if you don't have Simon Poole's FS patches. X# -Di8088/-DATARI_ST must be specified to describe the target machine. X# -DNDEBUG if you want no debugging in the library routines. X# -D_SAFEMACRO if you want a few extra ctype/stdio macros for speed. X XCFLAGS='-LIB -D_MINIX -D_V7 -Di8088 -DNDEBUG -D_SAFEMACRO' X Xif test ${TMPDIR} = ${MAKEDIR} Xthen Xecho Please change either TMPDIR or MAKEDIR. Xexit Xfi X X# Save old library routines. Xecho Saving old library ${LIBC} as ${LIB}/${LIBC}${SUFFIX} Xif mv ${LIB}/${LIBC} ${LIB}/${LIBC}${SUFFIX} Xthen echo Xelse echo "Couldn't save original ${LIBC}" Xexit Xfi X X# Extract existing routines. Xecho Extracting existing library routines. Xcd ${TMPDIR} Xar x ${LIB}/${LIBC}${SUFFIX} X X# Install new include files. Xecho "Installing new headers in ${INCLUDE}; old ones saved with suffix ${SUFFIX}" Xcd ${MAKEDIR} Xmv stdiolib.h stdiolib.H # Don't install these two in ${INCLUDE} Xmv lib.h lib.H Xfor i in *.h Xdo if test -f ${INCLUDE}/${i} Xthen mv ${INCLUDE}/${i} ${INCLUDE}/${i}${SUFFIX} Xfi Xdone Xmv *.h ${INCLUDE} Xmv stdiolib.H stdiolib.h Xmv lib.H lib.h Xcd sys Xfor i in *.h Xdo if test -f ${INCLUDE}/${i} Xthen mv ${INCLUDE}/sys/${i} ${INCLUDE}/sys/${i}${SUFFIX} Xfi Xdone Xmv *.h ${INCLUDE}/sys X X# Make new library routines. Xecho Making new library routines. Xcd ${MAKEDIR} Xif make CFLAGS="${CFLAGS}" objects Xthen echo Make complete. Xelse echo Make aborted. Xexit Xfi X X# Install new library routines. Xecho Installing new routines in ${LIB}/${LIBC}. Xcd ${MAKEDIR} Xfor i in *.s Xdo rm -f ${TMPDIR}/${i}; mv ${i} ${TMPDIR} Xdone Xcd ${TMPDIR} # Remove some extra hangers on. Xrm -f atoi.s atol.s cleanup.s doprintf.s fprintf.s printdat.s puts.s vsprintf.s Xmake -f ${MAKEDIR}/Makefile.libc TARGET=${LIBC} Xmv ${LIBC} ${LIB} X X# Clean up. Xrm .Made Xrm -f [a-e]*.s Xrm -f [f-j]*.s Xrm -f [k-o]*.s Xrm -f [p-t]*.s Xrm -f [u-z]*.s Xecho Installation complete. Xecho Xecho All the new sources can be found in ${MAKEDIR} - save them in an Xecho appropriate location. Be sure to save "lib.h" and "stdiolib.h". / echo x - Makefile sed '/^X/s///' > Makefile << '/' XCFLAGS = -LIB -D_MINIX -D_V7 -Di8088 -DNDEBUG -D_SAFEMACRO X XSTDIO = _bufproc.s _cleanup.s _doprnt.s _doscan.s _filbuf.s _flsbuf.s \ X _flspbuf.s _iobdata.s _iobproc.s _ioinit.s _valmode.s \ X atexit.s exit.s fclose.s fdopen.s fflush.s \ X fgetc.s fgets.s fopen.s fputc.s fputs.s fread.s \ X freopen.s fseek.s ftell.s fwrite.s gets.s perror.s \ X printf.s remove.s rename.s scanf.s setvbuf.s \ X sprintf.s sscanf.s stdio_misc.s tmpfile.s tmpnam.s ungetc.s X XSTDLIB = div.s ldiv.s strtol.s strtoul.s X XCTYPE = ctype.s X XOTHERS = printk.s prints.s cuserid.s getlogin.s getgrent.s getpwent.s X Xobjects: $(STDIO) $(STDLIB) $(CTYPE) $(OTHERS) X Xcrclist: X crc I* M* >crclist X crc *.h >>crclist X crc sys/*.h >>crclist X crc *.c >>crclist / echo x - Makefile.libc sed '/^X/s///' > Makefile.libc << '/' XCURSES = curses.s termcap.s X XMISCELLANEOUS = getpass.s lock.s popen.s putenv.s getopt.s stderr.s \ X itoa.s ffs.s swab.s stb.s getutil.s portio.s X XANSI_UNISTD = ctermid.s cuserid.s execlp.s getcwd.s getlogin.s \ X getgrent.s getpwent.s ttyname.s X XIOCTL = gtty.s stty.s ioctl.s X XAMOEBA = uniqport.s amoeba.s X XTIME = ctime.s X XSTRERROR = strerror.s X XSTDIO = fclose.s fdopen.s fopen.s freopen.s tmpfile.s _valmode.s \ X scanf.s sscanf.s _doscan.s \ X fgets.s fread.s gets.s fgetc.s ungetc.s _filbuf.s \ X printf.s sprintf.s _doprnt.s \ X fputs.s fwrite.s fputc.s _flsbuf.s \ X fseek.s ftell.s perror.s setvbuf.s stdio_misc.s tmpnam.s \ X _ioinit.s _cleanup.s fflush.s _flspbuf.s \ X _bufproc.s _iobproc.s _iobdata.s \ X remove.s rename.s X XNOT_STDIO = mktemp.s printk.s prints.s X XSTDLIB = abort.s abs.s atexit.s bsearch.s div.s getenv.s ldiv.s \ X malloc.s qsort.s rand.s strtol.s strtoul.s system.s \ X lrand.s lsearch.s X XCTYPE = ctype.s X XDIRENT = opendir.s closedir.s telldir.s rewinddir.s seekdir.s readdir.s \ X getdents.s X XSETJMP = setjmp.s X XREGEXP = regexp.s regsub.s X XSTRING_BSD = bcmp.s bcopy.s bzero.s XSTRING_SYSV = index.s rindex.s XSTRING = $(STRING_BSD) $(STRING_SYSV) \ X memccpy.s memchr.s memcmp.s memcpy.s memset.s \ X strstr.s strcat.s strchr.s strcmp.s strcpy.s strcspn.s strlen.s \ X strncat.s strncmp.s strncpy.s strpbrk.s strrchr.s strspn.s strtok.s X XCRYPT = crypt.s X XCLEAN_UNISTD = isatty.s sleep.s X XUNIX = access.s alarm.s chdir.s chmod.s chown.s chroot.s close.s creat.s \ X dup.s dup2.s exec.s fork.s fstat.s getegid.s geteuid.s getgid.s \ X getuid.s kill.s link.s lseek.s brk.s brk2.s brksize.s mknod.s \ X getpid.s getppid.s mount.s open.s pause.s pipe.s read.s setgid.s \ X setuid.s signal.s catchsig.s stat.s stime.s sync.s time.s times.s \ X umask.s umount.s unlink.s utime.s wait.s write.s X XMINIX_INTERFACE = syslib.s call.s message.s sendrec.s X XCOMPILER_INTERNAL = \ X adi.s and.s blm.s cii.s cmi4.s cms.s cmu4.s com.s csa2.s csb2.s \ X cuu.s _dup.s dvi4.s dvu4.s exg.s fakfp.s gto.s iaar.s ilar.s \ X inn.s ior.s isar.s lar2.s loi.s mli4.s mon.s nop.s rck.s \ X rmi4.s rmu4.s sar2.s sbi.s set.s sti.s strhp.s xor.s \ X ret6.s ret8.s lfr6.s lfr8.s retarea.s return.s X XCOMPILER_TRAP = error.s unknown.s fat.s trp.s vars.s X XEXIT = stop.s exit.s X Xlibc.a: .Made X -mv libc.a libc.a.orig X ar q libc.a $(CURSES) X ar q libc.a $(MISCELLANEOUS) X ar q libc.a $(ANSI_UNISTD) X ar q libc.a $(IOCTL) X ar q libc.a $(AMOEBA) X ar q libc.a $(TIME) X ar q libc.a $(STRERROR) X ar q libc.a $(STDIO) X ar q libc.a $(NOT_STDIO) X ar q libc.a $(STDLIB) X ar q libc.a $(CTYPE) X ar q libc.a $(DIRENT) X ar q libc.a $(SETJMP) X ar q libc.a $(REGEXP) X ar q libc.a $(STRING) X ar q libc.a $(CRYPT) X ar q libc.a $(CLEAN_UNISTD) X ar q libc.a $(UNIX) X ar q libc.a $(MINIX_INTERFACE) X ar q libc.a $(COMPILER_INTERNAL) X ar q libc.a $(COMPILER_TRAP) X ar q libc.a $(EXIT) X touch .Made X X.Made: $(CURSES) X.Made: $(MISCELLANEOUS) X.Made: $(ANSI_UNISTD) X.Made: $(IOCTL) X.Made: $(AMOEBA) X.Made: $(TIME) X.Made: $(STRERROR) X.Made: $(STDIO) X.Made: $(NOT_STDIO) X.Made: $(STDLIB) X.Made: $(CTYPE) X.Made: $(DIRENT) X.Made: $(SETJMP) X.Made: $(REGEXP) X.Made: $(STRING) X.Made: $(CRYPT) X.Made: $(UNIX) X.Made: $(MINIX_INTERFACE) X.Made: $(COMPILER_INTERNAL) X.Made: $(COMPILER_TRAP) X.Made: $(EXIT) / echo x - CRCLIST sed '/^X/s///' > CRCLIST << '/' X42976 2909 Install X29509 736 Makefile X49536 3238 Makefile.libc X36390 306 assert.h X04501 1827 ctype.h X16607 894 dirent.h X61144 1267 errno.h X23155 1390 fcntl.h X59055 478 grp.h X36738 293 lib.h X56982 1251 limits.h X36832 166 prototype.h X18121 553 pwd.h X18182 721 setjmp.h X23686 2249 signal.h X46349 1465 stdarg.h X46642 579 stddef.h X41917 6158 stdio.h X42306 1348 stdiolib.h X34643 2233 stdlib.h X31036 2807 string.h X25499 3361 termios.h X10320 1246 time.h X05318 3507 unistd.h X17559 389 utime.h X47700 1421 sys/dirent.h X23639 2125 sys/stat.h X45063 429 sys/times.h X03055 707 sys/types.h X63086 483 sys/utsname.h X56375 887 sys/wait.h X44639 1012 _bufproc.c X09696 202 _cleanup.c X33452 9856 _doprnt.c X52978 8006 _doscan.c X53014 1148 _filbuf.c X01268 1447 _flsbuf.c X17271 728 _flspbuf.c X00706 538 _iobdata.c X38693 1043 _iobproc.c X36193 1515 _ioinit.c X09043 983 _valmode.c X64177 1126 atexit.c X20154 2579 ctype.c X16928 348 cuserid.c X22853 167 div.c X07059 334 exit.c X24358 525 fclose.c X17370 1056 fdopen.c X36047 1371 fflush.c X41316 625 fgetc.c X00549 681 fgets.c X39208 1593 fopen.c X17604 847 fputc.c X34903 625 fputs.c X33170 2925 fread.c X63326 1735 freopen.c X52582 1164 fseek.c X00763 963 ftell.c X36592 3251 fwrite.c X18799 1882 getgrent.c X61455 286 getlogin.c X12848 1852 getpwent.c X63222 424 gets.c X08852 180 ldiv.c X06090 1546 perror.c X48671 1415 printf.c X25746 120 printk.c X01820 1420 prints.c X35554 262 remove.c X32949 1739 rename.c X56330 939 scanf.c X01335 1251 setvbuf.c X60329 1091 sprintf.c X50293 437 sscanf.c X03709 763 stdio_misc.c X34867 1609 strtol.c X63398 1466 strtoul.c X17346 1152 tmpfile.c X49999 993 tmpnam.c X30591 815 ungetc.c /
nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (09/30/89)
echo x - assert.h sed '/^X/s///' > assert.h << '/' X#ifndef __ASSERT_H X#define __ASSERT_H X X/* --- Macros --- */ X#ifndef NDEBUG X#define assert(p) \ X if(!(p)) { \ X fprintf(stderr, "False assertion at line %d in file \"%s\"\n", \ X __LINE__, __FILE__); \ X exit(1); \ X } X#else X#define assert(p) X#endif X X#endif /* !defined __ASSERT_H */ / echo x - ctype.h sed '/^X/s///' > ctype.h << '/' X#ifndef __CTYPE_H X#define __CTYPE_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#define _CT_U 0x01 X#define _CT_L 0x02 X#define _CT_N 0x04 X#define _CT_S 0x08 X#define _CT_P 0x10 X#define _CT_C 0x20 X#define _CT_X 0x40 X#define _CT_SP 0x80 X X/* --- Prototypes --- */ Xint isalnum _PROTO((int c)); Xint isalpha _PROTO((int c)); Xint isascii _PROTO((int c)); Xint iscntrl _PROTO((int c)); Xint isdigit _PROTO((int c)); Xint isgraph _PROTO((int c)); Xint islower _PROTO((int c)); Xint isprint _PROTO((int c)); Xint ispunct _PROTO((int c)); Xint isspace _PROTO((int c)); Xint isupper _PROTO((int c)); Xint isxdigit _PROTO((int c)); Xint toascii _PROTO((int c)); Xint _tolower _PROTO((int c)); Xint _toupper _PROTO((int c)); Xint tolower _PROTO((int c)); Xint toupper _PROTO((int c)); X X/* --- Storage --- */ Xextern char _ctype[]; X#ifdef _SAFEMACRO Xextern int _ct_c; X#endif X X/* --- Macros --- */ X#define isalnum(c) ((_ctype+1)[c] & (_CT_U|_CT_L|_CT_N)) X#define isalpha(c) ((_ctype+1)[c] & (_CT_U|_CT_L)) X#define isascii(c) ((unsigned)(c) <= 0x7f) X#define iscntrl(c) ((_ctype+1)[c] & (_CT_C)) X#define isdigit(c) ((_ctype+1)[c] & (_CT_N)) X#define isgraph(c) ((_ctype+1)[c] & (_CT_U|_CT_L|_CT_N|_CT_P)) X#define islower(c) ((_ctype+1)[c] & (_CT_L)) X#define isprint(c) ((_ctype+1)[c] & (_CT_U|_CT_L|_CT_N|_CT_P|_CT_SP)) X#define ispunct(c) ((_ctype+1)[c] & (_CT_P)) X#define isspace(c) ((_ctype+1)[c] & (_CT_S|_CT_SP)) X#define isupper(c) ((_ctype+1)[c] & (_CT_U)) X#define isxdigit(c) ((_ctype+1)[c] & (_CT_N|_CT_X)) X X#define toascii(c) ((c) & 0x7f) X#define _tolower(c) ((c) - 'A' + 'a') X#define _toupper(c) ((c) - 'a' + 'A') X#ifdef _SAFEMACRO X#define tolower(c) (_ct_c = (c), _isupper(_ct_c) ? _tolower(_ct_c) : _ct_c) X#define toupper(c) (_ct_c = (c), _islower(_ct_c) ? _toupper(_ct_c) : _ct_c) X#endif X X#endif /* !defined __CTYPE_H */ / echo x - dirent.h sed '/^X/s///' > dirent.h << '/' X#ifndef __DIRENT_H X#define __DIRENT_H X X/* X <dirent.h> -- definitions for SVR3 directory access routines X X last edit: 25-Apr-1987 D A Gwyn X*/ X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <dirent.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X#include <sys/dirent.h> X X/* --- Types --- */ Xtypedef struct { X int dd_fd; /* file descriptor */ X int dd_loc; /* offset in block */ X int dd_size; /* amount of valid data */ X char *dd_buf; /* -> directory block */ X} DIR; /* stream data from opendir() */ X X/* --- Prototypes --- */ XDIR *opendir _PROTO((char *dirname)); Xstruct dirent *readdir _PROTO((DIR *dirp)); Xvoid rewinddir _PROTO((DIR *dirp)); Xint closedir _PROTO((DIR *dirp)); Xvoid seekdir _PROTO((DIR *dirp, off_t loc)); /* not POSIX */ Xoff_t telldir _PROTO((DIR *dirp)); /* not POSIX */ X X#endif /* !defined __DIRENT_H */ / echo x - errno.h sed '/^X/s///' > errno.h << '/' X#ifndef __ERRNO_H X#define __ERRNO_H X X/* --- Constants --- */ X#define OK 0 X#define ERROR 1 X#define EPERM 1 X#define ENOENT 2 X#define ESRCH 3 X#define EINTR 4 X#define EIO 5 X#define ENXIO 6 X#define E2BIG 7 X#define ENOEXEC 8 X#define EBADF 9 X#define ECHILD 10 X#define EAGAIN 11 X#define ENOMEM 12 X#define EACCES 13 X#define EFAULT 14 X#define ENOTBLK 15 X#define EBUSY 16 X#define EEXIST 17 X#define EXDEV 18 X#define ENODEV 19 X#define ENOTDIR 20 X#define EISDIR 21 X#define EINVAL 22 X#define ENFILE 23 X#define EMFILE 24 X#define ENOTTY 25 X#define ETXTBSY 26 X#define EFBIG 27 X#define ENOSPC 28 X#define ESPIPE 29 X#define EROFS 30 X#define EMLINK 31 X#define EPIPE 32 X#define EDOM 33 X#define ERANGE 34 X X#define E_LOCKED 101 X#define E_BAD_CALL 102 X#define E_LONG_STRING 103 X X/* --- Storage --- */ Xextern int errno; X X#endif /* !defined __ERRNO_H */ / echo x - fcntl.h sed '/^X/s///' > fcntl.h << '/' X#ifndef __FCNTL_H X#define __FCNTL_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <fcntl.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X /* --- For open(2) --- */ X#define O_RDONLY 0 X#define O_WRONLY 1 X#define O_RDWR 2 X#define O_NONBLOCK 0x0004 X#define O_APPEND 0x0008 X#define O_NOCTTY 0x0100 X#define O_CREAT 0x0200 X#define O_TRUNC 0x0400 X#define O_EXCL 0x0800 X /* --- For fcntl(2) --- */ X#define F_DUPFD 0 X#define F_GETFD 1 X#define F_SETFD 2 X#define F_GETFL 3 X#define F_SETFL 4 X#define F_GETLK 7 X#define F_SETLK 8 X#define F_SETLKW 9 X /* --- fcntl(2) descriptor flags --- */ X#define FD_CLOEXEC 0x4000 /* Arbitrary!! */ X /* --- fcntl(2) lock flags --- */ X#define F_RDLCK 1 X#define F_WRLCK 2 X#define F_UNLCK 3 X /* --- Compatibility --- */ X#ifdef _SYSV X#define O_NDELAY O_NONBLOCK X#endif X X#ifdef _BSD X#define FNDELAY O_NONBLOCK X#define FAPPEND O_APPEND X#define FCREAT O_CREAT X#define FTRUNC O_TRUNC X#define FEXCL O_EXCL X#define F_GETOWN 5 X#define F_SETOWN 6 X#endif X X/* --- Structures --- */ Xstruct flock { X short l_type; X short l_whence; X off_t l_start; X off_t l_len; X pid_t l_pid; X}; X X/* --- Prototypes --- */ Xint open _PROTO((char *path, int oflag, ...)); Xint creat _PROTO((char *path, mode_t mode)); Xint fcntl _PROTO((int fd, int cmd, ...)); X X#endif /* !defined __FCNTL_H */ / echo x - grp.h sed '/^X/s///' > grp.h << '/' X#ifndef __GRP_H X#define __GRP_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <grp.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Structures --- */ Xstruct group { X char *gr_name; X char *gr_passwd; /* not required by POSIX */ X gid_t gr_gid; X char **gr_mem; X}; X X/* --- Prototypes --- */ Xstruct group *getgrgid _PROTO((gid_t gid)); Xstruct group *getgrnam _PROTO((char *name)); X X#endif /* !defined __GRP_H */ / echo x - lib.h sed '/^X/s///' > lib.h << '/' X#include <minix/const.h> X#include <minix/type.h> X#include <minix/callnr.h> X#include <errno.h> X Xextern message M; X X#define MM 0 X#define FS 1 X Xextern int callm1(), callm3(), callx(), len(); Xextern int errno; Xextern int begsig(); /* interrupts all vector here */ / echo x - limits.h sed '/^X/s///' > limits.h << '/' X#ifndef __LIMITS_H X#define __LIMITS_H X X/* --- Constants --- */ X#define CHAR_BIT 8 X#define SCHAR_MIN -128 X#define SCHAR_MAX 127 X#define CHAR_MIN -128 /* char is signed by default */ X#define CHAR_MAX 127 X#define UCHAR_MAX 255 X#define SHRT_MIN -32767 /* PENDING - Minix 1.3 compiler bug */ X#define SHRT_MAX 32767 X#define USHRT_MAX 65535 X#define INT_MIN -32767 /* PENDING - Minix 1.3 compiler bug */ X#define INT_MAX 32767 X#define UINT_MAX 65535 X#define LONG_MIN -2147483647 /* PENDING - Minix 1.3 compiler bug */ X#define LONG_MAX 2147483647 X#define ULONG_MAX 4294967295 X X#ifdef _POSIX_SOURCE X#define _POSIX_ARG_MAX 4096 X#define _POSIX_CHILD_MAX 6 X#define _POSIX_LINK_MAX 8 X#define _POSIX_MAX_CANON 255 X#define _POSIX_MAX_INPUT 255 X#define _POSIX_NAME_MAX 14 X#define _POSIX_NGROUPS_MAX 0 X#define _POSIX_OPEN_MAX 16 X#define _POSIX_PATH_MAX 255 X#define _POSIX_PIPE_BUF 512 X X#define NGROUPS_MAX 0 X#define ARG_MAX 2048 /* PENDING - POSIX requires >= 4096 */ X#define OPEN_MAX 20 X#define LINK_MAX 127 X#define MAX_CANON 256 X#define MAX_INPUT 256 X#define NAME_MAX 14 X#define PATH_MAX 127 /* PENDING - POSIX requires >= 256 */ X#define PIPE_BUF 7168 X X#endif /* defined _POSIX_SOURCE */ X X#endif /* !defined __LIMITS_H */ / echo x - prototype.h sed '/^X/s///' > prototype.h << '/' X#ifndef __PROTOTYPE_H X#define __PROTOTYPE_H X X#ifdef __STDC__ X#define _PROTO(p) p X#else X#define _PROTO(p) () X#define const X#endif X X#endif /* !defined __PROTOTYPE_H */ / echo x - pwd.h sed '/^X/s///' > pwd.h << '/' X#ifndef __PWD_H X#define __PWD_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <pwd.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Structures --- */ Xstruct passwd { X char *pw_name; X char *pw_passwd; /* not required by POSIX */ X uid_t pw_uid; X gid_t pw_gid; X char *pw_gecos; /* not required by POSIX */ X char *pw_dir; X char *pw_shell; X}; X X/* --- Prototypes --- */ Xstruct passwd *getpwuid _PROTO((uid_t uid)); Xstruct passwd *getpwnam _PROTO((char *name)); X X#endif /* !defined __PWD_H */ / echo x - setjmp.h sed '/^X/s///' > setjmp.h << '/' X#ifndef __SETJMP_H X#define __SETJMP_H X X/* --- Inclusions --- */ X#include "../include/prototype.h" X X/* --- Constants --- */ X#ifndef _JB_LEN X#ifdef i8088 X#define _JB_LEN 3 X#else X#ifdef ATARI_ST X#define _JB_LEN 13 X#else X#error Either i8088 or ATARI_ST must be defined! X#endif X#endif X#endif X X/* --- Types --- */ Xtypedef int jmp_buf[_JB_LEN]; X#ifdef _POSIX_SOURCE Xtypedef int sigjmp_buf[_JB_LEN + sizeof(long)] /* PENDING - just a guess! */ X#endif X X/* --- Prototypes --- */ Xint setjmp _PROTO((jmp_buf env)); Xvoid longjmp _PROTO((jmp_buf env, int value)); X#ifdef _POSIX_SOURCE Xint sigsetjmp _PROTO((sigjmp_buf env, int savemask)); Xvoid siglongjmp _PROTO((sigjmp_buf env, int value)); X#endif X X#endif /* !defined __SETJMP_H */ / echo x - signal.h sed '/^X/s///' > signal.h << '/' X#ifndef __SIGNAL_H X#define __SIGNAL_H X X/* --- Prerequisites --- */ X#ifdef _POSIX_SOURCE X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <signal.h> X#endif X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#define SIG_ERR (void (*)())-1 X#define SIG_DFL (void (*)())0 X#define SIG_IGN (void (*)())1 X X#define NSIG 16 /* PENDING! This limit needs to be 32 but the code */ X#define NR_SIGS NSIG /* PENDING! in the kernel isn't fixed yet. Also, */ X#define STACK_FAULT 16 /* PENDING! these names pollute the name space. */ X X#define SIGHUP 1 /* hangup */ X#define SIGINT 2 /* interrupt (DEL) */ X#define SIGQUIT 3 /* quit (ASCII FS) */ X#define SIGILL 4 /* illegal instruction (not reset when caught)*/ X#define SIGTRAP 5 /* trace trap (not reset when caught) */ X#define SIGABRT 6 /* abnormal termination */ X#define SIGIOT SIGABRT /* compatibility - IOT instruction (PDP 11!) */ X#define SIGEMT 7 /* EMT instruction (PDP 11!) */ X#define SIGFPE 8 /* floating point exception */ X#define SIGKILL 9 /* kill (cannot be caught or ignored) */ X#define SIGBUS 10 /* bus error */ X#define SIGSEGV 11 /* segmentation violation */ X#define SIGSYS 12 /* bad argument to system call */ X#define SIGPIPE 13 /* write on a pipe with no one to read it */ X#define SIGALRM 14 /* alarm clock */ X#define SIGTERM 15 /* software termination signal from kill */ X/*#define SIGUSR1 30 /* user defined signal 1 */ X/*#define SIGUSR2 31 /* user defined signal 2 */ X X /* --- Job control (POSIX requires definition but not support) --- */ X#define SIGSTOP 17 /* stop (cannot be caught or ignored) */ X#define SIGTSTP 18 /* interactive stop signal */ X#define SIGCONT 19 /* continue if stopped */ X#define SIGCHLD 20 /* child process terminated or stopped */ X#define SIGTTIN 21 /* to reader's process group on background read */ X#define SIGTTOU 22 /* to writer's process group on background write */ X X/* --- Types --- */ Xtypedef int sig_atomic_t; X X/* --- Function prototypes --- */ Xint raise _PROTO((int sig)); Xvoid (*signal _PROTO((int sig, void (*func)(int)))) _PROTO((int)); X#ifdef _POSIX_SOURCE Xint kill _PROTO((pid_t pid, int sig)); X/* PENDING - A zillion sig* functions required by POSIX are missing. */ X#endif X X#endif /* !defined __SIGNAL_H */ / echo x - stdarg.h sed '/^X/s///' > stdarg.h << '/' X#ifndef __STDARG_H X#define __STDARG_H X X/* --- Types --- */ X#ifndef _VA_LIST X#define _VA_LIST Xtypedef char * va_list; X#endif X X/* --- Definitions --- */ X /* --- Add your favourite machine here! --- */ X /* _STK_OP indicates which way addresses change as one moves X along an argument list X _STK_OPE is _STK_OP with an = behind it X _STK_ALIGN is the minimum number of bytes moved by a stack PUSH X _STK_OFFSET is the offset of an argument after the pointer has X been bumped. X For example, if a machine has 4 bytes to a word, little endian, X grows its stack downwards and always pushes at least a word, X then we should define: X _STK_OP + X _STK_OP += X _STK_ALIGN 4 X _STK_OFFSET(v) ((sizeof(v) == 1) ? -4 : ((sizeof(v) == 2) ? -2 : -1)) X */ X X#ifdef i8088 X#define _STK_OP + /* stack grows down */ X#define _STK_OPE += X#define _STK_ALIGN 2 /* PUSH moves at least 2 bytes */ X#define _STK_OFFSET(v) ((sizeof(v) < 2) ? -2 : -1) /* little endian */ X#endif X X#ifdef ATARI_ST X#define _STK_OP + /* stack grows down */ X#define _STK_OPE += X#define _STK_ALIGN 2 /* PUSH moves at least 2 bytes */ X#define _STK_OFFSET(v) -1 /* big endian */ X#endif X X#define _STK_BUMP(v) ((sizeof(v) < _STK_ALIGN) ? _STK_ALIGN : sizeof(v)) X X/* --- Macros --- */ X#define va_start(ap, last) ((ap) = (va_list) &(last) _STK_OP _STK_BUMP(last)) X#define va_arg(ap, type) (((type *) ((ap) _STK_OPE _STK_BUMP(type)))[_STK_OFFSET(type)]) X#define va_end(ap) X X#endif /* !defined __STDARG_H */ / echo x - stddef.h sed '/^X/s///' > stddef.h << '/' X#ifndef __STDDEF_H X#define __STDDEF_H X X/* --- Constants --- */ X#ifndef __STDC__ X#define NULL 0 X#else X#define NULL ((void *) 0) X#endif X X/* --- Types --- */ X#ifndef __SIZE_T X#define __SIZE_T Xtypedef unsigned int size_t; X#endif X X#ifndef __PTRDIFF_T X#define __PTRDIFF_T Xtypedef int ptrdiff_t; /* Should be like size_t plus a sign bit! */ X#endif X X#ifndef __WCHAR_T X#define __WCHAR_T Xtypedef char wchar_t; /* No special support for wide characters! */ X#endif X X/* --- Macros --- */ X#define offsetof(type, member) ((size_t) (&(((type *) 0)->member))) X X#endif /* !defined __STDDEF_H */ / echo x - stdio.h sed '/^X/s///' > stdio.h << '/' X#ifndef __STDIO_H X#define __STDIO_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#ifndef __STDC__ X#define NULL 0 X#else X#define NULL ((void *) 0) X#endif X#define EOF (-1) X#define BUFSIZ 1024 X X#define _IOFBF 0 X#define _IOLBF _IO_LBUF X#define _IONBF (-1) X#define L_tmpnam (4 + 1 + FILENAME_MAX) /* "/tmp/" + file name + '\0' */ X#define TMP_MAX 32767 /* Arbitrary! */ X#define SEEK_SET 0 X#define SEEK_CUR 1 X#define SEEK_END 2 X#ifdef _POSIX_SOURCE X#ifdef __LIMITS_H X#define FILENAME_MAX (NAME_MAX + 1) /* includes room for trailing '\0' */ X#define FOPEN_MAX OPEN_MAX X#endif X#define L_cuserid (30+1) /* Arbitrary! */ X#define L_ctermid (10+1) /* Arbitrary! */ X#endif X#ifndef FILENAME_MAX X#define FILENAME_MAX 15 /* 14 character file name + '\0' */ X#define FOPEN_MAX 20 X#endif X X/* --- Types --- */ X#ifndef __SIZE_T X#define __SIZE_T Xtypedef unsigned int size_t; X#endif X X#ifndef _VA_LIST X#define _VA_LIST Xtypedef char * va_list; X#endif X Xtypedef long fpos_t; X Xtypedef struct { X int _io_fd; X unsigned int _io_flags; X int _io_count; X int _io_bufsiz; X unsigned char *_io_buf; X union { X unsigned char *_io_ptr; X int _io_char; X } _io; X} FILE; X X/* --- Definitions --- */ X#define stdin (&_iob[0]) X#define stdout (&_iob[1]) X#define stderr (&_iob[2]) X /* --- Flag bits --- */ X#define _IO_READ 0x0001 X#define _IO_WRITE 0x0002 X#define _IO_UPDATE 0x0004 X#define _IO_LBUF 0x0008 X#define _IO_MYBUF 0x0010 X#define _IO_EOF 0x0020 X#define _IO_ERR 0x0040 X#define _IO_STRING 0x0080 X#define _IO_TEMP 0x0100 X#define _IO_TTY 0x1000 X#ifdef _V7 X#define _IO_APPEND 0x4000 /* won't be needed with Posix */ X#define _IO_NEEDSEEK 0x8000 /* won't be needed with Posix */ X#endif X X/* --- Prototypes --- */ X /* --- Streams: open and close --- */ Xint fclose _PROTO((FILE *stream)); X#ifdef _POSIX_SOURCE XFILE *fdopen _PROTO((int fd, const char *mode)); X#endif XFILE *fopen _PROTO((const char *filename, const char *mode)); XFILE *freopen _PROTO((const char *filename, const char *mode, FILE *stream)); XFILE *tmpfile _PROTO((void)); X /* --- Streams: input --- */ Xint fgetc _PROTO((FILE *stream)); Xchar *fgets _PROTO((char *s, int n, FILE *stream)); Xsize_t fread _PROTO((void *ptr, size_t size, size_t nmemb, FILE *stream)); Xint fscanf _PROTO((FILE *stream, const char *format, ...)); Xint getc _PROTO((FILE *stream)); Xint getchar _PROTO((void)); Xchar *gets _PROTO((char *s)); Xint scanf _PROTO((const char *format, ...)); Xint sscanf _PROTO((const char *s, const char *format, ...)); Xint ungetc _PROTO((int c, FILE *stream)); X /* --- Streams: output --- */ Xint fprintf _PROTO((FILE *stream, const char *format, ...)); Xint fputc _PROTO((int c, FILE *stream)); Xint fputs _PROTO((const char *s, FILE *stream)); Xsize_t fwrite _PROTO((const void *ptr, size_t size, size_t nmemb, FILE *stream)); Xint printf _PROTO((const char *format, ...)); Xint putc _PROTO((int c, FILE *stream)); Xint putchar _PROTO((int c)); Xint puts _PROTO((const char *s)); Xint sprintf _PROTO((char *s, const char *format, ...)); Xint vfprintf _PROTO((FILE *stream, const char *format, va_list arg)); Xint vprintf _PROTO((const char *format, va_list arg)); Xint vsprintf _PROTO((char *s, const char *format, va_list arg)); X /* --- Streams: inquiry and control --- */ Xvoid clearerr _PROTO((FILE *stream)); Xint feof _PROTO((FILE *stream)); Xint ferror _PROTO((FILE *stream)); Xint fflush _PROTO((FILE *stream)); Xint fgetpos _PROTO((FILE *stream, fpos_t *pos)); X#ifdef _POSIX_SOURCE Xint fileno _PROTO((FILE *stream)); X#endif Xint fseek _PROTO((FILE *stream, long int offset, int whence)); Xint fsetpos _PROTO((FILE *stream, const fpos_t *pos)); Xlong int ftell _PROTO((FILE *stream)); Xvoid rewind _PROTO((FILE *stream)); Xvoid setbuf _PROTO((FILE *stream, char *buf)); Xint setvbuf _PROTO((FILE *stream, char *buf, int mode, size_t size)); X /* --- File system manipulation --- */ Xint remove _PROTO((const char *filename)); Xint rename _PROTO((const char *old, const char *new)); X /* --- Miscellaneous --- */ Xvoid perror _PROTO((const char *s)); Xchar *tmpnam _PROTO((char *s)); X X/* --- Some standard functions are defined below as macros. In --- */ X/* --- general, using the macros results in faster code at the --- */ X/* --- expense of larger code size and increased compile time. --- */ X/* --- Any macro may be #undef'ed to expose a library function. --- */ X X/* --- The macros getc() and putc() are "unsafe" in that they --- */ X/* --- evaluate their arguments more than once. By default, --- */ X/* --- the safe alternatives are the functions fgetc()/fputc(). --- */ X/* --- #define _SAFEMACRO will define fgetc()/fputc() as --- */ X/* --- safe macros, at the cost of increased storage. --- */ X X /* --- Streams: input --- */ X#ifdef _SAFEMACRO X#define fgetc(f) (_io_f = (f), getc(_io_f)) X#endif X#define getc(f) ((--(f)->_io_count >= 0) ? *(f)->_io._io_ptr++ : _filbuf(f)) X#define getchar() getc(stdin) X /* --- Streams: output --- */ X#ifdef _SAFEMACRO X#define fputc(c, f) (_io_c = (c), _io_f = (f), putc(_io_c, _io_f)) X#endif X#define putc(c, f) \ X ( \ X ((--(f)->_io_count < 0) || (_io_testflag(f, _IO_LBUF) && c == '\n')) \ X ? _flsbuf(c, f) \ X : (int) (*(f)->_io._io_ptr++ = c) \ X ) X#define putchar(c) putc(c, stdout) X#define puts(s) \ X ((fputs(s, stdout) >= 0) ? ((putchar('\n') == '\n') ? 0 : EOF) : EOF) X#define vfprintf(f, fmt, ap) _doprnt(f, fmt, ap) X#define vprintf(fmt, ap) _doprnt(stdout, fmt, ap) X /* --- Streams: inquiry and control --- */ X#define clearerr(f) _io_clearflag((f), (_IO_EOF | _IO_ERR)) X#define feof(f) _io_testflag((f), _IO_EOF) X#define ferror(f) _io_testflag((f), _IO_ERR) X#define _io_testflag(f, flag) ((f)->_io_flags & (flag)) X#ifdef _POSIX_SOURCE X#define fileno(f) ((f)->_io_fd) X#endif /* defined _POSIX_SOURCE */ X#define fgetpos(f, p) ((*(p) = (fpos_t) ftell(f)) >= 0L) ? 0 : EOF) X#define fsetpos (f, p) fseek((f), *(p), SEEK_SET) X#define setbuf(f, b) setvbuf((f), (b), ((b) == NULL) ? _IONBF : _IOFBF, BUFSIZ) X /* --- File system manipulation --- */ X#define remove(p) unlink(p) X X/* --- Storage --- */ Xextern FILE _iob[FOPEN_MAX]; X X#ifdef _SAFEMACRO Xextern FILE *_io_f; Xextern int _io_c; X#endif X X#endif /* !defined __STDIO_H */ / echo x - stdiolib.h sed '/^X/s///' > stdiolib.h << '/' X#ifndef __STDIOLIB_H X#define __STDIOLIB_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#define _IO_NEVER (-1) /* MAGIC count for virgin streams */ X#define P_tmpdir "/tmp" /* directory for temporary files */ X X/* --- Prototypes --- */ Xvoid _bufalloc _PROTO((FILE *stream)); Xvoid _buffree _PROTO((FILE *stream)); Xvoid _cleanup _PROTO((void)); Xint _doprnt _PROTO((FILE *stream, const char *format, va_list arg)); Xint _doscan _PROTO((int is_string, void *source, const char *format, va_list arg)); Xint _filbuf _PROTO((FILE *stream)); Xint _flsbuf _PROTO((int c, FILE *stream)); Xint _flspbuf _PROTO((FILE *stream)); XFILE *_ioballoc _PROTO((void)); Xvoid _iobfree _PROTO((FILE *stream)); Xint _iobindex _PROTO((FILE *stream)); Xvoid _i_init _PROTO((FILE *stream)); Xvoid _o_init _PROTO((FILE *stream)); Xint _valmode _PROTO((const char *mode)); X X/* --- Macros --- */ X#define _io_valid(f) (_iobindex(f) >= 0) X#define _io_setflag(f, flag) ((f)->_io_flags |= (flag)) X#define _io_clearflag(f, flag) ((f)->_io_flags &= ~(flag)) X X#ifdef NDEBUG X#define _io_assert(condition) X#define _io_guarded(stmt) X#else X#define _io_assert(condition) \ X if (!(condition)) \ X return (_IO_ERRVAL) X#define _io_guarded(stmt) (stmt) X#endif /* !defined NDEBUG */ X X/* --- Storage --- */ Xextern void (*__cleanup)(); X X#endif /* !defined __STDIOLIB_H */ / echo x - stdlib.h sed '/^X/s///' > stdlib.h << '/' X#ifndef __STDLIB_H X#define __STDLIB_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#ifndef __STDC__ X#define NULL 0 X#else X#define NULL ((void *) 0) X#endif X#define RAND_MAX 32767 X#define EXIT_SUCCESS 0 X#define EXIT_FAILURE 1 X X/* --- Types --- */ X#ifndef __SIZE_T X#define __SIZE_T Xtypedef unsigned int size_t; X#endif X X#ifndef __WCHAR_T X#define __WCHAR_T Xtypedef char wchar_t; /* No special support for wide characters! */ X#endif X X#ifndef __DIV_T X#define __DIV_T Xtypedef struct {int quot; int rem;} div_t; X#endif X X#ifndef __LDIV_T X#define __LDIV_T Xtypedef struct {long int quot; long int rem;} ldiv_t; X#endif X X/* --- Prototypes --- */ X /* --- String conversion --- */ Xdouble atof _PROTO((const char *nptr)); Xint atoi _PROTO((const char *nptr)); Xlong atol _PROTO((const char *nptr)); Xdouble strtod _PROTO((const char *nptr, char **endptr)); Xlong strtol _PROTO((const char *nptr, char **endptr, int base)); Xunsigned long strtoul _PROTO((const char *nptr, char **endptr, int base)); X /* --- Pseudo-random sequence generation --- */ Xint rand _PROTO((void)); Xvoid srand _PROTO((unsigned int seed)); X /* --- Memory management --- */ Xvoid *calloc _PROTO((size_t nmemb, size_t size)); Xvoid free _PROTO((void *ptr)); Xvoid *malloc _PROTO((size_t size)); Xvoid *realloc _PROTO((void *ptr, size_t size)); X /* --- Communication with the environment --- */ Xvoid abort _PROTO((void)); Xint atexit _PROTO((void (*func)(void))); Xvoid exit _PROTO((int status)); Xchar *getenv _PROTO((const char *name)); Xint system _PROTO((const char *string)); X /* --- Searching and sorting --- */ Xvoid *bsearch _PROTO((const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))); Xvoid qsort _PROTO((void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))); X /* --- Integer arithmetic --- */ Xint abs _PROTO((int j)); Xdiv_t div _PROTO((int numer, int denom)); Xlong int labs _PROTO((long int j)); Xldiv_t ldiv _PROTO((long int numer, long int denom)); X /* --- Multibyte characters --- */ X/* Nothing implemented! */ X X/* --- Macros --- */ X#define atoi(nptr) ((int) strtol((nptr), NULL, 10)) X#define atol(nptr) strtol((nptr), NULL, 10) X X#endif /* !defined __STDLIB_H */ / echo x - string.h sed '/^X/s///' > string.h << '/' X#ifndef __STRING_H X#define __STRING_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#ifndef __STDC__ X#define NULL 0 X#else X#define NULL ((void *) 0) X#endif X X/* --- Types --- */ X#ifndef __SIZE_T X#define __SIZE_T Xtypedef unsigned int size_t; X#endif X X/* --- Prototypes --- */ X/* X# String library. Author: Henry Spencer X X# Configuration settings: how should "size_t", "void *", "const" be written? X# "size_t" is what's needed to hold the result of sizeof; beware of problems X# with compatibility here, because X3J11 uses this for e.g. the third X# argument of strncpy() as well. You may need to make it "int" even if X# this is a lie. "void *" is the generic pointer type, "char *" in most X# existing implementations. "const" is the keyword marking read-only X# variables and parameters, unimplemented in most existing implementations. X# These things need to be defined this way because they must be fitted into X# both the .h files and the .c files; see the make instructions for string.h X# in the Makefile. X XSIZET = int XVOIDSTAR = char * XLVOIDSTAR = char* # Lint shell file has problems with * alone. Barf. XCONST = X*/ X X/* X * String functions. X */ X Xvoid *memcpy _PROTO((void *dst, const void *src, size_t size)); Xvoid *memccpy _PROTO((void *dst, const void *src, int ucharstop, size_t size)); Xchar *strcpy _PROTO((char *dst, const char *src)); Xchar *strncpy _PROTO((char *dst, const char *src, size_t size)); Xchar *strcat _PROTO((char *dst, const char *src)); Xchar *strncat _PROTO((char *dst, const char *src, size_t size)); Xint memcmp _PROTO((const void *s1, const void *s2, size_t size)); Xint strcmp _PROTO((const char *s1, const char *s2)); Xint strncmp _PROTO((const char *s1, const char *s2, size_t size)); Xvoid *memchr _PROTO((const void *s, int ucharwanted, size_t size)); Xchar *strchr _PROTO((const char *s, int charwanted)); Xsize_t strcspn _PROTO((const char *s, const char *reject)); Xchar *strpbrk _PROTO((const char *s, const char *breakat)); Xchar *strrchr _PROTO((const char *s, int charwanted)); Xsize_t strspn _PROTO((const char *s, const char *accept)); Xchar *strstr _PROTO((const char *s, const char *wanted)); Xchar *strtok _PROTO((char *s, const char *delim)); Xvoid *memset _PROTO((void *s, int ucharfill, size_t size)); Xsize_t strlen _PROTO((const char *s)); X X/* X * V7 and Berklix compatibility. X */ X#ifdef _V7 Xchar *index _PROTO((const char *s, int charwanted)); Xchar *rindex _PROTO((const char *s, int charwanted)); X#endif X#ifdef _BSD Xint bcopy _PROTO((const char *src, char *dst, int length)); Xint bcmp _PROTO((const char *s1, const char *s2, int length)); Xint bzero _PROTO((char *dst, int length)); X#endif X X/* X * Putting this in here is really silly, but who am I to argue with X3J11? X */ Xchar *strerror _PROTO((int errnum)); X X#endif /* !defined __STRING_H */ / echo x - termios.h sed '/^X/s///' > termios.h << '/' X#ifndef __TERMIOS_H X#define __TERMIOS_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* PENDING - Fill these in when implemented. */ X/* PENDING - POSIX insists that all must be defined, even if unsupported. */ X/* --- Constants --- */ X /* --- Input modes (c_iflag) --- */ X#define BRKINT /* Signal interrupt on break */ X#define ICRNL /* Map CR to NL on input */ X#define IGNBRK /* Ignore break condition */ X#define IGNCR /* Ignore CR */ X#define IGNPAR /* Ignore characters with parity errors */ X#define INLCR /* Map NL to CR on input */ X#define INPCK /* Enable input parity check */ X#define ISTRIP /* Strip character */ X#define IXOFF /* Enable start/stop input control */ X#define IXON /* Enable start/stop output control */ X#define PARMRK /* Mark parity errors */ X /* --- Output modes (c_oflag) --- */ X#define OPOST /* Perform output processing */ X /* --- Control modes (c_cflag) --- */ X#define CLOCAL /* Ignore modem status lines */ X#define CREAD /* Enable receiver */ X#define CSIZE /* Number of bits per byte */ X#define CS5 /* 5 bits */ X#define CS6 /* 6 bits */ X#define CS7 /* 7 bits */ X#define CS8 /* 8 bits */ X#define CSTOPB /* Send two stop bits, else one */ X#define HUPCL /* Hang up on last close */ X#define PARENB /* Parity enable */ X#define PARODD /* Odd parity, else even */ X /* --- Local modes (c_lflag) --- */ X#define ECHO /* Enable echo */ X#define ECHOE /* Echo ERASE as an error-correcting BS */ X#define ECHOK /* Echo KILL */ X#define ECHONL /* Echo '\n' */ X#define ICANON /* Canonical input (erase and kill) */ X#define IEXTEN /* Enable extended functions */ X#define ISIG /* Enable signals */ X#define NOFLSH /* Disable flush after interrupt, quit, suspend */ X#define TOSTOP /* Send SIGTTOU for background output */ X /* --- Special control characters --- */ X#define NCCS /* Number of control characters */ X#define VEOF X#define VEOL X#define VERASE X#define VINTR X#define VKILL X#define VMIN X#define VQUIT X#define VSUSP X#define VTIME X#define VSTART X#define VSTOP X /* --- Line speeds --- */ X#define B0 /* Hang up */ X#define B50 X#define B75 X#define B110 X#define B134 X#define B150 X#define B200 X#define B300 X#define B600 X#define B1200 X#define B1800 X#define B2400 X#define B4800 X#define B9600 X#define B19200 X#define B38400 X X/* --- Types --- */ X#ifndef __TCFLAG_T X#define __TCFLAG_T Xtypedef unsigned int tcflag_t; X#endif X X#ifndef __CC_T X#define __CC_T Xtypedef unsigned int cc_t; X#endif X X#ifndef __SPEED_T X#define __SPEED_T Xtypedef unsigned char speed_t; X#endif X X/* --- Structures --- */ Xstruct termios { X tcflag_t c_iflag; X tcflag_t c_oflag; X tcflag_t c_cflag; X tcflag_t c_lflag; X cc_t c_cc[NCCS]; X speed_t c_ispeed; X speed_t c_ospeed; X}; X X/* --- Prototypes --- */ Xspeed_t cfgetospeed _PROTO((struct termios *termios_p)); Xspeed_t cfsetospeed _PROTO((struct termios *termios_p, speed_t speed)); Xspeed_t cfgetispeed _PROTO((struct termios *termios_p)); Xspeed_t cfsetispeed _PROTO((struct termios *termios_p, speed_t speed)); Xint tcgetattr _PROTO((int fd, struct termios *termios_p)); Xint tcsetattr _PROTO((int fd, int actions, struct termios *termios_p)); Xint tcsendbreak _PROTO((int fd, int duration)); Xint tcdrain _PROTO((int fd)); Xint tcflush _PROTO((int fd, int queue_selector)); Xint tcflow _PROTO((int fd, int action)); X X#endif /* !defined __TERMIOS_H */ / echo x - time.h sed '/^X/s///' > time.h << '/' X#ifndef __TIME_H X#define __TIME_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#ifndef __STDC__ X#define NULL 0 X#else X#define NULL ((void *) 0) X#endif X#define CLOCKS_PER_SEC 60 X#define CLK_TCK CLOCKS_PER_SEC /* PENDING - looks like ANSI won't like this */ X X/* --- Types --- */ X#ifndef __SIZE_T X#define __SIZE_T Xtypedef unsigned int size_t; X#endif X X#ifndef __CLOCK_T X#define __CLOCK_T Xtypedef long int clock_t; X#endif X X#ifndef __TIME_T X#define __TIME_T Xtypedef long int time_t; X#endif X X/* --- Structures --- */ Xstruct tm { X int tm_sec; X int tm_min; X int tm_hour; X int tm_mday; X int tm_mon; X int tm_year; X int tm_wday; X int tm_yday; X int tm_isdst; X}; X X/* --- Prototypes --- */ Xchar *asctime _PROTO((const struct tm *timeptr)); Xclock_t clock _PROTO((void)); Xchar *ctime _PROTO((time_t *timer)); Xdouble difftime _PROTO((time_t time1, time_t time2)); Xstruct tm *gmtime _PROTO((const time_t *timer)); Xstruct tm *localtime _PROTO((const time_t *timer)); Xtime_t mktime _PROTO((struct tm *timeptr)); Xsize_t strftime _PROTO((char *s, size_t maxsize, const char *format, const struct tm *timeptr)); Xtime_t time _PROTO((time_t *timer)); X#ifdef _POSIX_SOURCE Xvoid tzset _PROTO((void)); X#endif X X#endif /* !defined __TIME_H */ / echo x - unistd.h sed '/^X/s///' > unistd.h << '/' X#ifndef __UNISTD_H X#define __UNISTD_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <unistd.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#ifndef __STDC__ X#define NULL 0 X#else X#define NULL ((void *) 0) X#endif X#define _POSIX_VERSION 198808L X X/* --- For access(2) --- */ X#define R_OK 4 X#define W_OK 2 X#define X_OK 1 X#define F_OK 0 X X/* --- For lockf(2) --- */ X#define F_ULOCK 0 X#define F_LOCK 1 X#define F_TLOCK 2 X#define F_TEST 3 X X/* --- For lseek(2) --- */ X#define SEEK_SET 0 X#define SEEK_CUR 1 X#define SEEK_END 2 X X/* --- For sysconf() --- */ X#define _SC_ARG_MAX 1 X#define _SC_CHILD_MAX 2 X#define _SC_CLK_TCK 3 X#define _SC_NGROUPS_MAX 4 X#define _SC_OPEN_MAX 5 X#define _SC_JOB_CONTROL 6 X#define _SC_SAVED_IDS 7 X#define _SC_VERSION 8 X X/* --- Prototypes --- */ X /* --- Process creation and execution --- */ Xpid_t fork _PROTO((void)); Xint execl _PROTO((char *path, ...)); Xint execv _PROTO((char *path, char *argv[])); Xint execle _PROTO((char *path, ...)); Xint execve _PROTO((char *path, char *argv[], char *envp[])); Xint execlp _PROTO((char *file, ...)); Xint execvp _PROTO((char *file, char *argv[])); X /* --- Process termination --- */ Xvoid _exit _PROTO((int status)); X /* --- Timer operations --- */ Xunsigned int alarm _PROTO((unsigned int seconds)); Xint pause _PROTO((void)); Xunsigned int sleep _PROTO((unsigned int seconds)); X /* --- Process identification --- */ Xpid_t getpid _PROTO((void)); Xpid_t getppid _PROTO((void)); X /* --- User identification --- */ Xuid_t getuid _PROTO((void)); Xuid_t geteuid _PROTO((void)); Xgid_t getgid _PROTO((void)); Xgid_t getegid _PROTO((void)); Xint setuid _PROTO((uid_t uid)); Xint setgid _PROTO((gid_t gid)); Xint getgroups _PROTO((int gidsetsize, gid_t grouplist[])); Xchar *getlogin _PROTO((void)); Xchar *cuserid _PROTO((char *s)); X /* --- Process groups --- */ Xpid_t getpgrp _PROTO((void)); Xpid_t setsid _PROTO((void)); Xint setpgid _PROTO((pid_t pid, pid_t pgid)); X /* --- Terminal identification --- */ Xchar *ctermid _PROTO((char *s)); Xchar *ttyname _PROTO((int fd)); Xint isatty _PROTO((int fd)); X /* --- Configurable system variables --- */ Xlong sysconf _PROTO((int name)); X /* --- Working directory --- */ Xint chdir _PROTO((char *path)); Xchar *getcwd _PROTO((char *buf, int size)); X /* --- General file creation --- */ Xint link _PROTO((char *path1, char *path2)); X /* --- File removal --- */ Xint unlink _PROTO((char *path)); Xint rmdir _PROTO((char *path)); X /* --- File characteristics --- */ Xint access _PROTO((char *path, int amode)); Xint chown _PROTO((char *path, uid_t owner, gid_t group)); X /* --- Configurable pathname variables --- */ Xlong pathconf _PROTO((char *path, int name)); Xlong fpathconf _PROTO((int fd, int name)); X /* --- Pipes --- */ Xint pipe _PROTO((int fildes[2])); X /* --- File descriptor manipulation --- */ Xint dup _PROTO((int fd)); Xint dup2 _PROTO((int fd, int fd2)); X /* --- File descriptor deassignment --- */ Xint close _PROTO((int fd)); X /* --- Input and output --- */ Xint read _PROTO((int fd, char *buf, unsigned int n)); Xint write _PROTO((int fd, char *buf, unsigned int n)); X /* --- Control operations on files --- */ Xoff_t lseek _PROTO((int fd, off_t offset, int whence)); X /* --- General terminal interface control --- */ Xpid_t tcgetpgrp _PROTO((int fd)); Xint tcsetpgrp _PROTO((int fd, pid_t pgrp_id)); X X#endif /* !defined __UNISTD_H */ / echo x - utime.h sed '/^X/s///' > utime.h << '/' X#ifndef __UTIME_H X#define __UTIME_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <utime.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Structures --- */ Xstruct utimbuf { X time_t actime; X time_t modtime; X}; X X/* --- Prototypes --- */ Xint utime _PROTO((char *path, struct utimbuf *times)); X X#endif /* !defined __UTIME_H */ / echo x - sys/dirent.h sed '/^X/s///' > sys/dirent.h << '/' X#ifndef __SYS_DIRENT_H X#define __SYS_DIRENT_H X X/* X <sys/dirent.h> -- file system independent directory entry (SVR3) X X last edit: 27-Oct-1988 D A Gwyn X X prerequisite: <sys/types.h> X*/ X X/* --- Structures --- */ Xstruct dirent { /* data from getdents()/readdir() */ X long d_ino; /* inode number of entry */ X off_t d_off; /* offset of disk directory entry */ X unsigned short d_reclen; /* length of this record */ X char d_name[1]; /* name of file */ /* non-ANSI */ X}; X X#ifdef BSD_SYSV /* (e.g., when compiling getdents.c) */ Xextern struct dirent __dirent; /* (not actually used) */ X/* The following is portable, although rather silly. */ X#define DIRENTBASESIZ (__dirent.d_name - (char *)&__dirent.d_ino) X X#else X/* The following nonportable ugliness could have been avoided by defining X DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments. X There shouldn't be any problem if you avoid using the DIRENTSIZ() macro. */ X X#define DIRENTBASESIZ (((struct dirent *)0)->d_name \ X - (char *)&((struct dirent *)0)->d_ino) X#endif X X#define DIRENTSIZ( namlen ) ((DIRENTBASESIZ + sizeof(long) + (namlen)) \ X / sizeof(long) * sizeof(long)) X X/* DAG -- the following was moved from <dirent.h>, which was the wrong place */ X#define MAXNAMLEN 512 /* maximum filename length */ X X#ifndef NAME_MAX X#define NAME_MAX (MAXNAMLEN - 1) /* DAG -- added for POSIX */ X#endif X X#endif /* !defined __SYS_DIRENT_H */ / echo x - sys/stat.h sed '/^X/s///' > sys/stat.h << '/' X#ifndef __SYS_STAT_H X#define __SYS_STAT_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <sys/stat.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X#define S_IFMT 0170000 /* type of file */ X#define S_IFDIR 0040000 /* directory */ X#define S_IFCHR 0020000 /* character special */ X#define S_IFBLK 0060000 /* block special */ X#define S_IFREG 0100000 /* regular */ X#define S_IFIFO 0010000 /* named pipe (FIFO) */ X#define S_ISUID 04000 /* set user id on execution */ X#define S_ISGID 02000 /* set group id on execution */ X#define S_IRWXU 00700 /* owner rwx */ X#define S_IRUSR 00400 /* owner r */ X#define S_IWUSR 00200 /* owner w */ X#define S_IXUSR 00100 /* owner x */ X#define S_IRWXG 00070 /* group rwx */ X#define S_IRGRP 00040 /* group r */ X#define S_IWGRP 00020 /* group w */ X#define S_IXGRP 00010 /* group x */ X#define S_IRWXO 00007 /* other rwx */ X#define S_IROTH 00004 /* other r */ X#define S_IWOTH 00002 /* other w */ X#define S_IXOTH 00001 /* other x */ X X /* --- Compatibility --- */ X#define S_IREAD S_IRUSR /* read permission, owner */ X#define S_IWRITE S_IWUSR /* write permission, owner */ X#define S_IEXEC S_IXUSR /* execute/search permission, owner */ X#define S_ISVTX 01000 /* save swapped text even after use */ X X/* --- Structures --- */ Xstruct stat { X dev_t st_dev; X ino_t st_ino; X mode_t st_mode; X nlink_t st_nlink; X uid_t st_uid; X gid_t st_gid; X dev_t st_rdev; X off_t st_size; X time_t st_atime; X time_t st_mtime; X time_t st_ctime; X}; X X/* --- Macros --- */ X#define S_ISDIR(m) ((m) & S_IFDIR) X#define S_ISCHR(m) ((m) & S_IFCHR) X#define S_ISBLK(m) ((m) & S_IFBLK) X#define S_ISREG(m) ((m) & S_IFREG) X#define S_ISFIFO(m) ((m) & S_IFIFO) /* PENDING - should catch pipes */ X X/* --- Prototypes --- */ Xmode_t umask _PROTO((mode_t cmask)); Xint mkdir _PROTO((char *path, mode_t mode)); Xint mkfifo _PROTO((char *path, mode_t mode)); Xint stat _PROTO((char *path, struct stat *buf)); Xint fstat _PROTO((int fd, struct stat *buf)); Xint chmod _PROTO((char *path, mode_t mode)); X X#endif /* !defined __SYS_STAT_H */ / echo x - sys/times.h sed '/^X/s///' > sys/times.h << '/' X#ifndef __SYS_TIMES_H X#define __SYS_TIMES_H X X/* --- Prerequisites --- */ X#ifndef __TIME_H X#error <time.h> is a prerequisite for <sys/times.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Structures --- */ Xstruct tms { X clock_t tms_utime; X clock_t tms_stime; X clock_t tms_cutime; X clock_t tms_cstime; X}; X X/* --- Prototypes --- */ Xclock_t times _PROTO((struct tms *buffer)); X X#endif /* !defined __SYS_TIMES_H */ / echo x - sys/types.h sed '/^X/s///' > sys/types.h << '/' X#ifndef __SYS_TYPES_H X#define __SYS_TYPES_H X X/* --- Types --- */ X#ifndef __DEV_T X#define __DEV_T Xtypedef unsigned short int dev_t; X#endif X X#ifndef __GID_T X#define __GID_T Xtypedef char gid_t; X#endif X X#ifndef __INO_T X#define __INO_T Xtypedef unsigned short int ino_t; X#endif X X#ifndef __MODE_T X#define __MODE_T Xtypedef unsigned short int mode_t; X#endif X X#ifndef __NLINK_T X#define __NLINK_T Xtypedef char nlink_t; X#endif X X#ifndef __OFF_T X#define __OFF_T Xtypedef long int off_t; X#endif X X#ifndef __PID_T X#define __PID_T Xtypedef int pid_t; X#endif X X#ifndef __UID_T X#define __UID_T Xtypedef short int uid_t; X#endif X X#ifndef __TIME_T X#define __TIME_T Xtypedef long int time_t; X#endif X X#endif /* !defined __SYS_TYPES_H */ / echo x - sys/utsname.h sed '/^X/s///' > sys/utsname.h << '/' X#ifndef __SYS_UTSNAME_H X#define __SYS_UTSNAME_H X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Structures --- */ Xstruct utsname { X char *sysname; /* name of the operating system */ X char *nodename; /* name of this node in the network */ X char *release; /* release level */ X char *version; /* version of the release */ X char *machine; /* machine type */ X}; X X/* --- Prototypes --- */ Xint uname _PROTO((struct utsname *name)); X X#endif /* !defined __SYS_UTSNAME_H */ / echo x - sys/wait.h sed '/^X/s///' > sys/wait.h << '/' X#ifndef __SYS_WAIT_H X#define __SYS_WAIT_H X X/* --- Prerequisites --- */ X#ifndef __SYS_TYPES_H X#error <sys/types.h> is a prerequisite for <sys/wait.h> X#endif X X/* --- Inclusions --- */ X#include "prototype.h" X X/* --- Constants --- */ X/* PENDING - Define these when implemented. */ X#define WNOHANG X#define WUNTRACED X X/* --- Macros --- */ X#define _STAT_LO(stat_val) ((stat_val) & 0xff) X#define _STAT_HI(stat_val) (((stat_val) >> 8) & 0xff) X#define WIFEXITED(stat_val) (_STAT_LO(stat_val) == 0) X#define WEXITSTATUS(stat_val) (_STAT_HI(stat_val)) X#define WIFSIGNALED(stat_val) (_STAT_HI(stat_val) == 0 && _STAT_LO(stat_val) != 0) X#define WTERMSIG(stat_val) (_STAT_LO(stat_val)) X#define WIFSTOPPED(stat_val) X#define WSTOPSIG(stat_val) X X/* --- Prototypes --- */ Xpid_t wait _PROTO((int *stat_loc)); Xpid_t waitpid _PROTO((pid_t pid, int *stat_loc, int options)); X X#endif /* !defined __SYS_WAIT_H */ /
nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (09/30/89)
echo x - _bufproc.c sed '/^X/s///' > _bufproc.c << '/' X/* --- _bufproc.c --- */ X/* Manages buffers for stdio */ X X#include <stdlib.h> X#include <stdio.h> X#include "stdiolib.h" X X/* _bufalloc - allocate a new buffer */ X/* Input: A valid stream with _io_bufsiz appropriately set */ X/* Output: Maybe a buffer, maybe not */ X Xvoid _bufalloc(stream) Xregister FILE *stream; X{ X if (stream->_io_bufsiz > 0 && X (stream->_io_buf = (unsigned char *) malloc(stream->_io_bufsiz)) != NULL) { X _io_setflag(stream, _IO_MYBUF); X stream->_io._io_ptr = stream->_io_buf; X } else { X stream->_io_bufsiz = 0; X stream->_io._io_char = EOF; X } X} X X/* _buffree - free an existing buffer if allocated by _bufalloc */ X/* Input: A valid stream */ X/* Output: A valid unbuffered stream */ X Xvoid _buffree(stream) Xregister FILE *stream; X{ X if (stream->_io_buf != NULL && _io_testflag(stream, _IO_MYBUF)) { X free(stream->_io_buf); X stream->_io_buf = NULL; X stream->_io_count = stream->_io_bufsiz = 0; X stream->_io._io_char = EOF; X _io_clearflag(stream, (_IO_LBUF | _IO_MYBUF)); X } X} / echo x - _cleanup.c sed '/^X/s///' > _cleanup.c << '/' X/* --- _cleanup.c --- */ X/* Flushes all buffers at program exit */ X/* Notes: exit() knows about this through __cleanup */ X X#include <stdio.h> X#include "stdiolib.h" X Xvoid _cleanup() X{ X fflush(NULL); X} / echo x - _doprnt.c sed '/^X/s///' > _doprnt.c << '/' X/* --- _doprnt.c --- */ X/* Formatted printing workhorse */ X/* Notes: By default, this source compiles into _doprnt() */ X/* Floating point support is nominal */ X/* Cheap and nasty imitations of character type macros */ X/* Defining the symbol _KERNEL_ results in a routine named */ X/* printk() with the following differences: */ X/* No floating point support */ X/* An abbreviated version of the macro PUTC */ X X#include <stdarg.h> X X#ifndef _KERNEL_ X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#else Xextern int putc(); X#endif X X/* --- Constants --- */ X#define MAX_CONVERSION 512 /* largest possible conversion */ X X#define LEFT_JUSTIFY 0x0001 /* conversion flags */ X#define ALWAYS_SIGN 0x0002 X#define PREFIX_SPACE 0x0004 X#define ALTERNATE_FORM 0x0008 X#define ZERO_FILL 0x0010 X#define SHORT 0x0100 /* length modifiers */ X#define LONG 0x0200 X#define LONGDOUBLE 0x0400 X#define SIGNED 0x1000 /* signed integer argument */ X#define UPPER_CASE 0x4000 /* %X, %E, %G */ X X#define UNSPECIFIED (-1) /* for precision */ X X#define POINTER_BASE 16 /* constant for %p conversion */ X X/* --- Global state --- */ Xstatic struct { X#ifndef _KERNEL_ X FILE *stream; /* destination file */ X#endif X const char *fp; /* format pointer */ X va_list ap; /* argument pointer */ X int chars_written; /* number of characters written to the stream */ X} gs; X X/* --- Macros --- */ X#define TESTFLAG(x) (flags & (x)) X#define CLEARFLAG(x) (flags &= ~(x)) X#define SETFLAG(x) (flags |= (x)) X#define isdigit(c) ((c) >= '0' && (c) <= '9') X#define _tolower(c) ((c) - 'A' + 'a') X X#ifdef _KERNEL_ X#define EOF (-1) X#define PUTC(c, f) putc(c) X#else X/* --- Local unsafe fast version of putc: ignores line buffering; --- */ X/* --- has no rvalue; returns EOF from including routine on failure --- */ X#define PUTC(c, f) { \ X if (--(f)->_io_count >= 0) \ X *(f)->_io._io_ptr++ = c; \ X else \ X if (_flsbuf(c, f) == EOF) \ X return EOF; \ X } X#endif X X/* --- Format processors --- */ Xstatic int _parse_format(); /* parse formats */ Xstatic int _iconvert(); /* convert integers */ X#ifndef _KERNEL_ Xstatic int _fconvert(); /* convert floating point */ X#endif Xstatic int _sconvert(); /* convert strings */ Xstatic int _outcnvrt(); /* writes converted output to the stream */ X X#ifdef _KERNEL_ Xint printk(format, arg) X#else Xint _doprnt(stream, format, arg) XFILE *stream; X#endif Xregister const char *format; Xva_list arg; X{ X#ifndef _KERNEL_ X gs.stream = stream; X#endif X gs.fp = format; X gs.ap = arg; X gs.chars_written = 0; X X while (*format) { X if (*format != '%') { X PUTC(*format, stream); X format++; X gs.chars_written++; X } else { X gs.fp = ++format; X if (_parse_format() == EOF) X return EOF; X format = gs.fp; X } X } X X#ifndef _KERNEL_ X if (_io_testflag(stream, _IO_LBUF)) X _flspbuf(stream); X#endif X return gs.chars_written; X} X Xstatic int _parse_format() X{ X register const char *fp = gs.fp; X register int c; X int width; X int precision; X int flags; X union { X unsigned long l; X double d; X char c; X char *s; X } arg; X X if (*fp == '%') { X PUTC(*fp, gs.stream); X gs.fp++; X gs.chars_written++; X return 0; X } X X precision = UNSPECIFIED; X flags = 0; X X/* --- Extract the flags --- */ X c = *fp; X while (1) { X if (c == '-') X SETFLAG(LEFT_JUSTIFY); X else X if (c == '+') X SETFLAG(ALWAYS_SIGN); X else X if (c == ' ') X SETFLAG(PREFIX_SPACE); X else X if (c == '#') X SETFLAG(ALTERNATE_FORM); X else X if (c == '0') X SETFLAG(ZERO_FILL); X else X break; X c = *++fp; X } X X/* --- Extract the width --- */ X if (c == '*') { X width = va_arg(gs.ap, int); X ++fp; X } X else { X width = 0; X while (isdigit(*fp)) X width = 10 * width + *fp++ - '0'; X } X if (width < 0) { X SETFLAG(LEFT_JUSTIFY); X width = 0 - width; X } X X/* --- Extract the precision --- */ X if (*fp == '.') { X if (*++fp == '*') { X precision = va_arg(gs.ap, int); X ++fp; X } X else { /* PENDING - this should handle +/- signs */ X precision = 0; X while (isdigit(*fp)) X precision = 10 * precision + *fp++ - '0'; X } X if (precision < 0) X precision = UNSPECIFIED; X } X X/* --- Extract the length modifiers --- */ X if ((c = *fp) == 'h') { X SETFLAG(SHORT); X ++fp; X } else X if (c == 'l') { X SETFLAG(LONG); X ++fp; X } else X if (c == 'L') { X SETFLAG(LONGDOUBLE); X ++fp; X } X X/* --- Fetch argument type and save global format pointer --- */ X c = *fp; X gs.fp = ++fp; X if (c == 'D' || c == 'O' || c == 'U') { /* not ANSI */ X SETFLAG(LONG); X c = _tolower(c); X } X X/* --- Fetch the argument --- */ X switch (c) { X case 'd': X case 'i': X if (TESTFLAG(SHORT)) X arg.l = (long) va_arg(gs.ap, short); X else X if (TESTFLAG(LONG)) X arg.l = va_arg(gs.ap, long); X else X arg.l = (long) va_arg(gs.ap, int); X break; X case 'o': X case 'u': X case 'X': X case 'x': X if (TESTFLAG(SHORT)) X arg.l = (unsigned long) va_arg(gs.ap, unsigned short); X else X if (TESTFLAG(LONG)) X arg.l = va_arg(gs.ap, unsigned long); X else X arg.l = (unsigned long) va_arg(gs.ap, unsigned int); X break; X#ifndef _KERNEL_ X /* PENDING - This is probably wrong (due to argument widening). */ X case 'f': X case 'E': X case 'e': X case 'G': X case 'g': X if (TESTFLAG(LONG)) X arg.d = va_arg(gs.ap, double); X#ifdef __STDC__ X else X if (TESTFLAG(LONGDOUBLE)) X arg.d = (double) va_arg(gs.ap, long double); X#endif X else X arg.d = va_arg(gs.ap, float); X break; X#endif X case 'c': X arg.c = va_arg(gs.ap, int); X break; X case 's': X arg.s = va_arg(gs.ap, char *); X break; X case 'p': X arg.l = (unsigned long) va_arg(gs.ap, void *); X break; X default: X break; X } X X/* --- Resolve mutually exclusive flags --- */ X if (TESTFLAG(ALWAYS_SIGN)) X CLEARFLAG(PREFIX_SPACE); X if (TESTFLAG(LEFT_JUSTIFY)) X CLEARFLAG(ZERO_FILL); X X/* --- Produce some output (finally!) --- */ X switch (c) { X case 'd': X case 'i': X SETFLAG(SIGNED); X CLEARFLAG(ALTERNATE_FORM); X return _iconvert(arg.l, 10, width, precision, flags); X case 'o': X return _iconvert(arg.l, 8, width, precision, flags); X case 'u': X CLEARFLAG(ALTERNATE_FORM); X return _iconvert(arg.l, 10, width, precision, flags); X case 'X': X SETFLAG(UPPER_CASE); X case 'x': X return _iconvert(arg.l, 16, width, precision, flags); X#ifndef _KERNEL_ X case 'f': X return _fconvert(arg.d, width, precision, flags); X case 'E': X SETFLAG(UPPER_CASE); X case 'e': X return _fconvert(arg.d, width, precision, flags); X case 'G': X SETFLAG(UPPER_CASE); X case 'g': X return _fconvert(arg.d, width, precision, flags); X#endif X case 'c': X return _outcnvrt(&(arg.c), 1, width, flags); X case 's': X return _sconvert(arg.s, width, precision, flags); X case 'p': X SETFLAG(ALTERNATE_FORM); X return _iconvert(arg.l, POINTER_BASE, width, precision, flags); X case 'n': X *va_arg(gs.ap, int *) = gs.chars_written; X return 0; X default: X return EOF; X } X} X Xstatic int _iconvert(number, base, width, precision, flags) Xunsigned long number; Xint base; Xint width; Xint precision; Xint flags; X{ X char buf[MAX_CONVERSION]; X register char *p = &buf[MAX_CONVERSION - 1]; X register int digit; X int negative = 0; X X/* --- Set default precision (and annul zero fill if precision set) --- */ X if (precision == UNSPECIFIED) X precision = 1; X else X CLEARFLAG(ZERO_FILL); X X/* --- Get the sign right --- */ X if (TESTFLAG(SIGNED)) X if ((long) number < 0L) { X negative = 1; X number = (unsigned long) (0L - (long) number); X } X X/* --- Build the number back to front (at the back of the buffer) --- */ X while (--precision >= 0 || number != 0) { X digit = number % base; X if (digit < 10) X digit += '0'; X else X digit += (TESTFLAG(UPPER_CASE) ? 'A' : 'a') - 10; X *p-- = digit; X number /= base; X } X X/* --- Ensure enough precision --- */ X while (--precision >= 0) X *p-- = '0'; X X/* --- Zero fill if needed (but leave room for prefix and sign) --- */ X if (TESTFLAG(ZERO_FILL)) { X precision = width - (&buf[MAX_CONVERSION - 1] - p); X if (TESTFLAG(ALTERNATE_FORM)) X if (base == 8 && *(p+1) != '0') X precision--; X else X if (base == 16) X precision -= 2; X if (TESTFLAG(SIGNED)) X if (negative || TESTFLAG(ALWAYS_SIGN | PREFIX_SPACE)) X precision--; X while (--precision >= 0) X *p-- = '0'; X } X X/* --- Generate alternate forms for %o and %x --- */ X if (TESTFLAG(ALTERNATE_FORM)) { X if (base == 8 && *(p+1) != '0') X *p-- = '0'; X else X if (base == 16) { X *p-- = TESTFLAG(UPPER_CASE) ? 'X' : 'x'; X *p-- = '0'; X } X } X X/* --- Generate signs --- */ X if (TESTFLAG(SIGNED)) { X if (negative) X *p-- = '-'; X else { X if (TESTFLAG(ALWAYS_SIGN)) X *p-- = '+'; X else X if (TESTFLAG(PREFIX_SPACE)) X *p-- = ' '; X } X } X X p++; X return _outcnvrt(p, &buf[MAX_CONVERSION] - p, width, flags); X} X X#ifndef _KERNEL_ X Xstatic int _fconvert(arg, width, precision, flags) /* PENDING */ Xdouble arg; Xint width; Xint precision; Xint flags; X{ X/* --- Set default precision --- */ X if (precision == UNSPECIFIED) X precision = 6; X X/* --- What do you expect? --- */ X PUTC(' ', gs.stream); X PUTC('*', gs.stream); X PUTC('F', gs.stream); X PUTC('P', gs.stream); X PUTC('*', gs.stream); X PUTC(' ', gs.stream); X gs.chars_written += 6; X return 0; X} X X#endif X Xstatic int _sconvert(s, width, precision, flags) Xchar *s; Xint width; Xregister int precision; Xint flags; X{ X register char *p = s; X X if (precision == UNSPECIFIED) X precision = MAX_CONVERSION; X while (--precision >= 0 && *p) X p++; X return _outcnvrt(s, p - s, width, flags); X} X Xstatic int _outcnvrt(p, n, width, flags) Xregister char *p; /* start of converted field */ Xint n; /* number of characters in field */ Xint width; Xint flags; X{ X#ifndef _KERNEL_ X register FILE *stream = gs.stream; X#endif X int i; X X if (!TESTFLAG(LEFT_JUSTIFY)) /* pad to right justify */ X for (i = width - n ; --i >= 0; ) X PUTC(' ', stream); X X for (i = n; --i >= 0; p++) /* copy conversion result */ X PUTC(*p, stream); X X if (TESTFLAG(LEFT_JUSTIFY)) /* pad to left justify */ X for (i = width - n ; --i >= 0; ) X PUTC(' ', stream); X X gs.chars_written += (n > width) ? n : width; X return 0; X} / echo x - _doscan.c sed '/^X/s///' > _doscan.c << '/' X/* --- _doscan.c --- */ X/* Formatted input workhorse */ X/* Notes: Floating point support is nonexistent */ X X#include <ctype.h> X#include <limits.h> X#include <stdarg.h> X#include <stdio.h> X#include <string.h> X#include "stdiolib.h" X X/* --- Constants --- */ X#define OK 0 /* return values from input eaters */ X#define INPUT_FAILURE EOF X#define MATCHING_FAILURE 1 X#define UNIMPLEMENTED 2 X X#define POINTER_BASE 16 /* constants for %p conversion */ X#define POINTER_TYPE '\0' X X#define SIGNED 0 /* constants for _strtol() */ X#define UNSIGNED 1 X X#define NO_NULL 0 /* constants for _strtostr() */ X#define ADD_NULL 1 X#define NO_COMPARE 0 X#define WHITE_COMPARE 1 X#define SET_COMPARE 2 X#define CHAR_SET_SIZE 128 X X/* --- Global state --- */ Xstatic struct { X int (*next_char)(); /* pointer to input function */ X union { X unsigned char *s; /* pointer to input string */ X FILE *f; /* pointer to input file */ X } src; X int input_char; /* buffer for next input character */ X const char *fp; /* format pointer */ X va_list ap; /* argument pointer */ X int chars_read; /* number of characters read from the stream (%n) */ X int items_converted; /* successful conversions */ X int items_assigned; /* successful assignments */ X int no_assign; /* if set, conversion is done but not assignment */ X int width; /* maximum input field width */ X char modifier; /* short/long modifier */ X} gs; X Xstatic char valid_char[CHAR_SET_SIZE]; X X/* --- Macros --- */ X#define BACKUP_INPUT(c) ((gs.input_char = (c)), (gs.chars_read--)) X X/* --- Input functions --- */ Xstatic int _i_string(); Xstatic int _i_stream(); X X/* --- Input processors --- */ Xstatic int _eat_white(), /* ' ' */ X _eat_one(), /* any literal character */ X _parse_format(), /* parse formats */ X _strtol(), /* convert integer formats */ X _strtod(), /* convert floating formats */ X _strtostr(); /* convert string formats */ X X Xint _doscan(is_string, source, format, arg) Xint is_string; Xvoid *source; Xconst char *format; Xva_list arg; X{ X register int c; X register int error = OK; X X gs.next_char = (is_string) ? _i_string : _i_stream; X gs.src.s = (unsigned char *) source; X gs.input_char = EOF; X gs.fp = format; X gs.ap = arg; X gs.items_converted = 0; X gs.items_assigned = 0; X X while ((c = (int) *gs.fp++) && (error == OK)) { X if (isspace(c)) X error = _eat_white(); X else X if (c == '%') X error = _parse_format(); X else X error = _eat_one(c); X } X if (gs.input_char != EOF && !is_string) X ungetc(gs.input_char, gs.src.f); X return (error == INPUT_FAILURE && gs.items_converted == 0) X ? EOF : gs.items_assigned; X} X Xstatic int _i_stream() X{ X int rc; X X gs.chars_read++; X if ((rc = gs.input_char) != EOF) { X gs.input_char = EOF; X return rc; X } X return getc(gs.src.f); X} X Xstatic int _i_string() X{ X int rc; X gs.chars_read++; X if ((rc = gs.input_char) != EOF) { X gs.input_char = EOF; X return rc; X } X if (*gs.src.s == '\0') X return EOF; X return (int) *gs.src.s++; X} X Xstatic int _parse_format() X{ X register int c; X X if ((c = *gs.fp++) == '%') X return _eat_one(c); X X gs.no_assign = 0; /* default: assign converted value */ X gs.width = INT_MAX; /* default: enormous maximum width */ X gs.modifier = '\0'; /* default: no long/short modifier */ X X if (c == '*') { X gs.no_assign = 1; X c = *gs.fp++; X } X if (isdigit(c)) { X gs.width = 0; X while (isdigit(c)) { /* PENDING - this should handle +/- signs */ X gs.width = 10 * gs.width + c - '0'; X c = *gs.fp++; X } X } X if (c == 'h' || c == 'l' || c == 'L') { X gs.modifier = c; X c = *gs.fp++; X } X if (c == 'D' || c == 'O' || c == 'U') { /* not ANSI */ X gs.modifier = 'l'; X c = _tolower(c); X } X switch (c) { X case 'd': X return _strtol(10, SIGNED); X case 'i': X return _strtol(0, SIGNED); X case 'o': X return _strtol(8, UNSIGNED); X case 'u': X return _strtol(10, UNSIGNED); X case 'x': X case 'X': X return _strtol(16, UNSIGNED); X case 'f': X case 'e': X case 'E': X case 'g': X case 'G': X return _strtod(); X case 's': X return _strtostr(WHITE_COMPARE, ADD_NULL); X case '[': X return _strtostr(SET_COMPARE, ADD_NULL); X case 'c': X if (gs.width == INT_MAX) X gs.width = 1; X return _strtostr(NO_COMPARE, NO_NULL); X case 'p': X return _strtol(POINTER_BASE, UNSIGNED); X case 'n': X if (!gs.no_assign) X *va_arg(gs.ap, int *) = gs.chars_read; X return OK; X default: X return MATCHING_FAILURE; X } X} X X/* --- Input processors --- */ Xstatic int _eat_white() X{ X register int c; X X while ((c = (*gs.next_char)()) != EOF && isspace(c)) ; X BACKUP_INPUT(c); X return (c == EOF) ? INPUT_FAILURE : OK; X} X Xstatic int _eat_one(c) Xint c; X{ X register int i; X X if ((i = (*gs.next_char)()) == EOF) X return INPUT_FAILURE; X return (i == c) ? OK : MATCHING_FAILURE; X} X Xstatic int _strtol(base, is_unsigned) Xint base; Xint is_unsigned; X{ X register int c; X long result = 0L; X int negative = 0; X int original_width = gs.width; X int digit; X X if (_eat_white() == INPUT_FAILURE) X return INPUT_FAILURE; X X/* --- Handle signs --- */ X c = (*gs.next_char)(); X if (c == '+' || c == '-') { X negative = (c == '-'); X gs.width--; X c = (*gs.next_char)(); X } X X/* --- Determine base if unknown --- */ X if (base == 0) { X base = 10; X if (c == '0') { X base = 8; X gs.width--; X c = (*gs.next_char)(); X if (c == 'x' || c == 'X') { X base = 16; X gs.width--; X c = (*gs.next_char)(); X } X } X } X X/* --- Discard 0x or 0X prefix if hexadecimal --- */ X else X if (base == 16 && c == '0') { X gs.width--; X c = (*gs.next_char)(); X if (c == 'x' || c == 'X') { X gs.width--; X c = (*gs.next_char)(); X } X } X X/* --- Convert the number --- */ X while (gs.width-- > 0 && c != EOF) { X if (isdigit(c)) X digit = c - '0'; X else X digit = c - (isupper(c) ? 'A' : 'a') + 10; X if (digit < 0 || digit >= base) X break; X result = base * result + digit; X c = (*gs.next_char)(); X } X gs.width++; X BACKUP_INPUT(c); X gs.items_converted++; X X/* --- Sign the result --- */ X if (negative) X result = 0L - result; X X/* --- Stash the result --- */ X if (gs.width == original_width) X return (c == EOF) ? INPUT_FAILURE : MATCHING_FAILURE; X if (!gs.no_assign) { X if (is_unsigned) { X if (gs.modifier == 'l') X *va_arg(gs.ap, unsigned long *) = (unsigned long) result; X else X if (gs.modifier == 'h') X *va_arg(gs.ap, unsigned short *) = (unsigned short) result; X else X *va_arg(gs.ap, unsigned int *) = (unsigned int) result; X } else { X if (gs.modifier == 'l') X *va_arg(gs.ap, long *) = (long) result; X else X if (gs.modifier == 'h') X *va_arg(gs.ap, short *) = (short) result; X else X *va_arg(gs.ap, int *) = (int) result; X } X gs.items_assigned++; X } X return OK; X} X Xstatic int _strtod() /* PENDING */ X{ X return UNIMPLEMENTED; X} X Xstatic int _strtostr(method, string_end) Xint method; Xint string_end; X{ X int negated; X register int c; X register unsigned char *target; X int original_width = gs.width; X X/* --- Set up for comparisons --- */ X if (method == WHITE_COMPARE) { X if (_eat_white() == INPUT_FAILURE) X return INPUT_FAILURE; X } else X if (method == SET_COMPARE) { X negated = 0; X if (*gs.fp == '^') { X negated = 1; X gs.fp++; X } X memset(valid_char, negated, CHAR_SET_SIZE); X negated = !negated; X c = EOF; X do { X register int next = gs.fp[1]; X X if (c != EOF && *gs.fp == '-' && next != ']') { X for (c++ ; c <= next; c++) X valid_char[c] = negated; X gs.fp++; X c = EOF; X } X else X valid_char[c = *gs.fp] = negated; X } while (*++gs.fp != ']'); X gs.fp++; X } X X/* --- Copy the string --- */ X if (!gs.no_assign) X target = va_arg(gs.ap, unsigned char *); X c = (*gs.next_char)(); X while (gs.width-- > 0 && c != EOF) { X if (method == WHITE_COMPARE && isspace(c)) X break; X else X if (method == SET_COMPARE && !valid_char[c]) X break; X if (!gs.no_assign) X *target++ = c; X c = (*gs.next_char)(); X } X gs.width++; X BACKUP_INPUT(c); X gs.items_converted++; X X/* --- Finish up --- */ X if (!gs.no_assign) { X if (string_end == ADD_NULL) X *target = '\0'; X gs.items_assigned++; X } X if (gs.width == original_width) X return (c == EOF) ? INPUT_FAILURE : MATCHING_FAILURE; X return OK; X} / echo x - _filbuf.c sed '/^X/s///' > _filbuf.c << '/' X/* --- _filbuf.c --- */ X/* Read from the file associated with a stream */ X/* Notes: Will flush stdout if reading stdin and both are tty's */ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X Xint _filbuf(stream) Xregister FILE *stream; X{ X int c; X X/* --- Virgin stream: set things up --- */ X if (stream->_io_count < _IO_NEVER) X _i_init(stream); X X/* --- Read a bufferful --- */ X if (stream->_io_bufsiz == 0) { /* unbuffered */ X if (stream->_io._io_char != EOF) { /* check for ungetc()ed char */ X c = stream->_io._io_char; X stream->_io._io_char = EOF; X return c; X } X stream->_io_count = read(stream->_io_fd, (char *) &c, 1); X } else { X stream->_io_count = X read(stream->_io_fd, (char *) stream->_io_buf, stream->_io_bufsiz); X stream->_io._io_ptr = stream->_io_buf; X } X if (stream->_io_count < 0) { X _io_setflag(stream, _IO_ERR); X return EOF; X } X if (stream->_io_count == 0) { X _io_setflag(stream, _IO_EOF); X if (_io_testflag(stream, _IO_UPDATE)) X _io_clearflag(stream, (_IO_READ | _IO_WRITE)); X return EOF; X } X stream->_io_count--; X return (stream->_io_bufsiz == 0) X ? c X : *stream->_io._io_ptr++; X} / echo x - _flsbuf.c sed '/^X/s///' > _flsbuf.c << '/' X/* --- _flsbuf.c --- */ X/* Flushes full stream buffers */ X/* Notes: #define _V7 gives support for append mode when kernel doesn't*/ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X Xint _flsbuf(c, stream) /* stream must be valid, writable */ Xint c; Xregister FILE *stream; X{ X/* --- Virgin stream: set things up --- */ X if (++stream->_io_count == _IO_NEVER) X _o_init(stream); X X#ifdef _V7 X/* --- Append kludge --- */ X if (_io_testflag(stream, _IO_APPEND) && _io_testflag(stream, _IO_NEEDSEEK)) { X lseek(stream->_io_fd, 0L, SEEK_END); X _io_clearflag(stream, _IO_NEEDSEEK); X } X#endif X X/* --- Unbuffered stream: write one character --- */ X if (stream->_io_bufsiz == 0) { X stream->_io_count = 0; X if (write(stream->_io_fd, (char *) &c, 1) != 1) { X _io_setflag(stream, _IO_ERR); X return EOF; X } X return c; X } X X/* --- Buffered stream: write out a full buffer --- */ X if (stream->_io_count == 0) { X if (write(stream->_io_fd, (char *) stream->_io_buf, stream->_io_bufsiz) X != stream->_io_bufsiz) { X _io_setflag(stream, _IO_ERR); X return EOF; X } X stream->_io._io_ptr = stream->_io_buf; X stream->_io_count = stream->_io_bufsiz; X } X X/* --- Buffered stream: start filling new buffer --- */ X --stream->_io_count; X *stream->_io._io_ptr++ = c; X X/* --- Line buffered stream: flush a partial buffer --- */ X if (_io_testflag(stream, _IO_LBUF) && c == '\n' && _flspbuf(stream) != 0) X return EOF; X X return c; X} / echo x - _flspbuf.c sed '/^X/s///' > _flspbuf.c << '/' X/* --- _flspbuf.c --- */ X/* Flushes partially full stream buffers */ X/* Notes: #define _V7 gives support for append mode when kernel doesn't*/ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X Xint _flspbuf(stream) Xregister FILE *stream; X{ X register int bytes = stream->_io_bufsiz - stream->_io_count; X X#ifdef _V7 X if (_io_testflag(stream, _IO_APPEND) && _io_testflag(stream, _IO_NEEDSEEK)) { X lseek(stream->_io_fd, 0L, SEEK_END); X _io_clearflag(stream, _IO_NEEDSEEK); X } X#endif X X if (write(stream->_io_fd, stream->_io_buf, bytes) != bytes) { X _io_setflag(stream, _IO_ERR); X return EOF; X } X stream->_io._io_ptr = stream->_io_buf; X stream->_io_count = stream->_io_bufsiz; X return 0; X} / echo x - _iobdata.c sed '/^X/s///' > _iobdata.c << '/' X/* --- _iobdata.c --- */ X/* Data structures for stdio */ X X#include <stdio.h> X#include "stdiolib.h" X X#define STDIN {0, _IO_READ | _IO_LBUF | _IO_TTY, _IO_NEVER, BUFSIZ, NULL} X#define STDOUT {1, _IO_WRITE | _IO_LBUF | _IO_TTY, _IO_NEVER, BUFSIZ, NULL} X#define STDERR {2, _IO_WRITE, _IO_NEVER, 0, NULL} X XFILE _iob[FOPEN_MAX] = {STDIN, STDOUT, STDERR }; Xchar _iov[FOPEN_MAX] = {1, 1, 1 }; X XFILE *_io_f; /* for fgetc()/fputc() macros */ Xint _io_c; X Xint (*__tmprm)(); /* pointer for cleaning up tmpfile()'s trash */ / echo x - _iobproc.c sed '/^X/s///' > _iobproc.c << '/' X/* --- _iobproc.c --- */ X/* Manages allocation of FILEs */ X/* Notes: Includes _ioballoc(), _iobfree(), and _iobindex() */ X X#include <stdio.h> X#include "stdiolib.h" X X#define INVALID (-1) X Xextern char _iov[]; X X/* _ioballoc - allocates an i/o block (FILE) */ X/* Input: none */ X/* Output: Pointer to a currently free FILE */ X XFILE *_ioballoc() X{ X register int i; X X for (i = 0; i < FOPEN_MAX; i++) X if (_iov[i] == 0) { X _iov[i] = 1; X return &_iob[i]; X } X return NULL; X} X X/* _iobfree - frees an i/o block (FILE) */ X/* Input: A stream */ X/* Output: None (but FILE is freed) */ X Xvoid _iobfree(stream) XFILE *stream; X{ X register int i; X X if ((i = _iobindex(stream)) != INVALID) X _iov[i] = 0; X} X X/* _iobindex - finds the index of a given stream */ X/* Input: A stream */ X/* Output: Index of the stream if valid, -1 otherwise */ X Xint _iobindex(stream) Xregister FILE *stream; X{ X register FILE *f; X register int i; X X for (i = 0, f = _iob; i < FOPEN_MAX; i++, f++) X if (stream == f) X return _iov[i] ? i : INVALID; X return INVALID; X} / echo x - _ioinit.c sed '/^X/s///' > _ioinit.c << '/' X/* --- _ioinit.c --- */ X/* Checks for a whole bunch of initial conditions on i/o */ X/* Notes: Includes _i_init() and _o_init() */ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X Xvoid _i_init(stream) Xregister FILE *stream; X{ X/* --- Allocate a buffer if necessary --- */ X if (stream->_io_buf == NULL && stream->_io_bufsiz != 0) X _bufalloc(stream); X stream->_io_count = 0; X _io_setflag(stream, _IO_READ); X X/* --- Line buffering: check once and turn it off if stream is not a tty --- */ X if (_io_testflag(stream, _IO_TTY)) { X if (_io_testflag(stream, _IO_LBUF) && !isatty(stream->_io_fd)) X _io_clearflag(stream, _IO_LBUF); X _io_clearflag(stream, _IO_TTY); X } X X/* --- Flush stdout (if _IOLBF) when reading from _IONBF/_IOLBF stream --- */ X if (stream->_io_bufsiz == 0 || _io_testflag(stream, _IO_LBUF)) X if (_io_testflag(stdout, _IO_LBUF)) X fflush(stdout); X} X Xvoid _o_init(stream) Xregister FILE *stream; X{ X/* --- Register _cleanup() so that exit() can find it --- */ X if (__cleanup == NULL) X __cleanup = _cleanup; X X/* --- Allocate a buffer if necessary --- */ X if (stream->_io_buf == NULL && stream->_io_bufsiz != 0) X _bufalloc(stream); X stream->_io_count = stream->_io_bufsiz; X _io_setflag(stream, _IO_WRITE); X X/* --- Line buffering: check once and turn it off if stream is not a tty --- */ X if (_io_testflag(stream, _IO_TTY)) { X if (_io_testflag(stream, _IO_LBUF) && !isatty(stream->_io_fd)) X _io_clearflag(stream, _IO_LBUF); X _io_clearflag(stream, _IO_TTY); X } X} / echo x - _valmode.c sed '/^X/s///' > _valmode.c << '/' X/* --- _valmode.c --- */ X/* Validates mode for stream opening functions */ X X/* Input: mode - a mode string for fopen() */ X/* Output: EOF for a bad string */ X/* 0 for a good string without a '+' */ X/* _IO_UPDATE for a good string with a '+' */ X X#include <stdio.h> X#include "stdiolib.h" X Xint _valmode(mode) Xregister const char *mode; X{ X register int rc = 0; X X/* --- Check basic mode --- */ X if (*mode != 'r' && *mode != 'w' && *mode != 'a') X return EOF; X if (*++mode == '\0') X return rc; X X/* --- Check second character of mode string --- */ X if (*mode == '+') X rc = _IO_UPDATE; X else X if (*mode == 'b') /* ANSI mandated - of no use here */ X ; X else X return EOF; X if (*++mode == '\0') X return rc; X X/* --- Check third character of mode string --- */ X if (*mode == '+' && rc != _IO_UPDATE) X rc = _IO_UPDATE; X else X if (*mode == 'b' && rc == _IO_UPDATE) X ; X else X return EOF; X if (*++mode == '\0') X return rc; X X/* --- Mode string too long --- */ X return EOF; X} / echo x - atexit.c sed '/^X/s///' > atexit.c << '/' X/* Copyright 1988 Frank Wortner X** You may reproduce and use this software as long as you X** do not delete this notice from the source code. X*/ X X#define MAXFN 33 /* Maximum number of functions registerable X (includes 1 for __cleanup) */ X Xtypedef void (*PFN)(); /* Pointer to FuNction */ X Xextern PFN __cleanup; /* imported from exit.c */ X Xstatic PFN fn[MAXFN]; /* addresses of functions stored here */ Xstatic int nfn = -1; /* number of functions registered less one */ X Xstatic void checkcleanup(), run_atexit(); X Xint atexit(fun) XPFN fun; X{ X if (nfn == -1) /* Do we need to check for stdio? */ X checkcleanup(); X if (nfn >= MAXFN) /* Run out of room yet? */ X return (-1); X fn[++nfn] = fun; /* Save the address of the subr. */ X return (0); X} X X/* Check to see if stdio is used. If yes register stdio's cleanup routine X** with the atexit() system and then force stdio to call run_atexit(). X*/ Xstatic void checkcleanup() X{ X if (__cleanup) /* stdio used ? */ X fn[++nfn] = __cleanup; X __cleanup = run_atexit; X} X X/* Run the requested subroutines */ Xstatic void run_atexit() X{ X while (nfn >= 0) { X (*fn[nfn--])(); X } X} / echo x - exit.c sed '/^X/s///' > exit.c << '/' X#include <stddef.h> X#include "lib.h" X XPUBLIC void (*__cleanup)() = NULL; X XPUBLIC int exit(status) Xint status; X{ X if (__cleanup != NULL) X (*__cleanup)(); X return callm1(MM, EXIT, status, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR); X} X XPUBLIC int _exit(status) Xint status; X{ X return callm1(MM, EXIT, status, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR); X} / echo x - fclose.c sed '/^X/s///' > fclose.c << '/' X/* --- fclose.c --- */ X/* Closes a stream and its associated file */ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fclose X X#define _IO_ERRVAL EOF X Xextern int (*__tmprm)(); X Xint fclose(stream) Xregister FILE *stream; X{ X _io_assert(_io_valid(stream)); X X if (fflush(stream)) X return _IO_ERRVAL; X _buffree(stream); X if (close(stream->_io_fd)) X return _IO_ERRVAL; X if (_io_testflag(stream, _IO_TEMP)) X if (__tmprm) (*__tmprm)(_iobindex(stream)); X _iobfree(stream); X return 0; X} / echo x - fdopen.c sed '/^X/s///' > fdopen.c << '/' X/* --- fdopen.c --- */ X/* Associates a stream with an already open file */ X/* Notes: Open mode of file must agree with open mode specified */ X/* #define _V7 gives support for append mode when kernel doesn't*/ X/* POSIX function */ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fdopen X X#define _IO_ERRVAL NULL X X XFILE *fdopen(fd, mode) Xint fd; Xconst char *mode; X{ X int flags; X register FILE *stream; X X _io_assert(fd >= 0); X X if ((flags = _valmode(mode)) < 0) X return _IO_ERRVAL; X if ((stream = _ioballoc()) == NULL) X return _IO_ERRVAL; X X switch (*mode) { X case 'r': X flags |= _IO_READ; X break; X case 'w': X flags |= _IO_WRITE; X break; X case 'a': X#ifdef _V7 X flags |= _IO_WRITE | _IO_APPEND; X lseek(fd, 0L, SEEK_END); X#else X flags |= _IO_WRITE; X#endif X break; X default: X _iobfree(stream); X return _IO_ERRVAL; X } X X if (isatty(fd)) X flags |= _IO_LBUF; X stream->_io_fd = fd; X stream->_io_flags = flags; X stream->_io_count = _IO_NEVER; X stream->_io_bufsiz = BUFSIZ; X return stream; X} / echo x - fflush.c sed '/^X/s///' > fflush.c << '/' X/* --- fflush.c --- */ X/* Flushes a stream's buffer */ X/* Notes: Given a NULL pointer as a stream, fflush() flushes all streams. */ X/* Flushing a readable stream discards the buffer contents */ X/* and lseek()'s the underlying file to meet expectations. */ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fflush X X#define _IO_ERRVAL EOF X Xextern char _iov[]; Xstatic int _fflush _PROTO((FILE *stream)); X Xint fflush(stream) Xregister FILE *stream; X{ X register int i; X register int rc; X X if (stream == NULL) { X rc = 0; X for (i = 0, stream = _iob; i < FOPEN_MAX; i++, stream++) { X if (_iov[i]) X rc |= _fflush(stream); X } X return rc; X } else { X _io_assert(_io_valid(stream)); X return _fflush(stream); X } X} X Xstatic int _fflush(stream) Xregister FILE *stream; X{ X register int rc = 0; X X if (stream->_io_count == _IO_NEVER) X return rc; X if (stream->_io_bufsiz != 0) { X if (_io_testflag(stream, _IO_WRITE)) X rc = _flspbuf(stream); X else X if (_io_testflag(stream, _IO_READ) && !feof(stream)) X if (lseek(stream->_io_fd, 0L - stream->_io_count, SEEK_CUR) < 0L) X rc = EOF; X } X stream->_io_count = _IO_NEVER; X if (stream->_io_bufsiz == 0) X stream->_io._io_char = EOF; X else X stream->_io._io_ptr = stream->_io_buf; X if (_io_testflag(stream, _IO_UPDATE)) X _io_clearflag(stream, (_IO_READ | _IO_WRITE)); X return rc; X} / echo x - fgetc.c sed '/^X/s///' > fgetc.c << '/' X/* --- fgetc.c --- */ X/* Retrieves the next character from a stream */ X/* Notes: Includes getc() and getchar(), backstops for macros in <stdio.h> */ X X#include <stdio.h> X#include "stdiolib.h" X#undef fgetc X#undef getc X#undef getchar X X#define _IO_ERRVAL EOF X Xint fgetc(stream) Xregister FILE *stream; X{ X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_WRITE)); X _io_assert(!_io_testflag(stream, (_IO_EOF | _IO_ERR))); X X return (--stream->_io_count >= 0) ? X *stream->_io._io_ptr++ : _filbuf(stream); X} X Xint getc(stream) XFILE *stream; X{ X return fgetc(stream); X} X Xint getchar() X{ X return fgetc(stdin); X} / echo x - fgets.c sed '/^X/s///' > fgets.c << '/' X/* --- fgets.c --- */ X/* Reads limited number of characters from a stream, up to a newline */ X/* Notes: Returns EOF only if no characters read before end of file */ X X#include <stdio.h> X#include "stdiolib.h" X#undef fgets X X#define _IO_ERRVAL NULL X Xchar *fgets(s, n, stream) Xchar *s; Xregister int n; XFILE *stream; X{ X register int c; X register char *p = s; X X _io_assert(s); X _io_assert(n > 0); X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_WRITE)); X _io_assert(!_io_testflag(stream, (_IO_EOF | _IO_ERR))); X X while (--n > 0 && (c = getc(stream)) != EOF) { X *p++ = c; X if (c == '\n') X break; X } X *p = '\0'; X return (p == s && c == EOF) ? NULL : s; X} / echo x - fopen.c sed '/^X/s///' > fopen.c << '/' X/* --- fopen.c --- */ X/* Opens a file and associates a stream with it */ X/* Notes: #define _V7 gives support for append mode when kernel doesn't*/ X X#include <sys/types.h> X#include <fcntl.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fopen X X#define _IO_ERRVAL NULL X#define PMODE 0666 X XFILE *fopen(filename, mode) Xconst char *filename; Xconst char *mode; X{ X int fd; X int flags; X register FILE *stream; X X _io_assert(filename); X _io_assert(mode); X X if ((flags = _valmode(mode)) < 0) X return _IO_ERRVAL; X if ((stream = _ioballoc()) == NULL) X return _IO_ERRVAL; X X switch (*mode) { X case 'r': X fd = open(filename, flags ? O_RDWR : O_RDONLY); X flags |= _IO_READ; X break; X case 'w': X#ifdef _V7 X if ((fd = creat(filename, PMODE)) >= 0 && flags) { X close(fd); X fd = open(filename, O_RDWR); X } X#else X fd = open(filename, O_CREAT | O_TRUNC | (flags ? O_RDWR : O_WRONLY), PMODE); X#endif X flags |= _IO_WRITE; X break; X case 'a': X#ifdef _V7 X if ((fd = open(filename, flags ? O_RDWR : O_WRONLY)) >= 0) { X lseek(fd, 0L, SEEK_END); X } X else X if ((fd = creat(filename, PMODE)) >= 0 && flags) { X close(fd); X fd = open(filename, O_RDWR); X } X flags |= (_IO_WRITE | _IO_APPEND); X#else X fd = open(filename, O_CREAT | O_APPEND | (flags ? O_RDWR : O_WRONLY), PMODE); X flags |= _IO_WRITE; X#endif X break; X default: X fd = -1; X } X if (fd < 0) { X _iobfree(stream); X return _IO_ERRVAL; X } X X if (isatty(fd)) X flags |= _IO_LBUF; X stream->_io_fd = fd; X stream->_io_flags = flags; X stream->_io_count = _IO_NEVER; X stream->_io_bufsiz = BUFSIZ; X return stream; X} / echo x - fputc.c sed '/^X/s///' > fputc.c << '/' X/* --- fputc.c --- */ X/* Writes a single character onto a stream */ X/* Notes: Includes putc() and putchar(), macro backstops for <stdio.h> */ X X#include <stdio.h> X#include "stdiolib.h" X#undef fputc X#undef putc X#undef putchar X X#define _IO_ERRVAL EOF X X Xint fputc(c, stream) Xregister int c; Xregister FILE *stream; X{ X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_READ)); X _io_assert(!_io_testflag(stream, (_IO_EOF | _IO_ERR))); X X#ifndef NDEBUG X if (_io_testflag(stream, _IO_STRING)) X return (int) (*stream->_io._io_ptr++ = c); X#endif X X return ((--stream->_io_count < 0) || X (_io_testflag(stream, _IO_LBUF) && c == '\n')) X ? _flsbuf(c, stream) X : (int) (*stream->_io._io_ptr++ = c); X} X Xint putc(c, stream) Xint c; Xregister FILE *stream; X{ X return fputc(c, stream); X} X Xint putchar(c) Xint c; X{ X return fputc(c, stdout); X} / echo x - fputs.c sed '/^X/s///' > fputs.c << '/' X/* --- fputs.c --- */ X/* Writes a string to a stream */ X/* Notes: Includes puts(), which backstops a macro in <stdio.h> */ X X#include <stdio.h> X#include "stdiolib.h" X#undef fputs X#undef puts X X#define _IO_ERRVAL EOF X X Xint fputs(s, stream) Xregister const char *s; Xregister FILE *stream; X{ X _io_assert(s); X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_READ)); X _io_assert(!_io_testflag(stream, _IO_ERR)); X X while (*s) { X if (putc(*s, stream) == EOF) X return EOF; X s++; X } X return 0; X} X Xint puts(s) Xconst char *s; X{ X return (fputs(s, stdout) >= 0) ? ((putchar('\n') == '\n') ? 0 : EOF) : EOF; X} X / echo x - fread.c sed '/^X/s///' > fread.c << '/' X/* --- fread.c --- */ X/* Reads directly from a stream into a buffer */ X/* Notes: Attempts to buffer requests but reads directly if impossible */ X X#include <sys/types.h> X#include <limits.h> X#include <stdio.h> X#include <string.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fread X X#define _IO_ERRVAL 0 X X/* --- The following value determines whether fread() requests go --- */ X/* --- through the buffer or are done directly. As set, the limit --- */ X/* --- means that small requests (less than half the stream's buffer --- */ X/* --- size) will use buffering; larger requests are done directly. --- */ X/* --- Empirical testing shows this is reasonable; more should be done. --- */ X#define BUFFER_LIMIT (stream->_io_bufsiz >> 1) X X#define FROM_IO(bytes) { \ X memcpy(p, stream->_io._io_ptr, bytes); \ X p += bytes; \ X stream->_io._io_ptr += bytes; \ X stream->_io_count -= bytes; \ X } X#define FROM_FS(bytes) read(stream->_io_fd, (char *) p, bytes) X Xsize_t fread(ptr, size, nmemb, stream) Xvoid *ptr; Xsize_t size; Xsize_t nmemb; XFILE *stream; X{ X long total_size; X long bytes_left; X register unsigned char *p = (unsigned char *) ptr; X register int bytes; X int c; X int n; X X _io_assert(p != NULL); X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_WRITE)); X _io_assert(!_io_testflag(stream, (_IO_EOF | _IO_ERR))); X X if ((total_size = (long) nmemb * (long) size) == 0) X return 0; X X/* --- Virgin stream: set things up --- */ X if (stream->_io_count == _IO_NEVER) X _i_init(stream); X X/* --- Most common case(?): from the buffer --- */ X if (total_size <= stream->_io_count) { X bytes = total_size; X FROM_IO(bytes); X return nmemb; X } X X/* --- Empty the buffer --- */ X bytes_left = total_size; X if (stream->_io_count > 0) { X bytes_left -= stream->_io_count; X FROM_IO(stream->_io_count); X } X X/* --- Small objects: try filling the stdio buffer ONCE --- */ X if (bytes_left <= BUFFER_LIMIT) { X if ((c = _filbuf(stream)) == EOF) X return (total_size - bytes_left) / size; X *p++ = c; X if ((bytes = --bytes_left) <= stream->_io_count) { X FROM_IO(bytes); X return nmemb; X } X } X X/* --- Buffering failed: read() directly --- */ X if (stream->_io_count > 0) { X bytes_left -= stream->_io_count; X FROM_IO(stream->_io_count); X } X for ( ; bytes_left > INT_MAX; bytes_left -= n) { X if ((n = FROM_FS(INT_MAX)) <= 0) { X if (n < 0) { X _io_setflag(stream, _IO_ERR); X } else { X _io_setflag(stream, _IO_EOF); X if (_io_testflag(stream, _IO_UPDATE)) X _io_clearflag(stream, (_IO_READ | _IO_WRITE)); X } X return (total_size - bytes_left) / size; X } X p += n; X } X for (bytes = bytes_left; bytes > 0; bytes -= n) { X if ((n = FROM_FS(bytes)) <= 0) { X if (n < 0) { X _io_setflag(stream, _IO_ERR); X } else { X _io_setflag(stream, _IO_EOF); X if (_io_testflag(stream, _IO_UPDATE)) X _io_clearflag(stream, (_IO_READ | _IO_WRITE)); X } X return (total_size - bytes) / size; X } X p += n; X } X return nmemb; X} / echo x - freopen.c sed '/^X/s///' > freopen.c << '/' X/* --- freopen.c --- */ X/* Closes the file associated with a stream and then opens a new file */ X/* Notes: #define _V7 gives support for append mode when kernel doesn't*/ X/* Maintains buffer and buffering mode on stream. */ X X#include <sys/types.h> X#include <fcntl.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef freopen X X#define _IO_ERRVAL ((FILE *) NULL) X#define PMODE 0666 X X XFILE *freopen(filename, mode, stream) Xconst char *filename; Xconst char *mode; Xregister FILE *stream; X{ X int fd; X int flags; X X _io_assert(_io_valid(stream)); X X if (fflush(stream) || close(stream->_io_fd)) X return _IO_ERRVAL; X if ((flags = _valmode(mode)) < 0) X return _IO_ERRVAL; X X switch (*mode) { X case 'r': X fd = open(filename, flags ? O_RDWR : O_RDONLY); X flags |= _IO_READ; X break; X case 'w': X#ifdef _V7 X if ((fd = creat(filename, PMODE)) >= 0 && flags) { X close(fd); X fd = open(filename, O_RDWR); X } X#else X fd = open(filename, O_CREAT | O_TRUNC | (flags ? O_RDWR : O_WRONLY), PMODE); X#endif X flags |= _IO_WRITE; X break; X case 'a': X#ifdef _V7 X if ((fd = open(filename, flags ? O_RDWR : O_WRONLY)) >= 0) { X lseek(fd, 0L, SEEK_END); X } X else X if ((fd = creat(filename, PMODE)) >= 0 && flags) { X close(fd); X fd = open(filename, O_RDWR); X } X flags |= (_IO_WRITE | _IO_APPEND); X#else X fd = open(filename, O_CREAT | O_APPEND | (flags ? O_RDWR : O_WRONLY), PMODE); X flags |= _IO_WRITE; X#endif X break; X default: X fd = -1; X } X X if (fd < 0) { X _buffree(stream); X _iobfree(stream); X return _IO_ERRVAL; X } X X if (isatty(fd)) X flags |= _IO_LBUF; X stream->_io_fd = fd; X _io_clearflag(stream, ~(_IO_LBUF | _IO_MYBUF)); X _io_setflag(stream, flags); X stream->_io_count = _IO_NEVER; X return stream; X} / echo x - fseek.c sed '/^X/s///' > fseek.c << '/' X/* --- fseek.c --- */ X/* Sets the position of a stream */ X/* Notes: Always flushes a stream's buffer */ X/* Includes fsetpos() and rewind() */ X/* fsetpos() is a backstop for a macro in <stdio.h> */ X/* #define _V7 gives support for append mode when kernel doesn't*/ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fseek X#undef fsetpos X#undef rewind X X#define _IO_ERRVAL EOF X Xint fseek(stream, offset, whence) Xregister FILE *stream; Xlong int offset; Xregister int whence; X{ X _io_assert(_io_valid(stream)); X _io_assert(whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END); X X fflush(stream); X _io_clearflag(stream, _IO_EOF); X X#ifdef _V7 X if (_io_testflag(stream, _IO_APPEND)) { X if (!_io_testflag(stream, _IO_UPDATE)) X return 0; X if (whence != SEEK_END || offset != 0L) X _io_setflag(stream, _IO_NEEDSEEK); X } X#endif X X return (lseek(stream->_io_fd, offset, whence) < 0L) ? _IO_ERRVAL : 0; X} X Xint fsetpos(stream, pos) XFILE *stream; Xconst fpos_t *pos; X{ X return fseek(stream, *pos, SEEK_SET); X} X Xvoid rewind(stream) XFILE *stream; X{ X (void) fseek(stream, 0L, SEEK_SET); X clearerr(stream); X} / echo x - ftell.c sed '/^X/s///' > ftell.c << '/' X/* --- ftell.c --- */ X/* Returns the position of a stream */ X/* Notes: Includes fgetpos(), which backstops a macro in <stdio.h> */ X X#include <errno.h> X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#include "stdiolib.h" X#undef ftell X#undef fgetpos X X#define _IO_ERRVAL -1L X X Xlong ftell(stream) Xregister FILE *stream; X{ X extern int errno; X int adjustment; X long position; X long lseek(); X X errno = EBADF; X if (!_io_valid(stream)) X return _IO_ERRVAL; X errno = 0; X X if (stream->_io_count == _IO_NEVER) X adjustment = 0; X else X if (_io_testflag(stream, _IO_READ)) X adjustment = -stream->_io_count; X else X if (_io_testflag(stream, _IO_WRITE)) X adjustment = stream->_io_bufsiz - stream->_io_count; X X return ((position = lseek(stream->_io_fd, 0L, SEEK_CUR)) >= 0L) X ? position + (long) adjustment X : _IO_ERRVAL; X} X Xint fgetpos(stream, position) XFILE *stream; Xfpos_t *position; X{ X return (*position = (fpos_t) ftell(stream)) >= 0L ? 0 : EOF; X} / echo x - fwrite.c sed '/^X/s///' > fwrite.c << '/' X/* --- fwrite.c --- */ X/* Writes directly from a buffer into a stream */ X/* Notes: Attempts to buffer requests but writes directly if impossible*/ X/* #define _V7 gives support for append mode when kernel doesn't*/ X X#include <sys/types.h> X#include <limits.h> X#include <stdio.h> X#include <string.h> X#include <unistd.h> X#include "stdiolib.h" X#undef fwrite X X#define _IO_ERRVAL 0 X X/* --- The following value determines whether fwrite() requests go --- */ X/* --- through the buffer or are done directly. As set, the limit --- */ X/* --- means that small requests (less than half the stream's buffer --- */ X/* --- size) will use buffering; larger requests are done directly. --- */ X/* --- Empirical testing shows this is reasonable; more should be done. --- */ X#define BUFFER_LIMIT (stream->_io_bufsiz >> 1) X X#define TO_IO(bytes) { \ X memcpy(stream->_io._io_ptr, p, bytes); \ X stream->_io._io_ptr += bytes; \ X stream->_io_count -= bytes; \ X } X#define TO_FS(bytes) write(stream->_io_fd, (char *) p, bytes) X Xsize_t fwrite(ptr, size, nmemb, stream) Xconst void *ptr; Xsize_t size; Xsize_t nmemb; XFILE *stream; X{ X register unsigned char *p = (unsigned char *) ptr; X long total_size; X int buffer_limit; X size_t items; X int n; X X _io_assert(p != NULL); X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_READ)); X _io_assert(!_io_testflag(stream, _IO_ERR)); X X if ((total_size = (long) nmemb * (long) size) == 0) X return 0; X X/* --- Virgin stream: set things up --- */ X if (stream->_io_count == _IO_NEVER) X _o_init(stream); X X#ifdef _V7 X/* --- Append kludge --- */ X if (_io_testflag(stream, _IO_APPEND) && _io_testflag(stream, _IO_NEEDSEEK)) { X lseek(stream->_io_fd, 0L, SEEK_END); X _io_clearflag(stream, _IO_NEEDSEEK); X } X#endif X X/* --- Most common case(?): into the buffer --- */ X buffer_limit = (stream->_io_count < BUFFER_LIMIT) X ? stream->_io_count : BUFFER_LIMIT; X if (total_size <= buffer_limit) { X register int bytes = (int) total_size; X X TO_IO(bytes); X return nmemb; X } X X/* --- Doesn't fit: flush what we've accumulated --- */ X _flspbuf(stream); X X/* --- Huge objects: write() in manageable sections --- */ X items = 0; X if (size > INT_MAX) { X while (nmemb-- > 0) { X register size_t obj_size = size; X X while (obj_size > INT_MAX) { X if ((n = TO_FS(INT_MAX)) != INT_MAX) { X _io_setflag(stream, _IO_ERR); X return items; X } X obj_size -= INT_MAX; X p += INT_MAX; X } X if ((n = TO_FS(obj_size)) != obj_size) { X _io_setflag(stream, _IO_ERR); X return items; X } X p += obj_size; X items++; X } X return items; X } X X/* --- Lots of small objects: write() in chunks --- */ X { X size_t items_per_chunk; X register int chunk_size; X long cutoff = stream->_io_count; X X items_per_chunk = INT_MAX / size; X if ((chunk_size = size * items_per_chunk) > cutoff) X cutoff = chunk_size; X while (total_size > cutoff) { X if ((n = TO_FS(chunk_size)) != chunk_size) { X _io_setflag(stream, _IO_ERR); X return items + n / size; X } else { X items += items_per_chunk; X } X total_size -= chunk_size; X p += chunk_size; X } X if ((chunk_size = (int) total_size) > BUFFER_LIMIT) { X if ((n = TO_FS(chunk_size)) != chunk_size) X _io_setflag(stream, _IO_ERR); X return items + n / size; X } X TO_IO(chunk_size); X return nmemb; X } X} / echo x - gets.c sed '/^X/s///' > gets.c << '/' X/* --- gets.c --- */ X/* Reads characters from stdin, up to a newline */ X/* Notes: Returns EOF only if no characters read before end of file */ X X#include "stdio.h" X#include "stdiolib.h" X#undef gets X X#define _IO_ERRVAL NULL X Xchar *gets(s) Xchar *s; X{ X register char *p = s; X register int c; X X _io_assert(s); X X while ((c = getchar()) != EOF && c != '\n') X *p++ = c; X *p = '\0'; X return (p == s && c == EOF) ? NULL : s; X} / echo x - perror.c sed '/^X/s///' > perror.c << '/' X/* --- perror.c --- */ X/* Prints the current error message */ X/* Notes: Only minor changes from standard Minix issue */ X X#include <sys/types.h> X#include <errno.h> X#include <stdio.h> X#include <string.h> X#include <unistd.h> X Xchar *sys_errlist[] = { X "Error 0", X "Not owner", X "No such file or directory", X "No such process", X "Interrupted system call", X "I/O error", X "No such device or address", X "Arg list too long", X "Exec format error", X "Bad file number", X "No children", X "No more processes", X "Not enough core", X "Permission denied", X "Bad address", X "Block device required", X "Mount device busy", X "File exists", X "Cross-device link", X "No such device", X "Not a directory", X "Is a directory", X "Invalid argument", X "File table overflow", X "Too many open files", X "Not a typewriter", X "Text file busy", X "File too large", X "No space left on device", X "Illegal seek", X "Read-only file system", X "Too many links", X "Broken pipe", X "Math argument", X "Result too large" X}; X Xint sys_nerr = sizeof(sys_errlist)/sizeof(char *); X Xvoid perror(s) Xconst char *s; X{ X if (errno < 0 || errno >= sizeof(sys_errlist)/sizeof(char *)) { X write(2, "Invalid errno\n", 14); X } else { X write(2, s, strlen(s)); X write(2, ": ", 2); X write(2, sys_errlist[errno], strlen(sys_errlist[errno])); X write(2, "\n", 1); X } X} / echo x - printf.c sed '/^X/s///' > printf.c << '/' X/* --- printf.c --- */ X/* Formatted printing functions */ X/* Notes: Includes fprintf(), printf(), vfprintf(), and vprintf(); */ X/* All are front ends for _doprnt() */ X/* vfprintf() and vprintf() backstop macros in <stdio.h> */ X X#include <stdarg.h> X#include <stdio.h> X#include "stdiolib.h" X#undef fprintf X#undef printf X#undef vfprintf X#undef vprintf X X X#define _IO_ERRVAL 0 X Xint fprintf(stream, format /*, ... */) XFILE *stream; Xconst char *format; X{ X va_list arg; X int n; X X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_READ)); X _io_assert(!_io_testflag(stream, _IO_ERR)); X _io_assert(format); X X va_start(arg, format); X n = _doprnt(stream, format, arg); X va_end(arg); X return n; X} X Xint printf(format /*, ... */) Xconst char *format; X{ X va_list arg; X int n; X X _io_assert(_io_valid(stdout)); X _io_assert(!_io_testflag(stdout, _IO_READ)); X _io_assert(!_io_testflag(stdout, _IO_ERR)); X _io_assert(format); X X va_start(arg, format); X n = _doprnt(stdout, format, arg); X va_end(arg); X return n; X} X Xint vfprintf(stream, format, arg) XFILE *stream; Xconst char *format; Xva_list arg; X{ X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_READ)); X _io_assert(!_io_testflag(stream, _IO_ERR)); X _io_assert(format); X X return _doprnt(stream, format, arg); X} X Xint vprintf(format, arg) Xconst char *format; Xva_list arg; X{ X return _doprnt(stdout, format, arg); X} / echo x - remove.c sed '/^X/s///' > remove.c << '/' X/* --- remove.c --- */ X/* Removes a file from the file system */ X/* Notes: Backstops a macro in <stdio.h> */ X X#include <sys/types.h> X#include <stdio.h> X#include <unistd.h> X#undef remove X Xint remove(filename) Xconst char *filename; X{ X return unlink(filename); X} / echo x - rename.c sed '/^X/s///' > rename.c << '/' X/* --- rename.c --- */ X/* Renames a file in the file system */ X/* Author: Freeman Pascal */ X X#include <sys/types.h> X#include <sys/stat.h> X#include <errno.h> X#include <signal.h> X#include <stdio.h> X#include <unistd.h> X#undef rename X X/*========================================================================*\ X** rename() ** X\*========================================================================*/ Xint rename(old, new) Xconst char *old; Xconst char *new; X{ X/* X * Attempts new link 'old' as 'new'. If 'new' exists it is unlinked. X * X * NOTE: 'rename()' will not rename across file systems or X * file types. Also, if an attempt is made to copy across X * file systems both files will be left intact and an X * error will be returned. X */ X struct stat s_new, s_old; X void (*s_int)(), (*s_hup)(), (*s_quit)(); X int ret = 0; X X /* X * Get status of 'old' and 'new'; if either attempt fails we know X * one of the files doesn't exist. If 'old' doesn't exist, then X * return an error condition. If both files exist, then test if X * they are both on the same file system. If 'new' doesn't exist, X * then don't worry about it - it soon will. X */ X if (stat(old, &s_old) == 0) { X if (stat(new, &s_new) == 0) { X if (s_new.st_dev == s_old.st_dev) { X errno = EXDEV; X return -1; X } X } X /* Ignore SIGINT, SIGHUP, and SIGQUIT until we're finished. */ X s_int = signal(SIGINT, SIG_IGN); X s_hup = signal(SIGHUP, SIG_IGN); X s_quit = signal(SIGQUIT, SIG_IGN); X /* Does 'new' exist? If so, remove it. */ X ret = unlink(new); X if ((ret = link(old, new)) == 0) X ret = unlink(old); X /* Restore signals. */ X signal(SIGINT, s_int ); X signal(SIGHUP, s_hup ); X signal(SIGQUIT, s_quit); X return ret; X } X return -1; X} / echo x - scanf.c sed '/^X/s///' > scanf.c << '/' X/* --- scanf.c --- */ X/* Formatted input functions */ X/* Notes: Includes fscanf() and scanf(), front ends for _doscan() */ X X#include <stdarg.h> X#include <stdio.h> X#include "stdiolib.h" X#undef fscanf X#undef scanf X X#define _IO_ERRVAL EOF X Xint fscanf(stream, format /*, ... */) XFILE *stream; Xconst char *format; X{ X va_list arg; X int n; X X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_WRITE)); X _io_assert(!_io_testflag(stream, (_IO_EOF | _IO_ERR))); X _io_assert(format); X X va_start(arg, format); X n = _doscan(0, (void *) stream, format, arg); X va_end(arg); X return n; X} X X Xint scanf(format /*, ... */) Xconst char *format; X{ X va_list arg; X int n; X X _io_assert(_io_valid(stdin)); X _io_assert(!_io_testflag(stdin, _IO_WRITE)); X _io_assert(!_io_testflag(stdin, (_IO_EOF | _IO_ERR))); X _io_assert(format); X X va_start(arg, format); X n = _doscan(0, (void *) stdin, format, arg); X va_end(arg); X return n; X} / echo x - setvbuf.c sed '/^X/s///' > setvbuf.c << '/' X/* --- setvbuf.c --- */ X/* Associates a buffer with a stream and sets buffering modes */ X/* Notes: Does not actually allocate a buffer; just sets things up */ X/* Includes setbuf(), which backstops a macro in <stdio.h> */ X X#include <stdio.h> X#include "stdiolib.h" X#undef setvbuf X#undef setbuf X X#define _IO_ERRVAL EOF X X Xint setvbuf(stream, buffer, type, size) Xregister FILE *stream; Xchar *buffer; Xint type; Xsize_t size; X{ X _io_assert(_io_valid(stream)); X _io_assert(type == _IONBF || size != 0); X _io_assert(stream->_io_count == _IO_NEVER); X X fflush(stream); X _buffree(stream); X _io_clearflag(stream, (_IO_LBUF | _IO_MYBUF)); X switch (type) { X case _IONBF: X stream->_io_bufsiz = 0; X stream->_io_buf = NULL; X stream->_io._io_char = EOF; X stream->_io_count = _IO_NEVER; X return 0; X case _IOLBF: X case _IOFBF: X stream->_io_bufsiz = size; X stream->_io._io_ptr = stream->_io_buf = (unsigned char *) buffer; X stream->_io_count = _IO_NEVER; X _io_setflag(stream, type); X return 0; X default: X return _IO_ERRVAL; X } X} X X Xvoid setbuf(stream, buffer) /* ANSI requires function definition */ XFILE *stream; /* (even if the default is a macro) */ Xchar *buffer; X{ X (void) setvbuf(stream, buffer, (buffer == NULL) ? _IONBF : _IOFBF, BUFSIZ); X} / echo x - sprintf.c sed '/^X/s///' > sprintf.c << '/' X/* --- sprintf.c --- */ X/* Formatted printing functions for strings */ X/* Notes: Includes sprintf() and vsprintf() */ X/* Both are front ends for _doprnt() */ X X#include <limits.h> X#include <stdarg.h> X#include <stdio.h> X#include "stdiolib.h" X#undef sprintf X#undef vsprintf X X#define _IO_ERRVAL 0 X X Xint sprintf(s, format /*, ... */) Xchar *s; Xconst char *format; X{ X FILE fake; X va_list arg; X int n; X X _io_assert(s); X _io_assert(format); X X fake._io_fd = -1; X fake._io_flags = _IO_WRITE | _IO_STRING; X fake._io_bufsiz = fake._io_count = INT_MAX; X fake._io._io_ptr = fake._io_buf = (unsigned char *) s; X va_start(arg, format); X n = _doprnt(&fake, format, arg); X putc('\0', &fake); X va_end(arg); X return n; X} X Xint vsprintf(s, format, arg) Xchar *s; Xconst char *format; Xva_list arg; X{ X FILE fake; X int n; X X _io_assert(s); X _io_assert(format); X X fake._io_fd = -1; X fake._io_flags = _IO_WRITE | _IO_STRING; X fake._io_bufsiz = fake._io_count = INT_MAX; X fake._io._io_ptr = fake._io_buf = (unsigned char *) s; X n = _doprnt(&fake, format, arg); X putc('\0', &fake); X return n; X} / echo x - sscanf.c sed '/^X/s///' > sscanf.c << '/' X/* --- sscanf.c --- */ X/* Formatted input function for strings */ X/* Notes: Front end for _doscan() */ X X#include <stdarg.h> X#include <stdio.h> X#include "stdiolib.h" X#undef sscanf X X#define _IO_ERRVAL EOF X Xint sscanf(s, format /*, ... */) Xconst char *s; Xconst char *format; X{ X va_list arg; X int n; X X _io_assert(s); X _io_assert(format); X X va_start(arg, format); X n = _doscan(1, (void *) s, format, arg); X va_end(arg); X return n; X} / echo x - stdio_misc.c sed '/^X/s///' > stdio_misc.c << '/' X/* --- stdio_misc.c --- */ X/* Miscellaneous stream functions */ X/* Notes: Includes clearerr(), feof(), ferror(), and (POSIX) fileno() */ X/* All functions backstop macros in <stdio.h> */ X X#include <stdio.h> X#include "stdiolib.h" X#undef clearerr X#undef feof X#undef ferror X#undef fileno X X#define _IO_ERRVAL EOF X Xvoid clearerr(stream) XFILE *stream; X{ X _io_assert(_io_valid(stream)); X _io_clearflag(stream, (_IO_EOF | _IO_ERR)); X} X Xint feof(stream) XFILE *stream; X{ X _io_assert(_io_valid(stream)); X return _io_testflag(stream, _IO_EOF); X} X Xint ferror(stream) XFILE *stream; X{ X _io_assert(_io_valid(stream)); X return _io_testflag(stream, _IO_ERR); X} X Xint fileno(stream) /* Posix */ XFILE *stream; X{ X _io_assert(_io_valid(stream)); X return stream->_io_fd; X} / echo x - tmpfile.c sed '/^X/s///' > tmpfile.c << '/' X/* --- tmpfile.c --- */ X/* Opens a temporary file which will be deleted on close or exit */ X/* Notes: Also includes two cleanup routines: */ X/* _tmp_cleanup - registered with atexit() if tmpfile() is used */ X/* _tmp_remove - removes one temporary file */ X X#include <sys/types.h> X#include <stdio.h> X#include <stdlib.h> X#include <unistd.h> X#include "stdiolib.h" X#undef tmpfile X Xstatic void _tmp_cleanup(); Xstatic int _tmp_remove(); X Xextern int (*__tmprm)(); Xstatic char* tmp_name[FOPEN_MAX]; X XFILE *tmpfile() X{ X register char *name; X register FILE *stream; X X if ((name = (char *) malloc(L_tmpnam)) == NULL) X return NULL; X X (void) tmpnam(name); X if (stream = fopen(name, "w+b")) { X _io_setflag(stream, _IO_TEMP); X tmp_name[_iobindex(stream)] = name; X if (!__tmprm) { X __tmprm = _tmp_remove; X atexit(_tmp_cleanup); X } X } else { X free(name); X } X return stream; X} X Xstatic void _tmp_cleanup() X{ X register int i; X X for (i = 0; i < FOPEN_MAX; i++) X _tmp_remove(i); X} X Xstatic int _tmp_remove(i) Xregister int i; X{ X int rc = -1; X X if (tmp_name[i]) { X rc = unlink(tmp_name[i]); X free(tmp_name[i]); X tmp_name[i] = NULL; X } X return rc; X} / echo x - tmpnam.c sed '/^X/s///' > tmpnam.c << '/' X/* --- tmpnam.c --- */ X/* Generates a unique file name */ X/* Notes: File name is of the form Tmpxxxxx.yyyyy */ X/* Not reentrant */ X X#include <sys/types.h> X#include <stdio.h> X#include <string.h> X#include <unistd.h> X#include "stdiolib.h" X#undef tmpnam X X#define DIGITS 5 /* maximum digits converted */ X Xchar *tmpnam(s) Xchar *s; X{ X static char buf[L_tmpnam]; X static int pid = 0; X static int suffix = 1; X int length; X register int width; X register char *p; X int k; X X if (s == NULL) X s = buf; X if (suffix >= TMP_MAX) { X *s = '\0'; X return NULL; X } X if (pid == 0) X pid = getpid(); X X strcpy(s, P_tmpdir); X strcat(s, "/Tmp00000.00000"); X length = strlen(s); X p = s + (length - 1 - DIGITS - 1); /* pid ends here */ X width = DIGITS; X k = pid; X do { X *p-- = k % 10 + '0'; X } while ((k /= 10) && (--width > 0)); X p = s + (length - 1); /* suffix ends here */ X width = DIGITS; X k = suffix++; X do { X *p-- = k % 10 + '0'; X } while ((k /= 10) && (--width > 0)); X return s; X} / echo x - ungetc.c sed '/^X/s///' > ungetc.c << '/' X/* --- ungetc.c --- */ X/* Pushes one character back into an input stream */ X/* Notes: Will not push back EOF */ X/* Can fail if tried too many times */ X X#include <stdio.h> X#include "stdiolib.h" X#undef ungetc X X#define _IO_ERRVAL EOF X Xint ungetc(c, stream) Xregister int c; Xregister FILE *stream; X{ X _io_assert(_io_valid(stream)); X _io_assert(!_io_testflag(stream, _IO_WRITE)); X X if (c == EOF || stream->_io_count == _IO_NEVER) X return _IO_ERRVAL; X X if (stream->_io_bufsiz == 0) { X if (stream->_io._io_char == EOF) { X stream->_io._io_char = c; X _io_clearflag(stream, _IO_EOF); X } else { X c = _IO_ERRVAL; X } X } else { X if (stream->_io._io_ptr != stream->_io_buf) { X stream->_io_count++; X *--stream->_io._io_ptr = c; X _io_clearflag(stream, _IO_EOF); X } else { X c = _IO_ERRVAL; X } X } X return c; X} /
nfs@notecnirp.Princeton.EDU (Norbert Schlenker) (09/30/89)
echo x - ctype.c sed '/^X/s///' > ctype.c << '/' X#include <ctype.h> X#undef isalnum X#undef isalpha X#undef isascii X#undef iscntrl X#undef isdigit X#undef isgraph X#undef islower X#undef isprint X#undef ispunct X#undef isspace X#undef isupper X#undef isxdigit X#undef toascii X#undef _tolower X#undef _toupper X#undef tolower X#undef toupper X X#define _CT_CS (_CT_C | _CT_S) /* control character and white space */ X#define _CT_UX (_CT_U | _CT_X) /* upper case hex digit */ X#define _CT_LX (_CT_L | _CT_X) /* lower case hex digit */ X Xchar _ctype[] = { X 0, X _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, X _CT_C, _CT_CS, _CT_CS, _CT_CS, _CT_CS, _CT_CS, _CT_C, _CT_C, X _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, X _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, _CT_C, X _CT_SP, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, X _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, X _CT_N, _CT_N, _CT_N, _CT_N, _CT_N, _CT_N, _CT_N, _CT_N, X _CT_N, _CT_N, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, X _CT_P, _CT_UX, _CT_UX, _CT_UX, _CT_UX, _CT_UX, _CT_UX, _CT_U, X _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, X _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, _CT_U, X _CT_U, _CT_U, _CT_U, _CT_P, _CT_P, _CT_P, _CT_P, _CT_P, X _CT_P, _CT_LX, _CT_LX, _CT_LX, _CT_LX, _CT_LX, _CT_LX, _CT_L, X _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, X _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, _CT_L, X _CT_L, _CT_L, _CT_L, _CT_P, _CT_P, _CT_P, _CT_P, _CT_C X}; Xint _ct_c; X X Xint isalnum(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_U | _CT_L | _CT_N); X} X Xint isalpha(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_U | _CT_L); X} X Xint isascii(c) Xint c; X{ X return (unsigned) c <= 0x7f; X} X Xint iscntrl(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_C); X} X Xint isdigit(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_N); X} X Xint isgraph(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_U | _CT_L | _CT_N | _CT_P); X} X Xint islower(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_L); X} X Xint isprint(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_U | _CT_L | _CT_N | _CT_P | _CT_SP); X} X Xint ispunct(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_P); X} X Xint isspace(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_S | _CT_SP); X} X Xint isupper(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_U); X} X Xint isxdigit(c) Xint c; X{ X return (_ctype+1)[c] & (_CT_N | _CT_X); X} X Xint toascii(c) Xint c; X{ X return c & 0x7f; X} X Xint _tolower(c) Xint c; X{ X return c - 'A' + 'a'; X} X Xint _toupper(c) Xint c; X{ X return c - 'a' + 'A'; X} X Xint tolower(c) Xint c; X{ X return ((_ctype+1)[c] & (_CT_U)) ? c - 'A' + 'a' : c; X} X Xint toupper(c) Xint c; X{ X return ((_ctype+1)[c] & (_CT_L)) ? c - 'a' + 'A' : c; X} / echo x - div.c sed '/^X/s///' > div.c << '/' X#include <stdlib.h> X Xdiv_t div(numer, denom) Xint numer; Xint denom; X{ X div_t result; X X result.quot = numer / denom; X result.rem = numer % denom; X return result; X} / echo x - ldiv.c sed '/^X/s///' > ldiv.c << '/' X#include <stdlib.h> X Xldiv_t ldiv(numer, denom) Xlong int numer; Xlong int denom; X{ X ldiv_t result; X X result.quot = numer / denom; X result.rem = numer % denom; X return result; X} / echo x - strtol.c sed '/^X/s///' > strtol.c << '/' X#include <ctype.h> X#include <errno.h> X#include <limits.h> X#include <stdlib.h> X#undef strtol X#undef atoi X#undef atol X Xlong int strtol(nptr, endptr, base) Xregister const char *nptr; Xchar **endptr; Xint base; X{ X register int c; X long result = 0L; X long limit; X int negative = 0; X int overflow = 0; X int digit; X X while ((c = *nptr) && isspace(c)) /* skip leading white space */ X nptr++; X if ((c = *nptr) == '+' || c == '-') { /* handle signs */ X negative = (c == '-'); X nptr++; X } X if (base == 0) { /* determine base if unknown */ X base = 10; X if (*nptr == '0') { X base = 8; X nptr++; X if ((c = *nptr) == 'x' || c == 'X') { X base = 16; X nptr++; X } X } X } X else X if (base == 16 && *nptr == '0') { /* discard 0x/0X prefix if hex */ X nptr++; X if ((c = *nptr == 'x') || c == 'X') X nptr++; X } X X limit = LONG_MAX / base; /* ensure no overflow */ X X nptr--; /* convert the number */ X while (c = *++nptr) { X if (isdigit(c)) X digit = c - '0'; X else X digit = c - (isupper(c) ? 'A' : 'a') + 10; X if (digit < 0 || digit >= base) X break; X if (result > limit) X overflow = 1; X if (!overflow) { X result = base * result; X if (digit > LONG_MAX - result) X overflow = 1; X else X result += digit; X } X } X if (negative && !overflow) X result = 0L - result; X if (overflow) { X errno = ERANGE; X if (negative) X result = LONG_MIN; X else X result = LONG_MAX; X } X X if (endptr != NULL) /* set up return values */ X *endptr = nptr; X return result; X} X Xint atoi(nptr) Xconst char *nptr; X{ X return (int) strtol(nptr, NULL, 10); X} X Xlong atol(nptr) Xconst char *nptr; X{ X return strtol(nptr, NULL, 10); X} / echo x - strtoul.c sed '/^X/s///' > strtoul.c << '/' X#include <ctype.h> X#include <errno.h> X#include <limits.h> X#include <stdlib.h> X#undef strtoul X Xunsigned long int strtoul(nptr, endptr, base) Xregister const char *nptr; Xchar **endptr; Xint base; X{ X register int c; X unsigned long result = 0L; X unsigned long limit; X int negative = 0; X int overflow = 0; X int digit; X X while ((c = *nptr) && isspace(c)) /* skip leading white space */ X nptr++; X if ((c = *nptr) == '+' || c == '-') { /* handle signs */ X negative = (c == '-'); X nptr++; X } X if (base == 0) { /* determine base if unknown */ X base = 10; X if (*nptr == '0') { X base = 8; X nptr++; X if ((c = *nptr) == 'x' || c == 'X') { X base = 16; X nptr++; X } X } X } X else X if (base == 16 && *nptr == '0') { /* discard 0x/0X prefix if hex */ X nptr++; X if ((c = *nptr == 'x') || c == 'X') X nptr++; X } X X limit = ULONG_MAX / base; /* ensure no overflow */ X X nptr--; /* convert the number */ X while (c = *++nptr) { X if (isdigit(c)) X digit = c - '0'; X else X digit = c - (isupper(c) ? 'A' : 'a') + 10; X if (digit < 0 || digit >= base) X break; X if (result > limit) X overflow = 1; X if (!overflow) { X result = base * result; X if (digit > ULONG_MAX - result) X overflow = 1; X else X result += digit; X } X } X if (negative && !overflow) /* BIZARRE, but ANSI says we should do this! */ X result = 0L - result; X if (overflow) { X errno = ERANGE; X result = ULONG_MAX; X } X X if (endptr != NULL) /* point at tail */ X *endptr = nptr; X return result; X} / echo x - printk.c sed '/^X/s///' > printk.c << '/' X/* --- printk.c --- */ X/* Kernel's version of printf() */ X X#define _KERNEL_ X#include <prototype.h> X#include "_doprnt.c" / echo x - prints.c sed '/^X/s///' > prints.c << '/' X/* prints() is like printf(), except that it doesn't have anything to do X * with streams and it can only handle %s and %c. It cannot print any X * of the numeric types such as %d, %o, etc. It always left justifies X * strings; it cannot right justify them. It has the advantage of not X * requiring the runtime code for converting binary numbers to ASCII, X * which saves 1K bytes in the object program. Since many of the small X * utilities do not need numeric printing, they often use prints(). It X * has the disadvantage that its output is not synchronized with any stream. X */ X X#include <sys/types.h> X#include <stdarg.h> X#include <unistd.h> X X#define STDOUT 1 X#define TRUNC_SIZE 128 X#define PUT(c) { if (bp != &buf[TRUNC_SIZE]) *bp++ = c; } X Xint prints(s) Xchar *s; X{ X va_list ap; X char buf[TRUNC_SIZE]; X register char *fp = s; X register char *bp = buf; X register int width; X char *p, *p1; X X va_start(ap, s); X while (*fp) { X if (*fp != '%') { X PUT(*fp++); X continue; X } X fp++; X width = 0; X while (*fp >= '0' && *fp <= '9') X width = 10 * width + (*fp++ - '0'); X switch (*fp) { X case 'c': X PUT(va_arg(ap, char)); X break; X case 's': X p1 = p = va_arg(ap, char *); X while(*p1) PUT(*p1++); X for (width -= (p1 - p); --width >= 0; ) X PUT(' '); X break; X default: X PUT('%'); PUT(*s); X break; X } X fp++; X } X write(STDOUT, buf, bp - buf); /* write everything at once */ X return bp - buf; X} / echo x - cuserid.c sed '/^X/s///' > cuserid.c << '/' X#define _POSIX_SOURCE X#include <sys/types.h> X#include <pwd.h> X#include <stdio.h> X#include <string.h> X#include <unistd.h> X Xchar *cuserid(s) Xchar *s; X{ X static char id[L_cuserid]; X struct passwd *pwd; X X if (s == NULL) X s = id; X X if ((pwd = getpwuid(geteuid())) == NULL) { X *s = '\0'; X return NULL; X } X strcpy(s, pwd->pw_name); X return s; X} / echo x - getlogin.c sed '/^X/s///' > getlogin.c << '/' X#define _POSIX_SOURCE X#include <sys/types.h> X#include <pwd.h> X#include <stdio.h> X#include <string.h> X#include <unistd.h> X Xchar *getlogin() X{ X static char id[L_cuserid]; X struct passwd *pwd; X X if ((pwd = getpwuid(getuid())) == NULL) X return NULL; X return strcpy(id, pwd->pw_name); X} / echo x - getgrent.c sed '/^X/s///' > getgrent.c << '/' X/* X * get entry from group file X * By Patrick van Kleef X * POSIX conversion by Norbert Schlenker X */ X X#define _POSIX_SOURCE X#include <sys/types.h> X#include <fcntl.h> X#include <grp.h> X#include <stdlib.h> X#include <string.h> X#include <unistd.h> X X#define PRIVATE static X X XPRIVATE char _gr_file[] = "/etc/group"; XPRIVATE char _grbuf[256]; XPRIVATE char _buffer[1024]; XPRIVATE char *_pnt; XPRIVATE char *_buf; XPRIVATE int _gfd = -1; XPRIVATE int _bufcnt; XPRIVATE struct group grp; XPRIVATE char *_mem = NULL; X Xint setgrent() X{ X if (_gfd >= 0) X lseek (_gfd, 0L, SEEK_SET); X else X _gfd = open(_gr_file, O_RDONLY); X X _bufcnt = 0; X return (_gfd); X} X X Xvoid endgrent() X{ X if (_gfd >= 0) X close (_gfd); X X _gfd = -1; X _bufcnt = 0; X} X X XPRIVATE int _getline() X{ X if (_gfd < 0 && setgrent() < 0) X return 0; X X _buf = _grbuf; X do { X if (--_bufcnt <= 0) { X if ((_bufcnt = read(_gfd, _buffer, 1024)) <= 0) X return 0; X else X _pnt = _buffer; X } X *_buf++ = *_pnt++; X } while (*_pnt != '\n'); X _pnt++; X _bufcnt--; X *_buf = 0; X _buf = _grbuf; X return 1; X} X XPRIVATE void _skip_period() X{ X while ((*_buf) && (*_buf != ':')) X _buf++; X *_buf++ = '\0'; X} X Xstruct group *getgrent() X{ X if (_getline() == 0) X return 0; X X grp.gr_name = _buf; X _skip_period(); X grp.gr_passwd = _buf; X _skip_period(); X grp.gr_gid = (gid_t) atoi (_buf); X _skip_period(); X return &grp; X} X XPRIVATE void _grp_members() /* PENDING - needs to be rather more elaborate */ X{ X grp.gr_mem = &_mem; X} X Xstruct group *getgrnam(name) Xchar *name; X{ X struct group *grp; X X setgrent(); X while ((grp = getgrent()) != 0) X if (!strcmp(grp->gr_name, name)) X break; X endgrent(); X _grp_members(); X return grp; X} X Xstruct group *getgrgid(gid) Xgid_t gid; X{ X struct group *grp; X X setgrent(); X while ((grp = getgrent()) != 0) X if (grp->gr_gid == gid) X break; X endgrent(); X _grp_members(); X return grp; X} / echo x - getpwent.c sed '/^X/s///' > getpwent.c << '/' X/* X * get entry from password file X * By Patrick van Kleef X * POSIX conversion by Norbert Schlenker X */ X X#define _POSIX_SOURCE X#include <sys/types.h> X#include <fcntl.h> X#include <pwd.h> X#include <stdlib.h> X#include <string.h> X#include <unistd.h> X X#define PRIVATE static X XPRIVATE char _pw_file[] = "/etc/passwd"; XPRIVATE char _pwbuf[256]; XPRIVATE char _buffer[1024]; XPRIVATE char *_pnt; XPRIVATE char *_buf; XPRIVATE int _pw = -1; XPRIVATE int _bufcnt; XPRIVATE struct passwd pwd; X Xint setpwent() X{ X if (_pw >= 0) X lseek(_pw, 0L, SEEK_SET); X else X _pw = open(_pw_file, O_RDONLY); X X _bufcnt = 0; X return _pw; X} X X Xvoid endpwent() X{ X if (_pw >= 0) X close (_pw); X X _pw = -1; X _bufcnt = 0; X} X XPRIVATE int _getline() X{ X if (_pw < 0 && setpwent() < 0) X return 0; X _buf = _pwbuf; X do { X if (--_bufcnt <= 0) { X if ((_bufcnt = read(_pw, _buffer, 1024)) <= 0) X return 0; X else X _pnt = _buffer; X } X *_buf++ = *_pnt++; X } while (*_pnt != '\n'); X _pnt++; X _bufcnt--; X *_buf = 0; X _buf = _pwbuf; X return 1; X} X XPRIVATE void _skip_period() X{ X while (*_buf != ':') X _buf++; X *_buf++ = '\0'; X} X Xstruct passwd *getpwent() X{ X if (_getline() == 0) X return 0; X X pwd.pw_name = _buf; X _skip_period(); X pwd.pw_passwd = _buf; X _skip_period(); X pwd.pw_uid = (uid_t) atoi (_buf); X _skip_period(); X pwd.pw_gid = (gid_t) atoi (_buf); X _skip_period(); X pwd.pw_gecos = _buf; X _skip_period(); X pwd.pw_dir = _buf; X _skip_period(); X pwd.pw_shell = _buf; X X return &pwd; X} X Xstruct passwd *getpwnam(name) Xchar *name; X{ X struct passwd *pwd; X X setpwent(); X while ((pwd = getpwent()) != 0) X if (!strcmp(pwd->pw_name, name)) X break; X endpwent(); X return pwd; X} X Xstruct passwd *getpwuid(uid) Xuid_t uid; X{ X struct passwd *pwd; X X setpwent(); X while ((pwd = getpwent()) != 0) X if (pwd->pw_uid == uid) X break; X endpwent(); X return pwd; X} /