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