X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/c1380f31bfd2b5bf42f6ffce36cc871e8a01f827..d283640e036580b300c829e102c7237d844c7019:/lib-src/fakemail.c diff --git a/lib-src/fakemail.c b/lib-src/fakemail.c index a78fbe87f2..400861d4fd 100644 --- a/lib-src/fakemail.c +++ b/lib-src/fakemail.c @@ -1,11 +1,11 @@ /* 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 -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, @@ -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 -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 -#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. */ +int main () { + return 0; } #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. */ @@ -42,6 +52,10 @@ main () #undef close #endif +#ifdef WINDOWSNT +#include "ntlib.h" +#endif + #include #include #include @@ -123,7 +137,6 @@ static boolean no_problems = true; extern FILE *popen (); extern int fclose (), pclose (); -extern char *malloc (), *realloc (); #ifdef CURRENT_USER extern struct passwd *getpwuid (); @@ -160,23 +173,23 @@ fatal (s1, s2) /* Like malloc but get fatal error if memory is exhausted. */ -static char * +static long * 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; } -static char * +static long * xrealloc (ptr, size) - char *ptr; + long *ptr; 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; } @@ -211,8 +224,8 @@ readline (linebuffer, stream) { 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') @@ -226,6 +239,12 @@ readline (linebuffer, stream) return p - buffer; } +/* 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; @@ -237,18 +256,22 @@ get_keyword (field, rest) ptr = &keyword[0]; c = *field++; - if ((isspace (c)) || (c == ':')) + if (isspace (c) || c == ':') 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'; - 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]; } +/* Nonzero if the string FIELD starts with a colon-terminated keyword. */ + boolean has_keyword (field) char *field; @@ -257,6 +280,16 @@ has_keyword (field) 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; @@ -265,17 +298,48 @@ add_field (the_list, field, where) register char c; while (true) { + char *this_recipient_where; + int in_quotes = 0; + *where++ = ' '; + this_recipient_where = where; + 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; - 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; @@ -416,7 +480,7 @@ put_line (string) { char *breakpos; - /* Find the last char that fits. */ + /* Find the last char that fits. */ for (breakpos = s; *breakpos && column < 78; ++breakpos) { if (*breakpos == '\t') @@ -424,15 +488,20 @@ put_line (string) 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); @@ -451,6 +520,10 @@ put_line (string) #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; @@ -460,18 +533,18 @@ setup_files (the_list, field) 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; - 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)) @@ -479,12 +552,16 @@ setup_files (the_list, field) *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; } } +/* 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; @@ -496,9 +573,9 @@ args_size (the_header) { 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; @@ -511,6 +588,12 @@ args_size (the_header) 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; @@ -538,6 +621,12 @@ parse_header (the_header, where) return; } +/* 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 () { @@ -608,7 +697,7 @@ write_header (the_header) return; } -void +int main (argc, argv) int argc; char **argv; @@ -658,4 +747,5 @@ main (argc, argv) exit (close_the_streams ()); } +#endif /* not MSDOS */ #endif /* not BSD 4.2 (or newer) */