Mercurial > emacs
annotate lib-src/fakemail.c @ 22758:dbd9ecc9dbac
Added next-buffer/previous-buffer keybindings (bound to M-n/M-p).
(crisp-unbury-buffer): New function.
Fixed bogus XEmacs/Lucid string-match checking.
Made modeline entry mouse2-able.
(crisp-mode-map): Make this a sparse keymap parented from
current-global-map.
(crisp-mode-original-keymap): Don't copy the keymap.
(crisp-last-last-command): Renamed from last-last-command. defvar it.
(crisp-mode): Honor ARG.
(crisp-kill-line, crisp-copy-line): When a region isn't highlighted,
use the region from point to eol. Honor prefix argument.
(crisp-submit-bug-report): New command, taken from cc-mode.
Shortened the version numbering, removed the release-version tracking
(crisp-version): New function.
New keybindings `C-home', `C-end', `M-home', `M-end', `C-f', `M-l',
`M-m'.
(crisp-copy-line): No need to save point.
Removed S-right and S-left bindings.
Abstract the marking and selection interfaces so that we can be
compatible with both Emacs and XEmacs. And try and make the
behavior as close as possible under both environments so that there
are no surprises.
author | Karl Heuer <kwzh@gnu.org> |
---|---|
date | Tue, 14 Jul 1998 22:17:35 +0000 |
parents | 48690fd8d40a |
children | 7ebe942c4a9c |
rev | line source |
---|---|
18 | 1 /* sendmail-like interface to /bin/mail for system V, |
7307 | 2 Copyright (C) 1985, 1994 Free Software Foundation, Inc. |
18 | 3 |
4 This file is part of GNU Emacs. | |
5 | |
37 | 6 GNU Emacs is free software; you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | |
6109 | 8 the Free Software Foundation; either version 2, or (at your option) |
37 | 9 any later version. |
18 | 10 |
37 | 11 GNU Emacs is distributed in the hope that it will be useful, |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GNU Emacs; see the file COPYING. If not, write to | |
14186
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
12840
diff
changeset
|
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
12840
diff
changeset
|
19 Boston, MA 02111-1307, USA. */ |
18 | 20 |
21 | |
21389
48690fd8d40a
(_XOPEN_SOURCE): Define for declaration of cuserid.
Andreas Schwab <schwab@suse.de>
parents:
18841
diff
changeset
|
22 /* This is needed to get the declaration of cuserid in GNU libc. */ |
48690fd8d40a
(_XOPEN_SOURCE): Define for declaration of cuserid.
Andreas Schwab <schwab@suse.de>
parents:
18841
diff
changeset
|
23 #define _XOPEN_SOURCE 1 |
48690fd8d40a
(_XOPEN_SOURCE): Define for declaration of cuserid.
Andreas Schwab <schwab@suse.de>
parents:
18841
diff
changeset
|
24 |
18 | 25 #define NO_SHORTNAMES |
4696
1fc792473491
Include <config.h> instead of "config.h".
Roland McGrath <roland@gnu.org>
parents:
3219
diff
changeset
|
26 #include <../src/config.h> |
18 | 27 |
16218
32f82ca8b41f
Replaced all BSD with BSD_SYSTEM.
Karl Heuer <kwzh@gnu.org>
parents:
16121
diff
changeset
|
28 #if defined (BSD_SYSTEM) && !defined (BSD4_1) && !defined (USE_FAKEMAIL) |
18 | 29 /* This program isnot used in BSD, so just avoid loader complaints. */ |
15683 | 30 int |
18 | 31 main () |
32 { | |
16121 | 33 return 0; |
18 | 34 } |
35 #else /* not BSD 4.2 (or newer) */ | |
5447
6f0905b05218
(main) [MSDOS]: Dummy stub just to make the file compile.
Richard M. Stallman <rms@gnu.org>
parents:
4696
diff
changeset
|
36 #ifdef MSDOS |
15683 | 37 int |
5447
6f0905b05218
(main) [MSDOS]: Dummy stub just to make the file compile.
Richard M. Stallman <rms@gnu.org>
parents:
4696
diff
changeset
|
38 main () |
6f0905b05218
(main) [MSDOS]: Dummy stub just to make the file compile.
Richard M. Stallman <rms@gnu.org>
parents:
4696
diff
changeset
|
39 { |
16121 | 40 return 0; |
5447
6f0905b05218
(main) [MSDOS]: Dummy stub just to make the file compile.
Richard M. Stallman <rms@gnu.org>
parents:
4696
diff
changeset
|
41 } |
6f0905b05218
(main) [MSDOS]: Dummy stub just to make the file compile.
Richard M. Stallman <rms@gnu.org>
parents:
4696
diff
changeset
|
42 #else /* not MSDOS */ |
18 | 43 /* This conditional contains all the rest of the file. */ |
44 | |
45 /* These are defined in config in some versions. */ | |
46 | |
47 #ifdef static | |
48 #undef static | |
49 #endif | |
50 | |
51 #ifdef read | |
52 #undef read | |
53 #undef write | |
54 #undef open | |
55 #undef close | |
56 #endif | |
57 | |
15099
857388330750
[WINDOWSNT]: Include ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14186
diff
changeset
|
58 #ifdef WINDOWSNT |
857388330750
[WINDOWSNT]: Include ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14186
diff
changeset
|
59 #include "ntlib.h" |
857388330750
[WINDOWSNT]: Include ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14186
diff
changeset
|
60 #endif |
857388330750
[WINDOWSNT]: Include ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14186
diff
changeset
|
61 |
18 | 62 #include <stdio.h> |
63 #include <string.h> | |
64 #include <ctype.h> | |
65 #include <time.h> | |
66 #include <pwd.h> | |
18841
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
67 |
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
68 /* This is to declare cuserid. */ |
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
69 #ifdef HAVE_UNISTD_H |
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
70 #include <unistd.h> |
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
71 #endif |
18 | 72 |
73 /* Type definitions */ | |
74 | |
75 #define boolean int | |
76 #define true 1 | |
77 #define false 0 | |
78 | |
79 /* Various lists */ | |
80 | |
81 struct line_record | |
82 { | |
83 char *string; | |
84 struct line_record *continuation; | |
85 }; | |
86 typedef struct line_record *line_list; | |
87 | |
88 struct header_record | |
89 { | |
90 line_list text; | |
91 struct header_record *next; | |
92 struct header_record *previous; | |
93 }; | |
94 typedef struct header_record *header; | |
95 | |
96 struct stream_record | |
97 { | |
98 FILE *handle; | |
99 int (*action)(); | |
100 struct stream_record *rest_streams; | |
101 }; | |
102 typedef struct stream_record *stream_list; | |
103 | |
104 /* A `struct linebuffer' is a structure which holds a line of text. | |
105 * `readline' reads a line from a stream into a linebuffer | |
106 * and works regardless of the length of the line. | |
107 */ | |
108 | |
109 struct linebuffer | |
110 { | |
111 long size; | |
112 char *buffer; | |
113 }; | |
114 | |
115 struct linebuffer lb; | |
116 | |
117 #define new_list() \ | |
118 ((line_list) xmalloc (sizeof (struct line_record))) | |
119 #define new_header() \ | |
120 ((header) xmalloc (sizeof (struct header_record))) | |
121 #define new_stream() \ | |
122 ((stream_list) xmalloc (sizeof (struct stream_record))) | |
123 #define alloc_string(nchars) \ | |
124 ((char *) xmalloc ((nchars) + 1)) | |
125 | |
126 /* Global declarations */ | |
127 | |
128 #define BUFLEN 1024 | |
129 #define KEYWORD_SIZE 256 | |
130 #define FROM_PREFIX "From" | |
131 #define MY_NAME "fakemail" | |
132 #define NIL ((line_list) NULL) | |
133 #define INITIAL_LINE_SIZE 200 | |
134 | |
135 #ifndef MAIL_PROGRAM_NAME | |
136 #define MAIL_PROGRAM_NAME "/bin/mail" | |
137 #endif | |
138 | |
139 static char *my_name; | |
140 static char *the_date; | |
141 static char *the_user; | |
142 static line_list file_preface; | |
143 static stream_list the_streams; | |
144 static boolean no_problems = true; | |
145 | |
146 extern FILE *popen (); | |
147 extern int fclose (), pclose (); | |
148 | |
149 #ifdef CURRENT_USER | |
150 extern struct passwd *getpwuid (); | |
151 extern unsigned short geteuid (); | |
152 static struct passwd *my_entry; | |
153 #define cuserid(s) \ | |
154 (my_entry = getpwuid (((int) geteuid ())), \ | |
155 my_entry->pw_name) | |
156 #endif | |
157 | |
158 /* Utilities */ | |
159 | |
160 /* Print error message. `s1' is printf control string, `s2' is arg for it. */ | |
161 | |
162 static void | |
163 error (s1, s2) | |
164 char *s1, *s2; | |
165 { | |
166 printf ("%s: ", my_name); | |
167 printf (s1, s2); | |
168 printf ("\n"); | |
169 no_problems = false; | |
170 } | |
171 | |
172 /* Print error message and exit. */ | |
173 | |
174 static void | |
175 fatal (s1, s2) | |
176 char *s1, *s2; | |
177 { | |
178 error (s1, s2); | |
179 exit (1); | |
180 } | |
181 | |
182 /* Like malloc but get fatal error if memory is exhausted. */ | |
183 | |
12833
25464bf61eb1
(xmalloc, xrealloc): Use return-type long *.
Richard M. Stallman <rms@gnu.org>
parents:
10265
diff
changeset
|
184 static long * |
18 | 185 xmalloc (size) |
186 int size; | |
187 { | |
12833
25464bf61eb1
(xmalloc, xrealloc): Use return-type long *.
Richard M. Stallman <rms@gnu.org>
parents:
10265
diff
changeset
|
188 long *result = (long *) malloc (((unsigned) size)); |
25464bf61eb1
(xmalloc, xrealloc): Use return-type long *.
Richard M. Stallman <rms@gnu.org>
parents:
10265
diff
changeset
|
189 if (result == ((long *) NULL)) |
18 | 190 fatal ("virtual memory exhausted", 0); |
191 return result; | |
192 } | |
193 | |
12833
25464bf61eb1
(xmalloc, xrealloc): Use return-type long *.
Richard M. Stallman <rms@gnu.org>
parents:
10265
diff
changeset
|
194 static long * |
18 | 195 xrealloc (ptr, size) |
12833
25464bf61eb1
(xmalloc, xrealloc): Use return-type long *.
Richard M. Stallman <rms@gnu.org>
parents:
10265
diff
changeset
|
196 long *ptr; |
18 | 197 int size; |
198 { | |
12833
25464bf61eb1
(xmalloc, xrealloc): Use return-type long *.
Richard M. Stallman <rms@gnu.org>
parents:
10265
diff
changeset
|
199 long *result = (long *) realloc (ptr, ((unsigned) size)); |
12840
4e9a14304b8b
(xrealloc): Change cast to match return type.
Karl Heuer <kwzh@gnu.org>
parents:
12833
diff
changeset
|
200 if (result == ((long *) NULL)) |
18 | 201 fatal ("virtual memory exhausted"); |
202 return result; | |
203 } | |
204 | |
205 /* Initialize a linebuffer for use */ | |
206 | |
207 void | |
208 init_linebuffer (linebuffer) | |
209 struct linebuffer *linebuffer; | |
210 { | |
211 linebuffer->size = INITIAL_LINE_SIZE; | |
212 linebuffer->buffer = ((char *) xmalloc (INITIAL_LINE_SIZE)); | |
213 } | |
214 | |
215 /* Read a line of text from `stream' into `linebuffer'. | |
216 * Return the length of the line. | |
217 */ | |
218 | |
219 long | |
220 readline (linebuffer, stream) | |
221 struct linebuffer *linebuffer; | |
222 FILE *stream; | |
223 { | |
224 char *buffer = linebuffer->buffer; | |
225 char *p = linebuffer->buffer; | |
226 char *end = p + linebuffer->size; | |
227 | |
228 while (true) | |
229 { | |
230 int c = getc (stream); | |
231 if (p == end) | |
232 { | |
233 linebuffer->size *= 2; | |
234 buffer = ((char *) xrealloc (buffer, linebuffer->size)); | |
6992
ed57331fb222
(readline): Fix updating of p when buffer grows.
Richard M. Stallman <rms@gnu.org>
parents:
6954
diff
changeset
|
235 p = buffer + (p - linebuffer->buffer); |
6954
774fdc20d115
(readline): When extending the buffer,
Richard M. Stallman <rms@gnu.org>
parents:
6109
diff
changeset
|
236 end = buffer + linebuffer->size; |
18 | 237 linebuffer->buffer = buffer; |
238 } | |
239 if (c < 0 || c == '\n') | |
240 { | |
241 *p = 0; | |
242 break; | |
243 } | |
244 *p++ = c; | |
245 } | |
246 | |
247 return p - buffer; | |
248 } | |
249 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
250 /* Extract a colon-terminated keyword from the string FIELD. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
251 Return that keyword as a string stored in a static buffer. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
252 Store the address of the rest of the string into *REST. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
253 |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
254 If there is no keyword, return NULL and don't alter *REST. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
255 |
18 | 256 char * |
257 get_keyword (field, rest) | |
258 register char *field; | |
259 char **rest; | |
260 { | |
261 static char keyword[KEYWORD_SIZE]; | |
262 register char *ptr; | |
263 register char c; | |
264 | |
265 ptr = &keyword[0]; | |
266 c = *field++; | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
267 if (isspace (c) || c == ':') |
18 | 268 return ((char *) NULL); |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
269 *ptr++ = (islower (c) ? toupper (c) : c); |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
270 while (((c = *field++) != ':') && ! isspace (c)) |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
271 *ptr++ = (islower (c) ? toupper (c) : c); |
18 | 272 *ptr++ = '\0'; |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
273 while (isspace (c)) |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
274 c = *field++; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
275 if (c != ':') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
276 return ((char *) NULL); |
18 | 277 *rest = field; |
278 return &keyword[0]; | |
279 } | |
280 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
281 /* Nonzero if the string FIELD starts with a colon-terminated keyword. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
282 |
18 | 283 boolean |
284 has_keyword (field) | |
285 char *field; | |
286 { | |
287 char *ignored; | |
288 return (get_keyword (field, &ignored) != ((char *) NULL)); | |
289 } | |
290 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
291 /* Store the string FIELD, followed by any lines in THE_LIST, |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
292 into the buffer WHERE. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
293 Concatenate lines, putting just a space between them. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
294 Delete everything contained in parentheses. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
295 When a recipient name contains <...>, we discard |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
296 everything except what is inside the <...>. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
297 |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
298 We don't pay attention to overflowing WHERE; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
299 the caller has to make it big enough. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
300 |
18 | 301 char * |
302 add_field (the_list, field, where) | |
303 line_list the_list; | |
304 register char *field, *where; | |
305 { | |
306 register char c; | |
307 while (true) | |
308 { | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
309 char *this_recipient_where; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
310 int in_quotes = 0; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
311 |
18 | 312 *where++ = ' '; |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
313 this_recipient_where = where; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
314 |
18 | 315 while ((c = *field++) != '\0') |
316 { | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
317 if (c == '\\') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
318 *where++ = c; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
319 else if (c == '"') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
320 { |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
321 in_quotes = ! in_quotes; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
322 *where++ = c; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
323 } |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
324 else if (in_quotes) |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
325 *where++ = c; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
326 else if (c == '(') |
18 | 327 { |
328 while (*field && *field != ')') ++field; | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
329 if (! (*field++)) break; /* no close */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
330 continue; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
331 } |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
332 else if (c == ',') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
333 { |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
334 *where++ = ' '; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
335 /* When we get to the end of one recipient, |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
336 don't discard it if the next one has <...>. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
337 this_recipient_where = where; |
18 | 338 } |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
339 else if (c == '<') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
340 /* Discard everything we got before the `<'. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
341 where = this_recipient_where; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
342 else if (c == '>') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
343 /* Discard the rest of this name that follows the `>'. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
344 { |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
345 while (*field && *field != ',') ++field; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
346 if (! (*field++)) break; /* no comma */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
347 continue; |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
348 } |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
349 else |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
350 *where++ = c; |
18 | 351 } |
352 if (the_list == NIL) break; | |
353 field = the_list->string; | |
354 the_list = the_list->continuation; | |
355 } | |
356 return where; | |
357 } | |
358 | |
359 line_list | |
360 make_file_preface () | |
361 { | |
362 char *the_string, *temp; | |
363 long idiotic_interface; | |
364 long prefix_length; | |
365 long user_length; | |
366 long date_length; | |
367 line_list result; | |
368 | |
369 prefix_length = strlen (FROM_PREFIX); | |
370 time (&idiotic_interface); | |
371 the_date = ctime (&idiotic_interface); | |
372 /* the_date has an unwanted newline at the end */ | |
373 date_length = strlen (the_date) - 1; | |
374 the_date[date_length] = '\0'; | |
375 temp = cuserid ((char *) NULL); | |
376 user_length = strlen (temp); | |
377 the_user = alloc_string (user_length + 1); | |
378 strcpy (the_user, temp); | |
18841
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
379 the_string = alloc_string (3 + prefix_length |
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
380 + user_length |
36704f455f32
[HAVE_UNISTD_H]: Include unistd.h.
Richard M. Stallman <rms@gnu.org>
parents:
16218
diff
changeset
|
381 + date_length); |
18 | 382 temp = the_string; |
383 strcpy (temp, FROM_PREFIX); | |
384 temp = &temp[prefix_length]; | |
385 *temp++ = ' '; | |
386 strcpy (temp, the_user); | |
387 temp = &temp[user_length]; | |
388 *temp++ = ' '; | |
389 strcpy (temp, the_date); | |
390 result = new_list (); | |
391 result->string = the_string; | |
392 result->continuation = ((line_list) NULL); | |
393 return result; | |
394 } | |
395 | |
396 void | |
397 write_line_list (the_list, the_stream) | |
398 register line_list the_list; | |
399 FILE *the_stream; | |
400 { | |
401 for ( ; | |
402 the_list != ((line_list) NULL) ; | |
403 the_list = the_list->continuation) | |
404 { | |
405 fputs (the_list->string, the_stream); | |
406 putc ('\n', the_stream); | |
407 } | |
408 return; | |
409 } | |
410 | |
411 int | |
412 close_the_streams () | |
413 { | |
414 register stream_list rem; | |
415 for (rem = the_streams; | |
416 rem != ((stream_list) NULL); | |
417 rem = rem->rest_streams) | |
418 no_problems = (no_problems && | |
419 ((*rem->action) (rem->handle) == 0)); | |
420 the_streams = ((stream_list) NULL); | |
421 return (no_problems ? 0 : 1); | |
422 } | |
423 | |
424 void | |
425 add_a_stream (the_stream, closing_action) | |
426 FILE *the_stream; | |
427 int (*closing_action)(); | |
428 { | |
429 stream_list old = the_streams; | |
430 the_streams = new_stream (); | |
431 the_streams->handle = the_stream; | |
432 the_streams->action = closing_action; | |
433 the_streams->rest_streams = old; | |
434 return; | |
435 } | |
436 | |
437 int | |
438 my_fclose (the_file) | |
439 FILE *the_file; | |
440 { | |
441 putc ('\n', the_file); | |
442 fflush (the_file); | |
443 return fclose (the_file); | |
444 } | |
445 | |
446 boolean | |
447 open_a_file (name) | |
448 char *name; | |
449 { | |
450 FILE *the_stream = fopen (name, "a"); | |
451 if (the_stream != ((FILE *) NULL)) | |
452 { | |
453 add_a_stream (the_stream, my_fclose); | |
454 if (the_user == ((char *) NULL)) | |
455 file_preface = make_file_preface (); | |
456 write_line_list (file_preface, the_stream); | |
457 return true; | |
458 } | |
459 return false; | |
460 } | |
461 | |
462 void | |
463 put_string (s) | |
464 char *s; | |
465 { | |
466 register stream_list rem; | |
467 for (rem = the_streams; | |
468 rem != ((stream_list) NULL); | |
469 rem = rem->rest_streams) | |
470 fputs (s, rem->handle); | |
471 return; | |
472 } | |
473 | |
474 void | |
20 | 475 put_line (string) |
476 char *string; | |
18 | 477 { |
478 register stream_list rem; | |
479 for (rem = the_streams; | |
480 rem != ((stream_list) NULL); | |
481 rem = rem->rest_streams) | |
482 { | |
20 | 483 char *s = string; |
484 int column = 0; | |
485 | |
486 /* Divide STRING into lines. */ | |
487 while (*s != 0) | |
488 { | |
489 char *breakpos; | |
490 | |
5959
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
491 /* Find the last char that fits. */ |
20 | 492 for (breakpos = s; *breakpos && column < 78; ++breakpos) |
493 { | |
494 if (*breakpos == '\t') | |
495 column += 8; | |
496 else | |
497 column++; | |
498 } | |
5959
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
499 /* If we didn't reach end of line, break the line. */ |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
500 if (*breakpos) |
20 | 501 { |
5959
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
502 /* Back up to just after the last comma that fits. */ |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
503 while (breakpos != s && breakpos[-1] != ',') --breakpos; |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
504 |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
505 if (breakpos == s) |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
506 { |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
507 /* If no comma fits, move past the first address anyway. */ |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
508 while (*breakpos != 0 && *breakpos != ',') ++breakpos; |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
509 if (*breakpos != 0) |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
510 /* Include the comma after it. */ |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
511 ++breakpos; |
e4337a7bbe32
(put_line): Don't break the line if it all fits.
Richard M. Stallman <rms@gnu.org>
parents:
5447
diff
changeset
|
512 } |
20 | 513 } |
514 /* Output that much, then break the line. */ | |
515 fwrite (s, 1, breakpos - s, rem->handle); | |
516 column = 8; | |
517 | |
518 /* Skip whitespace and prepare to print more addresses. */ | |
519 s = breakpos; | |
520 while (*s == ' ' || *s == '\t') ++s; | |
3219
1aa8fa0a569e
(put_line): Don't output \n\t unless more text follows.
Richard M. Stallman <rms@gnu.org>
parents:
37
diff
changeset
|
521 if (*s != 0) |
1aa8fa0a569e
(put_line): Don't output \n\t unless more text follows.
Richard M. Stallman <rms@gnu.org>
parents:
37
diff
changeset
|
522 fputs ("\n\t", rem->handle); |
20 | 523 } |
18 | 524 putc ('\n', rem->handle); |
525 } | |
526 return; | |
527 } | |
528 | |
529 #define mail_error error | |
530 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
531 /* Handle an FCC field. FIELD is the text of the first line (after |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
532 the header name), and THE_LIST holds the continuation lines if any. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
533 Call open_a_file for each file. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
534 |
18 | 535 void |
536 setup_files (the_list, field) | |
537 register line_list the_list; | |
538 register char *field; | |
539 { | |
540 register char *start; | |
541 register char c; | |
542 while (true) | |
543 { | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
544 while (((c = *field) != '\0') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
545 && (c == ' ' |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
546 || c == '\t' |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
547 || c == ',')) |
18 | 548 field += 1; |
549 if (c != '\0') | |
550 { | |
551 start = field; | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
552 while (((c = *field) != '\0') |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
553 && c != ' ' |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
554 && c != '\t' |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
555 && c != ',') |
18 | 556 field += 1; |
557 *field = '\0'; | |
558 if (!open_a_file (start)) | |
559 mail_error ("Could not open file %s", start); | |
560 *field = c; | |
561 if (c != '\0') continue; | |
562 } | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
563 if (the_list == ((line_list) NULL)) |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
564 return; |
18 | 565 field = the_list->string; |
566 the_list = the_list->continuation; | |
567 } | |
568 } | |
569 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
570 /* Compute the total size of all recipient names stored in THE_HEADER. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
571 The result says how big to make the buffer to pass to parse_header. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
572 |
18 | 573 int |
574 args_size (the_header) | |
575 header the_header; | |
576 { | |
577 register header old = the_header; | |
578 register line_list rem; | |
579 register int size = 0; | |
580 do | |
581 { | |
582 char *field; | |
583 register char *keyword = get_keyword (the_header->text->string, &field); | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
584 if ((strcmp (keyword, "TO") == 0) |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
585 || (strcmp (keyword, "CC") == 0) |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
586 || (strcmp (keyword, "BCC") == 0)) |
18 | 587 { |
588 size += 1 + strlen (field); | |
589 for (rem = the_header->text->continuation; | |
590 rem != NIL; | |
591 rem = rem->continuation) | |
592 size += 1 + strlen (rem->string); | |
593 } | |
594 the_header = the_header->next; | |
595 } while (the_header != old); | |
596 return size; | |
597 } | |
598 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
599 /* Scan the header described by the lists THE_HEADER, |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
600 and put all recipient names into the buffer WHERE. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
601 Precede each recipient name with a space. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
602 |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
603 Also, if the header has any FCC fields, call setup_files for each one. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
604 |
21389
48690fd8d40a
(_XOPEN_SOURCE): Define for declaration of cuserid.
Andreas Schwab <schwab@suse.de>
parents:
18841
diff
changeset
|
605 void |
18 | 606 parse_header (the_header, where) |
607 header the_header; | |
608 register char *where; | |
609 { | |
610 register header old = the_header; | |
611 do | |
612 { | |
613 char *field; | |
614 register char *keyword = get_keyword (the_header->text->string, &field); | |
615 if (strcmp (keyword, "TO") == 0) | |
616 where = add_field (the_header->text->continuation, field, where); | |
617 else if (strcmp (keyword, "CC") == 0) | |
618 where = add_field (the_header->text->continuation, field, where); | |
619 else if (strcmp (keyword, "BCC") == 0) | |
620 { | |
621 where = add_field (the_header->text->continuation, field, where); | |
622 the_header->previous->next = the_header->next; | |
623 the_header->next->previous = the_header->previous; | |
624 } | |
625 else if (strcmp (keyword, "FCC") == 0) | |
626 setup_files (the_header->text->continuation, field); | |
627 the_header = the_header->next; | |
628 } while (the_header != old); | |
629 *where = '\0'; | |
630 return; | |
631 } | |
632 | |
10265
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
633 /* Read lines from the input until we get a blank line. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
634 Create a list of `header' objects, one for each header field, |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
635 each of which points to a list of `line_list' objects, |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
636 one for each line in that field. |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
637 Continuation lines are grouped in the headers they continue. */ |
c53a70ec8d85
(xmalloc, xrealloc): Add casts.
Richard M. Stallman <rms@gnu.org>
parents:
9621
diff
changeset
|
638 |
18 | 639 header |
640 read_header () | |
641 { | |
642 register header the_header = ((header) NULL); | |
643 register line_list *next_line = ((line_list *) NULL); | |
644 | |
645 init_linebuffer (&lb); | |
646 | |
647 do | |
648 { | |
649 long length; | |
650 register char *line; | |
651 | |
652 readline (&lb, stdin); | |
653 line = lb.buffer; | |
654 length = strlen (line); | |
655 if (length == 0) break; | |
656 | |
657 if (has_keyword (line)) | |
658 { | |
659 register header old = the_header; | |
660 the_header = new_header (); | |
661 if (old == ((header) NULL)) | |
662 { | |
663 the_header->next = the_header; | |
664 the_header->previous = the_header; | |
665 } | |
666 else | |
667 { | |
668 the_header->previous = old; | |
669 the_header->next = old->next; | |
670 old->next = the_header; | |
671 } | |
672 next_line = &(the_header->text); | |
673 } | |
674 | |
675 if (next_line == ((line_list *) NULL)) | |
676 { | |
677 /* Not a valid header */ | |
678 exit (1); | |
679 } | |
680 *next_line = new_list (); | |
681 (*next_line)->string = alloc_string (length); | |
682 strcpy (((*next_line)->string), line); | |
683 next_line = &((*next_line)->continuation); | |
684 *next_line = NIL; | |
685 | |
686 } while (true); | |
687 | |
688 return the_header->next; | |
689 } | |
690 | |
691 void | |
692 write_header (the_header) | |
693 header the_header; | |
694 { | |
695 register header old = the_header; | |
696 do | |
697 { | |
698 register line_list the_list; | |
699 for (the_list = the_header->text; | |
700 the_list != NIL; | |
701 the_list = the_list->continuation) | |
702 put_line (the_list->string); | |
703 the_header = the_header->next; | |
704 } while (the_header != old); | |
705 put_line (""); | |
706 return; | |
707 } | |
708 | |
15683 | 709 int |
18 | 710 main (argc, argv) |
711 int argc; | |
712 char **argv; | |
713 { | |
714 char *command_line; | |
715 header the_header; | |
716 long name_length; | |
717 char *mail_program_name; | |
718 char buf[BUFLEN + 1]; | |
719 register int size; | |
720 FILE *the_pipe; | |
721 | |
722 extern char *getenv (); | |
723 | |
724 mail_program_name = getenv ("FAKEMAILER"); | |
725 if (!(mail_program_name && *mail_program_name)) | |
726 mail_program_name = MAIL_PROGRAM_NAME; | |
727 name_length = strlen (mail_program_name); | |
728 | |
729 my_name = MY_NAME; | |
730 the_streams = ((stream_list) NULL); | |
731 the_date = ((char *) NULL); | |
732 the_user = ((char *) NULL); | |
733 | |
734 the_header = read_header (); | |
735 command_line = alloc_string (name_length + args_size (the_header)); | |
736 strcpy (command_line, mail_program_name); | |
737 parse_header (the_header, &command_line[name_length]); | |
738 | |
739 the_pipe = popen (command_line, "w"); | |
740 if (the_pipe == ((FILE *) NULL)) | |
741 fatal ("cannot open pipe to real mailer"); | |
742 | |
743 add_a_stream (the_pipe, pclose); | |
744 | |
745 write_header (the_header); | |
746 | |
747 /* Dump the message itself */ | |
748 | |
749 while (!feof (stdin)) | |
750 { | |
751 size = fread (buf, 1, BUFLEN, stdin); | |
752 buf[size] = '\0'; | |
753 put_string (buf); | |
754 } | |
755 | |
756 exit (close_the_streams ()); | |
757 } | |
758 | |
5447
6f0905b05218
(main) [MSDOS]: Dummy stub just to make the file compile.
Richard M. Stallman <rms@gnu.org>
parents:
4696
diff
changeset
|
759 #endif /* not MSDOS */ |
18 | 760 #endif /* not BSD 4.2 (or newer) */ |