Undo previous change.
[bpt/emacs.git] / lib-src / fakemail.c
index a78fbe8..400861d 100644 (file)
@@ -1,11 +1,11 @@
 /* sendmail-like interface to /bin/mail for system V,
 /* sendmail-like interface to /bin/mail for system V,
-   Copyright (C) 1985 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -15,18 +15,28 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #define NO_SHORTNAMES
 
 
 #define NO_SHORTNAMES
-#include "../src/config.h"
+#include <../src/config.h>
 
 #if defined (BSD) && !defined (BSD4_1) && !defined (USE_FAKEMAIL)
 /* This program isnot used in BSD, so just avoid loader complaints.  */
 
 #if defined (BSD) && !defined (BSD4_1) && !defined (USE_FAKEMAIL)
 /* This program isnot used in BSD, so just avoid loader complaints.  */
+int
 main ()
 {
 main ()
 {
+    return 0;
 }
 #else /* not BSD 4.2 (or newer) */
 }
 #else /* not BSD 4.2 (or newer) */
+#ifdef MSDOS
+int
+main ()
+{
+    return 0;
+}
+#else /* not MSDOS */
 /* This conditional contains all the rest of the file.  */
 
 /* These are defined in config in some versions. */
 /* This conditional contains all the rest of the file.  */
 
 /* These are defined in config in some versions. */
@@ -42,6 +52,10 @@ main ()
 #undef close
 #endif
 
 #undef close
 #endif
 
+#ifdef WINDOWSNT
+#include "ntlib.h"
+#endif
+
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
@@ -123,7 +137,6 @@ static boolean no_problems = true;
 
 extern FILE *popen ();
 extern int fclose (), pclose ();
 
 extern FILE *popen ();
 extern int fclose (), pclose ();
-extern char *malloc (), *realloc ();
 
 #ifdef CURRENT_USER
 extern struct passwd *getpwuid ();
 
 #ifdef CURRENT_USER
 extern struct passwd *getpwuid ();
@@ -160,23 +173,23 @@ fatal (s1, s2)
 
 /* Like malloc but get fatal error if memory is exhausted.  */
 
 
 /* Like malloc but get fatal error if memory is exhausted.  */
 
-static char *
+static long *
 xmalloc (size)
      int size;
 {
 xmalloc (size)
      int size;
 {
-  char *result = malloc (((unsigned) size));
-  if (result == ((char *) NULL))
+  long *result = (long *) malloc (((unsigned) size));
+  if (result == ((long *) NULL))
     fatal ("virtual memory exhausted", 0);
   return result;
 }
 
     fatal ("virtual memory exhausted", 0);
   return result;
 }
 
-static char *
+static long *
 xrealloc (ptr, size)
 xrealloc (ptr, size)
-     char *ptr;
+     long *ptr;
      int size;
 {
      int size;
 {
-  char *result = realloc (ptr, ((unsigned) size));
-  if (result == ((char *) NULL))
+  long *result = (long *) realloc (ptr, ((unsigned) size));
+  if (result == ((long *) NULL))
     fatal ("virtual memory exhausted");
   return result;
 }
     fatal ("virtual memory exhausted");
   return result;
 }
@@ -211,8 +224,8 @@ readline (linebuffer, stream)
        {
          linebuffer->size *= 2;
          buffer = ((char *) xrealloc (buffer, linebuffer->size));
        {
          linebuffer->size *= 2;
          buffer = ((char *) xrealloc (buffer, linebuffer->size));
-         p += buffer - linebuffer->buffer;
-         end += buffer - linebuffer->buffer;
+         p = buffer + (p - linebuffer->buffer);
+         end = buffer + linebuffer->size;
          linebuffer->buffer = buffer;
        }
       if (c < 0 || c == '\n')
          linebuffer->buffer = buffer;
        }
       if (c < 0 || c == '\n')
@@ -226,6 +239,12 @@ readline (linebuffer, stream)
   return p - buffer;
 }
 \f
   return p - buffer;
 }
 \f
+/* Extract a colon-terminated keyword from the string FIELD.
+   Return that keyword as a string stored in a static buffer.
+   Store the address of the rest of the string into *REST.
+
+   If there is no keyword, return NULL and don't alter *REST.  */
+
 char *
 get_keyword (field, rest)
      register char *field;
 char *
 get_keyword (field, rest)
      register char *field;
@@ -237,18 +256,22 @@ get_keyword (field, rest)
 
   ptr = &keyword[0];
   c = *field++;
 
   ptr = &keyword[0];
   c = *field++;
-  if ((isspace (c)) || (c == ':'))
+  if (isspace (c) || c == ':')
     return ((char *) NULL);
     return ((char *) NULL);
