pwgen.c 2.7 KB

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