"Fossies" - the Fresh Open Source Software Archive

Member "pwgen-2.08/pw_rand.c" (7 Aug 2017, 3258 Bytes) of package /linux/privat/pwgen-2.08.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pw_rand.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.07_vs_2.08.

    1 /*
    2  * pw_rand.c --- generate completely random (and hard to remember)
    3  *  passwords
    4  *
    5  * Copyright (C) 2001,2002 by Theodore Ts'o
    6  * 
    7  * This file may be distributed under the terms of the GNU Public
    8  * License.
    9  */
   10 
   11 #include <string.h>
   12 #include <stdio.h>
   13 #include <stdlib.h>
   14 #include "pwgen.h"
   15 
   16 const char *pw_digits = "0123456789";
   17 const char *pw_uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   18 const char *pw_lowers = "abcdefghijklmnopqrstuvwxyz";
   19 const char *pw_symbols = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
   20 const char *pw_ambiguous = "B8G6I1l0OQDS5Z2";
   21 const char *pw_vowels = "01aeiouyAEIOUY";
   22 
   23 static void remove_chars(char *buf, const char *remove)
   24 {
   25     const char *cp;
   26 
   27     if (!remove)
   28         return;
   29     for (cp = remove; *cp; cp++) {
   30         char *r = strchr(buf, *cp);
   31 
   32         if (r == NULL)
   33             continue;
   34         memmove(r, r+1, strlen(r));
   35     }
   36 }
   37 
   38 static int find_chars(char *buf, const char *set)
   39 {
   40     const char *cp;
   41 
   42     for (cp = set; *cp; cp++)
   43         if (strchr(buf, *cp))
   44             return 1;
   45     return 0;
   46 }
   47 
   48 void pw_rand(char *buf, int size, int pw_flags, char *remove)
   49 {
   50     char        ch, *chars, *wchars;
   51     int     i, len, feature_flags;
   52 
   53     len = 0;
   54     if (pw_flags & PW_DIGITS) {
   55         len += strlen(pw_digits);
   56     }
   57     if (pw_flags & PW_UPPERS) {
   58         len += strlen(pw_uppers);
   59     }
   60     len += strlen(pw_lowers);
   61     if (pw_flags & PW_SYMBOLS) {
   62         len += strlen(pw_symbols);
   63     }
   64         chars = malloc(len+1);
   65         if (!chars) {
   66         fprintf(stderr, "Couldn't malloc pw_rand buffer.\n");
   67         exit(1);
   68     }
   69     wchars = chars;
   70     if (pw_flags & PW_DIGITS) {
   71         strcpy(wchars, pw_digits);
   72         wchars += strlen(pw_digits);
   73     }
   74     if (pw_flags & PW_UPPERS) {
   75         strcpy(wchars, pw_uppers);
   76         wchars += strlen(pw_uppers);
   77     }
   78     strcpy(wchars, pw_lowers);
   79     wchars += strlen(pw_lowers);
   80     if (pw_flags & PW_SYMBOLS) {
   81         strcpy(wchars, pw_symbols);
   82     }
   83     if (remove) {
   84         if (pw_flags & PW_AMBIGUOUS)
   85             remove_chars(chars, pw_ambiguous);
   86         if (pw_flags & PW_NO_VOWELS)
   87             remove_chars(chars, pw_vowels);
   88         remove_chars(chars, remove);
   89         if ((pw_flags & PW_DIGITS) &&
   90             !find_chars(chars, pw_digits)) {
   91             fprintf(stderr,
   92                 "Error: No digits left in the valid set\n");
   93             exit(1);
   94         }
   95         if ((pw_flags & PW_UPPERS) &&
   96             !find_chars(chars, pw_uppers)) {
   97             fprintf(stderr,
   98                 "Error: No upper case letters left in "
   99                 "the valid set\n");
  100             exit(1);
  101         }
  102         if ((pw_flags & PW_SYMBOLS) &&
  103             !find_chars(chars, pw_symbols)) {
  104             fprintf(stderr,
  105                 "Error: No symbols left in the valid set\n");
  106             exit(1);
  107         }
  108         if (chars[0] == '\0') {
  109             fprintf(stderr,
  110                 "Error: No characters left in the valid set\n");
  111             exit(1);
  112         }
  113     }
  114     len = strlen(chars);
  115 try_again:
  116     feature_flags = (size > 2) ? pw_flags : 0;
  117     i = 0;
  118     while (i < size) {
  119         ch = chars[pw_number(len)];
  120         if ((pw_flags & PW_AMBIGUOUS) && strchr(pw_ambiguous,ch))
  121             continue;
  122         if ((pw_flags & PW_NO_VOWELS) && strchr(pw_vowels, ch))
  123             continue;
  124         buf[i++] = ch;
  125         if ((feature_flags & PW_DIGITS) &&
  126             strchr(pw_digits, ch))
  127             feature_flags &= ~PW_DIGITS;
  128         if ((feature_flags & PW_UPPERS) &&
  129             strchr(pw_uppers, ch))
  130             feature_flags &= ~PW_UPPERS;
  131         if ((feature_flags & PW_SYMBOLS) &&
  132             strchr(pw_symbols, ch))
  133             feature_flags &= ~PW_SYMBOLS;
  134     }
  135     if (feature_flags & (PW_UPPERS | PW_DIGITS | PW_SYMBOLS))
  136         goto try_again;
  137     buf[size] = 0;
  138     free(chars);
  139     return;
  140 }