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-_";
167 unsigned int cnt = 0;
208 *(--ptr) =
'0' +
dig;
224 if (*(
grp + 1) != 0) {
249 return ch >=
' ' &&
ch <=
'~';
261 if (
name ==
nullptr || *
name ==
'\0') {
265 for (;
'\0' !=
name[
i];
i++) {
288 const char illegal_chars[] = {
'|',
'%',
'"',
',',
'*',
'<',
'>',
'\0'};
292 if (
name ==
nullptr || *
name ==
'\0') {
326 if (s ==
nullptr ||
'\0' == *s) {
330 for (;
'\0' != s[
i];
i++) {
348 if (s ==
nullptr || 1 >
n) {
352 for (;
i < (
n - 1);
i++) {
384 const char *
const *
second)
525 if (
'-' == *
str ||
'+' == *
str) {
591 if (
'-' == *
str ||
'+' == *
str) {
617 return (
'\0' == *
str &&
dot
633#ifdef FREECIV_MSWINDOWS
634#define HOMEVAR "APPDATA"
636#define HOMEVAR "HOME"
741#ifdef FREECIV_MSWINDOWS
794 log_error(
"For \"%s\" in path cannot expand '~'"
842 if (dir !=
nullptr) {
894#ifdef FREECIV_APPIMAGE
900 "%s/usr/share/freeciv",
903#define default_data_path DEFAULT_DATA_PATH
908 log_error(
_(
"\"%s\" is set but empty; using default \"%s\" "
909 "data directories instead."),
944 log_error(
_(
"\"%s\" is set but empty; using default \"%s\" "
945 "save directories instead."),
979#ifdef FREECIV_APPIMAGE
987 "%s/usr/share/freeciv/scenarios",
990#define default_scenario_path DEFAULT_SCENARIO_PATH
995 log_error(
_(
"\"%s\" is set but empty; using default \"%s\" "
996 "scenario directories instead."),
1027 if (dirs ==
nullptr) {
1040 log_verbose(
"Skipping non-existing data directory %s.",
1044 log_error(
_(
"Could not read data directory %s: %s."),
1096#ifndef DIR_SEPARATOR_IS_DEFAULT
1097 char fnbuf[filename !=
nullptr ?
strlen(filename) + 1 : 1];
1100 const char *
fnbuf = filename;
1103 if (dirs ==
nullptr) {
1123#ifndef DIR_SEPARATOR_IS_DEFAULT
1124 for (
i = 0; filename[
i] !=
'\0';
i++) {
1125 if (filename[
i] ==
'/') {
1143 log_verbose(
"Could not find readable file \"%s\" in data path.", filename);
1172 time_t a = (*ppa)->mtime;
1173 time_t b = (*ppb)->mtime;
1175 return ((a < b) ? 1 : (a > b) ? -1 : 0);
1184 return fc_strcoll((*ppa)->name, (*ppb)->name);
1209 if (dirs ==
nullptr) {
1248 file->
name = filename;
1288#ifdef FREECIV_MSWINDOWS
1405#ifdef FREECIV_ENABLE_NLS
1417 if (
lang !=
nullptr &&
lang[0] !=
'\0' &&
lang[1] !=
'\0') {
1436#ifdef FREECIV_ENABLE_NLS
1440 if (
lang !=
nullptr) {
1474#ifdef FREECIV_MSWINDOWS
1494 if (
lc->grouping[0] ==
'\0') {
1544#if (defined(ALWAYS_ROOT) || defined(__EMX__) || defined(__BEOS__))
1549 _(
"%s: Fatal error: you're trying to run me as superuser!\n"),
1550 (
argv0 ?
argv0 : fallback ? fallback :
"freeciv"));
1566 static const char *
const descriptions[] = {
1577 return descriptions[result];
1670#ifdef FREECIV_IPV6_SUPPORT
1676 char *
env =
getenv(
"FREECIV_MULTICAST_GROUP");
1681#ifdef FREECIV_IPV6_SUPPORT
1717 }
else if (filename[0] ==
'~' && filename[1] ==
'\0') {
1742 }
else if (filename[0] ==
'~' && filename[1] ==
'\0') {
1759 for (j =
strlen(filepath); j >= 0; j--) {
1761 return &filepath[j+1];
1782 char *path =
nullptr;
1798 }
else if (dir[0] !=
'\0' && dir[1] ==
':' && dir[2] ==
'\\') {
1810#ifdef FREECIV_MSWINDOWS
1833 if (
mkdir(path, mode) == -1
1840 if (
mkdir(path, mode) == -1
1871 log_debug(
"Create directory \"%s\"", filename);
1890#ifdef FREECIV_MSWINDOWS
1891 if (
strchr(filename,
':')) {
1895 if (filename[0] ==
'/') {
1925 char *ptr,
found =
'?';
1937 dest[
size-1] =
'\0';
1944 if (ptr !=
nullptr) {
1953 if (*
buf !=
nullptr) {
1975 hours = (t / (60 * 60)) % 24;
1976 days = t / (60 * 60 * 24);
2013 if (
n > 1 && array !=
nullptr) {
2016 for (
i = 0;
i <
n - 1;
i++) {
2019 array[j] = array[
i];
2045 if (
'\0' == *
test) {
2066 while (
'\0' != *
test) {
2070 if (
test ==
nullptr) {
2092 const char *start = (*
pattern + 1);
2096 if (
'\0' == **
test) {
2107 }
else if (*(*
pattern - 1) !=
'\\') {
2116 if (
'!' == *start) {
2126 for (; start < *
pattern; start++) {
2127 if (
'-' == *start ||
'!' == *start) {
2130 }
else if (start < *
pattern - 2 &&
'-' == *(start + 1)) {
2132 if (*start <=
testc &&
testc <= *(start + 2)) {
2136 }
else if (*start ==
testc) {
2162 return '\0' == *
test;
2171 if (
'\0' == *
test) {
2210 const char *
f = format;
2224 while (
'\0' != *
f) {
2256 if (
pseq->letter == *
f) {
2258 switch (
pseq->type) {
2263 pseq->bool_value ?
"TRUE" :
"FALSE");
2269 pseq->bool_value ?
_(
"TRUE") :
_(
"FALSE"));
2305 log_error(
"Error: unsupported sequence type: %d.",
pseq->type);
2372 log_error(
"Too many custom sequences. Maybe did you forget cf_end() "
2373 "at the end of the arguments?");
2391 '*',
'd',
'i',
'o',
'u',
'x',
'X',
'e',
'E',
'f',
2392 'F',
'g',
'G',
'a',
'A',
'c',
's',
'p',
'n',
'\0'
2399 format =
strchr(format,
'%');
2400 while (format !=
nullptr) {
2402 if (
'%' == *format) {
2406 const char *start = format;
2412 if (
'$' == *format) {
2414 sscanf(start,
"%d", &idx);
2419 while (
'\0' != *format
2435 if (
'*' != *format) {
2436 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 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)
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)
static void remove_trailing_char(char *s, char trailing) fc__attribute((nonnull(1)))
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
bool make_dir(const char *pathname, int mode)
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)