split: Further option parsing improvements.

* Whenever possible, use strtonum() to parse numeric arguments.
* Improve usefulness and consistency of error messages.
* While here, fix some type and style issues.

Sponsored by:	Klara, Inc.
Reviewed by:	christos, kevans
Differential Revision:	https://reviews.freebsd.org/D42010
This commit is contained in:
Dag-Erling Smørgrav 2023-09-28 18:29:52 +02:00
parent 94cae4cb33
commit d7399551b0

View file

@ -63,7 +63,7 @@ static const char sccsid[] = "@(#)split.c 8.2 (Berkeley) 4/16/94";
#define DEFLINE 1000 /* Default num lines per file. */
static off_t bytecnt; /* Byte count to split on. */
static off_t chunks = 0; /* Chunks count to split into. */
static long chunks; /* Chunks count to split into. */
static bool clobber = true; /* Whether to overwrite existing output files. */
static long numlines; /* Line count to split on. */
static int file_open; /* If a file open. */
@ -73,7 +73,7 @@ static regex_t rgx;
static int pflag;
static bool dflag;
static long sufflen = 2; /* File name suffix length. */
static int autosfx = 1; /* Whether to auto-extend the suffix length. */
static bool autosfx = true; /* Whether to auto-extend the suffix length. */
static void newfile(void);
static void split1(void);
@ -84,8 +84,8 @@ static void usage(void) __dead2;
int
main(int argc, char **argv)
{
const char *p;
char *ep;
char errbuf[64];
const char *p, *errstr;
int ch, error;
setlocale(LC_ALL, "");
@ -106,20 +106,22 @@ main(int argc, char **argv)
while (numlines >= 0 && *p >= '0' && *p <= '9')
numlines = numlines * 10 + *p++ - '0';
if (numlines <= 0 || *p != '\0')
errx(EX_USAGE, "%c%s: illegal line count", ch,
optarg ? optarg : "");
errx(EX_USAGE, "%c%s: line count is invalid",
ch, optarg ? optarg : "");
break;
case 'a': /* Suffix length */
if ((sufflen = strtol(optarg, &ep, 10)) <= 0 || *ep)
errx(EX_USAGE,
"%s: illegal suffix length", optarg);
autosfx = 0;
sufflen = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
errx(EX_USAGE, "%s: suffix length is %s",
optarg, errstr);
}
autosfx = false;
break;
case 'b': /* Byte count. */
errno = 0;
error = expand_number(optarg, &bytecnt);
if (error == -1)
errx(EX_USAGE, "%s: offset too large", optarg);
if (expand_number(optarg, &bytecnt) != 0) {
errx(EX_USAGE, "%s: byte count is invalid",
optarg);
}
break;
case 'c': /* Continue, don't overwrite output files. */
clobber = false;
@ -130,22 +132,27 @@ main(int argc, char **argv)
case 'l': /* Line count. */
if (numlines != 0)
usage();
if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep)
errx(EX_USAGE,
"%s: illegal line count", optarg);
numlines = strtonum(optarg, 1, LONG_MAX, &errstr);
if (errstr != NULL) {
errx(EX_USAGE, "%s: line count is %s",
optarg, errstr);
}
break;
case 'n': /* Chunks. */
if (!isdigit((unsigned char)optarg[0]) ||
(chunks = (size_t)strtoul(optarg, &ep, 10)) == 0 ||
*ep != '\0') {
errx(EX_USAGE, "%s: illegal number of chunks",
optarg);
chunks = strtonum(optarg, 1, LONG_MAX, &errstr);
if (errstr != NULL) {
errx(EX_USAGE, "%s: number of chunks is %s",
optarg, errstr);
}
break;
case 'p': /* pattern matching. */
if (regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB) != 0)
errx(EX_USAGE, "%s: illegal regexp", optarg);
error = regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB);
if (error != 0) {
regerror(error, &rgx, errbuf, sizeof(errbuf));
errx(EX_USAGE, "%s: regex is invalid: %s",
optarg, errbuf);
}
pflag = 1;
break;
default:
@ -163,9 +170,10 @@ main(int argc, char **argv)
--argc;
}
if (argc > 0) { /* File name prefix. */
if (strlcpy(fname, *argv, sizeof(fname)) >= sizeof(fname))
errx(EX_USAGE, "file name prefix is too long: %s",
if (strlcpy(fname, *argv, sizeof(fname)) >= sizeof(fname)) {
errx(EX_USAGE, "%s: file name prefix is too long",
*argv);
}
++argv;
--argc;
}
@ -182,16 +190,16 @@ main(int argc, char **argv)
else if (bytecnt != 0 || chunks != 0)
usage();
if (bytecnt && chunks)
if (bytecnt != 0 && chunks != 0)
usage();
if (ifd == -1) /* Stdin by default. */
ifd = 0;
if (bytecnt) {
if (bytecnt != 0) {
split1();
exit (0);
} else if (chunks) {
} else if (chunks != 0) {
split3();
exit (0);
}
@ -225,7 +233,7 @@ split1(void)
/* NOTREACHED */
default:
if (!file_open) {
if (!chunks || (nfiles < chunks)) {
if (chunks == 0 || nfiles < chunks) {
newfile();
nfiles++;
}
@ -236,24 +244,24 @@ split1(void)
err(EX_IOERR, "write");
len -= dist;
for (C = bfr + dist; len >= bytecnt;
len -= bytecnt, C += bytecnt) {
if (!chunks || (nfiles < chunks)) {
newfile();
len -= bytecnt, C += bytecnt) {
if (chunks == 0 || nfiles < chunks) {
newfile();
nfiles++;
}
if (write(ofd,
C, bytecnt) != bytecnt)
if (write(ofd, C, bytecnt) != bytecnt)
err(EX_IOERR, "write");
}
if (len != 0) {
if (!chunks || (nfiles < chunks)) {
newfile();
if (chunks == 0 || nfiles < chunks) {
newfile();
nfiles++;
}
if (write(ofd, C, len) != len)
err(EX_IOERR, "write");
} else
} else {
file_open = 0;
}
bcnt = len;
} else {
bcnt += len;