1 /* source: xioinitialize.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
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]);
68 /* these dependencies required in applyopts() for OFUNC_FCNTL */
69 assert(F_GETFD
== F_SETFD
-1);
70 assert(F_GETFL
== F_SETFL
-1);
73 const char *default_ip
;
74 default_ip
= getenv("SOCAT_DEFAULT_LISTEN_IP");
75 if (default_ip
!= NULL
) {
76 switch (default_ip
[0]) {
79 xioopts
.default_ip
= default_ip
[0]; break;
84 const char *preferred_ip
;
85 preferred_ip
= getenv("SOCAT_PREFERRED_RESOLVE_IP");
86 if (preferred_ip
!= NULL
) {
87 switch (preferred_ip
[0]) {
90 xioopts
.preferred_ip
= preferred_ip
[0]; break;
92 xioopts
.preferred_ip
= '0'; break;
97 if (Atexit(xioexit
) < 0) {
98 Error("atexit(xioexit) failed");
106 /* call this function when option -lp (reset program name) has been applied */
107 int xioinitialize2(void) {
108 pid_t pid
= Getpid();
109 xiosetenvulong("PID", pid
, 1);
110 xiosetenvulong("PPID", pid
, 1);
115 /* well, this function is not for initialization, but I could not find a better
117 it is called in the child process after fork
118 it drops the locks of the xiofile's so only the parent owns them
120 void xiodroplocks(void) {
123 for (i
= 0; i
< XIO_MAXSOCK
; ++i
) {
124 if (sock
[i
] != NULL
&& sock
[i
]->tag
!= XIO_TAG_INVALID
) {
125 xiofiledroplock(sock
[i
]);
131 /* consider an invokation like this:
132 socat -u exec:'some program that accepts data' tcp-l:...,fork
133 we do not want the program to be killed by the first tcp-l sub process, it's
134 better if it survives all sub processes. Thus, it must not be killed when
135 the sub process delivers EOF. Also, a socket that is reused in sub processes
136 should not be shut down (affects the connection), but closed (affects only
137 sub processes copy of file descriptor) */
138 static int xio_nokill(xiofile_t
*sock
) {
141 case XIO_TAG_INVALID
:
145 if ((result
= xio_nokill((xiofile_t
*)sock
->dual
.stream
[0])) != 0)
147 result
= xio_nokill((xiofile_t
*)sock
->dual
.stream
[1]);
152 /* here is the core of this function */
153 switch (sock
->stream
.howtoend
) {
154 case END_SHUTDOWN_KILL
: sock
->stream
.howtoend
= END_CLOSE
; break;
155 case END_CLOSE_KILL
: sock
->stream
.howtoend
= END_CLOSE
; break;
156 case END_SHUTDOWN
: sock
->stream
.howtoend
= END_CLOSE
; break;
164 /* call this function immediately after fork() in child process */
165 /* it performs some neccessary actions
166 returns 0 on success or != 0 if an error occurred */
167 int xio_forked_inchild(void) {
172 for (i
=0; i
<NUMUNKNOWN
; ++i
) {
178 if (xio_reset_fips_mode() != 0) {
181 #endif /* WITH_FIPS */
182 /* some locks belong to parent process, so "drop" them now */
183 if (xiohook_newchild
) {
184 if ((*xiohook_newchild
)() != 0) {
189 /* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
192 result2
= xio_nokill(sock1
);
193 if (result2
< 0) Exit(1);
200 /* subchild != 0 means that the current process is already a child process of
201 the master process and thus the new sub child process should not set the
202 SOCAT_PID variable */
203 pid_t
xio_fork(bool subchild
, int level
) {
205 const char *forkwaitstring
;
206 int forkwaitsecs
= 0;
208 if ((pid
= Fork()) < 0) {
209 Msg1(level
, "fork(): %s", strerror(errno
));
213 if (pid
== 0) { /* child process */
214 pid_t cpid
= Getpid();
216 Info1("just born: child process "F_pid
, cpid
);
218 /* set SOCAT_PID to new value */
219 xiosetenvulong("PID", pid
, 1);
221 /* gdb recommends to have env controlled sleep after fork */
222 if (forkwaitstring
= getenv("SOCAT_FORK_WAIT")) {
223 forkwaitsecs
= atoi(forkwaitstring
);
226 if (xio_forked_inchild() != 0) {
234 Notice1("forked off child process "F_pid
, pid
);
235 /* gdb recommends to have env controlled sleep after fork */
236 if (forkwaitstring
= getenv("SOCAT_FORK_WAIT")) {
237 forkwaitsecs
= atoi(forkwaitstring
);