diff --git a/pw_phonemes.c b/pw_phonemes.c index 85a7fad..7a6e0ca 100644 --- a/pw_phonemes.c +++ b/pw_phonemes.c @@ -56,7 +56,7 @@ struct pw_element elements[] = { #define NUM_ELEMENTS (sizeof(elements) / sizeof (struct pw_element)) -void pw_phonemes(char *buf, int size, int pw_flags, char *remove) +void pw_phonemes(char *buf, int size, int pw_flags, char *add, char *remove, char *force) { int c, i, len, flags, feature_flags; int prev, should_be, first; diff --git a/pw_rand.c b/pw_rand.c index 3215196..a3a17ac 100644 --- a/pw_rand.c +++ b/pw_rand.c @@ -35,6 +35,24 @@ static void remove_chars(char *buf, const char *remove) } } +static void add_chars(char *buf, const char *add) +{ + const char *cp; + char *end; + + if (!add) + return; + end = buf + strlen(buf); + for (cp = add; *cp; cp++) { + char *r = strchr(buf, *cp); + + if (r != NULL) // skip if already there + continue; + *end++ = *cp; + *end = '\0'; + } +} + static int find_chars(char *buf, const char *set) { const char *cp; @@ -45,7 +63,17 @@ static int find_chars(char *buf, const char *set) return 0; } -void pw_rand(char *buf, int size, int pw_flags, char *remove) +static int find_all_chars(char *buf, const char *set) +{ + const char *cp; + + for (cp = set; *cp; cp++) + if (!strchr(buf, *cp)) + return 0; + return 1; +} + +void pw_rand(char *buf, int size, int pw_flags, char *add, char *remove, char *force) { char ch, *chars, *wchars; int i, len, feature_flags; @@ -61,6 +89,12 @@ void pw_rand(char *buf, int size, int pw_flags, char *remove) if (pw_flags & PW_SYMBOLS) { len += strlen(pw_symbols); } + if (add) { + len += strlen(add); + } + if (force) { + len += strlen(force); + } chars = malloc(len+1); if (!chars) { fprintf(stderr, "Couldn't malloc pw_rand buffer.\n"); @@ -80,12 +114,14 @@ void pw_rand(char *buf, int size, int pw_flags, char *remove) if (pw_flags & PW_SYMBOLS) { strcpy(wchars, pw_symbols); } - if (remove) { + if (add || remove || force) { if (pw_flags & PW_AMBIGUOUS) remove_chars(chars, pw_ambiguous); if (pw_flags & PW_NO_VOWELS) remove_chars(chars, pw_vowels); remove_chars(chars, remove); + add_chars(chars, add); // Override preceding removals + add_chars(chars, force); if ((pw_flags & PW_DIGITS) && !find_chars(chars, pw_digits)) { fprintf(stderr, @@ -135,6 +171,8 @@ void pw_rand(char *buf, int size, int pw_flags, char *remove) if (feature_flags & (PW_UPPERS | PW_DIGITS | PW_SYMBOLS)) goto try_again; buf[size] = 0; + if (force && !find_all_chars(buf, force)) + goto try_again; free(chars); return; } diff --git a/pwgen.c b/pwgen.c index c05b8de..e3a13e6 100644 --- a/pwgen.c +++ b/pwgen.c @@ -35,7 +35,9 @@ struct option pwgen_options[] = { { "numerals", no_argument, 0, 'n'}, { "symbols", no_argument, 0, 'y'}, { "num-passwords", required_argument, 0, 'N'}, + { "add-chars", required_argument, 0, 'j' }, { "remove-chars", required_argument, 0, 'r' }, + { "force-chars", required_argument, 0, 'f' }, { "secure", no_argument, 0, 's' }, { "help", no_argument, 0, 'h'}, { "no-numerals", no_argument, 0, '0' }, @@ -47,7 +49,7 @@ struct option pwgen_options[] = { }; #endif -const char *pw_options = "01AaBCcnN:sr:hH:vy"; +const char *pw_options = "01AaBCcnN:sj:r:f:hH:vy"; static void usage(void) { @@ -67,9 +69,15 @@ static void usage(void) fputs(" -y or --symbols\n", stderr); fputs("\tInclude at least one special symbol in the password\n", stderr); + fputs(" -j or --add-chars=\n", stderr); + fputs("\tAdds/joins characters to the set of characters to " + "generate passwords\n", stderr); fputs(" -r or --remove-chars=\n", stderr); fputs("\tRemove characters from the set of characters to " "generate passwords\n", stderr); + fputs(" -f or --force-chars=\n", stderr); + fputs("\tForce the usage of specified characters in generated passwords\n", + stderr); fputs(" -s or --secure\n", stderr); fputs("\tGenerate completely random passwords\n", stderr); fputs(" -B or --ambiguous\n", stderr); @@ -96,8 +104,10 @@ int main(int argc, char **argv) int c, i; int num_cols = -1; char *buf, *tmp; + char *add=NULL; char *remove=NULL; - void (*pwgen)(char *inbuf, int size, int pw_flags, char *remove); + char *force=NULL; + void (*pwgen)(char *inbuf, int size, int pw_flags, char *add, char *remove, char *force); pwgen = pw_phonemes; pw_number = pw_random_number; @@ -160,10 +170,18 @@ int main(int argc, char **argv) pwgen = pw_rand; pwgen_flags |= PW_NO_VOWELS; break; + case 'j': + add = strdup(optarg); + pwgen = pw_rand; + break; case 'r': remove = strdup(optarg); pwgen = pw_rand; break; + case 'f': + force = strdup(optarg); + pwgen = pw_rand; + break; case 'h': case '?': usage(); @@ -211,7 +229,7 @@ int main(int argc, char **argv) exit(1); } for (i=0; i < num_pw; i++) { - pwgen(buf, pw_length, pwgen_flags, remove); + pwgen(buf, pw_length, pwgen_flags, add, remove, force); if (!do_columns || ((i % num_cols) == (num_cols-1)) || (i == (num_pw - 1))) printf("%s\n", buf); @@ -219,5 +237,8 @@ int main(int argc, char **argv) printf("%s ", buf); } free(buf); + free(add); + free(remove); + free(force); return 0; } diff --git a/pwgen.h b/pwgen.h index f408fe3..9ccb735 100644 --- a/pwgen.h +++ b/pwgen.h @@ -38,10 +38,10 @@ extern const char *pw_ambiguous; /* Function prototypes */ /* pw_phonemes.c */ -extern void pw_phonemes(char *buf, int size, int pw_flags, char *remove); +extern void pw_phonemes(char *buf, int size, int pw_flags, char *add, char *remove, char *force); /* pw_rand.c */ -extern void pw_rand(char *buf, int size, int pw_flags, char *remove); +extern void pw_rand(char *buf, int size, int pw_flags, char *add, char *remove, char *force); /* randnum.c */ extern int pw_random_number(int max_num);