EXPORTED void sync_log_init(void) { const char *conf; int i; /* sync_log_init() may be called more than once */ if (channels) strarray_free(channels); conf = config_getstring(IMAPOPT_SYNC_LOG_CHANNELS); if (!conf) conf = "\"\""; channels = strarray_split(conf, " ", 0); /* * The sysadmin can specify "" in the value of sync_log_channels to * mean the default channel name - this will be useful for sysadmins * who want to start using a sync log channel for squatter but who * have been using the default sync log channel for sync_client. */ i = strarray_find(channels, "\"\"", 0); if (i >= 0) strarray_set(channels, i, NULL); strarray_free(unsuppressable); unsuppressable = NULL; conf = config_getstring(IMAPOPT_SYNC_LOG_UNSUPPRESSABLE_CHANNELS); if (conf) unsuppressable = strarray_split(conf, " ", 0); }
EXPORTED int is_system_user(const char *userid) { static strarray_t *admins = NULL; if (!admins) admins = strarray_split(config_getstring(IMAPOPT_ADMINS), NULL, STRARRAY_TRIM); if (!strcmp(userid, "anyone")) return 1; if (!strcmp(userid, "anonymous")) return 1; if (strarray_find(admins, userid, 0) >= 0) return 1; return 0; }
int main(int argc, char **argv) { int opt; char *alt_config = NULL; int r = IMAP_NOTFOUND; strarray_t mboxnames = STRARRAY_INITIALIZER; const char *query = NULL; int background = 1; const char *channel = "squatter"; const char *synclogfile = NULL; int init_flags = CYRUSINIT_PERROR; int multi_folder = 0; int user_mode = 0; int compact_flags = 0; const char *fromfile = NULL; strarray_t *srctiers = NULL; const char *desttier = NULL; enum { UNKNOWN, INDEXER, INDEXFROM, SEARCH, ROLLING, SYNCLOG, START_DAEMON, STOP_DAEMON, RUN_DAEMON, COMPACT } mode = UNKNOWN; if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) { fatal("must run as the Cyrus user", EC_USAGE); } setbuf(stdout, NULL); while ((opt = getopt(argc, argv, "C:I:N:RAXT:S:Fc:de:f:mn:rsiavz:t:ou")) != EOF) { switch (opt) { case 'C': /* alt config file */ alt_config = optarg; break; case 'A': compact_flags |= SEARCH_COMPACT_AUDIT; break; case 'F': compact_flags |= SEARCH_COMPACT_FILTER; break; case 'X': compact_flags |= SEARCH_COMPACT_REINDEX; break; case 'N': name_starts_from = optarg; break; case 'I': /* indexer, using specified mbox/uids in file */ if (mode != UNKNOWN && mode != INDEXFROM) usage(argv[0]); fromfile = optarg; mode = INDEXFROM; break; case 'R': /* rolling indexer */ if (mode != UNKNOWN) usage(argv[0]); mode = ROLLING; incremental_mode = 1; /* always incremental if rolling */ break; case 'S': /* sleep time in seconds */ sleepmicroseconds = (atof(optarg) * 1000000); break; case 'T': /* temporary root directory for search */ temp_root_dir = optarg; break; /* This option is deliberately undocumented, for testing only */ case 'c': /* daemon control mode */ if (mode != UNKNOWN) usage(argv[0]); if (!strcmp(optarg, "start")) mode = START_DAEMON; else if (!strcmp(optarg, "stop")) mode = STOP_DAEMON; else if (!strcmp(optarg, "run")) mode = RUN_DAEMON; else usage(argv[0]); break; case 'd': /* foreground (with -R) */ background = 0; break; /* This option is deliberately undocumented, for testing only */ case 'e': /* add a search term */ if (mode != UNKNOWN && mode != SEARCH) usage(argv[0]); query = optarg; mode = SEARCH; break; case 'f': /* alternate synclogfile used in SYNCLOG mode */ synclogfile = optarg; mode = SYNCLOG; break; /* This option is deliberately undocumented, for testing only */ case 'm': /* multi-folder in SEARCH mode */ if (mode != UNKNOWN && mode != SEARCH) usage(argv[0]); multi_folder = 1; mode = SEARCH; break; case 'n': /* sync channel name (with -R) */ channel = optarg; break; case 'o': /* copy one DB rather than compressing */ compact_flags |= SEARCH_COMPACT_COPYONE; break; case 'v': /* verbose */ verbose++; break; case 'r': /* recurse */ if (mode != UNKNOWN && mode != INDEXER) usage(argv[0]); recursive_flag = 1; mode = INDEXER; break; case 'i': /* incremental mode */ incremental_mode = 1; break; case 'a': /* use /squat annotation */ if (mode != UNKNOWN && mode != INDEXER) usage(argv[0]); annotation_flag = 1; mode = INDEXER; break; case 'z': if (mode != UNKNOWN && mode != COMPACT) usage(argv[0]); desttier = optarg; mode = COMPACT; break; case 't': if (mode != UNKNOWN && mode != COMPACT) usage(argv[0]); srctiers = strarray_split(optarg, ",", 0); mode = COMPACT; break; case 'u': user_mode = 1; break; default: usage("squatter"); } } compact_flags |= SEARCH_VERBOSE(verbose); if (mode == UNKNOWN) mode = INDEXER; /* fork and close fds if required */ if (mode == ROLLING && background) { become_daemon(); init_flags &= ~CYRUSINIT_PERROR; } if (mode == COMPACT && (!desttier || !srctiers)) { /* need both src and dest for compact */ usage("squatter"); } cyrus_init(alt_config, "squatter", init_flags, CONFIG_NEED_PARTITION_DATA); /* Set namespace -- force standard (internal) */ if ((r = mboxname_init_namespace(&squat_namespace, 1)) != 0) { fatal(error_message(r), EC_CONFIG); } annotate_init(NULL, NULL); annotatemore_open(); mboxlist_init(0); mboxlist_open(NULL); if (mode == ROLLING || mode == SYNCLOG) { signals_set_shutdown(&shut_down); signals_add_handlers(0); } switch (mode) { case UNKNOWN: break; case INDEXER: /* -r requires at least one mailbox */ if (recursive_flag && optind == argc) usage(argv[0]); expand_mboxnames(&mboxnames, argc-optind, (const char **)argv+optind, user_mode); syslog(LOG_NOTICE, "indexing mailboxes"); r = do_indexer(&mboxnames); syslog(LOG_NOTICE, "done indexing mailboxes"); break; case INDEXFROM: syslog(LOG_NOTICE, "indexing messages"); r = do_indexfrom(fromfile); syslog(LOG_NOTICE, "done indexing messages"); break; case SEARCH: if (recursive_flag && optind == argc) usage(argv[0]); expand_mboxnames(&mboxnames, argc-optind, (const char **)argv+optind, user_mode); r = do_search(query, !multi_folder, &mboxnames); break; case ROLLING: do_rolling(channel); /* never returns */ break; case SYNCLOG: r = do_synclogfile(synclogfile); break; case START_DAEMON: if (optind != argc) usage("squatter"); search_start_daemon(verbose); break; case STOP_DAEMON: if (optind != argc) usage("squatter"); search_stop_daemon(verbose); break; case RUN_DAEMON: if (optind != argc) usage("squatter"); do_run_daemon(); break; case COMPACT: if (recursive_flag && optind == argc) usage(argv[0]); expand_mboxnames(&mboxnames, argc-optind, (const char **)argv+optind, user_mode); r = do_compact(&mboxnames, srctiers, desttier, compact_flags); break; } strarray_fini(&mboxnames); shut_down(r ? EC_TEMPFAIL : 0); }
/* * Parse a quota database entry, which is formatted as a string * containing multiple space-separated fields, into a struct quota. * Returns: 0 on success or an IMAP error code. */ static int quota_parseval(const char *data, size_t datalen, struct quota *quota, int iswrite) { strarray_t *fields = NULL; int r = IMAP_MAILBOX_BADFORMAT; int i = 0; int res = QUOTA_STORAGE; struct dlist *dl = NULL; quota_t temp; /* new dlist format */ if (data[0] == '%') { if (dlist_parsemap(&dl, 0, data, datalen)) goto out; for (res = 0; res < QUOTA_NUMRESOURCES; res++) { struct dlist *val; struct dlist *item = dlist_getchild(dl, quota_db_names[res]); if (!item) continue; val = dlist_getchildn(item, 0); if (val) quota->useds[res] = dlist_num(val); val = dlist_getchildn(item, 1); if (val) quota->limits[res] = dlist_num(val); } /* only read the SCAN stuff if it's a write lock */ if (iswrite) { struct dlist *scan = dlist_getchild(dl, "SCAN"); const char *mboxname = NULL; if (!scan) goto done; if (!dlist_getatom(scan, "MBOX", &mboxname)) goto done; quota->scanmbox = xstrdup(mboxname); for (res = 0; res < QUOTA_NUMRESOURCES; res++) { struct dlist *val = dlist_getchild(scan, quota_db_names[res]); if (val) quota->scanuseds[res] = dlist_num(val); } } goto done; } /* parse historical formats */ fields = strarray_split(data, NULL, 0); for (;;) { if (i+2 > fields->count) goto out; /* need at least 2 more fields */ if (sscanf(fields->data[i++], QUOTA_T_FMT, "a->useds[res]) != 1) goto out; if (sscanf(fields->data[i++], QUOTA_T_FMT, "a->limits[res]) != 1) goto out; /* skip over temporary extra used data from failed quota -f runs */ if (i < fields->count && sscanf(fields->data[i], QUOTA_T_FMT, &temp) == 1) { i++; } if (i == fields->count) break; /* successfully parsed whole line */ for (res = 0 ; res < QUOTA_NUMRESOURCES ; res++) { if (quota_db_names[res] && !strcasecmp(fields->data[i], quota_db_names[res])) break; } if (res == QUOTA_NUMRESOURCES) goto out; i++; } done: r = 0; out: dlist_free(&dl); strarray_free(fields); return r; }
/* Called before a cyrus application starts (but after command line parameters * are read) */ EXPORTED int cyrus_init(const char *alt_config, const char *ident, unsigned flags, int config_need_data) { char *p; const char *val; const char *prefix; int umaskval = 0; int syslog_opts = LOG_PID; const char *facility; if(cyrus_init_run != NOT_RUNNING) { fatal("cyrus_init called twice!", EC_CONFIG); } else { cyrus_init_run = RUNNING; } cyrus_init_nodb = (flags & CYRUSINIT_NODB); #ifdef LOG_PERROR if ((flags & CYRUSINIT_PERROR)) syslog_opts |= LOG_PERROR; #endif initialize_imap_error_table(); initialize_mupd_error_table(); if(!ident) fatal("service name was not specified to cyrus_init", EC_CONFIG); config_ident = ident; /* xxx we lose here since we can't have the prefix until we load the * config file */ openlog(config_ident, syslog_opts, SYSLOG_FACILITY); /* Load configuration file. This will set config_dir when it finds it */ config_read(alt_config, config_need_data); prefix = config_getstring(IMAPOPT_SYSLOG_PREFIX); facility = config_getstring(IMAPOPT_SYSLOG_FACILITY); /* Reopen the log with the new prefix, if needed */ if (prefix || facility) { char *ident_buf; int facnum = facility ? get_facility(facility) : SYSLOG_FACILITY; if (prefix) ident_buf = strconcat(prefix, "/", ident, (char *)NULL); else ident_buf = xstrdup(ident); closelog(); openlog(ident_buf, syslog_opts, facnum); /* don't free the openlog() string! */ } /* allow debug logging */ if (!config_debug) setlogmask(~LOG_MASK(LOG_DEBUG)); /* Look up default partition */ config_defpartition = config_getstring(IMAPOPT_DEFAULTPARTITION); for (p = (char *)config_defpartition; p && *p; p++) { if (!Uisalnum(*p)) fatal("defaultpartition option contains non-alphanumeric character", EC_CONFIG); if (Uisupper(*p)) *p = tolower((unsigned char) *p); } /* Look up umask */ val = config_getstring(IMAPOPT_UMASK); while (*val) { if (*val >= '0' && *val <= '7') umaskval = umaskval*8 + *val - '0'; val++; } umask(umaskval); config_fulldirhash = config_getswitch(IMAPOPT_FULLDIRHASH); /* look up and canonify the implicit rights of mailbox owners */ cyrus_acl_strtomask(config_getstring(IMAPOPT_IMPLICIT_OWNER_RIGHTS), &config_implicitrights); /* XXX and if strtomask fails? */ config_metapartition_files = config_getbitfield(IMAPOPT_METAPARTITION_FILES); val = config_getstring(IMAPOPT_SUPPRESS_CAPABILITIES); if (val) suppressed_capabilities = strarray_split(val, NULL, 0); if (config_getswitch(IMAPOPT_SEARCH_SKIPDIACRIT)) charset_flags |= CHARSET_SKIPDIACRIT; switch (config_getenum(IMAPOPT_SEARCH_WHITESPACE)) { case IMAP_ENUM_SEARCH_WHITESPACE_MERGE: charset_flags |= CHARSET_MERGESPACE; break; case IMAP_ENUM_SEARCH_WHITESPACE_SKIP: charset_flags |= CHARSET_SKIPSPACE; break; default: break; } if (config_getswitch(IMAPOPT_SEARCH_SKIPHTML)) charset_flags |= CHARSET_SKIPHTML; if (config_getswitch(IMAPOPT_RFC2047_UTF8)) charset_flags |= CHARSET_MIME_UTF8; /* Set snippet conversion flags. */ charset_snippet_flags = CHARSET_SNIPPET; if (config_getenum(IMAPOPT_SEARCH_ENGINE) != IMAP_ENUM_SEARCH_ENGINE_XAPIAN) { /* All search engines other than Xapian require escaped HTML */ charset_snippet_flags |= CHARSET_ESCAPEHTML; } if (!cyrus_init_nodb) { /* lookup the database backends */ config_mboxlist_db = config_getstring(IMAPOPT_MBOXLIST_DB); config_quota_db = config_getstring(IMAPOPT_QUOTA_DB); config_subscription_db = config_getstring(IMAPOPT_SUBSCRIPTION_DB); config_annotation_db = config_getstring(IMAPOPT_ANNOTATION_DB); config_seenstate_db = config_getstring(IMAPOPT_SEENSTATE_DB); config_mboxkey_db = config_getstring(IMAPOPT_MBOXKEY_DB); config_duplicate_db = config_getstring(IMAPOPT_DUPLICATE_DB); config_tls_sessions_db = config_getstring(IMAPOPT_TLS_SESSIONS_DB); config_ptscache_db = config_getstring(IMAPOPT_PTSCACHE_DB); config_statuscache_db = config_getstring(IMAPOPT_STATUSCACHE_DB); config_userdeny_db = config_getstring(IMAPOPT_USERDENY_DB); config_zoneinfo_db = config_getstring(IMAPOPT_ZONEINFO_DB); config_conversations_db = config_getstring(IMAPOPT_CONVERSATIONS_DB); config_backup_db = config_getstring(IMAPOPT_BACKUP_DB); /* configure libcyrus as needed */ libcyrus_config_setstring(CYRUSOPT_CONFIG_DIR, config_dir); libcyrus_config_setswitch(CYRUSOPT_AUTH_UNIX_GROUP_ENABLE, config_getswitch(IMAPOPT_UNIX_GROUP_ENABLE)); libcyrus_config_setswitch(CYRUSOPT_USERNAME_TOLOWER, config_getswitch(IMAPOPT_USERNAME_TOLOWER)); libcyrus_config_setswitch(CYRUSOPT_SKIPLIST_UNSAFE, config_getswitch(IMAPOPT_SKIPLIST_UNSAFE)); libcyrus_config_setstring(CYRUSOPT_TEMP_PATH, config_getstring(IMAPOPT_TEMP_PATH)); libcyrus_config_setint(CYRUSOPT_PTS_CACHE_TIMEOUT, config_getint(IMAPOPT_PTSCACHE_TIMEOUT)); libcyrus_config_setswitch(CYRUSOPT_FULLDIRHASH, config_getswitch(IMAPOPT_FULLDIRHASH)); libcyrus_config_setstring(CYRUSOPT_PTSCACHE_DB, config_getstring(IMAPOPT_PTSCACHE_DB)); libcyrus_config_setstring(CYRUSOPT_PTSCACHE_DB_PATH, config_getstring(IMAPOPT_PTSCACHE_DB_PATH)); libcyrus_config_setstring(CYRUSOPT_PTLOADER_SOCK, config_getstring(IMAPOPT_PTLOADER_SOCK)); libcyrus_config_setswitch(CYRUSOPT_VIRTDOMAINS, config_getenum(IMAPOPT_VIRTDOMAINS)); libcyrus_config_setstring(CYRUSOPT_AUTH_MECH, config_getstring(IMAPOPT_AUTH_MECH)); libcyrus_config_setstring(CYRUSOPT_DELETERIGHT, config_getstring(IMAPOPT_DELETERIGHT)); libcyrus_config_setstring(CYRUSOPT_SQL_DATABASE, config_getstring(IMAPOPT_SQL_DATABASE)); libcyrus_config_setstring(CYRUSOPT_SQL_ENGINE, config_getstring(IMAPOPT_SQL_ENGINE)); libcyrus_config_setstring(CYRUSOPT_SQL_HOSTNAMES, config_getstring(IMAPOPT_SQL_HOSTNAMES)); libcyrus_config_setstring(CYRUSOPT_SQL_USER, config_getstring(IMAPOPT_SQL_USER)); libcyrus_config_setstring(CYRUSOPT_SQL_PASSWD, config_getstring(IMAPOPT_SQL_PASSWD)); libcyrus_config_setswitch(CYRUSOPT_SQL_USESSL, config_getswitch(IMAPOPT_SQL_USESSL)); libcyrus_config_setswitch(CYRUSOPT_SKIPLIST_ALWAYS_CHECKPOINT, config_getswitch(IMAPOPT_SKIPLIST_ALWAYS_CHECKPOINT)); /* Not until all configuration parameters are set! */ libcyrus_init(); } return 0; }