Example #1
0
/**
 * Search for config file.
 *
 * @return the relative path to config file
 */
static const char* find_conf_file(void)
{
# define CONF_FILE_NAME "rhashrc"
	struct rsh_stat_struct st;
	char *dir1, *path;

#ifndef _WIN32 /* Linux/Unix part */
	/* first check for $HOME/.rhashrc file */
	if( (dir1 = getenv("HOME")) ) {
		path = make_path(dir1, ".rhashrc");
		if(rsh_stat(path, &st) >= 0) {
			rsh_vector_add_ptr(opt.mem, path);
			return (conf_opt.config_file = path);
		}
		free(path);
	}
	/* then check for global config */
	if(rsh_stat( (path = "/etc/" CONF_FILE_NAME), &st) >= 0) {
		return (conf_opt.config_file = path);
	}

#else /* _WIN32 */

	/* first check for the %APPDATA%\RHash\rhashrc config */
	if( (dir1 = getenv("APPDATA")) ) {
		dir1 = make_path(dir1, "RHash");
		rsh_vector_add_ptr(opt.mem, path = make_path(dir1, CONF_FILE_NAME));
		free(dir1);
		if(rsh_stat(path, &st) >= 0) {
			return (conf_opt.config_file = path);
		}
	}

	/* then check for %HOMEDRIVE%%HOMEPATH%\rhashrc */
	/* note that %USERPROFILE% is generally not a user home dir */
	if( (dir1 = getenv("HOMEDRIVE")) && (path = getenv("HOMEPATH"))) {
		dir1 = make_path(dir1, path);
		rsh_vector_add_ptr(opt.mem, path = make_path(dir1, CONF_FILE_NAME));
		free(dir1);
		if(rsh_stat(path, &st) >= 0) {
			return (conf_opt.config_file = path);
		}
	}
#endif /* _WIN32 */

	return (conf_opt.config_file = NULL); /* config file not found */
}
Example #2
0
/**
 * Expand wildcards in the given filepath and store results into vector.
 * If no wildcards are found then just the filepath is stored.
 * Note: only wildcards in the last filename of the path are expanded.
 *
 * @param vect the vector to receive wide-strings with file paths
 * @param filepath the filepath to process
 */
void expand_wildcards(vector_t* vect, wchar_t* filepath)
{
	int added = 0;
	size_t len = wcslen(filepath);
	size_t index = wcscspn(filepath, L"*?");

	/* if a wildcard has been found without a directory separator after it */
	if(index < len && wcscspn(filepath + index, L"/\\") >= (len - index))
	{
		wchar_t* parent;
		WIN32_FIND_DATAW d;
		HANDLE h;

		/* find directory separator */
		for(; index > 0 && !IS_PATH_SEPARATOR(filepath[index]); index--);
		parent = (IS_PATH_SEPARATOR(filepath[index]) ? filepath : 0);

		h = FindFirstFileW(filepath, &d);
		if(INVALID_HANDLE_VALUE != h) {
			do {
				wchar_t* wpath;
				char* cstr;
				int failed;
				if((0 == wcscmp(d.cFileName, L".")) || (0 == wcscmp(d.cFileName, L".."))) continue;
				if(NULL == (wpath = make_pathw(parent, index + 1, d.cFileName))) continue;
				cstr = wchar_to_cstr(wpath, WIN_DEFAULT_ENCODING, &failed);
				/* note: just quietly skip unconvertible file names */
				if(!cstr || failed) {
					free(cstr);
					free(wpath);
					continue;
				}
				rsh_vector_add_ptr(vect, cstr);
				added++;
			} while(FindNextFileW(h, &d));
			FindClose(h);
		}
	}

	if(added == 0) {
		wchar_t* wpath = make_pathw(0, 0, filepath);
		char* cstr = w2c(wpath);
		if(cstr) rsh_vector_add_ptr(vect, cstr);
	}
}
Example #3
0
/**
 * Find long option info, by it's name and retrieve its parameter if required.
 * Error is reported for unknown options.
 *
 * @param option structure to receive the parsed option info
 * @param parg pointer to a command line argument
 */