-  *ptr++ = ((islower (c)) ? (toupper (c)) : c);
-  while (((c = *field++) != ':') && (!(isspace (c))))
-    *ptr++ = ((islower (c)) ? (toupper (c)) : c);
+  *ptr++ = (islower (c) ? toupper (c) : c);
+  while (((c = *field++) != ':') && ! isspace (c))
+    *ptr++ = (islower (c) ? toupper (c) : c);
   *ptr++ = '\0';
   *ptr++ = '\0';
-  while (isspace (c)) c = *field++;
-  if (c != ':') return ((char *) NULL);
+  while (isspace (c))
+    c = *field++;
+  if (c != ':')
+    return ((char *) NULL);
   *rest = field;
   return &keyword[0];
 }
 
   *rest = field;
   return &keyword[0];
 }
 
+/* Nonzero if the string FIELD starts with a colon-terminated keyword.  */
+
 boolean
 has_keyword (field)
      char *field;
 boolean
 has_keyword (field)
      char *field;
@@ -257,6 +280,16 @@ has_keyword (field)
   return (get_keyword (field, &ignored) != ((char *) NULL));
 }
 
   return (get_keyword (field, &ignored) != ((char *) NULL));
 }
 
+/* Store the string FIELD, followed by any lines in THE_LIST,
+   into the buffer WHERE.
+   Concatenate lines, putting just a space between them.
+   Delete everything contained in parentheses.
+   When a recipient name contains <...>, we discard
+   everything except what is inside the <...>.
+
+   We don't pay attention to overflowing WHERE;
+   the caller has to make it big enough.  */
+
 char *
 add_field (the_list, field, where)
      line_list the_list;
 char *
 add_field (the_list, field, where)
      line_list the_list;
