add netbsd nl(1)
[rofl0r-hardcore-utils.git] / pwgen.c
blobd3dba813d1c197ab58913f990e296de9f8f35bb4
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <unistd.h>
7 #define NUM "0123456789"
8 #define ALL "abcdefghijklmnopqrstuvwxyz"
9 #define ALU "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
10 #define SYM ",.;:=%*+-_/@!$&|\?\\(){}[]^ '\""
11 #define SL(X) sizeof(X) -1
12 #define ENTRY(X, Y, Z) {X, Y, SL(Z)}
14 static const struct {char name[6]; unsigned char idx, len;} md[] = {
15 ENTRY("all", 0, NUM ALL ALU SYM),
16 ENTRY("num", 0, NUM),
17 ENTRY("lower", SL(NUM), ALL),
18 ENTRY("upper", SL(NUM ALL), ALU),
19 ENTRY("sym", SL(NUM ALL ALU), SYM),
20 ENTRY("alnum", 0, NUM ALL ALU),
21 ENTRY("alnuml", 0, NUM ALL),
24 static int set(const char *name) {
25 int i; size_t l=strlen(name);
26 if (l>6) return -1;
27 for(i=0;i<sizeof(md)/sizeof(md[0]);i++)
28 if(memcmp(md[i].name, name, l)==0) return i;
29 return -1;
31 static int usage(const char *b0) {
32 dprintf(2,
33 "usage: SET=name %s [number]\n"
34 "generates a random password.\n"
35 "SET is an environment variable and can be one of:\n"
36 "all num lower upper sym alnum alnuml\n"
37 "it denotes the set of characters we pick characters from.\n"
38 "SET can also be a negative number\n"
39 "(shrinks number of available chars in the 'all' set)\n"
40 "default: all\n"
41 "number denotes the desired length of the password\n"
42 "default: 16\n", b0);
43 return 1;
46 int main(int a, char**b) {
47 static const char alphabet[] = NUM ALL ALU SYM;
48 if(a == 2 && !strcmp(b[1], "--help")) return usage(b[0]);
49 const char *myset = getenv("SET");
50 int reduce = 0, setidx = myset ? set(myset) : 0;
51 if(setidx == -1) {
52 if(!myset || myset[0] != '-') {
53 dprintf(2, "set %s not found\nexecute %s --help for a list of sets\n", myset, b[0]);
54 return 1;
56 reduce = atoi(myset+1);
57 setidx = 0;
58 if(reduce >= SL(NUM ALL ALU SYM)) {
59 dprintf(2, "SET reduction greater than available chars\n");
60 return 1;
63 const char* ch = alphabet + md[setidx].idx;
64 const size_t chl = md[setidx].len-reduce;
65 int fd = open("/dev/urandom", O_RDONLY);
66 if(fd == -1) {
67 dprintf(2, "open /dev/urandom failed\n");
68 return 1;
70 int i, pwlen = a > 1 ? atoi(b[1]) : 16;
71 for(i=0;i<pwlen;i++) {
72 unsigned char rnd;
73 if(1!=read(fd, &rnd, 1)) {
74 dprintf(2, "read error\n");
75 return 1;
77 dprintf(1, "%c", ch[rnd%chl]);
79 dprintf(1, "\n");
80 close(fd);
81 return 0;