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)
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 ***********************************************************************/
41 #include <fc_config.h>
44 #include "fc_prehdrs.h"
48 #include <math.h> /* ceil() */
56 #include <events.h> /* for WaitNextEvent() */
61 #ifdef HAVE_SYS_IOCTL_H
62 #include <sys/ioctl.h>
64 #ifdef HAVE_SYS_SELECT_H
65 #include <sys/select.h>
67 #ifdef HAVE_SYS_TIME_H
70 #ifdef FREECIV_HAVE_SYS_TYPES_H
71 #include <sys/types.h>
74 #include <unistd.h> /* usleep, fcntl, gethostname */
76 #ifdef HAVE_SYS_UTSNAME_H
77 #include <sys/utsname.h>
79 #ifdef FREECIV_HAVE_LIBZ
90 /* POSIX version of basename() */
94 #ifdef FREECIV_HAVE_LIBZ
107 /***************************************************************
108 Compare strings like strcmp(), but ignoring case.
109 ***************************************************************/
110 int fc_strcasecmp(const char *str0
, const char *str1
)
118 #ifdef HAVE_STRCASECMP
119 return strcasecmp (str0
, str1
);
121 for (; fc_tolower(*str0
) == fc_tolower(*str1
); str0
++, str1
++) {
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
)
144 #ifdef HAVE_STRNCASECMP
145 return strncasecmp (str0
, str1
, n
);
149 for (i
= 0; i
< n
&& fc_tolower(*str0
) == fc_tolower(*str1
);
150 i
++, str0
++, str1
++) {
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:
169 See also remove_escapes().
170 ****************************************************************************/
171 void make_escapes(const char *str
, char *buf
, size_t buf_len
)
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
) {
197 /****************************************************************************
198 Copies a string. Backslash followed by a genuine newline always
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
)
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 */
216 } else if (full_escapes
&& *str
== '\\') {
229 /***************************************************************
230 Count length of string without possible surrounding quotes.
231 ***************************************************************/
232 size_t effectivestrlenquote(const char *str
)
241 if (str
[0] == '"' && str
[len
-1] == '"') {
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
)
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 */
277 if (str1
[0] == '"') {
278 if (str1
[len1
- 1] == '"') {
279 /* Surrounded with quotes */
285 if (len0
< n
|| len1
< n
) {
286 /* One of the strings is shorter than what should be compared... */
288 /* ...and another is longer than it. */
292 cmplen
= len0
; /* This avoids comparing ending quote */
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 */
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
);
321 if (NULL
== needle
|| '\0' == *needle
) {
322 return (char *)haystack
;
324 if (NULL
== haystack
|| '\0' == *haystack
) {
327 haystacks
= strlen(haystack
);
328 needles
= strlen(needle
);
329 if (haystacks
< needles
) {
333 for (p
= haystack
; p
<= &haystack
[haystacks
- needles
]; p
++) {
334 if (0 == fc_strncasecmp(p
, needle
, needles
)) {
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
);
352 return strcmp(str0
, str1
);
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
);
371 return fc_strcasecmp(str0
, str1
);
375 /****************************************************************
376 Wrapper function for fopen() with filename conversion to local
378 ****************************************************************/
379 FILE *fc_fopen(const char *filename
, const char *opentype
)
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
);
388 #else /* WIN32_NATIVE */
389 return fopen(filename
, opentype
);
390 #endif /* WIN32_NATIVE */
393 /*****************************************************************
394 Wrapper function for gzopen() with filename conversion to local
396 *****************************************************************/
397 #ifdef FREECIV_HAVE_LIBZ
398 gzFile
fc_gzopen(const char *filename
, const char *opentype
)
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
);
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
416 ******************************************************************/
417 DIR *fc_opendir(const char *dir_to_open
)
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
);
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
434 *****************************************************************/
435 int fc_remove(const char *filename
)
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
);
444 #else /* WIN32_NATIVE */
445 return remove(filename
);
446 #endif /* WIN32_NATIVE */
449 /*****************************************************************
450 Wrapper function for stat() with filename conversion to local
452 *****************************************************************/
453 int fc_stat(const char *filename
, struct stat
*buf
)
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
);
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)
473 return GetLastError();
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
)
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
);
498 #else /* WIN32_NATIVE */
500 static char buf
[256];
502 return local_to_internal_string_buffer(strerror(err
),
504 #else /* HAVE_STRERROR */
507 fc_snprintf(buf
, sizeof(buf
),
508 _("error %d (compiled without strerror)"), err
);
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
)
522 #else /* HAVE_USLEEP */
523 #ifdef HAVE_SNOOZE /* BeOS */
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 */
535 #else /* WIN32_NATIVE */
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
553 **************************************************************************/
554 char *fc_strrep_resize(char *str
, size_t *len
, const char *search
,
560 fc_assert_ret_val(str
!= NULL
, NULL
);
561 fc_assert_ret_val(len
!= NULL
, NULL
);
562 if (search
== NULL
|| replace
== NULL
) {
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 */
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
);
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
588 **************************************************************************/
589 bool fc_strrep(char *str
, size_t len
, const char *search
,
592 size_t len_search
, len_replace
;
595 fc_assert_ret_val(str
!= NULL
, FALSE
);
596 if (search
== NULL
|| replace
== NULL
) {
600 len_search
= strlen(search
);
601 len_replace
= strlen(replace
);
605 p
= strstr(s
, search
);
611 if (len
< (strlen(str
) + len_replace
- len_search
+ 1)) {
612 /* sizeof(str) not large enough to do the replacement */
616 memmove(p
+ len_replace
, p
+ len_search
, strlen(p
+ len_search
) + 1);
617 memcpy(p
, replace
, len_replace
);
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
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);
659 return strlcpy(dest
, src
, n
);
662 size_t len
= strlen(src
);
663 size_t num_to_copy
= (len
>= n
) ? n
-1 : len
;
665 memcpy(dest
, src
, num_to_copy
);
666 dest
[num_to_copy
] = '\0';
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);
681 return strlcat(dest
, src
, n
);
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).
697 len_src
= strlen(src
);
698 num_to_copy
= (len_src
>= n
) ? n
-1 : len_src
;
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
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
766 /* This may be overzealous, but I suspect any triggering of these to
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
);
777 /* Convert C99 return value to C89. */
783 #else /* HAVE_WORKING_VSNPRINTF */
785 /* Don't use fc_malloc() or log_*() here, since they may call
786 fc_vsnprintf() if it fails. */
792 buf
= malloc(VSNP_BUF_SIZE
);
795 fprintf(stderr
, "Could not allocate %i bytes for vsnprintf() "
796 "replacement.", VSNP_BUF_SIZE
);
800 #ifdef HAVE_VSNPRINTF
801 vsnprintf(buf
, n
, format
, ap
);
803 vsprintf(buf
, format
, ap
);
804 #endif /* HAVE_VSNPRINTF */
805 buf
[VSNP_BUF_SIZE
- 1] = '\0';
808 if (len
>= VSNP_BUF_SIZE
- 1) {
809 fprintf(stderr
, "Overflow in vsnprintf replacement!"
810 " (buffer size %d) aborting...\n", VSNP_BUF_SIZE
);
814 memcpy(str
, buf
, len
+1);
817 memcpy(str
, buf
, n
-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
, ...)
833 fc_assert_ret_val(NULL
!= format
, -1);
835 va_start(ap
, format
);
836 ret
= fc_vsnprintf(str
, n
, format
, ap
);
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
, ...)
861 fc_assert_ret_val(NULL
!= format
, -1);
862 fc_assert_ret_val(NULL
!= str
, -1);
863 fc_assert_ret_val(0 < n
, -1);
866 fc_assert_ret_val(len
< n
, -1);
868 va_start(ap
, format
);
869 ret
= fc_vsnprintf(str
+len
, n
-len
, format
, 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
);
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 /**********************************************************************/
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
)) {
904 if ((s
= strchr(console_buf
, '\n'))) {
911 #endif /* WIN32_NATIVE */
913 /**********************************************************************
914 Initialize console I/O in case FREECIV_SOCKET_ZERO_NOT_STDIN.
915 ***********************************************************************/
916 void fc_init_console(void)
921 if (console_thread
!= INVALID_HANDLE_VALUE
) {
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
;
933 fc_nonblock(fileno(stdin
));
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
945 ***********************************************************************/
946 char *fc_read_console(void)
949 if (WaitForSingleObject(console_thread
, 0) == WAIT_OBJECT_0
) {
950 CloseHandle(console_thread
);
951 console_thread
= INVALID_HANDLE_VALUE
;
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') {
967 if (*bufptr
== '\0') {
968 bufptr
= console_buf
;
972 if ((bufptr
- console_buf
) <= CONSOLE_BUF_SIZE
) {
973 bufptr
++; /* prevent overrun */
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
)
992 if (fc_stat(name
, &tmp
) == 0) {
993 return S_ISREG(tmp
.st_mode
);
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
);
1008 /* At top of this loop, s points to the rest of string,
1009 * either at start or after inserted newline: */
1011 if (str
&& *str
!= '\0' && slen
> desired_len
) {
1016 /* check if there is already a newline: */
1017 for (c
= str
; c
< str
+ desired_len
; c
++) {
1019 slen
-= c
+ 1 - str
;
1025 /* find space and break: */
1026 for(c
= str
+ desired_len
; c
> str
; c
--) {
1027 if (fc_isspace(*c
)) {
1029 slen
-= c
+ 1 - str
;
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
)) {
1039 slen
-= c
+ 1 - str
;
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
) {
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
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 */
1175 #endif /* HAVE_AT_QUICK_EXIT */