Listing 3

/***************************************/
/*                                     */
/*              osem.c                 */
/*                                     */
/* Operating system emulation routines */
/* for embedded system example ROM     */
/* monitor.                            */
/*                                     */
/*          Copyright (c) 1990         */
/*          Pasquale J. Villani        */
/*          All Rights Reserved        */
/*                                     */
/*                                     */
/***************************************/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

/* convience defines                               */
#define STDIN   0
#define STDOUT  1
#define STDERR  2
#define MAXFD   3
#define BUFSIZ  512            /* buffers are 512 for this vsn  */

#ifndef TRUE
#define TRUE    1
#endif
#ifndef FALSE
#define FALSE   0
#endif
#ifndef ERROR
#define ERROR   -1
#endif
#ifndef OK
#define OK  0
#endif
#ifndef EOF
#define EOF -1
#endif

/* make errno accessible to the entire file            */
extern int errno;

/* special data structure for ioctl optional argument   */
union arg
{
   int i;
   void    *p;
};

/* a simple file table to keep track of stdin & stdout status  */
static char fd[MAXFD] =
{
   FALSE,          /* stdin                 */
   FALSE,          /* stdout                */
   FALSE           /* stderr                */
};

/* a simple set of i/o buffers for input buffering  */
struct _buf
{
   int nbytes;
   char    *bp;
   char    buf[BUFSIZ];
};

static struct _buf iobuf =
{
   -1, (char *)0
};

/*                                 */
/* smatch:                             */
/* match two strings. return true if equal          */
/*                                 */
static int smatch(s1, s2)
char *s1, *s2;

{
   while(*s1 != '\0')
   {
      if(*s1 != *s2)
         break;
      ++s1;
      ++s2;
   }
   return s1 == s2;
}

/*                                  */
/* open:                               */
/*  open a file for read or write                   */
/*  follows posix specification                  */
/*                                  */
int open(path, oflag, mode)
char *path;
int oflag, mode;
{
  if(smatch(path, "/dev/con") || ((oflag & O_RDWR) == O_RDWR))
  {
     errno = EACCES;
     return ERROR;    /* error - only console allowed  */
  }
  /* for this system, only stdin and stdout are available
  /* based on oflag and availability, assign appropraie fd
  if((oflag & O_RDONLY) && !fd[STDIN])
  {
     fd[STDIN] = TRUE;
     return STDIN;
  }
  else if(oflag & O_WRONLY)
  {
     fd[STDOUT] = TRUE;
     return STDOUT;
  }
  else
  {
     errno = EACCES;
     return ERROR;
  }
}

/*                                  */
/* close:                              */
/*  close a file                            */
/*                                  */
int close(fildes)
int fildes;
{
   if((fildes < 0) || (fildes > MAXFD) || !(fd[fildes]))
   {
      errno = EBADF;
      return ERROR;
   }
   fd[fildes] = FALSE;
   return OK;
}

/*                                  */
/* ioctl:                               */
/* direct device control                    */
/*                                  */
int ioctl(fildes, request, arg)
int fildes, request;
union arg arg;
{
   errno = EINVAL;
   return ERROR;
}
/*                                  */
/* write:                               */
/* write to a file                          */
/*                                  */
int write(fildes, buf, nbyte)
int fildes;
void *buf;
unsigned int nbyte;
{
   int cnt = nbyte;
   if(fildes != STDOUT && fildes != STDERR)
   {
      errno = EBADF;
      return ERROR;
   }
   while(cnt-- > 0)
   {
      if(*(char *)buf == '\n')
         _cout('\r');
      _cout(*((char *)buf)++);
   }
   return nbyte;
}
int read(fildes, buf, nbyte)
int fildes;
void *buf;
unsigned int nbyte;
{
  register char *bp;
  register int c;

  if(fildes != STDIN)
  {
     errno = EBADF;
     return ERROR;
  }
  if(iobuf.nbytes <= 0)
  {
     bp = iobuf.buf;
     iobuf.nbytes = 0;
     do
     {
         *bp++ = (_cout(c = _cin()));
         if(c == '\r')
            _cout('\n');
         ++iobuf.nbytes;
     } while(c != '\n' && c != '\r');
     iobuf.bp = iobuf.buf;
  }
  for(bp = iobuf.bp, c = 0; c < iobuf.nbytes && c <nbyte; c++)
  {
     *((char *)buf)++ = *bp == '\r' ? ++bp, '\n' : *bp++;
  }
     iobuf.bp = bp;
  iobuf.nbytes -= c;
  return c;
}