Diff of /fetchmail.c [000000] .. [6124ab] Maximize Restore

  Switch to side-by-side view

--- a
+++ b/fetchmail.c
@@ -0,0 +1,426 @@
+/* Copyright 1993-95 by Carl Harris, Jr.
+ * All rights reserved
+ *
+ * Distribute freely, except: don't remove my name from the source or
+ * documentation (don't take credit for my work), mark your changes (don't
+ * get me blamed for your possible bugs), don't alter or remove this
+ * notice.  May be sold if buildable source is provided to buyer.  No
+ * warrantee of any kind, express or implied, is included with this
+ * software; use at your own risk, responsibility for damages (if any) to
+ * anyone resulting from the use of this software rests entirely with the
+ * user.
+ *
+ * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
+ * I'll try to keep a version up to date.  I can be reached as follows:
+ * Carl Harris <ceharris@mal.com>
+ */
+
+/***********************************************************************
+  module:       popclient.c
+  project:      popclient
+  programmer:   Carl Harris, ceharris@mal.com
+  description:	main driver module for popclient
+
+  $Log: fetchmail.c,v $
+  Revision 1.1  1996/06/24 18:32:00  esr
+  Initial revision
+
+  Revision 1.7  1995/09/07 22:37:34  ceharris
+  Preparation for 3.0b4 release.
+
+  Revision 1.6  1995/08/14 18:36:43  ceharris
+  Patches to support POP3's LAST command.
+  Final revisions for beta3 release.
+
+  Revision 1.5  1995/08/10 00:32:39  ceharris
+  Preparation for 3.0b3 beta release:
+  -	added code for --kill/--keep, --limit, --protocol, --flush
+  	options; --pop2 and --pop3 options now obsoleted by --protocol.
+  - 	added support for APOP authentication, including --with-APOP
+  	argument for configure.
+  -	provisional and broken support for RPOP
+  -	added buffering to SockGets and SockRead functions.
+  -	fixed problem of command-line options not being correctly
+  	carried into the merged options record.
+
+  Revision 1.4  1995/08/09 01:32:56  ceharris
+  Version 3.0 beta 2 release.
+  Added
+  -	.poprc functionality
+  -	GNU long options
+  -	multiple servers on the command line.
+  Fixed
+  -	Passwords showing up in ps output.
+
+  Revision 1.3  1995/08/08 01:01:25  ceharris
+  Added GNU-style long options processing.
+  Fixed password in 'ps' output problem.
+  Fixed various RCS tag blunders.
+  Integrated .poprc parser, lexer, etc into Makefile processing.
+
+ ***********************************************************************/
+
+
+#include <config.h>
+
+#include <stdio.h>
+
+#if defined(STDC_HEADERS)
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "popclient.h"
+
+/* release info */
+#define         RELEASE_TAG	"3.0b6"
+
+#ifdef HAVE_PROTOTYPES
+/* prototypes for internal functions */
+int showoptions (struct optrec *options);
+int parseMDAargs (struct optrec *options);
+int showversioninfo (void);
+#endif
+
+/* Controls the detail of status/progress messages written to stderr */
+int outlevel;      /* see the O_.* constants in popclient.h */
+
+/* args for the MDA, parsed out in the usual fashion by parseMDAargs() */
+#ifdef MDA_ARGS
+char *mda_argv [MDA_ARGCOUNT + 2];
+#else
+char *mda_argv [2];
+#endif
+
+
+/*********************************************************************
+  function:      main
+  description:   main driver routine 
+  arguments:     
+    argc         argument count as passed by runtime startup code.
+    argv         argument strings as passed by runtime startup code.
+
+  return value:  an exit status code for the shell -- see the 
+                 PS_.* constants defined above.
+  calls:         parsecmdline, setdefaults, openuserfolder, doPOP2.
+  globals:       none.
+ *********************************************************************/
+
+main (argc,argv)
+int argc;
+char **argv;
+{ 
+  int mboxfd;
+  struct optrec cmd_opts, def_opts, merged_opts;
+  int popstatus;
+  int parsestatus;
+  char *servername; 
+
+  parsestatus = parsecmdline(argc,argv,&cmd_opts);
+  if (parsestatus >= 0) {
+    setoutlevel(&cmd_opts);
+    if (!cmd_opts.versioninfo)
+      if (setdefaults(&def_opts) == 0) {
+        if (prc_parse_file(prc_getpathname(&cmd_opts,&def_opts)) == 0) {
+          while ((servername = getnextserver(argc, argv, &parsestatus)) 
+                 != (char *) 0) {
+            if (outlevel != O_SILENT) 
+              fprintf(stderr, "querying %s\n", servername);
+            else
+              ;
+            prc_mergeoptions(servername, &cmd_opts, &def_opts, &merged_opts);
+            parseMDAargs(&merged_opts);
+	    switch (merged_opts.whichpop) {
+              case P_POP2:
+                popstatus = doPOP2(servername, &merged_opts);
+                break;
+              case P_POP3:
+              case P_APOP:
+                popstatus = doPOP3(servername, &merged_opts);
+                break;
+              default:
+                fprintf(stderr,"unsupported protocol selected.\n");
+            }
+          }
+        }
+	else
+          popstatus = PS_SYNTAX;
+      } 
+      else
+        popstatus = PS_UNDEFINED;
+    else
+      showversioninfo();
+  }
+  else
+    popstatus = PS_SYNTAX;
+
+  exit(popstatus);
+}
+    
+
+ 
+/*********************************************************************
+  function:      showversioninfo
+  description:   display program release and compiler info
+  arguments:     none.
+  return value:  none.
+  calls:         none.
+  globals:       none.
+ *********************************************************************/
+
+int showversioninfo()
+{
+  printf("popclient release %s\n",RELEASE_TAG);
+}
+
+
+
+
+/******************************************************************
+  function:	setoutlevel
+  description:	set output verbosity level.
+  arguments:
+    options	command-line options.
+
+  ret. value:	none.
+  globals:	writes outlevel.
+  calls:	none.
+ *****************************************************************/
+
+int setoutlevel (options)
+struct optrec *options;
+{
+  if (options->verbose) 
+    outlevel = O_VERBOSE;
+  else if (options->silent)
+    outlevel = O_SILENT;
+  else
+    outlevel = O_NORMAL;
+}
+
+
+
+/*********************************************************************
+  function:      openuserfolder
+  description:   open the file to which the retrieved messages will
+                 be appended.  Do NOT call when options->foldertype
+                 is OF_SYSMBOX.
+
+  arguments:     
+    options      fully-determined options (i.e. parsed, defaults invoked,
+                 etc).
+
+  return value:  file descriptor for the open file, else -1.
+  calls:         none.
+  globals:       none.
+ *********************************************************************/
+
+int openuserfolder (options)
+struct optrec *options;
+{
+  int fd;
+
+  if (options->foldertype == OF_STDOUT)
+    return(1);
+  else    /* options->foldertype == OF_USERMBOX */
+    if ((fd = open(options->userfolder,O_CREAT|O_WRONLY|O_APPEND,0600)) >= 0) {
+      return(fd);
+    }
+    else {
+      perror("popclient: openuserfolder: open()");
+      return(-1);
+    }
+  
+}
+
+
+
+/*********************************************************************
+  function:      openmailpipe
+  description:   open a one-way pipe to the mail delivery agent.
+  arguments:     
+    options      fully-determined options (i.e. parsed, defaults invoked,
+                 etc).
+
+  return value:  open file descriptor for the pipe or -1.
+  calls:         none.
+  globals:       reads mda_argv.
+ *********************************************************************/
+
+int openmailpipe (options)
+struct optrec *options;
+{
+  int pipefd [2];
+  int childpid;
+  char binmailargs [80];
+
+  if (pipe(pipefd) < 0) {
+    perror("popclient: openmailpipe: pipe");
+    return(-1);
+  }
+  if ((childpid = fork()) < 0) {
+    perror("popclient: openmailpipe: fork");
+    return(-1);
+  }
+  else if (childpid == 0) {
+
+    /* in child process space */
+    close(pipefd[1]);  /* close the 'write' end of the pipe */
+    close(0);          /* get rid of inherited stdin */
+    if (dup(pipefd[0]) != 0) {
+      fputs("popclient: openmailpipe: dup() failed\n",stderr);
+      exit(1);
+    }
+
+    execv(MDA_PATH,mda_argv);
+
+    /* if we got here, an error occurred */
+    perror("popclient: openmailpipe: exec");
+    return(-1);
+
+  }
+
+  /* in the parent process space */
+  close(pipefd[0]);  /* close the 'read' end of the pipe */
+  return(pipefd[1]);
+}
+
+
+
+/*********************************************************************
+  function:      closeuserfolder
+  description:   close the user-specified mail folder.
+  arguments:     
+    fd           mail folder descriptor.
+
+  return value:  zero if success else -1.
+  calls:         none.
+  globals:       none.
+ *********************************************************************/
+
+int closeuserfolder(fd)
+int fd;
+{
+  int err;
+
+  if (fd != 1) {   /* not stdout */
+    err = close(fd);
+  }   
+  else
+    err = 0;
+  
+  if (err)
+    perror("popclient: closeuserfolder: close");
+
+  return(err);
+}
+
+
+
+/*********************************************************************
+  function:      closemailpipe
+  description:   close pipe to the mail delivery agent.
+  arguments:     
+    options      fully-determined options record
+    fd           pipe descriptor.
+
+  return value:  0 if success, else -1.
+  calls:         none.
+  globals:       none.
+ *********************************************************************/
+
+int closemailpipe (fd)
+int fd;
+{
+  int err;
+  int childpid;
+
+  err = close(fd);
+#if defined(STDC_HEADERS)
+  childpid = wait(NULL);
+#else
+  childpid = wait((int *) 0);
+#endif
+  if (err)
+    perror("popclient: closemailpipe: close");
+
+  return(err);
+}
+
+
+
+/*********************************************************************
+  function:      parseMDAargs
+  description:   parse the argument string given in MDA_ARGS into
+                 a regular *argv[] array.
+  arguments:
+    options      fully-determined options record pointer.
+
+  return value:  none.
+  calls:         none.
+  globals:       writes mda_argv.
+ *********************************************************************/
+
+int parseMDAargs (options)
+struct optrec *options;
+{
+  int argi;
+  char *argp;
+
+  /* first put the MDA alias in as argv[0] */
+  mda_argv[0] = MDA_ALIAS;
+  
+#ifdef MDA_ARGS
+
+  /* make a writeable copy of MDA_ARGS */
+  argp = strcpy((char *) malloc(strlen(MDA_ARGS)+1), MDA_ARGS);
+  
+  while (*argp != '\0' && isspace(*argp))	/* skip null first arg */
+    argp++;					
+
+  /* now punch nulls into the delimiting whitespace in the args */
+  for (argi = 1;  
+       *argp != '\0';
+       argi++) {
+
+    mda_argv[argi] = argp;     /* store pointer to this argument */
+
+    /* find end of this argument */
+    while (!(*argp == '\0' || isspace(*argp)))
+      argp++;
+
+    /* punch in a null terminator */
+    if (*argp != '\0')
+      *(argp++) = '\0';  
+ 
+    /* check for macros */
+    if (strcmp(mda_argv[argi],"$u") == 0)
+      mda_argv[argi] = 
+        strcpy((char *) malloc(strlen(options->loginid)+1),options->loginid);
+    else
+      ;  /* no macros to expand */
+
+  }
+  mda_argv[argi] = (char *) 0;
+
+#else 
+
+  mda_argv[1] = (char *) 0;
+
+#endif
+
+}