catsys.c

/*
 * catsys.c -- a program to print a file twice
 * This demonstrates the use of file descriptors
 *
 * Matt Bishop, ECS 30 (now 36A)
 * -- November 9, 1996	original version
 * -- May 30, 2024	minor change to quiet strlen warning
 */
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

/*
 * macros
 */
#define BUFSIZ	1024	/* size of buffer for file I/O */

/*
 * forward declarations
 */
void perror(char *);	/* print system error message */

/*
 * print the file with the given file descriptor
 * returns 0 on success, -1 on error
 * does not print any error message
 */
int cat(int fd)
{
	register int n;		/* number of bytes read */
	char buf[BUFSIZ];	/* buffer for file I/O */

	/*
	 * grab BUFSIZ bytes and dump them to
	 * the standard output
	 */
	while((n = read(fd, buf, BUFSIZ)) > 0)
		/* if error, end this function at once */
		if (write(1, buf, n) != n)
			return(-1);

	/* if read failed, return error; else okay */
	return(n < 0 ? -1 : 0);
}

/*
 * print the named file twice
 * returns 0 on success, 1 on error
 * prints system error message if there is a problem
 */
int twocat(char *name)
{
	register int fd;		/* file's descriptor */
	register int retval = 0;	/* value to return */

	/*
	 * open the file
	 */
	if ((fd = open(name, O_RDONLY)) < 0){
		perror(name);
		return(-1);
	}
	/*
	 * display the file, rewind it, and redisplay it
	 * if there's an error, print the system error
	 * message and quit
	 */
	if (cat(fd) < 0 || lseek(fd, 0L, SEEK_SET) != 0 || cat(fd) < 0){
		perror(name);
		retval = 1;
	}
	/*
	 * close it up and return status
	 */
	(void) close(fd);
	return(retval);
}

/*
 * main routine
 */
int main(int argc, char *argv[])
{
	register int i;		/* counter in a for loop */
	register int estat = 0;	/* exit status */

	/*
	 * bad usage message
	 */
	if (argc == 1){
		(void) write(2, "Usage: ", strlen("Usage: "));
		(void) write(2, argv[0], strlen(argv[0]));
		(void) write(2, " file [ ... ]\n", strlen(" file [ ... ]\n"));
		return(1);
	}

	/*
	 * print each file twice as you go
	 */
	for(i = 1; i < argc; i++)
		estat += twocat(argv[i]);

	/*
	 * return number of failures
	 */
	return(estat);
}


UC Davis sigil
Matt Bishop
Office: 2209 Watershed Sciences
Phone: +1 (530) 752-8060
Email: [email protected]
ECS 36A, Programming & Problem Solving
Version of April 2, 2024 at 12:13PM

You can get the raw source code here.

Valid HTML 4.01 Transitional Built with BBEdit Built on a Macintosh