]> Pileus Git - ~andy/fetchmail/blobdiff - options.c
Comment fix.
[~andy/fetchmail] / options.c
index f8b2c0c252d2a80a60d6a8f5dd677891e041d75f..546442370acc725c46860ff0714953271fd91642 100644 (file)
--- a/options.c
+++ b/options.c
-/* Copyright 1993-95 by Carl Harris, Jr. Copyright 1996 by Eric S. Raymond
- * All rights reserved.
+/*
+ * options.c -- command-line option processing
+ *
  * For license terms, see the file COPYING in this directory.
  */
 
-/***********************************************************************
-  module:       options.c
-  project:      fetchmail
-  programmer:   Carl Harris, ceharris@mal.com
-  description: command-line option processing
-
- ***********************************************************************/
-
 #include <config.h>
-#include <stdio.h>
 
+#include <stdio.h>
 #include <pwd.h>
+#include <string.h>
+#if defined(STDC_HEADERS)
+#include  <stdlib.h>
+#endif
+
 #include "getopt.h"
 #include "fetchmail.h"
 
-#define LA_VERSION     1 
-#define LA_ALL          2
-#define LA_KILL                3
-#define        LA_KEEP         4 
+#define LA_HELP                1
+#define LA_VERSION     2 
+#define LA_CHECK       3
+#define LA_SILENT      4 
 #define LA_VERBOSE     5 
-#define LA_SILENT      6 
-#define LA_STDOUT      7
-#define LA_FLUSH        8
-#define LA_PROTOCOL    9
-#define LA_DAEMON      10
+#define LA_DAEMON      6
+#define LA_NODETACH    7
+#define LA_QUIT                8
+#define LA_LOGFILE     9
+#define LA_SYSLOG      10
 #define LA_RCFILE      11
-#define LA_USERNAME    12
-#define LA_REMOTEFILE  13
+#define LA_IDFILE      12
+#define LA_PROTOCOL    13
 #define LA_PORT                14
