1 /*  This program is free software; you can redistribute it and/or modify
2     it under the terms of the GNU General Public License as published by
3     the Free Software Foundation; either version 2 of the License , or
4     (at your option) any later version.
5 
6     This program is distributed in the hope that it will be useful,
7     but WITHOUT ANY WARRANTY; without even the implied warranty of
8     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9     GNU General Public License for more details.
10 
11     You should have received a copy of the GNU General Public License
12     along with this program; see the file COPYING.  If not, write to
13     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
14 
15     You may contact the author by:
16     e-mail:  hanslub42@gmail.com
17 */
18 
19 
20 
21 #include "rlwrap.h"
22 
23 
24 
25 
26 
27 static FILE *log_fp;
28 
29 
30 /* Give up the processor so that other processes (like command) can have their say. Especially useful with multi-line
31    input: if we, after writing a line to the inferior command, would return to the main select() loop immediately, we
32    would find more output to write, and keep blathering away without giving the poor command time to say something
33    back */
34 
35 void
yield()36 yield()
37 {
38   DPRINTF0(DEBUG_TERMIO, "yield...");
39 #if 0 /* If command writes some output and immediately starts a long computation, sched_yield() will not return for a
40          long time,and rlwrap will not see the output for all that time. The "poor mans sched_yield" with select
41          actually works better! */
42   sched_yield();
43 #else
44   { struct timeval a_few_millisecs = { 0, 1000 };
45     select(0, NULL, NULL, NULL, &a_few_millisecs); /* poor man's sched_yield() */
46   }
47 #endif
48 }
49 
50 
51 static volatile int signal_handled = FALSE;
52 
53 #ifdef HAVE_REAL_PSELECT
54 
zero_select_timeout()55 void zero_select_timeout () {
56   signal_handled = TRUE;
57 }
58 
59 #else
60 
61 
62 #define until_hell_freezes  NULL ;
63 static struct timeval * volatile pmy_select_timeout_tv; /* The SIGCHLD handler sets this variable (see zero_select_timeout() below) to make
64                                                           select() return immediately when a child has died. gcc (4.8 and higher) may optimize it
65                                                           into a register, which won't work: hence the "volatile" keyword */
66 static struct timeval my_select_timeout_tv;
67 
zero_select_timeout()68 void zero_select_timeout () {
69   my_select_timeout_tv.tv_sec = 0;
70   my_select_timeout_tv.tv_usec = 0;
71   pmy_select_timeout_tv = &my_select_timeout_tv;
72   signal_handled = TRUE;
73 }
74 #endif
75 
76 /*
77    Even though even older linux systems HAVE PSELECT, is is non-atomic: signal handlers may (and
78    generally will) run between the unblocking of the signals and the select call (which will
79    then wait untill hell freezes over) Therefore we always convert the contents op
80    ptimeout_ts into to a static struct timeval my_select_timeout_tv, and use the function
81    zero_select_timeout to set this to {0,0} from within a signal handler, which will then
82    make select return immediately.  (Linus Torvalds mentions this trick in
83    http://lkml.indiana.edu/hypermail/linux/kernel/0506.1/1191.html),
84 
85    As I know of no reliable way to distiguish real pselect from fake pselect at configure
86    time HAVE_REAL_PSELECT will be undefined on all systems, even those that do have a genuine
87    pselect.
88 */
89 
90 
91 
92 int
my_pselect(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,const struct timespec * ptimeout_ts,const sigset_t * sigmask)93 my_pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *ptimeout_ts, const sigset_t *sigmask) {
94 
95 #ifdef HAVE_REAL_PSELECT
96   return pselect(n, readfds, writefds, exceptfds, ptimeout_ts, sigmask);
97 #else
98   int retval;
99   sigset_t oldmask;
100   if (ptimeout_ts) { /* convert timespec e.g {0,40000000} to timeval {0, 40000} */
101     pmy_select_timeout_tv = &my_select_timeout_tv;
102     pmy_select_timeout_tv -> tv_sec = ptimeout_ts -> tv_sec;
103     pmy_select_timeout_tv -> tv_usec = ptimeout_ts -> tv_nsec / 1000;
104   } else
105     pmy_select_timeout_tv = until_hell_freezes;
106   signal_handled = FALSE;
107 
108   sigprocmask(SIG_SETMASK, sigmask, &oldmask);
109   /* most signals will be catched HERE (and their handlers will set my_select_timeout_tv to {0,0}) */
110   retval = select(n, readfds, writefds, exceptfds, pmy_select_timeout_tv);
111   /* but even if they are slow off the mark and get catched HERE the code 3 lines below will notice */
112   sigprocmask(SIG_SETMASK, &oldmask, NULL);
113 
114 
115   if (signal_handled && retval >= 0) {
116     errno = EINTR;
117     return -1;
118   } else {
119     return retval;
120   }
121 #endif
122 }
123 
124 struct termios *
my_tcgetattr(int fd,char * UNUSED (which))125 my_tcgetattr(int fd, char *UNUSED(which))
126 {
127   struct termios *pterm =
128     (struct termios *)mymalloc(sizeof(struct termios));
129   return tcgetattr(fd, pterm) < 0 ?  NULL : pterm;
130 }
131 
132 
133 /* empty signal handler */
134 void
do_nothing(int UNUSED (signal))135 do_nothing(int UNUSED(signal))
136 {
137   /* yawn.... */
138 }
139 
140 
141 
142 /* When using read (2) or write (2), one always has to be prepared to handle incomplete
143    reads or writes. The {read,write}_patiently* routines below do just that: they repeat the read
144    or write until the whole buffer has been filled, or an error occurs.
145    The {read,write}_patiently2 functions are specialised for reading/writing the input/output pipe
146    of a filter */
147 
148 
149 
150 int
write_patiently(int fd,const void * buffer,int count,const char * whither)151 write_patiently(int fd, const void *buffer, int count, const char *whither) {
152   int nwritten = 0;
153   int total_written =  0;
154   assert(count >= 0);
155   if (count == 0)
156     return TRUE;
157   while(1) {
158     if((nwritten = write(fd, (char *)buffer + total_written, count - total_written)) <= 0) {
159       if (errno == EINTR)
160         continue;
161       else if (errno == EPIPE || nwritten == 0) {
162         return FALSE;
163       } else
164         myerror(FATAL|USE_ERRNO, "write error %s", whither);
165     }
166 
167     total_written += nwritten;
168     if (total_written == count) /* done */
169       break;
170   }
171   return TRUE;
172 }
173 
174 
175 
176 
177 /* keep  reading from fd and write into buffer until count bytes have been read.
178    for uninterruptible_msec, restart when interrupted by a signal, after this,
179    bail out with an error. if count < 0, returns a 0-terminated copy of buffer  */
180 
181 
182 void
read_patiently2(int fd,void * buffer,int count,int uninterruptible_msec,const char * whence)183 read_patiently2 (int fd,
184                  void *buffer,
185                  int count,
186                  int uninterruptible_msec,
187                  const char *whence) {
188   int nread = 0;
189   int total_read =  0;
190   int interruptible = FALSE;
191 
192   DPRINTF2(DEBUG_AD_HOC, "read_patiently2 tries to read %d bytes (uninterruptible: %d msec)", count, uninterruptible_msec);
193 
194   assert (count >= 0);
195   if (count > 0) {
196     myalarm(uninterruptible_msec);
197     while (1) {
198       assert(count > total_read);
199       if((nread = read(fd, (char *) buffer + total_read, count - total_read)) <= 0) {
200         if (nread < 0 && errno == EINTR) {
201           if (interruptible)
202             myerror(FATAL|NOERRNO, "(user) interrupt reading %s, filter_hangs?", whence);
203 
204           if (received_sigALRM) {
205             received_sigALRM = FALSE;
206             interruptible = TRUE;
207           }
208           continue;
209         } else if (nread == 0)
210            myerror(FATAL|NOERRNO, "EOF reading %s", whence);
211          else  /* nread < 0 */
212            myerror(FATAL|USE_ERRNO, "error reading %s",  whence);
213 
214       }
215       total_read += nread;
216       if (total_read == count)  /* done */
217         break;
218 
219     }
220   }
221   myalarm(0); /* reset alarm */
222   block_all_signals();
223   DPRINTF2(DEBUG_AD_HOC, "read_patiently2 read %d bytes: %s", total_read, mangle_buffer_for_debug_log(buffer, total_read));
224   return;
225 }
226 
227 
228 
229 
230 
231 
232 void
write_patiently2(int fd,const void * buffer,int count,int uninterruptible_msec,const char * whither)233 write_patiently2(int fd,
234                  const void *buffer,
235                  int count,
236                  int uninterruptible_msec,
237                  const char* whither) {
238   int nwritten = 0;
239   int total_written =  0;
240   int interruptible = FALSE;
241 
242 
243   assert(count >= 0);
244   if (count == 0)
245     return; /* no-op */
246   myalarm(uninterruptible_msec);
247   while(1) {
248     if((nwritten = write(fd, (char *)buffer + total_written, count - total_written)) <= 0) {
249       if (nwritten < 0 && errno == EINTR) {
250         if (interruptible)
251            myerror(FATAL|NOERRNO, "(user) interrupt - filter hangs?");
252         if (received_sigALRM) {
253           received_sigALRM = FALSE;
254           interruptible = TRUE;
255         }
256         continue;
257       } else  /* nwritten== 0 or < 0 with error other than EINTR */
258         myerror(FATAL|USE_ERRNO, "error writing %s", whither);
259 
260     }
261     total_written += nwritten;
262     if (total_written == count) /* done */
263       break;
264   }
265   myalarm(0);
266   DPRINTF2(DEBUG_AD_HOC, "write_patiently2 wrote %d bytes: %s", total_written, mangle_buffer_for_debug_log(buffer, total_written));
267   return;
268 }
269 
270 
271 
272 void
mysetenv(const char * name,const char * value)273 mysetenv(const char *name, const char *value)
274 {
275   int return_value = 0;
276 
277 
278 #ifdef HAVE_SETENV
279   return_value = setenv(name, value, TRUE);
280 #elif defined(HAVE_PUTENV)
281   char *name_is_value = add3strings (name, "=", value);
282   return_value = putenv (name_is_value);
283 #else /* won't happen, but anyway: */
284   myerror(WARNING|NOERRNO, "setting environment variable %s=%s failed, as this system has neither setenv() nor putenv()", name, value);
285 #endif
286 
287   if (return_value != 0)
288     myerror(WARNING|USE_ERRNO, "setting environment variable %s=%s failed%s", name, value,
289            (errno ? "" : " (insufficient environment space?)"));     /* will setenv(...) = -1  set errno? */
290 }
291 
set_ulimit(int resource,long value)292 void set_ulimit(int resource, long value) {
293   #ifdef HAVE_SETRLIMIT
294   struct rlimit limit;
295   int result;
296 
297   limit.rlim_cur = value;
298   result = setrlimit(resource, &limit);
299   DPRINTF4(DEBUG_ALL, "setrlim() used to set resource #%d to value %ld, result = %d (%s)",
300           resource, value, result, (result == 0 ? "success" : "failure"));
301   #endif
302 }
303 
304 
305 
open_unique_tempfile(const char * suffix,char ** tmpfile_name)306 int open_unique_tempfile(const char *suffix, char **tmpfile_name) {
307   char **tmpdirs = list4(getenv("TMPDIR"), getenv("TMP"), getenv("TEMP"), "/tmp");
308   char *tmpdir = first_of(tmpdirs);
309   int tmpfile_fd;
310 
311   if (!suffix)
312     suffix = "";
313 
314   *tmpfile_name = mymalloc(MAXPATHLEN+1);
315 
316 #ifdef HAVE_MKSTEMPS
317   snprintf4(*tmpfile_name, MAXPATHLEN, "%s/%s_%s_XXXXXX%s", tmpdir, program_name, command_name, suffix);
318   tmpfile_fd = mkstemps(*tmpfile_name, strlen(suffix));  /* this will write into *tmpfile_name */
319 #else
320   {   static int tmpfile_counter = 0;
321       snprintf6(*tmpfile_name, MAXPATHLEN, "%s/%s_%s_%d_%d%s", tmpdir, program_name, command_name, command_pid, tmpfile_counter++, suffix);
322       tmpfile_fd = open(*tmpfile_name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
323   }
324 #endif
325   if (tmpfile_fd < 0)
326     myerror(FATAL|USE_ERRNO, "could not create readable/writable temporary file %s", tmpfile_name);
327   free(tmpdirs);
328   return tmpfile_fd;
329 }
330 
331 
332 
333 
334 static char*
markup(const char * colour_name,const char * str)335 markup(const char* colour_name, const char*str)
336 {
337   char *result, *colour_code;
338   if (colour_name && isatty(STDOUT_FILENO) && (ansi_colour_aware || term_has_colours || colour_the_prompt)) {
339     colour_code = add3strings("\033[", colour_name_to_ansi_code(colour_name), "m");
340     result = add3strings(colour_code, str,"\033[0m");
341     free(colour_code);
342   } else {
343     result =  mysavestring(str);
344   }
345   return result;
346 }
347 
348 
349 /* print error or warning message. There are two error flags,
350    defined in rlwrap.h
351 
352    FATAL:     exit(EXIT_FAILURE) after printing the message)
353    USE_ERRNO: print perror(errno) after the message
354 */
355 
356 
357 
358 
359 void
myerror(int error_flags,const char * message_format,...)360 myerror(int error_flags, const char *message_format, ...)
361 {
362   int saved_errno = errno;
363   char contents[BUFFSIZE];
364   int is_warning = !(error_flags & FATAL);
365   char *warning_or_error = is_warning ? "warning: " : "error: ";
366   char *coloured_warning_or_error = markup(is_warning? "Magenta" : "Red", warning_or_error);
367   char *message_for_debug_log;
368   static int warnings_given = 0;
369   char *message = add2strings(program_name, ": ");
370 
371   va_list ap;
372   va_start(ap, message_format);
373   vsnprintf(contents, sizeof(contents) - 1, message_format, ap);
374   va_end(ap);
375 
376   message = append_and_free_old(message, coloured_warning_or_error);
377   free(coloured_warning_or_error);
378   message = append_and_free_old(message, contents);
379 
380   if ((error_flags & USE_ERRNO) && saved_errno) {
381     message = append_and_free_old(message, ": ");
382     message = append_and_free_old(message, strerror(saved_errno));
383   }
384   message = append_and_free_old(message,"\n");
385   fflush(stdout);
386 
387   message_for_debug_log = search_and_replace("\n", "; ", contents, 0, NULL, NULL);
388   DPRINTF2(DEBUG_ALL, "%s %s", warning_or_error, message_for_debug_log);
389   free(message_for_debug_log);
390 
391   if (! (is_warning && nowarn))
392     fputs(message, stderr); /* @@@ error reporting (still) uses buffered I/O */
393 
394   if (is_warning && !warnings_given++ && !nowarn)
395     fputs("warnings can be silenced by the --no-warnings (-n) option\n", stderr);
396 
397   fflush(stderr);
398   free(message);
399   errno =  saved_errno;
400 
401   if (error_flags & FATAL) {
402     #ifdef DUMP_CORE_ON_ERROR
403       KA_BOOM;
404     #endif
405     if (!i_am_child)
406       cleanup_rlwrap_and_exit(EXIT_FAILURE);
407     else /* child: die and let parent clean up */
408       exit(EXIT_FAILURE);
409   }
410 
411 }
412 
413 /* fopen with error handling. Will close and re-open if *fp != NULL; */
my_fopen(FILE ** pfp,const char * path,const char * mode,const char * description)414 void my_fopen(FILE  **pfp, const char *path, const char *mode, const char *description ) {
415   char *what = "open";
416   char *how = mode[0] == 'w' ? "writing" : mode[0] == 'a' ? "appending" : "reading";
417   if (*pfp) {
418     fclose(*pfp);
419     what = "re-open";
420   }
421   *pfp = fopen(path, mode);
422   if (!*pfp)
423     myerror(FATAL|USE_ERRNO, "Cannot %s  %s %s for %s", what, description, path, how);
424 }
425 
426 
427 void
open_logfile(const char * filename)428 open_logfile(const char *filename)
429 {
430   time_t now;
431 
432   my_fopen(&log_fp, filename, "a", "logfile");
433   now = time(NULL);
434   fprintf(log_fp, "\n\n[rlwrap] %s\n", ctime(&now));
435 }
436 
437 
438 void
write_logfile(const char * str)439 write_logfile(const char *str)
440 {
441   if (log_fp)
442     fputs(str, log_fp);
443 }
444 
445 
446 size_t
filesize(const char * filename)447 filesize(const char *filename)
448 {
449   struct stat buf;
450 
451   if (stat(filename, &buf))
452     myerror(FATAL|USE_ERRNO, "couldn't stat file %s", filename);
453   return (size_t) buf.st_size;
454 }
455 
456 
457 
458 void
close_logfile()459 close_logfile()
460 {
461   if (log_fp)
462     fclose(log_fp);
463 }
464 
465 void
close_open_files_without_writing_buffers()466 close_open_files_without_writing_buffers() /* called from child just before exec(command) */
467 {
468   if(log_fp)
469     close(fileno(log_fp));  /* don't flush buffers to avoid avoid double double output output */
470   if (debug)
471     close(fileno(debug_fp));
472 }
473 
474 
475 void
timestamp(char * buf,int size)476 timestamp(char *buf, int size)
477 {
478   struct timeval now;
479   static struct timeval firsttime; /* remember when first called */
480   static int never_called = 1;
481   long diff_usec;
482   float diff_sec;
483 
484   gettimeofday(&now, NULL);
485   if (never_called) {
486     firsttime = now;
487     never_called = 0;
488   }
489   diff_usec = 1000000 * (now.tv_sec -firsttime.tv_sec) + (now.tv_usec - firsttime.tv_usec);
490   diff_sec = diff_usec / 1000000.0;
491 
492   snprintf1(buf, size, "%f ", diff_sec);
493 }
494 
495 
496 
497 /* Dan Bernsteins djb2, hashing n strings in one go */
498 unsigned long
hash_multiple(int n,...)499 hash_multiple(int n, ...)
500 {
501   unsigned long hash = 5381;
502   int i, c;
503   char *str;
504 
505   va_list ap;
506   va_start(ap, n);
507   for(i = 0; i < n; i++) {
508     str = va_arg(ap, char *);
509     assert(str != NULL);
510     while ((c = (unsigned char) *str++))
511       hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
512   }
513   va_end(ap);
514   return hash;
515 }
516 
517 
killed_by(int status)518 int killed_by(int status) {
519 #ifdef WTERMSIG
520   if (WIFSIGNALED(status))
521     return WTERMSIG(status);
522 #endif
523   return 0;
524 }
525 
526 
527 
528 /* get_new_slave_cwd(&cwd) tries to find the rlwrapped command's current working directory. If this
529    differs from cwd, free(*cwd) and set *cwd to (a copy of) the new working directory. Return value: 0, or 1
530    if rlwrap needs to do a chdir(cwd) to again have the same working dir as the rlwrapped command.
531 */
532 static int
get_new_slave_cwd(char ** cwd)533 get_new_slave_cwd(char **cwd)
534 {
535   char *possibly_new_cwd = NULL;
536   int return_value = 0;
537 
538 
539 #if defined(HAVE_PROC_PID_CWD) /* Linux, Solaris, and FreeBSD with the proc filesystem */
540 
541   static char *proc_pid_cwd = NULL;
542   char readlink_buffer[MAXPATHLEN+1];
543 
544   if (!proc_pid_cwd)
545     proc_pid_cwd = add3strings(PROC_MOUNTPOINT, "/", add2strings(as_string(command_pid), "/cwd"));
546 
547 # ifdef HAVE_READLINK
548   if  (readlink(proc_pid_cwd, readlink_buffer, MAXPATHLEN) > 0)
549     possibly_new_cwd = mysavestring(readlink_buffer);
550 # else
551   /* readlink unavailable, use /proc/nnn/cwd ... */
552   possibly_new_cwd = mysavestring(proc_pid_cwd);
553   return_value = 1; /* always do a chdir(): the symlink /proc/nnn/cwd may point somewhere else now... */
554 #  endif /* HAVE_READLINK */
555 
556 #elif HAVE_DECL_PROC_PIDVNODEPATHINFO /* OS X */
557 
558   struct proc_vnodepathinfo vpi;
559 
560   if (proc_pidinfo(command_pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)) <= 0)
561     DPRINTF2(DEBUG_COMPLETION, "proc_pidinfo(%d, .. failed: %s", command_pid, strerror(errno));
562   possibly_new_cwd = mysavestring(vpi.pvi_cdir.vip_path);
563 
564 #elif HAVE_FREEBSD_LIBPROCSTAT /* FreeBSD without the proc filesystem */
565 
566   unsigned int count = 0;
567   struct procstat *procstat = procstat_open_sysctl();
568   struct kinfo_proc *kip = procstat_getprocs(procstat, KERN_PROC_PID, command_pid, &count);
569   struct filestat_list *head;
570   struct filestat *fst;
571 
572   if (count == 1) {
573     head = procstat_getfiles(procstat, kip, 0);
574 
575     STAILQ_FOREACH(fst, head, next)
576       if (fst->fs_uflags & PS_FST_UFLAG_CDIR) {
577         possibly_new_cwd = mysavestring(fst->fs_path);
578         break;
579       }
580     procstat_freefiles(procstat, head);
581     procstat_freeprocs(procstat, kip);
582     procstat_close(procstat);
583   }
584 
585 #else
586   /* no HAVE_PROC_PID_CWD, HAVE_DECL_PROC_PIDVNODEPATHINFO or HAVE_FREEBSD_LIBPROCSTAT: do nothing */
587 #endif
588 
589   if (possibly_new_cwd && strcmp(*cwd, possibly_new_cwd)) {
590     return_value = 1;
591     free(*cwd);
592     *cwd = mysavestring(possibly_new_cwd);
593   }
594   free(possibly_new_cwd);
595   return return_value;
596 }
597 
598 
599 
600 /* change_working_directory() tries to change rlwrap's working directory to the rlwrapped command's current working directory   */
601 void
change_working_directory()602 change_working_directory()
603 {
604   static char *slaves_working_directory = NULL;
605   if (!slaves_working_directory)
606     slaves_working_directory = mysavestring(".");
607   if(command_pid > 0 && get_new_slave_cwd(&slaves_working_directory)) {
608     if (chdir(slaves_working_directory)) {
609       DPRINTF2(DEBUG_COMPLETION, "chdir(%s) failed: %s", slaves_working_directory, strerror(errno));
610     } else {
611       DPRINTF1(DEBUG_COMPLETION, "chdir(%s): success", slaves_working_directory);
612     }
613   }
614 }
615 
616 
617 
618 
619 #undef isset
620 #define isset(flag) ((flag) ? "set" : "unset")
621 
622 /* print info about terminal settings */
log_terminal_settings(struct termios * terminal_settings)623 void log_terminal_settings(struct termios *terminal_settings) {
624   if (!terminal_settings)
625     return;
626   DPRINTF3(DEBUG_TERMIO, "terminal settings: clflag.ISIG: %s, cc_c[VINTR]=%d, cc_c[VEOF]=%d",
627            isset(terminal_settings->c_lflag | ISIG),
628            terminal_settings->c_cc[VINTR],
629            terminal_settings->c_cc[VEOF]);
630 }
631 
log_fd_info(int fd)632 void log_fd_info(int fd) {
633   struct termios terminal_settings;
634   if (isatty(fd)) {
635     if (tcgetattr(fd, &terminal_settings) < 0) {
636       DPRINTF1(DEBUG_TERMIO, "could not get terminal settings for fd %d", fd);
637     } else {
638       DPRINTF1(DEBUG_TERMIO, "terminal settings for fd %d:", fd);
639     }
640     log_terminal_settings(&terminal_settings);
641   }
642 }
643 
644 
645 /* some last-minute checks before we can start */
646 void
last_minute_checks()647 last_minute_checks()
648 {
649   /* flag unhealthy option combinations */
650   if (multiline_separator && filter_command)
651     myerror(WARNING|NOERRNO, "Filters don't work very well with multi-line rlwrap!");
652 }
653 
654 
655 /* sleep a little (for debugging cursor movement with the SHOWCURSOR macro) */
mymicrosleep(int msec)656 void mymicrosleep(int msec) {
657   int sec = msec / 1000;
658   struct timeval timeout;
659   msec -= (1000*sec);
660 
661   timeout.tv_sec = sec;
662   timeout.tv_usec =  1000 * msec;
663   select (0,NULL,NULL,NULL,&timeout);
664 }
665 
666 
667 
668 /* print info about option, considering whether we HAVE_GETOPT_LONG and whether GETOPT_GROKS_OPTIONAL_ARGS */
print_option(char shortopt,char * longopt,char * argument,int optional,char * comment)669 static void print_option(char shortopt, char *longopt, char*argument, int optional, char *comment) {
670   int long_opts, optional_args;
671   char *format;
672   char *maybe_optional = "";
673   char *longoptional = "";
674 
675 
676 #ifdef HAVE_GETOPT_LONG
677   long_opts = TRUE;
678 #else
679   long_opts = FALSE;
680 #endif
681 
682 #ifdef GETOPT_GROKS_OPTIONAL_ARGS
683   optional_args = TRUE;
684 #else
685   optional_args = FALSE;
686 #endif
687 
688   if (argument) {
689     maybe_optional = (optional_args && optional ? add3strings("[", argument,"]") :  add3strings("  <", argument,">"));
690     longoptional = (optional ? add3strings("[=", argument,"]") : add3strings("=<", argument, ">"));
691   }
692 
693   /* if we cannot use long options, use the long option as a reminder (no warnings) instead of "--no-warnings" */
694   if (!long_opts)
695     longopt = search_and_replace("-"," ", longopt, 0, NULL,NULL);
696   format = add2strings ("  -%c%-24.24s", (long_opts  ? " --%s%s" : "(%s)"));
697   fprintf(stderr, format, shortopt, maybe_optional, longopt, longoptional);
698   if (comment)
699     fprintf(stderr, " %s", comment);
700   fprintf(stderr, "\n");
701   /* don't free allocated strings: we'll exit() soon */
702 }
703 
704 static void
print_debug_flag(int flag,char * explanation)705 print_debug_flag(int flag, char *explanation) {
706   fprintf(stderr, "    %4d    %s\n", flag, explanation);
707 }
708 
709 void
usage(int status)710 usage(int status)
711 {
712   fprintf(stderr, "Usage: %s [options] command ...\n"
713           "\n"
714           "Options:\n", program_name);
715 
716   print_option('a', "always-readline", "password prompt", TRUE, NULL);
717   print_option('A', "ansi-colour-aware", NULL, FALSE, NULL);
718   print_option('b', "break-chars", "chars", FALSE, NULL);
719   print_option('c', "complete-filenames", NULL, FALSE, NULL);
720   print_option('C', "command-name", "name|N", FALSE, NULL);
721   print_option('D', "history-no-dupes", "0|1|2", FALSE, NULL);
722   print_option('e', "extra-char-after-completion", "char|''", FALSE, NULL);
723   print_option('f', "file", "completion list", FALSE,NULL);
724   print_option('g', "forget-matching", "regexp", FALSE,NULL);
725   print_option('h', "help", NULL, FALSE, NULL);
726   print_option('H', "history-filename", "file", FALSE, NULL);
727   print_option('i', "case-insensitive", NULL, FALSE, NULL);
728   print_option('I', "pass-sigint-as-sigterm", NULL, FALSE, NULL);
729   print_option('l', "logfile", "file", FALSE, NULL);
730   print_option('m', "multi-line", "newline substitute", TRUE, NULL);
731   print_option('M', "multi-line-ext", ".ext", FALSE, NULL);
732   print_option('n', "no-warnings", NULL, FALSE, NULL);
733   print_option('N', "no-children", NULL, FALSE, NULL);
734   print_option('o', "one-shot", NULL, FALSE, NULL);
735   print_option('O', "only-cook", "regexp", FALSE, NULL);
736   print_option('p', "prompt-colour", "colour", TRUE, NULL);
737   print_option('P', "pre-given","input", FALSE, NULL);
738   print_option('q', "quote-characters", "chars", FALSE, NULL);
739   print_option('r', "remember", NULL, FALSE, NULL);
740   print_option('R', "renice", NULL, FALSE, NULL);
741   print_option('s', "histsize", "N", FALSE,"(negative: readonly)");
742   print_option('S', "substitute-prompt", "prompt", FALSE, NULL);
743   print_option('t', "set-term-name", "name", FALSE, NULL);
744   print_option('U', "mirror-arguments", NULL, FALSE, NULL);
745   print_option('v', "version", NULL, FALSE, NULL);
746   print_option('w', "wait-before-prompt", "N", FALSE, "(msec, <0  : patient mode)");
747   print_option('W', "polling", NULL, FALSE, NULL);
748   print_option('z', "filter", "filter command", FALSE, "('rlwrap -z listing' writes a list of installed filters)");
749 
750 
751 #ifdef DEBUG
752   fprintf(stderr, "\n");
753   print_option('T', "test-terminal", NULL, FALSE, NULL);
754   print_option('d', "debug", "mask", TRUE, add3strings("(output sent to ", DEBUG_FILENAME,")"));
755   fprintf(stderr,
756           "             \n"
757           "The -d or --debug option *must* come first\n"
758           "The debugging mask is a bitmask obtained by adding:\n");
759 
760   print_debug_flag (DEBUG_TERMIO, "to debug termio,");
761   print_debug_flag (DEBUG_SIGNALS, "signal handling,");
762   print_debug_flag (DEBUG_READLINE, "readline,");
763 
764   print_debug_flag (DEBUG_MEMORY_MANAGEMENT, "memory management,");
765   print_debug_flag (DEBUG_FILTERING, "filtering,");
766   print_debug_flag (DEBUG_COMPLETION, "and completion.");
767   print_debug_flag (DEBUG_AD_HOC, "to see your own DEBUG_AD_HOC results");
768   print_debug_flag (DEBUG_WITH_TIMESTAMPS, "to add (relative) timestamps,");
769   print_debug_flag (FORCE_HOMEGROWN_REDISPLAY, "to force the use of my_homegrown_redisplay(),");
770   print_debug_flag (DEBUG_LONG_STRINGS, "to not limit the length of strings in debug log (sloooow!)");
771   print_debug_flag (DEBUG_RACES, "add random delays to expose race conditions.");
772   fprintf(stderr,  "    default debug mask = %d (debug termio, signals and readline handling)\n"
773                    "    use the shell construct $[ ] to calculate the mask, e.g. -d$[%d+%d+%d]\n",
774           DEBUG_DEFAULT, DEBUG_DEFAULT, DEBUG_WITH_TIMESTAMPS, DEBUG_RACES);
775 
776 #endif
777 
778   fprintf(stderr,
779           "\n"
780           "bug reports, suggestions, updates:\n"
781           "https://github.com/hanslub42/rlwrap\n");
782 
783   exit(status);
784 }
785 
786 
787 #ifdef DEBUG
788 #undef mymalloc
789 #endif
790 
791 /* malloc with simplistic error handling: just bail out when out of memory */
792 void *
mymalloc(size_t size)793 mymalloc(size_t size)
794 {
795   void *ptr;
796   ptr = malloc(size);
797   if (ptr == NULL) {
798     /* don't call myerror(), as this calls mymalloc() again */
799     #ifdef DUMP_CORE_ON_ERROR
800        KA_BOOM;
801     #endif
802     fprintf(stderr, "Out of memory: tried in vain to allocate %d bytes\n", (int) size);
803     exit(EXIT_FAILURE);
804   }
805   return ptr;
806 }
807 
808 
809 /* free() with variable number of arguments. To show where the argumets end, the last argument should be special,
810    (and never a legitimate pointer) but we cannot use NULL (as the to-be-freed pointers may legitimately be NULL)
811    We now use FMEND (#defined as ((void *) -1) in rlwrap.h, but @@@ is this fool-proof?
812  */
813 
814 void
free_multiple(void * ptr,...)815 free_multiple(void *ptr, ...)
816 {
817   void *p;
818   va_list ap;
819   free(ptr);
820   va_start(ap, ptr);
821   while((p = va_arg(ap, void *)) != FMEND) {
822     free(p);
823   }
824   va_end(ap);
825 }
826 
827 
828 
829 
mysetsid()830 void mysetsid() {
831 # ifdef HAVE_SETSID /* c'mon, this is POSIX! */
832   pid_t ret = setsid();
833 
834   DPRINTF2(DEBUG_TERMIO, "setsid() returned %d %s", (int)ret,
835            ERRMSG(ret < 0));
836 # endif
837 }
838 
839 
840 
841 /* mirror_args(): look up command's command line and copy it to our own
842    important for commands that re-write their command lines e.g. to hide
843    passwords.
844 */
845 
846 
847 
848 static char ** rlwrap_command_argv; /* The slice of rlwrap's argv after all rlwrap options */
849 static char *argv_buffer;
850 static int argv_len;
851 static char *stored_cmdline_filename;
852 
853 
854 
855 
mirror_args_init(char ** argv)856 void mirror_args_init(char**argv) {
857 #ifdef ENABLE_MIRROR_ARGS
858   int i;
859   rlwrap_command_argv = argv;
860   stored_cmdline_filename = mymalloc(MAXPATHLEN);
861   *stored_cmdline_filename = '\0';
862 
863   for (i = 0; argv[i]; i++) {
864     argv_len += strlen(argv[i]) + 1;
865   }
866   argv_buffer = mymalloc(argv_len * sizeof(char) + 1);
867 #else
868   stored_cmdline_filename = NULL;
869   myerror(WARNING|NOERRNO, "On this system, the -U (--mirror-arguments) option doesn't work");
870 #endif
871 }
872 
873 /* C standard: "The parameters argc and argv and the strings pointed to by the argv
874                 array shall be modifiable by the program, and retain their last-stored
875                 values between program startup and program termination.
876 
877    This doesn't guarantee that those changed values will be visible to e.g. the ps (1) command
878 */
879 
880 
881 
882 
mirror_args(pid_t command_pid)883 void mirror_args(pid_t command_pid) {
884   int cmdline_fd;
885   long cmdline_length;
886   static int been_warned = 0;
887 
888   if (!stored_cmdline_filename || !command_pid) /* uninitialized, unborn or dead command */
889     return;
890   if (!*stored_cmdline_filename)
891      snprintf2(stored_cmdline_filename, MAXPATHLEN , "%s/%d/cmdline", PROC_MOUNTPOINT, command_pid);
892   if((cmdline_fd = open(stored_cmdline_filename, O_RDONLY)) < 1) {
893     stored_cmdline_filename = NULL;
894     if (been_warned++ == 0)
895       myerror(WARNING|USE_ERRNO, "cannot mirror command's command line, as %s is unreadable", stored_cmdline_filename);
896     return;
897   }
898   cmdline_length = read(cmdline_fd, argv_buffer,argv_len);
899   /*  argv_buffer[cmdline_length] = '\0'; */
900   DPRINTF2(DEBUG_TERMIO,"read %d bytes from %s", (int) cmdline_length, stored_cmdline_filename);
901 
902   if (memcmp(*rlwrap_command_argv, argv_buffer, cmdline_length)) {
903     char *rlwrap_argstr = mem2str(*rlwrap_command_argv, cmdline_length);
904     char *command_argstr = mem2str(argv_buffer, cmdline_length);
905     DPRINTF2(DEBUG_TERMIO, "discrepancy: rlwarp_args: %s, command_args %s", rlwrap_argstr, command_argstr);
906     free(rlwrap_argstr);
907     free(command_argstr);
908 
909     memcpy(*rlwrap_command_argv, argv_buffer, cmdline_length);
910   }
911 }
912 
913