mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-06-10 03:29:29 +00:00
- initial checkin, as submitted by Dave Tribby
- renamed makefile.mk to Makefile
This commit is contained in:
parent
fb3ab1728f
commit
590e077340
11
bin/tail/Makefile
Normal file
11
bin/tail/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# This makefile is intended for use with dmake(1) on Apple IIGS
|
||||
#
|
||||
# Created by Dave Tribby, July 1997
|
||||
|
||||
# Program name
|
||||
PROG= tail
|
||||
# Source files
|
||||
SRCS= tail.c forward.c misc.c read.c
|
||||
|
||||
.INCLUDE : <gno.prog.mk>
|
52
bin/tail/extern.h
Normal file
52
bin/tail/extern.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 6/6/93
|
||||
*/
|
||||
|
||||
#define WR(p, size) \
|
||||
if (write(STDOUT_FILENO, p, size) != size) \
|
||||
oerr();
|
||||
|
||||
enum STYLE { NOTSET = 0, FBYTES, FLINES, RBYTES, RLINES, REVERSE };
|
||||
|
||||
void forward __P((FILE *, enum STYLE, long, struct stat *));
|
||||
void reverse __P((FILE *, enum STYLE, long, struct stat *));
|
||||
|
||||
int bytes __P((FILE *, off_t));
|
||||
int lines __P((FILE *, off_t));
|
||||
|
||||
void ierr __P((void));
|
||||
void oerr __P((void));
|
||||
|
||||
extern int fflag, rflag, rval;
|
||||
extern char *fname;
|
331
bin/tail/forward.c
Normal file
331
bin/tail/forward.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Edward Sze-Tyan Wang.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified for GNO (Apple IIGS) by Dave Tribby, July 1997
|
||||
*
|
||||
* Constructs unacceptable to compiler are replaced using #ifndef __ORCAC__
|
||||
*
|
||||
* Changes not related to compiler are replaced using #ifndef __GNO__
|
||||
*
|
||||
* Added prototyped headers, surrounded by #ifndef __STDC__
|
||||
*/
|
||||
|
||||
#ifndef __GNO__ /* Don't need what strings for GNO */
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef __GNO__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include "extern.h"
|
||||
|
||||
static void rlines __P((FILE *, long, struct stat *));
|
||||
|
||||
/*
|
||||
* forward -- display the file, from an offset, forward.
|
||||
*
|
||||
* There are eight separate cases for this -- regular and non-regular
|
||||
* files, by bytes or lines and from the beginning or end of the file.
|
||||
*
|
||||
* FBYTES byte offset from the beginning of the file
|
||||
* REG seek
|
||||
* NOREG read, counting bytes
|
||||
*
|
||||
* FLINES line offset from the beginning of the file
|
||||
* REG read, counting lines
|
||||
* NOREG read, counting lines
|
||||
*
|
||||
* RBYTES byte offset from the end of the file
|
||||
* REG seek
|
||||
* NOREG cyclically read characters into a wrap-around buffer
|
||||
*
|
||||
* RLINES
|
||||
* REG mmap the file and step back until reach the correct offset.
|
||||
* NOREG cyclically read lines into a wrap-around array of buffers
|
||||
*/
|
||||
void
|
||||
#ifndef __STDC__
|
||||
forward(fp, style, off, sbp)
|
||||
FILE *fp;
|
||||
enum STYLE style;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
#else
|
||||
forward(FILE *fp,
|
||||
enum STYLE style,
|
||||
long off,
|
||||
struct stat *sbp)
|
||||
#endif
|
||||
{
|
||||
register int ch;
|
||||
struct timeval second;
|
||||
|
||||
switch(style) {
|
||||
case FBYTES:
|
||||
if (off == 0)
|
||||
break;
|
||||
if (S_ISREG(sbp->st_mode)) {
|
||||
if (sbp->st_size < off)
|
||||
off = sbp->st_size;
|
||||
if (fseek(fp, off, SEEK_SET) == -1) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
} else while (off--)
|
||||
if ((ch = getc(fp)) == EOF) {
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLINES:
|
||||
if (off == 0)
|
||||
break;
|
||||
for (;;) {
|
||||
if ((ch = getc(fp)) == EOF) {
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ch == '\n' && !--off)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RBYTES:
|
||||
if (S_ISREG(sbp->st_mode)) {
|
||||
if (sbp->st_size >= off &&
|
||||
fseek(fp, -off, SEEK_END) == -1) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
} else if (off == 0) {
|
||||
while (getc(fp) != EOF);
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
} else
|
||||
if (bytes(fp, off))
|
||||
return;
|
||||
break;
|
||||
case RLINES:
|
||||
if (S_ISREG(sbp->st_mode))
|
||||
if (!off) {
|
||||
if (fseek(fp, 0L, SEEK_END) == -1) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
} else
|
||||
rlines(fp, off, sbp);
|
||||
else if (off == 0) {
|
||||
while (getc(fp) != EOF);
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
} else
|
||||
if (lines(fp, off))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We pause for one second after displaying any data that has
|
||||
* accumulated since we read the file.
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
while ((ch = getc(fp)) != EOF)
|
||||
if (putchar(ch) == EOF)
|
||||
oerr();
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
(void)fflush(stdout);
|
||||
if (!fflag)
|
||||
break;
|
||||
|
||||
/* Sleep(3) is eight system calls. Do it fast. */
|
||||
second.tv_sec = 1;
|
||||
second.tv_usec = 0;
|
||||
if (select(0, NULL, NULL, NULL, &second) == -1)
|
||||
if (errno != EINTR)
|
||||
err(1, "select");
|
||||
clearerr(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Need a separate version of rlines for GNO (see below) */
|
||||
/* because the mmap routines are not available. DMT */
|
||||
#ifndef __GNO__
|
||||
/*
|
||||
* rlines -- display the last offset lines of the file.
|
||||
*/
|
||||
static void
|
||||
#ifndef __STDC__
|
||||
rlines(fp, off, sbp)
|
||||
FILE *fp;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
#else
|
||||
rlines(FILE *fp,
|
||||
long off,
|
||||
struct stat *sbp)
|
||||
#endif
|
||||
{
|
||||
register off_t size;
|
||||
register char *p;
|
||||
char *start;
|
||||
|
||||
if (!(size = sbp->st_size))
|
||||
return;
|
||||
|
||||
if (size > SIZE_T_MAX) {
|
||||
errno = EFBIG;
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((start = mmap(NULL, (size_t)size,
|
||||
PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Last char is special, ignore whether newline or not. */
|
||||
for (p = start + size - 1; --size;)
|
||||
if (*--p == '\n' && !--off) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the file pointer to reflect the length displayed. */
|
||||
size = sbp->st_size - size;
|
||||
WR(p, size);
|
||||
if (fseek(fp, (long)sbp->st_size, SEEK_SET) == -1) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
if (munmap(start, (size_t)sbp->st_size)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* rlines -- display the last offset lines of the file.
|
||||
* This GNO version doesn't use mmap calls. (DMT)
|
||||
*/
|
||||
static void
|
||||
rlines(FILE *fp,
|
||||
long off,
|
||||
struct stat *sbp)
|
||||
{
|
||||
off_t size, bytes_read, bytes_remaining;
|
||||
size_t readlen;
|
||||
#define BUFSIZE 4096
|
||||
static char buf[BUFSIZE];
|
||||
int offset;
|
||||
|
||||
if (!(size = sbp->st_size))
|
||||
return;
|
||||
|
||||
/* Last char is special, ignore whether newline or not. */
|
||||
bytes_remaining = size - 1;
|
||||
bytes_read = 1;
|
||||
|
||||
while (bytes_remaining && off) {
|
||||
if (bytes_remaining < BUFSIZE) {
|
||||
/* Need to read from beginning of file */
|
||||
readlen = bytes_remaining;
|
||||
rewind(fp);
|
||||
}
|
||||
else {
|
||||
/* Setup to read one buffer's worth of data */
|
||||
readlen = BUFSIZE;
|
||||
fseek(fp, -(bytes_read+BUFSIZE), SEEK_END);
|
||||
}
|
||||
if ((readlen = fread(buf, sizeof(char), readlen, fp)) == 0) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
bytes_read += readlen;
|
||||
bytes_remaining -= readlen;
|
||||
|
||||
/* Set pointer to end of the data that was just read */
|
||||
offset = readlen;
|
||||
|
||||
while (offset) {
|
||||
if (buf[--offset] == '\n' && ! --off) {
|
||||
++offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (off)
|
||||
/* Requested number of lines not found. Go to beginning. */
|
||||
rewind(fp);
|
||||
else {
|
||||
/* Set the file pointer to reflect the length displayed. */
|
||||
if (fseek(fp, size-bytes_read+offset, SEEK_SET) == -1) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
81
bin/tail/misc.c
Normal file
81
bin/tail/misc.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Edward Sze-Tyan Wang.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified for GNO (Apple IIGS) by Dave Tribby, July 1997
|
||||
*
|
||||
* Constructs unacceptable to compiler are replaced using #ifndef __ORCAC__
|
||||
*
|
||||
* Added prototyped headers, surrounded by #ifndef __STDC__
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GNO__ /* Don't need what strings for GNO */
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include "extern.h"
|
||||
|
||||
void
|
||||
#ifndef __STDC__
|
||||
ierr()
|
||||
#else
|
||||
ierr(void)
|
||||
#endif
|
||||
{
|
||||
warn("%s", fname);
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
void
|
||||
#ifndef __STDC__
|
||||
oerr()
|
||||
#else
|
||||
oerr(void)
|
||||
#endif
|
||||
{
|
||||
err(1, "stdout");
|
||||
}
|
213
bin/tail/read.c
Normal file
213
bin/tail/read.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Edward Sze-Tyan Wang.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __GNO__ /* Don't need what strings for GNO */
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* bytes -- read bytes to an offset from the end and display.
|
||||
*
|
||||
* This is the function that reads to a byte offset from the end of the input,
|
||||
* storing the data in a wrap-around buffer which is then displayed. If the
|
||||
* rflag is set, the data is displayed in lines in reverse order, and this
|
||||
* routine has the usual nastiness of trying to find the newlines. Otherwise,
|
||||
* it is displayed from the character closest to the beginning of the input to
|
||||
* the end.
|
||||
*/
|
||||
int
|
||||
#ifndef __STDC__
|
||||
bytes(fp, off)
|
||||
register FILE *fp;
|
||||
off_t off;
|
||||
#else
|
||||
bytes(register FILE *fp,
|
||||
off_t off)
|
||||
#endif
|
||||
{
|
||||
register int ch, len, tlen;
|
||||
register char *ep, *p, *t;
|
||||
int wrap;
|
||||
char *sp;
|
||||
|
||||
if ((sp = p = malloc(off)) == NULL)
|
||||
err(1, "malloc");
|
||||
|
||||
for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
|
||||
*p = ch;
|
||||
if (++p == ep) {
|
||||
wrap = 1;
|
||||
p = sp;
|
||||
}
|
||||
}
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (rflag) {
|
||||
for (t = p - 1, len = 0; t >= sp; --t, ++len)
|
||||
if (*t == '\n' && len) {
|
||||
WR(t + 1, len);
|
||||
len = 0;
|
||||
}
|
||||
if (wrap) {
|
||||
tlen = len;
|
||||
for (t = ep - 1, len = 0; t >= p; --t, ++len)
|
||||
if (*t == '\n') {
|
||||
if (len) {
|
||||
WR(t + 1, len);
|
||||
len = 0;
|
||||
}
|
||||
if (tlen) {
|
||||
WR(sp, tlen);
|
||||
tlen = 0;
|
||||
}
|
||||
}
|
||||
if (len)
|
||||
WR(t + 1, len);
|
||||
if (tlen)
|
||||
WR(sp, tlen);
|
||||
}
|
||||
} else {
|
||||
if (wrap && (len = ep - p))
|
||||
WR(p, len);
|
||||
if (len = p - sp)
|
||||
WR(sp, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lines -- read lines to an offset from the end and display.
|
||||
*
|
||||
* This is the function that reads to a line offset from the end of the input,
|
||||
* storing the data in an array of buffers which is then displayed. If the
|
||||
* rflag is set, the data is displayed in lines in reverse order, and this
|
||||
* routine has the usual nastiness of trying to find the newlines. Otherwise,
|
||||
* it is displayed from the line closest to the beginning of the input to
|
||||
* the end.
|
||||
*/
|
||||
int
|
||||
#ifndef __STDC__
|
||||
lines(fp, off)
|
||||
register FILE *fp;
|
||||
off_t off;
|
||||
#else
|
||||
lines(register FILE *fp,
|
||||
off_t off)
|
||||
#endif
|
||||
{
|
||||
struct {
|
||||
u_int blen;
|
||||
u_int len;
|
||||
char *l;
|
||||
} *lines;
|
||||
register int ch;
|
||||
register char *p;
|
||||
int blen, cnt, recno, wrap;
|
||||
char *sp;
|
||||
|
||||
if ((lines = malloc(off * sizeof(*lines))) == NULL)
|
||||
err(1, "malloc");
|
||||
bzero(lines, off * sizeof(*lines));
|
||||
sp = NULL;
|
||||
blen = cnt = recno = wrap = 0;
|
||||
|
||||
while ((ch = getc(fp)) != EOF) {
|
||||
if (++cnt > blen) {
|
||||
if ((sp = realloc(sp, blen += 1024)) == NULL)
|
||||
err(1, "realloc");
|
||||
p = sp + cnt - 1;
|
||||
}
|
||||
*p++ = ch;
|
||||
if (ch == '\n') {
|
||||
if (lines[recno].blen < cnt) {
|
||||
lines[recno].blen = cnt + 256;
|
||||
if ((lines[recno].l = realloc(lines[recno].l,
|
||||
lines[recno].blen)) == NULL)
|
||||
err(1, "realloc");
|
||||
}
|
||||
bcopy(sp, lines[recno].l, lines[recno].len = cnt);
|
||||
cnt = 0;
|
||||
p = sp;
|
||||
if (++recno == off) {
|
||||
wrap = 1;
|
||||
recno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return 1;
|
||||
}
|
||||
if (cnt) {
|
||||
lines[recno].l = sp;
|
||||
lines[recno].len = cnt;
|
||||
if (++recno == off) {
|
||||
wrap = 1;
|
||||
recno = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (rflag) {
|
||||
for (cnt = recno - 1; cnt >= 0; --cnt)
|
||||
WR(lines[cnt].l, lines[cnt].len);
|
||||
if (wrap)
|
||||
for (cnt = off - 1; cnt >= recno; --cnt)
|
||||
WR(lines[cnt].l, lines[cnt].len);
|
||||
} else {
|
||||
if (wrap)
|
||||
for (cnt = recno; cnt < off; ++cnt)
|
||||
WR(lines[cnt].l, lines[cnt].len);
|
||||
for (cnt = 0; cnt < recno; ++cnt)
|
||||
WR(lines[cnt].l, lines[cnt].len);
|
||||
}
|
||||
return 0;
|
||||
}
|
315
bin/tail/reverse.c
Normal file
315
bin/tail/reverse.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Edward Sze-Tyan Wang.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified for GNO (Apple IIGS) by Dave Tribby, July 1997
|
||||
*
|
||||
* Constructs unacceptable to compiler are replaced using #ifndef __ORCAC__
|
||||
*
|
||||
* Changes not related to compiler are replaced using #ifndef __GNO__
|
||||
*
|
||||
* Added prototyped headers, surrounded by #ifndef __STDC__
|
||||
*/
|
||||
|
||||
/* =====> NOTE <=====
|
||||
* Because the -r option has not been implemented for GNO (due to the
|
||||
* lack of mman.h routines), this source file IS NOT USED by GNO's tail.
|
||||
* It is being included with the distribution only for reference, and
|
||||
* in case someone wishes to implement the -r option some day.
|
||||
*/
|
||||
|
||||
#ifndef __GNO__ /* Don't need what strings for GNO */
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)reverse.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef __GNO__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include "extern.h"
|
||||
|
||||
static void r_buf __P((FILE *));
|
||||
static void r_reg __P((FILE *, enum STYLE, long, struct stat *));
|
||||
|
||||
/*
|
||||
* reverse -- display input in reverse order by line.
|
||||
*
|
||||
* There are six separate cases for this -- regular and non-regular
|
||||
* files by bytes, lines or the whole file.
|
||||
*
|
||||
* BYTES display N bytes
|
||||
* REG mmap the file and display the lines
|
||||
* NOREG cyclically read characters into a wrap-around buffer
|
||||
*
|
||||
* LINES display N lines
|
||||
* REG mmap the file and display the lines
|
||||
* NOREG cyclically read lines into a wrap-around array of buffers
|
||||
*
|
||||
* FILE display the entire file
|
||||
* REG mmap the file and display the lines
|
||||
* NOREG cyclically read input into a linked list of buffers
|
||||
*/
|
||||
void
|
||||
#ifndef __STDC__
|
||||
reverse(fp, style, off, sbp)
|
||||
FILE *fp;
|
||||
enum STYLE style;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
#else
|
||||
reverse(FILE *fp,
|
||||
enum STYLE style,
|
||||
long off,
|
||||
struct stat *sbp)
|
||||
#endif
|
||||
{
|
||||
if (style != REVERSE && off == 0)
|
||||
return;
|
||||
|
||||
if (S_ISREG(sbp->st_mode))
|
||||
#ifdef __GNO__
|
||||
{
|
||||
printf("Sorry, this option has not been implemented.\n");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
r_reg(fp, style, off, sbp);
|
||||
#endif
|
||||
else
|
||||
switch(style) {
|
||||
case FBYTES:
|
||||
case RBYTES:
|
||||
bytes(fp, off);
|
||||
break;
|
||||
case FLINES:
|
||||
case RLINES:
|
||||
lines(fp, off);
|
||||
break;
|
||||
case REVERSE:
|
||||
r_buf(fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* r_reg -- display a regular file in reverse order by line.
|
||||
*/
|
||||
static void
|
||||
#ifndef __STDC__
|
||||
r_reg(fp, style, off, sbp)
|
||||
FILE *fp;
|
||||
register enum STYLE style;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
#else
|
||||
r_reg(FILE *fp,
|
||||
register enum STYLE style,
|
||||
long off,
|
||||
struct stat *sbp)
|
||||
#endif
|
||||
{
|
||||
register off_t size;
|
||||
register int llen;
|
||||
register char *p;
|
||||
char *start;
|
||||
|
||||
if (!(size = sbp->st_size))
|
||||
return;
|
||||
|
||||
#ifndef __GNO__
|
||||
if (size > SIZE_T_MAX) {
|
||||
errno = EFBIG;
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((start = mmap(NULL, (size_t)size,
|
||||
PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
p = start + size - 1;
|
||||
|
||||
if (style == RBYTES && off < size)
|
||||
size = off;
|
||||
|
||||
/* Last char is special, ignore whether newline or not. */
|
||||
for (llen = 1; --size; ++llen)
|
||||
if (*--p == '\n') {
|
||||
WR(p + 1, llen);
|
||||
llen = 0;
|
||||
if (style == RLINES && !--off) {
|
||||
++p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (llen)
|
||||
WR(p, llen);
|
||||
#ifndef __GNO__
|
||||
if (munmap(start, (size_t)sbp->st_size))
|
||||
ierr();
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct bf {
|
||||
struct bf *next;
|
||||
struct bf *prev;
|
||||
int len;
|
||||
char *l;
|
||||
} BF;
|
||||
|
||||
/*
|
||||
* r_buf -- display a non-regular file in reverse order by line.
|
||||
*
|
||||
* This is the function that saves the entire input, storing the data in a
|
||||
* doubly linked list of buffers and then displays them in reverse order.
|
||||
* It has the usual nastiness of trying to find the newlines, as there's no
|
||||
* guarantee that a newline occurs anywhere in the file, let alone in any
|
||||
* particular buffer. If we run out of memory, input is discarded (and the
|
||||
* user warned).
|
||||
*/
|
||||
static void
|
||||
#ifndef __STDC__
|
||||
r_buf(fp)
|
||||
FILE *fp;
|
||||
#else
|
||||
r_buf(FILE *fp)
|
||||
#endif
|
||||
{
|
||||
register BF *mark, *tl, *tr;
|
||||
register int ch, len, llen;
|
||||
register char *p;
|
||||
off_t enomem;
|
||||
|
||||
#define BSZ (128 * 1024)
|
||||
for (mark = NULL, enomem = 0;;) {
|
||||
/*
|
||||
* Allocate a new block and link it into place in a doubly
|
||||
* linked list. If out of memory, toss the LRU block and
|
||||
* keep going.
|
||||
*/
|
||||
if (enomem || (tl = malloc(sizeof(BF))) == NULL ||
|
||||
(tl->l = malloc(BSZ)) == NULL) {
|
||||
if (!mark)
|
||||
err(1, "malloc");
|
||||
tl = enomem ? tl->next : mark;
|
||||
enomem += tl->len;
|
||||
} else if (mark) {
|
||||
tl->next = mark;
|
||||
tl->prev = mark->prev;
|
||||
mark->prev->next = tl;
|
||||
mark->prev = tl;
|
||||
} else
|
||||
mark->next = mark->prev = (mark = tl);
|
||||
|
||||
/* Fill the block with input data. */
|
||||
for (p = tl->l, len = 0;
|
||||
len < BSZ && (ch = getc(fp)) != EOF; ++len)
|
||||
*p++ = ch;
|
||||
|
||||
if (ferror(fp)) {
|
||||
ierr();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no input data for this block and we tossed some data,
|
||||
* recover it.
|
||||
*/
|
||||
if (!len) {
|
||||
if (enomem)
|
||||
enomem -= tl->len;
|
||||
tl = tl->prev;
|
||||
break;
|
||||
}
|
||||
|
||||
tl->len = len;
|
||||
if (ch == EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
if (enomem) {
|
||||
warnx("warning: %ld bytes discarded\n", enomem);
|
||||
rval = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Step through the blocks in the reverse order read. The last char
|
||||
* is special, ignore whether newline or not.
|
||||
*/
|
||||
for (mark = tl;;) {
|
||||
for (p = tl->l + (len = tl->len) - 1, llen = 0; len--;
|
||||
--p, ++llen)
|
||||
if (*p == '\n') {
|
||||
if (llen) {
|
||||
WR(p + 1, llen);
|
||||
llen = 0;
|
||||
}
|
||||
if (tl == mark)
|
||||
continue;
|
||||
for (tr = tl->next; tr->len; tr = tr->next) {
|
||||
WR(tr->l, tr->len);
|
||||
tr->len = 0;
|
||||
if (tr == mark)
|
||||
break;
|
||||
}
|
||||
}
|
||||
tl->len = llen;
|
||||
if ((tl = tl->prev) == mark)
|
||||
break;
|
||||
}
|
||||
tl = tl->next;
|
||||
if (tl->len) {
|
||||
WR(tl->l, tl->len);
|
||||
tl->len = 0;
|
||||
}
|
||||
while ((tl = tl->next)->len) {
|
||||
WR(tl->l, tl->len);
|
||||
tl->len = 0;
|
||||
}
|
||||
}
|
144
bin/tail/tail.1
Normal file
144
bin/tail/tail.1
Normal file
|
@ -0,0 +1,144 @@
|
|||
.\" Copyright (c) 1980, 1990, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the University of
|
||||
.\" California, Berkeley and its contributors.
|
||||
.\" 4. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)tail.1 2.0 (GNO) 8/1/97
|
||||
.\"
|
||||
.TH TAIL 1 "August 1997" "GNO" "Commands and Applications"
|
||||
.SH NAME
|
||||
.BR tail
|
||||
\- display the last part of a file
|
||||
.SH SYNOPSIS
|
||||
.BR tail
|
||||
.RB [ -f ]
|
||||
.RB [ -b
|
||||
.IR number " |"
|
||||
.B -c
|
||||
.IR number " |"
|
||||
.B -n
|
||||
.IR number ]
|
||||
.RI [ file ...]
|
||||
.SS Obsolescent:
|
||||
.BR tail "
|
||||
.RB [ -f ]
|
||||
.RB [ + | -\fInumber [ l
|
||||
.RB "| " b " | " c ]]
|
||||
.RI [ file ...]
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.BR tail
|
||||
utility displays the contents of
|
||||
.BR file
|
||||
or, by default, its standard input, to the standard output.
|
||||
.LP
|
||||
The display begins at a byte, line or 512-byte block location in the
|
||||
input.
|
||||
Numbers having a leading plus (``+'') sign are relative to the beginning
|
||||
of the input, for example,
|
||||
.B "-c +2"
|
||||
starts the display at the second
|
||||
byte of the input.
|
||||
Numbers having a leading minus (``-'') sign or no explicit sign are
|
||||
relative to the end of the input, for example,
|
||||
.B "-n 2"
|
||||
displays the last two lines of the input.
|
||||
The default starting location is
|
||||
.BR "-n 10" ,
|
||||
or the last 10 lines of the input.
|
||||
.LP
|
||||
.SH OPTIONS
|
||||
The options are as follows:
|
||||
.RS
|
||||
.IP \fB-b\fR \fInumber\fR
|
||||
The location is
|
||||
.IR number
|
||||
512-byte blocks.
|
||||
.IP \fB-c\fR \fInumber\fR
|
||||
The location is
|
||||
.IR number
|
||||
bytes.
|
||||
.IP \fB-f\fR
|
||||
The
|
||||
.B -f
|
||||
option causes
|
||||
.BR tail
|
||||
not to stop when end of file is reached, but rather to wait for additional
|
||||
data to be appended to the input.
|
||||
The
|
||||
.B -f
|
||||
option is ignored if the standard input is a pipe, but not if it is a FIFO.
|
||||
.IP \fB-n\fR \fInumber\fR
|
||||
The location is
|
||||
.IR number
|
||||
lines.
|
||||
.RE
|
||||
.LP
|
||||
If more than a single file is specified, each file is preceded by a
|
||||
header consisting of the string
|
||||
.B "==> XXX <=="
|
||||
where
|
||||
.B XXX
|
||||
is the name of the file.
|
||||
.LP
|
||||
The
|
||||
.BR tail
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.SH ATTRIBUTIONS
|
||||
This command was ported from FreeBSD source code
|
||||
for distribution with GNO/ME 2.0.6.
|
||||
.SH SEE ALSO
|
||||
.BR cat (1),
|
||||
.BR head (1),
|
||||
.BR sed (1)
|
||||
.SH STANDARDS
|
||||
The
|
||||
.BR tail
|
||||
utility is expected to be a superset of the POSIX.2
|
||||
specification.
|
||||
In particular, the
|
||||
.BR -b
|
||||
option is an extension to that standard.
|
||||
.LP
|
||||
The historic (obsolescent) command line syntax of
|
||||
.BR tail
|
||||
is supported by this implementation.
|
||||
.SH HISTORY
|
||||
The BSD
|
||||
.B -r
|
||||
option, which causes the input to be displayed in reverse order, by line,
|
||||
has not been implemented for the GNO version of
|
||||
.BR tail .
|
||||
.PP
|
||||
Version 1.1 (18-Jan-93) of
|
||||
.BR tail ,
|
||||
shipped with GNO 2.0, was written by Sameer Parekh (zane@ddsw1.MCS.COM).
|
381
bin/tail/tail.c
Normal file
381
bin/tail/tail.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Edward Sze-Tyan Wang.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified for GNO (Apple IIGS) by Dave Tribby, July 1997
|
||||
*
|
||||
* Constructs unacceptable to compiler are replaced using #ifndef __ORCAC__
|
||||
*
|
||||
* Changes not related to compiler are replaced using #ifndef __GNO__
|
||||
* (e.g., did not implement -r option)
|
||||
*
|
||||
* Added prototyped headers, surrounded by #ifndef __STDC__
|
||||
*/
|
||||
|
||||
#ifndef __GNO__ /* Don't need what strings for GNO */
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)tail.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
#endif __GNO__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include "extern.h"
|
||||
|
||||
int fflag, rflag, rval;
|
||||
char *fname;
|
||||
|
||||
static void obsolete __P((char **));
|
||||
static void usage __P((void));
|
||||
|
||||
/* Interface to check on how much stack space a C program uses. */
|
||||
#if defined(__GNO__) && defined(__STACK_CHECK__)
|
||||
#ifndef _STDLIB_H_
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
extern void begin_stack_check(void);
|
||||
extern int end_stack_check(void);
|
||||
static void report_stack(void)
|
||||
{
|
||||
fprintf(stderr,"\n ==> %d stack bytes used <== \n", end_stack_check());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
#ifndef __STDC__
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
#else
|
||||
main(int argc,
|
||||
char *argv[])
|
||||
#endif
|
||||
{
|
||||
struct stat sb;
|
||||
FILE *fp;
|
||||
long off;
|
||||
enum STYLE style;
|
||||
int ch, first;
|
||||
char *p;
|
||||
|
||||
#if defined(__GNO__) && defined(__STACK_CHECK__)
|
||||
begin_stack_check();
|
||||
atexit(report_stack);
|
||||
#endif
|
||||
/*
|
||||
* Tail's options are weird. First, -n10 is the same as -n-10, not
|
||||
* -n+10. Second, the number options are 1 based and not offsets,
|
||||
* so -n+1 is the first line, and -c-1 is the last byte. Third, the
|
||||
* number options for the -r option specify the number of things that
|
||||
* get displayed, not the starting point in the file. The one major
|
||||
* incompatibility in this version as compared to historical versions
|
||||
* is that the 'r' option couldn't be modified by the -lbc options,
|
||||
* i.e. it was always done in lines. This version treats -rc as a
|
||||
* number of characters in reverse order. Finally, the default for
|
||||
* -r is the entire file, not 10 lines.
|
||||
*/
|
||||
/* NOTE: for GNO the -r (reverse print) option has been removed */
|
||||
#define ARG(units, forward, backward) { \
|
||||
if (style) \
|
||||
usage(); \
|
||||
off = strtol(optarg, &p, 10) * (units); \
|
||||
if (*p) \
|
||||
errx(1, "illegal offset -- %s", optarg); \
|
||||
switch(optarg[0]) { \
|
||||
case '+': \
|
||||
if (off) \
|
||||
off -= (units); \
|
||||
style = (forward); \
|
||||
break; \
|
||||
case '-': \
|
||||
off = -off; \
|
||||
/* FALLTHROUGH */ \
|
||||
default: \
|
||||
style = (backward); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
|
||||
obsolete(argv);
|
||||
style = NOTSET;
|
||||
#ifndef __GNO__ /* -r option not used in GNO */
|
||||
while ((ch = getopt(argc, argv, "b:c:fn:r")) != -1)
|
||||
#else
|
||||
while ((ch = getopt(argc, argv, "b:c:fn:")) != -1)
|
||||
#endif
|
||||
switch(ch) {
|
||||
case 'b':
|
||||
ARG(512, FBYTES, RBYTES);
|
||||
break;
|
||||
case 'c':
|
||||
ARG(1, FBYTES, RBYTES);
|
||||
break;
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
break;
|
||||
case 'n':
|
||||
ARG(1, FLINES, RLINES);
|
||||
break;
|
||||
#ifndef __GNO__
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
#endif
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
#ifndef __ORCAC__
|
||||
argv += optind;
|
||||
#else
|
||||
argv = argv + optind;
|
||||
#endif
|
||||
|
||||
if (fflag && argc > 1)
|
||||
errx(1, "-f option only appropriate for a single file");
|
||||
|
||||
#ifndef __GNO__
|
||||
/*
|
||||
* If displaying in reverse, don't permit follow option, and convert
|
||||
* style values.
|
||||
*/
|
||||
if (rflag) {
|
||||
if (fflag)
|
||||
usage();
|
||||
if (style == FBYTES)
|
||||
style = RBYTES;
|
||||
else if (style == FLINES)
|
||||
style = RLINES;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If style not specified, the default is the whole file for -r, and
|
||||
* the last 10 lines if not -r.
|
||||
*/
|
||||
if (style == NOTSET)
|
||||
#ifndef __GNO__
|
||||
if (rflag) {
|
||||
off = 0;
|
||||
style = REVERSE;
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
off = 10;
|
||||
style = RLINES;
|
||||
}
|
||||
|
||||
if (*argv)
|
||||
for (first = 1; fname = *argv++;) {
|
||||
if ((fp = fopen(fname, "r")) == NULL ||
|
||||
fstat(fileno(fp), &sb)) {
|
||||
ierr();
|
||||
continue;
|
||||
}
|
||||
if (argc > 1) {
|
||||
(void)printf("%s==> %s <==\n",
|
||||
first ? "" : "\n", fname);
|
||||
first = 0;
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
|
||||
#ifndef __GNO__
|
||||
if (rflag)
|
||||
reverse(fp, style, off, &sb);
|
||||
else
|
||||
#endif
|
||||
forward(fp, style, off, &sb);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
else {
|
||||
fname = "stdin";
|
||||
|
||||
if (fstat(fileno(stdin), &sb)) {
|
||||
ierr();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if input is a pipe. 4.4BSD will set the SOCKET
|
||||
* bit in the st_mode field for pipes. Fix this then.
|
||||
*/
|
||||
if (lseek(fileno(stdin), (off_t)0, SEEK_CUR) == -1 &&
|
||||
errno == ESPIPE) {
|
||||
errno = 0;
|
||||
fflag = 0; /* POSIX.2 requires this. */
|
||||
}
|
||||
|
||||
#ifndef __GNO__
|
||||
if (rflag)
|
||||
reverse(stdin, style, off, &sb);
|
||||
else
|
||||
#endif
|
||||
forward(stdin, style, off, &sb);
|
||||
}
|
||||
exit(rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the obsolete argument form into something that getopt can handle.
|
||||
* This means that anything of the form [+-][0-9][0-9]*[lbc][fr] that isn't
|
||||
* the option argument for a -b, -c or -n option gets converted.
|
||||
*/
|
||||
static void
|
||||
#ifndef __STDC__
|
||||
obsolete(argv)
|
||||
char *argv[];
|
||||
#else
|
||||
obsolete(char **argv)
|
||||
#endif
|
||||
{
|
||||
register char *ap, *p, *t;
|
||||
int len;
|
||||
char *start;
|
||||
|
||||
while (ap = *++argv) {
|
||||
/* Return if "--" or not an option of any form. */
|
||||
if (ap[0] != '-') {
|
||||
if (ap[0] != '+')
|
||||
return;
|
||||
} else if (ap[1] == '-')
|
||||
return;
|
||||
|
||||
switch(*++ap) {
|
||||
/* Old-style option. */
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
|
||||
/* Malloc space for dash, new option and argument. */
|
||||
len = strlen(*argv);
|
||||
if ((start = p = malloc(len + 3)) == NULL)
|
||||
err(1, "malloc");
|
||||
*p++ = '-';
|
||||
|
||||
/*
|
||||
* Go to the end of the option argument. Save off any
|
||||
* trailing options (-3lf) and translate any trailing
|
||||
* output style characters.
|
||||
*/
|
||||
t = *argv + len - 1;
|
||||
#ifndef __GNO__
|
||||
if (*t == 'f' || *t == 'r') {
|
||||
#else
|
||||
if (*t == 'f') {
|
||||
#endif
|
||||
*p++ = *t;
|
||||
*t-- = '\0';
|
||||
}
|
||||
switch(*t) {
|
||||
case 'b':
|
||||
*p++ = 'b';
|
||||
*t = '\0';
|
||||
break;
|
||||
case 'c':
|
||||
*p++ = 'c';
|
||||
*t = '\0';
|
||||
break;
|
||||
case 'l':
|
||||
*t = '\0';
|
||||
/* FALLTHROUGH */
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
*p++ = 'n';
|
||||
break;
|
||||
default:
|
||||
errx(1, "illegal option -- %s", *argv);
|
||||
}
|
||||
*p++ = *argv[0];
|
||||
(void)strcpy(p, ap);
|
||||
*argv = start;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Options w/ arguments, skip the argument and continue
|
||||
* with the next option.
|
||||
*/
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'n':
|
||||
if (!ap[1])
|
||||
++argv;
|
||||
/* FALLTHROUGH */
|
||||
/* Options w/o arguments, continue with the next option. */
|
||||
case 'f':
|
||||
#ifndef __GNO__
|
||||
case 'r':
|
||||
#endif
|
||||
continue;
|
||||
|
||||
/* Illegal option, return and let getopt handle it. */
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
#ifndef __STDC__
|
||||
usage()
|
||||
#else
|
||||
usage(void)
|
||||
#endif
|
||||
{
|
||||
#ifndef __GNO__
|
||||
(void)fprintf(stderr,
|
||||
"usage: tail [-f | -r] [-b # | -c # | -n #] [file ...]\n");
|
||||
#else /* GNO doesn't implement -r; shows obsolescent form */
|
||||
(void)fprintf(stderr,
|
||||
"usage: tail [-f] [-b # | -c # | -n #] [file ...]\n");
|
||||
(void)fprintf(stderr,
|
||||
" tail [-f] [+|-#[b|c|l]] [file ...]\n");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
9
bin/tail/tail.desc
Normal file
9
bin/tail/tail.desc
Normal file
|
@ -0,0 +1,9 @@
|
|||
Name: tail
|
||||
Version: 2.0 (August 1997)
|
||||
Shell: GNO
|
||||
Author: Dave Tribby (from FreeBSD code)
|
||||
Contact: tribby@cup.hp.com
|
||||
Where: /bin/tail
|
||||
FTP: ground.isca.uiowa.edu apple2.caltech.edu trenco.myrias.com
|
||||
|
||||
Print the last part of a file.
|
29
bin/tail/tail.rez
Normal file
29
bin/tail/tail.rez
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Resources for version and comment
|
||||
*/
|
||||
#define PROG "tail"
|
||||
#define DESC "Print the last part of a file."
|
||||
|
||||
#include "Types.rez"
|
||||
|
||||
/*
|
||||
* Version
|
||||
*/
|
||||
resource rVersion (1, purgeable3) {
|
||||
{ 2, 0, 0, /* Version 2.0.0 */
|
||||
release, /* development|alpha|beta|final|release */
|
||||
0 }, /* non-final release number */
|
||||
verUS, /* Country */
|
||||
PROG, /* Program name */
|
||||
DESC " Released with GNO/ME."
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Comment
|
||||
*/
|
||||
resource rComment (1, purgeable3) {
|
||||
PROG " v2.0 (August 1997)\n"
|
||||
"GNO utility: " DESC "\n"
|
||||
"Ported from FreeBSD code by Dave Tribby."
|
||||
};
|
Loading…
Reference in New Issue
Block a user