int main (int argc, char **argv) { w_io_t *ios; char buf[BUFFER_SIZE]; w_opt_parse (options, NULL, NULL, NULL, argc, argv); if (!(ios = w_io_socket_open (W_IO_SOCKET_TCP4, serverhost, serverport))) { w_die ("Problem creating socket: $s\n", strerror (errno)); } w_io_socket_connect ((w_io_socket_t*) ios); w_io_result_t r; while (w_io_result_bytes (r = w_io_read (w_stdin, buf, BUFFER_SIZE)) > 0) { W_IO_CHECK_RETURN (w_io_write (ios, buf, w_io_result_bytes (r)), EXIT_FAILURE); } w_io_socket_send_eof ((w_io_socket_t*) ios); while (w_io_result_bytes (r = w_io_read (ios, buf, BUFFER_SIZE)) > 0) { W_IO_NORESULT (w_io_write (w_stdout, buf, w_io_result_bytes (r))); } w_obj_unref (ios); return EXIT_SUCCESS; }
static inline const w_opt_t* _opt_lookup_fuzz (const w_opt_t *opt, const char *str, const char *prg) { size_t len; const w_opt_t *ret; w_assert (opt != NULL); w_assert (str != NULL); w_assert (prg != NULL); len = strlen (str); for (; opt->string != NULL; opt++) if (!strncmp (opt->string, str, len)) break; if (opt->string == NULL) return NULL; ret = opt++; /* Check wether the option string is not ambiguous. */ for (; opt->string != NULL; opt++) if (!strncmp (opt->string, str, len)) break; /* If we reach the end, no other prefix is equal -> ok. */ if (opt->string == NULL) return ret; /* ...otherwise, we are in trouble. */ W_IO_NORESULT (w_io_format (w_stderr, "$s: option '$s' is ambiguous, possibilities:\n", prg, str)); for (; ret->string != NULL; ret++) { if (!strncmp (ret->string, str, len)) { W_IO_NORESULT (w_io_format (w_stderr, " --$s\n", ret->string)); } } W_IO_NORESULT (w_io_format (w_stderr, "Hint: try '$s --help'\n", prg)); exit (EXIT_FAILURE); return NULL; /* Never reached -- but keeps compiler happy =) */ }
static inline void _print_blanks (w_io_t *f, size_t n) { while (n--) { /* TODO: Maybe hanle I/O errors. */ W_IO_NORESULT (w_io_putchar (f, ' ')); } }
static inline void _print_some_chars (w_io_t *f, const char *s, size_t n) { while (n-- && (*s != '\0')) { /* TODO: Maybe hanle I/O errors. */ W_IO_NORESULT (w_io_putchar (f, *s++)); } }
static inline void _print_lspaced (w_io_t *f, const char *s, int l) { unsigned tty_cols = w_tty_cols () - l - 22; const char *spc = s; unsigned col = 0; int lstart = 1; size_t len; if (l > 65) l = 20; if (tty_cols > 60) { tty_cols = 60; } /* Reflow words by inserting line breaks at spaces. */ while (s != NULL) { spc = strchr (s, (spc == NULL) ? '\0' : ' '); len = (spc == NULL) ? strlen (s) : (size_t) (spc - s); if (lstart) { /* We're at line start, print always. */ col = l + len; _print_some_chars (f, s, len); lstart = 0; } else if ((col + len) > tty_cols) { /* Advance to next line. */ col = l + len; /* TODO: Maybe hanle I/O errors. */ W_IO_NORESULT (w_io_putchar (f, '\n')); _print_blanks (f, l); _print_some_chars (f, s, len); } else { col += len; _print_some_chars (f, s, len); } s = (spc == NULL) ? NULL : spc + 1; /* TODO: Maybe hanle I/O errors. */ W_IO_NORESULT (w_io_putchar (f, ' ')); } /* TODO: Maybe hanle I/O errors. */ W_IO_NORESULT (w_io_putchar (f, '\n')); }
/*~f char* w_cstr_formatv (const char *format, va_list arguments) * * Create a C (``\0``-terminated) string with a given `format`, consuming * additional `arguments` as needed by the `format`. * * The returned strings must be freed by the caller. * * See :ref:`formatted-output` for the available formatting options. */ char* w_cstr_formatv (const char *format, va_list args) { w_assert (format); w_io_buf_t buffer_stream; w_io_buf_init (&buffer_stream, NULL, false); W_IO_NORESULT (w_io_formatv (&buffer_stream.parent, format, args)); return w_io_buf_str (&buffer_stream); }
static bool serve_request (w_io_socket_t *io) { char buf[BUFFER_SIZE]; w_io_result_t r; W_IO_NORESULT (w_io_format (w_stdout, "BEGIN REQUEST\n")); while (!w_io_failed (r = w_io_read ((w_io_t*) io, buf, BUFFER_SIZE)) && w_io_result_bytes (r) > 0) { W_IO_CHECK_RETURN (w_io_write ((w_io_t*) io, buf, w_io_result_bytes (r)), false); W_IO_NORESULT (w_io_write (w_stdout, buf, w_io_result_bytes (r))); } w_io_socket_send_eof (io); if (w_io_failed (r)) { W_IO_NORESULT (w_io_format (w_stderr, "Error: %E\n")); } W_IO_NORESULT (w_io_format (w_stdout, "END REQUEST\n")); return true; }
void w_opt_help (const w_opt_t *opt, w_io_t *out, const char *progname, const char *syntax) { w_assert (opt != NULL); w_assert (out != NULL); /* TODO: Handle I/O errors. */ W_IO_NORESULT (w_io_format (out, "Usage: $s [options] $s\n" "Command line options:\n\n", progname, (syntax != NULL) ? syntax : "")); for (; opt->string != NULL; opt++) { if (OPT_LETTER (opt->letter) && opt->string) { W_IO_NORESULT (w_io_format (out, "-$c, --$s ", OPT_LETTER (opt->letter), opt->string)); } else if (opt->string) { W_IO_NORESULT (w_io_format (out, "--$s ", opt->string)); } else { W_IO_NORESULT (w_io_format (out, "-$c ", OPT_LETTER (opt->letter))); } switch (opt->narg) { case 0: W_IO_NORESULT (w_io_format (out, "\n ")); break; case 1: W_IO_NORESULT (w_io_format (out, "<ARG>\n ")); break; default: W_IO_NORESULT (w_io_format (out, "<ARG...>\n ")); } _print_lspaced (out, opt->info, 3); W_IO_NORESULT (w_io_putchar (out, '\n')); } }
static void format_meta (w_io_t *io, const w_meta_item_t *meta, int indent) { while (w_meta_item_is_valid (meta)) { if (indent) { int i = indent << 1; while (i--) W_IO_NORESULT (w_io_putchar (io, ' ')); } switch (meta->type) { case W_META_TYPE_I8: W_IO_NORESULT (w_io_format (io, "int8_t ")); break; case W_META_TYPE_I16: W_IO_NORESULT (w_io_format (io, "int16_t ")); break; case W_META_TYPE_I32: W_IO_NORESULT (w_io_format (io, "int32_t ")); break; case W_META_TYPE_I64: W_IO_NORESULT (w_io_format (io, "int64_t ")); break; case W_META_TYPE_U8 : W_IO_NORESULT (w_io_format (io, "uint8_t ")); break; case W_META_TYPE_U16: W_IO_NORESULT (w_io_format (io, "uint16_t ")); break; case W_META_TYPE_U32: W_IO_NORESULT (w_io_format (io, "uint32_t ")); break; case W_META_TYPE_U64: W_IO_NORESULT (w_io_format (io, "uint64_t ")); break; case W_META_TYPE_STR: W_IO_NORESULT (w_io_format (io, "char *")); break; case W_META_TYPE_BOOL:W_IO_NORESULT (w_io_format (io, "bool ")); break; default: break; } if (meta->type == W_META_TYPE_REG) { if (meta->alen) W_IO_NORESULT (w_io_format (io, "$s $s[$I] {\n", w_meta_desc_name (meta->mref), meta->name, meta->alen)); else W_IO_NORESULT (w_io_format (io, "$s $s {\n", w_meta_desc_name (meta->mref), meta->name)); format_meta (io, w_meta_desc_items (meta->mref), indent + 1); if (indent) { int i = indent << 1; while (i--) W_IO_NORESULT (w_io_putchar (io, ' ')); } W_IO_NORESULT (w_io_format (io, "};\n")); } else { W_IO_NORESULT (w_io_format (io, "$s", meta->name)); if (meta->alen) W_IO_NORESULT (w_io_format (io, "[$I];\n", meta->alen)); else W_IO_NORESULT (w_io_format (io, ";\n")); } meta = w_meta_item_next (meta); } }
unsigned w_opt_parse (const w_opt_t *options, w_action_fun_t file_cb, void *userdata, const char *syntax, int argc, char **argv) { w_opt_status_t status = W_OPT_OK; w_opt_context_t context = { argc, argv, NULL, userdata, NULL }; bool files_only = false; size_t i = 1; w_assert (options != NULL); w_assert (argv != NULL); while (i < (unsigned) argc) { if (!files_only && (argv[i][0] == '-')) { /* option */ context.option = ((argv[i][1] == '-') && (argv[i][2] != '\0')) ? _opt_lookup_long (options, &argv[i][2]) : ((argv[i][2] == '\0') ? _opt_lookup_shrt (options, argv[i][1]) : _opt_lookup_fuzz (options, &argv[i][1], _program_name (argv[0])) ); if (context.option == NULL) { status = W_OPT_BAD_ARG; break; } if (OPT_LETTER (context.option->letter) == 'h') { w_opt_help (options, w_stdout, _program_name (argv[0]), syntax); status = W_OPT_EXIT_OK; break; } if (context.option->narg >= (unsigned) (argc - i)) { status = W_OPT_MISSING_ARG; break; } /* Prepare context. */ context.argument = &argv[++i]; /* Invoke action. */ status = (*context.option->action) (&context); /* If --files (or similar) was given change flag and continue */ if (status == W_OPT_FILES) { files_only = 1; continue; } /* Bail out of this is not a good status */ if (status != W_OPT_OK) break; /* Advance in arguments. */ i += context.option->narg; } else { if (file_cb != NULL) (*file_cb) ((void*) argv[i++], userdata); else return i; } } /* Perform final status-based actions. */ switch (status) { case W_OPT_FILES: /* Nothing more to do. */ case W_OPT_OK: break; case W_OPT_BAD_ARG: /* Handle errors. */ case W_OPT_MISSING_ARG: if (context.option == NULL) { W_IO_NORESULT (w_io_format (w_stderr, "$s: unknown option '$s'\nHint: try '$s --help'\n", _program_name (argv[0]), argv[i], _program_name (argv[0]))); } else { W_IO_NORESULT (w_io_format (w_stderr, "$s: $s --$s\nTry \"$s --help\" for more information.\n", _program_name (argv[0]), (status == W_OPT_BAD_ARG) ? "bad argument passed to" : "missing argument(s) to", context.option->string, _program_name (argv[0]))); } /* fall-through */ case W_OPT_EXIT_FAIL: /* Exit with the given status hint. */ exit (EXIT_FAILURE); case W_OPT_EXIT_OK: exit (EXIT_SUCCESS); } return i; }
static void w_io_cleanup (void *obj) { /* Unfortunately, errors can't be reported here. */ W_IO_NORESULT (w_io_close ((w_io_t*) obj)); }
void proto_xmpp_handler (w_task_listener_t *listener, w_io_t *socket) { w_printerr ("$s: Client connected\n", w_task_name ()); W_IO_NORESULT (w_io_close (socket)); }