random password generator

A

Army1987

Is there anything wrong with this program? It seems to behave
strangely if I give stdin EOF when asked for the character set...

/* BEGIN pwdgen.c */
#include <stdio.h>
#include "random.h"
#include <stdlib.h>
#include <string.h>

#define MAX_PWD_LEN 128
#define MAX_CHARSET 128

char *pwdgen(size_t length, const char *charset, char *dest);
char *ord(unsigned n);
long input(const char *prompt);

int main(void)
{
char charset[MAX_CHARSET] = "";
char password[MAX_PWD_LEN];
char *charset_end;
char prompt[56];
unsigned long pwd_len;
printf("Insert characters from which to make passwords "
"(at most %d characters):\n", MAX_CHARSET - 1);
fgets(charset, MAX_CHARSET, stdin);
charset_end = strchr(charset, '\n');
if (charset_end != NULL)
*charset_end = '\0';
else if (getchar() != '\n') {
fprintf(stderr, "Characters after the %d%s will be discarded\n",
MAX_CHARSET - 1, ord(MAX_CHARSET - 1));
scanf("%*[^\n]%*c");
}
sprintf(prompt, "Insert password length (at most %d): ",
MAX_PWD_LEN - 1);
pwd_len = (unsigned long)input(prompt);
if (pwd_len > MAX_PWD_LEN - 1) {
printf("Maximum password length is %d.\n", MAX_PWD_LEN - 1);
pwd_len = MAX_PWD_LEN - 1;
}
fputs("Please wait...", stdout);
fflush(stdout);
pwdgen(pwd_len, charset, password);
puts("\rGenerated password is:");
puts(password);
return 0;
}

char *pwdgen(size_t length, const char *charset, char *dest)
/* Fills dest with length random characters from charset */
{
if (dest == NULL && (dest = malloc(length+1)) == NULL) {
perror("Unable to allocate memory");
return(NULL);
}
if (charset == NULL || charset[0] == '\0') {
fputs("Empty or null charset\n", stderr);
*dest = '\0';
} else {
char *cur = dest;
size_t n_chars = strlen(charset);
while (length-- > 0)
*cur++ = charset[randlong(n_chars)];
*cur = '\0';
}
return dest;
}

long input(const char *prompt)
{
long result;
int flag;

fputs(prompt, stdout);
fflush(stdout);
do {
flag = scanf("%ld", &result);
switch (flag) {
case EOF:
fputs("EOF in stdin\n", stderr);
exit(EXIT_FAILURE);
case 0:
scanf("%*[^\n]%*c");
fputs("Please enter a numeric value: ", stdout);
fflush(stdout);
continue;
default:
break;
}
} while (flag < 1);
return result;
}

char *ord(unsigned n)
{
char *result;
if (n%100 - n%10 == 10) /* 10th, 11th, 12th ... */
result = "th";
else switch (n % 10) {
case 1: /* 1st, 21st, ... */
result = "st";
break;
case 2: /* 2nd, 22nd, ... */
result = "nd";
break;
case 3: /* 3rd, 23rd, ... */
result = "rd";
break;
default: /* all others */
result = "th";
break;
}
return result;
}
/* END pwdgen.c */

/* BEGIN random.h */
#ifndef RANDOM_H__
#define RANDOM_H__
unsigned long randlong(unsigned long max);
unsigned long randomize(unsigned long *max);
#endif
/* END random.h */

/* BEGIN random.c */
#include <stdio.h>
#include "random.h"

unsigned long randlong(unsigned long max)
/* Return a uniformly distributed random integer from 0 to max-1, or from 0
to
* ULONG_MAX if max is 0. Print an error message to stderr if the actual
range
* is smaller. */
{
static unsigned long randcurr = 0;
static unsigned long maxrcurr = 0;
unsigned long result;

if (max == 0) {
unsigned long max_;

result = randomize(&max_);
if (max_ < (unsigned long)(-1))
fprintf(stderr, "Not enough entropy. Effective maximum value is
"
" %lu.\n", max_);
return result;
}
while (maxrcurr - randcurr < (maxrcurr % max + 1) % max) { /* Unbias */
randcurr = randomize(&maxrcurr);
if (maxrcurr < max) {
fprintf(stderr, "Not enough entropy. Effective maximum value is
"
" %lu.\n", max);
break;
}
}
result = randcurr % max;
randcurr /= max;
maxrcurr /= max;
return result;
}
/* END random.c */

/* BEGIN randomize.c (Linux version -- YMMV) */
#include <stdio.h>
#include <stdlib.h>
unsigned long randomize(unsigned long *max)
/* Set *max to a large value, and return a uniformly distributed random
* integer from 0 to *max */
{
FILE *random = fopen("/dev/random", "rb");
unsigned long result;
unsigned long max_;

if (random != NULL && fread(&result, sizeof result, 1, random) == 1)
max_ = (unsigned long)(-1);
else {
result = rand();
max_ = RAND_MAX;
}
if (max != NULL)
*max = max_;
if (random != NULL)
fclose(random);
return result;
}
/* END randomize.c */
 
R

Richard Heathfield

Army1987 said:
Is there anything wrong with this program? It seems to behave
strangely if I give stdin EOF when asked for the character set...

Don't you think it would be a good idea to test for this condition and
take appropriate action if it is encountered?
printf("Insert characters from which to make passwords "
"(at most %d characters):\n", MAX_CHARSET - 1);
fgets(charset, MAX_CHARSET, stdin);

You need to check whether fgets succeeded, and take appropriate action
if it did not.
 
B

Barry Schwarz

Is there anything wrong with this program? It seems to behave
strangely if I give stdin EOF when asked for the character set...

Define strangely. How do you give stdin EOF? If you give stdin EOF,
will there ever be a '\n'?

snip
fgets(charset, MAX_CHARSET, stdin);
charset_end = strchr(charset, '\n');
if (charset_end != NULL)
*charset_end = '\0';
else if (getchar() != '\n') {
fprintf(stderr, "Characters after the %d%s will be discarded\n",
MAX_CHARSET - 1, ord(MAX_CHARSET - 1));
scanf("%*[^\n]%*c");

snip


Remove del for email
 
A

Army1987

Barry Schwarz said:
Define strangely. How do you give stdin EOF? If you give stdin EOF,
will there ever be a '\n'?

Yeah... It turns out that the way I used to end stdin <ot>(pressing ctrl-D,
in Linux)</ot> works only if it is the first thing input on a line...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top