toybox/toys/other/pwgen.c
<<
>>
Prefs
   1/* pwgen.c - A password generator.
   2 *
   3 * Copyright 2020 Moritz Röhrich <moritz@ildefons.de>
   4
   5USE_PWGEN(NEWTOY(pwgen, ">2r(remove):c(capitalize)n(numerals)y(symbols)s(secure)B(ambiguous)h(help)C1vA(no-capitalize)0(no-numerals)[-cA][-n0][-C1]", TOYFLAG_USR|TOYFLAG_BIN))
   6
   7config PWGEN
   8  bool "pwgen"
   9  default y
  10  help
  11    usage: pwgen [-cAn0yrsBhC1v] [LENGTH] [COUNT]
  12
  13    Generate human-readable random passwords. When output is to tty produces
  14    a screenfull to defeat shoulder surfing (pick one and clear the screen).
  15
  16    -c  --capitalize                  Permit capital letters.
  17    -A  --no-capitalize               Don't include capital letters.
  18    -n  --numerals                    Permit numbers.
  19    -0  --no-numerals                 Don't include numbers.
  20    -y  --symbols                     Permit special characters ($#%...).
  21    -r <chars>  --remove=<chars>      Don't include the given characters.
  22    -s  --secure                      Generate more random passwords.
  23    -B  --ambiguous                   Avoid ambiguous characters (e.g. 0, O).
  24    -h  --help                        Print this help message.
  25    -C                                Print the output in columns.
  26    -1                                Print the output one line each.
  27    -v                                Don't include vowels.
  28*/
  29
  30#define FOR_pwgen
  31#include "toys.h"
  32
  33GLOBALS(
  34  char *r;
  35)
  36
  37void pwgen_main(void)
  38{
  39  int length = 8, count, ii, jj, c, rand = 0, x = 0;
  40  unsigned xx = 80, yy = 24;
  41  char randbuf[16];
  42
  43  if (isatty(1)) terminal_size(&xx, &yy);
  44  else toys.optflags |= FLAG_1;
  45
  46  if (toys.optc && (length = atolx(*toys.optargs))>sizeof(toybuf))
  47    error_exit("bad length");
  48  if (toys.optc>1) count = atolx(toys.optargs[1]);
  49  else count = FLAG(1) ? 1 : (xx/(length+1))*(yy-1);
  50
  51  for (jj = 0; jj<count; jj++) {
  52    for (ii = 0; ii<length;) {
  53      // Don't fetch more random than necessary, give each byte 2 tries to fit
  54      if (!rand) xgetrandom(randbuf, rand = sizeof(randbuf), 0);
  55      c = 33+randbuf[--rand]%93; // remainder 69 makes >102 less likely
  56      if (FLAG(s)) randbuf[rand] = 0;
  57
  58      if (c>='A' && c<='Z') {
  59        if (FLAG(A)) continue;
  60        // take out half the capital letters to be more human readable
  61        else c |= (0x80&randbuf[rand])>>2;
  62      }
  63      if (FLAG(0) && c>='0' && c<='9') continue;
  64      if (FLAG(B) && strchr("0O1lI8B5S2ZD'`.,", c)) continue;
  65      if (FLAG(v) && strchr("aeiou", tolower(c))) continue;
  66      if (!FLAG(y) || (0x80&randbuf[rand]))
  67        if (c<'0' || (c>'9' && c<'A') || (c>'Z' && c<'a') || c>'z') continue;
  68      if (TT.r && strchr(TT.r, c)) continue;
  69
  70      toybuf[ii++] = c;
  71    }
  72    if (FLAG(1) || (x += length+1)+length>=xx) x = 0;
  73    xprintf("%.*s%c", length, toybuf, x ? ' ' : '\n');
  74  }
  75  if (x) xputc('\n');
  76}
  77