1 /* Copyright 1993-95 by Carl Harris, Jr.
4 * Distribute freely, except: don't remove my name from the source or
5 * documentation (don't take credit for my work), mark your changes (don't
6 * get me blamed for your possible bugs), don't alter or remove this
7 * notice. May be sold if buildable source is provided to buyer. No
8 * warrantee of any kind, express or implied, is included with this
9 * software; use at your own risk, responsibility for damages (if any) to
10 * anyone resulting from the use of this software rests entirely with the
13 * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
14 * I'll try to keep a version up to date. I can be reached as follows:
15 * Carl Harris <ceharris@mal.com>
18 /***********************************************************************
21 programmer: Carl Harris, ceharris@mal.com
22 description: command-line option processing
25 Revision 1.1 1996/06/24 18:11:08 esr
28 Revision 1.4 1995/08/14 18:36:39 ceharris
29 Patches to support POP3's LAST command.
30 Final revisions for beta3 release.
32 Revision 1.3 1995/08/10 00:32:34 ceharris
33 Preparation for 3.0b3 beta release:
34 - added code for --kill/--keep, --limit, --protocol, --flush
35 options; --pop2 and --pop3 options now obsoleted by --protocol.
36 - added support for APOP authentication, including --with-APOP
37 argument for configure.
38 - provisional and broken support for RPOP
39 - added buffering to SockGets and SockRead functions.
40 - fixed problem of command-line options not being correctly
41 carried into the merged options record.
43 Revision 1.2 1995/08/09 01:32:51 ceharris
44 Version 3.0 beta 2 release.
46 - .poprc functionality
48 - multiple servers on the command line.
50 - Passwords showing up in ps output.
52 Revision 1.1 1995/08/08 01:01:21 ceharris
53 Added GNU-style long options processing.
54 Fixed password in 'ps' output problem.
55 Fixed various RCS tag blunders.
56 Integrated .poprc parser, lexer, etc into Makefile processing.
58 ***********************************************************************/
65 #include "popclient.h"
68 /* XXX -- Would like to use 'enum' here, but it causes type mismatch
69 problems many compilers */
79 #define LA_PROTOCOL 10
82 #define LA_USERNAME 13
83 #define LA_PASSWORD 14
84 #define LA_REMOTEFILE 15
85 #define LA_LOCALFILE 16
88 static char *shortoptions = "23VaKkvscl:Fd:f:u:p:r:o:";
89 static struct option longoptions[] = {
90 {"version", no_argument, (int *) 0, LA_VERSION },
91 {"all", no_argument, (int *) 0, LA_ALL },
92 {"kill", no_argument, (int *) 0, LA_KILL },
93 {"keep", no_argument, (int *) 0, LA_KEEP },
94 {"verbose", no_argument, (int *) 0, LA_VERBOSE },
95 {"silent", no_argument, (int *) 0, LA_SILENT },
96 {"stdout", no_argument, (int *) 0, LA_STDOUT },
97 {"limit", required_argument, (int *) 0, LA_LIMIT },
98 {"flush", no_argument, (int *) 0, LA_FLUSH },
99 {"protocol", required_argument, (int *) 0, LA_PROTOCOL },
100 {"proto", required_argument, (int *) 0, LA_PROTOCOL },
101 {"daemon", required_argument, (int *) 0, LA_DAEMON },
102 {"poprc", required_argument, (int *) 0, LA_POPRC },
103 {"user", required_argument, (int *) 0, LA_USERNAME },
104 {"username", required_argument, (int *) 0, LA_USERNAME },
105 {"password", required_argument, (int *) 0, LA_PASSWORD },
106 {"remote", required_argument, (int *) 0, LA_REMOTEFILE },
107 {"local", required_argument, (int *) 0, LA_LOCALFILE },
108 {(char *) 0, no_argument, (int *) 0, 0 }
112 /*********************************************************************
113 function: parsecmdline
114 description: parse/validate the command line options.
117 argv argument strings.
118 options pointer to a struct optrec to receive the parsed
121 return value: if positive, argv index of last parsed option + 1
122 (presumes one or more server names follows).
123 if zero, the command line switches are such that
124 no server names are required (e.g. --version).
125 if negative, the command line is has one or more
129 *********************************************************************/
131 int parsecmdline (argc,argv,options)
134 struct optrec *options;
137 int fflag = 0; /* TRUE when -o or -c has been specified */
138 int errflag = 0; /* TRUE when a syntax error is detected */
140 int got_kill = 0; /* TRUE when --kill is specified */
142 extern int optind, opterr; /* defined in getopt(2) */
143 extern char *optarg; /* defined in getopt(2) */
145 bzero(options,sizeof(struct optrec)); /* start clean */
148 (c = getopt_long(argc,argv,shortoptions,
149 longoptions,&option_index)) != -1) {
153 options->whichpop = P_POP2;
156 options->whichpop = P_POP3;
160 options->versioninfo = !0;
164 options->fetchall = !0;
178 options->verbose = !0;
182 options->silent = !0;
190 options->foldertype = OF_STDOUT;
195 options->limit = atoi(optarg);
196 if (options->limit < 0) {
197 fprintf(stderr,"Line count limit must be non-negative");
206 /* XXX -- should probably use a table lookup here */
207 if (strcasecmp(optarg,"pop2") == 0)
208 options->whichpop = P_POP2;
209 else if (strcasecmp(optarg,"pop3") == 0)
210 options->whichpop = P_POP3;
211 else if (strcasecmp(optarg,"imap") == 0)
212 options->whichpop = P_IMAP;
213 else if (strcasecmp(optarg,"apop") == 0)
214 options->whichpop = P_APOP;
215 else if (strcasecmp(optarg,"rpop") == 0)
216 options->whichpop = P_RPOP;
218 fprintf(stderr,"Invalid protocol '%s'\n specified.\n", optarg);
224 fprintf(stderr,"Got daemonize option with argument '%s'\n",optarg);
228 options->poprcfile = (char *) xmalloc(strlen(optarg)+1);
229 strcpy(options->poprcfile,optarg);
233 strncpy(options->userid,optarg,sizeof(options->userid)-1);
237 strncpy(options->password,optarg,sizeof(options->password)-1);
238 for (i = strlen(options->password)-1; i >= 0; i--)
239 argv[optind-1][i] = '*';
247 options->foldertype = OF_USERMBOX;
248 strncpy(options->userfolder,optarg,sizeof(options->userfolder)-1);
253 strncpy(options->remotefolder,optarg,sizeof(options->remotefolder)-1);
260 if (!options->versioninfo)
261 /* if options don't obviate the need, we must have server name(s)
262 left on the command line. */
271 /* squawk if syntax errors were detected */
272 fputs("usage: popclient [options] server [server ...]\n", stderr);
273 fputs(" options\n",stderr);
274 fputs(" -2 use POP2 protocol\n", stderr);
275 fputs(" -3 use POP3 protocol\n", stderr);
276 fputs(" --protocol specify pop2, pop3, imap, apop, or rpop\n",
278 fputs(" -V, --version display version info\n", stderr);
279 fputs(" -a, --all retrieve old and new messages\n", stderr);
280 fputs(" -F, --flush delete old messages from server\n", stderr);
281 fputs(" -K, --kill delete new messages after retrieval\n", stderr);
282 fputs(" -k, --keep save new messages after retrieval\n", stderr);
283 fputs(" -l, --limit retrieve at most n message lines\n", stderr);
284 fputs(" -s, --silent work silently\n", stderr);
285 fputs(" -v, --verbose work noisily (diagnostic output)\n", stderr);
286 fputs(" -d, --daemon run as a daemon\n", stderr);
287 fputs(" -f, --poprc specify alternate config file\n", stderr);
288 fputs(" -u, --username specify server user ID\n", stderr);
289 fputs(" -p, --password specify server password\n", stderr);
290 fputs(" -c, --stdout write received mail to stdout\n", stderr);
291 fputs(" -o, --local specify filename for received mail\n", stderr);
292 fputs(" -r, --remote specify remote folder name\n", stderr);
296 if (options->limit && !got_kill)
305 /*********************************************************************
306 function: setdefaults
307 description: set reasonable default values for unspecified options.
309 options option values parsed from the command-line; unspeci-
310 fied options must be filled with zero.
312 return value: zero if defaults were successfully set, else non-zero
313 (indicates a problem reading /etc/passwd).
315 globals: writes outlevel.
316 *********************************************************************/
318 int setdefaults (options)
319 struct optrec *options;
325 bzero(options,sizeof(*options));
327 if ((pw = getpwuid(uid = getuid())) == NULL) {
328 fprintf(stderr,"No passwd entry for uid %d\n",uid);
331 /* save the login name for delivery use */
332 strcpy(options->loginid,pw->pw_name);
334 options->whichpop = DEF_PROTOCOL;
335 options->foldertype = OF_SYSMBOX;
337 #if defined(KEEP_IS_DEFAULT)
343 strcpy(options->userid,pw->pw_name);
346 (char *) xmalloc(strlen(pw->pw_dir)+strlen(POPRC_NAME)+2);
348 strcpy(options->poprcfile, pw->pw_dir);
349 strcat(options->poprcfile, "/");
350 strcat(options->poprcfile, POPRC_NAME);
357 /******************************************************************
358 function: getnextserver
359 description: read next server name from the command line.
363 optind as returned by parsecmdline and this function.
365 ret. value: next server name from command line or NULL if all
366 server names have been retrieved.
369 *****************************************************************/
370 char *getnextserver (argc,argv,optind)
375 if (*optind >= argc) {
376 /* no more servers */
380 return(argv[(*optind)++]);