
/* Programmed in C by Juanjo Garcia <juanjo@eurogaran.com>
This file Copyright: (C)2003 Juanjo Garcia <juanjo@eurogaran.com>

   This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.

  You should have received a copy of the GNU Library General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* This file is  generall.c
 *
 * GENERAtes ALL possible combinations of
 * ASCII literals, numerals and signs
 * (presorted) to stdout.
 */

/* Compile:
 *
 $ cc -o generall generall.c
 *
 * or, under GNU:
 *
 $ gcc -Wall -O6 -ansi -pedantic -o generall generall.c
 *
 * inside vi:
 * :set makeprg=gcc\ -Wall\ -O6\ -ansi\ -pedantic\ -o\ generall\ generall.c
 * :make
 *
 * Examples of use:

 $ ./generall -s > passwords.txt

 $ generall > fifo && ./attack $ROUTER fifo

 $ generall | { while read; do
 > MD5SUM=`echo $REPLY | md5sum`;
 > echo "$REPLY $MD5SUM"; done }

 */


#include <stdio.h>   /* printf() */
#include <stdlib.h>  /* malloc() */
#include <string.h>  /* strcmp() */

#ifndef VERSION
#define VERSION "1.0"
#endif

#define INI_lngt 0   /* INItial num of characters */
#define FIN_lngt 65535  /* max size assignable by malloc() in 32 bit machines */
/* real FINal num of characters = FIN_lngt -1 (occupied by string terminator) */

#define FIN_crct 127 /* real FINal character = 126 ("~") */

static char *word;
static size_t lngt;
static char INI_crct; /* 32 (decimal) = space */

void combin (size_t pos) {
  unsigned char crct; /* locally created with every function call */
  if (pos<lngt) { /* inequality suffices, minor for security */
                  /* "while (pos<lngt)" would be unnecessary */
    for (crct=INI_crct; crct<FIN_crct; crct++) {
      word[pos]=crct;
      combin(pos+1); /* RECURSIVITY */
    }
  } else printf("%s\n",word);
}


int main (int argc, char ** argv)
{
  unsigned show_version=0, show_help=0, inc_spc=0, ini_set=0;
  size_t ini_lngt=INI_lngt, fin_lngt=FIN_lngt;

  for (lngt = 1; lngt < argc; lngt++) {
    if ((strcmp (argv[lngt], "--usage") == 0) ||
      (strcmp (argv[lngt], "--help") == 0) ||
      (strcmp (argv[lngt], "-h") == 0))
    {
      show_help = 1;
      argv[lngt] = NULL;
    }
    else if (strcmp (argv[lngt], "--version") == 0 ||
      strcmp (argv[lngt], "-v") == 0)
    {
      show_version = 1;
      argv[lngt] = NULL;
    }
    else if (strcmp (argv[lngt], "--spaces") == 0 ||
      strcmp (argv[lngt], "-s") == 0 ||
      strcmp (argv[lngt], "+s") == 0)
    {
      inc_spc = 1;
      argv[lngt] = NULL;
    }
  /* Anything else starting with a '-' is an error. */
    else if (argv[lngt][0] == '-') show_help = 1;
    else
    {
      if (ini_set)
      {
        fin_lngt = (size_t)strtol(argv[lngt],NULL,0)+1;
      } else {
        ini_set = 1;
        ini_lngt = (size_t)strtol(argv[lngt],NULL,0);
      }
      argv[lngt] = NULL;
    }
  }

  if (show_version)
    printf ("%s version %s \n", argv[0], VERSION);

  if (show_help) {
    printf ("\007Usage: %s [option ...] [int] [int]\n", argv[0]);
    printf ("Print all possible combinations of ASCII characters to standard output.\n");
    printf ("Valid options are:\n");
    printf ("  -v --version           Output version info.\n");
    printf ("  -h --help --usage      Output this help.\n");
    printf ("  -s +s --spaces         Do not exclude spaces.\n");
    printf ("  [int] [int]            Initial and final number of characters.\n");
  }

  if (show_version || show_help)
    exit (0);

  if (inc_spc)
    INI_crct = 32;
  else
    INI_crct = 33;

  if (ini_lngt > fin_lngt)  /* => permute: */
  {
    lngt = ini_lngt;
    ini_lngt = fin_lngt;
    fin_lngt = lngt;
  }

  for (lngt=ini_lngt; lngt<fin_lngt; lngt++) {
    if (!(word = (char *) malloc (lngt+1))) {
      fprintf(stderr, "%s: Could not allocate memory.\n",argv[0]);
      exit (1);
    }
    word[lngt]='\0';  /* necessary to terminate string */
        combin(0);
    free(word);
  }
  return (0);
}

