tail from ftp.uu.net:bsd-sources integrated
This commit is contained in:
parent
f7d7921aae
commit
aa97860f48
|
@ -0,0 +1,6 @@
|
|||
# @(#)Makefile 5.4 (Berkeley) 7/21/91
|
||||
|
||||
PROG= tail
|
||||
SRCS= forward.c misc.c read.c reverse.c tail.c
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -0,0 +1,53 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 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 5.1 (Berkeley) 7/21/91
|
||||
*/
|
||||
|
||||
#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 *));
|
||||
|
||||
void bytes __P((FILE *, off_t));
|
||||
void lines __P((FILE *, off_t));
|
||||
|
||||
void err __P((const char *fmt, ...));
|
||||
void ierr __P((void));
|
||||
void oerr __P((void));
|
||||
|
||||
extern int fflag, rflag, rval;
|
||||
extern char *fname;
|
|
@ -0,0 +1,202 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 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 lint
|
||||
static char sccsid[] = "@(#)forward.c 5.4 (Berkeley) 2/12/92";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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
|
||||
forward(fp, style, off, sbp)
|
||||
FILE *fp;
|
||||
enum STYLE style;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
{
|
||||
register int ch;
|
||||
struct timeval second;
|
||||
fd_set zero;
|
||||
|
||||
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();
|
||||
} else while (off--)
|
||||
if ((ch = getc(fp)) == EOF) {
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLINES:
|
||||
if (off == 0)
|
||||
break;
|
||||
for (;;) {
|
||||
if ((ch = getc(fp)) == EOF) {
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
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();
|
||||
} else if (off == 0) {
|
||||
while (getc(fp) != EOF);
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
} else
|
||||
bytes(fp, off);
|
||||
break;
|
||||
case RLINES:
|
||||
if (S_ISREG(sbp->st_mode))
|
||||
if (!off) {
|
||||
if (fseek(fp, 0L, SEEK_END) == -1)
|
||||
ierr();
|
||||
} else
|
||||
rlines(fp, off, sbp);
|
||||
else if (off == 0) {
|
||||
while (getc(fp) != EOF);
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
} else
|
||||
lines(fp, off);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We pause for one second after displaying any data that has
|
||||
* accumulated since we read the file.
|
||||
*/
|
||||
if (fflag) {
|
||||
FD_ZERO(&zero);
|
||||
second.tv_sec = 1;
|
||||
second.tv_usec = 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
while ((ch = getc(fp)) != EOF)
|
||||
if (putchar(ch) == EOF)
|
||||
oerr();
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
(void)fflush(stdout);
|
||||
if (!fflag)
|
||||
break;
|
||||
/* Sleep is eight system calls. Do it fast. */
|
||||
if (select(0, &zero, &zero, &zero, &second) == -1)
|
||||
err("select: %s", strerror(errno));
|
||||
clearerr(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rlines -- display the last offset lines of the file.
|
||||
*/
|
||||
static void
|
||||
rlines(fp, off, sbp)
|
||||
FILE *fp;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
{
|
||||
register off_t size;
|
||||
register char *p;
|
||||
|
||||
if (!(size = sbp->st_size))
|
||||
return;
|
||||
|
||||
if ((p = mmap(NULL,
|
||||
size, PROT_READ, MAP_FILE, fileno(fp), (off_t)0)) == (caddr_t)-1)
|
||||
err("%s", strerror(errno));
|
||||
|
||||
/* Last char is special, ignore whether newline or not. */
|
||||
for (p += 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, sbp->st_size, SEEK_SET) == -1)
|
||||
ierr();
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 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 lint
|
||||
static char sccsid[] = "@(#)misc.c 5.1 (Berkeley) 7/21/91";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "extern.h"
|
||||
|
||||
void
|
||||
ierr()
|
||||
{
|
||||
err("%s: %s", fname, strerror(errno));
|
||||
}
|
||||
|
||||
void
|
||||
oerr()
|
||||
{
|
||||
err("stdout: %s", strerror(errno));
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
err(const char *fmt, ...)
|
||||
#else
|
||||
err(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list ap;
|
||||
#if __STDC__
|
||||
va_start(ap, fmt);
|
||||
#else
|
||||
va_start(ap);
|
||||
#endif
|
||||
(void)fprintf(stderr, "tail: ");
|
||||
(void)vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 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 lint
|
||||
static char sccsid[] = "@(#)read.c 5.1 (Berkeley) 7/21/91";
|
||||
#endif /* not lint */
|
||||
|
||||
#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 "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.
|
||||
*/
|
||||
void
|
||||
bytes(fp, off)
|
||||
register FILE *fp;
|
||||
long off;
|
||||
{
|
||||
register int ch, len, tlen;
|
||||
register char *ep, *p, *t;
|
||||
int wrap;
|
||||
char *sp;
|
||||
|
||||
if ((sp = p = malloc(off)) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
|
||||
for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
|
||||
*p = ch;
|
||||
if (++p == ep) {
|
||||
wrap = 1;
|
||||
p = sp;
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void
|
||||
lines(fp, off)
|
||||
register FILE *fp;
|
||||
long off;
|
||||
{
|
||||
struct {
|
||||
u_int blen;
|
||||
u_int len;
|
||||
char *l;
|
||||
} *lines;
|
||||
register int ch;
|
||||
register char *p;
|
||||
u_int blen, cnt, recno;
|
||||
int wrap;
|
||||
char *sp;
|
||||
|
||||
if ((lines = malloc(off * sizeof(*lines))) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
|
||||
sp = NULL;
|
||||
blen = cnt = recno = wrap = 0;
|
||||
|
||||
while ((ch = getc(fp)) != EOF) {
|
||||
if (++cnt > blen) {
|
||||
if ((sp = realloc(sp, blen += 1024)) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
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("%s", strerror(errno));
|
||||
}
|
||||
bcopy(sp, lines[recno].l, lines[recno].len = cnt);
|
||||
cnt = 0;
|
||||
p = sp;
|
||||
if (++recno == off) {
|
||||
wrap = 1;
|
||||
recno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ferror(fp))
|
||||
ierr();
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,247 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 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 lint
|
||||
static char sccsid[] = "@(#)reverse.c 5.3 (Berkeley) 2/12/92";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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
|
||||
reverse(fp, style, off, sbp)
|
||||
FILE *fp;
|
||||
enum STYLE style;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
{
|
||||
if (style != REVERSE && off == 0)
|
||||
return;
|
||||
|
||||
if (S_ISREG(sbp->st_mode))
|
||||
r_reg(fp, style, off, sbp);
|
||||
else
|
||||
switch(style) {
|
||||
case FBYTES:
|
||||
bytes(fp, off);
|
||||
break;
|
||||
case FLINES:
|
||||
lines(fp, off);
|
||||
break;
|
||||
case REVERSE:
|
||||
r_buf(fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* r_reg -- display a regular file in reverse order by line.
|
||||
*/
|
||||
static void
|
||||
r_reg(fp, style, off, sbp)
|
||||
FILE *fp;
|
||||
register enum STYLE style;
|
||||
long off;
|
||||
struct stat *sbp;
|
||||
{
|
||||
register off_t size;
|
||||
register int llen;
|
||||
register char *p;
|
||||
int fd;
|
||||
|
||||
if (!(size = sbp->st_size))
|
||||
return;
|
||||
|
||||
fd = fileno(fp);
|
||||
if ((p =
|
||||
mmap(NULL, size, PROT_READ, MAP_FILE, fd, (off_t)0)) == (caddr_t)-1)
|
||||
err("%s", strerror(errno));
|
||||
p += 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);
|
||||
}
|
||||
|
||||
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
|
||||
r_buf(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
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("%s", strerror(errno));
|
||||
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 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) {
|
||||
(void)fprintf(stderr,
|
||||
"tail: 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
.\" Copyright (c) 1980, 1990, 1991 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 6.8 (Berkeley) 2/12/92
|
||||
.\"
|
||||
.Dd February 12, 1992
|
||||
.Dt TAIL 1
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm tail
|
||||
.Nd display the last part of a file
|
||||
.Sh SYNOPSIS
|
||||
.Nm tail
|
||||
.Op Fl f Li | Fl r
|
||||
.Oo
|
||||
.Fl b Ar number |
|
||||
.Fl c Ar number |
|
||||
.Fl n Ar number
|
||||
.Oc
|
||||
.Op Ar file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm tail
|
||||
utility displays the contents of
|
||||
.Ar file
|
||||
or, by default, its standard input, to the standard output.
|
||||
.Pp
|
||||
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,
|
||||
.Dq -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,
|
||||
.Dq -n 2
|
||||
displays the last two lines of the input.
|
||||
The default starting location is
|
||||
.Dq -n 10 ,
|
||||
or the last 10 lines of the input.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl b Ar number
|
||||
The location is
|
||||
.Ar number
|
||||
512-byte blocks.
|
||||
.It Fl c Ar number
|
||||
The location is
|
||||
.Ar number
|
||||
bytes.
|
||||
.It Fl f
|
||||
The
|
||||
.Fl f
|
||||
option causes
|
||||
.Nm tail
|
||||
to not stop when end of file is reached, but rather to wait for additional
|
||||
data to be appended to the input.
|
||||
The
|
||||
.Fl f
|
||||
option is ignored on pipes but not on FIFO's.
|
||||
.It Fl n Ar number
|
||||
The location is
|
||||
.Ar number
|
||||
lines.
|
||||
.It Fl r
|
||||
The
|
||||
.Fl r
|
||||
option causes the input to be displayed in reverse order, by line.
|
||||
Additionally, this option changes the meaning of the
|
||||
.Fl b ,
|
||||
.Fl c
|
||||
and
|
||||
.Fl n
|
||||
options.
|
||||
When the
|
||||
.Fl r
|
||||
option is specified, these options specify the number of bytes, lines
|
||||
or 512-byte blocks to display, instead of the bytes, lines or blocks
|
||||
from the beginning or end of the input from which to begin the display.
|
||||
The default for the
|
||||
.Fl r
|
||||
option is to display all of the input.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm tail
|
||||
utility exits 0 on success, and >0 if an error occurs.
|
||||
.Sh SEE ALSO
|
||||
.Xr cat 1 ,
|
||||
.Xr head 1 ,
|
||||
.Xr sed 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm tail
|
||||
utility is expected to be a superset of the POSIX 1003.2
|
||||
specification.
|
||||
In particular, the
|
||||
.Fl b
|
||||
and
|
||||
.Fl r
|
||||
options are extensions to that standard.
|
||||
.Pp
|
||||
The historic command line syntax of
|
||||
.Nm tail
|
||||
is supported by this implementation.
|
||||
The only difference between this implementation and historic versions
|
||||
of
|
||||
.Nm tail ,
|
||||
once the command line syntax translation has been done, is that the
|
||||
.Fl b ,
|
||||
.Fl c
|
||||
and
|
||||
.Fl n
|
||||
options modify the
|
||||
.Fl r
|
||||
option, i.e. ``-r -c 4'' displays the last 4 characters of the last line
|
||||
of the input, while the historic tail (using the historic syntax ``-4cr'')
|
||||
would ignore the
|
||||
.Fl c
|
||||
option and display the last 4 lines of the input.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm tail
|
||||
command appeared in
|
||||
.At v7 .
|
|
@ -0,0 +1,279 @@
|
|||
/*-
|
||||
* Copyright (c) 1991 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 lint
|
||||
char copyright[] =
|
||||
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
|
||||
All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)tail.c 5.7 (Berkeley) 2/12/92";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "extern.h"
|
||||
|
||||
int fflag, rflag, rval;
|
||||
char *fname;
|
||||
|
||||
static void obsolete __P((char **));
|
||||
static void usage __P((void));
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct stat sb;
|
||||
FILE *fp;
|
||||
long off;
|
||||
enum STYLE style;
|
||||
int ch;
|
||||
char *p;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define ARG(units, forward, backward) { \
|
||||
if (style) \
|
||||
usage(); \
|
||||
off = strtol(optarg, &p, 10) * (units); \
|
||||
if (*p) \
|
||||
err("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;
|
||||
while ((ch = getopt(argc, argv, "b:c:fn:r")) != EOF)
|
||||
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;
|
||||
case 'r':
|
||||
rflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* If displaying in reverse, don't permit follow option, and convert
|
||||
* style values.
|
||||
*/
|
||||
if (rflag) {
|
||||
if (fflag)
|
||||
usage();
|
||||
if (style == FBYTES)
|
||||
style = RBYTES;
|
||||
if (style == FLINES)
|
||||
style = RLINES;
|
||||
}
|
||||
|
||||
/*
|
||||
* If style not specified, the default is the whole file for -r, and
|
||||
* the last 10 lines if not -r.
|
||||
*/
|
||||
if (style == NOTSET)
|
||||
if (rflag) {
|
||||
off = 0;
|
||||
style = REVERSE;
|
||||
} else {
|
||||
off = 10;
|
||||
style = RLINES;
|
||||
}
|
||||
|
||||
if (fname = *argv) {
|
||||
if ((fp = fopen(fname, "r")) == NULL)
|
||||
ierr();
|
||||
} else {
|
||||
fp = stdin;
|
||||
fname = "stdin";
|
||||
}
|
||||
|
||||
if (fstat(fileno(fp), &sb))
|
||||
ierr();
|
||||
|
||||
/*
|
||||
* 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(fp), 0L, SEEK_CUR) == -1 && errno == ESPIPE) {
|
||||
errno = 0;
|
||||
fflag = 0; /* POSIX.2 requires this. */
|
||||
}
|
||||
|
||||
if (rflag)
|
||||
reverse(fp, style, off, &sb);
|
||||
else
|
||||
forward(fp, 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
|
||||
obsolete(argv)
|
||||
char **argv;
|
||||
{
|
||||
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("%s", strerror(errno));
|
||||
*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;
|
||||
if (*t == 'f' || *t == 'r') {
|
||||
*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:
|
||||
err("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':
|
||||
case 'r':
|
||||
continue;
|
||||
|
||||
/* Illegal option, return and let getopt handle it. */
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: tail [-f | -r] [-b # | -c # | -n #] [file]\n");
|
||||
exit(1);
|
||||
}
|
Loading…
Reference in New Issue