]> Pileus Git - ~andy/fetchmail/blobdiff - fetchmail.c
Add Esperanto-language translation.
[~andy/fetchmail] / fetchmail.c
index 8b8d8eb1d06f61527dee3615323f58ef56de6441..d720b04539172120dc902918a801dde91143f249 100644 (file)
@@ -6,18 +6,12 @@
 #include "config.h"
 
 #include <stdio.h>
-#if defined(STDC_HEADERS)
 #include <stdlib.h>
-#endif
-#if defined(HAVE_UNISTD_H)
 #include <unistd.h>
-#endif
 #include <fcntl.h>
 #include <string.h>
 #include <signal.h>
-#if defined(HAVE_SYSLOG)
 #include <syslog.h>
-#endif
 #include <pwd.h>
 #ifdef __FreeBSD__
 #include <grp.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifdef HAVE_SETRLIMIT
 #include <sys/resource.h>
-#endif /* HAVE_SETRLIMIT */
 
 #ifdef HAVE_SOCKS
 #include <socks.h> /* SOCKSinit() */
 #endif /* HAVE_SOCKS */
 
-#ifdef HAVE_LANGINFO_H
 #include <langinfo.h>
-#endif
 
 #include "fetchmail.h"
 #include "socket.h"
 #include "tunable.h"
 #include "smtp.h"
 #include "netrc.h"
-#include "i18n.h"
+#include "gettext.h"
 #include "lock.h"
 
 /* need these (and sys/types.h) for res_init() */
@@ -84,8 +74,8 @@ static int activecount;               /* count number of active entries */
 static struct runctl cmd_run;  /* global options set from command line */
 static time_t parsetime;       /* time of last parse */
 
-static RETSIGTYPE terminate_run(int);
-static RETSIGTYPE terminate_poll(int);
+static void terminate_run(int);
+static void terminate_poll(int);
 
 #ifdef HAVE_LIBPWMD
 static pwm_t *pwm;             /* the handle */
@@ -114,8 +104,8 @@ static void dropprivs(void)
 }
 #endif
 
-#if defined(HAVE_SETLOCALE) && defined(ENABLE_NLS) && defined(HAVE_STRFTIME)
 #include <locale.h>
+#if defined(ENABLE_NLS)
 /** returns timestamp in current locale,
  * and resets LC_TIME locale to POSIX. */
 static char *timestamp (void)
@@ -133,7 +123,7 @@ static char *timestamp (void)
 #define timestamp rfc822timestamp
 #endif
 
