20#ifdef FREECIV_HAVE_SYS_TYPES_H
25#ifdef FREECIV_HAVE_DIRENT_H
47#ifdef FREECIV_MSWINDOWS
68#ifndef DEFAULT_DATA_PATH
69#define DEFAULT_DATA_PATH "." PATH_SEPARATOR \
70 "data" PATH_SEPARATOR \
71 FREECIV_STORAGE_DIR DIR_SEPARATOR DATASUBDIR
73#ifndef DEFAULT_SAVE_PATH
74#define DEFAULT_SAVE_PATH "." PATH_SEPARATOR \
75 FREECIV_STORAGE_DIR DIR_SEPARATOR "saves"
77#ifndef DEFAULT_SCENARIO_PATH
78#define DEFAULT_SCENARIO_PATH \
80 "data" DIR_SEPARATOR "scenarios" PATH_SEPARATOR \
81 FREECIV_STORAGE_DIR DATASUBDIR DIR_SEPARATOR "scenarios" PATH_SEPARATOR \
82 FREECIV_STORAGE_DIR DIR_SEPARATOR "scenarios"
86#ifndef FREECIV_DATA_PATH
87#define FREECIV_DATA_PATH "FREECIV_DATA_PATH"
89#ifndef FREECIV_SAVE_PATH
90#define FREECIV_SAVE_PATH "FREECIV_SAVE_PATH"
92#ifndef FREECIV_SCENARIO_PATH
93#define FREECIV_SCENARIO_PATH "FREECIV_SCENARIO_PATH"
104 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
164 unsigned int cnt = 0;
205 *(--ptr) =
'0' +
dig;
221 if (*(
grp + 1) != 0) {
246 return ch >=
' ' &&
ch <=
'~';
262 for (;
'\0' !=
name[
i];
i++) {
285 const char illegal_chars[] = {
'|',
'%',
'"',
',',
'*',
'<',
'>',
'\0'};
323 if (
NULL == s ||
'\0' == *s) {
327 for (;
'\0' != s[
i];
i++) {
344 if (
NULL == s || 1 >
n) {
348 for (;
i < (
n - 1);
i++) {
380 const char *
const *
second)
529 if (
'-' == *
str ||
'+' == *
str) {
598 if (
'-' == *
str ||
'+' == *
str) {
624 return (
'\0' == *
str &&
dot
640#ifdef FREECIV_MSWINDOWS
641#define HOMEVAR "APPDATA"
643#define HOMEVAR "HOME"
748#ifdef FREECIV_MSWINDOWS
801 log_error(
"For \"%s\" in path cannot expand '~'"
901#ifdef FREECIV_APPIMAGE
907 "%s/usr/share/freeciv",
910#define default_data_path DEFAULT_DATA_PATH
915 log_error(
_(
"\"%s\" is set but empty; using default \"%s\" "
916 "data directories instead."),
951 log_error(
_(
"\"%s\" is set but empty; using default \"%s\" "
952 "save directories instead."),
986#ifdef FREECIV_APPIMAGE
994 "%s/usr/share/freeciv/scenarios",
997#define default_scenario_path DEFAULT_SCENARIO_PATH
1002 log_error(
_(
"\"%s\" is set but empty; using default \"%s\" "
1003 "scenario directories instead."),
1047 log_verbose(
"Skipping non-existing data directory %s.",
1051 log_error(
_(
"Could not read data directory %s: %s."),
1103#ifndef DIR_SEPARATOR_IS_DEFAULT
1107 const char *
fnbuf = filename;
1130#ifndef DIR_SEPARATOR_IS_DEFAULT
1131 for (
i = 0; filename[
i] !=
'\0';
i++) {
1132 if (filename[
i] ==
'/') {
1150 log_verbose(
"Could not find readable file \"%s\" in data path.", filename);
1179 time_t a = (*ppa)->mtime;
1180 time_t b = (*ppb)->mtime;
1182 return ((a < b) ? 1 : (a > b) ? -1 : 0);
1191 return fc_strcoll((*ppa)->name, (*ppb)->name);
1255 file->
name = filename;
1295#ifdef FREECIV_MSWINDOWS
1412#ifdef FREECIV_ENABLE_NLS
1443#ifdef FREECIV_ENABLE_NLS
1481#ifdef FREECIV_MSWINDOWS
1501 if (
lc->grouping[0] ==
'\0') {
1551#if (defined(ALWAYS_ROOT) || defined(__EMX__) || defined(__BEOS__))
1556 _(
"%s: Fatal error: you're trying to run me as superuser!\n"),
1557 (
argv0 ?
argv0 : fallback ? fallback :
"freeciv"));
1573 static const char *
const descriptions[] = {
1584 return descriptions[result];
1677#ifdef FREECIV_IPV6_SUPPORT
1683 char *
env =
getenv(
"FREECIV_MULTICAST_GROUP");
1688#ifdef FREECIV_IPV6_SUPPORT
1724 }
else if (filename[0] ==
'~' && filename[1] ==
'\0') {
1749 }
else if (filename[0] ==
'~' && filename[1] ==
'\0') {
1766 for (j =
strlen(filepath); j >= 0; j--) {
1768 return &filepath[j+1];
1797 }
else if (dir[0] !=
'\0' && dir[1] ==
':' && dir[2] ==
'\\') {
1809#ifdef FREECIV_MSWINDOWS
1832 if (
mkdir(path, 0755) == -1
1839 if (
mkdir(path, 0755) == -1
1870 log_debug(
"Create directory \"%s\"", filename);
1889#ifdef FREECIV_MSWINDOWS
1890 if (
strchr(filename,
':')) {
1894 if (filename[0] ==
'/') {
1924 char *ptr,
found =
'?';
1936 dest[
size-1] =
'\0';
1974 hours = (t / (60 * 60)) % 24;
1975 days = t / (60 * 60 * 24);
2012 if (
n > 1 && array !=
NULL) {
2015 for (
i = 0;
i <
n - 1;
i++) {
2018 array[j] = array[
i];
2044 if (
'\0' == *
test) {
2065 while (
'\0' != *
test) {
2091 const char *start = (*
pattern + 1);
2095 if (
'\0' == **
test) {
2106 }
else if (*(*
pattern - 1) !=
'\\') {
2115 if (
'!' == *start) {
2125 for (; start < *
pattern; start++) {
2126 if (
'-' == *start ||
'!' == *start) {
2129 }
else if (start < *
pattern - 2 &&
'-' == *(start + 1)) {
2131 if (*start <=
testc &&
testc <= *(start + 2)) {
2135 }
else if (*start ==
testc) {
2161 return '\0' == *
test;
2170 if (
'\0' == *
test) {
2209 const char *
f = format;
2223 while (
'\0' != *
f) {
2255 if (
pseq->letter == *
f) {
2257 switch (
pseq->type) {
2262 pseq->bool_value ?
"TRUE" :
"FALSE");
2268 pseq->bool_value ?
_(
"TRUE") :
_(
"FALSE"));
2304 log_error(
"Error: unsupported sequence type: %d.",
pseq->type);
2371 log_error(
"Too many custom sequences. Maybe did you forget cf_end() "
2372 "at the end of the arguments?");
2390 '*',
'd',
'i',
'o',
'u',
'x',
'X',
'e',
'E',
'f',
2391 'F',
'g',
'G',
'a',
'A',
'c',
's',
'p',
'n',
'\0'
2398 format =
strchr(format,
'%');
2399 while (
NULL != format) {
2401 if (
'%' == *format) {
2405 const char *start = format;
2411 if (
'$' == *format) {
2413 sscanf(start,
"%d", &idx);
2418 while (
'\0' != *format
2434 if (
'*' != *format) {
2435 format =
strchr(format,
'%');
void astr_free(struct astring *astr)
void astr_set(struct astring *astr, const char *format,...)
void astr_clear(struct astring *astr)
void astr_add(struct astring *astr, const char *format,...)
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
DIR * fc_opendir(const char *dir_to_open)
char * internal_to_local_string_malloc(const char *text)
char * local_to_internal_string_buffer(const char *text, char *buf, size_t bufsz)
void fc_fprintf(FILE *stream, const char *format,...) fc__attribute((__format__(__printf__
const char * get_locale_dir(void)
void capitalization_opt_in(bool opt_in)
#define bindtextdomain(Package, Directory)
#define PL_(String1, String2, n)
#define textdomain(Domain)
#define fc_assert_ret(condition)
#define log_verbose(message,...)
#define fc_assert(condition)
#define fc_assert_ret_val(condition, val)
#define log_debug(message,...)
#define log_normal(message,...)
#define log_error(message,...)
#define fc_assert_ret_val_msg(condition, val, message,...)
int compare_strings(const void *first, const void *second)
static size_t extract_escapes(const char *format, char *escapes, size_t max_escapes)
void format_time_duration(time_t t, char *buf, int maxlen)
static bool wildcard_asterisk_fit(const char *pattern, const char *test)
int compare_strings_ptrs(const void *first, const void *second)
char * user_username(char *buf, size_t bufsz)
int fc_snprintcf(char *buf, size_t buf_len, const char *format,...)
static char * grouping_sep
enum fc_tristate fc_tristate_and(enum fc_tristate one, enum fc_tristate two)
void dont_run_as_root(const char *argv0, const char *fallback)
bool wildcard_fit_string(const char *pattern, const char *test)
bool check_strlen(const char *str, size_t len, const char *errmsg)
const char * fileinfoname(const struct strvec *dirs, const char *filename)
static bool compare_fileinfo_name(const struct fileinfo *pa, const struct fileinfo *pb)
char * user_home_dir(void)
void remove_trailing_spaces(char *s)
void free_user_home_dir(void)
int fc_vsnprintcf(char *buf, size_t buf_len, const char *format, const struct cf_sequence *sequences, size_t sequences_num)
static char * storage_dir_freeciv
bool str_to_int(const char *str, int *pint)
#define default_data_path
bool str_to_float(const char *str, float *pfloat)
const char * m_pre_description(enum m_pre_result result)
static struct strvec * data_dir_names
#define FREECIV_SCENARIO_PATH
static const char base64url[]
struct strvec * fileinfolist(const struct strvec *dirs, const char *suffix)
char * skip_leading_spaces(char *s)
bool str_to_uint(const char *str, unsigned int *pint)
bool make_dir(const char *pathname)
void free_data_dir_names(void)
enum m_pre_result match_prefix_full(m_pre_accessor_fn_t accessor_fn, size_t n_names, size_t max_len_name, m_pre_strncmp_fn_t cmp_fn, m_strlen_fn_t len_fn, const char *prefix, int *ind_result, int *matches, int max_matches, int *pnum_matches)
const struct strvec * get_scenario_dirs(void)
size_t loud_strlcpy(char *buffer, const char *str, size_t len, const char *errmsg)
char * interpret_tilde_alloc(const char *filename)
#define FREECIV_SAVE_PATH
bool make_dir_for_file(char *filename)
static void fileinfo_destroy(struct fileinfo *pfile)
void interpret_tilde(char *buf, size_t buf_size, const char *filename)
static struct astring realfile
static void remove_trailing_char(char *s, char trailing)
int compare_strings_strvec(const char *const *first, const char *const *second)
bool is_base64url(const char *s)
void free_multicast_group(void)
static char * home_dir_user
void free_fileinfo_data(void)
static bool is_ascii(char ch)
char * end_of_strn(char *str, int *nleft)
bool path_is_absolute(const char *filename)
static bool wildcard_range_fit(const char **pattern, const char **test)
static struct strvec * scenario_dir_names
static int compare_file_mtime_ptrs(const struct fileinfo *const *ppa, const struct fileinfo *const *ppb)
bool formats_match(const char *format1, const char *format2)
const char * int_to_text(unsigned int number)
char scanin(const char **buf, char *delimiters, char *dest, int size)
static int compare_file_name_ptrs(const struct fileinfo *const *ppa, const struct fileinfo *const *ppb)
const struct strvec * get_save_dirs(void)
static char * expand_dir(char *tok_in, bool ok_to_free)
void remove_leading_spaces(char *s)
char * skip_to_basename(char *filepath)
#define FREECIV_DATA_PATH
#define default_scenario_path
void array_shuffle(int *array, int n)
enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn, size_t n_names, size_t max_len_name, m_pre_strncmp_fn_t cmp_fn, m_strlen_fn_t len_fn, const char *prefix, int *ind_result)
bool is_ascii_name(const char *name)
#define DEFAULT_SAVE_PATH
enum fc_tristate fc_tristate_or(enum fc_tristate one, enum fc_tristate two)
static struct strvec * base_get_dirs(const char *dir_list)
const char * setup_langname(void)
void randomize_base64url_string(char *s, size_t n)
char * get_multicast_group(bool ipv6_preferred)
void free_freeciv_storage_dir(void)
bool is_safe_filename(const char *name)
void remove_leading_trailing_spaces(char *s)
const char * big_int_to_text(unsigned int mantissa, unsigned int exponent)
const struct strvec * get_data_dirs(void)
char * freeciv_storage_dir(void)
void switch_lang(const char *lang)
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
static struct strvec * save_dir_names
int(* m_pre_strncmp_fn_t)(const char *, const char *, size_t n)
#define DIR_SEPARATOR_CHAR
size_t() m_strlen_fn_t(const char *str)
#define PARENT_DIR_OPERATOR
const char *(* m_pre_accessor_fn_t)(int)
void strvec_destroy(struct strvec *psv)
void strvec_sort(struct strvec *psv, int(*sort_func)(const char *const *, const char *const *))
void strvec_append(struct strvec *psv, const char *string)
struct strvec * strvec_new(void)
void strvec_remove_duplicate(struct strvec *psv, int(*cmp_func)(const char *, const char *))
#define strvec_iterate(psv, str)
#define strvec_iterate_end
int fc_snprintf(char *str, size_t n, const char *format,...)
size_t fc_strlcpy(char *dest, const char *src, size_t n)
const char * fc_strerror(fc_errno err)
int cat_snprintf(char *str, size_t n, const char *format,...)
fc_errno fc_get_errno(void)
int fc_strcoll(const char *str0, const char *str1)
int fc_stat(const char *filename, struct stat *buf)