static void parse_long_option(parsed_option_t* option, rsh_tchar ***parg)
{
	size_t length;
	rsh_tchar* eq_sign;
	cmdline_opt_t *t;
	char* name;

#ifdef _WIN32
	rsh_tchar* wname = **parg; /* "--<option name>" */
	int fail = 0;
	assert((**parg)[0] == L'-' && (**parg)[1] == L'-');

	/* search for the '=' sign */
	length = ((eq_sign = wcschr(wname, L'=')) ? (size_t)(eq_sign - wname) : wcslen(wname));
	option->name = name = (char*)rsh_malloc(length + 1);
	rsh_vector_add_ptr(opt.mem, name);
	if(length < 30) {
		size_t i = 0;
		for(; i < length; i++) {
			if(((unsigned)wname[i]) <= 128) name[i] = (char)wname[i];
			else {
				fail = 1;
				break;
			}
		}
		name[i] = '\0';
		
		name += 2; /* skip  "--" */
		length -= 2;
	} else fail = 1;

	if(fail) fail_on_unknow_option(w2c(**parg));
#else
	option->name = **parg;
	name =  **parg + 2; /* skip "--" */
	length = ((eq_sign = strchr(name, '=')) ? (size_t)(eq_sign - name) : strlen(name));
	name[length] = '\0';
#endif
	/* search for the option by its name */
	for(t = cmdline_opt; t->type && (strncmp(name, t->long_name, length) != 0 ||
		strlen(t->long_name) != length); t++) {
	}
	if(!t->type) {
		fail_on_unknow_option(option->name); /* report error and exit */
	}

	option->o = t; /* store the option found */
	if(is_param_required(t->type)) {
		/* store parameter without a code page conversion */
		option->parameter = (eq_sign ? eq_sign + 1 : *(++(*parg)));
	}
}
Example #4
0
/**
 * Process given command line option
 *
 * @param opts the structure to store results of option processing
 * @param option option to process
 */
static void apply_option(options_t *opts, parsed_option_t* option)
{
	cmdline_opt_t* o = option->o;
	unsigned short option_type = o->type;
	char* value = NULL;
	
	/* check if option requires a parameter */
	if(is_param_required(option_type)) {
		if(!option->parameter) {
			log_error(_("argument is required for option %s\n"), option->name);
			rsh_exit(2);
		}
#ifdef _WIN32
		/* convert from UTF-16 if not a filepath */
		if(option_type != F_OPTH) {
			value = w2c((wchar_t*)option->parameter);
			rsh_vector_add_ptr(opt.mem, value);
		} else
#endif
		{
			value = (char*)option->parameter;
		}
	}

	/* process option, choosing the method by type */
	switch(option_type) {
	case F_UFLG:
	case F_UENC:
		*(unsigned*)((char*)opts + ((char*)o->ptr - (char*)&opt)) |= o->param;
		break;
	case F_CSTR:
	case F_OPTH:
		/* save the option parameter */
		*(char**)((char*)opts + ((char*)o->ptr - (char*)&opt)) = value;
		break;
	case F_PFNC:
		/* call option parameter handler */
		( ( void(*)(options_t *, char*, unsigned) )o->ptr )(opts, value, o->param);
		break;
	case F_VFNC:
		( ( void(*)(options_t *) )o->ptr )(opts); /* call option handler */
		break;
	case F_PRNT:
		log_msg("%s", (char*)o->ptr);
		rsh_exit(0);
		break;
	default:
		assert(0); /* impossible option type */
	}
}
Example #5
0
/**
 * Convert the given string to lower-case then put it into
 * the specified array of 'file masks'.
 *
 * @param arr array of file masks
 * @param mask a string to add
 */
static void file_mask_add(file_mask_array* vect, const char* mask)
{
	rsh_vector_add_ptr(vect, str_tolower(mask));
}
Example #6
0
/**
 * Parse command line options.
 *
 * @param argv program arguments
 */
void read_options(int argc, char *argv[])
{
	struct parsed_cmd_line_t cmd_line;
#ifdef _WIN32
	int i;
	vector_t *expanded_cnames;
#endif

	memset(&opt, 0, sizeof(opt));
	opt.mem = rsh_vector_new_simple();
	opt.find_max_depth = -1;

	/* initialize cmd_line */
	memset(&cmd_line, 0, sizeof(cmd_line));
	rsh_blocks_vector_init(&cmd_line.options);
	cmd_line.argv = argv;
	cmd_line.argc = argc;

	/* parse command line and apply encoding options */
	parse_cmdline_options(&cmd_line);
	read_config();
	
#ifdef _WIN32
	/* set default encoding if no encoding options were specified, */
	/* this should be done here, even if config file was not found. */
	if( (opt.flags & OPT_ENCODING) == 0 ) opt.flags |= OPT_UTF8;
#endif

	/* note: encoding and -o/-l options are already applied */
	IF_WINDOWS(setup_console());
	setup_output(); /* setup program output */

	apply_cmdline_options(&cmd_line); /* process the rest of command options */

	/* options were processed, so we don't need them anymore */
	rsh_blocks_vector_destroy(&cmd_line.options);
	
#ifdef _WIN32
	expanded_cnames = rsh_vector_new_simple();

	/* convert paths to internal encoding and expand wildcards. */
	for(i = 0; i < cmd_line.n_files; i++) {
		wchar_t* path = cmd_line.files[i];
		wchar_t* p = wcschr(path, L'\0') - 1;

		/* strip trailing '\','/' symbols (if not preceded by ':') */
		for(; p > path && IS_PATH_SEPARATOR_W(*p) && p[-1] != L':'; p--) *p = 0;
		expand_wildcards(expanded_cnames, path);
	}

	opt.cmd_vec = expanded_cnames;
	opt.files = (char**)expanded_cnames->array;
	opt.n_files = (int)expanded_cnames->size;
	free(cmd_line.files);
	LocalFree(cmd_line.warg);
#else
	opt.files = cmd_line.files;
	opt.n_files = cmd_line.n_files;
	rsh_vector_add_ptr(opt.mem, opt.files);
#endif

	make_final_options_checks();

	set_default_sums_flags(argv[0]); /* detect default hashes from program name */
}
Example #7
0
/**
 * Parse config file of the program.
 *
 * @return 0 on success, -1 on fail
 */
static int read_config(void)
{
#define LINE_BUF_SIZE 2048
	char buf[LINE_BUF_SIZE];
	FILE* fd;
	parsed_option_t option;
	int res;

	/* initialize conf_opt and opt structures */
	memset(&conf_opt, 0, sizeof(opt));
	conf_opt.find_max_depth = -1;

	if(!find_conf_file()) return 0;

	fd = fopen(conf_opt.config_file, "r");
	if(!fd) return -1;

	while(fgets(buf, LINE_BUF_SIZE, fd)) {
		size_t index;
		cmdline_opt_t* t;
		char* line = str_trim(buf);
		char  *name, *value;

		if(*line == 0 || IS_COMMENT(*line)) continue;

		/* search for '=' */
		index = strcspn(line, "=");
		if(line[index] == 0) {
			log_warning(_("%s: can't parse line \"%s\"\n"), conf_opt.config_file, line);
			continue;
		}
		line[index] = 0;
		name = str_trim(line);

		for(t = cmdline_opt; t->type; t++) {
			if(strcmp(name, t->long_name) == 0) {
				break;
			}
		}

		if(!t->type) {
			log_warning(_("%s: unknown option \"%s\"\n"), conf_opt.config_file, line);
			continue;
		}

		value = str_trim(line + index + 1);

		/* process a long option */
		if(is_param_required(t->type)) {
			rsh_vector_add_ptr(opt.mem, (value = rsh_strdup(value)));;
		} else {
			/* possible boolean values for a config file variable */
			static const char* strings[] = {"1", "on", "yes", 0};
			const char** cmp;
			for(cmp = strings; *cmp && strcmp(value, *cmp); cmp++);
			if(*cmp == 0) continue;
		}

		option.name = name;
		option.parameter = value;
		option.o = t;
		apply_option(&conf_opt, &option);
	}
	res = fclose(fd);

#ifdef _WIN32
	if( (opt.flags & OPT_ENCODING) == 0 ) opt.flags |= (conf_opt.flags & OPT_ENCODING);
#endif
	return (res == 0 ? 0 : -1);
}