summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ball <nullspoon@oper.io>2019-08-25 23:01:53 -0600
committerAaron Ball <nullspoon@oper.io>2019-08-25 23:01:53 -0600
commit230c9f2ee14f3ce89ecaefc6d2dc7f4a18b0d5dc (patch)
treea1f2b0a5581b2e59d978754c2bde4b2c781efaca
parent4fc4a8a49eaecd5ac5d527a08438106c060dbfdd (diff)
downloadupwgen-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--Makefile6
-rw-r--r--src/i18n_set.c94
-rw-r--r--src/i18n_set.h25
-rw-r--r--src/main.c66
4 files changed, 165 insertions, 26 deletions
diff --git a/Makefile b/Makefile
index d6edc2e..e17dda5 100644
--- a/Makefile
+++ b/Makefile
@@ -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*);
diff --git a/src/main.c b/src/main.c
index 226b8d0..a266396 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}

Generated by cgit