[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