File: rander.el

package info (click to toggle)
xemacs21-packages 2009.02.17.dfsg.1-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 116,928 kB
  • ctags: 88,975
  • sloc: lisp: 1,232,060; ansic: 16,570; java: 13,514; xml: 6,477; sh: 4,611; makefile: 4,036; asm: 3,007; perl: 839; cpp: 500; ruby: 257; csh: 96; haskell: 93; awk: 49; python: 47
file content (137 lines) | stat: -rw-r--r-- 4,564 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
;;;  rander.el -- possibly better random numbers, using rc16 as a RNG

;; Copyright (C) 1998 Ray Jones

;; Author: Ray Jones, rjones@pobox.com
;; Keywords: RNG, rc4, rc16, stream cipher
;; Created: 1998-04-14

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, you can either send email to this
;; program's maintainer or write to: The Free Software Foundation,
;; Inc.; 675 Massachusetts Avenue; Cambridge, MA 02139, USA.


(require 'cl)
(require 'rc16)

(defvar *rander-file* (expand-file-name "~/.emacs.rander"))
(defvar *rander-file-length* 512)

;;; Initialization of the random state

;; generate a string with random information in it
(defun rander-noise-string ()
  (concat
   ;; randomness from before
   (if (file-readable-p *rander-file*)
       (let ((buf nil))
	 (unwind-protect
	     (progn
	       (setq buf (generate-new-buffer "randerdata"))
	       (save-excursion
		 (set-buffer buf)
		 (insert-file-contents-literally *rander-file*)
		 (buffer-string)))
	   (if buf
	       (let ((kill-buffer-hook nil))
		 (kill-buffer buf))))))

   ;; allocation randomness
   (if (boundp 'cons-cells-consed)
       (apply 'concat 
              (mapcar 'int-to-string 
                      (list cons-cells-consed
                            floats-consed
                            intervals-consed
                            misc-objects-consed
                            string-chars-consed
                            symbols-consed
                            vector-cells-consed)))
       "")
   
   ;; time randomness
   (apply 'concat (mapcar 'int-to-string (current-time)))
   
   ;; process randomness
   (int-to-string (emacs-pid))))


;;; Mixin keypress randomness, on the fly

;; don't use this if your (current-time) is not fine grained in the
;; microseconds.  or if your computer is particularly slow, and the
;; pre-command-hook stuff slows it down (unlikely).
(defvar *rander-use-keypress* t)
;; this number shouldn't be too high, as a call to (rander16) will
;; have to mixin up to this many values before actually returning
(defvar *rander-keypress-count* 128)
(defvar *rander-keypress-timings* 
  (and *rander-use-keypress*
       (make-vector *rander-keypress-count* 0)))
(defvar *rander-keypress-have* 0)

(defun rander-store-key-time ()
  "store keypress timings until we have filled the keypress timings buffer"
  (when (< *rander-keypress-have* *rander-keypress-count*)
    (aset *rander-keypress-timings* 
          *rander-keypress-have* 
          (nth 2 (current-time)))
    (incf *rander-keypress-have*)))

(if *rander-use-keypress*
    (add-hook 'pre-command-hook 'rander-store-key-time))

;;; main source of randomness, the rc16 generator
(defvar *rander-initialized* nil)
(defvar *rander-rc16-context* nil)

(defun rander-init ()
  (setq *rander-rc16-context* (rc16-create-context))
  (rc16-set-key *rander-rc16-context* (rander-noise-string))
  (add-hook 'kill-emacs-hook 'rander-write-file)
  (setq *rander-initialized* t))

(defun rander16 ()
  (if (not *rander-initialized*)
      (rander-init))
  (when (and *rander-use-keypress*
             (not (zerop *rander-keypress-have*)))
    ;; mixin all the keypresses we have stored to this point
    (dotimes (idx *rander-keypress-have*)
      (rc16-mixin *rander-rc16-context*
                  (aref *rander-keypress-timings* idx)))
    ;; reset the buffer
    (setq *rander-keypress-have* 0))

  ;; return a random value
  (rc16-short *rander-rc16-context*))

(defun rander-write-file ()
  "write out a seed file for the next time rander is used.  called at
the exit of emacs."  
  (let ((buf nil))
    (unwind-protect
        (progn
          (setq buf (generate-new-buffer "randerdata"))
          (save-excursion
            (set-buffer buf)
            (dotimes (count *rander-file-length*)
              (insert (logand ?\xff (rander16))))
	    (let ((backup-inhibited t))
	      (write-file *rander-file*))))
      (if buf
          (let ((kill-buffer-hook nil))
            (kill-buffer buf))))))

(provide 'rander)