webmcp
view libraries/multirand/multirand.c @ 491:7a7770297ae8
Fixed error in error handling when catching illegal static path
| author | jbe | 
|---|---|
| date | Tue Jun 27 15:38:24 2017 +0200 (2017-06-27) | 
| parents | 9d15451c340a | 
| children | 
 line source
     1 #include <lua.h>
     2 #include <lauxlib.h>
     4 static FILE *multirand_dev;
     6 static lua_Integer multirand_range(
     7   lua_State *L, lua_Integer from, lua_Integer to
     8 ) {
     9   lua_Integer range;
    10   int bits = 0;
    11   lua_Integer bit_mask = 0;
    12   if (to < from) return luaL_error(L, "Assertion failed in C.");
    13   range = to - from;
    14   {
    15     lua_Integer tmp;
    16     tmp = range;
    17     while (tmp) {
    18       bits++;
    19       bit_mask <<= 1;
    20       bit_mask |= 1;
    21       tmp >>= 1;
    22     }
    23   }
    24   while (1) {
    25     int i;
    26     lua_Integer rnd = 0;
    27     for (i = 0; i < (bits + 7) / 8; i++) {
    28       int b;
    29       b = getc(multirand_dev);
    30       if (b == EOF) {
    31         return luaL_error(L, "I/O error while reading random.");
    32       }
    33       rnd = (rnd << 8) | (unsigned char)b;
    34     }
    35     rnd &= bit_mask;
    36     if (rnd <= range) return from + rnd;
    37   }
    38 }
    40 static int multirand_integer(lua_State *L) {
    41   lua_Integer arg1, arg2;
    42   lua_settop(L, 2);
    43   arg1 = luaL_checkinteger(L, 1);
    44   if (lua_toboolean(L, 2)) {
    45     arg2 = luaL_checkinteger(L, 2);
    46     if (arg1 > arg2) {
    47       return luaL_error(L,
    48         "Upper boundary is smaller than lower boundary."
    49       );
    50     } else if (arg1 == arg2) {
    51       lua_pushinteger(L, arg1);
    52     } else {
    53       lua_pushinteger(L, multirand_range(L, arg1, arg2));
    54     }
    55   } else {
    56     luaL_argcheck(L, arg1 >= 1, 1, "smaller than 1");
    57     lua_pushinteger(L, multirand_range(L, 1, arg1));
    58   }
    59   return 1;
    60 }
    62 static int multirand_fraction(lua_State *L) {
    63   int i, j;
    64   lua_settop(L, 0);
    65   lua_Number rnd = 0.0;
    66   for (i = 0; i < 8; i++) {
    67     int b;
    68     unsigned char c;
    69     b = getc(multirand_dev);
    70     if (b == EOF) return luaL_error(L, "I/O error while reading random.");
    71     c = (unsigned char) b;
    72     for (j = 0; j < 8; j++) {
    73       rnd /= 2.0;
    74       if (c & 1) rnd += 0.5;
    75       c >>= 1;
    76     }
    77   }
    78   lua_pushnumber(L, rnd);
    79   return 1;
    80 }
    82 static int multirand_string(lua_State *L) {
    83   lua_Integer length;
    84   const char *charset;
    85   size_t charset_size;
    86   luaL_Buffer buf;
    87   lua_settop(L, 2);
    88   length = luaL_checkinteger(L, 1);
    89   charset = luaL_optlstring(L, 2, "abcdefghijklmnopqrstuvwxyz", &charset_size);
    90   if (charset_size > 32767) {
    91     return luaL_error(L, "Set of chars is too big.");
    92   }
    93   luaL_buffinit(L, &buf);
    94   for (; length > 0; length--) {
    95     luaL_addchar(&buf,
    96       charset[multirand_range(L, 0, (lua_Integer)charset_size - 1)]
    97     );
    98   }
    99   luaL_pushresult(&buf);
   100   return 1;
   101 }
   103 static const struct luaL_Reg multirand_module_functions[] = {
   104   {"integer",  multirand_integer},
   105   {"fraction", multirand_fraction},
   106   {"string",   multirand_string},
   107   {NULL, NULL}
   108 };
   110 int luaopen_multirand(lua_State *L) {
   111   multirand_dev = fopen("/dev/urandom", "r");
   112   if (!multirand_dev) return luaL_error(L, "Could not open /dev/urandom.");
   113 #if LUA_VERSION_NUM >= 502
   114   lua_newtable(L);
   115   luaL_setfuncs(L, multirand_module_functions, 0);
   116 #else
   117   luaL_register(L, lua_tostring(L, 1), multirand_module_functions);
   118 #endif
   119   return 1;
   120 }
