123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "prio.h"
- #include "prprf.h"
- #include "prinit.h"
- #include "prthread.h"
- #include "prinrval.h"
- #include "plerror.h"
- #include "plgetopt.h"
- #include <stdlib.h>
- #define BUFFER_SIZE 500
- static PRFileDesc *out = NULL, *err = NULL;
- static void Help(void)
- {
- PR_fprintf(err, "Usage: tail [-n <n>] [-f] [-h] <filename>\n");
- PR_fprintf(err, "\t-t <n> Dally time in milliseconds\n");
- PR_fprintf(err, "\t-n <n> Number of bytes before <eof>\n");
- PR_fprintf(err, "\t-f Follow the <eof>\n");
- PR_fprintf(err, "\t-h This message and nothing else\n");
- } /* Help */
- PRIntn main(PRIntn argc, char **argv)
- {
- PRIntn rv = 0;
- PLOptStatus os;
- PRStatus status;
- PRFileDesc *file;
- PRFileInfo fileInfo;
- PRIntervalTime dally;
- char buffer[BUFFER_SIZE];
- PRBool follow = PR_FALSE;
- const char *filename = NULL;
- PRUint32 position = 0, seek = 0, time = 0;
- PLOptState *opt = PL_CreateOptState(argc, argv, "hfn:");
- out = PR_GetSpecialFD(PR_StandardOutput);
- err = PR_GetSpecialFD(PR_StandardError);
- while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
- {
- if (PL_OPT_BAD == os) {
- continue;
- }
- switch (opt->option)
- {
- case 0: /* it's the filename */
- filename = opt->value;
- break;
- case 'n': /* bytes before end of file */
- seek = atoi(opt->value);
- break;
- case 't': /* dally time */
- time = atoi(opt->value);
- break;
- case 'f': /* follow the end of file */
- follow = PR_TRUE;
- break;
- case 'h': /* user wants some guidance */
- Help(); /* so give him an earful */
- return 2; /* but not a lot else */
- break;
- default:
- break;
- }
- }
- PL_DestroyOptState(opt);
- if (0 == time) {
- time = 1000;
- }
- dally = PR_MillisecondsToInterval(time);
- if (NULL == filename)
- {
- (void)PR_fprintf(out, "Input file not specified\n");
- rv = 1; goto done;
- }
- file = PR_Open(filename, PR_RDONLY, 0);
- if (NULL == file)
- {
- PL_FPrintError(err, "File cannot be opened for reading");
- return 1;
- }
- status = PR_GetOpenFileInfo(file, &fileInfo);
- if (PR_FAILURE == status)
- {
- PL_FPrintError(err, "Cannot acquire status of file");
- rv = 1; goto done;
- }
- if (seek > 0)
- {
- if (seek > fileInfo.size) {
- seek = 0;
- }
- position = PR_Seek(file, (fileInfo.size - seek), PR_SEEK_SET);
- if (-1 == (PRInt32)position) {
- PL_FPrintError(err, "Cannot seek to starting position");
- }
- }
- do
- {
- while (position < fileInfo.size)
- {
- PRInt32 read, bytes = fileInfo.size - position;
- if (bytes > sizeof(buffer)) {
- bytes = sizeof(buffer);
- }
- read = PR_Read(file, buffer, bytes);
- if (read != bytes) {
- PL_FPrintError(err, "Cannot read to eof");
- }
- position += read;
- PR_Write(out, buffer, read);
- }
- if (follow)
- {
- PR_Sleep(dally);
- status = PR_GetOpenFileInfo(file, &fileInfo);
- if (PR_FAILURE == status)
- {
- PL_FPrintError(err, "Cannot acquire status of file");
- rv = 1; goto done;
- }
- }
- } while (follow);
- done:
- PR_Close(file);
- return rv;
- } /* main */
- /* tail.c */
|