home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / TAIL.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  5KB  |  184 lines

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