nsprpub/tools/tail.c
author Arthur Iakab <aiakab@mozilla.com>
Wed, 26 Feb 2020 07:17:55 +0200
changeset 515608 7f41334e10443f4f1c7426e86fb0cb7adfdf4d62
parent 496698 679ba7a64a774209a7cc8444ef6d548ac5add9f1
permissions -rw-r--r--
Backed out 6 changesets (bug 1616716) forcausing multiple mochitest failures on test_ext_protocolHandlers.html Backed out changeset 609cbe8b736e (bug 1616716) Backed out changeset 9e61658c1778 (bug 1616716) Backed out changeset a0e842d96cd6 (bug 1616716) Backed out changeset 0174164a21e5 (bug 1616716) Backed out changeset 35186917e79a (bug 1616716) Backed out changeset 156d2898edb7 (bug 1616716)

/* -*- 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 */