⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stdio.c

📁 TCP_IPprotocol.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Standard I/O routines with socket support
 * Replaces those in Borland C++ library
 */
#include <string.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define __IN_OPEN	1	/* Less stringent open() proto in io.h */
#include <io.h>
#include "global.h"
#include "stdio.h"
#include "mbuf.h"
#include "proc.h"
#include "usock.h"
#include "socket.h"
#include "display.h"
#include "asy.h"

#define	_CREAT(a,b)	_creat((a),(b))
#define _OPEN(a,b)	_open((a),(b))
#define	_CLOSE(a)	_close((a))
#define	_READ(a,b,c)	_read((a),(b),(c))
#define	_WRITE(a,b,c)	_write((a),(b),(c))
#define	_LSEEK(a,b,c)	_lseek((a),(b),(c))
#define	_DUP(a)		dup((a))

long _lseek(int fd,long offset,int whence);

static void _fclose(FILE *fp);
static struct mbuf *_fillbuf(FILE *fp,int cnt);
static FILE *_fcreat(void);

FILE *_Files;
int _clrtmp = 1;
extern unsigned *Refcnt;

/* Open a file and associate it with a (possibly specified) stream */
FILE *
freopen(
char *filename,
char *mode,
FILE *fp
){
	int modef;
	int textmode = 0;
	int create = 0;
	int append = 0;
	int fd;
	struct stat statbuf;

	if(strchr(mode,'r') != NULL){
		modef = O_RDONLY;
	} else if(strchr(mode,'w') != NULL){
		create = 1;
		modef = O_WRONLY;
	} else if(strchr(mode,'a') != NULL){
		modef = O_WRONLY;
		append = 1;
		if(stat(filename,&statbuf) == -1 && errno == ENOENT)
			create = 1;	/* Doesn't exist, so create */
	} else
		return NULL;	/* No recognizable mode! */

	if(strchr(mode,'+') != NULL)
		modef = O_RDWR;	/* Update implies R/W */

	if(strchr(mode,'t') != NULL)
		textmode = 1;
	
	if(create)
		fd = _CREAT(filename,S_IREAD|S_IWRITE);
	else
		fd = _OPEN(filename,modef);
	if(fd == -1)
		return NULL;

	if(fp != NULL){
		_fclose(fp);
	} else {
		if((fp = _fcreat()) == NULL){
			_CLOSE(fd);
			if(create)
				unlink(filename);
			return NULL;
		}
	}
	fp->fd = fd;
	fp->offset = 0;
	fp->type = _FL_FILE;
	fp->bufmode = _IOFBF;
	fp->ptr = strdup(filename);
	fp->flags.ascii = textmode;
	fp->flags.append = append;
	fp->bufsize = BUFSIZ;
	seteol(fp,Eol);
	return fp;
}
/* Associate a file or socket descripter (small integer) with a stream */
FILE *
fdopen(
int handle,
char *mode
){
	FILE *fp;
	int textmode = 0;
	int append = 0;

	if(handle == -1)
		return NULL;

	if(strchr(mode,'a') != NULL)
		append = 1;

	if(strchr(mode,'t') != NULL)
		textmode = 1;
	
	if((fp = _fcreat()) == NULL)
		return NULL;

	fp->fd = handle;
	fp->bufmode = _IOFBF;
	fp->type = _fd_type(handle);
	fp->flags.ascii = textmode;
	fp->flags.append = append;

	fp->bufsize = BUFSIZ;
	/* set default eol sequence, can be overridden by user */
	switch(fp->type){
	case _FL_SOCK:
		seteol(fp,eolseq(handle));	/* Socket eol seq */
		break;
	case _FL_FILE:
		seteol(fp,Eol);	/* System end-of-line sequence */
		break;
	}
	fp->refcnt = 1;

	return fp;
}
/* Create a stream in pipe mode (whatever is written can be
 * read back). These always work in binary mode.
 */
