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