On Tue, Apr 14, 2020 at 01:05:44PM -0600, Todd C. Miller wrote:
> On Mon, 13 Apr 2020 21:45:21 -0600, Bob Beck wrote:
> 
> > Like this one plenty.  I think it's ok the values change on reload. 
> 
> Here's a cleaned up version that includes the man page.  The random
> interval can now be one of "~", "low~high", "low~", or "~high" where
> if low and/or high are omitted, the appropriate value for the field
> is used.  Multiple random intervals can be used, separated by a
> comma.
> 
>  - todd
> 

hi. i think the doc parts read fine.

a couple of points:

- in STANDARDS, i guess stick to using Ql rather than Dq
- the system crontab and the example in acme-client.1 should probably be 
changed too

jmc

> Index: usr.sbin/cron/crontab.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/cron/crontab.5,v
> retrieving revision 1.37
> diff -u -p -u -r1.37 crontab.5
> --- usr.sbin/cron/crontab.5   6 Jan 2020 19:44:09 -0000       1.37
> +++ usr.sbin/cron/crontab.5   14 Apr 2020 19:01:33 -0000
> @@ -144,7 +144,18 @@ For example,
>  .Ar hour
>  entry specifies execution at hours 8, 9, 10 and 11.
>  .Pp
> -Step values can be used in conjunction with ranges.
> +A random value (within the legal range) may be obtained by using the
> +.Ql ~
> +character in a field.
> +The interval of the random value may be specified explicitly, for example
> +.Dq 0~30
> +will result in a random value between 0 and 30 inclusive.
> +If either (or both) of the numbers on either side of the
> +.Ql ~
> +are omitted, the appropriate limit (low or high) for the field will be used.
> +.Pp
> +Step values can be used in conjunction with ranges (but not random ranges
> +which represent a single number).
>  Following a range with
>  .No / Ns Ar number
>  specifies skips of
> @@ -318,6 +329,9 @@ MAILTO=paul
>  23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
>  
>  5 4 * * sun     echo "run at 5 after 4 every sunday"
> +
> +# run hourly at a random time within the first 30 minutes of the hour
> +0~30 * * * *   /usr/libexec/spamd-setup
>  .Ed
>  .Sh SEE ALSO
>  .Xr crontab 1 ,
> @@ -337,6 +351,10 @@ field may use 7 to represent Sunday.
>  .It
>  Ranges may include
>  .Dq steps .
> +.It
> +Random intervals are supported using the
> +.Dq ~
> +character.
>  .It
>  Months or days of the week can be specified by name.
>  .It
> 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 19:03:47 -0000
> @@ -450,33 +450,29 @@ 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;
>  
> +     num1 = low;
> +     num2 = high;
> +
>       if (ch == '*') {
> -             /* '*' means "first-last" but can still be modified by /step
> +             /* '*' means [low, high] but can still be modified by /step
>                */
> -             num1 = low;
> -             num2 = high;
>               ch = get_char(file);
>               if (ch == EOF)
>                       return (EOF);
>       } else {
> -             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);
> +             if (ch != '~') {
> +                     ch = get_number(&num1, low, names, ch, file, ",-~ 
> \t\n");
> +                     if (ch == EOF)
>                               return (EOF);
> -                     }
> -                     return (ch);
> -             } else {
> +             }
> +
> +             switch (ch) {
> +             case '-':
>                       /* eat the dash
>                        */
>                       ch = get_char(file);
> @@ -488,6 +484,37 @@ get_range(bitstr_t *bits, int low, int h
>                       ch = get_number(&num2, low, names, ch, file, "/, \t\n");
>                       if (ch == EOF || num1 > num2)
>                               return (EOF);
> +                     break;
> +             case '~':
> +                     /* eat the tilde
> +                      */
> +                     ch = get_char(file);
> +                     if (ch == EOF)
> +                             return (EOF);
> +
> +                     /* get the (optional) number following the tilde
> +                      */
> +                     ch = get_number(&num2, low, names, ch, file, ", \t\n");
> +                     if (ch == EOF)
> +                             ch = get_char(file);
> +                     if (ch == EOF || num1 > num2) {
> +                             unget_char(ch, file);
> +                             return (EOF);
> +                     }
> +
> +                     /* get a random number in the interval [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);
>               }
>       }
>  
> 

Reply via email to