Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/clinet.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
clinet.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include "fc_prehdrs.h"
19
20#include <errno.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#ifdef FREECIV_HAVE_SYS_TYPES_H
26#include <sys/types.h>
27#endif
28#ifdef HAVE_SYS_SOCKET_H
29#include <sys/socket.h>
30#endif
31#ifdef HAVE_NETINET_IN_H
32#include <netinet/in.h>
33#endif
34#ifdef HAVE_ARPA_INET_H
35#include <arpa/inet.h>
36#endif
37#ifdef HAVE_NETDB_H
38#include <netdb.h>
39#endif
40#ifdef HAVE_PWD_H
41#include <pwd.h>
42#endif
43#ifdef HAVE_SYS_SELECT_H
44#include <sys/select.h>
45#endif
46#ifdef HAVE_SYS_TIME_H
47#include <sys/time.h>
48#endif
49#ifdef HAVE_SYS_UIO_H
50#include <sys/uio.h>
51#endif
52#ifdef HAVE_SYS_UTSNAME_H
53#include <sys/utsname.h>
54#endif
55#ifdef HAVE_UNISTD_H
56#include <unistd.h>
57#endif
58
59/* utility */
60#include "capstr.h"
61#include "dataio.h"
62#include "fcintl.h"
63#include "log.h"
64#include "mem.h"
65#include "netintf.h"
66#include "registry.h"
67#include "support.h"
68
69/* common */
70#include "game.h"
71#include "packets.h"
72#include "version.h"
73
74/* client */
75#include "agents.h"
76#include "attribute.h"
77#include "chatline_g.h"
78#include "client_main.h"
79#include "climisc.h"
80#include "connectdlg_common.h"
81#include "connectdlg_g.h"
82#include "dialogs_g.h" /* popdown_races_dialog() */
83#include "gui_main_g.h" /* add_net_input(), remove_net_input() */
84#include "mapview_common.h" /* unqueue_mapview_update */
85#include "menu_g.h"
86#include "messagewin_g.h"
87#include "options.h"
88#include "packhand.h"
89#include "pages_g.h"
90#include "plrdlg_g.h"
91#include "repodlgs_g.h"
92
93#include "clinet.h"
94
95/* In autoconnect mode, try to connect to once a second */
96#define AUTOCONNECT_INTERVAL 500
97
98/* In autoconnect mode, try to connect 100 times */
99#define MAX_AUTOCONNECT_ATTEMPTS 100
100
101extern char forced_tileset_name[512];
102 static struct fc_sockaddr_list *list = NULL;
103 static int name_count;
104
105/**********************************************************************/
109 static void close_socket_nomessage(struct connection *pc)
110{
111 connection_common_close(pc);
112 remove_net_input();
113 popdown_races_dialog();
114 close_connection_dialog();
115
116 set_client_state(C_S_DISCONNECTED);
117}
118
119/**********************************************************************/
123 static void client_conn_close_callback(struct connection *pconn)
124{
125 char reason[256];
126
127 if (NULL != pconn->closing_reason) {
128 fc_strlcpy(reason, pconn->closing_reason, sizeof(reason));
129 } else {
130 fc_strlcpy(reason, _("unknown reason"), sizeof(reason));
131 }
132
133 close_socket_nomessage(pconn);
134 /* If we lost connection to the internal server - kill it. */
135 client_kill_server(TRUE);
136 log_error("Lost connection to server: %s.", reason);
137 output_window_printf(ftc_client, _("Lost connection to server (%s)!"),
138 reason);
139}
140
141/**********************************************************************/
149 static int get_server_address(const char *hostname, int port,
150 char *errbuf, int errbufsize)
151{
152 if (port == 0) {
153#ifdef FREECIV_JSON_CONNECTION
154 port = FREECIV_JSON_PORT;
155#else /* FREECIV_JSON_CONNECTION */
156 port = DEFAULT_SOCK_PORT;
157#endif /* FREECIV_JSON_CONNECTION */
158 }
159
160 /* use name to find TCP/IP address of server */
161 if (!hostname) {
162 hostname = "localhost";
163 }
164
165 if (list != NULL) {
166 fc_sockaddr_list_destroy(list);
167 }
168
169 /* Any supported family will do */
170 list = net_lookup_service(hostname, port, FC_ADDR_ANY);
171
172 name_count = fc_sockaddr_list_size(list);
173
174 if (name_count <= 0) {
175 (void) fc_strlcpy(errbuf, _("Failed looking up host."), errbufsize);
176 return -1;
177 }
178
179 return 0;
180}
181
182/**********************************************************************/
193 static int try_to_connect(const char *username, char *errbuf, int errbufsize)
194{
195 int sock = -1;
196 fc_errno err = 0;
197
198 connections_set_close_callback(client_conn_close_callback);
199
200 /* connection in progress? wait. */
201 if (client.conn.used) {
202 (void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize);
203 return -1;
204 }
205
206 /* Try all (IPv4, IPv6, ...) addresses until we have a connection. */
207 sock = -1;
208 fc_sockaddr_list_iterate(list, paddr) {
209 if ((sock = socket(paddr->saddr.sa_family, SOCK_STREAM, 0)) == -1) {
210 if (err == 0) {
211 err = fc_get_errno();
212 }
213 /* Probably EAFNOSUPPORT or EPROTONOSUPPORT. */
214 continue;
215 }
216
217 if (fc_connect(sock, &paddr->saddr,
218 sockaddr_size(paddr)) == -1) {
219 err = fc_get_errno(); /* Save errno value before calling anything */
220 fc_closesocket(sock);
221 sock = -1;
222 continue;
223 } else {
224 /* We have a connection! */
225 break;
226 }
227 } fc_sockaddr_list_iterate_end;
228
229 client.conn.sock = sock;
230 if (client.conn.sock == -1) {
231 (void) fc_strlcpy(errbuf, fc_strerror(err), errbufsize);
232#ifdef FREECIV_HAVE_WINSOCK
233 return -1;
234#else
235 return err;
236#endif /* FREECIV_HAVE_WINSOCK */
237 }
238
239 make_connection(client.conn.sock, username);
240
241 return 0;
242}
243
244/**********************************************************************/
248 int connect_to_server(const char *username, const char *hostname, int port,
249 char *errbuf, int errbufsize)
250{
251 if (errbufsize > 0 && errbuf != NULL) {
252 errbuf[0] = '\0';
253 }
254
255 if (0 != get_server_address(hostname, port, errbuf, errbufsize)) {
256 return -1;
257 }
258
259 if (0 != try_to_connect(username, errbuf, errbufsize)) {
260 return -1;
261 }
262
263 if (gui_options.use_prev_server) {
264 sz_strlcpy(gui_options.default_server_host, hostname);
265 gui_options.default_server_port = port;
266 }
267
268 return 0;
269}
270
271/**********************************************************************/
274 void make_connection(int sock, const char *username)
275{
276 struct packet_server_join_req req;
277
278 connection_common_init(&client.conn);
279 client.conn.sock = sock;
280 client.conn.client.last_request_id_used = 0;
281 client.conn.client.last_processed_request_id_seen = 0;
282 client.conn.client.request_id_of_currently_handled_packet = 0;
283 client.conn.incoming_packet_notify = notify_about_incoming_packet;
284 client.conn.outgoing_packet_notify = notify_about_outgoing_packet;
285
286 /* call gui-dependent stuff in gui_main.c */
287 add_net_input(client.conn.sock);
288
289 /* now send join_request package */
290
291 req.major_version = MAJOR_VERSION;
292 req.minor_version = MINOR_VERSION;
293 req.patch_version = PATCH_VERSION;
294 sz_strlcpy(req.version_label, VERSION_LABEL);
295 sz_strlcpy(req.capability, our_capability);
296 sz_strlcpy(req.username, username);
297
298 send_packet_server_join_req(&client.conn, &req);
299}
300
301/**********************************************************************/
305 void disconnect_from_server(void)
306{
307 const bool force = !client.conn.used;
308
309 attribute_flush();
310
311 stop_turn_change_wait();
312
313 /* If it's internal server - kill it
314 * We assume that we are always connected to the internal server */
315 if (!force) {
316 client_kill_server(FALSE);
317 }
318 close_socket_nomessage(&client.conn);
319 if (force) {
320 client_kill_server(TRUE);
321 }
322 output_window_append(ftc_client, _("Disconnected from server."));
323
324 if (gui_options.save_options_on_exit) {
325 options_save(NULL);
326 }
327}
328
329/**********************************************************************/
340 static int read_from_connection(struct connection *pc, bool block)
341{
342 for (;;) {
343 fd_set readfs, writefs, exceptfs;
344 int socket_fd = pc->sock;
345 bool have_data_for_server = (pc->used && pc->send_buffer
346 && 0 < pc->send_buffer->ndata);
347 int n;
348 fc_timeval tv;
349
350 tv.tv_sec = 0;
351 tv.tv_usec = 0;
352
353 FC_FD_ZERO(&readfs);
354 FD_SET(socket_fd, &readfs);
355
356 FC_FD_ZERO(&exceptfs);
357 FD_SET(socket_fd, &exceptfs);
358
359 if (have_data_for_server) {
360 FC_FD_ZERO(&writefs);
361 FD_SET(socket_fd, &writefs);
362 n = fc_select(socket_fd + 1, &readfs, &writefs, &exceptfs,
363 block ? NULL : &tv);
364 } else {
365 n = fc_select(socket_fd + 1, &readfs, NULL, &exceptfs,
366 block ? NULL : &tv);
367 }
368
369 /* the socket is neither readable, writeable nor got an
370 * exception */
371 if (n == 0) {
372 return 0;
373 }
374
375 if (n == -1) {
376 if (errno == EINTR) {
377 /* EINTR can happen sometimes, especially when compiling with -pg.
378 * Generally we just want to run select again. */
379 log_debug("select() returned EINTR");
380 continue;
381 }
382
383 log_error("select() return=%d errno=%d (%s)",
384 n, errno, fc_strerror(fc_get_errno()));
385 return -1;
386 }
387
388 if (FD_ISSET(socket_fd, &exceptfs)) {
389 return -1;
390 }
391
392 if (have_data_for_server && FD_ISSET(socket_fd, &writefs)) {
393 flush_connection_send_buffer_all(pc);
394 }
395
396 if (FD_ISSET(socket_fd, &readfs)) {
397 return read_socket_data(socket_fd, pc->buffer);
398 }
399 }
400}
401
402/**********************************************************************/
406 void input_from_server(int fd)
407{
408 int nb;
409
410 fc_assert_ret(fd == client.conn.sock);
411
412 nb = read_from_connection(&client.conn, FALSE);
413 if (0 <= nb) {
414 agents_freeze_hint();
415 while (client.conn.used) {
416 enum packet_type type;
417 void *packet = get_packet_from_connection(&client.conn, &type);
418
419 if (NULL != packet) {
420 client_packet_input(packet, type);
421 free(packet);
422 } else {
423 break;
424 }
425 }
426 if (client.conn.used) {
427 agents_thaw_hint();
428 }
429 } else if (-2 == nb) {
430 connection_close(&client.conn, _("server disconnected"));
431 } else {
432 connection_close(&client.conn, _("read error"));
433 }
434}
435
436/**********************************************************************/
442 void input_from_server_till_request_got_processed(int fd,
443 int expected_request_id)
444{
445 fc_assert_ret(expected_request_id);
446 fc_assert_ret(fd == client.conn.sock);
447
448 log_debug("input_from_server_till_request_got_processed("
449 "expected_request_id=%d)", expected_request_id);
450
451 while (TRUE) {
452 int nb = read_from_connection(&client.conn, TRUE);
453
454 if (0 <= nb) {
455 enum packet_type type;
456
457 while (TRUE) {
458 void *packet = get_packet_from_connection(&client.conn, &type);
459 if (NULL == packet) {
460 break;
461 }
462
463 client_packet_input(packet, type);
464 free(packet);
465
466 if (type == PACKET_PROCESSING_FINISHED) {
467 log_debug("ifstrgp: expect=%d, seen=%d",
468 expected_request_id,
469 client.conn.client.last_processed_request_id_seen);
470 if (client.conn.client.last_processed_request_id_seen >=
471 expected_request_id) {
472 log_debug("ifstrgp: got it; returning");
473 return;
474 }
475 }
476 }
477 } else if (-2 == nb) {
478 connection_close(&client.conn, _("server disconnected"));
479 break;
480 } else {
481 connection_close(&client.conn, _("read error"));
482 break;
483 }
484 }
485}
486
487 static bool autoconnecting = FALSE;
488/**********************************************************************/
492 double try_to_autoconnect(void)
493{
494 char errbuf[512];
495 static int count = 0;
496#ifndef FREECIV_MSWINDOWS
497 static int warning_shown = 0;
498#endif
499
500 if (!autoconnecting) {
501 return FC_INFINITY;
502 }
503
504 count++;
505
506 if (count >= MAX_AUTOCONNECT_ATTEMPTS) {
507 log_fatal(_("Failed to contact server \"%s\" at port "
508 "%d as \"%s\" after %d attempts"),
509 server_host, server_port, user_name, count);
510 exit(EXIT_FAILURE);
511 }
512
513 switch (try_to_connect(user_name, errbuf, sizeof(errbuf))) {
514 case 0: /* Success! */
515 /* Don't call me again */
516 autoconnecting = FALSE;
517 return FC_INFINITY;
518#ifndef FREECIV_MSWINDOWS
519 /* See PR#4042 for more info on issues with try_to_connect() and errno. */
520 case ECONNREFUSED: /* Server not available (yet) */
521 if (!warning_shown) {
522 log_error("Connection to server refused. Please start the server.");
523 output_window_append(ftc_client, _("Connection to server refused. "
524 "Please start the server."));
525 warning_shown = 1;
526 }
527 /* Try again in 0.5 seconds */
528 return 0.001 * AUTOCONNECT_INTERVAL;
529#endif /* FREECIV_MSWINDOWS */
530 default: /* All other errors are fatal */
531 log_fatal(_("Error contacting server \"%s\" at port %d "
532 "as \"%s\":\n %s\n"),
533 server_host, server_port, user_name, errbuf);
534 exit(EXIT_FAILURE);
535 }
536
537 RETURN_VALUE_AFTER_EXIT(1.0);
538}
539
540/**********************************************************************/
547 void start_autoconnecting_to_server(void)
548{
549 char buf[512];
550
551 output_window_printf(ftc_client,
552 _("Auto-connecting to server \"%s\" at port %d "
553 "as \"%s\" every %f second(s) for %d times"),
554 server_host, server_port, user_name,
555 0.001 * AUTOCONNECT_INTERVAL,
556 MAX_AUTOCONNECT_ATTEMPTS);
557
558 if (get_server_address(server_host, server_port, buf, sizeof(buf)) < 0) {
559 log_fatal(_("Error contacting server \"%s\" at port %d "
560 "as \"%s\":\n %s\n"),
561 server_host, server_port, user_name, buf);
562 exit(EXIT_FAILURE);
563 }
564 autoconnecting = TRUE;
565}
agents_thaw_hint
void agents_thaw_hint(void)
Definition agents.c:436
agents_freeze_hint
void agents_freeze_hint(void)
Definition agents.c:427
agents.h
n
#define n
Definition astring.c:77
attribute_flush
void attribute_flush(void)
Definition attribute.c:327
attribute.h
our_capability
const char *const our_capability
Definition capstr.c:32
capstr.h
output_window_append
void output_window_append(const struct ft_color color, const char *featured_text)
Definition chatline_common.c:104
output_window_printf
void output_window_printf(const struct ft_color color, const char *format,...)
Definition chatline_common.c:153
chatline_g.h
user_name
char user_name[512]
Definition client_main.c:141
client_packet_input
void client_packet_input(void *packet, int type)
Definition client_main.c:777
server_host
char server_host[512]
Definition client_main.c:140
stop_turn_change_wait
void stop_turn_change_wait(void)
Definition client_main.c:1149
client
struct civclient client
Definition client_main.c:149
server_port
int server_port
Definition client_main.c:144
set_client_state
void set_client_state(enum client_states newstate)
Definition client_main.c:847
client_main.h
C_S_DISCONNECTED
@ C_S_DISCONNECTED
Definition client_main.h:45
climisc.h
start_autoconnecting_to_server
void start_autoconnecting_to_server(void)
Definition clinet.c:547
forced_tileset_name
char forced_tileset_name[512]
Definition client_main.c:136
list
static struct fc_sockaddr_list * list
Definition clinet.c:102
connect_to_server
int connect_to_server(const char *username, const char *hostname, int port, char *errbuf, int errbufsize)
Definition clinet.c:248
autoconnecting
static bool autoconnecting
Definition clinet.c:487
client_conn_close_callback
static void client_conn_close_callback(struct connection *pconn)
Definition clinet.c:123
make_connection
void make_connection(int sock, const char *username)
Definition clinet.c:274
read_from_connection
static int read_from_connection(struct connection *pc, bool block)
Definition clinet.c:340
AUTOCONNECT_INTERVAL
#define AUTOCONNECT_INTERVAL
Definition clinet.c:96
name_count
static int name_count
Definition clinet.c:103
try_to_connect
static int try_to_connect(const char *username, char *errbuf, int errbufsize)
Definition clinet.c:193
try_to_autoconnect
double try_to_autoconnect(void)
Definition clinet.c:492
MAX_AUTOCONNECT_ATTEMPTS
#define MAX_AUTOCONNECT_ATTEMPTS
Definition clinet.c:99
input_from_server_till_request_got_processed
void input_from_server_till_request_got_processed(int fd, int expected_request_id)
Definition clinet.c:442
input_from_server
void input_from_server(int fd)
Definition clinet.c:406
disconnect_from_server
void disconnect_from_server(void)
Definition clinet.c:305
close_socket_nomessage
static void close_socket_nomessage(struct connection *pc)
Definition clinet.c:109
get_server_address
static int get_server_address(const char *hostname, int port, char *errbuf, int errbufsize)
Definition clinet.c:149
clinet.h
client_kill_server
void client_kill_server(bool force)
Definition connectdlg_common.c:153
connectdlg_common.h
connectdlg_g.h
connections_set_close_callback
void connections_set_close_callback(conn_close_fn_t func)
Definition connection.c:80
flush_connection_send_buffer_all
void flush_connection_send_buffer_all(struct connection *pc)
Definition connection.c:229
connection_common_init
void connection_common_init(struct connection *pconn)
Definition connection.c:602
connection_close
void connection_close(struct connection *pconn, const char *reason)
Definition connection.c:88
connection_common_close
void connection_common_close(struct connection *pconn)
Definition connection.c:627
read_socket_data
int read_socket_data(int sock, struct socket_packet_buffer *buffer)
Definition connection.c:129
dataio.h
dialogs_g.h
fc_prehdrs.h
fcintl.h
_
#define _(String)
Definition fcintl.h:67
ftc_client
const struct ft_color ftc_client
Definition featured_text.c:78
game.h
close_connection_dialog
void close_connection_dialog(void)
Definition connectdlg.c:50
popdown_races_dialog
void popdown_races_dialog(void)
Definition dialogs.c:1238
remove_net_input
void remove_net_input(void)
Definition gui_main.c:2115
add_net_input
void add_net_input(int sock)
Definition gui_main.c:2097
type
GType type
Definition repodlgs.c:1312
gui_main_g.h
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_fatal
#define log_fatal(message,...)
Definition log.h:100
log_debug
#define log_debug(message,...)
Definition log.h:115
log_error
#define log_error(message,...)
Definition log.h:103
mapview_common.h
mem.h
menu_g.h
messagewin_g.h
FC_ADDR_ANY
@ FC_ADDR_ANY
Definition net_types.h:64
net_lookup_service
struct fc_sockaddr_list * net_lookup_service(const char *name, int port, enum fc_addr_family family)
Definition netintf.c:411
fc_closesocket
void fc_closesocket(int sock)
Definition netintf.c:186
sockaddr_size
int sockaddr_size(union fc_sockaddr *addr)
Definition netintf.c:305
fc_connect
int fc_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
Definition netintf.c:107
fc_select
int fc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, fc_timeval *timeout)
Definition netintf.c:125
netintf.h
fc_timeval
struct timeval fc_timeval
Definition netintf.h:90
fc_sockaddr_list_iterate_end
#define fc_sockaddr_list_iterate_end
Definition netintf.h:85
FC_FD_ZERO
#define FC_FD_ZERO(p)
Definition netintf.h:57
fc_sockaddr_list_iterate
#define fc_sockaddr_list_iterate(sockaddrlist, paddr)
Definition netintf.h:83
options_save
void options_save(option_save_log_callback log_cb)
Definition options.c:6053
gui_options
struct client_options gui_options
Definition options.c:71
options.h
packets.h
get_packet_from_connection
#define get_packet_from_connection(pc, ptype)
Definition packets.h:113
send_packet_server_join_req
int send_packet_server_join_req(struct connection *pc, const struct packet_server_join_req *packet)
Definition packets_gen.c:1989
packet_type
packet_type
Definition packets_gen.h:1883
PACKET_PROCESSING_FINISHED
@ PACKET_PROCESSING_FINISHED
Definition packets_gen.h:1885
notify_about_incoming_packet
void notify_about_incoming_packet(struct connection *pc, int packet_type, int size)
Definition packhand.c:5478
notify_about_outgoing_packet
void notify_about_outgoing_packet(struct connection *pc, int packet_type, int size, int request_id)
Definition packhand.c:5488
packhand.h
pages_g.h
plrdlg_g.h
registry.h
repodlgs_g.h
FC_INFINITY
#define FC_INFINITY
Definition shared.h:36
civclient::conn
struct connection conn
Definition client_main.h:96
client_options::default_server_port
int default_server_port
Definition options.h:109
client_options::use_prev_server
bool use_prev_server
Definition options.h:110
client_options::default_server_host
char default_server_host[512]
Definition options.h:108
client_options::save_options_on_exit
bool save_options_on_exit
Definition options.h:121
connection
Definition connection.h:141
connection::closing_reason
char * closing_reason
Definition connection.h:147
connection::client
struct connection::@57::@62 client
connection::request_id_of_currently_handled_packet
int request_id_of_currently_handled_packet
Definition connection.h:198
connection::last_request_id_used
int last_request_id_used
Definition connection.h:192
connection::incoming_packet_notify
void(* incoming_packet_notify)(struct connection *pc, int packet_type, int size)
Definition connection.h:253
connection::outgoing_packet_notify
void(* outgoing_packet_notify)(struct connection *pc, int packet_type, int size, int request_id)
Definition connection.h:261
connection::send_buffer
struct socket_packet_buffer * send_buffer
Definition connection.h:159
connection::sock
int sock
Definition connection.h:143
connection::last_processed_request_id_seen
int last_processed_request_id_seen
Definition connection.h:195
connection::buffer
struct socket_packet_buffer * buffer
Definition connection.h:158
connection::used
bool used
Definition connection.h:144
packet_server_join_req
Definition packets_gen.h:45
packet_server_join_req::version_label
char version_label[48]
Definition packets_gen.h:48
packet_server_join_req::capability
char capability[512]
Definition packets_gen.h:47
packet_server_join_req::minor_version
int minor_version
Definition packets_gen.h:50
packet_server_join_req::patch_version
int patch_version
Definition packets_gen.h:51
packet_server_join_req::major_version
int major_version
Definition packets_gen.h:49
packet_server_join_req::username
char username[48]
Definition packets_gen.h:46
socket_packet_buffer::ndata
int ndata
Definition connection.h:122
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
fc_strerror
const char * fc_strerror(fc_errno err)
Definition support.c:610
fc_get_errno
fc_errno fc_get_errno(void)
Definition support.c:593
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:161
RETURN_VALUE_AFTER_EXIT
#define RETURN_VALUE_AFTER_EXIT(_val_)
Definition support.h:121
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
fc_errno
int fc_errno
Definition support.h:115
version.h