char * dispatch_docstring (const char *text) { mu_stream_t str; struct mutool_action_tab *p; mu_off_t size; size_t n; char *ret; mu_memory_stream_create (&str, MU_STREAM_RDWR); mu_stream_printf (str, "%s\n%s\n\n", text, _("Commands are:")); for (p = mutool_action_tab; p->name; p++) mu_stream_printf (str, " %s %-16s - %s\n", mu_program_name, p->name, gettext (p->docstring)); mu_stream_printf (str, _("\nTry `%s COMMAND --help' to get help on a particular " "COMMAND.\n\n"), mu_program_name); mu_stream_printf (str, "%s\n", _("Options are:")); mu_stream_flush (str); mu_stream_size (str, &size); ret = mu_alloc (size + 1); mu_stream_seek (str, 0, MU_SEEK_SET, NULL); mu_stream_read (str, ret, size, &n); ret[n] = 0; mu_stream_destroy (&str); return ret; }
int main (int argc, char * argv []) { int c; mu_stream_t in, out; int reread_option = 0; mu_off_t reread_off; int skip_option = 0; mu_off_t skip_off; while ((c = getopt (argc, argv, "hs:r:")) != EOF) switch (c) { case 'r': reread_option = 1; reread_off = strtoul (optarg, NULL, 10); break; case 's': skip_option = 1; skip_off = strtoul (optarg, NULL, 10); break; case 'h': printf ("usage: cat [-s off]\n"); exit (0); default: exit (1); } MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_SEEK)); MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0)); if (skip_option) { mu_stream_printf (out, "skipping to %lu:\n", (unsigned long) skip_off); MU_ASSERT (mu_stream_seek (in, skip_off, MU_SEEK_SET, NULL)); } MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); if (reread_option) { mu_stream_printf (out, "rereading from %lu:\n", (unsigned long) reread_off); MU_ASSERT (mu_stream_seek (in, reread_off, MU_SEEK_SET, NULL)); MU_ASSERT (mu_stream_copy (out, in, 0, NULL)); } mu_stream_close (in); mu_stream_destroy (&in); mu_stream_close (out); mu_stream_destroy (&out); return 0; }
int mu_vgetyn (const char *fmt, va_list ap) { char repl[64]; while (1) { int rc; size_t n; mu_stream_vprintf (mu_strout, fmt, ap); mu_stream_write (mu_strout, "? ", 2, NULL); mu_stream_flush (mu_strout); if (mu_stream_read (mu_strin, repl, sizeof repl, &n) || n == 0) return 0; mu_rtrim_class (repl, MU_CTYPE_ENDLN); rc = mu_true_answer_p (repl); if (rc >= 0) return rc; /* TRANSLATORS: See msgids "nN" and "yY". */ mu_stream_printf (mu_strout, "%s", _("Please answer yes or no: ")); } return 0; /* to pacify gcc */ }
int mu_vgetans (const char *variants, const char *fmt, va_list ap) { char repl[64]; while (1) { size_t n; char *p; mu_stream_vprintf (mu_strout, fmt, ap); mu_stream_write (mu_strout, "? ", 2, NULL); mu_stream_flush (mu_strout); if (mu_stream_read (mu_strin, repl, sizeof repl, &n) || n == 0) return 0; mu_rtrim_class (repl, MU_CTYPE_ENDLN); p = strchr (variants, *repl); if (p) return *p; mu_stream_printf (mu_strout, _("Please answer one of [%s]: "), variants); } return 0; /* to pacify gcc */ }
/* Send the completion response and reset the state. */ int io_format_completion_response (mu_stream_t str, struct imap4d_command *command, int rc, const char *format, va_list ap) { int new_state; int status = 0; const char *sc = sc2string (rc); imap4d_sync (); mu_stream_printf (str, "%s %s%s ", command->tag, sc, command->name); mu_stream_vprintf (str, format, ap); mu_stream_write (str, "\n", 1, NULL); /* Reset the state. */ if (rc == RESP_OK) new_state = command->success; else if (command->failure <= state) new_state = command->failure; else new_state = STATE_NONE; if (new_state != STATE_NONE) { if (new_state == STATE_AUTH) set_xscript_level (MU_XSCRIPT_NORMAL); state = new_state; } return status; }
/* Send an untagged response. */ int io_untagged_response (int rc, const char *format, ...) { int status; va_list ap; mu_stream_printf (iostream, "* %s", sc2string (rc)); va_start (ap, format); status = mu_stream_vprintf (iostream, format, ap); va_end (ap); mu_stream_write (iostream, "\n", 1, NULL); return status; }
int main (int argc, char **argv) { int i; char *host = NULL; char *infile = NULL; char *port = NULL; int tls = 0; int raw = 1; int flags = 0; mu_stream_t stream; mu_smtp_t smtp; mu_stream_t instr; char *from = NULL; mu_list_t rcpt_list = NULL; mu_list_t meth_list = NULL; mu_list_t skiphdr_list = NULL; struct mu_sockaddr *sa; struct mu_sockaddr_hints hints; mu_set_program_name (argv[0]); mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); if (argc < 2) usage (); memset (&hints, 0, sizeof (hints)); hints.flags = MU_AH_DETECT_FAMILY; hints.port = 25; hints.protocol = IPPROTO_TCP; hints.socktype = SOCK_STREAM; MU_ASSERT (mu_smtp_create (&smtp)); for (i = 1; i < argc; i++) { if (strncmp (argv[i], "port=", 5) == 0) port = argv[i] + 5; else if (strncmp (argv[i], "family=", 7) == 0) { hints.flags &= ~MU_AH_DETECT_FAMILY; switch (argv[i][7]) { case '4': hints.family = AF_INET; break; case '6': hints.family = AF_INET6; break; default: mu_error ("invalid family name: %s", argv[i]+7); exit (1); } } else if (strncmp (argv[i], "trace=", 6) == 0) { char *arg = argv[i] + 6; if (mu_isdigit (arg[0])) mu_smtp_trace (smtp, atoi (argv[i] + 6) ? MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR); else { mu_smtp_trace (smtp, MU_SMTP_TRACE_SET); if (strcmp (arg, "secure") == 0) mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET, MU_XSCRIPT_SECURE); else if (strcmp (arg, "payload") == 0) mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET, MU_XSCRIPT_PAYLOAD); } } else if (strncmp (argv[i], "tls=", 4) == 0) tls = atoi (argv[i] + 4); else if (strncmp (argv[i], "domain=", 7) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN, argv[i] + 7)); else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE, argv[i] + 8)); else if (strncmp (argv[i], "realm=", 6) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM, argv[i] + 6)); else if (strncmp (argv[i], "host=", 5) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST, argv[i] + 5)); else if (strncmp (argv[i], "url=", 4) == 0) MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL, argv[i] + 4)); else if (strncmp (argv[i], "input=", 6) == 0) infile = argv[i] + 6; else if (strncmp (argv[i], "raw=", 4) == 0) raw = atoi (argv[i] + 4); else if (strncmp (argv[i], "rcpt=", 5) == 0) { if (!rcpt_list) MU_ASSERT (mu_list_create (&rcpt_list)); MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5)); } else if (strncmp (argv[i], "from=", 5) == 0) from = argv[i] + 5; else if (strncmp (argv[i], "auth=", 5) == 0) update_list (&meth_list, argv[i] + 5); else if (strncmp (argv[i], "skiphdr=", 8) == 0) { update_list (&skiphdr_list, argv[i] + 8); raw = 0; } else if (host) { mu_error ("server name already given: %s, new name %s?", host, argv[i]); exit (1); } else host = argv[i]; } if (!host) usage (); if (!raw) flags = MU_STREAM_SEEK; if (infile) MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags)); else MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags)); host = argv[1]; MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints)); MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR)); mu_smtp_set_carrier (smtp, stream); mu_stream_unref (stream); if (!from) { from = getenv ("USER"); if (!from) { mu_error ("cannot determine sender name"); exit (1); } } if (raw && !rcpt_list) { mu_error ("no recipients"); exit (1); } MU_ASSERT (mu_smtp_open (smtp)); MU_ASSERT (mu_smtp_ehlo (smtp)); if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0) { MU_ASSERT (mu_smtp_starttls (smtp)); MU_ASSERT (mu_smtp_ehlo (smtp)); } if (meth_list) { int status; MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list)); status = mu_smtp_auth (smtp); switch (status) { case 0: MU_ASSERT (mu_smtp_ehlo (smtp)); break; case ENOSYS: case MU_ERR_NOENT: /* Ok, skip it */ break; default: mu_error ("authentication failed: %s", mu_strerror (status)); exit (1); } } MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL)); mu_list_foreach (rcpt_list, send_rcpt_command, smtp); if (raw) { /* Raw sending mode: send from the stream directly */ MU_ASSERT (mu_smtp_send_stream (smtp, instr)); } else { /* Message (standard) sending mode: send a MU message. */ mu_message_t msg; mu_stream_t ostr, bstr; mu_header_t hdr; mu_iterator_t itr; mu_body_t body; if (skiphdr_list) mu_list_set_comparator (skiphdr_list, headercmp); MU_ASSERT (mu_stream_to_message (instr, &msg)); mu_stream_unref (instr); MU_ASSERT (mu_smtp_data (smtp, &ostr)); MU_ASSERT (mu_message_get_header (msg, &hdr)); MU_ASSERT (mu_header_get_iterator (hdr, &itr)); for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { const char *name; void *value; mu_iterator_current_kv (itr, (void*) &name, &value); if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0) continue; mu_stream_printf (ostr, "%s: %s\n", name, (char*)value); } mu_iterator_destroy (&itr); MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL)); MU_ASSERT (mu_message_get_body (msg, &body)); MU_ASSERT (mu_body_get_streamref (body, &bstr)); MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL)); mu_stream_destroy (&bstr); mu_stream_close (ostr); mu_stream_destroy (&ostr); } MU_ASSERT (mu_smtp_dot (smtp)); MU_ASSERT (mu_smtp_quit (smtp)); mu_smtp_destroy (&smtp); mu_stream_close (instr); mu_stream_destroy (&instr); return 0; }
int mu_imapio_getline (struct _mu_imapio *io) { int rc; char *last_arg; int xlev = MU_XSCRIPT_NORMAL; if (io->_imap_reply_ready) { mu_wordsplit_free_words (&io->_imap_ws); io->_imap_reply_ready = 0; } for (;;) { rc = mu_stream_getline (io->_imap_stream, &io->_imap_buf_base, &io->_imap_buf_size, &io->_imap_buf_level); if (rc) break; if (io->_imap_buf_level == 0) break; io->_imap_buf_level = mu_rtrim_class (io->_imap_buf_base, MU_CTYPE_ENDLN); rc = initial_parse (io); if (rc == IMAPIO_ERR) { rc = MU_ERR_PARSE; break; } else if (rc == IMAPIO_RESP) { rc = 0; break; } rc = mu_wordsplit_len (io->_imap_buf_base + io->_imap_ws.ws_endp, io->_imap_buf_level - io->_imap_ws.ws_endp, &io->_imap_ws, io->_imap_ws_flags); if (rc) { rc = MU_ERR_PARSE; break; } if (io->_imap_ws.ws_wordc == 0) break; last_arg = io->_imap_ws.ws_wordv[io->_imap_ws.ws_wordc - 1]; if (last_arg[0] == '{' && last_arg[strlen (last_arg)-1] == '}') { int rc; unsigned long number; char *sp = NULL; if (!io->_imap_trace_payload) xlev = mu_imapio_set_xscript_level (io, MU_XSCRIPT_PAYLOAD); number = strtoul (last_arg + 1, &sp, 10); /* Client can ask for non-synchronised literal, if a '+' is appended to the octet count. */ if (*sp == '}') { if (io->_imap_server) mu_stream_printf (io->_imap_stream, "+ GO AHEAD\n"); } else if (*sp != '+') break; if (number + 1 > io->_imap_buf_size) { size_t newsize = number + 1; void *newp = realloc (io->_imap_buf_base, newsize); if (!newp) { rc = ENOMEM; break; } io->_imap_buf_base = newp; io->_imap_buf_size = newsize; } for (io->_imap_buf_level = 0; io->_imap_buf_level < number; ) { size_t sz; rc = mu_stream_read (io->_imap_stream, io->_imap_buf_base + io->_imap_buf_level, number - io->_imap_buf_level, &sz); if (rc || sz == 0) break; io->_imap_buf_level += sz; } mu_imapio_set_xscript_level (io, xlev); if (rc) break; io->_imap_buf_base[io->_imap_buf_level++] = 0; free (last_arg); io->_imap_ws.ws_wordv[--io->_imap_ws.ws_wordc] = NULL; if (mu_wordsplit_len (io->_imap_buf_base, io->_imap_buf_level, &io->_imap_ws, io->_imap_ws_flags|MU_WRDSF_NOSPLIT)) { rc = MU_ERR_PARSE; break; } } else break; } if (!io->_imap_trace_payload) mu_imapio_set_xscript_level (io, xlev); io->_imap_reply_ready = 1; return rc; }
int main (int argc, char **argv) { int index; int rc; mu_stream_t in, tmp; mu_message_t msg; mu_header_t hdr; mu_iterator_t itr; const char *file; char *newval; mu_off_t size; mu_body_t body; mu_stream_t bstr; MU_APP_INIT_NLS (); mh_argp_init (); mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, opt_handler, NULL, &index); if (index == argc) { mu_error (_("file name not given")); exit (1); } file = argv[index]; prompter_init (); if (erase_seq) prompter_set_erase (erase_seq); if (kill_seq) prompter_set_erase (kill_seq); if ((rc = mu_stdio_stream_create (&strout, MU_STDOUT_FD, MU_STREAM_WRITE))) { mu_error (_("cannot open stdout: %s"), mu_strerror (rc)); return 1; } if ((rc = mu_file_stream_create (&in, file, MU_STREAM_RDWR))) { mu_error (_("cannot open input file `%s': %s"), file, mu_strerror (rc)); return 1; } rc = mu_stream_to_message (in, &msg); mu_stream_unref (in); if (rc) { mu_error (_("input stream %s is not a message (%s)"), file, mu_strerror (rc)); return 1; } if ((rc = mu_temp_file_stream_create (&tmp, NULL, 0))) { mu_error (_("Cannot open temporary file: %s"), mu_strerror (rc)); return 1; } /* Copy headers */ mu_message_get_header (msg, &hdr); mu_header_get_iterator (hdr, &itr); for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) { const char *name, *val; mu_iterator_current_kv (itr, (const void **)&name, (void**)&val); if (!is_empty_string (val)) { mu_stream_printf (tmp, "%s: %s\n", name, val); mu_stream_printf (strout, "%s: %s\n", name, val); } else { int cont = 0; mu_opool_t opool; const char *prompt = name; mu_opool_create (&opool, 1); do { size_t len; char *p; p = prompter_get_value (prompt); if (!p) return 1; prompt = NULL; if (cont) { mu_opool_append_char (opool, '\n'); if (!mu_isspace (p[0])) mu_opool_append_char (opool, '\t'); } len = strlen (p); if (len > 0 && p[len-1] == '\\') { len--; cont = 1; } else cont = 0; mu_opool_append (opool, p, len); free (p); } while (cont); mu_opool_append_char (opool, 0); newval = mu_opool_finish (opool, NULL); if (!is_empty_string (newval)) mu_stream_printf (tmp, "%s: %s\n", name, newval); mu_opool_destroy (&opool); } } mu_iterator_destroy (&itr); mu_stream_printf (strout, "--------\n"); mu_stream_write (tmp, "\n", 1, NULL); /* Copy body */ if (prepend_option) { mu_stream_printf (strout, "\n--------%s\n\n", _("Enter initial text")); while ((newval = prompter_get_line ())) { mu_stream_write (tmp, newval, strlen (newval), NULL); free (newval); mu_stream_write (tmp, "\n", 1, NULL); } } mu_message_get_body (msg, &body); mu_body_get_streamref (body, &bstr); if (!prepend_option && !rapid_option) { mu_stream_copy (strout, bstr, 0, NULL); mu_stream_seek (bstr, 0, MU_SEEK_SET, NULL); } mu_stream_copy (tmp, bstr, 0, NULL); mu_stream_unref (bstr); if (!prepend_option && !rapid_option) { printf ("\n--------%s\n\n", _("Enter additional text")); while ((newval = prompter_get_line ())) { mu_stream_write (tmp, newval, strlen (newval), NULL); free (newval); mu_stream_write (tmp, "\n", 1, NULL); } } /* Destroy the message */ mu_message_destroy (&msg, mu_message_get_owner (msg)); /* Rewind the streams and copy data back to in. */ mu_stream_seek (in, 0, MU_SEEK_SET, NULL); mu_stream_seek (tmp, 0, MU_SEEK_SET, NULL); mu_stream_copy (in, tmp, 0, &size); mu_stream_truncate (in, size); mu_stream_destroy (&in); mu_stream_destroy (&tmp); mu_stream_destroy (&strout); prompter_done (); return 0; }