diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval/funcs.c | 32 | ||||
-rw-r--r-- | src/nvim/testdir/test_random.vim | 16 |
2 files changed, 42 insertions, 6 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 96d8c93db3..6a0803704d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -10528,16 +10528,44 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "srand()" function static void f_srand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + static int dev_urandom_state = -1; // FAIL or OK once tried + tv_list_alloc_ret(rettv, 4); if (argvars[0].v_type == VAR_UNKNOWN) { - tv_list_append_number(rettv->vval.v_list, (varnumber_T)time(NULL)); + if (dev_urandom_state != FAIL) { + const int fd = os_open("/dev/urandom", O_RDONLY, 0); + struct { + union { + uint32_t number; + char bytes[sizeof(uint32_t)]; + } cont; + } buf; + + // Attempt reading /dev/urandom. + if (fd == -1) { + dev_urandom_state = FAIL; + } else { + buf.cont.number = 0; + if (read(fd, buf.cont.bytes, sizeof(uint32_t)) != sizeof(uint32_t)) { + dev_urandom_state = FAIL; + } else { + dev_urandom_state = OK; + tv_list_append_number(rettv->vval.v_list, (varnumber_T)buf.cont.number); + } + os_close(fd); + } + } + if (dev_urandom_state != OK) { + // Reading /dev/urandom doesn't work, fall back to time(). + tv_list_append_number(rettv->vval.v_list, (varnumber_T)time(NULL)); + } } else { bool error = false; const uint32_t x = tv_get_number_chk(&argvars[0], &error); if (error) { return; } - tv_list_append_number(rettv->vval.v_list, x); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)x); } tv_list_append_number(rettv->vval.v_list, 362436069); tv_list_append_number(rettv->vval.v_list, 521288629); diff --git a/src/nvim/testdir/test_random.vim b/src/nvim/testdir/test_random.vim index bde034a96c..46091836d4 100644 --- a/src/nvim/testdir/test_random.vim +++ b/src/nvim/testdir/test_random.vim @@ -11,10 +11,16 @@ func Test_Rand() " Nvim does not support test_settime " call test_settime(12341234) - " let s = srand() - " call assert_equal(s, srand()) - " call test_settime(12341235) - " call assert_notequal(s, srand()) + let s = srand() + if filereadable('/dev/urandom') + " using /dev/urandom + call assert_notequal(s, srand()) + " else + " " using time() + " call assert_equal(s, srand()) + " call test_settime(12341235) + " call assert_notequal(s, srand()) + endif call srand() let v = rand() @@ -26,6 +32,8 @@ func Test_Rand() call assert_fails('echo rand([1, [2], 3, 4])', 'E475:') call assert_fails('echo rand([1, 2, [3], 4])', 'E475:') call assert_fails('echo rand([1, 2, 3, [4]])', 'E475:') + + " call test_settime(0) endfunc " vim: shiftwidth=2 sts=2 expandtab |