Support VERSION_REVTYPE git builds on cleanup_checkout.sh
[freeciv.git] / utility / shared.c
blob352457ba6ec8c5fd5f82152e5fd083705dbcfcc2
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include "fc_prehdrs.h"
20 #ifdef FREECIV_HAVE_SYS_TYPES_H
21 /* Under Mac OS X sys/types.h must be included before dirent.h */
22 #include <sys/types.h>
23 #endif
25 #include <dirent.h>
26 #include <errno.h>
27 #include <limits.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
34 #ifdef HAVE_LOCALE_H
35 #include <locale.h>
36 #endif
38 #ifdef HAVE_PWD_H
39 #include <pwd.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #ifdef WIN32_NATIVE
45 #include <windows.h>
46 #include <lmcons.h> /* UNLEN */
47 #include <shlobj.h>
48 #ifdef HAVE_DIRECT_H
49 #include <direct.h>
50 #endif /* HAVE_DIRECT_H */
51 #endif /* WIN32_NATIVE */
53 /* utility */
54 #include "astring.h"
55 #include "fciconv.h"
56 #include "fcintl.h"
57 #include "mem.h"
58 #include "rand.h"
59 #include "string_vector.h"
61 #include "shared.h"
63 /* If no default data path is defined use the default default one */
64 #ifndef DEFAULT_DATA_PATH
65 #define DEFAULT_DATA_PATH "." PATH_SEPARATOR \
66 "data" PATH_SEPARATOR \
67 "~" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR DATASUBDIR
68 #endif
69 #ifndef DEFAULT_SAVE_PATH
70 #define DEFAULT_SAVE_PATH "." PATH_SEPARATOR \
71 "~" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR "saves"
72 #endif
73 #ifndef DEFAULT_SCENARIO_PATH
74 #define DEFAULT_SCENARIO_PATH \
75 "." PATH_SEPARATOR \
76 "data" DIR_SEPARATOR "scenarios" PATH_SEPARATOR \
77 "~" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR DATASUBDIR DIR_SEPARATOR "scenarios" PATH_SEPARATOR \
78 "~" DIR_SEPARATOR ".freeciv" DIR_SEPARATOR "scenarios"
79 #endif /* DEFAULT_SCENARIO_PATH */
81 /* environment */
82 #ifndef FREECIV_PATH
83 #define FREECIV_PATH "FREECIV_PATH"
84 #endif
85 #ifndef FREECIV_DATA_PATH
86 #define FREECIV_DATA_PATH "FREECIV_DATA_PATH"
87 #endif
88 #ifndef FREECIV_SAVE_PATH
89 #define FREECIV_SAVE_PATH "FREECIV_SAVE_PATH"
90 #endif
91 #ifndef FREECIV_SCENARIO_PATH
92 #define FREECIV_SCENARIO_PATH "FREECIV_SCENARIO_PATH"
93 #endif
95 /* Both of these are stored in the local encoding. The grouping_sep must
96 * be converted to the internal encoding when it's used. */
97 static char *grouping = NULL;
98 static char *grouping_sep = NULL;
100 /* As well as base64 functions, this string is used for checking for
101 * 'safe' filenames, so should not contain / \ . */
102 static const char base64url[] =
103 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
105 static struct strvec *data_dir_names = NULL;
106 static struct strvec *save_dir_names = NULL;
107 static struct strvec *scenario_dir_names = NULL;
109 static char *mc_group = NULL;
110 static char *home_dir = NULL;
112 static bool depr_freeciv_path_warned = FALSE;
114 static struct astring realfile = ASTRING_INIT;
116 static int compare_file_mtime_ptrs(const struct fileinfo *const *ppa,
117 const struct fileinfo *const *ppb);
120 /***************************************************************************
121 An AND function for fc_tristate.
122 ***************************************************************************/
123 enum fc_tristate fc_tristate_and(enum fc_tristate one, enum fc_tristate two)
125 if (TRI_NO == one || TRI_NO == two) {
126 return TRI_NO;
129 if (TRI_MAYBE == one || TRI_MAYBE == two) {
130 return TRI_MAYBE;
133 return TRI_YES;
136 /***************************************************************
137 Take a string containing multiple lines and create a copy where
138 each line is padded to the length of the longest line and centered.
139 We do not cope with tabs etc. Note that we're assuming that the
140 last line does _not_ end with a newline. The caller should
141 free() the result.
143 FIXME: This is only used in the Xaw client, and so probably does
144 not belong in common.
145 ***************************************************************/
146 char *create_centered_string(const char *s)
148 /* Points to the part of the source that we're looking at. */
149 const char *cp;
151 /* Points to the beginning of the line in the source that we're
152 * looking at. */
153 const char *cp0;
155 /* Points to the result. */
156 char *r;
158 /* Points to the part of the result that we're filling in right
159 now. */
160 char *rn;
162 int i;
164 int maxlen = 0;
165 int curlen = 0;
166 int nlines = 1;
168 for(cp=s; *cp != '\0'; cp++) {
169 if(*cp!='\n')
170 curlen++;
171 else {
172 if(maxlen<curlen)
173 maxlen=curlen;
174 curlen=0;
175 nlines++;
178 if(maxlen<curlen)
179 maxlen=curlen;
181 r=rn=fc_malloc(nlines*(maxlen+1));
183 curlen=0;
184 for(cp0=cp=s; *cp != '\0'; cp++) {
185 if(*cp!='\n')
186 curlen++;
187 else {
188 for(i=0; i<(maxlen-curlen)/2; i++)
189 *rn++=' ';
190 memcpy(rn, cp0, curlen);
191 rn+=curlen;
192 *rn++='\n';
193 curlen=0;
194 cp0=cp+1;
197 for(i=0; i<(maxlen-curlen)/2; i++)
198 *rn++=' ';
199 strcpy(rn, cp0);
201 return r;
204 /***************************************************************
205 Returns a statically allocated string containing a nicely-formatted
206 version of the given number according to the user's locale. (Only
207 works for numbers >= zero.) The number is given in scientific notation
208 as mantissa * 10^exponent.
209 ***************************************************************/
210 const char *big_int_to_text(unsigned int mantissa, unsigned int exponent)
212 static char buf[64]; /* Note that we'll be filling this in right to left. */
213 char *grp = grouping;
214 char *ptr;
215 unsigned int cnt = 0;
216 char sep[64];
217 size_t seplen;
219 /* We have to convert the encoding here (rather than when the locale
220 * is initialized) because it can't be done before the charsets are
221 * initialized. */
222 local_to_internal_string_buffer(grouping_sep, sep, sizeof(sep));
223 seplen = strlen(sep);
225 #if 0 /* Not needed while the values are unsigned. */
226 fc_assert_ret_val(0 <= mantissa, NULL);
227 fc_assert_ret_val(0 <= exponent, NULL);
228 #endif
230 if (mantissa == 0) {
231 return "0";
234 /* We fill the string in backwards, starting from the right. So the first
235 * thing we do is terminate it. */
236 ptr = &buf[sizeof(buf)];
237 *(--ptr) = '\0';
239 while (mantissa != 0 && exponent >= 0) {
240 int dig;
242 if (ptr <= buf + seplen) {
243 /* Avoid a buffer overflow. */
244 fc_assert_ret_val(ptr > buf + seplen, NULL);
245 return ptr;
248 /* Add on another character. */
249 if (exponent > 0) {
250 dig = 0;
251 exponent--;
252 } else {
253 dig = mantissa % 10;
254 mantissa /= 10;
256 *(--ptr) = '0' + dig;
258 cnt++;
259 if (mantissa != 0 && cnt == *grp) {
260 /* Reached count of digits in group: insert separator and reset count. */
261 cnt = 0;
262 if (*grp == CHAR_MAX) {
263 /* This test is unlikely to be necessary since we would need at
264 least 421-bit ints to break the 127 digit barrier, but why not. */
265 break;
267 ptr -= seplen;
268 fc_assert_ret_val(ptr >= buf, NULL);
269 memcpy(ptr, sep, seplen);
270 if (*(grp + 1) != 0) {
271 /* Zero means to repeat the present group-size indefinitely. */
272 grp++;
277 return ptr;
281 /****************************************************************************
282 Return a prettily formatted string containing the given number.
283 ****************************************************************************/
284 const char *int_to_text(unsigned int number)
286 return big_int_to_text(number, 0);
289 /****************************************************************************
290 Check whether or not the given char is a valid ascii character. The
291 character can be in any charset so long as it is a superset of ascii.
292 ****************************************************************************/
293 static bool is_ascii(char ch)
295 /* this works with both signed and unsigned char's. */
296 return ch >= ' ' && ch <= '~';
299 /****************************************************************************
300 Check if the name is safe security-wise. This is intended to be used to
301 make sure an untrusted filename is safe to be used.
302 ****************************************************************************/
303 bool is_safe_filename(const char *name)
305 int i = 0;
307 /* must not be NULL or empty */
308 if (!name || *name == '\0') {
309 return FALSE;
312 for (; '\0' != name[i]; i++) {
313 if ('.' != name[i] && NULL == strchr(base64url, name[i])) {
314 return FALSE;
318 /* we don't allow the filename to ascend directories */
319 if (strstr(name, PARENT_DIR_OPERATOR)) {
320 return FALSE;
323 /* Otherwise, it is okay... */
324 return TRUE;
327 /***************************************************************
328 This is used in sundry places to make sure that names of cities,
329 players etc. do not contain yucky characters of various sorts.
330 Returns TRUE iff the name is acceptable.
331 FIXME: Not internationalised.
332 ***************************************************************/
333 bool is_ascii_name(const char *name)
335 const char illegal_chars[] = {'|', '%', '"', ',', '*', '<', '>', '\0'};
336 int i, j;
338 /* must not be NULL or empty */
339 if (!name || *name == '\0') {
340 return FALSE;
343 /* must begin and end with some non-space character */
344 if ((*name == ' ') || (*(strchr(name, '\0') - 1) == ' ')) {
345 return FALSE;
348 /* must be composed entirely of printable ascii characters,
349 * and no illegal characters which can break ranking scripts. */
350 for (i = 0; name[i]; i++) {
351 if (!is_ascii(name[i])) {
352 return FALSE;
354 for (j = 0; illegal_chars[j]; j++) {
355 if (name[i] == illegal_chars[j]) {
356 return FALSE;
361 /* otherwise, it's okay... */
362 return TRUE;
365 /*************************************************************************
366 Check for valid base64url.
367 *************************************************************************/
368 bool is_base64url(const char *s)
370 size_t i = 0;
372 /* must not be NULL or empty */
373 if (NULL == s || '\0' == *s) {
374 return FALSE;
377 for (; '\0' != s[i]; i++) {
378 if (NULL == strchr(base64url, s[i])) {
379 return FALSE;
382 return TRUE;
385 /*************************************************************************
386 generate a random string meeting criteria such as is_ascii_name(),
387 is_base64url(), and is_safe_filename().
388 *************************************************************************/
389 void randomize_base64url_string(char *s, size_t n)
391 size_t i = 0;
393 /* must not be NULL or too short */
394 if (NULL == s || 1 > n) {
395 return;
398 for (; i < (n - 1); i++) {
399 s[i] = base64url[fc_rand(sizeof(base64url) - 1)];
401 s[i] = '\0';
404 /**************************************************************************
405 Compares two strings, in the collating order of the current locale,
406 given pointers to the two strings (i.e., given "char *"s).
407 Case-sensitive. Designed to be called from qsort().
408 **************************************************************************/
409 int compare_strings(const void *first, const void *second)
411 return fc_strcoll((const char *) first, (const char *) second);
414 /**************************************************************************
415 Compares two strings, in the collating order of the current locale,
416 given pointers to the two string pointers (i.e., given "char **"s).
417 Case-sensitive. Designed to be called from qsort().
418 **************************************************************************/
419 int compare_strings_ptrs(const void *first, const void *second)
421 return fc_strcoll(*((const char **) first), *((const char **) second));
424 /**************************************************************************
425 Compares two strings, in the collating order of the current locale,
426 given pointers to the two string pointers. Case-sensitive.
427 Designed to be called from strvec_sort().
428 **************************************************************************/
429 int compare_strings_strvec(const char *const *first,
430 const char *const *second)
432 return fc_strcoll(*first, *second);
435 /***************************************************************************
436 Returns 's' incremented to first non-space character.
437 ***************************************************************************/
438 char *skip_leading_spaces(char *s)
440 fc_assert_ret_val(NULL != s, NULL);
441 while(*s != '\0' && fc_isspace(*s)) {
442 s++;
444 return s;
447 /***************************************************************************
448 Removes leading spaces in string pointed to by 's'.
449 Note 's' must point to writeable memory!
450 ***************************************************************************/
451 void remove_leading_spaces(char *s)
453 char *t;
455 fc_assert_ret(NULL != s);
456 t = skip_leading_spaces(s);
457 if (t != s) {
458 while (*t != '\0') {
459 *s++ = *t++;
461 *s = '\0';
465 /***************************************************************************
466 Terminates string pointed to by 's' to remove traling spaces;
467 Note 's' must point to writeable memory!
468 ***************************************************************************/
469 void remove_trailing_spaces(char *s)
471 char *t;
472 size_t len;
474 fc_assert_ret(NULL != s);
475 len = strlen(s);
476 if (len > 0) {
477 t = s + len -1;
478 while(fc_isspace(*t)) {
479 *t = '\0';
480 if (t == s) {
481 break;
483 t--;
488 /***************************************************************************
489 Removes leading and trailing spaces in string pointed to by 's'.
490 Note 's' must point to writeable memory!
491 ***************************************************************************/
492 void remove_leading_trailing_spaces(char *s)
494 remove_leading_spaces(s);
495 remove_trailing_spaces(s);
498 /***************************************************************************
499 As remove_trailing_spaces(), for specified char.
500 ***************************************************************************/
501 static void remove_trailing_char(char *s, char trailing)
503 char *t;
505 fc_assert_ret(NULL != s);
506 t = s + strlen(s) -1;
507 while(t>=s && (*t) == trailing) {
508 *t = '\0';
509 t--;
513 /***************************************************************************
514 Returns pointer to '\0' at end of string 'str', and decrements
515 *nleft by the length of 'str'. This is intended to be useful to
516 allow strcat-ing without traversing the whole string each time,
517 while still keeping track of the buffer length.
519 char buf[128];
520 int n = sizeof(buf);
521 char *p = buf;
523 fc_snprintf(p, n, "foo%p", p);
524 p = end_of_strn(p, &n);
525 fc_strlcpy(p, "yyy", n);
526 ***************************************************************************/
527 char *end_of_strn(char *str, int *nleft)
529 int len = strlen(str);
530 *nleft -= len;
531 fc_assert_ret_val(0 < (*nleft), NULL); /* space for the terminating nul */
532 return str + len;
535 /**********************************************************************
536 Check the length of the given string. If the string is too long,
537 log errmsg, which should be a string in printf-format taking up to
538 two arguments: the string and the length.
539 **********************************************************************/
540 bool check_strlen(const char *str, size_t len, const char *errmsg)
542 fc_assert_ret_val_msg(strlen(str) < len, TRUE, errmsg, str, len);
543 return FALSE;
546 /**********************************************************************
547 Call check_strlen() on str and then strlcpy() it into buffer.
548 **********************************************************************/
549 size_t loud_strlcpy(char *buffer, const char *str, size_t len,
550 const char *errmsg)
552 (void) check_strlen(str, len, errmsg);
553 return fc_strlcpy(buffer, str, len);
556 /****************************************************************************
557 Convert 'str' to it's int reprentation if possible. 'pint' can be NULL,
558 then it will only test 'str' only contains an integer number.
559 ****************************************************************************/
560 bool str_to_int(const char *str, int *pint)
562 const char *start;
564 fc_assert_ret_val(NULL != str, FALSE);
566 while (fc_isspace(*str)) {
567 /* Skip leading spaces. */
568 str++;
571 start = str;
572 if ('-' == *str || '+' == *str) {
573 /* Handle sign. */
574 str++;
576 while (fc_isdigit(*str)) {
577 /* Digits. */
578 str++;
581 while (fc_isspace(*str)) {
582 /* Ignore trailing spaces. */
583 str++;
586 return ('\0' == *str && (NULL == pint || 1 == sscanf(start, "%d", pint)));
589 /****************************************************************************
590 Convert 'str' to it's float reprentation if possible. 'pfloat' can be NULL,
591 then it will only test 'str' only contains a floating point number.
592 ****************************************************************************/
593 bool str_to_float(const char *str, float *pfloat)
595 bool dot;
596 const char *start;
598 fc_assert_ret_val(NULL != str, FALSE);
600 while (fc_isspace(*str)) {
601 /* Skip leading spaces. */
602 str++;
605 start = str;
607 if ('-' == *str || '+' == *str) {
608 /* Handle sign. */
609 str++;
611 while (fc_isdigit(*str)) {
612 /* Digits. */
613 str++;
616 if (*str == '.') {
617 dot = TRUE;
618 str++;
620 while (fc_isdigit(*str)) {
621 /* Digits. */
622 str++;
624 } else {
625 dot = FALSE;
628 while (fc_isspace(*str)) {
629 /* Ignore trailing spaces. */
630 str++;
633 return ('\0' == *str && dot
634 && (NULL == pfloat || 1 == sscanf(start, "%f", pfloat)));
637 /***************************************************************************
638 Returns string which gives users home dir, as specified by $HOME.
639 Gets value once, and then caches result.
640 If $HOME is not set, give a log message and returns NULL.
641 Note the caller should not mess with the returned string.
642 ***************************************************************************/
643 char *user_home_dir(void)
645 #ifdef AMIGA
646 return "PROGDIR:";
647 #else /* AMIGA */
649 if (home_dir == NULL) {
650 #ifdef FREECIV_MSWINDOWS
652 /* some documentation at:
653 * http://justcheckingonall.wordpress.com/2008/05/16/find-shell-folders-win32/
654 * http://archives.seul.org/or/cvs/Oct-2004/msg00082.html */
656 LPITEMIDLIST pidl;
657 LPMALLOC pMalloc;
659 if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl))) {
660 char *home_dir_in_local_encoding = fc_malloc(PATH_MAX);
662 if (SUCCEEDED(SHGetPathFromIDList(pidl, home_dir_in_local_encoding))) {
663 /* convert to internal encoding */
664 home_dir = local_to_internal_string_malloc(home_dir_in_local_encoding);
665 free(home_dir_in_local_encoding);
667 #ifdef DIR_SEPARATOR_IS_DEFAULT
668 /* replace backslashes with forward slashes */
670 char *c;
672 for (c = home_dir; *c != 0; c++) {
673 if (*c == '\\') {
674 *c = DIR_SEPARATOR_CHAR;
678 #endif /* DIR_SEPARATOR_IS_DEFAULT */
679 } else {
680 free(home_dir_in_local_encoding);
681 home_dir = NULL;
682 log_error("Could not find home directory "
683 "(SHGetPathFromIDList() failed).");
686 SHGetMalloc(&pMalloc);
687 if (pMalloc) {
688 pMalloc->lpVtbl->Free(pMalloc, pidl);
689 pMalloc->lpVtbl->Release(pMalloc);
692 } else {
693 log_error("Could not find home directory "
694 "(SHGetSpecialFolderLocation() failed).");
697 if (home_dir == NULL)
698 #endif /* FREECIV_MSWINDOWS */
700 char *env = getenv("HOME");
702 if (env) {
703 home_dir = fc_strdup(env);
704 log_verbose("HOME is %s", home_dir);
705 } else {
706 log_error("Could not find home directory (HOME is not set).");
707 home_dir = NULL;
712 return home_dir;
713 #endif /* AMIGA */
716 /***************************************************************************
717 Free user home directory information
718 ***************************************************************************/
719 void free_user_home_dir(void)
721 if (home_dir != NULL) {
722 free(home_dir);
723 home_dir = NULL;
727 /***************************************************************************
728 Returns string which gives user's username, as specified by $USER or
729 as given in password file for this user's uid, or a made up name if
730 we can't get either of the above.
731 Gets value once, and then caches result.
732 Note the caller should not mess with returned string.
733 ***************************************************************************/
734 char *user_username(char *buf, size_t bufsz)
736 /* This function uses a number of different methods to try to find a
737 * username. This username then has to be truncated to bufsz
738 * characters (including terminator) and checked for sanity. Note that
739 * truncating a sane name can leave you with an insane name under some
740 * charsets. */
742 /* If the environment variable $USER is present and sane, use it. */
744 char *env = getenv("USER");
746 if (env) {
747 fc_strlcpy(buf, env, bufsz);
748 if (is_ascii_name(buf)) {
749 log_verbose("USER username is %s", buf);
750 return buf;
755 #ifdef HAVE_GETPWUID
756 /* Otherwise if getpwuid() is available we can use it to find the true
757 * username. */
759 struct passwd *pwent = getpwuid(getuid());
761 if (pwent) {
762 fc_strlcpy(buf, pwent->pw_name, bufsz);
763 if (is_ascii_name(buf)) {
764 log_verbose("getpwuid username is %s", buf);
765 return buf;
769 #endif /* HAVE_GETPWUID */
771 #ifdef WIN32_NATIVE
772 /* On win32 the GetUserName function will give us the login name. */
774 char name[UNLEN + 1];
775 DWORD length = sizeof(name);
777 if (GetUserName(name, &length)) {
778 fc_strlcpy(buf, name, bufsz);
779 if (is_ascii_name(buf)) {
780 log_verbose("GetUserName username is %s", buf);
781 return buf;
785 #endif /* WIN32_NATIVE */
787 #ifdef ALWAYS_ROOT
788 fc_strlcpy(buf, "name", bufsz);
789 #else
790 fc_snprintf(buf, bufsz, "name%d", (int) getuid());
791 #endif
792 log_verbose("fake username is %s", buf);
793 fc_assert(is_ascii_name(buf));
794 return buf;
797 /***************************************************************************
798 Returns a list of directory paths, in the order in which they should
799 be searched. Base function for get_data_dirs(), get_save_dirs(),
800 get_scenario_dirs()
801 ***************************************************************************/
802 static struct strvec *base_get_dirs(const char *dir_list)
804 struct strvec *dirs = strvec_new();
805 char *path, *tok;
807 path = fc_strdup(dir_list); /* something we can strtok */
808 tok = strtok(path, PATH_SEPARATOR);
809 do {
810 int i; /* strlen(tok), or -1 as flag */
812 tok = skip_leading_spaces(tok);
813 remove_trailing_spaces(tok);
814 if (strcmp(tok, DIR_SEPARATOR) != 0) {
815 remove_trailing_char(tok, DIR_SEPARATOR_CHAR);
818 i = strlen(tok);
819 if (tok[0] == '~') {
820 if (i > 1 && tok[1] != DIR_SEPARATOR_CHAR) {
821 log_error("For \"%s\" in path cannot expand '~'"
822 " except as '~" DIR_SEPARATOR "'; ignoring", tok);
823 i = 0; /* skip this one */
824 } else {
825 char *home = user_home_dir();
827 if (!home) {
828 log_verbose("No HOME, skipping path component %s", tok);
829 i = 0;
830 } else {
831 int len = strlen(home) + i; /* +1 -1 */
832 char *tmp = fc_malloc(len);
834 fc_snprintf(tmp, len, "%s%s", home, tok + 1);
835 tok = tmp;
836 i = -1; /* flag to free tok below */
841 if (i != 0) {
842 /* We could check whether the directory exists and
843 * is readable etc? Don't currently. */
844 strvec_append(dirs, tok);
845 if (i == -1) {
846 free(tok);
847 tok = NULL;
851 tok = strtok(NULL, PATH_SEPARATOR);
852 } while(tok);
854 free(path);
855 return dirs;
858 /***************************************************************************
859 Free data dir name vectors.
860 ***************************************************************************/
861 void free_data_dir_names(void)
863 if (data_dir_names != NULL) {
864 strvec_destroy(data_dir_names);
865 data_dir_names = NULL;
867 if (save_dir_names != NULL) {
868 strvec_destroy(save_dir_names);
869 save_dir_names = NULL;
871 if (scenario_dir_names != NULL) {
872 strvec_destroy(scenario_dir_names);
873 scenario_dir_names = NULL;
877 /***************************************************************************
878 Returns a list of data directory paths, in the order in which they should
879 be searched. These paths are specified internally or may be set as the
880 environment variable $FREECIV_DATA PATH (a separated list of directories,
881 where the separator itself is specified internally, platform-dependent).
882 FREECIV_PATH may also be consulted for backward compatibility.
883 '~' at the start of a component (provided followed by '/' or '\0') is
884 expanded as $HOME.
886 The returned pointer is static and shouldn't be modified, nor destroyed
887 by the user caller.
888 ***************************************************************************/
889 const struct strvec *get_data_dirs(void)
891 /* The first time this function is called it will search and
892 * allocate the directory listing. Subsequently we will already
893 * know the list and can just return it. */
894 if (NULL == data_dir_names) {
895 const char *path;
897 if ((path = getenv(FREECIV_DATA_PATH)) && '\0' == path[0]) {
898 /* TRANS: <FREECIV_DATA_PATH> configuration error */
899 log_error(_("\"%s\" is set but empty; trying \"%s\" instead."),
900 FREECIV_DATA_PATH, FREECIV_PATH);
901 path = NULL;
903 if (NULL == path && (path = getenv(FREECIV_PATH))) {
904 if (!depr_freeciv_path_warned) {
905 log_error(_("FREECIV_PATH is deprecated, and won't work in future versions."));
906 depr_freeciv_path_warned = TRUE;
908 if ('\0' == path[0]) {
909 /* TRANS: <FREECIV_PATH> configuration error */
910 log_error(_("\"%s\" is set but empty; using default \"%s\" "
911 "data directories instead."),
912 FREECIV_PATH, DEFAULT_DATA_PATH);
913 path = NULL;
916 data_dir_names = base_get_dirs(NULL != path ? path : DEFAULT_DATA_PATH);
917 strvec_remove_duplicate(data_dir_names, strcmp); /* Don't set a path both. */
918 strvec_iterate(data_dir_names, dirname) {
919 log_verbose("Data path component: %s", dirname);
920 } strvec_iterate_end;
923 return data_dir_names;
926 /***************************************************************************
927 Returns a list of save directory paths, in the order in which they should
928 be searched. These paths are specified internally or may be set as the
929 environment variable $FREECIV_SAVE_PATH (a separated list of directories,
930 where the separator itself is specified internally, platform-dependent).
931 FREECIV_PATH may also be consulted for backward compatibility.
932 '~' at the start of a component (provided followed by '/' or '\0') is
933 expanded as $HOME.
935 The returned pointer is static and shouldn't be modified, nor destroyed
936 by the user caller.
937 ***************************************************************************/
938 const struct strvec *get_save_dirs(void)
940 /* The first time this function is called it will search and
941 * allocate the directory listing. Subsequently we will already
942 * know the list and can just return it. */
943 if (NULL == save_dir_names) {
944 const char *path;
945 bool from_freeciv_path = FALSE;
947 if ((path = getenv(FREECIV_SAVE_PATH)) && '\0' == path[0]) {
948 /* TRANS: <FREECIV_SAVE_PATH> configuration error */
949 log_error(_("\"%s\" is set but empty; trying \"%s\" instead."),
950 FREECIV_SAVE_PATH, FREECIV_PATH);
951 path = NULL;
953 if (NULL == path && (path = getenv(FREECIV_PATH))) {
954 if (!depr_freeciv_path_warned) {
955 log_error(_("FREECIV_PATH is deprecated, and won't work in future versions."));
956 depr_freeciv_path_warned = TRUE;
958 if ('\0' == path[0]) {
959 /* TRANS: <FREECIV_PATH> configuration error */
960 log_error(_("\"%s\" is set but empty; using default \"%s\" "
961 "save directories instead."),
962 FREECIV_PATH, DEFAULT_SAVE_PATH);
963 path = NULL;
964 } else {
965 from_freeciv_path = TRUE;
968 save_dir_names = base_get_dirs(NULL != path ? path : DEFAULT_SAVE_PATH);
969 if (from_freeciv_path) {
970 /* Then also append a "/saves" suffix to every directory. */
971 char buf[512];
972 size_t i;
974 for (i = 0; i < strvec_size(save_dir_names); i++) {
975 path = strvec_get(save_dir_names, i);
976 fc_snprintf(buf, sizeof(buf), "%s/saves", path);
977 strvec_insert(save_dir_names, ++i, buf);
980 strvec_remove_duplicate(save_dir_names, strcmp); /* Don't set a path both. */
981 strvec_iterate(save_dir_names, dirname) {
982 log_verbose("Save path component: %s", dirname);
983 } strvec_iterate_end;
986 return save_dir_names;
989 /***************************************************************************
990 Returns a list of scenario directory paths, in the order in which they
991 should be searched. These paths are specified internally or may be set
992 as the environment variable $FREECIV_SCENARIO_PATH (a separated list of
993 directories, where the separator itself is specified internally,
994 platform-dependent). FREECIV_PATH may also be consulted for backward
995 compatibility. '~' at the start of a component (provided followed
996 by '/' or '\0') is expanded as $HOME.
998 The returned pointer is static and shouldn't be modified, nor destroyed
999 by the user caller.
1000 ***************************************************************************/
1001 const struct strvec *get_scenario_dirs(void)
1003 /* The first time this function is called it will search and
1004 * allocate the directory listing. Subsequently we will already
1005 * know the list and can just return it. */
1006 if (NULL == scenario_dir_names) {
1007 const char *path;
1008 bool from_freeciv_path = FALSE;
1010 if ((path = getenv(FREECIV_SCENARIO_PATH)) && '\0' == path[0]) {
1011 /* TRANS: <FREECIV_SCENARIO_PATH> configuration error */
1012 log_error(_("\"%s\" is set but empty; trying \"%s\" instead."),
1013 FREECIV_SCENARIO_PATH, FREECIV_PATH);
1014 path = NULL;
1016 if (NULL == path && (path = getenv(FREECIV_PATH))) {
1017 if (!depr_freeciv_path_warned) {
1018 log_error(_("FREECIV_PATH is deprecated, and won't work in future versions."));
1019 depr_freeciv_path_warned = TRUE;
1021 if ('\0' == path[0]) {
1022 /* TRANS: <FREECIV_PATH> configuration error */
1023 log_error( _("\"%s\" is set but empty; using default \"%s\" "
1024 "scenario directories instead."),
1025 FREECIV_PATH, DEFAULT_SCENARIO_PATH);
1026 path = NULL;
1027 } else {
1028 from_freeciv_path = TRUE;
1031 scenario_dir_names = base_get_dirs(NULL != path ? path : DEFAULT_SCENARIO_PATH);
1032 if (from_freeciv_path) {
1033 /* Then also append subdirs every directory. */
1034 const char *subdirs[] = {
1035 "scenarios", "scenario", NULL
1037 char buf[512];
1038 const char **subdir;
1039 size_t i;
1041 for (i = 0; i < strvec_size(scenario_dir_names); i++) {
1042 path = strvec_get(scenario_dir_names, i);
1043 for (subdir = subdirs; NULL != *subdir; subdir++) {
1044 fc_snprintf(buf, sizeof(buf), "%s/%s", path, *subdir);
1045 strvec_insert(scenario_dir_names, ++i, buf);
1049 strvec_remove_duplicate(scenario_dir_names, strcmp); /* Don't set a path both. */
1050 strvec_iterate(scenario_dir_names, dirname) {
1051 log_verbose("Scenario path component: %s", dirname);
1052 } strvec_iterate_end;
1055 return scenario_dir_names;
1058 /***************************************************************************
1059 Returns a string vector storing the filenames in the data directories
1060 matching the given suffix.
1062 The list is allocated when the function is called; it should either
1063 be stored permanently or destroyed (with strvec_destroy()).
1065 The suffixes are removed from the filenames before the list is
1066 returned.
1067 ***************************************************************************/
1068 struct strvec *fileinfolist(const struct strvec *dirs, const char *suffix)
1070 struct strvec *files = strvec_new();
1071 size_t suffix_len = strlen(suffix);
1073 fc_assert_ret_val(!strchr(suffix, DIR_SEPARATOR_CHAR), NULL);
1075 if (NULL == dirs) {
1076 return files;
1079 /* First assemble a full list of names. */
1080 strvec_iterate(dirs, dirname) {
1081 DIR *dir;
1082 struct dirent *entry;
1084 /* Open the directory for reading. */
1085 dir = fc_opendir(dirname);
1086 if (!dir) {
1087 if (errno == ENOENT) {
1088 log_verbose("Skipping non-existing data directory %s.",
1089 dirname);
1090 } else {
1091 /* TRANS: "...: <externally translated error string>."*/
1092 log_error(_("Could not read data directory %s: %s."),
1093 dirname, fc_strerror(fc_get_errno()));
1095 continue;
1098 /* Scan all entries in the directory. */
1099 while ((entry = readdir(dir))) {
1100 size_t len = strlen(entry->d_name);
1102 /* Make sure the file name matches. */
1103 if (len > suffix_len
1104 && strcmp(suffix, entry->d_name + len - suffix_len) == 0) {
1105 /* Strdup the entry so we can safely write to it. */
1106 char *match = fc_strdup(entry->d_name);
1108 /* Clip the suffix. */
1109 match[len - suffix_len] = '\0';
1111 strvec_append(files, match);
1112 free(match);
1116 closedir(dir);
1117 } strvec_iterate_end;
1119 /* Sort the list and remove duplications. */
1120 strvec_remove_duplicate(files, strcmp);
1121 strvec_sort(files, compare_strings_strvec);
1123 return files;
1126 /***************************************************************************
1127 Returns a filename to access the specified file from a
1128 directory by searching all specified directories for the file.
1130 If the specified 'filename' is NULL, the returned string contains
1131 the effective path. (But this should probably only be used for
1132 debug output.)
1134 Returns NULL if the specified filename cannot be found in any of the
1135 data directories. (A file is considered "found" if it can be
1136 read-opened.) The returned pointer points to static memory, so this
1137 function can only supply one filename at a time. Don't free that
1138 pointer.
1140 TODO: Make this re-entrant
1141 ***************************************************************************/
1142 const char *fileinfoname(const struct strvec *dirs, const char *filename)
1144 #ifdef WIN32_NATIVE
1145 char fnbuf[strlen(filename) + 1];
1146 int i;
1147 #else /* WIN32_NATIVE */
1148 const char *fnbuf = filename;
1149 #endif /* WIN32_NATIVE */
1151 if (NULL == dirs) {
1152 return NULL;
1155 if (!filename) {
1156 bool first = TRUE;
1158 astr_clear(&realfile);
1159 strvec_iterate(dirs, dirname) {
1160 if (first) {
1161 astr_add(&realfile, "%s%s", PATH_SEPARATOR, dirname);
1162 first = FALSE;
1163 } else {
1164 astr_add(&realfile, "%s", dirname);
1166 } strvec_iterate_end;
1168 return astr_str(&realfile);
1171 #ifndef DIR_SEPARATOR_IS_DEFAULT
1172 for (i = 0; filename[i] != '\0'; i++) {
1173 if (filename[i] == '/') {
1174 fnbuf[i] = DIR_SEPARATOR_CHAR;
1175 } else {
1176 fnbuf[i] = filename[i];
1179 fnbuf[i] = '\0';
1180 #endif /* DIR_SEPARATOR_IS_DEFAULT */
1182 strvec_iterate(dirs, dirname) {
1183 struct stat buf; /* see if we can open the file or directory */
1185 astr_set(&realfile, "%s" DIR_SEPARATOR "%s", dirname, fnbuf);
1186 if (fc_stat(astr_str(&realfile), &buf) == 0) {
1187 return astr_str(&realfile);
1189 } strvec_iterate_end;
1191 log_verbose("Could not find readable file \"%s\" in data path.", filename);
1193 return NULL;
1196 /**************************************************************************
1197 Free resources allocated for fileinfoname service
1198 **************************************************************************/
1199 void free_fileinfo_data(void)
1201 astr_free(&realfile);
1204 /**************************************************************************
1205 Destroys the file info structure.
1206 **************************************************************************/
1207 static void fileinfo_destroy(struct fileinfo *pfile)
1209 free(pfile->name);
1210 free(pfile->fullname);
1211 free(pfile);
1214 /**************************************************************************
1215 Compare modification times.
1216 **************************************************************************/
1217 static int compare_file_mtime_ptrs(const struct fileinfo *const *ppa,
1218 const struct fileinfo *const *ppb)
1220 time_t a = (*ppa)->mtime;
1221 time_t b = (*ppb)->mtime;
1223 return ((a < b) ? 1 : (a > b) ? -1 : 0);
1226 /**************************************************************************
1227 Compare names.
1228 **************************************************************************/
1229 static int compare_file_name_ptrs(const struct fileinfo *const *ppa,
1230 const struct fileinfo *const *ppb)
1232 return fc_strcoll((*ppa)->name, (*ppb)->name);
1235 /**************************************************************************
1236 Compare names.
1237 **************************************************************************/
1238 static bool compare_fileinfo_name(const struct fileinfo *pa,
1239 const struct fileinfo *pb)
1241 return 0 == fc_strcoll(pa->name, pb->name);
1244 /**************************************************************************
1245 Search for filenames with the "infix" substring in the "subpath"
1246 subdirectory of the data path.
1247 "nodups" removes duplicate names.
1248 The returned list will be sorted by name first and modification time
1249 second. Returned "name"s will be truncated starting at the "infix"
1250 substring. The returned list must be freed with fileinfo_list_destroy().
1251 **************************************************************************/
1252 struct fileinfo_list *fileinfolist_infix(const struct strvec *dirs,
1253 const char *infix, bool nodups)
1255 struct fileinfo_list *res;
1257 if (NULL == dirs) {
1258 return NULL;
1261 res = fileinfo_list_new_full(fileinfo_destroy);
1263 /* First assemble a full list of names. */
1264 strvec_iterate(dirs, dirname) {
1265 DIR *dir;
1266 struct dirent *entry;
1268 /* Open the directory for reading. */
1269 dir = fc_opendir(dirname);
1270 if (!dir) {
1271 continue;
1274 /* Scan all entries in the directory. */
1275 while ((entry = readdir(dir))) {
1276 struct fileinfo *file;
1277 char *ptr;
1278 /* Strdup the entry so we can safely write to it. */
1279 char *filename = fc_strdup(entry->d_name);
1281 /* Make sure the file name matches. */
1282 if ((ptr = strstr(filename, infix))) {
1283 struct stat buf;
1284 char *fullname;
1285 size_t len = strlen(dirname) + strlen(filename) + 2;
1287 fullname = fc_malloc(len);
1288 fc_snprintf(fullname, len, "%s" DIR_SEPARATOR "%s", dirname, filename);
1290 if (fc_stat(fullname, &buf) == 0) {
1291 file = fc_malloc(sizeof(*file));
1293 /* Clip the suffix. */
1294 *ptr = '\0';
1296 file->name = filename;
1297 file->fullname = fullname;
1298 file->mtime = buf.st_mtime;
1300 fileinfo_list_append(res, file);
1301 } else {
1302 free(fullname);
1303 free(filename);
1305 } else {
1306 free(filename);
1310 closedir(dir);
1311 } strvec_iterate_end;
1313 /* Sort the list by name. */
1314 fileinfo_list_sort(res, compare_file_name_ptrs);
1316 if (nodups) {
1317 fileinfo_list_unique_full(res, compare_fileinfo_name);
1320 /* Sort the list by last modification time. */
1321 fileinfo_list_sort(res, compare_file_mtime_ptrs);
1323 return res;
1326 /***************************************************************************
1327 Language environmental variable (with emulation).
1328 ***************************************************************************/
1329 char *setup_langname(void)
1331 char *langname = NULL;
1333 #ifdef ENABLE_NLS
1334 langname = getenv("LANG");
1336 #ifdef WIN32_NATIVE
1337 /* set LANG by hand if it is not set */
1338 if (!langname) {
1339 switch (PRIMARYLANGID(GetUserDefaultLangID())) {
1340 case LANG_ARABIC:
1341 langname = "ar";
1342 break;
1343 case LANG_CATALAN:
1344 langname = "ca";
1345 break;
1346 case LANG_CZECH:
1347 langname = "cs";
1348 break;
1349 case LANG_DANISH:
1350 langname = "da";
1351 break;
1352 case LANG_GERMAN:
1353 langname = "de";
1354 break;
1355 case LANG_GREEK:
1356 langname = "el";
1357 break;
1358 case LANG_ENGLISH:
1359 switch (SUBLANGID(GetUserDefaultLangID())) {
1360 case SUBLANG_ENGLISH_UK:
1361 langname = "en_GB";
1362 break;
1363 default:
1364 langname = "en";
1365 break;
1367 break;
1368 case LANG_SPANISH:
1369 langname = "es";
1370 break;
1371 case LANG_ESTONIAN:
1372 langname = "et";
1373 break;
1374 case LANG_FARSI:
1375 langname = "fa";
1376 break;
1377 case LANG_FINNISH:
1378 langname = "fi";
1379 break;
1380 case LANG_FRENCH:
1381 langname = "fr";
1382 break;
1383 case LANG_HEBREW:
1384 langname = "he";
1385 break;
1386 case LANG_HUNGARIAN:
1387 langname = "hu";
1388 break;
1389 case LANG_ITALIAN:
1390 langname = "it";
1391 break;
1392 case LANG_JAPANESE:
1393 langname = "ja";
1394 break;
1395 case LANG_KOREAN:
1396 langname = "ko";
1397 break;
1398 case LANG_LITHUANIAN:
1399 langname = "lt";
1400 break;
1401 case LANG_DUTCH:
1402 langname = "nl";
1403 break;
1404 case LANG_NORWEGIAN:
1405 langname = "nb";
1406 break;
1407 case LANG_POLISH:
1408 langname = "pl";
1409 break;
1410 case LANG_PORTUGUESE:
1411 switch (SUBLANGID(GetUserDefaultLangID())) {
1412 case SUBLANG_PORTUGUESE_BRAZILIAN:
1413 langname = "pt_BR";
1414 break;
1415 default:
1416 langname = "pt";
1417 break;
1419 break;
1420 case LANG_ROMANIAN:
1421 langname = "ro";
1422 break;
1423 case LANG_RUSSIAN:
1424 langname = "ru";
1425 break;
1426 case LANG_SWEDISH:
1427 langname = "sv";
1428 break;
1429 case LANG_TURKISH:
1430 langname = "tr";
1431 break;
1432 case LANG_UKRAINIAN:
1433 langname = "uk";
1434 break;
1435 case LANG_CHINESE:
1436 langname = "zh_CN";
1437 break;
1440 if (langname != NULL) {
1441 static char envstr[40];
1443 fc_snprintf(envstr, sizeof(envstr), "LANG=%s", langname);
1444 putenv(envstr);
1447 #endif /* WIN32_NATIVE */
1448 #endif /* ENABLE_NLS */
1450 return langname;
1453 /***************************************************************************
1454 Setup for Native Language Support, if configured to use it.
1455 (Call this only once, or it may leak memory.)
1456 ***************************************************************************/
1457 void init_nls(void)
1460 * Setup the cached locale numeric formatting information. Defaults
1461 * are as appropriate for the US.
1463 grouping = fc_strdup("\3");
1464 grouping_sep = fc_strdup(",");
1466 #ifdef ENABLE_NLS
1468 #ifdef WIN32_NATIVE
1469 setup_langname(); /* Makes sure LANG env variable has been set */
1470 #endif /* WIN32_NATIVE */
1472 (void) setlocale(LC_ALL, "");
1473 (void) bindtextdomain(PACKAGE, get_locale_dir());
1474 (void) textdomain(PACKAGE);
1476 /* Don't touch the defaults when LC_NUMERIC == "C".
1477 This is intended to cater to the common case where:
1478 1) The user is from North America. ;-)
1479 2) The user has not set the proper environment variables.
1480 (Most applications are (unfortunately) US-centric
1481 by default, so why bother?)
1482 This would result in the "C" locale being used, with grouping ""
1483 and thousands_sep "", where we really want "\3" and ",". */
1485 if (strcmp(setlocale(LC_NUMERIC, NULL), "C") != 0) {
1486 struct lconv *lc = localeconv();
1488 if (lc->grouping[0] == '\0') {
1489 /* This actually indicates no grouping at all. */
1490 char *m = malloc(sizeof(char));
1491 *m = CHAR_MAX;
1492 grouping = m;
1493 } else {
1494 size_t len;
1495 for (len = 0;
1496 lc->grouping[len] != '\0' && lc->grouping[len] != CHAR_MAX; len++) {
1497 /* nothing */
1499 len++;
1500 free(grouping);
1501 grouping = fc_malloc(len);
1502 memcpy(grouping, lc->grouping, len);
1504 free(grouping_sep);
1505 grouping_sep = fc_strdup(lc->thousands_sep);
1509 char *autocap_opt_in[] = { "fi", NULL };
1510 int i;
1511 bool ac_enabled = FALSE;
1513 char *lang = getenv("LANG");
1515 if (lang != NULL && lang[0] != '\0' && lang[1] != '\0') {
1516 for (i = 0; autocap_opt_in[i] != NULL && !ac_enabled; i++) {
1517 if (lang[0] == autocap_opt_in[i][0]
1518 && lang[1] == autocap_opt_in[i][1]) {
1519 ac_enabled = TRUE;
1520 capitalization_opt_in();
1526 #endif /* ENABLE_NLS */
1529 /***************************************************************************
1530 Free memory allocated by Native Language Support
1531 ***************************************************************************/
1532 void free_nls(void)
1534 free(grouping);
1535 grouping = NULL;
1536 free(grouping_sep);
1537 grouping_sep = NULL;
1540 /***************************************************************************
1541 If we have root privileges, die with an error.
1542 (Eg, for security reasons.)
1543 Param argv0 should be argv[0] or similar; fallback is
1544 used instead if argv0 is NULL.
1545 But don't die on systems where the user is always root...
1546 (a general test for this would be better).
1547 Doesn't use log_*() because gets called before logging is setup.
1548 ***************************************************************************/
1549 void dont_run_as_root(const char *argv0, const char *fallback)
1551 #if (defined(ALWAYS_ROOT) || defined(__EMX__) || defined(__BEOS__))
1552 return;
1553 #else
1554 if (getuid()==0 || geteuid()==0) {
1555 fc_fprintf(stderr,
1556 _("%s: Fatal error: you're trying to run me as superuser!\n"),
1557 (argv0 ? argv0 : fallback ? fallback : "freeciv"));
1558 fc_fprintf(stderr, _("Use a non-privileged account instead.\n"));
1559 exit(EXIT_FAILURE);
1561 #endif /* ALWAYS_ROOT */
1564 /***************************************************************************
1565 Return a description string of the result.
1566 In English, form of description is suitable to substitute in, eg:
1567 prefix is <description>
1568 (N.B.: The description is always in English, but they have all been marked
1569 for translation. If you want a localized version, use _() on the return.)
1570 ***************************************************************************/
1571 const char *m_pre_description(enum m_pre_result result)
1573 static const char * const descriptions[] = {
1574 N_("exact match"),
1575 N_("only match"),
1576 N_("ambiguous"),
1577 N_("empty"),
1578 N_("too long"),
1579 N_("non-match")
1581 fc_assert_ret_val(result >= 0 && result < ARRAY_SIZE(descriptions), NULL);
1582 return descriptions[result];
1585 /***************************************************************************
1586 See match_prefix_full().
1587 ***************************************************************************/
1588 enum m_pre_result match_prefix(m_pre_accessor_fn_t accessor_fn,
1589 size_t n_names,
1590 size_t max_len_name,
1591 m_pre_strncmp_fn_t cmp_fn,
1592 m_strlen_fn_t len_fn,
1593 const char *prefix,
1594 int *ind_result)
1596 return match_prefix_full(accessor_fn, n_names, max_len_name, cmp_fn,
1597 len_fn, prefix, ind_result, NULL, 0, NULL);
1600 /***************************************************************************
1601 Given n names, with maximum length max_len_name, accessed by
1602 accessor_fn(0) to accessor_fn(n-1), look for matching prefix
1603 according to given comparison function.
1604 Returns type of match or fail, and for return <= M_PRE_AMBIGUOUS
1605 sets *ind_result with matching index (or for ambiguous, first match).
1606 If max_len_name==0, treat as no maximum.
1607 If the int array 'matches' is non-NULL, up to 'max_matches' ambiguous
1608 matching names indices will be inserted into it. If 'pnum_matches' is
1609 non-NULL, it will be set to the number of indices inserted into 'matches'.
1610 ***************************************************************************/
1611 enum m_pre_result match_prefix_full(m_pre_accessor_fn_t accessor_fn,
1612 size_t n_names,
1613 size_t max_len_name,
1614 m_pre_strncmp_fn_t cmp_fn,
1615 m_strlen_fn_t len_fn,
1616 const char *prefix,
1617 int *ind_result,
1618 int *matches,
1619 int max_matches,
1620 int *pnum_matches)
1622 int i, len, nmatches;
1624 if (len_fn == NULL) {
1625 len = strlen(prefix);
1626 } else {
1627 len = len_fn(prefix);
1629 if (len == 0) {
1630 return M_PRE_EMPTY;
1632 if (len > max_len_name && max_len_name > 0) {
1633 return M_PRE_LONG;
1636 nmatches = 0;
1637 for(i=0; i<n_names; i++) {
1638 const char *name = accessor_fn(i);
1639 if (cmp_fn(name, prefix, len)==0) {
1640 if (strlen(name) == len) {
1641 *ind_result = i;
1642 return M_PRE_EXACT;
1644 if (nmatches==0) {
1645 *ind_result = i; /* first match */
1647 if (matches != NULL && nmatches < max_matches) {
1648 matches[nmatches] = i;
1650 nmatches++;
1654 if (nmatches == 1) {
1655 return M_PRE_ONLY;
1656 } else if (nmatches > 1) {
1657 if (pnum_matches != NULL) {
1658 *pnum_matches = MIN(max_matches, nmatches);
1660 return M_PRE_AMBIGUOUS;
1661 } else {
1662 return M_PRE_FAIL;
1666 /***************************************************************************
1667 Returns string which gives the multicast group IP address for finding
1668 servers on the LAN, as specified by $FREECIV_MULTICAST_GROUP.
1669 Gets value once, and then caches result.
1670 ***************************************************************************/
1671 char *get_multicast_group(bool ipv6_preferred)
1673 static char *default_multicast_group_ipv4 = "225.1.1.1";
1674 #ifdef FREECIV_IPV6_SUPPORT
1675 /* TODO: Get useful group (this is node local) */
1676 static char *default_multicast_group_ipv6 = "FF31::8000:15B4";
1677 #endif /* IPv6 support */
1679 if (mc_group == NULL) {
1680 char *env = getenv("FREECIV_MULTICAST_GROUP");
1682 if (env) {
1683 mc_group = fc_strdup(env);
1684 } else {
1685 #ifdef FREECIV_IPV6_SUPPORT
1686 if (ipv6_preferred) {
1687 mc_group = fc_strdup(default_multicast_group_ipv6);
1688 } else
1689 #endif /* IPv6 support */
1691 mc_group = fc_strdup(default_multicast_group_ipv4);
1696 return mc_group;
1699 /***************************************************************************
1700 Free multicast group resources
1701 ***************************************************************************/
1702 void free_multicast_group(void)
1704 if (mc_group != NULL) {
1705 free(mc_group);
1706 mc_group = NULL;
1710 /***************************************************************************
1711 Interpret ~/ in filename as home dir
1712 New path is returned in buf of size buf_size
1714 This may fail if the path is too long. It is better to use
1715 interpret_tilde_alloc.
1716 ***************************************************************************/
1717 void interpret_tilde(char* buf, size_t buf_size, const char* filename)
1719 if (filename[0] == '~' && filename[1] == DIR_SEPARATOR_CHAR) {
1720 fc_snprintf(buf, buf_size, "%s" DIR_SEPARATOR "%s", user_home_dir(), filename + 2);
1721 } else if (filename[0] == '~' && filename[1] == '\0') {
1722 strncpy(buf, user_home_dir(), buf_size);
1723 } else {
1724 strncpy(buf, filename, buf_size);
1728 /***************************************************************************
1729 Interpret ~/ in filename as home dir
1731 The new path is returned in buf, as a newly allocated buffer. The new
1732 path will always be allocated and written, even if there is no ~ present.
1733 ***************************************************************************/
1734 char *interpret_tilde_alloc(const char* filename)
1736 if (filename[0] == '~' && filename[1] == DIR_SEPARATOR_CHAR) {
1737 const char *home = user_home_dir();
1738 size_t sz;
1739 char *buf;
1741 filename += 2; /* Skip past "~/" */
1742 sz = strlen(home) + strlen(filename) + 2;
1743 buf = fc_malloc(sz);
1744 fc_snprintf(buf, sz, "%s/%s", home, filename);
1745 return buf;
1746 } else if (filename[0] == '~' && filename[1] == '\0') {
1747 return fc_strdup(user_home_dir());
1748 } else {
1749 return fc_strdup(filename);
1753 /**************************************************************************
1754 Return a pointer to the start of the file basename in filepath.
1755 If the string contains no dir separator, it is returned itself.
1756 **************************************************************************/
1757 char *skip_to_basename(char *filepath)
1759 int j;
1760 fc_assert_ret_val(NULL != filepath, NULL);
1762 for (j = strlen(filepath); j >= 0; j--) {
1763 if (filepath[j] == DIR_SEPARATOR_CHAR) {
1764 return &filepath[j+1];
1767 return filepath;
1770 /**************************************************************************
1771 If the directory "pathname" does not exist, recursively create all
1772 directories until it does.
1773 **************************************************************************/
1774 bool make_dir(const char *pathname)
1776 char *dir;
1777 char *path = NULL;
1779 path = interpret_tilde_alloc(pathname);
1780 dir = path;
1781 do {
1782 dir = strchr(dir, DIR_SEPARATOR_CHAR);
1783 /* We set the current / with 0, and restore it afterwards */
1784 if (dir) {
1785 *dir = 0;
1788 #ifdef WIN32_NATIVE
1789 #ifdef HAVE__MKDIR
1790 /* Prefer _mkdir() in Windows even if mkdir() would seem to be available -
1791 * chances are that it's wrong kind of mkdir().
1792 * TODO: Make a configure check for mkdir() that also makes sure that it
1793 * takes two parameters, and prefer such proper mkdir() here. */
1795 char *path_in_local_encoding = internal_to_local_string_malloc(path);
1797 _mkdir(path_in_local_encoding);
1798 free(path_in_local_encoding);
1800 #else /* HAVE__MKDIR */
1801 mkdir(path, 0755);
1802 #endif /* HAVE__MKDIR */
1803 #else /* WIN32_NATIVE */
1804 mkdir(path, 0755);
1805 #endif /* WIN32_NATIVE */
1807 if (dir) {
1808 *dir = DIR_SEPARATOR_CHAR;
1809 dir++;
1811 } while (dir);
1813 free(path);
1814 return TRUE;
1817 /**************************************************************************
1818 Returns TRUE if the filename's path is absolute.
1819 **************************************************************************/
1820 bool path_is_absolute(const char *filename)
1822 if (!filename) {
1823 return FALSE;
1826 #ifdef WIN32_NATIVE
1827 if (strchr(filename, ':')) {
1828 return TRUE;
1830 #else /* WIN32_NATIVE */
1831 if (filename[0] == '/') {
1832 return TRUE;
1834 #endif /* WIN32_NATIVE */
1836 return FALSE;
1839 /**************************************************************************
1840 Scan in a word or set of words from start to but not including
1841 any of the given delimiters. The buf pointer will point past delimiter,
1842 or be set to NULL if there is nothing there. Removes excess white
1843 space.
1845 This function should be safe, and dest will contain "\0" and
1846 *buf == NULL on failure. We always fail gently.
1848 Due to the way the scanning is performed, looking for a space
1849 will give you the first word even if it comes before multiple
1850 spaces.
1852 Returns delimiter found.
1854 Pass in NULL for dest and -1 for size to just skip ahead. Note that if
1855 nothing is found, dest will contain the whole string, minus leading and
1856 trailing whitespace. You can scan for "" to conveniently grab the
1857 remainder of a string.
1858 **************************************************************************/
1859 char scanin(const char **buf, char *delimiters, char *dest, int size)
1861 char *ptr, found = '?';
1863 if (*buf == NULL || strlen(*buf) == 0 || size == 0) {
1864 if (dest) {
1865 dest[0] = '\0';
1867 *buf = NULL;
1868 return '\0';
1871 if (dest) {
1872 strncpy(dest, *buf, size-1);
1873 dest[size-1] = '\0';
1874 remove_leading_trailing_spaces(dest);
1875 ptr = strpbrk(dest, delimiters);
1876 } else {
1877 /* Just skip ahead. */
1878 ptr = strpbrk(*buf, delimiters);
1880 if (ptr != NULL) {
1881 found = *ptr;
1882 if (dest) {
1883 *ptr = '\0';
1885 if (dest) {
1886 remove_leading_trailing_spaces(dest);
1888 *buf = strpbrk(*buf, delimiters);
1889 if (*buf != NULL) {
1890 (*buf)++; /* skip delimiter */
1891 } else {
1893 } else {
1894 *buf = NULL;
1897 return found;
1900 /**************************************************************************
1901 Convenience function to nicely format a time_t seconds value in to a
1902 string with hours, minutes, etc.
1903 **************************************************************************/
1904 void format_time_duration(time_t t, char *buf, int maxlen)
1906 int seconds, minutes, hours, days;
1907 bool space = FALSE;
1909 seconds = t % 60;
1910 minutes = (t / 60) % 60;
1911 hours = (t / (60 * 60)) % 24;
1912 days = t / (60 * 60 * 24);
1914 if (maxlen <= 0) {
1915 return;
1918 buf[0] = '\0';
1920 if (days > 0) {
1921 cat_snprintf(buf, maxlen, "%d %s", days, PL_("day", "days", days));
1922 space = TRUE;
1924 if (hours > 0) {
1925 cat_snprintf(buf, maxlen, "%s%d %s",
1926 space ? " " : "", hours, PL_("hour", "hours", hours));
1927 space = TRUE;
1929 if (minutes > 0) {
1930 cat_snprintf(buf, maxlen, "%s%d %s",
1931 space ? " " : "",
1932 minutes, PL_("minute", "minutes", minutes));
1933 space = TRUE;
1935 if (seconds > 0) {
1936 cat_snprintf(buf, maxlen, "%s%d %s",
1937 space ? " " : "",
1938 seconds, PL_("second", "seconds", seconds));
1942 /************************************************************************
1943 Randomize the elements of an array using the Fisher-Yates shuffle.
1945 see: http://benpfaff.org/writings/clc/shuffle.html
1946 ************************************************************************/
1947 void array_shuffle(int *array, int n)
1949 if (n > 1 && array != NULL) {
1950 int i, j, t;
1951 for (i = 0; i < n - 1; i++) {
1952 j = i + fc_rand(n - i);
1953 t = array[j];
1954 array[j] = array[i];
1955 array[i] = t;
1960 /****************************************************************************
1961 Test an asterisk in the pattern against test. Returns TRUE if test fit the
1962 pattern. May be recursive, as it calls wildcard_fit_string() itself (if
1963 many asterisks).
1964 ****************************************************************************/
1965 static bool wildcard_asterisk_fit(const char *pattern, const char *test)
1967 char jump_to;
1969 /* Jump over the leading asterisks. */
1970 pattern++;
1971 while (TRUE) {
1972 switch (*pattern) {
1973 case '\0':
1974 /* It is a leading asterisk. */
1975 return TRUE;
1976 case '*':
1977 pattern++;
1978 continue;
1979 case '?':
1980 if ('\0' == *test) {
1981 return FALSE;
1983 test++;
1984 pattern++;
1985 continue;
1988 break;
1991 if ('[' != *pattern) {
1992 if ('\\' == *pattern) {
1993 jump_to = *(pattern + 1);
1994 } else {
1995 jump_to = *pattern;
1997 } else {
1998 jump_to = '\0';
2001 while ('\0' != *test) {
2002 if ('\0' != jump_to) {
2003 /* Jump to next matching charather. */
2004 test = strchr(test, jump_to);
2005 if (NULL == test) {
2006 /* No match. */
2007 return FALSE;
2011 if (wildcard_fit_string(pattern, test)) {
2012 return TRUE;
2015 (test)++;
2018 return FALSE;
2021 /****************************************************************************
2022 Test a range in the pattern against test. Returns TRUE if **test fit the
2023 first range in *pattern.
2024 ****************************************************************************/
2025 static bool wildcard_range_fit(const char **pattern, const char **test)
2027 const char *start = (*pattern + 1);
2028 char testc;
2029 bool negation;
2031 if ('\0' == **test) {
2032 /* Need one character. */
2033 return FALSE;
2036 /* Find the end of the pattern. */
2037 while (TRUE) {
2038 *pattern = strchr(*pattern, ']');
2039 if (NULL == *pattern) {
2040 /* Wildcard format error. */
2041 return FALSE;
2042 } else if (*(*pattern - 1) != '\\') {
2043 /* This is the end. */
2044 break;
2045 } else {
2046 /* Try again. */
2047 (*pattern)++;
2051 if ('!' == *start) {
2052 negation = TRUE;
2053 start++;
2054 } else {
2055 negation = FALSE;
2057 testc = **test;
2058 (*test)++;
2059 (*pattern)++;
2061 for (; start < *pattern; start++) {
2062 if ('-' == *start || '!' == *start) {
2063 /* Wildcard format error. */
2064 return FALSE;
2065 } else if (start < *pattern - 2 && '-' == *(start + 1)) {
2066 /* Case range. */
2067 if (*start <= testc && testc <= *(start + 2)) {
2068 return !negation;
2070 start += 2;
2071 } else if (*start == testc) {
2072 /* Single character. */
2073 return !negation;
2077 return negation;
2080 /****************************************************************************
2081 Returns TRUE if test fit the pattern. The pattern can contain special
2082 characters:
2083 * '*': to specify a substitute for any zero or more characters.
2084 * '?': to specify a substitute for any one character.
2085 * '[...]': to specify a range of characters:
2086 * '!': at the begenning of the range means that the matching result
2087 will be inverted
2088 * 'A-Z': means any character between 'A' and 'Z'.
2089 * 'agr': means 'a', 'g' or 'r'.
2090 ****************************************************************************/
2091 bool wildcard_fit_string(const char *pattern, const char *test)
2093 while (TRUE) {
2094 switch (*pattern) {
2095 case '\0':
2096 /* '\0' != test. */
2097 return '\0' == *test;
2098 case '*':
2099 return wildcard_asterisk_fit(pattern, test); /* Maybe recursive. */
2100 case '[':
2101 if (!wildcard_range_fit(&pattern, &test)) {
2102 return FALSE;
2104 continue;
2105 case '?':
2106 if ('\0' == *test) {
2107 return FALSE;
2109 break;
2110 case '\\':
2111 pattern++;
2112 /* break; not missing. */
2113 default:
2114 if (*pattern != *test) {
2115 return FALSE;
2117 break;
2119 pattern++;
2120 test++;
2123 return FALSE;
2126 /****************************************************************************
2127 Print a string with a custom format. sequences is a pointer to an array of
2128 sequences, probably defined with CF_*_SEQ(). sequences_num is the number of
2129 the sequences, or -1 in the case the array is terminated with CF_END.
2131 Example:
2132 static const struct cf_sequence sequences[] = {
2133 CF_INT_SEQ('y', 2010)
2135 char buf[256];
2137 fc_vsnprintcf(buf, sizeof(buf), "%y %+06y", sequences, 1);
2138 // This will print "2010 +02010" into buf.
2139 ****************************************************************************/
2140 int fc_vsnprintcf(char *buf, size_t buf_len, const char *format,
2141 const struct cf_sequence *sequences, size_t sequences_num)
2143 const struct cf_sequence *pseq;
2144 char cformat[32];
2145 const char *f = format;
2146 char *const max = buf + buf_len - 1;
2147 char *b = buf, *c;
2148 const char *const cmax = cformat + sizeof(cformat) - 2;
2149 int i, j;
2151 if ((size_t) -1 == sequences_num) {
2152 /* Find the number of sequences. */
2153 sequences_num = 0;
2154 for (pseq = sequences; CF_LAST != pseq->type; pseq++) {
2155 sequences_num++;
2159 while ('\0' != *f) {
2160 if ('%' == *f) {
2161 /* Sequence. */
2163 f++;
2164 if ('%' == *f) {
2165 /* Double '%'. */
2166 *b++ = '%';
2167 f++;
2168 continue;
2171 /* Make format. */
2172 c = cformat;
2173 *c++ = '%';
2174 for (; !fc_isalpha(*f) && '\0' != *f && '%' != *f && cmax > c; f++) {
2175 *c++ = *f;
2178 if (!fc_isalpha(*f)) {
2179 /* Beginning of a new sequence, end of the format, or too long
2180 * sequence. */
2181 *c = '\0';
2182 j = fc_snprintf(b, max - b + 1, "%s", cformat);
2183 if (-1 == j) {
2184 return -1;
2186 b += j;
2187 continue;
2190 for (i = 0, pseq = sequences; i < sequences_num; i++, pseq++) {
2191 if (pseq->letter == *f) {
2192 j = -2;
2193 switch (pseq->type) {
2194 case CF_BOOLEAN:
2195 *c++ = 's';
2196 *c = '\0';
2197 j = fc_snprintf(b, max - b + 1, cformat,
2198 pseq->bool_value ? "TRUE" : "FALSE");
2199 break;
2200 case CF_TRANS_BOOLEAN:
2201 *c++ = 's';
2202 *c = '\0';
2203 j = fc_snprintf(b, max - b + 1, cformat,
2204 pseq->bool_value ? _("TRUE") : _("FALSE"));
2205 break;
2206 case CF_CHARACTER:
2207 *c++ = 'c';
2208 *c = '\0';
2209 j = fc_snprintf(b, max - b + 1, cformat, pseq->char_value);
2210 break;
2211 case CF_INTEGER:
2212 *c++ = 'd';
2213 *c = '\0';
2214 j = fc_snprintf(b, max - b + 1, cformat, pseq->int_value);
2215 break;
2216 case CF_HEXA:
2217 *c++ = 'x';
2218 *c = '\0';
2219 j = fc_snprintf(b, max - b + 1, cformat, pseq->int_value);
2220 break;
2221 case CF_FLOAT:
2222 *c++ = 'f';
2223 *c = '\0';
2224 j = fc_snprintf(b, max - b + 1, cformat, pseq->float_value);
2225 break;
2226 case CF_POINTER:
2227 *c++ = 'p';
2228 *c = '\0';
2229 j = fc_snprintf(b, max - b + 1, cformat, pseq->ptr_value);
2230 break;
2231 case CF_STRING:
2232 *c++ = 's';
2233 *c = '\0';
2234 j = fc_snprintf(b, max - b + 1, cformat, pseq->str_value);
2235 break;
2236 case CF_LAST:
2237 break;
2239 if (-2 == j) {
2240 log_error("Error: unsupported sequence type: %d.", pseq->type);
2241 break;
2243 if (-1 == j) {
2244 /* Full! */
2245 return -1;
2247 f++;
2248 b += j;
2249 break;
2252 if (i >= sequences_num) {
2253 /* Format not supported. */
2254 *c = '\0';
2255 j = fc_snprintf(b, max - b + 1, "%s%c", cformat, *f);
2256 if (-1 == j) {
2257 return -1;
2259 f++;
2260 b += j;
2262 } else {
2263 /* Not a sequence. */
2264 *b++ = *f++;
2266 if (max <= b) {
2267 /* Too long. */
2268 *max = '\0';
2269 return -1;
2272 *b = '\0';
2273 return b - buf;
2276 /****************************************************************************
2277 Print a string with a custom format. The additional arguments are a suite
2278 of cf_*_seq() finished by cf_end(). This return the number of printed
2279 characters (excluding the last '\0') or -1 if the buffer is full.
2281 Example:
2282 char buf[256];
2284 fc_snprintcf(buf, sizeof(buf), "%y %+06y",
2285 cf_int_seq('y', 2010), cf_end());
2286 // This will print "2010 +02010" into buf.
2287 ****************************************************************************/
2288 int fc_snprintcf(char *buf, size_t buf_len, const char *format, ...)
2290 struct cf_sequence sequences[16];
2291 size_t sequences_num = 0;
2292 va_list args;
2294 /* Collect sequence array. */
2295 va_start(args, format);
2296 do {
2297 sequences[sequences_num] = va_arg(args, struct cf_sequence);
2298 if (CF_LAST == sequences[sequences_num].type) {
2299 break;
2300 } else {
2301 sequences_num++;
2303 } while (ARRAY_SIZE(sequences) > sequences_num);
2305 if (ARRAY_SIZE(sequences) <= sequences_num
2306 && CF_LAST != va_arg(args, struct cf_sequence).type) {
2307 log_error("Too many custom sequences. Maybe did you forget cf_end() "
2308 "at the end of the arguments?");
2309 buf[0] = '\0';
2310 va_end(args);
2311 return -1;
2313 va_end(args);
2315 return fc_vsnprintcf(buf, buf_len, format, sequences, sequences_num);
2318 /****************************************************************************
2319 Extract the sequences of a format. Returns the number of extracted
2320 escapes.
2321 ****************************************************************************/
2322 static size_t extract_escapes(const char *format, char *escapes,
2323 size_t max_escapes)
2325 static const char format_escapes[] = {
2326 '*', 'd', 'i', 'o', 'u', 'x', 'X', 'e', 'E', 'f',
2327 'F', 'g', 'G', 'a', 'A', 'c', 's', 'p', 'n',
2329 bool reordered = FALSE;
2330 size_t num = 0;
2331 int idx = 0;
2333 memset(escapes, 0, max_escapes);
2334 format = strchr(format, '%');
2335 while (NULL != format) {
2336 format++;
2337 if ('%' == *format) {
2338 /* Double, not a sequence. */
2339 continue;
2340 } else if (fc_isdigit(*format)) {
2341 const char *start = format;
2343 do {
2344 format++;
2345 } while (fc_isdigit(*format));
2346 if ('$' == *format) {
2347 /* Strings are reordered. */
2348 sscanf(start, "%d", &idx);
2349 reordered = TRUE;
2353 while ('\0' != *format
2354 && NULL == strchr(format_escapes, *format)) {
2355 format++;
2357 escapes[idx] = *format;
2359 /* Increase the read count. */
2360 if (reordered) {
2361 if (idx > num) {
2362 num = idx;
2364 } else {
2365 idx++;
2366 num++;
2369 if ('*' != *format) {
2370 format = strchr(format, '%');
2371 } /* else we didn't have found the real sequence. */
2373 return num;
2376 /****************************************************************************
2377 Returns TRUE iff both formats are compatible (if 'format1' can be used
2378 instead 'format2' and reciprocally).
2379 ****************************************************************************/
2380 bool formats_match(const char *format1, const char *format2)
2382 char format1_escapes[256], format2_escapes[256];
2383 size_t format1_escapes_num = extract_escapes(format1, format1_escapes,
2384 sizeof(format1_escapes));
2385 size_t format2_escapes_num = extract_escapes(format2, format2_escapes,
2386 sizeof(format2_escapes));
2388 return (format1_escapes_num == format2_escapes_num
2389 && 0 == memcmp(format1_escapes, format2_escapes,
2390 format1_escapes_num));