xref: /csrg-svn/usr.bin/split/split.c (revision 30126)
1 static char *sccsid = "@(#)split.c	4.3 (Berkeley) 11/20/86";
2 
3 #include <sys/param.h>
4 #include <sys/file.h>
5 #include <stdio.h>
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 */
14 
15 static long	bytecnt,		/* byte count to split on */
16 		numlines;		/* lines in each file */
17 static int	ifd = ERR,		/* input file descriptor */
18 		ofd = ERR;		/* output file descriptor */
19 static short	file_open;		/* if a file open */
20 static char	bfr[MAXBSIZE],		/* I/O buffer */
21 		fname[MAXPATHLEN];	/* file name */
22 
23 main(argc,argv)
24 int	argc;
25 char	**argv;
26 {
27 	register int	cnt;		/* general counter */
28 	long	atol();
29 	char	*strcpy();
30 
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);
64 			}
65 		}
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  */
84 static
85 split1()
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  */
131 static
132 split2()
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));
163 		}
164 }
165 
166 /*
167  * newfile --
168  *	open a new file
169  */
170 static
171 newfile()
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;
181 		}
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);
198 		}
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  */
215 static
216 usage()
217 {
218 	fputs("usage: split [-] [-#] [-b byte_count] [file [prefix]]\n",stderr);
219 	exit(ERREXIT);
220 }
221