import of readlilne 5.1

This commit is contained in:
Elena Zannoni
2006-04-20 20:05:52 +00:00
parent 84041b4c47
commit b585a9fad5
112 changed files with 57294 additions and 18169 deletions

View 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.

View 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

View 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.

View 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

File diff suppressed because it is too large Load Diff

View 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)

View 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
View 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

View 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

View 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);
}

View File

@ -0,0 +1,2 @@
/* Dummy header to avoid modifying pty.c */
#include "os.h"