#include #include #include #include #include #include #include void print_labels(int i,char* argv[i],int error){ //------------------------------------------------------------------------ // FUNCTION: print_labels(int i,char* argv[i],int error) // output the labels when we have more than 1 file // PARAMETERS: // int i - the current argument number // char* argv[i] - the filename // int error - if an error occured up to now //------------------------------------------------------------------------ char msg[1024] = "==> "; if(i >= 2 && error == 0) write(STDOUT_FILENO, "\n", 1); // adds new line if(*argv[i] == '-') argv[i] = "standart input"; // the output when we have - should be ==> stand. input <== int compare = strcmp(argv[i],"tester.txt"); // argv[i] ?= tester.txt if(compare != 0){ strcat(strcat(msg,argv[i])," <==\n"); // concatenate msg and argv[i] and the result to last string write(STDOUT_FILENO, msg, strlen(msg)); // output msg argv[i] = "tester.txt"; } } void close_error(int i,char* argv[i]){ //------------------------------------------------------------------------ // FUNCTION: close_error(int i,char* argv[i]) // output message on close error // PARAMETERS: // int i - the current argument number // char* argv[i] - the filename //------------------------------------------------------------------------ char msg[1024] = "tail: error reading '"; strcat(msg,argv[i]); // concatenate msg and argv[i] write(2, msg, strlen(msg)); //output msg perror("'"); // print perror } void read_error(int i,char* argv[i]){ //------------------------------------------------------------------------ // FUNCTION: read_error(int i,char* argv[i]) // output message on read error, which is the same as close error // PARAMETERS: // int i - the current argument number // char* argv[i] - the filename //------------------------------------------------------------------------ close_error(i,argv); } void open_error(int i,char* argv[i]){ //------------------------------------------------------------------------ // FUNCTION: open_error(int i,char* argv[i]) // output message on file open error // PARAMETERS: // int i - the current argument number // char* argv[i] - the filename //------------------------------------------------------------------------ char msg[1024] = "tail: cannot open '"; strcat(strcat(msg,argv[i]),"' for ");// concatenate msg and argv[i] write(2, msg, strlen(msg)); // output msg perror("reading"); // print perror } void standart_read(int fd){ //------------------------------------------------------------------------ // FUNCTION: standart_read(int fd) // read from the terminal and write the input to a file // PARAMETERS: // int fd - the file descriptor //------------------------------------------------------------------------ char data[10]; while(read(0,data,1) != 0){ // 0 indicated EOF for(size_t i = 0,len =1; i< len;i++){ size_t wres = write(fd,data+i,1); if(wres < 0) break; // output else if(wres == 0) write(fd,data+i,1); } } } int file_output(int count,char *buff, int fd){ //------------------------------------------------------------------------ // FUNCTION: file_output(int count,char *buff, int fd) // read from the terminal and write the input to a file // PARAMETERS: // int fd - the file descriptor // int count - number of bytes to be written // char* buff - the buffer for read and write //------------------------------------------------------------------------ count *= -1; // get abs value of bytes while(count--){ ssize_t wres = write(STDOUT_FILENO,buff,read(fd, buff,1)); // output file content if(wres == 0){ do{ wres = write(STDOUT_FILENO,buff,1); }while(wres==0); } if(wres < 0) { perror("tail: error writing 'standard output'"); // output error return -1; } } return 0; } int go_to_tenth_line(int fd,int i, char* argv[]){ //------------------------------------------------------------------------ // FUNCTION: go_to_tenth_line(int fd,int i, char* argv[]){ // move with lseek to the 10th \n from down to up // PARAMETERS: // int fd - the file descriptor // int i - the current argument number // char* argv[i] - the filename //------------------------------------------------------------------------ int count,line_count = 10; ssize_t rres; char buff[1]; off_t offset; // go to 10th line from downward for(count = -1;line_count != 0;count--){ offset = lseek(fd, count, SEEK_END); // go to current byte if(offset == -1) break; // error occured if(count != 0) rres = read(fd,buff,1); // read one byte if(rres < 0){ read_error(i,argv); // output read error return 1; // error } if(*buff =='\n') if(count != -1) line_count--; // if found new line char, update how much lines are left } if (*buff != '\n') write(STDOUT_FILENO, buff, 1); // add last char if file is less than 10 lines return count; } int standart_input(int i, char* argv[i]){ //------------------------------------------------------------------------ // FUNCTION: standart_input(int i, char* argv[i]) // get terminal input and output it to a file, then print the last 10 lines // PARAMETERS: // int i - the current argument number // char* argv[i] - the filename //------------------------------------------------------------------------ int fd = open("tester.txt",O_CREAT | O_RDWR , 0664 ); // open file to which the standart input was outputed to standart_read(fd); //read from the terminal and write the input to a file char buff[1]; int count = go_to_tenth_line(fd,i,argv); // move with lseek to the 10th \n from down to up if(file_output(count,buff,fd) < 0 || count > 0) return -1; // print last 10 lines;error occured if(close(fd) <0) close_error(i,argv); // close file; error occured return 0; } int main(int argc,char* argv[]){ int i = 1,error = 0; char buff[1]; if(argc == 1 || ( *argv[i] == '-' && argc == 2 )){ // if there is only - or nothing standart_input(++i,argv); // takes care of - input return 0; } while(i <= argc-1){ while(*argv[i] == '-'){ print_labels(i,argv,error); // output messages when more than 2 files if(standart_input(++i,argv) < 0) return -1; if(i == argc) return 0; } int fd = open(argv[i],O_RDONLY); // file is opened while(fd < 0){ // while file can't be opened, go for the next open_error(i,argv); // output error mssg error = 1; if(i++ == argc-1) return -1; fd = open(argv[i],O_RDONLY); } if(argc > 2) print_labels(i,argv,error); // output messages when more than 2 files int count = go_to_tenth_line(fd,i,argv); if(count > 0) return -1; // error occured if(file_output(count,buff,fd)< 0) return -1; // error if(close(fd) <0) close_error(i,argv); // close file i++; } return 0; }