jeremyandrews
asked on
tail c code
Where can I find c code for the UNIX 'tail' command? Or something that works the same as 'tail -f'?
Thanks!
Thanks!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Check the RedHat ftp site, or the gnu site. You should be able to find it at either of them.
Anju
Anju
ASKER
Thanks. :)
I wrote what I needed. Here's the code that worked:
-------------------------- ----
#include <stdio.h>
#include <errno.h>
void main ( int iArgCount, char *aArgList[] )
{
FILE *pFile;
char szProgramName[128];
char szBuffer[2048];
char *pBuffer;
char szTailFile[2048];
long lFileLength;
long lBufferLength;
strcpy( szProgramName, basename(aArgList[0]) );
strcpy( szTailFile, "testfile" ); /* Default file to tail */
if (iArgCount == 2) /* aArgList[1] is alternative file to tail */
{
strncpy ( szTailFile, aArgList[1], sizeof(szTailFile) );
}
else if (iArgCount > 2) /* Too many arguments */
{
printf( "Usage: %s [filename]\n", szProgramName );
exit(1);
}
if ( (pFile = fopen ( szTailFile, "r")) != NULL) /* Attempt to open file to tail */
{
fseek ( pFile, 0L, SEEK_END );
if ( (lFileLength = (ftell (pFile))) != -1L) /* Get pointer to end of file */
{
fclose ( pFile );
while (1)
{
sleep (1);
if ( (pFile = fopen ( szTailFile, "r")) != NULL)
{
fseek ( pFile, 0L, SEEK_END );
if ( (lBufferLength = (ftell (pFile))) != -1L)
{
if (lFileLength < lBufferLength)
{
fseek ( pFile, lFileLength, SEEK_SET);
while ( (pBuffer = fgets( szBuffer, sizeof(szBuffer), pFile )))
{
printf( "%s", pBuffer);
}
if ( (lFileLength = (ftell (pFile))) == -1L)
{
printf( "ERROR!\n" );
exit(1);
}
fclose ( pFile );
}
else if (lFileLength > lBufferLength)
{
if ( (lFileLength = (ftell (pFile))) == -1L)
{
printf( "ERROR!\n" );
exit(1);
}
fclose ( pFile );
}
}
}
}
}
}
else
printf( "Unable to open \"%s\": %s\n", szTailFile, strerror(errno) );
}
I wrote what I needed. Here's the code that worked:
--------------------------
#include <stdio.h>
#include <errno.h>
void main ( int iArgCount, char *aArgList[] )
{
FILE *pFile;
char szProgramName[128];
char szBuffer[2048];
char *pBuffer;
char szTailFile[2048];
long lFileLength;
long lBufferLength;
strcpy( szProgramName, basename(aArgList[0]) );
strcpy( szTailFile, "testfile" ); /* Default file to tail */
if (iArgCount == 2) /* aArgList[1] is alternative file to tail */
{
strncpy ( szTailFile, aArgList[1], sizeof(szTailFile) );
}
else if (iArgCount > 2) /* Too many arguments */
{
printf( "Usage: %s [filename]\n", szProgramName );
exit(1);
}
if ( (pFile = fopen ( szTailFile, "r")) != NULL) /* Attempt to open file to tail */
{
fseek ( pFile, 0L, SEEK_END );
if ( (lFileLength = (ftell (pFile))) != -1L) /* Get pointer to end of file */
{
fclose ( pFile );
while (1)
{
sleep (1);
if ( (pFile = fopen ( szTailFile, "r")) != NULL)
{
fseek ( pFile, 0L, SEEK_END );
if ( (lBufferLength = (ftell (pFile))) != -1L)
{
if (lFileLength < lBufferLength)
{
fseek ( pFile, lFileLength, SEEK_SET);
while ( (pBuffer = fgets( szBuffer, sizeof(szBuffer), pFile )))
{
printf( "%s", pBuffer);
}
if ( (lFileLength = (ftell (pFile))) == -1L)
{
printf( "ERROR!\n" );
exit(1);
}
fclose ( pFile );
}
else if (lFileLength > lBufferLength)
{
if ( (lFileLength = (ftell (pFile))) == -1L)
{
printf( "ERROR!\n" );
exit(1);
}
fclose ( pFile );
}
}
}
}
}
}
else
printf( "Unable to open \"%s\": %s\n", szTailFile, strerror(errno) );
}
Excellent! Short, sweet, and to-the-point :) Of course, I have an observation to make from a purist, nit-picking point of view ;)
The sleep and poll method makes your implementation slow to respond when the file is written to, which would be fine for 99% of the applications where one would want to tail a file. The advantage to this approach is that the code to implement it is simple and easy to maintain.
The implementation I sent you contains a call to select to force the process to sleep until there is work to do. However, it responds very quickly when the file is written to, hence it is an event-driven approach rather than a polling approach. It was written to tail a log file from another process to search for a specific string, then return so the script which launched it can start another process immediately. The second process must interact with the first process which produced the log file, but can't be launched until a specific event has occurred. This approach is more complicated and harder to maintain, but responds more quickly for applications where response time is important.
If you already knew all this, please excuse my boring comments. But if you didn't, it was my hope to provide you with more tools for your arsenal of problem-solving skills :)
Anju
The sleep and poll method makes your implementation slow to respond when the file is written to, which would be fine for 99% of the applications where one would want to tail a file. The advantage to this approach is that the code to implement it is simple and easy to maintain.
The implementation I sent you contains a call to select to force the process to sleep until there is work to do. However, it responds very quickly when the file is written to, hence it is an event-driven approach rather than a polling approach. It was written to tail a log file from another process to search for a specific string, then return so the script which launched it can start another process immediately. The second process must interact with the first process which produced the log file, but can't be launched until a specific event has occurred. This approach is more complicated and harder to maintain, but responds more quickly for applications where response time is important.
If you already knew all this, please excuse my boring comments. But if you didn't, it was my hope to provide you with more tools for your arsenal of problem-solving skills :)
Anju
ASKER
Anju,
For my purpose, an up to 1 second delay is not a problem. (I'm tailing an alarm file and sending the alarms via a UDP stream to our alarm server.)
But then, it sounds as though your method would be more efficient as well, as your method wouldn't have to poll the system every second? I'll take another look at your code and attempt to understand the call to select... This is the first c program I've written in many years!
Thanks for your help and ideas! I appreciate the comments entirely. :)
-Jeremy
For my purpose, an up to 1 second delay is not a problem. (I'm tailing an alarm file and sending the alarms via a UDP stream to our alarm server.)
But then, it sounds as though your method would be more efficient as well, as your method wouldn't have to poll the system every second? I'll take another look at your code and attempt to understand the call to select... This is the first c program I've written in many years!
Thanks for your help and ideas! I appreciate the comments entirely. :)
-Jeremy
ASKER
(BTW: If anyone out there knows where I can find the source for tail, I'm still interested.)
Thanks again! :)