mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 20:28:28 +08:00
import of readlilne 5.1
This commit is contained in:
37
readline/examples/rlfe/ChangeLog
Normal file
37
readline/examples/rlfe/ChangeLog
Normal file
@ -0,0 +1,37 @@
|
||||
2004-11-04 Per Bothner <per@bothner.com>
|
||||
|
||||
* pty.c: Import from screen-4.0.2.
|
||||
* configure.in, Makefile.in, config.h.in: Set up autoconf handling,
|
||||
copying a bunk of stuff over from screen.
|
||||
* rlfe.c: Use OpenPTY from pty.c instead of get_master_pty.
|
||||
|
||||
2004-11-03 Per Bothner <per@bothner.com>
|
||||
|
||||
* rlfe.c: Get input emphasis (boldening) more robust.
|
||||
|
||||
* rlfe.c: Various cleanups on comments and names.
|
||||
|
||||
2003-11-07 Wolfgang Taeuber <wolfgang_taeuber@agilent.com>
|
||||
|
||||
* Specify a history file and the size of the history file with command
|
||||
* line options; use EDITOR/VISUAL to set vi/emacs preference.
|
||||
|
||||
1999-09-03 Chet Ramey <chet@nike.ins.cwru.edu>
|
||||
|
||||
* fep.c: Memmove is not universally available. This patch assumes
|
||||
that an autoconf test has been performed, and that memcpy is
|
||||
available without checking.
|
||||
|
||||
* fep.c: VDISCARD is not universally available, even when termios is.
|
||||
|
||||
* fep.c: If a system doesn't have TIOCSCTTY, the first `open'
|
||||
performed after setsid allocates a controlling terminal. The
|
||||
original code would leave the child process running on the slave pty
|
||||
without a controlling tty if TIOCSCTTY was not available.
|
||||
|
||||
* fep.c: Most versions of SVR4, including solaris, don't allow
|
||||
terminal ioctl calls on the master side of the pty.
|
||||
|
||||
1999-08-28 Per Bothner <per@bothner.com>
|
||||
|
||||
* fep.c: Initial release.
|
176
readline/examples/rlfe/Makefile.in
Normal file
176
readline/examples/rlfe/Makefile.in
Normal file
@ -0,0 +1,176 @@
|
||||
#
|
||||
# Makefile template for rlfe
|
||||
#
|
||||
# See machine dependant config.h for more configuration options.
|
||||
#
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
DESTDIR =
|
||||
|
||||
# Where to install screen.
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
# don't forget to change mandir and infodir in doc/Makefile.
|
||||
bindir = $(exec_prefix)/bin
|
||||
|
||||
VERSION = @VERSION@
|
||||
SCREEN = screen-$(VERSION)
|
||||
|
||||
CC = @CC@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
#LDFLAGS = -L$(READLINE_DIR)
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = -lreadline -lhistory -lncurses
|
||||
|
||||
CPP=@CPP@
|
||||
CPP_DEPEND=$(CC) -MM
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
AWK = @AWK@
|
||||
|
||||
OPTIONS=
|
||||
#OPTIONS= -DDEBUG
|
||||
|
||||
SHELL=/bin/sh
|
||||
|
||||
CFILES= rlfe.c pty.c
|
||||
HFILES= extern.h os.h screen.h
|
||||
EXTRA_DIST=configure.in configure Makefile.in config.h.in ChangeLog README
|
||||
OFILES= rlfe.o pty.o
|
||||
|
||||
all: rlfe
|
||||
|
||||
rlfe: $(OFILES)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OFILES) $(LIBS)
|
||||
|
||||
rlfe-$(VERSION).tar.gz:
|
||||
tar czf $@ $(CFILES) $(HFILES) $(EXTRA_DIST)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c -I. -I$(srcdir) $(M_CFLAGS) $(DEFS) $(OPTIONS) $(CFLAGS) $<
|
||||
|
||||
install_bin: .version screen
|
||||
-if [ -f $(DESTDIR)$(bindir)/$(SCREEN) ] && [ ! -f $(DESTDIR)$(bindir)/$(SCREEN).old ]; \
|
||||
then mv $(DESTDIR)$(bindir)/$(SCREEN) $(DESTDIR)$(bindir)/$(SCREEN).old; fi
|
||||
$(INSTALL_PROGRAM) screen $(DESTDIR)$(bindir)/$(SCREEN)
|
||||
-chown root $(DESTDIR)$(bindir)/$(SCREEN) && chmod 4755 $(DESTDIR)$(bindir)/$(SCREEN)
|
||||
# This doesn't work if $(bindir)/screen is a symlink
|
||||
-if [ -f $(DESTDIR)$(bindir)/screen ] && [ ! -f $(DESTDIR)$(bindir)/screen.old ]; then mv $(DESTDIR)$(bindir)/screen $(DESTDIR)$(bindir)/screen.old; fi
|
||||
rm -f $(DESTDIR)$(bindir)/screen
|
||||
(cd $(DESTDIR)$(bindir) && ln -sf $(SCREEN) screen)
|
||||
cp $(srcdir)/utf8encodings/?? $(DESTDIR)$(SCREENENCODINGS)
|
||||
|
||||
|
||||
uninstall: .version
|
||||
rm -f $(DESTDIR)$(bindir)/$(SCREEN)
|
||||
rm -f $(DESTDIR)$(bindir)/screen
|
||||
-mv $(DESTDIR)$(bindir)/screen.old $(DESTDIR)$(bindir)/screen
|
||||
rm -f $(DESTDIR)$(ETCSCREENRC)
|
||||
cd doc; $(MAKE) uninstall
|
||||
|
||||
shadow:
|
||||
mkdir shadow;
|
||||
cd shadow; ln -s ../*.[ch] ../*.in ../*.sh ../configure ../doc ../terminfo ../etc .
|
||||
rm -f shadow/term.h shadow/tty.c shadow/comm.h shadow/osdef.h
|
||||
echo "install all Makefiles and config:" > shadow/Makefile
|
||||
echo " rm -f config.cache" >> shadow/Makefile
|
||||
echo " sh ./configure" >> shadow/Makefile
|
||||
|
||||
term.h: term.c term.sh
|
||||
AWK=$(AWK) srcdir=$(srcdir) sh $(srcdir)/term.sh
|
||||
|
||||
kmapdef.c: term.h
|
||||
|
||||
tty.c: tty.sh
|
||||
sh $(srcdir)/tty.sh tty.c
|
||||
|
||||
mostlyclean:
|
||||
rm -f $(OFILES) rlfe *.o
|
||||
|
||||
clean celan: mostlyclean
|
||||
rm -f tty.c term.h comm.h osdef.h kmapdef.c core
|
||||
|
||||
# Delete all files from the current directory that are created by
|
||||
# configuring or building the program.
|
||||
# building of term.h/comm.h requires awk. Keep it in the distribution
|
||||
# we keep config.h, as this file knows where 'make dist' finds the ETCSCREENRC.
|
||||
#distclean: mostlyclean
|
||||
# rm -f $(SCREEN).tar $(SCREEN).tar.gz
|
||||
# rm -f config.status Makefile
|
||||
# rm -f osdef.h doc/Makefile
|
||||
|
||||
maintainer-clean:
|
||||
@echo "This command is not even intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
|
||||
# Delete everything from the current directory that can be
|
||||
# reconstructed with this Makefile.
|
||||
realclean: .version mostlyclean
|
||||
rm -f $(SCREEN).tar $(SCREEN).tar.gz
|
||||
rm -f config.status Makefile doc/Makefile
|
||||
rm -f tty.c term.h comm.h osdef.h kmapdef.c
|
||||
rm -f config.h
|
||||
echo "install all Makefiles and config:" > Makefile
|
||||
echo " sh ./configure" >> Makefile
|
||||
|
||||
tags TAGS: $(CFILES)
|
||||
-ctags *.sh $(CFILES) *.h
|
||||
-ctags -e *.sh $(CFILES) *.h
|
||||
|
||||
dist: .version $(SCREEN).tar.gz
|
||||
|
||||
|
||||
# Perform self-tests (if any).
|
||||
check:
|
||||
|
||||
config:
|
||||
rm -f config.cache
|
||||
sh ./configure
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
.version:
|
||||
@rev=`sed < $(srcdir)/patchlevel.h -n -e '/#define REV/s/#define REV *//p'`; \
|
||||
vers=`sed < $(srcdir)/patchlevel.h -n -e '/#define VERS/s/#define VERS *//p'`; \
|
||||
pat=`sed < $(srcdir)/patchlevel.h -n -e '/#define PATCHLEVEL/s/#define PATCHLEVEL *//p'`; \
|
||||
if [ "$${rev}.$${vers}.$${pat}" != "$(VERSION)" ]; then \
|
||||
echo "This distribution is screen-$${rev}.$${vers}.$${pat}, but"; \
|
||||
echo "the Makefile is from $(VERSION). Please update!"; exit 1; fi
|
||||
|
||||
###############################################################################
|
||||
|
||||
mdepend: $(CFILES) term.h
|
||||
@rm -f DEPEND ; \
|
||||
for i in ${CFILES} ; do \
|
||||
echo "$$i" ; \
|
||||
echo `echo "$$i" | sed -e 's/.c$$/.o/'`": $$i" `\
|
||||
cc -E $$i |\
|
||||
grep '^# .*"\./.*\.h"' |\
|
||||
(sort -t'"' -u -k 2,2 2>/dev/null || sort -t'"' -u +1 -2) |\
|
||||
sed -e 's/.*"\.\/\(.*\)".*/\1/'\
|
||||
` >> DEPEND ; \
|
||||
done
|
||||
|
||||
depend: depend.in
|
||||
./config.status || ./configure
|
||||
|
||||
depend.in: $(CFILES) term.h
|
||||
cp Makefile.in Makefile.in~
|
||||
sed -e '/\#\#\# Dependencies/q' < Makefile.in > tmp_make
|
||||
for i in $(CFILES); do echo $$i; $(CPP_DEPEND) $$i >> tmp_make; done
|
||||
mv tmp_make Makefile.in
|
||||
|
||||
###############################################################################
|
||||
|
||||
### Dependencies:
|
||||
pty.o: pty.c config.h
|
78
readline/examples/rlfe/README
Normal file
78
readline/examples/rlfe/README
Normal file
@ -0,0 +1,78 @@
|
||||
rlfe (ReadLine Front-End) is a "universal wrapper" around readline.
|
||||
You specify an interactive program to run (typically a shell), and
|
||||
readline is used to edit input lines.
|
||||
|
||||
There are other such front-ends; what distinguishes this one is that
|
||||
it monitors the state of the inferior pty, and if the inferior program
|
||||
switches its terminal to raw mode, then rlfe passes your characters
|
||||
through directly. This basically means you can run your entire
|
||||
session (including bash and terminal-mode emacs) under rlfe.
|
||||
|
||||
FEATURES
|
||||
|
||||
* Can use all readline commands (and history) in commands that
|
||||
read input lines in "canonical mode" - even 'cat'!
|
||||
|
||||
* Automatically switches between "readline-editing mode" and "raw mode"
|
||||
depending on the terminal mode. If the inferior program invokes
|
||||
readline itself, it will do its own line editing. (The inferior
|
||||
readline will not know about rlfe, and it will have its own history.)
|
||||
You can even run programs like 'emavs -nw' and 'vi' under rlfe.
|
||||
The goal is you could leave rlfe always on without even knowing
|
||||
about it. (We're not quite there, but it works tolerably well.)
|
||||
|
||||
* The input line (after any prompt) is changed to bold-face.
|
||||
|
||||
INSTALL
|
||||
|
||||
The usual: ./configure && make && make install
|
||||
|
||||
Note so far rlfe has only been tested on GNU Linux (Fedora Core 2)
|
||||
and Mac OS X (10.3).
|
||||
|
||||
This assumes readline header files and libraries are in the default
|
||||
places. If not, you can create a link named readline pointing to the
|
||||
readline sources. To link with libreadline.a and libhistory.a
|
||||
you can copy or link them, or add LDFLAGS='-/path/to/readline' to
|
||||
the make command-line.
|
||||
|
||||
USAGE
|
||||
|
||||
Just run it. That by default runs bash. You can run some other
|
||||
command by giving it as command-line arguments.
|
||||
|
||||
There are a few tweaks: -h allows you to name the history file,
|
||||
and -s allows you to specify its size. It default to "emacs" mode,
|
||||
but if the the environment variable EDITOR is set to "vi" that
|
||||
mode is chosen.
|
||||
|
||||
ISSUES
|
||||
|
||||
* The mode switching depends on the terminal mode set by the inferior
|
||||
program. Thus ssh/telnet/screen-type programs will typically be in
|
||||
raw mode, so rlfe won't be much use, even if remote programs run in
|
||||
canonical mode. The work-around is to run rlfe on the remote end.
|
||||
|
||||
* Echo supression and prompt recognition are somewhat fragile.
|
||||
(A protocol so that the o/s tty code can reliably communicate its
|
||||
state to rlfe could solve this problem, and the previous one.)
|
||||
|
||||
* See the intro to rlfe.c for more notes.
|
||||
|
||||
* Assumes a VT100-compatible terminal, though that could be generalized
|
||||
if anybody cares.
|
||||
|
||||
* Requires ncurses.
|
||||
|
||||
* It would be useful to integrate rlfe's logic in a terminal emulator.
|
||||
That would make it easier to reposition the edit position with a mouse,
|
||||
integrate cut-and-paste with the system clipboard, and more robustly
|
||||
handle escape sequence and multi-byte characters more robustly.
|
||||
|
||||
AUTHOR
|
||||
|
||||
Per Bothner <per@bothner.com>
|
||||
|
||||
LICENSE
|
||||
|
||||
GPL.
|
375
readline/examples/rlfe/config.h.in
Normal file
375
readline/examples/rlfe/config.h.in
Normal file
@ -0,0 +1,375 @@
|
||||
/* Copyright 2004 Per Bothner <per@bothner.com>
|
||||
* Based on config.h from screen-4.0.2.
|
||||
* Copyright (c) 1993-2000
|
||||
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
|
||||
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
|
||||
* Copyright (c) 1987 Oliver Laumann
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
****************************************************************
|
||||
* $Id$ FAU
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* User Configuration Section
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* define PTYMODE if you do not like the default of 0622, which allows
|
||||
* public write to your pty.
|
||||
* define PTYGROUP to some numerical group-id if you do not want the
|
||||
* tty to be in "your" group.
|
||||
* Note, screen is unable to change mode or group of the pty if it
|
||||
* is not installed with sufficient privilege. (e.g. set-uid-root)
|
||||
* define PTYROFS if the /dev/pty devices are mounted on a read-only
|
||||
* filesystem so screen should not even attempt to set mode or group
|
||||
* even if running as root (e.g. on TiVo).
|
||||
*/
|
||||
#undef PTYMODE
|
||||
#undef PTYGROUP
|
||||
#undef PTYROFS
|
||||
|
||||
/*
|
||||
* If screen is NOT installed set-uid root, screen can provide tty
|
||||
* security by exclusively locking the ptys. While this keeps other
|
||||
* users from opening your ptys, it also keeps your own subprocesses
|
||||
* from being able to open /dev/tty. Define LOCKPTY to add this
|
||||
* exclusive locking.
|
||||
*/
|
||||
#undef LOCKPTY
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* End of User Configuration Section
|
||||
*
|
||||
* Rest of this file is modified by 'configure'
|
||||
* Change at your own risk!
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some defines to identify special unix variants
|
||||
*/
|
||||
#ifndef SVR4
|
||||
#undef SVR4
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
#undef _POSIX_SOURCE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define POSIX if your system supports IEEE Std 1003.1-1988 (POSIX).
|
||||
*/
|
||||
#undef POSIX
|
||||
|
||||
/*
|
||||
* Define TERMIO if you have struct termio instead of struct sgttyb.
|
||||
* This is usually the case for SVID systems, where BSD uses sgttyb.
|
||||
* POSIX systems should define this anyway, even though they use
|
||||
* struct termios.
|
||||
*/
|
||||
#undef TERMIO
|
||||
|
||||
/*
|
||||
* Define CYTERMIO if you have cyrillic termio modes.
|
||||
*/
|
||||
#undef CYTERMIO
|
||||
|
||||
/*
|
||||
* Define TERMINFO if your machine emulates the termcap routines
|
||||
* with the terminfo database.
|
||||
* Thus the .screenrc file is parsed for
|
||||
* the command 'terminfo' and not 'termcap'.
|
||||
*/
|
||||
#undef TERMINFO
|
||||
|
||||
/*
|
||||
* If your library does not define ospeed, define this.
|
||||
*/
|
||||
#undef NEED_OSPEED
|
||||
|
||||
/*
|
||||
* Define SYSV if your machine is SYSV complient (Sys V, HPUX, A/UX)
|
||||
*/
|
||||
#ifndef SYSV
|
||||
#undef SYSV
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define SIGVOID if your signal handlers return void. On older
|
||||
* systems, signal returns int, but on newer ones, it returns void.
|
||||
*/
|
||||
#undef SIGVOID
|
||||
|
||||
/*
|
||||
* Define USESIGSET if you have sigset for BSD 4.1 reliable signals.
|
||||
*/
|
||||
#undef USESIGSET
|
||||
|
||||
/*
|
||||
* Define SYSVSIGS if signal handlers must be reinstalled after
|
||||
* they have been called.
|
||||
*/
|
||||
#undef SYSVSIGS
|
||||
|
||||
/*
|
||||
* Define BSDWAIT if your system defines a 'union wait' in <sys/wait.h>
|
||||
*
|
||||
* Only allow BSDWAIT i.e. wait3 on nonposix systems, since
|
||||
* posix implies wait(3) and waitpid(3). vdlinden@fwi.uva.nl
|
||||
*
|
||||
*/
|
||||
#ifndef POSIX
|
||||
#undef BSDWAIT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On RISCOS we prefer wait2() over wait3(). rouilj@sni-usa.com
|
||||
*/
|
||||
#ifdef BSDWAIT
|
||||
#undef USE_WAIT2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define if you have the utempter utmp helper program
|
||||
*/
|
||||
#undef HAVE_UTEMPTER
|
||||
|
||||
/*
|
||||
* If ttyslot() breaks getlogin() by returning indexes to utmp entries
|
||||
* of type DEAD_PROCESS, then our getlogin() replacement should be
|
||||
* selected by defining BUGGYGETLOGIN.
|
||||
*/
|
||||
#undef BUGGYGETLOGIN
|
||||
|
||||
/*
|
||||
* If your system has the calls setreuid() and setregid(),
|
||||
* define HAVE_SETREUID. Otherwise screen will use a forked process to
|
||||
* safely create output files without retaining any special privileges.
|
||||
*/
|
||||
#undef HAVE_SETREUID
|
||||
|
||||
/*
|
||||
* If your system supports BSD4.4's seteuid() and setegid(), define
|
||||
* HAVE_SETEUID.
|
||||
*/
|
||||
#undef HAVE_SETEUID
|
||||
|
||||
/*
|
||||
* If you want the "time" command to display the current load average
|
||||
* define LOADAV. Maybe you must install screen with the needed
|
||||
* privileges to read /dev/kmem.
|
||||
* Note that NLIST_ stuff is only checked, when getloadavg() is not available.
|
||||
*/
|
||||
#undef LOADAV
|
||||
|
||||
#undef LOADAV_NUM
|
||||
#undef LOADAV_TYPE
|
||||
#undef LOADAV_SCALE
|
||||
#undef LOADAV_GETLOADAVG
|
||||
#undef LOADAV_UNIX
|
||||
#undef LOADAV_AVENRUN
|
||||
#undef LOADAV_USE_NLIST64
|
||||
|
||||
#undef NLIST_DECLARED
|
||||
#undef NLIST_STRUCT
|
||||
#undef NLIST_NAME_UNION
|
||||
|
||||
/*
|
||||
* If your system has the new format /etc/ttys (like 4.3 BSD) and the
|
||||
* getttyent(3) library functions, define GETTTYENT.
|
||||
*/
|
||||
#undef GETTTYENT
|
||||
|
||||
/*
|
||||
* Define USEBCOPY if the bcopy/memcpy from your system's C library
|
||||
* supports the overlapping of source and destination blocks. When
|
||||
* undefined, screen uses its own (probably slower) version of bcopy().
|
||||
*
|
||||
* SYSV machines may have a working memcpy() -- Oh, this is
|
||||
* quite unlikely. Tell me if you see one.
|
||||
* "But then, memmove() should work, if at all available" he thought...
|
||||
* Boing, never say "works everywhere" unless you checked SCO UNIX.
|
||||
* Their memove fails the test in the configure script. Sigh. (Juergen)
|
||||
*/
|
||||
#undef USEBCOPY
|
||||
#undef USEMEMCPY
|
||||
#undef USEMEMMOVE
|
||||
|
||||
/*
|
||||
* If your system has vsprintf() and requires the use of the macros in
|
||||
* "varargs.h" to use functions with variable arguments,
|
||||
* define USEVARARGS.
|
||||
*/
|
||||
#undef USEVARARGS
|
||||
|
||||
/*
|
||||
* If your system has strerror() define this.
|
||||
*/
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/*
|
||||
* If the select return value doesn't treat a descriptor that is
|
||||
* usable for reading and writing as two hits, define SELECT_BROKEN.
|
||||
*/
|
||||
#undef SELECT_BROKEN
|
||||
|
||||
/*
|
||||
* Define this if your system supports named pipes.
|
||||
*/
|
||||
#undef NAMEDPIPE
|
||||
|
||||
/*
|
||||
* Define this if your system exits select() immediatly if a pipe is
|
||||
* opened read-only and no writer has opened it.
|
||||
*/
|
||||
#undef BROKEN_PIPE
|
||||
|
||||
/*
|
||||
* Define this if the unix-domain socket implementation doesn't
|
||||
* create a socket in the filesystem.
|
||||
*/
|
||||
#undef SOCK_NOT_IN_FS
|
||||
|
||||
/*
|
||||
* If your system has setenv() and unsetenv() define USESETENV
|
||||
*/
|
||||
#undef USESETENV
|
||||
|
||||
/*
|
||||
* If your system does not come with a setenv()/putenv()/getenv()
|
||||
* functions, you may bring in our own code by defining NEEDPUTENV.
|
||||
*/
|
||||
#undef NEEDPUTENV
|
||||
|
||||
/*
|
||||
* If the passwords are stored in a shadow file and you want the
|
||||
* builtin lock to work properly, define SHADOWPW.
|
||||
*/
|
||||
#undef SHADOWPW
|
||||
|
||||
/*
|
||||
* If you are on a SYS V machine that restricts filename length to 14
|
||||
* characters, you may need to enforce that by setting NAME_MAX to 14
|
||||
*/
|
||||
#undef NAME_MAX /* KEEP_UNDEF_HERE override system value */
|
||||
#undef NAME_MAX
|
||||
|
||||
/*
|
||||
* define HAVE_RENAME if your system has a rename() function
|
||||
*/
|
||||
#undef HAVE_RENAME
|
||||
|
||||
/*
|
||||
* define HAVE__EXIT if your system has the _exit() call.
|
||||
*/
|
||||
#undef HAVE__EXIT
|
||||
|
||||
/*
|
||||
* define HAVE_LSTAT if your system has symlinks and the lstat() call.
|
||||
*/
|
||||
#undef HAVE_LSTAT
|
||||
|
||||
/*
|
||||
* define HAVE_UTIMES if your system has the utimes() call.
|
||||
*/
|
||||
#undef HAVE_UTIMES
|
||||
|
||||
/*
|
||||
* define HAVE_FCHOWN if your system has the fchown() call.
|
||||
*/
|
||||
#undef HAVE_FCHOWN
|
||||
|
||||
/*
|
||||
* define HAVE_FCHMOD if your system has the fchmod() call.
|
||||
*/
|
||||
#undef HAVE_FCHMOD
|
||||
|
||||
/*
|
||||
* define HAVE_VSNPRINTF if your system has vsnprintf() (GNU lib).
|
||||
*/
|
||||
#undef HAVE_VSNPRINTF
|
||||
|
||||
/*
|
||||
* define HAVE_GETCWD if your system has the getcwd() call.
|
||||
*/
|
||||
#undef HAVE_GETCWD
|
||||
|
||||
/*
|
||||
* define HAVE_SETLOCALE if your system has the setlocale() call.
|
||||
*/
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/*
|
||||
* define HAVE_STRFTIME if your system has the strftime() call.
|
||||
*/
|
||||
#undef HAVE_STRFTIME
|
||||
|
||||
/*
|
||||
* define HAVE_NL_LANGINFO if your system has the nl_langinfo() call
|
||||
* and <langinfo.h> defines CODESET.
|
||||
*/
|
||||
#undef HAVE_NL_LANGINFO
|
||||
|
||||
/*
|
||||
* Newer versions of Solaris include fdwalk, which can greatly improve
|
||||
* the startup time of screen; otherwise screen spends a lot of time
|
||||
* closing file descriptors.
|
||||
*/
|
||||
#undef HAVE_FDWALK
|
||||
|
||||
/*
|
||||
* define HAVE_DEV_PTC if you have a /dev/ptc character special
|
||||
* device.
|
||||
*/
|
||||
#undef HAVE_DEV_PTC
|
||||
|
||||
/*
|
||||
* define HAVE_SVR4_PTYS if you have a /dev/ptmx character special
|
||||
* device and support the ptsname(), grantpt(), unlockpt() functions.
|
||||
*/
|
||||
#undef HAVE_SVR4_PTYS
|
||||
|
||||
/*
|
||||
* define HAVE_GETPT if you have the getpt() function.
|
||||
*/
|
||||
#undef HAVE_GETPT
|
||||
|
||||
/*
|
||||
* define HAVE_OPENPTY if your system has the openpty() call.
|
||||
*/
|
||||
#undef HAVE_OPENPTY
|
||||
|
||||
/*
|
||||
* define PTYRANGE0 and or PTYRANGE1 if you want to adapt screen
|
||||
* to unusual environments. E.g. For SunOs the defaults are "qpr" and
|
||||
* "0123456789abcdef". For SunOs 4.1.2
|
||||
* #define PTYRANGE0 "pqrstuvwxyzPQRST"
|
||||
* is recommended by Dan Jacobson.
|
||||
*/
|
||||
#undef PTYRANGE0
|
||||
#undef PTYRANGE1
|
||||
|
||||
#define USEVARARGS
|
5400
readline/examples/rlfe/configure
vendored
Executable file
5400
readline/examples/rlfe/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
438
readline/examples/rlfe/configure.in
Normal file
438
readline/examples/rlfe/configure.in
Normal file
@ -0,0 +1,438 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(rlfe.c)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
VERSION=0.4
|
||||
AC_SUBST(VERSION)
|
||||
|
||||
dnl
|
||||
dnl Define some useful macros
|
||||
dnl
|
||||
AC_DEFUN(AC_PROGRAM_SOURCE,
|
||||
[AC_REQUIRE([AC_PROG_CPP])AC_PROVIDE([$0])cat > conftest.c <<EOF
|
||||
#include "confdefs.h"
|
||||
[$1]
|
||||
_CUT_HERE_
|
||||
[$2]
|
||||
EOF
|
||||
eval "$ac_cpp conftest.c 2>&5 | sed -e '1,/_CUT_HERE_/d' -e 's/ //g' > conftest.out"
|
||||
. ./conftest.out
|
||||
rm -f conftest*
|
||||
])dnl
|
||||
dnl
|
||||
define(AC_NOTE,
|
||||
[echo "$1" 1>&AC_FD_MSG
|
||||
])dnl
|
||||
|
||||
old_CFLAGS="$CFLAGS"
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_ISC_POSIX
|
||||
|
||||
AC_TRY_RUN(main(){exit(0);},,[
|
||||
if test $CC != cc ; then
|
||||
AC_NOTE(Your $CC failed - restarting with CC=cc)
|
||||
AC_NOTE()
|
||||
CC=cc
|
||||
export CC
|
||||
exec $0 $configure_args
|
||||
fi
|
||||
])
|
||||
|
||||
AC_TRY_RUN(main(){exit(0);},,
|
||||
exec 5>&2
|
||||
eval $ac_link
|
||||
AC_NOTE(CC=$CC; CFLAGS=$CFLAGS; LIBS=$LIBS;)
|
||||
AC_NOTE($ac_compile)
|
||||
AC_MSG_ERROR(Can't run the compiler - sorry))
|
||||
|
||||
AC_TRY_RUN([
|
||||
main()
|
||||
{
|
||||
int __something_strange_();
|
||||
__something_strange_(0);
|
||||
}
|
||||
],AC_MSG_ERROR(Your compiler does not set the exit status - sorry))
|
||||
|
||||
AC_PROG_AWK
|
||||
|
||||
if test -f etc/toolcheck; then
|
||||
AC_CHECKING(for buggy tools)
|
||||
sh etc/toolcheck 1>&AC_FD_MSG
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl **** special unix variants ****
|
||||
dnl
|
||||
|
||||
AC_CHECKING(for System V)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>], [int x = SIGCHLD | FNDELAY;], , AC_DEFINE(SYSV))
|
||||
|
||||
AC_CHECKING(for Solaris 2.x)
|
||||
AC_EGREP_CPP(yes,
|
||||
[#if defined(SVR4) && defined(sun)
|
||||
yes
|
||||
#endif
|
||||
], LIBS="$LIBS -lsocket -lnsl -lkstat")
|
||||
|
||||
dnl
|
||||
dnl **** select() ****
|
||||
dnl
|
||||
|
||||
AC_CHECKING(select)
|
||||
AC_TRY_LINK(,[select(0, 0, 0, 0, 0);],,
|
||||
LIBS="$LIBS -lnet -lnsl"
|
||||
AC_CHECKING(select with $LIBS)
|
||||
AC_TRY_LINK(,[select(0, 0, 0, 0, 0);],,
|
||||
AC_MSG_ERROR(!!! no select - no screen))
|
||||
)
|
||||
dnl
|
||||
dnl **** check the select implementation ****
|
||||
dnl
|
||||
|
||||
AC_CHECKING(select return value)
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
char *nam = "/tmp/conftest$$";
|
||||
|
||||
#ifdef NAMEDPIPE
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK O_NDELAY
|
||||
#endif
|
||||
#ifndef S_IFIFO
|
||||
#define S_IFIFO 0010000
|
||||
#endif
|
||||
|
||||
|
||||
main()
|
||||
{
|
||||
#ifdef FD_SET
|
||||
fd_set f;
|
||||
#else
|
||||
int f;
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* From Andrew A. Chernov (ache@astral.msk.su):
|
||||
* opening RDWR fifo fails in BSD 4.4, but select return values are
|
||||
* right.
|
||||
*/
|
||||
exit(0);
|
||||
#endif
|
||||
(void)alarm(5);
|
||||
#ifdef POSIX
|
||||
if (mkfifo(nam, 0777))
|
||||
#else
|
||||
if (mknod(nam, S_IFIFO|0777, 0))
|
||||
#endif
|
||||
exit(1);
|
||||
close(0);
|
||||
if (open(nam, O_RDWR | O_NONBLOCK))
|
||||
exit(1);
|
||||
if (write(0, "TEST", 4) == -1)
|
||||
exit(1);
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
main()
|
||||
{
|
||||
int s1, s2, l;
|
||||
struct sockaddr_un a;
|
||||
#ifdef FD_SET
|
||||
fd_set f;
|
||||
#else
|
||||
int f;
|
||||
#endif
|
||||
|
||||
(void)alarm(5);
|
||||
if ((s1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
exit(1);
|
||||
a.sun_family = AF_UNIX;
|
||||
strcpy(a.sun_path, nam);
|
||||
(void) unlink(nam);
|
||||
if (bind(s1, (struct sockaddr *) &a, strlen(nam)+2) == -1)
|
||||
exit(1);
|
||||
if (listen(s1, 2))
|
||||
exit(1);
|
||||
if (fork() == 0)
|
||||
{
|
||||
if ((s2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
kill(getppid(), 3);
|
||||
(void)connect(s2, (struct sockaddr *)&a, strlen(nam) + 2);
|
||||
if (write(s2, "HELLO", 5) == -1)
|
||||
kill(getppid(), 3);
|
||||
exit(0);
|
||||
}
|
||||
l = sizeof(a);
|
||||
close(0);
|
||||
if (accept(s1, (struct sockaddr *)&a, &l))
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FD_SET
|
||||
FD_SET(0, &f);
|
||||
#else
|
||||
f = 1;
|
||||
#endif
|
||||
if (select(1, &f, 0, 0, 0) == -1)
|
||||
exit(1);
|
||||
if (select(1, &f, &f, 0, 0) != 2)
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
],AC_NOTE(- select is ok),
|
||||
AC_NOTE(- select can't count) AC_DEFINE(SELECT_BROKEN))
|
||||
|
||||
dnl
|
||||
dnl **** termcap or terminfo ****
|
||||
dnl
|
||||
AC_CHECKING(for tgetent)
|
||||
AC_TRY_LINK(,tgetent((char *)0, (char *)0);,,
|
||||
olibs="$LIBS"
|
||||
LIBS="-lcurses $olibs"
|
||||
AC_CHECKING(libcurses)
|
||||
AC_TRY_LINK(,[
|
||||
#ifdef __hpux
|
||||
__sorry_hpux_libcurses_is_totally_broken_in_10_10();
|
||||
#else
|
||||
tgetent((char *)0, (char *)0);
|
||||
#endif
|
||||
],,
|
||||
LIBS="-ltermcap $olibs"
|
||||
AC_CHECKING(libtermcap)
|
||||
AC_TRY_LINK(,tgetent((char *)0, (char *)0);,,
|
||||
LIBS="-ltermlib $olibs"
|
||||
AC_CHECKING(libtermlib)
|
||||
AC_TRY_LINK(,tgetent((char *)0, (char *)0);,,
|
||||
LIBS="-lncurses $olibs"
|
||||
AC_CHECKING(libncurses)
|
||||
AC_TRY_LINK(,tgetent((char *)0, (char *)0);,,
|
||||
AC_MSG_ERROR(!!! no tgetent - no screen))))))
|
||||
|
||||
AC_TRY_RUN([
|
||||
main()
|
||||
{
|
||||
exit(strcmp(tgoto("%p1%d", 0, 1), "1") ? 0 : 1);
|
||||
}], AC_NOTE(- you use the termcap database),
|
||||
AC_NOTE(- you use the terminfo database) AC_DEFINE(TERMINFO))
|
||||
AC_CHECKING(ospeed)
|
||||
AC_TRY_LINK(extern short ospeed;,ospeed=5;,,AC_DEFINE(NEED_OSPEED))
|
||||
|
||||
dnl
|
||||
dnl **** PTY specific things ****
|
||||
dnl
|
||||
AC_CHECKING(for /dev/ptc)
|
||||
if test -r /dev/ptc; then
|
||||
AC_DEFINE(HAVE_DEV_PTC)
|
||||
fi
|
||||
|
||||
AC_CHECKING(for SVR4 ptys)
|
||||
sysvr4ptys=
|
||||
if test -c /dev/ptmx ; then
|
||||
AC_TRY_LINK([],[ptsname(0);grantpt(0);unlockpt(0);],[AC_DEFINE(HAVE_SVR4_PTYS)
|
||||
sysvr4ptys=1])
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS(getpt)
|
||||
|
||||
dnl check for openpty()
|
||||
if test -z "$sysvr4ptys"; then
|
||||
AC_CHECK_FUNCS(openpty,,
|
||||
[AC_CHECK_LIB(util,openpty, [AC_DEFINE(HAVE_OPENPTY)] [LIBS="$LIBS -lutil"])])
|
||||
fi
|
||||
|
||||
AC_CHECKING(for ptyranges)
|
||||
if test -d /dev/ptym ; then
|
||||
pdir='/dev/ptym'
|
||||
else
|
||||
pdir='/dev'
|
||||
fi
|
||||
dnl SCO uses ptyp%d
|
||||
AC_EGREP_CPP(yes,
|
||||
[#ifdef M_UNIX
|
||||
yes;
|
||||
#endif
|
||||
], ptys=`echo /dev/ptyp??`, ptys=`echo $pdir/pty??`)
|
||||
dnl if test -c /dev/ptyp19; then
|
||||
dnl ptys=`echo /dev/ptyp??`
|
||||
dnl else
|
||||
dnl ptys=`echo $pdir/pty??`
|
||||
dnl fi
|
||||
if test "$ptys" != "$pdir/pty??" ; then
|
||||
p0=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'`
|
||||
p1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'`
|
||||
AC_DEFINE_UNQUOTED(PTYRANGE0,"$p0")
|
||||
AC_DEFINE_UNQUOTED(PTYRANGE1,"$p1")
|
||||
fi
|
||||
|
||||
dnl **** pty mode/group handling ****
|
||||
dnl
|
||||
dnl support provided by Luke Mewburn <lm@rmit.edu.au>, 931222
|
||||
AC_ARG_WITH(pty-mode, [ --with-pty-mode=mode default mode for ptys], [ ptymode="${withval}" ])
|
||||
AC_ARG_WITH(pty-group, [ --with-pty-group=group default group for ptys], [ ptygrp="${withval}" ])
|
||||
test -n "$ptymode" || ptymode=0620
|
||||
if test -n "$ptygrp" ; then
|
||||
AC_DEFINE_UNQUOTED(PTYMODE, $ptymode)
|
||||
AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp)
|
||||
else
|
||||
|
||||
AC_CHECKING(default tty permissions/group)
|
||||
rm -f conftest_grp
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
main()
|
||||
{
|
||||
struct stat sb;
|
||||
char *x,*ttyname();
|
||||
int om, m;
|
||||
FILE *fp;
|
||||
|
||||
if (!(x = ttyname(0))) exit(1);
|
||||
if (stat(x, &sb)) exit(1);
|
||||
om = sb.st_mode;
|
||||
if (om & 002) exit(0);
|
||||
m = system("mesg y");
|
||||
if (m == -1 || m == 127) exit(1);
|
||||
if (stat(x, &sb)) exit(1);
|
||||
m = sb.st_mode;
|
||||
if (chmod(x, om)) exit(1);
|
||||
if (m & 002) exit(0);
|
||||
if (sb.st_gid == getgid()) exit(1);
|
||||
if (!(fp=fopen("conftest_grp", "w")))
|
||||
exit(1);
|
||||
fprintf(fp, "%d\n", sb.st_gid);
|
||||
fclose(fp);
|
||||
exit(0);
|
||||
}
|
||||
],[
|
||||
if test -f conftest_grp; then
|
||||
ptygrp=`cat conftest_grp`
|
||||
AC_NOTE([- pty mode: $ptymode, group: $ptygrp])
|
||||
AC_DEFINE_UNQUOTED(PTYMODE, $ptymode)
|
||||
AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp)
|
||||
else
|
||||
AC_NOTE(- ptys are world accessable)
|
||||
fi
|
||||
],[
|
||||
WRITEPATH=''
|
||||
XTERMPATH=''
|
||||
AC_PATH_PROG(WRITEPATH, write)
|
||||
AC_PATH_PROG(XTERMPATH, xterm)
|
||||
found=
|
||||
if test -n "$WRITEPATH$XTERMPATH"; then
|
||||
findfollow=
|
||||
lsfollow=
|
||||
found=`find $WRITEPATH $XTERMPATH -follow -print 2>/dev/null`
|
||||
if test -n "$found"; then
|
||||
findfollow=-follow
|
||||
lsfollow=L
|
||||
fi
|
||||
if test -n "$XTERMPATH"; then
|
||||
ptygrpn=`ls -l$lsfollow $XTERMPATH | sed -n -e 1p | $AWK '{print $4}'`
|
||||
if test tty != "$ptygrpn"; then
|
||||
XTERMPATH=
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test -n "$WRITEPATH$XTERMPATH"; then
|
||||
found=`find $WRITEPATH $XTERMPATH $findfollow -perm -2000 -print`
|
||||
if test -n "$found"; then
|
||||
ptygrp=`ls -ln$lsfollow $found | sed -n -e 1p | $AWK '{print $4}'`
|
||||
AC_NOTE([- pty mode: $ptymode, group: $ptygrp])
|
||||
AC_DEFINE_UNQUOTED(PTYMODE, $ptymode)
|
||||
AC_DEFINE_UNQUOTED(PTYGROUP,$ptygrp)
|
||||
else
|
||||
AC_NOTE(- ptys are world accessable)
|
||||
fi
|
||||
else
|
||||
AC_NOTE(- can't determine - assume ptys are world accessable)
|
||||
fi
|
||||
]
|
||||
)
|
||||
rm -f conftest_grp
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl **** signal handling ****
|
||||
dnl
|
||||
if test -n "$posix" ; then
|
||||
|
||||
dnl POSIX has reliable signals with void return type.
|
||||
AC_NOTE(assuming posix signal definition)
|
||||
AC_DEFINE(SIGVOID)
|
||||
|
||||
else
|
||||
|
||||
AC_CHECKING(return type of signal handlers)
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#ifdef signal
|
||||
#undef signal
|
||||
#endif
|
||||
extern void (*signal ()) ();], [int i;], AC_DEFINE(SIGVOID))
|
||||
AC_CHECKING(sigset)
|
||||
AC_TRY_LINK([
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
],[
|
||||
#ifdef SIGVOID
|
||||
sigset(0, (void (*)())0);
|
||||
#else
|
||||
sigset(0, (int (*)())0);
|
||||
#endif
|
||||
], AC_DEFINE(USESIGSET))
|
||||
AC_CHECKING(signal implementation)
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef SIGCLD
|
||||
#define SIGCLD SIGCHLD
|
||||
#endif
|
||||
#ifdef USESIGSET
|
||||
#define signal sigset
|
||||
#endif
|
||||
|
||||
int got;
|
||||
|
||||
#ifdef SIGVOID
|
||||
void
|
||||
#endif
|
||||
hand()
|
||||
{
|
||||
got++;
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
/* on hpux we use sigvec to get bsd signals */
|
||||
#ifdef __hpux
|
||||
(void)signal(SIGCLD, hand);
|
||||
kill(getpid(), SIGCLD);
|
||||
kill(getpid(), SIGCLD);
|
||||
if (got < 2)
|
||||
exit(1);
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
],,AC_DEFINE(SYSVSIGS))
|
||||
|
||||
fi
|
||||
|
||||
AC_OUTPUT(Makefile)
|
33
readline/examples/rlfe/extern.h
Normal file
33
readline/examples/rlfe/extern.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright (c) 1993-2002
|
||||
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
|
||||
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
|
||||
* Copyright (c) 1987 Oliver Laumann
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
****************************************************************
|
||||
* $Id$ FAU
|
||||
*/
|
||||
|
||||
#if !defined(__GNUC__) || __GNUC__ < 2
|
||||
#undef __attribute__
|
||||
#define __attribute__(x)
|
||||
#endif
|
||||
|
||||
/* pty.c */
|
||||
extern int OpenPTY __P((char **));
|
||||
extern void InitPTY __P((int));
|
||||
|
530
readline/examples/rlfe/os.h
Normal file
530
readline/examples/rlfe/os.h
Normal file
@ -0,0 +1,530 @@
|
||||
/* Copyright (c) 1993-2002
|
||||
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
|
||||
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
|
||||
* Copyright (c) 1987 Oliver Laumann
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
****************************************************************
|
||||
* $Id$ FAU
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
/* In strict ANSI mode, HP-UX machines define __hpux but not hpux */
|
||||
#if defined(__hpux) && !defined(hpux)
|
||||
# define hpux
|
||||
#endif
|
||||
|
||||
#if defined(__bsdi__) || defined(__386BSD__) || defined(_CX_UX) || defined(hpux) || defined(_IBMR2) || defined(linux)
|
||||
# include <signal.h>
|
||||
#endif /* __bsdi__ || __386BSD__ || _CX_UX || hpux || _IBMR2 || linux */
|
||||
|
||||
#ifdef ISC
|
||||
# ifdef ENAMETOOLONG
|
||||
# undef ENAMETOOLONG
|
||||
# endif
|
||||
# ifdef ENOTEMPTY
|
||||
# undef ENOTEMPTY
|
||||
# endif
|
||||
# include <sys/bsdtypes.h>
|
||||
# include <net/errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef sun
|
||||
# define getpgrp __getpgrp
|
||||
# define exit __exit
|
||||
#endif
|
||||
#ifdef POSIX
|
||||
# include <unistd.h>
|
||||
# if defined(__STDC__)
|
||||
# include <stdlib.h>
|
||||
# endif /* __STDC__ */
|
||||
#endif /* POSIX */
|
||||
#ifdef sun
|
||||
# undef getpgrp
|
||||
# undef exit
|
||||
#endif /* sun */
|
||||
|
||||
#ifndef linux /* all done in <errno.h> */
|
||||
extern int errno;
|
||||
#endif /* linux */
|
||||
#ifndef HAVE_STRERROR
|
||||
/* No macros, please */
|
||||
#undef strerror
|
||||
#endif
|
||||
|
||||
#if !defined(SYSV) && !defined(linux)
|
||||
# ifdef NEWSOS
|
||||
# define strlen ___strlen___
|
||||
# include <strings.h>
|
||||
# undef strlen
|
||||
# else /* NEWSOS */
|
||||
# include <strings.h>
|
||||
# endif /* NEWSOS */
|
||||
#else /* SYSV */
|
||||
# if defined(SVR4) || defined(NEWSOS)
|
||||
# define strlen ___strlen___
|
||||
# include <string.h>
|
||||
# undef strlen
|
||||
# if !defined(NEWSOS) && !defined(__hpux)
|
||||
extern size_t strlen(const char *);
|
||||
# endif
|
||||
# else /* SVR4 */
|
||||
# include <string.h>
|
||||
# endif /* SVR4 */
|
||||
#endif /* SYSV */
|
||||
|
||||
#ifdef USEVARARGS
|
||||
# if defined(__STDC__)
|
||||
# include <stdarg.h>
|
||||
# define VA_LIST(var) va_list var;
|
||||
# define VA_DOTS ...
|
||||
# define VA_DECL
|
||||
# define VA_START(ap, fmt) va_start(ap, fmt)
|
||||
# define VA_ARGS(ap) ap
|
||||
# define VA_END(ap) va_end(ap)
|
||||
# else
|
||||
# include <varargs.h>
|
||||
# define VA_LIST(var) va_list var;
|
||||
# define VA_DOTS va_alist
|
||||
# define VA_DECL va_dcl
|
||||
# define VA_START(ap, fmt) va_start(ap)
|
||||
# define VA_ARGS(ap) ap
|
||||
# define VA_END(ap) va_end(ap)
|
||||
# endif
|
||||
#else
|
||||
# define VA_LIST(var)
|
||||
# define VA_DOTS p1, p2, p3, p4, p5, p6
|
||||
# define VA_DECL unsigned long VA_DOTS;
|
||||
# define VA_START(ap, fmt)
|
||||
# define VA_ARGS(ap) VA_DOTS
|
||||
# define VA_END(ap)
|
||||
# undef vsnprintf
|
||||
# define vsnprintf xsnprintf
|
||||
#endif
|
||||
|
||||
#if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX)
|
||||
# include <time.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef M_UNIX /* SCO */
|
||||
# include <sys/stream.h>
|
||||
# include <sys/ptem.h>
|
||||
# define ftruncate(fd, s) chsize(fd, s)
|
||||
#endif
|
||||
|
||||
#ifdef SYSV
|
||||
# define index strchr
|
||||
# define rindex strrchr
|
||||
# define bzero(poi,len) memset(poi,0,len)
|
||||
# define bcmp memcmp
|
||||
# define killpg(pgrp,sig) kill( -(pgrp), sig)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETCWD
|
||||
# define getcwd(b,l) getwd(b)
|
||||
#endif
|
||||
|
||||
#ifndef USEBCOPY
|
||||
# ifdef USEMEMMOVE
|
||||
# define bcopy(s,d,len) memmove(d,s,len)
|
||||
# else
|
||||
# ifdef USEMEMCPY
|
||||
# define bcopy(s,d,len) memcpy(d,s,len)
|
||||
# else
|
||||
# define NEED_OWN_BCOPY
|
||||
# define bcopy xbcopy
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef hpux
|
||||
# define setreuid(ruid, euid) setresuid(ruid, euid, -1)
|
||||
# define setregid(rgid, egid) setresgid(rgid, egid, -1)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SETEUID) || defined(HAVE_SETREUID)
|
||||
# define USE_SETEUID
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE__EXIT) && !defined(_exit)
|
||||
#define _exit(x) exit(x)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UTIMES
|
||||
# define utimes utime
|
||||
#endif
|
||||
|
||||
#ifdef BUILTIN_TELNET
|
||||
# include <netinet/in.h>
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_LOCALE) && (!defined(HAVE_SETLOCALE) || !defined(HAVE_STRFTIME))
|
||||
# undef USE_LOCALE
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
* terminal handling
|
||||
*/
|
||||
|
||||
#ifdef POSIX
|
||||
# include <termios.h>
|
||||
# ifdef hpux
|
||||
# include <bsdtty.h>
|
||||
# endif /* hpux */
|
||||
# ifdef NCCS
|
||||
# define MAXCC NCCS
|
||||
# else
|
||||
# define MAXCC 256
|
||||
# endif
|
||||
#else /* POSIX */
|
||||
# ifdef TERMIO
|
||||
# include <termio.h>
|
||||
# ifdef NCC
|
||||
# define MAXCC NCC
|
||||
# else
|
||||
# define MAXCC 256
|
||||
# endif
|
||||
# ifdef CYTERMIO
|
||||
# include <cytermio.h>
|
||||
# endif
|
||||
# else /* TERMIO */
|
||||
# include <sgtty.h>
|
||||
# endif /* TERMIO */
|
||||
#endif /* POSIX */
|
||||
|
||||
#ifndef VDISABLE
|
||||
# ifdef _POSIX_VDISABLE
|
||||
# define VDISABLE _POSIX_VDISABLE
|
||||
# else
|
||||
# define VDISABLE 0377
|
||||
# endif /* _POSIX_VDISABLE */
|
||||
#endif /* !VDISABLE */
|
||||
|
||||
|
||||
/* on sgi, regardless of the stream head's read mode (RNORM/RMSGN/RMSGD)
|
||||
* TIOCPKT mode causes data loss if our buffer is too small (IOSIZE)
|
||||
* to hold the whole packet at first read().
|
||||
* (Marc Boucher)
|
||||
*
|
||||
* matthew green:
|
||||
* TIOCPKT is broken on dgux 5.4.1 generic AViiON mc88100
|
||||
*
|
||||
* Joe Traister: On AIX4, programs like irc won't work if screen
|
||||
* uses TIOCPKT (select fails to return on pty read).
|
||||
*/
|
||||
#if defined(sgi) || defined(DGUX) || defined(_IBMR2)
|
||||
# undef TIOCPKT
|
||||
#endif
|
||||
|
||||
/* linux ncurses is broken, we have to use our own tputs */
|
||||
#if defined(linux) && defined(TERMINFO)
|
||||
# define tputs xtputs
|
||||
#endif
|
||||
|
||||
/* Alexandre Oliva: SVR4 style ptys don't work with osf */
|
||||
#ifdef __osf__
|
||||
# undef HAVE_SVR4_PTYS
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
* utmp handling
|
||||
*/
|
||||
|
||||
#ifdef GETUTENT
|
||||
typedef char *slot_t;
|
||||
#else
|
||||
typedef int slot_t;
|
||||
#endif
|
||||
|
||||
#if defined(UTMPOK) || defined(BUGGYGETLOGIN)
|
||||
# if defined(SVR4) && !defined(DGUX) && !defined(__hpux) && !defined(linux)
|
||||
# include <utmpx.h>
|
||||
# define UTMPFILE UTMPX_FILE
|
||||
# define utmp utmpx
|
||||
# define getutent getutxent
|
||||
# define getutid getutxid
|
||||
# define getutline getutxline
|
||||
# define pututline pututxline
|
||||
# define setutent setutxent
|
||||
# define endutent endutxent
|
||||
# define ut_time ut_xtime
|
||||
# else /* SVR4 */
|
||||
# include <utmp.h>
|
||||
# endif /* SVR4 */
|
||||
# ifdef apollo
|
||||
/*
|
||||
* We don't have GETUTENT, so we dig into utmp ourselves.
|
||||
* But we save the permanent filedescriptor and
|
||||
* open utmp just when we need to.
|
||||
* This code supports an unsorted utmp. jw.
|
||||
*/
|
||||
# define UTNOKEEP
|
||||
# endif /* apollo */
|
||||
|
||||
# ifndef UTMPFILE
|
||||
# ifdef UTMP_FILE
|
||||
# define UTMPFILE UTMP_FILE
|
||||
# else
|
||||
# ifdef _PATH_UTMP
|
||||
# define UTMPFILE _PATH_UTMP
|
||||
# else
|
||||
# define UTMPFILE "/etc/utmp"
|
||||
# endif /* _PATH_UTMP */
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* UTMPOK || BUGGYGETLOGIN */
|
||||
|
||||
#if !defined(UTMPOK) && defined(USRLIMIT)
|
||||
# undef USRLIMIT
|
||||
#endif
|
||||
|
||||
#ifdef LOGOUTOK
|
||||
# ifndef LOGINDEFAULT
|
||||
# define LOGINDEFAULT 0
|
||||
# endif
|
||||
#else
|
||||
# ifdef LOGINDEFAULT
|
||||
# undef LOGINDEFAULT
|
||||
# endif
|
||||
# define LOGINDEFAULT 1
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* file stuff
|
||||
*/
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif
|
||||
#ifndef X_OK
|
||||
#define X_OK 1
|
||||
#endif
|
||||
#ifndef W_OK
|
||||
#define W_OK 2
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif
|
||||
|
||||
#ifndef S_IFIFO
|
||||
#define S_IFIFO 0010000
|
||||
#endif
|
||||
#ifndef S_IREAD
|
||||
#define S_IREAD 0000400
|
||||
#endif
|
||||
#ifndef S_IWRITE
|
||||
#define S_IWRITE 0000200
|
||||
#endif
|
||||
#ifndef S_IEXEC
|
||||
#define S_IEXEC 0000100
|
||||
#endif
|
||||
|
||||
#if defined(S_IFIFO) && defined(S_IFMT) && !defined(S_ISFIFO)
|
||||
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||||
#endif
|
||||
#if defined(S_IFSOCK) && defined(S_IFMT) && !defined(S_ISSOCK)
|
||||
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
#endif
|
||||
#if defined(S_IFCHR) && defined(S_IFMT) && !defined(S_ISCHR)
|
||||
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
#endif
|
||||
#if defined(S_IFDIR) && defined(S_IFMT) && !defined(S_ISDIR)
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
#if defined(S_IFLNK) && defined(S_IFMT) && !defined(S_ISLNK)
|
||||
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SunOS 4.1.3: `man 2V open' has only one line that mentions O_NOBLOCK:
|
||||
*
|
||||
* O_NONBLOCK Same as O_NDELAY above.
|
||||
*
|
||||
* on the very same SunOS 4.1.3, I traced the open system call and found
|
||||
* that an open("/dev/ttyy08", O_RDWR|O_NONBLOCK|O_NOCTTY) was blocked,
|
||||
* whereas open("/dev/ttyy08", O_RDWR|O_NDELAY |O_NOCTTY) went through.
|
||||
*
|
||||
* For this simple reason I now favour O_NDELAY. jw. 4.5.95
|
||||
*/
|
||||
#if defined(sun) && !defined(SVR4)
|
||||
# undef O_NONBLOCK
|
||||
#endif
|
||||
|
||||
#if !defined(O_NONBLOCK) && defined(O_NDELAY)
|
||||
# define O_NONBLOCK O_NDELAY
|
||||
#endif
|
||||
|
||||
#if !defined(FNBLOCK) && defined(FNONBLOCK)
|
||||
# define FNBLOCK FNONBLOCK
|
||||
#endif
|
||||
#if !defined(FNBLOCK) && defined(FNDELAY)
|
||||
# define FNBLOCK FNDELAY
|
||||
#endif
|
||||
#if !defined(FNBLOCK) && defined(O_NONBLOCK)
|
||||
# define FNBLOCK O_NONBLOCK
|
||||
#endif
|
||||
|
||||
#ifndef POSIX
|
||||
#undef mkfifo
|
||||
#define mkfifo(n,m) mknod(n,S_IFIFO|(m),0)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_LSTAT) && !defined(lstat)
|
||||
# define lstat stat
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
* signal handling
|
||||
*/
|
||||
|
||||
#ifdef SIGVOID
|
||||
# define SIGRETURN
|
||||
# define sigret_t void
|
||||
#else
|
||||
# define SIGRETURN return 0;
|
||||
# define sigret_t int
|
||||
#endif
|
||||
|
||||
/* Geeeee, reverse it? */
|
||||
#if defined(SVR4) || (defined(SYSV) && defined(ISC)) || defined(_AIX) || defined(linux) || defined(ultrix) || defined(__386BSD__) || defined(__bsdi__) || defined(POSIX) || defined(NeXT)
|
||||
# define SIGHASARG
|
||||
#endif
|
||||
|
||||
#ifdef SIGHASARG
|
||||
# define SIGPROTOARG (int)
|
||||
# define SIGDEFARG (sigsig) int sigsig;
|
||||
# define SIGARG 0
|
||||
#else
|
||||
# define SIGPROTOARG (void)
|
||||
# define SIGDEFARG ()
|
||||
# define SIGARG
|
||||
#endif
|
||||
|
||||
#ifndef SIGCHLD
|
||||
#define SIGCHLD SIGCLD
|
||||
#endif
|
||||
|
||||
#if defined(POSIX) || defined(hpux)
|
||||
# define signal xsignal
|
||||
#else
|
||||
# ifdef USESIGSET
|
||||
# define signal sigset
|
||||
# endif /* USESIGSET */
|
||||
#endif
|
||||
|
||||
/* used in screen.c and attacher.c */
|
||||
#ifndef NSIG /* kbeal needs these w/o SYSV */
|
||||
# define NSIG 32
|
||||
#endif /* !NSIG */
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* Wait stuff
|
||||
*/
|
||||
|
||||
#if (!defined(sysV68) && !defined(M_XENIX)) || defined(NeXT) || defined(M_UNIX)
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#ifndef WTERMSIG
|
||||
# ifndef BSDWAIT /* if wait is NOT a union: */
|
||||
# define WTERMSIG(status) (status & 0177)
|
||||
# else
|
||||
# define WTERMSIG(status) status.w_T.w_Termsig
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef WSTOPSIG
|
||||
# ifndef BSDWAIT /* if wait is NOT a union: */
|
||||
# define WSTOPSIG(status) ((status >> 8) & 0377)
|
||||
# else
|
||||
# define WSTOPSIG(status) status.w_S.w_Stopsig
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* NET-2 uses WCOREDUMP */
|
||||
#if defined(WCOREDUMP) && !defined(WIFCORESIG)
|
||||
# define WIFCORESIG(status) WCOREDUMP(status)
|
||||
#endif
|
||||
|
||||
#ifndef WIFCORESIG
|
||||
# ifndef BSDWAIT /* if wait is NOT a union: */
|
||||
# define WIFCORESIG(status) (status & 0200)
|
||||
# else
|
||||
# define WIFCORESIG(status) status.w_T.w_Coredump
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef WEXITSTATUS
|
||||
# ifndef BSDWAIT /* if wait is NOT a union: */
|
||||
# define WEXITSTATUS(status) ((status >> 8) & 0377)
|
||||
# else
|
||||
# define WEXITSTATUS(status) status.w_T.w_Retcode
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* select stuff
|
||||
*/
|
||||
|
||||
#if defined(M_XENIX) || defined(M_UNIX) || defined(_SEQUENT_)
|
||||
#include <sys/select.h> /* for timeval + FD... */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SunOS 3.5 - Tom Schmidt - Micron Semiconductor, Inc - 27-Jul-93
|
||||
* tschmidt@vax.micron.com
|
||||
*/
|
||||
#ifndef FD_SET
|
||||
# ifndef SUNOS3
|
||||
typedef struct fd_set { int fds_bits[1]; } fd_set;
|
||||
# endif
|
||||
# define FD_ZERO(fd) ((fd)->fds_bits[0] = 0)
|
||||
# define FD_SET(b, fd) ((fd)->fds_bits[0] |= 1 << (b))
|
||||
# define FD_ISSET(b, fd) ((fd)->fds_bits[0] & 1 << (b))
|
||||
# define FD_SETSIZE 32
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
* user defineable stuff
|
||||
*/
|
||||
|
||||
#ifndef TERMCAP_BUFSIZE
|
||||
# define TERMCAP_BUFSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
# define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
/*
|
||||
* you may try to vary this value. Use low values if your (VMS) system
|
||||
* tends to choke when pasting. Use high values if you want to test
|
||||
* how many characters your pty's can buffer.
|
||||
*/
|
||||
#define IOSIZE 4096
|
||||
|
387
readline/examples/rlfe/pty.c
Normal file
387
readline/examples/rlfe/pty.c
Normal file
@ -0,0 +1,387 @@
|
||||
/* Copyright (c) 1993-2002
|
||||
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
|
||||
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
|
||||
* Copyright (c) 1987 Oliver Laumann
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "screen.h"
|
||||
|
||||
#ifndef sun
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
/* for solaris 2.1, Unixware (SVR4.2) and possibly others */
|
||||
#ifdef HAVE_SVR4_PTYS
|
||||
# include <sys/stropts.h>
|
||||
#endif
|
||||
|
||||
#if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL)
|
||||
# include <sys/ttold.h>
|
||||
#endif
|
||||
|
||||
#ifdef ISC
|
||||
# include <sys/tty.h>
|
||||
# include <sys/sioctl.h>
|
||||
# include <sys/pty.h>
|
||||
#endif
|
||||
|
||||
#ifdef sgi
|
||||
# include <sys/sysmacros.h>
|
||||
#endif /* sgi */
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
/*
|
||||
* if no PTYRANGE[01] is in the config file, we pick a default
|
||||
*/
|
||||
#ifndef PTYRANGE0
|
||||
# define PTYRANGE0 "qpr"
|
||||
#endif
|
||||
#ifndef PTYRANGE1
|
||||
# define PTYRANGE1 "0123456789abcdef"
|
||||
#endif
|
||||
|
||||
/* SVR4 pseudo ttys don't seem to work with SCO-5 */
|
||||
#ifdef M_UNIX
|
||||
# undef HAVE_SVR4_PTYS
|
||||
#endif
|
||||
|
||||
extern int eff_uid;
|
||||
|
||||
/* used for opening a new pty-pair: */
|
||||
static char PtyName[32], TtyName[32];
|
||||
|
||||
#if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS))
|
||||
# ifdef hpux
|
||||
static char PtyProto[] = "/dev/ptym/ptyXY";
|
||||
static char TtyProto[] = "/dev/pty/ttyXY";
|
||||
# else
|
||||
# ifdef M_UNIX
|
||||
static char PtyProto[] = "/dev/ptypXY";
|
||||
static char TtyProto[] = "/dev/ttypXY";
|
||||
# else
|
||||
static char PtyProto[] = "/dev/ptyXY";
|
||||
static char TtyProto[] = "/dev/ttyXY";
|
||||
# endif
|
||||
# endif /* hpux */
|
||||
#endif
|
||||
|
||||
static void initmaster __P((int));
|
||||
|
||||
#if defined(sun)
|
||||
/* sun's utmp_update program opens the salve side, thus corrupting
|
||||
*/
|
||||
int pty_preopen = 1;
|
||||
#else
|
||||
int pty_preopen = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Open all ptys with O_NOCTTY, just to be on the safe side
|
||||
* (RISCos mips breaks otherwise)
|
||||
*/
|
||||
#ifndef O_NOCTTY
|
||||
# define O_NOCTTY 0
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void
|
||||
initmaster(f)
|
||||
int f;
|
||||
{
|
||||
#ifdef POSIX
|
||||
tcflush(f, TCIOFLUSH);
|
||||
#else
|
||||
# ifdef TIOCFLUSH
|
||||
(void) ioctl(f, TIOCFLUSH, (char *) 0);
|
||||
# endif
|
||||
#endif
|
||||
#ifdef LOCKPTY
|
||||
(void) ioctl(f, TIOCEXCL, (char *) 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
InitPTY(f)
|
||||
int f;
|
||||
{
|
||||
if (f < 0)
|
||||
return;
|
||||
#if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX)
|
||||
if (ioctl(f, I_PUSH, "ptem"))
|
||||
Panic(errno, "InitPTY: cannot I_PUSH ptem");
|
||||
if (ioctl(f, I_PUSH, "ldterm"))
|
||||
Panic(errno, "InitPTY: cannot I_PUSH ldterm");
|
||||
# ifdef sun
|
||||
if (ioctl(f, I_PUSH, "ttcompat"))
|
||||
Panic(errno, "InitPTY: cannot I_PUSH ttcompat");
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if defined(OSX) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
register int f;
|
||||
if ((f = open_controlling_pty(TtyName)) < 0)
|
||||
return -1;
|
||||
initmaster(f);
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if (defined(sequent) || defined(_SEQUENT_)) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
char *m, *s;
|
||||
register int f;
|
||||
|
||||
if ((f = getpseudotty(&s, &m)) < 0)
|
||||
return -1;
|
||||
#ifdef _SEQUENT_
|
||||
fvhangup(s);
|
||||
#endif
|
||||
strncpy(PtyName, m, sizeof(PtyName));
|
||||
strncpy(TtyName, s, sizeof(TtyName));
|
||||
initmaster(f);
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if defined(__sgi) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
int f;
|
||||
char *name, *_getpty();
|
||||
sigret_t (*sigcld)__P(SIGPROTOARG);
|
||||
|
||||
/*
|
||||
* SIGCHLD set to SIG_DFL for _getpty() because it may fork() and
|
||||
* exec() /usr/adm/mkpts
|
||||
*/
|
||||
sigcld = signal(SIGCHLD, SIG_DFL);
|
||||
name = _getpty(&f, O_RDWR | O_NONBLOCK, 0600, 0);
|
||||
signal(SIGCHLD, sigcld);
|
||||
|
||||
if (name == 0)
|
||||
return -1;
|
||||
initmaster(f);
|
||||
*ttyn = name;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
register int f;
|
||||
struct stat buf;
|
||||
|
||||
strcpy(PtyName, "/dev/ptc");
|
||||
if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
|
||||
return -1;
|
||||
if (fstat(f, &buf) < 0)
|
||||
{
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev));
|
||||
initmaster(f);
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
register int f;
|
||||
char *m, *ptsname();
|
||||
int unlockpt __P((int)), grantpt __P((int));
|
||||
#if defined(HAVE_GETPT) && defined(linux)
|
||||
int getpt __P((void));
|
||||
#endif
|
||||
sigret_t (*sigcld)__P(SIGPROTOARG);
|
||||
|
||||
strcpy(PtyName, "/dev/ptmx");
|
||||
#if defined(HAVE_GETPT) && defined(linux)
|
||||
if ((f = getpt()) == -1)
|
||||
#else
|
||||
if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1)
|
||||
#endif
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* SIGCHLD set to SIG_DFL for grantpt() because it fork()s and
|
||||
* exec()s pt_chmod
|
||||
*/
|
||||
sigcld = signal(SIGCHLD, SIG_DFL);
|
||||
if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f))
|
||||
{
|
||||
signal(SIGCHLD, sigcld);
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
signal(SIGCHLD, sigcld);
|
||||
strncpy(TtyName, m, sizeof(TtyName));
|
||||
initmaster(f);
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
register int f;
|
||||
|
||||
/* a dumb looking loop replaced by mycrofts code: */
|
||||
strcpy (PtyName, "/dev/ptc");
|
||||
if ((f = open (PtyName, O_RDWR | O_NOCTTY)) < 0)
|
||||
return -1;
|
||||
strncpy(TtyName, ttyname(f), sizeof(TtyName));
|
||||
if (eff_uid && access(TtyName, R_OK | W_OK))
|
||||
{
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
initmaster(f);
|
||||
# ifdef _IBMR2
|
||||
pty_preopen = 1;
|
||||
# endif
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if defined(HAVE_OPENPTY) && !defined(PTY_DONE)
|
||||
#define PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
int f, s;
|
||||
if (openpty(&f, &s, TtyName, NULL, NULL) != 0)
|
||||
return -1;
|
||||
close(s);
|
||||
initmaster(f);
|
||||
pty_preopen = 1;
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#ifndef PTY_DONE
|
||||
int
|
||||
OpenPTY(ttyn)
|
||||
char **ttyn;
|
||||
{
|
||||
register char *p, *q, *l, *d;
|
||||
register int f;
|
||||
|
||||
debug("OpenPTY: Using BSD style ptys.\n");
|
||||
strcpy(PtyName, PtyProto);
|
||||
strcpy(TtyName, TtyProto);
|
||||
for (p = PtyName; *p != 'X'; p++)
|
||||
;
|
||||
for (q = TtyName; *q != 'X'; q++)
|
||||
;
|
||||
for (l = PTYRANGE0; (*p = *l) != '\0'; l++)
|
||||
{
|
||||
for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++)
|
||||
{
|
||||
debug1("OpenPTY tries '%s'\n", PtyName);
|
||||
if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1)
|
||||
continue;
|
||||
q[0] = *l;
|
||||
q[1] = *d;
|
||||
if (eff_uid && access(TtyName, R_OK | W_OK))
|
||||
{
|
||||
close(f);
|
||||
continue;
|
||||
}
|
||||
#if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3)
|
||||
/* Hack to ensure that the slave side of the pty is
|
||||
* unused. May not work in anything other than SunOS4.1
|
||||
*/
|
||||
{
|
||||
int pgrp;
|
||||
|
||||
/* tcgetpgrp does not work (uses TIOCGETPGRP)! */
|
||||
if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO)
|
||||
{
|
||||
close(f);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
initmaster(f);
|
||||
*ttyn = TtyName;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
780
readline/examples/rlfe/rlfe.c
Normal file
780
readline/examples/rlfe/rlfe.c
Normal file
@ -0,0 +1,780 @@
|
||||
/* A front-end using readline to "cook" input lines.
|
||||
*
|
||||
* Copyright (C) 2004, 1999 Per Bothner
|
||||
*
|
||||
* This front-end program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* Some code from Johnson & Troan: "Linux Application Development"
|
||||
* (Addison-Wesley, 1998) was used directly or for inspiration.
|
||||
*
|
||||
* 2003-11-07 Wolfgang Taeuber <wolfgang_taeuber@agilent.com>
|
||||
* Specify a history file and the size of the history file with command
|
||||
* line options; use EDITOR/VISUAL to set vi/emacs preference.
|
||||
*/
|
||||
|
||||
/* PROBLEMS/TODO:
|
||||
*
|
||||
* Only tested under GNU/Linux and Mac OS 10.x; needs to be ported.
|
||||
*
|
||||
* Switching between line-editing-mode vs raw-char-mode depending on
|
||||
* what tcgetattr returns is inherently not robust, plus it doesn't
|
||||
* work when ssh/telnetting in. A better solution is possible if the
|
||||
* tty system can send in-line escape sequences indicating the current
|
||||
* mode, echo'd input, etc. That would also allow a user preference
|
||||
* to set different colors for prompt, input, stdout, and stderr.
|
||||
*
|
||||
* When running mc -c under the Linux console, mc does not recognize
|
||||
* mouse clicks, which mc does when not running under rlfe.
|
||||
*
|
||||
* Pasting selected text containing tabs is like hitting the tab character,
|
||||
* which invokes readline completion. We don't want this. I don't know
|
||||
* if this is fixable without integrating rlfe into a terminal emulator.
|
||||
*
|
||||
* Echo suppression is a kludge, but can only be avoided with better kernel
|
||||
* support: We need a tty mode to disable "real" echoing, while still
|
||||
* letting the inferior think its tty driver to doing echoing.
|
||||
* Stevens's book claims SCR$ and BSD4.3+ have TIOCREMOTE.
|
||||
*
|
||||
* The latest readline may have some hooks we can use to avoid having
|
||||
* to back up the prompt. (See HAVE_ALREADY_PROMPTED.)
|
||||
*
|
||||
* Desirable readline feature: When in cooked no-echo mode (e.g. password),
|
||||
* echo characters are they are types with '*', but remove them when done.
|
||||
*
|
||||
* Asynchronous output while we're editing an input line should be
|
||||
* inserted in the output view *before* the input line, so that the
|
||||
* lines being edited (with the prompt) float at the end of the input.
|
||||
*
|
||||
* A "page mode" option to emulate more/less behavior: At each page of
|
||||
* output, pause for a user command. This required parsing the output
|
||||
* to keep track of line lengths. It also requires remembering the
|
||||
* output, if we want an option to scroll back, which suggests that
|
||||
* this should be integrated with a terminal emulator like xterm.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <signal.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef READLINE_LIBRARY
|
||||
# include "readline.h"
|
||||
# include "history.h"
|
||||
#else
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
#endif
|
||||
|
||||
#ifndef COMMAND
|
||||
#define COMMAND "/bin/bash"
|
||||
#endif
|
||||
#ifndef COMMAND_ARGS
|
||||
#define COMMAND_ARGS COMMAND
|
||||
#endif
|
||||
|
||||
#ifndef ALT_COMMAND
|
||||
#define ALT_COMMAND "/bin/sh"
|
||||
#endif
|
||||
#ifndef ALT_COMMAND_ARGS
|
||||
#define ALT_COMMAND_ARGS ALT_COMMAND
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMMOVE
|
||||
# if __GNUC__ > 1
|
||||
# define memmove(d, s, n) __builtin_memcpy(d, s, n)
|
||||
# else
|
||||
# define memmove(d, s, n) memcpy(d, s, n)
|
||||
# endif
|
||||
#else
|
||||
# define memmove(d, s, n) memcpy(d, s, n)
|
||||
#endif
|
||||
|
||||
#define APPLICATION_NAME "rlfe"
|
||||
|
||||
static int in_from_inferior_fd;
|
||||
static int out_to_inferior_fd;
|
||||
static void set_edit_mode ();
|
||||
static void usage_exit ();
|
||||
static char *hist_file = 0;
|
||||
static int hist_size = 0;
|
||||
|
||||
/* Unfortunately, we cannot safely display echo from the inferior process.
|
||||
The reason is that the echo bit in the pty is "owned" by the inferior,
|
||||
and if we try to turn it off, we could confuse the inferior.
|
||||
Thus, when echoing, we get echo twice: First readline echoes while
|
||||
we're actually editing. Then we send the line to the inferior, and the
|
||||
terminal driver send back an extra echo.
|
||||
The work-around is to remember the input lines, and when we see that
|
||||
line come back, we supress the output.
|
||||
A better solution (supposedly available on SVR4) would be a smarter
|
||||
terminal driver, with more flags ... */
|
||||
#define ECHO_SUPPRESS_MAX 1024
|
||||
char echo_suppress_buffer[ECHO_SUPPRESS_MAX];
|
||||
int echo_suppress_start = 0;
|
||||
int echo_suppress_limit = 0;
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#ifdef DEBUG
|
||||
FILE *logfile = NULL;
|
||||
#define DPRINT0(FMT) (fprintf(logfile, FMT), fflush(logfile))
|
||||
#define DPRINT1(FMT, V1) (fprintf(logfile, FMT, V1), fflush(logfile))
|
||||
#define DPRINT2(FMT, V1, V2) (fprintf(logfile, FMT, V1, V2), fflush(logfile))
|
||||
#else
|
||||
#define DPRINT0(FMT) ((void) 0) /* Do nothing */
|
||||
#define DPRINT1(FMT, V1) ((void) 0) /* Do nothing */
|
||||
#define DPRINT2(FMT, V1, V2) ((void) 0) /* Do nothing */
|
||||
#endif
|
||||
|
||||
struct termios orig_term;
|
||||
|
||||
/* Pid of child process. */
|
||||
static pid_t child = -1;
|
||||
|
||||
static void
|
||||
sig_child (int signo)
|
||||
{
|
||||
int status;
|
||||
wait (&status);
|
||||
if (hist_file != 0)
|
||||
{
|
||||
write_history (hist_file);
|
||||
if (hist_size)
|
||||
history_truncate_file (hist_file, hist_size);
|
||||
}
|
||||
DPRINT0 ("(Child process died.)\n");
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
volatile int propagate_sigwinch = 0;
|
||||
|
||||
/* sigwinch_handler
|
||||
* propagate window size changes from input file descriptor to
|
||||
* master side of pty.
|
||||
*/
|
||||
void sigwinch_handler(int signal) {
|
||||
propagate_sigwinch = 1;
|
||||
}
|
||||
|
||||
|
||||
/* get_slave_pty() returns an integer file descriptor.
|
||||
* If it returns < 0, an error has occurred.
|
||||
* Otherwise, it has returned the slave file descriptor.
|
||||
*/
|
||||
|
||||
int get_slave_pty(char *name) {
|
||||
struct group *gptr;
|
||||
gid_t gid;
|
||||
int slave = -1;
|
||||
|
||||
/* chown/chmod the corresponding pty, if possible.
|
||||
* This will only work if the process has root permissions.
|
||||
* Alternatively, write and exec a small setuid program that
|
||||
* does just this.
|
||||
*/
|
||||
if ((gptr = getgrnam("tty")) != 0) {
|
||||
gid = gptr->gr_gid;
|
||||
} else {
|
||||
/* if the tty group does not exist, don't change the
|
||||
* group on the slave pty, only the owner
|
||||
*/
|
||||
gid = -1;
|
||||
}
|
||||
|
||||
/* Note that we do not check for errors here. If this is code
|
||||
* where these actions are critical, check for errors!
|
||||
*/
|
||||
chown(name, getuid(), gid);
|
||||
/* This code only makes the slave read/writeable for the user.
|
||||
* If this is for an interactive shell that will want to
|
||||
* receive "write" and "wall" messages, OR S_IWGRP into the
|
||||
* second argument below.
|
||||
*/
|
||||
chmod(name, S_IRUSR|S_IWUSR);
|
||||
|
||||
/* open the corresponding slave pty */
|
||||
slave = open(name, O_RDWR);
|
||||
return (slave);
|
||||
}
|
||||
|
||||
/* Certain special characters, such as ctrl/C, we want to pass directly
|
||||
to the inferior, rather than letting readline handle them. */
|
||||
|
||||
static char special_chars[20];
|
||||
static int special_chars_count;
|
||||
|
||||
static void
|
||||
add_special_char(int ch)
|
||||
{
|
||||
if (ch != 0)
|
||||
special_chars[special_chars_count++] = ch;
|
||||
}
|
||||
|
||||
static int eof_char;
|
||||
|
||||
static int
|
||||
is_special_char(int ch)
|
||||
{
|
||||
int i;
|
||||
#if 0
|
||||
if (ch == eof_char && rl_point == rl_end)
|
||||
return 1;
|
||||
#endif
|
||||
for (i = special_chars_count; --i >= 0; )
|
||||
if (special_chars[i] == ch)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char buf[1024];
|
||||
/* buf[0 .. buf_count-1] is the what has been emitted on the current line.
|
||||
It is used as the readline prompt. */
|
||||
static int buf_count = 0;
|
||||
|
||||
int do_emphasize_input = 1;
|
||||
int current_emphasize_input;
|
||||
|
||||
char *start_input_mode = "\033[1m";
|
||||
char *end_input_mode = "\033[0m";
|
||||
|
||||
int num_keys = 0;
|
||||
|
||||
static void maybe_emphasize_input (int on)
|
||||
{
|
||||
if (on == current_emphasize_input
|
||||
|| (on && ! do_emphasize_input))
|
||||
return;
|
||||
fprintf (rl_outstream, on ? start_input_mode : end_input_mode);
|
||||
fflush (rl_outstream);
|
||||
current_emphasize_input = on;
|
||||
}
|
||||
|
||||
static void
|
||||
null_prep_terminal (int meta)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
null_deprep_terminal ()
|
||||
{
|
||||
maybe_emphasize_input (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pre_input_change_mode (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char pending_special_char;
|
||||
|
||||
static void
|
||||
line_handler (char *line)
|
||||
{
|
||||
if (line == NULL)
|
||||
{
|
||||
char buf[1];
|
||||
DPRINT0("saw eof!\n");
|
||||
buf[0] = '\004'; /* ctrl/d */
|
||||
write (out_to_inferior_fd, buf, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
static char enter[] = "\r";
|
||||
/* Send line to inferior: */
|
||||
int length = strlen (line);
|
||||
if (length > ECHO_SUPPRESS_MAX-2)
|
||||
{
|
||||
echo_suppress_start = 0;
|
||||
echo_suppress_limit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (echo_suppress_limit + length > ECHO_SUPPRESS_MAX - 2)
|
||||
{
|
||||
if (echo_suppress_limit - echo_suppress_start + length
|
||||
<= ECHO_SUPPRESS_MAX - 2)
|
||||
{
|
||||
memmove (echo_suppress_buffer,
|
||||
echo_suppress_buffer + echo_suppress_start,
|
||||
echo_suppress_limit - echo_suppress_start);
|
||||
echo_suppress_limit -= echo_suppress_start;
|
||||
echo_suppress_start = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo_suppress_limit = 0;
|
||||
}
|
||||
echo_suppress_start = 0;
|
||||
}
|
||||
memcpy (echo_suppress_buffer + echo_suppress_limit,
|
||||
line, length);
|
||||
echo_suppress_limit += length;
|
||||
echo_suppress_buffer[echo_suppress_limit++] = '\r';
|
||||
echo_suppress_buffer[echo_suppress_limit++] = '\n';
|
||||
}
|
||||
write (out_to_inferior_fd, line, length);
|
||||
if (pending_special_char == 0)
|
||||
{
|
||||
write (out_to_inferior_fd, enter, sizeof(enter)-1);
|
||||
if (*line)
|
||||
add_history (line);
|
||||
}
|
||||
free (line);
|
||||
}
|
||||
rl_callback_handler_remove ();
|
||||
buf_count = 0;
|
||||
num_keys = 0;
|
||||
if (pending_special_char != 0)
|
||||
{
|
||||
write (out_to_inferior_fd, &pending_special_char, 1);
|
||||
pending_special_char = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Value of rl_getc_function.
|
||||
Use this because readline should read from stdin, not rl_instream,
|
||||
points to the pty (so readline has monitor its terminal modes). */
|
||||
|
||||
int
|
||||
my_rl_getc (FILE *dummy)
|
||||
{
|
||||
int ch = rl_getc (stdin);
|
||||
if (is_special_char (ch))
|
||||
{
|
||||
pending_special_char = ch;
|
||||
return '\r';
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
char *path;
|
||||
int i;
|
||||
int master;
|
||||
char *name;
|
||||
int in_from_tty_fd;
|
||||
struct sigaction act;
|
||||
struct winsize ws;
|
||||
struct termios t;
|
||||
int maxfd;
|
||||
fd_set in_set;
|
||||
static char empty_string[1] = "";
|
||||
char *prompt = empty_string;
|
||||
int ioctl_err = 0;
|
||||
int arg_base = 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
logfile = fopen("/tmp/rlfe.log", "w");
|
||||
#endif
|
||||
|
||||
while (arg_base<argc)
|
||||
{
|
||||
if (argv[arg_base][0] != '-')
|
||||
break;
|
||||
if (arg_base+1 >= argc )
|
||||
usage_exit();
|
||||
switch(argv[arg_base][1])
|
||||
{
|
||||
case 'h':
|
||||
arg_base++;
|
||||
hist_file = argv[arg_base];
|
||||
break;
|
||||
case 's':
|
||||
arg_base++;
|
||||
hist_size = atoi(argv[arg_base]);
|
||||
if (hist_size<0)
|
||||
usage_exit();
|
||||
break;
|
||||
default:
|
||||
usage_exit();
|
||||
}
|
||||
arg_base++;
|
||||
}
|
||||
if (hist_file)
|
||||
read_history (hist_file);
|
||||
|
||||
set_edit_mode ();
|
||||
|
||||
rl_readline_name = APPLICATION_NAME;
|
||||
|
||||
if ((master = OpenPTY (&name)) < 0)
|
||||
{
|
||||
perror("ptypair: could not open master pty");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DPRINT1("pty name: '%s'\n", name);
|
||||
|
||||
/* set up SIGWINCH handler */
|
||||
act.sa_handler = sigwinch_handler;
|
||||
sigemptyset(&(act.sa_mask));
|
||||
act.sa_flags = 0;
|
||||
if (sigaction(SIGWINCH, &act, NULL) < 0)
|
||||
{
|
||||
perror("ptypair: could not handle SIGWINCH ");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
|
||||
{
|
||||
perror("ptypair: could not get window size");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((child = fork()) < 0)
|
||||
{
|
||||
perror("cannot fork");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (child == 0)
|
||||
{
|
||||
int slave; /* file descriptor for slave pty */
|
||||
|
||||
/* We are in the child process */
|
||||
close(master);
|
||||
|
||||
#ifdef TIOCSCTTY
|
||||
if ((slave = get_slave_pty(name)) < 0)
|
||||
{
|
||||
perror("ptypair: could not open slave pty");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We need to make this process a session group leader, because
|
||||
* it is on a new PTY, and things like job control simply will
|
||||
* not work correctly unless there is a session group leader
|
||||
* and process group leader (which a session group leader
|
||||
* automatically is). This also disassociates us from our old
|
||||
* controlling tty.
|
||||
*/
|
||||
if (setsid() < 0)
|
||||
{
|
||||
perror("could not set session leader");
|
||||
}
|
||||
|
||||
/* Tie us to our new controlling tty. */
|
||||
#ifdef TIOCSCTTY
|
||||
if (ioctl(slave, TIOCSCTTY, NULL))
|
||||
{
|
||||
perror("could not set new controlling tty");
|
||||
}
|
||||
#else
|
||||
if ((slave = get_slave_pty(name)) < 0)
|
||||
{
|
||||
perror("ptypair: could not open slave pty");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* make slave pty be standard in, out, and error */
|
||||
dup2(slave, STDIN_FILENO);
|
||||
dup2(slave, STDOUT_FILENO);
|
||||
dup2(slave, STDERR_FILENO);
|
||||
|
||||
/* at this point the slave pty should be standard input */
|
||||
if (slave > 2)
|
||||
{
|
||||
close(slave);
|
||||
}
|
||||
|
||||
/* Try to restore window size; failure isn't critical */
|
||||
if (ioctl(STDOUT_FILENO, TIOCSWINSZ, &ws) < 0)
|
||||
{
|
||||
perror("could not restore window size");
|
||||
}
|
||||
|
||||
/* now start the shell */
|
||||
{
|
||||
static char* command_args[] = { COMMAND_ARGS, NULL };
|
||||
static char* alt_command_args[] = { ALT_COMMAND_ARGS, NULL };
|
||||
if (argc <= 1)
|
||||
{
|
||||
execvp (COMMAND, command_args);
|
||||
execvp (ALT_COMMAND, alt_command_args);
|
||||
}
|
||||
else
|
||||
execvp (argv[arg_base], &argv[arg_base]);
|
||||
}
|
||||
|
||||
/* should never be reached */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* parent */
|
||||
signal (SIGCHLD, sig_child);
|
||||
|
||||
/* Note that we only set termios settings for standard input;
|
||||
* the master side of a pty is NOT a tty.
|
||||
*/
|
||||
tcgetattr(STDIN_FILENO, &orig_term);
|
||||
|
||||
t = orig_term;
|
||||
eof_char = t.c_cc[VEOF];
|
||||
/* add_special_char(t.c_cc[VEOF]);*/
|
||||
add_special_char(t.c_cc[VINTR]);
|
||||
add_special_char(t.c_cc[VQUIT]);
|
||||
add_special_char(t.c_cc[VSUSP]);
|
||||
#if defined (VDISCARD)
|
||||
add_special_char(t.c_cc[VDISCARD]);
|
||||
#endif
|
||||
|
||||
t.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOCTL | ECHOE | \
|
||||
ECHOK | ECHOKE | ECHONL | ECHOPRT );
|
||||
t.c_iflag &= ~ICRNL;
|
||||
t.c_iflag |= IGNBRK;
|
||||
t.c_cc[VMIN] = 1;
|
||||
t.c_cc[VTIME] = 0;
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &t);
|
||||
in_from_inferior_fd = master;
|
||||
out_to_inferior_fd = master;
|
||||
rl_instream = fdopen (master, "r");
|
||||
rl_getc_function = my_rl_getc;
|
||||
|
||||
rl_prep_term_function = null_prep_terminal;
|
||||
rl_deprep_term_function = null_deprep_terminal;
|
||||
rl_pre_input_hook = pre_input_change_mode;
|
||||
rl_callback_handler_install (prompt, line_handler);
|
||||
|
||||
in_from_tty_fd = STDIN_FILENO;
|
||||
FD_ZERO (&in_set);
|
||||
maxfd = in_from_inferior_fd > in_from_tty_fd ? in_from_inferior_fd
|
||||
: in_from_tty_fd;
|
||||
for (;;)
|
||||
{
|
||||
int num;
|
||||
FD_SET (in_from_inferior_fd, &in_set);
|
||||
FD_SET (in_from_tty_fd, &in_set);
|
||||
|
||||
num = select(maxfd+1, &in_set, NULL, NULL, NULL);
|
||||
|
||||
if (propagate_sigwinch)
|
||||
{
|
||||
struct winsize ws;
|
||||
if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
|
||||
{
|
||||
ioctl (master, TIOCSWINSZ, &ws);
|
||||
}
|
||||
propagate_sigwinch = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num <= 0)
|
||||
{
|
||||
perror ("select");
|
||||
exit (-1);
|
||||
}
|
||||
if (FD_ISSET (in_from_tty_fd, &in_set))
|
||||
{
|
||||
extern int readline_echoing_p;
|
||||
struct termios term_master;
|
||||
int do_canon = 1;
|
||||
int do_icrnl = 1;
|
||||
int ioctl_ret;
|
||||
|
||||
DPRINT1("[tty avail num_keys:%d]\n", num_keys);
|
||||
|
||||
/* If we can't get tty modes for the master side of the pty, we
|
||||
can't handle non-canonical-mode programs. Always assume the
|
||||
master is in canonical echo mode if we can't tell. */
|
||||
ioctl_ret = tcgetattr(master, &term_master);
|
||||
|
||||
if (ioctl_ret >= 0)
|
||||
{
|
||||
do_canon = (term_master.c_lflag & ICANON) != 0;
|
||||
do_icrnl = (term_master.c_lflag & ICRNL) != 0;
|
||||
readline_echoing_p = (term_master.c_lflag & ECHO) != 0;
|
||||
DPRINT1 ("echo,canon,crnl:%03d\n",
|
||||
100 * readline_echoing_p
|
||||
+ 10 * do_canon
|
||||
+ 1 * do_icrnl);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ioctl_err == 0)
|
||||
DPRINT1("tcgetattr on master fd failed: errno = %d\n", errno);
|
||||
ioctl_err = 1;
|
||||
}
|
||||
|
||||
if (do_canon == 0 && num_keys == 0)
|
||||
{
|
||||
char ch[10];
|
||||
int count = read (STDIN_FILENO, ch, sizeof(ch));
|
||||
DPRINT1("[read %d chars from stdin: ", count);
|
||||
DPRINT2(" \"%.*s\"]\n", count, ch);
|
||||
if (do_icrnl)
|
||||
{
|
||||
int i = count;
|
||||
while (--i >= 0)
|
||||
{
|
||||
if (ch[i] == '\r')
|
||||
ch[i] = '\n';
|
||||
}
|
||||
}
|
||||
maybe_emphasize_input (1);
|
||||
write (out_to_inferior_fd, ch, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_keys == 0)
|
||||
{
|
||||
int i;
|
||||
/* Re-install callback handler for new prompt. */
|
||||
if (prompt != empty_string)
|
||||
free (prompt);
|
||||
if (prompt == NULL)
|
||||
{
|
||||
DPRINT0("New empty prompt\n");
|
||||
prompt = empty_string;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (do_emphasize_input && buf_count > 0)
|
||||
{
|
||||
prompt = malloc (buf_count + strlen (end_input_mode)
|
||||
+ strlen (start_input_mode) + 5);
|
||||
sprintf (prompt, "\001%s\002%.*s\001%s\002",
|
||||
end_input_mode,
|
||||
buf_count, buf,
|
||||
start_input_mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
prompt = malloc (buf_count + 1);
|
||||
memcpy (prompt, buf, buf_count);
|
||||
prompt[buf_count] = '\0';
|
||||
}
|
||||
DPRINT1("New prompt '%s'\n", prompt);
|
||||
#if 0 /* ifdef HAVE_RL_ALREADY_PROMPTED */
|
||||
/* Doesn't quite work when do_emphasize_input is 1. */
|
||||
rl_already_prompted = buf_count > 0;
|
||||
#else
|
||||
if (buf_count > 0)
|
||||
write (1, "\r", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
rl_callback_handler_install (prompt, line_handler);
|
||||
}
|
||||
num_keys++;
|
||||
maybe_emphasize_input (1);
|
||||
rl_callback_read_char ();
|
||||
}
|
||||
}
|
||||
else /* output from inferior. */
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
int old_count;
|
||||
if (buf_count > (sizeof(buf) >> 2))
|
||||
buf_count = 0;
|
||||
count = read (in_from_inferior_fd, buf+buf_count,
|
||||
sizeof(buf) - buf_count);
|
||||
DPRINT2("read %d from inferior, buf_count=%d", count, buf_count);
|
||||
DPRINT2(": \"%.*s\"", count, buf+buf_count);
|
||||
maybe_emphasize_input (0);
|
||||
if (count <= 0)
|
||||
{
|
||||
DPRINT0 ("(Connection closed by foreign host.)\n");
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
|
||||
exit (0);
|
||||
}
|
||||
old_count = buf_count;
|
||||
|
||||
/* Look for any pending echo that we need to suppress. */
|
||||
while (echo_suppress_start < echo_suppress_limit
|
||||
&& count > 0
|
||||
&& buf[buf_count] == echo_suppress_buffer[echo_suppress_start])
|
||||
{
|
||||
count--;
|
||||
buf_count++;
|
||||
echo_suppress_start++;
|
||||
}
|
||||
DPRINT1("suppressed %d characters of echo.\n", buf_count-old_count);
|
||||
|
||||
/* Write to the terminal anything that was not suppressed. */
|
||||
if (count > 0)
|
||||
write (1, buf + buf_count, count);
|
||||
|
||||
/* Finally, look for a prompt candidate.
|
||||
* When we get around to going input (from the keyboard),
|
||||
* we will consider the prompt to be anything since the last
|
||||
* line terminator. So we need to save that text in the
|
||||
* initial part of buf. However, anything before the
|
||||
* most recent end-of-line is not interesting. */
|
||||
buf_count += count;
|
||||
#if 1
|
||||
for (i = buf_count; --i >= old_count; )
|
||||
#else
|
||||
for (i = buf_count - 1; i-- >= buf_count - count; )
|
||||
#endif
|
||||
{
|
||||
if (buf[i] == '\n' || buf[i] == '\r')
|
||||
{
|
||||
i++;
|
||||
memmove (buf, buf+i, buf_count - i);
|
||||
buf_count -= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DPRINT2("-> i: %d, buf_count: %d\n", i, buf_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_edit_mode ()
|
||||
{
|
||||
int vi = 0;
|
||||
char *shellopts;
|
||||
|
||||
shellopts = getenv ("SHELLOPTS");
|
||||
while (shellopts != 0)
|
||||
{
|
||||
if (strncmp ("vi", shellopts, 2) == 0)
|
||||
{
|
||||
vi = 1;
|
||||
break;
|
||||
}
|
||||
shellopts = index (shellopts + 1, ':');
|
||||
}
|
||||
|
||||
if (!vi)
|
||||
{
|
||||
if (getenv ("EDITOR") != 0)
|
||||
vi |= strcmp (getenv ("EDITOR"), "vi") == 0;
|
||||
}
|
||||
|
||||
if (vi)
|
||||
rl_variable_bind ("editing-mode", "vi");
|
||||
else
|
||||
rl_variable_bind ("editing-mode", "emacs");
|
||||
}
|
||||
|
||||
|
||||
static void usage_exit ()
|
||||
{
|
||||
fprintf (stderr, "Usage: rlfe [-h histfile] [-s size] cmd [arg1] [arg2] ...\n\n");
|
||||
exit (1);
|
||||
}
|
2
readline/examples/rlfe/screen.h
Normal file
2
readline/examples/rlfe/screen.h
Normal file
@ -0,0 +1,2 @@
|
||||
/* Dummy header to avoid modifying pty.c */
|
||||
#include "os.h"
|
Reference in New Issue
Block a user