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