-#define LA_SMTPHOST    15
-#define LA_LOGFILE     16
-#define LA_QUIT                17
-#define LA_NOREWRITE   18
-#define LA_YYDEBUG     19
-
-static char *shortoptions = "23PVaKkvS:sFd:f:u:r:L:qN";
+#define LA_AUTHENTICATE        15
+#define LA_TIMEOUT     16
+#define LA_ENVELOPE    17
+#define LA_USERNAME    18
+#define LA_ALL          19
+#define LA_KILL                20
+#define        LA_KEEP         21
+#define LA_FLUSH        22
+#define LA_NOREWRITE   23
+#define LA_LIMIT       24
+#define LA_REMOTEFILE  25
+#define LA_SMTPHOST    26
+#define LA_BATCHLIMIT  27
+#define LA_FETCHLIMIT  28
+#define LA_MDA         29
+#define LA_INTERFACE    30
+#define LA_MONITOR      31
+#define LA_YYDEBUG     32
+
+static char *shortoptions = "?Vcsvd:NqL:f:i:p:P:A:t:E:u:akKFnl:r:S:b:B:m:I:M:y";
 static struct option longoptions[] = {
-  {"version",   no_argument,       (int *) 0, LA_VERSION    },
-  {"all",      no_argument,       (int *) 0, LA_ALL        },
-  {"kill",     no_argument,       (int *) 0, LA_KILL       },
-  {"keep",      no_argument,       (int *) 0, LA_KEEP       },
-  {"verbose",   no_argument,       (int *) 0, LA_VERBOSE    },
-  {"silent",    no_argument,       (int *) 0, LA_SILENT     },
-  {"flush",    no_argument,       (int *) 0, LA_FLUSH      },
-  {"protocol", required_argument, (int *) 0, LA_PROTOCOL   },
-  {"proto",    required_argument, (int *) 0, LA_PROTOCOL   },
-  {"daemon",   required_argument, (int *) 0, LA_DAEMON     },
-  {"fetchmailrc",required_argument,(int *) 0, LA_RCFILE     },
-  {"user",     required_argument, (int *) 0, LA_USERNAME   },
-  {"username",  required_argument, (int *) 0, LA_USERNAME   },
-  {"remote",    required_argument, (int *) 0, LA_REMOTEFILE },
-  {"port",     required_argument, (int *) 0, LA_PORT       },
-  {"smtphost", required_argument, (int *) 0, LA_SMTPHOST   },
-  {"logfile",  required_argument, (int *) 0, LA_LOGFILE    },
-  {"quit",     no_argument,       (int *) 0, LA_QUIT       },
-  {"norewrite",        no_argument,       (int *) 0, LA_NOREWRITE  },
-  {"yydebug",  no_argument,       (int *) 0, LA_YYDEBUG    },
-  {(char *) 0,  no_argument,       (int *) 0, 0             }
-};
-
-
-/*********************************************************************
-  function:      parsecmdline
-  description:   parse/validate the command line options.
-  arguments:
-    argc         argument count.
-    argv         argument strings.
-    queryctl     pointer to a struct hostrec to receive the parsed 
-                 options.
-
-  return value:  if positive, argv index of last parsed option + 1
-                (presumes one or more server names follows).
-                if zero, the command line switches are such that
-                no server names are required (e.g. --version).
-                if negative, the command line is has one or more
-                syntax errors.
-  calls:         none.  
-  globals:       writes outlevel, versioninfo, yydebug, logfile, 
-                poll_interval, quitmode, rcfile, idfile.  
- *********************************************************************/
-
-int parsecmdline (argc,argv,queryctl)
-int argc;
-char **argv;
-struct hostrec *queryctl;
-{
-  int c,i;
-  int fflag = 0;     /* TRUE when -o or -c has been specified */
-  int errflag = 0;   /* TRUE when a syntax error is detected */
-  int option_index;
-  int got_kill = 0;  /* TRUE when --kill is specified */
-
-  extern int optind, opterr;     /* defined in getopt(2) */
-  extern char *optarg;          /* defined in getopt(2) */
+  {"help",     no_argument,       (int *) 0, LA_HELP        },
+  {"version",   no_argument,       (int *) 0, LA_VERSION     },
+  {"check",    no_argument,       (int *) 0, LA_CHECK       },
+  {"silent",    no_argument,       (int *) 0, LA_SILENT      },
+  {"verbose",   no_argument,       (int *) 0, LA_VERBOSE     },
+  {"daemon",   required_argument, (int *) 0, LA_DAEMON      },
+  {"nodetach", no_argument,       (int *) 0, LA_NODETACH    },
+  {"quit",     no_argument,       (int *) 0, LA_QUIT        },
+  {"logfile",  required_argument, (int *) 0, LA_LOGFILE     },
+  {"syslog",   no_argument,       (int *) 0, LA_SYSLOG      },
+  {"fetchmailrc",required_argument,(int *) 0, LA_RCFILE      },
+  {"idfile",   required_argument, (int *) 0, LA_IDFILE      },
+#ifdef linux
+  {"interface",        required_argument, (int *) 0, LA_INTERFACE   },
+  {"monitor",  required_argument, (int *) 0, LA_MONITOR     },
+#endif
 
-  memset(queryctl, '\0', sizeof(struct hostrec));    /* start clean */
+  {"protocol", required_argument, (int *) 0, LA_PROTOCOL    },
+  {"proto",    required_argument, (int *) 0, LA_PROTOCOL    },
+  {"port",     required_argument, (int *) 0, LA_PORT        },
+  {"auth",     required_argument, (int *) 0, LA_AUTHENTICATE},
+  {"timeout",  required_argument, (int *) 0, LA_TIMEOUT     },
+  {"envelope", required_argument, (int *) 0, LA_ENVELOPE    },
 
-  while (!errflag && 
-         (c = getopt_long(argc,argv,shortoptions,
-                          longoptions,&option_index)) != -1) {
+  {"user",     required_argument, (int *) 0, LA_USERNAME    },
+  {"username",  required_argument, (int *) 0, LA_USERNAME    },
 
-    switch (c) {
-      case '2':
-        queryctl->protocol = P_POP2;
-        break;
-      case '3':
-        queryctl->protocol = P_POP3;
-        break;
-      case 'V':
-      case LA_VERSION:
-        versioninfo = !0;
-        break;
-      case 'a':
-      case LA_ALL:
-        queryctl->fetchall = !0;
-        break;
-      case 'K':
-      case LA_KILL:
-        queryctl->keep = 0;
-        got_kill = 1;
-        break;
-      case 'k':
-      case LA_KEEP:
-        queryctl->keep = !0;
-        got_kill = 0;
-        break;
-      case 'v':
-      case LA_VERBOSE:
-        outlevel = O_VERBOSE;
-        break;
-      case 's':
-      case LA_SILENT:
-        outlevel = O_SILENT;
-        break;
-      case 'F':
-      case LA_FLUSH:
-        queryctl->flush = !0;
-        break;
-      case 'p':
-      case LA_PROTOCOL:
-        /* XXX -- should probably use a table lookup here */
-        if (strcasecmp(optarg,"pop2") == 0)
-          queryctl->protocol = P_POP2;
-        else if (strcasecmp(optarg,"pop3") == 0)
-          queryctl->protocol = P_POP3;
-        else if (strcasecmp(optarg,"imap") == 0)
-          queryctl->protocol = P_IMAP;
-        else if (strcasecmp(optarg,"apop") == 0)
-          queryctl->protocol = P_APOP;
-        else if (strcasecmp(optarg,"rpop") == 0)
-          queryctl->protocol = P_RPOP;
-        else {
-          fprintf(stderr,"Invalid protocol '%s'\n specified.\n", optarg);
-          errflag++;
-        }
-        break;
-      case 'd':
-      case LA_DAEMON:
-       poll_interval = atoi(optarg);
-        break;
-      case 'f':
-      case LA_RCFILE:
-        rcfile = (char *) xmalloc(strlen(optarg)+1);
-        strcpy(rcfile,optarg);
-        break;
-      case 'u':
-      case LA_USERNAME:
-        strncpy(queryctl->remotename,optarg,sizeof(queryctl->remotename)-1);
-        break;
-      case 'r':
-      case LA_REMOTEFILE:
-        strncpy(queryctl->remotefolder,optarg,sizeof(queryctl->remotefolder)-1);
-        break;
-      case 'P':
-      case LA_PORT:
-       queryctl->port = atoi(optarg);
-       break;
-      case 'S':
-      case LA_SMTPHOST:
-        if (fflag) 
-          errflag++;
-        else {
-          fflag++;
-          strncpy(queryctl->smtphost,optarg,sizeof(queryctl->smtphost)-1);
-        }
-       break;
-      case 'L':
-      case LA_LOGFILE:
-        logfile = optarg;
-        break;
-      case 'q':
-      case LA_QUIT:
-        quitmode = 1;
-        break;
-      case 'N':
-      case LA_NOREWRITE:
-       queryctl->norewrite = 1;
-       break;
-      case LA_YYDEBUG:
-       yydebug = 1;
-        break;
-      default:
-        errflag++;
-    }
-  }
+  {"all",      no_argument,       (int *) 0, LA_ALL         },
+  {"kill",     no_argument,       (int *) 0, LA_KILL        },
+  {"keep",      no_argument,       (int *) 0, LA_KEEP        },
+  {"flush",    no_argument,       (int *) 0, LA_FLUSH       },
+  {"norewrite",        no_argument,       (int *) 0, LA_NOREWRITE   },
+  {"limit",    required_argument, (int *) 0, LA_LIMIT       },
 
-  if (errflag) {
-    /* squawk if syntax errors were detected */
-    fputs("usage:  fetchmail [options] [server ...]\n", stderr);
-    fputs("  options\n",stderr);
-    fputs("  -2                use POP2 protocol\n", stderr);
-    fputs("  -3                use POP3 protocol\n", stderr);
-    fputs("  -p, --protocol    specify pop2, pop3, imap, apop\n", stderr);
-    fputs("  -V, --version     display version info\n", stderr);
-    fputs("  -a, --all         retrieve old and new messages\n", stderr);
-    fputs("  -F, --flush       delete old messages from server\n", stderr);
-    fputs("  -K, --kill        delete new messages after retrieval\n", stderr);
-    fputs("  -k, --keep        save new messages after retrieval\n", stderr);
-    fputs("  -S, --smtphost    set SMTP forwarding host\n", stderr);
-    fputs("  -q, --quit        kill daemon process\n", stderr);
-    fputs("  -s, --silent      work silently\n", stderr);
-    fputs("  -v, --verbose     work noisily (diagnostic output)\n", stderr);
-    fputs("  -d, --daemon      run as a daemon once per n seconds\n", stderr);
-    fputs("  -f, --fetchmailrc specify alternate run control file\n", stderr);
-    fputs("  -i, --idfile      specify alternate ID database\n", stderr);
-    fputs("  -u, --username    specify server user ID\n", stderr);
-    fputs("  -r, --remote      specify remote folder name\n", stderr);
-    fputs("  -L, --logfile     specify logfile name\n", stderr);
-    return(-1);
-  }
+  {"remote",    required_argument, (int *) 0, LA_REMOTEFILE  },
+  {"smtphost", required_argument, (int *) 0, LA_SMTPHOST    },
+  {"batchlimit",required_argument, (int *) 0, LA_BATCHLIMIT  },
+  {"fetchlimit",required_argument, (int *) 0, LA_FETCHLIMIT  },
+  {"mda",      required_argument, (int *) 0, LA_MDA         },
 
-  return(optind);
-}
-         
+  {"interface", required_argument, (int *) 0, LA_INTERFACE   },
+  {"monitor",   required_argument, (int *) 0, LA_MONITOR     },
 
