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: main driver module for popclient
25 Revision 1.1 1996/06/24 18:32:00 esr
28 Revision 1.7 1995/09/07 22:37:34 ceharris
29 Preparation for 3.0b4 release.
31 Revision 1.6 1995/08/14 18:36:43 ceharris
32 Patches to support POP3's LAST command.
33 Final revisions for beta3 release.
35 Revision 1.5 1995/08/10 00:32:39 ceharris
36 Preparation for 3.0b3 beta release:
37 - added code for --kill/--keep, --limit, --protocol, --flush
38 options; --pop2 and --pop3 options now obsoleted by --protocol.
39 - added support for APOP authentication, including --with-APOP
40 argument for configure.
41 - provisional and broken support for RPOP
42 - added buffering to SockGets and SockRead functions.
43 - fixed problem of command-line options not being correctly
44 carried into the merged options record.
46 Revision 1.4 1995/08/09 01:32:56 ceharris
47 Version 3.0 beta 2 release.
49 - .poprc functionality
51 - multiple servers on the command line.
53 - Passwords showing up in ps output.
55 Revision 1.3 1995/08/08 01:01:25 ceharris
56 Added GNU-style long options processing.
57 Fixed password in 'ps' output problem.
58 Fixed various RCS tag blunders.
59 Integrated .poprc parser, lexer, etc into Makefile processing.
61 ***********************************************************************/
68 #if defined(STDC_HEADERS)
73 #if defined(HAVE_UNISTD_H)
81 #include <sys/types.h>
87 #include "popclient.h"
90 #define RELEASE_TAG "3.0b6"
92 #ifdef HAVE_PROTOTYPES
93 /* prototypes for internal functions */
94 int showoptions (struct optrec *options);
95 int parseMDAargs (struct optrec *options);
96 int showversioninfo (void);
99 /* Controls the detail of status/progress messages written to stderr */
100 int outlevel; /* see the O_.* constants in popclient.h */
102 /* args for the MDA, parsed out in the usual fashion by parseMDAargs() */
104 char *mda_argv [MDA_ARGCOUNT + 2];
110 /*********************************************************************
112 description: main driver routine
114 argc argument count as passed by runtime startup code.
115 argv argument strings as passed by runtime startup code.
117 return value: an exit status code for the shell -- see the
118 PS_.* constants defined above.
119 calls: parsecmdline, setdefaults, openuserfolder, doPOP2.
121 *********************************************************************/
128 struct optrec cmd_opts, def_opts, merged_opts;
133 parsestatus = parsecmdline(argc,argv,&cmd_opts);
134 if (parsestatus >= 0) {
135 setoutlevel(&cmd_opts);
136 if (!cmd_opts.versioninfo)
137 if (setdefaults(&def_opts) == 0) {
138 if (prc_parse_file(prc_getpathname(&cmd_opts,&def_opts)) == 0) {
139 while ((servername = getnextserver(argc, argv, &parsestatus))
141 if (outlevel != O_SILENT)
142 fprintf(stderr, "querying %s\n", servername);
145 prc_mergeoptions(servername, &cmd_opts, &def_opts, &merged_opts);
146 parseMDAargs(&merged_opts);
147 switch (merged_opts.whichpop) {
149 popstatus = doPOP2(servername, &merged_opts);
153 popstatus = doPOP3(servername, &merged_opts);
156 fprintf(stderr,"unsupported protocol selected.\n");
161 popstatus = PS_SYNTAX;
164 popstatus = PS_UNDEFINED;
169 popstatus = PS_SYNTAX;
176 /*********************************************************************
177 function: showversioninfo
178 description: display program release and compiler info
183 *********************************************************************/
185 int showversioninfo()
187 printf("popclient release %s\n",RELEASE_TAG);
193 /******************************************************************
194 function: setoutlevel
195 description: set output verbosity level.
197 options command-line options.
200 globals: writes outlevel.
202 *****************************************************************/
204 int setoutlevel (options)
205 struct optrec *options;
207 if (options->verbose)
208 outlevel = O_VERBOSE;
209 else if (options->silent)
217 /*********************************************************************
218 function: openuserfolder
219 description: open the file to which the retrieved messages will
220 be appended. Do NOT call when options->foldertype
224 options fully-determined options (i.e. parsed, defaults invoked,
227 return value: file descriptor for the open file, else -1.
230 *********************************************************************/
232 int openuserfolder (options)
233 struct optrec *options;
237 if (options->foldertype == OF_STDOUT)
239 else /* options->foldertype == OF_USERMBOX */
240 if ((fd = open(options->userfolder,O_CREAT|O_WRONLY|O_APPEND,0600)) >= 0) {
244 perror("popclient: openuserfolder: open()");
252 /*********************************************************************
253 function: openmailpipe
254 description: open a one-way pipe to the mail delivery agent.
256 options fully-determined options (i.e. parsed, defaults invoked,
259 return value: open file descriptor for the pipe or -1.
261 globals: reads mda_argv.
262 *********************************************************************/
264 int openmailpipe (options)
265 struct optrec *options;
269 char binmailargs [80];
271 if (pipe(pipefd) < 0) {
272 perror("popclient: openmailpipe: pipe");
275 if ((childpid = fork()) < 0) {
276 perror("popclient: openmailpipe: fork");
279 else if (childpid == 0) {
281 /* in child process space */
282 close(pipefd[1]); /* close the 'write' end of the pipe */
283 close(0); /* get rid of inherited stdin */
284 if (dup(pipefd[0]) != 0) {
285 fputs("popclient: openmailpipe: dup() failed\n",stderr);
289 execv(MDA_PATH,mda_argv);
291 /* if we got here, an error occurred */
292 perror("popclient: openmailpipe: exec");
297 /* in the parent process space */
298 close(pipefd[0]); /* close the 'read' end of the pipe */
304 /*********************************************************************
305 function: closeuserfolder
306 description: close the user-specified mail folder.
308 fd mail folder descriptor.
310 return value: zero if success else -1.
313 *********************************************************************/
315 int closeuserfolder(fd)
320 if (fd != 1) { /* not stdout */
327 perror("popclient: closeuserfolder: close");
334 /*********************************************************************
335 function: closemailpipe
336 description: close pipe to the mail delivery agent.
338 options fully-determined options record
341 return value: 0 if success, else -1.
344 *********************************************************************/
346 int closemailpipe (fd)
353 #if defined(STDC_HEADERS)
354 childpid = wait(NULL);
356 childpid = wait((int *) 0);
359 perror("popclient: closemailpipe: close");
366 /*********************************************************************
367 function: parseMDAargs
368 description: parse the argument string given in MDA_ARGS into
369 a regular *argv[] array.
371 options fully-determined options record pointer.
375 globals: writes mda_argv.
376 *********************************************************************/
378 int parseMDAargs (options)
379 struct optrec *options;
384 /* first put the MDA alias in as argv[0] */
385 mda_argv[0] = MDA_ALIAS;
389 /* make a writeable copy of MDA_ARGS */
390 argp = strcpy((char *) malloc(strlen(MDA_ARGS)+1), MDA_ARGS);
392 while (*argp != '\0' && isspace(*argp)) /* skip null first arg */
395 /* now punch nulls into the delimiting whitespace in the args */
400 mda_argv[argi] = argp; /* store pointer to this argument */
402 /* find end of this argument */
403 while (!(*argp == '\0' || isspace(*argp)))
406 /* punch in a null terminator */
410 /* check for macros */
411 if (strcmp(mda_argv[argi],"$u") == 0)
413 strcpy((char *) malloc(strlen(options->loginid)+1),options->loginid);
415 ; /* no macros to expand */
418 mda_argv[argi] = (char *) 0;
422 mda_argv[1] = (char *) 0;