#!/usr/bin/python3

"""Generate a random string to use as a key."""

# I believe in giving people bizarre random passwords, with the idea
# in mind that they're more likely to change it if they hate typing it.

import random
import time
import os
import sys

# note: sometimes seed() returns a string, sometimes it returns a number.  random.seed
# should be able to deal with either anyway.
# Another note: This should be less necessary in python 2.4, but it's probably still
# a good idea there.  In 2.4, random.seed uses OS entropy when it can


class NeverException(Exception):
    """An exception that is never raised - just to quiet down pyflakes."""

    pass


def seed():
    """
    Get a seed for the PRNG.

    First we try the OS-provided /dev/random or /dev/urandom.  If
    neither of them exist, then we try to contact prngd. Failing all
    three of these, we do things the old, nasty way: time + pid.
    This is not the most heavily tested function I've ever written.  :)
    """
    have_seed = 0
    try:
        file = open("/dev/random", "rb")
        seed = file.read(16)
        file.close()
        have_seed = 1
        sys.stderr.write("Good, using /dev/random for entropy\n")
    except NeverException:
        pass
    if not have_seed:
        try:
            file = open("/dev/urandom", "r")
            seed = file.read(16)
            file.close()
            have_seed = 1
            sys.stderr.write("Decent, using /dev/urandom for entropy\n")
        except NeverException:
            pass
    if not have_seed:
        import socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock_opened = 1
        try:
            sock.connect(('localhost', 708))
        except NeverException:
            sock_opened = 0
        if sock_opened:
            # 2 means read blocking, 5 means gimme 5 bytes
            sock.send('\002\020')
            seed = ''
            for chno in range(16):
                seed += sock.recv(1)
            sock.close()
            have_seed = 1
            sys.stderr.write("Not bad, using prngd for entropy\n")
    if not have_seed:
        num = int(time.time() + os.getpid())
        time.sleep(1)
        num += int(time.time())
        seed = num
        sys.stderr.write("Not good, had to use time and pid for entropy\n")
    return seed


def chfrom62(n):
    """Convert a small number to a character in base 62."""
    if n < 26:
        return chr(ord('a')+n)
    elif n < 26 + 26:
        n = n - 26
        return chr(ord('A')+n)
    else:
        n = n - 26 - 26
        return chr(ord('0')+n)


def chfrom16(n):
    """Convert a small number to a character in base 32."""
    # print n
    if n < 10:
        return chr(ord('0')+n)
    elif n < 16:
        n = n - 10
        return chr(ord('a')+n)
    else:
        sys.stderr.write('internal error\n')
        sys.exit(0)


s = seed()
# print 'seed is',s
random.seed(s)


for i in range(32):
    sys.stdout.write(chfrom16(int(random.random()*16)))
print()