1 
2 /*  rlwrap.h: includes, definitions, declarations */
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:
19     e-mail:  hanslub42@gmail.com
20 */
21 
22 
23 #include "../config.h"
24 #include <sys/types.h>
25 #if HAVE_SYS_WAIT_H
26 #  include <sys/wait.h>
27 #endif
28 
29 #ifndef WEXITSTATUS
30 #  define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
31 #endif
32 
33 
34 
35 #include <sys/stat.h>
36 #include <sys/ioctl.h>
37 #include <sys/resource.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <inttypes.h>  /* stdint.h is not on AIX, inttypes.h is in ISO C 1999 */
44 
45 #include <errno.h>
46 #include <stdarg.h>
47 
48 #if defined(__DragonFly__)
49 #include <stdbool.h>
50 #endif
51 
52 /* #define __USE_XOPEN
53    #define __USE_GNU */
54 
55 #include <stdlib.h>
56 #include <locale.h>
57 
58 
59 #include <sched.h>
60 
61 
62 
63 
64 #if TIME_WITH_SYS_TIME
65 # include <sys/time.h>
66 # include <time.h>
67 #else
68 # if HAVE_SYS_TIME_H
69 #  include <sys/time.h>
70 # else
71 #  include <time.h>
72 # endif
73 #endif
74 
75 #if HAVE_SYS_FILE_H
76 #include <sys/file.h>
77 #endif
78 
79 #ifdef HAVE_GETOPT_H
80 #  include <getopt.h>
81 #endif
82 
83 #ifdef HAVE_STROPTS_H
84 #  include <stropts.h>
85 #endif
86 
87 
88 
89 #ifdef HAVE_LIBGEN_H
90 #  include <libgen.h>
91 #endif
92 
93 #ifdef HAVE_CURSES_H
94 #  include <curses.h>
95 #  ifdef HAVE_TERM_H
96 #    include <term.h>
97 #  else
98 #    ifdef HAVE_NCURSES_TERM_H /* cygwin? AIX? */
99 #      include <ncurses/term.h>
100 #    endif
101 #  endif
102 #else
103 #  ifdef HAVE_TERMCAP_H
104 #     include <termcap.h>
105 #  endif
106 #endif
107 
108 #include <termios.h>
109 
110 
111 #ifdef HAVE_REGEX_H
112 #  include <regex.h>
113 #endif
114 
115 #if STDC_HEADERS
116 #  include <string.h>
117 #else
118 #  ifndef HAVE_STRRCHR
119 #    define strrchr rindex
120 #  endif
121 char *strchr(), *strrchr();
122 
123 #  ifndef HAVE_MEMMOVE
124 #    define memmove(d, s, n) bcopy ((s), (d), (n))
125 #  endif
126 #endif
127 
128 
129 #ifdef HAVE_PTY_H /* glibc (even if BSD) */
130 #  include <pty.h>
131 #elif HAVE_LIBUTIL_H /* BSD, non-glibc */
132 #  include <libutil.h>
133 #elif HAVE_UTIL_H /* BSD, other varriants */
134 #  include <util.h>
135 #endif
136 
137 
138 #if HAVE_DECL_PROC_PIDVNODEPATHINFO
139 #  include <libproc.h>
140 #endif
141 
142 #if HAVE_FREEBSD_LIBPROCSTAT
143 #  include <sys/param.h>
144 #  include <sys/queue.h>
145 #  include <sys/socket.h>
146 #  include <libprocstat.h>
147 #  include <sys/sysctl.h>
148 #endif
149 
150 #if HAVE_PROC_PID_CWD || HAVE_DECL_PROC_PIDVNODEPATHINFO || HAVE_FREEBSD_LIBPROCSTAT
151 #  define CAN_FOLLOW_COMMANDS_CWD 1
152 #endif
153 
154 #define BUFFSIZE 2048
155 
156 #ifndef MAXPATHLEN
157 #define MAXPATHLEN 512
158 #endif
159 
160 
161 #ifdef  HAVE_SNPRINTF           /* don't rely on the compiler understanding variadic macros */
162 # define snprintf0(buf,bufsize,format)                           snprintf(buf,bufsize,format)
163 # define snprintf1(buf,bufsize,format,arg1)                      snprintf(buf,bufsize,format,arg1)
164 # define snprintf2(buf,bufsize,format,arg1,arg2)                 snprintf(buf,bufsize,format,arg1,arg2)
165 # define snprintf3(buf,bufsize,format,arg1,arg2,arg3)            snprintf(buf,bufsize,format,arg1,arg2,arg3)
166 # define snprintf4(buf,bufsize,format,arg1,arg2,arg3,arg4)       snprintf(buf,bufsize,format,arg1,arg2,arg3,arg4)
167 # define snprintf5(buf,bufsize,format,arg1,arg2,arg3,arg4,arg5)  snprintf(buf,bufsize,format,arg1,arg2,arg3,arg4,arg5)
168 # define snprintf6(buf,bufsize,format,arg1,arg2,arg3,arg4,arg5,arg6)  snprintf(buf,bufsize,format,arg1,arg2,arg3,arg4,arg5,arg6)
169 
170 #else
171 # define snprintf0(buf,bufsize,format)                           sprintf(buf,format)
172 # define snprintf1(buf,bufsize,format,arg1)                      sprintf(buf,format,arg1)
173 # define snprintf2(buf,bufsize,format,arg1,arg2)                 sprintf(buf,format,arg1,arg2)
174 # define snprintf3(buf,bufsize,format,arg1,arg2,arg3)            sprintf(buf,format,arg1,arg2,arg3)
175 # define snprintf4(buf,bufsize,format,arg1,arg2,arg3,arg4)       sprintf(buf,format,arg1,arg2,arg3,arg4)
176 # define snprintf5(buf,bufsize,format,arg1,arg2,arg3,arg4,arg5)  sprintf(buf,format,arg1,arg2,arg3,arg4,arg5)
177 # define snprintf6(buf,bufsize,format,arg1,arg2,arg3,arg4,arg5,arg6)  sprintf(buf,format,arg1,arg2,arg3,arg4,arg5,arg6)
178 # define vsnprintf(buf,bufsize,format,ap)                        vsprintf(buf,format,ap)
179 #endif
180 
181 
182 #ifndef HAVE_STRNLEN
183 # define strnlen(s,l) strlen(s)
184 #endif
185 
186 
187 
188 #include <readline/readline.h>
189 #include <readline/history.h>
190 
191 
192 #ifndef HAVE_RL_VARIABLE_VALUE
193 #  define rl_variable_value(s) "off"
194 #endif
195 
196 #ifndef HAVE_RL_READLINE_VERSION
197 #  define rl_readline_version 0xbaddef
198 #endif
199 
200 #if defined(SPY_ON_READLINE)
201 extern int _rl_eof_char; /* Spying on readline's private life .... */
202 extern int _rl_horizontal_scroll_mode;
203 # if !defined(HOMEGROWN_REDISPLAY)
204 #  define MAYBE_MULTILINE 1
205 # endif
206 #else
207 # define _rl_eof_char 0
208 #endif
209 
210 #ifdef MAYBE_MULTILINE
211 #  define redisplay_multiple_lines (!_rl_horizontal_scroll_mode)
212 #else
213 #  define redisplay_multiple_lines (strncmp(rl_variable_value("horizontal-scroll-mode"),"off",3) == 0)
214 #endif
215 
216 
217 
218 
219 
220 
221 extern void test_main(void);
222 
223 /* in main.c: */
224 extern int master_pty_fd;
225 extern int slave_pty_sensing_fd;
226 extern FILE *debug_fp;
227 extern char *program_name, *command_name;
228 extern int always_readline;
229 extern int always_echo;
230 extern int complete_filenames;
231 extern int within_line_edit;
232 extern int screen_is_alternate;
233 extern pid_t command_pid;
234 extern char *rlwrap_command_line;
235 extern int unit_test_argc;
236 extern char **unit_test_argv;
237 extern char *command_line;
238 extern char *extra_char_after_completion;
239 extern int i_am_child;
240 extern int i_am_filter;
241 extern int nowarn;
242 extern int debug;
243 extern char *password_prompt_search_string;
244 extern int one_shot_rlwrap;
245 extern char *substitute_prompt;
246 extern char *history_format;
247 extern char *forget_regexp;
248 extern char *multi_line_tmpfile_ext;
249 extern char *prompt_regexp;
250 extern int renice;
251 extern int ignore_queued_input;
252 extern int history_duplicate_avoidance_policy;
253 extern int pass_on_sigINT_as_sigTERM;
254 /* now follow the possible values for history_duplicate_avoidance_policy: */
255 #define KEEP_ALL_DOUBLES                0
256 #define ELIMINATE_SUCCESIVE_DOUBLES     1
257 #define ELIMINATE_ALL_DOUBLES           2
258 extern int one_shot_rlwrap;
259 extern int ansi_colour_aware;
260 extern int bleach_the_prompt;
261 extern int colour_the_prompt;
262 extern int received_WINCH;
263 extern int prompt_is_still_uncooked;
264 extern int mirror_arguments;
265 extern int impatient_prompt;
266 extern int we_just_got_a_signal_or_EOF;
267 extern int remember_for_completion;
268 extern int commands_children_not_wrapped;
269 extern int accepted_lines;
270 extern char *filter_command;
271 extern int polling;
272 
273 void cleanup_rlwrap_and_exit(int status);
274 void put_in_output_queue(char *stuff);
275 int  output_queue_is_nonempty(void);
276 void flush_output_queue(void);
277 
278 /* in readline.c: */
279 extern struct rl_state
280 {                               /* struct to save readline state while we're processing output from slave command*/
281   char *input_buffer;           /* current input buffer */
282   char *raw_prompt;             /* current prompt */
283   char *cooked_prompt;          /* ditto redefined by user, or with colour added */
284   int point;                    /* cursor position within input buffer */
285   int already_saved;            /* flag set when saved, cleared when restored */
286 } saved_rl_state;
287 
288 void save_rl_state(void);
289 void restore_rl_state(void);
290 void message_in_echo_area(char *message);
291 void init_readline(char *);
292 void my_redisplay(void);
293 void initialise_colour_codes(char *colour);
294 void reprint_prompt(int coloured);
295 char *colourise (const char *prompt);
296 void move_cursor_to_start_of_prompt(int erase);
297 #define ERASE 1
298 #define DONT_ERASE 0
299 int prompt_is_single_line(void);
300 char *process_new_output(const char* buffer, struct rl_state* state);
301 int cook_prompt_if_necessary (void);
302 
303 extern int transparent;
304 extern char *multiline_separator;
305 extern char *pre_given;
306 extern int leave_prompt_alone;
307 extern bool bracketed_paste_enabled;
308 
309 
310 /* in signals.c */
311 extern volatile int command_is_dead;
312 extern int commands_exit_status;
313 extern int filter_is_dead;
314 extern int filters_exit_status;
315 extern int sigterm_received;
316 extern int deferred_adapt_commands_window_size;
317 extern int signal_handlers_were_installed;
318 extern int received_sigALRM;
319 
320 #ifndef RETSIGTYPE
321 #define RETSIGTYPE void /* systems where RETSIGTYPE = int have died out, apparently */
322 #endif
323 typedef RETSIGTYPE (*sighandler_type)(int);
324 
325 /* we'll install signal handlers with mysignal(SIGBLAH, HANDLER(handler)), to improve debug log readabilty */
326 void mysignal(int sig, sighandler_type handler, const char *handler_name);
327 #define HANDLER(f) &f, #f
328 
329 void install_signal_handlers(void);
330 void block_signals(int *sigs);
331 void unblock_signals(int *sigs);
332 void block_all_passed_on_signals(void);
333 void block_all_signals(void);
334 void unblock_all_signals(void);
335 void ignore_sigchld(void);
336 void suicide_by(int sig, int status);
337 int  adapt_tty_winsize(int from_fd, int to_fd);
338 void myalarm(int msec);
339 void handle_sigALRM(int signo);
340 char *signal_name(int signal);
341 
342 
343 /* in utils.c */
344 void  yield(void);
345 void  zero_select_timeout(void);
346 int   my_pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *ptimeout_ts, const sigset_t *sigmask);
347 struct termios *my_tcgetattr(int fd, char *which);
348 int   read_patiently(int fd, void *buffer, int count, char *whence);
349 int   write_patiently(int fd, const void *buffer, int count, const char *whither);
350 void  read_patiently2(int fd, void *buffer, int count, int uninterruptible_msec, const char *whence);
351 void  write_patiently2(int fd, const void *buffer, int count, int uninterruptible_msec, const char *whither);
352 void  mysetenv(const char *name, const char *value);
353 void  set_ulimit(int resource, long value);
354 void  usage(int status);
355 int   open_unique_tempfile(const char *suffix, char **tmpfile_name);
356 void  mirror_args_init(char **argv);
357 void  mirror_args(pid_t command_pid);
358 
359 /* flags to use for the error_flags argument to myerror */
360 #define FATAL     2
361 #define WARNING   0
362 #define USE_ERRNO 1
363 #define NOERRNO   0
364 
365 /* constant to signify the end of a free_multiple() argument list (NULL would't work) */
366 #define FMEND  ((void *) -1)
367 
368 void  myerror(int error_flags, const char *message, ...);
369 void  *mymalloc(size_t size);
370 void  free_multiple(void *ptr, ...);
371 void  mysetsid(void);
372 void  close_open_files_without_writing_buffers(void);
373 size_t filesize(const char *filename);
374 void  my_fopen(FILE  **pfp, const char *path, const char *mode, const char *description);
375 void  open_logfile(const char *filename);
376 void  write_logfile(const char *str);
377 void  close_logfile(void);
378 void  timestamp(char *buf, int size);
379 unsigned long hash_multiple(int n, ...);
380 int   killed_by(int status);
381 void  change_working_directory(void);
382 void  log_terminal_settings(struct termios *terminal_settings);
383 void  log_fd_info(int fd);
384 void  last_minute_checks(void);
385 void  mymicrosleep(int msec);
386 void  do_nothing(int unused);
387 
388 
389 /* in string_utils.c */
390 char *mybasename(const char *filename);
391 char *mydirname(const char *filename);
392 void  mystrlcpy(char *dst, const char *src, size_t size);
393 void  mystrlcat(char *dst, const char *src, size_t size);
394 bool strings_are_equal(const char *s1, const char *s2);
395 char *mystrstr(const char *haystack, const char *needle);
396 char *mysavestring(const char *string);
397 char *strifnull(char *string);
398 char *add3strings(const char *str1, const char *str2, const char *str3);
399 #define add2strings(a,b)  add3strings(a,b,"")
400 int my_atoi(const char *nptr);
401 char *mystrtok(const char *s, const char *delim);
402 char **split_with(const char *string, const char *delim);
403 char *unsplit_with(int n, char ** strings, const char *delim);
404 char **split_on_single_char(const char *string, char c, int expected_count);
405 int scan_metacharacters(const char* string, const char *metacharacters);
406 char **list4 (char *el0, char *el1, char *el2, char *el3);
407 void free_splitlist (char **list);
408 char *append_and_free_old(char *str1, const char *str2);
409 char *mangle_char_for_debug_log(char c, int quote_me);
410 char *mangle_string_for_debug_log(const char *string, int maxlen);
411 char *mangle_buffer_for_debug_log(const char *buffer, int length);
412 char *mem2str(const char *mem, int size);
413 char *search_and_replace(char *patt, const char *repl, const char *string,
414                          int cursorpos, int *line, int *col);
415 char *first_of(char **strings);
416 char *as_string(int i);
417 char *append_and_expand_history_format(char *line);
418 void remove_padding_and_terminate(char *buf, int length);
419 void unbackspace(char* buf);
420 char *mark_invisible(const char *buf);
421 char *copy_and_unbackspace(const char *original);
422 int colourless_strlen(const char *str, char **pcopy_without_ignore_markers, int termwidth);
423 int colourless_strlen_unmarked (const char *str, int termwidth);
424 char *get_last_screenline(char *long_line, int termwidth);
425 char *lowercase(const char *str);
426 char *colour_name_to_ansi_code(const char *colour_name);
427 int match_regexp(const char *string, const char *regexp, int case_insensitive);
428 int isnumeric(char *string);
429 #define END_FIELD (char*)NULL /* marker object to terminate vargs */
430 char *append_field_and_free_old(char *message, const char *field);
431 char *merge_fields(char *field, ...);
432 char **split_filter_message(char *message, int *count);
433 char *protect_or_cleanup(char *prompt, bool free_prompt);
434 void check_cupcodes(const char *client_output);
435 
436 /* in pty.c: */
437 pid_t my_pty_fork(int *, const struct termios *, const struct winsize *);
438 int slave_is_in_raw_mode(void);
439 struct termios *get_pterm_slave(void);
440 void mirror_slaves_echo_mode(void);
441 void completely_mirror_slaves_terminal_settings(void);
442 void completely_mirror_slaves_output_settings(void);
443 void completely_mirror_slaves_special_characters(void);
444 void write_EOF_to_master_pty(void);
445 void write_EOL_to_master_pty(char *);
446 int dont_wrap_command_waits(void);
447 int skip_rlwrap(void);
448 
449 /* in ptytty.c: */
450 int ptytty_get_pty(int *fd_tty, const char **ttydev);
451 int ptytty_get_tty(const char *ttydev);
452 int ptytty_control_tty(int fd_tty, const char *ttydev);
453 int ptytty_openpty(int *amaster, int *aslave, const char **name);
454 
455 /* in completion.rb: */
456 void init_completer(void);
457 void feed_file_into_completion_list(const char *completions_file);
458 void feed_line_into_completion_list(const char *line);
459 void add_word_to_completions(const char *word);
460 void remove_word_from_completions(const char *word);
461 char *my_completion_function(char *prefix, int state);
462 
463 extern int completion_is_case_sensitive;
464 
465 
466 /* in term.c: */
467 extern int redisplay;                  /* TRUE when user input should be readable (instead of *******)  */
468 void init_terminal(void);
469 void set_echo(int);
470 void prepare_terminal(void);
471 void cr(void);
472 void backspace(int);
473 void clear_line(void);
474 void clear_the_screen(void);
475 void curs_up(void);
476 void curs_down(void);
477 void curs_left(void);
478 void test_terminal(void);
479 int my_putchar(TPUTS_PUTC_ARGTYPE c);
480 void my_putstr(const char *string);
481 int cursor_hpos(int col);
482 extern struct termios saved_terminal_settings;
483 extern int terminal_settings_saved;
484 extern struct winsize winsize;
485 extern char *term_name;
486 extern char *term_backspace, term_eof, term_stop, *term_cursor_hpos,
487   *term_cursor_up, *term_cursor_down, *term_cursor_left, *term_smcup,
488   *term_rmcup, *term_rmkx, *term_enable_bracketed_paste, *term_disable_bracketed_paste;
489 extern int term_has_colours;
490 extern int newline_came_last;
491 
492 /* in filter.c */
493 
494 #define MAX_TAG 255
495 #define TAG_INPUT 0
496 #define TAG_OUTPUT 1
497 #define TAG_HISTORY 2
498 #define TAG_COMPLETION 3
499 #define TAG_PROMPT 4
500 #define TAG_HOTKEY 5
501 #define TAG_SIGNAL 6
502 #define MAX_INTERESTING_TAG 6 /* max tag for which the filter can have a handler */
503 
504 #define TAG_WHAT_ARE_YOUR_INTERESTS 127
505 
506 
507 #define TAG_IGNORE 251
508 #define TAG_ADD_TO_COMPLETION_LIST 252
509 #define TAG_REMOVE_FROM_COMPLETION_LIST 253
510 #define TAG_OUTPUT_OUT_OF_BAND  254
511 #define TAG_ERROR 255
512 
513 #define out_of_band(tag) (tag & 128)
514 
515 
516 extern pid_t filter_pid;
517 extern int filter_is_dead;
518 void spawn_filter(const char *filter_command);
519 void kill_filter(void);
520 int filter_is_interested_in(int tag);
521 char *pass_through_filter(int tag, const char *buffer);
522 char *filters_last_words(void);
523 void filter_test(void);
524 
525 
526 
527 /* in multibyte.c: */
528 
529 #ifdef MULTIBYTE_AWARE /* i.e. if configured with --enable-multibyte-aware  */
530    #include <wchar.h>
531    #define MBSTATE mbstate_t
532 #else
533    #define MBSTATE int
534 #endif
535 
536 MBSTATE * mbc_initstate(MBSTATE *st);
537 MBSTATE *mbc_copystate(MBSTATE st, MBSTATE *stc);
538 int mbc_is_valid(const char *mb_string, const MBSTATE *st);
539 const char * mbc_next(const char *mb_string, MBSTATE *st);
540 int mbc_charwidth(const char *p, MBSTATE *st);
541 char *mbc_first(const char *mb_string, const MBSTATE *st);
542 int is_multibyte(const char *mb_char, const MBSTATE *st);
543 const char *mbc_inc(const char **mbc, MBSTATE *st);
544 void mbc_copy(const char *p, char **q, MBSTATE *st);
545 size_t mbc_strnlen(const char *mb_string, size_t maxlen, MBSTATE *st);
546 
547 
548 
549 /* some handy macros */
550 
551 #ifndef TRUE
552 #  define TRUE 1
553 #endif
554 
555 #ifndef FALSE
556 #  define FALSE 0
557 #endif
558 
559 
560 #ifndef min
561 # define min(a,b) ((a) < (b) ? (a) : (b))
562 #endif
563 
564 #ifndef max
565 # define max(a,b) ((a) < (b) ? (b) : (a))
566 #endif
567 
568 
569 /* macros for writing unit tests */
570 typedef enum  {TEST_AT_PROGRAM_START, TEST_AFTER_OPTION_PARSING, TEST_AFTER_SPAWNING_SLAVE_COMMAND,TEST_AFTER_READLINE_INIT} test_stage;
571 #define TESTFUNC(f, argc, argv, stage)   void f(int argc, char **argv, test_stage stage)
572 #define ONLY_AT_STAGE(s) if(stage != s) return
573 
574 
575 
576 #include "malloc_debug.h" /* malloc_debug.{c,h} not ready for prime time */
577 
578 #define DEBUG_FILENAME "/tmp/rlwrap.debug"
579 #define KA_BOOM  {char *p = (char *) 1; *p = 'c';} /* dump core right here  */
580 #define KA_SCRUNCH {volatile int x=1, y=0; x = x/y;} /* force a SIGFPE */
581 #define KA_SCREECH kill(getpid(),SIGTRAP);        /* enter the debugger - use it to set (conditional) breakpoints from within C code: if (condition) KA_SCREECH; */
582 
583 /* DPRINTF0 and its ilk  doesn't produce any output except when DEBUG is #defined (via --enable-debug configure option) */
584 
585 /* Use a superfluous "break" (withn a switch) to prevent "this statement may fall through" warnings when we know that a statement will end the program anyway */
586 #define WONTRETURN(statement) statement;break
587 
588 
589 # ifdef __GNUC__
590 #   define __MYFUNCTION__ __extension__ __FUNCTION__
591 #   define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
592 #   define UNUSED_FUNCTION(f) __attribute__((__unused__)) UNUSED_ ## f
593 # else
594 #   define __MYFUNCTION__ ""
595 #   define UNUSED(x) UNUSED_ ## x
596 #   define UNUSED_FUNCTION(f) UNUSED_ ## f
597 # endif
598 
599 
600 #define MAYBE_UNUSED(x) (void) (x)
601 
602 #ifdef  DEBUG
603 
604 
605 #  define DEBUG_TERMIO                           1
606 #  define DEBUG_SIGNALS                          2
607 #  define DEBUG_READLINE                         4
608 #  define DEBUG_MEMORY_MANAGEMENT                8   /* used with malloc_debug.c */
609 #  define DEBUG_FILTERING                        16
610 #  define DEBUG_COMPLETION                       32
611 #  define DEBUG_AD_HOC                           64  /* only used during rlwrap development */
612 #  define DEBUG_WITH_TIMESTAMPS                  128 /* add timestamps to every line in debug log    */
613 #  define FORCE_HOMEGROWN_REDISPLAY              256 /* force use of my_homegrown_redisplay()        */
614 #  define DEBUG_LONG_STRINGS                     512 /* log all strings completely, however long they are */
615 #  define DEBUG_RACES                            1024 /* introduce random delays */
616 #  define DEBUG_RANDOM_FAIL                      2048 /* fail tests randomly */
617 #  define DEBUG_SHOWCURSOR                       4096 /* run test_main and exit  */
618 
619 #  define DEBUG_MAX                              DEBUG_SHOWCURSOR
620 #  define MANGLE_LENGTH                          ((debug_saved & DEBUG_LONG_STRINGS) ? 0 : 20) /* debug_saved is defined within DPRINTF macro */
621 #  define DEBUG_DEFAULT                          (DEBUG_TERMIO | DEBUG_SIGNALS | DEBUG_READLINE)
622 #  define DEBUG_ALL                              (2*DEBUG_MAX-1)
623 
624 #  define M(x)                                   mangle_string_for_debug_log(x, MANGLE_LENGTH)
625 
626 
627 #  define ONLY_USED_FOR_DEBUGGING(x) x
628 
629 
630 #  ifndef HAVE_FLOCK
631 #    define flock(x,y)
632 #  endif
633 
634 
635 # define WHERE_AND_WHEN \
636   int debug_saved = debug; char file_line[100], when[100];                          \
637   if(debug & DEBUG_WITH_TIMESTAMPS) timestamp(when, sizeof(when)); else *when='\0'; \
638   debug = 0; /* don't debug while evaluating the DPRINTF arguments */               \
639   snprintf2(file_line, sizeof(file_line), "%.15s:%d:", __FILE__, __LINE__);         \
640   flock(fileno(debug_fp), LOCK_EX);                                                 \
641   fseek(debug_fp, 0, SEEK_END);                                                     \
642   fprintf(debug_fp, "%-20s %s %-7s %-25.25s ", file_line, when, (i_am_child ? "child" : i_am_filter? "filter" :"parent"), __MYFUNCTION__);
643 
644 
645 #  define NL_AND_FLUSH           fputc('\n', debug_fp) ; fflush(debug_fp); flock(fileno(debug_fp), LOCK_UN); debug = debug_saved
646 
647 #  define DPRINTF0(mask, format)                                        \
648   do {if ((debug & mask) && debug_fp) {WHERE_AND_WHEN; fprintf(debug_fp, format); NL_AND_FLUSH; }} while(FALSE)
649 
650 #  define DPRINTF1(mask, format,arg)                                    \
651   do {if ((debug & mask) && debug_fp) {WHERE_AND_WHEN; fprintf(debug_fp, format, arg); NL_AND_FLUSH; }} while(FALSE)
652 
653 #  define DPRINTF2(mask, format,arg1, arg2)                             \
654   do {if ((debug & mask) && debug_fp) {WHERE_AND_WHEN; fprintf(debug_fp, format, arg1, arg2); NL_AND_FLUSH; }} while (FALSE)
655 
656 #  define DPRINTF3(mask, format,arg1, arg2, arg3)                       \
657   do {if ((debug & mask) && debug_fp) {WHERE_AND_WHEN; fprintf(debug_fp, format, arg1, arg2, arg3); NL_AND_FLUSH; }} while (FALSE)
658 
659 #  define DPRINTF4(mask, format,arg1, arg2, arg3, arg4)                 \
660   do {if ((debug & mask) && debug_fp) {WHERE_AND_WHEN; fprintf(debug_fp, format, arg1, arg2, arg3, arg4); NL_AND_FLUSH; }} while (FALSE)
661 
662 #  define DPRINTF5(mask, format,arg1, arg2, arg3, arg4, arg5)                \
663   do {if ((debug & mask) && debug_fp) {WHERE_AND_WHEN; fprintf(debug_fp, format, arg1, arg2, arg3, arg4, arg5); NL_AND_FLUSH; }} while (FALSE)
664 
665 
666 #  define ERRMSG(b)              (b && (errno != 0) ? add3strings("(", strerror(errno), ")") : "" )
667 
668 #  define SHOWCURSOR(c)          if (debug & DEBUG_SHOWCURSOR) {my_putchar(c); mymicrosleep(1000); curs_left();} /* (may work incorrectly at last column!)*/
669 
670 #  define DEBUG_RANDOM_SLEEP        if (debug & DEBUG_RACES) {int sleeptime=rand()&31; DPRINTF1(DEBUG_RACES,"sleeping for %d msecs", sleeptime); mymicrosleep(sleeptime);}
671 
672 
673 #else
674 #  define ONLY_USED_FOR_DEBUGGING(x) UNUSED(x)
675 #  define MANGLE_LENGTH          0
676 #  define DPRINTF0(mask, format)  do {;} while(FALSE)
677 #  define DPRINTF1(mask, format,arg) do {;} while(FALSE)
678 #  define DPRINTF2(mask, format,arg1, arg2) do {;} while(FALSE)
679 #  define DPRINTF3(mask, format,arg1, arg2, arg3) do {;} while(FALSE)
680 #  define DPRINTF4(mask, format,arg1, arg2, arg3, arg4) do {;} while(FALSE)
681 #  define DPRINTF5(mask, format,arg1, arg2, arg3, arg4, arg5) do {;} while(FALSE)
682 #  define ERRMSG(b)
683 #  define SHOWCURSOR
684 #  define DEBUG_RANDOM_SLEEP
685 
686 /* Don't #define NDEBUG!  There are assertions that cannot be skipped, as in assert(important_function_call()) */
687 /* Todo (maybe) #define myassert(x) if(DEBUG){assert(x)} for the other (skippable) assertions                  */
688 
689 #endif
690 
691 #include <assert.h>
692