FILE *
pipeopen(void)
{
	FILE *fp;

	if((fp = _fcreat()) == NULL)
		return NULL;

	fp->fd = -1;
	fp->type = _FL_PIPE;
	fp->bufmode = _IOFBF;
	fp->bufsize = BUFSIZ;

	strcpy(fp->eol,"\r\n");
	return fp;
}
/* Open an asynch port for direct I/O. This must have already been attached
 * as a NOS interface. All packet-mode I/O is suspended until this stream
 * is closed.
 */
FILE *
asyopen(
char *name,	/* Name of interface */
char *mode	/* Usual fopen-style mode (used only for text/binary) */
){
	FILE *fp;
	int dev;
	int textmode = 0;

	if((dev = asy_open(name)) == -1)
		return NULL;
	if((fp = _fcreat()) == NULL)
		return NULL;

	if(strchr(mode,'t') != NULL)
		textmode = 1;

	fp->fd = dev;
	fp->type = _FL_ASY;
	fp->bufmode = _IOFBF;
	fp->flags.ascii = textmode;

	fp->bufsize = BUFSIZ;
	strcpy(fp->eol,"\r\n");
	return fp;
}
/* Create a new display screen and associate it with a stream. */
FILE *
displayopen(
char *mode,
int noscrol,
int sfsize
){
	FILE *fp;
	int textmode = 0;

	if(strchr(mode,'t') != NULL)
		textmode = 1;

	if((fp = _fcreat()) == NULL)
		return NULL;

	fp->fd = -1;
	fp->type = _FL_DISPLAY;
	fp->bufmode = _IOFBF;
	fp->flags.ascii = textmode;

	fp->ptr = newdisplay(0,0,noscrol,sfsize);
	fp->bufsize = BUFSIZ;
	strcpy(fp->eol,"\r\n");
	return fp;
}


/* Read string from stdin into buf until newline, which is not retained */
char *
gets(char *s)
{
	int c;
	char *cp;

	cp = s;
	for(;;){
		if((c = getc(stdin)) == EOF)
			return NULL;

		if(c == '\n')
			break;

		if(s != NULL)
			*cp++ = c;
	}
	if(s != NULL)
		*cp = '\0';
	return s;
}

/* Read a line from a stream into a buffer, retaining newline */
char *
fgets(
char *buf,	/* User buffer */
int len,	/* Length of buffer */
FILE *fp	/* Input stream */
){
	int c;
	char *cp;

	cp = buf;
	while(len-- > 1){	/* Allow room for the terminal null */
		if((c = getc(fp)) == EOF){
			return NULL;
		}
		if(buf != NULL)
			*cp++ = c;
		if(c == '\n')
			break;
	}
	if(buf != NULL)
		*cp = '\0';
	return buf;
}

/* Do printf on a stream */
int
fprintf(FILE *fp,char *fmt,...)
{
	va_list args;
	int len;

	va_start(args,fmt);
	len = vfprintf(fp,fmt,args);
	va_end(args);
	return len;
}
/* Printf on standard output stream */
int
printf(char *fmt,...)
{
	va_list args;
	int len;

	va_start(args,fmt);
	len = vfprintf(stdout,fmt,args);
	va_end(args);
	return len;
}
/* The guts of printf, uses variable arg version of sprintf */
int
vprintf(char *fmt, va_list args)
{
	return vfprintf(stdout,fmt,args);
}

/* There's a more efficient version of vfprintf() in vfprintf.c
 * that avoids the malloc(BUFSIZ) call by calling the internal 
 * Borland __vprinter() function directly.
 */
