X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=conf.c;h=167aac118039b8a11cfd0f7c8c66c99516d4a945;hb=40fe452223b5cc0ff5dbae0efa8551d7e96c1a5c;hp=e875cfbc940ac7d45f61fba55c78d77ca19106a6;hpb=bd4ffcc92d6bab5737222ca0091979ac2f31cfb0;p=~andy%2Ffetchmail diff --git a/conf.c b/conf.c index e875cfbc..167aac11 100644 --- a/conf.c +++ b/conf.c @@ -1,5 +1,5 @@ /* - * conf.c -- main driver module for fetchmailconf + * conf.c -- dump fetchmail configuration as Python dictionary initializer * * For license terms, see the file COPYING in this directory. */ @@ -9,18 +9,104 @@ #include #include -#if defined(STDC_HEADERS) #include -#endif -#if defined(HAVE_UNISTD_H) #include -#endif #include #include #include #include "fetchmail.h" +/* Python prettyprinting functions */ + +static int indent_level; + +static void indent(char ic) +/* indent current line */ +{ + int i; + + if (ic == ')' || ic == ']' || ic == '}') + indent_level--; + + /* + * The guard here is a kluge. It depends on the fact that in the + * particular structure we're dumping, opening [s are always + * initializers for dictionary members and thus will be preceded + * by a member name. + */ + if (ic != '[') + { + for (i = 0; i < indent_level / 2; i++) + putc('\t', stdout); + if (indent_level % 2) + fputs(" ", stdout); + } + + if (ic) + { + putc(ic, stdout); + putc('\n', stdout); + } + + if (ic == '(' || ic == '[' || ic == '{') + indent_level++; +} + + +static void stringdump(const char *name, const char *member) +/* dump a string member with current indent */ +{ + indent('\0'); + fprintf(stdout, "\"%s\":", name); + if (member) + fprintf(stdout, "\"%s\"", visbuf(member)); + else + fputs("None", stdout); + fputs(",\n", stdout); +} + +static void numdump(const char *name, const int num) +/* dump a numeric quantity at current indent */ +{ + indent('\0'); + fprintf(stdout, "'%s':%d,\n", name, NUM_VALUE_OUT(num)); +} + +static void booldump(const char *name, const int onoff) +/* dump a boolean quantity at current indent */ +{ + indent('\0'); + if (onoff) + fprintf(stdout, "'%s':TRUE,\n", name); + else + fprintf(stdout, "'%s':FALSE,\n", name); +} + +static void listdump(const char *name, struct idlist *list) +/* dump a string list member with current indent */ +{ + indent('\0'); + fprintf(stdout, "\"%s\":", name); + + if (!list) + fputs("[],\n", stdout); + else + { + struct idlist *idp; + + fputs("[", stdout); + for (idp = list; idp; idp = idp->next) + if (idp->id) + { + fprintf(stdout, "\"%s\"", visbuf(idp->id)); + if (idp->next) + fputs(", ", stdout); + } + fputs("],\n", stdout); + } +} + /* * Note: this function dumps the entire configuration, * after merging of the defaults record (if any). It @@ -33,22 +119,94 @@ void dump_config(struct runctl *runp, struct query *querylist) { struct query *ctl; struct idlist *idp; - time_t now; - - /* now write the edited configuration back to the file */ - time(&now); - fprintf(stdout, "# fetchmail rc file generated at %s", ctime(&now)); - - if (runp->poll_interval) - fprintf(stdout, "set daemon %d\n", runp->poll_interval); - if (runp->use_syslog) - fprintf(stdout, "set syslog\n"); - if (runp->logfile) - fprintf(stdout, "set logfile %s\n", runp->logfile); - if (runp->idfile) - fprintf(stdout, "set idfile %s\n", runp->idfile); - if (runp->invisible) - fprintf(stdout, "set invisible\n"); + const char *features; + + indent_level = 0; + + /* + * These had better match the values fetchmailconf is expecting! + * (We don't want to import them from Tkinter because the user + * might not have it installed.) + */ + fputs("TRUE=1; FALSE=0\n\n", stdout); + + /* + * We need this in order to know whether `interface' and `monitor' + * are valid options or not. + */ +#if defined(linux) + fputs("os_type = 'linux'\n", stdout); +#elif defined(__FreeBSD__) + fputs("os_type = 'freebsd'\n", stdout); +#else + fputs("os_type = 'generic'\n", stdout); +#endif + + /* + * This should be approximately in sync with the -V option dumping + * in fetchmail.c. + */ + features = "feature_options = (" +#ifdef POP3_ENABLE + "'pop3'," +#endif /* POP3_ENABLE */ +#ifdef IMAP_ENABLE + "'imap'," +#endif /* IMAP_ENABLE */ +#ifdef GSSAPI + "'gssapi'," +#endif /* GSSAPI */ +#ifdef RPA_ENABLE + "'rpa'," +#endif /* RPA_ENABLE */ +#ifdef SDPS_ENABLE + "'sdps'," +#endif /* SDPS_ENABLE */ +#ifdef ETRN_ENABLE + "'etrn'," +#endif /* ETRN_ENABLE */ +#ifdef ODMR_ENABLE + "'odmr'," +#endif /* ODMR_ENABLE */ +#ifdef SSL_ENABLE + "'ssl'," +#endif /* SSL_ENABLE */ +#ifdef OPIE_ENABLE + "'opie'," +#endif /* OPIE_ENABLE */ +#ifdef HAVE_SOCKS + "'socks'," +#endif /* HAVE_SOCKS */ + ")\n"; + fputs(features, stdout); + + fputs("# Start of configuration initializer\n", stdout); + fputs("fetchmailrc = ", stdout); + indent('{'); + + numdump("poll_interval", runp->poll_interval); + stringdump("logfile", runp->logfile); + stringdump("idfile", runp->idfile); + stringdump("postmaster", runp->postmaster); + booldump("bouncemail", runp->bouncemail); + booldump("spambounce", runp->spambounce); + booldump("softbounce", runp->softbounce); + stringdump("properties", runp->properties); + booldump("invisible", runp->invisible); + booldump("showdots", runp->showdots); + booldump("syslog", runp->use_syslog); + + if (!querylist) + { + fputs(" 'servers': []\n", stdout); + goto alldone; + } + + indent(0); + fputs("# List of server entries begins here\n", stdout); + indent(0); + fputs("'servers': ", stdout); + indent('['); for (ctl = querylist; ctl; ctl = ctl->next) { @@ -57,171 +215,205 @@ void dump_config(struct runctl *runp, struct query *querylist) */ if (!ctl->server.lead_server) { - flag using_kpop = - (ctl->server.protocol == P_POP3 && - ctl->server.port == KPOP_PORT && - ctl->server.preauthenticate == A_KERBEROS_V4); + flag using_kpop; - if (strcmp(ctl->server.pollname, "defaults") == 0) - fputs("defaults ", stdout); - else - fprintf(stdout, "%s %s ", - ctl->server.skip ? "skip" : "poll", - visbuf(ctl->server.pollname)); - if (ctl->server.via) - fprintf(stdout, "via %s ", ctl->server.via); - if (ctl->server.protocol != P_AUTO) - fprintf(stdout, "with protocol %s ", - using_kpop ? "KPOP" : showproto(ctl->server.protocol)); - if (ctl->server.port) - fprintf(stdout, "port %d ", ctl->server.port); - if (ctl->server.timeout) - fprintf(stdout, "timeout %d ", ctl->server.timeout); - if (ctl->server.interval) - fprintf(stdout, "interval %d ", ctl->server.interval); - if (ctl->server.envelope == STRING_DISABLED) - fprintf(stdout, "no envelope "); - else if (ctl->server.envelope) - fprintf(stdout, "envelope \"%s\" ", visbuf(ctl->server.envelope)); - if (ctl->server.qvirtual) - fprintf(stdout, "qvirtual \"%s\" ", visbuf(ctl->server.qvirtual)); - if (ctl->server.preauthenticate == A_KERBEROS_V4) - fprintf(stdout, "auth kerberos_v4 "); -#define DUMPOPT(flag, str) \ - if (flag) \ - fprintf(stdout, "%s ", str); \ - else \ - fprintf(stdout, "no %s ", str); -#if defined(HAVE_GETHOSTBYNAME) && defined(HAVE_RES_SEARCH) - if (ctl->server.dns || ctl->server.uidl) -#else - if (ctl->server.uidl) -#endif /* HAVE_GETHOSTBYNAME && HAVE_RES_SEARCH */ - fputs("and options ", stdout); -#if defined(HAVE_GETHOSTBYNAME) && defined(HAVE_RES_SEARCH) - DUMPOPT(ctl->server.dns, "dns"); -#endif /* HAVE_GETHOSTBYNAME && HAVE_RES_SEARCH */ - DUMPOPT(ctl->server.uidl, "uidl"); - fputs("\n", stdout); - - /* AKA and loca-domain declarations */ - if (ctl->server.akalist || ctl->server.localdomains) + /* + * Every time we see a leading server entry after the first one, + * it implicitly ends the both (a) the list of user structures + * associated with the previous entry, and (b) that previous entry. + */ + if (ctl > querylist) { - fputc('\t', stdout); - if (ctl->server.akalist) - { - struct idlist *idp; - - fprintf(stdout, "aka"); - for (idp = ctl->server.akalist; idp; idp = idp->next) - fprintf(stdout, " %s", visbuf(idp->id)); - } - - if (ctl->server.akalist && ctl->server.localdomains) - putc(' ', stdout); - - if (ctl->server.localdomains) - { - struct idlist *idp; - - fprintf(stdout, "localdomains"); - for (idp = ctl->server.localdomains; idp; idp = idp->next) - fprintf(stdout, " %s", visbuf(idp->id)); - } + indent(']'); + indent('}'); + indent('\0'); + putc(',', stdout); putc('\n', stdout); } -#ifdef linux - if (ctl->server.monitor || ctl->server.interface) - { - putc('\t', stdout); - if (ctl->server.monitor) - fprintf(stdout, "monitor \"%s\" ", ctl->server.monitor); - if (ctl->server.interface) - fprintf(stdout, "interface \"%s\"", ctl->server.interface); - putc('\n', stdout); + indent(0); + fprintf(stdout,"# Entry for site `%s' begins:\n",ctl->server.pollname); + indent('{'); + + using_kpop = + (ctl->server.protocol == P_POP3 && + ctl->server.service && !strcmp(ctl->server.service, KPOP_PORT ) && + ctl->server.authenticate == A_KERBEROS_V5); + + stringdump("pollname", ctl->server.pollname); + booldump("active", !ctl->server.skip); + stringdump("via", ctl->server.via); + stringdump("protocol", + using_kpop ? "KPOP" : showproto(ctl->server.protocol)); + stringdump("service", ctl->server.service); + numdump("timeout", ctl->server.timeout); + numdump("interval", ctl->server.interval); + + if (ctl->server.envelope == STRING_DISABLED) + stringdump("envelope", NULL); + else if (ctl->server.envelope == NULL) + stringdump("envelope", "Received"); + else + stringdump("envelope", ctl->server.envelope); + numdump("envskip", ctl->server.envskip); + stringdump("qvirtual", ctl->server.qvirtual); + + switch (ctl->server.authenticate) { + case A_ANY: + stringdump("auth", "any"); break; + case A_PASSWORD: + stringdump("auth", "password"); break; + case A_OTP: + stringdump("auth", "otp"); break; + case A_NTLM: + stringdump("auth", "ntlm"); break; + case A_CRAM_MD5: + stringdump("auth", "cram-md5"); break; + case A_GSSAPI: + stringdump("auth", "gssapi"); break; + case A_KERBEROS_V5: + stringdump("auth", "kerberos_v5"); break; + case A_SSH: + stringdump("auth", "ssh"); break; + case A_MSN: + stringdump("auth", "msn"); break; + default: abort(); } -#endif /* linux */ - } - fputc('\t', stdout); - if (ctl->remotename || ctl->password || ctl->localnames) - { - if (ctl->remotename) - fprintf(stdout, "user \"%s\" ", visbuf(ctl->remotename)); - if (ctl->remotename && ctl->password) - fputs("with ", stdout); - if (ctl->password) - fprintf(stdout, "password \"%s\" ", visbuf(ctl->password)); - if (ctl->localnames) - { - fprintf(stdout, "is "); - for (idp = ctl->localnames; idp; idp = idp->next) - if (idp->val.id2) - fprintf(stdout, "\"%s\"=\"%s\" ", - visbuf(idp->id), visbuf(idp->val.id2)); - else - fprintf(stdout, "%s ", visbuf(idp->id)); - if (ctl->wildcard) - fputs("*", stdout); +#ifdef HAVE_RES_SEARCH + booldump("dns", ctl->server.dns); +#endif /* HAVE_RES_SEARCH */ + listdump("aka", ctl->server.akalist); + listdump("localdomains", ctl->server.localdomains); + +#ifdef CAN_MONITOR + stringdump("interface", ctl->server.interface); + stringdump("monitor", ctl->server.monitor); +#endif + + stringdump("plugin", ctl->server.plugin); + stringdump("plugout", ctl->server.plugout); + stringdump("principal", ctl->server.principal); + if (ctl->server.esmtp_name) + stringdump("esmtpname",ctl->server.esmtp_name); + if (ctl->server.esmtp_password) + stringdump("esmtppassword",ctl->server.esmtp_password); + booldump("tracepolls", ctl->server.tracepolls); + indent(0); + switch(ctl->server.badheader) { + /* this is a hack - we map this to a boolean option for + * fetchmailconf purposes */ + case BHREJECT: puts("'badheader': FALSE,"); break; + case BHACCEPT: puts("'badheader': TRUE,"); break; + } + + switch (ctl->server.retrieveerror) { + case RE_ABORT: stringdump("retrieveerror", "abort"); break; + case RE_CONTINUE: stringdump("retrieveerror", "continue"); break; + case RE_MARKSEEN: stringdump("retrieveerror", "markseen"); break; } + + indent(0); + fputs("'users': ", stdout); + indent('['); } - if (ctl->fetchall || ctl->keep || ctl->flush || ctl->rewrite - || ctl->stripcr || ctl->forcecr || ctl->pass8bits) - fputs("options ", stdout); - DUMPOPT(ctl->fetchall, "fetchall"); - DUMPOPT(ctl->keep, "keep"); - DUMPOPT(ctl->flush, "flush"); - DUMPOPT(ctl->rewrite, "rewrite"); - DUMPOPT(ctl->stripcr, "stripcr"); - DUMPOPT(ctl->forcecr, "forcecr"); - DUMPOPT(ctl->pass8bits, "pass8bits"); - DUMPOPT(ctl->dropstatus, "dropstatus"); - DUMPOPT(ctl->mimedecode, "mimedecode"); -#undef DUMPOPT - - if (ctl->mda) - fprintf(stdout, "mda \"%s\" ", visbuf(ctl->mda)); -#ifdef INET6 - if (ctl->netsec) - fprintf(stdout, "netsec \"%s\" ", visbuf(ctl->netsec)); -#endif /* INET6 */ - if (ctl->preconnect) - fprintf(stdout, "preconnect \"%s\" ", visbuf(ctl->preconnect)); - if (ctl->postconnect) - fprintf(stdout, "postconnect \"%s\" ", visbuf(ctl->postconnect)); - if (ctl->fetchlimit) - fprintf(stdout, "fetchlimit %d ", ctl->fetchlimit); - if (ctl->batchlimit) - fprintf(stdout, "batchlimit %d ", ctl->batchlimit); - - if (ctl->smtphunt) + indent('{'); + + stringdump("remote", ctl->remotename); + stringdump("password", ctl->password); + + indent('\0'); + fprintf(stdout, "'localnames':["); + for (idp = ctl->localnames; idp; idp = idp->next) { - struct idlist *idp; + char namebuf[USERNAMELEN + 1]; - fprintf(stdout, "smtphost "); - for (idp = ctl->smtphunt; idp; idp = idp->next) - fprintf(stdout, "%s ", visbuf(idp->id)); + strlcpy(namebuf, visbuf(idp->id), sizeof(namebuf)); + if (idp->val.id2) + fprintf(stdout, "(\"%s\", %s)", namebuf, visbuf(idp->val.id2)); + else + fprintf(stdout, "\"%s\"", namebuf); + if (idp->next) + fputs(", ", stdout); } + if (ctl->wildcard) + fputs(", '*'", stdout); + fputs("],\n", stdout); - if (ctl->smtpaddress) - fprintf(stdout, "smtpaddress \"%s\" ", visbuf(ctl->smtpaddress)); + booldump("fetchall", ctl->fetchall); + booldump("keep", ctl->keep); + booldump("flush", ctl->flush); + booldump("limitflush", ctl->limitflush); + booldump("rewrite", ctl->rewrite); + booldump("stripcr", ctl->stripcr); + booldump("forcecr", ctl->forcecr); + booldump("pass8bits", ctl->pass8bits); + booldump("dropstatus", ctl->dropstatus); + booldump("dropdelivered", ctl->dropdelivered); + booldump("mimedecode", ctl->mimedecode); + booldump("idle", ctl->idle); - if (ctl->antispam) - fprintf(stdout, "antispam %d ", ctl->antispam); + stringdump("mda", ctl->mda); + stringdump("bsmtp", ctl->bsmtp); + indent('\0'); + if (ctl->listener == LMTP_MODE) + fputs("'lmtp':TRUE,\n", stdout); + else + fputs("'lmtp':FALSE,\n", stdout); + + stringdump("preconnect", ctl->preconnect); + stringdump("postconnect", ctl->postconnect); + numdump("limit", ctl->limit); + numdump("warnings", ctl->warnings); + numdump("fetchlimit", ctl->fetchlimit); + numdump("fetchsizelimit", ctl->fetchsizelimit); + numdump("fastuidl", ctl->fastuidl); + numdump("batchlimit", ctl->batchlimit); +#ifdef SSL_ENABLE + booldump("ssl", ctl->use_ssl); + stringdump("sslkey", ctl->sslkey); + stringdump("sslcert", ctl->sslcert); + stringdump("sslproto", ctl->sslproto); + booldump("sslcertck", ctl->sslcertck); + stringdump("sslcertpath", ctl->sslcertpath); + stringdump("sslcommonname", ctl->sslcommonname); + stringdump("sslfingerprint", ctl->sslfingerprint); +#endif /* SSL_ENABLE */ + numdump("expunge", ctl->expunge); + stringdump("properties", ctl->properties); + listdump("smtphunt", ctl->smtphunt); + listdump("fetchdomains", ctl->domainlist); + stringdump("smtpaddress", ctl->smtpaddress); + stringdump("smtpname", ctl->smtpname); - if (ctl->mailboxes && ctl->mailboxes->id) + indent('\0'); + fprintf(stdout, "'antispam':'"); + for (idp = ctl->antispam; idp; idp = idp->next) { - struct idlist *idp; - - fprintf(stdout, "mailboxes "); - for (idp = ctl->mailboxes; idp; idp = idp->next) - fprintf(stdout, "%s ", visbuf(idp->id)); + fprintf(stdout, "%d", idp->val.status.num); + if (idp->next) + fputs(" ", stdout); } + fputs("',\n", stdout); + listdump("mailboxes", ctl->mailboxes); - putc('\n', stdout); + indent('}'); + indent('\0'); + fputc(',', stdout); } + + /* end last span of user entries and last server entry */ + indent(']'); + indent('}'); + + /* end array of servers */ + indent(']'); + + alldone: + /* end top-level dictionary */ + indent('}'); + fputs("# End of initializer\n", stdout); } /* conf.c ends here */