Re: [hackers] Penfing patches for sbase and ubase
"Roberto E. Vargas Caballero" wrote: > I know that there are some pending patches for sbase and ubase, > but I am a bit busy these days and I will not be able to look > a bit deeper on them until next week. Be patient until then :) > > Thank you Sure, no problem! I've sent most of the patches I've made anyway, except for smaller bugfixes. Take care
[hackers] [sbase][PATCH] cron: heavy refactor of parsefield() and matchentry()
This patch heavily simplifies the parsing logic of parsefield(), and makes the grammar more standards-compliant. Before, this cron implementation would only recognize repeats ("/n" at the end of a range, or of a wildcar) for wildcars, and list elements could only be numbers. Now, the basic type is a range, which also includes and simplifies numbers, wildcars and "repeats". A field is thus a list of this basic types. So now we can have things such as "*/3,14-18" as a field. Every range (except for numbers) allow the "/n" syntax. Also added: random fields, using ~. This is a non-standard addition, but which matches many cron implementations, like OpenBSD's for instance. Its usefulness is debatable. --- cron.1 | 8 ++ cron.c | 259 ++--- 2 files changed, 144 insertions(+), 123 deletions(-) diff --git a/cron.1 b/cron.1 index 4553b46..2f62fde 100644 --- a/cron.1 +++ b/cron.1 @@ -21,3 +21,11 @@ instead of the default .It Fl n Do not daemonize. .El +.Sh NOTES +This +.Nm +accepts normal, standard syntax. +It also includes the '~' syntax for random ranges, +which is non-standard. +.Sh SEE ALSO +.Xf crontab 5 diff --git a/cron.c b/cron.c index 77304cc..5d940cd 100644 --- a/cron.c +++ b/cron.c @@ -17,19 +17,13 @@ #include "queue.h" #include "util.h" -struct field { - enum { - ERROR, - WILDCARD, - NUMBER, - RANGE, - REPEAT, - LIST - } type; - long *val; - int len; +struct range { + long low, high, repeat, random; + TAILQ_ENTRY(range) entry; }; +TAILQ_HEAD(field, range); + struct ctabentry { struct field min; struct field hour; @@ -202,143 +196,159 @@ matchentry(struct ctabentry *cte, struct tm *tm) { .f = >wday, .tm = tm->tm_wday, .len = 7 }, }; size_t i; - int j; + int found, t; + long low; + struct range *r; for (i = 0; i < LEN(matchtbl); i++) { - switch (matchtbl[i].f->type) { - case WILDCARD: - continue; - case NUMBER: - if (matchtbl[i].f->val[0] == matchtbl[i].tm) - continue; - break; - case RANGE: - if (matchtbl[i].f->val[0] <= matchtbl[i].tm) - if (matchtbl[i].f->val[1] >= matchtbl[i].tm) - continue; - break; - case REPEAT: - if (matchtbl[i].tm > 0) { - if (matchtbl[i].tm % matchtbl[i].f->val[0] == 0) - continue; - } else { - if (matchtbl[i].len % matchtbl[i].f->val[0] == 0) - continue; + found = 0; + t = matchtbl[i].tm; + TAILQ_FOREACH(r, matchtbl[i].f, entry) { + if (r->random) + low = r->random; + else + low = r->low; + if (low <= t && r->high >= t && t % r->repeat == 0) { + found = 1; + break; } - break; - case LIST: - for (j = 0; j < matchtbl[i].f->len; j++) - if (matchtbl[i].f->val[j] == matchtbl[i].tm) - break; - if (j < matchtbl[i].f->len) - continue; - break; - default: - break; } - break; + if (!found) + break; } if (i != LEN(matchtbl)) return 0; + + for (i = 0; i < LEN(matchtbl); i++) { /* only if entry is matched */ + TAILQ_FOREACH(r, matchtbl[i].f, entry) { + if (r->random) + r->random = random_uniform(r->high - r->low) + r->low; + } + } + return 1; } + static int -parsefield(const char *field, long low, long high, struct field *f) +parserange(char *str, long low, long high, struct range *r) { - int i; - char *e1, *e2; - const char *p; - - p = field; - while (isdigit(*p)) - p++; - - f->type = ERROR; - - switch (*p) { - case '*': - if (strcmp(field, "*") == 0) { - f->val = NULL; - f->len = 0; - f->type = WILDCARD; - } else if (strncmp(field, "*/", 2) == 0) { - f->val = emalloc(sizeof(*f->val)); -
[hackers] [sbase][PATCH] shuf: use libutil/random functions instead of custom ones
--- shuf.c | 37 + 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/shuf.c b/shuf.c index 2655d08..3d8ec51 100644 --- a/shuf.c +++ b/shuf.c @@ -7,41 +7,6 @@ #include "text.h" #include "util.h" -/* - * Uniformity is achieved by generating new random numbers until the one - * returned is outside the range [0, 2**32 % upper_bound). This - * guarantees the selected random number will be inside - * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) - * after reduction modulo upper_bound. - * - * Copied off OpenBSD (original is arc4random_uniform) - */ -uint32_t -random_uniform(uint32_t upper_bound) -{ - uint32_t r, min; - - if (upper_bound < 2) - return 0; - - /* 2**32 % x == (2**32 - x) % x */ - min = -upper_bound % upper_bound; - - /* -* This could theoretically loop forever but each retry has -* p > 0.5 (worst case, usually far better) of selecting a -* number inside the range we need, so it should rarely need -* to re-roll. -*/ - for (;;) { - r = random(); /* arc4random() is better, but we don't always have it */ - if (r >= min) - break; - } - - return r % upper_bound; -} - static void usage(void) { @@ -82,7 +47,7 @@ main(int argc, char *argv[]) } } - srandom((intptr_t)buf.nlines | time(NULL)); + random_seed(); if (!rflag) { for (i = buf.nlines - 1; i > 0; i--) { -- 2.44.0
[hackers] [sbase][PATCH] libutil: add random.c
Some programs need a good PRNG, such as shuf(1), or cron(1). This adds to libutil a random_uniform function which simply solves the problem of creating integers uniformly in a range. random_seed seeds the generator. arc4random would probably be a better PRNG than random, but it is less portable unfortunately. --- Makefile | 1 + libutil/random.c | 46 ++ 2 files changed, 47 insertions(+) create mode 100644 libutil/random.c diff --git a/Makefile b/Makefile index 7bd9626..50b84a1 100644 --- a/Makefile +++ b/Makefile @@ -86,6 +86,7 @@ LIBUTILOBJ =\ libutil/strsep.o\ libutil/strnsubst.o\ libutil/strtonum.o\ + libutil/random.o\ libutil/unescape.o\ libutil/writeall.o diff --git a/libutil/random.c b/libutil/random.c new file mode 100644 index 000..48eeb79 --- /dev/null +++ b/libutil/random.c @@ -0,0 +1,46 @@ +#include +#include +#include + +/* + * Uniformity is achieved by generating new random numbers until the one + * returned is outside the range [0, 2**32 % upper_bound). This + * guarantees the selected random number will be inside + * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) + * after reduction modulo upper_bound. + * + * Copied off OpenBSD (original is arc4random_uniform) + */ +uint32_t +random_uniform(uint32_t upper_bound) +{ + uint32_t r, min; + + if (upper_bound < 2) + return 0; + + /* 2**32 % x == (2**32 - x) % x */ + min = -upper_bound % upper_bound; + + /* +* This could theoretically loop forever but each retry has +* p > 0.5 (worst case, usually far better) of selecting a +* number inside the range we need, so it should rarely need +* to re-roll. +*/ + for (;;) { + r = random(); /* arc4random() is better, but we don't always have it */ + if (r >= min) + break; + } + + return r % upper_bound; +} + +void +random_seed(void) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, ); + srandom(ts.tv_nsec); /* not a good source of randomness, but eh */ +} -- 2.44.0