#ifndef	__TURBOC__
/* The guts of printf, uses variable arg version of sprintf */
int
vfprintf(FILE *fp,char *fmt, va_list args)
{
	int len,cnt,withargs;
	char *buf;

	if(fp == NULL || fp->cookie != _COOKIE)
		return -1;
	if(strchr(fmt,'%') == NULL){
		/* Common case optimization: no args, so we don't
		 * need vsprintf()
		 */
		withargs = 0;
		buf = fmt;
	} else {
		/* Use a default value that is hopefully longer than the
		 * biggest output string we'll ever print (!)
		 */
		withargs = 1;
		buf = mallocw(BUFSIZ);
		vsprintf(buf,fmt,args);
	}
	len = strlen(buf);
	cnt = fwrite(buf,1,len,fp);
	if(cnt != len)
		cnt = -1;
	if(withargs)
		free(buf);
	return cnt;
}
#endif	/* __TURBOC__ */
/* put a char to a stream */ 
int
fputc(int c,FILE *fp)
{
	int nbytes;
	struct mbuf *bp;
	int eol;

	if(c == '\n' && fp->flags.ascii){
		nbytes = strlen(fp->eol);
		eol = 1;
	} else {
		nbytes = 1;
		eol = 0;
	}
	bp = fp->obuf;
	if(bp != NULL && bp->size - bp->cnt < nbytes && fflush(fp) == EOF)
		return EOF;
	if(fp->obuf == NULL)
		fp->obuf = ambufw(max(nbytes,fp->bufsize));

	bp = fp->obuf;
	if(eol)
		memcpy(&bp->data[bp->cnt],fp->eol,nbytes);
	else
		bp->data[bp->cnt] = c;
	bp->cnt += nbytes;

	if(bp->cnt == bp->size || (fp->bufmode == _IONBF)
	 || ((fp->bufmode == _IOLBF) && eol)){
		if(fflush(fp) == EOF)
			return EOF;
	}
	return c;
}
/* put a string to a stream */
int
fputs(char *buf,FILE *fp)
{
	int cnt,len;

	len = strlen(buf);
	cnt = fwrite(buf,1,len,fp);
	if(cnt != len)
		return EOF;
	return buf[len-1];
}

/* Put a string to standard output */
int
puts(char *s)
{
	if(fputs(s,stdout) == EOF)
		return EOF;
	putchar('\n');
	return 1;
}

/* Read a character from the stream */
int
fgetc(FILE *fp)
{
	int c;

	if(fp == NULL || fp->cookie != _COOKIE)
		return EOF;
	c = _fgetc(fp);
	if(!fp->flags.ascii || c == EOF || c != fp->eol[0])
		return c;
	/* First char of newline sequence encountered */
	if(fp->eol[1] == '\0')
		return '\n';	/* Translate 1-char eol sequence */
	/* Try to read next input character */
	if((c = _fgetc(fp)) == EOF)
		return fp->eol[0];	/* Got a better idea? */
	if(c == fp->eol[1]){
		/* Translate two-character eol sequence into newline */
		return '\n';
	} else {
		/* CR-NUL sequence on Internet -> bare CR (kludge?) */
		if(c != '\0')
			ungetc(c,fp);
		/* Otherwise return first char unchanged */
		return fp->eol[0];
	}
}
/* Read a character from a stream without newline processing */
int
_fgetc(FILE *fp)
{
	struct mbuf *bp;

	if(fp == NULL || fp->cookie != _COOKIE)
		return EOF;
	fflush(fp);
	if((bp = fp->ibuf) == NULL || bp->cnt == 0)
		if(_fillbuf(fp,1) == NULL)
			return EOF;
	if(fp->type == _FL_PIPE)
		ksignal(&fp->obuf,1);
	return PULLCHAR(&fp->ibuf);
}

