martes, 2 de julio de 2013

Command tail -n option implementation



C tail -n Implementation 



This a simple implementation for the command 'tail' with the option -n





#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>

#define BUFF_SIZE 4096
#define DEFAULT_LAST_LINES 10

int isNumber(char *string)
{
    char *endPointer;
    long pid= strtol(string, &endPointer, 10);
    if (*endPointer == '\0')
    {
        return 1;
    }
    return 0;
}

void printProgramUsage(FILE* stream, int exitCode)
{
  fprintf(stream, "valid options\n");
  fprintf(stream, "-h Display program usage valid options.\n"
      "-n Prints the last n lines.\n");
  exit(exitCode);
}

int openFile(const char *file)
{
  int fd= open(file, O_RDONLY);
  if(fd == -1)
  {
    fprintf(stderr,"Error opening file: %s\n", file);
    exit(errno);
  }
  return (fd);
}

void printLines(int fd, off_t bytestart)
{
  char buffer[BUFF_SIZE];
  int readbytes;
  lseek(fd,bytestart,SEEK_SET);
  while((readbytes= read(fd,buffer,BUFF_SIZE)) > 0)
  {
     write(STDOUT_FILENO,buffer, readbytes);
  }
}

long moveLines(int fd, off_t fileset, long linesdistance)
{
  off_t current= lseek(fd, 0, SEEK_CUR);
  lseek(fd,fileset,SEEK_SET);
  long countlines= 0;
  int nbytes;
  char buffer[BUFF_SIZE];
  long amountbytes= 0;
  while((nbytes= read(fd,buffer,BUFF_SIZE)) > 0)
    {
      int index;
      for(index= 0; index < nbytes; index++)
    {
      if(buffer[index] == '\n')
        {
          if(countlines == (linesdistance - 1))
        {
          amountbytes++;
          return (fileset + amountbytes);
        }
          countlines++;
        }
      amountbytes++;
    }
    }
    return (fileset);
}
  

void walkFile(int fd, long numlines)
{
 long distance= 512;
 off_t end_file;
 off_t filebytes;
 int nbytes;
 int flag= 1;
 char buffer[BUFF_SIZE];
 long countbytes;
 long countlines;
 long linesdistance= 0;
 filebytes= lseek(fd,0,SEEK_END);
 end_file= filebytes - distance;
 do
 {
   if(end_file < 0)
   {
     end_file= 0;
     flag= 0;
   }
   else
     {
       end_file= moveLines(fd,end_file,1);
     }
   lseek(fd,end_file,SEEK_SET);
   linesdistance= 0;
   countbytes= 0;
   countlines= 0;
   while((nbytes= read(fd,buffer,BUFF_SIZE)) > 0)
   {
     int index;
     off_t moveline;
     for(index= 0; index < nbytes; index++)
     {
       if(buffer[index] == '\n' && (countbytes + end_file + 1) < filebytes)
       {
     if(countlines == numlines)
     {
       linesdistance++;
     }
     if(countlines < numlines)
     {
      countlines++;
     }
    }
       countbytes++;
     }
   }
   if(countlines == numlines)
   {
     linesdistance++;
     long startline= moveLines(fd,end_file,linesdistance);
     printLines(fd,startline);
     exit(0);
   }
   distance= distance * 2;
   end_file= filebytes - distance;
 }while(flag == 1);
  printLines(fd,0);
  close(fd);
}


int main(int argc, char *argv[])
{
  int fd;
  int opt;
  char *file= NULL;
  long lines;
  while((opt= getopt(argc,argv,"hn:")) != -1)
    {
      switch(opt)
    {
    case 'h': printProgramUsage(stdout,0);
      break;
    case 'n': 
      if(isNumber(optarg))
        {
          lines= atol(optarg);
          break;
        }
      else
        {
          fprintf(stderr,"-n argument not is a number\n");
          printProgramUsage(stderr,1);
        }
    case '?': printProgramUsage(stderr,1);
    default: printProgramUsage(stderr,1);
    }
    }
  if((optind + 1) != argc)
    {
      printProgramUsage(stderr,1);
    }

  file= argv[optind];
  if(lines <= 0)
    {
      lines= DEFAULT_LAST_LINES;
    }
  fd= openFile(file);
  walkFile(fd,lines);
  return 0;
}



No hay comentarios.:

Publicar un comentario