From 4831944a2b4204c907018ad99fdaef2e48c604ad Mon Sep 17 00:00:00 2001 From: Christian Mauderer Date: Tue, 5 Jul 2016 16:31:43 +0200 Subject: pfctl: Adapt for RTEMS. --- freebsd/contrib/pf/pfctl/parse-data.h | 42 ++++++++++++++++++++ freebsd/contrib/pf/pfctl/parse.y | 4 ++ freebsd/contrib/pf/pfctl/pf_print_state.c | 3 ++ freebsd/contrib/pf/pfctl/pfctl-data.h | 26 +++++++++++++ freebsd/contrib/pf/pfctl/pfctl.c | 53 ++++++++++++++++++++++++++ freebsd/contrib/pf/pfctl/pfctl_altq-data.h | 8 ++++ freebsd/contrib/pf/pfctl/pfctl_altq.c | 6 +++ freebsd/contrib/pf/pfctl/pfctl_optimize-data.h | 13 +++++++ freebsd/contrib/pf/pfctl/pfctl_optimize.c | 10 ++++- freebsd/contrib/pf/pfctl/pfctl_osfp-data.h | 7 ++++ freebsd/contrib/pf/pfctl/pfctl_osfp.c | 6 +++ freebsd/contrib/pf/pfctl/pfctl_parser-data.h | 3 ++ freebsd/contrib/pf/pfctl/pfctl_parser.c | 9 +++++ freebsd/contrib/pf/pfctl/pfctl_qstats-data.h | 3 ++ freebsd/contrib/pf/pfctl/pfctl_qstats.c | 6 +++ freebsd/contrib/pf/pfctl/pfctl_radix-data.h | 3 ++ freebsd/contrib/pf/pfctl/pfctl_radix.c | 9 +++++ freebsd/contrib/pf/pfctl/pfctl_table.c | 7 ++++ 18 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 freebsd/contrib/pf/pfctl/parse-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl_altq-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl_optimize-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl_osfp-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl_parser-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl_qstats-data.h create mode 100644 freebsd/contrib/pf/pfctl/pfctl_radix-data.h diff --git a/freebsd/contrib/pf/pfctl/parse-data.h b/freebsd/contrib/pf/pfctl/parse-data.h new file mode 100644 index 00000000..22f62958 --- /dev/null +++ b/freebsd/contrib/pf/pfctl/parse-data.h @@ -0,0 +1,42 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct antispoof_opts antispoof_opts); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int blockpolicy); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int debug); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int default_statelock); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct file *file); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct files files); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct filter_opts filter_opts); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct node_hfsc_opts hfsc_opts); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct node_state_opt *keep_state_defaults); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct loadanchorshead loadanchorshead); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char *parsebuf); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int parseindex); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct pfctl *pf); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct pool_opts pool_opts); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char pushback_buffer[]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int pushback_index); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct queue_opts queue_opts); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct node_queue *queues); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int require_order); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static u_int16_t returnicmp6default); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static u_int16_t returnicmpdefault); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int rulestate); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct scrub_opts scrub_opts); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct symhead symhead); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct table_opts table_opts); + +/* NOTE: the following variables are generated by yacc and may change with yacc + * version or generation options. */ +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static YYSTACKDATA yystack); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int yychar); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int yydebug); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int yyerrflag); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern YYSTYPE yylval); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int yynerrs); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern YYSTYPE yyval); diff --git a/freebsd/contrib/pf/pfctl/parse.y b/freebsd/contrib/pf/pfctl/parse.y index 30bf3616..df865066 100644 --- a/freebsd/contrib/pf/pfctl/parse.y +++ b/freebsd/contrib/pf/pfctl/parse.y @@ -29,6 +29,7 @@ %{ #ifdef __rtems__ #include +#include #define pf_find_or_create_ruleset _bsd_pf_find_or_create_ruleset #define pf_anchor_setup _bsd_pf_anchor_setup #define pf_remove_if_empty_ruleset _bsd_pf_remove_if_empty_ruleset @@ -6133,3 +6134,6 @@ rt_tableid_max(void) return (RT_TABLEID_MAX); #endif } +#ifdef __rtems__ +#include "parse-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pf_print_state.c b/freebsd/contrib/pf/pfctl/pf_print_state.c index 142dc2d6..792ea8b7 100644 --- a/freebsd/contrib/pf/pfctl/pf_print_state.c +++ b/freebsd/contrib/pf/pfctl/pf_print_state.c @@ -32,6 +32,9 @@ * */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); diff --git a/freebsd/contrib/pf/pfctl/pfctl-data.h b/freebsd/contrib/pf/pfctl/pfctl-data.h new file mode 100644 index 00000000..a7c7e49d --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl-data.h @@ -0,0 +1,26 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int altqsupport); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char*anchoropt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *clearopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *debugopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int dev); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int first_title); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char*ifaceopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int labels); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, extern int loadopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *optiopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct pf_anchor_global pf_anchors); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *pf_device); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct pf_anchor pf_main_anchor); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char*rulesopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *showopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char*src_node_kill[2]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int src_node_killers); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char*state_kill[2]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int state_killers); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char*tableopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *tblcmdopt); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static const char *tblcmdopt); diff --git a/freebsd/contrib/pf/pfctl/pfctl.c b/freebsd/contrib/pf/pfctl/pfctl.c index df598188..64d5a013 100644 --- a/freebsd/contrib/pf/pfctl/pfctl.c +++ b/freebsd/contrib/pf/pfctl/pfctl.c @@ -33,6 +33,19 @@ * */ +#ifdef __rtems__ +#include + +#define __need_getopt_newlib +#include + +/* We need some functions from kernel space. */ +#define pf_get_ruleset_number _bsd_pf_get_ruleset_number +#define pf_init_ruleset _bsd_pf_init_ruleset + +#include +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -292,7 +305,11 @@ static const int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; void usage(void) { +#ifndef __rtems__ extern char *__progname; +#else /* __rtems__ */ +#define __progname "pfctl" +#endif /* __rtems__ */ fprintf(stderr, "usage: %s [-AdeghmNnOPqRrvz] ", __progname); fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n"); @@ -1645,6 +1662,7 @@ pfctl_init_options(struct pfctl *pf) pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT; pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; +#ifndef __rtems__ mib[0] = CTL_HW; #ifdef __FreeBSD__ mib[1] = HW_PHYSMEM; @@ -1655,6 +1673,7 @@ pfctl_init_options(struct pfctl *pf) if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1) err(1, "sysctl"); if (mem <= 100*1024*1024) +#endif /* __rtems__ */ pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL; pf->debug = PF_DEBUG_URGENT; @@ -2069,6 +2088,27 @@ pfctl_lookup_option(char *cmd, const char * const *list) return (NULL); } +#ifdef __rtems__ +static int main(int argc, char *argv[]); + +RTEMS_LINKER_RWSET(bsd_prog_pfctl, char); + +int +rtems_bsd_command_pfctl(int argc, char *argv[]) +{ + int exit_code = EXIT_FAILURE; + const void *data_buf = RTEMS_LINKER_SET_BEGIN(bsd_prog_pfctl); + const size_t data_size = RTEMS_LINKER_SET_SIZE(bsd_prog_pfctl); + + rtems_bsd_program_lock(); + exit_code = rtems_bsd_program_call_main_with_data_restore("pfctl", + main, argc, argv, data_buf, data_size); + rtems_bsd_program_unlock(); + + return exit_code; +} + +#endif /* __rtems__ */ int main(int argc, char *argv[]) { @@ -2080,6 +2120,16 @@ main(int argc, char *argv[]) char anchorname[MAXPATHLEN]; char *path; +#ifdef __rtems__ + struct getopt_data getopt_data; + memset(&getopt_data, 0, sizeof(getopt_data)); +#define optind getopt_data.optind +#define optarg getopt_data.optarg +#define opterr getopt_data.opterr +#define optopt getopt_data.optopt +#define getopt(argc, argv, opt) getopt_r(argc, argv, "+" opt, &getopt_data) +#endif /* __rtems__ */ + if (argc < 2) usage(); @@ -2471,3 +2521,6 @@ main(int argc, char *argv[]) exit(error); } +#ifdef __rtems__ +#include "pfctl-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_altq-data.h b/freebsd/contrib/pf/pfctl/pfctl_altq-data.h new file mode 100644 index 00000000..49898bc7 --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl_altq-data.h @@ -0,0 +1,8 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct altqs altqs); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct gen_sc rtsc); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct gen_sc lssc); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static char r2sbuf[R2S_BUFS][RATESTR_MAX]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int r2sidx); diff --git a/freebsd/contrib/pf/pfctl/pfctl_altq.c b/freebsd/contrib/pf/pfctl/pfctl_altq.c index 703bc560..7458a5c1 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_altq.c +++ b/freebsd/contrib/pf/pfctl/pfctl_altq.c @@ -20,6 +20,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -1276,3 +1279,6 @@ print_hfsc_sc(const char *scname, u_int m1, u_int d, u_int m2, if (d != 0) printf(")"); } +#ifdef __rtems__ +#include "pfctl_altq-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_optimize-data.h b/freebsd/contrib/pf/pfctl/pfctl_optimize-data.h new file mode 100644 index 00000000..1d55415a --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl_optimize-data.h @@ -0,0 +1,13 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int add_opt_table_num); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int pf_opt_create_table_num); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct pf_rule_field pf_rule_desc[]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int + (*skip_comparitors[PF_SKIP_COUNT])(struct pf_rule *, struct pf_rule *)); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static const char *skip_comparitors_names[PF_SKIP_COUNT]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, + static struct pfr_buffer table_buffer); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int table_identifier); diff --git a/freebsd/contrib/pf/pfctl/pfctl_optimize.c b/freebsd/contrib/pf/pfctl/pfctl_optimize.c index 8b459361..1872fa4e 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_optimize.c +++ b/freebsd/contrib/pf/pfctl/pfctl_optimize.c @@ -18,6 +18,12 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef __rtems__ +#include + +/* We need some functions from kernel space. */ +#define pf_find_or_create_ruleset _bsd_pf_find_or_create_ruleset +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -1692,4 +1698,6 @@ superblock_free(struct pfctl *pf, struct superblock *block) superblock_free(pf, block->sb_profiled_block); free(block); } - +#ifdef __rtems__ +#include "pfctl_optimize-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_osfp-data.h b/freebsd/contrib/pf/pfctl/pfctl_osfp-data.h new file mode 100644 index 00000000..1ac0ee31 --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl_osfp-data.h @@ -0,0 +1,7 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int class_count); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct name_list classes); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int fingerprint_count); +/* There is also one static buffer called "buf". But this can be ignored. See + * comment in source file. */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_osfp.c b/freebsd/contrib/pf/pfctl/pfctl_osfp.c index 3183a046..2085af68 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_osfp.c +++ b/freebsd/contrib/pf/pfctl/pfctl_osfp.c @@ -18,6 +18,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include #include #include @@ -1125,3 +1128,6 @@ print_ioctl(struct pf_osfp_ioctl *fp) return (buf); } +#ifdef __rtems__ +#include "pfctl_osfp-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_parser-data.h b/freebsd/contrib/pf/pfctl/pfctl_parser-data.h new file mode 100644 index 00000000..5e9ff5c1 --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl_parser-data.h @@ -0,0 +1,3 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct node_host *iftab); diff --git a/freebsd/contrib/pf/pfctl/pfctl_parser.c b/freebsd/contrib/pf/pfctl/pfctl_parser.c index f62fbdad..0686e610 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_parser.c +++ b/freebsd/contrib/pf/pfctl/pfctl_parser.c @@ -33,6 +33,9 @@ * */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -40,6 +43,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include #include #include @@ -1767,3 +1773,6 @@ pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; return ioctl(dev, cmd, &trans); } +#ifdef __rtems__ +#include "pfctl_parser-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_qstats-data.h b/freebsd/contrib/pf/pfctl/pfctl_qstats-data.h new file mode 100644 index 00000000..275a184c --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl_qstats-data.h @@ -0,0 +1,3 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static u_int32_t last_ticket); diff --git a/freebsd/contrib/pf/pfctl/pfctl_qstats.c b/freebsd/contrib/pf/pfctl/pfctl_qstats.c index 3589f6f4..502b52e7 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_qstats.c +++ b/freebsd/contrib/pf/pfctl/pfctl_qstats.c @@ -18,6 +18,9 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -455,3 +458,6 @@ update_avg(struct pf_altq_node *a) if (n < AVGN_MAX) qs->avgn++; } +#ifdef __rtems__ +#include "pfctl_qstats-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_radix-data.h b/freebsd/contrib/pf/pfctl/pfctl_radix-data.h new file mode 100644 index 00000000..bcb5f3bb --- /dev/null +++ b/freebsd/contrib/pf/pfctl/pfctl_radix-data.h @@ -0,0 +1,3 @@ +#include + +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char next_ch); diff --git a/freebsd/contrib/pf/pfctl/pfctl_radix.c b/freebsd/contrib/pf/pfctl/pfctl_radix.c index 7868489a..0a300470 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_radix.c +++ b/freebsd/contrib/pf/pfctl/pfctl_radix.c @@ -32,6 +32,9 @@ * */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -48,6 +51,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef __rtems__ +#define SIZE_T_MAX SIZE_MAX +#endif /* __rtems__ */ #include #include "pfctl.h" @@ -594,3 +600,6 @@ pfr_strerror(int errnum) return strerror(errnum); } } +#ifdef __rtems__ +#include "pfctl_radix-data.h" +#endif /* __rtems__ */ diff --git a/freebsd/contrib/pf/pfctl/pfctl_table.c b/freebsd/contrib/pf/pfctl/pfctl_table.c index a62b49a9..a89f4353 100644 --- a/freebsd/contrib/pf/pfctl/pfctl_table.c +++ b/freebsd/contrib/pf/pfctl/pfctl_table.c @@ -32,6 +32,9 @@ * */ +#ifdef __rtems__ +#include +#endif /* __rtems__ */ #include __FBSDID("$FreeBSD$"); @@ -495,7 +498,11 @@ print_astats(struct pfr_astats *as, int dns) void radix_perror(void) { +#ifndef __rtems__ extern char *__progname; +#else /* __rtems__ */ +#define __progname "pfctl" +#endif /* __rtems__ */ fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno)); } -- cgit v1.2.3