/* cat.c -- provides a routine to output the contents of the named files in either a buffered or unbuffered fashion. */ /* Accepts the following parameters: */ /* -u: Output should be unbuffered. */ /* Returns the following values: */ /* 0: All files were printed successfully. */ /* 1: One or more files could not be opened. */ #include "common.h" /* If mode is set to zero, return a null pointer and print characters directly. Otherwise, return a pointer to a buffer containing */ /* the contents of the file pointed to by fp. */ char *cat(FILE *fp, const int mode) { char c; if(!mode) { int i, buflen; buflen = 4096; char *arr = malloc(4096); char *newarr = 0; for(i = 0; (c = fgetc(fp)) != EOF; i++) { /* Rewrite using memcpy? */ if(i >= buflen) { buflen *= 2; newarr = malloc(buflen); strcpy(newarr, arr); free(arr); arr = newarr; } arr[i] = c; } arr[i] = '\0'; return arr; } else { for(;(c = fgetc(fp)) != EOF;) { putchar(c); } } return NULL; } int main(int argc, char **argv) { char *buf, *newbuf, *tmpbuf; int i, upresence, fppresence; i = upresence = fppresence = 0; long unsigned int buflen; buflen = 4096; FILE *fp; fp = 0; buf = malloc(buflen); if((upresence = (getopt(argc, argv, ":u") == 'u'))) { i++; } for(i++;argv[i] != NULL; i++) { if(!strcmp(argv[i], "-")) { fppresence++; newbuf = cat(stdin, upresence); } else if((fp = fopen(argv[i], "r")) != NULL) { fppresence++; newbuf = cat(fp, upresence); } else { fprintf(stderr, "%s: failed to open %s. Aborting.\n", argv[0], argv[i]); exit(1); } if(!upresence and (2 * (strlen(buf) + strlen(newbuf)) >= buflen)) { /* Rewrite this bit to use realloc and/or memcpy? */ tmpbuf = malloc(2 * (strlen(buf) + strlen(newbuf))); strcpy(tmpbuf, buf); free(buf); buf = tmpbuf; } if(!upresence) { strcat(buf, newbuf); } } if(!fppresence) { buf = cat(stdin, upresence); } if(!upresence) { printf("%s", buf); } exit(0); }