#include #include #include #include #include #include #include /*This is the main method for a C program to duplicate the behaviors of the * UNIX command "cat". * input: filenames to use cat on, and cat flags to use on files * output: the results of the requested cat call. * return: Type is int, value is 0 */ int main( int argc, char ** argv ) { /*count and tally are used to track iterations*/ int count=0; int tally=0; /*check is used to ensure certain blocks run on first iteration * only*/ int check=0; /*i and tmp are both used as holding variables to assign values onto * the array*/ int i=0; int tmp=1; /*file descriptor*/ int fd=0; /*used to track size of arrays*/ int size=0; int size2=0; /*stores number of cat flags entered at command line*/ int num_flags=0; /*arr holds all of the data read from file(s)*/ char * arr = (char *)malloc( sizeof( char )); /*holds each flag entered*/ char * flag = (char *)malloc( sizeof( char )); /*array utilized when reading more than one file*/ char * buf = (char *)malloc( sizeof( char )); /*if else block to process filename and flags (if applicable) * entered at command line. If no flags were specified, first if * block triggers to open file only. If flags were entered, else * block triggers to open file, and store each flag entered */ if (argv[2] == '\0') { /*opens file to read*/ fd = open(argv[1], O_RDONLY, 0); /*checks validity of file chosen, prints error message and exits if * unable to open */ if(fd==-1) { printf("Unable to open file!!!\n"); exit( 1 ); } /*this while loop reads the data from the file, and stores it * in the char array arr, runs while read does not return 0 */ while ( tmp != 0 ) { /*reads one char at a time from file*/ tmp = read( fd, &i, sizeof(char)); /*if block to check for read errors*/ if ( tmp < 0 ) { printf("read error!!!\n"); exit( 2 ); } /*increments size to track number of chars read*/ size+=tmp; /*dynamically grows arr to new size*/ arr=(char *)realloc(arr, sizeof(char)*(size)); /*assigns last read value to arr*/ arr[tally] = i; /*increments tally to track position in array*/ tally++; } /*sets last value in array to null*/ arr[size-1]='\0'; } else { /*stores flags to flag array*/ if (argv[1][0] == '-') { /*stores flags entered into char array flag*/ while ( argv[1][count+1] != '\0' ) { flag[count]=argv[1][count+1]; count++; } /*int to track number of flags entered*/ num_flags = count; /*sets count to 2 so that next while block know what * position in array argv to check for file*/ count = 2; } else { /*sets count to 1 so that next while block know what * position in array argv to check for file*/ count=1; } /*this while loop opens and reads each file entered at command * line*/ while (count < argc) { /*opens file to read*/ fd = open(argv[count], O_RDONLY, 0); /*checks validity of file chosen, prints error message and exits if * unable to open */ if(fd==-1) { printf("Unable to open file!!!\n"); exit( 1 ); } /*if runs to store first file only, else stores each * additional file, and uses strcat to save that data to * arr*/ if ( check == 0 ) { /*this while loop reads the data from the file, and stores it * in the char array arr */ while ( tmp != 0 ) { /*reads from file*/ tmp = read( fd, &i, sizeof(char)); /*checks if read was successful*/ if ( tmp < 0 ) { printf("read error!!!\n"); exit( 2 ); } /*increments size*/ size+=tmp; /*dynamically grows array*/ arr=(char *)realloc(arr, sizeof(char)*(size)); /*assigns read value to arr*/ arr[tally] = i; /*increments tally*/ tally++; } /*sets check to 1 to stop this block from triggering * again*/ check = 1; /*resets tmp to 1*/ tmp = 1; } else { /*this while loop reads the data from the file, and stores it * in the char array arr */ while ( tmp != 0 ) { tmp = read( fd, &i, sizeof(char)); if ( tmp < 0 ) { printf("read error!!!\n"); exit( 2 ); } /*TODO - figure out wtf*/ size2+=tmp; size2++; buf=(char *)realloc(buf, sizeof(char)*(size2)); buf[0] = '\n'; buf[tally+1] = i; tally++; } /*changes size variable to size of arr + buf*/ size = size + size2; /*grows arr to new size*/ arr=(char *)realloc(arr, sizeof(char)*(size)); /*concatenates buf onto end of arr*/ strcat(arr, buf); } /*sets last value in array to null*/ arr[size-1]='\0'; /*resets tmp, size2, and tally. increments count*/ tmp=1; size2=0; tally=0; count++; /*free the file descriptor*/ close(fd); } } /*these three blocks change the A, e, and t flags to -vET, -vE, and * -vT respectively*/ if (flag[0] == 'A') { flag=(char *)realloc(flag, sizeof(char)*(3)); flag[0]='v'; flag[1]='E'; flag[2]='T'; num_flags = 3; } else if (flag[0] == 'e') { flag=(char *)realloc(flag, sizeof(char)*(2)); flag[0]='v'; flag[1]='E'; num_flags = 2; } else if (flag[0] == 't') { flag=(char *)realloc(flag, sizeof(char)*(2)); flag[0]='v'; flag[1]='T'; num_flags = 2; } /*This block processes info from file and formats it accordingly * based on flags entered */ for( count = 0 ; count < num_flags ; count++ ) { /*this switch structures performs the format operations on the * array based on the flag/s entered */ switch(flag[count]) { /*duplicates -E flag*/ case 'E': /*loop processes arr char by char*/ do { /*searches arrary for \n, then shifts array values * up by 1 and adds the $ when a \n is found*/ if(arr[tally]=='\n') { size += 1; arr=(char *)realloc(arr, sizeof(char)*(size)); for (i=size-2 ; i>=tally ; --i) { arr[i+1]=arr[i]; } arr[tally]='$'; tally++; } tally++; } while(arr[tally] != '\0'); /*adds a $ to the end of the last line*/ if (arr[size-2] != '$') { size+=1; arr=(char *)realloc(arr, sizeof(char)*(size)); arr[size-2]='$'; arr[size-1]='\0'; } break; case 'T': do { /*checks each value to see if it is a \t and shifts * all elements up one, and inserts a ^ and an I in * the \t's place*/ if(arr[tally]=='\t') { size += 1; arr=(char *)realloc(arr, sizeof(char)*(size)); for (i=size-2 ; i>=tally ; --i) { arr[i+1]=arr[i]; } arr[tally]='^'; arr[tally+1]='I'; tally++; } tally++; } while(arr[tally] != '\0'); break; case 'b': /*sets initial value for i which will track current line * number*/ i=1; /*if block to number first line if it is non-blank*/ if( arr[0] != '\n' ) { /*this for loop handles growing the array to allow * the spaces and line numbers to be adding in*/ for ( tally = size+7 ; tally > 0 ; tally-- ) { /*resizes array on first run of of for loop*/ if ( tally == size+7 ) { size+=8; arr=(char *)realloc(arr, sizeof(char)*(size)); } /*shifts array values up*/ arr[tally] = arr[tally-8]; } /*inserts first line number if first line was not * \n*/ arr[0]=' '; arr[1]=' '; arr[2]=' '; arr[3]=' '; arr[4]=' '; arr[5]='1'; arr[6]=' '; arr[7]=' '; /*increments i so next line number will be 2*/ i++; } /*temporarily stores count's value in tmp, so count can * be used as a counting variable*/ tmp=count; /*this for loop walks through arr, and when it finds \n * it grows the array, shifts values and inserts line * number*/ for ( count = 0 ; count < size ; count++ ) { /*checks to see if line is blank*/ if (arr[count] == '\n' && arr[count+1] != '\n') { /*grows arr*/ size+=8; arr=(char *)realloc(arr, sizeof(char)*(size)); /*shifts values*/ for ( tally = size-1 ; tally-8 > count ; tally-- ) { arr[tally] = arr[tally-8]; } /*prints line number which is an int into a char * array*/ sprintf(buf, "%d", i); /*if/else block to push line numbers onto array * based on number of digits in line number*/ if ( i < 10 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=' '; arr[count+4]=' '; arr[count+5]=' '; arr[count+6]=buf[0]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 9 && i < 100 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=' '; arr[count+4]=' '; arr[count+5]=buf[0]; arr[count+6]=buf[1]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 99 && i < 1000 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=' '; arr[count+4]=buf[0]; arr[count+5]=buf[1]; arr[count+6]=buf[2]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 999 && i < 10000 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=buf[0]; arr[count+4]=buf[1]; arr[count+5]=buf[2]; arr[count+6]=buf[3]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 9999 && i < 100000 ) { arr[count+1]=' '; arr[count+2]=buf[0]; arr[count+3]=buf[1]; arr[count+4]=buf[2]; arr[count+5]=buf[3]; arr[count+6]=buf[4]; arr[count+7]=' '; arr[count+8]=' '; } else { arr[count+1]=buf[0]; arr[count+2]=buf[1]; arr[count+3]=buf[2]; arr[count+4]=buf[3]; arr[count+5]=buf[4]; arr[count+6]=buf[5]; arr[count+7]=' '; arr[count+8]=' '; } /*increments i*/ i++; } } /*sets count back to its previous value*/ count=tmp; break; case 'n': /*sets initial value for i*/ i=2; /*reallocs arr and shifts values*/ for ( tally = size+7 ; tally > 0 ; tally-- ) { if ( tally == size+7 ) { /*increment size to track number chars*/ size+=8; /*grows arr*/ arr=(char *)realloc(arr, sizeof(char)*(size)); } /*shifts values*/ arr[tally] = arr[tally-8]; } /*prints line number 1*/ arr[0]=' '; arr[1]=' '; arr[2]=' '; arr[3]=' '; arr[4]=' '; arr[5]='1'; arr[6]=' '; arr[7]=' '; /*stores count's value in tmp so count can be used as a * tracking variable*/ tmp=count; /*for loop to check each char to see if it is a \n*/ for ( count = 0 ; count < size ; count++ ) { /*when \n is found, line number will be printed*/ if (arr[count]=='\n') { /*grows size variable*/ size+=8; /*realloc's arr to new size*/ arr=(char *)realloc(arr, sizeof(char)*(size)); /*for loop to walk backwards through array to * shift values*/ for ( tally = size-1 ; tally-8 > count ; tally-- ) { arr[tally] = arr[tally-8]; } /*prints next line number value (an int) to char * array buf*/ sprintf(buf, "%d", i); /*if/else block to push line number value onto * arr based on number of digits in line number*/ if ( i < 10 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=' '; arr[count+4]=' '; arr[count+5]=' '; arr[count+6]=buf[0]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 9 && i < 100 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=' '; arr[count+4]=' '; arr[count+5]=buf[0]; arr[count+6]=buf[1]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 99 && i < 1000 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=' '; arr[count+4]=buf[0]; arr[count+5]=buf[1]; arr[count+6]=buf[2]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 999 && i < 10000 ) { arr[count+1]=' '; arr[count+2]=' '; arr[count+3]=buf[0]; arr[count+4]=buf[1]; arr[count+5]=buf[2]; arr[count+6]=buf[3]; arr[count+7]=' '; arr[count+8]=' '; } else if ( i > 9999 && i < 100000 ) { arr[count+1]=' '; arr[count+2]=buf[0]; arr[count+3]=buf[1]; arr[count+4]=buf[2]; arr[count+5]=buf[3]; arr[count+6]=buf[4]; arr[count+7]=' '; arr[count+8]=' '; } else { arr[count+1]=buf[0]; arr[count+2]=buf[1]; arr[count+3]=buf[2]; arr[count+4]=buf[3]; arr[count+5]=buf[4]; arr[count+6]=buf[5]; arr[count+7]=' '; arr[count+8]=' '; } /*increments i*/ i++; } } /*resets count to original value*/ count=tmp; break; case 's': /*checks each value in array to see if it is a \n, and * when it finds consecutive \n chars, it deletes third * \n if 3 are found in a row. Then shifts all values * down by one and checks if there are still 3 in a row*/ for ( tally = 0 ; tally < size-2 ; tally++ ) { if ( arr[tally] == '\n' && arr[tally+1] == '\n' && arr[tally+2] == '\n') { for (tmp = tally ; tmp < size-1 ; tmp++) { arr[tmp]=arr[tmp+1]; } tally--; size--; arr=(char *)realloc(arr, sizeof(char)*(size)); } } break; case 'v': /*PARDON OUR MESS!!! * We're sorry, but this cat flag is still under * construction, we hope it will be up soon! We apologize * for any inconvenience this may have caused!*/ break; } } /*writes the contents of the cat'd array to stdout*/ i = write(1, arr, size); printf("\n"); /*frees the memory from the 3 arrays*/ free(arr); free(flag); free(buf); return 0; }