After fixing the undefined reference to 'pow' by adding -lm at the end of the cc line, you have another error:
charset_length is 62. max is 8.
So, when you do:
int num_combinations = pow(charset_length, max);
You are doing pow(62,8) which, when truncated to an int, you get a negative number. The result of the pow is on the order of 2.1e14, so far too large for an int.
So, the subsequent for loop will execute zero times.
You may want to use long long instead, but 2e14 iterations seems like a lot.
Doing:
int num_combinations = pow(charset_length, max - min);
seems more reasonable (and fits inside an int). But, in that case, your program just outputs blank lines.
UPDATE
When I've done a similar type of iteration, I've used a "helper" vector that is the current number width in length. I treat this an an N digit wide number in base(charset_length).
It takes values for each digit in the range of 0 to charset_length - 1.
I think it's easier to have the outer loop be output word length (e.g. 4-8) and then generate all words of that length from the charset
So, I had to do some considerable refactoring, splitting up the generation code into multiple functions.
The actual runtime is so large that I added progress output to stdout ...
Here is the refactored code. It is annotated:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
// incbignum -- increment the base N number
// RETURNS: carryout/overflow
int
incbignum(unsigned char *bignum,int iwid,int base)
{
int carry = 1;
for (int idx = 0; idx < iwid; ++idx) {
int val = bignum[idx];
val += carry;
carry = (val >= base);
if (carry)
val %= base;
bignum[idx] = val;
if (! carry)
break;
}
return carry;
}
// tscgetf -- get time in fractional seconds
double
tscgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_MONOTONIC,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
return sec;
}
// genlength -- generate all words of a given length from all chars in charset
void
genlength(FILE *file,const char *charset,int iwid)
{
int charset_length = strlen(charset);
unsigned long long wordcount = 0;
char buffer[iwid + 1];
// create a number in base(charset_length) with iwid number of digits
unsigned char bignum[iwid];
memset(bignum,0,iwid);
// show some progress
printf("genlength: iwid=%d\n",iwid);
double tscold = tscgetf();
while (1) {
// get the current output word
for (int idx = 0; idx < iwid; ++idx)
buffer[idx] = charset[bignum[idx]];
buffer[iwid] = 0;
// send it to the file
fputs(buffer,file);
fputc('\n',file);
// advance the base(charset_length) number
if (incbignum(bignum,iwid,charset_length))
break;
// show progress
if ((++wordcount % 3761) == 0) {
double tscnow = tscgetf();
if ((tscnow - tscold) >= 1.0) {
printf("\rwordcount=%llu %s",wordcount,buffer);
fflush(stdout);
tscold = tscnow;
}
}
}
printf("\nfinal=%llu\n",wordcount);
}
void
Dictionary_Generator(const char *charset, int min, int max)
{
char *password = malloc((max + 1) * sizeof(char));
if (password == NULL) {
fprintf(stderr, "Error: memory allocation failed\n");
exit(1);
}
FILE *file = fopen("dictionary.txt", "w");
if (file == NULL) {
fprintf(stderr, "Error: could not create file\n");
exit(1);
}
int charset_length = strlen(charset);
#if 0
int num_combinations = pow(charset_length, max);
#else
int num_combinations = pow(charset_length, max - min);
#endif
printf("num_combinations=%d\n",num_combinations);
#if 0
for (int i = 0; i < num_combinations; i++) {
int index = i;
int length = min;
while (index >= charset_length) {
password[length - 1] = charset[index % charset_length];
index /= charset_length;
length++;
}
password[length - 1] = charset[index];
password[length] = '\0';
if (length >= min) {
int result = fprintf(file, "%s\n", password);
if (result < 0) {
perror("Error writing to file");
exit(1);
}
}
}
#else
for (int iwid = min; iwid <= max; ++iwid)
genlength(file,charset,iwid);
#endif
fclose(file);
free(password);
}
int
main()
{
// NOTE -- the full charset takes a _long_ time ... :-)
#if TEST
const char *charset = "abcdefghijklmnopqrstuvwxyz";
#else
const char *charset = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789";
#endif
int min = 4;
int max = 8;
Dictionary_Generator(charset, min, max);
return 0;
}