I have to create a program that gets from the command line n arguments arg1, arg2 .... argn, creates n threads and each of them will read a text file argi and will print in reverse order even lines.
The problem is that my program creates the threads, finishes them, but actually he does nothing. He prints only some random characters, different at every runtime(characters from memory i think).
Below is my code:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 100
pthread_t myThread[10];
pthread_mutex_t myMutex;
void * fileprint(void * numei) {
printf("Thread: %ld ...> %s\n", pthread_self(), (char*)numei);
FILE *fi;
char line[MAXLINE], *p;
pthread_mutex_lock(&myMutex);
int k=0;
fi = fopen((char*)numei, "r");
for ( ; ; ) {
k++;
p = fgets(line, MAXLINE, fi);
if (p == NULL) break;
line[strlen(line) - 1] = '\0';
if(k %2 ==0){
for(int j=strlen(line);j>=0;j++){
printf("%c", line[j]);
}
printf("%c","\n");
}
}
fclose(fi);
printf("Finished thread: %ld ...> %s\n", pthread_self(), (char*)numei);
pthread_mutex_unlock(&myMutex);
}
int main(int argc, char* argv[]) {
pthread_mutex_init(&myMutex, NULL);
printf("I'm the father...\n");
int i;
for (i = 1; argv[i]; i++) {
pthread_create(&myThread[i], NULL, fileprint, (void*)argv[i]);
printf("Created thread: %ld ...> %s\n", myThread[i], argv[i]);
}
for (i = 1; argv[i]; i++) {
pthread_join(myThread[i], NULL);
}
printf("I'm still the father...\n");
pthread_mutex_destroy(&myMutex);
return 1;
}
So, anyone can tell me what's the problem? I tried lots of things to modify but nothing...
If you walk the string backward, you have to decrement the index inside the loop (j--). Also you should start at strlen(x)-1.
This line is incorrect:
printf("%c","\n");
The operand of %c must be a char, not char*. It should be either:
printf("%c",'\n');
or:
printf("%s", "\n");
or:
printf("\n");
However, I don't think this will cause a segmentation fault, it will just cause a random character to be printed.
for (i = 1; argv[i]; i++) {
You can also use "argc", it's the arg-counter.
printf("Thread: %ld ...> %s\n", pthread_self(), (char*)numei);
FILE *fi;
char line[MAXLINE], *p;
pthread_mutex_lock(&myMutex);
In your fileprint(...), put the printf(...) behind the mutex, or other threads could interrupt it and you get half-printed, weird sentences on you output.
mfg
Related
I am having an issue with my current code. I am working on a project where I am using threads to read a group of files from the terminal and tell how many lines there are in the individual and total grouping of files. My question is that when I run the code I get a core dump and when I run my code through gdb I get a segmentation fault at the pthread_create call. Is it because of my implementation or is it due to something else in my code?
#define NUM_THREADS 12
struct thread_data{
char *thread_id;
int count;
};
struct thread_data thread_data_array[NUM_THREADS];
void* filecount(void * thread_arg){
char thread_id;
int count;
struct thread_data *thread;
thread = (struct thread_data *) thread_arg;
thread_id = *thread->thread_id;
count = thread->count;
FILE *fp = fopen(&thread_id, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open %s\n", thread_id);
exit(-1);
}
for (char c = getc(fp); c != EOF; c = getc(fp))
if (c == '\n')
count++;
fclose(fp);
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
if (argc == 1)
return 0;
pthread_t threads[argc];
int t, total_count, count;
total_count = 0;
for(t=1; t<argc; t++){
thread_data_array[t].thread_id = argv[t];
thread_data_array[t].count = count;
printf("Creating thread for file: %s",thread_data_array[t].thread_id);
///This is the line in question///
pthread_create(&threads[t], NULL,filecount,(void *) &thread_data_array[t]);
printf("File name: %s --- line count: %d", thread_data_array[t].thread_id, total_count);
total_count += thread_data_array[t].count;
}
printf("Total line count: %d", total_count);
pthread_exit(NULL);
}
To summarize some of the comments:
This
char thread_id;
thread_id = *thread->thread_id;
will give you the first character of the filename. So while &thread_id is the correct type (char *) for the first argument of fopen, its not a pointer to a null terminating string. This is undefined behaviour.
In
thread_data_array[t].count = count;
count is uninitialized, and its value is indeterminate. This is undefined behaviour.
You need to wait for each thread to finish before you use its result. pthread_join is the function to use here.
getc (fgetc) returns type int, which allows for the check against EOF. Narrowing to char removes the ability to properly test for EOF.
thread_data_array should match the threads array in size.
Here is a refactored program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct thread_data {
char *thread_id;
int count;
};
void *filecount(void *thread_arg){
struct thread_data *arg = thread_arg;
FILE *fp = fopen(arg->thread_id, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open %s\n", arg->thread_id);
pthread_exit(NULL);
}
for (int c = getc(fp); c != EOF; c = getc(fp))
if (c == '\n')
arg->count++;
fclose(fp);
return NULL;
}
int main(int argc, char *argv[]){
if (argc == 1)
return 0;
argv++;
argc--;
pthread_t threads[argc];
struct thread_data thread_data_array[argc];
int total_count = 0;
for (int i = 0; i < argc; i++) {
thread_data_array[i].thread_id = argv[i];
thread_data_array[i].count = 0;
pthread_create(&threads[i], NULL, filecount,(void *) &thread_data_array[i]);
}
for (int i = 0; i < argc; i++) {
pthread_join(threads[i], NULL);
total_count += thread_data_array[i].count;
}
printf("Total line count: %d\n", total_count);
}
I've been trying to split writing to a file with threads and to do so I'm trying to use structs to hold the start and end positions of the file. The code compiles, However, I've been getting a segmentation fault when the code tries to create multiple threads and doesn't execute the thread code. Am I using structs correctly?
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define MAX_THREADS 100
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct position {
int start;
int end;
};
void *ThreadJob(void *id) //what the thread should do
{
pthread_mutex_lock(&mutex);
struct position *b;
printf("\nstart: %d \nend: %d\n", (*b).start, (*b).end);
double* arrayPtr = malloc( 100000* sizeof(double));
FILE *file;
FILE* nFile; // New file
double n;
nFile = fopen("newTriData1.txt","a");
char line[128]; //the lines of the txt file
file = fopen("TriData1.txt", "r");
long tid;
tid = (long)id;
int count = 0;
while (fgets(line, 128, file)) //gets the lines from the txt file - line by line
{
sscanf(line ," %lf", &arrayPtr[count]); //converts the value on the line into a double to manipulate
count++; //increment the count
}
free(arrayPtr);
while((*b).start<(*b).end){
double x = (sqrt(8*arrayPtr[(*b).start]+1) - 1) / 2; //equation to detect triangular numbers
if (x == floor(x)) //checks if the value has a remainder. The value should be a whole number
{
fprintf(nFile, "\nNumber %s: Triangular\n", line); //if true writes the value and triangular
}
else
{
fprintf(nFile, "\nNumber %s: Not Triangular\n", line);
}
(*b).start++;
}
(*b).start=(*b).end;
(*b).end = ((*b).end + (*b).end);
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
int main (void) //main
{
struct position a;
(a).start=0;
int line_count;
FILE *file;
double count_lines = 1.0;
char check;
double i = 4;
file = fopen("TriData1.txt", "r");
double divider;
check = getc(file);
while (check != EOF)
{
if (check == '\n')
{
count_lines = count_lines + 1;
}
check = getc(file); //take the next character from the file
}
printf("cl: %f", count_lines);
double vo = fmod(count_lines,4); //using fmod to find which number divides the line count into equal parts for the number of threads
if (fmod(count_lines,4) == 0) {
double value1 = count_lines/4;
double value2 = count_lines/4;
double value3 = count_lines/4;
double value4 = count_lines/4;
printf("v1: %f \n v2: %f \n v3: %f \n v4: %f", value1,value2,value3,value4);
divider =4;
line_count = count_lines/4;
(a).end=line_count;
}
else
{
while (fmod(count_lines, i) != 0) //if the value is not divisible by 4 then i will increment until a suitable divider is found
{
i++;
divider = i;
line_count = count_lines/i;
printf("divider: %f", divider);
}
(a).end=line_count;
}
fclose(file); //close file.
printf("There are %f lines in this file\n", count_lines);
printf("\nstart: %d \nend: %d\n", (a).start, (a).end);
pthread_t threads[MAX_THREADS];
int thread;
long threadNum ;
for(threadNum=0; threadNum<divider; threadNum++){
printf("Creating thread %ld\n", threadNum);
thread = pthread_create(&threads[threadNum], NULL, ThreadJob, (void *)threadNum);
if (thread){
printf("ERROR; %d\n", thread);
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}
Almost every line of your code is wrong, but most of your mistakes will just make your program do the wrong thing, not crash entirely. Here's just the mistakes that are making your program crash:
struct position *b;
printf("\nstart: %d \nend: %d\n", (*b).start, (*b).end);
That will probably segfault because you can't dereference an uninitialized pointer.
free(arrayPtr);
while((*b).start<(*b).end){
double x = (sqrt(8*arrayPtr[(*b).start]+1) - 1) / 2; //equation to detect triangular numbers
That might segfault because you can't use memory after you free it. Also, the last line of it will probably segfault because you still never initialized b.
(*b).start++;
}
(*b).start=(*b).end;
(*b).end = ((*b).end + (*b).end);
All of those lines will probably segfault because b still isn't initialized.
Frankly, you should give up on advanced topics like threads for now and work on trying to understand the basics of C.
I have a program that must take on command-line a file_name, a string string_name (word) and an integer (number of threads) as arguments. Then the program creates those many threads to count the number of times string_name occurs in the file - file_name.
The serial code run properly.
The multithreaded code has following problems:
It leads to core dump - segmentation fault.
It is giving wrong count.
I added some debugging statements:
It is showing wrong line numbers where I am trying to print which line number is being checked by which thread number.
#include <stdio.h>
// #include <conio.h> - Does not exist in gcc
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#define MAX_LINE_LENGTH 4096
#define MAX_WORD_SIZE 64
#define MAX_THREAD_COUNT_PER_PROCESS 64
// Important - in GCC - for pthread functions in addition to include pthread.h must also use flag -lpthread in compilation command
// gcc -w -o main main_multithreaded.c -lpthread
typedef unsigned int uint;
typedef struct {
uint valid;
uint line_num;
char* line;
} struct_line;
volatile struct_line buffer[MAX_THREAD_COUNT_PER_PROCESS];
pthread_mutex_t *buffer_mutex;
pthread_t* threads;
typedef struct {
FILE* fp;
} read_pthread_argv_type;
read_pthread_argv_type read_pthread_argv;
void read_file(void* read_pthread_argv)
{
read_pthread_argv_type* i_read_pthread_argv;
i_read_pthread_argv = (read_pthread_argv_type*) read_pthread_argv;
FILE* local_file_ptr;
local_file_ptr = i_read_pthread_argv->fp;
char *line;
uint i, line_count = 0, line_length;
line = (char*) malloc (MAX_LINE_LENGTH);
while (fgets(line, MAX_LINE_LENGTH, local_file_ptr) != NULL)
{
line_length = strlen (line);
while (pthread_mutex_lock(buffer_mutex))
{}
for (i = 0; i<MAX_THREAD_COUNT_PER_PROCESS; i++)
{
if (buffer[i].valid != 1)
{
break;
}
}
buffer[i].line = (char*) malloc (line_length);
buffer[i].line = line;
buffer[i].line_num = line_count;
buffer[i].valid = 1;
// printf ("Line %u of file read and saved as %s \n", buffer[i].line_num, buffer[i].line);
line_count++;
pthread_mutex_unlock(buffer_mutex);
}
printf ("File read finished \n");
free (line);
pthread_exit(NULL);
}
typedef struct {
char* string_to_search;
uint thread_num;
uint count;
} count_pthread_argv_type;
count_pthread_argv_type count_pthread_argv[MAX_THREAD_COUNT_PER_PROCESS];
int count_string (void* pthread_argv_i)
{
// Declare variables for line and word
char *line, *word;
line = (char*) malloc (MAX_LINE_LENGTH);
word = (char*) malloc (MAX_WORD_SIZE);
// Declare and initiaize count
uint count = 0, wordcount_in_line;
uint i, k = 0;
int j;
count_pthread_argv_type* i_pthread_argv;
i_pthread_argv = (count_pthread_argv_type*)pthread_argv_i;
char* local_string_to_search = i_pthread_argv->string_to_search;
uint local_thread_num = i_pthread_argv-> thread_num;
//printf (" For thread %u -> Local string to search = %s \n starting line = %u and num_lines = %u \n", \
local_thread_num, local_string_to_search, local_starting_line, local_num_lines);
//getchar();
while (1)
{
while (pthread_mutex_lock(buffer_mutex))
{}
for (i=0; i < MAX_THREAD_COUNT_PER_PROCESS; i++)
{
if (buffer[i].valid == 1)
{
line = buffer[i].line;
k = buffer[i].line_num;
buffer[i].valid = 0;
printf ("Thread %u checking line %u - which is %s \n", local_thread_num, k, buffer[i].line);
break;
}
}
pthread_mutex_unlock(buffer_mutex);
i = 0, j = 0, wordcount_in_line = 0;
while ( (*(line+i) != '\n') )
{
// Extract word
if ( (*(line+i) == ' '))
{
// NUll terminate the word to make it a string
*(word+j) = '\0';
// Compare
//printf ("Thread %u checking line %u - word number %u which is %s \n", local_thread_num, k, wordcount_in_line, word);
if (strcmp (word, local_string_to_search) == 0) // No double quotes around argv[2]
{
count ++;
printf("Thread %u found its local %uth occurence of %s in line %u at word %u \n", local_thread_num, count, word, k, wordcount_in_line);
}
// Make j = -1, after increment it will be 0 for new word
j = -1;
wordcount_in_line++ ;
}
else
{
*(word+j) = *(line+i);
}
// Increment both i and j to go to next character
i++; j++;
}
if ((*(line + i)) == '\n')
{
// If end of line - do the same thing on last word as is for every word
// NUll terminate the word to make it a string
*(word + j) = '\0';
// Compare
//printf ("Thread %u checking line %u - word number %u which is %s \n", local_thread_num, k, wordcount_in_line, word);
if (strcmp(word, local_string_to_search) == 0) // No double quotes around argv[2]
{
count++;
printf("Thread %u found its local %uth occurence of %s in line %u at word %u \n", local_thread_num, count, word, k, wordcount_in_line);
}
wordcount_in_line++ ;
}
}
void* status;
int rc;
rc = pthread_join (threads[0], &status);
printf ("Thread %u found %u occurences \n", local_thread_num, count);
i_pthread_argv->count = count;
//return (count);
pthread_exit(NULL);
}
int main (int argc, char* argv[])
{
// Declare file *
FILE* fp;
// Get file path and open file
//fp = fopen ("file_name.txt","r");
fp = fopen (argv[1],"r"); // No "" around argv[1]
if (fp == NULL)
{
printf ("fopen failed \n");
return 0;
}
printf ("file = %s and string to look for = %s \n", argv[1], argv[2]);
//fopen_s(&fp, "file_name.txt", "r");
//Initialize mutex
if (pthread_mutex_init(buffer_mutex, NULL))
printf ("Mutex initialization failed \n");
// Get number of lines in file
uint num_threads;
sscanf(argv[3], "%u", &num_threads);
// Create threads
//pthread_t* threads;
threads = (pthread_t*) malloc (sizeof (pthread_t)*MAX_THREAD_COUNT_PER_PROCESS);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
uint i = 0;
read_pthread_argv.fp = fp;
if ( pthread_create (&threads[0], &attr , read_file, (void*)(&read_pthread_argv) ) == 0)
printf("Thread creation %u passed \n", i);
for ( i = 1; i<num_threads; i++ )
{
count_pthread_argv[i].thread_num = i;
count_pthread_argv[i].string_to_search = argv[2];
//printf("Reached debugging point 1 \n");
if ( pthread_create (&threads[i], &attr , count_string, (void*)(&count_pthread_argv[i]) ) == 0)
printf("Thread creation %u passed \n", i);
}
//printf("Reached debugging point 2 \n");
// Doubt 2 - How to call pthread_join to wait for completion of multiple threads -
// Isnt the for loop executed sequentially and pthread_join in main for thread-2 will be executed after thread-1 exits
// Wait till all are over
pthread_attr_destroy(&attr);
void* status;
int rc;
for (i = 1; i<num_threads; i++ )
{
rc = pthread_join (threads[i], &status);
}
uint totalcount = 0;
for (i = 1; i<num_threads; i++)
{
printf ("count_returned = %u \n", count_pthread_argv[i].count);
totalcount += count_pthread_argv[i].count;
}
printf("From main, The file has %s -> %u times", argv[2], totalcount);
for (i=0; i<MAX_THREAD_COUNT_PER_PROCESS; i++)
{
free (buffer[i].line);
}
pthread_mutex_destroy(buffer_mutex);
getchar();
pthread_exit(NULL);
}
When i type ls i get this message twice : ls: cannot access : No such file or directory. But when i type something like that ls -l /tmp or executing a "c" code located in the path everything is fine. Any ideas what is going wrong?
My code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
for (;;) {
char *cmd,*splitcmd,*pr0,*pr1,*pr2;
int i, j, nargc = 0, characters;
char **cmdArray;
size_t bufsize = 1024;
pid_t pid, wpid;
int status = 0;
printf("Type a command : \n");
cmd = (char *) malloc(bufsize * sizeof(char));
characters = getline(&cmd, &bufsize, stdin);
// printf("cmd===> %s characters===> %d \n",cmd,characters);
if (cmd[characters-1] == '\n')
{
cmd[characters-1] = '\0';
characters--;
}
// printf("cmd===> %s characters===> %d \n",cmd,characters);
cmdArray = (char**) malloc(bufsize * sizeof(char *));
for (i = 0 ; i < bufsize ; i++)
{
cmdArray[i] = (char*) malloc(bufsize*sizeof(char));
}
splitcmd = strtok(cmd," ");
// printf(" cmd==== %s\n",cmd);
while ((splitcmd))
{
cmdArray[nargc] = splitcmd;
if (cmdArray[nargc][(strlen(cmdArray[nargc])) - 1] == ' ')
cmdArray[nargc][(strlen(cmdArray[nargc]))-1] == '\0';
// printf(" nargc====%d cmdArray===[ %s ] \n",nargc,cmdArray[nargc]);
nargc++;
pr0 = cmdArray[0];
pr1 = cmdArray[1];
pr2 = cmdArray[2];
splitcmd = strtok(NULL," ");
//printf(" pr0 %s \n",pr0);
//printf(" pr1 %s \n",pr1);
//printf(" pr2 %s \n",pr2);
}
if ((pid = fork()) == 0)
{
char *argv[] = {pr0, pr1, pr2, NULL};
execvp(argv[0],argv);
for (int i = 0; i < 100; i++) {
free(cmdArray[i]);
}
free(cmdArray);
}
wait(&status);
}
}
Your code has a number of problems, many of which are identified by turning on warnings. Use -Weverything if your compiler supports it, or at least -Wall if it does not. However, your particular question is in how you're calling execvp().
char *argv[] = {pr0, pr1, pr2, NULL};
execvp(argv[0],argv);
This will always pass two arguments to ls. Even if pr1 and pr2 are empty, ls will still act like it was passed arguments. ls will determine how many arguments it has by looking for a NULL entry.
Your code has a flaw in that it is trying to hard code the number of arguments by splitting up the cmdArray into individual variables. This isn't going to work. For starters, commands take more than two arguments. You should instead leave cmdArray together, properly NULL terminate it, and pass that into execvp.
Currently attempting to get this program to use multithreading using pthread_create, pthread_join, pthread_exit, and pthread_self. I then intend to use crypt_r in place of crypt in my code.
It will only be able to go up to 8 threads, but I don't even know how to get started with two. I just have one line that declares pthread_t t1,t2,t3,t4,t5,t6,t7,t8.
The plan with these is to put them in to pthread_create but besides initializing these values, I don't know where to go from here.
I know that pthread_create's input would be something like pthread_create(t1, NULL, ... , ...) but I do not know how to go about making the 3rd input or what the 4th input even is.
I then have to make sure to split up the range of letters that each thread is checking based on the number of threads specified by a command line arg. I've designed this so far to work on one thread only, planning on moving it to crypt_r with multithreading...
Really confused as to how I could get to make this work.. If possible.
I know some sort of void function is the third entry in to pthread_create.. but does that function have to be what my passwordChecker is? Or what?
/*
crack.exe
*/
/* g++ -o crack crack.c -lcrypt -lpthread */
//#define _GNU_SOURCE
#include <crypt.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
void *passwordLooper(int ks, char target[9], char s[10]);
void *threadFunction(void *threads);
int main(int argc, char *argv[]){ /* usage = crack threads keysize target */
int i = 0;
/* arg[0] = crack, arg[1] = #of threads arg[2] = size of password, arg[3] = hashed password being cracked */
if (argc != 4) {
fprintf(stderr, "Too few/many arguements give.\n");
fprintf(stderr, "Proper usage: ./crack threads keysize target\n");
exit(0);
}
int threads = *argv[1]-'0'; // threads is now equal to the second command line argument number
int keysize = *argv[2]-'0'; // keysize is now equal to the third command line argument number
char target[9];
strcpy(target, argv[3]);
char salt[10];
while ( i < 2 ){ //Takes first two characters of the hashed password and assigns them to the salt variable
salt[i] = target[i];
i++;
}
printf("threads = %d\n", threads); /*used for testing */
printf("keysize = %d\n", keysize);
printf("target = %s\n", target);
printf("salt = %s\n", salt);
if (threads < 1 || threads > 8){
fprintf(stderr, "0 < threads <= 8\n");
exit(0);
} /*Checks to be sure that threads and keysize are*/
if (keysize < 1 || keysize > 8){ /*of the correct size */
fprintf(stderr, "0 < keysize <= 8\n");
exit(0);
}
pthread_t t1,t2,t3,t4,t5,t6,t7,t8;
if ( threads = 1 ){
pthread_create(&t1, NULL, *threadFunction, threads);
}
char unSalted[30];
int j = 0;
for (i = 2; target[i] != '\0'; i++){ /*generates variable from target that does not include salt*/
unSalted[j] = target[i];
j++;
}
printf("unSalted = %s\n", unSalted); //unSalted is the variable target without the first two characters (the salt)
char password[9] = {0};
passwordLooper(keysize, target, salt);
}
/*_____________________________________________________________________________________________________________*/
/*_____________________________________________________________________________________________________________*/
void *passwordLooper(int ks, char target[9], char s[10]){
char password[9] = {0};
struct crypt_data cd;
cd.initialized = 0;
int result;
for (;;){
int level = 0;
while (level < ks && strcmp( crypt(password, s), target ) != 0) {
if (password[level] == 0){
password[level] = 'a';
break;
}
if (password[level] >= 'a' && password[level] < 'z'){
password[level]++;
break;
}
if (password[level] == 'z'){
password[level] = 'a';
level++;
}
}
char *cryptPW = crypt(password, s);
result = strcmp(cryptPW, target);
if (result == 0){ //if result is zero, cryptPW and target are the same
printf("result = %d\n", result);
printf ("Password found: %s\n", password);
printf("Hashed version of password is %s\n", cryptPW);
break;
}
if (level >= ks){ //if level ends up bigger than the keysize, break, no longer checking for passwords
printf("Password not found\n");
break;
}
}
return 0;
}
With malloc'd structs
/*
crack.exe
By: Zach Corse
*/
/* g++ -o crack crack.c -lcrypt -lpthread */
//#define _GNU_SOURCE
#include <crypt.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
void *passwordLooper(void *passwordData);
//void *threadFunction(void *threads);
typedef struct{
int keysize;
char *target;
char *salt;
}passwordData;
int main(int argc, char *argv[]){ /* usage = crack threads keysize target */
int i = 0;
/* arg[0] = crack, arg[1] = #of threads arg[2] = size of password, arg[3] = hashed password being cracked */
if (argc != 4) {
fprintf(stderr, "Too few/many arguements give.\n");
fprintf(stderr, "Proper usage: ./crack threads keysize target\n");
exit(0);
}
int threads = *argv[1]-'0'; // threads is now equal to the second command line argument number
int keysize = *argv[2]-'0'; // keysize is now equal to the third command line argument number
char target[9];
strcpy(target, argv[3]);
char salt[10];
while ( i < 2 ){ //Takes first two characters of the hashed password and assigns them to the salt variable
salt[i] = target[i];
i++;
}
printf("threads = %d\n", threads); /*used for testing */
printf("keysize = %d\n", keysize);
printf("target = %s\n", target);
printf("salt = %s\n", salt);
if (threads < 1 || threads > 8){
fprintf(stderr, "0 < threads <= 8\n");
exit(0);
} /*Checks to be sure that threads and keysize are*/
if (keysize < 1 || keysize > 8){ /*of the correct size */
fprintf(stderr, "0 < keysize <= 8\n");
exit(0);
}
pthread_t t1,t2,t3,t4,t5,t6,t7,t8;
struct crypt_data data;
data.initialized = 0;
//~ passwordData.keysize = keysize;
//~ passwordData.target = target;
//~ passwordData.salt = salt;
passwordData *pwd = (passwordData *) malloc(sizeof(pwd));
pwd->keysize = keysize;
pwd->target = target;
pwd->salt = salt;
//~ if ( threads = 1 ){
//~ pthread_create(&t1, NULL, *threadFunction, threads);
//~ }
char unSalted[30];
int j = 0;
for (i = 2; target[i] != '\0'; i++){ /*generates variable from target that does not include salt*/
unSalted[j] = target[i];
j++;
}
printf("unSalted = %s\n", unSalted); //unSalted is the variable target without the first two characters (the salt)
char password[9] = {0};
passwordLooper(pwd);
}
/*_____________________________________________________________________________________________________________*/
/*_____________________________________________________________________________________________________________*/
void *passwordLooper(passwordData pwd){
char password[9] = {0};
int result;
int ks = pwd.keysize;
char *target = pwd.target;
char *s = pwd.salt;
for (;;){
int level = 0;
while (level < ks && strcmp( crypt(password, s), target ) != 0) {
if (password[level] == 0){
password[level] = 'a';
break;
}
if (password[level] >= 'a' && password[level] < 'z'){
password[level]++;
break;
}
if (password[level] == 'z'){
password[level] = 'a';
level++;
}
}
char *cryptPW = crypt(password, s);
result = strcmp(cryptPW, target);
if (result == 0){ //if result is zero, cryptPW and target are the same
printf("result = %d\n", result);
printf ("Password found: %s\n", password);
printf("Hashed version of password is %s\n", cryptPW);
break;
}
if (level >= ks){ //if level ends up bigger than the keysize, break, no longer checking for passwords
printf("Password not found\n");
break;
}
}
return 0;
}
Well, here's the prototype for pthread_create:
int
pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void *), void *restrict arg);
It shows that the 3rd arg is a pointer to a function that returns a pointer to void and takes a pointer to void as its sole argument. I see you have a prototype for:
void *threadFunction(void *threads);
which meets those specifications, but it's not actually written? The 4th argument in pthread_create is just a pointer to void, which can essentially contain anything you want it to.
I'm guessing that the function you want to thread is actually passwordLooper, which takes 3 arguments.. but pthread_create specifies a function that takes only 1. You have to find a workaround so that you can only accept a single argument to your passwordLooper function yet still pass all 3 variables that you care about. There are a few ways this can be done:
Global variables (yuck, not thread safe, don't really do this)
malloc() some memory, memcpy() your arguments into it (or pointers to them), and pass that newly malloc()ed memory to pthread_create(). In your called function you'll have to parse the 3 variables back out of the void * (hacky, but works in theory)
Define a struct that contains your 3 arguments, malloc a copy of that struct, copy your variables into the newly malloced struct, and pass it as your 4th argument. This greatly simplifies parsing the values back out and is the general way to accomplish passing multiple variables as pthread_create's 4th argument