Initial revision
authoreck <none@none>
Mon, 18 Dec 1989 14:40:54 +0000 (14:40 +0000)
committereck <none@none>
Mon, 18 Dec 1989 14:40:54 +0000 (14:40 +0000)
20 files changed:
lang/cem/libcc.ansi/misc/.distr [new file with mode: 0644]
lang/cem/libcc.ansi/misc/LIST [new file with mode: 0644]
lang/cem/libcc.ansi/misc/Makefile [new file with mode: 0644]
lang/cem/libcc.ansi/misc/closedir.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/fdopen.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/getdents.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/getgrent.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/getopt.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/getpass.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/getpw.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/getw.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/opendir.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/popen.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/putw.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/readdir.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/rewinddir.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/seekdir.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/sleep.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/telldir.c [new file with mode: 0644]
lang/cem/libcc.ansi/misc/termcap.c [new file with mode: 0644]

diff --git a/lang/cem/libcc.ansi/misc/.distr b/lang/cem/libcc.ansi/misc/.distr
new file mode 100644 (file)
index 0000000..afac124
--- /dev/null
@@ -0,0 +1,19 @@
+LIST
+Makefile
+closedir.c
+fdopen.c
+getdents.c
+getgrent.c
+getopt.c
+getpass.c
+getpw.c
+getw.c
+opendir.c
+popen.c
+putw.c
+readdir.c
+rewinddir.c
+seekdir.c
+sleep.c
+telldir.c
+termcap.c
diff --git a/lang/cem/libcc.ansi/misc/LIST b/lang/cem/libcc.ansi/misc/LIST
new file mode 100644 (file)
index 0000000..ab676f0
--- /dev/null
@@ -0,0 +1,17 @@
+getgrent.c
+getopt.c
+getpass.c
+getpw.c
+getw.c
+putw.c
+popen.c
+sleep.c
+termcap.c
+fdopen.c
+closedir.c
+getdents.c
+opendir.c
+readdir.c
+rewinddir.c
+seekdir.c
+telldir.c
diff --git a/lang/cem/libcc.ansi/misc/Makefile b/lang/cem/libcc.ansi/misc/Makefile
new file mode 100644 (file)
index 0000000..a94ae10
--- /dev/null
@@ -0,0 +1,29 @@
+CFLAGS=-L -LIB -DNFS
+
+.SUFFIXES: .o .e .c
+
+.e.o:
+       $(CC) $(CFLAGS) -c -o $@ $*.e
+
+clean:
+       rm -rf getgrent.o getopt.o getpass.o getpw.o getw.o putw.o \
+               popen.o sleep.o termcap.o fdopen.o closedir.o getdents.o \
+               opendir.o readdir.o rewinddir.o seekdir.o telldir.o OLIST
+
+getgrent.o:
+getopt.o:
+getpass.o:
+getpw.o:
+getw.o:
+putw.o:
+popen.o:
+sleep.o:
+termcap.o:
+fdopen.o:
+closedir.o:
+getdents.o:
+opendir.o:
+readdir.o:
+rewinddir.o:
+seekdir.o:
+telldir.o:
diff --git a/lang/cem/libcc.ansi/misc/closedir.c b/lang/cem/libcc.ansi/misc/closedir.c
new file mode 100644 (file)
index 0000000..c6cad9c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+       closedir -- close a directory stream
+
+       last edit:      11-Nov-1988     D A Gwyn
+*/
+
+#include       <errno.h>
+#include       <stdlib.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#include       <dirent.h>
+
+typedef void   *pointer;               /* (void *) if you have it */
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+int close(int d);
+
+int
+closedir(register DIR *dirp)           /* stream from opendir */
+{
+       register int    fd;
+
+       if ( dirp == NULL || dirp->dd_buf == NULL )
+               {
+               errno = EFAULT;
+               return -1;              /* invalid pointer */
+               }
+
+       fd = dirp->dd_fd;               /* bug fix thanks to R. Salz */
+       free( (pointer)dirp->dd_buf );
+       free( (pointer)dirp );
+       return close( fd );
+}
diff --git a/lang/cem/libcc.ansi/misc/fdopen.c b/lang/cem/libcc.ansi/misc/fdopen.c
new file mode 100644 (file)
index 0000000..7a928d6
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * fdopen - convert a (UNIX) file descriptor into a FILE pointer
+ */
+/* $Header$ */
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       "../stdio/loc_incl.h"
+
+int lseek(int d, int offset, int whence);
+
+FILE *
+fdopen(int fd, const char *mode)
+{
+       register int i;
+       FILE *stream;
+       int flags = 0;
+
+       if (fd < 0) return (FILE *)NULL;
+       for (i = 0; __iotab[i] != 0 ; i++) 
+               if (i >= FOPEN_MAX)
+                       return (FILE *)NULL;
+
+       switch(*mode++) {
+       case 'r':
+               flags |= _IOREAD | _IOREADING;
+               break;
+       case 'a':
+               flags |= _IOAPPEND;
+       case 'w':
+               flags |= _IOWRITE | _IOWRITING;
+               break;
+       default:
+               return (FILE *)NULL;
+       }
+       while(*mode) {
+               switch(*mode++) {
+               case 'b':
+                       break;
+               case '+':
+                       flags |= _IOREAD | _IOWRITE;
+                       break;
+               default:
+                       return (FILE *)NULL;
+               }
+       }
+
+       if ((stream = (FILE *) malloc(sizeof(FILE))) == NULL) {
+               return (FILE *)NULL;
+       }
+
+       if ((flags & _IOREAD) && (flags & _IOWRITE))
+               flags &= ~(_IOREADING | _IOWRITING);
+
+       stream->_count = 0;
+       stream->_fd = fd;
+       stream->_flags = flags;
+       stream->_buf = NULL;
+       __iotab[i] = stream;
+       return stream;
+}
diff --git a/lang/cem/libcc.ansi/misc/getdents.c b/lang/cem/libcc.ansi/misc/getdents.c
new file mode 100644 (file)
index 0000000..2fc7ccd
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+       getdents -- get directory entries in a file system independent format
+                       (SVR3 system call emulation)
+
+       last edit:      06-Jul-1987     D A Gwyn
+
+       This single source file supports several different methods of
+       getting directory entries from the operating system.  Define
+       whichever one of the following describes your system:
+
+       UFS     original UNIX filesystem (14-character name limit)
+       BFS     4.2BSD (also 4.3BSD) native filesystem (long names)
+       NFS     getdirentries() system call
+
+       Also define any of the following that are pertinent:
+
+       ATT_SPEC        check user buffer address for longword alignment
+       BSD_SYSV        BRL UNIX System V emulation environment on 4.nBSD
+       UNK             have _getdents() system call, but kernel may not
+                       support it
+
+       If your C library has a getdents() system call interface, but you
+       can't count on all kernels on which your application binaries may
+       run to support it, change the system call interface name to
+       _getdents() and define "UNK" to enable the system-call validity
+       test in this "wrapper" around _getdents().
+
+       If your system has a getdents() system call that is guaranteed 
+       to always work, you shouldn't be using this source file at all.
+*/
+
+#include       <errno.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#ifdef BSD_SYSV
+#include       <sys/_dir.h>            /* BSD flavor, not System V */
+#else
+#if    defined(UFS)
+#define        DIRSIZ          14              /* 14 char filename in Version 7 */
+#endif
+#define        MAXNAMLEN       255
+struct  direct {
+       off_t   d_off;                  /* offset of next disk directory entry */
+       u_long  d_fileno;               /* file number of entry */
+       u_short d_reclen;               /* length of this record */
+       u_short d_namlen;               /* length of string in d_name */
+       char    d_name[MAXNAMLEN + 1];  /* name (up to MAXNAMLEN + 1) */
+};
+#undef MAXNAMLEN                       /* avoid conflict with SVR3 */
+
+#define        d_ino   d_fileno                /* compatability */
+
+#ifdef d_ino                           /* 4.3BSD/NFS using d_fileno */
+#undef d_ino                           /* (not absolutely necessary) */
+#else
+#define        d_fileno        d_ino           /* (struct direct) member */
+#endif
+#endif
+#include       <sys/dirent.h>
+#include       <sys/stat.h>
+#ifdef UNK
+#ifndef UFS
+#error UNK applies only to UFS
+/* One could do something similar for getdirentries(), but I didn't bother. */
+#endif
+#include       <signal.h>
+#endif
+
+#if defined(UFS) + defined(BFS) + defined(NFS) != 1    /* sanity check */
+#error exactly one of UFS, BFS, or NFS must be defined
+#endif
+
+#ifdef UFS
+#define        RecLen( dp )    (sizeof(struct direct)) /* fixed-length entries */
+#else  /* BFS || NFS */
+#define        RecLen( dp )    ((dp)->d_reclen)        /* variable-length entries */
+#endif
+
+#ifdef NFS
+#ifdef BSD_SYSV
+#define        getdirentries   _getdirentries  /* package hides this system call */
+#endif
+extern int     getdirentries(int fd, char *buf, int nbytes, long *basep);
+static long    dummy;                  /* getdirentries() needs basep */
+#define        GetBlock( fd, buf, n )  getdirentries( fd, buf, (unsigned)n, &dummy )
+#else  /* UFS || BFS */
+#ifdef BSD_SYSV
+#define read   _read                   /* avoid emulation overhead */
+#endif
+extern int     read();
+#define        GetBlock( fd, buf, n )  read( fd, buf, (unsigned)n )
+#endif
+
+#ifdef UNK
+extern int     _getdents();            /* actual system call */
+#endif
+
+extern int     fstat(int fd, struct stat *buf);
+extern off_t   lseek(int d, int offset, int whence);
+
+#ifndef DIRBLKSIZ
+#define        DIRBLKSIZ       4096            /* directory file read buffer size */
+#endif
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#ifndef SEEK_CUR
+#define        SEEK_CUR        1
+#endif
+
+#ifndef S_ISDIR                                /* macro to test for directory file */
+#define        S_ISDIR( mode )         (((mode) & S_IFMT) == S_IFDIR)
+#endif
+
+#ifdef UFS
+
+/*
+       The following routine is necessary to handle DIRSIZ-long entry names.
+       Thanks to Richard Todd for pointing this out.
+*/
+
+static int
+NameLen( char name[] )                         /* return # chars in embedded name */
+               /* -> name embedded in struct direct */
+{
+       register char   *s;             /* -> name[.] */
+       register char   *stop = &name[DIRSIZ];  /* -> past end of name field */
+
+       for ( s = &name[1];             /* (empty names are impossible) */
+             *s != '\0'                /* not NUL terminator */
+          && ++s < stop;               /* < DIRSIZ characters scanned */
+           )
+               ;
+
+       return s - name;                /* # valid characters in name */
+}
+
+#else  /* BFS || NFS */
+
+#define        NameLen( name ) strlen( name )  /* names are always NUL-terminated */
+
+#endif
+
+#ifdef UNK
+static enum    { maybe, no, yes }      state = maybe;
+                                       /* does _getdents() work? */
+
+/*ARGSUSED*/
+static void
+sig_catch(int sig)                     /* sig must be SIGSYS */
+{
+       state = no;                     /* attempted _getdents() faulted */
+}
+#endif
+
+int
+getdents(int fildes, char *buf, unsigned nbyte)        /* returns # bytes read;
+                                                   0 on EOF, -1 on error */
+/* fildes == directory file descriptor */
+/* *buf == where to put the (struct dirent)s */
+/* nbyte == size of buf[] */
+{
+       int                     serrno; /* entry errno */
+       off_t                   offset; /* initial directory file offset */
+       struct stat             statb;  /* fstat() info */
+       union   {
+               char            dblk[DIRBLKSIZ];
+                                       /* directory file block buffer */
+               struct direct   dummy;  /* just for alignment */
+               }       u;              /* (avoids having to malloc()) */
+       register struct direct  *dp;    /* -> u.dblk[.] */
+       register struct dirent  *bp;    /* -> buf[.] */
+
+#ifdef UNK
+       switch ( state )
+               {
+               void            (*shdlr)();     /* entry SIGSYS handler */
+               register int    retval; /* return from _getdents() if any */
+
+       case yes:                       /* _getdents() is known to work */
+               return _getdents( fildes, buf, nbyte );
+
+       case maybe:                     /* first time only */
+               shdlr = signal( SIGSYS, sig_catch );
+               retval = _getdents( fildes, buf, nbyte );       /* try it */
+               (void)signal( SIGSYS, shdlr );
+
+               if ( state == maybe )   /* SIGSYS did not occur */
+                       {
+                       state = yes;    /* so _getdents() must have worked */
+                       return retval;
+                       }
+               /* else fall through into emulation */
+
+/*     case no:        /* fall through into emulation */
+               }
+#endif
+
+       if ( buf == NULL
+#ifdef ATT_SPEC
+         || (unsigned long)buf % sizeof(long) != 0     /* ugh */
+#endif
+          )    {
+               errno = EFAULT;         /* invalid pointer */
+               return -1;
+               }
+
+       if ( fstat( fildes, &statb ) != 0 )
+               return -1;              /* errno set by fstat() */
+
+       if ( !S_ISDIR( statb.st_mode ) )
+               {
+               errno = ENOTDIR;        /* not a directory */
+               return -1;
+               }
+
+       if ( (offset = lseek( fildes, (off_t)0, SEEK_CUR )) < 0 )
+               return -1;              /* errno set by lseek() */
+
+#ifdef BFS                             /* no telling what remote hosts do */
+       if ( (unsigned long)offset % DIRBLKSIZ != 0 )
+               {
+               errno = ENOENT;         /* file pointer probably misaligned */
+               return -1;
+               }
+#endif
+
+       serrno = errno;                 /* save entry errno */
+
+       for ( bp = (struct dirent *)buf; bp == (struct dirent *)buf; )
+               {                       /* convert next directory block */
+               int     size;
+
+               do      size = GetBlock( fildes, u.dblk, DIRBLKSIZ );
+               while ( size == -1 && errno == EINTR );
+
+               if ( size <= 0 )
+                       return size;    /* EOF or error (EBADF) */
+
+               for ( dp = (struct direct *)u.dblk;
+                     (char *)dp < &u.dblk[size];
+                     dp = (struct direct *)((char *)dp + RecLen( dp ))
+                   )   {
+#ifndef UFS
+                       if ( dp->d_reclen <= 0 )
+                               {
+                               errno = EIO;    /* corrupted directory */
+                               return -1;
+                               }
+#endif
+
+                       if ( dp->d_fileno != 0 )
+                               {       /* non-empty; copy to user buffer */
+                               register int    reclen =
+                                       DIRENTSIZ( NameLen( dp->d_name ) );
+
+                               if ( (char *)bp + reclen > &buf[nbyte] )
+                                       {
+                                       errno = EINVAL;
+                                       return -1;      /* buf too small */
+                                       }
+
+                               bp->d_ino = dp->d_fileno;
+                               bp->d_off = offset + ((char *)dp - u.dblk);
+                               bp->d_reclen = reclen;
+                               (void)strncpy( bp->d_name, dp->d_name,
+                                              reclen - DIRENTBASESIZ
+                                            ); /* adds NUL padding */
+
+                               bp = (struct dirent *)((char *)bp + reclen);
+                               }
+                       }
+
+#ifndef BFS    /* 4.2BSD screwed up; fixed in 4.3BSD */
+               if ( (char *)dp > &u.dblk[size] )
+                       {
+                       errno = EIO;    /* corrupted directory */
+                       return -1;
+                       }
+#endif
+               }
+
+       errno = serrno;                 /* restore entry errno */
+       return (char *)bp - buf;        /* return # bytes read */
+}
diff --git a/lang/cem/libcc.ansi/misc/getgrent.c b/lang/cem/libcc.ansi/misc/getgrent.c
new file mode 100644 (file)
index 0000000..247479f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * getgrent - get entry form group file
+ *
+ * Author: Patrick van Kleef
+ */
+/* $Header$ */
+
+#include       <stdlib.h>
+#include       <string.h>
+#include       <grp.h>
+
+#define        O_RDONLY        0
+
+int open(const char *path, int flags);
+
+#if   defined(__BSD4_2)
+typedef int off_t;                              /* see lseek(2) */
+#else
+typedef long off_t;
+#endif
+
+off_t lseek(int d, off_t offset, int whence);
+int read(int d, char *buf, int nbytes);
+int close(int d);
+
+#define        RBUFSIZE        1024
+static char _gr_file[] = "/etc/group";
+static char _grbuf[256];
+static char _buffer[RBUFSIZE];
+static char *_pnt;
+static char *_buf;
+static int  _gfd = -1;
+static int  _bufcnt;
+static struct group grp;
+
+int
+setgrent(void)
+{
+        if (_gfd >= 0)
+               lseek(_gfd, 0L, 0);
+        else
+               _gfd = open(_gr_file, O_RDONLY);
+
+        _bufcnt = 0;
+        return _gfd;
+}
+
+int
+endgrent(void) 
+{
+        if (_gfd >= 0)
+               close(_gfd);
+
+        _gfd = -1;
+        _bufcnt = 0;
+}
+
+
+static int
+getline(void) 
+{
+        if (_gfd < 0 && setgrent() < 0)
+               return 0;
+
+        _buf = _grbuf;
+        do {
+               if (--_bufcnt <= 0){
+                       if ((_bufcnt = read(_gfd, _buffer, RBUFSIZE)) <= 0)
+                               return 0;
+                       else
+                               _pnt = _buffer;
+               }
+               *_buf++ = *_pnt++;
+        } while (*_pnt != '\n');
+        _pnt++;
+        _bufcnt--;
+        *_buf = 0;
+        _buf = _grbuf;
+        return 1;
+}
+
+static int
+skip_period(void) 
+{
+        while (*_buf && *_buf != ':')
+               _buf++;
+        *_buf++ = '\0';
+}
+
+struct group *
+getgrent(void) 
+{
+        if (getline() == 0)
+               return 0;
+
+        grp.gr_name = _buf;
+        skip_period();
+        grp.gr_passwd = _buf;
+        skip_period();
+        grp.gr_gid = atoi(_buf);
+        skip_period();
+        return &grp;
+}
+
+struct group *
+getgrnam(const char *name)
+{
+        struct group *grp;
+
+        setgrent();
+        while ((grp = getgrent()) != 0)
+               if (!strcmp(grp -> gr_name, name))
+                       break;
+        endgrent();
+        if (grp != 0)
+               return grp;
+        else
+               return 0;
+}
+
+struct group *
+getgrgid(int gid)
+{
+        struct group   *grp;
+
+        setgrent();
+        while ((grp = getgrent()) != 0)
+               if (grp -> gr_gid == gid)
+                       break;
+        endgrent();
+        if (grp != 0)
+               return grp;
+        else
+               return 0;
+}
diff --git a/lang/cem/libcc.ansi/misc/getopt.c b/lang/cem/libcc.ansi/misc/getopt.c
new file mode 100644 (file)
index 0000000..55d843c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * getopt - parse command-line options
+ */
+/* $Header$ */
+
+#include       <stdio.h>
+#include       <string.h>
+
+#define ERR(s, c)       if(opterr){\
+       fputs(argv[0], stderr);\
+       fputs(s, stderr);\
+       fputc(c, stderr);\
+       fputc('\n', stderr);}
+
+int     opterr = 1;
+int     optind = 1;
+int    optopt;
+char    *optarg;
+
+int
+getopt(int argc, char **argv, char *opts)
+{
+       static int sp = 1;
+       register c;
+       register char *cp;
+
+       if (sp == 1)
+               if (optind >= argc ||
+                  argv[optind][0] != '-' || argv[optind][1] == '\0')
+                       return EOF;
+               else if (!strcmp(argv[optind], "--")) {
+                       optind++;
+                       return EOF;
+               }
+       optopt = c = argv[optind][sp];
+       if (c == ':' || (cp=strchr(opts, c)) == NULL) {
+               ERR (": illegal option -- ", c);
+               if (argv[optind][++sp] == '\0') {
+                       optind++;
+                       sp = 1;
+               }
+               return '?';
+       }
+       if (*++cp == ':') {
+               if (argv[optind][sp+1] != '\0')
+                       optarg = &argv[optind++][sp+1];
+               else if (++optind >= argc) {
+                       ERR (": option requires an argument -- ", c);
+                       sp = 1;
+                       return '?';
+               } else
+                       optarg = argv[optind++];
+               sp = 1;
+       } else {
+               if (argv[optind][++sp] == '\0') {
+                       sp = 1;
+                       optind++;
+               }
+               optarg = NULL;
+       }
+       return c;
+}
diff --git a/lang/cem/libcc.ansi/misc/getpass.c b/lang/cem/libcc.ansi/misc/getpass.c
new file mode 100644 (file)
index 0000000..e1a535b
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * getpass - ask for a password
+ */
+/* $Header$ */
+
+#include       <signal.h>
+#include       <string.h>
+#include       <sgtty.h>
+
+#define        O_RDONLY        0
+int open(const char *path, int flags);
+int write(int d, const char *buf, int nbytes);
+int read(int d, char *buf, int nbytes);
+int close(int d);
+
+int stty(int, struct sgttyb *);
+int gtty(int, struct sgttyb *);
+
+char *
+getpass(const char *prompt)
+{
+       int i = 0;
+       struct sgttyb tty, ttysave;
+       static char pwdbuf[9];
+       int fd;
+       void (*savesig)(int);
+
+       if ((fd = open("/dev/tty", O_RDONLY)) < 0) fd = 0;
+       savesig = signal(SIGINT, SIG_IGN);
+       write(2, prompt, strlen(prompt));
+       gtty(fd, &tty);
+       ttysave = tty;
+       tty.sg_flags &= ~ECHO;
+       stty(fd, &tty);
+       i = read(fd, pwdbuf, 9);
+       while (pwdbuf[i - 1] != '\n')
+               read(fd, &pwdbuf[i - 1], 1);
+       pwdbuf[i - 1] = '\0';
+       stty(fd, &ttysave);
+       write(2, "\n", 1);
+       if (fd != 0) close(fd);
+       signal(SIGINT, savesig);
+       return(pwdbuf);
+}
diff --git a/lang/cem/libcc.ansi/misc/getpw.c b/lang/cem/libcc.ansi/misc/getpw.c
new file mode 100644 (file)
index 0000000..bbd9c39
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * getpw - get a password from the password file
+ */
+/* $Header$ */
+
+#include       <stdio.h>
+
+getpw(int uid, char buf[])
+{
+       register FILE *pwf;
+       register int ch, i;
+       register char *bp;
+
+       pwf = fopen("/etc/passwd", "r");
+       if (pwf == NULL) return(1);
+
+       for (;;) {
+               bp = buf;
+               while ((ch = getc(pwf)) != '\n') {
+                       if (ch == EOF) return 1;
+                       *bp++ = ch;
+               }
+               *bp++ = '\0';
+               bp = buf;
+               for (i = 2; i; i--) {
+                       while ((ch = *bp++) != ':') {
+                               if(ch = '\0') return 1;
+                       }
+               }
+               i = 0;
+               while ((ch = *bp++) != ':') {
+                       if (ch < '0' || ch > '9') return 1;
+                       i = i * 10 + (ch - '0');
+               }
+               if (i == uid) return(0);
+       }
+       /*NOTREACHED*/
+}
diff --git a/lang/cem/libcc.ansi/misc/getw.c b/lang/cem/libcc.ansi/misc/getw.c
new file mode 100644 (file)
index 0000000..68a7978
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * getw - read a word from a stream
+ */
+/* $Header$ */
+
+#include       <stdio.h>
+
+int getw(register FILE *stream)
+{
+       register int cnt = sizeof(int);
+       int w;
+       register char *p = (char *) &w;
+
+       while (cnt--) {
+               *p++ = getc(stream);
+       }
+       if (feof(stream) || ferror(stream)) return EOF;
+       return w;
+}
diff --git a/lang/cem/libcc.ansi/misc/opendir.c b/lang/cem/libcc.ansi/misc/opendir.c
new file mode 100644 (file)
index 0000000..7386b60
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+       opendir -- open a directory stream
+
+       last edit:      16-Jun-1987     D A Gwyn
+*/
+
+#include       <errno.h>
+#include       <stdlib.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#include       <sys/stat.h>
+#include       <dirent.h>
+
+#ifdef BSD_SYSV
+#define open   _open                   /* avoid emulation overhead */
+#endif
+
+typedef void   *pointer;               /* (void *) if you have it */
+
+extern int open(const char *path, int flags, int mode);
+extern int close(int d);
+extern int fstat(int fd, struct stat *buf);
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#ifndef O_RDONLY
+#define        O_RDONLY        0
+#endif
+
+#ifndef S_ISDIR                                /* macro to test for directory file */
+#define        S_ISDIR( mode )         (((mode) & S_IFMT) == S_IFDIR)
+#endif
+
+DIR *
+opendir(const char *dirname)           /* name of directory */
+{
+       register DIR    *dirp;          /* -> malloc'ed storage */
+       register int    fd;             /* file descriptor for read */
+       struct stat     sbuf;           /* result of fstat() */
+
+       if ( (fd = open( dirname, O_RDONLY, 0 )) < 0 )
+               return NULL;            /* errno set by open() */
+
+       if ( fstat( fd, &sbuf ) != 0 || !S_ISDIR( sbuf.st_mode ) )
+               {
+               (void)close( fd );
+               errno = ENOTDIR;
+               return NULL;            /* not a directory */
+               }
+
+       if ( (dirp = (DIR *)malloc( sizeof(DIR) )) == NULL
+         || (dirp->dd_buf = (char *)malloc( (unsigned)DIRBUF )) == NULL
+          )    {
+               register int    serrno = errno;
+                                       /* errno set to ENOMEM by sbrk() */
+
+               if ( dirp != NULL )
+                       free( (pointer)dirp );
+
+               (void)close( fd );
+               errno = serrno;
+               return NULL;            /* not enough memory */
+               }
+
+       dirp->dd_fd = fd;
+       dirp->dd_loc = dirp->dd_size = 0;       /* refill needed */
+
+       return dirp;
+}
diff --git a/lang/cem/libcc.ansi/misc/popen.c b/lang/cem/libcc.ansi/misc/popen.c
new file mode 100644 (file)
index 0000000..c566c5f
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * popen - open a pipe
+ */
+/* $Header$ */
+
+#include       <errno.h>
+#include       <stdio.h>
+#include       <signal.h>
+#if    defined(__BSD4_2)
+#if    _EM_WSIZE != 4
+#error union wait is too small
+#endif
+union wait {
+       int     w_status;
+};
+typedef union wait wait_arg;
+#else
+typedef int wait_arg;
+#endif /* __BSD4_2 */
+#include       "../stdio/loc_incl.h"
+
+int close(int d);
+int dup2(int oldd, int newd);          /* not present in System 5 */
+int execl(const char *name, ... );
+int fork(void);
+int pipe(int fildes[2]);
+int wait(wait_arg *status);
+void _exit(int status);
+
+static int pids[20];
+
+FILE *
+popen(const char *command, const char *type)
+{
+       int piped[2];
+       int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
+       int pid;
+
+       if (Xtype == 2 ||
+           pipe(piped) < 0 ||
+           (pid = fork()) < 0) return 0;
+       
+       if (pid == 0) {
+               /* child */
+               register int *p;
+
+               for (p = pids; p < &pids[ FOPEN_MAX]; p++) {
+                       if (*p) close(p - pids);
+               }
+               close(piped[Xtype]);
+               dup2(piped[!Xtype], !Xtype);
+               close(piped[!Xtype]);
+               execl("/bin/sh", "sh", "-c", command, (char *) 0);
+               _exit(127);     /* like system() ??? */
+       }
+
+       pids[piped[Xtype]] = pid;
+       close(piped[!Xtype]);
+       return fdopen(piped[Xtype], type);
+}
+
+#if    defined(__BSD4_2)
+#define        ret_val status.w_status
+#else
+#define        ret_val status
+#endif
+
+int
+pclose(FILE *stream)
+{
+       int fd = fileno(stream);
+       wait_arg status;
+       int wret;
+       void (*intsave)(int) = signal(SIGINT, SIG_IGN);
+       void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
+
+       fclose(stream);
+       while ((wret = wait(&status)) != -1) {
+               if (wret == pids[fd]) break;
+       }
+       if (wret == -1) ret_val = -1;
+       signal(SIGINT, intsave);
+       signal(SIGQUIT, quitsave);
+       pids[fd] = 0;
+       return ret_val;
+}
+
+#if    defined(__USG)
+int
+dup2(int oldd, int newd)
+{
+       int i = 0, fd, tmp;
+       int fdbuf[_NFILES];
+
+       /* ignore the error on the close() */
+       tmp = errno; (void) close(newd); errno = tmp;
+       while ((fd = dup(oldd)) != newd) {
+               if (fd == -1) break;
+               fdbuf[i++] = fd;
+       }
+       tmp = errno;
+       while (--i >= 0) {
+               close(fdbuf[i]);
+       }
+       errno = tmp;
+       return -(fd == -1);
+}
+#endif /* __USG */
diff --git a/lang/cem/libcc.ansi/misc/putw.c b/lang/cem/libcc.ansi/misc/putw.c
new file mode 100644 (file)
index 0000000..23a591a
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+ * putw - write an word on a stream
+ */
+/* $Header$ */
+
+#include       <stdio.h>
+
+int
+putw(int w, register FILE *stream)
+{
+       register int cnt = sizeof(int);
+       register char *p = (char *) &w;
+
+       while (cnt--) {
+               putc(*p++, stream);
+       }
+       if (ferror(stream)) return EOF;
+       return w;
+}
diff --git a/lang/cem/libcc.ansi/misc/readdir.c b/lang/cem/libcc.ansi/misc/readdir.c
new file mode 100644 (file)
index 0000000..2497e46
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+       readdir -- read next entry from a directory stream
+
+       last edit:      25-Apr-1987     D A Gwyn
+*/
+
+#include       <errno.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#include       <dirent.h>
+
+/* SVR3 system call, or emulation for getdents() */
+extern int getdents(int fildes, char *buf, unsigned nbyte);
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+struct dirent *
+readdir(register DIR *dirp)
+{
+       register struct dirent  *dp;    /* -> directory data */
+
+       if ( dirp == NULL || dirp->dd_buf == NULL )
+               {
+               errno = EFAULT;
+               return NULL;            /* invalid pointer */
+               }
+
+       do      {
+               if ( dirp->dd_loc >= dirp->dd_size )    /* empty or obsolete */
+                       dirp->dd_loc = dirp->dd_size = 0;
+
+               if ( dirp->dd_size == 0 /* need to refill buffer */
+                 && (dirp->dd_size =
+                       getdents( dirp->dd_fd, dirp->dd_buf, (unsigned)DIRBUF )
+                    ) <= 0
+                  )
+                       return NULL;    /* EOF or error */
+
+               dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc];
+               dirp->dd_loc += dp->d_reclen;
+               }
+       while ( dp->d_ino == 0L );      /* don't rely on getdents() */
+
+       return dp;
+}
diff --git a/lang/cem/libcc.ansi/misc/rewinddir.c b/lang/cem/libcc.ansi/misc/rewinddir.c
new file mode 100644 (file)
index 0000000..6b52f69
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+       rewinddir -- rewind a directory stream
+
+       last edit:      25-Apr-1987     D A Gwyn
+
+       This is not simply a call to seekdir(), because seekdir()
+       will use the current buffer whenever possible and we need
+       rewinddir() to forget about buffered data.
+*/
+
+#include       <errno.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#include       <dirent.h>
+
+extern off_t   lseek(int d, int offset, int whence);
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#ifndef SEEK_SET
+#define        SEEK_SET        0
+#endif
+
+void
+rewinddir(register DIR *dirp)
+{
+       if ( dirp == NULL || dirp->dd_buf == NULL )
+               {
+               errno = EFAULT;
+               return;                 /* invalid pointer */
+               }
+
+       dirp->dd_loc = dirp->dd_size = 0;       /* invalidate buffer */
+       (void)lseek( dirp->dd_fd, (off_t)0, SEEK_SET ); /* may set errno */
+}
diff --git a/lang/cem/libcc.ansi/misc/seekdir.c b/lang/cem/libcc.ansi/misc/seekdir.c
new file mode 100644 (file)
index 0000000..eff0ef5
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+       seekdir -- reposition a directory stream
+
+       last edit:      24-May-1987     D A Gwyn
+
+       An unsuccessful seekdir() will in general alter the current
+       directory position; beware.
+
+       NOTE:   4.nBSD directory compaction makes seekdir() & telldir()
+               practically impossible to do right.  Avoid using them!
+*/
+
+#include       <errno.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#include       <dirent.h>
+
+extern off_t lseek(int d, int offset, int whence);
+
+#ifndef NULL
+#define        NULL    0
+#endif
+
+#ifndef SEEK_SET
+#define        SEEK_SET        0
+#endif
+
+typedef int    bool;                   /* Boolean data type */
+#define        false   0
+#define        true    1
+
+void
+seekdir(register DIR *dirp, register off_t loc)
+/* loc == position from telldir() */
+{
+       register bool   rewind;         /* "start over when stymied" flag */
+
+       if ( dirp == NULL || dirp->dd_buf == NULL )
+               {
+               errno = EFAULT;
+               return;                 /* invalid pointer */
+               }
+
+       /* A (struct dirent)'s d_off is an invented quantity on 4.nBSD
+          NFS-supporting systems, so it is not safe to lseek() to it. */
+
+       /* Monotonicity of d_off is heavily exploited in the following. */
+
+       /* This algorithm is tuned for modest directory sizes.  For
+          huge directories, it might be more efficient to read blocks
+          until the first d_off is too large, then back up one block,
+          or even to use binary search on the directory blocks.  I
+          doubt that the extra code for that would be worthwhile. */
+
+       if ( dirp->dd_loc >= dirp->dd_size      /* invalid index */
+         || ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off > loc
+                                       /* too far along in buffer */
+          )
+               dirp->dd_loc = 0;       /* reset to beginning of buffer */
+       /* else save time by starting at current dirp->dd_loc */
+
+       for ( rewind = true; ; )
+               {
+               register struct dirent  *dp;
+
+               /* See whether the matching entry is in the current buffer. */
+
+               if ( (dirp->dd_loc < dirp->dd_size      /* valid index */
+                  || readdir( dirp ) != NULL   /* next buffer read */
+                  && (dirp->dd_loc = 0, true)  /* beginning of buffer set */
+                    )
+                 && (dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off
+                       <= loc          /* match possible in this buffer */
+                  )    {
+                       for ( /* dp initialized above */ ;
+                             (char *)dp < &dirp->dd_buf[dirp->dd_size];
+                             dp = (struct dirent *)((char *)dp + dp->d_reclen)
+                           )
+                               if ( dp->d_off == loc )
+                                       {       /* found it! */
+                                       dirp->dd_loc =
+                                               (char *)dp - dirp->dd_buf;
+                                       return;
+                                       }
+
+                       rewind = false; /* no point in backing up later */
+                       dirp->dd_loc = dirp->dd_size;   /* set end of buffer */
+                       }
+               else                    /* whole buffer past matching entry */
+                       if ( !rewind )
+                               {       /* no point in searching further */
+                               errno = EINVAL;
+                               return; /* no entry at specified loc */
+                               }
+                       else    {       /* rewind directory and start over */
+                               rewind = false; /* but only once! */
+
+                               dirp->dd_loc = dirp->dd_size = 0;
+
+                               if ( lseek( dirp->dd_fd, (off_t)0, SEEK_SET )
+                                       != 0
+                                  )
+                                       return; /* errno already set (EBADF) */
+
+                               if ( loc == 0 )
+                                       return; /* save time */
+                               }
+               }
+}
diff --git a/lang/cem/libcc.ansi/misc/sleep.c b/lang/cem/libcc.ansi/misc/sleep.c
new file mode 100644 (file)
index 0000000..abb147e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * sleep - suspend current process for a number of seconds
+ */
+/* $Header$ */
+
+#include       <signal.h>
+#include       <setjmp.h>
+
+int alarm(int n);
+void pause(void);
+
+static jmp_buf setjmpbuf;
+
+static void
+alfun(int sig)
+{
+       longjmp(setjmpbuf, 1);
+}              /* used with sleep() below */
+
+void
+sleep(int n)
+{
+/* sleep(n) pauses for 'n' seconds by scheduling an alarm interrupt. */
+       unsigned oldalarm;
+       void (*oldsig)(int);
+
+       if (n <= 0) return;
+       if (setjmp(setjmpbuf)) {
+               signal(SIGALRM, oldsig);
+               alarm(oldalarm);
+               return;
+       }
+       oldalarm = alarm(5000);         /* Who cares how long, as long
+                                        * as it is long enough
+                                        */
+       if (oldalarm > n) oldalarm -= n;
+       else if (oldalarm) {
+               n = oldalarm;
+               oldalarm = 1;
+       }
+       oldsig = signal(SIGALRM, alfun);
+       alarm(n);
+       for (;;)  {
+               /* allow for other handlers ... */
+               pause();
+       }
+}
diff --git a/lang/cem/libcc.ansi/misc/telldir.c b/lang/cem/libcc.ansi/misc/telldir.c
new file mode 100644 (file)
index 0000000..359c7bf
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+       telldir -- report directory stream position
+
+       last edit:      25-Apr-1987     D A Gwyn
+
+       NOTE:   4.nBSD directory compaction makes seekdir() & telldir()
+               practically impossible to do right.  Avoid using them!
+*/
+
+#include       <errno.h>
+#include       <sys/errno.h>
+#include       <sys/types.h>
+#include       <dirent.h>
+
+extern off_t lseek(int d, int offset, int whence);
+
+#ifndef SEEK_CUR
+#define        SEEK_CUR        1
+#endif
+
+off_t
+telldir(register DIR *dirp)            /* return offset of next entry */
+{
+       if ( dirp == NULL || dirp->dd_buf == NULL )
+               {
+               errno = EFAULT;
+               return -1;              /* invalid pointer */
+               }
+
+       if ( dirp->dd_loc < dirp->dd_size )     /* valid index */
+               return ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off;
+       else                            /* beginning of next directory block */
+               return lseek( dirp->dd_fd, (off_t)0, SEEK_CUR );
+}
diff --git a/lang/cem/libcc.ansi/misc/termcap.c b/lang/cem/libcc.ansi/misc/termcap.c
new file mode 100644 (file)
index 0000000..ef874e3
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ *     termcap.c       1.1     20/7/87         agc     Joypace Ltd
+ *
+ *     Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
+ *     This file may be freely distributed provided that this notice
+ *     remains attached.
+ *
+ *     A public domain implementation of the termcap(3) routines.
+ *
+ *     Made fully functional by Ceriel J.H. Jacobs.
+ *
+ * BUGS:
+ *     - does not check termcap entry sizes
+ *     - not fully tested
+ */
+/* $Header$ */
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+
+#define CAPABLEN       2
+
+#define ISSPACE(c)     ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
+#define ISDIGIT(x)     ((x) >= '0' && (x) <= '9')
+
+short  ospeed;         /* output speed */
+char   PC;             /* padding character */
+char   *BC;            /* back cursor movement */
+char   *UP;            /* up cursor movement */
+
+static const char      *capab;         /* the capability itself */
+static int     check_for_tc(void);
+static int     match_name(const char *buf, const char *name);
+
+/*
+ *     tgetent - get the termcap entry for terminal name, and put it
+ *     in bp (which must be an array of 1024 chars). Returns 1 if
+ *     termcap entry found, 0 if not found, and -1 if file not found.
+ */
+int
+tgetent(char *bp, const char *name)
+{
+       FILE    *fp;
+       char    *file;
+       char    *cp;
+       short   len = strlen(name);
+       char    buf[1024];
+
+       capab = bp;
+       if ((file = getenv("TERMCAP")) != (char *) NULL) {
+               if (*file != '/' &&
+                   (cp = getenv("TERM")) != NULL && strcmp(name, cp) == 0) {
+                       (void) strcpy(bp, file);
+                       return(1);
+               }
+               else file = "/etc/termcap";
+       } else
+               file = "/etc/termcap";
+       if ((fp = fopen(file, "r")) == (FILE *) NULL)
+               return(-1); 
+       while (fgets(buf, 1024, fp) != NULL) {
+               if (buf[0] == '#') continue;
+               while (*(cp = &buf[strlen(buf) - 2]) == '\\')
+                       if (fgets(cp, 1024, fp) == NULL)
+                               return (0);
+               if (match_name(buf, name)) {
+                       strcpy(bp, buf);
+                       fclose(fp);
+                       return(check_for_tc());
+               }
+       }
+       fclose(fp);
+       return(0);
+}
+
+/*
+ *     Compare the terminal name with each termcap entry name; Return 1 if a
+ *     match is found.
+ */
+static int
+match_name(const char *buf, const char *name)
+{
+       register const char *tp = buf;
+       register const char *np;
+
+       for (;;) {
+               for (np = name; *np && *tp == *np; np++, tp++) { }
+               if (*np == 0 && (*tp == '|' || *tp == ':' || *tp == 0))
+                       return(1);
+               while (*tp != 0 && *tp != '|' && *tp != ':') tp++;
+               if (*tp++ != '|') return (0);
+       }
+}
+
+/*
+ *     Handle tc= definitions recursively.
+ */
+static int
+check_for_tc(void)
+{
+       static int      count = 0;
+       const char      *savcapab = capab;
+       char            buf[1024];
+       char            terminalname[128];
+       register char   *p = (char *)capab + strlen(capab) - 2, *q;
+
+       while (*p != ':')
+               if (--p < (char *)capab)
+                       return(0);      /* no : in termcap entry */
+       if (p[1] != 't' || p[2] != 'c')
+               return(1);
+       if (count > 16) return(0);      /* recursion in tc= definitions */
+       count++;
+       strcpy(terminalname, &p[4]);
+       q = terminalname;
+       while (*q && *q != ':') q++;
+       *q = 0;
+       if (tgetent(buf, terminalname) != 1) {
+               --count;
+               return(0);
+       }
+       --count;
+       for (q = buf; *q && *q != ':'; q++) { }
+       strcpy(p, q);
+       capab = savcapab;
+       return(1);
+}
+
+/*
+ *     tgetnum - get the numeric terminal capability corresponding
+ *     to id. Returns the value, -1 if invalid.
+ */
+int
+tgetnum(const char *id)
+{
+       const char      *cp;
+       int     ret;
+
+       if ((cp = capab) == NULL || id == NULL)
+               return(-1);
+       while (*++cp != ':')
+               ;
+       while (*cp) {
+               cp++;
+               while (ISSPACE(*cp))
+                       cp++;
+               if (strncmp(cp, id, CAPABLEN) == 0) {
+                       while (*cp && *cp != ':' && *cp != '#')
+                               cp++;
+                       if (*cp != '#')
+                               return(-1);
+                       for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
+                               ret = ret * 10 + *cp - '0';
+                       return(ret);
+               }
+               while (*cp && *cp != ':')
+                       cp++;
+       }
+       return(-1);
+}
+
+/*
+ *     tgetflag - get the boolean flag corresponding to id. Returns -1
+ *     if invalid, 0 if the flag is not in termcap entry, or 1 if it is
+ *     present.
+ */
+int
+tgetflag(const char *id)
+{
+       const char      *cp;
+
+       if ((cp = capab) == NULL || id == NULL)
+               return(-1);
+       while (*++cp != ':')
+               ;
+       while (*cp) {
+               cp++;
+               while (ISSPACE(*cp))
+                       cp++;
+               if (strncmp(cp, id, CAPABLEN) == 0)
+                       return(1);
+               while (*cp && *cp != ':')
+                       cp++;
+       }
+       return(0);
+}
+
+/*
+ *     tgetstr - get the string capability corresponding to id and place
+ *     it in area (advancing area at same time). Expand escape sequences
+ *     etc. Returns the string, or NULL if it can't do it.
+ */
+char *
+tgetstr(const char *id, char ** const area)
+{
+       const char      *cp;
+       char    *ret;
+       int     i;
+
+       if ((cp = capab) == NULL || id == NULL)
+               return(NULL);
+       while (*++cp != ':')
+               ;
+       while (*cp) {
+               cp++;
+               while (ISSPACE(*cp))
+                       cp++;
+               if (strncmp(cp, id, CAPABLEN) == 0) {
+                       while (*cp && *cp != ':' && *cp != '=')
+                               cp++;
+                       if (*cp != '=')
+                               return(NULL);
+                       for (ret = *area, cp++; *cp && *cp != ':' ; (*area)++, cp++)
+                               switch(*cp) {
+                               case '^' :
+                                       **area = *++cp - 'A' + 1;
+                                       break;
+                               case '\\' :
+                                       switch(*++cp) {
+                                       case 'E' :
+                                               **area = '\033';
+                                               break;
+                                       case 'n' :
+                                               **area = '\n';
+                                               break;
+                                       case 'r' :
+                                               **area = '\r';
+                                               break;
+                                       case 't' :
+                                               **area = '\t';
+                                               break;
+                                       case 'b' :
+                                               **area = '\b';
+                                               break;
+                                       case 'f' :
+                                               **area = '\f';
+                                               break;
+                                       case '0' :
+                                       case '1' :
+                                       case '2' :
+                                       case '3' :
+                                               for (i=0 ; *cp && ISDIGIT(*cp) ; cp++)
+                                                       i = i * 8 + *cp - '0';
+                                               **area = i;
+                                               cp--;
+                                               break;
+                                       case '^' :
+                                       case '\\' :
+                                               **area = *cp;
+                                               break;
+                                       }
+                                       break;
+                               default :
+                                       **area = *cp;
+                               }
+                       *(*area)++ = '\0';
+                       return(ret);
+               }
+               while (*cp && *cp != ':')
+                       cp++;
+       }
+       return(NULL);
+}
+
+/*
+ *     tgoto - given the cursor motion string cm, make up the string
+ *     for the cursor to go to (destcol, destline), and return the string.
+ *     Returns "OOPS" if something's gone wrong, or the string otherwise.
+ */
+char *
+tgoto(const char *cm, int destcol, int destline)
+{
+       register char   *rp;
+       static char     ret[24];
+       char            added[16];
+       int             *dp = &destline;
+       int             numval;
+       int             swapped = 0;
+
+       added[0] = 0;
+       for (rp = ret ; *cm ; cm++) {
+               if (*cm == '%') {
+                       switch(*++cm) {
+                       case '>' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               cm++;
+                               if (*dp > *cm++) {
+                                       *dp += *cm;
+                               }
+                               break;
+                       case '+' :
+                       case '.' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               if (*cm == '+') *dp = *dp + *++cm;
+                               for (;;) {
+                                   switch(*dp) {
+                                   case 0:
+                                   case 04:
+                                   case '\t':
+                                   case '\n':
+                                       /* filter these out */
+                                       if (dp == &destcol || swapped || UP) {
+                                               strcat(added, dp == &destcol || swapped ?
+                                                       (BC ? BC : "\b") :
+                                                       UP);
+                                               (*dp)++;
+                                               continue;
+                                       }
+                                   }
+                                   break;
+                               }
+                               *rp++ = *dp;
+                               dp = (dp == &destline) ? &destcol : NULL;
+                               break;
+
+                       case 'r' : {
+                               int tmp = destline;
+
+                               destline = destcol;
+                               destcol = tmp;
+                               swapped = 1 - swapped;
+                               break;
+                       }
+                       case 'n' :
+                               destcol ^= 0140;
+                               destline ^= 0140;
+                               break;
+
+                       case '%' :
+                               *rp++ = '%';
+                               break;
+
+                       case 'i' :
+                               destcol++;
+                               destline++;
+                               break;
+
+                       case 'B' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               *dp = 16 * (*dp / 10) + *dp % 10;
+                               break;
+
+                       case 'D' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               *dp = *dp - 2 * (*dp % 16);
+                               break;
+
+                       case 'd' :
+                       case '2' :
+                       case '3' :
+                               if (dp == NULL)
+                                       return("OOPS");
+                               numval = *dp;
+                               dp = (dp == &destline) ? &destcol : NULL;
+                               if (numval >= 100) {
+                                       *rp++ = '0' + numval / 100;
+                               }
+                               else if (*cm == '3') {
+                                       *rp++ = ' ';
+                               }
+                               if (numval >= 10) {
+                                       *rp++ = '0' + ((numval%100)/10);
+                               }
+                               else if (*cm == '3' || *cm == '2') {
+                                       *rp++ = ' ';
+                               }
+                               *rp++ = '0' + (numval%10);
+                               break;
+                       default :
+                               return("OOPS");
+                       }
+               }
+               else *rp++ = *cm;
+       }
+       *rp = '\0';
+       strcpy(rp, added);
+       return(ret);
+}
+
+static int tens_of_ms_p_char[] = {     /* index as returned by gtty */
+                                       /* assume 10 bits per char */
+       0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 2
+};
+/*
+ *     tputs - put the string cp out onto the terminal, using the function
+ *     outc. Also handle padding.
+ */
+int
+tputs(register const char *cp, int affcnt, int (*outc)(int))
+{
+       int delay = 0;
+       if (cp == NULL)
+               return(1);
+       while (ISDIGIT(*cp)) {
+               delay = delay * 10 + (*cp++ - '0');
+       }
+       delay *= 10;
+       if (*cp == '.') {
+               cp++;
+               if (ISDIGIT(*cp)) {
+                       delay += *cp++ - '0';
+               }
+               while (ISDIGIT(*cp)) cp++;
+       }
+       if (*cp == '*') {
+               delay *= affcnt;
+               cp++;
+       }
+       while (*cp)
+               (*outc)(*cp++);
+       if (delay != 0 &&
+           ospeed > 0 &&
+           ospeed < (sizeof tens_of_ms_p_char / sizeof tens_of_ms_p_char[0])) {
+               delay = (delay + tens_of_ms_p_char[ospeed] - 1) / 
+                                 tens_of_ms_p_char[ospeed];
+               while (delay--) (*outc)(PC);
+       }
+       return(1);
+}
+
+/*
+ *     That's all, folks...
+ */