split.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }