Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/bin/date Provide real error messages.
details: https://anonhg.NetBSD.org/src/rev/4b85004f09fe
branches: trunk
changeset: 331953:4b85004f09fe
user: dholland <dholland%NetBSD.org@localhost>
date: Mon Sep 01 21:42:21 2014 +0000
description:
Provide real error messages.
Inspired by PR 49169 from David H. Gutteridge, but a much broader patch :-)
diffstat:
bin/date/date.c | 135 ++++++++++++++++++++++++++++++++-----------------------
1 files changed, 79 insertions(+), 56 deletions(-)
diffs (262 lines):
diff -r 11ff42244edc -r 4b85004f09fe bin/date/date.c
--- a/bin/date/date.c Mon Sep 01 19:46:55 2014 +0000
+++ b/bin/date/date.c Mon Sep 01 21:42:21 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $ */
+/* $NetBSD: date.c,v 1.61 2014/09/01 21:42:21 dholland Exp $ */
/*
* Copyright (c) 1985, 1987, 1988, 1993
@@ -40,7 +40,7 @@
#if 0
static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $");
+__RCSID("$NetBSD: date.c,v 1.61 2014/09/01 21:42:21 dholland Exp $");
#endif
#endif /* not lint */
@@ -66,9 +66,7 @@
static time_t tval;
static int aflag, jflag, rflag, nflag;
-__dead static void badformat(void);
-__dead static void badtime(void);
-__dead static void badvalue(const char *);
+__dead static void badcanotime(const char *, const char *, size_t);
static void setthetime(const char *);
__dead static void usage(void);
@@ -94,9 +92,10 @@
case 'd':
rflag = 1;
tval = parsedate(optarg, NULL, NULL);
- if (tval == -1)
-badarg: errx(EXIT_FAILURE,
- "Cannot parse `%s'", optarg);
+ if (tval == -1) {
+ errx(EXIT_FAILURE,
+ "%s: Unrecognized date format", optarg);
+ }
break;
case 'j': /* don't set time */
jflag = 1;
@@ -105,13 +104,18 @@
nflag = 1;
break;
case 'r': /* user specified seconds */
+ if (optarg[0] == '\0') {
+ errx(EXIT_FAILURE, "<empty>: Invalid number");
+ }
errno = 0;
val = strtoll(optarg, &buf, 0);
- if (optarg[0] == '\0' || *buf != '\0')
- goto badarg;
- if (errno == ERANGE && (val == LLONG_MAX ||
- val == LLONG_MIN))
- err(EXIT_FAILURE, "Bad number `%s'", optarg);
+ if (errno) {
+ err(EXIT_FAILURE, "%s", optarg);
+ }
+ if (optarg[0] == '\0' || *buf != '\0') {
+ errx(EXIT_FAILURE,
+ "%s: Invalid number", optarg);
+ }
rflag = 1;
tval = (time_t)val;
break;
@@ -148,7 +152,7 @@
goto bad;
if ((tm = localtime(&tval)) == NULL)
- err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
+ err(EXIT_FAILURE, "%lld: localtime", (long long)tval);
while (strftime(buf, bufsiz, format, tm) == 0)
if ((buf = realloc(buf, bufsiz <<= 1)) == NULL)
@@ -162,23 +166,11 @@
}
static void
-badformat(void)
-{
- warnx("illegal time format");
- usage();
-}
-
-static void
-badtime(void)
+badcanotime(const char *msg, const char *val, size_t where)
{
- errx(EXIT_FAILURE, "illegal time");
- /* NOTREACHED */
-}
-
-static void
-badvalue(const char *param)
-{
- warnx("invalid %s supplied", param);
+ warnx("%s in canonical time", msg);
+ warnx("%s", val);
+ warnx("%*s", (int)where + 1, "^");
usage();
}
@@ -190,44 +182,52 @@
struct timeval tv;
time_t new_time;
struct tm *lt;
- const char *dot, *t;
+ const char *dot, *t, *op;
size_t len;
int yearset;
for (t = p, dot = NULL; *t; ++t) {
- if (isdigit((unsigned char)*t))
- continue;
- if (*t == '.' && dot == NULL) {
- dot = t;
- continue;
+ if (*t == '.') {
+ if (dot == NULL) {
+ dot = t;
+ } else {
+ badcanotime("Unexpected dot", p, t - p);
+ }
+ } else if (!isdigit((unsigned char)*t)) {
+ badcanotime("Expected digit", p, t - p);
}
- badformat();
}
if ((lt = localtime(&tval)) == NULL)
- err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
+ err(EXIT_FAILURE, "%lld: localtime", (long long)tval);
lt->tm_isdst = -1; /* Divine correct DST */
if (dot != NULL) { /* .ss */
len = strlen(dot);
- if (len != 3)
- badformat();
+ if (len > 3) {
+ badcanotime("Unexpected digit after seconds field",
+ p, strlen(p) - 1);
+ } else if (len < 3) {
+ badcanotime("Expected digit in seconds field",
+ p, strlen(p));
+ }
++dot;
lt->tm_sec = ATOI2(dot);
if (lt->tm_sec > 61)
- badvalue("seconds");
+ badcanotime("Seconds out of range", p, strlen(p) - 1);
} else {
len = 0;
lt->tm_sec = 0;
}
+ op = p;
yearset = 0;
switch (strlen(p) - len) {
case 12: /* cc */
lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
if (lt->tm_year < 0)
- badtime();
+ badcanotime("Year before 1900", op, p - op + 1);
yearset = 1;
/* FALLTHROUGH */
case 10: /* yy */
@@ -244,7 +244,7 @@
case 8: /* mm */
lt->tm_mon = ATOI2(p);
if (lt->tm_mon > 12 || lt->tm_mon == 0)
- badvalue("month");
+ badcanotime("Month out of range", op, p - op - 1);
--lt->tm_mon; /* time struct is 0 - 11 */
/* FALLTHROUGH */
case 6: /* dd */
@@ -258,47 +258,70 @@
case 9:
case 11:
if (lt->tm_mday > 31 || lt->tm_mday == 0)
- badvalue("day of month");
+ badcanotime("Day out of range (max 31)",
+ op, p - op - 1);
break;
case 3:
case 5:
case 8:
case 10:
if (lt->tm_mday > 30 || lt->tm_mday == 0)
- badvalue("day of month");
+ badcanotime("Day out of range (max 30)",
+ op, p - op - 1);
break;
case 1:
- if (lt->tm_mday > 29 || lt->tm_mday == 0 ||
- (lt->tm_mday == 29 &&
- !isleap(lt->tm_year + TM_YEAR_BASE)))
- badvalue("day of month");
+ if (isleap(lt->tm_year + TM_YEAR_BASE)) {
+ if (lt->tm_mday > 29 || lt->tm_mday == 0) {
+ badcanotime("Day out of range "
+ "(max 29)",
+ op, p - op - 1);
+ }
+ } else {
+ if (lt->tm_mday > 28 || lt->tm_mday == 0) {
+ badcanotime("Day out of range "
+ "(max 28)",
+ op, p - op - 1);
+ }
+ }
break;
default:
- badvalue("month");
- break;
+ /*
+ * If the month was given, it's already been
+ * checked. If a bad value came back from
+ * localtime, something's badly broken.
+ * (make this an assertion?)
+ */
+ errx(EXIT_FAILURE, "localtime gave invalid month %d",
+ lt->tm_mon);
}
/* FALLTHROUGH */
case 4: /* hh */
lt->tm_hour = ATOI2(p);
if (lt->tm_hour > 23)
- badvalue("hour");
+ badcanotime("Hour out of range", op, p - op - 1);
/* FALLTHROUGH */
case 2: /* mm */
lt->tm_min = ATOI2(p);
if (lt->tm_min > 59)
- badvalue("minute");
+ badcanotime("Minute out of range", op, p - op - 1);
break;
case 0: /* was just .sss */
if (len != 0)
break;
/* FALLTHROUGH */
default:
- badformat();
+ if (strlen(p) - len > 12) {
+ badcanotime("Too many digits", p, 12);
+ } else {
+ badcanotime("Not enough digits", p, strlen(p) - len);
+ }
}
/* convert broken-down time to UTC clock time */
- if ((new_time = mktime(lt)) == -1)
- badtime();
+ if ((new_time = mktime(lt)) == -1) {
+ /* Can this actually happen? */
+ err(EXIT_FAILURE, "%s: mktime", op);
+ }
/* if jflag is set, don't actually change the time, just return */
if (jflag) {
Home |
Main Index |
Thread Index |
Old Index