/*! \brief Annotates symbols in an Init with their key. * * \param symbol_table * the symbol table. * \param scope * the scope under which the Init is defined. * \param init * the Init. */ static void annotate_init (SymbolTable symbol_table, Key scope, Init init) { if (init) { if (P_GetInitExpr (init)) annotate_expr (symbol_table, scope, P_GetInitExpr (init)); else annotate_init (symbol_table, scope, P_GetInitSet (init)); annotate_init (symbol_table, scope, P_GetInitNext (init)); } return; }
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); }
/*! \brief Annotates symbols in a Stmt with their key. * * \param symbol_table * the symbol table. * \param scope * the scope under which the Stmt is defined. * \param stmt * the Stmt. */ static void annotate_stmt (SymbolTable symbol_table, Key scope, Stmt stmt) { while (stmt) { if (stmt == NULL) return; switch (P_GetStmtType (stmt)) { case ST_NOOP: case ST_CONT: case ST_BREAK: case ST_ADVANCE: case ST_AWAIT: case ST_MUTEX: break; case ST_RETURN: annotate_expr (symbol_table, scope, P_GetStmtRet (stmt)); break; case ST_GOTO: if (!P_ValidKey (P_GetStmtLabelKey (stmt))) P_SetStmtLabelKey (stmt, find_label (symbol_table, scope, P_GetStmtLabelVal (stmt))); break; case ST_COMPOUND: { Compound c = P_GetStmtCompound (stmt); VarList var_list = P_GetCompoundVarList (c); VarDcl var_dcl; /* Annotate any variables used in initializers. */ for (List_start (var_list), var_dcl = (VarDcl)List_next (var_list); var_dcl; var_dcl = (VarDcl)List_next (var_list)) { if (P_GetVarDclInit (var_dcl)) annotate_init (symbol_table, P_GetStmtKey (stmt), P_GetVarDclInit (var_dcl)); } annotate_stmt (symbol_table, P_GetStmtKey (stmt), P_GetCompoundStmtList (c)); } break; case ST_IF: { IfStmt i = P_GetStmtIfStmt (stmt); annotate_expr (symbol_table, scope, P_GetIfStmtCondExpr (i)); annotate_stmt (symbol_table, scope, P_GetIfStmtThenBlock (i)); annotate_stmt (symbol_table, scope, P_GetIfStmtElseBlock (i)); } break; case ST_SWITCH: { SwitchStmt s = P_GetStmtSwitchStmt (stmt); annotate_expr (symbol_table, scope, P_GetSwitchStmtExpression (s)); annotate_stmt (symbol_table, scope, P_GetSwitchStmtSwitchBody (s)); } break; case ST_PSTMT: { Pstmt p = P_GetStmtPstmt (stmt); annotate_stmt (symbol_table, scope, P_GetPstmtStmt (p)); } break; case ST_COBEGIN: { Cobegin c = P_GetStmtCobegin (stmt); annotate_stmt (symbol_table, scope, P_GetCobeginStatements (c)); } break; case ST_PARLOOP: { ParLoop p = P_GetStmtParLoop (stmt); annotate_stmt (symbol_table, scope, P_GetPstmtStmt (P_GetParLoopPstmt (p))); annotate_expr (symbol_table, scope, P_GetParLoopIterationVar (p)); annotate_expr (symbol_table, scope, P_GetParLoopInitValue (p)); annotate_expr (symbol_table, scope, P_GetParLoopFinalValue (p)); annotate_expr (symbol_table, scope, P_GetParLoopIncrValue (p)); annotate_stmt (symbol_table, scope, P_GetParLoopChild (p)); } break; case ST_SERLOOP: { SerLoop s = P_GetStmtSerLoop (stmt); annotate_stmt (symbol_table, scope, P_GetSerLoopLoopBody (s)); annotate_expr (symbol_table, scope, P_GetSerLoopCondExpr (s)); annotate_expr (symbol_table, scope, P_GetSerLoopInitExpr (s)); annotate_expr (symbol_table, scope, P_GetSerLoopIterExpr (s)); } break; case ST_EXPR: annotate_expr (symbol_table, scope, P_GetStmtExpr (stmt)); break; case ST_BODY: { BodyStmt b = P_GetStmtBodyStmt (stmt); annotate_stmt (symbol_table, scope, P_GetBodyStmtStatement (b)); } break; case ST_EPILOGUE: { EpilogueStmt e = P_GetStmtEpilogueStmt (stmt); annotate_stmt (symbol_table, scope, P_GetEpilogueStmtStatement (e)); } break; case ST_ASM: { AsmStmt a = P_GetStmtAsmStmt (stmt); annotate_expr (symbol_table, scope, P_GetAsmStmtAsmClobbers (a)); annotate_expr (symbol_table, scope, P_GetAsmStmtAsmString (a)); annotate_expr (symbol_table, scope, P_GetAsmStmtAsmOperands (a)); } break; } stmt = P_GetStmtLexNext (stmt); } return; }