Mercurial > hg > xemacs-beta
annotate lib-src/i.c @ 4952:19a72041c5ed
Mule-izing, various fixes related to char * arguments
-------------------- ChangeLog entries follow: --------------------
modules/ChangeLog addition:
2010-01-26 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c:
* postgresql/postgresql.c (CHECK_LIVE_CONNECTION):
* postgresql/postgresql.c (print_pgresult):
* postgresql/postgresql.c (Fpq_conn_defaults):
* postgresql/postgresql.c (Fpq_connectdb):
* postgresql/postgresql.c (Fpq_connect_start):
* postgresql/postgresql.c (Fpq_result_status):
* postgresql/postgresql.c (Fpq_res_status):
Mule-ize large parts of it.
2010-01-26 Ben Wing <ben@xemacs.org>
* ldap/eldap.c (print_ldap):
* ldap/eldap.c (allocate_ldap):
Use write_ascstring().
src/ChangeLog addition:
2010-01-26 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (build_ascstring):
* alloc.c (build_msg_cistring):
* alloc.c (staticpro_1):
* alloc.c (staticpro_name):
* alloc.c (staticpro_nodump_1):
* alloc.c (staticpro_nodump_name):
* alloc.c (unstaticpro_nodump_1):
* alloc.c (mcpro_1):
* alloc.c (mcpro_name):
* alloc.c (object_memory_usage_stats):
* alloc.c (common_init_alloc_early):
* alloc.c (init_alloc_once_early):
* buffer.c (print_buffer):
* buffer.c (vars_of_buffer):
* buffer.c (common_init_complex_vars_of_buffer):
* buffer.c (init_initial_directory):
* bytecode.c (invalid_byte_code):
* bytecode.c (print_compiled_function):
* bytecode.c (mark_compiled_function):
* chartab.c (print_table_entry):
* chartab.c (print_char_table):
* config.h.in:
* console-gtk.c:
* console-gtk.c (gtk_device_to_console_connection):
* console-gtk.c (gtk_semi_canonicalize_console_connection):
* console-gtk.c (gtk_canonicalize_console_connection):
* console-gtk.c (gtk_semi_canonicalize_device_connection):
* console-gtk.c (gtk_canonicalize_device_connection):
* console-stream.c (stream_init_frame_1):
* console-stream.c (vars_of_console_stream):
* console-stream.c (init_console_stream):
* console-x.c (x_semi_canonicalize_console_connection):
* console-x.c (x_semi_canonicalize_device_connection):
* console-x.c (x_canonicalize_device_connection):
* console-x.h:
* data.c (eq_with_ebola_notice):
* data.c (Fsubr_interactive):
* data.c (Fnumber_to_string):
* data.c (digit_to_number):
* device-gtk.c (gtk_init_device):
* device-msw.c (print_devmode):
* device-x.c (x_event_name):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-msw.c (handle_file_dialog_box):
* dialog-msw.c (vars_of_dialog_mswindows):
* doc.c (weird_doc):
* doc.c (Fsnarf_documentation):
* doc.c (vars_of_doc):
* dumper.c (pdump):
* dynarr.c:
* dynarr.c (Dynarr_realloc):
* editfns.c (Fuser_real_login_name):
* editfns.c (get_home_directory):
* elhash.c (print_hash_table_data):
* elhash.c (print_hash_table):
* emacs.c (main_1):
* emacs.c (vars_of_emacs):
* emodules.c:
* emodules.c (_emodules_list):
* emodules.c (Fload_module):
* emodules.c (Funload_module):
* emodules.c (Flist_modules):
* emodules.c (find_make_module):
* emodules.c (attempt_module_delete):
* emodules.c (emodules_load):
* emodules.c (emodules_doc_subr):
* emodules.c (emodules_doc_sym):
* emodules.c (syms_of_module):
* emodules.c (vars_of_module):
* emodules.h:
* eval.c (print_subr):
* eval.c (signal_call_debugger):
* eval.c (build_error_data):
* eval.c (signal_error):
* eval.c (maybe_signal_error):
* eval.c (signal_continuable_error):
* eval.c (maybe_signal_continuable_error):
* eval.c (signal_error_2):
* eval.c (maybe_signal_error_2):
* eval.c (signal_continuable_error_2):
* eval.c (maybe_signal_continuable_error_2):
* eval.c (signal_ferror):
* eval.c (maybe_signal_ferror):
* eval.c (signal_continuable_ferror):
* eval.c (maybe_signal_continuable_ferror):
* eval.c (signal_ferror_with_frob):
* eval.c (maybe_signal_ferror_with_frob):
* eval.c (signal_continuable_ferror_with_frob):
* eval.c (maybe_signal_continuable_ferror_with_frob):
* eval.c (syntax_error):
* eval.c (syntax_error_2):
* eval.c (maybe_syntax_error):
* eval.c (sferror):
* eval.c (sferror_2):
* eval.c (maybe_sferror):
* eval.c (invalid_argument):
* eval.c (invalid_argument_2):
* eval.c (maybe_invalid_argument):
* eval.c (invalid_constant):
* eval.c (invalid_constant_2):
* eval.c (maybe_invalid_constant):
* eval.c (invalid_operation):
* eval.c (invalid_operation_2):
* eval.c (maybe_invalid_operation):
* eval.c (invalid_change):
* eval.c (invalid_change_2):
* eval.c (maybe_invalid_change):
* eval.c (invalid_state):
* eval.c (invalid_state_2):
* eval.c (maybe_invalid_state):
* eval.c (wtaerror):
* eval.c (stack_overflow):
* eval.c (out_of_memory):
* eval.c (print_multiple_value):
* eval.c (issue_call_trapping_problems_warning):
* eval.c (backtrace_specials):
* eval.c (backtrace_unevalled_args):
* eval.c (Fbacktrace):
* eval.c (warn_when_safe):
* event-Xt.c (modwarn):
* event-Xt.c (modbarf):
* event-Xt.c (check_modifier):
* event-Xt.c (store_modifier):
* event-Xt.c (emacs_Xt_format_magic_event):
* event-Xt.c (describe_event):
* event-gtk.c (dragndrop_data_received):
* event-gtk.c (store_modifier):
* event-gtk.c (gtk_reset_modifier_mapping):
* event-msw.c (dde_eval_string):
* event-msw.c (Fdde_alloc_advise_item):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (FROB):
* event-msw.c (emacs_mswindows_format_magic_event):
* event-stream.c (external_debugging_print_event):
* event-stream.c (execute_help_form):
* event-stream.c (vars_of_event_stream):
* events.c (print_event_1):
* events.c (print_event):
* events.c (event_equal):
* extents.c (print_extent_1):
* extents.c (print_extent):
* extents.c (vars_of_extents):
* faces.c (print_face):
* faces.c (complex_vars_of_faces):
* file-coding.c:
* file-coding.c (print_coding_system):
* file-coding.c (print_coding_system_in_print_method):
* file-coding.c (default_query_method):
* file-coding.c (find_coding_system):
* file-coding.c (make_coding_system_1):
* file-coding.c (chain_print):
* file-coding.c (undecided_print):
* file-coding.c (gzip_print):
* file-coding.c (vars_of_file_coding):
* file-coding.c (complex_vars_of_file_coding):
* fileio.c:
* fileio.c (report_file_type_error):
* fileio.c (report_error_with_errno):
* fileio.c (report_file_error):
* fileio.c (barf_or_query_if_file_exists):
* fileio.c (vars_of_fileio):
* floatfns.c (matherr):
* fns.c (print_bit_vector):
* fns.c (Fmapconcat):
* fns.c (add_suffix_to_symbol):
* fns.c (add_prefix_to_symbol):
* frame-gtk.c:
* frame-gtk.c (Fgtk_window_id):
* frame-x.c (def):
* frame-x.c (x_cde_transfer_callback):
* frame.c:
* frame.c (Fmake_frame):
* gc.c (show_gc_cursor_and_message):
* gc.c (vars_of_gc):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate):
* glyphs-gtk.c (gtk_print_image_instance):
* glyphs-msw.c (mswindows_print_image_instance):
* glyphs-x.c (x_print_image_instance):
* glyphs-x.c (update_widget_face):
* glyphs.c (make_string_from_file):
* glyphs.c (print_image_instance):
* glyphs.c (signal_image_error):
* glyphs.c (signal_image_error_2):
* glyphs.c (signal_double_image_error):
* glyphs.c (signal_double_image_error_2):
* glyphs.c (xbm_mask_file_munging):
* glyphs.c (pixmap_to_lisp_data):
* glyphs.h:
* gui.c (gui_item_display_flush_left):
* hpplay.c (player_error_internal):
* hpplay.c (myHandler):
* intl-win32.c:
* intl-win32.c (langcode_to_lang):
* intl-win32.c (sublangcode_to_lang):
* intl-win32.c (Fmswindows_get_locale_info):
* intl-win32.c (lcid_to_locale_mule_or_no):
* intl-win32.c (mswindows_multibyte_to_unicode_print):
* intl-win32.c (complex_vars_of_intl_win32):
* keymap.c:
* keymap.c (print_keymap):
* keymap.c (ensure_meta_prefix_char_keymapp):
* keymap.c (Fkey_description):
* keymap.c (Ftext_char_description):
* lisp.h:
* lisp.h (struct):
* lisp.h (DECLARE_INLINE_HEADER):
* lread.c (Fload_internal):
* lread.c (locate_file):
* lread.c (read_escape):
* lread.c (read_raw_string):
* lread.c (read1):
* lread.c (read_list):
* lread.c (read_compiled_function):
* lread.c (init_lread):
* lrecord.h:
* marker.c (print_marker):
* marker.c (marker_equal):
* menubar-msw.c (displayable_menu_item):
* menubar-x.c (command_builder_operate_menu_accelerator):
* menubar.c (vars_of_menubar):
* minibuf.c (reinit_complex_vars_of_minibuf):
* minibuf.c (complex_vars_of_minibuf):
* mule-charset.c (Fmake_charset):
* mule-charset.c (complex_vars_of_mule_charset):
* mule-coding.c (iso2022_print):
* mule-coding.c (fixed_width_query):
* number.c (bignum_print):
* number.c (ratio_print):
* number.c (bigfloat_print):
* number.c (bigfloat_finalize):
* objects-msw.c:
* objects-msw.c (mswindows_color_to_string):
* objects-msw.c (mswindows_color_list):
* objects-tty.c:
* objects-tty.c (tty_font_list):
* objects-tty.c (tty_find_charset_font):
* objects-xlike-inc.c (xft_find_charset_font):
* objects-xlike-inc.c (endif):
* print.c:
* print.c (write_istring):
* print.c (write_ascstring):
* print.c (Fterpri):
* print.c (Fprint):
* print.c (print_error_message):
* print.c (print_vector_internal):
* print.c (print_cons):
* print.c (print_string):
* print.c (printing_unreadable_object):
* print.c (print_internal):
* print.c (print_float):
* print.c (print_symbol):
* process-nt.c (mswindows_report_winsock_error):
* process-nt.c (nt_canonicalize_host_name):
* process-unix.c (unix_canonicalize_host_name):
* process.c (print_process):
* process.c (report_process_error):
* process.c (report_network_error):
* process.c (make_process_internal):
* process.c (Fstart_process_internal):
* process.c (status_message):
* process.c (putenv_internal):
* process.c (vars_of_process):
* process.h:
* profile.c (vars_of_profile):
* rangetab.c (print_range_table):
* realpath.c (vars_of_realpath):
* redisplay.c (vars_of_redisplay):
* search.c (wordify):
* search.c (Freplace_match):
* sheap.c (sheap_adjust_h):
* sound.c (report_sound_error):
* sound.c (Fplay_sound_file):
* specifier.c (print_specifier):
* symbols.c (Fsubr_name):
* symbols.c (do_symval_forwarding):
* symbols.c (set_default_buffer_slot_variable):
* symbols.c (set_default_console_slot_variable):
* symbols.c (store_symval_forwarding):
* symbols.c (default_value):
* symbols.c (defsymbol_massage_name_1):
* symbols.c (defsymbol_massage_name_nodump):
* symbols.c (defsymbol_massage_name):
* symbols.c (defsymbol_massage_multiword_predicate_nodump):
* symbols.c (defsymbol_massage_multiword_predicate):
* symbols.c (defsymbol_nodump):
* symbols.c (defsymbol):
* symbols.c (defkeyword):
* symbols.c (defkeyword_massage_name):
* symbols.c (check_module_subr):
* symbols.c (deferror_1):
* symbols.c (deferror):
* symbols.c (deferror_massage_name):
* symbols.c (deferror_massage_name_and_message):
* symbols.c (defvar_magic):
* symeval.h:
* symeval.h (DEFVAR_SYMVAL_FWD):
* sysdep.c:
* sysdep.c (init_system_name):
* sysdll.c:
* sysdll.c (MAYBE_PREPEND_UNDERSCORE):
* sysdll.c (dll_function):
* sysdll.c (dll_variable):
* sysdll.c (dll_error):
* sysdll.c (dll_open):
* sysdll.c (dll_close):
* sysdll.c (image_for_address):
* sysdll.c (my_find_image):
* sysdll.c (search_linked_libs):
* sysdll.h:
* sysfile.h:
* sysfile.h (DEFAULT_DIRECTORY_FALLBACK):
* syswindows.h:
* tests.c (DFC_CHECK_LENGTH):
* tests.c (DFC_CHECK_CONTENT):
* tests.c (Ftest_hash_tables):
* text.c (vars_of_text):
* text.h:
* tooltalk.c (tt_opnum_string):
* tooltalk.c (tt_message_arg_ival_string):
* tooltalk.c (Ftooltalk_default_procid):
* tooltalk.c (Ftooltalk_default_session):
* tooltalk.c (init_tooltalk):
* tooltalk.c (vars_of_tooltalk):
* ui-gtk.c (Fdll_load):
* ui-gtk.c (type_to_marshaller_type):
* ui-gtk.c (Fgtk_import_function_internal):
* ui-gtk.c (emacs_gtk_object_printer):
* ui-gtk.c (emacs_gtk_boxed_printer):
* unicode.c (unicode_to_ichar):
* unicode.c (unicode_print):
* unicode.c (unicode_query):
* unicode.c (vars_of_unicode):
* unicode.c (complex_vars_of_unicode):
* win32.c:
* win32.c (mswindows_report_process_error):
* window.c (print_window):
* xemacs.def.in.in:
BASIC IDEA: Further fixing up uses of char * and CIbyte *
to reflect their actual semantics; Mule-izing some code;
redoing of the not-yet-working code to handle message translation.
Clean up code to handle message-translation (not yet working).
Create separate versions of build_msg_string() for working with
Ibyte *, CIbyte *, and Ascbyte * arguments. Assert that Ascbyte *
arguments are pure-ASCII. Make build_msg_string() be the same
as build_msg_ascstring(). Create same three versions of GETTEXT()
and DEFER_GETTEXT(). Also create build_defer_string() and
variants for the equivalent of DEFER_GETTEXT() when building a
string. Remove old CGETTEXT(). Clean up code where GETTEXT(),
DEFER_GETTEXT(), build_msg_string(), etc. was being called and
introduce some new calls to build_msg_string(), etc. Remove
GETTEXT() from calls to weird_doc() -- we assume that the
message snarfer knows about weird_doc(). Remove uses of
DEFER_GETTEXT() from error messages in sysdep.c and instead use
special comments /* @@@begin-snarf@@@ */ and /* @@@end-snarf@@@ */
that the message snarfer presumably knows about.
Create build_ascstring() and use it in many instances in place
of build_string(). The purpose of having Ascbyte * variants is
to make the code more self-documenting in terms of what sort of
semantics is expected for char * strings. In fact in the process
of looking for uses of build_string(), much improperly Mule-ized
was discovered.
Mule-ize a lot of code as described in previous paragraph,
e.g. in sysdep.c.
Make the error functions take Ascbyte * strings and fix up a
couple of places where non-pure-ASCII strings were being passed in
(file-coding.c, mule-coding.c, unicode.c). (It's debatable whether
we really need to make the error functions work this way. It
helps catch places where code is written in a way that message
translation won't work, but we may well never implement message
translation.)
Make staticpro() and friends take Ascbyte * strings instead of
raw char * strings. Create a const_Ascbyte_ptr dynarr type
to describe what's held by staticpro_names[] and friends,
create pdump descriptions for const_Ascbyte_ptr dynarrs, and
use them in place of specially-crafted staticpro descriptions.
Mule-ize certain other functions (e.g. x_event_name) by correcting
raw use of char * to Ascbyte *, Rawbyte * or another such type,
and raw use of char[] buffers to another type (usually Ascbyte[]).
Change many uses of write_c_string() to write_msg_string(),
write_ascstring(), etc.
Mule-ize emodules.c, emodules.h, sysdll.h.
Fix some un-Mule-ized code in intl-win32.c.
A comment in event-Xt.c and the limitations of the message
snarfer (make-msgfile or whatever) is presumably incorrect --
it should be smart enough to handle function calls spread over
more than one line. Clean up code in event-Xt.c that was
written awkwardly for this reason.
In config.h.in, instead of NEED_ERROR_CHECK_TYPES_INLINES,
create a more general XEMACS_DEFS_NEEDS_INLINE_DECLS to
indicate when inlined functions need to be declared in
xemacs.defs.in.in, and make use of it in xemacs.defs.in.in.
We need to do this because postgresql.c now calls qxestrdup(),
which is an inline function.
Make nconc2() and other such functions MODULE_API and put
them in xemacs.defs.in.in since postgresql.c now uses them.
Clean up indentation in lread.c and a few other places.
In text.h, document ASSERT_ASCTEXT_ASCII() and
ASSERT_ASCTEXT_ASCII_LEN(), group together the stand-in
encodings and add some more for DLL symbols, function and
variable names, etc.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Tue, 26 Jan 2010 23:22:30 -0600 |
parents | 49316578f12d |
children | 308d34e9f07d |
rev | line source |
---|---|
442 | 1 /* I-connector utility |
2 Copyright (C) 2000 Kirill M. Katsnelson | |
1346 | 3 Copyright (C) 2002, 2003 Ben Wing. |
442 | 4 |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* When run with an argument, i treats it as a command line, and pipes | |
23 command stdin, stdout and stderr to its own respective streams. How | |
24 silly it should sound, but windowed program in Win32 cannot do output | |
25 to the console from which it has been started, and should be run using | |
26 this utility. | |
27 | |
28 This utility is for running [tx]emacs as part of make process so that | |
29 its output goes to the same console as the rest of the make output | |
30 does. It can be used also when xemacs should be run as a batch | |
31 command ina script, especially when its standart output should be | |
32 obtained programmatically. */ | |
33 | |
2993 | 34 #ifdef HAVE_CONFIG_H |
35 # include <config.h> | |
36 #endif | |
37 | |
442 | 38 #include <windows.h> |
39 #include <stdio.h> | |
40 #include <string.h> | |
41 #include <tchar.h> | |
42 | |
43 typedef struct | |
44 { | |
45 HANDLE source; | |
46 HANDLE drain; | |
47 } I_connector; | |
48 | |
49 /* | |
50 * Make new handle as that pointed to by PH but | |
51 * inheritable, substitute PH with it, and close the | |
52 * original one | |
53 */ | |
54 static void | |
55 make_inheritable (HANDLE* ph) | |
56 { | |
57 HANDLE htmp; | |
58 DuplicateHandle (GetCurrentProcess(), *ph, GetCurrentProcess(), &htmp, | |
59 0, TRUE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); | |
60 *ph = htmp; | |
61 } | |
62 | |
63 /* | |
64 * Worker thread proc. Reads source, pumps into drain, | |
65 * till either clogs. | |
66 */ | |
67 static DWORD CALLBACK | |
68 pump (LPVOID pv_i) | |
69 { | |
70 I_connector* pi = (I_connector*) pv_i; | |
71 BYTE buffer [256]; | |
72 DWORD really_read, unused; | |
73 | |
2426 | 74 /* I said: |
75 | |
76 [[ The docs for ReadFile claim: | |
1346 | 77 |
78 The ReadFile function returns when one of the following is true: a write | |
79 operation completes on the write end of the pipe, the number of bytes | |
80 requested has been read, or an error occurs. | |
81 | |
82 But this is just not true. ReadFile never seems to block, and unless we | |
2426 | 83 Sleep(), we will chew up all the CPU time. --ben ]] |
84 | |
85 But in fact | |
86 | |
87 [a] this does not appear to be the case any more [maybe a temporary | |
88 bug in some versions of Win2000?] | |
89 [b] it causes data lossage. [#### Why should this be? Seems extremely | |
90 fishy. I tried commenting out the calls to close the standard | |
91 handles at the bottom of the program, but it made no difference. | |
92 Would we need some kind of additional handshaking? If we get | |
93 data loss with the sleep, then we are a race condition waiting | |
94 to happen. */ | |
442 | 95 while (ReadFile (pi->source, buffer, sizeof (buffer), &really_read, NULL) && |
96 WriteFile (pi->drain, buffer, really_read, &unused, NULL)) | |
2426 | 97 /* Sleep (100) */ ; |
442 | 98 |
99 return 0; | |
100 } | |
101 | |
102 /* | |
103 * Launch a pump for the given I-connector | |
104 */ | |
105 static void | |
106 start_pump (I_connector* pi) | |
107 { | |
108 DWORD unused; | |
109 HANDLE h_thread = CreateThread (NULL, 0, pump, (void*)pi, 0, &unused); | |
110 CloseHandle (h_thread); | |
111 } | |
112 | |
826 | 113 static HANDLE external_event; |
114 | |
115 static BOOL | |
116 ctrl_c_handler (unsigned long type) | |
117 { | |
118 SetEvent (external_event); | |
119 return FALSE; | |
120 } | |
121 | |
122 /* Skip over the executable name in the given command line. Correctly | |
123 handles quotes in the name. Return NULL upon error. If | |
124 REQUIRE_FOLLOWING is non-zero, it's an error if no argument follows the | |
125 executable name. */ | |
126 | |
442 | 127 static LPTSTR |
826 | 128 skip_executable_name (LPTSTR cl, int require_following) |
442 | 129 { |
130 int ix; | |
131 | |
132 while (1) | |
133 { | |
134 ix = _tcscspn (cl, _T(" \t\"")); | |
135 if (cl[ix] == '\"') | |
136 { | |
137 cl = _tcschr (cl + ix + 1, '\"'); | |
138 if (cl == NULL) | |
139 return NULL; /* Unmatched quote */ | |
140 cl++; | |
141 } | |
142 else | |
143 { | |
144 cl += ix; | |
145 cl += _tcsspn (cl, _T(" \t")); | |
826 | 146 if (!require_following) |
147 return cl; | |
442 | 148 return *cl ? cl : NULL; |
149 } | |
150 } | |
151 } | |
152 | |
153 /* | |
154 * Brew coffee and bring snickers | |
155 */ | |
156 void | |
157 usage (void) | |
158 { | |
159 fprintf (stderr, | |
160 "\n" | |
161 "usage: i command\n" | |
162 "i executes the command and reroutes its standard handles to the calling\n" | |
163 "console. Good for seeing output of GUI programs that use standard output." | |
164 "\n"); | |
165 } | |
166 | |
167 int | |
168 main (void) | |
169 { | |
170 STARTUPINFO si; | |
171 PROCESS_INFORMATION pi; | |
172 I_connector I_in, I_out, I_err; | |
173 DWORD exit_code; | |
826 | 174 LPTSTR command = skip_executable_name (GetCommandLine (), 1); |
175 | |
442 | 176 if (command == NULL) |
177 { | |
178 usage (); | |
179 return 1; | |
180 } | |
181 | |
182 ZeroMemory (&si, sizeof (si)); | |
183 si.dwFlags = STARTF_USESTDHANDLES; | |
184 | |
185 I_in.source = GetStdHandle (STD_INPUT_HANDLE); | |
186 CreatePipe (&si.hStdInput, &I_in.drain, NULL, 0); | |
187 make_inheritable (&si.hStdInput); | |
188 | |
189 I_out.drain = GetStdHandle (STD_OUTPUT_HANDLE); | |
190 CreatePipe (&I_out.source, &si.hStdOutput, NULL, 0); | |
191 make_inheritable (&si.hStdOutput); | |
192 | |
193 I_err.drain = GetStdHandle (STD_ERROR_HANDLE); | |
194 CreatePipe (&I_err.source, &si.hStdError, NULL, 0); | |
195 make_inheritable (&si.hStdError); | |
196 | |
826 | 197 { |
198 SECURITY_ATTRIBUTES sa; | |
199 LPTSTR new_command = | |
200 (LPTSTR) malloc (666 + sizeof (TCHAR) * _tcslen (command)); | |
201 LPTSTR past_exe; | |
202 | |
203 if (!new_command) | |
204 { | |
205 _ftprintf (stderr, _T ("Out of memory when launching `%s'\n"), | |
206 command); | |
207 return 2; | |
208 } | |
209 | |
210 past_exe = skip_executable_name (command, 0); | |
211 if (!past_exe) | |
212 { | |
213 usage (); | |
214 return 1; | |
215 } | |
216 | |
217 /* Since XEmacs isn't a console application, it can't easily be | |
218 terminated using ^C. Therefore, we set up a communication path with | |
219 it so that when a ^C is sent to us (using GenerateConsoleCtrlEvent), | |
220 we in turn signals it to commit suicide. (This is cleaner than using | |
221 TerminateProcess()). This makes (e.g.) the "Stop Build" command | |
222 from VC++ correctly terminate XEmacs. | |
223 | |
224 #### This will cause problems if i.exe is used for commands other | |
225 than XEmacs. We need to make behavior this a command-line | |
226 option. */ | |
442 | 227 |
826 | 228 /* Create the event as inheritable so that we can use it to communicate |
229 with the child process */ | |
230 sa.nLength = sizeof (sa); | |
231 sa.bInheritHandle = TRUE; | |
232 sa.lpSecurityDescriptor = NULL; | |
233 external_event = CreateEvent (&sa, FALSE, FALSE, NULL); | |
234 if (!external_event) | |
235 { | |
236 _ftprintf (stderr, _T ("Error %d creating signal event for `%s'\n"), | |
237 GetLastError (), command); | |
238 return 2; | |
239 } | |
240 | |
241 SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE); | |
242 _tcsncpy (new_command, command, past_exe - command); | |
243 _stprintf (new_command + (past_exe - command), | |
244 /* start with space in case no args past command name */ | |
245 " -mswindows-termination-handle %d ", (long) external_event); | |
246 _tcscat (new_command, past_exe); | |
247 | |
248 if (CreateProcess (NULL, new_command, NULL, NULL, TRUE, 0, | |
249 NULL, NULL, &si, &pi) == 0) | |
250 { | |
251 _ftprintf (stderr, _T("Error %d launching `%s'\n"), | |
252 GetLastError (), command); | |
253 return 2; | |
254 } | |
255 | |
256 CloseHandle (pi.hThread); | |
257 } | |
258 | |
442 | 259 |
260 /* Start pump in each I-connector */ | |
261 start_pump (&I_in); | |
262 start_pump (&I_out); | |
263 start_pump (&I_err); | |
264 | |
265 /* Wait for the process to complete */ | |
266 WaitForSingleObject (pi.hProcess, INFINITE); | |
267 GetExitCodeProcess (pi.hProcess, &exit_code); | |
268 CloseHandle (pi.hProcess); | |
269 | |
270 /* Make pump threads eventually die out. Looks rude, I agree */ | |
271 CloseHandle (GetStdHandle (STD_INPUT_HANDLE)); | |
272 CloseHandle (GetStdHandle (STD_OUTPUT_HANDLE)); | |
273 CloseHandle (GetStdHandle (STD_ERROR_HANDLE)); | |
274 | |
275 return exit_code; | |
276 } |