tail c code

Where can I find c code for the UNIX 'tail' command?  Or something that works the same as 'tail -f'?

Thanks!
jeremyandrewsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Anju111599Commented:
Just use popen() to do a "tail -f" and read from the pipe.  

Try out the source below.  It tails a file until it finds the user-supplied search string.

Anju

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <libgen.h>
#include <sys/ioctl.h>


void main( int iArgCount, char *aArgList[] )
{
      char   szProgramName[128];
      fd_set sReadFDs;
      FILE   *pFile;
      int    iFileDescriptor;
      char   szBuffer[2048];
      char   *pBuffer;
      char   szSearch[2048];
      char   szFileName[128];
      char   szCommand[128];
      int    iSearchLength;
      int    iRetVal;
      struct timeval sTimeout;
      long   lBytesAvail;
      int    fFound = 0;

  strcpy( szProgramName, basename(aArgList[0]) );
      fprintf( stderr, "%s -- wait for a string from a file.\n", szProgramName );

  strcpy( szSearch, "junk." );
      strcpy( szFileName, "stdin" );

  if (iArgCount < 2)
    {
    fprintf( stderr, "usage:  %s inputfile [searchstring]\n", szProgramName );
    exit(1);
    }
  strcpy( szFileName, aArgList[1] );
  sprintf( szCommand, "tail -f %s\n", szFileName );
  pFile = popen( szCommand, "r" );
  if (pFile == NULL)
    {
    fprintf( stderr,
             "Couldn't open %s for reading:  %s\n",
             szFileName,
             strerror(errno)
           );
    exit(1);
    }

  if (iArgCount == 3)
    strncpy( szSearch, aArgList[2], sizeof(szSearch) );

  iSearchLength = strlen(szSearch);

  iFileDescriptor = fileno(pFile);

  printf( "   Waiting for: \"%s\"\n", szSearch );
  printf( "   From file:   \"%s\"\n", szFileName );
  while (!fFound)
    {
    sTimeout.tv_sec  = 5;
    sTimeout.tv_usec = 0;
    FD_ZERO( &sReadFDs );
    FD_SET( iFileDescriptor, &sReadFDs );
    iRetVal = select( FD_SETSIZE, &sReadFDs, NULL, NULL, &sTimeout );
    if (iRetVal == -1)
      {
      perror( "select failed" );
      exit(1);
      }
    if (FD_ISSET(iFileDescriptor, &sReadFDs))
      {
      iRetVal = ioctl( iFileDescriptor, FIONREAD, &lBytesAvail );
                  if (iRetVal)
                        {
                        fprintf( stderr, "ioctl:  %s\n", strerror(errno) );
                        }
                  if (lBytesAvail > 0L)
        {
                    while ((pBuffer = fgets( szBuffer, sizeof(szBuffer), pFile )))
          {
          printf( "." );
          if (strstr( szBuffer, szSearch ) != NULL)
            {
                                    fFound = 1;
                                    break;
                                    }
          }
        }
      }
    }

  printf( "\n" );
      printf( "Found.\n" );
  exit(0);
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jeremyandrewsAuthor Commented:
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!  :)
0
Anju111599Commented:
Check the RedHat ftp site, or the gnu site.  You should be able to find it at either of them.

Anju
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

jeremyandrewsAuthor Commented:
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) );
}
0
Anju111599Commented:
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
0
jeremyandrewsAuthor Commented:
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
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.