new stdio
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Mon, 21 Jan 1991 13:35:03 +0000 (05:35 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Mon, 21 Jan 1991 13:35:03 +0000 (05:35 -0800)
SCCS-vsn: lib/libc/stdio/setbuf.c 5.3
SCCS-vsn: lib/libc/stdio/setbuffer.c 5.3
SCCS-vsn: lib/libc/stdio/sprintf.c 5.7
SCCS-vsn: lib/libc/stdio/stdio.3 6.3
SCCS-vsn: lib/libc/stdio/ungetc.3 6.3
SCCS-vsn: lib/libc/stdio/ungetc.c 5.4
SCCS-vsn: lib/libc/stdio/vprintf.c 5.4
SCCS-vsn: lib/libc/stdio/vsprintf.c 5.4
SCCS-vsn: lib/libc/stdio/fclose.c 5.1
SCCS-vsn: lib/libc/stdio/feof.c 5.1
SCCS-vsn: lib/libc/stdio/ferror.c 5.1
SCCS-vsn: lib/libc/stdio/fflush.c 5.1
SCCS-vsn: lib/libc/stdio/fgetln.c 5.1
SCCS-vsn: lib/libc/stdio/fgetpos.c 5.1
SCCS-vsn: lib/libc/stdio/fileno.c 5.1
SCCS-vsn: lib/libc/stdio/flags.c 5.1
SCCS-vsn: lib/libc/stdio/floatio.h 5.1
SCCS-vsn: lib/libc/stdio/fpurge.c 5.1
SCCS-vsn: lib/libc/stdio/fscanf.c 5.1
SCCS-vsn: lib/libc/stdio/fsetpos.c 5.1
SCCS-vsn: lib/libc/stdio/funopen.c 5.1
SCCS-vsn: lib/libc/stdio/fvwrite.c 5.1
SCCS-vsn: lib/libc/stdio/fvwrite.h 5.1
SCCS-vsn: lib/libc/stdio/fwalk.c 5.1
SCCS-vsn: lib/libc/stdio/getc.c 5.1
SCCS-vsn: lib/libc/stdio/glue.h 5.1
SCCS-vsn: lib/libc/stdio/local.h 5.1
SCCS-vsn: lib/libc/stdio/makebuf.c 5.1
SCCS-vsn: lib/libc/stdio/putc.c 5.1
SCCS-vsn: lib/libc/stdio/refill.c 5.1
SCCS-vsn: lib/libc/stdio/remove.c 5.1
SCCS-vsn: lib/libc/stdio/rget.c 5.1
SCCS-vsn: lib/libc/stdio/setvbuf.c 5.1
SCCS-vsn: lib/libc/stdio/snprintf.c 5.1
SCCS-vsn: lib/libc/stdio/sscanf.c 5.1
SCCS-vsn: lib/libc/stdio/stdio.c 5.1
SCCS-vsn: lib/libc/stdio/tmpfile.c 5.1
SCCS-vsn: lib/libc/stdio/tmpnam.c 5.1
SCCS-vsn: lib/libc/stdio/vsnprintf.c 5.1
SCCS-vsn: lib/libc/stdio/wsetup.c 5.1

40 files changed:
usr/src/lib/libc/stdio/fclose.c [new file with mode: 0644]
usr/src/lib/libc/stdio/feof.c [new file with mode: 0644]
usr/src/lib/libc/stdio/ferror.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fflush.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fgetln.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fgetpos.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fileno.c [new file with mode: 0644]
usr/src/lib/libc/stdio/flags.c [new file with mode: 0644]
usr/src/lib/libc/stdio/floatio.h [new file with mode: 0644]
usr/src/lib/libc/stdio/fpurge.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fscanf.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fsetpos.c [new file with mode: 0644]
usr/src/lib/libc/stdio/funopen.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fvwrite.c [new file with mode: 0644]
usr/src/lib/libc/stdio/fvwrite.h [new file with mode: 0644]
usr/src/lib/libc/stdio/fwalk.c [new file with mode: 0644]
usr/src/lib/libc/stdio/getc.c [new file with mode: 0644]
usr/src/lib/libc/stdio/glue.h [new file with mode: 0644]
usr/src/lib/libc/stdio/local.h [new file with mode: 0644]
usr/src/lib/libc/stdio/makebuf.c [new file with mode: 0644]
usr/src/lib/libc/stdio/putc.c [new file with mode: 0644]
usr/src/lib/libc/stdio/refill.c [new file with mode: 0644]
usr/src/lib/libc/stdio/remove.c [new file with mode: 0644]
usr/src/lib/libc/stdio/rget.c [new file with mode: 0644]
usr/src/lib/libc/stdio/setbuf.c
usr/src/lib/libc/stdio/setbuffer.c
usr/src/lib/libc/stdio/setvbuf.c [new file with mode: 0644]
usr/src/lib/libc/stdio/snprintf.c [new file with mode: 0644]
usr/src/lib/libc/stdio/sprintf.c
usr/src/lib/libc/stdio/sscanf.c [new file with mode: 0644]
usr/src/lib/libc/stdio/stdio.3
usr/src/lib/libc/stdio/stdio.c [new file with mode: 0644]
usr/src/lib/libc/stdio/tmpfile.c [new file with mode: 0644]
usr/src/lib/libc/stdio/tmpnam.c [new file with mode: 0644]
usr/src/lib/libc/stdio/ungetc.3
usr/src/lib/libc/stdio/ungetc.c
usr/src/lib/libc/stdio/vprintf.c
usr/src/lib/libc/stdio/vsnprintf.c [new file with mode: 0644]
usr/src/lib/libc/stdio/vsprintf.c
usr/src/lib/libc/stdio/wsetup.c [new file with mode: 0644]

diff --git a/usr/src/lib/libc/stdio/fclose.c b/usr/src/lib/libc/stdio/fclose.c
new file mode 100644 (file)
index 0000000..d30977d
--- /dev/null
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fclose.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+fclose(fp)
+       register FILE *fp;
+{
+       register int r;
+
+       if (fp->_flags == 0) {  /* not open! */
+               errno = EBADF;
+               return (EOF);
+       }
+       r = fp->_flags & __SWR ? fflush(fp) : 0;
+       if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
+               r = EOF;
+       if (fp->_flags & __SMBF)
+               free((char *)fp->_bf._base);
+       if (HASUB(fp))
+               FREEUB(fp);
+       if (HASLB(fp))
+               FREELB(fp);
+       fp->_flags = 0;         /* release this FILE for reuse */
+       return (r);
+}
diff --git a/usr/src/lib/libc/stdio/feof.c b/usr/src/lib/libc/stdio/feof.c
new file mode 100644 (file)
index 0000000..cecd43b
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)feof.c     5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro feof.
+ */
+#undef feof
+
+feof(fp)
+       FILE *fp;
+{
+       return (__sfeof(fp));
+}
diff --git a/usr/src/lib/libc/stdio/ferror.c b/usr/src/lib/libc/stdio/ferror.c
new file mode 100644 (file)
index 0000000..67df0a3
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ferror.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro ferror.
+ */
+#undef ferror
+
+ferror(fp)
+       FILE *fp;
+{
+       return (__sferror(fp));
+}
diff --git a/usr/src/lib/libc/stdio/fflush.c b/usr/src/lib/libc/stdio/fflush.c
new file mode 100644 (file)
index 0000000..1c57888
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fflush.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/errno.h>
+#include <stdio.h>
+#include "local.h"
+
+/* Flush a single file, or (if fp is NULL) all files.  */
+fflush(fp)
+       register FILE *fp;
+{
+       if (fp == NULL)
+               return (_fwalk(__sflush));
+
+       if ((fp->_flags & __SWR) == 0) {
+               errno = EBADF;
+               return (EOF);
+       }
+       return (__sflush(fp));
+}
+
+__sflush(fp)
+       register FILE *fp;
+{
+       register unsigned char *p;
+       register int n, t;
+
+       t = fp->_flags;
+       if ((t & __SWR) == 0)
+               return (0);
+
+       if ((p = fp->_bf._base) == NULL)
+               return (0);
+
+       n = fp->_p - p;         /* write this much */
+
+       /*
+        * Set these immediately to avoid problems with longjmp and to allow
+        * exchange buffering (via setvbuf) in user write function.
+        */
+       fp->_p = p;
+       fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
+
+       for (; n > 0; n -= t, p += t) {
+               t = (*fp->_write)(fp->_cookie, (char *)p, n);
+               if (t <= 0) {
+                       fp->_flags |= __SERR;
+                       return (EOF);
+               }
+       }
+       return (0);
+}
diff --git a/usr/src/lib/libc/stdio/fgetln.c b/usr/src/lib/libc/stdio/fgetln.c
new file mode 100644 (file)
index 0000000..df4ec86
--- /dev/null
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetln.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+
+/*
+ * Expand the line buffer.  Return -1 on error.
+ * The `new size' does not account for a terminating '\0',
+ * so we add 1 here.
+ */
+__slbexpand(fp, newsize)
+       FILE *fp;
+       size_t newsize;
+{
+       void *p;
+
+       if (fp->_lb._size >= ++newsize)
+               return (0);
+       if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+               return (-1);
+       fp->_lb._base = p;
+       fp->_lb._size = newsize;
+       return (0);
+}
+
+/*
+ * Get an input line.  The returned pointer often (but not always)
+ * points into a stdio buffer.  Fgetline smashes the newline (if any)
+ * in the stdio buffer; callers must not use it on streams that
+ * have `magic' setvbuf() games happening.
+ */
+char *
+fgetline(fp, lenp)
+       register FILE *fp;
+       size_t *lenp;
+{
+       register unsigned char *p;
+       register size_t len;
+       size_t off;
+
+       /* make sure there is input */
+       if (fp->_r <= 0 && __srefill(fp)) {
+               if (lenp != NULL)
+                       *lenp = 0;
+               return (NULL);
+       }
+
+       /* look for a newline in the input */
+       if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
+               register char *ret;
+
+               /*
+                * Found one.  Flag buffer as modified to keep
+                * fseek from `optimising' a backward seek, since
+                * the newline is about to be trashed.  (We should
+                * be able to get away with doing this only if
+                * p is not pointing into an ungetc buffer, since
+                * fseek discards ungetc data, but this is the
+                * usual case anyway.)
+                */
+               ret = (char *)fp->_p;
+               len = p - fp->_p;
+               fp->_flags |= __SMOD;
+               *p = 0;
+               fp->_r -= len + 1;
+               fp->_p = p + 1;
+               if (lenp != NULL)
+                       *lenp = len;
+               return (ret);
+       }
+
+       /*
+        * We have to copy the current buffered data to the line buffer.
+        *
+        * OPTIMISTIC is length that we (optimistically)
+        * expect will accomodate the `rest' of the string,
+        * on each trip through the loop below.
+        */
+#define OPTIMISTIC 80
+
+       for (len = fp->_r, off = 0;; len += fp->_r) {
+               register size_t diff;
+
+               /*
+                * Make sure there is room for more bytes.
+                * Copy data from file buffer to line buffer,
+                * refill file and look for newline.  The
+                * loop stops only when we find a newline.
+                */
+               if (__slbexpand(fp, len + OPTIMISTIC))
+                       goto error;
+               (void) memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+                   len - off);
+               off = len;
+               if (__srefill(fp))
+                       break;  /* EOF or error: return partial line */
+               if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
+                       continue;
+
+               /* got it: finish up the line (like code above) */
+               fp->_flags |= __SMOD;   /* soon */
+               diff = p - fp->_p;
+               len += diff;
+               if (__slbexpand(fp, len))
+                       goto error;
+               (void) memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+                   diff);
+               fp->_r -= diff + 1;
+               fp->_p = p + 1;
+               break;
+       }
+       if (lenp != NULL)
+               *lenp = len;
+       fp->_lb._base[len] = 0;
+       return ((char *)fp->_lb._base);
+
+error:
+       if (lenp != NULL)
+               *lenp = 0;      /* ??? */
+       return (NULL);          /* ??? */
+}
diff --git a/usr/src/lib/libc/stdio/fgetpos.c b/usr/src/lib/libc/stdio/fgetpos.c
new file mode 100644 (file)
index 0000000..7c9bc98
--- /dev/null
@@ -0,0 +1,22 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetpos.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+fgetpos(fp, pos)
+       FILE *fp;
+       fpos_t *pos;
+{
+       return((*pos = ftell(fp)) != (fpos_t)-1);
+}
diff --git a/usr/src/lib/libc/stdio/fileno.c b/usr/src/lib/libc/stdio/fileno.c
new file mode 100644 (file)
index 0000000..fd6fa2d
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fileno.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro fileno.
+ */
+#undef fileno
+
+fileno(fp)
+       FILE *fp;
+{
+       return (__sfileno(fp));
+}
diff --git a/usr/src/lib/libc/stdio/flags.c b/usr/src/lib/libc/stdio/flags.c
new file mode 100644 (file)
index 0000000..34e6630
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)flags.c    5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * Return the (stdio) flags for a given mode.  Store the flags
+ * to be passed to an open() syscall through *optr.
+ * Return 0 on error.
+ */
+__sflags(mode, optr)
+       register char *mode;
+       int *optr;
+{
+       register int ret, m, o;
+
+       switch (*mode++) {
+
+       case 'r':       /* open for reading */
+               ret = __SRD;
+               m = O_RDONLY;
+               o = 0;
+               break;
+
+       case 'w':       /* open for writing */
+               ret = __SWR;
+               m = O_WRONLY;
+               o = O_CREAT | O_TRUNC;
+               break;
+
+       case 'a':       /* open for appending */
+               ret = __SWR;
+               m = O_WRONLY;
+               o = O_CREAT | O_APPEND;
+               break;
+
+       default:        /* illegal mode */
+               errno = EINVAL;
+               return (0);
+       }
+
+       /* [rwa]\+ or [rwa]b\+ means read and write */
+       if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) {
+               ret = __SRW;
+               m = O_RDWR;
+       }
+       *optr = m | o;
+       return (ret);
+}
diff --git a/usr/src/lib/libc/stdio/floatio.h b/usr/src/lib/libc/stdio/floatio.h
new file mode 100644 (file)
index 0000000..cb764e4
--- /dev/null
@@ -0,0 +1,20 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)floatio.h   5.1 (Berkeley) %G%
+ */
+
+/*
+ * Floating point scanf/printf (input/output) definitions.
+ */
+
+/* 11-bit exponent (VAX G floating point) is 308 decimal digits */
+#define        MAXEXP          308
+/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
+#define        MAXFRACT        39
diff --git a/usr/src/lib/libc/stdio/fpurge.c b/usr/src/lib/libc/stdio/fpurge.c
new file mode 100644 (file)
index 0000000..0423196
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fpurge.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * fpurge: like fflush, but without writing anything: leave the
+ * given FILE's buffer empty.
+ */
+int
+fpurge(fp)
+       register FILE *fp;
+{
+       if (!fp->_flags) {
+               errno = EBADF;
+               return(EOF);
+       }
+
+       if (HASUB(fp))
+               FREEUB(fp);
+       fp->_p = fp->_bf._base;
+       fp->_r = 0;
+       fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
+       return (0);
+}
diff --git a/usr/src/lib/libc/stdio/fscanf.c b/usr/src/lib/libc/stdio/fscanf.c
new file mode 100644 (file)
index 0000000..3ecc756
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fscanf.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#if __STDC__
+fscanf(FILE *fp, char const *fmt, ...) {
+       int ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+#else
+fscanf(fp, fmt, va_alist)
+       FILE *fp;
+       char *fmt;
+       va_dcl
+{
+       int ret;
+       va_list ap;
+
+       va_start(ap);
+#endif
+       ret = __svfscanf(fp, fmt, ap);
+       va_end(ap);
+       return (ret);
+}
diff --git a/usr/src/lib/libc/stdio/fsetpos.c b/usr/src/lib/libc/stdio/fsetpos.c
new file mode 100644 (file)
index 0000000..52d481b
--- /dev/null
@@ -0,0 +1,25 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fsetpos.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * fsetpos: like fseek.
+ */
+fsetpos(iop, pos)
+       FILE *iop;
+       fpos_t *pos;
+{
+       return (fseek(iop, (long)*pos, SEEK_SET));
+}
diff --git a/usr/src/lib/libc/stdio/funopen.c b/usr/src/lib/libc/stdio/funopen.c
new file mode 100644 (file)
index 0000000..13af26c
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)funopen.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <errno.h>
+#include "local.h"
+
+FILE *
+funopen(cookie, readfn, writefn, seekfn, closefn)
+       char *cookie;
+       int (*readfn)(), (*writefn)();
+#if __STDC__
+       fpos_t (*seekfn)(char *cookie, fpos_t off, int whence);
+#else
+       fpos_t (*seekfn)();
+#endif
+       int (*closefn)();
+{
+       register FILE *fp;
+       int flags;
+
+       if (readfn == NULL) {
+               if (writefn == NULL) {          /* illegal */
+                       errno = EINVAL;
+                       return (NULL);
+               } else
+                       flags = __SWR;          /* write only */
+       } else {
+               if (writefn == NULL)
+                       flags = __SRD;          /* read only */
+               else
+                       flags = __SRW;          /* read-write */
+       }
+       if ((fp = __sfp()) == NULL)
+               return (NULL);
+       fp->_flags = flags;
+       fp->_file = -1;
+       fp->_cookie = cookie;
+       fp->_read = readfn;
+       fp->_write = writefn;
+       fp->_seek = seekfn;
+       fp->_close = closefn;
+       return (fp);
+}
diff --git a/usr/src/lib/libc/stdio/fvwrite.c b/usr/src/lib/libc/stdio/fvwrite.c
new file mode 100644 (file)
index 0000000..f7297ef
--- /dev/null
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fvwrite.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+#include "fvwrite.h"
+
+/*
+ * Write some memory regions.  Return zero on success, EOF on error.
+ *
+ * This routine is large and unsightly, but most of the ugliness due
+ * to the three different kinds of output buffering is handled here.
+ */
+__sfvwrite(fp, uio)
+       register FILE *fp;
+       register struct __suio *uio;
+{
+       register size_t len;
+       register char *p;
+       register struct __siov *iov;
+       register int w, s;
+       char *nl;
+       int nlknown, nldist;
+
+       if ((len = uio->uio_resid) == 0)
+               return (0);
+       /* make sure we can write */
+       if (cantwrite(fp))
+               return (EOF);
+
+#define        MIN(a, b) ((a) < (b) ? (a) : (b))
+#define        COPY(n)   (void) memcpy((void *)fp->_p, (void *)p, (size_t)(n));
+
+       iov = uio->uio_iov;
+       len = 0;
+#define GETIOV(extra_work) \
+       while (len == 0) { \
+               extra_work; \
+               p = iov->iov_base; \
+               len = iov->iov_len; \
+               iov++; \
+       }
+       if (fp->_flags & __SNBF) {
+               /*
+                * Unbuffered: write up to BUFSIZ bytes at a time.
+                */
+               do {
+                       GETIOV(;);
+                       w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
+                       if (w <= 0)
+                               goto err;
+                       p += w;
+                       len -= w;
+               } while ((uio->uio_resid -= w) != 0);
+       } else if ((fp->_flags & __SLBF) == 0) {
+               /*
+                * Fully buffered: fill partially full buffer, if any,
+                * and then flush.  If there is no partial buffer, write
+                * one _bf._size byte chunk directly (without copying).
+                *
+                * String output is a special case: write as many bytes
+                * as fit, but pretend we wrote everything.  This makes
+                * snprintf() return the number of bytes needed, rather
+                * than the number used, and avoids its write function
+                * (so that the write function can be invalid).
+                */
+               do {
+                       GETIOV(;);
+                       w = fp->_w;
+                       if (fp->_flags & __SSTR) {
+                               if (len < w)
+                                       w = len;
+                               COPY(w);        /* copy MIN(fp->_w,len), */
+                               fp->_w -= w;
+                               fp->_p += w;
+                               w = len;        /* but pretend copied all */
+                       } else if (fp->_p > fp->_bf._base && len > w) {
+                               /* fill and flush */
+                               COPY(w);
+                               /* fp->_w -= w; */ /* unneeded */
+                               fp->_p += w;
+                               if (fflush(fp))
+                                       goto err;
+                       } else if (len >= (w = fp->_bf._size)) {
+                               /* write directly */
+                               w = (*fp->_write)(fp->_cookie, p, w);
+                               if (w <= 0)
+                                       goto err;
+                       } else {
+                               /* fill and done */
+                               w = len;
+                               COPY(w);
+                               fp->_w -= w;
+                               fp->_p += w;
+                       }
+                       p += w;
+                       len -= w;
+               } while ((uio->uio_resid -= w) != 0);
+       } else {
+               /*
+                * Line buffered: like fully buffered, but we
+                * must check for newlines.  Compute the distance
+                * to the first newline (including the newline),
+                * or `infinity' if there is none, then pretend
+                * that the amount to write is MIN(len,nldist).
+                */
+               nlknown = 0;
+               do {
+                       GETIOV(nlknown = 0);
+                       if (!nlknown) {
+                               nl = memchr((void *)p, '\n', len);
+                               nldist = nl ? nl + 1 - p : len + 1;
+                               nlknown = 1;
+                       }
+                       s = MIN(len, nldist);
+                       w = fp->_w + fp->_bf._size;
+                       if (fp->_p > fp->_bf._base && s > w) {
+                               COPY(w);
+                               /* fp->_w -= w; */
+                               fp->_p += w;
+                               if (fflush(fp))
+                                       goto err;
+                       } else if (s >= (w = fp->_bf._size)) {
+                               w = (*fp->_write)(fp->_cookie, p, w);
+                               if (w <= 0)
+                                       goto err;
+                       } else {
+                               w = s;
+                               COPY(w);
+                               fp->_w -= w;
+                               fp->_p += w;
+                       }
+                       if ((nldist -= w) == 0) {
+                               /* copied the newline: flush and forget */
+                               if (fflush(fp))
+                                       goto err;
+                               nlknown = 0;
+                       }
+                       p += w;
+                       len -= w;
+               } while ((uio->uio_resid -= w) != 0);
+       }
+       return (0);
+
+err:
+       fp->_flags |= __SERR;
+       return (EOF);
+}
diff --git a/usr/src/lib/libc/stdio/fvwrite.h b/usr/src/lib/libc/stdio/fvwrite.h
new file mode 100644 (file)
index 0000000..c8012b5
--- /dev/null
@@ -0,0 +1,30 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)fvwrite.h   5.1 (Berkeley) %G%
+ */
+
+/*
+ * I/O descriptors for __sfvwrite().
+ */
+struct __siov {
+       void    *iov_base;
+       size_t  iov_len;
+};
+struct __suio {
+       struct  __siov *uio_iov;
+       int     uio_iovcnt;
+       int     uio_resid;
+};
+
+#if __STDC__ || c_plusplus
+extern int __sfvwrite(FILE *, struct __suio *);
+#else
+extern int __sfvwrite();
+#endif
diff --git a/usr/src/lib/libc/stdio/fwalk.c b/usr/src/lib/libc/stdio/fwalk.c
new file mode 100644 (file)
index 0000000..5f6e88e
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fwalk.c    5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "local.h"
+#include "glue.h"
+
+_fwalk(function)
+       register int (*function)();
+{
+       register FILE *fp;
+       register int n, ret;
+       register struct glue *g;
+
+       ret = 0;
+       for (g = &__sglue; g != NULL; g = g->next)
+               for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
+                       if (fp->_flags != 0)
+                               ret |= (*function)(fp);
+       return (ret);
+}
diff --git a/usr/src/lib/libc/stdio/getc.c b/usr/src/lib/libc/stdio/getc.c
new file mode 100644 (file)
index 0000000..5029df4
--- /dev/null
@@ -0,0 +1,26 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getc.c     5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro getc.
+ */
+#undef getc
+
+getc(fp)
+       register FILE *fp;
+{
+       return (__sgetc(fp));
+}
diff --git a/usr/src/lib/libc/stdio/glue.h b/usr/src/lib/libc/stdio/glue.h
new file mode 100644 (file)
index 0000000..c9d21f5
--- /dev/null
@@ -0,0 +1,21 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)glue.h      5.1 (Berkeley) %G%
+ */
+
+/*
+ * The first few FILEs are statically allocated; others are dynamically
+ * allocated and linked in via this glue structure.
+ */
+struct glue {
+       struct  glue *next;
+       int     niobs;
+       FILE    *iobs;
+} __sglue;
diff --git a/usr/src/lib/libc/stdio/local.h b/usr/src/lib/libc/stdio/local.h
new file mode 100644 (file)
index 0000000..d3f3bf0
--- /dev/null
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)local.h     5.1 (Berkeley) %G%
+ */
+
+/*
+ * Information local to this implementation of stdio,
+ * in particular, macros and private variables.
+ */
+
+#if __STDC__ || c_plusplus
+extern int     __sflush(FILE *);
+extern FILE    *__sfp(void);
+extern int     __srefill(FILE *);
+extern int     __sread(void *, char *, int);
+extern int     __swrite(void *, char const *, int);
+extern fpos_t  __sseek(void *, fpos_t, int);
+extern int     __sclose(void *);
+extern void    __sinit(void);
+extern void    _cleanup(void);
+extern void    (*__cleanup)(void);
+extern void    __smakebuf(FILE *);
+extern int     _fwalk(int (*)(FILE *));
+#else /* __STDC__ || c_plusplus */
+extern int     __sflush();
+extern FILE    *__sfp();
+extern int     __srefill();
+extern int     __sread();
+extern int     __swrite();
+extern fpos_t  __sseek();
+extern int     __sclose();
+extern void    __sinit();
+extern void    _cleanup();
+extern void    (*__cleanup)();
+extern void    __smakebuf();
+extern int     __sfwalk();
+#endif /* __STDC__ || c_plusplus */
+
+extern int __sdidinit;
+
+/*
+ * Return true iff the given FILE cannot be written now.
+ */
+#define        cantwrite(fp) \
+       ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \
+        __swsetup(fp))
+
+/*
+ * Test whether the given stdio file has an active ungetc buffer;
+ * release such a buffer, without restoring ordinary unread data.
+ */
+#define        HASUB(fp) ((fp)->_ub._base != NULL)
+#define        FREEUB(fp) { \
+       if ((fp)->_ub._base != (fp)->_ubuf) \
+               free((char *)(fp)->_ub._base); \
+       (fp)->_ub._base = NULL; \
+}
+
+/*
+ * test for an fgetline() buffer.
+ */
+#define        HASLB(fp) ((fp)->_lb._base != NULL)
+#define        FREELB(fp) { \
+       free((char *)(fp)->_lb._base); \
+       (fp)->_lb._base = NULL; \
+}
diff --git a/usr/src/lib/libc/stdio/makebuf.c b/usr/src/lib/libc/stdio/makebuf.c
new file mode 100644 (file)
index 0000000..ae0b3f5
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)makebuf.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * Allocate a file buffer, or switch to unbuffered I/O.
+ * Per the ANSI C standard, ALL tty devices default to line buffered.
+ *
+ * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
+ * optimisation) right after the fstat() that finds the buffer size.
+ */
+void
+__smakebuf(fp)
+       register FILE *fp;
+{
+       register size_t size, couldbetty;
+       register void *p;
+       struct stat st;
+
+       if (fp->_flags & __SNBF) {
+               fp->_bf._base = fp->_p = fp->_nbuf;
+               fp->_bf._size = 1;
+               return;
+       }
+       if (fp->_file < 0 || fstat(fp->_file, &st) < 0) {
+               couldbetty = 0;
+               size = BUFSIZ;
+               /* do not try to optimise fseek() */
+               fp->_flags |= __SNPT;
+       } else {
+               couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
+               size = st.st_blksize <= 0 ? BUFSIZ : st.st_blksize;
+               /*
+                * Optimise fseek() only if it is a regular file.
+                * (The test for __sseek is mainly paranoia.)
+                */
+               if ((st.st_mode & S_IFMT) == S_IFREG &&
+                   fp->_seek == __sseek) {
+                       fp->_flags |= __SOPT;
+                       fp->_blksize = st.st_blksize;
+               } else
+                       fp->_flags |= __SNPT;
+       }
+       if ((p = malloc(size)) == NULL) {
+               fp->_flags |= __SNBF;
+               fp->_bf._base = fp->_p = fp->_nbuf;
+               fp->_bf._size = 1;
+       } else {
+               __cleanup = _cleanup;
+               fp->_flags |= __SMBF;
+               fp->_bf._base = fp->_p = p;
+               fp->_bf._size = size;
+               if (couldbetty && isatty(fp->_file))
+                       fp->_flags |= __SLBF;
+       }
+}
diff --git a/usr/src/lib/libc/stdio/putc.c b/usr/src/lib/libc/stdio/putc.c
new file mode 100644 (file)
index 0000000..93c0bde
--- /dev/null
@@ -0,0 +1,27 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putc.c     5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * A subroutine version of the macro putc.
+ */
+#undef putc
+
+putc(c, fp)
+       int c;
+       register FILE *fp;
+{
+       return (__sputc(c, fp));
+}
diff --git a/usr/src/lib/libc/stdio/refill.c b/usr/src/lib/libc/stdio/refill.c
new file mode 100644 (file)
index 0000000..e70bd4b
--- /dev/null
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)refill.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <errno.h>
+#include <stdio.h>
+#include "local.h"
+
+static
+lflush(fp)
+       FILE *fp;
+{
+
+       if ((fp->_flags & (__SLBF|__SWR)) == __SLBF|__SWR)
+               return (fflush(fp));
+       return (0);
+}
+
+/*
+ * Refill a stdio buffer.
+ * Return EOF on eof or error, 0 otherwise.
+ */
+__srefill(fp)
+       register FILE *fp;
+{
+
+       /* make sure stdio is set up */
+       if (!__sdidinit)
+               __sinit();
+
+       fp->_r = 0;             /* largely a convenience for callers */
+
+       /* SysV does not make this test; take it out for compatibility */
+       if (fp->_flags & __SEOF)
+               return (EOF);
+
+       /* if not already reading, have to be reading and writing */
+       if ((fp->_flags & __SRD) == 0) {
+               if ((fp->_flags & __SRW) == 0) {
+                       errno = EBADF;
+                       return (EOF);
+               }
+               /* switch to reading */
+               if (fp->_flags & __SWR) {
+                       if (fflush(fp))
+                               return (EOF);
+                       fp->_flags &= ~__SWR;
+                       fp->_w = 0;
+                       fp->_lbfsize = 0;
+               }
+               fp->_flags |= __SRD;
+       } else {
+               /*
+                * We were reading.  If there is an ungetc buffer,
+                * we must have been reading from that.  Drop it,
+                * restoring the previous buffer (if any).  If there
+                * is anything in that buffer, return.
+                */
+               if (HASUB(fp)) {
+                       FREEUB(fp);
+                       if ((fp->_r = fp->_ur) != 0) {
+                               fp->_p = fp->_up;
+                               return (0);
+                       }
+               }
+       }
+
+       if (fp->_bf._base == NULL)
+               __smakebuf(fp);
+
+       /*
+        * Before reading from a line buffered or unbuffered file,
+        * flush all line buffered output files, per the ANSI C
+        * standard.
+        */
+       if (fp->_flags & (__SLBF|__SNBF))
+               (void) _fwalk(lflush);
+       fp->_p = fp->_bf._base;
+       fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size);
+       fp->_flags &= ~__SMOD;  /* buffer contents are again pristine */
+       if (fp->_r <= 0) {
+               if (fp->_r == 0)
+                       fp->_flags |= __SEOF;
+               else {
+                       fp->_r = 0;
+                       fp->_flags |= __SERR;
+               }
+               return (EOF);
+       }
+       return (0);
+}
diff --git a/usr/src/lib/libc/stdio/remove.c b/usr/src/lib/libc/stdio/remove.c
new file mode 100644 (file)
index 0000000..81f929b
--- /dev/null
@@ -0,0 +1,21 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)remove.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+remove(file)
+       char *file;
+{
+       return (unlink(file));
+}
diff --git a/usr/src/lib/libc/stdio/rget.c b/usr/src/lib/libc/stdio/rget.c
new file mode 100644 (file)
index 0000000..7c2728b
--- /dev/null
@@ -0,0 +1,30 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rget.c     5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * Handle getc() when the buffer ran out:
+ * Refill, then return the first character
+ * in the newly-filled buffer.
+ */
+__srget(fp)
+       register FILE *fp;
+{
+       if (__srefill(fp) == 0) {
+               fp->_r--;
+               return (*fp->_p++);
+       }
+       return (EOF);
+}
index d98e6f5..a3ef14f 100644 (file)
@@ -1,28 +1,24 @@
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)setbuf.c   5.2 (Berkeley) %G%";
-#endif LIBC_SCCS and not lint
+static char sccsid[] = "@(#)setbuf.c   5.3 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
 
 
-#include       <stdio.h>
+#include <stdio.h>
+#include "local.h"
 
 
-setbuf(iop, buf)
-register FILE *iop;
-char *buf;
+void
+setbuf(fp, buf)
+       FILE *fp;
+       char *buf;
 {
 {
-       if (iop->_base != NULL && iop->_flag&_IOMYBUF)
-               free(iop->_base);
-       iop->_flag &= ~(_IOMYBUF|_IONBF|_IOLBF);
-       if ((iop->_base = buf) == NULL) {
-               iop->_flag |= _IONBF;
-               iop->_bufsiz = NULL;
-       } else {
-               iop->_ptr = iop->_base;
-               iop->_bufsiz = BUFSIZ;
-       }
-       iop->_cnt = 0;
+       (void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
 }
 }
index bed05a9..861cf18 100644 (file)
@@ -1,47 +1,35 @@
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)setbuffer.c        5.2 (Berkeley) %G%";
-#endif LIBC_SCCS and not lint
+static char sccsid[] = "@(#)setbuffer.c        5.3 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
 
 
-#include       <stdio.h>
+#include <stdio.h>
+#include <stdlib.h>
 
 
-setbuffer(iop, buf, size)
-       register FILE *iop;
+void
+setbuffer(fp, buf, size)
+       register FILE *fp;
        char *buf;
        int size;
 {
        char *buf;
        int size;
 {
-       if (iop->_base != NULL && iop->_flag&_IOMYBUF)
-               free(iop->_base);
-       iop->_flag &= ~(_IOMYBUF|_IONBF|_IOLBF);
-       if ((iop->_base = buf) == NULL) {
-               iop->_flag |= _IONBF;
-               iop->_bufsiz = NULL;
-       } else {
-               iop->_ptr = iop->_base;
-               iop->_bufsiz = size;
-       }
-       iop->_cnt = 0;
+       (void) setvbuf(fp, buf, buf ? _IONBF : _IOFBF, size);
 }
 
 /*
 }
 
 /*
- * set line buffering for either stdout or stderr
+ * set line buffering
  */
  */
-setlinebuf(iop)
-       register FILE *iop;
+setlinebuf(fp)
+       FILE *fp;
 {
 {
-       char *buf;
-       extern char *malloc();
-
-       fflush(iop);
-       setbuffer(iop, NULL, 0);
-       buf = malloc(BUFSIZ);
-       if (buf != NULL) {
-               setbuffer(iop, buf, BUFSIZ);
-               iop->_flag |= _IOLBF|_IOMYBUF;
-       }
+       (void) setvbuf(fp, (char *)NULL, _IOLBF, (size_t)0);
+       return (0);     /* ??? */
 }
 }
diff --git a/usr/src/lib/libc/stdio/setvbuf.c b/usr/src/lib/libc/stdio/setvbuf.c
new file mode 100644 (file)
index 0000000..bd66017
--- /dev/null
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setvbuf.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * Set one of the three kinds of buffering, optionally including
+ * a buffer.
+ */
+setvbuf(fp, buf, mode, size)
+       register FILE *fp;
+       char *buf;
+       register int mode;
+       register size_t size;
+{
+
+       /*
+        * Verify arguments.  The `int' limit on `size' is due to this
+        * particular implementation.
+        */
+       if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) ||
+           (int)size < 0)
+               return (EOF);
+
+       /*
+        * Write current buffer, if any; drop read count, if any.
+        * Make sure putc() will not think fp is line buffered.
+        * Free old buffer if it was from malloc().  Clear line and
+        * non buffer flags, and clear malloc flag.
+        */
+       (void) fflush(fp);
+       fp->_r = 0;
+       fp->_lbfsize = 0;
+       if (fp->_flags & __SMBF)
+               free((void *)fp->_bf._base);
+       fp->_flags &= ~(__SLBF|__SNBF|__SMBF);
+
+       /*
+        * Now put back whichever flag is needed, and fix _lbfsize
+        * if line buffered.  Ensure output flush on exit if the
+        * stream will be buffered at all.
+        */
+       switch (mode) {
+
+       case _IONBF:
+               fp->_flags |= __SNBF;
+               fp->_bf._base = fp->_p = fp->_nbuf;
+               fp->_bf._size = 1;
+               break;
+
+       case _IOLBF:
+               fp->_flags |= __SLBF;
+               fp->_lbfsize = -size;
+               /* FALLTHROUGH */
+
+       case _IOFBF:
+               /* no flag */
+               __cleanup = _cleanup;
+               fp->_bf._base = fp->_p = (unsigned char *)buf;
+               fp->_bf._size = size;
+               break;
+       }
+
+       /*
+        * Patch up write count if necessary.
+        */
+       if (fp->_flags & __SWR)
+               fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : size;
+
+       return (0);
+}
diff --git a/usr/src/lib/libc/stdio/snprintf.c b/usr/src/lib/libc/stdio/snprintf.c
new file mode 100644 (file)
index 0000000..4687ec4
--- /dev/null
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)snprintf.c 5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#if __STDC__
+snprintf(char *str, size_t n, char const *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+       char *str;
+       size_t n;
+       char *fmt;
+       va_dcl
+#endif
+{
+       int ret;
+       va_list ap;
+       FILE f;
+
+       if ((int)n < 1)
+               return (EOF);
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       f._flags = __SWR | __SSTR;
+       f._bf._base = f._p = (unsigned char *)str;
+       f._bf._size = f._w = n - 1;
+       ret = vfprintf(&f, fmt, ap);
+       *f._p = 0;
+       va_end(ap);
+       return (ret);
+}
index 1727c0b..ee792d1 100644 (file)
@@ -1,27 +1,49 @@
-/*
- * Copyright (c) 1987 Regents of the University of California.
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * All rights reserved.
  *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
  * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)sprintf.c  5.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)sprintf.c  5.7 (Berkeley) %G%";
 #endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
 #endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <limits.h>
+#include "local.h"
 
 
-sprintf(str, fmt, args)
-       char *str, *fmt;
-       int args;
+#if __STDC__
+sprintf(char *str, char const *fmt, ...)
+#else
+sprintf(str, fmt, va_alist)
+       char *str;
+       char *fmt;
+       va_dcl
+#endif
 {
 {
-       FILE _strbuf;
-       int len;
+       int ret;
+       va_list ap;
+       FILE f;
 
 
-       _strbuf._flag = _IOWRT+_IOSTRG;
-       _strbuf._ptr = str;
-       _strbuf._cnt = 32767;
-       len = _doprnt(fmt, &args, &_strbuf);
-       *_strbuf._ptr = 0;
-       return(len);
+       f._flags = __SWR | __SSTR;
+       f._bf._base = f._p = (unsigned char *)str;
+       f._bf._size = f._w = INT_MAX;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       ret = vfprintf(&f, fmt, ap);
+       va_end(ap);
+       *f._p = 0;
+       return (ret);
 }
 }
diff --git a/usr/src/lib/libc/stdio/sscanf.c b/usr/src/lib/libc/stdio/sscanf.c
new file mode 100644 (file)
index 0000000..2879a25
--- /dev/null
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sscanf.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <string.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "local.h"
+
+/* ARGSUSED */
+static int
+eofread(cookie, buf, len)
+       void *cookie;
+       char *buf;
+       int len;
+{
+
+       return (0);
+}
+
+#if __STDC__
+sscanf(char *str, char const *fmt, ...)
+#else
+sscanf(str, fmt, va_alist)
+       char *str;
+       char *fmt;
+       va_dcl
+#endif
+{
+       int ret;
+       va_list ap;
+       FILE f;
+
+       f._flags = __SRD;
+       f._bf._base = f._p = (unsigned char *)str;
+       f._bf._size = f._r = strlen(str);
+       f._read = eofread;
+       f._ub._base = NULL;
+       f._lb._base = NULL;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       ret = __svfscanf(&f, fmt, ap);
+       va_end(ap);
+       return (ret);
+}
index b8f54e5..525fa2c 100644 (file)
@@ -1,10 +1,10 @@
-.\" Copyright (c) 1980 Regents of the University of California.
+.\" Copyright (c) 1990 Regents of the University of California.
 .\" All rights reserved.  The Berkeley software License Agreement
 .\" specifies the terms and conditions for redistribution.
 .\"
 .\" All rights reserved.  The Berkeley software License Agreement
 .\" specifies the terms and conditions for redistribution.
 .\"
-.\"    @(#)stdio.3     6.2 (Berkeley) %G%
+.\"    @(#)stdio.3     6.3 (Berkeley) %G%
 .\"
 .\"
-.TH STDIO 3S ""
+.TH STDIO 3 ""
 .UC 4
 .SH NAME
 stdio \- standard buffered input/output package
 .UC 4
 .SH NAME
 stdio \- standard buffered input/output package
@@ -23,22 +23,14 @@ stdio \- standard buffered input/output package
 .B FILE
 .B *stderr;
 .SH DESCRIPTION
 .B FILE
 .B *stderr;
 .SH DESCRIPTION
-The functions described in section 3S constitute a user-level buffering
-scheme.  The in-line macros
-.I getc
+The functions described here constitute a user-level buffering scheme.
+The in-line macros
+.IR getc (3)
 and
 and
-.IR  putc (3S)
-handle characters quickly.  The higher level routines
-.IR gets ,
-.IR fgets ,
-.IR scanf ,
-.IR fscanf ,
-.IR fread ,
-.IR puts ,
-.IR fputs ,
-.IR printf ,
-.IR fprintf ,
-.IR fwrite
+.IR putc (3)
+handle characters quickly.
+The higher level routines in
+.I stdio
 all use
 .I getc
 and
 all use
 .I getc
 and
@@ -50,9 +42,11 @@ A file with associated buffering is called a
 and is declared to be a pointer to a defined type
 .SM
 .BR FILE .
 and is declared to be a pointer to a defined type
 .SM
 .BR FILE .
-.IR  Fopen (3S)
-creates certain descriptive data for a stream
-and returns a pointer to designate the stream in all further transactions.
+.IR Fopen (3)
+and
+.IR funopen (3)
+create certain descriptive data for a stream
+and return a pointer to designate the stream in all further transactions.
 There are three normally open streams with constant pointers declared in
 the include file and associated with the standard open files:
 .TP 10n
 There are three normally open streams with constant pointers declared in
 the include file and associated with the standard open files:
 .TP 10n
@@ -83,22 +77,63 @@ deal with streams.
 .PP
 Any routine that uses the standard input/output package
 must include the header file
 .PP
 Any routine that uses the standard input/output package
 must include the header file
-.RI < stdio.h >
-of pertinent macro definitions.
-The functions and constants mentioned in sections labeled 3S
+.RI < stdio.h > .
+The constants and functions listed here
 are declared in the include file and need no further declaration.
 are declared in the include file and need no further declaration.
-The constants, and the following `functions' are
-implemented as macros; redeclaration of these names is perilous:
+The following are implemented as macros;
+these names may not be reused
+without first removing their current definitions with
+.BR #undef :
+.IR NULL ,
+.IR BUFSIZ ,
+.IR EOF ,
+.IR FOPEN_MAX ,
+.IR FILENAME_MAX ,
+.IR L_tmpnam ,
+.IR SEEK_SET ,
+.IR SEE_CUR ,
+.IR SEEK_END ,
+.IR TMP_MAX ,
+.IR stdin ,
+.IR stdout ,
+.IR stderr ,
+.IR fropen ,
+.IR fwopen ,
+.IR feof ,
+.IR ferror ,
+.IR clearerr ,
+.IR fileno ,
 .IR getc ,
 .IR getchar ,
 .IR putc ,
 .IR putchar ,
 .IR getc ,
 .IR getchar ,
 .IR putc ,
 .IR putchar ,
+.IR L_cuserid .
+Function versions of the macro functions
 .IR feof ,
 .IR ferror ,
 .IR feof ,
 .IR ferror ,
-.IR fileno .
+.IR clearerr ,
+.IR fileno ,
+.IR getc ,
+.IR getchar ,
+.IR putc ,
+and
+.I putchar
+exist and will be used if the macros definitions are explicitly removed.
+.PP
+Output streams that refer to terminal devices
+are always line buffered by default;
+pending output to such streams is written automatically
+whenever an input stream that refers to a terminal device is read.
+In cases where a large amount of computation is done after printing
+part of a line on an output terminal, it is necessary to
+.IR fflush (3)
+the standard output before going off and computing so that the output
+will appear.
 .SH "SEE ALSO"
 .SH "SEE ALSO"
-open(2), close(2), read(2), write(2), fread(3S), fseek(3S), f*(3S)
-.SH DIAGNOSTICS
+open(2), close(2), read(2), write(2)
+.br
+all of the manuals listed below
+.SH "RETURN VALUE"
 The value
 .SM
 .B EOF
 The value
 .SM
 .B EOF
@@ -114,66 +149,85 @@ pointer designates corrupt or otherwise unintelligible
 .SM
 .B FILE
 data.
 .SM
 .B FILE
 data.
-.PP
-For purposes of efficiency, this implementation of the standard library
-has been changed to line buffer output to a terminal by default and attempts
-to do this transparently by flushing the output whenever a 
-.IR read (2)
-from the standard input is necessary.  This is almost always transparent,
-but may cause confusion or malfunctioning of programs which use
-standard i/o routines but use
-.IR read (2)
-themselves to read from the standard input.
-.PP
-In cases where a large amount of computation is done after printing
-part of a line on an output terminal, it is necessary to
-.IR fflush (3S)
-the standard output before going off and computing so that the output
-will appear.
 .SH BUGS
 The standard buffered functions do not interact well with certain other
 library and system functions, especially \fIvfork\fP and \fIabort\fP.
 .SH "LIST OF FUNCTIONS"
 .sp 2
 .nf
 .SH BUGS
 The standard buffered functions do not interact well with certain other
 library and system functions, especially \fIvfork\fP and \fIabort\fP.
 .SH "LIST OF FUNCTIONS"
 .sp 2
 .nf
-.ta \w'setlinebuf'u+2n +\w'setbuf.3s'u+10n
+.ta \w'setlinebuf'u+2n +\w'setvbuf.3'u+10n
+\fIName\fP     \fIAppears on Page\fP   \fIDescription\fP
+.ta \w'setlinebuf'u+4n +\w'setvbuf.3'u+4n
+.sp 5p
+clearerr       ferror.3        stream status inquiries
+fclose fclose.3        close a stream
+fdopen fopen.3 open a stream
+feof   ferror.3        stream status inquiries
+ferror ferror.3        stream status inquiries
+fflush fflush.3        flush a stream
+fgetc  getc.3  get a character or word from a stream
+fgetline       fgetline.3      get a line from a stream
+fgetpos        fseek.3 reposition a stream
+fgets  fgets.3 get a line from a stream
+fileno ferror.3        stream status inquiries
+fmemopen       fmemopen.3      open a block of memory as a stream
+fopen  fopen.3 open a stream
+fprintf        printf.3        formatted output conversion
+fpurge fpurge.3        discard buffered stream data
+fputc  putc.3  put a character or word to a stream
+fputs  fputs.3 put a line to a stream
+fread  fread.3 stream binary input/output
+freopen        fopen.3 open a stream
+fscanf scanf.3 formatted input conversion
+fseek  fseek.3 reposition a stream
+fsetpos        fseek.3 reposition a stream
+ftell  fseek.3 reposition a stream
+funopen        fopen.3 open a stream
+fwrite fread.3 stream binary input/output
+getc   getc.3  get a character or word from a stream
+getchar        getc.3  get a character or word from a stream
+gets   fgets.3 get a line from a stream
+getw   getc.3  get a character or word from a stream
+printf printf.3        formatted output conversion
+putc   putc.3  put a character or word to a stream
+putchar        putc.3  put a character or word to a stream
+puts   fputs.3 put a line to a stream
+putw   putc.3  put a character or word to a stream
+remove remove.3        remove a file   xxx
+rewind fseek.3 reposition a stream
+scanf  scanf.3 formatted input conversion
+setbuf setvbuf.3       assign buffering to a stream
+setbuffer      setvbuf.3       assign buffering to a stream
+setlinebuf     setvbuf.3       assign buffering to a stream
+setvbuf        setvbuf.3       assign buffering to a stream
+.\" smprintf   printf.3        formatted output conversion
+snprintf       printf.3        formatted output conversion
+sprintf        printf.3        formatted output conversion
+tmpfile        xxx.3   xxx
+tmpnam xxx.3   xxx
+ungetc ungetc.3        push character back into input stream
+vfprintf       printf.3        formatted output conversion
+vprintf        printf.3        formatted output conversion
+.\" vsmprintf  printf.3        formatted output conversion
+vsnprintf      printf.3        formatted output conversion
+vsprintf       printf.3        formatted output conversion
+.fi
+.sp 2
+Although these have nothing to do with `standard I/O',
+the following declarations also appear in
+.RI < stdio.h >
+as required by ANSI X3.159-1989 and IEEE 1003.2 standards:
+.sp
+.nf
+.ta \w'setlinebuf'u+2n +\w'setvbuf.3'u+10n
 \fIName\fP     \fIAppears on Page\fP   \fIDescription\fP
 \fIName\fP     \fIAppears on Page\fP   \fIDescription\fP
-.ta \w'setlinebuf'u+4n +\w'setbuf.3s'u+4n
+.ta \w'setlinebuf'u+4n +\w'setvbuf.3'u+4n
 .sp 5p
 .sp 5p
-clearerr       ferror.3s       stream status inquiries
-fclose fclose.3s       close or flush a stream
-fdopen fopen.3s        open a stream
-feof   ferror.3s       stream status inquiries
-ferror ferror.3s       stream status inquiries
-fflush fclose.3s       close or flush a stream
-fgetc  getc.3s get character or word from stream
-fgets  gets.3s get a string from a stream
-fileno ferror.3s       stream status inquiries
-fopen  fopen.3s        open a stream
-fprintf        printf.3s       formatted output conversion
-fputc  putc.3s put character or word on a stream
-fputs  puts.3s put a string on a stream
-fread  fread.3s        buffered binary input/output
-freopen        fopen.3s        open a stream
-fscanf scanf.3s        formatted input conversion
-fseek  fseek.3s        reposition a stream
-ftell  fseek.3s        reposition a stream
-fwrite fread.3s        buffered binary input/output
-getc   getc.3s get character or word from stream
-getchar        getc.3s get character or word from stream
-gets   gets.3s get a string from a stream
-getw   getc.3s get character or word from stream
-printf printf.3s       formatted output conversion
-putc   putc.3s put character or word on a stream
-putchar        putc.3s put character or word on a stream
-puts   puts.3s put a string on a stream
-putw   putc.3s put character or word on a stream
-rewind fseek.3s        reposition a stream
-scanf  scanf.3s        formatted input conversion
-setbuf setbuf.3s       assign buffering to a stream
-setbuffer      setbuf.3s       assign buffering to a stream
-setlinebuf     setbuf.3s       assign buffering to a stream
-sprintf        printf.3s       formatted output conversion
-sscanf scanf.3s        formatted input conversion
-ungetc ungetc.3s       push character back into input stream
+cuserid        cuserid.3       xxx
+getlogin       getlogin.3      get login name
+pclose popen.3 initiate I/O to/from a process
+perror strerror.3      xxx
+popen  popen.3 initiate I/O to/from a process
+remove remove.3        xxx
+rename rename.2        xxx
 .fi
 .fi
diff --git a/usr/src/lib/libc/stdio/stdio.c b/usr/src/lib/libc/stdio/stdio.c
new file mode 100644 (file)
index 0000000..c70674f
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)stdio.c    5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stdc.h>
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * Small standard I/O/seek/close functions.
+ * These maintain the `known seek offset' for seek optimisation.
+ */
+__sread(cookie, buf, n)
+       void *cookie;
+       char *buf;
+       int n;
+{
+       register FILE *fp = cookie;
+       register int ret;
+       
+       ret = read(fp->_file, buf, n);
+       /* if the read succeeded, update the current offset */
+       if (ret >= 0)
+               fp->_offset += ret;
+       else
+               fp->_flags &= ~__SOFF;  /* paranoia */
+       return (ret);
+}
+
+__swrite(cookie, buf, n)
+       void *cookie;
+       char const *buf;
+       int n;
+{
+       register FILE *fp = cookie;
+
+       if (fp->_flags & __SAPP)
+               (void) lseek(fp->_file, (off_t)0, SEEK_END);
+       fp->_flags &= ~__SOFF;  /* in case FAPPEND mode is set */
+       return (write(fp->_file, buf, n));
+}
+
+fpos_t
+__sseek(cookie, offset, whence)
+       void *cookie;
+       fpos_t offset;
+       int whence;
+{
+       register FILE *fp = cookie;
+       register off_t ret;
+       
+       ret = lseek(fp->_file, (off_t)offset, whence);
+       if (ret == -1L)
+               fp->_flags &= ~__SOFF;
+       else {
+               fp->_flags |= __SOFF;
+               fp->_offset = ret;
+       }
+       return (ret);
+}
+
+__sclose(cookie)
+       void *cookie;
+{
+
+       return (close(((FILE *)cookie)->_file));
+}
diff --git a/usr/src/lib/libc/stdio/tmpfile.c b/usr/src/lib/libc/stdio/tmpfile.c
new file mode 100644 (file)
index 0000000..be82915
--- /dev/null
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpfile.c  5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <errno.h>
+
+FILE *
+tmpfile()
+{
+       FILE *fp;
+       int e;
+       char *f, buf[MAXPATHLEN];
+
+       if ((f = tmpnam(buf)) == NULL)
+               return (NULL);
+       fp = fopen(f, "w+");
+       e = errno;
+       (void) unlink(f);
+       errno = e;
+       return (fp);
+}
diff --git a/usr/src/lib/libc/stdio/tmpnam.c b/usr/src/lib/libc/stdio/tmpnam.c
new file mode 100644 (file)
index 0000000..a9a1369
--- /dev/null
@@ -0,0 +1,29 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpnam.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <stdio.h>
+
+char *
+tmpnam(s)
+       char *s;
+{
+       static char buf[MAXPATHLEN];
+       char *mktemp();
+
+       if (s == NULL)
+               s = buf;
+       (void) sprintf(s, "%s/XXXXXX", P_tmpdir);
+       return (mktemp(s));
+}
index 1ba3820..690ecc9 100644 (file)
@@ -1,41 +1,55 @@
-.\"    @(#)ungetc.3    6.2 (Berkeley) %G%
+.\" Copyright (c) 1990 The Regents of the University of California.
+.\" All rights reserved.
 .\"
 .\"
-.TH UNGETC 3  ""
-.AT 3
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\"
+.\" %sccs.include.redist.man%
+.\"
+.\"    @(#)ungetc.3    6.3 (Berkeley) %G%
+.\"
+.TH UNGETC 3 ""
+.UC 7
 .SH NAME
 ungetc \- push character back into input stream
 .SH SYNOPSIS
 .SH NAME
 ungetc \- push character back into input stream
 .SH SYNOPSIS
-.B #include <stdio.h>
-.PP
-.B ungetc(c, stream)
-.br
-.SM
-.B FILE
-.B *stream;
+.nf
+.ft B
+#include <stdio.h>
+
+int
+ungetc(int c, FILE *stream);
+.fr R
+.fi
 .SH DESCRIPTION
 .I Ungetc
 .SH DESCRIPTION
 .I Ungetc
-pushes the character
+pushes the integer
 .I c
 .I c
-back on an input stream.  That character will be returned by the next
+(converted to an ``unsigned char'') back on an input stream, so that
+the next
 .I getc
 .I getc
-call on that stream.
+call on that stream will return
+.IR c .
 .I Ungetc 
 returns 
 .IR c .
 .PP
 .I Ungetc 
 returns 
 .IR c .
 .PP
-One character of pushback is guaranteed provided
-something has been read from the stream and the stream is actually buffered.
-Attempts to push EOF are rejected.
+One character of pushback is always guaranteed, but as long as there is
+sufficient memory, an effectively infinite amount of pushback is allowed.
+Attempts to push
+.B EOF
+are rejected.
 .PP
 .PP
-.IR  Fseek (3)
+A successful call to
+.I fseek
 erases all memory of pushed back characters.
 .SH "SEE ALSO"
 erases all memory of pushed back characters.
 .SH "SEE ALSO"
-getc(3),
-setbuf(3),
-fseek(3)
-.SH DIAGNOSTICS
+getc(3), fseek(3), setvbuf(3)
+.SH "RETURN VALUE"
 .I Ungetc
 returns
 .SM
 .B EOF
 .I Ungetc
 returns
 .SM
 .B EOF
-if it can't push a character back.
+if it cannot push back the given character for any reason
+(this includes attempts to push
+.BR EOF ).
index b691d58..91864b8 100644 (file)
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
 #if defined(LIBC_SCCS) && !defined(lint)
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)ungetc.c   5.3 (Berkeley) %G%";
-#endif LIBC_SCCS and not lint
+static char sccsid[] = "@(#)ungetc.c   5.4 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+
+/*
+ * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
+ * the buffer moves, so that it points the same distance from the end,
+ * and move the bytes in the buffer around as necessary so that they
+ * are all at the end (stack-style).
+ */
+static
+__submore(fp)
+       register FILE *fp;
+{
+       register int i;
+       register unsigned char *p;
+
+       if (fp->_ub._base == fp->_ubuf) {
+               /*
+                * Get a new buffer (rather than expanding the old one).
+                */
+               if ((p = malloc((size_t)BUFSIZ)) == NULL)
+                       return (EOF);
+               fp->_ub._base = p;
+               fp->_ub._size = BUFSIZ;
+               p += BUFSIZ - sizeof(fp->_ubuf);
+               for (i = sizeof(fp->_ubuf); --i >= 0;)
+                       p[i] = fp->_ubuf[i];
+               fp->_p = p;
+               return (0);
+       }
+       i = fp->_ub._size;
+       p = realloc(fp->_ub._base, i << 1);
+       if (p == NULL)
+               return (EOF);
+       (void) memcpy((void *)(p + i), (void *)p, (size_t)i);
+       fp->_p = p + i;
+       fp->_ub._base = p;
+       fp->_ub._size = i << 1;
+       return (0);
+}
 
 
-ungetc(c, iop)
-       register FILE *iop;
+ungetc(c, fp)
+       int c;
+       register FILE *fp;
 {
 {
-       if (c == EOF || (iop->_flag & (_IOREAD|_IORW)) == 0 ||
-           iop->_ptr == NULL || iop->_base == NULL)
+       if (c == EOF)
                return (EOF);
                return (EOF);
+       if (!__sdidinit)
+               __sinit();
+       if ((fp->_flags & __SRD) == 0) {
+               /*
+                * Not already reading: no good unless reading-and-writing.
+                * Otherwise, flush any current write stuff.
+                */
+               if ((fp->_flags & __SRW) == 0)
+                       return (EOF);
+               if (fp->_flags & __SWR) {
+                       if (fflush(fp))
+                               return (EOF);
+                       fp->_flags &= ~__SWR;
+                       fp->_w = 0;
+                       fp->_lbfsize = 0;
+               }
+               fp->_flags |= __SRD;
+       }
+       c = (unsigned char)c;
 
 
-       if (iop->_ptr == iop->_base)
-               if (iop->_cnt == 0)
-                       iop->_ptr++;
-               else
+       /*
+        * If we are in the middle of ungetc'ing, just continue.
+        * This may require expanding the current ungetc buffer.
+        */
+       if (HASUB(fp)) {
+               if (fp->_r >= fp->_ub._size && __submore(fp))
                        return (EOF);
                        return (EOF);
+               *--fp->_p = c;
+               fp->_r++;
+               return (c);
+       }
 
 
-       iop->_cnt++;
-       *--iop->_ptr = c;
+       /*
+        * If we can handle this by simply backing up, do so,
+        * but never replace the original character.
+        * (This makes sscanf() work when scanning `const' data.)
+        */
+       if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
+           fp->_p[-1] == c) {
+               fp->_p--;
+               fp->_r++;
+               return (c);
+       }
 
 
+       /*
+        * Create an ungetc buffer.
+        * Initially, we will use the `reserve' buffer.
+        */
+       fp->_ur = fp->_r;
+       fp->_up = fp->_p;
+       fp->_ub._base = fp->_ubuf;
+       fp->_ub._size = sizeof(fp->_ubuf);
+       fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
+       fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
+       fp->_r = 1;
        return (c);
 }
        return (c);
 }
