- initial checkin, as submitted by Dave Tribby

- renamed makefile.mk to Makefile
This commit is contained in:
gdr 1997-09-17 06:24:18 +00:00
parent fb3ab1728f
commit 590e077340
10 changed files with 1566 additions and 0 deletions

11
bin/tail/Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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."
};