[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [BusyBox] Tail Update II
From:       "Allen Soard" <esp-software () mail ! hypermart ! net>
Date:       2000-07-27 14:36:22
[Download RAW message or body]

> THIS IS A MESSAGE IN 'MIME' FORMAT.  Your mail reader does not support MIME.
> Please read the first section, which is plain text, and ignore the rest.

Erik,

Here's the (again) updated tail.c. I've
implemented the -c option when working with
pipes, fixed a bug where -NUM wasn't working with
numbers > 9 and managed to shrink it back down to
the sizes that I was so proud of. ;-P 

I think the method layout is pretty much stable
now. And about terminating the strings...I'm
treating the files as tho they're binary i.e
using write rather than printf and memcpy rather
than strcpy, so explicitly putting a \0 in a
buffer position that "write" won't even get to as
a waste of instructions.  I also believe that all
buffers are now being freed at the end of their
scope (I don't know why, but I thought C did that
automatically).

E.Allen Soard

P.S. I'm sending the source because it's smaller
than the patch.

Bookmark the HyperMart Small Business Center. All the tools you need to
succeed!
http://www.hypermart.net/center/
["tail.c" (application/octet-stream)]

/* vi: set sw=4 ts=4: */
/* tail -- output the last part of file(s)
   Copyright (C) 89, 90, 91, 95, 1996 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

   Original version by Paul Rubin <phr@ocf.berkeley.edu>.
   Extensions by David MacKenzie <djm@gnu.ai.mit.edu>.
   tail -f for multiple files by Ian Lance Taylor <ian@airs.com>.  

   Rewrote the option parser, removed locales support,
   and generally busyboxed, Erik Andersen <andersen@lineo.com>

   Removed superfluous options and associated code ("-c", "-n", "-q").
   Removed "tail -f" support for multiple files.
   Both changes by Friedrich Vedder <fwv@myrtle.lahn.de>.

   Compleate Rewrite to correctly support "-NUM", "+NUM", and "-s" by
   E.Allen Soard (esp@espsw.net).

 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include "internal.h"

#define STDIN "standard input"
#define LINES 0
#define BYTES 1

static int n_files = 0;
static char **files = NULL;

static char follow=0;

#ifdef BB_FEATURE_SIMPLE_TAIL
static const char unit_type=LINES;
static const char sleep_int=1;
#else
static char unit_type=LINES;
static int sleep_int=1;
static char verbose = 0;
#endif

static off_t units=-10;

int tail_stream(int file_id)
{
	int fd;
	ssize_t bytes_read=0;
	ssize_t bs=BUFSIZ;
	ssize_t startpoint=bs;
	ssize_t endpoint=0;
	ssize_t count=0;
	ssize_t filesize=0;
	ssize_t filelocation=0;
	char direction=units/abs(units);
	char * buffer;
	char pipe;


	if (!strcmp(files[file_id], STDIN))
		fd = 0;
	else
		fd = open(files[file_id], O_RDONLY);
	if (fd == -1)
		fatalError("Unable to open file %s.\n", files[file_id]);

	buffer=malloc(bs+1);
	filesize=lseek(fd, 0, SEEK_END);
	pipe=(filesize<0);

	if(direction<0) {
		if (filesize < bs)
			filelocation = lseek(fd, -filesize, SEEK_CUR);
		else
			filelocation = lseek(fd, -bs, SEEK_CUR);
	} else {
		units--;
		lseek(fd,0,SEEK_SET);
	}
	while(1) {
		if (pipe) {
			char * line;
			ssize_t f_size=0;

			line=malloc(bs+1);
			while(1) {
				bytes_read=read(fd,line,bs);
				line[bytes_read]='\0';
				if(bytes_read<=0)
					break;
				buffer=realloc(buffer,f_size+bytes_read);
				memcpy(&buffer[f_size],line,bytes_read);
				f_size+=bytes_read;
			}

			bs=f_size;
			if (line)
				free(line);
		} else {
			bytes_read = read(fd, buffer, bs);
			if (bytes_read <= 0)
				break;
			bs=bytes_read;
		}
		startpoint=bs;
		if(direction>0) {
			endpoint=startpoint;
			startpoint=0;
		}
		for(;startpoint!=endpoint;startpoint+=direction) {
			if(count==abs(units))
				break;
#ifndef BB_FEATURE_SIMPLE_TAIL
			if(unit_type==BYTES)
				count++;
			else
#endif
				if(buffer[startpoint]=='\n')
					count++;
		}
		if((count==abs(units)) | pipe)
			break;
	}
	if(direction<0)
#ifndef BB_FEATURE_SIMPLE_TAIL
		if (unit_type==LINES)
#endif
			startpoint++;
	memcpy(&buffer[0],&buffer[startpoint],bs-startpoint);

	write(1,buffer,bs-startpoint);

	while (1) {
		bytes_read = read(fd, buffer, bs);
		if (bytes_read <= 0) {
			if (!follow) {
				close(fd);
				break;
			}
			sleep(sleep_int);
		} else
			buffer[bytes_read]='\0';
		write(1, buffer, bytes_read);
		usleep(sleep_int * 1000);
	}
	if(direction<0)
		units++;

	if (buffer)
		free(buffer);
	return 0;
}

void add_file(char *name)
{
	++n_files;
	files = realloc(files, n_files);
	files[n_files - 1] = (char *) malloc(strlen(name) + 1);
	strcpy(files[n_files - 1], name);
}


int tail_main(int argc, char **argv)
{
	int show_headers = 1;
	int test;
	int c;

	opterr = 0;
	while (1) {
		int opt_index = 0;

		c = getopt_long_only(argc, argv, "c:fhn:s:qv", NULL, &opt_index);
		if (c == -1)
			break;
		switch (c) {

#ifndef BB_FEATURE_SIMPLE_TAIL

		case 'c':
			unit_type = BYTES;
			test = atoi(optarg);
			if(test==0)
				usage(tail_usage);
			if(optarg[0]=='+')
				units=test;
			else
				units=-test;
			if(optarg[strlen(optarg)-1]>'9') {
				switch (optarg[strlen(optarg)-1]) {
				case 'b':
					units *= 512;
					break;
				case 'k':
					units *= 1024;
					break;
				case 'm':
					units *= (1024 * 1024);
					break;
				default:
					fprintf(stderr,"Size must be b,k, or m.");
					usage(tail_usage);
				}
			}
			break;
		case 'q':
			show_headers = 0;
			break;
		case 's':
			sleep_int = atoi(optarg);
			if(sleep_int<1)
				sleep_int=1;
			break;
		case 'v':
			verbose = 1;
			break;
#endif
		case 'f':
			follow = 1;
			break;
		case 'h':
			usage(tail_usage);
			break;
		case 'n':
			test = atoi(optarg);
			if (test) {
				if (optarg[0] == '+')
					units = test;
				else
					units = -test;
			} else
				usage(tail_usage);
			break;
		default:
			if(argv[optind][0]=='-'){
				test=atoi(argv[optind]);
				if (test==0) {
					fprintf(stderr, "\nUnknown arg: %s.\n\n",
							argv[optind]);
					usage(tail_usage);
				}
				units = test;
			}
		}
	}
	while (optind < argc) {
		test = atoi(argv[optind]);
		if (test)
			units = test;
		else {
			if (!strcmp(argv[optind], "-"))
				add_file(STDIN);
			else
				add_file(argv[optind]);
		}
		optind++;
	}
	if (n_files == 0)
		add_file(STDIN);
	if (n_files == 1)
#ifndef BB_FEATURE_SIMPLE_TAIL
		if (!verbose)
#endif
			show_headers = 0;
	for (test = 0; test < n_files; test++) {
		if (show_headers)
			printf("==> %s <==\n", files[test]);
		tail_stream(test);
	}
	if(files)
		free(files);
	return 0;
}

/*
Local Variables:
c-file-style: "linux"
c-basic-offset: 4
tab-width: 4
End:
*/


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic