]> Pileus Git - ~andy/fetchmail/blob - options.c
Kerberos V support.
[~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 #include <pwd.h>
11 #include <string.h>
12 #if defined(STDC_HEADERS)
13 #include  <stdlib.h>
14 #endif
15
16 #include "getopt.h"
17 #include "fetchmail.h"
18
19 #define LA_HELP         1
20 #define LA_VERSION      2 
21 #define LA_CHECK        3
22 #define LA_SILENT       4 
23 #define LA_VERBOSE      5 
24 #define LA_DAEMON       6
25 #define LA_NODETACH     7
26 #define LA_QUIT         8
27 #define LA_LOGFILE      9
28 #define LA_INVISIBLE    10
29 #define LA_SYSLOG       11
30 #define LA_RCFILE       12
31 #define LA_IDFILE       13
32 #define LA_PROTOCOL     14
33 #define LA_UIDL         15
34 #define LA_PORT         16
35 #define LA_AUTHENTICATE 17
36 #define LA_TIMEOUT      18
37 #define LA_ENVELOPE     19
38 #define LA_QVIRTUAL     20
39 #define LA_USERNAME     21
40 #define LA_ALL          22
41 #define LA_NOKEEP       23
42 #define LA_KEEP         24
43 #define LA_FLUSH        25
44 #define LA_NOREWRITE    26
45 #define LA_LIMIT        27
46 #define LA_FOLDER       28
47 #define LA_SMTPHOST     29
48 #define LA_SMTPADDR     30
49 #define LA_BATCHLIMIT   31
50 #define LA_FETCHLIMIT   32
51 #define LA_EXPUNGE      33
52 #define LA_MDA          34
53 #define LA_NETSEC       35
54 #define LA_INTERFACE    36
55 #define LA_MONITOR      37
56 #define LA_YYDEBUG      38
57
58 /* options still left: CgGhHjJoORUwWxXYzZ */
59 static const char *shortoptions = 
60         "?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:b:B:e:m:I:M:y";
61
62 static const struct option longoptions[] = {
63 /* this can be const because all flag fields are 0 and will never get set */
64   {"help",      no_argument,       (int *) 0, LA_HELP        },
65   {"version",   no_argument,       (int *) 0, LA_VERSION     },
66   {"check",     no_argument,       (int *) 0, LA_CHECK       },
67   {"silent",    no_argument,       (int *) 0, LA_SILENT      },
68   {"verbose",   no_argument,       (int *) 0, LA_VERBOSE     },
69   {"daemon",    required_argument, (int *) 0, LA_DAEMON      },
70   {"nodetach",  no_argument,       (int *) 0, LA_NODETACH    },
71   {"quit",      no_argument,       (int *) 0, LA_QUIT        },
72   {"logfile",   required_argument, (int *) 0, LA_LOGFILE     },
73   {"invisible", no_argument,       (int *) 0, LA_INVISIBLE   },
74   {"syslog",    no_argument,       (int *) 0, LA_SYSLOG      },
75   {"fetchmailrc",required_argument,(int *) 0, LA_RCFILE      },
76   {"idfile",    required_argument, (int *) 0, LA_IDFILE      },
77
78   {"protocol",  required_argument, (int *) 0, LA_PROTOCOL    },
79   {"proto",     required_argument, (int *) 0, LA_PROTOCOL    },
80   {"uidl",      no_argument,       (int *) 0, LA_UIDL        },
81   {"port",      required_argument, (int *) 0, LA_PORT        },
82   {"auth",      required_argument, (int *) 0, LA_AUTHENTICATE},
83   {"timeout",   required_argument, (int *) 0, LA_TIMEOUT     },
84   {"envelope",  required_argument, (int *) 0, LA_ENVELOPE    },
85   {"qvirtual",  required_argument, (int *) 0, LA_QVIRTUAL    },
86
87   {"user",      required_argument, (int *) 0, LA_USERNAME    },
88   {"username",  required_argument, (int *) 0, LA_USERNAME    },
89
90   {"all",       no_argument,       (int *) 0, LA_ALL         },
91   {"nokeep",    no_argument,       (int *) 0, LA_NOKEEP      },
92   {"keep",      no_argument,       (int *) 0, LA_KEEP        },
93   {"flush",     no_argument,       (int *) 0, LA_FLUSH       },
94   {"norewrite", no_argument,       (int *) 0, LA_NOREWRITE   },
95   {"limit",     required_argument, (int *) 0, LA_LIMIT       },
96
97   {"folder",    required_argument, (int *) 0, LA_FOLDER      },
98   {"smtphost",  required_argument, (int *) 0, LA_SMTPHOST    },
99   {"smtpaddress", required_argument, (int *) 0, LA_SMTPADDR  },
100   
101   {"batchlimit",required_argument, (int *) 0, LA_BATCHLIMIT  },
102   {"fetchlimit",required_argument, (int *) 0, LA_FETCHLIMIT  },
103   {"expunge",   required_argument, (int *) 0, LA_EXPUNGE     },
104   {"mda",       required_argument, (int *) 0, LA_MDA         },
105
106 #ifdef INET6
107   {"netsec",    required_argument, (int *) 0, LA_NETSEC    },
108 #endif /* INET6 */
109
110 #if defined(linux) && !INET6
111   {"interface", required_argument, (int *) 0, LA_INTERFACE   },
112   {"monitor",   required_argument, (int *) 0, LA_MONITOR     },
113 #endif /* defined(linux) && !INET6 */
114
115   {"yydebug",   no_argument,       (int *) 0, LA_YYDEBUG     },
116
117   {(char *) 0,  no_argument,       (int *) 0, 0              }
118 };
119
120 int parsecmdline (argc, argv, ctl)
121 /* parse and validate the command line options */
122 int argc;               /* argument count */
123 char **argv;            /* argument strings */
124 struct query *ctl;      /* option record to be initialized */
125 {
126     /*
127      * return value: if positive, argv index of last parsed option + 1
128      * (presumes one or more server names follows).  if zero, the
129      * command line switches are such that no server names are
130      * required (e.g. --version).  if negative, the command line is
131      * has one or more syntax errors.
132      */
133
134     int c;
135     int ocount = 0;     /* count of destinations specified */
136     int errflag = 0;   /* TRUE when a syntax error is detected */
137     int option_index;
138     char buf[BUFSIZ], *cp;
139
140     cmd_daemon = -1;
141
142     memset(ctl, '\0', sizeof(struct query));    /* start clean */
143     ctl->smtp_socket = -1;
144
145     while (!errflag && 
146            (c = getopt_long(argc,argv,shortoptions,
147                             longoptions,&option_index)) != -1) {
148
149         switch (c) {
150         case 'V':
151         case LA_VERSION:
152             versioninfo = TRUE;
153             break;
154         case 'c':
155         case LA_CHECK:
156             check_only = TRUE;
157             break;
158         case 's':
159         case LA_SILENT:
160             outlevel = O_SILENT;
161             break;
162         case 'v':
163         case LA_VERBOSE:
164             outlevel = O_VERBOSE;
165             break;
166         case 'd':
167         case LA_DAEMON:
168             cmd_daemon = atoi(optarg);
169             break;
170         case 'N':
171         case LA_NODETACH:
172             nodetach = TRUE;
173             break;
174         case 'q':
175         case LA_QUIT:
176             quitmode = TRUE;
177             break;
178         case 'L':
179         case LA_LOGFILE:
180             cmd_logfile = optarg;
181             break;
182         case LA_INVISIBLE:
183             use_invisible = TRUE;
184             break;
185         case 'f':
186         case LA_RCFILE:
187             rcfile = (char *) xmalloc(strlen(optarg)+1);
188             strcpy(rcfile,optarg);
189             break;
190         case 'i':
191         case LA_IDFILE:
192             idfile = (char *) xmalloc(strlen(optarg)+1);
193             strcpy(idfile,optarg);
194             break;
195         case 'p':
196         case LA_PROTOCOL:
197             /* XXX -- should probably use a table lookup here */
198             if (strcasecmp(optarg,"pop2") == 0)
199                 ctl->server.protocol = P_POP2;
200             else if (strcasecmp(optarg,"pop3") == 0)
201                 ctl->server.protocol = P_POP3;
202             else if (strcasecmp(optarg,"apop") == 0)
203                 ctl->server.protocol = P_APOP;
204             else if (strcasecmp(optarg,"rpop") == 0)
205                 ctl->server.protocol = P_RPOP;
206             else if (strcasecmp(optarg,"kpop") == 0)
207             {
208                 ctl->server.protocol = P_POP3;
209 #if INET6
210                 ctl->server.service = KPOP_PORT;
211 #else /* INET6 */
212                 ctl->server.port = KPOP_PORT;
213 #endif /* INET6 */
214 #ifdef KERBEROS_V5
215                 ctl->server.preauthenticate =  A_KERBEROS_V5;
216 #else
217                 ctl->server.preauthenticate =  A_KERBEROS_V4;
218 #endif /* KERBEROS_V5 */
219             }
220             else if (strcasecmp(optarg,"imap") == 0)
221                 ctl->server.protocol = P_IMAP;
222 #ifdef KERBEROS_V4
223             else if (strcasecmp(optarg,"imap-k4") == 0)
224                 ctl->server.protocol = P_IMAP_K4;
225 #endif /* KERBEROS_V4 */
226             else if (strcasecmp(optarg,"etrn") == 0)
227                 ctl->server.protocol = P_ETRN;
228             else {
229                 fprintf(stderr,"Invalid protocol `%s' specified.\n", optarg);
230                 errflag++;
231             }
232             break;
233         case 'U':
234         case LA_UIDL:
235             ctl->server.uidl = FLAG_TRUE;
236             break;
237         case 'P':
238         case LA_PORT:
239 #if INET6
240             ctl->server.service = optarg;
241 #else /* INET6 */
242             ctl->server.port = atoi(optarg);
243 #endif /* INET6 */
244             break;
245         case 'A':
246         case LA_AUTHENTICATE:
247             if (strcmp(optarg, "password") == 0)
248                 ctl->server.preauthenticate = A_PASSWORD;
249             else if (strcmp(optarg, "kerberos") == 0)
250 #ifdef KERBEROS_V5
251                 ctl->server.preauthenticate = A_KERBEROS_V5;
252             else if (strcmp(optarg, "kerberos_v5") == 0)
253                 ctl->server.preauthenticate = A_KERBEROS_V5;
254 #else
255                 ctl->server.preauthenticate = A_KERBEROS_V4;
256             else if (strcmp(optarg, "kerberos_v4") == 0)
257                 ctl->server.preauthenticate = A_KERBEROS_V4;
258 #endif /* KERBEROS_V5 */
259             else {
260                 fprintf(stderr,"Invalid preauthentication `%s' specified.\n", optarg);
261                 errflag++;
262             }
263             break;
264         case 't':
265         case LA_TIMEOUT:
266             ctl->server.timeout = atoi(optarg);
267             if (ctl->server.timeout == 0)
268                 ctl->server.timeout = -1;
269             break;
270         case 'E':
271         case LA_ENVELOPE:
272             ctl->server.envelope = xstrdup(optarg);
273             break;
274         case 'Q':    
275         case LA_QVIRTUAL:
276             ctl->server.qvirtual = xstrdup(optarg);
277             break;
278
279         case 'u':
280         case LA_USERNAME:
281             ctl->remotename = xstrdup(optarg);
282             break;
283         case 'a':
284         case LA_ALL:
285             ctl->fetchall = FLAG_TRUE;
286             break;
287         case 'K':
288         case LA_NOKEEP:
289             ctl->keep = FLAG_FALSE;
290             break;
291         case 'k':
292         case LA_KEEP:
293             ctl->keep = FLAG_TRUE;
294             break;
295         case 'F':
296         case LA_FLUSH:
297             ctl->flush = FLAG_TRUE;
298             break;
299         case 'n':
300         case LA_NOREWRITE:
301             ctl->rewrite = FLAG_FALSE;
302             break;
303         case 'l':
304         case LA_LIMIT:
305             c = atoi(optarg);
306             ctl->limit = NUM_VALUE(c);
307             break;
308         case 'r':
309         case LA_FOLDER:
310             strcpy(buf, optarg);
311             cp = strtok(buf, ",");
312             do {
313                 save_str(&ctl->mailboxes, -1, cp);
314             } while
315                 ((cp = strtok((char *)NULL, ",")));
316             break;
317         case 'S':
318         case LA_SMTPHOST:
319             strcpy(buf, optarg);
320             cp = strtok(buf, ",");
321             do {
322                 save_str(&ctl->smtphunt, TRUE, cp);
323             } while
324                 ((cp = strtok((char *)NULL, ",")));
325             ocount++;
326             break;
327         case 'D':
328         case LA_SMTPADDR:
329           ctl->smtpaddress = xstrdup(optarg);
330           break;
331         case 'b':
332         case LA_BATCHLIMIT:
333             c = atoi(optarg);
334             ctl->batchlimit = NUM_VALUE(c);
335             break;
336         case 'B':
337         case LA_FETCHLIMIT:
338             c = atoi(optarg);
339             ctl->fetchlimit = NUM_VALUE(c);
340             break;
341         case 'e':
342         case LA_EXPUNGE:
343             c = atoi(optarg);
344             ctl->expunge = NUM_VALUE(c);
345             break;
346         case 'm':
347         case LA_MDA:
348             ctl->mda = xstrdup(optarg);
349             ocount++;
350             break;
351
352         case 'T':
353         case LA_NETSEC:
354 #if NET_SECURITY
355             ctl->server.netsec = (void *)optarg;
356 #else
357             fprintf(stderr, "fetchmail: network security support is disabled\n");
358             errflag++;
359 #endif /* NET_SECURITY */
360             break;
361
362 #if defined(linux) && !INET6
363         case 'I':
364         case LA_INTERFACE:
365             interface_parse(optarg, &ctl->server);
366             break;
367         case 'M':
368         case LA_MONITOR:
369             ctl->server.monitor = xstrdup(optarg);
370             break;
371 #endif /* defined(linux) && !INET6 */
372
373         case 'y':
374         case LA_YYDEBUG:
375             yydebug = TRUE;
376             break;
377
378         case LA_SYSLOG:
379             errors_to_syslog = TRUE;
380             break;
381
382         case '?':
383         case LA_HELP:
384         default:
385             errflag++;
386         }
387     }
388
389     if (errflag || ocount > 1) {
390         /* squawk if syntax errors were detected */
391         fputs("usage:  fetchmail [options] [server ...]\n", stderr);
392         fputs("  Options are as follows:\n",stderr);
393         fputs("  -?, --help        display this option help\n", stderr);
394         fputs("  -V, --version     display version info\n", stderr);
395
396         fputs("  -c, --check       check for messages without fetching\n", stderr);
397         fputs("  -s, --silent      work silently\n", stderr);
398         fputs("  -v, --verbose     work noisily (diagnostic output)\n", stderr);
399         fputs("  -d, --daemon      run as a daemon once per n seconds\n", stderr);
400         fputs("  -N, --nodetach    don't detach daemon process\n", stderr);
401         fputs("  -q, --quit        kill daemon process\n", stderr);
402         fputs("  -L, --logfile     specify logfile name\n", stderr);
403         fputs("      --syslog      use syslog(3) for most messages when running as a daemon\n", stderr);
404         fputs("      --invisible   suppress Received line & enable host spoofing\n", stderr);
405         fputs("  -f, --fetchmailrc specify alternate run control file\n", stderr);
406         fputs("  -i, --idfile      specify alternate UIDs file\n", stderr);
407 #if defined(linux) && !INET6
408         fputs("  -I, --interface   interface required specification\n",stderr);
409         fputs("  -M, --monitor     monitor interface for activity\n",stderr);
410 #endif
411
412 #ifdef KERBEROS_V4
413         fputs("  -p, --protocol    specify pop2, pop3, imap, apop, rpop, kpop, etrn, imap-k4\n", stderr);
414 #else
415         fputs("  -p, --protocol    specify pop2, pop3, imap, apop, rpop, kpop, etrn\n", stderr);
416 #endif /* KERBEROS_V4 */
417         fputs("  -U, --uidl        force the use of UIDLs (pop3 only)\n", stderr);
418         fputs("  -P, --port        TCP/IP service port to connect to\n",stderr);
419         fputs("  -A, --auth        authentication type (password or kerberos)\n",stderr);
420         fputs("  -t, --timeout     server nonresponse timeout\n",stderr);
421         fputs("  -E, --envelope    envelope address header\n",stderr);
422         fputs("  -Q, --qvirtual    prefix to remove from local user id\n",stderr);
423
424         fputs("  -u, --username    specify users's login on server\n", stderr);
425         fputs("  -a, --all         retrieve old and new messages\n", stderr);
426         fputs("  -K, --nokeep      delete new messages after retrieval\n", stderr);
427         fputs("  -k, --keep        save new messages after retrieval\n", stderr);
428         fputs("  -F, --flush       delete old messages from server\n", stderr);
429         fputs("  -n, --norewrite   don't rewrite header addresses\n", stderr);
430         fputs("  -l, --limit       don't fetch messages over given size\n", stderr);
431
432 #if NET_SECURITY
433         fputs("  -T, --netsec      set IP security request\n", stderr);
434 #endif /* NET_SECURITY */
435         fputs("  -S, --smtphost    set SMTP forwarding host\n", stderr);
436         fputs("  -D, --smtpaddress set SMTP delivery domain to use\n", stderr);
437         fputs("  -b, --batchlimit  set batch limit for SMTP connections\n", stderr);
438         fputs("  -B, --fetchlimit  set fetch limit for server connections\n", stderr);
439         fputs("  -e, --expunge     set max deletions between expunges\n", stderr);
440         fputs("  -r, --folder      specify remote folder name\n", stderr);
441         return(-1);
442     }
443
444     return(optind);
445 }
446
447 /* options.c ends here */