--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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:
--- /dev/null
+/*
+ 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 );
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ 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 */
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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*/
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 */
+}
--- /dev/null
+/*
+ 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 */
+ }
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ 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 );
+}
--- /dev/null
+/*
+ * 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...
+ */