Mercurial > hg > xemacs-beta
annotate lib-src/fakemail.c @ 4981:4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
-------------------- ChangeLog entries follow: --------------------
modules/ChangeLog addition:
2010-02-05 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c:
* postgresql/postgresql.c (CHECK_LIVE_CONNECTION):
* postgresql/postgresql.c (Fpq_connectdb):
* postgresql/postgresql.c (Fpq_connect_start):
* postgresql/postgresql.c (Fpq_lo_import):
* postgresql/postgresql.c (Fpq_lo_export):
* ldap/eldap.c (Fldap_open):
* ldap/eldap.c (Fldap_search_basic):
* ldap/eldap.c (Fldap_add):
* ldap/eldap.c (Fldap_modify):
* ldap/eldap.c (Fldap_delete):
* canna/canna_api.c (Fcanna_initialize):
* canna/canna_api.c (Fcanna_store_yomi):
* canna/canna_api.c (Fcanna_parse):
* canna/canna_api.c (Fcanna_henkan_begin):
EXTERNAL_TO_C_STRING returns its argument instead of storing it
in a parameter, and is renamed to EXTERNAL_TO_ITEXT. Similar
things happen to related macros. See entry in src/ChangeLog.
More Mule-izing of postgresql.c. Extract out common code
between `pq-connectdb' and `pq-connect-start'. Fix places
that signal an error string using a formatted string to instead
follow the standard and have a fixed reason followed by the
particular error message stored as one of the frobs.
src/ChangeLog addition:
2010-02-05 Ben Wing <ben@xemacs.org>
* console-msw.c (write_string_to_mswindows_debugging_output):
* console-msw.c (Fmswindows_message_box):
* console-x.c (x_perhaps_init_unseen_key_defaults):
* console.c:
* database.c (dbm_get):
* database.c (dbm_put):
* database.c (dbm_remove):
* database.c (berkdb_get):
* database.c (berkdb_put):
* database.c (berkdb_remove):
* database.c (Fopen_database):
* device-gtk.c (gtk_init_device):
* device-msw.c (msprinter_init_device_internal):
* device-msw.c (msprinter_default_printer):
* device-msw.c (msprinter_init_device):
* device-msw.c (sync_printer_with_devmode):
* device-msw.c (Fmsprinter_select_settings):
* device-x.c (sanity_check_geometry_resource):
* device-x.c (Dynarr_add_validified_lisp_string):
* device-x.c (x_init_device):
* device-x.c (Fx_put_resource):
* device-x.c (Fx_valid_keysym_name_p):
* device-x.c (Fx_set_font_path):
* dialog-msw.c (push_lisp_string_as_unicode):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-msw.c (handle_file_dialog_box):
* dialog-x.c (dbox_descriptor_to_widget_value):
* editfns.c (Fformat_time_string):
* editfns.c (Fencode_time):
* editfns.c (Fset_time_zone_rule):
* emacs.c (make_argc_argv):
* emacs.c (Fdump_emacs):
* emodules.c (emodules_load):
* eval.c:
* eval.c (maybe_signal_error_1):
* event-msw.c (Fdde_alloc_advise_item):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (mswindows_wnd_proc):
* fileio.c (report_error_with_errno):
* fileio.c (Fsysnetunam):
* fileio.c (Fdo_auto_save):
* font-mgr.c (extract_fcapi_string):
* font-mgr.c (Ffc_config_app_font_add_file):
* font-mgr.c (Ffc_config_app_font_add_dir):
* font-mgr.c (Ffc_config_filename):
* frame-gtk.c (gtk_set_frame_text_value):
* frame-gtk.c (gtk_create_widgets):
* frame-msw.c (mswindows_init_frame_1):
* frame-msw.c (mswindows_set_title_from_ibyte):
* frame-msw.c (msprinter_init_frame_3):
* frame-x.c (x_set_frame_text_value):
* frame-x.c (x_set_frame_properties):
* frame-x.c (start_drag_internal_1):
* frame-x.c (x_cde_transfer_callback):
* frame-x.c (x_create_widgets):
* glyphs-eimage.c (my_jpeg_output_message):
* glyphs-eimage.c (jpeg_instantiate):
* glyphs-eimage.c (gif_instantiate):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate):
* glyphs-gtk.c (xbm_instantiate_1):
* glyphs-gtk.c (gtk_xbm_instantiate):
* glyphs-gtk.c (gtk_xpm_instantiate):
* glyphs-gtk.c (gtk_xface_instantiate):
* glyphs-gtk.c (cursor_font_instantiate):
* glyphs-gtk.c (gtk_redisplay_widget):
* glyphs-gtk.c (gtk_widget_instantiate_1):
* glyphs-gtk.c (gtk_add_tab_item):
* glyphs-msw.c (mswindows_xpm_instantiate):
* glyphs-msw.c (bmp_instantiate):
* glyphs-msw.c (mswindows_resource_instantiate):
* glyphs-msw.c (xbm_instantiate_1):
* glyphs-msw.c (mswindows_xbm_instantiate):
* glyphs-msw.c (mswindows_xface_instantiate):
* glyphs-msw.c (mswindows_redisplay_widget):
* glyphs-msw.c (mswindows_widget_instantiate):
* glyphs-msw.c (add_tree_item):
* glyphs-msw.c (add_tab_item):
* glyphs-msw.c (mswindows_combo_box_instantiate):
* glyphs-msw.c (mswindows_widget_query_string_geometry):
* glyphs-x.c (x_locate_pixmap_file):
* glyphs-x.c (xbm_instantiate_1):
* glyphs-x.c (x_xbm_instantiate):
* glyphs-x.c (extract_xpm_color_names):
* glyphs-x.c (x_xpm_instantiate):
* glyphs-x.c (x_xface_instantiate):
* glyphs-x.c (autodetect_instantiate):
* glyphs-x.c (safe_XLoadFont):
* glyphs-x.c (cursor_font_instantiate):
* glyphs-x.c (x_redisplay_widget):
* glyphs-x.c (Fchange_subwindow_property):
* glyphs-x.c (x_widget_instantiate):
* glyphs-x.c (x_tab_control_redisplay):
* glyphs.c (pixmap_to_lisp_data):
* gui-x.c (menu_separator_style_and_to_external):
* gui-x.c (add_accel_and_to_external):
* gui-x.c (button_item_to_widget_value):
* hpplay.c (player_error_internal):
* hpplay.c (play_sound_file):
* hpplay.c (play_sound_data):
* intl.c (Fset_current_locale):
* lisp.h:
* menubar-gtk.c (gtk_xemacs_set_accel_keys):
* menubar-msw.c (populate_menu_add_item):
* menubar-msw.c (populate_or_checksum_helper):
* menubar-x.c (menu_item_descriptor_to_widget_value_1):
* nt.c (init_user_info):
* nt.c (get_long_basename):
* nt.c (nt_get_resource):
* nt.c (init_mswindows_environment):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_readdir):
* nt.c (read_unc_volume):
* nt.c (mswindows_stat):
* nt.c (mswindows_getdcwd):
* nt.c (mswindows_executable_type):
* nt.c (Fmswindows_short_file_name):
* ntplay.c (nt_play_sound_file):
* objects-gtk.c:
* objects-gtk.c (gtk_valid_color_name_p):
* objects-gtk.c (gtk_initialize_font_instance):
* objects-gtk.c (gtk_font_list):
* objects-msw.c (font_enum_callback_2):
* objects-msw.c (parse_font_spec):
* objects-x.c (x_parse_nearest_color):
* objects-x.c (x_valid_color_name_p):
* objects-x.c (x_initialize_font_instance):
* objects-x.c (x_font_instance_truename):
* objects-x.c (x_font_list):
* objects-xlike-inc.c (XFUN):
* objects-xlike-inc.c (xft_find_charset_font):
* process-nt.c (mswindows_report_winsock_error):
* process-nt.c (nt_create_process):
* process-nt.c (get_internet_address):
* process-nt.c (nt_open_network_stream):
* process-unix.c:
* process-unix.c (allocate_pty):
* process-unix.c (get_internet_address):
* process-unix.c (unix_canonicalize_host_name):
* process-unix.c (unix_open_network_stream):
* realpath.c:
* select-common.h (lisp_data_to_selection_data):
* select-gtk.c (symbol_to_gtk_atom):
* select-gtk.c (atom_to_symbol):
* select-msw.c (symbol_to_ms_cf):
* select-msw.c (mswindows_register_selection_data_type):
* select-x.c (symbol_to_x_atom):
* select-x.c (x_atom_to_symbol):
* select-x.c (hack_motif_clipboard_selection):
* select-x.c (Fx_store_cutbuffer_internal):
* sound.c (Fplay_sound_file):
* sound.c (Fplay_sound):
* sound.h (sound_perror):
* sysdep.c:
* sysdep.c (qxe_allocating_getcwd):
* sysdep.c (qxe_execve):
* sysdep.c (copy_in_passwd):
* sysdep.c (qxe_getpwnam):
* sysdep.c (qxe_ctime):
* sysdll.c (dll_open):
* sysdll.c (dll_function):
* sysdll.c (dll_variable):
* sysdll.c (search_linked_libs):
* sysdll.c (dll_error):
* sysfile.h:
* sysfile.h (PATHNAME_CONVERT_OUT_TSTR):
* sysfile.h (PATHNAME_CONVERT_OUT_UTF_8):
* sysfile.h (PATHNAME_CONVERT_OUT):
* sysfile.h (LISP_PATHNAME_CONVERT_OUT):
* syswindows.h (ITEXT_TO_TSTR):
* syswindows.h (LOCAL_FILE_FORMAT_TO_TSTR):
* syswindows.h (TSTR_TO_LOCAL_FILE_FORMAT):
* syswindows.h (LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN):
* syswindows.h (LISP_LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR):
* text.h:
* text.h (eicpy_ext_len):
* text.h (enum new_dfc_src_type):
* text.h (EXTERNAL_TO_ITEXT):
* text.h (GET_STRERROR):
* tooltalk.c (check_status):
* tooltalk.c (Fadd_tooltalk_message_arg):
* tooltalk.c (Fadd_tooltalk_pattern_attribute):
* tooltalk.c (Fadd_tooltalk_pattern_arg):
* win32.c (tstr_to_local_file_format):
* win32.c (mswindows_lisp_error_1):
* win32.c (mswindows_report_process_error):
* win32.c (Fmswindows_shell_execute):
* win32.c (mswindows_read_link_1):
Changes involving external/internal format conversion,
mostly code cleanup and renaming.
1. Eliminate the previous macros like LISP_STRING_TO_EXTERNAL
that stored its result in a parameter. The new version of
LISP_STRING_TO_EXTERNAL returns its result through the
return value, same as the previous NEW_LISP_STRING_TO_EXTERNAL.
Use the new-style macros throughout the code.
2. Rename C_STRING_TO_EXTERNAL and friends to ITEXT_TO_EXTERNAL,
in keeping with overall naming rationalization involving
Itext and related types.
Macros involved in previous two:
EXTERNAL_TO_C_STRING -> EXTERNAL_TO_ITEXT
EXTERNAL_TO_C_STRING_MALLOC -> EXTERNAL_TO_ITEXT_MALLOC
SIZED_EXTERNAL_TO_C_STRING -> SIZED_EXTERNAL_TO_ITEXT
SIZED_EXTERNAL_TO_C_STRING_MALLOC -> SIZED_EXTERNAL_TO_ITEXT_MALLOC
C_STRING_TO_EXTERNAL -> ITEXT_TO_EXTERNAL
C_STRING_TO_EXTERNAL_MALLOC -> ITEXT_TO_EXTERNAL_MALLOC
LISP_STRING_TO_EXTERNAL
LISP_STRING_TO_EXTERNAL_MALLOC
LISP_STRING_TO_TSTR
C_STRING_TO_TSTR -> ITEXT_TO_TSTR
TSTR_TO_C_STRING -> TSTR_TO_ITEXT
The following four still return their values through parameters,
since they have more than one value to return:
C_STRING_TO_SIZED_EXTERNAL -> ITEXT_TO_SIZED_EXTERNAL
LISP_STRING_TO_SIZED_EXTERNAL
C_STRING_TO_SIZED_EXTERNAL_MALLOC -> ITEXT_TO_SIZED_EXTERNAL_MALLOC
LISP_STRING_TO_SIZED_EXTERNAL_MALLOC
Sometimes additional casts had to be inserted, since the old
macros played strange games and completely defeated the type system
of the store params.
3. Rewrite many places where direct calls to TO_EXTERNAL_FORMAT
occurred with calls to one of the convenience macros listed above,
or to make_extstring().
4. Eliminate SIZED_C_STRING macros (they were hardly used, anyway)
and use a direct call to TO_EXTERNAL_FORMAT or TO_INTERNAL_FORMAT.
4. Use LISP_PATHNAME_CONVERT_OUT in many places instead of something
like LISP_STRING_TO_EXTERNAL(..., Qfile_name).
5. Eliminate some temporary variables that are no longer necessary
now that we return a value rather than storing it into a variable.
6. Some Mule-izing in database.c.
7. Error functions:
-- A bit of code cleanup in maybe_signal_error_1.
-- Eliminate report_file_type_error; it's just an alias for
signal_error_2 with params in a different order.
-- Fix some places in the hostname-handling code that directly
inserted externally-retrieved error strings into the
supposed ASCII "reason" param instead of doing the right thing
and sticking text descriptive of what was going on in "reason"
and putting the external message in a frob.
8. Use Ascbyte instead of CIbyte in process-unix.c and maybe one
or two other places.
9. Some code cleanup in copy_in_passwd() in sysdep.c.
10. Fix a real bug due to accidental variable shadowing in
tstr_to_local_file_format() in win32.c.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Feb 2010 11:02:24 -0600 |
parents | 8b63e21b0436 |
children | cd167465bf69 061f4f90f874 |
rev | line source |
---|---|
428 | 1 /* sendmail-like interface to /bin/mail for system V, |
2 Copyright (C) 1985, 1994 Free Software Foundation, Inc. | |
3 | |
613 | 4 This file is part of XEmacs. |
428 | 5 |
613 | 6 XEmacs is free software; you can redistribute it and/or modify |
428 | 7 it under the terms of the GNU General Public License as published by |
8 the Free Software Foundation; either version 2, or (at your option) | |
9 any later version. | |
10 | |
613 | 11 XEmacs is distributed in the hope that it will be useful, |
428 | 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 | |
613 | 17 along with XEmacs; see the file COPYING. If not, write to |
428 | 18 the Free the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Synched up with: FSF 19.28. */ | |
22 | |
23 #define NO_SHORTNAMES | |
438 | 24 #include <config.h> |
428 | 25 |
26 #if defined (BSD) && !defined (BSD4_1) && !defined (USE_FAKEMAIL) | |
27 /* This program is not used in BSD, so just avoid loader complaints. */ | |
28 int | |
29 main (int argc, char *argv[]) | |
30 { | |
31 return 0; | |
32 } | |
33 #elif defined (LINUX) | |
34 #include <stdio.h> | |
35 #include <stdlib.h> | |
36 int | |
2509 | 37 main (int argc, char *argv[]) |
428 | 38 { |
39 /* Linux /bin/mail, if it exists, is NOT the Unix v7 mail that | |
40 fakemail depends on! This causes garbled mail. Better to | |
41 output an error message. */ | |
42 fprintf (stderr, "Sorry, fakemail does not work on Linux.\n"); | |
43 fprintf (stderr, "Make sure you have the sendmail program, and\n"); | |
44 fprintf (stderr, "set the Lisp variable `sendmail-program' to point\n"); | |
45 fprintf (stderr, "to the path of the sendmail binary.\n"); | |
46 return 1; | |
47 } | |
48 #else /* not BSD 4.2 (or newer) */ | |
49 | |
50 /* These are defined in config in some versions. */ | |
51 | |
52 #ifdef static | |
53 #undef static | |
54 #endif | |
55 | |
56 #ifdef read | |
57 #undef read | |
58 #undef write | |
59 #undef open | |
60 #undef close | |
61 #endif | |
62 | |
63 #include <stdio.h> | |
64 #if __STDC__ || defined(STDC_HEADERS) | |
65 #include <stdlib.h> | |
66 #include <unistd.h> | |
67 #endif | |
68 #include <string.h> | |
69 #include <ctype.h> | |
70 #include <time.h> | |
71 #include <pwd.h> | |
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)(FILE *); | |
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 { | |
440 | 111 size_t size; |
428 | 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 #define MAIL_PROGRAM_NAME "/bin/mail" | |
135 | |
442 | 136 static const char *my_name; |
428 | 137 static char *the_date; |
138 static char *the_user; | |
139 static line_list file_preface; | |
140 static stream_list the_streams; | |
141 static boolean no_problems = true; | |
142 | |
143 #if !__STDC__ && !defined(STDC_HEADERS) | |
144 extern FILE *popen (); | |
145 extern int fclose (), pclose (); | |
146 extern char *malloc (), *realloc (); | |
147 #endif | |
148 | |
2687 | 149 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400000 |
150 #define CURRENT_USER | |
151 #endif | |
152 | |
428 | 153 #ifdef CURRENT_USER |
154 extern struct passwd *getpwuid (); | |
2687 | 155 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400000 |
156 extern uid_t geteuid (); | |
157 #else | |
158 extern unsigned short geteuid (); | |
159 #endif | |
428 | 160 static struct passwd *my_entry; |
161 #define cuserid(s) \ | |
434 | 162 (my_entry = getpwuid ((int) geteuid ()), \ |
428 | 163 my_entry->pw_name) |
164 #endif | |
165 | |
166 /* Utilities */ | |
167 | |
168 /* Print error message. `s1' is printf control string, `s2' is arg for it. */ | |
169 | |
170 static void | |
442 | 171 error (const char *s1, const char *s2) |
428 | 172 { |
173 printf ("%s: ", my_name); | |
174 printf (s1, s2); | |
175 printf ("\n"); | |
176 no_problems = false; | |
177 } | |
178 | |
179 /* Print error message and exit. */ | |
180 | |
181 static void | |
442 | 182 fatal (const char *s1, const char *s2) |
428 | 183 { |
184 error (s1, s2); | |
185 exit (1); | |
186 } | |
187 | |
188 /* Like malloc but get fatal error if memory is exhausted. */ | |
189 | |
440 | 190 static void * |
428 | 191 xmalloc (size_t size) |
192 { | |
440 | 193 void *result = malloc (size); |
194 if (result == NULL) | |
428 | 195 fatal ("virtual memory exhausted", (char *) 0); |
196 return result; | |
197 } | |
198 | |
440 | 199 static void * |
200 xrealloc (void *ptr, size_t size) | |
428 | 201 { |
440 | 202 void *result = realloc (ptr, size); |
203 if (result == NULL) | |
428 | 204 fatal ("virtual memory exhausted", (char *) 0); |
205 return result; | |
206 } | |
207 | |
208 /* Initialize a linebuffer for use */ | |
209 | |
210 static void | |
211 init_linebuffer (struct linebuffer *linebuffer) | |
212 { | |
213 linebuffer->size = INITIAL_LINE_SIZE; | |
440 | 214 linebuffer->buffer = (char *) xmalloc (INITIAL_LINE_SIZE); |
428 | 215 } |
216 | |
217 /* Read a line of text from `stream' into `linebuffer'. | |
218 * Return the length of the line. | |
219 */ | |
220 | |
221 static long | |
222 readline (struct linebuffer *linebuffer, 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; | |
440 | 234 buffer = (char *) xrealloc (buffer, linebuffer->size); |
428 | 235 p = buffer + (p - linebuffer->buffer); |
236 end = buffer + linebuffer->size; | |
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 | |
250 static char * | |
251 get_keyword (register char *field, char **rest) | |
252 { | |
253 static char keyword[KEYWORD_SIZE]; | |
254 register char *ptr; | |
255 register char c; | |
256 | |
257 ptr = &keyword[0]; | |
258 c = *field++; | |
259 if ((isspace ((int) (unsigned char) c)) || (c == ':')) | |
260 return (char *) NULL; | |
261 *ptr++ = ((islower ((int) (unsigned char) c)) ? | |
262 (toupper ((int) (unsigned char) c)) : c); | |
263 while (((c = *field++) != ':') && | |
264 (!(isspace ((int) (unsigned char) c)))) | |
265 *ptr++ = ((islower ((int) (unsigned char) c)) ? | |
266 (toupper ((int) (unsigned char) c)) : c); | |
267 *ptr++ = '\0'; | |
268 while (isspace ((int) (unsigned char) c)) c = *field++; | |
269 if (c != ':') return (char *) NULL; | |
270 *rest = field; | |
271 return &keyword[0]; | |
272 } | |
273 | |
274 static boolean | |
275 has_keyword (char *field) | |
276 { | |
277 char *ignored; | |
440 | 278 return (get_keyword (field, &ignored) != (char *) NULL); |
428 | 279 } |
280 | |
281 static char * | |
282 add_field (line_list the_list, register char *field, register char *where) | |
283 { | |
284 register char c; | |
285 while (true) | |
286 { | |
287 *where++ = ' '; | |
288 while ((c = *field++) != '\0') | |
289 { | |
290 if (c == '(') | |
291 { | |
292 while (*field && *field != ')') ++field; | |
293 if (! (*field++)) break; /* no closer */ | |
294 if (! (*field)) break; /* closerNULL */ | |
295 c = *field; | |
296 } | |
297 *where++ = ((c == ','||c=='>'||c=='<') ? ' ' : c); | |
298 } | |
299 if (the_list == NIL) break; | |
300 field = the_list->string; | |
301 the_list = the_list->continuation; | |
302 } | |
303 return where; | |
304 } | |
305 | |
306 static line_list | |
307 make_file_preface (void) | |
308 { | |
309 char *the_string, *temp; | |
442 | 310 time_t idiotic_interface; |
428 | 311 long prefix_length; |
312 long user_length; | |
313 long date_length; | |
314 line_list result; | |
315 | |
316 prefix_length = strlen (FROM_PREFIX); | |
317 time (&idiotic_interface); | |
318 the_date = ctime (&idiotic_interface); | |
319 /* the_date has an unwanted newline at the end */ | |
320 date_length = strlen (the_date) - 1; | |
442 | 321 if (the_date[date_length] == '\n') |
322 the_date[date_length] = '\0'; | |
323 #ifdef WIN32_NATIVE | |
428 | 324 temp = "(null)"; |
325 #else | |
326 temp = cuserid ((char *) NULL); | |
327 #endif | |
328 user_length = strlen (temp); | |
329 the_user = alloc_string ((size_t) (user_length + 1)); | |
330 strcpy (the_user, temp); | |
331 the_string = alloc_string ((size_t) (3 + prefix_length + | |
332 user_length + | |
333 date_length)); | |
334 temp = the_string; | |
335 strcpy (temp, FROM_PREFIX); | |
336 temp = &temp[prefix_length]; | |
337 *temp++ = ' '; | |
338 strcpy (temp, the_user); | |
339 temp = &temp[user_length]; | |
340 *temp++ = ' '; | |
341 strcpy (temp, the_date); | |
342 result = new_list (); | |
343 result->string = the_string; | |
344 result->continuation = ((line_list) NULL); | |
345 return result; | |
346 } | |
347 | |
348 static void | |
349 write_line_list (register line_list the_list, FILE *the_stream) | |
350 { | |
351 for ( ; | |
352 the_list != ((line_list) NULL) ; | |
353 the_list = the_list->continuation) | |
354 { | |
355 fputs (the_list->string, the_stream); | |
356 putc ('\n', the_stream); | |
357 } | |
358 return; | |
359 } | |
360 | |
361 static int | |
362 close_the_streams (void) | |
363 { | |
364 register stream_list rem; | |
365 for (rem = the_streams; | |
366 rem != ((stream_list) NULL); | |
367 rem = rem->rest_streams) | |
368 no_problems = (no_problems && | |
369 ((*rem->action) (rem->handle) == 0)); | |
370 the_streams = ((stream_list) NULL); | |
371 return (no_problems ? 0 : 1); | |
372 } | |
373 | |
374 static void | |
375 add_a_stream (FILE *the_stream, int (*closing_action)(FILE *)) | |
376 { | |
377 stream_list old = the_streams; | |
378 the_streams = new_stream (); | |
379 the_streams->handle = the_stream; | |
380 the_streams->action = closing_action; | |
381 the_streams->rest_streams = old; | |
382 return; | |
383 } | |
384 | |
385 static int | |
386 my_fclose (FILE *the_file) | |
387 { | |
388 putc ('\n', the_file); | |
389 fflush (the_file); | |
390 return fclose (the_file); | |
391 } | |
392 | |
393 static boolean | |
394 open_a_file (char *name) | |
395 { | |
396 FILE *the_stream = fopen (name, "a"); | |
397 if (the_stream != ((FILE *) NULL)) | |
398 { | |
399 add_a_stream (the_stream, my_fclose); | |
440 | 400 if (the_user == (char *) NULL) |
428 | 401 file_preface = make_file_preface (); |
402 write_line_list (file_preface, the_stream); | |
403 return true; | |
404 } | |
405 return false; | |
406 } | |
407 | |
408 static void | |
409 put_string (char *s) | |
410 { | |
411 register stream_list rem; | |
412 for (rem = the_streams; | |
413 rem != ((stream_list) NULL); | |
414 rem = rem->rest_streams) | |
415 fputs (s, rem->handle); | |
416 return; | |
417 } | |
418 | |
419 static void | |
442 | 420 put_line (const char *string) |
428 | 421 { |
422 register stream_list rem; | |
423 for (rem = the_streams; | |
424 rem != ((stream_list) NULL); | |
425 rem = rem->rest_streams) | |
426 { | |
442 | 427 const char *s = string; |
428 | 428 int column = 0; |
429 | |
430 /* Divide STRING into lines. */ | |
431 while (*s != 0) | |
432 { | |
442 | 433 const char *breakpos; |
428 | 434 |
435 /* Find the last char that fits. */ | |
436 for (breakpos = s; *breakpos && column < 78; ++breakpos) | |
437 { | |
438 if (*breakpos == '\t') | |
439 column += 8; | |
440 else | |
441 column++; | |
442 } | |
443 /* If we didn't reach end of line, break the line. */ | |
444 if (*breakpos) | |
445 { | |
446 /* Back up to just after the last comma that fits. */ | |
447 while (breakpos != s && breakpos[-1] != ',') --breakpos; | |
448 | |
449 if (breakpos == s) | |
450 { | |
451 /* If no comma fits, move past the first address anyway. */ | |
452 while (*breakpos != 0 && *breakpos != ',') ++breakpos; | |
453 if (*breakpos != 0) | |
454 /* Include the comma after it. */ | |
455 ++breakpos; | |
456 } | |
457 } | |
458 /* Output that much, then break the line. */ | |
459 fwrite (s, 1, breakpos - s, rem->handle); | |
460 column = 8; | |
461 | |
462 /* Skip whitespace and prepare to print more addresses. */ | |
463 s = breakpos; | |
464 while (*s == ' ' || *s == '\t') ++s; | |
465 if (*s != 0) | |
466 fputs ("\n\t", rem->handle); | |
467 } | |
468 putc ('\n', rem->handle); | |
469 } | |
470 return; | |
471 } | |
472 | |
473 #define mail_error error | |
474 | |
475 static void | |
476 setup_files (register line_list the_list, register char *field) | |
477 { | |
478 register char *start; | |
479 register char c; | |
480 while (true) | |
481 { | |
482 while (((c = *field) != '\0') && | |
483 ((c == ' ') || | |
484 (c == '\t') || | |
485 (c == ','))) | |
486 field += 1; | |
487 if (c != '\0') | |
488 { | |
489 start = field; | |
490 while (((c = *field) != '\0') && | |
491 (c != ' ') && | |
492 (c != '\t') && | |
493 (c != ',')) | |
494 field += 1; | |
495 *field = '\0'; | |
496 if (!open_a_file (start)) | |
497 mail_error ("Could not open file %s", start); | |
498 *field = c; | |
499 if (c != '\0') continue; | |
500 } | |
501 if (the_list == ((line_list) NULL)) return; | |
502 field = the_list->string; | |
503 the_list = the_list->continuation; | |
504 } | |
505 } | |
506 | |
507 static int | |
508 args_size (header the_header) | |
509 { | |
510 register header old = the_header; | |
511 register line_list rem; | |
512 register int size = 0; | |
513 do | |
514 { | |
4932 | 515 char *field = NULL; |
428 | 516 register char *keyword = get_keyword (the_header->text->string, &field); |
517 if ((strcmp (keyword, "TO") == 0) || | |
518 (strcmp (keyword, "CC") == 0) || | |
519 (strcmp (keyword, "BCC") == 0)) | |
520 { | |
521 size += 1 + strlen (field); | |
522 for (rem = the_header->text->continuation; | |
523 rem != NIL; | |
524 rem = rem->continuation) | |
525 size += 1 + strlen (rem->string); | |
526 } | |
527 the_header = the_header->next; | |
528 } while (the_header != old); | |
529 return size; | |
530 } | |
531 | |
532 static void | |
533 parse_header (header the_header, register char *where) | |
534 { | |
535 register header old = the_header; | |
536 do | |
537 { | |
4932 | 538 char *field = NULL; |
428 | 539 register char *keyword = get_keyword (the_header->text->string, &field); |
540 if (strcmp (keyword, "TO") == 0) | |
541 where = add_field (the_header->text->continuation, field, where); | |
542 else if (strcmp (keyword, "CC") == 0) | |
543 where = add_field (the_header->text->continuation, field, where); | |
544 else if (strcmp (keyword, "BCC") == 0) | |
545 { | |
546 where = add_field (the_header->text->continuation, field, where); | |
547 the_header->previous->next = the_header->next; | |
548 the_header->next->previous = the_header->previous; | |
549 } | |
550 else if (strcmp (keyword, "FCC") == 0) | |
551 setup_files (the_header->text->continuation, field); | |
552 the_header = the_header->next; | |
553 } while (the_header != old); | |
554 *where = '\0'; | |
555 return; | |
556 } | |
557 | |
558 static header | |
559 read_header (void) | |
560 { | |
561 register header the_header = ((header) NULL); | |
562 register line_list *next_line = ((line_list *) NULL); | |
563 | |
564 init_linebuffer (&lb); | |
565 | |
566 do | |
567 { | |
568 long length; | |
569 register char *line; | |
570 | |
571 readline (&lb, stdin); | |
572 line = lb.buffer; | |
573 length = strlen (line); | |
574 if (length == 0) break; | |
575 | |
576 if (has_keyword (line)) | |
577 { | |
578 register header old = the_header; | |
579 the_header = new_header (); | |
580 if (old == ((header) NULL)) | |
581 { | |
582 the_header->next = the_header; | |
583 the_header->previous = the_header; | |
584 } | |
585 else | |
586 { | |
587 the_header->previous = old; | |
588 the_header->next = old->next; | |
589 old->next = the_header; | |
590 } | |
591 next_line = &(the_header->text); | |
592 } | |
593 | |
594 if (next_line == ((line_list *) NULL)) | |
595 { | |
596 /* Not a valid header */ | |
597 exit (1); | |
598 } | |
599 *next_line = new_list (); | |
600 (*next_line)->string = alloc_string ((size_t) length); | |
601 strcpy (((*next_line)->string), line); | |
602 next_line = &((*next_line)->continuation); | |
603 *next_line = NIL; | |
604 | |
605 } while (true); | |
606 | |
607 return the_header->next; | |
608 } | |
609 | |
610 static void | |
611 write_header (header the_header) | |
612 { | |
613 register header old = the_header; | |
614 do | |
615 { | |
616 register line_list the_list; | |
617 for (the_list = the_header->text; | |
618 the_list != NIL; | |
619 the_list = the_list->continuation) | |
620 put_line (the_list->string); | |
621 the_header = the_header->next; | |
622 } while (the_header != old); | |
623 put_line (""); | |
624 return; | |
625 } | |
626 | |
627 int | |
628 main (int argc, char *argv[]) | |
629 { | |
630 char *command_line; | |
631 header the_header; | |
632 long name_length; | |
4759
aa5ed11f473b
Remove support for obsolete systems. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
2687
diff
changeset
|
633 const char *mail_program_name; |
428 | 634 char buf[BUFLEN + 1]; |
635 register int size; | |
636 FILE *the_pipe; | |
637 | |
638 mail_program_name = getenv ("FAKEMAILER"); | |
639 if (!(mail_program_name && *mail_program_name)) | |
4759
aa5ed11f473b
Remove support for obsolete systems. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
2687
diff
changeset
|
640 mail_program_name = MAIL_PROGRAM_NAME; |
428 | 641 name_length = strlen (mail_program_name); |
642 | |
643 my_name = MY_NAME; | |
644 the_streams = ((stream_list) NULL); | |
440 | 645 the_date = (char *) NULL; |
646 the_user = (char *) NULL; | |
428 | 647 |
648 the_header = read_header (); | |
649 command_line = alloc_string ((size_t) (name_length + | |
650 args_size (the_header))); | |
651 strcpy (command_line, mail_program_name); | |
652 parse_header (the_header, &command_line[name_length]); | |
653 | |
654 the_pipe = popen (command_line, "w"); | |
655 if (the_pipe == ((FILE *) NULL)) | |
440 | 656 fatal ("cannot open pipe to real mailer", (char *) NULL); |
428 | 657 |
658 add_a_stream (the_pipe, pclose); | |
659 | |
660 write_header (the_header); | |
661 | |
662 /* Dump the message itself */ | |
663 | |
664 while (!feof (stdin)) | |
665 { | |
666 size = fread (buf, 1, BUFLEN, stdin); | |
667 buf[size] = '\0'; | |
668 put_string (buf); | |
669 } | |
670 | |
671 return close_the_streams (); | |
672 } | |
673 | |
674 #endif /* not BSD 4.2 (or newer) */ |