sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

split.c (2086B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <ctype.h>
      3 #include <stdint.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 
      8 #include "util.h"
      9 
     10 static int base = 26, start = 'a';
     11 
     12 static int
     13 itostr(char *str, int x, int n)
     14 {
     15 	str[n] = '\0';
     16 	while (n-- > 0) {
     17 		str[n] = start + (x % base);
     18 		x /= base;
     19 	}
     20 
     21 	return x ? -1 : 0;
     22 }
     23 
     24 static FILE *
     25 nextfile(FILE *f, char *buf, int plen, int slen)
     26 {
     27 	static int filecount = 0;
     28 
     29 	if (f)
     30 		fshut(f, "<file>");
     31 	if (itostr(buf + plen, filecount++, slen) < 0)
     32 		return NULL;
     33 
     34 	if (!(f = fopen(buf, "w")))
     35 		eprintf("'%s':", buf);
     36 
     37 	return f;
     38 }
     39 
     40 static void
     41 usage(void)
     42 {
     43 	eprintf("usage: %s [-a num] [-b num[k|m|g] | -l num] [-d] "
     44 	        "[file [prefix]]\n", argv0);
     45 }
     46 
     47 int
     48 main(int argc, char *argv[])
     49 {
     50 	FILE *in = stdin, *out = NULL;
     51 	off_t size = 1000, n;
     52 	int ret = 0, ch, plen, slen = 2, always = 0;
     53 	char name[NAME_MAX + 1], *prefix = "x", *file = NULL;
     54 
     55 	ARGBEGIN {
     56 	case 'a':
     57 		slen = estrtonum(EARGF(usage()), 0, INT_MAX);
     58 		break;
     59 	case 'b':
     60 		always = 1;
     61 		if ((size = parseoffset(EARGF(usage()))) < 0)
     62 			return 1;
     63 		if (!size)
     64 			eprintf("size needs to be positive\n");
     65 		break;
     66 	case 'd':
     67 		base = 10;
     68 		start = '0';
     69 		break;
     70 	case 'l':
     71 		always = 0;
     72 		size = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SSIZE_MAX));
     73 		break;
     74 	default:
     75 		usage();
     76 	} ARGEND
     77 
     78 	if (*argv)
     79 		file = *argv++;
     80 	if (*argv)
     81 		prefix = *argv++;
     82 	if (*argv)
     83 		usage();
     84 
     85 	plen = strlen(prefix);
     86 	if (plen + slen > NAME_MAX)
     87 		eprintf("names cannot exceed %d bytes\n", NAME_MAX);
     88 	estrlcpy(name, prefix, sizeof(name));
     89 
     90 	if (file && strcmp(file, "-")) {
     91 		if (!(in = fopen(file, "r")))
     92 			eprintf("fopen %s:", file);
     93 	}
     94 
     95 	n = 0;
     96 	while ((ch = getc(in)) != EOF) {
     97 		if (!out || n >= size) {
     98 			if (!(out = nextfile(out, name, plen, slen)))
     99 				eprintf("fopen: %s:", name);
    100 			n = 0;
    101 		}
    102 		n += (always || ch == '\n');
    103 		putc(ch, out);
    104 	}
    105 
    106 	ret |= (in != stdin) && fshut(in, "<infile>");
    107 	ret |= out && (out != stdout) && fshut(out, "<outfile>");
    108 	ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
    109 
    110 	return ret;
    111 }