@@ -265,17 +298,48 @@ add_field (the_list, field, where)
   register char c;
   while (true)
     {
   register char c;
   while (true)
     {
+      char *this_recipient_where;
+      int in_quotes = 0;
+
       *where++ = ' ';
       *where++ = ' ';
+      this_recipient_where = where;
+
       while ((c = *field++) != '\0')
        {
       while ((c = *field++) != '\0')
        {
-         if (c == '(')
+         if (c == '\\')
+           *where++ = c;
+         else if (c == '"')
+           {
+             in_quotes = ! in_quotes;
+             *where++ = c;
+           }
+         else if (in_quotes)
+           *where++ = c;
+         else if (c == '(')
            {
              while (*field && *field != ')') ++field;
            {
              while (*field && *field != ')') ++field;
-             if (! (*field++)) break; /* no closer */
-             if (! (*field))   break; /* closerNULL */
-             c = *field;
+             if (! (*field++)) break; /* no close */
+             continue;
+           }
+         else if (c == ',')
+           {
+             *where++ = ' ';
+             /* When we get to the end of one recipient,
+                don't discard it if the next one has <...>.  */
+             this_recipient_where = where;
+           }
+         else if (c == '<')
+           /* Discard everything we got before the `<'.  */
+           where = this_recipient_where;
+         else if (c == '>')
+           /* Discard the rest of this name that follows the `>'.  */
+           {
+             while (*field && *field != ',') ++field;
+             if (! (*field++)) break; /* no comma */
+             continue;
            }
            }
-         *where++ = ((c == ','||c=='>'||c=='<') ? ' ' : c);
+         else
+           *where++ = c;
        }
       if (the_list == NIL) break;
       field = the_list->string;
        }
       if (the_list == NIL) break;
       field = the_list->string;
@@ -416,7 +480,7 @@ put_line (string)
        {
          char *breakpos;
 
        {
          char *breakpos;
 
-         /* Find the last char that fits. */
+         /* Find the last char that fits.  */
          for (breakpos = s; *breakpos && column < 78; ++breakpos)
            {
              if (*breakpos == '\t')
          for (breakpos = s; *breakpos && column < 78; ++breakpos)
            {
              if (*breakpos == '\t')
@@ -424,15 +488,20 @@ put_line (string)
              else
                column++;
            }
              else
                column++;
            }
-         /* Back up to just after the last comma that fits.  */
-         while (breakpos != s && breakpos[-1] != ',') --breakpos;
-         if (breakpos == s)
+         /* If we didn't reach end of line, break the line.  */
+         if (*breakpos)
            {
            {
-             /* If no comma fits, move past the first address anyway.  */
-             while (*breakpos != 0 && *breakpos != ',') ++breakpos;
-             if (*breakpos != 0)
-               /* Include the comma after it.  */
-               ++breakpos;
+             /* Back up to just after the last comma that fits.  */
+             while (breakpos != s && breakpos[-1] != ',') --breakpos;
+
+             if (breakpos == s)
+               {
+                 /* If no comma fits, move past the first address anyway.  */
+                 while (*breakpos != 0 && *breakpos != ',') ++breakpos;
+                 if (*breakpos != 0)
+                   /* Include the comma after it.  */
+                   ++breakpos;
+               }
            }
          /* Output that much, then break the line.  */
          fwrite (s, 1, breakpos - s, rem->handle);
            }
          /* Output that much, then break the line.  */
          fwrite (s, 1, breakpos - s, rem->handle);
@@ -451,6 +520,10 @@ put_line (string)
 \f
 #define mail_error error
 
 \f
 #define mail_error error
 
+/* Handle an FCC field.  FIELD is the text of the first line (after
+   the header name), and THE_LIST holds the continuation lines if any.
+   Call open_a_file for each file.  */
+
 void
 setup_files (the_list, field)
      register line_list the_list;
 void
 setup_files (the_list, field)
      register line_list the_list;
@@ -460,18 +533,18 @@ setup_files (the_list, field)
   register char c;
   while (true)
     {
   register char c;
   while (true)
     {
-      while (((c = *field) != '\0') &&
-            ((c == ' ') ||
-             (c == '\t') ||
-             (c == ',')))
+      while (((c = *field) != '\0')
+            && (c == ' '
+                || c == '\t'
+                || c == ','))
        field += 1;
       if (c != '\0')
        {
          start = field;
        field += 1;
       if (c != '\0')
        {
          start = field;
-         while (((c = *field) != '\0') &&
-                (c != ' ') &&
-                (c != '\t') &&
-                (c != ','))
+         while (((c = *field) != '\0')
+                && c != ' '
+                && c != '\t'
+                && c != ',')
            field += 1;
          *field = '\0';
          if (!open_a_file (start))
            field += 1;
          *field = '\0';
          if (!open_a_file (start))
@@ -479,12 +552,16 @@ setup_files (the_list, field)
          *field = c;
          if (c != '\0') continue;
        }
          *field = c;
          if (c != '\0') continue;
        }
-      if (the_list == ((line_list) NULL)) return;
+      if (the_list == ((line_list) NULL))
+       return;
       field = the_list->string;
       the_list = the_list->continuation;
     }
 }
 \f
       field = the_list->string;
       the_list = the_list->continuation;
     }
 }
 \f
+/* Compute the total size of all recipient names stored in THE_HEADER.
+   The result says how big to make the buffer to pass to parse_header.  */
+
 int
 args_size (the_header)
      header the_header;
 int
 args_size (the_header)
      header the_header;
@@ -496,9 +573,9 @@ args_size (the_header)
     {
       char *field;
       register char *keyword = get_keyword (the_header->text->string, &field);
     {
       char *field;
       register char *keyword = get_keyword (the_header->text->string, &field);
-      if ((strcmp (keyword, "TO") == 0) ||
-         (strcmp (keyword, "CC") == 0) ||
-         (strcmp (keyword, "BCC") == 0))
+      if ((strcmp (keyword, "TO") == 0)
+         || (strcmp (keyword, "CC") == 0)
+         || (strcmp (keyword, "BCC") == 0))
        {
          size += 1 + strlen (field);
          for (rem = the_header->text->continuation;
        {
          size += 1 + strlen (field);
          for (rem = the_header->text->continuation;
@@ -511,6 +588,12 @@ args_size (the_header)
   return size;
 }
 
   return size;
 }
 
+/* Scan the header described by the lists THE_HEADER,
+   and put all recipient names into the buffer WHERE.
+   Precede each recipient name with a space.
+
+   Also, if the header has any FCC fields, call setup_files for each one.  */
+
 parse_header (the_header, where)
      header the_header;
      register char *where;
 parse_header (the_header, where)
      header the_header;
      register char *where;
@@ -538,6 +621,12 @@ parse_header (the_header, where)
   return;
 }
 \f    
   return;
 }
 \f    
+/* Read lines from the input until we get a blank line.
+   Create a list of `header' objects, one for each header field,
+   each of which points to a list of `line_list' objects,
+   one for each line in that field.
+   Continuation lines are grouped in the headers they continue.  */
+   
 header
 read_header ()
 {
 header
 read_header ()
 {
@@ -608,7 +697,7 @@ write_header (the_header)
   return;
 }
 \f
   return;
 }
 \f
-void
+int
 main (argc, argv)
      int argc;
      char **argv;
 main (argc, argv)
      int argc;
      char **argv;
@@ -658,4 +747,5 @@ main (argc, argv)
   exit (close_the_streams ());
 }
 
   exit (close_the_streams ());
 }
 
+#endif /* not MSDOS */
 #endif /* not BSD 4.2 (or newer) */
 #endif /* not BSD 4.2 (or newer) */