EXPORTED void sieve_register_imapflags(sieve_interp_t *interp, const strarray_t *mark) { static strarray_t default_mark = STRARRAY_INITIALIZER; if (!default_mark.count) strarray_append(&default_mark, "\\flagged"); interp->markflags = (mark && mark->data && mark->count) ? mark : &default_mark; }
static int do_synclogfile(const char *synclogfile) { strarray_t *folders = NULL; sync_log_reader_t *slr; int nskipped = 0; int i; int r; slr = sync_log_reader_create_with_filename(synclogfile); r = sync_log_reader_begin(slr); if (r) goto out; folders = read_sync_log_items(slr); sync_log_reader_end(slr); /* sort folders for locality of reference in file processing mode */ strarray_sort(folders, cmpstringp_raw); signals_poll(); /* have some due items in the queue, try to index them */ rx = search_begin_update(verbose); for (i = 0; i < folders->count; i++) { const char *mboxname = strarray_nth(folders, i); if (verbose > 1) syslog(LOG_INFO, "do_synclogfile: indexing %s", mboxname); r = index_one(mboxname, /*blocking*/1); if (r == IMAP_MAILBOX_NONEXISTENT) r = 0; if (r == IMAP_MAILBOX_LOCKED || r == IMAP_AGAIN) { nskipped++; if (nskipped > 10000) { syslog(LOG_ERR, "IOERROR: skipped too many times at %s", mboxname); break; } r = 0; /* try again at the end */ strarray_append(folders, mboxname); } if (r) { syslog(LOG_ERR, "IOERROR: failed to index %s: %s", mboxname, error_message(r)); break; } if (sleepmicroseconds) usleep(sleepmicroseconds); } search_end_update(rx); rx = NULL; out: strarray_free(folders); sync_log_reader_free(slr); return r; }
static int addmbox(const mbentry_t *mbentry, void *rock) { strarray_t *sa = (strarray_t *) rock; if (strcmpsafe(mbentry->name, name_starts_from) < 0) return 0; if (mboxname_isdeletedmailbox(mbentry->name, NULL)) return 0; strarray_append(sa, mbentry->name); return 0; }
EXPORTED int run_command(const char *argv0, ...) { va_list va; const char *p; strarray_t argv = STRARRAY_INITIALIZER; pid_t pid; int r = 0; strarray_append(&argv, argv0); va_start(va, argv0); while ((p = va_arg(va, const char *))) strarray_append(&argv, p); va_end(va); pid = fork(); if (pid < 0) { syslog(LOG_ERR, "Failed to fork: %m"); r = IMAP_SYS_ERROR; goto out; } if (!pid) { /* in child */ r = execv(argv0, argv.data); syslog(LOG_ERR, "Failed to execute %s: %m", argv0); exit(1); } else { /* in parent */ r = wait_for_child(argv0, pid); } out: strarray_fini(&argv); return r; }
static int sieve_addflag(strarray_t *imapflags, const char *flag) { int n; /* search for flag already in list */ for (n = 0; n < imapflags->count; n++) { if (!strcmp(imapflags->data[n], flag)) break; } /* add flag to list, iff not in list */ if (n == imapflags->count) strarray_append(imapflags, flag); return SIEVE_OK; }
static strarray_t *mygroups(const struct auth_state *auth_state) { strarray_t *sa; int i; if (!auth_state->ngroups) return NULL; sa = strarray_new(); strarray_truncate(sa, auth_state->ngroups); for (i = 0; i < auth_state->ngroups; i++) { strarray_append(sa, auth_state->groups[i].id); } return sa; }
int main(int argc, char *argv[]) { int option; int i; char *alt_config = NULL; struct incremental_record irec; progname = basename(argv[0]); while ((option = getopt(argc, argv, "vC:")) != EOF) { switch (option) { case 'v': verbose++; break; case 'C': /* alt config file */ alt_config = optarg; break; default: usage(); break; } } if (optind == argc) { usage(); } cyrus_init(alt_config, "dump", 0, CONFIG_NEED_PARTITION_DATA); search_attr_init(); irec.incruid = 0; strarray_t *array = strarray_new(); for (i = optind; i < argc; i++) { strarray_append(array, argv[i]); } if (array->count) mboxlist_findallmulti(NULL, array, 1, 0, 0, dump_me, &irec); strarray_free(array); cyrus_done(); return 0; }
int main(int argc, char *argv[]) { extern char *optarg; int opt; char *alt_config = NULL, *port = "119"; const char *peer = NULL, *server = "localhost", *wildmat = "*"; char *authname = NULL, *password = NULL; int psock = -1, ssock = -1; struct protstream *pin, *pout, *sin, *sout; char buf[BUFFERSIZE]; char sfile[1024] = ""; int fd = -1, i, offered, rejected, accepted, failed; time_t stamp; strarray_t resp = STRARRAY_INITIALIZER; int newnews = 1; char *datefmt = "%y%m%d %H%M%S"; if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) { fatal("must run as the Cyrus user", EC_USAGE); } while ((opt = getopt(argc, argv, "C:s:w:f:a:p:ny")) != EOF) { switch (opt) { case 'C': /* alt config file */ alt_config = optarg; break; case 's': /* server */ server = xstrdup(optarg); if ((port = strchr(server, ':'))) *port++ = '\0'; else port = "119"; break; case 'w': /* wildmat */ wildmat = optarg; break; case 'f': /* timestamp file */ snprintf(sfile, sizeof(sfile), "%s", optarg); break; case 'a': /* authname */ authname = optarg; break; case 'p': /* password */ password = optarg; break; case 'n': /* no newnews */ newnews = 0; break; case 'y': /* newsserver is y2k compliant */ datefmt = "%Y%m%d %H%M%S"; break; default: usage(); /* NOTREACHED */ } } if (argc - optind < 1) { usage(); /* NOTREACHED */ } peer = argv[optind++]; cyrus_init(alt_config, "fetchnews", 0, 0); /* connect to the peer */ /* xxx configurable port number? */ if ((psock = init_net(peer, "119", &pin, &pout)) < 0) { fprintf(stderr, "connection to %s failed\n", peer); cyrus_done(); exit(-1); } /* read the initial greeting */ if (!prot_fgets(buf, sizeof(buf), pin) || strncmp("20", buf, 2)) { syslog(LOG_ERR, "peer not available"); goto quit; } if (authname) { /* authenticate to peer */ /* XXX this should be modified to support SASL and STARTTLS */ prot_printf(pout, "AUTHINFO USER %s\r\n", authname); if (!prot_fgets(buf, sizeof(buf), pin)) { syslog(LOG_ERR, "AUTHINFO USER terminated abnormally"); goto quit; } else if (!strncmp("381", buf, 3)) { /* password required */ if (!password) password = cyrus_getpass("Please enter the password: "******"failed to get password\n"); goto quit; } prot_printf(pout, "AUTHINFO PASS %s\r\n", password); if (!prot_fgets(buf, sizeof(buf), pin)) { syslog(LOG_ERR, "AUTHINFO PASS terminated abnormally"); goto quit; } } if (strncmp("281", buf, 3)) { /* auth failed */ goto quit; } } /* change to reader mode - not always necessary, so ignore result */ prot_printf(pout, "MODE READER\r\n"); prot_fgets(buf, sizeof(buf), pin); if (newnews) { struct tm ctime, *ptime; /* fetch the server's current time */ prot_printf(pout, "DATE\r\n"); if (!prot_fgets(buf, sizeof(buf), pin) || strncmp("111 ", buf, 4)) { syslog(LOG_ERR, "error fetching DATE"); goto quit; } /* parse and normalize the server time */ memset(&ctime, 0, sizeof(struct tm)); sscanf(buf+4, "%4d%02d%02d%02d%02d%02d", &ctime.tm_year, &ctime.tm_mon, &ctime.tm_mday, &ctime.tm_hour, &ctime.tm_min, &ctime.tm_sec); ctime.tm_year -= 1900; ctime.tm_mon--; ctime.tm_isdst = -1; /* read the previous timestamp */ if (!sfile[0]) { char oldfile[1024]; snprintf(sfile, sizeof(sfile), "%s/fetchnews.stamp", config_dir); /* upgrade from the old stamp filename to the new */ snprintf(oldfile, sizeof(oldfile), "%s/newsstamp", config_dir); rename(oldfile, sfile); } if ((fd = open(sfile, O_RDWR | O_CREAT, 0644)) == -1) { syslog(LOG_ERR, "cannot open %s", sfile); goto quit; } if (lock_nonblocking(fd) == -1) { syslog(LOG_ERR, "cannot lock %s: %m", sfile); goto quit; } if (read(fd, &stamp, sizeof(stamp)) < (int) sizeof(stamp)) { /* XXX do something better here */ stamp = 0; } /* ask for new articles */ if (stamp) stamp -= 180; /* adjust back 3 minutes */ ptime = gmtime(&stamp); ptime->tm_isdst = -1; strftime(buf, sizeof(buf), datefmt, ptime); prot_printf(pout, "NEWNEWS %s %s GMT\r\n", wildmat, buf); if (!prot_fgets(buf, sizeof(buf), pin) || strncmp("230", buf, 3)) { syslog(LOG_ERR, "peer doesn't support NEWNEWS"); newnews = 0; } /* prepare server's current time as new timestamp */ stamp = mktime(&ctime); /* adjust for local timezone XXX We need to do this because we use gmtime() above. We can't change this, otherwise we'd be incompatible with an old localtime timestamp. */ stamp += gmtoff_of(&ctime, stamp); } if (!newnews) { prot_printf(pout, "LIST ACTIVE %s\r\n", wildmat); if (!prot_fgets(buf, sizeof(buf), pin) || strncmp("215", buf, 3)) { syslog(LOG_ERR, "peer doesn't support LIST ACTIVE"); goto quit; } } /* process the NEWNEWS/LIST ACTIVE list */ while (prot_fgets(buf, sizeof(buf), pin)) { if (buf[0] == '.') break; strarray_append(&resp, buf); } if (buf[0] != '.') { syslog(LOG_ERR, "%s terminated abnormally", newnews ? "NEWNEWS" : "LIST ACTIVE"); goto quit; } if (!resp.count) { /* nothing matches our wildmat */ goto quit; } /* connect to the server */ if ((ssock = init_net(server, port, &sin, &sout)) < 0) { fprintf(stderr, "connection to %s failed\n", server); goto quit; } /* read the initial greeting */ if (!prot_fgets(buf, sizeof(buf), sin) || strncmp("20", buf, 2)) { syslog(LOG_ERR, "server not available"); goto quit; } /* fetch and store articles */ offered = rejected = accepted = failed = 0; if (newnews) { /* response is a list of msgids */ for (i = 0; i < resp.count; i++) { /* find the end of the msgid */ *(strrchr(resp.data[i], '>') + 1) = '\0'; offered++; if (fetch(resp.data[i], 1, pin, pout, sin, sout, &rejected, &accepted, &failed)) { goto quit; } } /* write the current timestamp */ lseek(fd, 0, SEEK_SET); if (write(fd, &stamp, sizeof(stamp)) < (int) sizeof(stamp)) syslog(LOG_ERR, "error writing %s", sfile); lock_unlock(fd); close(fd); } else { char group[BUFFERSIZE], msgid[BUFFERSIZE], lastbuf[50]; const char *data; unsigned long low, high, last, cur; int start; size_t datalen; struct txn *tid = NULL; newsrc_init(NULL, 0); /* * response is a list of groups. * select each group, and STAT each article we haven't seen yet. */ for (i = 0; i < resp.count; i++) { /* parse the LIST ACTIVE response */ sscanf(resp.data[i], "%s %lu %lu", group, &high, &low); last = 0; if (!cyrusdb_fetchlock(newsrc_db, group, strlen(group), &data, &datalen, &tid)) { last = strtoul(data, NULL, 10); } if (high <= last) continue; /* select the group */ prot_printf(pout, "GROUP %s\r\n", group); if (!prot_fgets(buf, sizeof(buf), pin)) { syslog(LOG_ERR, "GROUP terminated abnormally"); continue; } else if (strncmp("211", buf, 3)) break; for (start = 1, cur = low > last ? low : ++last;; cur++) { if (start) { /* STAT the first article we haven't seen */ prot_printf(pout, "STAT %lu\r\n", cur); } else { /* continue with the NEXT article */ prot_printf(pout, "NEXT\r\n"); } if (!prot_fgets(buf, sizeof(buf), pin)) { syslog(LOG_ERR, "STAT/NEXT terminated abnormally"); cur--; break; } if (!strncmp("223", buf, 3)) { /* parse the STAT/NEXT response */ sscanf(buf, "223 %lu %s", &cur, msgid); /* find the end of the msgid */ *(strrchr(msgid, '>') + 1) = '\0'; if (fetch(msgid, 0, pin, pout, sin, sout, &rejected, &accepted, &failed)) { cur--; break; } offered++; start = 0; } /* have we reached the highwater mark? */ if (cur >= high) break; } snprintf(lastbuf, sizeof(lastbuf), "%lu", cur); cyrusdb_store(newsrc_db, group, strlen(group), lastbuf, strlen(lastbuf)+1, &tid); } if (tid) cyrusdb_commit(newsrc_db, tid); newsrc_done(); } syslog(LOG_NOTICE, "fetchnews: %s offered %d; %s rejected %d, accepted %d, failed %d", peer, offered, server, rejected, accepted, failed); quit: if (psock >= 0) { prot_printf(pout, "QUIT\r\n"); prot_flush(pout); /* Flush the incoming buffer */ prot_NONBLOCK(pin); prot_fill(pin); /* close/free socket & prot layer */ close(psock); prot_free(pin); prot_free(pout); } if (ssock >= 0) { prot_printf(sout, "QUIT\r\n"); prot_flush(sout); /* Flush the incoming buffer */ prot_NONBLOCK(sin); prot_fill(sin); /* close/free socket & prot layer */ close(psock); prot_free(sin); prot_free(sout); } cyrus_done(); return 0; }
EXPORTED int command_popen(struct command **cmdp, const char *mode, const char *cwd, const char *argv0, ...) { va_list va; const char *p; strarray_t argv = STRARRAY_INITIALIZER; pid_t pid; int r = 0; struct command *cmd; int do_stdin = (strchr(mode, 'w') != NULL); int do_stdout = (strchr(mode, 'r') != NULL); int stdin_pipe[2] = { -1, -1 }; int stdout_pipe[2] = { -1, -1 }; strarray_append(&argv, argv0); va_start(va, argv0); while ((p = va_arg(va, const char *))) strarray_append(&argv, p); va_end(va); if (do_stdin) { r = pipe(stdin_pipe); if (r) { syslog(LOG_ERR, "Failed to pipe(): %m"); r = IMAP_SYS_ERROR; goto out; } } if (do_stdout) { r = pipe(stdout_pipe); if (r) { syslog(LOG_ERR, "Failed to pipe(): %m"); r = IMAP_SYS_ERROR; goto out; } } pid = fork(); if (pid < 0) { syslog(LOG_ERR, "Failed to fork: %m"); r = IMAP_SYS_ERROR; goto out; } if (!pid) { /* in child */ if (do_stdin) { close(stdin_pipe[PIPE_WRITE]); dup2(stdin_pipe[PIPE_READ], STDIN_FILENO); close(stdin_pipe[PIPE_READ]); } if (do_stdout) { close(stdout_pipe[PIPE_READ]); dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO); close(stdout_pipe[PIPE_WRITE]); } if (cwd) { r = chdir(cwd); if (r) syslog(LOG_ERR, "Failed to chdir(%s): %m", cwd); } r = execv(argv0, argv.data); syslog(LOG_ERR, "Failed to execute %s: %m", argv0); exit(1); } /* in parent */ cmd = xzmalloc(sizeof(struct command)); cmd->argv0 = xstrdup(argv0); cmd->pid = pid; if (do_stdin) cmd->stdin_prot = prot_new(stdin_pipe[PIPE_WRITE], /*write*/1); if (do_stdout) cmd->stdout_prot = prot_new(stdout_pipe[PIPE_READ], /*write*/0); *cmdp = cmd; out: if (stdin_pipe[PIPE_READ] >= 0) close(stdin_pipe[PIPE_READ]); if (stdout_pipe[PIPE_WRITE] >= 0) close(stdout_pipe[PIPE_WRITE]); if (r) { if (stdin_pipe[PIPE_WRITE] >= 0) close(stdin_pipe[PIPE_WRITE]); if (stdout_pipe[PIPE_READ] >= 0) close(stdout_pipe[PIPE_READ]); } strarray_fini(&argv); return r; }
EXPORTED void vparse_set_multiparam(struct vparse_state *state, const char *name) { if (!state->multiparam) state->multiparam = strarray_new(); strarray_append(state->multiparam, name); }
/* * Set the current user to 'identifier'. 'cacheid', if non-null, * points to a 16-byte binary key to cache identifier's information * with. */ static struct auth_state *mynewstate(const char *identifier) { struct auth_state *newstate; struct passwd *pwd; struct group *grp; #if defined(HAVE_GETGROUPLIST) && defined(__GLIBC__) gid_t gid, *groupids = NULL; int ret, ngroups = 10, oldngroups; #else char **mem; #endif identifier = mycanonifyid(identifier, 0); if (!identifier) return 0; if (!strncmp(identifier, "group:", 6)) return 0; newstate = (struct auth_state *)xmalloc(sizeof(struct auth_state)); strcpy(newstate->userid, identifier); strarray_init(&newstate->groups); if(!libcyrus_config_getswitch(CYRUSOPT_AUTH_UNIX_GROUP_ENABLE)) return newstate; pwd = getpwnam(identifier); #if defined(HAVE_GETGROUPLIST) && defined(__GLIBC__) gid = pwd ? pwd->pw_gid : (gid_t) -1; /* get the group ids */ do { groupids = (gid_t *)xrealloc((gid_t *)groupids, ngroups * sizeof(gid_t)); oldngroups = ngroups; /* copy of ngroups for comparision */ ret = getgrouplist(identifier, gid, groupids, &ngroups); /* * This is tricky. We do this as long as getgrouplist tells us to * realloc _and_ the number of groups changes. It tells us to realloc * also in the case of failure... */ } while (ret == -1 && ngroups != oldngroups); if (ret == -1) goto err; while (ngroups--) { if (pwd || groupids[ngroups] != gid) { if ((grp = getgrgid(groupids[ngroups]))) strarray_append(&newstate->groups, grp->gr_name); } } err: if (groupids) free(groupids); #else /* !HAVE_GETGROUPLIST */ setgrent(); while ((grp = getgrent())) { for (mem = grp->gr_mem; *mem; mem++) { if (!strcmp(*mem, identifier)) break; } if (*mem || (pwd && pwd->pw_gid == grp->gr_gid)) strarray_append(&newstate->groups, grp->gr_name); } endgrent(); #endif /* HAVE_GETGROUPLIST */ return newstate; }
/* * mboxlist_findall() callback function to reconstruct a mailbox */ static int do_reconstruct(struct findall_data *data, void *rock) { if (!data) return 0; strarray_t *discovered = (strarray_t *)rock; int r; static char lastname[MAX_MAILBOX_NAME] = ""; char *other; struct mailbox *mailbox = NULL; char outpath[MAX_MAILBOX_PATH]; const char *name = mbname_intname(data->mbname); signals_poll(); /* don't repeat */ if (!strcmp(name, lastname)) return 0; strncpy(lastname, name, sizeof(lastname)); lastname[sizeof(lastname)-1] = '\0'; r = mailbox_reconstruct(lastname, reconstruct_flags); if (r) { com_err(lastname, r, "%s", (r == IMAP_IOERROR) ? error_message(errno) : "Failed to reconstruct mailbox"); return 0; } r = mailbox_open_iwl(lastname, &mailbox); if (r) { com_err(lastname, r, "Failed to open after reconstruct"); return 0; } other = hash_lookup(mailbox->uniqueid, &unqid_table); if (other) { syslog (LOG_ERR, "uniqueid clash with %s for %s - changing %s", other, mailbox->uniqueid, mailbox->name); /* uniqueid change required! */ mailbox_make_uniqueid(mailbox); } hash_insert(mailbox->uniqueid, xstrdup(mailbox->name), &unqid_table); /* Convert internal name to external */ char *extname = mboxname_to_external(lastname, &recon_namespace, NULL); if (!(reconstruct_flags & RECONSTRUCT_QUIET)) printf("%s\n", extname); strncpy(outpath, mailbox_meta_fname(mailbox, META_HEADER), MAX_MAILBOX_NAME); if (setversion) { /* need to re-set the version! */ int r = mailbox_setversion(mailbox, setversion); if (r) { printf("FAILED TO REPACK %s with new version %s\n", extname, error_message(r)); } else { printf("Repacked %s to version %d\n", extname, setversion); } } mailbox_close(&mailbox); free(extname); if (discovered) { char fnamebuf[MAX_MAILBOX_PATH]; char *ptr; DIR *dirp; struct dirent *dirent; struct stat sbuf; ptr = strstr(outpath, "cyrus.header"); if (!ptr) return 0; *ptr = 0; r = chdir(outpath); if (r) return 0; /* we recurse down this directory to see if there's any mailboxes under this not in the mailboxes database */ dirp = opendir("."); if (!dirp) return 0; while ((dirent = readdir(dirp)) != NULL) { /* mailbox directories never have a dot in them */ if (strchr(dirent->d_name, '.')) continue; if (stat(dirent->d_name, &sbuf) < 0) continue; if (!S_ISDIR(sbuf.st_mode)) continue; /* ok, we found a directory that doesn't have a dot in it; is there a cyrus.header file? */ snprintf(fnamebuf, MAX_MAILBOX_PATH, "%s%s", dirent->d_name, FNAME_HEADER); if (stat(fnamebuf, &sbuf) < 0) continue; /* ok, we have a real mailbox directory */ char buf[MAX_MAILBOX_NAME]; snprintf(buf, MAX_MAILBOX_NAME, "%s.%s", name, dirent->d_name); /* does fnamebuf exist as a mailbox in mboxlist? */ do { r = mboxlist_lookup(buf, NULL, NULL); } while (r == IMAP_AGAIN); if (!r) continue; /* mailbox exists; it'll be reconstructed with a -r */ if (r != IMAP_MAILBOX_NONEXISTENT) break; /* erg? */ else r = 0; /* reset error condition */ printf("discovered %s\n", buf); strarray_append(discovered, buf); } closedir(dirp); } return 0; }
int main (int argc, char *argv[]) { int option; /* getopt() returns an int */ char *alt_config = NULL; if ((geteuid()) == 0 && (become_cyrus(/*is_master*/0) != 0)) { fatal("must run as the Cyrus user", EC_USAGE); } while ((option = getopt(argc, argv, "C:rn")) != EOF) { switch (option) { case 'C': /* alt config file */ alt_config = optarg; break; case 'r': disinfect = 1; break; case 'n': notify = 1; break; case 'h': default: usage(argv[0]); } } cyrus_init(alt_config, "cyr_virusscan", 0, CONFIG_NEED_PARTITION_DATA); if (!engine.name) { fatal("no virus scanner configured", EC_SOFTWARE); } else { if (verbose) printf("Using %s virus scanner\n", engine.name); } engine.state = engine.init(); mboxlist_init(0); mboxlist_open(NULL); /* open the quota db, we'll need it for expunge */ quotadb_init(0); quotadb_open(NULL); sync_log_init(); /* setup for mailbox event notifications */ mboxevent_init(); if (optind == argc) { /* do the whole partition */ mboxlist_findall(NULL, "*", 1, 0, 0, scan_me, NULL); } else { strarray_t *array = strarray_new(); for (; optind < argc; optind++) { strarray_append(array, argv[optind]); } mboxlist_findallmulti(NULL, array, 1, 0, 0, scan_me, NULL); strarray_free(array); } if (notify) append_notifications(); sync_log_done(); quotadb_close(); quotadb_done(); mboxlist_close(); mboxlist_done(); engine.destroy(engine.state); cyrus_done(); return 0; }