index 44e53c4..d26e055 100644 (file)
@@ -1,24 +1,23 @@
-/*
- * Copyright (c) 1988 Regents of the University of California.
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * All rights reserved.
  *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
  * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)vprintf.c  5.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)vprintf.c  5.4 (Berkeley) %G%";
 #endif /* LIBC_SCCS and not lint */
 
 #endif /* LIBC_SCCS and not lint */
 
+#include <sys/stdc.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <varargs.h>
 
 
-int
 vprintf(fmt, ap)
 vprintf(fmt, ap)
-       char *fmt;
-       va_list ap;
+       char const *fmt;
+       _VA_LIST_ ap;
 {
 {
-       int len;
-
-       len = _doprnt(fmt, ap, stdout);
-       return (ferror(stdout) ? EOF : len);
+       return (vfprintf(stdout, fmt, ap));
 }
 }
diff --git a/usr/src/lib/libc/stdio/vsnprintf.c b/usr/src/lib/libc/stdio/vsnprintf.c
new file mode 100644 (file)
index 0000000..8492da4
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vsnprintf.c        5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+vsnprintf(str, n, fmt, ap)
+       char *str;
+       size_t n;
+       char *fmt;
+       _VA_LIST_ ap;
+{
+       int ret;
+       FILE f;
+
+       if ((int)n < 1)
+               return (EOF);
+       f._flags = __SWR | __SSTR;
+       f._bf._base = f._p = (unsigned char *)str;
+       f._bf._size = f._w = n - 1;
+       ret = vfprintf(&f, fmt, ap);
+       *f._p = 0;
+       return (ret);
+}
index 1ef89e0..c2c23f3 100644 (file)
@@ -1,29 +1,32 @@
-/*
- * Copyright (c) 1988 Regents of the University of California.
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * All rights reserved.
  *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
  * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  * %sccs.include.redist.c%
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)vsprintf.c 5.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)vsprintf.c 5.4 (Berkeley) %G%";
 #endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
 #endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
-#include <varargs.h>
+#include <limits.h>
 
 
-int
 vsprintf(str, fmt, ap)
 vsprintf(str, fmt, ap)
-       char *str, *fmt;
-       va_list ap;
+       char *str;
+       char *fmt;
+       _VA_LIST_ ap;
 {
 {
+       int ret;
        FILE f;
        FILE f;
-       int len;
 
 
-       f._flag = _IOWRT+_IOSTRG;
-       f._ptr = str;
-       f._cnt = 32767;
-       len = _doprnt(fmt, ap, &f);
-       *f._ptr = 0;
-       return (len);
+       f._flags = __SWR | __SSTR;
+       f._bf._base = f._p = (unsigned char *)str;
+       f._bf._size = f._w = INT_MAX;
+       ret = vfprintf(&f, fmt, ap);
+       *f._p = 0;
+       return (ret);
 }
 }
diff --git a/usr/src/lib/libc/stdio/wsetup.c b/usr/src/lib/libc/stdio/wsetup.c
new file mode 100644 (file)
index 0000000..e817481
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)wsetup.c   5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * Various output routines call wsetup to be sure it is safe to write,
+ * because either _flags does not include __SWR, or _buf is NULL.
+ * _wsetup returns 0 if OK to write, nonzero otherwise.
+ */
+__swsetup(fp)
+       register FILE *fp;
+{
+       /* make sure stdio is set up */
+       if (!__sdidinit)
+               __sinit();
+
+       /*
+        * If we are not writing, we had better be reading and writing.
+        */
+       if ((fp->_flags & __SWR) == 0) {
+               if ((fp->_flags & __SRW) == 0)
+                       return (EOF);
+               if (fp->_flags & __SRD) {
+                       /* clobber any ungetc data */
+                       if (HASUB(fp))
+                               FREEUB(fp);
+                       fp->_flags &= ~(__SRD|__SEOF);
+                       fp->_r = 0;
+                       fp->_p = fp->_bf._base;
+               }
+               fp->_flags |= __SWR;
+       }
+
+       /*
+        * Make a buffer if necessary, then set _w.
+        */
+       if (fp->_bf._base == NULL)
+               __smakebuf(fp);
+       if (fp->_flags & __SLBF) {
+               /*
+                * It is line buffered, so make _lbfsize be -_bufsize
+                * for the putc() macro.  We will change _lbfsize back
+                * to 0 whenever we turn off __SWR.
+                */
+               fp->_w = 0;
+               fp->_lbfsize = -fp->_bf._size;
+       } else
+               fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size;
+       return (0);
+}