On Mon, Apr 13, 2020 at 09:23:23PM -0600, Todd C. Miller wrote: > On Mon, 13 Apr 2020 20:27:30 -0600, Bob Beck wrote: > > > In my hearts desire I'd love for "R" to be chosen for each line once at > > start > > up. (so in > > the above example the things are randomly distributed). but not sure how > > har > > d that is.. > > > > If it saves code and effort I really think this is only useful for hours > > and > > minutes > > Here's a version that uses a suggestion from Theo to support ranges > like "0~30" to mean a random number between 0 and 30 and just a > bare "~" to mean a random value in the valid range for that field. > > The random values are chosen when the file is parsed which means > that on reload due to crontab edit they will change. I was trying > to avoid that initially but now I don't think it is a big deal.
Like this one plenty. I think it's ok the values change on reload. > > - todd > > Index: usr.sbin/cron/entry.c > =================================================================== > RCS file: /cvs/src/usr.sbin/cron/entry.c,v > retrieving revision 1.49 > diff -u -p -u -r1.49 entry.c > --- usr.sbin/cron/entry.c 13 Jun 2018 11:27:30 -0000 1.49 > +++ usr.sbin/cron/entry.c 14 Apr 2020 01:52:13 -0000 > @@ -450,13 +450,30 @@ static int > get_range(bitstr_t *bits, int low, int high, const char *names[], > int ch, FILE *file) > { > - /* range = number | number "-" number [ "/" number ] > + /* range = number | number* "~" number* | number "-" number ["/" number] > */ > > int i, num1, num2, num3; > > + /* XXX - parse ~, X~Y, X~ and ~Y */ > + > + if (ch == '~') { > + /* '~' means a random number [high, low] > + */ > + num1 = arc4random_uniform(high - low + 1) + low; > + ch = get_char(file); > + if (ch == EOF) > + return (EOF); > + > + if (EOF == set_element(bits, low, high, num1)) { > + unget_char(ch, file); > + return (EOF); > + } > + return (ch); > + } > + > if (ch == '*') { > - /* '*' means "first-last" but can still be modified by /step > + /* '*' means "high-low" but can still be modified by /step > */ > num1 = low; > num2 = high; > @@ -464,30 +481,45 @@ get_range(bitstr_t *bits, int low, int h > if (ch == EOF) > return (EOF); > } else { > - ch = get_number(&num1, low, names, ch, file, ",- \t\n"); > + ch = get_number(&num1, low, names, ch, file, ",-~ \t\n"); > if (ch == EOF) > return (EOF); > > - if (ch != '-') { > - /* not a range, it's a single number. > - */ > - if (EOF == set_element(bits, low, high, num1)) { > - unget_char(ch, file); > - return (EOF); > - } > - return (ch); > - } else { > - /* eat the dash > + switch (ch) { > + case '-': > + case '~': > + num3 = ch; > + > + /* eat the dash/tilde > */ > ch = get_char(file); > if (ch == EOF) > return (EOF); > > - /* get the number following the dash > + /* get the number following the dash/tilde > */ > ch = get_number(&num2, low, names, ch, file, "/, \t\n"); > if (ch == EOF || num1 > num2) > return (EOF); > + > + /* if it's a standard range, we're done here. > + */ > + if (num3 == '-') > + break; > + > + /* get a random number in the range [num1, num2] > + */ > + num3 = num1; > + num1 = arc4random_uniform(num2 - num3 + 1) + num3; > + /* FALLTHROUGH */ > + default: > + /* not a range, it's a single number. > + */ > + if (EOF == set_element(bits, low, high, num1)) { > + unget_char(ch, file); > + return (EOF); > + } > + return (ch); > } > } > >