aboutsummaryrefslogblamecommitdiff
path: root/8.4/stdio.c
blob: 57b90baf92bea65ab4b59103df3a3f15f3e8c729 (plain) (tree)































































































































































                                                          
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "stdio.h"

#define PERMS 0666

FILE _iob[OPN_MAX] = {
	{0, NULL, NULL, _READ, 0},
	{0, NULL, NULL, _WRITE, 1},
	{0, NULL, NULL, _WRITE | _UNBUF, 2}
};

FILE *fopen(char *name, char *mode)
{
	FILE *fp;

	if (*mode != 'r' && *mode != 'w' && *mode != 'a')
		return NULL;
	
	for(fp = _iob; fp < _iob + OPN_MAX; ++fp)
		if (!(fp->flag & (_READ | _WRITE)))
			break;
	if (fp == _iob + OPN_MAX)
		return NULL;

	if (*mode == 'w') {
		fp->fd = open(name, O_WRONLY);
	} else if (*mode == 'a') {
		if ((fp->fd = open(name, O_WRONLY)) == -1)
			fp->fd = creat(name, PERMS);
		lseek(fp->fd, 0L, 2);
	} else {
		fp->fd = open(name, O_RDONLY);
	}

	if (fp->fd == -1) {
		fp->fd = 0;
		return NULL;
	}

	fp->base = fp->ptr = NULL;
	fp->flag = (*mode == 'r') ? _READ : _WRITE;
	fp->cnt = 0;

	return fp;
}

int _fillbuf(FILE *fp)
{
	int bufsize;

	if ((fp->flag & (_READ | _EOF | _ERR)) != _READ)
		return EOF;

	bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ;
	if (fp->base == NULL)
		if ((fp->base = malloc(bufsize)) == NULL)
			return EOF;
	fp->ptr = fp->base;

	fp->cnt = read(fp->fd, fp->base, bufsize);
	if (--fp->cnt < 0) {
		if (fp->cnt == -1)
			fp->flag = _EOF;
		else // fp->cnt == -2
			fp->flag = _ERR;
		fp->cnt = 0;
		return EOF;
	}

	return (unsigned char) *fp->ptr++;
}

int _flushbuf(int c, FILE *fp)
{
	int bufsize, nc;

	if ((fp->flag & (_WRITE | _ERR)) != _WRITE)
		return EOF;

	bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ;
	if (fp->base == NULL) {
		if ((fp->base = malloc(bufsize)) == NULL)
			return EOF;
	} else {
		nc = fp->ptr - fp->base;
		if (write(fp->fd, fp->base, nc) != nc) {
			fp->flag = _ERR;
			return EOF;
		}
	}

	fp->ptr = fp->base;
	fp->cnt = bufsize - 1;
	*fp->ptr++ = c;

	return (unsigned char) c;
}

int fflush(FILE *fp)
{
	int rc = 0;

	if (fp < _iob && fp >= _iob + OPN_MAX)
		return EOF;
	if (fp->flag & _WRITE)
		rc = _flushbuf(0, fp);

	fp->ptr = fp->base;
	fp->cnt = (fp->flag & _UNBUF) ? 1 : BUFSIZ;

	return rc;
}


int fclose(FILE *fp)
{
	int rc;

	if ((rc = fflush(fp)) != EOF) {
		free(fp->base);
		fp->base = fp->ptr = NULL;
		fp->flag &= ~(_READ | _WRITE);
		fp->cnt = 0;
		close(fp->fd);
	}

	return rc;
}

int fseek(FILE *fp, ssize_t os, int origin)
{
	int rc = 0;

	if (fp < _iob && fp >= _iob + OPN_MAX)
		return EOF;

	if (fp->flag & _READ) {
		if (os == SEEK_CUR)
			os -= fp->cnt;
		rc = lseek(fp->fd, os, origin);
		fp->cnt = 0;
	} else if (fp->flag & _WRITE) {
		if ((rc = fflush(fp)) != EOF)
			rc = lseek(fp->fd, os, origin);
	}

	return (rc == -1) ? -1 : 0;
}

int puts(const char *s)
{
	while (*s)
		if (putchar(*s++) == EOF)
			return EOF;
	fflush(stdout);

	return 1;
}