]> Pileus Git - ~andy/fetchmail/blob - options.c
Clean up option dumping.
[~andy/fetchmail] / options.c
1 /*
2  * options.c -- command-line option processing
3  *
4  * For license terms, see the file COPYING in this directory.
5  */
6
7 #include "config.h"
8
9 #include <stdio.h>
10 #if defined(HAVE_ALLOCA_H)
11 #include <alloca.h>
12 #else
13 #ifdef _AIX
14  #pragma alloca
15 #endif
16 #endif
17 #include <pwd.h>
18 #include <string.h>
19 #include <errno.h>
20 #if defined(STDC_HEADERS)
21 #include  <stdlib.h>
22 #include  <limits.h>
23 #else
24 #include  <ctype.h>
25 #endif
26
27 #include "getopt.h"
28 #include "fetchmail.h"
29
30 #define LA_HELP         1
31 #define LA_VERSION      2 
32 #define LA_CHECK        3
33 #define LA_SILENT       4 
34 #define LA_VERBOSE      5 
35 #define LA_DAEMON       6
36 #define LA_NODETACH     7
37 #define LA_QUIT         8
38 #define LA_LOGFILE      9
39 #define LA_INVISIBLE    10
40 #define LA_SYSLOG       11
41 #define LA_NOSYSLOG     12
42 #define LA_RCFILE       13
43 #define LA_IDFILE       14
44 #define LA_POSTMASTER   15
45 #define LA_PROTOCOL     16
46 #define LA_UIDL         17
47 #define LA_PORT         18
48 #define LA_AUTHENTICATE 19
49 #define LA_TIMEOUT      20
50 #define LA_ENVELOPE     21
51 #define LA_QVIRTUAL     22
52 #define LA_USERNAME     23
53 #define LA_ALL          24
54 #define LA_NOKEEP       25
55 #define LA_KEEP         26
56 #define LA_FLUSH        27
57 #define LA_NOREWRITE    28
58 #define LA_LIMIT        29
59 #define LA_WARNINGS     30
60 #define LA_FOLDER       31
61 #define LA_SMTPHOST     32
62 #define LA_SMTPADDR     33
63 #define LA_ANTISPAM     34
64 #define LA_BATCHLIMIT   35
65 #define LA_FETCHLIMIT   36
66 #define LA_EXPUNGE      37
67 #define LA_MDA          38
68 #define LA_NETSEC       39
69 #define LA_INTERFACE    40
70 #define LA_MONITOR      41
71 #define LA_CONFIGDUMP   42
72 #define LA_YYDEBUG      43
73
74 /* options still left: CgGhHjJoORwWxXYz */
75 static const char *shortoptions = 
76         "?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:T:I:M:yw:";
77
78 static const struct option longoptions[] = {
79 /* this can be const because all flag fields are 0 and will never get set */
80   {"help",      no_argument,       (int *) 0, LA_HELP        },
81   {"version",   no_argument,       (int *) 0, LA_VERSION     },
82   {"check",     no_argument,       (int *) 0, LA_CHECK       },
83   {"silent",    no_argument,       (int *) 0, LA_SILENT      },
84   {"verbose",   no_argument,       (int *) 0, LA_VERBOSE     },
85   {"daemon",    required_argument, (int *) 0, LA_DAEMON      },
86   {"nodetach",  no_argument,       (int *) 0, LA_NODETACH    },
87   {"quit",      no_argument,       (int *) 0, LA_QUIT        },
88   {"logfile",   required_argument, (int *) 0, LA_LOGFILE     },
89   {"invisible", no_argument,       (int *) 0, LA_INVISIBLE   },
90   {"syslog",    no_argument,       (int *) 0, LA_SYSLOG      },
91   {"nosyslog",  no_argument,       (int *) 0, LA_NOSYSLOG    },
92   {"fetchmailrc",required_argument,(int *) 0, LA_RCFILE      },
93   {"idfile",    required_argument, (int *) 0, LA_IDFILE      },
94   {"postmaster",required_argument, (int *) 0, LA_POSTMASTER  },
95
96   {"protocol",  required_argument, (int *) 0, LA_PROTOCOL    },
97   {"proto",     required_argument, (int *) 0, LA_PROTOCOL    },
98   {"uidl",      no_argument,       (int *) 0, LA_UIDL        },
99   {"port",      required_argument, (int *) 0, LA_PORT        },
100   {"auth",      required_argument, (int *) 0, LA_AUTHENTICATE},
101   {"timeout",   required_argument, (int *) 0, LA_TIMEOUT     },
102   {"envelope",  required_argument, (int *) 0, LA_ENVELOPE    },
103   {"qvirtual",  required_argument, (int *) 0, LA_QVIRTUAL    },
104
105   {"user",      required_argument, (int *) 0, LA_USERNAME    },
106   {"username",  required_argument, (int *) 0, LA_USERNAME    },
107
108   {"all",       no_argument,       (int *) 0, LA_ALL         },
109   {"nokeep",    no_argument,       (int *) 0, LA_NOKEEP      },
110   {"keep",      no_argument,       (int *) 0, LA_KEEP        },
111   {"flush",     no_argument,       (int *) 0, LA_FLUSH       },
112   {"norewrite", no_argument,       (int *) 0, LA_NOREWRITE   },
113   {"limit",     required_argument, (int *) 0, LA_LIMIT       },
114   {"warnings",  required_argument, (int *) 0, LA_WARNINGS    },
115
116   {"folder",    required_argument, (int *) 0, LA_FOLDER      },
117   {"smtphost",  required_argument, (int *) 0, LA_SMTPHOST    },
118   {"smtpaddress", required_argument, (int *) 0, LA_SMTPADDR  },
119   {"antispam",  required_argument, (int *) 0, LA_ANTISPAM    },
120   
121   {"batchlimit",required_argument, (int *) 0, LA_BATCHLIMIT  },
122   {"fetchlimit",required_argument, (int *) 0, LA_FETCHLIMIT  },
123   {"expunge",   required_argument, (int *) 0, LA_EXPUNGE     },
124   {"mda",       required_argument, (int *) 0, LA_MDA         },
125
126 #ifdef INET6
127   {"netsec",    required_argument, (int *) 0, LA_NETSEC    },
128 #endif /* INET6 */
129
130 #if defined(linux) && !INET6
131   {"interface", required_argument, (int *) 0, LA_INTERFACE   },
132   {"monitor",   required_argument, (int *) 0, LA_MONITOR     },
133 #endif /* defined(linux) && !INET6 */
134
135   {"configdump",no_argument,       (int *) 0, LA_CONFIGDUMP  },
136
137   {"yydebug",   no_argument,       (int *) 0, LA_YYDEBUG     },
138
139   {(char *) 0,  no_argument,       (int *) 0, 0              }
140 };
141
142 static int xatoi(char *s, int *errflagptr)
143 /* do safe conversion from string to number */
144 {
145 #if defined (STDC_HEADERS) && defined (LONG_MAX) && defined (INT_MAX)
146     /* parse and convert numbers, but also check for invalid characters in
147      * numbers
148      */
149
150     char *endptr;
151     long value;
152
153     errno = 0;
154
155     value = strtol(s, &endptr, 0);
156
157     /* any invalid chars in string? */
158     if ( (endptr == s) || (*endptr != '\0') ) {
159         (void) fprintf(stderr, "String '%s' is not a valid number string.\n", s);
160         (*errflagptr)++;
161         return 0;
162     }
163
164     /* is the range valid? */
165     if ( (((value == LONG_MAX) || (value == LONG_MIN)) && (errno == ERANGE)) ||
166                                 (value > INT_MAX) || (value < INT_MIN)) {
167
168         (void) fprintf(stderr, "Value of string '%s' is %s than %d.\n", s,
169                                         (value < 0) ? "smaller": "larger",
170                                         (value < 0) ? INT_MIN : INT_MAX);
171         (*errflagptr)++;
172         return 0;
173     }
174
175     return (int) value;  /* shut up, I know what I'm doing */
176 #else
177     int i;
178     char *dp;
179 # if defined (STDC_HEADERS)
180     size_t      len;
181 # else
182     int         len;
183 # endif
184
185     /* We do only base 10 conversions here (atoi)! */
186
187     len = strlen(s);
188     /* check for leading white spaces */
189     for (i = 0; (i < len) && isspace(s[i]); i++)
190         ;
191
192     dp = &s[i];
193
194     /* check for +/- */
195     if (i < len && (s[i] == '+' || s[i] == '-'))        i++;
196
197     /* skip over digits */
198     for ( /* no init */ ; (i < len) && isdigit(s[i]); i++)
199         ;
200
201     /* check for trailing garbage */
202     if (i != len) {
203         (void) fprintf(stderr, "String '%s' is not a valid number string.\n", s);
204         (*errflagptr)++;
205         return 0;
206     }
207
208     /* atoi should be safe by now, except for number range over/underflow */
209     return atoi(dp);
210 #endif
211 }
212
213 int parsecmdline (argc, argv, rctl, ctl)
214 /* parse and validate the command line options */
215 int argc;               /* argument count */
216 char **argv;            /* argument strings */
217 struct runctl *rctl;    /* global run controls to modify */
218 struct query *ctl;      /* option record to be initialized */
219 {
220     /*
221      * return value: if positive, argv index of last parsed option + 1
222      * (presumes one or more server names follows).  if zero, the
223      * command line switches are such that no server names are
224      * required (e.g. --version).  if negative, the command line is
225      * has one or more syntax errors.
226      */
227
228     int c;
229     int ocount = 0;     /* count of destinations specified */
230     int errflag = 0;   /* TRUE when a syntax error is detected */
231     int option_index;
232     char *buf, *cp;
233
234     rctl->poll_interval = -1;
235
236     memset(ctl, '\0', sizeof(struct query));    /* start clean */
237     ctl->smtp_socket = -1;
238
239     while (!errflag && 
240            (c = getopt_long(argc,argv,shortoptions,
241                             longoptions,&option_index)) != -1) {
242
243         switch (c) {
244         case 'V':
245         case LA_VERSION:
246             versioninfo = TRUE;
247             break;
248         case 'c':
249         case LA_CHECK:
250             check_only = TRUE;
251             break;
252         case 's':
253         case LA_SILENT:
254             outlevel = O_SILENT;
255             break;
256         case 'v':
257         case LA_VERBOSE:
258             if (outlevel == O_VERBOSE)
259                 outlevel = O_DEBUG;
260             else
261                 outlevel = O_VERBOSE;
262             break;
263         case 'd':
264         case LA_DAEMON:
265             rctl->poll_interval = xatoi(optarg, &errflag);
266             break;
267         case 'N':
268         case LA_NODETACH:
269             nodetach = TRUE;
270             break;
271         case 'q':
272         case LA_QUIT:
273             quitmode = TRUE;
274             break;
275         case 'L':
276         case LA_LOGFILE:
277             rctl->logfile = optarg;
278             break;
279         case LA_INVISIBLE:
280             rctl->invisible = TRUE;
281             break;
282         case 'f':
283         case LA_RCFILE:
284             rcfile = (char *) xmalloc(strlen(optarg)+1);
285             strcpy(rcfile,optarg);
286             break;
287         case 'i':
288         case LA_IDFILE:
289             rctl->idfile = (char *) xmalloc(strlen(optarg)+1);
290             strcpy(rctl->idfile,optarg);
291             break;
292         case LA_POSTMASTER:
293             rctl->postmaster = (char *) xmalloc(strlen(optarg)+1);
294             break;
295         case 'p':
296         case LA_PROTOCOL:
297             /* XXX -- should probably use a table lookup here */
298             if (strcasecmp(optarg,"pop2") == 0)
299                 ctl->server.protocol = P_POP2;
300 #ifdef SDPS_ENABLE
301             else if (strcasecmp(optarg,"sdps") == 0)
302             {
303                 ctl->server.protocol = P_POP3; 
304                 ctl->server.sdps = TRUE;
305             }
306 #endif /* SDPS_ENABLE */
307             else if (strcasecmp(optarg,"pop3") == 0)
308                 ctl->server.protocol = P_POP3;
309             else if (strcasecmp(optarg,"apop") == 0)
310                 ctl->server.protocol = P_APOP;
311             else if (strcasecmp(optarg,"rpop") == 0)
312                 ctl->server.protocol = P_RPOP;
313             else if (strcasecmp(optarg,"kpop") == 0)
314             {
315                 ctl->server.protocol = P_POP3;
316 #if INET6
317                 ctl->server.service = KPOP_PORT;
318 #else /* INET6 */
319                 ctl->server.port = KPOP_PORT;
320 #endif /* INET6 */
321 #ifdef KERBEROS_V5
322                 ctl->server.preauthenticate =  A_KERBEROS_V5;
323 #else
324                 ctl->server.preauthenticate =  A_KERBEROS_V4;
325 #endif /* KERBEROS_V5 */
326             }
327             else if (strcasecmp(optarg,"imap") == 0)
328                 ctl->server.protocol = P_IMAP;
329 #ifdef KERBEROS_V4
330             else if (strcasecmp(optarg,"imap-k4") == 0)
331                 ctl->server.protocol = P_IMAP_K4;
332 #endif /* KERBEROS_V4 */
333 #ifdef GSSAPI
334             else if (strcasecmp(optarg, "imap-gss") == 0)
335                 ctl->server.protocol = P_IMAP_GSS;
336 #endif /* GSSAPI */
337             else if (strcasecmp(optarg,"etrn") == 0)
338                 ctl->server.protocol = P_ETRN;
339             else {
340                 fprintf(stderr,"Invalid protocol `%s' specified.\n", optarg);
341                 errflag++;
342             }
343             break;
344         case 'U':
345         case LA_UIDL:
346             ctl->server.uidl = FLAG_TRUE;
347             break;
348         case 'P':
349         case LA_PORT:
350 #if INET6
351             ctl->server.service = optarg;
352 #else /* INET6 */
353             ctl->server.port = xatoi(optarg, &errflag);
354 #endif /* INET6 */
355             break;
356         case 'A':
357         case LA_AUTHENTICATE:
358             if (strcmp(optarg, "password") == 0)
359                 ctl->server.preauthenticate = A_PASSWORD;
360             else if (strcmp(optarg, "kerberos") == 0)
361 #ifdef KERBEROS_V5
362                 ctl->server.preauthenticate = A_KERBEROS_V5;
363             else if (strcmp(optarg, "kerberos_v5") == 0)
364                 ctl->server.preauthenticate = A_KERBEROS_V5;
365 #else
366                 ctl->server.preauthenticate = A_KERBEROS_V4;
367             else if (strcmp(optarg, "kerberos_v4") == 0)
368                 ctl->server.preauthenticate = A_KERBEROS_V4;
369 #endif /* KERBEROS_V5 */
370             else {
371                 fprintf(stderr,"Invalid preauthentication `%s' specified.\n", optarg);
372                 errflag++;
373             }
374             break;
375         case 't':
376         case LA_TIMEOUT:
377             ctl->server.timeout = xatoi(optarg, &errflag);
378             if (ctl->server.timeout == 0)
379                 ctl->server.timeout = -1;
380             break;
381         case 'E':
382         case LA_ENVELOPE:
383             ctl->server.envelope = xstrdup(optarg);
384             break;
385         case 'Q':    
386         case LA_QVIRTUAL:
387             ctl->server.qvirtual = xstrdup(optarg);
388             break;
389
390         case 'u':
391         case LA_USERNAME:
392             ctl->remotename = xstrdup(optarg);
393             break;
394         case 'a':
395         case LA_ALL:
396             ctl->fetchall = FLAG_TRUE;
397             break;
398         case 'K':
399         case LA_NOKEEP:
400             ctl->keep = FLAG_FALSE;
401             break;
402         case 'k':
403         case LA_KEEP:
404             ctl->keep = FLAG_TRUE;
405             break;
406         case 'F':
407         case LA_FLUSH:
408             ctl->flush = FLAG_TRUE;
409             break;
410         case 'n':
411         case LA_NOREWRITE:
412             ctl->rewrite = FLAG_FALSE;
413             break;
414         case 'l':
415         case LA_LIMIT:
416             c = xatoi(optarg, &errflag);
417             ctl->limit = NUM_VALUE(c);
418             break;
419         case 'r':
420         case LA_FOLDER:
421             buf = alloca(strlen(optarg));
422             strcpy(buf, optarg);
423             cp = strtok(buf, ",");
424             do {
425                 save_str(&ctl->mailboxes, cp, 0);
426             } while
427                 ((cp = strtok((char *)NULL, ",")));
428             break;
429         case 'S':
430         case LA_SMTPHOST:
431             buf = alloca(strlen(optarg));
432             strcpy(buf, optarg);
433             cp = strtok(buf, ",");
434             do {
435                 save_str(&ctl->smtphunt, cp, TRUE);
436             } while
437                 ((cp = strtok((char *)NULL, ",")));
438             ocount++;
439             break;
440         case 'D':
441         case LA_SMTPADDR:
442             ctl->smtpaddress = xstrdup(optarg);
443             break;
444         case 'Z':
445         case LA_ANTISPAM:
446             buf = alloca(strlen(optarg));
447             strcpy(buf, optarg);
448             cp = strtok(buf, ",");
449             do {
450                 struct idlist   *idp = save_str(&ctl->antispam, NULL, 0);;
451
452                 idp->val.status.num = atoi(cp);
453             } while
454                 ((cp = strtok((char *)NULL, ",")));
455             break;
456         case 'b':
457         case LA_BATCHLIMIT:
458             c = xatoi(optarg, &errflag);
459             ctl->batchlimit = NUM_VALUE(c);
460             break;
461         case 'B':
462         case LA_FETCHLIMIT:
463             c = xatoi(optarg, &errflag);
464             ctl->fetchlimit = NUM_VALUE(c);
465             break;
466         case 'e':
467         case LA_EXPUNGE:
468             c = xatoi(optarg, &errflag);
469             ctl->expunge = NUM_VALUE(c);
470             break;
471         case 'm':
472         case LA_MDA:
473             ctl->mda = xstrdup(optarg);
474             ocount++;
475             break;
476
477         case 'T':
478         case LA_NETSEC:
479 #if NET_SECURITY
480             ctl->server.netsec = (void *)optarg;
481 #else
482             fprintf(stderr, "fetchmail: network security support is disabled\n");
483             errflag++;
484 #endif /* NET_SECURITY */
485             break;
486
487 #if defined(linux) && !INET6
488         case 'I':
489         case LA_INTERFACE:
490             interface_parse(optarg, &ctl->server);
491             break;
492         case 'M':
493         case LA_MONITOR:
494             ctl->server.monitor = xstrdup(optarg);
495             break;
496 #endif /* defined(linux) && !INET6 */
497
498         case 'y':
499         case LA_YYDEBUG:
500             yydebug = TRUE;
501             break;
502
503         case 'w':
504         case LA_WARNINGS:
505             c = xatoi(optarg, &errflag);
506             ctl->warnings = NUM_VALUE(c);
507             break;
508
509         case LA_CONFIGDUMP:
510             configdump = TRUE;
511             break;
512
513         case LA_SYSLOG:
514             rctl->use_syslog = FLAG_TRUE;
515             break;
516
517         case LA_NOSYSLOG:
518             rctl->use_syslog = FLAG_FALSE;
519             break;
520
521         case '?':
522         case LA_HELP:
523         default:
524             errflag++;
525         }
526     }
527
528     if (errflag || ocount > 1) {
529         /* squawk if syntax errors were detected */
530 #define P(s)    fputs(s, stderr)
531         P("usage:  fetchmail [options] [server ...]\n");
532         P("  Options are as follows:\n");
533         P("  -?, --help        display this option help\n");
534         P("  -V, --version     display version info\n");
535
536         P("  -c, --check       check for messages without fetching\n");
537         P("  -s, --silent      work silently\n");
538         P("  -v, --verbose     work noisily (diagnostic output)\n");
539         P("  -d, --daemon      run as a daemon once per n seconds\n");
540         P("  -N, --nodetach    don't detach daemon process\n");
541         P("  -q, --quit        kill daemon process\n");
542         P("  -L, --logfile     specify logfile name\n");
543         P("      --syslog      use syslog(3) for most messages when running as a daemon\n");
544         P("      --invisible   don't write Received & enable host spoofing\n");
545         P("  -f, --fetchmailrc specify alternate run control file\n");
546         P("  -i, --idfile      specify alternate UIDs file\n");
547         P("      --postmaster  specify recipient of last resort\n");
548 #if defined(linux) && !INET6
549         P("  -I, --interface   interface required specification\n");
550         P("  -M, --monitor     monitor interface for activity\n");
551 #endif
552
553         P("  -p, --protocol    specify retrieval protocol (see man page)\n");
554         P("  -U, --uidl        force the use of UIDLs (pop3 only)\n");
555         P("  -P, --port        TCP/IP service port to connect to\n");
556         P("  -A, --auth        authentication type (password or kerberos)\n");
557         P("  -t, --timeout     server nonresponse timeout\n");
558         P("  -E, --envelope    envelope address header\n");
559         P("  -Q, --qvirtual    prefix to remove from local user id\n");
560
561         P("  -u, --username    specify users's login on server\n");
562         P("  -a, --all         retrieve old and new messages\n");
563         P("  -K, --nokeep      delete new messages after retrieval\n");
564         P("  -k, --keep        save new messages after retrieval\n");
565         P("  -F, --flush       delete old messages from server\n");
566         P("  -n, --norewrite   don't rewrite header addresses\n");
567         P("  -l, --limit       don't fetch messages over given size\n");
568         P("  -w, --warnings   interval between warning mail notification\n");
569
570 #if NET_SECURITY
571         P("  -T, --netsec      set IP security request\n");
572 #endif /* NET_SECURITY */
573         P("  -S, --smtphost    set SMTP forwarding host\n");
574         P("  -D, --smtpaddress set SMTP delivery domain to use\n");
575         P("  -Z, --antispam,   set antispam response values\n");
576         P("  -b, --batchlimit  set batch limit for SMTP connections\n");
577         P("  -B, --fetchlimit  set fetch limit for server connections\n");
578         P("  -e, --expunge     set max deletions between expunges\n");
579         P("  -r, --folder      specify remote folder name\n");
580 #undef P
581         return(-1);
582     }
583
584     return(optind);
585 }
586
587 /* options.c ends here */