diff options
author | Aaron Ball <nullspoon@oper.io> | 2019-08-25 23:01:53 -0600 |
---|---|---|
committer | Aaron Ball <nullspoon@oper.io> | 2019-08-25 23:01:53 -0600 |
commit | 230c9f2ee14f3ce89ecaefc6d2dc7f4a18b0d5dc (patch) | |
tree | a1f2b0a5581b2e59d978754c2bde4b2c781efaca | |
parent | 4fc4a8a49eaecd5ac5d527a08438106c060dbfdd (diff) | |
download | upwgen-230c9f2ee14f3ce89ecaefc6d2dc7f4a18b0d5dc.tar.gz upwgen-230c9f2ee14f3ce89ecaefc6d2dc7f4a18b0d5dc.tar.xz |
Refactor of character set selection process
Previously, selected character sets were appended to a large array. This
made the program unable to easily mirror functionality of the
inspiration program pwgen in that removal of default character sets was
not very feasible.
This adds each character set into its own struct, which is a linked list
item, enabling easy addition to or removal from the character set list.
Further, character selection is now different as well. Since previously
the character pool was stored as one big array and now it is a linked
list of structs, a random character set type must be selected before
the character within that set is subsequently selected. This requires
two calls to rand now rather than only one.
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | src/i18n_set.c | 94 | ||||
-rw-r--r-- | src/i18n_set.h | 25 | ||||
-rw-r--r-- | src/main.c | 66 |
4 files changed, 165 insertions, 26 deletions
@@ -1,5 +1,5 @@ CC = cc -CCOPTS = -Wall -std=gnu99 +CCOPTS = -Wall -std=gnu99 $(DBG) PREFIX = /usr/bin MANPREFIX = /usr/share/man @@ -13,6 +13,7 @@ VERSTR = "$(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL))$(EXTRAVERSION)" all: @if [ ! -d obj ]; then mkdir obj; fi $(CC) $(CCOPTS) -c src/i18n_cat.c -o obj/i18n_cat.o + $(CC) $(CCOPTS) -c src/i18n_set.c -o obj/i18n_set.o $(CC) $(CCOPTS) -DVERSTR=$(VERSTR) src/main.c obj/*.o -o upwgen # Interpolate the man page and compress sed \ @@ -20,6 +21,9 @@ all: -e "s/{{ RELDATE }}/$(RELDATE)/" \ doc/upwgen.1 | gzip -c > upwgen.1.gz +debug: + make DBG=-g + install: # Install the binary install -D -m 755 upwgen "$(DESTDIR)/$(PREFIX)/upwgen" diff --git a/src/i18n_set.c b/src/i18n_set.c new file mode 100644 index 0000000..b864658 --- /dev/null +++ b/src/i18n_set.c @@ -0,0 +1,94 @@ +#include "i18n_set.h" + +struct i18n_set* i18n_set_new(int type) { + struct i18n_set* out = malloc(sizeof(struct i18n_set)); + + out->count = 0; + out->type = type; + out->next = NULL; + out->chars[0] = '\0'; + + switch(type) { + case I18N_TYPE_ASCII_LOWER: + out->count = i18n_cat_ascii_lower(out->chars); + break; + case I18N_TYPE_ASCII_UPPER: + out->count = i18n_cat_ascii_upper(out->chars); + break; + case I18N_TYPE_ASCII_NUMERALS: + out->count = i18n_cat_ascii_numerals(out->chars); + break; + case I18N_TYPE_ASCII_SYMBOLS: + out->count = i18n_cat_ascii_symbols(out->chars); + break; + case I18N_TYPE_ONE: + out->count = i18n_cat_one(out->chars); + break; + case I18N_TYPE_TWO: + out->count = i18n_cat_two(out->chars); + break; + case I18N_TYPE_THREE: + out->count = i18n_cat_three(out->chars); + break; + case I18N_TYPE_FOUR: + out->count = i18n_cat_four(out->chars); + break; + } + + return out; +} + + +struct i18n_set* i18n_set_add(struct i18n_set* set, int type) { + struct i18n_set* cursor = set; + if(!set) + return i18n_set_new(type); + + while(cursor->next) + cursor = cursor->next; + + cursor->next = i18n_set_new(type); + return cursor->next; +} + + +struct i18n_set* i18n_set_rm_type(struct i18n_set* set, int type) { + struct i18n_set* cursor = set; + struct i18n_set* prev = NULL; + + while(cursor) { + if(cursor->type == type) { + if(cursor == set) + set = set->next; + else if(!cursor->next) + prev->next = NULL; + else + prev->next = cursor->next; + + free(cursor); + } + prev = cursor; + cursor = cursor->next; + } + return set; +} + + +void i18n_set_dump(struct i18n_set* set) { + struct i18n_set* cursor = set; + while(cursor) { + i18n_dump_arr(cursor->chars); + cursor = cursor->next; + } +} + + +void i18n_set_free(struct i18n_set* set) { + struct i18n_set* next = NULL; + + while(set) { + next = set->next; + free(set); + set = next; + } +} diff --git a/src/i18n_set.h b/src/i18n_set.h new file mode 100644 index 0000000..9a79e83 --- /dev/null +++ b/src/i18n_set.h @@ -0,0 +1,25 @@ +#include <stdlib.h> +#include "i18n_cat.h" + +#define I18N_SETSIZE 1024 +#define I18N_TYPE_ASCII_LOWER 1000 +#define I18N_TYPE_ASCII_UPPER 1100 +#define I18N_TYPE_ASCII_NUMERALS 1200 +#define I18N_TYPE_ASCII_SYMBOLS 1300 +#define I18N_TYPE_ONE 2000 +#define I18N_TYPE_TWO 3000 +#define I18N_TYPE_THREE 4000 +#define I18N_TYPE_FOUR 5000 + +struct i18n_set { + int type; + int count; + unsigned int chars[I18N_SETSIZE]; + struct i18n_set* next; +}; + +struct i18n_set* i18n_set_new(int); +struct i18n_set* i18n_set_add(struct i18n_set*, int); +struct i18n_set* i18n_set_rm_type(struct i18n_set*, int); +void i18n_set_dump(struct i18n_set*); +void i18n_set_free(struct i18n_set*); @@ -19,7 +19,7 @@ #include <time.h> #include <locale.h> -#include "i18n_cat.h" +#include "i18n_set.h" // Shamelessly ripped off from the GCC docs on stringizing // This (xstr) converts a macro to a string literal @@ -54,51 +54,58 @@ void usage() { int main(int argc, char* argv[]) { struct timespec ts; // Timespec for seeding rng - unsigned int count; // Number of chars to choose from int debug; // Debug mode switch int len; // Password length int i; // Arg index unsigned long seed; // Seed for the RNG (current seconds * nanoseconds) - unsigned int chars[4096]; // Uint array to hold international chars + + struct i18n_set* set = NULL; // Linked list of i18n_set structs + struct i18n_set* cursor = NULL; // Cursor to track current position with in + // the linked list // Initialize debug = 0; - count = 0; len = 32; i = 1; - chars[0] = '\0'; - setlocale(LC_ALL, "en_US.UTF-8"); + setlocale(LC_ALL, ""); + + // Start with the defaults + set = i18n_set_new(I18N_TYPE_ASCII_UPPER); + i18n_set_add(set, I18N_TYPE_ASCII_LOWER); + i18n_set_add(set, I18N_TYPE_ASCII_NUMERALS); + i18n_set_add(set, I18N_TYPE_ASCII_SYMBOLS); + while(i < argc) { if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--capitals") == 0) { - count += i18n_cat_ascii_upper(chars); + i18n_set_add(set, I18N_TYPE_ASCII_UPPER); } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--lower") == 0) { - count += i18n_cat_ascii_lower(chars); + i18n_set_add(set, I18N_TYPE_ASCII_LOWER); } else if(strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--numerals") == 0) { - count += i18n_cat_ascii_numerals(chars); + i18n_set_add(set, I18N_TYPE_ASCII_NUMERALS); } else if(strcmp(argv[i], "-y") == 0 || strcmp(argv[i], "--symbols") == 0) { - count += i18n_cat_ascii_symbols(chars); + i18n_set_add(set, I18N_TYPE_ASCII_SYMBOLS); } else if(strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--i18n") == 0) { - count += i18n_cat_one(chars); - count += i18n_cat_two(chars); - count += i18n_cat_three(chars); - count += i18n_cat_four(chars); + i18n_set_add(set, I18N_TYPE_ONE); + i18n_set_add(set, I18N_TYPE_TWO); + i18n_set_add(set, I18N_TYPE_THREE); + i18n_set_add(set, I18N_TYPE_FOUR); } else if(strcmp(argv[i], "-1") == 0) { - count += i18n_cat_one(chars); + i18n_set_add(set, I18N_TYPE_ONE); } else if(strcmp(argv[i], "-2") == 0) { - count += i18n_cat_two(chars); + i18n_set_add(set, I18N_TYPE_TWO); } else if(strcmp(argv[i], "-3") == 0) { - count += i18n_cat_three(chars); + i18n_set_add(set, I18N_TYPE_THREE); } else if(strcmp(argv[i], "-4") == 0) { - count += i18n_cat_four(chars); + i18n_set_add(set, I18N_TYPE_FOUR); } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { usage(); @@ -125,25 +132,34 @@ int main(int argc, char* argv[]) { i++; } - // If no charset was specified, use standard ascii 33 - 126 chars, which - // includes english lower case, upper case, numbers, and some symbols. - if(chars[0] == '\0') - count += i18n_cat_ascii(chars); if(debug) - i18n_dump_arr(chars); + i18n_set_dump(set); // Get the random data seed clock_gettime(CLOCK_REALTIME, &ts); seed = ts.tv_sec + ts.tv_nsec; srand((unsigned)seed); + cursor = set; while(len > 0) { - int r = rand() % count; - printf("%lc", chars[r]); + // Randomly select the number of character sets to advance through (max 10) + int i = rand() % 10; + while(i > 0) { + // Loop + if(cursor->next == NULL) + cursor = set; + cursor = cursor->next; + i--; + } + + // Randomly select an integer within the set size + int rc = rand() % cursor->count; // Random char within set + printf("%lc", cursor->chars[rc]); len--; } printf("\n"); + i18n_set_free(set); return 0; } |