/* * The program begins here. * * Arguments: * argc - count of arguments * argv - array of arguments * envp - array of enviroment variables */ int main(int argc, char* argv[], char* envp[]) { /* * initialize configuration (if config file isn't set) */ config.run_script_on_finish = 0; /* * path to home dir "/home/$USER", read from $HOME enviroment variable */ const char* home_dir = getenv("HOME"); /* variables used with getopt() */ extern char *optarg; extern int optind, opterr; int argument; int i_option_enabled = 0; /* * read arguments in while loop and set the neccessary variables */ while( (argument = getopt(argc, argv, "c:dhin:uV:v")) != -1 ) { LOG(DEBUG, "argument='%c', optarg='%s'", argument, optarg); switch(argument) { case 'c': LOG(INFO, "Will use custom config file"); use_custom_config_file = 1; custom_config_file_location = optarg; break; case 'd': LOG(WARN, "DRY RUN ENABLED!!!"); dry_run = 1; break; case 'h': help(); break; case 'i': LOG(INFO, "-i option enabled"); i_option_enabled = 1; break; case 'n': override_config_threads_num = atoi(optarg); if (override_config_threads_num <= 0) { die("Invalid number of threads (-n parameter)!"); } break; case 'u': disable_color_output(); LOG(INFO, "Disabling colored output"); break; case 'V': quality = optarg; break; case 'v': enable_verbose(); break; default: /* '?' */ die("Wrong arguments or argument requires an option which was not supplied"); } } config_file_actions(home_dir); size = INITIAL_SIZE; /* * allocate initial memory for array of input and output filenames (paths) */ input_files = malloc(sizeof(char*) * size); output_filenames = malloc(sizeof(char*) * size); if ( input_files == NULL || output_filenames == NULL) { die("Memory error!"); } /* * initialize input and output filenames to NULL. not sure if this is really neccessary */ int i; for (i = 0; i < size; i++) { input_files[i] = NULL; output_filenames[i] = NULL; } if (i_option_enabled) { filenames_input(argc, argv, optind); } else { folder_input(argc, argv, optind); } /* * array which stores the threads which will run. */ pthread_t threads[config.threads]; LOG(INFO, "Starting %d threads", config.threads); /* * this is only used for logging, so that each call to decode() knows which number it is. * a single variable for this cannot be used because it is passed by reference (pointer), * that's how the pthread_create works. */ int* thread_indexes[config.threads]; for (i = 0; i < config.threads; i++) { thread_indexes[i] = malloc(sizeof(int)); if (thread_indexes[i] == NULL) die("Memory error!"); *thread_indexes[i] = i; /* * create a new thread (call do_work() in a new thread) */ pthread_create(&threads[i], NULL, &do_work, (void *) thread_indexes[i]); } /* * join the just created threads (wait for them to finish! */ for (i = 0; i < config.threads; i++) { pthread_join(threads[i], NULL); free(thread_indexes[i]); } /* * if the config file has the run_script_on_finish set to a path to script, execute it. * TODO explain how this script works */ if (config.run_script_on_finish) { LOG(INFO, "Starting script: %s", config.script_path); for (i = 0; i < files_count; i++) { char* script_command = print_to_string("%s \"%s\" \"%s\"", config.script_path, input_files[i], output_filenames[i]); LOG(INFO, "Running post script on file: %s", output_filenames[i]); LOG(DEBUG, "Running post script: %s", script_command); FILE* fp = popen(script_command, "r"); if (fp == NULL) die("Unable to open script"); free(script_command); pclose(fp); } } /** FREE MEMORY **/ for (i = 0; i < size; i++) { if (input_files[i] != NULL) { free(input_files[i]); } if (output_filenames[i] != NULL) { free(output_filenames[i]); } } free(input_files); free(output_filenames); free_config(config); LOG(INFO, "Program finished successfully!"); return 0; }
/* parse_args() * * parses command line arguments * * returns pointer to options structure on success, NULL on failure */ static int parse_args(int argc, char** argv, struct options * opts) { int i = 0, ret = 0, option_index = 0; const char * cur_option = NULL; static struct option long_opts[] = { {"help",0,0,0}, {"version",0,0,0}, {"verbose",0,0,0}, {"dereference",0,0,0}, {0,0,0,0} }; while((ret = getopt_long_only(argc, argv, "VL", long_opts, &option_index)) != -1) { switch (ret) { case 0: cur_option = long_opts[option_index].name; if(strcmp("help", cur_option) == 0) { usage(argc, argv); exit(0); } else if(strcmp("verbose", cur_option) == 0) { enable_verbose(opts); } else if(strcmp("dereference", cur_option) == 0) { enable_dereference(opts); } else if (strcmp("version", cur_option) == 0) { printf("%s\n", PVFS2_VERSION); exit(0); } else { usage(argc, argv); exit(0); } break; case 'V': /* --verbose */ enable_verbose(opts); break; case 'L': /* --dereference */ enable_dereference(opts); break; case '?': usage(argc, argv); exit(0); default: usage(argc, argv); exit(0); } } /* We processed all arguments, so let's figure out how many files the user * wants to stat, and allocate enough space to hold them, barring they haven't * exceeded the limit. */ opts->nNumFiles = argc - optind; /* Validation to make sure we have at least one file to check */ if(opts->nNumFiles <= 0) { fprintf(stderr, "No filename(s)\n"); usage(argc, argv); exit(0); } /* Validation to make sure we haven't exceeded */ if(opts->nNumFiles > MAX_NUM_FILES) { fprintf(stderr, "Filename limit of [%d] exceeded. [%d] file entered\n", MAX_NUM_FILES, opts->nNumFiles); usage(argc, argv); exit(0); } /* Allocate memory to hold the filenames */ opts->pszFiles = (char **)calloc(opts->nNumFiles, sizeof(char *)); if(opts->pszFiles == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(0); } /* Loop through arguments and capture the file names */ for(i = optind; i < argc; i++) { opts->pszFiles[i-optind] = argv[i]; } return(0); }