1 // upwgen generates random internationalized passwords
2 // Copyright (C) 2019 Aaron Ball <nullspoon@oper.io>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <time.h>
20 #include <locale.h>
21
22 #include "i18n_cat.h"
23
24
25 void usage() {
26 printf(
27 "Upwgen is a password generator with international support. If no length\n"
28 "is specified, defaults to 32 characters output length, selecting from\n"
29 "the standard English character set (lower case, upper case, numerals,\n"
30 "and symbols).\n\n"
31 "Usage:\n upwgen [options] [length]\n\n"
32 "Options:\n"
33 " -c,--capitalize Include at least one capital letter in output\n"
34 " -l,--lower Include at least one lower case letter in output\n"
35 " -n,--numerals Include at least one numeral in output\n"
36 " -y,--symbols Include at least one symbol in output\n"
37 " -i,--i18n Include at least one international letter in output\n"
38 " -1 Include chars from the most used scripts in the world\n"
39 " -2 Include chars from the second most used scripts in the world\n"
40 " -3 Include chars from the third most used scripts in the world\n"
41 " -4 Include chars from the forth most used scripts in the world\n"
42 "\n"
43 " -h,--help Print this help text\n"
44 );
45 }
46
47
48 int main(int argc, char* argv[]) {
49 struct timespec ts; // Timespec for seeding rng
50 unsigned int count; // Number of chars to choose from
51 int len; // Password length
52 int i; // Arg index
53 unsigned long seed; // Seed for the RNG (current seconds * nanoseconds)
54 unsigned int chars[4096]; // Uint array to hold international chars
55
56 // Initialize
57 count = 0;
58 len = 32;
59 i = 1;
60 chars[0] = '\0';
61 setlocale(LC_ALL, "en_US.UTF-8");
62
63 while(i < argc) {
64 if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--capitals") == 0) {
65 count += i18n_cat_ascii_upper(chars);
66
67 } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--lower") == 0) {
68 count += i18n_cat_ascii_lower(chars);
69
70 } else if(strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--numerals") == 0) {
71 count += i18n_cat_ascii_numerals(chars);
72
73 } else if(strcmp(argv[i], "-y") == 0 || strcmp(argv[i], "--symbols") == 0) {
74 count += i18n_cat_ascii_symbols(chars);
75
76 } else if(strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--i18n") == 0) {
77 count += i18n_cat_one(chars);
78 count += i18n_cat_two(chars);
79 count += i18n_cat_three(chars);
80 count += i18n_cat_four(chars);
81
82 } else if(strcmp(argv[i], "-1") == 0) {
83 count += i18n_cat_one(chars);
84
85 } else if(strcmp(argv[i], "-2") == 0) {
86 count += i18n_cat_two(chars);
87
88 } else if(strcmp(argv[i], "-3") == 0) {
89 count += i18n_cat_three(chars);
90
91 } else if(strcmp(argv[i], "-4") == 0) {
92 count += i18n_cat_four(chars);
93
94 } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
95 usage();
96 return 0;
97
98 } else {
99 // If we reach this block, the user specified a custom length (or
100 // fatfingered something). Test for ability to convert from str to int
101 // and set length if possible.
102 if(atoi(argv[i]) == 0) {
103 printf("Invalid length \"%s\"\n", argv[i]);
104 return 1;
105 } else {
106 len = atoi(argv[i]);
107 }
108 }
109 i++;
110 }
111
112 // If no charset was specified, use standard ascii 33 - 126 chars, which
113 // includes english lower case, upper case, numbers, and some symbols.
114 if(chars[0] == '\0')
115 count += i18n_cat_ascii(chars);
116
117 // Get the random data seed
118 clock_gettime(CLOCK_REALTIME, &ts);
119 seed = ts.tv_sec + ts.tv_nsec;
120 srand((unsigned)seed);
121
122 while(len > 0) {
123 int r = rand() % count;
124 printf("%lc", chars[r]);
125 len--;
126 }
127 printf("\n");
128
129 return 0;
130 }
|