/* based upon Dale Schumacher's dLibs library */
/* extensively modified by ers */

#include <compiler.h>
#include <osbind.h>
#include <mintbind.h>
#include <limits.h>
#include <fcntl.h>
#include <ioctl.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include "lib.h"

static int __umask = -1;
extern int __mint;

static void _get_umask __PROTO((void));

/*
 * function to set the initial value of __umask
 */

static void
_get_umask()
{
	if (__mint < 9) {
		__umask = 0;
	} else {
		__umask = Pumask(0);
		(void) Pumask(__umask);
	}
}

/* NOTE: we assume here that every compiler that can handle __PROTO
 *       is __STDC__ and can handle the >>...<< ellipsis
 *       (see also unistd.h)
 */

#ifdef __STDC__
int open(const char *_filename, int iomode, ...)
#else
int open(_filename, iomode, pmode)
	const char *_filename;
	int iomode;
	unsigned pmode;
#endif
{
	int rv;
	int modemask;			/* which bits get passed to the OS? */
	char filename[PATH_MAX];

#ifdef __STDC__
	unsigned pmode;
	va_list argp;
	va_start(argp, iomode);
	pmode = va_arg(argp, unsigned int);
	va_end(argp);
#endif

	_unx2dos(_filename, filename);

/* use the umask() setting to get the right permissions */
	if (__umask == -1)
		_get_umask();
	pmode &= ~__umask;

/* set the file access modes correctly */
	iomode = iomode & ~O_SHMODE;

	if (__mint >= 9) {
		modemask = O_ACCMODE | O_SHMODE | O_SYNC | O_NDELAY;
		iomode |= (iomode & O_EXCL) ? O_DENYRW : O_DENYNONE;
	} else {
		modemask = O_ACCMODE;
	}

	if(Fattrib(filename, 0, 0) >= 0)		/* file exists */
	{
		if((iomode & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
			errno = EEXIST;
			return -1;
		}
		if(iomode & O_TRUNC)
			rv = (int)Fcreate(filename, 0x00);
		else
			rv = (int)Fopen(filename,iomode & modemask);
	}
	else					/* file doesn't exist */
	{
		if(iomode & O_CREAT) {
			rv = (int)Fcreate(filename, 0x00);
			if (rv >= 0 && __mint >= 9)
				(void)Fchmod(filename, pmode);
		}
		else
			rv = -ENOENT;
	}

	if((rv >= 0) && (iomode & O_APPEND))
		(void)lseek(rv, 0L, SEEK_END);

	if(rv < (__SMALLEST_VALID_HANDLE)) {
		errno = -rv;
		return __SMALLEST_VALID_HANDLE - 1;
	}

	(void)isatty(rv);	/* sets up tty flags under TOS */

	return(rv);
}

int
creat(name, mode)
	const char *name;
	unsigned   mode;
{
	return open(name, O_WRONLY|O_CREAT|O_TRUNC, mode);
}

/* umask -- change default file creation mask */

int umask(complmode)
       int complmode;
{
	int old_umask;

	if (__umask == -1)
		_get_umask();
	old_umask = __umask;
	__umask = complmode;
	if (__mint >= 9)
		return Pumask(complmode);
	return old_umask;
}
