E x c e r c i s e 8 − 1 Excercise\quad 8-1 Excercise8−1:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
enum fileDescriptors {
STDIN, STDOUT, STDERR };
void filecopy(int src, int dst);
void error(char *fmt, ...);
int main(int argc, char *argv[])
{
int f;
/* no args; copy standard input to output */
if (argc == 1)
{
filecopy(STDIN, STDOUT);
}
else
{
while (--argc > 0)
{
if ((f = open(*++argv, O_RDONLY, 0)) == -1)
{
error("can't open %s", *--argv);
}
else
{
filecopy(f, STDOUT);
/* close the file since finished reading it */
close(f);
}
}
}
exit(0);
}
/* copy src to dst */
void filecopy(int src, int dst)
{
int n;
char buf[BUFSIZ];
while ((n = read(src, buf, BUFSIZ)) > 0)
if (write(dst, buf, n) != n)
error("unable to copy src to dst");
}
/* print an error message and die */
void error(char *fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "error: ");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(1);
}
E x c e r c i s e 8 − 2 Excercise\quad 8-2 Excercise8−2:
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef NULL
#undef NULL
#endif
typedef struct _iobuf
{
int cnt; /* characters left */
char *ptr; /* next character position */
char *base; /* location of buffer */
struct flags /* mode of file access field struct */
{
unsigned int _READ : 1; /* file open for reading */
unsigned int _WRITE : 1; /* file open for writing */
unsigned int _UNBUF : 1; /* file is unbuffered */
unsigned int _EOF : 1; /* EOF has occurred on this file */
unsigned int _ERR : 1; /* error occurred on this file */
} _flags;
int fd; /* file descriptor */
} FILE;
#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
/* max #files open at once */
#define OPEN_MAX 20
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
extern FILE _iob[OPEN_MAX];
int _fillbuf(FILE *fp);
int _flushbuf(int, FILE *);
#define feof(p) ((p)->_flags._EOF != 0)
#define ferror(p) ((p)->_flags._ERR != 0)
#define fileno(p) ((p)->fd)
#define getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : _fillbuf(p))
#define putc(x, p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : _flushbuf((x), p))
#define getchar() getc(stdin)
#define putchar(x) putc((x), stdout)
#define PERMS 0666 /* RW for owner, group, others */
/* stdin, stdout, stderr */
FILE _iob[OPEN_MAX] =
{
{
0, (char *) 0, (char *) 0, {
._READ = 1 }, 0 },
{
0, (char *) 0, (char *) 0, {
._WRITE = 1 }, 1 },
{
0, (char *) 0, (char *) 0, {
._WRITE = 1, ._UNBUF = 1 }, 2 }
};
FILE *fopen(char *name, char *mode);
int main()
{
int c;
/* read until end and then exit for testing purposes */
while ((c = getchar()) != EOF);
exit(0);
}
/* open file, return file ptr */
FILE *fopen(char *name, char *mode)
{
int fd;
FILE *fp;
if (*mode != 'r' && *mode != 'w' && *mode != 'a')
return NULL;
for (fp = _iob; fp < _iob + OPEN_MAX; fp++)
{
/* if both flags are zero */
if (fp->_flags._READ == 0 && fp->_flags._WRITE == 0)
break;
}
/* no free slots */
if (fp >= _iob + OPEN_MAX)
return NULL;
if (*mode == 'w')
fd = creat(name, PERMS);
else if (*mode == 'a')
{
if ((fd = open(name, O_WRONLY, 0)) == -1)
fd = creat(name, PERMS);
lseek(fd, 0L, 2);
}
else
fd = open(name, O_RDONLY, 0);
/* couldn't access name */
if (fd == -1)
return NULL;
fp->fd = fd;
fp->cnt = 0;
fp->base = NULL;
fp->_flags._READ = fp->_flags._WRITE = fp->_flags._UNBUF = fp->_flags._EOF = fp->_flags._ERR = 0;
if (*mode == 'r')
fp->_flags._READ = 1;
else
fp->_flags._WRITE = 1;
return fp;
}
/* allocate and fill input buffer */
int _fillbuf(FILE *fp)
{
int bufsize;
if (fp->_flags._READ == 0 || fp->_flags._EOF == 1 || fp->_flags._ERR == 1)
return EOF;
bufsize = (fp->_flags._UNBUF == 1) ? 1 : BUFSIZ;
if (fp->base == NULL) /* no buffer yet */
if ((fp->base = (char *) malloc(bufsize)) == NULL)
return EOF; /* can't get buffer */
fp->ptr = fp->base;
fp->cnt = read(fp->fd, fp->ptr, bufsize);
if (--fp->cnt < 0)
{
if (fp->cnt == -1)
fp->_flags._EOF = 1;
else
fp->_flags._ERR = 1;
fp->cnt = 0;
return EOF;
}
return (unsigned char) *fp->ptr++;
}
E x c e r c i s e 8 − 3 Excercise\quad 8-3 Excercise8−3:
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#ifdef NULL
#undef NULL
#endif
typedef struct _iobuf
{
int cnt; /* characters left */
char *ptr; /* next character position */
char *base; /* location of buffer */
int flag; /* mode of file access */
int fd; /* file descriptor */
} FILE;
enum _flags {
_READ = 01, /* file open for reading */
_WRITE = 02, /* file open for writing */
_UNBUF = 04, /* file is unbuffered */
_EOF = 010, /* EOF has occurred on this file */
_ERR = 020 /* error occurred on this file */
};
#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20 /* max #files open at once */
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
extern FILE _iob[OPEN_MAX];
int _fillbuf(FILE *fp);
int _flushbuf(int c, FILE *fp);
void error(char *msg);
#define feof(p) (((p)->flag & _EOF) == _EOF)
#define ferror(p) (((p)->flag & _ERR) == _ERR)
#define fileno(p) ((p)->fd)
#define getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : _fillbuf(p))
#define putc(x, p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : _flushbuf((x), p))
#define getchar() getc(stdin)
#define putchar(x) putc((x), stdout)
#define PERMS 0666 /* RW for owner, group, others */
#define MAXERRORMSG 1000
/* stdin, stdout, stderr */
FILE _iob[OPEN_MAX] =
{
{
0, (char *) 0, (char *) 0, _READ, 0 },
{
0, (char *) 0, (char *) 0, _WRITE, 1 },
{
0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2 }
};
FILE *fopen(char *name, char *mode);
int fflush(FILE *fp);
int fclose(FILE *fp);
int main(int argc, char *argv[])
{
int c;
char msg[MAXERRORMSG];
/* fpOut == stdout for usage 1 and 2 */
FILE *fpIn, *fpOut = stdout;
if (argc == 1) /* read from stdin and write to stdout */
fpIn = stdin;
else if (argc == 2) /* read from file and write to stdout */
{
if ((fpIn = fopen(*++argv, "r")) == NULL)
error(strcat(strcat(msg, "error: couldn't open file "), *argv));
}
else if (argc == 3) /* read from file1 and write to file2 */
{
if ((fpIn = fopen(*++argv, "r")</