-static RETSIGTYPE donothing(int sig) 
+static void donothing(int sig) 
 {
     set_signal_handler(sig, donothing);
     lastsig = sig;
@@ -143,12 +133,16 @@ static void printcopyright(FILE *fp) {
        fprintf(fp, GT_("Copyright (C) 2002, 2003 Eric S. Raymond\n"
                   "Copyright (C) 2004 Matthias Andree, Eric S. Raymond,\n"
                   "                   Robert M. Funk, Graham Wilson\n"
-                  "Copyright (C) 2005 - 2006, 2010 Sunil Shetye\n"
-                  "Copyright (C) 2005 - 2010 Matthias Andree\n"
+                  "Copyright (C) 2005 - 2012 Sunil Shetye\n"
+                  "Copyright (C) 2005 - 2013 Matthias Andree\n"
                   ));
        fprintf(fp, GT_("Fetchmail comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
                   "are welcome to redistribute it under certain conditions. For details,\n"
                   "please see the file COPYING in the source or documentation directory.\n"));
+#ifdef SSL_ENABLE
+       /* Do not translate this */
+       fprintf(fp, "This product includes software developed by the OpenSSL Project\nfor use in the OpenSSL Toolkit. (http://www.openssl.org/)\n");
+#endif
 }
 
 const char *iana_charset;
@@ -428,11 +422,12 @@ static int get_pwmd_details(const char *pwmd_account, int protocol,
     return 0;
 }
 #endif
-
 int main(int argc, char **argv)
 {
     int bkgd = FALSE;
     int implicitmode = FALSE;
+    flag safewithbg = FALSE; /** if parsed options are compatible with a
+                             fetchmail copy running in the background */
     struct query *ctl;
     netrc_entry *netrc_list;
     char *netrc_file, *tmpbuf;
@@ -476,7 +471,6 @@ int main(int argc, char **argv)
 
 #define IDFILE_NAME    ".fetchids"
     run.idfile = prependdir (IDFILE_NAME, fmhome);
-  
     outlevel = O_NORMAL;
 
     /*
@@ -500,7 +494,7 @@ int main(int argc, char **argv)
     {
        int i;
 
-       i = parsecmdline(argc, argv, &cmd_run, &cmd_opts);
+       i = parsecmdline(argc, argv, &cmd_run, &cmd_opts, &safewithbg);
        if (i < 0)
            exit(PS_SYNTAX);
 
@@ -511,9 +505,6 @@ int main(int argc, char **argv)
     if (versioninfo)
     {
        const char *features = 
-#ifdef POP2_ENABLE
-       "+POP2"
-#endif /* POP2_ENABLE */
 #ifndef POP3_ENABLE
        "-POP3"
 #endif /* POP3_ENABLE */
@@ -553,15 +544,9 @@ int main(int argc, char **argv)
 #ifdef ENABLE_NLS
        "+NLS"
 #endif /* ENABLE_NLS */
-#ifdef KERBEROS_V4
-       "+KRB4"
-#endif /* KERBEROS_V4 */
 #ifdef KERBEROS_V5
        "+KRB5"
 #endif /* KERBEROS_V5 */
-#ifndef HAVE_RES_SEARCH
-       "-DNS"
-#endif
 #ifdef HAVE_LIBPWMD
        "+PWMD"
 #endif /* HAVE_LIBPWMD */
@@ -588,26 +573,50 @@ int main(int argc, char **argv)
     if (!quitonly)
        implicitmode = load_params(argc, argv, optind);
 
-    /* precedence: logfile (if effective) overrides syslog. */
-    if (run.logfile && run.poll_interval && !nodetach) {
-       run.use_syslog = 0;
+    if (run.logfile) {
+       /* nodetach -> turn off logfile option */
+       if (nodetach) {
+           if (outlevel >= O_NORMAL) { fprintf(stderr, GT_("The nodetach option is in effect, ignoring logfile option.\n")); }
+           xfree(run.logfile);
+       }
+
+#if 0
+       /* not in daemon mode -> turn off logfile option */
+       if (0 == run.poll_interval) {
+           if (outlevel >= O_NORMAL) { fprintf(stderr, GT_("Not running in daemon mode, ignoring logfile option.\n")); }
+           xfree(run.logfile);
+       }
+#endif
+
+       /* log file not writable -> turn off logfile option */
+       if (run.logfile && 0 != access(run.logfile, F_OK)) {
+           if (outlevel >= O_NORMAL) { fprintf(stderr, GT_("Logfile \"%s\" does not exist, ignoring logfile option.\n"), run.logfile); }
+           xfree(run.logfile);
+       }
+
+       /* log file not writable -> turn off logfile option */
+       if (run.logfile && 0 != access(run.logfile, W_OK)) {
+           fprintf(stderr, GT_("Logfile \"%s\" is not writable, aborting.\n"), run.logfile);
+           xfree(run.logfile);
+           exit(PS_UNDEFINED);
+       }
     }
 
-#if defined(HAVE_SYSLOG)
     /* logging should be set up early in case we were restarted from exec */
     if (run.use_syslog)
     {
-#if defined(LOG_MAIL)
        openlog(program_name, LOG_PID, LOG_MAIL);
-#else
-       /* Assume BSD4.2 openlog with two arguments */
-       openlog(program_name, LOG_PID);
-#endif
-       report_init(-1);
+       /* precedence: logfile (if effective) overrides syslog. */
+       if (run.logfile) {
+           syslog(LOG_ERR, GT_("syslog and logfile options are both set, ignoring syslog, and logging to %s"), run.logfile);
+           run.use_syslog = 0;
+           report_init((run.poll_interval == 0 || nodetach) && !run.logfile); /* when changing this, change copy below, too */
+       } else {
+           report_init(-1);
+       }
     }
     else
-#endif
-       report_init((run.poll_interval == 0 || nodetach) && !run.logfile);
+       report_init((run.poll_interval == 0 || nodetach) && !run.logfile); /* when changing this, change copy above, too */
 
 #ifdef POP3_ENABLE
     /* initialize UID handling */
@@ -624,7 +633,6 @@ int main(int argc, char **argv)
     /* construct the lockfile */
     fm_lock_setup(&run);
 
-#ifdef HAVE_SETRLIMIT
     /*
      * Before getting passwords, disable core dumps unless -v -d0 mode is on.
      * Core dumps could otherwise contain passwords to be scavenged by a
@@ -637,7 +645,6 @@ int main(int argc, char **argv)
        corelimit.rlim_max = 0;
        setrlimit(RLIMIT_CORE, &corelimit);
     }
-#endif /* HAVE_SETRLIMIT */
 
 #define        NETRC_FILE      ".netrc"
     /* parse the ~/.netrc file (if present) for future password lookups. */
@@ -783,17 +790,23 @@ int main(int argc, char **argv)
        else if (getpid() == pid)
            /* this test enables re-execing on a changed rcfile */
            fm_lock_assert();
-       else if (argc > 1)
+       else if (argc > 1 && !safewithbg)
        {
            fprintf(stderr,
                    GT_("fetchmail: can't accept options while a background fetchmail is running.\n"));
+           {
+               int i;
+               fprintf(stderr, "argc = %d, arg list:\n", argc);
+               for (i = 1; i < argc; i++) fprintf(stderr, "arg %d = \"%s\"\n", i, argv[i]);
+           }
            return(PS_EXCLUDE);
        }
        else if (kill(pid, SIGUSR1) == 0)
        {
-           fprintf(stderr,
-                   GT_("fetchmail: background fetchmail at %ld awakened.\n"),
-                   (long)pid);
+           if (outlevel > O_SILENT)
+               fprintf(stderr,
+                       GT_("fetchmail: background fetchmail at %ld awakened.\n"),
+                       (long)pid);
            return(0);
        }
        else
@@ -882,14 +895,12 @@ int main(int argc, char **argv)
     else
     {
        /* not in daemon mode */
-       if (run.logfile && !nodetach && access(run.logfile, F_OK) == 0)
-       {
+       if (run.logfile)
+       {
            if (!freopen(run.logfile, "a", stdout))
                    report(stderr, GT_("could not open %s to append logs to\n"), run.logfile);
            if (!freopen(run.logfile, "a", stderr))
                    report(stdout, GT_("could not open %s to append logs to\n"), run.logfile);
-           if (run.use_syslog)
-               report(stdout, GT_("fetchmail: Warning: syslog and logfile are set. Check both for logs!\n"));
        }
     }
 
@@ -1126,7 +1137,6 @@ int main(int argc, char **argv)
            pwm = NULL;
        }
 #endif
-
        /* close connections cleanly */
        terminate_poll(0);
 
@@ -1250,7 +1260,6 @@ static void optmerge(struct query *h2, struct query *h1, int force)
     FLAG_MERGE(server.skip);
     FLAG_MERGE(server.dns);
     FLAG_MERGE(server.checkalias);
-    FLAG_MERGE(server.uidl);
     FLAG_MERGE(server.principal);
 
 #ifdef CAN_MONITOR
@@ -1263,6 +1272,7 @@ static void optmerge(struct query *h2, struct query *h1, int force)
     FLAG_MERGE(server.plugout);
     FLAG_MERGE(server.tracepolls);
     FLAG_MERGE(server.badheader);
+    FLAG_MERGE(server.retrieveerror);
 
     FLAG_MERGE(wildcard);
     FLAG_MERGE(remotename);
@@ -1422,7 +1432,6 @@ static int load_params(int argc, char **argv, int optind)
                        fprintf(stderr,GT_("Warning: multiple mentions of host %s in config file\n"),argv[optind]);
                    ctl->active = TRUE;
                    predeclared = TRUE;
-
 #ifdef HAVE_LIBPWMD
                    if (ctl->pwmd_file) {
                        /*
@@ -1453,7 +1462,6 @@ static int load_params(int argc, char **argv, int optind)
                 * call later on.
                 */
                ctl = hostalloc((struct query *)NULL);
-
 #ifdef HAVE_LIBPWMD
                if (cmd_opts.pwmd_file) {
                    /*
@@ -1476,8 +1484,8 @@ static int load_params(int argc, char **argv, int optind)
                    ctl->server.via =
                        ctl->server.pollname = xstrdup(argv[optind]);
 #else
-               ctl->server.via =
-                   ctl->server.pollname = xstrdup(argv[optind]);
+               ctl->server.via =
+                   ctl->server.pollname = xstrdup(argv[optind]);
 #endif
                ctl->active = TRUE;
                ctl->server.lead_server = (struct hostdata *)NULL;
@@ -1554,7 +1562,6 @@ static int load_params(int argc, char **argv, int optind)
     for (ctl = querylist; ctl; ctl = ctl->next)
        if (ctl->active && 
                (ctl->server.protocol==P_ETRN || ctl->server.protocol==P_ODMR
-                || ctl->server.authenticate == A_KERBEROS_V4
                 || ctl->server.authenticate == A_KERBEROS_V5))
        {
            fetchmailhost = host_fqdn(1);
@@ -1614,7 +1621,6 @@ static int load_params(int argc, char **argv, int optind)
            DEFAULT(ctl->mimedecode, FALSE);
            DEFAULT(ctl->idle, FALSE);
            DEFAULT(ctl->server.dns, TRUE);
-           DEFAULT(ctl->server.uidl, FALSE);
            DEFAULT(ctl->use_ssl, FALSE);
            DEFAULT(ctl->sslcertck, FALSE);
            DEFAULT(ctl->server.checkalias, FALSE);
@@ -1630,12 +1636,6 @@ static int load_params(int argc, char **argv, int optind)
            }
 #endif /* SSL_ENABLE */
 #undef DEFAULT
-#ifndef KERBEROS_V4
-           if (ctl->server.authenticate == A_KERBEROS_V4) {
-               report(stderr, GT_("KERBEROS v4 support is configured, but not compiled in.\n"));
-               exit(PS_SYNTAX);
-           }
-#endif
 #ifndef KERBEROS_V5
            if (ctl->server.authenticate == A_KERBEROS_V5) {
                report(stderr, GT_("KERBEROS v5 support is configured, but not compiled in.\n"));
@@ -1669,14 +1669,6 @@ static int load_params(int argc, char **argv, int optind)
            if (!ctl->localnames)       /* for local delivery via SMTP */
                save_str_pair(&ctl->localnames, user, NULL);
 
-#ifndef HAVE_RES_SEARCH
-           /* can't handle multidrop mailboxes unless we can do DNS lookups */
-           if (MULTIDROP(ctl) && ctl->server.dns)
-           {
-               ctl->server.dns = FALSE;
-               report(stderr, GT_("fetchmail: warning: no DNS available to check multidrop fetches from %s\n"), ctl->server.pollname);
-           }
-#endif /* !HAVE_RES_SEARCH */
 
            /*
             * can't handle multidrop mailboxes without "envelope"
@@ -1707,13 +1699,6 @@ static int load_params(int argc, char **argv, int optind)
                                   ctl->server.pollname);
                    exit(PS_SYNTAX);
                }
-               if (ctl->server.protocol == P_RPOP && port >= 1024)
-               {
-                   (void) fprintf(stderr,
-                                  GT_("fetchmail: %s configuration invalid, RPOP requires a privileged port\n"),
-                                  ctl->server.pollname);
-                   exit(PS_SYNTAX);
-               }
            }
            if (ctl->listener == LMTP_MODE)
            {
@@ -1762,7 +1747,7 @@ static int load_params(int argc, char **argv, int optind)
     return(implicitmode);
 }
 
-static RETSIGTYPE terminate_poll(int sig)
+static void terminate_poll(int sig)
 /* to be executed at the end of a poll cycle */
 {
 
@@ -1780,7 +1765,7 @@ static RETSIGTYPE terminate_poll(int sig)
 #endif /* POP3_ENABLE */
 }
 
-static RETSIGTYPE terminate_run(int sig)
+static void terminate_run(int sig)
 /* to be executed on normal or signal-induced termination */
 {
     struct query       *ctl;
@@ -1802,9 +1787,6 @@ static RETSIGTYPE terminate_run(int sig)
        if (ctl->password)
          memset(ctl->password, '\0', strlen(ctl->password));
 
-#if !defined(HAVE_ATEXIT)
-    fm_lock_release();
-#endif
 
     if (activecount == 0)
        exit(PS_NOMAIL);
@@ -1823,9 +1805,6 @@ static const int autoprobe[] =
 #ifdef POP3_ENABLE
     P_POP3,
 #endif /* POP3_ENABLE */
-#ifdef POP2_ENABLE
-    P_POP2
-#endif /* POP2_ENABLE */
 };
 
 static int query_host(struct query *ctl)
@@ -1861,17 +1840,7 @@ static int query_host(struct query *ctl)
        }
        ctl->server.protocol = P_AUTO;
        break;
-    case P_POP2:
-#ifdef POP2_ENABLE
-       st = doPOP2(ctl);
-#else
-       report(stderr, GT_("POP2 support is not configured.\n"));
-       st = PS_PROTOCOL;
-#endif /* POP2_ENABLE */
-       break;
     case P_POP3:
-    case P_APOP:
-    case P_RPOP:
 #ifdef POP3_ENABLE
        do {
            st = doPOP3(ctl);
@@ -1928,6 +1897,13 @@ static int query_host(struct query *ctl)
     return(st);
 }
 
+static int print_id_of(struct uid_db_record *rec, void *unused)
+{
+    (void)unused;
+
+    printf("\t%s\n", rec->id);
+    return 0;
+}
 static void dump_params (struct runctl *runp,
                         struct query *querylist, flag implicit)
 /* display query parameters in English */
@@ -1940,10 +1916,8 @@ static void dump_params (struct runctl *runp,
        printf(GT_("Logfile is %s\n"), runp->logfile);
     if (strcmp(runp->idfile, IDFILE_NAME))
        printf(GT_("Idfile is %s\n"), runp->idfile);
-#if defined(HAVE_SYSLOG)
     if (runp->use_syslog)
        printf(GT_("Progress messages will be logged via syslog\n"));
-#endif
     if (runp->invisible)
        printf(GT_("Fetchmail will masquerade and will not generate Received\n"));
     if (runp->showdots)
@@ -1989,22 +1963,14 @@ static void dump_params (struct runctl *runp,
                printf(GT_("  Password will be prompted for.\n"));
            else if (outlevel >= O_VERBOSE)
            {
-               if (ctl->server.protocol == P_APOP)
-                   printf(GT_("  APOP secret = \"%s\".\n"),
-                          visbuf(ctl->password));
-               else if (ctl->server.protocol == P_RPOP)
-                   printf(GT_("  RPOP id = \"%s\".\n"),
-                          visbuf(ctl->password));
-               else
-                   printf(GT_("  Password = \"%s\".\n"),
-                                                       visbuf(ctl->password));
+               printf(GT_("  Password = \"%s\".\n"),
+                                   visbuf(ctl->password));
            }
        }
 
        if (ctl->server.protocol == P_POP3 
            && ctl->server.service && !strcmp(ctl->server.service, KPOP_PORT)
-           && (ctl->server.authenticate == A_KERBEROS_V4 ||
-               ctl->server.authenticate == A_KERBEROS_V5))
+           && (ctl->server.authenticate == A_KERBEROS_V5))
            printf(GT_("  Protocol is KPOP with Kerberos %s authentication"),
                   ctl->server.authenticate == A_KERBEROS_V5 ? "V" : "IV");
        else
@@ -2013,8 +1979,6 @@ static void dump_params (struct runctl *runp,
            printf(GT_(" (using service %s)"), ctl->server.service);
        else if (outlevel >= O_VERBOSE)
            printf(GT_(" (using default port)"));
-       if (ctl->server.uidl && MAILBOX_PROTOCOL(ctl))
-           printf(GT_(" (forcing UIDL use)"));
        putchar('.');
        putchar('\n');
        switch (ctl->server.authenticate)
@@ -2035,20 +1999,22 @@ static void dump_params (struct runctl *runp,
            printf(GT_("  OTP authentication will be forced.\n"));
            break;
        case A_CRAM_MD5:
-           printf(GT_("  CRAM-Md5 authentication will be forced.\n"));
+           printf(GT_("  CRAM-MD5 authentication will be forced.\n"));
            break;
        case A_GSSAPI:
            printf(GT_("  GSSAPI authentication will be forced.\n"));
            break;
-       case A_KERBEROS_V4:
-           printf(GT_("  Kerberos V4 authentication will be forced.\n"));
-           break;
        case A_KERBEROS_V5:
            printf(GT_("  Kerberos V5 authentication will be forced.\n"));
            break;
        case A_SSH:
            printf(GT_("  End-to-end encryption assumed.\n"));
            break;
+       case A_APOP:
+           printf(GT_("  APOP authentication will be forced.\n"));
+           break;
+       default:
+           abort();
        }
        if (ctl->server.principal != (char *) NULL)
            printf(GT_("  Mail service principal is: %s\n"), ctl->server.principal);
@@ -2327,22 +2293,17 @@ static void dump_params (struct runctl *runp,
        else if (outlevel >= O_VERBOSE)
            printf(GT_("  No plugout command specified.\n"));
 
-       if (ctl->server.protocol > P_POP2 && MAILBOX_PROTOCOL(ctl))
+       if (MAILBOX_PROTOCOL(ctl))
        {
-           if (!ctl->oldsaved)
+           int count;
+
+           if (!(count = uid_db_n_records(&ctl->oldsaved)))
                printf(GT_("  No UIDs saved from this host.\n"));
            else
            {
-               struct idlist *idp;
-               int count = 0;
-
-               for (idp = ctl->oldsaved; idp; idp = idp->next)
-                   ++count;
 
                printf(GT_("  %d UIDs saved.\n"), count);
-               if (outlevel >= O_VERBOSE)
-                   for (idp = ctl->oldsaved; idp; idp = idp->next)
-                       printf("\t%s\n", idp->id);
+               traverse_uid_db(&ctl->oldsaved, print_id_of, NULL);
            }
        }
 
@@ -2361,6 +2322,19 @@ static void dump_params (struct runctl *runp,
                break;
        }
 
+       switch (ctl->server.retrieveerror) {
+           case RE_ABORT:
+               if (outlevel >= O_VERBOSE)
+                   printf(GT_("  Messages with fetch body errors will cause the session to abort.\n"));
+               break;
+           case RE_CONTINUE:
+               printf(GT_("  Messages with fetch body errors will be skipped, the session will continue.\n"));
+               break;
+           case RE_MARKSEEN:
+               printf(GT_("  Messages with fetch body errors will be marked seen, the session will continue.\n"));
+               break;
+       }
+
        if (ctl->properties)
            printf(GT_("  Pass-through properties \"%s\".\n"),
                   visbuf(ctl->properties));