Back to index

lightning-sunbird  0.9+nobinonly
tail.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "prio.h"
00039 #include "prprf.h"
00040 #include "prinit.h"
00041 #include "prthread.h"
00042 #include "prinrval.h"
00043 
00044 #include "plerror.h"
00045 #include "plgetopt.h"
00046 
00047 #include <stdlib.h>
00048 
00049 #define BUFFER_SIZE 500
00050 
00051 static PRFileDesc *out = NULL, *err = NULL;
00052 
00053 static void Help(void)
00054 {
00055     PR_fprintf(err, "Usage: tail [-n <n>] [-f] [-h] <filename>\n");
00056     PR_fprintf(err, "\t-t <n>      Dally time in milliseconds\n");
00057     PR_fprintf(err, "\t-n <n>      Number of bytes before <eof>\n");
00058     PR_fprintf(err, "\t-f          Follow the <eof>\n");
00059     PR_fprintf(err, "\t-h          This message and nothing else\n");
00060 }  /* Help */
00061 
00062 PRIntn main(PRIntn argc, char **argv)
00063 {
00064        PRIntn rv = 0;
00065     PLOptStatus os;
00066        PRStatus status;
00067        PRFileDesc *file;
00068        PRFileInfo fileInfo;
00069        PRIntervalTime dally;
00070        char buffer[BUFFER_SIZE];
00071        PRBool follow = PR_FALSE;
00072        const char *filename = NULL;
00073        PRUint32 position = 0, seek = 0, time = 0;
00074     PLOptState *opt = PL_CreateOptState(argc, argv, "hfn:");
00075 
00076     out = PR_GetSpecialFD(PR_StandardOutput);
00077     err = PR_GetSpecialFD(PR_StandardError);
00078 
00079     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00080     {
00081         if (PL_OPT_BAD == os) continue;
00082         switch (opt->option)
00083         {
00084               case 0:  /* it's the filename */
00085                      filename = opt->value;
00086                      break;
00087         case 'n':  /* bytes before end of file */
00088             seek = atoi(opt->value);
00089             break;
00090         case 't':  /* dally time */
00091             time = atoi(opt->value);
00092             break;
00093         case 'f':  /* follow the end of file */
00094             follow = PR_TRUE;
00095             break;
00096         case 'h':  /* user wants some guidance */
00097             Help();  /* so give him an earful */
00098             return 2;  /* but not a lot else */
00099             break;
00100          default:
00101             break;
00102         }
00103     }
00104     PL_DestroyOptState(opt);
00105 
00106        if (0 == time) time = 1000;
00107        dally = PR_MillisecondsToInterval(time);
00108 
00109     if (NULL == filename)
00110     {
00111         (void)PR_fprintf(out, "Input file not specified\n");
00112         rv = 1; goto done;
00113     }
00114        file = PR_Open(filename, PR_RDONLY, 0);
00115        if (NULL == file)
00116        {
00117               PL_FPrintError(err, "File cannot be opened for reading");
00118               return 1;
00119        }
00120 
00121        status = PR_GetOpenFileInfo(file, &fileInfo);
00122        if (PR_FAILURE == status)
00123        {
00124               PL_FPrintError(err, "Cannot acquire status of file");
00125               rv = 1; goto done;
00126        }
00127        if (seek > 0)
00128        {
00129            if (seek > fileInfo.size) seek = 0;
00130               position = PR_Seek(file, (fileInfo.size - seek), PR_SEEK_SET);
00131               if (-1 == (PRInt32)position)
00132                      PL_FPrintError(err, "Cannot seek to starting position");
00133        }
00134 
00135        do
00136        {
00137               while (position < fileInfo.size)
00138               {
00139                      PRInt32 read, bytes = fileInfo.size - position;
00140                      if (bytes > sizeof(buffer)) bytes = sizeof(buffer);
00141                      read = PR_Read(file, buffer, bytes);
00142                      if (read != bytes)
00143                             PL_FPrintError(err, "Cannot read to eof");
00144                      position += read;
00145                      PR_Write(out, buffer, read);
00146               }
00147 
00148               if (follow)
00149               {
00150                      PR_Sleep(dally);
00151                      status = PR_GetOpenFileInfo(file, &fileInfo);
00152                      if (PR_FAILURE == status)
00153                      {
00154                             PL_FPrintError(err, "Cannot acquire status of file");
00155                             rv = 1; goto done;
00156                      }
00157               }
00158        } while (follow);
00159 
00160 done:
00161        PR_Close(file);
00162 
00163        return rv;
00164 }  /* main */
00165 
00166 /* tail.c */