1 /* source: xioinitialize.c */
2 /* Copyright Gerhard Rieger 2001-2011 */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for the initialize function */
7 #include "xiosysincludes.h"
10 #include "xiolockfile.h"
12 #include "xio-openssl.h" /* xio_reset_fips_mode() */
14 static int xioinitialized
;
15 xiofile_t
*sock
[XIO_MAXSOCK
];
16 int (*xiohook_newchild
)(void); /* xio calls this function from a new child
20 /* returns 0 on success or != if an error occurred */
21 int xioinitialize(void) {
22 if (xioinitialized
) return 0;
24 /* configure and .h's cannot guarantee this */
25 assert(sizeof(uint8_t)==1);
26 assert(sizeof(uint16_t)==2);
27 assert(sizeof(uint32_t)==4);
29 /* assertions regarding O_ flags - important for XIO_READABLE() etc. */
38 /* some assertions about termios */
40 #if defined(CRDLY) && CRDLY_SHIFT >= 0
41 assert(3 << opt_crdly
.arg3
== CRDLY
);
43 #if defined(TABDLY) && TABDLY_SHIFT >= 0
44 assert(3 << opt_tabdly
.arg3
== TABDLY
);
47 assert(3 << opt_csize
.arg3
== CSIZE
);
51 struct termios termarg
;
53 #if HAVE_TERMIOS_ISPEED
54 speed_t speeds
[sizeof(struct termios
)/sizeof(speed_t
)];
57 tdata
.termarg
.c_iflag
= 0x12345678;
58 tdata
.termarg
.c_oflag
= 0x23456789;
59 tdata
.termarg
.c_cflag
= 0x3456789a;
60 tdata
.termarg
.c_lflag
= 0x456789ab;
61 assert(tdata
.termarg
.c_iflag
== tdata
.flags
[0]);
62 assert(tdata
.termarg
.c_oflag
== tdata
.flags
[1]);
63 assert(tdata
.termarg
.c_cflag
== tdata
.flags
[2]);
64 assert(tdata
.termarg
.c_lflag
== tdata
.flags
[3]);
65 #if HAVE_TERMIOS_ISPEED && (ISPEED_OFFSET != -1) && (OSPEED_OFFSET != -1)
66 #if defined(ISPEED_OFFSET) && (ISPEED_OFFSET != -1)
67 #if defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
68 tdata
.termarg
.c_ispeed
= 0x56789abc;
69 tdata
.termarg
.c_ospeed
= 0x6789abcd;
70 assert(tdata
.termarg
.c_ispeed
== tdata
.speeds
[ISPEED_OFFSET
]);
71 assert(tdata
.termarg
.c_ospeed
== tdata
.speeds
[OSPEED_OFFSET
]);
78 /* these dependencies required in applyopts() for OFUNC_FCNTL */
79 assert(F_GETFD
== F_SETFD
-1);
80 assert(F_GETFL
== F_SETFL
-1);
83 const char *default_ip
;
84 default_ip
= getenv("SOCAT_DEFAULT_LISTEN_IP");
85 if (default_ip
!= NULL
) {
86 switch (default_ip
[0]) {
89 xioopts
.default_ip
= default_ip
[0]; break;
94 const char *preferred_ip
;
95 preferred_ip
= getenv("SOCAT_PREFERRED_RESOLVE_IP");
96 if (preferred_ip
!= NULL
) {
97 switch (preferred_ip
[0]) {
100 xioopts
.preferred_ip
= preferred_ip
[0]; break;
102 xioopts
.preferred_ip
= '0'; break;
107 if (Atexit(xioexit
) < 0) {
108 Error("atexit(xioexit) failed");
116 /* call this function when option -lp (reset program name) has been applied */
117 int xioinitialize2(void) {
118 pid_t pid
= Getpid();
119 xiosetenvulong("PID", pid
, 1);
120 xiosetenvulong("PPID", pid
, 1);
125 /* well, this function is not for initialization, but I could not find a better
127 it is called in the child process after fork
128 it drops the locks of the xiofile's so only the parent owns them
130 void xiodroplocks(void) {
133 for (i
= 0; i
< XIO_MAXSOCK
; ++i
) {
134 if (sock
[i
] != NULL
&& sock
[i
]->tag
!= XIO_TAG_INVALID
) {
135 xiofiledroplock(sock
[i
]);
141 /* consider an invokation like this:
142 socat -u exec:'some program that accepts data' tcp-l:...,fork
143 we do not want the program to be killed by the first tcp-l sub process, it's
144 better if it survives all sub processes. Thus, it must not be killed when
145 the sub process delivers EOF. Also, a socket that is reused in sub processes
146 should not be shut down (affects the connection), but closed (affects only
147 sub processes copy of file descriptor) */
148 static int xio_nokill(xiofile_t
*sock
) {
151 case XIO_TAG_INVALID
:
155 if ((result
= xio_nokill((xiofile_t
*)sock
->dual
.stream
[0])) != 0)
157 result
= xio_nokill((xiofile_t
*)sock
->dual
.stream
[1]);
162 /* here is the core of this function */
163 switch (sock
->stream
.howtoend
) {
164 case END_SHUTDOWN_KILL
: sock
->stream
.howtoend
= END_CLOSE
; break;
165 case END_CLOSE_KILL
: sock
->stream
.howtoend
= END_CLOSE
; break;
166 case END_SHUTDOWN
: sock
->stream
.howtoend
= END_CLOSE
; break;
174 /* call this function immediately after fork() in child process */
175 /* it performs some neccessary actions
176 returns 0 on success or != 0 if an error occurred */
177 int xio_forked_inchild(void) {
181 for (i
=0; i
<NUMUNKNOWN
; ++i
) {
187 if (xio_reset_fips_mode() != 0) {
190 #endif /* WITH_FIPS */
191 /* some locks belong to parent process, so "drop" them now */
192 if (xiohook_newchild
) {
193 if ((*xiohook_newchild
)() != 0) {
198 /* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
201 result2
= xio_nokill(sock1
);
202 if (result2
< 0) Exit(1);
209 /* subchild != 0 means that the current process is already a child process of
210 the master process and thus the new sub child process should not set the
211 SOCAT_PID variable */
212 pid_t
xio_fork(bool subchild
, int level
) {
214 const char *forkwaitstring
;
215 int forkwaitsecs
= 0;
217 if ((pid
= Fork()) < 0) {
218 Msg1(level
, "fork(): %s", strerror(errno
));
222 if (pid
== 0) { /* child process */
223 pid_t cpid
= Getpid();
225 Info1("just born: child process "F_pid
, cpid
);
227 /* set SOCAT_PID to new value */
228 xiosetenvulong("PID", pid
, 1);
230 /* gdb recommends to have env controlled sleep after fork */
231 if (forkwaitstring
= getenv("SOCAT_FORK_WAIT")) {
232 forkwaitsecs
= atoi(forkwaitstring
);
235 if (xio_forked_inchild() != 0) {
243 Notice1("forked off child process "F_pid
, pid
);
244 /* gdb recommends to have env controlled sleep after fork */
245 if (forkwaitstring
= getenv("SOCAT_FORK_WAIT")) {
246 forkwaitsecs
= atoi(forkwaitstring
);