Harald Arnesen [28.03.2020 15:31]:

> Since my previous attempt at providing a tail command for FreeDOS didn't
> work out, here is another go. Taken directly from 4.3BSD
> <https://www.tuhs.org/Archive/Distributions/UCB/4.3BSD/src.tar.gz>,
> with one small change.

A cleaned-up version. Compiles without errors with Watcom C.
-- 
Hilsen Harald
/*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#ifndef lint
char copyright[] =
    "@(#) Copyright (c) 1980 Regents of the University of California.\n\
 All rights reserved.\n";
#endif

#ifndef lint
char sccsid[] = "@(#)tail.c	5.2 (Berkeley) 1/10/86";
#endif

/* tail command
 *
 *	tail where [file]
 *	where is +/-n[type]
 *	- means n lines before end
 *	+ means nth line from beginning
 *	type 'b' means tail n blocks, not lines
 *	type 'c' means tail n characters
 *	Type 'r' means in lines in reverse order from end
 *	 (for -r, default is entire buffer )
 *	option 'f' means loop endlessly trying to read more
 *		characters after the end of file, on the  assumption
 *		that the file is growing
*/

#include	<stdio.h>
#include	<stdlib.h>
#include	<ctype.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<fcntl.h>
#include	<unistd.h>
#include	<errno.h>

#define LBIN 32769
#undef	BUFSIZ
#define	BUFSIZ	8192
struct stat statb;
int follow;
int piped;
char bin[LBIN];
int errno;

void fexit(void);

int main(int argc, char **argv)
{
	long n, di, i, j, k;
	char *arg;
	int partial, bylines, bkwds, fromend, lastnl;
	char *p;

	arg = argv[1];
	if (argc <= 1 || (*arg != '-' && *arg != '+')) {
		arg = "-10l";
		argc++;
		argv--;
	}
	fromend = *arg == '-';
	arg++;
	if (isdigit(*arg)) {
		n = 0;
		while (isdigit(*arg))
			n = n * 10 + *arg++ - '0';
	} else
		n = -1;
	if (!fromend && n > 0)
		n--;
	if (argc > 2) {
		(void)close(0);
		if (open(argv[2], 0) != 0) {
			perror(argv[2]);
			return EXIT_FAILURE;
		}
	}
	(void)lseek(0, (off_t) 0, SEEK_CUR);
	piped = errno == ESPIPE;
	bylines = -1;
	bkwds = 0;
	while (*arg)
		switch (*arg++) {

		case 'b':
			if (n == -1)
				n = 1;
			n <<= 9;
			if (bylines != -1)
				goto errcom;
			bylines = 0;
			break;
		case 'c':
			if (bylines != -1)
				goto errcom;
			bylines = 0;
			break;
		case 'f':
			follow = 1;
			break;
		case 'r':
			if (n == -1)
				n = LBIN;
			bkwds = 1;
			fromend = 1;
			bylines = 1;
			break;
		case 'l':
			if (bylines != -1)
				goto errcom;
			bylines = 1;
			break;
		default:
			goto errcom;
		}
	if (n == -1)
		n = 10;
	if (bylines == -1)
		bylines = 1;
	if (bkwds)
		follow = 0;
	if (fromend)
		goto keep;

	/*seek from beginning */

	if (bylines) {
		j = 0;
		while (n-- > 0) {
			do {
				if (j-- <= 0) {
					p = bin;
					j = read(0, p, BUFSIZ);
					if (j-- <= 0)
						fexit();
				}
			} while (*p++ != '\n');
		}
		(void)write(1, p, j);
	} else if (n > 0) {
		if (!piped)
			(void)fstat(0, &statb);
		if (piped || (statb.st_mode & S_IFMT) == S_IFCHR)
			while (n > 0) {
				i = n > BUFSIZ ? BUFSIZ : n;
				i = read(0, bin, i);
				if (i <= 0)
					fexit();
				n -= i;
		} else
			(void)lseek(0, (off_t) n, SEEK_SET);
	}
      copy:
	while ((i = read(0, bin, BUFSIZ)) > 0)
		(void)write(1, bin, i);
	fexit();

	/*seek from end */

      keep:
	if (n <= 0)
		fexit();
	if (!piped) {
		(void)fstat(0, &statb);
		/* If by lines, back up 1 buffer: else back up as needed */
		di = bylines ? LBIN - 1 : n;
		if (statb.st_size > di)
			(void)lseek(0, (off_t) - di, SEEK_END);
		if (!bylines)
			goto copy;
	}
	partial = 1;
	for (;;) {
		i = 0;
		do {
			j = read(0, &bin[i], LBIN - i);
			if (j <= 0)
				goto brka;
			i += j;
		} while (i < LBIN);
		partial = 0;
	}
      brka:
	if (!bylines) {
		k = n <= i ? i - n :
		    partial ? 0 : n >= LBIN ? i + 1 : i - n + LBIN;
		k--;
	} else {
		if (bkwds && bin[i == 0 ? LBIN - 1 : i - 1] != '\n') {	/* force trailing newline */
			bin[i] = '\n';
			if (++i >= LBIN) {
				i = 0;
				partial = 0;
			}
		}
		k = i;
		j = 0;
		do {
			lastnl = k;
			do {
				if (--k < 0) {
					if (partial) {
						if (bkwds)
							(void)write(1, bin,
								    lastnl + 1);
						goto brkb;
					}
					k = LBIN - 1;
				}
			} while (bin[k] != '\n' && k != i);
			if (bkwds && j > 0) {
				if (k < lastnl)
					(void)write(1, &bin[k + 1], lastnl - k);
				else {
					(void)write(1, &bin[k + 1],
						    LBIN - k - 1);
					(void)write(1, bin, lastnl + 1);
				}
			}
		} while (j++ < n && k != i);
	      brkb:
		if (bkwds)
			return EXIT_FAILURE;
		if (k == i)
			do {
				if (++k >= LBIN)
					k = 0;
			} while (bin[k] != '\n' && k != i);
	}
	if (k < i)
		(void)write(1, &bin[k + 1], i - k - 1);
	else {
		(void)write(1, &bin[k + 1], LBIN - k - 1);
		(void)write(1, bin, i);
	}
	fexit();
      errcom:
	fprintf(stderr, "usage: tail [+_[n][lbc][rf]] [file]\n");
	return EXIT_SUCCESS;
}

void fexit()
{
	int n;
	if (!follow || piped)
		exit(0);
	for (;;) {
		sleep(1);
		while ((n = read(0, bin, BUFSIZ)) > 0)
			(void)write(1, bin, n);
	}
}
_______________________________________________
Freedos-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freedos-devel

Reply via email to