home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 14 / CD_ASCQ_14_0694.iso / maj / 653 / tail.c < prev    next >
C/C++ Source or Header  |  1994-04-03  |  5KB  |  182 lines

  1. /*
  2. **  TAIL.C
  3. **  ----------------------------------------------------------------------
  4. **  Display the last n lines of a file (20 lines by default).
  5. **
  6. **  Revision history
  7. **  ================
  8. **  Modified  19930604 by Ruurd Pels:
  9. **  - Increased default line numbers from 5 to 20
  10. **  - Made ANSI C conformant (I hope)
  11. **  - Added '-' support for commandline
  12. **  - Outputs header to stderr instead of stdout to leave it out when
  13. **    redirecting files
  14. **  - Fixed \r\r\n bug for MSDOS machines
  15. **
  16. **  Modified  19861005 by Joe Huffman:
  17. **  - Utilize prototyping, fixed a bug, added (a few) comments and help.
  18. **
  19. **  Written   19860204 by Joe Huffman.
  20. **
  21. **  Not copyrighted.
  22. */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26.  
  27. char            head1[] = {"\n------- \""};
  28. char            head2[] = {" -------\n"};
  29. FILE *          fp;
  30. int             filenum;
  31. int             cc;
  32. unsigned int    linenum = 20;
  33. unsigned int    indx;
  34. long int *      tail;
  35.  
  36. /*
  37. **  Get the number of lines to display at the "tail" of each file from
  38. **  the command line.
  39. */
  40.  
  41. void getlinenum(int n, char * str[])
  42. {
  43.       for (--n; n; --n)
  44.       {
  45.             ++str;
  46.             if ((**str == '/') || (**str == '-'))
  47.             {
  48.                   linenum = atoi(*(str) + 1);
  49.                   if (linenum <= 0)
  50.                         linenum = 20;
  51.             }
  52.       }
  53.  
  54.       /* Because we save a pointer to the end of the PREVIOUS line */
  55.       linenum++;
  56. }
  57.  
  58. /*
  59. **  Set the file pointer "fp" to "linenum - 1" lines before the end of
  60. **  the file.
  61. */
  62.  
  63. void gettail(void)
  64. {
  65.       unsigned char outstr[15];
  66.       unsigned long int currline = 0L;
  67.  
  68.       tail = (long int *)malloc(sizeof(*tail) * linenum);
  69.       if (!tail)
  70.       {
  71.             fputs("Insufficient memory.", stderr);
  72.             exit(1);
  73.       }
  74.       tail[0] = ftell(fp);
  75.       indx = 0;
  76.  
  77.       for (cc = getc(fp); cc != EOF; cc = getc(fp))
  78.       {
  79.             if (cc == '\r')
  80.             {
  81.                   ++currline;
  82.                   cc = getc(fp);
  83.                   if (cc != '\n')
  84.                         ungetc(cc, fp);
  85.                   ++indx;
  86.                   indx %= linenum;
  87.                   tail[indx] = ftell(fp);
  88.             }
  89.             else
  90.             {
  91.                   if (cc == '\n')
  92.                   {
  93.                         ++currline;
  94.                         cc = getc(fp);
  95.                         if (cc != '\r')
  96.                               ungetc(cc, fp);
  97.                         ++indx;
  98.                         indx %= linenum;
  99.                         tail[indx] = ftell(fp);
  100.                   }
  101.             }
  102.       }
  103.       fputs("\" ", stderr);
  104.       ltoa(currline, outstr, 10);
  105.       fputs(outstr, stderr);
  106.       fputs(" lines", stderr);
  107.       if (currline >= linenum - 1)
  108.       {
  109.             indx++;
  110.             indx %= linenum;
  111.       }
  112.       else  indx = 0;
  113.  
  114.       if (fseek(fp, tail[indx], 0) == -1)
  115.       {
  116.             fputs("\nFile seek error.", stderr);
  117.             exit(1);
  118.       }
  119.       free(tail);
  120. }
  121.  
  122. /*
  123. **  Tell the user what the program is and how to use it.
  124. */
  125.  
  126. void help(void)
  127. {
  128.       char *ptr;
  129.       static char help_str[] =  "Usage:\n\nTAIL <filename> [filename] "
  130.             "[/n]\n\n<filename>  - The name of a valid file, wildcards "
  131.             "accepted.\nn           - Number of lines to print out, 20 "
  132.             "by default.";
  133.  
  134.       for (ptr = &help_str[0]; *ptr; ptr++)
  135.             fputc(*ptr, stdout);
  136. }
  137.  
  138. int main(int argc, char **argv)
  139. {
  140.       if (argc <= 1)
  141.       {
  142.             help();
  143.             exit(1);
  144.       }
  145.  
  146.       getlinenum(argc, argv);
  147.  
  148.       for (filenum = 1; filenum < argc; ++filenum)
  149.       {
  150.             if (*argv[filenum] == '/')
  151.                   continue;
  152.             fp = fopen(argv[filenum], "rb");
  153.             if (!fp)
  154.             {
  155.                   fputs(head1, stderr);
  156.                   fputs(argv[filenum], stderr);
  157.                   fputs("\" not found.", stderr);
  158.                   fputs(head2, stderr);
  159.             }
  160.             else
  161.             {
  162.                   fputs(head1, stderr);
  163.                   fputs(argv[filenum], stderr);
  164.                   gettail();
  165.                   fputs(head2, stderr);
  166.                   for (cc = getc(fp); cc != EOF; cc = getc(fp))
  167.                   {
  168. #ifdef __MSDOS__
  169.                         if (cc != '\r')
  170.                         {
  171.                               fputc(cc, stdout);
  172.                         }
  173. #else
  174.                         fputc(cc, stdout);
  175. #endif
  176.                   }
  177.                   fclose(fp);
  178.             }
  179.       }
  180.       return EXIT_SUCCESS;
  181. }
  182.