-/*********************************************************************
-  function:      setdefaults
-  description:   set reasonable default values for unspecified options.
-  arguments:     
-    options      option values parsed from the command-line; unspeci-
-                 fied options must be filled with zero.
+  {"yydebug",  no_argument,       (int *) 0, LA_YYDEBUG     },
 
-  return value:  zero if defaults were successfully set, else non-zero
-                 (indicates a problem reading /etc/passwd).
-  calls:         none.
-  globals:       writes outlevel, rcfile, idfile.
- *********************************************************************/
-#include <stdlib.h>
+  {(char *) 0,  no_argument,       (int *) 0, 0              }
+};
 
-int setdefaults (queryctl)
-struct hostrec *queryctl;
+int parsecmdline (argc, argv, ctl)
+/* parse and validate the command line options */
+int argc;                      /* argument count */
+char **argv;                   /* argument strings */
+struct query *ctl;     /* option record to be initialized */
 {
-    char *user, *home;
+    /*
+     * return value: if positive, argv index of last parsed option + 1
+     * (presumes one or more server names follows).  if zero, the
+     * command line switches are such that no server names are
+     * required (e.g. --version).  if negative, the command line is
+     * has one or more syntax errors.
+     */
+
+    int c;
+    int ocount = 0;     /* count of destinations specified */
+    int errflag = 0;   /* TRUE when a syntax error is detected */
+    int option_index;
+
+    memset(ctl, '\0', sizeof(struct query));    /* start clean */
+
+    while (!errflag && 
+          (c = getopt_long(argc,argv,shortoptions,
+                           longoptions,&option_index)) != -1) {
+
+       switch (c) {
+       case 'V':
+       case LA_VERSION:
+           versioninfo = TRUE;
+           break;
+       case 'c':
+       case LA_CHECK:
+           check_only = TRUE;
+           break;
+       case 's':
+       case LA_SILENT:
+           outlevel = O_SILENT;
+           break;
+       case 'v':
+       case LA_VERBOSE:
+           outlevel = O_VERBOSE;
+           break;
+       case 'd':
+       case LA_DAEMON:
+           poll_interval = atoi(optarg);
+           break;
+       case 'N':
+       case LA_NODETACH:
+           nodetach = TRUE;
+           break;
+       case 'q':
+       case LA_QUIT:
+           quitmode = TRUE;
+           break;
+       case 'L':
+       case LA_LOGFILE:
+           cmd_logfile = optarg;
+           break;
+       case 'f':
+       case LA_RCFILE:
+           rcfile = (char *) xmalloc(strlen(optarg)+1);
+           strcpy(rcfile,optarg);
+           break;
+       case 'i':
+       case LA_IDFILE:
+           idfile = (char *) xmalloc(strlen(optarg)+1);
+           strcpy(idfile,optarg);
+           break;
+       case 'p':
+       case LA_PROTOCOL:
+           /* XXX -- should probably use a table lookup here */
+           if (strcasecmp(optarg,"pop2") == 0)
+               ctl->server.protocol = P_POP2;
+           else if (strcasecmp(optarg,"pop3") == 0)
+               ctl->server.protocol = P_POP3;
+           else if (strcasecmp(optarg,"imap") == 0)
+               ctl->server.protocol = P_IMAP;
+           else if (strcasecmp(optarg,"apop") == 0)
+               ctl->server.protocol = P_APOP;
+           else if (strcasecmp(optarg,"kpop") == 0)
+           {
+               ctl->server.protocol = P_POP3;
+               ctl->server.port = KPOP_PORT;
+               ctl->server.authenticate =  A_KERBEROS;
+           }
+           else {
+               fprintf(stderr,"Invalid protocol `%s' specified.\n", optarg);
+               errflag++;
+           }
+           break;
+       case 'P':
+       case LA_PORT:
+           ctl->server.port = atoi(optarg);
+           break;
+       case 'A':
+       case LA_AUTHENTICATE:
+           if (strcmp(optarg, "password") == 0)
+               ctl->server.authenticate = A_PASSWORD;
+           else if (strcmp(optarg, "kerberos") == 0)
+               ctl->server.authenticate = A_KERBEROS;
+           else {
+               fprintf(stderr,"Invalid authentication `%s' specified.\n", optarg);
+               errflag++;
+           }
+           break;
+       case 't':
+       case LA_TIMEOUT:
+           ctl->server.timeout = atoi(optarg);
+           break;
+       case 'E':
+       case LA_ENVELOPE:
+           ctl->server.envelope = xstrdup(optarg);
+           break;
+
+       case 'u':
+       case LA_USERNAME:
+           ctl->remotename = xstrdup(optarg);
+           break;
+       case 'a':
+       case LA_ALL:
+           ctl->fetchall = TRUE;
+           break;
+       case 'K':
+       case LA_KILL:
+           ctl->keep = FALSE;
+           break;
+       case 'k':
+       case LA_KEEP:
+           ctl->keep = TRUE;
+           break;
+       case 'F':
+       case LA_FLUSH:
+           ctl->flush = TRUE;
+           break;
+       case 'n':
+       case LA_NOREWRITE:
+           ctl->no_rewrite = TRUE;
+           break;
+       case 'l':
+       case LA_LIMIT:
+           ctl->limit = atoi(optarg);
+           break;
+       case 'r':
+       case LA_REMOTEFILE:
+           ctl->mailbox = xstrdup(optarg);
+           break;
+       case 'S':
+       case LA_SMTPHOST:
+           ctl->smtphost = xstrdup(optarg);
+           ocount++;
+           break;
+       case 'b':
+       case LA_BATCHLIMIT:
+           ctl->batchlimit = atoi(optarg);
+           break;
+       case 'B':
+       case LA_FETCHLIMIT:
+           ctl->fetchlimit = atoi(optarg);
+           break;
+       case 'm':
+       case LA_MDA:
+           ctl->mda = xstrdup(optarg);
+           ocount++;
+           break;
+
+#ifdef linux
+       case 'I':
+       case LA_INTERFACE:
+           ctl->server.interface = xstrdup(optarg);
+           break;
+       case 'M':
+       case LA_MONITOR:
+           ctl->server.monitor = xstrdup(optarg);
+           break;
+#endif
 
-    memset(queryctl, '\0', sizeof(*queryctl));
+       case 'y':
+       case LA_YYDEBUG:
+           yydebug = TRUE;
+           break;
 
-    if ((user = getenv("USER")) == (char *)NULL
-               || (home = getenv("HOME")) == (char *)NULL)
-    {
-       struct passwd *pw;
+       case LA_SYSLOG:
+           use_syslog = TRUE;
+           break;
 
-       if ((pw = getpwuid(getuid())) != NULL)
-       {
-           user = pw->pw_name;
-           home = pw->pw_dir;
-       }
-       else
-       {
-           fprintf(stderr,"I can't find your name and home directory!\n");
-           return(-1);
+       case '?':
+       case LA_HELP:
+       default:
+           errflag++;
        }
     }
 
-    queryctl->protocol = P_AUTO;
-
-#if defined(KEEP_IS_DEFAULT)
-    queryctl->keep = 1;
-#else
-    queryctl->keep = 0;
-#endif
-    queryctl->norewrite = 0;
+    if (check_only && poll_interval)
+    {
+       fputs("The --check and --daemon options aren't compatible.\n", stderr);
+       return(-1);
+    }
 
-    strcpy(queryctl->localname, user);
-    strcpy(queryctl->remotename, user);
-    strcpy(queryctl->smtphost, "localhost");
+    if (poll_interval == 0 && use_syslog)
+    {
+       fputs("The --syslog option is only valid with the --daemon option.\n", stderr);
+       return(-1);
+    }
 
-    rcfile = 
-       (char *) xmalloc(strlen(home)+strlen(RCFILE_NAME)+2);
-    strcpy(rcfile, home);
-    strcat(rcfile, "/");
-    strcat(rcfile, RCFILE_NAME);
+    if (errflag || ocount > 1) {
+       /* squawk if syntax errors were detected */
+       fputs("usage:  fetchmail [options] [server ...]\n", stderr);
+       fputs("  Options are as follows:\n",stderr);
+       fputs("  -?, --help        display this option help\n", stderr);
+       fputs("  -V, --version     display version info\n", stderr);
+
+       fputs("  -c, --check       check for messages without fetching\n", stderr);
+       fputs("  -s, --silent      work silently\n", stderr);
+       fputs("  -v, --verbose     work noisily (diagnostic output)\n", stderr);
+       fputs("  -d, --daemon      run as a daemon once per n seconds\n", stderr);
+       fputs("  -N, --nodetach    don't detach daemon process\n", stderr);
+       fputs("  -q, --quit        kill daemon process\n", stderr);
+       fputs("  -L, --logfile     specify logfile name\n", stderr);
+       fputs("      --syslog      use syslog(3) for most messages when running as a daemon\n", stderr);
+       fputs("  -f, --fetchmailrc specify alternate run control file\n", stderr);
+       fputs("  -i, --idfile      specify alternate UIDs file\n", stderr);
+#ifdef linux
+       fputs("  -I, --interface   interface required specification\n",stderr);
+       fputs("  -M, --monitor     monitor interface for activity\n",stderr);
+#endif
 
-    outlevel = O_NORMAL;
+       fputs("  -p, --protocol    specify pop2, pop3, imap, apop, rpop, kpop\n", stderr);
+       fputs("  -P, --port        TCP/IP service port to connect to\n",stderr);
+       fputs("  -A, --auth        authentication type (password or kerberos)\n",stderr);
+       fputs("  -t, --timeout     server nonresponse timeout\n",stderr);
+       fputs("  -E, --envelope    envelope address header\n",stderr);
+
+       fputs("  -u, --username    specify users's login on server\n", stderr);
+       fputs("  -a, --all         retrieve old and new messages\n", stderr);
+       fputs("  -K, --kill        delete new messages after retrieval\n", stderr);
+       fputs("  -k, --keep        save new messages after retrieval\n", stderr);
+       fputs("  -F, --flush       delete old messages from server\n", stderr);
+       fputs("  -n, --norewrite   don't rewrite header addresses\n", stderr);
+       fputs("  -l, --limit       don't fetch messages over given size\n", stderr);
+
+       fputs("  -S, --smtphost    set SMTP forwarding host\n", stderr);
+       fputs("  -b, --batchlimit  set batch limit for SMTP connections\n", stderr);
+       fputs("  -B, --fetchlimit  set fetch limit for server connections\n", stderr);
+       fputs("  -r, --remote      specify remote folder name\n", stderr);
+       return(-1);
+    }
 
-    return(0);
+    return(optind);
 }
 
-
-
-/******************************************************************
-  function:    getnextserver
-  description: read next server name from the command line.
-  arguments:   
-    argc       from main()
-    argv       from main()
-    optind     as returned by parsecmdline and this function.
-
-  ret. value:  next server name from command line or NULL if all
-               server names have been retrieved.
-  globals:     none.
-  calls:       none.
- *****************************************************************/
-char *getnextserver (argc,argv,optind)
-int argc;
-char **argv;
-int *optind;
-{
-   if (*optind >= argc) {
-     /* no more servers */
-     return((char *) 0);
-   }
-   else
-     return(argv[(*optind)++]);
-}
+/* options.c ends here */