RosettaCodeData/Task/Password-generator/Racket/password-generator.rkt

61 lines
2.5 KiB
Racket

#lang racket
(require racket/cmdline)
(define valid-uppercase '(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\J
#\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T
#\U #\V #\W #\X #\Y #\Z))
(define valid-lowercase '(#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j
#\k #\l #\m #\n #\o #\p #\q #\r #\s #\t
#\u #\v #\w #\x #\y #\z))
(define valid-numbers '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
(define valid-symbols '(#\! #\\ #\" #\# #\$ #\% #\& #\' #\( #\)
#\* #\+ #\, #\- #\. #\/ #\: #\; #\< #\=
#\> #\? #\@ #\[ #\] #\^ #\_ #\{ #\| #\}
#\~))
(define visual-invalid '(#\0 #\O #\1 #\I #\l #\| #\5 #\S #\2 #\Z))
(define (is-readable? c)
(empty? (filter (lambda (x) (eq? x c)) visual-invalid)))
(define (random-selection lst)
(list-ref lst (random (length lst))))
(define (generate len readable)
(let ([upper (if readable (filter is-readable? valid-uppercase) valid-uppercase)]
[lower (if readable (filter is-readable? valid-lowercase) valid-lowercase)]
[numbers (if readable (filter is-readable? valid-numbers) valid-numbers)]
[symbols (if readable (filter is-readable? valid-symbols) valid-symbols)])
(let loop ([lst (map random-selection (list upper lower numbers symbols))])
(cond
[(<= len (length lst)) (shuffle lst)]
[else (match (random 4)
[0 (loop (cons (random-selection upper) lst))]
[1 (loop (cons (random-selection lower) lst))]
[2 (loop (cons (random-selection numbers) lst))]
[3 (loop (cons (random-selection symbols) lst))])]))))
(define (run len cnt seed readable)
(random-seed seed)
(let loop ([x cnt])
(unless (zero? x)
(display (list->string (generate len readable)))
(newline)
(loop (- x 1)))))
(define len (make-parameter 10))
(define cnt (make-parameter 1))
(define seed (make-parameter (random 1 1000000)))
(define readable? (make-parameter #f))
(command-line #:program "passwdgen"
#:once-each
[("-l" "--length") integer "password length" (len (string->number integer))]
[("-c" "--count") integer "number of password" (cnt (string->number integer))]
[("-s" "--seed") integer "random generator seed" (seed (string->number integer))]
[("-r" "--readable") "safe characters" (readable? #t)])
(run (len) (cnt) (seed) (readable?))