Allow using things that were deprecated in gtk+-3.22.
[freeciv.git] / utility / support.c
blob430758677f3611dfb6f5f2025012bda266413840
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 /***********************************************************************
15 This module contains replacements for functions which are not
16 available on all platforms. Where the functions are available
17 natively, these are (mostly) just wrappers.
19 Notice the function names here are prefixed by, eg, "fc". An
20 alternative would be to use the "standard" function name, and
21 provide the implementation only if required. However the method
22 here has some advantages:
24 - We can provide definite prototypes in support.h, rather than
25 worrying about whether a system prototype exists, and if so where,
26 and whether it is correct. (Note that whether or not configure
27 finds a function and defines HAVE_FOO does not necessarily say
28 whether or not there is a _prototype_ for the function available.)
30 - We don't have to include fc_config.h in support.h, but can instead
31 restrict it to this .c file.
33 - We can add some extra stuff to these functions if we want.
35 The main disadvantage is remembering to use these "fc" functions on
36 systems which have the functions natively.
38 ***********************************************************************/
40 #ifdef HAVE_CONFIG_H
41 #include <fc_config.h>
42 #endif
44 #include "fc_prehdrs.h"
46 #include <ctype.h>
47 #include <errno.h>
48 #include <math.h> /* ceil() */
49 #include <stdarg.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sys/stat.h>
55 #ifdef GENERATING_MAC
56 #include <events.h> /* for WaitNextEvent() */
57 #endif
58 #ifdef HAVE_FCNTL_H
59 #include <fcntl.h>
60 #endif
61 #ifdef HAVE_SYS_IOCTL_H
62 #include <sys/ioctl.h>
63 #endif
64 #ifdef HAVE_SYS_SELECT_H
65 #include <sys/select.h>
66 #endif
67 #ifdef HAVE_SYS_TIME_H
68 #include <sys/time.h>
69 #endif
70 #ifdef FREECIV_HAVE_SYS_TYPES_H
71 #include <sys/types.h>
72 #endif
73 #ifdef HAVE_UNISTD_H
74 #include <unistd.h> /* usleep, fcntl, gethostname */
75 #endif
76 #ifdef HAVE_SYS_UTSNAME_H
77 #include <sys/utsname.h>
78 #endif
79 #ifdef FREECIV_HAVE_LIBZ
80 #include <zlib.h>
81 #endif
82 #ifdef WIN32_NATIVE
83 #include <process.h>
84 #include <windows.h>
85 #endif
86 #ifdef HAVE_STRINGS_H
87 # include <strings.h>
88 #endif
89 #ifdef HAVE_LIBGEN_H
90 /* POSIX version of basename() */
91 # include <libgen.h>
92 #endif
94 #ifdef FREECIV_HAVE_LIBZ
95 #include <zlib.h>
96 #endif
98 /* utility */
99 #include "fciconv.h"
100 #include "fcintl.h"
101 #include "log.h"
102 #include "mem.h"
103 #include "netintf.h"
105 #include "support.h"
107 /***************************************************************
108 Compare strings like strcmp(), but ignoring case.
109 ***************************************************************/
110 int fc_strcasecmp(const char *str0, const char *str1)
112 if (str0 == NULL) {
113 return -1;
115 if (str1 == NULL) {
116 return 1;
118 #ifdef HAVE_STRCASECMP
119 return strcasecmp (str0, str1);
120 #else
121 for (; fc_tolower(*str0) == fc_tolower(*str1); str0++, str1++) {
122 if (*str0 == '\0') {
123 return 0;
127 return ((int) (unsigned char) fc_tolower(*str0))
128 - ((int) (unsigned char) fc_tolower(*str1));
129 #endif /* HAVE_STRCASECMP */
132 /***************************************************************
133 Compare strings like strncmp(), but ignoring case.
134 ie, only compares first n chars.
135 ***************************************************************/
136 int fc_strncasecmp(const char *str0, const char *str1, size_t n)
138 if (str0 == NULL) {
139 return -1;
141 if (str1 == NULL) {
142 return 1;
144 #ifdef HAVE_STRNCASECMP
145 return strncasecmp (str0, str1, n);
146 #else
147 size_t i;
149 for (i = 0; i < n && fc_tolower(*str0) == fc_tolower(*str1);
150 i++, str0++, str1++) {
151 if (*str0 == '\0') {
152 return 0;
156 if (i == n)
157 return 0;
158 else
159 return ((int) (unsigned char) fc_tolower(*str0))
160 - ((int) (unsigned char) fc_tolower(*str1));
161 #endif /* HAVE_STRNCASECMP */
164 /****************************************************************************
165 Copies a string and convert the following characters:
166 - '\n' to "\\n".
167 - '\\' to "\\\\".
168 - '\"' to "\\\"".
169 See also remove_escapes().
170 ****************************************************************************/
171 void make_escapes(const char *str, char *buf, size_t buf_len)
173 char *dest = buf;
174 /* Sometimes we insert 2 characters at once ('\n' -> "\\n"), so keep
175 * place for '\0' and an extra character. */
176 const char *const max = buf + buf_len - 2;
178 while (*str != '\0' && dest < max) {
179 switch (*str) {
180 case '\n':
181 *dest++ = '\\';
182 *dest++ = 'n';
183 str++;
184 break;
185 case '\\':
186 case '\"':
187 *dest++ = '\\';
188 /* Fallthrough. */
189 default:
190 *dest++ = *str++;
191 break;
194 *dest = 0;
197 /****************************************************************************
198 Copies a string. Backslash followed by a genuine newline always
199 removes the newline.
200 If full_escapes is TRUE:
201 - '\n' -> newline translation.
202 - Other '\c' sequences (any character 'c') are just passed
203 through with the '\' removed (eg, includes '\\', '\"').
204 See also make_escapes().
205 ****************************************************************************/
206 void remove_escapes(const char *str, bool full_escapes,
207 char *buf, size_t buf_len)
209 char *dest = buf;
210 const char *const max = buf + buf_len - 1;
212 while (*str != '\0' && dest < max) {
213 if (*str == '\\' && *(str + 1) == '\n') {
214 /* Escape followed by newline. Skip both */
215 str += 2;
216 } else if (full_escapes && *str == '\\') {
217 str++;
218 if (*str == 'n') {
219 *dest++ = '\n';
220 str++;
222 } else {
223 *dest++ = *str++;
226 *dest = '\0';
229 /***************************************************************
230 Count length of string without possible surrounding quotes.
231 ***************************************************************/
232 size_t effectivestrlenquote(const char *str)
234 int len;
235 if (!str) {
236 return 0;
239 len = strlen(str);
241 if (str[0] == '"' && str[len-1] == '"') {
242 return len - 2;
245 return len;
248 /***************************************************************
249 Compare strings like strncasecmp() but ignoring surrounding
250 quotes in either string.
251 ***************************************************************/
252 int fc_strncasequotecmp(const char *str0, const char *str1, size_t n)
254 size_t i;
255 size_t len0;
256 size_t len1;
257 size_t cmplen;
259 if (str0 == NULL) {
260 return -1;
262 if (str1 == NULL) {
263 return 1;
266 len0 = strlen(str0); /* TODO: We iterate string once already here, */
267 len1 = strlen(str1); /* could iterate only once */
269 if (str0[0] == '"') {
270 if (str0[len0 - 1] == '"') {
271 /* Surrounded with quotes */
272 str0++;
273 len0 -= 2;
277 if (str1[0] == '"') {
278 if (str1[len1 - 1] == '"') {
279 /* Surrounded with quotes */
280 str1++;
281 len1 -= 2;
285 if (len0 < n || len1 < n) {
286 /* One of the strings is shorter than what should be compared... */
287 if (len0 != len1) {
288 /* ...and another is longer than it. */
289 return len0 - len1;
292 cmplen = len0; /* This avoids comparing ending quote */
293 } else {
294 cmplen = n;
297 for (i = 0; i < cmplen ; i++, str0++, str1++) {
298 if (fc_tolower(*str0) != fc_tolower(*str1)) {
299 return ((int) (unsigned char) fc_tolower(*str0))
300 - ((int) (unsigned char) fc_tolower(*str1));
304 /* All characters compared and all matched */
305 return 0;
308 /***************************************************************
309 Return the needle in the haystack (or NULL).
310 Naive implementation.
311 ***************************************************************/
312 char *fc_strcasestr(const char *haystack, const char *needle)
314 #ifdef HAVE_STRCASESTR
315 return strcasestr(haystack, needle);
316 #else
317 size_t haystacks;
318 size_t needles;
319 const char *p;
321 if (NULL == needle || '\0' == *needle) {
322 return (char *)haystack;
324 if (NULL == haystack || '\0' == *haystack) {
325 return NULL;
327 haystacks = strlen(haystack);
328 needles = strlen(needle);
329 if (haystacks < needles) {
330 return NULL;
333 for (p = haystack; p <= &haystack[haystacks - needles]; p++) {
334 if (0 == fc_strncasecmp(p, needle, needles)) {
335 return (char *)p;
338 return NULL;
339 #endif /* HAVE_STRCASESTR */
342 /****************************************************************************
343 Wrapper function for strcoll().
344 ****************************************************************************/
345 int fc_strcoll(const char *str0, const char *str1)
347 #if defined(ENABLE_NLS) && defined(HAVE_STRCOLL)
348 return strcoll(str0, str1);
349 #elif defined(ENABLE_NLS) && defined(HAVE__STRCOLL)
350 return _strcoll(str0, str1);
351 #else
352 return strcmp(str0, str1);
353 #endif
356 /****************************************************************************
357 Wrapper function for stricoll().
358 ****************************************************************************/
359 int fc_stricoll(const char *str0, const char *str1)
361 /* We prefer _stricoll() over stricoll() since
362 * latter is not declared in MinGW headers causing compiler
363 * warning, preventing -Werror builds. */
364 #if defined(ENABLE_NLS) && defined(HAVE__STRICOLL)
365 return _stricoll(str0, str1);
366 #elif defined(ENABLE_NLS) && defined(HAVE_STRICOLL)
367 return stricoll(str0, str1);
368 #elif defined(ENABLE_NLS) && defined(HAVE_STRCASECOLL)
369 return strcasecoll(str0, str1);
370 #else
371 return fc_strcasecmp(str0, str1);
372 #endif
375 /****************************************************************
376 Wrapper function for fopen() with filename conversion to local
377 encoding on Windows.
378 ****************************************************************/
379 FILE *fc_fopen(const char *filename, const char *opentype)
381 #ifdef WIN32_NATIVE
382 FILE *result;
383 char *filename_in_local_encoding =
384 internal_to_local_string_malloc(filename);
385 result = fopen(filename_in_local_encoding, opentype);
386 free(filename_in_local_encoding);
387 return result;
388 #else /* WIN32_NATIVE */
389 return fopen(filename, opentype);
390 #endif /* WIN32_NATIVE */
393 /*****************************************************************
394 Wrapper function for gzopen() with filename conversion to local
395 encoding on Windows.
396 *****************************************************************/
397 #ifdef FREECIV_HAVE_LIBZ
398 gzFile fc_gzopen(const char *filename, const char *opentype)
400 #ifdef WIN32_NATIVE
401 gzFile result;
402 char *filename_in_local_encoding =
403 internal_to_local_string_malloc(filename);
404 result = gzopen(filename_in_local_encoding, opentype);
405 free(filename_in_local_encoding);
406 return result;
407 #else /* WIN32_NATIVE */
408 return gzopen(filename, opentype);
409 #endif /* WIN32_NATIVE */
411 #endif /* FREECIV_HAVE_LIBZ */
413 /******************************************************************
414 Wrapper function for opendir() with filename conversion to local
415 encoding on Windows.
416 ******************************************************************/
417 DIR *fc_opendir(const char *dir_to_open)
419 #ifdef WIN32_NATIVE
420 DIR *result;
421 char *dirname_in_local_encoding =
422 internal_to_local_string_malloc(dir_to_open);
423 result = opendir(dirname_in_local_encoding);
424 free(dirname_in_local_encoding);
425 return result;
426 #else /* WIN32_NATIVE */
427 return opendir(dir_to_open);
428 #endif /* WIN32_NATIVE */
431 /*****************************************************************
432 Wrapper function for remove() with filename conversion to local
433 encoding on Windows.
434 *****************************************************************/
435 int fc_remove(const char *filename)
437 #ifdef WIN32_NATIVE
438 int result;
439 char *filename_in_local_encoding =
440 internal_to_local_string_malloc(filename);
441 result = remove(filename_in_local_encoding);
442 free(filename_in_local_encoding);
443 return result;
444 #else /* WIN32_NATIVE */
445 return remove(filename);
446 #endif /* WIN32_NATIVE */
449 /*****************************************************************
450 Wrapper function for stat() with filename conversion to local
451 encoding on Windows.
452 *****************************************************************/
453 int fc_stat(const char *filename, struct stat *buf)
455 #ifdef WIN32_NATIVE
456 int result;
457 char *filename_in_local_encoding =
458 internal_to_local_string_malloc(filename);
459 result = stat(filename_in_local_encoding, buf);
460 free(filename_in_local_encoding);
461 return result;
462 #else /* WIN32_NATIVE */
463 return stat(filename, buf);
464 #endif /* WIN32_NATIVE */
467 /***************************************************************
468 Returns last error code.
469 ***************************************************************/
470 fc_errno fc_get_errno(void)
472 #ifdef WIN32_NATIVE
473 return GetLastError();
474 #else
475 return errno;
476 #endif
479 /***************************************************************
480 Return a string which describes a given error (errno-style.)
481 The string is converted as necessary from the local_encoding
482 to internal_encoding, for inclusion in translations. May be
483 subsequently converted back to local_encoding for display.
485 Note that this is not the reentrant form.
486 ***************************************************************/
487 const char *fc_strerror(fc_errno err)
489 #ifdef WIN32_NATIVE
490 static char buf[256];
492 if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
493 NULL, err, 0, buf, sizeof(buf), NULL)) {
494 fc_snprintf(buf, sizeof(buf),
495 _("error %ld (failed FormatMessage)"), err);
497 return buf;
498 #else /* WIN32_NATIVE */
499 #ifdef HAVE_STRERROR
500 static char buf[256];
502 return local_to_internal_string_buffer(strerror(err),
503 buf, sizeof(buf));
504 #else /* HAVE_STRERROR */
505 static char buf[64];
507 fc_snprintf(buf, sizeof(buf),
508 _("error %d (compiled without strerror)"), err);
509 return buf;
510 #endif /* HAVE_STRERROR */
511 #endif /* WIN32_NATIVE */
515 /***************************************************************
516 Suspend execution for the specified number of microseconds.
517 ***************************************************************/
518 void fc_usleep(unsigned long usec)
520 #ifdef HAVE_USLEEP
521 usleep(usec);
522 #else /* HAVE_USLEEP */
523 #ifdef HAVE_SNOOZE /* BeOS */
524 snooze(usec);
525 #else /* HAVE_SNOOZE */
526 #ifdef GENERATING_MAC
527 EventRecord the_event; /* dummy - always be a null event */
528 usec /= 16666; /* microseconds to 1/60th seconds */
529 if (usec < 1) usec = 1;
530 /* suposed to give other application processor time for the mac */
531 WaitNextEvent(0, &the_event, usec, 0L);
532 #else /* GENERATING_MAC */
533 #ifdef WIN32_NATIVE
534 Sleep(usec / 1000);
535 #else /* WIN32_NATIVE */
536 fc_timeval tv;
538 tv.tv_sec = 0;
539 tv.tv_usec = usec;
540 /* FIXME: an interrupt can cause an EINTR return here. In that case we
541 * need to have another select call. */
542 fc_select(0, NULL, NULL, NULL, &tv);
543 #endif /* WIN32_NATIVE */
544 #endif /* GENERATING_MAC */
545 #endif /* HAVE_SNOOZE */
546 #endif /* HAVE_USLEEP */
549 /**************************************************************************
550 Replace 'search' by 'replace' within 'str'. If needed 'str' is resized
551 using realloc() to fit the modified string. The new pointer to the string
552 is returned.
553 **************************************************************************/
554 char *fc_strrep_resize(char *str, size_t *len, const char *search,
555 const char *replace)
557 size_t len_max;
558 bool success;
560 fc_assert_ret_val(str != NULL, NULL);
561 fc_assert_ret_val(len != NULL, NULL);
562 if (search == NULL || replace == NULL) {
563 return str;
566 len_max = ceil((double)strlen(str) * strlen(replace) / strlen(search)) + 1;
567 if ((*len) < len_max) {
568 /* replace string is longer than search string; allocated enough memory
569 * for the worst case */
570 (*len) = len_max;
571 str = fc_realloc(str, len_max);
574 success = fc_strrep(str, (*len), search, replace);
575 /* should never happen */
576 fc_assert_ret_val_msg(success == TRUE, NULL,
577 "Can't replace '%s' by '%s' in '%s'. To small "
578 "size after reallocation: %lu.", search, replace,
579 str, (long unsigned int)*len);
581 return str;
584 /**************************************************************************
585 Replace 'search' by 'replace' within 'str'. sizeof(str) should be large
586 enough for the modified value of 'str'. Returns TRUE if the replacement
587 was successful.
588 **************************************************************************/
589 bool fc_strrep(char *str, size_t len, const char *search,
590 const char *replace)
592 size_t len_search, len_replace;
593 char *s, *p;
595 fc_assert_ret_val(str != NULL, FALSE);
596 if (search == NULL || replace == NULL) {
597 return TRUE;
600 len_search = strlen(search);
601 len_replace = strlen(replace);
603 s = str;
604 while (s != NULL) {
605 p = strstr(s, search);
606 if (p == NULL) {
607 /* nothing found */
608 break;
611 if (len < (strlen(str) + len_replace - len_search + 1)) {
612 /* sizeof(str) not large enough to do the replacement */
613 return FALSE;
616 memmove(p + len_replace, p + len_search, strlen(p + len_search) + 1);
617 memcpy(p, replace, len_replace);
618 s = p + len_replace;
621 return TRUE;
624 /****************************************************************************
625 fc_strlcpy() and fc_strlcat() provide (non-standard) functions
626 strlcpy() and strlcat(), with semantics following OpenBSD (and
627 maybe others). They are intended as more user-friendly
628 versions of strncpy and strncat, in particular easier to
629 use safely and correctly, and ensuring nul-terminated results
630 while being able to detect truncation.
632 n is the full size of the destination buffer, including
633 space for trailing nul, and including the pre-existing
634 string for fc_strlcat(). Thus can eg use sizeof(buffer),
635 or exact size malloc-ed.
637 Result is always nul-terminated, whether or not truncation occurs,
638 and the return value is the strlen the destination would have had
639 without truncation. I.e., a return value >= input n indicates
640 truncation occurred.
642 Will assume that if configure found strlcpy/strlcat they are ok.
643 For replacement implementations, will keep it simple rather
644 than try for super-efficiency.
646 Not sure about the asserts below, but they are easier than
647 trying to ensure correct behaviour on strange inputs.
648 In particular note that n == 0 is prohibited (e.g., since there
649 must at least be room for a nul); could consider other options.
651 See also fc_utf8_strlcpy_trunc(), fc_utf8_strlcpy_rep().
652 ****************************************************************************/
653 size_t fc_strlcpy(char *dest, const char *src, size_t n)
655 fc_assert_ret_val(NULL != dest, -1);
656 fc_assert_ret_val(NULL != src, -1);
657 fc_assert_ret_val(0 < n, -1);
658 #ifdef HAVE_STRLCPY
659 return strlcpy(dest, src, n);
660 #else
662 size_t len = strlen(src);
663 size_t num_to_copy = (len >= n) ? n-1 : len;
664 if (num_to_copy>0)
665 memcpy(dest, src, num_to_copy);
666 dest[num_to_copy] = '\0';
667 return len;
669 #endif /* HAVE_STRLCPY */
672 /****************************************************************************
673 See also fc_utf8_strlcat_trunc(), fc_utf8_strlcat_rep().
674 ****************************************************************************/
675 size_t fc_strlcat(char *dest, const char *src, size_t n)
677 fc_assert_ret_val(NULL != dest, -1);
678 fc_assert_ret_val(NULL != src, -1);
679 fc_assert_ret_val(0 < n, -1);
680 #ifdef HAVE_STRLCAT
681 return strlcat(dest, src, n);
682 #else
684 size_t num_to_copy, len_dest, len_src;
686 len_dest = strlen(dest);
687 fc_assert_ret_val(len_dest < n, -1);
688 /* Otherwise have bad choice of leaving dest not nul-terminated
689 * within the specified length n (which should be assumable as
690 * a post-condition of fc_strlcat), or modifying dest before end
691 * of existing string (which breaks strcat semantics).
694 dest += len_dest;
695 n -= len_dest;
697 len_src = strlen(src);
698 num_to_copy = (len_src >= n) ? n-1 : len_src;
699 if (num_to_copy>0)
700 memcpy(dest, src, num_to_copy);
701 dest[num_to_copy] = '\0';
702 return len_dest + len_src;
704 #endif /* HAVE_STRLCAT */
707 /****************************************************************************
708 vsnprintf() replacement using a big malloc()ed internal buffer,
709 originally by David Pfitzner <dwp@mso.anu.edu.au>
711 Parameter n specifies the maximum number of characters to produce.
712 This includes the trailing null, so n should be the actual number
713 of characters allocated (or sizeof for char array). If truncation
714 occurs, the result will still be null-terminated. (I'm not sure
715 whether all native vsnprintf() functions null-terminate on
716 truncation; this does so even if calls native function.)
718 Return value: if there is no truncation, returns the number of
719 characters printed, not including the trailing null. If truncation
720 does occur, returns the number of characters which would have been
721 produced without truncation.
722 (Linux man page says returns -1 on truncation, but glibc seems to
723 do as above nevertheless; check_native_vsnprintf() above tests this.)
725 [glibc is correct. Viz.
727 PRINTF(3) Linux Programmer's Manual PRINTF(3)
729 (Thus until glibc 2.0.6. Since glibc 2.1 these functions follow the
730 C99 standard and return the number of characters (excluding the
731 trailing '\0') which would have been written to the final string if
732 enough space had been available.)]
734 The method is simply to malloc (first time called) a big internal
735 buffer, longer than any result is likely to be (for non-malicious
736 usage), then vsprintf to that buffer, and copy the appropriate
737 number of characters to the destination. Thus, this is not 100%
738 safe. But somewhat safe, and at least safer than using raw snprintf!
739 :-) (And of course if you have the native version it is safe.)
741 Before rushing to provide a 100% safe replacement version, consider
742 the following advantages of this method:
744 - It is very simple, so not likely to have many bugs (other than
745 arguably the core design bug regarding absolute safety), nor need
746 maintenance.
748 - It uses native vsprintf() (which is required), thus exactly
749 duplicates the native format-string parsing/conversions.
751 - It is *very* portable. Eg, it does not require mprotect(), nor
752 does it do any of its own parsing of the format string, nor use
753 any tricks to go through the va_list twice.
755 See also fc_utf8_vsnprintf_trunc(), fc_utf8_vsnprintf_rep().
756 ****************************************************************************/
758 /* "64k should be big enough for anyone" ;-) */
759 #define VSNP_BUF_SIZE (64*1024)
760 int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
762 #ifdef HAVE_WORKING_VSNPRINTF
763 int r;
764 #endif
766 /* This may be overzealous, but I suspect any triggering of these to
767 * be bugs. */
769 fc_assert_ret_val(NULL != str, -1);
770 fc_assert_ret_val(0 < n, -1);
771 fc_assert_ret_val(NULL != format, -1);
773 #ifdef HAVE_WORKING_VSNPRINTF
774 r = vsnprintf(str, n, format, ap);
775 str[n - 1] = 0;
777 /* Convert C99 return value to C89. */
778 if (r >= n) {
779 return -1;
782 return r;
783 #else /* HAVE_WORKING_VSNPRINTF */
785 /* Don't use fc_malloc() or log_*() here, since they may call
786 fc_vsnprintf() if it fails. */
788 static char *buf;
789 size_t len;
791 if (!buf) {
792 buf = malloc(VSNP_BUF_SIZE);
794 if (!buf) {
795 fprintf(stderr, "Could not allocate %i bytes for vsnprintf() "
796 "replacement.", VSNP_BUF_SIZE);
797 exit(EXIT_FAILURE);
800 #ifdef HAVE_VSNPRINTF
801 vsnprintf(buf, n, format, ap);
802 #else
803 vsprintf(buf, format, ap);
804 #endif /* HAVE_VSNPRINTF */
805 buf[VSNP_BUF_SIZE - 1] = '\0';
806 len = strlen(buf);
808 if (len >= VSNP_BUF_SIZE - 1) {
809 fprintf(stderr, "Overflow in vsnprintf replacement!"
810 " (buffer size %d) aborting...\n", VSNP_BUF_SIZE);
811 abort();
813 if (n >= len + 1) {
814 memcpy(str, buf, len+1);
815 return len;
816 } else {
817 memcpy(str, buf, n-1);
818 str[n - 1] = '\0';
819 return -1;
822 #endif /* HAVE_WORKING_VSNPRINTF */
825 /****************************************************************************
826 See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
827 ****************************************************************************/
828 int fc_snprintf(char *str, size_t n, const char *format, ...)
830 int ret;
831 va_list ap;
833 fc_assert_ret_val(NULL != format, -1);
835 va_start(ap, format);
836 ret = fc_vsnprintf(str, n, format, ap);
837 va_end(ap);
838 return ret;
841 /****************************************************************************
842 cat_snprintf is like a combination of fc_snprintf and fc_strlcat;
843 it does snprintf to the end of an existing string.
845 Like fc_strlcat, n is the total length available for str, including
846 existing contents and trailing nul. If there is no extra room
847 available in str, does not change the string.
849 Also like fc_strlcat, returns the final length that str would have
850 had without truncation, or -1 if the end of the buffer is reached.
851 I.e., if return is >= n, truncation occurred.
853 See also cat_utf8_snprintf(), cat_utf8_snprintf_rep().
854 ****************************************************************************/
855 int cat_snprintf(char *str, size_t n, const char *format, ...)
857 size_t len;
858 int ret;
859 va_list ap;
861 fc_assert_ret_val(NULL != format, -1);
862 fc_assert_ret_val(NULL != str, -1);
863 fc_assert_ret_val(0 < n, -1);
865 len = strlen(str);
866 fc_assert_ret_val(len < n, -1);
868 va_start(ap, format);
869 ret = fc_vsnprintf(str+len, n-len, format, ap);
870 va_end(ap);
871 return (-1 == ret ? -1 : ret + len);
874 /**********************************************************************
875 Call gethostname() if supported, else just returns -1.
876 ***********************************************************************/
877 int fc_gethostname(char *buf, size_t len)
879 #ifdef HAVE_GETHOSTNAME
880 return gethostname(buf, len);
881 #else
882 return -1;
883 #endif
886 #ifdef FREECIV_SOCKET_ZERO_NOT_STDIN
887 /**********************************************************************
888 Support for console I/O in case FREECIV_SOCKET_ZERO_NOT_STDIN.
889 ***********************************************************************/
891 #define CONSOLE_BUF_SIZE 100
892 static char console_buf[CONSOLE_BUF_SIZE + 1];
894 /**********************************************************************/
896 #ifdef WIN32_NATIVE
897 static HANDLE console_thread = INVALID_HANDLE_VALUE;
899 static DWORD WINAPI thread_proc(LPVOID arg)
901 if (fgets(console_buf, CONSOLE_BUF_SIZE, stdin)) {
902 char *s;
904 if ((s = strchr(console_buf, '\n'))) {
905 *s = '\0';
909 return 0;
911 #endif /* WIN32_NATIVE */
913 /**********************************************************************
914 Initialize console I/O in case FREECIV_SOCKET_ZERO_NOT_STDIN.
915 ***********************************************************************/
916 void fc_init_console(void)
918 #ifdef WIN32_NATIVE
919 DWORD threadid;
921 if (console_thread != INVALID_HANDLE_VALUE) {
922 return;
925 console_buf[0] = '\0';
926 console_thread = (HANDLE) CreateThread(NULL, 0, thread_proc, NULL, 0, &threadid);
927 #else /* WIN32_NATIVE */
928 static bool initialized = FALSE;
930 if (!initialized) {
931 initialized = TRUE;
932 #ifdef HAVE_FILENO
933 fc_nonblock(fileno(stdin));
934 #endif
936 #endif /* WIN32_NATIVE */
939 /**********************************************************************
940 Read a line from console I/O in case FREECIV_SOCKET_ZERO_NOT_STDIN.
942 This returns a pointer to a statically allocated buffer.
943 Subsequent calls to fc_read_console() or fc_init_console() will
944 overwrite it.
945 ***********************************************************************/
946 char *fc_read_console(void)
948 #ifdef WIN32_NATIVE
949 if (WaitForSingleObject(console_thread, 0) == WAIT_OBJECT_0) {
950 CloseHandle(console_thread);
951 console_thread = INVALID_HANDLE_VALUE;
953 return console_buf;
956 return NULL;
957 #else /* WIN32_NATIVE */
958 if (!feof(stdin)) { /* input from server operator */
959 static char *bufptr = console_buf;
961 /* fetch chars until \n, or run out of space in buffer */
962 /* blocks if fc_nonblock() in fc_init_console() failed */
963 while ((*bufptr = fgetc(stdin)) != EOF) {
964 if (*bufptr == '\n') {
965 *bufptr = '\0';
967 if (*bufptr == '\0') {
968 bufptr = console_buf;
970 return console_buf;
972 if ((bufptr - console_buf) <= CONSOLE_BUF_SIZE) {
973 bufptr++; /* prevent overrun */
978 return NULL;
979 #endif /* WIN32_NATIVE */
982 #endif /* FREECIV_SOCKET_ZERO_NOT_STDIN */
984 /**********************************************************************
985 Returns TRUE iff the file is a regular file or a link to a regular
986 file or write_access is TRUE and the file doesn't exists yet.
987 ***********************************************************************/
988 bool is_reg_file_for_access(const char *name, bool write_access)
990 struct stat tmp;
992 if (fc_stat(name, &tmp) == 0) {
993 return S_ISREG(tmp.st_mode);
994 } else {
995 return write_access && errno == ENOENT;
999 /****************************************************************************
1000 Replace the spaces by line breaks when the line lenght is over the desired
1001 one. 'str' is modified. Returns number of lines in modified s.
1002 ****************************************************************************/
1003 int fc_break_lines(char *str, size_t desired_len)
1005 size_t slen = (size_t)strlen(str);
1006 int num_lines = 0;
1008 /* At top of this loop, s points to the rest of string,
1009 * either at start or after inserted newline: */
1010 top:
1011 if (str && *str != '\0' && slen > desired_len) {
1012 char *c;
1014 num_lines++;
1016 /* check if there is already a newline: */
1017 for (c = str; c < str + desired_len; c++) {
1018 if (*c == '\n') {
1019 slen -= c + 1 - str;
1020 str = c + 1;
1021 goto top;
1025 /* find space and break: */
1026 for(c = str + desired_len; c > str; c--) {
1027 if (fc_isspace(*c)) {
1028 *c = '\n';
1029 slen -= c + 1 - str;
1030 str = c + 1;
1031 goto top;
1035 /* couldn't find a good break; settle for a bad one... */
1036 for (c = str + desired_len + 1; *c != '\0'; c++) {
1037 if (fc_isspace(*c)) {
1038 *c = '\n';
1039 slen -= c + 1 - str;
1040 str = c + 1;
1041 goto top;
1046 return num_lines;
1049 /****************************************************************************
1050 Character function wrappers
1052 These functions are wrappers for the libc character class functions,
1053 without any locale-dependent behavior. The character functions work as
1054 documented for ASCII. Bytes outside of the ASCII set will not be reported
1055 to belong to any character class, and will be left unchanged by
1056 transformations. This behavior is safe but not strictly correct
1057 forsingle-byte 8-bit- or UTF-8 encoded text; in UTF-8, any byte that is
1058 part of a multibyte sequence is non-ASCII.
1059 ****************************************************************************/
1061 /****************************************************************************
1062 Wrapper function to work around broken libc implementations. See above.
1063 ****************************************************************************/
1064 bool fc_isalnum(char c)
1066 if (128 <= (unsigned char) c) {
1067 return FALSE;
1069 return isalnum((int) ((unsigned char) c)) != 0;
1072 /****************************************************************************
1073 Wrapper function to work around broken libc implementations. See above.
1074 ****************************************************************************/
1075 bool fc_isalpha(char c)
1077 if (128 <= (unsigned char) c) {
1078 return FALSE;
1080 return isalpha((int) ((unsigned char) c)) != 0;
1083 /****************************************************************************
1084 Wrapper function to work around broken libc implementations. See above.
1085 ****************************************************************************/
1086 bool fc_isdigit(char c)
1088 if (128 <= (unsigned char) c) {
1089 return FALSE;
1091 return isdigit((int) ((unsigned char) c)) != 0;
1094 /****************************************************************************
1095 Wrapper function to work around broken libc implementations. See above.
1096 ****************************************************************************/
1097 bool fc_isprint(char c)
1099 if (128 <= (unsigned char) c) {
1100 return FALSE;
1102 return isprint((int) ((unsigned char) c)) != 0;
1105 /****************************************************************************
1106 Wrapper function to work around broken libc implementations. See above.
1107 ****************************************************************************/
1108 bool fc_isspace(char c)
1110 if (128 <= (unsigned char) c) {
1111 return FALSE;
1113 return isspace((int) ((unsigned char) c)) != 0;
1116 /****************************************************************************
1117 Wrapper function to work around broken libc implementations. See above.
1118 ****************************************************************************/
1119 bool fc_isupper(char c)
1121 if (128 <= (unsigned char) c) {
1122 return FALSE;
1124 return isupper((int) ((unsigned char) c)) != 0;
1127 /****************************************************************************
1128 Wrapper function to work around broken libc implementations. See above.
1129 ****************************************************************************/
1130 char fc_toupper(char c)
1132 if (128 <= (unsigned char) c) {
1133 return c;
1135 return (char) toupper((int) ((unsigned char) c));
1138 /****************************************************************************
1139 Wrapper function to work around broken libc implementations. See above.
1140 ****************************************************************************/
1141 char fc_tolower(char c)
1143 if (128 <= (unsigned char) c) {
1144 return c;
1146 return (char) tolower((int) ((unsigned char) c));
1149 /*****************************************************************
1150 basename() replacement that always takes const parameter.
1151 POSIX basename() modifies its parameter, GNU one does not.
1152 Ideally we would like to use GNU one, when available, directly
1153 without extra string copies.
1154 *****************************************************************/
1155 const char *fc_basename(const char *path)
1157 static char buf[2048];
1159 /* Copy const parameter string to buffer that basename() can
1160 * modify */
1161 fc_strlcpy(buf, path, sizeof(buf));
1163 return basename(buf);
1166 /*****************************************************************
1167 Set quick_exit() callback if possible.
1168 *****************************************************************/
1169 int fc_at_quick_exit(void (*func)(void))
1171 #ifdef HAVE_AT_QUICK_EXIT
1172 return at_quick_exit(func);
1173 #else /* HAVE_AT_QUICK_EXIT */
1174 return -1;
1175 #endif /* HAVE_AT_QUICK_EXIT */