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