1 /* main.c: main(), initialisation and cleanup
2 * (C) 2000-2009 Hans Lub
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License , or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 * You may contact the author by e-mail: hanslub42@gmail.com
19 */
20
21 #include "rlwrap.h"
22
23 /* global vars */
24
25
26
27 /* variables set via command line options */
28 int always_readline = FALSE; /* -a option: always be in readline mode */
29 char *password_prompt_search_string = NULL; /* (part of) password prompt (argument of -a option) */
30 int ansi_colour_aware = FALSE; /* -A option: make readline aware of ANSI colour codes in prompt */
31 int bleach_the_prompt = FALSE; /* -A!: remove all ANSI colour codes in prompt */
32 int complete_filenames = FALSE; /* -c option: whether to complete file names */
33 int debug = 0; /* -d option: debugging mask */
34 char *extra_char_after_completion = " "; /* -e option: override readlines's default completion_append_char (space) */
35 int always_echo = FALSE; /* -E option: always echo, even if client has ECHO off */
36 int history_duplicate_avoidance_policy = ELIMINATE_SUCCESIVE_DOUBLES; /* -D option: whether and how to avoid duplicate history entries */
37 char *history_format = NULL; /* -F option: format to append to history entries */
38 char *forget_regexp = NULL; /* -g option: keep matching input out of history */
39 int pass_on_sigINT_as_sigTERM = FALSE; /* -I option: send a SIGTERM to client when a SIGINT is received */
40 char *multi_line_tmpfile_ext = NULL; /* -M option: tmpfile extension for multi-line editor */
41 int nowarn = FALSE; /* -n option: suppress warnings */
42 int commands_children_not_wrapped = FALSE; /* -N option: always use direct mode when <command> is waiting */
43 int one_shot_rlwrap = FALSE; /* -o option: whether to close the pty after writing the first line to <command> */
44 char *prompt_regexp = NULL; /* -O option: only ever "cook" prompts matching this regexp */
45 bool regexp_means_prompt = FALSE; /* -O! all candidate prompts that match rhe regexp are prompts */
46 int colour_the_prompt = FALSE; /* -p option: whether we should paint the prompt */
47 int renice = FALSE; /* -R option: whether to be nicer than command */
48 int mirror_arguments = FALSE; /* -U option: whether to mirror command's arguments */
49 int wait_before_prompt = 40; /* -w option: how long we wait before deciding we have a cookable prompt (in msec)) */
50 int polling = FALSE; /* -W option: always give select() a small (=wait_before_prompt) timeout. */
51 int impatient_prompt = TRUE; /* show raw prompt as soon as possible, even before we cook it. may result in "flashy" prompt */
52 char *substitute_prompt = NULL; /* -S option: substitute our own prompt for <command>s */
53 char *filter_command = NULL; /* -z option: pipe prompts, input, output, history and completion requests through an external filter */
54
55
56 /* variables for global bookkeeping */
57 int master_pty_fd; /* master pty (rlwrap uses this to communicate with client) */
58 FILE *debug_fp = NULL; /* filehandle of debugging log */
59 char *program_name = "rlwrap", *command_name;/* "rlwrap" (or whatever has been symlinked to rlwrap) and (base-)name of command */
60 char *rlwrap_command_line = ""; /* rlwrap command line (rlwrap -options command <command_args> */
61 char *command_line = ""; /* command <command_args> */
62 int within_line_edit = FALSE; /* TRUE while user is editing input */
63 int screen_is_alternate = FALSE; /* TRUE after client has sent smcup, FALSE after rmcup */
64 pid_t command_pid = 0; /* pid of child (client), or 0 before child is born */
65 int i_am_child = FALSE; /* Am I child or parent? after forking, child will set this to TRUE */
66 int i_am_filter = FALSE; /* After forking, filter will set this to TRUE */
67 int ignore_queued_input = FALSE; /* read and then ignore all characters in input queue until it is empty (i.e. read would block) */
68 int received_WINCH = FALSE; /* flag set in SIGWINCH signal handler: start line edit as soon as possible */
69 int prompt_is_still_uncooked = TRUE; /* The main loop consults this variable to determine the select() timeout: when TRUE, it is
70 a few millisecs, if FALSE, it is infinite.
71 TRUE just after receiving command output (when we still don't know whether we have a
72 prompt), and, importantly, at startup (so that substitute prompts get displayed even with
73 programs that don't have a startup message, such as cat) */
74
75 int we_just_got_a_signal_or_EOF = FALSE; /* When we got a signal or EOF, and the program sends something that ends in a newline, take it
76 as a response to user input - i.e. preserve a cooked prompt and just print the new output after it */
77 int rlwrap_already_prompted = FALSE;
78 int accepted_lines = 0; /* number of lines accepted (used for one-shot rlwrap) */
79 bool user_has_typed_first_NL = FALSE; /* When the *first* user NL is typed in direct mode, we probably need --always-readline: give a warning, .. */
80 bool advise_always_readline = FALSE; /* ... which has to be given a bit later in order to not mess up the screen */
81
82 /* private variables */
83 static char *history_filename = NULL;
84 static int histsize = 300;
85 static int write_histfile = TRUE;
86 static char *completion_filename, *default_completion_filename;
87 static char *full_program_name;
88 static int last_option_didnt_have_optional_argument = FALSE;
89 static int last_opt = -1;
90 static char *client_term_name = NULL; /* we'll set TERM to this before exec'ing client command */
91 static int feed_history_into_completion_list = FALSE;
92
93
94 /*
95 * Since version 0.24, rlwrap only writes to master_pty
96 * asynchronously, keeping a queue of pending output. The readline
97 * line handler calls put_in_output_queue(user_input) , while
98 * main_loop calls flush_output_queue() as long as there is something
99 * in the queue.
100 */
101
102 static char *output_queue; /* NULL when empty */
103
104
105 /* private functions */
106 static void init_rlwrap(char *command_line);
107 static void fork_child(char *command_name, char **argv);
108 static char *read_options_and_command_name(int argc, char **argv);
109 static void main_loop(void);
110
111
112
113 /* options */
114 #ifdef GETOPT_GROKS_OPTIONAL_ARGS
115 static char optstring[] = "+:a::A::b:cC:d::D:e:Ef:F:g:hH:iIl:nNM:m::oO:p::P:q:rRs:S:t:TUvw:Wz:";
116 /* +: is not really documented. configure checks wheteher it works as expected
117 if not, GETOPT_GROKS_OPTIONAL_ARGS is undefined. @@@ */
118 #else
119 static char optstring[] = "+:a:A:b:cC:d:D:e:Ef:F:g:hH:iIl:nNM:m:oO:p:P:q:rRs:S:t:TUvw:Wz:";
120 #endif
121
122 #ifdef HAVE_GETOPT_LONG
123 static struct option longopts[] = {
124 {"always-readline", optional_argument, NULL, 'a'},
125 {"ansi-colour-aware", optional_argument, NULL, 'A'},
126 {"break-chars", required_argument, NULL, 'b'},
127 {"complete-filenames", no_argument, NULL, 'c'},
128 {"command-name", required_argument, NULL, 'C'},
129 {"debug", optional_argument, NULL, 'd'},
130 {"extra-char-after-completion", required_argument, NULL, 'e'},
131 {"always-echo", no_argument, NULL, 'E'},
132 {"history-no-dupes", required_argument, NULL, 'D'},
133 {"file", required_argument, NULL, 'f'},
134 {"history-format", required_argument, NULL, 'F'},
135 {"forget-matching", required_argument, NULL, 'g'},
136 {"help", no_argument, NULL, 'h'},
137 {"history-filename", required_argument, NULL, 'H'},
138 {"case-insensitive", no_argument, NULL, 'i'},
139 {"pass-sigint-as-sigterm", no_argument, NULL, 'I'},
140 {"logfile", required_argument, NULL, 'l'},
141 {"multi-line", optional_argument, NULL, 'm'},
142 {"multi-line-ext", required_argument, NULL, 'M'},
143 {"no-warnings", no_argument, NULL, 'n'},
144 {"no-children", no_argument, NULL, 'N'},
145 {"one-shot", no_argument, NULL, 'o'},
146 {"only-cook", required_argument, NULL, 'O'},
147 {"prompt-colour", optional_argument, NULL, 'p'},
148 {"pre-given", required_argument, NULL, 'P'},
149 {"quote-characters", required_argument, NULL, 'q'},
150 {"remember", no_argument, NULL, 'r'},
151 {"renice", no_argument, NULL, 'R'},
152 {"histsize", required_argument, NULL, 's'},
153 {"substitute-prompt", required_argument, NULL, 'S'},
154 {"set-terminal-name", required_argument, NULL, 't'},
155 {"test-terminal", no_argument, NULL, 'T'},
156 {"mirror-arguments", no_argument, NULL, 'U'},
157 {"version", no_argument, NULL, 'v'},
158 {"wait-before-prompt", required_argument, NULL, 'w'},
159 {"polling", no_argument, NULL, 'W'},
160 {"filter", required_argument, NULL, 'z'},
161 {0, 0, 0, 0}
162 };
163 #endif
164
165
166
167 /* helper function to run a unit test whenever UNIT_TEST is #defined, e.g. by "make clean; make CFLAGS='-DUNIT_TEST=my_test'" */
168
169 #ifdef UNIT_TEST
run_unit_test(int argc,char ** argv,test_stage stage)170 static void run_unit_test(int argc, char **argv, test_stage stage) {
171 extern void UNIT_TEST(int argc, char **argv, test_stage stage);
172 #define VALUE_AS_STRING(v) NAME_AS_STRING(v)
173 #define NAME_AS_STRING(n) #n
174
175 if(stage == TEST_AT_PROGRAM_START)
176 myerror(WARNING|NOERRNO, "running unit test %s", VALUE_AS_STRING(UNIT_TEST));
177 UNIT_TEST(argc, argv, stage);
178 }
179 #else
run_unit_test(int UNUSED (argc),char ** UNUSED (argv),test_stage UNUSED (stage))180 static void run_unit_test(int UNUSED(argc), char ** UNUSED(argv), test_stage UNUSED(stage)) {
181 /*do nothing */
182 }
183 #endif
184 /*
185 * main function. initialises everything and calls main_loop(),
186 * which never returns
187 */
188
189 int
main(int argc,char ** argv)190 main(int argc, char **argv)
191 {
192 char *command_name;
193
194 if (!(setlocale (LC_ALL, "") && setlocale(LC_COLLATE, "C")))/* ANSI C says that all programs start by default in the standard `C' locale... */
195 myerror(WARNING|NOERRNO, "could not set locale"); /* ... To use the locales specified by the environment, we must call setlocale. */
196 /* LC_COLLATE = 'C' because we use character ranges as byte ranges in regexps */
197
198 run_unit_test(argc, argv,TEST_AT_PROGRAM_START);
199 rlwrap_command_line = unsplit_with(argc, argv, " ");
200 init_completer();
201
202 /* Harvest options and leave optind pointing to first non-option argument: */
203 command_name = read_options_and_command_name(argc, argv);
204
205
206 /* by now, optind points to slave <command>, and &argv[optind] is <command>'s argv. Remember slave command line: */
207 command_line = unsplit_with(argc - optind, argv + optind, " ");
208
209 run_unit_test(argc - optind, argv + optind, TEST_AFTER_OPTION_PARSING); /* argv points at the first non-option rlwrap argument */
210
211 /* if stdin is not a tty, or we're inside emacs, just execute <command>: */
212 if (!isatty(STDIN_FILENO) || getenv("INSIDE_EMACS"))
213 if (execvp(argv[optind], &argv[optind]) < 0)
214 myerror(FATAL|USE_ERRNO, "Cannot execute %s", argv[optind]);
215
216 init_rlwrap(rlwrap_command_line);
217 install_signal_handlers();
218 block_all_signals();
219 fork_child(command_name, argv); /* this will unblock most signals most of the time */
220
221 init_readline("");
222 last_minute_checks();
223 run_unit_test(0,NULL, TEST_AFTER_READLINE_INIT);
224
225 if (filter_command)
226 spawn_filter(filter_command);
227 run_unit_test(argc - optind, argv + optind, TEST_AFTER_SPAWNING_SLAVE_COMMAND); /* argv points at the first non-option rlwrap argument */
228
229 main_loop();
230 return 42; /* The Answer, but, sadly, we'll never get there.... */
231 }
232
233
234 /*
235 * create pty pair and fork using my_pty_fork; parent returns immediately; child
236 * executes the part of rlwrap's command line that remains after
237 * read_options_and_command_name() has harvested rlwrap's own options
238 */
239 static void
fork_child(char * UNUSED (command_name),char ** argv)240 fork_child(char *UNUSED(command_name), char **argv)
241 {
242 char *arg = argv[optind], *p;
243 int pid;
244
245 if (mirror_arguments)
246 mirror_args_init(&argv[optind]);
247
248 pid = my_pty_fork(&master_pty_fd, &saved_terminal_settings, &winsize);
249 if (pid > 0) /* parent: */
250 return;
251 else { /* child: */
252 DPRINTF1(DEBUG_TERMIO, "preparing to execute %s", arg);
253 close_open_files_without_writing_buffers();
254
255 if (client_term_name)
256 mysetenv("TERM", client_term_name);
257 if (execvp(argv[optind], &argv[optind]) < 0) {
258 if (last_opt > 0 && last_option_didnt_have_optional_argument) { /* e.g. 'rlwrap -a Password: sqlpus' will try to exec 'Password:' */
259 for (p=" '; !(){}"; *p; p++) /* does arg need shell quoting? */
260 if (strchr(arg,*p)) {
261 arg = add3strings("'", arg,"'"); /* quote it */
262 break;
263 }
264 fprintf(stderr, "Did you mean '%s' to be an option argument?\nThen you should write -%c%s, without the space(s)\n",
265 argv[optind], last_opt, arg);
266 }
267 myerror(FATAL|USE_ERRNO, "Cannot execute %s", argv[optind]); /* stillborn child, parent will live on and display child's last gasps */
268 }
269 }
270 }
271
272
273 /*
274 * main loop: listen on stdin (for user input) and master pty (for command output),
275 * and try to write output_queue to master_pty (if it is not empty)
276 * This function never returns.
277 */
278 void
main_loop()279 main_loop()
280 {
281 int nfds;
282 fd_set readfds;
283 fd_set writefds;
284 int nread;
285 char buf[BUFFSIZE], *timeoutstr, *old_raw_prompt, *new_output_minus_prompt;
286 int promptlen = 0;
287 int leave_prompt_alone;
288 sigset_t no_signals_blocked;
289 int seen_EOF = FALSE;
290
291 struct timespec select_timeout, *select_timeoutptr;
292 struct timespec immediately = { 0, 0 }; /* zero timeout when child is dead */
293 struct timespec wait_a_little = {0, 0xBadf00d }; /* tv_usec field will be filled in when initialising */
294 struct timespec *forever = NULL;
295 wait_a_little.tv_nsec = 1000 * 1000 * wait_before_prompt;
296
297
298 sigemptyset(&no_signals_blocked);
299
300
301
302 pass_through_filter(TAG_OUTPUT,""); /* If something is wrong with filter, get the error NOW */
303 set_echo(FALSE); /* This will also put the terminal in CBREAK mode */
304 /* ------------------------------ main loop -------------------------------*/
305 while (TRUE) {
306 /* listen on both stdin and pty_fd */
307 FD_ZERO(&readfds);
308 FD_SET(STDIN_FILENO, &readfds);
309 FD_SET(master_pty_fd, &readfds);
310
311 /* try to write output_queue to master_pty (but only if it is nonempty) */
312 FD_ZERO(&writefds);
313 if (output_queue_is_nonempty())
314 FD_SET(master_pty_fd, &writefds);
315
316
317
318 DPRINTF1(DEBUG_AD_HOC, "prompt_is_still_uncooked = %d", prompt_is_still_uncooked);
319 if (command_is_dead || ignore_queued_input) {
320 select_timeout = immediately;
321 select_timeoutptr = &select_timeout;
322 timeoutstr = "immediately";
323 } else if (prompt_is_still_uncooked || polling) {
324 select_timeout = wait_a_little;
325 select_timeoutptr = &select_timeout;
326 timeoutstr = "wait_a_little";
327 } else {
328 select_timeoutptr = forever; /* NULL */
329 timeoutstr = "forever";
330 }
331
332 DPRINTF2(DEBUG_TERMIO, "calling select() with timeout %s %s ...", timeoutstr, within_line_edit ? "(within line edit)" : "");
333
334
335 nfds = my_pselect(1 + master_pty_fd, &readfds, &writefds, NULL, select_timeoutptr, &no_signals_blocked);
336
337 /* DPRINTF3(DEBUG_TERMIO, "select() returned %d (stdin|pty in|pty out = %03d), within_line_edit=%d", nfds, */
338 /* 100*(FD_ISSET(STDIN_FILENO, &readfds)?1:0) + 10*(FD_ISSET(master_pty_fd, &readfds)?1:0) + (FD_ISSET(master_pty_fd, &writefds)?1:0), */
339 /* within_line_edit); */
340
341
342 DPRINTF5(DEBUG_TERMIO, "... returning %d%s %s %s %s"
343 , nfds
344 , nfds > 0 ? ": " : "."
345 , nfds > 0 && FD_ISSET(STDIN_FILENO, &readfds) ? "stdin ready for input" : ""
346 , nfds > 0 && FD_ISSET(master_pty_fd, &readfds) ? "pty master ready for input": ""
347 , nfds > 0 && FD_ISSET(master_pty_fd, &writefds) ? "output queue nonempty and pty master ready for output" : "");
348
349 assert(!filter_pid || filter_is_dead || kill(filter_pid,0) == 0);
350 assert(command_is_dead || kill(command_pid,0) == 0);
351
352 /* check flags that may have been set by signal handlers */
353 if (filter_is_dead)
354 filters_last_words(); /* will call myerror with last words */
355
356 if (received_WINCH) { /* received_WINCH flag means we've had a WINCH while within_line_edit was FALSE */
357 DPRINTF0(DEBUG_READLINE, "Starting line edit as a result of WINCH ");
358 within_line_edit = TRUE;
359 restore_rl_state();
360 received_WINCH = FALSE;
361 continue;
362 }
363
364 if (nfds < 0) { /* exception */
365 if (errno == EINTR || errno == 0) { /* interrupted by signal, or by a cygwin bug (errno == 0) :-( */
366 continue;
367 } else
368 myerror(FATAL|USE_ERRNO, "select received exception");
369 } else if (nfds == 0) {
370
371 /* timeout, which can only happen when .. */
372 if (ignore_queued_input) { /* ... we have read all the input keystrokes that should
373 be ignored (i.e. those that accumulated on stdin while we
374 were calling an external editor) */
375 ignore_queued_input = FALSE;
376 continue;
377 } else if (command_is_dead) { /* ... or else, if child is dead, ... */
378 DPRINTF2(DEBUG_SIGNALS,
379 "select returned 0, command_is_dead=%d, commands_exit_status=%d",
380 command_is_dead, commands_exit_status);
381 cleanup_rlwrap_and_exit(EXIT_SUCCESS);
382 } else if (prompt_is_still_uncooked) { /* cooking time? */
383 if (we_just_got_a_signal_or_EOF) {
384 we_just_got_a_signal_or_EOF = FALSE; /* 1. If we got a signal/EOF before cooking time, we don't need special action
385 to preserve the cooked prompt.
386 2. Reset we_just_got_a_signal_or_EOF after a signal or EOF that didn't kill command */
387 continue;
388 }
389 if (!skip_rlwrap()) { /* ... or else, it is time to cook the prompt */
390 if (pre_given && accepted_lines == 0) {
391 /* input_buffer and point have already been set in init_readline() */
392 DPRINTF0(DEBUG_READLINE, "Starting line edit (because of -P option)");
393 within_line_edit = TRUE;
394 restore_rl_state();
395 continue;
396 }
397
398 move_cursor_to_start_of_prompt(ERASE); /* cooked prompt may be shorter than raw prompt, hence the ERASE */
399 /* move and erase before cooking, as we need to move/erase according
400 to the raw prompt */
401 cook_prompt_if_necessary();
402 DPRINTF2(DEBUG_READLINE,"After cooking, raw_prompt=%s, cooked=%s", M(saved_rl_state.raw_prompt), M(saved_rl_state.cooked_prompt));
403 my_putstr(saved_rl_state.cooked_prompt);
404 rlwrap_already_prompted = TRUE;
405 }
406 prompt_is_still_uncooked = FALSE;
407 } else if (polling) {
408 completely_mirror_slaves_special_characters();
409 if (mirror_arguments)
410 mirror_args(command_pid);
411 continue;
412 } else {
413 myerror(FATAL|NOERRNO, "unexpected select() timeout");
414 }
415 } else if (nfds > 0) { /* Hah! something to read or write */
416
417 /* -------------------------- read pty --------------------------------- */
418 /* Always first read and process the slave command's output, even if there is input waiting on stdin
419 (which may happen when pasting a lot of text). E.g. when pasting "a\nb\nc" into "rlwrap cat" we want
420 a
421 a
422 b
423 b
424 c
425 c
426
427 and not
428
429 a
430 b
431 c
432 a
433 b
434 c
435 */
436 if (FD_ISSET(master_pty_fd, &readfds)) { /* there is something (or nothing, if EOF) to read on master pty: */
437 nread = read(master_pty_fd, buf, BUFFSIZE - 1); /* read it */
438 DPRINTF1(DEBUG_AD_HOC, "nread: %d", nread);
439 if (nread <= 0) {
440 if (command_is_dead || nread == 0) { /* we catched a SIGCHLD, or slave command has closed its stdout */
441 if (promptlen > 0) /* commands dying words were not terminated by \n ... */
442 my_putchar('\n'); /* provide the missing \n */
443 cleanup_rlwrap_and_exit(EXIT_SUCCESS);
444 } else if (errno == EINTR) { /* interrupted by signal ...*/
445 continue; /* ... don't worry */
446 } else if (! seen_EOF) { /* maybe command has just died (and SIGCHLD, whose handler sets command_is_dead is not */
447 mymicrosleep(50); /* yet caught) Therefore we wait a bit, */
448 seen_EOF = TRUE; /* set a flag */
449 continue; /* and try one more time (hopefully catching the signal this time round */
450 } else {
451 myerror(FATAL|USE_ERRNO, "read error on master pty");
452 }
453 }
454 remove_padding_and_terminate(buf, nread);
455 completely_mirror_slaves_output_settings(); /* some programs (e.g. joe) need this. Gasp!! */
456 mirror_args(command_pid);
457 check_cupcodes(buf);
458 if (skip_rlwrap()) { /* Race condition here! The client may just have finished an emacs session and
459 returned to cooked mode, while its ncurses-riddled output is stil waiting for us to be processed. */
460 if (advise_always_readline) {
461 char *newlines = "\n\n";
462 assert(!always_readline);
463 write_patiently(STDOUT_FILENO, newlines, strlen(newlines), "to stdout"); /* make the following warning stand out ... */
464 myerror(WARNING|NOERRNO, "rlwrap appears to do nothing for %s, which asks for\n"
465 "single keypresses all the time. Don't you need --always-readline\n"
466 "and possibly --no-children? (cf. the rlwrap manpage)\n", command_name);
467 advise_always_readline = FALSE;
468 }
469 write_patiently(STDOUT_FILENO, buf, nread, "to stdout"); /* ... and print it before the clients output */
470 DPRINTF1(DEBUG_AD_HOC, "advise_always_readline = %d", advise_always_readline);
471 DPRINTF2(DEBUG_TERMIO, "read from pty and wrote to stdout %d bytes in direct mode <%s>", nread, M(buf));
472 yield();
473 continue;
474 }
475
476 DPRINTF2(DEBUG_TERMIO, "read %d bytes from pty into buffer: %s", nread, M(buf));
477
478
479 write_logfile(buf);
480 if (within_line_edit) /* client output arrives while we're editing keyboard input: */
481 save_rl_state(); /* temporarily disable readline and restore the screen state before readline was called */
482
483
484 assert(saved_rl_state.raw_prompt != NULL);
485
486
487 /* We *always* compute the printable part and the new raw prompt, and *always* print the printable part
488 There are four possibilities:
489 1. impatient before cooking. The raw prompt has been printed, write the new output after it
490 2. patient before cooking No raw prompt has been printed yet, don't print anything
491 3. impatient after cooking
492 3a no current prompt print the new output
493 3b some current prompt erase it, replace by current raw prompt and print new output
494 4. patient after cooking don't print anything
495 */
496
497 /* sometimes we want to leave the prompt standing, e.g. after accepting a line, or when a signal arrived */
498 leave_prompt_alone =
499 *saved_rl_state.raw_prompt == '\0' /* saved_rl_state.raw_prompt = "" in two distinct cases: when there is actually no prompt,
500 or just after accepting a line, when the cursor is at the end of the prompt. In both
501 cases, we dont't want to move the cursor */
502 || prompt_is_still_uncooked /* in this case no prompt has been displayed yet */
503 || command_is_dead
504 || (we_just_got_a_signal_or_EOF && strrchr(buf, '\n')); /* a signal followed by output with a newline in it: treat it as
505 response to user input, so leave the prompt alone */
506
507 DPRINTF3(DEBUG_READLINE, "leave_prompt_alone: %s (raw prompt: %s, prompt_is_still_uncooked: %d)",
508 (leave_prompt_alone? "yes" : "no"), M(saved_rl_state.raw_prompt), prompt_is_still_uncooked);
509
510 if (!leave_prompt_alone) /* && (!impatient_prompt || !saved_rl_state.cooked_prompt)) */
511 move_cursor_to_start_of_prompt(ERASE);
512 else if (we_just_got_a_signal_or_EOF) {
513 free (saved_rl_state.raw_prompt);
514 saved_rl_state.raw_prompt = mysavestring(""); /* prevent reprinting the prompt */
515 }
516
517 if (impatient_prompt && !leave_prompt_alone)
518 old_raw_prompt = mysavestring(saved_rl_state.raw_prompt);
519
520 new_output_minus_prompt = process_new_output(buf, &saved_rl_state); /* chop off the part after the last newline and put this in
521 saved_rl_state.raw_prompt (or append buf if no newline found)*/
522
523 if (impatient_prompt) { /* in impatient mode, ALL command output is passed through the OUTPUT filter, including the prompt The
524 prompt, however, is filtered separately at cooking time and then displayed */
525 char *filtered = pass_through_filter(TAG_OUTPUT, buf);
526 if(!leave_prompt_alone) {
527 my_putstr(old_raw_prompt);
528 free(old_raw_prompt);
529 }
530
531 my_putstr(filtered);
532 free (filtered);
533 if (regexp_means_prompt && prompt_regexp && match_regexp(saved_rl_state.raw_prompt, prompt_regexp, FALSE)) {
534 /* user specified -O!.... so any natching candidate prompt will be cooked and output immediately: */
535 move_cursor_to_start_of_prompt(ERASE); /* erase already printed raw prompt */
536 cook_prompt_if_necessary();
537 my_putstr(saved_rl_state.cooked_prompt);
538 }
539
540 rlwrap_already_prompted = TRUE;
541 } else {
542 my_putstr(new_output_minus_prompt);
543 rlwrap_already_prompted = FALSE;
544 }
545
546 free(new_output_minus_prompt);
547
548
549 prompt_is_still_uncooked = TRUE;
550
551
552 if (within_line_edit)
553 restore_rl_state();
554
555 yield(); /* wait for what client has to say .... */
556 continue; /* ... and don't attempt to process keyboard input as long as it is talking ,
557 in order to avoid re-printing the current prompt (i.e. unfinished output line) */
558 }
559
560
561 /* ----------------------------- key pressed: read stdin -------------------------*/
562 if (FD_ISSET(STDIN_FILENO, &readfds)) { /* key pressed */
563 unsigned char byte_read; /* the readline function names and documentation talk about "characters" and "keys",
564 but we're reading bytes (i.e. unsigned chars) here, and those may very well be
565 part of a multi-byte character. Example: hebrew "aleph" in utf-8 is 0xd790; pressing this key
566 will make us read 2 bytes 0x90 and then 0xd7, (or maybe the other way round depending on endianness??)
567 The readline library hides all this complexity and allows one to just "pass the bytes around" */
568 nread = read(STDIN_FILENO, &byte_read, 1); /* read next byte of input */
569 assert(sizeof(unsigned char) == 1); /* gets optimised away */
570
571 if (nread <= 0)
572 DPRINTF1(DEBUG_TERMIO, "read from stdin returned %d", nread);
573 if (nread < 0)
574 if (errno == EINTR)
575 continue;
576 else
577 myerror(FATAL|USE_ERRNO, "Unexpected error");
578 else if (nread == 0) /* EOF on stdin */
579 cleanup_rlwrap_and_exit(EXIT_SUCCESS);
580 else if (ignore_queued_input)
581 continue; /* do nothing with it*/
582 assert(nread == 1);
583 DPRINTF2(DEBUG_TERMIO, "read from stdin: byte 0x%02x (%s)", byte_read, mangle_char_for_debug_log(byte_read, TRUE));
584 if (skip_rlwrap()) { /* direct mode, just pass it on */
585 /* remote possibility of a race condition here: when the first half of a multi-byte char is read in
586 direct mode and the second half in readline mode. Oh well... */
587 DPRINTF0(DEBUG_TERMIO, "passing it on (in transparent mode)");
588 if (!user_has_typed_first_NL && (byte_read == '\r' || byte_read == '\n')) {
589 user_has_typed_first_NL = TRUE;
590 advise_always_readline = TRUE; /* first NL is in direct mode: advise the user that she probably wants --always-readline */
591 }
592
593 completely_mirror_slaves_terminal_settings(); /* this is of course 1 keypress too late: we should
594 mirror the terminal settings *before* the user presses a key.
595 (maybe using rl_event_hook??) @@@FIXME @@@ HOW?*/
596 write_patiently(master_pty_fd, &byte_read, 1, "to master pty");
597 } else { /* hand it over to readline */
598 if (!within_line_edit) { /* start a new line edit */
599 DPRINTF0(DEBUG_READLINE, "Starting line edit");
600 within_line_edit = TRUE;
601 restore_rl_state();
602 }
603
604 if (term_eof && byte_read == term_eof && strlen(rl_line_buffer) == 0) { /* hand a term_eof (usually CTRL-D) directly to command */
605 char *sent_EOF = mysavestring("?");
606 *sent_EOF = term_eof;
607 put_in_output_queue(sent_EOF);
608 we_just_got_a_signal_or_EOF = TRUE;
609 free(sent_EOF);
610 }
611 else {
612 rl_stuff_char(byte_read); /* stuff it back in readline's input queue */
613 DPRINTF0(DEBUG_TERMIO, "passing it to readline");
614 DPRINTF2(DEBUG_READLINE, "rl_callback_read_char() (_rl_eof_char=%d, term_eof=%d)", _rl_eof_char, term_eof);
615 message_in_echo_area(NULL);
616 rl_callback_read_char();
617 }
618 }
619 }
620
621 /* -------------------------- write pty --------------------------------- */
622 if (FD_ISSET(master_pty_fd, &writefds)) {
623 flush_output_queue();
624 if(output_queue) { /* there was more than one line in the queue - probably pasted input */
625 mymicrosleep(10); /* give slave some time to respond */
626 yield(); /* If we woudn't do this, nothing bad would happen, but the */
627 /* "dialogue" on screen will be out of order (which can still happen) */
628 }
629 }
630 } /* if (ndfs > 0) */
631 } /* while (1) */
632 } /* void main_loop() */
633
634
635 /* Read history and completion word lists */
636 static void
init_rlwrap(char * command_line)637 init_rlwrap(char *command_line)
638 {
639
640 char *homedir, *histdir, *homedir_prefix, *hostname;
641 struct stat statbuf;
642 time_t now;
643
644
645 hostname = getenv("HOSTNAME") ? getenv("HOSTNAME") : "?";
646 now = time(NULL);
647 DPRINTF0(DEBUG_ALL, "-*- mode: grep -*-");
648 DPRINTF1(DEBUG_ALL, "command line: %s", command_line);
649 DPRINTF3(DEBUG_ALL, "rlwrap version %s, host: %s, time: %s", VERSION, hostname, ctime(&now));
650
651 init_terminal();
652
653
654
655 /* Determine rlwrap home dir and prefix for default history and completion filenames */
656 homedir = (getenv("RLWRAP_HOME") ? getenv("RLWRAP_HOME") : getenv("HOME"));
657 if (!homedir) {
658 homedir = ".";
659 myerror(WARNING | NOERRNO, "No HOME, using '%s'", homedir);
660 }
661 homedir_prefix = (getenv("RLWRAP_HOME") ? /* is RLWRAP_HOME set? */
662 add2strings(getenv("RLWRAP_HOME"), "/") : /* use $RLWRAP_HOME/<command>_history */
663 add2strings(homedir, "/.")); /* if not, use ~/.<command>_history */
664
665 /* Determine history file name and check its existence and permissions */
666
667 if (history_filename) {
668 histdir = mydirname(history_filename);
669 } else {
670 histdir = homedir;
671 history_filename = add3strings(homedir_prefix, command_name, "_history");
672 }
673
674
675
676 if (write_histfile) {
677 if (access(history_filename, F_OK) == 0) { /* already exists, can we read/write it? */
678 if (access(history_filename, R_OK | W_OK) != 0) {
679 myerror(FATAL|USE_ERRNO, "cannot read and write %s", history_filename);
680 }
681 /* OK, we can read and write it, but do we want to? Not if our effective UID
682 doesn't match the owner of the history file (like after sudo rlwrap on Ubuntu) */
683 assert(!stat(history_filename, &statbuf));
684 if(statbuf.st_uid != geteuid()) {
685 myerror(WARNING | NOERRNO, "Owner of %s and your effective UID don't match. History will be read-only", history_filename);
686 write_histfile = FALSE;
687 }
688 } else { /* doesn't exist, can we create it? */
689 if(access(histdir, W_OK) != 0) {
690 if (errno == ENOENT) {
691 mode_t oldmask = umask(0);
692 if (mkdir(histdir, 0700)) /* rwx------ */
693 myerror(FATAL|USE_ERRNO, "cannot create directory %s", histdir);
694 umask(oldmask);
695 } else {
696 myerror(FATAL|USE_ERRNO, "cannot create history file %s", history_filename);
697 }
698 }
699 }
700 }
701
702 /* Initialize history */
703 using_history();
704 stifle_history(histsize);
705 read_history(history_filename); /* ignore errors here: history file may not yet exist, but will be created on exit */
706
707 if (feed_history_into_completion_list)
708 feed_file_into_completion_list(history_filename);
709 /* Determine completion file name (completion files are never written to,
710 and ignored when unreadable or non-existent) */
711
712 completion_filename =
713 add3strings(homedir_prefix, command_name, "_completions");
714 default_completion_filename =
715 add3strings(DATADIR, "/rlwrap/completions/", command_name);
716
717 rl_readline_name = command_name;
718 DPRINTF1(DEBUG_READLINE, "Setting readline command name to '%s'", command_name);
719
720 /* Initialise completion list (if <completion_filename> is readable) */
721 if (access(completion_filename, R_OK) == 0) {
722 feed_file_into_completion_list(completion_filename);
723 } else if (access(default_completion_filename, R_OK) == 0) {
724 feed_file_into_completion_list(default_completion_filename);
725 }
726
727
728 }
729
730 /*
731 * On systems where getopt doens't handle optional argments, warn the user whenever an
732 * argument of the form -<letter> is seen, or whenever the argument is the last item on the command line
733 * (e.g. 'rlwrap -a command', which will be parsed as 'rlwrap --always-readline=command')
734 */
735
736 static char *
check_optarg(char opt,int remaining,bool isdummy,const char * suggestion)737 check_optarg(char opt, int remaining, bool isdummy, const char *suggestion)
738 {
739
740 MAYBE_UNUSED(opt); MAYBE_UNUSED(remaining); MAYBE_UNUSED(isdummy); MAYBE_UNUSED(suggestion);
741
742 if (!optarg)
743 last_option_didnt_have_optional_argument = TRUE; /* if this variable is set, and if command is not found,
744 suggest that it may have been meant
745 as optional argument (e.g. 'rlwrap -a password sqlplus' will try to
746 execute 'password sqlplus' ) */
747 #ifndef GETOPT_GROKS_OPTIONAL_ARGS
748 if (optarg && /* is there an optional arg? have a look at it: */
749 ((optarg[0] == '-' && (optarg[1] == '-' || isalpha(optarg[1]))) || /* looks like next option */
750 remaining == 0)) /* or is last item on command line */
751
752 myerror(WARNING|NOERRNO, "on this system, the getopt() library function doesn't\n"
753 "grok optional arguments, so '%s' is taken as an argument to the -%c option\n"
754 "Is this what you meant? If not, please provide %s argument like '%s'", optarg, opt, isdummy ? "a dummy" : "an", suggestion);
755 #endif
756
757 return optarg;
758 }
759
760
761 /* find name of current option
762 */
763 static const char *
current_option(int opt,int longindex)764 current_option(int opt, int longindex)
765 {
766 static char buf[BUFFSIZE];
767 #ifdef HAVE_GETOPT_LONG
768 if (longindex >=0) {
769 sprintf(buf, "--%s", longopts[longindex].name);
770 return buf;
771 }
772 #endif
773 sprintf(buf, "-%c", opt);
774 return buf;
775 }
776
777
778 char *
read_options_and_command_name(int argc,char ** argv)779 read_options_and_command_name(int argc, char **argv)
780 {
781 int c;
782 char *opt_C = NULL;
783 int option_count = 0;
784 int opt_b = FALSE;
785 int opt_f = FALSE;
786 int remaining = -1; /* remaining number of arguments on command line */
787 int longindex = -1; /* index of current option in longopts[], set by getopt_long */
788
789
790 full_program_name = mysavestring(argv[0]);
791 program_name = mybasename(full_program_name); /* normally "rlwrap"; needed by myerror() */
792 rl_basic_word_break_characters = " \t\n\r(){}[],'+-=&^%$#@\";|\\";
793
794 opterr = 0; /* we do our own error reporting */
795
796 while (1) {
797 #ifdef HAVE_GETOPT_LONG
798 c = getopt_long(argc, argv, optstring, longopts, &longindex);
799 #else
800 c = getopt(argc, argv, optstring);
801 #endif
802
803 if (c == EOF)
804 break;
805 option_count++;
806 last_option_didnt_have_optional_argument = FALSE;
807 remaining = argc - optind;
808 last_opt = c;
809
810 switch (c) {
811 case 'a':
812 always_readline = TRUE;
813 if (check_optarg('a', remaining, TRUE, "brumbleslurgh"))
814 password_prompt_search_string = mysavestring(optarg);
815 break;
816 case 'A':
817 ansi_colour_aware = TRUE;
818 if (check_optarg('A', remaining, TRUE, "") && strings_are_equal(optarg, "!"))
819 bleach_the_prompt = TRUE;
820 break;
821 case 'b':
822 rl_basic_word_break_characters = add3strings("\r\n \t", optarg, "");
823 opt_b = TRUE;
824 break;
825 case 'c': complete_filenames = TRUE;
826 #ifndef CAN_FOLLOW_COMMANDS_CWD
827 myerror(WARNING|NOERRNO, "On this system rlwrap cannot follow the rlwrapped command's working directory:\n"
828 "filename completion will only be relative to rlwrap's own working directory ");
829 #endif
830 break;
831 case 'C': opt_C = mysavestring(optarg); break;
832 case 'd':
833 #ifdef DEBUG
834 if (option_count > 1)
835 myerror(FATAL|NOERRNO, "-d or --debug option has to be the *first* rlwrap option\n"
836 "in order to be able to follow the processing of all subsequent options");
837 debug = check_optarg('d', remaining, FALSE, "7") ? my_atoi(optarg) : DEBUG_DEFAULT;
838 my_fopen(&debug_fp, DEBUG_FILENAME, "w+", "debug log"); /* w+, not w: both parent and child write to the same logfile, and need to fseek beyond where the other may have written stuff */
839 #else
840 myerror(FATAL|NOERRNO, "To use -d( for debugging), configure %s with --enable-debug and rebuild",program_name);
841 #endif
842 break;
843
844 case 'D':
845 history_duplicate_avoidance_policy=my_atoi(optarg);
846 if (history_duplicate_avoidance_policy < 0 || history_duplicate_avoidance_policy > 2)
847 myerror(FATAL|NOERRNO, "%s option with illegal value %d, should be 0, 1 or 2",
848 current_option('D', longindex), history_duplicate_avoidance_policy);
849 break;
850 case 'e':
851 extra_char_after_completion = mysavestring(optarg);
852 if (strlen(extra_char_after_completion) > 1)
853 myerror(FATAL|NOERRNO, "-e (--extra-char-after-completion) argument should be at most one character");
854 break;
855 case 'E': always_echo = TRUE; break;
856 case 'f':
857 if (strcmp(optarg, ".") == 0)
858 feed_history_into_completion_list = TRUE;
859 else
860 feed_file_into_completion_list(optarg);
861 opt_f = TRUE;
862 break;
863 case 'F': WONTRETURN(myerror(FATAL|NOERRNO, "The -F (--history-format) option is obsolete. Use -z \"history_format '%s'\" instead", optarg));
864 case 'g': forget_regexp = mysavestring(optarg); match_regexp("complain NOW if regexp is wrong", forget_regexp, 1); break;
865 case 'h': WONTRETURN(usage(EXIT_SUCCESS));
866 case 'H': history_filename = mysavestring(optarg); break;
867 case 'i':
868 if (opt_f)
869 myerror(FATAL|NOERRNO, "-i option has to precede -f options");
870 completion_is_case_sensitive = FALSE;
871 break;
872 case 'I': pass_on_sigINT_as_sigTERM = TRUE; break;
873 case 'l': open_logfile(optarg); break;
874 case 'n': nowarn = TRUE; break;
875 case 'm':
876 #ifndef HAVE_SYSTEM
877 myerror(WARNING|NOERRNO, "the -m option doesn't work on this system");
878 #endif
879 multiline_separator = /* \\\\ will be printed as \\ which is correct if we want ' \ ' to be the multiline separator */
880 (check_optarg('m', remaining, FALSE, " \\\\ ") ? mysavestring(optarg) : " \\ ");
881 break;
882 case 'M': multi_line_tmpfile_ext = mysavestring(optarg); break;
883 case 'N': commands_children_not_wrapped = TRUE; break;
884 case 'o':
885 one_shot_rlwrap = TRUE; break;
886 case 'O': prompt_regexp = mysavestring(optarg);
887 if (*prompt_regexp == '!') {
888 regexp_means_prompt = TRUE;
889 prompt_regexp += 1;
890 }
891 match_regexp("complain NOW if regexp is wrong", prompt_regexp, 1);
892 break;
893 case 'p':
894 colour_the_prompt = TRUE;
895 initialise_colour_codes(check_optarg('p', remaining, FALSE, "Red") ?
896 colour_name_to_ansi_code(optarg) :
897 colour_name_to_ansi_code("Red"));
898 break;
899 case 'P':
900 pre_given = mysavestring(optarg);
901 always_readline = TRUE; /* pre_given does not work well with transparent mode */
902
903 break;
904 case 'q': rl_basic_quote_characters = mysavestring(optarg); break;
905 case 'r': remember_for_completion = TRUE; break;
906 case 'R': renice = TRUE; break;
907 case 's':
908 histsize = my_atoi(optarg);
909 if (histsize < 0 || *optarg == '-') {
910 write_histfile = 0;
911 histsize = -histsize;
912 }
913 break;
914 case 'S': substitute_prompt = mysavestring(optarg);break;
915 case 't': client_term_name=mysavestring(optarg);break;
916 #ifdef DEBUG
917 case 'T': test_terminal(); exit(EXIT_SUCCESS);
918 #endif
919 case 'U': mirror_arguments = TRUE; break;
920 case 'v': printf("rlwrap %s\n", VERSION); exit(EXIT_SUCCESS);
921 case 'w':
922 wait_before_prompt = my_atoi(optarg);
923 if (wait_before_prompt < 0) {
924 wait_before_prompt *= -1;
925 impatient_prompt = FALSE;
926 }
927 break;
928 case 'W':
929 polling = TRUE; break;
930 case 'z': filter_command = mysavestring(optarg); break;
931 case '?':
932 assert(optind > 0);
933 WONTRETURN(myerror(FATAL|NOERRNO, "unrecognised option %s\ntry '%s --help' for more information", argv[optind-1], full_program_name));
934 case ':':
935 assert(optind > 0);
936 WONTRETURN(myerror(FATAL|NOERRNO, "option %s requires an argument \ntry '%s --help' for more information", argv[optind-1], full_program_name));
937
938 default:
939 usage(EXIT_FAILURE);
940 }
941 }
942
943 if (!complete_filenames && !opt_b) { /* use / and . as default breaking characters whenever we don't complete filenames */
944 rl_basic_word_break_characters =
945 add2strings(rl_basic_word_break_characters, "/.");
946 }
947
948
949 if (optind >= argc) { /* rlwrap -a -b -c with no command specified */
950 if (filter_command) { /* rlwrap -z filter with no command specified */
951 mysignal(SIGALRM, HANDLER(handle_sigALRM)); /* needed for read_patiently2 */
952 spawn_filter(filter_command);
953 pass_through_filter(TAG_OUTPUT,""); /* ignore result but allow TAG_OUTPUT_OUT_OF_BAND */
954 cleanup_rlwrap_and_exit(EXIT_SUCCESS);
955 } else {
956 usage(EXIT_FAILURE);
957 }
958 }
959 if (opt_C) {
960 int countback = 0;
961 if (isnumeric(opt_C)) countback = my_atoi(opt_C); /* investigate whether -C option argument is numeric */
962
963 if (countback > 0) { /* e.g -C 1 or -C 12 */
964 if (argc - countback < optind) /* -C 666 */
965 myerror(FATAL|NOERRNO, "when using -C %d you need at least %d non-option arguments",
966 countback, countback);
967 else if (argv[argc - countback][0] == '-') /* -C 2 perl -d blah.pl */
968 myerror(FATAL|NOERRNO, "the last argument minus %d appears to be an option!",
969 countback);
970 else { /* -C 1 perl test.cgi */
971 command_name = mysavestring(mybasename(argv[argc - countback]));
972
973 }
974 } else if (countback == 0) { /* -C name1 name2 or -C 0 */
975 if (opt_C[0] == '0' && opt_C[1] == '\0') /* -C 0 */
976 myerror(FATAL|NOERRNO, "-C 0 makes no sense");
977 else if (strlen(mybasename(opt_C)) != strlen(opt_C)) /* -C dir/name */
978 myerror(FATAL|NOERRNO, "-C option argument should not contain directory components");
979 else if (opt_C[0] == '-') /* -C -d (?) */
980 myerror(FATAL|NOERRNO, "-C option needs argument");
981 else /* -C name */
982 command_name = opt_C;
983 } else { /* -C -2 */
984 myerror (FATAL|NOERRNO, "-C option needs string or positive number as argument, perhaps you meant -C %d?",
985 -countback);
986 }
987 } else { /* no -C option given, use command name */
988 command_name = mysavestring(mybasename(argv[optind]));
989 }
990 assert(command_name != NULL);
991 return command_name;
992 }
993
994
995 int
output_queue_is_nonempty()996 output_queue_is_nonempty()
997 {
998 return (output_queue ? TRUE : FALSE);
999 }
1000
1001 void
put_in_output_queue(char * stuff)1002 put_in_output_queue(char *stuff)
1003 {
1004
1005 output_queue = append_and_free_old(output_queue, stuff);
1006 DPRINTF3(DEBUG_TERMIO,"put %d bytes in output queue (which now has %d bytes): %s", (int) strlen(stuff), (int) strlen(output_queue), M(stuff));
1007
1008 }
1009
1010
1011 /*
1012 * flush the output queue, writing its contents to master_pty_fd
1013 * never write more than one line, or BUFFSIZE in one go
1014 */
1015
1016 void
flush_output_queue()1017 flush_output_queue()
1018 {
1019 int nwritten, queuelen, how_much;
1020 char *old_queue = output_queue;
1021 char *nl;
1022
1023 if (!output_queue)
1024 return;
1025 queuelen = strlen(output_queue);
1026 nl = strchr(output_queue, '\n');
1027 how_much = min(BUFFSIZE, nl ? 1+ nl - output_queue : queuelen); /* never write more than one line, and never more than BUFFSIZE in one go */
1028 nwritten = write(master_pty_fd, output_queue, how_much);
1029
1030 assert(nwritten <= (int) strlen(output_queue));
1031 if (debug) {
1032 char scratch = output_queue[nwritten];
1033 output_queue[nwritten] = '\0'; /* temporarily replace the last written byte + 1 by a '\0' */
1034 DPRINTF3(DEBUG_TERMIO,"flushed %d of %d bytes from output queue to pty: %s", nwritten, queuelen, M(output_queue));
1035 output_queue[nwritten] = scratch;
1036 }
1037
1038 if (nwritten < 0) {
1039 switch (nwritten) {
1040 case EINTR:
1041 case EAGAIN:
1042 return;
1043 default:
1044 myerror(FATAL|USE_ERRNO, "write to master pty failed");
1045 }
1046 }
1047
1048 if (!output_queue[nwritten]) /* nothing left in queue */
1049 output_queue = NULL;
1050 else
1051 output_queue = mysavestring(output_queue + nwritten); /* this much is left to be written */
1052
1053 free(old_queue);
1054 }
1055
1056
1057 void
cleanup_rlwrap_and_exit(int status)1058 cleanup_rlwrap_and_exit(int status)
1059 {
1060 unblock_all_signals();
1061 DPRINTF0(DEBUG_TERMIO, "Cleaning up");
1062
1063 if (write_histfile && (histsize==0 || history_total_bytes() > 0)) /* avoid creating empty .speling_eror_history file after typo */
1064 write_history(history_filename); /* ignore errors */
1065
1066 close_logfile();
1067
1068 DPRINTF4(DEBUG_SIGNALS, "command_pid: %d, commands_exit_status: %x, filter_pid: %d, filters_exit_status: %x",
1069 command_pid, commands_exit_status, filter_pid, filters_exit_status);
1070 mymicrosleep(10); /* we may have got an EOF or EPIPE because the filter or command died, but this doesn't mean that
1071 SIGCHLD has been caught already. Taking a little nap now improves the chance that we will catch it
1072 (no grave problem if we miss it, but diagnostics, exit status and transparent signal handling depend on it) */
1073 if (filter_pid)
1074 kill_filter();
1075 else if (filter_is_dead) {
1076 int filters_killer = killed_by(filters_exit_status);
1077 myerror(WARNING|NOERRNO, (filters_killer ? "filter was killed by signal %d (%s)" :
1078 WEXITSTATUS(filters_exit_status) ? "filter died" : "filter exited"), filters_killer, signal_name(filters_killer));
1079 }
1080 if (debug)
1081 debug_postmortem();
1082
1083
1084 if (bracketed_paste_enabled) {
1085 DPRINTF0(DEBUG_READLINE, "disabling bracketed-paste");
1086 my_putstr(term_disable_bracketed_paste);
1087 }
1088 if (terminal_settings_saved)
1089 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_terminal_settings) < 0) /* ignore errors (almost dead anyway) */
1090 { /* nothing ... */ } /* fprintf(stderr, "Arggh\n"); don't use myerror!!*/
1091
1092 if (!newline_came_last) /* print concluding newline, if necessary */
1093 my_putstr("\n");
1094
1095
1096 if (status != EXIT_SUCCESS) /* rlwrap itself has failed, rather than the wrapped command */
1097 exit(status);
1098 else {
1099 int commands_killer = killed_by(commands_exit_status);
1100 if (commands_killer)
1101 suicide_by(commands_killer, commands_exit_status); /* command terminated by signal, make rlwrap's
1102 parent believe rlwrap was killed by it */
1103 else
1104 exit(WEXITSTATUS(commands_exit_status)); /* propagate command's exit status */
1105 }
1106 }
1107
1108
1109