version 1.7.3.0
[socat.git] / xioopts.c
blob3b0f300bc939693b3bcf5b9fa14473f069a40c41
1 /* source: xioopts.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for address options handling */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
9 #include "xio-unix.h"
11 #include "xiomodes.h"
12 #include "xiolockfile.h"
13 #include "nestlex.h"
15 bool xioopts_ignoregroups;
17 #define IF_ANY(a,b) {a,b},
19 #if WITH_NAMED
20 # define IF_NAMED(a,b) {a,b},
21 #else
22 # define IF_NAMED(a,b)
23 #endif
25 #if WITH_PIPE || WITH_GOPEN
26 # define IF_OPEN(a,b) {a,b},
27 #else
28 # define IF_OPEN(a,b)
29 #endif
31 #if WITH_TERMIOS
32 # define IF_TERMIOS(a,b) {a,b},
33 #else
34 # define IF_TERMIOS(a,b)
35 #endif
37 #if WITH_EXEC
38 # define IF_EXEC(a,b) {a,b},
39 #else
40 # define IF_EXEC(a,b)
41 #endif
43 #if _WITH_SOCKET
44 # define IF_SOCKET(a,b) {a,b},
45 #else
46 # define IF_SOCKET(a,b)
47 #endif
49 #if WITH_LISTEN
50 # define IF_LISTEN(a,b) {a,b},
51 #else
52 # define IF_LISTEN(a,b)
53 #endif
55 #if (WITH_UDP || WITH_TCP) && WITH_LISTEN
56 # define IF_RANGE(a,b) {a,b},
57 #else
58 # define IF_RANGE(a,b)
59 #endif
61 #if WITH_IP4 || WITH_IP6
62 # define IF_IP(a,b) {a,b},
63 #else
64 # define IF_IP(a,b)
65 #endif
67 #if WITH_IP6
68 # define IF_IP6(a,b) {a,b},
69 #else
70 # define IF_IP6(a,b)
71 #endif
73 #if WITH_TCP|WITH_UDP
74 # define IF_IPAPP(a,b) {a,b},
75 #else
76 # define IF_IPAPP(a,b)
77 #endif
79 #if WITH_TCP
80 # define IF_TCP(a,b) {a,b},
81 #else
82 # define IF_TCP(a,b)
83 #endif
85 #if WITH_SCTP
86 # define IF_SCTP(a,b) {a,b},
87 #else
88 # define IF_SCTP(a,b)
89 #endif
91 #if WITH_SOCKS4
92 # define IF_SOCKS4(a,b) {a,b},
93 #else
94 # define IF_SOCKS4(a,b)
95 #endif
97 #if WITH_PROXY
98 # define IF_PROXY(a,b) {a,b},
99 #else
100 # define IF_PROXY(a,b)
101 #endif
103 #if WITH_READLINE
104 # define IF_READLINE(a,b) {a,b},
105 #else
106 # define IF_READLINE(a,b)
107 #endif
109 #if WITH_PTY
110 # define IF_PTY(a,b) {a,b},
111 #else
112 # define IF_PTY(a,b)
113 #endif
115 #if WITH_OPENSSL
116 # define IF_OPENSSL(a,b) {a,b},
117 #else
118 # define IF_OPENSSL(a,b)
119 #endif
121 #if WITH_TUN
122 # define IF_TUN(a,b) {a,b},
123 #else
124 # define IF_TUN(a,b)
125 #endif
127 #if WITH_UNIX
128 # define IF_UNIX(a,b) {a,b},
129 #else
130 # define IF_UNIX(a,b)
131 #endif
133 #if WITH_RETRY
134 # define IF_RETRY(a,b) {a,b},
135 #else
136 # define IF_RETRY(a,b)
137 #endif
140 static int applyopt_offset(struct single *xfd, struct opt *opt);
143 /* address options - keep this array strictly alphabetically sorted for
144 binary search! */
145 /* NULL terminated */
146 const struct optname optionnames[] = {
147 #if HAVE_RESOLV_H
148 IF_IP ("aaonly", &opt_res_aaonly)
149 #endif /* HAVE_RESOLV_H */
150 #ifdef TCP_ABORT_THRESHOLD /* HP_UX */
151 IF_TCP ("abort-threshold", &opt_tcp_abort_threshold)
152 #endif
153 #ifdef SO_ACCEPTCONN /* AIX433 */
154 IF_SOCKET ("acceptconn", &opt_so_acceptconn)
155 #endif /* SO_ACCEPTCONN */
156 #ifdef IP_ADD_MEMBERSHIP
157 IF_IP ("add-membership", &opt_ip_add_membership)
158 #endif
159 IF_TUN ("allmulti", &opt_iff_allmulti)
160 #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
161 IF_IPAPP ("allow-table", &opt_tcpwrap_hosts_allow_table)
162 #endif
163 IF_ANY ("append", &opt_append)
164 #ifdef O_ASYNC
165 IF_ANY ("async", &opt_async)
166 #endif
167 #ifdef SO_ATTACH_FILTER
168 IF_SOCKET ("attach-filter", &opt_so_attach_filter)
169 IF_SOCKET ("attachfilter", &opt_so_attach_filter)
170 #endif
171 #ifdef SO_AUDIT /* AIX 4.3.3 */
172 IF_SOCKET ("audit", &opt_so_audit)
173 #endif /* SO_AUDIT */
174 #ifdef IPV6_AUTHHDR
175 IF_IP6 ("authhdr", &opt_ipv6_authhdr)
176 #endif
177 IF_TUN ("automedia", &opt_iff_automedia)
178 #ifdef CBAUD
179 IF_TERMIOS("b0", &opt_b0)
180 #ifdef B1000000
181 IF_TERMIOS("b1000000", &opt_b1000000)
182 #endif
183 IF_TERMIOS("b110", &opt_b110)
184 #ifdef B115200
185 IF_TERMIOS("b115200", &opt_b115200)
186 #endif
187 #ifdef B1152000
188 IF_TERMIOS("b1152000", &opt_b1152000)
189 #endif
190 IF_TERMIOS("b1200", &opt_b1200)
191 IF_TERMIOS("b134", &opt_b134)
192 IF_TERMIOS("b150", &opt_b150)
193 #ifdef B1500000
194 IF_TERMIOS("b1500000", &opt_b1500000)
195 #endif
196 IF_TERMIOS("b1800", &opt_b1800)
197 IF_TERMIOS("b19200", &opt_b19200)
198 IF_TERMIOS("b200", &opt_b200)
199 #ifdef B2000000
200 IF_TERMIOS("b2000000", &opt_b2000000)
201 #endif
202 #ifdef B230400
203 IF_TERMIOS("b230400", &opt_b230400)
204 #endif
205 IF_TERMIOS("b2400", &opt_b2400)
206 #ifdef B2500000
207 IF_TERMIOS("b2500000", &opt_b2500000)
208 #endif
209 IF_TERMIOS("b300", &opt_b300)
210 #ifdef B3000000
211 IF_TERMIOS("b3000000", &opt_b3000000)
212 #endif
213 #ifdef B3500000
214 IF_TERMIOS("b3500000", &opt_b3500000)
215 #endif
216 #ifdef B3600 /* HP-UX */
217 IF_TERMIOS("b3600", &opt_b3600)
218 #endif
219 IF_TERMIOS("b38400", &opt_b38400)
220 #ifdef B4000000
221 IF_TERMIOS("b4000000", &opt_b4000000)
222 #endif
223 #ifdef B460800
224 IF_TERMIOS("b460800", &opt_b460800)
225 #endif
226 IF_TERMIOS("b4800", &opt_b4800)
227 IF_TERMIOS("b50", &opt_b50)
228 #ifdef B500000
229 IF_TERMIOS("b500000", &opt_b500000)
230 #endif
231 #ifdef B57600
232 IF_TERMIOS("b57600", &opt_b57600)
233 #endif
234 #ifdef B576000
235 IF_TERMIOS("b576000", &opt_b576000)
236 #endif
237 IF_TERMIOS("b600", &opt_b600)
238 #ifdef B7200 /* HP-UX */
239 IF_TERMIOS("b7200", &opt_b7200)
240 #endif
241 IF_TERMIOS("b75", &opt_b75)
242 #ifdef B900 /* HP-UX */
243 IF_TERMIOS("b900", &opt_b900)
244 #endif
245 #ifdef B921600
246 IF_TERMIOS("b921600", &opt_b921600)
247 #endif
248 IF_TERMIOS("b9600", &opt_b9600)
249 #endif /* defined(CBAUD) */
250 IF_LISTEN ("backlog", &opt_backlog)
251 #ifdef O_BINARY
252 IF_OPEN ("bin", &opt_o_binary)
253 IF_OPEN ("binary", &opt_o_binary)
254 #endif
255 IF_SOCKET ("bind", &opt_bind)
256 #ifdef SO_BINDTODEVICE
257 IF_SOCKET ("bindtodevice", &opt_so_bindtodevice)
258 #endif
259 IF_TERMIOS("brkint", &opt_brkint)
260 IF_SOCKET ("broadcast", &opt_so_broadcast)
261 #ifdef BSDLY
262 # ifdef BS0
263 IF_TERMIOS("bs0", &opt_bs0)
264 # endif
265 # ifdef BS1
266 IF_TERMIOS("bs1", &opt_bs1)
267 # endif
268 #endif
269 #ifdef SO_BSDCOMPAT
270 IF_SOCKET ("bsdcompat", &opt_so_bsdcompat)
271 #endif
272 #ifdef BSDLY
273 IF_TERMIOS("bsdly", &opt_bsdly)
274 #endif
275 IF_ANY ("bytes", &opt_readbytes)
276 IF_OPENSSL("cafile", &opt_openssl_cafile)
277 IF_OPENSSL("capath", &opt_openssl_capath)
278 IF_OPENSSL("cert", &opt_openssl_certificate)
279 IF_OPENSSL("certificate", &opt_openssl_certificate)
280 IF_TERMIOS("cfmakeraw", &opt_termios_cfmakeraw)
281 IF_ANY ("chroot", &opt_chroot)
282 IF_ANY ("chroot-early", &opt_chroot_early)
283 /*IF_TERMIOS("cibaud", &opt_cibaud)*/
284 IF_OPENSSL("cipher", &opt_openssl_cipherlist)
285 IF_OPENSSL("cipherlist", &opt_openssl_cipherlist)
286 IF_OPENSSL("ciphers", &opt_openssl_cipherlist)
287 #ifdef SO_CKSUMRECV
288 IF_SOCKET ("cksumrecv", &opt_so_cksumrecv)
289 #endif /* SO_CKSUMRECV */
290 /*IF_NAMED ("cleanup", &opt_cleanup)*/
291 IF_TERMIOS("clocal", &opt_clocal)
292 IF_ANY ("cloexec", &opt_cloexec)
293 IF_ANY ("close", &opt_end_close)
294 IF_OPENSSL("cn", &opt_openssl_commonname)
295 IF_OPENSSL("commonname", &opt_openssl_commonname)
296 #if WITH_EXT2 && defined(EXT2_COMPR_FL)
297 IF_ANY ("compr", &opt_ext2_compr)
298 #endif
299 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
300 IF_OPENSSL("compress", &opt_openssl_compress)
301 #endif
302 #ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
303 IF_TCP ("conn-abort-threshold", &opt_tcp_conn_abort_threshold)
304 #endif
305 IF_SOCKET ("connect-timeout", &opt_connect_timeout)
306 IF_LISTEN ("cool-write", &opt_cool_write)
307 IF_LISTEN ("coolwrite", &opt_cool_write)
308 #ifdef TCP_CORK
309 IF_TCP ("cork", &opt_tcp_cork)
310 #endif
311 IF_ANY ("cr", &opt_cr)
312 #ifdef CRDLY
313 # ifdef CR0
314 IF_TERMIOS("cr0", &opt_cr0)
315 # endif
316 # ifdef CR1
317 IF_TERMIOS("cr1", &opt_cr1)
318 # endif
319 # ifdef CR2
320 IF_TERMIOS("cr2", &opt_cr2)
321 # endif
322 # ifdef CR3
323 IF_TERMIOS("cr3", &opt_cr3)
324 # endif
325 # if CRDLY_SHIFT >= 0
326 IF_TERMIOS("crdly", &opt_crdly)
327 # endif
328 #endif /* defined(CRDLY) */
329 IF_TERMIOS("cread", &opt_cread)
330 IF_OPEN ("creat", &opt_o_create)
331 IF_OPEN ("create", &opt_o_create)
332 IF_ANY ("crlf", &opt_crnl)
333 IF_ANY ("crnl", &opt_crnl)
334 IF_TERMIOS("crterase", &opt_echoe)
335 IF_TERMIOS("crtkill", &opt_echoke)
336 #ifdef CRTSCTS
337 IF_TERMIOS("crtscts", &opt_crtscts)
338 #endif
339 IF_TERMIOS("cs5", &opt_cs5)
340 IF_TERMIOS("cs6", &opt_cs6)
341 IF_TERMIOS("cs7", &opt_cs7)
342 IF_TERMIOS("cs8", &opt_cs8)
343 #if CSIZE_SHIFT >= 0
344 IF_TERMIOS("csize", &opt_csize)
345 #endif
346 IF_TERMIOS("cstopb", &opt_cstopb)
347 IF_TERMIOS("ctlecho", &opt_echoctl)
348 IF_TERMIOS("ctty", &opt_tiocsctty)
349 IF_EXEC ("dash", &opt_dash)
350 IF_SOCKET ("debug", &opt_so_debug)
351 /*IF_IP ("debug", &opt_res_debug)*/
352 #ifdef O_DEFER
353 IF_OPEN ("defer", &opt_o_defer)
354 #endif
355 #ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
356 IF_TCP ("defer-accept", &opt_tcp_defer_accept)
357 #endif
358 #if HAVE_RESOLV_H
359 IF_IP ("defnames", &opt_res_defnames)
360 #endif /* HAVE_RESOLV_H */
361 #ifdef O_DELAY
362 IF_OPEN ("delay", &opt_o_delay)
363 #endif
364 IF_NAMED ("delete", &opt_unlink)
365 #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
366 IF_IPAPP ("deny-table", &opt_tcpwrap_hosts_deny_table)
367 #endif
368 #ifdef SO_DETACH_FILTER
369 IF_SOCKET ("detach-filter", &opt_so_detach_filter)
370 IF_SOCKET ("detachfilter", &opt_so_detach_filter)
371 #endif
372 #ifdef SO_DGRAM_ERRIND
373 IF_SOCKET ("dgram-errind", &opt_so_dgram_errind)
374 IF_SOCKET ("dgramerrind", &opt_so_dgram_errind)
375 #endif
376 IF_OPENSSL("dh", &opt_openssl_dhparam)
377 IF_OPENSSL("dhparam", &opt_openssl_dhparam)
378 #ifdef O_DIRECT
379 IF_OPEN ("direct", &opt_o_direct)
380 #endif
381 #ifdef O_DIRECTORY
382 IF_OPEN ("directory", &opt_o_directory)
383 #endif
384 #if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
385 IF_ANY ("dirsync", &opt_ext2_dirsync)
386 #endif
387 #ifdef VDISCARD
388 IF_TERMIOS("discard", &opt_vdiscard)
389 #endif
390 #if HAVE_RESOLV_H
391 IF_IP ("dnsrch", &opt_res_dnsrch)
392 #endif /* HAVE_RESOLV_H */
393 #ifdef SO_DONTLINGER
394 IF_SOCKET ("dontlinger", &opt_so_dontlinger)
395 #endif
396 IF_SOCKET ("dontroute", &opt_so_dontroute)
397 #ifdef IPV6_DSTOPTS
398 IF_IP6 ("dstopts", &opt_ipv6_dstopts)
399 #endif
400 #ifdef VDSUSP /* HP-UX */
401 IF_TERMIOS("dsusp", &opt_vdsusp)
402 #endif
403 #ifdef O_DSYNC
404 IF_OPEN ("dsync", &opt_o_dsync)
405 #endif
406 IF_TERMIOS("echo", &opt_echo)
407 IF_TERMIOS("echoctl", &opt_echoctl)
408 IF_TERMIOS("echoe", &opt_echoe)
409 IF_TERMIOS("echok", &opt_echok)
410 IF_TERMIOS("echoke", &opt_echoke)
411 IF_TERMIOS("echonl", &opt_echonl)
412 #ifdef ECHOPRT
413 IF_TERMIOS("echoprt", &opt_echoprt)
414 #endif
415 IF_OPENSSL("egd", &opt_openssl_egd)
416 IF_ANY ("end-close", &opt_end_close)
417 IF_TERMIOS("eof", &opt_veof)
418 IF_TERMIOS("eol", &opt_veol)
419 IF_TERMIOS("eol2", &opt_veol2)
420 IF_TERMIOS("erase", &opt_verase)
421 IF_SOCKET ("error", &opt_so_error)
422 IF_ANY ("escape", &opt_escape)
423 IF_OPEN ("excl", &opt_o_excl)
424 #if WITH_EXT2 && defined(EXT2_APPEND_FL)
425 IF_ANY ("ext2-append", &opt_ext2_append)
426 #endif
427 #if WITH_EXT2 && defined(EXT2_COMPR_FL)
428 IF_ANY ("ext2-compr", &opt_ext2_compr)
429 #endif
430 #if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
431 IF_ANY ("ext2-dirsync", &opt_ext2_dirsync)
432 #endif
433 #if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
434 IF_ANY ("ext2-immutable", &opt_ext2_immutable)
435 #endif
436 #if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
437 IF_ANY ("ext2-journal-data", &opt_ext2_journal_data)
438 #endif
439 #if WITH_EXT2 && defined(EXT2_NOATIME_FL)
440 IF_ANY ("ext2-noatime", &opt_ext2_noatime)
441 #endif
442 #if WITH_EXT2 && defined(EXT2_NODUMP_FL)
443 IF_ANY ("ext2-nodump", &opt_ext2_nodump)
444 #endif
445 #if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
446 IF_ANY ("ext2-notail", &opt_ext2_notail)
447 #endif
448 #if WITH_EXT2 && defined(EXT2_SECRM_FL)
449 IF_ANY ("ext2-secrm", &opt_ext2_secrm)
450 #endif
451 #if WITH_EXT2 && defined(EXT2_SYNC_FL)
452 IF_ANY ("ext2-sync", &opt_ext2_sync)
453 #endif
454 #if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
455 IF_ANY ("ext2-topdir", &opt_ext2_topdir)
456 #endif
457 #if WITH_EXT2 && defined(EXT2_UNRM_FL)
458 IF_ANY ("ext2-unrm", &opt_ext2_unrm)
459 #endif
460 #if WITH_EXT2 && defined(EXT2_APPEND_FL)
461 IF_ANY ("ext3-append", &opt_ext2_append)
462 #endif
463 #if WITH_EXT2 && defined(EXT2_COMPR_FL)
464 IF_ANY ("ext3-compr", &opt_ext2_compr)
465 #endif
466 #if WITH_EXT2 && defined(EXT2_DIRSYNC_FL)
467 IF_ANY ("ext3-dirsync", &opt_ext2_dirsync)
468 #endif
469 #if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
470 IF_ANY ("ext3-immutable", &opt_ext2_immutable)
471 #endif
472 #if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
473 IF_ANY ("ext3-journal-data", &opt_ext2_journal_data)
474 #endif
475 #if WITH_EXT2 && defined(EXT2_NOATIME_FL)
476 IF_ANY ("ext3-noatime", &opt_ext2_noatime)
477 #endif
478 #if WITH_EXT2 && defined(EXT2_NODUMP_FL)
479 IF_ANY ("ext3-nodump", &opt_ext2_nodump)
480 #endif
481 #if WITH_EXT2 && defined(EXT2_NOTAIL_FL)
482 IF_ANY ("ext3-notail", &opt_ext2_notail)
483 #endif
484 #if WITH_EXT2 && defined(EXT2_SECRM_FL)
485 IF_ANY ("ext3-secrm", &opt_ext2_secrm)
486 #endif
487 #if WITH_EXT2 && defined(EXT2_SYNC_FL)
488 IF_ANY ("ext3-sync", &opt_ext2_sync)
489 #endif
490 #if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
491 IF_ANY ("ext3-topdir", &opt_ext2_topdir)
492 #endif
493 #if WITH_EXT2 && defined(EXT2_UNRM_FL)
494 IF_ANY ("ext3-unrm", &opt_ext2_unrm)
495 #endif
496 IF_ANY ("f-setlk", &opt_f_setlk_wr)
497 IF_ANY ("f-setlk-rd", &opt_f_setlk_rd)
498 IF_ANY ("f-setlk-wr", &opt_f_setlk_wr)
499 IF_ANY ("f-setlkw", &opt_f_setlkw_wr)
500 IF_ANY ("f-setlkw-rd", &opt_f_setlkw_rd)
501 IF_ANY ("f-setlkw-wr", &opt_f_setlkw_wr)
502 IF_EXEC ("fdin", &opt_fdin)
503 IF_EXEC ("fdout", &opt_fdout)
504 #ifdef FFDLY
505 # ifdef FF0
506 IF_TERMIOS("ff0", &opt_ff0)
507 # endif
508 # ifdef FF1
509 IF_TERMIOS("ff1", &opt_ff1)
510 # endif
511 IF_TERMIOS("ffdly", &opt_ffdly)
512 #endif
513 #ifdef FIOSETOWN
514 IF_SOCKET ("fiosetown", &opt_fiosetown)
515 #endif
516 #if WITH_FIPS
517 IF_OPENSSL("fips", &opt_openssl_fips)
518 #endif
519 #if HAVE_FLOCK
520 IF_ANY ("flock", &opt_flock_ex)
521 IF_ANY ("flock-ex", &opt_flock_ex)
522 IF_ANY ("flock-ex-nb", &opt_flock_ex_nb)
523 IF_ANY ("flock-nb", &opt_flock_ex_nb)
524 IF_ANY ("flock-sh", &opt_flock_sh)
525 IF_ANY ("flock-sh-nb", &opt_flock_sh_nb)
526 #endif
527 #ifdef IPV4_FLOWINFO
528 IF_IP6 ("flowinfo", &opt_ipv6_flowinfo)
529 #endif
530 IF_TERMIOS("flusho", &opt_flusho)
531 IF_RETRY ("forever", &opt_forever)
532 IF_LISTEN ("fork", &opt_fork)
533 #ifdef IP_FREEBIND
534 IF_IP ("freebind", &opt_ip_freebind)
535 #endif
536 #if HAVE_FTRUNCATE64
537 IF_ANY ("ftruncate", &opt_ftruncate64)
538 #else
539 IF_ANY ("ftruncate", &opt_ftruncate32)
540 #endif
541 IF_ANY ("ftruncate32", &opt_ftruncate32)
542 #if HAVE_FTRUNCATE64
543 IF_ANY ("ftruncate64", &opt_ftruncate64)
544 #endif
545 IF_ANY ("gid", &opt_group)
546 IF_NAMED ("gid-e", &opt_group_early)
547 IF_ANY ("gid-l", &opt_group_late)
548 IF_ANY ("group", &opt_group)
549 IF_NAMED ("group-early", &opt_group_early)
550 IF_ANY ("group-late", &opt_group_late)
551 #ifdef IP_HDRINCL
552 IF_IP ("hdrincl", &opt_ip_hdrincl)
553 #endif
554 IF_READLINE("history", &opt_history_file)
555 IF_READLINE("history-file", &opt_history_file)
556 #ifdef IPV6_HOPLIMIT
557 IF_IP6 ("hoplimit", &opt_ipv6_hoplimit)
558 #endif
559 #ifdef IPV6_HOPOPTS
560 IF_IP6 ("hopopts", &opt_ipv6_hopopts)
561 #endif
562 #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
563 IF_IPAPP ("hosts-allow", &opt_tcpwrap_hosts_allow_table)
564 #endif
565 #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
566 IF_IPAPP ("hosts-deny", &opt_tcpwrap_hosts_deny_table)
567 #endif
568 IF_TERMIOS("hup", &opt_hupcl)
569 IF_TERMIOS("hupcl", &opt_hupcl)
570 #ifdef I_POP
571 IF_ANY ("i-pop-all", &opt_streams_i_pop_all)
572 #endif
573 #ifdef I_PUSH
574 IF_ANY ("i-push", &opt_streams_i_push)
575 #endif
576 IF_TERMIOS("icanon", &opt_icanon)
577 IF_TERMIOS("icrnl", &opt_icrnl)
578 IF_TERMIOS("iexten", &opt_iexten)
579 #ifdef SO_BINDTODEVICE
580 IF_SOCKET ("if", &opt_so_bindtodevice)
581 #endif
582 IF_TUN ("iff-allmulti", &opt_iff_allmulti)
583 IF_TUN ("iff-automedia", &opt_iff_automedia)
584 IF_TUN ("iff-broadcast", &opt_iff_broadcast)
585 IF_TUN ("iff-debug", &opt_iff_debug)
586 /*IF_TUN ("iff-dynamic", &opt_iff_dynamic)*/
587 IF_TUN ("iff-loopback", &opt_iff_loopback)
588 IF_TUN ("iff-master", &opt_iff_master)
589 IF_TUN ("iff-multicast", &opt_iff_multicast)
590 IF_TUN ("iff-no-pi", &opt_iff_no_pi)
591 IF_TUN ("iff-noarp", &opt_iff_noarp)
592 IF_TUN ("iff-notrailers", &opt_iff_notrailers)
593 IF_TUN ("iff-pointopoint", &opt_iff_pointopoint)
594 IF_TUN ("iff-portsel", &opt_iff_portsel)
595 IF_TUN ("iff-promisc", &opt_iff_promisc)
596 IF_TUN ("iff-running", &opt_iff_running)
597 IF_TUN ("iff-slave", &opt_iff_slave)
598 IF_TUN ("iff-up", &opt_iff_up)
599 IF_TERMIOS("ignbrk", &opt_ignbrk)
600 IF_TERMIOS("igncr", &opt_igncr)
601 /* you might need to terminate socat manually if you use this option: */
602 IF_PROXY ("ignorecr", &opt_ignorecr)
603 IF_ANY ("ignoreeof", &opt_ignoreeof)
604 IF_ANY ("ignoreof", &opt_ignoreeof)
605 IF_TERMIOS("ignpar", &opt_ignpar)
606 #if HAVE_RESOLV_H
607 IF_IP ("igntc", &opt_res_igntc)
608 #endif /* HAVE_RESOLV_H */
609 IF_TERMIOS("imaxbel", &opt_imaxbel)
610 #if WITH_EXT2 && defined(EXT2_IMMUTABLE_FL)
611 IF_ANY ("immutable", &opt_ext2_immutable)
612 #endif
613 #ifdef TCP_INFO /* Linux 2.4.0 */
614 IF_TCP ("info", &opt_tcp_info)
615 #endif
616 IF_TERMIOS("inlcr", &opt_inlcr)
617 IF_TERMIOS("inpck", &opt_inpck)
618 #ifdef SO_BINDTODEVICE
619 IF_SOCKET ("interface", &opt_so_bindtodevice)
620 #endif
621 IF_RETRY ("interval", &opt_intervall)
622 IF_RETRY ("intervall", &opt_intervall)
623 IF_TERMIOS("intr", &opt_vintr)
624 IF_ANY ("ioctl", &opt_ioctl_void)
625 IF_ANY ("ioctl-bin", &opt_ioctl_bin)
626 IF_ANY ("ioctl-int", &opt_ioctl_int)
627 IF_ANY ("ioctl-intp", &opt_ioctl_intp)
628 IF_ANY ("ioctl-string", &opt_ioctl_string)
629 IF_ANY ("ioctl-void", &opt_ioctl_void)
630 #ifdef IP_ADD_MEMBERSHIP
631 IF_IP ("ip-add-membership", &opt_ip_add_membership)
632 #endif
633 #ifdef IP_FREEBIND
634 IF_IP ("ip-freebind", &opt_ip_freebind)
635 #endif
636 #ifdef IP_HDRINCL
637 IF_IP ("ip-hdrincl", &opt_ip_hdrincl)
638 #endif
639 #ifdef IP_ADD_MEMBERSHIP
640 IF_IP ("ip-membership", &opt_ip_add_membership)
641 #endif
642 #ifdef IP_MTU
643 IF_IP ("ip-mtu", &opt_ip_mtu)
644 #endif
645 #ifdef IP_MTU_DISCOVER
646 IF_IP ("ip-mtu-discover", &opt_ip_mtu_discover)
647 #endif
648 IF_IP ("ip-multicast-if", &opt_ip_multicast_if)
649 IF_IP ("ip-multicast-loop", &opt_ip_multicast_loop)
650 IF_IP ("ip-multicast-ttl", &opt_ip_multicast_ttl)
651 #ifdef IP_OPTIONS
652 IF_IP ("ip-options", &opt_ip_options)
653 #endif
654 #ifdef IP_PKTINFO
655 IF_IP ("ip-pktinfo", &opt_ip_pktinfo)
656 #endif
657 #ifdef IP_PKTOPTIONS
658 IF_IP ("ip-pktoptions", &opt_ip_pktoptions)
659 #endif
660 #ifdef IP_RECVDSTADDR
661 IF_IP ("ip-recvdstaddr", &opt_ip_recvdstaddr)
662 #endif
663 #ifdef IP_RECVERR
664 IF_IP ("ip-recverr", &opt_ip_recverr)
665 #endif
666 #ifdef IP_RECVIF
667 IF_IP ("ip-recvif", &opt_ip_recvif)
668 #endif
669 #ifdef IP_RECVOPTS
670 IF_IP ("ip-recvopts", &opt_ip_recvopts)
671 #endif
672 #ifdef IP_RECVTOS
673 IF_IP ("ip-recvtos", &opt_ip_recvtos)
674 #endif
675 #ifdef IP_RECVTTL
676 IF_IP ("ip-recvttl", &opt_ip_recvttl)
677 #endif
678 #ifdef IP_RETOPTS
679 IF_IP ("ip-retopts", &opt_ip_retopts)
680 #endif
681 #ifdef IP_ROUTER_ALERT
682 IF_IP ("ip-router-alert", &opt_ip_router_alert)
683 #endif
684 IF_IP ("ip-tos", &opt_ip_tos)
685 IF_IP ("ip-ttl", &opt_ip_ttl)
686 #ifdef IP_FREEBIND
687 IF_IP ("ipfreebind", &opt_ip_freebind)
688 #endif
689 #ifdef IP_HDRINCL
690 IF_IP ("iphdrincl", &opt_ip_hdrincl)
691 #endif
692 #ifdef IP_MTU
693 IF_IP ("ipmtu", &opt_ip_mtu)
694 #endif
695 #ifdef IP_MTU_DISCOVER
696 IF_IP ("ipmtudiscover", &opt_ip_mtu_discover)
697 #endif
698 IF_IP ("ipmulticastloop", &opt_ip_multicast_loop)
699 IF_IP ("ipmulticastttl", &opt_ip_multicast_ttl)
700 #ifdef IP_OPTIONS
701 IF_IP ("ipoptions", &opt_ip_options)
702 #endif
703 #ifdef IP_PKTINFO
704 IF_IP ("ippktinfo", &opt_ip_pktinfo)
705 #endif
706 #ifdef IP_PKTOPTIONS
707 IF_IP ("ippktoptions", &opt_ip_pktoptions)
708 #endif
709 #ifdef IP_RECVDSTADDR
710 IF_IP ("iprecvdstaddr", &opt_ip_recvdstaddr)
711 #endif
712 #ifdef IP_RECVERR
713 IF_IP ("iprecverr", &opt_ip_recverr)
714 #endif
715 #ifdef IP_RECVOPTS
716 IF_IP ("iprecvopts", &opt_ip_recvopts)
717 #endif
718 #ifdef IP_RECVTOS
719 IF_IP ("iprecvtos", &opt_ip_recvtos)
720 #endif
721 #ifdef IP_RECVTTL
722 IF_IP ("iprecvttl", &opt_ip_recvttl)
723 #endif
724 #ifdef IP_RETOPTS
725 IF_IP ("ipretopts", &opt_ip_retopts)
726 #endif
727 #ifdef IP_ROUTER_ALERT
728 IF_IP ("iprouteralert", &opt_ip_router_alert)
729 #endif
730 IF_IP ("iptos", &opt_ip_tos)
731 IF_IP ("ipttl", &opt_ip_ttl)
732 #ifdef IPV6_JOIN_GROUP
733 IF_IP6 ("ipv6-add-membership", &opt_ipv6_join_group)
734 #endif
735 #ifdef IPV6_AUTHHDR
736 IF_IP6 ("ipv6-authhdr", &opt_ipv6_authhdr)
737 #endif
738 #ifdef IPV6_DSTOPTS
739 IF_IP6 ("ipv6-dstopts", &opt_ipv6_dstopts)
740 #endif
741 #ifdef IPV4_FLOWINFO
742 IF_IP6 ("ipv6-flowinfo", &opt_ipv6_flowinfo)
743 #endif
744 #ifdef IPV6_HOPLIMIT
745 IF_IP6 ("ipv6-hoplimit", &opt_ipv6_hoplimit)
746 #endif
747 #ifdef IPV6_HOPOPTS
748 IF_IP6 ("ipv6-hopopts", &opt_ipv6_hopopts)
749 #endif
750 #ifdef IPV6_JOIN_GROUP
751 IF_IP6 ("ipv6-join-group", &opt_ipv6_join_group)
752 #endif
753 #ifdef IPV6_PKTINFO
754 IF_IP6 ("ipv6-pktinfo", &opt_ipv6_pktinfo)
755 #endif
756 #ifdef IPV6_RECVDSTOPTS
757 IF_IP6 ("ipv6-recvdstopts", &opt_ipv6_recvdstopts)
758 #endif
759 #ifdef IPV6_RECVERR
760 IF_IP6 ("ipv6-recverr", &opt_ipv6_recverr)
761 #endif
762 #ifdef IPV6_RECVHOPLIMIT
763 IF_IP6 ("ipv6-recvhoplimit", &opt_ipv6_recvhoplimit)
764 #endif
765 #ifdef IPV6_RECVHOPOPTS
766 IF_IP6 ("ipv6-recvhopopts", &opt_ipv6_recvhopopts)
767 #endif
768 #ifdef IPV6_PATHMTU
769 IF_IP6 ("ipv6-recvpathmtu", &opt_ipv6_recvpathmtu)
770 #endif
771 #ifdef IPV6_RECVPKTINFO
772 IF_IP6 ("ipv6-recvpktinfo", &opt_ipv6_recvpktinfo)
773 #endif
774 #ifdef IPV6_RECVRTHDR
775 IF_IP6 ("ipv6-recvrthdr", &opt_ipv6_recvrthdr)
776 #endif
777 #ifdef IPV6_RECVTCLASS
778 IF_IP6 ("ipv6-recvtclass", &opt_ipv6_recvtclass)
779 #endif
780 #ifdef IPV6_RTHDR
781 IF_IP6 ("ipv6-rthdr", &opt_ipv6_rthdr)
782 #endif
783 #ifdef IPV6_TCLASS
784 IF_IP6 ("ipv6-tclass", &opt_ipv6_tclass)
785 #endif
786 IF_IP6 ("ipv6-unicast-hops", &opt_ipv6_unicast_hops)
787 #ifdef IPV6_V6ONLY
788 IF_IP6 ("ipv6-v6only", &opt_ipv6_v6only)
789 IF_IP6 ("ipv6only", &opt_ipv6_v6only)
790 #endif
791 IF_TERMIOS("isig", &opt_isig)
792 #if defined(HAVE_TERMIOS_ISPEED) && defined(ISPEED_OFFSET) && (ISPEED_OFFSET != -1)
793 IF_TERMIOS("ispeed", &opt_ispeed)
794 #endif
795 IF_TERMIOS("istrip", &opt_istrip)
796 #ifdef IUCLC
797 IF_TERMIOS("iuclc", &opt_iuclc)
798 #endif
799 IF_TERMIOS("ixany", &opt_ixany)
800 IF_TERMIOS("ixoff", &opt_ixoff)
801 IF_TERMIOS("ixon", &opt_ixon)
802 #ifdef IPV6_JOIN_GROUP
803 IF_IP6 ("join-group", &opt_ipv6_join_group)
804 #endif
805 #if WITH_EXT2 && defined(EXT2_JOURNAL_DATA_FL)
806 IF_ANY ("journal", &opt_ext2_journal_data)
807 IF_ANY ("journal-data", &opt_ext2_journal_data)
808 #endif
809 IF_SOCKET ("keepalive", &opt_so_keepalive)
810 #ifdef TCP_KEEPCNT /* Linux 2.4.0 */
811 IF_TCP ("keepcnt", &opt_tcp_keepcnt)
812 #endif
813 #ifdef TCP_KEEPIDLE /* Linux 2.4.0 */
814 IF_TCP ("keepidle", &opt_tcp_keepidle)
815 #endif
816 #ifdef TCP_KEEPINIT /* OSF1 */
817 IF_TCP ("keepinit", &opt_tcp_keepinit)
818 #endif
819 #ifdef TCP_KEEPINTVL /* Linux 2.4.0 */
820 IF_TCP ("keepintvl", &opt_tcp_keepintvl)
821 #endif
822 #ifdef SO_KERNACCEPT /* AIX 4.3.3 */
823 IF_SOCKET ("kernaccept", &opt_so_kernaccept)
824 #endif /* SO_KERNACCEPT */
825 IF_OPENSSL("key", &opt_openssl_key)
826 IF_TERMIOS("kill", &opt_vkill)
827 #ifdef O_LARGEFILE
828 IF_OPEN ("largefile", &opt_o_largefile)
829 #endif
830 #if WITH_LIBWRAP
831 IF_IPAPP ("libwrap", &opt_tcpwrappers)
832 #endif
833 IF_SOCKET ("linger", &opt_so_linger)
834 #ifdef TCP_LINGER2 /* Linux 2.4.0 */
835 IF_TCP ("linger2", &opt_tcp_linger2)
836 #endif
837 IF_PTY ("link", &opt_symbolic_link)
838 IF_TERMIOS("lnext", &opt_vlnext)
839 #if defined(F_SETLKW)
840 IF_ANY ("lock", &opt_f_setlkw_wr) /* POSIX, first choice */
841 #elif defined(HAVE_FLOCK)
842 IF_ANY ("lock", &opt_flock_ex) /* BSD, fallback */
843 #endif
844 IF_ANY ("lockfile", &opt_lockfile)
845 #if defined(F_SETLKW)
846 IF_ANY ("lockw", &opt_f_setlkw_wr) /* POSIX, first choice */
847 #elif defined(HAVE_FLOCK)
848 IF_ANY ("lockw", &opt_flock_ex_nb) /* BSD, fallback */
849 #endif
850 IF_EXEC ("login", &opt_dash)
851 IF_TUN ("loopback", &opt_iff_loopback)
852 IF_IPAPP ("lowport", &opt_lowport)
853 #if HAVE_LSEEK64
854 IF_ANY ("lseek", &opt_lseek64_set)
855 #else
856 IF_ANY ("lseek", &opt_lseek32_set)
857 #endif
858 IF_ANY ("lseek32", &opt_lseek32_set)
859 IF_ANY ("lseek32-cur", &opt_lseek32_cur)
860 IF_ANY ("lseek32-end", &opt_lseek32_end)
861 IF_ANY ("lseek32-set", &opt_lseek32_set)
862 #if HAVE_LSEEK64
863 IF_ANY ("lseek64", &opt_lseek64_set)
864 IF_ANY ("lseek64-cur", &opt_lseek64_cur)
865 IF_ANY ("lseek64-end", &opt_lseek64_end)
866 IF_ANY ("lseek64-set", &opt_lseek64_set)
867 #endif
868 IF_TUN ("master", &opt_iff_master)
869 IF_LISTEN ("max-children", &opt_max_children)
870 IF_LISTEN ("maxchildren", &opt_max_children)
871 #ifdef TCP_MAXSEG
872 IF_TCP ("maxseg", &opt_tcp_maxseg)
873 IF_TCP ("maxseg-late", &opt_tcp_maxseg_late)
874 #endif
875 #ifdef TCP_MD5SUM
876 IF_TCP ("md5sig", &opt_tcp_md5sig)
877 #endif
878 #ifdef IP_ADD_MEMBERSHIP
879 IF_IP ("membership", &opt_ip_add_membership)
880 #endif
881 IF_OPENSSL("method", &opt_openssl_method)
882 IF_TERMIOS("min", &opt_vmin)
883 IF_ANY ("mode", &opt_perm)
884 #ifdef TCP_MAXSEG
885 IF_TCP ("mss", &opt_tcp_maxseg)
886 IF_TCP ("mss-late", &opt_tcp_maxseg_late)
887 #endif
888 #ifdef IP_MTU
889 IF_IP ("mtu", &opt_ip_mtu)
890 #endif
891 #ifdef IP_MTU_DISCOVER
892 IF_IP ("mtudiscover", &opt_ip_mtu_discover)
893 #endif
894 IF_TUN ("multicast", &opt_iff_multicast)
895 IF_IP ("multicast-if", &opt_ip_multicast_if)
896 IF_IP ("multicast-loop", &opt_ip_multicast_loop)
897 IF_IP ("multicast-ttl", &opt_ip_multicast_ttl)
898 IF_IP ("multicastloop", &opt_ip_multicast_loop)
899 IF_IP ("multicastttl", &opt_ip_multicast_ttl)
900 #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
901 IF_ANY ("ndelay", &opt_o_ndelay)
902 #else
903 IF_ANY ("ndelay", &opt_nonblock)
904 #endif
905 IF_NAMED ("new", &opt_unlink_early)
906 #ifdef NLDLY
907 # ifdef NL0
908 IF_TERMIOS("nl0", &opt_nl0)
909 # endif
910 # ifdef NL1
911 IF_TERMIOS("nl1", &opt_nl1)
912 # endif
913 IF_TERMIOS("nldly", &opt_nldly)
914 #endif /* defined(NLDLY) */
915 #ifdef SO_NO_CHECK
916 IF_SOCKET ("no-check", &opt_so_no_check)
917 #endif
918 IF_TUN ("no-pi", &opt_iff_no_pi)
919 IF_TUN ("noarp", &opt_iff_noarp)
920 #ifdef O_NOATIME
921 IF_OPEN ("noatime", &opt_o_noatime)
922 #endif
923 #ifdef SO_NO_CHECK
924 IF_SOCKET ("nocheck", &opt_so_no_check)
925 #endif
926 IF_OPEN ("noctty", &opt_o_noctty)
927 #ifdef TCP_NODELAY
928 IF_TCP ("nodelay", &opt_tcp_nodelay)
929 #endif
930 #if WITH_EXT2 && defined(EXT2_NODUMP_FL)
931 IF_ANY ("nodump", &opt_ext2_nodump)
932 #endif
933 #if HAVE_REGEX_H
934 IF_READLINE("noecho", &opt_noecho)
935 #endif /* HAVE_REGEX_H */
936 IF_TERMIOS("noflsh", &opt_noflsh)
937 #ifdef O_NOFOLLOW
938 IF_OPEN ("nofollow", &opt_o_nofollow)
939 #endif
940 IF_EXEC ("nofork", &opt_nofork)
941 #ifdef O_NOINHERIT
942 IF_ANY ("noinherit", &opt_o_noinherit)
943 #endif
944 IF_ANY ("nonblock", &opt_nonblock)
945 #ifdef TCP_NOOPT
946 IF_TCP ("noopt", &opt_tcp_noopt)
947 #endif
948 IF_READLINE("noprompt", &opt_noprompt)
949 #ifdef TCP_NOPUSH
950 IF_TCP ("nopush", &opt_tcp_nopush)
951 #endif
952 #ifdef SO_NOREUSEADDR /* AIX 4.3.3 */
953 IF_SOCKET ("noreuseaddr", &opt_so_noreuseaddr)
954 #endif /* SO_NOREUSEADDR */
955 IF_TUN ("notrailers", &opt_iff_notrailers)
956 #ifdef O_NSHARE
957 IF_OPEN ("nshare", &opt_o_nshare)
958 #endif
959 IF_SOCKET ("null-eof", &opt_null_eof)
960 IF_ANY ("o-append", &opt_append)
961 #ifdef O_ASYNC
962 IF_ANY ("o-async", &opt_async)
963 #endif
964 #ifdef O_BINARY
965 IF_OPEN ("o-binary", &opt_o_binary)
966 #endif
967 IF_OPEN ("o-creat", &opt_o_create)
968 IF_OPEN ("o-create", &opt_o_create)
969 #ifdef O_DEFER
970 IF_OPEN ("o-defer", &opt_o_defer)
971 #endif
972 #ifdef O_DELAY
973 IF_OPEN ("o-delay", &opt_o_delay)
974 #endif
975 #ifdef O_DIRECT
976 IF_OPEN ("o-direct", &opt_o_direct)
977 #endif
978 #ifdef O_DIRECTORY
979 IF_OPEN ("o-directory", &opt_o_directory)
980 #endif
981 #ifdef O_DSYNC
982 IF_OPEN ("o-dsync", &opt_o_dsync)
983 #endif
984 IF_OPEN ("o-excl", &opt_o_excl)
985 #ifdef O_LARGEFILE
986 IF_OPEN ("o-largefile", &opt_o_largefile)
987 #endif
988 #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
989 IF_ANY ("o-ndelay", &opt_o_ndelay)
990 #else
991 IF_ANY ("o-ndelay", &opt_nonblock)
992 #endif
993 #ifdef O_NOATIME
994 IF_OPEN ("o-noatime", &opt_o_noatime)
995 #endif
996 IF_OPEN ("o-noctty", &opt_o_noctty)
997 #ifdef O_NOFOLLOW
998 IF_OPEN ("o-nofollow", &opt_o_nofollow)
999 #endif
1000 #ifdef O_NOINHERIT
1001 IF_ANY ("o-noinherit", &opt_o_noinherit)
1002 #endif
1003 IF_ANY ("o-nonblock", &opt_nonblock)
1004 #ifdef O_NSHARE
1005 IF_OPEN ("o-nshare", &opt_o_nshare)
1006 #endif
1007 #ifdef O_PRIV
1008 IF_OPEN ("o-priv", &opt_o_priv)
1009 #endif
1010 IF_OPEN ("o-rdonly", &opt_o_rdonly)
1011 IF_OPEN ("o-rdwr", &opt_o_rdwr)
1012 #ifdef O_RSHARE
1013 IF_OPEN ("o-rshare", &opt_o_rshare)
1014 #endif
1015 #ifdef O_RSYNC
1016 IF_OPEN ("o-rsync", &opt_o_rsync)
1017 #endif
1018 #ifdef O_SYNC
1019 IF_OPEN ("o-sync", &opt_o_sync)
1020 #endif
1021 #ifdef O_TEXT
1022 IF_ANY ("o-text", &opt_o_text)
1023 #endif
1024 IF_OPEN ("o-trunc", &opt_o_trunc)
1025 IF_OPEN ("o-wronly", &opt_o_wronly)
1026 IF_OPEN ("o_create", &opt_o_create)
1027 #ifdef O_DEFER
1028 IF_OPEN ("o_defer", &opt_o_defer)
1029 #endif
1030 #ifdef O_DELAY
1031 IF_OPEN ("o_delay", &opt_o_delay)
1032 #endif
1033 #ifdef O_DIRECT
1034 IF_OPEN ("o_direct", &opt_o_direct)
1035 #endif
1036 #ifdef O_DIRECTORY
1037 IF_OPEN ("o_directory", &opt_o_directory)
1038 #endif
1039 #ifdef O_DSYNC
1040 IF_OPEN ("o_dsync", &opt_o_dsync)
1041 #endif
1042 IF_OPEN ("o_excl", &opt_o_excl)
1043 #ifdef O_LARGEFILE
1044 IF_OPEN ("o_largefile", &opt_o_largefile)
1045 #endif
1046 #if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
1047 IF_ANY ("o_ndelay", &opt_o_ndelay)
1048 #else
1049 IF_ANY ("o_ndelay", &opt_nonblock)
1050 #endif
1051 IF_OPEN ("o_noctty", &opt_o_noctty)
1052 #ifdef O_NOFOLLOW
1053 IF_OPEN ("o_nofollow", &opt_o_nofollow)
1054 #endif
1055 #ifdef O_NSHARE
1056 IF_OPEN ("o_nshare", &opt_o_nshare)
1057 #endif
1058 #ifdef O_PRIV
1059 IF_OPEN ("o_priv", &opt_o_priv)
1060 #endif
1061 IF_OPEN ("o_rdonly", &opt_o_rdonly)
1062 IF_OPEN ("o_rdwr", &opt_o_rdwr)
1063 #ifdef O_RSHARE
1064 IF_OPEN ("o_rshare", &opt_o_rshare)
1065 #endif
1066 #ifdef O_RSYNC
1067 IF_OPEN ("o_rsync", &opt_o_rsync)
1068 #endif
1069 #ifdef O_SYNC
1070 IF_OPEN ("o_sync", &opt_o_sync)
1071 #endif
1072 IF_OPEN ("o_wronly", &opt_o_wronly)
1073 #ifdef OCRNL
1074 IF_TERMIOS("ocrnl", &opt_ocrnl)
1075 #endif
1076 #ifdef OFDEL
1077 IF_TERMIOS("ofdel", &opt_ofdel)
1078 #endif
1079 #ifdef OFILL
1080 IF_TERMIOS("ofill", &opt_ofill)
1081 #endif
1082 #ifdef OLCUC
1083 IF_TERMIOS("olcuc", &opt_olcuc)
1084 #endif
1085 IF_TERMIOS("onlcr", &opt_onlcr)
1086 #ifdef ONLRET
1087 IF_TERMIOS("onlret", &opt_onlret)
1088 #endif
1089 #ifdef ONOCR
1090 IF_TERMIOS("onocr", &opt_onocr)
1091 #endif
1092 IF_SOCKET ("oobinline", &opt_so_oobinline)
1093 #if HAVE_OPENPTY
1094 IF_EXEC ("openpty", &opt_openpty)
1095 #endif /* HAVE_OPENPTY */
1096 IF_OPENSSL("openssl-cafile", &opt_openssl_cafile)
1097 IF_OPENSSL("openssl-capath", &opt_openssl_capath)
1098 IF_OPENSSL("openssl-certificate", &opt_openssl_certificate)
1099 IF_OPENSSL("openssl-cipherlist", &opt_openssl_cipherlist)
1100 IF_OPENSSL("openssl-commonname", &opt_openssl_commonname)
1101 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
1102 IF_OPENSSL("openssl-compress", &opt_openssl_compress)
1103 #endif
1104 IF_OPENSSL("openssl-dhparam", &opt_openssl_dhparam)
1105 IF_OPENSSL("openssl-egd", &opt_openssl_egd)
1106 #if WITH_FIPS
1107 IF_OPENSSL("openssl-fips", &opt_openssl_fips)
1108 #endif
1109 IF_OPENSSL("openssl-key", &opt_openssl_key)
1110 IF_OPENSSL("openssl-method", &opt_openssl_method)
1111 IF_OPENSSL("openssl-pseudo", &opt_openssl_pseudo)
1112 IF_OPENSSL("openssl-verify", &opt_openssl_verify)
1113 IF_TERMIOS("opost", &opt_opost)
1114 #if defined(HAVE_TERMIOS_ISPEED) && defined(OSPEED_OFFSET) && (OSPEED_OFFSET != -1)
1115 IF_TERMIOS("ospeed", &opt_ospeed)
1116 #endif
1117 IF_ANY ("owner", &opt_user)
1118 IF_TERMIOS("parenb", &opt_parenb)
1119 IF_TERMIOS("parmrk", &opt_parmrk)
1120 IF_TERMIOS("parodd", &opt_parodd)
1121 #ifdef SO_PASSCRED
1122 IF_SOCKET ("passcred", &opt_so_passcred)
1123 #endif
1124 IF_EXEC ("path", &opt_path)
1125 #ifdef TCP_PAWS /* OSF1 */
1126 IF_TCP ("paws", &opt_tcp_paws)
1127 #endif
1128 #ifdef SO_PEERCRED
1129 IF_SOCKET ("peercred", &opt_so_peercred)
1130 #endif
1131 #ifdef PENDIN
1132 IF_TERMIOS("pendin", &opt_pendin)
1133 #endif
1134 IF_ANY ("perm", &opt_perm)
1135 IF_NAMED ("perm-early", &opt_perm_early)
1136 IF_ANY ("perm-late", &opt_perm_late)
1137 IF_SOCKET ("pf", &opt_protocol_family)
1138 IF_EXEC ("pgid", &opt_setpgid)
1139 IF_EXEC ("pipes", &opt_pipes)
1140 #ifdef IP_PKTINFO
1141 IF_IP ("pktinfo", &opt_ip_pktinfo)
1142 #endif
1143 #ifdef IP_PKTOPTIONS
1144 IF_IP ("pktoptions", &opt_ip_pktoptions)
1145 IF_IP ("pktopts", &opt_ip_pktoptions)
1146 #endif
1147 IF_TUN ("pointopoint", &opt_iff_pointopoint)
1148 #ifdef I_POP
1149 IF_ANY ("pop-all", &opt_streams_i_pop_all)
1150 #endif
1151 /*IF_IPAPP("port", &opt_port)*/
1152 IF_TUN ("portsel", &opt_iff_portsel)
1153 #if HAVE_RESOLV_H
1154 IF_IP ("primary", &opt_res_primary)
1155 #endif /* HAVE_RESOLV_H */
1156 #ifdef SO_PRIORITY
1157 IF_SOCKET ("priority", &opt_so_priority)
1158 #endif
1159 #ifdef O_PRIV
1160 IF_OPEN ("priv", &opt_o_priv)
1161 #endif
1162 IF_TUN ("promisc", &opt_iff_promisc)
1163 IF_READLINE("prompt", &opt_prompt)
1164 #ifdef SO_PROTOTYPE
1165 IF_SOCKET ("protocol", &opt_so_prototype)
1166 #endif
1167 IF_SOCKET ("protocol-family", &opt_protocol_family)
1168 #ifdef SO_PROTOTYPE
1169 IF_SOCKET ("prototype", &opt_so_prototype)
1170 #endif
1171 IF_PROXY ("proxy-auth", &opt_proxy_authorization)
1172 IF_PROXY ("proxy-authorization", &opt_proxy_authorization)
1173 IF_PROXY ("proxy-resolve", &opt_proxy_resolve)
1174 IF_PROXY ("proxyauth", &opt_proxy_authorization)
1175 IF_PROXY ("proxyport", &opt_proxyport)
1176 #ifdef ECHOPRT
1177 IF_TERMIOS("prterase", &opt_echoprt)
1178 #endif
1179 IF_OPENSSL("pseudo", &opt_openssl_pseudo)
1180 #if HAVE_DEV_PTMX || HAVE_DEV_PTC
1181 IF_EXEC ("ptmx", &opt_ptmx)
1182 #endif
1183 #if HAVE_PTY
1184 IF_EXEC ("pty", &opt_pty)
1185 #endif
1186 #if HAVE_PTY && HAVE_POLL
1187 IF_PTY ("pty-interval", &opt_pty_intervall)
1188 IF_PTY ("pty-intervall", &opt_pty_intervall)
1189 IF_PTY ("pty-wait-slave", &opt_pty_wait_slave)
1190 #endif /* HAVE_PTY && HAVE_POLL */
1191 #ifdef I_PUSH
1192 IF_ANY ("push", &opt_streams_i_push)
1193 #endif
1194 #ifdef TCP_QUICKACK
1195 IF_TCP ("quickack", &opt_tcp_quickack)
1196 #endif
1197 IF_TERMIOS("quit", &opt_vquit)
1198 IF_RANGE ("range", &opt_range)
1199 IF_TERMIOS("raw", &opt_raw)
1200 IF_TERMIOS("rawer", &opt_termios_rawer)
1201 IF_SOCKET ("rcvbuf", &opt_so_rcvbuf)
1202 IF_SOCKET ("rcvbuf-late", &opt_so_rcvbuf_late)
1203 #ifdef SO_RCVLOWAT
1204 IF_SOCKET ("rcvlowat", &opt_so_rcvlowat)
1205 #endif
1206 #ifdef SO_RCVTIMEO
1207 IF_SOCKET ("rcvtimeo", &opt_so_rcvtimeo)
1208 #endif
1209 IF_OPEN ("rdonly", &opt_o_rdonly)
1210 IF_OPEN ("rdwr", &opt_o_rdwr)
1211 IF_ANY ("readbytes", &opt_readbytes)
1212 #if HAVE_RESOLV_H
1213 IF_IP ("recurse", &opt_res_recurse)
1214 #endif /* HAVE_RESOLV_H */
1215 #ifdef IP_RECVDSTADDR
1216 IF_IP ("recvdstaddr", &opt_ip_recvdstaddr)
1217 #endif
1218 #ifdef IPV6_RECVDSTOPTS
1219 IF_IP6 ("recvdstopts", &opt_ipv6_recvdstopts)
1220 #endif
1221 #ifdef IP_RECVERR
1222 IF_IP ("recverr", &opt_ip_recverr)
1223 #endif
1224 #ifdef IPV6_RECVHOPLIMIT
1225 IF_IP6 ("recvhoplimit", &opt_ipv6_recvhoplimit)
1226 #endif
1227 #ifdef IPV6_RECVHOPOPTS
1228 IF_IP6 ("recvhopopts", &opt_ipv6_recvhopopts)
1229 #endif
1230 #ifdef IP_RECVIF
1231 IF_IP ("recvif", &opt_ip_recvif)
1232 #endif
1233 #ifdef IP_RECVOPTS
1234 IF_IP ("recvopts", &opt_ip_recvopts)
1235 #endif
1236 #ifdef IPV6_RECVPKTINFO
1237 IF_IP6 ("recvpktinfo", &opt_ipv6_recvpktinfo)
1238 #endif
1239 #ifdef IPV6_RECVRTHDR
1240 IF_IP6 ("recvrthdr", &opt_ipv6_recvrthdr)
1241 #endif
1242 #ifdef IP_RECVTOS
1243 IF_IP ("recvtos", &opt_ip_recvtos)
1244 #endif
1245 #ifdef IP_RECVTTL
1246 IF_IP ("recvttl", &opt_ip_recvttl)
1247 #endif
1248 IF_NAMED ("remove", &opt_unlink)
1249 #ifdef VREPRINT
1250 IF_TERMIOS("reprint", &opt_vreprint)
1251 #endif
1252 #if HAVE_RESOLV_H
1253 IF_IP ("res-aaonly", &opt_res_aaonly)
1254 IF_IP ("res-debug", &opt_res_debug)
1255 IF_IP ("res-defnames", &opt_res_defnames)
1256 IF_IP ("res-dnsrch", &opt_res_dnsrch)
1257 IF_IP ("res-igntc", &opt_res_igntc)
1258 IF_IP ("res-primary", &opt_res_primary)
1259 IF_IP ("res-recurse", &opt_res_recurse)
1260 IF_IP ("res-stayopen", &opt_res_stayopen)
1261 IF_IP ("res-usevc", &opt_res_usevc)
1262 #endif /* HAVE_RESOLV_H */
1263 IF_PROXY ("resolv", &opt_proxy_resolve)
1264 IF_PROXY ("resolve", &opt_proxy_resolve)
1265 #ifdef IP_RETOPTS
1266 IF_IP ("retopts", &opt_ip_retopts)
1267 #endif
1268 IF_RETRY ("retry", &opt_retry)
1269 IF_SOCKET ("reuseaddr", &opt_so_reuseaddr)
1270 #ifdef SO_REUSEPORT /* AIX 4.3.3 */
1271 IF_SOCKET ("reuseport", &opt_so_reuseport)
1272 #endif /* defined(SO_REUSEPORT) */
1273 #ifdef TCP_RFC1323
1274 IF_TCP ("rfc1323", &opt_tcp_rfc1323)
1275 #endif
1276 #ifdef IP_ROUTER_ALERT
1277 IF_IP ("routeralert", &opt_ip_router_alert)
1278 #endif
1279 #ifdef VREPRINT
1280 IF_TERMIOS("rprnt", &opt_vreprint)
1281 #endif
1282 #ifdef O_RSHARE
1283 IF_OPEN ("rshare", &opt_o_rshare)
1284 #endif
1285 #ifdef O_RSYNC
1286 IF_OPEN ("rsync", &opt_o_rsync)
1287 #endif
1288 #ifdef IPV6_RTHDR
1289 IF_IP6 ("rthdr", &opt_ipv6_rthdr)
1290 #endif
1291 IF_TUN ("running", &opt_iff_running)
1292 #ifdef TCP_SACK_DISABLE
1293 IF_TCP ("sack-disable", &opt_tcp_sack_disable)
1294 #endif
1295 #ifdef TCP_SACKENA /* OSF1 */
1296 IF_TCP ("sackena", &opt_tcp_sackena)
1297 #endif
1298 IF_TERMIOS("sane", &opt_sane)
1299 #ifdef SCTP_MAXSEG
1300 IF_SCTP ("sctp-maxseg", &opt_sctp_maxseg)
1301 IF_SCTP ("sctp-maxseg-late", &opt_sctp_maxseg_late)
1302 #endif
1303 #ifdef SCTP_NODELAY
1304 IF_SCTP ("sctp-nodelay", &opt_sctp_nodelay)
1305 #endif
1306 #if WITH_EXT2 && defined(EXT2_SECRM_FL)
1307 IF_ANY ("secrm", &opt_ext2_secrm)
1308 #endif
1309 #ifdef SO_SECURITY_AUTHENTICATION
1310 IF_SOCKET ("security-authentication", &opt_so_security_authentication)
1311 #endif
1312 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
1313 IF_SOCKET ("security-encryption-network", &opt_so_security_encryption_network)
1314 #endif
1315 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
1316 IF_SOCKET ("security-encryption-transport", &opt_so_security_encryption_transport)
1317 #endif
1318 #ifdef SO_SECURITY_AUTHENTICATION
1319 IF_SOCKET ("securityauthentication", &opt_so_security_authentication)
1320 #endif
1321 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
1322 IF_SOCKET ("securityencryptionnetwork", &opt_so_security_encryption_network)
1323 #endif
1324 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
1325 IF_SOCKET ("securityencryptiontransport", &opt_so_security_encryption_transport)
1326 #endif
1327 #if HAVE_LSEEK64
1328 IF_ANY ("seek", &opt_lseek64_set)
1329 IF_ANY ("seek-cur", &opt_lseek64_cur)
1330 IF_ANY ("seek-end", &opt_lseek64_end)
1331 IF_ANY ("seek-set", &opt_lseek64_set)
1332 #else
1333 IF_ANY ("seek", &opt_lseek32_set)
1334 IF_ANY ("seek-cur", &opt_lseek32_cur)
1335 IF_ANY ("seek-end", &opt_lseek32_end)
1336 IF_ANY ("seek-set", &opt_lseek32_set)
1337 #endif
1338 IF_ANY ("setgid", &opt_setgid)
1339 IF_ANY ("setgid-early", &opt_setgid_early)
1340 IF_ANY ("setlk", &opt_f_setlk_wr)
1341 IF_ANY ("setlk-rd", &opt_f_setlk_rd)
1342 IF_ANY ("setlk-wr", &opt_f_setlk_wr)
1343 IF_ANY ("setlkw", &opt_f_setlkw_wr)
1344 IF_ANY ("setlkw-rd", &opt_f_setlkw_rd)
1345 IF_ANY ("setlkw-wr", &opt_f_setlkw_wr)
1346 IF_EXEC ("setpgid", &opt_setpgid)
1347 #if WITH_EXEC || WITH_SYSTEM
1348 IF_EXEC ("setsid", &opt_setsid)
1349 #endif
1350 IF_SOCKET ("setsockopt-bin", &opt_setsockopt_bin)
1351 IF_SOCKET ("setsockopt-int", &opt_setsockopt_int)
1352 IF_SOCKET ("setsockopt-string", &opt_setsockopt_string)
1353 IF_ANY ("setuid", &opt_setuid)
1354 IF_ANY ("setuid-early", &opt_setuid_early)
1355 IF_ANY ("shut-close", &opt_shut_close)
1356 IF_ANY ("shut-down", &opt_shut_down)
1357 IF_ANY ("shut-none", &opt_shut_none)
1358 IF_ANY ("shut-null", &opt_shut_null)
1359 #if WITH_EXEC || WITH_SYSTEM
1360 IF_ANY ("sid", &opt_setsid)
1361 #endif
1362 IF_EXEC ("sighup", &opt_sighup)
1363 IF_EXEC ("sigint", &opt_sigint)
1364 #ifdef TCP_SIGNATURE_ENABLE
1365 IF_TCP ("signature-enable", &opt_tcp_signature_enable)
1366 #endif
1367 IF_EXEC ("sigquit", &opt_sigquit)
1368 #ifdef SIOCSPGRP
1369 IF_SOCKET ("siocspgrp", &opt_siocspgrp)
1370 #endif
1371 IF_TUN ("slave", &opt_iff_slave)
1372 IF_SOCKET ("sndbuf", &opt_so_sndbuf)
1373 IF_SOCKET ("sndbuf-late", &opt_so_sndbuf_late)
1374 #ifdef SO_SNDLOWAT
1375 IF_SOCKET ("sndlowat", &opt_so_sndlowat)
1376 #endif
1377 #ifdef SO_SNDTIMEO
1378 IF_SOCKET ("sndtimeo", &opt_so_sndtimeo)
1379 #endif
1380 #ifdef SO_ACCEPTCONN /* AIX433 */
1381 IF_SOCKET ("so-acceptconn", &opt_so_acceptconn)
1382 #endif /* SO_ACCEPTCONN */
1383 #ifdef SO_ATTACH_FILTER
1384 IF_SOCKET ("so-attach-filter", &opt_so_attach_filter)
1385 #endif
1386 #ifdef SO_AUDIT /* AIX 4.3.3 */
1387 IF_SOCKET ("so-audit", &opt_so_audit)
1388 #endif /* SO_AUDIT */
1389 #ifdef SO_BINDTODEVICE
1390 IF_SOCKET ("so-bindtodevice", &opt_so_bindtodevice)
1391 #endif
1392 IF_SOCKET ("so-broadcast", &opt_so_broadcast)
1393 #ifdef SO_BSDCOMPAT
1394 IF_SOCKET ("so-bsdcompat", &opt_so_bsdcompat)
1395 #endif
1396 #ifdef SO_CKSUMRECV
1397 IF_SOCKET ("so-cksumrecv", &opt_so_cksumrecv)
1398 #endif /* SO_CKSUMRECV */
1399 IF_SOCKET ("so-debug", &opt_so_debug)
1400 #ifdef SO_DETACH_FILTER
1401 IF_SOCKET ("so-detach-filter", &opt_so_detach_filter)
1402 #endif
1403 #ifdef SO_DGRAM_ERRIND
1404 IF_SOCKET ("so-dgram-errind", &opt_so_dgram_errind)
1405 #endif
1406 #ifdef SO_DONTLINGER
1407 IF_SOCKET ("so-dontlinger", &opt_so_dontlinger)
1408 #endif
1409 IF_SOCKET ("so-dontroute", &opt_so_dontroute)
1410 IF_SOCKET ("so-error", &opt_so_error)
1411 IF_SOCKET ("so-keepalive", &opt_so_keepalive)
1412 #ifdef SO_KERNACCEPT /* AIX 4.3.3 */
1413 IF_SOCKET ("so-kernaccept", &opt_so_kernaccept)
1414 #endif /* SO_KERNACCEPT */
1415 IF_SOCKET ("so-linger", &opt_so_linger)
1416 #ifdef SO_NO_CHECK
1417 IF_SOCKET ("so-no-check", &opt_so_no_check)
1418 #endif
1419 #ifdef SO_NOREUSEADDR /* AIX 4.3.3 */
1420 IF_SOCKET ("so-noreuseaddr", &opt_so_noreuseaddr)
1421 #endif /* SO_NOREUSEADDR */
1422 IF_SOCKET ("so-oobinline", &opt_so_oobinline)
1423 #ifdef SO_PASSCRED
1424 IF_SOCKET ("so-passcred", &opt_so_passcred)
1425 #endif
1426 #ifdef SO_PEERCRED
1427 IF_SOCKET ("so-peercred", &opt_so_peercred)
1428 #endif
1429 #ifdef SO_PRIORITY
1430 IF_SOCKET ("so-priority", &opt_so_priority)
1431 #endif
1432 #ifdef SO_PROTOTYPE
1433 IF_SOCKET ("so-prototype", &opt_so_prototype)
1434 #endif
1435 IF_SOCKET ("so-rcvbuf", &opt_so_rcvbuf)
1436 IF_SOCKET ("so-rcvbuf-late", &opt_so_rcvbuf_late)
1437 #ifdef SO_RCVLOWAT
1438 IF_SOCKET ("so-rcvlowat", &opt_so_rcvlowat)
1439 #endif
1440 #ifdef SO_RCVTIMEO
1441 IF_SOCKET ("so-rcvtimeo", &opt_so_rcvtimeo)
1442 #endif
1443 IF_SOCKET ("so-reuseaddr", &opt_so_reuseaddr)
1444 #ifdef SO_REUSEPORT /* AIX 4.3.3 */
1445 IF_SOCKET ("so-reuseport", &opt_so_reuseport)
1446 #endif /* defined(SO_REUSEPORT) */
1447 #ifdef SO_SECURITY_AUTHENTICATION
1448 IF_SOCKET ("so-security-authentication", &opt_so_security_authentication)
1449 #endif
1450 #ifdef SO_SECURITY_ENCRYPTION_NETWORK
1451 IF_SOCKET ("so-security-encryption-network", &opt_so_security_encryption_network)
1452 #endif
1453 #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT
1454 IF_SOCKET ("so-security-encryption-transport", &opt_so_security_encryption_transport)
1455 #endif
1456 IF_SOCKET ("so-sndbuf", &opt_so_sndbuf)
1457 IF_SOCKET ("so-sndbuf-late", &opt_so_sndbuf_late)
1458 #ifdef SO_SNDLOWAT
1459 IF_SOCKET ("so-sndlowat", &opt_so_sndlowat)
1460 #endif
1461 #ifdef SO_SNDTIMEO
1462 IF_SOCKET ("so-sndtimeo", &opt_so_sndtimeo)
1463 #endif
1464 #ifdef SO_TIMESTAMP
1465 IF_SOCKET ("so-timestamp", &opt_so_timestamp)
1466 #endif
1467 IF_SOCKET ("so-type", &opt_so_type)
1468 #ifdef SO_USE_IFBUFS
1469 IF_SOCKET ("so-use-ifbufs", &opt_so_use_ifbufs)
1470 #endif /* SO_USE_IFBUFS */
1471 #ifdef SO_USELOOPBACK /* AIX433, Solaris */
1472 IF_SOCKET ("so-useloopback", &opt_so_useloopback)
1473 #endif /* SO_USELOOPBACK */
1474 IF_SOCKET ("sockopt-bin", &opt_setsockopt_bin)
1475 IF_SOCKET ("sockopt-int", &opt_setsockopt_int)
1476 IF_SOCKET ("sockopt-string", &opt_setsockopt_string)
1477 IF_SOCKS4 ("socksport", &opt_socksport)
1478 IF_SOCKS4 ("socksuser", &opt_socksuser)
1479 IF_SOCKET ("socktype", &opt_so_type)
1480 IF_IPAPP ("sourceport", &opt_sourceport)
1481 IF_IPAPP ("sp", &opt_sourceport)
1482 IF_TERMIOS("start", &opt_vstart)
1483 #if HAVE_RESOLV_H
1484 IF_IP ("stayopen", &opt_res_stayopen)
1485 #endif /* HAVE_RESOLV_H */
1486 IF_EXEC ("stderr", &opt_stderr)
1487 #ifdef TCP_STDURG
1488 IF_TCP ("stdurg", &opt_tcp_stdurg)
1489 #endif
1490 IF_TERMIOS("stop", &opt_vstop)
1491 #ifdef I_POP
1492 IF_ANY ("streams-i-pop-all", &opt_streams_i_pop_all)
1493 #endif
1494 #ifdef I_PUSH
1495 IF_ANY ("streams-i-push", &opt_streams_i_push)
1496 #endif
1497 IF_ANY ("su", &opt_substuser)
1498 #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
1499 IF_ANY ("su-d", &opt_substuser_delayed)
1500 #endif
1501 IF_ANY ("su-e", &opt_substuser_early)
1502 IF_ANY ("substuser", &opt_substuser)
1503 #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
1504 IF_ANY ("substuser-delayed", &opt_substuser_delayed)
1505 #endif
1506 IF_ANY ("substuser-early", &opt_substuser_early)
1507 IF_TERMIOS("susp", &opt_vsusp)
1508 #ifdef VSWTC
1509 IF_TERMIOS("swtc", &opt_vswtc)
1510 IF_TERMIOS("swtch", &opt_vswtc)
1511 #endif
1512 IF_PTY ("symbolic-link", &opt_symbolic_link)
1513 #ifdef O_SYNC
1514 IF_OPEN ("sync", &opt_o_sync)
1515 #elif EXT2_SYNC_FL
1516 IF_ANY ("sync", &opt_ext2_sync)
1517 #endif
1518 #ifdef TCP_SYNCNT
1519 IF_TCP ("syncnt", &opt_tcp_syncnt)
1520 #endif
1521 #ifdef TABDLY
1522 # ifdef TAB0
1523 IF_TERMIOS("tab0", &opt_tab0)
1524 # endif
1525 # ifdef TAB1
1526 IF_TERMIOS("tab1", &opt_tab1)
1527 # endif
1528 # ifdef TAB2
1529 IF_TERMIOS("tab2", &opt_tab2)
1530 # endif
1531 # ifdef TAB3
1532 IF_TERMIOS("tab3", &opt_tab3)
1533 # endif
1534 # if TABDLY_SHIFT >= 0
1535 IF_TERMIOS("tabdly", &opt_tabdly)
1536 # endif
1537 #endif
1538 IF_TERMIOS("tandem", &opt_ixoff)
1539 #ifdef TCP_ABORT_THRESHOLD /* HP_UX */
1540 IF_TCP ("tcp-abort-threshold", &opt_tcp_abort_threshold)
1541 #endif
1542 #ifdef TCP_CONN_ABORT_THRESHOLD /* HP_UX */
1543 IF_TCP ("tcp-conn-abort-threshold", &opt_tcp_conn_abort_threshold)
1544 #endif
1545 #ifdef TCP_CORK
1546 IF_TCP ("tcp-cork", &opt_tcp_cork)
1547 #endif
1548 #ifdef TCP_DEFER_ACCEPT /* Linux 2.4.0 */
1549 IF_TCP ("tcp-defer-accept", &opt_tcp_defer_accept)
1550 #endif
1551 #ifdef TCP_INFO /* Linux 2.4.0 */
1552 IF_TCP ("tcp-info", &opt_tcp_info)
1553 #endif
1554 #ifdef TCP_KEEPCNT /* Linux 2.4.0 */
1555 IF_TCP ("tcp-keepcnt", &opt_tcp_keepcnt)
1556 #endif
1557 #ifdef TCP_KEEPIDLE /* Linux 2.4.0 */
1558 IF_TCP ("tcp-keepidle", &opt_tcp_keepidle)
1559 #endif
1560 #ifdef TCP_KEEPINIT /* OSF1 */
1561 IF_TCP ("tcp-keepinit", &opt_tcp_keepinit)
1562 #endif
1563 #ifdef TCP_KEEPINTVL /* Linux 2.4.0 */
1564 IF_TCP ("tcp-keepintvl", &opt_tcp_keepintvl)
1565 #endif
1566 #ifdef TCP_LINGER2 /* Linux 2.4.0 */
1567 IF_TCP ("tcp-linger2", &opt_tcp_linger2)
1568 #endif
1569 #ifdef TCP_MAXSEG
1570 IF_TCP ("tcp-maxseg", &opt_tcp_maxseg)
1571 IF_TCP ("tcp-maxseg-late", &opt_tcp_maxseg_late)
1572 #endif
1573 #ifdef TCP_MD5SIG
1574 IF_TCP ("tcp-md5sig", &opt_tcp_md5sig)
1575 #endif
1576 #ifdef TCP_NODELAY
1577 IF_TCP ("tcp-nodelay", &opt_tcp_nodelay)
1578 #endif
1579 #ifdef TCP_NOOPT
1580 IF_TCP ("tcp-noopt", &opt_tcp_noopt)
1581 #endif
1582 #ifdef TCP_NOPUSH
1583 IF_TCP ("tcp-nopush", &opt_tcp_nopush)
1584 #endif
1585 #ifdef TCP_PAWS /* OSF1 */
1586 IF_TCP ("tcp-paws", &opt_tcp_paws)
1587 #endif
1588 #ifdef TCP_QUICKACK
1589 IF_TCP ("tcp-quickack", &opt_tcp_quickack)
1590 #endif
1591 #ifdef TCP_RFC1323
1592 IF_TCP ("tcp-rfc1323", &opt_tcp_rfc1323)
1593 #endif
1594 #ifdef TCP_SACK_DISABLE
1595 IF_TCP ("tcp-sack-disable", &opt_tcp_sack_disable)
1596 #endif
1597 #ifdef TCP_SACKENA /* OSF1 */
1598 IF_TCP ("tcp-sackena", &opt_tcp_sackena)
1599 #endif
1600 #ifdef TCP_SIGNATURE_ENABLE
1601 IF_TCP ("tcp-signature-enable", &opt_tcp_signature_enable)
1602 #endif
1603 #ifdef TCP_STDURG
1604 IF_TCP ("tcp-stdurg", &opt_tcp_stdurg)
1605 #endif
1606 #ifdef TCP_SYNCNT /* Linux 2.4.0 */
1607 IF_TCP ("tcp-syncnt", &opt_tcp_syncnt)
1608 #endif
1609 #ifdef TCP_TSOPTENA /* OSF1 */
1610 IF_TCP ("tcp-tsoptena", &opt_tcp_tsoptena)
1611 #endif
1612 #ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */
1613 IF_TCP ("tcp-window-clamp", &opt_tcp_window_clamp)
1614 #endif
1615 #if WITH_LIBWRAP
1616 IF_IPAPP ("tcpwrap", &opt_tcpwrappers)
1617 IF_IPAPP ("tcpwrap-dir", &opt_tcpwrap_etc)
1618 IF_IPAPP ("tcpwrap-etc", &opt_tcpwrap_etc)
1619 #if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
1620 IF_IPAPP ("tcpwrap-hosts-allow-table", &opt_tcpwrap_hosts_allow_table)
1621 #endif
1622 #if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
1623 IF_IPAPP ("tcpwrap-hosts-deny-table", &opt_tcpwrap_hosts_deny_table)
1624 #endif
1625 IF_IPAPP ("tcpwrapper", &opt_tcpwrappers)
1626 IF_IPAPP ("tcpwrappers", &opt_tcpwrappers)
1627 #endif
1628 IF_TERMIOS("termios-cfmakeraw", &opt_termios_cfmakeraw)
1629 IF_TERMIOS("termios-rawer", &opt_termios_rawer)
1630 #ifdef O_TEXT
1631 IF_ANY ("text", &opt_o_text)
1632 #endif
1633 IF_UNIX ("tightsocklen", &xioopt_unix_tightsocklen)
1634 IF_TERMIOS("time", &opt_vtime)
1635 #ifdef SO_TIMESTAMP
1636 IF_SOCKET ("timestamp", &opt_so_timestamp)
1637 #endif
1638 IF_TERMIOS("tiocsctty", &opt_tiocsctty)
1639 #if WITH_EXT2 && defined(EXT2_TOPDIR_FL)
1640 IF_ANY ("topdir", &opt_ext2_topdir)
1641 #endif
1642 IF_IP ("tos", &opt_ip_tos)
1643 IF_TERMIOS("tostop", &opt_tostop)
1644 IF_OPEN ("trunc", &opt_o_trunc)
1645 #if HAVE_FTRUNCATE64
1646 IF_ANY ("truncate", &opt_ftruncate64)
1647 #else
1648 IF_ANY ("truncate", &opt_ftruncate32)
1649 #endif
1650 #ifdef TCP_TSOPTENA /* OSF1 */
1651 IF_TCP ("tsoptena", &opt_tcp_tsoptena)
1652 #endif
1653 IF_IP ("ttl", &opt_ip_ttl)
1654 IF_TUN ("tun-device", &opt_tun_device)
1655 IF_TUN ("tun-name", &opt_tun_name)
1656 IF_TUN ("tun-no-pi", &opt_iff_no_pi)
1657 IF_TUN ("tun-type", &opt_tun_type)
1658 IF_SOCKET ("type", &opt_so_type)
1659 IF_ANY ("uid", &opt_user)
1660 IF_NAMED ("uid-e", &opt_user_early)
1661 IF_ANY ("uid-l", &opt_user_late)
1662 IF_NAMED ("umask", &opt_umask)
1663 IF_IP6 ("unicast-hops", &opt_ipv6_unicast_hops)
1664 IF_UNIX ("unix-tightsocklen", &xioopt_unix_tightsocklen)
1665 IF_NAMED ("unlink", &opt_unlink)
1666 IF_NAMED ("unlink-close", &opt_unlink_close)
1667 IF_NAMED ("unlink-early", &opt_unlink_early)
1668 IF_NAMED ("unlink-late", &opt_unlink_late)
1669 #if WITH_EXT2 && defined(EXT2_UNRM_FL)
1670 IF_ANY ("unrm", &opt_ext2_unrm)
1671 #endif
1672 IF_TUN ("up", &opt_iff_up)
1673 #ifdef SO_USE_IFBUFS
1674 IF_SOCKET ("use-ifbufs", &opt_so_use_ifbufs)
1675 IF_SOCKET ("useifbufs", &opt_so_use_ifbufs)
1676 #endif /* SO_USE_IFBUFS */
1677 #ifdef SO_USELOOPBACK /* AIX433, Solaris */
1678 IF_SOCKET ("useloopback", &opt_so_useloopback)
1679 #endif /* SO_USELOOPBACK */
1680 IF_ANY ("user", &opt_user)
1681 IF_NAMED ("user-early", &opt_user_early)
1682 IF_ANY ("user-late", &opt_user_late)
1683 #if HAVE_RESOLV_H
1684 IF_IP ("usevc", &opt_res_usevc)
1685 #endif /* HAVE_RESOLV_H */
1686 #ifdef IPV6_V6ONLY
1687 IF_IP6 ("v6only", &opt_ipv6_v6only)
1688 #endif
1689 #ifdef VDISCARD
1690 IF_TERMIOS("vdiscard", &opt_vdiscard)
1691 #endif
1692 #ifdef VDSUSP /* HP-UX */
1693 IF_TERMIOS("vdsusp", &opt_vdsusp)
1694 #endif
1695 IF_TERMIOS("veof", &opt_veof)
1696 IF_TERMIOS("veol", &opt_veol)
1697 IF_TERMIOS("veol2", &opt_veol2)
1698 IF_TERMIOS("verase", &opt_verase)
1699 IF_OPENSSL("verify", &opt_openssl_verify)
1700 IF_TERMIOS("vintr", &opt_vintr)
1701 IF_TERMIOS("vkill", &opt_vkill)
1702 IF_TERMIOS("vlnext", &opt_vlnext)
1703 IF_TERMIOS("vmin", &opt_vmin)
1704 IF_TERMIOS("vquit", &opt_vquit)
1705 #ifdef VREPRINT
1706 IF_TERMIOS("vreprint", &opt_vreprint)
1707 #endif
1708 IF_TERMIOS("vstart", &opt_vstart)
1709 IF_TERMIOS("vstop", &opt_vstop)
1710 IF_TERMIOS("vsusp", &opt_vsusp)
1711 #ifdef VSWTC
1712 IF_TERMIOS("vswtc", &opt_vswtc)
1713 #endif
1714 #ifdef VTDLY
1715 # ifdef VT0
1716 IF_TERMIOS("vt0", &opt_vt0)
1717 # endif
1718 # ifdef VT1
1719 IF_TERMIOS("vt1", &opt_vt1)
1720 # endif
1721 IF_TERMIOS("vtdly", &opt_vtdly)
1722 #endif
1723 IF_TERMIOS("vtime", &opt_vtime)
1724 #ifdef VWERASE
1725 IF_TERMIOS("vwerase", &opt_vwerase)
1726 #endif
1727 #if HAVE_PTY && HAVE_POLL
1728 IF_PTY ("wait-slave", &opt_pty_wait_slave)
1729 #endif /* HAVE_PTY && HAVE_POLL */
1730 IF_ANY ("waitlock", &opt_waitlock)
1731 #if HAVE_PTY && HAVE_POLL
1732 IF_PTY ("waitslave", &opt_pty_wait_slave)
1733 #endif /* HAVE_PTY && HAVE_POLL */
1734 #ifdef VWERASE
1735 IF_TERMIOS("werase", &opt_vwerase)
1736 #endif
1737 #ifdef TCP_WINDOW_CLAMP /* Linux 2.4.0 */
1738 IF_TCP ("window-clamp", &opt_tcp_window_clamp)
1739 #endif
1740 #if WITH_LIBWRAP
1741 IF_IPAPP ("wrap", &opt_tcpwrappers)
1742 #endif
1743 IF_OPEN ("wronly", &opt_o_wronly)
1744 #ifdef XCASE
1745 IF_TERMIOS("xcase", &opt_xcase)
1746 #endif
1747 #if defined(TABDLY) && defined(XTABS)
1748 IF_TERMIOS("xtabs", &opt_xtabs)
1749 #endif
1750 { NULL }
1754 /* walks the text argument a and writes its options that conform to groups
1755 to the array opts. Uses the option table 'optionnames'.
1756 returns 0 on success, -1 on error, 1 on unknown/wrong option
1758 int parseopts(const char **a, unsigned int groups, struct opt **opts) {
1760 return parseopts_table(a, groups, opts, optionnames,
1761 sizeof(optionnames)/sizeof(struct optname)-1);
1765 /* walks the text argument a and writes its options that conform to groups
1766 to the array opts. Uses the specified option table.
1767 returns 0 on success, -1 on error, 1 on unknown/wrong option
1769 int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
1770 const struct optname optionnames[], size_t optionnum) {
1771 int i=0;
1772 struct opt *opt;
1773 bool assign;
1774 const char *a0 = *a;
1775 unsigned long ulongval;
1776 long slongval;
1777 long long slonglongval;
1778 char token[512], *tokp; size_t len;
1779 int parsres;
1780 int result;
1781 char optbuf[256]; size_t optlen;
1782 const char *endkey[6+1];
1783 const char *endval[5+1];
1784 const char *assign_str = "=";
1785 const char *hquotes[] = {
1786 "'",
1787 NULL
1789 const char *squotes[] = {
1790 "\"",
1791 NULL
1793 const char *nests[] = {
1794 "(", ")",
1795 "[", "]",
1796 "{", "}",
1797 NULL
1800 i = 0;
1801 /*endkey[i++] = xioopts.chainsep;*/ /* default: "|" */
1802 endkey[i++] = xioopts.pipesep; /* default: "!!" */
1803 endkey[i++] = ","/*xioopts.comma*/; /* default: "," */
1804 endkey[i++] = "=";
1805 endkey[i++] = NULL;
1807 i = 0;
1808 /*endval[i++] = xioopts.chainsep;*/ /* default: "|" */
1809 endval[i++] = xioopts.pipesep; /* default: "!!" */
1810 endval[i++] = ","/*xioopts.comma*/; /* default: "," */
1811 endval[i++] = NULL;
1813 i = 0;
1814 *opts = Malloc((i+8)*sizeof(struct opt));
1815 if (*opts == NULL) {
1816 return -1;
1818 if (*a == NULL) {
1819 (*opts)[i].desc = ODESC_END;
1820 return 0;
1823 while (true) {
1824 const struct optname *ent;
1826 if (a == NULL || *a == NULL || **a == '\0')
1827 break;
1829 while (!strncmp(*a, ",", strlen(","))) { (*a) += strlen(","); }
1830 a0 = *a;
1832 len = sizeof(token); tokp = token;
1833 parsres =
1834 nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
1835 true, true, false);
1836 if (parsres < 0) {
1837 Error1("option too long: \"%s\"", *a);
1838 return -1;
1839 } else if (parsres > 0) {
1840 Error1("syntax error in \"%s\"", *a);
1841 return -1;
1843 if (tokp == token) {
1844 /* no option found */
1845 break;
1847 *tokp = '\0';
1849 ent = (struct optname *)
1850 keyw((struct wordent *)optionnames, token, optionnum);
1851 if (ent == NULL) {
1852 Error1("parseopts(): unknown option \"%s\"", token);
1853 continue;
1856 if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
1857 !xioopts_ignoregroups) {
1858 Error1("parseopts(): option \"%s\" not supported with this address type",
1859 token /*a0*/);
1860 Info2("parseopts() groups=%08x, ent->group=%08x",
1861 groups, ent->desc->group);
1862 #if 0
1863 continue;
1864 #endif
1866 (*opts)[i].desc = ent->desc;
1868 if (!strncmp(*a, assign_str, strlen(assign_str))) {
1869 /* there is an assignment (mostly "=") */
1870 (*a) += strlen(assign_str);
1871 len = sizeof(token); tokp = token;
1872 parsres =
1873 nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
1874 true, true, false);
1875 if (parsres < 0) {
1876 Error1("option too long: \"%s\"", *a);
1877 return -1;
1878 } else if (parsres > 0) {
1879 Error1("syntax error in \"%s\"", *a);
1880 return -1;
1882 *tokp = '\0';
1883 assign = true;
1885 } else {
1886 assign = false;
1888 opt = &(*opts)[i];
1890 switch (ent->desc->type) {
1891 case TYPE_CONST:
1892 if (assign) {
1893 Error1("no value permitted for option \"%s\"",
1894 ent->desc->defname);
1895 continue;
1897 Info1("setting option \"%s\"", ent->desc->defname);
1898 break;
1899 case TYPE_BIN:
1900 if (!assign) { Error1("option \"%s\": value required", a0);
1901 continue; }
1902 optlen = 0;
1903 if ((result = dalan(token, optbuf, &optlen, sizeof(optbuf))) != 0) {
1904 Error1("parseopts(): problem with \"%s\" data", token);
1905 continue;
1907 if (((*opts)[i].value.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
1908 Error1("memdup(, "F_Zu"): out of memory", optlen);
1909 return -1;
1911 (*opts)[i].value.u_bin.b_len = optlen;
1912 break;
1913 case TYPE_BYTE:
1914 if (assign) {
1915 unsigned long ul;
1916 char *rest;
1917 ul = strtoul(token, &rest/*!*/, 0);
1918 if (ul > UCHAR_MAX) {
1919 Error3("parseopts(%s): byte value exceeds limit (%lu vs. %u), using max",
1920 a0, ul, UCHAR_MAX);
1921 (*opts)[i].value.u_byte = UCHAR_MAX;
1922 } else {
1923 (*opts)[i].value.u_byte = ul;
1925 } else {
1926 (*opts)[i].value.u_byte = 1;
1928 Info2("setting option \"%s\" to %d", ent->desc->defname,
1929 (*opts)[i].value.u_byte);
1930 break;
1931 #if HAVE_BASIC_OFF_T==3
1932 case TYPE_OFF32:
1933 #endif
1934 case TYPE_INT:
1935 if (assign) {
1936 char *rest;
1937 (*opts)[i].value.u_int = strtoul(token, &rest/*!*/, 0);
1938 } else {
1939 (*opts)[i].value.u_int = 1;
1941 Info2("setting option \"%s\" to %d", ent->desc->defname,
1942 (*opts)[i].value.u_int);
1943 break;
1944 case TYPE_BOOL:
1945 if (!assign) {
1946 (*opts)[i].value.u_bool = 1;
1947 } else {
1948 char *rest;
1949 (*opts)[i].value.u_bool = strtoul(token, &rest, 0);
1950 if (rest && *rest) {
1951 Error1("error in option \"%s\": \"0\" or \"1\" required", a0);
1954 Info2("setting option \"%s\" to %d", ent->desc->defname,
1955 (*opts)[i].value.u_bool);
1956 break;
1958 #if HAVE_BASIC_SIZE_T==4
1959 case TYPE_SIZE_T:
1960 #endif
1961 case TYPE_UINT:
1962 if (!assign) {
1963 (*opts)[i].value.u_uint = 1;
1964 } else {
1965 char *rest;
1966 ulongval = strtoul(token, &rest/*!*/, 0);
1967 if (ulongval > UINT_MAX) {
1968 Error3("parseopts(%s): unsigned int value exceeds limit (%lu vs. %u), using max",
1969 a0, ulongval, UINT_MAX);
1971 (*opts)[i].value.u_uint = ulongval;
1973 Info2("setting option \"%s\" to %u", ent->desc->defname,
1974 (*opts)[i].value.u_uint);
1975 break;
1977 #if HAVE_BASIC_SIZE_T==2
1978 case TYPE_SIZE_T:
1979 #endif
1980 case TYPE_USHORT:
1981 if (!assign) {
1982 (*opts)[i].value.u_ushort = 1;
1983 } else {
1984 char *rest;
1985 ulongval = strtoul(token, &rest/*!*/, 0);
1986 if (ulongval > USHRT_MAX) {
1987 Error3("parseopts(%s): unsigned short value exceeds limit (%lu vs. %u), using max",
1988 a0, ulongval, USHRT_MAX);
1990 (*opts)[i].value.u_ushort = ulongval;
1992 Info2("setting option \"%s\" to %u", ent->desc->defname,
1993 (*opts)[i].value.u_ushort);
1994 break;
1996 #if HAVE_BASIC_OFF_T==5
1997 case TYPE_OFF32:
1998 #endif
1999 #if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==5
2000 case TYPE_OFF64:
2001 #endif
2002 case TYPE_LONG:
2003 if (!assign) {
2004 (*opts)[i].value.u_long = 1;
2005 } else {
2006 char *rest;
2007 slongval = strtol(token, &rest, 0);
2008 (*opts)[i].value.u_long = slongval;
2010 Info2("setting option \"%s\" to %lu", ent->desc->defname,
2011 (*opts)[i].value.u_long);
2012 break;
2014 #if HAVE_BASIC_SIZE_T==6
2015 case TYPE_SIZE_T:
2016 #endif
2017 case TYPE_ULONG:
2018 if (!assign) {
2019 (*opts)[i].value.u_ulong = 1;
2020 } else {
2021 char *rest;
2022 ulongval = strtoul(token, &rest, 0);
2023 (*opts)[i].value.u_ulong = ulongval;
2025 Info2("setting option \"%s\" to %lu", ent->desc->defname,
2026 (*opts)[i].value.u_ulong);
2027 break;
2029 #if HAVE_BASIC_OFF_T==7
2030 case TYPE_OFF32:
2031 #endif
2032 #if HAVE_TYPE_LONGLONG
2033 case TYPE_LONGLONG:
2034 # if HAVE_STAT64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T==7
2035 case TYPE_OFF64:
2036 # endif
2037 if (!assign) {
2038 (*opts)[i].value.u_longlong = 1;
2039 } else {
2040 char *rest;
2041 # if HAVE_STRTOLL
2042 slonglongval = strtoll(token, &rest, 0);
2043 # else
2044 /* in this case, input value range is limited */
2045 slonglongval = strtol(token, &rest, 0);
2046 # endif /* HAVE_STRTOLL */
2047 (*opts)[i].value.u_longlong = slonglongval;
2049 Info2("setting option \"%s\" to %Lu", ent->desc->defname,
2050 (*opts)[i].value.u_longlong);
2051 break;
2052 #endif /* HAVE_TYPE_LONGLONG */
2054 case TYPE_UIDT:
2055 if (!assign) {
2056 Error1("option \"%s\": value required", a0);
2057 continue;
2059 if (isdigit((*token)&0xff)) {
2060 char *rest;
2061 (*opts)[i].value.u_uidt = strtoul(token, &rest/*!*/, 0);
2062 } else {
2063 struct passwd *pwd;
2064 if ((pwd = getpwnam(token)) == NULL) {
2065 Error1("getpwnam(\"%s\"): no such user", token);
2066 continue;
2068 (*opts)[i].value.u_uidt = getpwnam(token)->pw_uid;
2070 Info2("setting option \"%s\" to %u", ent->desc->defname,
2071 (*opts)[i].value.u_uidt);
2072 break;
2074 case TYPE_GIDT:
2075 if (!assign) { Error1("option \"%s\": value required", a0);
2076 continue; }
2077 if (isdigit((token[0])&0xff)) {
2078 char *rest;
2079 (*opts)[i].value.u_gidt = strtoul(token, &rest/*!*/, 0);
2080 } else {
2081 struct group *grp;
2082 grp = getgrnam(token);
2083 if (grp == NULL) {
2084 Error1("getgrnam(\"%s\"): no such group", token);
2085 continue;
2087 (*opts)[i].value.u_gidt = grp->gr_gid;
2089 Info2("setting option \"%s\" to %u", ent->desc->defname,
2090 (*opts)[i].value.u_gidt);
2091 break;
2093 case TYPE_MODET:
2094 if (!assign) { Error1("option \"%s\": value required", a0);
2095 continue;
2098 char *rest;
2099 (*opts)[i].value.u_modet = strtoul(token, &rest/*!*/, 8);
2101 Info2("setting option \"%s\" to %u", ent->desc->defname,
2102 (*opts)[i].value.u_modet);
2103 break;
2105 case TYPE_STRING:
2106 if (!assign) {
2107 Error1("option \"%s\": value required", a0);
2108 continue;
2110 if (((*opts)[i].value.u_string = strdup(token)) == NULL) {
2111 Error("out of memory"); return -1;
2113 Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
2114 (*opts)[i].value.u_string);
2115 break;
2117 case TYPE_STRING_NULL:
2118 if (!assign) {
2119 (*opts)[i].value.u_string = NULL;
2120 Info1("setting option \"%s\" to NULL", ent->desc->defname);
2121 } else {
2122 (*opts)[i].value.u_string = strdup(token);
2123 Info2("setting option \"%s\" to \"%s\"", ent->desc->defname,
2124 (*opts)[i].value.u_string);
2126 break;
2128 #if LATER
2129 case TYPE_INT3:
2131 break;
2132 #endif
2134 case TYPE_TIMEVAL:
2135 if (!assign) {
2136 Error1("option \"%s\": value required", a0);
2137 continue;
2138 } else {
2139 double val;
2140 val = strtod(token, NULL);
2141 if (val == HUGE_VAL || val == -HUGE_VAL ||
2142 val == 0.0 && errno == ERANGE) {
2143 Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
2144 val = 0.0;
2146 (*opts)[i].value.u_timeval.tv_sec = val;
2147 (*opts)[i].value.u_timeval.tv_usec =
2148 (val-(*opts)[i].value.u_timeval.tv_sec) * 1000000;
2150 break;
2152 #if HAVE_STRUCT_TIMESPEC
2153 case TYPE_TIMESPEC:
2154 if (!assign) {
2155 Error1("option \"%s\": value required", a0);
2156 continue;
2157 } else {
2158 double val;
2159 val = strtod(token, NULL);
2160 if (val == HUGE_VAL || val == -HUGE_VAL ||
2161 val == 0.0 && errno == ERANGE) {
2162 Error2("strtod(\"%s\", NULL): %s", token, strerror(errno));
2163 val = 0.0;
2165 (*opts)[i].value.u_timespec.tv_sec = val;
2166 (*opts)[i].value.u_timespec.tv_nsec =
2167 (val-(*opts)[i].value.u_timespec.tv_sec) * 1000000000.;
2169 break;
2170 #endif /* HAVE_STRUCT_TIMESPEC */
2172 #if HAVE_STRUCT_LINGER
2173 case TYPE_LINGER:
2174 if (!assign) {
2175 Error1("option \"%s\": value required", a0);
2176 continue;
2178 (*opts)[i].value.u_linger.l_onoff = 1;
2180 char *rest;
2181 (*opts)[i].value.u_linger.l_linger = strtoul(token, &rest/*!*/, 0);
2183 Info3("setting option \"%s\" to {%d,%d}", ent->desc->defname,
2184 (*opts)[i].value.u_linger.l_onoff,
2185 (*opts)[i].value.u_linger.l_linger);
2186 break;
2187 #endif /* HAVE_STRUCT_LINGER */
2189 case TYPE_INT_INT:
2190 case TYPE_INT_INTP:
2191 if (!assign) {
2192 Error1("option \"%s\": values required", a0);
2193 continue;
2196 char *rest;
2197 (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2198 if (*rest != ':') {
2199 Error1("option \"%s\": 2 arguments required",
2200 ent->desc->defname);
2202 ++rest;
2203 (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2205 Info3("setting option \"%s\" to %d:%d", ent->desc->defname,
2206 (*opts)[i].value.u_int, (*opts)[i].value2.u_int);
2207 break;
2209 case TYPE_INT_BIN:
2210 if (!assign) {
2211 Error1("option \"%s\": values required", a0);
2212 continue;
2215 char *rest;
2216 (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2217 if (*rest != ':') {
2218 Error1("option \"%s\": 2 arguments required",
2219 ent->desc->defname);
2221 ++rest;
2222 optlen = 0;
2223 if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) {
2224 Error1("parseopts(): problem with \"%s\" data", rest);
2225 continue;
2227 if (((*opts)[i].value2.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
2228 Error1("memdup(, "F_Zu"): out of memory", optlen);
2229 return -1;
2231 (*opts)[i].value2.u_bin.b_len = optlen;
2233 Info2("setting option \"%s\" to %d:..."/*!!!*/, ent->desc->defname,
2234 (*opts)[i].value.u_int);
2235 break;
2237 case TYPE_INT_STRING:
2238 if (!assign) {
2239 Error1("option \"%s\": values required", a0);
2240 continue;
2243 char *rest;
2244 (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2245 if (*rest != ':') {
2246 Error1("option \"%s\": 2 arguments required",
2247 ent->desc->defname);
2249 ++rest;
2250 if (((*opts)[i].value2.u_string = strdup(rest)) == NULL) {
2251 Error("out of memory"); return -1;
2254 Info3("setting option \"%s\" to %d:\"%s\"", ent->desc->defname,
2255 (*opts)[i].value.u_int, (*opts)[i].value2.u_string);
2256 break;
2258 case TYPE_INT_INT_INT:
2259 if (!assign) {
2260 Error1("option \"%s\": values required", a0);
2261 continue;
2264 char *rest;
2265 (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2266 if (*rest != ':') {
2267 Error1("option \"%s\": 3 arguments required",
2268 ent->desc->defname);
2270 ++rest;
2271 (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2272 if (*rest != ':') {
2273 Error1("option \"%s\": 3 arguments required",
2274 ent->desc->defname);
2276 ++rest;
2277 (*opts)[i].value3.u_int = strtoul(rest, &rest, 0);
2279 Info4("setting option \"%s\" to %d:%d:%d", ent->desc->defname,
2280 (*opts)[i].value.u_int, (*opts)[i].value2.u_int, (*opts)[i].value3.u_int);
2281 break;
2283 case TYPE_INT_INT_BIN:
2284 if (!assign) {
2285 Error1("option \"%s\": values required", a0);
2286 continue;
2289 char *rest;
2290 (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2291 if (*rest != ':') {
2292 Error1("option \"%s\": 3 arguments required",
2293 ent->desc->defname);
2295 ++rest;
2296 (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2297 if (*rest != ':') {
2298 Error1("option \"%s\": 3 arguments required",
2299 ent->desc->defname);
2301 ++rest;
2302 optlen = 0;
2303 if ((result = dalan(rest, optbuf, &optlen, sizeof(optbuf))) != 0) {
2304 Error1("parseopts(): problem with \"%s\" data", rest);
2305 continue;
2307 if (((*opts)[i].value3.u_bin.b_data = memdup(optbuf, optlen)) == NULL) {
2308 Error1("memdup(, "F_Zu"): out of memory", optlen);
2309 return -1;
2311 (*opts)[i].value3.u_bin.b_len = optlen;
2313 Info3("setting option \"%s\" to %d:%d:..."/*!!!*/, ent->desc->defname,
2314 (*opts)[i].value.u_int, (*opts)[i].value2.u_int);
2315 break;
2317 case TYPE_INT_INT_STRING:
2318 if (!assign) {
2319 Error1("option \"%s\": values required", a0);
2320 continue;
2323 char *rest;
2324 (*opts)[i].value.u_int = strtoul(token, &rest, 0);
2325 if (*rest != ':') {
2326 Error1("option \"%s\": 3 arguments required",
2327 ent->desc->defname);
2329 ++rest;
2330 (*opts)[i].value2.u_int = strtoul(rest, &rest, 0);
2331 if (*rest != ':') {
2332 Error1("option \"%s\": 3 arguments required",
2333 ent->desc->defname);
2335 ++rest;
2336 if (((*opts)[i].value3.u_string = strdup(rest)) == NULL) {
2337 Error("out of memory"); return -1;
2340 Info4("setting option \"%s\" to %d:%d:\"%s\"", ent->desc->defname,
2341 (*opts)[i].value.u_int, (*opts)[i].value2.u_int,
2342 (*opts)[i].value3.u_string);
2343 break;
2344 #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
2346 case TYPE_IP_MREQN:
2348 /* we do not resolve the addresses here because we do not yet know
2349 if we are coping with a IPv4 or IPv6 socat address */
2350 const char *ends[] = { ":", NULL };
2351 const char *nests[] = { "[","]", NULL };
2352 char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
2354 /* parse first IP address, expect ':' */
2355 tokp = token;
2356 /*! result= */
2357 parsres =
2358 nestlex((const char **)&tokp, &buffp, &bufspc,
2359 ends, NULL, NULL, nests,
2360 true, false, false);
2361 if (parsres < 0) {
2362 Error1("option too long: \"%s\"", *a);
2363 return -1;
2364 } else if (parsres > 0) {
2365 Error1("syntax error in \"%s\"", *a);
2366 return -1;
2368 if (*tokp != ':') {
2369 Error1("syntax in option %s: missing ':'", token);
2371 *buffp++ = '\0';
2372 (*opts)[i].value.u_ip_mreq.multiaddr = strdup(buff); /*!!! NULL */
2374 ++tokp;
2375 /* parse second IP address, expect ':' or '\0'' */
2376 buffp = buff;
2377 /*! result= */
2378 parsres =
2379 nestlex((const char **)&tokp, &buffp, &bufspc,
2380 ends, NULL, NULL, nests,
2381 true, false, false);
2382 if (parsres < 0) {
2383 Error1("option too long: \"%s\"", *a);
2384 return -1;
2385 } else if (parsres > 0) {
2386 Error1("syntax error in \"%s\"", *a);
2387 return -1;
2389 *buffp++ = '\0';
2390 (*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */
2392 #if HAVE_STRUCT_IP_MREQN
2393 if (*tokp++ == ':') {
2394 strncpy((*opts)[i].value.u_ip_mreq.ifindex, tokp, IF_NAMESIZE); /* ok */
2395 Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}",
2396 ent->desc->defname,
2397 (*opts)[i].value.u_ip_mreq.multiaddr,
2398 (*opts)[i].value.u_ip_mreq.param2,
2399 (*opts)[i].value.u_ip_mreq.ifindex);
2400 } else {
2401 (*opts)[i].value.u_ip_mreq.ifindex[0] = '\0';
2402 Info3("setting option \"%s\" to {\"%s\",\"%s\"}",
2403 ent->desc->defname,
2404 (*opts)[i].value.u_ip_mreq.multiaddr,
2405 (*opts)[i].value.u_ip_mreq.param2);
2407 #else /* !HAVE_STRUCT_IP_MREQN */
2408 Info3("setting option \"%s\" to {0x%08x,0x%08x}",
2409 ent->desc->defname,
2410 (*opts)[i].value.u_ip_mreq.multiaddr,
2411 (*opts)[i].value.u_ip_mreq.param2);
2412 #endif /* !HAVE_STRUCT_IP_MREQN */
2414 break;
2415 #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
2417 #if WITH_IP4
2418 case TYPE_IP4NAME:
2420 struct sockaddr_in sa; socklen_t salen = sizeof(sa);
2421 const char *ends[] = { NULL };
2422 const char *nests[] = { "[","]", NULL };
2423 char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
2425 tokp = token;
2426 parsres =
2427 nestlex((const char **)&tokp, &buffp, &bufspc,
2428 ends, NULL, NULL, nests,
2429 true, false, false);
2430 if (parsres < 0) {
2431 Error1("option too long: \"%s\"", *a);
2432 return -1;
2433 } else if (parsres > 0) {
2434 Error1("syntax error in \"%s\"", *a);
2435 return -1;
2437 if (*tokp != '\0') {
2438 Error1("trailing data in option \"%s\"", token);
2440 *buffp = '\0';
2441 if (xiogetaddrinfo(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
2442 (union sockaddr_union *)&sa, &salen,
2443 0, 0/*!!!*/) != STAT_OK) {
2444 opt->desc = ODESC_ERROR; continue;
2446 opt->value.u_ip4addr = sa.sin_addr;
2448 break;
2449 #endif /* defined(WITH_IP4) */
2451 default:
2452 Error2("parseopts(): internal error on option \"%s\": unimplemented type %d",
2453 ent->desc->defname, ent->desc->type);
2454 continue;
2457 ++i;
2458 if ((i % 8) == 0) {
2459 *opts = Realloc(*opts, (i+8) * sizeof(struct opt));
2460 if (*opts == NULL) {
2461 return -1;
2466 /*(*opts)[i+1].desc = ODESC_END;*/
2467 (*opts)[i].desc = ODESC_END;
2468 return 0;
2471 /* copy the already parsed options for repeated application, but only those
2472 matching groups ANY and <groups> */
2473 struct opt *copyopts(const struct opt *opts, unsigned int groups) {
2474 struct opt *new;
2475 int i, j, n;
2477 if (!opts) return NULL;
2479 /* just count the options in the array */
2480 i = 0; while (opts[i].desc != ODESC_END) {
2481 ++i;
2483 n = i+1;
2485 new = Malloc(n * sizeof(struct opt));
2486 if (new == NULL) {
2487 return NULL;
2490 i = 0, j = 0;
2491 while (i < n-1) {
2492 if (opts[i].desc == ODESC_DONE) {
2493 new[j].desc = ODESC_DONE;
2494 } else if ((opts[i].desc->group & (GROUP_ANY&~GROUP_PROCESS)) ||
2495 (opts[i].desc->group & groups)) {
2496 new[j++] = opts[i];
2498 ++i;
2500 new[j].desc = ODESC_END;
2501 return new;
2504 /* move options to a new options list
2505 move only those matching <groups> */
2506 struct opt *moveopts(struct opt *opts, unsigned int groups) {
2507 struct opt *new;
2508 int i, j, n;
2510 if (!opts) return NULL;
2512 /* just count the options in the array */
2513 i = 0; j = 0; while (opts[i].desc != ODESC_END) {
2514 if (opts[i].desc != ODESC_DONE &&
2515 opts[i].desc != ODESC_ERROR)
2516 ++j;
2517 ++i;
2519 n = i;
2521 new = Malloc((j+1) * sizeof(struct opt));
2522 if (new == NULL) {
2523 return NULL;
2526 i = 0, j = 0;
2527 while (i < n) {
2528 if (opts[i].desc == ODESC_DONE ||
2529 opts[i].desc == ODESC_ERROR) {
2530 ++i; continue;
2531 } else if (opts[i].desc->group & groups) {
2532 new[j++] = opts[i];
2533 opts[i].desc = ODESC_DONE;
2535 ++i;
2537 new[j].desc = ODESC_END;
2538 return new;
2541 /* return the number of yet unconsumed options; -1 on error */
2542 int leftopts(const struct opt *opts) {
2543 const struct opt *opt = opts;
2544 int num = 0;
2546 if (!opts) return 0;
2548 while (opt->desc != ODESC_END) {
2549 if (opt->desc != ODESC_DONE) {
2550 ++num;
2552 ++opt;
2554 return num;
2557 /* show as warning which options are still unused */
2558 int showleft(const struct opt *opts) {
2559 const struct opt *opt = opts;
2561 while (opt->desc != ODESC_END) {
2562 if (opt->desc != ODESC_DONE) {
2563 Warn1("showleft(): option \"%s\" not inquired", opt->desc->defname);
2565 ++opt;
2567 return 0;
2571 /* determines the address group from mode_t */
2572 /* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */
2573 int _groupbits(mode_t mode) {
2574 unsigned int result = 0;
2576 switch ((mode&S_IFMT)>>12) {
2577 case (S_IFIFO>>12): /* 1, FIFO */
2578 result = GROUP_FIFO; break;
2579 case (S_IFCHR>>12): /* 2, character device */
2580 result = GROUP_CHR|GROUP_TERMIOS; break;
2581 case (S_IFDIR>>12): /* 4, directory !!! not supported */
2582 result = GROUP_NONE; break;
2583 case (S_IFBLK>>12): /* 6, block device */
2584 result = GROUP_BLK; break;
2585 case (S_IFREG>>12): /* 8, regular file */
2586 result = GROUP_REG; break;
2587 case (S_IFLNK>>12): /* 10, symbolic link !!! not supported */
2588 result = GROUP_NONE; break;
2589 #ifdef S_IFSOCK
2590 case (S_IFSOCK>>12): /* 12, socket */
2591 result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
2592 #else
2593 default: /* some systems (pure POSIX.1) do not know S_IFSOCK */
2594 result = GROUP_SOCKET|GROUP_SOCK_UNIX; break;
2595 #endif
2597 Debug2("_groupbits(%d) -> %d", mode, result);
2598 return result;
2601 /* does not set GROUP_FD */
2602 int groupbits(int fd) {
2603 #if HAVE_STAT64
2604 struct stat64 buf;
2605 #else
2606 struct stat buf;
2607 #endif /* !HAVE_STAT64 */
2608 int result;
2610 if (
2611 #if HAVE_STAT64
2612 Fstat64(fd, &buf) < 0
2613 #else
2614 Fstat(fd, &buf) < 0
2615 #endif /* !HAVE_STAT64 */
2617 Error4("groupbits(%d): fstat(%d, %p): %s",
2618 fd, fd, &buf, strerror(errno));
2619 return -1;
2621 result = _groupbits(buf.st_mode&S_IFMT);
2622 if (result == GROUP_CHR) {
2623 if (Isatty(fd) > 0) {
2624 result |= GROUP_TERMIOS;
2627 return result;
2630 #if 0 /* currently not used */
2631 int retropt(struct opt *opts, int optcode, union integral *result) {
2632 struct opt *opt = opts;
2634 while (opt->desc != ODESC_END) {
2635 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2636 *result = opt->value;
2637 opt->desc = ODESC_DONE;
2638 return 0;
2640 ++opt;
2642 return -1;
2644 #endif
2646 static struct opt *xio_findopt(struct opt *opts, int optcode) {
2647 struct opt *opt = opts;
2649 while (opt->desc != ODESC_END) {
2650 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2651 return opt;
2653 ++opt;
2655 return NULL;
2658 int retropt_timespec(struct opt *opts, int optcode, struct timespec *result) {
2659 struct opt *opt;
2661 if (!(opt = xio_findopt(opts, optcode))) {
2662 return -1;
2664 *result = opt->value.u_timespec;
2665 opt->desc = ODESC_DONE;
2666 return 0;
2670 /* Looks for the first option of type <optcode>. If the option is found,
2671 this function stores its bool value in *result, "consumes" the
2672 option, and returns 0.
2673 If the option is not found, *result is not modified, and -1 is returned. */
2674 int retropt_bool(struct opt *opts, int optcode, bool *result) {
2675 struct opt *opt = opts;
2677 while (opt->desc != ODESC_END) {
2678 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2679 *result = opt->value.u_bool;
2680 opt->desc = ODESC_DONE;
2681 return 0;
2683 ++opt;
2685 return -1;
2688 #if 0 /* currently not used */
2689 /* Looks for the first option of type <optcode>. If the option is found,
2690 this function stores its short value in *result, "consumes" the
2691 option, and returns 0.
2692 If the option is not found, *result is not modified, and -1 is returned. */
2693 int retropt_short(struct opt *opts, int optcode, short *result) {
2694 struct opt *opt = opts;
2696 while (opt->desc != ODESC_END) {
2697 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2698 *result = opt->value.u_short;
2699 opt->desc = ODESC_DONE;
2700 return 0;
2702 ++opt;
2704 return -1;
2706 #endif
2708 /* Looks for the first option of type <optcode>. If the option is found,
2709 this function stores its unsigned short value in *result, "consumes" the
2710 option, and returns 0.
2711 If the option is not found, *result is not modified, and -1 is returned. */
2712 int retropt_ushort(struct opt *opts, int optcode, unsigned short *result) {
2713 struct opt *opt = opts;
2715 while (opt->desc != ODESC_END) {
2716 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2717 *result = opt->value.u_ushort;
2718 opt->desc = ODESC_DONE;
2719 return 0;
2721 ++opt;
2723 return -1;
2726 /* Looks for the first option of type <optcode>. If the option is found,
2727 this function stores its int value in *result, "consumes" the
2728 option, and returns 0.
2729 If the option is not found, *result is not modified, and -1 is returned. */
2730 int retropt_int(struct opt *opts, int optcode, int *result) {
2731 struct opt *opt = opts;
2733 while (opt->desc != ODESC_END) {
2734 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2735 switch (opt->desc->type) {
2736 case TYPE_INT: *result = opt->value.u_int; break;
2737 case TYPE_STRING: *result = strtol(opt->value.u_string, NULL, 0);
2738 break;
2739 default: Error2("cannot convert type %d of option %s to int",
2740 opt->desc->type, opt->desc->defname);
2741 opt->desc = ODESC_ERROR;
2742 return -1;
2744 opt->desc = ODESC_DONE;
2745 return 0;
2747 ++opt;
2749 return -1;
2752 /* Looks for the first option of type <optcode>. If the option is found,
2753 this function stores its unsigned int value in *result, "consumes" the
2754 option, and returns 0.
2755 If the option is not found, *result is not modified, and -1 is returned. */
2756 int retropt_uint(struct opt *opts, int optcode, unsigned int *result) {
2757 struct opt *opt = opts;
2759 while (opt->desc != ODESC_END) {
2760 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2761 *result = opt->value.u_uint;
2762 opt->desc = ODESC_DONE;
2763 return 0;
2765 ++opt;
2767 return -1;
2770 /* Looks for the first option of type <optcode>. If the option is found,
2771 this function stores its long value in *result, "consumes" the option,
2772 and returns 0.
2773 If the option is not found, *result is not modified, and -1 is returned. */
2774 int retropt_long(struct opt *opts, int optcode, long *result) {
2775 struct opt *opt = opts;
2777 while (opt->desc != ODESC_END) {
2778 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2779 *result = opt->value.u_long;
2780 opt->desc = ODESC_DONE;
2781 return 0;
2783 ++opt;
2785 return -1;
2788 /* Looks for the first option of type <optcode>. If the option is found,
2789 this function stores its unsigned long value in *result, "consumes" the
2790 option, and returns 0.
2791 If the option is not found, *result is not modified, and -1 is returned. */
2792 int retropt_ulong(struct opt *opts, int optcode, unsigned long *result) {
2793 struct opt *opt = opts;
2795 while (opt->desc != ODESC_END) {
2796 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2797 *result = opt->value.u_ulong;
2798 opt->desc = ODESC_DONE;
2799 return 0;
2801 ++opt;
2803 return -1;
2806 #if 0 /* currently not used */
2807 /* get the value of a FLAG typed option, and apply it to the appropriate
2808 bit position. Mark the option as consumed (done). return 0 if options was found and successfully applied,
2809 or -1 if option was not in opts */
2810 int retropt_flag(struct opt *opts, int optcode, flags_t *result) {
2811 struct opt *opt = opts;
2813 while (opt->desc != ODESC_END) {
2814 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2815 if (opt->value.u_bool) {
2816 *result |= opt->desc->major;
2817 } else {
2818 *result &= ~opt->desc->major;
2820 opt->desc = ODESC_DONE;
2821 return 0;
2823 ++opt;
2825 return -1;
2827 #endif
2829 /* Looks for the first option of type <optcode>. If the option is found,
2830 this function stores its character pointer value in *result, "consumes" the
2831 option, and returns 0. Note that, for options of type STRING_NULL, the
2832 character pointer might degenerate to NULL.
2833 The resulting string is malloc'ed and should be freed after use.
2834 If the option is not found, *result is not modified, and -1 is returned.
2836 int retropt_string(struct opt *opts, int optcode, char **result) {
2837 struct opt *opt = opts;
2839 while (opt->desc != ODESC_END) {
2840 if (opt->desc != ODESC_DONE && opt->desc->optcode == optcode) {
2841 if (opt->value.u_string == NULL) {
2842 *result = NULL;
2843 } else if ((*result = strdup(opt->value.u_string)) == NULL) {
2844 Error1("strdup("F_Zu"): out of memory",
2845 strlen(opt->value.u_string));
2846 return -1;
2848 opt->desc = ODESC_DONE;
2849 return 0;
2851 ++opt;
2853 return -1;
2857 #if _WITH_SOCKET
2858 /* looks for a bind option and, if found, overwrites the complete contents of
2859 sa with the appropriate value(s).
2860 returns STAT_OK if option exists and could be resolved,
2861 STAT_NORETRY if option exists but had error,
2862 or STAT_NOACTION if it does not exist */
2863 /* currently only for IP (v4, v6) and raw (PF_UNSPEC) */
2864 int retropt_bind(struct opt *opts,
2865 int af,
2866 int socktype,
2867 int ipproto,
2868 struct sockaddr *sa,
2869 socklen_t *salen,
2870 int feats, /* TCP etc: 1..address allowed,
2871 3..address and port allowed
2872 UNIX (or'd): 1..tight
2873 2..abstract
2875 unsigned long res_opts0, unsigned long res_opts1) {
2876 const char portsep[] = ":";
2877 const char *ends[] = { portsep, NULL };
2878 const char *nests[] = { "[", "]", NULL };
2879 bool portallowed;
2880 char *bindname, *bindp;
2881 char hostname[512], *hostp = hostname, *portp = NULL;
2882 size_t hostlen = sizeof(hostname)-1;
2883 int parsres;
2884 int result;
2886 if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
2887 return STAT_NOACTION;
2889 bindp = bindname;
2891 switch (af) {
2893 case AF_UNSPEC:
2895 size_t p = 0;
2896 dalan(bindname, (char *)sa->sa_data, &p, *salen-sizeof(sa->sa_family));
2897 *salen = p + sizeof(sa->sa_family);
2898 *salen = p +
2899 #if HAVE_STRUCT_SOCKADDR_SALEN
2900 sizeof(sa->sa_len) +
2901 #endif
2902 sizeof(sa->sa_family);
2903 #if HAVE_STRUCT_SOCKADDR_SALEN
2904 sa->sa_len = *salen;
2905 #endif
2907 break;
2909 #if WITH_IP4 || WITH_IP6
2910 #if WITH_IP4
2911 case AF_INET:
2912 #endif
2913 #if WITH_IP6
2914 case AF_INET6:
2915 #endif /*WITH_IP6 */
2916 portallowed = (feats>=2);
2917 parsres =
2918 nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
2919 true, false, false);
2920 if (parsres < 0) {
2921 Error1("option too long: \"%s\"", bindp);
2922 return STAT_NORETRY;
2923 } else if (parsres > 0) {
2924 Error1("syntax error in \"%s\"", bindp);
2925 return STAT_NORETRY;
2927 *hostp++ = '\0';
2928 if (!strncmp(bindp, portsep, strlen(portsep))) {
2929 if (!portallowed) {
2930 Error("port specification not allowed in this bind option");
2931 return STAT_NORETRY;
2932 } else {
2933 portp = bindp + strlen(portsep);
2936 if ((result =
2937 xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
2938 af, socktype, ipproto,
2939 (union sockaddr_union *)sa, salen,
2940 res_opts0, res_opts1))
2941 != STAT_OK) {
2942 Error("error resolving bind option");
2943 return STAT_NORETRY;
2945 break;
2946 #endif /* WITH_IP4 || WITH_IP6 */
2948 #if WITH_UNIX
2949 case AF_UNIX:
2951 bool abstract = (feats&2);
2952 bool tight = (feats&1);
2953 struct sockaddr_un *s_un = (struct sockaddr_un *)sa;
2954 *salen = xiosetunix(af, s_un, bindname, abstract, tight);
2956 break;
2957 #endif /* WITH_UNIX */
2959 default:
2960 Error1("bind: unknown address family %d", af);
2961 return STAT_NORETRY;
2963 return STAT_OK;
2965 #endif /* _WITH_SOCKET */
2968 /* applies to fd all options belonging to phase */
2969 /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
2970 implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
2971 OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
2972 int applyopts(int fd, struct opt *opts, enum e_phase phase) {
2973 struct opt *opt;
2975 opt = opts; while (opt && opt->desc != ODESC_END) {
2976 if (opt->desc == ODESC_DONE ||
2977 (phase != PH_ALL && opt->desc->phase != phase)) {
2978 ++opt; continue; }
2980 if (opt->desc->func == OFUNC_SEEK32) {
2981 if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) {
2982 Error4("lseek(%d, "F_off", %d): %s",
2983 fd, opt->value.u_off, opt->desc->major, strerror(errno));
2985 #if HAVE_LSEEK64
2986 } else if (opt->desc->func == OFUNC_SEEK64) {
2988 /*! this depends on off64_t atomic type */
2989 if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) {
2990 Error4("lseek64(%d, "F_off64", %d): %s",
2991 fd, opt->value.u_off64, opt->desc->major, strerror(errno));
2993 #endif /* HAVE_LSEEK64 */
2995 } else if (opt->desc->func == OFUNC_FCNTL) {
2996 int flag;
2998 /* retrieve existing flag setttings */
2999 if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) {
3000 Error3("fcntl(%d, %d): %s",
3001 fd, opt->desc->major, strerror(errno));
3002 opt->desc = ODESC_ERROR; ++opt; continue;
3003 } else {
3004 if (opt->value.u_bool) {
3005 flag |= opt->desc->minor;
3006 } else {
3007 flag &= ~opt->desc->minor;
3009 if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
3010 Error4("fcntl(%d, %d, %d): %s",
3011 fd, opt->desc->major, flag, strerror(errno));
3012 opt->desc = ODESC_ERROR; ++opt; continue;
3016 } else if (opt->desc->func == OFUNC_IOCTL) {
3017 if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) {
3018 Error4("ioctl(%d, 0x%x, %p): %s",
3019 fd, opt->desc->major, (void *)&opt->value, strerror(errno));
3020 opt->desc = ODESC_ERROR; ++opt; continue;
3023 } else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) {
3024 long val;
3025 int getreq = opt->desc->major;
3026 int setreq = opt->desc->minor;
3027 long mask = opt->desc->arg3;
3029 if (Ioctl(fd, getreq, (void *)&val) < 0) {
3030 Error4("ioctl(%d, 0x%x, %p): %s",
3031 fd, opt->desc->major, (void *)&val, strerror(errno));
3032 opt->desc = ODESC_ERROR; ++opt; continue;
3034 val &= ~mask;
3035 if (opt->value.u_bool) val |= mask;
3036 if (Ioctl(fd, setreq, (void *)&val) < 0) {
3037 Error4("ioctl(%d, 0x%x, %p): %s",
3038 fd, opt->desc->major, (void *)&val, strerror(errno));
3039 opt->desc = ODESC_ERROR; ++opt; continue;
3042 } else if (opt->desc->func == OFUNC_IOCTL_GENERIC) {
3043 switch (opt->desc->type) {
3044 case TYPE_INT:
3045 if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
3046 Error3("ioctl(%d, 0x%x, NULL): %s",
3047 fd, opt->value.u_int, strerror(errno));
3048 opt->desc = ODESC_ERROR; ++opt; continue;
3050 break;
3051 case TYPE_INT_INT:
3052 if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) {
3053 Error4("ioctl(%d, 0x%x, 0x%x): %s",
3054 fd, opt->value.u_int, opt->value2.u_int, strerror(errno));
3055 opt->desc = ODESC_ERROR; ++opt; continue;
3057 break;
3058 case TYPE_INT_INTP:
3059 if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) {
3060 Error4("ioctl(%d, 0x%x, %p): %s",
3061 fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno));
3062 opt->desc = ODESC_ERROR; ++opt; continue;
3064 break;
3065 case TYPE_INT_BIN:
3066 if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) {
3067 Error4("ioctl(%d, 0x%x, %p): %s",
3068 fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno));
3069 opt->desc = ODESC_ERROR; ++opt; continue;
3071 break;
3072 case TYPE_INT_STRING:
3073 if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) {
3074 Error4("ioctl(%d, 0x%x, %p): %s",
3075 fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno));
3076 opt->desc = ODESC_ERROR; ++opt; continue;
3078 break;
3079 default:
3080 Error1("ioctl() data type %d not implemented",
3081 opt->desc->type);
3084 #if _WITH_SOCKET
3085 } else if (opt->desc->func == OFUNC_SOCKOPT) {
3086 if (0) {
3088 #if 0 && HAVE_STRUCT_LINGER
3089 } else if (opt->desc->optcode == OPT_SO_LINGER) {
3090 struct linger lingstru;
3091 lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0);
3092 lingstru.l_linger = opt->value.u_int;
3093 if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru,
3094 sizeof(lingstru)) < 0) {
3095 Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu,
3096 fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff,
3097 lingstru.l_linger, sizeof(lingstru));
3098 opt->desc = ODESC_ERROR; ++opt; continue;
3100 #endif /* HAVE_STRUCT_LINGER */
3101 } else {
3102 switch (opt->desc->type) {
3103 case TYPE_BIN:
3104 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3105 opt->value.u_bin.b_data, opt->value.u_bin.b_len)
3106 < 0) {
3107 Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s",
3108 fd, opt->desc->major, opt->desc->minor,
3109 opt->value.u_bin.b_data, opt->value.u_bin.b_len,
3110 strerror(errno));
3111 opt->desc = ODESC_ERROR; ++opt; continue;
3113 break;
3114 case TYPE_BOOL:
3115 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3116 &opt->value.u_bool, sizeof(opt->value.u_bool))
3117 < 0) {
3118 Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd,
3119 opt->desc->major, opt->desc->minor,
3120 opt->value.u_bool, sizeof(opt->value.u_bool),
3121 strerror(errno));
3122 opt->desc = ODESC_ERROR; ++opt; continue;
3124 break;
3125 case TYPE_BYTE:
3126 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3127 &opt->value.u_byte, sizeof(uint8_t)) < 0) {
3128 Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
3129 fd, opt->desc->major, opt->desc->minor,
3130 opt->value.u_byte, sizeof(uint8_t), strerror(errno));
3131 opt->desc = ODESC_ERROR; ++opt; continue;
3133 break;
3134 case TYPE_INT:
3135 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3136 &opt->value.u_int, sizeof(int)) < 0) {
3137 Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
3138 fd, opt->desc->major, opt->desc->minor,
3139 opt->value.u_int, sizeof(int), strerror(errno));
3140 opt->desc = ODESC_ERROR; ++opt; continue;
3142 break;
3143 case TYPE_LONG:
3144 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3145 &opt->value.u_long, sizeof(long)) < 0) {
3146 Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s",
3147 fd, opt->desc->major, opt->desc->minor,
3148 opt->value.u_long, sizeof(long), strerror(errno));
3149 opt->desc = ODESC_ERROR; ++opt; continue;
3151 break;
3152 case TYPE_STRING:
3153 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3154 opt->value.u_string,
3155 strlen(opt->value.u_string)+1) < 0) {
3156 Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
3157 fd, opt->desc->major, opt->desc->minor,
3158 opt->value.u_string, strlen(opt->value.u_string)+1,
3159 strerror(errno));
3160 opt->desc = ODESC_ERROR; ++opt; continue;
3162 break;
3163 case TYPE_UINT:
3164 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3165 &opt->value.u_uint, sizeof(unsigned int)) < 0) {
3166 Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s",
3167 fd, opt->desc->major, opt->desc->minor,
3168 opt->value.u_uint, sizeof(unsigned int),
3169 strerror(errno));
3170 opt->desc = ODESC_ERROR; ++opt; continue;
3172 break;
3173 case TYPE_TIMEVAL:
3174 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3175 &opt->value.u_timeval, sizeof(struct timeval)) < 0) {
3176 Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s",
3177 fd, opt->desc->major, opt->desc->minor,
3178 opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec,
3179 sizeof(struct timeval), strerror(errno));
3180 opt->desc = ODESC_ERROR; ++opt; continue;
3182 break;
3183 #if HAVE_STRUCT_LINGER
3184 case TYPE_LINGER:
3186 struct linger lingstru;
3187 lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0);
3188 lingstru.l_linger = opt->value.u_linger.l_linger;
3189 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3190 &lingstru, sizeof(lingstru)) < 0) {
3191 Error6("setsockopt(%d, %d, %d, {%d,%d}): %s",
3192 fd, opt->desc->major, opt->desc->minor,
3193 lingstru.l_onoff, lingstru.l_linger,
3194 strerror(errno));
3195 opt->desc = ODESC_ERROR; ++opt; continue;
3198 break;
3199 #endif /* HAVE_STRUCT_LINGER */
3200 #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)
3201 case TYPE_IP_MREQN:
3202 /* handled in applyopts_single */
3203 ++opt; continue;
3204 #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
3206 /*! still many types missing; implement on demand */
3207 #if WITH_IP4
3208 case TYPE_IP4NAME:
3209 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3210 &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) {
3211 Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s",
3212 fd, opt->desc->major, opt->desc->minor,
3213 *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr),
3214 strerror(errno));
3216 break;
3217 #endif /* defined(WITH_IP4) */
3218 default:
3219 #if !NDEBUG
3220 Error1("applyopts(): type %d not implemented",
3221 opt->desc->type);
3222 #else
3223 Warn1("applyopts(): type %d not implemented",
3224 opt->desc->type);
3225 #endif
3226 opt->desc = ODESC_ERROR; ++opt; continue;
3230 } else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) {
3231 switch (opt->desc->type) {
3232 uint8_t data[256];
3233 socklen_t oldlen, newlen;
3234 case TYPE_BIN:
3235 oldlen = sizeof(data);
3236 if (Getsockopt(fd, opt->desc->major, opt->desc->minor,
3237 data, &oldlen)
3238 < 0) {
3239 Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s",
3240 fd, opt->desc->major, opt->desc->minor, data, oldlen,
3241 strerror(errno));
3242 opt->desc = ODESC_ERROR; ++opt; continue;
3244 memcpy(&data[oldlen], opt->value.u_bin.b_data,
3245 MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen));
3246 newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen);
3247 if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
3248 data, newlen)
3249 < 0) {
3250 Error6("setsockopt(%d, %d, %d, %p, %d): %s",
3251 fd, opt->desc->major, opt->desc->minor, data, newlen,
3252 strerror(errno));
3253 opt->desc = ODESC_ERROR; ++opt; continue;
3255 break;
3256 default:
3257 Error2("internal: option \"%s\": unimplemented type %d",
3258 opt->desc->defname, opt->desc->type);
3259 break;
3261 } else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) {
3262 switch (opt->desc->type) {
3263 case TYPE_INT_INT_INT:
3264 if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
3265 &opt->value3.u_int, sizeof(int)) < 0) {
3266 Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s",
3267 fd, opt->value.u_int, opt->value2.u_int,
3268 opt->value3.u_int, sizeof(int), strerror(errno));
3270 break;
3271 case TYPE_INT_INT_BIN:
3272 if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
3273 opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) {
3274 Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s",
3275 fd, opt->value.u_int, opt->value2.u_int,
3276 opt->value3.u_bin.b_len, strerror(errno));
3278 break;
3279 case TYPE_INT_INT_STRING:
3280 if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
3281 opt->value3.u_string,
3282 strlen(opt->value3.u_string)+1) < 0) {
3283 Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s",
3284 fd, opt->value.u_int, opt->value2.u_int,
3285 opt->value3.u_string, strlen(opt->value3.u_string)+1,
3286 strerror(errno));
3288 break;
3289 default:
3290 Error1("setsockopt() data type %d not implemented",
3291 opt->desc->type);
3293 #endif /* _WITH_SOCKET */
3295 #if HAVE_FLOCK
3296 } else if (opt->desc->func == OFUNC_FLOCK) {
3297 if (Flock(fd, opt->desc->major) < 0) {
3298 Error3("flock(%d, %d): %s",
3299 fd, opt->desc->major, strerror(errno));
3300 opt->desc = ODESC_ERROR; ++opt; continue;
3302 #endif /* defined(HAVE_FLOCK) */
3304 } else if (opt->desc->func == OFUNC_SPEC ||
3305 opt->desc->func == OFUNC_FLAG) {
3306 switch (opt->desc->optcode) {
3307 case OPT_USER:
3308 case OPT_USER_LATE:
3309 if (Fchown(fd, opt->value.u_uidt, -1) < 0) {
3310 Error3("fchown(%d, "F_uid", -1): %s",
3311 fd, opt->value.u_uidt, strerror(errno));
3312 opt->desc = ODESC_ERROR; ++opt; continue;
3314 break;
3315 case OPT_GROUP:
3316 case OPT_GROUP_LATE:
3317 if (Fchown(fd, -1, opt->value.u_gidt) < 0) {
3318 Error3("fchown(%d, -1, "F_gid"): %s",
3319 fd, opt->value.u_gidt, strerror(errno));
3320 opt->desc = ODESC_ERROR; ++opt; continue;
3322 break;
3323 case OPT_PERM:
3324 case OPT_PERM_LATE:
3325 if (Fchmod(fd, opt->value.u_modet) < 0) {
3326 Error3("fchmod(%d, %u): %s",
3327 fd, opt->value.u_modet, strerror(errno));
3328 opt->desc = ODESC_ERROR; ++opt; continue;
3330 break;
3331 case OPT_FTRUNCATE32:
3332 if (Ftruncate(fd, opt->value.u_off) < 0) {
3333 Error3("ftruncate(%d, "F_off"): %s",
3334 fd, opt->value.u_off, strerror(errno));
3335 opt->desc = ODESC_ERROR; ++opt; continue;
3337 break;
3338 #if HAVE_FTRUNCATE64
3339 case OPT_FTRUNCATE64:
3340 if (Ftruncate64(fd, opt->value.u_off64) < 0) {
3341 Error3("ftruncate64(%d, "F_off64"): %s",
3342 fd, opt->value.u_off64, strerror(errno));
3343 opt->desc = ODESC_ERROR; ++opt; continue;
3345 #endif /* HAVE_FTRUNCATE64 */
3346 break;
3347 case OPT_F_SETLK_RD:
3348 case OPT_F_SETLK_WR:
3349 case OPT_F_SETLKW_RD:
3350 case OPT_F_SETLKW_WR:
3352 struct flock l; /* Linux: <asm/fcntl.h> */
3353 l.l_type = opt->desc->minor;
3354 l.l_whence = SEEK_SET;
3355 l.l_start = 0;
3356 l.l_len = LONG_MAX;
3357 l.l_pid = 0; /* hope this uses our current process */
3358 if (Fcntl_lock(fd, opt->desc->major, &l) < 0) {
3359 Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno));
3360 opt->desc = ODESC_ERROR; ++opt; continue;
3363 break;
3364 case OPT_SETUID_EARLY:
3365 case OPT_SETUID:
3366 if (Setuid(opt->value.u_uidt) < 0) {
3367 Error2("setuid("F_uid"): %s", opt->value.u_uidt,
3368 strerror(errno));
3369 opt->desc = ODESC_ERROR; ++opt; continue;
3371 break;
3372 case OPT_SETGID_EARLY:
3373 case OPT_SETGID:
3374 if (Setgid(opt->value.u_gidt) < 0) {
3375 Error2("setgid("F_gid"): %s", opt->value.u_gidt,
3376 strerror(errno));
3377 opt->desc = ODESC_ERROR; ++opt; continue;
3379 break;
3380 case OPT_SUBSTUSER_EARLY:
3381 case OPT_SUBSTUSER:
3383 struct passwd *pwd;
3384 if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
3385 Error1("getpwuid("F_uid"): no such user",
3386 opt->value.u_uidt);
3387 opt->desc = ODESC_ERROR; ++opt; continue;
3389 if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
3390 Error3("initgroups(%s, "F_gid"): %s",
3391 pwd->pw_name, pwd->pw_gid, strerror(errno));
3392 opt->desc = ODESC_ERROR; ++opt; continue;
3394 if (Setgid(pwd->pw_gid) < 0) {
3395 Error2("setgid("F_gid"): %s", pwd->pw_gid,
3396 strerror(errno));
3397 opt->desc = ODESC_ERROR; ++opt; continue;
3399 if (Setuid(opt->value.u_uidt) < 0) {
3400 Error2("setuid("F_uid"): %s", opt->value.u_uidt,
3401 strerror(errno));
3402 opt->desc = ODESC_ERROR; ++opt; continue;
3404 #if 1
3405 if (setenv("USER", pwd->pw_name, 1) < 0)
3406 Error1("setenv(\"USER\", \"%s\", 1): insufficient space",
3407 pwd->pw_name);
3408 if (setenv("LOGNAME", pwd->pw_name, 1) < 0)
3409 Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space",
3410 pwd->pw_name);
3411 if (setenv("HOME", pwd->pw_dir, 1) < 0)
3412 Error1("setenv(\"HOME\", \"%s\", 1): insufficient space",
3413 pwd->pw_dir);
3414 if (setenv("SHELL", pwd->pw_shell, 1) < 0)
3415 Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space",
3416 pwd->pw_shell);
3417 #endif
3419 break;
3420 #if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
3421 case OPT_SUBSTUSER_DELAYED:
3423 struct passwd *pwd;
3425 if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) {
3426 Error1("getpwuid("F_uid"): no such user",
3427 opt->value.u_uidt);
3428 opt->desc = ODESC_ERROR; ++opt; continue;
3430 delayeduser_uid = opt->value.u_uidt;
3431 delayeduser_gid = pwd->pw_gid;
3432 if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) {
3433 Error1("strdup("F_Zu"): out of memory",
3434 strlen(pwd->pw_name)+1);
3435 opt->desc = ODESC_ERROR; ++opt; continue;
3437 if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) {
3438 Error1("strdup("F_Zu"): out of memory",
3439 strlen(pwd->pw_dir)+1);
3440 opt->desc = ODESC_ERROR; ++opt; continue;
3442 if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) {
3443 Error1("strdup("F_Zu"): out of memory",
3444 strlen(pwd->pw_shell)+1);
3445 opt->desc = ODESC_ERROR; ++opt; continue;
3447 /* function to get all supplementary groups of user */
3448 delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t);
3449 getusergroups(delayeduser_name, delayeduser_gids,
3450 &delayeduser_ngids);
3451 delayeduser = true;
3453 break;
3454 #endif
3455 case OPT_CHROOT_EARLY:
3456 case OPT_CHROOT:
3457 if (Chroot(opt->value.u_string) < 0) {
3458 Error2("chroot(\"%s\"): %s", opt->value.u_string,
3459 strerror(errno));
3460 opt->desc = ODESC_ERROR; ++opt; continue;
3462 if (Chdir("/") < 0) {
3463 Error1("chdir(\"/\"): %s", strerror(errno));
3465 break;
3466 case OPT_SETSID:
3467 if (Setsid() < 0) {
3468 Warn1("setsid(): %s", strerror(errno));
3469 if (Setpgid(getpid(), getppid()) < 0) {
3470 Warn3("setpgid(%d, %d): %s",
3471 getpid(), getppid(), strerror(errno));
3472 } else {
3473 if (Setsid() < 0) {
3474 Error1("setsid(): %s", strerror(errno));
3478 break;
3479 case OPT_SETPGID:
3480 if (Setpgid(0, opt->value.u_int) < 0) {
3481 Warn2("setpgid(0, "F_pid"): %s",
3482 opt->value.u_int, strerror(errno));
3484 break;
3485 case OPT_TIOCSCTTY:
3487 int mytty;
3488 /* this code idea taken from ssh/pty.c: make pty controlling term. */
3489 if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) {
3490 Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno));
3491 } else {
3492 /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/
3493 #ifdef TIOCNOTTY
3494 if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) {
3495 Warn2("ioctl(%d, TIOCNOTTY, NULL): %s",
3496 mytty, strerror(errno));
3498 #endif
3499 if (Close(mytty) < 0) {
3500 Info2("close(%d): %s",
3501 mytty, strerror(errno));
3504 #ifdef TIOCSCTTY
3505 if (Ioctl(fd, TIOCSCTTY, NULL) < 0) {
3506 Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno));
3508 #endif
3509 if (Tcsetpgrp(0, getpid()) < 0) {
3510 Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno));
3513 break;
3515 default: Error1("applyopts(): option \"%s\" not implemented",
3516 opt->desc->defname);
3517 opt->desc = ODESC_ERROR; ++opt; continue;
3520 #if WITH_TERMIOS
3521 } else if (opt->desc->func == OFUNC_TERMIOS_FLAG) {
3522 #if 0
3523 union {
3524 struct termios termarg;
3525 tcflag_t flags[4];
3526 } tdata;
3527 if (Tcgetattr(fd, &tdata.termarg) < 0) {
3528 Error3("tcgetattr(%d, %p): %s",
3529 fd, &tdata.termarg, strerror(errno));
3530 opt->desc = ODESC_ERROR; ++opt; continue;
3532 if (opt->value.u_bool) {
3533 tdata.flags[opt->desc->major] |= opt->desc->minor;
3534 } else {
3535 tdata.flags[opt->desc->major] &= ~opt->desc->minor;
3537 if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
3538 Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
3539 fd, &tdata.termarg, strerror(errno));
3540 opt->desc = ODESC_ERROR; ++opt; continue;
3542 #else
3543 if (xiotermiosflag_applyopt(fd, opt) < 0) {
3544 opt->desc = ODESC_ERROR; ++opt; continue;
3546 #endif
3548 } else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
3549 union {
3550 struct termios termarg;
3551 tcflag_t flags[4];
3552 } tdata;
3553 if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) !=
3554 (opt->value.u_uint << opt->desc->arg3)) {
3555 Error2("option %s: invalid value %u",
3556 opt->desc->defname, opt->value.u_uint);
3557 opt->desc = ODESC_ERROR; ++opt; continue;
3559 if (Tcgetattr(fd, &tdata.termarg) < 0) {
3560 Error3("tcgetattr(%d, %p): %s",
3561 fd, &tdata.termarg, strerror(errno));
3562 opt->desc = ODESC_ERROR; ++opt; continue;
3565 tdata.flags[opt->desc->major] &= ~opt->desc->minor;
3566 tdata.flags[opt->desc->major] |=
3567 ((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor);
3568 if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
3569 Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
3570 fd, &tdata.termarg, strerror(errno));
3571 opt->desc = ODESC_ERROR; ++opt; continue;
3574 } else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
3575 union {
3576 struct termios termarg;
3577 tcflag_t flags[4];
3578 } tdata;
3579 if (Tcgetattr(fd, &tdata.termarg) < 0) {
3580 Error3("tcgetattr(%d, %p): %s",
3581 fd, &tdata.termarg, strerror(errno));
3582 opt->desc = ODESC_ERROR; ++opt; continue;
3584 tdata.flags[opt->desc->major] &= ~opt->desc->arg3;
3585 tdata.flags[opt->desc->major] |= opt->desc->minor;
3586 if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
3587 Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
3588 fd, &tdata.termarg, strerror(errno));
3589 opt->desc = ODESC_ERROR;++opt; continue;
3592 } else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
3593 struct termios termarg;
3594 if (Tcgetattr(fd, &termarg) < 0) {
3595 Error3("tcgetattr(%d, %p): %s",
3596 fd, &termarg, strerror(errno));
3597 opt->desc = ODESC_ERROR; ++opt; continue;
3599 termarg.c_cc[opt->desc->major] = opt->value.u_byte;
3600 if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
3601 Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
3602 fd, &termarg, strerror(errno));
3603 opt->desc = ODESC_ERROR; ++opt; continue;
3606 #ifdef HAVE_TERMIOS_ISPEED
3607 } else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
3608 union {
3609 struct termios termarg;
3610 speed_t speeds[sizeof(struct termios)/sizeof(speed_t)];
3611 } tdata;
3612 if (Tcgetattr(fd, &tdata.termarg) < 0) {
3613 Error3("tcgetattr(%d, %p): %s",
3614 fd, &tdata.termarg, strerror(errno));
3615 opt->desc = ODESC_ERROR; ++opt; continue;
3617 tdata.speeds[opt->desc->major] = opt->value.u_uint;
3618 if (Tcsetattr(fd, TCSADRAIN, &tdata.termarg) < 0) {
3619 Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
3620 fd, &tdata.termarg, strerror(errno));
3621 opt->desc = ODESC_ERROR; ++opt; continue;
3623 #endif /* HAVE_TERMIOS_ISPEED */
3625 } else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
3626 struct termios termarg;
3627 if (Tcgetattr(fd, &termarg) < 0) {
3628 Error3("tcgetattr(%d, %p): %s",
3629 fd, &termarg, strerror(errno));
3630 opt->desc = ODESC_ERROR; ++opt; continue;
3632 switch (opt->desc->optcode) {
3633 case OPT_RAW:
3634 termarg.c_iflag &=
3635 ~(IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF
3636 #ifdef IUCLC
3637 |IUCLC
3638 #endif
3639 |IXANY|IMAXBEL);
3640 termarg.c_iflag |= (0);
3641 termarg.c_oflag &= ~(OPOST);
3642 termarg.c_oflag |= (0);
3643 termarg.c_cflag &= ~(0);
3644 termarg.c_cflag |= (0);
3645 termarg.c_lflag &= ~(ISIG|ICANON
3646 #ifdef XCASE
3647 |XCASE
3648 #endif
3650 termarg.c_lflag |= (0);
3651 termarg.c_cc[VMIN] = 1;
3652 termarg.c_cc[VTIME] = 0;
3653 break;
3654 case OPT_TERMIOS_RAWER:
3655 termarg.c_iflag = 0;
3656 termarg.c_oflag = 0;
3657 termarg.c_lflag = 0;
3658 termarg.c_cflag = (CS8);
3659 termarg.c_cc[VMIN] = 1;
3660 termarg.c_cc[VTIME] = 0;
3661 break;
3662 case OPT_SANE:
3663 /* cread -ignbrk brkint -inlcr -igncr icrnl
3664 -ixoff -iuclc -ixany imaxbel opost -olcuc -ocrnl
3665 onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0
3666 vt0 ff0 isig icanon iexten echo echoe echok -echonl
3667 -noflsh -xcase -tostop -echoprt echoctl echoke, and
3668 also sets all special characters to their default
3669 values.
3671 termarg.c_iflag &= ~(IGNBRK|INLCR|IGNCR|IXOFF
3672 #ifdef IUCLC
3673 |IUCLC
3674 #endif
3675 |IXANY);
3676 termarg.c_iflag |= (BRKINT|ICRNL|IMAXBEL);
3677 termarg.c_oflag &= ~(0 /* for canonical reasons */
3678 #ifdef OLCUC
3679 |OLCUC
3680 #endif
3681 #ifdef OCRNL
3682 |OCRNL
3683 #endif
3684 #ifdef ONOCR
3685 |ONOCR
3686 #endif
3687 #ifdef ONLRET
3688 |ONLRET
3689 #endif
3690 #ifdef OFILL
3691 |OFILL
3692 #endif
3693 #ifdef OFDEL
3694 |OFDEL
3695 #endif
3696 #ifdef NLDLY
3697 |NLDLY
3698 #endif
3699 #ifdef CRDLY
3700 |CRDLY
3701 #endif
3702 #ifdef TABDLY
3703 |TABDLY
3704 #endif
3705 #ifdef BSDLY
3706 |BSDLY
3707 #endif
3708 #ifdef VTDLY
3709 |VTDLY
3710 #endif
3711 #ifdef FFDLY
3712 |FFDLY
3713 #endif
3715 termarg.c_oflag |= (OPOST|ONLCR
3716 #ifdef NL0
3717 |NL0
3718 #endif
3719 #ifdef CR0
3720 |CR0
3721 #endif
3722 #ifdef TAB0
3723 |TAB0
3724 #endif
3725 #ifdef BS0
3726 |BS0
3727 #endif
3728 #ifdef VT0
3729 |VT0
3730 #endif
3731 #ifdef FF0
3732 |FF0
3733 #endif
3735 termarg.c_cflag &= ~(0);
3736 termarg.c_cflag |= (CREAD);
3737 termarg.c_lflag &= ~(ECHONL|NOFLSH
3738 #ifdef XCASE
3739 |XCASE
3740 #endif
3741 |TOSTOP
3742 #ifdef ECHOPRT
3743 |ECHOPRT
3744 #endif
3746 termarg.c_lflag |= (ISIG|ICANON|IEXTEN|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE);
3747 /*! "sets characters to their default values... - which? */
3748 break;
3749 case OPT_TERMIOS_CFMAKERAW:
3750 #if HAVE_CFMAKERAW
3751 cfmakeraw(&termarg);
3752 #else
3753 /* these setting follow the Linux documenation of cfmakeraw */
3754 termarg.c_iflag &=
3755 ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
3756 termarg.c_oflag &= ~(OPOST);
3757 termarg.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
3758 termarg.c_cflag &= ~(CSIZE|PARENB);
3759 termarg.c_cflag |= (CS8);
3760 #endif
3761 break;
3762 default:
3763 Error("TERMIOS option not handled - internal error?");
3765 if (Tcsetattr(fd, TCSADRAIN, &termarg) < 0) {
3766 Error3("tcsetattr(%d, TCSADRAIN, %p): %s",
3767 fd, &termarg, strerror(errno));
3768 opt->desc = ODESC_ERROR; ++opt; continue;
3771 #endif /* WITH_TERMIOS */
3773 #if WITH_STREAMS
3774 #define ENABLE_APPLYOPT
3775 #include "xio-streams.c"
3776 #undef ENABLE_APPLYOPT
3777 #endif /* WITH_STREAMS */
3779 } else {
3780 /*Error1("applyopts(): function %d not implemented",
3781 opt->desc->func);*/
3782 if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) {
3783 Error1("applyopts(): option \"%s\" does not apply",
3784 opt->desc->defname);
3785 opt->desc = ODESC_ERROR;
3786 ++opt;
3787 continue;
3789 ++opt;
3790 continue;
3792 opt->desc = ODESC_DONE;
3793 ++opt;
3795 return 0;
3798 /* applies to fd all options belonging to phases */
3799 /* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
3800 implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
3801 OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
3802 int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) {
3803 unsigned int i;
3804 int stat;
3806 for (i = from; i <= to; ++i) {
3807 if ((stat = applyopts(fd, opts, i)) < 0)
3808 return stat;
3810 return 0;
3813 /* apply and consume all options of type FLAG and group.
3814 Return 0 if everything went right, or -1 if an error occurred. */
3815 int applyopts_flags(struct opt *opts, int group, flags_t *result) {
3816 struct opt *opt = opts;
3818 if (!opts) return 0;
3820 while (opt->desc != ODESC_END) {
3821 if (opt->desc != ODESC_DONE &&
3822 (opt->desc->group & group)) {
3823 if (opt->desc->func == OFUNC_FLAG) {
3824 if (opt->value.u_bool) {
3825 *result |= opt->desc->major;
3826 } else {
3827 *result &= ~opt->desc->major;
3829 opt->desc = ODESC_DONE;
3830 } else if (opt->desc->func == OFUNC_FLAG_PATTERN) {
3831 *result &= ~opt->desc->minor;
3832 *result |= opt->desc->major;
3833 opt->desc = ODESC_DONE;
3836 ++opt;
3838 return 0;
3843 /* set the FD_CLOEXEC fcntl if the options do not set it to 0 */
3844 int applyopts_cloexec(int fd, struct opt *opts) {
3845 bool docloexec = 1;
3847 if (!opts) return 0;
3849 retropt_bool(opts, OPT_CLOEXEC, &docloexec);
3850 if (docloexec) {
3851 if (Fcntl_l(fd, F_SETFD, FD_CLOEXEC) < 0) {
3852 Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", fd, strerror(errno));
3855 return 0;
3858 int applyopts_fchown(int fd, struct opt *opts) {
3859 uid_t user = -1;
3860 gid_t group = -1;
3862 retropt_uidt(opts, OPT_USER, &user);
3863 retropt_gidt(opts, OPT_GROUP, &group);
3865 if (user != (uid_t)-1 || group != (gid_t)-1) {
3866 if (Fchown(fd, user, group) < 0) {
3867 Error4("fchown(%d, "F_uid", "F_gid"): %s", fd, user, group,
3868 strerror(errno));
3869 return STAT_RETRYLATER;
3872 return 0;
3875 /* caller must make sure that option is not yet consumed */
3876 static int applyopt_offset(struct single *xfd, struct opt *opt) {
3877 unsigned char *ptr;
3879 ptr = (unsigned char *)xfd + opt->desc->major;
3880 switch (opt->desc->type) {
3881 case TYPE_BOOL:
3882 *(bool *)ptr = opt->value.u_bool; break;
3883 case TYPE_INT:
3884 *(int *)ptr = opt->value.u_int; break;
3885 case TYPE_DOUBLE:
3886 *(double *)ptr = opt->value.u_double; break;
3887 case TYPE_TIMEVAL:
3888 *(struct timeval *)ptr = opt->value.u_timeval; break;
3889 case TYPE_STRING_NULL:
3890 if (opt->value.u_string == NULL) {
3891 *(char **)ptr = NULL;
3892 break;
3894 /* PASSTHROUGH */
3895 case TYPE_STRING:
3896 if ((*(char **)ptr = strdup(opt->value.u_string)) == NULL) {
3897 Error1("strdup("F_Zu"): out of memory",
3898 strlen(opt->value.u_string)+1);
3900 break;
3901 case TYPE_CONST:
3902 *(int *)ptr = opt->desc->minor;
3903 break;
3904 default:
3905 Error1("applyopt_offset(): type %d not implemented",
3906 opt->desc->type);
3907 return -1;
3909 opt->desc = ODESC_DONE;
3910 return 0;
3913 int applyopts_offset(struct single *xfd, struct opt *opts) {
3914 struct opt *opt;
3916 opt = opts; while (opt->desc != ODESC_END) {
3917 if ((opt->desc == ODESC_DONE) ||
3918 opt->desc->func != OFUNC_OFFSET) {
3919 ++opt; continue; }
3921 applyopt_offset(xfd, opt);
3922 opt->desc = ODESC_DONE;
3923 ++opt;
3925 return 0;
3928 /* applies to xfd all OFUNC_EXT options belonging to phase
3929 returns -1 if an error occurred */
3930 int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
3931 struct opt *opt;
3932 int lockrc;
3934 if (!opts) return 0;
3936 opt = opts; while (opt->desc != ODESC_END) {
3937 if ((opt->desc == ODESC_DONE) ||
3938 (opt->desc->phase != phase && phase != PH_ALL)) {
3939 /* option not handled in this function */
3940 ++opt; continue;
3941 } else {
3942 switch (opt->desc->func) {
3944 case OFUNC_OFFSET:
3945 applyopt_offset(xfd, opt);
3946 break;
3948 case OFUNC_EXT:
3949 switch (opt->desc->optcode) {
3950 #if 0
3951 case OPT_IGNOREEOF:
3952 xfd->ignoreeof = true;
3953 break;
3954 case OPT_CR:
3955 xfd->lineterm = LINETERM_CR;
3956 break;
3957 case OPT_CRNL:
3958 xfd->lineterm = LINETERM_CRNL;
3959 break;
3960 #endif /* 0 */
3961 case OPT_READBYTES:
3962 xfd->readbytes = opt->value.u_sizet;
3963 xfd->actbytes = xfd->readbytes;
3964 break;
3965 case OPT_LOCKFILE:
3966 if (xfd->lock.lockfile) {
3967 Error("only one use of options lockfile and waitlock allowed");
3969 xfd->lock.lockfile = strdup(opt->value.u_string);
3970 xfd->lock.intervall.tv_sec = 1;
3971 xfd->lock.intervall.tv_nsec = 0;
3973 if ((lockrc = xiolock(&xfd->lock)) < 0) {
3974 /* error message already printed */
3975 return -1;
3977 if (lockrc) {
3978 Error1("could not obtain lock \"%s\"", xfd->lock.lockfile);
3979 } else {
3980 xfd->havelock = true;
3982 break;
3983 case OPT_WAITLOCK:
3984 if (xfd->lock.lockfile) {
3985 Error("only one use of options lockfile and waitlock allowed");
3987 xfd->lock.lockfile = strdup(opt->value.u_string);
3988 xfd->lock.waitlock = true;
3989 xfd->lock.intervall.tv_sec = 1;
3990 xfd->lock.intervall.tv_nsec = 0;
3992 /*! this should be integrated into central select()/poll() loop */
3993 if (xiolock(&xfd->lock) < 0) {
3994 return -1;
3996 xfd->havelock = true;
3997 break;
3999 default:
4000 /* just store the value in the correct component of struct single */
4001 if (opt->desc->type == TYPE_CONST) {
4002 /* only for integral types compatible to int */
4003 *(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3;
4004 } else {
4005 memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor);
4008 break;
4010 case OFUNC_OFFSET_MASKS:
4012 void *masks = (char *)xfd + opt->desc->major;
4013 size_t masksize = opt->desc->minor;
4014 unsigned long bit = opt->desc->arg3;
4015 switch (masksize) {
4016 case sizeof(uint16_t):
4017 if (opt->value.u_bool) {
4018 ((uint16_t *)masks)[0] |= bit;
4019 } else {
4020 ((uint16_t *)masks)[1] |= bit;
4022 break;
4023 case sizeof(uint32_t):
4024 if (opt->value.u_bool) {
4025 ((uint32_t *)masks)[0] |= bit;
4026 } else {
4027 ((uint32_t *)masks)[1] |= bit;
4029 break;
4030 default:
4031 Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
4032 Error1("applyopts_single: masksize "F_Zu" not implemented",
4033 masksize);
4036 break;
4038 #if _WITH_SOCKET
4039 case OFUNC_SOCKOPT:
4040 switch (opt->desc->optcode) {
4041 #if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
4042 case OPT_IP_ADD_MEMBERSHIP:
4044 union {
4045 #if HAVE_STRUCT_IP_MREQN
4046 struct ip_mreqn mreqn;
4047 #endif
4048 struct ip_mreq mreq;
4049 } ip4_mreqn = {{{0}}};
4050 /* IPv6 not supported - seems to have different handling */
4052 mc:addr:ifname|ifind
4053 mc:ifname|ifind
4054 mc:addr
4056 union sockaddr_union sockaddr1;
4057 socklen_t socklen1 = sizeof(sockaddr1.ip4);
4058 union sockaddr_union sockaddr2;
4059 socklen_t socklen2 = sizeof(sockaddr2.ip4);
4061 /* first parameter is alway multicast address */
4062 /*! result */
4063 xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
4064 xfd->para.socket.la.soa.sa_family,
4065 SOCK_DGRAM, IPPROTO_IP,
4066 &sockaddr1, &socklen1, 0, 0);
4067 ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
4068 if (0) {
4069 ; /* for canonical reasons */
4070 #if HAVE_STRUCT_IP_MREQN
4071 } else if (opt->value.u_ip_mreq.ifindex[0] != '\0') {
4072 /* three parameters */
4073 /* second parameter is interface address */
4074 xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
4075 xfd->para.socket.la.soa.sa_family,
4076 SOCK_DGRAM, IPPROTO_IP,
4077 &sockaddr2, &socklen2, 0, 0);
4078 ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
4079 /* third parameter is interface */
4080 if (ifindex(opt->value.u_ip_mreq.ifindex,
4081 (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex, -1)
4082 < 0) {
4083 Error1("cannot resolve interface \"%s\"",
4084 opt->value.u_ip_mreq.ifindex);
4086 #endif /* HAVE_STRUCT_IP_MREQN */
4087 } else {
4088 /* two parameters */
4089 if (0) {
4090 ; /* for canonical reasons */
4091 #if HAVE_STRUCT_IP_MREQN
4092 /* there is a form with two parameters that uses mreqn */
4093 } else if (ifindex(opt->value.u_ip_mreq.param2,
4094 (unsigned int *)&ip4_mreqn.mreqn.imr_ifindex,
4096 >= 0) {
4097 /* yes, second param converts to interface */
4098 ip4_mreqn.mreq.imr_interface.s_addr = htonl(0);
4099 #endif /* HAVE_STRUCT_IP_MREQN */
4100 } else {
4101 /*! result */
4102 xiogetaddrinfo(opt->value.u_ip_mreq.param2, NULL,
4103 xfd->para.socket.la.soa.sa_family,
4104 SOCK_DGRAM, IPPROTO_IP,
4105 &sockaddr2, &socklen2, 0, 0);
4106 ip4_mreqn.mreq.imr_interface = sockaddr2.ip4.sin_addr;
4110 #if LATER
4111 if (0) {
4112 ; /* for canonical reasons */
4113 } else if (xfd->para.socket.la.soa.sa_family == PF_INET) {
4114 } else if (xfd->para.socket.la.soa.sa_family == PF_INET6) {
4115 ip6_mreqn.mreq.imr_multiaddr = sockaddr1.ip6.sin6_addr;
4116 ip6_mreqn.mreq.imr_interface = sockaddr2.ip6.sin6_addr;
4118 #endif
4120 #if HAVE_STRUCT_IP_MREQN
4121 if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
4122 &ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
4123 Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
4124 xfd->fd, opt->desc->major, opt->desc->minor,
4125 ip4_mreqn.mreqn.imr_multiaddr.s_addr,
4126 ip4_mreqn.mreqn.imr_address.s_addr,
4127 ip4_mreqn.mreqn.imr_ifindex,
4128 sizeof(ip4_mreqn.mreqn),
4129 strerror(errno));
4130 opt->desc = ODESC_ERROR; continue;
4132 #else
4133 if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
4134 &ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
4135 Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
4136 xfd->fd, opt->desc->major, opt->desc->minor,
4137 ip4_mreqn.mreq.imr_multiaddr,
4138 ip4_mreqn.mreq.imr_interface,
4139 sizeof(ip4_mreqn.mreq),
4140 strerror(errno));
4141 opt->desc = ODESC_ERROR; continue;
4143 #endif
4144 break;
4146 break;
4147 #endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
4151 #if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
4152 case OPT_IPV6_JOIN_GROUP:
4154 struct ipv6_mreq ip6_mreq = {{{{0}}}};
4155 union sockaddr_union sockaddr1;
4156 socklen_t socklen1 = sizeof(sockaddr1.ip6);
4158 /* always two parameters */
4159 /* first parameter is multicast address */
4160 /*! result */
4161 xiogetaddrinfo(opt->value.u_ip_mreq.multiaddr, NULL,
4162 xfd->para.socket.la.soa.sa_family,
4163 SOCK_DGRAM, IPPROTO_IP,
4164 &sockaddr1, &socklen1, 0, 0);
4165 ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr;
4166 if (ifindex(opt->value.u_ip_mreq.param2,
4167 &ip6_mreq.ipv6mr_interface, -1)
4168 < 0) {
4169 Error1("interface \"%s\" not found",
4170 opt->value.u_ip_mreq.param2);
4171 ip6_mreq.ipv6mr_interface = htonl(0);
4174 if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
4175 &ip6_mreq, sizeof(ip6_mreq)) < 0) {
4176 Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
4177 xfd->fd, opt->desc->major, opt->desc->minor,
4178 ip6_mreq.ipv6mr_interface,
4179 sizeof(ip6_mreq),
4180 strerror(errno));
4181 opt->desc = ODESC_ERROR; continue;
4184 break;
4185 #endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
4186 default:
4187 /* ignore here */
4188 ++opt; continue;
4190 break;
4191 #endif /* _WITH_SOCKET */
4193 default:
4194 ++opt;
4195 continue;
4197 opt->desc = ODESC_DONE;
4198 ++opt;
4201 return 0;
4205 /* xfd->para.exec.pid must be set */
4206 int applyopts_signal(struct single *xfd, struct opt *opts) {
4207 struct opt *opt;
4209 if (!opts) return 0;
4211 opt = opts; while (opt->desc != ODESC_END) {
4212 if (opt->desc == ODESC_DONE || opt->desc->func != OFUNC_SIGNAL) {
4213 ++opt; continue;
4216 if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) {
4217 opt->desc = ODESC_ERROR; continue;
4219 opt->desc = ODESC_DONE;
4220 ++opt;
4222 return 0;
4225 /* apply remaining options to file descriptor, and tell us if something is
4226 still unused */
4227 int _xio_openlate(struct single *fd, struct opt *opts) {
4228 int numleft;
4229 int result;
4231 _xioopen_setdelayeduser();
4233 if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) {
4234 return result;
4236 if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) {
4237 return result;
4239 if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) {
4240 return result;
4243 if ((numleft = leftopts(opts)) > 0) {
4244 showleft(opts);
4245 Error1("%d option(s) could not be used", numleft);
4246 return -1;
4248 return 0;
4251 int dropopts(struct opt *opts, unsigned int phase) {
4252 struct opt *opt;
4254 if (phase == PH_ALL) {
4255 opts[0].desc = ODESC_END;
4256 return 0;
4258 opt = opts; while (opt && opt->desc != ODESC_END) {
4259 if (opt->desc != ODESC_DONE && opt->desc->phase == phase) {
4260 Debug1("ignoring option \"%s\"", opt->desc->defname);
4261 opt->desc = ODESC_DONE;
4263 ++opt;
4265 return 0;
4268 int dropopts2(struct opt *opts, unsigned int from, unsigned int to) {
4269 unsigned int i;
4271 for (i = from; i <= to; ++i) {
4272 dropopts(opts, i);
4274 return 0;