aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2018-10-21 21:36:51 -0500
committerRob Landley <rob@landley.net>2018-10-21 21:36:51 -0500
commit07a3b9192001369c7bf74cd4f096dc49703b24e9 (patch)
treecfb6f13f8a275f0ae21d6b577baa69d8a05f9ce7
parent3e0b077ec236aa26bfeb290f3cd7973ec3fbcb7d (diff)
downloadtoybox-07a3b9192001369c7bf74cd4f096dc49703b24e9.tar.gz
Add % to lib/args.c (long time in milliseconds), add xmillitime(), redo
xparsetime() not to need floating point, adjust callers.
-rw-r--r--lib/args.c21
-rw-r--r--lib/lib.h1
-rw-r--r--lib/xwrap.c47
-rw-r--r--scripts/mkflags.c22
-rw-r--r--toys/net/ping.c23
-rw-r--r--toys/other/timeout.c2
-rw-r--r--toys/posix/ps.c21
-rw-r--r--toys/posix/sleep.c2
8 files changed, 66 insertions, 73 deletions
diff --git a/lib/args.c b/lib/args.c
index 5267ebe2..1927a930 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -53,17 +53,18 @@
//
// Suffixes specify that this option takes an argument (stored in GLOBALS):
// Note that pointer and long are always the same size, even on 64 bit.
-// : plus a string argument, keep most recent if more than one
-// * plus a string argument, appended to a list
-// # plus a signed long argument
+// : string argument, keep most recent if more than one
+// * string argument, appended to a struct arg_list linked list.
+// # signed long argument
// <LOW - die if less than LOW
// >HIGH - die if greater than HIGH
// =DEFAULT - value if not specified
-// - plus a signed long argument defaulting to negative (say + for positive)
-// . plus a double precision floating point argument (with CFG_TOYBOX_FLOAT)
+// - signed long argument defaulting to negative (say + for positive)
+// . double precision floating point argument (with CFG_TOYBOX_FLOAT)
// Chop this option out with USE_TOYBOX_FLOAT() in option string
// Same <LOW>HIGH=DEFAULT as #
-// @ plus an occurrence counter (which is a long)
+// @ occurrence counter (which is a long)
+// % time offset in milliseconds with optional s/m/h/d suffix
// (longopt)
// | this is required. If more than one marked, only one required.
// ; long option's argument is optional (can only be supplied with --opt=)
@@ -215,7 +216,7 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt)
help_exit("-%c < %lf", opt->c, (double)opt->val[0].f);
if (opt->val[1].l != LONG_MAX && *f > opt->val[1].f)
help_exit("-%c > %lf", opt->c, (double)opt->val[1].f);
- }
+ } else if (type=='%') *(opt->arg) = xparsemillitime(arg);
if (!gof->nodash_now) gof->arg = "";
}
@@ -291,20 +292,20 @@ void parse_optflaglist(struct getoptflagstate *gof)
// If this is the start of a new option that wasn't a longopt,
- } else if (strchr(":*#@.-", *options)) {
+ } else if (strchr(":*#@.-%", *options)) {
if (CFG_TOYBOX_DEBUG && new->type)
error_exit("multiple types %c:%c%c", new->c, new->type, *options);
new->type = *options;
} else if (-1 != (idx = stridx("|^ ;", *options))) new->flags |= 1<<idx;
// bounds checking
else if (-1 != (idx = stridx("<>=", *options))) {
- if (new->type == '#') {
+ if (new->type == '#' || new->type == '%') {
long l = strtol(++options, &temp, 10);
if (temp != options) new->val[idx].l = l;
} else if (CFG_TOYBOX_FLOAT && new->type == '.') {
FLOAT f = strtod(++options, &temp);
if (temp != options) new->val[idx].f = f;
- } else error_exit("<>= only after .#");
+ } else error_exit("<>= only after .#%%");
options = --temp;
// At this point, we've hit the end of the previous option. The
diff --git a/lib/lib.h b/lib/lib.h
index 98c042c7..e630bbc9 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -172,6 +172,7 @@ void xsetuser(struct passwd *pwd);
char *xreadlink(char *name);
double xstrtod(char *s);
long xparsetime(char *arg, long units, long *fraction);
+long long xparsemillitime(char *arg);
void xpidfile(char *name);
void xregcomp(regex_t *preg, char *rexec, int cflags);
char *xtzset(char *new);
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 2c3b6041..fba262b9 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -789,36 +789,45 @@ double xstrtod(char *s)
}
// parse fractional seconds with optional s/m/h/d suffix
-long xparsetime(char *arg, long units, long *fraction)
+long xparsetime(char *arg, long zeroes, long *fraction)
{
- double d;
- long l;
+ long l, fr;
char *end;
- if (*arg != '.' && !isdigit(*arg)) error_exit("bad %s", arg);
- if (CFG_TOYBOX_FLOAT) d = strtod(arg, &end);
- else l = strtoul(arg, &end, 10);
-
- if (end == arg) error_exit("Not a number '%s'", arg);
- arg = end;
+ if (*arg != '.' && !isdigit(*arg)) error_exit("Not a number '%s'", arg);
+ l = strtoul(arg, &end, 10);
+ fr = 0;
+ if (*end == '.') {
+ end++;
+ while (zeroes--) {
+ fr *= 10;
+ if (isdigit(*end)) fr += *end++-'0';
+ }
+ }
+ if (fraction) *fraction = fr;
// Parse suffix
- if (*arg) {
- int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *arg);
+ if (*end) {
+ int ismhd[]={1,60,3600,86400}, i = stridx("smhd", *end);
- if (i == -1 || *(arg+1)) error_exit("Unknown suffix '%s'", arg);
- if (CFG_TOYBOX_FLOAT) d *= ismhd[i];
- else l *= ismhd[i];
+ if (i == -1 || *(end+1)) error_exit("Unknown suffix '%s'", end);
+ l *= ismhd[i];
}
- if (CFG_TOYBOX_FLOAT) {
- l = (long)d;
- if (fraction) *fraction = units*(d-l);
- } else if (fraction) *fraction = 0;
-
return l;
}
+long long xparsemillitime(char *arg)
+{
+ long l, ll;
+
+ l = xparsetime(arg, 3, &ll);
+
+ return (l*1000LL)+ll;
+}
+
+
+
// Compile a regular expression into a regex_t
void xregcomp(regex_t *preg, char *regex, int cflags)
{
diff --git a/scripts/mkflags.c b/scripts/mkflags.c
index c96f7f55..6b4a527e 100644
--- a/scripts/mkflags.c
+++ b/scripts/mkflags.c
@@ -1,7 +1,7 @@
-// Take three word input lines on stdin (the three space separated words are
-// command name, option string with current config, option string from
-// allyesconfig; space separated, the last two are and double quotes)
-// and produce flag #defines to stdout.
+// Take three word input lines on stdin and produce flag #defines to stdout.
+// The three words on each input lnie are command name, option string with
+// current config, option string from allyesconfig. The three are space
+// separated and the last two are in double quotes.
// This is intentionally crappy code because we control the inputs. It leaks
// memory like a sieve and segfaults if malloc returns null, but does the job.
@@ -21,7 +21,10 @@ struct flag {
int chrtype(char c)
{
- if (strchr("?&^-:#|@*; ", c)) return 1;
+ // Does this populate a GLOBALS() variable?
+ if (strchr("?&^-:#|@*; %", c)) return 1;
+
+ // Is this followed by a numeric argument in optstr?
if (strchr("=<>", c)) return 2;
return 0;
@@ -74,12 +77,12 @@ char *mark_gaps(char *flags, char *all)
return n;
}
-// Break down a command string into struct flag list.
+// Break down a command string into linked list of "struct flag".
struct flag *digest(char *string)
{
struct flag *list = NULL;
- char *err = string;
+ char *err = string, c;
while (*string) {
// Groups must be at end.
@@ -108,8 +111,9 @@ struct flag *digest(char *string)
continue;
}
- if (strchr("?&^-:#|@*; ", *string)) string++;
- else if (strchr("=<>", *string)) {
+ c = chrtype(*string);
+ if (c == 1) string++;
+ else if (c == 2) {
if (string[1]=='-') string++;
if (!isdigit(string[1])) {
fprintf(stderr, "%c without number in '%s'", *string, err);
diff --git a/toys/net/ping.c b/toys/net/ping.c
index 752879a2..ad7679fd 100644
--- a/toys/net/ping.c
+++ b/toys/net/ping.c
@@ -11,7 +11,7 @@
* Yes, I wimped out and capped -s at sizeof(toybuf), waiting for a complaint...
// -s > 4088 = sizeof(toybuf)-sizeof(struct icmphdr), then kernel adds 20 bytes
-USE_PING(NEWTOY(ping, "<1>1m#t#<0>255=64c#<0=3s#<0>4088=56I:i:W#<0=3w#<0qf46[-46]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PING(NEWTOY(ping, "<1>1m#t#<0>255=64c#<0=3s#<0>4088=56I:i%W#<0=3w#<0qf46[-46]", TOYFLAG_USR|TOYFLAG_BIN))
USE_PING(OLDTOY(ping6, ping, TOYFLAG_USR|TOYFLAG_BIN))
config PING
@@ -47,18 +47,12 @@ config PING
#include <netinet/ip_icmp.h>
GLOBALS(
- long w;
- long W;
- char *i;
+ long w, W, i;
char *I;
- long s;
- long c;
- long t;
- long m;
+ long s, c, t, m;
struct sockaddr *sa;
int sock;
- long i_ms;
unsigned long sent, recv, fugit, min, max;
)
@@ -115,13 +109,8 @@ void ping_main(void)
struct icmphdr *ih = (void *)toybuf;
// Interval
- if (TT.i) {
- long frac;
-
- TT.i_ms = xparsetime(TT.i, 1000, &frac) * 1000;
- TT.i_ms += frac;
- if (TT.i_ms<200 && getuid()) error_exit("need root for -i <200");
- } else TT.i_ms = (toys.optflags&FLAG_f) ? 200 : 1000;
+ if (!(toys.optflags&FLAG_i)) TT.i = (toys.optflags&FLAG_f) ? 200 : 1000;
+ else if (TT.i<200 && getuid()) error_exit("need root for -i <200");
if (!(toys.optflags&FLAG_s)) TT.s = 56; // 64-PHDR_LEN
if ((toys.optflags&(FLAG_f|FLAG_c)) == FLAG_f) TT.c = 15;
@@ -230,7 +219,7 @@ void ping_main(void)
// Time to send the next packet?
if (!tW && tnext-tnow <= 0) {
- tnext += TT.i_ms;
+ tnext += TT.i;
memset(ih, 0, sizeof(*ih));
ih->type = (ai->ai_family == AF_INET) ? 8 : 128;
diff --git a/toys/other/timeout.c b/toys/other/timeout.c
index b62d696e..b903c3ec 100644
--- a/toys/other/timeout.c
+++ b/toys/other/timeout.c
@@ -58,7 +58,7 @@ void xparsetimeval(char *s, struct timeval *tv)
{
long ll;
- tv->tv_sec = xparsetime(s, 1000000, &ll);
+ tv->tv_sec = xparsetime(s, 6, &ll);
tv->tv_usec = ll;
}
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index d8f54862..833ecabe 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -48,8 +48,8 @@ USE_PS(NEWTOY(ps, "k(sort)*P(ppid)*aAdeflMno*O*p(pid)*s*t*Tu*U*g*G*wZ[!ol][+Ae][
// stayroot because iotop needs root to read other process' proc/$$/io
// TOP and IOTOP have a large common option block used for common processing,
// the default values are different but the flags are in the same order.
-USE_TOP(NEWTOY(top, ">0O*" "Hk*o*p*u*s#<1d:m#n#<1bq[!oO]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
-USE_IOTOP(NEWTOY(iotop, ">0AaKO" "Hk*o*p*u*s#<1=7d:m#n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE))
+USE_TOP(NEWTOY(top, ">0O*" "Hk*o*p*u*s#<1d%<100=3000m#n#<1bq[!oO]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
+USE_IOTOP(NEWTOY(iotop, ">0AaKO" "Hk*o*p*u*s#<1=7d%<100=3000m#n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE))
USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
USE_PKILL(NEWTOY(pkill, "?Vu*U*t*s*P*g*G*fnovxl:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
@@ -193,12 +193,8 @@ GLOBALS(
struct arg_list *G, *g, *U, *u, *t, *s, *p, *O, *o, *P, *k;
} ps;
struct {
- long n, m;
- char *d;
- long s;
+ long n, m, d, s;
struct arg_list *u, *p, *o, *k, *O;
-
- long d_ms;
} top;
struct {
char *L;
@@ -1638,8 +1634,8 @@ static void top_common(
}
now = millitime();
- if (timeout<=now) timeout = new.whence+TT.top.d_ms;
- if (timeout<=now || timeout>now+TT.top.d_ms) timeout = now+TT.top.d_ms;
+ if (timeout<=now) timeout = new.whence+TT.top.d;
+ if (timeout<=now || timeout>now+TT.top.d) timeout = now+TT.top.d;
// In batch mode, we ignore the keyboard.
if (toys.optflags&FLAG_b) {
@@ -1693,13 +1689,6 @@ static void top_common(
static void top_setup(char *defo, char *defk)
{
- if (TT.top.d) {
- long frac;
-
- TT.top.d_ms = xparsetime(TT.top.d, 1000, &frac) * 1000;
- TT.top.d_ms += frac;
- } else TT.top.d_ms = 3000;
-
TT.ticks = sysconf(_SC_CLK_TCK); // units for starttime/uptime
TT.tty = tty_fd() != -1;
diff --git a/toys/posix/sleep.c b/toys/posix/sleep.c
index c7b8bbf1..0381c107 100644
--- a/toys/posix/sleep.c
+++ b/toys/posix/sleep.c
@@ -31,6 +31,6 @@ void sleep_main(void)
{
struct timespec tv;
- tv.tv_sec = xparsetime(*toys.optargs, 1000000000, &tv.tv_nsec);
+ tv.tv_sec = xparsetime(*toys.optargs, 9, &tv.tv_nsec);
toys.exitval = !!nanosleep(&tv, NULL);
}