/* Flush output on a stream. All actual output is done here. */
int
fflush(FILE *fp)
{
	struct mbuf *bp;
	int cnt;

	if(fp == NULL || fp->cookie != _COOKIE){
		flushall();
		return 0;
	}
	if(fp->obuf == NULL)
		return 0;	/* Nothing to do */

	bp = fp->obuf;
	fp->obuf = NULL;
	switch(fp->type){
	case _FL_ASY:
		while(bp != NULL){
			asy_write(fp->fd,bp->data,bp->cnt);
			bp = free_mbuf(&bp);
		}
		return 0;		
	case _FL_PIPE:
		append(&fp->ibuf,&bp);
		ksignal(&fp->ibuf,1);
		while(len_p(fp->ibuf) >= BUFSIZ)
			kwait(&fp->obuf);	/* Hold at hiwat mark */	
		return 0;
	case _FL_SOCK:
		return send_mbuf(fp->fd,&bp,0,NULL,0);
	case _FL_FILE:
		do {
			if(fp->flags.append)
				_LSEEK(fp->fd,0L,SEEK_END);
			else
				_LSEEK(fp->fd,fp->offset,SEEK_SET);
			cnt = _WRITE(fp->fd,bp->data,bp->cnt);
			if(cnt > 0)
				fp->offset += cnt;
			if(cnt != bp->cnt){
				fp->flags.err = 1;
				free_p(&bp);
				return EOF;
			}
			bp = free_mbuf(&bp);
		} while(bp != NULL);
		return 0;
	case _FL_DISPLAY:
		do {
			displaywrite(fp->ptr,bp->data,bp->cnt);
			bp = free_mbuf(&bp);
		} while(bp != NULL);
		return 0;
	}
	return 0;	/* Can't happen */
}

/* Set the end-of-line sequence on a stream */
int
seteol(FILE *fp,char *seq)
{
	if(fp == NULL || fp->cookie != _COOKIE)
		return -1;
	if(seq != NULL)
		strncpy(fp->eol,seq,sizeof(fp->eol));
	else
		*fp->eol = '\0';
	return 0;
}
/* Enable/disable eol translation, return previous state */
int
fmode(FILE *fp,int mode)
{
	int prev;

	if(fp == NULL || fp->cookie != _COOKIE)
		return -1;
	fflush(fp);
	prev = fp->flags.ascii;
	fp->flags.ascii = mode;
	return prev;
}
/* Control blocking behavior for fread on network, pipe and asy streams */
int
fblock(FILE *fp,int mode)
{
	int prev;

	if(fp == NULL || fp->cookie != _COOKIE)
		return -1;
	prev = fp->flags.partread;
	fp->flags.partread = mode;
	return prev;
}

int
fclose(FILE *fp)
{
	if(fp == NULL || fp->cookie != _COOKIE){
		return -1;
	}
	if(--fp->refcnt != 0)
		return 0;	/* Others are still using it */
	_fclose(fp);
	if(fp->prev != NULL)
		fp->prev->next = fp->next;
	else
		_Files = fp->next;

	if(fp->next != NULL)
		fp->next->prev = fp->prev;
	free(fp);
	return 0;
}
int
fseek(
FILE *fp,
long offset,
int whence
){
	struct stat statbuf;

	if(fp == NULL || fp->cookie != _COOKIE || fp->type != _FL_FILE){
		errno = EINVAL;
		return -1;
	}
	/* Optimize for do-nothing seek */ 
#ifdef	notdef
	if(whence == SEEK_SET && fp->offset == offset)
		return 0;
#endif
	fflush(fp);	/* Flush output buffer */
	/* On relative seeks, adjust for data in input buffer */
	switch(whence){
	case SEEK_SET:
		fp->offset = offset;	/* Absolute seek */
		break;
	case SEEK_CUR:
		/* Relative seek, adjusting for buffered data */
		fp->offset += offset - len_p(fp->ibuf);
		break;
	case SEEK_END:
		/* Find out how big the file currently is */
		if(fstat(fp->fd,&statbuf) == -1)
			return -1;	/* "Can't happen" */
		fp->offset = statbuf.st_size + offset;
		break;
	}
	/* Toss input buffer */
	free_p(&fp->ibuf);
	fp->ibuf = NULL;
	fp->flags.eof = 0;
	return 0;
}
long
ftell(FILE *fp)
{
	if(fp == NULL || fp->cookie != _COOKIE || fp->type != _FL_FILE)
		return -1;
	fflush(fp);
	return fp->offset - len_p(fp->ibuf);
}

int
ungetc(int c,FILE *fp)
{
	if(fp == NULL || fp->cookie != _COOKIE)
		return -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -