tab as a printing character; bug report 4.3BSD/ucb/9
[unix-history] / usr / src / usr.bin / split / split.c
CommitLineData
460f3462
KB
1static char *sccsid = "@(#)split.c 4.3 (Berkeley) %G%";
2
3#include <sys/param.h>
4#include <sys/file.h>
f37d3151 5#include <stdio.h>
460f3462
KB
6#include <ctype.h>
7
8#define DEFLINE 1000 /* default num lines per file */
9#define ERR -1 /* general error */
10#define ERREXIT 0 /* error exit */
11#define NO 0 /* no/false */
12#define OK 0 /* okay exit */
13#define YES 1 /* yes/true */
f37d3151 14
460f3462
KB
15static long bytecnt, /* byte count to split on */
16 numlines; /* lines in each file */
17static int ifd = ERR, /* input file descriptor */
18 ofd = ERR; /* output file descriptor */
19static short file_open; /* if a file open */
20static char bfr[MAXBSIZE], /* I/O buffer */
21 fname[MAXPATHLEN]; /* file name */
f37d3151 22
460f3462
KB
23main(argc,argv)
24int argc;
25char **argv;
f37d3151 26{
460f3462
KB
27 register int cnt; /* general counter */
28 long atol();
29 char *strcpy();
f37d3151 30
460f3462
KB
31 for (cnt = 1;cnt < argc;++cnt) {
32 if (argv[cnt][0] == '-')
33 switch(argv[cnt][1]) {
34 case 0: /* stdin by request */
35 if (ifd != ERR)
36 usage();
37 ifd = 0;
38 break;
39 case 'b': /* byte count split */
40 if (numlines)
41 usage();
42 if (!argv[cnt][2])
43 bytecnt = atol(argv[++cnt]);
44 else
45 bytecnt = atol(argv[cnt] + 2);
46 if (bytecnt <= 0) {
47 fputs("split: byte count must be greater than zero.\n",stderr);
48 usage();
49 }
50 break;
51 default:
52 if (!isdigit(argv[cnt][1]) || bytecnt)
53 usage();
54 if ((numlines = atol(argv[cnt] + 2)) <= 0) {
55 fputs("split: line count must be greater than zero.\n",stderr);
56 usage();
57 }
58 break;
59 }
60 else if (ifd == ERR) { /* input file */
61 if ((ifd = open(argv[cnt],O_RDONLY,0)) < 0) {
62 perror(argv[cnt]);
63 exit(ERREXIT);
f37d3151 64 }
f37d3151 65 }
460f3462
KB
66 else if (!*fname) /* output file prefix */
67 strcpy(fname,argv[cnt]);
68 else
69 usage();
70 }
71 if (ifd == ERR) /* stdin by default */
72 ifd = 0;
73 if (bytecnt)
74 split1();
75 if (!numlines)
76 numlines = DEFLINE;
77 split2();
78}
79
80/*
81 * split1 --
82 * split by bytes
83 */
84static
85split1()
86{
87 register long bcnt; /* byte counter */
88 register int dist, /* buffer offset */
89 len; /* read length */
90 register char *C; /* tmp pointer into buffer */
91
92 for (bcnt = 0;;)
93 switch(len = read(ifd,bfr,MAXBSIZE)) {
94 case 0:
95 exit(OK);
96 case ERR:
97 perror("read");
98 exit(ERREXIT);
99 default:
100 if (!file_open) {
101 newfile();
102 file_open = YES;
103 }
104 if (bcnt + len >= bytecnt) {
105 dist = bytecnt - bcnt;
106 write(ofd,bfr,dist);
107 len -= dist;
108 for (C = bfr + dist;len >= bytecnt;len -= bytecnt,C += bytecnt) {
109 newfile();
110 write(ofd,C,(int)bytecnt);
111 }
112 if (len) {
113 newfile();
114 write(ofd,C,len);
115 }
116 else
117 file_open = NO;
118 bcnt = len;
119 }
120 else {
121 bcnt += len;
122 write(ofd,bfr,len);
123 }
124 }
125}
126
127/*
128 * split2 --
129 * split by lines
130 */
131static
132split2()
133{
134 register char *Ce, /* start/end pointers */
135 *Cs;
136 register long lcnt; /* line counter */
137 register int len; /* read length */
138
139 for (lcnt = 0;;)
140 switch(len = read(ifd,bfr,MAXBSIZE)) {
141 case 0:
142 exit(0);
143 case ERR:
144 perror("read");
145 break;
146 default:
147 if (!file_open) {
148 newfile();
149 file_open = YES;
150 }
151 for (Cs = Ce = bfr;len--;Ce++)
152 if (*Ce == '\n' && ++lcnt == numlines) {
153 write(ofd,Cs,(int)(Ce - Cs) + 1);
154 lcnt = 0;
155 Cs = Ce + 1;
156 if (len)
157 newfile();
158 else
159 file_open = NO;
160 }
161 if (Cs < Ce)
162 write(ofd,Cs,(int)(Ce - Cs));
f37d3151 163 }
460f3462 164}
f37d3151 165
460f3462
KB
166/*
167 * newfile --
168 * open a new file
169 */
170static
171newfile()
172{
173 static long fnum; /* file name counter */
174 static short defname; /* using default name, "x" */
175 static char *fpnt; /* output file name pointer */
176
177 if (ofd == ERR) {
178 if (fname[0]) {
179 fpnt = fname + strlen(fname);
180 defname = NO;
f37d3151 181 }
460f3462
KB
182 else {
183 fname[0] = 'x';
184 fpnt = fname + 1;
185 defname = YES;
186 }
187 ofd = fileno(stdout);
188 }
189 /*
190 * hack to increase max files; original code just wandered through
191 * magic characters. Maximum files is 3 * 26 * 26 == 2028
192 */
193#define MAXFILES 676
194 if (fnum == MAXFILES) {
195 if (!defname || fname[0] == 'z') {
196 fputs("split: too many files.\n",stderr);
197 exit(ERREXIT);
f37d3151 198 }
460f3462
KB
199 ++fname[0];
200 fnum = 0;
201 }
202 fpnt[0] = fnum / 26 + 'a';
203 fpnt[1] = fnum % 26 + 'a';
204 ++fnum;
205 if (!freopen(fname,"w",stdout)) {
206 fprintf(stderr,"split: unable to write to %s.\n",fname);
207 exit(ERR);
208 }
209}
210
211/*
212 * usage --
213 * print usage message and die
214 */
215static
216usage()
217{
218 fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n",stderr);
219 exit(ERREXIT);
f37d3151 220}