#ifndef _FCNTL_H_
#define _FCNTL_H_
/**
*                       < f c n t l . h >
*
* The following symbols are used for the "open" and "creat" functions.
*
* AMENDMENT HISTORY
* ~~~~~~~~~~~~~~~~~
*   28 Aug 93   DJW   - Changed O_xxx flags so that 0 now means no flags
*                       set (which should be illegal).  This makes it
*                       easier to set particular bits.
*
*   03 Sep 94   DJW   - Added name hiding definitions for routines that are
*                       used internally within the C68 libraries.
*
*   13 Sep 94   DJW   - Changed the values associated with O_RDONLY, O_WRONLY,
*                       and O_RDWR to be 0,1 and 2 respectively.  This is to
*                       bring them into line with the original K&R spec for
*                       those programs that have these values hard coded as
*                       constants (like certain GNU programs!).  Changed some
*                       of the values associated with the other constants to
*                       make them slightly more consistent.
*
*   31 Dec 94   DJW   - Added qopen() routine and _OpenVector vector.
*                     - Changed name hiding of open() accordingly.
*
*   24 Feb 96   DJW   - Changed definitions used for name hiding of open()
*                       routine as redefining it as a vector could cause
*                       problems in any program which had its own function
*                       declarations for open() not preceded by 'extern'.
*                       The change is to now call a routine which then tests
*                       the vector and calls the correct variant of open().
**/

#ifndef _SYS_TYPES_H
#include <sys/types.h>
#endif /* SYS_TYPES_H */

#define O_RDONLY 0x0000  /* Read-only value (right byte of mode word) */
#define O_WRONLY 0x0001  /* Write-only value */
#define O_RDWR   0x0002  /* Read-write value */
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)

#define O_BINARY 0x0008  /* Binary access mode (ignored under QDOS) */
#define O_CREAT  0x0010  /* File creation flag */
#define O_EXCL   0x0020  /* Exclusive access flag */
#define O_NOCTTY 0x0040  /* POSIX: Not controlling TTY (ignored under QDOS */
#define O_TRUNC  0x0080  /* File truncation flag */

#define O_APPEND   0x0100  /* Append mode flag */
#define O_NDELAY   0x0200  /* Non-blocking I/O flag */
#define O_NONBLOCK 0x0400  /* POSIX: ignored under QDOS */
#define O_SYNC     0x0800  /* POSIX: ignored under QDOS */

#define O_RAW    0x1000    /* Raw I/O flag (Lattice feature) */

#define O_PDIR 0x1000  /* Open file in program directory */
#define O_DDIR 0x2000  /* Open file in destination directory */
#define O_DIR  0x4000  /* Open file in data directory (default) */
/**
*
* The following symbols are used for the "fcntl" function.
* (although they will not all be supported in meaningful ways)
*
*/
#define F_DUPFD 1       /* Duplicate file descriptor */
#define F_GETFD 2       /* Get file descriptor device */
#define F_SETFD 3       /* Set file descriptor device */
#define F_GETFL 4       /* Get file flags */
#define F_SETFL 5       /* Set file flags */
#define F_GETLK 6       /* Get record locking information */
#define F_SETLK 7       /* Set record locking information */
#define F_SETLKW 8      /* Set record locking information with wait if blocked */

/*
* Structure that describes a file lock
*/
struct flock {
    short   l_type;     /* Type of lock */
    short   l_whence;   /* Flag for starting offset */
    off_t   l_start;    /* Relative offset in bytes */
    off_t   l_len;      /* Size;  if 0 then until EOF */
    long    l_sysid;    /* Returned with F_GETLK */
    pid_t   l_pid;      /* Returned with F_GETLK */
    };
/*
 *  values for 'l_type'
 */
#define F_RDLCK  1      /* Shared or read lock */
#define F_UNLCK  2      /* Unlock */
#define F_WRLCK  3      /* Exclusive or write lock */

/*
* The following codes are used for the lseek function.
*/
#ifndef SEEK_SET
#define SEEK_SET 0      /* seek from beginning */
#define SEEK_CUR 1      /* seek from here */
#define SEEK_END 2      /* seek from end */
#endif

/**
 *
 *  Definitions used for backward compatibility with old programs
 *
 **/
#define SEEK_START  SEEK_SET
#define SEEK_REL    SEEK_CUR

/*
 * The following routine is a macro to return position in a file
 */
#define tell( fd ) lseek( fd, 0L, SEEK_REL)

#ifndef _TYPES_H
#include <sys/types.h>
#endif

#ifdef __STDC__
#define _P_(params) params
#else
#define _P_(params) ()
#endif

/*  Name Hiding definitions */
#define creat   _Creat
#define open    _open
/*  Prototypes */
extern  int   fdmode    _P_((int, int));
extern  int   iomode    _P_((int, int));
extern  int   fcntl     _P_((int, int, ...));
extern  int   opene     _P_((const char *, mode_t,int));
extern  int   creat     _P_((const char *, mode_t));
extern  int   open      _P_((const char *, int, ...));

/*
--------------------------------------------------------------------------
        ALL INFORMATION BEYOND THIS POINT IS QDOS SPECIFIC
--------------------------------------------------------------------------
*/
/*
 *  Forward declare the UFB structure for use in function prorotypes.
 *  Note that only internal library routines should need to ever know
 *  the detailed layout of this structure as it is subject to change
 *  without notice at different releases of C68 for QDOS/SMS.
 */
typedef struct UFB UFB_t;

/*
*
* UFB.ufbtyp definitions
*
*/
#define D_UNKNOWN 0
#define D_DISK    1
#define D_CON     2
#define D_PRN     3
#define D_AUX     4
#define D_NULL    5
#define D_PIPE    6
#define D_SOCKET  7
#define D_NET     8
/*
*
* UFB.ufbst definitions
*
*/
#define UFB_EOF  0x80                       /* End-of-file state */
/*
 *
 * UFB.ufbflg definitions
 *
 */
#define UFB_OP 0x01   /* file is open */
#define UFB_RA 0x02   /* reading is allowed */
#define UFB_WA 0x04   /* writing is allowed */
#define UFB_AP 0x08   /* append mode flag */
#define UFB_NC 0x10   /* no close flag */
#define UFB_DP 0x20   /* file has been DUP'ed flag */
#define UFB_NT 0x40   /* access file with no translation */
#define UFB_ND 0x80   /* I/O to be done with no delay on this file */
#define UFB_TF 0x100  /* file is only temporary (delete on close) */
#define UFB_SY 0x200  /* sync (flush) file after each write */
#define UFB_NB 0x400  /* I/O to be done with no delay (Posix O_NONBLOCK mode) */

/**
 *
 *  The following routines are specific to the QDOS
 *  implementation of Unix style file descriptors.
 *  (For those available for use see QdosC68_DOC for details)
 *
**/
#define  _Open  _OpenVector /* for backwards compatibility */
extern int  (*_OpenVector)  _P_((const char *, int, ...));

extern int  (*_conread)     _P_((struct UFB *, void *, unsigned int));
extern int  (*_conwrite)    _P_((struct UFB *, void *, unsigned int));
extern int  qopen           _P_((const char *, int, ...));

extern char _Qopen_in[];    /* "Special" characters for qopen() */
extern char _Qopen_out[];   /* Replacement values for special characters */

extern timeout_t  _Timeout; /* Default value for I/O timeout */

#ifdef __LIBRARY__
/*************************************************************************
 *
 *                          C A U T I O N
 *                          ~~~~~~~~~~~~~
 *
 *  The remainder of this header contains definitions that are internal
 *  to the way that the C68 libraries have been implemented on QDOS/SMS.
 *  These definitions should not be used by any user program as they are
 *  subject to change without notice.
 *
 *************************************************************************/

/**
 *  The following data structures and routines are used internally within the
 *  QDOS implementation of the standard C library to allow UNIX system calls
 *  for file accessing to be emulated.
 *
 *  It is effectively a UNIX file block that retains information
 *  about a file being accessed via the level 1 I/O functions. It
 *  also retains information about the termios emulation.
 *
 * N.B. Care must be taken in handling the UFB structures as opening
 *      a file can cause them all to be moved in memory.
 */

#ifndef _TERMIOS_H
#include <termios.h>
#endif /* _TERMIOS_H */

struct UFB  {
    char  ufbtyp;       /* device type */
    char  ufbst;        /* device status */
    short ufbflg;       /* flags */
    long  ufbfh;        /* QDOS channel id */
    long  ufbfh1;       /* Secondary id for sockets/pipes */
                        /* Name pointer for temporary files */
    long  ufbjob;       /* Job id for pipes */
    char *ufbnam;       /* channel name (if it is known) */
    struct termios ufbterm;  /* Data fields for termios emulation */
    };

extern struct _MODE_TABLE {
        short   ufbflag;        /* Flag at UFB level */
        short   fileflag;       /* Flag at level 1 level */
        short   modemask;       /* Mask when checking level 1 mode */
        } _ModeTable[];

extern UFB_t *  _ufbs;           /* Pointer to UFB table */
extern long     _nufbs;          /* Current number of UFB's allocated */
                                    /* (they may not all be in use) */

int       __Open      _P_((const char *, int, ...));
long      _do_opene   _P_((char *, long, int, long (*)_P_((char *, long, ...))));
UFB_t *   _Chkufb     _P_((int));
timeout_t _GetTimeout _P_((UFB_t *));
int       _ModeFd     _P_((short));
short     _ModeUfb    _P_((int));
UFB_t *   _Newufb     _P_((int));
int       _Openufb    _P_((void));
void      _Initcon    _P_((void));

#endif /* __LIBRARY__ */
         
#undef _P_

#endif /* _FCNTL_H */

