morpheus-base

morpheus base system
git clone git://git.2f30.org/morpheus-base
Log | Files | Refs

tail.c (1845B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <unistd.h>
      6 
      7 #include "text.h"
      8 #include "util.h"
      9 
     10 static void dropinit(FILE *, const char *, long);
     11 static void taketail(FILE *, const char *, long);
     12 
     13 static void
     14 usage(void)
     15 {
     16 	eprintf("usage: %s [-n lines] [file]\n", argv0);
     17 }
     18 
     19 int
     20 main(int argc, char *argv[])
     21 {
     22 	long n = 10;
     23 	FILE *fp;
     24 	void (*tail)(FILE *, const char *, long) = taketail;
     25 	char *lines;
     26 	int ret = 0;
     27 	int newline, many;
     28 
     29 	ARGBEGIN {
     30 	case 'n':
     31 		lines = EARGF(usage());
     32 		n = abs(estrtol(lines, 0));
     33 		if (lines[0] == '+')
     34 			tail = dropinit;
     35 		break;
     36 	ARGNUM:
     37 		n = ARGNUMF(0);
     38 		break;
     39 	default:
     40 		usage();
     41 	} ARGEND;
     42 	if (argc == 0) {
     43 		tail(stdin, "<stdin>", n);
     44 	} else {
     45 		many = argc > 1;
     46 		for (newline = 0; argc > 0; argc--, argv++) {
     47 			if (!(fp = fopen(argv[0], "r"))) {
     48 				weprintf("fopen %s:", argv[0]);
     49 				ret = 1;
     50 				continue;
     51 			}
     52 			if (many)
     53 				printf("%s==> %s <==\n",
     54 				       newline ? "\n" : "", argv[0]);
     55 			newline = 1;
     56 			tail(fp, argv[0], n);
     57 			fclose(fp);
     58 		}
     59 	}
     60 	return ret;
     61 }
     62 
     63 static void
     64 dropinit(FILE *fp, const char *str, long n)
     65 {
     66 	char *buf = NULL;
     67 	size_t size = 0;
     68 	ssize_t len;
     69 	unsigned long i = 0;
     70 
     71 	while (i < n && ((len = getline(&buf, &size, fp)) != -1))
     72 		if (len && buf[len - 1] == '\n')
     73 			i++;
     74 	free(buf);
     75 	concat(fp, str, stdout, "<stdout>");
     76 }
     77 
     78 static void
     79 taketail(FILE *fp, const char *str, long n)
     80 {
     81 	char **ring = NULL;
     82 	long i, j;
     83 	size_t *size = NULL;
     84 
     85 	ring = ecalloc(n, sizeof *ring);
     86 	size = ecalloc(n, sizeof *size);
     87 
     88 	for (i = j = 0; getline(&ring[i], &size[i], fp) != -1; i = j = (i + 1) % n)
     89 		;
     90 	if (ferror(fp))
     91 		eprintf("%s: read error:", str);
     92 
     93 	do {
     94 		if (ring[j]) {
     95 			fputs(ring[j], stdout);
     96 			free(ring[j]);
     97 		}
     98 	} while ((j = (j+1)%n) != i);
     99 	free(ring);
    100 	free(size);
    101 }