diff options
| author | Glenn Morris | 2011-05-17 20:39:45 -0700 |
|---|---|---|
| committer | Glenn Morris | 2011-05-17 20:39:45 -0700 |
| commit | c136e5cdf2e7ea9745727c07146713c582f93cde (patch) | |
| tree | ae0d7bb83755d036f5856199f481c74a49583bc9 /lib-src | |
| parent | e565dd3789e0ef5589035034893d99de239c87a2 (diff) | |
| download | emacs-c136e5cdf2e7ea9745727c07146713c582f93cde.tar.gz emacs-c136e5cdf2e7ea9745727c07146713c582f93cde.zip | |
Remove lib-src/fakemail.c.
* lib-src/fakemail.c: Remove file.
* lib-src/Makefile.in (UTILITIES): Remove fakemail${EXEEXT}.
(fakemail${EXEEXT}): Remove rule.
* lib-src/makefile.w32-in ($(BLD)/fakemail.exe, fakemail)
($(BLD)/fakemail.$(O)): Remove.
* lisp/mail/sendmail.el (sendmail-program): Fall back to just "sendmail".
* lisp/mail/feedmail.el: Update commentary.
* doc/emacs/ack.texi (Acknowledgments): Remove fakemail.c.
* etc/NEWS: Mention this.
* INSTALL: Remove fakemail.
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/ChangeLog | 8 | ||||
| -rw-r--r-- | lib-src/Makefile.in | 7 | ||||
| -rw-r--r-- | lib-src/fakemail.c | 744 | ||||
| -rw-r--r-- | lib-src/makefile.w32-in | 13 |
4 files changed, 11 insertions, 761 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index c4a2df5bdbf..27dc3a14d48 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2011-05-18 Glenn Morris <rgm@gnu.org> | ||
| 2 | |||
| 3 | * fakemail.c: Remove file. | ||
| 4 | * makefile.w32-in ($(BLD)/fakemail.exe, fakemail) | ||
| 5 | ($(BLD)/fakemail.$(O)): Remove. | ||
| 6 | * Makefile.in (UTILITIES): Remove fakemail${EXEEXT}. | ||
| 7 | (fakemail${EXEEXT}): Remove rule. | ||
| 8 | |||
| 1 | 2011-04-24 Teodor Zlatanov <tzz@lifelogs.com> | 9 | 2011-04-24 Teodor Zlatanov <tzz@lifelogs.com> |
| 2 | 10 | ||
| 3 | * makefile.w32-in (obj): Add gnutls.o. | 11 | * makefile.w32-in (obj): Add gnutls.o. |
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in index 36366a4d2e7..1c2018dbbc9 100644 --- a/lib-src/Makefile.in +++ b/lib-src/Makefile.in | |||
| @@ -117,8 +117,8 @@ STAMP_INST_SCRIPTS = stamp-rcs-checkin stamp-grep-changelog | |||
| 117 | 117 | ||
| 118 | # Things that Emacs runs internally, or during the build process, | 118 | # Things that Emacs runs internally, or during the build process, |
| 119 | # which should not be installed in bindir. | 119 | # which should not be installed in bindir. |
| 120 | UTILITIES = profile${EXEEXT} movemail${EXEEXT} fakemail${EXEEXT} \ | 120 | UTILITIES = profile${EXEEXT} movemail${EXEEXT} hexl${EXEEXT} \ |
| 121 | hexl${EXEEXT} update-game-score${EXEEXT} | 121 | update-game-score${EXEEXT} |
| 122 | 122 | ||
| 123 | DONT_INSTALL= test-distrib${EXEEXT} make-docfile${EXEEXT} | 123 | DONT_INSTALL= test-distrib${EXEEXT} make-docfile${EXEEXT} |
| 124 | 124 | ||
| @@ -353,9 +353,6 @@ movemail.o: ${srcdir}/movemail.c ../src/config.h | |||
| 353 | pop.o: ${srcdir}/pop.c ${srcdir}/../lib/min-max.h ../src/config.h | 353 | pop.o: ${srcdir}/pop.c ${srcdir}/../lib/min-max.h ../src/config.h |
| 354 | $(CC) -c ${CPP_CFLAGS} ${MOVE_FLAGS} ${srcdir}/pop.c | 354 | $(CC) -c ${CPP_CFLAGS} ${MOVE_FLAGS} ${srcdir}/pop.c |
| 355 | 355 | ||
| 356 | fakemail${EXEEXT}: ${srcdir}/fakemail.c ../src/config.h | ||
| 357 | $(CC) ${ALL_CFLAGS} ${srcdir}/fakemail.c $(LOADLIBES) -o fakemail | ||
| 358 | |||
| 359 | emacsclient${EXEEXT}: ${srcdir}/emacsclient.c ../src/config.h | 356 | emacsclient${EXEEXT}: ${srcdir}/emacsclient.c ../src/config.h |
| 360 | $(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c \ | 357 | $(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c \ |
| 361 | -DVERSION="\"${version}\"" \ | 358 | -DVERSION="\"${version}\"" \ |
diff --git a/lib-src/fakemail.c b/lib-src/fakemail.c deleted file mode 100644 index 435512125ff..00000000000 --- a/lib-src/fakemail.c +++ /dev/null | |||
| @@ -1,744 +0,0 @@ | |||
| 1 | /* sendmail-like interface to /bin/mail for system V, | ||
| 2 | Copyright (C) 1985, 1994, 1999, 2001-2011 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | Author: Bill Rozas <jinx@martigny.ai.mit.edu> | ||
| 5 | (according to ack.texi) | ||
| 6 | |||
| 7 | This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation, either version 3 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 21 | |||
| 22 | |||
| 23 | #define _XOPEN_SOURCE 500 /* for cuserid */ | ||
| 24 | |||
| 25 | #ifdef HAVE_CONFIG_H | ||
| 26 | #include <config.h> | ||
| 27 | #endif | ||
| 28 | |||
| 29 | #if defined (BSD_SYSTEM) && !defined (USE_FAKEMAIL) | ||
| 30 | /* This program isnot used in BSD, so just avoid loader complaints. */ | ||
| 31 | int | ||
| 32 | main (void) | ||
| 33 | { | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | #else /* not BSD 4.2 (or newer) */ | ||
| 37 | #ifdef MSDOS | ||
| 38 | int | ||
| 39 | main () | ||
| 40 | { | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | #else /* not MSDOS */ | ||
| 44 | /* This conditional contains all the rest of the file. */ | ||
| 45 | |||
| 46 | /* These are defined in config in some versions. */ | ||
| 47 | |||
| 48 | #ifdef static | ||
| 49 | #undef static | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #ifdef WINDOWSNT | ||
| 53 | #include "ntlib.h" | ||
| 54 | #endif | ||
| 55 | |||
| 56 | #include <stdio.h> | ||
| 57 | #include <string.h> | ||
| 58 | #include <ctype.h> | ||
| 59 | #include <time.h> | ||
| 60 | #include <pwd.h> | ||
| 61 | #include <stdlib.h> | ||
| 62 | |||
| 63 | /* This is to declare cuserid. */ | ||
| 64 | #include <unistd.h> | ||
| 65 | |||
| 66 | /* Type definitions */ | ||
| 67 | |||
| 68 | #define boolean int | ||
| 69 | #define true 1 | ||
| 70 | #define false 0 | ||
| 71 | |||
| 72 | #define TM_YEAR_BASE 1900 | ||
| 73 | |||
| 74 | /* Nonzero if TM_YEAR is a struct tm's tm_year value that causes | ||
| 75 | asctime to have well-defined behavior. */ | ||
| 76 | #ifndef TM_YEAR_IN_ASCTIME_RANGE | ||
| 77 | # define TM_YEAR_IN_ASCTIME_RANGE(tm_year) \ | ||
| 78 | (1000 - TM_YEAR_BASE <= (tm_year) && (tm_year) <= 9999 - TM_YEAR_BASE) | ||
| 79 | #endif | ||
| 80 | |||
| 81 | /* Various lists */ | ||
| 82 | |||
| 83 | struct line_record | ||
| 84 | { | ||
| 85 | char *string; | ||
| 86 | struct line_record *continuation; | ||
| 87 | }; | ||
| 88 | typedef struct line_record *line_list; | ||
| 89 | |||
| 90 | struct header_record | ||
| 91 | { | ||
| 92 | line_list text; | ||
| 93 | struct header_record *next; | ||
| 94 | struct header_record *previous; | ||
| 95 | }; | ||
| 96 | typedef struct header_record *header; | ||
| 97 | |||
| 98 | struct stream_record | ||
| 99 | { | ||
| 100 | FILE *handle; | ||
| 101 | int (*action)(FILE *); | ||
| 102 | struct stream_record *rest_streams; | ||
| 103 | }; | ||
| 104 | typedef struct stream_record *stream_list; | ||
| 105 | |||
| 106 | /* A `struct linebuffer' is a structure which holds a line of text. | ||
| 107 | * `readline' reads a line from a stream into a linebuffer | ||
| 108 | * and works regardless of the length of the line. | ||
| 109 | */ | ||
| 110 | |||
| 111 | struct linebuffer | ||
| 112 | { | ||
| 113 | long size; | ||
| 114 | char *buffer; | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct linebuffer lb; | ||
| 118 | |||
| 119 | #define new_list() \ | ||
| 120 | ((line_list) xmalloc (sizeof (struct line_record))) | ||
| 121 | #define new_header() \ | ||
| 122 | ((header) xmalloc (sizeof (struct header_record))) | ||
| 123 | #define new_stream() \ | ||
| 124 | ((stream_list) xmalloc (sizeof (struct stream_record))) | ||
| 125 | #define alloc_string(nchars) \ | ||
| 126 | ((char *) xmalloc ((nchars) + 1)) | ||
| 127 | |||
| 128 | /* Global declarations */ | ||
| 129 | |||
| 130 | #define BUFLEN 1024 | ||
| 131 | #define KEYWORD_SIZE 256 | ||
| 132 | #define FROM_PREFIX "From" | ||
| 133 | #define MY_NAME "fakemail" | ||
| 134 | #define NIL ((line_list) NULL) | ||
| 135 | #define INITIAL_LINE_SIZE 200 | ||
| 136 | |||
| 137 | #ifndef MAIL_PROGRAM_NAME | ||
| 138 | #define MAIL_PROGRAM_NAME "/bin/mail" | ||
| 139 | #endif | ||
| 140 | |||
| 141 | static const char *my_name; | ||
| 142 | static char *the_date; | ||
| 143 | static char *the_user; | ||
| 144 | static line_list file_preface; | ||
| 145 | static stream_list the_streams; | ||
| 146 | static boolean no_problems = true; | ||
| 147 | |||
| 148 | static void fatal (const char *s1) NO_RETURN; | ||
| 149 | |||
| 150 | #ifdef CURRENT_USER | ||
| 151 | static struct passwd *my_entry; | ||
| 152 | #define cuserid(s) \ | ||
| 153 | (my_entry = getpwuid (((int) geteuid ())), \ | ||
| 154 | my_entry->pw_name) | ||
| 155 | #endif | ||
| 156 | |||
| 157 | /* Utilities */ | ||
| 158 | |||
| 159 | /* Print error message. `s1' is printf control string, `s2' is arg for it. */ | ||
| 160 | |||
| 161 | static void | ||
| 162 | error (const char *s1, const char *s2) | ||
| 163 | { | ||
| 164 | printf ("%s: ", my_name); | ||
| 165 | printf (s1, s2); | ||
| 166 | printf ("\n"); | ||
| 167 | no_problems = false; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* Print error message and exit. */ | ||
| 171 | |||
| 172 | static void | ||
| 173 | fatal (const char *s1) | ||
| 174 | { | ||
| 175 | error ("%s", s1); | ||
| 176 | exit (EXIT_FAILURE); | ||
| 177 | } | ||
| 178 | |||
| 179 | /* Like malloc but get fatal error if memory is exhausted. */ | ||
| 180 | |||
| 181 | static void * | ||
| 182 | xmalloc (size_t size) | ||
| 183 | { | ||
| 184 | void *result = malloc (size); | ||
| 185 | if (! result) | ||
| 186 | fatal ("virtual memory exhausted"); | ||
| 187 | return result; | ||
| 188 | } | ||
| 189 | |||
| 190 | static void * | ||
| 191 | xrealloc (void *ptr, size_t size) | ||
| 192 | { | ||
| 193 | void *result = realloc (ptr, size); | ||
| 194 | if (! result) | ||
| 195 | fatal ("virtual memory exhausted"); | ||
| 196 | return result; | ||
| 197 | } | ||
| 198 | |||
| 199 | /* Initialize a linebuffer for use */ | ||
| 200 | |||
| 201 | static void | ||
| 202 | init_linebuffer (struct linebuffer *linebuffer) | ||
| 203 | { | ||
| 204 | linebuffer->size = INITIAL_LINE_SIZE; | ||
| 205 | linebuffer->buffer = ((char *) xmalloc (INITIAL_LINE_SIZE)); | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Read a line of text from `stream' into `linebuffer'. | ||
| 209 | Return the length of the line. */ | ||
| 210 | |||
| 211 | static long | ||
| 212 | readline (struct linebuffer *linebuffer, FILE *stream) | ||
| 213 | { | ||
| 214 | char *buffer = linebuffer->buffer; | ||
| 215 | char *p = linebuffer->buffer; | ||
| 216 | char *end = p + linebuffer->size; | ||
| 217 | |||
| 218 | while (true) | ||
| 219 | { | ||
| 220 | int c = getc (stream); | ||
| 221 | if (p == end) | ||
| 222 | { | ||
| 223 | linebuffer->size *= 2; | ||
| 224 | buffer = (char *) xrealloc (buffer, linebuffer->size); | ||
| 225 | p = buffer + (p - linebuffer->buffer); | ||
| 226 | end = buffer + linebuffer->size; | ||
| 227 | linebuffer->buffer = buffer; | ||
| 228 | } | ||
| 229 | if (c < 0 || c == '\n') | ||
| 230 | { | ||
| 231 | *p = 0; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | *p++ = c; | ||
| 235 | } | ||
| 236 | |||
| 237 | return p - buffer; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* Extract a colon-terminated keyword from the string FIELD. | ||
| 241 | Return that keyword as a string stored in a static buffer. | ||
| 242 | Store the address of the rest of the string into *REST. | ||
| 243 | |||
| 244 | If there is no keyword, return NULL and don't alter *REST. */ | ||
| 245 | |||
| 246 | static char * | ||
| 247 | get_keyword (register char *field, char **rest) | ||
| 248 | { | ||
| 249 | static char keyword[KEYWORD_SIZE]; | ||
| 250 | register char *ptr; | ||
| 251 | register int c; | ||
| 252 | |||
| 253 | ptr = &keyword[0]; | ||
| 254 | c = (unsigned char) *field++; | ||
| 255 | if (isspace (c) || c == ':') | ||
| 256 | return ((char *) NULL); | ||
| 257 | *ptr++ = (islower (c) ? toupper (c) : c); | ||
| 258 | while (((c = (unsigned char) *field++) != ':') && ! isspace (c)) | ||
| 259 | *ptr++ = (islower (c) ? toupper (c) : c); | ||
| 260 | *ptr++ = '\0'; | ||
| 261 | while (isspace (c)) | ||
| 262 | c = (unsigned char) *field++; | ||
| 263 | if (c != ':') | ||
| 264 | return ((char *) NULL); | ||
| 265 | *rest = field; | ||
| 266 | return &keyword[0]; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* Nonzero if the string FIELD starts with a colon-terminated keyword. */ | ||
| 270 | |||
| 271 | static boolean | ||
| 272 | has_keyword (char *field) | ||
| 273 | { | ||
| 274 | char *ignored; | ||
| 275 | return (get_keyword (field, &ignored) != ((char *) NULL)); | ||
| 276 | } | ||
| 277 | |||
| 278 | /* Store the string FIELD, followed by any lines in THE_LIST, | ||
| 279 | into the buffer WHERE. | ||
| 280 | Concatenate lines, putting just a space between them. | ||
| 281 | Delete everything contained in parentheses. | ||
| 282 | When a recipient name contains <...>, we discard | ||
| 283 | everything except what is inside the <...>. | ||
| 284 | |||
| 285 | We don't pay attention to overflowing WHERE; | ||
| 286 | the caller has to make it big enough. */ | ||
| 287 | |||
| 288 | static char * | ||
| 289 | add_field (line_list the_list, register char *field, register char *where) | ||
| 290 | { | ||
| 291 | register char c; | ||
| 292 | while (true) | ||
| 293 | { | ||
| 294 | char *this_recipient_where; | ||
| 295 | int in_quotes = 0; | ||
| 296 | |||
| 297 | *where++ = ' '; | ||
| 298 | this_recipient_where = where; | ||
| 299 | |||
| 300 | while ((c = *field++) != '\0') | ||
| 301 | { | ||
| 302 | if (c == '\\') | ||
| 303 | *where++ = c; | ||
| 304 | else if (c == '"') | ||
| 305 | { | ||
| 306 | in_quotes = ! in_quotes; | ||
| 307 | *where++ = c; | ||
| 308 | } | ||
| 309 | else if (in_quotes) | ||
| 310 | *where++ = c; | ||
| 311 | else if (c == '(') | ||
| 312 | { | ||
| 313 | while (*field && *field != ')') ++field; | ||
| 314 | if (! (*field++)) break; /* no close */ | ||
| 315 | continue; | ||
| 316 | } | ||
| 317 | else if (c == ',') | ||
| 318 | { | ||
| 319 | *where++ = ' '; | ||
| 320 | /* When we get to the end of one recipient, | ||
| 321 | don't discard it if the next one has <...>. */ | ||
| 322 | this_recipient_where = where; | ||
| 323 | } | ||
| 324 | else if (c == '<') | ||
| 325 | /* Discard everything we got before the `<'. */ | ||
| 326 | where = this_recipient_where; | ||
| 327 | else if (c == '>') | ||
| 328 | /* Discard the rest of this name that follows the `>'. */ | ||
| 329 | { | ||
| 330 | while (*field && *field != ',') ++field; | ||
| 331 | if (! (*field++)) break; /* no comma */ | ||
| 332 | continue; | ||
| 333 | } | ||
| 334 | else | ||
| 335 | *where++ = c; | ||
| 336 | } | ||
| 337 | if (the_list == NIL) break; | ||
| 338 | field = the_list->string; | ||
| 339 | the_list = the_list->continuation; | ||
| 340 | } | ||
| 341 | return where; | ||
| 342 | } | ||
| 343 | |||
| 344 | static line_list | ||
| 345 | make_file_preface (void) | ||
| 346 | { | ||
| 347 | char *the_string, *temp; | ||
| 348 | long idiotic_interface; | ||
| 349 | struct tm *tm; | ||
| 350 | long prefix_length; | ||
| 351 | long user_length; | ||
| 352 | long date_length; | ||
| 353 | line_list result; | ||
| 354 | |||
| 355 | prefix_length = strlen (FROM_PREFIX); | ||
| 356 | time (&idiotic_interface); | ||
| 357 | /* Convert to a string, checking for out-of-range time stamps. | ||
| 358 | Don't use 'ctime', as that might dump core if the hardware clock | ||
| 359 | is set to a bizarre value. */ | ||
| 360 | tm = localtime (&idiotic_interface); | ||
| 361 | if (! (tm && TM_YEAR_IN_ASCTIME_RANGE (tm->tm_year) | ||
| 362 | && (the_date = asctime (tm)))) | ||
| 363 | fatal ("current time is out of range"); | ||
| 364 | /* the_date has an unwanted newline at the end */ | ||
| 365 | date_length = strlen (the_date) - 1; | ||
| 366 | the_date[date_length] = '\0'; | ||
| 367 | temp = cuserid ((char *) NULL); | ||
| 368 | user_length = strlen (temp); | ||
| 369 | the_user = alloc_string (user_length + 1); | ||
| 370 | strcpy (the_user, temp); | ||
| 371 | the_string = alloc_string (3 + prefix_length | ||
| 372 | + user_length | ||
| 373 | + date_length); | ||
| 374 | temp = the_string; | ||
| 375 | strcpy (temp, FROM_PREFIX); | ||
| 376 | temp = &temp[prefix_length]; | ||
| 377 | *temp++ = ' '; | ||
| 378 | strcpy (temp, the_user); | ||
| 379 | temp = &temp[user_length]; | ||
| 380 | *temp++ = ' '; | ||
| 381 | strcpy (temp, the_date); | ||
| 382 | result = new_list (); | ||
| 383 | result->string = the_string; | ||
| 384 | result->continuation = ((line_list) NULL); | ||
| 385 | return result; | ||
| 386 | } | ||
| 387 | |||
| 388 | static void | ||
| 389 | write_line_list (register line_list the_list, FILE *the_stream) | ||
| 390 | { | ||
| 391 | for ( ; | ||
| 392 | the_list != ((line_list) NULL) ; | ||
| 393 | the_list = the_list->continuation) | ||
| 394 | { | ||
| 395 | fputs (the_list->string, the_stream); | ||
| 396 | putc ('\n', the_stream); | ||
| 397 | } | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | |||
| 401 | static int | ||
| 402 | close_the_streams (void) | ||
| 403 | { | ||
| 404 | register stream_list rem; | ||
| 405 | for (rem = the_streams; | ||
| 406 | rem != ((stream_list) NULL); | ||
| 407 | rem = rem->rest_streams) | ||
| 408 | if (no_problems && (*rem->action) (rem->handle) != 0) | ||
| 409 | error ("output error", NULL); | ||
| 410 | the_streams = ((stream_list) NULL); | ||
| 411 | return (no_problems ? EXIT_SUCCESS : EXIT_FAILURE); | ||
| 412 | } | ||
| 413 | |||
| 414 | static void | ||
| 415 | add_a_stream (FILE *the_stream, int (*closing_action) (FILE *)) | ||
| 416 | { | ||
| 417 | stream_list old = the_streams; | ||
| 418 | the_streams = new_stream (); | ||
| 419 | the_streams->handle = the_stream; | ||
| 420 | the_streams->action = closing_action; | ||
| 421 | the_streams->rest_streams = old; | ||
| 422 | return; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int | ||
| 426 | my_fclose (FILE *the_file) | ||
| 427 | { | ||
| 428 | putc ('\n', the_file); | ||
| 429 | fflush (the_file); | ||
| 430 | if (ferror (the_file)) | ||
| 431 | return EOF; | ||
| 432 | return fclose (the_file); | ||
| 433 | } | ||
| 434 | |||
| 435 | static boolean | ||
| 436 | open_a_file (char *name) | ||
| 437 | { | ||
| 438 | FILE *the_stream = fopen (name, "a"); | ||
| 439 | if (the_stream != ((FILE *) NULL)) | ||
| 440 | { | ||
| 441 | add_a_stream (the_stream, my_fclose); | ||
| 442 | if (the_user == ((char *) NULL)) | ||
| 443 | file_preface = make_file_preface (); | ||
| 444 | write_line_list (file_preface, the_stream); | ||
| 445 | return true; | ||
| 446 | } | ||
| 447 | return false; | ||
| 448 | } | ||
| 449 | |||
| 450 | static void | ||
| 451 | put_string (char *s) | ||
| 452 | { | ||
| 453 | register stream_list rem; | ||
| 454 | for (rem = the_streams; | ||
| 455 | rem != ((stream_list) NULL); | ||
| 456 | rem = rem->rest_streams) | ||
| 457 | fputs (s, rem->handle); | ||
| 458 | return; | ||
| 459 | } | ||
| 460 | |||
| 461 | static void | ||
| 462 | put_line (const char *string) | ||
| 463 | { | ||
| 464 | register stream_list rem; | ||
| 465 | for (rem = the_streams; | ||
| 466 | rem != ((stream_list) NULL); | ||
| 467 | rem = rem->rest_streams) | ||
| 468 | { | ||
| 469 | const char *s = string; | ||
| 470 | int column = 0; | ||
| 471 | |||
| 472 | /* Divide STRING into lines. */ | ||
| 473 | while (*s != 0) | ||
| 474 | { | ||
| 475 | const char *breakpos; | ||
| 476 | |||
| 477 | /* Find the last char that fits. */ | ||
| 478 | for (breakpos = s; *breakpos && column < 78; ++breakpos) | ||
| 479 | { | ||
| 480 | if (*breakpos == '\t') | ||
| 481 | column += 8; | ||
| 482 | else | ||
| 483 | column++; | ||
| 484 | } | ||
| 485 | /* If we didn't reach end of line, break the line. */ | ||
| 486 | if (*breakpos) | ||
| 487 | { | ||
| 488 | /* Back up to just after the last comma that fits. */ | ||
| 489 | while (breakpos != s && breakpos[-1] != ',') --breakpos; | ||
| 490 | |||
| 491 | if (breakpos == s) | ||
| 492 | { | ||
| 493 | /* If no comma fits, move past the first address anyway. */ | ||
| 494 | while (*breakpos != 0 && *breakpos != ',') ++breakpos; | ||
| 495 | if (*breakpos != 0) | ||
| 496 | /* Include the comma after it. */ | ||
| 497 | ++breakpos; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | /* Output that much, then break the line. */ | ||
| 501 | fwrite (s, 1, breakpos - s, rem->handle); | ||
| 502 | column = 8; | ||
| 503 | |||
| 504 | /* Skip whitespace and prepare to print more addresses. */ | ||
| 505 | s = breakpos; | ||
| 506 | while (*s == ' ' || *s == '\t') ++s; | ||
| 507 | if (*s != 0) | ||
| 508 | fputs ("\n\t", rem->handle); | ||
| 509 | } | ||
| 510 | putc ('\n', rem->handle); | ||
| 511 | } | ||
| 512 | return; | ||
| 513 | } | ||
| 514 | |||
| 515 | #define mail_error error | ||
| 516 | |||
| 517 | /* Handle an FCC field. FIELD is the text of the first line (after | ||
| 518 | the header name), and THE_LIST holds the continuation lines if any. | ||
| 519 | Call open_a_file for each file. */ | ||
| 520 | |||
| 521 | static void | ||
| 522 | setup_files (register line_list the_list, register char *field) | ||
| 523 | { | ||
| 524 | register char *start; | ||
| 525 | register char c; | ||
| 526 | while (true) | ||
| 527 | { | ||
| 528 | while (((c = *field) != '\0') | ||
| 529 | && (c == ' ' | ||
| 530 | || c == '\t' | ||
| 531 | || c == ',')) | ||
| 532 | field += 1; | ||
| 533 | if (c != '\0') | ||
| 534 | { | ||
| 535 | start = field; | ||
| 536 | while (((c = *field) != '\0') | ||
| 537 | && c != ' ' | ||
| 538 | && c != '\t' | ||
| 539 | && c != ',') | ||
| 540 | field += 1; | ||
| 541 | *field = '\0'; | ||
| 542 | if (!open_a_file (start)) | ||
| 543 | mail_error ("Could not open file %s", start); | ||
| 544 | *field = c; | ||
| 545 | if (c != '\0') continue; | ||
| 546 | } | ||
| 547 | if (the_list == ((line_list) NULL)) | ||
| 548 | return; | ||
| 549 | field = the_list->string; | ||
| 550 | the_list = the_list->continuation; | ||
| 551 | } | ||
| 552 | } | ||
| 553 | |||
| 554 | /* Compute the total size of all recipient names stored in THE_HEADER. | ||
| 555 | The result says how big to make the buffer to pass to parse_header. */ | ||
| 556 | |||
| 557 | static int | ||
| 558 | args_size (header the_header) | ||
| 559 | { | ||
| 560 | register header old = the_header; | ||
| 561 | register line_list rem; | ||
| 562 | register int size = 0; | ||
| 563 | do | ||
| 564 | { | ||
| 565 | char *field; | ||
| 566 | register char *keyword = get_keyword (the_header->text->string, &field); | ||
| 567 | if ((strcmp (keyword, "TO") == 0) | ||
| 568 | || (strcmp (keyword, "CC") == 0) | ||
| 569 | || (strcmp (keyword, "BCC") == 0)) | ||
| 570 | { | ||
| 571 | size += 1 + strlen (field); | ||
| 572 | for (rem = the_header->text->continuation; | ||
| 573 | rem != NIL; | ||
| 574 | rem = rem->continuation) | ||
| 575 | size += 1 + strlen (rem->string); | ||
| 576 | } | ||
| 577 | the_header = the_header->next; | ||
| 578 | } while (the_header != old); | ||
| 579 | return size; | ||
| 580 | } | ||
| 581 | |||
| 582 | /* Scan the header described by the lists THE_HEADER, | ||
| 583 | and put all recipient names into the buffer WHERE. | ||
| 584 | Precede each recipient name with a space. | ||
| 585 | |||
| 586 | Also, if the header has any FCC fields, call setup_files for each one. */ | ||
| 587 | |||
| 588 | static void | ||
| 589 | parse_header (header the_header, register char *where) | ||
| 590 | { | ||
| 591 | register header old = the_header; | ||
| 592 | do | ||
| 593 | { | ||
| 594 | char *field; | ||
| 595 | register char *keyword = get_keyword (the_header->text->string, &field); | ||
| 596 | if (strcmp (keyword, "TO") == 0) | ||
| 597 | where = add_field (the_header->text->continuation, field, where); | ||
| 598 | else if (strcmp (keyword, "CC") == 0) | ||
| 599 | where = add_field (the_header->text->continuation, field, where); | ||
| 600 | else if (strcmp (keyword, "BCC") == 0) | ||
| 601 | { | ||
| 602 | where = add_field (the_header->text->continuation, field, where); | ||
| 603 | the_header->previous->next = the_header->next; | ||
| 604 | the_header->next->previous = the_header->previous; | ||
| 605 | } | ||
| 606 | else if (strcmp (keyword, "FCC") == 0) | ||
| 607 | setup_files (the_header->text->continuation, field); | ||
| 608 | the_header = the_header->next; | ||
| 609 | } while (the_header != old); | ||
| 610 | *where = '\0'; | ||
| 611 | return; | ||
| 612 | } | ||
| 613 | |||
| 614 | /* Read lines from the input until we get a blank line. | ||
| 615 | Create a list of `header' objects, one for each header field, | ||
| 616 | each of which points to a list of `line_list' objects, | ||
| 617 | one for each line in that field. | ||
| 618 | Continuation lines are grouped in the headers they continue. */ | ||
| 619 | |||
| 620 | static header | ||
| 621 | read_header (void) | ||
| 622 | { | ||
| 623 | register header the_header = ((header) NULL); | ||
| 624 | register line_list *next_line = ((line_list *) NULL); | ||
| 625 | |||
| 626 | init_linebuffer (&lb); | ||
| 627 | |||
| 628 | do | ||
| 629 | { | ||
| 630 | long length; | ||
| 631 | register char *line; | ||
| 632 | |||
| 633 | readline (&lb, stdin); | ||
| 634 | line = lb.buffer; | ||
| 635 | length = strlen (line); | ||
| 636 | if (length == 0) break; | ||
| 637 | |||
| 638 | if (has_keyword (line)) | ||
| 639 | { | ||
| 640 | register header old = the_header; | ||
| 641 | the_header = new_header (); | ||
| 642 | if (old == ((header) NULL)) | ||
| 643 | { | ||
| 644 | the_header->next = the_header; | ||
| 645 | the_header->previous = the_header; | ||
| 646 | } | ||
| 647 | else | ||
| 648 | { | ||
| 649 | the_header->previous = old; | ||
| 650 | the_header->next = old->next; | ||
| 651 | old->next = the_header; | ||
| 652 | } | ||
| 653 | next_line = &(the_header->text); | ||
| 654 | } | ||
| 655 | |||
| 656 | if (next_line == ((line_list *) NULL)) | ||
| 657 | { | ||
| 658 | /* Not a valid header */ | ||
| 659 | exit (EXIT_FAILURE); | ||
| 660 | } | ||
| 661 | *next_line = new_list (); | ||
| 662 | (*next_line)->string = alloc_string (length); | ||
| 663 | strcpy (((*next_line)->string), line); | ||
| 664 | next_line = &((*next_line)->continuation); | ||
| 665 | *next_line = NIL; | ||
| 666 | |||
| 667 | } while (true); | ||
| 668 | |||
| 669 | if (! the_header) | ||
| 670 | fatal ("input message has no header"); | ||
| 671 | return the_header->next; | ||
| 672 | } | ||
| 673 | |||
| 674 | static void | ||
| 675 | write_header (header the_header) | ||
| 676 | { | ||
| 677 | register header old = the_header; | ||
| 678 | do | ||
| 679 | { | ||
| 680 | register line_list the_list; | ||
| 681 | for (the_list = the_header->text; | ||
| 682 | the_list != NIL; | ||
| 683 | the_list = the_list->continuation) | ||
| 684 | put_line (the_list->string); | ||
| 685 | the_header = the_header->next; | ||
| 686 | } while (the_header != old); | ||
| 687 | put_line (""); | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | |||
| 691 | int | ||
| 692 | main (int argc, char **argv) | ||
| 693 | { | ||
| 694 | char *command_line; | ||
| 695 | header the_header; | ||
| 696 | long name_length; | ||
| 697 | const char *mail_program_name; | ||
| 698 | char buf[BUFLEN + 1]; | ||
| 699 | register int size; | ||
| 700 | FILE *the_pipe; | ||
| 701 | |||
| 702 | mail_program_name = getenv ("FAKEMAILER"); | ||
| 703 | if (!(mail_program_name && *mail_program_name)) | ||
| 704 | mail_program_name = MAIL_PROGRAM_NAME; | ||
| 705 | name_length = strlen (mail_program_name); | ||
| 706 | |||
| 707 | my_name = MY_NAME; | ||
| 708 | the_streams = ((stream_list) NULL); | ||
| 709 | the_date = ((char *) NULL); | ||
| 710 | the_user = ((char *) NULL); | ||
| 711 | |||
| 712 | the_header = read_header (); | ||
| 713 | command_line = alloc_string (name_length + args_size (the_header)); | ||
| 714 | strcpy (command_line, mail_program_name); | ||
| 715 | parse_header (the_header, &command_line[name_length]); | ||
| 716 | |||
| 717 | the_pipe = popen (command_line, "w"); | ||
| 718 | if (the_pipe == ((FILE *) NULL)) | ||
| 719 | fatal ("cannot open pipe to real mailer"); | ||
| 720 | |||
| 721 | add_a_stream (the_pipe, pclose); | ||
| 722 | |||
| 723 | write_header (the_header); | ||
| 724 | |||
| 725 | /* Dump the message itself */ | ||
| 726 | |||
| 727 | while (!feof (stdin)) | ||
| 728 | { | ||
| 729 | size = fread (buf, 1, BUFLEN, stdin); | ||
| 730 | buf[size] = '\0'; | ||
| 731 | put_string (buf); | ||
| 732 | } | ||
| 733 | |||
| 734 | if (no_problems && (ferror (stdin) || fclose (stdin) != 0)) | ||
| 735 | error ("input error", NULL); | ||
| 736 | |||
| 737 | exit (close_the_streams ()); | ||
| 738 | } | ||
| 739 | |||
| 740 | #endif /* not MSDOS */ | ||
| 741 | #endif /* not BSD 4.2 (or newer) */ | ||
| 742 | |||
| 743 | |||
| 744 | /* fakemail.c ends here */ | ||
diff --git a/lib-src/makefile.w32-in b/lib-src/makefile.w32-in index 38d453d5259..0e203d18bd2 100644 --- a/lib-src/makefile.w32-in +++ b/lib-src/makefile.w32-in | |||
| @@ -31,8 +31,6 @@ $(BLD)/make-docfile.exe: $(BLD)/make-docfile.$(O) $(BLD)/ntlib.$(O) | |||
| 31 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/make-docfile.$(O) $(BLD)/ntlib.$(O) $(LIBS) | 31 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/make-docfile.$(O) $(BLD)/ntlib.$(O) $(LIBS) |
| 32 | $(BLD)/hexl.exe: $(BLD)/hexl.$(O) | 32 | $(BLD)/hexl.exe: $(BLD)/hexl.$(O) |
| 33 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/hexl.$(O) $(LIBS) | 33 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/hexl.$(O) $(LIBS) |
| 34 | $(BLD)/fakemail.exe: $(BLD)/fakemail.$(O) $(BLD)/ntlib.$(O) | ||
| 35 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/fakemail.$(O) $(BLD)/ntlib.$(O) $(LIBS) | ||
| 36 | $(BLD)/test-distrib.exe: $(BLD)/test-distrib.$(O) | 34 | $(BLD)/test-distrib.exe: $(BLD)/test-distrib.$(O) |
| 37 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/test-distrib.$(O) $(LIBS) | 35 | $(LINK) $(LINK_OUT)$@ $(LINK_FLAGS) $(BLD)/test-distrib.$(O) $(LIBS) |
| 38 | 36 | ||
| @@ -42,7 +40,6 @@ etags: stamp_BLD $(BLD)/etags.exe | |||
| 42 | ebrowse: stamp_BLD $(BLD)/ebrowse.exe | 40 | ebrowse: stamp_BLD $(BLD)/ebrowse.exe |
| 43 | hexl: stamp_BLD $(BLD)/hexl.exe | 41 | hexl: stamp_BLD $(BLD)/hexl.exe |
| 44 | movemail: stamp_BLD $(BLD)/movemail.exe | 42 | movemail: stamp_BLD $(BLD)/movemail.exe |
| 45 | fakemail: stamp_BLD $(BLD)/fakemail.exe | ||
| 46 | emacsclient: stamp_BLD $(BLD)/emacsclient.exe $(BLD)/emacsclientw.exe | 43 | emacsclient: stamp_BLD $(BLD)/emacsclient.exe $(BLD)/emacsclientw.exe |
| 47 | 44 | ||
| 48 | test-distrib: stamp_BLD $(BLD)/test-distrib.exe | 45 | test-distrib: stamp_BLD $(BLD)/test-distrib.exe |
| @@ -406,14 +403,6 @@ $(BLD)/etags.$(O) : \ | |||
| 406 | $(SRC)/ntlib.h \ | 403 | $(SRC)/ntlib.h \ |
| 407 | $(EMACS_ROOT)/lib/getopt.h | 404 | $(EMACS_ROOT)/lib/getopt.h |
| 408 | 405 | ||
| 409 | $(BLD)/fakemail.$(O) : \ | ||
| 410 | $(SRC)/fakemail.c \ | ||
| 411 | $(SRC)/ntlib.h \ | ||
| 412 | $(EMACS_ROOT)/src/s/ms-w32.h \ | ||
| 413 | $(EMACS_ROOT)/src/m/intel386.h \ | ||
| 414 | $(EMACS_ROOT)/lib-src/../src/config.h \ | ||
| 415 | $(EMACS_ROOT)/nt/inc/pwd.h | ||
| 416 | |||
| 417 | $(BLD)/getdate.$(O) : \ | 406 | $(BLD)/getdate.$(O) : \ |
| 418 | $(SRC)/getdate.c \ | 407 | $(SRC)/getdate.c \ |
| 419 | $(EMACS_ROOT)/src/s/ms-w32.h \ | 408 | $(EMACS_ROOT)/src/s/ms-w32.h \ |
| @@ -483,7 +472,7 @@ $(BLD)/timer.$(O) : \ | |||
| 483 | # The following dependencies are for supporting parallel builds, where | 472 | # The following dependencies are for supporting parallel builds, where |
| 484 | # we must make sure $(BLD) exists before any compilation starts. | 473 | # we must make sure $(BLD) exists before any compilation starts. |
| 485 | # | 474 | # |
| 486 | $(BLD)/make-docfile.$(O) $(BLD)/hexl.$(O) $(BLD)/fakemail.$(O): stamp_BLD | 475 | $(BLD)/make-docfile.$(O) $(BLD)/hexl.$(O): stamp_BLD |
| 487 | 476 | ||
| 488 | $(BLD)/test-distrib.$(O) $(MOVEMAILOBJS): stamp_BLD | 477 | $(BLD)/test-distrib.$(O) $(MOVEMAILOBJS): stamp_BLD |
| 489 | 478 | ||