splice

Data stream splicer
git clone https://git.sinitax.com/sinitax/splice
Log | Files | Refs | LICENSE | sfeed.txt

splice.c (1376B)


      1#include <err.h>
      2#include <stdio.h>
      3#include <stdint.h>
      4#include <stdlib.h>
      5
      6#define MIN(a, b) ((a) < (b) ? (a) : (b))
      7
      8int
      9main(int argc, const char **argv)
     10{
     11	char buf[BUFSIZ];
     12	ssize_t start, end;
     13	ssize_t pos, nread, nreq;
     14	FILE *main_file;
     15	char *endc;
     16	int ret;
     17
     18	if (argc < 3 || argc > 4) {
     19		fprintf(stderr, "USAGE: splice MAIN START [END]\n");
     20		return 0;
     21	}
     22
     23	main_file = fopen(argv[1], "rb");
     24	if (!main_file) err(1, "fopen %s", argv[1]);
     25
     26	start = strtoll(argv[2], &endc, 0);
     27	if (endc && *endc) err(1, "strtoll %s", argv[2]);
     28	if (start < 0) errx(1, "negative start");
     29
     30	if (argc == 4) {
     31		end = strtoll(argv[3], &endc, 0);
     32		if (endc && *endc) err(1, "strtoll %s", argv[3]);
     33		if (start >= end) errx(1, "invalid end");
     34	} else {
     35		end = -1;
     36	}
     37
     38	pos = 0;
     39	while (!feof(main_file) || !feof(stdin)) {
     40		if (pos >= start && (pos < end || !feof(stdin))) {
     41			if (feof(stdin)) errx(1, "input truncated");
     42			nreq = end >= 0 ? MIN(BUFSIZ, end - start) : BUFSIZ;
     43			nread = fread(buf, 1, nreq, stdin);
     44			if (pos == start && end >= 0)
     45				fseek(main_file, end, SEEK_SET);
     46			else if (end < 0)
     47				fseek(main_file, nread, SEEK_CUR);
     48		} else {
     49			nreq = pos < start ? MIN(BUFSIZ, start - pos) : BUFSIZ;
     50			nread = fread(buf, 1, nreq, main_file);
     51		}
     52		if (fwrite(buf, 1, nread, stdout) != nread)
     53			errx(1, "output truncated");
     54		pos += nread;
     55	}
     56
     57	fclose(main_file);
     58}