/* 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. The size of the new buffer is stored in the int pointed to by bufsize. */ char *cat(FILE *fp, const int mode, long unsigned *bufsize) { char c; if(!mode) { static long unsigned int i, finalbuflen, tmpbuflen; tmpbuflen = 4096; char *arr = malloc(tmpbuflen); char *tmparr = 0; char *finalarr = 0; for(i = 0, finalbuflen = 0; (c = fgetc(fp)) != EOF; i++, finalbuflen++) { if(i >= tmpbuflen) { tmpbuflen *= 2; tmparr = malloc(tmpbuflen); memcpy(tmparr, arr, tmpbuflen/2); free(arr); arr = tmparr; } arr[i] = c; } finalarr = malloc(finalbuflen); memcpy(finalarr, arr, finalbuflen); free(arr); arr = finalarr; *bufsize = finalbuflen; return arr; } else { for(;(c = fgetc(fp)) != EOF;) { putchar(c); } } return NULL; } int main(int argc, char **argv) { char *buf, *newbuf, *tmpbuf; long unsigned int i, upresence, fppresence; i = upresence = fppresence = 0; long unsigned int buflen, newbuflen; buflen = newbuflen = 0; FILE *fp; fp = 0; buf = newbuf = tmpbuf = 0; if((upresence = (getopt(argc, argv, ":u") == 'u'))) { i++; } for(i++;argv[i] != NULL; i++) { if(!strcmp(argv[i], "-")) { fppresence++; newbuf = cat(fopen("/dev/stdin", "r"), upresence, &newbuflen); } else if((fp = fopen(argv[i], "r")) != NULL) { fppresence++; newbuf = cat(fp, upresence, &newbuflen); fclose(fp); } else { fprintf(stderr, "%s: failed to open %s. Aborting.\n", argv[0], argv[i]); exit(1); } /* This is where the actual magic happens. */ if(!upresence) { /* Here, we copy buf and newbuf end-to-end into a new buffer of size buflen+newbuflen, then store that in buflen and */ /* return a pointer to the new buffer. */ tmpbuf = arrccat(buf, newbuf, &buflen, newbuflen); free(buf); buf = tmpbuf; } } if(!fppresence) { buf = cat(fopen("/dev/stdin", "r"), upresence, &buflen); } if(!upresence) { for(i = 0; i < buflen; i++) { putchar(buf[i]); } } exit(0); }