/**********************************************************************/
/*                                                                    */
/* Program: rndpw.c                                                   */
/*                                                                    */
/* Description:                                                       */
/* ============                                                       */
/*                                                                    */
/* This program generates random ascii passwords with n characters.   */
/* The algorithm is quite simple. The random numbers are rectangular  */
/* distributed and the same character can appeare several times in    */
/* the password. Flags are set to select digits, lower case, upper    */
/* case and other characters. The random seed is generated automa-    */
/* tically or selected manually. All input parameter are integers.    */
/*                                                                    */
/* Usually one has to run the program several times to get a useable  */
/* password. For security reasons random passwords are very good,     */
/* but on the other hand they are hard to remember.                   */
/*                                                                    */
/* Author:                                                            */
/* =======                                                            */
/*                                                                    */
/* Stefan Spaennare, Lund, Sweden                                     */
/*                                                                    */
/* E-mail: stefan@spaennare.se                                        */
/*                                                                    */
/* First version: 2003-01-31                                          */
/* Latest update: 2007-07-27                                          */
/*                                                                    */
/* Reference:                                                         */
/* ==========                                                         */
/*                                                                    */
/* Random function (ran2) from "Numerical Recipes in C"               */ 
/* second edition.                                                    */
/*                                                                    */
/**********************************************************************/ 

/********************************************************************************/
/*                                                                              */
/* Notice                                                                       */
/* ======                                                                       */
/*                                                                              */
/* I make no warranties that this program is (1) free of errors, (2) consistent */
/* with any standard merchantability, or (3) meeting the requirements of a      */
/* particular application. This software shall not, partly or as a whole,       */
/* participate in a process, whose outcome can result in injury to a person or  */
/* loss of property. It is solely designed for analytical work. Permission to   */
/* use, copy and distribute is hereby granted without fee, providing that the   */
/* header above including this notice appears in all copies.                    */
/*                                                                              */
/*                                                            Stefan Spaennare  */
/*                                                                              */
/********************************************************************************/


#include <math.h>
#include <stdio.h>
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h>
#include <time.h>

double timetic=(double)(CLOCKS_PER_SEC); 


#define IM1 2147483563
#define IM2 2147483399
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NTAB 32
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS) 


double ran2(idum)
long *idum;
{
   int j;
   long k;
   static long idum2=123456789;
   static long iy=0; 
   static long iv[NTAB];
   double temp;    if (*idum <= 0) {
      if (-(*idum) < 1) {
         *idum=1;
      }
      else {
         *idum=-(*idum);
      } /* if */
      idum2=(*idum);
      for (j=NTAB+7; j>=0; j--) {
         k=(*idum)/IQ1;
	 *idum=IA1*(*idum-k*IQ1)-k*IR1;
	 if (*idum < 0) {
	    *idum += IM1;
	 } /* if */
	 if (j < NTAB) {
	    iv[j]=*idum;
	 } /* if */
      } /* for j */
      iy=iv[0];
   } /* if */
   k=(*idum)/IQ1;
   *idum=IA1*(*idum-k*IQ1)-k*IR1;
   if (*idum < 0) {
      *idum += IM1;
   } /* if */
   k=idum2/IQ2;
   idum2=IA2*(idum2-k*IQ2)-k*IR2;
   if (idum2 < 0) {
      idum2 += IM2;
   } /* if */
   j=iy/NDIV;
   iy=iv[j]-idum2;
   iv[j] = *idum;
   if (iy < 1) {
      iy += IMM1;
   } /* if */
   temp=AM*(double)(iy);
   if (temp > RNMX) {
      return(RNMX);
   }
   else {
      return(temp);
   } /* if */

} /* ran2 */

 
int main(argc,argv) 
int argc;
char *argv[];
{    

   int i,n,d1,l1,u1,o1;    
   
   long idum,seed;    
   
   double ttt1,ttt2;

   char c;

   time_t tt;
 
   if (argc != 7) {
      printf("Usage: %s seedi digitsi(0/1) lower_casei(0/1) upper_casei(0/1) othersi(0/1) ncharsi \n",argv[0]);
      printf("\n");
      printf("seed:       Random seed > 0. If seed = 0 the random numbers are initialized automatically.\n");
      printf("digits:     If digits = 1 the characters 0...9 can be included.\n");
      printf("lower_case: If lower_case = 1 the characters a...z can be included.\n");
      printf("upper_case: If upper_case = 1 the characters A...Z can be included.\n");
      printf("others:     If others = 1 all other characters (except ^  ~ and space) can be included.\n");
      printf("nchars:     Number of output characters.\n");
      printf("\n");
      exit(0);
   } /* if */    

   seed=atoi(argv[1]);
   d1=atoi(argv[2]);
   l1=atoi(argv[3]);
   u1=atoi(argv[4]);
   o1=atoi(argv[5]);
   n=atoi(argv[6]);

   if (seed == 0) {
      tt=time(0);    
      ttt1=(double)(tt)+0.5;    
      ttt2=fmod(ttt1,2147483647.0);    
      seed=(long)(ttt2);    
      idum=-seed-1;
   } 
   else {
      idum=-abs(seed)-1;
   } /* if */

   if (d1 != 1) {
      d1=0;
   } /* if */

   if (l1 != 1) {
      l1=0;
   } /* if */

   if (u1 != 1) {
      u1=0;
   } /* if */

   if (o1 != 1) {
      o1=0;
   } /* if */


   printf("\n");


      if ((o1==0) && (u1==0) && (l1==0) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=47) || (c>=58));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==0) && (u1==0) && (l1==1) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=96) || (c>=123));

             putchar(c);

          } /* for i */

      }  /* if */


      if ((o1==0) && (u1==0) && (l1==1) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=47) || ((c>=58) && (c<=96)) || (c>=123));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==0) && (u1==1) && (l1==0) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=64) || (c>=91));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==0) && (u1==1) && (l1==0) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=47) || ((c>=58) && (c<=64)) || (c>=91));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==0) && (u1==1) && (l1==1) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=64) || ((c>=91) && (c<=96)) || (c>=123));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==0) && (u1==1) && (l1==1) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while ((c<=47) || ((c>=58) && (c<=64)) ||
                    ((c>=91) && (c<=96)) || (c>=123));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==0) && (l1==0) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=48) && (c<=57)) || ((c>=65) && (c<=90)) || 
	            ((c>=97) && (c<=122)) || (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==0) && (l1==0) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=65) && (c<=90)) || ((c>=97) && (c<=122)) || 
	            (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==0) && (l1==1) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=48) && (c<=57)) || ((c>=65) && (c<=90)) || 
	            (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==0) && (l1==1) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=65) && (c<=90)) || (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==1) && (l1==0) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=48) && (c<=57)) || ((c>=97) && (c<=122)) || 
	            (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==1) && (l1==0) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=97) && (c<=122)) || (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==1) && (l1==1) && (d1==0)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

            } while (((c>=48) && (c<=57)) || (c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


      if ((o1==1) && (u1==1) && (l1==1) && (d1==1)) {

         for (i=1; i<=n; i++) {

            do {             

               c=(int)(94.0*ran2(&idum))+33;

             } while ((c==94) || (c==126));

             putchar(c);

          } /* for i */

      } /* if */


   printf("\n");


} /* End */

