コード例 #1
0
ファイル: interp.c プロジェクト: kolab-groupware/cyrus-imapd
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;
}
コード例 #2
0
ファイル: squatter.c プロジェクト: JensErat/cyrus-imapd
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;
}
コード例 #3
0
ファイル: squatter.c プロジェクト: JensErat/cyrus-imapd
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;
}
コード例 #4
0
ファイル: command.c プロジェクト: cyrusimap/cyrus-imapd
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;
}
コード例 #5
0
ファイル: script.c プロジェクト: gnb/cyrus-imapd
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;
}
コード例 #6
0
ファイル: auth_pts.c プロジェクト: brong/cyrus-imapd
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;
}
コード例 #7
0
ファイル: cyrdump.c プロジェクト: brong/cyrus-imapd
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;
}
コード例 #8
0
ファイル: fetchnews.c プロジェクト: sebmichel/cyrus-imapd
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;
}
コード例 #9
0
ファイル: command.c プロジェクト: cyrusimap/cyrus-imapd
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;
}
コード例 #10
0
ファイル: vparse.c プロジェクト: JensErat/cyrus-imapd
EXPORTED void vparse_set_multiparam(struct vparse_state *state, const char *name)
{
    if (!state->multiparam) state->multiparam = strarray_new();
    strarray_append(state->multiparam, name);
}
コード例 #11
0
ファイル: auth_unix.c プロジェクト: sebmichel/cyrus-imapd
/*
 * 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;
}
コード例 #12
0
ファイル: reconstruct.c プロジェクト: RaymondPo/cyrus-imapd
/*
 * 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;
}
コード例 #13
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;
}