int main (int argc, char **argv) { struct group *gr; int status = 0; static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, SIGABRT }; imap4d_argc = argc; imap4d_argv = argv; /* Native Language Support */ MU_APP_INIT_NLS (); state = STATE_NONAUTH; /* Starting state in non-auth. */ MU_AUTH_REGISTER_ALL_MODULES (); /* Register the desired formats. */ mu_register_local_mbox_formats (); imap4d_capability_init (); #ifdef WITH_TLS mu_gocs_register ("tls", mu_tls_module_init); #endif /* WITH_TLS */ #ifdef WITH_GSASL mu_gocs_register ("gsasl", mu_gsasl_module_init); #endif mu_tcpwrapper_cfg_init (); mu_acl_cfg_init (); mu_m_server_cfg_init (); mu_argp_init (program_version, NULL); mu_m_server_create (&server, program_version); mu_m_server_set_conn (server, imap4d_connection); mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork); mu_m_server_set_mode (server, MODE_INTERACTIVE); mu_m_server_set_max_children (server, 20); /* FIXME mu_m_server_set_pidfile (); */ mu_m_server_set_default_port (server, 143); mu_m_server_set_timeout (server, 1800); /* RFC2060: 30 minutes. */ mu_m_server_set_strexit (server, mu_strexit); if (mu_app_init (&argp, imap4d_capa, imap4d_cfg_param, argc, argv, 0, NULL, server)) exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */ if (login_disabled) imap4d_capability_add (IMAP_CAPA_LOGINDISABLED); #ifdef WITH_TLS if (tls_required) imap4d_capability_add (IMAP_CAPA_XTLSREQUIRED); #endif namespace_init (); auth_gssapi_init (); auth_gsasl_init (); #ifdef USE_LIBPAM if (!mu_pam_service) mu_pam_service = "gnu-imap4d"; #endif if (mu_m_server_mode (server) == MODE_DAEMON) { /* Normal operation: */ /* First we want our group to be mail so we can access the spool. */ errno = 0; gr = getgrnam ("mail"); if (gr == NULL) { if (errno == 0 || errno == ENOENT) { mu_error (_("%s: no such group"), "mail"); exit (EX_CONFIG); } else { mu_diag_funcall (MU_DIAG_ERROR, "getgrnam", "mail", errno); exit (EX_OSERR); } } if (setgid (gr->gr_gid) == -1) { mu_error (_("error setting mail group: %s"), mu_strerror (errno)); exit (EX_OSERR); } } /* Set the signal handlers. */ mu_set_signals (imap4d_master_signal, sigtab, MU_ARRAY_SIZE (sigtab)); /* Set up for syslog. */ openlog (MU_LOG_TAG (), LOG_PID, mu_log_facility); /* Redirect any stdout error from the library to syslog, they should not go to the client. */ { mu_debug_t debug; mu_diag_get_debug (&debug); mu_debug_set_print (debug, mu_diag_syslog_printer, NULL); mu_debug_default_printer = mu_debug_syslog_printer; } umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ /* Check TLS environment, i.e. cert and key files */ #ifdef WITH_TLS starttls_init (); #endif /* WITH_TLS */ /* Actually run the daemon. */ if (mu_m_server_mode (server) == MODE_DAEMON) { mu_m_server_begin (server); status = mu_m_server_run (server); mu_m_server_end (server); mu_m_server_destroy (&server); } else { /* Make sure we are in the root directory. */ chdir ("/"); status = imap4d_mainloop (fileno (stdin), stdin, stdout); } if (status) mu_error (_("main loop status: %s"), mu_strerror (status)); /* Close the syslog connection and exit. */ closelog (); return status ? EX_SOFTWARE : EX_OK; }
int main (int argc, char **argv) { struct group *gr; int status = OK; static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE }; /* Native Language Support */ MU_APP_INIT_NLS (); MU_AUTH_REGISTER_ALL_MODULES(); /* Register the desired formats. */ mu_register_local_mbox_formats (); #ifdef WITH_TLS mu_gocs_register ("tls", mu_tls_module_init); #endif /* WITH_TLS */ mu_tcpwrapper_cfg_init (); manlock_cfg_init (); mu_acl_cfg_init (); mu_m_server_cfg_init (pop3d_srv_param); mu_argp_init (NULL, NULL); mu_m_server_create (&server, program_version); mu_m_server_set_config_size (server, sizeof (struct pop3d_srv_config)); mu_m_server_set_conn (server, pop3d_connection); mu_m_server_set_prefork (server, mu_tcp_wrapper_prefork); mu_m_server_set_mode (server, MODE_INTERACTIVE); mu_m_server_set_max_children (server, 20); /* FIXME mu_m_server_set_pidfile (); */ mu_m_server_set_default_port (server, 110); mu_m_server_set_timeout (server, 600); mu_m_server_set_strexit (server, mu_strexit); mu_alloc_die_hook = pop3d_alloc_die; mu_log_syslog = 1; manlock_mandatory_locking = 1; #ifdef ENABLE_DBM set_dbm_safety (); #endif if (mu_app_init (&argp, pop3d_argp_capa, pop3d_cfg_param, argc, argv, 0, NULL, server)) exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */ if (expire == 0) expire_on_exit = 1; #ifdef USE_LIBPAM if (!mu_pam_service) mu_pam_service = "gnu-pop3d"; #endif if (mu_m_server_mode (server) == MODE_INTERACTIVE && isatty (0)) { /* If input is a tty, switch to debug mode */ debug_mode = 1; } else { errno = 0; gr = getgrnam ("mail"); if (gr == NULL) { if (errno == 0 || errno == ENOENT) { mu_error (_("%s: no such group"), "mail"); exit (EX_CONFIG); } else { mu_diag_funcall (MU_DIAG_ERROR, "getgrnam", "mail", errno); exit (EX_OSERR); } } if (setgid (gr->gr_gid) == -1) { mu_error (_("error setting mail group: %s"), mu_strerror (errno)); exit (EX_OSERR); } } /* Set the signal handlers. */ mu_set_signals (pop3d_master_signal, sigtab, MU_ARRAY_SIZE (sigtab)); mu_stdstream_strerr_setup (mu_log_syslog ? MU_STRERR_SYSLOG : MU_STRERR_STDERR); umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */ /* Check TLS environment, i.e. cert and key files */ #ifdef WITH_TLS tls_available = mu_check_tls_environment (); if (tls_available) enable_stls (); #endif /* WITH_TLS */ /* Actually run the daemon. */ if (mu_m_server_mode (server) == MODE_DAEMON) { mu_m_server_begin (server); status = mu_m_server_run (server); mu_m_server_end (server); mu_m_server_destroy (&server); } else { /* Make sure we are in the root directory. */ chdir ("/"); status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, tls_mode); } if (status) mu_error (_("main loop status: %s"), mu_strerror (status)); /* Close the syslog connection and exit. */ closelog (); return status ? EX_SOFTWARE : EX_OK; }
int main (int argc, char *argv[]) { mu_locker_t locker = 0; int err = 0; pid_t usergid = getgid (); pid_t mailgid = getegid (); /* Native Language Support */ MU_APP_INIT_NLS (); /* Drop permissions during argument parsing. */ if (setegid (usergid) < 0) return MU_DL_EX_ERROR; argp_err_exit_status = MU_DL_EX_ERROR; mu_argp_init (NULL, NULL); if (mu_app_init (&argp, dotlock_capa, dotlock_cfg_param, argc, argv, 0, NULL, NULL)) exit (1); if (force) { force *= 60; flags |= MU_LOCKER_TIME; } if (retries != 0) flags |= MU_LOCKER_RETRY; if ((err = mu_locker_create (&locker, file, flags))) { if (debug) mu_diag_funcall (MU_DIAG_ERROR, "mu_locker_create", NULL, err); return MU_DL_EX_ERROR; } if (force != 0) mu_locker_set_expire_time (locker, force); if (retries != 0) mu_locker_set_retries (locker, retries); if (setegid (mailgid) < 0) return MU_DL_EX_ERROR; if (unlock) err = mu_locker_remove_lock (locker); else err = mu_locker_lock (locker); setegid(usergid); mu_locker_destroy (&locker); if (debug && err) mu_error (unlock ? _("unlocking the file %s failed: %s") : _("locking the file %s failed: %s"), file, mu_strerror (err)); switch (err) { case 0: err = MU_DL_EX_OK; break; case EPERM: err = MU_DL_EX_PERM; break; case MU_ERR_LOCK_NOT_HELD: err = MU_DL_EX_NEXIST; break; case MU_ERR_LOCK_CONFLICT: err = MU_DL_EX_EXIST; break; default: err = MU_DL_EX_ERROR; break; } return err; }
/* The main part of the daemon. This function reads input from the client and executes the proper functions. Also handles the bulk of error reporting. Arguments: ifd -- input descriptor ofd -- output descriptor tls -- initiate encrypted connection */ int pop3d_mainloop (int ifd, int ofd, enum tls_mode tls) { int status = OK; char buffer[512]; static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, SIGABRT, SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGALRM }; struct pop3d_session session; mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab)); if (tls == tls_unspecified) tls = tls_available ? tls_ondemand : tls_no; else if (tls != tls_no && !tls_available) { mu_error (_("TLS is not configured, but requested in the " "configuration")); tls = tls_no; } pop3d_setio (ifd, ofd, tls == tls_connection); if (tls == tls_required) initial_state = INITIAL; state = tls == tls_connection ? AUTHORIZATION : initial_state; pop3d_session_init (&session); session.tls = tls; /* FIXME: state should also be in the session? */ /* Prepare the shared secret for APOP. */ { char *local_hostname; status = mu_get_host_name (&local_hostname); if (status) { mu_diag_funcall (MU_DIAG_ERROR, "mu_get_host_name", NULL, status); exit (EXIT_FAILURE); } md5shared = mu_alloc (strlen (local_hostname) + 51); snprintf (md5shared, strlen (local_hostname) + 50, "<%u.%u@%s>", getpid (), (unsigned)time (NULL), local_hostname); free (local_hostname); } /* Lets boogie. */ pop3d_outf ("+OK POP3 Ready %s\n", md5shared); while (state != UPDATE && state != ABORT) { char *buf; char *arg, *cmd; pop3d_command_handler_t handler; pop3d_flush_output (); status = OK; buf = pop3d_readline (buffer, sizeof (buffer)); pop3d_parse_command (buf, &cmd, &arg); if (state == TRANSACTION && !mu_mailbox_is_updated (mbox)) { static mu_off_t mailbox_size; mu_off_t newsize = 0; mu_mailbox_get_size (mbox, &newsize); /* Did we shrink? First time save the size. */ if (!mailbox_size) mailbox_size = newsize; else if (newsize < mailbox_size) /* FIXME: Should it be a != ? */ pop3d_abquit (ERR_MBOX_SYNC); /* Out of sync, Bail out. */ } /* Refresh the Lock. */ manlock_touchlock (mbox); if ((handler = pop3d_find_command (cmd)) != NULL) status = handler (arg, &session); else status = ERR_BAD_CMD; if (status != OK) pop3d_outf ("-ERR %s\n", pop3d_error_string (status)); } pop3d_session_free (&session); pop3d_bye (); return status; }
static int rmf (const char *name) { DIR *dir; struct dirent *entry; int failures = 0; dir = opendir (name); if (!dir) { mu_error (_("cannot scan folder %s: %s"), name, strerror (errno)); return 1; } if (interactive && !mh_getyn (_("Remove folder %s"), name)) exit (0); while ((entry = readdir (dir))) { char *p; struct stat st; if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0) continue; asprintf (&p, "%s/%s", name, entry->d_name); if (stat (p, &st) < 0) { mu_diag_funcall (MU_DIAG_ERROR, "stat", p, errno); } else if (S_ISDIR (st.st_mode)) { if (recurse) failures += rmf (p); else { printf ("%s: file `%s' not deleted, continuing...\n", mu_program_name, p); failures++; } } else { if (unlink (p)) { mu_diag_funcall (MU_DIAG_ERROR, "unlink", p, errno); failures++; } } free (p); } closedir (dir); if (failures == 0) failures += rmdir (name); else printf ("%s: folder `%s' not removed\n", mu_program_name, name); if (failures == 0) { if (cur_folder_path && strcmp (name, cur_folder_path) == 0) { mh_set_current_folder ("inbox"); mh_global_sequences_drop (); mh_global_save_state (); printf ("[+inbox now current]\n"); } } return failures; }
int main (int argc, char **argv) { int i; int rc; mu_folder_t folder; char *fname = NULL; mu_set_program_name (argv[0]); mu_registrar_record (mu_imap_record); mu_registrar_record (mu_imaps_record); if (argc == 1) { usage (); exit (0); } for (i = 1; i < argc; i++) { if (strncmp (argv[i], "debug=", 6) == 0) mu_debug_parse_spec (argv[i] + 6); else if (strncmp (argv[i], "url=", 4) == 0) fname = argv[i] + 4; else break; } if (!fname) { mu_error ("URL not specified"); exit (1); } rc = mu_folder_create (&folder, fname); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", fname, rc); return 1; } rc = mu_folder_open (folder, MU_STREAM_READ); if (rc) { mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", fname, rc); return 1; } while (i < argc) { char *comargs[2]; struct command *cmd; cmd = find_command (argv[i]); if (!cmd) { mu_error ("unknown command %s\n", argv[i]); break; } i++; if (i + cmd->nargs > argc) { mu_error ("not enough arguments for %s", cmd->verb); break; } memcpy (comargs, argv + i, cmd->nargs * sizeof (comargs[0])); i += cmd->nargs; cmd->handler (folder, comargs); } mu_folder_close (folder); mu_folder_destroy (&folder); return 0; }
/* This code is shared with EXAMINE. */ int imap4d_select0 (struct imap4d_command *command, const char *mboxname, int flags) { int status; char *mailbox_name; /* FIXME: Check state. */ /* Even if a mailbox is selected, a SELECT EXAMINE or LOGOUT command MAY be issued without previously issuing a CLOSE command. The SELECT, EXAMINE, and LOGUT commands implictly close the currently selected mailbox without doing an expunge. */ if (mbox) { imap4d_enter_critical (); mu_mailbox_sync (mbox); mu_mailbox_close (mbox); manlock_unlock (mbox); imap4d_leave_critical (); mu_mailbox_destroy (&mbox); /* Destroy the old uid table. */ imap4d_sync (); } if (strcmp (mboxname, "INBOX") == 0) flags |= MU_STREAM_CREAT; mailbox_name = namespace_getfullpath (mboxname, NULL); if (!mailbox_name) return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); if (flags & MU_STREAM_RDWR) { status = manlock_open_mailbox (&mbox, mailbox_name, 1, flags); } else { status = mu_mailbox_create_default (&mbox, mailbox_name); if (status) mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_default", mailbox_name, status); else { status = mu_mailbox_open (mbox, flags); if (status) { mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open", mailbox_name, status); mu_mailbox_destroy (&mbox); } } } if (status == 0) { select_flags = flags; state = STATE_SEL; imap4d_set_observer (mbox); if ((status = imap4d_select_status ()) == 0) { free (mailbox_name); /* Need to set the state explicitely for select. */ return io_sendf ("%s OK [%s] %s Completed\n", command->tag, ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR) ? "READ-WRITE" : "READ-ONLY", command->name); } } mu_mailbox_destroy (&mbox); status = io_completion_response (command, RESP_NO, "Could not open %s: %s", mboxname, mu_strerror (status)); free (mailbox_name); return status; }
int mutool_send (int argc, char **argv) { int index; char *infile; mu_stream_t instr; mu_message_t msg; size_t count; mu_url_t urlhint, url; mu_mailer_t mailer; MU_ASSERT (mu_address_create_null (&rcpt_addr)); mu_register_all_mailer_formats (); if (argp_parse (&send_argp, argc, argv, 0, &index, NULL)) return 1; argc -= index; argv += index; if (argc < 1) { mu_error (_("not enough arguments")); return 1; } infile = argv[1]; if (infile) MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|MU_STREAM_SEEK)); else MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, MU_STREAM_READ|MU_STREAM_SEEK)); MU_ASSERT (mu_stream_to_message (instr, &msg)); mu_stream_unref (instr); mu_address_get_count (rcpt_addr, &count); if (count == 0) read_recipients = 1; if (read_recipients) { int rc; mu_header_t header; const char *value; MU_ASSERT (mu_message_get_header (msg, &header)); rc = mu_header_sget_value (header, MU_HEADER_TO, &value); if (rc == 0) send_address_add (&rcpt_addr, value); else if (rc != MU_ERR_NOENT) { mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value", MU_HEADER_TO, rc); exit (1); } rc = mu_header_sget_value (header, MU_HEADER_CC, &value); if (rc == 0) send_address_add (&rcpt_addr, value); else if (rc != MU_ERR_NOENT) { mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value", MU_HEADER_CC, rc); exit (1); } rc = mu_header_sget_value (header, MU_HEADER_BCC, &value); if (rc == 0) send_address_add (&rcpt_addr, value); else if (rc != MU_ERR_NOENT) { mu_diag_funcall (MU_DIAG_ERROR, "mu_header_sget_value", MU_HEADER_BCC, rc); exit (1); } } mu_address_get_count (rcpt_addr, &count); if (count == 0) { mu_error (_("no recipients")); exit (1); } MU_ASSERT (mu_url_create (&urlhint, "smtp://")); MU_ASSERT (mu_url_create_hint (&url, argv[0], MU_URL_PARSE_DEFAULT, urlhint)); mu_url_invalidate (url); MU_ASSERT (mu_mailer_create_from_url (&mailer, url)); MU_ASSERT (mu_mailer_open (mailer, MU_STREAM_RDWR)); MU_ASSERT (mu_mailer_send_message (mailer, msg, from_addr, rcpt_addr)); mu_mailer_close (mailer); mu_mailer_destroy (&mailer); return 0; }