diff options
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/fakemail.c | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/lib-src/fakemail.c b/lib-src/fakemail.c new file mode 100644 index 00000000000..d055c7f38e7 --- /dev/null +++ b/lib-src/fakemail.c | |||
| @@ -0,0 +1,627 @@ | |||
| 1 | /* sendmail-like interface to /bin/mail for system V, | ||
| 2 | Copyright (C) 1985 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 7 | but WITHOUT ANY WARRANTY. No author or distributor | ||
| 8 | accepts responsibility to anyone for the consequences of using it | ||
| 9 | or for whether it serves any particular purpose or works at all, | ||
| 10 | unless he says so in writing. Refer to the GNU Emacs General Public | ||
| 11 | License for full details. | ||
| 12 | |||
| 13 | Everyone is granted permission to copy, modify and redistribute | ||
| 14 | GNU Emacs, but only under the conditions described in the | ||
| 15 | GNU Emacs General Public License. A copy of this license is | ||
| 16 | supposed to have been given to you along with GNU Emacs so you | ||
| 17 | can know your rights and responsibilities. It should be in a | ||
| 18 | file named COPYING. Among other things, the copyright notice | ||
| 19 | and this notice must be preserved on all copies. */ | ||
| 20 | |||
| 21 | |||
| 22 | #define NO_SHORTNAMES | ||
| 23 | #include "../src/config.h" | ||
| 24 | |||
| 25 | #if defined (BSD) && !defined (BSD4_1) && !defined (USE_FAKEMAIL) | ||
| 26 | /* This program isnot used in BSD, so just avoid loader complaints. */ | ||
| 27 | main () | ||
| 28 | { | ||
| 29 | } | ||
| 30 | #else /* not BSD 4.2 (or newer) */ | ||
| 31 | /* This conditional contains all the rest of the file. */ | ||
| 32 | |||
| 33 | /* These are defined in config in some versions. */ | ||
| 34 | |||
| 35 | #ifdef static | ||
| 36 | #undef static | ||
| 37 | #endif | ||
| 38 | |||
| 39 | #ifdef read | ||
| 40 | #undef read | ||
| 41 | #undef write | ||
| 42 | #undef open | ||
| 43 | #undef close | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #include <stdio.h> | ||
| 47 | #include <string.h> | ||
| 48 | #include <ctype.h> | ||
| 49 | #include <time.h> | ||
| 50 | #include <pwd.h> | ||
| 51 | |||
| 52 | /* Type definitions */ | ||
| 53 | |||
| 54 | #define boolean int | ||
| 55 | #define true 1 | ||
| 56 | #define false 0 | ||
| 57 | |||
| 58 | /* Various lists */ | ||
| 59 | |||
| 60 | struct line_record | ||
| 61 | { | ||
| 62 | char *string; | ||
| 63 | struct line_record *continuation; | ||
| 64 | }; | ||
| 65 | typedef struct line_record *line_list; | ||
| 66 | |||
| 67 | struct header_record | ||
| 68 | { | ||
| 69 | line_list text; | ||
| 70 | struct header_record *next; | ||
| 71 | struct header_record *previous; | ||
| 72 | }; | ||
| 73 | typedef struct header_record *header; | ||
| 74 | |||
| 75 | struct stream_record | ||
| 76 | { | ||
| 77 | FILE *handle; | ||
| 78 | int (*action)(); | ||
| 79 | struct stream_record *rest_streams; | ||
| 80 | }; | ||
| 81 | typedef struct stream_record *stream_list; | ||
| 82 | |||
| 83 | /* A `struct linebuffer' is a structure which holds a line of text. | ||
| 84 | * `readline' reads a line from a stream into a linebuffer | ||
| 85 | * and works regardless of the length of the line. | ||
| 86 | */ | ||
| 87 | |||
| 88 | struct linebuffer | ||
| 89 | { | ||
| 90 | long size; | ||
| 91 | char *buffer; | ||
| 92 | }; | ||
| 93 | |||
| 94 | struct linebuffer lb; | ||
| 95 | |||
| 96 | #define new_list() \ | ||
| 97 | ((line_list) xmalloc (sizeof (struct line_record))) | ||
| 98 | #define new_header() \ | ||
| 99 | ((header) xmalloc (sizeof (struct header_record))) | ||
| 100 | #define new_stream() \ | ||
| 101 | ((stream_list) xmalloc (sizeof (struct stream_record))) | ||
| 102 | #define alloc_string(nchars) \ | ||
| 103 | ((char *) xmalloc ((nchars) + 1)) | ||
| 104 | |||
| 105 | /* Global declarations */ | ||
| 106 | |||
| 107 | #define BUFLEN 1024 | ||
| 108 | #define KEYWORD_SIZE 256 | ||
| 109 | #define FROM_PREFIX "From" | ||
| 110 | #define MY_NAME "fakemail" | ||
| 111 | #define NIL ((line_list) NULL) | ||
| 112 | #define INITIAL_LINE_SIZE 200 | ||
| 113 | |||
| 114 | #ifndef MAIL_PROGRAM_NAME | ||
| 115 | #define MAIL_PROGRAM_NAME "/bin/mail" | ||
| 116 | #endif | ||
| 117 | |||
| 118 | static char *my_name; | ||
| 119 | static char *the_date; | ||
| 120 | static char *the_user; | ||
| 121 | static line_list file_preface; | ||
| 122 | static stream_list the_streams; | ||
| 123 | static boolean no_problems = true; | ||
| 124 | |||
| 125 | extern FILE *popen (); | ||
| 126 | extern int fclose (), pclose (); | ||
| 127 | extern char *malloc (), *realloc (); | ||
| 128 | |||
| 129 | #ifdef CURRENT_USER | ||
| 130 | extern struct passwd *getpwuid (); | ||
| 131 | extern unsigned short geteuid (); | ||
| 132 | static struct passwd *my_entry; | ||
| 133 | #define cuserid(s) \ | ||
| 134 | (my_entry = getpwuid (((int) geteuid ())), \ | ||
| 135 | my_entry->pw_name) | ||
| 136 | #endif | ||
| 137 | |||
| 138 | /* Utilities */ | ||
| 139 | |||
| 140 | /* Print error message. `s1' is printf control string, `s2' is arg for it. */ | ||
| 141 | |||
| 142 | static void | ||
| 143 | error (s1, s2) | ||
| 144 | char *s1, *s2; | ||
| 145 | { | ||
| 146 | printf ("%s: ", my_name); | ||
| 147 | printf (s1, s2); | ||
| 148 | printf ("\n"); | ||
| 149 | no_problems = false; | ||
| 150 | } | ||
| 151 | |||
| 152 | /* Print error message and exit. */ | ||
| 153 | |||
| 154 | static void | ||
| 155 | fatal (s1, s2) | ||
| 156 | char *s1, *s2; | ||
| 157 | { | ||
| 158 | error (s1, s2); | ||
| 159 | exit (1); | ||
| 160 | } | ||
| 161 | |||
| 162 | /* Like malloc but get fatal error if memory is exhausted. */ | ||
| 163 | |||
| 164 | static char * | ||
| 165 | xmalloc (size) | ||
| 166 | int size; | ||
| 167 | { | ||
| 168 | char *result = malloc (((unsigned) size)); | ||
| 169 | if (result == ((char *) NULL)) | ||
| 170 | fatal ("virtual memory exhausted", 0); | ||
| 171 | return result; | ||
| 172 | } | ||
| 173 | |||
| 174 | static char * | ||
| 175 | xrealloc (ptr, size) | ||
| 176 | char *ptr; | ||
| 177 | int size; | ||
| 178 | { | ||
| 179 | char *result = realloc (ptr, ((unsigned) size)); | ||
| 180 | if (result == ((char *) NULL)) | ||
| 181 | fatal ("virtual memory exhausted"); | ||
| 182 | return result; | ||
| 183 | } | ||
| 184 | |||
| 185 | /* Initialize a linebuffer for use */ | ||
| 186 | |||
| 187 | void | ||
| 188 | init_linebuffer (linebuffer) | ||
| 189 | struct linebuffer *linebuffer; | ||
| 190 | { | ||
| 191 | linebuffer->size = INITIAL_LINE_SIZE; | ||
| 192 | linebuffer->buffer = ((char *) xmalloc (INITIAL_LINE_SIZE)); | ||
| 193 | } | ||
| 194 | |||
| 195 | /* Read a line of text from `stream' into `linebuffer'. | ||
| 196 | * Return the length of the line. | ||
| 197 | */ | ||
| 198 | |||
| 199 | long | ||
| 200 | readline (linebuffer, stream) | ||
| 201 | struct linebuffer *linebuffer; | ||
| 202 | FILE *stream; | ||
| 203 | { | ||
| 204 | char *buffer = linebuffer->buffer; | ||
| 205 | char *p = linebuffer->buffer; | ||
| 206 | char *end = p + linebuffer->size; | ||
| 207 | |||
| 208 | while (true) | ||
| 209 | { | ||
| 210 | int c = getc (stream); | ||
| 211 | if (p == end) | ||
| 212 | { | ||
| 213 | linebuffer->size *= 2; | ||
| 214 | buffer = ((char *) xrealloc (buffer, linebuffer->size)); | ||
| 215 | p += buffer - linebuffer->buffer; | ||
| 216 | end += buffer - linebuffer->buffer; | ||
| 217 | linebuffer->buffer = buffer; | ||
| 218 | } | ||
| 219 | if (c < 0 || c == '\n') | ||
| 220 | { | ||
| 221 | *p = 0; | ||
| 222 | break; | ||
| 223 | } | ||
| 224 | *p++ = c; | ||
| 225 | } | ||
| 226 | |||
| 227 | return p - buffer; | ||
| 228 | } | ||
| 229 | |||
| 230 | char * | ||
| 231 | get_keyword (field, rest) | ||
| 232 | register char *field; | ||
| 233 | char **rest; | ||
| 234 | { | ||
| 235 | static char keyword[KEYWORD_SIZE]; | ||
| 236 | register char *ptr; | ||
| 237 | register char c; | ||
| 238 | |||
| 239 | ptr = &keyword[0]; | ||
| 240 | c = *field++; | ||
| 241 | if ((isspace (c)) || (c == ':')) | ||
| 242 | return ((char *) NULL); | ||
| 243 | *ptr++ = ((islower (c)) ? (toupper (c)) : c); | ||
| 244 | while (((c = *field++) != ':') && (!(isspace (c)))) | ||
| 245 | *ptr++ = ((islower (c)) ? (toupper (c)) : c); | ||
| 246 | *ptr++ = '\0'; | ||
| 247 | while (isspace (c)) c = *field++; | ||
| 248 | if (c != ':') return ((char *) NULL); | ||
| 249 | *rest = field; | ||
| 250 | return &keyword[0]; | ||
| 251 | } | ||
| 252 | |||
| 253 | boolean | ||
| 254 | has_keyword (field) | ||
| 255 | char *field; | ||
| 256 | { | ||
| 257 | char *ignored; | ||
| 258 | return (get_keyword (field, &ignored) != ((char *) NULL)); | ||
| 259 | } | ||
| 260 | |||
| 261 | char * | ||
| 262 | add_field (the_list, field, where) | ||
| 263 | line_list the_list; | ||
| 264 | register char *field, *where; | ||
| 265 | { | ||
| 266 | register char c; | ||
| 267 | while (true) | ||
| 268 | { | ||
| 269 | *where++ = ' '; | ||
| 270 | while ((c = *field++) != '\0') | ||
| 271 | { | ||
| 272 | if (c == '(') | ||
| 273 | { | ||
| 274 | while (*field && *field != ')') ++field; | ||
| 275 | if (! (*field++)) break; /* no closer */ | ||
| 276 | if (! (*field)) break; /* closerNULL */ | ||
| 277 | c = *field; | ||
| 278 | } | ||
| 279 | *where++ = ((c == ','||c=='>'||c=='<') ? ' ' : c); | ||
| 280 | } | ||
| 281 | if (the_list == NIL) break; | ||
| 282 | field = the_list->string; | ||
| 283 | the_list = the_list->continuation; | ||
| 284 | } | ||
| 285 | return where; | ||
| 286 | } | ||
| 287 | |||
| 288 | line_list | ||
| 289 | make_file_preface () | ||
| 290 | { | ||
| 291 | char *the_string, *temp; | ||
| 292 | long idiotic_interface; | ||
| 293 | long prefix_length; | ||
| 294 | long user_length; | ||
| 295 | long date_length; | ||
| 296 | line_list result; | ||
| 297 | |||
| 298 | prefix_length = strlen (FROM_PREFIX); | ||
| 299 | time (&idiotic_interface); | ||
| 300 | the_date = ctime (&idiotic_interface); | ||
| 301 | /* the_date has an unwanted newline at the end */ | ||
| 302 | date_length = strlen (the_date) - 1; | ||
| 303 | the_date[date_length] = '\0'; | ||
| 304 | temp = cuserid ((char *) NULL); | ||
| 305 | user_length = strlen (temp); | ||
| 306 | the_user = alloc_string (user_length + 1); | ||
| 307 | strcpy (the_user, temp); | ||
| 308 | the_string = alloc_string (3 + prefix_length + | ||
| 309 | user_length + | ||
| 310 | date_length); | ||
| 311 | temp = the_string; | ||
| 312 | strcpy (temp, FROM_PREFIX); | ||
| 313 | temp = &temp[prefix_length]; | ||
| 314 | *temp++ = ' '; | ||
| 315 | strcpy (temp, the_user); | ||
| 316 | temp = &temp[user_length]; | ||
| 317 | *temp++ = ' '; | ||
| 318 | strcpy (temp, the_date); | ||
| 319 | result = new_list (); | ||
| 320 | result->string = the_string; | ||
| 321 | result->continuation = ((line_list) NULL); | ||
| 322 | return result; | ||
| 323 | } | ||
| 324 | |||
| 325 | void | ||
| 326 | write_line_list (the_list, the_stream) | ||
| 327 | register line_list the_list; | ||
| 328 | FILE *the_stream; | ||
| 329 | { | ||
| 330 | for ( ; | ||
| 331 | the_list != ((line_list) NULL) ; | ||
| 332 | the_list = the_list->continuation) | ||
| 333 | { | ||
| 334 | fputs (the_list->string, the_stream); | ||
| 335 | putc ('\n', the_stream); | ||
| 336 | } | ||
| 337 | return; | ||
| 338 | } | ||
| 339 | |||
| 340 | int | ||
| 341 | close_the_streams () | ||
| 342 | { | ||
| 343 | register stream_list rem; | ||
| 344 | for (rem = the_streams; | ||
| 345 | rem != ((stream_list) NULL); | ||
| 346 | rem = rem->rest_streams) | ||
| 347 | no_problems = (no_problems && | ||
| 348 | ((*rem->action) (rem->handle) == 0)); | ||
| 349 | the_streams = ((stream_list) NULL); | ||
| 350 | return (no_problems ? 0 : 1); | ||
| 351 | } | ||
| 352 | |||
| 353 | void | ||
| 354 | add_a_stream (the_stream, closing_action) | ||
| 355 | FILE *the_stream; | ||
| 356 | int (*closing_action)(); | ||
| 357 | { | ||
| 358 | stream_list old = the_streams; | ||
| 359 | the_streams = new_stream (); | ||
| 360 | the_streams->handle = the_stream; | ||
| 361 | the_streams->action = closing_action; | ||
| 362 | the_streams->rest_streams = old; | ||
| 363 | return; | ||
| 364 | } | ||
| 365 | |||
| 366 | int | ||
| 367 | my_fclose (the_file) | ||
| 368 | FILE *the_file; | ||
| 369 | { | ||
| 370 | putc ('\n', the_file); | ||
| 371 | fflush (the_file); | ||
| 372 | return fclose (the_file); | ||
| 373 | } | ||
| 374 | |||
| 375 | boolean | ||
| 376 | open_a_file (name) | ||
| 377 | char *name; | ||
| 378 | { | ||
| 379 | FILE *the_stream = fopen (name, "a"); | ||
| 380 | if (the_stream != ((FILE *) NULL)) | ||
| 381 | { | ||
| 382 | add_a_stream (the_stream, my_fclose); | ||
| 383 | if (the_user == ((char *) NULL)) | ||
| 384 | file_preface = make_file_preface (); | ||
| 385 | write_line_list (file_preface, the_stream); | ||
| 386 | return true; | ||
| 387 | } | ||
| 388 | return false; | ||
| 389 | } | ||
| 390 | |||
| 391 | void | ||
| 392 | put_string (s) | ||
| 393 | char *s; | ||
| 394 | { | ||
| 395 | register stream_list rem; | ||
| 396 | for (rem = the_streams; | ||
| 397 | rem != ((stream_list) NULL); | ||
| 398 | rem = rem->rest_streams) | ||
| 399 | fputs (s, rem->handle); | ||
| 400 | return; | ||
| 401 | } | ||
| 402 | |||
| 403 | void | ||
| 404 | put_line (s) | ||
| 405 | char *s; | ||
| 406 | { | ||
| 407 | register stream_list rem; | ||
| 408 | for (rem = the_streams; | ||
| 409 | rem != ((stream_list) NULL); | ||
| 410 | rem = rem->rest_streams) | ||
| 411 | { | ||
| 412 | fputs (s, rem->handle); | ||
| 413 | putc ('\n', rem->handle); | ||
| 414 | } | ||
| 415 | return; | ||
| 416 | } | ||
| 417 | |||
| 418 | #define mail_error error | ||
| 419 | |||
| 420 | void | ||
| 421 | setup_files (the_list, field) | ||
| 422 | register line_list the_list; | ||
| 423 | register char *field; | ||
| 424 | { | ||
| 425 | register char *start; | ||
| 426 | register char c; | ||
| 427 | while (true) | ||
| 428 | { | ||
| 429 | while (((c = *field) != '\0') && | ||
| 430 | ((c == ' ') || | ||
| 431 | (c == '\t') || | ||
| 432 | (c == ','))) | ||
| 433 | field += 1; | ||
| 434 | if (c != '\0') | ||
| 435 | { | ||
| 436 | start = field; | ||
| 437 | while (((c = *field) != '\0') && | ||
| 438 | (c != ' ') && | ||
| 439 | (c != '\t') && | ||
| 440 | (c != ',')) | ||
| 441 | field += 1; | ||
| 442 | *field = '\0'; | ||
| 443 | if (!open_a_file (start)) | ||
| 444 | mail_error ("Could not open file %s", start); | ||
| 445 | *field = c; | ||
| 446 | if (c != '\0') continue; | ||
| 447 | } | ||
| 448 | if (the_list == ((line_list) NULL)) return; | ||
| 449 | field = the_list->string; | ||
| 450 | the_list = the_list->continuation; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | int | ||
| 455 | args_size (the_header) | ||
| 456 | header the_header; | ||
| 457 | { | ||
| 458 | register header old = the_header; | ||
| 459 | register line_list rem; | ||
| 460 | register int size = 0; | ||
| 461 | do | ||
| 462 | { | ||
| 463 | char *field; | ||
| 464 | register char *keyword = get_keyword (the_header->text->string, &field); | ||
| 465 | if ((strcmp (keyword, "TO") == 0) || | ||
| 466 | (strcmp (keyword, "CC") == 0) || | ||
| 467 | (strcmp (keyword, "BCC") == 0)) | ||
| 468 | { | ||
| 469 | size += 1 + strlen (field); | ||
| 470 | for (rem = the_header->text->continuation; | ||
| 471 | rem != NIL; | ||
| 472 | rem = rem->continuation) | ||
| 473 | size += 1 + strlen (rem->string); | ||
| 474 | } | ||
| 475 | the_header = the_header->next; | ||
| 476 | } while (the_header != old); | ||
| 477 | return size; | ||
| 478 | } | ||
| 479 | |||
| 480 | parse_header (the_header, where) | ||
| 481 | header the_header; | ||
| 482 | register char *where; | ||
| 483 | { | ||
| 484 | register header old = the_header; | ||
| 485 | do | ||
| 486 | { | ||
| 487 | char *field; | ||
| 488 | register char *keyword = get_keyword (the_header->text->string, &field); | ||
| 489 | if (strcmp (keyword, "TO") == 0) | ||
| 490 | where = add_field (the_header->text->continuation, field, where); | ||
| 491 | else if (strcmp (keyword, "CC") == 0) | ||
| 492 | where = add_field (the_header->text->continuation, field, where); | ||
| 493 | else if (strcmp (keyword, "BCC") == 0) | ||
| 494 | { | ||
| 495 | where = add_field (the_header->text->continuation, field, where); | ||
| 496 | the_header->previous->next = the_header->next; | ||
| 497 | the_header->next->previous = the_header->previous; | ||
| 498 | } | ||
| 499 | else if (strcmp (keyword, "FCC") == 0) | ||
| 500 | setup_files (the_header->text->continuation, field); | ||
| 501 | the_header = the_header->next; | ||
| 502 | } while (the_header != old); | ||
| 503 | *where = '\0'; | ||
| 504 | return; | ||
| 505 | } | ||
| 506 | |||
| 507 | header | ||
| 508 | read_header () | ||
| 509 | { | ||
| 510 | register header the_header = ((header) NULL); | ||
| 511 | register line_list *next_line = ((line_list *) NULL); | ||
| 512 | |||
| 513 | init_linebuffer (&lb); | ||
| 514 | |||
| 515 | do | ||
| 516 | { | ||
| 517 | long length; | ||
| 518 | register char *line; | ||
| 519 | |||
| 520 | readline (&lb, stdin); | ||
| 521 | line = lb.buffer; | ||
| 522 | length = strlen (line); | ||
| 523 | if (length == 0) break; | ||
| 524 | |||
| 525 | if (has_keyword (line)) | ||
| 526 | { | ||
| 527 | register header old = the_header; | ||
| 528 | the_header = new_header (); | ||
| 529 | if (old == ((header) NULL)) | ||
| 530 | { | ||
| 531 | the_header->next = the_header; | ||
| 532 | the_header->previous = the_header; | ||
| 533 | } | ||
| 534 | else | ||
| 535 | { | ||
| 536 | the_header->previous = old; | ||
| 537 | the_header->next = old->next; | ||
| 538 | old->next = the_header; | ||
| 539 | } | ||
| 540 | next_line = &(the_header->text); | ||
| 541 | } | ||
| 542 | |||
| 543 | if (next_line == ((line_list *) NULL)) | ||
| 544 | { | ||
| 545 | /* Not a valid header */ | ||
| 546 | exit (1); | ||
| 547 | } | ||
| 548 | *next_line = new_list (); | ||
| 549 | (*next_line)->string = alloc_string (length); | ||
| 550 | strcpy (((*next_line)->string), line); | ||
| 551 | next_line = &((*next_line)->continuation); | ||
| 552 | *next_line = NIL; | ||
| 553 | |||
| 554 | } while (true); | ||
| 555 | |||
| 556 | return the_header->next; | ||
| 557 | } | ||
| 558 | |||
| 559 | void | ||
| 560 | write_header (the_header) | ||
| 561 | header the_header; | ||
| 562 | { | ||
| 563 | register header old = the_header; | ||
| 564 | do | ||
| 565 | { | ||
| 566 | register line_list the_list; | ||
| 567 | for (the_list = the_header->text; | ||
| 568 | the_list != NIL; | ||
| 569 | the_list = the_list->continuation) | ||
| 570 | put_line (the_list->string); | ||
| 571 | the_header = the_header->next; | ||
| 572 | } while (the_header != old); | ||
| 573 | put_line (""); | ||
| 574 | return; | ||
| 575 | } | ||
| 576 | |||
| 577 | void | ||
| 578 | main (argc, argv) | ||
| 579 | int argc; | ||
| 580 | char **argv; | ||
| 581 | { | ||
| 582 | char *command_line; | ||
| 583 | header the_header; | ||
| 584 | long name_length; | ||
| 585 | char *mail_program_name; | ||
| 586 | char buf[BUFLEN + 1]; | ||
| 587 | register int size; | ||
| 588 | FILE *the_pipe; | ||
| 589 | |||
| 590 | extern char *getenv (); | ||
| 591 | |||
| 592 | mail_program_name = getenv ("FAKEMAILER"); | ||
| 593 | if (!(mail_program_name && *mail_program_name)) | ||
| 594 | mail_program_name = MAIL_PROGRAM_NAME; | ||
| 595 | name_length = strlen (mail_program_name); | ||
| 596 | |||
| 597 | my_name = MY_NAME; | ||
| 598 | the_streams = ((stream_list) NULL); | ||
| 599 | the_date = ((char *) NULL); | ||
| 600 | the_user = ((char *) NULL); | ||
| 601 | |||
| 602 | the_header = read_header (); | ||
| 603 | command_line = alloc_string (name_length + args_size (the_header)); | ||
| 604 | strcpy (command_line, mail_program_name); | ||
| 605 | parse_header (the_header, &command_line[name_length]); | ||
| 606 | |||
| 607 | the_pipe = popen (command_line, "w"); | ||
| 608 | if (the_pipe == ((FILE *) NULL)) | ||
| 609 | fatal ("cannot open pipe to real mailer"); | ||
| 610 | |||
| 611 | add_a_stream (the_pipe, pclose); | ||
| 612 | |||
| 613 | write_header (the_header); | ||
| 614 | |||
| 615 | /* Dump the message itself */ | ||
| 616 | |||
| 617 | while (!feof (stdin)) | ||
| 618 | { | ||
| 619 | size = fread (buf, 1, BUFLEN, stdin); | ||
| 620 | buf[size] = '\0'; | ||
| 621 | put_string (buf); | ||
| 622 | } | ||
| 623 | |||
| 624 | exit (close_the_streams ()); | ||
| 625 | } | ||
| 626 | |||
| 627 | #endif /* not BSD 4.2 (or newer) */ | ||