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);
>               }
>       }
>  
> 

Reply via email to