Link to home
Start Free TrialLog in
Avatar of jeremyandrews
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!
ASKER CERTIFIED SOLUTION
Avatar of Anju111599
Anju111599

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jeremyandrews
jeremyandrews

ASKER

Thanks.  This is not the source code for tail, but it will serve my purpose.  I can easily adapt it to what I want to do.

(BTW:  If anyone out there knows where I can find the source for tail, I'm still interested.)

Thanks again!  :)
Check the RedHat ftp site, or the gnu site.  You should be able to find it at either of them.

Anju
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) );
}
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
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