Files
Arquivotheca.AIX-4.1.3/bos/usr/bin/split/split.c
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

296 lines
6.4 KiB
C

static char sccsid[] = "@(#)80 1.18 src/bos/usr/bin/split/split.c, cmdfiles, bos412, 9446C 11/14/94 16:49:33";
/*
* COMPONENT_NAME: (CMDFILES) commands that manipulate files
*
* FUNCTIONS: split
*
* ORIGINS: 3, 26, 27
*
* This module contains IBM CONFIDENTIAL code. -- (IBM
* Confidential Restricted when combined with the aggregated
* modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1985, 1994
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#include "split_msg.h"
static nl_catd catd;
#define MSGSTR(Num, Str) catgets(catd, MS_SPLIT, Num, Str)
#define atosize_t(str) ((size_t) strtoul(str, NULL, 10))
#define NUM_ALPHA 26
static size_t count = 1000; /* Default Line Count per POSIX */
static int suffix_len = 2;
static int max_outf;
static char fname[PATH_MAX+1];
static char *ofil;
static FILE *is;
static FILE *os;
static void split_by_bytes(void);
static void split_by_lines(void);
static FILE *open_file(int);
static void close_file(FILE *f);
static size_t str2num(char *);
static void usage(void);
/*
* NAME: split [-l line_count] [-a suffix_length] [file [name]]
* split -b number[k|m] [-a suffix_length] [file [name]]
*
* obsolete: split [-line_count] [-a suffix_length] [file [name]]
*
* FUNCTION: Splits a file into pieces.
* -a suffix_length The length of the suffix. Default = 2.
* -b number[k|m] The max number of bytes for each output file.
* k = Kilobytes and m = Megabytes.
* -l line_count The max number of lines for each output file.
* Default = 1000.
* file Input file name. Use "-" to specify stdin.
* name Alternate prefix. (Must not exceed PATH_MAX-1
* bytes when combined with suffix.)
*
* RETURN VALUES: 0 if no errors
* 1 if error
*/
main(int argc, char *argv[])
{
int ch, i, numargs;
int bflag = 0, lflag = 0;
char *ifil;
setlocale(LC_ALL, "");
catd = catopen(MF_SPLIT, NL_CAT_LOCALE);
ch = '\0';
while (ch != EOF) {
if (optind >= argc)
break;
ch = argv[optind][0];
if ((ch == '-') && (isdigit(argv[optind][1]))) {
count = atosize_t(argv[optind]+1);
if (bflag)
usage();
lflag++;
optind++;
} else if ((ch = getopt(argc, argv, "a:b:l:")) != EOF) {
switch(ch) {
case 'a':
suffix_len = atoi(optarg);
if (suffix_len < 0)
usage();
break;
case 'b':
count = str2num(optarg);
if (lflag)
usage();
bflag++;
break;
case 'l':
count = atosize_t(optarg);
if (bflag)
usage();
lflag++;
break;
default:
usage();
}
}
}
if (count < 1) {
if (bflag)
fprintf(stderr, MSGSTR(INVALNUMB,
"Invalid number of bytes specified\n."));
else
fprintf(stderr, MSGSTR(INVALNUML,
"Invalid number of lines specified\n."));
usage();
}
numargs = argc - optind;
if ((numargs < 0) || (numargs > 2))
usage();
/* No args or "-", use stdin */
if ((numargs < 1) || (!strcmp("-", argv[optind])))
ifil = NULL;
else
ifil = argv[optind];
/* 2nd arg, if given, is a prefix */
if (numargs == 2)
ofil = argv[optind+1];
else
ofil = "x";
if(ifil == NULL)
is = stdin;
else /* open file */
if((is=fopen(ifil,"r")) == NULL) {
fprintf(stderr,MSGSTR(INPOPNER, "cannot open input\n"));
exit(1);
}
if((strlen(ofil) + suffix_len) > PATH_MAX) {
fprintf(stderr, MSGSTR(OUTNMSIZ, "more than %d characters in output file name\n"),PATH_MAX);
exit(1);
}
for(i=0, max_outf=1; i<suffix_len; i++) {
if (max_outf > (INT_MAX/NUM_ALPHA)) {
max_outf = INT_MAX;
break;
}
max_outf *= NUM_ALPHA;
}
if (bflag)
split_by_bytes();
else
split_by_lines();
fclose(is);
exit(0);
} /* main */
static void
split_by_bytes(void)
{
int done, fnumber;
size_t i, rcount, numread;
char buffer[BUFSIZ];
for (done = 0, fnumber = 0; !done; fnumber++)
{
os = NULL;
for(i=0; i<count; i += numread) /* break file */
{
rcount = ((count - i) < BUFSIZ) ? count - i : BUFSIZ;
if ((numread = fread(buffer, 1, rcount, is)) <= 0) {
done = 1;
break; /* break out of inner loop */
}
/* open file only after we have read something */
if (os == NULL)
os = open_file(fnumber);
if (fwrite(buffer, 1, numread, os) != numread) {
perror("split");
exit(1);
}
}
close_file(os);
}
return;
} /* split_by_bytes */
static void
split_by_lines(void)
{
int done, fnumber;
size_t i;
char buffer[LINE_MAX + 1];
for (done = 0, fnumber = 0; !done; fnumber++)
{
os = NULL;
for(i=0; i<count; i++) /* break file */
{
if (fgets(buffer, LINE_MAX + 1, is) == NULL) {
done = 1;
break; /* break out of inner loop */
}
/* open file only after we have read something */
if (os == NULL)
os = open_file(fnumber);
if (fputs(buffer, os) == EOF) {
perror("split");
exit(1);
}
}
close_file(os);
}
return;
} /* split_by_lines */
static FILE *
open_file(int n)
{
int i, j;
FILE *f;
if(n >= max_outf) {
fprintf(stderr, MSGSTR(ABRTSPLT, "more than %d output files needed, aborting split\n"), max_outf);
exit(1);
}
for(i=0; ofil[i]; i++)
fname[i] = ofil[i];
for(j=suffix_len-1; j>=0; j--) {
fname[i+j] = n%NUM_ALPHA + 'a';
n /= NUM_ALPHA;
}
i += suffix_len;
fname[i] = '\0';
if((f=fopen(fname,"w")) == NULL) {
perror("split");
exit(1);
}
return f;
} /* open_file */
static void
close_file(FILE *f)
{
if ((f != NULL) && (fclose(f) == EOF)) {
perror("split");
exit(1);
}
return;
} /* close_file */
static size_t
str2num(char *str)
{
char *endptr;
size_t val, mult;
val = (size_t) strtoul(str, &endptr, 10);
switch(*endptr) {
case '\0':
mult = 1; break;
case 'k':
mult = 1024;
break;
case 'm':
mult = 1048576;
break;
default:
fprintf(stderr, MSGSTR(INVALMULT,
"Invalid multiplier specified.\n"));
usage();
}
return (val * mult);
} /* str2num */
static void
usage(void)
{
fprintf(stderr,MSGSTR(USAGE, "usage: split [-l line_count] [-a suffix_length] [file [name]]\n or: split -b number[k|m] [-a suffix_length] [file [name]]\n"));
exit(1);
} /* usage */